[
  {
    "path": ".github/ISSUE_TEMPLATE/config.yml",
    "content": "blank_issues_enabled: false\ncontact_links:\n  - name: General Questions and Inquiries\n    url: https://www.mongodb.com/community/forums/tags/c/realm-sdks/58/java\n    about: Please ask general design/architecture questions in the community forums.\n  - name: MongoDB Atlas Device Sync Production Issues\n    url: https://support.mongodb.com/\n    about: Please report urgent production issues to the support portal directly.\n"
  },
  {
    "path": ".github/advanced-issue-labeler.yml",
    "content": "# NOTE: This is a common file that is overwritten by realm/ci-actions sync service\n# and should only be modified in that repository.\n\n# syntax - https://github.com/redhat-plumbers-in-action/advanced-issue-labeler#policy\n# Below keys map from the option used in issue form dropdowns to issue labels\n# Limitation:\n# Currently it's not possible to use strings containing ,␣ in the dropdown menus in the issue forms.\n\n---\n\npolicy:\n  - template: [bug.yml, feature.yml]\n    section:\n      - id: [frequency]\n        label:\n          - name: 'Frequency:Once'\n            keys: ['Once']\n          - name: 'Frequency:Sometimes'\n            keys: ['Sometimes']\n          - name: 'Frequency:Always'\n            keys: ['Always']\n\n      - id: [repro]\n        label:\n          - name: 'Repro:Always'\n            keys: ['Always']\n          - name: 'Repro:Sometimes'\n            keys: ['Sometimes']\n          - name: 'Repro:No'\n            keys: ['No']\n\n      - id: [sync, flavour, services]\n        block-list: []\n        label:\n          - name: 'SDK-Use:Local'\n            keys: ['Local Database only']\n          - name: 'SDK-Use:Sync'\n            keys: ['Atlas Device Sync']\n          - name: 'SDK-Use:Services'\n            keys: ['Atlas App Services: Function or GraphQL or DataAPI etc']\n          - name: ['SDK-Use:All']\n            keys: ['Both Atlas Device Sync and Atlas App Services']\n\n      - id: [encryption]\n        block-list: []\n        label:\n          - name: 'Encryption:On'\n            keys: ['Yes']\n          - name: 'Encryption:Off'\n            keys: ['No']\n\n      - id: [app-type]\n        block-list: []\n        label:\n          - name: 'App-type:Unity'\n            keys: ['Unity']\n          - name: 'App-type:Xamarin'\n            keys: ['Xamarin']\n          - name: 'App-type:WPF'\n            keys: ['WPF']\n          - name: 'App-type:Console'\n            keys: ['Console or Server']\n          - name: 'App-type:Other'\n            keys: ['Other']\n\n      - id: [importance]\n        block-list: []\n        label:\n          - name: 'Importance:Dealbraker'\n            keys: ['Dealbreaker']\n          - name: 'Importance:Major'\n            keys: ['Would be a major improvement']\n          - name: 'Importance:Workaround'\n            keys: ['I would like to have it but have a workaround']\n          - name: 'Importance:Nice'\n            keys: ['Fairly niche but nice to have anyway']\n"
  },
  {
    "path": ".github/auto_assign.yml",
    "content": "addAssignees: author\naddReviewers: false\nrunOnDraft: true\n"
  },
  {
    "path": ".github/no-response.yml",
    "content": "# Configuration for probot-no-response - https://github.com/probot/no-response\n\n# Number of days of inactivity before an Issue is closed for lack of response\ndaysUntilClose: 14\n# Label requiring a response\nresponseRequiredLabel: More-information-needed\n# Comment to post when closing an Issue for lack of response. Set to `false` to disable\ncloseComment: >\n  This issue has been automatically closed because there has been no response\n  to our request for more information from the original author. With only the\n  information that is currently in the issue, we don't have enough information\n  to take action. Please reach out if you have or find the answers we need so\n  that we can investigate further.\n"
  },
  {
    "path": ".github/workflows/Issue-Needs-Attention.yml",
    "content": "# NOTE: This is a common file that is overwritten by realm/ci-actions sync service\n# and should only be modified in that repository.\n\nname: Issue Needs Attention\n# This workflow is triggered on issue comments.\non:\n  issue_comment:\n    types: created\n\njobs:\n  applyNeedsAttentionLabel:\n    uses: realm/ci-actions/.github/workflows/issue-needs-attention.yml@main\n"
  },
  {
    "path": ".github/workflows/auto-assign.yml",
    "content": "# NOTE: This is a common file that is overwritten by realm/ci-actions sync service\n# and should only be modified in that repository.\n\nname: 'Auto Assign'\non:\n  pull_request:\n    types: [opened]\n\njobs:\n  add-assignee:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: kentaro-m/auto-assign-action@248761c4feb3917c1b0444e33fad1a50093b9847\n"
  },
  {
    "path": ".github/workflows/check-changelog.yml",
    "content": "# NOTE: This is a common file that is overwritten by realm/ci-actions sync service\n# and should only be modified in that repository.\n\nname: \"Check Changelog\"\non:\n  pull_request:\n    types: [opened, synchronize, reopened, ready_for_review, labeled, unlabeled]\n\njobs:\n  changelog:\n    runs-on: ubuntu-latest\n    steps:\n      - name: Checkout\n        uses: actions/checkout@8230315d06ad95c617244d2f265d237a1682d445\n        with:\n          submodules: false\n      - name: Enforce Changelog\n        uses: dangoslen/changelog-enforcer@c0b9fd225180a405c5f21f7a74b99e2eccc3e951\n        with:\n          skipLabels: no-changelog\n          missingUpdateErrorMessage: Please add an entry in CHANGELOG.md or apply the 'no-changelog' label to skip this check.\n"
  },
  {
    "path": ".github/workflows/check-pr-title.yml",
    "content": "# NOTE: This is a common file that is overwritten by realm/ci-actions sync service\n# and should only be modified in that repository.\n\nname: \"Check PR Title\"\non:\n  pull_request:\n    types: [opened, synchronize, reopened, ready_for_review, labeled, unlabeled, converted_to_draft, edited]\n\njobs:\n  check-pr-title:\n    name: Check PR Title\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4\n        with:\n          submodules: false\n      - name: Enforce PR title\n        uses: realm/ci-actions/title-checker@main\n        with:\n          regex: R[A-Z]{2,6}-[0-9]{1,6}\n          error-hint: Invalid PR title. Make sure it's prefixed with the JIRA ticket the PR addresses or add the no-jira-ticket label.\n          ignore-labels: 'no-jira-ticket'"
  },
  {
    "path": ".github/workflows/gradle-wrapper-validation.yml",
    "content": "name: \"Validate Gradle Wrapper\"\non: [push, pull_request]\n\npermissions:\n  contents: read # to fetch code (actions/checkout)\n\njobs:\n  validation:\n    name: \"Validation\"\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v2\n      - uses: gradle/wrapper-validation-action@v1\n"
  },
  {
    "path": ".github/workflows/issue-labeler.yml",
    "content": "# NOTE: This is a common file that is overwritten by realm/ci-actions sync service\n# and should only be modified in that repository.\n\n# See configuration in .github/advanced-issue-labeler.yml\n\nname: Issue labeler (policy)\non:\n  issues:\n    types: [ opened ]\n\njobs:\n  label-issues-policy:\n    runs-on: ubuntu-latest\n    permissions:\n      issues: write\n\n    strategy:\n      matrix:\n        template: [ bug.yml, feature.yml ]\n\n    steps:\n      - uses: actions/checkout@v4\n\n      - name: Parse issue form\n        uses: stefanbuck/github-issue-parser@c1a559d78bfb8dd05216dab9ffd2b91082ff5324  # v3.0.1\n        id: issue-parser\n        with:\n          template-path: .github/ISSUE_TEMPLATE/${{ matrix.template }}\n\n      - name: Set labels based on policy\n        uses: redhat-plumbers-in-action/advanced-issue-labeler@6ee6fddfd744ee26b977e6a0436916f256896971  # v2.0.3\n        with:\n          issue-form: ${{ steps.issue-parser.outputs.jsonString }}\n          template: ${{ matrix.template }}\n          token: ${{ secrets.GITHUB_TOKEN }}\n"
  },
  {
    "path": ".github/workflows/lock-threads.yml",
    "content": "name: 'Lock Threads'\n\non:\n  schedule:\n    - cron: '0 * * * *'\n  workflow_dispatch:\n\npermissions:\n  issues: write\n  pull-requests: write\n  discussions: write\n\nconcurrency:\n  group: lock-threads\n\njobs:\n  action:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: dessant/lock-threads@v5\n        with:\n          issue-inactive-days: 30\n          pr-inactive-days: 30\n          log-output: true\n"
  },
  {
    "path": ".github/workflows/no-response.yml",
    "content": "# NOTE: This is a common file that is overwritten by realm/ci-actions sync service\n# and should only be modified in that repository.\n\nname: No Response\n\n# Both `issue_comment` and `scheduled` event types are required for this Action\n# to work properly.\non:\n  issue_comment:\n    types: [created]\n  schedule:\n    # Schedule at 00:00 every day\n    - cron: '0 0 * * *'\n\njobs:\n  noResponse:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: lee-dohm/no-response@v0.5.0\n        with:\n          token: ${{ github.token }}\n          responseRequiredLabel: More-information-needed\n"
  },
  {
    "path": ".gitignore",
    "content": "# Gradle build artifacts\nbuild\nrealm/build\n!realm-transformer/src/main/kotlin/io/realm/transformer/build\n\n# Gradle cache\n.gradle\n\n# Gradle local properties\nlocal.properties\n\n# Core\ncore\ncore-*\nrealm-sync-android-*\n!realm/realm-library/src/main/java/io/realm/internal/core/\n\n# Android Studio\n.idea\n*.iml\n\n# DS_Store\n.DS_Store\n*/.DS_Store\n\n# JNI libs\nrealm_version_check.timestamp\n\n# Build artifacts\n*.so\n*.d\n*.o\n\n# Backup files\n*.bak\n*~\n\n# Navigation Editor\n.navigation\n\n# Distribution files\nrealm*.jar\nrealm*.aar\ndistribution/*/realm\ndistribution/javadoc\ndistribution/version.txt\ndistribution/RealmGridViewExample/app/src\ndistribution/RealmIntroExample/app/src\ndistribution/RealmMigrationExample/app/src\n\n# Generated JNI headers\nrealm/realm-library/src/main/cpp/jni_include\n# Downloaded core\nrealm/realm-library/distribution\n# Cmake output\nrealm/realm-library/.externalNativeBuild\nrealm/realm-library/.cxx\n"
  },
  {
    "path": ".gitmodules",
    "content": "[submodule \"realm/realm-library/src/main/cpp/realm-core\"]\n\tpath = realm/realm-library/src/main/cpp/realm-core\n\turl = https://github.com/realm/realm-core.git\n"
  },
  {
    "path": "CHANGELOG.md",
    "content": "## 11.0.0 (2024-09-DD)\n\n### Breaking Changes\n* None.\n\n### Enhancements\n* None.\n\n### Fixed\n* None.\n\n### Compatibility\n* File format: Generates Realms with format v23. Unsynced Realms will be upgraded from Realm Java 2.0 and later. Synced Realms can only be read and upgraded if created with Realm Java v10.0.0-BETA.1.\n* APIs are backwards compatible with all previous release of realm-java in the 10.6.y series.\n* Realm Studio 13.0.0 or above is required to open Realms created by this version.\n* Gradle 7.5 and above.\n* Android Gradle Plugin 7.4.0 and above.\n\n### Internal\n* Updated links to new documentation URL.\n\n\n## 10.19.0 (2024-09-13)\n\n### Breaking Changes\n* None.\n\n### Enhancements\n* None.\n\n### Fixed\n* Use 16 KB ELF packaging for native artifacts produced by `realm-library`, allowing them to be loaded on devices with 16 KB memory page sizes. (Issue [#7894](https://github.com/realm/realm-java/issues/7894))\n\n### Compatibility\n* File format: Generates Realms with format v23. Unsynced Realms will be upgraded from Realm Java 2.0 and later. Synced Realms can only be read and upgraded if created with Realm Java v10.0.0-BETA.1.\n* APIs are backwards compatible with all previous release of realm-java in the 10.6.y series.\n* Realm Studio 13.0.0 or above is required to open Realms created by this version.\n* Gradle 7.5 and above.\n* Android Gradle Plugin 7.4.0 and above.\n\n### Internal\n* Updated links to new documentation URL.\n\n\n## 10.18.0 (2024-02-06)\n\n### Breaking Changes\n* None.\n\n### Enhancements\n* None.\n\n### Fixed\n* None.\n\n### Compatibility\n* File format: Generates Realms with format v23. Unsynced Realms will be upgraded from Realm Java 2.0 and later. Synced Realms can only be read and upgraded if created with Realm Java v10.0.0-BETA.1.\n* APIs are backwards compatible with all previous release of realm-java in the 10.6.y series.\n* Realm Studio 13.0.0 or above is required to open Realms created by this version.\n* Gradle 7.5 and above.\n* Android Gradle Plugin 7.4.0 and above.\n\n### Internal\n* Updated to Realm Core 13.26.0, commit 5533505d18fda93a7a971d58a191db5005583c92.\n* Updated to CMake 3.27.7.\n\n\n## 10.17.0 (2023-10-13)\n\nThis release upgrades the Sync metadata in a way that is not compatible with older versions. To downgrade a Sync app from this version, you'll need to manually delete the metadata folder located at $[SYNC-ROOT-DIRECTORY]/mongodb-realm/[APP-ID]/server-utility/metadata/. This will log out all users.\n\n### Breaking Changes\n* None.\n\n### Enhancements\n* [RealmApp] Simplified the number of error codes in `ErrorCode`. A number of enum entries have been deprecated. (Issue [#7837](https://github.com/realm/realm-java/pull/7837)).\n\n### Fixed\n* Rare corruption causing 'Invalid streaming format cookie'-exception. Typically following compact, convert or copying to a new file. (Issue [#7775](https://github.com/realm/realm-java/issues/7775), since v10.13.0 (Core v12.12.0))\n* [RealmApp] Crash when opening a Realm with a proxy enabled. (Issue [#7828](https://github.com/realm/realm-java/issues/7828))\n\n### Compatibility\n* File format: Generates Realms with format v23. Unsynced Realms will be upgraded from Realm Java 2.0 and later. Synced Realms can only be read and upgraded if created with Realm Java v10.0.0-BETA.1.\n* APIs are backwards compatible with all previous release of realm-java in the 10.6.y series.\n* Realm Studio 13.0.0 or above is required to open Realms created by this version.\n* Gradle 7.5 and above.\n* Android Gradle Plugin 7.4.0 and above.\n\n### Internal\n* Updated to Realm Core 13.23.0, commit 5abbf7f10fb3ef6bd622877cc840ada804bccb89.\n\n\n## 10.16.2 (2023-10-12)\n\n### Breaking Changes\n* None.\n\n### Enhancements\n* None.\n\n### Fixed\n* Realm objects accessors behave as an unmanaged object after an incremental build. (Issue [#7844](https://github.com/realm/realm-java/pull/7844))\n* [RealmApp] Crash when opening a Realm with a proxy enabled. (Issue [#7828](https://github.com/realm/realm-java/issues/7828))\n* [RealmApp] It was possible to create a `User` object with invalid state that would throw a `NullPointerException` when accessed. (Issue [#7847](https://github.com/realm/realm-java/issues/7847))\n\n### Compatibility\n* File format: Generates Realms with format v23. Unsynced Realms will be upgraded from Realm Java 2.0 and later. Synced Realms can only be read and upgraded if created with Realm Java v10.0.0-BETA.1.\n* APIs are backwards compatible with all previous release of realm-java in the 10.6.y series.\n* Realm Studio 13.0.0 or above is required to open Realms created by this version.\n* Gradle 7.5 and above.\n* Android Gradle Plugin 7.4.0 and above.\n\n### Internal\n* None.\n\n\n## 10.16.1 (2023-06-26)\n\n### Breaking Changes\n* None.\n\n### Enhancements\n* None.\n\n### Fixed\n* [RealmApp] Sync errors could return the error code UNKNOWN instead of the actual error code. (Issue [#7823](https://github.com/realm/realm-java/issues/7823))\n\n### Compatibility\n* File format: Generates Realms with format v23. Unsynced Realms will be upgraded from Realm Java 2.0 and later. Synced Realms can only be read and upgraded if created with Realm Java v10.0.0-BETA.1.\n* APIs are backwards compatible with all previous release of realm-java in the 10.6.y series.\n* Realm Studio 13.0.0 or above is required to open Realms created by this version.\n* Gradle 7.5 and above.\n* Android Gradle Plugin 7.4.0 and above.\n\n### Internal\n* None.\n\n\n## 10.16.0 (2023-06-02)\n\n### Breaking Changes\n* None.\n\n### Enhancements\n* Add support for sorting query results on dictionary values through `RealmQuery.rawPredicate(\"<PREDICATE> SORT(<DICTIONARY-PROPERTY>['<DICTIONARY-KEY>'] <ORDER>)\")` (Issue [#7817](https://github.com/realm/realm-java/issues/7817)).\n* Improve performance of equality queries on a non-indexed mixed property by about 30%. (Core Issue [#6506](https://github.com/realm/realm-core/issues/6506))\n* [RealmApp] Support for migrating from Partition-based to Flexible Sync automatically on the device if the server has migrated to Flexible Sync. (Core Issue [#6554](https://github.com/realm/realm-core/issues/6554))\n\n### Fixed\n* Add support for incremental builds on the bytecode transformation with the new AGP transform API. Incremental builds can be disabled by setting the gradle property `io.realm.disableIncrementalBuilds` to `true`. (Issue [#7802](https://github.com/realm/realm-java/issues/7802))\n\n### Compatibility\n* File format: Generates Realms with format v23. Unsynced Realms will be upgraded from Realm Java 2.0 and later. Synced Realms can only be read and upgraded if created with Realm Java v10.0.0-BETA.1.\n* APIs are backwards compatible with all previous release of realm-java in the 10.6.y series.\n* Realm Studio 13.0.0 or above is required to open Realms created by this version.\n* Gradle 7.5 and above.\n* Android Gradle Plugin 7.4.0 and above.\n\n### Internal\n* Updated to Realm Core 13.13.0, commit 79183be6417821431fff44a6d416a68664957c66.\n\n\n## 10.15.1 (2023-05-20)\n\n### Breaking Changes\n* None.\n\n### Enhancements\n* None.\n\n### Fixed\n* Building with Realm on Java 17 would fail with `java.lang.IllegalAccessError: class io.realm.processor.Utils (in unnamed module @0x5316ec7f) cannot access class com.sun.tools.javac.code.Symbol$ClassSymbol`. (Issue [#7799](https://github.com/realm/realm-java/issues/7799))\n\n### Compatibility\n* File format: Generates Realms with format v23. Unsynced Realms will be upgraded from Realm Java 2.0 and later. Synced Realms can only be read and upgraded if created with Realm Java v10.0.0-BETA.1.\n* APIs are backwards compatible with all previous release of realm-java in the 10.6.y series.\n* Realm Studio 13.0.0 or above is required to open Realms created by this version.\n* Gradle 7.5 and above.\n* Android Gradle Plugin 7.4.0 and above.\n\n### Internal\n* Updated to Google Compile Testing 0.21.0.\n* Updated Annotation Processor to use Java 11 reflection API's.\n\n\n## 10.15.0 (2023-04-19)\n\n### Breaking Changes\n* Minimum version of Android Gradle Plugin has been raised to 7.4.\n* Minimum version of Java has been raised to 11.\n* Minimum supported version of Gradle has been raised to 7.5.\n\n### Enhancements\n* None.\n\n### Fixed\n* Building with Realm on Java 17 would fail with `java.lang.IllegalAccessError: class io.realm.processor.Utils (in unnamed module @0x5316ec7f) cannot access class com.sun.tools.javac.code.Symbol$ClassSymbol`. (Issue [#7799](https://github.com/realm/realm-java/issues/7799))\n\n### Compatibility\n* File format: Generates Realms with format v23. Unsynced Realms will be upgraded from Realm Java 2.0 and later. Synced Realms can only be read and upgraded if created with Realm Java v10.0.0-BETA.1.\n* APIs are backwards compatible with all previous release of realm-java in the 10.6.y series.\n* Realm Studio 13.0.0 or above is required to open Realms created by this version.\n* Gradle 7.5 and above.\n* Android Gradle Plugin 7.4.0 and above.\n\n### Internal\n* None.\n\n\n## 10.14.0-transformer-api (2023-04-14)\n\nThis release will bump the Realm file format from version 22 to 23. Opening a file with an older format will automatically upgrade it. Downgrading to a previous file format is not possible.\n\n### Breaking Changes\n* [RealmApp] As a result of a refactor on the some error codes and categories have been deleted and new ones have been added, see PR for more details. ([#7760](https://github.com/realm/realm-java/pull/7760))\n\n### Enhancements\n* Updated OpenSSL from 1.1.1n to 3.0.8.\n* Realm will now use a lot less memory and disk space when different versions of realm objects are used. (Core Issue [#5440](https://github.com/realm/realm-core/issues/5440))\n* Realm will now use a lot less memory and disk space when different versions of realm objects are used. (Core Issue [#5440](https://github.com/realm/realm-core/issues/5440))\n* Realm will now continuously track and reduce the size of the Realm file when it is in use rather that only when opening the file with Configuration.compactOnLaunch enabled. (Core Issue [#5754](https://github.com/realm/realm-core/issues/5754))\n* Multiple processes can now access the same encrypted Realm instead of throwing `Encrypted interprocess sharing is currently unsupported`. (Core Issue [#1845](https://github.com/realm/realm-core/issues/1845))\n\n### Fixed\n* Set<Mixed> consider string and binary data equivalent. This could cause the client to be inconsistent with the server if a string and some binary data with equivalent content was inserted from Atlas. ([#4860](https://github.com/realm/realm-core/issues/4860), since v11.0.0)\n* Fixed wrong assertion on query error that could result in a crash. ([#6038](https://github.com/realm/realm-core/issues/6038), since v11.7.0)\n* Fixed a bug that would result in `RealmDictionary` not being able to find `double` values due not taking the precision of the input parameter into consideration when using `RealmDictionary.contains`.\n* Not possible to open an encrypted file on a device with a page size bigger than the one on which the file was produced. ([#8030](https://github.com/realm/realm-swift/issues/8030), since v12.11.0)\n* Fix no notification for write transaction that contains only change to backlink property. ([#4994](https://github.com/realm/realm-core/issues/4994), since v11.4.1)\n\n### Compatibility\n* File format: Generates Realms with format v23. Unsynced Realms will be upgraded from Realm Java 2.0 and later. Synced Realms can only be read and upgraded if created with Realm Java v10.0.0-BETA.1.\n* APIs are backwards compatible with all previous release of realm-java in the 10.6.y series.\n* Realm Studio 11.0.0-alpha.0 or above is required to open Realms created by this version.\n\n### Internal\n* Updated to Realm Core 13.9.0, commit 063927de66f79a0afffbbe36c0bb14d27deba8f2.\n\n\n## 10.14.0 (2023-04-13)\n\nThis release will bump the Realm file format from version 22 to 23. Opening a file with an older format will automatically upgrade it. Downgrading to a previous file format is not possible.\n\n### Breaking Changes\n* [RealmApp] As a result of a refactor on the some error codes and categories have been deleted and new ones have been added, see PR for more details. ([#7760](https://github.com/realm/realm-java/pull/7760))\n\n### Enhancements\n* Updated OpenSSL from 1.1.1n to 3.0.8.\n* Realm will now use a lot less memory and disk space when different versions of realm objects are used. (Core Issue [#5440](https://github.com/realm/realm-core/issues/5440))\n* Realm will now continuously track and reduce the size of the Realm file when it is in use rather that only when opening the file with Configuration.compactOnLaunch enabled. (Core Issue [#5754](https://github.com/realm/realm-core/issues/5754))\n* Multiple processes can now access the same encrypted Realm instead of throwing `Encrypted interprocess sharing is currently unsupported`. (Core Issue [#1845](https://github.com/realm/realm-core/issues/1845))\n\n### Fixed\n* Set<Mixed> consider string and binary data equivalent. This could cause the client to be inconsistent with the server if a string and some binary data with equivalent content was inserted from Atlas. ([#4860](https://github.com/realm/realm-core/issues/4860), since v11.0.0)\n* Fixed wrong assertion on query error that could result in a crash. ([#6038](https://github.com/realm/realm-core/issues/6038), since v11.7.0)\n* Fixed a bug that would result in `RealmDictionary` not being able to find `double` values due not taking the precision of the input parameter into consideration when using `RealmDictionary.contains`.\n* Not possible to open an encrypted file on a device with a page size bigger than the one on which the file was produced. ([#8030](https://github.com/realm/realm-swift/issues/8030), since v12.11.0)\n* Fix no notification for write transaction that contains only change to backlink property. ([#4994](https://github.com/realm/realm-core/issues/4994), since v11.4.1)\n\n### Compatibility\n* File format: Generates Realms with format v23. Unsynced Realms will be upgraded from Realm Java 2.0 and later. Synced Realms can only be read and upgraded if created with Realm Java v10.0.0-BETA.1.\n* APIs are backwards compatible with all previous release of realm-java in the 10.6.y series.\n* Realm Studio 11.0.0-alpha.0 or above is required to open Realms created by this version.\n\n### Internal\n* Updated to Realm Core 13.9.0, commit 063927de66f79a0afffbbe36c0bb14d27deba8f2.\n\n\n## 10.13.3-transformer-api (2023-03-16)\n\n### Enhancements\n* None.\n\n### Fixed\n* Added support for automatic handling of orphan embedded objects after migrating regular object properties to become embedded objects. (Issue [#7769](https://github.com/realm/realm-java/issues/7769)).\n* Unit tests not being executed. (Issue [#7771](https://github.com/realm/realm-java/issues/7771))\n* Instrumented unit tests failed to execute because of the Realm dependencies being missing. (Issue [#7736](https://github.com/realm/realm-java/issues/7736))\n\n### Compatibility\n* File format: Generates Realms with format v22. Unsynced Realms will be upgraded from Realm Java 2.0 and later. Synced Realms can only be read and upgraded if created with Realm Java v10.0.0-BETA.1.\n* APIs are backwards compatible with all previous release of realm-java in the 10.6.y series.\n* Realm Studio 11.0.0-alpha.0 or above is required to open Realms created by this version.\n\n### Internal\n* None.\n\n\n## 10.13.2-transformer-api (2023-01-27)\n\n### Enhancements\n* None.\n\n### Fixed\n* Fix zip path separator for transformer on Windows (Issue [#7757](https://github.com/realm/realm-java/issues/7757))\n\n### Compatibility\n* File format: Generates Realms with format v22. Unsynced Realms will be upgraded from Realm Java 2.0 and later. Synced Realms can only be read and upgraded if created with Realm Java v10.0.0-BETA.1.\n* APIs are backwards compatible with all previous release of realm-java in the 10.6.y series.\n* Realm Studio 11.0.0-alpha.0 or above is required to open Realms created by this version.\n\n### Internal\n* None.\n\n\n## 10.13.1-transformer-api (2023-01-16)\n\n### Enhancements\n* None.\n\n### Fixed\n* Add support for Gradle configuration cache. (Issue [#7299](https://github.com/realm/realm-java/issues/7299))\n\n### Compatibility\n* File format: Generates Realms with format v22. Unsynced Realms will be upgraded from Realm Java 2.0 and later. Synced Realms can only be read and upgraded if created with Realm Java v10.0.0-BETA.1.\n* APIs are backwards compatible with all previous release of realm-java in the 10.6.y series.\n* Realm Studio 11.0.0-alpha.0 or above is required to open Realms created by this version.\n\n### Internal\n* None.\n\n### Credits\n* Thanks to @pstavytskyi-turo for adding support for Gradle configuration cache. (Issue [#7299](https://github.com/realm/realm-java/issues/7299))\n\n\n## 10.13.1 (2023-03-16)\n\n### Enhancements\n* None.\n\n### Fixed\n* Added support for automatic handling of orphan embedded objects after migrating regular object properties to become embedded objects. (Issue [#7769](https://github.com/realm/realm-java/issues/7769)).\n\n### Compatibility\n* File format: Generates Realms with format v22. Unsynced Realms will be upgraded from Realm Java 2.0 and later. Synced Realms can only be read and upgraded if created with Realm Java v10.0.0-BETA.1.\n* APIs are backwards compatible with all previous release of realm-java in the 10.6.y series.\n* Realm Studio 11.0.0-alpha.0 or above is required to open Realms created by this version.\n\n### Internal\n* None.\n\n\n## 10.13.0-transformer-api (2012-12-12)\n\n### Enhancements\n* [RealmApp] Added option for working with Device Sync from an internal network. `SyncConfiguration.trustedRootCA(assetPath)` can embed a custom certificate in the app that will be used by Sync. (Issue [#7739](https://github.com/realm/realm-java/pull/7739)).\n* [RealmApp] Added option for working with Device Sync from an internal network. `SyncConfiguration.disableSSLVerification()` makes it possible to turn off local SSL validation. (Issue [#7739](https://github.com/realm/realm-java/pull/7739)).\n\n### Fixed\n* Fixed database corruption and encryption issues on apple platforms. (Issue [#5076](https://github.com/realm/realm-js/issues/5076))\n* [Sync] Bootstraps will not be applied in a single write transaction - they will be applied 1MB of changesets at a time. (Issue [#5999](https://github.com/realm/realm-core/pull/5999)).\n* [Sync] Fixed a race condition which could result in operation cancelled errors being delivered to `Realm.open` rather than the actual sync error which caused things to fail. (Issue [#5968](https://github.com/realm/realm-core/pull/5968)).\n\n### Compatibility\n* File format: Generates Realms with format v22. Unsynced Realms will be upgraded from Realm Java 2.0 and later. Synced Realms can only be read and upgraded if created with Realm Java v10.0.0-BETA.1.\n* APIs are backwards compatible with all previous release of realm-java in the 10.6.y series.\n* Realm Studio 11.0.0-alpha.0 or above is required to open Realms created by this version.\n\n### Internal\n* Updated to Realm Core 12.13.0, commit b77443ca7fa25407869ca537bf3ae912b1427bff.\n\n\n## 10.13.0 (2022-12-05)\n\n### Enhancements\n* [RealmApp] Added option for working with Device Sync from an internal network. `SyncConfiguration.trustedRootCA(assetPath)` can embed a custom certificate in the app that will be used by Sync. (Issue [#7739](https://github.com/realm/realm-java/pull/7739)).\n* [RealmApp] Added option for working with Device Sync from an internal network. `SyncConfiguration.disableSSLVerification()` makes it possible to turn off local SSL validation. (Issue [#7739](https://github.com/realm/realm-java/pull/7739)).\n\n### Fixed\n* Fixed database corruption and encryption issues on apple platforms. (Issue [#5076](https://github.com/realm/realm-js/issues/5076))\n* [Sync] Bootstraps will not be applied in a single write transaction - they will be applied 1MB of changesets at a time. (Issue [#5999](https://github.com/realm/realm-core/pull/5999)).\n* [Sync] Fixed a race condition which could result in operation cancelled errors being delivered to `Realm.open` rather than the actual sync error which caused things to fail. (Issue [#5968](https://github.com/realm/realm-core/pull/5968)).\n\n### Compatibility\n* File format: Generates Realms with format v22. Unsynced Realms will be upgraded from Realm Java 2.0 and later. Synced Realms can only be read and upgraded if created with Realm Java v10.0.0-BETA.1.\n* APIs are backwards compatible with all previous release of realm-java in the 10.6.y series.\n* Realm Studio 11.0.0-alpha.0 or above is required to open Realms created by this version.\n\n### Internal\n* Updated to Realm Core 12.13.0, commit b77443ca7fa25407869ca537bf3ae912b1427bff.\n\n\n## 10.12.0-transformer-api (2022-09-28)\n\n### Breaking Changes\n* Only works with Android Gradle Plugin 7.4 or newer. (Issue [#7714](https://github.com/realm/realm-java/issues/7714))\n\n### Enhancements\n* [RealmApp] Introduced `SyncSession.RecoverOrDiscardUnsyncedChangesStrategy`, an alternative automatic client reset strategy that tries to automatically recover any unsynced data from the client, and discards any unsynced data if not possible. This is now the default client reset policy if not explicitly set in the `SyncConfiguration`.\n* [RealmApp] Introduced `SyncSession.RecoverUnsyncedChangesStrategy`, an alternative automatic client reset strategy that tries to automatically recover any unsynced data from the client and will revert to manual client reset if not possible.\n* [RealmApp] Flexible sync client reset is no longer limited to `ManuallyRecoverChangesStrategy`, it now supports all available strategies: `RecoverOrDiscardUnsyncedChangesStrategy`, `RecoverUnsyncedChangesStrategy`, `DiscardUnsyncedChangesStrategy` and `ManuallyRecoverChangesStrategy`.\n\n### Fixed\n* Now queries can point to fields with query language-reserved words like 'desc', 'sort', 'distinct', etc. Issue [#7705](https://github.com/realm/realm-java/issues/7705)\n\n### Compatibility\n* File format: Generates Realms with format v22. Unsynced Realms will be upgraded from Realm Java 2.0 and later. Synced Realms can only be read and upgraded if created with Realm Java v10.0.0-BETA.1.\n* APIs are backwards compatible with all previous release of realm-java in the 10.6.y series.\n* Realm Studio 11.0.0-alpha.0 or above is required to open Realms created by this version.\n\n### Internal\n* Update to Realm Core 12.6.0, commit: 5da7744b4056ad185c025bccf0924f17f73f7a91.\n\n\n## 10.12.0 (2022-09-22)\n\n### Enhancements\n* [RealmApp] Introduced `SyncSession.RecoverOrDiscardUnsyncedChangesStrategy`, an alternative automatic client reset strategy that tries to automatically recover any unsynced data from the client, and discards any unsynced data if not possible. This is now the default client reset policy if not explicitly set in the `SyncConfiguration`.\n* [RealmApp] Introduced `SyncSession.RecoverUnsyncedChangesStrategy`, an alternative automatic client reset strategy that tries to automatically recover any unsynced data from the client and will revert to manual client reset if not possible.\n* [RealmApp] Flexible sync client reset is no longer limited to `ManuallyRecoverChangesStrategy`, it now supports all available strategies: `RecoverOrDiscardUnsyncedChangesStrategy`, `RecoverUnsyncedChangesStrategy`, `DiscardUnsyncedChangesStrategy` and `ManuallyRecoverChangesStrategy`.\n\n### Fixed\n* Now queries can point to fields with query language-reserved words like 'desc', 'sort', 'distinct', etc. Issue [#7705](https://github.com/realm/realm-java/issues/7705)\n\n### Compatibility\n* File format: Generates Realms with format v22. Unsynced Realms will be upgraded from Realm Java 2.0 and later. Synced Realms can only be read and upgraded if created with Realm Java v10.0.0-BETA.1.\n* APIs are backwards compatible with all previous release of realm-java in the 10.6.y series.\n* Realm Studio 11.0.0-alpha.0 or above is required to open Realms created by this version.\n\n### Internal\n* Update to Realm Core 12.6.0, commit: 5da7744b4056ad185c025bccf0924f17f73f7a91.\n\n\n## 10.11.1 (2022-07-14)\n\n### Enhancements\n* None\n\n### Fixed\n* Fixed deadlock while trying to close all Realm instances during a manual client reset. Issue [#7696](https://github.com/realm/realm-java/pull/7696))\n* [RealmApp] Throw RuntimeException if subscription set is requested and flexible sync is not enabled. (Realm Core issue [#5079](https://github.com/realm/realm-core/issues/5079))\n* Adding an object to a Set, deleting the parent object, and then deleting the previously mentioned object causes crash. (Realm Core issue [#5387](https://github.com/realm/realm-core/issues/5387), since 11.0.0)\n* [RealmApp] The sync client may have sent a corrupted upload cursor leading to a fatal error from the server due to an uninitialized variable. ([#5460](https://github.com/realm/realm-core/pull/5460, since v11.14.0)\n* [RealmApp] Flexible sync would not correctly resume syncing if a bootstrap was interrupted. ([#5466](https://github.com/realm/realm-core/pull/5466, since v11.8.0)\n* [RealmApp] Flexible sync subscription state changes will now correctly be reported after sync progress is reported. ([#5553](https://github.com/realm/realm-core/pull/5553, since v12.0.0)\n\n### Compatibility\n* File format: Generates Realms with format v22. Unsynced Realms will be upgraded from Realm Java 2.0 and later. Synced Realms can only be read and upgraded if created with Realm Java v10.0.0-BETA.1.\n* APIs are backwards compatible with all previous release of realm-java in the 10.6.y series.\n* Realm Studio 11.0.0-alpha.0 or above is required to open Realms created by this version.\n\n### Internal\n* Update to Realm Core 12.3.0, commit: 55a48c287b5e3a8ca129c257ec7e3b92bcb2a05f.\n\n\n## 10.11.0 (2022-05-20)\n\n### Enhancements\n* Throw a more comprehensive error when initializing Realm on an Instant App.\n\n### Fixed\n* Fixed various corruption bugs when encryption is used. (Realm Core issue [#5360](https://github.com/realm/realm-core/issues/5360), since 10.10.0)\n* Fixed imprecise conversion from double/float to Decimal128. (Realm Core issue [#5191](https://github.com/realm/realm-core/pull/5191))\n* Fixed `RealmQuery.distinct` when it receives three or more arguments. (Issue [#7639](https://github.com/realm/realm-java/pull/7639))\n* Fix issues resolving class information for `copyToRealmOrUpdate` for already managed objects in multi module projects. (Issue [#7650](https://github.com/realm/realm-java/issues/7650))\n\n### Compatibility\n* File format: Generates Realms with format v22. Unsynced Realms will be upgraded from Realm Java 2.0 and later. Synced Realms can only be read and upgraded if created with Realm Java v10.0.0-BETA.1.\n* APIs are backwards compatible with all previous release of realm-java in the 10.6.y series.\n* Realm Studio 11.0.0-alpha.0 or above is required to open Realms created by this version.\n\n### Internal\n* Update to Realm Core 11.14.0, commit: db7ca86cf7ff8c9c3da6c7e742ecd46315ddc280.\n\n### Credits\n* Thanks to @Mr4Mike4 for fixing `RealmQuery.distinct` when it receives three or more arguments ([#7639](https://github.com/realm/realm-java/pull/7639)).\n* Thanks to @Waboodoo for fixing some typos ([#7646](https://github.com/realm/realm-java/pull/7646)).\n* Thanks to @ZherebtsovAlexandr for updating the use of the deprecated method `offer` to `trySend` ([#7648](https://github.com/realm/realm-java/pull/7648)).\n\n\n## 10.10.1 (2022-01-26)\n\n### Enhancements\n* [RealmApp] Add support for setting the filename on Flexible and Partition Sync configurations.\n\n### Fixed\n* [RealmApp] Creating multiple anonymous subscriptions for a Realm would throw an exception.\n\n### Compatibility\n* File format: Generates Realms with format v22. Unsynced Realms will be upgraded from Realm Java 2.0 and later. Synced Realms can only be read and upgraded if created with Realm Java v10.0.0-BETA.1.\n* APIs are backwards compatible with all previous release of realm-java in the 10.6.y series.\n* Realm Studio 11.0.0-alpha.0 or above is required to open Realms created by this version.\n\n### Internal\n* Updated to Android Gradle Plugin 7.1.0\n* Updated to Gradle 7.3.3.\n\n\n## 10.10.0 (2022-01-18)\n\n### Enhancements\n* [RealmApp] Add support for a new mode for synchronized realms: Flexible Sync that only synchronizes selective parts of the backend data. The following classes have been added to support this: `Subscription`, `SubscriptionSet` and `MutableSubscriptionSet`. This mode and all APIs are marked as Beta.\n\n### Fixed\n* [RealmApp] The sync client will now drain the receive queue when send fails with ECONNRESET - ensuring that any error message from the server gets received and processed. (Realm Core issue [#5078](https://github.com/realm/realm-core/pull/5078))\n* [RealmApp] UserIdentity metadata table grows indefinitely. (Realm Core issue [#5152](https://github.com/realm/realm-core/issues/5152))\n* Schema validation was missing for embedded objects in sets, resulting in an unhelpful error being thrown if the user attempted to define one.\n* Output from the annotation processor was not deterministic, which could result in cache misses. (Issue [#7615](https://github.com/realm/realm-java/issues/7615))\n* Crashes when using `RealmAny` inside `RealmList` on ARM 32 devices. (Issue [#7626](https://github.com/realm/realm-java/issues/7626))\n\n### Compatibility\n* File format: Generates Realms with format v22. Unsynced Realms will be upgraded from Realm Java 2.0 and later. Synced Realms can only be read and upgraded if created with Realm Java v10.0.0-BETA.1.\n* APIs are backwards compatible with all previous release of realm-java in the 10.6.y series.\n* Realm Studio 11.0.0-alpha.0 or above is required to open Realms created by this version.\n\n### Internal\n* Update to Realm Core 11.9.0, commit: 733f12702d16ab0d0c7fea0831a2aee5ca5c26db.\n\n### Credits\n* Thanks to @jprinet for making the annotation processor output deterministic.\n\n\n## 10.9.0 (2021-12-06)\n\n### Enhancements\n* [RealmApp] Add support for UUID's as partition values. (Issue [#7598](https://github.com/realm/realm-java/issues/7598))\n* [RealmApp] Reduced native memory usage when working with synchronized Realms.\n* [RealmApp] Make it possible to bundle synchronized Realms in apps using `Realm.writeCopyTo()` and `SyncConfiguration.Builder.assetFile()`.\n* The Realm Transformer and Realm Gradle Plugin now supports the Gradle Configuration Cache. (Issue [#7299](https://github.com/realm/realm-java/issues/7299))\n* [RealmApp] Introduced `SyncSession.DiscardUnsyncedChangesStrategy`, an alternative automatic client reset strategy that doesn't require the Realm to be closed, but discards any unsynced data from the client. This is now the default policy if not overridden.\n\n### Deprecated\n* [RealmApp] `SyncSession.ClientResetHandler()`. Use `SyncSession.ManuallyRecoverUnsyncedChangesStrategy()` instead.\n* [RealmApp] `AppConfiguration.Builder.defaultClientResetHandler()`. Use `AppConfiguration.Builder.setDefaultSyncClientResetStrategy()` instead.\n* [RealmApp] `AppConfiguration.getDefaultClientResetHandler()`. Use `AppConfiguration.getDefaultSyncClientResetStrategy()` instead.\n* [RealmApp] `SyncConfiguration.Builder.clientResetHandler()`. Use `SyncConfiguration.Builder.setSyncClientResetStrategy()` instead.\n* [RealmApp] `SyncConfiguration.getClientResetHandler()`. Use `SyncConfiguration.getSyncClientResetStrategy()` instead.\n\n### Fixed\n* [RealmApp] Setting `AppConfiguration.syncRootDirectory()` didn't have any effect beside creating the new folder. Realms were still placed in the default location.\n* [RealmApp] Bug where progress notifiers continue to be called after the download of a synced realm is complete. (Issue [Realm Core #4919](https://github.com/realm/realm-core/issues/4919))\n* [RealmApp] User being left in the logged in state when the user's refresh token expires. (Issue [Realm Core #4882](https://github.com/realm/realm-core/issues/4882), since v10)\n* Using \"sort\", \"distinct\", or \"limit\" as field name in query expression would cause an \"Invalid predicate\" error. (Issue [#7545](), since v10.X.X)\n* Crash when quering with 'Not()' followed by empty group. (Issue [Realm Core #4168]() since v1.0.0)\n* Streaming download notifiers reported incorrect values for transferrable bytes. (Issue [Realm Core #5008]() since v11.5.2)\n* `@sum` and `@avg` queries on Dictionaries of floats or doubles used too much precision for intermediates, resulting in incorrect rounding.\n\n### Compatibility\n* File format: Generates Realms with format v22. Unsynced Realms will be upgraded from Realm Java 2.0 and later. Synced Realms can only be read and upgraded if created with Realm Java v10.0.0-BETA.1.\n* APIs are backwards compatible with all previous release of realm-java in the 10.6.y series.\n* Realm Studio 11.0.0-alpha.0 or above is required to open Realms created by this version.\n\n### Internal\n* Updated to Realm Core 11.7.0, commit: 81eafa44879eb5f5829b345005abf99adb306133.\n* Building the SDK now requires JDK 11.\n* Updated to Gradle 7.2.\n* Updated to Android Gradle Plugin 7.1.0-beta03.\n* Updated to Kotlin 1.5.31.\n* Updated to Kotlin Coroutines 1.5.2.\n* Updated to CMake 3.21.4.\n* Updated to NDK 23.1.7779620.\n* Disable analytics for any value of the `REALM_DISABLE_ANALYTICS` environment variable, not just `true`.\n* Disable analytics whenever the `CI` environment variable is set.\n\n\n## 10.8.1 (2021-10-28)\n\n### Enhancements\n* None.\n\n### Fixed\n* [RealmApp] Failing to refresh the access token due to a 401/403 error will now correctly emit an error with `ErrorCode.BAD_AUTHENTICATION` rather than `ErrorCode.PERMISSION_DENIED`. (Realm Core [#4881](https://github.com/realm/realm-core/issues/4881), since 10.6.1)\n* [RealmApp] If an object with a null primary key was deleted by another sync client, the exception `KeyNotFound: No such object` could be triggered. ([Realm Core #4885](https://github.com/realm/realm-core/issues/4885), since 10.0.0)\n* Exceptions inside change listeners running on background looper threads would crash the Looper with a native `JNI DETECTED ERROR IN APPLICATION: JNI NewLocalRef called with pending exception` instead of the original Java exception. This could also happen when canceling a corutine using a background looper as a Dispatcher.\n* [RealmApp] Reduced native memory use when synchronizing changes with the server in the background.\n\n### Compatibility\n* File format: Generates Realms with format v22. Unsynced Realms will be upgraded from Realm Java 2.0 and later. Synced Realms can only be read and upgraded if created with Realm Java v10.0.0-BETA.1.\n* APIs are backwards compatible with all previous release of realm-java in the 10.6.y series.\n* Realm Studio 11.0.0-alpha.0 or above is required to open Realms created by this version.\n\n### Internal\n* Updated to Realm Core 11.4.1, commit: 23f60515a00f076a9e3f2dc672fe1ae07601ee90.\n\n\n## 10.8.0 (2021-08-27)\n\n### Enhancements\n* [RealmApp] `ErrorCode.INVALID_EMAIL_PASSWORD` has been added, and is now thrown instead of `ErrorCode.SERVICE_UNKNOWN` when loggin in with the wrong credentials.\n* `RealmQuery.rawPredicate()` now accepts a \"BETWEEN\" operator. Can be used like \"age BETWEEN {20, 60}\" which means \"'Age' must be in the open interval ]20;60[\".\n* [RealmApp] Added `User.remove()` and `User.removeAsync()` that makes it possible to delete a user's Realm(s) from the device.\n\n### Fixed\n* [RealmApp] Crash when integrating a schema from the server with a `RealmAny` property to a Realm File that already had that property defined locally. ([Realm Core #4873](https://github.com/realm/realm-core/issues/4873), since 10.0.0)\n* [RealmApp] Refreshing the access token after 30 minutes would fail silently, causing infinite retries every 10 seconds. This would also block opening Realms when opening an app with an already logged in user. (Issue [#7501](https://github.com/realm/realm-java/issues/7501), since 10.0.0)\n* [RealmApp] Clarified Javadoc for `User.logOut()` and `User.logOutAsync()` as these methods do not delete a user's Realm(s).\n* Build error when having cross module model references (Issue [#7474](https://github.com/realm/realm-java/issues/7474), since v10.4.0)\n\n### Compatibility\n* File format: Generates Realms with format v22. Unsynced Realms will be upgraded from Realm Java 2.0 and later. Synced Realms can only be read and upgraded if created with Realm Java v10.0.0-BETA.1.\n* APIs are backwards compatible with all previous release of realm-java in the 10.6.y series.\n* Realm Studio 11.0.0-alpha.0 or above is required to open Realms created by this version.\n\n### Internal\n* Updated to Realm Core 11.3.0, commit: 321c79a67119db8177af13eefd5378586648ba73.\n\n\n## 10.7.1 (2021-08-03)\n\n### Enhancements\n* None.\n\n### Fixed\n* [RealmApp] Crash when an object which is linked to by a `RealmAny` is invalidated (Sync only). ([Realm Core #4828](https://github.com/realm/realm-core/issues/4828), since v10.6.0)\n* Object change listeners did not handle the object being deleted properly, which could result in assertion failures mentioning \"m_table\" in ObjectNotifier ([Realm Core #4824](https://github.com/realm/realm-core/issues/4824), since v10.6.0).\n* Crash when delivering notifications over a nested hierarchy of lists of `RealmAny` that contain object references. ([Realm Core #4803](https://github.com/realm/realm-core/issues/4803), since v10.6.0)\n\n### Compatibility\n* File format: Generates Realms with format v22. Unsynced Realms will be upgraded from Realm Java 2.0 and later. Synced Realms can only be read and upgraded if created with Realm Java v10.0.0-BETA.1.\n* APIs are backwards compatible with all previous release of realm-java in the 10.6.y series.\n* Realm Studio 11.0.0-alpha.0 or above is required to open Realms created by this version.\n\n### Internal\n* Updated to Realm Core 11.2.0, commit: 583fc73040709383470797813096bee17802398e.\n\n\n## 10.7.0 (2021-07-27)\n\n### Breaking Changes\n* Removed automatic injection of repositories from Gradle plugin. From now on `mavenCentral()` repository needs to be added manually. (Issue [#7365](https://github.com/realm/realm-java/issues/7365))\n\n### Enhancements\n* None.\n\n### Fixed\n* [RealmApp] Realm.getInstanceAsync does not wait for the initial remote data. (Issue [#7517](https://github.com/realm/realm-java/issues/7517))\n* Build errors when doing incremental builds with Android Studio's _Apply Changes..._-actions. (Issue [#7473](https://github.com/realm/realm-java/issues/7473))\n\n### Compatibility\n* File format: Generates Realms with format v22. Unsynced Realms will be upgraded from Realm Java 2.0 and later. Synced Realms can only be read and upgraded if created with Realm Java v10.0.0-BETA.1.\n* APIs are backwards compatible with all previous release of realm-java in the 10.6.y series.\n* Realm Studio 11.0.0-alpha.0 or above is required to open Realms created by this version.\n\n### Internal\n* Updated to Realm Core 11.1.1, commit: 71db56caba8f8ef0398eedfffb82a908cb94ccec.\n\n\n## 10.6.1 (2021-07-01)\n\n### Enhancements\n* None.\n\n### Fixed\n* [RealmApp] Configuring HTTP timeout through `AppConfiguration.Builder.requestTimeout()` did not work correctly. (Issue [#7455](https://github.com/realm/realm-java/issues/7455))\n* [RealmApp] A recursive loop that would eventually crash trying to refresh a user app token when it had been revoked by an admin. Now this situation logs the user out and reports an error. (Issue [#7501](https://github.com/realm/realm-java/issues/7501))\n* An endless recursive loop that could cause a stack overflow when computing changes on a set of objects which contained cycles. (Realm Core Issue [#4767](https://github.com/realm/realm-core/issues/4767))\n* Opening cached Realms no longer trigger `android.os.strictmode.DiskReadViolation`. (Issue [#7500](https://github.com/realm/realm-java/issues/7500]))\n* `NullPointerException` was thrown instead of `IllegalStateException` when calling `Realm.executeTransaction()` on a closed Realm. (Issue [#7511](https://github.com/realm/realm-java/issues/7511), since 10.0.0)\n* `RealmDictionary` did not handle hash collisions correctly. (Realm Core issue [#4776](https://github.com/realm/realm-core/issues/4767))\n* Crash after clearing a List or Set of `RealmAny` containing references to objects (Realm Core issue [#4774](https://github.com/realm/realm-core/issues/4774))\n\n### Compatibility\n* File format: Generates Realms with format v22. Unsynced Realms will be upgraded from Realm Java 2.0 and later. Synced Realms can only be read and upgraded if created with Realm Java v10.0.0-BETA.1.\n* APIs are backwards compatible with all previous release of realm-java in the 10.6.y series.\n* Realm Studio 11.0.0-alpha.0 or above is required to open Realms created by this version.\n\n### Internal\n* Updated to Realm Core 11.0.4, commit: 44304ce6104c4a9fc7e2359990c75be3b867b8fe.\n\n\n## 10.6.0 (2021-06-15)\n\nThis release combines all changes from 10.6.0-BETA.1 and 10.6.0-BETA.2.\n\n### Breaking Changes\n* [RealmApp] Sync protocol version increased to 3. This version adds support for the new data types introduced in file format version 21.\n* Primary keys now have automatic indexes again. Indexes was removed in v10.0.0 because they were not needed, but it caused issues when upgrading from a pre v10 version of Realm, and in some cases resulted in large delays when upgrading the fileformat. (Issue [#7426](https://github.com/realm/realm-java/issues/7426), since 10.0.0).\n* Queries no longer do nullability checks on non-nullable fields, so using `null` as an argument will not throw an `IllegalArgumentException`.\n* String query filters `contains`, `beginsWith`, `endsWith`, and `like`, now throw a null pointer exception on null values.\n* The query builder no longer throw `IllegalStateException` but `IllegalArgumentException`.\n* The `distinct` query filter on unsupported fields no longer throws an exception when applied through when querying across relationships.\n* The `distinct` query filter no longer throws an exception when applied on non-existent fields.\n* `RealmFieldType` has been updated to account for the new types being added.\n\n### Enhancements\n* Added support for `java.util.UUID` as supported field in model classes.\n* Added support for `java.util.UUID` as a primary key.\n* Added support for `RealmAny` as supported field in model classes. A `RealmAny` is used to represent a polymorphic Realm value or Realm Object, is indexable but cannot be used as a primary key. See [Javadoc for RealmAny](https://docs.mongodb.com/realm-sdks/java/latest/io/realm/RealmAny.html).\n* Added support for `RealmDictionary` as supported field in model classes. A `RealmDictionary` is a `Map` of strings to values - all types under the `RealmAny` umbrella can be used as values. See [Javadoc for RealmDictionary](https://docs.mongodb.com/realm-sdks/java/latest/io/realm/RealmDictionary.html) and [Javadoc for RealmMap](https://docs.mongodb.com/realm-sdks/java/latest/io/realm/RealmMap.html). `RealmDictionary` is not yet supported by any of the `Realm.insert` and `Realm.createFromJson` methods - This support will be added in a future release.\n* Added support for `RealmSet` as supported field in model classes. A `RealmSet` is a collection that implements the Java `Set` interface and contains no duplicate values - all types under the `RealmAny` umbrella can be used as values. See [Javadoc for RealmSet](https://docs.mongodb.com/realm-sdks/java/latest/io/realm/RealmSet.html). `RealmSet` is not yet supported by any of the `Realm.insert` and `Realm.createFromJson` methods - This support will be added in a future release.\n* Allow UTF8 encoded characters in property names in string-based queries ([#4467](https://github.com/realm/realm-core/issues/4467))\n* The error message when the initial steps of opening a Realm file fails is now more descriptive.\n* Make conversion of Decimal128 to/from string work for numbers with more than 19 significant digits. ([#4548](https://github.com/realm/realm-core/issues/4548))\n* Remove type coercion on bool and ObjectId when doing queries.\n* Allow passing arguments into string-based query predicates.\n* Queries across relationships now support the `between` operator.\n* Queries on numerical fields (byte, short, int, long, float, double, decimal128) now accept any numerical value as an argument.\n* `isEmpty` query filter can now be applied on `RealmList` and `RealmObject` fields.\n\n### Fixed\n* Fix assertion failures such as \"!m_notifier_skip_version.version\" or \"m_notifier_sg->get_version() + 1 == new_version.version\" when performing writes inside change notification callbacks. Previously refreshing the Realm by beginning a write transaction would skip delivering notifications, leaving things in an inconsistent state. Notifications are now delivered recursively when needed instead. ([Cocoa #7165](https://github.com/realm/realm-cocoa/issues/7165)).\n* Fixed name aliasing not working in sort/distinct clauses when doing string-based queries. ([#4550](https://github.com/realm/realm-core/issues/4550), never before working).\n* Potential/unconfirmed fix for crashes associated with failure to memory map (low on memory, low on virtual address space). For example ([#4514](https://github.com/realm/realm-core/issues/4514)).\n* Syncing large Decimal128 values will cause \"Assertion failed: cx.w[1] == 0\" ([#4519](https://github.com/realm/realm-core/issues/4519), since v10.0.0)\n* Classes names \"class_class_...\" were not handled correctly when doing queries ([#4480](https://github.com/realm/realm-core/issues/4480))\n* Fix collection notification reporting for modifications. This could be observed by receiving the wrong indices of modifications on sorted or distinct results, or notification blocks sometimes not being called when only modifications have occurred. ([#4573](https://github.com/realm/realm-core/pull/4573) since v6).\n\n### Compatibility\n* File format: Generates Realms with format v22. Unsynced Realms will be upgraded from Realm Java 2.0 and later. Synced Realms can only be read and upgraded if created with Realm Java v10.0.0-BETA.1.\n* APIs are backwards compatible with all previous release of realm-java in the 10.6.y series.\n* Realm Studio 11.0.0-alpha.0 or above is required to open Realms created by this version.\n\n### Internal\n* Updated to Realm Core 11.0.3, commit de25ad9db783f931e7652d5c1431d5610b2ad67b.\n\n\n## 10.6.0-BETA.2 (2021-06-14)\n\n### Breaking Changes\n* `MapChangeSet.getDeletionsCount()` has been replaced with `MapChangeSet.getDeletions()` that return the keys for entries that has been deleted instead of just the number of deleted entries.\n* Primary keys now have automatic indexes again. Indexes was removed in v10.0.0 because they were not needed, but it caused issues when upgrading from a pre v10 version of Realm, and in some cases resulted in large delays when upgrading the fileformat. (Issue [#7426](https://github.com/realm/realm-java/issues/7426), since 10.0.0).\n\n### Enhancements\n* Allow `insert` and `insertOrUpdate` operations on `RealmObject` or `RealmObject` collections containing `RealmDictionary` or `RealmSet` fields.\n* Added support for `RealmDictionary` in `DynamicRealmObject` with `setDictionary(String fieldName, RealmDictionary<?> dictionary)`, `getDictionary(String fieldName, Class<?> primitiveType)`, and `getDictionary(String fieldName)`.\n* Added support for `RealmSet` in `DynamicRealmObject` with `setRealmSet(String fieldName, RealmSet<?> realmSet)`, `getRealmSet(String fieldName, Class<?> primitiveType)`, and `getRealmSet(String fieldName)`.\n\n### Fixed\n* Removed wrong `@Nullable` annotation on `RealmQuery.maxRealmAny()`.\n* Fixed `RealmAny.getValueClass()` returning the `RealmObject` proxy class instead of the model class on a `RealmAny` referencing a managed `RealmObject`.\n\n### Compatibility\n* File format: Generates Realms with format v22. Unsynced Realms will be upgraded from Realm Java 2.0 and later. Synced Realms can only be read and upgraded if created with Realm Java v10.0.0-BETA.1.\n* APIs are backwards compatible with all previous release of realm-java in the 10.6.y series.\n* Realm Studio 11.0.0-alpha.0 or above is required to open Realms created by this version.\n\n### Internal\n* Updated to Realm Core 11.0.2, commit a30382469eb72c0cf1824b44e7062071c2f3f3a9.\n* Updated to Gradle 6.8.3.\n\n\n## 10.6.0-BETA.1 (2021-05-17)\n\n### Breaking Changes\n* [RealmApp] Sync protocol version increased to 3. This version adds support for the new data types introduced in file format version 21.\n* File format version bumped to 21. In this version we support new basic datatypes `UUID` and `RealmAny`, as well as `RealmSet` and `RealmMap` collections with string-based keys (i.e. `RealmDictionary`).\n* Queries no longer do nullability checks on non-nullable fields, so using `null` as an argument will not throw an `IllegalArgumentException`.\n* String query filters `contains`, `beginsWith`, `endsWith`, and `like`, now throw a null pointer exception on null values.\n* The query builder no longer throw `IllegalStateException` but `IllegalArgumentException`.\n* The `distinct` query filter on unsupported fields no longer throws an exception when applied through when querying across relationships.\n* The `distinct` query filter no longer throws an exception when applied on non-existent fields.\n\n### Enhancements\n* Added support for `java.util.UUID` as supported field in model classes.\n* Added support for `java.util.UUID` as a primary key.\n* Added support for `RealmAny` as supported field in model classes. A `RealmAny` is used to represent a polymorphic Realm value or Realm Object, is indexable but cannot be used as a primary key. See [Javadoc for RealmAny](https://docs.mongodb.com/realm-sdks/java/latest/io/realm/RealmAny.html).\n* Added support for `RealmDictionary` as supported field in model classes. A `RealmDictionary` is a `Map` of strings to values - all types under the `RealmAny` umbrella can be used as values. See [Javadoc for RealmDictionary](https://docs.mongodb.com/realm-sdks/java/latest/io/realm/RealmDictionary.html) and [Javadoc for RealmMap](https://docs.mongodb.com/realm-sdks/java/latest/io/realm/RealmMap.html). `RealmDictionary` is not yet supported by any of the `Realm.insert` and `Realm.createFromJson` methods - This support will be added in a future release.\n* Added support for `RealmSet` as supported field in model classes. A `RealmSet` is a collection that implements the Java `Set` interface and contains no duplicate values - all types under the `RealmAny` umbrella can be used as values. See [Javadoc for RealmSet](https://docs.mongodb.com/realm-sdks/java/latest/io/realm/RealmSet.html). `RealmSet` is not yet supported by any of the `Realm.insert` and `Realm.createFromJson` methods - This support will be added in a future release.\n* Allow UTF8 encoded characters in property names in string-based queries ([#4467](https://github.com/realm/realm-core/issues/4467))\n* The error message when the initial steps of opening a Realm file fails is now more descriptive.\n* Make conversion of Decimal128 to/from string work for numbers with more than 19 significant digits. ([#4548](https://github.com/realm/realm-core/issues/4548))\n* Remove type coercion on bool and ObjectId when doing queries.\n* Allow passing arguments into string-based query predicates.\n* Queries across relationships now support the `between` operator.\n* Queries on numerical fields (byte, short, int, long, float, double, decimal128) now accept any numerical value as an argument.\n* `isEmpty` query filter can now be applied on `RealmList` and `RealmObject` fields.\n\n### Fixed\n* Fix assertion failures such as \"!m_notifier_skip_version.version\" or \"m_notifier_sg->get_version() + 1 == new_version.version\" when performing writes inside change notification callbacks. Previously refreshing the Realm by beginning a write transaction would skip delivering notifications, leaving things in an inconsistent state. Notifications are now delivered recursively when needed instead. ([Cocoa #7165](https://github.com/realm/realm-cocoa/issues/7165)).\n* Fixed name aliasing not working in sort/distinct clauses when doing string-based queries. ([#4550](https://github.com/realm/realm-core/issues/4550), never before working).\n* Potential/unconfirmed fix for crashes associated with failure to memory map (low on memory, low on virtual address space). For example ([#4514](https://github.com/realm/realm-core/issues/4514)).\n* Syncing large Decimal128 values will cause \"Assertion failed: cx.w[1] == 0\" ([#4519](https://github.com/realm/realm-core/issues/4519), since v10.0.0)\n* Classes names \"class_class_...\" were not handled correctly when doing queries ([#4480](https://github.com/realm/realm-core/issues/4480))\n* Fix collection notification reporting for modifications. This could be observed by receiving the wrong indices of modifications on sorted or distinct results, or notification blocks sometimes not being called when only modifications have occurred. ([#4573](https://github.com/realm/realm-core/pull/4573) since v6).\n\n### Compatibility\n* File format: Generates Realms with format v21. Unsynced Realms will be upgraded from Realm Java 2.0 and later. Synced Realms can only be read and upgraded if created with Realm Java v10.0.0-BETA.1.\n* APIs are backwards compatible with all previous release of realm-java in the 10.6.y series.\n* Realm Studio 11.0.0-alpha.0 or above is required to open Realms created by this version.\n\n### Internal\n* Updated to Realm Core 11.0.0-beta.4, commit: d50aef63a8aaf435e3afed82b589b47d8e1ab1ab.\n\n\n## 10.5.1 (2021-06-14)\n\n### Enhancements\n* None.\n\n### Fixes\n* [RealmApp] Errors related to \"uncaught exception in notifier thread: N5realm11KeyNotFoundE: No such object\". This could happen in a sync'd app when a linked object was deleted by another client.\n* [RealmApp] Replacing a referenced embedded object could result in a \"ERROR: ArrayInsert: Invalid\" error. (Issue [#7480](https://github.com/realm/realm-java/issues/7480))\n* Notifications now trigger correctly on Linux kernel 5.5 and above. So far this only impacted the preview emulator image for Android 12. (Issue[#7321](https://github.com/realm/realm-java/issues/7321))\n* Raw query predicates not supporting integer constants above 32 bits on a 32 bit platform.\n\n### Compatibility\n* File format: Generates Realms with format v20. Unsynced Realms will be upgraded from Realm Java 2.0 and later. Synced Realms can only be read and upgraded if created with Realm Java v10.0.0-BETA.1.\n* APIs are backwards compatible with all previous release of realm-java in the 10.x.y series.\n* Realm Studio 10.0.0 or above is required to open Realms created by this version.\n\n### Internal\n* Updated to Realm Core 10.8.1, commit 2a67b996faf9e0b5d47ac402c4d3926713f99418.\n\n\n## 10.5.0 (2021-05-07)\n\n### Breaking Changes\n* [RealmApp] `SyncSession.State.WaitingForAccessToken` has been added. It represents the local access token not longer being valid, but is automatically being refreshed.\n\n### Enhancements\n* We now make a backup of a Realm file prior to any file format upgrade. The backup is retained for 3 months. Backups from before a file format upgrade allows for better analysis of any upgrade failure. We also restore a backup, if a) an attempt is made to open a realm file whith a \"future\" file format and b) a backup file exist that fits the current file format. The backup file is placed next to the real Realm file and is named `<fileName>.v<realmFileFormatVersion>.backup.realm`.\n* The error message when the intial steps of opening a Realm file fails is now more descriptive.\n\n### Fixes\n* [RealmApp] Client Reset errors now correctly forward the server error message. (Issue [#7363](https://github.com/realm/realm-java/issues/7363), since 10.0.0)\n* [RealmApp] All `AppException`s now correctly report the error message through `RuntimeException.getMessage()` instead of only through `AppException.getErrorMessage()`.\n* [RealmApp] Proactively check the expiry time on the access token and refresh it before attempting to initiate a sync session. This prevents some error logs from appearing on the client such as: \"ERROR: Connection[1]: Websocket: Expected HTTP response 101 Switching Protocols, but received: HTTP/1.1 401 Unauthorized\" (RCORE-473, since v10.0.0).\n* Fix name aliasing not working in sort/distinct clauses of raw string predicates.\n* Fix collection notification reporting for modifications. This could be observed by receiving the wrong indices of modifications on sorted or distinct results, or notification sometimes not being called when only modifications have occured. (since v7.0.0).\n* Make conversion of Decimal128 to/from string work for numbers with more than 19 significant digits. (#4548)\n\n### Compatibility\n* File format: Generates Realms with format v20. Unsynced Realms will be upgraded from Realm Java 2.0 and later. Synced Realms can only be read and upgraded if created with Realm Java v10.0.0-BETA.1.\n* APIs are backwards compatible with all previous release of realm-java in the 10.x.y series.\n* Realm Studio 10.0.0 or above is required to open Realms created by this version.\n\n### Internal\n* Updated to Realm Core 10.7.1, commit 5043c25e1d8f5971002e0fec85dea5ea3d7eb3d7.\n\n\n## 10.4.0 (2021-03-26)\n\nAll releases from 10.4.0 and forward are now found on `mavenCentral()` instead of `jcenter()`.\n\nA minimal supported setup will therefore now look like this:\n\n```\nallprojects {\n    buildscript {\n        repositories {\n            mavenCentral()\n        }\n        dependencies {\n            classpath \"io.realm:realm-gradle-plugin:10.4.0\"\n        }\n    }\n\n    repositories {\n        mavenCentral()\n    }\n}\n```\n\n`SNAPSHOT` releases have also been moved from `http://oss.jfrog.org/artifactory/oss-snapshot-local`\nto `https://oss.sonatype.org/content/repositories/snapshots/`. See [here](https://github.com/realm/realm-java/blob/master/README.md#using-snapshots)\nfor more information.\n\n### Enhancements\n* Added support for the string-based Realm Query Language through `RealmQuery.rawPredicate(...)`. This allows many new type of queries not previously supported by the typed query API. See the Javadoc on this method for further details. (Issue [#6116](https://github.com/realm/realm-java/pull/6116))\n* Performance of sorting on more than one property has been improved. Especially important if many elements match on the first property.\n\n### Fixes\n* Calling max/min/sum/avg on a List may give wrong results (Realm Core [#4252](https://github.com/realm/realm-core/issues/4252), since v10.0.0)\n* Fix an issue when using `RealmResults.freeze()` across threads with different transaction versions. Previously, copying the `RealmsResults`' native resource could result in a stale state or objects from a future version. (Realm Core [#4254](https://github.com/realm/realm-core/pull/4254)).\n* On 32-bit devices you may get exception with \"No such object\" when upgrading to v10.* ([#7314](https://github.com/realm/realm-java/issues/7314), since v10.0.0)\n\n### Compatibility\n* File format: Generates Realms with format v20. Unsynced Realms will be upgraded from Realm Java 2.0 and later. Synced Realms can only be read and upgraded if created with Realm Java v10.0.0-BETA.1.\n* APIs are backwards compatible with all previous release of realm-java in the 10.x.y series.\n* Realm Studio 10.0.0 or above is required to open Realms created by this version.\n\n### Internal\n* Updated to Realm Core 10.5.6, commit 92129110dece2cee59839e20be3a7067084a1196.\n* Updated to NDK 22.0.7026061.\n* Updated to ReLinker 1.4.3.\n\n## 10.3.1 (2021-01-28)\n\n### Enhancements\n* None.\n\n### Fixes\n* RxJava Flowables/Observables and Coroutine Flows would crash if they were created from a `RealmList` and the parent object holding the list was deleted. Now, the stream is disposed/closed instead. (Issue [#7242](https://github.com/realm/realm-java/issues/7242))\n* Fixes Realm models default values containing objects with a PK might crash with a `RealmPrimaryKeyConstraintException`. (Issue [#7269] (https://github.com/realm/realm-java/issues/7269))\n\n### Compatibility\n* File format: Generates Realms with format v20. Unsynced Realms will be upgraded from Realm Java 2.0 and later. Synced Realms can only be read and upgraded if created with Realm Java v10.0.0-BETA.1.\n* APIs are backwards compatible with all previous release of realm-java in the 10.x.y series.\n* Realm Studio 10.0.0 or above is required to open Realms created by this version.\n\n### Internal\n* None.\n\n\n## 10.3.0 (2021-01-08)\n\n### Enhancements\n* [RealmApp] Upgraded to OpenSSL 1.1.1g.\n\n### Fixes\n* [RealmApp] Integrating a remote Sync changeset into the local Realm could result in an `Index out of range error`.\n* Change notifications not firing when removing and adding an object with the same primary key within a transaction (Issue [#7098](https://github.com/realm/realm-java/issues/7098)).\n* Race condition which would lead to \"uncaught exception in notifier thread: N5realm15InvalidTableRefE: transaction_ended\" and a crash when the source Realm was closed or invalidated at a very specific time during the first run of a collection notifier (Core issue [#3761](https://github.com/realm/realm-core/issues/3761), since v7.0.0).\n* Deleting and recreating objects with embedded objects could fail (Core issue [#4240](https://github.com/realm/realm-core/pull/4240), since v10.0.0)\n* Added `@Nullable` annotation to input parameter in `RealmObject.isValid(item)` to avoid mismatch warnings from Kotlin code (Issue [#7216](https://github.com/realm/realm-java/issues/7216)).\n\n### Compatibility\n* File format: Generates Realms with format v20. Unsynced Realms will be upgraded from Realm Java 2.0 and later. Synced Realms can only be read and upgraded if created with Realm Java v10.0.0-BETA.1.\n* APIs are backwards compatible with all previous release of realm-java in the 10.x.y series.\n* Realm Studio 10.0.0 or above is required to open Realms created by this version.\n\n### Internal\n* Updated to Realm Core: 10.3.3 (Monorepo).\n* Updated to Realm Core commit: 8af0f8d609491986b49f2c986e771d9dc445664d.\n\n\n## 10.2.0 (2020-12-02)\n\n### Deprecated\n* [RealmApp] `Credentials.google(authenticationCode: String)`. Use `Credentials.google(token: String, authType: GoogleAuthType)` instead.\n\n### Breaking Changes\n* None.\n\n### Enhancements\n* [RealmApp] Added `Credentials.google(token: String, authType: GoogleAuthType)`, as MongoDB Realm now supports multiple ways of logging into Google Accounts.\n\n### Fixes\n* [RealmApp] Bug that would prevent eventual consistency during conflict resolution. Affected clients would experience data divergence and potentially consistency errors as a result if they experienced conflict resolution between cycles of Create-Erase-Create for objects with primary keys.\n* Clean up JNI references to prevent crash from JNI reference table overflow (Issue [#7217](https://github.com/realm/realm-java/issues/7217))\n\n### Compatibility\n* File format: Generates Realms with format v20. Unsynced Realms will be upgraded from Realm Java 2.0 and later. Synced Realms can only be read and upgraded if created with Realm Java v10.0.0-BETA.1.\n* APIs are backwards compatible with all previous release of realm-java in the 10.x.y series.\n* Realm Studio 10.0.0 or above is required to open Realms created by this version.\n\n### Internal\n* Updated to Realm Sync: 10.1.4.\n* Updated to Object Store commit: f838a27402c5b5243280102014defd844420abba66eb93c10334507d9c0fd513.\n\n\n## 10.1.2 (2020-12-02)\n\n### Breaking Changes\n* None.\n\n### Enhancements\n* None.\n\n### Fixes\n* Complementary fix for missed edge case in https://github.com/realm/realm-java/pull/7220 where KAPT crash if we process a RealmObject referencing a type in RealmList defined in another module. (Issue [#7213](https://github.com/realm/realm-java/issues/7213), since v10.0.0).\n\n### Compatibility\n* File format: Generates Realms with format v20. Unsynced Realms will be upgraded from Realm Java 2.0 and later. Synced Realms can only be read and upgraded if created with Realm Java v10.0.0-BETA.1.\n* APIs are backwards compatible with all previous release of realm-java in the 10.x.y series.\n* Realm Studio 10.0.0 or above is required to open Realms created by this version.\n\n\n## 10.1.1 (2020-11-27)\n\n### Breaking Changes\n* None.\n\n### Enhancements\n* None.\n\n### Fixes\n* KAPT crash when processing a RealmObject referenced from another module (changed revealed after we started checking for embedded types). (Issue [#7213](https://github.com/realm/realm-java/issues/7213), since v10.0.0).\n\n### Compatibility\n* File format: Generates Realms with format v20. Unsynced Realms will be upgraded from Realm Java 2.0 and later. Synced Realms can only be read and upgraded if created with Realm Java v10.0.0-BETA.1.\n* APIs are backwards compatible with all previous release of realm-java in the 10.x.y series.\n* Realm Studio 10.0.0 or above is required to open Realms created by this version.\n\n### Internal\n* Updated to Realm Sync: 10.1.3.\n* Updated to Realm Core: 10.1.3.\n* Updated to Object Store commit: fc6daca61133aa9601e4cb34fbeb9ec7569e162e.\n\n\n## 10.1.0 (2020-11-23)\n\n### Breaking Changes\n* None.\n\n### Enhancements\n* Added `FlowFactory` interface that allows customization of `Flow` emissions, just as we do with `RxObservableFactory`. A default implementation, `RealmFlowFactory`, is provided when building `RealmConfiguration`s.\n* Added `toChangeSetFlow` methods (similar to the Rx `asChangesetFlowable` methods) for `RealmObject`, `RealmResults` and `RealmList`.\n\n### Fixes\n* Fixed crash when adding classes containing an `ObjectId` as primary key to the schema. (Issue [#7189](https://github.com/realm/realm-java/issues/7189), since v10.0.0)\n* Fixed crash when creating proxy classes containing an `ObjectId` as primary key. (Issue [#7197](https://github.com/realm/realm-java/issues/7197), since v10.0.0)\n* Fixed crash where calls to `toFlow` could crash if the Flow job is canceled and object updates are emitted after that happens. (Issue [7211](https://github.com/realm/realm-java/issues/7211), since v10.0.1)\n\n### Compatibility\n* File format: Generates Realms with format v20. Unsynced Realms will be upgraded from Realm Java 2.0 and later. Synced Realms can only be read and upgraded if created with Realm Java v10.0.0-BETA.1.\n* APIs are backwards compatible with all previous release of realm-java in the 10.x.y series.\n* Realm Studio 10.0.0 or above is required to open Realms created by this version.\n\n### Internal\n* Updated to Realm Sync: 10.1.3.\n* Updated to Realm Core: 10.1.3.\n* Updated to Object Store commit: fc6daca61133aa9601e4cb34fbeb9ec7569e162e.\n\n\n## 10.0.1 (2020-11-06)\n\n### Breaking Changes\n* None.\n\n### Enhancements\n* Improved the error message for `NoSuchTable` errors. In some cases an outdated native reference was used,but the table was still there. In those cases an `InvalidTableRef` error is now used.\n\n### Fixes\n* [RealmApp] The `SyncConfiguration.Builder.allowQueriesOnUiThread` flag was wrongly initialized to `false` keeping users from running queries from the UI thread when using synced Realms. It now defaults to `true`, allowing queries to be run from the UI. (Issue [#7177](https://github.com/realm/realm-java/issues/7177), since 10.0.0)\n* Crash with `Assertion failed: m_method_id != nullptr with (method_name, signature) =  [\"<init>\", \"(Ljava/lang/String;)V\"]` when `Minify` is enabled. (Issue [#7159](https://github.com/realm/realm-java/pull/7159), since 10.0.0)\n* Fix crash in case insensitive query on indexed string columns when nothing matches (Cocoa issue [#6836](https://github.com/realm/realm-cocoa/issues/6836), since v10.0.0)\n* Fix list of primitives with nullable values where `Lst::is_null(ndx)` always false even on null values, (Core issue [#3987](https://github.com/realm/realm-core/pull/3987), since v10.0.0).\n* Fix queries for the size of a list of primitive nullable ints returning size + 1. (Core issue [#4016](https://github.com/realm/realm-core/pull/4016), since v10.0.0).\n\n### Compatibility\n* File format: Generates Realms with format v20. Unsynced Realms will be upgraded from Realm Java 2.0 and later. Synced Realms can only be read and upgraded if created with Realm Java v10.0.0-BETA.1.\n* APIs are backwards compatible with all previous release of realm-java in the 10.x.y series.\n* Realm Studio 10.0.0 or above is required to open Realms created by this version.\n\n### Internal\n* Updated to Realm Sync: 10.1.0.\n* Updated to Realm Core: 10.1.0.\n* Updated to Object Store commit: fd246c54de7d1fee6bcbeb3609de75a4eccd5b70.\n\n\n## 10.0.0 (2020-10-15)\n\nNOTE: This is a unified release note covering all v10.0.0-BETA.X v10.0.0-RC.X releases.\n\nNOTE: Support for syncing with realm.cloud.io and/or Realm Object Server has been replaced with support for syncing with MongoDB Realm Cloud.\n\nNOTE: This version upgrades the Realm file format to version 20. It is not possible to downgrade to earlier versions than v10.0.0-BETA.7. Non-sync Realms will be upgraded automatically. Synced Realms can only be automatically upgraded if created with Realm Java v10.0.0-BETA.1 and above.\n\n### Breaking Changes\n* [RealmApp] Most APIs for interacting with Realm Cloud have changed significantly. All new APIs can be found in the `io.realm.mongodb` package. The entry point is through the `App` class from which you can create and login users and otherwise interact with MongoDB Realm. See [the docs](https://docs.mongodb.com/realm/android/) for further details. Synced Realms still use a `SyncConfiguration` that are largely created the same way.\n* [RealmApp] Client Resets are now handled through a custom `SyncConfiguration.Builder.clientResetHandler()` instead of through the default session error handler `SyncConfiguration.Builder.errorHandler()`\n* [RealmApp] Realm files have changed location on disk. They are now located in `getFiles()/mongodb-realm`.\n* [RealmApp] All synced model classes not marked as embedded are required to have a primary key named `_id`. It is possible to use `@RealmField(name = \"_id\")` to map from any Java or Kotlin property.\n* From now on it is by default not allowed to run transactions with either `Realm.executeTransaction()` or `DynamicRealm.executeTransaction()` from the UI thread. Doing so will yield a `RealmException`. Users can override this behavior by using `RealmConfiguration.Builder.allowWritesOnUiThread(true)` when building a `RealmConfiguration` to obtain a Realm or DynamicRealm instance, however, we do not recommend doing so. Instead, we recommend using `executeTransactionAsync()` or, alternatively, using non-UI threads when calling `executeTransaction()` for both `Realm`s and `DynamicRealm`s.\n\n### Enhancements\n* Users can now opt out from allowing queries to be launched from the UI thread by using `RealmConfiguration.Builder.allowQueriesOnUiThread(false)`. A `RealmException` will be thrown when calling `RealmQuery.findAll()`, `RealmQuery.findFirst()`, `RealmQuery.minimumDate()`, `RealmQuery.maximumDate()`, `RealmQuery.count()`, `RealmQuery.sum()`, `RealmQuery.max()`, `RealmQuery.min()`, `RealmQuery.average()` and `RealmQuery.averageDecimal128()` from the UI thread after having used `allowQueriesOnUiThread(false)`. Queries will be allowed from the thread from which the Realm instance was obtained as it always has been by default, although we recommend using `RealmQuery.findAllAsync()` or `RealmQuery.findFirstAsync()`, or, alternatively, using a non-UI thread to launch them.\n* `BaseRealm.refresh()` will throw a `RealmException` if it is being called from the UI thread if `allowQueriesOnUiThread` is set to `false`, though it will be allowed by default.\n* Added `DynamicRealm.executeTransactionAsync()`.\n* Added Kotlin extension suspend function `Realm.executeTransactionAwait()` which runs transactions inside coroutines.\n* Added Kotlin extension function `RealmResults.toFlow()` which returns a Kotlin flow, similar to our RxJava convenience method `asFlowable()`.\n* Added Kotlin extension function `RealmList.toFlow()` which returns a Kotlin flow, similar to our RxJava convenience method `asFlowable()`.\n* Added Kotlin extension function `RealmModel.toFlow()` which returns a Kotlin flow, similar to our RxJava convenience method `asFlowable()`.\n* RealmLists can now be marked final. (Issue [#6892](https://github.com/realm/realm-java/issues/6892))\n* Added support for `distinct` queries on non-index and linked fields. (Issue [#1906](https://github.com/realm/realm-java/issues/1906))\n* Added support for `org.bson.types.Decimal128` and `org.bson.types.ObjectId` as supported fields in model classes.\n* Added support for `org.bson.types.ObjectId` as a primary key.\n* Added support for \"Embedded Objects\". They are enabled using `@RealmClass(embedded = true)`. An embedded object must have exactly one parent object linking to it and it will be deleted when the parent is. Embedded objects can also be the parent of other embedded classes. Read more [here](https://docs.mongodb.com/realm/android/embedded-objects/). (Issue [#6713](https://github.com/realm/realm-java/issues/6713))\n\n\n### Fixes\n* None.\n\n### Compatibility\n* File format: Generates Realms with format v20. Unsynced Realms will be upgraded from Realm Java 2.0 and later. Synced Realms can only be read and upgraded if created with Realm Java v10.0.0-BETA.1.\n* APIs are backwards compatible with all previous release of realm-java in the 10.x.y series.\n* Realm Studio 10.0.0 or above is required to open Realms created by this version.\n\n### Internal\n* Updated to Realm Sync: 10.0.0.\n* Updated to Realm Core: 10.0.0.\n\n\n## 10.0.0-RC.2 (2020-10-12)\n\n### Enhancements\n* [RealmApp] Illegal schemas where embedded object classes referenced each other is now correctly detected and throws and exception when opening a Realm with such a schema.\n\n### Fixed\n* [RealmApp] It is now possible to use types different than `ObjectId` for the `_id` field in documents inserted with `MongoCollection.insertOne` and `MongoCollection.insertMany`.\n* [RealmApp] Lossy round trip of Double and Timestamps through functions when using Bson. (ObjectStore issue (#1106)[https://github.com/realm/realm-object-store/issues/1106])\n\n### Compatibility\n* File format: Generates Realms with format v20. Unsynced Realms will be upgraded from Realm Java 2.0 and later. Synced Realms can only be read and upgraded if created with Realm Java 10.0.0-BETA.1.\n* APIs are backwards compatible with all previous release of realm-java in the 10.x.y series.\n* Realm Studio 10.0.0 and above is required to open Realms created by this version.\n\n### Internal\n* Updated to Object Store commit: 6b44209e6fcac0137e193c96444f93c50d184d06.\n\n\n## 10.0.0-RC.1 (2020-10-02)\n\nWe no longer support Realm Cloud (legacy), but instead the new MongoDB Realm Cloud. MongoDB Realm is a serverless platform that enables developers to quickly build applications without having to set up server infrastructure. MongoDB Realm is built on top of MongoDB Atlas, automatically integrating the connection to your database.\n\nThe old Realm Cloud legacy APIs have undergone significant refactoring. The new APIs are all located in the `io.realm.mongodb` package with `io.realm.mongodb.App` as the entry point.\n\n### Breaking Changes\n* From now on it is not allowed by default to run transactions with either `Realm.executeTransaction()` or `DynamicRealm.executeTransaction()` from the UI thread. Doing so will yield a `RealmException`. Users can override this behavior by using `RealmConfiguration.Builder.allowWritesOnUiThread(true)` when building a `RealmConfiguration` to obtain a Realm or DynamicRealm instance, though we do not recommend doing so. Instead, we recommend using `executeTransactionAsync()` or, alternatively, using non-UI threads when calling `executeTransaction()` for both `Realm`s and `DynamicRealm`s.\n\n### Enhancements\n* Users can now opt out from allowing queries to be launched from the UI thread by using `RealmConfiguration.Builder.allowQueriesOnUiThread(false)`. A `RealmException` will be thrown when calling `RealmQuery.findAll()`, `RealmQuery.findFirst()`, `RealmQuery.minimumDate()`, `RealmQuery.maximumDate()`, `RealmQuery.count()`, `RealmQuery.sum()`, `RealmQuery.max()`, `RealmQuery.min()`, `RealmQuery.average()` and `RealmQuery.averageDecimal128()` from the UI thread after having used `allowQueriesOnUiThread(false)`. Queries will be allowed from the thread from which the Realm instance was obtained as it always has been by default, although we recommend using `RealmQuery.findAllAsync()` or `RealmQuery.findFirstAsync()`, or, alternatively, using a non-UI thread to launch them.\n* `BaseRealm.refresh()` will throw a `RealmException` if it is being called from the UI thread if `allowQueriesOnUiThread` is set to `false`, though it will be allowed by default.\n* Added `DynamicRealm.executeTransactionAsync()`.\n* Added Kotlin extension suspend function `Realm.executeTransactionAwait()` which runs transactions inside coroutines.\n* Added Kotlin extension function `RealmResults.toFlow()` which returns a Kotlin flow, similar to our RxJava convenience method `asFlowable()`.\n* Added Kotlin extension function `RealmList.toFlow()` which returns a Kotlin flow, similar to our RxJava convenience method `asFlowable()`.\n* Added Kotlin extension function `RealmModel.toFlow()` which returns a Kotlin flow, similar to our RxJava convenience method `asFlowable()`.\n\n### Fixed\n* Using `Realm.copyToRealmOrUpdate()` and `Realm.insertOrUpdate()` did not correctly update objects if they contained lists of embedded objets. Instead of replacing the original list, list items was appended to the original list. Note, some corner cases are still not supported. See [#7138](https://github.com/realm/realm-java/issues/7138) for more information. (Issue [#7131](https://github.com/realm/realm-java/issues/7131), since 10.0.0-BETA.1).\n\n### Compatibility\n* File format: Generates Realms with format v20. Unsynced Realms will be upgraded from Realm Java 2.0 and later. Synced Realms can only be read and upgraded if created with Realm Java 10.0.0-BETA.1.\n* APIs are backwards compatible with all previous release of realm-java in the 10.x.y series.\n* Realm Studio 10.0.0 and above is required to open Realms created by this version.\n\n### Internal\n* Updated to Object Store commit: ef6736cc07a8b94d1242c522969114bb8047deef\n* Updated to Realm Sync 10.0.0-beta.14.\n* Updated to Realm Core 10.0.0-beta.9.\n\n\n## 10.0.0-BETA.8 (2020-09-23)\n\nWe no longer support Realm Cloud (legacy), but instead the new MongoDB Realm Cloud. MongoDB Realm is a serverless platform that enables developers to quickly build applications without having to set up server infrastructure. MongoDB Realm is built on top of MongoDB Atlas, automatically integrating the connection to your database.\n\nThe old Realm Cloud legacy APIs have undergone significant refactoring. The new APIs are all located in the `io.realm.mongodb` package with `io.realm.mongodb.App` as the entry point.\n\n### Fixed\n* [RealmApp] Logging in caused an `token contains an invalid number of segments` error. (Issue [#7117](https://github.com/realm/realm-java/issues/7117), since 10.0.0-BETA.7)\n* [RealmApp] The order of arguments to `EmailPassword.resetPassword()` was not handled correctly, resulting in resetting the password failing. (Issue [#7116](https://github.com/realm/realm-java/issues/7116), since 10.0.0-BETA.1)\n\n### Compatibility\n* File format: Generates Realms with format v20. Unsynced Realms will be upgraded from Realm Java 2.0 and later. Synced Realms can only be read and upgraded if created with Realm Java 10.0.0-BETA.1.\n* APIs are backwards compatible with all previous release of realm-java in the 10.x.y series.\n* Realm Studio 10.0.0 and above is required to open Realms created by this version.\n\n### Internal\n* Updated to Object Store commit: 035eb07f3ef313bfb78c046be9cf6b4f065d6772.\n\n\n## 10.0.0-BETA.7 (2020-09-16)\n\nWe no longer support Realm Cloud (legacy), but instead the new MongoDB Realm Cloud. MongoDB Realm is a serverless platform that enables developers to quickly build applications without having to set up server infrastructure. MongoDB Realm is built on top of MongoDB Atlas, automatically integrating the connection to your database.\n\nThe old Realm Cloud legacy APIs have undergone significant refactoring. The new APIs are all located in the `io.realm.mongodb` package with `io.realm.mongodb.App` as the entry point.\n\nWARNING: This release upgrades the fileformat to 20. Non-sync Realms will be upgraded automatically. Synced Realms can only be automatically upgraded if created with Realm Java 10.0.0-BETA.1 and above.\n\n\n### Breaking Changes\n* [RealmApp] Moved `User.remove()` to `App.removeUser()`.\n* [RealmApp] Renamed `ApiKeyAuth.createApiKey()` to `ApiKeyAuth.create()` and `ApiKeyAuth.createApiKeyAsync()` to `ApiKeyAuth.createAsync()`.\n* [RealmApp] Renamed `ApiKeyAuth.fetchApiKey()` to `ApiKeyAuth.fetch()` and `ApiKeyAuth.fetchApiKeyAsync()` to `ApiKeyAuth.fetchAsync()`.\n* [RealmApp] Renamed `ApiKeyAuth.fetchAllApiKeys()` to `ApiKeyAuth.fetchAll()` and `ApiKeyAuth.fetchAllApiKeysAsync()` to `ApiKeyAuth.fetchAllAsync()`.\n* [RealmApp] Renamed `ApiKeyAuth.deleteApiKey()` to `ApiKeyAuth.delete()` and `ApiKeyAuth.deleteApiKeyAsync()` to `ApiKeyAuth.deleteAsync()`.\n* [RealmApp] Renamed `ApiKeyAuth.enableApiKey()` to `ApiKeyAuth.enable()` and `ApiKeyAuth.enableApiKeyAsync()` to `ApiKeyAuth.enableAsync()`.\n* [RealmApp] Renamed `ApiKeyAuth.disableApiKey()` to `ApiKeyAuth.disable()` and `ApiKeyAuth.disableApiKeyAsync()` to `ApiKeyAuth.disableAsync()`.\n* [RealmApp] Renamed `User.getApiKeysAuth()` to `User.getApiKeys()`.\n* [RealmApp] Renamed `UserApiKey` class to `ApiKey`.\n* [RealmApp] Removed support for `Credentials.serverApiKey()`.\n* [RealmApp] Renamed `App.getEmailPasswordAuth()` to `App.getEmailPassword()`.\n* [RealmApp] User profile methods `getName()`, `getEmail()`, `getPictureUrl()`, `getFirstName()`, `getLastName()`, `getGender()`, `getBirthday()`, `getMinAge()` and `getMaxAge()` are now available under a new class `UserProfile`. It can be accessed using `User.getProfile()`.\n* [RealmApp] Renamed `Sync.refreshConnections()` to `Sync.reconnect()`.\n* [RealmApp] Renamed `Credentials.IdentityProvider` to `Credentials.Provider`.\n* [RealmApp] Removed support for `User.getLocalId()`.\n* [RealmApp] Client Resets are now handled through a custom `SyncConfiguration.Builder.clientResetHandler()` instead of through the default session error handler `SyncConfiguration.Builder.errorHandler()`\n\n### Enhancements\n* [RealmApp] It is now possible to create App instances with different app id's.\n* [RealmApp] Support for using `null` as a partition value.\n* [RealmApp] Improve errors exception messages from `SyncSession.downloadAllServerChanges()` and `SyncSession.uploadAllLocalChanges()`.\n* [RealmApp] Support for watching MongoCollection change streams (Issue [#6912](https://github.com/realm/realm-java/issues/6912))\n* [RealmApp] Support for retrying a custom confirmation function on an User for a given email (Issue [#7079](https://github.com/realm/realm-java/pull/7079))\n* [RealmApp] Support for getting all app sessions via `Sync.getAllSessions()`.\n* [RealmApp] Support to retrieve the MongoClient service name using `MongoClient.getServiceName()`\n* [RealmApp] Support to retrieve the MongoDatabase name using `MongoDatabase.getName()`\n* [RealmApp] Support to retrieve the MongoCollection name using `MongoCollection.getName()`\n\n### Fixed\n* If you have a realm file growing towards 2Gb and have a table with more than 16 columns, then you may get a \"Key not found\" exception when updating an object. If asserts are enabled at the sdk level, you may get an \"assert(m_has_refs)\" instead. ([#3194](https://github.com/realm/realm-js/issues/3194), since v7.0.0)\n* In cases where you have more than 32 columns in a table, you may get a currrupted file resulting in various crashes ([#7057](https://github.com/realm/realm-java/issues/7057), since v7.0.0)\n\n### Compatibility\n* File format: Generates Realms with format v20. Unsynced Realms will be upgraded from Realm Java 2.0 and later. Synced Realms can only be read and upgraded if created with Realm Java 10.0.0-BETA.1.\n* APIs are backwards compatible with all previous release of realm-java in the 10.x.y series.\n* Realm Studio 10.0.0 and above is required to open Realms created by this version.\n\n### Internal\n* Updated to Object Store commit: 6ab48d3b4b1e0865f68b84d5993bb2aad910320b.\n* Updated to Realm Sync 10.0.0-beta.11.\n* Updated to Realm Core 10.0.0-beta.7.\n\n\n## 10.0.0-BETA.6 (2020-08-17)\n\nWe no longer support Realm Cloud (legacy), but instead the new MongoDB Realm Cloud. MongoDB Realm is a serverless platform that enables developers to quickly build applications without having to set up server infrastructure. MongoDB Realm is built on top of MongoDB Atlas, automatically integrating the connection to your database.\n\nThe old Realm Cloud legacy APIs have undergone significant refactoring. The new APIs are all located in the `io.realm.mongodb` package with `io.realm.mongodb.App` as the entry point.\n\n### Breaking Changes\n* [RealmApp] Realm files have changed location on disk, so Realms should upload all their data to the server before upgrading.\n* [RealmApp] Removed GMS Task framework and added RealmResultTask to provide with a mechanism to operate with asynchronous operations. MongoCollection has been updated to reflect this change.\n\n### Enhancements\n* [RealmApp] Credentials information (e.g. username, password) displayed in Logcat is now obfuscated by default, even if [LogLevel] is set to DEBUG, TRACE or ALL.\n* RealmLists can now be marked final. (Issue [#6892](https://github.com/realm/realm-java/issues/6892))\n* It is now possible to create embedded objects using [DynamicRealm]s. (Issue [#6982](https://github.com/realm/realm-java/pull/6982))\n* Added extra validation and more meaningful error messages when creating embedded objects pointing to the wrong parent property. (See issue above)\n\n### Fixed\n* [RealmApp] The same user opening different Realms with different partion key values would crash with an IllegalArgumentException. (Issue [#6882](https://github.com/realm/realm-java/issues/6882), since 10.0.0-BETA.1)\n* [RealmApp] Sync would not refresh the access token if started with an expired one. (Since 10.0.0-BETA.1)\n* [RealmApp] Leaking objects when registering session listeners. (Issue [#6916](https://github.com/realm/realm-java/issues/6916))\n* Added support for Json-import of objects containing embedded objects. (Issue [#6896](https://github.com/realm/realm-java/issues/6896))\n* Upgrading the file format result did in some cases not work correctly. This could result in a number of crashes, e.g. `FORMAT_UPGRADE_REQUIRED`. (Issue [#6889](https://github.com/realm/realm-java/issues/6889), since 7.0.0)\n* Bug in memory mapping management. This bug could result in multiple different asserts as well as segfaults. In many cases stack backtraces would include members of the EncyptedFileMapping near the top - even if encryption was not used at all. In other cases asserts or crashes would be in methods reading an array header or array element. In all cases the application would terminate immediately. (Realm Core PR [#3838](https://github.com/realm/realm-core/pull/3838), since 7.0.0)\n* It was possible to use `RealmObjectSchema` to mark a Class as embedded even if some of the objects broke the constraints for being embedded.\n\n### Compatibility\n* File format: Generates Realms with format v11 (Reads and upgrades all previous formats from Realm Java 2.0 and later).\n* APIs are backwards compatible with all previous release of realm-java in the 10.x.y series.\n* Realm Studio 10.0.0 and above is required to open Realms created by this version.\n\n### Internal\n* Upgraded to Object Store commit: 5b5fb8a90192cb4ee6799e7465745cd2067f939b.\n* Upgraded to Realm Sync 10.0.0-beta.6.\n* Upgraded to Realm Core 10.0.0-beta.4.\n\n\n## 10.0.0-BETA.5 (2020-06-19)\n\nWe no longer support Realm Cloud (legacy), but instead the new MongoDB Realm Cloud. MongoDB Realm is a serverless platform that enables developers to quickly build applications without having to set up server infrastructure. MongoDB Realm is built on top of MongoDB Atlas, automatically integrating the connection to your database.\n\nThe old Realm Cloud legacy API's have undergone significant refactoring. The new API's are all located in the `io.realm.mongodb` package with `io.realm.mongodb.App` as the entry point.\n\n### Enhancements\n* [RealmApp] Added support for Api Keys, Server Api Keys and Custom Functions as Credential types when logging in.\n* Added support for `distinct` queries on non-index and linked fields. (Issue [#1906](https://github.com/realm/realm-java/issues/1906))\n\n### Fixed\n* None.\n\n### Compatibility\n* File format: Generates Realms with format v11 (Reads and upgrades all previous formats from Realm Java 2.0 and later).\n* APIs are backwards compatible with all previous release of realm-java in the 10.x.y series.\n* Realm Studio 10.0.0 and above is required to open Realms created by this version.\n\n### Internal\n* Upgraded to Object Store commit: e1570f8d3d7cf4d77f049933e6a241a501301383.\n\n## 10.0.0-BETA.4 (2020-06-11)\n\nWe no longer support Realm Cloud (legacy), but instead the new MongoDB Realm Cloud. MongoDB Realm is a serverless platform that enables developers to quickly build applications without having to set up server infrastructure. MongoDB Realm is built on top of MongoDB Atlas, automatically integrating the connection to your database.\n\nThe old Realm Cloud legacy API's have undergone significant refactoring. The new API's are all located in the `io.realm.mongodb` package with `io.realm.mongodb.App` as the entry point.\n\n### Breaking Changes\n* None.\n\n### Enhancements\n* [RealmApp] Added support for Custom Data using `User.customData()` and `User.refreshCustomData()`.\n* [RealmApp] Added support for managing push notifications using `App.getPush()`.\n\n### Fixed\n* [RealmApp] Opening a synced Realm for a cached user with expired access token would crash the app with `Assertion failed: cls with (class_name) = [\"io/realm/internal/objectstore/OsJavaNetworkTransport$Response\"]`. (Issue [#6937](https://github.com/realm/realm-java/issues/6937), since 10.0.0-BETA.1)\n\n### Compatibility\n* File format: Generates Realms with format v11 (Reads and upgrades all previous formats from Realm Java 2.0 and later).\n* APIs are backwards compatible with all previous release of realm-java in the 10.x.y series.\n* Realm Studio 10.0.0 and above is required to open Realms created by this version.\n\n### Internal\n* Updated to Object Store commit: 017d58fbec8a18ab003976b4c346308df88349a6.\n\n\n## 10.0.0-BETA.3 (2020-06-09)\n\nWe no longer support Realm Cloud (legacy), but instead the new MongoDB Realm Cloud. MongoDB Realm is a serverless platform that enables developers to quickly build applications without having to set up server infrastructure. MongoDB Realm is built on top of MongoDB Atlas, automatically integrating the connection to your database.\n\nThe old Realm Cloud legacy API's have undergone significant refactoring. The new API's are all located in the `io.realm.mongodb` package with `io.realm.mongodb.App` as the entry point.\n\n### Breaking Changes\n* None.\n\n### Enhancements\n* None.\n\n### Fixed\n* [RealmApp] When restarting an app, the base URL used would in some cases be incorrect. (Since 10.0.0-BETA.2)\n\n### Compatibility\n* File format: Generates Realms with format v11 (Reads and upgrades all previous formats from Realm Java 2.0 and later).\n* APIs are backwards compatible with all previous release of realm-java in the 10.x.y series.\n* Realm Studio 10.0.0 and above is required to open Realms created by this version.\n\n### Internal\n* Updated to Object Store commit: c02707bc28e1886970c5da29ef481dc0cb6c3dd8.\n\n\n## 10.0.0-BETA.2 (2020-06-08)\n\nWe no longer support Realm Cloud (legacy), but instead the new MongoDB Realm Cloud. MongoDB Realm is a serverless platform that enables developers to quickly build applications without having to set up server infrastructure. MongoDB Realm is built on top of MongoDB Atlas, automatically integrating the connection to your database.\n\nThe old Realm Cloud legacy API's have undergone significant refactoring. The new API's are all located in the `io.realm.mongodb` package with `io.realm.mongodb.App` as the entry point.\n\n### Breaking Changes\n* None.\n\n### Enhancements\n* None.\n\n### Fixed\n* [RealmApp] `AppConfiguration` did not fallback to the correct default baseUrl if none was provided. (Since 10.0.0-BETA.1)\n* [RealmApp] When restarting an app, re-using the already logged in user would result in Sync not resuming. (Since 10.0.0-BETA.1)\n\n### Compatibility\n* File format: Generates Realms with format v11 (Reads and upgrades all previous formats from Realm Java 2.0 and later).\n* APIs are backwards compatible with all previous release of realm-java in the 10.x.y series.\n* Realm Studio 10.0.0 and above is required to open Realms created by this version.\n\n### Internal\n* Updated to Object Store commit: c50be4dd178ef7e11d453f61a5ac2afa8c1c10bf.\n* Updated to Realm Sync 10.0.0-beta.2.\n\n\n## 10.0.0-BETA.1 (2020-06-05)\n\nWe no longer support Realm Cloud (legacy), but instead the new MongoDB Realm Cloud. MongoDB Realm is a serverless platform that enables developers to quickly build applications without having to set up server infrastructure. MongoDB Realm is built on top of MongoDB Atlas, automatically integrating the connection to your database.\n\nThe old Realm Cloud legacy API's have undergone significant refactoring. The new API's are all located in the `io.realm.mongodb` package with `io.realm.mongodb.App` as the entry point.\n\n### Breaking Changes\n* [RealmApp] Removed all references and API's releated to permissions. These are now managed through MongoDB Realm.\n* [RealmApp] Query Based Sync API's and Subscriptions. These API's are not initially supported by MongoDB Realm. They will be re-introduced in a future release. `SyncConfiguration.partitionKey()` has been added as a replacement.\n* [RealmApp] Removed support for Client Resync. These API's are not initially supported by MongoDB Realm. They will be re-introduced in a future release.\n* [RealmApp] Removed suppport for custom SSL certificates. These API's are not initially supported by MongoDB Realm. They will be re-introduced in a future release.\n* [RealmApp] Destructive updates of a schema of a synced Realm will now consistently throw an `UnsupportedOperationException` instead of some methods throwing `IllegalArgumentException`. The affected methods are `RealmSchema.remove(String)`, `RealmSchema.rename(String, String)`, `RealmObjectSchema.setClassName(String)`, `RealmObjectSchema.removeField(String)`, `RealmObjectSchema.renameField(String, String)`, `RealmObjectSchema.removeIndex(String)`, `RealmObjectSchema.removePrimaryKey()`, `RealmObjectSchema.addPrimaryKey(String)` and `RealmObjectSchema.addField(String, Class<?>, FieldAttribute)`\n\n### Enhancements\n* Added support for `org.bson.types.Decimal128` and `org.bson.types.ObjectId` as supported fields in model classes.\n* Added support for `org.bson.types.ObjectId` as a primary key.\n* Added support for \"Embedded Objects\". They are enabled using `@RealmClass(embedded = true)`. An embedded object must have exactly one parent object linking to it and it will be deleted when the the parent is. Embedded objects can also be the parent of other embedded classes. Read more [here](https://realm.io/docs/java/latest/#embedded-objects). (Issue [#6713](https://github.com/realm/realm-java/issues/6713))\n\n### Fixed\n* After upgrading a Realm file, you may at some point receive a 'NoSuchTable' exception. (Issue [Core#3701](https://github.com/realm/realm-core/issues/3701), since 7.0.0)\n* If the Realm file upgrade process was interrupted/killed for various reasons, the following run would some assertions failing. (Issue [#6866](https://github.com/realm/realm-java/issues/6866), since 7.0.0).\n\n### Compatibility\n* File format: Generates Realms with format v11 (Reads and upgrades all previous formats from Realm Java 2.0 and later).\n* APIs are backwards compatible with all previous release of realm-java in the 10.x.y series.\n* Realm Studio 10.0.0 and above is required to open Realms created by this version.\n\n### Internal\n* Updated to Object Store commit: 6d081a53377514f9b77736cb03051a03d829da922.\n* Updated to Realm Sync 10.0.0-beta.1.\n* Updated to Realm Core 10.0.0-beta.1.\n* OKHttp was upgraded to 3.12.0 from 3.10.0.\n* Updated Android Gradle Plugin to 3.6.1.\n* Updated Gradle to 5.6.4\n* Updated Dokka to 0.10.1\n* Updated Android Build Tools to 29.0.2.\n* Updated compileSdkVersion to 29.\n\n\n## 7.0.8 (2020-10-01)\n\n### Enhancements\n* Slightly improve performance of most operations which read data from the Realm file.\n\n### Fixes\n* Making a query in an indexed property may give a \"Key not found\" exception. (.NET issue [#2025](https://github.com/realm/realm-dotnet/issues/2025), since 7.0.0)\n* Queries for null on non-nullable indexed integer properties could return wrong results if 0 entries should be found. (Since 7.0.0)\n* Rerunning an equals query on an indexed string column which previously had more than one match and now has one match would sometimes throw a \"key not found\" exception. (Cocoa issue [#6536](https://github.com/realm/realm-cocoa/issues/6536), Since 7.0.0)\n\n### Compatibility\n* Realm Object Server: 3.23.1 or later.\n* File format: Generates Realms with format v11 (Reads and upgrades all previous formats from Realm Java 2.0 and later).\n* APIs are backwards compatible with all previous release of realm-java in the 7.x.y series.\n\n### Internal\n* Upgraded to Object Store commit: 8a68df3e9fa7743c13d927eb7fc330ed9bb06693.\n* Upgraded to Realm Sync: 5.0.28.\n* Upgraded to Realm Core: 6.1.3.\n\n\n## 7.0.7 (2020-09-25)\n\n### Enhancements\n* None.\n\n### Fixes\n* When querying a class where object references are part of the condition, the application may crash if objects have recently been added to the target table. (Issue [#7118](https://github.com/realm/realm-java/issues/7118), since v7.0.0)\n\n### Compatibility\n* Realm Object Server: 3.23.1 or later.\n* File format: Generates Realms with format v11 (Reads and upgrades all previous formats from Realm Java 2.0 and later).\n* APIs are backwards compatible with all previous release of realm-java in the 7.x.y series.\n\n### Internal\n* Upgraded to Object Store commit: 37e86c2905bfd424c16fc5d7860a1298bfc0ffa2.\n* Upgraded to Realm Sync: 5.0.25.\n* Upgraded to Realm Core: 6.1.1.\n\n\n## 7.0.6 (2020-09-18)\n\n### Enhancements\n* Better exception messaging for UTF encoding errors. ([Issue #7093](https://github.com/realm/realm-java/pull/7093))\n\n### Fixes\n* Fixes concurrent modification exceptions in the schema when refreshing a Realm (Issue [#6876](https://github.com/realm/realm-java/issues/6876))\n* If you use encryption your application cound crash with a message like \"Opening Realm files of format version 0 is not supported by this version of Realm\". ([#6889](https://github.com/realm/realm-java/issues/6889) among others, since v7.0.0)\n\n### Compatibility\n* Realm Object Server: 3.23.1 or later.\n* Realm Studio: 5.0.0 or later.\n* File format: Generates Realms with format v11 (Reads and upgrades all previous formats from Realm Java 2.0 and later).\n* APIs are backwards compatible with all previous release of realm-java in the 7.x.y series.\n\n### Internal\n* Upgraded to Object Store commit: e29b5515df8b8adfe2454424b78878bb63879307.\n* Upgraded to Realm Sync: 5.0.23.\n* Upgraded to Realm Core: 6.0.26.\n\n\n## 7.0.5 (2020-09-09)\n\n### Enhancements\n* None.\n\n### Fixes\n* If you have a Realm file growing towards 2Gb and have a model class with more than 16 properties, then you may get a \"Key not found\" exception when updating an object. (Realm JS issue [#3194](https://github.com/realm/realm-js/issues/3194), since v7.0.0)\n* In cases where you have more than 32 properties in a model class, you may get a currrupted file resulting in various crashes (Issue [#7057](https://github.com/realm/realm-java/issues/7057), since v7.0.0)\n\n### Compatibility\n* Realm Object Server: 3.23.1 or later.\n* Realm Studio: 5.0.0 or later.\n* File format: Generates Realms with format v11 (Reads and upgrades all previous formats from Realm Java 2.0 and later).\n* APIs are backwards compatible with all previous release of realm-java in the 7.x.y series.\n\n### Internal\n* Upgraded to Realm Sync: 5.0.22.\n* Upgraded to Realm Core: 6.0.25.\n\n\n## 7.0.4 (2020-09-08)\n\nNote: Fileformat has been bumped from 10 to 11. This means that downgrading to an earlier version of Realm is not possible and Realm Studio 5.0.0 must be used to view Realm files.\n\n### Enhancements\n* None.\n\n### Fixes\n* In some cases a frozen Realm of the wrong version could be returned. ([ObjectStore issue #1078](https://github.com/realm/realm-object-store/pull/1078))\n* Upgrading files with string primary keys would result in a file where it was not possible to find the objects by primary key. ([Core issue #3893](https://github.com/realm/realm-core/pull/3893), since 7.0.0)\n* NullPointerException when calling `toString` on RealmObjects with a binary field containing `null`. (Issue [#7084](https://github.com/realm/realm-java/issues/7084), since 7.0.0)\n\n### Compatibility\n* Realm Object Server: 3.23.1 or later.\n* Realm Studio: 5.0.0 or later.\n* File format: Generates Realms with format v11 (Reads and upgrades all previous formats from Realm Java 2.0 and later).\n* APIs are backwards compatible with all previous release of realm-java in the 7.x.y series.\n\n### Internal\n* Upgraded to Object Store commit: 286d7cb2f10c41f89a2efb43b22938610ccad4cf.\n* Upgraded to Realm Sync: 5.0.21.\n* Upgraded to Realm Core: 6.0.24.\n\n## 7.0.3 (2020-09-01)\n\n### Enhancements\n* Added `Realm.getNumberOfActiveVersions()`, which returns the current number of active versions maintained by the Realm file.\n\n### Fixes\n* Creating a query inside a change listener could in some cases result in the version being pinned, which would either drastically increase filesize or cause `RealmConfiguration.maxNumberOfActiveVersions()` to trigger. (Issue [#6977](https://github.com/realm/realm-java/issues/6977), since 7.0.0)\n* If you upgrade a Realm file where you have \"\" elements in a list of non-nullable strings, the upgrade would crash.\n* If an attempt to upgrade a Realm file has ended with a crash with \"migrate_links\" in the call stack, the Realm ended in a corrupt state where further upgrade was not possible. A remedy for this situation is now provided.\n\n### Compatibility\n* Realm Object Server: 3.23.1 or later.\n* Realm Studio: 4.0.0 or later.\n* File format: Generates Realms with format v10 (Reads and upgrades all previous formats from Realm Java 2.0 and later).\n* APIs are backwards compatible with all previous release of realm-java in the 7.x.y series.\n\n### Internal\n* Upgraded to Object Store commit: eef80f42e6ede2294eb60f048228012d9b7bc627.\n* Upgraded to Realm Sync: 5.0.19.\n* Upgraded to Realm Core: 6.0.22.\n* The upgrade logic for upgrading fileformats has changed so that progress is now recorded explicitly in a table. This makes the logic simpler and reduces the chance of errors. It will also make it easier to detect if a file has only been partially upgraded.\n\n\n## 7.0.2 (2020-08-14)\n\n### Enhancements\n* None.\n\n### Fixes\n* [ObjectServer] Calling `SyncManager.refreshConnections()` did not correctly refresh connections in all cases, which could delay reconnects up to 5 minutes. (Issue [#7003](https://github.com/realm/realm-java/issues/7003))\n* Upgrading the file format result did in some cases not work correctly. This could result in a number of crashes, e.g. `FORMAT_UPGRADE_REQUIRED`. (Issue [#6889](https://github.com/realm/realm-java/issues/6889), since 7.0.0)\n* Bug in memory mapping management. This bug could result in multiple different asserts as well as segfaults. In many cases stack backtraces would include members of the EncyptedFileMapping near the top - even if encryption was not used at all. In other cases asserts or crashes would be in methods reading an array header or array element. In all cases the application would terminate immediately. (Issue [#3838](https://github.com/realm/realm-core/pull/3838), since 7.0.0)\n* Crash when retrieving `null` valued primitive fields from dynamic realm. (Issue [#7025](https://github.com/realm/realm-java/issues/7025))\n\n### Compatibility\n* Realm Object Server: 3.23.1 or later.\n* Realm Studio: 4.0.0 or later.\n* File format: Generates Realms with format v10 (Reads and upgrades all previous formats from Realm Java 2.0 and later).\n* APIs are backwards compatible with all previous release of realm-java in the 7.x.y series.\n\n### Internal\n* Upgraded to Realm Sync 5.0.15.\n* Upgraded to Realm Core 6.0.17.\n\n\n## 7.0.1 (2020-07-01)\n\n### Enhancements\n* None.\n\n### Fixes\n* Upgrading older Realm files with String indexes was very slow. (Issue [#6875](https://github.com/realm/realm-java/issues/6875), since 7.0.0)\n* Aborting upgrading a Realm file could result in the file getting corrupted. (Isse [#6866](https://github.com/realm/realm-java/issues/6866), since 7.0.0)\n* Automatic indexes on primary keys are now correctly stripped when upgrading the file as they are no longer needed. (Since 7.0.0)\n* `NoSuchTable` was thrown after comitting a transaction. (Issue [#6947](https://github.com/realm/realm-java/issues/6947))\n\n### Compatibility\n* Realm Object Server: 3.23.1 or later.\n* Realm Studio: 4.0.0 or later.\n* File format: Generates Realms with format v10 (Reads and upgrades all previous formats from Realm Java 2.0 and later).\n* APIs are backwards compatible with all previous release of realm-java in the 7.x.y series.\n\n### Internal\n* Upgraded to Realm Sync 5.0.7.\n* Upgraded to Realm Core 6.0.8.\n\n\n## 7.0.0 (2020-05-16)\n\nNOTE: This version bumps the Realm file format to version 10. Files created with previous versions of Realm will be automatically upgraded. It is not possible to downgrade to version 9 or earlier. Only [Studio 3.11](https://github.com/realm/realm-studio/releases/tag/v3.11.0) or later will be able to open the new file format.\nNOTE: This version bumps the Realm file format to version 10. Files created with previous versions of Realm will be automatically upgraded. It is not possible to downgrade to version 9 or earlier. Only [Realm Studio 4](https://github.com/realm/realm-studio/releases/tag/v4.0.0) or later will be able to open the new file format.\n\n### Breaking Changes\n* [ObjectServer] Removed deprecated method `SyncConfiguration.Builder.partialRealm()`. Use `SyncConfiguration.Builder.fullSynchronization()` instead.\n* [ObjectServer] Removed deprecated methods `SyncConfiguration.automatic()` and `SyncConfiguration.automatic(User, Uri)`. Use `SyncUser.getDefaultConfiguration()` and `SyncUser.createConfiguration(Url)`.\n* [ObjectServer] Removed deprecated method `ErrorCode.fromInt(int)`.\n* [ObjectServer] Removed deprecated method `SyncCredentials.nickname(name)` and `SyncCredentials.nickname(name, isAdmin)`. Use `SyncCredentials.usernamePassword(username, password)` instead.\n* [ObjectServer] Deprecated state `SyncSession.State.ERROR` has been removed. Use `SyncConfiguration.Builder.errorHandler(ErrorHandler)` instead.\n* [ObjectServer] `IncompatibleSyncedFileException` is removed as it is no longer used.\n* [ObjectServer] New error codes thrown by the underlying sync layers now have proper enum mappings in `ErrorCode.java`. A few other errors have been renamed in order to have consistent naming. (Issue [#6387](https://github.com/realm/realm-java/issues/6387))\n* RxJava Flowables and Observables are now subscribed to and unsubscribed to asynchronously on the thread holding the live Realm, instead of previously where this was done synchronously.\n* All RxJava Flowables and Observables now return frozen objects instead of live objects. This can be configured using `RealmConfiguration.Builder.rxFactory(new RealmObservableFactory(true|false))`. By using frozen objects, it is possible to send RealmObjects across threads, which means that all RxJava operators should now be supported without the need to copy Realm data into unmanaged objects.\n* MIPS is not supported anymore.\n* Realm now requires `minSdkVersion` 16. Up from 9.\n* [ObjectServer] `IncompatibleSyncedFileException` is removed and no longer thrown.\n\n### Enhancements\n* Added `Realm.freeze()`, `RealmObject.freeze()`, `RealmResults.freeze()` and `RealmList.freeze()`. These methods will return a frozen version of the current Realm data. This data can be read from any thread without throwing an `IllegalStateException`, but will never change. All frozen Realms and data can be closed by calling `Realm.close()` on the frozen Realm, but fully closing all live Realms will also close the frozen ones. Frozen data can be queried as normal, but trying to mutate it in any way will throw an `IllegalStateException`. This includes all methods that attempt to refresh or add change listeners. (Issue [#6590](https://github.com/realm/realm-java/pull/6590))\n* Added `Realm.isFrozen()`, `RealmObject.isFrozen()`, `RealmObject.isFrozen(RealmModel)`, `RealmResults.isFrozen()` and `RealmList.isFrozen()`, which returns whether or not the data is frozen.\n* Added `RealmConfiguration.Builder.maxNumberOfActiveVersions(long number)`. Setting this will cause Realm to throw an `IllegalStateException` if too many versions of the Realm data are live at the same time. Having too many versions can dramatically increase the filesize of the Realm.\n* Storing large binary blobs in Realm files no longer forces the file to be at least 8x the size of the largest blob.\n* Reduce the size of transaction logs stored inside the Realm file, reducing file size growth from large transactions.\n* `RealmResults.asJSON()` is no longer `@Beta`\n* The default `toString()` for proxy objects now print the length of binary fields. (Issue [#6767](https://github.com/realm/realm-java/pull/6767))\n\n### Fixes\n* If a DynamicRealm and Realm was opened for the same file they would share transaction state by accident. The implication was that writes to a `Realm` would immediately show up in the `DynamicRealm`. This has been fixed, so now it is required to call `refresh()` on the other Realm or wait for normal change listeners to detect the change.\n\n### Compatibility\n* Realm Object Server: 3.23.1 or later.\n* Realm Studio: 4.0.0 or later.\n* File format: Generates Realms with format v10 (Reads and upgrades all previous formats from Realm Java 2.0 and later).\n* APIs are backwards compatible with all previous release of realm-java in the 7.x.y series.\n\n### Internal\n* `OsSharedRealm.VersionID.hashCode()` was not implemented correctly and included the memory location in the hashcode.\n* OKHttp was upgraded to 3.10.0 from 3.9.0.\n* The NDK has been upgraded from r10e to r21.\n* The compiler used for C++ code has changed from GCC to Clang.\n* OpenSSL used by Realms encryption layer has been upgraded from 1.0.2k to 1.1.1b.\n* Updated to Object Store commit: 820b74e2378f111991877d43068a95d2b7a2e404.\n* Updated to Realm Sync 5.0.3.\n* Updated to Realm Core 6.0.4.\n\n### Credits\n* Thanks to @joxon for better support for binary fields in proxy objects.\n\n\n## 6.1.0(2020-01-17)\n\n### Fixed\n* None.\n\n### Compatibility\n* Realm Object Server: 3.23.1 or later.\n* File format: Generates Realms with format v9 (Reads and upgrades all previous formats)\n* APIs are backwards compatible with all previous release of realm-java in the 6.x.y series.\n\n### Internal\n* None.\n\n\n\n## 6.1.0(2020-01-17)\n\n### Enhancements\n* The Realm Gradle plugin now applies `kapt` when used in Kotlin Multiplatform projects. Note, Realm Java still only works for the Android part of a Kotlin Multiplatform project. (Issue [#6653](https://github.com/realm/realm-java/issues/6653))\n* The error message shown when no native code could be found for the device is now much more descriptive. This is particular helpful if an app is using App Bundle or APK Split and the resulting APK was side-loaded outside the Google Play Store. (Issue [#6673](https://github.com/realm/realm-java/issues/6673))\n* `RealmResults.asJson()` now encode binary data as Base64 and null object links are reported as `null` instead of `[]`.\n\n### Fixed\n* Fixed using `RealmList` with a primitive type sometimes crashing with `Destruction of mutex in use`. (Issue [#6689](https://github.com/realm/realm-java/issues/6689))\n* `RealmObjectSchema.transform()` would crash if one of the `DynamicRealmObject` provided are deleted from the Realm. (Issue [#6657](https://github.com/realm/realm-java/issues/6657), since 0.86.0)\n* The Realm Transformer will no longer attempt to send anonymous metrics when Gradle is invoked with `--offline`. (Issue [#6691](https://github.com/realm/realm-java/issues/6691))\n\n### Compatibility\n* Realm Object Server: 3.23.1 or later.\n* File format: Generates Realms with format v9 (Reads and upgrades all previous formats)\n* APIs are backwards compatible with all previous release of realm-java in the 6.x.y series.\n\n### Internal\n* Updated to ReLinker 1.4.0.\n* Updated to Object Store commit: 2a204063e1e1a366efbdd909fbea9effceb7d3c4.\n* Updated to Realm Sync 4.9.4.\n* Updated to Realm Core 5.23.8.\n\n### Credits\n* Thanks to @sellmair (Sebastian Sellmair) for improving Kotlin Multiplatform support.\n\n\n## 6.0.2(2019-11-21)\n\n### Enhancements\n* None.\n\n### Fixed\n* [ObjectServer] `SyncSession` progress listeners now work correctly in combination with `SyncConfiguration.waitForInitialRemoteData()`.\n* The `@RealmModule` annotation would be stripped on an empty class when using R8 resulting in apps crashing on startup with `io.realm.DefaultRealmModule is not a RealmModule. Add @RealmModule to the class definition.`. ([#6449](https://github.com/realm/realm-java/issues/6449))\n\n### Compatibility\n* Realm Object Server: 3.23.1 or later.\n* File format: Generates Realms with format v9 (Reads and upgrades all previous formats)\n* APIs are backwards compatible with all previous release of realm-java in the 6.x.y series.\n\n### Internal\n* Updated to Object Store commit: ad96a4c334b475dd67d50c1ca419e257d7a21e18.\n* Updated to Realm Sync v4.8.3.\n\n## 6.0.1(2019-11-11)\n\nNOTE: Anyone using encrypted Realms are strongly advised to upgrade to this version.\n\n### Enhancements\n* None\n\n### Fixed\n* When using encrypted Realms a race condition could lead to the Realm ending up corrupted when the file increased in size. This could manifest as a wide array of different error messages. Most commonly seen has been \"Fatal signal 11 (SIGSEGV) from Java_io_realm_internal_UncheckedRow_nativeGetString\", \"RealmFileException: Top ref outside file\" and \"Unable to open a realm at path. ACCESS_ERROR: Invalid mnemonic\". ([#6152](https://github.com/realm/realm-java/issues/6152), since 5.0.0)\n* `RealmResults.asJSON()` now prints lists with primitive values directly instead of wrapping each value in an object with an `!ARRAY_VALUE` property.\n\n### Compatibility\n* Realm Object Server: 3.23.1 or later.\n* File format: Generates Realms with format v9 (Reads and upgrades all previous formats)\n* APIs are backwards compatible with all previous release of realm-java in the 6.x.y series.\n\n### Internal\n* Updated to Realm Sync 4.7.12.\n* Updated to Realm Core 5.23.6.\n\n### Credits\n* Thanks to Vladimir Konkov (@vladimirfx) for help with isolating ([#6152](https://github.com/realm/realm-java/issues/6152)).\n\n\n## 6.0.0(2019-10-01)\n\n### Breaking Changes\n* [ObjectServer] The `PermissionManager` is no longer backed by Realms but instead a REST API. This means that the `PermissionManager` class has been removed and all methods have been moved to `SyncUser`. Some method names have been renamed slightly and return values for methods have changed from `RealmResults<Permission>` to `List<Permission>`. This should only have an impact if change listeners were used to listen for changes. In these cases, you must now manually retry the request.\n\n### Enhancements\nNone.\n\n### Fixed\nNone.\n\n### Compatibility\n* Realm Object Server: 3.23.1 or later.\n* File format: Generates Realms with format v9 (Reads and upgrades all previous formats)\n* APIs are backwards compatible with all previous release of realm-java in the 6.x.y series.\n\n### Internal\n* [ObjectServer] The OKHttp client will now follow redirects from the Realm Object Server.\n\n\n## 5.15.2(2019-09-30)\n\n### Enhancements\n* None.\n\n### Fixed\n* `null` values were not printed correctly when using `RealmResults.asJSON()` (Realm Core Issue [#3399](https://github.com/realm/realm-core/pull/3399))\n* [ObjectServer] Queries with nullable `Date`'s did not serialize correctly. Only relevant if using Query-based Synchronization. (Realm Core issue [#3388](https://github.com/realm/realm-core/pull/3388))\n* [ObjectServer] Fixed crash with `java.lang.IllegalStateException: The following changes cannot be made in additive-only schema mode` when opening an old Realm created between Realm Java 5.10.0 and Realm Java 5.13.0. (Issue [#6619](https://github.com/realm/realm-java/issues/6619), since 5.13.0).\n\n### Compatibility\n* Realm Object Server: 3.21.0 or later.\n* File format: Generates Realms with format v9 (Reads and upgrades all previous formats)\n* APIs are backwards compatible with all previous release of realm-java in the 5.x.y series.\n\n### Internal\n* Updated to Object Store commit: 8416010e4be5e32ba552ff3fb29e500f3102d3db.\n* Updated to Realm Sync 4.7.8.\n* Updated to Realm Core 5.23.5.\n* Updated Docker image used on CI to Node 10.\n\n\n## 5.15.1(2019-09-09)\n\n### Enhancements\n* None.\n\n### Fixed\n* Projects with `flatDirs` repositories defined crashed the build with `MissingPropertyException`. (Issue [#6610](https://github.com/realm/realm-java/issues/6610), since 5.15.0).\n\n### Compatibility\n* Realm Object Server: 3.21.0 or later.\n* File format: Generates Realms with format v9 (Reads and upgrades all previous formats)\n* APIs are backwards compatible with all previous release of realm-java in the 5.x.y series.\n\n### Internal\n* None.\n\n## 5.15.0(2019-09-05)\n\n### Enhancements\n* [ObjectServer] Added support for Client Resync for fully synchronized Realms which automatically will recover the local Realm in case the server is rolled back. This largely replaces the Client Reset mechanism. Can be configured using `SyncConfiguration.Builder.clientResyncMode()`. (Issue [#6487](https://github.com/realm/realm-java/issues/6487))\n\n### Fixed\n* Huawei devices reporting `Permission denied` when opening a Realm file after an app upgrade or factory reset. This does not automatically fix already existing Realm files. See [this FAQ entry](https://realm.io/docs/java/latest/#huawei-permission-denied) for more details. (Issue [#5715](https://github.com/realm/realm-java/issues/5715))\n* `Realm.copyToRealm()` and `Realm.insertOrUpdate()` crashed on model classes if `@LinkingObjects` was used to target a field with a re-defined internal name in the parent class (e.g. by using `@RealmField`). (Issue [#6581](https://github.com/realm/realm-java/issues/6581))\n\n### Compatibility\n* Realm Object Server: 3.21.0 or later.\n* File format: Generates Realms with format v9 (Reads and upgrades all previous formats)\n* APIs are backwards compatible with all previous release of realm-java in the 5.x.y series.\n\n### Internal\n* Implemented direct access to sync workers on Cloud, bypassing the Sync Proxy: the binding will override the sync session's url prefix if the token refresh response for a realm contains a sync worker path field.\n* Updated to Object Store commit: 9f19d79fde248ba37cef0bd52fe64984f9d71be0.\n* Updated to Realm Sync 4.7.4.\n* Updated to Realm Core 5.23.2.\n\n\n## 5.14.0(2019-08-12)\n\n### Deprecated\n* [ObjectServer] `SyncCredentials.nickname()` has been deprecated in favour of `SyncCredentials.usernamePassword()`.\n* [ObjectServer] `SyncCredentials.IdentityProvider.NICKNAME` has been deprecated in favour of `SyncCredentials.IdentityProvider.USERNAME_PASSWORD`.\n\n### Enhancements\n* None.\n\n### Fixed\n* None.\n\n### Compatibility\n* Realm Object Server: 3.21.0 or later.\n* File format: Generates Realms with format v9 (Reads and upgrades all previous formats)\n* APIs are backwards compatible with all previous release of realm-java in the 5.x.y series.\n\n### Internal\n* None.\n\n\n## 5.13.1(2019-08-05)\n\n### Enhancements\n* None.\n\n### Fixed\n* [ObjectServer] The C++ networking layer now correctly uses any system defined proxy the same way the Java networking layer does. (Issue [#6574](https://github.com/realm/realm-java/pull/6574)).\n* The Realm bytecode transformer now works correctly with Android Gradle Plugin 3.6.0-alpha01 and beyond. (Issue [#6531](https://github.com/realm/realm-java/issues/6531)).\n* Queries on RealmLists with objects containing indexed integers could return the wrong result. (Issue [#6522](https://github.com/realm/realm-java/issues/6522), since 5.11.0)\n\n### Compatibility\n* Realm Object Server: 3.21.0 or later.\n* File format: Generates Realms with format v9 (Reads and upgrades all previous formats)\n* APIs are backwards compatible with all previous release of realm-java in the 5.x.y series.\n\n### Internal\n* Updated JavaAssist in the Realm Transformer to 3.25.0-GA.\n* Updated to Realm Core 5.23.1.\n* Updated to Realm Sync 4.7.1.\n* Updated to Object Store commit: bcc6a7524e52071bfcd35cf740f506e0cc6a595e\n\n\n## 5.13.0(2019-07-23)\n\n### Enhancements\n* [ObjectServer] Added support for faster initial synchronization for fully synchronized Realms. (Issue [#6469](https://github.com/realm/realm-java/issues/6469))\n* [ObjectServer] Improved session lifecycle debug output. (Issue [#6552](https://github.com/realm/realm-java/pull/6552)).\n\n### Fixed\n* None.\n\n### Compatibility\n* Realm Object Server: 3.21.0 or later.\n* File format: Generates Realms with format v9 (Reads and upgrades all previous formats)\n* APIs are backwards compatible with all previous release of realm-java in the 5.x.y series.\n\n### Internal\n* Updated to Realm Core 5.22.0.\n* Updated to Realm Sync 4.6.1.\n* Updated to Object Store commit f0d75261fc8d332c20dc82f643dd795c0f4c7aec\n\n\n## 5.12.0(2019-06-20)\n\n### Enhancements\n* [ObjectServer] Added `SyncManager.refreshConnections()` that can be used to manually trigger a reconnect for all sessions. This is useful if the device has been offline for a long time or fail to detect that it regained connectivity. (Issue [#259](https://github.com/realm/realm-java-private/issues/259))\n* Added `RealmResults.asJson()` in `@Beta` that returns the result of the query as a JSON payload (#6540).\n\n### Fixed\n* [ObjectServer] `PermissionManager` stopped working if an intermittent network error was reported. (Issue [#6492](https://github.com/realm/realm-java/issues/6492), since 3.7.0)\n* The Kotlin extensions library no longer defines a `app_name`, which in some cases conflicted with the `app_name` defined by applications. (Issue [#6536](https://github.com/realm/realm-java/issues/6536), since 4.3.0)\n\n### Compatibility\n* Realm Object Server: 3.21.0 or later.\n* File format: Generates Realms with format v9 (Reads and upgrades all previous formats)\n* APIs are backwards compatible with all previous release of realm-java in the 5.x.y series.\n\n### Internal\n* Updated to Realm Core 5.22.0.\n* Updated to Realm Sync 4.6.1.\n* Updated to Object Store commit 7c3ff8235579550a3e3c6060c47140b2005174f5\n\n## 5.11.0(2019-05-01)\n\nNOTE: This version is only compatible with Realm Object Server 3.21.0 or later.\n\n### Enhancements\n* [ObjectServer] Added `RealmQuery.includeLinkingObjects()`. This is only relevant for Query-based Realms and tells subscriptions to include objects linked through `@LinkingObjects` fields as part of the subscription as well. Objects referenced through objects and lists are always included as a default. (Issue [#6426](https://github.com/realm/realm-java/issues/6426))\n* Encryption now uses hardware optimized functions, which significantly improves the performance of encrypted Realms. ([Realm Core PR #3241](https://github.com/realm/realm-core/pull/3241))\n* Improved query performance when using `RealmQuery.in()` queries. ([Realm Core PR #3250](https://github.com/realm/realm-core/pull/3250)).\n* Improved query performance when querying Integer fields with indexes, e.g. primary key fields. ([Realm Core PR #3272](https://github.com/realm/realm-core/pull/3272)).\n* Improved write performance when writing changes to disk ([Realm Core PR #2927](https://github.com/realm/realm-sync/issues/2927))\n* Added support for incremental annotation processing added in Gradle 4.7. (Issue [#5906](https://github.com/realm/realm-java/issues/5906)).\n\n### Fixed\n* [ObjectServer] Fix an error in the calculation of the `downloadableBytes` value sent by `ProgressListeners`.\n* [ObjectServer] HTTP requests made by the Sync client now always include a Host: header, as required by HTTP/1.1, although its value will be empty if no value is specified by the application.\n* [ObjectServer] The server no longer rejects subscriptions based on queries with distinct and/or limit clauses.\n* [ObjectServer] If a user had `canCreate` but not `canUpdate` privileges on a class, the user would be able to create the object, but not actually set any meaningful values on that object, despite the rule that objects created within the same transaction can always be modified.\n*  Native crash happening if bulk updating a field in a `RealmResult` would cause the object to no longer be part of the query result. (Issue [#6478](https://github.com/realm/realm-java/issues/6478), since 5.8.0).\n\n### Compatibility\n* Realm Object Server: 3.21.0 or later.\n* File format: Generates Realms with format v9 (Reads and upgrades all previous formats)\n* APIs are backwards compatible with all previous release of realm-java in the 5.x.y series.\n\n### Internal\n* Updated to Realm Core 5.19.1.\n* Updated to Relm Sync 4.4.2.\n* Updated to Object Store commit e4b1314d21b521fd604af7f1aacf3ca94272c19a\n\n\n## 5.10.0(2019-03-22)\n\n### Enhancements\n* [ObjectServer] Added 4 new fields to query-based Subscriptions: `createdAt`, `updatedAt`, `expiresAt` and `timeToLive`. These make it possible to better reason about and control current subscriptions. (Issue [#6453](https://github.com/realm/realm-java/issues/6453))\n* [ObjectServer] Added the option of updating the query controlled by a Subscription using either `RealmQuery.findAllAsync(String name, boolean update)`,  `RealmQuery.subscribe(String name, boolean update)` or `Subscription.setQuery(RealmQuery query)`. (Issue [#6453](https://github.com/realm/realm-java/issues/6453))\n* [ObjectServer] Added the option of setting a time-to-live for subscriptions. Setting this will automatically delete the subscription after the provided TTL has expired and the subscription hasn't been used. (Issue [#6453](https://github.com/realm/realm-java/issues/6453))\n\n### Fixed\n* Dates returned from the Realm file no longer overflow or underflow if they exceed `Long.MAX_VALUE` or `Long.MIN_VALUE` but instead clamp to their respective value. (Issue [#2722](https://github.com/realm/realm-java/issues/2722))\n\n### Compatibility\n* Realm Object Server: 3.11.0 or later.\n* File format: Generates Realms with format v9 (Reads and upgrades all previous formats).\n* APIs are backwards compatible with all previous release of realm-java in the 5.x.y series.\n\n### Internal\n* Updated to Object Store commit: e9819ed9c77ed87b5d7bed416a76cd5bcf255802\n\n\n## 5.9.1(2019-02-21)\n\n### Enhancements\n* None\n\n### Fixed\n* [ObjectServer] Reporting too many errors from the native layer resulted in a native crash with `local reference table overflow`. (Issue [#249](https://github.com/realm/realm-java-private/issues/249), since 5.9.0)\n\n### Compatibility\n* Realm Object Server: 3.11.0 or later.\n* File format: Generates Realms with format v9 (Reads and upgrades all previous formats)\n* APIs are backwards compatible with all previous release of realm-java in the 5.x.y series.\n\n### Internal\n* None\n\n## 5.9.0(2019-01-15)\n\n### Enhancements\n* [ObjectServer] Added `ObjectServerError.getErrorType()` and `ObjectServerError.getErrorType()` which returns the underlying native error information. This is especially relevant if `ObjectServerError.getErrorCode()` returns `UNKNOWN`. [#6364](https://github.com/realm/realm-java/issues/6364)\n* Added better checks for detecting corrupted files, both before and after the file is written to disk.\n\n### Fixed\n* [ObjectServer] Native errors sometimes mapped to the wrong Java ErrorCode. (Issue [#6364](https://github.com/realm/realm-java/issues/6364), since 2.0.0)\n* [ObjectServer] Query-based Sync queries involving LIMIT, limited the result before permissions were evaluated. This could sometimes result in the wrong number of elements being returned.\n* Removed Java 8 bytecode. Resulted in errors like `D8: Invoke-customs are only supported starting with Android O (--min-api 26)` if not compiled with Java 8. (Issue [#6300](https://github.com/realm/realm-java/issues/6300), since 5.8.0).\n\n### Compatibility\n* Realm Object Server: 3.11.0 or later.\n* File format: Generates Realms with format v9 (Reads and upgrades all previous formats)\n* APIs are backwards compatible with all previous release of realm-java in the 5.x.y series.\n\n### Internal\n* Updated to Object Store commit: f964c2640f635e76839559cb703732e9e906ba4c\n* Updated Realm Sync to 3.14.13\n* Updated Realm Core to 5.12.7\n\n\n## 5.8.0 (2018-11-06)\n\nThis release also contains all changes from 5.8.0-BETA1 and 5.8.0-BETA2.\n\n### Enhancements\n* [ObjectServer] Added Subscription class available to Query-based Realms. This exposes a Subscription more directly. This class is in beta. [#6231](https://github.com/realm/realm-java/pull/6231).\n  * [ObjectServer] Added `Realm.getSubscriptions()`, `Realm.getSubscriptions(String pattern)` and `Realm.getSubscription` to make it easier to find existing subscriptions. These API's are in beta. [#6231](https://github.com/realm/realm-java/pull/6231)\n  * [ObjectServer] Added `RealmQuery.subscribe()` and `RealmQuery.subscribe(String name)` to subscribe immediately inside a transaction. These API's are in beta. [#6231](https://github.com/realm/realm-java/pull/6231)\n  * [ObjectServer] Added support for subscribing directly inside `SyncConfiguration.initialData()`. This can be coupled with `SyncConfiguration.waitForInitialRemoteData()` in order to block a Realm from opening until the initial subscriptions are ready and have downloaded data. This API are in beta. [#6231](https://github.com/realm/realm-java/pull/6231)\n* [ObjectServer] Improved performance when merging changes from the server.\n* [ObjectServer] Added support for timeouts when uploading or downloading data manually using `SyncSession.downloadAllServerChanges(long timeout, TimeUnit unit)` and `SyncSession.uploadAllLocalChanges(long timeout, TimeUnit unit)`. [#6073](https://github.com/realm/realm-java/pull/6073)\n* [ObjectServer] Added support for timing out when downloading initial data for synchronized Realms using `SyncConfiguration.waitForInitialRemoteData(long timeout, TimeUnit unit)`. [#6247](https://github.com/realm/realm-java/issues/6247)\n* [ObjectServer] Added `Realm.init(Context, String)` which defines a custom User-Agent String sent to the Realm Object Server when a session is created. Using this requires Realm Object Server 3.12.4 or later. [#6267](https://github.com/realm/realm-java/issues/6267)\n* Added support for `ImportFlag`s to `Realm.copyToRealm()` and `Realm.copyToRealmOrUpdate()`. This makes it possible to choose a mode so only fields that actually changed are written to disk. This improves notifications and Object Server performance. [#6224](https://github.com/realm/realm-java/pull/6224)\n* Added support for bulk updating the same property in all objects that are part of a query result using `RealmResults.setValue(String fieldName, Object value)` or one of the specialized overrides that have been added for all supported types, e.g. `RealmResults.setString(String fieldName, String value)`. [#762](https://github.com/realm/realm-java/issues/762)\n\n### Fixed\n* All known bugs introduced in 5.8.0-BETA1 and 5.8.0-BETA2. See the release notes for these releases.\n\n### Compatibility\n* Realm Object Server: 3.11.0 or later.\n* File format: Generates Realms with format v9 (Reads and upgrades all previous formats)\n* APIs are backwards compatible with all previous release of realm-java in the 5.x.y series.\n\n### Internal\n* Updated to Object Store commit: f0dfe6c03be49194bc40777901059eaf55e7bff6\n* Updated Realm Sync to 3.13.1\n* Updated Realm Core to 5.12.0\n\n\n## 5.8.0-BETA2 (2018-10-19)\n\n### Enhancements\n* None\n\n### Fixed\n* `RealmResults` listeners not triggering the initial callback for Query-based Realm when the device is offline [#6235](https://github.com/realm/realm-java/issues/6235).\n\n### Known Bugs\n* `Realm.copyToRealm()` and `Realm.copyToRealmOrUpdate` has been rewritten to support import flags. It is currently ~30% slower than in 5.7.0.\n* IllegalStateException thrown when trying to create an object with a primary key that already exists when using `Realm.copyToRealm`, will always report \"null\" instead of the correct primary key value.\n* When using `ImportFlag.DO_NOT_SET_SAME_VALUES`, lists will still be written and reported as changed, even if they didn't change.\n\n### Compatibility\n* Realm Object Server: 3.11.0 or later.\n* File format: Generates Realms with format v9 (Reads and upgrades all previous formats)\n* APIs are backwards compatible with all previous release of realm-java in the 5.x.y series.\n\n### Internal\n* None\n\n\n## 5.8.0-BETA1 (2018-10-11)\n\n### Enhancements\n* Added new `ImportFlag` class that is used to specify additional behaviour when importing\n  data into Realm [#6224](https://github.com/realm/realm-java/pull/6224).\n* Added support for `ImportFlag` to `Realm.copyToRealm()` and `Realm.copyToRealmOrUpdate()` [#6224](https://github.com/realm/realm-java/pull/6224).\n\n### Fixed\n* None\n\n### Known Bugs\n* `Realm.copyToRealm()` and `Realm.copyToRealmOrUpdate` has been rewritten to support import flags. It is currently ~30% slower than in 5.7.0.\n* IllegalStateException thrown when trying to create an object with a primary key that already exists when using `Realm.copyToRealm`, will always report \"null\" instead of the correct primary key value.\n* When using `ImportFlag.DO_NOT_SET_SAME_VALUES`, lists will still be written and reported as changed, even if they didn't change.\n\n### Compatibility\n* Realm Object Server: 3.11.0 or later.\n* File format: Generates Realms with format v9 (Reads and upgrades all previous formats)\n* APIs are backwards compatible with all previous release of realm-java in the 5.x.y series.\n\n\n## 5.7.1 (2018-10-22)\n\n### Enhancements\n* None\n\n### Fixed\n* [ObjectServer] `RealmResults` listeners not triggering the initial callback for Query-based Realm when the device is offline. (Issue [#6235](https://github.com/realm/realm-java/issues/6235), since 5.0.0).\n\n### Compatibility\n* Realm Object Server: 3.11.0 or later.\n* File format: Generates Realms with format v9 (Reads and upgrades all previous formats)\n* APIs are backwards compatible with all previous release of realm-java in the 5.x.y series.\n\n### Internal\n* Updated to Object Store commit: 362b886628b3aefc5b7a0bc32293d794dc1d4ad5\n\n\n## 5.7.0 (2018-09-24)\n\n### Enhancements\n* [ObjectServer] Devices will now report download progress for read-only Realms which\n  will allow the server to compact files sooner, saving server space. This does not affect\n  the client. You will need to upgrade your Realm Object Server to at least version 3.11.0\n  or use [Realm Cloud](https://cloud.realm.io). If you try to connect to a ROS v3.10.x or\n  previous, you will see an error like `Wrong protocol version in Sync HTTP request,\n  client protocol version = 25, server protocol version = 24`.\n\n### Fixed\n* None\n\n### Compatibility\n* Realm Object Server: 3.11.0 or later.\n* File format: Generates Realms with format v9 (Reads and upgrades all previous formats)\n* APIs are backwards compatible with all previous release of realm-java in the 5.x.y series.\n\n### Internal\n* Sync Protocol version increased to 25.\n* Updated Realm Sync to 3.10.1\n* Updated Realm Core to 5.10.2\n\n\n## 5.6.0 (2018-09-24)\n\n### Enhancements\n* [ObjectServer] Added `RealmPermissions.findOrCreate(String roleName)` and\n  `ClassPermissions.findOrCreate(String roleName)` ([#6168](https://github.com/realm/realm-java/issues/6168)).\n* `@RealmClass(\"name\")` and `@RealmField(\"name\")` can now be used as a shorthand for defining custom\n  name mappings ([#6145](https://github.com/realm/realm-java/issues/6145)).\n* Added support for `RealmQuery.limit(long limit)` ([#544](https://github.com/realm/realm-java/issues/544)).\n  When building a `RealmQuery`, `sort()`, `distinct()` and `limit()` will now be applied in the order\n  they are called. Before this release, `sort()`  and `distinct()` could be called any order, but\n  `sort()` would always be applied before `distinct()`.\n* Building with Android App Bundle is now supported ([#5977](https://github.com/realm/realm-java/issues/5977)).\n\n### Fixed\n* None\n\n### Compatibility\n* Realm Object Server: 3.11.0 or later.\n* File format: Generates Realms with format v9 (Reads and upgrades all previous formats)\n* APIs are backwards compatible with all previous release of realm-java in the 5.x.y series.\n\n### Internal\n* Updated ReLinker to 1.3.0.\n* Updated to Object Store commit: 7e19c51af72c3343b453b8a13c82dfda148e4bbc\n\n\n## 5.5.0 (2018-08-31)\n\n### Enhancements\n* [ObjectServer] Added `ConnectionState` enum describing the states a connection can be in.\n* [ObjectServer] Added `SyncSession.isConnected()` and `SyncSession.getConnectionState()`.\n* [ObjectServer] Added support for observing connection changes for a session using `SyncSession.addConnectionChangeListener()` and `SyncSession.removeConnectionChangeListener()`.\n* [ObjectServer] Added Kotlin extension property `Realm.syncSession` for synchronized Realms.\n* [ObjectServer] Added Kotlin extension method `Realm.classPermissions<RealmModel>()`.\n* [ObjectServer] Added support for starting and stopping synchronization using `SyncSession.start()` and `SyncSession.stop()` (#6135).\n* [ObjectServer] Added API's for making it easier to work with network proxies (#6163):\n  * `SyncManager.setAuthorizationHeaderName(String headerName)`\n  * `SyncManager.setAuthorizationHeaderName(String headerName, String host)`\n  * `SyncManager.addCustomRequestHeader(String headerName, String headerValue)`\n  * `SyncManager.addCustomRequestHeader(String headerName, String headerValue, String host)`\n  * `SyncManager.addCustomRequestHeaders(Map<String, String> headers)`\n  * `SyncManager.addCustomRequestHeaders(Map<String, String> headers, String host)`\n  * `SyncConfiguration.Builder.urlPrefix(String prefix)`\n\n### Fixed\n* Methods and classes requiring synchronized Realms have been removed from the standard AAR package. They are now only visible when enabling synchronized Realms in Gradle. The methods and classes will still be visible in the source files and docs, but annotated with `@ObjectServer` (#5799).\n\n### Internal\n* Updated to Realm Sync 3.9.4\n* Updated to Realm Core 5.8.0\n* Updated to Object Store commit: b0fc2814d9e6061ce5ba1da887aab6cfba4755ca\n\n### Credits\n* Thanks to @lucasdornelasv for improving the performance of `Realm.copyToRealm()`, `Realm.copyToRealmOrUpdate()` and `Realm.copyFromRealm()` #(6124).\n\n\n## 5.4.3 (YYYY-MM-DD)\n\n### Bug Fixes\n\n* [ObjectServer] ProGuard was not configured correctly when working with Subscriptions for Query-based Realms.\n\n\n## 5.4.2 (2018-08-09)\n\n### Bug Fixes\n\n* [ObjectServer] Fixed bugs in the Sync Client that could lead to memory corruption and crashes.\n\n### Internal\n\n* Upgraded to Realm Sync 3.8.8\n\n\n## 5.4.1 (2018-08-03)\n\n### Bug Fixes\n\n* Compile time crash if no `targetSdk` was defined in Gradle. This was introduced in 5.4.0 (#6082).\n* Fix Realm Gradle Plugin adding dependencies in a way incompatible with Kotlin Android Extensions. This was introduced in Realm Java 5.4.0 (#6080).\n\n\n## 5.4.0 (2018-07-22)\n\n### Enhancements\n\n* Removing a ChangeListener on invalid objects or `RealmResults` should warn instead of throwing (fixes #5855).\n\n### Bug Fixes\n\n* [ObjectServer] Using Android Network Security Configuration is necessary to install the custom root CA for tests (API >= 24) (#5970).\n* Fixes issue with the incremental build causing direct access to model without accessor to fail (#6056).\n* `RealmQuery.distinct()` is now correctly applied when calling `RealmQuery.count()` (#5958).\n\n### Internal\n\n* Upgraded to Realm Core 5.7.2\n* Upgraded to Realm Sync 3.8.1\n* [ObjectServer] Improved performance when integrating changes from the server.\n* Added extra information about the state of the Realm file if an exception is thrown due to Realm not being able to open it.\n* Removed internal dependency on Groovy in the Realm Transformer (#3971).\n\n### Credits\n\n* Thanks to @kageiit for removing Groovy from the Realm Transformer (#3971).\n\n\n## 5.3.1 (2018-06-19)\n\n### Bug Fixes\n\n* [ObjectServer] Fixed a bug which could potentially flood Realm Object Server with PING messages.\n* Calling `Realm.deleteAll()` on a Realm file that contains more classes than in the schema throws exception (#5745).\n* `Realm.isEmpty()` returning false in some cases, even if all tables part of the schema are empty (#5745).\n* Fixed rare native crash materializing as `Assertion failed: ref + size <= after_ref with (ref, size, after_ref, ndx, m_free_positions.size())` (#5300).\n\n### Internal\n\n* Upgraded to Realm Core 5.6.2\n* Upgraded to Realm Sync 3.5.6\n* Upgraded to Object Store commit `0bcb9643b8fb14323df697999b79c4a5341a8a21`\n\n\n## 5.3.0 (2018-06-12)\n\n### Enhancements\n\n* [ObjectServer] `Realm.compactRealm(config)` now works on synchronized Realms (#5937).\n* [ObjectServer] `SyncConfiguration.compactOnLaunch()` and `SyncConfiguration.compactOnLaunch(callback)` has been added (#5937).\n* Added `RealmQuery.getRealm()`, `RealmResults.getRealm()`, `RealmList.getRealm()` and `OrderedRealmCollectionSnapshot.getRealm()` (#5997).\n* Removing a ChangeListener on invalid objects or `RealmResults` should warn instead of throwing (fixes #5855).\n\n\n### Internal\n\n* Upgraded to Realm Core 5.6.0\n* Upgraded to Realm Sync 3.5.2\n\n\n## 5.2.0 (2018-06-06)\n\nThe feature previously named Partial Sync is now called Query-Based Sync and is now the default mode when synchronizing Realms.\nThis has impacted a number of API's. See below for the details.\n\n### Deprecated\n\n* [ObjectServer] `SyncConfiguration.automatic()` has been deprecated in favour of `SyncUser.getDefaultConfiguration()`.\n* [ObjectServer] `new SyncConfiguration.Builder(user, url)` has been deprecated in favour of `SyncUser.createConfiguration(url)`. NOTE: Creating configurations using `SyncUser` will default to using query-based Realms, while creating them using `new SyncConfiguration.Builder(user, url)` will default to fully synchronized Realms.\n* [ObjectServer] With query-based sync being the default `SyncConfiguration.Builder.partialRealm()` has been deprecated. Use `SyncConfiguration.Builder.fullSynchronization()` if you want full synchronisation instead.\n\n### Enhancements\n\n* [ObjectServer] Added `SyncUser.createConfiguration(url)`. Realms created this way are query-based Realms by default.\n* [ObjectServer] Added `SyncUser.getDefaultConfiguration()`.\n* The Realm bytecode transformer now supports incremental builds (#3034).\n* Improved speed and allocations when parsing field descriptions in queries (#5547).\n\n### Bug Fixes\n\n* Having files that ends with `RealmProxy` will no longer break the Realm Transformer (#3709).\n\n### Internal\n\n* Module mediator classes being generated now produces a stable output enabling better support for incremental builds (#3034).\n\n\n## 5.1.0 (2018-04-25)\n\n### Enhancements\n\n* [ObjectServer] Added support for `SyncUser.requestPasswordReset()`, `SyncUser.completePasswordReset()`\n  and their async variants. This makes it possible to reset the password for users created using\n  `Credentials.usernamePassword()` where they used their email as username (#5821).\n* [ObjectServer] Added support for `SyncUser.requestEmailConfirmation()`, `SyncUser.confirmEmail()`\n  and their async variants. This makes it possible to ask users to confirm their email. This is only\n  supported for users created using `Credentials.usernamePassword()` who have used an email as their\n  username (#5821).\n* `RealmQuery.in()` now support `null` which will always return no matches (#4011).\n* Added support for `RealmQuery.alwaysTrue()` and `RealmQuery.alwaysFalse()`.\n\n### Bug Fixes\n\n* Changing a primary key from being nullable to being required could result in objects being deleted (##5899).\n\n\n## 5.0.1 (2018-04-09)\n\n### Enhancements\n\n* [ObjectServer] `SyncConfiguration.automatic()` will make use of the host port to work out the default Realm URL.\n* [ObjectServer] A role is now automatically created for each user with that user as its only member. This simplifies the common use case of restricting access to specific objects to a single user. This role can be accessed at `PermissionUser.getRole()`.\n* [ObjectServer] Expose `Role.getMembers()` to access the list of associated `UserPermission`.\n\n### Bug Fixes\n\n* `RealmList.move()` did not move items correctly for unmanaged lists (#5860).\n* `RealmObject.isValid()` not correctly returns `false` if `null` is provided as an argument (#5865).\n* `RealmQuery.findFirst()` and `RealmQuery.findFirstAsync()` not working correctly with sorting (#5714).\n* Permission `noPrivileges` and `allPrivileges` were returning opposite privileges.\n* Fixes an issue caused by JNI local table reference overflow (#5880).\n\n### Internal\n\n* Upgraded to Realm Sync 3.0.1\n* Upgraded to Realm Core 5.4.2\n\n## 5.0.0 (2018-03-15)\n\nThis release is compatible with the Realm Object Server 3.0.0-beta.3 or later.\n\n### Known Bugs\n\n* API's marked @ObjectServer are shipped as part of the base binary, they should only be available when enabling synchronized Realms.\n\n### Breaking Changes\n\n* [ObjectServer] Renamed `SyncUser.currentUser()` to `SyncUser.current()`.\n* [ObjectServer] Renamed `SyncUser.login(...)` and `SyncUser.loginAsync(...)` to `SyncUser.logIn(...)` and `SyncUser.logInAsync(...)`.\n* [ObjectServer] Renamed `SyncUser.logout()` to `SyncUser.logOut()`.\n* The `OrderedCollectionChangeSet` parameter in `OrderedRealmCollectionChangeListener.onChange()` is no longer nullable. Use `changeSet.getState()` instead (#5619).\n* `realm.subscribeForObjects()` have been removed. Use `RealmQuery.findAllAsync(String subscriptionName)` and `RealmQuery.findAllAsync()` instead.\n* Removed previously deprecated `RealmQuery.findAllSorted()`, `RealmQuery.findAllSortedAsync()` `RealmQuery.distinct()` and `RealmQuery.distinctAsync()`.\n* Renamed `RealmQuery.distinctValues()` to `RealmQuery.distinct()`\n\n### Enhancements\n\n* [ObjectServer] Added support for partial Realms. Read [here](https://realm.io/docs/java/latest/#partial-realms) for more information.\n* [ObjectServer] Added support for Object Level Permissions (requires partial synchronized Realms). Read [here](https://realm.io/docs/java/latest/#partial-realms) for more information.\n* [ObjectServer] Added `SyncConfiguration.automatic()` and `SyncConfiguration.automatic(SyncUser user)` (#5806).\n* Added two new methods to `OrderedCollectionChangeSet`: `getState()` and `getError()` (#5619).\n\n## Bug Fixes\n\n* Better exception message if a non model class is provided to methods only accepting those (#5779).\n\n### Internal\n\n* Upgraded to Realm Sync 3.0.0\n* Upgraded to Realm Core 5.3.0\n\n\n## 4.4.0 (2018-03-13)\n\n### Enhancements\n\n* Added support for mapping between a Java name and the underlying name in the Realm file using `@RealmModule`, `@RealmClass` and `@RealmField` annotations (#5280).\n\n## Bug Fixes\n\n* [ObjectServer] Fixed an issue where login after a logout will not resume Syncing (https://github.com/realm/my-first-realm-app/issues/22).\n\n\n## 4.3.4 (2018-02-06)\n\n## Bug Fixes\n\n* Added missing `RealmQuery.oneOf()` for Kotlin that accepts non-nullable types (#5717).\n* [ObjectServer] Fixed an issue preventing sync to resume when the network is back (#5677).\n\n## 4.3.3 (2018-01-19)\n\n### Internal\n\n* Downgrade JavaAssist to 3.21.0-GA to fix an issue with a `ClassNotFoundException` at runtime (#5641).\n\n\n## 4.3.2 (2018-01-17)\n\n### Bug Fixes\n\n* Throws a better exception message when calling `RealmObjectSchema.addField()` with a `RealmModel` class (#3388).\n* Use https for Realm version checker (#4043).\n* Prevent Realms Gradle plugin from transitively forcing specific versions of Google Build Tools onto downstream projects (#5640).\n* [ObjectServer] logging a warning message instead of throwing an exception, when sync report an unknown error code (#5403).\n\n### Enhancements\n\n* [ObjectServer] added support for both Anonymous and Nickname authentication.\n\n\n### Internal\n\n* Upgraded to Realm Sync 2.2.9\n* Upgraded to Realm Core 5.1.2\n\n## 4.3.1 (2017-12-06)\n\n### Bug Fixes\n\n* Fixed kotlin standard library being added to both Java and Kotlin projects (#5587).\n\n\n## 4.3.0 (2017-12-05)\n\n### Deprecated\n\n* Support for mips devices are deprecated.\n* `RealmQuery.findAllSorted()` and `RealmQuery.findAllSortedAsync()` variants in favor of predicate `RealmQuery.sort().findAll()`.\n* `RealmQuery.distinct()` and `RealmQuery.distinctAsync()` variants in favor of predicate `RealmQuery.distinctValues().findAll()`\n\n### Enhancements\n\n* [ObjectServer] Added explicit support for JSON Web Tokens (JWT) using `SyncCredentials.jwt(String token)`. It requires Object Server 2.0.23+ (#5580).\n* Projects using Kotlin now include additional extension functions that make working with Kotlin easier. See [docs](https://realm.io/docs/java/latest/#kotlin) for more info (#4684).\n* New query predicate: `sort()`.\n* New query predicate: `distinctValues()`. Will be renamed to `distinct` in next major version.\n* The Realm annotation processor now has a stable output when there are no changes to model classes, improving support for incremental compilers (#5567).\n\n### Bug Fixes\n\n* Added missing `toString()` for the implementation of `OrderedCollectionChangeSet`.\n* Sync queries are evaluated immediately to solve the performance issue when the query results are huge, `RealmResults.size()` takes too long time (#5387).\n* Correctly close the Realm instance if an exception was thrown while opening it. This avoids `IllegalStateException` when deleting the Realm in the catch block (#5570).\n* Fixed the listener on `RealmList` not being called when removing the listener then adding it again (#5507). Please notice that a similar issue still exists for `RealmResults`.\n\n### Internal\n\n* Use `OsList` instead of `OsResults` to add notification token on for `RealmList<RealmModel>`.\n* Updated Gradle and plugins to support Android Studio `3.0.0` (#5472).\n* Upgraded to Realm Sync 2.1.8.\n* Upgraded to Realm Core 4.0.4.\n\n### Credits\n\n* Thanks to @tbsandee for fixing a typo (#5548).\n* Thanks to @vivekkiran for updating Gradle and plugins to support Android Studio `3.0.0` (#5472).\n* Thanks to @madisp for adding better support for incremental compilers (#5567).\n\n\n## 4.2.0 (2017-11-17)\n\n### Enhancements\n\n* Added support for using non-encrypted Realms in multiple processes. Some caveats apply. Read [doc](https://realm.io/docs/java/latest/#multiprocess) for more info (#1091).\n* Added support for importing primitive lists from JSON (#5362).\n* [ObjectServer] Support SSL validation using Android TrustManager (no need to specify `trustedRootCA` in `SynConfiguration` if the certificate is installed on the device), fixes (#4759).\n* Added the and() function to `RealmQuery` in order to improve readability.\n\n### Bug Fixes\n\n* Leaked file handler in the Realm Transformer (#5521).\n* Potential fix for \"RealmError: Incompatible lock file\" crash (#2459).\n\n### Internal\n\n* Updated JavaAssist to 3.22.0-GA.\n* Upgraded to Realm Sync 2.1.4.\n* Upgraded to Realm Core 4.0.3.\n\n### Credits\n\n* Thanks to @rakshithravi1997 for adding `RealmQuery.and()` (#5520).\n\n\n## 4.1.1 (2017-10-27)\n\n### Bug Fixes\n\n* Fixed the compile warnings of using deprecated method `RealmProxyMediator.getTableName()` in generated mediator classes (#5455).\n* [ObjectServer] now retrying network query when encountering any `IOException` (#5453).\n* Fixed a `NoClassDefFoundError` due to using `@SafeVarargs` below API 19 (#5463).\n\n### Internal\n\n* Updated Realm Sync to 2.1.0.\n\n\n## 4.1.0 (2017-10-20)\n\n### Enhancements\n\n* `Realm.deleteRealm()` and `RealmConfiguration.assetFile()` are multi-processes safe now.\n\n### Bug Fixes\n\n* Fix some potential database corruption caused by deleting the Realm file while a Realm instance are still opened in another process or the sync client thread.\n* Added `realm.ignoreKotlinNullability` as a kapt argument to disable treating kotlin non-null types as `@Required` (#5412) (introduced in `v3.6.0`).\n* Increased http connect/write timeout for low bandwidth network.\n\n\n## 4.0.0 (2017-10-16)\n\n### Breaking Changes\n\nThe internal file format has been upgraded. Opening an older Realm will upgrade the file automatically, but older versions of Realm will no longer be able to read the file.\n\n* [ObjectServer] Updated protocol version to 22 which is only compatible with Realm Object Server >= 2.0.0.\n* [ObjectServer] Removed deprecated APIs `SyncUser.retrieveUser()` and `SyncUser.retrieveUserAsync()`. Use `SyncUser.retrieveInfoForUser()` and `retrieveInfoForUserAsync()` instead.\n* [ObjectServer] `SyncUser.Callback` now accepts a generic parameter indicating type of object returned when `onSuccess` is called.\n* [ObjectServer] Renamed `SyncUser.getAccessToken` to `SyncUser.getRefreshToken`.\n* [ObjectServer] Removed deprecated API `SyncUser.getManagementRealm()`.\n* Calling `distinct()` on a sorted `RealmResults` no longer clears any sorting defined (#3503).\n* Relaxed upper bound of type parameter of `RealmList`, `RealmQuery`, `RealmResults`, `RealmCollection`, `OrderedRealmCollection` and `OrderedRealmCollectionSnapshot`.\n* Realm has upgraded its RxJava1 support to RxJava2 (#3497)\n  * `Realm.asObservable()` has been renamed to `Realm.asFlowable()`.\n  * `RealmList.asObservable()` has been renamed to `RealmList.asFlowable()`.\n  * `RealmResults.asObservable()` has been renamed to `RealmResults.asFlowable()`.\n  * `RealmObject.asObservable()` has been renamed to `RealmObject.asFlowable()`.\n  * `RxObservableFactory` now return RxJava2 types instead of RxJava1 types.\n* Removed deprecated APIs `RealmSchema.close()` and `RealmObjectSchema.close()`. Those don't have to be called anymore.\n* Removed deprecated API `RealmResults.removeChangeListeners()`. Use `RealmResults.removeAllChangeListeners()` instead.\n* Removed deprecated API `RealmObject.removeChangeListeners()`. Use `RealmObject.removeAllChangeListeners()` instead.\n* Removed `UNSUPPORTED_TABLE`, `UNSUPPORTED_MIXED` and `UNSUPPORTED_DATE` from `RealmFieldType`.\n* Removed deprecated API `RealmResults.distinct()`/`RealmResults.distinctAsync()`. Use `RealmQuery.distinct()`/`RealmQuery.distinctAsync()` instead.\n* `RealmQuery.createQuery(Realm, Class)`, `RealmQuery.createDynamicQuery(DynamicRealm, String)`, `RealmQuery.createQueryFromResult(RealmResults)` and `RealmQuery.createQueryFromList(RealmList)` have been removed. Use `Realm.where(Class)`, `DynamicRealm.where(String)`, `RealmResults.where()` and `RealmList.where()` instead.\n\n### Enhancements\n\n* [ObjectServer] `SyncUserInfo` now also exposes a users metadata using `SyncUserInfo.getMetadata()`\n* `RealmList` can now contain `String`, `byte[]`, `Boolean`, `Long`, `Integer`, `Short`, `Byte`, `Double`, `Float` and `Date` values. [Queries](https://github.com/realm/realm-java/issues/5361) and [Importing primitive lists from JSON](https://github.com/realm/realm-java/issues/5362) are not supported yet.\n* Added support for lists of primitives in `RealmObjectSchema` with `addRealmListField(String fieldName, Class<?> primitiveType)`\n* Added support for lists of primitives in `DynamicRealmObject` with `setList(String fieldName, RealmList<?> list)` and `getList(String fieldName, Class<?> primitiveType)`.\n* Minor performance improvement when copy/insert objects into Realm.\n* Added `static RealmObject.getRealm(RealmModel)`, `RealmObject.getRealm()` and `DynamicRealmObject.getDynamicRealm()` (#4720).\n* Added `RealmResults.asChangesetObservable()` that emits the pair `(results, changeset)` (#4277).\n* Added `RealmList.asChangesetObservable()` that emits the pair `(list, changeset)` (#4277).\n* Added `RealmObject.asChangesetObservable()` that emits the pair `(object, changeset)` (#4277).\n* All Realm annotations are now kept at runtime, allowing runtime tools access to them (#5344).\n* Speedup schema initialization when a Realm file is first accessed (#5391).\n\n### Bug Fixes\n\n* [ObjectServer] Exposing a `RealmConfiguration` that allows a user to open the backup Realm after the client reset (#4759/#5223).\n* [ObjectServer] Realm no longer throws a native “unsupported instruction” exception in some cases when opening a synced Realm asynchronously (https://github.com/realm/realm-object-store/issues/502).\n* [ObjectServer] Fixed \"Cannot open the read only Realm\" issue when get`PermissionManager` (#5414).\n* Throw `IllegalArgumentException` instead of `IllegalStateException` when calling string/binary data setters if the data length exceeds the limit.\n* Added support for ISO8601 2-digit time zone designators (#5309).\n* \"Bad File Header\" caused by the device running out of space while compacting the Realm (#5011).\n* `RealmQuery.equalTo()` failed to find null values on an indexed field if using Case.INSENSITIVE (#5299).\n* Assigning a managed object's own list to itself would accidentally clear it (#5395).\n* Don't try to acquire `ApplicationContext` if not available in `Realm.init(Context)` (#5389).\n* Removing and re-adding a changelistener from inside a changelistener sometimes caused notifications to be missed (#5411).\n\n### Internal\n\n* Upgraded to Realm Sync 2.0.2.\n* Upgraded to Realm Core 4.0.2.\n* Upgraded to OkHttp 3.9.0.\n* Upgraded to RxJava 2.1.4.\n* Use Object Store to create the primary key table.\n\n### Credits\n\n* Thanks to @JussiPekonen for adding support for 2-digit time zone designators when importing JSON (#5309).\n\n\n## 3.7.2 (2017-09-12)\n\n### Bug Fixes\n\n* Fixed a JNI memory issue when doing queries which might potentially cause various native crashes.\n* Fixed a bug that `RealmList.deleteFromRealm(int)`, `RealmList.deleteFirstFromRealm()` and `RealmList.deleteLastFromRealm()` did not remove target objects from Realm. This bug was introduced in `3.7.1` (#5233).\n* Crash with \"'xxx' doesn't exist in current schema.\" when ProGuard is enabled (#5211).\n\n\n## 3.7.1 (2017-09-07)\n\n### Bug Fixes\n\n* Fixed potential memory leaks of `LinkView` when calling bulk insertions APIs.\n* Fixed possible assertion when using `PermissionManager` at the beginning (#5195).\n* Crash caused by JNI couldn't find `SharedRealm`'s inner classes when ProGuard is enabled (#5211).\n\n### Internal\n\n* Replaced LinkView with Object Store's List.\n* Renaming `io.realm.internal.CollectionChangeSet` to `io.realm.internal.OsCollectionChangeSet`.\n\n\n## 3.7.0 (2017-09-01)\n\n### Deprecated\n\n* [ObjectServer] `SyncUser.getManagementRealm()`. Use `SyncUser.getPermissionManager()` instead.\n\n### Enhancements\n\n* [ObjectServer] `SyncUser.getPermissionManager` added as a helper API for working with permissions and permission offers.\n\n### Internal\n\n* [ObjectServer] Upgraded OkHttp to 3.7.0.\n\n\n## 3.6.0 (2017-09-01)\n\n### Breaking Changes\n\n* [ObjectServer] `SyncUser.logout()` no longer throws an exception when associated Realms instances are not closed (#4962).\n\n### Deprecated\n\n* [ObjectServer] `SyncUser#retrieveUser` and `SyncUser#retrieveUserAsync` replaced by `SyncUser#retrieveInfoForUser`\nand `SyncUser#retrieveInfoForUserAsync` which returns a `SyncUserInfo` with mode information (#5008).\n* [ObjectServer] `SyncUser#Callback` replaced by the generic version `SyncUser#RequestCallback<T>`.\n\n### Enhancements\n\n* [ObjectServer] Added `SyncSession.uploadAllLocalChanges()`.\n* [ObjectServer] APIs of `UserStore` have been changed to support same user identity but different authentication server scenario.\n* [ObjectServer] Added `SyncUser.allSessions` to retrieve the all valid sessions belonging to the user (#4783).\n* Added `Nullable` annotation to methods that may return `null` in order to improve Kotlin usability. This also introduced a dependency to `com.google.code.findbugs:jsr305`.\n* `org.jetbrains.annotations.NotNull` is now an alias for `@Required`. This means that the Realm Schema now fully understand Kotlin non-null types.\n* Added support for new data type `MutableRealmIntegers`. The new type behaves almost exactly as a reference to a Long (mutable nullable, etc) but supports `increment` and `decrement` methods, which implement a Conflict Free Replicated Data Type, whose value will converge even when changed across distributed devices with poor connections (#4266).\n* Added more detailed exception message for `RealmMigrationNeeded`.\n* Bumping schema version only without any actual schema changes will just succeed even when the migration block is not supplied. It threw an `RealmMigrationNeededException` before in the same case.\n* Throw `IllegalStateException` when schema validation fails because of wrong declaration of `@LinkingObjects`.\n\n### Bug Fixes\n\n* Potential crash after using `Realm.getSchema()` to change the schema of a typed Realm. `Realm.getSchema()` now returns an immutable `RealmSchema` instance.\n* `Realm.copyToRealmOrUpdate()` could cause a `RealmList` field to contain duplicated elements (#4957).\n* `RealmSchema.create(String)` and `RealmObjectSchema.setClassName(String)` did not accept class name whose length was 51 to 57.\n* Workaround for an Android JVM crash when using `compactOnLaunch()` (#4964).\n* Class name in exception message from link query is wrong (#5096).\n* The `compactOnLaunch` callback is no longer invoked if the Realm at that path is already open on other threads.\n\n### Internal\n\n* [ObjectServer] removed `ObjectServerUser` and its inner classes, in a step to reduce `SyncUser` complexity (#3741).\n* [ObjectServer] changed the `SyncSessionStopPolicy` to `AfterChangesUploaded` to align with other binding and to prevent use cases where the Realm might be deleted before the last changes get synchronized (#5028).\n* Upgraded Realm Sync to 1.10.8\n* Let Object Store handle migration.\n\n\n## 3.5.0 (2017-07-11)\n\n### Enhancements\n\n* Added `RealmConfiguration.Builder.compactOnLaunch()` to compact the file on launch (#3739).\n* [ObjectServer] Adding user lookup API for administrators (#4828).\n* An `IllegalStateException` will be thrown if the given `RealmModule` doesn't include all required model classes (#3398).\n\n### Bug Fixes\n\n* Bug in `isNull()`, `isNotNull()`, `isEmpty()`, and `isNotEmpty()` when queries involve nullable fields in link queries (#4856).\n* Bug in how to resolve field names when querying `@LinkingObjects` as the last field (#4864).\n* Rare crash in `RealmLog` when log level was set to `LogLevel.DEBUG`.\n* Broken case insensitive query with indexed field (#4788).\n* [ObjectServer] Bug related to the behaviour of `SyncUser#logout` and the use of invalid `SyncUser` with `SyncConfiguration` (#4822).\n* [ObjectServer] Not all error codes from the server were recognized correctly, resulting in UNKNOWN being reported instead.\n* [ObjectServer] Prevent the use of a `SyncUser` that explicitly logged out, to open a Realm (#4975).\n\n### Internal\n\n* Use Object Store to do table initialization.\n* Removed `Table#Table()`, `Table#addEmptyRow()`, `Table#addEmptyRows()`, `Table#add(Object...)`, `Table#pivot(long,long,PivotType)` and `Table#createnative()`.\n* Upgraded Realm Core to 2.8.6\n* Upgraded Realm Sync to 1.10.5\n* Removed `io.realm.internal.OutOfMemoryError`. `java.lang.OutOfMemoryError` will be thrown instead.\n\n\n## 3.4.0 (2017-06-22)\n\n### Breaking Changes\n\n* [ObjectServer] Updated protocol version to 18 which is only compatible with ROS > 1.6.0.\n\n### Deprecated\n\n* `RealmSchema.close()` and `RealmObjectSchema.close()`. They don't need to be closed manually. They were added to the public API by mistake.\n\n### Enhancements\n\n* [ObjectServer] Added support for Sync Progress Notifications through `SyncSession.addDownloadProgressListener(ProgressMode, ProgressListener)` and `SyncSession.addUploadProgressListener(ProgressMode, ProgressListener)` (#4104).\n* [ObjectServer] Added `SyncSession.getState()` (#4784).\n* Added support for querying inverse relationships (#2904).\n* Moved inverse relationships out of beta stage.\n* Added `Realm.getDefaultConfiguration()` (#4725).\n\n### Bug Fixes\n\n* [ObjectServer] Bug which may crash when the JNI local reference limitation was reached on sync client thread.\n* [ObjectServer] Retrying connections with exponential backoff, when encountering `ConnectException` (#4310).\n* When converting nullable BLOB field to required, `null` values should be converted to `byte[0]` instead of `byte[1]`.\n* Bug which may cause duplicated primary key values when migrating a nullable primary key field to not nullable. `RealmObjectSchema.setRequired()` and `RealmObjectSchema.setNullable()` will throw when converting a nullable primary key field with null values stored to a required primary key field.\n\n### Internal\n\n* Upgraded to Realm Sync 1.10.1\n* Upgraded to Realm Core 2.8.4\n\n### Credits\n\n* Thanks to Anis Ben Nsir (@abennsir) for upgrading Roboelectric in the unitTestExample (#4698).\n\n\n## 3.3.2 (2017-06-09)\n\n### Bug Fixes\n\n* [ObjectServer] Crash when an authentication error happens (#4726).\n* [ObjectServer] Enabled encryption with Sync (#4561).\n* [ObjectServer] Admin users did not connect correctly to the server (#4750).\n\n### Internal\n\n* Factor out internal interface ManagedObject.\n\n## 3.3.1 (2017-05-26)\n\n### Bug Fixes\n\n* [ObjectServer] Accepted extra columns against synced Realm (#4706).\n\n\n## 3.3.0 (2017-05-24)\n\n### Enhancements\n\n* [ObjectServer] Added two options to `SyncConfiguration` to provide a trusted root CA `trustedRootCA` and to disable SSL validation `disableSSLVerification` (#4371).\n* [ObjectServer] Added support for changing passwords through `SyncUser.changePassword()` using an admin user (#4588).\n\n### Bug Fixes\n\n* Queries on proguarded Realm model classes, failed with \"Table not found\" (#4673).\n\n\n## 3.2.1 (2017-05-19)\n\n### Enhancements\n\n* Not in transaction illegal state exception message changed to \"Cannot modify managed objects outside of a write transaction.\".\n\n### Bug Fixes\n\n* [ObjectServer] `schemaVersion` was mistakenly required in order to trigger migrations (#4658).\n* [ObjectServer] Fields removed from model classes will now correctly be hidden instead of throwing an exception when opening the Realm (#4658).\n* Random crashes which were caused by a race condition in encrypted Realm (#4343).\n\n### Internal\n\n* Upgraded to Realm Sync 1.8.5.\n* Upgraded to Realm Core 2.8.0.\n\n## 3.2.0 (2017-05-16)\n\n### Enhancements\n\n* [ObjectServer] Added support for `SyncUser.isAdmin()` (#4353).\n* [ObjectServer] New set of Permission API's have been added to `SyncUser` through `SyncUser.getPermissionManager()` (#4296).\n* [ObjectServer] Added support for changing passwords through `SyncUser.changePassword()` (#4423).\n* [ObjectServer] Added support for `SyncConfiguration.Builder.waitForInitialRemoteData()` (#4270).\n* Transient fields are now allowed in model classes, but are implicitly treated as having the `@Ignore` annotation (#4279).\n* Added `Realm.refresh()` and `DynamicRealm.refresh()` (#3476).\n* Added `Realm.getInstanceAsync()` and `DynamicRealm.getInstanceAsync()` (#2299).\n* Added `DynamicRealmObject#linkingObjects(String,String)` to support linking objects on `DynamicRealm` (#4492).\n* Added support for read only Realms using `RealmConfiguration.Builder.readOnly()` and `SyncConfiguration.Builder.readOnly()`(#1147).\n* Change listeners will now auto-expand variable names to be more descriptive when using Android Studio.\n* The `toString()` methods for the standard and dynamic proxies now print \"proxy\", or \"dynamic\" before the left bracket enclosing the data.\n\n### Bug Fixes\n\n* `@LinkingObjects` annotation now also works with Kotlin (#4611).\n\n### Internal\n\n* Use separated locks for different `RealmCache`s (#4551).\n\n## 3.1.4 (2017-05-04)\n\n## Bug fixes\n\n* Added missing row validation check in certain cases on invalidated/deleted objects (#4540).\n* Initializing Realm is now more resilient if `Context.getFilesDir()` isn't working correctly (#4493).\n* `OrderedRealmCollectionSnapshot.get()` returned a wrong object (#4554).\n* `onSuccess` callback got triggered infinitely if a synced transaction was committed in the async transaction's `onSuccess` callback (#4594).\n\n## 3.1.3 (2017-04-20)\n\n### Enhancements\n\n* [ObjectServer] Resume synchronization as soon as the connectivity is back (#4141).\n\n### Bug Fixes\n\n* `equals()` and `hashCode()` of managed `RealmObject`s that come from linking objects don't work correctly (#4487).\n* Field name was missing in exception message when `null` was set to required field (#4484).\n* Now throws `IllegalStateException` when a getter of linking objects is called against deleted or not yet loaded `RealmObject`s (#4499).\n* `NullPointerException` caused by local transaction inside the listener of `findFirstAsync()`'s results (#4495).\n* Native crash when adding listeners to `RealmObject` after removing listeners from the same `RealmObject` before (#4502).\n* Native crash with \"Invalid argument\" error happened on some Android 7.1.1 devices when opening Realm on external storage (#4461).\n* `OrderedRealmCollectionChangeListener` didn't report change ranges correctly when circular link's field changed (#4474).\n\n### Internal\n\n* Upgraded to Realm Sync 1.6.0.\n* Upgraded to Realm Core 2.6.1.\n\n## 3.1.2 (2017-04-12)\n\n### Bug Fixes\n\n* Crash caused by JNI couldn't find `OsObject.notifyChangeListeners` when ProGuard is enabled (#4461).\n* Incompatible return type of `RealmSchema.getAll()` and `BaseRealm.getSchema()` (#4443).\n* Memory leaked when synced Realm was initialized (#4465).\n* An `IllegalStateException` will be thrown when starting iterating `OrderedRealmCollection` if the Realm is closed (#4471).\n\n## 3.1.1 (2017-04-07)\n\n### Bug Fixes\n\n* Crash caused by Listeners on `RealmObject` getting triggered the 2nd time with different changed field (#4437).\n* Unintentionally exposing `StandardRealmSchema` (#4443).\n* Workaround for crashes on specific Samsung devices which are caused by a buggy `memmove` call (#3651).\n\n## 3.1.0 (2017-04-05)\n\n### Breaking Changes\n\n* Updated file format of Realm files. Existing Realm files will automatically be migrated to the new format when they are opened, but older versions of Realm cannot open these files.\n* [ObjectServer] Due to file format changes, Realm Object Server 1.3.0 or later is required.\n\n### Enhancements\n\n* Added support for reverse relationships through the `@LinkingObjects` annotation. See `io.realm.annotations.LinkingObjects` for documentation.\n  * This feature is in `@Beta`.\n  * Queries on linking objects do not work.  Queries like `where(...).equalTo(\"field.linkingObjects.id\", 7).findAll()` are not yet supported.\n  * Backlink verification is incomplete.  Evil code can cause native crashes.\n* The listener on `RealmObject` will only be triggered if the object changes (#3894).\n* Added `RealmObjectChangeListener` interface that provide detailed information about `RealmObject` field changes.\n* Listeners on `RealmList` and `RealmResults` will be triggered immediately when the transaction is committed on the same thread (#4245).\n* The real `RealmMigrationNeededException` is now thrown instead of `IllegalArgumentException` if no migration is provided for a Realm that requires it.\n* `RealmQuery.distinct()` can be performed on unindexed fields (#2285).\n* `targetSdkVersion` is now 25.\n* [ObjectServer] In case of a Client Reset, information about the location of the backed up Realm file is now reported through the `ErrorHandler` interface (#4080).\n* [ObjectServer] Authentication URLs now automatically append `/auth` if no other path segment is set (#4370).\n\n### Bug Fixes\n\n* Crash with `LogicError` with `Bad version number` on notifier thread (#4369).\n* `Realm.migrateRealm(RealmConfiguration)` now fails correctly with an `IllegalArgumentException` if a `SyncConfiguration` is provided (#4075).\n* Potential cause for Realm file corruptions (never reported).\n* Add `@Override` annotation to proxy class accessors and stop using raw type in proxy classes in order to remove warnings from javac (#4329).\n* `findFirstAsync()` now returns an invalid object if there is no object matches the query condition instead of running the query repeatedly until it can find one (#4352).\n* [ObjectServer] Changing the log level after starting a session now works correctly (#4337).\n\n### Internal\n\n* Using the Object Store's Session and SyncManager.\n* Upgraded to Realm Sync 1.5.0.\n* Upgraded to Realm Core 2.5.1.\n* Upgraded Gradle to 3.4.1\n\n## 3.0.0 (2017-02-28)\n\n### Breaking Changes\n\n* `RealmResults.distinct()` returns a new `RealmResults` object instead of filtering on the original object (#2947).\n* `RealmResults` is auto-updated continuously. Any transaction on the current thread which may have an impact on the order or elements of the `RealmResults` will change the `RealmResults` immediately instead of change it in the next event loop. The standard `RealmResults.iterator()` will continue to work as normal, which means that you can still delete or modify elements without impacting the iterator. The same is not true for simple for-loops. In some cases a simple for-loop will not work (https://realm.io/docs/java/3.0.0/api/io/realm/OrderedRealmCollection.html#loops), and you must use the new createSnapshot() method.\n* `RealmChangeListener` on `RealmObject` will now also be triggered when the object is deleted. Use `RealmObject.isValid()` to check this state(#3138).\n* `RealmObject.asObservable()` will now emit the object when it is deleted. Use `RealmObject.isValid()` to check this state (#3138).\n* Removed deprecated classes `Logger` and `AndroidLogger` (#4050).\n\n### Deprecated\n\n* `RealmResults.removeChangeListeners()`. Use `RealmResults.removeAllChangeListeners()` instead.\n* `RealmObject.removeChangeListeners()`. Use `RealmObject.removeAllChangeListeners()` instead.\n* `RealmResults.distinct()` and `RealmResults.distinctAsync()`. Use `RealmQuery.distinct()` and `RealmQuery.distinctAsync()` instead.\n\n### Enhancements\n\n* Added support for sorting by link's field (#672).\n* Added `OrderedRealmCollectionSnapshot` class and `OrderedRealmCollection.createSnapshot()` method. `OrderedRealmCollectionSnapshot` is useful when changing `RealmResults` or `RealmList` in simple loops.\n* Added `OrderedRealmCollectionChangeListener` interface for supporting fine-grained collection notifications.\n* Added support for ChangeListeners on `RealmList`.\n* Added `RealmList.asObservable()`.\n\n### Bug Fixes\n\n* Element type checking in `DynamicRealmObject#setList()` (#4252).\n* Now throws `IllegalStateException` instead of process crash when any of thread confined methods in `RealmQuery` is called from wrong thread (#4228).\n* Now throws `IllegalStateException` when any of thread confined methods in `DynamicRealmObject` is called from wrong thread (#4258).\n\n### Internal\n\n* Use Object Store's `Results` as the backend for `RealmResults` (#3372).\n  - Use Object Store's notification mechanism to trigger listeners.\n  - Local commits triggers Realm global listener and `RealmObject` listener on current thread immediately instead of in the next event loop.\n\n\n## 2.3.2 (2017-02-27)\n\n### Bug fixes\n\n* Log levels in JNI layer were all reported as \"Error\" (#4204).\n* Encrypted realms can end up corrupted if many threads are reading and writing at the same time (#4128).\n* \"Read-only file system\" exception when compacting Realm file on external storage (#4140).\n\n### Internal\n\n* Updated to Realm Sync v1.2.1.\n* Updated to Realm Core v2.3.2.\n\n### Enhancements\n\n* Improved performance of getters and setters in proxy classes.\n\n\n## 2.3.1 (2017-02-07)\n\n### Enhancements\n\n* [ObjectServer] The `serverUrl` given to `SyncConfiguration.Builder()` is now more lenient and will also accept only paths as argument (#4144).\n* [ObjectServer] Add a timer to refresh periodically the access_token.\n\n### Bug fixes\n\n* NPE problem in SharedRealm.finalize() (#3730).\n* `RealmList.contains()` and `RealmResults.contains()` now correctly use custom `equals()` method on Realm model classes.\n* Build error when the project is using Kotlin (#4087).\n* Bug causing classes to be replaced by classes already in Gradle's classpath (#3568).\n* NullPointerException when notifying a single object that it changed (#4086).\n\n\n## 2.3.0 (2017-01-19)\n\n### Object Server API Changes\n\n* Realm Sync v1.0.0 has been released, and Realm Mobile Platform is no longer considered in beta.\n* Breaking change: Location of Realm files are now placed in `getFilesDir()/<userIdentifier>` instead of `getFilesDir()/`.\n  This is done in order to support shared Realms among users, while each user retaining their own local copy.\n* Breaking change: `SyncUser.all()` now returns Map instead of List.\n* Breaking change: Added a default `UserStore` saving users in a Realm file (`RealmFileUserStore`).\n* Breaking change: Added multi-user support to `UserStore`. Added `get(String)` and `remove(String)`, removed `remove()` and renamed `get()` to `getCurrent()`.\n* Breaking change: Changed the order of arguments to `SyncCredentials.custom()` to match iOS: token, provider, userInfo.\n* Added support for `PermissionOffer` and `PermissionOfferResponse` to `SyncUser.getManagementRealm()`.\n* Exceptions thrown in error handlers are ignored but logged (#3559).\n* Removed unused public constants in `SyncConfiguration` (#4047).\n* Fixed bug, preventing Sync client to renew the access token (#4038) (#4039).\n* Now `SyncUser.logout()` properly revokes tokens (#3639).\n\n### Bug fixes\n\n* Fixed native memory leak setting the value of a primary key (#3993).\n* Activated Realm's annotation processor on connectedTest when the project is using kapt (#4008).\n* Fixed \"too many open files\" issue (#4002).\n* Added temporary work-around for bug crashing Samsung Tab 3 devices on startup (#3651).\n\n### Enhancements\n\n* Added `like` predicate for String fields (#3752).\n\n### Internal\n\n* Updated to Realm Sync v1.0.0.\n* Added a Realm backup when receiving a Sync client reset message from the server.\n\n## 2.2.2 (2017-01-16)\n\n### Object Server API Changes (In Beta)\n\n* Disabled `Realm.compactRealm()` when sync is enabled as it might corrupt the Realm (https://github.com/realm/realm-core/issues/2345).\n\n### Bug fixes\n\n* \"operation not permitted\" issue when creating Realm file on some devices' external storage (#3629).\n* Crash on API 10 devices (#3726).\n* `UnsatisfiedLinkError` caused by `pipe2` (#3945).\n* Unrecoverable error with message \"Try again\" when the notification fifo is full (#3964).\n* Realm migration wasn't triggered when the primary key definition was altered (#3966).\n* Use phantom reference to solve the finalize time out issue (#2496).\n\n### Enhancements\n\n* All major public classes are now non-final. This is mostly a compromise to support Mockito. All protected fields/methods are still not considered part of the public API and can change without notice (#3869).\n* All Realm instances share a single notification daemon thread.\n* Fixed Java lint warnings with generated proxy classes (#2929).\n\n### Internal\n\n* Upgraded Realm Core to 2.3.0.\n* Upgraded Realm Sync to 1.0.0-BETA-6.5.\n\n## 2.2.1 (2016-11-12)\n\n### Object Server API Changes (In Beta)\n\n* Fixed `SyncConfiguration.toString()` so it now outputs a correct description instead of an empty string (#3787).\n\n### Bug fixes\n\n* Added version number to the native library, preventing ReLinker from accidentally loading old code (#3775).\n* `Realm.getLocalInstanceCount(config)` throwing NullPointerException if called after all Realms have been closed (#3791).\n\n## 2.2.0 (2016-11-12)\n\n### Object Server API Changes (In Beta)\n\n* Added support for `SyncUser.getManagementRealm()` and permission changes.\n\n### Bug fixes\n\n* Kotlin projects no longer create the `RealmDefaultModule` if no Realm model classes are present (#3746).\n* Remove `includedescriptorclasses` option from ProGuard rule file in order to support built-in shrinker of Android Gradle Plugin (#3714).\n* Unexpected `RealmMigrationNeededException` was thrown when a field was added to synced Realm.\n\n### Enhancements\n\n* Added support for the `annotationProcessor` configuration provided by Android Gradle Plugin 2.2.0 or later. Realm plugin adds its annotation processor to the `annotationProcessor` configuration instead of `apt` configuration if it is available and the `com.neenbedankt.android-apt` plugin is not used. In Kotlin projects, `kapt` is used instead of the `annotationProcessor` configuration (#3026).\n\n## 2.1.1 (2016-10-27)\n\n### Bug fixes\n\n* Fixed a bug in `Realm.insert` and `Realm.insertOrUpdate` methods causing a `StackOverFlow` when you try to insert a cyclic graph of objects between Realms (#3732).\n\n### Object Server API Changes (In Beta)\n\n* Set default RxFactory to `SyncConfiguration`.\n\n### Bug fixes\n\n* ProGuard configuration introduced in 2.1.0 unexpectedly kept classes that did not have the @KeepMember annotation (#3689).\n\n## 2.1.0 (2016-10-25)\n\n### Breaking changes\n\n* * `SecureUserStore` has been moved to its own GitHub repository: https://github.com/realm/realm-android-user-store\n  See https://github.com/realm/realm-android-user-store/blob/master/README.md for further info on how to include it.\n\n\n### Object Server API Changes (In Beta)\n\n* Renamed `User` to `SyncUser`, `Credentials` to `SyncCredentials` and `Session` to `SyncSession` to align names with Cocoa.\n* Removed `SyncManager.setLogLevel()`. Use `RealmLog.setLevel()` instead.\n* `SyncUser.logout()` now correctly clears `SyncUser.currentUser()` (#3638).\n* Missing ProGuard configuration for libraries used by Sync extension (#3596).\n* Error handler was not called when sync session failed (#3597).\n* Added `User.all()` that returns all known Realm Object Server users.\n* Upgraded Realm Sync to 1.0.0-BETA-3.2\n\n### Deprecated\n\n* `Logger`. Use `RealmLogger` instead.\n* `AndroidLogger`. The logger for Android is implemented in native code instead.\n\n### Bug fixes\n\n* The following were not kept by ProGuard: names of native methods not in the `io.realm.internal` package, names of classes used in method signature (#3596).\n* Permission error when a database file was located on external storage (#3140).\n* Memory leak when unsubscribing from a RealmResults/RealmObject RxJava Observable (#3552).\n\n### Enhancements\n\n* `Realm.compactRealm()` now works for encrypted Realms.\n* Added `first(E defaultValue)` and `last(E defaultValue)` methods to `RealmList` and `RealmResult`. These methods will return the provided object instead of throwing an `IndexOutOfBoundsException` if the list is empty.\n* Reduce transformer logger verbosity (#3608).\n* `RealmLog.setLevel(int)` for setting the log level across all loggers.\n\n### Internal\n\n* Upgraded Realm Core to 2.1.3\n\n### Credits\n\n* Thanks to Max Furman (@maxfurman) for adding support for `first()` and `last()` default values.\n\n## 2.0.2 (2016-10-06)\n\nThis release is not protocol-compatible with previous versions of the Realm Mobile Platform. The base library is still fully compatible.\n\n### Bug fixes\n\n* Build error when using Java 7 (#3563).\n\n### Internal\n\n* Upgraded Realm Core to 2.1.0\n* Upgraded Realm Sync to 1.0.0-BETA-2.0.\n\n## 2.0.1 (2016-10-05)\n\n### Bug fixes\n\n* `android.net.conn.CONNECTIVITY_CHANGE` broadcast caused `RuntimeException` if sync extension was disabled (#3505).\n* `android.net.conn.CONNECTIVITY_CHANGE` was not delivered on Android 7 devices.\n* `distinctAsync` did not respect other query parameters (#3537).\n* `ConcurrentModificationException` from Gradle when building an application (#3501).\n\n### Internal\n\n* Upgraded to Realm Core 2.0.1 / Realm Sync 1.3-BETA\n\n## 2.0.0 (2016-09-27)\n\nThis release introduces support for the Realm Mobile Platform!\nSee <https://realm.io/news/introducing-realm-mobile-platform/> for an overview of these great new features.\n\n### Breaking Changes\n\n* Files written by Realm 2.0 cannot be read by 1.x or earlier versions. Old files can still be opened.\n* It is now required to call `Realm.init(Context)` before calling any other Realm API.\n* Removed `RealmConfiguration.Builder(Context)`, `RealmConfiguration.Builder(Context, File)` and `RealmConfiguration.Builder(File)` constructors.\n* `isValid()` now always returns `true` instead of `false` for unmanaged `RealmObject` and `RealmList`. This puts it in line with the behaviour of the Cocoa and .NET API's (#3101).\n* armeabi is not supported anymore.\n* Added new `RealmFileException`.\n  - `IncompatibleLockFileException` has been removed and replaced by `RealmFileException` with kind `INCOMPATIBLE_LOCK_FILE`.\n  - `RealmIOExcpetion` has been removed and replaced by `RealmFileException`.\n* `RealmConfiguration.Builder.assetFile(Context, String)` has been renamed to `RealmConfiguration.Builder.assetFile(String)`.\n* Object with primary key is now required to define it when the object is created. This means that `Realm.createObject(Class<E>)` and `DynamicRealm.createObject(String)` now throws `RealmException` if they are used to create an object with a primary key field. Use `Realm.createObject(Class<E>, Object)` or `DynamicRealm.createObject(String, Object)` instead.\n* Importing from JSON without the primary key field defined in the JSON object now throws `IllegalArgumentException`.\n* Now `Realm.beginTransaction()`, `Realm.executeTransaction()` and `Realm.waitForChange()` throw `RealmMigrationNeededException` if a remote process introduces incompatible schema changes (#3409).\n* The primary key value of an object can no longer be changed after the object was created. Instead a new object must be created and all fields copied over.\n* Now `Realm.createObject(Class)` and `Realm.createObject(Class,Object)` take the values from the model's fields and default constructor. Creating objects through the `DynamicRealm` does not use these values (#777).\n* When `Realm.create*FromJson()`s create a new `RealmObject`, now they take the default values defined by the field itself and its default constructor for those fields that are not defined in the JSON object.\n\n### Enhancements\n\n* Added `realmObject.isManaged()`, `RealmObject.isManaged(obj)` and `RealmCollection.isManaged()` (#3101).\n* Added `RealmConfiguration.Builder.directory(File)`.\n* `RealmLog` has been moved to the public API. It is now possible to control which events Realm emit to Logcat. See the `RealmLog` class for more details.\n* Typed `RealmObject`s can now continue to access their fields properly even though the schema was changed while the Realm was open (#3409).\n* A `RealmMigrationNeededException` will be thrown with a cause to show the detailed message when a migration is needed and the migration block is not in the `RealmConfiguration`.\n\n\n### Bug fixes\n\n* Fixed a lint error in proxy classes when the 'minSdkVersion' of user's project is smaller than 11 (#3356).\n* Fixed a potential crash when there were lots of async queries waiting in the queue.\n* Fixed a bug causing the Realm Transformer to not transform field access in the model's constructors (#3361).\n* Fixed a bug causing a build failure when the Realm Transformer adds accessors to a model class that was already transformed in other project (#3469).\n* Fixed a bug causing the `NullPointerException` when calling getters/setters in the model's constructors (#2536).\n\n### Internal\n\n* Moved JNI build to CMake.\n* Updated Realm Core to 2.0.0.\n* Updated ReLinker to 1.2.2.\n\n## 1.2.0 (2016-08-19)\n\n### Bug fixes\n\n* Throw a proper exception when operating on a non-existing field with the dynamic API (#3292).\n* `DynamicRealmObject.setList` should only accept `RealmList<DynamicRealmObject>` (#3280).\n* `DynamicRealmObject.getX(fieldName)` now throws a proper exception instead of a native crash when called with a field name of the wrong type (#3294).\n* Fixed a concurrency crash which might happen when `Realm.executeTransactionAsync()` tried to call `onSucess` after the Realm was closed.\n\n### Enhancements\n\n* Added `RealmQuery.in()` for a comparison against multiple values.\n* Added byte array (`byte[]`) support to `RealmQuery`'s `equalTo` and `notEqualTo` methods.\n* Optimized internal caching of schema classes (#3315).\n\n### Internal\n\n* Updated Realm Core to 1.5.1.\n* Improved sorting speed.\n* Completely removed the `OptionalAPITransformer`.\n\n### Credits\n\n* Thanks to Brenden Kromhout (@bkromhout) for adding binary array support to `equalTo` and `notEqualTo`.\n\n## 1.1.1 (2016-07-01)\n\n### Bug fixes\n\n* Fixed a wrong JNI method declaration which might cause \"method not found\" crash on some devices.\n* Fixed a bug that `Error` in the background async thread is not forwarded to the caller thread.\n* Fixed a crash when an empty `Collection` is passed to `insert()`/`insertOrUpdate()` (#3103).\n* Fixed a bug that does not transfer the primary key when `RealmSchemaObject.setClassName()` is called to rename a class (#3118).\n* Fixed bug in `Realm.insert` and `Realm.insertOrUpdate` methods causing a `RealmList` to be cleared when inserting a managed `RealmModel` (#3105).\n* Fixed a concurrency allocation bug in storage engine which might lead to some random crashes.\n* Bulk insertion now throws if it is not called in a transaction (#3173).\n* The IllegalStateException thrown when accessing an empty RealmObject is now more meaningful (#3200).\n* `insert()` now correctly throws an exception if two different objects have the same primary key (#3212).\n* Blackberry Z10 throwing \"Function not implemented\" (#3178).\n* Reduced the number of file descriptors used by Realm Core (#3197).\n* Throw a proper `IllegalStateException` if a `RealmChangeListener` is used inside an IntentService (#2875).\n\n### Enhancements\n\n* The Realm Annotation processor no longer consumes the Realm annotations. Allowing other annotation processors to run.\n\n### Internal\n\n* Updated Realm Core to 1.4.2.\n* Improved sorting speed.\n\n## 1.1.0 (2016-06-30)\n\n### Bug fixes\n\n* A number of bug fixes in the storage engine related to memory management in rare cases when a Realm has been compacted.\n* Disabled the optional API transformer since it has problems with DexGuard (#3022).\n* `OnSuccess.OnSuccess()` might not be called with the correct Realm version for async transaction (#1893).\n* Fixed a bug in `copyToRealm()` causing a cyclic dependency objects being duplicated.\n* Fixed a build failure when model class has a conflicting name such as `Map`, `List`, `String`, ... (#3077).\n\n### Enhancements\n\n* Added `insert(RealmModel obj)`, `insertOrUpdate(RealmModel obj)`, `insert(Collection<RealmModel> collection)` and `insertOrUpdate(Collection<RealmModel> collection)` to perform batch inserts (#1684).\n* Enhanced `Table.toString()` to show a PrimaryKey field details (#2903).\n* Enabled ReLinker when loading a Realm from a custom path by adding a `RealmConfiguration.Builder(Context, File)` constructor (#2900).\n* Changed `targetSdkVersion` of `realm-library` to 24.\n* Logs warning if `DynamicRealm` is not closed when GC happens as it does for `Realm`.\n\n### Deprecated\n\n* `RealmConfiguration.Builder(File)`. Use `RealmConfiguration.Builder(Context, File)` instead.\n\n### Internal\n\n* Updated Realm Core to 1.2.0.\n\n## 1.0.1 (2016-05-25)\n\n### Bug fixes\n\n* Fixed a crash when calling `Table.toString()` in debugger (#2429).\n* Fixed a race condition which would cause some `RealmResults` to not be properly updated inside a `RealmChangeListener`. This could result in crashes when accessing items from those results (#2926/#2951).\n* Revised `RealmResults.isLoaded()` description (#2895).\n* Fixed a bug that could cause Realm to lose track of primary key when using `RealmObjectSchema.removeField()` and `RealmObjectSchema.renameField()` (#2829/#2926).\n* Fixed a bug that prevented some devices from finding async related JNI methods correctly.\n* Updated ProGuard configuration in order not to depend on Android's default configuration (#2972).\n* Fixed a race condition between Realms notifications and other UI events. This could e.g. cause ListView to crash (#2990).\n* Fixed a bug that allowed both `RealmConfiguration.Builder.assetFile()`/`deleteRealmIfMigrationNeeded()` to be configured at the same time, which leads to the asset file accidentally being deleted in migrations (#2933).\n* Realm crashed outright when the same Realm file was opened in two processes. Realm will now optimistically retry opening for 1 second before throwing an Error (#2459).\n\n### Enhancements\n\n* Removes RxJava related APIs during bytecode transforming to make RealmObject plays well with reflection when rx.Observable doesn't exist.\n\n## 1.0.0 (2016-05-25)\n\nNo changes since 0.91.1.\n\n## 0.91.1 (2016-05-25)\n\n* Updated Realm Core to 1.0.1.\n\n### Bug fixes\n\n* Fixed a bug when opening a Realm causes a staled memory mapping. Symptoms are error messages like \"Bad or incompatible history type\", \"File format version doesn't match\", and \"Encrypted interprocess sharing is currently unsupported\".\n\n## 0.91.0 (2016-05-20)\n\n* Updated Realm Core to 1.0.0.\n\n### Breaking changes\n\n* Removed all `@Deprecated` methods.\n* Calling `Realm.setAutoRefresh()` or `DynamicRealm.setAutoRefresh()` from non-Looper thread throws `IllegalStateException` even if the `autoRefresh` is false (#2820).\n\n### Bug fixes\n\n* Calling RealmResults.deleteAllFromRealm() might lead to native crash (#2759).\n* The annotation processor now correctly reports an error if trying to reference interfaces in model classes (#2808).\n* Added null check to `addChangeListener` and `removeChangeListener` in `Realm` and `DynamicRealm` (#2772).\n* Calling `RealmObjectSchema.addPrimaryKey()` adds an index to the primary key field, and calling `RealmObjectSchema.removePrimaryKey()` removes the index from the field (#2832).\n* Log files are not deleted when calling `Realm.deleteRealm()` (#2834).\n\n### Enhancements\n\n* Upgrading to OpenSSL 1.0.1t. From July 11, 2016, Google Play only accept apps using OpenSSL 1.0.1r or later (https://support.google.com/faqs/answer/6376725, #2749).\n* Added support for automatically copying an initial database from assets using `RealmConfiguration.Builder.assetFile()`.\n* Better error messages when certain file operations fail.\n\n### Credits\n\n* Paweł Surówka (@thesurix) for adding the `RealmConfiguration.Builder.assetFile()`.\n\n## 0.90.1\n\n* Updated Realm Core to 0.100.2.\n\n### Bug fixes\n\n* Opening a Realm while closing a Realm in another thread could lead to a race condition.\n* Automatic migration to the new file format could in rare circumstances lead to a crash.\n* Fixing a race condition that may occur when using Async API (#2724).\n* Fixed CannotCompileException when related class definition in android.jar cannot be found (#2703).\n\n### Enhancements\n\n* Prints path when file related exceptions are thrown.\n\n## 0.90.0\n\n* Updated Realm Core to 0.100.0.\n\n### Breaking changes\n\n* RealmChangeListener provides the changed object/Realm/collection as well (#1594).\n* All JSON methods on Realm now only wraps JSONException in RealmException. All other Exceptions are thrown as they are.\n* Marked all methods on `RealmObject` and all public classes final (#1594).\n* Removed `BaseRealm` from the public API.\n* Removed `HandlerController` from the public API.\n* Removed constructor of `RealmAsyncTask` from the public API (#1594).\n* `RealmBaseAdapter` has been moved to its own GitHub repository: https://github.com/realm/realm-android-adapters\n  See https://github.com/realm/realm-android-adapters/blob/master/README.md for further info on how to include it.\n* File format of Realm files is changed. Files will be automatically upgraded but opening a Realm file with older\n  versions of Realm is not possible.\n\n### Deprecated\n\n* `Realm.allObjects*()`. Use `Realm.where(clazz).findAll*()` instead.\n* `Realm.distinct*()`. Use `Realm.where(clazz).distinct*()` instead.\n* `DynamicRealm.allObjects*()`. Use `DynamicRealm.where(className).findAll*()` instead.\n* `DynamicRealm.distinct*()`. Use `DynamicRealm.where(className).distinct*()` instead.\n* `Realm.allObjectsSorted(field, sort, field, sort, field, sort)`. Use `RealmQuery.findAllSorted(field[], sort[])` instead.\n* `RealmQuery.findAllSorted(field, sort, field, sort, field, sort)`. Use `RealmQuery.findAllSorted(field[], sort[])` instead.\n* `RealmQuery.findAllSortedAsync(field, sort, field, sort, field, sort)`. Use `RealmQuery.findAllSortedAsync(field[], sort[])` instead.\n* `RealmConfiguration.setModules()`. Use `RealmConfiguration.modules()` instead.\n* `Realm.refresh()` and `DynamicRealm.refresh()`. Use `Realm.waitForChange()`/`stopWaitForChange()` or `DynamicRealm.waitForChange()`/`stopWaitForChange()` instead.\n\n### Enhancements\n\n* `RealmObjectSchema.getPrimaryKey()` (#2636).\n* `Realm.createObject(Class, Object)` for creating objects with a primary key directly.\n* Unit tests in Android library projects now detect Realm model classes.\n* Better error message if `equals()` and `hashCode()` are not properly overridden in custom Migration classes.\n* Expanding the precision of `Date` fields to cover full range (#833).\n* `Realm.waitForChange()`/`stopWaitForChange()` and `DynamicRealm.waitForChange()`/`stopWaitForChange()` (#2386).\n\n### Bug fixes\n\n* `RealmChangeListener` on `RealmObject` is not triggered when adding listener on returned `RealmObject` of `copyToRealmOrUpdate()` (#2569).\n\n### Credits\n\n* Thanks to Brenden Kromhout (@bkromhout) for adding `RealmObjectSchema.getPrimaryKey()`.\n\n## 0.89.1\n\n### Bug fixes\n\n* @PrimaryKey + @Required on String type primary key no longer throws when using copyToRealm or copyToRealmOrUpdate (#2653).\n* Primary key is cleared/changed when calling RealmSchema.remove()/RealmSchema.rename() (#2555).\n* Objects implementing RealmModel can be used as a field of RealmModel/RealmObject (#2654).\n\n## 0.89.0\n\n### Breaking changes\n\n* @PrimaryKey field value can now be null for String, Byte, Short, Integer, and Long types. Older Realms should be migrated, using RealmObjectSchema.setNullable(), or by adding the @Required annotation (#2515).\n* `RealmResults.clear()` now throws UnsupportedOperationException. Use `RealmResults.deleteAllFromRealm()` instead.\n* `RealmResults.remove(int)` now throws UnsupportedOperationException. Use `RealmResults.deleteFromRealm(int)` instead.\n* `RealmResults.sort()` and `RealmList.sort()` now return the sorted result instead of sorting in-place.\n* `RealmList.first()` and `RealmList.last()` now throw `ArrayIndexOutOfBoundsException` if `RealmList` is empty.\n* Removed deprecated method `Realm.getTable()` from public API.\n* `Realm.refresh()` and `DynamicRealm.refresh()` on a Looper no longer have any effect. `RealmObject` and `RealmResults` are always updated on the next event loop.\n\n### Deprecated\n\n* `RealmObject.removeFromRealm()` in place of `RealmObject.deleteFromRealm()`\n* `Realm.clear(Class)` in favour of `Realm.delete(Class)`.\n* `DynamicRealm.clear(Class)` in place of `DynamicRealm.delete(Class)`.\n\n### Enhancements\n\n* Added a `RealmModel` interface that can be used instead of extending `RealmObject`.\n* `RealmCollection` and `OrderedRealmCollection` interfaces have been added. `RealmList` and `RealmResults` both implement these.\n* `RealmBaseAdapter` now accept an `OrderedRealmCollection` instead of only `RealmResults`.\n* `RealmObjectSchema.isPrimaryKey(String)` (#2440)\n* `RealmConfiguration.initialData(Realm.Transaction)` can now be used to populate a Realm file before it is used for the first time.\n\n### Bug fixes\n\n* `RealmObjectSchema.isRequired(String)` and `RealmObjectSchema.isNullable(String)` don't throw when the given field name doesn't exist.\n\n### Credits\n\n* Thanks to @thesurix for adding `RealmConfiguration.initialData()`.\n\n## 0.88.3\n\n* Updated Realm Core to 0.97.3.\n\n### Enhancements\n\n* Throws an IllegalArgumentException when calling Realm.copyToRealm()/Realm.copyToRealmOrUpdate() with a RealmObject which belongs to another Realm instance in a different thread.\n* Improved speed of cleaning up native resources (#2496).\n\n### Bug fixes\n\n* Field annotated with @Ignored should not have accessors generated by the bytecode transformer (#2478).\n* RealmResults and RealmObjects can no longer accidentially be GC'ed if using `asObservable()`. Previously this caused the observable to stop emitting (#2485).\n* Fixed an build issue when using Realm in library projects on Windows (#2484).\n* Custom equals(), toString() and hashCode() are no longer incorrectly overwritten by the proxy class (#2545).\n\n## 0.88.2\n\n* Updated Realm Core to 0.97.2.\n\n### Enhancements\n\n* Outputs additional information when incompatible lock file error occurs.\n\n### Bug fixes\n\n* Race condition causing BadVersionException when running multiple async writes and queries at the same time (#2021/#2391/#2417).\n\n## 0.88.1\n\n### Bug fixes\n\n* Prevent throwing NullPointerException in RealmConfiguration.equals(RealmConfiguration) when RxJava is not in the classpath (#2416).\n* RealmTransformer fails because of missing annotation classes in user's project (#2413).\n* Added SONAME header to shared libraries (#2432).\n* now DynamicRealmObject.toString() correctly shows null value as \"null\" and the format is aligned to the String from typed RealmObject (#2439).\n* Fixed an issue occurring while resolving ReLinker in apps using a library based on Realm (#2415).\n\n## 0.88.0 (2016-03-10)\n\n* Updated Realm Core to 0.97.0.\n\n### Breaking changes\n\n* Realm has now to be installed as a Gradle plugin.\n* DynamicRealm.executeTransaction() now directly throws any RuntimeException instead of wrapping it in a RealmException (#1682).\n* DynamicRealm.executeTransaction() now throws IllegalArgumentException instead of silently accepting a null Transaction object.\n* String setters now throw IllegalArgumentException instead of RealmError for invalid surrogates.\n* DynamicRealm.distinct()/distinctAsync() and Realm.distinct()/distinctAsync() now throw IllegalArgumentException instead of UnsupportedOperationException for invalid type or unindexed field.\n* All thread local change listeners are now delayed until the next Looper event instead of being triggered when committing.\n* Removed RealmConfiguration.getSchemaMediator() from public API which was deprecated in 0.86.0. Please use RealmConfiguration.getRealmObjectClasses() to obtain the set of model classes (#1797).\n* Realm.migrateRealm() throws a FileNotFoundException if the Realm file doesn't exist.\n* It is now required to unsubscribe from all Realm RxJava observables in order to fully close the Realm (#2357).\n\n### Deprecated\n\n* Realm.getInstance(Context). Use Realm.getInstance(RealmConfiguration) or Realm.getDefaultInstance() instead.\n* Realm.getTable(Class) which was public because of the old migration API. Use Realm.getSchema() or DynamicRealm.getSchema() instead.\n* Realm.executeTransaction(Transaction, Callback) and replaced it with Realm.executeTransactionAsync(Transaction), Realm.executeTransactionAsync(Transaction, OnSuccess), Realm.executeTransactionAsync(Transaction, OnError) and Realm.executeTransactionAsync(Transaction, OnSuccess, OnError).\n\n### Enhancements\n\n* Support for custom methods, custom logic in accessors, custom accessor names, interface implementation and public fields in Realm objects (#909).\n* Support to project Lombok (#502).\n* RealmQuery.isNotEmpty() (#2025).\n* Realm.deleteAll() and RealmList.deleteAllFromRealm() (#1560).\n* RealmQuery.distinct() and RealmResults.distinct() (#1568).\n* RealmQuery.distinctAsync() and RealmResults.distinctAsync() (#2118).\n* Improved .so loading by using [ReLinker](https://github.com/KeepSafe/ReLinker).\n* Improved performance of RealmList#contains() (#897).\n* distinct(...) for Realm, DynamicRealm, RealmQuery, and RealmResults can take multiple parameters (#2284).\n* \"realm\" and \"row\" can be used as field name in model classes (#2255).\n* RealmResults.size() now returns Integer.MAX_VALUE when actual size is greater than Integer.MAX_VALUE (#2129).\n* Removed allowBackup from AndroidManifest (#2307).\n\n### Bug fixes\n\n* Error occurring during test and (#2025).\n* Error occurring during test and connectedCheck of unit test example (#1934).\n* Bug in jsonExample (#2092).\n* Multiple calls of RealmResults.distinct() causes to return wrong results (#2198).\n* Calling DynamicRealmObject.setList() with RealmList<DynamicRealmObject> (#2368).\n* RealmChangeListeners did not triggering correctly if findFirstAsync() didn't find any object. findFirstAsync() Observables now also correctly call onNext when the query completes in that case (#2200).\n* Setting a null value to trigger RealmChangeListener (#2366).\n* Preventing throwing BadVersionException (#2391).\n\n### Credits\n\n* Thanks to Bill Best (@wmbest2) for snapshot testing.\n* Thanks to Graham Smith (@grahamsmith) for a detailed bug report (#2200).\n\n## 0.87.5 (2016-01-29)\n* Updated Realm Core to 0.96.2.\n  - IllegalStateException won't be thrown anymore in RealmResults.where() if the RealmList which the RealmResults is created on has been deleted. Instead, the RealmResults will be treated as empty forever.\n  - Fixed a bug causing a bad version exception, when using findFirstAsync (#2115).\n\n## 0.87.4 (2016-01-28)\n* Updated Realm Core to 0.96.0.\n  - Fixed bug causing BadVersionException or crashing core when running async queries.\n\n## 0.87.3 (2016-01-25)\n* IllegalArgumentException is now properly thrown when calling Realm.copyFromRealm() with a DynamicRealmObject (#2058).\n* Fixed a message in IllegalArgumentException thrown by the accessors of DynamicRealmObject (#2141).\n* Fixed RealmList not returning DynamicRealmObjects of the correct underlying type (#2143).\n* Fixed potential crash when rolling back removal of classes that reference each other (#1829).\n* Updated Realm Core to 0.95.8.\n  - Fixed a bug where undetected deleted object might lead to seg. fault (#1945).\n  - Better performance when deleting objects (#2015).\n\n## 0.87.2 (2016-01-08)\n* Removed explicit GC call when committing a transaction (#1925).\n* Fixed a bug when RealmObjectSchema.addField() was called with the PRIMARY_KEY modifier, the field was not set as a required field (#2001).\n* Fixed a bug which could throw a ConcurrentModificationException in RealmObject's or RealmResults' change listener (#1970).\n* Fixed RealmList.set() so it now correctly returns the old element instead of the new (#2044).\n* Fixed the deployment of source and javadoc jars (#1971).\n\n## 0.87.1 (2015-12-23)\n* Upgraded to NDK R10e. Using gcc 4.9 for all architectures.\n* Updated Realm Core to 0.95.6\n  - Fixed a bug where an async query can be copied incomplete in rare cases (#1717).\n* Fixed potential memory leak when using async query.\n* Added a check to prevent removing a RealmChangeListener from a non-Looper thread (#1962). (Thank you @hohnamkung.)\n\n## 0.87.0 (2015-12-17)\n* Added Realm.asObservable(), RealmResults.asObservable(), RealmObject.asObservable(), DynamicRealm.asObservable() and DynamicRealmObject.asObservable().\n* Added RealmConfiguration.Builder.rxFactory() and RxObservableFactory for custom RxJava observable factory classes.\n* Added Realm.copyFromRealm() for creating detached copies of Realm objects (#931).\n* Added RealmObjectSchema.getFieldType() (#1883).\n* Added unitTestExample to showcase unit and instrumentation tests. Examples include jUnit3, jUnit4, Espresso, Robolectric, and MPowermock usage with Realm (#1440).\n* Added support for ISO8601 based dates for JSON import. If JSON dates are invalid a RealmException will be thrown (#1213).\n* Added APK splits to gridViewExample (#1834).\n\n## 0.86.1 (2015-12-11)\n* Improved the performance of removing objects (RealmResults.clear() and RealmResults.remove()).\n* Updated Realm Core to 0.95.5.\n* Updated ProGuard configuration (#1904).\n* Fixed a bug where RealmQuery.findFirst() returned a wrong result if the RealmQuery had been created from a RealmResults.where() (#1905).\n* Fixed a bug causing DynamicRealmObject.getObject()/setObject() to use the wrong class (#1912).\n* Fixed a bug which could cause a crash when closing Realm instances in change listeners (#1900).\n* Fixed a crash occurring during update of multiple async queries (#1895).\n* Fixed listeners not triggered for RealmObject & RealmResults created using copy or create methods (#1884).\n* Fixed RealmChangeListener never called inside RealmResults (#1894).\n* Fixed crash when calling clear on a RealmList (#1886).\n\n## 0.86.0 (2015-12-03)\n* BREAKING CHANGE: The Migration API has been replaced with a new API.\n* BREAKING CHANGE: RealmResults.SORT_ORDER_ASCENDING and RealmResults.SORT_ORDER_DESCENDING constants have been replaced by Sort.ASCENDING and Sort.DESCENDING enums.\n* BREAKING CHANGE: RealmQuery.CASE_SENSITIVE and RealmQuery.CASE_INSENSITIVE constants have been replaced by Case.SENSITIVE and Case.INSENSITIVE enums.\n* BREAKING CHANGE: Realm.addChangeListener, RealmObject.addChangeListener and RealmResults.addChangeListener hold a strong reference to the listener, you should unregister the listener to avoid memory leaks.\n* BREAKING CHANGE: Removed deprecated methods RealmQuery.minimum{Int,Float,Double}, RealmQuery.maximum{Int,Float,Double}, RealmQuery.sum{Int,Float,Double} and RealmQuery.average{Int,Float,Double}. Use RealmQuery.min(), RealmQuery.max(), RealmQuery.sum() and RealmQuery.average() instead.\n* BREAKING CHANGE: Removed RealmConfiguration.getSchemaMediator() which is public by mistake. And RealmConfiguration.getRealmObjectClasses() is added as an alternative in order to obtain the set of model classes (#1797).\n* BREAKING CHANGE: Realm.addChangeListener, RealmObject.addChangeListener and RealmResults.addChangeListener will throw an IllegalStateException when invoked on a non-Looper thread. This is to prevent registering listeners that will not be invoked.\n* BREAKING CHANGE: trying to access a property on an unloaded RealmObject obtained asynchronously will throw an IllegalStateException\n* Added new Dynamic API using DynamicRealm and DynamicRealmObject.\n* Added Realm.getSchema() and DynamicRealm.getSchema().\n* Realm.createOrUpdateObjectFromJson() now works correctly if the RealmObject class contains a primary key (#1777).\n* Realm.compactRealm() doesn't throw an exception if the Realm file is opened. It just returns false instead.\n* Updated Realm Core to 0.95.3.\n  - Fixed a bug where RealmQuery.average(String) returned a wrong value for a nullable Long/Integer/Short/Byte field (#1803).\n  - Fixed a bug where RealmQuery.average(String) wrongly counted the null value for average calculation (#1854).\n\n## 0.85.1 (2015-11-23)\n* Fixed a bug which could corrupt primary key information when updating from a Realm version <= 0.84.1 (#1775).\n\n## 0.85.0 (2016-11-19)\n* BREAKING CHANGE: Removed RealmEncryptionNotSupportedException since the encryption implementation changed in Realm's underlying storage engine. Encryption is now supported on all devices.\n* BREAKING CHANGE: Realm.executeTransaction() now directly throws any RuntimeException instead of wrapping it in a RealmException (#1682).\n* BREAKING CHANGE: RealmQuery.isNull() and RealmQuery.isNotNull() now throw IllegalArgumentException instead of RealmError if the fieldname is a linked field and the last element is a link (#1693).\n* Added Realm.isEmpty().\n* Setters in managed object for RealmObject and RealmList now throw IllegalArgumentException if the value contains an invalid (unmanaged, removed, closed, from different Realm) object (#1749).\n* Attempting to refresh a Realm while a transaction is in process will now throw an IllegalStateException (#1712).\n* The Realm AAR now also contains the ProGuard configuration (#1767). (Thank you @skyisle.)\n* Updated Realm Core to 0.95.\n  - Removed reliance on POSIX signals when using encryption.\n\n## 0.84.2\n* Fixed a bug making it impossible to convert a field to become required during a migration (#1695).\n* Fixed a bug making it impossible to read Realms created using primary keys and created by iOS (#1703).\n* Fixed some memory leaks when an Exception is thrown (#1730).\n* Fixed a memory leak when using relationships (#1285).\n* Fixed a bug causing cached column indices to be cleared too soon (#1732).\n\n## 0.84.1 (2015-10-28)\n* Updated Realm Core to 0.94.4.\n  - Fixed a bug that could cause a crash when running the same query multiple times.\n* Updated ProGuard configuration. See [documentation](https://realm.io/docs/java/latest/#proguard) for more details.\n* Updated Kotlin example to use 1.0.0-beta.\n* Fixed warnings reported by \"lint -Xlint:all\" (#1644).\n* Fixed a bug where simultaneous opening and closing a Realm from different threads might result in a NullPointerException (#1646).\n* Fixed a bug which made it possible to externally modify the encryption key in a RealmConfiguration (#1678).\n\n## 0.84.0 (2015-10-22)\n* Added support for async queries and transactions.\n* Added support for parsing JSON Dates with timezone information. (Thank you @LateralKevin.)\n* Added RealmQuery.isEmpty().\n* Added Realm.isClosed() method.\n* Added Realm.distinct() method.\n* Added RealmQuery.isValid(), RealmResults.isValid() and RealmList.isValid(). Each method checks whether the instance is still valid to use or not(for example, the Realm has been closed or any parent object has been removed).\n* Added Realm.isInTransaction() method.\n* Updated Realm Core to version 0.94.3.\n  - Fallback for mremap() now work correctly on BlackBerry devices.\n* Following methods in managed RealmList now throw IllegalStateException instead of native crash when RealmList.isValid() returns false: add(int,RealmObject), add(RealmObject)\n* Following methods in managed RealmList now throw IllegalStateException instead of ArrayIndexOutOfBoundsException when RealmList.isValid() returns false: set(int,RealmObject), move(int,int), remove(int), get(int)\n* Following methods in managed RealmList now throw IllegalStateException instead of returning 0/null when RealmList.isValid() returns false: clear(), removeAll(Collection), remove(RealmObject), first(), last(), size(), where()\n* RealmPrimaryKeyConstraintException is now thrown instead of RealmException if two objects with same primary key are inserted.\n* IllegalStateException is now thrown when calling Realm's clear(), RealmResults's remove(), removeLast(), clear() or RealmObject's removeFromRealm() from an incorrect thread.\n* Fixed a bug affecting RealmConfiguration.equals().\n* Fixed a bug in RealmQuery.isNotNull() which produced wrong results for binary data.\n* Fixed a bug in RealmQuery.isNull() and RealmQuery.isNotNull() which validated the query prematurely.\n* Fixed a bug where closed Realms were trying to refresh themselves resulting in a NullPointerException.\n* Fixed a bug that made it possible to migrate open Realms, which could cause undefined behavior when querying, reading or writing data.\n* Fixed a bug causing column indices to be wrong for some edge cases. See #1611 for details.\n\n## 0.83.1 (2015-10-15)\n* Updated Realm Core to version 0.94.1.\n  - Fixed a bug when using Realm.compactRealm() which could make it impossible to open the Realm file again.\n  - Fixed a bug, so isNull link queries now always return true if any part is null.\n\n## 0.83 (2015-10-08)\n* BREAKING CHANGE: Database file format update. The Realm file created by this version cannot be used by previous versions of Realm.\n* BREAKING CHANGE: Removed deprecated methods and constructors from the Realm class.\n* BREAKING CHANGE: Introduced boxed types Boolean, Byte, Short, Integer, Long, Float and Double. Added null support. Introduced annotation @Required to indicate a field is not nullable. String, Date and byte[] became nullable by default which means a RealmMigrationNeededException will be thrown if an previous version of a Realm file is opened.\n* Deprecated methods: RealmQuery.minimum{Int,Float,Double}, RealmQuery.maximum{Int,Float,Double}. Use RealmQuery.min() and RealmQuery.max() instead.\n* Added support for x86_64.\n* Fixed an issue where opening the same Realm file on two Looper threads could potentially lead to an IllegalStateException being thrown.\n* Fixed an issue preventing the call of listeners on refresh().\n* Opening a Realm file from one thread will no longer be blocked by a transaction from another thread.\n* Range restrictions of Date fields have been removed. Date fields now accepts any value. Milliseconds are still removed.\n\n## 0.82.2 (2015-09-04)\n* Fixed a bug which might cause failure when loading the native library.\n* Fixed a bug which might trigger a timeout in Context.finalize().\n* Fixed a bug which might cause RealmObject.isValid() to throw an exception if the object is deleted.\n* Updated Realm core to version 0.89.9\n  - Fixed a potential stack overflow issue which might cause a crash when encryption was used.\n  - Embedded crypto functions into Realm dynamic lib to avoid random issues on some devices.\n  - Throw RealmEncryptionNotSupportedException if the device doesn't support Realm encryption. At least one device type (HTC One X) contains system bugs that prevents Realm's encryption from functioning properly. This is now detected, and an exception is thrown when trying to open/create an encrypted Realm file. It's up to the application to catch this and decide if it's OK to proceed without encryption instead.\n\n## 0.82.1 (2015-08-06)\n* Fixed a bug where using the wrong encryption key first caused the right key to be seen as invalid.\n* Fixed a bug where String fields were ignored when updating objects from JSON with null values.\n* Fixed a bug when calling System.exit(0), the process might hang.\n\n## 0.82 (2015-07-28)\n* BREAKING CHANGE: Fields with annotation @PrimaryKey are indexed automatically now. Older schemas require a migration.\n* RealmConfiguration.setModules() now accept ignore null values which Realm.getDefaultModule() might return.\n* Trying to access a deleted Realm object throw throws a proper IllegalStateException.\n* Added in-memory Realm support.\n* Closing realm on another thread different from where it was created now throws an exception.\n* Realm will now throw a RealmError when Realm's underlying storage engine encounters an unrecoverable error.\n* @Index annotation can also be applied to byte/short/int/long/boolean/Date now.\n* Fixed a bug where RealmQuery objects are prematurely garbage collected.\n* Removed RealmQuery.between() for link queries.\n\n## 0.81.1 (2015-06-22)\n* Fixed memory leak causing Realm to never release Realm objects.\n\n## 0.81 (2015-06-19)\n* Introduced RealmModules for working with custom schemas in libraries and apps.\n* Introduced Realm.getDefaultInstance(), Realm.setDefaultInstance(RealmConfiguration) and Realm.getInstance(RealmConfiguration).\n* Deprecated most constructors. They have been been replaced by Realm.getInstance(RealmConfiguration) and Realm.getDefaultInstance().\n* Deprecated Realm.migrateRealmAtPath(). It has been replaced by Realm.migrateRealm(RealmConfiguration).\n* Deprecated Realm.deleteFile(). It has been replaced by Realm.deleteRealm(RealmConfiguration).\n* Deprecated Realm.compactFile(). It has been replaced by Realm.compactRealm(RealmConfiguration).\n* RealmList.add(), RealmList.addAt() and RealmList.set() now copy unmanaged objects transparently into Realm.\n* Realm now works with Kotlin (M12+). (Thank you @cypressious.)\n* Fixed a performance regression introduced in 0.80.3 occurring during the validation of the Realm schema.\n* Added a check to give a better error message when null is used as value for a primary key.\n* Fixed unchecked cast warnings when building with Realm.\n* Cleaned up examples (remove old test project).\n* Added checking for missing generic type in RealmList fields in annotation processor.\n\n## 0.80.3 (2015-05-22)\n* Calling Realm.copyToRealmOrUpdate() with an object with a null primary key now throws a proper exception.\n* Fixed a bug making it impossible to open Realms created by Realm-Cocoa if a model had a primary key defined.\n* Trying to using Realm.copyToRealmOrUpdate() with an object with a null primary key now throws a proper exception.\n* RealmChangedListener now also gets called on the same thread that did the commit.\n* Fixed bug where Realm.createOrUpdateWithJson() reset Date and Binary data to default values if not found in the JSON output.\n* Fixed a memory leak when using RealmBaseAdapter.\n* RealmBaseAdapter now allow RealmResults to be null. (Thanks @zaki50.)\n* Fixed a bug where a change to a model class (`RealmList<A>` to `RealmList<B>`) would not throw a RealmMigrationNeededException.\n* Fixed a bug where setting multiple RealmLists didn't remove the previously added objects.\n* Solved ConcurrentModificationException thrown when addChangeListener/removeChangeListener got called in the onChange. (Thanks @beeender)\n* Fixed duplicated listeners in the same realm instance. Trying to add duplicated listeners is ignored now. (Thanks @beeender)\n\n## 0.80.2 (2015-05-04)\n* Trying to use Realm.copyToRealmOrUpdate() with an object with a null primary key now throws a proper exception.\n* RealmMigrationNeedException can now return the path to the Realm that needs to be migrated.\n* Fixed bug where creating a Realm instance with a hashcode collision no longer returned the wrong Realm instance.\n* Updated Realm Core to version 0.89.2\n  - fixed bug causing a crash when opening an encrypted Realm file on ARM64 devices.\n\n## 0.80.1 (2015-04-16)\n* Realm.createOrUpdateWithJson() no longer resets fields to their default value if they are not found in the JSON input.\n* Realm.compactRealmFile() now uses Realm Core's compact() method which is more failure resilient.\n* Realm.copyToRealm() now correctly handles referenced child objects that are already in the Realm.\n* The ARM64 binary is now properly a part of the Eclipse distribution package.\n* A RealmMigrationExceptionNeeded is now properly thrown if @Index and @PrimaryKey are not set correctly during a migration.\n* Fixed bug causing Realms to be cached even though they failed to open correctly.\n* Added Realm.deleteRealmFile(File) method.\n* Fixed bug causing queries to fail if multiple Realms has different field ordering.\n* Fixed bug when using Realm.copyToRealm() with a primary key could crash if default value was already used in the Realm.\n* Updated Realm Core to version 0.89.0\n  - Improved performance for sorting RealmResults.\n  - Improved performance for refreshing a Realm after inserting or modifying strings or binary data.\n  - Fixed bug causing incorrect result when querying indexed fields.\n  - Fixed bug causing corruption of string index when deleting an object where there are duplicate values for the indexed field.\n  - Fixed bug causing a crash after compacting the Realm file.\n* Added RealmQuery.isNull() and RealmQuery.isNotNull() for querying relationships.\n* Fixed a potential NPE in the RealmList constructor.\n\n## 0.80 (2015-03-11)\n* Queries on relationships can be case sensitive.\n* Fixed bug when importing JSONObjects containing NULL values.\n* Fixed crash when trying to remove last element of a RealmList.\n* Fixed bug crashing annotation processor when using \"name\" in model classes for RealmObject references\n* Fixed problem occurring when opening an encrypted Realm with two different instances of the same key.\n* Version checker no longer reports that updates are available when latest version is used.\n* Added support for static fields in RealmObjects.\n* Realm.writeEncryptedCopyTo() has been reenabled.\n\n## 0.79.1 (2015-02-20)\n* copyToRealm() no longer crashes on cyclic data structures.\n* Fixed potential crash when using copyToRealmOrUpdate with an object graph containing a mix of elements with and without primary keys.\n\n## 0.79 (2015-02-16)\n* Added support for ARM64.\n* Added RealmQuery.not() to negate a query condition.\n* Added copyToRealmOrUpdate() and createOrUpdateFromJson() methods, that works for models with primary keys.\n* Made the native libraries much smaller. Arm went from 1.8MB to 800KB.\n* Better error reporting when trying to create or open a Realm file fails.\n* Improved error reporting in case of missing accessors in model classes.\n* Re-enabled RealmResults.remove(index) and RealmResults.removeLast().\n* Primary keys are now supported through the @PrimaryKey annotation.\n* Fixed error when instantiating a Realm with the wrong key.\n* Throw an exception if deleteRealmFile() is called when there is an open instance of the Realm.\n* Made migrations and compression methods synchronised.\n* Removed methods deprecated in 0.76. Now Realm.allObjectsSorted() and RealmQuery.findAllSorted() need to be used instead.\n* Reimplemented Realm.allObjectSorted() for better performance.\n\n## 0.78 (2015-01-22)\n* Added proper support for encryption. Encryption support is now included by default. Keys are now 64 bytes long.\n* Added support to write an encrypted copy of a Realm.\n* Realm no longer incorrectly warns that an instance has been closed too many times.\n* Realm now shows a log warning if an instance is being finalized without being closed.\n* Fixed bug causing Realms to be cached during a RealmMigration resulting in invalid realms being returned from Realm.getInstance().\n* Updated core to 0.88.\n\n## 0.77 (2015-01-16)\n* Added Realm.allObjectsSorted() and RealmQuery.findAllSorted() and extending RealmResults.sort() for multi-field sorting.\n* Added more logging capabilities at the JNI level.\n* Added proper encryption support. NOTE: The key has been increased from 32 bytes to 64 bytes (see example).\n* Added support for unmanaged objects and custom constructors.\n* Added more precise imports in proxy classes to avoid ambiguous references.\n* Added support for executing a transaction with a closure using Realm.executeTransaction().\n* Added RealmObject.isValid() to test if an object is still accessible.\n* RealmResults.sort() now has better error reporting.\n* Fixed bug when doing queries on the elements of a RealmList, ie. like Realm.where(Foo.class).getBars().where().equalTo(\"name\").\n* Fixed bug causing refresh() to be called on background threads with closed Realms.\n* Fixed bug where calling Realm.close() too many times could result in Realm not getting closed at all. This now triggers a log warning.\n* Throw NoSuchMethodError when RealmResults.indexOf() is called, since it's not implemented yet.\n* Improved handling of empty model classes in the annotation processor\n* Removed deprecated static constructors.\n* Introduced new static constructors based on File instead of Context, allowing to save Realm files in custom locations.\n* RealmList.remove() now properly returns the removed object.\n* Calling realm.close() no longer prevent updates to other open realm instances on the same thread.\n\n## 0.76.0 (2014-12-19)\n* RealmObjects can now be imported using JSON.\n* Gradle wrapper updated to support Android Studio 1.0.\n* Fixed bug in RealmObject.equals() so it now correctly compares two objects from the same Realm.\n* Fixed bug in Realm crashing for receiving notifications after close().\n* Realm class is now marked as final.\n* Replaced concurrency example with a better thread example.\n* Allowed to add/remove RealmChangeListeners in RealmChangeListeners.\n* Upgraded to core 0.87.0 (encryption support, API changes).\n* Close the Realm instance after migrations.\n* Added a check to deny the writing of objects outside of a transaction.\n\n## 0.75.1 (2014-12-03)\n* Changed sort to be an in-place method.\n* Renamed SORT_ORDER_DECENDING to SORT_ORDER_DESCENDING.\n* Added sorting functionality to allObjects() and findAll().\n* Fixed bug when querying a date column with equalTo(), it would act as lessThan()\n\n## 0.75.0 (2014-11-28)\n* Realm now implements Closeable, allowing better cleanup of native resources.\n* Added writeCopyTo() and compactRealmFile() to write and compact a Realm to a new file.\n* RealmObject.toString(), equals() and hashCode() now support models with cyclic references.\n* RealmResults.iterator() and listIterator() now correctly iterates the results when using remove().\n* Bug fixed in Exception text when field names was not matching the database.\n* Bug fixed so Realm no longer throws an Exception when removing the last object.\n* Bug fixed in RealmResults which prevented sub-querying.\n* The Date type does not support millisecond resolution, and dates before 1901-12-13 and dates after 2038-01-19 are not supported on 32 bit systems.\n* Fixed bug so Realm no longer throws an Exception when removing the last object.\n* Fixed bug in RealmResults which prevented sub-querying.\n\n## 0.74.0 (2014-11-19)\n* Added support for more field/accessors naming conventions.\n* Added case sensitive versions of string comparison operators equalTo and notEqualTo.\n* Added where() to RealmList to initiate queries.\n* Added verification of fields names in queries with links.\n* Added exception for queries with invalid field name.\n* Allow static methods in model classes.\n* An exception will now be thrown if you try to move Realm, RealmResults or RealmObject between threads.\n* Fixed a bug in the calculation of the maximum of date field in a RealmResults.\n* Updated core to 0.86.0, fixing a bug in cancelling an empty transaction, and major query speedups with floats/doubles.\n* Consistent handling of UTF-8 strings.\n* removeFromRealm() now calls moveLastOver() which is faster and more reliable when deleting multiple objects.\n\n## 0.73.1 (2014-11-05)\n* Fixed a bug that would send infinite notifications in some instances.\n\n## 0.73.0 (2014-11-04)\n* Fixed a bug not allowing queries with more than 1024 conditions.\n* Rewritten the notification system. The API did not change but it's now much more reliable.\n* Added support for switching auto-refresh on and off (Realm.setAutoRefresh).\n* Added RealmBaseAdapter and an example using it.\n* Added deleteFromRealm() method to RealmObject.\n\n## 0.72.0 (2014-10-27)\n* Extended sorting support to more types: boolean, byte, short, int, long, float, double, Date, and String fields are now supported.\n* Better support for Java 7 and 8 in the annotations processor.\n* Better support for the Eclipse annotations processor.\n* Added Eclipse support to the distribution folder.\n* Added Realm.cancelTransaction() to cancel/abort/rollback a transaction.\n* Added support for link queries in the form realm.where(Owner.class).equalTo(\"cat.age\", 12).findAll().\n* Faster implementation of RealmQuery.findFirst().\n* Upgraded core to 0.85.1 (deep copying of strings in queries; preparation for link queries).\n\n## 0.71.0 (2014-10-07)\n* Simplified the release artifact to a single Jar file.\n* Added support for Eclipse.\n* Added support for deploying to Maven.\n* Throw exception if nested transactions are used (it's not allowed).\n* Javadoc updated.\n* Fixed [bug in RealmResults](https://github.com/realm/realm-java/issues/453).\n* New annotation @Index to add search index to a field (currently only supporting String fields).\n* Made the annotations processor more verbose and strict.\n* Added RealmQuery.count() method.\n* Added a new example about concurrency.\n* Upgraded to core 0.84.0.\n\n## 0.70.1 (2014-09-30)\n* Enabled unit testing for the realm project.\n* Fixed handling of camel-cased field names.\n\n## 0.70.0 (2014-09-29)\n* This is the first public beta release.\n"
  },
  {
    "path": "CONTRIBUTING.md",
    "content": "# Contributing\n\n## Filing Issues\n\nWhether you find a bug, typo or an API call that could be clarified, please [file an issue](https://github.com/realm/realm-java/issues) on our GitHub repository.\n\nWhen filing an issue, please provide as much of the following information as possible in order to help us fix it:\n\n1. **Goals**\n2. **Expected results**\n3. **Actual results**\n4. **Steps to reproduce**\n5. **Code sample that highlights the issue** (link to full Android Studio projects that we can compile ourselves are ideal)\n6. **Version of Realm/Android Studio/OS**\n\nIf you'd like to send us sensitive sample code to help troubleshoot your issue, you can email <help@realm.io> directly.\n\n## Contributing Enhancements\n\nWe love contributions to Realm! If you'd like to contribute code, documentation, or any other improvements, please [file a Pull Request](https://github.com/realm/realm-java/pulls) on our GitHub repository. Make sure to accept our [CLA](#CLA)!\n\n### CLA\n\nRealm welcomes all contributions! The only requirement we have is that, like many other projects, we need to have a [Contributor License Agreement](https://en.wikipedia.org/wiki/Contributor_License_Agreement) (CLA) in place before we can accept any external code. Our own CLA is a modified version of the Apache Software Foundation’s CLA.\n\n[Please submit your CLA electronically using our Google form](https://docs.google.com/forms/d/e/1FAIpQLSeQ9ROFaTu9pyrmPhXc-dEnLD84DbLuT_-tPNZDOL9J10tOKQ/viewform) so we can accept your submissions. The GitHub username you file there will need to match that of your Pull Requests. If you have any questions or cannot file the CLA electronically, you can email <help@realm.io>.\n\n## Repository Guidelines\n\n### Code Style\n\nWhile we havn't described our code style yet, please just follow the existing style you see in the files you change.\n\nFor source code written in C++, we format it using `clang-format`. You can use the [plugin](https://plugins.jetbrains.com/plugin/8396-clangformatij): mark the entire file and right-click to execute `clang-format` before committing any changes. Of course, if you don't use Android Studio to edit C++ code, run `clang-format` on the command-line.\n\n### Nullability by Annotataion\n\nTo improve code quality and usability in Kotlin, nullability of parameters and return types must be annotated with JSR305 annotations.\n\nIf a parameter is nullable, you must add `@Nullable` annotation to the parameter. On the other hand, if a parameter is non-null, you don't need to add `@Nonnull` annotation since all parameters are treated as `@Nonnull` by default.\n\nFor return types, there is no default nullability. If a method can return `null` as a return value, you must add `@Nullable` annotation to the return type. Currently, `Nonnull` annotation is not mandatory if the method never return `null`.\n\nWhen you add a new package, you must add `package-info.java` and add `@javax.annotation.ParametersAreNonnullByDefault` to the package. Please note that you can't add multiple `package-info.java` in the same package but different location (for example, main and androidTest). When you add a package to both main and androidTest, you only need to add `package-info.java` to main.\n\n### Unit Tests\n\nAll PR's must be accompanied by related unit tests. All bug fixes must have a unit test proving that the bug is fixed.\nYou can use `./realm/gradlew connectedCheck createDebugCoverageReport` to generate a coverage report to check for \nmissing unit test coverage. The aim is 100% code coverage.\n\nWhen writing unit tests, use the following guide lines:\n\n1) Unit tests must be written using JUnit4.\n\n2) All tests for a class should be grouped in a class called `<className>Tests`, unless the functionality is cross-\n   cutting like [`RxJavaTests`](https://github.com/realm/realm-java/blob/master/realm/realm-library/src/androidTest/java/io/realm/RxJavaTests.java) \n   or [`RealmAsyncQueryTests`](https://github.com/realm/realm-java/blob/master/realm/realm-library/src/androidTest/java/io/realm/RealmAsyncQueryTests.java).\n\n3) Test methods should use camelCase and underscore `_` between logical sections to increase method name readability. \n   Methods should ideally start with the name of the method being tested. Patterns like: `<methodName>_<description>`, \n   `<methodName>_<param>_<description>` or `<description>` are encouraged.\n   \n4) All unit tests creating Realms must do so using the [`TestRealmConfigurationFactory`](https://github.com/realm/realm-java/blob/master/realm/realm-library/src/androidTest/java/io/realm/rule/TestRealmConfigurationFactory.java) \n   or [`RunInLooperThread`](https://github.com/realm/realm-java/blob/master/realm/realm-library/src/androidTest/java/io/realm/rule/RunInLooperThread.java) \n   test rules. This ensures that all Realms are properly closed and deleted between each test.\n\n5) Use the `@RunInLooperThread` rule for any test that depends on Realms notification system. \n\n6) Input-parameters should be boundary tested. Especially `Null/NotNull`, but also the state of Realm objects like\n   unmanaged objects, deleted objects, objects from other threads.\n\n7) Unit tests are not required to only have 1 test. It is acceptable to combine multiple tests into one unit test, but\n   if it fails, it should be clear why it failed. E.g. you can group related tests with the same setup like negative \n   tests. If you do so, make sure to separate each \"subtest\" with a comment stating what you test.\n\n8) Use only `@Test(expected = xxx.class)` if the test case contains one line. If the test contains multiple \n   lines and it is the last line that is tested, use the `ExceptedException` rule instead. In all other cases, use \n   the following pattern:\n   \n    try {\n      somethingThatThrowsIllegalArgument();   \n    } catch (IllegalArgumentException ignored) {\n    }\n\n9) Use comments to make the intent of the unit test easily understandable at a glance. A simple one line comment is \n   often easier to read `thanALongCamelCasedSentenceThatAttemptsToDescribeWhatHappens`. Describe the test steps inside \n   the method, if it's not glaringly obvious.\n\nThis is an example of how a unit test class could look like:\n\n    @RunWith(AndroidJUnit4.class)\n    public class RealmTests {\n    \n      @Rule\n      public final TestRealmConfigurationFactory configFactory = new TestRealmConfigurationFactory();\n    \n      @Rule\n      public final RunInLooperThread looperThread = new RunInLooperThread();\n    \n      private Realm realm;   \n    \n      @Before\n      public void setUp() {\n         RealmConfiguration config = configFactory.createConfiguration();\n         realm = Realm.getInstance(config);\n      }\n      \n      @After\n      public void tearDown() {\n        if (realm != null) {\n            realm.close();\n        }  \n      }\n    \n      @Test(expected = IllegalStateException.class)\n      public void createObject_outsideTransaction() {\n        realm.createObject(Foo.class);\n      }\n    \n      @Test\n      public void createObject_illegalInput {\n        // Class not part of the schema\n        try {\n          realm.createObject(Foo.class);    \n        } catch (IllegalArgumentException ignored) {\n        }\n    \n        // Null class\n        try {\n            realm.createObject(null);    \n        } catch (IllegalArgumentException ignored) {\n        }\n      }\n      \n      @Test\n      @RunTestInLooperThread\n      public void addChangeListener_notifiedOnLocalCommit() {\n        realm.addChangeListener(new RealmChangeListener() {\n            @Override\n            public void onChange() {\n                assert(1, realm.allObjects(Foo.class).size());\n                looperThread.testComplete();\n            }\n        });\n    \n        realm.beginTransaction();\n        realm.createObject(Foo.class);\n        realm.commitTransaction();\n      }\n    }\n  \n### Javadoc\n\nAll public classes and methods must have Javadoc describing their purpose.\n\n```java\n/**\n * Checks if given field is equal to the provided value. \n *\n * <pre>\n * {@code\n *   // A multi-line code sample should be formatted like this.\n *   // Please wrap the code element in a <pre> tag.\n * }\n * </pre>\n *\n * @param fieldName the field to compare.\n * @param fieldValue the value to compare with.\n * @param caseSensitive if {@code true}, substring matching is case sensitive. Setting this to {@code false} works for English locale characters only.\n * @param caseSensitive if true, substring matching is case sensitive. Setting this to false only works for English\n *                      locale characters.\n * @return the query object.\n * @throws java.lang.IllegalArgumentException if one or more arguments do not match class or field type.\n * @throws IllegalArgumentException if field name doesn't exists, it doesn't contain a list of links or the type\n * of the object represented by the DynamicRealmObject doesn't match.\n * @deprecated Please use {@link #average(String)} instead.\n * @see #endGroup()\n */\npublic RealmQuery<E> equalTo(String fieldName, String fieldValue, boolean caseSensitive) {\n  // ...\n}\n```\n\n* Method descriptions begin with a verb phrase, e.g. \"Checks\" instead of \"Check\". \n* Capitalize the first letter of the method and @deprecated descriptions. Everything else starts with lower case.\n* Empty line between method description and the rest.\n* End all descriptions with a period `.` (except @see).\n* Reference other Realm classes using `{@link ...}`.\n* Wrap Java values in `{@code ...}`.\n* @throws description must start with \"if\".\n* Never list generic exceptions like `RuntimeException`, `Exception` or `Error`. Always reference the specific error.\n* Line-length maximum is 120 chars. Parameter descriptions that go above this, should be split into multiple lines and indented. Otherwise do not use indentation (contrary to Oracle guidelines).\n\nAbove is based on the official guidelines from Oracle regarding Javadoc: http://www.oracle.com/technetwork/articles/java/index-137868.html\n\n### Branch Strategy\n\nWe have two branches for shared development: `master` and `releases`. We make releases from each.\n\n`master`:\n\n* The `master` branch is where major/minor versions are released from.\n* It is for new features and/or breaking changes.\n\n`releases`:\n\n* The releases branch is where patch versions are released from.\n* It is mainly for bug fixes.\n* Every commit is automatically merged to `master`.\n* Minor changes (e.g. to documentation, tests, and the build system) may not affect end users but should still be merged to `releases` to avoid diverging too far from `master` and to reduce the likelihood of merge conflicts.\n\n"
  },
  {
    "path": "Dockerfile",
    "content": "FROM ubuntu:22.04\n\n# Locales\nRUN apt-get clean && apt-get -y update && apt-get install -y locales && locale-gen en_US.UTF-8\nENV LANG \"en_US.UTF-8\"\nENV LANGUAGE \"en_US.UTF-8\"\nENV LC_ALL \"en_US.UTF-8\"\nENV TZ=Europe/Copenhagen\nRUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone\n\n# Set the environment variables\nENV JAVA_HOME /usr/lib/jvm/java-11-openjdk-amd64\nENV JAVA8_HOME /usr/lib/jvm/java-8-openjdk-amd64\nENV ANDROID_HOME /opt/android-sdk-linux\n# Need by cmake\nENV ANDROID_NDK_HOME /opt/android-ndk\nENV ANDROID_NDK /opt/android-ndk\nENV PATH ${PATH}:${ANDROID_HOME}/emulator:${ANDROID_HOME}/cmdline-tools/latest:${ANDROID_HOME}/cmdline-tools/latest/bin:${ANDROID_HOME}/platform-tools\nENV PATH ${PATH}:${NDK_HOME}\nENV NDK_CCACHE /usr/bin/ccache\nENV CCACHE_CPP2 yes\nENV REALM_DISABLE_ANALYTICS true\n\n# Keep the packages in alphabetical order to make it easy to avoid duplication\n# tzdata needs to be installed first. See https://askubuntu.com/questions/909277/avoiding-user-interaction-with-tzdata-when-installing-certbot-in-a-docker-contai\n# `file` is need by the Android Emulator\nRUN DEBIAN_FRONTEND=noninteractive \\\n    && apt-get update -qq \\\n    && apt-get install -y tzdata \\\n    && apt-get install -y \\\n                          bsdmainutils \\\n                          bridge-utils \\\n                          build-essential \\\n                          ccache \\\n                          curl \\\n                          file \\\n                          git \\\n                          jq \\\n                          libc6 \\\n                          libgcc1 \\\n                          libglu1 \\\n                          libncurses5 \\\n                          libstdc++6 \\\n                          libz1 \\\n                          libvirt-clients \\\n                          libvirt-daemon-system \\\n                          openjdk-11-jdk-headless \\\n                          openjdk-8-jdk-headless \\\n                          qemu-kvm \\\n                          s3cmd \\\n                          unzip \\\n                          virt-manager \\\n                          wget \\\n                          zip \\\n                          ninja-build \\\n    && apt-get clean\n\n# Install the Android SDK\n# See https://developer.android.com/studio/index.html#downloads for latest version\nRUN cd /opt && \\\n    wget -q https://dl.google.com/android/repository/commandlinetools-linux-8512546_latest.zip -O android-tools-linux.zip && \\\n    mkdir --parents ${ANDROID_HOME}/cmdline-tools/latest && \\\n    unzip android-tools-linux.zip -d ${ANDROID_HOME}/cmdline-tools/latest && \\\n    mv ${ANDROID_HOME}/cmdline-tools/latest/cmdline-tools/* ${ANDROID_HOME}/cmdline-tools/latest/ && \\\n    rm -f android-tools-linux.zip\n\n# Grab what's needed in the SDK\nRUN sdkmanager --update\n\n# Accept licenses before installing components, no need to echo y for each component\n# License is valid for all the standard components in versions installed from this file\n# Non-standard components: MIPS system images, preview versions, GDK (Google Glass) and Android Google TV require separate licenses, not accepted there\nRUN yes | sdkmanager --licenses\n\n# SDKs\n# The `yes` is for accepting all non-standard tool licenses.\n# Please keep all sections in descending order!\nRUN yes | sdkmanager \\\n    'build-tools;30.0.3' \\\n    'emulator' \\\n    'extras;android;m2repository' \\\n    'platforms;android-30' \\\n    'platform-tools' \\\n    'ndk;23.1.7779620' \\\n    'system-images;android-31;default;x86_64'\n\n# Make the SDK universally writable\nRUN chmod -R a+rwX ${ANDROID_HOME}\n\n# Ensure a new enough version of CMake is available.\nRUN cd /opt \\\n    && wget -nv https://cmake.org/files/v3.22/cmake-3.27.7-linux-x86_64.tar.gz \\\n    && tar zxf cmake-3.27.7-linux-x86_64.tar.gz\n\n# Workaround for https://issuetracker.google.com/issues/206099937\nRUN ln -s /usr/bin/ninja /opt/cmake-3.22.1-linux-x86_64/bin/ninja\n\nENV PATH \"/opt/cmake-3.27.7-linux-x86_64/bin:$PATH\"\n"
  },
  {
    "path": "Jenkinsfile",
    "content": "#!groovy\n\n@Library('realm-ci') _\n\nimport groovy.json.JsonOutput\n\n// CONSTANTS\n\n// Branches from which we release SNAPSHOT's. Only release branches need to run on actual hardware.\nreleaseBranches = ['main', 'next-major', 'support-new-datatypes', 'releases', 'release/transformer-api' ]\n// Branches that are \"important\", so if they do not compile they will generate a Slack notification\nslackNotificationBranches = [ 'main', 'releases', 'next-major', 'support-new-datatypes', 'release/transformer-api' ]\n// WARNING: Only set to `false` as an absolute last resort. Doing this will disable all integration\n// tests.\nenableIntegrationTests = true\n\n// RUNTIME PROPERTIES\n\n// Will store whether or not this build was successful.\nbuildSuccess = false\n// Will be set to `true` if this build is a full release that should be available on Maven Central.\n// This is determined by comparing the current git tag to the version number of the build.\npublishBuild = false\nmongoDbRealmContainer = null\nmongoDbRealmCommandServerContainer = null\nemulatorContainer = null\ndockerNetworkId = UUID.randomUUID().toString()\ncurrentBranch = (env.CHANGE_BRANCH == null) ? env.BRANCH_NAME : env.CHANGE_BRANCH\nisReleaseBranch = releaseBranches.contains(currentBranch)\n// FIXME: Always used the emulator until we can enable more reliable devices\n// 'android' nodes have android devices attached and 'brix' are physical machines in Copenhagen.\n// nodeSelector = (releaseBranches.contains(currentBranch)) ? 'android' : 'docker-cph-03' // Switch to `brix` when all CPH nodes work: https://jira.mongodb.org/browse/RCI-14\nnodeSelector = 'docker-cph-01'\ntry {\n  node(nodeSelector) {\n    timeout(time: 150, unit: 'MINUTES') {\n      // Allocate a custom workspace to avoid having % in the path (it breaks ld)\n      ws('/tmp/realm-java') {\n        stage('SCM') {\n          checkout([\n                  $class           : 'GitSCM',\n                  branches         : scm.branches,\n                  gitTool          : 'native git',\n                  extensions       : scm.extensions + [\n                          [$class: 'CleanCheckout'],\n                          [$class: 'SubmoduleOption', recursiveSubmodules: true]\n                  ],\n                  userRemoteConfigs: scm.userRemoteConfigs\n          ])\n        }\n\n        // Check type of Build. We are treating this as a release build if we are building\n        // the exact Git SHA that was tagged.\n        echo \"Building from branch: $currentBranch\"\n        gitTag = readGitTag()\n        echo \"Git tag: ${gitTag ?: 'none'}\"\n        if (!gitTag) {\n          gitSha = sh(returnStdout: true, script: 'git rev-parse HEAD').trim().take(8)\n          echo \"Building non-release: ${gitSha}\"\n          setBuildName(gitSha)\n          publishBuild = false\n        } else {\n          def version = readFile('version.txt').trim()\n          if (gitTag != \"v${version}\") {\n            error \"Git tag '${gitTag}' does not match v${version}\"\n          } else {\n            echo \"Building release: '${gitTag}'\"\n            setBuildName(\"Tag ${gitTag}\")\n            sh \"\"\"\n              set +x\n              sh tools/publish_release.sh verify\n            \"\"\"\n            publishBuild = true\n          }\n        }\n\n        // Toggles for PR vs. Master builds.\n        // - For PR's, we favor speed > absolute correctness. So we just build for x86, use an\n        //   emulator and run unit tests for the ObjectServer variant.\n        // - For branches from which we make releases, we build all architectures and run tests\n        //   on an actual device.\n        def useEmulator = false\n        def emulatorImage = \"\"\n        def buildFlags = \"\"\n        def instrumentationTestTarget = \"connectedAndroidTest\"\n        def deviceSerial = \"\"\n\n        if (!isReleaseBranch) {\n          // Build development branch\n          useEmulator = true\n          emulatorImage = \"system-images;android-31;default;x86_64\"\n          // Build core from source instead of doing it from binary\n          buildFlags = \"-PbuildTargetABIs=x86_64 -PenableLTO=false -PbuildCore=true\"\n          instrumentationTestTarget = \"connectedObjectServerDebugAndroidTest\"\n          deviceSerial = \"emulator-5554\"\n        } else {\n          // Build main/release branch\n          // FIXME: Use emulator until we can get reliable devices on CI.\n          //  But still build all ABI's and run all types of tests.\n          useEmulator = true\n          emulatorImage = \"system-images;android-31;default;x86_64\"\n          buildFlags = \"-PenableLTO=true -PbuildCore=true\"\n          instrumentationTestTarget = \"connectedAndroidTest\"\n          deviceSerial = \"emulator-5554\"\n        }\n\n        try {\n\n          def buildEnv = null\n          stage('Prepare Docker Images') {\n            // TODO Caching is currently disabled (with -do-not-cache suffix) due to the upload speed\n            //  in Copenhagen being too slow. So the upload times out.\n            buildEnv = buildDockerEnv(\"ci/realm-java:main\", push: currentBranch == 'main-do-not-cache')\n            def props = readProperties file: 'dependencies.list'\n            echo \"Version in dependencies.list: ${props.MONGODB_REALM_SERVER}\"\n            def mdbRealmImage = docker.image(\"docker.pkg.github.com/realm/ci/mongodb-realm-test-server:${props.MONGODB_REALM_SERVER}\")\n            docker.withRegistry('https://docker.pkg.github.com', 'github-packages-token') {\n              mdbRealmImage.pull()\n            }\n            def commandServerEnv = docker.build 'mongodb-realm-command-server', \"tools/sync_test_server\"\n\n            // Prepare Docker containers used by Instrumentation tests\n            // TODO: How much of this logic can be moved to start_server.sh for shared logic with local testing.\n            withCredentials([\n                    [$class: 'AmazonWebServicesCredentialsBinding', credentialsId: 'realm-kotlin-baas-aws-credentials', accessKeyVariable: 'BAAS_AWS_ACCESS_KEY_ID', secretKeyVariable: 'BAAS_AWS_SECRET_ACCESS_KEY']\n            ]) {\n              def tempDir = runCommand('mktemp -d -t app_config.XXXXXXXXXX')\n              sh \"tools/sync_test_server/app_config_generator.sh ${tempDir} tools/sync_test_server/app_template partition auto testapp1\"\n              sh \"tools/sync_test_server/app_config_generator.sh ${tempDir} tools/sync_test_server/app_template partition email testapp2\"\n              sh \"tools/sync_test_server/app_config_generator.sh ${tempDir} tools/sync_test_server/app_template flex function testapp3\"\n              sh \"docker network create ${dockerNetworkId}\"\n              mongoDbRealmContainer = mdbRealmImage.run(\"--network ${dockerNetworkId} -v$tempDir:/apps  -e AWS_ACCESS_KEY_ID='$BAAS_AWS_ACCESS_KEY_ID' -e AWS_SECRET_ACCESS_KEY='$BAAS_AWS_SECRET_ACCESS_KEY'\")\n              mongoDbRealmCommandServerContainer = commandServerEnv.run(\"--network container:${mongoDbRealmContainer.id} -v$tempDir:/apps\")\n              sh \"timeout 60 sh -c \\\"while [[ ! -f $tempDir/testapp1/app_id || ! -f $tempDir/testapp2/app_id ]]; do echo 'Waiting for server to start'; sleep 1; done\\\"\"\n            }\n          }\n\n          // There is a chance that real devices are attached to the host, so if the emulator is\n          // running we need to make sure that ADB and tests targets the correct device.\n          String restrictDevice = \"\"\n          if (deviceSerial != null) {\n            restrictDevice = \"-e ANDROID_SERIAL=${deviceSerial} \"\n          }\n\n          buildEnv.inside(\"-e HOME=/tmp \" +\n                  \"-e _JAVA_OPTIONS=-Duser.home=/tmp \" +\n                  \"--privileged \" +\n                  \"-v /dev/kvm:/dev/kvm \" +\n                  \"-v /dev/bus/usb:/dev/bus/usb \" +\n                  \"-v ${env.HOME}/gradle-cache:/tmp/.gradle \" +\n                  \"-v ${env.HOME}/.android:/tmp/.android \" +\n                  \"-v ${env.HOME}/ccache:/tmp/.ccache \" +\n                  restrictDevice +\n                  \"-e REALM_CORE_DOWNLOAD_DIR=/tmp/.gradle \" +\n                  \"--network container:${mongoDbRealmContainer.id} \") {\n\n            // Lock required around all usages of Gradle as it isn't\n            // able to share its cache between builds.\n            lock(\"${env.NODE_NAME}-android\") {\n              if (useEmulator) {\n                // TODO: We should wait until the emulator is online. For now assume it starts fast enough\n                //  before the tests will run, since the library needs to build first.\n                sh \"\"\"yes '\\n' | avdmanager create avd -n CIEmulator -k '${emulatorImage}' --force\"\"\"\n                sh \"adb start-server\" // https://stackoverflow.com/questions/56198290/problems-with-adb-exe\n                // Need to go to ANDROID_HOME due to https://askubuntu.com/questions/1005944/emulator-avd-does-not-launch-the-virtual-device\n                sh \"cd \\$ANDROID_HOME/tools && emulator -avd CIEmulator -no-boot-anim -no-window -wipe-data -noaudio -partition-size 4096 -memory 1536 &\"\n                try {\n                  runBuild(buildFlags, instrumentationTestTarget)\n                } finally {\n                  sh \"adb emu kill\"\n                }\n              } else {\n                runBuild(buildFlags, instrumentationTestTarget)\n              }\n\n              // Release the library if needed\n              if (publishBuild) {\n                runPublish()\n              }\n            }\n          }\n        } finally {\n          // We assume that creating these containers and the docker network can be considered an atomic operation.\n          if (mongoDbRealmContainer != null && mongoDbRealmCommandServerContainer != null) {\n            archiveServerLogs(mongoDbRealmContainer.id, mongoDbRealmCommandServerContainer.id)\n            mongoDbRealmContainer.stop()\n            mongoDbRealmCommandServerContainer.stop()\n            sh \"docker network rm ${dockerNetworkId}\"\n          }\n          if (emulatorContainer != null) {\n            emulatorContainer.stop()\n          }\n        }\n      }\n    }\n    currentBuild.rawBuild.setResult(Result.SUCCESS)\n    buildSuccess = true\n  }\n} catch(Exception e) {\n  currentBuild.rawBuild.setResult(Result.FAILURE)\n  buildSuccess = false\n  throw e\n} finally {\n  if (slackNotificationBranches.contains(currentBranch)) {\n    node {\n      withCredentials([[$class: 'StringBinding', credentialsId: 'slack-webhook-java-ci-channel', variable: 'SLACK_URL']]) {\n        def payload = null\n        if (!buildSuccess) {\n          payload = JsonOutput.toJson([\n                  username: \"Realm CI\",\n                  icon_emoji: \":realm_new:\",\n                  text: \"*The ${currentBranch} branch is broken!*\\n<${env.BUILD_URL}|Click here> to check the build.\"\n          ])\n        } else if (currentBuild.getPreviousBuild() && currentBuild.getPreviousBuild().getResult().toString() != \"SUCCESS\" && buildSuccess) {\n          payload = JsonOutput.toJson([\n                  username: \"Realm CI\",\n                  icon_emoji: \":realm_new:\",\n                  text: \"*${currentBranch} is back to normal!*\\n<${env.BUILD_URL}|Click here> to check the build.\"\n          ])\n        }\n\n        if (payload != null) {\n          sh \"curl -X POST --data-urlencode \\'payload=${payload}\\' ${env.SLACK_URL}\"\n        }\n      }\n    }\n  }\n}\n\n// Runs all build steps\ndef runBuild(buildFlags, instrumentationTestTarget) {\n\n  stage('Build') {\n    withCredentials([\n            [$class: 'StringBinding', credentialsId: 'maven-central-java-ring-file', variable: 'SIGN_KEY'],\n            [$class: 'StringBinding', credentialsId: 'maven-central-java-ring-file-password', variable: 'SIGN_KEY_PASSWORD'],\n    ]) {\n      sh \"chmod +x gradlew\"\n      def signingFlags = \"\"\n      if (isReleaseBranch) {\n        signingFlags = \"-PsignBuild=true -PsignSecretRingFile=\\\"${SIGN_KEY}\\\" -PsignPassword=${SIGN_KEY_PASSWORD}\"\n      }\n      sh \"./gradlew assemble ${buildFlags} ${signingFlags} --stacktrace\"\n    }\n  }\n\n  stage('Tests') {\n    parallel 'JVM' : {\n      try {\n        sh \"chmod +x gradlew && ./gradlew check ${buildFlags} --stacktrace\"\n      } finally {\n        storeJunitResults 'realm/realm-annotations-processor/build/test-results/test/TEST-*.xml'\n        storeJunitResults 'examples/unitTestExample/build/test-results/**/TEST-*.xml'\n        storeJunitResults 'realm/realm-library/build/test-results/**/TEST-*.xml'\n        step([$class: 'LintPublisher'])\n      }\n    },\n    // FIXME https://github.com/realm/realm-java/issues/7593\n    // 'JVM8 introExample check' : {\n    //   // Force build with JVM8, by disabling the cache, and check introExample.\n    //   sh \"\"\"\n    //     cd examples/moduleExample\n    //     JAVA_HOME=\\$JAVA8_HOME ../gradlew check ${buildFlags} --stacktrace\n    //   \"\"\"\n    // },\n    'Realm Transformer' : {\n      try {\n        gradle('realm-transformer', 'check')\n      } finally {\n        storeJunitResults 'realm-transformer/build/test-results/test/TEST-*.xml'\n      }\n    },\n    // 'Static code analysis' : {\n    //   try {\n    //     gradle('realm', \"spotbugsMain pmd checkstyle ${buildFlags}\")\n    //   } finally {\n    //     publishHTML(target: [\n    //       allowMissing: false,\n    //       alwaysLinkToLastBuild: false,\n    //       keepAll: true,\n    //       reportDir: 'realm/realm-library/build/reports/spotbugs',\n    //       reportFiles: 'main.html',\n    //       reportName: 'Spotbugs report'\n    //     ])\n\n    //     publishHTML(target: [\n    //       allowMissing: false,\n    //       alwaysLinkToLastBuild: false,\n    //       keepAll: true,\n    //       reportDir: 'realm/realm-library/build/reports/pmd',\n    //       reportFiles: 'pmd.html',\n    //       reportName: 'PMD report'\n    //     ])\n\n    //     publishHTML(target: [\n    //       allowMissing: false,\n    //       alwaysLinkToLastBuild: false,\n    //       keepAll: true,\n    //       reportDir: 'realm/realm-library/build/reports/checkstyle',\n    //       reportFiles: 'checkstyle.html',\n    //       reportName: 'Checkstyle report'\n    //     ])\n    //   }\n    // },\n    'Gradle Plugin' : {\n      try {\n        gradle('gradle-plugin', 'check')\n      } finally {\n        storeJunitResults 'gradle-plugin/build/test-results/test/TEST-*.xml'\n      }\n    },\n    'JavaDoc': {\n      sh \"./gradlew javadoc ${buildFlags} --stacktrace\"\n    }\n  }\n\n  stage('Device Tests') {\n      if (enableIntegrationTests) {\n        String backgroundPid\n        try {\n          backgroundPid = startLogCatCollector()\n          forwardAdbPorts()\n          gradle('realm', \"${instrumentationTestTarget} ${buildFlags}\")\n          gradle('examples', \":unitTestExample:connectedDebugAndroidTest\")\n        } finally {\n          stopLogCatCollector(backgroundPid)\n          storeJunitResults 'realm/realm-library/build/outputs/androidTest-results/connected/**/TEST-*.xml'\n          storeJunitResults 'realm/kotlin-extensions/build/outputs/androidTest-results/connected/**/TEST-*.xml'\n        }\n      } else {\n        echo \"Instrumentation tests were disabled.\"\n      }\n  }\n\n\n  // TODO: add support for running monkey on the example apps\n\n  def collectMetrics = ['main'].contains(currentBranch)\n  echo \"Collecting metrics: $collectMetrics\"\n  if (collectMetrics) {\n    stage('Collect metrics') {\n      collectAarMetrics()\n    }\n  }\n\n  echo \"Releasing SNAPSHOT: ($isReleaseBranch, $publishBuild)\"\n  if (isReleaseBranch && !publishBuild) {\n    stage('Publish SNAPSHOT') {\n      withCredentials([[$class: 'UsernamePasswordMultiBinding', credentialsId: 'maven-central-credentials', passwordVariable: 'MAVEN_CENTRAL_PASSWORD', usernameVariable: 'MAVEN_CENTRAL_USER']]) {\n        sh \"chmod +x gradlew && ./gradlew mavenCentralUpload ${buildFlags} -PossrhUsername='$MAVEN_CENTRAL_USER' -PossrhPassword='$MAVEN_CENTRAL_PASSWORD' --stacktrace\"\n      }\n    }\n  }\n}\n\ndef runPublish() {\n  stage('Publish Release') {\n    withCredentials([\n            [$class: 'StringBinding', credentialsId: 'maven-central-java-ring-file', variable: 'SIGN_KEY'],\n            [$class: 'StringBinding', credentialsId: 'maven-central-java-ring-file-password', variable: 'SIGN_KEY_PASSWORD'],\n            [$class: 'StringBinding', credentialsId: 'slack-webhook-java-ci-channel', variable: 'SLACK_URL_CI'],\n            [$class: 'StringBinding', credentialsId: 'slack-webhook-releases-channel', variable: 'SLACK_URL_RELEASE'],\n            [$class: 'UsernamePasswordMultiBinding', credentialsId: 'maven-central-credentials', passwordVariable: 'MAVEN_CENTRAL_PASSWORD', usernameVariable: 'MAVEN_CENTRAL_USER'],\n            [$class: 'AmazonWebServicesCredentialsBinding', accessKeyVariable: 'DOCS_S3_ACCESS_KEY', credentialsId: 'mongodb-realm-docs-s3', secretKeyVariable: 'DOCS_S3_SECRET_KEY'],\n            [$class: 'AmazonWebServicesCredentialsBinding', accessKeyVariable: 'REALM_S3_ACCESS_KEY', credentialsId: 'tightdb-s3-ci', secretKeyVariable: 'REALM_S3_SECRET_KEY']\n    ]) {\n      // TODO Make sure that buildFlags and signingFlags are unified across builds\n      sh \"\"\"\n        set +x\n        sh tools/publish_release.sh '$MAVEN_CENTRAL_USER' '$MAVEN_CENTRAL_PASSWORD' \\\n        '$REALM_S3_ACCESS_KEY' '$REALM_S3_SECRET_KEY' \\\n        '$DOCS_S3_ACCESS_KEY' '$DOCS_S3_SECRET_KEY' \\\n        '$SLACK_URL_RELEASE' '$SLACK_URL_CI' \\\n        '-PsignBuild=true -PsignSecretRingFile=\"${SIGN_KEY}\" -PsignPassword=${SIGN_KEY_PASSWORD} -PenableLTO=true -PbuildCore=true'\n      \"\"\"\n    }\n  }\n}\n\n\ndef forwardAdbPorts() {\n  sh \"\"\" adb reverse tcp:9080 tcp:9080 && adb reverse tcp:9443 tcp:9443 &&\n      adb reverse tcp:8888 tcp:8888 && adb reverse tcp:9090 tcp:9090\n  \"\"\"\n}\n\nString startLogCatCollector() {\n  // Cancel build quickly if no device is available. The lock acquired already should\n  // ensure we have access to a device. If not, it is most likely a more severe problem.\n  timeout(time: 1, unit: 'MINUTES') {\n    // Need ADB as root to clear all buffers: https://stackoverflow.com/a/47686978/1389357\n    sh 'adb devices'\n    sh \"\"\"adb root\n      adb logcat -b all -c\n      adb logcat -v time > 'logcat.txt' &\n      echo \\$! > pid\n    \"\"\"\n    return readFile(\"pid\").trim()\n  }\n}\n\ndef stopLogCatCollector(String backgroundPid) {\n  // The pid might not be available if the build was terminated early or stopped due to\n  // a build error.\n  if (backgroundPid != null) {\n    sh \"kill ${backgroundPid}\"\n    zip([\n      'zipFile': 'logcat.zip',\n      'archive': true,\n      'glob' : 'logcat.txt'\n    ])\n    sh 'rm logcat.txt'\n  }\n}\n\ndef archiveServerLogs(String mongoDbRealmContainerId, String commandServerContainerId) {\n  sh \"docker logs ${commandServerContainerId} > ./command-server.log\"\n  zip([\n    'zipFile': 'command-server-log.zip',\n    'archive': true,\n    'glob' : 'command-server.log'\n  ])\n  sh 'rm command-server.log'\n\n  sh \"docker cp ${mongoDbRealmContainerId}:/var/log/stitch.log ./stitch.log\"\n  zip([\n    'zipFile': 'stitchlog.zip',\n    'archive': true,\n    'glob' : 'stitch.log'\n  ])\n  sh 'rm stitch.log'\n\n  sh \"docker cp ${mongoDbRealmContainerId}:/var/log/mongodb.log ./mongodb.log\"\n  zip([\n    'zipFile': 'mongodb.zip',\n    'archive': true,\n    'glob' : 'mongodb.log'\n  ])\n  sh 'rm mongodb.log'\n}\n\ndef sendMetrics(String metricName, String metricValue, Map<String, String> tags) {\n  def tagsString = getTagsString(tags)\n  withCredentials([[$class: 'UsernamePasswordMultiBinding', credentialsId: '5b8ad2d9-61a4-43b5-b4df-b8ff6b1f16fa', passwordVariable: 'influx_pass', usernameVariable: 'influx_user']]) {\n    sh \"curl -i -XPOST 'https://influxdb.realmlab.net/write?db=realm' --data-binary '${metricName},${tagsString} value=${metricValue}i' --user '${env.influx_user}:${env.influx_pass}'\"\n  }\n}\n\n@NonCPS\ndef getTagsString(Map<String, String> tags) {\n  return tags.collect { k,v -> \"$k=$v\" }.join(',')\n}\n\ndef storeJunitResults(String path) {\n  step([\n    $class: 'JUnitResultArchiver',\n    allowEmptyResults: true,\n    testResults: path\n  ])\n}\n\ndef collectAarMetrics() {\n  def flavors = ['base', 'objectServer']\n  for (def i = 0; i < flavors.size(); i++) {\n    def flavor = flavors[i]\n    sh \"\"\"set -xe\n      cd realm/realm-library/build/outputs/aar\n      unzip realm-android-library-${flavor}-release.aar -d unzipped${flavor}\n      find \\$ANDROID_HOME -name d8 | sort -r | head -n 1 > d8\n      \\$(cat d8) --release --output ./unzipped${flavor} unzipped${flavor}/classes.jar\n      cat ./unzipped${flavor}/temp${flavor}.dex | head -c 92 | tail -c 4 | hexdump -e '1/4 \\\"%d\\\"' > methods${flavor}\n    \"\"\"\n\n    def methods = readFile(\"realm/realm-library/build/outputs/aar/methods${flavor}\")\n    sendMetrics('methods', methods, ['flavor':flavor])\n\n    def aarFile = findFiles(glob: \"realm/realm-library/build/outputs/aar/realm-android-library-${flavor}-release.aar\")[0]\n    sendMetrics('aar_size', aarFile.length as String, ['flavor':flavor])\n\n    def soFiles = findFiles(glob: \"realm/realm-library/build/outputs/aar/unzipped${flavor}/jni/*/librealm-jni.so\")\n    for (def j = 0; j < soFiles.size(); j++) {\n      def soFile = soFiles[j]\n      def abiName = soFile.path.tokenize('/')[-2]\n      def libSize = soFile.length as String\n      sendMetrics('abi_size', libSize, ['flavor':flavor, 'type':abiName])\n    }\n  }\n}\n\ndef gradle(String commands) {\n  sh \"chmod +x gradlew && ./gradlew ${commands} --stacktrace\"\n}\n\ndef gradle(String relativePath, String commands) {\n  sh \"cd ${relativePath} && chmod +x gradlew && ./gradlew ${commands} --stacktrace\"\n}\n\ndef readGitTag() {\n  def command = 'git describe --exact-match --tags HEAD'\n  def returnStatus = sh(returnStatus: true, script: command)\n  if (returnStatus != 0) {\n    return null\n  }\n  return sh(returnStdout: true, script: command).trim()\n}\n\ndef runCommand(String command){\n  return sh(script: command, returnStdout: true).trim()\n}\n"
  },
  {
    "path": "LICENSE",
    "content": "                                 Apache License\n                           Version 2.0, January 2004\n                        http://www.apache.org/licenses/\n\n   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n   1. Definitions.\n\n      \"License\" shall mean the terms and conditions for use, reproduction,\n      and distribution as defined by Sections 1 through 9 of this document.\n\n      \"Licensor\" shall mean the copyright owner or entity authorized by\n      the copyright owner that is granting the License.\n\n      \"Legal Entity\" shall mean the union of the acting entity and all\n      other entities that control, are controlled by, or are under common\n      control with that entity. For the purposes of this definition,\n      \"control\" means (i) the power, direct or indirect, to cause the\n      direction or management of such entity, whether by contract or\n      otherwise, or (ii) ownership of fifty percent (50%) or more of the\n      outstanding shares, or (iii) beneficial ownership of such entity.\n\n      \"You\" (or \"Your\") shall mean an individual or Legal Entity\n      exercising permissions granted by this License.\n\n      \"Source\" form shall mean the preferred form for making modifications,\n      including but not limited to software source code, documentation\n      source, and configuration files.\n\n      \"Object\" form shall mean any form resulting from mechanical\n      transformation or translation of a Source form, including but\n      not limited to compiled object code, generated documentation,\n      and conversions to other media types.\n\n      \"Work\" shall mean the work of authorship, whether in Source or\n      Object form, made available under the License, as indicated by a\n      copyright notice that is included in or attached to the work\n      (an example is provided in the Appendix below).\n\n      \"Derivative Works\" shall mean any work, whether in Source or Object\n      form, that is based on (or derived from) the Work and for which the\n      editorial revisions, annotations, elaborations, or other modifications\n      represent, as a whole, an original work of authorship. For the purposes\n      of this License, Derivative Works shall not include works that remain\n      separable from, or merely link (or bind by name) to the interfaces of,\n      the Work and Derivative Works thereof.\n\n      \"Contribution\" shall mean any work of authorship, including\n      the original version of the Work and any modifications or additions\n      to that Work or Derivative Works thereof, that is intentionally\n      submitted to Licensor for inclusion in the Work by the copyright owner\n      or by an individual or Legal Entity authorized to submit on behalf of\n      the copyright owner. For the purposes of this definition, \"submitted\"\n      means any form of electronic, verbal, or written communication sent\n      to the Licensor or its representatives, including but not limited to\n      communication on electronic mailing lists, source code control systems,\n      and issue tracking systems that are managed by, or on behalf of, the\n      Licensor for the purpose of discussing and improving the Work, but\n      excluding communication that is conspicuously marked or otherwise\n      designated in writing by the copyright owner as \"Not a Contribution.\"\n\n      \"Contributor\" shall mean Licensor and any individual or Legal Entity\n      on behalf of whom a Contribution has been received by Licensor and\n      subsequently incorporated within the Work.\n\n   2. Grant of Copyright License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      copyright license to reproduce, prepare Derivative Works of,\n      publicly display, publicly perform, sublicense, and distribute the\n      Work and such Derivative Works in Source or Object form.\n\n   3. Grant of Patent License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      (except as stated in this section) patent license to make, have made,\n      use, offer to sell, sell, import, and otherwise transfer the Work,\n      where such license applies only to those patent claims licensable\n      by such Contributor that are necessarily infringed by their\n      Contribution(s) alone or by combination of their Contribution(s)\n      with the Work to which such Contribution(s) was submitted. If You\n      institute patent litigation against any entity (including a\n      cross-claim or counterclaim in a lawsuit) alleging that the Work\n      or a Contribution incorporated within the Work constitutes direct\n      or contributory patent infringement, then any patent licenses\n      granted to You under this License for that Work shall terminate\n      as of the date such litigation is filed.\n\n   4. Redistribution. You may reproduce and distribute copies of the\n      Work or Derivative Works thereof in any medium, with or without\n      modifications, and in Source or Object form, provided that You\n      meet the following conditions:\n\n      (a) You must give any other recipients of the Work or\n          Derivative Works a copy of this License; and\n\n      (b) You must cause any modified files to carry prominent notices\n          stating that You changed the files; and\n\n      (c) You must retain, in the Source form of any Derivative Works\n          that You distribute, all copyright, patent, trademark, and\n          attribution notices from the Source form of the Work,\n          excluding those notices that do not pertain to any part of\n          the Derivative Works; and\n\n      (d) If the Work includes a \"NOTICE\" text file as part of its\n          distribution, then any Derivative Works that You distribute must\n          include a readable copy of the attribution notices contained\n          within such NOTICE file, excluding those notices that do not\n          pertain to any part of the Derivative Works, in at least one\n          of the following places: within a NOTICE text file distributed\n          as part of the Derivative Works; within the Source form or\n          documentation, if provided along with the Derivative Works; or,\n          within a display generated by the Derivative Works, if and\n          wherever such third-party notices normally appear. The contents\n          of the NOTICE file are for informational purposes only and\n          do not modify the License. You may add Your own attribution\n          notices within Derivative Works that You distribute, alongside\n          or as an addendum to the NOTICE text from the Work, provided\n          that such additional attribution notices cannot be construed\n          as modifying the License.\n\n      You may add Your own copyright statement to Your modifications and\n      may provide additional or different license terms and conditions\n      for use, reproduction, or distribution of Your modifications, or\n      for any such Derivative Works as a whole, provided Your use,\n      reproduction, and distribution of the Work otherwise complies with\n      the conditions stated in this License.\n\n   5. Submission of Contributions. Unless You explicitly state otherwise,\n      any Contribution intentionally submitted for inclusion in the Work\n      by You to the Licensor shall be under the terms and conditions of\n      this License, without any additional terms or conditions.\n      Notwithstanding the above, nothing herein shall supersede or modify\n      the terms of any separate license agreement you may have executed\n      with Licensor regarding such Contributions.\n\n   6. Trademarks. This License does not grant permission to use the trade\n      names, trademarks, service marks, or product names of the Licensor,\n      except as required for reasonable and customary use in describing the\n      origin of the Work and reproducing the content of the NOTICE file.\n\n   7. Disclaimer of Warranty. Unless required by applicable law or\n      agreed to in writing, Licensor provides the Work (and each\n      Contributor provides its Contributions) on an \"AS IS\" BASIS,\n      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n      implied, including, without limitation, any warranties or conditions\n      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n      PARTICULAR PURPOSE. You are solely responsible for determining the\n      appropriateness of using or redistributing the Work and assume any\n      risks associated with Your exercise of permissions under this License.\n\n   8. Limitation of Liability. In no event and under no legal theory,\n      whether in tort (including negligence), contract, or otherwise,\n      unless required by applicable law (such as deliberate and grossly\n      negligent acts) or agreed to in writing, shall any Contributor be\n      liable to You for damages, including any direct, indirect, special,\n      incidental, or consequential damages of any character arising as a\n      result of this License or out of the use or inability to use the\n      Work (including but not limited to damages for loss of goodwill,\n      work stoppage, computer failure or malfunction, or any and all\n      other commercial damages or losses), even if such Contributor\n      has been advised of the possibility of such damages.\n\n   9. Accepting Warranty or Additional Liability. While redistributing\n      the Work or Derivative Works thereof, You may choose to offer,\n      and charge a fee for, acceptance of support, warranty, indemnity,\n      or other liability obligations and/or rights consistent with this\n      License. However, in accepting such obligations, You may act only\n      on Your own behalf and on Your sole responsibility, not on behalf\n      of any other Contributor, and only if You agree to indemnify,\n      defend, and hold each Contributor harmless for any liability\n      incurred by, or claims asserted against, such Contributor by reason\n      of your accepting any such warranty or additional liability.\n\n   END OF TERMS AND CONDITIONS\n\n"
  },
  {
    "path": "README.md",
    "content": "> [!WARNING]\n> We announced the deprecation of Atlas Device Sync + Realm SDKs in September 2024. For more information please see:\n> - [SDK Deprecation](https://www.mongodb.com/docs/atlas/device-sdks/deprecation/)\n> - [Device Sync Deprecation](https://www.mongodb.com/docs/atlas/app-services/sync/device-sync-deprecation/)\n>\n\n<picture>\n    <source srcset=\"./media/logo-dark.svg\" media=\"(prefers-color-scheme: dark)\" alt=\"realm\">\n    <img src=\"./media/logo.svg\" alt=\"realm\">\n</picture>\n\n[![Maven Central](https://img.shields.io/maven-central/v/io.realm/realm-gradle-plugin?colorB=4dc427&label=Maven%20Central)](https://search.maven.org/artifact/io.realm/realm-gradle-plugin)\n[![License](https://img.shields.io/badge/License-Apache-blue.svg)](https://github.com/realm/realm-java/blob/master/LICENSE)\n\nRealm is a mobile database that runs directly inside phones, tablets or wearables.\nThis repository holds the source code for the Java version of Realm, which currently runs only on Android.\n\n## Realm Kotlin\n\nThe [Realm Kotlin SDK](https://github.com/realm/realm-kotlin) is now GA and can be used for both Android and Kotlin Multiplatform. While we are still adding features, please consider using Realm Kotlin for any new project, and let us know if you miss anything there!\n\n## Features\n\n* **Mobile-first:** Realm is the first database built from the ground up to run directly inside phones, tablets, and wearables.\n* **Simple:** Data is directly exposed as objects and queryable by code, removing the need for ORM's riddled with performance & maintenance issues. Plus, we've worked hard to [keep our API down to very few classes](https://www.mongodb.com/docs/atlas/device-sdks/sdk/java/): most of our users pick it up intuitively, getting simple apps up & running in minutes.\n* **Modern:** Realm supports easy thread-safety, relationships & encryption.\n* **Fast:** Realm is faster than even raw SQLite on common operations while maintaining an extremely rich feature set.\n* **[Device Sync](https://www.mongodb.com/atlas/app-services/device-sync)**: Makes it simple to keep data in sync across users, devices, and your backend in real-time. Get started for free with [a template application](https://github.com/mongodb/template-app-react-native-todo) and [create the cloud backend](http://mongodb.com/realm/register?utm_medium=github_atlas_CTA&utm_source=realm_js_github).\n\n## Getting Started\n\nPlease see the [Quick Start](docs/guides/quick-start-local.md) to add Realm to your project.\n\n## Documentation\n\nDocumentation for Realm can be found in the [docs/](docs/README.md) directory.\n\nThe Javadoc and Kotlin Extensions API Reference docs can be generated\nfrom source.\n\n## Getting Help\n\n- **Got a question?**: Look for previous questions on the [#realm tag](https://stackoverflow.com/questions/tagged/realm?sort=newest) — or [ask a new question](http://stackoverflow.com/questions/ask?tags=realm). We actively monitor & answer questions on StackOverflow! You can also check out our [Community Forum](https://developer.mongodb.com/community/forums/tags/c/realm/9/realm-sdk) where general questions about how to do something can be discussed.\n- **Think you found a bug?** [Open an issue](https://github.com/realm/realm-java/issues/new?template=bug_report.md). If possible, include the version of Realm, a full log, the Realm file, and a project that shows the issue.\n- **Have a feature request?** [Open an issue](https://github.com/realm/realm-java/issues/new?template=feature_request.md). Tell us what the feature should do, and why you want the feature.\n\n## Using Snapshots\n\nIf you want to test recent bugfixes or features that have not been packaged in an official release yet, you can use a **-SNAPSHOT** release of the current development version of Realm via Gradle, available on [Sonatype OSS](https://oss.sonatype.org/#nexus-search;quick~realm-gradle-plugin)\n\n\n```\nbuildscript {\n    repositories {\n        mavenCentral()\n        google()\n        maven {\n            url 'https://oss.sonatype.org/content/repositories/snapshots/'\n        }\n        jcenter()\n    }\n    dependencies {\n        classpath \"io.realm:realm-gradle-plugin:<version>-SNAPSHOT\"\n    }\n}\n\nallprojects {\n    repositories {\n        mavenCentral()\n        google()\n        maven {\n            url 'https://oss.sonatype.org/content/repositories/snapshots/'\n        }\n        jcenter()\n    }\n}\n```\n\nSee [version.txt](version.txt) for the latest version number.\n\n## Building Realm\n\nIn case you don't want to use the precompiled version, you can build Realm yourself from source.\n\n### Prerequisites\n\n * Download the [**JDK 8**](http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html) from Oracle and install it.\n * The latest stable version of Android Studio. Currently [4.1.1](https://developer.android.com/studio/).\n * Download & install the Android SDK **Build-Tools 29.0.3**, **Android Pie (API 29)** (for example through Android Studio’s **Android SDK Manager**).\n * Install CMake version 3.18.4 and build Ninja.\n * Install the NDK (Side-by-side) **21.0.6113669** from the SDK Manager in Android Studio. Remember to check `☑  Show package details` in the manager to display all available versions.\n\n * Add the Android home environment variable to your profile:\n\n    ```\n    export ANDROID_HOME=~/Library/Android/sdk\n    ```\n\n * If you are launching Android Studio from the macOS Finder, you should also run the following command:\n\n    ```\n    launchctl setenv ANDROID_HOME \"$ANDROID_HOME\"\n    ```\n\n * If you'd like to specify the location in which to store the archives of Realm Core, define the `REALM_CORE_DOWNLOAD_DIR` environment variable. It enables caching core release artifacts.\n\n   ```\n   export REALM_CORE_DOWNLOAD_DIR=~/.realmCore\n   ```\n\n   macOS users must also run the following command for Android Studio to see this environment variable.\n\n   ```\n   launchctl setenv REALM_CORE_DOWNLOAD_DIR \"$REALM_CORE_DOWNLOAD_DIR\"\n   ```\n\nIt would be a good idea to add all of the symbol definitions (and their accompanying `launchctl` commands, if you are using macOS) to your `~/.profile` (or `~/.zprofile` if the login shell is `zsh`)\n\n * If you develop Realm Java with Android Studio, we recommend you to exclude some directories from indexing target by executing following steps on Android Studio. It really speeds up indexing phase after the build.\n\n    - Under `/realm/realm-library/`, select `build`, `.cxx` and `distribution` folders in `Project` view.\n    - Press `Command + Shift + A` to open `Find action` dialog. If you are not using default keymap nor using macOS, you can find your shortcut key in `Keymap` preference by searching `Find action`.\n    - Search `Excluded` (not `Exclude`) action and select it. Selected folder icons should become orange (in default theme).\n    - Restart Android Studio.\n\n### Download sources\n\nYou can download the source code of Realm Java by using git. Since realm-java has git submodules, use `--recursive` when cloning the repository.\n\n```\ngit clone git@github.com:realm/realm-java.git --recursive\n```\n\nor\n\n```\ngit clone https://github.com/realm/realm-java.git --recursive\n```\n\n### Build\n\nOnce you have completed all the pre-requisites building Realm is done with a simple command.\n\n```\n./gradlew assemble\n```\n\nThat command will generate:\n\n * a jar file for the Realm Gradle plugin\n * an aar file for the Realm library\n * a jar file for the annotations\n * a jar file for the annotations processor\n\nThe full build may take an hour or more, to complete.\n\n### Building from source\n\nIt is possible to build Realm Java with the submodule version of Realm Core. This is done by providing the following parameter when building: `-PbuildCore=true`.\n\n```\n./gradlew assembleBase -PbuildCore=true\n```\n\nYou can turn off interprocedural optimizations with the following parameter: `-PenableLTO=false`. \n\n```\n./gradlew assembleBase -PenableLTO=false`\n```\n\nNote: Building the `Base` variant would always build realm-core.\n\nNote: Interprocedural optimizations are enabled by default.\n\nNote: If you want to build from source inside Android Studio, you need to update the Gradle parameters by going into the Realm projects settings `Settings > Build, Execution, Deployment > Compiler > Command-line options` and add `-PbuildCore=true` or `-PenableLTO=false` to it. Alternatively you can add it into your `gradle.properties`:\n\n```\nbuildCore=true\nenableLTO=false\n```\n\nNote: If building on OSX you might like to prevent Gatekeeper to block all NDK executables by disabling it: `sudo spctl --master-disable`. Remember to enable it afterwards: `sudo spctl --master-enable`\n\n### Other Commands\n\n * `./gradlew tasks` will show all the available tasks\n * `./gradlew javadoc` will generate the Javadocs\n * `./gradlew monkeyExamples` will run the monkey tests on all the examples\n * `./gradlew installRealmJava` will install the Realm library and plugin to mavenLocal()\n * `./gradlew clean -PdontCleanJniFiles` will remove all generated files except for JNI related files. This reduces recompilation time a lot.\n * `./gradlew connectedUnitTests -PbuildTargetABIs=$(adb shell getprop ro.product.cpu.abi)` will build JNI files only for the ABI which corresponds to the connected device.  These tests require a running Object Server (see below)\n\nGenerating the Javadoc using the command above may generate warnings. The Javadoc is generated despite the warnings.\n\n\n### Upgrading Gradle Wrappers\n\n All gradle projects in this repository have `wrapper` task to generate Gradle Wrappers. Those tasks refer to `gradle` property defined in `/dependencies.list` to determine Gradle Version of generating wrappers.\nWe have a script `./tools/update_gradle_wrapper.sh` to automate these steps. When you update Gradle Wrappers, please obey the following steps.\n\n 1. Edit `gradle` property in defined in `/dependencies.list` to new Gradle Wrapper version.\n 2. Execute `/tools/update_gradle_wrapper.sh`.\n\n### Gotchas\n\nThe repository is organized into six Gradle projects:\n\n * `realm`: it contains the actual library (including the JNI layer) and the annotations processor.\n * `realm-annotations`: it contains the annotations defined by Realm.\n * `realm-transformer`: it contains the bytecode transformer.\n * `gradle-plugin`: it contains the Gradle plugin.\n * `examples`: it contains the example projects. This project directly depends on `gradle-plugin` which adds a dependency to the artifacts produced by `realm`.\n * The root folder is another Gradle project.  All it does is orchestrate the other jobs.\n\nThis means that `./gradlew clean` and `./gradlew cleanExamples` will fail if `assembleExamples` has not been executed first.\nNote that IntelliJ [does not support multiple projects in the same window](https://youtrack.jetbrains.com/issue/IDEABKL-6118#)\nso each of the six Gradle projects must be imported as a separate IntelliJ project.\n\nSince the repository contains several completely independent Gradle projects, several independent builds are run to assemble it.\nSeeing a line like: `:realm:realm-library:compileBaseDebugAndroidTestSources UP-TO-DATE` in the build log does *not* imply\nthat you can run `./gradlew :realm:realm-library:compileBaseDebugAndroidTestSources`.\n\n## Examples\n\nThe `./examples` folder contains many example projects showing how Realm can be used. If this is the first time you checkout or pull a new version of this repository to try the examples, you must call `./gradlew installRealmJava` from the top-level directory first. Otherwise, the examples will not compile as they depend on all Realm artifacts being installed in `mavenLocal()`.\n\n## Running Tests on a Device\n\nTo run these tests, you must have a device connected to the build computer, and the `adb` command must be in your `PATH`\n\n1. Connect an Android device and verify that the command `adb devices` shows a connected device:\n\n    ```sh\n    adb devices\n    List of devices attached\n    004c03eb5615429f device\n    ```\n\n2. Run instrumentation tests:\n\n    ```sh\n    cd realm\n    ./gradlew connectedBaseDebugAndroidTest\n    ```\n\nThese tests may take as much as half an hour to complete.\n\n## Running Tests Using The Realm Object Server\n\nTests in `realm/realm-library/src/syncIntegrationTest` require a running testing server to work.\nA docker image can be built from `tools/sync_test_server/Dockerfile` to run the test server.\n`tools/sync_test_server/start_server.sh` will build the docker image automatically.\n\nTo run a testing server locally:\n\n1. Install [docker](https://www.docker.com/products/overview) and run it.\n\n2. Run `tools/sync_test_server/start_server.sh`:\n\n    ```sh\n    cd tools/sync_test_server\n    ./start_server.sh\n    ```\n\n    This command will not complete until the server has stopped.\n\n3. Run instrumentation tests\n\n    In a new terminal window, run:\n\n    ```sh\n    cd realm\n    ./gradlew connectedObjectServerDebugAndroidTest\n    ```\n\nNote that if using VirtualBox (Genymotion), the network needs to be bridged for the tests to work.\nThis is done in `VirtualBox > Network`. Set \"Adapter 2\" to \"Bridged Adapter\".\n\nThese tests may take as much as half an hour to complete.\n\n## Contributing\n\nSee [CONTRIBUTING.md](CONTRIBUTING.md) for more details!\n\nThis project adheres to the [MongoDB Code of Conduct](https://www.mongodb.com/community-code-of-conduct).\nBy participating, you are expected to uphold this code. Please report\nunacceptable behavior to [community-conduct@mongodb.com](mailto:community-conduct@mongodb.com).\n\nThe directory `realm/config/studio` contains lint and style files recommended for project code.\nImport them from Android Studio with Android Studio > Preferences... > Code Style > Manage... > Import,\nor Android Studio > Preferences... > Inspections > Manage... > Import.  Once imported select the\nstyle/lint in the drop-down to the left of the Manage... button.\n\n## License\n\nRealm Java is published under the Apache 2.0 license.\n\nRealm Core is also published under the Apache 2.0 license and is available\n[here](https://github.com/realm/realm-core).\n\n## Feedback\n\n**_If you use Realm and are happy with it, all we ask is that you, please consider sending out a tweet mentioning [@realm](http://twitter.com/realm) to share your thoughts!_**\n\n**_And if you don't like it, please let us know what you would like improved, so we can fix it!_**\n\n<img style=\"width: 0px; height: 0px;\" src=\"https://3eaz4mshcd.execute-api.us-east-1.amazonaws.com/prod?s=https://github.com/realm/realm-java#README.md\">\n"
  },
  {
    "path": "SUPPORT.md",
    "content": "# Support\n\nThe Realm team is here to help you with your Realm-related issues!\n\n## Documentation\n\nBefore asking questions, please familiarize yourself with our [Java](https://www.mongodb.com/docs/atlas/device-sdks/sdk/java/) documentation. We also have a number of [Troubleshooting Notes](https://www.mongodb.com/docs/atlas/device-sdks/sdk/java/troubleshooting/) which cover various topics that may be of interest.\n\n## Stack Overflow\n\nIf you have questions about configuring or using Realm you can ask them on Stack Overflow. We continually monitor the [`realm` tag](https://stackoverflow.com/tags/realm). Please also tag your question with `java`, `android`, or other tags as appropriate.\n\nWhen asking questions on Stack Overflow, please keep in mind Stack Overflow's [question guidelines](https://stackoverflow.com/help/how-to-ask), and please use their search functionality to see if your question has been asked before.\n\n## GitHub Issues\n\nIf you are running into issues with Realm, including potential bugs or feature requests, we encourage you to file an issue on our [GitHub issue tracker](https://github.com/realm/realm-java/issues). Please check out our [Contribution Guidelines](CONTRIBUTING.md) for information on how to properly file an issue.\n\nWe greatly appreciate demonstration projects that we can run for ourselves in order to see issues or potential bugs; we prioritize clearly-written tickets that include reproduction cases. You may attach these to the ticket; let us know if you need to share them confidentially, and we’ll provide instructions on how to do so.\n"
  },
  {
    "path": "build.gradle",
    "content": "buildscript {\n    def properties = new Properties()\n    properties.load(new FileInputStream(\"${projectDir}/dependencies.list\"))\n\n    repositories {\n        jcenter()\n        maven {\n            url \"https://plugins.gradle.org/m2/\"\n        }\n    }\n}\n\ndef currentVersion = file(\"${projectDir}/version.txt\").text.trim()\n\n// Find property in either System environment or Gradle properties.\n// If set in both places, Gradle properties win.\ndef getPropertyValueOrThrow(String propertyName) {\n    def value = System.getenv(propertyName)\n    if (project.hasProperty(propertyName)) {\n        value = project.getProperty(propertyName)\n    }\n    if (value == null || value.trim().isEmpty()) {\n        throw new GradleException(\"Could not find '$propertyName'. \" +\n                \"Most be provided as either environment variable or \" +\n                \"a Gradle property.\")\n    }\n    return value\n}\n\n// Shared configuration that copies relevant properties from the root level and parse them on to\n// child projects.\ndef copyProperties = {\n    if (project.hasProperty('buildTargetABIs')) {\n        // Valid options: armeabi-v7a, arm64-v8a, x86, x86_64\n        startParameter.projectProperties += [buildTargetABIs: project.getProperty('buildTargetABIs')]\n    }\n    if (project.hasProperty('coreSourcePath')) {\n        def absolutePath = file(project.getProperty('coreSourcePath')).absolutePath\n        startParameter.projectProperties += [coreSourcePath: absolutePath]\n    }\n    if (project.hasProperty('s3cfg')) {\n        startParameter.projectProperties += [s3cfg: project.getProperty('s3cfg')]\n    }\n    if (project.hasProperty('enableLTO')) {\n        startParameter.projectProperties += [enableLTO: project.getProperty('enableLTO')]\n    }\n    if (project.hasProperty('buildCore')) {\n        startParameter.projectProperties += [buildCore: project.getProperty('buildCore')]\n    }\n    if (project.hasProperty('signBuild')) {\n        startParameter.projectProperties += [signBuild: project.getProperty('signBuild')]\n    }\n    if (project.hasProperty('signPassword')) {\n        startParameter.projectProperties += [signPassword: project.getProperty('signPassword')]\n    }\n    if (project.hasProperty('signSecretRingFile')) {\n        startParameter.projectProperties += [signSecretRingFile: project.getProperty('signSecretRingFile')]\n    }\n    if (project.hasProperty('ossrhUsername')) {\n        startParameter.projectProperties += [ossrhUsername: project.getProperty('ossrhUsername')]\n    }\n    if (project.hasProperty('ossrhPassword')) {\n        startParameter.projectProperties += [ossrhPassword: project.getProperty('ossrhPassword')]\n    }\n}\n\ntask assembleAnnotations(type:GradleBuild) {\n    group = 'Build'\n    description = 'Assemble the Realm annotations'\n    buildFile = file('realm-annotations/build.gradle')\n    tasks = ['assemble']\n}\n\ntask installAnnotations(type:GradleBuild) {\n    group = 'Install'\n    description = 'Install the jar realm-annotations into mavenLocal()'\n    buildFile = file('realm-annotations/build.gradle')\n    tasks = ['publishToMavenLocal']\n}\n\ntask assembleTransformer(type:GradleBuild) {\n    group = 'Build'\n    description = 'Assemble the Realm transformer'\n    dependsOn installAnnotations\n    buildFile = file('realm-transformer/build.gradle')\n    tasks = ['assemble']\n}\n\ntask installTransformer(type:GradleBuild) {\n    group = 'Install'\n    description = 'Install the jar realm-transformer into mavenLocal()'\n    dependsOn installAnnotations\n    buildFile = file('realm-transformer/build.gradle')\n    tasks = ['publishToMavenLocal']\n}\n\ntask installBuildTransformer(type:GradleBuild) {\n    group = 'Install'\n    description = 'Install the jar realm-library-build-transformer into mavenLocal()'\n    buildFile = file('library-build-transformer/build.gradle')\n    tasks = ['publishToMavenLocal']\n}\n\ntask assembleRealm(type:GradleBuild) {\n    group = 'Build'\n    description = 'Assemble the Realm project'\n    dependsOn installAnnotations\n    dependsOn installTransformer\n    dependsOn installBuildTransformer\n    buildFile = file('realm/build.gradle')\n    tasks = ['assemble', 'javadocJar', 'sourcesJar']\n    configure copyProperties\n}\n\ntask checkExamples(type:GradleBuild) {\n    group = 'Test'\n    description = 'Run the JVM tests and checks the examples'\n    buildFile = file('examples/build.gradle')\n    tasks = ['check']\n    configure copyProperties\n}\n\ntask checkRealm(type:GradleBuild) {\n    group = 'Test'\n    description = 'Run the JVM tests and checks Realm project'\n    buildFile = file('realm/build.gradle')\n    tasks = ['check']\n    configure copyProperties\n}\n\ntask check {\n    group = 'Test'\n    description = 'Run the JVM tests and checks in the realm and examples projects'\n    dependsOn checkRealm\n    dependsOn checkExamples\n}\n\ntask assembleUnitTests(type:GradleBuild) {\n    group = 'Build'\n    description = 'Assemble Android unit tests of the Realm project'\n    dependsOn installTransformer\n    buildFile = file('realm/build.gradle')\n    tasks = ['assembleAndroidTest']\n    configure copyProperties\n}\n\ntask connectedUnitTests(type:GradleBuild) {\n    group = 'Test'\n    description = 'Run the Android unit tests of the Realm project'\n    dependsOn installTransformer\n    buildFile = file('realm/build.gradle')\n    tasks = ['connectedAndroidTest']\n    configure copyProperties\n}\n\ntask assembleBenchmarks(type:GradleBuild) {\n    group = 'Build'\n    description = 'Assemble benchmark tests for the library '\n    dependsOn installTransformer\n    buildFile = file('library-benchmarks/build.gradle')\n    tasks = ['assembleAndroidTest']\n    configure copyProperties\n}\n\ntask connectedBenchmarks(type:GradleBuild) {\n    group = 'Test'\n    description = 'Run all the benchmark tests for the library '\n    dependsOn installTransformer\n    buildFile = file('library-benchmarks/build.gradle')\n    tasks = ['connectedAndroidTest']\n    configure copyProperties\n}\n\ntask installRealm(type:GradleBuild) {\n    group = 'Install'\n    description = 'Install the artifacts of Realm libraries into mavenLocal()'\n    dependsOn installTransformer\n    dependsOn installBuildTransformer\n    buildFile = file('realm/build.gradle')\n    tasks = ['publishToMavenLocal']\n    configure copyProperties\n}\n\ntask assembleGradlePlugin(type:GradleBuild) {\n    group = 'Build'\n    description = 'Assemble the Realm Gradle plugin'\n    dependsOn installRealm\n    dependsOn installTransformer\n    buildFile = file('gradle-plugin/build.gradle')\n    tasks = ['assemble']\n}\n\ntask installGradlePlugin(type:GradleBuild) {\n    description = 'Install the Realm Gradle plugin into mavenLocal()'\n    group = 'Install'\n    dependsOn installRealm\n    dependsOn installTransformer\n    buildFile = file('gradle-plugin/build.gradle')\n    tasks = ['publishToMavenLocal']\n}\n\ntask installRealmJava(type:Task) {\n    dependsOn installGradlePlugin\n    dependsOn installRealm\n    group = 'Install'\n    description = 'Install the Realm library and Gradle plugin into mavenLocal()'\n}\n\ntask assembleExamples(type:GradleBuild) {\n    dependsOn installGradlePlugin\n    dependsOn installRealm\n    group = 'Build'\n    description = 'Assemble the Realm examples'\n    buildFile = file('examples/build.gradle')\n    tasks = ['assemble']\n}\n\ntask monkeyExamples(type:GradleBuild) {\n    dependsOn installGradlePlugin\n    dependsOn installRealm\n    group = 'Build'\n    description = 'Run the monkey tests on the Realm examples'\n    buildFile = file('examples/build.gradle')\n    tasks = ['monkeyRelease']\n}\n\ntask javadoc(type:GradleBuild) {\n    description = 'Generate the Javadoc Jar for the Realm project'\n    group = 'Docs'\n    buildFile = file('realm/build.gradle')\n    tasks = ['javadocJar']\n    configure copyProperties\n}\n\ntask uploadJavadoc {\n    group = 'Release'\n    description = 'Upload Java and Kotlin docs to S3'\n    dependsOn javadoc\n\n    doLast {\n        def awsAccessKey = getPropertyValueOrThrow(\"SDK_DOCS_AWS_ACCESS_KEY\")\n        def awsSecretKey = getPropertyValueOrThrow(\"SDK_DOCS_AWS_SECRET_KEY\")\n\n        // Upload two copies, to 'latest' and a versioned folder for posterity.\n        // Symlinks would have been safer and faster, but this is not supported by S3.\n        [ \"${currentVersion}\", \"latest\"].forEach { version ->\n            exec {\n                commandLine 's3cmd', 'put', '--recursive', '--acl-public', \"--access_key=${awsAccessKey}\", \"--secret_key=${awsSecretKey}\", 'realm/realm-library/build/docs/javadoc/', \"s3://realm-sdks/realm-sdks/java/${version}/\"\n            }\n            // The stylesheet is being uploaded with the wrong Content-Type header, which causes the stylesheet to not be applied in some browsers.\n            // So we need to modify the stylesheet after it has been uploaded.\n            exec {\n                commandLine 's3cmd', 'modify', \"--access_key=${awsAccessKey}\", \"--secret_key=${awsSecretKey}\", \"--debug\", '--add-header=Content-Type: text/css', \"s3://realm-sdks/realm-sdks/java/${version}/stylesheet.css\"\n            }\n            // Upload Kotlin extension docs to a subdirectory of the Javadoc. This should not conflict with the Javadoc folder layout.\n            exec {\n                commandLine 's3cmd', 'put', '--recursive', '--acl-public', \"--access_key=${awsAccessKey}\", \"--secret_key=${awsSecretKey}\", 'realm/kotlin-extensions/build/dokka/', \"s3://realm-sdks/realm-sdks/java/${version}/kotlin-extensions/\"\n            }\n        }\n    }\n}\n\ntask sourcesJar(type:GradleBuild) {\n    description = 'Generate the sources Jar for the Realm project'\n    group = 'Docs'\n    buildFile = file('realm/build.gradle')\n    tasks = ['sourcesJar']\n    configure copyProperties\n}\n\ntask assemble {\n    group 'Build'\n    description = 'Build Realm, the Gradle plugin and the examples'\n    dependsOn assembleExamples\n}\n\ntask distributionJniUnstrippedPackage(type:Zip) {\n    description = 'Generate native libs package with debug symbols'\n\n    group = 'Artifact'\n    archiveName = \"realm-java-jni-libs-unstripped-${currentVersion}.zip\"\n    destinationDir = file(\"${buildDir}/outputs/distribution\")\n\n    from(\"realm/realm-library/build/outputs/jniLibs-unstripped\") {\n        include '**/*.so'\n    }\n}\n\ntask cleanRealm(type:GradleBuild) {\n    description = 'Clean the Realm project'\n    group = 'Clean'\n    buildFile = file('realm/build.gradle')\n    tasks = ['clean']\n    configure copyProperties\n}\n\ntask cleanGradlePlugin(type:GradleBuild) {\n    description = 'Clean the Realm Gradle plugin project'\n    group = 'Clean'\n    buildFile = file('gradle-plugin/build.gradle')\n    tasks = ['clean']\n}\n\ntask cleanExamples(type:GradleBuild) {\n    description = 'Clean the Realm examples'\n    group = 'Clean'\n    buildFile = file('examples/build.gradle')\n    tasks = ['clean']\n}\n\ntask cleanLocalMavenRepos(type:Delete) {\n    description = 'Remove any Realm artifacts from the local Maven repositories'\n    group = 'Clean'\n    delete \"${System.env.HOME}/.m2/repository/io/realm\"\n}\n\ntask clean {\n    description = 'Perform all the other clean tasks'\n    group = 'Clean'\n    cleanLocalMavenRepos.dependsOn cleanRealm\n    cleanLocalMavenRepos.dependsOn cleanGradlePlugin\n    cleanLocalMavenRepos.dependsOn cleanExamples\n    dependsOn cleanLocalMavenRepos\n}\n\ntask manualClean {\n    description = 'Clean build files without using clean tasks defined in sub projects'\n    group = 'Clean'\n\n    doLast {\n        // clean 'build' directories\n        exec {\n            workingDir \"${rootDir}\"\n            commandLine 'find', '.', '-type', 'd', '-name', 'build', '-print', '-exec', 'rm', '-rf', '{}', ';', '-prune'\n        }\n\n        // clean '.externalNativeBuild' directories\n        exec {\n            workingDir \"${rootDir}\"\n            commandLine 'find', '.', '-type', 'd', '-name', '.externalNativeBuild', '-print', '-exec', 'rm', '-rf', '{}', ';', '-prune'\n        }\n\n        // clean '.gradle' directories except one in the root\n        exec {\n            workingDir \"${rootDir}\"\n            commandLine 'find', '.', '-mindepth', '2', '-type', 'd', '-name', '.gradle', '-print', '-exec', 'rm', '-rf', '{}', ';', '-prune'\n        }\n\n        // clean ${System.env.HOME}/.m2/repository/io/realm\n        exec {\n            workingDir \"${rootDir}\"\n            commandLine 'sh', '-c', \"echo \\\"${System.env.HOME}/.m2/repository/io/realm\\\" && rm -rf \\\"${System.env.HOME}/.m2/repository/io/realm\\\"\"\n        }\n    }\n}\n\ntask uploadDistributionPackage {\n    group = 'Release'\n    description = 'Upload the distribution package to S3'\n    dependsOn distributionJniUnstrippedPackage\n    def s3AccessKey = \"${ -> getPropertyValueOrThrow('REALM_S3_ACCESS_KEY')}\"\n    def s3SecretKey = \"${ -> getPropertyValueOrThrow('REALM_S3_SECRET_KEY')}\"\n    doLast {\n\n        // Check that zip file exists. Creating the zip file will silently fail if no files exists, so check here.\n        def zipFile = file(\"${buildDir}/outputs/distribution/realm-java-jni-libs-unstripped-${currentVersion}.zip\")\n        if (!zipFile.exists()) {\n            throw new GradleException(\"Could not locate unstripped binary zip file in: ${zipFile.getPath()}\")\n        }\n\n        exec {\n            commandLine 's3cmd', \"--access_key=${s3AccessKey}\", \"--secret_key=${s3SecretKey}\", 'put', zipFile.getAbsolutePath(), 's3://static.realm.io/downloads/java/'\n        }\n    }\n}\n\ntask uploadUpdateVersion(type: Exec) {\n    group = 'Release'\n    description = 'Update the file on S3 containing the latest version'\n    def s3AccessKey = \"${ -> getPropertyValueOrThrow('REALM_S3_ACCESS_KEY')}\"\n    def s3SecretKey = \"${ -> getPropertyValueOrThrow('REALM_S3_SECRET_KEY')}\"\n    commandLine 's3cmd', \"--access_key=${s3AccessKey}\", \"--secret_key=${s3SecretKey}\", 'put', \"${rootDir}/version.txt\", 's3://static.realm.io/update/java'\n}\n\ntask distribute {\n    group = 'Release'\n    description = 'Distribute release artifacts to S3'\n    dependsOn uploadDistributionPackage\n    dependsOn uploadUpdateVersion\n}\n\ntask mavenCentralRealm(type: GradleBuild) {\n    description = 'Publish the Realm AAR and AP to Maven Central'\n    group = 'Publishing'\n    buildFile = file('realm/build.gradle')\n    tasks = ['publishToSonatype']\n    startParameter.projectProperties = gradle.startParameter.projectProperties\n    configure copyProperties\n}\n\ntask mavenCentralAnnotations(type: GradleBuild) {\n    description = 'Publish the Realm Annotations to Maven Central'\n    group = 'Publishing'\n    buildFile = file('realm-annotations/build.gradle')\n    tasks = ['publishToSonatype']\n    startParameter.projectProperties = gradle.startParameter.projectProperties\n    configure copyProperties\n}\n\ntask mavenCentralGradlePlugin(type: GradleBuild) {\n    description = 'Publish the Realm Gradle Plugin to Maven Central'\n    group = 'Publishing'\n    buildFile = file('gradle-plugin/build.gradle')\n    tasks = ['publishToSonatype']\n    startParameter.projectProperties = gradle.startParameter.projectProperties\n    configure copyProperties\n}\n\ntask mavenCentralTransformer(type: GradleBuild) {\n    description = 'Publish the Realm Transformer to Maven Central'\n    group = 'Publishing'\n    buildFile = file('realm-transformer/build.gradle')\n    tasks = ['publishToSonatype']\n    startParameter.projectProperties = gradle.startParameter.projectProperties\n    configure copyProperties\n}\n\ntask mavenCentralUpload {\n    description = 'Publish all the Realm artifacts to Maven Central'\n    group = 'Publishing'\n    dependsOn mavenCentralRealm\n    dependsOn mavenCentralAnnotations\n    dependsOn mavenCentralGradlePlugin\n    dependsOn mavenCentralTransformer\n}\n"
  },
  {
    "path": "dependencies.list",
    "content": "# Realm Core release used by Realm Java\n# https://github.com/realm/realm-core/releases\nREALM_CORE=13.26.0\n\n# Version of MongoDB Realm used by integration tests\n# See https://github.com/realm/ci/packages/147854 for available versions\nMONGODB_REALM_SERVER=2023-05-31\n\n# `BAAS` and `BAAS-UI` projects commit hashes matching MONGODB_REALM_SERVER image version\n# note that the MONGODB_REALM_SERVER image is a nightly build, find the matching commits\n# for that date within the following repositories: \n# https://github.com/10gen/baas/ \n# https://github.com/10gen/baas-ui/\nREALM_BAAS_GIT_HASH=1de3337309b9a89094f739efaa69afa2dbc2daa9\nREALM_BAAS_UI_GIT_HASH=9c4ef71f69776651cf0110052ce760920ac8c7da\n\n# Common Android settings across projects\nGRADLE_BUILD_TOOLS=7.4.0\nANDROID_BUILD_TOOLS=30.0.3\nKOTLIN=1.6.21\nKOTLIN_COROUTINES=1.6.0\n\n# Common classpath dependencies\ngradle=7.5\nndkVersion=23.1.7779620\nBUILD_INFO_EXTRACTOR_GRADLE=4.23.4\nGRADLE_NEXUS_PLUGIN=1.0.0\nCMAKE=3.27.7\n\n# Bson dependency version\nBSON_DEPENDENCY=3.12.1\n\n# RxJava dependency version\nRXJAVA_DEPENDENCY=2.1.5\nRXANDROID_DEPENDENCY=2.1.1\n"
  },
  {
    "path": "docs/README.md",
    "content": "# Realm SDK for Java\nUse the Realm SDK for Java to develop Android apps in Java or Kotlin.\nTo develop multiplatform apps using Kotlin Multiplatform (KMP), refer to the\nKotlin SDK.\n\n## SDK in Maintenance Mode\nThis SDK is in best-effort maintenance mode and **no longer receives\nnew development or non-critical bug fixes**. To develop your app with new\nfeatures, use the Kotlin SDK. You can use the Java SDK with the Kotlin SDK.\n\n## Develop Apps with the SDK\nUse the SDK's open-source database - Realm - as an object store on the device.\n\n### Install the Java SDK\nUse the Gradle build system to\ninstall the Java SDK in your project.\n\n### Define an Object Schema\nUse Java or Kotlin to idiomatically define an object schema.\n\n### Open a Database\nThe SDK's database - Realm - stores objects in files on your device.\nOr you can open an in-memory database which does not create a file.\nTo get started reading and writing data,\nconfigure and open a database.\n\n### Read and Write Data\nCreate, read, update, and\ndelete objects from the database.\nUse Android-native queries to filter data.\n\n### React to Changes\nLive objects mean that your data is always up-to-date.\nYou can register a notification handler to watch for changes and perform some\nlogic, such as updating your UI.\n\n## Examples\n\nSee the [examples/](..examples/) directory.\n"
  },
  {
    "path": "docs/guides/adapters.md",
    "content": "# Display Collections - Java SDK\nAndroid apps often populate the UI using\n[RecyclerView](https://developer.android.com/reference/androidx/recyclerview/widget/RecyclerView.html)\nor [ListView](https://developer.android.com/reference/android/widget/ListView) components.\nRealm offers **adapters** to display realm object\ncollections. These collections implement\nthe `OrderedRealmCollections` interface. RealmResults\nand RealmList are examples of these adaptors.\nWith these adapters, UI components update when your app changes\nRealm objects.\n\n## Install Adapters\nAdd these dependencies to your application level `build.gradle` file:\n\n```gradle\ndependencies {\n   implementation 'io.realm:android-adapters:4.0.0'\n   implementation 'androidx.recyclerview:recyclerview:1.1.0'\n}\n```\n\nRealm hosts these adapters on the\n[JCenter](https://mvnrepository.com/repos/jcenter)\nartifact repository. To use `jcenter` in your Android app, add it to your\nproject-level `build.gradle` file:\n\n```gradle\nbuildscript {\n    repositories {\n        jcenter()\n    }\n}\n\nallprojects {\n    repositories {\n        jcenter()\n    }\n}\n```\n\n> Seealso:\n> Source code: [realm/realm-android-adapters](https://github.com/realm/realm-android-adapters) on GitHub.\n>\n\n## Example Models\nThe examples on this page use a Realm object named `Item`.\nThis class contains a string named \"name\" and an identifier number named\n\"id\":\n\n#### Java\n\n```java\n\nimport io.realm.RealmObject;\n\npublic class Item extends RealmObject {\n    int id;\n    String name;\n\n    public Item() {}\n\n    public int getId() { return id; }\n    public void setId(int id) { this.id = id; }\n    public String getName() { return name; }\n    public void setName(String name) { this.name = name; }\n}\n\n```\n\n#### Kotlin\n\n```kotlin\n\nimport io.realm.RealmObject\n\nopen class Item(var id: Int = 0,\n                var name: String? = null): RealmObject()\n\n```\n\n## Display Collections in a ListView\nDisplay Realm objects in a\n[ListView](https://developer.android.com/reference/android/widget/ListView) by extending\n[RealmBaseAdapter](https://github.com/realm/realm-android-adapters/blob/master/adapters/src/main/java/io/realm/RealmBaseAdapter.java).\nThe adapter uses the `ListAdapter` interface. Implementation works\nlike any `ListAdapter`. This provides support for automatically-updating\nRealm objects.\n\nSubclass `RealmBaseAdapter` to display\nItem objects in a `ListView`:\n\n#### Java\n\n```java\nimport android.util.Log;\nimport android.view.View;\nimport android.view.ViewGroup;\nimport android.widget.LinearLayout;\nimport android.widget.ListAdapter;\nimport android.widget.TextView;\nimport com.mongodb.realm.examples.model.java.Item;\nimport io.realm.OrderedRealmCollection;\nimport io.realm.RealmBaseAdapter;\n\nclass ExampleListAdapter extends RealmBaseAdapter<Item> implements ListAdapter {\n    String TAG = \"REALM_LIST_ADAPTER\";\n\n    ExampleListAdapter(OrderedRealmCollection<Item> realmResults) {\n        super(realmResults);\n    }\n\n    @Override\n    public View getView(int position, View convertView, ViewGroup parent) {\n        ViewHolder viewHolder;\n        if (convertView == null) {\n            Log.i(TAG, \"Creating view holder\");\n            // create a top-level layout for our item views\n            LinearLayout layout = new LinearLayout(parent.getContext());\n            layout.setLayoutParams(\n                    new ViewGroup.LayoutParams(\n                            ViewGroup.LayoutParams.MATCH_PARENT,\n                            ViewGroup.LayoutParams.MATCH_PARENT));\n\n            // create a text view to display item names\n            TextView titleView = new TextView(parent.getContext());\n            titleView.setLayoutParams(\n                    new ViewGroup.LayoutParams(\n                            ViewGroup.LayoutParams.MATCH_PARENT,\n                            ViewGroup.LayoutParams.MATCH_PARENT));\n\n            // attach the text view to the item view layout\n            layout.addView(titleView);\n            convertView = layout;\n            viewHolder = new ViewHolder(titleView);\n            convertView.setTag(viewHolder);\n        } else {\n            viewHolder = (ViewHolder) convertView.getTag();\n        }\n\n        // as long as we\n        if (adapterData != null) {\n            final Item item = adapterData.get(position);\n            viewHolder.title.setText(item.getName());\n            Log.i(TAG, \"Populated view holder with data: \" + item.getName());\n        } else {\n            Log.e(TAG, \"No data in adapter! Failed to populate view holder.\");\n        }\n        return convertView;\n    }\n\n    private static class ViewHolder {\n        TextView title;\n\n        public ViewHolder(TextView textView) {\n            title = textView;\n        }\n    }\n}\n\n```\n\nTo display list data in an activity, instantiate a `ListView`. Then,\nattach an `ExampleListAdapter`:\n\n```java\n// instantiate a ListView programmatically\nListView listView = new ListView(activity.getApplicationContext());\nlistView.setLayoutParams(\n        new ViewGroup.LayoutParams(\n                ViewGroup.LayoutParams.MATCH_PARENT,\n                ViewGroup.LayoutParams.MATCH_PARENT));\n\n// create an adapter with a RealmResults collection\n// and attach it to the ListView\nExampleListAdapter adapter =\n        new ExampleListAdapter(\n                realm.where(Item.class).findAll());\nlistView.setAdapter(adapter);\nViewGroup.LayoutParams layoutParams =\n        new ViewGroup.LayoutParams(\n                ViewGroup.LayoutParams.MATCH_PARENT,\n                ViewGroup.LayoutParams.MATCH_PARENT);\nactivity.addContentView(listView, layoutParams);\n\n```\n\n#### Kotlin\n\n```kotlin\nimport android.util.Log\nimport android.view.View\nimport android.view.ViewGroup\nimport android.widget.LinearLayout\nimport android.widget.ListAdapter\nimport android.widget.TextView\nimport com.mongodb.realm.examples.model.kotlin.Item\nimport io.realm.OrderedRealmCollection\nimport io.realm.RealmBaseAdapter\n\ninternal class ExampleListAdapter(realmResults: OrderedRealmCollection<Item?>?) :\n    RealmBaseAdapter<Item?>(realmResults), ListAdapter {\n    var TAG = \"REALM_LIST_ADAPTER\"\n\n    override fun getView(position: Int,\n                         convertView: View?,\n                         parent: ViewGroup): View {\n        var convertView = convertView\n        val viewHolder: ViewHolder\n        if (convertView == null) {\n            Log.i(TAG, \"Creating view holder\")\n            // create a top-level layout for our item views\n            val layout = LinearLayout(parent.context)\n            layout.layoutParams = ViewGroup.LayoutParams(\n                ViewGroup.LayoutParams.MATCH_PARENT,\n                ViewGroup.LayoutParams.MATCH_PARENT\n            )\n\n            // create a text view to display item names\n            val titleView = TextView(parent.context)\n            titleView.layoutParams = ViewGroup.LayoutParams(\n                ViewGroup.LayoutParams.MATCH_PARENT,\n                ViewGroup.LayoutParams.MATCH_PARENT\n            )\n\n            // attach the text view to the item view layout\n            layout.addView(titleView)\n            convertView = layout\n            viewHolder = ViewHolder(titleView)\n            convertView.tag = viewHolder\n        } else {\n            viewHolder = convertView.tag as ViewHolder\n        }\n\n        // as long as we\n        if (adapterData != null) {\n            val item = adapterData!![position]!!\n            viewHolder.title.text = item.name\n            Log.i(TAG, \"Populated view holder with data: ${item.name}\")\n        } else {\n            Log.e(TAG, \"No data in adapter! Failed to populate view holder.\")\n        }\n        return convertView\n    }\n\n    private class ViewHolder(var title: TextView)\n}\n\n```\n\nTo display list data in an activity, instantiate a `ListView`. Then,\nattach an `ExampleListAdapter`:\n\n```kotlin\n// instantiate a ListView programmatically\nval listView = ListView(activity!!.applicationContext)\nlistView.layoutParams = ViewGroup.LayoutParams(\n    ViewGroup.LayoutParams.MATCH_PARENT,\n    ViewGroup.LayoutParams.MATCH_PARENT\n)\n\n// create an adapter with a RealmResults collection\n// and attach it to the ListView\nval adapter = ExampleListAdapter(realm.where(Item::class.java).findAll())\nlistView.adapter = adapter\nval layoutParams = ViewGroup.LayoutParams(\n    ViewGroup.LayoutParams.MATCH_PARENT,\n    ViewGroup.LayoutParams.MATCH_PARENT\n)\nactivity!!.addContentView(listView, layoutParams)\n\n```\n\n## Display Collections in a RecyclerView\nDisplay Realm objects in a\n[RecyclerView](https://developer.android.com/reference/androidx/recyclerview/widget/RecyclerView.html)\nby extending [RealmRecyclerViewAdapter](https://github.com/realm/realm-android-adapters/blob/master/adapters/src/main/java/io/realm/RealmRecyclerViewAdapter.java).\nThe adapter extends `RecyclerView.Adapter`. Implementation works like any\n`RecyclerView` adapter. This provides support\nfor automatically-updating Realm objects.\n\nSubclass `RealmRecyclerViewAdapter` to display\nItem objects in a `RecyclerView`:\n\n#### Java\n\n```java\nimport android.util.Log;\nimport android.view.ViewGroup;\nimport android.widget.TextView;\nimport androidx.recyclerview.widget.RecyclerView;\nimport com.mongodb.realm.examples.model.java.Item;\nimport io.realm.OrderedRealmCollection;\nimport io.realm.RealmRecyclerViewAdapter;\n\n/*\n * ExampleRecyclerViewAdapter: extends the Realm-provided\n * RealmRecyclerViewAdapter to provide data\n * for a RecyclerView to display\n * Realm objects on screen to a user.\n */\nclass ExampleRecyclerViewAdapter\n        extends RealmRecyclerViewAdapter<Item,\n        ExampleRecyclerViewAdapter.ExampleViewHolder> {\n    String TAG = \"REALM_RECYCLER_ADAPTER\";\n\n    ExampleRecyclerViewAdapter(OrderedRealmCollection<Item> data) {\n        super(data, true);\n        Log.i(TAG, \"Created RealmRecyclerViewAdapter for \"\n                + getData().size() + \" items.\");\n    }\n\n    @Override\n    public ExampleViewHolder onCreateViewHolder(ViewGroup parent,\n                                                int viewType) {\n        Log.i(TAG, \"Creating view holder\");\n        TextView textView = new TextView(parent.getContext());\n        textView.setLayoutParams(\n                new ViewGroup.LayoutParams(\n                        ViewGroup.LayoutParams.MATCH_PARENT,\n                        ViewGroup.LayoutParams.WRAP_CONTENT));\n        return new ExampleViewHolder(textView);\n    }\n\n    @Override\n    public void onBindViewHolder(ExampleViewHolder holder,\n                                 int position) {\n        final Item obj = getItem(position);\n        Log.i(TAG, \"Binding view holder: \" + obj.getName());\n        holder.data = obj;\n        holder.title.setText(obj.getName());\n    }\n\n    @Override\n    public long getItemId(int index) {\n        return getItem(index).getId();\n    }\n\n    class ExampleViewHolder extends RecyclerView.ViewHolder {\n        TextView title;\n        public Item data;\n\n        ExampleViewHolder(TextView view) {\n            super(view);\n            title = view;\n        }\n    }\n}\n\n```\n\nTo display list data in an activity, instantiate a `RecyclerView`. Then,\nattach an `ExampleRecyclerViewAdapter`:\n\n```java\n// instantiate a RecyclerView programmatically\nRecyclerView recyclerView =\n        new RecyclerView(activity.getApplicationContext());\nrecyclerView.setLayoutManager(\n        new LinearLayoutManager(activity.getApplicationContext()));\nrecyclerView.setHasFixedSize(true);\nrecyclerView.addItemDecoration(new DividerItemDecoration(\n        activity.getApplicationContext(),\n        DividerItemDecoration.VERTICAL));\n\n// create an adapter with a RealmResults collection\n// and attach it to the RecyclerView\nExampleRecyclerViewAdapter adapter =\n        new ExampleRecyclerViewAdapter(\n                realm.where(Item.class).findAll());\nrecyclerView.setAdapter(adapter);\nViewGroup.LayoutParams layoutParams =\n        new ViewGroup.LayoutParams(\n                ViewGroup.LayoutParams.MATCH_PARENT,\n                ViewGroup.LayoutParams.MATCH_PARENT);\nactivity.addContentView(recyclerView, layoutParams);\n\n```\n\n#### Kotlin\n\n```kotlin\nimport android.util.Log\nimport android.view.ViewGroup\nimport android.widget.TextView\nimport androidx.recyclerview.widget.RecyclerView\nimport com.mongodb.realm.examples.model.kotlin.Item\nimport io.realm.OrderedRealmCollection\nimport io.realm.RealmRecyclerViewAdapter\n\n/*\n * ExampleRecyclerViewAdapter: extends the Realm-provided\n * RealmRecyclerViewAdapter to provide data\n * for a RecyclerView to display\n * Realm objects on screen to a user.\n */\ninternal class ExampleRecyclerViewAdapter(data: OrderedRealmCollection<Item?>?) :\n    RealmRecyclerViewAdapter<Item?,\n            ExampleRecyclerViewAdapter.ExampleViewHolder?>(data, true) {\n    var TAG = \"REALM_RECYCLER_ADAPTER\"\n\n    override fun onCreateViewHolder(parent: ViewGroup,\n                                    viewType: Int): ExampleViewHolder {\n        Log.i(TAG, \"Creating view holder\")\n        val textView = TextView(parent.context)\n        textView.layoutParams = ViewGroup.LayoutParams(\n            ViewGroup.LayoutParams.MATCH_PARENT,\n            ViewGroup.LayoutParams.WRAP_CONTENT\n        )\n        return ExampleViewHolder(textView)\n    }\n\n    override fun onBindViewHolder(holder: ExampleViewHolder, position: Int) {\n        val obj = getItem(position)\n        Log.i(TAG, \"Binding view holder: ${obj!!.name}\")\n        holder.data = obj\n        holder.title.text = obj.name\n    }\n\n    override fun getItemId(index: Int): Long {\n        return getItem(index)!!.id.toLong()\n    }\n\n    internal inner class ExampleViewHolder(var title: TextView)\n        : RecyclerView.ViewHolder(title) {\n        var data: Item? = null\n    }\n\n    init {\n        Log.i(TAG,\n            \"Created RealmRecyclerViewAdapter for ${getData()!!.size} items.\")\n    }\n}\n\n```\n\nTo display list data in an activity, instantiate a `RecyclerView`. Then,\nattach an `ExampleRecyclerViewAdapter`:\n\n```kotlin\n// instantiate a RecyclerView programmatically\nval recyclerView = RecyclerView(activity!!.applicationContext)\nrecyclerView.layoutManager =\n    LinearLayoutManager(activity!!.applicationContext)\nrecyclerView.setHasFixedSize(true)\nrecyclerView.addItemDecoration(\n    DividerItemDecoration(activity!!.applicationContext,\n        DividerItemDecoration.VERTICAL))\n\n// create an adapter with a RealmResults collection\n// and attach it to the RecyclerView\nval adapter = ExampleRecyclerViewAdapter(realm.where(Item::class.java).findAll())\nrecyclerView.adapter = adapter\nval layoutParams = ViewGroup.LayoutParams(\n    ViewGroup.LayoutParams.MATCH_PARENT,\n    ViewGroup.LayoutParams.MATCH_PARENT\n)\nactivity!!.addContentView(recyclerView, layoutParams)\n\n```\n\n"
  },
  {
    "path": "docs/guides/async-api.md",
    "content": "# Asynchronous API - Java SDK\nThe Java SDK lets you access network and disk\nresources in two ways: **synchronously** and **asynchronously**. While\nsynchronous, or \"sync\", requests block execution until the request returns\nsuccess or failure, asynchronous, or \"async\", requests assign a\ncallback and proceed execution to the next line of code. When\nthe request returns, the callback runs to process results.\nIn the callback, you can check if the request executed\nsuccessfully and either access the returned results or the returned\nerror.\n\n## Asynchronous Calls\nAsynchronous API requests in the SDK end with the suffix \"Async\".\nThere are several different ways an asynchronous request can behave,\ndepending on which part of the SDK you're using.\n\n### Realm.Callback\nAsynchronous calls to open a realm,\nuse a final parameter of type `Realm.Callback`. To retrieve returned values after the\nrequest completes, implement the `onSuccess()` method in the callback\nobject passed as the final parameter to these asynchronous methods. You\nshould also implement the `onError()` method to handle request failures,\nbut it is not required.\n\n#### Java\n\n```java\nRealm.getInstanceAsync(config, new Realm.Callback() {\n    @Override\n    public void onSuccess(@NotNull Realm realm) {\n        Log.v(\"EXAMPLE\", \"Successfully fetched realm instance.\");\n    }\n    public void onError(Exception e) {\n        Log.e(\"EXAMPLE\", \"Failed to get realm instance: \" + e);\n    }\n});\n\n```\n\n#### Kotlin\n\n```kotlin\nRealm.getInstanceAsync(config, object : Realm.Callback() {\n    override fun onSuccess(realm: Realm) {\n        Log.v(\"EXAMPLE\", \"Successfully fetched realm instance.\")\n    }\n\n    fun onError(e: java.lang.Exception) {\n        Log.e(\"EXAMPLE\", \"Failed to get realm instance: $e\")\n    }\n})\n\n```\n\n### RealmAsyncTask\nAsynchronous calls to execute transactions on a realm return\nan instance of `RealmAsyncTask`. You can optionally specify an error\nhandler or a\nsuccess notification for `RealmAsyncTask` by\npassing additional parameters to the asynchronous call. Additionally,\nyou use the `cancel()`\nmethod to stop a transaction from completing. The lambda function passed\nto a `RealmAsyncTask` contains the write operations to include in the\ntransaction.\n\n#### Java\n\n```java\n// transaction logic, success notification, error handler all via lambdas\nrealm.executeTransactionAsync(transactionRealm -> {\n    Item item = transactionRealm.createObject(Item.class);\n}, () -> {\n    Log.v(\"EXAMPLE\", \"Successfully completed the transaction\");\n}, error -> {\n    Log.e(\"EXAMPLE\", \"Failed the transaction: \" + error);\n});\n\n// using class instances for transaction, success, error\nrealm.executeTransactionAsync(new Realm.Transaction() {\n    @Override\n    public void execute(Realm transactionRealm) {\n        Item item = transactionRealm.createObject(Item.class);\n    }\n}, new Realm.Transaction.OnSuccess() {\n    @Override\n    public void onSuccess() {\n        Log.v(\"EXAMPLE\", \"Successfully completed the transaction\");\n    }\n}, new Realm.Transaction.OnError() {\n    @Override\n    public void onError(Throwable error) {\n        Log.e(\"EXAMPLE\", \"Failed the transaction: \" + error);\n    }\n});\n\n```\n\n#### Kotlin\n\n```kotlin\n// using class instances for transaction, success, error\nrealm.executeTransactionAsync(Realm.Transaction { transactionRealm ->\n        val item: Item = transactionRealm.createObject<Item>()\n}, Realm.Transaction.OnSuccess {\n        Log.v(\"EXAMPLE\", \"Successfully completed the transaction\")\n}, Realm.Transaction.OnError { error ->\n        Log.e(\"EXAMPLE\", \"Failed the transaction: $error\")\n})\n\n// transaction logic, success notification, error handler all via lambdas\nrealm.executeTransactionAsync(\n    { transactionRealm ->\n        val item = transactionRealm.createObject<Item>()\n    },\n    { Log.v(\"EXAMPLE\", \"Successfully completed the transaction\") },\n    { error ->\n        Log.e(\"EXAMPLE\", \"Failed the transaction: $error\")\n    })\n\n```\n\n### RealmResults\nAsynchronous reads from a realm using `findAllAsync()` immediately return an empty\n`[RealmResults` instance. The SDK\nexecutes the query on a background thread and populates the\n`RealmResults` instance with the results when the query completes. You\ncan register a listener with `addChangeListener()`\nto receive a notification when the query completes.\n\n#### Java\n\n```java\nRealmResults<Item> items = realm.where(Item.class).findAllAsync();\n// length of items is zero when initially returned\nitems.addChangeListener(new RealmChangeListener<RealmResults<Item>>() {\n    @Override\n    public void onChange(RealmResults<Item> items) {\n        Log.v(\"EXAMPLE\", \"Completed the query.\");\n        // items results now contains all matched objects (more than zero)\n    }\n});\n\n```\n\n#### Kotlin\n\n```kotlin\nval items = realm.where<Item>().findAllAsync()\n// length of items is zero when initially returned\nitems.addChangeListener(RealmChangeListener {\n    Log.v(\"EXAMPLE\", \"Completed the query.\")\n    // items results now contains all matched objects (more than zero)\n})\n\n```\n\n### RealmResultTask\nYou can cancel `RealmResultTask` instances just like\n`RealmAsyncTask`. To access the values returned by your query, you\ncan use:\n\n- `get()` to\nblock until the operation completes\n- `getAsync()`\nto handle the result via an App.Callback\ninstance\n\n#### Java\n\n```java\nDocument queryFilter  = new Document(\"type\", \"perennial\");\nmongoCollection.findOne(queryFilter).getAsync(task -> {\n    if (task.isSuccess()) {\n        Plant result = task.get();\n        Log.v(\"EXAMPLE\", \"successfully found a document: \" + result);\n    } else {\n        Log.e(\"EXAMPLE\", \"failed to find document with: \", task.getError());\n    }\n});\n\n```\n\n#### Kotlin\n\n```kotlin\nval queryFilter = Document(\"type\", \"perennial\")\nmongoCollection.findOne(queryFilter)\n    .getAsync { task ->\n        if (task.isSuccess) {\n            val result = task.get()\n            Log.v(\"EXAMPLE\", \"successfully found a document: $result\")\n        } else {\n            Log.e(\"EXAMPLE\", \"failed to find document with: ${task.error}\")\n        }\n    }\n\n```\n\n## Coroutines\nThe SDK provides a set of Kotlin extensions to request\nasynchronously using coroutines and flows instead of callbacks. You can\nuse these extensions to execute transactions, watch for changes, read,\nand write.\n\n```kotlin\n// open a realm asynchronously\nRealm.getInstanceAsync(config, object : Realm.Callback() {\n    override fun onSuccess(realm: Realm) {\n        Log.v(\"EXAMPLE\", \"Successfully fetched realm instance\")\n\n        CoroutineScope(Dispatchers.Main).launch {\n            // asynchronous transaction\n            realm.executeTransactionAwait(Dispatchers.IO) { transactionRealm: Realm ->\n                if (isActive) {\n                    val item = transactionRealm.createObject<Item>()\n                }\n            }\n        }\n        // asynchronous query\n        val items: Flow<RealmResults<Item>> = realm.where<Item>().findAllAsync().toFlow()\n    }\n\n    fun onError(e: Exception) {\n        Log.e(\"EXAMPLE\", \"Failed to get realm instance: $e\")\n    }\n})\n\n```\n\n> Tip:\n> The `toFlow()` extension method passes frozen Realm objects to safely\ncommunicate between threads.\n>\n\n> Seealso:\n> The SDK also includes Kotlin extensions that make specifying type\nparameters for Realm reads and writes easier.\n>\n"
  },
  {
    "path": "docs/guides/crud/create.md",
    "content": "# CRUD - Create - Java SDK\n## About the Examples on this Page\nThe examples on this page use the data model of a project\nmanagement app that has two Realm object types: `Project`\nand `Task`. A `Project` has zero or more `Tasks`.\n\nSee the schema for these two classes, `Project` and\n`Task`, below:\n\n#### Java\n\n```java\n\nimport org.bson.types.ObjectId;\n\nimport io.realm.RealmObject;\nimport io.realm.annotations.PrimaryKey;\nimport io.realm.annotations.RealmClass;\nimport io.realm.annotations.Required;\n\npublic class ProjectTask extends RealmObject {\n    @PrimaryKey\n    public ObjectId _id;\n    @Required\n    public String name;\n    public String assignee;\n    public int progressMinutes;\n    public boolean isComplete;\n    public int priority;\n    @Required\n    public String _partition;\n}\n\n```\n\n```java\n\nimport org.bson.types.ObjectId;\n\nimport io.realm.RealmList;\nimport io.realm.RealmObject;\nimport io.realm.annotations.PrimaryKey;\nimport io.realm.annotations.RealmClass;\nimport io.realm.annotations.Required;\n\npublic class Project extends RealmObject {\n    @PrimaryKey\n    public ObjectId _id;\n    @Required\n    public String name;\n    public RealmList<ProjectTask> tasks = new RealmList<>();\n}\n\n```\n\n#### Kotlin\n\n```kotlin\nimport io.realm.RealmObject\nimport io.realm.annotations.PrimaryKey\nimport io.realm.annotations.Required\nimport org.bson.types.ObjectId\n\nopen class ProjectTask(\n    @PrimaryKey\n    var _id: ObjectId = ObjectId(),\n    @Required\n    var name: String = \"\",\n    var assignee: String? = null,\n    var progressMinutes: Int = 0,\n    var isComplete: Boolean = false,\n    var priority: Int = 0,\n    var _partition: String = \"\"\n): RealmObject()\n\n```\n\n```kotlin\nimport io.realm.RealmList\nimport io.realm.RealmObject\nimport io.realm.annotations.PrimaryKey\nimport io.realm.annotations.Required\nimport org.bson.types.ObjectId\n\nopen class Project(\n    @PrimaryKey\n    var _id: ObjectId = ObjectId(),\n    @Required\n    var name: String = \"\",\n    var tasks: RealmList<ProjectTask> = RealmList(),\n): RealmObject()\n\n```\n\n## Create a New Object\nUse `realm.createObject()`\nin a transaction to create a persistent instance of a Realm object in a\nrealm. You can then modify the returned object with other field values\nusing accessors and mutators.\n\nThe following example demonstrates how to create an object with\n`createObject()`:\n\n#### Java\n\n```java\nrealm.executeTransaction(r -> {\n    // Instantiate the class using the factory function.\n    Turtle turtle = r.createObject(Turtle.class, new ObjectId());\n    // Configure the instance.\n    turtle.setName(\"Max\");\n    // Create a TurtleEnthusiast with a primary key.\n    ObjectId primaryKeyValue = new ObjectId();\n    TurtleEnthusiast turtleEnthusiast = r.createObject(TurtleEnthusiast.class, primaryKeyValue);\n});\n\n```\n\n#### Kotlin\n\n```kotlin\nrealm.executeTransaction { r: Realm ->\n    // Instantiate the class using the factory function.\n    val turtle = r.createObject(Turtle::class.java, ObjectId())\n    // Configure the instance.\n    turtle.name = \"Max\"\n    // Create a TurtleEnthusiast with a primary key.\n    val primaryKeyValue = ObjectId()\n    val turtleEnthusiast = r.createObject(\n        TurtleEnthusiast::class.java,\n        primaryKeyValue\n    )\n}\n\n```\n\nYou can also insert objects into a realm from JSON. Realm\nsupports creating objects from `String`,\n[JSONObject](https://developer.android.com/reference/org/json/JSONObject.html), and\n[InputStream](https://developer.android.com/reference/java/io/InputStream.html) types.\nRealm ignores any properties present in the JSON that are\nnot defined in the Realm object schema.\n\nThe following example demonstrates how to create a single object from JSON with\n`createObjectFromJson()`\nor multiple objects from JSON with\n`createAllFromJson()`:\n\n#### Java\n\n```java\n// Insert from a string\nrealm.executeTransaction(new Realm.Transaction() {\n    @Override\n    public void execute(Realm realm) {\n        realm.createObjectFromJson(Frog.class,\n                \"{ name: \\\"Doctor Cucumber\\\", age: 1, species: \\\"bullfrog\\\", owner: \\\"Wirt\\\" }\");\n    }\n});\n\n// Insert multiple items using an InputStream\nrealm.executeTransaction(new Realm.Transaction() {\n    @Override\n    public void execute(Realm realm) {\n        try {\n            InputStream inputStream = new FileInputStream(\n                    new File(\"path_to_file\"));\n            realm.createAllFromJson(Frog.class, inputStream);\n        } catch (IOException e) {\n            throw new RuntimeException(e);\n        }\n    }\n});\n\n```\n\n#### Kotlin\n\n```kotlin\n// Insert from a string\nrealm.executeTransaction { realm ->\n    realm.createObjectFromJson(\n        Frog::class.java,\n        \"{ name: \\\"Doctor Cucumber\\\", age: 1, species: \\\"bullfrog\\\", owner: \\\"Wirt\\\" }\"\n    )\n}\n\n// Insert multiple items using an InputStream\nrealm.executeTransaction { realm ->\n    try {\n        val inputStream: InputStream =\n            FileInputStream(File(\"path_to_file\"))\n        realm.createAllFromJson(Frog::class.java, inputStream)\n    } catch (e: IOException) {\n        throw RuntimeException(e)\n    }\n}\n\n```\n\n"
  },
  {
    "path": "docs/guides/crud/delete.md",
    "content": "# CRUD - Delete - Java SDK\n## About the Examples on this Page\nThe examples on this page use the data model of a project\nmanagement app that has two Realm object types: `Project`\nand `Task`. A `Project` has zero or more `Tasks`.\n\nSee the schema for these two classes, `Project` and\n`Task`, below:\n\n#### Java\n\n```java\n\nimport org.bson.types.ObjectId;\n\nimport io.realm.RealmObject;\nimport io.realm.annotations.PrimaryKey;\nimport io.realm.annotations.RealmClass;\nimport io.realm.annotations.Required;\n\npublic class ProjectTask extends RealmObject {\n    @PrimaryKey\n    public ObjectId _id;\n    @Required\n    public String name;\n    public String assignee;\n    public int progressMinutes;\n    public boolean isComplete;\n    public int priority;\n    @Required\n    public String _partition;\n}\n\n```\n\n```java\n\nimport org.bson.types.ObjectId;\n\nimport io.realm.RealmList;\nimport io.realm.RealmObject;\nimport io.realm.annotations.PrimaryKey;\nimport io.realm.annotations.RealmClass;\nimport io.realm.annotations.Required;\n\npublic class Project extends RealmObject {\n    @PrimaryKey\n    public ObjectId _id;\n    @Required\n    public String name;\n    public RealmList<ProjectTask> tasks = new RealmList<>();\n}\n\n```\n\n#### Kotlin\n\n```kotlin\nimport io.realm.RealmObject\nimport io.realm.annotations.PrimaryKey\nimport io.realm.annotations.Required\nimport org.bson.types.ObjectId\n\nopen class ProjectTask(\n    @PrimaryKey\n    var _id: ObjectId = ObjectId(),\n    @Required\n    var name: String = \"\",\n    var assignee: String? = null,\n    var progressMinutes: Int = 0,\n    var isComplete: Boolean = false,\n    var priority: Int = 0,\n    var _partition: String = \"\"\n): RealmObject()\n\n```\n\n```kotlin\nimport io.realm.RealmList\nimport io.realm.RealmObject\nimport io.realm.annotations.PrimaryKey\nimport io.realm.annotations.Required\nimport org.bson.types.ObjectId\n\nopen class Project(\n    @PrimaryKey\n    var _id: ObjectId = ObjectId(),\n    @Required\n    var name: String = \"\",\n    var tasks: RealmList<ProjectTask> = RealmList(),\n): RealmObject()\n\n```\n\n## Delete an Object\nTo delete an object from a realm, use either the dynamic or static\nversions of the `deleteFromRealm()` method of a `RealmObject` subclass.\n\nThe following example shows how to delete one object from\nits realm with `deleteFromRealm()`:\n\n#### Java\n\n```java\nrealm.executeTransaction(r -> {\n    // Get a turtle named \"Tony\".\n    Turtle tony = r.where(Turtle.class).equalTo(\"name\", \"Tony\").findFirst();\n    tony.deleteFromRealm();\n    // discard the reference\n    tony = null;\n});\n\n```\n\n#### Kotlin\n\n```kotlin\nrealm.executeTransaction { r: Realm ->\n    // Get a turtle named \"Tony\".\n    var tony = r.where(Turtle::class.java)\n        .equalTo(\"name\", \"Tony\")\n        .findFirst()\n    tony!!.deleteFromRealm()\n    // discard the reference\n    tony = null\n}\n\n```\n\n> Tip:\n> The SDK throws an error if you try to use an object after\nit has been deleted.\n>\n\n## Delete Multiple Objects\nTo delete an object from a realm, use the `deleteAllFromRealm()`\nmethod of the `RealmResults`\ninstance that contains the objects you would like to delete. You can\nfilter the `RealmResults` down to a subset of objects using the\n`where()` method.\n\nThe following example demonstrates how to delete a\ncollection from a realm with `deleteAllFromRealm()`:\n\n#### Java\n\n```java\nrealm.executeTransaction(r -> {\n    // Find turtles older than 2 years old.\n    RealmResults<Turtle> oldTurtles = r.where(Turtle.class).greaterThan(\"age\", 2).findAll();\n    oldTurtles.deleteAllFromRealm();\n});\n\n```\n\n#### Kotlin\n\n```kotlin\nrealm.executeTransaction { r: Realm ->\n    // Find turtles older than 2 years old.\n    val oldTurtles = r.where(Turtle::class.java)\n        .greaterThan(\"age\", 2)\n        .findAll()\n    oldTurtles.deleteAllFromRealm()\n}\n\n```\n\n## Delete an Object and its Dependent Objects\nSometimes, you have dependent objects that you want to delete when\nyou delete the parent object. We call this a **chaining\ndelete**. Realm does not delete the dependent\nobjects for you. If you do not delete the objects yourself,\nthey will remain orphaned in your realm. Whether or not\nthis is a problem depends on your application's needs.\n\nCurrently, the best way to delete dependent objects is to\niterate through the dependencies and delete them before\ndeleting the parent object.\n\nThe following example demonstrates how to perform a\nchaining delete by first deleting all of Ali's turtles,\nthen deleting Ali:\n\n#### Java\n\n```java\nrealm.executeTransaction(r -> {\n    // Find a turtle enthusiast named \"Ali\"\n    TurtleEnthusiast ali = r.where(TurtleEnthusiast.class).equalTo(\"name\", \"Ali\").findFirst();\n    // Delete all of ali's turtles\n    ali.getTurtles().deleteAllFromRealm();\n    ali.deleteFromRealm();\n});\n\n```\n\n#### Kotlin\n\n```kotlin\nrealm.executeTransaction { r: Realm ->\n    // Find a turtle enthusiast named \"Ali\"\n    val ali = r.where(TurtleEnthusiast::class.java)\n        .equalTo(\"name\", \"Ali\").findFirst()\n    // Delete all of ali's turtles\n    ali!!.turtles!!.deleteAllFromRealm()\n    ali.deleteFromRealm()\n}\n\n```\n\n## Delete All Objects of a Specific Type\nRealm supports deleting all instances of a Realm type from a realm.\n\nThe following example demonstrates how to delete all\nTurtle instances from a realm with `delete()`:\n\n#### Java\n\n```java\nrealm.executeTransaction(r -> {\n    r.delete(Turtle.class);\n});\n\n```\n\n#### Kotlin\n\n```kotlin\nrealm.executeTransaction { r: Realm ->\n    r.delete(Turtle::class.java)\n}\n\n```\n\n## Delete All Objects in a Realm\nIt is possible to delete all objects from the realm. This\ndoes not affect the schema of the realm. This is useful for\nquickly clearing out your realm while prototyping.\n\nThe following example demonstrates how to delete everything\nfrom a realm with `deleteAll()`:\n\n#### Java\n\n```java\nrealm.executeTransaction(r -> {\n    r.deleteAll();\n});\n\n```\n\n#### Kotlin\n\n```kotlin\nrealm.executeTransaction { r: Realm ->\n    r.deleteAll()\n}\n\n```\n\n## Delete an Object Using an Iterator\nBecause realm collections always reflect the latest state, they\ncan appear, disappear, or change while you iterate over a collection.\nTo get a stable collection you can iterate over, you can create a\n**snapshot** of a collection's data. A snapshot guarantees the order of\nelements will not change, even if an element is deleted.\n\nFor an example, refer to Iteration.\n"
  },
  {
    "path": "docs/guides/crud/filter-data.md",
    "content": "# Filter Data - Java SDK\n## Query Engine\nTo filter data in your realm, use the Realm query engine.\n\nThere are two ways to access the query engine with the Java SDK:\n\n- Fluent interface\n- Realm Query Language\n\n## Fluent Interface\nThe Java SDK uses a [Fluent interface](https://en.wikipedia.org/wiki/Fluent_interface)\nto construct multi-clause queries that are passed to the query engine.\n\nSee RealmQuery API\nfor a complete list of available methods.\n\nThere are several types of operators available to filter a\nRealm collection.\nFilters work by **evaluating** an operator expression for\nevery object in the collection being\nfiltered. If the expression resolves to `true`, Realm\nDatabase includes the object in the results collection.\n\nAn **expression** consists of one of the following:\n\n- The name of a property of the object currently being evaluated.\n- An operator and up to two argument expression(s).\n- A literal string, number, or date.\n\n### About the Examples In This Section\nThe examples in this section use a simple data set for a\ntask list app. The two Realm object types are `Project`\nand `Task`. A `Task` has a name, assignee's name, and\ncompleted flag. There is also an arbitrary number for\npriority (higher is more important) and a count of\nminutes spent working on it. A `Project` has zero or more\n`Tasks`.\n\nSee the schema for these two classes, `Project` and\n`Task`, below:\n\n#### Java\n\n```java\n\nimport org.bson.types.ObjectId;\n\nimport io.realm.RealmObject;\nimport io.realm.annotations.PrimaryKey;\nimport io.realm.annotations.RealmClass;\nimport io.realm.annotations.Required;\n\npublic class ProjectTask extends RealmObject {\n    @PrimaryKey\n    public ObjectId _id;\n    @Required\n    public String name;\n    public String assignee;\n    public int progressMinutes;\n    public boolean isComplete;\n    public int priority;\n    @Required\n    public String _partition;\n}\n\n```\n\n```java\n\nimport org.bson.types.ObjectId;\n\nimport io.realm.RealmList;\nimport io.realm.RealmObject;\nimport io.realm.annotations.PrimaryKey;\nimport io.realm.annotations.RealmClass;\nimport io.realm.annotations.Required;\n\npublic class Project extends RealmObject {\n    @PrimaryKey\n    public ObjectId _id;\n    @Required\n    public String name;\n    public RealmList<ProjectTask> tasks = new RealmList<>();\n}\n\n```\n\n#### Kotlin\n\n```kotlin\nimport io.realm.RealmObject\nimport io.realm.annotations.PrimaryKey\nimport io.realm.annotations.Required\nimport org.bson.types.ObjectId\n\nopen class ProjectTask(\n    @PrimaryKey\n    var _id: ObjectId = ObjectId(),\n    @Required\n    var name: String = \"\",\n    var assignee: String? = null,\n    var progressMinutes: Int = 0,\n    var isComplete: Boolean = false,\n    var priority: Int = 0,\n    var _partition: String = \"\"\n): RealmObject()\n\n```\n\n```kotlin\nimport io.realm.RealmList\nimport io.realm.RealmObject\nimport io.realm.annotations.PrimaryKey\nimport io.realm.annotations.Required\nimport org.bson.types.ObjectId\n\nopen class Project(\n    @PrimaryKey\n    var _id: ObjectId = ObjectId(),\n    @Required\n    var name: String = \"\",\n    var tasks: RealmList<ProjectTask> = RealmList(),\n): RealmObject()\n\n```\n\n### Comparison Operators\nThe most straightforward operation in a search is to compare\nvalues.\n\n|Operator|Description|\n| --- | --- |\n|`between`|Evaluates to `true` if the left-hand numerical or date expression is between or equal to the right-hand range. For dates, this evaluates to `true` if the left-hand date is within the right-hand date range.|\n|equalTo|Evaluates to `true` if the left-hand expression is equal to the right-hand expression.|\n|greaterThan|Evaluates to `true` if the left-hand numerical or date expression is greater than the right-hand numerical or date expression. For dates, this evaluates to `true` if the left-hand date is later than the right-hand date.|\n|greaterThanOrEqualTo|Evaluates to `true` if the left-hand numerical or date expression is greater than or equal to the right-hand numerical or date expression. For dates, this evaluates to `true` if the left-hand date is later than or the same as the right-hand date.|\n|`in`|Evaluates to `true` if the left-hand expression is in the right-hand list.|\n|lessThan|Evaluates to `true` if the left-hand numerical or date expression is less than the right-hand numerical or date expression. For dates, this evaluates to `true` if the left-hand date is earlier than the right-hand date.|\n|lessThanOrEqualTo|Evaluates to `true` if the left-hand numeric expression is less than or equal to the right-hand numeric expression. For dates, this evaluates to `true` if the left-hand date is earlier than or the same as the right-hand date.|\n|notEqualTo|Evaluates to `true` if the left-hand expression is not equal to the right-hand expression.|\n\n> Example:\n> The following example uses the query engine's\ncomparison operators to:\n>\n> - Find high priority tasks by comparing the value of the `priority` property value with a threshold number, above which priority can be considered high.\n> - Find just-started or short-running tasks by seeing if the `progressMinutes` property falls within a certain range.\n> - Find unassigned tasks by finding tasks where the `assignee` property is equal to `null`.\n> - Find tasks assigned to specific teammates Ali or Jamie by seeing if the `assignee` property is in a list of names.\n>\n> #### Java\n>\n> ```java\n> RealmQuery<ProjectTask> tasksQuery = realm.where(ProjectTask.class);\n> Log.i(\"EXAMPLE\", \"High priority tasks: \" + tasksQuery.greaterThan(\"priority\", 5).count());\n> Log.i(\"EXAMPLE\", \"Just-started or short tasks: \" + tasksQuery.between(\"progressMinutes\", 1, 10).count());\n> Log.i(\"EXAMPLE\", \"Unassigned tasks: \" + tasksQuery.isNull(\"assignee\").count());\n> Log.i(\"EXAMPLE\", \"Ali or Jamie's tasks: \" + tasksQuery.in(\"assignee\", new String[]{\"Ali\", \"Jamie\"}).count());\n>\n> ```\n>\n>\n> #### Kotlin\n>\n> ```kotlin\n> val tasksQuery = realm.where(ProjectTask::class.java)\n> Log.i(\"EXAMPLE\", \"High priority tasks: \" + tasksQuery.greaterThan(\"priority\", 5).count())\n> Log.i(\"EXAMPLE\", \"Just-started or short tasks: \" + tasksQuery.between(\"progressMinutes\", 1, 10).count())\n> Log.i(\"EXAMPLE\", \"Unassigned tasks: \" + tasksQuery.isNull(\"assignee\").count())\n> Log.i(\"EXAMPLE\", \"Ali or Jamie's tasks: \" + tasksQuery.`in`(\"assignee\", arrayOf(\"Ali\", \"Jamie\")).count())\n>\n> ```\n>\n>\n\n### Logical Operators\nYou can make compound predicates using logical operators.\n\n|Operator|Description|\n| --- | --- |\n|and|Evaluates to `true` if both left-hand and right-hand expressions are `true`.|\n|not|Negates the result of the given expression.|\n|or|Evaluates to `true` if either expression returns `true`.|\n\n> Example:\n> We can use the query language's logical operators to find\nall of Ali's completed tasks. That is, we find all tasks\nwhere the `assignee` property value is equal to 'Ali' AND\nthe `isComplete` property value is `true`:\n>\n> #### Java\n>\n> ```java\n> RealmQuery<ProjectTask> tasksQuery = realm.where(ProjectTask.class);\n> Log.i(\"EXAMPLE\", \"Ali has completed \" +\n>         tasksQuery.equalTo(\"assignee\", \"Ali\").and().equalTo(\"isComplete\", true).findAll().size() +\n>         \" tasks.\");\n>\n> ```\n>\n>\n> #### Kotlin\n>\n> ```kotlin\n> val tasksQuery = realm.where(ProjectTask::class.java)\n> Log.i(\"EXAMPLE\", \"Ali has completed \" +\n>             tasksQuery.equalTo(\"assignee\", \"Ali\").and()\n>                 .equalTo(\"isComplete\", true).findAll().size + \" tasks.\")\n>\n> ```\n>\n>\n\n### String Operators\nYou can compare string values using these string operators.\nRegex-like wildcards allow more flexibility in search.\n\n|Operator|Description|\n| --- | --- |\n|beginsWith|Evaluates to `true` if the left-hand string expression begins with the right-hand string expression. This is similar to `contains`, but only matches if the left-hand string expression is found at the beginning of the right-hand string expression.|\n|`contains`|Evaluates to `true` if the left-hand string expression is found anywhere in the right-hand string expression.|\n|endsWith|Evaluates to `true` if the left-hand string expression ends with the right-hand string expression. This is similar to `contains`, but only matches if the left-hand string expression is found at the very end of the right-hand string expression.|\n|like|Evaluates to `true` if the left-hand string expression matches the right-hand string wildcard string expression. A wildcard string expression is a string that uses normal characters with two special wildcard characters: The `*` wildcard matches zero or more of any character The `?` wildcard matches any character. For example, the wildcard string \"d?g\" matches \"dog\", \"dig\", and \"dug\", but not \"ding\", \"dg\", or \"a dog\".|\n|equalTo|Evaluates to `true` if the left-hand string is lexicographically equal to the right-hand string.|\n\n> Example:\n> We use the query engine's string operators to find\nprojects with a name starting with the letter 'e' and\nprojects with names that contain 'ie':\n>\n> #### Java\n>\n> ```java\n> RealmQuery<Project> projectsQuery = realm.where(Project.class);\n> // Pass Case.INSENSITIVE as the third argument for case insensitivity.\n> Log.i(\"EXAMPLE\", \"Projects that start with 'e': \"\n>         + projectsQuery.beginsWith(\"name\", \"e\", Case.INSENSITIVE).count());\n> Log.i(\"EXAMPLE\", \"Projects that contain 'ie': \"\n>         + projectsQuery.contains(\"name\", \"ie\").count());\n>\n> ```\n>\n>\n> #### Kotlin\n>\n> ```kotlin\n> val projectsQuery = realm.where(Project::class.java)\n> // Pass Case.INSENSITIVE as the third argument for case insensitivity.\n> Log.i(\"EXAMPLE\", \"Projects that start with 'e': \"\n>             + projectsQuery.beginsWith(\"name\", \"e\", Case.INSENSITIVE).count())\n> Log.i(\"EXAMPLE\", \"Projects that contain 'ie': \"\n>         + projectsQuery.contains(\"name\", \"ie\").count())\n>\n> ```\n>\n>\n\n> Note:\n> Case-insensitive string operators only support the\n`Latin Basic`, `Latin Supplement`, `Latin Extended A`, and\n`Latin Extended B (UTF-8 range 0-591)` character sets. Setting\nthe case insensitive flag in queries when using `equalTo`,\n`notEqualTo`, `contains`, `endsWith`, `beginsWith`, or\n`like` only works on English locale characters.\n>\n\n### Aggregate Operators\nYou can apply an aggregate operator to a collection property\nof a Realm object. Aggregate operators traverse a\ncollection and reduce it\nto a single value.\n\n|Operator|Description|\n| --- | --- |\n|average|Evaluates to the average value of a given numerical property across a collection.|\n|count|Evaluates to the number of objects in the given collection.|\n|max|Evaluates to the highest value of a given numerical property across a collection.|\n|min|Evaluates to the lowest value of a given numerical property across a collection.|\n|sum|Evaluates to the sum of a given numerical property across a collection.|\n\n> Example:\n> We create a couple of filters to show different facets of\nthe data:\n>\n> - Projects with average tasks priority above 5.\n> - Long running projects.\n>\n> #### Java\n>\n> ```java\n> RealmQuery<ProjectTask> tasksQuery = realm.where(ProjectTask.class);\n> /*\n> Aggregate operators do not support dot-notation, so you\n> cannot directly operate on a property of all of the objects\n> in a collection property.\n>\n> You can operate on a numeric property of the top-level\n> object, however:\n> */\n> Log.i(\"EXAMPLE\", \"Tasks average priority: \" + tasksQuery.average(\"priority\"));\n>\n> ```\n>\n>\n> #### Kotlin\n>\n> ```kotlin\n> val tasksQuery = realm.where(ProjectTask::class.java)\n> /*\n> Aggregate operators do not support dot-notation, so you\n> cannot directly operate on a property of all of the objects\n> in a collection property.\n>\n> You can operate on a numeric property of the top-level\n> object, however:\n> */Log.i(\"EXAMPLE\", \"Tasks average priority: \" + tasksQuery.average(\"priority\"))\n>\n> ```\n>\n>\n\n## Filter, Sort, Limit, Unique, and Chain Queries\n### About the Examples in This Section\nThe examples in this section use two Realm object types: `Teacher`\nand `Student`.\n\nSee the schema for these two classes below:\n\n#### Java\n\n```java\nimport io.realm.RealmList;\nimport io.realm.RealmObject;\n\npublic class Teacher extends RealmObject {\n    private String name;\n    private Integer numYearsTeaching;\n    private String subject;\n    private RealmList<Student> students;\n    public Teacher() {}\n\n    public String getName() { return name; }\n    public void setName(String name) { this.name = name; }\n    public Integer getNumYearsTeaching() { return numYearsTeaching; }\n    public void setNumYearsTeaching(Integer numYearsTeaching) { this.numYearsTeaching = numYearsTeaching; }\n    public String getSubject() { return subject; }\n    public void setSubject(String subject) { this.subject = subject; }\n    public RealmList<Student> getStudents() { return students; }\n    public void setStudents(RealmList<Student> students) { this.students = students; }\n}\n\n```\n\n```java\nimport io.realm.RealmObject;\nimport io.realm.RealmResults;\nimport io.realm.annotations.LinkingObjects;\n\npublic class Student extends RealmObject {\n    private String name;\n    private Integer year;\n    @LinkingObjects(\"students\")\n    private final RealmResults<Teacher> teacher = null;\n    public Student() {}\n\n    public String getName() { return name; }\n    public void setName(String name) { this.name = name; }\n    public Integer getYear() { return year; }\n    public void setYear(Integer year) { this.year = year; }\n    public RealmResults<Teacher> getTeacher() { return teacher; }\n}\n\n```\n\n#### Kotlin\n\n```kotlin\nimport io.realm.RealmList\nimport io.realm.RealmObject\n\nopen class Teacher : RealmObject() {\n    var name: String? = null\n    var numYearsTeaching: Int? = null\n    var subject: String? = null\n    var students: RealmList<Student>? = null\n}\n\n```\n\n```kotlin\nimport io.realm.RealmObject\nimport io.realm.RealmResults\nimport io.realm.annotations.LinkingObjects\n\nopen class Student : RealmObject() {\n    var name: String? = null\n    var year: Int? = null\n\n    @LinkingObjects(\"students\")\n    val teacher: RealmResults<Teacher>? = null\n}\n\n```\n\n### Filters\nYou can build filters using the operator methods of the\n[fluent interface](https://en.wikipedia.org/wiki/Fluent_interface) exposed by the\n`RealmQuery` class:\n\n#### Java\n\n```java\n// Build the query looking at all teachers:\nRealmQuery<Teacher> query = realm.where(Teacher.class);\n\n// Add query conditions:\nquery.equalTo(\"name\", \"Ms. Langtree\");\nquery.or().equalTo(\"name\", \"Mrs. Jacobs\");\n\n// Execute the query:\nRealmResults<Teacher> result1 = query.findAll();\n\n// Or alternatively do the same all at once (the \"Fluent interface\"):\nRealmResults<Teacher> result2 = realm.where(Teacher.class)\n        .equalTo(\"name\", \"Ms. Langtree\")\n        .or()\n        .equalTo(\"name\", \"Mrs. Jacobs\")\n        .findAll();\n\n```\n\n#### Kotlin\n\n```kotlin\n// Build the query looking at all teachers:\nval query = realm.where(Teacher::class.java)\n\n// Add query conditions:\nquery.equalTo(\"name\", \"Ms. Langtree\")\nquery.or().equalTo(\"name\", \"Mrs. Jacobs\")\n\n// Execute the query:\nval result1 = query.findAll()\n\n// Or alternatively do the same all at once (the \"Fluent interface\"):\nval result2 = realm.where(Teacher::class.java)\n    .equalTo(\"name\", \"Ms. Langtree\")\n    .or()\n    .equalTo(\"name\", \"Mrs. Jacobs\")\n    .findAll()\n\n```\n\nThis gives you a new instance of the class `RealmResults`,\ncontaining teachers with the name \"Ms. Langtree\" or \"Mrs. Jacobs\".\n\n`RealmQuery` includes several methods that can execute queries:\n\n- `findAll()` blocks until\nit finds all objects that meet the query conditions\n- `findAllAsync()`\nreturns immediately and finds all objects that meet the query\nconditions asynchronously on a background thread\n- `findFirst()` blocks\nuntil it finds the first object that meets the query conditions\n- `findFirstAsync()`\nreturns immediately and finds the first object that meets the query\nconditions asynchronously on a background thread\n\nQueries return a list of references to the matching Realm\nobjects using the RealmResults type.\n\n#### Link Queries\nWhen referring to an object property, you can use **dot notation** to refer\nto child properties of that object. You can refer to the properties of\nembedded objects and relationships with dot notation.\n\nFor example, consider a query for all teachers with a student named\n\"Wirt\" or \"Greg\":\n\n#### Java\n\n```java\n// Find all teachers who have students with the names \"Wirt\" or \"Greg\"\nRealmResults<Teacher> result = realm.where(Teacher.class)\n        .equalTo(\"students.name\", \"Wirt\")\n        .or()\n        .equalTo(\"students.name\", \"Greg\")\n        .findAll();\n\n```\n\n#### Kotlin\n\n```kotlin\n// Find all teachers who have students with the names \"Wirt\" or \"Greg\"\nval result = realm.where(Teacher::class.java)\n    .equalTo(\"students.name\", \"Wirt\")\n    .or()\n    .equalTo(\"students.name\", \"Greg\")\n    .findAll()\n\n```\n\nYou can even use dot notation to query inverse relationships:\n\n#### Java\n\n```java\n// Find all students who have teachers with the names \"Ms. Langtree\" or \"Mrs. Jacobs\"\nRealmResults<Student> result = realm.where(Student.class)\n        .equalTo(\"teacher.name\", \"Ms. Langtree\")\n        .or()\n        .equalTo(\"teacher.name\", \"Mrs. Jacobs\")\n        .findAll();\n\n```\n\n#### Kotlin\n\n```kotlin\n// Find all students who have teachers with the names \"Ms. Langtree\" or \"Mrs. Jacobs\"\nval result = realm.where(Student::class.java)\n    .equalTo(\"teacher.name\", \"Ms. Langtree\")\n    .or()\n    .equalTo(\"teacher.name\", \"Mrs. Jacobs\")\n    .findAll()\n\n```\n\n### Sort Results\n> Important:\n> Realm applies the `distinct()`, `sort()` and\n`limit()` methods in the order you specify. Depending on the\ndata set this can alter the query result. Generally, you should\napply `limit()` last to avoid unintended result sets.\n>\n\nYou can define the order of query results using the\n`sort()`\nmethod:\n\n#### Java\n\n```java\n// Find all students in year 7, and sort them by name\nRealmResults<Student> result = realm.where(Student.class)\n        .equalTo(\"year\", 7)\n        .sort(\"name\")\n        .findAll();\n\n// Alternatively, find all students in year 7\nRealmResults<Student> unsortedResult = realm.where(Student.class)\n        .equalTo(\"year\", 7)\n        .findAll();\n// then sort the results set by name\nRealmResults<Student> sortedResult = unsortedResult.sort(\"name\");\n\n```\n\n#### Kotlin\n\n```kotlin\n// Find all students in year 7, and sort them by name\nval result: RealmResults<Student> = realm.where(Student::class.java)\n    .equalTo(\"year\", 7L)\n    .sort(\"name\")\n    .findAll()\n\n// Alternatively, find all students in year 7\nval unsortedResult: RealmResults<Student> = realm.where(Student::class.java)\n    .equalTo(\"year\", 7L)\n    .findAll()\n// then sort the results set by name\nval sortedResult = unsortedResult.sort(\"name\")\n\n```\n\nSorts organize results in ascending order by default. To organize results\nin descending order, pass `Sort.DESCENDING` as a second argument.\nYou can resolve sort order ties between identical property values\nby passing an array of properties instead of a single property: in the\nevent of a tie, Realm sorts the tied objects by subsequent\nproperties in order.\n\n> Note:\n> Realm uses non-standard sorting for upper and lowercase\nletters, sorting them together rather than sorting uppercase first.\nAs a result, `'- !\"#0&()*,./:;?_+<=>123aAbBcC...xXyYzZ` is the\nactual sorting order in Realm. Additionally, sorting\nstrings only supports the `Latin Basic`, `Latin Supplement`,\n`Latin Extended A`, and `Latin Extended B (UTF-8 range 0–591)`\ncharacter sets.\n>\n\n### Limit Results\nYou can cap the number of query results to a specific maximum number\nusing the `limit()`\nmethod:\n\n#### Java\n\n```java\n// Find all students in year 8, and limit the results collection to 10 items\nRealmResults<Student> result = realm.where(Student.class)\n        .equalTo(\"year\", 8)\n        .limit(10)\n        .findAll();\n\n```\n\n#### Kotlin\n\n```kotlin\n// Find all students in year 8, and limit the results collection to 10 items\nval result: RealmResults<Student> = realm.where(Student::class.java)\n    .equalTo(\"year\", 8L)\n    .limit(10)\n    .findAll()\n\n```\n\nLimited result collections automatically update like any other query\nresult. Consequently, objects might drop out of the collection as\nunderlying data changes.\n\n> Tip:\n> Some databases encourage paginating results with limits to avoid\nreading unnecessary data from disk or using too much memory.\n>\n> Since Realm queries are lazy, there is no need to\ntake such measures. Realm only loads objects from query\nresults when they are explicitly accessed.\n>\n\n> Tip:\n> Collection notifications\nreport objects as deleted when they drop out of the result set.\nThis does not necessarily mean that they have been deleted from the\nunderlying realm, just that they are no longer part of the\nquery result.\n>\n\n### Unique Results\nYou can reduce query results to unique values for a given field or fields\nusing the `distinct()` method:\n\n#### Java\n\n```java\n// Find all students in year 9, and cap the result collection at 10 items\nRealmResults<Student> result = realm.where(Student.class)\n        .equalTo(\"year\", 9)\n        .distinct(\"name\")\n        .findAll();\n\n```\n\n#### Kotlin\n\n```kotlin\n// Find all students in year 9, and cap the result collection at 10 items\nval result: RealmResults<Student> = realm.where<Student>(Student::class.java)\n    .equalTo(\"year\", 9L)\n    .distinct(\"name\")\n    .findAll()\n\n```\n\nYou can only call `distinct()` on integer, long, short, and `String`\nfields; other field types will throw an exception. As with sorting,\nyou can specify multiple fields to resolve ties.\n\n### Chain Queries\nYou can apply additional filters to a results collection by calling the\n`where()` method:\n\n#### Java\n\n```java\n// Find all students in year 9 and resolve the query into a results collection\nRealmResults<Student> result = realm.where(Student.class)\n        .equalTo(\"year\", 9)\n        .findAll();\n\n// filter the students results again by teacher name\nRealmResults<Student> filteredResults = result.where().equalTo(\"teacher.name\", \"Ms. Langtree\").findAll();\n\n```\n\n#### Kotlin\n\n```kotlin\n// Find all students in year 9 and resolve the query into a results collection\nval result: RealmResults<Student> = realm.where(Student::class.java)\n    .equalTo(\"year\", 9L)\n    .findAll()\n\n// filter the students results again by teacher name\nval filteredResults =\n    result.where().equalTo(\"teacher.name\", \"Ms. Langtree\").findAll()\n\n```\n\nThe `where()` method returns a `RealmQuery` that you can resolve into\na `RealmResults` using a `find` method. Filtered results can only\nreturn objects of the same type as the original results set, but are\notherwise able to use any filters.\n\n## Query with Realm Query Language\n> Version added: 10.4.0\n\nYou can also query realms using Realm Query Language, a string-based\nquery language to constrain searches when retrieving objects from a realm.\n\nYou can use `RealmQuery.rawPredicate()`.\nFor more information about syntax, usage and limitations,\nrefer to the Realm Query Language reference.\n\nRealm Query Language can use either the class and property names defined\nin your Realm Model classes or the internal names defined with `@RealmField`.\nYou can combine raw predicates with other raw predicates or type-safe\npredicates created with `RealmQuery`:\n\n#### Java\n\n```java\n// Build a RealmQuery based on the Student type\nRealmQuery<Student> query = realm.where(Student.class);\n\n// Simple query\nRealmResults<Student> studentsNamedJane =\n        query.rawPredicate(\"name = 'Jane'\").findAll();\n\n// Multiple predicates\nRealmResults<Student> studentsNamedJaneOrJohn =\n        query.rawPredicate(\"name = 'Jane' OR name = 'John'\").findAll();\n\n// Collection queries\nRealmResults<Student> studentsWithTeachers =\n        query.rawPredicate(\"teacher.@count > 0\").findAll();\nRealmResults<Student> studentsWithSeniorTeachers =\n        query.rawPredicate(\"ALL teacher.numYearsTeaching > 5\").findAll();\n\n// Sub queries\nRealmResults<Student> studentsWithMathTeachersNamedSteven =\n        query.rawPredicate(\"SUBQUERY(teacher, $teacher, $teacher.subject = 'Mathematics' AND $teacher.name = 'Mr. Stevens').@count > 0\").findAll();\n\n// Sort, Distinct, Limit\nRealmResults<Student> students =\n        query.rawPredicate(\"teacher.@count > 0 SORT(year ASCENDING) DISTINCT(name) LIMIT(5)\").findAll();\n\n// Combine two raw predicates\nRealmResults<Student> studentsNamedJaneOrHenry =\n        query.rawPredicate(\"name = 'Jane'\")\n                .rawPredicate(\"name = 'Henry'\").findAll();\n\n// Combine raw predicate with type-safe predicate\nRealmResults<Student> studentsNamedJaneOrHenryAgain =\n        query.rawPredicate(\"name = 'Jane'\")\n                .equalTo(\"name\", \"Henry\").findAll();\n\n```\n\n#### Kotlin\n\n```kotlin\n// Build a RealmQuery based on the Student type\nval query = realm.where(Student::class.java)\n\n// Simple query\nval studentsNamedJane = query.rawPredicate(\"name = 'Jane'\").findAll()\n\n// Multiple predicates\nval studentsNamedJaneOrJohn =\n    query.rawPredicate(\"name = 'Jane' OR name = 'John'\").findAll()\n\n// Collection queries\nval studentsWithTeachers =\n    query.rawPredicate(\"teacher.@count > 0\").findAll()\nval studentsWithSeniorTeachers =\n    query.rawPredicate(\"ALL teacher.numYearsTeaching > 5\").findAll()\n\n// Sub queries\nval studentsWithMathTeachersNamedSteven =\n    query.rawPredicate(\"SUBQUERY(teacher, \\$teacher, \\$teacher.subject = 'Mathematics' AND \\$teacher.name = 'Mr. Stevens').@count > 0\")\n        .findAll()\n\n// Sort, Distinct, Limit\nval students =\n    query.rawPredicate(\"teacher.@count > 0 SORT(year ASCENDING) DISTINCT(name) LIMIT(5)\")\n        .findAll()\n\n// Combine two raw predicates\nval studentsNamedJaneOrHenry = query.rawPredicate(\"name = 'Jane'\")\n    .rawPredicate(\"name = 'Henry'\").findAll()\n\n// Combine raw predicate with type-safe predicate\nval studentsNamedJaneOrHenryAgain =\n    query.rawPredicate(\"name = 'Jane'\")\n        .equalTo(\"name\", \"Henry\").findAll()\n\n```\n"
  },
  {
    "path": "docs/guides/crud/read.md",
    "content": "# CRUD - Read - Java SDK\n## Read Operations\nYou can read back the data that you have\nstored in Realm.\nThe standard data access pattern across Realm\nSDKs is to find, filter, and sort objects, in that order. To\nget the best performance from Realm as your app grows and\nyour queries become more complex, design your app's data\naccess patterns around a solid understanding of Realm\nread characteristics.\n\n### Read Characteristics\nWhen you design your app's data access patterns around the\nfollowing three key characteristics of reads in Realm,\nyou can be confident you are reading data as\nefficiently as possible.\n\n### Results Are Not Copies\nResults to a query are not copies of your data: modifying\nthe results of a query will modify the data on disk\ndirectly. This memory mapping also means that results are\n**live**: that is, they always reflect the current state on\ndisk.\n\n### Results Are Lazy\nRealm defers execution of a query until you access the\nresults. You can chain several filter and sort operations\nwithout requiring extra work to process the intermediate\nstate.\n\n### References Are Retained\nOne benefit of Realm's object model is that\nRealm automatically retains all of an object's\nrelationships as\ndirect references, so you can traverse your graph of\nrelationships directly through the results of a query.\n\nA **direct reference**, or pointer, allows you to access a\nrelated object's properties directly through the reference.\n\nOther databases typically copy objects from database storage\ninto application memory when you need to work with them\ndirectly. Because application objects contain direct\nreferences, you are left with a choice: copy the object\nreferred to by each direct reference out of the database in\ncase it's needed, or just copy the foreign key for each\nobject and query for the object with that key if it's\naccessed. If you choose to copy referenced objects into\napplication memory, you can use up a lot of resources for\nobjects that are never accessed, but if you choose to only\ncopy the foreign key, referenced object lookups can cause\nyour application to slow down.\n\nRealm bypasses all of this using zero-copy\nlive objects. Realm object accessors point directly into\ndatabase storage using memory mapping, so there is no distinction\nbetween the objects in Realm and the results of your query in\napplication memory. Because of this, you can traverse direct references\nacross an entire realm from any query result.\n\n## About the Examples on this Page\nThe examples on this page use the data model of a project\nmanagement app that has two Realm object types: `Project`\nand `Task`. A `Project` has zero or more `Tasks`.\n\nSee the schema for these two classes, `Project` and\n`Task`, below:\n\n#### Java\n\n```java\n\nimport org.bson.types.ObjectId;\n\nimport io.realm.RealmObject;\nimport io.realm.annotations.PrimaryKey;\nimport io.realm.annotations.RealmClass;\nimport io.realm.annotations.Required;\n\npublic class ProjectTask extends RealmObject {\n    @PrimaryKey\n    public ObjectId _id;\n    @Required\n    public String name;\n    public String assignee;\n    public int progressMinutes;\n    public boolean isComplete;\n    public int priority;\n    @Required\n    public String _partition;\n}\n\n```\n\n```java\n\nimport org.bson.types.ObjectId;\n\nimport io.realm.RealmList;\nimport io.realm.RealmObject;\nimport io.realm.annotations.PrimaryKey;\nimport io.realm.annotations.RealmClass;\nimport io.realm.annotations.Required;\n\npublic class Project extends RealmObject {\n    @PrimaryKey\n    public ObjectId _id;\n    @Required\n    public String name;\n    public RealmList<ProjectTask> tasks = new RealmList<>();\n}\n\n```\n\n#### Kotlin\n\n```kotlin\nimport io.realm.RealmObject\nimport io.realm.annotations.PrimaryKey\nimport io.realm.annotations.Required\nimport org.bson.types.ObjectId\n\nopen class ProjectTask(\n    @PrimaryKey\n    var _id: ObjectId = ObjectId(),\n    @Required\n    var name: String = \"\",\n    var assignee: String? = null,\n    var progressMinutes: Int = 0,\n    var isComplete: Boolean = false,\n    var priority: Int = 0,\n    var _partition: String = \"\"\n): RealmObject()\n\n```\n\n```kotlin\nimport io.realm.RealmList\nimport io.realm.RealmObject\nimport io.realm.annotations.PrimaryKey\nimport io.realm.annotations.Required\nimport org.bson.types.ObjectId\n\nopen class Project(\n    @PrimaryKey\n    var _id: ObjectId = ObjectId(),\n    @Required\n    var name: String = \"\",\n    var tasks: RealmList<ProjectTask> = RealmList(),\n): RealmObject()\n\n```\n\n## Read from Realm\nA read from a realm generally consists of the following\nsteps:\n\n- Get all objects of a certain type from the realm.\n- Optionally, filter the results using the query engine.\n- Optionally, sort the results.\n\nAll query, filter, and sort operations return a\nresults collection. The results\ncollections are live, meaning they always contain the latest\nresults of the associated query.\n\n> Important:\n> By default, you can only read or write to a realm in your\napplication's UI thread using\nasynchronous transactions. That is,\nyou can only use `Realm` methods whose name ends with the word\n`Async` in the main thread of your Android application unless you\nexplicitly allow the use of synchronous methods.\n>\n> This restriction exists for the benefit of your application users:\nperforming read and write operations on the UI thread can lead to\nunresponsive or slow UI interactions, so it's usually best to handle\nthese operations either asynchronously or in a background thread.\n\n### Find a Specific Object by Primary Key\nTo find an object with a specific primary key value, open a realm\nand query the primary key field for the desired primary key value\nusing the `RealmQuery.equalTo()` method:\n\n#### Java\n\n```java\nProjectTask task = realm.where(ProjectTask.class).equalTo(\"_id\", PRIMARY_KEY_VALUE.get()).findFirst();\nLog.v(\"EXAMPLE\", \"Fetched object by primary key: \" + task);\n\n```\n\n#### Kotlin\n\n```kotlin\nval task = realm.where(ProjectTask::class.java)\n    .equalTo(\"_id\", ObjectId.get()).findFirst()\nLog.v(\"EXAMPLE\", \"Fetched object by primary key: $task\")\n\n```\n\n### Query All Objects of a Given Type\nThe first step of any read is to **get all objects** of a\ncertain type in a realm. With this results collection, you\ncan operate on all instances on a type or filter and sort to\nrefine the results.\n\nIn order to access all instances of `ProjectTask` and `Project`, use\nthe `where()` method\nto specify a class:\n\n#### Java\n\n```java\nRealmQuery<ProjectTask> tasksQuery = realm.where(ProjectTask.class);\nRealmQuery<Project> projectsQuery = realm.where(Project.class);\n\n```\n\n#### Kotlin\n\n```kotlin\nval tasksQuery = realm.where(ProjectTask::class.java)\nval projectsQuery = realm.where(Project::class.java)\n\n```\n\n### Filter Queries Based on Object Properties\nA **filter** selects a subset of results based on the\nvalue(s) of one or more object properties. Realm provides a\nfull-featured query engine you\ncan use to define filters. The most common use case is to\nfind objects where a certain property matches a certain\nvalue. Additionally, you can compare strings, aggregate over\ncollections of numbers, and use logical operators to build\nup complex queries.\n\nIn the following example, we use the query\nengine's comparison operators to:\n\n- Find high priority tasks by comparing the value of the `priority` property value with a threshold number, above which priority can be considered high.\n- Find just-started or short-running tasks by seeing if the `progressMinutes` property falls within a certain range.\n- Find unassigned tasks by finding tasks where the `assignee` property is equal to null.\n- Find tasks assigned to specific teammates Ali or Jamie by seeing if the `assignee` property is in a list of names.\n\n#### Java\n\n```java\nRealmQuery<ProjectTask> tasksQuery = realm.where(ProjectTask.class);\nLog.i(\"EXAMPLE\", \"High priority tasks: \" + tasksQuery.greaterThan(\"priority\", 5).count());\nLog.i(\"EXAMPLE\", \"Just-started or short tasks: \" + tasksQuery.between(\"progressMinutes\", 1, 10).count());\nLog.i(\"EXAMPLE\", \"Unassigned tasks: \" + tasksQuery.isNull(\"assignee\").count());\nLog.i(\"EXAMPLE\", \"Ali or Jamie's tasks: \" + tasksQuery.in(\"assignee\", new String[]{\"Ali\", \"Jamie\"}).count());\n\n```\n\n#### Kotlin\n\n```kotlin\nval tasksQuery = realm.where(ProjectTask::class.java)\nLog.i(\n    \"EXAMPLE\", \"High priority tasks: \" + tasksQuery.greaterThan(\n        \"priority\",\n        5\n    ).count()\n)\nLog.i(\n    \"EXAMPLE\", \"Just-started or short tasks: \" + tasksQuery.between(\n        \"progressMinutes\",\n        1,\n        10\n    ).count()\n)\nLog.i(\n    \"EXAMPLE\",\n    \"Unassigned tasks: \" + tasksQuery.isNull(\"assignee\").count()\n)\nLog.i(\n    \"EXAMPLE\", \"Ali or Jamie's tasks: \" + tasksQuery.`in`(\n        \"assignee\", arrayOf(\n            \"Ali\",\n            \"Jamie\"\n        )\n    ).count()\n)\n\n```\n\n### Sort Query Results\nA **sort** operation allows you to configure the order in\nwhich Realm returns queried objects. You can sort based on\none or more properties of the objects in the results\ncollection.\n\nRealm only guarantees a consistent order of results when the\nresults are sorted.\n\nThe following code sorts the projects by name in reverse\nalphabetical order (i.e. \"descending\" order).\n\n#### Java\n\n```java\nRealmQuery<Project> projectsQuery = realm.where(Project.class);\nRealmResults<Project> results = projectsQuery.sort(\"name\", Sort.DESCENDING).findAll();\n\n```\n\n#### Kotlin\n\n```kotlin\nval projectsQuery = realm.where(Project::class.java)\nval results = projectsQuery.sort(\"name\", Sort.DESCENDING).findAll()\n\n```\n\n### Query a Relationship\n#### Java\n\nConsider the following relationship between classes `Human` and\n`Cat`. This arrangement allows each human to own a single cat:\n\n```java\nimport org.bson.types.ObjectId;\n\nimport io.realm.RealmObject;\nimport io.realm.annotations.PrimaryKey;\n\npublic class Human extends RealmObject {\n    @PrimaryKey\n    private ObjectId _id = new ObjectId();\n    private String name;\n    private Cat cat; \n\n    public Human(String name) {\n        this.name = name;\n    }\n\n    public Human() {\n    }\n\n    public String getName() {\n        return name;\n    }\n\n    public void setName(String name) {\n        this.name = name;\n    }\n\n    public Cat getCat() {\n        return cat;\n    }\n\n    public void setCat(Cat cat) {\n        this.cat = cat;\n    }\n\n    public ObjectId get_id() {\n        return _id;\n    }\n}\n\n```\n\n```java\nimport org.bson.types.ObjectId;\n\nimport io.realm.RealmObject;\nimport io.realm.RealmResults;\nimport io.realm.annotations.LinkingObjects;\nimport io.realm.annotations.PrimaryKey;\n\npublic class Cat extends RealmObject {\n    @PrimaryKey\n    private ObjectId _id = new ObjectId();\n    private String name = null;\n    @LinkingObjects(\"cat\") \n    private final RealmResults<Human> owner = null; \n    public Cat(String name) {\n        this.name = name;\n    }\n    public Cat() {\n    }\n\n    public ObjectId get_id() {\n        return _id;\n    }\n\n    public String getName() {\n        return name;\n    }\n\n    public void setName(String name) {\n        this.name = name;\n    }\n\n    public RealmResults<Human> getOwner() {\n        return owner;\n    }\n}\n\n```\n\nTo query this relationship, use dot notation in a\nquery to access any property\nof the linked object.\n\n#### Kotlin\n\nConsider the following relationship between classes `Person` and\n`Dog`. This arrangement allows each person to own a single dog:\n\n```kotlin\nimport io.realm.RealmObject\nimport io.realm.annotations.PrimaryKey\nimport org.bson.types.ObjectId\n\nopen class Person(var name : String? = null) : RealmObject() {\n    @PrimaryKey\n    var _id : ObjectId = ObjectId()\n    var dog: Dog? = null \n}\n\n```\n\n```kotlin\nimport io.realm.RealmObject\nimport io.realm.RealmResults\nimport io.realm.annotations.LinkingObjects\nimport io.realm.annotations.PrimaryKey\nimport org.bson.types.ObjectId\n\nopen class Dog(var name : String? = null): RealmObject() {\n    @PrimaryKey\n    var _id : ObjectId = ObjectId()\n    @LinkingObjects(\"dog\") \n    val owner: RealmResults<Person>? = null \n}\n\n```\n\nTo query this relationship, use dot notation in a\nquery to access any property\nof the linked object.\n\n### Query an Inverse Relationship\n#### Java\n\nConsider the following relationship between classes `Cat` and\n`Human`. In this example, all cats link to their human (or\nmultiple humans, if multiple human objects refer to the same cat).\nRealm calculates the owners of each cat for you based on the field\nname you provide to the `@LinkingObjects` annotation:\n\n```java\nimport org.bson.types.ObjectId;\n\nimport io.realm.RealmObject;\nimport io.realm.RealmResults;\nimport io.realm.annotations.LinkingObjects;\nimport io.realm.annotations.PrimaryKey;\n\npublic class Cat extends RealmObject {\n    @PrimaryKey\n    private ObjectId _id = new ObjectId();\n    private String name = null;\n    @LinkingObjects(\"cat\")\n    private final RealmResults<Human> owner = null;\n    public Cat(String name) {\n        this.name = name;\n    }\n    public Cat() {\n    }\n\n    public ObjectId get_id() {\n        return _id;\n    }\n\n    public String getName() {\n        return name;\n    }\n\n    public void setName(String name) {\n        this.name = name;\n    }\n\n    public RealmResults<Human> getOwner() {\n        return owner;\n    }\n}\n```\n\n```java\nimport org.bson.types.ObjectId;\n\nimport io.realm.RealmObject;\nimport io.realm.annotations.PrimaryKey;\n\npublic class Human extends RealmObject {\n    @PrimaryKey\n    private ObjectId _id = new ObjectId();\n    private String name;\n    private Cat cat;\n\n    public Human(String name) {\n        this.name = name;\n    }\n\n    public Human() {\n    }\n\n    public String getName() {\n        return name;\n    }\n\n    public void setName(String name) {\n        this.name = name;\n    }\n\n    public Cat getCat() {\n        return cat;\n    }\n\n    public void setCat(Cat cat) {\n        this.cat = cat;\n    }\n\n    public ObjectId get_id() {\n        return _id;\n    }\n}\n```\n\nTo query this relationship, use dot notation in a\nquery to access any property\nof the linked object.\n\n#### Kotlin\n\nConsider the following relationship between classes `Dog` and\n`Person`. In this example, all dogs link to their owner (or\nmultiple owners, if multiple person objects refer to the same dog).\nRealm calculates the owners of each dog for you based on the field\nname you provide to the `@LinkingObjects` annotation:\n\n```kotlin\nimport io.realm.RealmObject\nimport io.realm.RealmResults\nimport io.realm.annotations.LinkingObjects\nimport io.realm.annotations.PrimaryKey\nimport org.bson.types.ObjectId\n\nopen class Dog(var name : String? = null): RealmObject() {\n    @PrimaryKey\n    var _id : ObjectId = ObjectId()\n    @LinkingObjects(\"dog\")\n    val owner: RealmResults<Person>? = null\n}\n```\n\n```kotlin\nimport io.realm.RealmObject\nimport io.realm.annotations.PrimaryKey\nimport org.bson.types.ObjectId\n\nopen class Person(var name : String? = null) : RealmObject() {\n    @PrimaryKey\n    var _id : ObjectId = ObjectId()\n    var dog: Dog? = null\n}\n```\n\nTo query this relationship, use dot notation in a\nquery to access any property\nof the linked object.\n\n### Aggregate Data\n#### Java\n\n```java\nRealmQuery<ProjectTask> tasksQuery = realm.where(ProjectTask.class);\n/*\nAggregate operators do not support dot-notation, so you\ncannot directly operate on a property of all of the objects\nin a collection property.\n\nYou can operate on a numeric property of the top-level\nobject, however:\n*/\nLog.i(\"EXAMPLE\", \"Tasks average priority: \" + tasksQuery.average(\"priority\"));\n\n```\n\n#### Kotlin\n\n```kotlin\nval tasksQuery = realm.where(ProjectTask::class.java)\n/*\nAggregate operators do not support dot-notation, so you\ncannot directly operate on a property of all of the objects\nin a collection property.\n\nYou can operate on a numeric property of the top-level\nobject, however:\n*/Log.i(\"EXAMPLE\", \"Tasks average priority: \" + tasksQuery.average(\"priority\"))\n\n```\n\n"
  },
  {
    "path": "docs/guides/crud/threading.md",
    "content": "# Threading - Java SDK\nTo make your Android apps fast and responsive, you must\nbalance the computing time needed to lay out the visuals and\nhandle user interactions with the time needed to process\nyour data and run your business logic. Typically, app\ndevelopers spread this work across multiple threads: the\nmain or UI thread for all of the user interface-related\nwork, and one or more background threads to compute heavier\nworkloads before sending it to the UI thread for\npresentation. By offloading heavy work to background\nthreads, the UI thread can remain highly responsive\nregardless of the size of the workload.\n\n## Three Rules to Keep in Mind\nRealm enables simple and safe multithreaded code when you\nfollow these three rules:\n\nYou can write to a\nrealm from any thread, but there can be only one\nwriter at a time. Consequently, write transactions block\neach other. A write on the UI thread may result in your\napp appearing unresponsive while it waits for a write on a\nbackground thread to complete.\n\nLive objects, collections, and realm instances are\n**thread-confined**: that is, they are only valid on the\nthread on which they were created. Practically speaking,\nthis means you cannot pass live instances to other\nthreads. However, Realm offers several mechanisms for\nsharing objects across threads.\n\nRealm's Multiversion Concurrency Control (MVCC) architecture eliminates the need to lock for read operations. The\nvalues you read will never be corrupted or in a\npartially-modified state. You can freely read from realms\non any thread without the need for locks or mutexes.\nUnnecessarily locking would be a performance bottleneck\nsince each thread might need to wait its turn before\nreading.\n\n## Communication Across Threads\nLive objects, collections, and realms are **thread-confined**. If\nyou need to work with the same data across multiple threads, you should\nopen the same realm on multiple threads as separate realm\ninstances. The Java SDK consolidates underlying connections across\nthreads where possible to make this pattern\nmore efficient.\n\nWhen you need to communicate across threads, you have\nseveral options depending on your use case:\n\n- To modify the data on two threads, query\nfor the object on both threads using a\nprimary key.\n- To send a fast, read-only view of an object to other threads,\nfreeze the object.\n- To keep and share many read-only views of the object in your app, copy\nthe object from the realm.\n- To react to changes made on any thread, use\nnotifications.\n- To see changes from other threads in the realm on the current\nthread, refresh your realm\ninstance (event loop threads refresh automatically).\n\n### Intents\nManaged `RealmObject` instances are\nnot thread-safe or `Parcelable`, so you cannot pass them between\nactivities or threads via an `Intent`. Instead, you can pass an object\nidentifier, like a primary key,\nin the `Intent` extras bundle, and then open a new realm instance\nin the separate thread to query for that identifier. Alternatively, you\ncan freeze Realm objects.\n\n> Seealso:\n> You can find working examples in the [Passing Objects](https://github.com/realm/realm-java/blob/master/examples/threadExample/src/main/java/io/realm/examples/threads/PassingObjectsFragment.java)\nportion of the [Java SDK Threading Example](https://github.com/realm/realm-java/tree/master/examples/threadExample).\nThe example shows you how to pass IDs and retrieve a `RealmObject`\nin common Android use cases.\n>\n\n### Frozen Objects\nLive, thread-confined objects work fine in most cases.\nHowever, some apps -- those based on reactive, event\nstream-based architectures, for example -- need to send\nimmutable copies across threads. In this case,\nyou can **freeze** objects, collections, and realms.\n\nFreezing creates an immutable view of a specific object,\ncollection, or realm that still exists on disk and does not\nneed to be deeply copied when passed around to other\nthreads. You can freely share a frozen object across threads\nwithout concern for thread issues.\n\nFrozen objects are not live and do not automatically update. They are\neffectively snapshots of the object state at the time of freezing. When\nyou freeze a realm all child objects and collections also become\nfrozen. You can't modify frozen objects, but you can read the primary\nkey from a frozen object, query a live realm for the underlying\nobject, and then update that live object instance.\n\nFrozen objects remain valid for as long as the realm that\nspawned them stays open. Avoid closing realms that contain frozen\nobjects until all threads are done working with those frozen objects.\n\n> Warning:\n> When working with frozen objects, an attempt to do any of\nthe following throws an exception:\n>\n> - Opening a write transaction on a frozen realm.\n> - Modifying a frozen object.\n> - Adding a change listener to a frozen realm, collection, or object.\n>\n\nOnce frozen, you cannot unfreeze an object. You\ncan use `isFrozen()` to check if an object is frozen.\nThis method is always thread-safe.\n\nTo freeze an object, collection, or realm, use the\n`freeze()` method:\n\n#### Java\n\n```java\nRealm realm = Realm.getInstance(config);\n\n// Get an immutable copy of the realm that can be passed across threads\nRealm frozenRealm = realm.freeze();\nAssert.assertTrue(frozenRealm.isFrozen());\n\nRealmResults<Frog> frogs = realm.where(Frog.class).findAll();\n// You can freeze collections\nRealmResults<Frog> frozenFrogs = frogs.freeze();\nAssert.assertTrue(frozenFrogs.isFrozen());\n\n// You can still read from frozen realms\nRealmResults<Frog> frozenFrogs2 = frozenRealm.where(Frog.class).findAll();\nAssert.assertTrue(frozenFrogs2.isFrozen());\n\nFrog frog = frogs.first();\nAssert.assertTrue(!frog.getRealm().isFrozen());\n\n// You can freeze objects\nFrog frozenFrog = frog.freeze();\nAssert.assertTrue(frozenFrog.isFrozen());\n// Frozen objects have a reference to a frozen realm\nAssert.assertTrue(frozenFrog.getRealm().isFrozen());\n\n```\n\n#### Kotlin\n\n```kotlin\nval realm = Realm.getInstance(config)\n\n// Get an immutable copy of the realm that can be passed across threads\nval frozenRealm = realm.freeze()\nAssert.assertTrue(frozenRealm.isFrozen)\nval frogs = realm.where(Frog::class.java).findAll()\n// You can freeze collections\nval frozenFrogs = frogs.freeze()\nAssert.assertTrue(frozenFrogs.isFrozen)\n\n// You can still read from frozen realms\nval frozenFrogs2 =\n    frozenRealm.where(Frog::class.java).findAll()\nAssert.assertTrue(frozenFrogs2.isFrozen)\nval frog: Frog = frogs.first()!!\nAssert.assertTrue(!frog.realm.isFrozen)\n\n// You can freeze objects\nval frozenFrog: Frog = frog.freeze()\nAssert.assertTrue(frozenFrog.isFrozen)\nAssert.assertTrue(frozenFrog.realm.isFrozen)\n\n```\n\n> Important:\n> Frozen objects preserve an entire copy of the realm that contains\nthem at the moment they were frozen. As a result, freezing a large\nnumber of objects can cause a realm to consume more memory and\nstorage than it might have without frozen objects. If you need to\nseparately freeze a large number of objects for long periods of time,\nconsider copying what you need out of the realm instead.\n>\n\n## Refreshing Realms\nWhen you open a realm, it reflects the most recent successful write\ncommit and remains on that version until it is **refreshed**. This means\nthat the realm will not see changes that happened on another thread\nuntil the next refresh. Realms on any event loop thread\n(including the UI thread) automatically refresh themselves at the\nbeginning of that thread's loop. However, you must manually refresh\nrealm instances that are tied to non-looping threads or that have\nauto-refresh disabled. To refresh a realm, call\n`Realm.refresh()`:\n\n#### Java\n\n```java\nif (!realm.isAutoRefresh()) {\n    // manually refresh\n    realm.refresh();\n}\n\n```\n\n#### Kotlin\n\n```kotlin\nif (!realm.isAutoRefresh) {\n    // manually refresh\n    realm.refresh()\n}\n\n```\n\n> Tip:\n> Realms also automatically refresh after completing a write transaction.\n>\n\n## Realm's Threading Model in Depth\nRealm provides safe, fast, lock-free, and concurrent access\nacross threads with its [Multiversion Concurrency\nControl (MVCC)](https://en.wikipedia.org/wiki/Multiversion_concurrency_control)\narchitecture.\n\n### Compared and Contrasted with Git\nIf you are familiar with a distributed version control\nsystem like [Git](https://git-scm.com/), you may already\nhave an intuitive understanding of MVCC. Two fundamental\nelements of Git are:\n\n- Commits, which are atomic writes.\n- Branches, which are different versions of the commit history.\n\nSimilarly, Realm has atomically-committed writes in the form\nof transactions. Realm also has many\ndifferent versions of the history at any given time, like\nbranches.\n\nUnlike Git, which actively supports distribution and\ndivergence through forking, a realm only has one true latest\nversion at any given time and always writes to the head of\nthat latest version. Realm cannot write to a previous\nversion. This makes sense: your data should converge on one\nlatest version of the truth.\n\n### Internal Structure\nA realm is implemented using a [B+ tree](https://en.wikipedia.org/wiki/B%2B_tree) data structure. The top-level node represents a\nversion of the realm; child nodes are objects in that\nversion of the realm. The realm has a pointer to its latest\nversion, much like how Git has a pointer to its HEAD commit.\n\nRealm uses a copy-on-write technique to ensure\n[isolation](https://en.wikipedia.org/wiki/Isolation_(database_systems)) and\n[durability](https://en.wikipedia.org/wiki/Durability_(database_systems)).\nWhen you make changes, Realm copies the relevant part of the\ntree for writing, then commits the changes in two phases:\n\n- Write changes to disk and verify success.\n- Set the latest version pointer to point to the newly-written version.\n\nThis two-step commit process guarantees that even if the\nwrite failed partway, the original version is not corrupted\nin any way because the changes were made to a copy of the\nrelevant part of the tree. Likewise, the realm's root\npointer will point to the original version until the new\nversion is guaranteed to be valid.\n\nRealm uses zero-copy techniques\nlike memory mapping to handle data. When you read a value\nfrom the realm, you are virtually looking at the value on\nthe actual disk, not a copy of it. This is the basis for\nlive objects. This is also why a realm\nhead pointer can be set to point to the new version after\nthe write to disk has been validated.\n\n## Summary\n- Realm enables simple and safe multithreaded code when you follow\nthese rules: Don't pass live objects to other threads, and don't lock to read.\n- In order to see changes made on other threads in your realm\ninstance, you must manually **refresh** realm instances that do\nnot exist on \"loop\" threads or that have auto-refresh disabled.\n- For apps based on reactive, event-stream-based architectures, you can\n**freeze** objects, collections, and realms in order to pass\ncopies around efficiently to different threads for processing.\n- Realm's multiversion concurrency control (MVCC)\narchitecture is similar to Git's. Unlike Git, Realm has\nonly one true latest version for each realm.\n- Realm commits in two stages to guarantee isolation and\ndurability.\n"
  },
  {
    "path": "docs/guides/crud/update.md",
    "content": "# CRUD - Update - Java SDK\n## About the Examples on this Page\nThe examples on this page use the data model of a project\nmanagement app that has two Realm object types: `Project`\nand `Task`. A `Project` has zero or more `Tasks`.\n\nSee the schema for these two classes, `Project` and\n`Task`, below:\n\n#### Java\n\n```java\n\nimport org.bson.types.ObjectId;\n\nimport io.realm.RealmObject;\nimport io.realm.annotations.PrimaryKey;\nimport io.realm.annotations.RealmClass;\nimport io.realm.annotations.Required;\n\npublic class ProjectTask extends RealmObject {\n    @PrimaryKey\n    public ObjectId _id;\n    @Required\n    public String name;\n    public String assignee;\n    public int progressMinutes;\n    public boolean isComplete;\n    public int priority;\n    @Required\n    public String _partition;\n}\n\n```\n\n```java\n\nimport org.bson.types.ObjectId;\n\nimport io.realm.RealmList;\nimport io.realm.RealmObject;\nimport io.realm.annotations.PrimaryKey;\nimport io.realm.annotations.RealmClass;\nimport io.realm.annotations.Required;\n\npublic class Project extends RealmObject {\n    @PrimaryKey\n    public ObjectId _id;\n    @Required\n    public String name;\n    public RealmList<ProjectTask> tasks = new RealmList<>();\n}\n\n```\n\n#### Kotlin\n\n```kotlin\nimport io.realm.RealmObject\nimport io.realm.annotations.PrimaryKey\nimport io.realm.annotations.Required\nimport org.bson.types.ObjectId\n\nopen class ProjectTask(\n    @PrimaryKey\n    var _id: ObjectId = ObjectId(),\n    @Required\n    var name: String = \"\",\n    var assignee: String? = null,\n    var progressMinutes: Int = 0,\n    var isComplete: Boolean = false,\n    var priority: Int = 0,\n    var _partition: String = \"\"\n): RealmObject()\n\n```\n\n```kotlin\nimport io.realm.RealmList\nimport io.realm.RealmObject\nimport io.realm.annotations.PrimaryKey\nimport io.realm.annotations.Required\nimport org.bson.types.ObjectId\n\nopen class Project(\n    @PrimaryKey\n    var _id: ObjectId = ObjectId(),\n    @Required\n    var name: String = \"\",\n    var tasks: RealmList<ProjectTask> = RealmList(),\n): RealmObject()\n\n```\n\n## Modify an Object\nWithin a transaction, you can update a Realm object the same\nway you would update any other object in your language of\nchoice. Just assign a new value to the property or update\nthe property.\n\nThe following example changes the turtle's name to \"Archibald\" and\nsets Archibald's age to 101 by assigning new values to properties:\n\n#### Java\n\n```java\nrealm.executeTransaction(r -> {\n    // Get a turtle to update.\n    Turtle turtle = r.where(Turtle.class).findFirst();\n    // Update properties on the instance.\n    // This change is saved to the realm.\n    turtle.setName(\"Archibald\");\n    turtle.setAge(101);\n});\n\n```\n\n#### Kotlin\n\n```kotlin\nrealm.executeTransaction { r: Realm ->\n    // Get a turtle to update.\n    val turtle = r.where(Turtle::class.java).findFirst()\n    // Update properties on the instance.\n    // This change is saved to the realm.\n    turtle!!.name = \"Archibald\"\n    turtle.age = 101\n}\n\n```\n\n## Upsert an Object\nAn **upsert** is a write operation that either inserts a new object\nwith a given primary key or updates an existing object that already has\nthat primary key. We call this an upsert because it is an \"**update** or\n**insert**\" operation. This is useful when an object may or may not\nalready exist, such as when bulk importing a dataset into an existing\nrealm. Upserting is an elegant way to update existing entries while\nadding any new entries.\n\nThe following example demonstrates how to upsert an object with\nrealm. We create a new turtle enthusiast named \"Drew\" and then\nupdate their name to \"Andy\" using `insertOrUpdate()`:\n\n#### Java\n\n```java\nrealm.executeTransaction(r -> {\n    ObjectId id = new ObjectId();\n    TurtleEnthusiast drew = new TurtleEnthusiast();\n    drew.set_id(id);\n    drew.setName(\"Drew\");\n    drew.setAge(25);\n    // Add a new turtle enthusiast to the realm. Since nobody with this id\n    // has been added yet, this adds the instance to the realm.\n    r.insertOrUpdate(drew);\n    TurtleEnthusiast andy = new TurtleEnthusiast();\n    andy.set_id(id);\n    andy.setName(\"Andy\");\n    andy.setAge(56);\n    // Judging by the ID, it's the same turtle enthusiast, just with a different name.\n    // As a result, you overwrite the original entry, renaming \"Drew\" to \"Andy\".\n    r.insertOrUpdate(andy);\n});\n\n```\n\n#### Kotlin\n\n```kotlin\nrealm.executeTransaction { r: Realm ->\n    val id = ObjectId()\n    val drew = TurtleEnthusiast()\n    drew._id = id\n    drew.name = \"Drew\"\n    drew.age = 25\n    // Add a new turtle enthusiast to the realm. Since nobody with this id\n    // has been added yet, this adds the instance to the realm.\n    r.insertOrUpdate(drew)\n    val andy = TurtleEnthusiast()\n    andy._id = id\n    andy.name = \"Andy\"\n    andy.age = 56\n    // Judging by the ID, it's the same turtle enthusiast, just with a different name.\n    // As a result, you overwrite the original entry, renaming \"Drew\" to \"Andy\".\n    r.insertOrUpdate(andy)\n}\n\n```\n\nYou can also use `copyToRealmOrUpdate()` to\neither create a new object based on a supplied object or update an\nexisting object with the same primary key value. Use the\n`CHECK_SAME_VALUES_BEFORE_SET`\n`ImportFlag` to only update fields\nthat are different in the supplied object:\n\nThe following example demonstrates how to insert an object or, if an object already\nexists with the same primary key, update only those fields that differ:\n\n#### Java\n\n```java\nrealm.executeTransaction(r -> {\n    ObjectId id = new ObjectId();\n    TurtleEnthusiast drew = new TurtleEnthusiast();\n    drew.set_id(id);\n    drew.setName(\"Drew\");\n    drew.setAge(25);\n    // Add a new turtle enthusiast to the realm. Since nobody with this id\n    // has been added yet, this adds the instance to the realm.\n    r.insertOrUpdate(drew);\n    TurtleEnthusiast andy = new TurtleEnthusiast();\n    andy.set_id(id);\n    andy.setName(\"Andy\");\n    // Judging by the ID, it's the same turtle enthusiast, just with a different name.\n    // As a result, you overwrite the original entry, renaming \"Drew\" to \"Andy\".\n    // the flag passed ensures that we only write the updated name field to the db\n    r.copyToRealmOrUpdate(andy, ImportFlag.CHECK_SAME_VALUES_BEFORE_SET);\n});\n\n```\n\n#### Kotlin\n\n```kotlin\nrealm.executeTransaction { r: Realm ->\n    val id = ObjectId()\n    val drew = TurtleEnthusiast()\n    drew._id = id\n    drew.name = \"Drew\"\n    drew.age = 25\n    // Add a new turtle enthusiast to the realm. Since nobody with this id\n    // has been added yet, this adds the instance to the realm.\n    r.insertOrUpdate(drew)\n    val andy = TurtleEnthusiast()\n    andy._id = id\n    andy.name = \"Andy\"\n    // Judging by the ID, it's the same turtle enthusiast, just with a different name.\n    // As a result, you overwrite the original entry, renaming \"Drew\" to \"Andy\".\n    r.copyToRealmOrUpdate(andy,\n        ImportFlag.CHECK_SAME_VALUES_BEFORE_SET)\n}\n\n```\n\n## Update a Collection\nRealm supports collection-wide updates. A collection update\napplies the same update to specific properties of several\nobjects in a collection at once.\n\nThe following example demonstrates how to update a\ncollection. Thanks to the implicit inverse\nrelationship between the Turtle's\n`owner` property and the TurtleEnthusiast's `turtles` property,\nRealm automatically updates Josephine's list of turtles\nwhen you use `setObject()`\nto update the \"owner\" property for all turtles in the collection.\n\n#### Java\n\n```java\nrealm.executeTransaction(r -> {\n    // Create a turtle enthusiast named Josephine.\n    TurtleEnthusiast josephine = r.createObject(TurtleEnthusiast.class, new ObjectId());\n    josephine.setName(\"Josephine\");\n\n    // Get all turtles named \"Pierogi\".\n    RealmResults<Turtle> turtles = r.where(Turtle.class).equalTo(\"name\", \"Pierogi\").findAll();\n\n    // Give all turtles named \"Pierogi\" to Josephine\n    turtles.setObject(\"owner\", josephine);\n});\n\n```\n\n#### Kotlin\n\n```kotlin\nrealm.executeTransaction { r: Realm ->\n    // Create a turtle enthusiast named Josephine.\n    val josephine = realm.createObject(\n        TurtleEnthusiast::class.java,\n        ObjectId()\n    )\n    josephine.name = \"Josephine\"\n\n    // Get all turtles named \"Pierogi\".\n    val turtles = r.where(Turtle::class.java)\n        .equalTo(\"name\", \"Pierogi\")\n        .findAll()\n\n    // Give all turtles named \"Pierogi\" to Josephine\n    turtles.setObject(\"owner\", josephine)\n}\n\n```\n\n## Iteration\nBecause realm collections always reflect the latest state, they\ncan appear, disappear, or change while you iterate over a collection.\nTo get a stable collection you can iterate over, you can create a\n**snapshot** of a collection's data. A snapshot guarantees the order of\nelements will not change, even if an element is deleted or modified.\n\n`Iterator` objects created from `RealmResults` use snapshots\nautomatically. `Iterator` objects created from `RealmList`\ninstances do *not* use snapshots. Use\n`RealmList.createSnapshot()`\nor\n`RealmResults.createSnapshot()`\nto manually generate a snapshot you can iterate over manually:\n\nThe following example demonstrates how to iterate over a collection\nsafely using either an implicit snapshot created from a `RealmResults`\n`Iterator` or a manual snapshot created from a `RealmList`:\n\n#### Java\n\n```java\nRealmResults<Frog> frogs = realm.where(Frog.class)\n        .equalTo(\"species\", \"bullfrog\")\n        .findAll();\n\n// Use an iterator to rename the species of all bullfrogs\nrealm.executeTransaction(r -> {\n    for (Frog frog : frogs) {\n        frog.setSpecies(\"Lithobates catesbeiana\");\n    }\n});\n\n// Use a snapshot to rename the species of all bullfrogs\nrealm.executeTransaction(r -> {\n    OrderedRealmCollectionSnapshot<Frog> frogsSnapshot = frogs.createSnapshot();\n    for (int i = 0; i < frogsSnapshot.size(); i++) {\n        frogsSnapshot.get(i).setSpecies(\"Lithobates catesbeiana\");\n    }\n});\n\n```\n\n#### Kotlin\n\n```kotlin\nval frogs = realm.where(Frog::class.java)\n    .equalTo(\"species\", \"bullfrog\")\n    .findAll()\n\n// Use an iterator to rename the species of all bullfrogs\nrealm.executeTransaction {\n    for (frog in frogs) {\n        frog.species = \"Lithobates catesbeiana\"\n    }\n}\n\n// Use a snapshot to rename the species of all bullfrogs\nrealm.executeTransaction {\n    val frogsSnapshot = frogs.createSnapshot()\n    for (i in frogsSnapshot.indices) {\n        frogsSnapshot[i]!!.species = \"Lithobates catesbeiana\"\n    }\n}\n\n```\n\n"
  },
  {
    "path": "docs/guides/crud.md",
    "content": "# CRUD - Java SDK\n## Write Operations\nYou can **create** objects in a realm,\n**update** objects in a realm, and eventually **delete**\nobjects from a realm. Because these operations modify the\nstate of the realm, we call them writes.\n\nRealm handles writes in terms of **transactions**. A\ntransaction is a list of read and write operations that\nRealm treats as a single indivisible operation. In other\nwords, a transaction is *all or nothing*: either all of the\noperations in the transaction succeed or none of the\noperations in the transaction take effect.\n\n> Note:\n> All writes must happen in a transaction.\n>\n\nA realm allows only one open write transaction at a time. Realm\nblocks other writes on other threads until the open\ntransaction is complete. Consequently, there is no race\ncondition when reading values from the realm within a\ntransaction.\n\nWhen you are done with your transaction, Realm either\n**commits** it or **cancels** it:\n\n- When Realm **commits** a transaction, Realm writes\nall changes to disk.\n- When Realm **cancels** a write transaction or an operation in\nthe transaction causes an error, all changes are discarded\n(or \"rolled back\").\n\n> Tip:\n> Whenever you create, update, or delete a Realm object,\nyour changes update the representation of that object in\nRealm and emit\nnotifications to any subscribed\nlisteners. As a result, you should only write to Realm\nobjects when necessary to persist data.\n>\n\n> Important:\n> By default, you can only read or write to a realm in your\napplication's UI thread using\nasynchronous transactions. That is,\nyou can only use `Realm` methods whose name ends with the word\n`Async` in the main thread of your Android application unless you\nexplicitly allow the use of synchronous methods.\n>\n> This restriction exists for the benefit of your application users:\nperforming read and write operations on the UI thread can lead to\nunresponsive or slow UI interactions, so it's usually best to handle\nthese operations either asynchronously or in a background thread.\n\n## Managed Objects\n**Managed objects** are live Realm objects that update\nbased on changes to underlying data in Realm. Managed\nobjects can only come from an open realm, and receive updates\nas long as that realm remains open. Managed objects *cannot be passed\nbetween threads*.\n\n## Unmanaged objects\n**Unmanaged objects** are instances of Realm objects that are\nnot live. You can get an unmanaged object by manually constructing a\nRealm object yourself, or by calling\n`[Realm.copyFromRealm()`.\nUnmanaged objects *can be passed between threads*.\n\n## Run a Transaction\nRealm represents each transaction as a callback function\nthat contains zero or more read and write operations. To run\na transaction, define a transaction callback and pass it to\nthe realm's `write` method. Within this callback, you are\nfree to create, read, update, and delete on the realm. If\nthe code in the callback throws an exception when Realm runs\nit, Realm cancels the transaction. Otherwise, Realm commits\nthe transaction immediately after the callback.\n\n> Example:\n> The following code shows how to run a transaction with\n`executeTransaction()`\nor `executeTransactionAsync()`.\nIf the code in the callback throws an exception, Realm\ncancels the transaction. Otherwise, Realm commits the\ntransaction.\n>\n> #### Java\n>\n> ```java\n> realm.executeTransaction(r -> {\n>     // Create a turtle enthusiast named Ali.\n>     TurtleEnthusiast ali = r.createObject(TurtleEnthusiast.class, new ObjectId());\n>     ali.setName(\"Ali\");\n>     // Find turtles younger than 2 years old\n>     RealmResults<Turtle> hatchlings = r.where(Turtle.class).lessThan(\"age\", 2).findAll();\n>     // Give all hatchlings to Ali.\n>     hatchlings.setObject(\"owner\", ali);\n> });\n>\n> ```\n>\n>\n> #### Kotlin\n>\n> ```kotlin\n> realm.executeTransaction { r: Realm ->\n>     // Create a turtle enthusiast named Ali.\n>     val ali = r.createObject(TurtleEnthusiast::class.java, ObjectId())\n>     ali.name = \"Ali\"\n>     // Find turtles younger than 2 years old\n>     val hatchlings =\n>         r.where(Turtle::class.java).lessThan(\"age\", 2).findAll()\n>     // Give all hatchlings to Ali.\n>     hatchlings.setObject(\"owner\", ali)\n> }\n>\n> ```\n>\n>\n"
  },
  {
    "path": "docs/guides/install.md",
    "content": "# Install Realm - Java SDK\n> Note:\n> The Java SDK is in best-effort maintenance mode and **no longer receives\nnew development or non-critical bug fixes. To develop your app with new\nfeatures, use the Kotlin SDK. You can use the Java SDK\nwith the Kotlin SDK in the same project.\n>\n> Learn more about how to Migrate from the Java SDK to the Kotlin SDK.\n>\n\n## Overview\nThis page details how to install Realm using the Java SDK in your project\nand get started.\n\nYou can use multiple SDKs in your project. Because the Java SDK is no longer\nreceiving new development, this is useful if you want to\nuse new features in your app.\n\n## Prerequisites\n- [Android Studio](https://developer.android.com/studio/index.html) version 1.5.1 or higher.\n- Java Development Kit (JDK) 11 or higher.\n- An emulated or hardware Android device for testing.\n- Android API Level 16 or higher (Android 4.1 and above).\n\n## Installation\nRealm only supports the Gradle build system. Follow these steps\nto add the Realm Java SDK to your project.\n\n> Note:\n> Because Realm provides a ProGuard configuration as part\nof the Realm library, you do not need to add any\nRealm-specific rules to your ProGuard configuration.\n>\n\n### Project Gradle Configuration\nTo add local realm to your application, make\nthe following changes to your project-level Gradle build\nfile, typically found at <project>/build.gradle:\n\n#### Gradle Plugin\n\n> Tip:\n> The Java SDK does not yet support the Gradle Plugin syntax. Fortunately,\nyou can still add the SDK to projects that use this syntax.\n>\n\n- Add a `buildscript` block that contains a `repositories` block and a `dependencies` block.\n- Add the `mavenCentral()` repository to the `buildscript.repositories` block.\n- Add the `io.realm:realm-gradle-plugin` dependency to the `buildscript.dependencies` block.\n\n```groovy\nbuildscript {\n    repositories {\n        mavenCentral()\n    }\n    dependencies {\n        classpath \"io.realm:realm-gradle-plugin:10.18.0\"\n    }\n}\n\nplugins {\n    id 'com.android.application' version '7.1.2' apply false\n    id 'com.android.library' version '7.1.2' apply false\n    id 'org.jetbrains.kotlin.android' version '1.6.10' apply false\n    id \"org.jetbrains.kotlin.kapt\" version \"1.6.20\" apply false\n}\n\ntask clean(type: Delete) {\n    delete rootProject.buildDir\n}\n```\n\n#### Gradle Legacy\n\n- Add the `io.realm:realm-gradle-plugin` dependency to the `buildscript.dependencies` block.\n- Add the `mavenCentral()` repository to the `allprojects.repositories` block.\n\n```groovy\nbuildscript {\n    repositories {\n        google()\n    }\n    dependencies {\n        classpath \"com.android.tools.build:gradle:3.5.1\"\n        classpath \"io.realm:realm-gradle-plugin:10.18.0\"\n    }\n}\n\nallprojects {\n    repositories {\n        google()\n        mavenCentral()\n    }\n    dependencies {\n    }\n}\n\ntask clean(type: Delete) {\n    delete rootProject.buildDir\n}\n```\n\n### Application Module Gradle Configuration\nThen, make the following changes to your application-level\nGradle build file, typically found at <project>/app/build.gradle:\n\n#### Gradle Plugin\n\n- Apply the `kotlin-kapt` plugin if your application uses Kotlin\n- Beneath the `plugins` block, apply the `realm-android` plugin.\n\n```groovy\nplugins {\n    id 'com.android.application'\n    id 'org.jetbrains.kotlin.android'\n    id 'org.jetbrains.kotlin.kapt'\n}\n\napply plugin: \"realm-android\"\n\nandroid {\n    compileSdk 31\n    defaultConfig {\n        applicationId \"com.mongodb.example-realm-application\"\n        minSdk 28\n        targetSdk 31\n        versionCode 1\n        versionName \"1.0\"\n        testInstrumentationRunner \"androidx.test.runner.AndroidJUnitRunner\"\n    }\n    buildTypes {\n        release {\n            minifyEnabled false\n            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'\n        }\n    }\n    compileOptions {\n        sourceCompatibility JavaVersion.VERSION_11\n        targetCompatibility JavaVersion.VERSION_11\n    }\n    kotlinOptions {\n        jvmTarget = '11'\n    }\n}\n\ndependencies {\n    implementation 'io.realm:realm-gradle-plugin:10.10.1'\n    implementation 'androidx.core:core-ktx:1.7.0'\n    implementation 'androidx.appcompat:appcompat:1.4.1'\n    implementation 'com.google.android.material:material:1.5.0'\n    implementation 'androidx.constraintlayout:constraintlayout:2.1.3'\n    testImplementation 'junit:junit:4.13.2'\n    androidTestImplementation 'androidx.test.ext:junit:1.1.3'\n    androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'\n}\n```\n\n#### Gradle Legacy\n\n- Apply the `kotlin-kapt` plugin if your application uses Kotlin\n- Apply the `realm-android` plugin\n\n```groovy\napply plugin: 'com.android.application'\napply plugin: 'kotlin-android'\napply plugin: 'kotlin-kapt'\napply plugin: 'realm-android'\n\nandroid {\n    compileSdkVersion 31\n    buildToolsVersion \"29.0.2\"\n    defaultConfig {\n        applicationId \"com.mongodb.example-realm-application\"\n        minSdkVersion 28\n        targetSdkVersion 31\n    }\n    compileOptions {\n        sourceCompatibility 1.11\n        targetCompatibility 1.11\n    }\n    kotlinOptions {\n        jvmTarget = '11'\n    }\n}\n\ndependencies {\n    implementation fileTree(dir: 'libs', include: ['*.jar'])\n    implementation \"org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version\"\n    implementation \"androidx.appcompat:appcompat:1.1.0\"\n    implementation \"androidx.core:core-ktx:1.2.0\"\n}\n```\n\nAfter updating the `build.gradle` files, resolve the dependencies by\nclicking File > Sync Project with Gradle Files.\n\n## Supported Platforms\nRealm's Java SDK enables you to build apps for the\nfollowing platforms:\n\n- Android\n- Wear OS\n- Android Automotive OS\n- Android TV\n- Android Things\n"
  },
  {
    "path": "docs/guides/model-data/data-types/collections.md",
    "content": "# Collections - Java SDK\nA Realm collection is an\nobject that contains zero or more instances of one\ntype. Realm collections\nare homogenous, i.e. all objects in a collection are of the\nsame type.\n\nYou can filter and sort any collection using Realm's\nquery engine. Collections are\nlive, so they always reflect the\ncurrent state of the realm instance on the current\nthread. You can also listen for changes in the collection by subscribing\nto collection notifications.\n\nRealm has two kinds of collections: **lists** and **results**.\n\n## Lists\nRealm objects can contain lists of non-Realm-object data\ntypes. You can model these collections with the type `RealmList<T>`,\nwhere `T` can be the following types:\n\n- `String`\n- `Integer`\n- `UUID`\n- `ObjectId`\n- `Boolean`\n- `Float`\n- `Double`\n- `Short`\n- `Long`\n- `Byte`\n- `byte[]`\n- `Date`\n\n> Seealso:\n> Lists\n>\n\n### List Collections\nA **list collection** represents a to-many\nrelationship between two Realm\ntypes. Lists are mutable: within a write transaction, you\ncan add and remove elements on a list. Lists are not\nassociated with a query.\n\n### Results Collections\nA **results collection** represents the lazily-evaluated\nresults of a query operation. Results are immutable: you\ncannot add or remove elements on the results collection.\nResults have an associated query that determines their\ncontents.\n\nThe `RealmResults` class inherits from\n[AbstractList](https://developer.android.com/reference/java/util/AbstractList) and behaves\nin similar ways. For example, `RealmResults` are ordered, and you can\naccess the individual objects through an index. If a query has no\nmatches, the returned `RealmResults` object will be a list of length\n0, not a `null` object reference.\n\nYou can only modify or delete objects in a `RealmResults` set\nin a write transaction.\n\n## Iteration\nBecause Realm collections are live, objects may move as you\niterate over a collection. You can use\nsnapshots to iterate over collections safely.\n\n## Adapters\nRealm offers adapters to help bind data\nto standard UI widgets. These classes work with any class that\nimplements the `OrderedRealmCollection` interface, which includes\nthe built-in `RealmResults` and `RealmList` classes. For more\ninformation on adapters, see the documentation on\nDisplaying Collections.\n\n> Important:\n> The Realm adapters only accept *managed*\nRealm object instances tied to an instance of a realm.\nTo display non-managed objects, use the general-use Android\n`RecyclerView.Adapter` for recycler views or `ArrayAdapter` for\nlist views.\n>\n\n## Collections are Live\nLike live objects, Realm collections\nare usually **live**:\n\n- Live results collections always reflect the current results of the associated query.\n- Live lists always reflect the current state of the relationship on the realm instance.\n\nThere are three cases when a collection is **not** live:\n\n- The collection is unmanaged, e.g. a List property of a Realm object that has not been added to a realm yet or that has been copied from a realm.\n- The collection is frozen.\n- The collection is part of a snapshot.\n\nCombined with collection notifications, live collections enable clean,\nreactive code. For example, suppose your view displays the\nresults of a query. You can keep a reference to the results\ncollection in your view class, then read the results\ncollection as needed without having to refresh it or\nvalidate that it is up-to-date.\n\n> Warning:\n> Results update themselves automatically. If you\nstore the positional index of an object in a collection\nor the count of objects in a collection, the stored index\nor count value could be outdated by the time you use it.\n>\n\n## Results are Lazily Evaluated\nRealm only runs a query when you actually request the\nresults of that query, e.g. by accessing elements of the\nresults collection. This lazy evaluation enables you to\nwrite elegant, highly performant code for handling large\ndata sets and complex queries.\n\n### Limiting Query Results\nAs a result of lazy evaluation, you do not need any special\nmechanism to limit query results with Realm. For example, if\nyour query matches thousands of objects, but you only want\nto load the first ten, simply access only the first ten\nelements of the results collection.\n\n### Pagination\nThanks to lazy evaluation, the common task of pagination\nbecomes quite simple. For example, suppose you have a\nresults collection associated with a query that matches\nthousands of objects in your realm. You display one hundred\nobjects per page. To advance to any page, simply access the\nelements of the results collection starting at the index\nthat corresponds to the target page.\n\n## List vs. Results\nWhen you need a collection, you can use the following rule\nof thumb to determine whether a list or a results collection\nis appropriate:\n\n- When you define the properties of your Realm objects, use lists to define to-many relationships except implicit inverse relationships.\n- Use results everywhere else.\n\nTo understand these different use cases, consider whether\nyou should be able to add or remove objects directly. Lists\nallow you to add and remove objects directly, because you\ncontrol the relationships. Results collections do not allow\nyou to add or remove objects directly, because their contents\nare determined by a query.\n\n> Example:\n> Consider a Realm type called Person with a field called\n`emails` that is a collection of strings representing\nemail addresses. You control this data. Your application\nneeds to add and remove email addresses from your Person\ninstances. Therefore, use a **list** to define the field\ntype of `emails`.\n>\n> On the other hand, when you query the realm for all\nPersons over the age of 25, it would not make sense for\nyou to add or remove Persons directly to the resulting\ncollection. The contents of that collection only change\nwhen the query matches a different set of Persons.\nTherefore, Realm gives you a **results** collection.\n>\n\n> Note:\n> Since Realm automatically determines the contents of\nimplicit inverse relationship collections, you may not add\nor remove objects from such a collection.\nTherefore, the type of such a one-to-many relationship\nproperty is actually a results collection, not a list.\n>\n"
  },
  {
    "path": "docs/guides/model-data/data-types/counters.md",
    "content": "# Counters - Java SDK\nRealm offers `MutableRealmInteger`, a wrapper around numeric values,\nto help better synchronize numeric changes across multiple clients.\n\nTypically, incrementing or decrementing a\n`byte`, `short`, `int`, or `long` field of a Realm\nobject looks something like this:\n\n1. Read the current value of the field.\n2. Update that value in memory to a new value based on the increment or\ndecrement.\n3. Write a new value back to the field.\n\nWhen multiple distributed clients attempt this at the same time,\nupdates reaching clients in different orders can\nresult in different values on different clients. `MutableRealmInteger`\nimproves on this by translating numeric updates into sync operations\nthat can be executed in any order to converge to the same value.\n\n`MutableRealmInteger` fields are backed by traditional numeric types,\nso no migration is required when changing a field from `byte`, `short`,\n`int` or `long` to `MutableRealmInteger`.\n\nThe following example demonstrates a `MutableRealmInteger` field that\ncounts the number of ghosts found in a haunted house:\n\n#### Java\n\n```java\nimport io.realm.MutableRealmInteger;\nimport io.realm.RealmObject;\nimport io.realm.annotations.Required;\n\npublic class HauntedHouse extends RealmObject {\n    @Required\n    private final MutableRealmInteger ghosts = MutableRealmInteger.valueOf(0);\n    public HauntedHouse() {}\n    public MutableRealmInteger getGhosts() { return ghosts; }\n}\n\n```\n\n#### Kotlin\n\n```kotlin\nimport io.realm.MutableRealmInteger\nimport io.realm.RealmObject\nimport io.realm.annotations.Required\n\nopen class HauntedHouse: RealmObject() {\n    @Required\n    val ghosts: MutableRealmInteger = MutableRealmInteger.valueOf(0)\n}\n\n```\n\n> Important:\n> `MutableRealmInteger` is a live object like `RealmObject`,\n`RealmResults` and `RealmList`. This means the value contained\ninside the `MutableRealmInteger` can change when a realm is\nwritten to. For this reason `MutableRealmInteger` fields must be\nmarked final in Java and `val` in Kotlin.\n>\n\n## Usage\nThe `counter.increment()`\nand `counter.decrement()`\noperators ensure that increments and decrements from multiple distributed\nclients are aggregated correctly.\n\nTo change a `MutableRealmInteger` value, call `increment()` or\n`decrement()` within a write transaction:\n\n#### Java\n\n```java\nHauntedHouse house = realm.where(HauntedHouse.class)\n        .findFirst();\nrealm.executeTransaction(r -> {\n    Log.v(\"EXAMPLE\", \"Number of ghosts: \" + house.getGhosts().get()); // 0\n    house.getGhosts().increment(1);\n    Log.v(\"EXAMPLE\", \"Number of ghosts: \" + house.getGhosts().get()); // 1\n    house.getGhosts().increment(5);\n    Log.v(\"EXAMPLE\", \"Number of ghosts: \" + house.getGhosts().get()); // 6\n    house.getGhosts().decrement(2);\n    Log.v(\"EXAMPLE\", \"Number of ghosts: \" + house.getGhosts().get()); // 4\n});\n\n```\n\n#### Kotlin\n\n```kotlin\nval house = realm.where(HauntedHouse::class.java)\n    .findFirst()!!\nrealm.executeTransaction {\n    Log.v(\"EXAMPLE\", \"Number of ghosts: ${house.ghosts.get()}\") // 0\n    house.ghosts.increment(1)\n    Log.v(\"EXAMPLE\", \"Number of ghosts: ${house.ghosts.get()}\") // 1\n    house.ghosts.increment(5)\n    Log.v(\"EXAMPLE\", \"Number of ghosts: ${house.ghosts.get()}\") // 6\n    house.ghosts.decrement(2)\n    Log.v(\"EXAMPLE\", \"Number of ghosts: ${house.ghosts.get()}\") // 4\n}\n\n```\n\nYou can assign a `MutableRealmInteger` a new value with a call to\n`counter.set()`\nwithin a write transaction.\n\n> Warning:\n> Use the `set()` operator with extreme care. `set()` ignores\nthe effects of any prior calls to `increment()` or `decrement()`.\nAlthough the value of a `MutableRealmInteger` always converges\nacross devices, the specific value on which it converges depends on\nthe actual order in which operations took place.\nMixing `set()` with `increment()` and `decrement()` is\nnot advised unless fuzzy counting is acceptable.\n>\n\n#### Java\n\n```java\nrealm.executeTransaction(r -> {\n    house.getGhosts().set(42);\n});\n\n```\n\n#### Kotlin\n\n```kotlin\nrealm.executeTransaction {\n    house!!.ghosts.set(42)\n}\n\n```\n\nSince `MutableRealmInteger` instances retain a reference to their\nparent object, neither object can be garbage collected while you still\nretain a reference to the `MutableRealmInteger`.\n"
  },
  {
    "path": "docs/guides/model-data/data-types/embedded-objects.md",
    "content": "# Embedded Objects - Java SDK\nAn embedded object is a special type of Realm object that models complex data about a specific object.\nEmbedded objects are similar to relationships, but they provide additional constraints and\nmap more naturally to the denormalized document model.\n\nRealm enforces unique ownership constraints that treat each embedded\nobject as nested data inside of a single, specific parent object. An\nembedded object inherits the lifecycle of its parent object and cannot\nexist as an independent Realm object. Realm automatically deletes\nembedded objects if their parent object is deleted or when overwritten\nby a new embedded object instance.\n\n> Warning:\n> When you delete a Realm object, Realm automatically deletes any\nembedded objects referenced by that object. Any objects that your\napplication must persist after the deletion of their parent object\nshould use relationships\ninstead.\n>\n\n## Embedded Object Data Models\nYou can define embedded object types using either Realm object models or\na server-side document schema. Embedded object types are reusable and\ncomposable. You can use the same embedded object type in multiple parent\nobject types and you can embed objects inside of other embedded objects.\n\n> Important:\n> Embedded objects cannot have a primary key.\n>\n\n### Realm Object Models\nTo define an embedded object, derive a class from `RealmObject` and set the `embedded` property of the\n`RealmClass` annotation\nto `true`. You can reference an embedded object type from parent\nobject types in the same way as you would define a relationship:\n\n#### Java\n\n```java\n// Define an embedded object\n@RealmClass(embedded = true)\npublic class Address extends RealmObject {\n    String street;\n    String city;\n    String country;\n    String postalCode;\n\n    public Address(String street, String city, String country, String postalCode) {\n        this.street = street;\n        this.city = city;\n        this.country = country;\n        this.postalCode = postalCode;\n    }\n\n    public Address() {}\n}\n\n// Define an object containing one embedded object\npublic class Contact extends RealmObject {\n    @PrimaryKey\n    private ObjectId _id = new ObjectId();\n    String name = \"\";\n\n    // Embed a single object.\n    // Embedded object properties must be marked optional\n    Address address;\n\n    public Contact(String name, Address address) {\n        this.name = name;\n        this.address = address;\n    }\n\n    public Contact() {}\n}\n\n// Define an object containing an array of embedded objects\npublic class Business extends RealmObject {\n    @PrimaryKey\n    private ObjectId _id = new ObjectId();\n    String name = \"\";\n\n    // Embed an array of objects\n    RealmList<Address> addresses = new RealmList<Address>();\n\n    public Business(String name, RealmList<Address> addresses) {\n        this.name = name;\n        this.addresses = addresses;\n    }\n\n    public Business() {}\n}\n\n```\n\n#### Kotlin\n\n```kotlin\n// Define an embedded object\n@RealmClass(embedded = true)\nopen class Address(\n    var street: String? = null,\n    var city: String? = null,\n    var country: String? = null,\n    var postalCode: String? = null\n): RealmObject() {}\n\n// Define an object containing one embedded object\nopen class Contact(_name: String = \"\", _address: Address? = null) : RealmObject() {\n    @PrimaryKey var _id: ObjectId = ObjectId()\n    var name: String = _name\n\n    // Embed a single object.\n    // Embedded object properties must be marked optional\n    var address: Address? = _address\n}\n\n// Define an object containing an array of embedded objects\nopen class Business(_name: String = \"\", _addresses: RealmList<Address> = RealmList()) : RealmObject() {\n    @PrimaryKey var _id: ObjectId = ObjectId()\n    var name: String = _name\n\n    // Embed an array of objects\n    var addresses: RealmList<Address> = _addresses\n}\n\n```\n\n### JSON Schema\nEmbedded objects map to embedded documents in the parent type's schema.\n\n```json\n{\n  \"title\": \"Contact\",\n  \"bsonType\": \"object\",\n  \"required\": [\"_id\"],\n  \"properties\": {\n    \"_id\": { \"bsonType\": \"objectId\" },\n    \"name\": { \"bsonType\": \"string\" },\n    \"address\": {\n      \"title\": \"Address\",\n      \"bsonType\": \"object\",\n      \"properties\": {\n        \"street\": { \"bsonType\": \"string\" },\n        \"city\": { \"bsonType\": \"string\" },\n        \"country\": { \"bsonType\": \"string\" },\n        \"postalCode\": { \"bsonType\": \"string\" }\n      }\n    }\n  }\n}\n```\n\n```json\n{\n  \"title\": \"Business\",\n  \"bsonType\": \"object\",\n  \"required\": [\"_id\", \"name\"],\n  \"properties\": {\n    \"_id\": { \"bsonType\": \"objectId\" },\n    \"name\": { \"bsonType\": \"string\" },\n    \"addresses\": {\n      \"bsonType\": \"array\",\n      \"items\": {\n        \"title\": \"Address\",\n        \"bsonType\": \"object\",\n        \"properties\": {\n          \"street\": { \"bsonType\": \"string\" },\n          \"city\": { \"bsonType\": \"string\" },\n          \"country\": { \"bsonType\": \"string\" },\n          \"postalCode\": { \"bsonType\": \"string\" }\n        }\n      }\n    }\n  }\n}\n```\n\n## Read and Write Embedded Objects\n### Create an Embedded Object\nTo create an embedded object, assign an instance of the embedded object\nto a parent object's property.\n\n#### Java\n\n```java\n// open realm\n\nAddress address = new Address(\"123 Fake St.\", \"Springfield\", \"USA\", \"90710\");\nContact contact = new Contact(\"Nick Riviera\", address);\n\nrealm.executeTransaction(transactionRealm -> {\n    transactionRealm.insert(contact);\n});\n\nrealm.close();\n\n```\n\n#### Kotlin\n\n```kotlin\n// open realm\n\nval address = Address(\"123 Fake St.\", \"Springfield\", \"USA\", \"90710\")\nval contact = Contact(\"Nick Riviera\", address)\n\nrealm.executeTransaction { transactionRealm ->\n    transactionRealm.insert(contact)\n}\n\nrealm.close()\n\n```\n\n### Update an Embedded Object Property\nTo update a property in an embedded object, modify the property in a\nwrite transaction:\n\n#### Java\n\n```java\n// assumes that at least one contact already exists in this partition\nContact resultContact = realm.where(Contact.class).findFirst();\n\nrealm.executeTransaction(transactionRealm -> {\n    resultContact.address.street = \"Hollywood Upstairs Medical College\";\n    resultContact.address.city = \"Los Angeles\";\n    resultContact.address.postalCode = \"90210\";\n    Log.v(\"EXAMPLE\", \"Updated contact: \" + resultContact);\n});\n\nrealm.close();\n\n```\n\n#### Kotlin\n\n```kotlin\n// assumes that at least one contact already exists in this partition\nval result = realm.where<Contact>().findFirst()!!\n\nrealm.executeTransaction { transactionRealm ->\n    result.address?.street = \"Hollywood Upstairs Medical College\"\n    result.address?.city = \"Los Angeles\"\n    result.address?.postalCode = \"90210\"\n    Log.v(\"EXAMPLE\", \"Updated contact: ${result.name}\")\n}\n\nrealm.close()\n\n```\n\n### Overwrite an Embedded Object\nTo overwrite an embedded object, reassign the embedded object property\nof a party to a new instance in a write transaction:\n\n#### Java\n\n```java\n// assumes that at least one contact already exists in this partition\nContact oldContact = realm.where(Contact.class).findFirst();\n\nrealm.executeTransaction(transactionRealm -> {\n    Address newAddress = new Address(\n        \"Hollywood Upstairs Medical College\",\n        \"Los Angeles\",\n        \"USA\"\n        \"90210\"\n        );\n    oldContact.address = newAddress;\n    Log.v(\"EXAMPLE\", \"Replaced contact: \" + oldContact);\n});\n\nrealm.close();\n\n```\n\n#### Kotlin\n\n```kotlin\n// assumes that at least one contact already exists\nval oldContact = realm.where<Contact>().findFirst()!!\n\nrealm.executeTransaction { transactionRealm ->\n    val newAddress = Address(\n        \"Hollywood Upstairs Medical College\",\n        \"Los Angeles\",\n        \"USA\",\n        \"90210\")\n    oldContact.address = newAddress\n    Log.v(\"EXAMPLE\", \"Updated contact: $oldContact\")\n}\n\nrealm.close()\n\n```\n\n### Query a Collection on Embedded Object Properties\nUse dot notation to filter or sort a collection of objects based on an embedded object\nproperty value:\n\n> Note:\n> It is not possible to query embedded objects directly. Instead,\naccess embedded objects through a query for the parent object type.\n>\n\n#### Java\n\n```java\nRealmResults<Contact> losAngelesContacts = realm.where(Contact.class)\n        .equalTo(\"address.city\", \"Los Angeles\")\n        .sort(\"address.street\").findAll();\nLog.v(\"EXAMPLE\", \"Los Angeles contacts: \" + losAngelesContacts);\n\n```\n\n#### Kotlin\n\n```kotlin\nval losAngelesContacts = realm.where<Contact>()\n    .equalTo(\"address.city\", \"Los Angeles\")\n    .sort(\"address.street\").findAll()\nLog.v(\"EXAMPLE\", \"Los Angeles Contacts: $losAngelesContacts\")\n\n```\n\n"
  },
  {
    "path": "docs/guides/model-data/data-types/enums.md",
    "content": "# Enumerations - Java SDK\nEnumerations, also known as enums, are not supported natively in the\nJava SDK. However, you can use Java and Kotlin enums in your\nRealm objects if you follow these steps.\n\n## Usage\nTo use an enum in a Realm object class, define a field\nwith a type matching the underlying data type of your enum. Create\ngetters and setters for the field that convert the field value between\nthe underlying value and the enum type. You can use the Java's built-in\n[Enum.valueOf()](https://docs.oracle.com/javase/7/docs/api/java/lang/Enum.html#valueOf(java.lang.Class,%20java.lang.String))\nmethod to convert from the underlying type to the enum type.\n\n#### Java\n\n```kotlin\npublic enum FrogState {\n    TADPOLE(\"Tadpole\"),\n    FROG(\"Frog\"),\n    OLD_FROG(\"Old Frog\");\n\n    private String state;\n    FrogState(String state) {\n        this.state = state;\n    }\n    public String getState() {\n        return state;\n    }\n}\n\n```\n\n```java\nimport io.realm.RealmObject;\n\npublic class Frog extends RealmObject {\n    String name;\n    String state = FrogState.TADPOLE.getState();\n    // realm-required empty constructor\n    public Frog() {}\n\n    public String getName() { return name; }\n    public void setName(String name) { this.name = name; }\n    public FrogState getState() {\n        // because state is actually a String and another client could assign an invalid value,\n        // default the state to \"TADPOLE\" if the state is unreadable\n        FrogState currentState = null;\n        try {\n            // fetches the FrogState enum value associated with the current internal string value\n            currentState = FrogState.valueOf(state);\n        } catch (IllegalArgumentException e) {\n            currentState = FrogState.TADPOLE;\n        }\n        return currentState;\n    }\n    public void setState(FrogState value) {\n        // users set state using a FrogState, but it is saved as a string internally\n        this.state = value.getState();\n    }\n}\n\n```\n\n```java\nFrog frog = realm.createObject(Frog.class);\nfrog.setName(\"Jonathan Livingston Applesauce\");\n// set the state using the enum\nfrog.setState(FrogState.FROG);\n\n// fetching the state returns an enum\nFrogState currentJonathanState = frog.getState();\n\n```\n\n#### Kotlin\n\n```kotlin\nenum class FrogState(val state: String) {\n    TADPOLE(\"Tadpole\"),\n    FROG(\"Frog\"),\n    OLD_FROG(\"Old Frog\");\n}\n\n```\n\n```kotlin\nimport io.realm.RealmObject\nimport java.lang.IllegalArgumentException\n\nopen class Frog  // realm-required empty constructor\n    : RealmObject() {\n    var name: String? = null\n    private var state: String = FrogState.TADPOLE.state\n    var stateEnum: FrogState\n        get() {\n            // because state is actually a String and another client could assign an invalid value,\n            // default the state to \"TADPOLE\" if the state is unreadable\n            return try {\n                // fetches the FrogState enum value associated with the current internal string value\n                FrogState.valueOf(state)\n            } catch (e: IllegalArgumentException) {\n                FrogState.TADPOLE\n            }\n        }\n        set(value) {\n            // users set state using a FrogState, but it is saved as a string internally\n            state = value.state\n        }\n}\n\n```\n\n```kotlin\nval frog = realm.createObject(Frog::class.java)\nfrog.name = \"Jonathan Livingston Applesauce\"\n// set the state using the enum\nfrog.stateEnum = FrogState.FROG\n\n// fetching the state returns an enum\nval currentJonathanState: FrogState = frog.stateEnum\n\n```\n\n"
  },
  {
    "path": "docs/guides/model-data/data-types/field-types.md",
    "content": "# Field Types - Java SDK\nRealm supports the following field data types:\n\n- `Boolean` or `boolean`\n- `Integer` or `int`\n- `Short` or `short`\n- `Long` or `long`\n- `Byte` or `byte[]`\n- `Double` or `double`\n- `Float` or `float`\n- `String`\n- `Date`\n- `Decimal128` from `org.bson.types`\n- `ObjectId` from `org.bson.types`\n- `UUID` from `java.util.UUID`\n- Any `RealmObject` subclass\n- `RealmList`\n- `RealmAny`\n- `RealmSet`\n- `RealmDictionary`\n\nThe `Byte`, `Short`, `Integer`, and `Long` types and their\nlowercase primitive alternatives are all stored as `Long` values\nwithin Realm. Similarly, Realm stores objects\nof the `Float` and `float` types as type `Double`.\n\nRealm does not support fields with modifiers `final` and\n`volatile`, though you can use fields with those modifiers if you\nignore them. If you choose to provide custom\nconstructors, you must declare a public constructor with no arguments.\n\n## Updating Strings and Byte Arrays\nSince Realm operates on fields as a whole, it's not possible\nto directly update individual elements of strings or byte arrays. Instead,\nyou'll need to read the whole field, make your modification to individual\nelements, and then write the entire field back again in a transaction block.\n\n## Object IDs and UUIDs\n`ObjectId` and `UUID` (Universal Unique Identifier) both provide\nunique values that can be used as identifiers for objects.\n`ObjectId` is a\n12-byte unique value. `UUID` is a [standardized](https://tools.ietf.org/html/rfc4122) 16-byte\nunique value. Both types are indexable\nand can be used as primary keys.\n"
  },
  {
    "path": "docs/guides/model-data/data-types/realmany.md",
    "content": "# RealmAny - Java SDK\n> Version added: 10.6.0\n\nYou can use the `RealmAny` data type to create\nRealm object fields that can contain any of several\nunderlying types. You can store multiple `RealmAny` instances in\n`RealmList`, `RealmDictionary`, or `RealmSet` fields. To change\nthe value of a `RealmAny` field, assign a new `RealmAny` instance\nwith a different underlying value. `RealmAny` fields are indexable, but\ncannot be used as primary keys.\n\n> Note:\n> `RealmAny` objects can refer to any\nsupported field type\n*except*:\n>\n> - `RealmAny`\n> - `RealmList`\n> - `RealmSet`\n> - `RealmDictionary`\n>\n\n## Usage\nTo create a `RealmAny` instance, use the\n`RealmAny.valueOf()` method\nto assign an initial value or `RealmAny.nullValue()` to assign no\nvalue. `RealmAny` instances are immutable just like `String` or\n`Integer` instances; if you want to assign a new value to a\n`RealmAny` field, you must create a new `RealmAny` instance.\n\n> Warning:\n> `RealmAny` instances are always nullable. Additionally, instances can contain a value\nof type `RealmAny.Type.NULL`.\n>\n\n#### Java\n\n```java\nimport com.mongodb.realm.examples.model.kotlin.Person;\n\nimport io.realm.RealmAny;\nimport io.realm.RealmObject;\n\npublic class Frog extends RealmObject {\n    String name;\n    RealmAny bestFriend;\n    // realm-required empty constructor\n    public Frog() {}\n\n    public String getName() { return name; }\n    public void setName(String name) { this.name = name; }\n    public RealmAny getBestFriend() { return bestFriend; }\n    public void setBestFriend(RealmAny bestFriend) { this.bestFriend = bestFriend; }\n    public String bestFriendToString() {\n        switch(bestFriend.getType()) {\n            case NULL: {\n                return \"no best friend\";\n            }\n            case STRING: {\n                return bestFriend.asString();\n            }\n            case OBJECT: {\n                if (bestFriend.getValueClass().equals(Person.class)) {\n                    Person person = bestFriend.asRealmModel(Person.class);\n                    return person.getName();\n                }\n            }\n            default: {\n                return \"unknown type\";\n            }\n        }\n    }\n}\n\n```\n\n```java\n  Frog frog = realm.createObject(Frog.class);\n  frog.setName(\"Jonathan Livingston Applesauce\");\n\n  // set RealmAny field to a null value\n  frog.setBestFriend(RealmAny.nullValue());\n  Log.v(\"EXAMPLE\", \"Best friend: \" + frog.bestFriendToString());\n\n  // possible types for RealmAny are defined in RealmAny.Type\n  Assert.assertTrue(frog.getBestFriend().getType() == RealmAny.Type.NULL);\n\n  // set RealmAny field to a string with RealmAny.valueOf a string value\n  frog.setBestFriend(RealmAny.valueOf(\"Greg\"));\n  Log.v(\"EXAMPLE\", \"Best friend: \" + frog.bestFriendToString());\n\n  // RealmAny instances change type as you reassign to different values\n  Assert.assertTrue(frog.getBestFriend().getType() == RealmAny.Type.STRING);\n\n  // set RealmAny field to a realm object, also with valueOf\n  Person person = new Person(\"Jason Funderburker\");\n\n  frog.setBestFriend(RealmAny.valueOf(person));\n  Log.v(\"EXAMPLE\", \"Best friend: \" + frog.bestFriendToString());\n\n  // You can also extract underlying Realm Objects from RealmAny with asRealmModel\n  Person bestFriendObject = frog.getBestFriend().asRealmModel(Person.class);\n  Log.v(\"EXAMPLE\", \"Best friend: \" + bestFriendObject.getName());\n\n  // RealmAny fields referring to any Realm Object use the OBJECT type\n  Assert.assertTrue(frog.getBestFriend().getType() == RealmAny.Type.OBJECT);\n\n  // you can't put a RealmList in a RealmAny field directly,\n  // ...but you can set a RealmAny field to a RealmObject that contains a list\n  GroupOfPeople persons = new GroupOfPeople();\n  // GroupOfPeople contains a RealmList of people\n  persons.getPeople().add(\"Rand\");\n  persons.getPeople().add(\"Perrin\");\n  persons.getPeople().add(\"Mat\");\n\n  frog.setBestFriend(RealmAny.valueOf(persons));\n  Log.v(\"EXAMPLE\", \"Best friend: \" +\n          frog.getBestFriend().asRealmModel(GroupOfPeople.class).getPeople().toString());\n\n```\n\n#### Kotlin\n\n```kotlin\nimport io.realm.RealmAny\nimport io.realm.RealmObject\n\nopen class Frog(var bestFriend: RealmAny? = RealmAny.nullValue()) : RealmObject() {\n    var name: String? = null\n    open fun bestFriendToString(): String {\n        if (bestFriend == null) {\n            return \"null\"\n        }\n        return when (bestFriend!!.type) {\n            RealmAny.Type.NULL -> {\n                \"no best friend\"\n            }\n            RealmAny.Type.STRING -> {\n                bestFriend!!.asString()\n            }\n            RealmAny.Type.OBJECT -> {\n                if (bestFriend!!.valueClass == Person::class.java) {\n                    val person = bestFriend!!.asRealmModel(Person::class.java)\n                    person.name\n                }\n                \"unknown type\"\n            }\n            else -> {\n                \"unknown type\"\n            }\n        }\n    }\n}\n\n```\n\n```kotlin\nval frog = realm.createObject(Frog::class.java)\nfrog.name = \"George Washington\"\n\n// set RealmAny field to a null value\n\n// set RealmAny field to a null value\nfrog.bestFriend = RealmAny.nullValue()\nLog.v(\"EXAMPLE\", \"Best friend: \" + frog.bestFriendToString())\n\n// possible types for RealmAny are defined in RealmAny.Type\nAssert.assertEquals(frog.bestFriend?.type, RealmAny.Type.NULL)\n\n// set RealmAny field to a string with RealmAny.valueOf a string value\nfrog.bestFriend = RealmAny.valueOf(\"Greg\")\nLog.v(\"EXAMPLE\", \"Best friend: \" + frog.bestFriendToString())\n\n// RealmAny instances change type as you reassign to different values\nAssert.assertEquals(frog.bestFriend?.type, RealmAny.Type.STRING)\n\n// set RealmAny field to a realm object, also with valueOf\nval person = Person(\"Jason Funderburker\")\n\nfrog.bestFriend = RealmAny.valueOf(person)\nLog.v(\"EXAMPLE\", \"Best friend: \" + frog.bestFriendToString())\n\n// You can also extract underlying Realm Objects from RealmAny with asRealmModel\nval bestFriendObject = frog.bestFriend?.asRealmModel(Person::class.java)\nLog.v(\"EXAMPLE\", \"Best friend: \" + bestFriendObject?.name)\n\n// RealmAny fields referring to any Realm Object use the OBJECT type\nAssert.assertEquals(frog.bestFriend?.type, RealmAny.Type.OBJECT)\n\n// you can't put a RealmList in a RealmAny field directly,\n// ...but you can set a RealmAny field to a RealmObject that contains a list\nval persons = GroupOfPeople()\n// GroupOfPeople contains a RealmList of people\npersons.people.add(\"Rand\")\npersons.people.add(\"Perrin\")\npersons.people.add(\"Mat\")\n\nfrog.bestFriend = RealmAny.valueOf(persons)\nLog.v(\"EXAMPLE\", \"Best friend: \" +\n        frog.bestFriend?.asRealmModel(GroupOfPeople::class.java)\n                ?.people.toString())\n\n```\n\n## Queries\nYou can query a `RealmAny` field just like any other data type.\nOperators that only work with certain types, such as string\noperators and arithmetic operators, ignore\nvalues that do not contain that type. Negating such operators matches\nvalues that do not contain the type. Type queries match the underlying\ntype, rather than `RealmAny`. Arithmetic operators convert numeric\nvalues implicitly to compare across types.\n\n## Notifications\nTo subscribe to changes to a `RealmAny` field, use the\n`RealmObject.addChangeListener`\nmethod of the enclosing object. You can use the\n`ObjectChangeSet`\nparameter to determine if the `RealmAny` field changed.\n\n#### Java\n\n```java\nAtomicReference<Frog> frog = new AtomicReference<Frog>();\nrealm.executeTransaction(r -> {\n        frog.set(realm.createObject(Frog.class));\n        frog.get().setName(\"Jonathan Livingston Applesauce\");\n});\n\nRealmObjectChangeListener<Frog> objectChangeListener =\n        new RealmObjectChangeListener<Frog>() {\n    @Override\n    public void onChange(@NotNull Frog frog, @Nullable ObjectChangeSet changeSet) {\n        if (changeSet != null) {\n            Log.v(\"EXAMPLE\", \"Changes to fields: \" +\n                    Arrays.toString(changeSet.getChangedFields()));\n            if (changeSet.isFieldChanged(\"best_friend\")) {\n                Log.v(\"EXAMPLE\", \"RealmAny best friend field changed to : \" +\n                        frog.bestFriendToString());\n            }\n        }\n    }\n};\n\nfrog.get().addChangeListener(objectChangeListener);\n\nrealm.executeTransaction(r -> {\n    // set RealmAny field to a null value\n    frog.get().setBestFriend(RealmAny.nullValue());\n    Log.v(\"EXAMPLE\", \"Best friend: \" + frog.get().bestFriendToString());\n\n    // set RealmAny field to a string with RealmAny.valueOf a string value\n    frog.get().setBestFriend(RealmAny.valueOf(\"Greg\"));\n\n});\n\n```\n\n#### Kotlin\n\n```kotlin\nvar frog: Frog? = null\n\nrealm.executeTransaction { r: Realm? ->\n    frog = realm.createObject(Frog::class.java)\n    frog?.name = \"Jonathan Livingston Applesauce\"\n}\n\nval objectChangeListener\n        = RealmObjectChangeListener<Frog> { frog, changeSet ->\n    if (changeSet != null) {\n        Log.v(\"EXAMPLE\", \"Changes to fields: \" +\n                changeSet.changedFields)\n        if (changeSet.isFieldChanged(\"best_friend\")) {\n            Log.v(\"EXAMPLE\", \"RealmAny best friend field changed to : \" +\n                    frog.bestFriendToString())\n        }\n    }\n}\n\nfrog?.addChangeListener(objectChangeListener)\n\nrealm.executeTransaction { r: Realm? ->\n    // set RealmAny field to a null value\n    frog?.bestFriend = RealmAny.nullValue()\n    Log.v(\"EXAMPLE\", \"Best friend: \" + frog?.bestFriendToString())\n\n    // set RealmAny field to a string with RealmAny.valueOf a string value\n    frog?.bestFriend = RealmAny.valueOf(\"Greg\")\n}\n\n```\n\n"
  },
  {
    "path": "docs/guides/model-data/data-types/realmdictionary.md",
    "content": "# RealmDictionary - Java SDK\n> Version added: 10.6.0\n\nYou can use the `RealmDictionary` data type to manage a collection of\nunique `String` keys paired with values. `RealmDictionary`\nimplements Java's `Map` interface, so it works just like the built-in\n`HashMap` class, except managed `RealmDictionary` instances persist\ntheir contents to a realm. `RealmDictionary` instances that\ncontain Realm objects store references to those objects.\nWhen you delete a Realm object from a realm, any\nreferences to that object in a `RealmDictionary` become `null`\nvalues.\n\n## Usage\nTo create a field of type `RealmDictionary`, define an object property\nof type `RealmDictionary<T>`, where `T` defines the values you would\nlike to store in your `RealmDictionary`. Currently, `RealmDictionary`\ninstances can only use keys of type `String`.\n\nThe following table shows which methods you can use to complete common\ncollection tasks with `RealmDictionary`:\n\n|Task|Method|\n| --- | --- |\n|Add an object to a `RealmDictionary`|`put()` (or the `[]` operator in Kotlin)|\n|Add multiple objects to a `RealmDictionary`|`putAll()`|\n|Check if the dictionary contains an specific key|`containsKey()`|\n|Check if the dictionary contains a specific value|`containsValue()`|\n\n#### Java\n\n```java\nimport io.realm.RealmDictionary;\nimport io.realm.RealmObject;\n\npublic class Frog extends RealmObject {\n    String name;\n    RealmDictionary<Frog> nicknamesToFriends;\n    // realm-required empty constructor\n    public Frog() {}\n\n    public String getName() { return name; }\n    public void setName(String name) { this.name = name; }\n    public RealmDictionary<Frog> getNicknamesToFriends() { return nicknamesToFriends; }\n    public void setNicknamesToFriends(RealmDictionary<Frog> nicknamesToFriends) { this.nicknamesToFriends = nicknamesToFriends; }\n}\n\n```\n\n```java\nFrog frog = realm.createObject(Frog.class);\nfrog.setName(\"George Washington\");\n\n// get the RealmDictionary field from the object we just created\nRealmDictionary<Frog> dictionary = frog.getNicknamesToFriends();\n\n// add key/value to the dictionary\nFrog wirt = realm.createObject(Frog.class);\nwirt.setName(\"Wirt\");\ndictionary.put(\"tall frog\", wirt);\n\n// add multiple keys/values to the dictionary\nFrog greg = realm.createObject(Frog.class);\ngreg.setName(\"Greg\");\nFrog beatrice = realm.createObject(Frog.class);\nbeatrice.setName(\"Beatrice\");\ndictionary.putAll(Map.of(\"small frog\", greg, \"feathered frog\", beatrice));\n\n// check for the presence of a key\nAssert.assertTrue(dictionary.containsKey(\"small frog\"));\n\n// check for the presence of a value\nAssert.assertTrue(dictionary.containsValue(greg));\n\n// remove a key\ndictionary.remove(\"feathered frog\");\nAssert.assertFalse(dictionary.containsKey(\"feathered frog\"));\n\n// deleting a Realm object does NOT remove it from the dictionary\nint sizeOfDictionaryBeforeDelete = dictionary.size();\ngreg.deleteFromRealm();\n// deleting greg object did not reduce the size of the dictionary\nAssert.assertEquals(sizeOfDictionaryBeforeDelete, dictionary.size());\n// but greg object IS now null:\nAssert.assertEquals(dictionary.get(\"small frog\"), null);\n\n```\n\n#### Kotlin\n\n```kotlin\nimport io.realm.RealmDictionary\nimport io.realm.RealmObject\n\nopen class Frog\n    : RealmObject() {\n    var name: String? = null\n    var nicknamesToFriends: RealmDictionary<Frog> = RealmDictionary<Frog>()\n}\n\n```\n\n```kotlin\nval frog =\n    realm.createObject(Frog::class.java)\nfrog.name = \"George Washington\"\n\n// get the RealmDictionary field from the object we just created\nval dictionary = frog.nicknamesToFriends\n\n// add key/value to the dictionary\nval wirt =\n    realm.createObject(Frog::class.java)\nwirt.name = \"Wirt\"\ndictionary[\"tall frog\"] = wirt\n\n// add multiple keys/values to the dictionary\nval greg =\n    realm.createObject(Frog::class.java)\ngreg.name = \"Greg\"\nval beatrice =\n    realm.createObject(Frog::class.java)\nbeatrice.name = \"Beatrice\"\ndictionary.putAll(mapOf<String, Frog>(\n    Pair(\"small frog\", greg),\n    Pair(\"feathered frog\", beatrice)))\n\n// check for the presence of a key\nAssert.assertTrue(dictionary.containsKey(\"small frog\"))\n\n// check for the presence of a value\nAssert.assertTrue(dictionary.containsValue(greg))\n\n// remove a key\ndictionary.remove(\"feathered frog\")\nAssert.assertFalse(dictionary.containsKey(\"feathered frog\"))\n\n// deleting a Realm object does NOT remove it from the dictionary\nval sizeOfDictionaryBeforeDelete = dictionary.size\ngreg.deleteFromRealm()\n// deleting greg object did not reduce the size of the dictionary\nAssert.assertEquals(\n    sizeOfDictionaryBeforeDelete.toLong(),\n    dictionary.size.toLong()\n)\n// but greg object IS now null:\nAssert.assertEquals(dictionary[\"small frog\"], null)\n\n```\n\n## Notifications\nTo subscribe to changes to a `RealmDictionary`, pass a\n`MapChangeListener`\nimplementation to the `RealmSet.addChangeListener` method.\nYour `MapChangeListener` implementation must define an\n`onChange()` method, which accepts a reference to the changed `RealmDictionary`\nand a set of changes as parameters. You can access the keys\nadded to the dictionary as well as the keys removed from the dictionary\nthrough the `MapChangeSet` parameter.\n\n#### Java\n\n```java\nAtomicReference<Frog> frog = new AtomicReference<Frog>();\nrealm.executeTransaction(r -> {\n    frog.set(realm.createObject(Frog.class));\n    frog.get().setName(\"Jonathan Livingston Applesauce\");\n});\n\nMapChangeListener<String, Frog> mapChangeListener =\n    new MapChangeListener<String, Frog>() {\n        @Override\n        public void onChange(RealmMap<String, Frog> map,\n                             MapChangeSet<String> changes) {\n            for (String insertion : changes.getInsertions()) {\n                Log.v(\"EXAMPLE\",\n                        \"Inserted key:  \" + insertion +\n                                \", Inserted value: \" + map.get(insertion).getName());\n            }\n        }\n    };\n\nfrog.get().getNicknamesToFriends().addChangeListener(mapChangeListener);\n\nrealm.executeTransaction(r -> {\n    // get the RealmDictionary field from the object we just created\n    RealmDictionary<Frog> dictionary = frog.get().getNicknamesToFriends();\n\n    // add key/value to the dictionary\n    Frog wirt = realm.createObject(Frog.class);\n    wirt.setName(\"Wirt\");\n    dictionary.put(\"tall frog\", wirt);\n\n    // add multiple keys/values to the dictionary\n    Frog greg = realm.createObject(Frog.class);\n    greg.setName(\"Greg\");\n    Frog beatrice = realm.createObject(Frog.class);\n    beatrice.setName(\"Beatrice\");\n    dictionary.putAll(Map.of(\"small frog\", greg, \"feathered frog\", beatrice));\n\n});\n\n```\n\n#### Kotlin\n\n```kotlin\nvar frog: Frog? = null\nrealm.executeTransaction { r: Realm? ->\n    frog = realm.createObject(Frog::class.java)\n    frog?.name = \"Jonathan Livingston Applesauce\"\n}\n\nval mapChangeListener: MapChangeListener<String, Frog>\n        = MapChangeListener<String, Frog> { map, changes ->\n    for (insertion in changes.insertions) {\n        Log.v(\"EXAMPLE\",\n                \"Inserted key:  $insertion, Inserted value: ${map[insertion]!!.name}\")\n    }\n}\n\nfrog?.nicknamesToFriends?.addChangeListener(mapChangeListener)\n\nrealm.executeTransaction { r: Realm? ->\n    // get the RealmDictionary field from the object we just created\n    val dictionary = frog!!.nicknamesToFriends\n\n    // add key/value to the dictionary\n    val wirt = realm.createObject(Frog::class.java)\n    wirt.name = \"Wirt\"\n    dictionary[\"tall frog\"] = wirt\n\n    // add multiple keys/values to the dictionary\n    val greg = realm.createObject(Frog::class.java)\n    greg.name = \"Greg\"\n    val beatrice = realm.createObject(Frog::class.java)\n    beatrice.name = \"Beatrice\"\n    dictionary.putAll(mapOf<String, Frog>(\n            Pair(\"small frog\", greg),\n            Pair(\"feathered frog\", beatrice)))\n}\n\n```\n\n"
  },
  {
    "path": "docs/guides/model-data/data-types/realmset.md",
    "content": "# RealmSet - Java SDK\n> Version added: 10.6.0\n\nYou can use the `RealmSet` data type\nto manage a collection of unique keys. `RealmSet` implements Java's\n`Set` interface, so it works just like the built-in `HashSet` class,\nexcept managed `RealmSet` instances persist their contents to a\nrealm. `RealmSet` instances that contain Realm objects\nactually only store references to those objects, so deleting a\nRealm object from a realm also deletes that object from\nany `RealmSet` instances that contain the object.\n\nBecause `RealmSet` implements `RealmCollection`, it has some useful\nmathematical methods, such as `sum`, `min`, and `max`. For a complete\nlist of available `RealmSet` methods, see: [the RealmSet API\nreference](https://www.mongodb.com/docs/realm-sdks/java/latest/io/realm/RealmSet.html).\n\n## Method Limitations\nYou cannot use the following `Realm` methods on objects that contain\na field of type `RealmSet`:\n\n- `Realm.insert()`\n- `Realm.insertOrUpdate()`\n- `Realm.createAllFromJson()`\n- `Realm.createObjectFromJson()`\n- `Realm.createOrUpdateAllFromJson()`\n- `Realm.createOrUpdateObjectFromJson()`\n\n## Usage\nTo create a field of type `RealmSet`, define an object property of\ntype `RealmSet<E>`, where `E` defines the keys you would like to\nstore in your `RealmSet`.\n\n- Add an object to a `RealmSet` with\n`RealmSet.add()`\n- Add multiple objects with\n`RealmSet.addAll()`\n- Check if the set contains a specific object with\n`RealmSet.contains()`\n- Check if the set contains all of multiple objects with\n`RealmSet.containsAll()`\n\n#### Java\n\n```java\nimport io.realm.RealmObject;\nimport io.realm.RealmSet;\n\npublic class Frog extends RealmObject {\n    String name;\n    RealmSet<Snack> favoriteSnacks;\n    // realm-required empty constructor\n    public Frog() {}\n\n    public String getName() { return name; }\n    public void setName(String name) { this.name = name; }\n    public RealmSet<Snack> getFavoriteSnacks() { return favoriteSnacks; }\n    public void setFavoriteSnacks(RealmSet<Snack> favoriteSnacks) { this.favoriteSnacks = favoriteSnacks; }\n}\n\n```\n\n```java\nimport io.realm.RealmObject;\n\npublic class Snack extends RealmObject {\n    private String name;\n    public Snack() {}\n\n    public String getName() { return name; }\n    public void setName(String name) { this.name = name; }\n}\n\n```\n\n```java\nFrog frog = realm.createObject(Frog.class);\nfrog.setName(\"George Washington\");\n\n// get the RealmSet field from the object we just created\nRealmSet<Snack> set = frog.getFavoriteSnacks();\n\n// add value to the RealmSet\nSnack flies = realm.createObject(Snack.class);\nflies.setName(\"flies\");\nset.add(flies);\n\n// add multiple values to the RealmSet\nSnack water = realm.createObject(Snack.class);\nwater.setName(\"water\");\nSnack verySmallRocks = realm.createObject(Snack.class);\nverySmallRocks.setName(\"verySmallRocks\");\nset.addAll(Arrays.asList(water, verySmallRocks));\n\n// check for the presence of a key with contains\nAssert.assertTrue(set.contains(flies));\n\n// check for the presence of multiple keys with containsAll\nSnack biscuits = realm.createObject(Snack.class);\nbiscuits.setName(\"biscuits\");\nAssert.assertTrue(set.containsAll(Arrays.asList(water, biscuits)) == false);\n\n// remove string from a set\nset.remove(verySmallRocks);\n\n// set no longer contains that string\nAssert.assertTrue(set.contains(verySmallRocks) == false);\n\n// deleting a Realm object also removes it from any RealmSets\nint sizeOfSetBeforeDelete = set.size();\nflies.deleteFromRealm();\n// deleting flies object reduced the size of the set by one\nAssert.assertTrue(sizeOfSetBeforeDelete == set.size() + 1);\n\n```\n\n#### Kotlin\n\n```kotlin\nimport io.realm.RealmObject\nimport io.realm.RealmSet\n\nopen class Frog\n    : RealmObject() {\n    var name: String = \"\"\n    var favoriteSnacks: RealmSet<Snack> = RealmSet<Snack>();\n}\n\n```\n\n```kotlin\nimport io.realm.RealmObject\n\nopen class Snack : RealmObject() {\n    var name: String? = null\n}\n\n```\n\n```kotlin\nval frog = realm.createObject(Frog::class.java)\nfrog.name = \"Jonathan Livingston Applesauce\"\n\n// get the RealmSet field from the object we just created\nval set = frog.favoriteSnacks\n\n// add value to the RealmSet\nval flies = realm.createObject(Snack::class.java)\nflies.name = \"flies\"\nset.add(flies)\n\n// add multiple values to the RealmSet\nval water = realm.createObject(Snack::class.java)\nwater.name = \"water\"\nval verySmallRocks = realm.createObject(Snack::class.java)\nverySmallRocks.name = \"verySmallRocks\"\nset.addAll(listOf(water, verySmallRocks))\n\n// check for the presence of a key with contains\nAssert.assertTrue(set.contains(flies))\n\n// check for the presence of multiple keys with containsAll\nval biscuits = realm.createObject(Snack::class.java)\nbiscuits.name = \"biscuits\"\nAssert.assertTrue(set.containsAll(Arrays.asList(water, biscuits)) == false)\n\n// remove string from a set\nset.remove(verySmallRocks)\n\n// set no longer contains that string\nAssert.assertTrue(set.contains(verySmallRocks) == false)\n\n// deleting a Realm object also removes it from any RealmSets\nval sizeOfSetBeforeDelete = set.size\nflies.deleteFromRealm()\n// deleting flies object reduced the size of the set by one\nAssert.assertTrue(sizeOfSetBeforeDelete == set.size + 1)\n\n```\n\n## Notifications\nTo subscribe to changes to a `RealmSet`, pass a\n`SetChangeListener`\nimplementation to the `RealmSet.addChangeListener` method.\nYour `SetChangeListener` implementation must define an\n`onChange()` method, which accepts a reference to the changed `RealmSet`\nand a set of changes as parameters. You can access the number of items\nadded to the set as well as the number of items removed from the set\nthrough the `SetChangeSet` parameter.\n\n#### Java\n\n```java\nAtomicReference<Frog> frog = new AtomicReference<Frog>();\nrealm.executeTransaction(r -> {\n    frog.set(realm.createObject(Frog.class));\n    frog.get().setName(\"Jonathan Livingston Applesauce\");\n});\n\nSetChangeListener<Snack> setChangeListener = new SetChangeListener<Snack>() {\n    @Override\n    public void onChange(@NotNull RealmSet<Snack> set, SetChangeSet changes) {\n        Log.v(\"EXAMPLE\", \"Set changed: \" +\n                changes.getNumberOfInsertions() + \" new items, \" +\n                changes.getNumberOfDeletions() + \" items removed.\");\n    }\n};\nfrog.get().getFavoriteSnacks().addChangeListener(setChangeListener);\n\nrealm.executeTransaction(r -> {\n    // get the RealmSet field from the object we just created\n    RealmSet<Snack> set = frog.get().getFavoriteSnacks();\n\n    // add value to the RealmSet\n    Snack flies = realm.createObject(Snack.class);\n    flies.setName(\"flies\");\n    set.add(flies);\n\n    // add multiple values to the RealmSet\n    Snack water = realm.createObject(Snack.class);\n    water.setName(\"water\");\n    Snack verySmallRocks = realm.createObject(Snack.class);\n    verySmallRocks.setName(\"verySmallRocks\");\n    set.addAll(Arrays.asList(water, verySmallRocks));\n\n});\n\n```\n\n#### Kotlin\n\n```kotlin\nvar frog :Frog? = null\nrealm.executeTransaction { r: Realm? ->\n    frog = realm.createObject(Frog::class.java)\n    frog?.name = \"Jonathan Livingston Applesauce\"\n}\n\nval setChangeListener: SetChangeListener<Snack>\n        = SetChangeListener<Snack> { set, changes ->\n    Log.v(\"EXAMPLE\", \"Set changed: \" +\n            changes.numberOfInsertions + \" new items, \" +\n            changes.numberOfDeletions + \" items removed.\")\n}\nfrog?.favoriteSnacks?.addChangeListener(setChangeListener)\n\nrealm.executeTransaction { r: Realm? ->\n    // get the RealmSet field from the object we just created\n    val set = frog!!.favoriteSnacks\n\n    // add value to the RealmSet\n    val flies = realm.createObject(Snack::class.java)\n    flies.name = \"flies\"\n    set.add(flies)\n\n    // add multiple values to the RealmSet\n    val water = realm.createObject(Snack::class.java)\n    water.name = \"water\"\n    val verySmallRocks = realm.createObject(Snack::class.java)\n    verySmallRocks.name = \"verySmallRocks\"\n    set.addAll(Arrays.asList(water, verySmallRocks))\n}\n\n```\n\n"
  },
  {
    "path": "docs/guides/model-data/data-types.md",
    "content": "# Realm Data Types - Java SDK\n\nExplore detailed guidance for each Realm Java SDK data type and related concepts:\n\n- [Field Types](./data-types/field-types.md)\n- [Collections](./data-types/collections.md)\n- [Counters](./data-types/counters.md)\n- [Dictionaries](./data-types/realmdictionary.md)\n- [Sets](./data-types/realmset.md)\n- [Mixed (RealmAny)](./data-types/realmany.md)\n- [Enums](./data-types/enums.md)\n- [Embedded Objects](./data-types/embedded-objects.md)\n\nEach linked page covers usage details, constraints, and example code where applicable.\n"
  },
  {
    "path": "docs/guides/model-data/define-a-realm-object-model.md",
    "content": "# Define a Realm Object Model - Java SDK\n## Define a Realm Object\nTo define a Realm object in your application,\ncreate a subclass of `RealmObject`\nor implement `RealmModel`.\n\n> Important:\n> - All Realm objects must provide an empty constructor.\n> - All Realm objects must use the `public` visibility modifier in Java\nor the `open` visibility modifier in Kotlin.\n>\n\n> Note:\n> Class names are limited to a maximum of 57 UTF-8 characters.\n>\n\n### Extend RealmObject\nThe following code block shows a Realm object that\ndescribes a Frog. This Frog class can be stored in\nRealm because it `extends` the `RealmObject` class.\n\n#### Java\n\n```java\nimport io.realm.RealmObject;\n\n// To add an object to your Realm Schema, extend RealmObject\npublic class Frog extends RealmObject {\n    private String name;\n    private int age;\n    private String species;\n    private String owner;\n    public Frog(String name, int age, String species, String owner) {\n        this.name = name;\n        this.age = age;\n        this.species = species;\n        this.owner = owner;\n    }\n    public Frog(){} // RealmObject subclasses must provide an empty constructor\n\n    public String getName() { return name; }\n    public void setName(String name) { this.name = name; }\n    public int getAge() { return age; }\n    public void setAge(int age) { this.age = age; }\n    public String getSpecies() { return species; }\n    public void setSpecies(String species) { this.species = species; }\n    public String getOwner() { return owner; }\n    public void setOwner(String owner) { this.owner = owner; }\n}\n```\n\n#### Kotlin\n\n```kotlin\nimport io.realm.RealmObject\n\n// providing default values for each constructor parameter\n// fulfills the need for an empty constructor\nopen class Frog(\n    var name: String? = null,\n    var age: Int = 0,\n    var species: String? = null,\n    var owner: String? = null\n) : RealmObject() // To add an object to your Realm Schema, extend RealmObject\n```\n\n### Implement RealmModel\nThe following code block shows a Realm object that\ndescribes a Frog. This Frog class can\nbe stored in Realm because it `implements` the\n`RealmModel` class and uses the `@RealmClass` annotation:\n\n#### Java\n\n```java\nimport io.realm.RealmModel;\nimport io.realm.annotations.RealmClass;\n\n@RealmClass\npublic class Frog implements RealmModel {\n    private String name;\n    private int age;\n    private String species;\n    private String owner;\n    public Frog(String name, int age, String species, String owner) {\n        this.name = name;\n        this.age = age;\n        this.species = species;\n        this.owner = owner;\n    }\n    public Frog() {} // RealmObject subclasses must provide an empty constructor\n\n    public String getName() { return name; }\n    public void setName(String name) { this.name = name; }\n    public int getAge() { return age; }\n    public void setAge(int age) { this.age = age; }\n    public String getSpecies() { return species; }\n    public void setSpecies(String species) { this.species = species; }\n    public String getOwner() { return owner; }\n    public void setOwner(String owner) { this.owner = owner; }\n}\n```\n\n> Important:\n> All Realm objects must use the `public`\nvisibility modifier.\n>\n\n#### Kotlin\n\n```kotlin\nimport io.realm.RealmModel\nimport io.realm.annotations.RealmClass\n\n@RealmClass\nopen class Frog : RealmModel {\n    var name: String? = null\n    var age = 0\n    var species: String? = null\n    var owner: String? = null\n\n    constructor(name: String?, age: Int, species: String?, owner: String?) {\n        this.name = name\n        this.age = age\n        this.species = species\n        this.owner = owner\n    }\n\n    constructor() {} // RealmObject subclasses must provide an empty constructor\n}\n```\n\n> Important:\n> All Realm objects must use the `open`\nvisibility modifier.\n>\n\n> Tip:\n> When you create a Realm object by extending the `RealmObject`\nclass, you can access `RealmObject` class methods dynamically on\ninstances of your Realm object. Realm objects\ncreated by implementing `RealmModel` can access those same methods\nstatically through the `RealmObject` class:\n>\n> #### Java\n>\n> ```java\n> // With RealmObject\n> frogRealmObject.isValid();\n> frogRealmObject.addChangeListener(listener);\n>\n> // With RealmModel\n> RealmObject.isValid(frogRealmModel);\n> RealmObject.addChangeListener(frogRealmModel, listener);\n>\n> ```\n>\n>\n> #### Kotlin\n>\n> ```kotlin\n> // With RealmObject\n> frogRealmObject?.isValid\n> frogRealmObject?.addChangeListener(listener)\n>\n> // With RealmModel\n> RealmObject.isValid(frogRealmModel)\n> RealmObject.addChangeListener(frogRealmModel, listener)\n>\n> ```\n>\n>\n\n## Lists\nRealm objects can contain lists of non-Realm-object data\ntypes:\n\n#### Java\n\nUnlike lists of Realm objects, these lists can contain\nnull values. If null values shouldn't be allowed, use the\n@Required annotation.\n\n```java\nimport io.realm.RealmList;\nimport io.realm.RealmObject;\n\npublic class Frog extends RealmObject {\n    private String name;\n    private int age;\n    private String species;\n    private String owner;\n    private RealmList<String> favoriteColors;\n    public Frog(String name, int age, String species, String owner, RealmList<String> favoriteColors) {\n        this.name = name;\n        this.age = age;\n        this.species = species;\n        this.owner = owner;\n        this.favoriteColors = favoriteColors;\n    }\n    public Frog(){} // RealmObject subclasses must provide an empty constructor\n\n    public String getName() { return name; }\n    public void setName(String name) { this.name = name; }\n    public int getAge() { return age; }\n    public void setAge(int age) { this.age = age; }\n    public String getSpecies() { return species; }\n    public void setSpecies(String species) { this.species = species; }\n    public String getOwner() { return owner; }\n    public void setOwner(String owner) { this.owner = owner; }\n    public RealmList<String> getFavoriteColors() { return favoriteColors; }\n    public void setFavoriteColors(RealmList<String> favoriteColors) { this.favoriteColors = favoriteColors; }\n}\n```\n\n#### Kotlin\n\n```kotlin\nimport io.realm.RealmList\nimport io.realm.RealmObject\n\nopen class Frog : RealmObject {\n    var name: String? = null\n    var age = 0\n    var species: String? = null\n    var owner: String? = null\n    var favoriteColors : RealmList<String>? = null\n\n    constructor(\n        name: String?,\n        age: Int,\n        species: String?,\n        owner: String?,\n        favoriteColors: RealmList<String>?\n    ) {\n        this.name = name\n        this.age = age\n        this.species = species\n        this.owner = owner\n        this.favoriteColors = favoriteColors\n    }\n\n    constructor() {} // RealmObject subclasses must provide an empty constructor\n}\n```\n\n> Seealso:\n> Data Types: Lists\n>\n\n## Define an Embedded Object Field\nRealm provides the ability to nest objects within other\nobjects. This has several advantages:\n\n- When you delete an object that contains another object, the delete\noperation removes both objects from the realm, so unused objects\ndon't accumulate in your realm file, taking up valuable space on\nuser's mobile devices.\n\nTo embed an object, set the `embedded` property of the\n`@RealmClass`\nannotation to `true` on the class that you'd like to nest within\nanother class:\n\n#### Java\n\n```java\nimport io.realm.RealmObject;\nimport io.realm.annotations.RealmClass;\n\n@RealmClass(embedded=true)\npublic class Fly extends RealmObject {\n    private String name;\n    public Fly(String name) {\n        this.name = name;\n    }\n    public Fly() {} // RealmObject subclasses must provide an empty constructor\n}\n```\n\n#### Kotlin\n\n```kotlin\nimport io.realm.RealmObject\nimport io.realm.annotations.RealmClass\n\n@RealmClass(embedded = true)\nopen class Fly : RealmObject {\n    private var name: String? = null\n\n    constructor(name: String?) {\n        this.name = name\n    }\n\n    constructor() {} // RealmObject subclasses must provide an empty constructor\n}\n```\n\nThen, any time you reference that class from another class,\nRealm will embed the referenced class within the enclosing\nclass, as in the following example:\n\n#### Java\n\n```java\nimport io.realm.RealmObject;\n\npublic class Frog extends RealmObject {\n    private String name;\n    private int age;\n    private String species;\n    private String owner;\n    private Fly lastMeal;\n    public Frog(String name, int age, String species, String owner, Fly lastMeal) {\n        this.name = name;\n        this.age = age;\n        this.species = species;\n        this.owner = owner;\n        this.lastMeal = lastMeal;\n    }\n    public Frog(){} // RealmObject subclasses must provide an empty constructor\n\n    public String getName() { return name; }\n    public void setName(String name) { this.name = name; }\n    public int getAge() { return age; }\n    public void setAge(int age) { this.age = age; }\n    public String getSpecies() { return species; }\n    public void setSpecies(String species) { this.species = species; }\n    public String getOwner() { return owner; }\n    public void setOwner(String owner) { this.owner = owner; }\n    public Fly getLastMeal() { return lastMeal; }\n    public void setLastMeal(Fly lastMeal) { this.lastMeal = lastMeal; }\n}\n```\n\n#### Kotlin\n\n```kotlin\nimport io.realm.RealmObject\n\nopen class Frog : RealmObject {\n    var name: String? = null\n    var age = 0\n    var species: String? = null\n    var owner: String? = null\n    var lastMeal: Fly? = null\n\n    constructor(\n        name: String?,\n        age: Int,\n        species: String?,\n        owner: String?,\n        lastMeal: Fly?\n    ) {\n        this.name = name\n        this.age = age\n        this.species = species\n        this.owner = owner\n        this.lastMeal = lastMeal\n    }\n\n    constructor() {} // RealmObject subclasses must provide an empty constructor\n}\n```\n\n> Seealso:\n> Data Types: Embedded Objects\n>\n\n## Annotations\nUse annotations to customize your Realm object models.\n\n### Primary Key\n> Version added: 10.6.0\n> Realm automatically indexes\nprimary key fields. Previously, Realm only indexed `String` primary\nkeys automatically.\n>\n\nRealm treats fields marked with the\n`@PrimaryKey` annotation\nas primary keys for their corresponding object schema. Primary keys are\nsubject to the following limitations:\n\n- You can define only one primary key per object schema.\n- Primary key values must be unique across all instances of an object\nin a realm. Attempting to insert a duplicate primary key value\nresults in a `RealmPrimaryKeyConstraintException`.\n- Primary key values are immutable. To change the primary key value of\nan object, you must delete the original object and insert a new object\nwith a different primary key value.\n- Embedded objects cannot define a\nprimary key.\n\nYou can create a primary key with any of the following types:\n\n- `String`\n- `UUID`\n- `ObjectId`\n- `Integer` or `int`\n- `Long` or `long`\n- `Short` or `short`\n- `Byte` or `byte[]`\n\nNon-primitive types can contain a value of `null` as a primary key\nvalue, but only for one object of a particular type, since each primary\nkey value must be unique. Attempting to insert an object with an existing\nprimary key into a realm will result in a\n`[RealmPrimaryKeyConstraintException`.\n\nRealm automatically indexes\nprimary key fields, which allows you to efficiently read and modify\nobjects based on their primary key.\n\nYou cannot change the primary key field for an object type after adding\nany object of that type to a realm.\n\nEmbedded objects cannot contain primary keys.\n\nYou may optionally define a primary key for an object type as part of\nthe object schema with the\n`@PrimaryKey` annotation:\n\n#### Java\n\n```java\nimport io.realm.RealmObject;\nimport io.realm.annotations.PrimaryKey;\n\npublic class Frog extends RealmObject {\n    @PrimaryKey private String name;\n    private int age;\n    private String species;\n    private String owner;\n    public Frog(String name, int age, String species, String owner) {\n        this.name = name;\n        this.age = age;\n        this.species = species;\n        this.owner = owner;\n    }\n    public Frog(){} // RealmObject subclasses must provide an empty constructor\n\n    public String getName() { return name; }\n    public void setName(String name) { this.name = name; }\n    public int getAge() { return age; }\n    public void setAge(int age) { this.age = age; }\n    public String getSpecies() { return species; }\n    public void setSpecies(String species) { this.species = species; }\n    public String getOwner() { return owner; }\n    public void setOwner(String owner) { this.owner = owner; }\n}\n```\n\n#### Kotlin\n\n```kotlin\nimport io.realm.RealmObject\nimport io.realm.annotations.PrimaryKey\n\nopen class Frog : RealmObject {\n    @PrimaryKey var name : String? = null\n    var age = 0\n    var species: String? = null\n    var owner: String? = null\n\n    constructor(name: String?, age: Int, species: String?, owner: String?) {\n        this.name = name\n        this.age = age\n        this.species = species\n        this.owner = owner\n    }\n\n    constructor() {} // RealmObject subclasses must provide an empty constructor\n}\n```\n\n### Required Fields\n#### Java\n\n```java\nimport io.realm.RealmObject;\nimport io.realm.annotations.Required;\n\npublic class Frog extends RealmObject {\n    @Required private String name;\n    private int age;\n    private String species;\n    private String owner;\n    public Frog(String name, int age, String species, String owner) {\n        this.name = name;\n        this.age = age;\n        this.species = species;\n        this.owner = owner;\n    }\n    public Frog(){} // RealmObject subclasses must provide an empty constructor\n\n    public String getName() { return name; }\n    public void setName(String name) { this.name = name; }\n    public int getAge() { return age; }\n    public void setAge(int age) { this.age = age; }\n    public String getSpecies() { return species; }\n    public void setSpecies(String species) { this.species = species; }\n    public String getOwner() { return owner; }\n    public void setOwner(String owner) { this.owner = owner; }\n}\n```\n\n#### Kotlin\n\n```kotlin\nimport io.realm.RealmObject\nimport io.realm.annotations.Required\n\nopen class Frog : RealmObject {\n    @Required var name: String? = null\n    var age = 0\n    var species: String? = null\n    var owner: String? = null\n\n    constructor(name: String?, age: Int, species: String?, owner: String?) {\n        this.name = name\n        this.age = age\n        this.species = species\n        this.owner = owner\n    }\n\n    constructor() {} // RealmObject subclasses must provide an empty constructor\n}\n```\n\n### Optional Fields\nFields marked with Java object types and Kotlin nullable types\n(ending with `?`) are nullable by default. All other types\n(primitives, non-nullable Kotlin object types) are required by default.\nYou can mark a nullable field with the `@Required`\nannotation to prevent that field from holding a null value.\n`RealmLists` are never nullable, but\nyou can use the `@Required` annotation to prevent objects in a list\nfrom holding a null value, even if the base type would otherwise allow it.\nYou cannot mark a `RealmList` of `RealmObject` subtypes as required.\n\nYou can make any of the following types required:\n\n- `String`\n- `UUID`\n- `ObjectId`\n- `Integer`\n- `Long`\n- `Short`\n- `Byte` or `byte[]`\n- `Boolean`\n- `Float`\n- `Double`\n- `Date`\n- `RealmList`\n\nPrimitive types such as `int` and the `RealmList` type are\nimplicitly required. Fields with the `RealmObject` type are always\nnullable, and cannot be made required.\n\n> Important:\n> In Kotlin, types are non-nullable by default unless you explicitly\nadd a `?` suffix to the type. You can only annotate\nnullable types. Using the\n`@Required` annotation on non-nullable types will fail compilation.\n>\n\n#### Java\n\nNullable fields are optional by default in Realm, unless\notherwise specified with the @Required\nannotation. The following types are nullable:\n\n- `String`\n- `Date`\n- `UUID`\n- `ObjectId`\n- `Integer`\n- `Long`\n- `Short`\n- `Byte` or `byte[]`\n- `Boolean`\n- `Float`\n- `Double`\n\nPrimitive types like `int` and `long` are non-nullable by\ndefault and cannot be made nullable, as they cannot be set to a\nnull value.\n\n#### Kotlin\n\nIn Kotlin, fields are considered nullable only if a field is\nmarked nullable with the Kotlin [? operator](https://kotlinlang.org/docs/reference/null-safety.html) except\nfor the following types:\n\n- `String`\n- `Date`\n- `UUID`\n- `ObjectId`\n- `Decimal128`\n- `RealmAny`\n\nYou can require any type that ends with the Kotlin `?`\noperator, such as `Int?`.\n\nThe `RealmList` type is non-nullable by default and cannot be\nmade nullable.\n\n### Default Field Values\nTo assign a default value to a field, use the built-in language features\nto assign default values.\n\n#### Java\n\nUse the class constructor(s) to assign default values:\n\n```java\nimport io.realm.RealmObject;\n\npublic class Frog extends RealmObject {\n    private String name = \"Kitty\";\n    private int age;\n    private String species;\n    private String owner;\n    public Frog(String name, int age, String species, String owner) {\n        this.name = name;\n        this.age = age;\n        this.species = species;\n        this.owner = owner;\n    }\n    public Frog(){} // RealmObject subclasses must provide an empty constructor\n\n    public String getName() { return name; }\n    public void setName(String name) { this.name = name; }\n    public int getAge() { return age; }\n    public void setAge(int age) { this.age = age; }\n    public String getSpecies() { return species; }\n    public void setSpecies(String species) { this.species = species; }\n    public String getOwner() { return owner; }\n    public void setOwner(String owner) { this.owner = owner; }\n}\n```\n\n#### Kotlin\n\nAssign default values in the field declaration:\n\n```kotlin\nimport io.realm.RealmObject\n\nopen class Frog : RealmObject {\n    var name = \"Kitty\"\n    var age = 0\n    var species: String? = null\n    var owner: String? = null\n\n    constructor(name: String, age: Int, species: String?, owner: String?) {\n        this.name = name\n        this.age = age\n        this.species = species\n        this.owner = owner\n    }\n\n    constructor() {} // RealmObject subclasses must provide an empty constructor\n}\n```\n\n> Note:\n> While default values ensure that a newly created object cannot contain\na value of `null` (unless you specify a default value of `null`),\nthey do not impact the nullability of a field. To make a field\nnon-nullable, see Required Fields.\n>\n\n### Index a Field\n**Indexes** support the efficient execution of queries in\nRealm. Without indexes, Realm must perform a\n*collection scan*, i.e. scan every document in a collection, to select\nthose documents that match a query. If an appropriate index exists for a\nquery, Realm can use the index to limit the number of\ndocuments that it must inspect.\n\nIndexes are special data structures that store a small portion of a\nrealm's data in an easy to traverse form. The index stores the value\nof a specific field ordered by the value of the field. The ordering of\nthe index entries supports efficient equality matches and range-based\nquery operations.\n\nAdding an index can speed up some queries at the cost of slightly slower write\ntimes and additional storage and memory overhead. Indexes require space in your\nrealm file, so adding an index to a property will increase disk space consumed\nby your realm file. Each index entry is a minimum of 12 bytes.\n\nYou can index fields with the following types:\n\n- `String`\n- `UUID`\n- `ObjectId`\n- `Integer` or `int`\n- `Long` or `long`\n- `Short` or `short`\n- `Byte` or `byte[]`\n- `Boolean` or `bool`\n- `Date`\n- `RealmAny`\n\nRealm creates indexes for fields annotated with\n`@Index`.\n\nTo index a field, use the `@Index`\nannotation:\n\n#### Java\n\n```java\nimport io.realm.RealmObject;\nimport io.realm.annotations.Index;\n\npublic class Frog extends RealmObject {\n    private String name;\n    private int age;\n    @Index private String species;\n    private String owner;\n    public Frog(String name, int age, String species, String owner) {\n        this.name = name;\n        this.age = age;\n        this.species = species;\n        this.owner = owner;\n    }\n    public Frog(){} // RealmObject subclasses must provide an empty constructor\n\n    public String getName() { return name; }\n    public void setName(String name) { this.name = name; }\n    public int getAge() { return age; }\n    public void setAge(int age) { this.age = age; }\n    public String getSpecies() { return species; }\n    public void setSpecies(String species) { this.species = species; }\n    public String getOwner() { return owner; }\n    public void setOwner(String owner) { this.owner = owner; }\n}\n```\n\n#### Kotlin\n\n```kotlin\nimport io.realm.RealmObject\nimport io.realm.annotations.Index\n\nopen class Frog : RealmObject {\n    var name: String? = null\n    var age = 0\n    @Index var species : String? = null\n    var owner: String? = null\n\n    constructor(name: String?, age: Int, species: String?, owner: String?) {\n        this.name = name\n        this.age = age\n        this.species = species\n        this.owner = owner\n    }\n\n    constructor() {} // RealmObject subclasses must provide an empty constructor\n}\n```\n\n### Ignore a Field\nIf you don't want to save a field in your model to a realm, you can\nignore a field.\n\nIgnore a field from a Realm object model with the\n`@Ignore` annotation:\n\n#### Java\n\n```java\nimport io.realm.RealmObject;\nimport io.realm.annotations.Ignore;\n\npublic class Frog extends RealmObject {\n    private String name;\n    private int age;\n    private String species;\n    // can you ever really own a frog persistently?\n    @Ignore private String owner;\n    public Frog(String name, int age, String species, String owner) {\n        this.name = name;\n        this.age = age;\n        this.species = species;\n        this.owner = owner;\n    }\n    public Frog(){} // RealmObject subclasses must provide an empty constructor\n\n    public String getName() { return name; }\n    public void setName(String name) { this.name = name; }\n    public int getAge() { return age; }\n    public void setAge(int age) { this.age = age; }\n    public String getSpecies() { return species; }\n    public void setSpecies(String species) { this.species = species; }\n    public String getOwner() { return owner; }\n    public void setOwner(String owner) { this.owner = owner; }\n}\n```\n\n#### Kotlin\n\n```kotlin\nimport io.realm.RealmObject\nimport io.realm.annotations.Ignore\n\nopen class Frog : RealmObject {\n    var name: String? = null\n    var age = 0\n    var species: String? = null\n    // can you ever really own a frog persistently?\n    @Ignore var owner  : String? = null\n\n    constructor(name: String?, age: Int, species: String?, owner: String?) {\n        this.name = name\n        this.age = age\n        this.species = species\n        this.owner = owner\n    }\n\n    constructor() {} // RealmObject subclasses must provide an empty constructor\n}\n```\n\n> Note:\n> Fields marked `static` or `transient` are always ignored, and do\nnot need the `@Ignore` annotation.\n>\n\n### Rename a Field\nBy default, Realm uses the name defined in the model class\nto represent fields internally. In some cases you might want to change\nthis behavior:\n\n- To make it easier to work across platforms, since naming conventions differ.\n- To change a field name in Kotlin without forcing a migration.\n\nChoosing an internal name that differs from the name used in model classes\nhas the following implications:\n\n- Migrations must use the internal name when creating classes and fields.\n- Schema errors reported will use the internal name.\n\nUse the `@RealmField`\nannotation to rename a field:\n\n#### Java\n\n```java\nimport io.realm.RealmObject;\nimport io.realm.annotations.RealmField;\n\npublic class Frog extends RealmObject {\n    private String name;\n    private int age;\n    @RealmField(\"latinName\") private String species;\n    private String owner;\n    public Frog(String name, int age, String species, String owner) {\n        this.name = name;\n        this.age = age;\n        this.species = species;\n        this.owner = owner;\n    }\n    public Frog(){} // RealmObject subclasses must provide an empty constructor\n\n    public String getName() { return name; }\n    public void setName(String name) { this.name = name; }\n    public int getAge() { return age; }\n    public void setAge(int age) { this.age = age; }\n    public String getSpecies() { return species; }\n    public void setSpecies(String species) { this.species = species; }\n    public String getOwner() { return owner; }\n    public void setOwner(String owner) { this.owner = owner; }\n}\n```\n\n#### Kotlin\n\n```kotlin\nimport io.realm.RealmObject\nimport io.realm.annotations.RealmField\n\nopen class Frog : RealmObject {\n    var name: String? = null\n    var age = 0\n    @RealmField(\"latinName\") var species: String? = null\n    var owner: String? = null\n\n    constructor(name: String?, age: Int, species: String?, owner: String?) {\n        this.name = name\n        this.age = age\n        this.species = species\n        this.owner = owner\n    }\n\n    constructor() {} // RealmObject subclasses must provide an empty constructor\n}\n```\n\nAlternatively, you can also assign a naming policy at the module or\nclass levels to change the way that Realm interprets field\nnames.\n\nYou can define a\n`naming policy`\nat the module level,\nwhich will affect all classes included in the module:\n\n#### Java\n\n```java\nimport io.realm.annotations.RealmModule;\nimport io.realm.annotations.RealmNamingPolicy;\n\n@RealmModule(\n        allClasses = true,\n        classNamingPolicy = RealmNamingPolicy.LOWER_CASE_WITH_UNDERSCORES,\n        fieldNamingPolicy = RealmNamingPolicy.LOWER_CASE_WITH_UNDERSCORES\n)\npublic class MyModule {\n}\n```\n\n#### Kotlin\n\n```kotlin\nimport io.realm.annotations.RealmModule\nimport io.realm.annotations.RealmNamingPolicy\n\n@RealmModule(\n    allClasses = true,\n    classNamingPolicy = RealmNamingPolicy.LOWER_CASE_WITH_UNDERSCORES,\n    fieldNamingPolicy = RealmNamingPolicy.LOWER_CASE_WITH_UNDERSCORES\n)\nopen class MyModule\n```\n\nYou can also define a\n`naming policy`\nat the class level, which overrides module level settings:\n\n#### Java\n\n```java\nimport io.realm.RealmObject;\nimport io.realm.annotations.RealmClass;\nimport io.realm.annotations.RealmNamingPolicy;\n\n@RealmClass(fieldNamingPolicy = RealmNamingPolicy.PASCAL_CASE)\npublic class Frog extends RealmObject {\n    private String name;\n    private int age;\n    private String species;\n    private String owner;\n    public Frog(String name, int age, String species, String owner) {\n        this.name = name;\n        this.age = age;\n        this.species = species;\n        this.owner = owner;\n    }\n    public Frog(){} // RealmObject subclasses must provide an empty constructor\n\n    public String getName() { return name; }\n    public void setName(String name) { this.name = name; }\n    public int getAge() { return age; }\n    public void setAge(int age) { this.age = age; }\n    public String getSpecies() { return species; }\n    public void setSpecies(String species) { this.species = species; }\n    public String getOwner() { return owner; }\n    public void setOwner(String owner) { this.owner = owner; }\n}\n```\n\n#### Kotlin\n\n```kotlin\nimport io.realm.RealmObject\nimport io.realm.annotations.RealmClass\nimport io.realm.annotations.RealmNamingPolicy\n\n@RealmClass(fieldNamingPolicy = RealmNamingPolicy.PASCAL_CASE)\nopen class Frog : RealmObject {\n    var name: String? = null\n    var age = 0\n    var species: String? = null\n    var owner: String? = null\n\n    constructor(name: String?, age: Int, species: String?, owner: String?) {\n        this.name = name\n        this.age = age\n        this.species = species\n        this.owner = owner\n    }\n\n    constructor() {} // RealmObject subclasses must provide an empty constructor\n}\n```\n\n### Rename a Class\nBy default, Realm uses the name defined in the model class\nto represent classes internally. In some cases you might want to change\nthis behavior:\n\n- To support multiple model classes with the same simple name in different packages.\n- To make it easier to work across platforms, since naming conventions differ.\n- To use a class name that is longer than the 57 character limit enforced by Realm.\n- To change a class name in Kotlin without forcing a migration.\n\nUse the `@RealmClass`\nannotation to rename a class:\n\n#### Java\n\n```java\nimport io.realm.RealmObject;\nimport io.realm.annotations.RealmClass;\n\n@RealmClass(name = \"ShortBodiedTaillessAmphibian\")\npublic class Frog extends RealmObject {\n    private String name;\n    private int age;\n    private String species;\n    private String owner;\n    public Frog(String name, int age, String species, String owner) {\n        this.name = name;\n        this.age = age;\n        this.species = species;\n        this.owner = owner;\n    }\n    public Frog(){} // RealmObject subclasses must provide an empty constructor\n\n    public String getName() { return name; }\n    public void setName(String name) { this.name = name; }\n    public int getAge() { return age; }\n    public void setAge(int age) { this.age = age; }\n    public String getSpecies() { return species; }\n    public void setSpecies(String species) { this.species = species; }\n    public String getOwner() { return owner; }\n    public void setOwner(String owner) { this.owner = owner; }\n}\n```\n\n#### Kotlin\n\n```kotlin\nimport io.realm.RealmObject\nimport io.realm.annotations.RealmClass\n\n@RealmClass(name = \"Short_Bodied_Tailless_Amphibian\")\nopen class Frog : RealmObject {\n    var name: String? = null\n    var age = 0\n    var species: String? = null\n    var owner: String? = null\n\n    constructor(name: String?, age: Int, species: String?, owner: String?) {\n        this.name = name\n        this.age = age\n        this.species = species\n        this.owner = owner\n    }\n\n    constructor() {} // RealmObject subclasses must provide an empty constructor\n}\n```\n\n## Omit Classes from your Realm Schema\nBy default, your application's Realm Schema includes all\nclasses that extend `RealmObject`. If you only want to include a\nsubset of classes that extend `RealmObject` in your Realm\nSchema, you can include that subset of classes in a module and open\nyour realm using that module:\n\n#### Java\n\n```java\nimport io.realm.annotations.RealmModule;\n\n@RealmModule(classes = { Frog.class, Fly.class })\npublic class MyModule {\n}\n```\n\n#### Kotlin\n\n```kotlin\nimport io.realm.annotations.RealmModule\n\n@RealmModule(classes = [Frog::class, Fly::class])\nopen class MyModule\n```\n\n"
  },
  {
    "path": "docs/guides/model-data/modify-an-object-schema.md",
    "content": "# Change an Object Model - Java SDK\n#### Local\n\nThe following examples demonstrate how to add, delete, and modify\nproperties in a schema. First, make the required schema change.\nThen, increment the schema version. Finally, if the change is\nbreaking (destructive) create a corresponding migration function to move data from the original schema\nto the updated schema.\n\n> Note:\n> Assume that each schema change shown in the following example\noccurs after the application has used the existing schema. The\nnew schema version numbers apply only after you open the\nrealm and explicitly specify the new version number.\nIn other words, you can't specify version 3 without previously\nspecifying and using versions 0, 1, and 2.\n>\n\nA realm using schema version `0` has a `Person` object type:\n\n#### Java\n\n```java\npublic class Person extends RealmObject { // Realm schema version 0\n    @Required\n    public String firstName;\n    @Required\n    public int age;\n}\n\n```\n\n#### Kotlin\n\n```kotlin\nclass Person: RealmObject { // Realm schema version 0\n    var firstName: String = \"\"\n    var age: int = 0\n}\n\n```\n\n### A. Add a Property\nThe following example adds a `lastName` property to the\noriginal Person schema:\n\n#### Java\n\n```java\npublic class Person extends RealmObject { // Realm schema version 1\n    @Required\n    public String firstName;\n    @Required\n    public String lastName;\n    @Required\n    public int age;\n}\n```\n\n#### Kotlin\n\n```kotlin\nclass Person: RealmObject { // Realm schema version 1\n    var firstName: String = \"\"\n    var lastName: String = \"\"\n    var age: int = 0\n}\n\n```\n\n### B. Delete a Property\nThe following example uses a combined\n`fullName` property instead of the separate `firstName` and\n`lastName` property in the original Person schema:\n\n#### Java\n\n```java\npublic class Person extends RealmObject { // Realm schema version 2\n    @Required\n    public String fullName;\n    @Required\n    public int age;\n}\n\n```\n\n#### Kotlin\n\n```kotlin\nclass Person: RealmObject { // Realm schema version 2\n    var fullName: String = \"\"\n    var age: int = 0\n}\n\n```\n\n### C. Modify a Property Type or Rename a Property\nThe following example modifies the `age` property in the\noriginal Person schema by\nrenaming it to `birthday` and changing the type to `Date`:\n\n#### Java\n\n```java\npublic class Person extends RealmObject { // Realm schema version 3\n    @Required\n    public String fullName;\n    @Required\n    public Date birthday = new Date();\n}\n\n```\n\n#### Kotlin\n\n```kotlin\nclass Person: RealmObject { // Realm schema version 3\n    var fullName: String = \"\"\n    var birthday: Date = Date()\n}\n\n```\n\n### D. Migration Functions\nTo migrate the realm to conform to the updated\n`Person` schema, set the realm's\nschema version to `3`\nand define a migration function to set the value of\n`fullName` based on the existing `firstName` and\n`lastName` properties and the value of `birthday` based on\n`age`:\n\n#### Java\n\n```java\npublic class Migration implements RealmMigration {\n  @Override\n  public void migrate(DynamicRealm realm, long oldVersion, long newVersion) {\n     Long version = oldVersion;\n\n     // DynamicRealm exposes an editable schema\n     RealmSchema schema = realm.getSchema();\n\n     // Changes from version 0 to 1: Adding lastName.\n     // All properties will be initialized with the default value \"\".\n     if (version == 0L) {\n        schema.get(\"Person\")\n            .addField(\"lastName\", String.class, FieldAttribute.REQUIRED);\n        version++;\n     }\n\n     // Changes from version 1 to 2: combine firstName/lastName into fullName\n     if (version == 1L) {\n        schema.get(\"Person\")\n            .addField(\"fullName\", String.class, FieldAttribute.REQUIRED)\n            .transform( DynamicRealmObject obj -> {\n                String name = \"${obj.getString(\"firstName\")} ${obj.getString(\"lastName\")}\";\n                obj.setString(\"fullName\", name);\n            })\n            .removeField(\"firstName\")\n            .removeField(\"lastName\");\n        version++;\n     }\n\n     // Changes from version 2 to 3: replace age with birthday\n     if (version == 2L) {\n        schema.get(\"Person\")\n            .addField(\"birthday\", Date::class.java, FieldAttribute.REQUIRED)\n            .transform(DynamicRealmObject obj -> {\n                Int birthYear = Date().year - obj.getInt(\"age\");\n                obj.setDate(\"birthday\", Date(birthYear, 1, 1));\n            })\n            .removeField(\"age\");\n        version++;\n     }\n  }\n};\n\n@RealmModule(classes = { Person.class })\npublic class Module {}\n\nRealmConfiguration config = new RealmConfiguration.Builder()\n    .modules(new Module())\n    .schemaVersion(3) // Must be bumped when the schema changes\n    .migration(new Migration()) // Migration to run instead of throwing an exception\n    .build();\n\n```\n\n#### Kotlin\n\n```kotlin\nval migration = object: RealmMigration {\n    override fun migrate(realm: DynamicRealm, oldVersion: Long, newVersion: Long) {\n        var version: Long = oldVersion\n\n        // DynamicRealm exposes an editable schema\n        val schema: RealmSchema = realm.schema\n\n        // Changes from version 0 to 1: Adding lastName.\n        // All properties will be initialized with the default value \"\".\n        if (version == 0L) {\n            schema.get(\"Person\")!!\n                    .addField(\"lastName\", String::class.java, FieldAttribute.REQUIRED)\n            version++\n        }\n\n        // Changes from version 1 to 2: Combining firstName/lastName into fullName\n        if (version == 1L) {\n            schema.get(\"Person\")!!\n                    .addField(\"fullName\", String::class.java, FieldAttribute.REQUIRED)\n                    .transform { obj: DynamicRealmObject ->\n                        val name = \"${obj.getString(\"firstName\")} ${obj.getString(\"lastName\")}\"\n                        obj.setString(\"fullName\", name)\n                    }\n                    .removeField(\"firstName\")\n                    .removeField(\"lastName\")\n            version++\n        }\n\n        // Changes from version 2 to 3: Replace age with birthday\n        if (version == 2L) {\n            schema.get(\"Person\")!!\n                    .addField(\"birthday\", Date::class.java, FieldAttribute.REQUIRED)\n                    .transform { obj: DynamicRealmObject ->\n                        var birthYear = Date().year - obj.getInt(\"age\")\n                        obj.setDate(\"birthday\", Date(birthYear, 1, 1))\n                    }\n                    .removeField(\"age\")\n            version++\n        }\n    }\n}\n\n@RealmModule(classes = { Person::class.java })\nclass Module\n\nval config = RealmConfiguration.Builder()\n    .schemaVersion(3) // Must be bumped when the schema changes\n    .migration(migration) // Migration to run instead of throwing an exception\n    .build()\n```\n"
  },
  {
    "path": "docs/guides/model-data/relationships.md",
    "content": "# Relationships - Java SDK\n## Relationships\nRealm allows you to define explicit relationships between the types of\nobjects in an App. A relationship is an object property that references\nanother Realm object rather than one of the primitive data types. You\ndefine relationships by setting the type of an object property to\nanother object type in the property schema.\n\nRelationships are direct references to other objects in a realm, which\nmeans that you don't need bridge tables or explicit joins to define a\nrelationship like you would in a relational database. Instead you can\naccess related objects by reading and writing to the property that\ndefines the relationship. Realm executes read operations\nlazily as they come in, so querying a relationship is just as performant\nas reading a regular property.\n\nThere are three primary types of relationships between objects:\n\n- One-to-One Relationship\n- One-to-Many Relationship\n- Inverse Relationship\n\nYou can define relationships, collections, and embedded objects in your\nobject schema using the following types:\n\n- `RealmObject`\n- `RealmList <? extends RealmObject>`\n\nUse annotations to indicate whether a given field represents a foreign\nkey relationship or an embedded object relationship. For more\ninformation, see Relationship Annotations.\n\n### To-One Relationship\nA **to-one** relationship means that an object is related in a specific\nway to no more than one other object. You define a to-one relationship\nfor an object type in its object schema by\nspecifying a property where the type is the related Realm object type.\n\nSetting a relationship field to null removes the connection between\nobjects, but Realm does not delete the referenced object\nunless that object is embedded.\n\n### To-Many Relationship\nA **to-many** relationship means that an object is related in a specific\nway to multiple objects. You can create a relationship between one object\nand any number of objects using a field of type `RealmList<T>`\nwhere `T` is a Realm object in your application:\n\n### Inverse Relationship\nAn **inverse relationship** links an object back to any other objects that refer\nto it in a defined to-one or to-many relationship. Relationship definitions are\nunidirectional, so you must explicitly define a property in the object's model\nas an inverse relationship.\n\nFor example, the to-many relationship \"User has many Tasks\" does not\nautomatically create the inverse relationship \"Task belongs to User\". If you\ndon't specify the inverse relationship in the object model, you would need to\nrun a separate query to look up the user that is assigned to a given task.\n\nTo define an inverse relationship, define a `LinkingObjects` property in your\nobject model. The `LinkingObjects` definition specifies the object type and\nproperty name of the relationship that it inverts.\n\nRealm automatically updates implicit relationships whenever an\nobject is added or removed in the specified relationship. You cannot manually\nset the value of an inverse relationship property.\n\nFields annotated with `@LinkingObjects` must be:\n\n- marked `final`\n- of type `RealmResults<T>` where `T` is the type at the opposite\nend of the relationship\n\nSince relationships are many-to-one or many-to-many, following inverse\nrelationships can result in zero, one, or many objects.\n\nLike any other `RealmResults` set, you can\nquery an inverse relationship.\n\n## Define a Relationship Field\n\n> Warning:\n> Realm objects use getters and setters to persist updated\nfield values to your realms. Always use getters and setters for\nupdates.\n>\n\n### Many-to-One\nTo set up a many-to-one or one-to-one relationship, create a field\nwhose type is a Realm object in your application:\n\n#### Java\n\n```java\nimport io.realm.RealmObject;\n\npublic class Frog extends RealmObject {\n    private String name;\n    private int age;\n    private String species;\n    private String owner;\n    private Frog bestFriend;\n    public Frog(String name, int age, String species, String owner, Frog bestFriend) {\n        this.name = name;\n        this.age = age;\n        this.species = species;\n        this.owner = owner;\n        this.bestFriend = bestFriend;\n    }\n    public Frog(){} // RealmObject subclasses must provide an empty constructor\n\n    public String getName() { return name; }\n    public void setName(String name) { this.name = name; }\n    public int getAge() { return age; }\n    public void setAge(int age) { this.age = age; }\n    public String getSpecies() { return species; }\n    public void setSpecies(String species) { this.species = species; }\n    public String getOwner() { return owner; }\n    public void setOwner(String owner) { this.owner = owner; }\n    public Frog getBestFriend() { return bestFriend; }\n    public void setBestFriend(Frog bestFriend) { this.bestFriend = bestFriend; }\n}\n```\n\n#### Kotlin\n\n```kotlin\nimport io.realm.RealmObject\n\nopen class Frog : RealmObject {\n    var name: String? = null\n    var age = 0\n    var species: String? = null\n    var owner: String? = null\n    var bestFriend: Frog? = null\n\n    constructor(\n        name: String?,\n        age: Int,\n        species: String?,\n        owner: String?,\n        bestFriend: Frog?\n    ) {\n        this.name = name\n        this.age = age\n        this.species = species\n        this.owner = owner\n        this.bestFriend = bestFriend\n    }\n\n    constructor() {} // RealmObject subclasses must provide an empty constructor\n}\n```\n\n> Important:\n> When you declare a to-one relationship in your object model, it must\nbe an optional property. If you try to make a to-one relationship\nrequired, Realm throws an exception at runtime.\n>\n\nEach `Frog` references either zero `Frog` instances or one other `Frog` instance. Nothing\nprevents multiple `Frog` instances from referencing the same `Frog`\nas a best friend; the distinction between a many-to-one and a one-to-one\nrelationship is up to your application.\n\n### Many-to-Many\n#### Java\n\n```java\nimport io.realm.RealmList;\nimport io.realm.RealmObject;\n\npublic class Frog extends RealmObject {\n    private String name;\n    private int age;\n    private String species;\n    private String owner;\n    private RealmList<Frog> bestFriends;\n    public Frog(String name, int age, String species, String owner, RealmList<Frog> bestFriends) {\n        this.name = name;\n        this.age = age;\n        this.species = species;\n        this.owner = owner;\n        this.bestFriends = bestFriends;\n    }\n    public Frog(){} // RealmObject subclasses must provide an empty constructor\n\n    public String getName() { return name; }\n    public void setName(String name) { this.name = name; }\n    public int getAge() { return age; }\n    public void setAge(int age) { this.age = age; }\n    public String getSpecies() { return species; }\n    public void setSpecies(String species) { this.species = species; }\n    public String getOwner() { return owner; }\n    public void setOwner(String owner) { this.owner = owner; }\n    public RealmList<Frog> getBestFriends() { return bestFriends; }\n    public void setBestFriends(RealmList<Frog> bestFriends) { this.bestFriends = bestFriends; }\n}\n```\n\n#### Kotlin\n\n```kotlin\nimport io.realm.RealmList\nimport io.realm.RealmObject\n\nopen class Frog : RealmObject {\n    var name: String? = null\n    var age = 0\n    var species: String? = null\n    var owner: String? = null\n    var bestFriends: RealmList<Frog>? = null\n\n    constructor(\n        name: String?,\n        age: Int,\n        species: String?,\n        owner: String?,\n        bestFriends: RealmList<Frog>?\n    ) {\n        this.name = name\n        this.age = age\n        this.species = species\n        this.owner = owner\n        this.bestFriends = bestFriends\n    }\n\n    constructor() {} // RealmObject subclasses must provide an empty constructor\n}\n```\n\n`RealmList` s are containers of `RealmObject` s, but otherwise behave\nlike a regular collection. You can use the same object in multiple\n`RealmList` s.\n\n### Inverse Relationships\nBy default, Realm relationships are unidirectional. You\ncan follow a link from one class to a referenced class, but not in the\nopposite direction. Consider the following class defining a `Toad` with\na list of `frogFriends`:\n\n#### Java\n\n```java\nimport io.realm.RealmList;\nimport io.realm.RealmObject;\n\npublic class Toad extends RealmObject {\n    private RealmList<Frog> frogFriends;\n    public Toad(RealmList<Frog> frogFriends) {\n        this.frogFriends = frogFriends;\n    }\n    public Toad() {}\n\n    public RealmList<Frog> getFrogFriends() { return frogFriends; }\n    public void setFrogFriends(RealmList<Frog> frogFriends) { this.frogFriends = frogFriends; }\n}\n```\n\n#### Kotlin\n\n```kotlin\nimport io.realm.RealmList\nimport io.realm.RealmObject\n\nopen class Toad : RealmObject {\n    var frogFriends: RealmList<Frog>? = null\n\n    constructor(frogFriends: RealmList<Frog>?) {\n        this.frogFriends = frogFriends\n    }\n\n    constructor() {}\n}\n```\n\nYou can provide a link in the opposite direction, from `Frog` to `Toad`,\nwith the `@LinkingObjects`\nannotation on a `final` (in Java) or `val` (in Kotlin) field of type\n`RealmResults<T>`:\n\n#### Java\n\n```java\nimport io.realm.RealmObject;\nimport io.realm.RealmResults;\nimport io.realm.annotations.LinkingObjects;\n\npublic class Frog extends RealmObject {\n    private String name;\n    private int age;\n    private String species;\n    private String owner;\n    @LinkingObjects(\"frogFriends\")\n    private final RealmResults<Toad> toadFriends = null;\n\n    public Frog(String name, int age, String species, String owner) {\n        this.name = name;\n        this.age = age;\n        this.species = species;\n        this.owner = owner;\n    }\n    public Frog(){} // RealmObject subclasses must provide an empty constructor\n\n    public String getName() { return name; }\n    public void setName(String name) { this.name = name; }\n    public int getAge() { return age; }\n    public void setAge(int age) { this.age = age; }\n    public String getSpecies() { return species; }\n    public void setSpecies(String species) { this.species = species; }\n    public String getOwner() { return owner; }\n    public void setOwner(String owner) { this.owner = owner; }\n}\n```\n\n#### Kotlin\n\n```kotlin\nimport io.realm.RealmObject\nimport io.realm.RealmResults\nimport io.realm.annotations.LinkingObjects\n\nopen class Frog : RealmObject {\n    var name: String? = null\n    var age = 0\n    var species: String? = null\n    var owner: String? = null\n    @LinkingObjects(\"frogFriends\")\n    private val toadFriends: RealmResults<Toad>? = null\n\n    constructor(name: String?, age: Int, species: String?, owner: String?) {\n        this.name = name\n        this.age = age\n        this.species = species\n        this.owner = owner\n    }\n\n    constructor() {} // RealmObject subclasses must provide an empty constructor\n}\n```\n\n> Important:\n> Inverse relationship fields must be marked `final`.\n>\n"
  },
  {
    "path": "docs/guides/model-data.md",
    "content": "# Model Data - Java SDK\n\nAn **object schema** is a configuration object that defines the fields and\nrelationships of a Realm object type. Android\nRealm applications define object schemas with Java or Kotlin\nclasses using Realm Schemas.\n\nObject schemas specify constraints on object fields such as the data\ntype of each field, whether a\nfield is required, and default field values. Schemas can also define\nrelationships between object types in\na realm.\n\nModifying your application's Realm Schema requires you to\nmigrate data from older\nversions of your Realm Schema to the new version.\n\n## Realm Apps\nEvery App has a Realm Schema\ncomposed of a list of object schemas for each type of object that the\nrealms in that application may contain.\n\nRealm guarantees that all objects in a realm conform to the\nschema for their object type and validates objects whenever they're\ncreated, modified, or deleted.\n\n## Relationships\nYou can model **one-to-one** relationships in realm with\n`RealmObject` fields.\nYou can model **one-to-many** and **many-to-one** relationships\n`RealmList` fields.\nInverse relationships are the opposite end of a **one-to-many** or\n**many-to-one** relationship.\nYou can make **inverse** relationships traversable with the\n`@LinkingObjects`\nannotation on a `RealmResults`\nfield. In an instance of a `RealmObject`, inverse relationship fields\ncontain the set of Realm objects that point to that object\ninstance through the described relationship. You can find the same set\nof Realm objects with a manual query, but the inverse\nrelationship field reduces boilerplate query code and capacity for error.\n\n## Realm Objects\nUnlike normal Java objects, which contain their own data, a\nRealm object doesn't contain data. Instead,\nRealm objects read and write properties directly to\nRealm.\n\nInstances of Realm objects can be either **managed** or **unmanaged**.\n\n- **Managed** objects are: persisted in Realmalways up to datethread-confinedgenerally more lightweight than the unmanaged version, as they take\nup less space on the Java heap.\n- **Unmanaged** objects are just like ordinary Java objects, since\nthey are not persisted and never update automatically.\nYou can move unmanaged objects freely across threads.\n\nYou can convert between the two states using\n`realm.copyToRealm()`\nand `realm.copyFromRealm()`.\n\n### RealmProxy\nThe `RealmProxy` classes are the Realm SDK's way of\nensuring that Realm objects don't contain any data\nthemselves. Instead, each class's `RealmProxy` accesses data directly\nin the database.\n\nFor every model class in your project, the Realm annotation\nprocessor generates a corresponding `RealmProxy` class. This class\nextends your model class and is returned when you call\n`Realm.createObject()`. In your code, this object works just like your\nmodel class.\n\n### Realm Object Limitations\nRealm objects:\n\n- cannot contain fields that use the `final` or `volatile` modifiers\n(except for inverse relationship\nfields).\n- cannot extend any object other than `RealmObject`.\n- must contain an empty constructor (if your class does not include any\nconstructor, the automatically generated empty constructor will suffice)\n\nNaming limitations:\n\n- Class names cannot exceed 57 characters.\n- Class names must be unique within realm modules\n- Field names cannot exceed 63 characters.\n\nSize limitations:\n\n- `String` or `byte[]` fields cannot exceed 16 MB.\n\nUsage limitations:\n\n- Because Realm objects are live and can change at any time,\ntheir `hashCode()` value can change over time. As a result, you\nshould not use `RealmObject` instances as a key in any map or set.\n\n## Incremental Builds\nThe bytecode transformer used by Realm supports incremental\nbuilds, but your application requires a full rebuild when adding or\nremoving the following from a Realm object field:\n\n- an `@Ignore` annotation\n- the `static` keyword\n- the `transient` keyword\n\nYou can perform a full rebuild with Build > Clean Project\nand Build > Rebuild Project in these cases.\n\n## Schema Version\nA **schema version** identifies the state of a Realm Schema at some point in time. Realm tracks the schema\nversion of each realm and uses it to map the objects in each realm\nto the correct schema.\n\nSchema versions are integers that you may include\nin the realm configuration when you open a realm. If a client\napplication does not specify a version number when it opens a realm then\nthe realm defaults to version `0`.\n\n> Important:\n> Migrations must update a realm to a\nhigher schema version. Realm throws an error if a client\napplication opens a realm with a schema version that is lower than\nthe realm's current version or if the specified schema version is the\nsame as the realm's current version but includes different\nobject schemas.\n>\n\n## Migrations\nA **local migration** is a migration for a realm with\nanother realm. Local migrations have access to the existing\nRealm Schema, version, and objects and define logic that\nincrementally updates the realm to its new schema version.\nTo perform a local migration you must specify a new schema\nversion that is higher than the current version and provide\na migration function when you open the out-of-date realm.\n\nWith the SDK, you can update underlying data to reflect schema changes\nusing manual migrations. During such a manual migration, you can\ndefine new and deleted properties when they are added or removed from\nyour schema. The editable schema exposed via a\n`DynamicRealm` provides\nconvenience functions for renaming fields. This gives you full control\nover the behavior of your data during complex schema migrations.\n\n> Tip:\n> During development of an application, `RealmObject` classes can\nchange frequently. You can use `Realm.deleteRealm()`to\ndelete the database file and eliminate the need to write a full\nmigration for testing data.\n>\n"
  },
  {
    "path": "docs/guides/quick-start-local.md",
    "content": "# Quick Start - Java SDK\n\nThis page contains information to quickly get Realm\nintegrated into your app. Before you begin, ensure you have:\n\n- Installed the Java SDK\n\n## Initialize Realm\nBefore you can use Realm in your app, you must\ninitialize the Realm library. Your application should\ninitialize Realm just once each time the application runs.\n\nTo initialize the Realm library, provide an Android\n`context` to the `Realm.init()` static function. You can provide\nan Activity, Fragment, or Application `context` for initialization with no\ndifference in behavior. You can initialize the Realm library\nin the `onCreate()` method of an [application subclass](https://developer.android.com/reference/android/app/Application) to\nensure that you only initialize Realm once each time the\napplication runs.\n\n#### Java\n\n```java\nRealm.init(this); // context, usually an Activity or Application\n\n```\n\n#### Kotlin\n\n```kotlin\nRealm.init(this) // context, usually an Activity or Application\n\n```\n\n> Tip:\n> If you create your own `Application` subclass, you must add it to your\napplication's `AndroidManifest.xml` to execute your custom\napplication logic. Set the `android.name` property of your manifest's\napplication definition to ensure that Android instantiates your `Application`\nsubclass before any other class when a user launches your application.\n>\n> ```xml\n> <?xml version=\"1.0\" encoding=\"utf-8\"?>\n> <manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n>    package=\"com.mongodb.example\">\n>\n>    <application\n>       android:name=\".MyApplicationSubclass\"\n>       ...\n>    />\n> </manifest>\n> ```\n>\n\n## Define Your Object Model\nYour application's **data model** defines the structure of data\nstored within Realm.\nYou can define your application's data model via Kotlin or\nJava classes in your application code with\nRealm Object Models.\n\nTo define your application's data model, add the following class\ndefinitions to your application code:\n\n#### Java\n\n```java\nimport io.realm.RealmObject;\nimport io.realm.annotations.PrimaryKey;\nimport io.realm.annotations.Required;\n\npublic class Task extends RealmObject {\n    @PrimaryKey private String name;\n    @Required private String status = TaskStatus.Open.name();\n\n    public void setStatus(TaskStatus status) { this.status = status.name(); }\n    public String getStatus() { return this.status; }\n    public String getName() { return name; }\n    public void setName(String name) { this.name = name; }\n    public Task(String _name) { this.name = _name; }\n    public Task() {}\n}\n\n```\n\n```java\n\npublic enum TaskStatus {\n    Open(\"Open\"),\n    InProgress(\"In Progress\"),\n    Complete(\"Complete\");\n\n    String displayName;\n    TaskStatus(String displayName) {\n        this.displayName = displayName;\n    }\n}\n\n```\n\n#### Kotlin\n\n```kotlin\n\nenum class TaskStatus(val displayName: String) {\n    Open(\"Open\"),\n    InProgress(\"In Progress\"),\n    Complete(\"Complete\"),\n}\n\nopen class Task() : RealmObject() {\n    @PrimaryKey\n    var name: String = \"task\"\n\n    @Required\n    var status: String = TaskStatus.Open.name\n    var statusEnum: TaskStatus\n        get() {\n            // because status is actually a String and another client could assign an invalid value,\n            // default the status to \"Open\" if the status is unreadable\n            return try {\n                TaskStatus.valueOf(status)\n            } catch (e: IllegalArgumentException) {\n                TaskStatus.Open\n            }\n        }\n        set(value) { status = value.name }\n}\n\n```\n\n## Open a Realm\nUse `RealmConfiguration` to control the specifics of the realm you\nwould like to open, including the name or location of the realm,\nwhether to allow synchronous reads or writes to a realm on the UI\nthread, and more.\n\n#### Java\n\n```java\nString realmName = \"My Project\";\nRealmConfiguration config = new RealmConfiguration.Builder().name(realmName).build();\n\nRealm backgroundThreadRealm = Realm.getInstance(config);\n\n```\n\n#### Kotlin\n\n```kotlin\nval realmName: String = \"My Project\"\nval config = RealmConfiguration.Builder().name(realmName).build()\n\nval backgroundThreadRealm : Realm = Realm.getInstance(config)\n\n```\n\n## Create, Read, Update, and Delete Objects\nOnce you have opened a realm, you can modify the\nobjects within that realm in a\nwrite transaction block.\n\n> Important:\n> By default, you can only read or write to a realm in your\napplication's UI thread using\nasynchronous transactions. That is,\nyou can only use `Realm` methods whose name ends with the word\n`Async` in the main thread of your Android application unless you\nexplicitly allow the use of synchronous methods.\n>\n> This restriction exists for the benefit of your application users:\nperforming read and write operations on the UI thread can lead to\nunresponsive or slow UI interactions, so it's usually best to handle\nthese operations either asynchronously or in a background thread.\n\nTo create a new `Task`, instantiate an instance of the\n`Task` class and add it to the realm in a write block:\n\n#### Java\n\n```java\nTask Task = new Task(\"New Task\");\nbackgroundThreadRealm.executeTransaction (transactionRealm -> {\n    transactionRealm.insert(Task);\n});\n\n```\n\n#### Kotlin\n\n```kotlin\nval task : Task = Task()\ntask.name = \"New Task\"\nbackgroundThreadRealm.executeTransaction { transactionRealm ->\n    transactionRealm.insert(task)\n}\n\n```\n\nYou can retrieve a live collection\nof all items in the realm:\n\n#### Java\n\n```java\n// all Tasks in the realm\nRealmResults<Task> Tasks = backgroundThreadRealm.where(Task.class).findAll();\n\n```\n\n#### Kotlin\n\n```kotlin\n// all tasks in the realm\nval tasks : RealmResults<Task> = backgroundThreadRealm.where<Task>().findAll()\n\n```\n\nYou can also filter that collection using a filter:\n\n#### Java\n\n```java\n// you can also filter a collection\nRealmResults<Task> TasksThatBeginWithN = Tasks.where().beginsWith(\"name\", \"N\").findAll();\nRealmResults<Task> openTasks = Tasks.where().equalTo(\"status\", TaskStatus.Open.name()).findAll();\n\n```\n\n#### Kotlin\n\n```kotlin\n// you can also filter a collection\nval tasksThatBeginWithN : List<Task> = tasks.where().beginsWith(\"name\", \"N\").findAll()\nval openTasks : List<Task> = tasks.where().equalTo(\"status\", TaskStatus.Open.name).findAll()\n\n```\n\nTo modify a task, update its properties in a write transaction block:\n\n#### Java\n\n```java\nTask otherTask = Tasks.get(0);\n\n// all modifications to a realm must happen inside of a write block\nbackgroundThreadRealm.executeTransaction( transactionRealm -> {\n    Task innerOtherTask = transactionRealm.where(Task.class).equalTo(\"_id\", otherTask.getName()).findFirst();\n    innerOtherTask.setStatus(TaskStatus.Complete);\n});\n\n```\n\n#### Kotlin\n\n```kotlin\nval otherTask: Task = tasks[0]!!\n\n// all modifications to a realm must happen inside of a write block\nbackgroundThreadRealm.executeTransaction { transactionRealm ->\n    val innerOtherTask : Task = transactionRealm.where<Task>().equalTo(\"name\", otherTask.name).findFirst()!!\n    innerOtherTask.status = TaskStatus.Complete.name\n}\n\n```\n\nFinally, you can delete a task by calling the `deleteFromRealm()`\nmethod in a write transaction block:\n\n#### Java\n\n```java\nTask yetAnotherTask = Tasks.get(0);\nString yetAnotherTaskName = yetAnotherTask.getName();\n// all modifications to a realm must happen inside of a write block\nbackgroundThreadRealm.executeTransaction( transactionRealm -> {\n    Task innerYetAnotherTask = transactionRealm.where(Task.class).equalTo(\"_id\", yetAnotherTaskName).findFirst();\n    innerYetAnotherTask.deleteFromRealm();\n});\n\n```\n\n#### Kotlin\n\n```kotlin\nval yetAnotherTask: Task = tasks.get(0)!!\nval yetAnotherTaskName: String = yetAnotherTask.name\n// all modifications to a realm must happen inside of a write block\nbackgroundThreadRealm.executeTransaction { transactionRealm ->\n    val innerYetAnotherTask : Task = transactionRealm.where<Task>().equalTo(\"name\", yetAnotherTaskName).findFirst()!!\n    innerYetAnotherTask.deleteFromRealm()\n}\n\n```\n\n## Watch for Changes\nYou can watch a realm, collection, or object for changes by attaching a custom\n`OrderedRealmCollectionChangeListener` with the `addChangeListener()`\nmethod:\n\n#### Java\n\n```java\n// all Tasks in the realm\nRealmResults<Task> Tasks = uiThreadRealm.where(Task.class).findAllAsync();\n\nTasks.addChangeListener(new OrderedRealmCollectionChangeListener<RealmResults<Task>>() {\n    @Override\n    public void onChange(RealmResults<Task> collection, OrderedCollectionChangeSet changeSet) {\n        // process deletions in reverse order if maintaining parallel data structures so indices don't change as you iterate\n        OrderedCollectionChangeSet.Range[] deletions = changeSet.getDeletionRanges();\n        for (OrderedCollectionChangeSet.Range range : deletions) {\n            Log.v(\"QUICKSTART\", \"Deleted range: \" + range.startIndex + \" to \" + (range.startIndex + range.length - 1));\n        }\n\n        OrderedCollectionChangeSet.Range[] insertions = changeSet.getInsertionRanges();\n        for (OrderedCollectionChangeSet.Range range : insertions) {\n            Log.v(\"QUICKSTART\", \"Inserted range: \" + range.startIndex + \" to \" + (range.startIndex + range.length - 1));                            }\n\n        OrderedCollectionChangeSet.Range[] modifications = changeSet.getChangeRanges();\n        for (OrderedCollectionChangeSet.Range range : modifications) {\n            Log.v(\"QUICKSTART\", \"Updated range: \" + range.startIndex + \" to \" + (range.startIndex + range.length - 1));                            }\n    }\n});\n\n```\n\n#### Kotlin\n\n```kotlin\n// all tasks in the realm\nval tasks : RealmResults<Task> = realm.where<Task>().findAllAsync()\n\ntasks.addChangeListener(OrderedRealmCollectionChangeListener<RealmResults<Task>> { collection, changeSet ->\n    // process deletions in reverse order if maintaining parallel data structures so indices don't change as you iterate\n    val deletions = changeSet.deletionRanges\n    for (i in deletions.indices.reversed()) {\n        val range = deletions[i]\n        Log.v(\"QUICKSTART\", \"Deleted range: ${range.startIndex} to ${range.startIndex + range.length - 1}\")\n    }\n\n    val insertions = changeSet.insertionRanges\n    for (range in insertions) {\n        Log.v(\"QUICKSTART\", \"Inserted range: ${range.startIndex} to ${range.startIndex + range.length - 1}\")\n    }\n\n    val modifications = changeSet.changeRanges\n    for (range in modifications) {\n        Log.v(\"QUICKSTART\", \"Updated range: ${range.startIndex} to ${range.startIndex + range.length - 1}\")\n    }\n})\n\n```\n\n## Complete Example\nIf you're running this project in a fresh Android Studio project, you can\ncopy and paste this file into your application's `MainActivity` -- just\nremember to:\n\n- use a package declaration at the top of the file for your own project\n- update the `import` statements for `Task` and `TaskStatus` if\nyou're using java\n\n#### Java\n\n```java\nimport io.realm.RealmObject;\nimport io.realm.annotations.PrimaryKey;\nimport io.realm.annotations.Required;\n\npublic class Task extends RealmObject {\n    @PrimaryKey private String name;\n    @Required private String status = TaskStatus.Open.name();\n\n    public void setStatus(TaskStatus status) { this.status = status.name(); }\n    public String getStatus() { return this.status; }\n    public String getName() { return name; }\n    public void setName(String name) { this.name = name; }\n    public Task(String _name) { this.name = _name; }\n    public Task() {}\n}\n\n```\n\n```java\n\npublic enum TaskStatus {\n    Open(\"Open\"),\n    InProgress(\"In Progress\"),\n    Complete(\"Complete\");\n\n    String displayName;\n    TaskStatus(String displayName) {\n        this.displayName = displayName;\n    }\n}\n\n```\n\n```java\nimport io.realm.OrderedCollectionChangeSet;\n\nimport android.os.Bundle;\n\nimport androidx.appcompat.app.AppCompatActivity;\nimport android.util.Log;\n\nimport io.realm.OrderedRealmCollectionChangeListener;\n\nimport io.realm.Realm;\nimport io.realm.RealmConfiguration;\nimport io.realm.RealmResults;\n\nimport java.util.concurrent.ExecutionException;\nimport java.util.concurrent.ExecutorService;\nimport java.util.concurrent.Executors;\nimport java.util.concurrent.FutureTask;\n\nimport com.mongodb.realm.examples.model.java.Task;\nimport com.mongodb.realm.examples.model.java.TaskStatus;\n\npublic class MainActivity extends AppCompatActivity {\n    Realm uiThreadRealm;\n\n    @Override\n    protected void onCreate(Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n\n        Realm.init(this); // context, usually an Activity or Application\n\n        String realmName = \"My Project\";\n        RealmConfiguration config = new RealmConfiguration.Builder().name(realmName).build();\n\n        uiThreadRealm = Realm.getInstance(config);\n\n        addChangeListenerToRealm(uiThreadRealm);\n\n        FutureTask<String> Task = new FutureTask(new BackgroundQuickStart(), \"test\");\n        ExecutorService executorService = Executors.newFixedThreadPool(2);\n        executorService.execute(Task);\n\n    }\n\n    private void addChangeListenerToRealm(Realm realm) {\n        // all Tasks in the realm\n        RealmResults<Task> Tasks = uiThreadRealm.where(Task.class).findAllAsync();\n\n        Tasks.addChangeListener(new OrderedRealmCollectionChangeListener<RealmResults<Task>>() {\n            @Override\n            public void onChange(RealmResults<Task> collection, OrderedCollectionChangeSet changeSet) {\n                // process deletions in reverse order if maintaining parallel data structures so indices don't change as you iterate\n                OrderedCollectionChangeSet.Range[] deletions = changeSet.getDeletionRanges();\n                for (OrderedCollectionChangeSet.Range range : deletions) {\n                    Log.v(\"QUICKSTART\", \"Deleted range: \" + range.startIndex + \" to \" + (range.startIndex + range.length - 1));\n                }\n\n                OrderedCollectionChangeSet.Range[] insertions = changeSet.getInsertionRanges();\n                for (OrderedCollectionChangeSet.Range range : insertions) {\n                    Log.v(\"QUICKSTART\", \"Inserted range: \" + range.startIndex + \" to \" + (range.startIndex + range.length - 1));                            }\n\n                OrderedCollectionChangeSet.Range[] modifications = changeSet.getChangeRanges();\n                for (OrderedCollectionChangeSet.Range range : modifications) {\n                    Log.v(\"QUICKSTART\", \"Updated range: \" + range.startIndex + \" to \" + (range.startIndex + range.length - 1));                            }\n            }\n        });\n    }\n\n        @Override\n    protected void onDestroy() {\n        super.onDestroy();\n        // the ui thread realm uses asynchronous transactions, so we can only safely close the realm\n        // when the activity ends and we can safely assume that those transactions have completed\n        uiThreadRealm.close();\n    }\n\n    public class BackgroundQuickStart implements Runnable {\n\n        @Override\n        public void run() {\n            String realmName = \"My Project\";\n            RealmConfiguration config = new RealmConfiguration.Builder().name(realmName).build();\n\n            Realm backgroundThreadRealm = Realm.getInstance(config);\n\n            Task Task = new Task(\"New Task\");\n            backgroundThreadRealm.executeTransaction (transactionRealm -> {\n                transactionRealm.insert(Task);\n            });\n\n            // all Tasks in the realm\n            RealmResults<Task> Tasks = backgroundThreadRealm.where(Task.class).findAll();\n\n            // you can also filter a collection\n            RealmResults<Task> TasksThatBeginWithN = Tasks.where().beginsWith(\"name\", \"N\").findAll();\n            RealmResults<Task> openTasks = Tasks.where().equalTo(\"status\", TaskStatus.Open.name()).findAll();\n\n            Task otherTask = Tasks.get(0);\n\n            // all modifications to a realm must happen inside of a write block\n            backgroundThreadRealm.executeTransaction( transactionRealm -> {\n                Task innerOtherTask = transactionRealm.where(Task.class).equalTo(\"_id\", otherTask.getName()).findFirst();\n                innerOtherTask.setStatus(TaskStatus.Complete);\n            });\n\n            Task yetAnotherTask = Tasks.get(0);\n            String yetAnotherTaskName = yetAnotherTask.getName();\n            // all modifications to a realm must happen inside of a write block\n            backgroundThreadRealm.executeTransaction( transactionRealm -> {\n                Task innerYetAnotherTask = transactionRealm.where(Task.class).equalTo(\"_id\", yetAnotherTaskName).findFirst();\n                innerYetAnotherTask.deleteFromRealm();\n            });\n\n            // because this background thread uses synchronous realm transactions, at this point all\n            // transactions have completed and we can safely close the realm\n            backgroundThreadRealm.close();\n        }\n    }\n}\n\n```\n\n#### Kotlin\n\n```kotlin\n\nimport android.os.Bundle\nimport androidx.appcompat.app.AppCompatActivity\nimport android.util.Log\nimport io.realm.*\nimport io.realm.annotations.PrimaryKey\n\nimport io.realm.annotations.Required\nimport io.realm.kotlin.where\nimport java.util.concurrent.ExecutorService\nimport java.util.concurrent.Executors\nimport java.util.concurrent.FutureTask\n\nclass MainActivity : AppCompatActivity() {\n    lateinit var uiThreadRealm: Realm\n\n    override fun onCreate(savedInstanceState: Bundle?) {\n        super.onCreate(savedInstanceState)\n\n        Realm.init(this) // context, usually an Activity or Application\n\n        val realmName: String = \"My Project\"\n        val config = RealmConfiguration.Builder()\n            .name(realmName)\n            .build()\n\n        uiThreadRealm = Realm.getInstance(config)\n\n        addChangeListenerToRealm(uiThreadRealm)\n\n        val task : FutureTask<String> = FutureTask(BackgroundQuickStart(), \"test\")\n        val executorService: ExecutorService = Executors.newFixedThreadPool(2)\n        executorService.execute(task)\n\n    }\n\n    fun addChangeListenerToRealm(realm : Realm) {\n        // all tasks in the realm\n        val tasks : RealmResults<Task> = realm.where<Task>().findAllAsync()\n\n        tasks.addChangeListener(OrderedRealmCollectionChangeListener<RealmResults<Task>> { collection, changeSet ->\n            // process deletions in reverse order if maintaining parallel data structures so indices don't change as you iterate\n            val deletions = changeSet.deletionRanges\n            for (i in deletions.indices.reversed()) {\n                val range = deletions[i]\n                Log.v(\"QUICKSTART\", \"Deleted range: ${range.startIndex} to ${range.startIndex + range.length - 1}\")\n            }\n\n            val insertions = changeSet.insertionRanges\n            for (range in insertions) {\n                Log.v(\"QUICKSTART\", \"Inserted range: ${range.startIndex} to ${range.startIndex + range.length - 1}\")\n            }\n\n            val modifications = changeSet.changeRanges\n            for (range in modifications) {\n                Log.v(\"QUICKSTART\", \"Updated range: ${range.startIndex} to ${range.startIndex + range.length - 1}\")\n            }\n        })\n    }\n\n    override fun onDestroy() {\n        super.onDestroy()\n        // the ui thread realm uses asynchronous transactions, so we can only safely close the realm\n        // when the activity ends and we can safely assume that those transactions have completed\n        uiThreadRealm.close()\n    }\n\n    class BackgroundQuickStart : Runnable {\n\n        override fun run() {\n            val realmName: String = \"My Project\"\n            val config = RealmConfiguration.Builder().name(realmName).build()\n\n            val backgroundThreadRealm : Realm = Realm.getInstance(config)\n\n            val task : Task = Task()\n            task.name = \"New Task\"\n            backgroundThreadRealm.executeTransaction { transactionRealm ->\n                transactionRealm.insert(task)\n            }\n\n            // all tasks in the realm\n            val tasks : RealmResults<Task> = backgroundThreadRealm.where<Task>().findAll()\n\n            // you can also filter a collection\n            val tasksThatBeginWithN : List<Task> = tasks.where().beginsWith(\"name\", \"N\").findAll()\n            val openTasks : List<Task> = tasks.where().equalTo(\"status\", TaskStatus.Open.name).findAll()\n\n            val otherTask: Task = tasks[0]!!\n\n            // all modifications to a realm must happen inside of a write block\n            backgroundThreadRealm.executeTransaction { transactionRealm ->\n                val innerOtherTask : Task = transactionRealm.where<Task>().equalTo(\"name\", otherTask.name).findFirst()!!\n                innerOtherTask.status = TaskStatus.Complete.name\n            }\n\n            val yetAnotherTask: Task = tasks.get(0)!!\n            val yetAnotherTaskName: String = yetAnotherTask.name\n            // all modifications to a realm must happen inside of a write block\n            backgroundThreadRealm.executeTransaction { transactionRealm ->\n                val innerYetAnotherTask : Task = transactionRealm.where<Task>().equalTo(\"name\", yetAnotherTaskName).findFirst()!!\n                innerYetAnotherTask.deleteFromRealm()\n            }\n\n            // because this background thread uses synchronous realm transactions, at this point all\n            // transactions have completed and we can safely close the realm\n            backgroundThreadRealm.close()\n        }\n\n    }\n}\n\nenum class TaskStatus(val displayName: String) {\n    Open(\"Open\"),\n    InProgress(\"In Progress\"),\n    Complete(\"Complete\"),\n}\n\nopen class Task() : RealmObject() {\n    @PrimaryKey\n    var name: String = \"task\"\n\n    @Required\n    var status: String = TaskStatus.Open.name\n    var statusEnum: TaskStatus\n        get() {\n            // because status is actually a String and another client could assign an invalid value,\n            // default the status to \"Open\" if the status is unreadable\n            return try {\n                TaskStatus.valueOf(status)\n            } catch (e: IllegalArgumentException) {\n                TaskStatus.Open\n            }\n        }\n        set(value) { status = value.name }\n}\n\n```\n\n## Output\nRunning the above code should produce output resembling the following:\n\n```shell\nSuccessfully authenticated anonymously.\n\nUpdated range: 0 to 1\n\nDeleted range: 0 to 1\n\nSuccessfully logged out.\n```\n"
  },
  {
    "path": "docs/guides/react-to-changes.md",
    "content": "# React to Changes - Java SDK\nObjects in Realm clients are **live objects** that\nupdate automatically to reflect data changes and emit\nnotification events that you\ncan subscribe to whenever their underlying data changes.\n\nAny modern app should be able to react when data changes,\nregardless of where that change originated. When a user adds\na new item to a list, you may want to update the UI, show a\nnotification, or log a message. When someone updates that\nitem, you may want to change its visual state or fire off a\nnetwork request. Finally, when someone deletes the item, you\nprobably want to remove it from the UI. Realm's notification\nsystem allows you to watch for and react to changes in your\ndata, independent of the writes that caused the changes.\n\nRealm emits three kinds of notifications:\n\n- Realm notifications whenever a specific realm commits a write transaction.\n- Collection notifications whenever any Realm object in a collection changes, including inserts, updates, and deletes.\n- Object notifications whenever a specific Realm object changes, including updates and deletes.\n\n## Auto-Refresh\nRealm objects accessed on a thread associated with a\n[Looper](https://developer.android.com/reference/android/os/Looper.html) automatically\nupdate periodically to reflect changes to underlying data.\n\nThe Android UI thread always contains a `Looper` instance. If you need\nto keep Realm objects around for long periods of time on\nany other thread, you should configure a `Looper` for that thread.\n\n> Warning:\n> Realms on a thread without a [Looper](https://developer.android.com/reference/android/os/Looper)\ndo not automatically advance their version. This can increase the size of the\nrealm in memory and on disk. Avoid using realm instances on\nnon-Looper threads when possible. If you *do* open a realm on a non-Looper\nthread, close the realm when you're done using it.\n>\n\n## Register a Realm Change Listener\nYou can register a notification handler on an entire realm.\nRealm calls the notification handler whenever any write\ntransaction involving that realm is committed. The\nhandler receives no information about the change.\n\nThis is useful when you want to know that there has been a\nchange but do not care to know specifically what changed.\nFor example, proof of concept apps often use this\nnotification type and simply refresh the entire UI when\nanything changes. As the app becomes more sophisticated and\nperformance-sensitive, the app developers shift to more\ngranular notifications.\n\n> Example:\n> Suppose you are writing a real-time collaborative app. To\ngive the sense that your app is buzzing with collaborative\nactivity, you want to have an indicator that lights up when\nany change is made. In that case, a realm notification\nhandler would be a great way to drive the code that controls\nthe indicator. The following code shows how to observe a realm\nfor changes with with `addChangeListener()`:\n>\n> #### Java\n>\n> ```java\n> public class MyActivity extends Activity {\n>     private Realm realm;\n>     private RealmChangeListener realmListener;\n>\n>     @Override\n>     protected void onCreate(Bundle savedInstanceState) {\n>         super.onCreate(savedInstanceState);\n>         realm = Realm.getDefaultInstance();\n>         realmListener = new RealmChangeListener<Realm>() {\n>             @Override\n>             public void onChange(Realm realm) {\n>               // ... do something with the updates (UI, etc.) ...\n>             }\n>           };\n>         // Observe realm notifications.\n>         realm.addChangeListener(realmListener);\n>     }\n>\n>     @Override\n>     protected void onDestroy() {\n>         super.onDestroy();\n>         // Remove the listener.\n>         realm.removeChangeListener(realmListener);\n>         // Close the Realm instance.\n>         realm.close();\n>     }\n> }\n>\n> ```\n>\n>\n> #### Kotlin\n>\n> ```kotlin\n> class MyActivity : Activity() {\n>     private lateinit var realm: Realm\n>     private lateinit var realmListener: RealmChangeListener<Realm>\n>\n>     override fun onCreate(savedInstanceState: Bundle?) {\n>         super.onCreate(savedInstanceState)\n>         realm = Realm.getDefaultInstance()\n>         realmListener = RealmChangeListener {\n>             // ... do something with the updates (UI, etc.) ...\n>         }\n>         // Observe realm notifications.\n>         realm.addChangeListener(realmListener)\n>     }\n>\n>     override fun onDestroy() {\n>         super.onDestroy()\n>         // Remove the listener.\n>         realm.removeChangeListener(realmListener)\n>         // Close the Realm instance.\n>         realm.close()\n>     }\n> }\n>\n> ```\n>\n>\n\n> Important:\n> All threads that contain a `Looper` automatically refresh\n`RealmObject` and `RealmResult` instances when new changes are\nwritten to the realm. As a result, it isn't necessary to fetch\nthose objects again when reacting to a `RealmChangeListener`, since\nthose objects are already updated and ready to be redrawn to the\nscreen.\n>\n\n## Register a Collection Change Listener\nYou can register a notification handler on a specific\ncollection within a realm. The handler receives a\ndescription of changes since the last notification.\nSpecifically, this description consists of three lists of\nindices:\n\n- The indices of the objects that were deleted.\n- The indices of the objects that were inserted.\n- The indices of the objects that were modified.\n\nStop notification delivery by calling the `removeChangeListener()` or\n`removeAllChangeListeners()` methods. Notifications also stop if:\n\n- the object on which the listener is registered gets garbage collected.\n- the realm instance closes.\n\nKeep a strong reference to the object you're listening to\nfor as long as you need the notifications.\n\n> Important:\n> In collection notification handlers, always apply changes\nin the following order: deletions, insertions, then\nmodifications. Handling insertions before deletions may\nresult in unexpected behavior.\n>\n\nRealm emits an initial notification after retrieving the\ncollection. After that, Realm delivers collection\nnotifications asynchronously whenever a write transaction\nadds, changes, or removes objects in the collection.\n\nUnlike realm notifications, collection notifications contain\ndetailed information about the change. This enables\nsophisticated and selective reactions to changes. Collection\nnotifications provide all the information needed to manage a\nlist or other view that represents the collection in the UI.\n\nThe following code shows how to observe a collection for\nchanges with `addChangeListener()`:\n\n#### Java\n\n```java\nRealmResults<Dog> dogs = realm.where(Dog.class).findAll();\n// Set up the collection notification handler.\nOrderedRealmCollectionChangeListener<RealmResults<Dog>> changeListener = (collection, changeSet) -> {\n    // For deletions, notify the UI in reverse order if removing elements the UI\n    OrderedCollectionChangeSet.Range[] deletions = changeSet.getDeletionRanges();\n    for (int i = deletions.length - 1; i >= 0; i--) {\n        OrderedCollectionChangeSet.Range range = deletions[i];\n        Log.v(\"EXAMPLE\", range.length + \" dogs deleted at \" + range.startIndex);\n    }\n    OrderedCollectionChangeSet.Range[] insertions = changeSet.getInsertionRanges();\n    for (OrderedCollectionChangeSet.Range range : insertions) {\n        Log.v(\"EXAMPLE\", range.length + \" dogs inserted at \" + range.startIndex);\n    }\n    OrderedCollectionChangeSet.Range[] modifications = changeSet.getChangeRanges();\n    for (OrderedCollectionChangeSet.Range range : modifications) {\n        Log.v(\"EXAMPLE\", range.length + \" dogs modified at \" + range.startIndex);\n    }\n};\n// Observe collection notifications.\ndogs.addChangeListener(changeListener);\n\n```\n\n#### Kotlin\n\n```kotlin\nval dogs = realm.where(Dog::class.java).findAll()\n// Set up the collection notification handler.\nval changeListener =\n    OrderedRealmCollectionChangeListener { collection: RealmResults<Dog>?, changeSet: OrderedCollectionChangeSet ->\n        // For deletions, notify the UI in reverse order if removing elements the UI\n        val deletions = changeSet.deletionRanges\n        for (i in deletions.indices.reversed()) {\n            val range = deletions[i]\n            Log.v(\"EXAMPLE\", \"${range.length} dogs deleted at ${range.startIndex}\")\n        }\n        val insertions = changeSet.insertionRanges\n        for (range in insertions) {\n            Log.v(\"EXAMPLE\", \"${range.length} dogs inserted at ${range.startIndex}\")\n        }\n        val modifications = changeSet.changeRanges\n        for (range in modifications) {\n            Log.v(\"EXAMPLE\", \"${range.length} dogs modified at ${range.startIndex}\")\n        }\n    }\n// Observe collection notifications.\ndogs.addChangeListener(changeListener)\n\n```\n\n## Register an Object Change Listener\nYou can register a notification handler on a specific object\nwithin a realm. Realm notifies your handler:\n\n- When the object is deleted.\n- When any of the object's properties change.\n\nThe handler receives information about what fields changed\nand whether the object was deleted.\n\nStop notification delivery by calling the `removeChangeListener()` or\n`removeAllChangeListeners()` methods. Notifications also stop if:\n\n- the object on which the listener is registered gets garbage collected.\n- the realm instance closes.\n\nKeep a strong reference of the object you're listening to\nfor as long as you need the notifications.\n\nThe following code shows how create a new instance of a class\nin a realm and observe that instance for changes with\n`addChangeListener()`:\n\n#### Java\n\n```java\n// Create a dog in the realm.\nAtomicReference<Dog> dog = new AtomicReference<Dog>();\nrealm.executeTransaction(transactionRealm -> {\n    dog.set(transactionRealm.createObject(Dog.class, new ObjectId()));\n    dog.get().setName(\"Max\");\n});\n\n// Set up the listener.\nRealmObjectChangeListener<Dog> listener = (changedDog, changeSet) -> {\n    if (changeSet.isDeleted()) {\n        Log.i(\"EXAMPLE\", \"The dog was deleted\");\n        return;\n    }\n    for (String fieldName : changeSet.getChangedFields()) {\n        Log.i(\"EXAMPLE\", \"Field '\" + fieldName + \"' changed.\");\n    }\n};\n\n// Observe object notifications.\ndog.get().addChangeListener(listener);\n\n// Update the dog to see the effect.\nrealm.executeTransaction(r -> {\n    dog.get().setName(\"Wolfie\"); // -> \"Field 'name' was changed.\"\n});\n\n```\n\n#### Kotlin\n\n```kotlin\n// Create a dog in the realm.\nvar dog = Dog()\nrealm.executeTransaction { transactionRealm ->\n    dog = transactionRealm.createObject(Dog::class.java, ObjectId())\n    dog.name = \"Max\"\n}\n\n// Set up the listener.\nval listener = RealmObjectChangeListener { changedDog: Dog?, changeSet: ObjectChangeSet? ->\n    if (changeSet!!.isDeleted) {\n        Log.i(\"EXAMPLE\", \"The dog was deleted\")\n    } else {\n        for (fieldName in changeSet.changedFields) {\n            Log.i(\n                \"EXAMPLE\",\n                \"Field '$fieldName' changed.\"\n            )\n        }\n    }\n}\n\n// Observe object notifications.\ndog.addChangeListener(listener)\n\n// Update the dog to see the effect.\nrealm.executeTransaction { r: Realm? ->\n    dog.name = \"Wolfie\" // -> \"Field 'name' was changed.\"\n}\n\n```\n\n## Unregister a Change Listener\nYou can unregister a change listener by passing your change listener to\n`Realm.removeChangeListener()`.\nYou can unregister all change listeners currently subscribed to changes\nin a realm or any of its linked objects or collections with\n`Realm.removeAllChangeListeners()`.\n\n## Use Realm in System Apps on Custom ROMs\nRealm uses named pipes in order to support notifications and\naccess to the realm file from multiple processes. While this is\nallowed by default for normal user apps, it is disallowed for system\napps.\n\nYou can define a system apps by setting\n`android:sharedUserId=\"android.uid.system\"` in the Android manifest.\nWhen working with a system app, you may see a security violation in\nLogcat that looks something like this:\n\n```\n05-24 14:08:08.984  6921  6921 W .realmsystemapp: type=1400 audit(0.0:99): avc: denied { write } for name=\"realm.testapp.com.realmsystemapp-Bfqpnjj4mUvxWtfMcOXBCA==\" dev=\"vdc\" ino=14660 scontext=u:r:system_app:s0 tcontext=u:object_r:apk_data_file:s0 tclass=dir permissive=0\n05-24 14:08:08.984  6921  6921 W .realmsystemapp: type=1400 audit(0.0:100): avc: denied { write } for name=\"realm.testapp.com.realmsystemapp-Bfqpnjj4mUvxWtfMcOXBCA==\" dev=\"vdc\" ino=14660 scontext=u:r:system_app:s0 tcontext=u:object_r:apk_data_file:s0 tclass=dir permissive=0\n```\n\nIn order to fix this you need to adjust the SELinux security rules in\nthe ROM. This can be done by using the tool `audit2allow`, which ships\nas part of AOSP:\n\n1. Pull the current policy from the device: `adb pull /sys/fs/selinux/policy`\n2. Copy the SELinux error inside a text file called input.txt.\n3. Run the `audit2allow` tool: `audit2allow -p policy -i input.txt`\n4. The tool should output a rule you can add to your existing policy\nto enable the use of Realm.\n\nAn example of such a policy is provided below:\n\n```\n# Allow system_app to create named pipes required by Realm\n# Credit: https://github.com/mikalackis/platform_vendor_ariel/blob/master_oreo/sepolicy/system_app.te\nallow system_app fuse:fifo_file create;\nallow system_app system_app_data_file:fifo_file create;\nallow system_app system_app_data_file:fifo_file { read write };\nallow system_app system_app_data_file:fifo_file open;\n```\n\n> Seealso:\n> `audit2allow` is produced when compiling AOSP/ROM and only runs on\nLinux. You can read more about it [here](https://source.android.com/security/selinux/validate#using_audit2allow).\n>\n\n> Note:\n> Since Android Oreo, Google changed the way it configures SELinux.\nThe default security policies are now much more modularized.\nRead more about that\n[here](https://source.android.com/security/selinux/images/SELinux_Treble.pdf).\n>\n\n## Change Notification Limits\nChanges in nested documents deeper than four levels down do not trigger\nchange notifications.\n\nIf you have a data structure where you need to listen for changes five\nlevels down or deeper, workarounds include:\n\n- Refactor the schema to reduce nesting.\n- Add something like \"push-to-refresh\" to enable users to manually refresh data.\n"
  },
  {
    "path": "docs/guides/realm-files/bundle-a-realm.md",
    "content": "# Bundle a Realm File - Java SDK\nRealm supports **bundling** realm files. When you bundle\na realm file, you include a database and all of its data in your\napplication download.\n\nThis allows users to start applications for the first time with a set of\ninitial data.\n\n## Overview\nTo create and bundle a realm file with your application:\n\n1. Create a realm file that\ncontains the data you'd like to bundle.\n2. Bundle the realm file in the\n/<app name>/src/main/assets folder of your production\napplication.\n3. In your production application,\nopen the realm from the bundled asset file.\n\n## Create a Realm File for Bundling\n1. Build a temporary realm app that shares the data model of your\napplication.\n2. Open a realm and add the data you wish to bundle.\n3. Use the `writeCopyTo()`\nmethod to copy the realm to a new file.\n\n`writeCopyTo()` automatically compacts your realm to the smallest\npossible size before copying.\n\n## Bundle a Realm File in Your Production Application\nNow that you have a copy of the realm that contains the initial data,\nbundle it with your production application.\n\n1. Search your application logs to find the location of the realm file\ncopy you just created.\n2. Using the \"Device File Explorer\" widget in the bottom right of your\nAndroid Studio window, navigate to the file.\n3. Right click on the file and select \"Save As\". Navigate to the\n/<app name>/src/main/assets folder of your production application.\nSave a copy of the realm file there.\n\n> Tip:\n> If your application does not already contain an asset folder, you can\ncreate one by right clicking on your top-level application\nfolder (<app name>) in Android Studio and selecting\nNew > Folder > Assets Folder in the menu.\n>\n\n## Open a Realm from a Bundled Realm File\nNow that you have a copy of the realm included with your production\napplication, you need to add code to use it. Use the `assetFile()`\nmethod when configuring your realm to open the realm\nfrom the bundled file.\n"
  },
  {
    "path": "docs/guides/realm-files/encryption.md",
    "content": "# Encrypt a Realm - Java SDK\n## Overview\nYou can encrypt your realms to ensure that the data stored to disk can't be\nread outside of your application. You encrypt the realm file on disk with AES-256 +\nSHA-2 by supplying a 64-byte encryption key when opening a\nrealm.\n\nRealm transparently encrypts and decrypts data with standard\n[AES-256 encryption](https://en.wikipedia.org/wiki/Advanced_Encryption_Standard) using the\nfirst 256 bits of the given 512-bit encryption key. Realm\nuses the other 256 bits of the 512-bit encryption key to validate\nintegrity using a [hash-based message authentication code\n(HMAC)](https://en.wikipedia.org/wiki/HMAC).\n\n> Warning:\n> Do not use cryptographically-weak hashes for realm encryption keys.\nFor optimal security, we recommend generating random rather than derived\nencryption keys.\n>\n\n## Considerations\nThe following are key impacts to consider when encrypting a realm.\n\n### Storing & Reusing Keys\nYou **must** pass the same encryption key to `RealmConfiguration.Builder.encryptionKey()` each\ntime you open the realm.\nIf you don't provide a key or specify the wrong key for an encrypted\nrealm, the Realm SDK throws an error.\n\nApps should store the encryption key in the\n[Android KeyStore](https://developer.android.com/training/articles/keystore.html) so\nthat other apps cannot read the key.\n\n### Performance Impact\nReads and writes on encrypted realms can be up to 10% slower than unencrypted realms.\n\n### Accessing an Encrypted Realm from Multiple Processes\n> Version changed: 10.14.0\n\nStarting with Realm Java SDK version 10.14.0, Realm supports opening\nthe same encrypted realm in multiple processes.\n\nIf your app uses Realm Java SDK version 10.14.0 or earlier, attempting to\nopen an encrypted realm from multiple processes throws this error:\n`Encrypted interprocess sharing is currently unsupported.`\n\n## Example\nThe following steps describe the recommended way to use the\n[Android KeyStore](https://developer.android.com/training/articles/keystore.html) for encryption with\nRealm:\n\n1. Generate an asymmetric RSA key that Android can securely store and\nretrieve using the Android KeyStore. Versions M and above require user PIN or fingerprint to unlock\nthe KeyStore.\n2. Generate a symmetric key (AES) you can use to encrypt the realm.\n3. Encrypt the symmetric AES key using your private RSA key.\n4. Store the encrypted AES key on filesystem (in a\n`SharedPreferences`, for example).\n\nWhen you need to use your encrypted realm:\n\n1. Retrieve your encrypted AES key.\n2. Decrypt your encrypted AES key using the public RSA key.\n3. Use the decrypted AES key in the `RealmConfiguration` to open the\nencrypted realm.\n\n> Seealso:\n> For an end-to-end example of storing and reusing encryption keys, see\nthe [store_password](https://github.com/realm/realm-java/tree/feature/example/store_password/examples/StoreEncryptionPassword) example project, which demonstrates the\nfingerprint API.\n>\n\n### Generate and Store an Encryption Key\nThe following code demonstrates how to securely generate and store an\nencryption key for a realm:\n\n#### Java\n\n```java\n// Create a key to encrypt a realm and save it securely in the keystore\npublic byte[] getNewKey() {\n    // open a connection to the android keystore\n    KeyStore keyStore;\n    try {\n        keyStore = KeyStore.getInstance(\"AndroidKeyStore\");\n        keyStore.load(null);\n    } catch (KeyStoreException | NoSuchAlgorithmException\n            | CertificateException | IOException e) {\n        Log.v(\"EXAMPLE\", \"Failed to open the keystore.\");\n        throw new RuntimeException(e);\n    }\n\n    // create a securely generated random asymmetric RSA key\n    byte[] realmKey = new byte[Realm.ENCRYPTION_KEY_LENGTH];\n    new SecureRandom().nextBytes(realmKey);\n\n    // create a cipher that uses AES encryption -- we'll use this to encrypt our key\n    Cipher cipher;\n    try {\n        cipher = Cipher.getInstance(KeyProperties.KEY_ALGORITHM_AES\n                + \"/\" + KeyProperties.BLOCK_MODE_CBC\n                + \"/\" + KeyProperties.ENCRYPTION_PADDING_PKCS7);\n    } catch (NoSuchAlgorithmException | NoSuchPaddingException e) {\n        Log.e(\"EXAMPLE\", \"Failed to create a cipher.\");\n        throw new RuntimeException(e);\n    }\n\n    // generate secret key\n    KeyGenerator keyGenerator;\n    try {\n        keyGenerator = KeyGenerator.getInstance(\n                KeyProperties.KEY_ALGORITHM_AES,\n                \"AndroidKeyStore\");\n    } catch (NoSuchAlgorithmException | NoSuchProviderException e) {\n        Log.e(\"EXAMPLE\", \"Failed to access the key generator.\");\n        throw new RuntimeException(e);\n    }\n    KeyGenParameterSpec keySpec = new KeyGenParameterSpec.Builder(\n            \"realm_key\",\n            KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)\n            .setBlockModes(KeyProperties.BLOCK_MODE_CBC)\n            .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_PKCS7)\n            .setUserAuthenticationRequired(true)\n            .setUserAuthenticationValidityDurationSeconds(\n                   AUTH_VALID_DURATION_IN_SECOND)\n            .build();\n    try {\n        keyGenerator.init(keySpec);\n    } catch (InvalidAlgorithmParameterException e) {\n        Log.e(\"EXAMPLE\", \"Failed to generate a secret key.\");\n        throw new RuntimeException(e);\n    }\n    keyGenerator.generateKey();\n\n    // access the generated key in the android keystore, then\n    // use the cipher to create an encrypted version of the key\n    byte[] initializationVector;\n    byte[] encryptedKeyForRealm;\n    try {\n        SecretKey secretKey =\n                (SecretKey) keyStore.getKey(\"realm_key\", null);\n        cipher.init(Cipher.ENCRYPT_MODE, secretKey);\n        encryptedKeyForRealm = cipher.doFinal(realmKey);\n        initializationVector = cipher.getIV();\n    } catch (InvalidKeyException | UnrecoverableKeyException\n            | NoSuchAlgorithmException | KeyStoreException\n            | BadPaddingException | IllegalBlockSizeException e) {\n        Log.e(\"EXAMPLE\", \"Failed encrypting the key with the secret key.\");\n        throw new RuntimeException(e);\n    }\n\n    // keep the encrypted key in shared preferences\n    // to persist it across application runs\n    byte[] initializationVectorAndEncryptedKey =\n            new byte[Integer.BYTES +\n                    initializationVector.length +\n                    encryptedKeyForRealm.length];\n    ByteBuffer buffer = ByteBuffer.wrap(initializationVectorAndEncryptedKey);\n    buffer.order(ByteOrder.BIG_ENDIAN);\n    buffer.putInt(initializationVector.length);\n    buffer.put(initializationVector);\n    buffer.put(encryptedKeyForRealm);\n    activity.getSharedPreferences(\"realm_key\", Context.MODE_PRIVATE).edit()\n            .putString(\"iv_and_encrypted_key\",\n                    Base64.encodeToString(initializationVectorAndEncryptedKey, Base64.NO_WRAP))\n            .apply();\n\n    return realmKey; // pass to a realm configuration via encryptionKey()\n}\n\n```\n\n#### Kotlin\n\n```kotlin\n// Create a key to encrypt a realm and save it securely in the keystore\nfun getNewKey(): ByteArray {\n    // open a connection to the android keystore\n    val keyStore: KeyStore\n    try {\n        keyStore = KeyStore.getInstance(\"AndroidKeyStore\")\n        keyStore.load(null)\n    } catch (e: Exception) {\n        Log.v(\"EXAMPLE\", \"Failed to open the keystore.\")\n        throw RuntimeException(e)\n    }\n\n    // create a securely generated random asymmetric RSA key\n    val realmKey = ByteArray(Realm.ENCRYPTION_KEY_LENGTH)\n    SecureRandom().nextBytes(realmKey)\n\n    // create a cipher that uses AES encryption -- we'll use this to encrypt our key\n    val cipher: Cipher\n    cipher = try {\n        Cipher.getInstance(KeyProperties.KEY_ALGORITHM_AES\n                + \"/\" + KeyProperties.BLOCK_MODE_CBC\n                + \"/\" + KeyProperties.ENCRYPTION_PADDING_PKCS7)\n    } catch (e: Exception) {\n        Log.e(\"EXAMPLE\", \"Failed to create a cipher.\")\n        throw RuntimeException(e)\n    }\n\n    // generate secret key\n    val keyGenerator: KeyGenerator\n    keyGenerator = try {\n        KeyGenerator.getInstance(\n                KeyProperties.KEY_ALGORITHM_AES,\n                \"AndroidKeyStore\")\n    } catch (e: NoSuchAlgorithmException) {\n        Log.e(\"EXAMPLE\", \"Failed to access the key generator.\")\n        throw RuntimeException(e)\n    }\n    val keySpec = KeyGenParameterSpec.Builder(\n            \"realm_key\",\n            KeyProperties.PURPOSE_ENCRYPT or KeyProperties.PURPOSE_DECRYPT)\n            .setBlockModes(KeyProperties.BLOCK_MODE_CBC)\n            .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_PKCS7)\n            .setUserAuthenticationRequired(true)\n            .setUserAuthenticationValidityDurationSeconds(\n                   AUTH_VALID_DURATION_IN_SECOND)\n            .build()\n    try {\n        keyGenerator.init(keySpec)\n    } catch (e: InvalidAlgorithmParameterException) {\n        Log.e(\"EXAMPLE\", \"Failed to generate a secret key.\")\n        throw RuntimeException(e)\n    }\n    keyGenerator.generateKey()\n\n    // access the generated key in the android keystore, then\n    // use the cipher to create an encrypted version of the key\n    val initializationVector: ByteArray\n    val encryptedKeyForRealm: ByteArray\n    try {\n        val secretKey = keyStore.getKey(\"realm_key\", null) as SecretKey\n        cipher.init(Cipher.ENCRYPT_MODE, secretKey)\n        encryptedKeyForRealm = cipher.doFinal(realmKey)\n        initializationVector = cipher.iv\n    } catch (e: Exception) {\n        Log.e(\"EXAMPLE\", \"Failed encrypting the key with the secret key.\")\n        throw RuntimeException(e)\n    }\n\n    // keep the encrypted key in shared preferences\n    // to persist it across application runs\n    val initializationVectorAndEncryptedKey = ByteArray(Integer.BYTES +\n            initializationVector.size +\n            encryptedKeyForRealm.size)\n    val buffer = ByteBuffer.wrap(initializationVectorAndEncryptedKey)\n    buffer.order(ByteOrder.BIG_ENDIAN)\n    buffer.putInt(initializationVector.size)\n    buffer.put(initializationVector)\n    buffer.put(encryptedKeyForRealm)\n    activity!!.getSharedPreferences(\"realm_key\", Context.MODE_PRIVATE).edit()\n            .putString(\"iv_and_encrypted_key\",\n                    Base64.encodeToString(initializationVectorAndEncryptedKey, Base64.NO_WRAP))\n            .apply()\n    return realmKey // pass to a realm configuration via encryptionKey()\n}\n\n```\n\n### Access an Existing Encryption Key\nThe following code demonstrates how to access and decrypt a securely\nstored encryption key for a realm:\n\n#### Java\n\n```java\n// Access the encrypted key in the keystore, decrypt it with the secret,\n// and use it to open and read from the realm again\npublic byte[] getExistingKey() {\n    // open a connection to the android keystore\n    KeyStore keyStore;\n    try {\n        keyStore = KeyStore.getInstance(\"AndroidKeyStore\");\n        keyStore.load(null);\n    } catch (KeyStoreException | NoSuchAlgorithmException\n            | CertificateException | IOException e) {\n        Log.e(\"EXAMPLE\", \"Failed to open the keystore.\");\n        throw new RuntimeException(e);\n    }\n\n    // access the encrypted key that's stored in shared preferences\n    byte[] initializationVectorAndEncryptedKey = Base64.decode(activity\n            .getSharedPreferences(\"realm_key\", Context.MODE_PRIVATE)\n            .getString(\"iv_and_encrypted_key\", null), Base64.DEFAULT);\n    ByteBuffer buffer = ByteBuffer.wrap(initializationVectorAndEncryptedKey);\n    buffer.order(ByteOrder.BIG_ENDIAN);\n\n    // extract the length of the initialization vector from the buffer\n    int initializationVectorLength = buffer.getInt();\n    // extract the initialization vector based on that length\n    byte[] initializationVector = new byte[initializationVectorLength];\n    buffer.get(initializationVector);\n    // extract the encrypted key\n    byte[] encryptedKey = new byte[initializationVectorAndEncryptedKey.length\n            - Integer.BYTES\n            - initializationVectorLength];\n    buffer.get(encryptedKey);\n\n    // create a cipher that uses AES encryption to decrypt our key\n    Cipher cipher;\n    try {\n        cipher = Cipher.getInstance(KeyProperties.KEY_ALGORITHM_AES\n                + \"/\" + KeyProperties.BLOCK_MODE_CBC\n                + \"/\" + KeyProperties.ENCRYPTION_PADDING_PKCS7);\n    } catch (NoSuchAlgorithmException | NoSuchPaddingException e) {\n        Log.e(\"EXAMPLE\", \"Failed to create cipher.\");\n        throw new RuntimeException(e);\n    }\n\n    // decrypt the encrypted key with the secret key stored in the keystore\n    byte[] decryptedKey;\n    try {\n        final SecretKey secretKey =\n                (SecretKey) keyStore.getKey(\"realm_key\", null);\n        final IvParameterSpec initializationVectorSpec =\n                new IvParameterSpec(initializationVector);\n        cipher.init(Cipher.DECRYPT_MODE, secretKey, initializationVectorSpec);\n        decryptedKey = cipher.doFinal(encryptedKey);\n    } catch (InvalidKeyException e) {\n        Log.e(\"EXAMPLE\", \"Failed to decrypt. Invalid key.\");\n        throw new RuntimeException(e);\n    } catch (UnrecoverableKeyException | NoSuchAlgorithmException\n            | BadPaddingException | KeyStoreException\n            | IllegalBlockSizeException | InvalidAlgorithmParameterException e) {\n        Log.e(\"EXAMPLE\",\n                \"Failed to decrypt the encrypted realm key with the secret key.\");\n        throw new RuntimeException(e);\n    }\n    return decryptedKey; // pass to a realm configuration via encryptionKey()\n}\n\n```\n\n#### Kotlin\n\n```kotlin\n// Access the encrypted key in the keystore, decrypt it with the secret,\n// and use it to open and read from the realm again\nfun getExistingKey(): ByteArray {\n    // open a connection to the android keystore\n    val keyStore: KeyStore\n    try {\n        keyStore = KeyStore.getInstance(\"AndroidKeyStore\")\n        keyStore.load(null)\n    } catch (e: Exception) {\n        Log.e(\"EXAMPLE\", \"Failed to open the keystore.\")\n        throw RuntimeException(e)\n    }\n\n    // access the encrypted key that's stored in shared preferences\n    val initializationVectorAndEncryptedKey = Base64.decode(activity\n            ?.getSharedPreferences(\"realm_key\", Context.MODE_PRIVATE)\n            ?.getString(\"iv_and_encrypted_key\", null), Base64.DEFAULT)\n    val buffer = ByteBuffer.wrap(initializationVectorAndEncryptedKey)\n    buffer.order(ByteOrder.BIG_ENDIAN)\n\n    // extract the length of the initialization vector from the buffer\n    val initializationVectorLength = buffer.int\n    // extract the initialization vector based on that length\n    val initializationVector = ByteArray(initializationVectorLength)\n    buffer[initializationVector]\n    // extract the encrypted key\n    val encryptedKey = ByteArray(initializationVectorAndEncryptedKey.size\n            - Integer.BYTES\n            - initializationVectorLength)\n    buffer[encryptedKey]\n\n    // create a cipher that uses AES encryption to decrypt our key\n    val cipher: Cipher\n    cipher = try {\n        Cipher.getInstance(KeyProperties.KEY_ALGORITHM_AES\n                + \"/\" + KeyProperties.BLOCK_MODE_CBC\n                + \"/\" + KeyProperties.ENCRYPTION_PADDING_PKCS7)\n    } catch (e: Exception) {\n        Log.e(\"EXAMPLE\", \"Failed to create cipher.\")\n        throw RuntimeException(e)\n    }\n\n    // decrypt the encrypted key with the secret key stored in the keystore\n    val decryptedKey: ByteArray\n    decryptedKey = try {\n        val secretKey = keyStore.getKey(\"realm_key\", null) as SecretKey\n        val initializationVectorSpec = IvParameterSpec(initializationVector)\n        cipher.init(Cipher.DECRYPT_MODE, secretKey, initializationVectorSpec)\n        cipher.doFinal(encryptedKey)\n    } catch (e: InvalidKeyException) {\n        Log.e(\"EXAMPLE\", \"Failed to decrypt. Invalid key.\")\n        throw RuntimeException(e)\n    } catch (e: Exception ) {\n                Log.e(\"EXAMPLE\",\n                        \"Failed to decrypt the encrypted realm key with the secret key.\")\n                throw RuntimeException(e)\n    }\n    return decryptedKey // pass to a realm configuration via encryptionKey()\n}\n\n```\n"
  },
  {
    "path": "docs/guides/realm-files/open-and-close-a-realm.md",
    "content": "# Open & Close a Realm - Java SDK\nInteracting with realms in an Android\napplication uses the following high-level series of steps:\n\n1. Create a configuration for the realm you want to open.\n2. Open the realm using the config.\n3. Close the realm to free up resources when you're finished.\n\n## The Default Realm\nYou can save any `RealmConfiguration`\nas the default for your application using the\n`setDefaultConfiguration()`\nmethod:\n\n#### Java\n\n```java\nRealmConfiguration config = new RealmConfiguration.Builder()\n        .name(\"default-realm\")\n        .allowQueriesOnUiThread(true)\n        .allowWritesOnUiThread(true)\n        .compactOnLaunch()\n        .inMemory()\n        .build();\n// set this config as the default realm\nRealm.setDefaultConfiguration(config);\n```\n\n#### Kotlin\n\n```kotlin\nval config = RealmConfiguration.Builder()\n    .name(\"default-realm\")\n    .allowQueriesOnUiThread(true)\n    .allowWritesOnUiThread(true)\n    .compactOnLaunch()\n    .inMemory()\n    .build()\n// set this config as the default realm\nRealm.setDefaultConfiguration(config)\n```\n\nYou can then use\n`getDefaultConfiguration()`\nto access that configuration, or\n`getDefaultInstance()`\nto open a realm with that configuration:\n\n#### Java\n\n```java\nRealm realm = Realm.getDefaultInstance();\nLog.v(\"EXAMPLE\",\"Successfully opened the default realm at: \" + realm.getPath());\n```\n\n#### Kotlin\n\n```kotlin\nval realm = Realm.getDefaultInstance()\nLog.v(\"EXAMPLE\",\"Successfully opened the default realm at: ${realm.path}\")\n```\n\n## Local Realms\nLocal realms store data only on the client device. You can customize\nthe settings for a local realm with `RealmConfiguration`.\n\n### Local Realm Configuration\nTo configure settings for a realm, create a\n`RealmConfiguration` with a\n`RealmConfiguration.Builder`.\nThe following example configures a local realm with:\n\n- the file name \"alternate-realm\"\n- synchronous reads explicitly allowed on the UI thread\n- synchronous writes explicitly allowed on the UI thread\n- automatic compaction when launching the realm to save file space\n\n#### Java\n\n```java\nRealmConfiguration config = new RealmConfiguration.Builder()\n        .name(\"alternate-realm\")\n        .allowQueriesOnUiThread(true)\n        .allowWritesOnUiThread(true)\n        .compactOnLaunch()\n        .build();\n\nRealm realm = Realm.getInstance(config);\nLog.v(\"EXAMPLE\", \"Successfully opened a realm at: \" + realm.getPath());\n\n```\n\n#### Kotlin\n\n```kotlin\nval config = RealmConfiguration.Builder()\n    .name(\"alternate-realm\")\n    .allowQueriesOnUiThread(true)\n    .allowWritesOnUiThread(true)\n    .compactOnLaunch()\n    .build()\nval realm = Realm.getInstance(config)\nLog.v(\"EXAMPLE\", \"Successfully opened a realm at: ${realm.path}\")\n\n```\n\n> Important:\n> By default, you can only read or write to a realm in your\napplication's UI thread using\nasynchronous transactions. That is,\nyou can only use `Realm` methods whose name ends with the word\n`Async` in the main thread of your Android application unless you\nexplicitly allow the use of synchronous methods.\n>\n> This restriction exists for the benefit of your application users:\nperforming read and write operations on the UI thread can lead to\nunresponsive or slow UI interactions, so it's usually best to handle\nthese operations either asynchronously or in a background thread.\n\n### Open a Local Realm\nTo open a realm, create a\n`RealmConfiguration` with\n`RealmConfiguration.Builder` and\npass the resulting `RealmConfiguration` to\n`getInstance()`\nor `getInstanceAsync()`:\n\n#### Java\n\n```java\nRealmConfiguration config = new RealmConfiguration.Builder()\n        .allowQueriesOnUiThread(true)\n        .allowWritesOnUiThread(true)\n        .build();\n\nRealm realm;\ntry {\n    realm = Realm.getInstance(config);\n    Log.v(\"EXAMPLE\", \"Successfully opened a realm at: \" + realm.getPath());\n} catch (RealmFileException ex) {\n    Log.v(\"EXAMPLE\", \"Error opening the realm.\");\n    Log.v(\"EXAMPLE\", ex.toString());\n}\n\n```\n\n#### Kotlin\n\n```kotlin\nval config = RealmConfiguration.Builder()\n    .allowQueriesOnUiThread(true)\n    .allowWritesOnUiThread(true)\n    .build()\n\nvar realm: Realm\ntry {\n    realm = Realm.getInstance(config)\n    Log.v(\"EXAMPLE\", \"Successfully opened a realm at: ${realm.path}\")\n} catch(ex: RealmFileException) {\n    Log.v(\"EXAMPLE\", \"Error opening the realm.\")\n    Log.v(\"EXAMPLE\", ex.toString())\n}\n\n```\n\n### Read-Only Realms\nIt's sometimes useful to ship a prepared realm file with your app\nthat contains shared data that does not frequently change. You can use\nthe `readOnly()`\nmethod when configuring your realm to make it read-only. This can\nprevent accidental writes to the realm and causes the realm to\nthrow an `IllegalStateException` if a write occurs.\n\n> Warning:\n> Read-only realms are only enforced as read-only in process.\nThe realm file itself is still writeable.\n>\n\n#### Java\n\n```java\nRealmConfiguration config = new RealmConfiguration.Builder()\n        .assetFile(\"bundled.realm\")\n        .readOnly()\n        .modules(new BundledRealmModule())\n        .build();\n```\n\n#### Kotlin\n\n```kotlin\nval config = RealmConfiguration.Builder()\n    .assetFile(\"readonly.realm\")\n    .readOnly()\n    .modules(BundledRealmModule())\n    .build()\n```\n\n### In-Memory Realms\nYou can create a realm that runs entirely in memory without being written\nto a file. When memory runs low on an Android device, in-memory realms\nmay [swap](https://en.wikipedia.org/wiki/Memory_paging#Terminology) temporarily from main\nmemory to disk space. The SDK deletes all files created by an in-memory\nrealm when:\n\n- the realm closes\n- all references to that realm fall out of scope\n\nTo create an in-memory realm, use `inMemory()`\nwhen configuring your realm:\n\n#### Java\n\n```java\nRealmConfiguration config = new RealmConfiguration.Builder()\n        .inMemory()\n        .name(\"java.transient.realm\")\n        .build();\nRealm realm = Realm.getInstance(config);\n```\n\n#### Kotlin\n\n```kotlin\nval config = RealmConfiguration.Builder()\n    .inMemory()\n    .name(\"kt.transient.realm\")\n    .build()\nval realm = Realm.getInstance(config)\n```\n\n### Dynamic Realms\nConventional realms define a schema using `RealmObject` subclasses\nor the `RealmModel` interface. A\n`DynamicRealm` uses strings to\ndefine a schema at runtime. Opening a dynamic realm uses the same\nconfiguration as a conventional realm, but dynamic realms ignore\nall configured schema, migration, and schema versions.\n\nDynamic realms offer flexibility at the expense of type safety and\nperformance. As a result, only use dynamic realms when that\nflexibility is required, such as during migrations, manual client\nresets, and when working with string-based data like CSV files or JSON.\n\nTo open a Dynamic Realm with a mutable schema, use\n`DynamicRealm`:\n\n#### Java\n\n```java\nRealmConfiguration config = new RealmConfiguration.Builder()\n        .allowWritesOnUiThread(true)\n        .allowQueriesOnUiThread(true)\n        .name(\"java.dynamic.realm\")\n        .build();\nDynamicRealm dynamicRealm = DynamicRealm.getInstance(config);\n\n// all objects in a DynamicRealm are DynamicRealmObjects\nAtomicReference<DynamicRealmObject> frog = new AtomicReference<>();\ndynamicRealm.executeTransaction(transactionDynamicRealm -> {\n    // add type Frog to the schema with name and age fields\n    dynamicRealm.getSchema()\n            .create(\"Frog\")\n            .addField(\"name\", String.class)\n            .addField(\"age\", int.class);\n     frog.set(transactionDynamicRealm.createObject(\"Frog\"));\n     frog.get().set(\"name\", \"Wirt Jr.\");\n     frog.get().set(\"age\", 42);\n});\n\n// access all fields in a DynamicRealm using strings\nString name = frog.get().getString(\"name\");\nint age = frog.get().getInt(\"age\");\n\n// because an underlying schema still exists,\n// accessing a field that does not exist throws an exception\ntry {\n    frog.get().getString(\"doesn't exist\");\n} catch (IllegalArgumentException e) {\n    Log.e(\"EXAMPLE\", \"That field doesn't exist.\");\n}\n\n// Queries still work normally\nRealmResults<DynamicRealmObject> frogs = dynamicRealm.where(\"Frog\")\n        .equalTo(\"name\", \"Wirt Jr.\")\n        .findAll();\n```\n\n#### Kotlin\n\n```kotlin\nval config = RealmConfiguration.Builder()\n    .allowWritesOnUiThread(true)\n    .allowQueriesOnUiThread(true)\n    .name(\"kt.dynamic.realm\")\n    .build()\nval dynamicRealm = DynamicRealm.getInstance(config)\n\n// all objects in a DynamicRealm are DynamicRealmObjects\nvar frog: DynamicRealmObject? = null\ndynamicRealm.executeTransaction { transactionDynamicRealm: DynamicRealm ->\n    // add type Frog to the schema with name and age fields\n    dynamicRealm.schema\n        .create(\"Frog\")\n        .addField(\"name\", String::class.java)\n        .addField(\"age\", Integer::class.java)\n    frog = transactionDynamicRealm.createObject(\"Frog\")\n    frog?.set(\"name\", \"Wirt Jr.\")\n    frog?.set(\"age\", 42)\n}\n\n// access all fields in a DynamicRealm using strings\nval name = frog?.getString(\"name\")\nval age = frog?.getInt(\"age\")\n\n// because an underlying schema still exists,\n// accessing a field that does not exist throws an exception\ntry {\n    frog?.getString(\"doesn't exist\")\n} catch (e: IllegalArgumentException) {\n    Log.e(\"EXAMPLE\", \"That field doesn't exist.\")\n}\n\n// Queries still work normally\nval frogs = dynamicRealm.where(\"Frog\")\n    .equalTo(\"name\", \"Wirt Jr.\")\n    .findAll()\n```\n\n## Close a Realm\nIt is important to remember to call the `close()` method when done with a\nrealm instance to free resources. Neglecting to close realms can lead to an\n`OutOfMemoryError`.\n\n#### Java\n\n```java\nrealm.close();\n\n```\n\n#### Kotlin\n\n```kotlin\nrealm.close()\n\n```\n\n## Configure Which Classes to Include in Your Realm Schema\nRealm modules are collections of Realm object\nmodels. Specify a module or modules when opening a realm to control\nwhich classes Realm should include in your schema. If you\ndo not specify a module, Realm uses the default module,\nwhich includes all Realm objects defined in your\napplication.\n\n> Note:\n> Libraries that include Realm must expose and use their\nschema through a module. Doing so prevents the library from\ngenerating the default `RealmModule`, which would conflict with\nthe default `RealmModule` used by any app that includes the library.\nApps using the library access library classes through the module.\n>\n\n"
  },
  {
    "path": "docs/guides/realm-files.md",
    "content": "# Work with Realm Files - Java SDK\nA **realm** is a set of related objects that conform to a pre-defined\nschema. Realms may contain more than one type of data as long as a\nschema exists for each type.\n\nEvery realm stores data in a separate realm file that\ncontains a binary encoding of each object in the realm. You can\nautomatically synchronize realm across multiple\ndevices and set up reactive\nevent handlers that call a\nfunction any time an object in a realm is created,\nmodified, or deleted.\n\n## The Realm Lifecycle\nEvery realm instance consumes a significant amount of resources.\nOpening and closing a realm are both expensive operations, but\nkeeping a realm open also incurs significant resource overhead. To\nmaximize the performance of your application, you should minimize the\nnumber of open realms at any given time and limit the number of\nopen and close operations used.\n\nHowever, opening a realm is not always consistently expensive.\nIf the realm is already open within the same process or thread,\nopening an additional instance requires fewer resources:\n\n- If the realm is not open within the same process, opening the\nrealm is expensive.\n- If the realm is already open on a different thread within the\nsame process, opening the realm is less expensive, but still\nnontrivial.\n- If the realm is already open on the same thread within the same\nprocess, opening the realm requires minimal additional resources.\n\nWhen you open a realm for the first time, Realm\nperforms the memory-mapping and schema validation required to read and\nwrite data to the realm. Additional instances of that\nrealm on the same thread use the same underlying resources.\nInstances of that realm on separate threads use some of the same\nunderlying resources.\n\nWhen all connections to a realm are closed in\na thread, Realm frees the thread resources used to\nconnect to that realm. When all connections to a realm are\nclosed in a process, Realm frees all resources used to\nconnect to that realm.\n\nAs a best practice, we recommend tying the realm instance\nlifecycle to the lifecycles of the views that observe the realm. For\ninstance, consider a `RecyclerView` that displays `RealmResults`\ndata via a `Fragment`. You could:\n\n- Open a single realm that contains the data for that view\nin the `Fragment.onCreateView()` lifecycle method.\n- Close that same realm in the `Fragment.onDestroyView()`\nlifecycle method.\n\n> Note:\n> If your realm is especially large, fetching a realm instance\nin `Fragment.onCreateView()` may briefly block rendering. If\nopening your realm in `onCreateView()` causes performance\nissues, consider managing the realm from `Fragment.onStart()`\nand `Fragment.onStop()` instead.\n>\n\nIf multiple `Fragment` instances require access to the same dataset,\nyou could manage a single realm in the enclosing `Activity`:\n\n- Open the realm in the `Activity.onCreate()` lifecycle method.\n- Close the realm in the `Activity.onDestroy()` lifecycle method.\n\n## Multi-process\nYou cannot access encrypted or\n[delete me]s\nsimultaneously from different processes. However, local realms\nfunction normally across processes, so you can read, write, and\nreceive notifications from multiple APKs.\n\n## Realm Schema\nA **Realm Schema** is a list of valid object schemas that each define an object type that an App\nmay persist. All objects in a realm must conform to the Realm Schema.\n\nBy default, the SDK automatically adds all classes in your project\nthat derive from `RealmObject` to the\nrealm schema.\n\nClient applications provide a Realm Schema when they open a\nrealm. If a realm already contains data, then Realm\nvalidates each existing object to ensure that an object schema was\nprovided for its type and that it meets all of the constraints specified\nin the schema.\n\n> Example:\n> A realm that contains basic data about books in libraries might use a\nschema like the following:\n>\n> ```json\n> [\n>   {\n>     \"type\": \"Library\",\n>     \"properties\": {\n>       \"address\": \"string\",\n>       \"books\": \"Book[]\"\n>     }\n>   },\n>   {\n>     \"type\": \"Book\",\n>     \"primaryKey\": \"isbn\",\n>     \"properties\": {\n>       \"isbn\": \"string\",\n>       \"title\": \"string\",\n>       \"author\": \"string\",\n>       \"numberOwned\": { \"type\": \"int?\", \"default\": 0 },\n>       \"numberLoaned\": { \"type\": \"int?\", \"default\": 0 }\n>     }\n>   }\n> ]\n> ```\n>\n\n## Find Your Realm File\nRealm stores a binary encoded version of every object\nand type in a realm in a single `.realm` file.\n\nThe filesystem used by Android emulators is not directly accessible\nfrom the machine running Realm Studio. You must download the file\nfrom the emulator before you can access it.\n\nFirst, find the path of the file on the emulator:\n\n```java\n// Run this on the device to find the path on the emulator\nRealm realm = Realm.getDefaultInstance();\nLog.i(\"Realm\", realm.getPath());\n```\n\nThen, download the file using ADB. You can do this while the app\nis running.\n\n```java\n> adb pull <path>\n```\n\nYou can also upload the modified file again using ADB, but only\nwhen the app isn't running. Uploading a modified file while the\napp is running can corrupt the file.\n\n```java\n> adb push <file> <path>\n```\n\n> Seealso:\n> Realm creates additional files for each realm.\nTo learn more about these files, see Realm Internals.\n>\n\n## Realm File Size\nRealm usually takes up less space on disk than an\nequivalent SQLite database. However, in order to give you a consistent\nview of your data, Realm operates on multiple versions of a\nrealm. If many versions of a realm are opened simultaneously,\nthe realm file can require additional space on disk.\n\nThese versions take up an amount of space dependent on the amount of\nchanges in each transaction. Many small transactions have the same\noverhead as a small number of large transactions.\n\nUnexpected file size growth usually happens for one of three reasons:\n\n1. *You open a realm on a background thread and forget to close it\nagain.* As a result, Realm retains a reference to the\nolder version of data on the background thread. Because\nRealm automatically updates realms to the most\nrecent version on threads with loopers, the UI thread and other\nLooper threads do not have this problem.\n2. *You hold references to too many versions of frozen objects.*\nFrozen objects preserve the version of a realm that existed when\nthe object was first frozen. If you need to freeze a large number of\nobjects, consider using `Realm.copyFromRealm()` instead to only preserve the\ndata you need.\n3. *You read some data from a realm. Then, you block the thread with\na long-running operation. Meanwhile, you write many times to the\nrealm on other threads.* This causes Realm to\ncreate many intermediate versions. You can avoid this by: batching the\nwrites, avoiding leaving the realm open while otherwise blocking the\nbackground thread.\n\n### Limit the Maximum Number of Active Versions\nYou can set `maxNumberOfActiveVersions()`\nwhen building your `RealmConfiguration` to throw an\n`IllegalStateException` if your application opens more versions of\na realm than the permitted number. Versions are created when\nexecuting a write transaction.\n\nRealm automatically removes older versions of data once\nthey are no longer used by your application. However,\nRealm does not free the space used by older versions of\ndata; instead, that space is used for new writes to the realm.\n\n### Compact a Realm\nYou can remove unused space by **compacting** the realm file:\n\n- Manually: call `compactRealm()`\n- Automatically: specify the `compactOnLaunch()`\nbuilder option when opening the first connection to a realm in your\nAndroid application\n\n> Important:\n> Every production application should implement compacting to\nperiodically reduce realm file size.\n>\n\n## Backup and Restore Realms\nRealm persists realms to disk using files on your\nAndroid device. To back up a realm, find your realm file and copy it to a safe location. You should close\nall instances of the realm before copying it.\n\nAlternatively, you can also use `realm.writeCopyTo()` to write a compacted\nversion of a realm to a destination file.\n\n> Seealso:\n> If you want to back up a realm to an external location like\nGoogle Drive, see the following article series: ([Part 1](https://medium.com/glucosio-project/example-class-to-export-import-a-realm-database-on-java-c429ade2b4ed#.80ibsc7wm),\n[Part 2](https://medium.com/glucosio-project/backup-restore-a-realm-database-on-google-drive-with-drive-api-c238515a5975#.qbuugb322),\n[Part 3](https://medium.com/glucosio-project/build-a-nice-ux-to-backup-and-sync-your-app-data-on-google-drive-3-3-a3b598cab68b#.5mjk4w4se)).\n>\n\n## Modules\nRealm Modules describe the set of Realm objects\nthat can be stored in a realm. By default, Realm\nautomatically creates a Realm Module that contains all\nRealm objects defined in your application.\nYou can define a `RealmModule`\nto restrict a realm to a subset of classes defined in an application.\nIf you produce a library that uses Realm, you can use a\nRealm Module to explicitly include only the Realm\nobjects defined in your library in your realm. This allows\napplications that include your library to also use Realm\nwithout managing object name conflicts and migrations with your library's\ndefined Realm objects.\n"
  },
  {
    "path": "docs/guides/realm-query-language.md",
    "content": "# Realm Query Language\nRealm Query Language (RQL) is a string-based query language to constrain\nsearches when retrieving objects from a realm. SDK-specific methods pass queries\nto the Realm query engine, which retrieves matching objects from the realm.\nRealm Query Language syntax is based on [NSPredicate](https://developer.apple.com/documentation/foundation/nspredicate).\n\nQueries evaluate a predicate for every object in the collection being queried.\nIf the predicate resolves to `true`, the results collection includes the object.\n\nYou can use Realm Query Language in most Realm SDKs with your SDK's filter\nor query methods. The Swift SDK is the exception, as it uses the\nNSPredicate query API.\nSome SDKs also support idiomatic APIs for querying realms in their language.\n\nYou can also use Realm Query Language to browse for data in\nRealm Studio. Realm Studio is a visual tool\nto view, edit, and design Realm files.\n\n## Examples on This Page\nMany of the examples in this page use a simple data set for a to-do list app.\nThe two Realm object types are `Project` and `Item`.\n\n- An `Item` has a name, assignee's name, and completed flag.\nThere is also an arbitrary number for priority (higher is more important)\nand a count of minutes spent working on it.\n- A `Project` has zero or more `Items` and an optional quota\nfor minimum number of to-do items expected to be completed.\n\nSee the schema for these two classes, `Project` and `Item`, below:\n\n### Java\n\n```java\npublic class Item extends RealmObject {\n  ObjectId id = new ObjectId();\n  String name;\n  Boolean isComplete = false;\n  String assignee;\n  Integer priority = 0;\n  Integer progressMinutes = 0;\n  @LinkingObjects(\"items\")\n  final RealmResults<Project> projects = null;\n}\npublic class Project extends RealmObject {\n  ObjectId id = new ObjectId();\n  String name;\n  RealmList<Item> items;\n  Integer quota = null;\n}\n```\n\n### Kotlin\n\n```kotlin\nopen class Item(): RealmObject() {\n  var id: ObjectId = new ObjectId()\n  @FullText\n  lateinit var name: String\n  var isComplete: Boolean = false\n  var assignee: String? = null\n  var priority: Int = 0\n  var progressMinutes: Int = 0\n}\n\nopen class Project(): RealmObject() {\n  var id: ObjectId = new ObjectId()\n  lateinit var name: String\n  lateinit var items: RealmList<Item>\n  var quota: Int? = null\n}\n```\n\n\n\n## Expressions\nFilters consist of **expressions** in a predicate. An expression consists of\none of the following:\n\n- The name of a property of the object currently being evaluated.\n- An operator and up to two argument expression(s). For example, in the\nexpression `A + B`, the entirety of `A + B` is an expression, but `A`\nand `B` are also argument expressions to the operator `+`.\n- A value, such as a string (`'hello'`) or a number (`5`).\n\n```javascript\n\"progressMinutes > 1 AND assignee == $0\", \"Ali\"\n\n```\n\n## Parameterized Queries\nCreate parameterized queries to interpolate variables into prepared\nRealm Query Language statements. The syntax for interpolated variables is\n`$<int>`, starting at `0`. Pass the positional arguments as\nadditional arguments to Realm SDK methods that use Realm Query Language.\n\nInclude just one parameter with `$0`.\n\n```js\n\"progressMinutes > 1 AND assignee == $0\", \"Ali\"\n\n```\n\nInclude multiple parameters with ascending integers starting at `$0`.\n\n```js\n\"progressMinutes > $0 AND assignee == $1\", 1, \"Alex\"\n\n```\n\n### Query Formats\nThe following table shows how a query should be formatted when serialized and\nparameterized for the following data types:\n\n|Type|Parameterized Example|Serialized Example|Note|\n| --- | --- | --- | --- |\n|Boolean|\"setting == $0\", false|\"setting == false\"|`true` or `false` values.|\n|String|\"name == $0\", \"George\"|\"name == 'George'\"|Applies to `string` and `char` data type.|\n|Number|\"age > $0\", 5.50|\"age > 5.50\"|Applies to `int`, `short`, `long`, `double`, `Decimal128`, and `float` data types.|\n|Date|\"date < $0\", dateObject|\"date < 2021-02-20@17:30:15:0\"|For parameterized date queries, you must pass in a date object. For serialized date queries, you can represented the date in the following formats: As an explicit date and time- YYYY-MM-DD@HH:mm:ss:nn (year-month-day@hours:minutes:seconds:nanoseconds) As a `datetime` relative to the [Unix epoch](https://en.wikipedia.org/wiki/Unix_time)- Ts:n (T, designates the start of the time; `s`, seconds; `n`, nanoseconds) Parameterized `Date` object|\n|ObjectID|\"_id == $0\", oidValue|\"_id == oid(507f1f77bcf86cd799439011)\"|For parameterized ObjectId queries, you must pass in an ObjectId. For serialized ObjectId queries, the string representation is `oid(<ObjectId String>)`.|\n|UUID|\"id == $0\", uuidValue|\"id == uuid(d1b186e1-e9e0-4768-a1a7-c492519d47ee)\"|For parameterized UUID queries, you must pass in a UUID. For serialized UUID queries, the string representation is `uuid(<UUID String>)`.|\n|Binary|\"value == $0\", \"binary\"|\"value == 'binary'\"|For ASCII characters, RQL serializes the binary value like a string, with quotes. For non-printable characters, RQL serializes the binary to a base 64 value.|\n|List|\"ANY items.name == {$0, $1}\", \"milk\", \"bread\"|\"ANY items.name == {'milk', 'bread'}\"|Applies for list, collections, and sets. A parameterized value should be used for each member of the list.|\n|RealmObject|\"ANY items == $0\", obj(\"Item\", oid(6489f036f7bd0546377303ab))|\"ANY items == obj('Item', oid(6489f036f7bd0546377303ab))\"|To pass in a RealmObject, you need the class and primary key of the object.|\n\n## Dot Notation\nWhen referring to an object property, you can use **dot notation** to refer\nto child properties of that object. You can even refer to the properties of\nembedded objects and relationships with dot notation.\n\nFor example, consider a query on an object with a `workplace` property that\nrefers to a Workplace object. The Workplace object has an embedded object\nproperty, `address`. You can chain dot notations to refer to the zipcode\nproperty of that address:\n\n```js\n\"workplace.address.zipcode == 10019\"\n\n```\n\n## Nil Type\nRealm Query Language include the `nil` type to represent a null pointer.\nYou can either reference `nil` directly in your queries or with a parameterized query.\nIf you're using a parameterized query, each SDK maps its respective null pointer\nto `nil`.\n\n```js\n\"assignee == nil\"\n\n```\n\n```js\n// comparison to language null pointer\n\"assignee == $0\", null\n\n```\n\n## Comparison Operators\nThe most straightforward operation in a search is to compare\nvalues.\n\n> Important:\n> The type on both sides of the operator must be equivalent. For\nexample, comparing an ObjectId with string will result in a precondition\nfailure with a message like:\n>\n> ```\n> \"Expected object of type object id for property 'id' on object of type\n> 'User', but received: 11223344556677889900aabb (Invalid value)\"\n> ```\n>\n> You can compare any numeric type with any other numeric type,\nincluding decimal, float, and Decimal128.\n>\n\n|Operator|Description|\n| --- | --- |\n|`BETWEEN {number1, number2}`|Evaluates to `true` if the left-hand numerical or date expression is between or equal to the right-hand range. For dates, this evaluates to `true` if the left-hand date is within the right-hand date range.|\n|== , =|Evaluates to `true` if the left-hand expression is equal to the right-hand expression.|\n|>|Evaluates to `true` if the left-hand numerical or date expression is greater than the right-hand numerical or date expression. For dates, this evaluates to `true` if the left-hand date is later than the right-hand date.|\n|>=|Evaluates to `true` if the left-hand numerical or date expression is greater than or equal to the right-hand numerical or date expression. For dates, this evaluates to `true` if the left-hand date is later than or the same as the right-hand date.|\n|IN|Evaluates to `true` if the left-hand expression is in the right-hand list. This is equivalent to and used as a shorthand for `== ANY`.|\n|<|Evaluates to `true` if the left-hand numerical or date expression is less than the right-hand numerical or date expression. For dates, this evaluates to `true` if the left-hand date is earlier than the right-hand date.|\n|<=|Evaluates to `true` if the left-hand numeric expression is less than or equal to the right-hand numeric expression. For dates, this evaluates to `true` if the left-hand date is earlier than or the same as the right-hand date.|\n|!= , <>|Evaluates to `true` if the left-hand expression is not equal to the right-hand expression.|\n\n> Example:\n> The following example uses Realm Query Language's comparison operators to:\n>\n> - Find high priority to-do items by comparing the value of the `priority`\nproperty value with a threshold number, above which priority can be considered high.\n> - Find long-running to-do items by seeing if the `progressMinutes` property\nis at or above a certain value.\n> - Find unassigned to-do items by finding items where the `assignee` property\nis equal to `null`.\n> - Find to-do items within a certain time range by finding items where the\n`progressMinutes` property is between two numbers.\n> - Find to-do items with a certain amount of `progressMinutes` from the\ngiven list.\n>\n> ```javascript\n>   // Find high priority to-do items by comparing the value of the ``priority``\n>   // property value with a threshold number, above which priority can be considered high.\n>   \"priority > $0\", 5\n>\n>   // Find long-running to-do items by seeing if the progressMinutes property is at or above a certain value.\n>   \"progressMinutes > $0\", 120\n>\n>   // Find unassigned to-do items by finding items where the assignee property is equal to null.\n>   \"assignee == $0\", null\n>\n>   // Find to-do items within a certain time range by finding items\n>   // where the progressMinutes property is between two numbers.\n>   \"progressMinutes BETWEEN { $0 , $1 }\", 30, 60\n>\n>   // Find to-do items with a certain amount of progressMinutes from the given list.\n>   \"progressMinutes IN { $0, $1, $2, $3, $4, $5 }\", 10, 20, 30, 40, 50, 60\n>\n> ```\n>\n\n## Logical Operators\nMake compound predicates using logical operators.\n\n|Operator|Description|\n| --- | --- |\n|AND &&|Evaluates to `true` if both left-hand and right-hand expressions are `true`.|\n|NOT !|Negates the result of the given expression.|\n|OR \\\\|\\\\||Evaluates to `true` if either expression returns `true`.|\n\n> Example:\n> We can use the query language's logical operators to find\nall of Ali's completed to-do items. That is, we find all items\nwhere the `assignee` property value is equal to 'Ali' AND\nthe `isComplete` property value is `true`:\n>\n> ```javascript\n> \"assignee == $0 AND isComplete == $1\", \"Ali\", true\n>\n> ```\n>\n\n## String Operators\nCompare string values using these string operators.\nRegex-like wildcards allow more flexibility in search.\n\n> Note:\n> You can use the following modifiers with the string operators:\n>\n> - `[c]` for case insensitivity. `\"name CONTAINS[c] $0\", 'a'`\n>\n\n|Operator|Description|\n| --- | --- |\n|BEGINSWITH|Evaluates to `true` if the left-hand string expression begins with the right-hand string expression. This is similar to `contains`, but only matches if the right-hand string expression is found at the beginning of the left-hand string expression.|\n|CONTAINS|Evaluates to `true` if the right-hand string expression is found anywhere in the left-hand string expression.|\n|ENDSWITH|Evaluates to `true` if the left-hand string expression ends with the right-hand string expression. This is similar to `contains`, but only matches if the left-hand string expression is found at the very end of the right-hand string expression.|\n|LIKE|Evaluates to `true` if the left-hand string expression matches the right-hand string wildcard string expression. A wildcard string expression is a string that uses normal characters with two special wildcard characters: The `*` wildcard matches zero or more of any character The `?` wildcard matches any character. For example, the wildcard string \"d?g\" matches \"dog\", \"dig\", and \"dug\", but not \"ding\", \"dg\", or \"a dog\".|\n|== , =|Evaluates to `true` if the left-hand string is lexicographically equal to the right-hand string.|\n|!= , <>|Evaluates to `true` if the left-hand string is not lexicographically equal to the right-hand string.|\n\n> Example:\n> We use the query engine's string operators to find:\n>\n> - Projects with a name starting with the letter 'e'\n> - Projects with names that contain 'ie'\n>\n> ```javascript\n>   \"name BEGINSWITH[c] $0\", 'e'\n>\n>   \"name CONTAINS $0\", 'ie'\n>\n> ```\n>\n\n## ObjectId and UUID Operators\nQuery [BSON ObjectIds](https://www.mongodb.com/docs/manual/reference/method/ObjectId/) and\n[UUIDs](https://www.mongodb.com/docs/manual/reference/method/UUID/).\nThese data types are often used as primary keys.\n\nTo query with ObjectIds, use a parameterized query. Pass the ObjectId or UUID\nyou're querying against as the argument.\n\n```js\n\"_id == $0\", oidValue\n\n```\n\nYou can also put a string representation of the ObjectId you're evaluating\nin `oid(<ObjectId String>)`.\n\n```js\n\"_id == oid(6001c033600510df3bbfd864)\"\n\n```\n\nTo query with UUIDs, put a string representation of the UUID you're evaluating\nin `uuid(<UUID String>)`.\n\n```js\n\"id == uuid(d1b186e1-e9e0-4768-a1a7-c492519d47ee)\"\n\n```\n\n|Operator|Description|\n| --- | --- |\n|== , =|Evaluates to `true` if the left-hand value is equal to the right-hand value.|\n|!= , <>|Evaluates to `true` if the left-hand value is not equal to the right-hand value.|\n\n## Arithmetic Operators\nPerform basic arithmetic in one side of a RQL expression when evaluating\nnumeric data types.\n\n```js\n  \"2 * priority > 6\"\n  // Is equivalent to\n  \"priority >= 2 * (2 - 1) + 2\"\n\n```\n\nYou can also use multiple object properties together in a mathematic operation.\n\n```js\n\"progressMinutes * priority == 90\"\n\n```\n\n|Operator|Description|\n| --- | --- |\n|*|Multiplication.|\n|/|Division.|\n|+|Addition.|\n|-|Subtraction.|\n|()|Group expressions together.|\n\n## Type Operator\nCheck the type of a property using the `@type` operator.\nYou can only use the type operator with mixed types and dictionaries.\n\nEvaluate the property against a string representation of the data type name.\nRefer to SDK documentation on the mapping from the SDK language's data types\nto Realm data types.\n\n|Operator|Description|\n| --- | --- |\n|`@type`|Check if type of a property is the property name as a string. Use `==` and `!=` to compare equality.|\n\n```js\n  \"mixedType.@type == 'string'\"\n\n  \"mixedType.@type == 'bool'\"\n\n```\n\n## Dictionary Operators\nCompare dictionary values using these dictionary operators.\n\n|Operator|Description|\n| --- | --- |\n|`@values`|Returns objects that have the value specified in the right-hand expression.|\n|`@keys`|Returns objects that have the key specified in the right-hand expression.|\n|`@size`, `@count`|The number of elements in a dictionary.|\n|`Dictionary['key']`|Access the value at a key of a dictionary.|\n|`ALL \\| ANY \\| NONE <property>.@type`|Checks if the dictionary contains properties of certain type.|\n\nYou can also use dictionary operators in combination with\ncomparison operators to filter objects\nbased on dictionary keys and values. The following examples show some ways\nto use dictionary operators with comparison operators. All examples query\na collection of Realm objects with a dictionary property named `dict`.\n\n> Example:\n> The following examples use various dictionary operators.\n>\n> ```js\n>   // Evaluates if there is a dictionary key with the name 'foo'\n>   \"ANY dict.@keys == $0\", 'foo'\n>\n>   // Evaluates if there is a dictionary key with key 'foo' and value 'bar\n>   \"dict['foo'] == $0\", 'bar'\n>\n>   // Evaluates if there is greater than one key-value pair in the dictionary\n>   \"dict.@count > $0\", 1\n>\n>   // Evaluates if dictionary has property of type 'string'\n>   \"ANY dict.@type == 'string'\"\n>\n>   // Evaluates if all the dictionary's values are integers\n>   \"ALL dict.@type == 'bool'\"\n>\n>   // Evaluates if dictionary does not have any values of type int\n>   \"NONE dict.@type == 'double'\"\n>\n>   // ANY is implied.\n>   \"dict.@type == 'string'\"\n>\n> ```\n>\n\n## Date Operators\nQuery date types in a realm.\n\nGenerally, you should use a parameterized query to pass a date data type\nfrom the SDK language you are using to a query.\n\n```js\n\"timeCompleted < $0\", someDate\n\n```\n\nYou can also specify dates in the following two ways:\n\n- As a specific date (in UTC)- `YYYY-MM-DD@HH:mm:ss:nnnnnnnnnn` (year-month-day@hours:minutes:seconds:nanoseconds), UTC.\nYou can also use `T` instead of `@` to separate the date from the time.\n- As a time in seconds since the [Unix epoch](https://en.wikipedia.org/wiki/Unix_time)- `Ts:n`, where `T` designates the start of the time,\n`s` is the number of seconds, and `n` is the number of nanoseconds.\n\nDate supports comparison operators.\n\n> Example:\n> The following example shows how to use a parameterized query with\na date object:\n>\n> ```js\n> var date = new Date(\"2021-02-20@17:30:15:0\");\n>\n>   \"timeCompleted > $0\", date\n> ```\n>\n\n## Aggregate Operators\nApply an aggregate operator to a collection property of a Realm\nobject. Aggregate operators traverse a collection and reduce it to a\nsingle value.\n\n|Operator|Description|\n| --- | --- |\n|@avg|Evaluates to the average value of a given numerical property across a collection. If any values are `null`, they are not counted in the result.|\n|@count|Evaluates to the number of objects in the given collection.|\n|@max|Evaluates to the highest value of a given numerical property across a collection. `null` values are ignored.|\n|@min|Evaluates to the lowest value of a given numerical property across a collection. `null` values are ignored.|\n|@sum|Evaluates to the sum of a given numerical property across a collection, excluding `null` values.|\n\n> Example:\n> These examples all query for projects containing to-do items that meet\nthis criteria:\n>\n> - Projects with average item priority above 5.\n> - Projects with an item whose priority is less than 5.\n> - Projects with an item whose priority is greater than 5.\n> - Projects with more than 5 items.\n> - Projects with long-running items.\n>\n> ```javascript\n> var priorityNum = 5;\n>\n>   \"items.@avg.priority > $0\", priorityNum\n>\n>   \"items.@max.priority < $0\", priorityNum\n>\n>   \"items.@min.priority > $0\", priorityNum\n>\n>   \"items.@count > $0\", 5\n>\n>   \"items.@sum.progressMinutes > $0\", 100\n>\n> ```\n>\n\n## Collection Operators\nA **collection operator** lets you query list properties within a collection of objects.\nCollection operators filter a collection by applying a predicate\nto every element of a given list property of the object.\nIf the predicate returns true, the object is included in the output collection.\n\n|Operator|Description|\n| --- | --- |\n|`ALL`|Returns objects where the predicate evaluates to `true` for all objects in the collection.|\n|`ANY`, `SOME`|Returns objects where the predicate evaluates to `true` for any objects in the collection.|\n|`NONE`|Returns objects where the predicate evaluates to false for all objects in the collection.|\n\n> Example:\n> This example uses collection operators to find projects that contain to-do items\nmatching certain criteria:\n>\n> ```js\n>   // Projects with no complete items.\n>   \"NONE items.isComplete == $0\", true\n>\n>   // Projects that contain a item with priority 10\n>   \"ANY items.priority == $0\", 10\n>\n>   // Projects that only contain completed items\n>   \"ALL items.isComplete == $0\", true\n>\n>   // Projects with at least one item assigned to either Alex or Ali\n>   \"ANY items.assignee IN { $0 , $1 }\", \"Alex\", \"Ali\"\n>\n>   // Projects with no items assigned to either Alex or Ali\n>   \"NONE items.assignee IN { $0 , $1 }\", \"Alex\", \"Ali\"\n>\n> ```\n>\n\n## List Comparisons\nYou can use comparison operators and\ncollection operators to filter based\non lists of data.\n\nYou can compare any type of valid list. This includes:\n\n- collections of Realm objects, which let you filter against other data\nin the realm. `\"oid(631a072f75120729dc9223d9) IN items.id\"\n`\n- lists defined directly in the query, which let you filter against\nstatic data. You define static lists as a comma-separated list of\nliteral values enclosed in opening (`{`) and closing (`}`) braces. `\"priority IN {0, 1, 2}\"\n`\n- native list objects passed in a parameterized expression, which let you pass application data\ndirectly to your queries. `const ids = [\n  new BSON.ObjectId(\"631a072f75120729dc9223d9\"),\n  new BSON.ObjectId(\"631a0737c98f89f5b81cd24d\"),\n  new BSON.ObjectId(\"631a073c833a34ade21db2b2\"),\n];\nconst parameterizedQuery = realm.objects(\"Item\").filtered(\"id IN $0\", ids);\n`\n\nIf you do not define a collection operator, a list expression defaults\nto the `ANY` operator.\n\n> Example:\n> These two list queries are equivalent:\n>\n> - `age == ANY {18, 21}`\n> - `age == {18, 21}`\n>\n> Both of these queries return objects with an age property equal to\neither 18 or 21. You could also do the opposite by returning objects\nonly if the age is not equal to either 18 or 21:\n>\n> - `age == NONE {18, 21}`\n>\n\nThe following table includes examples that illustrate how collection\noperators interact with lists and comparison operators:\n\n|Expression|Match?|Reason|\n| --- | --- | --- |\n|`ANY {1, 2, 3} > ALL {1, 2}`|true|A value on the left (3) is greater than some value on the right (both 1 and 2)|\n|`ANY {1, 2, 3} == NONE {1, 2}`|true|3 does not match either of 1 or 2|\n|`ANY {4, 8} == ANY {5, 9, 11}`|false|Neither 4 nor 8 matches any value on the right (5, 9 or 11)|\n|`ANY {1, 2, 7} <= NONE {1, 2}`|true|A value on the left (7) is not less than or equal to both 1 and 2|\n|`ALL {1, 2} IN ANY {1, 2, 3}`|true|Every value on the left (1 and 2) is equal to 1, 2 or 3|\n|`ALL {3, 1, 4, 3} == NONE {1, 2}`|false|1 matches a value in the NONE list (1 or 2)|\n|`ALL {} in ALL {1, 2}`|true|An empty list matches all lists|\n|`NONE {1, 2, 3, 12} > ALL {5, 9, 11}`|false|12 is bigger than all values on the right (5, 9, and 11)|\n|`NONE {4, 8} > ALL {5, 9, 11}`|true|4 and 8 are both less than some value on the right (5, 9, or 11)|\n|`NONE {0, 1} < NONE {1, 2}`|true|0 and 1 are both less than none of 1 and 2|\n\n## Full Text Search\nYou can use RQL to query on properties that have a full-text search (FTS)\nannotation. FTS supports boolean match word searches, rather than searches for relevance.\nFor information on enabling FTS on a property, see the FTS documentation for\nyour SDK:\n\n- Flutter SDK\n- Kotlin SDK\n- .NET SDK\n- Node.js SDK\n- React Native SDK\n- Swift SDK does not yet support Full-Text Search.\n\nTo query these properties, use the `TEXT` predicate in your query.\n\nYou can search for entire words or phrases, or limit your results with the following characters:\n\n- Exclude results for a word by placing the `-` character in front of the word.\n- Specify prefixes by placing the `*` character at the end of a prefix. Suffix\nsearching is not currently supported.\n\nIn the following example, we query the `Item.name` property:\n\n```js\n    // Filter for items with 'write' in the name\n    \"name TEXT $0\", \"write\"\n\n    // Find items with 'write' but not 'tests' using '-'\n    \"name TEXT $0\", \"write -tests\"\n\n    // Find items starting with 'wri-' using '*'\n    \"name TEXT $0\", \"wri*\"\n\n```\n\n### Full-Text Search Tokenizer Details\nFull-Text Search (FTS) indexes support:\n\n- Tokens are diacritics- and case-insensitive.\n- Tokens can only consist of characters from ASCII and the Latin-1 supplement (western languages).\nAll other characters are considered whitespace.\n- Words split by a hyphen (-) are split into two tokens.  For example, `full-text`\nsplits into `full` and `text`.\n\n## Backlink Queries\nA backlink is an inverse relationship link that lets you look up objects\nthat reference another object. Backlinks use the to-one and to-many\nrelationships defined in your object schemas but reverse the direction.\nEvery relationship that you define in your schema implicitly has a\ncorresponding backlink.\n\nYou can access backlinks in queries using the\n`@links.<ObjectType>.<PropertyName>` syntax, where `<ObjectType>`\nand `<PropertyName>` refer to a specific property on an object type\nthat references the queried object type.\n\n```js\n// Find items that belong to a project with a quota greater than 10 (@links)\n\"@links.Project.items.quota > 10\"\n\n```\n\nYou can also define a `linkingObjects` property to explicitly include\nthe backlink in your data model. This lets you reference the backlink\nthrough an assigned property name using standard dot notation.\n\n```js\n// Find items that belong to a project with a quota greater than 10 (LinkingObjects)\n\"projects.quota > 10\"\n\n```\n\nThe result of a backlink is treated like a collection and supports\ncollection operators.\n\n```js\n  // Find items where any project that references the item has a quota greater than 0\n  \"ANY @links.Project.items.quota > 0\"\n  // Find items where all projects that reference the item have a quota greater than 0\n  \"ALL @links.Project.items.quota > 0\"\n\n```\n\nYou can use aggregate operators on the backlink collection.\n\n```js\n  // Find items that are referenced by multiple projects\n  \"projects.@count > 1\"\n  // Find items that are not referenced by any project\n  \"@links.Project.items.@count == 0\"\n  // Find items that belong to a project where the average item has\n  // been worked on for at least 5 minutes\n  \"@links.Project.items.items.@avg.progressMinutes > 10\"\n\n```\n\nYou can query the count of all relationships that point to an object by\nusing the `@count` operator directly on `@links`.\n\n```js\n// Find items that are not referenced by another object of any type\n\"@links.@count == 0\"\n\n```\n\n## Subqueries\nIterate through list properties with another query using the\n`SUBQUERY()` predicate function.\n\nSubqueries are useful for the following scenarios:\n\n- Matching each object in a list property on multiple conditions\n- Counting the number of objects that match a subquery\n\n`SUBQUERY()` has the following structure:\n\n```js\nSUBQUERY(<collection>, <variableName>, <predicate>)\n```\n\n- `collection`: The name of the property to iterate through\n- `variableName`: A variable name of the element to use in the subquery\n- `predicate`: The subquery predicate.\nUse the variable specified by `variableName` to refer to the\ncurrently-iterated element.\n\nA subquery iterates through the given collection and checks the given predicate\nagainst each object in the collection. The predicate can refer to the current\niterated object with the variable name passed to `SUBQUERY()`.\n\nA subquery expression resolves to a list of objects.\nRealm only supports the `@count` aggregate operator on the result\nof a subquery. This allows you to count how many objects in the subquery\ninput collection matched the predicate.\n\nYou can use the count of the subquery result as you would any other number\nin a valid expression. In particular, you can compare the count with the\nnumber `0` to return all matching objects.\n\n> Example:\n> The following example shows two subquery filters on a collection of projects.\n>\n> ```js\n>   // Returns projects with items that have not been completed\n>   // by a user named Alex.\n>   \"SUBQUERY(items, $item, $item.isComplete == false AND $item.assignee == 'Alex').@count > 0\"\n>\n>   // Returns the projects where the number of completed items is\n>   // greater than or equal to the value of a project's `quota` property.\n>   \"SUBQUERY(items, $item, $item.isComplete == true).@count >= quota\"\n>\n> ```\n>\n\n## Sort, Distinct & Limit\nSort and limit the results collection of your query using additional operators.\n\n|Operator|Description|\n| --- | --- |\n|`SORT`|Specify the name of the property to compare, and whether to sort by ascending (`ASC`) or descending (`DESC`) order. If you specify multiple SORT fields, you must specify sort order for each field. With multiple sort fields, the query sorts by the first field, and then the second. For example, if you `SORT (priority DESC, name DESC)`, the query returns sorted by priority, and then by name when priority value is the same.|\n|`DISTINCT`|Specify a name of the property to compare. Remove duplicates for that property in the results collection. If you specify multiple DISTINCT fields, the query removes duplicates by the first field, and then the second. For example, if you `DISTINCT (name, assignee)`, the query only removes duplicates where the values of both properties are the same.|\n|`LIMIT`|Limit the results collection to the specified number.|\n\n> Example:\n> Use the query engine's sort, distinct, and limit operators to find to-do items\nwhere the assignee is Ali:\n>\n> - Sorted by priority in descending order\n> - Enforcing uniqueness by name\n> - Limiting the results to 5 items\n>\n> ```javascript\n> \"assignee == 'Ali' SORT(priority DESC) DISTINCT(name) LIMIT(5)\"\n>\n> ```\n>\n"
  },
  {
    "path": "docs/guides/test-and-debug/debugging.md",
    "content": "# Debugging - Java SDK\n## Android Studio Debugging\n> Important:\n> The Android Studio debugger can provide misleading values for\nRealm object fields. For correct values, you can watch\naccessor values instead, or use the Realm object\n`toString()` method to see the latest field values.\n>\n\nThis section details information you should keep in mind when debugging\nRealm applications with Android Studio to avoid incorrect\nvalue reporting. When you watch a Realm object,\nyou'll see values displayed in the object's fields. These values\nare incorrect because the field values themselves are not used. This is\nbecause Realm creates a proxy object behind the scenes, overriding\nthe getters and setters to access the persisted data in the\nrealm. To see the correct values, add a watch on the accessors.\n\nIn the image above, the debugger has stopped on line `113`. There are\nthree watch values:\n\n- The `person` variable\n- The `person.getName()` accessor\n- The `person.getAge()` accessor\n\nThe code from lines `107` to `111` alters the `person` instance by\nchanging the name and age in a write transaction. On line `113`, the `person` watch instance reports\nincorrect values for the *field* watch values. The watch values that use\nthe *accessors* report values that are correct.\n\n## NDK Debugging\nThe Realm Java SDK library contains native code.\nDebugging NDK crashes can be cumbersome, as the default stack trace\nprovides minimal information.\n\nWe recommend you use a crash reporting tool such as\n[Crashlytics](http://www.crashlytics.com/). This gives you the\nability to track native errors and gather other valuable information. We\ncan help with your issues faster if you have this information.\n\nTo enable NDK crash reporting in Crashlytics for\nyour project, add the following to the root of your application\n`build.gradle` file:\n\n```groovy\ncrashlytics {\n   enableNdk true\n}\n```\n\n> Note:\n> The values `androidNdkOut` and `androidNdkLibsOut` are not needed.\n>\n"
  },
  {
    "path": "docs/guides/test-and-debug/log-realm-events.md",
    "content": "# Log Realm Events - Java SDK\nThe SDK logs events to the Android system log automatically. You can\nview these events using [Logcat](https://developer.android.com//studio/debug/am-logcat).\n\n## Set the Client Log Level\nRealm uses the log levels defined by [Log4J](https://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/Level.html).\nTo configure the log level for Realm logs in your application, pass a\n`LogLevel` to\n`RealmLog.setLevel()`:\n\n#### Java\n\n```java\nRealmLog.setLevel(LogLevel.ALL);\n\n```\n\n#### Kotlin\n\n```kotlin\nRealmLog.setLevel(LogLevel.ALL)\n\n```\n\n> Tip:\n> To diagnose and troubleshoot errors while developing your application, set the\nlog level to `debug` or `trace`. For production deployments, decrease the\nlog level for improved performance.\n>\n"
  },
  {
    "path": "docs/guides/test-and-debug/testing.md",
    "content": "# Testing - Java SDK\nYou can test your application using unit tests or integration tests.\n**Unit tests** only assess the logic written in your application's code.\n**Integration tests** assess your application logic, database queries and\nwrites, and calls to your application's backend, if you have one. Unit tests\nrun on your development machine using the JVM, while integration tests\nrun on a physical or emulated Android device. You can run integration\ntests by communicating with actual instances of Realm\nor an App backend using Android's built-in instrumented tests.\n\nAndroid uses specific file paths and folder names in Android projects\nfor unit tests and instrumented tests:\n\n|Test Type|Path|\n| --- | --- |\n|Unit Tests|/app/src/test|\n|Instrumented Tests|/app/src/androidTest|\n\nBecause the SDK uses C++ code via Android Native for data\nstorage, unit testing requires you to entirely mock interactions with\nRealm. Prefer integration tests for logic that requires\nextensive interaction with the database.\n\n## Integration Tests\nThis section shows how to integration test an application that uses\nthe Realm SDK. It covers the following concepts in the test\nenvironment:\n\n- acquiring an application context\n- executing logic on a `Looper` thread\n- how to delay test execution while asynchronous method calls complete\n\n### Application Context\nTo initialize the SDK, you'll need to provide an application or activity\n[context](https://developer.android.com/reference/android/content/Context).\nThis isn't available by default in Android integration tests. However,\nyou can use Android's built-in testing [ActivityScenario](https://developer.android.com/reference/androidx/test/core/app/ActivityScenario)\nclass to start an activity in your tests. You can use any activity from\nyour application, or you can create an empty activity just for testing.\nCall `ActivityScenario.launch()` with your activity class as a\nparameter to start the simulated activity.\n\nNext, use the `ActivityScenario.onActivity()` method to run a lambda\non the simulated activity's main thread. In this lambda, you should call\nthe `Realm.init()` function to initialize the SDK with your activity\nas a parameter. Additionally, you should save the parameter passed to\nyour lambda (the newly created instance of your activity) for future\nuse.\n\nBecause the `onActivity()` method runs on a different thread, you\nshould block your test from executing further until this initial setup completes.\n\nThe following example uses an `ActivityScenario`, an empty testing\nactivity, and a `CountDownLatch` to demonstrate how to set up an\nenvironment where you can test your Realm application:\n\n#### Java\n\n```java\nAtomicReference<Activity> testActivity = new AtomicReference<Activity>();\nActivityScenario<BasicActivity> scenario = ActivityScenario.launch(BasicActivity.class);\n\n// create a latch to force blocking for an async call to initialize realm\nCountDownLatch setupLatch = new CountDownLatch(1);\n\nscenario.onActivity(activity -> {\n    Realm.init(activity);\n    testActivity.set(activity);\n    setupLatch.countDown(); // unblock the latch await\n});\n\n// block until we have an activity to run tests on\ntry {\n    Assert.assertTrue(setupLatch.await(1, TimeUnit.SECONDS));\n} catch (InterruptedException e) {\n    Log.e(\"EXAMPLE\", e.getMessage());\n}\n\n```\n\n#### Kotlin\n\n```kotlin\nvar testActivity: Activity? = null\nval scenario: ActivityScenario<BasicActivity>? =\n    ActivityScenario.launch(BasicActivity::class.java)\n\n// create a latch to force blocking for an async call to initialize realm\nval setupLatch = CountDownLatch(1)\n\nscenario?.onActivity{ activity: BasicActivity ->\n    Realm.init(activity)\n    testActivity = activity\n    setupLatch.countDown() // unblock the latch await\n}\n\n```\n\n### Looper Thread\nRealm functionality such as\nLive objects and change notifications only\nwork on [Looper](https://developer.android.com/reference/android/os/Looper) threads.\nThreads configured with a `Looper` object pass events over a message\nloop coordinated by the `Looper`. Test functions normally don't have\na `Looper` object, and configuring one to work in your tests can be\nvery error-prone.\n\nInstead, you can use the [Activity.runOnUiThread()](https://developer.android.com/reference/android/app/Activity#runOnUiThread(java.lang.Runnable))\nmethod of your test activity to execute logic on a thread that already\nhas a `Looper` configured. Combine `Activity.runOnUiThread()` with\na `CountDownLatch` as described in the delay section to prevent your test from completing\nand exiting before your logic has executed. Within the `runOnUiThread()`\ncall, you can interact with the SDK just like you normally would in your\napplication code:\n\n#### Java\n\n```java\ntestActivity.get().runOnUiThread(() -> {\n    // instantiate an app connection\n    String appID = YOUR_APP_ID; // replace this with your test application App ID\n    App app = new App(new AppConfiguration.Builder(appID).build());\n\n    // authenticate a user\n    Credentials credentials = Credentials.anonymous();\n    app.loginAsync(credentials, it -> {\n        if (it.isSuccess()) {\n            Log.v(\"EXAMPLE\", \"Successfully authenticated.\");\n\n            Realm.getInstanceAsync(config, new Realm.Callback() {\n                @Override\n                public void onSuccess(@NonNull Realm realm) {\n                    Log.v(\"EXAMPLE\", \"Successfully opened a realm.\");\n                    // read and write to realm here via transactions\n                    testLatch.countDown();\n                    realm.executeTransaction(new Realm.Transaction() {\n                        @Override\n                        public void execute(@NonNull Realm realm) {\n                            realm.createObjectFromJson(Frog.class,\n                                    \"{ name: \\\"Doctor Cucumber\\\", age: 1, species: \\\"bullfrog\\\", owner: \\\"Wirt\\\", _id: 0 }\");\n                        }\n                    });\n                    realm.close();\n                }\n                @Override\n                public void onError(@NonNull Throwable exception) {\n                    Log.e(\"EXAMPLE\", \"Failed to open the realm: \" + exception.getLocalizedMessage());\n                }\n            });\n        } else {\n            Log.e(\"EXAMPLE\", \"Failed login: \" + it.getError().getErrorMessage());\n        }\n    });\n});\n\n```\n\n#### Kotlin\n\n```kotlin\ntestActivity?.runOnUiThread {\n    // instantiate an app connection\n    val appID: String = YOUR_APP_ID // replace this with your App ID\n    val app = App(AppConfiguration.Builder(appID).build())\n\n    // authenticate a user\n    val credentials = Credentials.anonymous()\n    app.loginAsync(credentials) {\n        if (it.isSuccess) {\n            Log.v(\"EXAMPLE\", \"Successfully authenticated.\")\n\n            Realm.getInstanceAsync(config, object : Realm.Callback() {\n                override fun onSuccess(realm: Realm) {\n                    Log.v(\"EXAMPLE\", \"Successfully opened a realm.\")\n                    // read and write to realm here via transactions\n                    realm.executeTransaction {\n                        realm.createObjectFromJson(\n                            Frog::class.java,\n                            \"{ name: \\\"Doctor Cucumber\\\", age: 1, species: \\\"bullfrog\\\", owner: \\\"Wirt\\\", _id:0 }\"\n                        )\n                    }\n                    testLatch.countDown()\n                    realm.close()\n                }\n                override fun onError(exception: Throwable) {\n                    Log.e(\"EXAMPLE\",\n                        \"Failed to open the realm: \" + exception.localizedMessage)\n                }\n            })\n        } else {\n            Log.e(\"EXAMPLE\", \"Failed login: \" + it.error.errorMessage)\n        }\n    }\n}\n\n```\n\n### Delay Test Execution While Async Calls Complete\nBecause the SDK uses asynchronous calls for common operations, tests need a way\nto wait for those async calls to complete. Otherwise, your tests will\nexit before your asynchronous (or multi-threaded) calls run. This example\nuses Java's built-in [CountDownLatch](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/concurrent/CountDownLatch.html). Follow these steps to use a `CountDownLatch` in your own tests:\n\n1. Instantiate a `CountDownLatch` with a count of 1.\n2. After running the async logic your test needs to wait for, call that\n`CountDownLatch` instance's `countDown()` method.\n3. When you need to wait for async logic, add a `try`/`catch` block\nthat handles an `InterruptedException`. In that block,\ncall that `CountDownLatch` instance's `await()` method.\n4. Pass a timeout interval and unit to `await()`, and wrap\nthe call in a `Assert.assertTrue()` assertion. If the logic takes\ntoo long, the `await()` call times out, returning false and failing\nthe test.\n\n### Testing Backend\nApplications that use an App backend should not connect to the\nproduction backend for testing purposes for the following reasons:\n\n- you should always keep test users and production users separate\nfor security and privacy reasons\n- tests often require a clean initial state, so there's a good chance\nyour tests will include a setup or teardown method that deletes all\nusers or large chunks of data\n\nYou can use environments to manage separate\napps for testing and production.\n\n## Unit Tests\nTo unit test Realm applications that use Realm,\nyou must [mock](https://en.wikipedia.org/wiki/Mock_object) Realm (and your\napplication backend, if you use one). Use the following libraries to\nmock SDK functionality:\n\n- [Robolectric](http://robolectric.org/)\n- [PowerMock](https://powermock.github.io/)\n- [Mockito](https://site.mockito.org/)\n\nTo make these libraries available for unit testing in your Android project,\nadd the following to the `dependencies` block of your application\n`build.gradle` file:\n\n```\n testImplementation \"org.robolectric:robolectric:4.1\"\n testImplementation \"org.mockito:mockito-core:3.3.3\"\n testImplementation \"org.powermock:powermock-module-junit4:2.0.9\"\n testImplementation \"org.powermock:powermock-module-junit4-rule:2.0.9\"\n testImplementation \"org.powermock:powermock-api-mockito2:2.0.9\"\n testImplementation \"org.powermock:powermock-classloading-xstream:2.0.9\"\n```\n\n> Note:\n> Mocking the SDK in unit tests requires Robolectric, Mockito, and\nPowermock because the SDK uses Android Native C++ method calls to\ninteract with Realm. Because the frameworks required to\noverride these method calls can be delicate, you should use the\nversions listed above to ensure that your mocking is successful. Some\nrecent version updates (particularly Robolectric version 4.2+) can\nbreak compiliation of unit tests using the SDK.\n>\n\nTo configure your unit tests to use Robolectric, PowerMock, and Mockito\nwith the SDK, add the following annotations to each unit test class that\nmocks the SDK:\n\n#### Java\n\n```java\n@RunWith(RobolectricTestRunner.class)\n@Config(sdk = 28)\n@PowerMockIgnore({\"org.mockito.*\", \"org.robolectric.*\", \"android.*\", \"jdk.internal.reflect.*\", \"androidx.*\"})\n@SuppressStaticInitializationFor(\"io.realm.internal.Util\")\n@PrepareForTest({Realm.class, RealmConfiguration.class, RealmQuery.class, RealmResults.class, RealmCore.class, RealmLog.class})\n\n```\n\n#### Kotlin\n\n```kotlin\n@RunWith(RobolectricTestRunner::class)\n@Config(sdk = [28])\n@PowerMockIgnore(\n    \"org.mockito.*\",\n    \"org.robolectric.*\",\n    \"android.*\",\n    \"jdk.internal.reflect.*\",\n    \"androidx.*\"\n)\n@SuppressStaticInitializationFor(\"io.realm.internal.Util\")\n@PrepareForTest(\n    Realm::class,\n    RealmConfiguration::class,\n    RealmQuery::class,\n    RealmResults::class,\n    RealmCore::class,\n    RealmLog::class\n)\n\n```\n\nThen, bootstrap Powermock globally in the test class:\n\n#### Java\n\n```java\n// bootstrap powermock\n@Rule\npublic PowerMockRule rule = new PowerMockRule();\n\n```\n\n#### Kotlin\n\n```kotlin\n// bootstrap powermock\n@Rule\nvar rule = PowerMockRule()\n\n```\n\nNext, mock the components of the SDK that might query native C++ code\nso we don't hit the limitations of the test environment:\n\n#### Java\n\n```java\n// set up realm SDK components to be mocked. The order of these matters\nmockStatic(RealmCore.class);\nmockStatic(RealmLog.class);\nmockStatic(Realm.class);\nmockStatic(RealmConfiguration.class);\nRealm.init(RuntimeEnvironment.application);\n// boilerplate to mock realm components -- this prevents us from hitting any\n// native code\ndoNothing().when(RealmCore.class);\nRealmCore.loadLibrary(any(Context.class));\n\n```\n\n#### Kotlin\n\n```kotlin\n// set up realm SDK components to be mocked. The order of these matters\nPowerMockito.mockStatic(RealmCore::class.java)\nPowerMockito.mockStatic(RealmLog::class.java)\nPowerMockito.mockStatic(Realm::class.java)\nPowerMockito.mockStatic(RealmConfiguration::class.java)\nRealm.init(RuntimeEnvironment.application)\nPowerMockito.doNothing().`when`(RealmCore::class.java)\nRealmCore.loadLibrary(ArgumentMatchers.any(Context::class.java))\n\n```\n\nOnce you've completed the setup required for mocking, you can start\nmocking components and wiring up behavior for your tests. You can also\nconfigure PowerMockito to return specific objects when new objects of\na type are instantiated, so even code that references the default\nrealm in your application won't break your tests:\n\n#### Java\n\n```java\n// create the mocked realm\nfinal Realm mockRealm = mock(Realm.class);\nfinal RealmConfiguration mockRealmConfig = mock(RealmConfiguration.class);\n// use this mock realm config for all new realm configurations\nwhenNew(RealmConfiguration.class).withAnyArguments().thenReturn(mockRealmConfig);\n// use this mock realm for all new default realms\nwhen(Realm.getDefaultInstance()).thenReturn(mockRealm);\n\n```\n\n#### Kotlin\n\n```kotlin\n// create the mocked realm\nval mockRealm = PowerMockito.mock(Realm::class.java)\nval mockRealmConfig = PowerMockito.mock(\n    RealmConfiguration::class.java\n)\n// use this mock realm config for all new realm configurations\nPowerMockito.whenNew(RealmConfiguration::class.java).withAnyArguments()\n    .thenReturn(mockRealmConfig)\n// use this mock realm for all new default realms\nPowerMockito.`when`(Realm.getDefaultInstance()).thenReturn(mockRealm)\n\n```\n\nAfter mocking a realm, you'll have to configure data for your test\ncases. See the full example below for some examples of how you can\nprovide testing data in unit tests.\n\n### Full Example\nThe following example shows a full JUnit `test`\nexample mocking Realm in unit tests. This example tests\nan activity that performs some basic Realm operations.\nThe tests use mocking to simulate those operations when that activity is\nstarted during a unit test:\n\n#### Java\n\n```java\npackage com.mongodb.realm.examples.java;\n\nimport androidx.appcompat.app.AppCompatActivity;\n\nimport android.os.Bundle;\n\nimport android.os.AsyncTask;\nimport android.util.Log;\nimport android.widget.LinearLayout;\nimport android.widget.TextView;\n\nimport com.mongodb.realm.examples.R;\nimport com.mongodb.realm.examples.model.java.Cat;\n\nimport io.realm.Realm;\nimport io.realm.RealmResults;\n\npublic class UnitTestActivity extends AppCompatActivity {\n\n    public static final String TAG = UnitTestActivity.class.getName();\n    private LinearLayout rootLayout = null;\n\n    private Realm realm;\n\n    @Override\n    protected void onCreate(Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n        Realm.init(getApplicationContext());\n        setContentView(R.layout.activity_unit_test);\n        rootLayout = findViewById(R.id.container);\n        rootLayout.removeAllViews();\n\n        // open the default Realm for the UI thread.\n        realm = Realm.getDefaultInstance();\n\n        // clean up from previous run\n        cleanUp();\n\n        // small operation that is ok to run on the main thread\n        basicCRUD(realm);\n\n        // more complex operations can be executed on another thread.\n        AsyncTask<Void, Void, String> foo = new AsyncTask<Void, Void, String>() {\n            @Override\n            protected String doInBackground(Void... voids) {\n                String info = \"\";\n                info += complexQuery();\n                return info;\n            }\n\n            @Override\n            protected void onPostExecute(String result) {\n                showStatus(result);\n            }\n        };\n\n        foo.execute();\n\n        findViewById(R.id.clean_up).setOnClickListener(view -> {\n            view.setEnabled(false);\n            Log.d(\"TAG\", \"clean up\");\n            cleanUp();\n            view.setEnabled(true);\n        });\n    }\n\n    private void cleanUp() {\n        // delete all cats\n        realm.executeTransaction(r -> r.delete(Cat.class));\n    }\n\n    @Override\n    public void onDestroy() {\n        super.onDestroy();\n        realm.close(); // remember to close realm when done.\n    }\n\n    private void showStatus(String txt) {\n        Log.i(TAG, txt);\n        TextView tv = new TextView(this);\n        tv.setText(txt);\n        rootLayout.addView(tv);\n    }\n\n    private void basicCRUD(Realm realm) {\n        showStatus(\"Perform basic Create/Read/Update/Delete (CRUD) operations...\");\n\n        // all writes must be wrapped in a transaction to facilitate safe multi threading\n        realm.executeTransaction(r -> {\n            // add a cat\n            Cat cat = r.createObject(Cat.class);\n            cat.setName(\"John Young\");\n        });\n\n        // find the first cat (no query conditions) and read a field\n        final Cat cat = realm.where(Cat.class).findFirst();\n        showStatus(cat.getName());\n\n        // update cat in a transaction\n        realm.executeTransaction(r -> {\n            cat.setName(\"John Senior\");\n        });\n\n        showStatus(cat.getName());\n\n        // add two more cats\n        realm.executeTransaction(r -> {\n            Cat jane = r.createObject(Cat.class);\n            jane.setName(\"Jane\");\n\n            Cat doug = r.createObject(Cat.class);\n            doug.setName(\"Robert\");\n        });\n\n        RealmResults<Cat> cats = realm.where(Cat.class).findAll();\n        showStatus(String.format(\"Found %s cats\", cats.size()));\n        for (Cat p : cats) {\n            showStatus(\"Found \" + p.getName());\n        }\n    }\n\n    private String complexQuery() {\n        String status = \"\\n\\nPerforming complex Query operation...\";\n\n        Realm realm = Realm.getDefaultInstance();\n        status += \"\\nNumber of cats in the DB: \" + realm.where(Cat.class).count();\n\n        // find all cats where name begins with \"J\".\n        RealmResults<Cat> results = realm.where(Cat.class)\n                .beginsWith(\"name\", \"J\")\n                .findAll();\n        status += \"\\nNumber of cats whose name begins with 'J': \" + results.size();\n\n        realm.close();\n        return status;\n    }\n}\n\n```\n\n```java\nimport android.content.Context;\n\nimport com.mongodb.realm.examples.java.UnitTestActivity;\nimport com.mongodb.realm.examples.model.java.Cat;\n\nimport org.junit.Before;\nimport org.junit.Rule;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.powermock.core.classloader.annotations.PowerMockIgnore;\nimport org.powermock.core.classloader.annotations.PrepareForTest;\nimport org.powermock.core.classloader.annotations.SuppressStaticInitializationFor;\nimport org.powermock.modules.junit4.rule.PowerMockRule;\nimport org.robolectric.Robolectric;\nimport org.robolectric.RobolectricTestRunner;\nimport org.robolectric.RuntimeEnvironment;\nimport org.robolectric.annotation.Config;\n\nimport java.util.Arrays;\nimport java.util.List;\n\nimport io.realm.Realm;\nimport io.realm.RealmConfiguration;\nimport io.realm.RealmObject;\nimport io.realm.RealmQuery;\nimport io.realm.RealmResults;\nimport io.realm.internal.RealmCore;\nimport io.realm.log.RealmLog;\n\nimport com.mongodb.realm.examples.R;\n\nimport static org.mockito.Matchers.any;\nimport static org.mockito.Matchers.anyInt;\nimport static org.mockito.Matchers.anyString;\nimport static org.mockito.Mockito.doCallRealMethod;\nimport static org.mockito.Mockito.times;\nimport static org.mockito.Mockito.verify;\nimport static org.powermock.api.mockito.PowerMockito.doNothing;\nimport static org.powermock.api.mockito.PowerMockito.mock;\nimport static org.powermock.api.mockito.PowerMockito.mockStatic;\nimport static org.powermock.api.mockito.PowerMockito.when;\nimport static org.powermock.api.mockito.PowerMockito.whenNew;\n\n@RunWith(RobolectricTestRunner.class)\n@Config(sdk = 28)\n@PowerMockIgnore({\"org.mockito.*\", \"org.robolectric.*\", \"android.*\", \"jdk.internal.reflect.*\", \"androidx.*\"})\n@SuppressStaticInitializationFor(\"io.realm.internal.Util\")\n@PrepareForTest({Realm.class, RealmConfiguration.class, RealmQuery.class, RealmResults.class, RealmCore.class, RealmLog.class})\npublic class TestTest {\n    // bootstrap powermock\n    @Rule\n    public PowerMockRule rule = new PowerMockRule();\n\n    // mocked realm SDK components for tests\n    private Realm mockRealm;\n    private RealmResults<Cat> cats;\n\n    @Before\n    public void setup() throws Exception {\n        // set up realm SDK components to be mocked. The order of these matters\n        mockStatic(RealmCore.class);\n        mockStatic(RealmLog.class);\n        mockStatic(Realm.class);\n        mockStatic(RealmConfiguration.class);\n        Realm.init(RuntimeEnvironment.application);\n        // boilerplate to mock realm components -- this prevents us from hitting any\n        // native code\n        doNothing().when(RealmCore.class);\n        RealmCore.loadLibrary(any(Context.class));\n\n        // create the mocked realm\n        final Realm mockRealm = mock(Realm.class);\n        final RealmConfiguration mockRealmConfig = mock(RealmConfiguration.class);\n        // use this mock realm config for all new realm configurations\n        whenNew(RealmConfiguration.class).withAnyArguments().thenReturn(mockRealmConfig);\n        // use this mock realm for all new default realms\n        when(Realm.getDefaultInstance()).thenReturn(mockRealm);\n\n        // any time we ask Realm to create a Cat, return a new instance.\n        when(mockRealm.createObject(Cat.class)).thenReturn(new Cat());\n\n        // set up test data\n        Cat p1 = new Cat();\n        p1.setName(\"Enoch\");\n        Cat p2 = new Cat();\n        p2.setName(\"Quincy Endicott\");\n        Cat p3 = new Cat();\n        p3.setName(\"Sara\");\n        Cat p4 = new Cat();\n        p4.setName(\"Jimmy Brown\");\n        List<Cat> catList = Arrays.asList(p1, p2, p3, p4);\n\n        // create a mocked RealmQuery\n        RealmQuery<Cat> catQuery = mockRealmQuery();\n        // when the RealmQuery performs findFirst, return the first record in the list.\n        when(catQuery.findFirst()).thenReturn(catList.get(0));\n        // when the where clause is called on the Realm, return the mock query.\n        when(mockRealm.where(Cat.class)).thenReturn(catQuery);\n        // when the RealmQuery is filtered on any string and any integer, return the query\n        when(catQuery.equalTo(anyString(), anyInt())).thenReturn(catQuery);\n        // when a between query is performed with any string as the field and any int as the\n        // value, then return the catQuery itself\n        when(catQuery.between(anyString(), anyInt(), anyInt())).thenReturn(catQuery);\n        // When a beginsWith clause is performed with any string field and any string value\n        // return the same cat query\n        when(catQuery.beginsWith(anyString(), anyString())).thenReturn(catQuery);\n\n        // RealmResults is final, must mock static and also place this in the PrepareForTest\n        // annotation array.\n        mockStatic(RealmResults.class);\n        // create a mock RealmResults\n        RealmResults<Cat> cats = mockRealmResults();\n        // the for(...) loop in Java needs an iterator, so we're giving it one that has items,\n        // since the mock RealmResults does not provide an implementation. Therefore, any time\n        // anyone asks for the RealmResults Iterator, give them a functioning iterator from the\n        // ArrayList of Cats we created above. This will allow the loop to execute.\n        when(cats.iterator()).thenReturn(catList.iterator());\n        // Return the size of the mock list.\n        when(cats.size()).thenReturn(catList.size());\n\n        // when we ask Realm for all of the Cat instances, return the mock RealmResults\n        when(mockRealm.where(Cat.class).findAll()).thenReturn(cats);\n        // when we ask the RealmQuery for all of the Cat objects, return the mock RealmResults\n        when(catQuery.findAll()).thenReturn(cats);\n\n        this.mockRealm = mockRealm;\n        this.cats = cats;\n    }\n\n    @Test\n    public void shouldBeAbleToAccessActivityAndVerifyRealmInteractions() {\n        doCallRealMethod().when(mockRealm)\n                .executeTransaction(any(Realm.Transaction.class));\n\n        // create test activity --  onCreate method calls methods that\n        // query/write to realm\n        UnitTestActivity activity = Robolectric\n                .buildActivity(UnitTestActivity.class)\n                .create()\n                .start()\n                .resume()\n                .visible()\n                .get();\n\n        // click the clean up button\n        activity.findViewById(R.id.clean_up).performClick();\n\n        // verify that we queried for Cat instances five times in this run\n        // (2 in basicCrud(), 2 in complexQuery() and 1 in the button click)\n        verify(mockRealm, times(5)).where(Cat.class);\n\n        // verify that the delete method was called. We also call delete at\n        // the start of the activity to ensure we start with a clean db.\n        verify(mockRealm, times(2)).delete(Cat.class);\n\n        // call the destroy method so we can verify that the .close() method\n        // was called (below)\n        activity.onDestroy();\n\n        // verify that the realm got closed 2 separate times. Once in the\n        // AsyncTask, once in onDestroy\n        verify(mockRealm, times(2)).close();\n    }\n\n    @SuppressWarnings(\"unchecked\")\n    private <T extends RealmObject> RealmQuery<T> mockRealmQuery() {\n        return mock(RealmQuery.class);\n    }\n\n    @SuppressWarnings(\"unchecked\")\n    private <T extends RealmObject> RealmResults<T> mockRealmResults() {\n        return mock(RealmResults.class);\n    }\n}\n\n```\n\n#### Kotlin\n\n```kotlin\npackage com.mongodb.realm.examples.kotlin\n\nimport android.os.AsyncTask\nimport android.os.Bundle\nimport android.util.Log\nimport android.view.View\nimport android.widget.LinearLayout\nimport android.widget.TextView\nimport androidx.appcompat.app.AppCompatActivity\nimport com.mongodb.realm.examples.R\nimport com.mongodb.realm.examples.model.java.Cat\nimport io.realm.Realm\n\nclass UnitTestActivity : AppCompatActivity() {\n    private var rootLayout: LinearLayout? = null\n    private var realm: Realm? = null\n    override fun onCreate(savedInstanceState: Bundle?) {\n        super.onCreate(savedInstanceState)\n        Realm.init(applicationContext)\n        setContentView(R.layout.activity_unit_test)\n        rootLayout = findViewById(R.id.container)\n        rootLayout!!.removeAllViews()\n\n        // open the default Realm for the UI thread.\n        realm = Realm.getDefaultInstance()\n\n        // clean up from previous run\n        cleanUp()\n\n        // small operation that is ok to run on the main thread\n        basicCRUD(realm)\n\n        // more complex operations can be executed on another thread.\n        val foo: AsyncTask<Void?, Void?, String> = object : AsyncTask<Void?, Void?, String>() {\n            protected override fun doInBackground(vararg params: Void?): String? {\n                var info = \"\"\n                info += complexQuery()\n                return info\n            }\n\n            override fun onPostExecute(result: String) {\n                showStatus(result)\n            }\n        }\n        foo.execute()\n        findViewById<View>(R.id.clean_up).setOnClickListener { view: View ->\n            view.isEnabled = false\n            Log.d(\"TAG\", \"clean up\")\n            cleanUp()\n            view.isEnabled = true\n        }\n    }\n\n    private fun cleanUp() {\n        // delete all cats\n        realm!!.executeTransaction { r: Realm -> r.delete(Cat::class.java) }\n    }\n\n    public override fun onDestroy() {\n        super.onDestroy()\n        realm!!.close() // remember to close realm when done.\n    }\n\n    private fun showStatus(txt: String) {\n        Log.i(TAG, txt)\n        val tv = TextView(this)\n        tv.text = txt\n        rootLayout!!.addView(tv)\n    }\n\n    private fun basicCRUD(realm: Realm?) {\n        showStatus(\"Perform basic Create/Read/Update/Delete (CRUD) operations...\")\n\n        // all writes must be wrapped in a transaction to facilitate safe multi threading\n        realm!!.executeTransaction { r: Realm ->\n            // add a cat\n            val cat = r.createObject(Cat::class.java)\n            cat.name = \"John Young\"\n        }\n\n        // find the first cat (no query conditions) and read a field\n        val cat = realm.where(Cat::class.java).findFirst()\n        showStatus(cat!!.name)\n\n        // update cat in a transaction\n        realm.executeTransaction { r: Realm? ->\n            cat.name = \"John Senior\"\n        }\n        showStatus(cat.name)\n\n        // add two more cats\n        realm.executeTransaction { r: Realm ->\n            val jane = r.createObject(Cat::class.java)\n            jane.name = \"Jane\"\n            val doug = r.createObject(Cat::class.java)\n            doug.name = \"Robert\"\n        }\n        val cats = realm.where(Cat::class.java).findAll()\n        showStatus(String.format(\"Found %s cats\", cats.size))\n        for (p in cats) {\n            showStatus(\"Found \" + p.name)\n        }\n    }\n\n    private fun complexQuery(): String {\n        var status = \"\\n\\nPerforming complex Query operation...\"\n        val realm = Realm.getDefaultInstance()\n        status += \"\"\"\n\n            Number of cats in the DB: ${realm.where(Cat::class.java).count()}\n            \"\"\".trimIndent()\n\n        // find all cats where name begins with \"J\".\n        val results = realm.where(Cat::class.java)\n            .beginsWith(\"name\", \"J\")\n            .findAll()\n        status += \"\"\"\n\n            Number of cats whose name begins with 'J': ${results.size}\n            \"\"\".trimIndent()\n        realm.close()\n        return status\n    }\n\n    companion object {\n        val TAG = UnitTestActivity::class.java.name\n    }\n}\n\n```\n\n```kotlin\nimport android.content.Context\nimport android.view.View\nimport com.mongodb.realm.examples.R\nimport com.mongodb.realm.examples.kotlin.UnitTestActivity\nimport com.mongodb.realm.examples.model.java.Cat\nimport io.realm.Realm\nimport io.realm.RealmConfiguration\nimport io.realm.RealmObject\nimport io.realm.RealmQuery\nimport io.realm.RealmResults\nimport io.realm.internal.RealmCore\nimport io.realm.log.RealmLog\nimport java.lang.Exception\nimport java.util.*\nimport org.junit.Before\nimport org.junit.Rule\nimport org.junit.Test\nimport org.junit.runner.RunWith\nimport org.mockito.ArgumentMatchers\nimport org.mockito.Mockito\nimport org.powermock.api.mockito.PowerMockito\nimport org.powermock.core.classloader.annotations.PowerMockIgnore\nimport org.powermock.core.classloader.annotations.PrepareForTest\nimport org.powermock.core.classloader.annotations.SuppressStaticInitializationFor\nimport org.powermock.modules.junit4.rule.PowerMockRule\nimport org.robolectric.Robolectric\nimport org.robolectric.RobolectricTestRunner\nimport org.robolectric.RuntimeEnvironment\nimport org.robolectric.annotation.Config\n\n@RunWith(RobolectricTestRunner::class)\n@Config(sdk = [28])\n@PowerMockIgnore(\n    \"org.mockito.*\",\n    \"org.robolectric.*\",\n    \"android.*\",\n    \"jdk.internal.reflect.*\",\n    \"androidx.*\"\n)\n@SuppressStaticInitializationFor(\"io.realm.internal.Util\")\n@PrepareForTest(\n    Realm::class,\n    RealmConfiguration::class,\n    RealmQuery::class,\n    RealmResults::class,\n    RealmCore::class,\n    RealmLog::class\n)\nclass TestTest {\n    // bootstrap powermock\n    @Rule\n    var rule = PowerMockRule()\n\n    // mocked realm SDK components for tests\n    private var mockRealm: Realm? = null\n    private var cats: RealmResults<Cat>? = null\n    @Before\n    @Throws(Exception::class)\n    fun setup() {\n        // set up realm SDK components to be mocked. The order of these matters\n        PowerMockito.mockStatic(RealmCore::class.java)\n        PowerMockito.mockStatic(RealmLog::class.java)\n        PowerMockito.mockStatic(Realm::class.java)\n        PowerMockito.mockStatic(RealmConfiguration::class.java)\n        Realm.init(RuntimeEnvironment.application)\n        PowerMockito.doNothing().`when`(RealmCore::class.java)\n        RealmCore.loadLibrary(ArgumentMatchers.any(Context::class.java))\n\n        // create the mocked realm\n        val mockRealm = PowerMockito.mock(Realm::class.java)\n        val mockRealmConfig = PowerMockito.mock(\n            RealmConfiguration::class.java\n        )\n        // use this mock realm config for all new realm configurations\n        PowerMockito.whenNew(RealmConfiguration::class.java).withAnyArguments()\n            .thenReturn(mockRealmConfig)\n        // use this mock realm for all new default realms\n        PowerMockito.`when`(Realm.getDefaultInstance()).thenReturn(mockRealm)\n\n        // any time we ask Realm to create a Cat, return a new instance.\n        PowerMockito.`when`(mockRealm.createObject(Cat::class.java)).thenReturn(Cat())\n\n        // set up test data\n        val p1 = Cat()\n        p1.name = \"Enoch\"\n        val p2 = Cat()\n        p2.name = \"Quincy Endicott\"\n        val p3 = Cat()\n        p3.name = \"Sara\"\n        val p4 = Cat()\n        p4.name = \"Jimmy Brown\"\n        val catList = Arrays.asList(p1, p2, p3, p4)\n\n        // create a mocked RealmQuery\n        val catQuery = mockRealmQuery<Cat>()\n        // when the RealmQuery performs findFirst, return the first record in the list.\n        PowerMockito.`when`(catQuery!!.findFirst()).thenReturn(catList[0])\n        // when the where clause is called on the Realm, return the mock query.\n        PowerMockito.`when`(mockRealm.where(Cat::class.java)).thenReturn(catQuery)\n        // when the RealmQuery is filtered on any string and any integer, return the query\n        PowerMockito.`when`(\n            catQuery.equalTo(\n                ArgumentMatchers.anyString(),\n                ArgumentMatchers.anyInt()\n            )\n        ).thenReturn(catQuery)\n        // when a between query is performed with any string as the field and any int as the\n        // value, then return the catQuery itself\n        PowerMockito.`when`(\n            catQuery.between(\n                ArgumentMatchers.anyString(),\n                ArgumentMatchers.anyInt(),\n                ArgumentMatchers.anyInt()\n            )\n        ).thenReturn(catQuery)\n        // When a beginsWith clause is performed with any string field and any string value\n        // return the same cat query\n        PowerMockito.`when`(\n            catQuery.beginsWith(\n                ArgumentMatchers.anyString(),\n                ArgumentMatchers.anyString()\n            )\n        ).thenReturn(catQuery)\n\n        // RealmResults is final, must mock static and also place this in the PrepareForTest\n        // annotation array.\n        PowerMockito.mockStatic(RealmResults::class.java)\n        // create a mock RealmResults\n        val cats = mockRealmResults<Cat>()\n        // the for(...) loop in Java needs an iterator, so we're giving it one that has items,\n        // since the mock RealmResults does not provide an implementation. Therefore, any time\n        // anyone asks for the RealmResults Iterator, give them a functioning iterator from the\n        // ArrayList of Cats we created above. This will allow the loop to execute.\n        PowerMockito.`when`<Iterator<Cat>>(cats!!.iterator()).thenReturn(catList.iterator())\n        // Return the size of the mock list.\n        PowerMockito.`when`(cats.size).thenReturn(catList.size)\n\n        // when we ask Realm for all of the Cat instances, return the mock RealmResults\n        PowerMockito.`when`(mockRealm.where(Cat::class.java).findAll()).thenReturn(cats)\n        // when we ask the RealmQuery for all of the Cat objects, return the mock RealmResults\n        PowerMockito.`when`(catQuery.findAll()).thenReturn(cats)\n        this.mockRealm = mockRealm\n        this.cats = cats\n    }\n\n    @Test\n    fun shouldBeAbleToAccessActivityAndVerifyRealmInteractions() {\n        Mockito.doCallRealMethod().`when`(mockRealm)!!\n            .executeTransaction(ArgumentMatchers.any(Realm.Transaction::class.java))\n\n        // create test activity --  onCreate method calls methods that\n        // query/write to realm\n        val activity = Robolectric\n            .buildActivity(UnitTestActivity::class.java)\n            .create()\n            .start()\n            .resume()\n            .visible()\n            .get()\n\n        // click the clean up button\n        activity.findViewById<View>(R.id.clean_up).performClick()\n\n        // verify that we queried for Cat instances five times in this run\n        // (2 in basicCrud(), 2 in complexQuery() and 1 in the button click)\n        Mockito.verify(mockRealm, Mockito.times(5))!!.where(Cat::class.java)\n\n        // verify that the delete method was called. We also call delete at\n        // the start of the activity to ensure we start with a clean db.\n        Mockito.verify(mockRealm, Mockito.times(2))!!.delete(Cat::class.java)\n\n        // call the destroy method so we can verify that the .close() method\n        // was called (below)\n        activity.onDestroy()\n\n        // verify that the realm got closed 2 separate times. Once in the\n        // AsyncTask, once in onDestroy\n        Mockito.verify(mockRealm, Mockito.times(2))!!.close()\n    }\n\n    private fun <T : RealmObject?> mockRealmQuery(): RealmQuery<T>? {\n        @Suppress(\"UNCHECKED_CAST\")\n        return PowerMockito.mock(RealmQuery::class.java) as RealmQuery<T>\n    }\n\n    private fun <T : RealmObject?> mockRealmResults(): RealmResults<T>? {\n        @Suppress(\"UNCHECKED_CAST\")\n        return PowerMockito.mock(RealmResults::class.java) as RealmResults<T>\n    }\n}\n\n```\n\n> Seealso:\n> See the [Unit Testing Example App](https://github.com/realm/realm-java/tree/master/examples/unitTestExample)\nfor an example of unit testing an application that uses\nRealm.\n>\n"
  },
  {
    "path": "docs/guides/test-and-debug/troubleshooting.md",
    "content": "# Troubleshooting - Java SDK\n## Couldn't load \"librealm-jni.so\"\nIf your app uses native libraries that don't ship with support for\n64-bit architectures, Android will fail to load Realm's\n`librealm-jni.so` file on ARM64 devices. This happens because Android\ncannot load 32-bit and 64-bit native libraries concurrently. Ideally,\nall libraries could provide the same set of supported ABIs, but\nsometimes that may not be doable when using a 3rd-party library.\n\nTo work around this issue, you can exclude Realm's ARM64 library from\nthe APK file by adding the following code to the application's\n`build.gradle`. You can refer to Mixing 32- and 64-bit Dependencies in Android for more information.\n\n```gradle\nandroid {\n    //...\n    packagingOptions {\n        exclude \"lib/arm64-v8a/librealm-jni.so\"\n    }\n    //...\n}\n```\n\n> Seealso:\n> For more information, see [Mixing 32- and 64-bit Dependencies in Android](https://corbt.com/posts/2015/09/18/mixing-32-and-64bit-dependencies-in-android.html).\n>\n\n## Network Calls to Mixpanel\nRealm collects anonymous analytics when you run the\nRealm bytecode transformer on your source code. This is\ncompletely anonymous and helps us improve the product by flagging:\n\n- which version of the SDK you use\n- which operating system you use\n- if your application uses Kotlin\n\nAnalytics do not run when your application runs on user devices - only\nwhen you compile your source code. To opt out of analytics, you can set\nthe `REALM_DISABLE_ANALYTICS` environment variable to `true`.\n\n## Change Listeners in Android 12 with SDK Versions Below 10.5.1\nDue to a change in the Linux kernel,\nobject, collection, and realm notifications do not work in SDK versions below\n10.5.1 on devices running certain early versions of\nAndroid 12.\n\nThis change effects Linux kernel versions beginning with `5.5`.\nLinux kernel version `5.14-rc4` fixed the issue. The fix was\nalso backported to `LTS 5.10.56` and `LTS 5.13.8`. All mainline\nand LTS Android 12 branches contain the fix or a backport of it.\n\nIf you experience this issue, you can restore notification functionality\nwith the following fixes:\n\n- upgrade to a version of the SDK later than 10.5.1.\n- upgrade to a version of Android 12 that uses a Linux kernel release\nthat contains the fix (kernel commit `3a34b13a88caeb2800ab44a4918f230041b37dd9`)\nor the backport of the fix (kernel commit `4b20d2de0b367bca627b49efd8d2e9e01bb66753`).\n\n## Configurations Cannot be Different if Used to Open the Same File\nRealm runs checks whenever you open a realm file to\navoid corruption. In order to avoid accidentally opening a realm\nfile with incompatible settings, the SDK uses Java's `equals()` method\nto compare `RealmConfiguration` objects. This prevents the SDK from\nopening a single realm file with different schemas, durability levels,\nor writability settings. However, configurations that include lambda\nfunctions, such as those passed to\n`initialData()`\nand\n`compactOnLaunch()`,\ncan break this `equals()` comparison, since two different lambdas are\nnever considered equal using Java's built-in comparison.\nTo avoid this error when using lambdas, you can either:\n\n1. Store a single configuration statically in your application, so that\nseparate realm instances use the exact same\n`RealmConfiguration` object and it passes the check.\n2. Override the default equals check of the `RealmConfiguration`: `val config = RealmConfiguration.Builder()\n     .initialData(object: Realm.Transaction {\n         override fun execute(realm: Realm) {\n             TODO(\"Not yet implemented\")\n         }\n\n         override fun equals(other: Any?): Boolean {\n             return true\n         }\n\n         override fun hashCode(): Int {\n             return 37\n         }\n     }).build()`\n\n## Kapt Exceptions During Builds\nIf you experience an exception in the Kapt library with a description\nlike the following:\n\n```\nA failure occurred while executing org.jetbrains.kotlin.gradle.internal.KaptWithoutKotlincTask$KaptExecutionWorkAction\n```\n\nThis most likely means there is an issue with one of your model classes.\nPossible causes include:\n\n- introducing a field type that is not supported by the SDK\n- using a visibility type other than `open` or `public` for a realm object model class\n- using a Realm annotation on an incompatible field\n\nIf you experience this error, check any recent updates to your schema for\nproblems.\n\n## Installation Size\nOnce your app is built for release and split for distribution, the SDK\nshould only add about 800KB to your APK in most cases. The releases are\nsignificantly larger because they include support for more architectures,\nsuch as ARM7, ARMv7, ARM64, x86, and MIPS. The APK file contains all\nsupported architectures, but the Android installer only installs native\ncode for the device's architecture. This means that the installed app\nis smaller than the size of the APK file.\n\nYou can reduce the size of the Android APK itself by splitting the APK\ninto a version for each architecture. Use the Android Build Tool ABI\nSplit support by adding the following to your build.gradle:\n\n```gradle\nandroid {\n    splits {\n        abi {\n            enable true\n            reset()\n            include 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64'\n        }\n    }\n}\n```\n\nSelect the architectures that you'd like to include to build a separate\nAPK for each.\n\n> Seealso:\n> See the [Android Tools documentation about ABI Splits](https://developer.android.com/studio/build/configure-apk-splits.html)\nfor more information, or the [example on GitHub](https://github.com/realm/realm-java/tree/master/examples/gridViewExample).\n>\n\nIf you don't want to handle multiple APKs, you can restrict the number\nof architectures supported in a single APK. This is done by adding\n`abiFilters` to your build.gradle:\n\n```gradle\nandroid {\n    defaultConfig {\n        ndk {\n            abiFilters 'armeabi-v7a', 'arm64-v8a', 'mips', 'x86', 'x86_64'\n        }\n    }\n}\n```\n\n> Seealso:\n> [Controlling APK Size When Using Native Libraries](https://medium.com/android-news/controlling-apk-size-when-using-native-libraries-45c6c0e5b70a).\n>\n\n## Customize Dependencies Defined by the Realm Gradle Plugin\nRealm uses a Gradle plugin because it makes it easier to set\nup a large number of dependencies. Unfortunately this also makes it a\nbit harder to ignore specific transitive dependencies.\n\nIf you want to customize Realm beyond what is exposed by the\nplugin, you can manually set up all the dependencies and ignore the\nGradle plugin. The following example demonstrates how to set up the SDK\nfor an Android application using Kotlin manually:\n\n```gradle\nbuildscript {\n    ext.kotlin_version = '1.5.21'\n    ext.realm_version = '10.18.0'\n    repositories {\n        jcenter()\n        mavenCentral()\n    }\n    dependencies {\n        classpath \"io.realm:realm-transformer:$realm_version\"\n        classpath \"org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version\"\n    }\n}\n\napply plugin: 'com.android.application'\napply plugin: 'kotlin-android'\napply plugin: 'kotlin-kapt'\n\nimport io.realm.transformer.RealmTransformer\nandroid.registerTransform(new RealmTransformer(project))\n\ndependencies {\n  api \"io.realm:realm-annotations:$realm_version\"\n  api \"io.realm:realm-android-library:$realm_version\"\n  api \"io.realm:realm-android-kotlin-extensions:$realm_version\"\n  kapt \"io.realm:realm-annotations-processor:$realm_version\"\n}\n```\n"
  },
  {
    "path": "docs/guides/troubleshooting.md",
    "content": "# Troubleshooting - Java SDK\n## Use in System Apps on Custom Android ROMs\nRealm SDKs use named pipes to support notifications and access to\nthe Realm file from multiple processes. While this is allowed by\ndefault for normal user apps, it is disallowed for system apps.\n\nSystem apps are defined by setting `android:sharedUserId=\"android.uid.system\"`\nin the Android manifest. For system apps, you may see a security violation in\nLogcat that looks something like this:\n\n```bash\n05-24 14:08:08.984  6921  6921 W .realmsystemapp: type=1400 audit(0.0:99): avc: denied { write } for name=\"realm.testapp.com.realmsystemapp-Bfqpnjj4mUvxWtfMcOXBCA==\" dev=\"vdc\" ino=14660 scontext=u:r:system_app:s0 tcontext=u:object_r:apk_data_file:s0 tclass=dir permissive=0\n05-24 14:08:08.984  6921  6921 W .realmsystemapp: type=1400 audit(0.0:100): avc: denied { write } for name=\"realm.testapp.com.realmsystemapp-Bfqpnjj4mUvxWtfMcOXBCA==\" dev=\"vdc\" ino=14660 scontext=u:r:system_app:s0 tcontext=u:object_r:apk_data_file:s0 tclass=dir permissive=0\n```\n\nTo fix this, you need to adjust the SELinux security rules in the ROM. This can\nbe done by using the tool `audit2allow`. This tool ships as part of\n[AOSP](https://source.android.com/).\n\n1. Pull the current policy from the device: `adb pull /sys/fs/selinux/policy`.\n2. Copy the SELinux error inside a text file called `input.txt`.\n3. Run the `audit2allow` tool: `audit2allow -p policy -i input.txt`.\n4. The tool should output a rule you can add to your existing policy.\nThe rule allows you to access the Realm file from multiple processes.\n\n`audit2allow` is produced when compiling AOSP/ROM and only runs on\nLinux. Check out the details in the [Android Source documentation](https://source.android.com/security/selinux/validate#using_audit2allow).\nAlso note that since Android Oreo, Google changed the way it configures\nSELinux and the default security policies are now more modularized. More details\nare in the [Android Source documentation](https://source.android.com/security/selinux/images/SELinux_Treble.pdf).\n"
  },
  {
    "path": "examples/architectureComponentsExample/build.gradle",
    "content": "apply plugin: 'com.android.application'\napply plugin: 'realm-android'\n\nandroid {\n    compileSdkVersion rootProject.sdkVersion\n    buildToolsVersion rootProject.buildTools\n\n    compileOptions {\n        sourceCompatibility JavaVersion.VERSION_1_8\n        targetCompatibility JavaVersion.VERSION_1_8\n    }\n    defaultConfig {\n        applicationId 'io.realm.examples.arch'\n        targetSdkVersion rootProject.sdkVersion\n        minSdkVersion rootProject.minSdkVersion\n        versionCode 1\n        versionName \"1.0\"\n\n        vectorDrawables.useSupportLibrary = true\n    }\n\n    buildTypes {\n        release {\n            minifyEnabled true\n            signingConfig signingConfigs.debug\n        }\n        debug {\n            minifyEnabled false\n        }\n    }\n}\n\ndependencies {\n    implementation \"android.arch.lifecycle:runtime:1.1.1\"\n    implementation \"android.arch.lifecycle:extensions:1.1.1\"\n    annotationProcessor \"android.arch.lifecycle:compiler:1.1.1\"\n    implementation 'com.android.support:appcompat-v7:27.1.1'\n    implementation 'com.android.support:recyclerview-v7:27.1.1'\n    implementation 'com.android.support:design:27.1.1'\n}\n"
  },
  {
    "path": "examples/architectureComponentsExample/lint.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<lint>\n    <!-- Disable the given check in this project -->\n    <issue id=\"AllowBackup\" severity=\"ignore\" />\n    <issue id=\"IconLauncherShape\" severity=\"ignore\" />\n    <issue id=\"IconMissingDensityFolder\" severity=\"ignore\" />\n    <issue id=\"GoogleAppIndexingWarning\" severity=\"ignore\" />\n    <issue id=\"InvalidPackage\" severity=\"ignore\" />\n</lint>\n"
  },
  {
    "path": "examples/architectureComponentsExample/src/main/AndroidManifest.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    package=\"io.realm.examples.arch\" >\n\n    <application\n        android:icon=\"@mipmap/ic_launcher\"\n        android:label=\"@string/app_name\"\n        android:name=\".CustomApplication\"\n        android:theme=\"@style/AppTheme\" >\n        <activity\n            android:name=\".ArchExampleActivity\"\n            android:label=\"@string/app_name\" >\n            <intent-filter>\n                <action android:name=\"android.intent.action.MAIN\" />\n\n                <category android:name=\"android.intent.category.LAUNCHER\" />\n            </intent-filter>\n        </activity>\n    </application>\n\n</manifest>\n"
  },
  {
    "path": "examples/architectureComponentsExample/src/main/java/io/realm/examples/arch/ArchExampleActivity.java",
    "content": "/*\n * Copyright 2018 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\npackage io.realm.examples.arch;\n\nimport android.os.Bundle;\nimport android.support.annotation.MainThread;\nimport android.support.design.widget.FloatingActionButton;\nimport android.support.v7.app.AppCompatActivity;\n\npublic class ArchExampleActivity extends AppCompatActivity {\n    private FloatingActionButton backgroundJobStartStop;\n\n    private BackgroundTask backgroundTask;\n\n    @Override\n    protected void onCreate(Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n\n        setContentView(R.layout.activity_arch_example);\n        setupViews();\n\n        backgroundTask = (BackgroundTask) getLastCustomNonConfigurationInstance();\n        if (backgroundTask == null) { // this could also live inside a ViewModel, a singleton job queue, etc.\n            backgroundTask = new BackgroundTask();\n            backgroundTask.start(); // this task will update items in Realm on a background thread.\n        }\n        updateJobButton();\n\n        if (savedInstanceState == null) {\n            getSupportFragmentManager().beginTransaction()\n                    .add(R.id.container, PersonListFragment.create())\n                    .addToBackStack(null)\n                    .commit();\n        }\n    }\n\n    @Override\n    public Object onRetainCustomNonConfigurationInstance() {\n        return backgroundTask; // retain background task through config changes without ViewModel.\n    }\n\n    @Override\n    protected void onDestroy() {\n        super.onDestroy();\n        if (isFinishing()) {\n            if(backgroundTask.isStarted()) {\n                backgroundTask.stop(); // make sure job is stopped when exiting the app\n            }\n        }\n    }\n\n    @Override\n    public void onBackPressed() {\n        if (getSupportFragmentManager().getBackStackEntryCount() <= 1) {\n            finish();\n        } else {\n            super.onBackPressed();\n        }\n    }\n\n    @MainThread\n    private void setupViews() {\n        backgroundJobStartStop = findViewById(R.id.backgroundJobStartStop);\n        backgroundJobStartStop.setOnClickListener(v -> {\n            if (!backgroundTask.isStarted()) {\n                backgroundTask.start();\n            } else {\n                backgroundTask.stop();\n            }\n            updateJobButton();\n        });\n    }\n\n    private void updateJobButton() {\n        if (backgroundTask.isStarted()) {\n            backgroundJobStartStop.setImageResource(R.drawable.ic_stop_black_24dp);\n        } else {\n            backgroundJobStartStop.setImageResource(R.drawable.ic_play_arrow_black_24dp);\n        }\n    }\n}\n"
  },
  {
    "path": "examples/architectureComponentsExample/src/main/java/io/realm/examples/arch/BackgroundTask.java",
    "content": "/*\n * Copyright 2018 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\npackage io.realm.examples.arch;\n\nimport android.annotation.SuppressLint;\nimport android.os.SystemClock;\nimport android.support.annotation.MainThread;\nimport android.util.Log;\n\nimport io.realm.Realm;\nimport io.realm.RealmResults;\nimport io.realm.examples.arch.model.Person;\n\n\npublic class BackgroundTask {\n    private static final Object lock = new Object();\n\n    private static final String TAG = \"BackgroundTask\";\n\n    private boolean isStarted;\n\n    private volatile Thread thread;\n\n    @MainThread\n    public boolean isStarted() {\n        return isStarted;\n    }\n\n    @MainThread\n    public void start() {\n        synchronized (lock) {\n            if (isStarted) {\n                return;\n            }\n            thread = new IncrementThread();\n            thread.start();\n            isStarted = true;\n            Log.i(TAG, \"Background job started.\");\n        }\n    }\n\n    @MainThread\n    public void stop() {\n        synchronized (lock) {\n            if (thread != null) {\n                thread.interrupt();\n                thread = null;\n            }\n            isStarted = false;\n        }\n    }\n\n    private static final class IncrementThread extends Thread {\n        IncrementThread() {\n            super(\"Aging thread\");\n        }\n\n        @Override\n        @SuppressLint(\"NewApi\")\n        public void run() {\n            try (Realm realm = Realm.getDefaultInstance()) {\n                final RealmResults<Person> persons = realm.where(Person.class).findAll();\n                Realm.Transaction transaction = (Realm r) -> {\n                    for (Person person : persons) {\n                        person.setAge(person.getAge() + 1); // updates the Persons in the Realm.\n                    }\n                };\n\n                while (!isInterrupted()) {\n                    realm.executeTransaction(transaction);\n                    SystemClock.sleep(1000L);\n                }\n            }\n            Log.i(TAG, \"Background job stopped.\");\n        }\n    }\n}\n\n"
  },
  {
    "path": "examples/architectureComponentsExample/src/main/java/io/realm/examples/arch/CustomApplication.java",
    "content": "/*\n * Copyright 2018 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\npackage io.realm.examples.arch;\n\nimport android.app.Application;\nimport android.support.annotation.NonNull;\n\nimport io.realm.Realm;\nimport io.realm.RealmConfiguration;\nimport io.realm.examples.arch.model.Person;\n\n\npublic class CustomApplication extends Application {\n\n    @Override\n    public void onCreate() {\n        super.onCreate();\n\n        Realm.init(this);\n        Realm.setDefaultConfiguration(new RealmConfiguration.Builder()\n                .deleteRealmIfMigrationNeeded()\n                .initialData(new Realm.Transaction() {\n                    @Override\n                    public void execute(@NonNull Realm realm) {\n                        Person person = realm.createObject(Person.class);\n                        person.setName(\"Makoto Yamazaki\");\n                        person.setAge(32);\n\n                        person = realm.createObject(Person.class);\n                        person.setName(\"Christian Melchior\");\n                        person.setAge(34);\n\n                        person = realm.createObject(Person.class);\n                        person.setName(\"Chen Mulong\");\n                        person.setAge(29);\n\n                        person = realm.createObject(Person.class);\n                        person.setName(\"Nabil Hachicha\");\n                        person.setAge(31);\n                    }\n                })\n                .build());\n    }\n}\n"
  },
  {
    "path": "examples/architectureComponentsExample/src/main/java/io/realm/examples/arch/PersonFragment.java",
    "content": "/*\n * Copyright 2018 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 */\npackage io.realm.examples.arch;\n\nimport android.arch.lifecycle.ViewModel;\nimport android.arch.lifecycle.ViewModelProvider;\nimport android.arch.lifecycle.ViewModelProviders;\nimport android.os.Bundle;\nimport android.support.annotation.NonNull;\nimport android.support.annotation.Nullable;\nimport android.support.v4.app.Fragment;\nimport android.view.LayoutInflater;\nimport android.view.View;\nimport android.view.ViewGroup;\nimport android.widget.TextView;\n\npublic class PersonFragment extends Fragment {\n    private static final String ARG_PERSON_NAME = \"personName\";\n\n    public static PersonFragment create(String personName) {\n        PersonFragment personFragment = new PersonFragment();\n        Bundle bundle = new Bundle();\n        bundle.putString(ARG_PERSON_NAME, personName);\n        personFragment.setArguments(bundle);\n        return personFragment;\n    }\n\n    private PersonViewModel personViewModel;\n\n    private TextView name;\n    private TextView age;\n\n    @Override\n    public void onCreate(@Nullable Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n        @SuppressWarnings(\"ConstantConditions\") final String personName = getArguments().getString(ARG_PERSON_NAME);\n        personViewModel = ViewModelProviders.of(this, new ViewModelProvider.Factory() {\n            @NonNull\n            @Override\n            public <T extends ViewModel> T create(@NonNull Class<T> modelClass) {\n                if (modelClass == PersonViewModel.class) {\n                    PersonViewModel personViewModel = new PersonViewModel();\n                    personViewModel.setup(personName); // we use a Factory to ensure `setup` is called before use.\n                    //noinspection unchecked\n                    return (T) personViewModel;\n                }\n                //noinspection ConstantConditions\n                return null;\n            }\n        }).get(PersonViewModel.class);\n\n        personViewModel.getPerson().observe(this, person -> {\n            if (person != null) { // null would mean the object was deleted.\n                name.setText(person.getName());\n                age.setText(String.valueOf(person.getAge()));\n            }\n        });\n    }\n\n    @Nullable\n    @Override\n    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {\n        return inflater.inflate(R.layout.fragment_person, container, false);\n    }\n\n    @Override\n    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {\n        super.onViewCreated(view, savedInstanceState);\n        name = view.findViewById(R.id.personName);\n        age = view.findViewById(R.id.personAge);\n    }\n}\n"
  },
  {
    "path": "examples/architectureComponentsExample/src/main/java/io/realm/examples/arch/PersonListFragment.java",
    "content": "/*\n * Copyright 2018 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 */\npackage io.realm.examples.arch;\n\nimport android.arch.lifecycle.ViewModelProviders;\nimport android.os.Bundle;\nimport android.support.annotation.NonNull;\nimport android.support.annotation.Nullable;\nimport android.support.v4.app.Fragment;\nimport android.support.v4.app.FragmentTransaction;\nimport android.support.v7.app.AppCompatActivity;\nimport android.support.v7.widget.LinearLayoutManager;\nimport android.support.v7.widget.RecyclerView;\nimport android.view.LayoutInflater;\nimport android.view.View;\nimport android.view.ViewGroup;\nimport android.widget.TextView;\n\nimport java.util.Collections;\nimport java.util.List;\n\nimport io.realm.examples.arch.model.Person;\nimport io.realm.examples.arch.utils.ContextUtils;\n\npublic class PersonListFragment extends Fragment {\n    public static PersonListFragment create() {\n        return new PersonListFragment();\n    }\n\n    private RecyclerView recyclerView;\n    private Adapter adapter;\n\n    private PersonListViewModel personListViewModel;\n    private List<Person> personList = Collections.emptyList();\n\n    @Override\n    public void onCreate(@Nullable Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n        // Fragments should start listening in `onCreate()`\n        // to ensure single observer instance, even if detached (for example in FragmentPagerAdapter).\n        personListViewModel = ViewModelProviders.of(this).get(PersonListViewModel.class);\n        personListViewModel.getPersons().observe(this, people -> {\n            personList = people;\n            if (adapter != null) {\n                adapter.updateItems(people);\n            }\n        });\n    }\n\n    @Nullable\n    @Override\n    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {\n        return inflater.inflate(R.layout.fragment_person_list, container, false);\n    }\n\n    @Override\n    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {\n        super.onViewCreated(view, savedInstanceState);\n        recyclerView = view.findViewById(R.id.recyclerView);\n        recyclerView.setHasFixedSize(true);\n        recyclerView.setLayoutManager(new LinearLayoutManager(getActivity(), LinearLayoutManager.VERTICAL, false));\n        adapter = new Adapter(personList);\n        recyclerView.setAdapter(adapter);\n    }\n\n    static class Adapter extends RecyclerView.Adapter<Adapter.ViewHolder> {\n        private List<Person> persons;\n\n        public Adapter(List<Person> persons) {\n            this.persons = persons;\n        }\n\n        @Override\n        public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {\n            return new ViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_person, parent, false));\n        }\n\n        @Override\n        public void onBindViewHolder(ViewHolder holder, int position) {\n            holder.bind(persons.get(position));\n        }\n\n        @Override\n        public int getItemCount() {\n            return persons == null ? 0 : persons.size();\n        }\n\n        public void updateItems(List<Person> persons) {\n            this.persons = persons;\n            notifyDataSetChanged();\n        }\n\n        static class ViewHolder extends RecyclerView.ViewHolder {\n            TextView name;\n            TextView age;\n\n            Person person;\n\n            private final View.OnClickListener onClick = (view) -> {\n                if (person == null) {\n                    return;\n                }\n                AppCompatActivity activity = ContextUtils.findActivity(view.getContext());\n                PersonFragment personFragment = PersonFragment.create(person.name);\n                activity.getSupportFragmentManager()\n                        .beginTransaction()\n                        .setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE)\n                        .replace(R.id.container, personFragment)\n                        .addToBackStack(null)\n                        .commit();\n            };\n\n            public ViewHolder(View itemView) {\n                super(itemView);\n                name = itemView.findViewById(R.id.personName);\n                age = itemView.findViewById(R.id.personAge);\n                itemView.setOnClickListener(onClick);\n            }\n\n            public void bind(Person person) {\n                this.person = person;\n                name.setText(person.getName());\n                age.setText(String.valueOf(person.getAge()));\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "examples/architectureComponentsExample/src/main/java/io/realm/examples/arch/PersonListViewModel.java",
    "content": "/*\n * Copyright 2018 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 */\npackage io.realm.examples.arch;\n\nimport android.arch.lifecycle.LiveData;\nimport android.arch.lifecycle.ViewModel;\n\nimport java.util.List;\n\nimport io.realm.Realm;\nimport io.realm.examples.arch.livemodel.LiveRealmResults;\nimport io.realm.examples.arch.model.Person;\n\npublic class PersonListViewModel extends ViewModel {\n    private final Realm realm;\n    private final LiveData<List<Person>> persons;\n\n    public PersonListViewModel() {\n        realm = Realm.getDefaultInstance(); // Realm is bound to the lifecycle of the ViewModel, and stays alive as long as it is needed.\n        persons = new LiveRealmResults<>(realm.where(Person.class).sort(\"age\").findAllAsync());\n    }\n\n    public LiveData<List<Person>> getPersons() {\n        return persons;\n    }\n\n    @Override\n    protected void onCleared() {\n        realm.close(); // Realm is bound to the lifecycle of the ViewModel, and is destroyed when no longer needed.\n        super.onCleared();\n    }\n}\n"
  },
  {
    "path": "examples/architectureComponentsExample/src/main/java/io/realm/examples/arch/PersonViewModel.java",
    "content": "/*\n * Copyright 2018 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\npackage io.realm.examples.arch;\n\nimport android.arch.lifecycle.LiveData;\nimport android.arch.lifecycle.ViewModel;\n\nimport io.realm.Realm;\nimport io.realm.examples.arch.livemodel.LiveRealmObject;\nimport io.realm.examples.arch.model.Person;\n\n\npublic class PersonViewModel extends ViewModel {\n    private final Realm realm;\n\n    private LiveData<Person> livePerson;\n\n    public PersonViewModel() {\n        realm = Realm.getDefaultInstance(); // Realm is bound to the lifecycle of the ViewModel, and stays alive as long as it is needed.\n    }\n\n    public LiveData<Person> getPerson() {\n        return livePerson;\n    }\n\n    @Override\n    protected void onCleared() {\n        realm.close(); // Realm is bound to the lifecycle of the ViewModel, and is destroyed when no longer needed.\n        super.onCleared();\n    }\n\n    public void setup(String personName) {\n        Person person = realm.where(Person.class).equalTo(\"name\", personName).findFirst();\n        if (person == null) {\n            throw new IllegalStateException(\"The person was not found, it shouldn't be deleted!\");\n        }\n        livePerson = new LiveRealmObject<>(person);\n    }\n}\n"
  },
  {
    "path": "examples/architectureComponentsExample/src/main/java/io/realm/examples/arch/livemodel/LiveRealmObject.java",
    "content": "/*\n * Copyright 2018 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\npackage io.realm.examples.arch.livemodel;\n\nimport android.arch.lifecycle.LiveData;\nimport android.support.annotation.MainThread;\nimport android.support.annotation.NonNull;\n\nimport io.realm.ObjectChangeSet;\nimport io.realm.RealmModel;\nimport io.realm.RealmObject;\nimport io.realm.RealmObjectChangeListener;\n\n/**\n * This class represents a RealmObject wrapped inside a LiveData.\n *\n * It is expected that the provided RealmObject is a managed object, and exists in the Realm on creation.\n *\n * This allows observing the RealmObject in such a way, that the listener that will be automatically unsubscribed when the enclosing LifecycleOwner is killed.\n *\n * Realm will keep the managed RealmObject up-to-date whenever a change occurs on any thread,\n * and when that happens, the observer will be notified.\n *\n * The object will be observed until it is invalidated - deleted, or all local Realm instances are closed.\n *\n * @param <T> the type of the RealmModel\n */\npublic class LiveRealmObject<T extends RealmModel> extends LiveData<T> {\n    // The listener will listen until the object is deleted.\n    // An invalidated object shouldn't be set in LiveData, null is set instead.\n    private RealmObjectChangeListener<T> listener = new RealmObjectChangeListener<T>() {\n        @Override\n        public void onChange(@NonNull T object, ObjectChangeSet objectChangeSet) {\n            if (!objectChangeSet.isDeleted()) {\n                setValue(object);\n            } else {\n                setValue(null);\n            }\n        }\n    };\n\n    /**\n     * Wraps the provided managed RealmObject as a LiveData.\n     *\n     * The provided object should not be null, should be managed, and should be valid.\n     *\n     * @param object the managed RealmModel to wrap as LiveData\n     */\n    @MainThread\n    public LiveRealmObject(@NonNull T object) {\n        //noinspection ConstantConditions\n        if (object == null) {\n            throw new IllegalArgumentException(\"The object cannot be null!\");\n        }\n        if (!RealmObject.isManaged(object)) {\n            throw new IllegalArgumentException(\"LiveRealmObject only supports managed RealmModel instances!\");\n        }\n        if (!RealmObject.isValid(object)) {\n            throw new IllegalArgumentException(\"The provided RealmObject is no longer valid, and therefore cannot be observed for changes.\");\n        }\n        setValue(object);\n    }\n\n    // We should start observing and stop observing, depending on whether we have observers.\n    // Deleted objects can no longer be observed.\n    // We can also no longer observe the object if all local Realm instances on this thread (the UI thread) are closed.\n\n    /**\n     * Starts observing the RealmObject, if it is still valid.\n     */\n    @Override\n    protected void onActive() {\n        super.onActive();\n        T object = getValue();\n        if (object != null && RealmObject.isValid(object)) {\n            RealmObject.addChangeListener(object, listener);\n        }\n    }\n\n    /**\n     * Stops observing the RealmObject.\n     */\n    @Override\n    protected void onInactive() {\n        super.onInactive();\n        T object = getValue();\n        if (object != null && RealmObject.isValid(object)) {\n            RealmObject.removeChangeListener(object, listener);\n        }\n    }\n}\n"
  },
  {
    "path": "examples/architectureComponentsExample/src/main/java/io/realm/examples/arch/livemodel/LiveRealmResults.java",
    "content": "/*\n * Copyright 2018 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\npackage io.realm.examples.arch.livemodel;\n\nimport android.arch.lifecycle.LiveData;\nimport android.support.annotation.MainThread;\nimport android.support.annotation.NonNull;\n\nimport java.util.List;\n\nimport javax.annotation.Nullable;\n\nimport io.realm.OrderedCollectionChangeSet;\nimport io.realm.OrderedRealmCollectionChangeListener;\nimport io.realm.RealmModel;\nimport io.realm.RealmResults;\n\n/**\n * This class represents a RealmResults wrapped inside a LiveData.\n *\n * Realm will always keep the RealmResults up-to-date whenever a change occurs on any thread,\n * and when that happens, the observer will be notified.\n *\n * The RealmResults will be observed until it is invalidated - meaning all local Realm instances on this thread are closed.\n *\n * @param <T> the type of the RealmModel\n */\npublic class LiveRealmResults<T extends RealmModel> extends LiveData<List<T>> {\n    private final RealmResults<T> results;\n\n    // The listener will notify the observers whenever a change occurs.\n    // The results are modified in change. This could be expanded to also return the change set in a pair.\n    private OrderedRealmCollectionChangeListener<RealmResults<T>> listener = new OrderedRealmCollectionChangeListener<RealmResults<T>>() {\n        @Override\n        public void onChange(@NonNull RealmResults<T> results, @Nullable OrderedCollectionChangeSet changeSet) {\n            LiveRealmResults.this.setValue(results);\n        }\n    };\n\n    @MainThread\n    public LiveRealmResults(@NonNull RealmResults<T> results) {\n        //noinspection ConstantConditions\n        if (results == null) {\n            throw new IllegalArgumentException(\"Results cannot be null!\");\n        }\n        if (!results.isValid()) {\n            throw new IllegalArgumentException(\"The provided RealmResults is no longer valid, the Realm instance it belongs to is closed. It can no longer be observed for changes.\");\n        }\n        this.results = results;\n        if (results.isLoaded()) {\n            // we should not notify observers when results aren't ready yet (async query).\n            // however, synchronous query should be set explicitly.\n            setValue(results);\n        }\n    }\n\n    // We should start observing and stop observing, depending on whether we have observers.\n\n    /**\n     * Starts observing the RealmResults, if it is still valid.\n     */\n    @Override\n    protected void onActive() {\n        super.onActive();\n        if (results.isValid()) { // invalidated results can no longer be observed.\n            results.addChangeListener(listener);\n        }\n    }\n\n    /**\n     * Stops observing the RealmResults.\n     */\n    @Override\n    protected void onInactive() {\n        super.onInactive();\n        if (results.isValid()) {\n            results.removeChangeListener(listener);\n        }\n    }\n}\n"
  },
  {
    "path": "examples/architectureComponentsExample/src/main/java/io/realm/examples/arch/model/Person.java",
    "content": "/*\n * Copyright 2018 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\npackage io.realm.examples.arch.model;\n\nimport io.realm.RealmObject;\nimport io.realm.annotations.Index;\n\npublic class Person extends RealmObject {\n    @Index\n    public String name;\n\n    private int age;\n\n    public String getName() {\n        return name;\n    }\n\n    public void setName(String name) {\n        this.name = name;\n    }\n\n    public int getAge() {\n        return age;\n    }\n\n    public void setAge(int age) {\n        this.age = age;\n    }\n}\n"
  },
  {
    "path": "examples/architectureComponentsExample/src/main/java/io/realm/examples/arch/utils/ContextUtils.java",
    "content": "/*\n * Copyright 2018 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 */\npackage io.realm.examples.arch.utils;\n\nimport android.app.Activity;\nimport android.content.Context;\nimport android.content.ContextWrapper;\n\n/**\n * This is a helper class to look up an Activity inside a View's context chain in a reliable/safe manner.\n */\npublic class ContextUtils {\n    private ContextUtils() {\n    }\n\n    /**\n     * Finds the Activity inside the hierarchy of the provided Context.\n     *\n     * @param context the context\n     * @param <T> the expected type of the Activity\n     * @return the activity\n     *\n     * @throws IllegalArgumentException if the context has no Activity in its base context hierarchy\n     */\n    public static <T extends Activity> T findActivity(Context context) {\n        if (context instanceof Activity) {\n            //noinspection unchecked\n            return (T) context;\n        }\n        while (context != null && context instanceof ContextWrapper) {\n            context = ((ContextWrapper) context).getBaseContext();\n            if (context instanceof Activity) {\n                //noinspection unchecked\n                return (T) context;\n            }\n        }\n        throw new IllegalArgumentException(\"No activity found in context hierarchy.\");\n    }\n}\n"
  },
  {
    "path": "examples/architectureComponentsExample/src/main/res/drawable/ic_play_arrow_black_24dp.xml",
    "content": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n        android:width=\"24dp\"\n        android:height=\"24dp\"\n        android:viewportWidth=\"24.0\"\n        android:viewportHeight=\"24.0\">\n    <path\n        android:fillColor=\"#FF000000\"\n        android:pathData=\"M8,5v14l11,-7z\"/>\n</vector>\n"
  },
  {
    "path": "examples/architectureComponentsExample/src/main/res/drawable/ic_stop_black_24dp.xml",
    "content": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n        android:width=\"24dp\"\n        android:height=\"24dp\"\n        android:viewportWidth=\"24.0\"\n        android:viewportHeight=\"24.0\">\n    <path\n        android:fillColor=\"#FF000000\"\n        android:pathData=\"M6,6h12v12H6z\"/>\n</vector>\n"
  },
  {
    "path": "examples/architectureComponentsExample/src/main/res/layout/activity_arch_example.xml",
    "content": "<RelativeLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:orientation=\"vertical\">\n\n    <FrameLayout\n        android:id=\"@+id/container\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\"/>\n\n    <android.support.design.widget.FloatingActionButton\n        android:id=\"@+id/backgroundJobStartStop\"\n        android:layout_width=\"40dp\"\n        android:layout_height=\"40dp\"\n        android:layout_alignParentBottom=\"true\"\n        android:layout_alignParentEnd=\"true\"\n        android:layout_alignParentRight=\"true\"\n        android:layout_marginBottom=\"16dp\"\n        android:layout_marginEnd=\"16dp\"\n        android:layout_marginRight=\"16dp\"\n        android:scaleType=\"center\"\n        app:fabSize=\"normal\"\n        app:srcCompat=\"@drawable/ic_stop_black_24dp\" />\n</RelativeLayout>\n"
  },
  {
    "path": "examples/architectureComponentsExample/src/main/res/layout/fragment_person.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:orientation=\"vertical\"\n    android:gravity=\"center\">\n\n    <TextView\n        android:id=\"@+id/personName\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:gravity=\"center_horizontal\"\n        android:textSize=\"24sp\"\n        android:textColor=\"@android:color/black\"\n        android:textStyle=\"bold\"\n        android:paddingTop=\"8dp\"\n        android:paddingBottom=\"8dp\"\n        tools:text=\"Makoto\" />\n\n    <TextView\n        android:id=\"@+id/personAge\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:gravity=\"center_horizontal\"\n        android:textColor=\"#232323\"\n        android:textSize=\"20sp\"\n        tools:text=\"16\" />\n\n</LinearLayout>"
  },
  {
    "path": "examples/architectureComponentsExample/src/main/res/layout/fragment_person_list.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:orientation=\"vertical\">\n\n    <android.support.v7.widget.RecyclerView\n        android:id=\"@+id/recyclerView\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\" />\n</LinearLayout>"
  },
  {
    "path": "examples/architectureComponentsExample/src/main/res/layout/item_person.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"wrap_content\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:orientation=\"vertical\">\n    <TextView\n        android:id=\"@+id/personName\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:paddingTop=\"8dp\"\n        android:paddingBottom=\"8dp\"\n        android:paddingLeft=\"8dp\"\n        android:paddingRight=\"8dp\"\n        android:textSize=\"24sp\"\n        android:textStyle=\"bold\"\n        android:textColor=\"@android:color/black\"\n        tools:text=\"Makoto\"/>\n\n    <LinearLayout\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\">\n        <TextView\n            android:id=\"@+id/personAgeLabel\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:paddingTop=\"8dp\"\n            android:paddingBottom=\"8dp\"\n            android:paddingLeft=\"8dp\"\n            android:paddingRight=\"4dp\"\n            android:paddingStart=\"8dp\"\n            android:paddingEnd=\"4dp\"\n            android:textSize=\"20sp\"\n            android:textColor=\"#212121\"\n            android:text=\"Age: \"/>\n\n        <TextView\n            android:id=\"@+id/personAge\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:paddingTop=\"8dp\"\n            android:paddingBottom=\"8dp\"\n            android:paddingLeft=\"8dp\"\n            android:paddingRight=\"8dp\"\n            android:textSize=\"20sp\"\n            android:textColor=\"#212121\"\n            tools:text=\"16\"/>\n    </LinearLayout>\n\n    <View\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"1dp\"\n        android:background=\"#EFEFEF\"/>\n</LinearLayout>"
  },
  {
    "path": "examples/architectureComponentsExample/src/main/res/values/dimens.xml",
    "content": "<resources>\n    <!-- Default screen margins, per the Android Design guidelines. -->\n    <dimen name=\"activity_horizontal_margin\">16dp</dimen>\n    <dimen name=\"activity_vertical_margin\">16dp</dimen>\n</resources>\n"
  },
  {
    "path": "examples/architectureComponentsExample/src/main/res/values/strings.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n\n    <string name=\"app_name\">Lifecycle example</string>\n\n</resources>\n"
  },
  {
    "path": "examples/architectureComponentsExample/src/main/res/values/styles.xml",
    "content": "<resources>\n\n    <!-- Base application theme. -->\n    <style name=\"AppTheme\" parent=\"Theme.Design.Light\">\n        <!-- Customize your theme here. -->\n    </style>\n\n</resources>\n"
  },
  {
    "path": "examples/architectureComponentsExample/src/main/res/values-w820dp/dimens.xml",
    "content": "<resources>\n    <!-- Example customization of dimensions originally defined in res/values/dimens.xml\n         (such as screen margins) for screens with more than 820dp of available width. This\n         would include 7\" and 10\" devices in landscape (~960dp and ~1280dp respectively). -->\n    <dimen name=\"activity_horizontal_margin\">64dp</dimen>\n</resources>\n"
  },
  {
    "path": "examples/build.gradle",
    "content": "def projectDependencies = new Properties()\nprojectDependencies.load(new FileInputStream(\"${rootDir}/../dependencies.list\"))\nproject.ext.sdkVersion = 29\nproject.ext.minSdkVersion = 16\nproject.ext.buildTools = projectDependencies.get(\"ANDROID_BUILD_TOOLS\")\nproject.ext.kotlinVersion = projectDependencies.get('KOTLIN')\n\n// Don't cache SNAPSHOT (changing) dependencies.\nconfigurations.all {\n    resolutionStrategy.cacheChangingModulesFor 0, 'seconds'\n}\n\nstatic String getAppId (path) {\n    String build = new File(path).text\n    def matcher = build =~ 'applicationId.*'\n    def appId = matcher.size() > 0 ? matcher[0].trim() - 'applicationId' - ~/\\s/ : ''\n    String myappId = appId.replaceAll('\"', '')\n    myappId = myappId.replaceAll('\\'', '')\n    return myappId\n}\n\nallprojects {\n    def currentVersion = file(\"${rootDir}/../version.txt\").text.trim()\n\n    def props = new Properties()\n    props.load(new FileInputStream(\"${rootDir}/../dependencies.list\"))\n    props.each { key, val ->\n        project.ext.set(key, val)\n    }\n\n    buildscript {\n        ext {\n            kotlin_version = projectDependencies.get('KOTLIN')\n        }\n        repositories {\n            mavenLocal()\n            mavenCentral()\n            maven { url 'https://jitpack.io' }\n            google()\n            jcenter()\n        }\n        dependencies {\n            classpath \"com.android.tools.build:gradle:${props.get(\"GRADLE_BUILD_TOOLS\")}\"\n            classpath \"io.realm:realm-gradle-plugin:${currentVersion}\"\n            classpath \"org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version\"\n        }\n    }\n\n    group = 'io.realm'\n    version = currentVersion\n\n    repositories {\n        mavenLocal()\n        mavenCentral()\n        google()\n        jcenter()\n    }\n\n    if (!project.name.startsWith(\"realm-examples\")\n            && !project.name.startsWith(\"library\")\n            && !project.name.startsWith(\"moduleExample\")) { // exclude root and library project\n        [\"Debug\", \"Release\"].each {\n            task \"monkey${it}\"(dependsOn: \"install${it}\") {\n                doLast {\n                    def numberOfEvents = 2000\n                    def appId = getAppId(\"${project.projectDir}/build.gradle\")\n                    def process = \"adb shell monkey -p ${appId} --pct-syskeys 0 ${numberOfEvents}\".execute([], project.rootDir)\n\n                    def sout = new StringBuilder(), serr = new StringBuilder()\n                    process.consumeProcessOutput(sout, serr)\n                    process.waitFor()\n\n                    if (process.exitValue() != 0\n                            || !sout?.toString()?.trim()?.contains(\"Events injected: ${numberOfEvents}\")) {\n                        // fail Gradle build\n                        throw new GradleException(\"monkey failed for AppID: ${appId} \\nExit code: ${process.exitValue()}\\nStd out:  ${sout}\\nStd err:  ${serr}\")\n                    }\n                }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "examples/compatibilityExample/README.md",
    "content": "# Using this example\n\nThis example is not really meant for use, but only as a compatibility check to ensure that we can\nbuild projects without AndroidX and Java 8 features.\n\n"
  },
  {
    "path": "examples/compatibilityExample/build.gradle",
    "content": "apply plugin: 'com.android.application'\napply plugin: 'kotlin-android'\napply plugin: 'kotlin-kapt'\napply plugin: 'kotlin-android-extensions'\napply plugin: 'realm-android'\n\nandroid {\n    compileSdkVersion rootProject.sdkVersion\n    buildToolsVersion rootProject.buildTools\n\n    defaultConfig {\n        applicationId 'io.realm.examples.compatibility'\n        targetSdkVersion rootProject.sdkVersion\n        minSdkVersion rootProject.minSdkVersion\n        versionCode 1\n        versionName \"1.0\"\n    }\n\n    buildTypes {\n        // Configure server and App Id.\n        // The default server is https://realm-dev.mongodb.com/ . Go to that and copy the MongoDB\n        // Realm App Id.\n        //\n        // If you are running a local version of MongoDB Realm, modify endpoint accordingly. Most\n        // likely it is \"http://localhost:9090\"\n        def mongodbRealmUrl = \"https://realm-dev.mongodb.com\"\n        def appId = \"my-app-id\"\n        debug {\n            buildConfigField \"String\", \"MONGODB_REALM_URL\", \"\\\"${mongodbRealmUrl}\\\"\"\n            buildConfigField \"String\", \"MONGODB_REALM_APP_ID\", \"\\\"${appId}\\\"\"\n        }\n        release {\n            buildConfigField \"String\", \"MONGODB_REALM_URL\", \"\\\"${mongodbRealmUrl}\\\"\"\n            buildConfigField \"String\", \"MONGODB_REALM_APP_ID\", \"\\\"${appId}\\\"\"\n            minifyEnabled true\n            signingConfig signingConfigs.debug\n        }\n    }\n\n    // Ensure that we can compile an app without Java 8 features\n    compileOptions {\n        sourceCompatibility 1.8\n        targetCompatibility 1.8\n    }\n}\n\nrealm {\n    syncEnabled = true\n}\n\ndependencies {\n    implementation 'com.android.support:appcompat-v7:27.1.1'\n    implementation 'com.android.support:design:27.1.1'\n    implementation 'me.zhanghai.android.materialprogressbar:library:1.3.0'\n    implementation \"org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version\"\n    implementation 'com.android.support.constraint:constraint-layout:1.1.3'\n}\n\nif ((project.findProperty(\"android.useAndroidX\") ?: false).toBoolean())\n    throw new RuntimeException(\"Compatibility project should run without AndroidX\")\n"
  },
  {
    "path": "examples/compatibilityExample/gradle.properties",
    "content": "# Ensure that we do not use AndroidX for this project\nandroid.useAndroidX=false\n"
  },
  {
    "path": "examples/compatibilityExample/lint.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<lint>\n    <!-- Disable the given check in this project -->\n    <issue id=\"AllowBackup\" severity=\"ignore\" />\n    <issue id=\"IconLauncherShape\" severity=\"ignore\" />\n    <issue id=\"IconMissingDensityFolder\" severity=\"ignore\" />\n    <issue id=\"GoogleAppIndexingWarning\" severity=\"ignore\" />\n    <issue id=\"InvalidPackage\" severity=\"ignore\" />\n</lint>\n"
  },
  {
    "path": "examples/compatibilityExample/src/main/AndroidManifest.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    package=\"io.realm.examples.compatibility\">\n\n    <application\n        android:name=\".MyApplication\"\n        android:icon=\"@mipmap/ic_launcher\"\n        android:label=\"@string/app_name\"\n        android:theme=\"@style/AppTheme\">\n        <activity\n            android:name=\".MyActivity\"\n            android:label=\"@string/app_name\">\n            <intent-filter>\n                <action android:name=\"android.intent.action.MAIN\" />\n\n                <category android:name=\"android.intent.category.LAUNCHER\" />\n            </intent-filter>\n        </activity>\n    </application>\n\n</manifest>\n"
  },
  {
    "path": "examples/compatibilityExample/src/main/java/io/realm/examples/compatibility/MyActivity.kt",
    "content": "package io.realm.examples.compatibility\n\nimport android.support.v7.app.AppCompatActivity\nimport android.os.Bundle\n\nclass MyActivity : AppCompatActivity() {\n    override fun onCreate(savedInstanceState: Bundle?) {\n        super.onCreate(savedInstanceState)\n        setContentView(R.layout.activity_my_activty)\n    }\n}\n"
  },
  {
    "path": "examples/compatibilityExample/src/main/java/io/realm/examples/compatibility/MyApplication.kt",
    "content": "/*\n * Copyright 2019 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\npackage io.realm.examples.compatibility\n\nimport android.app.Application\n\nimport io.realm.Realm\nimport io.realm.log.LogLevel\nimport io.realm.log.RealmLog\nimport io.realm.mongodb.App\nimport io.realm.mongodb.AppConfiguration\n\nlateinit var APP: App\n\nclass MyApplication : Application() {\n\n    override fun onCreate() {\n        super.onCreate()\n        Realm.init(this)\n        APP = App(AppConfiguration.Builder(BuildConfig.MONGODB_REALM_APP_ID)\n                .baseUrl(BuildConfig.MONGODB_REALM_URL)\n                .appName(BuildConfig.VERSION_NAME)\n                .appVersion(BuildConfig.VERSION_CODE.toString())\n                .build())\n\n        // Enable more logging in debug mode\n        if (BuildConfig.DEBUG) {\n            RealmLog.setLevel(LogLevel.DEBUG)\n        }\n    }\n}\n"
  },
  {
    "path": "examples/compatibilityExample/src/main/res/layout/activity_my_activty.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<android.support.constraint.ConstraintLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    tools:context=\".MyActivity\">\n\n</android.support.constraint.ConstraintLayout>\n"
  },
  {
    "path": "examples/compatibilityExample/src/main/res/values/dimens.xml",
    "content": "<resources>\n    <!-- Default screen margins, per the Android Design guidelines. -->\n    <dimen name=\"activity_horizontal_margin\">16dp</dimen>\n    <dimen name=\"activity_vertical_margin\">16dp</dimen>\n</resources>\n"
  },
  {
    "path": "examples/compatibilityExample/src/main/res/values/realm_colors.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <!-- Grays -->\n    <color name=\"charcoal\">#1C233F</color>\n    <color name=\"elephant\">#9A9BA5</color>\n    <color name=\"elephant_half\">#b1b3bf</color>\n    <color name=\"dove\">#EBEBF2</color>\n\n    <!-- Orb colors -->\n    <color name=\"ultramarine\">#39477F</color>\n    <color name=\"indigo\">#59569E</color>\n    <color name=\"grape_jelly\">#9A59A5</color>\n    <color name=\"mulberry\">#D34CA3</color>\n    <color name=\"flamingo\">#F25192</color>\n    <color name=\"sexy_salmon\">#F77C88</color>\n    <color name=\"peach\">#FC9F95</color>\n    <color name=\"melon\">#FCC397</color>\n\n    <!-- Material adjustments -->\n    <color name=\"flamingo_darker\">#d64881</color>\n    <color name=\"touch_area_pressed\">#dadada</color>\n\n    <!-- Progress bar colors -->\n    <color name=\"progress_upload\">#EF5350</color>\n    <color name=\"progress_download\">#9CCC65</color>\n    <color name=\"progress_both\">#FFA726</color>\n\n</resources>"
  },
  {
    "path": "examples/compatibilityExample/src/main/res/values/strings.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <string name=\"app_name\">Realm Compatibility Example</string>\n    <string name=\"realm_logo\">Realm Logo</string>\n</resources>\n"
  },
  {
    "path": "examples/compatibilityExample/src/main/res/values/styles.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n\n    <!-- Base application theme. -->\n    <style name=\"AppTheme\" parent=\"Theme.AppCompat.Light.DarkActionBar\">\n        <item name=\"colorPrimary\">@color/flamingo</item>\n        <item name=\"colorPrimaryDark\">@color/flamingo_darker</item>\n        <item name=\"colorAccent\">@color/ultramarine</item>\n    </style>\n</resources>\n\n"
  },
  {
    "path": "examples/coroutinesExample/build.gradle",
    "content": "apply plugin: 'com.android.application'\napply plugin: 'kotlin-android'\napply plugin: 'kotlin-android-extensions'\napply plugin: 'kotlin-kapt'\napply plugin: 'realm-android'\n\nandroid {\n    // androidx.lifecycle dependencies requires Android APIs 31 or later\n    compileSdkVersion 31\n    buildToolsVersion rootProject.buildTools\n\n    defaultConfig {\n        applicationId \"io.realm.examples.coroutinesexample\"\n        targetSdkVersion rootProject.sdkVersion\n        minSdkVersion rootProject.minSdkVersion\n        versionCode 1\n        versionName \"1.0\"\n        multiDexEnabled true\n\n        testInstrumentationRunner \"android.support.test.runner.AndroidJUnitRunner\"\n    }\n\n    buildTypes {\n        release {\n            minifyEnabled false\n            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'\n        }\n    }\n\n    buildFeatures {\n        dataBinding true\n    }\n\n    packagingOptions {\n        exclude 'META-INF/LICENSE'\n    }\n\n    compileOptions {\n        sourceCompatibility JavaVersion.VERSION_1_8\n        targetCompatibility JavaVersion.VERSION_1_8\n    }\n\n    kotlinOptions {\n        jvmTarget = JavaVersion.VERSION_1_8.toString()\n    }\n}\n\ndependencies {\n    implementation fileTree(dir: \"libs\", include: [\"*.jar\"])\n    implementation \"org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version\"\n\n    implementation \"androidx.activity:activity-ktx:1.1.0\"\n\n    implementation \"androidx.appcompat:appcompat:1.2.0\"\n\n    implementation \"androidx.constraintlayout:constraintlayout:2.0.4\"\n    implementation \"androidx.coordinatorlayout:coordinatorlayout:1.1.0\"\n\n    implementation \"androidx.fragment:fragment-ktx:1.2.5\"\n\n    implementation \"androidx.lifecycle:lifecycle-viewmodel-ktx:2.4.0\"\n    implementation \"androidx.lifecycle:lifecycle-runtime-ktx:2.4.0\"\n    implementation \"androidx.lifecycle:lifecycle-livedata-ktx:2.4.0\"\n    implementation \"androidx.lifecycle:lifecycle-common-java8:2.4.0\"\n\n    implementation \"androidx.legacy:legacy-support-v4:1.0.0\"\n\n    implementation \"androidx.multidex:multidex:2.0.1\"\n\n    implementation \"androidx.recyclerview:recyclerview:1.1.0\"\n\n    implementation \"com.dropbox.mobile.store:store4:4.0.5\"\n\n    implementation \"com.google.android.material:material:1.2.1\"\n\n    implementation \"com.squareup.retrofit2:adapter-rxjava2:2.3.0\"\n    implementation \"com.squareup.retrofit2:retrofit:2.8.1\"\n    implementation \"com.squareup.retrofit2:converter-moshi:2.8.1\"\n    implementation \"com.squareup.okhttp3:logging-interceptor:4.9.0\"\n\n    implementation \"org.jetbrains.kotlinx:kotlinx-coroutines-rx2:1.4.0\"\n\n    testImplementation 'junit:junit:4.13'\n    androidTestImplementation 'com.android.support.test:runner:1.0.2'\n    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'\n}\n"
  },
  {
    "path": "examples/coroutinesExample/proguard-rules.pro",
    "content": "# Add project specific ProGuard rules here.\n# You can control the set of applied configuration files using the\n# proguardFiles setting in build.gradle.\n#\n# For more details, see\n#   http://developer.android.com/guide/developing/tools/proguard.html\n\n# If your project uses WebView with JS, uncomment the following\n# and specify the fully qualified class name to the JavaScript interface\n# class:\n#-keepclassmembers class fqcn.of.javascript.interface.for.webview {\n#   public *;\n#}\n\n# Uncomment this to preserve the line number information for\n# debugging stack traces.\n#-keepattributes SourceFile,LineNumberTable\n\n# If you keep the line number information, uncomment this to\n# hide the original source file name.\n#-renamesourcefileattribute SourceFile\n"
  },
  {
    "path": "examples/coroutinesExample/src/main/AndroidManifest.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    package=\"io.realm.examples.coroutinesexample\">\n\n    <uses-permission android:name=\"android.permission.INTERNET\" />\n\n    <application\n        android:name=\".MainApplication\"\n        android:allowBackup=\"true\"\n        android:icon=\"@mipmap/ic_launcher\"\n        android:label=\"@string/app_name\"\n        android:roundIcon=\"@mipmap/ic_launcher_round\"\n        android:supportsRtl=\"true\"\n        android:theme=\"@style/AppTheme\">\n        <activity android:name=\".MainActivity\">\n            <intent-filter>\n                <action android:name=\"android.intent.action.MAIN\" />\n\n                <category android:name=\"android.intent.category.LAUNCHER\" />\n            </intent-filter>\n        </activity>\n    </application>\n\n</manifest>\n"
  },
  {
    "path": "examples/coroutinesExample/src/main/java/io/realm/examples/coroutinesexample/MainActivity.kt",
    "content": "/*\n * Copyright 2020 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\npackage io.realm.examples.coroutinesexample\n\nimport android.os.Bundle\nimport androidx.appcompat.app.AppCompatActivity\nimport androidx.fragment.app.Fragment\nimport androidx.fragment.app.commit\nimport io.realm.examples.coroutinesexample.ui.details.DetailsFragment\nimport io.realm.examples.coroutinesexample.ui.main.MainFragment\nimport kotlin.time.ExperimentalTime\n\n@ExperimentalTime\nclass MainActivity : AppCompatActivity(), MainFragment.OnItemClicked {\n\n    override fun onCreate(savedInstanceState: Bundle?) {\n        super.onCreate(savedInstanceState)\n\n        setContentView(R.layout.activity_main)\n\n        if (savedInstanceState == null) {\n            showMainFragment()\n        }\n    }\n\n    override fun onAttachFragment(fragment: Fragment) {\n        when (fragment) {\n            is MainFragment -> fragment.onItemclickedCallback = this\n        }\n    }\n\n    override fun onBackPressed() {\n        val detailsFragment = supportFragmentManager.findFragmentByTag(DetailsFragment.TAG)\n        if (detailsFragment != null) {\n            supportFragmentManager.popBackStackImmediate()\n        } else {\n            super.onBackPressed()\n        }\n    }\n\n    override fun onItemClicked(id: String) {\n        val mainFragment = supportFragmentManager.findFragmentByTag(MainFragment.TAG)\n        val detailsFragment = DetailsFragment.instantiate(DetailsFragment.ArgsBundle(id))\n\n        supportFragmentManager.commit {\n            setCustomAnimations(R.anim.fragment_open_enter, R.anim.fragment_open_exit)\n            add(R.id.container, detailsFragment, DetailsFragment.TAG)\n            hide(requireNotNull(mainFragment))\n            addToBackStack(null)\n        }\n    }\n\n    private fun showMainFragment() {\n        supportFragmentManager.commit {\n            replace(R.id.container, MainFragment.newInstance(), MainFragment.TAG)\n        }\n    }\n}\n"
  },
  {
    "path": "examples/coroutinesExample/src/main/java/io/realm/examples/coroutinesexample/MainApplication.kt",
    "content": "/*\n * Copyright 2020 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\npackage io.realm.examples.coroutinesexample\n\nimport androidx.multidex.MultiDexApplication\nimport io.realm.Realm\nimport io.realm.examples.coroutinesexample.data.newsreader.local.repository.NewsReaderRepository\nimport io.realm.examples.coroutinesexample.di.DependencyGraph\n\nconst val TAG = \"--- CoroutinesExample\"\n\nclass MainApplication : MultiDexApplication() {\n\n    override fun onCreate() {\n        super.onCreate()\n        Realm.init(this)\n\n        repository = DependencyGraph.provideNewsReaderRepository()\n    }\n\n    companion object {\n        lateinit var repository: NewsReaderRepository\n    }\n}\n"
  },
  {
    "path": "examples/coroutinesExample/src/main/java/io/realm/examples/coroutinesexample/data/newsreader/local/RealmNYTDao.kt",
    "content": "/*\n * Copyright 2020 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\npackage io.realm.examples.coroutinesexample.data.newsreader.local\n\nimport io.realm.Realm\nimport io.realm.RealmConfiguration\nimport io.realm.RealmList\nimport io.realm.RealmResults\nimport io.realm.examples.coroutinesexample.data.newsreader.network.model.NYTMultimedium\nimport io.realm.examples.coroutinesexample.data.newsreader.network.model.NYTimesArticle\nimport io.realm.kotlin.executeTransactionAwait\nimport io.realm.kotlin.toFlow\nimport io.realm.kotlin.where\nimport kotlinx.coroutines.asCoroutineDispatcher\nimport kotlinx.coroutines.flow.Flow\nimport kotlinx.coroutines.withContext\nimport java.io.Closeable\nimport java.util.concurrent.Executors\n\n/**\n * Data Access Object interface used to gain access to Realm.\n *\n * It implements [Closeable] to allow proper Realm instance housekeeping linked to handling the\n * Android activity/fragment lifecycle.\n */\ninterface RealmNYTDao : Closeable {\n    suspend fun insertArticles(articles: List<RealmNYTimesArticle>)\n    suspend fun updateArticle(id: String)\n    suspend fun deleteArticles(section: String)\n    suspend fun deleteAllArticles()\n    fun getArticlesBlocking(section: String): RealmResults<RealmNYTimesArticle>\n    fun getArticles(section: String): Flow<List<RealmNYTimesArticle>>\n    fun getArticleBlocking(id: String): RealmNYTimesArticle?\n    fun getArticle(id: String): Flow<RealmNYTimesArticle?>\n    fun countArticles(section: String): Long\n}\n\nclass RealmNYTDaoImpl(\n        private val realmConfiguration: RealmConfiguration\n) : RealmNYTDao {\n\n    /**\n     * Dispatcher used to run suspendable functions that run Realm transactions. This is needed to\n     * confine Realm instances within the same thread as long as the coroutine is running to avoid\n     * accessing said instances from different threads and thus (potentially) triggering a thread\n     * violation.\n     */\n    private val monoThreadDispatcher = Executors.newFixedThreadPool(1).asCoroutineDispatcher()\n\n    /**\n     * [Realm] instance used to fire queries. It must not be used for other than firing queries and\n     * has to be closed when no longer in use.\n     */\n    private val realm = Realm.getInstance(realmConfiguration)\n\n    override suspend fun insertArticles(articles: List<RealmNYTimesArticle>) {\n        withContext(monoThreadDispatcher) {\n            runCloseableTransaction(realmConfiguration) { transactionRealm ->\n                transactionRealm.insertOrUpdate(articles)\n            }\n        }\n    }\n\n    override suspend fun updateArticle(id: String) {\n        withContext(monoThreadDispatcher) {\n            runCloseableTransaction(realmConfiguration) { transactionRealm ->\n                val article = transactionRealm.where<RealmNYTimesArticle>()\n                        .equalTo(RealmNYTimesArticle.COLUMN_URL, id)\n                        .findFirst()\n                checkNotNull(article).read = true\n            }\n        }\n    }\n\n    override suspend fun deleteArticles(section: String) {\n        withContext(monoThreadDispatcher) {\n            runCloseableTransaction(realmConfiguration) { transactionRealm ->\n                transactionRealm.deleteAll()\n            }\n        }\n    }\n\n    override suspend fun deleteAllArticles() {\n        withContext(monoThreadDispatcher) {\n            runCloseableTransaction(realmConfiguration) { transactionRealm ->\n                transactionRealm.deleteAll()\n            }\n        }\n    }\n\n    override fun getArticlesBlocking(section: String): RealmResults<RealmNYTimesArticle> {\n        return realm.where<RealmNYTimesArticle>()\n                .equalTo(RealmNYTimesArticle.COLUMN_API_SECTION, section)\n                .findAll()\n    }\n\n    override fun getArticles(section: String): Flow<List<RealmNYTimesArticle>> {\n        return realm.where<RealmNYTimesArticle>()\n                .equalTo(RealmNYTimesArticle.COLUMN_API_SECTION, section)\n                .findAllAsync()\n                .toFlow()\n    }\n\n    override fun getArticleBlocking(id: String): RealmNYTimesArticle? {\n        return realm.where<RealmNYTimesArticle>()\n                .equalTo(RealmNYTimesArticle.COLUMN_URL, id)\n                .findFirst()\n    }\n\n    override fun getArticle(id: String): Flow<RealmNYTimesArticle?> {\n        return realm.where<RealmNYTimesArticle>()\n                .equalTo(RealmNYTimesArticle.COLUMN_URL, id)\n                .findFirstAsync()\n                .toFlow()\n    }\n\n    override fun countArticles(section: String): Long {\n        return realm.where<RealmNYTimesArticle>()\n                .equalTo(RealmNYTimesArticle.COLUMN_API_SECTION, section)\n                .count()\n    }\n\n    override fun close() {\n        realm.close()\n    }\n}\n\n/**\n * Inserts a [List] of [NYTimesArticle]s after they have been mapped to [RealmNYTimesArticle]\n * instances.\n */\nsuspend fun RealmNYTDao.insertArticles(apiSection: String, articles: List<NYTimesArticle>) {\n    val realmArticles = articles.toRealmArticles(apiSection)\n    insertArticles(realmArticles)\n}\n\nprivate fun List<NYTimesArticle>.toRealmArticles(apiQuerySection: String): List<RealmNYTimesArticle> {\n    val timestamp = System.currentTimeMillis()\n    return map { article ->\n        RealmNYTimesArticle().apply {\n            updateTime = timestamp\n            apiSection = apiQuerySection\n            section = article.section\n            subsection = article.subsection\n            title = article.title\n            abstractText = article.abstractText\n            url = article.url\n            uri = article.uri\n            byline = article.byline\n            itemType = article.itemType\n            updatedDate = article.updatedDate\n            createDate = article.createDate\n            publishedDate = article.publishedDate\n            materialTypeFacet = article.materialTypeFacet\n            kicker = article.kicker\n            desFacet = RealmList<String>().apply { addAll(article.desFacet ?: listOf()) }\n            orgFacet = RealmList<String>().apply { addAll(article.orgFacet ?: listOf()) }\n            perFacet = RealmList<String>().apply { addAll(article.perFacet ?: listOf()) }\n            geoFacet = RealmList<String>().apply { addAll(article.geoFacet ?: listOf()) }\n            orgFacet = RealmList<String>().apply { addAll(article.orgFacet ?: listOf()) }\n            perFacet = RealmList<String>().apply { addAll(article.perFacet ?: listOf()) }\n            geoFacet = RealmList<String>().apply { addAll(article.geoFacet ?: listOf()) }\n            multimedia = article.multimedia.toRealmMultimediumRealmList()\n            shortUrl = article.shortUrl\n        }\n    }\n}\n\nprivate fun List<NYTMultimedium>?.toRealmMultimediumRealmList(): RealmList<RealmNYTMultimedium> {\n    return RealmList<RealmNYTMultimedium>().also { realmList ->\n        realmList.addAll(\n                this?.map { multimedium ->\n                    multimedium.toRealmMultimedium()\n                } ?: listOf()\n        )\n    }\n}\n\nprivate fun NYTMultimedium.toRealmMultimedium(): RealmNYTMultimedium {\n    return RealmNYTMultimedium().also {\n        it.url = url\n        it.format = format\n        it.height = height\n        it.width = width\n        it.type = type\n        it.subtype = subtype\n        it.caption = caption\n        it.copyright = copyright\n    }\n}\n\nprivate suspend fun runCloseableTransaction(\n        realmConfiguration: RealmConfiguration,\n        transaction: (realm: Realm) -> Unit\n) {\n    Realm.getInstance(realmConfiguration).use { realmInstance ->\n        realmInstance.executeTransactionAwait(transaction = transaction)\n    }\n}\n"
  },
  {
    "path": "examples/coroutinesExample/src/main/java/io/realm/examples/coroutinesexample/data/newsreader/local/RealmNYTimes.kt",
    "content": "/*\n * Copyright 2020 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\npackage io.realm.examples.coroutinesexample.data.newsreader.local\n\nimport io.realm.RealmList\nimport io.realm.RealmObject\nimport io.realm.annotations.LinkingObjects\nimport io.realm.annotations.PrimaryKey\nimport io.realm.annotations.RealmClass\nimport java.time.LocalDateTime\nimport java.util.*\n\nopen class RealmNYTimesArticle : RealmObject() {\n    var read: Boolean = false\n    var updateTime: Long = 0\n    var apiSection: String = \"\"\n    var section: String = \"\"\n    var subsection: String? = null\n    var title: String = \"\"\n    var abstractText: String? = null\n\n    @PrimaryKey\n    var url: String = UUID.randomUUID().toString()\n\n    var uri: String? = null\n    var byline: String? = null\n    var itemType: String? = null\n    var updatedDate: String? = null\n    var createDate: String? = null\n    var publishedDate: String? = null\n    var materialTypeFacet: String? = null\n    var kicker: String? = null\n    var desFacet: RealmList<String> = RealmList()\n    var orgFacet: RealmList<String> = RealmList()\n    var perFacet: RealmList<String> = RealmList()\n    var geoFacet: RealmList<String> = RealmList()\n    var multimedia: RealmList<RealmNYTMultimedium> = RealmList()\n    var shortUrl: String? = null\n\n    companion object {\n        const val EMBEDDED_MULTIMEDIA = \"multimedia\"\n        const val COLUMN_URL = \"url\"\n        const val COLUMN_API_SECTION = \"apiSection\"\n    }\n}\n\n@RealmClass(embedded = true)\nopen class RealmNYTMultimedium : RealmObject() {\n    var url: String? = null\n    var format: String? = null\n    var height: Int = 0\n    var width: Int = 0\n    var type: String? = null\n    var subtype: String? = null\n    var caption: String? = null\n    var copyright: String? = null\n\n    @LinkingObjects(RealmNYTimesArticle.EMBEDDED_MULTIMEDIA)\n    val parent = RealmNYTimesArticle()\n}\n"
  },
  {
    "path": "examples/coroutinesExample/src/main/java/io/realm/examples/coroutinesexample/data/newsreader/local/repository/NewsReaderRepository.kt",
    "content": "/*\n * Copyright 2020 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\npackage io.realm.examples.coroutinesexample.data.newsreader.local.repository\n\nimport androidx.lifecycle.LiveData\nimport androidx.lifecycle.MutableLiveData\nimport com.dropbox.android.external.store4.*\nimport io.realm.examples.coroutinesexample.data.newsreader.local.RealmNYTDao\nimport io.realm.examples.coroutinesexample.data.newsreader.local.RealmNYTimesArticle\nimport io.realm.examples.coroutinesexample.ui.main.NewsReaderState\nimport kotlinx.coroutines.CoroutineScope\nimport kotlinx.coroutines.Job\nimport kotlinx.coroutines.cancelAndJoin\nimport kotlinx.coroutines.flow.Flow\nimport kotlinx.coroutines.flow.launchIn\nimport kotlinx.coroutines.flow.onEach\nimport kotlinx.coroutines.launch\n\nprivate const val THIRTY_MINUTES = 30 * 60 * 1000\n\nclass NewsReaderRepository(\n        private val dao: RealmNYTDao,\n        private val store: Store<String, List<RealmNYTimesArticle>>\n) {\n\n    private val _newsReaderState = MutableLiveData<NewsReaderState>()\n    val newsReaderState: LiveData<NewsReaderState>\n        get() = _newsReaderState\n\n    private val sectionRefreshJobs = mutableMapOf<String, Job>()\n\n    fun getTopStories(scope: CoroutineScope, apiSection: String, refresh: Boolean = false) {\n        scope.launch {\n            if (refresh) {\n                store.fresh(apiSection)\n            } else {\n                getFromStream(scope, apiSection)\n            }\n        }\n    }\n\n    fun getStory(id: String): Flow<RealmNYTimesArticle?> {\n        return dao.getArticle(id)\n    }\n\n    fun updateArticle(scope: CoroutineScope, id: String) {\n        scope.launch {\n            dao.updateArticle(id)\n        }\n    }\n\n    fun close() {\n        dao.close()\n        sectionRefreshJobs.values.forEach { it.cancel() }\n        sectionRefreshJobs.clear()\n    }\n\n    private fun getFromStream(scope: CoroutineScope, apiSection: String) {\n        store.stream(StoreRequest.cached(\n                key = apiSection,\n                refresh = false\n        )).onEach { response ->\n            val origin = response.origin.toString()\n            when (response) {\n                is StoreResponse.Loading -> NewsReaderState.Loading(origin)\n                is StoreResponse.Data -> getNewsReaderState(response, store, apiSection, origin)\n                is StoreResponse.NoNewData -> NewsReaderState.NoNewData(origin)\n                is StoreResponse.Error.Exception -> NewsReaderState.ErrorException(origin, response.error)\n                is StoreResponse.Error.Message -> NewsReaderState.ErrorMessage(origin, response.message)\n            }.also {\n                _newsReaderState.postValue(it)\n            }\n        }.launchIn(\n                scope\n        ).also { job ->\n            scope.launch {\n                sectionRefreshJobs.values.forEach { it.cancelAndJoin() }\n                sectionRefreshJobs.clear()\n                sectionRefreshJobs[apiSection] = job\n            }\n        }\n    }\n\n    private suspend fun getNewsReaderState(\n            response: StoreResponse.Data<List<RealmNYTimesArticle>>,\n            store: Store<String, List<RealmNYTimesArticle>>,\n            apiSection: String,\n            origin: String\n    ): NewsReaderState {\n        val data = response.value\n        return if (data.isNotEmpty()) {\n            data.first()\n                    .let { firstElement ->\n                        val now = System.currentTimeMillis()\n                        val entryExpired = (firstElement.updateTime + THIRTY_MINUTES) < now\n\n                        if (!(response.origin == ResponseOrigin.Fetcher || !entryExpired)) {\n                            store.fresh(apiSection)\n                            NewsReaderState.Loading(origin)\n                        } else {\n                            NewsReaderState.Data(origin, response.value)\n                        }\n                    }\n        } else {\n            NewsReaderState.Data(origin, response.value)\n        }\n    }\n}\n"
  },
  {
    "path": "examples/coroutinesExample/src/main/java/io/realm/examples/coroutinesexample/data/newsreader/network/NYTimesApiClient.kt",
    "content": "/*\n * Copyright 2020 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\npackage io.realm.examples.coroutinesexample.data.newsreader.network\n\nimport io.realm.examples.coroutinesexample.data.newsreader.network.model.NYTimesResponse\nimport okhttp3.HttpUrl\nimport okhttp3.OkHttpClient\nimport okhttp3.Request\nimport okhttp3.logging.HttpLoggingInterceptor\nimport retrofit2.Retrofit\nimport retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory\nimport retrofit2.converter.moshi.MoshiConverterFactory\n\nprivate const val API_KEY = \"YUPmyj0Q09Fm2VlCHmD9FU7rpCcI5dUD\"\n\ninterface NYTimesApiClient {\n    suspend fun getTopStories(section: String): NYTimesResponse\n}\n\nclass NYTimesApiClientImpl : NYTimesApiClient {\n\n    private val service: NYTimesService\n\n    init {\n        val okHttpClient = OkHttpClient.Builder()\n                .addInterceptor(\n                        HttpLoggingInterceptor()\n                                .apply { setLevel(HttpLoggingInterceptor.Level.BASIC) }\n                )\n                .addInterceptor { chain ->\n                    val original = chain.request()\n                    val originalHttpUrl = original.url\n\n                    val url = originalHttpUrl.newBuilder()\n                            .addEncodedQueryParameter(\"api-key\", API_KEY)\n                            .build()\n\n                    val requestBuilder: Request.Builder = original.newBuilder()\n                            .url(url)\n\n                    val request: Request = requestBuilder.build()\n                    chain.proceed(request)\n                }\n                .build()\n\n        service = Retrofit.Builder()\n                .client(okHttpClient)\n                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())\n                .addConverterFactory(MoshiConverterFactory.create())\n                .baseUrl(\"https://api.nytimes.com/\")\n                .build()\n                .create<NYTimesService>(NYTimesService::class.java)\n    }\n\n    override suspend fun getTopStories(section: String): NYTimesResponse {\n        return service.topStories(section)\n    }\n}\n"
  },
  {
    "path": "examples/coroutinesExample/src/main/java/io/realm/examples/coroutinesexample/data/newsreader/network/NYTimesService.kt",
    "content": "/*\n * Copyright 2020 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\npackage io.realm.examples.coroutinesexample.data.newsreader.network\n\nimport io.realm.examples.coroutinesexample.data.newsreader.network.model.NYTimesResponse\nimport retrofit2.http.GET\nimport retrofit2.http.Path\n\ninterface NYTimesService {\n    @GET(\"svc/topstories/v2/{section}.json\")\n    suspend fun topStories(@Path(\"section\") section: String): NYTimesResponse\n}\n\nval sectionsToNames = mapOf(\n        \"Home\" to \"home\",\n        \"World\" to \"world\",\n        \"National\" to \"national\",\n        \"Politics\" to \"politics\",\n        \"NY Region\" to \"nyregion\",\n        \"Business\" to \"business\",\n        \"Opinion\" to \"opinion\",\n        \"Technology\" to \"technology\",\n        \"Science\" to \"science\",\n        \"Health\" to \"health\",\n        \"Sports\" to \"sports\",\n        \"Arts\" to \"arts\",\n        \"Fashion\" to \"fashion\",\n        \"Dining\" to \"dining\",\n        \"Travel\" to \"travel\",\n        \"Magazine\" to \"magazine\",\n        \"Real Estate\" to \"realestate\"\n)\n"
  },
  {
    "path": "examples/coroutinesExample/src/main/java/io/realm/examples/coroutinesexample/data/newsreader/network/model/NYTimes.kt",
    "content": "/*\n * Copyright 2020 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\npackage io.realm.examples.coroutinesexample.data.newsreader.network.model\n\nimport com.squareup.moshi.Json\n\ndata class NYTimesResponse(\n        val status: String,\n        val copyright: String,\n        val section: String,\n        @field:Json(name = \"last_updated\") val lastUpdated: String,\n        @field:Json(name = \"num_results\") val numResults: Int,\n        val results: List<NYTimesArticle>\n)\n\ndata class NYTimesArticle(\n        val section: String,\n        val subsection: String,\n        val title: String,\n        @field:Json(name = \"abstract\") val abstractText: String?,\n        val url: String,\n        val uri: String,\n        val byline: String,\n        @field:Json(name = \"item_type\") val itemType: String?,\n        @field:Json(name = \"updated_date\") val updatedDate: String?,\n        @field:Json(name = \"created_date\") val createDate: String?,\n        @field:Json(name = \"published_date\") val publishedDate: String?,\n        @field:Json(name = \"material_type_facet\") val materialTypeFacet: String?,\n        val kicker: String,\n        @field:Json(name = \"des_facet\") val desFacet: List<String>?,\n        @field:Json(name = \"org_facet\") val orgFacet: List<String>?,\n        @field:Json(name = \"per_facet\") val perFacet: List<String>?,\n        @field:Json(name = \"geo_facet\") val geoFacet: List<String>?,\n        val multimedia: List<NYTMultimedium>,\n        @field:Json(name = \"short_url\") val shortUrl: String?\n)\n\ndata class NYTMultimedium(\n        val url: String,\n        val format: String,\n        val height: Int,\n        val width: Int,\n        val type: String,\n        val subtype: String,\n        val caption: String,\n        val copyright: String\n)\n"
  },
  {
    "path": "examples/coroutinesExample/src/main/java/io/realm/examples/coroutinesexample/di/DependencyGraph.kt",
    "content": "/*\n * Copyright 2020 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\npackage io.realm.examples.coroutinesexample.di\n\nimport com.dropbox.android.external.store4.Fetcher\nimport com.dropbox.android.external.store4.SourceOfTruth\nimport com.dropbox.android.external.store4.Store\nimport com.dropbox.android.external.store4.StoreBuilder\nimport io.realm.RealmConfiguration\nimport io.realm.examples.coroutinesexample.data.newsreader.local.RealmNYTDao\nimport io.realm.examples.coroutinesexample.data.newsreader.local.RealmNYTDaoImpl\nimport io.realm.examples.coroutinesexample.data.newsreader.local.RealmNYTimesArticle\nimport io.realm.examples.coroutinesexample.data.newsreader.local.insertArticles\nimport io.realm.examples.coroutinesexample.data.newsreader.local.repository.NewsReaderRepository\nimport io.realm.examples.coroutinesexample.data.newsreader.network.NYTimesApiClient\nimport io.realm.examples.coroutinesexample.data.newsreader.network.NYTimesApiClientImpl\nimport io.realm.examples.coroutinesexample.data.newsreader.network.model.NYTimesArticle\nimport io.realm.examples.coroutinesexample.util.NewsReaderFlowFactory\nimport kotlinx.coroutines.flow.map\n\n/**\n * Homemade, simple DI solution - ideally, we should use a proper DI framework instead.\n */\nobject DependencyGraph {\n\n    // Repository dependencies\n    fun provideNewsReaderRepository(): NewsReaderRepository =\n            NewsReaderRepository(provideRealmDao(), provideStore())\n\n    private fun provideStore(): Store<String, List<RealmNYTimesArticle>> = StoreBuilder.from(\n            fetcher = provideFetcher(provideApiClient()),\n            sourceOfTruth = provideSourceOfTruth(provideRealmDao())\n    ).build()\n\n    private fun provideFetcher(nytApiClient: NYTimesApiClient): Fetcher<String, List<NYTimesArticle>> =\n            Fetcher.of { apiSection ->\n                nytApiClient.getTopStories(apiSection).results\n            }\n\n    private fun provideSourceOfTruth(realmDao: RealmNYTDao): SourceOfTruth<String, List<NYTimesArticle>, List<RealmNYTimesArticle>> =\n            SourceOfTruth.of(\n                    reader = { apiSection ->\n                        realmDao.getArticles(apiSection)\n                                .map { articles ->\n                                    if (articles.isEmpty()) null\n                                    else articles\n                                }\n                    },\n                    writer = { apiSection, articles ->\n                        realmDao.insertArticles(apiSection, articles)\n                    },\n                    delete = { apiSection ->\n                        realmDao.deleteArticles(apiSection)\n                    },\n                    deleteAll = {\n                        realmDao.deleteAllArticles()\n                    }\n            )\n\n    // Database dependencies\n    private fun provideRealmDao(): RealmNYTDao = RealmNYTDaoImpl(provideRealmConfig())\n\n    private fun provideRealmConfig(): RealmConfiguration = RealmConfiguration.Builder()\n            .flowFactory(NewsReaderFlowFactory())\n            .build()\n\n    // Network dependencies\n    private fun provideApiClient(): NYTimesApiClient = NYTimesApiClientImpl()\n}\n"
  },
  {
    "path": "examples/coroutinesExample/src/main/java/io/realm/examples/coroutinesexample/ui/details/DetailsFragment.kt",
    "content": "/*\n * Copyright 2020 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\npackage io.realm.examples.coroutinesexample.ui.details\n\nimport android.os.Bundle\nimport android.view.LayoutInflater\nimport android.view.View\nimport android.view.ViewGroup\nimport androidx.fragment.app.Fragment\nimport androidx.fragment.app.viewModels\nimport androidx.lifecycle.Observer\nimport io.realm.examples.coroutinesexample.databinding.FragmentDetailsBinding\nimport kotlin.time.ExperimentalTime\n\n@ExperimentalTime\nclass DetailsFragment : Fragment() {\n\n    private val viewModel: DetailsViewModel by viewModels()\n\n    private lateinit var binding: FragmentDetailsBinding\n\n    override fun onCreateView(\n            inflater: LayoutInflater,\n            container: ViewGroup?,\n            savedInstanceState: Bundle?\n    ): View? {\n        return FragmentDetailsBinding.inflate(inflater, container, false)\n                .also { binding ->\n                    this.binding = binding\n                    binding.lifecycleOwner = viewLifecycleOwner\n                    binding.viewModel = viewModel\n                    setupLiveData()\n                }.root\n    }\n\n    override fun onActivityCreated(savedInstanceState: Bundle?) {\n        super.onActivityCreated(savedInstanceState)\n\n        val id = requireNotNull(requireArguments().getString(ARG_ID))\n        viewModel.loadDetails(id)\n    }\n\n    private fun setupLiveData() {\n        viewModel.read.observe(viewLifecycleOwner, Observer {\n            setRead()\n        })\n    }\n\n    private fun setRead() {\n        with(binding.read) {\n            animate().alpha(1.0f)\n        }\n    }\n\n    data class ArgsBundle(val id: String)\n\n    companion object {\n\n        const val TAG = \"DetailsFragment\"\n\n        private const val ARG_ID = \"id\"\n\n        fun instantiate(argsBundle: ArgsBundle): DetailsFragment {\n            return DetailsFragment().apply {\n                arguments = Bundle().apply {\n                    putString(ARG_ID, argsBundle.id)\n                }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "examples/coroutinesExample/src/main/java/io/realm/examples/coroutinesexample/ui/details/DetailsViewModel.kt",
    "content": "/*\n * Copyright 2020 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\npackage io.realm.examples.coroutinesexample.ui.details\n\nimport androidx.lifecycle.*\nimport io.realm.examples.coroutinesexample.data.newsreader.local.RealmNYTimesArticle\nimport io.realm.examples.coroutinesexample.di.DependencyGraph\nimport kotlinx.coroutines.currentCoroutineContext\nimport kotlinx.coroutines.delay\nimport kotlinx.coroutines.flow.flow\nimport kotlinx.coroutines.flow.launchIn\nimport kotlinx.coroutines.flow.onEach\nimport kotlinx.coroutines.isActive\nimport kotlin.time.ExperimentalTime\nimport kotlin.time.seconds\n\n@ExperimentalTime\nclass DetailsViewModel : ViewModel() {\n\n    private val repository = DependencyGraph.provideNewsReaderRepository()\n\n    private val article = MutableLiveData<RealmNYTimesArticle>()\n\n    private val _read = MutableLiveData<Boolean>()\n    val read: LiveData<Boolean>\n        get() = _read\n\n    val date = article.map { it.updatedDate.toString() }\n    val title = article.map { it.title }\n    val articleText = article.map { it.abstractText }\n\n    override fun onCleared() {\n        repository.close()\n    }\n\n    fun loadDetails(id: String) {\n        repository.getStory(id)\n                .onEach { realmArticle ->\n                    checkNotNull(realmArticle)\n                            .also {\n                                if (article.value == null) {\n                                    article.postValue(it)\n\n                                    if (!it.read) {\n                                        markAsRead(it)\n                                    } else {\n                                        markAsRead(it, true)\n                                    }\n                                }\n                            }\n                }.launchIn(viewModelScope)\n    }\n\n    private fun markAsRead(article: RealmNYTimesArticle, immediately: Boolean = false) {\n        if (immediately) {\n            _read.postValue(true)\n        } else {\n            flow<Unit> {\n                delay(2.seconds)\n                repository.updateArticle(viewModelScope, article.url)\n                _read.postValue(true)\n            }.launchIn(viewModelScope)\n        }\n    }\n}\n"
  },
  {
    "path": "examples/coroutinesExample/src/main/java/io/realm/examples/coroutinesexample/ui/main/MainAdapter.kt",
    "content": "/*\n * Copyright 2020 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\npackage io.realm.examples.coroutinesexample.ui.main\n\nimport android.view.LayoutInflater\nimport android.view.View\nimport android.view.ViewGroup\nimport android.widget.TextView\nimport androidx.recyclerview.widget.DiffUtil\nimport androidx.recyclerview.widget.ListAdapter\nimport androidx.recyclerview.widget.RecyclerView\nimport io.realm.examples.coroutinesexample.R\nimport io.realm.examples.coroutinesexample.data.newsreader.local.RealmNYTimesArticle\n\nclass MainAdapter(\n        private val onClick: (String) -> Unit\n) : ListAdapter<RealmNYTimesArticle, MainAdapter.ArticleViewHolder>(DIFF_CALLBACK) {\n\n    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ArticleViewHolder =\n            LayoutInflater.from(parent.context)\n                    .inflate(R.layout.item_article, parent, false)\n                    .let { view -> ArticleViewHolder(view) }\n\n    override fun onBindViewHolder(holder: ArticleViewHolder, position: Int) {\n        with(holder.title) {\n            val article = getItem(position)\n\n            text = article.title\n            isEnabled = !article.read\n        }\n    }\n\n    inner class ArticleViewHolder(view: View) : RecyclerView.ViewHolder(view) {\n\n        val title: TextView = view.findViewById(R.id.title)\n\n        init {\n            view.setOnClickListener {\n                onClick.invoke(getItem(adapterPosition).url)\n            }\n        }\n    }\n\n    companion object {\n        val DIFF_CALLBACK = object : DiffUtil.ItemCallback<RealmNYTimesArticle>() {\n            override fun areItemsTheSame(oldItem: RealmNYTimesArticle, newItem: RealmNYTimesArticle): Boolean =\n                    oldItem == newItem\n\n            override fun areContentsTheSame(oldItem: RealmNYTimesArticle, newItem: RealmNYTimesArticle): Boolean =\n                    oldItem.read == newItem.read\n                            && oldItem.title == newItem.title\n                            && oldItem.abstractText == newItem.abstractText\n        }\n    }\n}\n"
  },
  {
    "path": "examples/coroutinesExample/src/main/java/io/realm/examples/coroutinesexample/ui/main/MainFragment.kt",
    "content": "/*\n * Copyright 2020 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\npackage io.realm.examples.coroutinesexample.ui.main\n\nimport android.os.Bundle\nimport android.util.Log\nimport android.view.LayoutInflater\nimport android.view.View\nimport android.view.ViewGroup\nimport android.widget.AdapterView\nimport android.widget.ArrayAdapter\nimport android.widget.SpinnerAdapter\nimport android.widget.Toast\nimport androidx.fragment.app.Fragment\nimport androidx.fragment.app.viewModels\nimport androidx.lifecycle.Observer\nimport androidx.recyclerview.widget.LinearLayoutManager\nimport io.realm.examples.coroutinesexample.R\nimport io.realm.examples.coroutinesexample.data.newsreader.local.RealmNYTimesArticle\nimport io.realm.examples.coroutinesexample.data.newsreader.network.sectionsToNames\nimport io.realm.examples.coroutinesexample.databinding.FragmentMainBinding\nimport java.util.*\nimport kotlin.Comparator\n\nclass MainFragment : Fragment() {\n\n    interface OnItemClicked {\n        fun onItemClicked(id: String)\n    }\n\n    internal lateinit var onItemclickedCallback: OnItemClicked\n\n    private val viewModel: MainViewModel by viewModels()\n    private val newsReaderAdapter = MainAdapter { id ->\n        onItemclickedCallback.onItemClicked(id)\n    }\n\n    private lateinit var binding: FragmentMainBinding\n\n    override fun onCreateView(\n            inflater: LayoutInflater,\n            container: ViewGroup?,\n            savedInstanceState: Bundle?\n    ): View? = FragmentMainBinding.inflate(inflater, container, false)\n            .also { binding ->\n                binding.lifecycleOwner = viewLifecycleOwner\n                this.binding = binding\n                setupSpinner()\n                setupRecyclerView()\n                setupLiveData()\n            }.root\n\n    private fun setupSpinner() {\n        with(binding.spinner) {\n            adapter = ArrayAdapter<CharSequence>(\n                    context,\n                    android.R.layout.simple_spinner_dropdown_item,\n                    sectionsToNames.keys.sortedWith(\n                            Comparator { o1, o2 ->\n                                if (o1.toLowerCase(Locale.ROOT) == \"home\") return@Comparator -1\n                                if (o2.toLowerCase(Locale.ROOT) == \"home\") return@Comparator 1\n                                return@Comparator o1.compareTo(o2, ignoreCase = true)\n                            }\n                    )\n            )\n            onItemSelectedListener = object : AdapterView.OnItemSelectedListener {\n                override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {\n                    viewModel.getTopStories(getApiSection(adapter, position))\n                }\n\n                override fun onNothingSelected(parent: AdapterView<*>?) {\n                    // No-op\n                }\n            }\n        }\n    }\n\n    private fun setupRecyclerView() {\n        with(binding.list) {\n            layoutManager = LinearLayoutManager(context)\n            adapter = newsReaderAdapter\n        }\n\n        with(binding.refresh) {\n            setOnRefreshListener {\n                with(binding.spinner) {\n                    viewModel.getTopStories(getApiSection(adapter, selectedItemPosition), true)\n                }\n            }\n        }\n    }\n\n    private fun setupLiveData() {\n        viewModel.newsReaderState.observe(viewLifecycleOwner, Observer { viewState ->\n            when (viewState) {\n                is NewsReaderState.Loading -> {\n                    Log.d(TAG, \"--- origin: ${viewState.origin}, loading\")\n                    RealmStateHelper.loading(binding)\n                }\n                is NewsReaderState.Data -> {\n                    Log.d(TAG, \"--- origin: ${viewState.origin}, elements: ${viewState.data.size}\")\n                    RealmStateHelper.data(binding, viewState.data, newsReaderAdapter)\n                }\n                is NewsReaderState.NoNewData -> {\n                    Log.d(TAG, \"--- origin: ${viewState.origin}, no new data\")\n                    RealmStateHelper.noNewData(binding)\n                }\n                is NewsReaderState.ErrorException -> {\n                    val stacktrace = viewState.throwable.cause?.stackTrace?.joinToString { \"$it\\n\" }\n                    Log.e(TAG, \"--- error (exception): ${viewState.throwable.message} - ${viewState.throwable.cause?.message}: $stacktrace\")\n                    RealmStateHelper.error(binding)\n                }\n                is NewsReaderState.ErrorMessage -> {\n                    Log.e(TAG, \"--- error (message): ${viewState.message}\")\n                    RealmStateHelper.error(binding)\n                }\n            }\n        })\n    }\n\n    private fun getApiSection(adapter: SpinnerAdapter, position: Int): String {\n        val apiSection = adapter.getItem(position) as String\n        return requireNotNull(sectionsToNames[apiSection])\n    }\n\n    companion object {\n\n        const val TAG = \"MainFragment\"\n\n        fun newInstance() = MainFragment()\n    }\n}\n\nsealed class NewsReaderState {\n\n    abstract val origin: String\n\n    data class Loading(override val origin: String) : NewsReaderState()\n    data class Data(override val origin: String, val data: List<RealmNYTimesArticle>) : NewsReaderState()\n    data class NoNewData(override val origin: String) : NewsReaderState()\n    data class ErrorException(override val origin: String, val throwable: Throwable) : NewsReaderState()\n    data class ErrorMessage(override val origin: String, val message: String) : NewsReaderState()\n}\n\nprivate object RealmStateHelper {\n    fun loading(binding: FragmentMainBinding) {\n        if (!binding.refresh.isRefreshing) {\n            binding.refresh.setRefreshing(true)\n        }\n    }\n\n    fun data(\n            binding: FragmentMainBinding,\n            data: List<RealmNYTimesArticle>,\n            newsReaderAdapter: MainAdapter\n    ) {\n        hideLoadingSpinner(binding)\n        newsReaderAdapter.submitList(data)\n    }\n\n    fun noNewData(binding: FragmentMainBinding) {\n        hideLoadingSpinner(binding)\n    }\n\n    fun error(binding: FragmentMainBinding) {\n        hideLoadingSpinner(binding)\n        Toast.makeText(binding.root.context, R.string.error_generic, Toast.LENGTH_SHORT).show()\n    }\n\n    private fun hideLoadingSpinner(binding: FragmentMainBinding) {\n        if (binding.refresh.isRefreshing) {\n            binding.refresh.setRefreshing(false)\n        }\n    }\n\n    private fun showLoadingSpinner(binding: FragmentMainBinding) {\n        if (!binding.refresh.isRefreshing) {\n            binding.refresh.setRefreshing(true)\n        }\n    }\n}\n"
  },
  {
    "path": "examples/coroutinesExample/src/main/java/io/realm/examples/coroutinesexample/ui/main/MainViewModel.kt",
    "content": "/*\n * Copyright 2020 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\npackage io.realm.examples.coroutinesexample.ui.main\n\nimport android.util.Log\nimport androidx.lifecycle.LiveData\nimport androidx.lifecycle.ViewModel\nimport androidx.lifecycle.viewModelScope\nimport io.realm.examples.coroutinesexample.TAG\nimport io.realm.examples.coroutinesexample.di.DependencyGraph\n\nclass MainViewModel : ViewModel() {\n\n    private val repository = DependencyGraph.provideNewsReaderRepository()\n\n    val newsReaderState: LiveData<NewsReaderState>\n        get() = repository.newsReaderState\n\n    override fun onCleared() {\n        repository.close()\n    }\n\n    fun getTopStories(apiSection: String, refresh: Boolean = false) {\n        Log.d(TAG, \"------ apiSection: $apiSection - refresh '$refresh'\")\n        repository.getTopStories(viewModelScope, apiSection, refresh)\n    }\n}\n"
  },
  {
    "path": "examples/coroutinesExample/src/main/java/io/realm/examples/coroutinesexample/util/NewsReaderFlowFactory.kt",
    "content": "/*\n * Copyright 2020 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\npackage io.realm.examples.coroutinesexample.util\n\nimport io.realm.DynamicRealm\nimport io.realm.Realm\nimport io.realm.RealmResults\nimport io.realm.coroutines.RealmFlowFactory\nimport io.realm.rx.CollectionChange\nimport kotlinx.coroutines.flow.Flow\nimport kotlinx.coroutines.flow.drop\n\n/**\n * Similar to [io.realm.coroutines.RealmFlowFactory] but it will not emit the current value\n * immediately. This is needed by Store to function properly or else it will receive updates with\n * empty [RealmResults] that will make it think existing values for the current key are present.\n *\n * There is no need to override the methods for [io.realm.RealmModel] since the internal factory\n * does check whether or not an object is loaded before the first emission.\n */\nclass NewsReaderFlowFactory : RealmFlowFactory(true) {\n\n    override fun <T> from(\n            realm: Realm,\n            results: RealmResults<T>\n    ): Flow<RealmResults<T>> =\n            super.from(realm, results)\n                    .drop(1)\n\n    override fun <T> from(\n            dynamicRealm: DynamicRealm,\n            results: RealmResults<T>\n    ): Flow<RealmResults<T>> =\n            super.from(dynamicRealm, results)\n                    .drop(1)\n\n    override fun <T> changesetFrom(\n            realm: Realm,\n            results: RealmResults<T>\n    ): Flow<CollectionChange<RealmResults<T>>> =\n            super.changesetFrom(realm, results)\n                    .drop(1)\n\n    override fun <T> changesetFrom(\n            dynamicRealm: DynamicRealm,\n            results: RealmResults<T>\n    ): Flow<CollectionChange<RealmResults<T>>> =\n            super.changesetFrom(dynamicRealm, results)\n                    .drop(1)\n}\n"
  },
  {
    "path": "examples/coroutinesExample/src/main/res/drawable/ic_launcher_background.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:width=\"108dp\"\n    android:height=\"108dp\"\n    android:viewportWidth=\"108\"\n    android:viewportHeight=\"108\">\n    <path\n        android:fillColor=\"#3DDC84\"\n        android:pathData=\"M0,0h108v108h-108z\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M9,0L9,108\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M19,0L19,108\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M29,0L29,108\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M39,0L39,108\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M49,0L49,108\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M59,0L59,108\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M69,0L69,108\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M79,0L79,108\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M89,0L89,108\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M99,0L99,108\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M0,9L108,9\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M0,19L108,19\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M0,29L108,29\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M0,39L108,39\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M0,49L108,49\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M0,59L108,59\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M0,69L108,69\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M0,79L108,79\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M0,89L108,89\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M0,99L108,99\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M19,29L89,29\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M19,39L89,39\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M19,49L89,49\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M19,59L89,59\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M19,69L89,69\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M19,79L89,79\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M29,19L29,89\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M39,19L39,89\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M49,19L49,89\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M59,19L59,89\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M69,19L69,89\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M79,19L79,89\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n</vector>\n"
  },
  {
    "path": "examples/coroutinesExample/src/main/res/drawable-v24/ic_launcher_foreground.xml",
    "content": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:aapt=\"http://schemas.android.com/aapt\"\n    android:width=\"108dp\"\n    android:height=\"108dp\"\n    android:viewportWidth=\"108\"\n    android:viewportHeight=\"108\">\n    <path android:pathData=\"M31,63.928c0,0 6.4,-11 12.1,-13.1c7.2,-2.6 26,-1.4 26,-1.4l38.1,38.1L107,108.928l-32,-1L31,63.928z\">\n        <aapt:attr name=\"android:fillColor\">\n            <gradient\n                android:endX=\"85.84757\"\n                android:endY=\"92.4963\"\n                android:startX=\"42.9492\"\n                android:startY=\"49.59793\"\n                android:type=\"linear\">\n                <item\n                    android:color=\"#44000000\"\n                    android:offset=\"0.0\" />\n                <item\n                    android:color=\"#00000000\"\n                    android:offset=\"1.0\" />\n            </gradient>\n        </aapt:attr>\n    </path>\n    <path\n        android:fillColor=\"#FFFFFF\"\n        android:fillType=\"nonZero\"\n        android:pathData=\"M65.3,45.828l3.8,-6.6c0.2,-0.4 0.1,-0.9 -0.3,-1.1c-0.4,-0.2 -0.9,-0.1 -1.1,0.3l-3.9,6.7c-6.3,-2.8 -13.4,-2.8 -19.7,0l-3.9,-6.7c-0.2,-0.4 -0.7,-0.5 -1.1,-0.3C38.8,38.328 38.7,38.828 38.9,39.228l3.8,6.6C36.2,49.428 31.7,56.028 31,63.928h46C76.3,56.028 71.8,49.428 65.3,45.828zM43.4,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2c-0.3,-0.7 -0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C45.3,56.528 44.5,57.328 43.4,57.328L43.4,57.328zM64.6,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2s-0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C66.5,56.528 65.6,57.328 64.6,57.328L64.6,57.328z\"\n        android:strokeWidth=\"1\"\n        android:strokeColor=\"#00000000\" />\n</vector>\n"
  },
  {
    "path": "examples/coroutinesExample/src/main/res/layout/activity_main.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?><!--\n  ~ Copyright 2020 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<FrameLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:id=\"@+id/container\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    tools:context=\"io.realm.examples.coroutinesexample.MainActivity\" />\n"
  },
  {
    "path": "examples/coroutinesExample/src/main/res/layout/fragment_details.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?><!--\n  ~ Copyright 2020 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<layout>\n\n    <data>\n\n        <variable\n            name=\"viewModel\"\n            type=\"io.realm.examples.coroutinesexample.ui.details.DetailsViewModel\" />\n\n    </data>\n\n    <androidx.constraintlayout.widget.ConstraintLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n        xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n        xmlns:tools=\"http://schemas.android.com/tools\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\">\n\n        <com.google.android.material.appbar.AppBarLayout\n            android:id=\"@+id/appBar\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"wrap_content\"\n            android:theme=\"@style/AppTheme.AppBarOverlay\"\n            app:layout_constraintEnd_toEndOf=\"parent\"\n            app:layout_constraintStart_toStartOf=\"parent\"\n            app:layout_constraintTop_toTopOf=\"parent\">\n\n            <androidx.appcompat.widget.Toolbar\n                android:id=\"@+id/toolbar\"\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"?attr/actionBarSize\"\n                android:background=\"?attr/colorPrimary\"\n                app:popupTheme=\"@style/AppTheme.PopupOverlay\" />\n\n        </com.google.android.material.appbar.AppBarLayout>\n\n        <TextView\n            android:id=\"@+id/date\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:layout_alignParentStart=\"true\"\n            android:layout_alignParentLeft=\"true\"\n            android:layout_alignParentTop=\"true\"\n            android:gravity=\"center_vertical\"\n            android:padding=\"@dimen/default_double_padding\"\n            android:text=\"@{viewModel.date}\"\n            android:textColor=\"@android:color/darker_gray\"\n            app:layout_constraintStart_toStartOf=\"parent\"\n            app:layout_constraintTop_toBottomOf=\"@id/appBar\"\n            tools:text=\"2020-11-16\" />\n\n        <TextView\n            android:id=\"@+id/read\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:layout_alignParentTop=\"true\"\n            android:layout_alignParentEnd=\"true\"\n            android:layout_alignParentRight=\"true\"\n            android:alpha=\"0\"\n            android:gravity=\"center_vertical\"\n            android:padding=\"@dimen/default_double_padding\"\n            android:text=\"@string/read\"\n            android:textAllCaps=\"true\"\n            android:textColor=\"@android:color/holo_green_dark\"\n            app:layout_constraintEnd_toEndOf=\"parent\"\n            app:layout_constraintTop_toBottomOf=\"@id/appBar\"\n            tools:alpha=\"1\"\n            tools:ignore=\"RelativeOverlap\" />\n\n        <TextView\n            android:id=\"@+id/title\"\n            android:layout_width=\"0dp\"\n            android:layout_height=\"wrap_content\"\n            android:ellipsize=\"end\"\n            android:maxLines=\"3\"\n            android:padding=\"@dimen/default_double_padding\"\n            android:paddingTop=\"16dp\"\n            android:text=\"@{viewModel.title}\"\n            app:layout_constraintEnd_toEndOf=\"parent\"\n            app:layout_constraintStart_toStartOf=\"parent\"\n            app:layout_constraintTop_toBottomOf=\"@id/date\"\n            tools:text=\"With 11 Million Cases in the U.S., the Coronavirus Has Gotten Personal for Most People \" />\n\n        <TextView\n            android:id=\"@+id/article\"\n            android:layout_width=\"0dp\"\n            android:layout_height=\"wrap_content\"\n            android:ellipsize=\"end\"\n            android:maxLines=\"5\"\n            android:padding=\"@dimen/default_double_padding\"\n            android:paddingTop=\"16dp\"\n            android:text=\"@{viewModel.articleText}\"\n            app:layout_constraintEnd_toEndOf=\"parent\"\n            app:layout_constraintStart_toStartOf=\"parent\"\n            app:layout_constraintTop_toBottomOf=\"@id/title\"\n            tools:text=\"What was once a health crisis that Americans feared has evolved into one virtually everyone has experienced up close. That will affect behavior, but in many different ways.\" />\n\n    </androidx.constraintlayout.widget.ConstraintLayout>\n\n</layout>\n"
  },
  {
    "path": "examples/coroutinesExample/src/main/res/layout/fragment_main.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?><!--\n  ~ Copyright 2020 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<layout>\n\n    <androidx.constraintlayout.widget.ConstraintLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n        xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n        xmlns:tools=\"http://schemas.android.com/tools\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\"\n        android:fitsSystemWindows=\"true\"\n        tools:context=\".ui.ScrollingActivity\">\n\n        <com.google.android.material.appbar.AppBarLayout\n            android:id=\"@+id/appBar\"\n            android:layout_width=\"0dp\"\n            android:layout_height=\"?attr/actionBarSize\"\n            android:fitsSystemWindows=\"true\"\n            android:theme=\"@style/AppTheme.AppBarOverlay\"\n            app:layout_constraintBottom_toTopOf=\"@id/refresh\"\n            app:layout_constraintEnd_toEndOf=\"parent\"\n            app:layout_constraintStart_toStartOf=\"parent\"\n            app:layout_constraintTop_toTopOf=\"parent\">\n\n            <androidx.appcompat.widget.Toolbar\n                android:id=\"@+id/toolbar\"\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"?attr/actionBarSize\"\n                app:layout_collapseMode=\"pin\"\n                app:popupTheme=\"@style/AppTheme.PopupOverlay\">\n\n                <Spinner\n                    android:id=\"@+id/spinner\"\n                    android:layout_width=\"wrap_content\"\n                    android:layout_height=\"wrap_content\" />\n\n            </androidx.appcompat.widget.Toolbar>\n\n        </com.google.android.material.appbar.AppBarLayout>\n\n        <androidx.swiperefreshlayout.widget.SwipeRefreshLayout\n            android:id=\"@+id/refresh\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"0dp\"\n            app:layout_constraintBottom_toBottomOf=\"parent\"\n            app:layout_constraintEnd_toEndOf=\"parent\"\n            app:layout_constraintStart_toStartOf=\"parent\"\n            app:layout_constraintTop_toBottomOf=\"@id/appBar\"\n            tools:context=\".MainActivity\">\n\n            <androidx.recyclerview.widget.RecyclerView\n                android:id=\"@+id/list\"\n                android:name=\"io.realm.examples.coroutinesexample.ui.main.ItemFragment\"\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"match_parent\"\n                android:layout_marginLeft=\"@dimen/default_margin\"\n                android:layout_marginRight=\"@dimen/default_margin\"\n                app:layoutManager=\"LinearLayoutManager\"\n                tools:context=\".ui.main.MainFragment\"\n                tools:listitem=\"@layout/item_article\" />\n\n        </androidx.swiperefreshlayout.widget.SwipeRefreshLayout>\n\n    </androidx.constraintlayout.widget.ConstraintLayout>\n\n</layout>\n"
  },
  {
    "path": "examples/coroutinesExample/src/main/res/layout/item_article.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<androidx.constraintlayout.widget.ConstraintLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"wrap_content\"\n    android:orientation=\"horizontal\">\n\n    <TextView\n        android:id=\"@+id/title\"\n        android:layout_width=\"0dp\"\n        android:layout_height=\"@dimen/item_height\"\n        android:layout_margin=\"@dimen/text_margin\"\n        android:ellipsize=\"end\"\n        android:gravity=\"start|center_vertical\"\n        android:maxLines=\"2\"\n        android:textAppearance=\"?attr/textAppearanceListItem\"\n        app:layout_constraintBottom_toTopOf=\"@id/separator\"\n        app:layout_constraintEnd_toEndOf=\"parent\"\n        app:layout_constraintStart_toStartOf=\"parent\"\n        app:layout_constraintTop_toTopOf=\"parent\"\n        tools:text=\"This is the title of a fact-checked article from a reliable source, but you wouldn't believe what happens next\" />\n\n    <View\n        android:id=\"@+id/separator\"\n        android:layout_width=\"0dp\"\n        android:layout_height=\"1dp\"\n        android:background=\"@android:color/darker_gray\"\n        app:layout_constraintBottom_toBottomOf=\"parent\"\n        app:layout_constraintEnd_toEndOf=\"parent\"\n        app:layout_constraintStart_toStartOf=\"parent\"\n        app:layout_constraintTop_toBottomOf=\"@id/title\" />\n\n</androidx.constraintlayout.widget.ConstraintLayout>\n"
  },
  {
    "path": "examples/coroutinesExample/src/main/res/mipmap-anydpi-v26/ic_launcher.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<adaptive-icon xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <background android:drawable=\"@drawable/ic_launcher_background\" />\n    <foreground android:drawable=\"@drawable/ic_launcher_foreground\" />\n</adaptive-icon>\n"
  },
  {
    "path": "examples/coroutinesExample/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<adaptive-icon xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <background android:drawable=\"@drawable/ic_launcher_background\" />\n    <foreground android:drawable=\"@drawable/ic_launcher_foreground\" />\n</adaptive-icon>\n"
  },
  {
    "path": "examples/coroutinesExample/src/main/res/values/colors.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <color name=\"colorPrimary\">#6200EE</color>\n    <color name=\"colorPrimaryDark\">#3700B3</color>\n    <color name=\"colorAccent\">#03DAC5</color>\n</resources>\n"
  },
  {
    "path": "examples/coroutinesExample/src/main/res/values/dimens.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <dimen name=\"default_padding\">8dp</dimen>\n    <dimen name=\"default_double_padding\">16dp</dimen>\n    <dimen name=\"default_margin\">8dp</dimen>\n    <dimen name=\"item_height\">40dp</dimen>\n    <dimen name=\"text_margin\">16dp</dimen>\n</resources>\n"
  },
  {
    "path": "examples/coroutinesExample/src/main/res/values/strings.xml",
    "content": "<resources>\n    <string name=\"app_name\">Coroutines Example</string>\n    <string name=\"error_generic\">An error has occurred. Check Logcat for more details.</string>\n    <string name=\"read\">Read</string>\n</resources>\n"
  },
  {
    "path": "examples/coroutinesExample/src/main/res/values/styles.xml",
    "content": "<resources>\n    <!-- Base application theme. -->\n    <style name=\"AppTheme\" parent=\"Theme.AppCompat.Light.NoActionBar\">\n        <!-- Customize your theme here. -->\n        <item name=\"colorPrimary\">@color/colorPrimary</item>\n        <item name=\"colorPrimaryDark\">@color/colorPrimaryDark</item>\n        <item name=\"colorAccent\">@color/colorAccent</item>\n    </style>\n\n</resources>\n"
  },
  {
    "path": "examples/coroutinesExample/src/main/res/values/themes.xml",
    "content": "<resources>\n\n    <style name=\"AppTheme.NoActionBar\">\n        <item name=\"windowActionBar\">false</item>\n        <item name=\"windowNoTitle\">true</item>\n    </style>\n\n    <style name=\"AppTheme.AppBarOverlay\" parent=\"ThemeOverlay.AppCompat.Dark.ActionBar\" />\n\n    <style name=\"AppTheme.PopupOverlay\" parent=\"ThemeOverlay.AppCompat.Light\" />\n</resources>\n"
  },
  {
    "path": "examples/encryptionExample/build.gradle",
    "content": "apply plugin: 'com.android.application'\napply plugin: 'realm-android'\n\nandroid {\n    compileSdkVersion rootProject.sdkVersion\n    buildToolsVersion rootProject.buildTools\n\n    defaultConfig {\n        applicationId 'io.realm.examples.encryption'\n        targetSdkVersion rootProject.sdkVersion\n        minSdkVersion rootProject.minSdkVersion\n        versionCode 1\n        versionName '1.0'\n    }\n\n    buildTypes {\n        release {\n            minifyEnabled true\n            signingConfig signingConfigs.debug\n        }\n        debug {\n            minifyEnabled true\n        }\n    }\n    productFlavors {\n    }\n}\n"
  },
  {
    "path": "examples/encryptionExample/lint.xml",
    "content": "<lint>\n    <issue id=\"AllowBackup\" severity=\"ignore\" />\n    <issue id=\"IconLauncherShape\" severity=\"ignore\" />\n    <issue id=\"IconMissingDensityFolder\" severity=\"ignore\" />\n    <issue id=\"GoogleAppIndexingWarning\" severity=\"ignore\" />\n    <issue id=\"TrulyRandom\" severity=\"ignore\" />\n    <issue id=\"InvalidPackage\" severity=\"ignore\" />\n</lint>\n"
  },
  {
    "path": "examples/encryptionExample/src/main/AndroidManifest.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    package=\"io.realm.examples.encryption\">\n\n    <application\n        android:name=\".MyApplication\"\n        android:allowBackup=\"true\"\n        android:icon=\"@mipmap/ic_launcher\"\n        android:label=\"@string/app_name\"\n        android:theme=\"@style/AppTheme\">\n        <activity\n            android:name=\".EncryptionExampleActivity\"\n            android:configChanges=\"keyboardHidden|orientation|screenSize\"\n            android:label=\"Realm Encryption Example\">\n            <intent-filter>\n                <action android:name=\"android.intent.action.MAIN\" />\n                <category android:name=\"android.intent.category.LAUNCHER\" />\n            </intent-filter>\n        </activity>\n    </application>\n</manifest>\n"
  },
  {
    "path": "examples/encryptionExample/src/main/java/io/realm/examples/encryption/EncryptionExampleActivity.java",
    "content": "/*\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\npackage io.realm.examples.encryption;\n\nimport android.app.Activity;\nimport android.os.Bundle;\nimport android.util.Base64;\nimport android.util.Log;\n\nimport java.security.SecureRandom;\n\nimport io.realm.Realm;\nimport io.realm.RealmConfiguration;\n\npublic class EncryptionExampleActivity extends Activity {\n\n    public static final String TAG = EncryptionExampleActivity.class.getName();\n\n    private Realm realm;\n\n    @Override\n    protected void onCreate(Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n\n        // Generate a key\n        // IMPORTANT! This is a silly way to generate a key. It is also never stored.\n        // For proper key handling please consult:\n        // * https://developer.android.com/training/articles/keystore.html\n        // * http://nelenkov.blogspot.dk/2012/05/storing-application-secrets-in-androids.html\n        byte[] key = new byte[64];\n        new SecureRandom().nextBytes(key);\n\n        // An encrypted Realm file can be opened in Realm Studio by using a Hex encoded version\n        // of the key. Copy the key from Logcat, then download the Realm file from the device using\n        // the method described here: https://stackoverflow.com/a/28486297/1389357\n        // The path is normally `/data/data/io.realm.examples.encryption/files/default.realm`\n        Log.i(\"RealmEncryptionKey\", Util.bytesToHex(key));\n\n        RealmConfiguration realmConfiguration = new RealmConfiguration.Builder()\n                .encryptionKey(key)\n                .allowQueriesOnUiThread(true)\n                .allowWritesOnUiThread(true)\n                .build();\n\n        // Start with a clean slate every time\n        Realm.deleteRealm(realmConfiguration);\n\n        // Open the Realm with encryption enabled\n        realm = Realm.getInstance(realmConfiguration);\n\n        // Everything continues to work as normal except for that the file is encrypted on disk\n        realm.executeTransaction(new Realm.Transaction() {\n            @Override\n            public void execute(Realm realm) {\n                Person person = realm.createObject(Person.class);\n                person.setName(\"Happy Person\");\n                person.setAge(14);\n            }\n        });\n\n        Person person = realm.where(Person.class).findFirst();\n        Log.i(TAG, String.format(\"Person name: %s\", person.getName()));\n    }\n\n    @Override\n    protected void onDestroy() {\n        super.onDestroy();\n        realm.close(); // Remember to close Realm when done.\n    }\n}\n"
  },
  {
    "path": "examples/encryptionExample/src/main/java/io/realm/examples/encryption/MyApplication.java",
    "content": "/*\n * Copyright 2016 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\npackage io.realm.examples.encryption;\n\nimport android.app.Application;\n\nimport io.realm.Realm;\n\npublic class MyApplication extends Application {\n\n    @Override\n    public void onCreate() {\n        super.onCreate();\n        Realm.init(this);\n    }\n}\n"
  },
  {
    "path": "examples/encryptionExample/src/main/java/io/realm/examples/encryption/Person.java",
    "content": "/*\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\npackage io.realm.examples.encryption;\n\nimport io.realm.RealmObject;\n\npublic class Person extends RealmObject {\n    private String name;\n    private int age;\n\n    public String getName() {\n        return name;\n    }\n\n    public void setName(String name) {\n        this.name = name;\n    }\n\n    public int getAge() {\n        return age;\n    }\n\n    public void setAge(int age) {\n        this.age = age;\n    }\n}"
  },
  {
    "path": "examples/encryptionExample/src/main/java/io/realm/examples/encryption/Util.java",
    "content": "/*\n * Copyright 2017 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 */\npackage io.realm.examples.encryption;\n\npublic class Util {\n\n    private final static char[] hexArray = \"0123456789ABCDEF\".toCharArray();\n\n    //Original source: https://stackoverflow.com/a/9855338/1389357\n    public static String bytesToHex(byte[] bytes) {\n        char[] hexChars = new char[bytes.length * 2];\n        for ( int j = 0; j < bytes.length; j++ ) {\n            int v = bytes[j] & 0xFF;\n            hexChars[j * 2] = hexArray[v >>> 4];\n            hexChars[j * 2 + 1] = hexArray[v & 0x0F];\n        }\n        return new String(hexChars);\n    }\n\n}\n"
  },
  {
    "path": "examples/encryptionExample/src/main/res/values/strings.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n\n    <string name=\"app_name\">Realm Encryption Example</string>\n\n</resources>\n"
  },
  {
    "path": "examples/encryptionExample/src/main/res/values/styles.xml",
    "content": "<resources>\n\n    <!-- Base application theme. -->\n    <style name=\"AppTheme\" parent=\"android:Theme.Holo.Light.DarkActionBar\">\n        <!-- Customize your theme here. -->\n    </style>\n\n</resources>\n"
  },
  {
    "path": "examples/gradle/wrapper/gradle-wrapper.properties",
    "content": "distributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\ndistributionUrl=https\\://services.gradle.org/distributions/gradle-7.5-all.zip\nzipStoreBase=GRADLE_USER_HOME\nzipStorePath=wrapper/dists\n"
  },
  {
    "path": "examples/gradle.properties",
    "content": "org.gradle.jvmargs=-Xmx2048M -XX:MaxMetaspaceSize=1024M\norg.gradle.caching=true\nandroid.enableD8=true\n\n# Gradle sync failed: Due to a limitation of Gradle’s new variant-aware dependency management, loading the Android Gradle plugin in different class loaders leads to a build error.\n# This can occur when the buildscript classpaths that contain the Android Gradle plugin in sub-projects, or included projects in the case of composite builds, are set differently.\n# To resolve this issue, add the Android Gradle plugin to only the buildscript classpath of the top-level build.gradle file.\n# In the case of composite builds, also make sure the build script classpaths that contain the Android Gradle plugin are identical across the main and included projects.\n# If you are using a version of Gradle that has fixed the issue, you can disable this check by setting android.enableBuildScriptClasspathCheck=false in the gradle.properties file.\n# To learn more about this issue, go to https://d.android.com/r/tools/buildscript-classpath-check.html.\nandroid.enableBuildScriptClasspathCheck=false\n\n# See https://developer.android.com/studio/build/optimize-your-build#configuration_on_demand\norg.gradle.configureondemand=false\nandroid.useAndroidX=true\n"
  },
  {
    "path": "examples/gradlew",
    "content": "#!/bin/sh\n\n#\n# Copyright © 2015-2021 the original authors.\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#      https://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##############################################################################\n#\n#   Gradle start up script for POSIX generated by Gradle.\n#\n#   Important for running:\n#\n#   (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is\n#       noncompliant, but you have some other compliant shell such as ksh or\n#       bash, then to run this script, type that shell name before the whole\n#       command line, like:\n#\n#           ksh Gradle\n#\n#       Busybox and similar reduced shells will NOT work, because this script\n#       requires all of these POSIX shell features:\n#         * functions;\n#         * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,\n#           «${var#prefix}», «${var%suffix}», and «$( cmd )»;\n#         * compound commands having a testable exit status, especially «case»;\n#         * various built-in commands including «command», «set», and «ulimit».\n#\n#   Important for patching:\n#\n#   (2) This script targets any POSIX shell, so it avoids extensions provided\n#       by Bash, Ksh, etc; in particular arrays are avoided.\n#\n#       The \"traditional\" practice of packing multiple parameters into a\n#       space-separated string is a well documented source of bugs and security\n#       problems, so this is (mostly) avoided, by progressively accumulating\n#       options in \"$@\", and eventually passing that to Java.\n#\n#       Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,\n#       and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;\n#       see the in-line comments for details.\n#\n#       There are tweaks for specific operating systems such as AIX, CygWin,\n#       Darwin, MinGW, and NonStop.\n#\n#   (3) This script is generated from the Groovy template\n#       https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt\n#       within the Gradle project.\n#\n#       You can find Gradle at https://github.com/gradle/gradle/.\n#\n##############################################################################\n\n# Attempt to set APP_HOME\n\n# Resolve links: $0 may be a link\napp_path=$0\n\n# Need this for daisy-chained symlinks.\nwhile\n    APP_HOME=${app_path%\"${app_path##*/}\"}  # leaves a trailing /; empty if no leading path\n    [ -h \"$app_path\" ]\ndo\n    ls=$( ls -ld \"$app_path\" )\n    link=${ls#*' -> '}\n    case $link in             #(\n      /*)   app_path=$link ;; #(\n      *)    app_path=$APP_HOME$link ;;\n    esac\ndone\n\nAPP_HOME=$( cd \"${APP_HOME:-./}\" && pwd -P ) || exit\n\nAPP_NAME=\"Gradle\"\nAPP_BASE_NAME=${0##*/}\n\n# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\nDEFAULT_JVM_OPTS='\"-Xmx64m\" \"-Xms64m\"'\n\n# Use the maximum available, or set MAX_FD != -1 to use that value.\nMAX_FD=maximum\n\nwarn () {\n    echo \"$*\"\n} >&2\n\ndie () {\n    echo\n    echo \"$*\"\n    echo\n    exit 1\n} >&2\n\n# OS specific support (must be 'true' or 'false').\ncygwin=false\nmsys=false\ndarwin=false\nnonstop=false\ncase \"$( uname )\" in                #(\n  CYGWIN* )         cygwin=true  ;; #(\n  Darwin* )         darwin=true  ;; #(\n  MSYS* | MINGW* )  msys=true    ;; #(\n  NONSTOP* )        nonstop=true ;;\nesac\n\nCLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar\n\n\n# Determine the Java command to use to start the JVM.\nif [ -n \"$JAVA_HOME\" ] ; then\n    if [ -x \"$JAVA_HOME/jre/sh/java\" ] ; then\n        # IBM's JDK on AIX uses strange locations for the executables\n        JAVACMD=$JAVA_HOME/jre/sh/java\n    else\n        JAVACMD=$JAVA_HOME/bin/java\n    fi\n    if [ ! -x \"$JAVACMD\" ] ; then\n        die \"ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME\n\nPlease set the JAVA_HOME variable in your environment to match the\nlocation of your Java installation.\"\n    fi\nelse\n    JAVACMD=java\n    which java >/dev/null 2>&1 || die \"ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.\n\nPlease set the JAVA_HOME variable in your environment to match the\nlocation of your Java installation.\"\nfi\n\n# Increase the maximum file descriptors if we can.\nif ! \"$cygwin\" && ! \"$darwin\" && ! \"$nonstop\" ; then\n    case $MAX_FD in #(\n      max*)\n        MAX_FD=$( ulimit -H -n ) ||\n            warn \"Could not query maximum file descriptor limit\"\n    esac\n    case $MAX_FD in  #(\n      '' | soft) :;; #(\n      *)\n        ulimit -n \"$MAX_FD\" ||\n            warn \"Could not set maximum file descriptor limit to $MAX_FD\"\n    esac\nfi\n\n# Collect all arguments for the java command, stacking in reverse order:\n#   * args from the command line\n#   * the main class name\n#   * -classpath\n#   * -D...appname settings\n#   * --module-path (only if needed)\n#   * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.\n\n# For Cygwin or MSYS, switch paths to Windows format before running java\nif \"$cygwin\" || \"$msys\" ; then\n    APP_HOME=$( cygpath --path --mixed \"$APP_HOME\" )\n    CLASSPATH=$( cygpath --path --mixed \"$CLASSPATH\" )\n\n    JAVACMD=$( cygpath --unix \"$JAVACMD\" )\n\n    # Now convert the arguments - kludge to limit ourselves to /bin/sh\n    for arg do\n        if\n            case $arg in                                #(\n              -*)   false ;;                            # don't mess with options #(\n              /?*)  t=${arg#/} t=/${t%%/*}              # looks like a POSIX filepath\n                    [ -e \"$t\" ] ;;                      #(\n              *)    false ;;\n            esac\n        then\n            arg=$( cygpath --path --ignore --mixed \"$arg\" )\n        fi\n        # Roll the args list around exactly as many times as the number of\n        # args, so each arg winds up back in the position where it started, but\n        # possibly modified.\n        #\n        # NB: a `for` loop captures its iteration list before it begins, so\n        # changing the positional parameters here affects neither the number of\n        # iterations, nor the values presented in `arg`.\n        shift                   # remove old arg\n        set -- \"$@\" \"$arg\"      # push replacement arg\n    done\nfi\n\n# Collect all arguments for the java command;\n#   * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of\n#     shell script including quotes and variable substitutions, so put them in\n#     double quotes to make sure that they get re-expanded; and\n#   * put everything else in single quotes, so that it's not re-expanded.\n\nset -- \\\n        \"-Dorg.gradle.appname=$APP_BASE_NAME\" \\\n        -classpath \"$CLASSPATH\" \\\n        org.gradle.wrapper.GradleWrapperMain \\\n        \"$@\"\n\n# Stop when \"xargs\" is not available.\nif ! command -v xargs >/dev/null 2>&1\nthen\n    die \"xargs is not available\"\nfi\n\n# Use \"xargs\" to parse quoted args.\n#\n# With -n1 it outputs one arg per line, with the quotes and backslashes removed.\n#\n# In Bash we could simply go:\n#\n#   readarray ARGS < <( xargs -n1 <<<\"$var\" ) &&\n#   set -- \"${ARGS[@]}\" \"$@\"\n#\n# but POSIX shell has neither arrays nor command substitution, so instead we\n# post-process each arg (as a line of input to sed) to backslash-escape any\n# character that might be a shell metacharacter, then use eval to reverse\n# that process (while maintaining the separation between arguments), and wrap\n# the whole thing up as a single \"set\" statement.\n#\n# This will of course break if any of these variables contains a newline or\n# an unmatched quote.\n#\n\neval \"set -- $(\n        printf '%s\\n' \"$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS\" |\n        xargs -n1 |\n        sed ' s~[^-[:alnum:]+,./:=@_]~\\\\&~g; ' |\n        tr '\\n' ' '\n    )\" '\"$@\"'\n\nexec \"$JAVACMD\" \"$@\"\n"
  },
  {
    "path": "examples/gradlew.bat",
    "content": "@rem\r\n@rem Copyright 2015 the original author or authors.\r\n@rem\r\n@rem Licensed under the Apache License, Version 2.0 (the \"License\");\r\n@rem you may not use this file except in compliance with the License.\r\n@rem You may obtain a copy of the License at\r\n@rem\r\n@rem      https://www.apache.org/licenses/LICENSE-2.0\r\n@rem\r\n@rem Unless required by applicable law or agreed to in writing, software\r\n@rem distributed under the License is distributed on an \"AS IS\" BASIS,\r\n@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n@rem See the License for the specific language governing permissions and\r\n@rem limitations under the License.\r\n@rem\r\n\r\n@if \"%DEBUG%\"==\"\" @echo off\r\n@rem ##########################################################################\r\n@rem\r\n@rem  Gradle startup script for Windows\r\n@rem\r\n@rem ##########################################################################\r\n\r\n@rem Set local scope for the variables with windows NT shell\r\nif \"%OS%\"==\"Windows_NT\" setlocal\r\n\r\nset DIRNAME=%~dp0\r\nif \"%DIRNAME%\"==\"\" set DIRNAME=.\r\nset APP_BASE_NAME=%~n0\r\nset APP_HOME=%DIRNAME%\r\n\r\n@rem Resolve any \".\" and \"..\" in APP_HOME to make it shorter.\r\nfor %%i in (\"%APP_HOME%\") do set APP_HOME=%%~fi\r\n\r\n@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\r\nset DEFAULT_JVM_OPTS=\"-Xmx64m\" \"-Xms64m\"\r\n\r\n@rem Find java.exe\r\nif defined JAVA_HOME goto findJavaFromJavaHome\r\n\r\nset JAVA_EXE=java.exe\r\n%JAVA_EXE% -version >NUL 2>&1\r\nif %ERRORLEVEL% equ 0 goto execute\r\n\r\necho.\r\necho ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.\r\necho.\r\necho Please set the JAVA_HOME variable in your environment to match the\r\necho location of your Java installation.\r\n\r\ngoto fail\r\n\r\n:findJavaFromJavaHome\r\nset JAVA_HOME=%JAVA_HOME:\"=%\r\nset JAVA_EXE=%JAVA_HOME%/bin/java.exe\r\n\r\nif exist \"%JAVA_EXE%\" goto execute\r\n\r\necho.\r\necho ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%\r\necho.\r\necho Please set the JAVA_HOME variable in your environment to match the\r\necho location of your Java installation.\r\n\r\ngoto fail\r\n\r\n:execute\r\n@rem Setup the command line\r\n\r\nset CLASSPATH=%APP_HOME%\\gradle\\wrapper\\gradle-wrapper.jar\r\n\r\n\r\n@rem Execute Gradle\r\n\"%JAVA_EXE%\" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% \"-Dorg.gradle.appname=%APP_BASE_NAME%\" -classpath \"%CLASSPATH%\" org.gradle.wrapper.GradleWrapperMain %*\r\n\r\n:end\r\n@rem End local scope for the variables with windows NT shell\r\nif %ERRORLEVEL% equ 0 goto mainEnd\r\n\r\n:fail\r\nrem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of\r\nrem the _cmd.exe /c_ return code!\r\nset EXIT_CODE=%ERRORLEVEL%\r\nif %EXIT_CODE% equ 0 set EXIT_CODE=1\r\nif not \"\"==\"%GRADLE_EXIT_CONSOLE%\" exit %EXIT_CODE%\r\nexit /b %EXIT_CODE%\r\n\r\n:mainEnd\r\nif \"%OS%\"==\"Windows_NT\" endlocal\r\n\r\n:omega\r\n"
  },
  {
    "path": "examples/gridViewExample/build.gradle",
    "content": "apply plugin: 'com.android.application'\napply plugin: 'realm-android'\n\nandroid {\n    compileSdkVersion rootProject.sdkVersion\n    buildToolsVersion rootProject.buildTools\n\n    compileOptions {\n        sourceCompatibility JavaVersion.VERSION_1_8\n        targetCompatibility JavaVersion.VERSION_1_8\n    }\n    defaultConfig {\n        applicationId 'io.realm.examples.realmgridview'\n        targetSdkVersion rootProject.sdkVersion\n        minSdkVersion rootProject.minSdkVersion\n        versionCode 1\n        versionName \"1.0\"\n    }\n    buildTypes {\n        release {\n            minifyEnabled true\n            signingConfig signingConfigs.debug\n            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'\n        }\n        debug {\n            minifyEnabled true\n            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'\n        }\n    }\n    productFlavors {\n    }\n\n    splits {\n        // Split apks on build target ABI, view all options for the splits here:\n        // http://tools.android.com/tech-docs/new-build-system/user-guide/apk-splits\n        abi {\n            enable true\n            reset()\n            include 'armeabi', 'armeabi-v7a', 'arm64-v8a', 'mips', 'x86', 'x86_64'\n        }\n    }\n}\n\ndependencies {\n    implementation 'com.google.code.gson:gson:2.8.2'\n}\n"
  },
  {
    "path": "examples/gridViewExample/lint.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<lint>\n    <!-- Disable the given check in this project -->\n    <issue id=\"AllowBackup\" severity=\"ignore\" />\n    <issue id=\"IconLauncherShape\" severity=\"ignore\" />\n    <issue id=\"IconMissingDensityFolder\" severity=\"ignore\" />\n    <issue id=\"GoogleAppIndexingWarning\" severity=\"ignore\" />\n    <issue id=\"InvalidPackage\" severity=\"ignore\" />\n</lint>\n"
  },
  {
    "path": "examples/gridViewExample/proguard-rules.pro",
    "content": "-keep class io.realm.examples.realmgridview.City { <fields>; }"
  },
  {
    "path": "examples/gridViewExample/src/main/AndroidManifest.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    package=\"io.realm.examples.realmgridview\">\n\n    <application\n        android:name=\".MyApplication\"\n        android:allowBackup=\"true\"\n        android:icon=\"@mipmap/ic_launcher\"\n        android:label=\"@string/app_name\"\n        android:theme=\"@style/AppTheme\">\n        <activity\n            android:name=\".GridViewExampleActivity\"\n            android:configChanges=\"keyboard|screenSize|orientation\"\n            android:label=\"@string/app_name\">\n            <intent-filter>\n                <action android:name=\"android.intent.action.MAIN\" />\n                <category android:name=\"android.intent.category.LAUNCHER\" />\n            </intent-filter>\n        </activity>\n    </application>\n\n</manifest>\n"
  },
  {
    "path": "examples/gridViewExample/src/main/assets/cities.json",
    "content": "[\n    { \"name\"  : \"Barcelona\",\n      \"votes\" : 23 },\n\n    { \"name\"  : \"San Francisco\",\n      \"votes\" : 21 },\n\n    { \"name\"  : \"Venice\",\n      \"votes\" : 19 },\n\n    { \"name\"  : \"Melbourne\",\n      \"votes\" : 18 },\n\n    { \"name\"  : \"Paris\",\n      \"votes\" : 17 },\n\n    { \"name\"  : \"Seville\",\n      \"votes\" : 14 },\n\n    { \"name\"  : \"Sydney\",\n      \"votes\" : 12 },\n\n    { \"name\"  : \"New York\",\n      \"votes\" : 11 },\n\n    { \"name\"  : \"Krakow\",\n      \"votes\" : 9 },\n\n    { \"name\"  : \"Peoria\",\n      \"votes\" : 72 },\n\n    { \"name\"  : \"Springfield\",\n      \"votes\" : 88 },\n\n    { \"name\"  : \"Kansas City\",\n      \"votes\" : 100 },\n\n    { \"name\"  : \"Tokyo\",\n      \"votes\" : 20 },\n\n    { \"name\"  : \"Boise\",\n      \"votes\" : 17 },\n\n    { \"name\"  : \"Los Angeles\",\n      \"votes\" : 14 },\n\n    { \"name\"  : \"Newark\",\n      \"votes\" : 12 },\n\n    { \"name\"  : \"Chicago\",\n      \"votes\" : 11 },\n\n    { \"name\"  : \"Detroit\",\n      \"votes\" : 91 },\n\n    { \"name\"  : \"Florence\",\n      \"votes\" : 4 },\n\n    { \"name\"  : \"Madrid\",\n      \"votes\" : 1 },\n\n    { \"name\"  : \"London\",\n      \"votes\" : 9 }\n]"
  },
  {
    "path": "examples/gridViewExample/src/main/java/io/realm/examples/realmgridview/City.java",
    "content": "/*\n * Copyright 2018 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\npackage io.realm.examples.realmgridview;\n\nimport io.realm.RealmObject;\nimport io.realm.annotations.PrimaryKey;\n\npublic class City extends RealmObject {\n    // If you are using GSON, field names should not be obfuscated.\n    // Add either the proguard rule in proguard-rules.pro or the @SerializedName annotation.\n    @PrimaryKey\n    private String name;\n    private long votes;\n\n    public String getName() {\n        return name;\n    }\n\n    public void setName(String name) {\n        this.name = name;\n    }\n\n    public long getVotes() {\n        return votes;\n    }\n\n    public void setVotes(long votes) {\n        this.votes = votes;\n    }\n\n}\n"
  },
  {
    "path": "examples/gridViewExample/src/main/java/io/realm/examples/realmgridview/CityAdapter.java",
    "content": "/*\n * Copyright 2018 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\npackage io.realm.examples.realmgridview;\n\nimport android.view.LayoutInflater;\nimport android.view.View;\nimport android.view.ViewGroup;\nimport android.widget.BaseAdapter;\nimport android.widget.TextView;\n\nimport java.util.Collections;\nimport java.util.List;\nimport java.util.Locale;\n\n// This adapter is strictly to interface with the GridView and doesn't\n// particular show much interesting Realm functionality.\n\n// Alternatively from this example,\n// a developer could update the getView() to pull items from the Realm.\n\npublic class CityAdapter extends BaseAdapter {\n    private List<City> cities = Collections.emptyList();\n\n    public CityAdapter() {\n    }\n\n    public void setData(List<City> details) {\n        if (details == null) {\n            details = Collections.emptyList();\n        }\n        this.cities = details;\n        notifyDataSetChanged();\n    }\n\n    @Override\n    public int getCount() {\n        return cities.size();\n    }\n\n    @Override\n    public City getItem(int position) {\n        return cities.get(position);\n    }\n\n    @Override\n    public long getItemId(int i) {\n        return i;\n    }\n\n    // ViewHolder caches view resources so that `findViewById` is not called for each row\n    private static class ViewHolder {\n        private TextView name;\n        private TextView vote;\n\n        public ViewHolder(View view) {\n            name = view.findViewById(R.id.name);\n            vote = view.findViewById(R.id.votes);\n        }\n\n        public void bind(City city) {\n            name.setText(city.getName());\n            vote.setText(String.format(Locale.US, \"%d\", city.getVotes()));\n        }\n    }\n\n    @Override\n    public View getView(int position, View currentView, ViewGroup parent) {\n        // GridView requires ViewHolder pattern to ensure optimal performance\n        ViewHolder viewHolder;\n        if (currentView == null) {\n            currentView = LayoutInflater.from(parent.getContext()).inflate(R.layout.city_listitem, parent, false);\n            viewHolder = new ViewHolder(currentView);\n            currentView.setTag(viewHolder);\n        } else {\n            viewHolder = (ViewHolder)currentView.getTag();\n        }\n\n        City city = cities.get(position);\n        viewHolder.bind(city);\n\n        return currentView;\n    }\n}\n"
  },
  {
    "path": "examples/gridViewExample/src/main/java/io/realm/examples/realmgridview/GridViewExampleActivity.java",
    "content": "/*\n * Copyright 2018 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\npackage io.realm.examples.realmgridview;\n\nimport android.app.Activity;\nimport android.os.Bundle;\nimport android.view.View;\nimport android.widget.AdapterView;\nimport android.widget.GridView;\n\nimport io.realm.Realm;\nimport io.realm.RealmChangeListener;\nimport io.realm.RealmResults;\n\npublic class GridViewExampleActivity extends Activity implements AdapterView.OnItemClickListener {\n\n    private GridView gridView;\n    private CityAdapter adapter;\n\n    private Realm realm;\n    private RealmResults<City> cities;\n    private RealmChangeListener<RealmResults<City>> realmChangeListener = cities -> {\n        // Set the cities to the adapter only when async query is loaded.\n        // It will also be called for any future writes made to the Realm.\n        adapter.setData(cities);\n    };\n\n    @Override\n    protected void onCreate(Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n        setContentView(R.layout.activity_realm_example);\n\n        // This is the GridView adapter\n        adapter = new CityAdapter();\n\n        //This is the GridView which will display the list of cities\n        gridView = findViewById(R.id.cities_list);\n        gridView.setAdapter(adapter);\n        gridView.setOnItemClickListener(GridViewExampleActivity.this);\n\n        // Clear the realm from last time\n        //noinspection ConstantConditions\n        Realm.deleteRealm(Realm.getDefaultConfiguration());\n\n        // Create a new empty instance of Realm\n        realm = Realm.getDefaultInstance();\n\n        // Obtain the cities in the Realm with asynchronous query.\n        cities = realm.where(City.class).findAllAsync();\n\n        // The RealmChangeListener will be called when the results are asynchronously loaded, and available for use.\n        cities.addChangeListener(realmChangeListener);\n    }\n\n    @Override\n    protected void onDestroy() {\n        super.onDestroy();\n        cities.removeAllChangeListeners(); // Remove change listeners to prevent updating views not yet GCed.\n        realm.close(); // Remember to close Realm when done.\n    }\n\n    @Override\n    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {\n        City modifiedCity = adapter.getItem(position);\n\n        // Acquire the name of the clicked City, in order to be able to query for it.\n        final String name = modifiedCity.getName();\n\n        // Create an asynchronous transaction to increment the vote count for the selected City in the Realm.\n        // The write will happen on a background thread, and the RealmChangeListener will update the GridView automatically.\n        realm.executeTransactionAsync(bgRealm -> {\n            // We need to find the City we want to modify from the background thread's Realm\n            City city = bgRealm.where(City.class).equalTo(\"name\", name).findFirst();\n            if (city != null) {\n                // Let's increase the votes of the selected city!\n                city.setVotes(city.getVotes() + 1);\n            }\n        });\n    }\n}\n"
  },
  {
    "path": "examples/gridViewExample/src/main/java/io/realm/examples/realmgridview/MyApplication.java",
    "content": "/*\n * Copyright 2018 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\npackage io.realm.examples.realmgridview;\n\nimport android.app.Application;\n\nimport com.google.gson.Gson;\nimport com.google.gson.GsonBuilder;\nimport com.google.gson.JsonElement;\nimport com.google.gson.JsonParser;\nimport com.google.gson.reflect.TypeToken;\n\nimport java.io.IOException;\nimport java.io.InputStream;\nimport java.io.InputStreamReader;\nimport java.util.List;\n\nimport io.realm.Realm;\nimport io.realm.RealmConfiguration;\n\npublic class MyApplication extends Application {\n    @Override\n    public void onCreate() {\n        super.onCreate();\n        Realm.init(this);\n        Realm.setDefaultConfiguration(new RealmConfiguration.Builder()\n                .initialData(realm -> {\n                    // Load from file \"cities.json\" first time\n                    List<City> cities = loadCities();\n                    if (cities != null) {\n                        // Use insertOrUpdate() to convert the objects into proper RealmObjects managed by Realm.\n                        realm.insertOrUpdate(cities);\n                    }\n                })\n                .deleteRealmIfMigrationNeeded()\n                .build()\n        );\n    }\n\n    private List<City> loadCities() {\n        // In this case we're loading from local assets.\n        // NOTE: could alternatively easily load from network.\n        // However, that would need to happen on a background thread.\n        InputStream stream;\n        try {\n            stream = getAssets().open(\"cities.json\");\n        } catch (IOException e) {\n            return null;\n        }\n\n        Gson gson = new GsonBuilder().create();\n\n        JsonElement json = new JsonParser().parse(new InputStreamReader(stream));\n\n        return gson.fromJson(json, new TypeToken<List<City>>() {\n        }.getType());\n    }\n}\n"
  },
  {
    "path": "examples/gridViewExample/src/main/res/layout/activity_realm_example.xml",
    "content": "<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:orientation=\"vertical\"\n    tools:context=\".GridViewExampleActivity\">\n\n    <TextView\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:layout_marginTop=\"24dp\"\n        android:gravity=\"center_horizontal\"\n        android:text=\"@string/my_favorite_city\"\n        android:textSize=\"22sp\" />\n\n    <TextView\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:layout_marginBottom=\"24dp\"\n        android:gravity=\"center_horizontal\"\n        android:padding=\"4dp\"\n        android:text=\"@string/add_vote\"\n        android:textSize=\"16sp\"\n        android:textStyle=\"bold\" />\n\n    <GridView\n        android:id=\"@+id/cities_list\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:numColumns=\"2\" />\n</LinearLayout>\n"
  },
  {
    "path": "examples/gridViewExample/src/main/res/layout/city_listitem.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"wrap_content\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:gravity=\"center\"\n    android:orientation=\"horizontal\"\n    android:padding=\"4dp\">\n\n    <TextView\n        android:id=\"@+id/name\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:layout_margin=\"12dp\"\n        android:textColor=\"#121212\"\n        android:textSize=\"20sp\"\n        tools:text=\"Barcelona\"/>\n\n    <TextView\n        android:id=\"@+id/votes\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:layout_margin=\"12dp\"\n        android:textSize=\"18sp\"\n        android:textColor=\"#3A3A3A\"\n        tools:text=\"19\"/>\n</LinearLayout>\n"
  },
  {
    "path": "examples/gridViewExample/src/main/res/values/strings.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <string name=\"app_name\">GridView example</string>\n    <string name=\"my_favorite_city\">My Favorite City</string>\n    <string name=\"add_vote\">Click to Add A Vote</string>\n</resources>\n"
  },
  {
    "path": "examples/gridViewExample/src/main/res/values/styles.xml",
    "content": "<resources>\n\n    <!-- Base application theme. -->\n    <style name=\"AppTheme\" parent=\"android:Theme.Holo.Light.DarkActionBar\">\n        <!-- Customize your theme here. -->\n    </style>\n\n</resources>\n"
  },
  {
    "path": "examples/introExample/build.gradle",
    "content": "apply plugin: 'com.android.application'\napply plugin: 'realm-android'\n\nandroid {\n    compileSdkVersion rootProject.sdkVersion\n    buildToolsVersion rootProject.buildTools\n\n    compileOptions {\n        sourceCompatibility JavaVersion.VERSION_1_8\n        targetCompatibility JavaVersion.VERSION_1_8\n    }\n    defaultConfig {\n        applicationId 'io.realm.examples.intro'\n        targetSdkVersion rootProject.sdkVersion\n        minSdkVersion rootProject.minSdkVersion\n        versionCode 1\n        versionName \"1.0\"\n    }\n\n    buildTypes {\n        release {\n            minifyEnabled true\n            signingConfig signingConfigs.debug\n        }\n        debug {\n            minifyEnabled true\n        }\n    }\n\n    productFlavors {\n    }\n\n}\n"
  },
  {
    "path": "examples/introExample/lint.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<lint>\n    <!-- Disable the given check in this project -->\n    <issue id=\"AllowBackup\" severity=\"ignore\" />\n    <issue id=\"IconLauncherShape\" severity=\"ignore\" />\n    <issue id=\"IconMissingDensityFolder\" severity=\"ignore\" />\n    <issue id=\"GoogleAppIndexingWarning\" severity=\"ignore\" />\n    <issue id=\"InvalidPackage\" severity=\"ignore\" />\n</lint>\n"
  },
  {
    "path": "examples/introExample/src/main/AndroidManifest.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    package=\"io.realm.examples.intro\" >\n\n    <application\n        android:icon=\"@mipmap/ic_launcher\"\n        android:label=\"@string/app_name\"\n        android:name=\".MyApplication\"\n        android:theme=\"@style/AppTheme\" >\n        <activity\n            android:name=\".IntroExampleActivity\"\n            android:label=\"@string/app_name\" >\n            <intent-filter>\n                <action android:name=\"android.intent.action.MAIN\" />\n\n                <category android:name=\"android.intent.category.LAUNCHER\" />\n            </intent-filter>\n        </activity>\n    </application>\n\n</manifest>\n"
  },
  {
    "path": "examples/introExample/src/main/java/io/realm/examples/intro/IntroExampleActivity.java",
    "content": "/*\n * Copyright 2018 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\npackage io.realm.examples.intro;\n\nimport android.app.Activity;\nimport android.os.AsyncTask;\nimport android.os.Bundle;\nimport android.util.Log;\nimport android.widget.LinearLayout;\nimport android.widget.TextView;\n\nimport java.lang.ref.WeakReference;\nimport java.util.Arrays;\n\nimport io.realm.OrderedRealmCollectionChangeListener;\nimport io.realm.Realm;\nimport io.realm.RealmConfiguration;\nimport io.realm.RealmResults;\nimport io.realm.Sort;\nimport io.realm.examples.intro.model.Cat;\nimport io.realm.examples.intro.model.Dog;\nimport io.realm.examples.intro.model.Person;\n\npublic class IntroExampleActivity extends Activity {\n    public static final String TAG = \"IntroExampleActivity\";\n\n    private LinearLayout rootLayout;\n\n    private Realm realm;\n\n    // Results obtained from a Realm are live, and can be observed on looper threads (like the UI thread).\n    // Note that if you want to observe the RealmResults for a long time, then it should be a field reference.\n    // Otherwise, the RealmResults can no longer be notified if the GC has cleared the reference to it.\n    private RealmResults<Person> persons;\n\n    // OrderedRealmCollectionChangeListener receives fine-grained changes - insertions, deletions, and changes.\n    // If the change set isn't needed, then RealmChangeListener can also be used.\n    private final OrderedRealmCollectionChangeListener<RealmResults<Person>> realmChangeListener = (people, changeSet) -> {\n        String insertions = changeSet.getInsertions().length == 0 ? \"\" : \"\\n - Insertions: \" + Arrays.toString(changeSet.getInsertions());\n        String deletions = changeSet.getDeletions().length == 0 ? \"\" : \"\\n - Deletions: \" + Arrays.toString(changeSet.getDeletions());\n        String changes = changeSet.getChanges().length == 0 ? \"\" : \"\\n - Changes: \" + Arrays.toString(changeSet.getChanges());\n        showStatus(\"Person was loaded, or written to. \" + insertions + deletions + changes);\n    };\n\n    @Override\n    protected void onCreate(Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n        setContentView(R.layout.activity_realm_basic_example);\n        rootLayout = findViewById(R.id.container);\n        rootLayout.removeAllViews();\n\n        // Clear the Realm if the example was previously run.\n        Realm.deleteRealm(Realm.getDefaultConfiguration());\n\n        // Create the Realm instance\n        RealmConfiguration build = new RealmConfiguration.Builder()\n                .allowWritesOnUiThread(true)\n                .allowQueriesOnUiThread(true).build();\n        realm = Realm.getInstance(build);\n\n        // Asynchronous queries are evaluated on a background thread,\n        // and passed to the registered change listener when it's done.\n        // The change listener is also called on any future writes that change the result set.\n        persons = realm.where(Person.class).findAllAsync();\n\n        // The change listener will be notified when the data is loaded,\n        // or the Realm is written to from any threads (and the result set is modified).\n        persons.addChangeListener(realmChangeListener);\n\n        // These operations are small enough that\n        // we can generally safely run them on the UI thread.\n        basicCRUD(realm);\n        basicQuery(realm);\n        basicLinkQuery(realm);\n\n        // More complex operations can be executed on another thread.\n        new ComplexBackgroundOperations(this).execute();\n    }\n\n    @Override\n    protected void onDestroy() {\n        super.onDestroy();\n        persons.removeAllChangeListeners(); // Remove the change listener when no longer needed.\n        realm.close(); // Remember to close Realm when done.\n    }\n\n    private void showStatus(String text) {\n        Log.i(TAG, text);\n        TextView textView = new TextView(this);\n        textView.setText(text);\n        rootLayout.addView(textView);\n    }\n\n    private void basicCRUD(Realm realm) {\n        showStatus(\"Perform basic Create/Read/Update/Delete (CRUD) operations...\");\n\n        // All writes must be wrapped in a transaction to facilitate safe multi threading\n        realm.executeTransaction(r -> {\n            // Add a person. \n            // RealmObjects with primary keys created with `createObject()` must specify the primary key value as an argument.\n            Person person = r.createObject(Person.class, 1);\n            person.setName(\"Young Person\");\n            person.setAge(14);\n\n            // Even young people have at least one phone in this day and age.\n            // Please note that this is a RealmList that contains primitive values.\n            person.getPhoneNumbers().add(\"+1 123 4567\");\n        });\n\n        // Find the first person (no query conditions) and read a field\n        final Person person = realm.where(Person.class).findFirst();\n        showStatus(person.getName() + \":\" + person.getAge());\n\n        // Update person in a transaction\n        realm.executeTransaction(r -> {\n            // Managed objects can be modified inside transactions.\n            person.setName(\"Senior Person\");\n            person.setAge(99);\n            showStatus(person.getName() + \" got older: \" + person.getAge());\n        });\n\n        // Delete all persons\n        showStatus(\"Deleting all persons\");\n        realm.executeTransaction(r -> r.delete(Person.class));\n    }\n\n    private void basicQuery(Realm realm) {\n        showStatus(\"\\nPerforming basic Query operation...\");\n\n        // Let's add a person so that the query returns something.\n        realm.executeTransaction(r -> {\n            Person oldPerson = new Person();\n            oldPerson.setId(99);\n            oldPerson.setAge(99);\n            oldPerson.setName(\"George\");\n            realm.insertOrUpdate(oldPerson);\n        });\n\n        showStatus(\"Number of persons: \" + realm.where(Person.class).count());\n\n        RealmResults<Person> results = realm.where(Person.class).equalTo(\"age\", 99).findAll();\n\n        showStatus(\"Size of result set: \" + results.size());\n    }\n\n    private void basicLinkQuery(Realm realm) {\n        showStatus(\"\\nPerforming basic Link Query operation...\");\n\n        // Let's add a person with a cat so that the query returns something.\n        realm.executeTransaction(r -> {\n            Person catLady = realm.createObject(Person.class, 24);\n            catLady.setAge(52);\n            catLady.setName(\"Mary\");\n\n            Cat tiger = realm.createObject(Cat.class);\n            tiger.name = \"Tiger\";\n            catLady.getCats().add(tiger);\n        });\n\n        showStatus(\"Number of persons: \" + realm.where(Person.class).count());\n\n        RealmResults<Person> results = realm.where(Person.class).equalTo(\"cats.name\", \"Tiger\").findAll();\n\n        showStatus(\"Size of result set: \" + results.size());\n    }\n\n    // This AsyncTask shows how to use Realm in background thread operations.\n    //\n    // AsyncTasks should be static inner classes to avoid memory leaks.\n    // In this example, WeakReference is used for the sake of simplicity.\n    private static class ComplexBackgroundOperations extends AsyncTask<Void, Void, String> {\n        private WeakReference<IntroExampleActivity> weakReference;\n\n        public ComplexBackgroundOperations(IntroExampleActivity introExampleActivity) {\n            this.weakReference = new WeakReference<>(introExampleActivity);\n        }\n\n        @Override\n        protected void onPreExecute() {\n            IntroExampleActivity activity = weakReference.get();\n            if (activity == null) {\n                return;\n            }\n            activity.showStatus(\"\\n\\nBeginning complex operations on background thread.\");\n        }\n\n        @Override\n        protected String doInBackground(Void... voids) {\n            IntroExampleActivity activity = weakReference.get();\n            if (activity == null) {\n                return \"\";\n            }\n            // Open the default realm. Uses `try-with-resources` to automatically close Realm when done.\n            // All threads must use their own reference to the realm.\n            // Realm instances, RealmResults, and managed RealmObjects can not be transferred across threads.\n            try (Realm realm = Realm.getDefaultInstance()) {\n                String info;\n                info = activity.complexReadWrite(realm);\n                info += activity.complexQuery(realm);\n                return info;\n            }\n        }\n\n        @Override\n        protected void onPostExecute(String result) {\n            IntroExampleActivity activity = weakReference.get();\n            if (activity == null) {\n                return;\n            }\n            activity.showStatus(result);\n        }\n    }\n\n    private String complexReadWrite(Realm realm) {\n        String status = \"\\nPerforming complex Read/Write operation...\";\n\n        // Add ten persons in one transaction\n        realm.executeTransaction(r -> {\n            Dog fido = r.createObject(Dog.class);\n            fido.name = \"fido\";\n            for (int i = 0; i < 10; i++) {\n                Person person = r.createObject(Person.class, i);\n                person.setName(\"Person no. \" + i);\n                person.setAge(i);\n                person.setDog(fido);\n\n                // The field tempReference is annotated with @Ignore.\n                // This means setTempReference sets the Person tempReference\n                // field directly. The tempReference is NOT saved as part of\n                // the RealmObject:\n                person.setTempReference(42);\n\n                for (int j = 0; j < i; j++) {\n                    Cat cat = r.createObject(Cat.class);\n                    cat.name = \"Cat_\" + j;\n                    person.getCats().add(cat);\n                }\n            }\n        });\n\n        // Implicit read transactions allow you to access your objects\n        status += \"\\nNumber of persons: \" + realm.where(Person.class).count();\n\n        // Iterate over all objects, with an iterator\n        for (Person person : realm.where(Person.class).findAll()) {\n            String dogName;\n            if (person.getDog() == null) {\n                dogName = \"None\";\n            } else {\n                dogName = person.getDog().name;\n            }\n            status += \"\\n\" + person.getName() + \":\" + person.getAge() + \" : \" + dogName + \" : \" + person.getCats().size();\n        }\n\n        // Sorting\n        RealmResults<Person> sortedPersons = realm.where(Person.class).sort(\"age\", Sort.DESCENDING).findAll();\n        status += \"\\nSorting \" + sortedPersons.last().getName() + \" == \" + realm.where(Person.class).findFirst()\n                .getName();\n\n        return status;\n    }\n\n    private String complexQuery(Realm realm) {\n        String status = \"\\n\\nPerforming complex Query operation...\";\n        status += \"\\nNumber of persons: \" + realm.where(Person.class).count();\n\n        // Find all persons where age between 7 and 9 and name begins with \"Person\".\n        RealmResults<Person> results = realm.where(Person.class)\n                .between(\"age\", 7, 9)       // Notice implicit \"and\" operation\n                .beginsWith(\"name\", \"Person\").findAll();\n\n        status += \"\\nSize of result set: \" + results.size();\n\n        return status;\n    }\n}\n"
  },
  {
    "path": "examples/introExample/src/main/java/io/realm/examples/intro/MyApplication.java",
    "content": "/*\n * Copyright 2018 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\npackage io.realm.examples.intro;\n\nimport android.app.Application;\n\nimport io.realm.Realm;\n\npublic class MyApplication extends Application {\n\n    @Override\n    public void onCreate() {\n        super.onCreate();\n        // Initialize Realm. Should only be done once when the application starts.\n        Realm.init(this);\n\n        // In this example, no default configuration is set,\n        // so by default, `RealmConfiguration.Builder().build()` is used.\n    }\n}\n"
  },
  {
    "path": "examples/introExample/src/main/java/io/realm/examples/intro/model/Cat.java",
    "content": "/*\n * Copyright 2018 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\npackage io.realm.examples.intro.model;\n\nimport io.realm.RealmObject;\nimport io.realm.RealmResults;\nimport io.realm.annotations.LinkingObjects;\n\npublic class Cat extends RealmObject {\n    // It is possible to also use public fields, instead of getters/setters.\n    public String name;\n\n    // You can define inverse relationships.\n    @LinkingObjects(\"cats\")\n    public final RealmResults<Person> owners = null;\n}\n"
  },
  {
    "path": "examples/introExample/src/main/java/io/realm/examples/intro/model/Dog.java",
    "content": "/*\n * Copyright 2018 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\npackage io.realm.examples.intro.model;\n\nimport io.realm.RealmModel;\nimport io.realm.RealmResults;\nimport io.realm.annotations.LinkingObjects;\nimport io.realm.annotations.RealmClass;\n\n// It is possible to use @RealmClass and implement RealmModel, instead of extending RealmObject.\n@RealmClass\npublic class Dog implements RealmModel {\n    // It is possible to also use public fields, instead of getters/setters.\n    public String name;\n\n    // You can define inverse relationships.\n    @LinkingObjects(\"dog\")\n    public final RealmResults<Person> owners = null;\n}\n"
  },
  {
    "path": "examples/introExample/src/main/java/io/realm/examples/intro/model/Person.java",
    "content": "/*\n * Copyright 2018 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\npackage io.realm.examples.intro.model;\n\nimport io.realm.RealmList;\nimport io.realm.RealmObject;\nimport io.realm.annotations.Ignore;\nimport io.realm.annotations.Index;\nimport io.realm.annotations.PrimaryKey;\n\n// Your model just have to extend RealmObject.\n// This will inherit an annotation which produces proxy getters and setters for all fields.\n// It is also possible to use @RealmClass annotation, and implement RealmModel interface.\npublic class Person extends RealmObject {\n\n    // All fields are by default persisted.\n    private int age;\n\n    // Adding an index makes queries execute faster on that field.\n    @Index\n    private String name;\n\n    // Primary keys are optional, but it allows identifying a specific object\n    // when Realm writes are instructed to update if the object already exists in the Realm\n    @PrimaryKey\n    private long id;\n\n    // Other objects in a one-to-one relation must also implement RealmModel, or extend RealmObject\n    private Dog dog;\n\n    // One-to-many relations is simply a RealmList of the objects which also implements RealmModel\n    private RealmList<Cat> cats;\n\n    // It is also possible to have list of primitive types (long, String, Date, byte[], etc.)\n    private RealmList<String> phoneNumbers;\n\n    // You can instruct Realm to ignore a field and not persist it.\n    @Ignore\n    private int tempReference;\n\n    // Let your IDE generate getters and setters for you!\n    // Or if you like you can even have public fields and no accessors! See Dog.java and Cat.java\n    public String getName() {\n        return name;\n    }\n\n    public void setName(String name) {\n        this.name = name;\n    }\n\n    public int getAge() {\n        return age;\n    }\n\n    public void setAge(int age) {\n        this.age = age;\n    }\n\n    public long getId() {\n        return id;\n    }\n\n    public void setId(long id) {\n        this.id = id;\n    }\n\n    public Dog getDog() {\n        return dog;\n    }\n\n    public void setDog(Dog dog) {\n        this.dog = dog;\n    }\n\n    public RealmList<Cat> getCats() {\n        return cats;\n    }\n\n    public void setCats(RealmList<Cat> cats) {\n        this.cats = cats;\n    }\n\n    public int getTempReference() {\n        return tempReference;\n    }\n\n    public void setTempReference(int tempReference) {\n        this.tempReference = tempReference;\n    }\n\n    public RealmList<String> getPhoneNumbers() {\n        return phoneNumbers;\n    }\n\n    public void setPhoneNumbers(RealmList<String> phoneNumbers) {\n        this.phoneNumbers = phoneNumbers;\n    }\n}\n"
  },
  {
    "path": "examples/introExample/src/main/res/layout/activity_realm_basic_example.xml",
    "content": "<ScrollView\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:paddingLeft=\"@dimen/activity_horizontal_margin\"\n    android:paddingRight=\"@dimen/activity_horizontal_margin\"\n    android:paddingTop=\"@dimen/activity_vertical_margin\"\n    android:paddingBottom=\"@dimen/activity_vertical_margin\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\">\n    <LinearLayout\n        android:orientation=\"vertical\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\">\n        <TextView\n            android:gravity=\"center_horizontal\"\n            android:text=\"@string/status_output\"\n            android:textStyle=\"bold\"\n            android:textSize=\"18sp\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"wrap_content\"/>\n        <LinearLayout\n            android:id=\"@+id/container\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"match_parent\"\n            android:paddingTop=\"10sp\"\n            android:orientation=\"vertical\"\n            tools:context=\".RealmIntroExample\"/>\n    </LinearLayout>\n</ScrollView>\n"
  },
  {
    "path": "examples/introExample/src/main/res/values/dimens.xml",
    "content": "<resources>\n    <!-- Default screen margins, per the Android Design guidelines. -->\n    <dimen name=\"activity_horizontal_margin\">16dp</dimen>\n    <dimen name=\"activity_vertical_margin\">16dp</dimen>\n</resources>\n"
  },
  {
    "path": "examples/introExample/src/main/res/values/strings.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n\n    <string name=\"app_name\">Intro example</string>\n    <string name=\"status_output\">Status Output…</string>\n\n</resources>\n"
  },
  {
    "path": "examples/introExample/src/main/res/values/styles.xml",
    "content": "<resources>\n\n    <!-- Base application theme. -->\n    <style name=\"AppTheme\" parent=\"android:Theme.Holo.Light.DarkActionBar\">\n        <!-- Customize your theme here. -->\n    </style>\n\n</resources>\n"
  },
  {
    "path": "examples/introExample/src/main/res/values-w820dp/dimens.xml",
    "content": "<resources>\n    <!-- Example customization of dimensions originally defined in res/values/dimens.xml\n         (such as screen margins) for screens with more than 820dp of available width. This\n         would include 7\" and 10\" devices in landscape (~960dp and ~1280dp respectively). -->\n    <dimen name=\"activity_horizontal_margin\">64dp</dimen>\n</resources>\n"
  },
  {
    "path": "examples/jsonExample/build.gradle",
    "content": "apply plugin: 'com.android.application'\napply plugin: 'realm-android'\n\nandroid {\n    compileSdkVersion rootProject.sdkVersion\n    buildToolsVersion rootProject.buildTools\n\n    compileOptions {\n        sourceCompatibility JavaVersion.VERSION_1_8\n        targetCompatibility JavaVersion.VERSION_1_8\n    }\n    defaultConfig {\n        applicationId 'io.realm.examples.json'\n        targetSdkVersion rootProject.sdkVersion\n        minSdkVersion rootProject.minSdkVersion\n        versionCode 1\n        versionName \"1.0\"\n    }\n    buildTypes {\n        release {\n            minifyEnabled true\n            signingConfig signingConfigs.debug\n        }\n        debug {\n            minifyEnabled true\n        }\n    }\n    productFlavors {\n    }\n}\n\ndependencies {\n    compileOnly 'org.projectlombok:lombok:1.18.22'\n    compileOnly 'javax.annotation:javax.annotation-api:1.3.1'\n    annotationProcessor 'org.projectlombok:lombok:1.18.22'\n}\n"
  },
  {
    "path": "examples/jsonExample/lint.xml",
    "content": "<lint>\n    <issue id=\"AllowBackup\" severity=\"ignore\" />\n    <issue id=\"IconLauncherShape\" severity=\"ignore\" />\n    <issue id=\"IconMissingDensityFolder\" severity=\"ignore\" />\n    <issue id=\"GoogleAppIndexingWarning\" severity=\"ignore\" />\n    <issue id=\"InvalidPackage\" severity=\"ignore\" />\n</lint>\n"
  },
  {
    "path": "examples/jsonExample/lombok.config",
    "content": "lombok.addGeneratedAnnotation = false"
  },
  {
    "path": "examples/jsonExample/src/main/AndroidManifest.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    package=\"io.realm.examples.json\">\n\n    <application\n        android:name=\".MyApplication\"\n        android:allowBackup=\"true\"\n        android:icon=\"@mipmap/ic_launcher\"\n        android:label=\"@string/app_name\"\n        android:theme=\"@style/AppTheme\">\n        <activity\n            android:name=\".JsonExampleActivity\"\n            android:configChanges=\"keyboard|screenSize|orientation\"\n            android:label=\"@string/app_name\">\n            <intent-filter>\n                <action android:name=\"android.intent.action.MAIN\" />\n                <category android:name=\"android.intent.category.LAUNCHER\" />\n            </intent-filter>\n        </activity>\n    </application>\n\n</manifest>\n"
  },
  {
    "path": "examples/jsonExample/src/main/assets/cities.json",
    "content": "[\n    { \"name\"  : \"Barcelona\",\n      \"votes\" : 23 },\n\n    { \"name\"  : \"San Francisco\",\n      \"votes\" : 21 },\n\n    { \"name\"  : \"Venice\",\n      \"votes\" : 19 },\n\n    { \"name\"  : \"Melbourne\",\n      \"votes\" : 18 },\n\n    { \"name\"  : \"Paris\",\n      \"votes\" : 17 },\n\n    { \"name\"  : \"Seville\",\n      \"votes\" : 14 },\n\n    { \"name\"  : \"Sydney\",\n      \"votes\" : 12 },\n\n    { \"name\"  : \"New York\",\n      \"votes\" : 11 },\n\n    { \"name\"  : \"Krakow\",\n      \"votes\" : 9 },\n\n    { \"name\"  : \"Peoria\",\n      \"votes\" : 72 },\n\n    { \"name\"  : \"Springfield\",\n      \"votes\" : 88 },\n\n    { \"name\"  : \"Kansas City\",\n      \"votes\" : 100 },\n\n    { \"name\"  : \"Tokyo\",\n      \"votes\" : 20 },\n\n    { \"name\"  : \"Boise\",\n      \"votes\" : 17 },\n\n    { \"name\"  : \"Los Angeles\",\n      \"votes\" : 14 },\n\n    { \"name\"  : \"Newark\",\n      \"votes\" : 12 },\n\n    { \"name\"  : \"Chicago\",\n      \"votes\" : 11 },\n\n    { \"name\"  : \"Detroit\",\n      \"votes\" : 91 },\n\n    { \"name\"  : \"Florence\",\n      \"votes\" : 4 },\n\n    { \"name\"  : \"Madrid\",\n      \"votes\" : 1 },\n\n    { \"name\"  : \"London\",\n      \"votes\" : 9 }\n]"
  },
  {
    "path": "examples/jsonExample/src/main/java/io/realm/examples/json/City.java",
    "content": "/*\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\npackage io.realm.examples.json;\n\nimport io.realm.RealmObject;\nimport lombok.Getter;\nimport lombok.Setter;\n\n@Getter\n@Setter\npublic class City extends RealmObject {\n    private String name;\n    private long votes;\n}\n"
  },
  {
    "path": "examples/jsonExample/src/main/java/io/realm/examples/json/CityAdapter.java",
    "content": "/*\n * Copyright 2018 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\npackage io.realm.examples.json;\n\nimport android.view.LayoutInflater;\nimport android.view.View;\nimport android.view.ViewGroup;\nimport android.widget.BaseAdapter;\nimport android.widget.TextView;\n\nimport java.util.Collections;\nimport java.util.List;\n\n// This adapter is strictly to interface with the GridView and doesn't\n// particular show much interesting Realm functionality.\npublic class CityAdapter extends BaseAdapter {\n    public static final String TAG = \"CityAdapter\";\n\n    private List<City> cities = Collections.emptyList();\n\n    public CityAdapter() {\n    }\n\n    public void setData(List<City> details) {\n        this.cities = details;\n        notifyDataSetChanged();\n    }\n\n    @Override\n    public int getCount() {\n        return cities == null ? 0 : cities.size();\n    }\n\n    @Override\n    public City getItem(int position) {\n        return cities.get(position);\n    }\n\n    @Override\n    public long getItemId(int i) {\n        return i;\n    }\n\n    private static class ViewHolder {\n        private TextView name;\n        private TextView votes;\n\n        public ViewHolder(View view) {\n            this.name = view.findViewById(R.id.name);\n            this.votes = view.findViewById(R.id.votes);\n        }\n\n        public void bind(City city) {\n            name.setText(city.getName());\n            votes.setText(String.valueOf(city.getVotes()));\n        }\n    }\n\n    @Override\n    public View getView(int position, View currentView, ViewGroup parent) {\n        LayoutInflater inflater = LayoutInflater.from(parent.getContext());\n        ViewHolder viewHolder;\n\n        if (currentView == null) {\n            currentView = inflater.inflate(R.layout.city_listitem, parent, false);\n            viewHolder = new ViewHolder(currentView);\n            currentView.setTag(viewHolder);\n        } else {\n            viewHolder = (ViewHolder)currentView.getTag();\n        }\n\n        City city = cities.get(position);\n        viewHolder.bind(city);\n\n        return currentView;\n    }\n}\n"
  },
  {
    "path": "examples/jsonExample/src/main/java/io/realm/examples/json/JsonExampleActivity.java",
    "content": "/*\n * Copyright 2018 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\npackage io.realm.examples.json;\n\nimport android.app.Activity;\nimport android.os.Bundle;\nimport android.widget.GridView;\n\nimport org.json.JSONObject;\n\nimport java.io.IOException;\nimport java.io.InputStream;\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport io.realm.Realm;\nimport io.realm.RealmChangeListener;\nimport io.realm.RealmConfiguration;\nimport io.realm.RealmResults;\n\n/**\n * This example demonstrates how to import RealmObjects as JSON. Realm supports JSON represented\n * as Strings, JSONObject, JSONArray or InputStreams (from API 11+)\n */\npublic class JsonExampleActivity extends Activity {\n\n    private GridView gridView;\n    private CityAdapter adapter;\n\n    private Realm realm;\n    private RealmResults<City> cities;\n    private RealmChangeListener<RealmResults<City>> realmChangeListener = (cities) -> {\n        adapter.setData(cities);\n    };\n\n    @Override\n    protected void onCreate(Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n        setContentView(R.layout.activity_realm_example);\n        RealmConfiguration config = new RealmConfiguration.Builder()\n                .allowWritesOnUiThread(true)\n                .allowQueriesOnUiThread(true)\n                .build();\n\n        Realm.deleteRealm(config);\n\n        realm = Realm.getInstance(config);\n\n        gridView = findViewById(R.id.cities_list);\n\n        cities = realm.where(City.class).findAllAsync();\n        cities.addChangeListener(realmChangeListener);\n\n        adapter = new CityAdapter();\n        gridView.setAdapter(adapter);\n\n        // Load from file \"cities.json\" first time\n        loadCities();\n    }\n\n\n    @Override\n    protected void onDestroy() {\n        super.onDestroy();\n        cities.removeAllChangeListeners();\n        realm.close();\n    }\n\n    public void loadCities() {\n        try {\n            loadJsonFromStream();\n            loadJsonFromJsonObject();\n            loadJsonFromString();\n        } catch(IOException e) {\n            throw new RuntimeException(e);\n        }\n    }\n\n    private void loadJsonFromStream() throws IOException {\n        // Use streams if you are worried about the size of the JSON whether it was persisted on disk\n        // or received from the network.\n        try(InputStream stream = getAssets().open(\"cities.json\")) {\n            try {\n                // Open a transaction to store items into the realm\n                realm.beginTransaction();\n                realm.createAllFromJson(City.class, stream);\n                realm.commitTransaction();\n            } catch (IOException e) {\n                // Remember to cancel the transaction if anything goes wrong.\n                if(realm.isInTransaction()) {\n                    realm.cancelTransaction();\n                }\n                throw new RuntimeException(e);\n            }\n        }\n    }\n\n    private void loadJsonFromJsonObject() {\n        Map<String, String> city = new HashMap<String, String>();\n        city.put(\"name\", \"København\");\n        city.put(\"votes\", \"9\");\n        final JSONObject json = new JSONObject(city);\n\n        realm.executeTransaction(realm -> realm.createObjectFromJson(City.class, json));\n    }\n\n    private void loadJsonFromString() {\n        final String json = \"{ name: \\\"Aarhus\\\", votes: 99 }\";\n\n        realm.executeTransaction(realm -> realm.createObjectFromJson(City.class, json));\n    }\n}\n"
  },
  {
    "path": "examples/jsonExample/src/main/java/io/realm/examples/json/MyApplication.java",
    "content": "/*\n * Copyright 2016 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\npackage io.realm.examples.json;\n\nimport android.app.Application;\n\nimport io.realm.Realm;\n\npublic class MyApplication extends Application {\n\n    @Override\n    public void onCreate() {\n        super.onCreate();\n        Realm.init(this);\n    }\n}\n"
  },
  {
    "path": "examples/jsonExample/src/main/res/layout/activity_realm_example.xml",
    "content": "<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:orientation=\"vertical\"\n    android:paddingLeft=\"@dimen/activity_horizontal_margin\"\n    android:paddingRight=\"@dimen/activity_horizontal_margin\"\n    tools:context=\".JsonExampleActivity\">\n\n    <TextView\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:gravity=\"center_horizontal\"\n        android:paddingBottom=\"@dimen/activity_vertical_margin\"\n        android:paddingTop=\"@dimen/activity_vertical_margin\"\n        android:text=\"@string/label\"\n        android:textSize=\"18sp\" />\n\n    <GridView\n        android:id=\"@+id/cities_list\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:listSelector=\"@android:color/transparent\"\n        android:numColumns=\"2\" />\n</LinearLayout>\n"
  },
  {
    "path": "examples/jsonExample/src/main/res/layout/city_listitem.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"wrap_content\"\n    android:gravity=\"center\"\n    android:orientation=\"horizontal\">\n\n    <TextView\n        android:id=\"@+id/name\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:layout_margin=\"5dp\"\n        android:textColor=\"@android:color/black\" />\n\n    <TextView\n        android:id=\"@+id/votes\"\n        android:layout_width=\"wrap_content\"\n         android:layout_height=\"wrap_content\"\n        android:layout_margin=\"5dp\"\n        android:textColor=\"@android:color/black\" />\n</LinearLayout>\n"
  },
  {
    "path": "examples/jsonExample/src/main/res/values/dimens.xml",
    "content": "<resources>\n    <!-- Default screen margins, per the Android Design guidelines. -->\n    <dimen name=\"activity_horizontal_margin\">16dp</dimen>\n    <dimen name=\"activity_vertical_margin\">16dp</dimen>\n</resources>\n"
  },
  {
    "path": "examples/jsonExample/src/main/res/values/strings.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <string name=\"app_name\">JSON Example</string>\n    <string name=\"label\">My Favorite City</string>\n</resources>\n"
  },
  {
    "path": "examples/jsonExample/src/main/res/values/styles.xml",
    "content": "<resources>\n\n    <!-- Base application theme. -->\n    <style name=\"AppTheme\" parent=\"android:Theme.Holo.Light.DarkActionBar\">\n        <!-- Customize your theme here. -->\n    </style>\n\n</resources>\n"
  },
  {
    "path": "examples/jsonExample/src/main/res/values-w820dp/dimens.xml",
    "content": "<resources>\n    <!-- Example customization of dimensions originally defined in res/values/dimens.xml\n         (such as screen margins) for screens with more than 820dp of available width. This\n         would include 7\" and 10\" devices in landscape (~960dp and ~1280dp respectively). -->\n    <dimen name=\"activity_horizontal_margin\">64dp</dimen>\n</resources>\n"
  },
  {
    "path": "examples/kotlinExample/build.gradle",
    "content": "apply plugin: 'com.android.application'\napply plugin: 'kotlin-android'\napply plugin: 'kotlin-kapt'\napply plugin: 'realm-android'\n\nandroid {\n    //noinspection GroovyAssignabilityCheck\n    compileSdkVersion rootProject.sdkVersion\n    //noinspection GroovyAssignabilityCheck\n    buildToolsVersion rootProject.buildTools\n\n    defaultConfig {\n        applicationId 'io.realm.examples.kotlin'\n        //noinspection GroovyAssignabilityCheck\n        targetSdkVersion rootProject.sdkVersion\n        minSdkVersion rootProject.minSdkVersion\n        versionCode 1\n        versionName \"1.0\"\n    }\n\n    buildTypes {\n        release {\n            minifyEnabled true\n            signingConfig signingConfigs.debug\n        }\n        debug {\n            minifyEnabled true\n        }\n    }\n\n    sourceSets {\n        main.java.srcDirs += 'src/main/kotlin'\n    }\n}\n\n// This is added automatically if Kotlin is registered in the project, but Kotlin extension functions\n// for Realm can be excluded if needed.\nrealm {\n    kotlinExtensionsEnabled = true\n}\n\n// enable @ParametersAreNonnullByDefault annotation. See https://blog.jetbrains.com/kotlin/2017/09/kotlin-1-1-50-is-out/\ntasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).all {\n    kotlinOptions {\n        freeCompilerArgs = [\"-Xjsr305=strict\"]\n    }\n}\n\ndependencies {\n    implementation \"org.jetbrains.anko:anko-commons:0.10.4\"\n}\n"
  },
  {
    "path": "examples/kotlinExample/lint.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<lint>\n    <issue id=\"AllowBackup\" severity=\"ignore\" />\n    <issue id=\"GoogleAppIndexingWarning\" severity=\"ignore\" />\n    <issue id=\"IconMissingDensityFolder\" severity=\"ignore\" />\n    <issue id=\"IconLauncherShape\" severity=\"ignore\" />\n    <issue id=\"InvalidPackage\" severity=\"ignore\" />\n</lint>\n"
  },
  {
    "path": "examples/kotlinExample/src/main/AndroidManifest.xml",
    "content": "<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    package=\"io.realm.examples.kotlin\">\n\n    <application\n        android:name=\".MyApplication\"\n        android:allowBackup=\"true\"\n        android:icon=\"@mipmap/ic_launcher\"\n        android:label=\"@string/app_name\"\n        android:theme=\"@style/AppTheme\">\n        <activity\n            android:name=\".KotlinExampleActivity\"\n            android:label=\"@string/app_name\">\n            <intent-filter>\n                <action android:name=\"android.intent.action.MAIN\" />\n\n                <category android:name=\"android.intent.category.LAUNCHER\" />\n            </intent-filter>\n        </activity>\n    </application>\n\n</manifest>\n"
  },
  {
    "path": "examples/kotlinExample/src/main/kotlin/io/realm/examples/kotlin/KotlinExampleActivity.kt",
    "content": "/*\n * Copyright 2015 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\npackage io.realm.examples.kotlin\n\nimport android.app.Activity\nimport android.os.Bundle\nimport android.util.Log\nimport android.widget.LinearLayout\nimport android.widget.TextView\nimport io.realm.Realm\nimport io.realm.RealmConfiguration\nimport io.realm.Sort\nimport io.realm.examples.kotlin.model.Cat\nimport io.realm.examples.kotlin.model.Dog\nimport io.realm.examples.kotlin.model.Person\nimport io.realm.kotlin.createObject\nimport io.realm.kotlin.where\nimport org.jetbrains.anko.doAsync\nimport org.jetbrains.anko.uiThread\n\nclass KotlinExampleActivity : Activity() {\n    companion object {\n        const val TAG: String = \"KotlinExampleActivity\"\n    }\n\n    private lateinit var rootLayout: LinearLayout\n    private lateinit var realm: Realm\n\n    override fun onCreate(savedInstanceState: Bundle?) {\n        super.onCreate(savedInstanceState)\n        setContentView(R.layout.activity_realm_basic_example)\n\n        rootLayout = findViewById(R.id.container)\n        rootLayout.removeAllViews()\n\n        Realm.setDefaultConfiguration(\n            RealmConfiguration.Builder()\n                .allowQueriesOnUiThread(true)\n                .allowWritesOnUiThread(true)\n                .build()\n        )\n\n        // Open the realm for the UI thread.\n        realm = Realm.getDefaultInstance()\n\n        // Delete all persons\n        // Using executeTransaction with a lambda reduces code size and makes it impossible\n        // to forget to commit the transaction.\n        realm.executeTransaction { realm ->\n            realm.deleteAll()\n        }\n\n        // These operations are small enough that\n        // we can generally safely run them on the UI thread.\n        basicCRUD(realm)\n        basicQuery(realm)\n        basicLinkQuery(realm)\n\n        // More complex operations can be executed on another thread, for example using\n        // Anko's doAsync extension method.\n        doAsync {\n            var info = \"\"\n\n            // Open the default realm. All threads must use its own reference to the realm.\n            // Those can not be transferred across threads.\n\n            // Realm implements the Closable interface, therefore\n            // we can make use of Kotlin's built-in extension method 'use' (pun intended).\n            Realm.getDefaultInstance().use { realm ->\n                info += complexReadWrite(realm)\n                info += complexQuery(realm)\n            }\n            uiThread {\n                showStatus(info)\n            }\n        }\n    }\n\n    override fun onDestroy() {\n        super.onDestroy()\n        realm.close() // Remember to close Realm when done.\n    }\n\n    private fun showStatus(text: String) {\n        Log.i(TAG, text)\n        val textView = TextView(this)\n        textView.text = text\n        rootLayout.addView(textView)\n    }\n\n    @Suppress(\"NAME_SHADOWING\")\n    private fun basicCRUD(realm: Realm) {\n        showStatus(\"Perform basic Create/Read/Update/Delete (CRUD) operations...\")\n\n        // All writes must be wrapped in a transaction to facilitate safe multi threading\n        realm.executeTransaction { realm ->\n            // Add a person\n            val person = realm.createObject<Person>(0)\n            person.name = \"Young Person\"\n            person.age = 14\n        }\n\n        // Find the first person (no query conditions) and read a field\n        val person = realm.where<Person>().findFirst()!!\n        showStatus(person.name + \": \" + person.age)\n\n        // Update person in a transaction\n        realm.executeTransaction { _ ->\n            person.name = \"Senior Person\"\n            person.age = 99\n            showStatus(person.name + \" got older: \" + person.age)\n        }\n    }\n\n    private fun basicQuery(realm: Realm) {\n        showStatus(\"\\nPerforming basic Query operation...\")\n        showStatus(\"Number of persons: ${realm.where<Person>().count()}\")\n\n        val ageCriteria = 99\n        val results = realm.where<Person>().equalTo(\"age\", ageCriteria).findAll()\n\n        showStatus(\"Size of result set: \" + results.size)\n    }\n\n    private fun basicLinkQuery(realm: Realm) {\n        showStatus(\"\\nPerforming basic Link Query operation...\")\n        showStatus(\"Number of persons: ${realm.where<Person>().count()}\")\n\n        val results = realm.where<Person>().equalTo(\"cats.name\", \"Tiger\").findAll()\n\n        showStatus(\"Size of result set: ${results.size}\")\n    }\n\n    private fun complexReadWrite(realm: Realm): String {\n        var status = \"\\nPerforming complex Read/Write operation...\"\n\n        // Add ten persons in one transaction\n        realm.executeTransaction {\n            val fido = realm.createObject<Dog>()\n            fido.name = \"fido\"\n            for (i in 1..9) {\n                val person = realm.createObject<Person>(i.toLong())\n                person.name = \"Person no. $i\"\n                person.age = i\n                person.dog = fido\n\n                // The field tempReference is annotated with @Ignore.\n                // This means setTempReference sets the Person tempReference\n                // field directly. The tempReference is NOT saved as part of\n                // the RealmObject:\n                person.tempReference = 42\n\n                for (j in 0..i - 1) {\n                    val cat = realm.createObject<Cat>()\n                    cat.name = \"Cat_$j\"\n                    person.cats.add(cat)\n                }\n            }\n        }\n\n        // Implicit read transactions allow you to access your objects\n        status += \"\\nNumber of persons: ${realm.where<Person>().count()}\"\n\n        // Iterate over all objects\n        for (person in realm.where<Person>().findAll()) {\n            val dogName: String = person?.dog?.name ?: \"None\"\n\n            status += \"\\n${person.name}: ${person.age} : $dogName : ${person.cats.size}\"\n\n            // The field tempReference is annotated with @Ignore\n            // Though we initially set its value to 42, it has\n            // not been saved as part of the Person RealmObject:\n            check(person.tempReference == 0)\n        }\n\n        // Sorting\n        val sortedPersons = realm.where<Person>().sort(Person::age.name, Sort.DESCENDING).findAll()\n        status += \"\\nSorting ${sortedPersons.last()?.name} == ${realm.where<Person>().findAll().first()?.name}\"\n\n        return status\n    }\n\n    private fun complexQuery(realm: Realm): String {\n        var status = \"\\n\\nPerforming complex Query operation...\"\n\n        status += \"\\nNumber of persons: ${realm.where<Person>().count()}\"\n\n        // Find all persons where age between 7 and 9 and name begins with \"Person\".\n        val results = realm.where<Person>()\n            .between(\"age\", 7, 9)       // Notice implicit \"and\" operation\n            .beginsWith(\"name\", \"Person\")\n            .findAll()\n\n        status += \"\\nSize of result set: ${results.size}\"\n\n        return status\n    }\n}\n"
  },
  {
    "path": "examples/kotlinExample/src/main/kotlin/io/realm/examples/kotlin/MyApplication.kt",
    "content": "/*\n * Copyright 2016 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\npackage io.realm.examples.kotlin\n\nimport android.app.Application\n\nimport io.realm.Realm\n\nclass MyApplication : Application() {\n\n    override fun onCreate() {\n        super.onCreate()\n        // Initialize Realm. Should only be done once when the application starts.\n        Realm.init(this)\n    }\n}\n"
  },
  {
    "path": "examples/kotlinExample/src/main/kotlin/io/realm/examples/kotlin/model/Cat.kt",
    "content": "/*\n * Copyright 2015 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\npackage io.realm.examples.kotlin.model\n\nimport io.realm.RealmObject\nimport io.realm.RealmResults\nimport io.realm.annotations.LinkingObjects\n\nopen class Cat : RealmObject() {\n    var name: String? = null\n\n    @LinkingObjects(\"cats\")\n    val owners: RealmResults<Person>? = null\n}\n"
  },
  {
    "path": "examples/kotlinExample/src/main/kotlin/io/realm/examples/kotlin/model/Dog.kt",
    "content": "/*\n * Copyright 2015 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\npackage io.realm.examples.kotlin.model\n\nimport io.realm.RealmObject\nimport io.realm.RealmResults\nimport io.realm.annotations.LinkingObjects\n\nopen class Dog : RealmObject() {\n    var name: String? = null\n\n    @LinkingObjects(\"dog\")\n    val owners: RealmResults<Person>? = null\n}\n"
  },
  {
    "path": "examples/kotlinExample/src/main/kotlin/io/realm/examples/kotlin/model/Person.kt",
    "content": "/*\n * Copyright 2015 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\npackage io.realm.examples.kotlin.model\n\nimport io.realm.RealmList\nimport io.realm.RealmObject\nimport io.realm.annotations.Ignore\nimport io.realm.annotations.PrimaryKey\n\n// Your model has to extend RealmObject. Furthermore, the class must be annotated with open (Kotlin classes are final\n// by default).\nopen class Person(\n        // You can put properties in the constructor as long as all of them are initialized with\n        // default values. This ensures that an empty constructor is generated.\n        // All properties are by default persisted.\n        // Properties can be annotated with PrimaryKey or Index.\n        // If you use non-nullable types, properties must be initialized with non-null values.\n        @PrimaryKey var id: Long = 0,\n\n        var name: String = \"\",\n\n        var age: Int = 0,\n\n        // Other objects in a one-to-one relation must also subclass RealmObject\n        var dog: Dog? = null,\n\n        // One-to-many relations is simply a RealmList of the objects which also subclass RealmObject\n        var cats: RealmList<Cat> = RealmList(),\n\n        // You can instruct Realm to ignore a field and not persist it.\n        @Ignore var tempReference: Int = 0\n\n) : RealmObject() {\n    // The Kotlin compiler generates standard getters and setters.\n    // Realm will overload them and code inside them is ignored.\n    // So if you prefer you can also just have empty abstract methods.\n}\n"
  },
  {
    "path": "examples/kotlinExample/src/main/res/layout/activity_realm_basic_example.xml",
    "content": "<ScrollView\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:paddingLeft=\"@dimen/activity_horizontal_margin\"\n    android:paddingRight=\"@dimen/activity_horizontal_margin\"\n    android:paddingTop=\"@dimen/activity_vertical_margin\"\n    android:paddingBottom=\"@dimen/activity_vertical_margin\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\">\n    <LinearLayout\n        android:orientation=\"vertical\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\">\n        <TextView\n            android:gravity=\"center_horizontal\"\n            android:text=\"@string/status_output\"\n            android:textStyle=\"bold\"\n            android:textSize=\"18sp\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"wrap_content\"/>\n        <LinearLayout\n            android:id=\"@+id/container\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"match_parent\"\n            android:paddingTop=\"10sp\"\n            android:orientation=\"vertical\"\n            tools:context=\".RealmIntroExample\"/>\n    </LinearLayout>\n</ScrollView>\n"
  },
  {
    "path": "examples/kotlinExample/src/main/res/values/dimens.xml",
    "content": "<resources>\n    <!-- Default screen margins, per the Android Design guidelines. -->\n    <dimen name=\"activity_horizontal_margin\">16dp</dimen>\n    <dimen name=\"activity_vertical_margin\">16dp</dimen>\n</resources>\n"
  },
  {
    "path": "examples/kotlinExample/src/main/res/values/strings.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <string name=\"app_name\">Kotlin example</string>\n    <string name=\"status_output\">Status Output…</string>\n</resources>\n"
  },
  {
    "path": "examples/kotlinExample/src/main/res/values/styles.xml",
    "content": "<resources>\n\n    <!-- Base application theme. -->\n    <style name=\"AppTheme\" parent=\"android:Theme.Holo.Light.DarkActionBar\">\n        <!-- Customize your theme here. -->\n    </style>\n\n</resources>\n"
  },
  {
    "path": "examples/kotlinExample/src/main/res/values-w820dp/dimens.xml",
    "content": "<resources>\n    <!-- Example customization of dimensions originally defined in res/values/dimens.xml\n         (such as screen margins) for screens with more than 820dp of available width. This\n         would include 7\" and 10\" devices in landscape (~960dp and ~1280dp respectively). -->\n    <dimen name=\"activity_horizontal_margin\">64dp</dimen>\n</resources>\n"
  },
  {
    "path": "examples/migrationExample/build.gradle",
    "content": "apply plugin: 'com.android.application'\napply plugin: 'realm-android'\n\nandroid {\n    compileSdkVersion rootProject.sdkVersion\n    buildToolsVersion rootProject.buildTools\n\n    defaultConfig {\n        applicationId \"examples.realm.io.migration\"\n        targetSdkVersion rootProject.sdkVersion\n        minSdkVersion rootProject.minSdkVersion\n        versionCode 1\n        versionName \"1.0\"\n    }\n    buildTypes {\n        release {\n            minifyEnabled true\n            signingConfig signingConfigs.debug\n        }\n        debug {\n            minifyEnabled true\n        }\n    }\n}\n"
  },
  {
    "path": "examples/migrationExample/lint.xml",
    "content": "<lint>\n    <issue id=\"AllowBackup\" severity=\"ignore\" />\n    <issue id=\"IconLauncherShape\" severity=\"ignore\" />\n    <issue id=\"IconMissingDensityFolder\" severity=\"ignore\" />\n    <issue id=\"GoogleAppIndexingWarning\" severity=\"ignore\" />\n    <issue id=\"InvalidPackage\" severity=\"ignore\" />\n</lint>\n"
  },
  {
    "path": "examples/migrationExample/src/main/AndroidManifest.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    package=\"io.realm.examples.realmmigrationexample\" >\n\n    <application\n        android:name=\".MyApplication\"\n        android:allowBackup=\"true\"\n        android:icon=\"@mipmap/ic_launcher\"\n        android:label=\"@string/app_name\"\n        android:theme=\"@style/AppTheme\" >\n        <activity\n            android:name=\".MigrationExampleActivity\"\n            android:label=\"@string/app_name\" >\n            <intent-filter>\n                <action android:name=\"android.intent.action.MAIN\" />\n\n                <category android:name=\"android.intent.category.LAUNCHER\" />\n            </intent-filter>\n        </activity>\n    </application>\n\n</manifest>\n"
  },
  {
    "path": "examples/migrationExample/src/main/java/io/realm/examples/realmmigrationexample/MigrationExampleActivity.java",
    "content": "/*\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\npackage io.realm.examples.realmmigrationexample;\n\nimport android.app.Activity;\nimport android.os.Bundle;\nimport android.util.Log;\nimport android.widget.LinearLayout;\nimport android.widget.TextView;\n\nimport java.io.File;\nimport java.io.FileNotFoundException;\nimport java.io.FileOutputStream;\nimport java.io.IOException;\nimport java.io.InputStream;\n\nimport io.realm.Realm;\nimport io.realm.RealmConfiguration;\nimport io.realm.examples.realmmigrationexample.model.Migration;\nimport io.realm.examples.realmmigrationexample.model.Person;\n\n/*\n** This example demonstrates how you can migrate your data through different updates\n** of your models.\n*/\npublic class MigrationExampleActivity extends Activity {\n\n    public static final String TAG = MigrationExampleActivity.class.getName();\n\n    private LinearLayout rootLayout = null;\n    private Realm realm;\n\n    @Override\n    protected void onCreate(Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n        setContentView(R.layout.activity_realm_migration_example);\n\n        rootLayout = ((LinearLayout) findViewById(R.id.container));\n        rootLayout.removeAllViews();\n\n        // 3 versions of the databases for testing. Normally you would only have one.\n        copyBundledRealmFile(this.getResources().openRawResource(R.raw.default0), \"default0.realm\");\n        copyBundledRealmFile(this.getResources().openRawResource(R.raw.default1), \"default1.realm\");\n        copyBundledRealmFile(this.getResources().openRawResource(R.raw.default2), \"default2.realm\");\n\n        // When you create a RealmConfiguration you can specify the version of the schema.\n        // If the schema does not have that version a RealmMigrationNeededException will be thrown.\n        RealmConfiguration config0 = new RealmConfiguration.Builder()\n                .name(\"default0.realm\")\n                .schemaVersion(3)\n                .build();\n\n        // You can then manually call Realm.migrateRealm().\n        try {\n            Realm.migrateRealm(config0, new Migration());\n        } catch (FileNotFoundException ignored) {\n            // If the Realm file doesn't exist, just ignore.\n        }\n        realm = Realm.getInstance(config0);\n        showStatus(\"Default0\");\n        showStatus(realm);\n        realm.close();\n\n        // Or you can add the migration code to the configuration. This will run the migration code without throwing\n        // a RealmMigrationNeededException.\n        RealmConfiguration config1 = new RealmConfiguration.Builder()\n                .name(\"default1.realm\")\n                .schemaVersion(3)\n                .migration(new Migration())\n                .build();\n\n        realm = Realm.getInstance(config1); // Automatically run migration if needed\n        showStatus(\"Default1\");\n        showStatus(realm);\n        realm.close();\n\n        // or you can set .deleteRealmIfMigrationNeeded() if you don't want to bother with migrations.\n        // WARNING: This will delete all data in the Realm though.\n        RealmConfiguration config2 = new RealmConfiguration.Builder()\n                .name(\"default2.realm\")\n                .schemaVersion(3)\n                .deleteRealmIfMigrationNeeded()\n                .build();\n\n        realm = Realm.getInstance(config2);\n        showStatus(\"default2\");\n        showStatus(realm);\n        realm.close();\n    }\n\n    private String copyBundledRealmFile(InputStream inputStream, String outFileName) {\n        try {\n            File file = new File(this.getFilesDir(), outFileName);\n            FileOutputStream outputStream = new FileOutputStream(file);\n            byte[] buf = new byte[1024];\n            int bytesRead;\n            while ((bytesRead = inputStream.read(buf)) > 0) {\n                outputStream.write(buf, 0, bytesRead);\n            }\n            outputStream.close();\n            return file.getAbsolutePath();\n        } catch (IOException e) {\n            e.printStackTrace();\n        }\n        return null;\n    }\n\n    private String realmString(Realm realm) {\n        StringBuilder stringBuilder = new StringBuilder();\n        for (Person person : realm.where(Person.class).findAll()) {\n            stringBuilder.append(person.toString()).append(\"\\n\");\n        }\n\n        return (stringBuilder.length() == 0) ? \"<data was deleted>\" : stringBuilder.toString();\n    }\n\n    private void showStatus(Realm realm) {\n        showStatus(realmString(realm));\n    }\n\n    private void showStatus(String txt) {\n        Log.i(TAG, txt);\n        TextView tv = new TextView(this);\n        tv.setText(txt);\n        rootLayout.addView(tv);\n    }\n}\n"
  },
  {
    "path": "examples/migrationExample/src/main/java/io/realm/examples/realmmigrationexample/MyApplication.java",
    "content": "/*\n * Copyright 2016 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\npackage io.realm.examples.realmmigrationexample;\n\nimport android.app.Application;\n\nimport io.realm.Realm;\n\npublic class MyApplication extends Application {\n\n    @Override\n    public void onCreate() {\n        super.onCreate();\n        Realm.init(this);\n    }\n}\n"
  },
  {
    "path": "examples/migrationExample/src/main/java/io/realm/examples/realmmigrationexample/model/Migration.java",
    "content": "/*\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\npackage io.realm.examples.realmmigrationexample.model;\n\nimport io.realm.DynamicRealm;\nimport io.realm.DynamicRealmObject;\nimport io.realm.FieldAttribute;\nimport io.realm.RealmMigration;\nimport io.realm.RealmObjectSchema;\nimport io.realm.RealmSchema;\n\n/**\n * Example of migrating a Realm file from version 0 (initial version) to its last version (version 3).\n */\npublic class Migration implements RealmMigration {\n\n    @Override\n    public void migrate(final DynamicRealm realm, long oldVersion, long newVersion) {\n        // During a migration, a DynamicRealm is exposed. A DynamicRealm is an untyped variant of a normal Realm, but\n        // with the same object creation and query capabilities.\n        // A DynamicRealm uses Strings instead of Class references because the Classes might not even exist or have been\n        // renamed.\n\n        // Access the Realm schema in order to create, modify or delete classes and their fields.\n        RealmSchema schema = realm.getSchema();\n\n        /************************************************\n            // Version 0\n            class Person\n                @Required\n                String firstName;\n                @Required\n                String lastName;\n                int    age;\n\n            // Version 1\n            class Person\n                @Required\n                String fullName;            // combine firstName and lastName into single field.\n                int age;\n        ************************************************/\n        // Migrate from version 0 to version 1\n        if (oldVersion == 0) {\n            RealmObjectSchema personSchema = schema.get(\"Person\");\n\n            // Combine 'firstName' and 'lastName' in a new field called 'fullName'\n            personSchema\n                    .addField(\"fullName\", String.class, FieldAttribute.REQUIRED)\n                    .transform(new RealmObjectSchema.Function() {\n                        @Override\n                        public void apply(DynamicRealmObject obj) {\n                            obj.set(\"fullName\", obj.getString(\"firstName\") + \" \" + obj.getString(\"lastName\"));\n                        }\n                    })\n                    .removeField(\"firstName\")\n                    .removeField(\"lastName\");\n            oldVersion++;\n        }\n\n        /************************************************\n            // Version 2\n                class Pet                   // add a new model class\n                    @Required\n                    String name;\n                    @Required\n                    String type;\n\n                class Person\n                    @Required\n                    String fullName;\n                    int age;\n                    RealmList<Pet> pets;    // add an array property\n\n         ************************************************/\n        // Migrate from version 1 to version 2\n        if (oldVersion == 1) {\n\n            // Create a new class\n            RealmObjectSchema petSchema = schema.create(\"Pet\")\n                    .addField(\"name\", String.class, FieldAttribute.REQUIRED)\n                    .addField(\"type\", String.class, FieldAttribute.REQUIRED);\n\n            // Add a new field to an old class and populate it with initial data\n            schema.get(\"Person\")\n                .addRealmListField(\"pets\", petSchema)\n                .transform(new RealmObjectSchema.Function() {\n                    @Override\n                    public void apply(DynamicRealmObject obj) {\n                        if (obj.getString(\"fullName\").equals(\"JP McDonald\")) {\n                            DynamicRealmObject pet = realm.createObject(\"Pet\");\n                            pet.setString(\"name\", \"Jimbo\");\n                            pet.setString(\"type\", \"dog\");\n                            obj.getList(\"pets\").add(pet);\n                        }\n                    }\n                });\n            oldVersion++;\n        }\n\n        /************************************************\n            // Version 3\n                class Pet\n                    @Required\n                    String name;\n                    int type;               // type becomes int\n\n                class Person\n                    String fullName;        // fullName is nullable now\n                    RealmList<Pet> pets;    // age and pets re-ordered (no action needed)\n                    int age;\n         ************************************************/\n        // Migrate from version 2 to version 3\n        if (oldVersion == 2) {\n            RealmObjectSchema personSchema = schema.get(\"Person\");\n            personSchema.setNullable(\"fullName\", true); // fullName is nullable now.\n\n            // Change type from String to int\n            schema.get(\"Pet\")\n                .addField(\"type_tmp\", int.class)\n                .transform(new RealmObjectSchema.Function() {\n                    @Override\n                    public void apply(DynamicRealmObject obj) {\n                        String oldType = obj.getString(\"type\");\n                        if (oldType.equals(\"dog\")) {\n                            obj.setLong(\"type_tmp\", 1);\n                        } else if (oldType.equals(\"cat\")) {\n                            obj.setInt(\"type_tmp\", 2);\n                        } else if (oldType.equals(\"hamster\")) {\n                            obj.setInt(\"type_tmp\", 3);\n                        }\n                    }\n                })\n                .removeField(\"type\")\n                .renameField(\"type_tmp\", \"type\");\n            oldVersion++;\n        }\n    }\n}\n"
  },
  {
    "path": "examples/migrationExample/src/main/java/io/realm/examples/realmmigrationexample/model/Person.java",
    "content": "/*\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\npackage io.realm.examples.realmmigrationexample.model;\n\nimport io.realm.RealmList;\nimport io.realm.RealmObject;\nimport io.realm.annotations.Ignore;\n\npublic class Person extends RealmObject {\n\n    private String fullName;\n    private int age;\n    private RealmList<Pet> pets;\n\n    public String getFullName() {\n        return fullName;\n    }\n\n    public void setFullName(String fullName) {\n        this.fullName = fullName;\n    }\n\n    public int getAge() {\n        return age;\n    }\n\n    public void setAge(int age) {\n        this.age = age;\n    }\n\n    public RealmList<Pet> getPets() {\n        return pets;\n    }\n\n    public void setPets(RealmList<Pet> pets) {\n        this.pets = pets;\n    }\n}\n\n"
  },
  {
    "path": "examples/migrationExample/src/main/java/io/realm/examples/realmmigrationexample/model/Pet.java",
    "content": "/*\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\npackage io.realm.examples.realmmigrationexample.model;\n\nimport io.realm.RealmObject;\nimport io.realm.annotations.Required;\n\npublic class Pet extends RealmObject {\n    @Required\n    private String name;\n    private int type;\n\n    public String getName() {\n        return name;\n    }\n\n    public void setName(String name) {\n        this.name = name;\n    }\n\n    public int getType() {\n        return type;\n    }\n\n    public void setType(int type) {\n        this.type = type;\n    }\n\n}\n"
  },
  {
    "path": "examples/migrationExample/src/main/res/layout/activity_realm_migration_example.xml",
    "content": "<ScrollView\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:paddingLeft=\"@dimen/activity_horizontal_margin\"\n    android:paddingRight=\"@dimen/activity_horizontal_margin\"\n    android:paddingTop=\"@dimen/activity_vertical_margin\"\n    android:paddingBottom=\"@dimen/activity_vertical_margin\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    tools:context=\".MigrationExampleActivity\">\n    <LinearLayout\n        android:orientation=\"vertical\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\">\n        <TextView\n            android:gravity=\"center_horizontal\"\n            android:text=\"@string/label\"\n            android:textStyle=\"bold\"\n            android:textSize=\"18sp\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"wrap_content\"/>\n        <LinearLayout\n            android:id=\"@+id/container\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"match_parent\"\n            android:paddingTop=\"10sp\"\n            android:orientation=\"vertical\"\n            tools:context=\".RealmIntroExample\"/>\n    </LinearLayout>\n</ScrollView>\n"
  },
  {
    "path": "examples/migrationExample/src/main/res/values/dimens.xml",
    "content": "<resources>\n    <!-- Default screen margins, per the Android Design guidelines. -->\n    <dimen name=\"activity_horizontal_margin\">16dp</dimen>\n    <dimen name=\"activity_vertical_margin\">16dp</dimen>\n</resources>\n"
  },
  {
    "path": "examples/migrationExample/src/main/res/values/strings.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources xmlns:tools=\"http://schemas.android.com/tools\">\n\n    <string name=\"app_name\">Migration example</string>\n    <string name=\"label\" tools:ignore=\"TypographyEllipsis\">Status Output...</string>\n\n</resources>\n"
  },
  {
    "path": "examples/migrationExample/src/main/res/values/styles.xml",
    "content": "<resources>\n\n    <!-- Base application theme. -->\n    <style name=\"AppTheme\" parent=\"android:Theme.Holo.Light.DarkActionBar\">\n        <!-- Customize your theme here. -->\n    </style>\n\n</resources>\n"
  },
  {
    "path": "examples/migrationExample/src/main/res/values-w820dp/dimens.xml",
    "content": "<resources>\n    <!-- Example customization of dimensions originally defined in res/values/dimens.xml\n         (such as screen margins) for screens with more than 820dp of available width. This\n         would include 7\" and 10\" devices in landscape (~960dp and ~1280dp respectively). -->\n    <dimen name=\"activity_horizontal_margin\">64dp</dimen>\n</resources>\n"
  },
  {
    "path": "examples/moduleExample/app/build.gradle",
    "content": "apply plugin: 'com.android.application'\napply plugin: 'realm-android'\n\nandroid {\n    compileSdkVersion rootProject.sdkVersion\n    buildToolsVersion rootProject.buildTools\n\n    defaultConfig {\n        applicationId 'io.realm.examples.appmodules'\n        targetSdkVersion rootProject.sdkVersion\n        minSdkVersion rootProject.minSdkVersion\n        versionCode 1\n        versionName \"1.0\"\n    }\n\n    signingConfigs {\n        release {\n            storeFile file(\"keystore/release.keystore\")\n            storePassword \"realm1234\"\n            keyAlias \"realm-introexample\"\n            keyPassword \"realm1234\"\n        }\n    }\n\n    buildTypes {\n        release {\n            minifyEnabled true\n            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'\n            signingConfig signingConfigs.release\n        }\n    }\n\n    compileOptions {\n        sourceCompatibility 1.8\n        targetCompatibility 1.8\n    }\n}\n\ndependencies {\n    implementation project(':moduleExample:library')\n}\n"
  },
  {
    "path": "examples/moduleExample/app/lint.xml",
    "content": "<lint>\n    <issue id=\"AllowBackup\" severity=\"ignore\" />\n    <issue id=\"IconLauncherShape\" severity=\"ignore\" />\n    <issue id=\"IconMissingDensityFolder\" severity=\"ignore\" />\n    <issue id=\"GoogleAppIndexingWarning\" severity=\"ignore\" />\n    <issue id=\"InvalidPackage\" severity=\"ignore\" />\n</lint>\n"
  },
  {
    "path": "examples/moduleExample/app/proguard-rules.pro",
    "content": "# Add project specific ProGuard rules here.\n# By default, the flags in this file are appended to flags specified\n# in /usr/local/Cellar/android-sdk/22.6.2/tools/proguard/proguard-android.txt\n# You can edit the include path and order by changing the proguardFiles\n# directive in build.gradle.\n#\n# For more details, see\n#   http://developer.android.com/guide/developing/tools/proguard.html\n\n# Add any project specific keep options here:\n\n# If your project uses WebView with JS, uncomment the following\n# and specify the fully qualified class name to the JavaScript interface\n# class:\n#-keepclassmembers class fqcn.of.javascript.interface.for.webview {\n#   public *;\n#}\n"
  },
  {
    "path": "examples/moduleExample/app/src/main/AndroidManifest.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    package=\"io.realm.examples.appmodules\" >\n\n    <application\n        android:name=\".MyApplication\"\n        android:icon=\"@mipmap/ic_launcher\"\n        android:label=\"@string/app_name\"\n        android:theme=\"@style/AppTheme\" >\n        <activity\n            android:name=\".ModulesExampleActivity\"\n            android:label=\"@string/app_name\" >\n            <intent-filter>\n                <action android:name=\"android.intent.action.MAIN\" />\n                <category android:name=\"android.intent.category.LAUNCHER\" />\n            </intent-filter>\n        </activity>\n    </application>\n</manifest>\n"
  },
  {
    "path": "examples/moduleExample/app/src/main/java/io/realm/examples/appmodules/ModulesExampleActivity.java",
    "content": "/*\n * Copyright 2015 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\npackage io.realm.examples.appmodules;\n\nimport android.app.Activity;\nimport android.os.Bundle;\nimport android.util.Log;\nimport android.widget.LinearLayout;\nimport android.widget.TextView;\n\nimport io.realm.Realm;\nimport io.realm.RealmConfiguration;\nimport io.realm.examples.appmodules.model.Cow;\nimport io.realm.examples.appmodules.model.Pig;\nimport io.realm.examples.appmodules.model.Snake;\nimport io.realm.examples.appmodules.model.Spider;\nimport io.realm.examples.appmodules.modules.CreepyAnimalsModule;\nimport io.realm.examples.librarymodules.Zoo;\nimport io.realm.examples.librarymodules.model.Cat;\nimport io.realm.examples.librarymodules.model.Dog;\nimport io.realm.examples.librarymodules.model.Elephant;\nimport io.realm.examples.librarymodules.model.Lion;\nimport io.realm.examples.librarymodules.model.Zebra;\nimport io.realm.examples.librarymodules.modules.AllAnimalsModule;\nimport io.realm.examples.librarymodules.modules.DomesticAnimalsModule;\nimport io.realm.examples.librarymodules.modules.ZooAnimalsModule;\nimport io.realm.exceptions.RealmException;\n\n/**\n* This example demonstrates how you can use modules to control which classes belong to which Realms and how you can\n * work with multiple Realms at the same time.\n*/\npublic class ModulesExampleActivity extends Activity {\n\n    public static final String TAG = ModulesExampleActivity.class.getName();\n    private LinearLayout rootLayout = null;\n\n    @Override\n    protected void onCreate(Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n        setContentView(R.layout.activity_modules_example);\n        rootLayout = ((LinearLayout) findViewById(R.id.container));\n        rootLayout.removeAllViews();\n\n        // The default Realm instance implicitly knows about all classes in the realmModuleAppExample Android Studio\n        // module. This does not include the classes from the realmModuleLibraryExample AS module so a Realm using this\n        // configuration would know about the following classes: { Cow, Pig, Snake, Spider }\n        RealmConfiguration defaultConfig = new RealmConfiguration\n                .Builder()\n                .modules(Realm.getDefaultModule(), new AllAnimalsModule())\n                .allowQueriesOnUiThread(true)\n                .allowWritesOnUiThread(true)\n                .build();\n\n        // It is possible to extend the default schema by adding additional Realm modules using modules(). This can\n        // also be Realm modules from libraries. The below Realm contains the following classes: { Cow, Pig, Snake,\n        // Spider, Cat, Dog }\n        RealmConfiguration farmAnimalsConfig = new RealmConfiguration.Builder()\n                .name(\"farm.realm\")\n                .allowQueriesOnUiThread(true)\n                .allowWritesOnUiThread(true)\n                .modules(Realm.getDefaultModule(), new AllAnimalsModule())\n                .build();\n\n        // Or you can completely replace the default schema.\n        // This Realm contains the following classes: { Elephant, Lion, Zebra, Snake, Spider }\n        RealmConfiguration exoticAnimalsConfig = new RealmConfiguration.Builder()\n                .name(\"exotic.realm\")\n                .allowQueriesOnUiThread(true)\n                .allowWritesOnUiThread(true)\n                .modules(new ZooAnimalsModule(), new CreepyAnimalsModule())\n                .build();\n\n        // Multiple Realms can be opened at the same time\n        showStatus(\"Opening multiple Realms\");\n        Realm defaultRealm = Realm.getInstance(defaultConfig);\n        final Realm farmRealm = Realm.getInstance(farmAnimalsConfig);\n        Realm exoticRealm = Realm.getInstance(exoticAnimalsConfig);\n\n        // Objects can be added to each Realm independantly\n        showStatus(\"Create objects in the default Realm\");\n        defaultRealm.executeTransaction(new Realm.Transaction() {\n            @Override\n            public void execute(Realm realm) {\n                realm.createObject(Cow.class);\n                realm.createObject(Pig.class);\n                realm.createObject(Snake.class);\n                realm.createObject(Spider.class);\n            }\n        });\n\n        showStatus(\"Create objects in the farm Realm\");\n        farmRealm.executeTransaction(new Realm.Transaction() {\n            @Override\n            public void execute(Realm realm) {\n                realm.createObject(Cow.class);\n                realm.createObject(Pig.class);\n                realm.createObject(Cat.class);\n                realm.createObject(Dog.class);\n            }\n        });\n\n        showStatus(\"Create objects in the exotic Realm\");\n        exoticRealm.executeTransaction(new Realm.Transaction() {\n            @Override\n            public void execute(Realm realm) {\n                realm.createObject(Elephant.class);\n                realm.createObject(Lion.class);\n                realm.createObject(Zebra.class);\n                realm.createObject(Snake.class);\n                realm.createObject(Spider.class);\n            }\n        });\n\n        // You can copy objects between Realms\n        showStatus(\"Copy objects between Realms\");\n        showStatus(\"Number of pigs on the farm : \" + farmRealm.where(Pig.class).count());\n        showStatus(\"Copy pig from defaultRealm to farmRealm\");\n        final Pig defaultPig = defaultRealm.where(Pig.class).findFirst();\n        farmRealm.executeTransaction(new Realm.Transaction() {\n            @Override\n            public void execute(Realm realm) {\n                realm.copyToRealm(defaultPig);\n            }\n        });\n\n        showStatus(\"Number of unnamed pigs on the farm : \" + farmRealm.where(Pig.class).isNull(\"name\").count());\n\n        // Each Realm is restricted to only accept the classes in their schema.\n        showStatus(\"Trying to add an unsupported class\");\n        defaultRealm.beginTransaction();\n        try {\n            defaultRealm.createObject(Elephant.class);\n        } catch (RealmException expected) {\n            showStatus(\"This throws a :\" + expected.toString());\n        } finally {\n            defaultRealm.cancelTransaction();\n        }\n\n        // And Realms in library projects are independent from Realms in the app code\n        showStatus(\"Interacting with library code that uses Realm internally\");\n        int animals = 5;\n        Zoo libraryZoo = new Zoo();\n        libraryZoo.open();\n        showStatus(\"Adding animals: \" + animals);\n        libraryZoo.addAnimals(5);\n        showStatus(\"Number of animals in the library Realm:\" + libraryZoo.getNoOfAnimals());\n        libraryZoo.close();\n\n        // Remember to close all open Realms\n        defaultRealm.close();\n        farmRealm.close();\n        exoticRealm.close();\n    }\n\n    private void showStatus(String txt) {\n        Log.i(TAG, txt);\n        TextView tv = new TextView(this);\n        tv.setText(txt);\n        rootLayout.addView(tv);\n    }\n}\n"
  },
  {
    "path": "examples/moduleExample/app/src/main/java/io/realm/examples/appmodules/MyApplication.java",
    "content": "/*\n * Copyright 2016 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\npackage io.realm.examples.appmodules;\n\nimport android.app.Application;\n\nimport io.realm.Realm;\n\npublic class MyApplication extends Application {\n\n    @Override\n    public void onCreate() {\n        super.onCreate();\n        Realm.init(this);\n    }\n}\n"
  },
  {
    "path": "examples/moduleExample/app/src/main/java/io/realm/examples/appmodules/model/Cow.java",
    "content": "/*\n * Copyright 2015 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\npackage io.realm.examples.appmodules.model;\n\nimport io.realm.RealmObject;\n\npublic class Cow extends RealmObject {\n\n    private String name;\n\n    public String getName() {\n        return name;\n    }\n\n    public void setName(String name) {\n        this.name = name;\n    }\n}\n"
  },
  {
    "path": "examples/moduleExample/app/src/main/java/io/realm/examples/appmodules/model/CrossModuleLinks.java",
    "content": "package io.realm.examples.appmodules.model;\n\nimport io.realm.RealmDictionary;\nimport io.realm.RealmList;\nimport io.realm.RealmObject;\nimport io.realm.RealmSet;\nimport io.realm.examples.librarymodules.model.Cat;\nimport io.realm.examples.librarymodules.model.EmbeddedAnimal;\n\n// Not used by the app, but merely acts as sanity checks that we can make cross module references,\n// and generate valid code for it.\npublic class CrossModuleLinks extends RealmObject {\n    public EmbeddedAnimal embeded;\n    public Cat link;\n    public RealmList<Cat> list;\n    public RealmSet<Cat> set;\n    public RealmDictionary<Cat> dictionary;\n}\n"
  },
  {
    "path": "examples/moduleExample/app/src/main/java/io/realm/examples/appmodules/model/Pig.java",
    "content": "/*\n * Copyright 2015 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\npackage io.realm.examples.appmodules.model;\n\nimport io.realm.RealmObject;\n\npublic class Pig extends RealmObject {\n\n    private String name;\n\n    public String getName() {\n        return name;\n    }\n\n    public void setName(String name) {\n        this.name = name;\n    }\n}\n"
  },
  {
    "path": "examples/moduleExample/app/src/main/java/io/realm/examples/appmodules/model/Snake.java",
    "content": "/*\n * Copyright 2015 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\npackage io.realm.examples.appmodules.model;\n\nimport io.realm.RealmObject;\n\npublic class Snake extends RealmObject {\n\n    private String name;\n\n    public String getName() {\n        return name;\n    }\n\n    public void setName(String name) {\n        this.name = name;\n    }\n\n}\n"
  },
  {
    "path": "examples/moduleExample/app/src/main/java/io/realm/examples/appmodules/model/Spider.java",
    "content": "/*\n * Copyright 2015 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\npackage io.realm.examples.appmodules.model;\n\nimport io.realm.RealmObject;\n\npublic class Spider extends RealmObject {\n\n    private String name;\n\n    public String getName() {\n        return name;\n    }\n\n    public void setName(String name) {\n        this.name = name;\n    }\n\n}\n"
  },
  {
    "path": "examples/moduleExample/app/src/main/java/io/realm/examples/appmodules/modules/CreepyAnimalsModule.java",
    "content": "/*\n * Copyright 2015 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\npackage io.realm.examples.appmodules.modules;\n\nimport io.realm.annotations.RealmModule;\nimport io.realm.examples.appmodules.model.Snake;\nimport io.realm.examples.appmodules.model.Spider;\n\n@RealmModule(classes = {Snake.class, Spider.class})\npublic class CreepyAnimalsModule {\n}\n"
  },
  {
    "path": "examples/moduleExample/app/src/main/res/layout/activity_modules_example.xml",
    "content": "<ScrollView\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:paddingLeft=\"@dimen/activity_horizontal_margin\"\n    android:paddingRight=\"@dimen/activity_horizontal_margin\"\n    android:paddingTop=\"@dimen/activity_vertical_margin\"\n    android:paddingBottom=\"@dimen/activity_vertical_margin\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\">\n    <LinearLayout\n        android:orientation=\"vertical\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\">\n        <TextView\n            android:gravity=\"center_horizontal\"\n            android:text=\"@string/status_output\"\n            android:textStyle=\"bold\"\n            android:textSize=\"18sp\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"wrap_content\"/>\n        <LinearLayout\n            android:id=\"@+id/container\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"match_parent\"\n            android:paddingTop=\"10sp\"\n            android:orientation=\"vertical\"\n            tools:context=\".RealmIntroExample\"/>\n    </LinearLayout>\n</ScrollView>\n"
  },
  {
    "path": "examples/moduleExample/app/src/main/res/values/dimens.xml",
    "content": "<resources>\n    <!-- Default screen margins, per the Android Design guidelines. -->\n    <dimen name=\"activity_horizontal_margin\">16dp</dimen>\n    <dimen name=\"activity_vertical_margin\">16dp</dimen>\n</resources>\n"
  },
  {
    "path": "examples/moduleExample/app/src/main/res/values/strings.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n\n    <string name=\"app_name\">RealmModule example</string>\n    <string name=\"status_output\">Status Output…</string>\n\n</resources>\n"
  },
  {
    "path": "examples/moduleExample/app/src/main/res/values/styles.xml",
    "content": "<resources>\n\n    <!-- Base application theme. -->\n    <style name=\"AppTheme\" parent=\"android:Theme.Holo.Light.DarkActionBar\">\n        <!-- Customize your theme here. -->\n    </style>\n\n</resources>\n"
  },
  {
    "path": "examples/moduleExample/app/src/main/res/values-w820dp/dimens.xml",
    "content": "<resources>\n    <!-- Example customization of dimensions originally defined in res/values/dimens.xml\n         (such as screen margins) for screens with more than 820dp of available width. This\n         would include 7\" and 10\" devices in landscape (~960dp and ~1280dp respectively). -->\n    <dimen name=\"activity_horizontal_margin\">64dp</dimen>\n</resources>\n"
  },
  {
    "path": "examples/moduleExample/library/build.gradle",
    "content": "apply plugin: 'com.android.library'\napply plugin: 'realm-android'\n\nandroid {\n    compileSdkVersion rootProject.sdkVersion\n    buildToolsVersion rootProject.buildTools\n\n    defaultConfig {\n        targetSdkVersion rootProject.sdkVersion\n        minSdkVersion rootProject.minSdkVersion\n        versionCode 1\n        versionName \"1.0\"\n    }\n\n    buildTypes {\n        release {\n            minifyEnabled false\n        }\n    }\n}\n"
  },
  {
    "path": "examples/moduleExample/library/lint.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<lint>\n    <!-- Disable the given check in this project -->\n    <issue id=\"AllowBackup\" severity=\"ignore\" />\n    <issue id=\"IconLauncherShape\" severity=\"ignore\" />\n    <issue id=\"IconMissingDensityFolder\" severity=\"ignore\" />\n    <issue id=\"GoogleAppIndexingWarning\" severity=\"ignore\" />\n    <issue id=\"InvalidPackage\" severity=\"ignore\" />\n</lint>\n"
  },
  {
    "path": "examples/moduleExample/library/src/main/AndroidManifest.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    package=\"io.realm.examples.librarymodules\" >\n\n    <application\n        android:label=\"@string/app_name\" >\n    </application>\n\n</manifest>\n"
  },
  {
    "path": "examples/moduleExample/library/src/main/java/io/realm/examples/librarymodules/Zoo.java",
    "content": "/*\n * Copyright 2015 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\npackage io.realm.examples.librarymodules;\n\nimport android.content.Context;\n\nimport io.realm.Realm;\nimport io.realm.RealmConfiguration;\nimport io.realm.examples.librarymodules.model.Cat;\nimport io.realm.examples.librarymodules.modules.AllAnimalsModule;\n\n/**\n * Library projects can also use Realms, but some configuration options are mandatory to avoid clashing with Realms used\n * in the app code.\n */\npublic class Zoo {\n\n    private final RealmConfiguration realmConfig;\n    private Realm realm;\n\n    public Zoo() {\n        realmConfig = new RealmConfiguration.Builder()     // The app is responsible for calling `Realm.init(Context)`\n                .name(\"library.zoo.realm\")                 // So always use a unique name\n                .allowQueriesOnUiThread(true)\n                .allowWritesOnUiThread(true)\n                .modules(new AllAnimalsModule())\n                // Always use explicit modules in library projects\n                .build();\n\n        // Reset Realm\n        Realm.deleteRealm(realmConfig);\n    }\n\n    public void open() {\n        // Don't use Realm.setDefaultInstance() in library projects. It is unsafe as app developers can override the\n        // default configuration. So always use explicit configurations in library projects.\n        realm = Realm.getInstance(realmConfig);\n    }\n\n    public long getNoOfAnimals() {\n        return realm.where(Cat.class).count();\n    }\n\n    public void addAnimals(final int count) {\n        realm.executeTransaction(new Realm.Transaction() {\n            @Override\n            public void execute(Realm realm) {\n                for (int i = 0; i < count; i++) {\n                    Cat cat = realm.createObject(Cat.class);\n                    cat.setName(\"Cat \" + i);\n                }\n            }\n        });\n    }\n\n    public void close() {\n        realm.close();\n    }\n}\n"
  },
  {
    "path": "examples/moduleExample/library/src/main/java/io/realm/examples/librarymodules/model/Cat.java",
    "content": "/*\n * Copyright 2015 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\npackage io.realm.examples.librarymodules.model;\n\nimport io.realm.RealmObject;\n\npublic class Cat extends RealmObject {\n\n    private String name;\n\n    public String getName() {\n        return name;\n    }\n\n    public void setName(String name) {\n        this.name = name;\n    }\n}\n"
  },
  {
    "path": "examples/moduleExample/library/src/main/java/io/realm/examples/librarymodules/model/Dog.java",
    "content": "/*\n * Copyright 2015 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\npackage io.realm.examples.librarymodules.model;\n\nimport io.realm.RealmObject;\n\npublic class Dog extends RealmObject {\n\n    private String name;\n\n    public String getName() {\n        return name;\n    }\n\n    public void setName(String name) {\n        this.name = name;\n    }\n}\n"
  },
  {
    "path": "examples/moduleExample/library/src/main/java/io/realm/examples/librarymodules/model/Elephant.java",
    "content": "/*\n * Copyright 2015 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\npackage io.realm.examples.librarymodules.model;\n\nimport io.realm.RealmObject;\n\npublic class Elephant extends RealmObject {\n\n    private String name;\n\n    public String getName() {\n        return name;\n    }\n\n    public void setName(String name) {\n        this.name = name;\n    }\n}\n"
  },
  {
    "path": "examples/moduleExample/library/src/main/java/io/realm/examples/librarymodules/model/EmbeddedAnimal.java",
    "content": "package io.realm.examples.librarymodules.model;\n\nimport io.realm.RealmObject;\nimport io.realm.annotations.RealmClass;\n\n// Not used by the app, but merely acts as sanity checks that we can make cross module references,\n// and generate valid code for it.\n@RealmClass(embedded = true)\npublic class EmbeddedAnimal extends RealmObject {\n    public String name;\n}\n"
  },
  {
    "path": "examples/moduleExample/library/src/main/java/io/realm/examples/librarymodules/model/Lion.java",
    "content": "/*\n * Copyright 2015 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\npackage io.realm.examples.librarymodules.model;\n\nimport io.realm.RealmObject;\n\npublic class Lion extends RealmObject {\n\n    private String name;\n\n    public String getName() {\n        return name;\n    }\n\n    public void setName(String name) {\n        this.name = name;\n    }\n}\n"
  },
  {
    "path": "examples/moduleExample/library/src/main/java/io/realm/examples/librarymodules/model/Zebra.java",
    "content": "/*\n * Copyright 2015 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\npackage io.realm.examples.librarymodules.model;\n\nimport io.realm.RealmObject;\n\npublic class Zebra extends RealmObject {\n\n    private String name;\n\n    public String getName() {\n        return name;\n    }\n\n    public void setName(String name) {\n        this.name = name;\n    }\n}\n"
  },
  {
    "path": "examples/moduleExample/library/src/main/java/io/realm/examples/librarymodules/modules/AllAnimalsModule.java",
    "content": "/*\n * Copyright 2015 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\npackage io.realm.examples.librarymodules.modules;\n\nimport io.realm.annotations.RealmModule;\n\n@RealmModule(library = true, allClasses = true)\npublic class AllAnimalsModule {\n}\n"
  },
  {
    "path": "examples/moduleExample/library/src/main/java/io/realm/examples/librarymodules/modules/DomesticAnimalsModule.java",
    "content": "/*\n * Copyright 2015 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\npackage io.realm.examples.librarymodules.modules;\n\nimport io.realm.annotations.RealmModule;\nimport io.realm.examples.librarymodules.model.Cat;\nimport io.realm.examples.librarymodules.model.Dog;\n\n@RealmModule(library = true, classes = {Cat.class, Dog.class})\npublic class DomesticAnimalsModule {\n}\n"
  },
  {
    "path": "examples/moduleExample/library/src/main/java/io/realm/examples/librarymodules/modules/ZooAnimalsModule.java",
    "content": "/*\n * Copyright 2015 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\npackage io.realm.examples.librarymodules.modules;\n\nimport io.realm.annotations.RealmModule;\nimport io.realm.examples.librarymodules.model.Elephant;\nimport io.realm.examples.librarymodules.model.Lion;\nimport io.realm.examples.librarymodules.model.Zebra;\n\n@RealmModule(library = true, classes = {Elephant.class, Lion.class, Zebra.class})\npublic class ZooAnimalsModule {\n}\n"
  },
  {
    "path": "examples/moduleExample/library/src/main/res/values/strings.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n\n    <string name=\"app_name\">RealmModule Library Example</string>\n\n</resources>\n"
  },
  {
    "path": "examples/mongoDbRealmExample/README.md",
    "content": "# Using this example\n\nThis example is a minimal demonstration of how to connect to and use the\nRealm Object Server to synchronize changes between devices.\n\nThe example assumes that the Object Server is running on the machine\nthat built the application: The build machine IP address is automatically\ninjected into the build configuration.\n\nTo use a different ObjectServer, simply put the server IP Address into\nthe `build.gradle`, as indicated in the comments, on the lines like this:\n\n    def rosUrl = \"<INSERT_REALM_OBJECT_SERVER_URL>\"\n\nFor instance:\n\n    def rosUrl = \"https://myinstance.us1.cloud.realm.io\"\n\nor:\n\n    def rosUrl = \"http://127.0.0.1:9080\"\n\nTo read more about the Realm Object Server and how to deploy it, see\nhttps://realm.io/news/introducing-realm-mobile-platform/\n"
  },
  {
    "path": "examples/mongoDbRealmExample/build.gradle",
    "content": "apply plugin: 'com.android.application'\napply plugin: 'kotlin-android'\napply plugin: 'kotlin-kapt'\napply plugin: 'kotlin-android-extensions'\napply plugin: 'realm-android'\n\nandroid {\n    // androidx.lifecycle dependencies requires Android APIs 31 or later\n    compileSdkVersion 31\n    buildToolsVersion rootProject.buildTools\n\n    defaultConfig {\n        applicationId 'com.mongodb.realm.example'\n        targetSdkVersion rootProject.sdkVersion\n        minSdkVersion rootProject.minSdkVersion\n        versionCode 1\n        versionName \"1.0\"\n    }\n\n    dataBinding {\n        enabled = true\n    }\n\n    buildTypes {\n        // Configure server and App Id.\n        // The default server is https://realm-dev.mongodb.com/ . Go to that and copy the MongoDB\n        // Realm App Id.\n        //\n        // If you are running a local version of MongoDB Realm, modify endpoint accordingly. Most\n        // likely it is \"http://localhost:9090\"\n        def mongodbRealmUrl = \"https://realm-dev.mongodb.com\"\n        def appId = \"my-app-id\"\n        debug {\n            buildConfigField \"String\", \"MONGODB_REALM_URL\", \"\\\"${mongodbRealmUrl}\\\"\"\n            buildConfigField \"String\", \"MONGODB_REALM_APP_ID\", \"\\\"${appId}\\\"\"\n            minifyEnabled true\n        }\n        release {\n            buildConfigField \"String\", \"MONGODB_REALM_URL\", \"\\\"${mongodbRealmUrl}\\\"\"\n            buildConfigField \"String\", \"MONGODB_REALM_APP_ID\", \"\\\"${appId}\\\"\"\n            minifyEnabled true\n            signingConfig signingConfigs.debug\n        }\n    }\n\n    compileOptions {\n        sourceCompatibility 1.8\n        targetCompatibility 1.8\n    }\n}\n\nrealm {\n    syncEnabled = true\n}\n\ndependencies {\n    implementation 'androidx.appcompat:appcompat:1.4.2'\n    implementation 'com.google.android.material:material:1.6.1'\n    implementation 'me.zhanghai.android.materialprogressbar:library:1.6.1'\n    implementation \"org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version\"\n}\n"
  },
  {
    "path": "examples/mongoDbRealmExample/gradle.properties",
    "content": "# FIXME: Required as long as we depend on PlayServices for RemoteMongDB API's\nandroid.useAndroidX=true\n"
  },
  {
    "path": "examples/mongoDbRealmExample/lint.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<lint>\n    <!-- Disable the given check in this project -->\n    <issue id=\"AllowBackup\" severity=\"ignore\" />\n    <issue id=\"IconLauncherShape\" severity=\"ignore\" />\n    <issue id=\"IconMissingDensityFolder\" severity=\"ignore\" />\n    <issue id=\"GoogleAppIndexingWarning\" severity=\"ignore\" />\n    <issue id=\"InvalidPackage\" severity=\"ignore\" />\n</lint>\n"
  },
  {
    "path": "examples/mongoDbRealmExample/src/main/AndroidManifest.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    package=\"com.mongodb.realm.example\">\n\n    <application\n        android:name=\".MyApplication\"\n        android:icon=\"@mipmap/ic_launcher\"\n        android:label=\"@string/app_name\"\n        android:theme=\"@style/AppTheme\">\n        <activity\n            android:name=\".CounterActivity\"\n            android:label=\"@string/app_name\">\n            <intent-filter>\n                <action android:name=\"android.intent.action.MAIN\" />\n                <category android:name=\"android.intent.category.LAUNCHER\" />\n            </intent-filter>\n        </activity>\n        <activity\n            android:name=\".LoginActivity\"\n            android:label=\"Login\"></activity>\n    </application>\n\n</manifest>\n"
  },
  {
    "path": "examples/mongoDbRealmExample/src/main/java/com/mongodb/realm/example/CounterActivity.kt",
    "content": "/*\n * Copyright 2019 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\npackage com.mongodb.realm.example\n\nimport android.content.Intent\nimport android.graphics.PorterDuff\nimport android.os.Bundle\nimport android.view.Menu\nimport android.view.MenuItem\nimport android.view.View\nimport android.widget.TextView\nimport androidx.appcompat.app.AppCompatActivity\nimport androidx.databinding.DataBindingUtil\nimport io.realm.*\nimport com.mongodb.realm.example.model.CRDTCounter\nimport com.mongodb.realm.example.databinding.ActivityCounterBinding\nimport io.realm.kotlin.syncSession\nimport io.realm.kotlin.where\nimport io.realm.log.RealmLog\nimport io.realm.mongodb.User\nimport io.realm.mongodb.sync.ProgressListener\nimport io.realm.mongodb.sync.ProgressMode\nimport io.realm.mongodb.sync.SyncConfiguration\nimport io.realm.mongodb.sync.SyncSession\nimport me.zhanghai.android.materialprogressbar.MaterialProgressBar\nimport java.util.*\nimport java.util.concurrent.atomic.AtomicBoolean\n\nclass CounterActivity : AppCompatActivity() {\n\n    private lateinit var binding: ActivityCounterBinding\n\n    private val downloadListener = ProgressListener { progress ->\n        downloadingChanges.set(!progress.isTransferComplete)\n        runOnUiThread(updateProgressBar)\n    }\n    private val uploadListener = ProgressListener { progress ->\n        uploadingChanges.set(!progress.isTransferComplete)\n        runOnUiThread(updateProgressBar)\n    }\n    private val updateProgressBar = Runnable { updateProgressBar(downloadingChanges.get(), uploadingChanges.get()) }\n\n    private val downloadingChanges = AtomicBoolean(false)\n    private val uploadingChanges = AtomicBoolean(false)\n\n    private var realm: Realm? = null\n    private lateinit var session: SyncSession\n    private var user: User? = null\n\n    private lateinit var counterView: TextView\n    private lateinit var progressBar: MaterialProgressBar\n    private lateinit var counter: CRDTCounter // Keep strong reference to counter to keep change listeners alive.\n\n    private val loggedInUser: User?\n        get() {\n            var user: User? = null\n\n            try {\n                user = APP.currentUser()\n            } catch (e: IllegalStateException) {\n                RealmLog.warn(e);\n            }\n\n            if (user == null) {\n                startActivity(Intent(this, LoginActivity::class.java))\n            }\n\n            return user\n        }\n\n\n    override fun onCreate(savedInstanceState: Bundle?) {\n        super.onCreate(savedInstanceState)\n        binding = DataBindingUtil.setContentView(this, R.layout.activity_counter)\n        counterView = binding.textCounter\n        progressBar = binding.progressbar\n        binding.upper.setOnClickListener { adjustCounter(1) }\n        binding.lower.setOnClickListener { adjustCounter(-1) }\n    }\n\n    override fun onStart() {\n        super.onStart()\n        user = loggedInUser\n        val user = user\n        if (user != null) {\n            // Create a RealmConfiguration for our user\n            // Use user id as partition value, so each user gets an unique view.\n            // FIXME Right now we are using waitForInitialRemoteData and a more advanced\n            // initialData block due to Sync only supporting ObjectId keys. This should\n            // be changed once natural keys are supported.\n            val config = SyncConfiguration.Builder(user, user.id)\n                    .initialData {\n                        if (it.isEmpty) {\n                            it.insert(CRDTCounter())\n                        }\n                    }\n                    .waitForInitialRemoteData()\n                    .build()\n\n            // This will automatically sync all changes in the background for as long as the Realm is open\n            Realm.getInstanceAsync(config, object: Realm.Callback() {\n                override fun onSuccess(realm: Realm) {\n                    this@CounterActivity.realm = realm\n\n                    counter = realm.where<CRDTCounter>().findFirstAsync()\n                    counter.addChangeListener<CRDTCounter> { obj, _ ->\n                        if (obj.isValid) {\n                            counterView.text = String.format(Locale.US, \"%d\", counter.count)\n                        } else {\n                            counterView.text = \"-\"\n                        }\n                    }\n\n                    // Setup progress listeners for indeterminate progress bars\n                    session = realm.syncSession\n                    session.run {\n                        addDownloadProgressListener(ProgressMode.INDEFINITELY, downloadListener)\n                        addUploadProgressListener(ProgressMode.INDEFINITELY, uploadListener)\n                    }\n                }\n            })\n            counterView.text = \"-\"\n        }\n    }\n\n    override fun onStop() {\n        super.onStop()\n        user?.run {\n            session.run {\n                removeProgressListener(downloadListener)\n                removeProgressListener(uploadListener)\n            }\n            realm?.close()\n        }\n    }\n\n    override fun onCreateOptionsMenu(menu: Menu): Boolean {\n        menuInflater.inflate(R.menu.menu_counter, menu)\n        return true\n    }\n\n    override fun onOptionsItemSelected(item: MenuItem): Boolean {\n        return when (item.itemId) {\n            R.id.action_logout -> {\n                val user = user\n                user?.logOutAsync {\n                    if (it.isSuccess) {\n                        realm?.close()\n                        this.user = loggedInUser\n                    } else {\n                        RealmLog.error(it.error.toString())\n                    }\n                }\n                true\n            }\n            else -> super.onOptionsItemSelected(item)\n        }\n    }\n\n    private fun updateProgressBar(downloading: Boolean, uploading: Boolean) {\n        val color = when {\n            downloading && uploading -> R.color.progress_both\n            downloading -> R.color.progress_download\n            uploading -> R.color.progress_upload\n            else -> android.R.color.black\n        }\n        progressBar.indeterminateDrawable.setColorFilter(resources.getColor(color), PorterDuff.Mode.SRC_IN)\n        progressBar.visibility = if (color == android.R.color.black) View.GONE else View.VISIBLE\n    }\n\n    private fun adjustCounter(adjustment: Int) {\n        // A synchronized Realm can get written to at any point in time, so doing synchronous writes on the UI\n        // thread is HIGHLY discouraged as it might block longer than intended. Use only async transactions.\n        realm?.executeTransactionAsync { realm ->\n            val counter = realm.where<CRDTCounter>().findFirst()\n            counter?.incrementCounter(adjustment.toLong())\n        }\n    }\n\n}\n"
  },
  {
    "path": "examples/mongoDbRealmExample/src/main/java/com/mongodb/realm/example/LoginActivity.kt",
    "content": "/*\n * Copyright 2019 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\npackage com.mongodb.realm.example\n\nimport android.app.ProgressDialog\nimport android.os.Bundle\nimport android.widget.Button\nimport android.widget.EditText\nimport android.widget.Toast\nimport androidx.appcompat.app.AppCompatActivity\nimport androidx.databinding.DataBindingUtil\nimport com.mongodb.realm.example.databinding.ActivityLoginBinding\nimport io.realm.*\nimport io.realm.log.RealmLog\nimport io.realm.mongodb.Credentials\n\nclass LoginActivity : AppCompatActivity() {\n\n    private lateinit var username: EditText\n    private lateinit var password: EditText\n    private lateinit var loginButton: Button\n    private lateinit var createUserButton: Button\n\n    lateinit private var binding: ActivityLoginBinding\n\n    public override fun onCreate(savedInstanceState: Bundle?) {\n        super.onCreate(savedInstanceState)\n        binding = DataBindingUtil.setContentView(this, R.layout.activity_login)\n        username = binding.inputUsername\n        password = binding.inputPassword\n        loginButton = binding.buttonLogin\n        createUserButton = binding.buttonCreate\n\n        loginButton.setOnClickListener { login(false) }\n        createUserButton.setOnClickListener { login(true) }\n    }\n\n    private fun login(createUser: Boolean) {\n        if (!validate()) {\n            onLoginFailed(\"Invalid username or password\")\n            return\n        }\n\n        binding.buttonCreate.isEnabled = false\n        binding.buttonLogin.isEnabled = false\n\n        val progressDialog = ProgressDialog(this@LoginActivity)\n        progressDialog.isIndeterminate = true\n        progressDialog.setMessage(\"Authenticating...\")\n        progressDialog.show()\n\n        val username = this.username.text.toString()\n        val password = this.password.text.toString()\n\n\n        if (createUser) {\n            APP.emailPassword.registerUserAsync(username, password) {\n                progressDialog.dismiss()\n                binding.buttonCreate.isEnabled = true\n                binding.buttonLogin.isEnabled = true\n                if (!it.isSuccess) {\n                    onLoginFailed(\"Could not register user. Check Logcat\")\n                }\n            }\n        } else {\n            val creds = Credentials.emailPassword(username, password)\n            APP.loginAsync(creds) {\n                progressDialog.dismiss()\n                if (!it.isSuccess) {\n                    RealmLog.error(it.error.toString())\n                    onLoginFailed(it.error.message ?: \"An error occurred. Check Logcat\")\n                } else {\n                    onLoginSuccess()\n                }\n            }\n        }\n    }\n\n    override fun onBackPressed() {\n        // Disable going back to the MainActivity\n        moveTaskToBack(true)\n    }\n\n    private fun onLoginSuccess() {\n        loginButton.isEnabled = true\n        createUserButton.isEnabled = true\n        finish()\n    }\n\n    private fun onLoginFailed(errorMsg: String) {\n        loginButton.isEnabled = true\n        createUserButton.isEnabled = true\n        Toast.makeText(baseContext, errorMsg, Toast.LENGTH_LONG).show()\n    }\n\n    private fun validate(): Boolean = when {\n        username.text.toString().isEmpty() -> false\n        password.text.toString().isEmpty() -> false\n        else -> true\n    }\n}\n"
  },
  {
    "path": "examples/mongoDbRealmExample/src/main/java/com/mongodb/realm/example/MyApplication.kt",
    "content": "/*\n * Copyright 2019 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\npackage com.mongodb.realm.example\n\nimport android.app.Application\n\nimport io.realm.Realm\nimport io.realm.log.LogLevel\nimport io.realm.log.RealmLog\nimport io.realm.mongodb.App\nimport io.realm.mongodb.AppConfiguration\n\nlateinit var APP: App\n\nclass MyApplication : Application() {\n\n    override fun onCreate() {\n        super.onCreate()\n        Realm.init(this)\n        APP = App(AppConfiguration.Builder(BuildConfig.MONGODB_REALM_APP_ID)\n                .baseUrl(BuildConfig.MONGODB_REALM_URL)\n                .appName(BuildConfig.VERSION_NAME)\n                .appVersion(BuildConfig.VERSION_CODE.toString())\n                .build())\n\n        // Enable more logging in debug mode\n        if (BuildConfig.DEBUG) {\n            RealmLog.setLevel(LogLevel.DEBUG)\n        }\n    }\n}\n"
  },
  {
    "path": "examples/mongoDbRealmExample/src/main/java/com/mongodb/realm/example/model/CRDTCounter.kt",
    "content": "/*\n * Copyright 2019 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 */\npackage com.mongodb.realm.example.model\n\nimport io.realm.MutableRealmInteger\nimport io.realm.RealmObject\nimport io.realm.annotations.PrimaryKey\nimport io.realm.annotations.RealmField\nimport io.realm.annotations.Required\nimport org.bson.types.ObjectId\n\nopen class CRDTCounter : RealmObject() {\n\n    @PrimaryKey\n    @RealmField(\"_id\")\n    var id: ObjectId = ObjectId.get()\n    @Required\n    private val counter: MutableRealmInteger = MutableRealmInteger.valueOf(0L)\n\n    val count: Long\n        get() = this.counter.get()!!.toLong()\n\n    fun incrementCounter(delta: Long) {\n        counter.increment(delta)\n    }\n\n}\n"
  },
  {
    "path": "examples/mongoDbRealmExample/src/main/res/drawable/button_counter.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<selector xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <item android:drawable=\"@color/touch_area_pressed\" android:state_pressed=\"true\"/>\n    <item android:drawable=\"@color/touch_area_pressed\" android:state_focused=\"true\"/>\n    <item android:drawable=\"@android:color/background_light\"/>\n</selector>\n"
  },
  {
    "path": "examples/mongoDbRealmExample/src/main/res/layout/activity_counter.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<layout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\">\n\n    <data />\n\n    <RelativeLayout\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\">\n\n        <LinearLayout\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"match_parent\"\n            android:orientation=\"vertical\">\n\n            <View\n                android:id=\"@+id/upper\"\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"0dp\"\n                android:layout_weight=\"1\"\n                android:background=\"@drawable/button_counter\" />\n\n            <View\n                android:id=\"@+id/lower\"\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"0dp\"\n                android:layout_weight=\"1\"\n                android:background=\"@drawable/button_counter\" />\n        </LinearLayout>\n\n        <TextView\n            android:id=\"@+id/text_counter\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:layout_centerInParent=\"true\"\n            android:textSize=\"160sp\"\n            app:fontFamily=\"sans-serif-light\" />\n\n        <me.zhanghai.android.materialprogressbar.MaterialProgressBar\n            android:id=\"@+id/progressbar\"\n            style=\"@style/Widget.MaterialProgressBar.ProgressBar.Horizontal.NoPadding\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"wrap_content\"\n            android:layout_gravity=\"top\"\n            android:indeterminate=\"true\"\n            android:visibility=\"visible\"\n            app:mpb_progressStyle=\"horizontal\" />\n\n    </RelativeLayout>\n</layout>\n\n"
  },
  {
    "path": "examples/mongoDbRealmExample/src/main/res/layout/activity_login.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<layout xmlns:android=\"http://schemas.android.com/apk/res/android\">\n\n    <data />\n\n    <ScrollView\n        android:layout_width=\"fill_parent\"\n        android:layout_height=\"fill_parent\"\n        android:fitsSystemWindows=\"true\">\n\n        <LinearLayout\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"wrap_content\"\n            android:orientation=\"vertical\"\n            android:paddingLeft=\"24dp\"\n            android:paddingTop=\"56dp\"\n            android:paddingRight=\"24dp\">\n\n            <ImageView\n                android:layout_width=\"wrap_content\"\n                android:layout_height=\"72dp\"\n                android:layout_gravity=\"center_horizontal\"\n                android:layout_marginBottom=\"24dp\"\n                android:contentDescription=\"@string/realm_logo\"\n                android:src=\"@drawable/logo\" />\n\n            <com.google.android.material.textfield.TextInputLayout\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"wrap_content\"\n                android:layout_marginTop=\"8dp\"\n                android:layout_marginBottom=\"8dp\">\n\n                <EditText\n                    android:id=\"@+id/input_username\"\n                    android:layout_width=\"match_parent\"\n                    android:layout_height=\"wrap_content\"\n                    android:hint=\"@string/username\"\n                    android:inputType=\"text\" />\n            </com.google.android.material.textfield.TextInputLayout>\n\n            <com.google.android.material.textfield.TextInputLayout\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"wrap_content\"\n                android:layout_marginTop=\"8dp\"\n                android:layout_marginBottom=\"8dp\">\n\n                <EditText\n                    android:id=\"@+id/input_password\"\n                    android:layout_width=\"match_parent\"\n                    android:layout_height=\"wrap_content\"\n                    android:hint=\"@string/password\"\n                    android:inputType=\"textPassword\" />\n            </com.google.android.material.textfield.TextInputLayout>\n\n            <androidx.appcompat.widget.AppCompatButton\n                android:id=\"@+id/button_login\"\n                android:layout_width=\"fill_parent\"\n                android:layout_height=\"wrap_content\"\n                android:layout_marginTop=\"24dp\"\n                android:layout_marginBottom=\"12dp\"\n                android:padding=\"12dp\"\n                android:text=\"@string/login\" />\n\n            <androidx.appcompat.widget.AppCompatButton\n                android:id=\"@+id/button_create\"\n                android:layout_width=\"fill_parent\"\n                android:layout_height=\"wrap_content\"\n                android:layout_marginBottom=\"24dp\"\n                android:padding=\"12dp\"\n                android:text=\"@string/create_account\" />\n        </LinearLayout>\n    </ScrollView>\n\n</layout>\n\n"
  },
  {
    "path": "examples/mongoDbRealmExample/src/main/res/menu/menu_counter.xml",
    "content": "<menu xmlns:android=\"http://schemas.android.com/apk/res/android\"\n      xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n      xmlns:tools=\"http://schemas.android.com/tools\"\n      tools:context=\"com.mongodb.realm.example.CounterActivity\">\n    <item\n        android:id=\"@+id/action_logout\"\n        android:orderInCategory=\"100\"\n        android:title=\"@string/logout\"\n        android:icon=\"@drawable/ic_exit_to_app_white_24dp\"\n        app:showAsAction=\"always\"/>\n</menu>\n"
  },
  {
    "path": "examples/mongoDbRealmExample/src/main/res/values/dimens.xml",
    "content": "<resources>\n    <!-- Default screen margins, per the Android Design guidelines. -->\n    <dimen name=\"activity_horizontal_margin\">16dp</dimen>\n    <dimen name=\"activity_vertical_margin\">16dp</dimen>\n</resources>\n"
  },
  {
    "path": "examples/mongoDbRealmExample/src/main/res/values/realm_colors.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <!-- Grays -->\n    <color name=\"charcoal\">#1C233F</color>\n    <color name=\"elephant\">#9A9BA5</color>\n    <color name=\"elephant_half\">#b1b3bf</color>\n    <color name=\"dove\">#EBEBF2</color>\n\n    <!-- Orb colors -->\n    <color name=\"ultramarine\">#39477F</color>\n    <color name=\"indigo\">#59569E</color>\n    <color name=\"grape_jelly\">#9A59A5</color>\n    <color name=\"mulberry\">#D34CA3</color>\n    <color name=\"flamingo\">#F25192</color>\n    <color name=\"sexy_salmon\">#F77C88</color>\n    <color name=\"peach\">#FC9F95</color>\n    <color name=\"melon\">#FCC397</color>\n\n    <!-- Material adjustments -->\n    <color name=\"flamingo_darker\">#d64881</color>\n    <color name=\"touch_area_pressed\">#dadada</color>\n\n    <!-- Progress bar colors -->\n    <color name=\"progress_upload\">#EF5350</color>\n    <color name=\"progress_download\">#9CCC65</color>\n    <color name=\"progress_both\">#FFA726</color>\n\n</resources>"
  },
  {
    "path": "examples/mongoDbRealmExample/src/main/res/values/strings.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <string name=\"app_name\">MongoDB Realm Example</string>\n    <string name=\"realm_logo\">Realm Logo</string>\n    <string name=\"username\">Username</string>\n    <string name=\"password\">Password</string>\n    <string name=\"create_account\">Create account and login</string>\n    <string name=\"login\">Login</string>\n    <string name=\"logout\">Logout</string>\n    <string name=\"login_error_unknown_account\">Account does not exist.</string>\n    <string name=\"login_error_invalid_credentials\">User name and password do not match.</string>\n</resources>\n"
  },
  {
    "path": "examples/mongoDbRealmExample/src/main/res/values/styles.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n\n    <!-- Base application theme. -->\n    <style name=\"AppTheme\" parent=\"Theme.AppCompat.Light.DarkActionBar\">\n        <item name=\"colorPrimary\">@color/flamingo</item>\n        <item name=\"colorPrimaryDark\">@color/flamingo_darker</item>\n        <item name=\"colorAccent\">@color/ultramarine</item>\n    </style>\n</resources>\n\n"
  },
  {
    "path": "examples/mongoDbRealmExample/src/main/res/values-w820dp/dimens.xml",
    "content": "<resources>\n    <!-- Example customization of dimensions originally defined in res/values/dimens.xml\n         (such as screen margins) for screens with more than 820dp of available width. This\n         would include 7\" and 10\" devices in landscape (~960dp and ~1280dp respectively). -->\n    <dimen name=\"activity_horizontal_margin\">64dp</dimen>\n</resources>\n"
  },
  {
    "path": "examples/multiprocessExample/.gitignore",
    "content": "/build\n"
  },
  {
    "path": "examples/multiprocessExample/build.gradle",
    "content": "apply plugin: 'com.android.application'\napply plugin: 'realm-android'\n\nandroid {\n    compileSdkVersion rootProject.sdkVersion\n    buildToolsVersion rootProject.buildTools\n\n    defaultConfig {\n        applicationId \"io.realm.examples.realmmultiprocessexample\"\n        targetSdkVersion rootProject.sdkVersion\n        minSdkVersion rootProject.minSdkVersion\n        versionCode 1\n        versionName \"1.0\"\n    }\n\n    buildTypes {\n        release {\n            minifyEnabled true\n            signingConfig signingConfigs.debug\n        }\n        debug {\n            minifyEnabled true\n        }\n    }\n}\n\ndependencies {\n    implementation 'com.android.support:appcompat-v7:27.1.1'\n}\n"
  },
  {
    "path": "examples/multiprocessExample/proguard-rules.pro",
    "content": "# Add project specific ProGuard rules here.\n# By default, the flags in this file are appended to flags specified\n# in /home/cc/.android-sdk/tools/proguard/proguard-android.txt\n# You can edit the include path and order by changing the proguardFiles\n# directive in build.gradle.\n#\n# For more details, see\n#   http://developer.android.com/guide/developing/tools/proguard.html\n\n# Add any project specific keep options here:\n\n# If your project uses WebView with JS, uncomment the following\n# and specify the fully qualified class name to the JavaScript interface\n# class:\n#-keepclassmembers class fqcn.of.javascript.interface.for.webview {\n#   public *;\n#}\n"
  },
  {
    "path": "examples/multiprocessExample/src/main/AndroidManifest.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<manifest package=\"io.realm.examples.realmmultiprocessexample\"\n          xmlns:android=\"http://schemas.android.com/apk/res/android\" >\n\n    <application\n        android:allowBackup=\"true\"\n        android:icon=\"@mipmap/ic_launcher\"\n        android:label=\"@string/app_name\"\n        android:supportsRtl=\"true\"\n        android:theme=\"@style/AppTheme\"\n        android:name=\"io.realm.examples.realmmultiprocessexample.MyApplication\">\n        <activity android:name=\"io.realm.examples.realmmultiprocessexample.MainActivity\">\n            <intent-filter>\n                <action android:name=\"android.intent.action.MAIN\"/>\n                <category android:name=\"android.intent.category.LAUNCHER\"/>\n            </intent-filter>\n        </activity>\n\n        <service\n            android:name=\"io.realm.examples.realmmultiprocessexample.AnotherProcessService\"\n            android:enabled=\"true\"\n            android:exported=\"false\"\n            android:process=\":remote\">\n        </service>\n    </application>\n</manifest>\n"
  },
  {
    "path": "examples/multiprocessExample/src/main/java/io/realm/examples/realmmultiprocessexample/AnotherProcessService.java",
    "content": "/*\n * Copyright 2017 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\npackage io.realm.examples.realmmultiprocessexample;\n\nimport android.app.Service;\nimport android.content.Intent;\nimport android.os.Handler;\nimport android.os.IBinder;\nimport android.os.Looper;\n\nimport io.realm.Realm;\n\npublic class AnotherProcessService extends Service {\n\n    Handler handler;\n\n    @Override\n    public void onCreate() {\n        super.onCreate();\n\n        handler = new Handler(Looper.myLooper());\n        final Runnable runnable = new Runnable() {\n            @Override\n            public void run() {\n                Realm realm = Realm.getDefaultInstance();\n                realm.beginTransaction();\n                realm.copyToRealmOrUpdate(Utils.createStandaloneProcessInfo(AnotherProcessService.this));\n                realm.commitTransaction();\n                realm.close();\n                handler.postDelayed(this, 1000);\n            }\n        };\n        handler.postDelayed(runnable, 1000);\n    }\n\n    @Override\n    public void onDestroy() {\n        super.onDestroy();\n    }\n\n    @Override\n    public IBinder onBind(Intent intent) {\n        throw new UnsupportedOperationException(\"Not yet implemented\");\n    }\n}\n"
  },
  {
    "path": "examples/multiprocessExample/src/main/java/io/realm/examples/realmmultiprocessexample/MainActivity.java",
    "content": "/*\n * Copyright 2017 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 */\npackage io.realm.examples.realmmultiprocessexample;\n\nimport android.content.Intent;\nimport android.support.v7.app.AppCompatActivity;\nimport android.os.Bundle;\nimport android.view.View;\nimport android.widget.TextView;\n\nimport java.text.DateFormat;\nimport java.text.SimpleDateFormat;\nimport java.util.Locale;\n\nimport io.realm.Realm;\nimport io.realm.RealmChangeListener;\nimport io.realm.RealmResults;\nimport io.realm.examples.realmmultiprocessexample.models.ProcessInfo;\n\npublic class MainActivity extends AppCompatActivity {\n\n    private TextView textView;\n    private Realm realm;\n    private RealmResults<ProcessInfo> processInfoResults;\n    private DateFormat dateFormat = new SimpleDateFormat(\"MM/dd/yyyy HH:mm:ss\", Locale.ENGLISH);\n\n    private RealmChangeListener<RealmResults<ProcessInfo>> listener =\n            new RealmChangeListener<RealmResults<ProcessInfo>>() {\n        @Override\n        public void onChange(RealmResults<ProcessInfo> results) {\n            StringBuilder stringBuilder = new StringBuilder();\n\n            for (ProcessInfo processInfo : results) {\n                stringBuilder.append(processInfo.getName());\n                stringBuilder.append(\"\\npid: \");\n                stringBuilder.append(processInfo.getPid());\n                stringBuilder.append(\"\\nlast response time: \");\n                stringBuilder.append(dateFormat.format(processInfo.getLastResponseDate()));\n                stringBuilder.append(\"\\n------\\n\");\n            }\n            textView.setText(stringBuilder.toString());\n        }\n    };\n\n    @Override\n    protected void onCreate(Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n        setContentView(R.layout.activity_main);\n        textView = (TextView) findViewById(R.id.textView);\n\n        if (realm == null) {\n            realm = Realm.getDefaultInstance();\n            processInfoResults = realm.where(ProcessInfo.class).findAllAsync();\n            processInfoResults.addChangeListener(listener);\n        }\n\n        realm.beginTransaction();\n        realm.copyToRealmOrUpdate(Utils.createStandaloneProcessInfo(this));\n        realm.commitTransaction();\n    }\n\n    @Override\n    protected void onDestroy() {\n        super.onDestroy();\n        if (realm != null) {\n            realm.close();\n            realm = null;\n            processInfoResults = null;\n        }\n    }\n\n    public void onStartButton(View button) {\n        Intent intent = new Intent(MainActivity.this, AnotherProcessService.class);\n        startService(intent);\n        button.setEnabled(false);\n    }\n}\n"
  },
  {
    "path": "examples/multiprocessExample/src/main/java/io/realm/examples/realmmultiprocessexample/MyApplication.java",
    "content": "/*\n * Copyright 2017 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\npackage io.realm.examples.realmmultiprocessexample;\n\nimport android.app.Application;\n\nimport io.realm.Realm;\nimport io.realm.RealmConfiguration;\n\npublic class MyApplication extends Application {\n    @Override\n    public void onCreate() {\n        super.onCreate();\n        Realm.init(this);\n        RealmConfiguration configuration = new RealmConfiguration.Builder()\n                .deleteRealmIfMigrationNeeded()\n                .allowWritesOnUiThread(true)\n                .allowQueriesOnUiThread(true)\n                .build();\n        Realm.setDefaultConfiguration(configuration);\n    }\n}\n"
  },
  {
    "path": "examples/multiprocessExample/src/main/java/io/realm/examples/realmmultiprocessexample/Utils.java",
    "content": "/*\n * Copyright 2017 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\npackage io.realm.examples.realmmultiprocessexample;\n\nimport android.app.ActivityManager;\nimport android.app.ActivityManager.RunningAppProcessInfo;\nimport android.content.Context;\nimport android.os.Process;\n\nimport java.util.Date;\nimport java.util.List;\n\nimport io.realm.examples.realmmultiprocessexample.models.ProcessInfo;\n\npublic class Utils {\n\n    public static String getMyProcessName(Context context) {\n        String processName = \"\";\n        ActivityManager am = (ActivityManager)context.getSystemService(Context.ACTIVITY_SERVICE);\n        List<RunningAppProcessInfo> infoList = am.getRunningAppProcesses();\n        if (infoList == null) {\n            throw new RuntimeException(\"getRunningAppProcesses() returns 'null'.\");\n        }\n        for (RunningAppProcessInfo info : infoList) {\n            try {\n                if (info.pid == Process.myPid()) {\n                    processName = info.processName;\n                    break;\n                }\n            } catch (Exception ignored) {\n            }\n        }\n        return processName;\n    }\n\n    public static ProcessInfo createStandaloneProcessInfo(Context context) {\n        ProcessInfo processInfo = new ProcessInfo();\n        processInfo.setName(getMyProcessName(context));\n        processInfo.setPid(android.os.Process.myPid());\n        processInfo.setLastResponseDate(new Date());\n\n        return processInfo;\n    }\n}\n"
  },
  {
    "path": "examples/multiprocessExample/src/main/java/io/realm/examples/realmmultiprocessexample/models/ProcessInfo.java",
    "content": "/*\n * Copyright 2017 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 */\npackage io.realm.examples.realmmultiprocessexample.models;\n\nimport java.util.Date;\n\nimport io.realm.RealmObject;\nimport io.realm.annotations.PrimaryKey;\nimport io.realm.annotations.Required;\n\npublic class ProcessInfo extends RealmObject {\n    @PrimaryKey\n    private String name;\n    private int pid;\n    @Required\n    private Date lastResponseDate;\n\n    public int getPid() {\n        return pid;\n    }\n\n    public void setPid(int pid) {\n        this.pid = pid;\n    }\n\n    public String getName() {\n        return name;\n    }\n\n    public void setName(String name) {\n        this.name = name;\n    }\n\n    public Date getLastResponseDate() {\n        return lastResponseDate;\n    }\n\n    public void setLastResponseDate(Date lastResponseDate) {\n        this.lastResponseDate = lastResponseDate;\n    }\n}\n"
  },
  {
    "path": "examples/multiprocessExample/src/main/res/layout/activity_main.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<RelativeLayout\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:paddingBottom=\"@dimen/activity_vertical_margin\"\n    android:paddingLeft=\"@dimen/activity_horizontal_margin\"\n    android:paddingRight=\"@dimen/activity_horizontal_margin\"\n    android:paddingTop=\"@dimen/activity_vertical_margin\" >\n\n    <Button\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:text=\"@string/start_remote_service\"\n        android:id=\"@+id/button\"\n        android:layout_alignParentTop=\"true\"\n        android:layout_centerHorizontal=\"true\"\n        android:onClick=\"onStartButton\"/>\n\n    <TextView\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\"\n        android:id=\"@+id/textView\"\n        android:layout_centerHorizontal=\"true\"\n        android:layout_below=\"@+id/button\"/>\n</RelativeLayout>\n"
  },
  {
    "path": "examples/multiprocessExample/src/main/res/values/colors.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <color name=\"colorPrimary\">#3F51B5</color>\n    <color name=\"colorPrimaryDark\">#303F9F</color>\n    <color name=\"colorAccent\">#FF4081</color>\n</resources>\n"
  },
  {
    "path": "examples/multiprocessExample/src/main/res/values/dimens.xml",
    "content": "<resources>\n    <!-- Default screen margins, per the Android Design guidelines. -->\n    <dimen name=\"activity_horizontal_margin\">16dp</dimen>\n    <dimen name=\"activity_vertical_margin\">16dp</dimen>\n</resources>\n"
  },
  {
    "path": "examples/multiprocessExample/src/main/res/values/strings.xml",
    "content": "<resources>\n    <string name=\"app_name\">Realm Multi Process example</string>\n    <string name=\"start_remote_service\">Start remote service</string>\n</resources>\n"
  },
  {
    "path": "examples/multiprocessExample/src/main/res/values/styles.xml",
    "content": "<resources>\n\n    <!-- Base application theme. -->\n    <style name=\"AppTheme\" parent=\"Theme.AppCompat.Light.DarkActionBar\">\n        <!-- Customize your theme here. -->\n        <item name=\"colorPrimary\">@color/colorPrimary</item>\n        <item name=\"colorPrimaryDark\">@color/colorPrimaryDark</item>\n        <item name=\"colorAccent\">@color/colorAccent</item>\n    </style>\n\n</resources>\n"
  },
  {
    "path": "examples/multiprocessExample/src/main/res/values-w820dp/dimens.xml",
    "content": "<resources>\n    <!-- Example customization of dimensions originally defined in res/values/dimens.xml\n         (such as screen margins) for screens with more than 820dp of available width. This\n         would include 7\" and 10\" devices in landscape (~960dp and ~1280dp respectively). -->\n    <dimen name=\"activity_horizontal_margin\">64dp</dimen>\n</resources>\n"
  },
  {
    "path": "examples/rxJavaExample/README.md",
    "content": "# Examples combining RxJava and Realm\n\n# Things to keep in mind\n\n- Observables might have a default `Scheduler` they operate on that is different than the one \n  the RealmObject was created on. Accessing Realm objects on the wrong thread will throw an \n  `IllegalStateException`.\n  \n- RealmObjects are live objects that automatically stay up to date. Operators that expect\n  immutable objects will most likely not work as expected, e.g. `distinctUntilChanged`.\n\n- Retrofit 1.x automatically uses a worker thread.\n\n- Use the Realm async API instead of `subscribeOn` to move Realm work off the UI thread.\n\n- You can use `Realm.copyFromRealm` to make a copy of Realm data.\n"
  },
  {
    "path": "examples/rxJavaExample/build.gradle",
    "content": "apply plugin: 'com.android.application'\napply plugin: 'realm-android'\n\nandroid {\n    //noinspection GroovyAssignabilityCheck\n    compileSdkVersion rootProject.sdkVersion\n    //noinspection GroovyAssignabilityCheck\n    buildToolsVersion rootProject.buildTools\n\n    defaultConfig {\n        applicationId 'io.realm.examples.rxjava'\n        //noinspection GroovyAssignabilityCheck\n        targetSdkVersion rootProject.sdkVersion\n        minSdkVersion rootProject.minSdkVersion\n        versionCode 1\n        versionName \"1.0\"\n    }\n\n    buildTypes {\n        release {\n            minifyEnabled false\n        }\n    }\n\n    packagingOptions {\n        exclude 'META-INF/LICENSE'\n    }\n\n    compileOptions {\n        sourceCompatibility JavaVersion.VERSION_1_8\n        targetCompatibility JavaVersion.VERSION_1_8\n    }\n}\n\ndependencies {\n    implementation 'io.reactivex.rxjava2:rxandroid:2.0.2'\n    implementation 'io.reactivex.rxjava2:rxjava:2.1.13'\n    implementation 'com.android.support:appcompat-v7:27.1.1'\n    implementation 'com.jakewharton.rxbinding2:rxbinding:2.0.0'\n    implementation 'com.squareup.retrofit2:adapter-rxjava2:2.3.0'\n    implementation 'com.squareup.retrofit2:converter-jackson:2.3.0'\n    implementation 'com.squareup.retrofit2:retrofit:2.3.0'\n}\n"
  },
  {
    "path": "examples/rxJavaExample/lint.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<lint>\n    <issue id=\"AllowBackup\" severity=\"ignore\" />\n    <issue id=\"GoogleAppIndexingWarning\" severity=\"ignore\" />\n    <issue id=\"IconMissingDensityFolder\" severity=\"ignore\" />\n    <issue id=\"IconLauncherShape\" severity=\"ignore\" />\n    <issue id=\"InvalidPackage\" severity=\"ignore\" />\n</lint>\n"
  },
  {
    "path": "examples/rxJavaExample/src/main/AndroidManifest.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    package=\"io.realm.examples.rxjava\">\n\n    <uses-permission android:name=\"android.permission.INTERNET\" />\n\n    <application\n        android:name=\".MyApplication\"\n        android:icon=\"@mipmap/ic_launcher\"\n        android:label=\"@string/app_name\"\n        android:theme=\"@style/AppTheme\">\n        <activity\n            android:name=\".MainActivity\"\n            android:label=\"@string/app_name\">\n            <intent-filter>\n                <action android:name=\"android.intent.action.MAIN\" />\n                <category android:name=\"android.intent.category.LAUNCHER\" />\n            </intent-filter>\n        </activity>\n        <activity android:name=\".animation.AnimationActivity\" />\n        <activity android:name=\".retrofit.RetrofitExample\" />\n        <activity android:name=\".throttle.ThrottleSearchActivity\" />\n        <activity android:name=\".gotchas.GotchasActivity\" />\n    </application>\n\n</manifest>\n"
  },
  {
    "path": "examples/rxJavaExample/src/main/java/io/realm/examples/rxjava/MainActivity.java",
    "content": "/*\n * Copyright 2015 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\npackage io.realm.examples.rxjava;\n\nimport android.app.Activity;\nimport android.content.Intent;\nimport android.os.Bundle;\nimport android.support.v7.app.AppCompatActivity;\nimport android.view.ViewGroup;\nimport android.widget.Button;\n\nimport java.util.Map;\nimport java.util.TreeMap;\n\nimport io.realm.examples.rxjava.animation.AnimationActivity;\nimport io.realm.examples.rxjava.gotchas.GotchasActivity;\nimport io.realm.examples.rxjava.retrofit.RetrofitExample;\nimport io.realm.examples.rxjava.throttle.ThrottleSearchActivity;\n\npublic class MainActivity extends AppCompatActivity {\n\n    private ViewGroup container;\n    private final TreeMap<String, Class<? extends Activity>> buttons = new TreeMap<String, Class<? extends Activity>>() {{\n        put(\"Animation\", AnimationActivity.class);\n        put(\"Throttle search\", ThrottleSearchActivity.class);\n        put(\"Network\", RetrofitExample.class);\n        put(\"Working with Realm\", GotchasActivity.class);\n    }};\n\n    @Override\n    protected void onCreate(Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n        setContentView(R.layout.activity_main);\n        container = findViewById(R.id.list);\n        setupButtons();\n    }\n\n    private void setupButtons() {\n        for (final Map.Entry<String, Class<? extends Activity>> entry : buttons.entrySet()) {\n            Button button = new Button(this);\n            button.setText(entry.getKey());\n            button.setOnClickListener(view -> startActivity(entry.getValue()));\n            container.addView(button);\n        }\n    }\n\n    private void startActivity(Class<? extends Activity> activityClass) {\n        startActivity(new Intent(this, activityClass));\n    }\n}\n"
  },
  {
    "path": "examples/rxJavaExample/src/main/java/io/realm/examples/rxjava/MyApplication.java",
    "content": "/*\n * Copyright 2015 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\npackage io.realm.examples.rxjava;\n\nimport android.app.Application;\n\nimport java.util.Map;\nimport java.util.Random;\nimport java.util.TreeMap;\n\nimport io.realm.Realm;\nimport io.realm.RealmConfiguration;\nimport io.realm.examples.rxjava.model.Person;\n\npublic class MyApplication extends Application {\n\n    private static final TreeMap<String, String> testPersons = new TreeMap<>();\n    static {\n        testPersons.put(\"Chris\", null);\n        testPersons.put(\"Christian\", \"cmelchior\");\n        testPersons.put(\"Christoffer\", null);\n        testPersons.put(\"Emanuele\", \"emanuelez\");\n        testPersons.put(\"Dan\", null);\n        testPersons.put(\"Donn\", \"donnfelker\");\n        testPersons.put(\"Nabil\", \"nhachicha\");\n        testPersons.put(\"Ron\", null);\n        testPersons.put(\"Leonardo\", \"dalinaum\");\n    }\n\n    @Override\n    public void onCreate() {\n        super.onCreate();\n        Realm.init(this);\n        RealmConfiguration config = new RealmConfiguration.Builder()\n                .allowWritesOnUiThread(true)\n                .allowQueriesOnUiThread(true)\n                .build();\n        Realm.deleteRealm(config);\n        Realm.setDefaultConfiguration(config);\n        createTestData();\n    }\n\n    // Create test data\n    private void createTestData() {\n        final Random random = new Random(42);\n        Realm realm = Realm.getDefaultInstance();\n        realm.executeTransaction(r -> {\n            for (Map.Entry<String, String> entry : testPersons.entrySet()) {\n                Person p = r.createObject(Person.class);\n                p.setName(entry.getKey());\n                p.setGithubUserName(entry.getValue());\n                p.setAge(random.nextInt(100));\n            }\n        });\n        realm.close();\n    }\n}\n"
  },
  {
    "path": "examples/rxJavaExample/src/main/java/io/realm/examples/rxjava/animation/AnimationActivity.java",
    "content": "/*\n * Copyright 2015 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\npackage io.realm.examples.rxjava.animation;\n\nimport android.os.Bundle;\nimport android.support.v7.app.AppCompatActivity;\nimport android.view.ViewGroup;\nimport android.widget.TextView;\n\nimport java.util.concurrent.TimeUnit;\n\nimport io.reactivex.Flowable;\nimport io.reactivex.android.schedulers.AndroidSchedulers;\nimport io.reactivex.disposables.Disposable;\nimport io.realm.Realm;\nimport io.realm.examples.rxjava.R;\nimport io.realm.examples.rxjava.model.Person;\n\npublic class AnimationActivity extends AppCompatActivity {\n\n    private Realm realm;\n    private Disposable disposable;\n    private ViewGroup container;\n\n    @Override\n    protected void onCreate(Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n        setContentView(R.layout.activity_animations);\n        container = findViewById(R.id.list);\n        realm = Realm.getDefaultInstance();\n    }\n\n    @Override\n    protected void onResume() {\n        super.onResume();\n\n        // Load all persons and start inserting them with 1 sec. intervals.\n        // All RealmObject access has to be done on the same thread `findAllAsync` was called on.\n        // Warning: This example doesn't handle back pressure well.\n        disposable = realm.where(Person.class).findAllAsync().asFlowable()\n                .flatMap(persons -> Flowable.fromIterable(persons))\n                .zipWith(Flowable.interval(1, TimeUnit.SECONDS), (person, tick) -> person)\n                .observeOn(AndroidSchedulers.mainThread())\n                .subscribe(person -> {\n                    TextView personView = new TextView(AnimationActivity.this);\n                    personView.setText(person.getName());\n                    container.addView(personView);\n                });\n    }\n\n    @Override\n    protected void onPause() {\n        super.onPause();\n        disposable.dispose();\n    }\n\n    @Override\n    protected void onDestroy() {\n        super.onDestroy();\n        realm.close();\n    }\n}\n"
  },
  {
    "path": "examples/rxJavaExample/src/main/java/io/realm/examples/rxjava/gotchas/GotchasActivity.java",
    "content": "/*\n * Copyright 2015 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\npackage io.realm.examples.rxjava.gotchas;\n\nimport android.os.Bundle;\nimport android.support.v7.app.AppCompatActivity;\nimport android.view.ViewGroup;\nimport android.widget.TextView;\n\nimport java.util.Random;\n\nimport io.reactivex.Flowable;\nimport io.reactivex.disposables.CompositeDisposable;\nimport io.reactivex.disposables.Disposable;\nimport io.reactivex.schedulers.Schedulers;\nimport io.realm.Realm;\nimport io.realm.Sort;\nimport io.realm.examples.rxjava.R;\nimport io.realm.examples.rxjava.model.Person;\n\n/**\n * This class shows some of the current obstacles when combining RxJava and Realm. 2 things are\n * important to keep in mind.\n *\n * 1) Thread confinement: Realm objects are thread confined, so trying to access them from another thread will throw\n *    an exception.\n *\n * 2) Realm objects are live objects. This means that the same object will alter it's state automatically over time to\n *    automatically reflect the latest state in Realm.\n *\n * Both of these characteristics doesn't play well with RxJava's threading model which favor immutable thread-safe\n * objects.\n *\n * Work is in progress to make it easier to work around these constraints. See\n * - https://github.com/realm/realm-java/issues/1208\n * - https://github.com/realm/realm-java/issues/931\n */\npublic class GotchasActivity extends AppCompatActivity {\n    private Realm realm;\n    private CompositeDisposable compositeDisposable = new CompositeDisposable();\n    private ViewGroup container;\n\n    @Override\n    protected void onCreate(Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n        setContentView(R.layout.activity_gotchas);\n        container = findViewById(R.id.list);\n        realm = Realm.getDefaultInstance();\n    }\n\n    @Override\n    protected void onResume() {\n        super.onResume();\n        testDistinct();\n        testBuffer();\n        testSubscribeOn();\n\n        // Trigger updates\n        realm.executeTransaction(r ->\n                r.where(Person.class).sort( \"name\", Sort.ASCENDING).findAll().get(0).setAge(new Random().nextInt(100)));\n    }\n\n    /**\n     * Shows how to be careful with `subscribeOn()`\n     */\n    private void testSubscribeOn() {\n        Disposable subscribeOnDisposable = realm.asFlowable()\n                .map(realm -> realm.where(Person.class).sort(\"name\").findAll().get(0))\n                // The Realm was created on the UI thread. Accessing it on `Schedulers.io()` will crash.\n                // Avoid using subscribeOn() and use Realms `findAllAsync*()` methods instead.\n                .subscribeOn(Schedulers.io()) //\n                .subscribe(\n                        person -> {}, // Do nothing\n                        throwable -> showStatus(\"subscribeOn: \" + throwable.toString())\n                );\n        compositeDisposable.add(subscribeOnDisposable);\n\n        // Use Realms Async API instead\n        Disposable asyncSubscribeOnDisposable = realm.where(Person.class).sort(\"name\").findAllAsync().get(0).<Person>asFlowable()\n                .subscribe(\n                        person -> showStatus(\"subscribeOn/async: \" + person.getName() + \":\" + person.getAge()),\n                        throwable -> showStatus(\"subscribeOn/async: \" +throwable.toString())\n                );\n        compositeDisposable.add(asyncSubscribeOnDisposable);\n    }\n\n    /**\n     * Shows how to be careful with `buffer()`\n     */\n    private void testBuffer() {\n        Flowable<Person> personFlowable =\n                realm.asFlowable().map(realm -> realm.where(Person.class).sort(\"name\").findAll().get(0));\n\n        // buffer() caches objects until the buffer is full. Due to Realms auto-update of all objects it means\n        // that all objects in the cache will contain the same data.\n        // Either avoid using buffer or copy data into an unmanaged object.\n        Disposable disposable = personFlowable\n                .buffer(2)\n                .subscribe(people -> {\n                    showStatus(\"Buffer[0] : \" + people.get(0).getName() + \":\" + people.get(0).getAge());\n                    showStatus(\"Buffer[1] : \" + people.get(1).getName() + \":\" + people.get(1).getAge());\n                });\n        compositeDisposable.add(disposable);\n    }\n\n    /**\n     * Shows how to to be careful when using `distinct()`\n     */\n    private void testDistinct() {\n        Flowable<Person> personFlowable =\n                realm.asFlowable().map(realm -> realm.where(Person.class).sort(\"name\").findAll().get(0));\n\n        // distinct() and distinctUntilChanged() uses standard equals with older objects stored in a HashMap.\n        // Realm objects auto-update which means the objects stored will also auto-update.\n        // This makes comparing against older objects impossible (even if the new object has changed) because the\n        // cached object will also have changed.\n        // Use a keySelector function to work around this.\n        Disposable distinctDisposable = personFlowable\n                .distinct() // Because old == new. This will only allow the first version of the \"Chris\" object to pass.\n                .subscribe(person -> showStatus(\"distinct(): \" + person.getName() + \":\" + person.getAge()));\n        compositeDisposable.add(distinctDisposable);\n\n        Disposable distinctKeySelectorDisposable = personFlowable\n                .distinct(person -> person.getAge())\n                .subscribe(person -> showStatus(\"distinct(keySelector): \" + person.getName() + \":\" + person.getAge()));\n        compositeDisposable.add(distinctKeySelectorDisposable);\n    }\n\n    private void showStatus(String message) {\n        TextView v = new TextView(this);\n        v.setText(message);\n        container.addView(v);\n    }\n\n    @Override\n    protected void onPause() {\n        super.onPause();\n        compositeDisposable.clear();\n    }\n\n    @Override\n    protected void onDestroy() {\n        super.onDestroy();\n        realm.close();\n    }\n}\n"
  },
  {
    "path": "examples/rxJavaExample/src/main/java/io/realm/examples/rxjava/model/Person.java",
    "content": "/*\n * Copyright 2015 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\npackage io.realm.examples.rxjava.model;\n\nimport io.realm.RealmObject;\n\npublic class Person extends RealmObject {\n\n    // All fields are by default persisted.\n    private String name;\n    private int age;\n    private String githubUserName;\n\n    public String getName() {\n        return name;\n    }\n\n    public void setName(String name) {\n        this.name = name;\n    }\n\n    public int getAge() {\n        return age;\n    }\n\n    public void setAge(int age) {\n        this.age = age;\n    }\n\n    public String getGithubUserName() {\n        return githubUserName;\n    }\n\n    public void setGithubUserName(String githubUserName) {\n        this.githubUserName = githubUserName;\n    }\n}\n"
  },
  {
    "path": "examples/rxJavaExample/src/main/java/io/realm/examples/rxjava/retrofit/GitHubApi.java",
    "content": "/*\n * Copyright 2015 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\npackage io.realm.examples.rxjava.retrofit;\n\nimport io.reactivex.Flowable;\nimport retrofit2.http.GET;\nimport retrofit2.http.Path;\n\n/**\n * GitHub API definition\n */\ninterface GitHubApi {\n    /**\n     * See https://developer.github.com/v3/users/\n     */\n    @GET(\"/users/{user}\")\n    Flowable<GitHubUser> user(@Path(\"user\") String user);\n}\n"
  },
  {
    "path": "examples/rxJavaExample/src/main/java/io/realm/examples/rxjava/retrofit/GitHubUser.java",
    "content": "/*\n * Copyright 2015 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\npackage io.realm.examples.rxjava.retrofit;\n\nimport com.fasterxml.jackson.annotation.JsonIgnoreProperties;\n\n/**\n * Model class for GitHub users: https://developer.github.com/v3/users/#get-a-single-user\n */\n@SuppressWarnings(\"unused\")\n@JsonIgnoreProperties(ignoreUnknown = true)\nclass GitHubUser {\n    public String name;\n    public int public_repos;\n    public int public_gists;\n}\n"
  },
  {
    "path": "examples/rxJavaExample/src/main/java/io/realm/examples/rxjava/retrofit/RetrofitExample.java",
    "content": "/*\n * Copyright 2015 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\npackage io.realm.examples.rxjava.retrofit;\n\nimport android.os.Bundle;\nimport android.support.v7.app.AppCompatActivity;\nimport android.view.ViewGroup;\nimport android.widget.TextView;\n\nimport java.util.Locale;\n\nimport io.reactivex.Flowable;\nimport io.reactivex.android.schedulers.AndroidSchedulers;\nimport io.reactivex.disposables.Disposable;\nimport io.reactivex.schedulers.Schedulers;\nimport io.realm.Realm;\nimport io.realm.examples.rxjava.R;\nimport io.realm.examples.rxjava.model.Person;\nimport okhttp3.OkHttpClient;\nimport okhttp3.Request;\nimport retrofit2.Retrofit;\nimport retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;\nimport retrofit2.converter.jackson.JacksonConverterFactory;\n\nimport static android.text.TextUtils.isEmpty;\nimport static java.lang.String.format;\n\npublic class RetrofitExample extends AppCompatActivity {\n\n    private Realm realm;\n    private Disposable disposable;\n    private ViewGroup container;\n    private GitHubApi api;\n\n    @Override\n    protected void onCreate(Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n        setContentView(R.layout.activity_network);\n        container = findViewById(R.id.list);\n        realm = Realm.getDefaultInstance();\n        api = createGitHubApi();\n    }\n\n    @Override\n    protected void onResume() {\n        super.onResume();\n\n        // Load all persons and merge them with their latest stats from GitHub (if they have any)\n        disposable = realm.where(Person.class).isNotNull(\"githubUserName\").sort(\"name\").findAllAsync().asFlowable()\n                // We only want the list once it is loaded.\n                .filter(people -> people.isLoaded())\n                .switchMap(people -> Flowable.fromIterable(people))\n\n                // get GitHub statistics.\n                .flatMap(person -> api.user(person.getGithubUserName()))\n\n                // Map Network model to our View model\n                .map(gitHubUser -> new UserViewModel(gitHubUser.name, gitHubUser.public_repos, gitHubUser.public_gists))\n\n                // Retrofit put us on a worker thread. Move back to UI\n                .observeOn(AndroidSchedulers.mainThread())\n\n                .subscribe(user -> {\n                    // Print user info.\n                    TextView userView = new TextView(RetrofitExample.this);\n                    userView.setText(\n                            String.format(Locale.US, \"%s : %d/%d\", user.getUsername(), user.getPublicRepos(), user.getPublicGists()));\n                    container.addView(userView);\n                }, throwable -> throwable.printStackTrace());\n    }\n\n    @Override\n    protected void onPause() {\n        super.onPause();\n        disposable.dispose();\n    }\n\n    @Override\n    protected void onDestroy() {\n        super.onDestroy();\n        realm.close();\n    }\n\n    private GitHubApi createGitHubApi() {\n\n        Retrofit.Builder builder = new Retrofit.Builder()\n                .baseUrl(\"https://api.github.com/\")\n                .addCallAdapterFactory(RxJava2CallAdapterFactory.createWithScheduler(Schedulers.io()))\n                .addConverterFactory(JacksonConverterFactory.create());\n\n        OkHttpClient.Builder httpClientBuilder = new OkHttpClient.Builder();\n\n        final String gitHubToken = \"\"; // Set GitHub OAuth token to avoid throttling if example is used a lot\n\n        if (!isEmpty(gitHubToken)) {\n            httpClientBuilder.addInterceptor(chain -> {\n                Request originalRequest = chain.request();\n                Request modifiedRequest = originalRequest\n                        .newBuilder()\n                        .header(\"Authorization\", format(\"token %s\", gitHubToken))\n                        .method(originalRequest.method(), originalRequest.body())\n                        .build();\n                return chain.proceed(modifiedRequest);\n            });\n        }\n\n        OkHttpClient httpClient = httpClientBuilder.build();\n        builder.client(httpClient);\n        return builder.build().create(GitHubApi.class);\n    }\n}\n"
  },
  {
    "path": "examples/rxJavaExample/src/main/java/io/realm/examples/rxjava/retrofit/UserViewModel.java",
    "content": "/*\n * Copyright 2015 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\npackage io.realm.examples.rxjava.retrofit;\n\npublic class UserViewModel {\n\n    private final String username;\n    private final int publicRepos;\n    private final int publicGists;\n\n    public UserViewModel(String username, int publicRepos, int publicGists) {\n        this.username = username;\n        this.publicRepos = publicRepos;\n        this.publicGists = publicGists;\n    }\n\n    public String getUsername() {\n        return username;\n    }\n\n    public int getPublicRepos() {\n        return publicRepos;\n    }\n\n    public int getPublicGists() {\n        return publicGists;\n    }\n}\n"
  },
  {
    "path": "examples/rxJavaExample/src/main/java/io/realm/examples/rxjava/throttle/ThrottleSearchActivity.java",
    "content": "/*\n * Copyright 2015 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\npackage io.realm.examples.rxjava.throttle;\n\nimport android.os.Bundle;\nimport android.support.v7.app.AppCompatActivity;\nimport android.view.ViewGroup;\nimport android.widget.EditText;\nimport android.widget.TextView;\n\nimport com.jakewharton.rxbinding2.widget.RxTextView;\n\nimport java.util.concurrent.TimeUnit;\n\nimport io.reactivex.BackpressureStrategy;\nimport io.reactivex.android.schedulers.AndroidSchedulers;\nimport io.reactivex.disposables.Disposable;\nimport io.realm.Realm;\nimport io.realm.examples.rxjava.R;\nimport io.realm.examples.rxjava.model.Person;\n\npublic class ThrottleSearchActivity extends AppCompatActivity {\n\n    private Realm realm;\n    private Disposable disposable;\n    private EditText searchInputView;\n    private ViewGroup searchResultsView;\n\n    @Override\n    protected void onCreate(Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n        setContentView(R.layout.activity_throttlesearch);\n        searchInputView = findViewById(R.id.search);\n        searchResultsView = findViewById(R.id.search_results);\n        realm = Realm.getDefaultInstance();\n    }\n\n    @Override\n    protected void onResume() {\n        super.onResume();\n\n        // Listen to key presses and only start search after user paused to avoid excessive redrawing on the screen.\n        disposable = RxTextView.textChangeEvents(searchInputView)\n                .debounce(200, TimeUnit.MILLISECONDS) // default Scheduler is Schedulers.computation()\n                .observeOn(AndroidSchedulers.mainThread()) // Needed to access Realm data\n                .toFlowable(BackpressureStrategy.BUFFER)\n                .switchMap(textChangeEvent -> {\n                    // Use Async API to move Realm queries off the main thread.\n                    // Realm currently doesn't support the standard Schedulers.\n                    return realm.where(Person.class)\n                            .beginsWith(\"name\", textChangeEvent.text().toString())\n                            .sort(\"name\")\n                            .findAllAsync()\n                            .asFlowable();\n                })\n                // Only continue once data is actually loaded\n                // RealmObservables will emit the unloaded (empty) list as its first item\n                .filter(people -> people.isLoaded())\n                .subscribe(people -> {\n                    searchResultsView.removeAllViews();\n                    for (Person person : people) {\n                        TextView view = new TextView(ThrottleSearchActivity.this);\n                        view.setText(person.getName());\n                        searchResultsView.addView(view);\n                    }\n                }, throwable -> throwable.printStackTrace());\n    }\n\n    @Override\n    protected void onPause() {\n        super.onPause();\n        disposable.dispose();\n    }\n\n    @Override\n    protected void onDestroy() {\n        super.onDestroy();\n        realm.close();\n    }\n}\n"
  },
  {
    "path": "examples/rxJavaExample/src/main/res/layout/activity_animations.xml",
    "content": "<ScrollView\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:paddingLeft=\"@dimen/activity_horizontal_margin\"\n    android:paddingRight=\"@dimen/activity_horizontal_margin\"\n    android:paddingTop=\"@dimen/activity_vertical_margin\"\n    android:paddingBottom=\"@dimen/activity_vertical_margin\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\">\n    <LinearLayout\n        android:id=\"@+id/list\"\n        android:orientation=\"vertical\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\">\n    </LinearLayout>\n</ScrollView>\n"
  },
  {
    "path": "examples/rxJavaExample/src/main/res/layout/activity_gotchas.xml",
    "content": "<ScrollView\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:paddingBottom=\"@dimen/activity_vertical_margin\"\n    android:paddingLeft=\"@dimen/activity_horizontal_margin\"\n    android:paddingRight=\"@dimen/activity_horizontal_margin\"\n    android:paddingTop=\"@dimen/activity_vertical_margin\">\n\n    <LinearLayout\n        android:id=\"@+id/list\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:orientation=\"vertical\">\n\n        <TextView\n            android:id=\"@+id/textView\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"wrap_content\"\n            android:gravity=\"center_horizontal\"\n            android:textStyle=\"italic\"\n            android:paddingBottom=\"16dp\"\n            android:text=\"@string/default_message\"\n            android:textAppearance=\"?android:attr/textAppearanceMedium\"/>\n    </LinearLayout>\n</ScrollView>\n"
  },
  {
    "path": "examples/rxJavaExample/src/main/res/layout/activity_main.xml",
    "content": "<ScrollView\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:paddingLeft=\"@dimen/activity_horizontal_margin\"\n    android:paddingRight=\"@dimen/activity_horizontal_margin\"\n    android:paddingTop=\"@dimen/activity_vertical_margin\"\n    android:paddingBottom=\"@dimen/activity_vertical_margin\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\">\n    <LinearLayout\n        android:id=\"@+id/list\"\n        android:orientation=\"vertical\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\">\n    </LinearLayout>\n</ScrollView>\n"
  },
  {
    "path": "examples/rxJavaExample/src/main/res/layout/activity_network.xml",
    "content": "<ScrollView\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:paddingLeft=\"@dimen/activity_horizontal_margin\"\n    android:paddingRight=\"@dimen/activity_horizontal_margin\"\n    android:paddingTop=\"@dimen/activity_vertical_margin\"\n    android:paddingBottom=\"@dimen/activity_vertical_margin\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\">\n    <LinearLayout\n        android:id=\"@+id/list\"\n        android:orientation=\"vertical\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\">\n    </LinearLayout>\n</ScrollView>\n"
  },
  {
    "path": "examples/rxJavaExample/src/main/res/layout/activity_throttlesearch.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n              android:layout_width=\"match_parent\"\n              android:layout_height=\"match_parent\"\n              android:orientation=\"vertical\">\n\n    <EditText\n        android:id=\"@+id/search\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"48dp\"\n        android:hint=\"@string/search\"/>\n\n    <LinearLayout\n        android:id=\"@+id/search_results\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:orientation=\"vertical\">\n    </LinearLayout>\n</LinearLayout>"
  },
  {
    "path": "examples/rxJavaExample/src/main/res/values/colors.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <color name=\"colorPrimary\">#3F51B5</color>\n    <color name=\"colorPrimaryDark\">#303F9F</color>\n    <color name=\"colorAccent\">#FF4081</color>\n</resources>"
  },
  {
    "path": "examples/rxJavaExample/src/main/res/values/dimens.xml",
    "content": "<resources>\n    <!-- Default screen margins, per the Android Design guidelines. -->\n    <dimen name=\"activity_horizontal_margin\">16dp</dimen>\n    <dimen name=\"activity_vertical_margin\">16dp</dimen>\n</resources>\n"
  },
  {
    "path": "examples/rxJavaExample/src/main/res/values/strings.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <string name=\"app_name\">RxJava examples</string>\n    <string name=\"default_message\">Use the Source, Luke!</string>\n    <string name=\"search\">Search</string>\n</resources>\n"
  },
  {
    "path": "examples/rxJavaExample/src/main/res/values/styles.xml",
    "content": "<resources>\n\n    <style name=\"AppTheme\" parent=\"Theme.AppCompat.Light.DarkActionBar\">\n        <item name=\"colorPrimary\">@color/colorPrimary</item>\n        <item name=\"colorPrimaryDark\">@color/colorPrimaryDark</item>\n        <item name=\"colorAccent\">@color/colorAccent</item>\n    </style>\n\n</resources>\n"
  },
  {
    "path": "examples/rxJavaExample/src/main/res/values-w820dp/dimens.xml",
    "content": "<resources>\n    <!-- Example customization of dimensions originally defined in res/values/dimens.xml\n         (such as screen margins) for screens with more than 820dp of available width. This\n         would include 7\" and 10\" devices in landscape (~960dp and ~1280dp respectively). -->\n    <dimen name=\"activity_horizontal_margin\">64dp</dimen>\n</resources>\n"
  },
  {
    "path": "examples/settings.gradle",
    "content": "rootProject.name = 'realm-examples'\ninclude 'architectureComponentsExample'\ninclude 'encryptionExample'\ninclude 'gridViewExample'\ninclude 'introExample'\ninclude 'jsonExample'\ninclude 'kotlinExample'\ninclude 'migrationExample'\ninclude 'moduleExample:app'\ninclude 'moduleExample:library'\ninclude 'rxJavaExample'\ninclude 'threadExample'\ninclude 'unitTestExample'\ninclude 'mongoDbRealmExample'\ninclude 'multiprocessExample'\ninclude 'compatibilityExample'\ninclude ':coroutinesExample'\n"
  },
  {
    "path": "examples/threadExample/build.gradle",
    "content": "apply plugin: 'com.android.application'\napply plugin: 'realm-android'\n\nandroid {\n    compileSdkVersion rootProject.sdkVersion\n    buildToolsVersion rootProject.buildTools\n\n    defaultConfig {\n        applicationId \"io.realm.examples.threads\"\n        targetSdkVersion rootProject.sdkVersion\n        minSdkVersion rootProject.minSdkVersion\n        versionCode 1\n        versionName \"1.0\"\n    }\n    buildTypes {\n        release {\n            minifyEnabled true\n            signingConfig signingConfigs.debug\n        }\n        debug {\n            minifyEnabled true\n        }\n    }\n}\n\ndependencies {\n    implementation 'com.android.support:appcompat-v7:27.1.1'\n}\n"
  },
  {
    "path": "examples/threadExample/lint.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<lint>\n    <!-- Disable the given check in this project -->\n    <issue id=\"AllowBackup\" severity=\"ignore\" />\n    <issue id=\"IconLauncherShape\" severity=\"ignore\" />\n    <issue id=\"IconMissingDensityFolder\" severity=\"ignore\" />\n    <issue id=\"GoogleAppIndexingWarning\" severity=\"ignore\" />\n    <issue id=\"InvalidPackage\" severity=\"ignore\" />\n</lint>\n"
  },
  {
    "path": "examples/threadExample/src/main/AndroidManifest.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<manifest package=\"io.realm.examples.threads\"\n          xmlns:android=\"http://schemas.android.com/apk/res/android\">\n\n    <uses-permission android:name=\"android.permission.WAKE_LOCK\" />\n    \n    <application\n        android:name=\".MyApplication\"\n        android:allowBackup=\"true\"\n        android:icon=\"@mipmap/ic_launcher\"\n        android:label=\"@string/app_name\"\n        android:theme=\"@style/AppTheme\">\n        <activity\n            android:name=\".ThreadExampleActivity\"\n            android:label=\"@string/app_name\">\n            <intent-filter>\n                <action android:name=\"android.intent.action.MAIN\"/>\n\n                <category android:name=\"android.intent.category.LAUNCHER\"/>\n            </intent-filter>\n        </activity>\n        <activity\n            android:name=\".ReceivingActivity\"\n            android:label=\"@string/title_activity_receiving\">\n        </activity>\n        <service android:name=\".ReceivingService\"\n                 android:exported=\"false\" />\n        <receiver android:name=\".WakefulReceivingBroadcastReceiver\" />\n        <service android:name=\".WakefulReceivingService\" />\n    </application>\n\n</manifest>"
  },
  {
    "path": "examples/threadExample/src/main/java/io/realm/examples/threads/AsyncQueryFragment.java",
    "content": "/*\n * Copyright 2015 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\npackage io.realm.examples.threads;\n\nimport android.content.Context;\nimport android.os.Bundle;\nimport android.support.v4.app.Fragment;\nimport android.view.LayoutInflater;\nimport android.view.View;\nimport android.view.ViewGroup;\nimport android.widget.BaseAdapter;\nimport android.widget.ListView;\nimport android.widget.TextView;\nimport android.widget.Toast;\n\nimport java.util.Collections;\nimport java.util.List;\n\nimport io.realm.Realm;\nimport io.realm.RealmAsyncTask;\nimport io.realm.RealmChangeListener;\nimport io.realm.RealmResults;\nimport io.realm.Sort;\nimport io.realm.examples.threads.model.Dot;\n\n/**\n * This fragment demonstrates how you can perform asynchronous queries with Realm.\n */\npublic class AsyncQueryFragment extends Fragment implements View.OnClickListener, RealmChangeListener<RealmResults<Dot>> {\n    private Realm realm;\n    private DotAdapter dotAdapter;\n    private RealmResults<Dot> allSortedDots;\n    private RealmAsyncTask asyncTransaction;\n\n    @Override\n    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {\n        View rootView = inflater.inflate(R.layout.fragment_async_query, container, false);\n        rootView.findViewById(R.id.translate_button).setOnClickListener(this);\n\n        ListView listView = (ListView) rootView.findViewById(android.R.id.list);\n        dotAdapter = new DotAdapter(getActivity());\n        listView.setAdapter(dotAdapter);\n        return rootView;\n    }\n\n    @Override\n    public void onStart() {\n        super.onStart();\n        // Create Realm instance for the UI thread\n        realm = Realm.getDefaultInstance();\n        allSortedDots = realm.where(Dot.class)\n                .between(\"x\", 25, 75)\n                .between(\"y\", 0, 50)\n                .sort(\n                         \"x\", Sort.ASCENDING,\n                         \"y\", Sort.DESCENDING\n                 )\n                .findAllAsync();\n        dotAdapter.updateList(allSortedDots);\n        allSortedDots.addChangeListener(this);\n    }\n\n    @Override\n    public void onStop() {\n        super.onStop();\n        // Remember to close the Realm instance when done with it.\n        cancelAsyncTransaction();\n        allSortedDots.removeChangeListener(this);\n        allSortedDots = null;\n        realm.close();\n    }\n\n    @Override\n    public void onClick(View view) {\n        switch (view.getId()) {\n            case R.id.translate_button: {\n                cancelAsyncTransaction();\n                // translate all points coordinates using an async transaction\n                asyncTransaction = realm.executeTransactionAsync(new Realm.Transaction() {\n                    @Override\n                    public void execute(Realm realm) {\n                        // query for all points\n                        RealmResults<Dot> dots = realm.where(Dot.class).findAll();\n\n                        for (int i = dots.size() - 1; i >= 0; i--) {\n                            Dot dot = dots.get(i);\n                            if (dot.isValid()) {\n                                int x = dot.getX();\n                                int y = dot.getY();\n                                dot.setX(y);\n                                dot.setY(x);\n                            }\n                        }\n                    }\n                }, new Realm.Transaction.OnSuccess() {\n                    @Override\n                    public void onSuccess() {\n                        if (isAdded()) {\n                            Toast.makeText(getActivity(), \"Translation completed\", Toast.LENGTH_SHORT).show();\n                        }\n                    }\n                }, new Realm.Transaction.OnError() {\n\n                    @Override\n                    public void onError(Throwable e) {\n                        if (isAdded()) {\n                            Toast.makeText(getActivity(), \"Error while translating dots\", Toast.LENGTH_SHORT).show();\n                            e.printStackTrace();\n                        }\n                    }\n                });\n                break;\n            }\n        }\n    }\n\n    private void cancelAsyncTransaction() {\n        if (asyncTransaction != null && !asyncTransaction.isCancelled()) {\n            asyncTransaction.cancel();\n            asyncTransaction = null;\n        }\n    }\n\n    @Override\n    public void onChange(RealmResults<Dot> result) {\n        dotAdapter.notifyDataSetChanged();\n    }\n\n    // Using a generic Adapter instead of RealmBaseAdapter, because\n    // RealmBaseAdapter registers a listener against all Realm changes\n    // whereas in this scenario we're only interested on the changes of our query\n    private static class DotAdapter extends BaseAdapter {\n        private List<Dot> dots = Collections.emptyList();\n        private final LayoutInflater inflater;\n\n        DotAdapter(Context context) {\n            this.inflater = LayoutInflater.from(context);\n        }\n\n        void updateList(RealmResults<Dot> dots) {\n            this.dots = dots;\n            notifyDataSetChanged();\n        }\n\n        @Override\n        public int getCount() {\n            return dots.size();\n        }\n\n        @Override\n        public Dot getItem(int i) {\n            return dots.get(i);\n        }\n\n        @Override\n        public long getItemId(int i) {\n            return i;\n        }\n\n        @Override\n        public View getView(int i, View view, ViewGroup viewGroup) {\n            if (view == null) {\n                view = inflater.inflate(android.R.layout.simple_list_item_1, viewGroup, false);\n                ViewHolder viewHolder = new ViewHolder(view);\n                view.setTag(viewHolder);\n            }\n            ViewHolder vh = (ViewHolder) view.getTag();\n            vh.text.setText(view.getResources().getString(R.string.coordinate, getItem(i).getX(), getItem(i).getY()));\n            return view;\n        }\n\n        private class ViewHolder {\n            TextView text;\n\n            ViewHolder(View view) {\n                text = (TextView) view.findViewById(android.R.id.text1);\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "examples/threadExample/src/main/java/io/realm/examples/threads/AsyncTaskFragment.java",
    "content": "/*\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\npackage io.realm.examples.threads;\n\nimport android.os.AsyncTask;\nimport android.os.Bundle;\nimport android.support.v4.app.Fragment;\nimport android.util.Log;\nimport android.view.LayoutInflater;\nimport android.view.View;\nimport android.view.ViewGroup;\nimport android.widget.LinearLayout;\nimport android.widget.ProgressBar;\nimport android.widget.SeekBar;\nimport android.widget.TextView;\n\nimport java.lang.ref.WeakReference;\n\nimport io.realm.Realm;\nimport io.realm.examples.threads.model.Score;\n\n/**\n * This fragment demonstrates how Realm can work with AsyncTasks.\n */\npublic class AsyncTaskFragment extends Fragment {\n\n    private static final String TAG = AsyncTaskFragment.class.getName();\n    private static final int TEST_OBJECTS = 100;\n\n    private LinearLayout logsView;\n    private ProgressBar progressView;\n    private ImportAsyncTask asyncTask;\n\n    @Override\n    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {\n        View rootView = inflater.inflate(R.layout.fragment_asynctask, container, false);\n        logsView = (LinearLayout) rootView.findViewById(R.id.logs);\n        progressView = (ProgressBar) rootView.findViewById(R.id.progressBar);\n        progressView.setVisibility(View.GONE);\n        rootView.findViewById(R.id.start_button).setOnClickListener(new View.OnClickListener() {\n            @Override\n            public void onClick(View v) {\n                if (asyncTask != null) {\n                    asyncTask.cancel(true);\n                }\n\n                asyncTask = new ImportAsyncTask(AsyncTaskFragment.this);\n                asyncTask.execute();\n            }\n        });\n\n        return rootView;\n    }\n\n    @Override\n    public void onStop() {\n        super.onStop();\n        if (asyncTask != null) {\n            asyncTask.cancel(false);\n        }\n    }\n\n    private void showStatus(String txt) {\n        Log.i(TAG, txt);\n        TextView tv = new TextView(getActivity());\n        tv.setText(txt);\n        tv.setTextColor(getResources().getColor(android.R.color.white));\n        logsView.addView(tv);\n    }\n\n    // ASyncTask that imports Realm data while providing progress and returns the value of an\n    // aggregate function in the end.\n    //\n    // Note:\n    // doInBackground() runs in its own background thread while all other methods are executed on the\n    // UI thread. This means that it is not possible to reuse RealmObjects or RealmResults created\n    // in doInBackground() in the other methods. Nor is it possible to use RealmObjects as Progress\n    // or Result objects.\n    private static class ImportAsyncTask extends AsyncTask<Void, Integer, Integer> {\n\n        private final WeakReference<AsyncTaskFragment> fragmentRef;\n\n        ImportAsyncTask(AsyncTaskFragment outerFragment) {\n            fragmentRef = new WeakReference<AsyncTaskFragment>(outerFragment);\n        }\n\n        @Override\n        protected Integer doInBackground(Void... params) {\n            Realm realm = Realm.getDefaultInstance();\n\n            realm.executeTransaction(new Realm.Transaction() {\n                @Override\n                public void execute(Realm realm) {\n                    realm.delete(Score.class);\n                    for (int i = 0; i < TEST_OBJECTS; i++) {\n                        if (isCancelled()) break;\n                        Score score = realm.createObject(Score.class);\n                        score.setName(\"Name\" + i);\n                        score.setScore(i);\n                    }\n                }\n            });\n\n            Number sum = realm.where(Score.class).sum(\"score\");\n            realm.close();\n            return sum.intValue();\n        }\n\n        @Override\n        protected void onPreExecute() {\n            final AsyncTaskFragment fragment = fragmentRef.get();\n            if (fragment == null || fragment.isDetached()) {\n                cancel(false);\n                return;\n            }\n            fragment.logsView.removeAllViews();\n            fragment.progressView.setVisibility(View.VISIBLE);\n            fragment.showStatus(\"Starting import\");\n        }\n\n        @Override\n        protected void onPostExecute(Integer sum) {\n            final AsyncTaskFragment fragment = fragmentRef.get();\n            if (fragment == null || fragment.isDetached()) {\n                return;\n            }\n            fragment.progressView.setVisibility(View.GONE);\n            fragment.showStatus(TEST_OBJECTS + \" objects imported.\");\n            fragment.showStatus(\"The total score is : \" + sum);\n        }\n    }\n}\n"
  },
  {
    "path": "examples/threadExample/src/main/java/io/realm/examples/threads/MyApplication.java",
    "content": "/*\n * Copyright 2015 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\npackage io.realm.examples.threads;\n\nimport android.app.Application;\n\nimport io.realm.Realm;\nimport io.realm.RealmConfiguration;\n\npublic class MyApplication extends Application {\n\n    @Override\n    public void onCreate() {\n        super.onCreate();\n\n        // Configure Realm for the application\n        Realm.init(this);\n        RealmConfiguration realmConfiguration = new RealmConfiguration.Builder()\n                .allowWritesOnUiThread(true)\n                .allowQueriesOnUiThread(true)\n                .build();\n        Realm.deleteRealm(realmConfiguration); // Clean slate\n        Realm.setDefaultConfiguration(realmConfiguration); // Make this Realm the default\n    }\n}\n"
  },
  {
    "path": "examples/threadExample/src/main/java/io/realm/examples/threads/PassingObjectsFragment.java",
    "content": "/*\n * Copyright 2015 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\npackage io.realm.examples.threads;\n\n\nimport android.content.Intent;\nimport android.os.Bundle;\nimport android.support.annotation.Nullable;\nimport android.support.v4.app.Fragment;\nimport android.view.LayoutInflater;\nimport android.view.View;\nimport android.view.ViewGroup;\nimport android.widget.TextView;\n\nimport java.util.UUID;\n\nimport io.realm.Realm;\nimport io.realm.examples.threads.model.Person;\n\npublic class PassingObjectsFragment extends Fragment {\n\n    private TextView textContent;\n\n    private Realm realm;\n    private Person person;\n\n    @Nullable\n    @Override\n    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {\n        View view = inflater.inflate(R.layout.fragment_passing_objects, container, false);\n        textContent = (TextView) view.findViewById(R.id.text_content);\n\n        setListeners(view);\n        return view;\n    }\n\n    /**\n     * Sets the click listeners on the three buttons.\n     *\n     * RealmObjects are thread confined, therefore they cannot be passed through an intent. We\n     * recommend using an object identifier and passing that value through the intent. The\n     * receiving Android component will then obtain that value, open the Realm and query for\n     * that object.\n     *\n     * Below, each {@link android.view.View.OnClickListener} builds an {@link Intent} that\n     * accepts the {@link Person#getId()} value as a string extra. This is the value that will\n     * be retrieved in the receiving Android components ({@link ReceivingActivity},\n     * {@link ReceivingService} and {@link WakefulReceivingBroadcastReceiver}.\n     *\n     * @param view The view where the buttons are located.\n     */\n    private void setListeners(View view) {\n        view.findViewById(R.id.start_activity).setOnClickListener(new View.OnClickListener() {\n            @Override\n            public void onClick(View v) {\n                Intent intent = new Intent(getActivity(), ReceivingActivity.class);\n                intent.putExtra(\"person_id\", person.getId());\n                startActivity(intent);\n            }\n        });\n\n        view.findViewById(R.id.start_intent_service).setOnClickListener(new View.OnClickListener() {\n            @Override\n            public void onClick(View v) {\n                Intent intent = new Intent(getActivity(), ReceivingService.class);\n                intent.putExtra(\"person_id\", person.getId());\n                getActivity().startService(intent);\n            }\n        });\n\n        view.findViewById(R.id.start_receiver).setOnClickListener(new View.OnClickListener() {\n            @Override\n            public void onClick(View v) {\n                Intent intent = new Intent(getActivity(), WakefulReceivingBroadcastReceiver.class);\n                intent.putExtra(\"person_id\", person.getId());\n                getActivity().sendBroadcast(intent);\n            }\n        });\n    }\n\n    @Override\n    public void onActivityCreated(Bundle savedInstanceState) {\n        super.onActivityCreated(savedInstanceState);\n\n        realm = Realm.getDefaultInstance();\n        realm.executeTransaction(new Realm.Transaction() {\n            @Override\n            public void execute(Realm realm) {\n                person = realm.createObject(Person.class, UUID.randomUUID().toString());\n                person.setName(\"Jane\");\n                person.setAge(42);\n            }\n        });\n        textContent.setText(person.toString());\n    }\n\n    @Override\n    public void onDestroy() {\n        super.onDestroy();\n        realm.executeTransaction(new Realm.Transaction() {\n            @Override\n            public void execute(Realm realm) {\n                realm.delete(Person.class);\n            }\n        });\n        // Clear out all Person instances.\n        realm.close();\n    }\n}\n\n"
  },
  {
    "path": "examples/threadExample/src/main/java/io/realm/examples/threads/ReceivingActivity.java",
    "content": "/*\n * Copyright 2015 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\npackage io.realm.examples.threads;\n\nimport android.os.Bundle;\nimport android.support.v7.app.AppCompatActivity;\nimport android.widget.TextView;\n\nimport io.realm.Realm;\nimport io.realm.examples.threads.model.Person;\n\npublic class ReceivingActivity extends AppCompatActivity {\n\n    private Realm realm;\n\n    @Override\n    protected void onCreate(Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n        setContentView(R.layout.activity_receiving);\n\n        realm = Realm.getDefaultInstance();\n\n        if (getIntent() != null) {\n            String personId = getIntent().getStringExtra(\"person_id\");\n            if (personId != null) {\n                Person person = realm.where(Person.class).equalTo(\"id\", personId).findFirst();\n                ((TextView) findViewById(R.id.received_content)).setText(String.format(\"Received person_id and loaded: %s\", person.toString()));\n            }\n        }\n    }\n\n    @Override\n    protected void onDestroy() {\n        super.onDestroy();\n        realm.close();\n    }\n}\n"
  },
  {
    "path": "examples/threadExample/src/main/java/io/realm/examples/threads/ReceivingService.java",
    "content": "/*\n * Copyright 2015 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\npackage io.realm.examples.threads;\n\nimport android.app.IntentService;\nimport android.content.Intent;\nimport android.os.Handler;\nimport android.widget.Toast;\n\nimport io.realm.Realm;\nimport io.realm.examples.threads.model.Person;\n\npublic class ReceivingService extends IntentService {\n\n    public ReceivingService() {\n        super(\"ReceivingService\");\n    }\n\n    @Override\n    protected void onHandleIntent(Intent intent) {\n        if (intent.getExtras() != null) {\n            String personId = intent.getStringExtra(\"person_id\");\n            Realm realm = Realm.getDefaultInstance();\n            Person person = realm.where(Person.class).equalTo(\"id\", personId).findFirst();\n            final String output = person.toString();\n            new Handler(getMainLooper()).post(new Runnable() {\n                @Override\n                public void run() {\n                    Toast.makeText(getApplicationContext(), \"Loaded Person from intent service: \" + output, Toast.LENGTH_LONG).show();\n                }\n            });\n            realm.close();\n        }\n    }\n}\n"
  },
  {
    "path": "examples/threadExample/src/main/java/io/realm/examples/threads/ThreadExampleActivity.java",
    "content": "/*\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\npackage io.realm.examples.threads;\n\nimport android.os.Bundle;\nimport android.support.v4.app.Fragment;\nimport android.support.v4.app.FragmentManager;\nimport android.support.v4.app.FragmentPagerAdapter;\nimport android.support.v4.app.FragmentTransaction;\nimport android.support.v4.view.ViewPager;\nimport android.support.v7.app.ActionBar;\nimport android.support.v7.app.AppCompatActivity;\n\nimport java.util.Locale;\n\n\npublic class ThreadExampleActivity extends AppCompatActivity implements android.support.v7.app.ActionBar.TabListener {\n\n    private ViewPager viewPager;\n\n    @Override\n    protected void onCreate(Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n        setContentView(R.layout.activity_main);\n\n        // Set up the action bar.\n        final android.support.v7.app.ActionBar actionBar = getSupportActionBar();\n        actionBar.setNavigationMode(android.support.v7.app.ActionBar.NAVIGATION_MODE_TABS);\n\n        SectionsPagerAdapter pageAdapter = new SectionsPagerAdapter(getSupportFragmentManager());\n        viewPager = (ViewPager) findViewById(R.id.pager);\n        viewPager.setAdapter(pageAdapter);\n\n        viewPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {\n            @Override\n            public void onPageSelected(int position) {\n                actionBar.setSelectedNavigationItem(position);\n            }\n        });\n\n        for (int i = 0; i < pageAdapter.getCount(); i++) {\n            getSupportActionBar().addTab(getSupportActionBar().newTab()\n                    .setText(pageAdapter.getPageTitle(i))\n                    .setTabListener(this));\n        }\n    }\n\n    @Override\n    public void onTabSelected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {\n        viewPager.setCurrentItem(tab.getPosition());\n    }\n\n    @Override\n    public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {\n\n    }\n\n    @Override\n    public void onTabReselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {\n\n    }\n\n\n    public class SectionsPagerAdapter extends FragmentPagerAdapter {\n\n        public SectionsPagerAdapter(FragmentManager fm) {\n            super(fm);\n        }\n\n        @Override\n        public Fragment getItem(int position) {\n            switch(position) {\n                case 0: return new ThreadFragment();\n                case 1: return new AsyncTaskFragment();\n                case 2: return new AsyncQueryFragment();\n                case 3: return new PassingObjectsFragment();\n                default: return null;\n            }\n        }\n\n        @Override\n        public int getCount() {\n            return 4;\n        }\n\n        @Override\n        public CharSequence getPageTitle(int position) {\n            Locale l = Locale.getDefault();\n            switch (position) {\n                case 0: return getString(R.string.title_section1).toUpperCase(l);\n                case 1: return getString(R.string.title_section2).toUpperCase(l);\n                case 2: return getString(R.string.title_section3).toUpperCase(l);\n                case 3: return getString(R.string.title_section4).toUpperCase(l);\n                default: return null;\n            }\n        }\n    }\n}"
  },
  {
    "path": "examples/threadExample/src/main/java/io/realm/examples/threads/ThreadFragment.java",
    "content": "/*\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\npackage io.realm.examples.threads;\n\nimport android.os.Bundle;\nimport android.os.SystemClock;\nimport android.support.v4.app.Fragment;\nimport android.view.LayoutInflater;\nimport android.view.Menu;\nimport android.view.MenuInflater;\nimport android.view.MenuItem;\nimport android.view.View;\nimport android.view.ViewGroup;\n\nimport java.util.Random;\n\nimport io.realm.Realm;\nimport io.realm.RealmChangeListener;\nimport io.realm.examples.threads.model.Dot;\nimport io.realm.examples.threads.widget.DotsView;\n\n/**\n * This fragment demonstrates how Realm can interact with a background thread.\n */\npublic class ThreadFragment extends Fragment {\n\n    private Realm realm;\n    private Random random = new Random();\n    private Thread backgroundThread;\n    private DotsView dotsView;\n\n    // Realm change listener that refreshes the UI when there is changes to Realm.\n    private RealmChangeListener<Realm> realmListener = new RealmChangeListener<Realm>() {\n        @Override\n        public void onChange(Realm realm) {\n            dotsView.invalidate();\n        }\n    };\n\n    @Override\n    public void onCreate(Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n        setHasOptionsMenu(true);\n    }\n\n    @Override\n    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {\n        View rootView = inflater.inflate(R.layout.fragment_thread, container, false);\n        dotsView = (DotsView) rootView.findViewById(R.id.dots);\n        return rootView;\n    }\n\n    @Override\n    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {\n        super.onCreateOptionsMenu(menu, inflater);\n        inflater.inflate(R.menu.menu_backgroundthread, menu);\n    }\n\n    @Override\n    public boolean onOptionsItemSelected(MenuItem item) {\n\n        switch(item.getItemId()) {\n            case R.id.action_add_dot:\n                // Add blue dot from the UI thread\n                realm.executeTransaction(new Realm.Transaction() {\n                    @Override\n                    public void execute(Realm realm) {\n                        Dot dot = realm.createObject(Dot.class);\n                        dot.setX(random.nextInt(100));\n                        dot.setY(random.nextInt(100));\n                        dot.setColor(getResources().getColor(R.color.realm_blue));\n                    }\n                });\n                return true;\n\n            case R.id.action_clear:\n                realm.executeTransaction(new Realm.Transaction() {\n                    @Override\n                    public void execute(Realm realm) {\n                        realm.delete(Dot.class);\n                    }\n                });\n                return true;\n\n            default:\n                return super.onOptionsItemSelected(item);\n        }\n    }\n\n    @Override\n    public void onStart() {\n        super.onStart();\n        // Create Realm instance for the UI thread\n        realm = Realm.getDefaultInstance();\n\n        // Create a RealmQuery on the UI thread and send the results to the custom view. The\n        // RealmResults will automatically be updated whenever the Realm data is changed.\n        // We still need to invalidate the UI to show the changes however. See the RealmChangeListener.\n        //\n        // Note that the query gets updated by rerunning it on the thread it was\n        // created. This can negatively effect frame rates if it is a complicated query or a very\n        // large data set.\n        dotsView.setRealmResults(realm.where(Dot.class).findAll());\n    }\n\n    @Override\n    public void onResume() {\n        super.onResume();\n\n        // Enable UI refresh while the fragment is active.\n        realm.addChangeListener(realmListener);\n\n        // Create background thread that add a new dot every 0.5 second.\n        backgroundThread = new Thread() {\n\n            @Override\n            public void run() {\n                // Realm instances cannot be shared between threads, so we need to create a new\n                // instance on the background thread.\n                final int redColor = getResources().getColor(R.color.realm_red);\n                final Realm backgroundThreadRealm = Realm.getDefaultInstance();\n                while (!backgroundThread.isInterrupted()) {\n                    backgroundThreadRealm.executeTransaction(new Realm.Transaction() {\n                        @Override\n                        public void execute(Realm realm) {\n                            // Add red dot from the background thread\n                            Dot dot = backgroundThreadRealm.createObject(Dot.class);\n                            dot.setX(random.nextInt(100));\n                            dot.setY(random.nextInt(100));\n                            dot.setColor(redColor);\n                        }\n                    });\n\n                    // Wait 0.5 sec. before adding the next dot.\n                    SystemClock.sleep(500);\n                }\n\n                // Also close Realm instances used in background threads.\n                backgroundThreadRealm.close();\n            }\n        };\n        backgroundThread.start();\n    }\n\n    @Override\n    public void onPause() {\n        super.onPause();\n\n        // Disable UI refresh while the fragment is no longer active.\n        realm.removeChangeListener(realmListener);\n        backgroundThread.interrupt();\n    }\n\n    @Override\n    public void onStop() {\n        super.onStop();\n        // Remember to close the Realm instance when done with it.\n        dotsView.setRealmResults(null);\n        realm.close();\n    }\n}\n"
  },
  {
    "path": "examples/threadExample/src/main/java/io/realm/examples/threads/WakefulReceivingBroadcastReceiver.java",
    "content": "/*\n * Copyright 2015 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\npackage io.realm.examples.threads;\n\nimport android.content.Context;\nimport android.content.Intent;\nimport android.support.v4.content.WakefulBroadcastReceiver;\n\npublic class WakefulReceivingBroadcastReceiver extends WakefulBroadcastReceiver {\n    @Override\n    public void onReceive(Context context, Intent intent) {\n        // Do not do work in onReceive as it can cause an ANR. Perform work in a\n        // service as to avoid the ANR.\n        Intent serviceIntent = new Intent(context, WakefulReceivingService.class);\n        serviceIntent.putExtra(\"person_id\", intent.getStringExtra(\"person_id\"));\n        startWakefulService(context, serviceIntent);\n    }\n}\n"
  },
  {
    "path": "examples/threadExample/src/main/java/io/realm/examples/threads/WakefulReceivingService.java",
    "content": "/*\n * Copyright 2015 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\npackage io.realm.examples.threads;\n\nimport android.app.IntentService;\nimport android.content.Intent;\nimport android.os.Handler;\nimport android.support.v4.content.WakefulBroadcastReceiver;\nimport android.widget.Toast;\n\nimport io.realm.Realm;\nimport io.realm.examples.threads.model.Person;\n\npublic class WakefulReceivingService extends IntentService {\n\n    public WakefulReceivingService() {\n        super(\"WakefulReceivingService\");\n    }\n\n    @Override\n    protected void onHandleIntent(Intent intent) {\n        if (intent.getExtras() != null) {\n            String personId = intent.getStringExtra(\"person_id\");\n            Realm realm = Realm.getDefaultInstance();\n            Person person = realm.where(Person.class).equalTo(\"id\", personId).findFirst();\n            final String output = person.toString();\n            new Handler(getMainLooper()).post(new Runnable() {\n                @Override\n                public void run() {\n                    Toast.makeText(getApplicationContext(), \"Loaded Person from broadcast-receiver->intent-service: \" + output, Toast.LENGTH_LONG).show();\n                }\n            });\n            realm.close();\n        }\n\n        // All the work is done, release the wake locks/etc\n        WakefulBroadcastReceiver.completeWakefulIntent(intent);\n    }\n}\n"
  },
  {
    "path": "examples/threadExample/src/main/java/io/realm/examples/threads/model/Dot.java",
    "content": "/*\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\npackage io.realm.examples.threads.model;\n\nimport io.realm.RealmObject;\n\npublic class Dot extends RealmObject{\n\n    private int x;\n    private int y;\n    private int color;\n    private long timestamp;\n\n    public int getX() {\n        return x;\n    }\n\n    public void setX(int x) {\n        this.x = x;\n    }\n\n    public int getY() {\n        return y;\n    }\n\n    public void setY(int y) {\n        this.y = y;\n    }\n\n    public int getColor() {\n        return color;\n    }\n\n    public void setColor(int color) {\n        this.color = color;\n    }\n\n    public long getTimestamp() {\n        return timestamp;\n    }\n\n    public void setTimestamp(long timestamp) {\n        this.timestamp = timestamp;\n    }\n}\n"
  },
  {
    "path": "examples/threadExample/src/main/java/io/realm/examples/threads/model/Person.java",
    "content": "/*\n * Copyright 2015 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\npackage io.realm.examples.threads.model;\n\nimport io.realm.RealmObject;\nimport io.realm.annotations.PrimaryKey;\n\npublic class Person extends RealmObject {\n\n    @PrimaryKey\n    private String id;\n    private String name;\n    private int age;\n\n\n    public String getId() {\n        return id;\n    }\n\n    public void setId(String id) {\n        this.id = id;\n    }\n\n    public String getName() {\n        return name;\n    }\n\n    public void setName(String name) {\n        this.name = name;\n    }\n\n    public int getAge() {\n        return age;\n    }\n\n    public void setAge(int age) {\n        this.age = age;\n    }\n}\n"
  },
  {
    "path": "examples/threadExample/src/main/java/io/realm/examples/threads/model/Score.java",
    "content": "/*\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\npackage io.realm.examples.threads.model;\n\nimport io.realm.RealmObject;\n\npublic class Score extends RealmObject {\n\n    private String name;\n    private int score;\n\n    public String getName() {\n        return name;\n    }\n\n    public void setName(String name) {\n        this.name = name;\n    }\n\n    public int getScore() {\n        return score;\n    }\n\n    public void setScore(int score) {\n        this.score = score;\n    }\n}\n"
  },
  {
    "path": "examples/threadExample/src/main/java/io/realm/examples/threads/widget/DotsView.java",
    "content": "/*\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\npackage io.realm.examples.threads.widget;\n\nimport android.content.Context;\nimport android.graphics.Canvas;\nimport android.graphics.Color;\nimport android.graphics.Paint;\nimport android.util.AttributeSet;\nimport android.view.View;\n\nimport io.realm.RealmResults;\nimport io.realm.examples.threads.model.Dot;\n\n/**\n * Custom view that plot (x,y) coordinates from a RealmQuery\n */\npublic class DotsView extends View {\n\n    // RealmResults will automatically be up to date.\n    private RealmResults<Dot> results;\n\n    private Paint circlePaint;\n    private float circleRadius;\n    private float pixelsPrWidth;\n    private float pixelsPrHeight;\n\n\n    public DotsView(Context context) {\n        super(context);\n        init();\n    }\n\n    public DotsView(Context context, AttributeSet attrs) {\n        super(context, attrs);\n        init();\n    }\n\n    public DotsView(Context context, AttributeSet attrs, int defStyleAttr) {\n        super(context, attrs, defStyleAttr);\n        init();\n    }\n\n    private void init() {\n        circlePaint = new Paint(Paint.ANTI_ALIAS_FLAG);\n        circlePaint.setStyle(Paint.Style.FILL);\n        circlePaint.setColor(Color.RED);\n        circleRadius = 10;\n    }\n\n    public void setRealmResults(RealmResults results) {\n        this.results = results;\n        invalidate();\n    }\n\n    @Override\n    protected void onSizeChanged(int w, int h, int oldw, int oldh) {\n        super.onSizeChanged(w, h, oldw, oldh);\n        pixelsPrWidth = w/100f;\n        pixelsPrHeight = h/100f;\n    }\n\n    @Override\n    protected void onDraw(Canvas canvas) {\n        super.onDraw(canvas);\n        if (results == null) {\n            return;\n        }\n        canvas.drawColor(Color.TRANSPARENT);\n        for (Dot dot : results) {\n            circlePaint.setColor(dot.getColor());\n            canvas.drawCircle(dot.getX()*pixelsPrWidth, dot.getY()*pixelsPrHeight, circleRadius, circlePaint);\n        }\n    }\n}\n"
  },
  {
    "path": "examples/threadExample/src/main/res/layout/activity_main.xml",
    "content": "<android.support.v4.view.ViewPager xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:id=\"@+id/pager\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    tools:context=\".ThreadExampleActivity\" />\n"
  },
  {
    "path": "examples/threadExample/src/main/res/layout/activity_receiving.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<RelativeLayout\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:paddingBottom=\"@dimen/activity_vertical_margin\"\n    android:paddingLeft=\"@dimen/activity_horizontal_margin\"\n    android:paddingRight=\"@dimen/activity_horizontal_margin\"\n    android:paddingTop=\"@dimen/activity_vertical_margin\"\n    tools:context=\"io.realm.examples.threads.ReceivingActivity\">\n\n    <TextView\n        android:id=\"@+id/received_content\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:textColor=\"@android:color/white\"/>\n\n</RelativeLayout>\n"
  },
  {
    "path": "examples/threadExample/src/main/res/layout/fragment_async_query.xml",
    "content": "<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n                xmlns:tools=\"http://schemas.android.com/tools\"\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"match_parent\"\n                android:orientation=\"vertical\"\n                android:paddingBottom=\"@dimen/activity_vertical_margin\"\n                android:paddingLeft=\"@dimen/activity_horizontal_margin\"\n                android:paddingRight=\"@dimen/activity_horizontal_margin\"\n                android:paddingTop=\"@dimen/activity_vertical_margin\"\n                tools:context=\".MainActivity$PlaceholderFragment\">\n\n    <Button\n        android:id=\"@+id/translate_button\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:text=\"@string/translate\"/>\n\n    <ListView\n        android:id=\"@android:id/list\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:layout_marginTop=\"16dp\">\n    </ListView>\n\n\n</LinearLayout>\n"
  },
  {
    "path": "examples/threadExample/src/main/res/layout/fragment_asynctask.xml",
    "content": "<RelativeLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n                xmlns:tools=\"http://schemas.android.com/tools\"\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"match_parent\"\n                android:orientation=\"vertical\"\n                android:paddingBottom=\"@dimen/activity_vertical_margin\"\n                android:paddingLeft=\"@dimen/activity_horizontal_margin\"\n                android:paddingRight=\"@dimen/activity_horizontal_margin\"\n                android:paddingTop=\"@dimen/activity_vertical_margin\"\n                tools:context=\".MainActivity$PlaceholderFragment\">\n\n    <Button\n        android:id=\"@+id/start_button\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:layout_alignParentTop=\"true\"\n        android:text=\"@string/start\"/>\n\n    <LinearLayout\n        android:id=\"@+id/logs\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:layout_below=\"@id/start_button\"\n        android:layout_marginTop=\"16dp\"\n        android:orientation=\"vertical\">\n    </LinearLayout>\n\n    <ProgressBar\n        android:id=\"@+id/progressBar\"\n        style=\"?android:attr/progressBarStyleLarge\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:layout_centerInParent=\"true\"/>\n\n</RelativeLayout>\n"
  },
  {
    "path": "examples/threadExample/src/main/res/layout/fragment_passing_objects.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n              android:layout_width=\"match_parent\"\n              android:layout_height=\"match_parent\"\n              android:layout_margin=\"@dimen/activity_horizontal_margin\"\n              android:orientation=\"vertical\">\n\n    <TextView\n        android:id=\"@+id/text_content\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:textColor=\"@android:color/white\"/>\n\n    <Button\n        android:id=\"@+id/start_activity\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:text=\"@string/start_activity\"/>\n\n    <Button\n        android:id=\"@+id/start_intent_service\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:text=\"@string/start_intent_service\"/>\n\n    <Button\n        android:id=\"@+id/start_receiver\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:text=\"@string/start_receiver\"/>\n\n</LinearLayout>"
  },
  {
    "path": "examples/threadExample/src/main/res/layout/fragment_thread.xml",
    "content": "<RelativeLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    tools:context=\".MainActivity$PlaceholderFragment\">\n\n    <io.realm.examples.threads.widget.DotsView\n        android:id=\"@+id/dots\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\" />\n\n</RelativeLayout>\n"
  },
  {
    "path": "examples/threadExample/src/main/res/menu/menu_backgroundthread.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?><!--\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<menu xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\">\n\n    <item\n        android:id=\"@+id/action_add_dot\"\n        android:title=\"@string/add_dot\"\n        android:icon=\"@android:drawable/ic_menu_add\"\n        app:showAsAction=\"ifRoom\" />\n\n    <item\n        android:id=\"@+id/action_clear\"\n        android:title=\"@string/clear_dots\"\n        android:icon=\"@android:drawable/ic_menu_delete\"\n        app:showAsAction=\"ifRoom\" />\n\n</menu>"
  },
  {
    "path": "examples/threadExample/src/main/res/values/colors.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <color name=\"screen_background\">#333333</color>\n    <color name=\"realm_red\">#f0727d</color>\n    <color name=\"realm_blue\">#428bca</color>\n</resources>"
  },
  {
    "path": "examples/threadExample/src/main/res/values/dimens.xml",
    "content": "<resources>\n    <!-- Default screen margins, per the Android Design guidelines. -->\n    <dimen name=\"activity_horizontal_margin\">16dp</dimen>\n    <dimen name=\"activity_vertical_margin\">16dp</dimen>\n</resources>\n"
  },
  {
    "path": "examples/threadExample/src/main/res/values/strings.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n\n    <string name=\"app_name\">Thread example</string>\n    <string name=\"title_section1\">Threads</string>\n    <string name=\"title_section2\">AsyncTask</string>\n    <string name=\"title_section3\">Async Query</string>\n    <string name=\"add_dot\">Add blue dot</string>\n    <string name=\"clear_dots\">Clear dots</string>\n    <string name=\"translate\">Translate Dots</string>\n    <string name=\"start_activity\">Passing to Activity</string>\n    <string name=\"title_activity_receiving\">Receiving Activity</string>\n    <string name=\"title_section4\">Object Passing</string>\n    <string name=\"start_intent_service\">Passing to Intent Service</string>\n    <string name=\"start_receiver\">Passing To Receiver</string>\n    <string name=\"coordinate\">[X= %1$d Y= %2$d]</string>\n    <string name=\"start\">Start</string>\n\n</resources>\n"
  },
  {
    "path": "examples/threadExample/src/main/res/values/styles.xml",
    "content": "<resources>\n\n    <!-- Base application theme. -->\n    <style name=\"AppTheme\" parent=\"Theme.AppCompat.Light.DarkActionBar\">\n        <!-- Customize your theme here. -->\n        <item name=\"android:windowBackground\">@color/screen_background</item>\n    </style>\n\n</resources>\n"
  },
  {
    "path": "examples/unitTestExample/README.md",
    "content": "# Running The Tests\nRun them in Android Studio or run them via Gradle: \n\nInstrumentation Tests\n`./gradlew connectedCheck`\n\nUnit Tests\n`./gradlew test` \n\n# Troubleshooting\n\nDepending on what version of Java you have installed you may encounter the following errors: \n\n`initializationError(com.your.ClassHere): Bad <init> method call from inside of a branch`\n  \nor\n \n`Exception in thread \"main\" java.lang.annotation.AnnotationFormatError: Invalid default: public abstract java.lang.Class org.robolectric.annotation.Config.application()` \n\nThese issues manifest themselves because of changes to the Java bytecode verifier. \nA workaround is to set the `-noverify` flag on the the JVM. \n\n\nTypically, the tests can be run via the command line without fail, however, to get them to run in Android Studio you will need to perform the following steps in your run configurations in Android Studio:\n![Unit Test Config Settings](unittest-config-settings.png)\n\n[Source 1](http://stackoverflow.com/a/25428318/5210) [Source 2](https://code.google.com/p/powermock/issues/detail?id=504)"
  },
  {
    "path": "examples/unitTestExample/build.gradle",
    "content": "apply plugin: 'com.android.application'\napply plugin: 'realm-android'\n\nandroid {\n    compileSdkVersion rootProject.sdkVersion\n    buildToolsVersion rootProject.buildTools\n\n    defaultConfig {\n        applicationId 'io.realm.examples.unittesting'\n        targetSdkVersion rootProject.sdkVersion\n        minSdkVersion rootProject.minSdkVersion\n        versionCode 1\n        versionName \"1.0\"\n\n        // Needed for jUnit4 support.\n        testInstrumentationRunner \"android.support.test.runner.AndroidJUnitRunner\"\n    }\n\n    buildTypes {\n        release {\n            minifyEnabled true\n            signingConfig signingConfigs.debug\n        }\n        debug {\n            minifyEnabled false\n        }\n    }\n\n    compileOptions {\n        sourceCompatibility JavaVersion.VERSION_1_8\n        targetCompatibility JavaVersion.VERSION_1_8\n    }\n\n    testOptions {\n        unitTests {\n            includeAndroidResources = true\n        }\n    }\n}\n\n\ndependencies {\n    implementation 'com.android.support:appcompat-v7:27.1.1'\n\n    testImplementation 'io.reactivex.rxjava2:rxjava:2.1.13'\n\n    // Testing\n    testImplementation 'junit:junit:4.13.2'\n    // Seen quite many issues when bumping from 3.8 (due to AndroidX)\n    // 4.1 seems to be the only one not exibiting these. Some of the relevant links\n    // - https://github.com/robolectric/robolectric/issues/4015\n    // - https://github.com/roObolectric/robolectric/issues/5082\n    // - https://stackoverflow.com/questions/29072148/mockito-with-robolectric-classcastexception-occurred-when-creating-the-proxy/36720803\n    testImplementation \"org.robolectric:robolectric:4.6.1\"\n    testImplementation \"org.mockito:mockito-core:3.3.3\"\n    testImplementation 'org.robolectric:shadows-support-v4:3.2'\n\n    testImplementation \"org.powermock:powermock-module-junit4:2.0.9\"\n    testImplementation \"org.powermock:powermock-module-junit4-rule:2.0.9\"\n    testImplementation \"org.powermock:powermock-api-mockito2:2.0.9\"\n    testImplementation \"org.powermock:powermock-classloading-xstream:2.0.9\"\n\n\n    androidTestImplementation 'com.android.support.test:runner:1.0.2'\n    // Set this dependency to use JUnit 4 rules\n    androidTestImplementation 'com.android.support.test:rules:1.0.2'\n    // Set this dependency to build and run Espresso tests\n    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'\n}\n"
  },
  {
    "path": "examples/unitTestExample/gradle.properties",
    "content": "android.useAndroidX=true\n"
  },
  {
    "path": "examples/unitTestExample/lint.xml",
    "content": "<lint>\n    <issue id=\"AllowBackup\" severity=\"ignore\" />\n    <issue id=\"IconLauncherShape\" severity=\"ignore\" />\n    <issue id=\"IconMissingDensityFolder\" severity=\"ignore\" />\n    <issue id=\"GoogleAppIndexingWarning\" severity=\"ignore\" />\n    <issue id=\"InvalidPackage\" severity=\"ignore\" />\n    <issue id=\"WrongThread\" severity=\"ignore\" />\n</lint>\n"
  },
  {
    "path": "examples/unitTestExample/src/androidTest/java/io/realm/examples/unittesting/jUnit4ExampleTest.java",
    "content": "/*\n * Copyright 2015 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\npackage io.realm.examples.unittesting;\n\n\nimport android.support.test.rule.ActivityTestRule;\nimport android.support.test.runner.AndroidJUnit4;\n\nimport org.junit.Rule;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\n\nimport static android.support.test.espresso.Espresso.onView;\nimport static android.support.test.espresso.assertion.ViewAssertions.matches;\nimport static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;\nimport static android.support.test.espresso.matcher.ViewMatchers.withText;\n\n@RunWith(AndroidJUnit4.class)\npublic class jUnit4ExampleTest {\n\n    @Rule\n    public ActivityTestRule<ExampleActivity> mActivityRule = new ActivityTestRule<>(ExampleActivity.class);\n\n    @Test\n    public void testShouldBeAbleToLaunchActivityAndSeeRealmResults() {\n        onView(withText(\"John Senior got older: 89\")).check(matches(isDisplayed()));\n    }\n}\n"
  },
  {
    "path": "examples/unitTestExample/src/main/AndroidManifest.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    package=\"io.realm.examples.unittesting\" >\n\n    <application\n        android:allowBackup=\"true\"\n        android:icon=\"@mipmap/ic_launcher\"\n        android:label=\"@string/app_name\"\n        android:theme=\"@style/AppTheme\" >\n        <activity\n            android:name=\".ExampleActivity\"\n            android:label=\"@string/app_name\" >\n            <intent-filter>\n                <action android:name=\"android.intent.action.MAIN\" />\n\n                <category android:name=\"android.intent.category.LAUNCHER\" />\n            </intent-filter>\n        </activity>\n    </application>\n\n</manifest>\n"
  },
  {
    "path": "examples/unitTestExample/src/main/java/io/realm/examples/unittesting/ExampleActivity.java",
    "content": "/*\n * Copyright 2015 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\npackage io.realm.examples.unittesting;\n\nimport android.os.AsyncTask;\nimport android.os.Bundle;\nimport android.support.v7.app.AppCompatActivity;\nimport android.util.Log;\nimport android.widget.LinearLayout;\nimport android.widget.TextView;\n\nimport io.realm.Realm;\nimport io.realm.RealmConfiguration;\nimport io.realm.RealmResults;\nimport io.realm.examples.unittesting.model.Person;\n\npublic class ExampleActivity extends AppCompatActivity {\n\n    public static final String TAG = ExampleActivity.class.getName();\n    private LinearLayout rootLayout = null;\n\n    private Realm realm;\n\n    @Override\n    protected void onCreate(Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n        Realm.init(getApplicationContext());\n        setContentView(R.layout.activity_example);\n        rootLayout = findViewById(R.id.container);\n        rootLayout.removeAllViews();\n\n        // Open the default Realm for the UI thread.\n        RealmConfiguration conf = new RealmConfiguration\n                .Builder()\n                .allowWritesOnUiThread(true)\n                .allowQueriesOnUiThread(true)\n                .build();\n        realm = Realm.getInstance(conf);\n\n        // Clean up from previous run\n        cleanUp();\n\n        // Small operation that is ok to run on the main thread\n        basicCRUD(realm);\n\n        // More complex operations can be executed on another thread.\n        AsyncTask<Void, Void, String> foo = new AsyncTask<Void, Void, String>() {\n            @Override\n            protected String doInBackground(Void... voids) {\n                String info = \"\";\n                info += complexQuery();\n                return info;\n            }\n\n            @Override\n            protected void onPostExecute(String result) {\n                showStatus(result);\n            }\n        };\n\n        foo.execute();\n\n        findViewById(R.id.clean_up).setOnClickListener(view -> {\n            view.setEnabled(false);\n            Log.d(\"TAG\", \"clean up\");\n            cleanUp();\n            view.setEnabled(true);\n        });\n    }\n\n    private void cleanUp() {\n        // Delete all persons\n        realm.executeTransaction(r -> r.delete(Person.class));\n    }\n\n    @Override\n    protected void onDestroy() {\n        super.onDestroy();\n        realm.close(); // Remember to close Realm when done.\n    }\n\n    private void showStatus(String txt) {\n        Log.i(TAG, txt);\n        TextView tv = new TextView(this);\n        tv.setText(txt);\n        rootLayout.addView(tv);\n    }\n\n    private void basicCRUD(Realm realm) {\n        showStatus(\"Perform basic Create/Read/Update/Delete (CRUD) operations...\");\n\n        // All writes must be wrapped in a transaction to facilitate safe multi threading\n        realm.executeTransaction(r -> {\n            // Add a person\n            Person person = r.createObject(Person.class);\n            person.setId(1);\n            person.setName(\"John Young\");\n            person.setAge(14);\n        });\n\n        // Find the first person (no query conditions) and read a field\n        final Person person = realm.where(Person.class).findFirst();\n        showStatus(person.getName() + \":\" + person.getAge());\n\n        // Update person in a transaction\n        realm.executeTransaction(r -> {\n            person.setName(\"John Senior\");\n            person.setAge(89);\n        });\n\n        showStatus(person.getName() + \" got older: \" + person.getAge());\n\n        // Add two more people\n        realm.executeTransaction(r -> {\n            Person jane = r.createObject(Person.class);\n            jane.setName(\"Jane\");\n            jane.setAge(27);\n\n            Person doug = r.createObject(Person.class);\n            doug.setName(\"Robert\");\n            doug.setAge(42);\n        });\n\n        RealmResults<Person> people = realm.where(Person.class).findAll();\n        showStatus(String.format(\"Found %s people\", people.size()));\n        for (Person p : people) {\n            showStatus(\"Found \" + p.getName());\n        }\n    }\n\n    private String complexQuery() {\n        String status = \"\\n\\nPerforming complex Query operation...\";\n\n        Realm realm = Realm.getDefaultInstance();\n        status += \"\\nNumber of people in the DB: \" + realm.where(Person.class).count();\n\n        // Find all persons where age between 1 and 99 and name begins with \"J\".\n        RealmResults<Person> results = realm.where(Person.class)\n                .between(\"age\", 1, 99)       // Notice implicit \"and\" operation\n                .beginsWith(\"name\", \"J\")\n                .findAll();\n        status += \"\\nNumber of people aged between 1 and 99 who's name start with 'J': \" + results.size();\n\n        realm.close();\n        return status;\n    }\n}\n"
  },
  {
    "path": "examples/unitTestExample/src/main/java/io/realm/examples/unittesting/model/Cat.java",
    "content": "/*\n * Copyright 2015 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\npackage io.realm.examples.unittesting.model;\n\nimport io.realm.RealmObject;\n\npublic class Cat extends RealmObject {\n    private String name;\n\n    public String getName() {\n        return name;\n    }\n\n    public void setName(String name) {\n        this.name = name;\n    }\n}\n"
  },
  {
    "path": "examples/unitTestExample/src/main/java/io/realm/examples/unittesting/model/Dog.java",
    "content": "/*\n * Copyright 2015 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\npackage io.realm.examples.unittesting.model;\n\nimport io.realm.RealmObject;\n\npublic class Dog extends RealmObject {\n    private String name;\n\n    public String getName() {\n        return name;\n    }\n\n    public void setName(String name) {\n        this.name = name;\n    }\n}\n"
  },
  {
    "path": "examples/unitTestExample/src/main/java/io/realm/examples/unittesting/model/Person.java",
    "content": "/*\n * Copyright 2015 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\npackage io.realm.examples.unittesting.model;\n\nimport io.realm.RealmList;\nimport io.realm.RealmObject;\nimport io.realm.annotations.Ignore;\n\n// Your model just have to extend RealmObject.\n// This will inherit an annotation which produces proxy getters and setters for all fields.\npublic class Person extends RealmObject {\n\n    // All fields are by default persisted.\n    private String name;\n    private int age;\n\n    // Other objects in a one-to-one relation must also subclass RealmObject\n    private Dog dog;\n\n    // One-to-many relations is simply a RealmList of the objects which also subclass RealmObject\n    private RealmList<Cat> cats;\n\n    // You can instruct Realm to ignore a field and not persist it.\n    @Ignore\n    private int tempReference;\n\n    private long id;\n\n    // The standard getters and setters your IDE generates are fine.\n    // Realm will overload them and code inside them is ignored.\n    // So if you prefer you can also just have empty abstract methods.\n\n    public String getName() {\n        return name;\n    }\n\n    public void setName(String name) {\n        this.name = name;\n    }\n\n    public int getAge() {\n        return age;\n    }\n\n    public void setAge(int age) {\n        this.age = age;\n    }\n\n    public Dog getDog() {\n        return dog;\n    }\n\n    public void setDog(Dog dog) {\n        this.dog = dog;\n    }\n\n    public RealmList<Cat> getCats() {\n        return cats;\n    }\n\n    public void setCats(RealmList<Cat> cats) {\n        this.cats = cats;\n    }\n\n    public int getTempReference() {\n        return tempReference;\n    }\n\n    public void setTempReference(int tempReference) {\n        this.tempReference = tempReference;\n    }\n\n    public long getId() {\n        return id;\n    }\n\n    public void setId(long id) {\n        this.id = id;\n    }\n}\n"
  },
  {
    "path": "examples/unitTestExample/src/main/java/io/realm/examples/unittesting/repository/DogRepository.java",
    "content": "/*\n * Copyright 2015 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\npackage io.realm.examples.unittesting.repository;\n\npublic interface DogRepository {\n    void createDog(String name);\n}\n"
  },
  {
    "path": "examples/unitTestExample/src/main/java/io/realm/examples/unittesting/repository/DogRepositoryImpl.java",
    "content": "/*\n * Copyright 2015 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\npackage io.realm.examples.unittesting.repository;\n\nimport io.realm.Realm;\nimport io.realm.examples.unittesting.model.Dog;\n\npublic class DogRepositoryImpl implements DogRepository {\n    @Override\n    public void createDog(final String name) {\n        Realm realm = Realm.getDefaultInstance();\n        realm.executeTransaction(r -> {\n            Dog dog = r.createObject(Dog.class);\n            dog.setName(name);\n        });\n        realm.close();\n    }\n}\n"
  },
  {
    "path": "examples/unitTestExample/src/main/res/layout/activity_example.xml",
    "content": "<ScrollView\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:paddingLeft=\"@dimen/activity_horizontal_margin\"\n    android:paddingRight=\"@dimen/activity_horizontal_margin\"\n    android:paddingTop=\"@dimen/activity_vertical_margin\"\n    android:paddingBottom=\"@dimen/activity_vertical_margin\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\">\n    <LinearLayout\n        android:orientation=\"vertical\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\">\n        <Button\n            android:id=\"@+id/clean_up\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"wrap_content\"\n            android:text=\"@string/clean_up\"\n            />\n        <TextView\n            android:gravity=\"center_horizontal\"\n            android:text=\"@string/label\"\n            android:textStyle=\"bold\"\n            android:textSize=\"18sp\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"wrap_content\"/>\n        <LinearLayout\n            android:id=\"@+id/container\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"match_parent\"\n            android:paddingTop=\"10sp\"\n            android:orientation=\"vertical\"\n            tools:context=\".RealmIntroExample\"/>\n    </LinearLayout>\n</ScrollView>\n"
  },
  {
    "path": "examples/unitTestExample/src/main/res/values/colors.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <color name=\"colorPrimary\">#3F51B5</color>\n    <color name=\"colorPrimaryDark\">#303F9F</color>\n    <color name=\"colorAccent\">#FF4081</color>\n</resources>"
  },
  {
    "path": "examples/unitTestExample/src/main/res/values/dimens.xml",
    "content": "<resources>\n    <!-- Default screen margins, per the Android Design guidelines. -->\n    <dimen name=\"activity_horizontal_margin\">16dp</dimen>\n    <dimen name=\"activity_vertical_margin\">16dp</dimen>\n</resources>\n"
  },
  {
    "path": "examples/unitTestExample/src/main/res/values/strings.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n\n    <string name=\"app_name\">Unit Test Example</string>\n    <string name=\"clean_up\">Clean Up</string>\n    <string name=\"label\">Status Output…</string>\n\n</resources>\n"
  },
  {
    "path": "examples/unitTestExample/src/main/res/values/styles.xml",
    "content": "<resources>\n\n    <style name=\"AppTheme\" parent=\"Theme.AppCompat.Light.DarkActionBar\">\n        <item name=\"colorPrimary\">@color/colorPrimary</item>\n        <item name=\"colorPrimaryDark\">@color/colorPrimaryDark</item>\n        <item name=\"colorAccent\">@color/colorAccent</item>\n    </style>\n\n</resources>\n"
  },
  {
    "path": "examples/unitTestExample/src/main/res/values-w820dp/dimens.xml",
    "content": "<resources>\n    <!-- Example customization of dimensions originally defined in res/values/dimens.xml\n         (such as screen margins) for screens with more than 820dp of available width. This\n         would include 7\" and 10\" devices in landscape (~960dp and ~1280dp respectively). -->\n    <dimen name=\"activity_horizontal_margin\">64dp</dimen>\n</resources>\n"
  },
  {
    "path": "examples/unitTestExample/src/test/java/io/realm/examples/unittesting/ExampleActivityTest.java",
    "content": "/*\n * Copyright 2015 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\npackage io.realm.examples.unittesting;\n\nimport android.content.Context;\n\nimport org.junit.Before;\nimport org.junit.Ignore;\nimport org.junit.Rule;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.mockito.Mockito;\nimport org.powermock.core.classloader.annotations.PowerMockIgnore;\nimport org.powermock.core.classloader.annotations.PrepareForTest;\nimport org.powermock.core.classloader.annotations.SuppressStaticInitializationFor;\nimport org.powermock.modules.junit4.PowerMockRunner;\nimport org.powermock.modules.junit4.PowerMockRunnerDelegate;\nimport org.powermock.modules.junit4.rule.PowerMockRule;\nimport org.robolectric.Robolectric;\nimport org.robolectric.RobolectricTestRunner;\nimport org.robolectric.RuntimeEnvironment;\nimport org.robolectric.annotation.Config;\n\nimport java.util.Arrays;\nimport java.util.List;\n\nimport io.realm.Realm;\nimport io.realm.RealmConfiguration;\nimport io.realm.RealmObject;\nimport io.realm.RealmQuery;\nimport io.realm.RealmResults;\nimport io.realm.examples.unittesting.model.Person;\nimport io.realm.internal.RealmCore;\nimport io.realm.log.RealmLog;\n\nimport static org.hamcrest.CoreMatchers.is;\nimport static org.junit.Assert.assertThat;\nimport static org.mockito.Matchers.any;\nimport static org.mockito.Matchers.anyInt;\nimport static org.mockito.Matchers.anyString;\nimport static org.mockito.Mockito.doCallRealMethod;\nimport static org.mockito.Mockito.times;\nimport static org.mockito.Mockito.verify;\nimport static org.powermock.api.mockito.PowerMockito.doNothing;\nimport static org.powermock.api.mockito.PowerMockito.mock;\nimport static org.powermock.api.mockito.PowerMockito.mockStatic;\nimport static org.powermock.api.mockito.PowerMockito.verifyStatic;\nimport static org.powermock.api.mockito.PowerMockito.when;\nimport static org.powermock.api.mockito.PowerMockito.whenNew;\n\n\n@RunWith(RobolectricTestRunner.class)\n@Config(sdk = 21)\n@PowerMockIgnore({\"org.mockito.*\", \"org.robolectric.*\", \"android.*\"})\n@SuppressStaticInitializationFor(\"io.realm.internal.Util\")\n@PrepareForTest({Realm.class, RealmConfiguration.class, RealmQuery.class, RealmResults.class, RealmCore.class, RealmLog.class})\n@Ignore(\"https://github.com/realm/realm-java/issues/7550\")\npublic class ExampleActivityTest {\n    // Robolectric, Using Power Mock https://github.com/robolectric/robolectric/wiki/Using-PowerMock\n\n    @Rule\n    public PowerMockRule rule = new PowerMockRule();\n\n    private Realm mockRealm;\n    private RealmResults<Person> people;\n\n    @Before\n    public void setup() throws Exception {\n\n        // Setup Realm to be mocked. The order of these matters\n        mockStatic(RealmCore.class);\n        mockStatic(RealmLog.class);\n        mockStatic(Realm.class);\n        mockStatic(RealmConfiguration.class);\n        Realm.init(RuntimeEnvironment.application);\n\n        // Create the mock\n        final Realm mockRealm = mock(Realm.class);\n        final RealmConfiguration mockRealmConfig = mock(RealmConfiguration.class);\n\n        // TODO: Better solution would be just mock the RealmConfiguration.Builder class. But it seems there is some\n        // problems for powermock to mock it (static inner class). We just mock the RealmCore.loadLibrary(Context) which\n        // will be called by RealmConfiguration.Builder's constructor.\n        doNothing().when(RealmCore.class);\n        RealmCore.loadLibrary(any(Context.class));\n\n\n        // TODO: Mock the RealmConfiguration's constructor. If the RealmConfiguration.Builder.build can be mocked, this\n        // is not necessary anymore.\n        whenNew(RealmConfiguration.class).withAnyArguments().thenReturn(mockRealmConfig);\n\n        // Anytime getInstance is called with any configuration, then return the mockRealm\n        when(Realm.getDefaultInstance()).thenReturn(mockRealm);\n\n        // Anytime we ask Realm to create a Person, return a new instance.\n        when(mockRealm.createObject(Person.class)).thenReturn(new Person());\n\n        // Set up some naive stubs\n        Person p1 = new Person();\n        p1.setAge(14);\n        p1.setName(\"John Young\");\n\n        Person p2 = new Person();\n        p2.setAge(89);\n        p2.setName(\"John Senior\");\n\n        Person p3 = new Person();\n        p3.setAge(27);\n        p3.setName(\"Jane\");\n\n        Person p4 = new Person();\n        p4.setAge(42);\n        p4.setName(\"Robert\");\n\n        List<Person> personList = Arrays.asList(p1, p2, p3, p4);\n\n        // Create a mock RealmQuery\n        RealmQuery<Person> personQuery = mockRealmQuery();\n\n        // When the RealmQuery performs findFirst, return the first record in the list.\n        when(personQuery.findFirst()).thenReturn(personList.get(0));\n\n        // When the where clause is called on the Realm, return the mock query.\n        when(mockRealm.where(Person.class)).thenReturn(personQuery);\n\n        // When the RealmQuery is filtered on any string and any integer, return the person query\n        when(personQuery.equalTo(anyString(), anyInt())).thenReturn(personQuery);\n\n        // RealmResults is final, must mock static and also place this in the PrepareForTest annotation array.\n        mockStatic(RealmResults.class);\n\n        // Create a mock RealmResults\n        RealmResults<Person> people = mockRealmResults();\n\n        // When we ask Realm for all of the Person instances, return the mock RealmResults\n        when(mockRealm.where(Person.class).findAll()).thenReturn(people);\n\n        // When a between query is performed with any string as the field and any int as the\n        // value, then return the personQuery itself\n        when(personQuery.between(anyString(), anyInt(), anyInt())).thenReturn(personQuery);\n\n        // When a beginsWith clause is performed with any string field and any string value\n        // return the same person query\n        when(personQuery.beginsWith(anyString(), anyString())).thenReturn(personQuery);\n\n        // When we ask the RealmQuery for all of the Person objects, return the mock RealmResults\n        when(personQuery.findAll()).thenReturn(people);\n\n\n        // The for(...) loop in Java needs an iterator, so we're giving it one that has items,\n        // since the mock RealmResults does not provide an implementation. Therefore, anytime\n        // anyone asks for the RealmResults Iterator, give them a functioning iterator from the\n        // ArrayList of Persons we created above. This will allow the loop to execute.\n        when(people.iterator()).thenReturn(personList.iterator());\n\n        // Return the size of the mock list.\n        when(people.size()).thenReturn(personList.size());\n\n        this.mockRealm = mockRealm;\n        this.people = people;\n    }\n\n\n    @Test\n    public void shouldBeAbleToAccessActivityAndVerifyRealmInteractions() {\n        doCallRealMethod().when(mockRealm).executeTransaction(Mockito.any(Realm.Transaction.class));\n\n        // Create activity\n        ExampleActivity activity = Robolectric.buildActivity(ExampleActivity.class).create().start().resume().visible().get();\n\n        assertThat(activity.getTitle().toString(), is(\"Unit Test Example\"));\n\n        // Verify that two Realm.getInstance() calls took place.\n        verifyStatic(Realm.class, times(2));\n        Realm.getDefaultInstance();\n\n        // verify that we have four begin and commit transaction calls\n        // Do not verify partial mock invocation count: https://github.com/jayway/powermock/issues/649\n        //verify(mockRealm, times(4)).executeTransaction(Mockito.any(Realm.Transaction.class));\n\n        // Click the clean up button\n        activity.findViewById(R.id.clean_up).performClick();\n\n        // Verify that begin and commit transaction were called (been called a total of 5 times now)\n        // Do not verify partial mock invocation count: https://github.com/jayway/powermock/issues/649\n        //verify(mockRealm, times(5)).executeTransaction(Mockito.any(Realm.Transaction.class));\n\n        // Verify that we queried for Person instances five times in this run (2 in basicCrud(),\n        // 2 in complexQuery() and 1 in the button click)\n        verify(mockRealm, times(5)).where(Person.class);\n\n        // Verify that the delete method was called. Delete is also called in the start of the\n        // activity to ensure we start with a clean db.\n        verify(mockRealm, times(2)).delete(Person.class);\n\n        // Call the destroy method so we can verify that the .close() method was called (below)\n        activity.onDestroy();\n\n        // Verify that the realm got closed 2 separate times. Once in the AsyncTask, once\n        // in onDestroy\n        verify(mockRealm, times(2)).close();\n    }\n\n    /**\n     * Have to verify the transaction execution in a different test because\n     * of a problem with Powermock: https://github.com/jayway/powermock/issues/649\n     */\n    @Test\n    public void shouldBeAbleToVerifyTransactionCalls() {\n\n        // Create activity\n        ExampleActivity activity = Robolectric.buildActivity(ExampleActivity.class).create().start().resume().visible().get();\n\n        assertThat(activity.getTitle().toString(), is(\"Unit Test Example\"));\n\n        // Verify that two Realm.getInstance() calls took place.\n        verifyStatic(Realm.class, times(2));\n        Realm.getDefaultInstance();\n\n        // verify that we have four begin and commit transaction calls\n        // Do not verify partial mock invocation count: https://github.com/jayway/powermock/issues/649\n        verify(mockRealm, times(4)).executeTransaction(Mockito.any(Realm.Transaction.class));\n\n        // Click the clean up button\n        activity.findViewById(R.id.clean_up).performClick();\n\n        // Verify that begin and commit transaction were called (been called a total of 5 times now)\n        // Do not verify partial mock invocation count: https://github.com/jayway/powermock/issues/649\n        verify(mockRealm, times(5)).executeTransaction(Mockito.any(Realm.Transaction.class));\n\n        // Call the destroy method so we can verify that the .close() method was called (below)\n        activity.onDestroy();\n\n        // Verify that the realm got closed 2 separate times. Once in the AsyncTask, once\n        // in onDestroy\n        verify(mockRealm, times(2)).close();\n    }\n\n\n    @SuppressWarnings(\"unchecked\")\n    private <T extends RealmObject> RealmQuery<T> mockRealmQuery() {\n        return mock(RealmQuery.class);\n    }\n\n    @SuppressWarnings(\"unchecked\")\n    private <T extends RealmObject> RealmResults<T> mockRealmResults() {\n        return mock(RealmResults.class);\n    }\n}\n"
  },
  {
    "path": "examples/unitTestExample/src/test/java/io/realm/examples/unittesting/ExampleRealmTest.java",
    "content": "/*\n * Copyright 2015 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\npackage io.realm.examples.unittesting;\n\nimport org.junit.Before;\nimport org.junit.Ignore;\nimport org.junit.Rule;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.mockito.Mockito;\nimport org.powermock.api.mockito.PowerMockito;\nimport org.powermock.core.classloader.annotations.PowerMockIgnore;\nimport org.powermock.core.classloader.annotations.PrepareForTest;\nimport org.powermock.core.classloader.annotations.SuppressStaticInitializationFor;\nimport org.powermock.modules.junit4.rule.PowerMockRule;\nimport org.robolectric.RobolectricTestRunner;\nimport org.robolectric.annotation.Config;\n\nimport io.realm.Realm;\nimport io.realm.examples.unittesting.model.Dog;\nimport io.realm.examples.unittesting.repository.DogRepository;\nimport io.realm.examples.unittesting.repository.DogRepositoryImpl;\nimport io.realm.log.RealmLog;\n\nimport static org.hamcrest.CoreMatchers.is;\nimport static org.junit.Assert.assertThat;\nimport static org.mockito.Mockito.mock;\nimport static org.mockito.Mockito.verify;\nimport static org.mockito.internal.verification.VerificationModeFactory.times;\nimport static org.powermock.api.mockito.PowerMockito.doCallRealMethod;\nimport static org.powermock.api.mockito.PowerMockito.mockStatic;\nimport static org.powermock.api.mockito.PowerMockito.when;\n\n\n@RunWith(RobolectricTestRunner.class)\n@Config(sdk = 19)\n@PowerMockIgnore({\"org.mockito.*\", \"org.robolectric.*\", \"android.*\"})\n@SuppressStaticInitializationFor(\"io.realm.internal.Util\")\n@PrepareForTest({Realm.class, RealmLog.class})\n@Ignore(\"https://github.com/realm/realm-java/issues/7550\")\npublic class ExampleRealmTest {\n    // Robolectric, Using Power Mock https://github.com/robolectric/robolectric/wiki/Using-PowerMock\n\n    @Rule\n    public PowerMockRule rule = new PowerMockRule();\n    Realm mockRealm;\n\n    @Before\n    public void setup() {\n        mockStatic(RealmLog.class);\n        mockStatic(Realm.class);\n\n        Realm mockRealm = PowerMockito.mock(Realm.class);\n\n        when(Realm.getDefaultInstance()).thenReturn(mockRealm);\n\n        this.mockRealm = mockRealm;\n    }\n\n    @Test\n    public void shouldBeAbleToGetDefaultInstance() {\n        assertThat(Realm.getDefaultInstance(), is(mockRealm));\n    }\n\n    @Test\n    public void shouldBeAbleToMockRealmMethods() {\n        when(mockRealm.isAutoRefresh()).thenReturn(true);\n        assertThat(mockRealm.isAutoRefresh(), is(true));\n\n        when(mockRealm.isAutoRefresh()).thenReturn(false);\n        assertThat(mockRealm.isAutoRefresh(), is(false));\n    }\n\n    @Test\n    public void shouldBeAbleToCreateARealmObject() {\n        Dog dog = new Dog();\n        when(mockRealm.createObject(Dog.class)).thenReturn(dog);\n\n        Dog output = mockRealm.createObject(Dog.class);\n\n        assertThat(output, is(dog));\n    }\n\n    /**\n     * This test verifies the behavior in the {@link DogRepositoryImpl} class.\n     */\n    @Test\n    public void shouldVerifyThatDogWasCreated() {\n\n        doCallRealMethod().when(mockRealm).executeTransaction(Mockito.any(Realm.Transaction.class));\n\n        Dog dog = mock(Dog.class);\n        when(mockRealm.createObject(Dog.class)).thenReturn(dog);\n\n        DogRepository dogRepo = new DogRepositoryImpl();\n        dogRepo.createDog(\"Spot\");\n\n        // Attempting to verify that a method was called (executeTransaction) on a partial\n        // mock will return unexpected results due to the partial mock. For example,\n        // verifying that `executeTransaction` was called only once will fail as Powermock\n        // actually calls the method 3 times for some reason. I cannot determine why at this\n        // point.\n\n\n        // Verify that Realm#createObject was called only once\n        verify(mockRealm, times(1)).createObject(Dog.class); // Verify that a Dog was in fact created.\n\n        // Verify that Dog#setName() is called only once\n        verify(dog, times(1)).setName(Mockito.anyString()); // Any string will do\n\n        // Verify that the Realm was closed only once.\n        verify(mockRealm, times(1)).close();\n    }\n\n    /**\n     * Have to verify the {@link Realm#executeTransaction(Realm.Transaction)} call in a different\n     * test because of a problem with Powermock: https://github.com/jayway/powermock/issues/649\n     */\n    @Test\n    public void shouldVerifyThatTransactionWasExecuted() {\n\n        DogRepository dogRepo = new DogRepositoryImpl();\n        dogRepo.createDog(\"Spot\");\n\n        // Verify that the begin transaction was called only once\n        verify(mockRealm, times(1)).executeTransaction(Mockito.any(Realm.Transaction.class));\n\n        // Verify that the Realm was closed only once.\n        verify(mockRealm, times(1)).close();\n    }\n}\n"
  },
  {
    "path": "gradle/wrapper/gradle-wrapper.properties",
    "content": "distributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\ndistributionUrl=https\\://services.gradle.org/distributions/gradle-7.5-all.zip\nzipStoreBase=GRADLE_USER_HOME\nzipStorePath=wrapper/dists\n"
  },
  {
    "path": "gradle-plugin/build.gradle",
    "content": "import org.apache.tools.ant.filters.ReplaceTokens\nimport org.gradle.api.internal.classpath.ModuleRegistry\nimport org.gradle.api.internal.project.ProjectInternal\n\nbuildscript {\n    def properties = new Properties()\n    properties.load(new FileInputStream(\"${rootDir}/../dependencies.list\"))\n    ext.kotlin_version = properties.get('KOTLIN')\n    repositories {\n        jcenter()\n        maven {\n            url \"https://plugins.gradle.org/m2/\"\n        }\n    }\n    dependencies {\n        classpath \"org.jfrog.buildinfo:build-info-extractor-gradle:${properties.get('BUILD_INFO_EXTRACTOR_GRADLE')}\"\n        classpath \"io.github.gradle-nexus:publish-plugin:${properties.get(\"GRADLE_NEXUS_PLUGIN\")}\"\n        classpath \"org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version\"\n    }\n}\n\napply plugin: 'kotlin'\napply plugin: 'java-gradle-plugin'\napply plugin: 'maven-publish'\n\ndef props = new Properties()\nprops.load(new FileInputStream(\"${rootDir}/../dependencies.list\"))\nprops.each { key, val ->\n    project.ext.set(key, val)\n}\n\nrepositories {\n    mavenLocal()\n    google()\n    jcenter()\n}\n\nsourceCompatibility = 11\ntargetCompatibility = 11\n\ngroup = 'io.realm'\nversion = file(\"${projectDir}/../version.txt\").text.trim()\n\nconfigurations {\n    provided\n    compile.extendsFrom provided\n}\n\ntest {\n    testLogging.showStandardStreams = true\n}\n\nsourceSets {\n    main {\n        compileClasspath += configurations.provided\n    }\n}\n\ndependencies {\n    implementation gradleApi()\n    implementation localGroovy()\n    implementation \"io.realm:realm-transformer:${version}\"\n    /*Note: the latest Android Gradle plugin has now built in support for annotation processors and warns and/or blocks android-apt,\n     see this https://bitbucket.org/hvisser/android-apt/wiki/Migration page on how to migrate\n     and this https://www.littlerobots.nl/blog/Whats-next-for-android-apt/ for more info.\n   */\n    implementation 'com.neenbedankt.gradle.plugins:android-apt:1.8' //TODO: https://www.littlerobots.nl/blog/Whats-next-for-android-apt/\n    compileOnly \"com.android.tools.build:gradle:${props.get(\"GRADLE_BUILD_TOOLS\")}\"\n\n    testImplementation gradleTestKit()\n    testImplementation 'junit:junit:4.12'\n    testImplementation \"com.android.tools.build:gradle:${props.get(\"GRADLE_BUILD_TOOLS\")}\"\n    // See https://github.com/gradle/gradle/issues/16774#issuecomment-893493869\n    def toolingApiBuildersJar = (project as ProjectInternal).services.get(ModuleRegistry.class)\n            .getModule(\"gradle-tooling-api-builders\")\n            .classpath\n            .asFiles\n            .first()\n    testRuntimeOnly(files(toolingApiBuildersJar))\n}\n\ntask generateVersionClass(type: Copy) {\n    from 'src/main/templates/Version.kt'\n    into 'build/generated-src/main/kotlin/io/realm'\n    filter(ReplaceTokens, tokens: [version: version])\n    outputs.upToDateWhen { false }\n}\n\n// Include the generated Version file\nsourceSets {\n    main {\n        java {\n            srcDirs += ['build/generated-src/main/kotlin']\n        }\n    }\n}\n\ncompileKotlin.dependsOn generateVersionClass\n\napply from: \"${rootDir}/../mavencentral-publications.gradle\"\napply from: \"${rootDir}/../mavencentral-publish.gradle\"\n\npublishing {\n    publications {\n        realmPublication(MavenPublication) {\n            groupId 'io.realm'\n            artifactId = 'realm-gradle-plugin'\n            from components.java\n            populatePom(\n                    it,\n                    'realm-gradle-plugin',\n                    'Gradle plugin for Realm. Realm is a mobile database: Build better apps, faster.'\n            )\n        }\n    }\n}\n\njava {\n    withSourcesJar()\n    withJavadocJar()\n}\n"
  },
  {
    "path": "gradle-plugin/gradle/wrapper/gradle-wrapper.properties",
    "content": "distributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\ndistributionUrl=https\\://services.gradle.org/distributions/gradle-7.5-all.zip\nzipStoreBase=GRADLE_USER_HOME\nzipStorePath=wrapper/dists\n"
  },
  {
    "path": "gradle-plugin/gradle.properties",
    "content": "org.gradle.caching=true"
  },
  {
    "path": "gradle-plugin/gradlew",
    "content": "#!/bin/sh\n\n#\n# Copyright © 2015-2021 the original authors.\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#      https://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##############################################################################\n#\n#   Gradle start up script for POSIX generated by Gradle.\n#\n#   Important for running:\n#\n#   (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is\n#       noncompliant, but you have some other compliant shell such as ksh or\n#       bash, then to run this script, type that shell name before the whole\n#       command line, like:\n#\n#           ksh Gradle\n#\n#       Busybox and similar reduced shells will NOT work, because this script\n#       requires all of these POSIX shell features:\n#         * functions;\n#         * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,\n#           «${var#prefix}», «${var%suffix}», and «$( cmd )»;\n#         * compound commands having a testable exit status, especially «case»;\n#         * various built-in commands including «command», «set», and «ulimit».\n#\n#   Important for patching:\n#\n#   (2) This script targets any POSIX shell, so it avoids extensions provided\n#       by Bash, Ksh, etc; in particular arrays are avoided.\n#\n#       The \"traditional\" practice of packing multiple parameters into a\n#       space-separated string is a well documented source of bugs and security\n#       problems, so this is (mostly) avoided, by progressively accumulating\n#       options in \"$@\", and eventually passing that to Java.\n#\n#       Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,\n#       and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;\n#       see the in-line comments for details.\n#\n#       There are tweaks for specific operating systems such as AIX, CygWin,\n#       Darwin, MinGW, and NonStop.\n#\n#   (3) This script is generated from the Groovy template\n#       https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt\n#       within the Gradle project.\n#\n#       You can find Gradle at https://github.com/gradle/gradle/.\n#\n##############################################################################\n\n# Attempt to set APP_HOME\n\n# Resolve links: $0 may be a link\napp_path=$0\n\n# Need this for daisy-chained symlinks.\nwhile\n    APP_HOME=${app_path%\"${app_path##*/}\"}  # leaves a trailing /; empty if no leading path\n    [ -h \"$app_path\" ]\ndo\n    ls=$( ls -ld \"$app_path\" )\n    link=${ls#*' -> '}\n    case $link in             #(\n      /*)   app_path=$link ;; #(\n      *)    app_path=$APP_HOME$link ;;\n    esac\ndone\n\nAPP_HOME=$( cd \"${APP_HOME:-./}\" && pwd -P ) || exit\n\nAPP_NAME=\"Gradle\"\nAPP_BASE_NAME=${0##*/}\n\n# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\nDEFAULT_JVM_OPTS='\"-Xmx64m\" \"-Xms64m\"'\n\n# Use the maximum available, or set MAX_FD != -1 to use that value.\nMAX_FD=maximum\n\nwarn () {\n    echo \"$*\"\n} >&2\n\ndie () {\n    echo\n    echo \"$*\"\n    echo\n    exit 1\n} >&2\n\n# OS specific support (must be 'true' or 'false').\ncygwin=false\nmsys=false\ndarwin=false\nnonstop=false\ncase \"$( uname )\" in                #(\n  CYGWIN* )         cygwin=true  ;; #(\n  Darwin* )         darwin=true  ;; #(\n  MSYS* | MINGW* )  msys=true    ;; #(\n  NONSTOP* )        nonstop=true ;;\nesac\n\nCLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar\n\n\n# Determine the Java command to use to start the JVM.\nif [ -n \"$JAVA_HOME\" ] ; then\n    if [ -x \"$JAVA_HOME/jre/sh/java\" ] ; then\n        # IBM's JDK on AIX uses strange locations for the executables\n        JAVACMD=$JAVA_HOME/jre/sh/java\n    else\n        JAVACMD=$JAVA_HOME/bin/java\n    fi\n    if [ ! -x \"$JAVACMD\" ] ; then\n        die \"ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME\n\nPlease set the JAVA_HOME variable in your environment to match the\nlocation of your Java installation.\"\n    fi\nelse\n    JAVACMD=java\n    which java >/dev/null 2>&1 || die \"ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.\n\nPlease set the JAVA_HOME variable in your environment to match the\nlocation of your Java installation.\"\nfi\n\n# Increase the maximum file descriptors if we can.\nif ! \"$cygwin\" && ! \"$darwin\" && ! \"$nonstop\" ; then\n    case $MAX_FD in #(\n      max*)\n        MAX_FD=$( ulimit -H -n ) ||\n            warn \"Could not query maximum file descriptor limit\"\n    esac\n    case $MAX_FD in  #(\n      '' | soft) :;; #(\n      *)\n        ulimit -n \"$MAX_FD\" ||\n            warn \"Could not set maximum file descriptor limit to $MAX_FD\"\n    esac\nfi\n\n# Collect all arguments for the java command, stacking in reverse order:\n#   * args from the command line\n#   * the main class name\n#   * -classpath\n#   * -D...appname settings\n#   * --module-path (only if needed)\n#   * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.\n\n# For Cygwin or MSYS, switch paths to Windows format before running java\nif \"$cygwin\" || \"$msys\" ; then\n    APP_HOME=$( cygpath --path --mixed \"$APP_HOME\" )\n    CLASSPATH=$( cygpath --path --mixed \"$CLASSPATH\" )\n\n    JAVACMD=$( cygpath --unix \"$JAVACMD\" )\n\n    # Now convert the arguments - kludge to limit ourselves to /bin/sh\n    for arg do\n        if\n            case $arg in                                #(\n              -*)   false ;;                            # don't mess with options #(\n              /?*)  t=${arg#/} t=/${t%%/*}              # looks like a POSIX filepath\n                    [ -e \"$t\" ] ;;                      #(\n              *)    false ;;\n            esac\n        then\n            arg=$( cygpath --path --ignore --mixed \"$arg\" )\n        fi\n        # Roll the args list around exactly as many times as the number of\n        # args, so each arg winds up back in the position where it started, but\n        # possibly modified.\n        #\n        # NB: a `for` loop captures its iteration list before it begins, so\n        # changing the positional parameters here affects neither the number of\n        # iterations, nor the values presented in `arg`.\n        shift                   # remove old arg\n        set -- \"$@\" \"$arg\"      # push replacement arg\n    done\nfi\n\n# Collect all arguments for the java command;\n#   * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of\n#     shell script including quotes and variable substitutions, so put them in\n#     double quotes to make sure that they get re-expanded; and\n#   * put everything else in single quotes, so that it's not re-expanded.\n\nset -- \\\n        \"-Dorg.gradle.appname=$APP_BASE_NAME\" \\\n        -classpath \"$CLASSPATH\" \\\n        org.gradle.wrapper.GradleWrapperMain \\\n        \"$@\"\n\n# Stop when \"xargs\" is not available.\nif ! command -v xargs >/dev/null 2>&1\nthen\n    die \"xargs is not available\"\nfi\n\n# Use \"xargs\" to parse quoted args.\n#\n# With -n1 it outputs one arg per line, with the quotes and backslashes removed.\n#\n# In Bash we could simply go:\n#\n#   readarray ARGS < <( xargs -n1 <<<\"$var\" ) &&\n#   set -- \"${ARGS[@]}\" \"$@\"\n#\n# but POSIX shell has neither arrays nor command substitution, so instead we\n# post-process each arg (as a line of input to sed) to backslash-escape any\n# character that might be a shell metacharacter, then use eval to reverse\n# that process (while maintaining the separation between arguments), and wrap\n# the whole thing up as a single \"set\" statement.\n#\n# This will of course break if any of these variables contains a newline or\n# an unmatched quote.\n#\n\neval \"set -- $(\n        printf '%s\\n' \"$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS\" |\n        xargs -n1 |\n        sed ' s~[^-[:alnum:]+,./:=@_]~\\\\&~g; ' |\n        tr '\\n' ' '\n    )\" '\"$@\"'\n\nexec \"$JAVACMD\" \"$@\"\n"
  },
  {
    "path": "gradle-plugin/gradlew.bat",
    "content": "@rem\r\n@rem Copyright 2015 the original author or authors.\r\n@rem\r\n@rem Licensed under the Apache License, Version 2.0 (the \"License\");\r\n@rem you may not use this file except in compliance with the License.\r\n@rem You may obtain a copy of the License at\r\n@rem\r\n@rem      https://www.apache.org/licenses/LICENSE-2.0\r\n@rem\r\n@rem Unless required by applicable law or agreed to in writing, software\r\n@rem distributed under the License is distributed on an \"AS IS\" BASIS,\r\n@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n@rem See the License for the specific language governing permissions and\r\n@rem limitations under the License.\r\n@rem\r\n\r\n@if \"%DEBUG%\"==\"\" @echo off\r\n@rem ##########################################################################\r\n@rem\r\n@rem  Gradle startup script for Windows\r\n@rem\r\n@rem ##########################################################################\r\n\r\n@rem Set local scope for the variables with windows NT shell\r\nif \"%OS%\"==\"Windows_NT\" setlocal\r\n\r\nset DIRNAME=%~dp0\r\nif \"%DIRNAME%\"==\"\" set DIRNAME=.\r\nset APP_BASE_NAME=%~n0\r\nset APP_HOME=%DIRNAME%\r\n\r\n@rem Resolve any \".\" and \"..\" in APP_HOME to make it shorter.\r\nfor %%i in (\"%APP_HOME%\") do set APP_HOME=%%~fi\r\n\r\n@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\r\nset DEFAULT_JVM_OPTS=\"-Xmx64m\" \"-Xms64m\"\r\n\r\n@rem Find java.exe\r\nif defined JAVA_HOME goto findJavaFromJavaHome\r\n\r\nset JAVA_EXE=java.exe\r\n%JAVA_EXE% -version >NUL 2>&1\r\nif %ERRORLEVEL% equ 0 goto execute\r\n\r\necho.\r\necho ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.\r\necho.\r\necho Please set the JAVA_HOME variable in your environment to match the\r\necho location of your Java installation.\r\n\r\ngoto fail\r\n\r\n:findJavaFromJavaHome\r\nset JAVA_HOME=%JAVA_HOME:\"=%\r\nset JAVA_EXE=%JAVA_HOME%/bin/java.exe\r\n\r\nif exist \"%JAVA_EXE%\" goto execute\r\n\r\necho.\r\necho ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%\r\necho.\r\necho Please set the JAVA_HOME variable in your environment to match the\r\necho location of your Java installation.\r\n\r\ngoto fail\r\n\r\n:execute\r\n@rem Setup the command line\r\n\r\nset CLASSPATH=%APP_HOME%\\gradle\\wrapper\\gradle-wrapper.jar\r\n\r\n\r\n@rem Execute Gradle\r\n\"%JAVA_EXE%\" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% \"-Dorg.gradle.appname=%APP_BASE_NAME%\" -classpath \"%CLASSPATH%\" org.gradle.wrapper.GradleWrapperMain %*\r\n\r\n:end\r\n@rem End local scope for the variables with windows NT shell\r\nif %ERRORLEVEL% equ 0 goto mainEnd\r\n\r\n:fail\r\nrem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of\r\nrem the _cmd.exe /c_ return code!\r\nset EXIT_CODE=%ERRORLEVEL%\r\nif %EXIT_CODE% equ 0 set EXIT_CODE=1\r\nif not \"\"==\"%GRADLE_EXIT_CONSOLE%\" exit %EXIT_CODE%\r\nexit /b %EXIT_CODE%\r\n\r\n:mainEnd\r\nif \"%OS%\"==\"Windows_NT\" endlocal\r\n\r\n:omega\r\n"
  },
  {
    "path": "gradle-plugin/settings.gradle",
    "content": "rootProject.name = 'realm-gradle-plugin'\n"
  },
  {
    "path": "gradle-plugin/src/main/kotlin/io/realm/gradle/Realm.kt",
    "content": "package io.realm.gradle\n\nimport com.android.build.gradle.AppPlugin\nimport com.android.build.gradle.LibraryPlugin\nimport io.realm.transformer.registerRealmTransformerTask\nimport org.gradle.api.GradleException\nimport org.gradle.api.Plugin\nimport org.gradle.api.Project\nimport org.gradle.api.artifacts.UnknownConfigurationException\nimport org.gradle.api.plugins.PluginCollection\nimport org.slf4j.Logger\nimport org.slf4j.LoggerFactory\n\nval logger: Logger = LoggerFactory.getLogger(\"realm-logger\")\n\nconst val ANDROID_TEST_IMPLEMENTATION = \"androidTestImplementation\"\n\n// TODO Run a Task or Visitor to collect runtimeClassPath, then serialize it\n//      Run another task that depends on the output of the first task in order to deserialize the ClassPool and process each class apart\nopen class Realm : Plugin<Project> {\n    override fun apply(project: Project) {\n        // Make sure the project is either an Android application or library\n        val isAndroidApp: PluginCollection<AppPlugin> =\n            project.plugins.withType(AppPlugin::class.java)\n        val isAndroidLib: PluginCollection<LibraryPlugin> =\n            project.plugins.withType(LibraryPlugin::class.java)\n\n        if (isAndroidApp.isEmpty() && isAndroidLib.isEmpty()) {\n            throw GradleException(\"'com.android.application' or 'com.android.library' plugin required.\")\n        }\n\n        checkCompatibleAGPVersion()\n\n        val isKotlinProject: Boolean =\n            project.plugins.findPlugin(\"kotlin-android\") != null || project.plugins.findPlugin(\"kotlin-multiplatform\") != null\n        val hasAnnotationProcessorConfiguration =\n            project.configurations.findByName(\"annotationProcessor\") != null\n        // TODO add a parameter in 'realm' block if this should be specified by users\n        val dependencyConfigurationName: String = getDependencyConfigurationName(project)\n        val extension = project.extensions.create(\"realm\", RealmPluginExtension::class.java)\n\n        extension.isKotlinExtensionsEnabled = isKotlinProject\n\n        registerRealmTransformerTask(project)\n\n        project.dependencies.add(\n            dependencyConfigurationName,\n            \"io.realm:realm-annotations:${Version.VERSION}\"\n        )\n        if (isKotlinProject) {\n            project.dependencies.add(\n                \"kapt\",\n                \"io.realm:realm-annotations-processor:${Version.VERSION}\"\n            )\n            project.dependencies.add(\n                \"kaptAndroidTest\",\n                \"io.realm:realm-annotations-processor:${Version.VERSION}\"\n            )\n        } else {\n            assert(hasAnnotationProcessorConfiguration)\n            project.dependencies.add(\n                \"annotationProcessor\",\n                \"io.realm:realm-annotations-processor:${Version.VERSION}\"\n            )\n            project.dependencies.add(\n                \"androidTestAnnotationProcessor\",\n                \"io.realm:realm-annotations-processor:${Version.VERSION}\"\n            )\n        }\n\n        // FIXME When injected, dependencies are not propagating correctly from the main release to the \n        // android test releases. We solve it by inject them into the instrumented tests manually.\n        project.afterEvaluate { \n            listOf(\n                dependencyConfigurationName,\n                ANDROID_TEST_IMPLEMENTATION // force adds the dependencies to the instrumented tests configuration\n            ).forEach { dependencyConfigurationName: String ->\n                setDependencies(\n                    project,\n                    dependencyConfigurationName,\n                    extension.isSyncEnabled,\n                    extension.isKotlinExtensionsEnabled\n                )\n            }\n        }\n    }\n\n    companion object {\n\n        private fun checkCompatibleAGPVersion() {\n            val version = SimpleAGPVersion.ANDROID_GRADLE_PLUGIN_VERSION\n            return when {\n                version >= SimpleAGPVersion(7, 4) -> {\n                    // minimum version compatible with https://developer.android.com/studio/releases/gradle-plugin-api-updates#support_for_transformations_based_on_whole_program_analysis\n                    logger.debug(\"Realm Plugin used with AGP version: ${version.major}.${version.minor}.\")\n                }\n                else -> {\n                    throw GradleException(\"Android Gradle Plugin $version is not supported. Upgrade to Realm Java `10.15.0` or later.\")\n                }\n            }\n        }\n\n        private fun getDependencyConfigurationName(project: Project): String {\n            /*\n             * Dependency configuration name for android gradle plugin 3.0.0-*.\n             * We need to use 'api' instead of 'implementation' since user's model class\n             * might be using Realm's classes and annotations.\n             */\n            val newDependencyName = \"api\"\n            val oldDependencyName = \"compile\"\n            return try {\n                project.configurations.getByName(newDependencyName)\n                newDependencyName\n            } catch (ignored: UnknownConfigurationException) {\n                oldDependencyName\n            }\n        }\n\n        // This will setup the required dependencies.\n        // This must only be called once, as removal of dependencies through the iterator API will\n        // not propagate correctly into the IterationOrderRetainingSetElementSource which is backing\n        // the dependency set deep inside the DefaultDependencySet implementation, and failure to do\n        // so causes some internal caching in IterationOrderRetainingSetElementSource to skip\n        // re-adding it if it had already been there once.\n        private fun setDependencies(\n            project: Project,\n            dependencyConfigurationName: String,\n            syncEnabled: Boolean,\n            kotlinExtensionsEnabled: Boolean\n        ) {\n            // remove libraries first\n            val iterator =\n                project.configurations.getByName(dependencyConfigurationName).dependencies.iterator()\n            while (iterator.hasNext()) {\n                val item = iterator.next()\n                if (item.group == \"io.realm\") {\n                    if (item.name.startsWith(\"realm-android-library\")) {\n                        iterator.remove()\n                    }\n                    if (item.name.startsWith(\"realm-android-kotlin-extensions\")) {\n                        iterator.remove()\n                    }\n                }\n            }\n\n            // then add again\n            val syncArtifactName =\n                \"realm-android-library${if (syncEnabled) \"-object-server\" else \"\"}\"\n            project.dependencies.add(\n                dependencyConfigurationName,\n                \"io.realm:${syncArtifactName}:${Version.VERSION}\"\n            )\n\n            if (kotlinExtensionsEnabled) {\n                val kotlinExtArtifactName =\n                    \"realm-android-kotlin-extensions${if (syncEnabled) \"-object-server\" else \"\"}\"\n                project.dependencies.add(\n                    dependencyConfigurationName,\n                    \"io.realm:${kotlinExtArtifactName}:${Version.VERSION}\"\n                )\n            }\n        }\n\n    }\n}\n"
  },
  {
    "path": "gradle-plugin/src/main/kotlin/io/realm/gradle/SimpleAGPVersion.kt",
    "content": "package io.realm.gradle\n\n/*\n * Copyright (C) 2022 The Dagger Authors.\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/**\n * Simple Android Gradle Plugin version class since there is no public API one. b/175816217\n */\ndata class SimpleAGPVersion(\n    val major: Int,\n    val minor: Int,\n) : Comparable<SimpleAGPVersion> {\n\n    override fun compareTo(other: SimpleAGPVersion): Int {\n        return compareValuesBy(\n            this,\n            other,\n            compareBy(SimpleAGPVersion::major).thenBy(SimpleAGPVersion::minor)\n        ) { it }\n    }\n\n    companion object {\n\n        // TODO: Migrate to AndroidPluginVersion once it is available (b/175816217)\n        val ANDROID_GRADLE_PLUGIN_VERSION by lazy {\n            val clazz =\n                findClass(\"com.android.Version\")\n                    ?: findClass(\"com.android.builder.model.Version\")\n            if (clazz != null) {\n                return@lazy parse(\n                    clazz.getField(\"ANDROID_GRADLE_PLUGIN_VERSION\").get(null) as String\n                )\n            }\n            error(\n                \"Unable to obtain AGP version. It is likely that the AGP version being used is too old.\"\n            )\n        }\n\n        private fun parse(version: String?) =\n            tryParse(version) ?: error(\"Unable to parse AGP version: $version\")\n\n        private fun tryParse(version: String?): SimpleAGPVersion? {\n            if (version == null) {\n                return null\n            }\n\n            val parts = version.split('.')\n            if (parts.size == 1) {\n                return SimpleAGPVersion(parts[0].toInt(), 0)\n            }\n\n            return SimpleAGPVersion(parts[0].toInt(), parts[1].toInt())\n        }\n\n        private fun findClass(fqName: String) =\n            try {\n                Class.forName(fqName)\n            } catch (ex: ClassNotFoundException) {\n                null\n            }\n    }\n}\n"
  },
  {
    "path": "gradle-plugin/src/main/resources/META-INF/gradle-plugins/realm-android.properties",
    "content": "#\n# Copyright 2016 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\nimplementation-class=io.realm.gradle.Realm\n"
  },
  {
    "path": "gradle-plugin/src/main/templates/Version.kt",
    "content": "package io.realm.gradle;\n\nobject Version {\n    const val VERSION = \"@version@\"\n}\n"
  },
  {
    "path": "gradle-plugin/src/test/groovy/io/realm/gradle/PluginTest.groovy",
    "content": "/*\n * Copyright 2016 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\npackage io.realm.gradle\n\nimport io.realm.transformer.RealmTransformer\n\nimport com.android.build.api.transform.Transform\nimport org.gradle.api.GradleException\nimport org.gradle.api.Project\nimport org.gradle.api.artifacts.Dependency\nimport org.gradle.api.artifacts.DependencySet\nimport org.gradle.api.artifacts.dsl.DependencyHandler\nimport org.gradle.api.artifacts.dsl.RepositoryHandler\nimport org.gradle.api.internal.artifacts.dsl.dependencies.DefaultDependencyHandler\nimport org.gradle.api.internal.plugins.PluginApplicationException\nimport org.gradle.testfixtures.ProjectBuilder\nimport org.junit.Before\nimport org.junit.Test\n\nimport static org.junit.Assert.assertEquals\nimport static org.junit.Assert.assertTrue\nimport static org.junit.Assert.fail\n\n/**\n * Comment about the order of repositories.\n * The order of repositories do matter, and might need to change depending on the \n * version of the Build Tools being used. See e.g.:\n *\n * https://stackoverflow.com/questions/55278227/android-gradle-build-error-artifacts-for-configuration-classpath/55278968#55278968\n * https://stackoverflow.com/questions/52968576/could-not-find-aapt2-proto-jar-com-android-tools-buildaapt2-proto0-3-1\n */\nclass PluginTest {\n\n    private Project project\n    private String currentVersion\n    private Properties projectDependencies\n\n    @Before\n    void setUp() {\n        project = ProjectBuilder.builder().build()\n        currentVersion = new File(\"../version.txt\").text.trim()\n        projectDependencies = new Properties()\n        projectDependencies.load(new FileInputStream(\"../dependencies.list\"))\n    }\n\n    @Test\n    void pluginAddsRightDependencies() {\n        project.buildscript {\n            repositories {\n                mavenLocal()\n                mavenCentral()\n                google()\n                jcenter()\n            }\n            dependencies {\n                classpath \"com.android.tools.build:gradle:${projectDependencies.get(\"GRADLE_BUILD_TOOLS\")}\"\n            }\n        }\n\n        def manifest = project.file(\"src/main/AndroidManifest.xml\")\n        manifest.parentFile.mkdirs()\n        manifest.text = '<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"  package=\"com.realm.test\"></manifest>'\n\n        project.apply plugin: 'com.android.application'\n        project.apply plugin: 'realm-android'\n\n        project.android {\n            compileSdkVersion 27\n\n            defaultConfig {\n                minSdkVersion 16\n                targetSdkVersion 27\n            }\n        }\n\n        project.evaluate()\n\n        assertTrue(containsDependency(project.dependencies, 'io.realm', 'realm-android-library', currentVersion))\n        assertTrue(containsDependency(project.dependencies, 'io.realm', 'realm-annotations', currentVersion))\n        assertTrue(containsTransform(project.android.transforms, RealmTransformer.class))\n    }\n\n    @Test\n    void pluginFailsWithoutAndroidPlugin() {\n        project.buildscript {\n            repositories {\n                mavenLocal()\n                mavenCentral()\n                jcenter()\n            }\n            dependencies {\n                classpath \"com.android.tools.build:gradle:${projectDependencies.get(\"GRADLE_BUILD_TOOLS\")}\"\n                classpath 'com.jakewharton.sdkmanager:gradle-plugin:0.12.0'\n            }\n        }\n\n        try {\n            project.apply plugin: 'realm-android'\n            fail()\n        } catch (PluginApplicationException e) {\n            assertEquals(e.getCause().class, GradleException.class)\n            assertTrue(e.getCause().getMessage().contains(\"'com.android.application' or 'com.android.library' plugin required.\"))\n        }\n    }\n\n    private static boolean containsDependency(DependencyHandler dependencies,\n                                              String group, String name, String version) {\n        def configurationContainerField = DefaultDependencyHandler.class.getDeclaredField(\"configurationContainer\")\n        configurationContainerField.setAccessible(true)\n        def configurationContainer = configurationContainerField.get(dependencies)\n        def compileConfiguration = configurationContainer.findByName(\"api\")\n\n        def DependencySet dependencySet = compileConfiguration.getDependencies()\n        for (Dependency dependency in dependencySet) {\n            if (dependency.properties.group == group\n                    && dependency.properties.name == name\n                    && dependency.properties.version == version) {\n                return true\n            }\n        }\n        return false\n    }\n\n    private static boolean containsTransform(List<Transform> transformList, Class<? extends Transform> targetClass) {\n        for (Transform t : transformList) {\n            if (t.getClass() == targetClass) {\n                return true\n            }\n        }\n        return false\n    }\n}\n"
  },
  {
    "path": "gradle.properties",
    "content": "org.gradle.jvmargs=-Xmx2048M -XX:MaxMetaspaceSize=2048M\norg.gradle.caching=true\nandroid.enableD8=true\n"
  },
  {
    "path": "gradlew",
    "content": "#!/bin/sh\n\n#\n# Copyright © 2015-2021 the original authors.\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#      https://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##############################################################################\n#\n#   Gradle start up script for POSIX generated by Gradle.\n#\n#   Important for running:\n#\n#   (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is\n#       noncompliant, but you have some other compliant shell such as ksh or\n#       bash, then to run this script, type that shell name before the whole\n#       command line, like:\n#\n#           ksh Gradle\n#\n#       Busybox and similar reduced shells will NOT work, because this script\n#       requires all of these POSIX shell features:\n#         * functions;\n#         * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,\n#           «${var#prefix}», «${var%suffix}», and «$( cmd )»;\n#         * compound commands having a testable exit status, especially «case»;\n#         * various built-in commands including «command», «set», and «ulimit».\n#\n#   Important for patching:\n#\n#   (2) This script targets any POSIX shell, so it avoids extensions provided\n#       by Bash, Ksh, etc; in particular arrays are avoided.\n#\n#       The \"traditional\" practice of packing multiple parameters into a\n#       space-separated string is a well documented source of bugs and security\n#       problems, so this is (mostly) avoided, by progressively accumulating\n#       options in \"$@\", and eventually passing that to Java.\n#\n#       Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,\n#       and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;\n#       see the in-line comments for details.\n#\n#       There are tweaks for specific operating systems such as AIX, CygWin,\n#       Darwin, MinGW, and NonStop.\n#\n#   (3) This script is generated from the Groovy template\n#       https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt\n#       within the Gradle project.\n#\n#       You can find Gradle at https://github.com/gradle/gradle/.\n#\n##############################################################################\n\n# Attempt to set APP_HOME\n\n# Resolve links: $0 may be a link\napp_path=$0\n\n# Need this for daisy-chained symlinks.\nwhile\n    APP_HOME=${app_path%\"${app_path##*/}\"}  # leaves a trailing /; empty if no leading path\n    [ -h \"$app_path\" ]\ndo\n    ls=$( ls -ld \"$app_path\" )\n    link=${ls#*' -> '}\n    case $link in             #(\n      /*)   app_path=$link ;; #(\n      *)    app_path=$APP_HOME$link ;;\n    esac\ndone\n\nAPP_HOME=$( cd \"${APP_HOME:-./}\" && pwd -P ) || exit\n\nAPP_NAME=\"Gradle\"\nAPP_BASE_NAME=${0##*/}\n\n# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\nDEFAULT_JVM_OPTS='\"-Xmx64m\" \"-Xms64m\"'\n\n# Use the maximum available, or set MAX_FD != -1 to use that value.\nMAX_FD=maximum\n\nwarn () {\n    echo \"$*\"\n} >&2\n\ndie () {\n    echo\n    echo \"$*\"\n    echo\n    exit 1\n} >&2\n\n# OS specific support (must be 'true' or 'false').\ncygwin=false\nmsys=false\ndarwin=false\nnonstop=false\ncase \"$( uname )\" in                #(\n  CYGWIN* )         cygwin=true  ;; #(\n  Darwin* )         darwin=true  ;; #(\n  MSYS* | MINGW* )  msys=true    ;; #(\n  NONSTOP* )        nonstop=true ;;\nesac\n\nCLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar\n\n\n# Determine the Java command to use to start the JVM.\nif [ -n \"$JAVA_HOME\" ] ; then\n    if [ -x \"$JAVA_HOME/jre/sh/java\" ] ; then\n        # IBM's JDK on AIX uses strange locations for the executables\n        JAVACMD=$JAVA_HOME/jre/sh/java\n    else\n        JAVACMD=$JAVA_HOME/bin/java\n    fi\n    if [ ! -x \"$JAVACMD\" ] ; then\n        die \"ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME\n\nPlease set the JAVA_HOME variable in your environment to match the\nlocation of your Java installation.\"\n    fi\nelse\n    JAVACMD=java\n    which java >/dev/null 2>&1 || die \"ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.\n\nPlease set the JAVA_HOME variable in your environment to match the\nlocation of your Java installation.\"\nfi\n\n# Increase the maximum file descriptors if we can.\nif ! \"$cygwin\" && ! \"$darwin\" && ! \"$nonstop\" ; then\n    case $MAX_FD in #(\n      max*)\n        MAX_FD=$( ulimit -H -n ) ||\n            warn \"Could not query maximum file descriptor limit\"\n    esac\n    case $MAX_FD in  #(\n      '' | soft) :;; #(\n      *)\n        ulimit -n \"$MAX_FD\" ||\n            warn \"Could not set maximum file descriptor limit to $MAX_FD\"\n    esac\nfi\n\n# Collect all arguments for the java command, stacking in reverse order:\n#   * args from the command line\n#   * the main class name\n#   * -classpath\n#   * -D...appname settings\n#   * --module-path (only if needed)\n#   * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.\n\n# For Cygwin or MSYS, switch paths to Windows format before running java\nif \"$cygwin\" || \"$msys\" ; then\n    APP_HOME=$( cygpath --path --mixed \"$APP_HOME\" )\n    CLASSPATH=$( cygpath --path --mixed \"$CLASSPATH\" )\n\n    JAVACMD=$( cygpath --unix \"$JAVACMD\" )\n\n    # Now convert the arguments - kludge to limit ourselves to /bin/sh\n    for arg do\n        if\n            case $arg in                                #(\n              -*)   false ;;                            # don't mess with options #(\n              /?*)  t=${arg#/} t=/${t%%/*}              # looks like a POSIX filepath\n                    [ -e \"$t\" ] ;;                      #(\n              *)    false ;;\n            esac\n        then\n            arg=$( cygpath --path --ignore --mixed \"$arg\" )\n        fi\n        # Roll the args list around exactly as many times as the number of\n        # args, so each arg winds up back in the position where it started, but\n        # possibly modified.\n        #\n        # NB: a `for` loop captures its iteration list before it begins, so\n        # changing the positional parameters here affects neither the number of\n        # iterations, nor the values presented in `arg`.\n        shift                   # remove old arg\n        set -- \"$@\" \"$arg\"      # push replacement arg\n    done\nfi\n\n# Collect all arguments for the java command;\n#   * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of\n#     shell script including quotes and variable substitutions, so put them in\n#     double quotes to make sure that they get re-expanded; and\n#   * put everything else in single quotes, so that it's not re-expanded.\n\nset -- \\\n        \"-Dorg.gradle.appname=$APP_BASE_NAME\" \\\n        -classpath \"$CLASSPATH\" \\\n        org.gradle.wrapper.GradleWrapperMain \\\n        \"$@\"\n\n# Stop when \"xargs\" is not available.\nif ! command -v xargs >/dev/null 2>&1\nthen\n    die \"xargs is not available\"\nfi\n\n# Use \"xargs\" to parse quoted args.\n#\n# With -n1 it outputs one arg per line, with the quotes and backslashes removed.\n#\n# In Bash we could simply go:\n#\n#   readarray ARGS < <( xargs -n1 <<<\"$var\" ) &&\n#   set -- \"${ARGS[@]}\" \"$@\"\n#\n# but POSIX shell has neither arrays nor command substitution, so instead we\n# post-process each arg (as a line of input to sed) to backslash-escape any\n# character that might be a shell metacharacter, then use eval to reverse\n# that process (while maintaining the separation between arguments), and wrap\n# the whole thing up as a single \"set\" statement.\n#\n# This will of course break if any of these variables contains a newline or\n# an unmatched quote.\n#\n\neval \"set -- $(\n        printf '%s\\n' \"$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS\" |\n        xargs -n1 |\n        sed ' s~[^-[:alnum:]+,./:=@_]~\\\\&~g; ' |\n        tr '\\n' ' '\n    )\" '\"$@\"'\n\nexec \"$JAVACMD\" \"$@\"\n"
  },
  {
    "path": "gradlew.bat",
    "content": "@rem\r\n@rem Copyright 2015 the original author or authors.\r\n@rem\r\n@rem Licensed under the Apache License, Version 2.0 (the \"License\");\r\n@rem you may not use this file except in compliance with the License.\r\n@rem You may obtain a copy of the License at\r\n@rem\r\n@rem      https://www.apache.org/licenses/LICENSE-2.0\r\n@rem\r\n@rem Unless required by applicable law or agreed to in writing, software\r\n@rem distributed under the License is distributed on an \"AS IS\" BASIS,\r\n@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n@rem See the License for the specific language governing permissions and\r\n@rem limitations under the License.\r\n@rem\r\n\r\n@if \"%DEBUG%\"==\"\" @echo off\r\n@rem ##########################################################################\r\n@rem\r\n@rem  Gradle startup script for Windows\r\n@rem\r\n@rem ##########################################################################\r\n\r\n@rem Set local scope for the variables with windows NT shell\r\nif \"%OS%\"==\"Windows_NT\" setlocal\r\n\r\nset DIRNAME=%~dp0\r\nif \"%DIRNAME%\"==\"\" set DIRNAME=.\r\nset APP_BASE_NAME=%~n0\r\nset APP_HOME=%DIRNAME%\r\n\r\n@rem Resolve any \".\" and \"..\" in APP_HOME to make it shorter.\r\nfor %%i in (\"%APP_HOME%\") do set APP_HOME=%%~fi\r\n\r\n@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\r\nset DEFAULT_JVM_OPTS=\"-Xmx64m\" \"-Xms64m\"\r\n\r\n@rem Find java.exe\r\nif defined JAVA_HOME goto findJavaFromJavaHome\r\n\r\nset JAVA_EXE=java.exe\r\n%JAVA_EXE% -version >NUL 2>&1\r\nif %ERRORLEVEL% equ 0 goto execute\r\n\r\necho.\r\necho ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.\r\necho.\r\necho Please set the JAVA_HOME variable in your environment to match the\r\necho location of your Java installation.\r\n\r\ngoto fail\r\n\r\n:findJavaFromJavaHome\r\nset JAVA_HOME=%JAVA_HOME:\"=%\r\nset JAVA_EXE=%JAVA_HOME%/bin/java.exe\r\n\r\nif exist \"%JAVA_EXE%\" goto execute\r\n\r\necho.\r\necho ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%\r\necho.\r\necho Please set the JAVA_HOME variable in your environment to match the\r\necho location of your Java installation.\r\n\r\ngoto fail\r\n\r\n:execute\r\n@rem Setup the command line\r\n\r\nset CLASSPATH=%APP_HOME%\\gradle\\wrapper\\gradle-wrapper.jar\r\n\r\n\r\n@rem Execute Gradle\r\n\"%JAVA_EXE%\" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% \"-Dorg.gradle.appname=%APP_BASE_NAME%\" -classpath \"%CLASSPATH%\" org.gradle.wrapper.GradleWrapperMain %*\r\n\r\n:end\r\n@rem End local scope for the variables with windows NT shell\r\nif %ERRORLEVEL% equ 0 goto mainEnd\r\n\r\n:fail\r\nrem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of\r\nrem the _cmd.exe /c_ return code!\r\nset EXIT_CODE=%ERRORLEVEL%\r\nif %EXIT_CODE% equ 0 set EXIT_CODE=1\r\nif not \"\"==\"%GRADLE_EXIT_CONSOLE%\" exit %EXIT_CODE%\r\nexit /b %EXIT_CODE%\r\n\r\n:mainEnd\r\nif \"%OS%\"==\"Windows_NT\" endlocal\r\n\r\n:omega\r\n"
  },
  {
    "path": "latest",
    "content": ""
  },
  {
    "path": "library-benchmarks/build.gradle",
    "content": "buildscript {\n    def properties = new Properties()\n    properties.load(new FileInputStream(\"${rootDir}/../dependencies.list\"))\n    ext.kotlin_version = properties.get('KOTLIN')\n    repositories {\n        mavenLocal()\n        google()\n        jcenter()\n    }\n    dependencies {\n        classpath \"androidx.benchmark:benchmark-gradle-plugin:1.0.0-rc01\"\n        classpath \"com.android.tools.build:gradle:${properties.get(\"GRADLE_BUILD_TOOLS\")}\"\n        classpath \"io.realm:realm-gradle-plugin:${file(\"${rootDir}/../version.txt\").text.trim()}\"\n        classpath \"org.jetbrains.kotlin:kotlin-gradle-plugin:${properties.get(\"KOTLIN\")}\"\n    }\n}\n\nallprojects {\n    def props = new Properties()\n    props.load(new FileInputStream(\"${rootDir}/../dependencies.list\"))\n    props.each { key, val ->\n        project.ext.set(key, val)\n    }\n}\n\napply plugin: 'com.android.library'\napply plugin: 'kotlin-android'\napply plugin: 'kotlin-kapt'\napply plugin: 'kotlin-android-extensions'\napply plugin: 'realm-android'\napply plugin: 'androidx.benchmark'\n\nandroid {\n    compileSdkVersion 28\n    buildToolsVersion \"${project.ext.get(\"ANDROID_BUILD_TOOLS\")}\"\n\n    defaultConfig {\n        minSdkVersion 16\n        targetSdkVersion 28\n        versionCode 1\n        versionName \"1.0\"\n        testInstrumentationRunner \"androidx.benchmark.junit4.AndroidBenchmarkRunner\"\n        testInstrumentationRunnerArgument 'androidx.benchmark.suppressErrors', 'EMULATOR,UNLOCKED'\n    }\n\n    buildTypes {\n        debug {\n            minifyEnabled = false\n            // Running with DEBUG = true will disable the JIT\n            debuggable = false\n        }\n    }\n\n    compileOptions {\n        sourceCompatibility JavaVersion.VERSION_11\n        targetCompatibility JavaVersion.VERSION_11\n    }\n\n    kotlinOptions {\n        jvmTarget = '11'\n    }\n}\n\nrepositories {\n    mavenLocal()\n    google()\n    jcenter()\n}\n\ndependencies {\n    androidTestImplementation 'androidx.test.ext:junit:1.1.1'\n    androidTestImplementation \"androidx.benchmark:benchmark-junit4:1.0.0-rc01\"\n    androidTestImplementation 'junit:junit:4.12'\n    implementation \"org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version\"\n}\n"
  },
  {
    "path": "library-benchmarks/gradle/wrapper/gradle-wrapper.properties",
    "content": "distributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\ndistributionUrl=https\\://services.gradle.org/distributions/gradle-7.5-all.zip\nzipStoreBase=GRADLE_USER_HOME\nzipStorePath=wrapper/dists\n"
  },
  {
    "path": "library-benchmarks/gradle.properties",
    "content": "org.gradle.caching=true\nandroid.enableD8=true"
  },
  {
    "path": "library-benchmarks/gradlew",
    "content": "#!/bin/sh\n\n#\n# Copyright © 2015-2021 the original authors.\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#      https://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##############################################################################\n#\n#   Gradle start up script for POSIX generated by Gradle.\n#\n#   Important for running:\n#\n#   (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is\n#       noncompliant, but you have some other compliant shell such as ksh or\n#       bash, then to run this script, type that shell name before the whole\n#       command line, like:\n#\n#           ksh Gradle\n#\n#       Busybox and similar reduced shells will NOT work, because this script\n#       requires all of these POSIX shell features:\n#         * functions;\n#         * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,\n#           «${var#prefix}», «${var%suffix}», and «$( cmd )»;\n#         * compound commands having a testable exit status, especially «case»;\n#         * various built-in commands including «command», «set», and «ulimit».\n#\n#   Important for patching:\n#\n#   (2) This script targets any POSIX shell, so it avoids extensions provided\n#       by Bash, Ksh, etc; in particular arrays are avoided.\n#\n#       The \"traditional\" practice of packing multiple parameters into a\n#       space-separated string is a well documented source of bugs and security\n#       problems, so this is (mostly) avoided, by progressively accumulating\n#       options in \"$@\", and eventually passing that to Java.\n#\n#       Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,\n#       and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;\n#       see the in-line comments for details.\n#\n#       There are tweaks for specific operating systems such as AIX, CygWin,\n#       Darwin, MinGW, and NonStop.\n#\n#   (3) This script is generated from the Groovy template\n#       https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt\n#       within the Gradle project.\n#\n#       You can find Gradle at https://github.com/gradle/gradle/.\n#\n##############################################################################\n\n# Attempt to set APP_HOME\n\n# Resolve links: $0 may be a link\napp_path=$0\n\n# Need this for daisy-chained symlinks.\nwhile\n    APP_HOME=${app_path%\"${app_path##*/}\"}  # leaves a trailing /; empty if no leading path\n    [ -h \"$app_path\" ]\ndo\n    ls=$( ls -ld \"$app_path\" )\n    link=${ls#*' -> '}\n    case $link in             #(\n      /*)   app_path=$link ;; #(\n      *)    app_path=$APP_HOME$link ;;\n    esac\ndone\n\nAPP_HOME=$( cd \"${APP_HOME:-./}\" && pwd -P ) || exit\n\nAPP_NAME=\"Gradle\"\nAPP_BASE_NAME=${0##*/}\n\n# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\nDEFAULT_JVM_OPTS='\"-Xmx64m\" \"-Xms64m\"'\n\n# Use the maximum available, or set MAX_FD != -1 to use that value.\nMAX_FD=maximum\n\nwarn () {\n    echo \"$*\"\n} >&2\n\ndie () {\n    echo\n    echo \"$*\"\n    echo\n    exit 1\n} >&2\n\n# OS specific support (must be 'true' or 'false').\ncygwin=false\nmsys=false\ndarwin=false\nnonstop=false\ncase \"$( uname )\" in                #(\n  CYGWIN* )         cygwin=true  ;; #(\n  Darwin* )         darwin=true  ;; #(\n  MSYS* | MINGW* )  msys=true    ;; #(\n  NONSTOP* )        nonstop=true ;;\nesac\n\nCLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar\n\n\n# Determine the Java command to use to start the JVM.\nif [ -n \"$JAVA_HOME\" ] ; then\n    if [ -x \"$JAVA_HOME/jre/sh/java\" ] ; then\n        # IBM's JDK on AIX uses strange locations for the executables\n        JAVACMD=$JAVA_HOME/jre/sh/java\n    else\n        JAVACMD=$JAVA_HOME/bin/java\n    fi\n    if [ ! -x \"$JAVACMD\" ] ; then\n        die \"ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME\n\nPlease set the JAVA_HOME variable in your environment to match the\nlocation of your Java installation.\"\n    fi\nelse\n    JAVACMD=java\n    which java >/dev/null 2>&1 || die \"ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.\n\nPlease set the JAVA_HOME variable in your environment to match the\nlocation of your Java installation.\"\nfi\n\n# Increase the maximum file descriptors if we can.\nif ! \"$cygwin\" && ! \"$darwin\" && ! \"$nonstop\" ; then\n    case $MAX_FD in #(\n      max*)\n        MAX_FD=$( ulimit -H -n ) ||\n            warn \"Could not query maximum file descriptor limit\"\n    esac\n    case $MAX_FD in  #(\n      '' | soft) :;; #(\n      *)\n        ulimit -n \"$MAX_FD\" ||\n            warn \"Could not set maximum file descriptor limit to $MAX_FD\"\n    esac\nfi\n\n# Collect all arguments for the java command, stacking in reverse order:\n#   * args from the command line\n#   * the main class name\n#   * -classpath\n#   * -D...appname settings\n#   * --module-path (only if needed)\n#   * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.\n\n# For Cygwin or MSYS, switch paths to Windows format before running java\nif \"$cygwin\" || \"$msys\" ; then\n    APP_HOME=$( cygpath --path --mixed \"$APP_HOME\" )\n    CLASSPATH=$( cygpath --path --mixed \"$CLASSPATH\" )\n\n    JAVACMD=$( cygpath --unix \"$JAVACMD\" )\n\n    # Now convert the arguments - kludge to limit ourselves to /bin/sh\n    for arg do\n        if\n            case $arg in                                #(\n              -*)   false ;;                            # don't mess with options #(\n              /?*)  t=${arg#/} t=/${t%%/*}              # looks like a POSIX filepath\n                    [ -e \"$t\" ] ;;                      #(\n              *)    false ;;\n            esac\n        then\n            arg=$( cygpath --path --ignore --mixed \"$arg\" )\n        fi\n        # Roll the args list around exactly as many times as the number of\n        # args, so each arg winds up back in the position where it started, but\n        # possibly modified.\n        #\n        # NB: a `for` loop captures its iteration list before it begins, so\n        # changing the positional parameters here affects neither the number of\n        # iterations, nor the values presented in `arg`.\n        shift                   # remove old arg\n        set -- \"$@\" \"$arg\"      # push replacement arg\n    done\nfi\n\n# Collect all arguments for the java command;\n#   * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of\n#     shell script including quotes and variable substitutions, so put them in\n#     double quotes to make sure that they get re-expanded; and\n#   * put everything else in single quotes, so that it's not re-expanded.\n\nset -- \\\n        \"-Dorg.gradle.appname=$APP_BASE_NAME\" \\\n        -classpath \"$CLASSPATH\" \\\n        org.gradle.wrapper.GradleWrapperMain \\\n        \"$@\"\n\n# Stop when \"xargs\" is not available.\nif ! command -v xargs >/dev/null 2>&1\nthen\n    die \"xargs is not available\"\nfi\n\n# Use \"xargs\" to parse quoted args.\n#\n# With -n1 it outputs one arg per line, with the quotes and backslashes removed.\n#\n# In Bash we could simply go:\n#\n#   readarray ARGS < <( xargs -n1 <<<\"$var\" ) &&\n#   set -- \"${ARGS[@]}\" \"$@\"\n#\n# but POSIX shell has neither arrays nor command substitution, so instead we\n# post-process each arg (as a line of input to sed) to backslash-escape any\n# character that might be a shell metacharacter, then use eval to reverse\n# that process (while maintaining the separation between arguments), and wrap\n# the whole thing up as a single \"set\" statement.\n#\n# This will of course break if any of these variables contains a newline or\n# an unmatched quote.\n#\n\neval \"set -- $(\n        printf '%s\\n' \"$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS\" |\n        xargs -n1 |\n        sed ' s~[^-[:alnum:]+,./:=@_]~\\\\&~g; ' |\n        tr '\\n' ' '\n    )\" '\"$@\"'\n\nexec \"$JAVACMD\" \"$@\"\n"
  },
  {
    "path": "library-benchmarks/gradlew.bat",
    "content": "@rem\r\n@rem Copyright 2015 the original author or authors.\r\n@rem\r\n@rem Licensed under the Apache License, Version 2.0 (the \"License\");\r\n@rem you may not use this file except in compliance with the License.\r\n@rem You may obtain a copy of the License at\r\n@rem\r\n@rem      https://www.apache.org/licenses/LICENSE-2.0\r\n@rem\r\n@rem Unless required by applicable law or agreed to in writing, software\r\n@rem distributed under the License is distributed on an \"AS IS\" BASIS,\r\n@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n@rem See the License for the specific language governing permissions and\r\n@rem limitations under the License.\r\n@rem\r\n\r\n@if \"%DEBUG%\"==\"\" @echo off\r\n@rem ##########################################################################\r\n@rem\r\n@rem  Gradle startup script for Windows\r\n@rem\r\n@rem ##########################################################################\r\n\r\n@rem Set local scope for the variables with windows NT shell\r\nif \"%OS%\"==\"Windows_NT\" setlocal\r\n\r\nset DIRNAME=%~dp0\r\nif \"%DIRNAME%\"==\"\" set DIRNAME=.\r\nset APP_BASE_NAME=%~n0\r\nset APP_HOME=%DIRNAME%\r\n\r\n@rem Resolve any \".\" and \"..\" in APP_HOME to make it shorter.\r\nfor %%i in (\"%APP_HOME%\") do set APP_HOME=%%~fi\r\n\r\n@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\r\nset DEFAULT_JVM_OPTS=\"-Xmx64m\" \"-Xms64m\"\r\n\r\n@rem Find java.exe\r\nif defined JAVA_HOME goto findJavaFromJavaHome\r\n\r\nset JAVA_EXE=java.exe\r\n%JAVA_EXE% -version >NUL 2>&1\r\nif %ERRORLEVEL% equ 0 goto execute\r\n\r\necho.\r\necho ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.\r\necho.\r\necho Please set the JAVA_HOME variable in your environment to match the\r\necho location of your Java installation.\r\n\r\ngoto fail\r\n\r\n:findJavaFromJavaHome\r\nset JAVA_HOME=%JAVA_HOME:\"=%\r\nset JAVA_EXE=%JAVA_HOME%/bin/java.exe\r\n\r\nif exist \"%JAVA_EXE%\" goto execute\r\n\r\necho.\r\necho ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%\r\necho.\r\necho Please set the JAVA_HOME variable in your environment to match the\r\necho location of your Java installation.\r\n\r\ngoto fail\r\n\r\n:execute\r\n@rem Setup the command line\r\n\r\nset CLASSPATH=%APP_HOME%\\gradle\\wrapper\\gradle-wrapper.jar\r\n\r\n\r\n@rem Execute Gradle\r\n\"%JAVA_EXE%\" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% \"-Dorg.gradle.appname=%APP_BASE_NAME%\" -classpath \"%CLASSPATH%\" org.gradle.wrapper.GradleWrapperMain %*\r\n\r\n:end\r\n@rem End local scope for the variables with windows NT shell\r\nif %ERRORLEVEL% equ 0 goto mainEnd\r\n\r\n:fail\r\nrem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of\r\nrem the _cmd.exe /c_ return code!\r\nset EXIT_CODE=%ERRORLEVEL%\r\nif %EXIT_CODE% equ 0 set EXIT_CODE=1\r\nif not \"\"==\"%GRADLE_EXIT_CONSOLE%\" exit %EXIT_CODE%\r\nexit /b %EXIT_CODE%\r\n\r\n:mainEnd\r\nif \"%OS%\"==\"Windows_NT\" endlocal\r\n\r\n:omega\r\n"
  },
  {
    "path": "library-benchmarks/settings.gradle",
    "content": "rootProject.name = 'realm-library-benchmarks'"
  },
  {
    "path": "library-benchmarks/src/androidTest/AndroidManifest.xml",
    "content": "<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    package=\"io.realm.benchmarks\">\n\n    <application\n        android:debuggable=\"false\"\n        tools:ignore=\"HardcodedDebugMode\"\n        tools:replace=\"android:debuggable\"/>\n\n</manifest>\n"
  },
  {
    "path": "library-benchmarks/src/androidTest/java/io/realm/benchmarks/CopyToRealmBenchmarks.kt",
    "content": "/* Copyright 2019 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\npackage io.realm.benchmarks\n\nimport androidx.benchmark.junit4.BenchmarkRule\nimport androidx.benchmark.junit4.measureRepeated\nimport androidx.test.ext.junit.runners.AndroidJUnit4\nimport androidx.test.platform.app.InstrumentationRegistry\nimport io.realm.Realm\nimport io.realm.RealmConfiguration\nimport io.realm.RealmList\nimport io.realm.benchmarks.entities.AllTypes\nimport io.realm.benchmarks.entities.AllTypesPrimaryKey\nimport org.junit.After\nimport org.junit.Before\nimport org.junit.Rule\nimport org.junit.Test\nimport org.junit.runner.RunWith\nimport java.util.*\n\n\n@RunWith(AndroidJUnit4::class)\nclass CopyToRealmBenchmarks {\n\n    @get:Rule\n    val benchmarkRule = BenchmarkRule()\n\n    private val COLLECTION_SIZE = 100\n    private lateinit var realm: Realm\n    private val noPkObjects = ArrayList<AllTypes>(COLLECTION_SIZE)\n    private val pkObjects = ArrayList<AllTypesPrimaryKey>(COLLECTION_SIZE)\n    private lateinit var complextTestObjects: ArrayList<AllTypesPrimaryKey>\n    private lateinit var simpleTestObjects: ArrayList<AllTypes>\n\n    @Before\n    fun before() {\n        Realm.init(InstrumentationRegistry.getInstrumentation().targetContext)\n        val config = RealmConfiguration.Builder().build()\n        Realm.deleteRealm(config)\n\n        // Create test data\n        complextTestObjects = ArrayList()\n        for (i in 0 until COLLECTION_SIZE) {\n            val obj = AllTypesPrimaryKey()\n            obj.columnString = \"obj$i\"\n            obj.columnLong = i.toLong()\n            obj.columnFloat = 1.23f\n            obj.columnDouble = 1.234\n            obj.isColumnBoolean = true\n            obj.columnDate = Date(1000)\n            obj.columnBinary = byteArrayOf(1, 2, 3)\n            obj.columnRealmObject = obj\n            obj.columnRealmList = RealmList(obj, obj, obj)\n            obj.columnBooleanList = RealmList(true, false, true)\n            obj.columnStringList = RealmList(\"foo\", \"bar\", \"baz\")\n            obj.columnBinaryList = RealmList(byteArrayOf(0, 1, 2), byteArrayOf(2, 3, 4), byteArrayOf(4, 5, 6))\n            obj.columnByteList = RealmList(1.toByte(), 2.toByte(), 3.toByte())\n            obj.columnShortList = RealmList(1.toShort(), 2.toShort(), 3.toShort())\n            obj.columnIntegerList = RealmList(1, 2, 3)\n            obj.columnLongList = RealmList(1L, 2L, 3L)\n            obj.columnFloatList = RealmList(1.1f, 1.2f, 1.3f)\n            obj.columnDoubleList = RealmList(1.111, 1.222, 1.333)\n            obj.columnDateList = RealmList(Date(1000), Date(2000), Date(3000))\n            complextTestObjects.add(obj)\n        }\n\n        simpleTestObjects = ArrayList()\n        for (i in 0 until COLLECTION_SIZE) {\n            val obj = AllTypes()\n            obj.columnString = \"obj$i\"\n            obj.columnLong = i.toLong()\n            obj.columnFloat = 1.23f\n            obj.columnDouble = 1.234\n            obj.isColumnBoolean = true\n            obj.columnDate = Date(1000)\n            obj.columnBinary = byteArrayOf(1, 2, 3)\n            simpleTestObjects.add(obj)\n        }\n\n        // Setup Realm before test\n        realm = Realm.getInstance(config)\n        realm.beginTransaction()\n    }\n\n    @After\n    fun after() {\n        realm.cancelTransaction()\n        realm.close()\n    }\n\n    @Test\n    fun copyToRealm_complexObjects() = benchmarkRule.measureRepeated {\n        realm.copyToRealmOrUpdate(complextTestObjects)\n    }\n\n    @Test\n    fun copyToRealm_simpleObjects() = benchmarkRule.measureRepeated {\n        realm.copyToRealm(simpleTestObjects)\n    }\n\n}\n"
  },
  {
    "path": "library-benchmarks/src/androidTest/java/io/realm/benchmarks/CopyToRealmOrUpdateBenchmarks.kt",
    "content": "/* Copyright 2019 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\npackage io.realm.benchmarks\n\nimport androidx.benchmark.junit4.BenchmarkRule\nimport androidx.benchmark.junit4.measureRepeated\nimport androidx.test.platform.app.InstrumentationRegistry\nimport androidx.test.ext.junit.runners.AndroidJUnit4\nimport io.realm.ImportFlag\nimport io.realm.Realm\nimport io.realm.RealmConfiguration\nimport io.realm.RealmList\nimport io.realm.benchmarks.entities.AllTypes\nimport io.realm.benchmarks.entities.AllTypesPrimaryKey\nimport org.junit.After\nimport org.junit.Before\nimport org.junit.Rule\nimport org.junit.Test\nimport org.junit.runner.RunWith\nimport java.util.*\n\n\n@RunWith(AndroidJUnit4::class)\nclass CopyToRealmOrUpdateBenchmarks {\n\n    @get:Rule\n    val benchmarkRule = BenchmarkRule()\n\n    private val COLLECTION_SIZE = 100\n    private lateinit var realm: Realm\n    private val noPkObjects = ArrayList<AllTypes>(COLLECTION_SIZE)\n    private val pkObjects = ArrayList<AllTypesPrimaryKey>(COLLECTION_SIZE)\n    private var complextTestObjects: ArrayList<AllTypesPrimaryKey>? = null\n    private var simpleTestObjects: ArrayList<AllTypes>? = null\n\n    @Before\n    fun before() {\n        Realm.init(InstrumentationRegistry.getInstrumentation().targetContext)\n        val config = RealmConfiguration.Builder().build()\n        Realm.deleteRealm(config)\n\n        // Setup Realm before test\n        realm = Realm.getInstance(config)\n        realm.beginTransaction()\n\n        // Create test data\n        complextTestObjects = ArrayList()\n        for (i in 0 until COLLECTION_SIZE) {\n            val obj = AllTypesPrimaryKey()\n            obj.columnString = \"obj$i\"\n            obj.columnLong = i.toLong()\n            obj.columnFloat = 1.23f\n            obj.columnDouble = 1.234\n            obj.isColumnBoolean = true\n            obj.columnDate = Date(1000)\n            obj.columnBinary = byteArrayOf(1, 2, 3)\n            obj.columnRealmObject = obj\n            obj.columnRealmList = RealmList(obj, obj, obj)\n            obj.columnBooleanList = RealmList(true, false, true)\n            obj.columnStringList = RealmList(\"foo\", \"bar\", \"baz\")\n            obj.columnBinaryList = RealmList(byteArrayOf(0, 1, 2), byteArrayOf(2, 3, 4), byteArrayOf(4, 5, 6))\n            obj.columnByteList = RealmList(1.toByte(), 2.toByte(), 3.toByte())\n            obj.columnShortList = RealmList(1.toShort(), 2.toShort(), 3.toShort())\n            obj.columnIntegerList = RealmList(1, 2, 3)\n            obj.columnLongList = RealmList(1L, 2L, 3L)\n            obj.columnFloatList = RealmList(1.1f, 1.2f, 1.3f)\n            obj.columnDoubleList = RealmList(1.111, 1.222, 1.333)\n            obj.columnDateList = RealmList(Date(1000), Date(2000), Date(3000))\n            complextTestObjects!!.add(obj)\n        }\n\n        simpleTestObjects = ArrayList()\n        for (i in 0 until COLLECTION_SIZE) {\n            val obj = AllTypes()\n            obj.columnString = \"obj$i\"\n            obj.columnLong = i.toLong()\n            obj.columnFloat = 1.23f\n            obj.columnDouble = 1.234\n            obj.isColumnBoolean = true\n            obj.columnDate = Date(1000)\n            obj.columnBinary = byteArrayOf(1, 2, 3)\n            simpleTestObjects!!.add(obj)\n        }\n\n        realm.copyToRealmOrUpdate(complextTestObjects)\n        realm.copyToRealmOrUpdate(simpleTestObjects)\n        realm.commitTransaction()\n        realm.beginTransaction()\n    }\n\n    @After\n    fun after() {\n        realm.cancelTransaction()\n        realm.close()\n    }\n\n    @Test\n    fun copyToRealmOrDiffedUpdate_complexObjects() {\n        benchmarkRule.measureRepeated {\n            realm.copyToRealmOrUpdate(complextTestObjects, ImportFlag.CHECK_SAME_VALUES_BEFORE_SET)\n        }\n    }\n\n    @Test\n    fun copyToRealmOrFullUpdate_complexObjects() {\n        benchmarkRule.measureRepeated {\n            realm.copyToRealmOrUpdate(complextTestObjects)\n        }\n    }\n\n    @Test\n    fun copyToRealmOrDiffedUpdate_simpleObjects() {\n        benchmarkRule.measureRepeated {\n            realm.copyToRealm(simpleTestObjects, ImportFlag.CHECK_SAME_VALUES_BEFORE_SET)\n        }\n    }\n\n    @Test\n    fun copyToRealmOrFullUpdate_simpleObjects() {\n        benchmarkRule.measureRepeated {\n            realm.copyToRealm(simpleTestObjects)\n        }\n    }\n\n}\n"
  },
  {
    "path": "library-benchmarks/src/androidTest/java/io/realm/benchmarks/FrozenObjectsBenchmarks.kt",
    "content": "/*\n * Copyright 2019 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\npackage io.realm.benchmarks\n\nimport androidx.benchmark.junit4.BenchmarkRule\nimport androidx.benchmark.junit4.measureRepeated\nimport androidx.test.ext.junit.runners.AndroidJUnit4\nimport androidx.test.platform.app.InstrumentationRegistry\nimport io.realm.Realm\nimport io.realm.RealmConfiguration\nimport io.realm.RealmList\nimport io.realm.RealmResults\nimport io.realm.benchmarks.entities.AllTypes\nimport io.realm.kotlin.createObject\nimport io.realm.kotlin.where\nimport io.realm.log.RealmLog\nimport org.junit.After\nimport org.junit.Before\nimport org.junit.Rule\nimport org.junit.Test\nimport org.junit.runner.RunWith\nimport java.util.*\n\n@RunWith(AndroidJUnit4::class)\nclass FrozenObjectsBenchmarks {\n\n    @get:Rule\n    val benchmarkRule = BenchmarkRule()\n\n    private lateinit var realm: Realm\n    private lateinit var readObject: AllTypes\n    private lateinit var realmConfig: RealmConfiguration\n\n    @Before\n    fun setUp() {\n        Realm.init(InstrumentationRegistry.getInstrumentation().context)\n        RealmLog.error(\"SETUP\")\n        realmConfig = RealmConfiguration.Builder().name(\"frozen${Random().nextLong()}.realm\").build()\n        realm = Realm.getInstance(realmConfig)\n        realm.executeTransaction { realm ->\n            readObject = realm.createObject(AllTypes::class.java)\n            readObject.columnString = \"Foo\"\n            readObject.columnLong = 42\n            readObject.columnDouble = 1.234\n        }\n    }\n\n    @After\n    fun tearDown() {\n        RealmLog.error(\"TEAR_DOWN\");\n        realm.close()\n    }\n\n    @Test\n    fun freezeRealm() {\n        benchmarkRule.measureRepeated {\n            // Skip caching in Java and directly measure how fast it is to freeze the SharedRealm.\n            // ObjectStore do not cache it, so it should be safe to run in a loop.\n            realm.sharedRealm.freeze()\n        }\n    }\n\n    @Test\n    fun freezeResults() {\n        realm.executeTransaction { r ->\n            for (i in 0..10_0000) {\n                val obj = r.createObject<AllTypes>()\n                obj.columnString= \"String: \" + i\n                obj.columnLong = i.toLong()\n                obj.isColumnBoolean = (i % 2 == 0)\n            }\n        }\n\n        var results: RealmResults<AllTypes> = realm.where<AllTypes>().findAll()\n        benchmarkRule.measureRepeated {\n            results.freeze()\n        }\n    }\n\n    @Test\n    fun freezeList() {\n        var list: RealmList<AllTypes> = RealmList()\n        realm.executeTransaction { r ->\n            for (i in 0..10_0000) {\n                list = readObject.columnRealmList\n                val obj = r.createObject<AllTypes>()\n                obj.columnString= \"String: \" + i\n                obj.columnLong = i.toLong()\n                obj.isColumnBoolean = (i % 2 == 0)\n                list.add(obj)\n            }\n        }\n\n        benchmarkRule.measureRepeated {\n            list.freeze()\n        }\n    }\n\n    @Test\n    fun freezeObject() {\n        benchmarkRule.measureRepeated {\n            readObject.freeze<AllTypes>()\n        }\n    }\n}\n"
  },
  {
    "path": "library-benchmarks/src/androidTest/java/io/realm/benchmarks/RealmAllocBenchmarks.kt",
    "content": "/*\n * Copyright 2019 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\npackage io.realm.benchmarks\n\nimport androidx.benchmark.junit4.BenchmarkRule\nimport androidx.benchmark.junit4.measureRepeated\nimport androidx.test.ext.junit.runners.AndroidJUnit4\nimport androidx.test.platform.app.InstrumentationRegistry\nimport io.realm.Realm\nimport io.realm.RealmConfiguration\nimport io.realm.benchmarks.entities.AllTypes\nimport org.junit.After\nimport org.junit.Before\nimport org.junit.Rule\nimport org.junit.Test\nimport org.junit.runner.RunWith\n\n\n@RunWith(AndroidJUnit4::class)\nclass RealmAllocBenchmarks {\n\n    @get:Rule\n    val benchmarkRule = BenchmarkRule()\n\n    private lateinit var realm: Realm\n\n    @Before\n    fun before() {\n        Realm.init(InstrumentationRegistry.getInstrumentation().targetContext)\n        val config = RealmConfiguration.Builder().build()\n        Realm.deleteRealm(config)\n        realm = Realm.getInstance(config)\n        realm.beginTransaction()\n        realm.createObject(AllTypes::class.java).columnRealmList.add(realm.createObject(AllTypes::class.java))\n        realm.commitTransaction()\n    }\n\n    @After\n    fun after() {\n        realm.close()\n    }\n\n    @Test\n    fun createObjects() {\n        val results = realm.where(AllTypes::class.java).findAll()\n        benchmarkRule.measureRepeated {\n            results.first()\n        }\n    }\n\n    @Test\n    fun createQueries() {\n        benchmarkRule.measureRepeated {\n            realm.where(AllTypes::class.java)\n        }\n    }\n\n    @Test\n    fun createRealmResults() {\n        val query = realm.where(AllTypes::class.java)\n        benchmarkRule.measureRepeated {\n            query.findAll()\n        }\n    }\n\n    @Test\n    fun createRealmLists() {\n        val allTypes = realm.where(AllTypes::class.java).findFirst()!!\n        benchmarkRule.measureRepeated {\n            allTypes.columnRealmList\n        }\n    }\n}\n"
  },
  {
    "path": "library-benchmarks/src/androidTest/java/io/realm/benchmarks/RealmBenchmarks.kt",
    "content": "/*\n * Copyright 2019 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\npackage io.realm.benchmarks\n\nimport androidx.benchmark.junit4.BenchmarkRule\nimport androidx.benchmark.junit4.measureRepeated\nimport androidx.test.ext.junit.runners.AndroidJUnit4\nimport androidx.test.platform.app.InstrumentationRegistry\nimport io.realm.Realm\nimport io.realm.RealmConfiguration\nimport io.realm.benchmarks.entities.AllTypes\nimport org.junit.After\nimport org.junit.Before\nimport org.junit.Rule\nimport org.junit.Test\nimport org.junit.runner.RunWith\n\n@RunWith(AndroidJUnit4::class)\nclass RealmBenchmarks {\n\n    @get:Rule\n    val benchmarkRule = BenchmarkRule()\n\n    private lateinit var realm: Realm\n    private lateinit var readObject: AllTypes\n    private lateinit var coldConfig: RealmConfiguration\n\n    @Before\n    fun setUp() {\n        Realm.init(InstrumentationRegistry.getInstrumentation().targetContext)\n        coldConfig = RealmConfiguration.Builder().name(\"cold\").build()\n        val config = RealmConfiguration.Builder().build()\n        Realm.deleteRealm(coldConfig)\n        Realm.deleteRealm(config)\n        realm = Realm.getInstance(config)\n        realm.executeTransaction { realm ->\n            readObject = realm.createObject(AllTypes::class.java)\n            readObject.columnString = \"Foo\"\n            readObject.columnLong = 42\n            readObject.columnDouble = 1.234\n        }\n    }\n\n    @After\n    fun tearDown() {\n        realm.close()\n    }\n\n    @Test\n    fun coldCreateAndClose() {\n        benchmarkRule.measureRepeated {\n            val realm = Realm.getInstance(coldConfig)\n            realm.close()\n        }\n    }\n\n    @Test\n    fun emptyTransaction() {\n        benchmarkRule.measureRepeated {\n            realm.beginTransaction()\n            realm.commitTransaction()\n        }\n    }\n}\n"
  },
  {
    "path": "library-benchmarks/src/androidTest/java/io/realm/benchmarks/RealmInsertBenchmark.kt",
    "content": "/*\n * Copyright 2019 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\npackage io.realm.benchmarks\n\nimport androidx.benchmark.junit4.BenchmarkRule\nimport androidx.benchmark.junit4.measureRepeated\nimport androidx.test.platform.app.InstrumentationRegistry\nimport androidx.test.ext.junit.runners.AndroidJUnit4\nimport io.realm.Realm\nimport io.realm.RealmConfiguration\nimport io.realm.benchmarks.entities.AllTypes\nimport io.realm.benchmarks.entities.AllTypesPrimaryKey\nimport org.junit.After\nimport org.junit.Before\nimport org.junit.Rule\nimport org.junit.Test\nimport org.junit.runner.RunWith\nimport java.util.*\n\n\n@RunWith(AndroidJUnit4::class)\nclass RealmInsertBenchmark {\n\n    @get:Rule\n    val benchmarkRule = BenchmarkRule()\n\n    private val COLLECTION_SIZE = 100\n    private lateinit var realm: Realm\n    private val noPkObjects = ArrayList<AllTypes>(COLLECTION_SIZE)\n    private val pkObjects = ArrayList<AllTypesPrimaryKey>(COLLECTION_SIZE)\n\n    @Before\n    fun before() {\n        Realm.init(InstrumentationRegistry.getInstrumentation().targetContext)\n        val config = RealmConfiguration.Builder().build()\n        Realm.deleteRealm(config)\n        realm = Realm.getInstance(config)\n\n        for (i in 0 until COLLECTION_SIZE) {\n            noPkObjects.add(AllTypes())\n        }\n\n        for (i in 0 until COLLECTION_SIZE) {\n            val allTypesPrimaryKey = AllTypesPrimaryKey()\n            allTypesPrimaryKey.columnLong = i.toLong()\n            pkObjects.add(allTypesPrimaryKey)\n        }\n\n        realm.beginTransaction()\n    }\n\n    @After\n    fun after() {\n        realm.cancelTransaction()\n        realm.close()\n    }\n\n    @Test\n    fun insertNoPrimaryKey() {\n        val allTypes = AllTypes()\n        benchmarkRule.measureRepeated {\n            realm.insert(allTypes)\n        }\n    }\n\n    @Test\n    fun insertNoPrimaryKeyList() {\n        benchmarkRule.measureRepeated {\n            realm.insert(noPkObjects)\n        }\n    }\n\n    @Test\n    fun insertWithPrimaryKey() {\n        val allTypesPrimaryKey = AllTypesPrimaryKey()\n        var i: Long = 0\n        benchmarkRule.measureRepeated {\n            allTypesPrimaryKey.columnLong = (i++)\n            realm.insertOrUpdate(allTypesPrimaryKey)\n        }\n    }\n\n    @Test\n    fun insertOrUpdateWithPrimaryKeyList() {\n        benchmarkRule.measureRepeated {\n            realm.insertOrUpdate(pkObjects)\n        }\n    }\n\n}\n"
  },
  {
    "path": "library-benchmarks/src/androidTest/java/io/realm/benchmarks/RealmObjectReadBenchmarks.kt",
    "content": "/*\n * Copyright 2019 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\npackage io.realm.benchmarks\n\nimport androidx.benchmark.junit4.BenchmarkRule\nimport androidx.benchmark.junit4.measureRepeated\nimport androidx.test.platform.app.InstrumentationRegistry\nimport androidx.test.ext.junit.runners.AndroidJUnit4\n\nimport org.junit.runner.RunWith\n\nimport io.realm.Realm\nimport io.realm.RealmConfiguration\nimport io.realm.benchmarks.entities.AllTypes\nimport org.junit.After\nimport org.junit.Before\nimport org.junit.Rule\nimport org.junit.Test\n\n\n@RunWith(AndroidJUnit4::class)\nclass RealmObjectReadBenchmarks {\n\n    @get:Rule\n    val benchmarkRule = BenchmarkRule()\n\n    private lateinit var realm: Realm\n    private lateinit var readObject: AllTypes\n\n    @Before\n    fun before() {\n        Realm.init(InstrumentationRegistry.getInstrumentation().targetContext)\n        val config = RealmConfiguration.Builder().build()\n        Realm.deleteRealm(config)\n        realm = Realm.getInstance(config)\n        realm.executeTransaction { realm ->\n            readObject = realm.createObject(AllTypes::class.java)\n            readObject.columnString = \"Foo\"\n            readObject.columnLong = 42\n            readObject.columnDouble = 1.234\n        }\n    }\n\n    @After\n    fun after() {\n        realm.close()\n    }\n\n    @Test\n    fun readString() {\n        benchmarkRule.measureRepeated {\n            val value = readObject.columnString\n        }\n    }\n\n    @Test\n    fun readLong() {\n        benchmarkRule.measureRepeated {\n            val value = readObject.columnLong\n        }\n    }\n\n    @Test\n    fun readDouble() {\n        benchmarkRule.measureRepeated {\n            val value = readObject.columnDouble\n        }\n    }\n}\n"
  },
  {
    "path": "library-benchmarks/src/androidTest/java/io/realm/benchmarks/RealmObjectWriteBenchmarks.kt",
    "content": "/*\n * Copyright 2019 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\npackage io.realm.benchmarks\n\nimport androidx.benchmark.junit4.BenchmarkRule\nimport androidx.benchmark.junit4.measureRepeated\nimport androidx.test.ext.junit.runners.AndroidJUnit4\nimport io.realm.Realm\nimport io.realm.RealmConfiguration\nimport io.realm.benchmarks.entities.AllTypes\nimport org.junit.After\nimport org.junit.Before\nimport org.junit.Rule\nimport org.junit.Test\nimport org.junit.runner.RunWith\n\n\n@RunWith(AndroidJUnit4::class)\nclass RealmObjectWriteBenchmarks {\n\n    @get:Rule\n    val benchmarkRule = BenchmarkRule()\n\n    private lateinit var realm: Realm\n    private lateinit var writeObject: AllTypes\n\n    @Before\n    fun before() {\n        val config = RealmConfiguration.Builder().build()\n        Realm.deleteRealm(config)\n        realm = Realm.getInstance(config)\n        realm.beginTransaction()\n        writeObject = realm.createObject(AllTypes::class.java)\n    }\n\n    @After\n    fun after() {\n        realm.cancelTransaction()\n        realm.close()\n    }\n\n    @Test\n    fun writeShortString() {\n        benchmarkRule.measureRepeated {\n            writeObject.columnString = \"Foo\"\n        }\n    }\n\n    @Test\n    fun writeMediumString() {\n        benchmarkRule.measureRepeated {\n            writeObject.columnString = \"ABCDEFHIJKLMNOPQ\"\n        }\n    }\n\n    @Test\n    fun writeLongString() {\n        benchmarkRule.measureRepeated {\n            writeObject.columnString = \"ABCDEFHIJKLMNOPQABCDEFHIJKLMNOPQABCDEFHIJKLMNOPQABCDEFHIJKLMNOPQ\"\n        }\n    }\n\n    @Test\n    fun writeLong() {\n        benchmarkRule.measureRepeated {\n            writeObject.columnLong = 42\n        }\n    }\n\n    @Test\n    fun writeDouble() {\n        benchmarkRule.measureRepeated {\n            writeObject.columnDouble = 1.234\n        }\n    }\n}\n"
  },
  {
    "path": "library-benchmarks/src/androidTest/java/io/realm/benchmarks/RealmQueryBenchmarks.kt",
    "content": "/*\n * Copyright 2019 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\npackage io.realm.benchmarks\n\nimport androidx.benchmark.junit4.BenchmarkRule\nimport androidx.benchmark.junit4.measureRepeated\nimport androidx.test.ext.junit.runners.AndroidJUnit4\nimport io.realm.Realm\nimport io.realm.RealmConfiguration\nimport io.realm.Sort\nimport io.realm.benchmarks.entities.AllTypes\nimport org.junit.After\nimport org.junit.Before\nimport org.junit.Rule\nimport org.junit.Test\nimport org.junit.runner.RunWith\n\n\n@RunWith(AndroidJUnit4::class)\nclass RealmQueryBenchmarks {\n\n    @get:Rule\n    val benchmarkRule = BenchmarkRule()\n\n    private val DATA_SIZE = 1000\n    private lateinit var realm: Realm\n\n    @Before\n    fun before() {\n        val config = RealmConfiguration.Builder().build()\n        Realm.deleteRealm(config)\n        realm = Realm.getInstance(config)\n        realm.beginTransaction()\n        for (i in 0 until DATA_SIZE) {\n            val obj = realm.createObject(AllTypes::class.java)\n            obj.columnLong = i.toLong()\n            obj.isColumnBoolean = i % 2 == 0\n            obj.columnString = \"Foo $i\"\n            obj.columnDouble = i + 1.234\n        }\n        realm.commitTransaction()\n    }\n\n    @After\n    fun after() {\n        realm.close()\n    }\n\n    @Test\n    fun containsQuery() {\n        benchmarkRule.measureRepeated {\n            val realmResults = realm.where(AllTypes::class.java).contains(AllTypes.FIELD_STRING, \"Foo 1\").findAll()\n        }\n    }\n\n    @Test\n    fun count() {\n        benchmarkRule.measureRepeated {\n            val size = realm.where(AllTypes::class.java).count()\n        }\n    }\n\n    @Test\n    fun findAll() {\n        benchmarkRule.measureRepeated {\n            val results = realm.where(AllTypes::class.java).findAll()\n        }\n    }\n\n    @Test\n    fun findAllSortedOneField() {\n        benchmarkRule.measureRepeated {\n            val results = realm.where(AllTypes::class.java).sort(AllTypes.FIELD_STRING, Sort.ASCENDING).findAll()\n        }\n    }\n\n}\n"
  },
  {
    "path": "library-benchmarks/src/androidTest/java/io/realm/benchmarks/RealmResultsBenchmarks.kt",
    "content": "/*\n * Copyright 2019 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\npackage io.realm.benchmarks\n\nimport androidx.benchmark.junit4.BenchmarkRule\nimport androidx.benchmark.junit4.measureRepeated\nimport androidx.test.platform.app.InstrumentationRegistry\nimport androidx.test.ext.junit.runners.AndroidJUnit4\nimport io.realm.Realm\nimport io.realm.RealmConfiguration\nimport io.realm.RealmResults\nimport io.realm.benchmarks.entities.AllTypes\nimport org.junit.After\nimport org.junit.Before\nimport org.junit.Rule\nimport org.junit.Test\nimport org.junit.runner.RunWith\n\n\n@RunWith(AndroidJUnit4::class)\nclass RealmResultsBenchmarks {\n\n    @get:Rule\n    val benchmarkRule = BenchmarkRule()\n\n    private val DATA_SIZE = 1000\n    private lateinit var realm: Realm\n    private lateinit var results: RealmResults<AllTypes>\n\n    @Before\n    fun before() {\n        Realm.init(InstrumentationRegistry.getInstrumentation().targetContext)\n        val config = RealmConfiguration.Builder().build()\n        Realm.deleteRealm(config)\n        realm = Realm.getInstance(config)\n        realm.beginTransaction()\n        for (i in 0 until DATA_SIZE) {\n            val obj = realm.createObject(AllTypes::class.java)\n            obj.columnLong = i.toLong()\n            obj.isColumnBoolean = i % 2 == 0\n            obj.columnString = \"Foo $i\"\n            obj.columnDouble = i + 1.234\n        }\n        realm.commitTransaction()\n        results = realm.where(AllTypes::class.java).findAll()\n    }\n\n    @After\n    fun after() {\n        realm.close()\n    }\n\n    @Test\n    fun get() {\n        benchmarkRule.measureRepeated {\n            val item = results[0]\n        }\n    }\n\n    @Test\n    fun size() {\n        benchmarkRule.measureRepeated {\n            val size = results.size.toLong()\n        }\n    }\n\n    @Test\n    fun min() {\n        benchmarkRule.measureRepeated {\n            val min = results.min(AllTypes.FIELD_LONG)\n        }\n    }\n\n    @Test\n    fun max() {\n        benchmarkRule.measureRepeated {\n            val max = results.max(AllTypes.FIELD_LONG)\n        }\n    }\n\n    @Test\n    fun average() {\n        benchmarkRule.measureRepeated {\n            val average = results.average(AllTypes.FIELD_LONG)\n        }\n    }\n\n    @Test\n    fun sum() {\n        benchmarkRule.measureRepeated {\n            val sum = results.sum(AllTypes.FIELD_LONG)\n        }\n    }\n\n    @Test\n    fun sort() {\n        benchmarkRule.measureRepeated {\n            val sorted = results.sort(AllTypes.FIELD_STRING)\n        }\n    }\n\n}\n"
  },
  {
    "path": "library-benchmarks/src/androidTest/java/io/realm/benchmarks/entities/AllTypes.java",
    "content": "/*\n * Copyright 2017 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\npackage io.realm.benchmarks.entities;\n\nimport java.util.Date;\n\nimport io.realm.RealmList;\nimport io.realm.RealmObject;\nimport io.realm.annotations.Required;\n\n\npublic class AllTypes extends RealmObject {\n\n    public static final String CLASS_NAME = \"AllTypes\";\n    public static final String FIELD_STRING = \"columnString\";\n    public static final String FIELD_LONG = \"columnLong\";\n    public static final String FIELD_FLOAT = \"columnFloat\";\n    public static final String FIELD_DOUBLE = \"columnDouble\";\n    public static final String FIELD_BOOLEAN = \"columnBoolean\";\n    public static final String FIELD_DATE = \"columnDate\";\n    public static final String FIELD_BINARY = \"columnBinary\";\n    public static final String FIELD_REALMOBJECT = \"columnRealmObject\";\n    public static final String FIELD_REALMLIST = \"columnRealmList\";\n\n    public static final String[] INVALID_TYPES_FIELDS_FOR_DISTINCT = new String[]{FIELD_REALMOBJECT, FIELD_REALMLIST, FIELD_DOUBLE, FIELD_FLOAT};\n\n    @Required\n    private String columnString = \"\";\n    private long columnLong;\n    private float columnFloat;\n    private double columnDouble;\n    private boolean columnBoolean;\n    @Required\n    private Date columnDate = new Date(0);\n    @Required\n    private byte[] columnBinary = new byte[0];\n    private AllTypes columnRealmObject;\n    private RealmList<AllTypes> columnRealmList;\n\n    public String getColumnString() {\n        return columnString;\n    }\n\n    public void setColumnString(String columnString) {\n        this.columnString = columnString;\n    }\n\n    public long getColumnLong() {\n        return columnLong;\n    }\n\n    public void setColumnLong(long columnLong) {\n        this.columnLong = columnLong;\n    }\n\n    public float getColumnFloat() {\n        return columnFloat;\n    }\n\n    public void setColumnFloat(float columnFloat) {\n        this.columnFloat = columnFloat;\n    }\n\n    public double getColumnDouble() {\n        return columnDouble;\n    }\n\n    public void setColumnDouble(double columnDouble) {\n        this.columnDouble = columnDouble;\n    }\n\n    public boolean isColumnBoolean() {\n        return columnBoolean;\n    }\n\n    public void setColumnBoolean(boolean columnBoolean) {\n        this.columnBoolean = columnBoolean;\n    }\n\n    public Date getColumnDate() {\n        return columnDate;\n    }\n\n    public void setColumnDate(Date columnDate) {\n        this.columnDate = columnDate;\n    }\n\n    public byte[] getColumnBinary() {\n        return columnBinary;\n    }\n\n    public void setColumnBinary(byte[] columnBinary) {\n        this.columnBinary = columnBinary;\n    }\n\n    public AllTypes getColumnRealmObject() {\n        return columnRealmObject;\n    }\n\n    public void setColumnRealmObject(AllTypes columnRealmObject) {\n        this.columnRealmObject = columnRealmObject;\n    }\n\n    public RealmList<AllTypes> getColumnRealmList() {\n        return columnRealmList;\n    }\n\n    public void setColumnRealmList(RealmList<AllTypes> columnRealmList) {\n        this.columnRealmList = columnRealmList;\n    }\n}\n"
  },
  {
    "path": "library-benchmarks/src/androidTest/java/io/realm/benchmarks/entities/AllTypesPrimaryKey.java",
    "content": "/*\n * Copyright 2017 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\npackage io.realm.benchmarks.entities;\n\nimport java.util.Date;\n\nimport io.realm.RealmList;\nimport io.realm.RealmObject;\nimport io.realm.annotations.PrimaryKey;\n\n\npublic class AllTypesPrimaryKey extends RealmObject {\n    private String columnString;\n    @PrimaryKey\n    private long columnLong;\n    private float columnFloat;\n    private double columnDouble;\n    private boolean columnBoolean;\n    private Date columnDate;\n    private byte[] columnBinary;\n    private AllTypesPrimaryKey columnRealmObject;\n    private RealmList<AllTypesPrimaryKey> columnRealmList;\n    private Boolean columnBoxedBoolean;\n    private RealmList<String> columnStringList;\n    private RealmList<byte[]> columnBinaryList;\n    private RealmList<Boolean> columnBooleanList;\n    private RealmList<Long> columnLongList;\n    private RealmList<Integer> columnIntegerList;\n    private RealmList<Short> columnShortList;\n    private RealmList<Byte> columnByteList;\n    private RealmList<Double> columnDoubleList;\n    private RealmList<Float> columnFloatList;\n    private RealmList<Date> columnDateList;\n\n    public String getColumnString() {\n        return columnString;\n    }\n\n    public void setColumnString(String columnString) {\n        this.columnString = columnString;\n    }\n\n    public long getColumnLong() {\n        return columnLong;\n    }\n\n    public void setColumnLong(long columnLong) {\n        this.columnLong = columnLong;\n    }\n\n    public float getColumnFloat() {\n        return columnFloat;\n    }\n\n    public void setColumnFloat(float columnFloat) {\n        this.columnFloat = columnFloat;\n    }\n\n    public double getColumnDouble() {\n        return columnDouble;\n    }\n\n    public void setColumnDouble(double columnDouble) {\n        this.columnDouble = columnDouble;\n    }\n\n    public boolean isColumnBoolean() {\n        return columnBoolean;\n    }\n\n    public void setColumnBoolean(boolean columnBoolean) {\n        this.columnBoolean = columnBoolean;\n    }\n\n    public Date getColumnDate() {\n        return columnDate;\n    }\n\n    public void setColumnDate(Date columnDate) {\n        this.columnDate = columnDate;\n    }\n\n    public byte[] getColumnBinary() {\n        return columnBinary;\n    }\n\n    public void setColumnBinary(byte[] columnBinary) {\n        this.columnBinary = columnBinary;\n    }\n\n    public AllTypesPrimaryKey getColumnRealmObject() {\n        return columnRealmObject;\n    }\n\n    public void setColumnRealmObject(AllTypesPrimaryKey columnRealmObject) {\n        this.columnRealmObject = columnRealmObject;\n    }\n\n    public RealmList<AllTypesPrimaryKey> getColumnRealmList() {\n        return columnRealmList;\n    }\n\n    public void setColumnRealmList(RealmList<AllTypesPrimaryKey> columnRealmList) {\n        this.columnRealmList = columnRealmList;\n    }\n\n    public Boolean getColumnBoxedBoolean() {\n        return columnBoxedBoolean;\n    }\n\n    public void setColumnBoxedBoolean(Boolean columnBoxedBoolean) {\n        this.columnBoxedBoolean = columnBoxedBoolean;\n    }\n\n    public RealmList<String> getColumnStringList() {\n        return columnStringList;\n    }\n\n    public void setColumnStringList(RealmList<String> columnStringList) {\n        this.columnStringList = columnStringList;\n    }\n\n    public RealmList<byte[]> getColumnBinaryList() {\n        return columnBinaryList;\n    }\n\n    public void setColumnBinaryList(RealmList<byte[]> columnBinaryList) {\n        this.columnBinaryList = columnBinaryList;\n    }\n\n    public RealmList<Boolean> getColumnBooleanList() {\n        return columnBooleanList;\n    }\n\n    public void setColumnBooleanList(RealmList<Boolean> columnBooleanList) {\n        this.columnBooleanList = columnBooleanList;\n    }\n\n    public RealmList<Long> getColumnLongList() {\n        return columnLongList;\n    }\n\n    public void setColumnLongList(RealmList<Long> columnLongList) {\n        this.columnLongList = columnLongList;\n    }\n\n    public RealmList<Integer> getColumnIntegerList() {\n        return columnIntegerList;\n    }\n\n    public void setColumnIntegerList(RealmList<Integer> columnIntegerList) {\n        this.columnIntegerList = columnIntegerList;\n    }\n\n    public RealmList<Short> getColumnShortList() {\n        return columnShortList;\n    }\n\n    public void setColumnShortList(RealmList<Short> columnShortList) {\n        this.columnShortList = columnShortList;\n    }\n\n    public RealmList<Byte> getColumnByteList() {\n        return columnByteList;\n    }\n\n    public void setColumnByteList(RealmList<Byte> columnByteList) {\n        this.columnByteList = columnByteList;\n    }\n\n    public RealmList<Double> getColumnDoubleList() {\n        return columnDoubleList;\n    }\n\n    public void setColumnDoubleList(RealmList<Double> columnDoubleList) {\n        this.columnDoubleList = columnDoubleList;\n    }\n\n    public RealmList<Float> getColumnFloatList() {\n        return columnFloatList;\n    }\n\n    public void setColumnFloatList(RealmList<Float> columnFloatList) {\n        this.columnFloatList = columnFloatList;\n    }\n\n    public RealmList<Date> getColumnDateList() {\n        return columnDateList;\n    }\n\n    public void setColumnDateList(RealmList<Date> columnDateList) {\n        this.columnDateList = columnDateList;\n    }\n}\n"
  },
  {
    "path": "library-benchmarks/src/main/AndroidManifest.xml",
    "content": "<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    package=\"io.realm.benchmarks\">\n\n    <application />\n\n</manifest>\n"
  },
  {
    "path": "library-build-transformer/.gitignore",
    "content": "out/\n"
  },
  {
    "path": "library-build-transformer/README.md",
    "content": "# Library Transformer\n\nThis project contains a transformer that removes all classes, methods and fields annotated with a\ngiven annotation.\n\nThis can be used to emulate Kotlin extension methods in cases where separating the code into flavour\nfolders is not feasible, like e.g. when the `Realm` class is shared between the `base` and\n`objectServer` flavour.\n\n## Usage\n\nRegister the transformer as normal and provide it with the flavor to strip and annotation to detect\n\n```\nimport io.realm.buildtransformer.RealmBuildTransformer\nandroid.registerTransform(new RealmBuildTransformer(\"base\", \"io.realm.internal.annotations.ObjectServer\", [\n  \"explicit_files_to_remove\"\n]))\n```\n\nIt is also possible to provide a specific list of files that will be removed whether or not they\nhave the annotation. This is used to remove some files created by the annotation processor that do\nnot carry over annotations.\n\n## Warning\n\nThere are no checks in place with regard to it being safe or not to remove classes and methods, so\nonly apply the transformer when it is safe to do so (i.e. the classes/methods/fields are not in use).\nAny errors will only be caught at runtime when the actual code is accessed.\n\n## Known limitations\n\n* If all constructors are stripped by this transformer, a new default constructor will not be\n  created. This will result in invalid byte code being generated.\n\n* If the top-level class is removed, all inner classes, enums and interfaces must also be annotated,\n  otherwise they are not removed, resulting in valid bytecode being generated.\n\n* Annotations on super classes will also remove subclasses, but only the first level of inheritance.\n\n* Single enum values cannot be stripped, only the entire enum class.\n\n## Running unit tests\n\nRunning unit tests can be done from the command line by using:\n\n    >./gradlew test\n\nIt should also be possible to run tests from IntelliJ CE, however in some cases it will report\n\n    \"Cannot find io.realm.buildtransformer.VistitorTests\"\n\nThis is a bug in IntelliJ and can be fixed by:\n\n1) Close the project in IntelliJ\n2) Delete the folder `.idea`\n3) Re-import the project into IntelliJ\n\n"
  },
  {
    "path": "library-build-transformer/build.gradle",
    "content": "buildscript {\n    def properties = new Properties()\n    properties.load(new FileInputStream(\"${projectDir}/../dependencies.list\"))\n    ext.kotlin_version = properties.get('KOTLIN')\n\n    repositories {\n        mavenCentral()\n        jcenter()\n        maven {\n            url \"https://plugins.gradle.org/m2/\"\n        }\n    }\n    dependencies {\n        classpath \"io.github.gradle-nexus:publish-plugin:${properties.get(\"GRADLE_NEXUS_PLUGIN\")}\"\n        classpath \"org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version\"\n    }\n}\n\ngroup = 'io.realm'\nversion = file(\"${projectDir}/../version.txt\").text.trim()\n\napply plugin: 'kotlin'\napply plugin: 'java'\napply plugin: 'maven-publish'\napply from: \"${rootDir}/../mavencentral-publications.gradle\"\n\nrepositories {\n    google()\n    mavenCentral()\n}\ndef properties = new Properties()\nproperties.load(new FileInputStream(\"${projectDir}/../dependencies.list\"))\ndependencies {\n    implementation gradleApi()\n    implementation 'org.ow2.asm:asm:6.2'\n    implementation 'org.ow2.asm:asm-util:6.2'\n    implementation \"org.jetbrains.kotlin:kotlin-stdlib-jdk8:${kotlin_version}\"\n    compileOnly \"com.android.tools.build:gradle:${properties.get(\"GRADLE_BUILD_TOOLS\")}\"\n\n    testImplementation group:'junit', name:'junit', version:'4.12'\n}\n\nsourceCompatibility = JavaVersion.VERSION_11\ntargetCompatibility = JavaVersion.VERSION_11\n\ncompileKotlin {\n    kotlinOptions.jvmTarget = \"11\"\n}\ncompileTestKotlin {\n    kotlinOptions.jvmTarget = \"11\"\n}\n\ndef commonPom = {\n    licenses {\n        license {\n            name 'The Apache Software License, Version 2.0'\n            url 'http://www.apache.org/licenses/LICENSE-2.0.txt'\n            distribution 'repo'\n        }\n    }\n    issueManagement {\n        system 'github'\n        url 'https://github.com/realm/realm-java/issues'\n    }\n    scm {\n        url 'scm:https://github.com/realm/realm-java'\n        connection 'scm:git@github.com:realm/realm-java.git'\n        developerConnection 'scm:git@github.com:realm/realm-java.git'\n    }\n}\n\npublishing {\n    publications {\n        realmPublication(MavenPublication) {\n            groupId 'io.realm'\n            artifactId = 'realm-library-build-transformer'\n            from components.java\n            pom.withXml {\n                Node root = asNode()\n                root.appendNode('name', 'realm-library-build-transformer')\n                root.appendNode('description', 'Transform library for Realm Java that will strip unwanted files at build time.')\n                root.appendNode('url', 'http://realm.io')\n                root.children().last() + commonPom\n            }\n        }\n    }\n    repositories {\n        maven {\n            credentials(AwsCredentials) {\n                accessKey project.hasProperty('s3AccessKey') ? s3AccessKey : 'noAccessKey'\n                secretKey project.hasProperty('s3SecretKey') ? s3SecretKey : 'noSecretKey'\n            }\n            if(project.version.endsWith('-SNAPSHOT')) {\n                url \"s3://realm-ci-artifacts/maven/snapshots/\"\n            } else {\n                url \"s3://realm-ci-artifacts/maven/releases/\"\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "library-build-transformer/gradle/wrapper/gradle-wrapper.properties",
    "content": "distributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\ndistributionUrl=https\\://services.gradle.org/distributions/gradle-7.5-all.zip\nzipStoreBase=GRADLE_USER_HOME\nzipStorePath=wrapper/dists\n"
  },
  {
    "path": "library-build-transformer/gradle.properties",
    "content": "org.gradle.caching=true\n"
  },
  {
    "path": "library-build-transformer/gradlew",
    "content": "#!/bin/sh\n\n#\n# Copyright © 2015-2021 the original authors.\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#      https://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##############################################################################\n#\n#   Gradle start up script for POSIX generated by Gradle.\n#\n#   Important for running:\n#\n#   (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is\n#       noncompliant, but you have some other compliant shell such as ksh or\n#       bash, then to run this script, type that shell name before the whole\n#       command line, like:\n#\n#           ksh Gradle\n#\n#       Busybox and similar reduced shells will NOT work, because this script\n#       requires all of these POSIX shell features:\n#         * functions;\n#         * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,\n#           «${var#prefix}», «${var%suffix}», and «$( cmd )»;\n#         * compound commands having a testable exit status, especially «case»;\n#         * various built-in commands including «command», «set», and «ulimit».\n#\n#   Important for patching:\n#\n#   (2) This script targets any POSIX shell, so it avoids extensions provided\n#       by Bash, Ksh, etc; in particular arrays are avoided.\n#\n#       The \"traditional\" practice of packing multiple parameters into a\n#       space-separated string is a well documented source of bugs and security\n#       problems, so this is (mostly) avoided, by progressively accumulating\n#       options in \"$@\", and eventually passing that to Java.\n#\n#       Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,\n#       and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;\n#       see the in-line comments for details.\n#\n#       There are tweaks for specific operating systems such as AIX, CygWin,\n#       Darwin, MinGW, and NonStop.\n#\n#   (3) This script is generated from the Groovy template\n#       https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt\n#       within the Gradle project.\n#\n#       You can find Gradle at https://github.com/gradle/gradle/.\n#\n##############################################################################\n\n# Attempt to set APP_HOME\n\n# Resolve links: $0 may be a link\napp_path=$0\n\n# Need this for daisy-chained symlinks.\nwhile\n    APP_HOME=${app_path%\"${app_path##*/}\"}  # leaves a trailing /; empty if no leading path\n    [ -h \"$app_path\" ]\ndo\n    ls=$( ls -ld \"$app_path\" )\n    link=${ls#*' -> '}\n    case $link in             #(\n      /*)   app_path=$link ;; #(\n      *)    app_path=$APP_HOME$link ;;\n    esac\ndone\n\nAPP_HOME=$( cd \"${APP_HOME:-./}\" && pwd -P ) || exit\n\nAPP_NAME=\"Gradle\"\nAPP_BASE_NAME=${0##*/}\n\n# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\nDEFAULT_JVM_OPTS='\"-Xmx64m\" \"-Xms64m\"'\n\n# Use the maximum available, or set MAX_FD != -1 to use that value.\nMAX_FD=maximum\n\nwarn () {\n    echo \"$*\"\n} >&2\n\ndie () {\n    echo\n    echo \"$*\"\n    echo\n    exit 1\n} >&2\n\n# OS specific support (must be 'true' or 'false').\ncygwin=false\nmsys=false\ndarwin=false\nnonstop=false\ncase \"$( uname )\" in                #(\n  CYGWIN* )         cygwin=true  ;; #(\n  Darwin* )         darwin=true  ;; #(\n  MSYS* | MINGW* )  msys=true    ;; #(\n  NONSTOP* )        nonstop=true ;;\nesac\n\nCLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar\n\n\n# Determine the Java command to use to start the JVM.\nif [ -n \"$JAVA_HOME\" ] ; then\n    if [ -x \"$JAVA_HOME/jre/sh/java\" ] ; then\n        # IBM's JDK on AIX uses strange locations for the executables\n        JAVACMD=$JAVA_HOME/jre/sh/java\n    else\n        JAVACMD=$JAVA_HOME/bin/java\n    fi\n    if [ ! -x \"$JAVACMD\" ] ; then\n        die \"ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME\n\nPlease set the JAVA_HOME variable in your environment to match the\nlocation of your Java installation.\"\n    fi\nelse\n    JAVACMD=java\n    which java >/dev/null 2>&1 || die \"ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.\n\nPlease set the JAVA_HOME variable in your environment to match the\nlocation of your Java installation.\"\nfi\n\n# Increase the maximum file descriptors if we can.\nif ! \"$cygwin\" && ! \"$darwin\" && ! \"$nonstop\" ; then\n    case $MAX_FD in #(\n      max*)\n        MAX_FD=$( ulimit -H -n ) ||\n            warn \"Could not query maximum file descriptor limit\"\n    esac\n    case $MAX_FD in  #(\n      '' | soft) :;; #(\n      *)\n        ulimit -n \"$MAX_FD\" ||\n            warn \"Could not set maximum file descriptor limit to $MAX_FD\"\n    esac\nfi\n\n# Collect all arguments for the java command, stacking in reverse order:\n#   * args from the command line\n#   * the main class name\n#   * -classpath\n#   * -D...appname settings\n#   * --module-path (only if needed)\n#   * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.\n\n# For Cygwin or MSYS, switch paths to Windows format before running java\nif \"$cygwin\" || \"$msys\" ; then\n    APP_HOME=$( cygpath --path --mixed \"$APP_HOME\" )\n    CLASSPATH=$( cygpath --path --mixed \"$CLASSPATH\" )\n\n    JAVACMD=$( cygpath --unix \"$JAVACMD\" )\n\n    # Now convert the arguments - kludge to limit ourselves to /bin/sh\n    for arg do\n        if\n            case $arg in                                #(\n              -*)   false ;;                            # don't mess with options #(\n              /?*)  t=${arg#/} t=/${t%%/*}              # looks like a POSIX filepath\n                    [ -e \"$t\" ] ;;                      #(\n              *)    false ;;\n            esac\n        then\n            arg=$( cygpath --path --ignore --mixed \"$arg\" )\n        fi\n        # Roll the args list around exactly as many times as the number of\n        # args, so each arg winds up back in the position where it started, but\n        # possibly modified.\n        #\n        # NB: a `for` loop captures its iteration list before it begins, so\n        # changing the positional parameters here affects neither the number of\n        # iterations, nor the values presented in `arg`.\n        shift                   # remove old arg\n        set -- \"$@\" \"$arg\"      # push replacement arg\n    done\nfi\n\n# Collect all arguments for the java command;\n#   * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of\n#     shell script including quotes and variable substitutions, so put them in\n#     double quotes to make sure that they get re-expanded; and\n#   * put everything else in single quotes, so that it's not re-expanded.\n\nset -- \\\n        \"-Dorg.gradle.appname=$APP_BASE_NAME\" \\\n        -classpath \"$CLASSPATH\" \\\n        org.gradle.wrapper.GradleWrapperMain \\\n        \"$@\"\n\n# Stop when \"xargs\" is not available.\nif ! command -v xargs >/dev/null 2>&1\nthen\n    die \"xargs is not available\"\nfi\n\n# Use \"xargs\" to parse quoted args.\n#\n# With -n1 it outputs one arg per line, with the quotes and backslashes removed.\n#\n# In Bash we could simply go:\n#\n#   readarray ARGS < <( xargs -n1 <<<\"$var\" ) &&\n#   set -- \"${ARGS[@]}\" \"$@\"\n#\n# but POSIX shell has neither arrays nor command substitution, so instead we\n# post-process each arg (as a line of input to sed) to backslash-escape any\n# character that might be a shell metacharacter, then use eval to reverse\n# that process (while maintaining the separation between arguments), and wrap\n# the whole thing up as a single \"set\" statement.\n#\n# This will of course break if any of these variables contains a newline or\n# an unmatched quote.\n#\n\neval \"set -- $(\n        printf '%s\\n' \"$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS\" |\n        xargs -n1 |\n        sed ' s~[^-[:alnum:]+,./:=@_]~\\\\&~g; ' |\n        tr '\\n' ' '\n    )\" '\"$@\"'\n\nexec \"$JAVACMD\" \"$@\"\n"
  },
  {
    "path": "library-build-transformer/gradlew.bat",
    "content": "@rem\r\n@rem Copyright 2015 the original author or authors.\r\n@rem\r\n@rem Licensed under the Apache License, Version 2.0 (the \"License\");\r\n@rem you may not use this file except in compliance with the License.\r\n@rem You may obtain a copy of the License at\r\n@rem\r\n@rem      https://www.apache.org/licenses/LICENSE-2.0\r\n@rem\r\n@rem Unless required by applicable law or agreed to in writing, software\r\n@rem distributed under the License is distributed on an \"AS IS\" BASIS,\r\n@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n@rem See the License for the specific language governing permissions and\r\n@rem limitations under the License.\r\n@rem\r\n\r\n@if \"%DEBUG%\"==\"\" @echo off\r\n@rem ##########################################################################\r\n@rem\r\n@rem  Gradle startup script for Windows\r\n@rem\r\n@rem ##########################################################################\r\n\r\n@rem Set local scope for the variables with windows NT shell\r\nif \"%OS%\"==\"Windows_NT\" setlocal\r\n\r\nset DIRNAME=%~dp0\r\nif \"%DIRNAME%\"==\"\" set DIRNAME=.\r\nset APP_BASE_NAME=%~n0\r\nset APP_HOME=%DIRNAME%\r\n\r\n@rem Resolve any \".\" and \"..\" in APP_HOME to make it shorter.\r\nfor %%i in (\"%APP_HOME%\") do set APP_HOME=%%~fi\r\n\r\n@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\r\nset DEFAULT_JVM_OPTS=\"-Xmx64m\" \"-Xms64m\"\r\n\r\n@rem Find java.exe\r\nif defined JAVA_HOME goto findJavaFromJavaHome\r\n\r\nset JAVA_EXE=java.exe\r\n%JAVA_EXE% -version >NUL 2>&1\r\nif %ERRORLEVEL% equ 0 goto execute\r\n\r\necho.\r\necho ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.\r\necho.\r\necho Please set the JAVA_HOME variable in your environment to match the\r\necho location of your Java installation.\r\n\r\ngoto fail\r\n\r\n:findJavaFromJavaHome\r\nset JAVA_HOME=%JAVA_HOME:\"=%\r\nset JAVA_EXE=%JAVA_HOME%/bin/java.exe\r\n\r\nif exist \"%JAVA_EXE%\" goto execute\r\n\r\necho.\r\necho ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%\r\necho.\r\necho Please set the JAVA_HOME variable in your environment to match the\r\necho location of your Java installation.\r\n\r\ngoto fail\r\n\r\n:execute\r\n@rem Setup the command line\r\n\r\nset CLASSPATH=%APP_HOME%\\gradle\\wrapper\\gradle-wrapper.jar\r\n\r\n\r\n@rem Execute Gradle\r\n\"%JAVA_EXE%\" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% \"-Dorg.gradle.appname=%APP_BASE_NAME%\" -classpath \"%CLASSPATH%\" org.gradle.wrapper.GradleWrapperMain %*\r\n\r\n:end\r\n@rem End local scope for the variables with windows NT shell\r\nif %ERRORLEVEL% equ 0 goto mainEnd\r\n\r\n:fail\r\nrem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of\r\nrem the _cmd.exe /c_ return code!\r\nset EXIT_CODE=%ERRORLEVEL%\r\nif %EXIT_CODE% equ 0 set EXIT_CODE=1\r\nif not \"\"==\"%GRADLE_EXIT_CONSOLE%\" exit %EXIT_CODE%\r\nexit /b %EXIT_CODE%\r\n\r\n:mainEnd\r\nif \"%OS%\"==\"Windows_NT\" endlocal\r\n\r\n:omega\r\n"
  },
  {
    "path": "library-build-transformer/settings.gradle",
    "content": "rootProject.name = 'library-build-transformer'\n"
  },
  {
    "path": "library-build-transformer/src/main/kotlin/io/realm/buildtransformer/RealmBuildTransformer.kt",
    "content": "/*\n * Copyright 2018 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 */\npackage io.realm.buildtransformer\n\nimport com.android.build.api.variant.AndroidComponentsExtension\nimport io.realm.buildtransformer.asm.visitors.AnnotatedCodeStripVisitor\nimport io.realm.buildtransformer.util.Stopwatch\nimport org.gradle.api.DefaultTask\nimport org.gradle.api.Project\nimport org.gradle.api.file.Directory\nimport org.gradle.api.file.RegularFile\nimport org.gradle.api.file.RegularFileProperty\nimport org.gradle.api.provider.ListProperty\nimport org.gradle.api.provider.Property\nimport org.gradle.api.tasks.Input\nimport org.gradle.api.tasks.InputFiles\nimport org.gradle.api.tasks.OutputFiles\nimport org.gradle.api.tasks.TaskAction\nimport org.objectweb.asm.ClassReader\nimport org.objectweb.asm.ClassWriter\nimport org.slf4j.Logger\nimport org.slf4j.LoggerFactory\nimport java.io.BufferedOutputStream\nimport java.io.FileInputStream\nimport java.io.FileOutputStream\nimport java.io.InputStream\nimport java.util.jar.JarEntry\nimport java.util.jar.JarFile\nimport java.util.jar.JarOutputStream\n\n// Type aliases for improving readability\ntypealias ByteCodeTypeDescriptor = String\ntypealias QualifiedName = String\ntypealias ByteCodeMethodName = String\ntypealias FieldName = String\n\n// Package level logger\nval logger: Logger = LoggerFactory.getLogger(\"realm-build-logger\")\n\n/**\n * Transformer that will strip all classes, methods and fields annotated with a given annotation from\n * a specific Android flavour. It is also possible to provide a list of files to delete whether or\n * not they have the annotation. These files will only be deleted from the defined flavour.\n */\nclass RealmBuildTransformer(\n    private val annotationQualifiedName: Property<String>,\n    private val input: ListProperty<RegularFile>,\n    private val output: RegularFileProperty,\n) {\n\n    internal fun transform() {\n        // The AGP build infrastructure will inject the task input and outputs and location is not\n        // to be considered as part of the API, so we must be able to accept the current scenario\n        // where the input and output is actually the same JAR. Thus, we write everything to a\n        // temporary output to avoid truncating the input, and then write this temporary output\n        // back to the final output location in the end.\n        // See https://developer.android.com/reference/tools/gradle-api/7.4/com/android/build/api/variant/ScopedArtifactsOperation#toTransform(com.android.build.api.artifact.ScopedArtifact,kotlin.Function1,kotlin.Function1,kotlin.Function1)\n        // for further information.\n        val temporaryOutput = output.get().asFile.absolutePath + \".tmp\"\n        val outputProvider = JarOutputStream(\n            BufferedOutputStream(FileOutputStream(temporaryOutput))\n        )\n\n        val timer = Stopwatch()\n        timer.start(\"Build Transform time\")\n\n        // The ASM infrastructure does not allow to inspect annotations of methods before visiting\n        // them. This prevents inspecting and stripping methods in the same pass, thus we first\n        // collect information about annotations and then secondly strip the annotation symbols.\n        // 1. Collect annotation information\n        val annotationDescriptor = createDescriptor(annotationQualifiedName.get())\n        val metadataCollector =\n            io.realm.buildtransformer.asm.visitors.AnnotationVisitor(annotationDescriptor)\n        forEachJarEntry { jarEntry, inputStream ->\n            if (jarEntry.name.endsWith(\".class\")) {\n                inputStream.use {\n                    val classReader = ClassReader(it)\n                    classReader.accept(metadataCollector, 0)\n                }\n            }\n        }\n        // 2. Strip annotated symbols\n        forEachJarEntry { jarEntry, inputStream ->\n            val bytes = inputStream.use { inputStream ->\n                if (jarEntry.name.endsWith(\".class\")) {\n                    val writer =\n                        ClassWriter(0) // We don't modify methods so no reason to re-calculate method frames\n                    val classRemover = AnnotatedCodeStripVisitor(\n                        annotationDescriptor,\n                        metadataCollector.annotatedClasses,\n                        metadataCollector.annotatedMethods,\n                        metadataCollector.annotatedFields,\n                        writer\n                    )\n                    ClassReader(inputStream).accept(classRemover, 0)\n                    if (classRemover.deleteClass) ByteArray(0) else writer.toByteArray()\n                } else {\n                    inputStream.readBytes()\n                }\n            }\n            if (bytes.isNotEmpty()) {\n                outputProvider.putNextEntry(JarEntry(jarEntry.name))\n                outputProvider.write(bytes)\n                outputProvider.closeEntry()\n            }\n        }\n        outputProvider.close()\n        // Write the temporary output to the final output location. See comment about\n        // temporaryOutput for the details\n        FileInputStream(temporaryOutput).channel.use { input ->\n            FileOutputStream(this.output.asFile.get().absoluteFile).channel.use { output ->\n                output.transferFrom(input, 0, input.size())\n            }\n        }\n        timer.stop()\n    }\n\n    private fun forEachJarEntry(block: (jarEntry: JarEntry, inputStream: InputStream) -> Unit) {\n        val jarFiles: List<JarFile> = input.get().map { JarFile(it.asFile) }\n        jarFiles.forEach { jarFile ->\n            jarFile.entries().toList().map {\n                block(it, jarFile.getInputStream(it))\n            }\n        }\n    }\n\n    private fun createDescriptor(qualifiedName: String): String {\n        return \"L${qualifiedName.replace(\".\", \"/\")};\"\n    }\n\n    companion object {\n        fun register(project: Project, flavorToStrip: String, annotationQualifiedName: QualifiedName) {\n            val androidComponents = project.extensions.getByType(AndroidComponentsExtension::class.java)\n            androidComponents.onVariants { variant ->\n                if (variant.name.startsWith(flavorToStrip)) {\n                    val taskProvider = project.tasks.register(\n                        \"${variant.name}RealmBuildTransformer\",\n                        ModifyClassesTask::class.java\n                    ) {\n                        it.annotationQualifiedName.set(annotationQualifiedName)\n                    }\n                    variant.artifacts.forScope(com.android.build.api.variant.ScopedArtifacts.Scope.PROJECT)\n                        .use<ModifyClassesTask>(taskProvider)\n                        .toTransform(\n                            com.android.build.api.artifact.ScopedArtifact.CLASSES,\n                            ModifyClassesTask::allJars,\n                            ModifyClassesTask::allDirectories,\n                            ModifyClassesTask::output\n                        )\n                }\n            }\n        }\n    }\n}\nabstract class ModifyClassesTask: DefaultTask() {\n    @get:InputFiles\n    abstract val allJars: ListProperty<RegularFile>\n\n    @get:InputFiles\n    abstract val allDirectories: ListProperty<Directory>\n\n    @get:OutputFiles\n    abstract val output: RegularFileProperty\n\n    @get:Input\n    abstract val annotationQualifiedName : Property<String>\n\n    @TaskAction\n    fun taskAction() {\n        RealmBuildTransformer(annotationQualifiedName, allJars, output)\n            .transform()\n    }\n}\n"
  },
  {
    "path": "library-build-transformer/src/main/kotlin/io/realm/buildtransformer/asm/ClassPoolTransformer.kt",
    "content": "/*\n * Copyright 2018 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 */\npackage io.realm.buildtransformer.asm\n\nimport io.realm.buildtransformer.ByteCodeMethodName\nimport io.realm.buildtransformer.ByteCodeTypeDescriptor\nimport io.realm.buildtransformer.FieldName\nimport io.realm.buildtransformer.QualifiedName\nimport io.realm.buildtransformer.asm.visitors.AnnotatedCodeStripVisitor\nimport io.realm.buildtransformer.asm.visitors.AnnotationVisitor\nimport io.realm.buildtransformer.ext.shouldBeDeleted\nimport org.objectweb.asm.ClassReader\nimport org.objectweb.asm.ClassWriter\nimport java.io.File\n\n/**\n * Transformer that will transform a pool of classes by removing all classes, methods and fields annotated with\n * a given annotation.\n *\n * It does so in 2 passes using the ASM Visitor API. The first pass will gather metadata about the class hierarchy,\n * the 2nd pass will do the actual transform. The ASM Tree API was considered as well, but it does not provide\n * access to referenced classes easily, so two passes would be required here as well and the Visitor API is faster and\n * requires less memory.\n */\nclass ClassPoolTransformer(annotationQualifiedName: QualifiedName, private val inputClasses: Set<File>) {\n\n    private val annotationDescriptor: String = createDescriptor(annotationQualifiedName)\n\n    /**\n     * Transform files\n     *\n     * @return All input files, both those that have been modified and those that have not.\n     */\n    fun transform(): Set<File> {\n        val (markedClasses, markedMethods, markedFields) = pass1()\n        return pass2(markedClasses, markedMethods, markedFields)\n    }\n\n    /**\n     * Pass 1: Collect all classes, interfaces and enums that contain the given annotation. This include both top-level\n     * and inner types.\n     */\n    private fun pass1(): Triple<Set<String>, Map<ByteCodeTypeDescriptor, Set<ByteCodeMethodName>>, Map<ByteCodeTypeDescriptor, Set<FieldName>>> {\n        val metadataCollector = AnnotationVisitor(annotationDescriptor)\n        inputClasses.forEach {\n            try {\n                it.inputStream().use {\n                    val classReader = ClassReader(it)\n                    classReader.accept(metadataCollector, 0)\n                }\n            } catch (ex: Exception) {\n                throw RuntimeException(\"Failed to collect data in: ${it.absolutePath}\", ex)\n            }\n        }\n        return Triple(metadataCollector.annotatedClasses, metadataCollector.annotatedMethods, metadataCollector.annotatedFields)\n    }\n\n    /**\n     * Pass 2: Remove methods and fields marked with the annotation. Classes that are removed\n     * are instead marked for deletion as deleting the File is the responsibility of the\n     * transform API.\n     */\n    private fun pass2(markedClasses: Set<String>, markedMethods: Map<ByteCodeTypeDescriptor, Set<ByteCodeMethodName>>, markedFields: Map<ByteCodeTypeDescriptor, Set<FieldName>>): Set<File> {\n        inputClasses.forEach { classFile ->\n            try {\n                var result = ByteArray(0)\n                if (!classFile.shouldBeDeleted) { // Respect previously set delete flag, so avoid doing any work\n                    classFile.inputStream().use { inputStream ->\n                        val writer = ClassWriter(0) // We don't modify methods so no reason to re-calculate method frames\n                        val classRemover = AnnotatedCodeStripVisitor(annotationDescriptor, markedClasses, markedMethods, markedFields, writer)\n                        val reader = ClassReader(inputStream)\n                        reader.accept(classRemover, 0)\n                        result = if (classRemover.deleteClass) ByteArray(0) else writer.toByteArray()\n                    }\n                    if (result.isNotEmpty()) {\n                        classFile.outputStream().use { outputStream -> outputStream.write(result) }\n                    } else {\n                        classFile.shouldBeDeleted = true\n                    }\n                }\n            } catch (ex: Exception) {\n                throw RuntimeException(\n                    \"Failed to remove class, field or method in: ${classFile.absolutePath}\",\n                    ex\n                )\n            }\n        }\n        return inputClasses\n    }\n\n    /**\n     * Creates the descriptor used by ASM to identify types.\n     */\n    private fun createDescriptor(qualifiedName: String): String {\n        return \"L${qualifiedName.replace(\".\", \"/\")};\"\n    }\n}\n"
  },
  {
    "path": "library-build-transformer/src/main/kotlin/io/realm/buildtransformer/asm/visitors/AnnotatedCodeStripVisitor.kt",
    "content": "/*\n * Copyright 2018 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 */\npackage io.realm.buildtransformer.asm.visitors\n\nimport io.realm.buildtransformer.ByteCodeMethodName\nimport io.realm.buildtransformer.ByteCodeTypeDescriptor\nimport io.realm.buildtransformer.FieldName\nimport io.realm.buildtransformer.logger\nimport org.objectweb.asm.*\nimport org.objectweb.asm.AnnotationVisitor\n\n/**\n * Visitor that will remove all classes, methods and fields annotated with given annotation.\n * Doing this requires a pre-processing step performed by the [AnnotationVisitor].\n */\nclass AnnotatedCodeStripVisitor(private val annotationDescriptor: String,\n                                private val markedClasses: Set<String>,\n                                private val markedMethods: Map<ByteCodeTypeDescriptor, Set<ByteCodeMethodName>>,\n                                private val markedFields: Map<ByteCodeTypeDescriptor, Set<FieldName>>,\n                                classWriter: ClassVisitor) : ClassVisitor(Opcodes.ASM7, classWriter) {\n\n    var deleteClass: Boolean = false\n    private lateinit var markedMethodsInClass: Set<ByteCodeMethodName>\n    private lateinit var markedFieldsInClass: Set<FieldName>\n\n    override fun visit(version: Int, access: Int, name: String?, signature: String?, superName: String?, interfaces: Array<out String>?) {\n        // Only process this class if it or its super class doesn't have the given annotation\n        markedMethodsInClass = markedMethods[name!!]!!\n        markedFieldsInClass = markedFields[name]!!\n        deleteClass = (markedClasses.contains(name) || markedClasses.contains(superName))\n        if (!deleteClass) {\n            super.visit(version, access, name, signature, superName, interfaces)\n        } else {\n            logger.debug(\"Removing top level class: $name\")\n        }\n    }\n\n    // Remove INNERCLASS definitions from the bytecode in the top level class. It isn't clear if\n    // these are used by any relevant API's, but better remove them just in case.\n    override fun visitInnerClass(name: String?, outerName: String?, innerName: String?, access: Int) {\n        if (!markedClasses.contains(name) && !deleteClass) {\n            super.visitInnerClass(name, outerName, innerName, access)\n        } else {\n            logger.debug(\"Removing inner class description: $name\")\n        }\n    }\n\n    override fun visitField(access: Int, name: String?, descriptor: String?, signature: String?, value: Any?): FieldVisitor? {\n        return if (!markedFieldsInClass.contains(name) && !deleteClass) {\n            super.visitField(access, name, descriptor, signature, value)\n        } else {\n            logger.debug(\"Removing field: $name\")\n            null\n        }\n    }\n\n    override fun visitMethod(access: Int, name: ByteCodeMethodName?, descriptor: String?, signature: String?, exceptions: Array<out String>?): MethodVisitor? {\n        return if (!markedMethodsInClass.contains(name + descriptor) && !deleteClass) {\n            super.visitMethod(access, name, descriptor, signature, exceptions)\n        } else {\n            logger.debug(\"Removing method: $name $descriptor\")\n            null\n        }\n    }\n\n}"
  },
  {
    "path": "library-build-transformer/src/main/kotlin/io/realm/buildtransformer/asm/visitors/AnnotationVisitor.kt",
    "content": "/*\n * Copyright 2018 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 */\npackage io.realm.buildtransformer.asm.visitors;\n\nimport io.realm.buildtransformer.ByteCodeMethodName\nimport io.realm.buildtransformer.ByteCodeTypeDescriptor\nimport io.realm.buildtransformer.FieldName\nimport org.objectweb.asm.*\nimport org.objectweb.asm.AnnotationVisitor\n\n/**\n * ClassVisitor that gather all classes and methods with the given annotation. This is the first\n * pass and is required for correctly identifying them in the 2nd pass before any byte code is\n * written.\n */\nclass AnnotationVisitor(private val annotationDescriptor: String) : ClassVisitor(Opcodes.ASM7) {\n\n    val annotatedClasses: MutableSet<ByteCodeTypeDescriptor> = mutableSetOf()\n    val annotatedMethods: MutableMap<ByteCodeTypeDescriptor, MutableSet<ByteCodeMethodName>> = mutableMapOf()\n    val annotatedFields: MutableMap<ByteCodeTypeDescriptor, MutableSet<FieldName>> = mutableMapOf()\n\n    private var internalQualifiedName: String = \"\"\n    private val annotatedMethodsInClass = mutableSetOf<ByteCodeMethodName>()\n    private val annotatedFieldsInClass = mutableSetOf<FieldName>()\n\n    override fun visit(version: Int, access: Int, name: String?, signature: String?, superName: String?, interfaces: Array<out String>?) {\n        internalQualifiedName = name!!\n        annotatedMethods[internalQualifiedName] = annotatedMethodsInClass\n        annotatedFields[internalQualifiedName] = annotatedFieldsInClass\n        super.visit(version, access, name, signature, superName, interfaces)\n    }\n\n    override fun visitAnnotation(descriptor: String?, visible: Boolean): AnnotationVisitor? {\n        if (descriptor == annotationDescriptor) {\n            annotatedClasses.add(internalQualifiedName)\n        }\n        return super.visitAnnotation(descriptor, visible)\n    }\n\n    override fun visitMethod(access: Int, name: String?, descriptor: String?, signature: String?, exceptions: Array<out String>?): MethodVisitor {\n        val parentVisitor = super.visitMethod(access, name, descriptor, signature, exceptions)\n        val methodDescriptor: String = descriptor!!\n        val methodName: String = name!!;\n        return object: MethodVisitor(api, parentVisitor) {\n            override fun visitAnnotation(descriptor: String?, visible: Boolean): AnnotationVisitor? {\n                if (descriptor == annotationDescriptor) {\n                    annotatedMethodsInClass.add(methodName + methodDescriptor) // Use name + return type + parameters to uniquely identify method\n                }\n                return super.visitAnnotation(descriptor, visible)\n            }\n        }\n    }\n\n    override fun visitField(access: Int, name: String?, descriptor: String?, signature: String?, value: Any?): FieldVisitor {\n        return object: FieldVisitor(api) {\n            override fun visitAnnotation(descriptor: String?, visible: Boolean): AnnotationVisitor? {\n                if (descriptor == annotationDescriptor) {\n                    annotatedFieldsInClass.add(name!!)\n                }\n                return super.visitAnnotation(descriptor, visible)\n            }\n        }\n    }\n\n    override fun visitEnd() {\n        annotatedMethods[internalQualifiedName] = annotatedMethodsInClass\n        super.visitEnd()\n    }\n\n}\n"
  },
  {
    "path": "library-build-transformer/src/main/kotlin/io/realm/buildtransformer/ext/FileExt.kt",
    "content": "/*\n * Copyright 2018 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 */\npackage io.realm.buildtransformer.ext\n\nimport java.io.File\nimport java.util.*\nimport kotlin.reflect.KProperty\n\n// Add support for extension properties\n// Credit: https://stackoverflow.com/questions/36502413/extension-fields-in-kotlin\nclass FieldProperty<R, T : Any>(val initializer: (R) -> T = { throw IllegalStateException(\"Field Property not initialized.\") }) {\n    private val map = WeakHashMap<R, T>()\n\n    operator fun getValue(thisRef: R, property: KProperty<*>): T =\n            map[thisRef] ?: setValue(thisRef, property, initializer(thisRef))\n\n    operator fun setValue(thisRef: R, property: KProperty<*>, value: T): T {\n        map[thisRef] = value\n        return value\n    }\n}\n\n/**\n * If the file points to a compiled `.class` file, this property stores the path leading to the root folder of the\n * package hierarchy.\n */\nvar File.packageHierarchyRootDir: String by FieldProperty<File, String>()\n\n/**\n * `true` if the file is marked for deletion after being processed.\n */\nvar File.shouldBeDeleted: Boolean by FieldProperty<File, Boolean>()\n"
  },
  {
    "path": "library-build-transformer/src/main/kotlin/io/realm/buildtransformer/util/Stopwatch.kt",
    "content": "/*\n * Copyright 2018 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 */\npackage io.realm.buildtransformer.util\n\nimport org.slf4j.Logger\nimport org.slf4j.LoggerFactory\nimport java.util.concurrent.TimeUnit\n\nclass Stopwatch {\n\n    val logger: Logger = LoggerFactory.getLogger(\"realm-stopwatch\")\n\n    var start: Long = -1L\n    var lastSplit: Long = -1L\n    lateinit var label: String\n\n    /**\n     * Start the stopwatch.\n     */\n    fun start(label: String) {\n        if (start != -1L) {\n            throw IllegalStateException(\"Stopwatch was already started\");\n        }\n        this.label = label\n        start = System.nanoTime();\n        lastSplit = start;\n    }\n\n    /**\n     * Reports the split time.\n     *\n     * @param label Label to use when printing split time\n     * @param reportDiffFromLastSplit if `true` report the time from last split instead of the start\n     */\n    fun splitTime(label: String, reportDiffFromLastSplit: Boolean = true) {\n        val split = System.nanoTime()\n        val diff = if (reportDiffFromLastSplit) { split - lastSplit } else { split - start }\n        lastSplit = split;\n        logger.debug(\"$label: ${TimeUnit.NANOSECONDS.toMillis(diff)} ms.\")\n    }\n\n    /**\n     * Stops the timer and report the result.\n     */\n    fun stop() {\n        val stop = System.nanoTime()\n        val diff = stop - start\n        logger.debug(\"$label: ${TimeUnit.NANOSECONDS.toMillis(diff)} ms.\")\n    }\n}"
  },
  {
    "path": "library-build-transformer/src/test/java/io/realm/buildtransformer/testclasses/NestedTestClass.java",
    "content": "/*\n * Copyright 2018 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 */\npackage io.realm.buildtransformer.testclasses;\n\nimport io.realm.internal.annotations.ObjectServer;\n\npublic class NestedTestClass {\n    public String name;\n\n    @ObjectServer\n    public static class StaticInnerClass {\n        public String foo;\n    }\n\n\n    @ObjectServer\n    public class InnerClass {\n        public String foo;\n    }\n\n    @ObjectServer\n    public enum Enum {\n        FOO\n    }\n\n    @ObjectServer\n    public interface Interface {\n        void foo();\n    }\n}\n"
  },
  {
    "path": "library-build-transformer/src/test/java/io/realm/buildtransformer/testclasses/SimpleTestClass.java",
    "content": "/*\n * Copyright 2018 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 */\npackage io.realm.buildtransformer.testclasses;\n\nimport io.realm.internal.annotations.ObjectServer;\n\n@ObjectServer\npublic class SimpleTestClass {\n    public String name;\n\n    public static class Foo {\n        public String bar;\n    }\n}\n"
  },
  {
    "path": "library-build-transformer/src/test/java/io/realm/buildtransformer/testclasses/SimpleTestFields.java",
    "content": "/*\n * Copyright 2018 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 */\npackage io.realm.buildtransformer.testclasses;\n\nimport io.realm.internal.annotations.ObjectServer;\nimport io.realm.internal.annotations.CustomAnnotation;\n\npublic class SimpleTestFields {\n\n    @ObjectServer\n    public String field1;\n\n    @CustomAnnotation // Annotations must be written back as well\n    public String field2;\n}\n"
  },
  {
    "path": "library-build-transformer/src/test/java/io/realm/buildtransformer/testclasses/SimpleTestMethods.java",
    "content": "/*\n * Copyright 2018 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 */\npackage io.realm.buildtransformer.testclasses;\n\nimport io.realm.internal.annotations.ObjectServer;\n\npublic class SimpleTestMethods {\n\n    @ObjectServer\n    public String foo() {\n        return \"foo\";\n    }\n\n    @ObjectServer\n    public String foo1(String input) {\n        return \"foo1\";\n    }\n\n    public String foo1(String input, String donRemoveThis) {\n        return \"foo1\"; // Only methods matching the exact signature should be removed\n    }\n\n    public String bar() {\n        return \"bar\";\n    }\n\n}\n"
  },
  {
    "path": "library-build-transformer/src/test/java/io/realm/buildtransformer/testclasses/SubClass.java",
    "content": "/*\n * Copyright 2018 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 */\npackage io.realm.buildtransformer.testclasses;\n\npublic class SubClass extends SuperClass {\n    public String foo;\n}\n"
  },
  {
    "path": "library-build-transformer/src/test/java/io/realm/buildtransformer/testclasses/SuperClass.java",
    "content": "/*\n * Copyright 2018 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 */\npackage io.realm.buildtransformer.testclasses;\n\nimport io.realm.internal.annotations.ObjectServer;\n\n@ObjectServer\npublic class SuperClass {\n}\n"
  },
  {
    "path": "library-build-transformer/src/test/java/io/realm/internal/annotations/CustomAnnotation.java",
    "content": "package io.realm.internal.annotations;\n\nimport java.lang.annotation.ElementType;\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.RetentionPolicy;\nimport java.lang.annotation.Target;\n\n@Retention(RetentionPolicy.RUNTIME)\n@Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD})\npublic @interface CustomAnnotation {\n}\n"
  },
  {
    "path": "library-build-transformer/src/test/java/io/realm/internal/annotations/ObjectServer.java",
    "content": "/*\n * Copyright 2018 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 */\npackage io.realm.internal.annotations;\n\nimport java.lang.annotation.ElementType;\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.RetentionPolicy;\nimport java.lang.annotation.Target;\n\n/**\n * Copy of an interface from the Realm Library (to break cyclic dependencies)\n */\n@Retention(RetentionPolicy.RUNTIME)\n@Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD})\npublic @interface ObjectServer {\n}\n"
  },
  {
    "path": "library-build-transformer/src/test/kotlin/io/realm/buildtransformer/DynamicClassLoader.kt",
    "content": "/*\n * Copyright 2018 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 */\npackage io.realm.buildtransformer\n\nimport java.io.File\n\n/**\n * Custom ClassLoader that can be used to dynamically load a class that have been dynamically modified, i.e. we\n * load it using the ByteArray that represents it.\n */\nclass DynamicClassLoader(parentLoader: ClassLoader) : ClassLoader(parentLoader) {\n\n    fun loadClass(qualifiedClassName: String, pool: Set<File>): Class<*> {\n        val classFile: File = pool.find {\n            it.absolutePath.endsWith(\"${qualifiedClassName.replace(\".\", \"/\")}.class\")\n        } ?: throw IllegalStateException(\"Class pool does not contain: $qualifiedClassName\")\n\n        val classBytes: ByteArray = classFile.readBytes()\n        return defineClass(qualifiedClassName, classBytes, 0, classBytes.size)\n    }\n}"
  },
  {
    "path": "library-build-transformer/src/test/kotlin/io/realm/buildtransformer/VisitorTests.kt",
    "content": "/*\n * Copyright 2018 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 */\npackage io.realm.buildtransformer\n\nimport io.realm.buildtransformer.asm.ClassPoolTransformer\nimport io.realm.buildtransformer.ext.packageHierarchyRootDir\nimport io.realm.buildtransformer.ext.shouldBeDeleted\nimport io.realm.buildtransformer.testclasses.*\nimport io.realm.internal.annotations.CustomAnnotation\nimport org.junit.Assert.*\nimport org.junit.Before\nimport org.junit.Test\nimport java.io.File\nimport java.lang.reflect.Method\nimport kotlin.reflect.KClass\n\nclass VisitorTests {\n\n    private lateinit var classLoader: DynamicClassLoader\n    private val qualifiedAnnotationName = \"io.realm.internal.annotations.ObjectServer\"\n\n    @Before\n    fun setUp () {\n        classLoader = DynamicClassLoader(this::class.java.classLoader)\n    }\n\n    @Test\n    fun removeFields() {\n        val c: Class<SimpleTestFields> = modifyClass(SimpleTestFields::class)\n        assetDefaultConstructorExists(c)\n        assertFieldExists(\"field2\", c)\n        assertFieldRemoved(\"field1\", c)\n        assertTrue(c.getField(\"field2\").isAnnotationPresent(CustomAnnotation::class.java))\n    }\n\n    @Test\n    fun removeMethods() {\n        val c: Class<SimpleTestMethods> = modifyClass(SimpleTestMethods::class)\n        assetDefaultConstructorExists(c)\n        assertMethodExists(c, \"bar\", emptyArray());\n        assertMethodExists(c, \"foo1\", arrayOf(String::class.java, String::class.java))\n        assertMethodRemoved(c, \"foo\", emptyArray());\n        assertMethodRemoved(c, \"foo1\", arrayOf(String::class.java))\n    }\n\n    @Test\n    fun removeTopLevelClass() {\n        try {\n            modifyClass(SimpleTestClass::class)\n            fail()\n        } catch(e: IllegalStateException) {\n            assertTrue(e.message?.contains(\"Class pool does not contain\") == true)\n        }\n    }\n\n    @Test\n    fun removeClassIfSuperClassIsAnnotated() {\n        try {\n            modifyClass(SubClass::class, setOf(SubClass::class, SuperClass::class))\n            fail()\n        } catch(e: IllegalStateException) {\n            assertTrue(e.message?.contains(\"Class pool does not contain\") == true)\n        }\n    }\n\n    @Test\n    fun removeInnerClasses() {\n        // The reflection API does not make it possible to find inner classes, so we need to inspect the bytecode\n        // instead. We do this by checking the output of the transformer which will only output files modified and\n        // not classes deleted.\n        val inputClasses: MutableSet<File> = mutableSetOf()\n        setOf<KClass<*>>(\n            NestedTestClass::class,\n            NestedTestClass.InnerClass::class,\n            NestedTestClass.StaticInnerClass::class,\n            NestedTestClass.Enum::class,\n            NestedTestClass.Interface::class\n        ).forEach { inputClasses.add(getClassFile(it)) }\n        val transformer = ClassPoolTransformer(qualifiedAnnotationName, inputClasses)\n        val outputFiles: Set<File> = transformer.transform()\n        assertEquals(1, outputFiles.filter { !it.shouldBeDeleted }.size) // Only top level file is saved.\n        assertTrue(outputFiles.first().name.endsWith(\"NestedTestClass.class\"))\n    }\n\n    private fun assetDefaultConstructorExists(clazz: Class<*>) {\n        clazz.getConstructor()\n    }\n\n    private fun assertFieldRemoved(fieldName: String, clazz: Class<*>) {\n        try {\n            clazz.getField(fieldName)\n            fail(\"Field $fieldName has not been removed\")\n        } catch (e: NoSuchFieldException) {\n        }\n    }\n\n    private fun assertFieldExists(fieldName: String, clazz: Class<*>) {\n        clazz.getField(fieldName)\n    }\n\n    private fun assertMethodRemoved(clazz: Class<*>, methodName: String, parameterTypes: Array<Class<*>>) {\n        try {\n            clazz.getMethod(methodName, *parameterTypes);\n            fail(\"Method $methodName has not been removed\");\n        } catch (e: NoSuchMethodException) {\n        }\n    }\n\n    private fun assertMethodExists(clazz: Class<*>, methodName: String, parameterTypes: Array<Class<*>>) {\n        val method: Method = clazz.getMethod(methodName, *parameterTypes) // Will throw exception if it doesn't exists\n        assertNotNull(method)\n    }\n\n    private fun <T: Any> modifyClass(clazz: KClass<T>): Class<T> {\n        return this.modifyClass(clazz, setOf(clazz))\n    }\n\n    private fun <T: Any> modifyClass(clazz: KClass<T>, pool: Set<KClass<*>>): Class<T> {\n        val inputClasses: MutableSet<File> = mutableSetOf()\n        pool.forEach { inputClasses.add(getClassFile(it)) }\n        val transformer = ClassPoolTransformer(qualifiedAnnotationName, inputClasses)\n        val outputFiles: Set<File> = transformer.transform().filter { !it.shouldBeDeleted }.toSet()\n        @Suppress(\"UNCHECKED_CAST\")\n        return classLoader.loadClass(clazz.java.name, outputFiles) as Class<T>\n    }\n\n    private fun getClassFile(clazz: KClass<*>): File {\n        return getClassFile(clazz.java)\n    }\n\n    private fun getClassFile(clazz: Class<*>): File {\n        val filePath = \"${clazz.name.replace(\".\", \"/\")}.class\"\n        val file = File(classLoader.getResource(filePath).file)\n        // Extension properties must be initialized before they can be read\n        file.shouldBeDeleted = false\n        file.packageHierarchyRootDir = \"\"\n        return file\n    }\n}\n"
  },
  {
    "path": "mavencentral-properties.gradle",
    "content": "// Find property in either System environment or Gradle properties.\n// If set in both places, Gradle properties win.\ndef getPropertyValue(String propertyName) {\n    return project.findProperty(propertyName) ?: System.getenv(propertyName) ?: \"\"\n}\n\n// Default values\ndef rootExt = rootProject.ext\nrootExt[\"signing.keyId\"] = 'BD9104E9'\nrootExt[\"sonatypeStagingProfileId\"] = '78c19333e4450f'\n\n// Set properties either from a global properties file or environment parameters\nrootExt[\"signBuild\"] = getPropertyValue('signBuild')\nrootExt[\"signing.password\"] = getPropertyValue('signPassword')\n// Apparently Gradle treats properties define through a gradle.properties file differently\n// than those defined through the commandline using `-P`. This is a problem with new\n// line characters as found in an ascii-armoured PGP file. To ensure work around this, all newlines\n// have been replaced with `#` and thus needs to be reverted here.\nrootExt[\"signing.secretKeyRingFile\"] = getPropertyValue('signSecretRingFile').replaceAll('#','\\n')\nrootExt[\"ossrhUsername\"] = getPropertyValue('ossrhUsername')\nrootExt[\"ossrhPassword\"] = getPropertyValue('ossrhPassword')\n"
  },
  {
    "path": "mavencentral-publications.gradle",
    "content": "// This script is responsible for setting up the publications, so they are ready to be published\n// to Maven Central and other repositories. Publishing to Maven Central is configured in\n// `mavencentral-publish.gradle`. They are in separate files as the nexus publish plugin used\n// to deploy to Maven Central can only be applied to top level projects.\napply plugin: 'maven-publish'\napply plugin: 'signing'\napply from: buildscript.sourceFile.getParent() + \"/\" + \"mavencentral-properties.gradle\"\n\n// The publications doesn't know about our AAR dependencies, so we have to manually add them to the pom\n// Credit: http://stackoverflow.com/questions/24743562/gradle-not-including-dependencies-in-published-pom-xml\ndef createPomDependencies(configurationNames) {\n    return {\n        def dependenciesNode = asNode().appendNode('dependencies')\n        configurationNames.each { configurationName ->\n            configurations[configurationName].allDependencies.each {\n                // Also ignore `realm-library` because that is used by the Kotlin Extensions as\n                // a project dependency, but it is being written to the POM file in a wrong way.\n                // Instead we just ignore it as the Gradle Plugin makes sure it is always present.\n                if (it.group != null && it.name != null && it.name != 'realm-library') {\n                    def dependencyNode = dependenciesNode.appendNode('dependency')\n                    dependencyNode.appendNode('groupId', it.group)\n                    dependencyNode.appendNode('artifactId', it.name)\n                    dependencyNode.appendNode('version', it.version)\n\n                    //If there are any exclusions in dependency\n                    if (it.excludeRules.size() > 0) {\n                        def exclusionsNode = dependencyNode.appendNode('exclusions')\n                        it.excludeRules.each { rule ->\n                            def exclusionNode = exclusionsNode.appendNode('exclusion')\n                            exclusionNode.appendNode('groupId', rule.group)\n                            exclusionNode.appendNode('artifactId', rule.module)\n                        }\n                    }\n                }\n            }\n        }\n    }\n}\n\n// TODO: Consider refactoring this. See https://github.com/realm/realm-java/pull/7327#discussion_r586281652\ndef populatePom(publication, pomName, pomDescription, pomDependencies = null) {\n    publication.pom {\n        name = \"${pomName}\"\n        description = \"${pomDescription}\"\n        url = 'https://docs.mongodb.com/realm'\n        licenses {\n            license {\n                name = 'The Apache Software License, Version 2.0'\n                url = 'http://www.apache.org/licenses/LICENSE-2.0.txt'\n                distribution = 'repo'\n            }\n        }\n        issueManagement {\n            system = 'github'\n            url = 'https://github.com/realm/realm-java/issues'\n        }\n        scm {\n            url = 'scm:https://github.com/realm/realm-java'\n            connection = 'scm:git@github.com:realm/realm-java.git'\n            developerConnection = 'scm:git@github.com:realm/realm-java.git'\n        }\n        developers {\n            developer {\n                name = 'Realm'\n                email = 'info@realm.io'\n                organization = 'MongoDB'\n                organizationUrl = 'https://www.mongodb.com'\n            }\n        }\n    }\n    if (pomDependencies) {\n        publication.pom.withXml(pomDependencies)\n    }\n}\n\npublishing {\n    repositories {\n        maven {\n            name = \"MavenCentral\"\n            def releasesRepoUrl = \"https://oss.sonatype.org/service/local/staging/deploy/maven2/\"\n            def snapshotsRepoUrl = \"https://oss.sonatype.org/content/repositories/snapshots/\"\n            url = version.endsWith('-SNAPSHOT') ? snapshotsRepoUrl : releasesRepoUrl\n            credentials {\n                username = rootProject.ext[\"ossrhUsername\"]\n                password = rootProject.ext[\"ossrhPassword\"]\n            }\n        }\n    }\n}\n\nsigning {\n    required { signBuild }\n    def keyId = rootProject.ext[\"signing.keyId\"]\n    def ringFile = rootProject.ext[\"signing.secretKeyRingFile\"]\n    def password = rootProject.ext[\"signing.password\"]\n    useInMemoryPgpKeys(keyId, ringFile, password)\n    sign publishing.publications\n}\n\n// Export methods so they are available in other gradle files\n// https://stackoverflow.com/questions/18715137/extract-common-methods-from-gradle-build-script\next {\n    createPomDependencies = this.&createPomDependencies\n    populatePom = this.&populatePom\n}\n\n"
  },
  {
    "path": "mavencentral-publish.gradle",
    "content": "// This script is responsible for setting up the configuration required to publish to Maven Central.\n// Setting up POM files and signing artifacts are done in `mavencentral-publications.gradle`. They\n// are separate as the nexus publish plugin used to publish to Maven Central be only applied to top\n// level projects.\napply plugin: 'io.github.gradle-nexus.publish-plugin'\napply from: buildscript.sourceFile.getParent() + \"/\" + \"mavencentral-properties.gradle\"\n\nnexusPublishing {\n    packageGroup = \"io.realm\"\n    repositories {\n        sonatype {\n            stagingProfileId = rootProject.ext[\"sonatypeStagingProfileId\"]\n            username = rootProject.ext[\"ossrhUsername\"]\n            password = rootProject.ext[\"ossrhPassword\"]\n        }\n    }\n    // Repository transitions seems, at times, to be really slow.\n    // This sets the timeout to 20 minutes\n    transitionCheckOptions {\n        maxRetries.set(120)\n        delayBetween.set(java.time.Duration.ofMillis(10000))\n    }\n}\n"
  },
  {
    "path": "realm/build.gradle",
    "content": "buildscript {\n    def projectDependencies = new Properties()\n    projectDependencies.load(new FileInputStream(\"${rootDir}/../dependencies.list\"))\n    ext.kotlin_version = projectDependencies.get('KOTLIN')\n    ext.coroutines_android_version = projectDependencies.get('KOTLIN_COROUTINES')\n    ext.dokka_version = '1.5.0'\n    repositories {\n        mavenLocal()\n        google()\n        jcenter()\n        maven { url 'https://jitpack.io' }\n        maven { url \"https://plugins.gradle.org/m2/\" }\n    }\n\n    dependencies {\n        classpath \"com.android.tools.build:gradle:${projectDependencies.get('GRADLE_BUILD_TOOLS')}\"\n        classpath 'de.undercouch:gradle-download-task:4.0.2'\n        classpath 'com.github.dcendents:android-maven-gradle-plugin:2.1'\n        classpath 'com.novoda:gradle-android-command-plugin:1.2.1'\n        classpath 'com.github.skhatri:gradle-s3-plugin:1.0.4'\n        classpath 'org.kt3k.gradle.plugin:coveralls-gradle-plugin:2.8.2'\n        classpath \"org.jfrog.buildinfo:build-info-extractor-gradle:${projectDependencies.get('BUILD_INFO_EXTRACTOR_GRADLE')}\"\n        classpath \"io.realm:realm-transformer:${file('../version.txt').text.trim()}\"\n        classpath \"io.realm:realm-library-build-transformer:${file('../version.txt').text.trim()}\"\n        classpath 'net.ltgt.gradle:gradle-errorprone-plugin:2.0.2'\n        classpath \"org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version\"\n        classpath \"org.jetbrains.dokka:dokka-gradle-plugin:${dokka_version}\"\n        classpath \"gradle.plugin.com.github.spotbugs.snom:spotbugs-gradle-plugin:4.5.0\"\n        classpath \"io.github.gradle-nexus:publish-plugin:${projectDependencies.get(\"GRADLE_NEXUS_PLUGIN\")}\"\n    }\n}\n\nallprojects {\n    def projectDependencies = new Properties()\n    projectDependencies.load(new FileInputStream(\"${rootDir}/../dependencies.list\"))\n    projectDependencies.each { key, val ->\n        project.ext.set(key, val)\n    }\n    project.ext.minSdkVersion = 16\n    project.ext.compileSdkVersion = 30\n    project.ext.buildToolsVersion = projectDependencies.get(\"ANDROID_BUILD_TOOLS\")\n    group = 'io.realm'\n    version = file(\"${rootDir}/../version.txt\").text.trim()\n    repositories {\n        mavenLocal()\n        google()\n        jcenter()\n    }\n}\n\n// Disable JavaDoc strict mode: https://blog.joda.org/2014/02/turning-off-doclint-in-jdk-8-javadoc.html\nif (JavaVersion.current().isJava8Compatible()) {\n    allprojects {\n        tasks.withType(Javadoc) {\n            options.addStringOption('Xdoclint:-missing', '-quiet')\n        }\n    }\n}\n\napply from: \"${rootDir}/../mavencentral-publish.gradle\"\n"
  },
  {
    "path": "realm/config/checkstyle/checkstyle-suppressions.xml",
    "content": "<?xml version=\"1.0\"?>\n<!DOCTYPE suppressions PUBLIC\n    \"-//Puppy Crawl//DTD Suppressions 1.1//EN\"\n    \"http://www.puppycrawl.com/dtds/suppressions_1_1.dtd\">\n<suppressions>\n    <suppress checks=\"[a-zA-Z0-9]*\" files=\"R\\.java\" />\n    <suppress checks=\".\" files=\"BuildConfig.java\" />\n    <suppress checks=\".\" files=\".*\\.properties\" />\n    <suppress checks=\"FileLength\" files=\"RealmTests.java\" />\n    <suppress checks=\"FileLengthCheck\" files=\"Realm.java|RealmAsyncQueryTests.java|RealmQuery.java|RealmQueryTests.java\"/>\n    <suppress checks=\"VisibilityModifier\" files=\".*\\.java\"/>\n</suppressions>\n"
  },
  {
    "path": "realm/config/checkstyle/checkstyle.xml",
    "content": "<?xml version=\"1.0\"?>\n<!DOCTYPE module PUBLIC\n    \"-//Puppy Crawl//DTD Check Configuration 1.2//EN\"\n    \"http://www.puppycrawl.com/dtds/configuration_1_2.dtd\">\n\n<module name=\"Checker\">\n    <!-- There are non-ascii test cases -->\n    <property name=\"charset\" value=\"UTF-8\"/>\n    <!-- Files to ignore -->\n    <module name=\"SuppressionFilter\">\n        <property name=\"file\" value=\"${config_loc}/checkstyle-suppressions.xml\"/>\n    </module>\n\n    <module name=\"NewlineAtEndOfFile\">\n        <property name=\"lineSeparator\" value=\"lf\"/>\n    </module>\n\n    <module name=\"FileLength\">\n        <property name=\"id\" value=\"checkstyle:filelength\"/>\n    </module>\n\n    <module name=\"FileTabCharacter\"/>\n\n    <!-- Trailing spaces -->\n\n    <!-- Space after 'for', 'if', 'while', 'try' -->\n    <module name=\"RegexpSingleline\">\n        <property name=\"format\" value=\"^\\s*(for|if|while|try)\\b[^ ]\"/>\n        <property name=\"message\" value=\"Space needed before opening parenthesis.\"/>\n    </module>\n\n    <!-- For each spacing -->\n    <module name=\"RegexpSingleline\">\n        <property name=\"format\" value=\"^\\s*for \\(.*?([^ ]:|:[^ ])\"/>\n        <property name=\"message\" value=\"Space needed around ':' character.\"/>\n    </module>\n\n    <!-- Filter out Checkstyle warnings that have been suppressed with the @SuppressWarnings annotation -->\n    <module name=\"SuppressWarningsFilter\" />\n\n    <module name=\"TreeWalker\">\n        <!-- Make the @SuppressWarnings annotations available to Checkstyle -->\n        <module name=\"SuppressWarningsHolder\" />\n        <!-- Checks for Javadoc comments.                     -->\n        <!-- See http://checkstyle.sf.net/config_javadoc.html -->\n\n\n        <!-- Checks for Naming Conventions.                  -->\n        <!-- See http://checkstyle.sf.net/config_naming.html -->\n\n\n        <!-- Checks for imports                              -->\n        <!-- See http://checkstyle.sf.net/config_import.html -->\n\n\n        <!-- Checks for Size Violations.                    -->\n        <!-- See http://checkstyle.sf.net/config_sizes.html -->\n\n\n        <!-- Checks for whitespace                               -->\n        <!-- See http://checkstyle.sf.net/config_whitespace.html -->\n        <module name=\"WhitespaceAround\">\n            <property name=\"tokens\" value=\"LITERAL_DO\"/>\n        </module>\n\n\n        <!-- Modifier Checks                                    -->\n        <!-- See http://checkstyle.sf.net/config_modifiers.html -->\n        <module name=\"ModifierOrder\"/>\n        <module name=\"RedundantModifier\"/>\n\n\n        <!-- Coding Checks                                   -->\n        <!-- See http://checkstyle.sf.net/config_coding.html -->\n\n        <!-- Checks for blocks. You know, those {}'s         -->\n        <!-- See http://checkstyle.sf.net/config_blocks.html -->\n        <module name=\"EmptyCatchBlock\">\n            <property name=\"exceptionVariableName\" value=\"expected|ignore\"/>\n        </module>\n\n\n        <!-- Checks for common coding problems               -->\n        <!-- See http://checkstyle.sf.net/config_coding.html -->\n        <module name=\"CovariantEquals\"/>\n\n        <!-- Checks for class design                         -->\n        <!-- See http://checkstyle.sf.net/config_design.html -->\n        <module name=\"MutableException\"/>\n        <module name=\"VisibilityModifier\">\n            <property name=\"allowPublicImmutableFields\" value=\"true\"/>\n        </module>\n\n\n        <!-- Miscellaneous other checks.                   -->\n        <!-- See http://checkstyle.sf.net/config_misc.html -->\n        <module name=\"ArrayTypeStyle\"/>\n    </module>\n</module>\n"
  },
  {
    "path": "realm/config/findbugs/findbugs-filter.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<FindBugsFilter>\n    <!--\n    In code, please prefer annotations as a way of ignoring Findbugs issues\n    -->\n\n    <!-- Exclude test classes -->\n    <Match>\n        <Class name=\"~.*Test$\"/>\n    </Match>\n    <Match>\n        <Class name=\"~.*Tests$\"/>\n    </Match>\n    <Match>\n        <Class name=\"~.*Test\\$[0-9]*\"/> <!-- Lamdas inside Tests -->\n    </Match>\n    <Match>\n        <Class name=\"~.*Tests\\$[0-9]*\"/> <!-- Lamdas inside Tests -->\n    </Match>\n    <Match>\n        <Package name=\"~test\\..*\"/>\n    </Match>\n    <Match>\n        <Class name=\"io.realm.TestHelper\"/>\n    </Match>\n    <Match>\n        <Package name=\"~io.realm.entities.*\"/>\n    </Match>\n    <Match>\n        <Class name=\"io.realm.SyncManager$Debug\" />\n    </Match>\n    <Match>\n        <Class name=\"io.realm.rule.RunInLooperThread\" />\n        <Method name=\"after\" />\n        <Bug pattern=\"ST_WRITE_TO_STATIC_FROM_INSTANCE_METHOD\" />\n    </Match>\n    <Match>\n        <Class name=\"io.realm.rule.RunInLooperThread$RunInLooperThreadStatement\" />\n        <Method name=\"runTest\" />\n        <Bug pattern=\"DLS_DEAD_LOCAL_STORE\" />\n    </Match>\n    <Match>\n        <Class name=\"io.realm.rule.RunInLooperThread$RunInLooperThreadStatement\" />\n        <Method name=\"evaluate\" />\n        <Bug pattern=\"ST_WRITE_TO_STATIC_FROM_INSTANCE_METHOD\" />\n    </Match>\n    <Match>\n        <Class name=\"io.realm.objectserver.utils.RemoteIntegrationTestService\" />\n        <Bug pattern=\"ST_WRITE_TO_STATIC_FROM_INSTANCE_METHOD\" />\n    </Match>\n    <Match>\n        <Class name=\"io.realm.internal.common.ThreadDispatcher\" />\n        <Bug pattern=\"RV_RETURN_VALUE_IGNORED_BAD_PRACTICE\" />\n    </Match>\n    <Match>\n        <Class name=\"io.realm.TestHelper$TestLogger\" />\n        <Bug pattern=\"URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD\" />\n    </Match>\n    <Match>\n        <Class name=\"io.realm.rule.RunWithRemoteService\" />\n        <Field name=\"afterRunnable\" />\n        <Bug pattern=\"URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD\" />\n    </Match>\n\n    <!-- Generated code -->\n    <Match>\n        <Class name=\"~.*RealmProxy$\"/>\n    </Match>\n</FindBugsFilter>\n"
  },
  {
    "path": "realm/config/pmd/ruleset.xml",
    "content": "<?xml version=\"1.0\"?>\n<ruleset name=\"RealmRuleset\"\n         xmlns=\"http://pmd.sourceforge.net/ruleset/2.0.0\"\n         xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://pmd.sourceforge.net/ruleset/2.0.0 http://pmd.sourceforge.net/ruleset_2_0_0.xsd\">\n\n    <description>\n        Realm PMD ruleset\n    </description>\n\n    <rule ref=\"category/java/errorprone.xml/CallSuperFirst\" />\n    <rule ref=\"category/java/errorprone.xml/CallSuperLast\"/>\n    <rule ref=\"category/java/errorprone.xml/DoNotHardCodeSDCard\"/>\n</ruleset>\n"
  },
  {
    "path": "realm/config/studio/Realm-style.xml",
    "content": "<code_scheme name=\"Realm-style\">\n  <option name=\"CLASS_COUNT_TO_USE_IMPORT_ON_DEMAND\" value=\"99\" />\n  <option name=\"NAMES_COUNT_TO_USE_IMPORT_ON_DEMAND\" value=\"99\" />\n  <option name=\"PACKAGES_TO_USE_IMPORT_ON_DEMAND\">\n    <value />\n  </option>\n  <option name=\"IMPORT_LAYOUT_TABLE\">\n    <value>\n      <package name=\"android\" withSubpackages=\"true\" static=\"false\" />\n      <emptyLine />\n      <package name=\"com\" withSubpackages=\"true\" static=\"false\" />\n      <emptyLine />\n      <package name=\"junit\" withSubpackages=\"true\" static=\"false\" />\n      <emptyLine />\n      <package name=\"net\" withSubpackages=\"true\" static=\"false\" />\n      <emptyLine />\n      <package name=\"org\" withSubpackages=\"true\" static=\"false\" />\n      <emptyLine />\n      <package name=\"java\" withSubpackages=\"true\" static=\"false\" />\n      <emptyLine />\n      <package name=\"javax\" withSubpackages=\"true\" static=\"false\" />\n      <emptyLine />\n      <package name=\"\" withSubpackages=\"true\" static=\"false\" />\n      <emptyLine />\n      <package name=\"\" withSubpackages=\"true\" static=\"true\" />\n      <emptyLine />\n    </value>\n  </option>\n  <option name=\"RIGHT_MARGIN\" value=\"120\" />\n  <option name=\"JD_ALIGN_PARAM_COMMENTS\" value=\"false\" />\n  <option name=\"JD_ALIGN_EXCEPTION_COMMENTS\" value=\"false\" />\n  <AndroidXmlCodeStyleSettings>\n    <option name=\"USE_CUSTOM_SETTINGS\" value=\"true\" />\n  </AndroidXmlCodeStyleSettings>\n  <Objective-C-extensions>\n    <option name=\"GENERATE_INSTANCE_VARIABLES_FOR_PROPERTIES\" value=\"ASK\" />\n    <option name=\"RELEASE_STYLE\" value=\"IVAR\" />\n    <option name=\"TYPE_QUALIFIERS_PLACEMENT\" value=\"BEFORE\" />\n    <file>\n      <option name=\"com.jetbrains.cidr.lang.util.OCDeclarationKind\" value=\"Import\" />\n      <option name=\"com.jetbrains.cidr.lang.util.OCDeclarationKind\" value=\"Macro\" />\n      <option name=\"com.jetbrains.cidr.lang.util.OCDeclarationKind\" value=\"Typedef\" />\n      <option name=\"com.jetbrains.cidr.lang.util.OCDeclarationKind\" value=\"Enum\" />\n      <option name=\"com.jetbrains.cidr.lang.util.OCDeclarationKind\" value=\"Constant\" />\n      <option name=\"com.jetbrains.cidr.lang.util.OCDeclarationKind\" value=\"Global\" />\n      <option name=\"com.jetbrains.cidr.lang.util.OCDeclarationKind\" value=\"Struct\" />\n      <option name=\"com.jetbrains.cidr.lang.util.OCDeclarationKind\" value=\"FunctionPredecl\" />\n      <option name=\"com.jetbrains.cidr.lang.util.OCDeclarationKind\" value=\"Function\" />\n    </file>\n    <class>\n      <option name=\"com.jetbrains.cidr.lang.util.OCDeclarationKind\" value=\"Property\" />\n      <option name=\"com.jetbrains.cidr.lang.util.OCDeclarationKind\" value=\"Synthesize\" />\n      <option name=\"com.jetbrains.cidr.lang.util.OCDeclarationKind\" value=\"InitMethod\" />\n      <option name=\"com.jetbrains.cidr.lang.util.OCDeclarationKind\" value=\"StaticMethod\" />\n      <option name=\"com.jetbrains.cidr.lang.util.OCDeclarationKind\" value=\"InstanceMethod\" />\n      <option name=\"com.jetbrains.cidr.lang.util.OCDeclarationKind\" value=\"DeallocMethod\" />\n    </class>\n    <extensions>\n      <pair source=\"cpp\" header=\"h\" />\n      <pair source=\"c\" header=\"h\" />\n    </extensions>\n  </Objective-C-extensions>\n  <XML>\n    <option name=\"XML_KEEP_LINE_BREAKS\" value=\"false\" />\n    <option name=\"XML_ALIGN_ATTRIBUTES\" value=\"false\" />\n    <option name=\"XML_SPACE_INSIDE_EMPTY_TAG\" value=\"true\" />\n  </XML>\n  <codeStyleSettings language=\"JAVA\">\n    <option name=\"BLANK_LINES_AFTER_IMPORTS\" value=\"2\" />\n    <option name=\"ALIGN_MULTILINE_PARAMETERS\" value=\"false\" />\n    <option name=\"SPACE_BEFORE_ARRAY_INITIALIZER_LBRACE\" value=\"true\" />\n    <option name=\"KEEP_SIMPLE_BLOCKS_IN_ONE_LINE\" value=\"true\" />\n    <option name=\"KEEP_SIMPLE_METHODS_IN_ONE_LINE\" value=\"true\" />\n    <option name=\"KEEP_SIMPLE_LAMBDAS_IN_ONE_LINE\" value=\"true\" />\n    <option name=\"KEEP_SIMPLE_CLASSES_IN_ONE_LINE\" value=\"true\" />\n    <option name=\"IF_BRACE_FORCE\" value=\"3\" />\n    <option name=\"DOWHILE_BRACE_FORCE\" value=\"3\" />\n    <option name=\"WHILE_BRACE_FORCE\" value=\"3\" />\n    <option name=\"FOR_BRACE_FORCE\" value=\"3\" />\n  </codeStyleSettings>\n  <codeStyleSettings language=\"XML\">\n    <option name=\"FORCE_REARRANGE_MODE\" value=\"1\" />\n    <indentOptions>\n      <option name=\"CONTINUATION_INDENT_SIZE\" value=\"4\" />\n    </indentOptions>\n    <arrangement>\n      <rules>\n        <section>\n          <rule>\n            <match>\n              <AND>\n                <NAME>xmlns:android</NAME>\n                <XML_NAMESPACE>^$</XML_NAMESPACE>\n              </AND>\n            </match>\n          </rule>\n        </section>\n        <section>\n          <rule>\n            <match>\n              <AND>\n                <NAME>xmlns:.*</NAME>\n                <XML_NAMESPACE>^$</XML_NAMESPACE>\n              </AND>\n            </match>\n            <order>BY_NAME</order>\n          </rule>\n        </section>\n        <section>\n          <rule>\n            <match>\n              <AND>\n                <NAME>.*:id</NAME>\n                <XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>\n              </AND>\n            </match>\n          </rule>\n        </section>\n        <section>\n          <rule>\n            <match>\n              <AND>\n                <NAME>.*:name</NAME>\n                <XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>\n              </AND>\n            </match>\n          </rule>\n        </section>\n        <section>\n          <rule>\n            <match>\n              <AND>\n                <NAME>name</NAME>\n                <XML_NAMESPACE>^$</XML_NAMESPACE>\n              </AND>\n            </match>\n          </rule>\n        </section>\n        <section>\n          <rule>\n            <match>\n              <AND>\n                <NAME>style</NAME>\n                <XML_NAMESPACE>^$</XML_NAMESPACE>\n              </AND>\n            </match>\n          </rule>\n        </section>\n        <section>\n          <rule>\n            <match>\n              <AND>\n                <NAME>.*</NAME>\n                <XML_NAMESPACE>^$</XML_NAMESPACE>\n              </AND>\n            </match>\n            <order>BY_NAME</order>\n          </rule>\n        </section>\n        <section>\n          <rule>\n            <match>\n              <AND>\n                <NAME>.*:layout_width</NAME>\n                <XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>\n              </AND>\n            </match>\n          </rule>\n        </section>\n        <section>\n          <rule>\n            <match>\n              <AND>\n                <NAME>.*:layout_height</NAME>\n                <XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>\n              </AND>\n            </match>\n          </rule>\n        </section>\n        <section>\n          <rule>\n            <match>\n              <AND>\n                <NAME>.*:layout_.*</NAME>\n                <XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>\n              </AND>\n            </match>\n            <order>BY_NAME</order>\n          </rule>\n        </section>\n        <section>\n          <rule>\n            <match>\n              <AND>\n                <NAME>.*:width</NAME>\n                <XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>\n              </AND>\n            </match>\n            <order>BY_NAME</order>\n          </rule>\n        </section>\n        <section>\n          <rule>\n            <match>\n              <AND>\n                <NAME>.*:height</NAME>\n                <XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>\n              </AND>\n            </match>\n            <order>BY_NAME</order>\n          </rule>\n        </section>\n        <section>\n          <rule>\n            <match>\n              <AND>\n                <NAME>.*</NAME>\n                <XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>\n              </AND>\n            </match>\n            <order>BY_NAME</order>\n          </rule>\n        </section>\n        <section>\n          <rule>\n            <match>\n              <AND>\n                <NAME>.*</NAME>\n                <XML_NAMESPACE>.*</XML_NAMESPACE>\n              </AND>\n            </match>\n            <order>BY_NAME</order>\n          </rule>\n        </section>\n      </rules>\n    </arrangement>\n  </codeStyleSettings>\n</code_scheme>\n"
  },
  {
    "path": "realm/config/studio/Realm_lint.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<inspections version=\"1.0\">\n  <option name=\"myName\" value=\"Realm-lint\" />\n  <inspection_tool class=\"AccessToNonThreadSafeStaticFieldFromInstance\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"true\">\n    <option name=\"nonThreadSafeClasses\">\n      <value />\n    </option>\n    <option name=\"nonThreadSafeTypes\" value=\"\" />\n  </inspection_tool>\n  <inspection_tool class=\"Anonymous2MethodRef\" enabled=\"false\" level=\"WARNING\" enabled_by_default=\"false\" />\n  <inspection_tool class=\"AnonymousClassComplexity\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"true\">\n    <option name=\"m_limit\" value=\"3\" />\n  </inspection_tool>\n  <inspection_tool class=\"AnonymousClassMethodCount\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"true\">\n    <option name=\"m_limit\" value=\"5\" />\n  </inspection_tool>\n  <inspection_tool class=\"ArrayEquality\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"true\" />\n  <inspection_tool class=\"ArrayLengthInLoopCondition\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"true\" />\n  <inspection_tool class=\"AssignmentToSuperclassField\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"true\" />\n  <inspection_tool class=\"BadExceptionCaught\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"true\">\n    <option name=\"exceptionsString\" value=\"\" />\n    <option name=\"exceptions\">\n      <value />\n    </option>\n  </inspection_tool>\n  <inspection_tool class=\"CStyleArrayDeclaration\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"true\" />\n  <inspection_tool class=\"ClassComplexity\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"true\">\n    <option name=\"m_limit\" value=\"80\" />\n  </inspection_tool>\n  <inspection_tool class=\"ClassCoupling\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"true\">\n    <option name=\"m_includeJavaClasses\" value=\"false\" />\n    <option name=\"m_includeLibraryClasses\" value=\"false\" />\n    <option name=\"m_limit\" value=\"15\" />\n  </inspection_tool>\n  <inspection_tool class=\"ClassInitializer\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"true\" />\n  <inspection_tool class=\"ClassNestingDepth\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"true\">\n    <option name=\"m_limit\" value=\"2\" />\n  </inspection_tool>\n  <inspection_tool class=\"ClassWithOnlyPrivateConstructors\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"true\" />\n  <inspection_tool class=\"ComparableImplementedButEqualsNotOverridden\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"true\" />\n  <inspection_tool class=\"CompareToUsesNonFinalVariable\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"true\" />\n  <inspection_tool class=\"Convert2Lambda\" enabled=\"false\" level=\"WARNING\" enabled_by_default=\"false\" />\n  <inspection_tool class=\"CovariantCompareTo\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"true\" />\n  <inspection_tool class=\"CovariantEquals\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"true\" />\n  <inspection_tool class=\"DanglingJavadoc\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"true\" />\n  <inspection_tool class=\"DoubleCheckedLocking\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"true\">\n    <option name=\"ignoreOnVolatileVariables\" value=\"false\" />\n  </inspection_tool>\n  <inspection_tool class=\"EmptyInitializer\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"true\" />\n  <inspection_tool class=\"EmptySynchronizedStatement\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"true\" />\n  <inspection_tool class=\"EnumerationCanBeIteration\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"true\" />\n  <inspection_tool class=\"EqualsAndHashcode\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"true\" />\n  <inspection_tool class=\"EqualsCalledOnEnumConstant\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"true\" />\n  <inspection_tool class=\"EqualsUsesNonFinalVariable\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"true\" />\n  <inspection_tool class=\"FieldAccessedSynchronizedAndUnsynchronized\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"true\">\n    <option name=\"countGettersAndSetters\" value=\"false\" />\n  </inspection_tool>\n  <inspection_tool class=\"FieldMayBeFinal\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"true\" />\n  <inspection_tool class=\"FinalMethodInFinalClass\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"true\" />\n  <inspection_tool class=\"HashCodeUsesNonFinalVariable\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"true\" />\n  <inspection_tool class=\"InnerClassMayBeStatic\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"true\" />\n  <inspection_tool class=\"InstanceGuardedByStatic\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"true\" />\n  <inspection_tool class=\"InstanceofCatchParameter\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"true\" />\n  <inspection_tool class=\"InstanceofIncompatibleInterface\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"true\" />\n  <inspection_tool class=\"IteratorHasNextCallsIteratorNext\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"true\" />\n  <inspection_tool class=\"IteratorNextDoesNotThrowNoSuchElementException\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"true\" />\n  <inspection_tool class=\"ListIndexOfReplaceableByContains\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"true\" />\n  <inspection_tool class=\"LiteralAsArgToStringEquals\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"true\" />\n  <inspection_tool class=\"LoggerInitializedWithForeignClass\" enabled=\"false\" level=\"WARNING\" enabled_by_default=\"false\">\n    <option name=\"loggerClassName\" value=\"org.apache.log4j.Logger,org.slf4j.LoggerFactory,org.apache.commons.logging.LogFactory,java.util.logging.Logger\" />\n    <option name=\"loggerFactoryMethodName\" value=\"getLogger,getLogger,getLog,getLogger\" />\n  </inspection_tool>\n  <inspection_tool class=\"MethodCallInLoopCondition\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"true\" />\n  <inspection_tool class=\"MethodCount\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"true\">\n    <option name=\"m_limit\" value=\"20\" />\n    <option name=\"ignoreGettersAndSetters\" value=\"true\" />\n    <option name=\"ignoreOverridingMethods\" value=\"true\" />\n  </inspection_tool>\n  <inspection_tool class=\"MethodMayBeSynchronized\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"true\" />\n  <inspection_tool class=\"MissingDeprecatedAnnotation\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"true\" />\n  <inspection_tool class=\"MissingOverrideAnnotation\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"true\">\n    <option name=\"ignoreObjectMethods\" value=\"true\" />\n    <option name=\"ignoreAnonymousClassMethods\" value=\"false\" />\n  </inspection_tool>\n  <inspection_tool class=\"MisspelledCompareTo\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"true\" />\n  <inspection_tool class=\"MisspelledEquals\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"true\" />\n  <inspection_tool class=\"NonAtomicOperationOnVolatileField\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"true\" />\n  <inspection_tool class=\"NonFinalFieldInEnum\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"true\" />\n  <inspection_tool class=\"NonProtectedConstructorInAbstractClass\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"true\">\n    <option name=\"m_ignoreNonPublicClasses\" value=\"false\" />\n  </inspection_tool>\n  <inspection_tool class=\"NonShortCircuitBoolean\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"true\" />\n  <inspection_tool class=\"NonSynchronizedMethodOverridesSynchronizedMethod\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"true\" />\n  <inspection_tool class=\"NullThrown\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"true\" />\n  <inspection_tool class=\"ObjectEquality\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"true\">\n    <option name=\"m_ignoreEnums\" value=\"true\" />\n    <option name=\"m_ignoreClassObjects\" value=\"false\" />\n    <option name=\"m_ignorePrivateConstructors\" value=\"false\" />\n  </inspection_tool>\n  <inspection_tool class=\"ObjectNotify\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"true\" />\n  <inspection_tool class=\"ObsoleteCollection\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"true\">\n    <option name=\"ignoreRequiredObsoleteCollectionTypes\" value=\"false\" />\n  </inspection_tool>\n  <inspection_tool class=\"OnDemandImport\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"true\" />\n  <inspection_tool class=\"ParameterTypePreventsOverriding\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"true\" />\n  <inspection_tool class=\"PrivateMemberAccessBetweenOuterAndInnerClass\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"true\" />\n  <inspection_tool class=\"ProblematicVarargsMethodOverride\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"true\" />\n  <inspection_tool class=\"ProtectedMemberInFinalClass\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"true\" />\n  <inspection_tool class=\"RedundantThrowsDeclaration\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"true\" />\n  <inspection_tool class=\"ResultOfObjectAllocationIgnored\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"true\" />\n  <inspection_tool class=\"ReturnOfInnerClass\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"true\" />\n  <inspection_tool class=\"SafeLock\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"true\" />\n  <inspection_tool class=\"SamePackageImport\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"true\" />\n  <inspection_tool class=\"SimplifiableIfStatement\" enabled=\"false\" level=\"WARNING\" enabled_by_default=\"false\" />\n  <inspection_tool class=\"SizeReplaceableByIsEmpty\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"true\" />\n  <inspection_tool class=\"SleepWhileHoldingLock\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"true\" />\n  <inspection_tool class=\"StaticCallOnSubclass\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"true\" />\n  <inspection_tool class=\"StaticFieldReferenceOnSubclass\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"true\" />\n  <inspection_tool class=\"StaticGuardedByInstance\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"true\" />\n  <inspection_tool class=\"StringBufferField\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"true\" />\n  <inspection_tool class=\"SystemOutErr\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"true\" />\n  <inspection_tool class=\"ThreadDumpStack\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"true\" />\n  <inspection_tool class=\"ThrowablePrintStackTrace\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"true\" />\n  <inspection_tool class=\"TooBroadCatch\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"true\" />\n  <inspection_tool class=\"TooBroadThrows\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"true\" />\n  <inspection_tool class=\"UnclearBinaryExpression\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"true\" />\n  <inspection_tool class=\"UnnecessaryInheritDoc\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"true\" />\n  <inspection_tool class=\"UnnecessaryJavaDocLink\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"true\">\n    <option name=\"ignoreInlineLinkToSuper\" value=\"false\" />\n  </inspection_tool>\n  <inspection_tool class=\"VolatileArrayField\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"true\" />\n  <inspection_tool class=\"VolatileLongOrDoubleField\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"true\" />\n  <inspection_tool class=\"WaitNotInLoop\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"true\" />\n  <inspection_tool class=\"WaitWhileHoldingTwoLocks\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"true\" />\n</inspections>\n\n"
  },
  {
    "path": "realm/gradle/wrapper/gradle-wrapper.properties",
    "content": "distributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\ndistributionUrl=https\\://services.gradle.org/distributions/gradle-7.5-all.zip\nzipStoreBase=GRADLE_USER_HOME\nzipStorePath=wrapper/dists\n"
  },
  {
    "path": "realm/gradle.properties",
    "content": "org.gradle.jvmargs=-Xms1024m -Xmx4096m\norg.gradle.caching=true\nkotlin.incremental=false\norg.gradle.parallel=false\norg.gradle.daemon=false\nandroid.useAndroidX=true\nandroid.enableJetifier=true\n#FIXME: enable when https://github.com/realm/realm-java/issues/7605 is resolved\nandroid.experimental.androidTest.useUnifiedTestPlatform=false\n\n# TODO Seems like using core binaries is currently broken and has been it for a while. Enabling\n#  explicit building of core so that builds don't fail. We should find out if we want to support\n#  using binaries or otherwise remove the logic around this and just always build core.\nbuildCore=true\n"
  },
  {
    "path": "realm/gradlew",
    "content": "#!/bin/sh\n\n#\n# Copyright © 2015-2021 the original authors.\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#      https://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##############################################################################\n#\n#   Gradle start up script for POSIX generated by Gradle.\n#\n#   Important for running:\n#\n#   (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is\n#       noncompliant, but you have some other compliant shell such as ksh or\n#       bash, then to run this script, type that shell name before the whole\n#       command line, like:\n#\n#           ksh Gradle\n#\n#       Busybox and similar reduced shells will NOT work, because this script\n#       requires all of these POSIX shell features:\n#         * functions;\n#         * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,\n#           «${var#prefix}», «${var%suffix}», and «$( cmd )»;\n#         * compound commands having a testable exit status, especially «case»;\n#         * various built-in commands including «command», «set», and «ulimit».\n#\n#   Important for patching:\n#\n#   (2) This script targets any POSIX shell, so it avoids extensions provided\n#       by Bash, Ksh, etc; in particular arrays are avoided.\n#\n#       The \"traditional\" practice of packing multiple parameters into a\n#       space-separated string is a well documented source of bugs and security\n#       problems, so this is (mostly) avoided, by progressively accumulating\n#       options in \"$@\", and eventually passing that to Java.\n#\n#       Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,\n#       and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;\n#       see the in-line comments for details.\n#\n#       There are tweaks for specific operating systems such as AIX, CygWin,\n#       Darwin, MinGW, and NonStop.\n#\n#   (3) This script is generated from the Groovy template\n#       https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt\n#       within the Gradle project.\n#\n#       You can find Gradle at https://github.com/gradle/gradle/.\n#\n##############################################################################\n\n# Attempt to set APP_HOME\n\n# Resolve links: $0 may be a link\napp_path=$0\n\n# Need this for daisy-chained symlinks.\nwhile\n    APP_HOME=${app_path%\"${app_path##*/}\"}  # leaves a trailing /; empty if no leading path\n    [ -h \"$app_path\" ]\ndo\n    ls=$( ls -ld \"$app_path\" )\n    link=${ls#*' -> '}\n    case $link in             #(\n      /*)   app_path=$link ;; #(\n      *)    app_path=$APP_HOME$link ;;\n    esac\ndone\n\nAPP_HOME=$( cd \"${APP_HOME:-./}\" && pwd -P ) || exit\n\nAPP_NAME=\"Gradle\"\nAPP_BASE_NAME=${0##*/}\n\n# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\nDEFAULT_JVM_OPTS='\"-Xmx64m\" \"-Xms64m\"'\n\n# Use the maximum available, or set MAX_FD != -1 to use that value.\nMAX_FD=maximum\n\nwarn () {\n    echo \"$*\"\n} >&2\n\ndie () {\n    echo\n    echo \"$*\"\n    echo\n    exit 1\n} >&2\n\n# OS specific support (must be 'true' or 'false').\ncygwin=false\nmsys=false\ndarwin=false\nnonstop=false\ncase \"$( uname )\" in                #(\n  CYGWIN* )         cygwin=true  ;; #(\n  Darwin* )         darwin=true  ;; #(\n  MSYS* | MINGW* )  msys=true    ;; #(\n  NONSTOP* )        nonstop=true ;;\nesac\n\nCLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar\n\n\n# Determine the Java command to use to start the JVM.\nif [ -n \"$JAVA_HOME\" ] ; then\n    if [ -x \"$JAVA_HOME/jre/sh/java\" ] ; then\n        # IBM's JDK on AIX uses strange locations for the executables\n        JAVACMD=$JAVA_HOME/jre/sh/java\n    else\n        JAVACMD=$JAVA_HOME/bin/java\n    fi\n    if [ ! -x \"$JAVACMD\" ] ; then\n        die \"ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME\n\nPlease set the JAVA_HOME variable in your environment to match the\nlocation of your Java installation.\"\n    fi\nelse\n    JAVACMD=java\n    which java >/dev/null 2>&1 || die \"ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.\n\nPlease set the JAVA_HOME variable in your environment to match the\nlocation of your Java installation.\"\nfi\n\n# Increase the maximum file descriptors if we can.\nif ! \"$cygwin\" && ! \"$darwin\" && ! \"$nonstop\" ; then\n    case $MAX_FD in #(\n      max*)\n        MAX_FD=$( ulimit -H -n ) ||\n            warn \"Could not query maximum file descriptor limit\"\n    esac\n    case $MAX_FD in  #(\n      '' | soft) :;; #(\n      *)\n        ulimit -n \"$MAX_FD\" ||\n            warn \"Could not set maximum file descriptor limit to $MAX_FD\"\n    esac\nfi\n\n# Collect all arguments for the java command, stacking in reverse order:\n#   * args from the command line\n#   * the main class name\n#   * -classpath\n#   * -D...appname settings\n#   * --module-path (only if needed)\n#   * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.\n\n# For Cygwin or MSYS, switch paths to Windows format before running java\nif \"$cygwin\" || \"$msys\" ; then\n    APP_HOME=$( cygpath --path --mixed \"$APP_HOME\" )\n    CLASSPATH=$( cygpath --path --mixed \"$CLASSPATH\" )\n\n    JAVACMD=$( cygpath --unix \"$JAVACMD\" )\n\n    # Now convert the arguments - kludge to limit ourselves to /bin/sh\n    for arg do\n        if\n            case $arg in                                #(\n              -*)   false ;;                            # don't mess with options #(\n              /?*)  t=${arg#/} t=/${t%%/*}              # looks like a POSIX filepath\n                    [ -e \"$t\" ] ;;                      #(\n              *)    false ;;\n            esac\n        then\n            arg=$( cygpath --path --ignore --mixed \"$arg\" )\n        fi\n        # Roll the args list around exactly as many times as the number of\n        # args, so each arg winds up back in the position where it started, but\n        # possibly modified.\n        #\n        # NB: a `for` loop captures its iteration list before it begins, so\n        # changing the positional parameters here affects neither the number of\n        # iterations, nor the values presented in `arg`.\n        shift                   # remove old arg\n        set -- \"$@\" \"$arg\"      # push replacement arg\n    done\nfi\n\n# Collect all arguments for the java command;\n#   * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of\n#     shell script including quotes and variable substitutions, so put them in\n#     double quotes to make sure that they get re-expanded; and\n#   * put everything else in single quotes, so that it's not re-expanded.\n\nset -- \\\n        \"-Dorg.gradle.appname=$APP_BASE_NAME\" \\\n        -classpath \"$CLASSPATH\" \\\n        org.gradle.wrapper.GradleWrapperMain \\\n        \"$@\"\n\n# Stop when \"xargs\" is not available.\nif ! command -v xargs >/dev/null 2>&1\nthen\n    die \"xargs is not available\"\nfi\n\n# Use \"xargs\" to parse quoted args.\n#\n# With -n1 it outputs one arg per line, with the quotes and backslashes removed.\n#\n# In Bash we could simply go:\n#\n#   readarray ARGS < <( xargs -n1 <<<\"$var\" ) &&\n#   set -- \"${ARGS[@]}\" \"$@\"\n#\n# but POSIX shell has neither arrays nor command substitution, so instead we\n# post-process each arg (as a line of input to sed) to backslash-escape any\n# character that might be a shell metacharacter, then use eval to reverse\n# that process (while maintaining the separation between arguments), and wrap\n# the whole thing up as a single \"set\" statement.\n#\n# This will of course break if any of these variables contains a newline or\n# an unmatched quote.\n#\n\neval \"set -- $(\n        printf '%s\\n' \"$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS\" |\n        xargs -n1 |\n        sed ' s~[^-[:alnum:]+,./:=@_]~\\\\&~g; ' |\n        tr '\\n' ' '\n    )\" '\"$@\"'\n\nexec \"$JAVACMD\" \"$@\"\n"
  },
  {
    "path": "realm/gradlew.bat",
    "content": "@rem\r\n@rem Copyright 2015 the original author or authors.\r\n@rem\r\n@rem Licensed under the Apache License, Version 2.0 (the \"License\");\r\n@rem you may not use this file except in compliance with the License.\r\n@rem You may obtain a copy of the License at\r\n@rem\r\n@rem      https://www.apache.org/licenses/LICENSE-2.0\r\n@rem\r\n@rem Unless required by applicable law or agreed to in writing, software\r\n@rem distributed under the License is distributed on an \"AS IS\" BASIS,\r\n@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n@rem See the License for the specific language governing permissions and\r\n@rem limitations under the License.\r\n@rem\r\n\r\n@if \"%DEBUG%\"==\"\" @echo off\r\n@rem ##########################################################################\r\n@rem\r\n@rem  Gradle startup script for Windows\r\n@rem\r\n@rem ##########################################################################\r\n\r\n@rem Set local scope for the variables with windows NT shell\r\nif \"%OS%\"==\"Windows_NT\" setlocal\r\n\r\nset DIRNAME=%~dp0\r\nif \"%DIRNAME%\"==\"\" set DIRNAME=.\r\nset APP_BASE_NAME=%~n0\r\nset APP_HOME=%DIRNAME%\r\n\r\n@rem Resolve any \".\" and \"..\" in APP_HOME to make it shorter.\r\nfor %%i in (\"%APP_HOME%\") do set APP_HOME=%%~fi\r\n\r\n@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\r\nset DEFAULT_JVM_OPTS=\"-Xmx64m\" \"-Xms64m\"\r\n\r\n@rem Find java.exe\r\nif defined JAVA_HOME goto findJavaFromJavaHome\r\n\r\nset JAVA_EXE=java.exe\r\n%JAVA_EXE% -version >NUL 2>&1\r\nif %ERRORLEVEL% equ 0 goto execute\r\n\r\necho.\r\necho ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.\r\necho.\r\necho Please set the JAVA_HOME variable in your environment to match the\r\necho location of your Java installation.\r\n\r\ngoto fail\r\n\r\n:findJavaFromJavaHome\r\nset JAVA_HOME=%JAVA_HOME:\"=%\r\nset JAVA_EXE=%JAVA_HOME%/bin/java.exe\r\n\r\nif exist \"%JAVA_EXE%\" goto execute\r\n\r\necho.\r\necho ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%\r\necho.\r\necho Please set the JAVA_HOME variable in your environment to match the\r\necho location of your Java installation.\r\n\r\ngoto fail\r\n\r\n:execute\r\n@rem Setup the command line\r\n\r\nset CLASSPATH=%APP_HOME%\\gradle\\wrapper\\gradle-wrapper.jar\r\n\r\n\r\n@rem Execute Gradle\r\n\"%JAVA_EXE%\" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% \"-Dorg.gradle.appname=%APP_BASE_NAME%\" -classpath \"%CLASSPATH%\" org.gradle.wrapper.GradleWrapperMain %*\r\n\r\n:end\r\n@rem End local scope for the variables with windows NT shell\r\nif %ERRORLEVEL% equ 0 goto mainEnd\r\n\r\n:fail\r\nrem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of\r\nrem the _cmd.exe /c_ return code!\r\nset EXIT_CODE=%ERRORLEVEL%\r\nif %EXIT_CODE% equ 0 set EXIT_CODE=1\r\nif not \"\"==\"%GRADLE_EXIT_CONSOLE%\" exit %EXIT_CODE%\r\nexit /b %EXIT_CODE%\r\n\r\n:mainEnd\r\nif \"%OS%\"==\"Windows_NT\" endlocal\r\n\r\n:omega\r\n"
  },
  {
    "path": "realm/kotlin-extensions/.gitignore",
    "content": "/build\n"
  },
  {
    "path": "realm/kotlin-extensions/build.gradle",
    "content": "apply plugin: 'com.android.library'\napply plugin: 'kotlin-android'\napply plugin: 'kotlin-kapt'\napply plugin: 'de.undercouch.download'\napply plugin: 'org.jetbrains.dokka'\n\n// TODO How many of these work on Kotlin?\n//apply plugin: 'findbugs'\n//apply plugin: 'pmd'\n//apply plugin: 'checkstyle'\n//apply plugin: 'com.github.kt3k.coveralls'\n//apply plugin: 'net.ltgt.errorprone'\n\ndef properties = new Properties()\nproperties.load(new FileInputStream(\"${projectDir}/../../dependencies.list\"))\n\nandroid {\n    compileSdkVersion rootProject.compileSdkVersion\n    buildToolsVersion rootProject.buildToolsVersion\n    defaultConfig {\n        minSdkVersion rootProject.minSdkVersion\n        targetSdkVersion rootProject.compileSdkVersion\n        versionName version\n        multiDexEnabled true\n        project.archivesBaseName = \"realm-kotlin-extensions\"\n\n        testInstrumentationRunner \"androidx.test.runner.AndroidJUnitRunner\"\n    }\n    buildTypes {\n        debug {\n            // https://youtrack.jetbrains.com/issue/KT-11333\n            // Until this is resolved, enabling code coverage will break extension functions\n            // during instrumentation testing.\n            testCoverageEnabled = false\n        }\n        release {\n            minifyEnabled false\n        }\n    }\n\n    flavorDimensions 'api'\n\n    productFlavors {\n        base {\n            dimension 'api'\n        }\n        objectServer {\n            dimension 'api'\n        }\n    }\n\n    sourceSets {\n        main.java.srcDirs += 'src/main/kotlin'\n        androidTest.java.srcDirs += [\n                'src/androidTest/kotlin',\n                '../realm-library/src/testUtils/java',\n                '../realm-library/src/testUtils/kotlin'\n        ]\n        objectServer.java.srcDirs += 'src/objectServer/kotlin'\n        androidTestObjectServer.java.srcDirs += [\n                'src/androidTestObjectServer/kotlin',\n                '../realm-library/src/testUtils/java',\n                '../realm-library/src/testUtils/kotlin',\n                '../realm-library/src/syncTestUtils/java',\n                '../realm-library/src/syncTestUtils/kotlin',\n        ]\n    }\n\n    packagingOptions {\n         exclude \"META-INF/AL2.0\"\n         exclude \"META-INF/LGPL2.1\"\n    }\n\n    // Required from Kotlin 1.1.2\n    compileOptions {\n        targetCompatibility JavaVersion.VERSION_1_8\n        sourceCompatibility JavaVersion.VERSION_1_8\n    }\n\n    kotlinOptions {\n        jvmTarget = JavaVersion.VERSION_1_8\n    }\n}\n\ndependencies {\n    implementation project(':realm-library')\n\n    implementation \"org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version\"\n    implementation \"org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutines_android_version\"\n    implementation \"org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutines_android_version\"\n    androidTestImplementation \"org.jetbrains.kotlinx:kotlinx-coroutines-test:$coroutines_android_version\"\n    androidTestImplementation \"org.jetbrains.kotlin:kotlin-test:$kotlin_version\"\n\n    androidTestImplementation 'junit:junit:4.12'\n    androidTestImplementation 'androidx.test.ext:junit:1.1.1'\n    androidTestImplementation 'androidx.test:rules:1.2.0'\n    androidTestImplementation \"org.mongodb:bson:${properties.getProperty('BSON_DEPENDENCY')}\"\n    androidTestImplementation 'com.google.code.findbugs:jsr305:3.0.2'\n    kaptAndroidTest project(':realm-annotations-processor')\n    androidTestImplementation \"org.jetbrains.kotlin:kotlin-reflect:$kotlin_version\"\n    androidTestObjectServerImplementation 'com.squareup.okhttp3:okhttp:3.9.0'\n    androidTestObjectServerImplementation \"io.reactivex.rxjava2:rxjava:${properties.getProperty('RXJAVA_DEPENDENCY')}\"\n}\n\nrepositories {\n    mavenCentral()\n}\n\n// enable @ParametersAreNonnullByDefault annotation. See https://blog.jetbrains.com/kotlin/2017/09/kotlin-1-1-50-is-out/\ntasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).all {\n    kotlinOptions {\n        freeCompilerArgs = [\"-Xjsr305=strict\"]\n    }\n}\n\ntask sourcesJar(type: Jar) {\n    from android.sourceSets.objectServer.java.srcDirs\n    from android.sourceSets.main.java.srcDirs\n    classifier = 'sources'\n}\n\ntasks.dokkaHtml.configure {\n    outputDirectory.set(file(\"$buildDir/dokka\"))\n}\n\ntask javadocJar(type: Jar, dependsOn: dokkaHtml) {\n    classifier = 'javadoc'\n    from \"$buildDir/dokka\"\n}\n\napply from: \"${rootDir}/../mavencentral-publications.gradle\"\n\npublishing {\n    publications {\n        basePublication(MavenPublication) {\n            groupId 'io.realm'\n            artifactId 'realm-android-kotlin-extensions'\n            version project.version\n            artifact (file(\"${rootDir}/kotlin-extensions/build/outputs/aar/realm-kotlin-extensions-base-release.aar\")) {\n                builtBy assemble\n            }\n            artifact sourcesJar\n            artifact javadocJar\n            populatePom(\n                    it,\n                    'realm-android-kotlin-extensions',\n                    'Kotlin specific APIs and extension functions for Realm for Android',\n                    createPomDependencies([\"baseImplementation\", \"implementation\", \"baseApi\", \"api\"])\n            )\n        }\n\n        objectServerPublication(MavenPublication) {\n            groupId 'io.realm'\n            artifactId 'realm-android-kotlin-extensions-object-server'\n            version project.version\n            artifact (file(\"${rootDir}/kotlin-extensions/build/outputs/aar/realm-kotlin-extensions-objectServer-release.aar\")) {\n                builtBy assemble\n            }\n            artifact sourcesJar\n            artifact javadocJar\n            populatePom(\n                    it,\n                    'realm-android-kotlin-extensions-object-server',\n                    'Kotlin specific APIs and extension functions for Realm for Android',\n                    createPomDependencies([\"objectServerImplementation\", \"implementation\", \"objectServerApi\", \"api\"])\n            )\n        }\n    }\n}\n\nartifacts {\n    archives javadocJar\n    archives sourcesJar\n}\n\npublishToMavenLocal.dependsOn assemble\n\nio.realm.transformer.RealmTransformerKt.registerRealmTransformerTask(project)\n\n"
  },
  {
    "path": "realm/kotlin-extensions/lib/package-list.txt",
    "content": "$dokka.format:kotlin-website-html\n$dokka.linkExtension:html\n$dokka.location:kotlin$and(java.math.BigInteger, java.math.BigInteger)\u001fkotlin/java.math.-big-integer/and.html\n$dokka.location:kotlin$dec(java.math.BigDecimal)\u001fkotlin/java.math.-big-decimal/dec.html\n$dokka.location:kotlin$dec(java.math.BigInteger)\u001fkotlin/java.math.-big-integer/dec.html\n$dokka.location:kotlin$div(java.math.BigDecimal, java.math.BigDecimal)\u001fkotlin/java.math.-big-decimal/div.html\n$dokka.location:kotlin$div(java.math.BigInteger, java.math.BigInteger)\u001fkotlin/java.math.-big-integer/div.html\n$dokka.location:kotlin$inc(java.math.BigDecimal)\u001fkotlin/java.math.-big-decimal/inc.html\n$dokka.location:kotlin$inc(java.math.BigInteger)\u001fkotlin/java.math.-big-integer/inc.html\n$dokka.location:kotlin$inv(java.math.BigInteger)\u001fkotlin/java.math.-big-integer/inv.html\n$dokka.location:kotlin$minus(java.math.BigDecimal, java.math.BigDecimal)\u001fkotlin/java.math.-big-decimal/minus.html\n$dokka.location:kotlin$minus(java.math.BigInteger, java.math.BigInteger)\u001fkotlin/java.math.-big-integer/minus.html\n$dokka.location:kotlin$mod(java.math.BigDecimal, java.math.BigDecimal)\u001fkotlin/java.math.-big-decimal/mod.html\n$dokka.location:kotlin$or(java.math.BigInteger, java.math.BigInteger)\u001fkotlin/java.math.-big-integer/or.html\n$dokka.location:kotlin$plus(java.math.BigDecimal, java.math.BigDecimal)\u001fkotlin/java.math.-big-decimal/plus.html\n$dokka.location:kotlin$plus(java.math.BigInteger, java.math.BigInteger)\u001fkotlin/java.math.-big-integer/plus.html\n$dokka.location:kotlin$rem(java.math.BigDecimal, java.math.BigDecimal)\u001fkotlin/java.math.-big-decimal/rem.html\n$dokka.location:kotlin$rem(java.math.BigInteger, java.math.BigInteger)\u001fkotlin/java.math.-big-integer/rem.html\n$dokka.location:kotlin$shl(java.math.BigInteger, kotlin.Int)\u001fkotlin/java.math.-big-integer/shl.html\n$dokka.location:kotlin$shr(java.math.BigInteger, kotlin.Int)\u001fkotlin/java.math.-big-integer/shr.html\n$dokka.location:kotlin$times(java.math.BigDecimal, java.math.BigDecimal)\u001fkotlin/java.math.-big-decimal/times.html\n$dokka.location:kotlin$times(java.math.BigInteger, java.math.BigInteger)\u001fkotlin/java.math.-big-integer/times.html\n$dokka.location:kotlin$toBigDecimal(java.math.BigInteger)\u001fkotlin/java.math.-big-integer/to-big-decimal.html\n$dokka.location:kotlin$toBigDecimal(java.math.BigInteger, kotlin.Int, java.math.MathContext)\u001fkotlin/java.math.-big-integer/to-big-decimal.html\n$dokka.location:kotlin$unaryMinus(java.math.BigDecimal)\u001fkotlin/java.math.-big-decimal/unary-minus.html\n$dokka.location:kotlin$unaryMinus(java.math.BigInteger)\u001fkotlin/java.math.-big-integer/unary-minus.html\n$dokka.location:kotlin$xor(java.math.BigInteger, java.math.BigInteger)\u001fkotlin/java.math.-big-integer/xor.html\n$dokka.location:kotlin.ArithmeticException\u001fkotlin/-arithmetic-exception/index.html\n$dokka.location:kotlin.AssertionError\u001fkotlin/-assertion-error/index.html\n$dokka.location:kotlin.ClassCastException\u001fkotlin/-class-cast-exception/index.html\n$dokka.location:kotlin.Comparator\u001fkotlin/-comparator/index.html\n$dokka.location:kotlin.ConcurrentModificationException\u001fkotlin/-concurrent-modification-exception/index.html\n$dokka.location:kotlin.Error\u001fkotlin/-error/index.html\n$dokka.location:kotlin.Exception\u001fkotlin/-exception/index.html\n$dokka.location:kotlin.IllegalArgumentException\u001fkotlin/-illegal-argument-exception/index.html\n$dokka.location:kotlin.IllegalStateException\u001fkotlin/-illegal-state-exception/index.html\n$dokka.location:kotlin.IndexOutOfBoundsException\u001fkotlin/-index-out-of-bounds-exception/index.html\n$dokka.location:kotlin.NoSuchElementException\u001fkotlin/-no-such-element-exception/index.html\n$dokka.location:kotlin.NullPointerException\u001fkotlin/-null-pointer-exception/index.html\n$dokka.location:kotlin.NumberFormatException\u001fkotlin/-number-format-exception/index.html\n$dokka.location:kotlin.RuntimeException\u001fkotlin/-runtime-exception/index.html\n$dokka.location:kotlin.Synchronized\u001fkotlin/-synchronized/index.html\n$dokka.location:kotlin.UnsupportedOperationException\u001fkotlin/-unsupported-operation-exception/index.html\n$dokka.location:kotlin.Volatile\u001fkotlin/-volatile/index.html\n$dokka.location:kotlin.collections$getOrPut(java.util.concurrent.ConcurrentMap((kotlin.collections.getOrPut.K, kotlin.collections.getOrPut.V)), kotlin.collections.getOrPut.K, kotlin.Function0((kotlin.collections.getOrPut.V)))\u001fkotlin.collections/java.util.concurrent.-concurrent-map/get-or-put.html\n$dokka.location:kotlin.collections$iterator(java.util.Enumeration((kotlin.collections.iterator.T)))\u001fkotlin.collections/java.util.-enumeration/iterator.html\n$dokka.location:kotlin.collections$toList(java.util.Enumeration((kotlin.collections.toList.T)))\u001fkotlin.collections/java.util.-enumeration/to-list.html\n$dokka.location:kotlin.collections.ArrayList\u001fkotlin.collections/-array-list/index.html\n$dokka.location:kotlin.collections.HashMap\u001fkotlin.collections/-hash-map/index.html\n$dokka.location:kotlin.collections.HashSet\u001fkotlin.collections/-hash-set/index.html\n$dokka.location:kotlin.collections.LinkedHashMap\u001fkotlin.collections/-linked-hash-map/index.html\n$dokka.location:kotlin.collections.LinkedHashSet\u001fkotlin.collections/-linked-hash-set/index.html\n$dokka.location:kotlin.concurrent$getOrSet(java.lang.ThreadLocal((kotlin.concurrent.getOrSet.T)), kotlin.Function0((kotlin.concurrent.getOrSet.T)))\u001fkotlin.concurrent/java.lang.-thread-local/get-or-set.html\n$dokka.location:kotlin.concurrent$read(java.util.concurrent.locks.ReentrantReadWriteLock, kotlin.Function0((kotlin.concurrent.read.T)))\u001fkotlin.concurrent/java.util.concurrent.locks.-reentrant-read-write-lock/read.html\n$dokka.location:kotlin.concurrent$schedule(java.util.Timer, java.util.Date, kotlin.Function1((java.util.TimerTask, kotlin.Unit)))\u001fkotlin.concurrent/java.util.-timer/schedule.html\n$dokka.location:kotlin.concurrent$schedule(java.util.Timer, java.util.Date, kotlin.Long, kotlin.Function1((java.util.TimerTask, kotlin.Unit)))\u001fkotlin.concurrent/java.util.-timer/schedule.html\n$dokka.location:kotlin.concurrent$schedule(java.util.Timer, kotlin.Long, kotlin.Function1((java.util.TimerTask, kotlin.Unit)))\u001fkotlin.concurrent/java.util.-timer/schedule.html\n$dokka.location:kotlin.concurrent$schedule(java.util.Timer, kotlin.Long, kotlin.Long, kotlin.Function1((java.util.TimerTask, kotlin.Unit)))\u001fkotlin.concurrent/java.util.-timer/schedule.html\n$dokka.location:kotlin.concurrent$scheduleAtFixedRate(java.util.Timer, java.util.Date, kotlin.Long, kotlin.Function1((java.util.TimerTask, kotlin.Unit)))\u001fkotlin.concurrent/java.util.-timer/schedule-at-fixed-rate.html\n$dokka.location:kotlin.concurrent$scheduleAtFixedRate(java.util.Timer, kotlin.Long, kotlin.Long, kotlin.Function1((java.util.TimerTask, kotlin.Unit)))\u001fkotlin.concurrent/java.util.-timer/schedule-at-fixed-rate.html\n$dokka.location:kotlin.concurrent$withLock(java.util.concurrent.locks.Lock, kotlin.Function0((kotlin.concurrent.withLock.T)))\u001fkotlin.concurrent/java.util.concurrent.locks.-lock/with-lock.html\n$dokka.location:kotlin.concurrent$write(java.util.concurrent.locks.ReentrantReadWriteLock, kotlin.Function0((kotlin.concurrent.write.T)))\u001fkotlin.concurrent/java.util.concurrent.locks.-reentrant-read-write-lock/write.html\n$dokka.location:kotlin.io$appendBytes(java.io.File, kotlin.ByteArray)\u001fkotlin.io/java.io.-file/append-bytes.html\n$dokka.location:kotlin.io$appendText(java.io.File, kotlin.String, java.nio.charset.Charset)\u001fkotlin.io/java.io.-file/append-text.html\n$dokka.location:kotlin.io$buffered(java.io.InputStream, kotlin.Int)\u001fkotlin.io/java.io.-input-stream/buffered.html\n$dokka.location:kotlin.io$buffered(java.io.OutputStream, kotlin.Int)\u001fkotlin.io/java.io.-output-stream/buffered.html\n$dokka.location:kotlin.io$buffered(java.io.Reader, kotlin.Int)\u001fkotlin.io/java.io.-reader/buffered.html\n$dokka.location:kotlin.io$buffered(java.io.Writer, kotlin.Int)\u001fkotlin.io/java.io.-writer/buffered.html\n$dokka.location:kotlin.io$bufferedReader(java.io.File, java.nio.charset.Charset, kotlin.Int)\u001fkotlin.io/java.io.-file/buffered-reader.html\n$dokka.location:kotlin.io$bufferedReader(java.io.InputStream, java.nio.charset.Charset)\u001fkotlin.io/java.io.-input-stream/buffered-reader.html\n$dokka.location:kotlin.io$bufferedWriter(java.io.File, java.nio.charset.Charset, kotlin.Int)\u001fkotlin.io/java.io.-file/buffered-writer.html\n$dokka.location:kotlin.io$bufferedWriter(java.io.OutputStream, java.nio.charset.Charset)\u001fkotlin.io/java.io.-output-stream/buffered-writer.html\n$dokka.location:kotlin.io$copyRecursively(java.io.File, java.io.File, kotlin.Boolean, kotlin.Function2((java.io.File, java.io.IOException, kotlin.io.OnErrorAction)))\u001fkotlin.io/java.io.-file/copy-recursively.html\n$dokka.location:kotlin.io$copyTo(java.io.File, java.io.File, kotlin.Boolean, kotlin.Int)\u001fkotlin.io/java.io.-file/copy-to.html\n$dokka.location:kotlin.io$copyTo(java.io.InputStream, java.io.OutputStream, kotlin.Int)\u001fkotlin.io/java.io.-input-stream/copy-to.html\n$dokka.location:kotlin.io$copyTo(java.io.Reader, java.io.Writer, kotlin.Int)\u001fkotlin.io/java.io.-reader/copy-to.html\n$dokka.location:kotlin.io$deleteRecursively(java.io.File)\u001fkotlin.io/java.io.-file/delete-recursively.html\n$dokka.location:kotlin.io$endsWith(java.io.File, java.io.File)\u001fkotlin.io/java.io.-file/ends-with.html\n$dokka.location:kotlin.io$endsWith(java.io.File, kotlin.String)\u001fkotlin.io/java.io.-file/ends-with.html\n$dokka.location:kotlin.io$extension#java.io.File\u001fkotlin.io/java.io.-file/extension.html\n$dokka.location:kotlin.io$forEachBlock(java.io.File, kotlin.Function2((kotlin.ByteArray, kotlin.Int, kotlin.Unit)))\u001fkotlin.io/java.io.-file/for-each-block.html\n$dokka.location:kotlin.io$forEachBlock(java.io.File, kotlin.Int, kotlin.Function2((kotlin.ByteArray, kotlin.Int, kotlin.Unit)))\u001fkotlin.io/java.io.-file/for-each-block.html\n$dokka.location:kotlin.io$forEachLine(java.io.File, java.nio.charset.Charset, kotlin.Function1((kotlin.String, kotlin.Unit)))\u001fkotlin.io/java.io.-file/for-each-line.html\n$dokka.location:kotlin.io$forEachLine(java.io.Reader, kotlin.Function1((kotlin.String, kotlin.Unit)))\u001fkotlin.io/java.io.-reader/for-each-line.html\n$dokka.location:kotlin.io$inputStream(java.io.File)\u001fkotlin.io/java.io.-file/input-stream.html\n$dokka.location:kotlin.io$invariantSeparatorsPath#java.io.File\u001fkotlin.io/java.io.-file/invariant-separators-path.html\n$dokka.location:kotlin.io$isRooted#java.io.File\u001fkotlin.io/java.io.-file/is-rooted.html\n$dokka.location:kotlin.io$iterator(java.io.BufferedInputStream)\u001fkotlin.io/java.io.-buffered-input-stream/iterator.html\n$dokka.location:kotlin.io$lineSequence(java.io.BufferedReader)\u001fkotlin.io/java.io.-buffered-reader/line-sequence.html\n$dokka.location:kotlin.io$nameWithoutExtension#java.io.File\u001fkotlin.io/java.io.-file/name-without-extension.html\n$dokka.location:kotlin.io$normalize(java.io.File)\u001fkotlin.io/java.io.-file/normalize.html\n$dokka.location:kotlin.io$outputStream(java.io.File)\u001fkotlin.io/java.io.-file/output-stream.html\n$dokka.location:kotlin.io$printWriter(java.io.File, java.nio.charset.Charset)\u001fkotlin.io/java.io.-file/print-writer.html\n$dokka.location:kotlin.io$readBytes(java.io.File)\u001fkotlin.io/java.io.-file/read-bytes.html\n$dokka.location:kotlin.io$readBytes(java.io.InputStream)\u001fkotlin.io/java.io.-input-stream/read-bytes.html\n$dokka.location:kotlin.io$readBytes(java.io.InputStream, kotlin.Int)\u001fkotlin.io/java.io.-input-stream/read-bytes.html\n$dokka.location:kotlin.io$readBytes(java.net.URL)\u001fkotlin.io/java.net.-u-r-l/read-bytes.html\n$dokka.location:kotlin.io$readLines(java.io.File, java.nio.charset.Charset)\u001fkotlin.io/java.io.-file/read-lines.html\n$dokka.location:kotlin.io$readLines(java.io.Reader)\u001fkotlin.io/java.io.-reader/read-lines.html\n$dokka.location:kotlin.io$readText(java.io.File, java.nio.charset.Charset)\u001fkotlin.io/java.io.-file/read-text.html\n$dokka.location:kotlin.io$readText(java.io.Reader)\u001fkotlin.io/java.io.-reader/read-text.html\n$dokka.location:kotlin.io$readText(java.net.URL, java.nio.charset.Charset)\u001fkotlin.io/java.net.-u-r-l/read-text.html\n$dokka.location:kotlin.io$reader(java.io.File, java.nio.charset.Charset)\u001fkotlin.io/java.io.-file/reader.html\n$dokka.location:kotlin.io$reader(java.io.InputStream, java.nio.charset.Charset)\u001fkotlin.io/java.io.-input-stream/reader.html\n$dokka.location:kotlin.io$relativeTo(java.io.File, java.io.File)\u001fkotlin.io/java.io.-file/relative-to.html\n$dokka.location:kotlin.io$relativeToOrNull(java.io.File, java.io.File)\u001fkotlin.io/java.io.-file/relative-to-or-null.html\n$dokka.location:kotlin.io$relativeToOrSelf(java.io.File, java.io.File)\u001fkotlin.io/java.io.-file/relative-to-or-self.html\n$dokka.location:kotlin.io$resolve(java.io.File, java.io.File)\u001fkotlin.io/java.io.-file/resolve.html\n$dokka.location:kotlin.io$resolve(java.io.File, kotlin.String)\u001fkotlin.io/java.io.-file/resolve.html\n$dokka.location:kotlin.io$resolveSibling(java.io.File, java.io.File)\u001fkotlin.io/java.io.-file/resolve-sibling.html\n$dokka.location:kotlin.io$resolveSibling(java.io.File, kotlin.String)\u001fkotlin.io/java.io.-file/resolve-sibling.html\n$dokka.location:kotlin.io$startsWith(java.io.File, java.io.File)\u001fkotlin.io/java.io.-file/starts-with.html\n$dokka.location:kotlin.io$startsWith(java.io.File, kotlin.String)\u001fkotlin.io/java.io.-file/starts-with.html\n$dokka.location:kotlin.io$toRelativeString(java.io.File, java.io.File)\u001fkotlin.io/java.io.-file/to-relative-string.html\n$dokka.location:kotlin.io$useLines(java.io.File, java.nio.charset.Charset, kotlin.Function1((kotlin.sequences.Sequence((kotlin.String)), kotlin.io.useLines.T)))\u001fkotlin.io/java.io.-file/use-lines.html\n$dokka.location:kotlin.io$useLines(java.io.Reader, kotlin.Function1((kotlin.sequences.Sequence((kotlin.String)), kotlin.io.useLines.T)))\u001fkotlin.io/java.io.-reader/use-lines.html\n$dokka.location:kotlin.io$walk(java.io.File, kotlin.io.FileWalkDirection)\u001fkotlin.io/java.io.-file/walk.html\n$dokka.location:kotlin.io$walkBottomUp(java.io.File)\u001fkotlin.io/java.io.-file/walk-bottom-up.html\n$dokka.location:kotlin.io$walkTopDown(java.io.File)\u001fkotlin.io/java.io.-file/walk-top-down.html\n$dokka.location:kotlin.io$writeBytes(java.io.File, kotlin.ByteArray)\u001fkotlin.io/java.io.-file/write-bytes.html\n$dokka.location:kotlin.io$writeText(java.io.File, kotlin.String, java.nio.charset.Charset)\u001fkotlin.io/java.io.-file/write-text.html\n$dokka.location:kotlin.io$writer(java.io.File, java.nio.charset.Charset)\u001fkotlin.io/java.io.-file/writer.html\n$dokka.location:kotlin.io$writer(java.io.OutputStream, java.nio.charset.Charset)\u001fkotlin.io/java.io.-output-stream/writer.html\n$dokka.location:kotlin.jvm$kotlin#java.lang.Class((kotlin.jvm.kotlin.T))\u001fkotlin.jvm/java.lang.-class/kotlin.html\n$dokka.location:kotlin.random$asKotlinRandom(java.util.Random)\u001fkotlin.random/java.util.-random/as-kotlin-random.html\n$dokka.location:kotlin.reflect.KAnnotatedElement\u001fkotlin.reflect/-k-annotated-element/index.html\n$dokka.location:kotlin.reflect.KDeclarationContainer\u001fkotlin.reflect/-k-declaration-container/index.html\n$dokka.location:kotlin.reflect.KFunction\u001fkotlin.reflect/-k-function/index.html\n$dokka.location:kotlin.reflect.KMutableProperty\u001fkotlin.reflect/-k-mutable-property/index.html\n$dokka.location:kotlin.reflect.KProperty\u001fkotlin.reflect/-k-property/index.html\n$dokka.location:kotlin.reflect.jvm$kotlinFunction#java.lang.reflect.Constructor((kotlin.reflect.jvm.kotlinFunction.T))\u001fkotlin.reflect.jvm/java.lang.reflect.-constructor/kotlin-function.html\n$dokka.location:kotlin.reflect.jvm$kotlinFunction#java.lang.reflect.Method\u001fkotlin.reflect.jvm/java.lang.reflect.-method/kotlin-function.html\n$dokka.location:kotlin.reflect.jvm$kotlinProperty#java.lang.reflect.Field\u001fkotlin.reflect.jvm/java.lang.reflect.-field/kotlin-property.html\n$dokka.location:kotlin.sequences$asSequence(java.util.Enumeration((kotlin.sequences.asSequence.T)))\u001fkotlin.sequences/java.util.-enumeration/as-sequence.html\n$dokka.location:kotlin.streams$asSequence(java.util.stream.DoubleStream)\u001fkotlin.streams/java.util.stream.-double-stream/as-sequence.html\n$dokka.location:kotlin.streams$asSequence(java.util.stream.IntStream)\u001fkotlin.streams/java.util.stream.-int-stream/as-sequence.html\n$dokka.location:kotlin.streams$asSequence(java.util.stream.LongStream)\u001fkotlin.streams/java.util.stream.-long-stream/as-sequence.html\n$dokka.location:kotlin.streams$asSequence(java.util.stream.Stream((kotlin.streams.asSequence.T)))\u001fkotlin.streams/java.util.stream.-stream/as-sequence.html\n$dokka.location:kotlin.streams$asStream(kotlin.sequences.Sequence((kotlin.streams.asStream.T)))\u001fkotlin.streams/kotlin.sequences.-sequence/as-stream.html\n$dokka.location:kotlin.streams$toList(java.util.stream.DoubleStream)\u001fkotlin.streams/java.util.stream.-double-stream/to-list.html\n$dokka.location:kotlin.streams$toList(java.util.stream.IntStream)\u001fkotlin.streams/java.util.stream.-int-stream/to-list.html\n$dokka.location:kotlin.streams$toList(java.util.stream.LongStream)\u001fkotlin.streams/java.util.stream.-long-stream/to-list.html\n$dokka.location:kotlin.streams$toList(java.util.stream.Stream((kotlin.streams.toList.T)))\u001fkotlin.streams/java.util.stream.-stream/to-list.html\n$dokka.location:kotlin.text$appendRange(java.lang.StringBuilder, kotlin.CharArray, kotlin.Int, kotlin.Int)\u001fkotlin.text/java.lang.-string-builder/append-range.html\n$dokka.location:kotlin.text$appendRange(java.lang.StringBuilder, kotlin.CharSequence, kotlin.Int, kotlin.Int)\u001fkotlin.text/java.lang.-string-builder/append-range.html\n$dokka.location:kotlin.text$appendln(java.lang.Appendable)\u001fkotlin.text/java.lang.-appendable/appendln.html\n$dokka.location:kotlin.text$appendln(java.lang.Appendable, kotlin.Char)\u001fkotlin.text/java.lang.-appendable/appendln.html\n$dokka.location:kotlin.text$appendln(java.lang.Appendable, kotlin.CharSequence)\u001fkotlin.text/java.lang.-appendable/appendln.html\n$dokka.location:kotlin.text$appendln(java.lang.StringBuilder)\u001fkotlin.text/java.lang.-string-builder/appendln.html\n$dokka.location:kotlin.text$appendln(java.lang.StringBuilder, java.lang.StringBuffer)\u001fkotlin.text/java.lang.-string-builder/appendln.html\n$dokka.location:kotlin.text$appendln(java.lang.StringBuilder, java.lang.StringBuilder)\u001fkotlin.text/java.lang.-string-builder/appendln.html\n$dokka.location:kotlin.text$appendln(java.lang.StringBuilder, kotlin.Any)\u001fkotlin.text/java.lang.-string-builder/appendln.html\n$dokka.location:kotlin.text$appendln(java.lang.StringBuilder, kotlin.Boolean)\u001fkotlin.text/java.lang.-string-builder/appendln.html\n$dokka.location:kotlin.text$appendln(java.lang.StringBuilder, kotlin.Byte)\u001fkotlin.text/java.lang.-string-builder/appendln.html\n$dokka.location:kotlin.text$appendln(java.lang.StringBuilder, kotlin.Char)\u001fkotlin.text/java.lang.-string-builder/appendln.html\n$dokka.location:kotlin.text$appendln(java.lang.StringBuilder, kotlin.CharArray)\u001fkotlin.text/java.lang.-string-builder/appendln.html\n$dokka.location:kotlin.text$appendln(java.lang.StringBuilder, kotlin.CharSequence)\u001fkotlin.text/java.lang.-string-builder/appendln.html\n$dokka.location:kotlin.text$appendln(java.lang.StringBuilder, kotlin.Double)\u001fkotlin.text/java.lang.-string-builder/appendln.html\n$dokka.location:kotlin.text$appendln(java.lang.StringBuilder, kotlin.Float)\u001fkotlin.text/java.lang.-string-builder/appendln.html\n$dokka.location:kotlin.text$appendln(java.lang.StringBuilder, kotlin.Int)\u001fkotlin.text/java.lang.-string-builder/appendln.html\n$dokka.location:kotlin.text$appendln(java.lang.StringBuilder, kotlin.Long)\u001fkotlin.text/java.lang.-string-builder/appendln.html\n$dokka.location:kotlin.text$appendln(java.lang.StringBuilder, kotlin.Short)\u001fkotlin.text/java.lang.-string-builder/appendln.html\n$dokka.location:kotlin.text$appendln(java.lang.StringBuilder, kotlin.String)\u001fkotlin.text/java.lang.-string-builder/appendln.html\n$dokka.location:kotlin.text$clear(java.lang.StringBuilder)\u001fkotlin.text/java.lang.-string-builder/clear.html\n$dokka.location:kotlin.text$deleteAt(java.lang.StringBuilder, kotlin.Int)\u001fkotlin.text/java.lang.-string-builder/delete-at.html\n$dokka.location:kotlin.text$deleteRange(java.lang.StringBuilder, kotlin.Int, kotlin.Int)\u001fkotlin.text/java.lang.-string-builder/delete-range.html\n$dokka.location:kotlin.text$insertRange(java.lang.StringBuilder, kotlin.Int, kotlin.CharArray, kotlin.Int, kotlin.Int)\u001fkotlin.text/java.lang.-string-builder/insert-range.html\n$dokka.location:kotlin.text$insertRange(java.lang.StringBuilder, kotlin.Int, kotlin.CharSequence, kotlin.Int, kotlin.Int)\u001fkotlin.text/java.lang.-string-builder/insert-range.html\n$dokka.location:kotlin.text$set(java.lang.StringBuilder, kotlin.Int, kotlin.Char)\u001fkotlin.text/java.lang.-string-builder/set.html\n$dokka.location:kotlin.text$setRange(java.lang.StringBuilder, kotlin.Int, kotlin.Int, kotlin.String)\u001fkotlin.text/java.lang.-string-builder/set-range.html\n$dokka.location:kotlin.text$toCharArray(java.lang.StringBuilder, kotlin.CharArray, kotlin.Int, kotlin.Int, kotlin.Int)\u001fkotlin.text/java.lang.-string-builder/to-char-array.html\n$dokka.location:kotlin.text$toRegex(java.util.regex.Pattern)\u001fkotlin.text/java.util.regex.-pattern/to-regex.html\n$dokka.location:kotlin.text.Appendable\u001fkotlin.text/-appendable/index.html\n$dokka.location:kotlin.text.CharacterCodingException\u001fkotlin.text/-character-coding-exception/index.html\n$dokka.location:kotlin.text.StringBuilder\u001fkotlin.text/-string-builder/index.html\n$dokka.location:kotlin.time$toKotlinDuration(java.time.Duration)\u001fkotlin.time/java.time.-duration/to-kotlin-duration.html\n$dokka.location:kotlin.time.DurationUnit\u001fkotlin.time/-duration-unit/index.html\n$dokka.location:kotlin.time.MonoClock\u001fkotlin.time/-mono-clock/index.html\nkotlin\nkotlin.annotation\nkotlin.browser\nkotlin.collections\nkotlin.comparisons\nkotlin.concurrent\nkotlin.contracts\nkotlin.coroutines\nkotlin.coroutines.experimental\nkotlin.coroutines.experimental.intrinsics\nkotlin.coroutines.intrinsics\nkotlin.dom\nkotlin.experimental\nkotlin.io\nkotlin.js\nkotlin.jvm\nkotlin.math\nkotlin.native\nkotlin.native.concurrent\nkotlin.native.ref\nkotlin.properties\nkotlin.random\nkotlin.ranges\nkotlin.reflect\nkotlin.reflect.full\nkotlin.reflect.jvm\nkotlin.sequences\nkotlin.streams\nkotlin.system\nkotlin.text\nkotlin.time\nkotlinx.cinterop\nkotlinx.cinterop.internal\nkotlinx.wasm.jsinterop\norg.khronos.webgl\norg.w3c.css.masking\norg.w3c.dom\norg.w3c.dom.clipboard\norg.w3c.dom.css\norg.w3c.dom.events\norg.w3c.dom.mediacapture\norg.w3c.dom.parsing\norg.w3c.dom.pointerevents\norg.w3c.dom.svg\norg.w3c.dom.url\norg.w3c.fetch\norg.w3c.files\norg.w3c.notifications\norg.w3c.performance\norg.w3c.workers\norg.w3c.xhr\n"
  },
  {
    "path": "realm/kotlin-extensions/proguard-rules.pro",
    "content": "# Add project specific ProGuard rules here.\n# By default, the flags in this file are appended to flags specified\n# in /usr/local/opt/android-sdk/tools/proguard/proguard-android.txt\n# You can edit the include path and order by changing the proguardFiles\n# directive in build.gradle.\n#\n# For more details, see\n#   http://developer.android.com/guide/developing/tools/proguard.html\n\n# Add any project specific keep options here:\n\n# If your project uses WebView with JS, uncomment the following\n# and specify the fully qualified class name to the JavaScript interface\n# class:\n#-keepclassmembers class fqcn.of.javascript.interface.for.webview {\n#   public *;\n#}\n\n# Uncomment this to preserve the line number information for\n# debugging stack traces.\n#-keepattributes SourceFile,LineNumberTable\n\n# If you keep the line number information, uncomment this to\n# hide the original source file name.\n#-renamesourcefileattribute SourceFile\n"
  },
  {
    "path": "realm/kotlin-extensions/src/androidTest/kotlin/io/realm/CoroutinesTests.kt",
    "content": "package io.realm\n\nimport io.realm.entities.AllTypes\nimport io.realm.entities.Dog\nimport io.realm.entities.SimpleClass\nimport io.realm.kotlin.*\nimport io.realm.rule.BlockingLooperThread\nimport kotlinx.coroutines.*\nimport kotlinx.coroutines.flow.*\nimport kotlinx.coroutines.test.TestCoroutineDispatcher\nimport kotlinx.coroutines.test.TestCoroutineScope\nimport kotlinx.coroutines.test.runBlockingTest\nimport org.junit.Before\nimport org.junit.Rule\nimport org.junit.Test\nimport java.util.concurrent.CountDownLatch\nimport java.util.concurrent.atomic.AtomicBoolean\nimport kotlin.test.*\n\n@ExperimentalCoroutinesApi\nclass CoroutinesTests {\n\n    @Suppress(\"MemberVisibilityCanPrivate\")\n    @Rule\n    @JvmField\n    val configFactory = TestRealmConfigurationFactory()\n\n    private lateinit var configuration: RealmConfiguration\n    private lateinit var testDispatcher: TestCoroutineDispatcher\n    private lateinit var testScope: TestCoroutineScope\n    private val looperThread = BlockingLooperThread()\n\n    @Before\n    fun setUp() {\n        testDispatcher = TestCoroutineDispatcher()\n        testScope = TestCoroutineScope(testDispatcher)\n        configuration = configFactory.createConfiguration()\n    }\n\n    @Test\n    fun realm_toFlow_emittedOnCollect() {\n        val countDownLatch = CountDownLatch(1)\n\n        val context = Dispatchers.Main\n        val scope = CoroutineScope(context)\n\n        scope.launch {\n            val realmInstance = Realm.getInstance(configuration)\n            realmInstance.toflow()\n                    .flowOn(context)\n                    .onEach { emittedRealm ->\n                        assertNotNull(emittedRealm)\n                        scope.cancel(\"Cancelling scope...\")\n                    }\n                    .onCompletion {\n                        realmInstance.close()\n                        countDownLatch.countDown()\n                    }\n                    .collect()\n        }\n\n        TestHelper.awaitOrFail(countDownLatch)\n    }\n\n    @Test\n    fun realm_toFlow_emittedOnUpdate() {\n        val countDownLatch = CountDownLatch(1)\n\n        val context = Dispatchers.Main\n        val scope = CoroutineScope(context)\n\n        scope.launch {\n            val realmInstance = Realm.getInstance(configuration)\n            realmInstance.toflow()\n                    .flowOn(context)\n                    .onEach { emittedRealm ->\n                        assertNotNull(emittedRealm)\n\n                        if (emittedRealm.isEmpty) {\n                            realmInstance.beginTransaction()\n                            realmInstance.createObject(AllTypes::class.java)\n                            realmInstance.commitTransaction()\n                        } else {\n                            assertTrue(emittedRealm.where<AllTypes>().count() > 0)\n                            scope.cancel(\"Cancelling scope...\")\n                        }\n                    }\n                    .onCompletion {\n                        realmInstance.close()\n                        countDownLatch.countDown()\n                    }\n                    .collect()\n        }\n\n        TestHelper.awaitOrFail(countDownLatch)\n    }\n\n    @Test\n    fun dynamicRealm_toFlow_emittedOnCollect() {\n        val countDownLatch = CountDownLatch(1)\n\n        val context = Dispatchers.Main\n        val scope = CoroutineScope(context)\n\n        scope.launch {\n            val realmInstance = DynamicRealm.getInstance(configuration)\n            realmInstance.toflow()\n                    .flowOn(context)\n                    .onEach { emittedRealm ->\n                        assertNotNull(emittedRealm)\n                        scope.cancel(\"Cancelling scope...\")\n                    }\n                    .onCompletion {\n                        realmInstance.close()\n                        countDownLatch.countDown()\n                    }\n                    .collect()\n        }\n\n        TestHelper.awaitOrFail(countDownLatch)\n    }\n\n    @Test\n    fun dynamicRealm_toFlow_emittedOnUpdate() {\n        val countDownLatch = CountDownLatch(1)\n\n        val context = Dispatchers.Main\n        val scope = CoroutineScope(context)\n\n        // Initializes schema. DynamicRealm will not do that, so let a normal Realm create the file first.\n        Realm.getInstance(configuration).close()\n\n        scope.launch {\n            val realmInstance = DynamicRealm.getInstance(configuration)\n            realmInstance.toflow()\n                    .flowOn(context)\n                    .onEach { emittedRealm ->\n                        assertNotNull(emittedRealm)\n\n                        if (emittedRealm.isEmpty) {\n                            realmInstance.beginTransaction()\n                            realmInstance.createObject(AllTypes.CLASS_NAME)\n                            realmInstance.commitTransaction()\n                        } else {\n                            assertTrue(emittedRealm.where(AllTypes.CLASS_NAME).count() > 0)\n                            scope.cancel(\"Cancelling scope...\")\n                        }\n                    }\n                    .onCompletion {\n                        realmInstance.close()\n                        countDownLatch.countDown()\n                    }\n                    .collect()\n        }\n\n        TestHelper.awaitOrFail(countDownLatch)\n    }\n\n    @Test\n    fun realmResults_toFlow_throwsOnClosed() {\n        val countDownLatch = CountDownLatch(1)\n\n        val context = Dispatchers.Main\n        val scope = CoroutineScope(context)\n\n        scope.launch {\n            val realmInstance = Realm.getInstance(configuration)\n\n            // No updates will be emitted, but at least ensure that we are not\n            // triggering coroutines internal java.lang.IllegalStateException due to missing\n            // 'awaitClose { yourCallbackOrListener.cancel() }', which should be used in the end of\n            // a callbackFlow block.\n            assertFailsWith<TimeoutCancellationException> {\n                withTimeout(100) {\n                    realmInstance.where<SimpleClass>()\n                            .findAllAsync()\n                            .toFlow()\n                            .onStart {\n                                realmInstance.close()\n                            }.onCompletion {\n                                countDownLatch.countDown()\n                            }.collect()\n                }\n            }\n        }\n\n        TestHelper.awaitOrFail(countDownLatch)\n    }\n\n    @Test\n    fun realmResults_toFlow_emittedOnCollect() {\n        val countDownLatch = CountDownLatch(1)\n\n        // TODO check this out for better testing: https://proandroiddev.com/from-rxjava-to-kotlin-flow-testing-42f1641d8433\n        val context = Dispatchers.Main\n        val scope = CoroutineScope(context)\n\n        scope.launch {\n            val realmInstance = Realm.getInstance(configuration)\n\n            realmInstance.where<SimpleClass>()\n                    .findAllAsync()\n                    .toFlow()\n                    .flowOn(context)\n                    .onEach { flowResults ->\n                        assertTrue(flowResults.isFrozen)\n                        assertEquals(0, flowResults.size)\n                        scope.cancel(\"Cancelling scope...\")\n                    }.onCompletion {\n                        realmInstance.close()\n                        countDownLatch.countDown()\n                    }.collect()\n        }\n\n        TestHelper.awaitOrFail(countDownLatch)\n    }\n\n    @Test\n    fun findAll_realmResults_toFlow_resultsEmittedAfterCollect() {\n        Realm.getInstance(configuration).use { realm ->\n            realm.executeTransaction { transactionRealm ->\n                transactionRealm.createObject<SimpleClass>().name = \"Foo\"\n                transactionRealm.createObject<SimpleClass>().name = \"Bar\"\n            }\n        }\n\n        val countDownLatch = CountDownLatch(1)\n\n        val context = Dispatchers.Main\n        val scope = CoroutineScope(context)\n\n        scope.launch {\n            val realmInstance = Realm.getInstance(configuration)\n            realmInstance.where<SimpleClass>()\n                    .findAllAsync()\n                    .toFlow()\n                    .flowOn(context)\n                    .onEach { flowResults ->\n                        assertTrue(flowResults.isFrozen)\n                        if (flowResults.size == 2) {\n                            scope.cancel(\"Cancelling scope...\")\n                        }\n                    }.onCompletion {\n                        realmInstance.close()\n                        countDownLatch.countDown()\n                    }.collect()\n        }\n\n        TestHelper.awaitOrFail(countDownLatch)\n    }\n\n    @Test\n    fun realmObject_findFirst_toFlow_onlyValidObjectsAreEmitted() {\n        Realm.getInstance(configuration).use { realm ->\n            realm.executeTransaction { transactionRealm ->\n                transactionRealm.createObject<SimpleClass>().name = \"Foo\"\n                transactionRealm.createObject<SimpleClass>().name = \"Bar\"\n            }\n        }\n\n        val countDownLatch = CountDownLatch(1)\n\n        val context = Dispatchers.Main\n        val scope = CoroutineScope(context)\n\n        scope.launch {\n            val realmInstance = Realm.getInstance(configuration)\n            realmInstance.where<SimpleClass>()\n                    .findFirstAsync()\n                    .toFlow()\n                    .flowOn(context)\n                    .onEach { flowObject ->\n                        assertNotNull(flowObject)\n                        assertTrue(flowObject.isFrozen())\n                        assertTrue(flowObject.isValid())\n                        assertEquals(\"Foo\", flowObject.name)\n                        scope.cancel(\"Cancelling scope...\")\n                    }.onCompletion {\n                        realmInstance.close()\n                        countDownLatch.countDown()\n                    }.collect()\n        }\n\n        TestHelper.awaitOrFail(countDownLatch)\n    }\n\n    @Test\n    fun realmResults_toChangesetFlow_emittedAfterCollect() {\n        Realm.getInstance(configuration).use { realm ->\n            realm.executeTransaction { transactionRealm ->\n                transactionRealm.createObject<SimpleClass>().name = \"Foo\"\n            }\n        }\n\n        val countDownLatch = CountDownLatch(1)\n\n        val context = Dispatchers.Main\n        val scope = CoroutineScope(context)\n\n        scope.launch {\n            val realmInstance = Realm.getInstance(configuration)\n            realmInstance.where<SimpleClass>()\n                    .findAllAsync()\n                    .toChangesetFlow()\n                    .flowOn(context)\n                    .onEach { collectionChange ->\n                        assertTrue(collectionChange.collection.isFrozen)\n\n                        if (collectionChange.collection.size == 0) {\n                            assertNull(collectionChange.changeset)\n                        } else {\n                            assertNotNull(collectionChange.changeset)\n                            assertEquals(1, collectionChange.collection.size)\n                            assertEquals(\"Foo\", collectionChange.collection.first()!!.name)\n                            scope.cancel(\"Cancelling scope...\")\n                        }\n                    }.onCompletion {\n                        realmInstance.close()\n                        countDownLatch.countDown()\n                    }.collect()\n        }\n\n        TestHelper.awaitOrFail(countDownLatch)\n    }\n\n    @Test\n    fun realmResults_dynamicRealm_toChangesetFlow_emittedAfterCollect() {\n        Realm.getInstance(configuration).use { realm ->\n            realm.executeTransaction { transactionRealm ->\n                transactionRealm.createObject<SimpleClass>().name = \"Foo\"\n            }\n        }\n\n        val countDownLatch = CountDownLatch(1)\n\n        val context = Dispatchers.Main\n        val scope = CoroutineScope(context)\n\n        scope.launch {\n            val realmInstance = DynamicRealm.getInstance(configuration)\n            realmInstance.where(\"SimpleClass\")\n                    .findAllAsync()\n                    .toChangesetFlow()\n                    .flowOn(context)\n                    .onEach { collectionChange ->\n                        assertTrue(collectionChange.collection.isFrozen)\n\n                        if (collectionChange.collection.size == 0) {\n                            assertNull(collectionChange.changeset)\n                        } else {\n                            assertNotNull(collectionChange.changeset)\n                            assertEquals(1, collectionChange.collection.size)\n                            assertEquals(\"Foo\", collectionChange.collection.first()!!.getString(\"name\"))\n                            scope.cancel(\"Cancelling scope...\")\n                        }\n                    }.onCompletion {\n                        realmInstance.close()\n                        countDownLatch.countDown()\n                    }.collect()\n        }\n\n        TestHelper.awaitOrFail(countDownLatch)\n    }\n\n    @Test\n    fun realmResults_toFlow_resultsCancelBeforeCollectActualResults() {\n        val countDownLatch = CountDownLatch(1)\n\n        val context = Dispatchers.Main\n        val scope = CoroutineScope(context)\n\n        scope.launch {\n            val realmInstance = Realm.getInstance(configuration)\n            realmInstance.where<SimpleClass>()\n                    .findAllAsync()\n                    .toFlow()\n                    .flowOn(context)\n                    .onCompletion {\n                        realmInstance.close()\n                        countDownLatch.countDown()\n                    }.launchIn(scope)\n\n            // Simulate asynchronous event and then cancel\n            delay(100)\n            scope.cancel(\"Cancelling\")\n        }\n\n        TestHelper.awaitOrFail(countDownLatch)\n    }\n\n    @Test\n    fun realmResults_toFlow_throwsDueToThreadViolation() {\n        Realm.getInstance(configuration).use { realm ->\n            val countDownLatch = CountDownLatch(1)\n\n            // Get results from the test thread\n            val findAll = realm.where<SimpleClass>().findAll()\n\n            CoroutineScope(Dispatchers.Main).launch {\n                assertFailsWith<IllegalStateException> {\n                    // Now we are on the main thread, which means crash\n                    findAll.toFlow().collect()\n                    fail(\"toFlow() must be called from the thread that retrieved the results!\")\n                }\n                countDownLatch.countDown()\n            }\n            TestHelper.awaitOrFail(countDownLatch)\n        }\n    }\n\n    @Test\n    fun realmResults_toFlow_multipleSubscribers() {\n        val countDownLatch = CountDownLatch(2)\n\n        val context = Dispatchers.Main\n        val scope = CoroutineScope(context)\n\n        var flow: Flow<RealmResults<SimpleClass>>?\n\n        scope.launch {\n            val realmInstance = Realm.getInstance(configuration)\n\n            flow = realmInstance.where<SimpleClass>()\n                    .findAllAsync()\n                    .toFlow()\n\n            // Subscriber 1\n            flow!!.flowOn(context)\n                    .onEach { flowResults ->\n                        assertTrue(flowResults.isFrozen)\n                        assertEquals(0, flowResults.size)\n                    }.onCompletion {\n                        if (countDownLatch.count > 1) {\n                            countDownLatch.countDown()\n                        } else {\n                            realmInstance.close()\n                            countDownLatch.countDown()\n                        }\n                    }.launchIn(scope)\n\n            // Subscriber 2\n            flow!!.flowOn(context)\n                    .onEach { flowResults ->\n                        assertTrue(flowResults.isFrozen)\n                        assertEquals(0, flowResults.size)\n                    }.onCompletion {\n                        if (countDownLatch.count > 1) {\n                            countDownLatch.countDown()\n                        } else {\n                            realmInstance.close()\n                            countDownLatch.countDown()\n                        }\n                    }.launchIn(scope)\n\n            // Simulate asynchronous event and then cancel\n            delay(100)\n            scope.cancel(\"Cancelling\")\n        }\n\n        TestHelper.awaitOrFail(countDownLatch)\n    }\n\n    @Test\n    fun dynamicRealm_realmResults_toFlow_emittedOnCollect() {\n        val countDownLatch = CountDownLatch(1)\n\n        val context = Dispatchers.Main\n        val scope = CoroutineScope(context)\n\n        // Initializes schema. DynamicRealm will not do that, so let a normal Realm create the file first.\n        Realm.getInstance(configuration).close()\n\n        scope.launch {\n            val realmInstance = DynamicRealm.getInstance(configuration)\n\n            realmInstance.where(\"SimpleClass\")\n                    .findAllAsync()\n                    .toFlow()\n                    .flowOn(context)\n                    .onEach { flowResults ->\n                        assertTrue(flowResults.isFrozen)\n                        assertEquals(0, flowResults.size)\n                        scope.cancel(\"Cancelling scope...\")\n                    }.onCompletion {\n                        realmInstance.close()\n                        countDownLatch.countDown()\n                    }.collect()\n        }\n\n        TestHelper.awaitOrFail(countDownLatch)\n    }\n\n    @Test\n    fun dynamicRealm_realmResults_toFlow_resultsEmittedAfterCollect() {\n        Realm.getInstance(configuration).use { realm ->\n            realm.executeTransaction { transactionRealm ->\n                transactionRealm.createObject<SimpleClass>().name = \"Foo\"\n                transactionRealm.createObject<SimpleClass>().name = \"Bar\"\n            }\n        }\n\n        val countDownLatch = CountDownLatch(1)\n\n        val context = Dispatchers.Main\n        val scope = CoroutineScope(context)\n\n        scope.launch {\n            val realmInstance = DynamicRealm.getInstance(configuration)\n            realmInstance.where(\"SimpleClass\")\n                    .findAllAsync()\n                    .toFlow()\n                    .flowOn(context)\n                    .onEach { flowResults ->\n                        assertTrue(flowResults.isFrozen)\n                        if (flowResults.size == 2) {\n                            scope.cancel(\"Cancelling scope...\")\n                        }\n                    }.onCompletion {\n                        realmInstance.close()\n                        countDownLatch.countDown()\n                    }.collect()\n        }\n\n        TestHelper.awaitOrFail(countDownLatch)\n    }\n\n    @Test\n    fun realmObject_toFlow_emitObjectOnCollect() {\n        val countDownLatch = CountDownLatch(1)\n\n        val context = Dispatchers.Main\n        val scope = CoroutineScope(context)\n\n        scope.launch {\n            val realmInstance = Realm.getInstance(configuration)\n            realmInstance.beginTransaction()\n            val obj = realmInstance.createObject<SimpleClass>()\n                    .apply { name = \"Foo\" }\n            realmInstance.commitTransaction()\n\n            obj.toFlow()\n                    .flowOn(context)\n                    .onEach { flowObject ->\n                        assertTrue(flowObject!!.isFrozen())\n                        if (flowObject.name == \"Foo\") {\n                            scope.cancel(\"Cancelling scope...\")\n                        }\n                    }.onCompletion {\n                        realmInstance.close()\n                        countDownLatch.countDown()\n                    }.launchIn(scope)\n        }\n\n        TestHelper.awaitOrFail(countDownLatch)\n    }\n\n    @Test\n    fun realmObject_toFlow_emitObjectOnObjectUpdates() {\n        val countDownLatch = CountDownLatch(1)\n\n        val context = Dispatchers.Main\n        val scope = CoroutineScope(context)\n\n        scope.launch {\n            val realmInstance = Realm.getInstance(configuration)\n            realmInstance.beginTransaction()\n            val obj = realmInstance.createObject<SimpleClass>()\n                    .apply { name = \"Foo\" }\n            realmInstance.commitTransaction()\n\n            obj.toFlow()\n                    .flowOn(context)\n                    .onEach { flowObject ->\n                        assertTrue(flowObject!!.isFrozen())\n\n                        if (flowObject.name == \"Foo\") {\n                            realmInstance.beginTransaction()\n                            obj.name = \"Bar\"\n                            realmInstance.commitTransaction()\n                        } else {\n                            assertEquals(\"Bar\", flowObject.name)\n                            scope.cancel(\"Cancelling scope...\")\n                        }\n                    }.onCompletion {\n                        realmInstance.close()\n                        countDownLatch.countDown()\n                    }.launchIn(scope)\n        }\n\n        TestHelper.awaitOrFail(countDownLatch)\n    }\n\n    @Test\n    fun realmObject_toChangesetFlow_emitObjectOnObjectUpdates() {\n        val countDownLatch = CountDownLatch(1)\n\n        val context = Dispatchers.Main\n        val scope = CoroutineScope(context)\n\n        scope.launch {\n            val realmInstance = Realm.getInstance(configuration)\n            realmInstance.beginTransaction()\n            val obj = realmInstance.createObject<SimpleClass>()\n                    .apply { name = \"Foo\" }\n            realmInstance.commitTransaction()\n\n            obj.toChangesetFlow()\n                    .flowOn(context)\n                    .onEach { objectChange ->\n                        assertNotNull(objectChange)\n                        assertTrue(objectChange.`object`.isFrozen())\n\n                        if (objectChange.`object`.name == \"Foo\") {\n                            realmInstance.beginTransaction()\n                            obj.name = \"Bar\"\n                            realmInstance.commitTransaction()\n                        } else {\n                            assertEquals(\"Bar\", objectChange.`object`.name)\n                            scope.cancel(\"Cancelling scope...\")\n                        }\n                    }.onCompletion {\n                        realmInstance.close()\n                        countDownLatch.countDown()\n                    }.launchIn(scope)\n        }\n\n        TestHelper.awaitOrFail(countDownLatch)\n    }\n\n    @Test\n    fun realmObject_toFlow_nullObjectEmitsNullFlow() {\n        val countDownLatch = CountDownLatch(1)\n\n        val context = Dispatchers.Main\n        val scope = CoroutineScope(context)\n\n        scope.launch {\n            val realmInstance = Realm.getInstance(configuration)\n            val obj = realmInstance.where<SimpleClass>().findFirst()\n\n            obj.toFlow()\n                    .flowOn(context)\n                    .onEach {\n                        assertNull(it)\n                    }.onCompletion {\n                        realmInstance.close()\n                        countDownLatch.countDown()\n                    }.launchIn(scope)\n        }\n\n        TestHelper.awaitOrFail(countDownLatch)\n    }\n\n    @Test\n    fun realmList_toFlow_emitListOnCollect() {\n        val countDownLatch = CountDownLatch(1)\n\n        val context = Dispatchers.Main\n        val scope = CoroutineScope(context)\n\n        scope.launch {\n            val realmInstance = Realm.getInstance(configuration)\n\n            realmInstance.beginTransaction()\n            val list = realmInstance.createObject<AllTypes>().columnRealmList\n            list.add(Dog(\"dog\"))\n            realmInstance.commitTransaction()\n\n            list.toFlow()\n                    .onEach { flowList ->\n                        assertTrue(flowList.isFrozen)\n                        assertEquals(1, flowList.size)\n                        assertEquals(\"dog\", flowList.first()!!.name)\n                        scope.cancel(\"Cancelling scope...\")\n                    }.onCompletion {\n                        realmInstance.close()\n                        countDownLatch.countDown()\n                    }.collect()\n        }\n\n        TestHelper.awaitOrFail(countDownLatch)\n    }\n\n    @Test\n    fun realmList_dynamicRealm_toFlow_emitListOnCollect() {\n        val countDownLatch = CountDownLatch(1)\n\n        val context = Dispatchers.Main\n        val scope = CoroutineScope(context)\n\n        // Initializes schema. DynamicRealm will not do that, so let a normal Realm create the file first.\n        Realm.getInstance(configuration).close()\n\n        scope.launch {\n            Realm.getInstance(configuration).use { realmInstance ->\n                realmInstance.beginTransaction()\n                realmInstance.createObject<AllTypes>()\n                        .columnRealmList\n                        .apply { add(Dog(\"dog\")) }\n                realmInstance.commitTransaction()\n            }\n\n            val dynamicRealmInstance = DynamicRealm.getInstance(configuration)\n            val list = dynamicRealmInstance.where(AllTypes.CLASS_NAME)\n                    .findFirst()!!\n                    .getList(AllTypes.FIELD_REALMLIST)\n                    .freeze()\n\n            list.toFlow()\n                    .onEach { flowList ->\n                        assertTrue(flowList.isFrozen)\n                        assertEquals(1, flowList.size)\n                        assertEquals(\"dog\", flowList.first()!!.getString(Dog.FIELD_NAME))\n                        scope.cancel(\"Cancelling scope...\")\n                    }.onCompletion {\n                        dynamicRealmInstance.close()\n                        countDownLatch.countDown()\n                    }.collect()\n        }\n\n        TestHelper.awaitOrFail(countDownLatch)\n    }\n\n    @Test\n    fun realmList_toFlow_emitListOnListUpdates() {\n        val countDownLatch = CountDownLatch(1)\n\n        val context = Dispatchers.Main\n        val scope = CoroutineScope(context)\n\n        scope.launch {\n            val realmInstance = Realm.getInstance(configuration)\n\n            realmInstance.beginTransaction()\n            val list = realmInstance.createObject<AllTypes>().columnRealmList\n            list.add(Dog(\"dog\"))\n            realmInstance.commitTransaction()\n\n            list.toFlow()\n                    .onEach { flowList ->\n                        assertTrue(flowList.isFrozen)\n                        assertEquals(1, flowList.size)\n\n                        val dogName = flowList.first()!!.name\n                        if (dogName != \"doggo\") {\n                            // Before update we have original name\n                            assertEquals(\"dog\", flowList.first()!!.name)\n\n                            // Now update object\n                            realmInstance.beginTransaction()\n                            list.first()?.apply {\n                                this.name = \"doggo\"\n                            }\n                            realmInstance.commitTransaction()\n                        } else {\n                            assertEquals(\"doggo\", dogName)\n\n                            // Name has been updated, close everything\n                            scope.cancel(\"Cancelling scope...\")\n                        }\n                    }.onCompletion {\n                        realmInstance.close()\n                        countDownLatch.countDown()\n                    }.launchIn(scope)\n        }\n\n        TestHelper.awaitOrFail(countDownLatch)\n    }\n\n    @Test\n    fun realmList_toChangesetFlow_emitListOnListUpdates() {\n        val countDownLatch = CountDownLatch(1)\n\n        val context = Dispatchers.Main\n        val scope = CoroutineScope(context)\n\n        scope.launch {\n            val realmInstance = Realm.getInstance(configuration)\n\n            realmInstance.beginTransaction()\n            val list = realmInstance.createObject<AllTypes>().columnRealmList\n            list.add(Dog(\"dog\"))\n            realmInstance.commitTransaction()\n\n            list.toChangesetFlow()\n                    .onEach { collectionChange ->\n                        assertTrue(collectionChange.collection.isFrozen)\n                        assertEquals(1, collectionChange.collection.size)\n\n                        val listDog = collectionChange.collection.first()!!\n                        val dogName = listDog.name\n                        if (dogName != \"doggo\") {\n                            assertNull(collectionChange.changeset)\n\n                            // Before update we have the original name\n                            assertEquals(\"dog\", dogName)\n\n                            // Now update object\n                            realmInstance.beginTransaction()\n                            list.first()?.apply {\n                                this.name = \"doggo\"\n                            }\n                            realmInstance.commitTransaction()\n                        } else {\n                            assertNotNull(collectionChange.changeset)\n                            assertEquals(\"doggo\", dogName)\n\n                            // Name has been updated, close everything\n                            scope.cancel(\"Cancelling scope...\")\n                        }\n                    }.onCompletion {\n                        realmInstance.close()\n                        countDownLatch.countDown()\n                    }.launchIn(scope)\n        }\n\n        TestHelper.awaitOrFail(countDownLatch)\n    }\n\n    @Test\n    fun realmList_dynamicRealm_toFlow_emitListOnListUpdates() {\n        val countDownLatch = CountDownLatch(1)\n\n        val context = Dispatchers.Main\n        val scope = CoroutineScope(context)\n\n        // Initializes schema. DynamicRealm will not do that, so let a normal Realm create the file first.\n        Realm.getInstance(configuration).close()\n\n        scope.launch {\n            val realmInstance = DynamicRealm.getInstance(configuration)\n\n            realmInstance.beginTransaction()\n            val dynamicRealmObject = realmInstance.createObject(AllTypes.CLASS_NAME)\n            val dog = realmInstance.createObject(\"Dog\")\n                    .apply { setString(Dog.FIELD_NAME, \"dog\") }\n            val list = dynamicRealmObject.getList(AllTypes.FIELD_REALMLIST)\n                    .apply { add(dog) }\n            realmInstance.commitTransaction()\n\n            list.toFlow()\n                    .onEach { flowList ->\n                        assertTrue(flowList.isFrozen)\n                        assertEquals(1, flowList.size)\n\n                        val flowDog = flowList.first()!!\n                        val dogName = flowDog.getString(Dog.FIELD_NAME)\n                        if (dogName != \"doggo\") {\n                            // Before update we have original name\n                            assertEquals(\"dog\", dogName)\n\n                            // Now update object\n                            realmInstance.beginTransaction()\n                            list.first()!!.apply {\n                                this.setString(Dog.FIELD_NAME, \"doggo\")\n                            }\n                            realmInstance.commitTransaction()\n                        } else {\n                            assertEquals(\"doggo\", dogName)\n\n                            // Name has been updated, close everything\n                            scope.cancel(\"Cancelling scope...\")\n                        }\n                    }.onCompletion {\n                        realmInstance.close()\n                        countDownLatch.countDown()\n                    }.launchIn(scope)\n        }\n\n        TestHelper.awaitOrFail(countDownLatch)\n    }\n\n    @Test\n    fun realmList_dynamicRealm_toChangesetFlow_emitListOnListUpdates() {\n        val countDownLatch = CountDownLatch(1)\n\n        val context = Dispatchers.Main\n        val scope = CoroutineScope(context)\n\n        // Initializes schema. DynamicRealm will not do that, so let a normal Realm create the file first.\n        Realm.getInstance(configuration).close()\n\n        scope.launch {\n            val realmInstance = DynamicRealm.getInstance(configuration)\n\n            realmInstance.beginTransaction()\n            val dynamicRealmObject = realmInstance.createObject(AllTypes.CLASS_NAME)\n            val dog = realmInstance.createObject(\"Dog\")\n                    .apply { setString(Dog.FIELD_NAME, \"dog\") }\n            val list = dynamicRealmObject.getList(AllTypes.FIELD_REALMLIST)\n                    .apply { add(dog) }\n            realmInstance.commitTransaction()\n\n            list.toChangesetFlow()\n                    .onEach { collectionChange ->\n                        assertTrue(collectionChange.collection.isFrozen)\n                        assertEquals(1, collectionChange.collection.size)\n\n                        val listDog = collectionChange.collection.first()!!\n                        val dogName = listDog.getString(Dog.FIELD_NAME)\n                        if (dogName != \"doggo\") {\n                            assertNull(collectionChange.changeset)\n\n                            // Before update we have the original name\n                            assertEquals(\"dog\", dogName)\n\n                            // Now update object\n                            realmInstance.beginTransaction()\n                            list.first()?.apply {\n                                this.setString(Dog.FIELD_NAME, \"doggo\")\n                            }\n                            realmInstance.commitTransaction()\n                        } else {\n                            assertNotNull(collectionChange.changeset)\n                            assertEquals(\"doggo\", dogName)\n\n                            // Name has been updated, close everything\n                            scope.cancel(\"Cancelling scope...\")\n                        }\n                    }.onCompletion {\n                        realmInstance.close()\n                        countDownLatch.countDown()\n                    }.launchIn(scope)\n        }\n\n        TestHelper.awaitOrFail(countDownLatch)\n    }\n\n    @Test\n    fun realmList_flow_parentDeletionComplete() = looperThread.runBlocking {\n        val realm = Realm.getInstance(configuration)\n        realm.beginTransaction()\n        val parent = realm.createObject<AllTypes>()\n        val list = parent.columnRealmList\n        list.add(Dog(\"dog\"))\n        realm.commitTransaction()\n\n        val collectingStarted = AtomicBoolean(false)\n        val context = looperThread.asDispatcher()\n        val scope = CoroutineScope(context)\n        scope.launch {\n            // We should only emit valid lists. If the parent of the list is invalidated\n            // it should close the stream gracefully resulting in onComplete being called.\n            list.toFlow()\n                    .onEach { assertTrue(it.isValid) }\n                    .onCompletion {\n                        realm.close()\n                        looperThread.testComplete()\n                    }.collect {\n                        collectingStarted.set(true)\n                    }\n        }\n\n        // Delete object holding list after stream started\n        looperThread.postRunnable(object: Runnable {\n            override fun run() {\n                // The Coroutine might not start straight away, so busy wait for it to happen.\n                if (!collectingStarted.get()) {\n                    looperThread.postRunnable(this)\n                } else {\n                    realm.executeTransaction { parent.deleteFromRealm() }\n                }\n            }\n        })\n    }\n\n    @Test\n    fun realmList_changeSetFlow_parentDeletionComplete() = looperThread.runBlocking {\n        val realm = Realm.getInstance(configuration)\n        realm.beginTransaction()\n        val parent = realm.createObject<AllTypes>()\n        val list = parent.columnRealmList\n        list.add(Dog(\"dog\"))\n        realm.commitTransaction()\n\n        val collectingStarted = AtomicBoolean(false)\n        val context = looperThread.asDispatcher()\n        val scope = CoroutineScope(context)\n        scope.launch {\n            // We should only emit valid lists. If the parent of the list is invalidated\n            // it should close the stream gracefully resulting in onComplete being called.\n            list.toChangesetFlow()\n                    .onEach { assertTrue(it.collection.isValid) }\n                    .onCompletion {\n                        realm.close()\n                        looperThread.testComplete()\n                    }.collect {\n                        collectingStarted.set(true)\n                    }\n        }\n\n        // Delete object holding list after stream started\n        looperThread.postRunnable(object: Runnable {\n            override fun run() {\n                // The Coroutine might not start straight away, so busy wait for it to happen.\n                if (!collectingStarted.get()) {\n                    looperThread.postRunnable(this)\n                } else {\n                    realm.executeTransaction { parent.deleteFromRealm() }\n                }\n            }\n        })\n    }\n\n    @Test\n    fun dynamicRealmList_flow_parentDeletionComplete() = looperThread.runBlocking {\n        Realm.getInstance(configuration).close() // Create schema\n        val realm = DynamicRealm.getInstance(configuration)\n        realm.beginTransaction()\n        val parent = realm.createObject(AllTypes.CLASS_NAME)\n        val list = parent.getList(AllTypes.FIELD_REALMLIST)\n        list.add(realm.createObject(Dog.CLASS_NAME))\n        realm.commitTransaction()\n\n        val collectingStarted = AtomicBoolean(false)\n        val context = looperThread.asDispatcher()\n        val scope = CoroutineScope(context)\n        scope.launch {\n            // We should only emit valid lists. If the parent of the list is invalidated\n            // it should close the stream gracefully resulting in onComplete being called.\n            list.toFlow()\n                    .onEach { assertTrue(it.isValid) }\n                    .onCompletion {\n                        realm.close()\n                        looperThread.testComplete()\n                    }.collect {\n                        collectingStarted.set(true)\n                    }\n        }\n\n        // Delete object holding list after stream started\n        looperThread.postRunnable(object: Runnable {\n            override fun run() {\n                // The Coroutine might not start straight away, so busy wait for it to happen.\n                if (!collectingStarted.get()) {\n                    looperThread.postRunnable(this)\n                } else {\n                    realm.executeTransaction { parent.deleteFromRealm() }\n                }\n            }\n        })\n    }\n\n    @Test\n    fun dynamicRealmList_changeSetFlow_parentDeletionComplete() = looperThread.runBlocking {\n        Realm.getInstance(configuration).close() // Create schema\n        val realm = DynamicRealm.getInstance(configuration)\n        realm.beginTransaction()\n        val parent = realm.createObject(AllTypes.CLASS_NAME)\n        val list = parent.getList(AllTypes.FIELD_REALMLIST)\n        list.add(realm.createObject(Dog.CLASS_NAME))\n        realm.commitTransaction()\n\n        val collectingStarted = AtomicBoolean(false)\n        val context = looperThread.asDispatcher()\n        val scope = CoroutineScope(context)\n        scope.launch {\n            // We should only emit valid lists. If the parent of the list is invalidated\n            // it should close the stream gracefully resulting in onComplete being called.\n            list.toChangesetFlow()\n                    .onEach { assertTrue(it.collection.isValid) }\n                    .onCompletion {\n                        realm.close()\n                        looperThread.testComplete()\n                    }.collect {\n                        collectingStarted.set(true)\n                    }\n        }\n\n        // Delete object holding list after stream started\n        looperThread.postRunnable(object: Runnable {\n            override fun run() {\n                // The Coroutine might not start straight away, so busy wait for it to happen.\n                if (!collectingStarted.get()) {\n                    looperThread.postRunnable(this)\n                } else {\n                    realm.executeTransaction { parent.deleteFromRealm() }\n                }\n            }\n        })\n    }\n\n    @Test\n    fun realmObject_toFlow_emitsOnCollect() {\n        val countDownLatch = CountDownLatch(1)\n\n        val context = Dispatchers.Main\n        val scope = CoroutineScope(context)\n\n        scope.launch {\n            val realmInstance = Realm.getInstance(configuration)\n            realmInstance.beginTransaction()\n            val obj = realmInstance.createObject<SimpleClass>()\n                    .apply { name = \"Foo\" }\n            realmInstance.commitTransaction()\n\n            obj.toFlow()\n                    .flowOn(context)\n                    .onEach { flowObject ->\n                        assertTrue(flowObject!!.isFrozen())\n                        if (flowObject.name == \"Foo\") {\n                            scope.cancel(\"Cancelling scope...\")\n                        }\n                    }.onCompletion {\n                        realmInstance.close()\n                        countDownLatch.countDown()\n                    }.collect()\n        }\n\n        TestHelper.awaitOrFail(countDownLatch)\n    }\n\n    @Test\n    fun dynamicRealmObject_toFlow_emitsOnCollect() {\n        val countDownLatch = CountDownLatch(1)\n\n        val context = Dispatchers.Main\n        val scope = CoroutineScope(context)\n\n        scope.launch {\n            Realm.getInstance(configuration).use { realmInstance ->\n                realmInstance.executeTransaction {\n                    realmInstance.createObject<AllTypes>()\n                }\n            }\n\n            val dynamicRealm = DynamicRealm.getInstance(configuration)\n            dynamicRealm.where(AllTypes.CLASS_NAME)\n                    .findFirst()!!\n                    .toFlow()\n                    .flowOn(context)\n                    .onEach { flowObject ->\n                        assertTrue(flowObject!!.isFrozen)\n                        scope.cancel(\"Cancelling scope...\")\n                    }.onCompletion {\n                        dynamicRealm.close()\n                        countDownLatch.countDown()\n                    }.collect()\n        }\n\n        TestHelper.awaitOrFail(countDownLatch)\n    }\n\n    @Test\n    fun dynamicRealmObject_toFlow_emitsOnUpdate() {\n        val countDownLatch = CountDownLatch(1)\n\n        val context = Dispatchers.Main\n        val scope = CoroutineScope(context)\n\n        // Initializes schema. DynamicRealm will not do that, so let a normal Realm create the file first.\n        Realm.getInstance(configuration).close()\n\n        scope.launch {\n            val realmInstance = DynamicRealm.getInstance(configuration)\n            realmInstance.beginTransaction()\n            val simpleObject = realmInstance.createObject(\"SimpleClass\")\n                    .apply { setString(\"name\", \"simpleName\") }\n            realmInstance.commitTransaction()\n\n            val dynamicRealm = DynamicRealm.getInstance(configuration)\n            dynamicRealm.where(\"SimpleClass\")\n                    .findFirst()\n                    .toFlow()\n                    .flowOn(context)\n                    .onEach { flowObject ->\n                        assertNotNull(flowObject)\n                        assertTrue(flowObject.isFrozen)\n\n                        val name = flowObject.getString(\"name\")\n                        if (name == \"simpleName\") {\n                            realmInstance.beginTransaction()\n                            simpleObject.setString(\"name\", \"advancedName\")\n                            realmInstance.commitTransaction()\n                        } else {\n                            assertEquals(\"advancedName\", name)\n                            scope.cancel(\"Cancelling scope...\")\n                        }\n                    }.onCompletion {\n                        realmInstance.close()\n                        dynamicRealm.close()\n                        countDownLatch.countDown()\n                    }.collect()\n        }\n\n        TestHelper.awaitOrFail(countDownLatch)\n    }\n\n    @Test\n    fun dynamicRealmObject_toChangesetFlow_emitsOnUpdate() {\n        val countDownLatch = CountDownLatch(1)\n\n        val context = Dispatchers.Main\n        val scope = CoroutineScope(context)\n\n        // Initializes schema. DynamicRealm will not do that, so let a normal Realm create the file first.\n        Realm.getInstance(configuration).close()\n\n        scope.launch {\n            val realmInstance = DynamicRealm.getInstance(configuration)\n            realmInstance.beginTransaction()\n            val simpleObject = realmInstance.createObject(\"SimpleClass\")\n                    .apply { setString(\"name\", \"simpleName\") }\n            realmInstance.commitTransaction()\n\n            val dynamicRealm = DynamicRealm.getInstance(configuration)\n            dynamicRealm.where(\"SimpleClass\")\n                    .findFirst()\n                    .toChangesetFlow()\n                    .flowOn(context)\n                    .onEach { objectChange ->\n                        assertNotNull(objectChange)\n                        assertNotNull(objectChange.`object`)\n                        assertTrue(objectChange.`object`.isFrozen)\n\n                        val name = objectChange.`object`.getString(\"name\")\n                        if (name == \"simpleName\") {\n                            assertNull(objectChange.changeset)\n                            realmInstance.beginTransaction()\n                            simpleObject.setString(\"name\", \"advancedName\")\n                            realmInstance.commitTransaction()\n                        } else {\n                            assertNotNull(objectChange.changeset)\n                            assertEquals(\"advancedName\", name)\n                            scope.cancel(\"Cancelling scope...\")\n                        }\n                    }.onCompletion {\n                        realmInstance.close()\n                        dynamicRealm.close()\n                        countDownLatch.countDown()\n                    }.collect()\n        }\n\n        TestHelper.awaitOrFail(countDownLatch)\n    }\n\n    @Test\n    fun executeTransactionAwait() {\n        testScope.runBlockingTest {\n            Realm.getInstance(configuration).use { realmInstance ->\n                assertEquals(0, realmInstance.where<SimpleClass>().findAll().size)\n\n                realmInstance.executeTransactionAwait(testDispatcher) { transactionRealm ->\n                    val simpleObject = SimpleClass().apply { name = \"simpleName\" }\n                    transactionRealm.insert(simpleObject)\n                }\n                assertEquals(1, realmInstance.where<SimpleClass>().findAll().size)\n            }\n        }\n    }\n\n    @Test\n    fun executeTransactionAwait_cancelCoroutineWithMultipleTransactions() {\n        val upperBound = 10\n        var realmInstance: Realm? = null\n\n        val job = CoroutineScope(Dispatchers.Main).launch {\n            realmInstance = Realm.getInstance(configuration)\n\n            for (i in 1..upperBound) {\n                realmInstance!!.executeTransactionAwait { transactionRealm ->\n                    val simpleObject = SimpleClass().apply { name = \"simpleName $i\" }\n                    transactionRealm.insert(simpleObject)\n                }\n\n                // Wait for 10 ms between inserts\n                delay(10)\n            }\n        }\n\n        val countDownLatch = CountDownLatch(1)\n        CoroutineScope(Dispatchers.Main).launch {\n            // Wait for 50 ms and cancel job so that not all planned 10 elements are inserted\n            delay(50)\n            job.cancelAndJoin()\n\n            assertNotEquals(upperBound.toLong(), realmInstance!!.where<SimpleClass>().count())\n\n            realmInstance!!.close()\n\n            countDownLatch.countDown()\n            this.cancel()\n        }\n\n        TestHelper.awaitOrFail(countDownLatch)\n    }\n\n    @Test\n    fun executeTransactionAwait_cancelCoroutineWithHeavyCooperativeTransaction() {\n        val upperBound = 100000\n        var realmInstance: Realm? = null\n\n        val job = CoroutineScope(Dispatchers.Main).launch {\n            realmInstance = Realm.getInstance(configuration)\n\n            realmInstance!!.executeTransactionAwait { transactionRealm ->\n                // Try to insert 100000 objects to give time to be cancelled after 5ms\n                for (i in 1..upperBound) {\n                    // The coroutine itself will not cancel the transaction, but we can make it cooperative ourselves\n                    if (isActive) {\n                        val simpleObject = SimpleClass().apply { name = \"simpleName $i\" }\n                        transactionRealm.insert(simpleObject)\n                    }\n                }\n            }\n        }\n\n        val countDownLatch = CountDownLatch(1)\n        CoroutineScope(Dispatchers.Main).launch {\n            // Wait for 5 ms and cancel job\n            delay(5)\n            job.cancelAndJoin()\n\n            // The coroutine won't finish until the transaction is completely done but not all\n            // elements will have been inserted since the transaction is cooperative.\n            // It isn't possible to guarantee we have inserted any element at all either because\n            // another coroutine is launched inside executeTransactionAwait and that triggers a\n            // context switching, which might result in that the call to cancelAndJoin above this\n            // comment be executed even before we check for isActive inside executeTransactionAwait.\n            // So the result yielded by count() will be a number from 0 to anywhere below 100000.\n            assertNotEquals(upperBound.toLong(), realmInstance!!.where<SimpleClass>().count())\n\n            realmInstance!!.close()\n\n            countDownLatch.countDown()\n            this.cancel()\n        }\n\n        TestHelper.awaitOrFail(countDownLatch)\n    }\n\n    @Test\n    fun executeTransactionAwait_throwsDueToThreadViolation() {\n        // Just to prevent the test to end prematurely\n        val countDownLatch = CountDownLatch(1)\n        var exception: IllegalStateException? = null\n\n        Realm.getInstance(configuration).use { realm ->\n            // It will crash so long we aren't using Dispatchers.Unconfined\n            CoroutineScope(Dispatchers.IO).launch {\n                assertFailsWith<IllegalStateException> {\n                    realm.executeTransactionAwait {\n                        // no-op\n                    }\n                }.let {\n                    exception = it\n                    countDownLatch.countDown()\n                }\n            }\n            TestHelper.awaitOrFail(countDownLatch)\n        }\n\n        // Ensure we failed\n        assertNotNull(exception)\n        assertTrue(exception!!.message!!.contains(\"incorrect thread\"))\n    }\n}\n"
  },
  {
    "path": "realm/kotlin-extensions/src/androidTest/kotlin/io/realm/KotlinRealmModelTests.kt",
    "content": "package io.realm\n\nimport androidx.test.platform.app.InstrumentationRegistry\nimport androidx.test.ext.junit.runners.AndroidJUnit4\nimport io.realm.entities.PrimaryKeyClass\nimport io.realm.entities.SimpleClass\nimport io.realm.kotlin.*\nimport io.realm.rule.RunInLooperThread\nimport io.realm.rule.RunTestInLooperThread\nimport org.junit.*\nimport org.junit.Assert.*\nimport org.junit.runner.RunWith\n\n@Suppress(\"FunctionName\")\n@RunWith(AndroidJUnit4::class)\nclass KotlinRealmModelTests {\n\n    @Suppress(\"MemberVisibilityCanPrivate\")\n    @Rule\n    @JvmField\n    val configFactory = TestRealmConfigurationFactory()\n\n    @Rule\n    @JvmField\n    val looperThread = RunInLooperThread()\n\n    private lateinit var realm: Realm\n\n    @Before\n    fun setUp() {\n        Realm.init(InstrumentationRegistry.getInstrumentation().targetContext)\n        realm = Realm.getInstance(configFactory.createConfiguration())\n    }\n\n    @After\n    fun tearDown() {\n        realm.close()\n    }\n\n    @Test\n    fun deleteFromRealm() {\n        // Make sure starting with 0\n        Assert.assertEquals(0, realm.where<SimpleClass>().count())\n\n        // Add 1, check count\n        realm.executeTransaction { it.createObject<SimpleClass>() }\n        Assert.assertEquals(1, realm.where<SimpleClass>().count())\n\n        // Delete the first, check count again.  !! is intentional to make\n        // sure we are sure calling deleteFromRealm\n        realm.executeTransaction { realm.where<SimpleClass>().findFirst()!!.deleteFromRealm() }\n        Assert.assertEquals(0, realm.where<SimpleClass>().count())\n\n    }\n\n    @Test\n    fun isValid() {\n        realm.executeTransaction {\n            val obj = it.createObject<SimpleClass>()\n            assertTrue(\"Expected valid after insert\", obj.isValid())\n\n            obj.deleteFromRealm()\n            assertFalse(\"Expected invalid after delete\", obj.isValid())\n        }\n    }\n\n   @Test\n    fun isManaged() {\n        realm.executeTransaction {\n            var obj = SimpleClass()\n            assertFalse(\"Expected not managed until attached\", obj.isManaged())\n\n            obj = it.copyToRealm(obj)\n            assertTrue(\"Expected managed after attaching\", obj.isManaged())\n        }\n    }\n\n    @Test\n    @RunTestInLooperThread\n    fun addChangeListener_RealmObjectChangeListener_addObject() {\n        val realm = looperThread.realm\n        realm.beginTransaction()\n        val obj = realm.createObject<SimpleClass>()\n        realm.commitTransaction()\n\n        looperThread.keepStrongReference(obj)\n        obj.addChangeListener( RealmObjectChangeListener { updatedObj, changes ->\n            assertTrue(changes?.isFieldChanged(SimpleClass::name.name) ?: false)\n            assertEquals(\"simple1\", updatedObj.name)\n            looperThread.testComplete()\n        })\n\n        realm.beginTransaction()\n        obj.name = \"simple1\"\n        realm.commitTransaction()\n    }\n\n    @Test\n    @RunTestInLooperThread\n    fun addChangeListener_RealmChangeListener_addObject() {\n        val realm = looperThread.realm\n        realm.beginTransaction()\n        val obj = realm.createObject<SimpleClass>()\n        realm.commitTransaction()\n\n        looperThread.keepStrongReference(obj)\n        obj.addChangeListener( RealmChangeListener { simpleClass ->\n            assertEquals(\"simple1\", simpleClass.name)\n            looperThread.testComplete()\n        })\n\n        realm.beginTransaction()\n        obj.name = \"simple1\"\n        realm.commitTransaction()\n    }\n\n    @Test\n    @RunTestInLooperThread\n    fun removeChangeListener_RealmChangeListener_removeObject() {\n        val realm = looperThread.realm\n        realm.beginTransaction()\n        val obj = realm.createObject<PrimaryKeyClass>(101)\n        realm.commitTransaction()\n\n        val listener = RealmChangeListener<PrimaryKeyClass>{\n            fail()\n        }\n\n        obj.addChangeListener(listener)\n        obj.removeChangeListener(listener)\n\n        realm.beginTransaction()\n        obj.name = \"Bobby Risigliano\"\n        realm.commitTransaction()\n\n        // Try to trigger the listeners.\n        realm.sharedRealm.refresh()\n        looperThread.testComplete()\n    }\n\n    @Test\n    @RunTestInLooperThread\n    fun removeChangeListener_RealmObjectChangeListener_removeObject() {\n        val realm = looperThread.realm\n        realm.beginTransaction()\n        val obj = realm.createObject<PrimaryKeyClass>(101)\n        realm.commitTransaction()\n\n        val listener = RealmObjectChangeListener<PrimaryKeyClass>{ _,_ ->\n            fail()\n        }\n\n        obj.addChangeListener(listener)\n        obj.removeChangeListener(listener)\n\n        realm.beginTransaction()\n        obj.name = \"Bobby Risigliano\"\n        realm.commitTransaction()\n\n        // Try to trigger the listeners.\n        realm.sharedRealm.refresh()\n        looperThread.testComplete()\n    }\n\n    @Test\n    @RunTestInLooperThread\n    fun removeAllChangeListeners() {\n        val realm = looperThread.realm\n        realm.beginTransaction()\n        val obj = realm.createObject<PrimaryKeyClass>(101)\n        realm.commitTransaction()\n\n        val changeListener = RealmChangeListener<PrimaryKeyClass> {\n            fail()\n        }\n        val objectChangeListener = RealmObjectChangeListener<PrimaryKeyClass> { _,_ ->\n            fail()\n        }\n\n        obj.addChangeListener(changeListener)\n        obj.addChangeListener(objectChangeListener)\n\n        obj.removeAllChangeListeners()\n\n        realm.beginTransaction()\n        obj.name = \"Bobby Risigliano\"\n        realm.commitTransaction()\n\n        // Try to trigger the listeners.\n        realm.sharedRealm.refresh()\n        looperThread.testComplete()\n    }\n\n    @Test\n    @RunTestInLooperThread\n    @Throws(Throwable::class)\n    fun isLoaded() {\n        val realm = looperThread.realm\n\n        realm.executeTransaction { it.createObject<SimpleClass>() }\n\n        val result = realm.where<SimpleClass>().findFirstAsync()\n        assertFalse(\"Expect isLoaded is false just after async call\", result.isLoaded())\n\n        looperThread.keepStrongReference(result)\n\n        result.addChangeListener(RealmChangeListener { r ->\n            assertTrue(\"Expected the loading to have completed\", r.isLoaded())\n            looperThread.testComplete()\n        })\n    }\n\n    @Test\n    @RunTestInLooperThread\n    @Throws(Throwable::class)\n    fun load() {\n        val realm = looperThread.realm\n\n        realm.executeTransaction { it.createObject<SimpleClass>() }\n\n        val result = realm.where<SimpleClass>().findFirstAsync()\n        assertFalse(\"Expect isLoaded is false just after async call\", result.isLoaded())\n\n        result.load()\n\n        assertTrue(\"Expected isLoaded is true after blocking on load()\", result.isLoaded())\n        looperThread.testComplete()\n    }\n\n}\n"
  },
  {
    "path": "realm/kotlin-extensions/src/androidTest/kotlin/io/realm/KotlinRealmQueryTests.kt",
    "content": "package io.realm\n\nimport androidx.test.platform.app.InstrumentationRegistry\nimport androidx.test.ext.junit.runners.AndroidJUnit4\nimport io.realm.entities.AllPropTypesClass\nimport io.realm.kotlin.createObject\nimport io.realm.kotlin.oneOf\nimport io.realm.kotlin.where\nimport org.junit.After\nimport org.junit.Assert.assertEquals\nimport org.junit.Before\nimport org.junit.Rule\nimport org.junit.Test\nimport org.junit.runner.RunWith\nimport java.util.*\n\n@Suppress(\"FunctionName\")\n@RunWith(AndroidJUnit4::class)\nclass KotlinRealmQueryTests {\n\n    @Suppress(\"MemberVisibilityCanPrivate\")\n    @Rule\n    @JvmField\n    val configFactory = TestRealmConfigurationFactory()\n\n    private lateinit var realm: Realm\n\n    @Before\n    fun setUp() {\n        Realm.init(InstrumentationRegistry.getInstrumentation().targetContext)\n        realm = Realm.getInstance(configFactory.createConfiguration())\n    }\n\n    @After\n    fun tearDown() {\n        realm.close()\n    }\n\n    @Test\n    fun oneOf_String() {\n        realm.beginTransaction()\n        val obj = realm.createObject<AllPropTypesClass>()\n        obj.stringVar = \"test\"\n        realm.commitTransaction()\n\n        assertEquals(1,\n                realm.where<AllPropTypesClass>()\n                     .oneOf(AllPropTypesClass::nullableStringVar.name, arrayOf<String?>(null, \"test\"))\n                     .count())\n\n        assertEquals(1,\n                realm.where<AllPropTypesClass>()\n                        .oneOf(AllPropTypesClass::stringVar.name, arrayOf<String>(\"test\"))\n                        .count())\n    }\n\n    @Test\n    fun oneOf_Byte() {\n        realm.beginTransaction()\n        val obj = realm.createObject<AllPropTypesClass>()\n        obj.byteVar = 3\n        realm.commitTransaction()\n\n        assertEquals(1,\n                realm.where<AllPropTypesClass>()\n                        .oneOf(AllPropTypesClass::nullableByteVar.name, arrayOf<Byte?>(null, 3))\n                        .count())\n\n        assertEquals(1,\n                realm.where<AllPropTypesClass>()\n                        .oneOf(AllPropTypesClass::byteVar.name, arrayOf<Byte>(3))\n                        .count())\n    }\n\n    @Test\n    fun oneOf_Short() {\n        realm.beginTransaction()\n        val obj = realm.createObject<AllPropTypesClass>()\n        obj.shortVar = 3\n        realm.commitTransaction()\n\n        assertEquals(1,\n                realm.where<AllPropTypesClass>()\n                        .oneOf(AllPropTypesClass::nullableShortVar.name, arrayOf<Short?>(null, 3))\n                        .count())\n\n        assertEquals(1,\n                realm.where<AllPropTypesClass>()\n                        .oneOf(AllPropTypesClass::shortVar.name, arrayOf<Short>(3))\n                        .count())\n    }\n\n    @Test\n    fun oneOf_Int() {\n        realm.beginTransaction()\n        val obj = realm.createObject<AllPropTypesClass>()\n        obj.intVar = 3\n        realm.commitTransaction()\n\n        assertEquals(1,\n                realm.where<AllPropTypesClass>()\n                        .oneOf(AllPropTypesClass::nullableIntVar.name, arrayOf<Int?>(null, 3))\n                        .count())\n\n        assertEquals(1,\n                realm.where<AllPropTypesClass>()\n                        .oneOf(AllPropTypesClass::intVar.name, arrayOf<Int>(3))\n                        .count())\n    }\n\n    @Test\n    fun oneOf_Long() {\n        realm.beginTransaction()\n        val obj = realm.createObject<AllPropTypesClass>()\n        obj.longVar = 3\n        realm.commitTransaction()\n\n        assertEquals(1,\n                realm.where<AllPropTypesClass>()\n                        .oneOf(AllPropTypesClass::nullableLongVar.name, arrayOf<Long?>(null, 3))\n                        .count())\n\n        assertEquals(1,\n                realm.where<AllPropTypesClass>()\n                        .oneOf(AllPropTypesClass::longVar.name, arrayOf<Long>(3))\n                        .count())\n    }\n\n    @Test\n    fun oneOf_Double() {\n        realm.beginTransaction()\n        val obj = realm.createObject<AllPropTypesClass>()\n        obj.doubleVar = 3.5\n        realm.commitTransaction()\n\n        assertEquals(1,\n                realm.where<AllPropTypesClass>()\n                        .oneOf(AllPropTypesClass::nullableDoubleVar.name, arrayOf<Double?>(null, 3.5))\n                        .count())\n\n        assertEquals(1,\n                realm.where<AllPropTypesClass>()\n                        .oneOf(AllPropTypesClass::doubleVar.name, arrayOf<Double>(3.5))\n                        .count())\n    }\n\n    @Test\n    fun oneOf_Float() {\n        realm.beginTransaction()\n        val obj = realm.createObject<AllPropTypesClass>()\n        obj.floatVar = 3.5f\n        realm.commitTransaction()\n\n        assertEquals(1,\n                realm.where<AllPropTypesClass>()\n                        .oneOf(AllPropTypesClass::nullableFloatVar.name, arrayOf<Float?>(null, 3.5f))\n                        .count())\n\n        assertEquals(1,\n                realm.where<AllPropTypesClass>()\n                        .oneOf(AllPropTypesClass::floatVar.name, arrayOf<Float>(3.5f))\n                        .count())\n    }\n\n    @Test\n    fun oneOf_Boolean() {\n        realm.beginTransaction()\n        val obj = realm.createObject<AllPropTypesClass>()\n        obj.booleanVar = true\n        realm.commitTransaction()\n\n        assertEquals(1,\n                realm.where<AllPropTypesClass>()\n                        .oneOf(AllPropTypesClass::nullableBooleanVar.name, arrayOf<Boolean?>(null, true))\n                        .count())\n\n        assertEquals(1,\n                realm.where<AllPropTypesClass>()\n                        .oneOf(AllPropTypesClass::booleanVar.name, arrayOf<Boolean?>(true))\n                        .count())\n    }\n\n    @Test\n    fun oneOf_Date() {\n\n        val testDate = Date()\n\n        realm.beginTransaction()\n        val obj = realm.createObject<AllPropTypesClass>()\n        obj.dateVar = testDate\n        realm.commitTransaction()\n\n        assertEquals(1,\n                realm.where<AllPropTypesClass>()\n                        .oneOf(AllPropTypesClass::nullableDateVar.name, arrayOf<Date?>(null, testDate))\n                        .count())\n\n        assertEquals(1,\n                realm.where<AllPropTypesClass>()\n                        .oneOf(AllPropTypesClass::dateVar.name, arrayOf<Date>(testDate))\n                        .count())\n    }\n\n}\n"
  },
  {
    "path": "realm/kotlin-extensions/src/androidTest/kotlin/io/realm/KotlinRealmTests.kt",
    "content": "package io.realm\n\nimport androidx.test.ext.junit.runners.AndroidJUnit4\nimport io.realm.entities.PrimaryKeyClass\nimport io.realm.entities.SimpleClass\nimport io.realm.kotlin.createObject\nimport io.realm.kotlin.where\nimport org.junit.After\nimport org.junit.Before\nimport org.junit.Rule\nimport org.junit.Test\nimport org.junit.runner.RunWith\nimport kotlin.test.assertEquals\n\n@Suppress(\"FunctionName\")\n@RunWith(AndroidJUnit4::class)\nclass KotlinRealmTests {\n\n    @Suppress(\"MemberVisibilityCanPrivate\")\n    @Rule\n    @JvmField\n    val configFactory = TestRealmConfigurationFactory()\n\n    private lateinit var realm: Realm\n\n    @Before\n    fun setUp() {\n        realm = Realm.getInstance(configFactory.createConfiguration())\n    }\n\n    @After\n    fun tearDown() {\n        realm.executeTransaction { it.deleteAll() }\n        realm.close()\n    }\n\n    @Test\n    fun createObject() {\n        realm.executeTransaction {\n            it.createObject<SimpleClass>()\n        }\n        assertEquals(1, realm.where<SimpleClass>().count())\n    }\n\n\n    @Test\n    fun createObject_primaryKey() {\n        realm.executeTransaction {\n            it.createObject<PrimaryKeyClass>(1)\n        }\n        assertEquals(1, realm.where<PrimaryKeyClass>().count())\n    }\n\n    @Test\n    fun where() {\n        assertEquals(0, realm.where<SimpleClass>().count())\n    }\n}\n"
  },
  {
    "path": "realm/kotlin-extensions/src/androidTest/kotlin/io/realm/entities/AllPropTypesClass.kt",
    "content": "package io.realm.entities\n\nimport io.realm.RealmModel\nimport io.realm.annotations.RealmClass\nimport java.util.*\n\n@RealmClass\nopen class AllPropTypesClass : RealmModel {\n\n    var stringVar: String = \"\"\n    var byteVar: Byte = 0\n    var shortVar: Short = 0\n    var intVar: Int = 0\n    var longVar: Long = 0\n    var doubleVar: Double = 0.0\n    var floatVar: Float = 0.0f\n    var booleanVar : Boolean = false\n    var dateVar : Date = Date()\n\n    var nullableStringVar: String? = null\n    var nullableByteVar: Byte? = null\n    var nullableShortVar: Short? = null\n    var nullableIntVar: Int? = null\n    var nullableLongVar: Long? = null\n    var nullableDoubleVar: Double? = null\n    var nullableFloatVar: Float? = null\n    var nullableBooleanVar : Boolean? = null\n    var nullableDateVar : Date? = null\n}\n"
  },
  {
    "path": "realm/kotlin-extensions/src/androidTest/kotlin/io/realm/entities/PrimaryKeyClass.kt",
    "content": "package io.realm.entities\n\nimport io.realm.RealmModel\nimport io.realm.annotations.PrimaryKey\nimport io.realm.annotations.RealmClass\n\n@RealmClass\nopen class PrimaryKeyClass: RealmModel {\n    @PrimaryKey\n    var id: Long = 0\n    var name: String = \"\"\n}\n"
  },
  {
    "path": "realm/kotlin-extensions/src/androidTest/kotlin/io/realm/entities/SimpleClass.kt",
    "content": "package io.realm.entities\n\nimport io.realm.RealmModel\nimport io.realm.annotations.RealmClass\n\n@RealmClass\nopen class SimpleClass : RealmModel {\n    var name: String = \"\"\n}\n"
  },
  {
    "path": "realm/kotlin-extensions/src/androidTestObjectServer/kotlin/io/realm/kotlin/KotlinSyncedRealmTests.kt",
    "content": "package io.realm.kotlin\n\nimport androidx.test.ext.junit.runners.AndroidJUnit4\nimport io.realm.*\nimport io.realm.mongodb.App\nimport io.realm.mongodb.sync.SyncConfiguration\nimport org.junit.*\nimport org.junit.Assert.assertEquals\nimport org.junit.Assert.fail\nimport org.junit.runner.RunWith\n\n@RunWith(AndroidJUnit4::class)\nclass KotlinSyncedRealmTests {\n\n    @get:Rule\n    val configFactory = TestSyncConfigurationFactory()\n\n    private lateinit var app: App\n    private lateinit var realm: Realm\n\n    @Before\n    fun setUp() {\n        // FIXME\n//        Realm.init(InstrumentationRegistry.getInstrumentation().targetContext)\n//        app = App(\"foo\")\n//        val user = SyncTestUtils.createTestUser(app)\n//        realm = Realm.getInstance(configFactory.createSyncConfigurationBuilder(user).build())\n    }\n\n    @After\n    fun tearDown() {\n        // FIXME\n//        if (this::realm.isInitialized) {\n//            realm.close()\n//        }\n//        if (this::app.isInitialized) {\n//            App.CREATED = false\n//        }\n    }\n\n    @Ignore(\"FIXME\")\n    @Test\n    fun syncSession() {\n        assertEquals(app.sync.getSession(realm.configuration as SyncConfiguration), realm.syncSession)\n    }\n\n    @Ignore(\"FIXME\")\n    @Test\n    fun syncSession_throwsForNonSyncRealm() {\n        realm.close()\n        realm = Realm.getInstance(configFactory.createConfiguration())\n        try {\n            realm.syncSession\n            fail()\n        } catch (ignored: IllegalStateException) {\n        }\n    }\n\n}\n"
  },
  {
    "path": "realm/kotlin-extensions/src/main/AndroidManifest.xml",
    "content": "<manifest package=\"io.realm.kotlin\" />\n"
  },
  {
    "path": "realm/kotlin-extensions/src/main/kotlin/io/realm/kotlin/DynamicRealmExtensions.kt",
    "content": "/*\n * Copyright 2020 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\npackage io.realm.kotlin\n\nimport io.realm.DynamicRealm\nimport io.realm.annotations.Beta\nimport kotlinx.coroutines.flow.Flow\n\n/**\n * Creates a [Flow] for a [DynamicRealm]. It should emit the initial state of the Realm when subscribed to and\n * on each subsequent update of the Realm.\n *\n * @return Kotlin [Flow] that emit all updates to the Realm.\n */\n@Beta\nfun DynamicRealm.toflow(): Flow<DynamicRealm> {\n    return configuration.flowFactory.from(this)\n}\n"
  },
  {
    "path": "realm/kotlin-extensions/src/main/kotlin/io/realm/kotlin/RealmExtensions.kt",
    "content": "/*\n * Copyright 2017 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 */\npackage io.realm.kotlin\n\nimport io.realm.Realm\nimport io.realm.RealmModel\nimport io.realm.RealmQuery\nimport io.realm.annotations.Beta\nimport io.realm.exceptions.RealmException\nimport kotlinx.coroutines.CoroutineScope\nimport kotlinx.coroutines.asCoroutineDispatcher\nimport kotlinx.coroutines.flow.Flow\nimport kotlinx.coroutines.isActive\nimport kotlinx.coroutines.withContext\nimport kotlin.coroutines.CoroutineContext\n\n/**\n * Returns a typed RealmQuery, which can be used to query for specific objects of this type\n *\n * @param T the class of the object which is to be queried for.\n * @return a typed `RealmQuery`, which can be used to query for specific objects of this type.\n */\ninline fun <reified T : RealmModel> Realm.where(): RealmQuery<T> {\n    return this.where(T::class.java)\n}\n\n/**\n * Deletes all objects of the specified class from the Realm.\n *\n * @param T the class of the object which is to be queried for.\n * @throws IllegalStateException if the corresponding Realm is closed or called from an incorrect thread.\n */\ninline fun <reified T : RealmModel> Realm.delete() {\n    return this.delete(T::class.java)\n}\n\n/**\n *\n * Instantiates and adds a new object to the Realm.\n *\n * This method is only available for model classes with no `@PrimaryKey` annotation.\n * If you like to create an object that has a primary key, use [createObject] instead.\n *\n * @param T the Class of the object to create.\n * @return the new object.\n * @throws RealmException if the primary key is defined in the model class or an object cannot be created.\n */\ninline fun <reified T : RealmModel> Realm.createObject(): T {\n    return this.createObject(T::class.java)\n}\n\n/**\n *\n * Instantiates and adds a new object to the Realm with the primary key value already set.\n *\n * If the value violates the primary key constraint, no object will be added and a RealmException will be\n * thrown. The default value for primary key provided by the model class will be ignored.\n *\n * @param T the Class of the object to create.\n * @param primaryKeyValue value for the primary key field.\n * @return the new object.\n * @throws RealmException if object could not be created due to the primary key being invalid.\n * @throws IllegalStateException if the model class does not have an primary key defined.\n * @throws IllegalArgumentException if the `primaryKeyValue` doesn't have a value that can be converted to the\n * expected value.\n */\ninline fun <reified T : RealmModel> Realm.createObject(primaryKeyValue: Any?): T {\n    return this.createObject(T::class.java, primaryKeyValue)\n}\n\n/**\n * Instantiates and adds a new embedded object to the Realm.\n *\n * This method should only be used to create objects of types marked as embedded.\n *\n * @param T the Class of the object to create. It must be marked with `@RealmClass(embedded = true)`.\n * @param parentObject The parent object which should hold a reference to the embedded object. If the parent property is a list\n * the embedded object will be added to the end of that list.\n * @param parentProperty the property in the parent class which holds the reference.\n * @return the newly created embedded object.\n * @throws IllegalArgumentException if `clazz` is not an embedded class or if the property\n * in the parent class cannot hold objects of the appropriate type.\n */\ninline fun <reified T : RealmModel> Realm.createEmbeddedObject(parentObject: RealmModel, parentProperty: String): T {\n    return this.createEmbeddedObject(T::class.java, parentObject, parentProperty)\n}\n\n/**\n * Creates a [Flow] for a [Realm]. It should emit the initial state of the Realm when subscribed to and\n * on each subsequent update of the Realm.\n *\n * @return Kotlin [Flow] that emit all updates to the Realm.\n */\n@Beta\nfun Realm.toflow(): Flow<Realm> {\n    return configuration.flowFactory.from(this)\n}\n\n/**\n * Suspend version of [Realm.executeTransaction] to use within coroutines.\n *\n * Canceling the scope or job in which this function is executed does not cancel the transaction itself. If you want to ensure\n * your transaction is cooperative, you have to check for the value of [CoroutineScope.isActive] while running the transaction:\n *\n * ```\n * coroutineScope.launch {\n *   // insert 100 objects\n *   realm.executeTransactionAwait { transactionRealm ->\n *     for (i in 1..100) {\n *       // all good if active, otherwise do nothing\n *       if (isActive) {\n *         transactionRealm.insert(MyObject(i))\n *       }\n *     }\n *   }\n * }\n * ```\n *\n * @param context optional [CoroutineContext] in which this coroutine will run.\n * @param transaction the [Realm.Transaction] to execute.\n * @throws IllegalArgumentException if the `transaction` is `null`.\n * @throws RealmMigrationNeededException if the latest version contains incompatible schema changes.\n */\nsuspend fun Realm.executeTransactionAwait(\n        context: CoroutineContext = Realm.WRITE_EXECUTOR.asCoroutineDispatcher(),\n        transaction: (realm: Realm) -> Unit\n) {\n    // Default to our own thread pool executor (as dispatcher)\n    withContext(context) {\n        // Get a new coroutine-confined Realm instance from the original Realm's configuration\n        Realm.getInstance(configuration).use { coroutineRealm ->\n            // Ensure cooperation and prevent execution if the scope is not active.\n            if (isActive) {\n                coroutineRealm.executeTransaction(transaction)\n            }\n        }\n    }\n\n    // force refresh because we risk fetching stale data from other realms\n    refresh()\n}\n\n/**\nMissing functions. Consider these for inclusion later:\n- createAllFromJson(Class<E> clazz, InputStream inputStream)\n- createAllFromJson(Class<E> clazz, org.json.JSONArray json)\n- createAllFromJson(Class<E> clazz, String json)\n- createObjectFromJson(Class<E> clazz, InputStream inputStream)\n- createObjectFromJson(Class<E> clazz, org.json.JSONObject json)\n- createObjectFromJson(Class<E> clazz, String json)\n- createOrUpdateAllFromJson(Class<E> clazz, InputStream in)\n- createOrUpdateAllFromJson(Class<E> clazz, org.json.JSONArray json)\n- createOrUpdateAllFromJson(Class<E> clazz, String json)\n- createOrUpdateObjectFromJson(Class<E> clazz, InputStream in)\n- createOrUpdateObjectFromJson(Class<E> clazz, org.json.JSONObject json)\n- createOrUpdateObjectFromJson(Class<E> clazz, String json)\n- createOrUpdateObjectFromJson(Class<E> clazz, String json)\n */\n"
  },
  {
    "path": "realm/kotlin-extensions/src/main/kotlin/io/realm/kotlin/RealmListExtensions.kt",
    "content": "/*\n * Copyright 2020 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\npackage io.realm.kotlin\n\nimport io.realm.*\nimport io.realm.annotations.Beta\nimport io.realm.rx.CollectionChange\nimport kotlinx.coroutines.flow.Flow\n\n/**\n * Returns a [Flow] that monitors changes to this RealmList. It will emit the current\n * RealmResults when subscribed to. RealmList updates will continually be emitted as the RealmList\n * is updated - `onCompletion` will never be called.\n *\n * Items emitted from Realm flows are frozen - see [RealmList.freeze]. This means that they are\n * immutable and can be read from any thread.\n *\n * Realm flows always emit items from the thread holding the live RealmList. This means that if you\n * need to do further processing, it is recommended to collect the values on a computation\n * dispatcher:\n *\n * ```\n * list.toFlow()\n *   .map { list -> doExpensiveWork(list) }\n *   .flowOn(Dispatchers.IO)\n *   .onEach { flowList ->\n *     // ...\n *   }.launchIn(Dispatchers.Main)\n * ```\n *\n * If your would like `toFlow()` to stop emitting items you can instruct the flow to only emit the\n * first item by calling [kotlinx.coroutines.flow.first]:\n * ```\n * val foo = list.toFlow()\n *   .flowOn(context)\n *   .first()\n * ```\n *\n * @return Kotlin [Flow] on which calls to `onEach` or `collect` can be made.\n */\n@Beta\nfun <T> RealmList<T>.toFlow(): Flow<RealmList<T>> {\n    @Suppress(\"INACCESSIBLE_TYPE\")\n    return when (val realmInstance = baseRealm) {\n        is Realm -> realmInstance.configuration.flowFactory.from(realmInstance, this)\n        is DynamicRealm -> realmInstance.configuration.flowFactory.from(realmInstance, this)\n        else -> throw IllegalStateException(\"Wrong type of Realm.\")\n    }\n}\n\n/**\n * Returns a [Flow] that monitors changes to this RealmList. It will emit the current\n * RealmList upon subscription. For each update to the RealmList a [CollectionChange] consisting of\n * a pair with the RealmList and its corresponding [OrderedCollectionChangeSet] will be sent. The\n * changeset will be `null` the first time the RealmList is emitted.\n *\n * The RealmList will continually be emitted as it is updated. This flow will never complete.\n *\n * Items emitted are frozen (see [RealmList.freeze]). This means that they are immutable and can\n * be read on any thread.\n *\n * Realm flows always emit items from the thread holding the live Realm. This means that if\n * you need to do further processing, it is recommended to collect the values on a computation\n * dispatcher:\n *\n * ```\n * list.toChangesetFlow()\n *   .map { change -> doExpensiveWork(change) }\n *   .flowOn(Dispatchers.IO)\n *   .onEach { change ->\n *     // ...\n *   }.launchIn(Dispatchers.Main)\n * ```\n *\n * If you would like `toChangesetFlow()` to stop emitting items you can instruct the flow to only\n * emit the first item by calling [kotlinx.coroutines.flow.first]:\n * ```\n * val foo = list.toChangesetFlow()\n *   .flowOn(context)\n *   .first()\n * ```\n *\n * @return Kotlin [Flow] that will never complete.\n * @throws UnsupportedOperationException if the required coroutines framework is not on the\n * classpath or the corresponding Realm instance doesn't support flows.\n * @throws IllegalStateException if the Realm wasn't opened on a Looper thread.\n */\n@Beta\nfun <T> RealmList<T>.toChangesetFlow(): Flow<CollectionChange<RealmList<T>>> {\n    @Suppress(\"INACCESSIBLE_TYPE\")\n    return when (val realmInstance = baseRealm) {\n        is Realm -> realmInstance.configuration.flowFactory.changesetFrom(realmInstance, this)\n        is DynamicRealm -> realmInstance.configuration.flowFactory.changesetFrom(realmInstance, this)\n        else -> throw IllegalStateException(\"Wrong type of Realm.\")\n    }\n}\n"
  },
  {
    "path": "realm/kotlin-extensions/src/main/kotlin/io/realm/kotlin/RealmModelExtensions.kt",
    "content": "/*\n * Copyright 2017 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 */\npackage io.realm.kotlin\n\nimport io.realm.RealmChangeListener\nimport io.realm.RealmModel\nimport io.realm.RealmObject\nimport io.realm.RealmObjectChangeListener\n\n/**\n * Deletes the object from the Realm it is currently associated with.\n *\n * After this method is called the object will be invalid and any operation (read or write) performed on it will\n * fail with an `IllegalStateException`.\n *\n * @throws IllegalStateException if the corresponding Realm is closed or in an incorrect thread.\n * @see [isValid]\n */\nfun RealmModel.deleteFromRealm() {\n    RealmObject.deleteFromRealm(this)\n}\n\n/**\n * Checks if the RealmObject is still valid to use i.e., the RealmObject hasn't been deleted nor has the\n * Realm been closed. It will always return `true` for unmanaged objects.\n *\n * @return `true` if the object is still accessible or an unmanaged object, `false` otherwise.\n */\nfun RealmModel.isValid(): Boolean {\n    return RealmObject.isValid(this)\n}\n\n/**\n * Returns a frozen snapshot of this object. The frozen copy can be read and queried from any thread without throwing\n * an [IllegalStateException].\n *\n * Freezing a RealmModel also creates a frozen Realm which has its own lifecycle, but if the live Realm that spawned the\n * original collection is fully closed (i.e. all instances across all threads are closed), the frozen Realm and\n * object will be closed as well.\n *\n * Frozen objects can be queried as normal, but trying to mutate it in any way or attempting to register a listener will\n * throw an [IllegalStateException].\n *\n * Note: Keeping a large number of frozen objects with different versions alive can have a negative impact on the filesize\n * of the Realm. In order to avoid such a situation it is possible to set [io.realm.RealmConfiguration.Builder.maxNumberOfActiveVersions].\n *\n * @return a frozen copy of this object.\n * @throws IllegalStateException if this method is called from inside a write transaction.\n */\nfun <T: RealmModel> RealmModel.freeze(): T {\n    return RealmObject.freeze(this) as T\n}\n\n/**\n * Returns whether or not this RealmModel is frozen.\n *\n * @return `true` if the RealmModel is frozen, `false` if it is not.\n * @see [freeze]\n */\nfun RealmModel.isFrozen(): Boolean {\n    return RealmObject.isFrozen(this)\n}\n\n/**\n * Checks if this object is managed by Realm. A managed object is just a wrapper around the data in the underlying\n * Realm file. On Looper threads, a managed object will be live-updated so it always points to the latest data. It\n * is possible to register a change listener using [addChangeListener] to be\n * notified when changes happen. Managed objects are thread confined so that they cannot be accessed from other threads\n * than the one that created them.\n *\n * If this method returns `false`, the object is unmanaged. An unmanaged object is just a normal Kotlin object,\n * so it can be passed freely across threads, but the data in the object is not connected to the underlying Realm,\n * so it will not be live updated.\n *\n * It is possible to create a managed object from an unmanaged object by using\n * [io.realm.Realm.copyToRealm]. An unmanaged object can be created from a managed object by using\n * [io.realm.Realm.copyFromRealm].\n *\n * @return `true` if the object is managed, `false` if it is unmanaged.\n */\nfun RealmModel.isManaged(): Boolean {\n    return RealmObject.isManaged(this)\n}\n\n/**\n * Checks if the query used to find this RealmObject has completed.\n *\n * Async methods like [io.realm.RealmQuery.findFirstAsync] return an RealmObject that represents the future result\n * of the RealmQuery. It can be considered similar to a [java.util.concurrent.Future] in this regard.\n *\n * Once `isLoaded()` returns `true`, the object represents the query result even if the query\n * didn't find any object matching the query parameters. In this case the RealmObject will\n * become a `null` object.\n *\n * \"Null\" objects represents `null`.  An exception is thrown if any accessor is called, so it is important to also\n * check isValid before calling any methods. A common pattern is:\n *\n *\n * ```kotlin\n * val person = realm.where<Person>().findFirstAsync()\n * person.isLoaded() // == false\n * person.addChangeListener { p ->\n *     p.isLoaded() // always true here\n *     if(p.isValid()) {\n *         // It is safe to access this person.\n *     }\n * }\n * ```\n * Synchronous RealmObjects are by definition blocking hence this method will always return `true` for them.\n * This method will return `true` if called on an unmanaged object (created outside of Realm).\n *\n * @return `true` if the query has completed, `false` if the query is in\n * progress.\n * @see [isValid]\n */\nfun RealmModel.isLoaded(): Boolean {\n    return RealmObject.isLoaded(this)\n}\n\n/**\n * Makes an asynchronous query blocking. This will also trigger any registered listeners.\n *\n * Note: This will return `true` if called for an unmanaged object (created outside of Realm).\n *\n * @return `true` if it successfully completed the query, `false` otherwise.\n */\nfun RealmModel.load(): Boolean {\n    return RealmObject.load(this)\n}\n\n\n/**\n * Adds a change listener to a RealmObject that will be triggered if any value field or referenced RealmObject field\n * is changed, or the RealmList field itself is changed.\n\n * Registering a change listener will not prevent the underlying RealmObject from being garbage collected.\n * If the RealmObject is garbage collected, the change listener will stop being triggered. To avoid this, keep a\n * strong reference for as long as appropriate e.g. in a class variable.\n *\n * ```kotlin\n * class MyActivity : Activity {\n *\n *     private var person: Person?\n *\n *     override fun onCreate(savedInstanceState: Bundle?) {\n *         super.onCreate(savedInstanceState)\n *         person = realm.where<Person>().findFirst()\n *         person?.addChangeListener(RealmChangeListener { person ->\n *             // React to change\n *         })\n *     }\n * }\n * ```\n *\n * @param listener the change listener to be notified.\n * @throws IllegalArgumentException if the `object` is `null` or an unmanaged object, or the change\n * listener is `null`.\n * @throws IllegalStateException if you try to add a listener from a non-Looper or IntentService thread.\n * @throws IllegalStateException if you try to add a listener inside a transaction.\n */\nfun <E : RealmModel> E.addChangeListener(listener: RealmChangeListener<E>) {\n    RealmObject.addChangeListener(this, listener)\n}\n\n/**\n * Adds a change listener to a RealmObject to get detailed information about the changes. The listener will be\n * triggered if any value field or referenced RealmObject field is changed, or the RealmList field itself is\n * changed.\n\n * Registering a change listener will not prevent the underlying RealmObject from being garbage collected.\n * If the RealmObject is garbage collected, the change listener will stop being triggered. To avoid this, keep a\n * strong reference for as long as appropriate e.g. in a class variable.\n *\n * ```kotlin\n * class MyActivity : Activity {\n *\n *     private var person: Person?\n *\n *     override fun onCreate(savedInstanceState: Bundle?) {\n *         super.onCreate(savedInstanceState)\n *         person = realm.where<Person>().findFirst()\n *         person?.addChangeListener(RealmObjectChangeListener { person, changeSet ->\n *             // React to change\n *         })\n *     }\n * }\n * ```\n *\n * @param listener the change listener to be notified.\n * @throws IllegalArgumentException if the `object` is `null` or an unmanaged object, or the change\n * listener is `null`.\n * @throws IllegalStateException if you try to add a listener from a non-Looper or IntentService thread.\n * @throws IllegalStateException if you try to add a listener inside a transaction.\n */\nfun <E : RealmModel> E.addChangeListener(listener: RealmObjectChangeListener<E>) {\n    RealmObject.addChangeListener(this, listener)\n}\n\n/**\n * Removes a previously registered listener on the given RealmObject.\n *\n * @param listener the instance to be removed.\n * @throws IllegalArgumentException if the `object` or the change listener is `null`.\n * @throws IllegalArgumentException if object is an unmanaged RealmObject.\n * @throws IllegalStateException if you try to remove a listener from a non-Looper Thread.\n */\nfun  <E : RealmModel> E.removeChangeListener(listener: RealmChangeListener<E>) {\n    RealmObject.removeChangeListener(this, listener)\n}\n\n/**\n * Removes a previously registered listener on the given RealmObject.\n *\n * @param listener the instance to be removed.\n * @throws IllegalArgumentException if the `object` or the change listener is `null`.\n * @throws IllegalArgumentException if object is an unmanaged RealmObject.\n * @throws IllegalStateException if you try to remove a listener from a non-Looper Thread.\n */\nfun  <E : RealmModel> E.removeChangeListener(listener: RealmObjectChangeListener<E>) {\n    RealmObject.removeChangeListener(this, listener)\n}\n\n/**\n * Removes all registered listeners from the given RealmObject.\n *\n * @throws IllegalArgumentException if object is `null` or isn't managed by Realm.\n */\nfun RealmModel.removeAllChangeListeners() {\n    return RealmObject.removeAllChangeListeners(this)\n}\n"
  },
  {
    "path": "realm/kotlin-extensions/src/main/kotlin/io/realm/kotlin/RealmObjectExtensions.kt",
    "content": "/*\n * Copyright 2020 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\npackage io.realm.kotlin\n\nimport io.realm.*\nimport io.realm.annotations.Beta\nimport io.realm.internal.RealmObjectProxy\nimport io.realm.rx.ObjectChange\nimport kotlinx.coroutines.flow.Flow\nimport kotlinx.coroutines.flow.flowOf\n\n/**\n * Returns a [Flow] that monitors changes to this RealmObject. It will emit the current\n * RealmObject upon subscription. Object updates will continually be emitted as the RealmObject is\n * updated - `onCompletion` will never be called.\n *\n * Items emitted from Realm flows are frozen - see [RealmObject.freeze]. This means that they are\n * immutable and can be read from any thread.\n *\n * Realm flows always emit items from the thread holding the live RealmObject. This means that if\n * you need to do further processing, it is recommended to collect the values on a computation\n * dispatcher:\n *\n * ```\n * object.toFlow()\n *   .map { obj -> doExpensiveWork(obj) }\n *   .flowOn(Dispatchers.IO)\n *   .onEach { flowObject ->\n *     // ...\n *   }.launchIn(Dispatchers.Main)\n * ```\n *\n * If your would like `toFlow()` to stop emitting items you can instruct the flow to only emit the\n * first item by calling [kotlinx.coroutines.flow.first]:\n * ```\n * val foo = object.toFlow()\n *   .flowOn(context)\n *   .first()\n * ```\n *\n * @return Kotlin [Flow] on which calls to `onEach` or `collect` can be made.\n */\n@Beta\nfun <T : RealmModel> T?.toFlow(): Flow<T?> {\n    // Return flow with object or null flow if this function is called on null\n    return this?.let { obj ->\n        if (obj is RealmObjectProxy) {\n            val proxy = obj as RealmObjectProxy\n\n            @Suppress(\"INACCESSIBLE_TYPE\")\n            when (val realm = proxy.`realmGet$proxyState`().`realm$realm`) {\n                is Realm -> realm.configuration.flowFactory.from<T>(realm, obj)\n                is DynamicRealm -> (obj as DynamicRealmObject).let { dynamicRealmObject ->\n                    realm.configuration.flowFactory.from(realm, dynamicRealmObject) as Flow<T?>\n                }\n                else -> throw UnsupportedOperationException(\"${realm.javaClass} is not supported as a candidate for 'toFlow'. Only subclasses of RealmModel/RealmObject can be used.\")\n            }\n        } else {\n            // Return a one-time emission in case the object is unmanaged\n            return flowOf(this)\n        }\n    } ?: flowOf(null)\n}\n\n/**\n * Returns a [Flow] that monitors changes to this RealmObject. It will emit the current\n * RealmObject upon subscription. For each update to the RealmObject a [ObjectChange] consisting of\n * a pair with the RealmObject and its corresponding [ObjectChangeSet] will be sent. The changeset\n * will be `null` the first time the RealmObject is emitted.\n *\n * The RealmObject will continually be emitted as it is updated. This flow will never complete.\n *\n * Items emitted are frozen (see [RealmObject.freeze]). This means that they are immutable and can\n * be read on any thread.\n *\n * Realm flows always emit items from the thread holding the live Realm. This means that if\n * you need to do further processing, it is recommended to collect the values on a computation\n * dispatcher:\n *\n * ```\n * object.toChangesetFlow()\n *   .map { change -> doExpensiveWork(change) }\n *   .flowOn(Dispatchers.IO)\n *   .onEach { change ->\n *     // ...\n *   }.launchIn(Dispatchers.Main)\n * ```\n *\n * If you would like `toChangesetFlow()` to stop emitting items you can instruct the flow to only\n * emit the first item by calling [kotlinx.coroutines.flow.first]:\n * ```\n * val foo = object.toChangesetFlow()\n *   .flowOn(context)\n *   .first()\n * ```\n *\n * @return Kotlin [Flow] that will never complete.\n * @throws UnsupportedOperationException if the required coroutines framework is not on the\n * classpath or the corresponding Realm instance doesn't support flows.\n * @throws IllegalStateException if the Realm wasn't opened on a Looper thread.\n */\n@Beta\nfun <T : RealmModel> T?.toChangesetFlow(): Flow<ObjectChange<T>?> {\n    // Return flow with objectchange containing this object or null flow if this function is called on null\n    return this?.let { obj ->\n        if (obj is RealmObjectProxy) {\n            val proxy = obj as RealmObjectProxy\n            @Suppress(\"INACCESSIBLE_TYPE\")\n            when (val realm = proxy.`realmGet$proxyState`().`realm$realm`) {\n                is Realm -> realm.configuration.flowFactory.changesetFrom<T>(realm, obj)\n                is DynamicRealm -> (obj as DynamicRealmObject).let { dynamicRealmObject ->\n                    realm.configuration.flowFactory.changesetFrom(realm, dynamicRealmObject) as Flow<ObjectChange<T>?>\n                }\n                else -> throw UnsupportedOperationException(\"${realm.javaClass} is not supported as a candidate for 'toFlow'. Only subclasses of RealmModel/RealmObject can be used.\")\n            }\n\n        } else {\n            // Return a one-time emission in case the object is unmanaged\n            return flowOf(ObjectChange(this, null))\n        }\n    } ?: flowOf(null)\n}\n"
  },
  {
    "path": "realm/kotlin-extensions/src/main/kotlin/io/realm/kotlin/RealmQueryExtensions.kt",
    "content": "/*\n * Copyright 2017 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 */\npackage io.realm.kotlin\n\nimport io.realm.Case\nimport io.realm.RealmModel\nimport io.realm.RealmQuery\nimport java.util.*\n\n\n/**\n * In comparison. This allows you to test if objects match any value in an array of values.\n *\n * @param fieldName the field to compare.\n * @param values array of values to compare with. If `null` or the empty array is provided the query will never\n *               match any results.\n * @param casing how casing is handled. [Case.INSENSITIVE] works only for the Latin-1 characters.\n * @return the query object.\n * @throws java.lang.IllegalArgumentException if the field isn't a String field or `values` is `null` or\n * empty.\n */\nfun <T : RealmModel> RealmQuery<T>.oneOf(propertyName: String,\n                                         value: Array<out String?>,\n                                         casing: Case = Case.SENSITIVE): RealmQuery<T> {\n    return this.`in`(propertyName, value, casing)\n}\n\n\n/**\n * In comparison. This allows you to test if objects match any value in an array of values.\n *\n * @param fieldName the field to compare.\n * @param values array of values to compare with. If `null` or the empty array is provided the query will never\n *               match any results.\n * @return the query object.\n * @throws java.lang.IllegalArgumentException if the field isn't a Byte field.\n * empty.\n */\nfun <T : RealmModel> RealmQuery<T>.oneOf(propertyName: String,\n                                         value: Array<out Byte?>): RealmQuery<T> {\n    return this.`in`(propertyName, value)\n}\n\n/**\n * In comparison. This allows you to test if objects match any value in an array of values.\n *\n * @param fieldName the field to compare.\n * @param values array of values to compare with. If `null` or the empty array is provided the query will never\n *               match any results.\n * @return the query object.\n * @throws java.lang.IllegalArgumentException if the field isn't a Short field.\n * empty.\n */\nfun <T : RealmModel> RealmQuery<T>.oneOf(propertyName: String,\n                                         value: Array<out Short?>): RealmQuery<T> {\n    return this.`in`(propertyName, value)\n}\n\n/**\n * In comparison. This allows you to test if objects match any value in an array of values.\n *\n * @param fieldName the field to compare.\n * @param values array of values to compare with. If `null` or the empty array is provided the query will never\n *               match any results.\n * @return the query object.\n * @throws java.lang.IllegalArgumentException if the field isn't a Integer field.\n * or empty.\n */\nfun <T : RealmModel> RealmQuery<T>.oneOf(propertyName: String,\n                                         value: Array<out Int?>): RealmQuery<T> {\n    return this.`in`(propertyName, value)\n}\n\n/**\n * In comparison. This allows you to test if objects match any value in an array of values.\n *\n * @param fieldName the field to compare.\n * @param values array of values to compare with. If `null` or the empty array is provided the query will never\n *               match any results.\n * @return the query object.\n * @throws java.lang.IllegalArgumentException if the field isn't a Long field.\n * empty.\n */\nfun <T : RealmModel> RealmQuery<T>.oneOf(propertyName: String,\n                                         value: Array<out Long?>): RealmQuery<T> {\n    return this.`in`(propertyName, value)\n}\n\n/**\n * In comparison. This allows you to test if objects match any value in an array of values.\n *\n * @param fieldName the field to compare.\n * @param values array of values to compare with. If `null` or the empty array is provided the query will never\n *               match any results.\n * @return the query object.\n * @throws java.lang.IllegalArgumentException if the field isn't a Double field.\n * empty.\n */\nfun <T : RealmModel> RealmQuery<T>.oneOf(propertyName: String,\n                                         value: Array<out Double?>): RealmQuery<T> {\n    return this.`in`(propertyName, value)\n}\n\n\n/**\n * In comparison. This allows you to test if objects match any value in an array of values.\n *\n * @param fieldName the field to compare.\n * @param values array of values to compare with. If `null` or the empty array is provided the query will never\n *               match any results.\n * @return the query object.\n * @throws java.lang.IllegalArgumentException if the field isn't a Float field.\n * empty.\n */\nfun <T : RealmModel> RealmQuery<T>.oneOf(propertyName: String,\n                                         value: Array<out Float?>): RealmQuery<T> {\n    return this.`in`(propertyName, value)\n}\n\n\n/**\n * In comparison. This allows you to test if objects match any value in an array of values.\n *\n * @param fieldName the field to compare.\n * @param values array of values to compare with. If `null` or the empty array is provided the query will never\n *               match any results.\n * @return the query object.\n * @throws java.lang.IllegalArgumentException if the field isn't a Boolean field.\n * or empty.\n */\nfun <T : RealmModel> RealmQuery<T>.oneOf(propertyName: String,\n                                         value: Array<out Boolean?>): RealmQuery<T> {\n    return this.`in`(propertyName, value)\n}\n\n/**\n * In comparison. This allows you to test if objects match any value in an array of values.\n *\n * @param fieldName the field to compare.\n * @param values array of values to compare with. If `null` or the empty array is provided the query will never\n *               match any results.\n * @return the query object.\n * @throws java.lang.IllegalArgumentException if the field isn't a Date field.\n * empty.\n */\nfun <T : RealmModel> RealmQuery<T>.oneOf(propertyName: String,\n                                         value: Array<out Date?>): RealmQuery<T> {\n    return this.`in`(propertyName, value)\n}\n"
  },
  {
    "path": "realm/kotlin-extensions/src/main/kotlin/io/realm/kotlin/RealmResultsExtensions.kt",
    "content": "/*\n * Copyright 2020 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\npackage io.realm.kotlin\n\nimport io.realm.*\nimport io.realm.annotations.Beta\nimport io.realm.rx.CollectionChange\nimport kotlinx.coroutines.flow.Flow\n\n/**\n * Returns a [Flow] that monitors changes to this RealmResults. It will emit the current\n * RealmResults when subscribed to. RealmResults will continually be emitted as the RealmResults are\n * updated - `onCompletion` will never be called.\n *\n * Items emitted from Realm flows are frozen - see [RealmResults.freeze]. This means that they are\n * immutable and can be read from any thread.\n *\n * Realm flows always emit items from the thread holding the live RealmResults. This means that if\n * you need to do further processing, it is recommended to collect the values on a computation\n * dispatcher:\n *\n * ```\n * realmInstance.where(Foo::class.java)\n *   .findAllAsync()\n *   .toFlow()\n *   .map { results -> doExpensiveWork(results) }\n *   .flowOn(Dispatchers.IO)\n *   .onEach { flowResults ->\n *     // ...\n *   }.launchIn(Dispatchers.Main)\n * ```\n *\n * If your would like `toFlow()` to stop emitting items you can instruct the flow to only emit the\n * first item by calling [kotlinx.coroutines.flow.first]:\n * ```\n * val foo = realmInstance.where(Foo::class.java)\n *   .findAllAsync()\n *   .toFlow()\n *   .flowOn(context)\n *   .first()\n * ```\n *\n * @return Kotlin [Flow] on which calls to `onEach` or `collect` can be made.\n */\n@Beta\nfun <T : RealmModel> RealmResults<T>.toFlow(): Flow<RealmResults<T>> {\n    @Suppress(\"INACCESSIBLE_TYPE\")\n    return when (val realmInstance = baseRealm) {\n        is Realm -> realmInstance.configuration.flowFactory.from(realmInstance, this)\n        is DynamicRealm -> realmInstance.configuration.flowFactory.from(realmInstance, this)\n        else -> throw IllegalStateException(\"Wrong type of Realm.\")\n    }\n}\n\n/**\n * Returns a [Flow] that monitors changes to this RealmResults. It will emit the current\n * RealmResults upon subscription. For each update to the RealmResults a [CollectionChange]\n * consisting of a pair with the RealmResults and its corresponding [OrderedCollectionChangeSet]\n * will be sent. The changeset will be `null` the first time the RealmResults is emitted.\n *\n * The RealmResults will continually be emitted as they are updated. This flow will never complete.\n *\n * Items emitted are frozen (see [RealmResults.freeze]). This means that they are immutable and can\n * be read on any thread.\n *\n * Realm flows always emit items from the thread holding the live Realm. This means that if\n * you need to do further processing, it is recommended to collect the values on a computation\n * dispatcher:\n *\n * ```\n * results.toChangesetFlow()\n *   .map { change -> doExpensiveWork(change) }\n *   .flowOn(Dispatchers.IO)\n *   .onEach { change ->\n *     // ...\n *   }.launchIn(Dispatchers.Main)\n * ```\n *\n * If you would like `toChangesetFlow()` to stop emitting items you can instruct the flow to only\n * emit the first item by calling [kotlinx.coroutines.flow.first]:\n * ```\n * val foo = results.toChangesetFlow()\n *   .flowOn(context)\n *   .first()\n * ```\n *\n * @return Kotlin [Flow] that will never complete.\n * @throws UnsupportedOperationException if the required coroutines framework is not on the\n * classpath or the corresponding Realm instance doesn't support flows.\n * @throws IllegalStateException if the Realm wasn't opened on a Looper thread.\n */\n@Beta\nfun <T : RealmModel> RealmResults<T>.toChangesetFlow(): Flow<CollectionChange<RealmResults<T>>> {\n    @Suppress(\"INACCESSIBLE_TYPE\")\n    return when (val realmInstance = baseRealm) {\n        is Realm -> realmInstance.configuration.flowFactory.changesetFrom(realmInstance, this)\n        is DynamicRealm -> realmInstance.configuration.flowFactory.changesetFrom(realmInstance, this)\n        else -> throw IllegalStateException(\"Wrong type of Realm.\")\n    }\n}\n"
  },
  {
    "path": "realm/kotlin-extensions/src/objectServer/kotlin/io/realm/kotlin/SyncedRealmExtensions.kt",
    "content": "/*\n * Copyright 2018 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 */\npackage io.realm.kotlin\n\nimport io.realm.Realm\nimport io.realm.mongodb.sync.SyncConfiguration\nimport io.realm.mongodb.sync.SyncSession\n\n\n/**\n * Returns the [SyncSession] associated with this Realm.\n *\n * @return the [SyncSession] associated with this Realm.\n * @throws IllegalStateException if the Realm is not a synchronized Realm.\n */\nval Realm.syncSession: SyncSession\n    get() {\n        if (!(this.configuration is SyncConfiguration)) {\n            throw IllegalStateException(\"This method is only available on synchronized Realms\")\n        }\n\n        val syncConfig = this.configuration as SyncConfiguration\n        return syncConfig.user.app.sync.getSession(syncConfig)\n    }\n"
  },
  {
    "path": "realm/realm-annotations-processor/build.gradle",
    "content": "apply plugin: 'kotlin'\napply plugin: 'maven-publish'\n\nsourceCompatibility = JavaVersion.VERSION_1_8\ntargetCompatibility = JavaVersion.VERSION_1_8\n\ndef properties = new Properties()\nproperties.load(new FileInputStream(\"${projectDir}/../../dependencies.list\"))\n\ndependencies {\n    implementation \"com.squareup:javawriter:2.5.1\"\n    implementation \"io.realm:realm-annotations:${version}\"\n    implementation \"org.mongodb:bson:${properties.getProperty('BSON_DEPENDENCY')}\"\n    implementation \"org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version\"\n    testImplementation files('../realm-library/build/intermediates/aar_main_jar/baseRelease/classes.jar') // Java projects cannot depend on AAR files\n    testImplementation group:'junit', name:'junit', version:'4.13.1'\n    testImplementation group:'com.google.testing.compile', name:'compile-testing', version:'0.21.0'\n    testImplementation files(file(\"${System.env.ANDROID_HOME}/platforms/android-29/android.jar\"))\n}\n\n// for Ant filter\nimport org.apache.tools.ant.filters.ReplaceTokens\nimport org.gradle.internal.jvm.Jvm\n\ntask generateVersionClass(type: Copy) {\n    from 'src/main/templates/Version.java'\n    into 'build/generated-src/main/java/io/realm/processor'\n    filter(ReplaceTokens, tokens: [version: version])\n    outputs.upToDateWhen { false }\n}\n\n// Include the generated Version file\nsourceSets {\n    main {\n        java {\n            srcDir 'build/generated-src/main/java'\n        }\n    }\n}\n\ncompileKotlin.dependsOn generateVersionClass\ncompileTestJava.dependsOn ':realm-library:assembleBaseRelease'\n\napply from: \"${rootDir}/../mavencentral-publications.gradle\"\n\npublishing {\n    publications {\n        basePublication(MavenPublication) {\n            groupId 'io.realm'\n            artifactId = 'realm-annotations-processor'\n            from components.java\n            populatePom(\n                it,\n                'realm-annotations-processor',\n                'Annotation Processor for Realm. Realm is a mobile database: Build better apps, faster.'\n            )\n        }\n    }\n}\n\njava {\n    withSourcesJar()\n    withJavadocJar()\n}\n\ncompileKotlin {\n    kotlinOptions {\n        jvmTarget = JavaVersion.VERSION_1_8\n        freeCompilerArgs += [\"-XXLanguage:+InlineClasses\"]\n    }\n}\n\ncompileTestKotlin {\n    kotlinOptions {\n        jvmTarget = JavaVersion.VERSION_1_8\n    }\n}\n\ntasks.withType(JavaCompile) {\n    options.encoding = \"UTF-8\"\n}\ntasks.withType(Test) {\n    systemProperty \"file.encoding\", \"UTF-8\"\n    // Work-around for https://github.com/google/compile-testing/issues/222\n    jvmArgs(\n        \"--add-opens=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED\",\n        \"--add-opens=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED\",\n        \"--add-opens=jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED\",\n\n    )\n}\n"
  },
  {
    "path": "realm/realm-annotations-processor/src/main/java/io/realm/processor/Backlink.kt",
    "content": "/*\n * Copyright 2019 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\npackage io.realm.processor\n\nimport java.util.Locale\n\nimport javax.lang.model.element.Modifier\nimport javax.lang.model.element.VariableElement\n\nimport io.realm.annotations.LinkingObjects\nimport io.realm.annotations.Required\n\n/**\n * A **Backlink** is an implicit backwards reference.  If field `sourceField` in instance `I`\n * of type `SourceClass` holds a reference to instance `J` of type `TargetClass`,\n * then a \"backlink\" is the automatically created reference from `J` to `I`.\n *\n * Backlinks are automatically created and destroyed when the forward references to which they\n * correspond are created and destroyed.  This can dramatically reduce the complexity of client\n * code.\n *\n * To expose backlinks for use, create a declaration as follows:\n *\n * ```\n * // For Normal top-level objects\n * class TargetClass {\n *   // ...\n *   @LinkingObjects(\"sourceField\")\n *   final RealmResults<SourceClass> targetField = null;\n * }\n *\n * // If the class is an embedded object, we know there is always one parent, so\n * // backlinks in this case can also be defined this way:\n * class TargetClass {\n *   // ...\n *   @LinkingObjects(\"sourceField\")\n *   final SourceClass targetField;\n * }\n *\n *```\n *\n * The `targetField`, the field annotated with the @LinkingObjects annotation must be final.\n * Its type must be `RealmResults` whose generic argument is the `SourceClass`, the class with the\n * `sourceField` that will hold the forward reference to an instance of `TargetClass`\n *\n * The `sourceField` must be either of type `TargetClass`  or `RealmList<TargetClass>`\n *\n * In the code link direction is from the perspective of the link, not the backlink: the source is\n * the instance to which the backlink points, the target is the instance holding the pointer.\n * This is consistent with the use of terms in the Realm Core.\n *\n * As should be obvious, from the declaration, backlinks are useful only on managed objects.\n * An unmanaged Model object will have, as the value of its backlink field, the value with which\n * the field is initialized (typically null).\n */\nclass Backlink(private val clazz: ClassMetaData, private val backlinkField: VariableElement) {\n\n    /**\n     * The fully-qualified name of the class containing the `targetField`, which is the field\n     * annotated with the @LinkingObjects annotation.\n     */\n    val targetClass: QualifiedClassName = clazz.qualifiedClassName\n\n    /**\n     * The name of the backlink field, in `targetClass`.\n     * A `RealmResults<>` field annotated with a @LinkingObjects annotation.\n     */\n    val targetField: String = backlinkField.simpleName.toString()\n\n    /**\n     * The fully-qualified name of the class to which the backlinks, from `targetField`, point.\n     */\n    val sourceClass: QualifiedClassName? = if (Utils.isRealmResults(backlinkField)) Utils.getRealmResultsType(backlinkField) else Utils.getModelClassQualifiedName(backlinkField)\n\n    /**\n     * The name of the field, in `SourceClass` that has a normal link to `targetClass`.\n     * Making this field, in an instance I of `SourceClass`, a reference to an instance J of\n     * `TargetClass` will cause the `targetField` of J to contain a backlink to I.\n     */\n    val sourceField: String? = backlinkField.getAnnotation(LinkingObjects::class.java)?.value\n\n    /**\n     * {@code true} if the parent link should be modeled as a RealmResults instead of a single link.\n     * Single links are only supported in classes that are embedded.\n     */\n    val exposeAsRealmResults: Boolean = Utils.isRealmResults(backlinkField)\n\n    val targetFieldType: String = backlinkField.asType().toString()\n\n    /**\n     * Validate the source side of the backlink.\n     *\n     * @return true if the backlink source looks good.\n     */\n    fun validateSource(): Boolean {\n        // The annotation must have an argument, identifying the linked field.\n        if (sourceField == null || sourceField == \"\") {\n            Utils.error(String.format(\n                    Locale.US,\n                    \"The @LinkingObjects annotation for the field \\\"%s.%s\\\" must have a parameter identifying the link target.\",\n                    targetClass,\n                    targetField))\n            return false\n        }\n\n        // Using link syntax to try to reference a linked field is not possible.\n        if (sourceField.contains(\".\")) {\n            Utils.error(String.format(\n                    Locale.US,\n                    \"The parameter to the @LinkingObjects annotation for the field \\\"%s.%s\\\" contains a '.'.  The use of '.' to specify fields in referenced classes is not supported.\",\n                    targetClass,\n                    targetField))\n            return false\n        }\n\n        if (Utils.isRealmResults(backlinkField)) {\n            return validateBacklinksAsRealmResults(backlinkField)\n        } else {\n            return validateBacklinkAsObjectReference(backlinkField)\n        }\n    }\n\n    private fun validateBacklinkAsObjectReference(field: VariableElement): Boolean {\n\n        // Using @LinkingObjects as a single parent reference is only allowed in embedded classes\n        if (!clazz.embedded && !Utils.isRealmResults(backlinkField)) {\n            Utils.error(String.format(\n                    Locale.US,\n                    \"The field \\\"%s.%s\\\" is a \\\"%s\\\". Fields annotated with @LinkingObjects must be RealmResults.\",\n                    targetClass,\n                    targetField,\n                    backlinkField.asType()))\n            return false\n        }\n\n        // A @LinkingObjects can only be required if for the class being embedded there is\n        // only one @LinkingField field defined. And even in that case, it requires runtime\n        // schema validation since we need to know if only one other type is pointing to it.\n        // If multiple types point to it, we cannot keep the contract of @Required.\n        if (field.getAnnotation(Required::class.java) != null && clazz.backlinkFields.isNotEmpty()) {\n            Utils.error(String.format(\n                    Locale.US,\n                    \"@Required cannot be used on @LinkingObjects field if multiple @LinkingParents are defined: \\\"%s.%s\\\".\",\n                    targetClass,\n                    targetField))\n            return false\n        }\n\n        // A @LinkingObjects field must be final.\n        if (!field.modifiers.contains(Modifier.FINAL)) {\n            Utils.error(String.format(\n                    Locale.US,\n                    \"The @LinkingObjects field \\\"%s.%s\\\" must be final.\",\n                    targetClass,\n                    targetField))\n            return false\n        }\n\n        return true\n    }\n\n    private fun validateBacklinksAsRealmResults(field: VariableElement): Boolean {\n        // A @LinkingObjects on a RealmResults cannot be @Required as doesn't have any\n        // meaning.\n        if (field.getAnnotation(Required::class.java) != null) {\n            Utils.error(String.format(\n                    Locale.US,\n                    \"The @LinkingObjects field \\\"%s.%s\\\" cannot be @Required.\",\n                    targetClass,\n                    targetField))\n            return false\n        }\n\n        if (sourceClass == null) {\n            Utils.error(String.format(\n                    Locale.US,\n                    \"\\\"The field \\\"%s.%s\\\", annotated with @LinkingObjects, must specify a generic type.\",\n                    targetClass,\n                    targetField))\n            return false\n        }\n\n        // A @LinkingObjects field must be final.\n        if (!backlinkField.modifiers.contains(Modifier.FINAL)) {\n            Utils.error(String.format(\n                    Locale.US,\n                    \"A @LinkingObjects field \\\"%s.%s\\\" must be final.\",\n                    targetClass,\n                    targetField))\n            return false\n        }\n\n        return true\n    }\n\n    fun validateTarget(clazz: ClassMetaData): Boolean {\n        val field = clazz.getDeclaredField(sourceField)\n\n        if (field == null) {\n            Utils.error(String.format(Locale.US,\n                    \"Field \\\"%s\\\", the target of the @LinkedObjects annotation on field \\\"%s.%s\\\", does not exist in class \\\"%s\\\".\",\n                    sourceField,\n                    targetClass,\n                    targetField,\n                    sourceClass))\n            return false\n        }\n\n        val fieldType = QualifiedClassName(field.asType().toString())\n        if (!(targetClass == fieldType || targetClass == Utils.getRealmListType(field))) {\n            Utils.error(String.format(Locale.US,\n                    \"Field \\\"%s.%s\\\", the target of the @LinkedObjects annotation on field \\\"%s.%s\\\", has type \\\"%s\\\" instead of \\\"%3\\$s\\\".\",\n                    sourceClass,\n                    sourceField,\n                    targetClass,\n                    targetField,\n                    fieldType))\n            return false\n        }\n\n        return true\n    }\n\n    override fun toString(): String {\n        return \"Backlink{$sourceClass.$sourceField ==> $targetClass.$targetField}\"\n    }\n\n    override fun equals(other: Any?): Boolean {\n        if (this === other) return true\n        if (javaClass != other?.javaClass) return false\n\n        other as Backlink\n\n        if (backlinkField != other.backlinkField) return false\n        if (targetClass != other.targetClass) return false\n        if (targetField != other.targetField) return false\n        if (sourceClass != other.sourceClass) return false\n        if (sourceField != other.sourceField) return false\n\n        return true\n    }\n\n    override fun hashCode(): Int {\n        var result = backlinkField.hashCode()\n        result = 31 * result + targetClass.hashCode()\n        result = 31 * result + targetField.hashCode()\n        result = 31 * result + (sourceClass?.hashCode() ?: 0)\n        result = 31 * result + sourceField.hashCode()\n        return result\n    }\n\n}\n"
  },
  {
    "path": "realm/realm-annotations-processor/src/main/java/io/realm/processor/ClassCollection.kt",
    "content": "/*\n * Copyright 2019 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 */\npackage io.realm.processor\n\nimport java.util.LinkedHashMap\nimport java.util.LinkedHashSet\n\n/**\n * Wrapper around all Realm model classes metadata found during processing. It also allows easy\n * lookup for specific class data.\n */\nclass ClassCollection {\n\n    // These three collections should always stay in sync\n    private val qualifiedNameClassMap = LinkedHashMap<QualifiedClassName, ClassMetaData>()\n    private val classSet = LinkedHashSet<ClassMetaData>()\n    val classes: Set<ClassMetaData>\n        get() = classSet.toSet()\n\n    fun addClass(metadata: ClassMetaData) {\n        classSet.add(metadata)\n        qualifiedNameClassMap[metadata.qualifiedClassName] = metadata\n    }\n\n    fun getClassFromQualifiedName(className: QualifiedClassName): ClassMetaData {\n        return qualifiedNameClassMap[className]\n                ?: throw IllegalArgumentException(\"Class $className was not found\")\n    }\n\n    fun getClassFromQualifiedNameOrNull(className: QualifiedClassName): ClassMetaData? {\n        return qualifiedNameClassMap[className]\n    }\n\n    fun size(): Int {\n        return classSet.size\n    }\n\n    fun containsQualifiedClass(qualifiedClassName: QualifiedClassName?): Boolean {\n        return qualifiedNameClassMap.containsKey(qualifiedClassName)\n    }\n}\n"
  },
  {
    "path": "realm/realm-annotations-processor/src/main/java/io/realm/processor/ClassMetaData.kt",
    "content": "/*\n * Copyright 2019 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\npackage io.realm.processor\n\nimport io.realm.annotations.*\nimport io.realm.processor.nameconverter.NameConverter\nimport java.util.*\nimport javax.annotation.processing.ProcessingEnvironment\nimport javax.lang.model.element.*\nimport javax.lang.model.type.DeclaredType\nimport javax.lang.model.type.TypeKind\nimport javax.lang.model.type.TypeMirror\nimport javax.lang.model.util.Elements\nimport javax.lang.model.util.Types\n\n/**\n * Utility class for holding metadata for RealmProxy classes.\n */\nclass ClassMetaData(env: ProcessingEnvironment, typeMirrors: TypeMirrors, private val classType: TypeElement /* Reference to model class. */) {\n\n    val simpleJavaClassName = SimpleClassName(classType.simpleName) // Model class simple name as defined in Java.\n    val fields = ArrayList<RealmFieldElement>() // List of all fields in the class except those @Ignored.\n    private val indexedFields = ArrayList<RealmFieldElement>() // list of all fields marked @Index.\n    private val _objectReferenceFields = ArrayList<RealmFieldElement>() // List of all fields that reference a Realm Object either directly or in a List\n    private val basicTypeFields = ArrayList<RealmFieldElement>() // List of all fields that reference basic types, i.e. no references to other Realm Objects\n    private val backlinks = LinkedHashSet<Backlink>()\n    private val nullableFields = LinkedHashSet<RealmFieldElement>() // Set of fields which can be nullable\n    private val nullableValueListFields = LinkedHashSet<RealmFieldElement>() // Set of fields whose elements can be nullable\n    private val nullableValueMapFields = LinkedHashSet<RealmFieldElement>() // Set of fields whose elements can be nullable\n    private val nullableValueSetFields = LinkedHashSet<RealmFieldElement>() // Set of fields whose elements can be nullable\n    private val realmModelSets = LinkedHashSet<RealmFieldElement>()\n\n    // package name for model class.\n    private lateinit var packageName: String\n\n    // True if model has a public no-arg constructor.\n    private var hasDefaultConstructor: Boolean = false\n\n    // Reference to field used as primary key\n    var primaryKey: VariableElement? = null\n        private set\n\n    private var containsToString: Boolean = false\n    private var containsEquals: Boolean = false\n    private var containsHashCode: Boolean = false\n\n    // Returns the name that Realm Core uses when saving data from this Java class.\n    lateinit var internalClassName: String\n        private set\n\n    private val validPrimaryKeyTypes: List<TypeMirror> = listOf(\n            typeMirrors.STRING_MIRROR,\n            typeMirrors.PRIMITIVE_LONG_MIRROR,\n            typeMirrors.PRIMITIVE_INT_MIRROR,\n            typeMirrors.PRIMITIVE_SHORT_MIRROR,\n            typeMirrors.PRIMITIVE_BYTE_MIRROR,\n            typeMirrors.OBJECT_ID_MIRROR,\n            typeMirrors.UUID_MIRROR\n    )\n    private val validListValueTypes: List<TypeMirror> = listOf(\n            typeMirrors.STRING_MIRROR,\n            typeMirrors.BINARY_MIRROR,\n            typeMirrors.BOOLEAN_MIRROR,\n            typeMirrors.LONG_MIRROR,\n            typeMirrors.INTEGER_MIRROR,\n            typeMirrors.SHORT_MIRROR,\n            typeMirrors.BYTE_MIRROR,\n            typeMirrors.DOUBLE_MIRROR,\n            typeMirrors.FLOAT_MIRROR,\n            typeMirrors.DATE_MIRROR,\n            typeMirrors.DECIMAL128_MIRROR,\n            typeMirrors.OBJECT_ID_MIRROR,\n            typeMirrors.UUID_MIRROR,\n            typeMirrors.MIXED_MIRROR\n    )\n    private val validDictionaryTypes: List<TypeMirror> = listOf(\n            typeMirrors.STRING_MIRROR,\n            typeMirrors.BINARY_MIRROR,\n            typeMirrors.BOOLEAN_MIRROR,\n            typeMirrors.LONG_MIRROR,\n            typeMirrors.INTEGER_MIRROR,\n            typeMirrors.SHORT_MIRROR,\n            typeMirrors.BYTE_MIRROR,\n            typeMirrors.DOUBLE_MIRROR,\n            typeMirrors.FLOAT_MIRROR,\n            typeMirrors.DATE_MIRROR,\n            typeMirrors.DECIMAL128_MIRROR,\n            typeMirrors.OBJECT_ID_MIRROR,\n            typeMirrors.UUID_MIRROR,\n            typeMirrors.MIXED_MIRROR\n    )\n    private val validSetTypes: List<TypeMirror>  = listOf(\n            typeMirrors.STRING_MIRROR,\n            typeMirrors.BINARY_MIRROR,\n            typeMirrors.BOOLEAN_MIRROR,\n            typeMirrors.LONG_MIRROR,\n            typeMirrors.INTEGER_MIRROR,\n            typeMirrors.SHORT_MIRROR,\n            typeMirrors.BYTE_MIRROR,\n            typeMirrors.DOUBLE_MIRROR,\n            typeMirrors.FLOAT_MIRROR,\n            typeMirrors.DATE_MIRROR,\n            typeMirrors.DECIMAL128_MIRROR,\n            typeMirrors.OBJECT_ID_MIRROR,\n            typeMirrors.UUID_MIRROR,\n            typeMirrors.MIXED_MIRROR\n    )\n    private val stringType = typeMirrors.STRING_MIRROR\n\n    private val typeUtils: Types = env.typeUtils\n    private val elements: Elements = env.elementUtils\n    private lateinit var defaultFieldNameFormatter: NameConverter\n\n    private val ignoreKotlinNullability: Boolean\n\n    val qualifiedClassName: QualifiedClassName\n        get() = QualifiedClassName(\"$packageName.$simpleJavaClassName\")\n\n    val backlinkFields: Set<Backlink>\n        get() = backlinks.toSet()\n\n    val primaryKeyGetter: String\n        get() = getInternalGetter(primaryKey!!.simpleName.toString())\n\n    val realmModelSetFields: Set<RealmFieldElement>\n        get() = realmModelSets.toSet()\n\n    /**\n     * Returns `true if the class is considered to be a valid RealmObject class.\n     * RealmObject and Proxy classes also have the @RealmClass annotation but are not considered valid\n     * RealmObject classes.\n     */\n    val isModelClass: Boolean\n        get() {\n            val type = classType.toString()\n            return type != \"io.realm.DynamicRealmObject\" && !type.endsWith(\".RealmObject\") && !type.endsWith(\"RealmProxy\")\n        }\n\n    var embedded: Boolean = false\n        private set\n\n    val classElement: Element\n        get() = classType\n\n    init {\n        for (element in classType.enclosedElements) {\n            if (element is ExecutableElement) {\n                val name = element.getSimpleName()\n                when {\n                    name.contentEquals(\"toString\") -> this.containsToString = true\n                    name.contentEquals(\"equals\") -> this.containsEquals = true\n                    name.contentEquals(\"hashCode\") -> this.containsHashCode = true\n                }\n            }\n        }\n\n        ignoreKotlinNullability = java.lang.Boolean.valueOf(\n                (env.options as MutableMap<String, String>).getOrDefault(OPTION_IGNORE_KOTLIN_NULLABILITY, \"false\"))\n    }\n\n    override fun toString(): String {\n        return \"class $qualifiedClassName\"\n    }\n\n    /**\n     * Returns the internal field name that matches the one in the Java model class.\n     */\n    fun getInternalFieldName(javaFieldName: String): String {\n        for (field in fields) {\n            if (field.javaName == javaFieldName) {\n                return field.internalFieldName\n            }\n        }\n        throw IllegalArgumentException(\"Could not find fieldname: $javaFieldName\")\n    }\n\n    /**\n     * Returns all persistable fields that reference other Realm objects.\n     */\n    val objectReferenceFields: List<RealmFieldElement>\n        get() = _objectReferenceFields.toList()\n\n    /**\n     * Returns all persistable fields that contain a basic type, this include lists of primitives.\n     */\n    fun getBasicTypeFields(): List<RealmFieldElement> {\n        return Collections.unmodifiableList(basicTypeFields)\n    }\n\n    fun getInternalGetter(fieldName: String): String {\n        return \"realmGet$$fieldName\"\n    }\n\n    fun getInternalSetter(fieldName: String): String {\n        return \"realmSet$$fieldName\"\n    }\n\n    fun hasPrimaryKey(): Boolean {\n        return primaryKey != null\n    }\n\n    fun containsToString(): Boolean {\n        return containsToString\n    }\n\n    fun containsEquals(): Boolean {\n        return containsEquals\n    }\n\n    fun containsHashCode(): Boolean {\n        return containsHashCode\n    }\n\n    /**\n     * Checks if a VariableElement is nullable.\n     *\n     * @return `true` if a VariableElement is nullable type, `false` otherwise.\n     */\n    fun isNullable(variableElement: VariableElement): Boolean {\n        return nullableFields.contains(variableElement)\n    }\n\n    /**\n     * Checks if the element of `RealmList` designated by `realmListVariableElement` is nullable.\n     *\n     * @return `true` if the element is nullable type, `false` otherwise.\n     */\n    fun isElementNullable(realmListVariableElement: VariableElement): Boolean {\n        return nullableValueListFields.contains(realmListVariableElement)\n    }\n\n    /**\n     * Checks if the value of a `RealmDictionary` entry designated by `realmDictionaryVariableElement` is nullable.\n     *\n     * @return `true` if the element is nullable type, `false` otherwise.\n     */\n    fun isDictionaryValueNullable(realmDictionaryVariableElement: VariableElement): Boolean {\n        return nullableValueMapFields.contains(realmDictionaryVariableElement)\n    }\n\n    /**\n     * Checks if the value of a `RealmDictionary` entry designated by `realmDictionaryVariableElement` is nullable.\n     *\n     * @return `true` if the element is nullable type, `false` otherwise.\n     */\n    fun isSetValueNullable(realmSetVariableElement: VariableElement): Boolean {\n        return nullableValueSetFields.contains(realmSetVariableElement)\n    }\n\n    /**\n     * Checks if a VariableElement is indexed.\n     *\n     * @param variableElement the element/field\n     * @return `true` if a VariableElement is indexed, `false` otherwise.\n     */\n    fun isIndexed(variableElement: VariableElement): Boolean {\n        return indexedFields.contains(variableElement)\n    }\n\n    /**\n     * Checks if a VariableElement is a primary key.\n     *\n     * @param variableElement the element/field\n     * @return `true` if a VariableElement is primary key, `false` otherwise.\n     */\n    fun isPrimaryKey(variableElement: VariableElement): Boolean {\n        return primaryKey != null && primaryKey == variableElement\n    }\n\n    /**\n     * Find the named field in this classes list of fields.\n     * This method is called only during backlink checking,\n     * so creating a map, even lazily, doesn't seem like a worthwhile optimization.\n     * If it gets used more widely, that decision should be revisited.\n     *\n     * @param fieldName The name of the sought field\n     * @return the named field's VariableElement, or null if not found\n     */\n    fun getDeclaredField(fieldName: String?): VariableElement? {\n        if (fieldName == null) {\n            return null\n        }\n        for (field in fields) {\n            if (field.simpleName.toString() == fieldName) {\n                return field\n            }\n        }\n        return null\n    }\n\n    /**\n     * Builds the meta data structures for this class. Any errors or messages will be\n     * posted on the provided Messager.\n     *\n     * @param moduleMetaData pre-processed module meta data.\n     * @return True if meta data was correctly created and processing can continue, false otherwise.\n     */\n    fun generate(moduleMetaData: ModuleMetaData): Boolean {\n        // Get the package of the class\n        val enclosingElement = classType.enclosingElement\n        if (enclosingElement.kind != ElementKind.PACKAGE) {\n            Utils.error(\"The RealmClass annotation does not support nested classes.\", classType)\n            return false\n        }\n\n        // Check if the @RealmClass is considered valid with respect to the type hierarchy\n        val parentElement = Utils.getSuperClass(classType) as TypeElement\n        if (parentElement.toString() != \"java.lang.Object\" && parentElement.toString() != \"io.realm.RealmObject\") {\n            Utils.error(\"Valid model classes must either extend RealmObject or implement RealmModel.\", classType)\n            return false\n        }\n\n        val packageElement = enclosingElement as PackageElement\n        packageName = packageElement.qualifiedName.toString()\n\n        // Determine naming rules for this class\n        val qualifiedClassName = QualifiedClassName(\"$packageName.$simpleJavaClassName\")\n        val moduleClassNameFormatter = moduleMetaData.getClassNameFormatter(qualifiedClassName)\n        defaultFieldNameFormatter = moduleMetaData.getFieldNameFormatter(qualifiedClassName)\n\n        val realmClassAnnotation = classType.getAnnotation(RealmClass::class.java)\n        // If name has been specifically set, it should override any module policy.\n        internalClassName = when {\n            realmClassAnnotation.name.isNotEmpty() -> realmClassAnnotation.name\n            realmClassAnnotation.value.isNotEmpty() -> realmClassAnnotation.value\n            else -> moduleClassNameFormatter.convert(simpleJavaClassName.toString())\n        }\n        if (internalClassName.length > MAX_CLASSNAME_LENGTH) {\n            Utils.error(String.format(Locale.US, \"Internal class name is too long. Class '%s' \" + \"is converted to '%s', which is longer than the maximum allowed of %d characters\",\n                    simpleJavaClassName, internalClassName, MAX_CLASSNAME_LENGTH))\n            return false\n        }\n\n        // If field name policy has been explicitly set, override the module field name policy\n        if (realmClassAnnotation.fieldNamingPolicy != RealmNamingPolicy.NO_POLICY) {\n            defaultFieldNameFormatter = Utils.getNameFormatter(realmClassAnnotation.fieldNamingPolicy)\n        }\n\n        embedded = realmClassAnnotation.embedded\n\n        // Categorize and check the rest of the file\n        if (!categorizeClassElements()) {\n            return false\n        }\n        if (!checkCollectionTypes()) {\n            return false\n        }\n        if (!checkDictionaryTypes()) {\n            return false\n        }\n        if (!checkSetTypes()) {\n            return false\n        }\n        if (!checkReferenceTypes()) {\n            return false\n        }\n        if (!checkDefaultConstructor()) {\n            return false\n        }\n        if (!checkForFinalFields()) {\n            return false\n        }\n        if (!checkForVolatileFields()) {\n            return false\n        }\n\n        // Meta data was successfully generated\n        return true\n    }\n\n    // Iterate through all class elements and add them to the appropriate internal data structures.\n    // Returns true if all elements could be categorized and false otherwise.\n    private fun categorizeClassElements(): Boolean {\n        for (element in classType.enclosedElements) {\n            when (element.kind) {\n                ElementKind.CONSTRUCTOR -> if (Utils.isDefaultConstructor(element)) {\n                    hasDefaultConstructor = true\n                }\n\n                ElementKind.FIELD -> if (!categorizeField(element)) {\n                    return false\n                }\n                else -> {\n                    /* Ignore */\n                }\n            }\n        }\n\n        if (fields.isEmpty()) {\n            Utils.error(String.format(Locale.US, \"Class \\\"%s\\\" must contain at least 1 persistable field.\", simpleJavaClassName))\n        }\n\n        return true\n    }\n\n    private fun checkCollectionTypes(): Boolean {\n        for (field in fields) {\n            if (Utils.isRealmList(field)) {\n                if (!checkRealmListType(field)) {\n                    return false\n                }\n            } else if (Utils.isRealmResults(field)) {\n                if (!checkRealmResultsType(field)) {\n                    return false\n                }\n            }\n        }\n\n        return true\n    }\n\n    private fun checkDictionaryTypes(): Boolean {\n        for (field in fields) {\n            if (Utils.isRealmDictionary(field)) {\n                if (!checkDictionaryValuesType(field)) {\n                    return false\n                }\n            }\n        }\n\n        return true\n    }\n\n    private fun checkSetTypes(): Boolean {\n        for (field in fields) {\n            if (Utils.isRealmSet(field)) {\n                if (!checkSetValuesType(field)) {\n                    return false\n                }\n            }\n        }\n\n        return true\n    }\n\n    private fun checkSetValuesType(field: VariableElement): Boolean {\n        // Check for missing generic (default back to Object)\n        if (Utils.getGenericTypeQualifiedName(field) == null) {\n            Utils.error(getFieldErrorSuffix(field) + \"No generic type supplied for field\", field)\n            return false\n        }\n\n        val elementTypeMirror = checkReferenceIsNotInterface(field) ?: return false\n        return checkAcceptableClass(\n                field,\n                elementTypeMirror,\n                validSetTypes,\n                \"Element type RealmSet must be of type 'RealmAny' or any type that can be boxed inside 'RealmAny': \"\n        )\n    }\n\n    private fun checkDictionaryValuesType(field: VariableElement): Boolean {\n        // Check for missing generic (default back to Object)\n        if (Utils.getGenericTypeQualifiedName(field) == null) {\n            Utils.error(getFieldErrorSuffix(field) + \"No generic type supplied for field\", field)\n            return false\n        }\n\n        val elementTypeMirror = checkReferenceIsNotInterface(field) ?: return false\n        return checkAcceptableClass(\n                field,\n                elementTypeMirror,\n                validDictionaryTypes,\n                \"Element type RealmDictionary must be of type 'RealmAny' or any type that can be boxed inside 'RealmAny': \"\n        )\n    }\n\n    private fun checkRealmListType(field: VariableElement): Boolean {\n        // Check for missing generic (default back to Object)\n        if (Utils.getGenericTypeQualifiedName(field) == null) {\n            Utils.error(getFieldErrorSuffix(field) + \"No generic type supplied for field\", field)\n            return false\n        }\n\n        val elementTypeMirror = checkReferenceIsNotInterface(field) ?: return false\n        return checkAcceptableClass(\n                field,\n                elementTypeMirror,\n                validListValueTypes,\n                \"Element type of RealmList must be a class implementing 'RealmModel' or one of \"\n        )\n    }\n\n    private fun checkAcceptableClass(\n            field: VariableElement,\n            elementTypeMirror: TypeMirror,\n            validTypes: List<TypeMirror>,\n            specificFieldTypeMessage: String\n    ): Boolean {\n        // Check if the actual value class is acceptable\n        if (!containsType(validTypes, elementTypeMirror) && !Utils.isRealmModel(elementTypeMirror)) {\n            val messageBuilder = StringBuilder(getFieldErrorSuffix(field) + \"Type was '$elementTypeMirror'. $specificFieldTypeMessage\")\n            val separator = \", \"\n            for (type in validTypes) {\n                messageBuilder.append('\\'').append(type.toString()).append('\\'').append(separator)\n            }\n            messageBuilder.setLength(messageBuilder.length - separator.length)\n            messageBuilder.append('.')\n            Utils.error(messageBuilder.toString(), field)\n            return false\n        }\n        return true\n    }\n\n    private fun checkReferenceIsNotInterface(field: VariableElement): TypeMirror? {\n        // Check that the referenced type is a concrete class and not an interface\n        val fieldType = field.asType()\n        val elementTypeMirror: TypeMirror = (fieldType as DeclaredType).typeArguments[0]\n        if (elementTypeMirror.kind == TypeKind.DECLARED /* class of interface*/) {\n            val elementTypeElement = (elementTypeMirror as DeclaredType).asElement() as TypeElement\n            if (elementTypeElement.superclass.kind == TypeKind.NONE) {\n                Utils.error(\n                        getFieldErrorSuffix(field) + \"Only concrete Realm classes are allowed in field '$field'. \"\n                                + \"Neither interfaces nor abstract classes are allowed.\",\n                        field)\n                return null\n            }\n        }\n        return elementTypeMirror\n    }\n\n    private fun checkRealmResultsType(field: VariableElement): Boolean {\n        // Only classes implementing RealmModel are allowed since RealmResults field is used only for backlinks.\n\n        // Check for missing generic (default back to Object)\n        if (Utils.getGenericTypeQualifiedName(field) == null) {\n            Utils.error(getFieldErrorSuffix(field) + \"No generic type supplied for field\", field)\n            return false\n        }\n\n        val fieldType = field.asType()\n        val elementTypeMirror = (fieldType as DeclaredType).typeArguments[0]\n        if (elementTypeMirror.kind == TypeKind.DECLARED /* class or interface*/) {\n            val elementTypeElement = (elementTypeMirror as DeclaredType).asElement() as TypeElement\n            if (elementTypeElement.superclass.kind == TypeKind.NONE) {\n                Utils.error(\n                        (\"Only concrete Realm classes are allowed in RealmResults. \" + \"Neither interfaces nor abstract classes are allowed.\"),\n                        field)\n                return false\n            }\n        }\n\n        // Check if the actual value class is acceptable\n        if (!Utils.isRealmModel(elementTypeMirror)) {\n            Utils.error(getFieldErrorSuffix(field) + \"Element type of RealmResults must be a class implementing 'RealmModel'.\", field)\n            return false\n        }\n\n        return true\n    }\n\n    private fun getFieldErrorSuffix(field: VariableElement): String {\n        return \"$simpleJavaClassName.${field.simpleName}: \"\n    }\n\n    private fun checkReferenceTypes(): Boolean {\n        for (field in fields) {\n            if (Utils.isRealmModel(field)) {\n                // Check that the referenced type is a concrete class and not an interface\n                val typeElement = elements.getTypeElement(field.asType().toString())\n                if (typeElement.superclass.kind == TypeKind.NONE) {\n                    Utils.error(\n                            (\"Only concrete Realm classes can be referenced from model classes. \" + \"Neither interfaces nor abstract classes are allowed.\"),\n                            field)\n                    return false\n                }\n            }\n        }\n\n        return true\n    }\n\n    // Report if the default constructor is missing\n    private fun checkDefaultConstructor(): Boolean {\n        return if (!hasDefaultConstructor) {\n            Utils.error(String.format(Locale.US,\n                    \"Class \\\"%s\\\" must declare a public constructor with no arguments if it contains custom constructors.\",\n                    simpleJavaClassName))\n            false\n        } else {\n            true\n        }\n    }\n\n    private fun checkForFinalFields(): Boolean {\n        for (field in fields) {\n            if (!field.modifiers.contains(Modifier.FINAL)) {\n                continue\n            }\n            if (Utils.isRealmList(field) ||\n                    Utils.isMutableRealmInteger(field) ||\n                    Utils.isRealmDictionary(field) ||\n                    Utils.isRealmSet(field)) {\n                continue\n            }\n\n            Utils.error(String.format(Locale.US, \"Class \\\"%s\\\" contains illegal final/immutable field \\\"%s\\\".\", simpleJavaClassName,\n                    field.simpleName.toString()))\n\n            return false\n        }\n        return true\n    }\n\n    private fun checkForVolatileFields(): Boolean {\n        for (field in fields) {\n            if (field.modifiers.contains(Modifier.VOLATILE)) {\n                Utils.error(String.format(Locale.US,\n                        \"Class \\\"%s\\\" contains illegal volatile field \\\"%s\\\".\",\n                        simpleJavaClassName,\n                        field.simpleName.toString()))\n                return false\n            }\n        }\n        return true\n    }\n\n    private fun categorizeField(element: Element): Boolean {\n        val fieldRef = element as VariableElement\n\n        // completely ignore any static fields\n        if (fieldRef.modifiers.contains(Modifier.STATIC)) {\n            return true\n        }\n\n        // Ignore fields marked with @Ignore or if they are transient\n        if (fieldRef.getAnnotation(Ignore::class.java) != null || fieldRef.modifiers.contains(Modifier.TRANSIENT)) {\n            return true\n        }\n\n        // Determine name for field\n        val internalFieldName = getInternalFieldName(fieldRef, defaultFieldNameFormatter)\n        val field = RealmFieldElement(fieldRef, internalFieldName)\n\n        if (field.getAnnotation(Index::class.java) != null) {\n            if (!categorizeIndexField(element, field)) {\n                return false\n            }\n        }\n\n        // @Required annotation of RealmList and RealmDictionary field only affects its value type, not field itself.\n        if (Utils.isRealmList(field)) {\n            val hasRequiredAnnotation = hasRequiredAnnotation(field)\n            val listGenericType = (field.asType() as DeclaredType).typeArguments\n            val containsRealmModelClasses = (listGenericType.isNotEmpty() && Utils.isRealmModel(listGenericType[0]))\n            val containsRealmAny = (listGenericType.isNotEmpty() && Utils.isRealmAny(listGenericType[0]))\n\n            // @Required not allowed if the list contains Realm model classes\n            if (hasRequiredAnnotation && (containsRealmModelClasses || containsRealmAny)) {\n                Utils.error(\"@Required not allowed on RealmList's that contain other Realm model classes or RealmAny.\")\n                return false\n            }\n\n            // @Required thus only makes sense for RealmLists with primitive types\n            // We only check @Required annotation. @org.jetbrains.annotations.NotNull annotation should not affect nullability of the list values.\n            if (!hasRequiredAnnotation) {\n                if (!containsRealmModelClasses) {\n                    nullableValueListFields.add(field)\n                }\n            }\n        } else if (Utils.isRealmDictionary(field)) {\n            // Same as RealmList\n            val hasRequiredAnnotation = hasRequiredAnnotation(field)\n            val listGenericType = (field.asType() as DeclaredType).typeArguments\n            val containsRealmModelClasses = (listGenericType.isNotEmpty() && Utils.isRealmModel(listGenericType[0]))\n            val containsRealmAny = (listGenericType.isNotEmpty() && Utils.isRealmAny(listGenericType[0]))\n\n            // @Required not allowed if the dictionary contains Realm model classes or RealmAny\n            if (hasRequiredAnnotation && (containsRealmModelClasses || containsRealmAny)) {\n                Utils.error(\"@Required not allowed on RealmDictionaries that contain other Realm model classes and RealmAny.\")\n                return false\n            }\n\n            // @Required thus only makes sense for RealmDictionaries with primitive types\n            // We only check @Required annotation. @org.jetbrains.annotations.NotNull annotation should not affect nullability of the list values.\n            if (!hasRequiredAnnotation) {\n                if (!containsRealmModelClasses) {\n                    nullableValueMapFields.add(field)\n                }\n            }\n        } else if (Utils.isRealmSet(field)) {\n            // Same as RealmList\n            val hasRequiredAnnotation = hasRequiredAnnotation(field)\n            val setGenericType = (field.asType() as DeclaredType).typeArguments\n            val containsRealmModelClasses = (setGenericType.isNotEmpty() && Utils.isRealmModel(setGenericType[0]))\n            val containsRealmAny = (setGenericType.isNotEmpty() && Utils.isRealmAny(setGenericType[0]))\n\n            // @Required not allowed if the set contains Realm model classes or RealmAny\n            if (hasRequiredAnnotation && (containsRealmModelClasses || containsRealmAny)) {\n                Utils.error(\"@Required not allowed on RealmSets that contain other Realm model classes and RealmAny.\")\n                return false\n            }\n\n            // @Required thus only makes sense for RealmSets with primitive types\n            // We only check @Required annotation. @org.jetbrains.annotations.NotNull annotation should not affect nullability of the list values.\n            if (!hasRequiredAnnotation) {\n                if (!containsRealmModelClasses) {\n                    nullableValueSetFields.add(field)\n                }\n            }\n\n            if (containsRealmModelClasses) {\n                realmModelSets.add(field)\n            }\n        } else if (isRequiredField(field)) {\n            if (!checkBasicRequiredAnnotationUsage(field)) {\n                return false\n            }\n        } else {\n            // The field doesn't have the @Required and @org.jetbrains.annotations.NotNull annotation.\n            // Without @Required annotation, boxed types/RealmObject/Date/String/bytes should be added to\n            // nullableFields.\n            // RealmList of models, RealmResults(backlinks) and primitive types are NOT nullable. @Required annotation is not supported.\n            if (!Utils.isPrimitiveType(field) && !Utils.isRealmResults(field)) {\n                nullableFields.add(field)\n            }\n        }\n\n        if (field.getAnnotation(PrimaryKey::class.java) != null) {\n            if (!categorizePrimaryKeyField(field)) {\n                return false\n            }\n        }\n\n        // @LinkingObjects cannot be @PrimaryKey or @Index.\n        if (field.getAnnotation(LinkingObjects::class.java) != null) {\n            // Do not add backlinks to fields list.\n            return categorizeBacklinkField(field)\n        }\n\n        // Similarly, a MutableRealmInteger cannot be a @PrimaryKey or @LinkingObject.\n        if (Utils.isMutableRealmInteger(field)) {\n            if (!categorizeMutableRealmIntegerField(field)) {\n                return false\n            }\n        }\n\n        // Standard field that appears to be valid (more fine grained checks might fail later).\n        fields.add(field)\n        if (Utils.isRealmModel(field) ||\n                Utils.isRealmModelList(field) ||\n                Utils.isRealmAnyList(field) ||\n                Utils.isRealmAny(field) ||\n                Utils.isRealmModelDictionary(field) ||\n                Utils.isRealmModelSet(field) ||\n                Utils.isRealmAnyDictionary(field)||\n                Utils.isRealmAnySet(field)) {\n            _objectReferenceFields.add(field)\n        } else {\n            basicTypeFields.add(field)\n        }\n\n        return true\n    }\n\n    private fun getInternalFieldName(field: VariableElement, defaultConverter: NameConverter): String {\n        val nameAnnotation: RealmField? = field.getAnnotation(RealmField::class.java)\n        if (nameAnnotation != null) {\n            if (nameAnnotation.name.isNotEmpty()) {\n                return nameAnnotation.name\n            }\n            if (nameAnnotation.value.isNotEmpty()) {\n                return nameAnnotation.value\n            }\n            Utils.note(String.format((\"Empty internal name defined on @RealmField. \" + \"Falling back to named used by Java model class: %s\"), field.simpleName), field)\n            return field.simpleName.toString()\n        } else {\n            return defaultConverter.convert(field.simpleName.toString())\n        }\n    }\n\n    /**\n     * This method only checks if the field has `@Required` annotation.\n     * In most cases, you should use [.isRequiredField] to take into account\n     * Kotlin's annotation as well.\n     *\n     * @param field target field.\n     * @return `true` if the field has `@Required` annotation, `false` otherwise.\n     * @see .isRequiredField\n     */\n    private fun hasRequiredAnnotation(field: VariableElement): Boolean {\n        return field.getAnnotation(Required::class.java) != null\n    }\n\n    /**\n     * Checks if the field is annotated as required.\n     * @param field target field.\n     * @return `true` if the field is annotated as required, `false` otherwise.\n     */\n    private fun isRequiredField(field: VariableElement): Boolean {\n        if (hasRequiredAnnotation(field)) {\n            return true\n        }\n\n        if (ignoreKotlinNullability) {\n            return false\n        }\n\n        // Kotlin uses the `org.jetbrains.annotations.NotNull` annotation to mark non-null fields.\n        // In order to fully support the Kotlin type system we interpret `@NotNull` as an alias\n        // for `@Required`\n        for (annotation in field.annotationMirrors) {\n            if (annotation.annotationType.toString() == \"org.jetbrains.annotations.NotNull\") {\n                return true\n            }\n        }\n\n        return false\n    }\n\n    // The field has the @Index annotation. It's only valid for column types:\n    // STRING, DATE, INTEGER, BOOLEAN, RealmMutableInteger, OBJECT_ID, UUID and MIXED\n    private fun categorizeIndexField(element: Element, fieldElement: RealmFieldElement): Boolean {\n        var indexable = false\n\n        if (Utils.isMutableRealmInteger(fieldElement) || Utils.isRealmAny(fieldElement)) {\n            indexable = true\n        } else {\n            when (Constants.JAVA_TO_REALM_TYPES[fieldElement.asType().toString()]) {\n                Constants.RealmFieldType.STRING,\n                Constants.RealmFieldType.DATE,\n                Constants.RealmFieldType.INTEGER,\n                Constants.RealmFieldType.BOOLEAN,\n                Constants.RealmFieldType.OBJECT_ID,\n                Constants.RealmFieldType.UUID -> { indexable = true }\n                else -> { /* Ignore */ }\n            }\n        }\n\n        if (indexable) {\n            indexedFields.add(fieldElement)\n            return true\n        }\n\n        Utils.error(String.format(Locale.US, \"Field \\\"%s\\\" of type \\\"%s\\\" cannot be an @Index.\", element, element.asType()))\n        return false\n    }\n\n    // The field has the @Required annotation\n    // Returns `true` if the field could be correctly validated, `false` if an error was reported.\n    private fun checkBasicRequiredAnnotationUsage(field: VariableElement): Boolean {\n        if (Utils.isPrimitiveType(field)) {\n            Utils.error(String.format(Locale.US,\n                    \"@Required or @NotNull annotation is unnecessary for primitive field \\\"%s\\\".\", field))\n            return false\n        }\n\n        if (Utils.isRealmModel(field)) {\n            /**\n             * Defer checking if @Required usage is valid when checking backlinks. See [categorizeBacklinkField]\n             */\n            if (!embedded || field.getAnnotation(LinkingObjects::class.java) == null) {\n                Utils.error(String.format(Locale.US,\n                        \"Field \\\"%s\\\" with type \\\"%s\\\" cannot be @Required or @NotNull.\", field, field.asType()))\n                return false\n            }\n        }\n\n        if (Utils.isRealmAny(field)) {\n            Utils.error(String.format(Locale.US, \"RealmAny field \\\"${field}\\\" cannot be @Required or @NotNull.\"))\n            return false\n        }\n\n        // Should never get here - user should remove @Required\n        if (nullableFields.contains(field)) {\n            Utils.error(String.format(Locale.US,\n                    \"Field \\\"%s\\\" with type \\\"%s\\\" appears to be nullable. Consider removing @Required.\",\n                    field,\n                    field.asType()))\n\n            return false\n        }\n\n        return true\n    }\n\n    // The field has the @PrimaryKey annotation. It is only valid for\n    // String, short, int and long and must only be present one time.\n    // From Core 6 String primary keys no longer needs to be indexed, and from Core 10\n    // none of the primary key types do.\n    private fun categorizePrimaryKeyField(fieldElement: RealmFieldElement): Boolean {\n        // Embedded Objects do not support primary keys at all\n        if (embedded) {\n            Utils.error(String.format(Locale.US,\n                    \"A model class marked as embedded cannot contain a @PrimaryKey. One was defined for: %s\",\n                    fieldElement.simpleName.toString()))\n            return false\n        }\n\n        // Only one primary key pr. class is allowed\n        if (primaryKey != null) {\n            Utils.error(String.format(Locale.US,\n                    \"A class cannot have more than one @PrimaryKey. Both \\\"%s\\\" and \\\"%s\\\" are annotated as @PrimaryKey.\",\n                    primaryKey!!.simpleName.toString(),\n                    fieldElement.simpleName.toString()))\n            return false\n        }\n\n        // Check that the primary key is defined on a supported field\n        val fieldType = fieldElement.asType()\n        if (!isValidPrimaryKeyType(fieldType)) {\n            Utils.error(String.format(Locale.US,\n                    \"Field \\\"%s\\\" with type \\\"%s\\\" cannot be used as primary key. See @PrimaryKey for legal types.\",\n                    fieldElement.simpleName.toString(),\n                    fieldType))\n            return false\n        }\n\n        primaryKey = fieldElement\n\n        return true\n    }\n\n    private fun categorizeBacklinkField(variableElement: VariableElement): Boolean {\n        val backlink = Backlink(this, variableElement)\n        if (!backlink.validateSource()) {\n            return false\n        }\n\n        backlinks.add(backlink)\n\n        return true\n    }\n\n    private fun categorizeMutableRealmIntegerField(field: VariableElement): Boolean {\n        if (field.modifiers.contains(Modifier.FINAL)) {\n            return true\n        }\n\n        Utils.error(String.format(Locale.US,\n                \"Field \\\"%s\\\", a MutableRealmInteger, must be final.\",\n                field.simpleName.toString()))\n        return false\n    }\n\n    private fun isValidPrimaryKeyType(type: TypeMirror): Boolean {\n        for (validType in validPrimaryKeyTypes) {\n            if (typeUtils.isAssignable(type, validType)) {\n                return true\n            }\n        }\n        return false\n    }\n\n    private fun isStringPrimaryKeyType(type: TypeMirror): Boolean = typeUtils.isAssignable(type, stringType)\n\n    private fun containsType(listOfTypes: List<TypeMirror>, type: TypeMirror): Boolean {\n        for (i in listOfTypes.indices) {\n            // Comparing TypeMirror's using `equals()` breaks when using incremental annotation processing.\n            if (typeUtils.isSameType(listOfTypes[i], type)) {\n                return true\n            }\n        }\n        return false\n    }\n\n    companion object {\n        private val OPTION_IGNORE_KOTLIN_NULLABILITY = \"realm.ignoreKotlinNullability\"\n        private val MAX_CLASSNAME_LENGTH = 57\n    }\n\n}\n\n"
  },
  {
    "path": "realm/realm-annotations-processor/src/main/java/io/realm/processor/Constants.kt",
    "content": "/*\n * Copyright 2019 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\npackage io.realm.processor\n\nobject Constants {\n\n    const val REALM_PACKAGE_NAME = \"io.realm\"\n    const val PROXY_SUFFIX = \"RealmProxy\"\n    const val INTERFACE_SUFFIX = \"RealmProxyInterface\"\n    const val INDENT = \"    \"\n    const val DEFAULT_MODULE_CLASS_NAME = \"DefaultRealmModule\"\n    const val STATEMENT_EXCEPTION_ILLEGAL_NULL_VALUE =\n            \"throw new IllegalArgumentException(\\\"Trying to set non-nullable field '%s' to null.\\\")\"\n    const val STATEMENT_EXCEPTION_NO_PRIMARY_KEY_IN_JSON =\n            \"throw new IllegalArgumentException(\\\"JSON object doesn't have the primary key field '%s'.\\\")\"\n    const val STATEMENT_EXCEPTION_PRIMARY_KEY_CANNOT_BE_CHANGED =\n            \"throw new io.realm.exceptions.RealmException(\\\"Primary key field '%s' cannot be changed after object was created.\\\")\"\n    const val STATEMENT_EXCEPTION_ILLEGAL_JSON_LOAD\n            = \"throw new io.realm.exceptions.RealmException(\\\"\\\\\\\"%s\\\\\\\" field \\\\\\\"%s\\\\\\\" cannot be loaded from json\\\")\"\n    val JAVA_TO_REALM_TYPES = mapOf(\"byte\" to RealmFieldType.INTEGER,\n            \"short\" to RealmFieldType.INTEGER,\n            \"int\" to RealmFieldType.INTEGER,\n            \"long\" to RealmFieldType.INTEGER,\n            \"float\" to RealmFieldType.FLOAT,\n            \"double\" to RealmFieldType.DOUBLE,\n            \"boolean\" to RealmFieldType.BOOLEAN,\n            \"java.lang.Byte\" to RealmFieldType.INTEGER,\n            \"java.lang.Short\" to RealmFieldType.INTEGER,\n            \"java.lang.Integer\" to RealmFieldType.INTEGER,\n            \"java.lang.Long\" to RealmFieldType.INTEGER,\n            \"java.lang.Float\" to RealmFieldType.FLOAT,\n            \"java.lang.Double\" to RealmFieldType.DOUBLE,\n            \"java.lang.Boolean\" to RealmFieldType.BOOLEAN,\n            \"java.lang.String\" to RealmFieldType.STRING,\n            \"java.util.Date\" to RealmFieldType.DATE,\n            \"byte[]\" to RealmFieldType.BINARY,\n            \"org.bson.types.Decimal128\" to RealmFieldType.DECIMAL128,\n            \"org.bson.types.ObjectId\" to RealmFieldType.OBJECT_ID,\n            \"java.util.UUID\" to RealmFieldType.UUID\n    )\n\n    val LIST_ELEMENT_TYPE_TO_REALM_TYPES = mapOf(\n            \"java.lang.Byte\" to RealmFieldType.INTEGER_LIST,\n            \"java.lang.Short\" to RealmFieldType.INTEGER_LIST,\n            \"java.lang.Integer\" to RealmFieldType.INTEGER_LIST,\n            \"java.lang.Long\" to RealmFieldType.INTEGER_LIST,\n            \"java.lang.Float\" to RealmFieldType.FLOAT_LIST,\n            \"java.lang.Double\" to RealmFieldType.DOUBLE_LIST,\n            \"java.lang.Boolean\" to RealmFieldType.BOOLEAN_LIST,\n            \"java.lang.String\" to RealmFieldType.STRING_LIST,\n            \"java.util.Date\" to RealmFieldType.DATE_LIST,\n            \"byte[]\" to RealmFieldType.BINARY_LIST,\n            \"org.bson.types.Decimal128\" to RealmFieldType.DECIMAL128_LIST,\n            \"org.bson.types.ObjectId\" to RealmFieldType.OBJECT_ID_LIST,\n            \"java.util.UUID\" to RealmFieldType.UUID_LIST,\n            \"io.realm.RealmAny\" to RealmFieldType.MIXED_LIST\n    )\n\n    val DICTIONARY_ELEMENT_TYPE_TO_REALM_TYPES = mapOf(\n            \"java.lang.Byte\" to RealmFieldType.STRING_TO_INTEGER_MAP,\n            \"java.lang.Short\" to RealmFieldType.STRING_TO_INTEGER_MAP,\n            \"java.lang.Integer\" to RealmFieldType.STRING_TO_INTEGER_MAP,\n            \"java.lang.Long\" to RealmFieldType.STRING_TO_INTEGER_MAP,\n            \"java.lang.Float\" to RealmFieldType.STRING_TO_FLOAT_MAP,\n            \"java.lang.Double\" to RealmFieldType.STRING_TO_DOUBLE_MAP,\n            \"java.lang.Boolean\" to RealmFieldType.STRING_TO_BOOLEAN_MAP,\n            \"java.lang.String\" to RealmFieldType.STRING_TO_STRING_MAP,\n            \"java.util.Date\" to RealmFieldType.STRING_TO_DATE_MAP,\n            \"byte[]\" to RealmFieldType.STRING_TO_BINARY_MAP,\n            \"org.bson.types.Decimal128\" to RealmFieldType.STRING_TO_DECIMAL128_MAP,\n            \"org.bson.types.ObjectId\" to RealmFieldType.STRING_TO_OBJECT_ID_MAP,\n            \"java.util.UUID\" to RealmFieldType.STRING_TO_UUID_MAP,\n            \"io.realm.RealmAny\" to RealmFieldType.STRING_TO_MIXED_MAP\n    )\n\n    val SET_ELEMENT_TYPE_TO_REALM_TYPES = mapOf(\n            \"java.lang.Byte\" to RealmFieldType.INTEGER_SET,\n            \"java.lang.Short\" to RealmFieldType.INTEGER_SET,\n            \"java.lang.Integer\" to RealmFieldType.INTEGER_SET,\n            \"java.lang.Long\" to RealmFieldType.INTEGER_SET,\n            \"java.lang.Float\" to RealmFieldType.FLOAT_SET,\n            \"java.lang.Double\" to RealmFieldType.DOUBLE_SET,\n            \"java.lang.Boolean\" to RealmFieldType.BOOLEAN_SET,\n            \"java.lang.String\" to RealmFieldType.STRING_SET,\n            \"java.util.Date\" to RealmFieldType.DATE_SET,\n            \"byte[]\" to RealmFieldType.BINARY_SET,\n            \"org.bson.types.Decimal128\" to RealmFieldType.DECIMAL128_SET,\n            \"org.bson.types.ObjectId\" to RealmFieldType.OBJECT_ID_SET,\n            \"java.util.UUID\" to RealmFieldType.UUID_SET,\n            \"io.realm.RealmAny\" to RealmFieldType.MIXED_SET\n    )\n\n    /**\n     * Realm types and their corresponding Java types.\n     *\n     * @param realmType The simple name of the Enum type used in the Java bindings, to represent this type.\n     * @param javaType The simple name of the Java type needed to store this Realm Type\n     */\n    enum class RealmFieldType(realmType: String?, val javaType: String?) {\n        NOTYPE(null, \"Void\"),\n        INTEGER(\"INTEGER\", \"Long\"),\n        FLOAT(\"FLOAT\", \"Float\"),\n        DOUBLE(\"DOUBLE\", \"Double\"),\n        BOOLEAN(\"BOOLEAN\", \"Boolean\"),\n        STRING(\"STRING\", \"String\"),\n        DATE(\"DATE\", \"Date\"),\n        BINARY(\"BINARY\", \"BinaryByteArray\"),\n        REALM_INTEGER(\"INTEGER\", \"Long\"),\n        MIXED(\"MIXED\", \"RealmAny\"),\n        OBJECT(\"OBJECT\", \"Object\"),\n        LIST(\"LIST\", \"List\"),\n        DECIMAL128(\"DECIMAL128\", \"Decimal128\"),\n        OBJECT_ID(\"OBJECT_ID\", \"ObjectId\"),\n        UUID(\"UUID\", \"UUID\"),\n\n        BACKLINK(\"LINKING_OBJECTS\", null),\n\n        INTEGER_LIST(\"INTEGER_LIST\", \"List\"),\n        BOOLEAN_LIST(\"BOOLEAN_LIST\", \"List\"),\n        STRING_LIST(\"STRING_LIST\", \"List\"),\n        BINARY_LIST(\"BINARY_LIST\", \"List\"),\n        DATE_LIST(\"DATE_LIST\", \"List\"),\n        FLOAT_LIST(\"FLOAT_LIST\", \"List\"),\n        DOUBLE_LIST(\"DOUBLE_LIST\", \"List\"),\n        DECIMAL128_LIST(\"DECIMAL128_LIST\", \"List\"),\n        OBJECT_ID_LIST(\"OBJECT_ID_LIST\", \"List\"),\n        UUID_LIST(\"UUID_LIST\", \"List\"),\n        MIXED_LIST(\"MIXED_LIST\", \"List\"),\n\n        STRING_TO_LINK_MAP(\"STRING_TO_LINK_MAP\", \"Map\"),\n        STRING_TO_INTEGER_MAP(\"STRING_TO_INTEGER_MAP\", \"Map\"),\n        STRING_TO_BOOLEAN_MAP(\"STRING_TO_BOOLEAN_MAP\", \"Map\"),\n        STRING_TO_STRING_MAP(\"STRING_TO_STRING_MAP\", \"Map\"),\n        STRING_TO_BINARY_MAP(\"STRING_TO_BINARY_MAP\", \"Map\"),\n        STRING_TO_DATE_MAP(\"STRING_TO_DATE_MAP\", \"Map\"),\n        STRING_TO_FLOAT_MAP(\"STRING_TO_FLOAT_MAP\", \"Map\"),\n        STRING_TO_DOUBLE_MAP(\"STRING_TO_DOUBLE_MAP\", \"Map\"),\n        STRING_TO_DECIMAL128_MAP(\"STRING_TO_DECIMAL128_MAP\", \"Map\"),\n        STRING_TO_OBJECT_ID_MAP(\"STRING_TO_OBJECT_ID_MAP\", \"Map\"),\n        STRING_TO_UUID_MAP(\"STRING_TO_UUID_MAP\", \"Map\"),\n        STRING_TO_MIXED_MAP(\"STRING_TO_MIXED_MAP\", \"Map\"),\n\n        INTEGER_SET(\"INTEGER_SET\", \"Set\"),\n        BOOLEAN_SET(\"BOOLEAN_SET\", \"Set\"),\n        STRING_SET(\"STRING_SET\", \"Set\"),\n        BINARY_SET(\"BINARY_SET\", \"Set\"),\n        DATE_SET(\"DATE_SET\", \"Set\"),\n        FLOAT_SET(\"FLOAT_SET\", \"Set\"),\n        DOUBLE_SET(\"DOUBLE_SET\", \"Set\"),\n        DECIMAL128_SET(\"DECIMAL128_SET\", \"Set\"),\n        OBJECT_ID_SET(\"OBJECT_ID_SET\", \"Set\"),\n        UUID_SET(\"UUID_SET\", \"Set\"),\n        LINK_SET(\"LINK_SET\", \"Set\"),\n        MIXED_SET(\"MIXED_SET\", \"Set\");\n\n        /**\n         * The name of the enum, used in the Java bindings, used to represent the corresponding type.\n         */\n        val realmType: String = \"RealmFieldType.$realmType\"\n    }\n}\n"
  },
  {
    "path": "realm/realm-annotations-processor/src/main/java/io/realm/processor/DefaultModuleGenerator.kt",
    "content": "/*\n * Copyright 2019 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\npackage io.realm.processor\n\nimport com.squareup.javawriter.JavaWriter\n\nimport java.io.BufferedWriter\nimport java.io.IOException\nimport java.util.LinkedHashMap\nimport java.util.Locale\n\nimport javax.annotation.processing.ProcessingEnvironment\n\nimport io.realm.annotations.RealmModule\n\n/**\n * This class is responsible for creating the DefaultRealmModule that contains all known\n * [io.realm.annotations.RealmClass]' known at compile time.\n */\nclass DefaultModuleGenerator(private val env: ProcessingEnvironment) {\n\n    @Throws(IOException::class)\n    fun generate() {\n        val qualifiedGeneratedClassName = String.format(Locale.US, \"%s.%s\", Constants.REALM_PACKAGE_NAME, Constants.DEFAULT_MODULE_CLASS_NAME)\n        val sourceFile = env.filer.createSourceFile(qualifiedGeneratedClassName)\n        val writer = JavaWriter(BufferedWriter(sourceFile.openWriter()))\n\n        /**\n         * Defines the [io.realm.annotations.RealmModule.allClasses] attribute\n         */\n        val attributes = LinkedHashMap<String, Boolean>()\n        attributes[\"allClasses\"] = java.lang.Boolean.TRUE\n\n        // Build minimal class with the required `@RealmModule` annotation for including all\n        // known Realm model classes in this compilation unit.\n        writer.apply {\n            indent = Constants.INDENT\n            emitPackage(Constants.REALM_PACKAGE_NAME)\n            emitEmptyLine()\n            emitAnnotation(RealmModule::class.java, attributes)\n            beginType(\n                    qualifiedGeneratedClassName, // full qualified name of the item to generate\n                    \"class\",               // the type of the item\n                    emptySet(),                 // modifiers to apply\n                    null)           // class to extend\n            emitEmptyLine()\n            endType()\n            close()\n        }\n\n    }\n}\n"
  },
  {
    "path": "realm/realm-annotations-processor/src/main/java/io/realm/processor/ModuleMetaData.kt",
    "content": "/*\n * Copyright 2019 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\npackage io.realm.processor\n\nimport io.realm.annotations.RealmModule\nimport io.realm.annotations.RealmNamingPolicy\nimport io.realm.processor.nameconverter.NameConverter\nimport java.util.*\nimport javax.lang.model.element.*\n\n/**\n * Utility class for holding metadata for the Realm modules.\n *\n * Modules are inherently difficult to process because a model class can be part of multiple modules\n * that contain information required by the model class (e.g. class/field naming policies). At the\n * same time, the module will need the data from processed model classes to fully complete its\n * analysis (e.g. to ensure that only valid Realm model classes are added to the module).\n *\n * For this reason, processing modules are separated into 3 steps:\n *\n * 1. Pre-processing. Done by calling [ModuleMetaData.preProcess], which will do an initial parse of the modules\n *    and build up all information it can before processing any model classes.\n *\n * 2. Process model classes. See [ClassMetaData.generate].\n *\n * 3. Post-processing. Done by calling [ModuleMetaData.postProcess]. All modules can now be fully verified, and\n *    all metadata required to output module files can be generated.\n */\nclass ModuleMetaData {\n\n    // Pre-processing\n    private val globalModules = LinkedHashSet<QualifiedClassName>() // All modules with `allClasses = true` set\n    private val specificClassesModules = LinkedHashMap<QualifiedClassName, Set<QualifiedClassName>>() // Modules with classes specifically named\n    private val classNamingPolicy = LinkedHashMap<QualifiedClassName, RealmNamingPolicy>()\n    private val fieldNamingPolicy = LinkedHashMap<QualifiedClassName, RealmNamingPolicy>()\n    private val moduleAnnotations = HashMap<QualifiedClassName, RealmModule>()\n\n    // Post-processing\n    private val modules = LinkedHashMap<QualifiedClassName, Set<ClassMetaData>>()\n    private val libraryModules = LinkedHashMap<QualifiedClassName, Set<ClassMetaData>>()\n\n    private var shouldCreateDefaultModule: Boolean = false\n\n    /**\n     * Returns all module classes and the RealmObjects they know of.\n     */\n    val allModules: Map<QualifiedClassName, Set<ClassMetaData>>\n        get() {\n            val allModules = LinkedHashMap<QualifiedClassName, Set<ClassMetaData>>()\n            allModules.putAll(modules)\n            allModules.putAll(libraryModules)\n            return allModules\n        }\n\n    /**\n     * Builds all meta data structures that can be calculated before processing any model classes.\n     * Any errors or messages will be posted on the provided Messager.\n     *\n     * @return True if meta data was correctly created and processing of model classes can continue, false otherwise.\n     */\n    fun preProcess(moduleClasses: Set<Element>): Boolean {\n\n        // Tracks all module settings with `allClasses` enabled\n        val globalModuleInfo = HashSet<ModulePolicyInfo>()\n\n        // Tracks which modules a class was mentioned in by name using `classes = { ... }`\n        // <Qualified\n        val classSpecificModuleInfo = HashMap<QualifiedClassName, MutableList<ModulePolicyInfo>>()\n\n        // Check that modules are setup correctly\n        for (classElement in moduleClasses) {\n            val classSimpleName = classElement.simpleName.toString()\n\n            // Check that the annotation is only applied to a class\n            if (classElement.kind != ElementKind.CLASS) {\n                Utils.error(\"The RealmModule annotation can only be applied to classes\", classElement)\n                return false\n            }\n\n            // Check that allClasses and classes are not set at the same time\n            val moduleAnnotation = classElement.getAnnotation(RealmModule::class.java)\n            Utils.note(\"Processing module $classSimpleName\")\n            if (moduleAnnotation.allClasses && hasCustomClassList(classElement)) {\n                Utils.error(\"Setting @RealmModule(allClasses=true) will override @RealmModule(classes={...}) in $classSimpleName\")\n                return false\n            }\n\n            // Validate that naming policies are correctly configured.\n            if (!validateNamingPolicies(globalModuleInfo, classSpecificModuleInfo, classElement as TypeElement, moduleAnnotation)) {\n                return false\n            }\n\n            moduleAnnotations[QualifiedClassName(classElement.qualifiedName)] = moduleAnnotation\n        }\n\n        return true\n    }\n\n    /**\n     * Validates that the class/field naming policy for this module is correct.\n     *\n     * @param globalModuleInfo list of all modules with `allClasses` set\n     * @param classSpecificModuleInfo map of explicit classes and which modules they are explicitly mentioned in.\n     * @param classElement class element currently being validated\n     * @param moduleAnnotation annotation on this class.\n     * @return `true` if everything checks out, `false` if an error was found and reported.\n     */\n    private fun validateNamingPolicies(globalModuleInfo: MutableSet<ModulePolicyInfo>,\n                                       classSpecificModuleInfo: HashMap<QualifiedClassName, MutableList<ModulePolicyInfo>>,\n                                       classElement: TypeElement,\n                                       moduleAnnotation: RealmModule): Boolean {\n        val classNamePolicy = moduleAnnotation.classNamingPolicy\n        val fieldNamePolicy = moduleAnnotation.fieldNamingPolicy\n        val moduleClassName = QualifiedClassName(classElement.qualifiedName)\n        val moduleInfo = ModulePolicyInfo(moduleClassName, classNamePolicy, fieldNamePolicy)\n\n        // The difference between `allClasses` and a list of classes is a bit tricky at this stage\n        // as we haven't processed the full list of classes yet. We therefore need to treat\n        // each case specifically :(\n        // We do not compare against the default module as it is always configured correctly\n        // with NO_POLICY, meaning it will not trigger any errors.\n        if (moduleAnnotation.allClasses) {\n            // Check for conflicts with all other modules with `allClasses` set.\n            for (otherModuleInfo in globalModuleInfo) {\n                if (checkAndReportPolicyConflict(moduleInfo, otherModuleInfo)) {\n                    return false\n                }\n            }\n\n            // Check for conflicts with specifically named classes. This can happen if another\n            // module is listing specific classes with another policy.\n            for ((_, value) in classSpecificModuleInfo) {\n                for (otherModuleInfo in value) {\n                    if (checkAndReportPolicyConflict(moduleInfo, otherModuleInfo)) {\n                        return false\n                    }\n                }\n            }\n\n            // Everything checks out. Add moduleInfo so we can track it for the next module.\n            globalModuleInfo.add(moduleInfo)\n            globalModules.add(moduleClassName)\n\n        } else {\n            // We need to verify each class in the modules class list\n            val classNames = getClassListFromModule(classElement)\n            for (className in classNames) {\n\n                // Check that no other module with `allClasses` conflict with this specific\n                // class configuration\n                for (otherModuleInfo in globalModuleInfo) {\n                    if (checkAndReportPolicyConflict(moduleInfo, otherModuleInfo)) {\n                        return false\n                    }\n                }\n\n                // Check that this specific class isn't conflicting with another module\n                // specifically mentioning it using `classes = { ... }`\n                val otherModules= classSpecificModuleInfo[className]\n                if (otherModules != null) {\n                    for (otherModuleInfo in otherModules) {\n                        if (checkAndReportPolicyConflict(className, moduleInfo, otherModuleInfo)) {\n                            return false\n                        }\n                    }\n                }\n\n                // Keep track of the specific class for other module checks. We only\n                // need to track the latest module seen as previous errors would have been\n                // caught in a previous iteration of the loop.\n                if (!classSpecificModuleInfo.containsKey(className)) {\n                    classSpecificModuleInfo[className] = ArrayList()\n                }\n                classSpecificModuleInfo[className]!!.add(moduleInfo)\n            }\n            specificClassesModules[moduleClassName] = classNames\n        }\n\n        classNamingPolicy[moduleClassName] = classNamePolicy\n        fieldNamingPolicy[moduleClassName] = fieldNamePolicy\n        return true\n    }\n\n    /**\n     * All model classes have now been processed and the final validation of modules can occur.\n     * Any errors or messages will be posted on the provided Messager.\n     *\n     * @param modelClasses all Realm model classes found by the annotation processor.\n     * @return `true` if the module is valid, `false` otherwise.\n     */\n    fun postProcess(modelClasses: ClassCollection): Boolean {\n\n        // Process all global modules\n        for (qualifiedModuleClassName: QualifiedClassName in globalModules) {\n            val classData = LinkedHashSet<ClassMetaData>()\n            classData.addAll(modelClasses.classes)\n            defineModule(qualifiedModuleClassName, classData)\n        }\n\n        // Process all modules with specific classes\n        for ((qualifiedModuleClassName, value) in specificClassesModules) {\n            val classData = LinkedHashSet<ClassMetaData>()\n            for (modelClassName: QualifiedClassName in value) {\n                if (!modelClasses.containsQualifiedClass(modelClassName)) {\n                    Utils.error(\"${modelClassName.getSimpleName()} could not be added to the module. \" +\n                            \"Only classes extending RealmObject or implementing RealmModel, which are part of this project, can be added.\")\n                    return false\n\n                }\n                classData.add(modelClasses.getClassFromQualifiedName(modelClassName))\n            }\n            defineModule(qualifiedModuleClassName, classData)\n        }\n\n        // Check that app and library modules are not mixed\n        if (modules.size > 0 && libraryModules.size > 0) {\n            val sb = StringBuilder()\n            sb.append(\"Normal modules and library modules cannot be mixed in the same project.\")\n            sb.append('\\n')\n            sb.append(\"Normal module(s):\\n\")\n            for (module in modules.keys) {\n                sb.append(\"  \")\n                sb.append(module)\n                sb.append('\\n')\n            }\n            sb.append(\"Library module(s):\\n\")\n            for (module in libraryModules.keys) {\n                sb.append(\"  \")\n                sb.append(module)\n                sb.append('\\n')\n            }\n            Utils.error(sb.toString())\n            return false\n        }\n\n        // Create default Realm module if needed.\n        // Note: Kotlin will trigger the annotation processor even if no Realm annotations are used.\n        // The DefaultRealmModule should not be created in this case either.\n        if (libraryModules.size == 0 && modelClasses.size() > 0) {\n            shouldCreateDefaultModule = true\n            val defaultModuleName = QualifiedClassName(\"${Constants.REALM_PACKAGE_NAME}.${Constants.DEFAULT_MODULE_CLASS_NAME}\")\n            modules[defaultModuleName] = modelClasses.classes\n        }\n\n        return true\n    }\n\n    private fun defineModule(moduleClassName: QualifiedClassName, classData: Set<ClassMetaData>) {\n        if (classData.isNotEmpty()) {\n            if (moduleAnnotations[moduleClassName]!!.library) {\n                libraryModules[moduleClassName] = classData\n            } else {\n                modules[moduleClassName] = classData\n            }\n        }\n    }\n\n    // Checks if two modules have policy conflicts. Returns true if a conflict was found and reported.\n    private fun checkAndReportPolicyConflict(moduleInfo: ModulePolicyInfo, otherModuleInfo: ModulePolicyInfo): Boolean {\n        return checkAndReportPolicyConflict(null, moduleInfo, otherModuleInfo)\n    }\n\n    /**\n     * Check for name policy conflicts and report the error if found.\n     *\n     * @param className optional class name if a specific class is being checked.\n     * @param moduleInfo current module.\n     * @param otherModuleInfo already processed module.\n     * @return `true` if any errors was reported, `false` otherwise.\n     */\n    private fun checkAndReportPolicyConflict(className: QualifiedClassName?, moduleInfo: ModulePolicyInfo, otherModuleInfo: ModulePolicyInfo): Boolean {\n        var foundErrors = false\n\n        // Check class naming policy\n        val classPolicy = moduleInfo.classNamePolicy\n        val otherClassPolicy = otherModuleInfo.classNamePolicy\n        if (classPolicy != RealmNamingPolicy.NO_POLICY\n                && otherClassPolicy != RealmNamingPolicy.NO_POLICY\n                && classPolicy != otherClassPolicy) {\n            Utils.error(String.format(\"The modules %s and %s disagree on the class naming policy%s: %s vs. %s. \" + \"They same policy must be used.\",\n                    moduleInfo.moduleClassName,\n                    otherModuleInfo.moduleClassName,\n                    if (className != null) \" for $className\" else \"\",\n                    classPolicy,\n                    otherClassPolicy))\n            foundErrors = true\n        }\n\n        // Check field naming policy\n        val fieldPolicy = moduleInfo.fieldNamePolicy\n        val otherFieldPolicy = otherModuleInfo.fieldNamePolicy\n        if (fieldPolicy != RealmNamingPolicy.NO_POLICY\n                && otherFieldPolicy != RealmNamingPolicy.NO_POLICY\n                && fieldPolicy != otherFieldPolicy) {\n            Utils.error(String.format(\"The modules %s and %s disagree on the field naming policy%s: %s vs. %s. \" + \"They same policy should be used.\",\n                    moduleInfo.moduleClassName,\n                    otherModuleInfo.moduleClassName,\n                    if (className != null) \" for $className\" else \"\",\n                    fieldPolicy,\n                    otherFieldPolicy))\n            foundErrors = true\n        }\n\n        return foundErrors\n    }\n\n    // Detour needed to access the class elements in the array\n    // See http://blog.retep.org/2009/02/13/getting-class-values-from-annotations-in-an-annotationprocessor/\n    private fun getClassListFromModule(classElement: Element): Set<QualifiedClassName> {\n        val annotationMirror: AnnotationMirror? = getAnnotationMirror(classElement)\n        val annotationValue: AnnotationValue? = getAnnotationValue(annotationMirror)\n        val classes = HashSet<QualifiedClassName>()\n        annotationValue?.let {\n            for (classMirror in it.value as List<*>) {\n                // FIXME: Something is fishy about this. Figure out how to get the proper types in Kotlin here\n                val className = QualifiedClassName(classMirror.toString().removeSuffix(\".class\"))\n                classes.add(className)\n            }\n    }\n        return classes\n    }\n\n    // Work-around for asking for a Class primitive array which would otherwise throw a TypeMirrorException\n    // https://community.oracle.com/thread/1184190\n    private fun hasCustomClassList(classElement: Element): Boolean {\n        val annotationMirror: AnnotationMirror? = getAnnotationMirror(classElement)\n        val annotationValue: AnnotationValue? = getAnnotationValue(annotationMirror)\n        return if (annotationValue == null) {\n            false\n        } else {\n            val moduleClasses = annotationValue.value as List<*>\n            moduleClasses.isNotEmpty()\n        }\n    }\n\n    private fun getAnnotationMirror(classElement: Element): AnnotationMirror? {\n        var annotationMirror: AnnotationMirror? = null\n        for (am in classElement.annotationMirrors) {\n            if (am.annotationType.toString() == RealmModule::class.java.canonicalName) {\n                annotationMirror = am\n                break\n            }\n        }\n        return annotationMirror\n    }\n\n    private fun getAnnotationValue(annotationMirror: AnnotationMirror?): AnnotationValue? {\n        if (annotationMirror == null) {\n            return null\n        }\n        var annotationValue: AnnotationValue? = null\n        for ((key, value) in annotationMirror.elementValues) {\n            if (key.simpleName.toString() == \"classes\") {\n                annotationValue = value\n                break\n            }\n        }\n        return annotationValue\n    }\n\n    /**\n     * Returns `true` if the DefaultRealmModule.java file should be created.\n     */\n    fun shouldCreateDefaultModule(): Boolean {\n        return shouldCreateDefaultModule\n    }\n\n    /**\n     * Only available after [.preProcess] has run.\n     * Returns the module name policy the given name.\n     */\n    fun getClassNameFormatter(className: QualifiedClassName): NameConverter {\n        // We already validated that module definitions all agree on the same name policy\n        // so just find first match\n        if (globalModules.isNotEmpty()) {\n            return Utils.getNameFormatter(classNamingPolicy[globalModules.iterator().next()])\n        }\n\n        // No global modules found, so find match in modules specifically listing the class.\n        // We already validated that all modules agree on the converter, so just find first match.\n        for ((key, value) in specificClassesModules) {\n            if (value.contains(className)) {\n                return Utils.getNameFormatter(classNamingPolicy[key])\n            }\n        }\n\n        // No policy was provided anywhere for this class\n        return Utils.getNameFormatter(RealmNamingPolicy.NO_POLICY)\n    }\n\n\n    /**\n     * Only available after [ModuleMetaData.preProcess] has run.\n     *\n     * Returns the module name policy the field names.\n     */\n    fun getFieldNameFormatter(className: QualifiedClassName): NameConverter {\n        // We already validated that module definitions all agree on the same name policy\n        // so just find first match\n        if (globalModules.isNotEmpty()) {\n            return Utils.getNameFormatter(fieldNamingPolicy[globalModules.iterator().next()])\n        }\n\n        for ((key, value) in specificClassesModules) {\n            if (value.contains(className)) {\n                return Utils.getNameFormatter(fieldNamingPolicy[key])\n            }\n        }\n\n        return Utils.getNameFormatter(RealmNamingPolicy.NO_POLICY)\n    }\n\n    // Tuple helper class\n    private data class ModulePolicyInfo(val moduleClassName: QualifiedClassName,\n                                        val classNamePolicy: RealmNamingPolicy,\n                                        val fieldNamePolicy: RealmNamingPolicy)\n}\n"
  },
  {
    "path": "realm/realm-annotations-processor/src/main/java/io/realm/processor/OsObjectBuilderTypeHelper.kt",
    "content": "/*\n * Copyright 2019 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 */\npackage io.realm.processor\n\nimport java.util.*\nimport javax.lang.model.element.VariableElement\n\n/**\n * Helper class for creating the correct method calls to the OsObjectBuilder class.\n */\nobject OsObjectBuilderTypeHelper {\n\n    private val QUALIFIED_TYPE_TO_BUILDER: Map<QualifiedClassName, String>\n    private val QUALIFIED_LIST_TYPE_TO_BUILDER: Map<QualifiedClassName, String>\n    private val QUALIFIED_MAP_VALUES: Map<QualifiedClassName, String> = mapOf(\n            QualifiedClassName(\"io.realm.RealmAny\") to \"RealmAnyValueDictionary\",\n            QualifiedClassName(\"java.lang.Boolean\") to \"BooleanValueDictionary\",\n            QualifiedClassName(\"java.lang.String\") to \"StringValueDictionary\",\n            QualifiedClassName(\"java.lang.Integer\") to \"IntegerValueDictionary\",\n            QualifiedClassName(\"java.lang.Float\") to \"FloatValueDictionary\",\n            QualifiedClassName(\"java.lang.Long\") to \"LongValueDictionary\",\n            QualifiedClassName(\"java.lang.Short\") to \"ShortValueDictionary\",\n            QualifiedClassName(\"java.lang.Byte\") to \"ByteValueDictionary\",\n            QualifiedClassName(\"java.lang.Double\") to \"DoubleValueDictionary\",\n            QualifiedClassName(\"java.util.Date\") to \"DateValueDictionary\",\n            QualifiedClassName(\"byte[]\") to \"BinaryValueDictionary\",\n            QualifiedClassName(\"org.bson.types.ObjectId\") to \"ObjectIdValueDictionary\",\n            QualifiedClassName(\"org.bson.types.Decimal128\") to \"Decimal128ValueDictionary\",\n            QualifiedClassName(\"java.util.UUID\") to \"UUIDValueDictionary\"\n    )\n\n    private val QUALIFIED_SET_VALUES: Map<QualifiedClassName, String> = mapOf(\n            QualifiedClassName(\"io.realm.RealmAny\") to \"RealmAnySet\",\n            QualifiedClassName(\"java.lang.Boolean\") to \"BooleanSet\",\n            QualifiedClassName(\"java.lang.String\") to \"StringSet\",\n            QualifiedClassName(\"java.lang.Integer\") to \"IntegerSet\",\n            QualifiedClassName(\"java.lang.Float\") to \"FloatSet\",\n            QualifiedClassName(\"java.lang.Long\") to \"LongSet\",\n            QualifiedClassName(\"java.lang.Short\") to \"ShortSet\",\n            QualifiedClassName(\"java.lang.Byte\") to \"ByteSet\",\n            QualifiedClassName(\"java.lang.Double\") to \"DoubleSet\",\n            QualifiedClassName(\"java.util.Date\") to \"DateSet\",\n            QualifiedClassName(\"byte[]\") to \"BinarySet\",\n            QualifiedClassName(\"org.bson.types.ObjectId\") to \"ObjectIdSet\",\n            QualifiedClassName(\"org.bson.types.Decimal128\") to \"Decimal128Set\",\n            QualifiedClassName(\"java.util.UUID\") to \"UUIDSet\"\n    )\n\n    init {\n        // Map of qualified types to their OsObjectBuilder Type\n        val fieldTypes = HashMap<QualifiedClassName, String>()\n        fieldTypes.apply {\n            this[QualifiedClassName(\"byte\")] = \"Integer\"\n            this[QualifiedClassName(\"byte\")] = \"Integer\"\n            this[QualifiedClassName(\"short\")] = \"Integer\"\n            this[QualifiedClassName(\"int\")] = \"Integer\"\n            this[QualifiedClassName(\"long\")] = \"Integer\"\n            this[QualifiedClassName(\"float\")] = \"Float\"\n            this[QualifiedClassName(\"double\")] = \"Double\"\n            this[QualifiedClassName(\"boolean\")] = \"Boolean\"\n            this[QualifiedClassName(\"byte[]\")] = \"ByteArray\"\n            this[QualifiedClassName(\"java.lang.Byte\")] = \"Integer\"\n            this[QualifiedClassName(\"java.lang.Short\")] = \"Integer\"\n            this[QualifiedClassName(\"java.lang.Integer\")] = \"Integer\"\n            this[QualifiedClassName(\"java.lang.Long\")] = \"Integer\"\n            this[QualifiedClassName(\"java.lang.Float\")] = \"Float\"\n            this[QualifiedClassName(\"java.lang.Double\")] = \"Double\"\n            this[QualifiedClassName(\"java.lang.Boolean\")] = \"Boolean\"\n            this[QualifiedClassName(\"java.lang.String\")] = \"String\"\n            this[QualifiedClassName(\"java.util.Date\")] = \"Date\"\n            this[QualifiedClassName(\"org.bson.types.Decimal128\")] = \"Decimal128\"\n            this[QualifiedClassName(\"org.bson.types.ObjectId\")] = \"ObjectId\"\n            this[QualifiedClassName(\"java.util.UUID\")] = \"UUID\"\n            this[QualifiedClassName(\"io.realm.MutableRealmInteger\")] = \"MutableRealmInteger\"\n            this[QualifiedClassName(\"io.realm.RealmAny\")] = \"RealmAny\"\n        }\n        QUALIFIED_TYPE_TO_BUILDER = Collections.unmodifiableMap(fieldTypes)\n\n        // Map of qualified types to their OsObjectBuilder Type\n        val listTypes = HashMap<QualifiedClassName, String>()\n        listTypes.apply {\n            this[QualifiedClassName(\"byte[]\")] = \"ByteArrayList\"\n            this[QualifiedClassName(\"java.lang.Byte\")] = \"ByteList\"\n            this[QualifiedClassName(\"java.lang.Short\")] = \"ShortList\"\n            this[QualifiedClassName(\"java.lang.Integer\")] = \"IntegerList\"\n            this[QualifiedClassName(\"java.lang.Long\")] = \"LongList\"\n            this[QualifiedClassName(\"java.lang.Float\")] = \"FloatList\"\n            this[QualifiedClassName(\"java.lang.Double\")] = \"DoubleList\"\n            this[QualifiedClassName(\"java.lang.Boolean\")] = \"BooleanList\"\n            this[QualifiedClassName(\"java.lang.String\")] = \"StringList\"\n            this[QualifiedClassName(\"java.util.Date\")] = \"DateList\"\n            this[QualifiedClassName(\"io.realm.MutableRealmInteger\")] = \"MutableRealmIntegerList\"\n            this[QualifiedClassName(\"org.bson.types.Decimal128\")] = \"Decimal128List\"\n            this[QualifiedClassName(\"org.bson.types.ObjectId\")] = \"ObjectIdList\"\n            this[QualifiedClassName(\"io.realm.RealmAny\")] = \"RealmAnyList\"\n            this[QualifiedClassName(\"java.util.UUID\")] = \"UUIDList\"\n        }\n        QUALIFIED_LIST_TYPE_TO_BUILDER = Collections.unmodifiableMap(listTypes)\n    }\n\n    /**\n     * Returns the method name used by the OsObjectBuilder for the given type, e.g. `addInteger`\n     * or `addIntegerList`.\n     */\n    fun getOsObjectBuilderName(field: VariableElement): String {\n        return if (Utils.isRealmModel(field)) {\n            \"addObject\"\n        } else if (Utils.isRealmModelList(field)) {\n            \"addObjectList\"\n        } else if (Utils.isRealmValueList(field)) {\n            \"add\" + getListTypeName(Utils.getRealmListType(field))\n        } else if (Utils.isRealmDictionary(field)) {\n            \"add\" + getDictionaryValueTypeName(Utils.getDictionaryType(field))\n        } else if (Utils.isRealmSet(field)) {\n            \"add\" + getSetValueTypeName(Utils.getSetType(field))\n        } else if (Utils.isRealmResults(field)) {\n            throw IllegalStateException(\"RealmResults are not supported by OsObjectBuilder: $field\")\n        } else {\n            \"add\" + getBasicTypeName(Utils.getFieldTypeQualifiedName(field))\n        }\n    }\n\n    private fun getBasicTypeName(qualifiedType: QualifiedClassName): String {\n        val type = QUALIFIED_TYPE_TO_BUILDER[qualifiedType]\n        if (type != null) {\n            return type\n        }\n        throw IllegalArgumentException(\"Unsupported type: $qualifiedType\")\n    }\n\n    private fun getListTypeName(typeName: QualifiedClassName?): String {\n        val type = QUALIFIED_LIST_TYPE_TO_BUILDER[typeName]\n        if (type != null) {\n            return type\n        }\n        throw IllegalArgumentException(\"Unsupported list type: $type\")\n    }\n\n    private fun getDictionaryValueTypeName(typeName: QualifiedClassName?): String {\n        return requireNotNull(QUALIFIED_MAP_VALUES[typeName]) {\n            \"Unsupported dictionary value type: '$typeName'\"\n        }\n    }\n\n    private fun getSetValueTypeName(typeName: QualifiedClassName?): String {\n        return requireNotNull(QUALIFIED_SET_VALUES[typeName]) {\n            \"Unsupported set value type: '$typeName'\"\n        }\n    }\n}\n"
  },
  {
    "path": "realm/realm-annotations-processor/src/main/java/io/realm/processor/RealmFieldElement.kt",
    "content": "/*\n * Copyright 2019 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 */\npackage io.realm.processor\n\nimport javax.lang.model.element.AnnotationMirror\nimport javax.lang.model.element.Element\nimport javax.lang.model.element.ElementKind\nimport javax.lang.model.element.ElementVisitor\nimport javax.lang.model.element.Modifier\nimport javax.lang.model.element.Name\nimport javax.lang.model.element.VariableElement\nimport javax.lang.model.type.TypeMirror\n\n/**\n * Wrapper for [javax.lang.model.element.VariableElement] that makes it possible to add\n * additional metadata.\n */\nclass RealmFieldElement(val fieldReference: VariableElement,\n                        /**\n                         * Returns the name that Realm Core uses internally when saving data to this field.\n                         * [RealmFieldElement.getSimpleName] returns the name in the Java class.\n                         */\n                        val internalFieldName: String // Name used for this field internally in Realm.\n) : VariableElement {\n\n    val javaName: String\n        get() = simpleName.toString()\n\n    override fun getModifiers(): Set<Modifier> {\n        return fieldReference.modifiers\n    }\n\n    override fun asType(): TypeMirror {\n        return fieldReference.asType()\n    }\n\n    override fun getKind(): ElementKind? {\n        return null\n    }\n\n    override fun getConstantValue(): Any {\n        return fieldReference.constantValue\n    }\n\n    /**\n     * Returns the name for this field in the Java class.\n     * [RealmFieldElement.internalFieldName] returns the name used by Realm Core for the same field.\n     */\n    override fun getSimpleName(): Name {\n        return fieldReference.simpleName\n    }\n\n    override fun getEnclosingElement(): Element {\n        return fieldReference.enclosingElement\n    }\n\n    override fun getEnclosedElements(): List<Element> {\n        return fieldReference.enclosedElements\n    }\n\n    override fun getAnnotationMirrors(): List<AnnotationMirror> {\n        return fieldReference.annotationMirrors\n    }\n\n    override fun <A : Annotation> getAnnotation(aClass: Class<A>): A? {\n        return fieldReference.getAnnotation(aClass)\n    }\n\n    override fun <A : Annotation> getAnnotationsByType(aClass: Class<A>): Array<A> {\n        return fieldReference.getAnnotationsByType(aClass)\n    }\n\n    override fun <R, P> accept(elementVisitor: ElementVisitor<R, P>, p: P): R {\n        return fieldReference.accept(elementVisitor, p)\n    }\n\n    override fun toString(): String {\n        // Mimics the behaviour of the standard implementation of VariableElement `toString()`\n        // Some methods in RealmProxyClassGenerator depended on this.\n        return simpleName.toString()\n    }\n}\n"
  },
  {
    "path": "realm/realm-annotations-processor/src/main/java/io/realm/processor/RealmJsonTypeHelper.kt",
    "content": "/*\n * Copyright 2019 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\npackage io.realm.processor\n\nimport com.squareup.javawriter.JavaWriter\nimport java.io.IOException\nimport java.util.*\n\n\n/**\n * Helper class for converting between Json types and data types in Java that are supported by Realm.\n */\nobject RealmJsonTypeHelper {\n    private val JAVA_TO_JSON_TYPES: Map<QualifiedClassName, JsonToRealmFieldTypeConverter>\n\n    init {\n        val m = HashMap<QualifiedClassName, JsonToRealmFieldTypeConverter>()\n        m[QualifiedClassName(\"byte\")] = SimpleTypeConverter(\"byte\", \"Int\")\n        m[QualifiedClassName(\"short\")] = SimpleTypeConverter(\"short\", \"Int\")\n        m[QualifiedClassName(\"int\")] = SimpleTypeConverter(\"int\", \"Int\")\n        m[QualifiedClassName(\"long\")] = SimpleTypeConverter(\"long\", \"Long\")\n        m[QualifiedClassName(\"float\")] = SimpleTypeConverter(\"float\", \"Double\")\n        m[QualifiedClassName(\"double\")] = SimpleTypeConverter(\"double\", \"Double\")\n        m[QualifiedClassName(\"boolean\")] = SimpleTypeConverter(\"boolean\", \"Boolean\")\n        m[QualifiedClassName(\"byte[]\")] = ByteArrayTypeConverter()\n        m[QualifiedClassName(\"java.lang.Byte\")] = m[QualifiedClassName(\"byte\")] as JsonToRealmFieldTypeConverter\n        m[QualifiedClassName(\"java.lang.Short\")] = m[QualifiedClassName(\"short\")] as JsonToRealmFieldTypeConverter\n        m[QualifiedClassName(\"java.lang.Integer\")] = m[QualifiedClassName(\"int\")] as JsonToRealmFieldTypeConverter\n        m[QualifiedClassName(\"java.lang.Long\")] = m[QualifiedClassName(\"long\")] as JsonToRealmFieldTypeConverter\n        m[QualifiedClassName(\"java.lang.Float\")] = m[QualifiedClassName(\"float\")] as JsonToRealmFieldTypeConverter\n        m[QualifiedClassName(\"java.lang.Double\")] = m[QualifiedClassName(\"double\")] as JsonToRealmFieldTypeConverter\n        m[QualifiedClassName(\"java.lang.Boolean\")] = m[QualifiedClassName(\"boolean\")] as JsonToRealmFieldTypeConverter\n        m[QualifiedClassName(\"java.lang.String\")] = SimpleTypeConverter(\"String\", \"String\")\n        m[QualifiedClassName(\"java.util.Date\")] = DateTypeConverter()\n        m[QualifiedClassName(\"org.bson.types.Decimal128\")] = Decimal128TypeConverter()\n        m[QualifiedClassName(\"org.bson.types.ObjectId\")] = ObjectIdTypeConverter()\n        m[QualifiedClassName(\"java.util.UUID\")] = UUIDTypeConverter()\n        m[QualifiedClassName(\"io.realm.RealmAny\")] = RealmAnyTypeConverter()\n        m[QualifiedClassName(\"io.realm.MutableRealmInteger\")] = MutableRealmIntegerTypeConverter()\n        JAVA_TO_JSON_TYPES = Collections.unmodifiableMap(m)\n    }\n\n    @Throws(IOException::class)\n    fun emitIllegalJsonValueException(fieldType: String, fieldName: String, writer: JavaWriter) {\n        writer.apply {\n            beginControlFlow(\"if (json.has(\\\"%s\\\"))\", fieldName)\n                emitStatement(Constants.STATEMENT_EXCEPTION_ILLEGAL_JSON_LOAD, fieldType, fieldName)\n            endControlFlow()\n        }\n    }\n\n    @Throws(IOException::class)\n    fun emitCreateObjectWithPrimaryKeyValue(realmObjectClass: QualifiedClassName,\n                                            realmObjectProxyClass: QualifiedClassName,\n                                            fieldType: QualifiedClassName,\n                                            fieldName: String,\n                                            writer: JavaWriter) {\n        val typeEmitter = JAVA_TO_JSON_TYPES[fieldType]\n        typeEmitter?.emitGetObjectWithPrimaryKeyValue(realmObjectClass, realmObjectProxyClass, fieldName, writer)\n    }\n\n    @Throws(IOException::class)\n    fun emitFillRealmObjectWithJsonValue(varName: String,\n                                         setter: String,\n                                         fieldName: String,\n                                         qualifiedFieldType: QualifiedClassName,\n                                         proxyClass: SimpleClassName,\n                                         embedded: Boolean,\n                                         writer: JavaWriter) {\n        writer.apply {\n            beginControlFlow(\"if (json.has(\\\"%s\\\"))\", fieldName)\n                beginControlFlow(\"if (json.isNull(\\\"%s\\\"))\", fieldName)\n                    emitStatement(\"%s.%s(null)\", varName, setter)\n                nextControlFlow(\"else\")\n                    if (!embedded) {\n                        emitStatement(\"%s %sObj = %s.createOrUpdateUsingJsonObject(realm, json.getJSONObject(\\\"%s\\\"), update)\", qualifiedFieldType, fieldName, proxyClass, fieldName)\n                        emitStatement(\"%s.%s(%sObj)\", varName, setter, fieldName)\n                    } else {\n                        emitStatement(\"%s.createOrUpdateEmbeddedUsingJsonObject(realm, (RealmModel)%s, \\\"%s\\\", json.getJSONObject(\\\"%s\\\"), update)\", proxyClass, varName, fieldName, fieldName)\n                    }\n                endControlFlow()\n            endControlFlow()\n        }\n    }\n\n    @Throws(IOException::class)\n    fun emitFillRealmListWithJsonValue(varName: String,\n                                       getter: String,\n                                       setter: String,\n                                       fieldName: String,\n                                       fieldTypeCanonicalName: String,\n                                       proxyClass: SimpleClassName,\n                                       embedded: Boolean,\n                                       writer: JavaWriter) {\n        writer.apply {\n            beginControlFlow(\"if (json.has(\\\"%s\\\"))\", fieldName)\n                beginControlFlow(\"if (json.isNull(\\\"%s\\\"))\", fieldName)\n                    emitStatement(\"%s.%s(null)\", varName, setter)\n                nextControlFlow(\"else\")\n                    emitStatement(\"%s.%s().clear()\", varName, getter)\n                    emitStatement(\"JSONArray array = json.getJSONArray(\\\"%s\\\")\", fieldName)\n                    beginControlFlow(\"for (int i = 0; i < array.length(); i++)\")\n                        if (!embedded) {\n                            emitStatement(\"%s item = %s.createOrUpdateUsingJsonObject(realm, array.getJSONObject(i), update)\", fieldTypeCanonicalName, proxyClass, fieldTypeCanonicalName)\n                            emitStatement(\"%s.%s().add(item)\", varName, getter)\n                       } else {\n                            emitStatement(\"%s.createOrUpdateEmbeddedUsingJsonObject(realm, (RealmModel)%s, \\\"%s\\\", array.getJSONObject(i), update)\", proxyClass, varName, fieldName)\n                        }\n                    endControlFlow()\n                endControlFlow()\n            endControlFlow()\n        }\n    }\n\n    @Throws(IOException::class)\n    fun emitFillJavaTypeWithJsonValue(varName: String, accessor: String, fieldName: String, fieldType: QualifiedClassName, writer: JavaWriter) {\n        val typeEmitter = JAVA_TO_JSON_TYPES[fieldType]\n        typeEmitter?.emitTypeConversion(varName, accessor, fieldName, fieldType, writer)\n    }\n\n    @Throws(IOException::class)\n    fun emitFillRealmObjectFromStream(varName: String,\n                                      setter: String,\n                                      fieldName: String,\n                                      fieldType: QualifiedClassName,\n                                      proxyClass: SimpleClassName,\n                                      writer: JavaWriter) {\n        writer.apply {\n            beginControlFlow(\"if (reader.peek() == JsonToken.NULL)\")\n                emitStatement(\"reader.skipValue()\")\n                emitStatement(\"%s.%s(null)\", varName, setter)\n            nextControlFlow(\"else\")\n                emitStatement(\"%s %sObj = %s.createUsingJsonStream(realm, reader)\", fieldType, fieldName, proxyClass)\n                emitStatement(\"%s.%s(%sObj)\", varName, setter, fieldName)\n            endControlFlow()\n        }\n    }\n\n    @Throws(IOException::class)\n    fun emitFillRealmListFromStream(varName: String,\n                                    getter: String,\n                                    setter: String,\n                                    fieldType: QualifiedClassName,\n                                    proxyClass: SimpleClassName,\n                                    writer: JavaWriter) {\n        writer.apply {\n            beginControlFlow(\"if (reader.peek() == JsonToken.NULL)\")\n                emitStatement(\"reader.skipValue()\")\n                emitStatement(\"%s.%s(null)\", varName, setter)\n            nextControlFlow(\"else\")\n                emitStatement(\"%s.%s(new RealmList<%s>())\", varName, setter, fieldType)\n                emitStatement(\"reader.beginArray()\")\n                beginControlFlow(\"while (reader.hasNext())\")\n                    emitStatement(\"%s item = %s.createUsingJsonStream(realm, reader)\", fieldType, proxyClass)\n                    emitStatement(\"%s.%s().add(item)\", varName, getter)\n                endControlFlow()\n                emitStatement(\"reader.endArray()\")\n            endControlFlow()\n        }\n    }\n\n    @Throws(IOException::class)\n    fun emitFillJavaTypeFromStream(varName: String,\n                                   metaData: ClassMetaData,\n                                   accessor: String,\n                                   fieldName: String,\n                                   fieldType: QualifiedClassName,\n                                   writer: JavaWriter) {\n        val isPrimaryKey = metaData.hasPrimaryKey() && metaData.primaryKey!!.simpleName.toString() == fieldName\n        val typeEmitter = JAVA_TO_JSON_TYPES[fieldType]\n        typeEmitter?.emitStreamTypeConversion(varName, accessor, fieldName, fieldType, writer, isPrimaryKey)\n    }\n\n    /**\n     * Creates a conversion between simple types which can be expressed as RealmObject.setFieldName((<castType>)\n     * json.get<jsonType>) or RealmObject.setFieldName((<castType>) reader.next<jsonType>\n     *\n     * @param castType Java type to cast to.\n     * @param jsonType JsonType to get data from.\n     */\n    private class SimpleTypeConverter(private val castType: String, private val jsonType: String) : JsonToRealmFieldTypeConverter {\n\n        @Throws(IOException::class)\n        override fun emitTypeConversion(varName: String, accessor: String, fieldName: String, fieldType: QualifiedClassName, writer: JavaWriter) {\n            // Only throw exception for primitive types.\n            // For boxed types and String, exception will be thrown in the setter.\n            val statementSetNullOrThrow = if (Utils.isPrimitiveType(fieldType))\n                String.format(Locale.US, Constants.STATEMENT_EXCEPTION_ILLEGAL_NULL_VALUE, fieldName)\n            else\n                String.format(Locale.US, \"%s.%s(null)\", varName, accessor)\n\n            writer.apply {\n                beginControlFlow(\"if (json.has(\\\"%s\\\"))\", fieldName)\n                    beginControlFlow(\"if (json.isNull(\\\"%s\\\"))\", fieldName)\n                        emitStatement(statementSetNullOrThrow)\n                    nextControlFlow(\"else\")\n                        emitStatement(\"%s.%s((%s) json.get%s(\\\"%s\\\"))\", varName, accessor, castType, jsonType, fieldName)\n                    endControlFlow()\n                endControlFlow()\n            }\n        }\n\n        @Throws(IOException::class)\n        override fun emitStreamTypeConversion(varName: String, accessor: String, fieldName: String, fieldType: QualifiedClassName, writer: JavaWriter, isPrimaryKey: Boolean) {\n            // Only throw exception for primitive types.\n            // For boxed types and String, exception will be thrown in the setter.\n            val statementSetNullOrThrow = if (Utils.isPrimitiveType(fieldType))\n                String.format(Locale.US, Constants.STATEMENT_EXCEPTION_ILLEGAL_NULL_VALUE, fieldName)\n            else\n                String.format(Locale.US, \"%s.%s(null)\", varName, accessor)\n\n            writer.apply {\n                beginControlFlow(\"if (reader.peek() != JsonToken.NULL)\")\n                    emitStatement(\"%s.%s((%s) reader.next%s())\", varName, accessor, castType, jsonType)\n                nextControlFlow(\"else\")\n                    emitStatement(\"reader.skipValue()\")\n                    emitStatement(statementSetNullOrThrow)\n                endControlFlow()\n\n                if (isPrimaryKey) {\n                    emitStatement(\"jsonHasPrimaryKey = true\")\n                }\n            }\n        }\n\n        @Throws(IOException::class)\n        override fun emitGetObjectWithPrimaryKeyValue(realmObjectClass: QualifiedClassName, realmObjectProxyClass: QualifiedClassName, fieldName: String, writer: JavaWriter) {\n            // No error checking is done here for valid primary key types.\n            // This should be done by the annotation processor.\n            writer.apply {\n                beginControlFlow(\"if (json.has(\\\"%s\\\"))\", fieldName)\n                    beginControlFlow(\"if (json.isNull(\\\"%s\\\"))\", fieldName)\n                        emitStatement(\"obj = (%1\\$s) realm.createObjectInternal(%2\\$s.class, null, true, excludeFields)\", realmObjectProxyClass, realmObjectClass)\n                    nextControlFlow(\"else\")\n                        emitStatement(\"obj = (%1\\$s) realm.createObjectInternal(%2\\$s.class, json.get%3\\$s(\\\"%4\\$s\\\"), true, excludeFields)\", realmObjectProxyClass, realmObjectClass, jsonType, fieldName)\n                    endControlFlow()\n                nextControlFlow(\"else\")\n                    emitStatement(Constants.STATEMENT_EXCEPTION_NO_PRIMARY_KEY_IN_JSON, fieldName)\n                endControlFlow()\n            }\n        }\n    }\n\n    private class ByteArrayTypeConverter : JsonToRealmFieldTypeConverter {\n        @Throws(IOException::class)\n        override fun emitTypeConversion(varName: String, accessor: String, fieldName: String, fieldType: QualifiedClassName, writer: JavaWriter) {\n            writer.apply {\n                beginControlFlow(\"if (json.has(\\\"%s\\\"))\", fieldName)\n                    beginControlFlow(\"if (json.isNull(\\\"%s\\\"))\", fieldName)\n                        emitStatement(\"%s.%s(null)\", varName, accessor)\n                    nextControlFlow(\"else\")\n                        emitStatement(\"%s.%s(JsonUtils.stringToBytes(json.getString(\\\"%s\\\")))\", varName, accessor, fieldName)\n                    endControlFlow()\n                endControlFlow()\n            }\n        }\n\n        @Throws(IOException::class)\n        override fun emitStreamTypeConversion(varName: String, accessor: String, fieldName: String, fieldType: QualifiedClassName, writer: JavaWriter, isPrimaryKey: Boolean) {\n            writer.apply {\n                beginControlFlow(\"if (reader.peek() != JsonToken.NULL)\")\n                    emitStatement(\"%s.%s(JsonUtils.stringToBytes(reader.nextString()))\", varName, accessor)\n                nextControlFlow(\"else\")\n                    emitStatement(\"reader.skipValue()\")\n                    emitStatement(\"%s.%s(null)\", varName, accessor)\n                endControlFlow()\n            }\n        }\n\n        @Throws(IOException::class)\n        override fun emitGetObjectWithPrimaryKeyValue(realmObjectClass: QualifiedClassName, realmObjectProxyClass: QualifiedClassName, fieldName: String, writer: JavaWriter) {\n            throw IllegalArgumentException(\"'byte[]' is not allowed as a primary key value.\")\n        }\n    }\n\n    private class DateTypeConverter : JsonToRealmFieldTypeConverter {\n        @Throws(IOException::class)\n        override fun emitTypeConversion(varName: String, accessor: String, fieldName: String, fieldType: QualifiedClassName, writer: JavaWriter) {\n            writer.apply {\n                beginControlFlow(\"if (json.has(\\\"%s\\\"))\", fieldName)\n                    beginControlFlow(\"if (json.isNull(\\\"%s\\\"))\", fieldName)\n                        emitStatement(\"%s.%s(null)\", varName, accessor)\n                    nextControlFlow(\"else\")\n                        emitStatement(\"Object timestamp = json.get(\\\"%s\\\")\", fieldName)\n                        beginControlFlow(\"if (timestamp instanceof String)\")\n                            emitStatement(\"%s.%s(JsonUtils.stringToDate((String) timestamp))\", varName, accessor)\n                        nextControlFlow(\"else\")\n                            emitStatement(\"%s.%s(new Date(json.getLong(\\\"%s\\\")))\", varName, accessor, fieldName)\n                        endControlFlow()\n                    endControlFlow()\n                endControlFlow()\n            }\n        }\n\n        @Throws(IOException::class)\n        override fun emitStreamTypeConversion(varName: String, accessor: String, fieldName: String, fieldType: QualifiedClassName, writer: JavaWriter, isPrimaryKey: Boolean) {\n            writer.apply {\n                beginControlFlow(\"if (reader.peek() == JsonToken.NULL)\")\n                    emitStatement(\"reader.skipValue()\")\n                    emitStatement(\"%s.%s(null)\", varName, accessor)\n                nextControlFlow(\"else if (reader.peek() == JsonToken.NUMBER)\")\n                    emitStatement(\"long timestamp = reader.nextLong()\", fieldName)\n                    beginControlFlow(\"if (timestamp > -1)\")\n                        emitStatement(\"%s.%s(new Date(timestamp))\", varName, accessor)\n                    endControlFlow()\n                nextControlFlow(\"else\")\n                    emitStatement(\"%s.%s(JsonUtils.stringToDate(reader.nextString()))\", varName, accessor)\n                endControlFlow()\n            }\n        }\n\n        @Throws(IOException::class)\n        override fun emitGetObjectWithPrimaryKeyValue(realmObjectClass: QualifiedClassName, realmObjectProxyClass: QualifiedClassName, fieldName: String, writer: JavaWriter) {\n            throw IllegalArgumentException(\"'Date' is not allowed as a primary key value.\")\n        }\n    }\n\n    private class Decimal128TypeConverter : JsonToRealmFieldTypeConverter {\n        @Throws(IOException::class)\n        override fun emitTypeConversion(varName: String, accessor: String, fieldName: String, fieldType: QualifiedClassName, writer: JavaWriter) {\n            writer.apply {\n                beginControlFlow(\"if (json.has(\\\"%s\\\"))\", fieldName)\n                    beginControlFlow(\"if (json.isNull(\\\"%s\\\"))\", fieldName)\n                        emitStatement(\"%s.%s(null)\", varName, accessor)\n                    nextControlFlow(\"else\")\n                            emitStatement(\"Object decimal = json.get(\\\"%s\\\")\", fieldName)\n                            beginControlFlow(\"if (decimal instanceof org.bson.types.Decimal128)\")\n                                emitStatement(\"%s.%s((org.bson.types.Decimal128) decimal)\", varName, accessor)\n                            nextControlFlow(\"else if (decimal instanceof String)\")\n                                emitStatement(\"%s.%s(org.bson.types.Decimal128.parse((String)decimal))\", varName, accessor)\n                            nextControlFlow(\"else if (decimal instanceof Integer)\")\n                            emitStatement(\"%s.%s(new org.bson.types.Decimal128((Integer)(decimal)))\", varName, accessor, fieldName)\n                            nextControlFlow(\"else if (decimal instanceof Long)\")\n                                emitStatement(\"%s.%s(new org.bson.types.Decimal128((Long)(decimal)))\", varName, accessor, fieldName)\n                            nextControlFlow(\"else if (decimal instanceof Double)\")\n                                emitStatement(\"%s.%s(new org.bson.types.Decimal128(new java.math.BigDecimal((Double)(decimal))))\", varName, accessor, fieldName)\n                            nextControlFlow(\"else\")\n                                emitStatement(\"throw new UnsupportedOperationException(decimal.getClass() + \\\" is not supported as a Decimal128 value\\\")\")\n                            endControlFlow()\n                    endControlFlow()\n                endControlFlow()\n            }\n        }\n\n        @Throws(IOException::class)\n        override fun emitStreamTypeConversion(varName: String, accessor: String, fieldName: String, fieldType: QualifiedClassName, writer: JavaWriter, isPrimaryKey: Boolean) {\n            writer.apply {\n                beginControlFlow(\"if (reader.peek() == JsonToken.NULL)\")\n                    emitStatement(\"reader.skipValue()\")\n                    emitStatement(\"%s.%s(null)\", varName, accessor)\n                nextControlFlow(\"else\")\n                    emitStatement(\"%s.%s(org.bson.types.Decimal128.parse(reader.nextString()))\", varName, accessor)\n                endControlFlow()\n            }\n        }\n\n        @Throws(IOException::class)\n        override fun emitGetObjectWithPrimaryKeyValue(realmObjectClass: QualifiedClassName, realmObjectProxyClass: QualifiedClassName, fieldName: String, writer: JavaWriter) {\n            throw IllegalArgumentException(\"'Decimal128' is not allowed as a primary key value.\")\n        }\n    }\n\n    private class ObjectIdTypeConverter() : JsonToRealmFieldTypeConverter {\n        @Throws(IOException::class)\n        override fun emitTypeConversion(varName: String, accessor: String, fieldName: String, fieldType: QualifiedClassName, writer: JavaWriter) {\n            writer.apply {\n                beginControlFlow(\"if (json.has(\\\"%s\\\"))\", fieldName)\n                    beginControlFlow(\"if (json.isNull(\\\"%s\\\"))\", fieldName)\n                        emitStatement(\"%s.%s(null)\", varName, accessor)\n                    nextControlFlow(\"else\")\n                        emitStatement(\"Object id = json.get(\\\"%s\\\")\", fieldName)\n                        beginControlFlow(\"if (id instanceof org.bson.types.ObjectId)\")\n                            emitStatement(\"%s.%s((org.bson.types.ObjectId) id)\", varName, accessor)\n                        nextControlFlow(\"else\")\n                            emitStatement(\"%s.%s(new org.bson.types.ObjectId((String)id))\", varName, accessor)\n                        endControlFlow()\n                    endControlFlow()\n                endControlFlow()\n            }\n        }\n\n        @Throws(IOException::class)\n        override fun emitStreamTypeConversion(varName: String, accessor: String, fieldName: String, fieldType: QualifiedClassName, writer: JavaWriter, isPrimaryKey: Boolean) {\n            writer.apply {\n                beginControlFlow(\"if (reader.peek() == JsonToken.NULL)\")\n                    emitStatement(\"reader.skipValue()\")\n                    emitStatement(\"%s.%s(null)\", varName, accessor)\n                nextControlFlow(\"else\")\n                    emitStatement(\"%s.%s(new org.bson.types.ObjectId(reader.nextString()))\", varName, accessor)\n                endControlFlow()\n            }\n        }\n\n        @Throws(IOException::class)\n        override fun emitGetObjectWithPrimaryKeyValue(realmObjectClass: QualifiedClassName, realmObjectProxyClass: QualifiedClassName, fieldName: String, writer: JavaWriter) {\n            // No error checking is done here for valid primary key types.\n            // This should be done by the annotation processor.\n            writer.apply {\n                beginControlFlow(\"if (json.has(\\\"%s\\\"))\", fieldName)\n                    beginControlFlow(\"if (json.isNull(\\\"%s\\\"))\", fieldName)\n                        emitStatement(\"obj = (%1\\$s) realm.createObjectInternal(%2\\$s.class, null, true, excludeFields)\", realmObjectProxyClass, realmObjectClass)\n                    nextControlFlow(\"else\")\n                        emitStatement(\"obj = (%1\\$s) realm.createObjectInternal(%2\\$s.class, json.get(\\\"%3\\$s\\\"), true, excludeFields)\", realmObjectProxyClass, realmObjectClass, fieldName)\n                    endControlFlow()\n                nextControlFlow(\"else\")\n                    emitStatement(Constants.STATEMENT_EXCEPTION_NO_PRIMARY_KEY_IN_JSON, fieldName)\n                endControlFlow()\n            }\n        }\n    }\n\n    private class UUIDTypeConverter() : JsonToRealmFieldTypeConverter {\n        @Throws(IOException::class)\n        override fun emitTypeConversion(varName: String, accessor: String, fieldName: String, fieldType: QualifiedClassName, writer: JavaWriter) {\n            writer.apply {\n                beginControlFlow(\"if (json.has(\\\"%s\\\"))\", fieldName)\n                    beginControlFlow(\"if (json.isNull(\\\"%s\\\"))\", fieldName)\n                        emitStatement(\"%s.%s(null)\", varName, accessor)\n                    nextControlFlow(\"else\")\n                        emitStatement(\"Object id = json.get(\\\"%s\\\")\", fieldName)\n                        beginControlFlow(\"if (id instanceof java.util.UUID)\")\n                            emitStatement(\"%s.%s((java.util.UUID) id)\", varName, accessor)\n                        nextControlFlow(\"else\")\n                            emitStatement(\"%s.%s(java.util.UUID.fromString((String)id))\", varName, accessor)\n                        endControlFlow()\n                    endControlFlow()\n                endControlFlow()\n            }\n        }\n\n        @Throws(IOException::class)\n        override fun emitStreamTypeConversion(varName: String, accessor: String, fieldName: String, fieldType: QualifiedClassName, writer: JavaWriter, isPrimaryKey: Boolean) {\n            writer.apply {\n                beginControlFlow(\"if (reader.peek() == JsonToken.NULL)\")\n                    emitStatement(\"reader.skipValue()\")\n                    emitStatement(\"%s.%s(null)\", varName, accessor)\n                nextControlFlow(\"else\")\n                    emitStatement(\"%s.%s(java.util.UUID.fromString(reader.nextString()))\", varName, accessor)\n                endControlFlow()\n            }\n        }\n\n        @Throws(IOException::class)\n        override fun emitGetObjectWithPrimaryKeyValue(realmObjectClass: QualifiedClassName, realmObjectProxyClass: QualifiedClassName, fieldName: String, writer: JavaWriter) {\n            // No error checking is done here for valid primary key types.\n            // This should be done by the annotation processor.\n            writer.apply {\n                beginControlFlow(\"if (json.has(\\\"%s\\\"))\", fieldName)\n                    beginControlFlow(\"if (json.isNull(\\\"%s\\\"))\", fieldName)\n                        emitStatement(\"obj = (%1\\$s) realm.createObjectInternal(%2\\$s.class, null, true, excludeFields)\", realmObjectProxyClass, realmObjectClass)\n                    nextControlFlow(\"else\")\n                        emitStatement(\"obj = (%1\\$s) realm.createObjectInternal(%2\\$s.class, json.get(\\\"%3\\$s\\\"), true, excludeFields)\", realmObjectProxyClass, realmObjectClass, fieldName)\n                    endControlFlow()\n                nextControlFlow(\"else\")\n                    emitStatement(Constants.STATEMENT_EXCEPTION_NO_PRIMARY_KEY_IN_JSON, fieldName)\n                endControlFlow()\n            }\n        }\n    }\n\n    private class RealmAnyTypeConverter() : JsonToRealmFieldTypeConverter {\n        @Throws(IOException::class)\n        override fun emitTypeConversion(varName: String, accessor: String, fieldName: String, fieldType: QualifiedClassName, writer: JavaWriter) {\n            writer.apply {\n                beginControlFlow(\"if (json.has(\\\"${fieldName}\\\"))\")\n                    beginControlFlow(\"if (json.isNull(\\\"${fieldName}\\\"))\")\n                        emitStatement(\"${varName}.${accessor}(null)\")\n                    nextControlFlow(\"else\")\n                        emitStatement(\"Object value = json.get(\\\"${fieldName}\\\")\")\n\n                        emitStatement(\"RealmAny realmAny\")\n\n                        beginControlFlow(\"if (value instanceof String)\")\n                            emitStatement(\"realmAny = RealmAny.valueOf((String) value)\")\n                        nextControlFlow(\"else if (value instanceof Integer)\")\n                            emitStatement(\"realmAny = RealmAny.valueOf((Integer) value)\")\n                        nextControlFlow(\"else if (value instanceof Long)\")\n                            emitStatement(\"realmAny = RealmAny.valueOf((Long) value)\")\n                        nextControlFlow(\"else if (value instanceof Double)\")\n                            emitStatement(\"realmAny = RealmAny.valueOf((Double) value)\")\n                        nextControlFlow(\"else if (value instanceof Boolean)\")\n                            emitStatement(\"realmAny = RealmAny.valueOf((Boolean) value)\")\n                        nextControlFlow(\"else if (value instanceof RealmAny)\")\n                            emitStatement(\"realmAny = (io.realm.RealmAny) value\")\n                            emitStatement(\"realmAny = ProxyUtils.copyOrUpdate(realmAny, realm, update, new HashMap<>(), new HashSet<>())\")\n                        nextControlFlow(\"else\")\n                            emitStatement(\"throw new IllegalArgumentException(String.format(\\\"Unsupported JSON type: %%s\\\", value.getClass().getSimpleName()))\")\n                        endControlFlow()\n                        emitStatement(\"${varName}.${accessor}(realmAny)\")\n                    endControlFlow()\n                endControlFlow()\n            }\n        }\n\n        @Throws(IOException::class)\n        override fun emitStreamTypeConversion(varName: String, accessor: String, fieldName: String, fieldType: QualifiedClassName, writer: JavaWriter, isPrimaryKey: Boolean) {\n            writer.apply {\n                beginControlFlow(\"if (reader.peek() == JsonToken.NULL)\")\n                    emitStatement(\"reader.skipValue()\")\n                    emitStatement(\"${varName}.${accessor}(RealmAny.nullValue())\")\n                nextControlFlow(\"else if (reader.peek() == JsonToken.STRING)\")\n                    emitStatement(\"${varName}.${accessor}(RealmAny.valueOf(reader.nextString()))\")\n                nextControlFlow(\"else if (reader.peek() == JsonToken.NUMBER)\")\n                    emitStatement(\"String value = reader.nextString()\")\n                    beginControlFlow(\"if (value.contains(\\\".\\\"))\")\n                        emitStatement(\"${varName}.${accessor}(RealmAny.valueOf(Double.parseDouble(value)))\")\n                    nextControlFlow(\"else\")\n                        emitStatement(\"${varName}.${accessor}(RealmAny.valueOf(Long.parseLong(value)))\")\n                    endControlFlow()\n                nextControlFlow(\"else if (reader.peek() == JsonToken.BOOLEAN)\")\n                    emitStatement(\"${varName}.${accessor}(RealmAny.valueOf(reader.nextBoolean()))\")\n                endControlFlow()\n            }\n        }\n\n        @Throws(IOException::class)\n        override fun emitGetObjectWithPrimaryKeyValue(realmObjectClass: QualifiedClassName, realmObjectProxyClass: QualifiedClassName, fieldName: String, writer: JavaWriter) {\n            throw IllegalArgumentException(\"'RealmAny' is not allowed as a primary key value.\")\n        }\n    }\n\n    private class MutableRealmIntegerTypeConverter : JsonToRealmFieldTypeConverter {\n        @Throws(IOException::class)\n        override fun emitTypeConversion(varName: String, accessor: String, fieldName: String, fieldType: QualifiedClassName, writer: JavaWriter) {\n            writer.apply {\n                beginControlFlow(\"if (json.has(\\\"%s\\\"))\", fieldName)\n                    emitStatement(\"%1\\$s.%2\\$s().set((json.isNull(\\\"%3\\$s\\\")) ? null : json.getLong(\\\"%3\\$s\\\"))\", varName, accessor, fieldName)\n                endControlFlow()\n            }\n        }\n\n        @Throws(IOException::class)\n        override fun emitStreamTypeConversion(varName: String, accessor: String, fieldName: String, fieldType: QualifiedClassName, writer: JavaWriter, isPrimaryKey: Boolean) {\n            writer.apply {\n                emitStatement(\"Long val = null\")\n                beginControlFlow(\"if (reader.peek() != JsonToken.NULL)\")\n                    emitStatement(\"val = reader.nextLong()\")\n                nextControlFlow(\"else\")\n                    emitStatement(\"reader.skipValue()\")\n                endControlFlow()\n                emitStatement(\"%1\\$s.%2\\$s().set(val)\", varName, accessor)\n            }\n        }\n\n        @Throws(IOException::class)\n        override fun emitGetObjectWithPrimaryKeyValue(realmObjectClass: QualifiedClassName, realmObjectProxyClass: QualifiedClassName, fieldName: String, writer: JavaWriter) {\n            throw IllegalArgumentException(\"'MutableRealmInteger' is not allowed as a primary key value.\")\n        }\n    }\n\n    private interface JsonToRealmFieldTypeConverter {\n        @Throws(IOException::class)\n        fun emitTypeConversion(varName: String,\n                               accessor: String,\n                               fieldName: String,\n                               fieldType: QualifiedClassName,\n                               writer: JavaWriter)\n\n        @Throws(IOException::class)\n        fun emitStreamTypeConversion(varName: String,\n                                     accessor: String,\n                                     fieldName: String,\n                                     fieldType: QualifiedClassName,\n                                     writer: JavaWriter,\n                                     isPrimaryKey: Boolean)\n\n        @Throws(IOException::class)\n        fun emitGetObjectWithPrimaryKeyValue(realmObjectClass: QualifiedClassName,\n                                             realmObjectProxyClass: QualifiedClassName,\n                                             fieldName: String,\n                                             writer: JavaWriter)\n    }\n}\n"
  },
  {
    "path": "realm/realm-annotations-processor/src/main/java/io/realm/processor/RealmProcessor.kt",
    "content": "/*\n * Copyright 2019 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\npackage io.realm.processor\n\nimport io.realm.annotations.RealmClass\nimport io.realm.annotations.RealmModule\nimport java.io.IOException\nimport java.util.*\nimport javax.annotation.processing.AbstractProcessor\nimport javax.annotation.processing.RoundEnvironment\nimport javax.annotation.processing.SupportedAnnotationTypes\nimport javax.annotation.processing.SupportedOptions\nimport javax.lang.model.SourceVersion\nimport javax.lang.model.element.ElementKind\nimport javax.lang.model.element.Name\nimport javax.lang.model.element.TypeElement\nimport javax.lang.model.type.DeclaredType\nimport javax.lang.model.type.TypeMirror\n\n\n/**\n * The RealmProcessor is responsible for creating the plumbing that connects the RealmObjects to a\n * Realm. The process for doing so is summarized below and then described in more detail.\n *\n * <h1>DESIGN GOALS</h1>\n *\n * The processor should support the following design goals:\n *\n *  * Minimize reflection.\n *  * Realm code can be obfuscated as much as possible.\n *  * Library projects must be able to use Realm without interfering with app code.\n *  * App code must be able to use RealmObject classes provided by library code.\n *  * It should work for app developers out of the box (ie. put the burden on the library developer)\n *\n * <h1>SUMMARY</h1>\n *\n *  1. Create proxy classes for all classes marked with @RealmClass. They are named\n *     `<className>RealmProxy.java`.\n *  2. Create a DefaultRealmModule containing all RealmObject classes (if needed).\n *  3. Create a RealmProxyMediator class for all classes marked with `@RealmModule`. They are named\n *     `<moduleName>Mediator.java`\n *\n * <h1>WHY</h1>\n *\n *  1. A RealmObjectProxy object is created for each class annotated with\n *     [io.realm.annotations.RealmClass]. This proxy extends the original RealmObject class and\n *     rewires all field access to point to the native Realm memory instead of Java memory. It also\n *     adds some static helper methods to the class.\n *\n *  2. The annotation processor is either in \"library\" mode or in \"app\" mode. This is defined by\n *     having a class annotated with @RealmModule(library = true). It is not allowed to have both a\n *     class with `library = true` and `library = false` in the same IntelliJ module and it will\n *     cause the annotation processor to throw an exception. If no library modules are defined, we\n *     will create a DefaultRealmModule containing all known RealmObjects and with the\n *     `@RealmModule` annotation. Realm automatically knows about this module, but it is still\n *     possible for users to create their own modules with a subset of model classes.\n *\n *  3. For each class annotated with @RealmModule a matching Mediator class is created (including\n *     the default one). This class has an interface that matches the static helper methods for the\n *     proxy classes. All access to these static helper methods should be done through this Mediator.\n *\n * This allows ProGuard to obfuscate all RealmObject and proxy classes as all access to the static\n * methods now happens through the Mediator, and the only requirement is now that only RealmModule\n * and Mediator class names cannot be obfuscated.\n *\n * <h1>CREATING A REALM</h1>\n *\n * This means the workflow when instantiating a Realm on runtime is the following:\n *\n *  1. Open a Realm.\n *  2. Assign one or more modules (that are allowed to overlap). If no module is assigned, the\n *     default module is used.\n *  3. The Realm schema is now defined as all RealmObject classes known by these modules.\n *  4. Each time a static helper method is needed, Realm can now delegate these method calls to the\n *     appropriate Mediator which in turn will delegate the method call to the appropriate\n *     RealmObjectProxy class.\n *\n * <h1>CREATING A MANAGED RealmObject</h1>\n *\n * To allow to specify default values by model's constructor or direct field assignment, the flow of\n * creating the proxy object is a bit complicated. This section illustrates how proxy object should\n * be created.\n *\n *  1. Get the thread local `io.realm.BaseRealm.RealmObjectContext` instance by\n *     `BaseRealm.objectContext.get()`\n *  2. Set the object context information to the `RealmObjectContext` those should be set to the\n *     creating proxy object.\n *  3. Create proxy object (`new io.realm.FooRealmProxy()`).\n *  4. Set the object context information to the created proxy when the first access of its\n *     accessors (or in its constructor if accessors are not used in the model's constructor).\n *  5. Clear the object context information in the thread local\n *     `io.realm.BaseRealm.RealmObjectContext` instance by calling `#clear()` method.\n *\n * The reason of this complicated step is that we can't pass these context information\n * via the constructor of the proxy. It's because the constructor of the proxy is executed\n * **after** the constructor of the model class. The access to the fields in the model's\n * constructor happens before the assignment of the context information to the 'proxyState'.\n * This will cause the [NullPointerException] if getters/setter is accessed in the model's\n * constructor (see [Issue #2536](https://github.com/realm/realm-java/issues/2536)).\n */\n\ninline class QualifiedClassName(val name: String) {\n    constructor(name: Name): this(name.toString())\n    constructor(name: TypeMirror) : this(name.toString())\n    fun getSimpleName(): SimpleClassName {\n        return SimpleClassName(Utils.stripPackage(name))\n    }\n    override fun toString(): String {\n        return name\n    }\n}\ninline class SimpleClassName(val name: String) {\n    constructor(name: Name): this(name.toString())\n    override fun toString(): String {\n        return name\n    }\n}\n\n@SupportedAnnotationTypes(\n        \"io.realm.annotations.RealmClass\",\n        \"io.realm.annotations.RealmField\",\n        \"io.realm.annotations.Ignore\",\n        \"io.realm.annotations.Index\",\n        \"io.realm.annotations.PrimaryKey\",\n        \"io.realm.annotations.RealmModule\",\n        \"io.realm.annotations.Required\")\n@SupportedOptions(value = [\"realm.suppressWarnings\", \"realm.ignoreKotlinNullability\"])\nclass RealmProcessor : AbstractProcessor() {\n\n    // Don't consume annotations. This allows 3rd party annotation processors to run.\n    private val CONSUME_ANNOTATIONS = false\n    private val ABORT = true // Abort the annotation processor by consuming all annotations\n\n    private val classCollection = ClassCollection() // Metadata for all classes found\n    private lateinit var moduleMetaData: ModuleMetaData // Metadata for all modules found\n\n    // List of backlinks\n    private val backlinksToValidate = HashSet<Backlink>()\n\n    // List of realm model sets\n    private val realmModelSetsToValidate = HashSet<RealmFieldElement>()\n\n    private var hasProcessedModules = false\n    private var round = -1\n\n    override fun getSupportedSourceVersion(): SourceVersion {\n        return SourceVersion.latestSupported()\n    }\n\n    override fun process(annotations: Set<TypeElement>, roundEnv: RoundEnvironment): Boolean {\n        round++\n\n        if (round == 0) {\n            RealmVersionChecker.getInstance(processingEnv).executeRealmVersionUpdate()\n        }\n\n        if (roundEnv.errorRaised()) {\n            return ABORT\n        }\n\n        if (!hasProcessedModules) {\n            Utils.initialize(processingEnv)\n            val typeMirrors = TypeMirrors(processingEnv)\n\n            // Build up internal metadata while validating as much as possible\n            if (!preProcessModules(roundEnv)) {\n                return ABORT\n            }\n            if (!processClassAnnotations(roundEnv, typeMirrors)) {\n                return ABORT\n            }\n            if (!postProcessModules()) {\n                return ABORT\n            }\n            if (!validateBacklinks()) {\n                return ABORT\n            }\n            if (!validateRealmModelSets()) {\n                return ABORT\n            }\n            hasProcessedModules = true\n\n            // Create all files\n            if (!createProxyClassFiles(typeMirrors)) {\n                return ABORT\n            }\n            if (!createModuleFiles()) {\n                return ABORT\n            }\n        }\n\n        return CONSUME_ANNOTATIONS\n    }\n\n    // Create all proxy classes\n    private fun processClassAnnotations(roundEnv: RoundEnvironment, typeMirrors: TypeMirrors): Boolean {\n\n        for (classElement in roundEnv.getElementsAnnotatedWith(RealmClass::class.java)) {\n\n            // The class must either extend RealmObject or implement RealmModel\n            if (!Utils.isImplementingMarkerInterface(classElement)) {\n                Utils.error(\"A RealmClass annotated object must implement RealmModel or derive from RealmObject.\", classElement)\n                return false\n            }\n\n            // Check the annotation was applied to a Class\n            if (classElement.kind != ElementKind.CLASS) {\n                Utils.error(\"The RealmClass annotation can only be applied to classes.\", classElement)\n                return false\n            }\n\n            val metadata = ClassMetaData(processingEnv, typeMirrors, classElement as TypeElement)\n            if (!metadata.isModelClass) {\n                continue\n            }\n\n            Utils.note(\"Processing class \" + metadata.simpleJavaClassName)\n            if (!metadata.generate(moduleMetaData)) {\n                return false\n            }\n\n            classCollection.addClass(metadata)\n            backlinksToValidate.addAll(metadata.backlinkFields)\n            realmModelSetsToValidate.addAll(metadata.realmModelSetFields)\n        }\n\n        return true\n    }\n\n    // Returns true if modules were processed successfully, false otherwise\n    private fun preProcessModules(roundEnv: RoundEnvironment): Boolean {\n        moduleMetaData = ModuleMetaData()\n        return moduleMetaData.preProcess(roundEnv.getElementsAnnotatedWith(RealmModule::class.java))\n    }\n\n    // Returns true of modules where successfully validated, false otherwise\n    private fun postProcessModules(): Boolean {\n        return moduleMetaData.postProcess(classCollection)\n    }\n\n    private fun createModuleFiles(): Boolean {\n        // Create default module if needed\n        if (moduleMetaData.shouldCreateDefaultModule()) {\n            if (!createDefaultModule()) {\n                return false\n            }\n        }\n\n        // Create RealmProxyMediators for all Realm modules\n        for ((key, value) in moduleMetaData.allModules) {\n            if (!createMediator(key.getSimpleName(), value)) {\n                return false\n            }\n        }\n\n        return true\n    }\n\n    private fun createProxyClassFiles(typeMirrors: TypeMirrors): Boolean {\n        for (metadata in classCollection.classes) {\n            val interfaceGenerator = RealmProxyInterfaceGenerator(processingEnv, metadata)\n            try {\n                interfaceGenerator.generate()\n            } catch (e: IOException) {\n                Utils.error(e.message, metadata.classElement)\n                return false\n            }\n\n            val sourceCodeGenerator = RealmProxyClassGenerator(processingEnv, typeMirrors, metadata, classCollection)\n            try {\n                sourceCodeGenerator.generate()\n            } catch (e: IOException) {\n                Utils.error(e.message, metadata.classElement)\n                return false\n            } catch (e: UnsupportedOperationException) {\n                Utils.error(e.message, metadata.classElement)\n                return false\n            }\n\n        }\n        return true\n    }\n\n    private fun createDefaultModule(): Boolean {\n        Utils.note(\"Creating DefaultRealmModule\")\n        val defaultModuleGenerator = DefaultModuleGenerator(processingEnv)\n        try {\n            defaultModuleGenerator.generate()\n        } catch (e: IOException) {\n            Utils.error(e.message)\n            return false\n        }\n\n        return true\n    }\n\n    private fun createMediator(moduleName: SimpleClassName, moduleClasses: Set<ClassMetaData>): Boolean {\n        val mediatorImplGenerator = RealmProxyMediatorGenerator(processingEnv, moduleName, moduleClasses)\n        try {\n            mediatorImplGenerator.generate()\n        } catch (e: IOException) {\n            Utils.error(e.message)\n            return false\n        }\n\n        return true\n    }\n\n    // Because library classes are processed separately, there is no guarantee that this method can\n    // see all of the classes necessary to completely validate all of the backlinks.  If it can find\n    // the fully-qualified class, though, and prove that the class either does not contain the\n    // necessary field, or that it does contain the field, but the field is of the wrong type, it\n    // can catch the error at compile time. Otherwise it is caught at runtime, when validating the\n    // schema.\n    private fun validateBacklinks(): Boolean {\n        var allValid = true\n\n        for (backlink in backlinksToValidate) {\n            // If the class is not here it might be part of some other compilation unit.\n            if (!classCollection.containsQualifiedClass(backlink.sourceClass)) {\n                continue\n            }\n            val clazz = classCollection.getClassFromQualifiedName(backlink.sourceClass!!)\n\n            // If the class is here, we can validate it.\n            if (!backlink.validateTarget(clazz) && allValid) {\n                allValid = false\n            }\n        }\n\n        return allValid\n    }\n\n    // Because library classes are processed separately, there is no guarantee that this method can\n    // see all of the classes necessary to completely validate all of the realm model sets.  If it can find\n    // the fully-qualified class, though, and prove that the generic type is an embedded object,\n    // it can catch the error at compile time. Otherwise it is caught at runtime, when validating the\n    // schema.\n    private fun validateRealmModelSets(): Boolean {\n        var allValid = true\n\n        for (field in realmModelSetsToValidate) {\n            val genericClassName = (field.asType() as DeclaredType).typeArguments.toString()\n            val genericType = processingEnv.elementUtils.getTypeElement(genericClassName).asType()\n\n            val embedded = Utils.isFieldTypeEmbedded(genericType, classCollection)\n            if(embedded && allValid){\n                Utils.error(\"RealmSets field ${field.javaName} at ${field.fieldReference} do not support embedded objects.\")\n                allValid = false\n            }\n        }\n\n        return allValid\n    }\n}\n"
  },
  {
    "path": "realm/realm-annotations-processor/src/main/java/io/realm/processor/RealmProxyClassGenerator.kt",
    "content": "/*\n * Copyright 2019 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\npackage io.realm.processor\n\nimport com.squareup.javawriter.JavaWriter\nimport io.realm.processor.Utils.fieldTypeHasPrimaryKey\nimport io.realm.processor.Utils.getGenericType\nimport io.realm.processor.ext.beginMethod\nimport io.realm.processor.ext.beginType\nimport java.io.BufferedWriter\nimport java.io.IOException\nimport java.util.*\nimport javax.annotation.processing.ProcessingEnvironment\nimport javax.lang.model.element.Modifier\nimport javax.lang.model.element.VariableElement\nimport javax.lang.model.type.DeclaredType\nimport javax.lang.model.type.TypeMirror\nimport javax.tools.JavaFileObject\n\n/**\n * This class is responsible for generating the Realm Proxy classes for each model class defined\n * by the user. This is the main entrypoint for users interacting with Realm, but it is hidden\n * from them as an implementation detail generated by the annotation processor.\n *\n * See [RealmProcessor] for a more detailed description on what files Realm creates internally and\n * why.\n *\n * NOTE: This file will look strangely formatted to you. This is on purpose. The intent of the\n * formatting it is to better represent the outputted code, not make _this_ code as readable as\n * possible. This mean two things:\n *\n * 1. Attempt to keep code that emit a single line to one line here.\n * 2. Attempt to indent the emit functions that would emulate the blocks created by the generated code.\n */\nclass RealmProxyClassGenerator(private val processingEnvironment: ProcessingEnvironment,\n                               private val typeMirrors: TypeMirrors,\n                               private val metadata: ClassMetaData,\n                               private val classCollection: ClassCollection) {\n\n    private val simpleJavaClassName: SimpleClassName = metadata.simpleJavaClassName\n    private val qualifiedJavaClassName: QualifiedClassName = metadata.qualifiedClassName\n    private val internalClassName: String = metadata.internalClassName\n    private val interfaceName: SimpleClassName = Utils.getProxyInterfaceName(qualifiedJavaClassName)\n    private val generatedClassName: QualifiedClassName = QualifiedClassName(String.format(Locale.US, \"%s.%s\", Constants.REALM_PACKAGE_NAME, Utils.getProxyClassName(qualifiedJavaClassName)))\n    // See the configuration for the Android debug build type,\n    //  in the realm-library project, for an example of how to set this flag.\n    private val suppressWarnings: Boolean = !\"false\".equals(processingEnvironment.options[OPTION_SUPPRESS_WARNINGS], ignoreCase = true)\n\n    lateinit var sourceFile: JavaFileObject\n    @Throws(IOException::class, UnsupportedOperationException::class)\n    fun generate() {\n        sourceFile = processingEnvironment.filer.createSourceFile(generatedClassName.toString())\n\n        val imports = ArrayList(IMPORTS)\n        if (metadata.backlinkFields.isNotEmpty()) {\n            imports.add(\"io.realm.internal.UncheckedRow\")\n        }\n\n        val writer = JavaWriter(BufferedWriter(sourceFile.openWriter()))\n        writer.apply {\n            indent = Constants.INDENT // Set source code indent\n            emitPackage(Constants.REALM_PACKAGE_NAME)\n            emitEmptyLine()\n            emitImports(imports)\n            emitEmptyLine()\n\n            // Begin the class definition\n            if (suppressWarnings) {\n                emitAnnotation(\"SuppressWarnings(\\\"all\\\")\")\n            }\n            beginType(generatedClassName, \"class\", setOf(Modifier.PUBLIC), qualifiedJavaClassName, arrayOf(\"RealmObjectProxy\", interfaceName.toString()))\n            emitEmptyLine()\n\n            // Emit class content\n            emitColumnInfoClass(writer)\n            emitClassFields(writer)\n            emitInstanceFields(writer)\n            emitConstructor(writer)\n            emitInjectContextMethod(writer)\n            emitPersistedFieldAccessors(writer)\n            emitBacklinkFieldAccessors(writer)\n            emitCreateExpectedObjectSchemaInfo(writer)\n            emitGetExpectedObjectSchemaInfo(writer)\n            emitCreateColumnInfoMethod(writer)\n            emitGetSimpleClassNameMethod(writer)\n            emitCreateOrUpdateUsingJsonObject(writer)\n            emitCreateUsingJsonStream(writer)\n            emitNewProxyInstance(writer)\n            emitCopyOrUpdateMethod(writer)\n            emitCopyMethod(writer)\n            emitInsertMethod(writer)\n            emitInsertListMethod(writer)\n            emitInsertOrUpdateMethod(writer)\n            emitInsertOrUpdateListMethod(writer)\n            emitCreateDetachedCopyMethod(writer)\n            emitUpdateMethod(writer)\n            emitUpdateEmbeddedObjectMethod(writer)\n            emitToStringMethod(writer)\n            emitRealmObjectProxyImplementation(writer)\n            emitHashcodeMethod(writer)\n            emitEqualsMethod(writer)\n\n            // End the class definition\n            endType()\n            close()\n        }\n    }\n\n    @Throws(IOException::class)\n    private fun emitColumnInfoClass(writer: JavaWriter) {\n        writer.apply {\n            beginType(columnInfoClassName(), \"class\", EnumSet.of(Modifier.STATIC, Modifier.FINAL), \"ColumnInfo\")                               // base class\n\n            // fields\n            for (variableElement in metadata.fields) {\n                emitField(\"long\", columnKeyVarName(variableElement))\n            }\n            emitEmptyLine()\n\n            // constructor #1\n            beginConstructor(EnumSet.noneOf(Modifier::class.java), \"OsSchemaInfo\", \"schemaInfo\")\n                emitStatement(\"super(%s)\", metadata.fields.size)\n                emitStatement(\"OsObjectSchemaInfo objectSchemaInfo = schemaInfo.getObjectSchemaInfo(\\\"%1\\$s\\\")\", internalClassName)\n                for (field in metadata.fields) {\n                    emitStatement(\"this.%1\\$sColKey = addColumnDetails(\\\"%1\\$s\\\", \\\"%2\\$s\\\", objectSchemaInfo)\", field.javaName, field.internalFieldName)\n                }\n                for (backlink in metadata.backlinkFields) {\n                    val sourceClass = classCollection.getClassFromQualifiedName(backlink.sourceClass!!)\n                    val internalSourceClassName = sourceClass.internalClassName\n                    val internalSourceFieldName = sourceClass.getInternalFieldName(backlink.sourceField!!)\n                    emitStatement(\"addBacklinkDetails(schemaInfo, \\\"%s\\\", \\\"%s\\\", \\\"%s\\\")\", backlink.targetField, internalSourceClassName, internalSourceFieldName)\n                }\n            endConstructor()\n            emitEmptyLine()\n\n            // constructor #2\n            beginConstructor(EnumSet.noneOf(Modifier::class.java),\"ColumnInfo\", \"src\", \"boolean\", \"mutable\")\n                emitStatement(\"super(src, mutable)\")\n                emitStatement(\"copy(src, this)\")\n            endConstructor()\n            emitEmptyLine()\n\n            // no-args copy method\n            emitAnnotation(\"Override\")\n            beginMethod(\"ColumnInfo\", \"copy\", EnumSet.of(Modifier.PROTECTED, Modifier.FINAL), \"boolean\", \"mutable\")\n                emitStatement(\"return new %s(this, mutable)\", columnInfoClassName())\n            endMethod()\n            emitEmptyLine()\n\n            // copy method\n            emitAnnotation(\"Override\")\n            beginMethod(\"void\", \"copy\", EnumSet.of(Modifier.PROTECTED, Modifier.FINAL), \"ColumnInfo\", \"rawSrc\", \"ColumnInfo\", \"rawDst\")\n                emitStatement(\"final %1\\$s src = (%1\\$s) rawSrc\", columnInfoClassName())\n                emitStatement(\"final %1\\$s dst = (%1\\$s) rawDst\", columnInfoClassName())\n                for (variableElement in metadata.fields) {\n                    emitStatement(\"dst.%1\\$s = src.%1\\$s\", columnKeyVarName(variableElement))\n                }\n            endMethod()\n            endType()\n        }\n    }\n\n    @Throws(IOException::class)\n    private fun emitClassFields(writer: JavaWriter) {\n        writer.apply {\n            emitEmptyLine()\n            // This should ideally have been placed outside the Proxy classes, but due to an unknown\n            // issue in the compile-testing framework, this kept failing tests. Keeping it here\n            // fixes that.\n            emitField(\"String\", \"NO_ALIAS\", EnumSet.of(Modifier.PRIVATE, Modifier.STATIC, Modifier.FINAL), \"\\\"\\\"\")\n            emitField(\"OsObjectSchemaInfo\", \"expectedObjectSchemaInfo\", EnumSet.of(Modifier.PRIVATE, Modifier.STATIC, Modifier.FINAL),\"createExpectedObjectSchemaInfo()\")\n        }\n    }\n\n    @Throws(IOException::class)\n    private fun emitInstanceFields(writer: JavaWriter) {\n        writer.apply {\n            emitEmptyLine()\n            emitField(columnInfoClassName(), \"columnInfo\", EnumSet.of(Modifier.PRIVATE))\n            emitField(\"ProxyState<$qualifiedJavaClassName>\", \"proxyState\", EnumSet.of(Modifier.PRIVATE))\n\n            for (variableElement in metadata.fields) {\n                if (Utils.isMutableRealmInteger(variableElement)) {\n                    emitMutableRealmIntegerField(writer, variableElement)\n                } else if (Utils.isRealmList(variableElement)) {\n                    val genericType = Utils.getGenericTypeQualifiedName(variableElement)\n                    emitField(\"RealmList<$genericType>\", \"${variableElement.simpleName}RealmList\", EnumSet.of(Modifier.PRIVATE))\n                } else if (Utils.isRealmDictionary(variableElement)) {\n                    val valueType = Utils.getDictionaryValueTypeQualifiedName(variableElement)\n                    emitField(\"RealmDictionary<$valueType>\", \"${variableElement.simpleName}RealmDictionary\", EnumSet.of(Modifier.PRIVATE))\n                } else if (Utils.isRealmSet(variableElement)) {\n                    val valueType = Utils.getGenericTypeQualifiedName(variableElement)\n                    emitField(\"RealmSet<$valueType>\", \"${variableElement.simpleName}RealmSet\", EnumSet.of(Modifier.PRIVATE))\n                }\n            }\n\n            for (backlink in metadata.backlinkFields) {\n                emitField(backlink.targetFieldType, backlink.targetField + BACKLINKS_FIELD_EXTENSION, EnumSet.of(Modifier.PRIVATE))\n            }\n        }\n    }\n\n    // The anonymous subclass of MutableRealmInteger.Managed holds a reference to this proxy.\n    // Even if all other references to the proxy are dropped, the proxy will not be GCed until\n    // the MutableInteger that it owns, also becomes unreachable.\n    @Throws(IOException::class)\n    private fun emitMutableRealmIntegerField(writer: JavaWriter, variableElement: VariableElement) {\n        writer.apply {\n            emitField(\"MutableRealmInteger.Managed\",\n                    mutableRealmIntegerFieldName(variableElement),\n                    EnumSet.of(Modifier.PRIVATE, Modifier.FINAL),\n                    String.format(\n                            \"new MutableRealmInteger.Managed<%1\\$s>() {\\n\"\n                                    + \"    @Override protected ProxyState<%1\\$s> getProxyState() { return proxyState; }\\n\"\n                                    + \"    @Override protected long getColumnIndex() { return columnInfo.%2\\$s; }\\n\"\n                                    + \"}\",\n                            qualifiedJavaClassName, columnKeyVarName(variableElement)))\n        }\n    }\n\n    @Throws(IOException::class)\n    private fun emitConstructor(writer: JavaWriter) {\n        writer.apply {\n            emitEmptyLine()\n            beginConstructor(EnumSet.noneOf(Modifier::class.java))\n                emitStatement(\"proxyState.setConstructionFinished()\")\n            endConstructor()\n            emitEmptyLine()\n        }\n    }\n\n    @Throws(IOException::class)\n    private fun emitPersistedFieldAccessors(writer: JavaWriter) {\n        for (field in metadata.fields) {\n            val fieldName = field.simpleName.toString()\n            val fieldTypeCanonicalName = field.asType().toString()\n            when {\n                Constants.JAVA_TO_REALM_TYPES.containsKey(fieldTypeCanonicalName) -> emitPrimitiveType(writer, field, fieldName, fieldTypeCanonicalName)\n                Utils.isMutableRealmInteger(field) -> emitMutableRealmInteger(writer, field, fieldName, fieldTypeCanonicalName)\n                Utils.isRealmAny(field) -> emitRealmAny(writer, field, fieldName, fieldTypeCanonicalName)\n                Utils.isRealmModel(field) -> emitRealmModel(writer, field, fieldName, fieldTypeCanonicalName)\n                Utils.isRealmList(field) -> {\n                    val elementTypeMirror = TypeMirrors.getRealmListElementTypeMirror(field)\n                    emitRealmList(writer, field, fieldName, fieldTypeCanonicalName, elementTypeMirror)\n                }\n                Utils.isRealmDictionary(field) -> {\n                    val valueTypeMirror = TypeMirrors.getRealmDictionaryElementTypeMirror(field)\n                    emitRealmDictionary(writer, field, fieldName, fieldTypeCanonicalName, requireNotNull(valueTypeMirror))\n                }\n                Utils.isRealmSet(field) -> {\n                    val valueTypeMirror = TypeMirrors.getRealmSetElementTypeMirror(field)\n                    emitRealmSet(writer, field, fieldName, fieldTypeCanonicalName, requireNotNull(valueTypeMirror))\n                }\n                else -> throw UnsupportedOperationException(String.format(Locale.US, \"Field \\\"%s\\\" of type \\\"%s\\\" is not supported.\", fieldName, fieldTypeCanonicalName))\n            }\n            writer.emitEmptyLine()\n        }\n    }\n\n    /**\n     * Emit Set/Get methods for Primitives and boxed types\n     */\n    @Throws(IOException::class)\n    private fun emitPrimitiveType(\n            writer: JavaWriter,\n            field: VariableElement,\n            fieldName: String,\n            fieldTypeCanonicalName: String) {\n\n        val fieldJavaType: String? = getRealmTypeChecked(field).javaType\n\n        writer.apply {\n            // Getter - Start\n            emitAnnotation(\"Override\")\n            emitAnnotation(\"SuppressWarnings\", \"\\\"cast\\\"\")\n            beginMethod(fieldTypeCanonicalName, metadata.getInternalGetter(fieldName), EnumSet.of(Modifier.PUBLIC))\n                emitStatement(\"proxyState.getRealm\\$realm().checkIfValid()\")\n\n                // For String and bytes[], null value will be returned by JNI code. Try to save one JNI call here.\n                if (metadata.isNullable(field) && !Utils.isString(field) && !Utils.isByteArray(field)) {\n                    beginControlFlow(\"if (proxyState.getRow\\$realm().isNull(%s))\", fieldColKeyVariableReference(field))\n                        emitStatement(\"return null\")\n                    endControlFlow()\n                }\n\n                // For Boxed types, this should be the corresponding primitive types. Others remain the same.\n                val castingBackType: String = if (Utils.isBoxedType(fieldTypeCanonicalName)) {\n                    val typeUtils = processingEnvironment.typeUtils\n                    typeUtils.unboxedType(field.asType()).toString()\n                } else {\n                    fieldTypeCanonicalName\n                }\n\n                emitStatement(\"return (%s) proxyState.getRow\\$realm().get%s(%s)\", castingBackType, fieldJavaType, fieldColKeyVariableReference(field))\n            endMethod()\n            emitEmptyLine()\n            // Getter - End\n\n            // Setter - Start\n            emitAnnotation(\"Override\")\n            beginMethod(\"void\", metadata.getInternalSetter(fieldName), EnumSet.of(Modifier.PUBLIC), fieldTypeCanonicalName, \"value\")\n                emitCodeForUnderConstruction(writer, metadata.isPrimaryKey(field)) {\n                    // set value as default value\n                    emitStatement(\"final Row row = proxyState.getRow\\$realm()\")\n                    if (metadata.isNullable(field)) {\n                        beginControlFlow(\"if (value == null)\")\n                            emitStatement(\"row.getTable().setNull(%s, row.getObjectKey(), true)\", fieldColKeyVariableReference(field))\n                            emitStatement(\"return\")\n                        endControlFlow()\n                    } else if (!metadata.isNullable(field) && !Utils.isPrimitiveType(field)) {\n                        beginControlFlow(\"if (value == null)\")\n                            emitStatement(Constants.STATEMENT_EXCEPTION_ILLEGAL_NULL_VALUE, fieldName)\n                        endControlFlow()\n                    }\n                    emitStatement(\"row.getTable().set%s(%s, row.getObjectKey(), value, true)\", fieldJavaType, fieldColKeyVariableReference(field))\n                    emitStatement(\"return\")\n                }\n                emitStatement(\"proxyState.getRealm\\$realm().checkIfValid()\")\n                // Although setting null value for String and bytes[] can be handled by the JNI code, we still generate the same code here.\n                // Compared with getter, null value won't trigger more native calls in setter which is relatively cheaper.\n                if (metadata.isPrimaryKey(field)) {\n                    // Primary key is not allowed to be changed after object created.\n                    emitStatement(Constants.STATEMENT_EXCEPTION_PRIMARY_KEY_CANNOT_BE_CHANGED, fieldName)\n                } else {\n                    if (metadata.isNullable(field)) {\n                        beginControlFlow(\"if (value == null)\")\n                            emitStatement(\"proxyState.getRow\\$realm().setNull(%s)\", fieldColKeyVariableReference(field))\n                            emitStatement(\"return\")\n                        endControlFlow()\n                    } else if (!metadata.isNullable(field) && !Utils.isPrimitiveType(field)) {\n                        // Same reason, throw IAE earlier.\n                        beginControlFlow(\"if (value == null)\")\n                            emitStatement(Constants.STATEMENT_EXCEPTION_ILLEGAL_NULL_VALUE, fieldName)\n                        endControlFlow()\n                    }\n                    emitStatement(\"proxyState.getRow\\$realm().set%s(%s, value)\", fieldJavaType, fieldColKeyVariableReference(field))\n                }\n            endMethod()\n            // Setter - End\n        }\n    }\n\n    /**\n     * Emit Get method for mutable Realm Integer fields.\n     */\n    @Throws(IOException::class)\n    private fun emitMutableRealmInteger(writer: JavaWriter, field: VariableElement, fieldName: String, fieldTypeCanonicalName: String) {\n        writer.apply {\n            emitAnnotation(\"Override\")\n            beginMethod(fieldTypeCanonicalName, metadata.getInternalGetter(fieldName), EnumSet.of(Modifier.PUBLIC))\n            emitStatement(\"proxyState.getRealm\\$realm().checkIfValid()\")\n            emitStatement(\"return this.%s\", mutableRealmIntegerFieldName(field))\n            endMethod()\n        }\n    }\n\n    /**\n     * Emit Get method for RealmAny fields.\n     */\n    @Throws(IOException::class)\n    private fun emitRealmAny(writer: JavaWriter, field: VariableElement, fieldName: String, fieldTypeCanonicalName: String) {\n        writer.apply {\n            // Getter - Start\n            emitAnnotation(\"Override\")\n            beginMethod(fieldTypeCanonicalName, metadata.getInternalGetter(fieldName), EnumSet.of(Modifier.PUBLIC))\n                emitStatement(\"proxyState.getRealm\\$realm().checkIfValid()\")\n                emitStatement(\"NativeRealmAny nativeRealmAny = proxyState.getRow\\$realm().getNativeRealmAny(%s)\", fieldColKeyVariableReference(field))\n                emitStatement(\"return new RealmAny(RealmAnyOperator.fromNativeRealmAny(proxyState.getRealm\\$realm(), nativeRealmAny))\")\n            endMethod()\n            // Getter - End\n\n            emitEmptyLine()\n\n            // Setter - Start\n            emitAnnotation(\"Override\")\n            beginMethod(\"void\", metadata.getInternalSetter(fieldName), EnumSet.of(Modifier.PUBLIC), fieldTypeCanonicalName, \"value\")\n\n            emitCodeForUnderConstruction(writer, metadata.isPrimaryKey(field)) {\n                beginControlFlow(\"if (proxyState.getExcludeFields\\$realm().contains(\\\"%1\\$s\\\"))\", field.simpleName.toString())\n                    emitStatement(\"return\")\n                endControlFlow()\n                emitEmptyLine()\n                emitStatement(\"value = ProxyUtils.copyToRealmIfNeeded(proxyState, value)\")\n                emitEmptyLine()\n                emitStatement(\"final Row row = proxyState.getRow\\$realm()\")\n                beginControlFlow(\"if (value == null)\")\n                    emitStatement(\"row.getTable().setNull(%s, row.getObjectKey(), true)\", fieldColKeyVariableReference(field))\n                    emitStatement(\"return\")\n                endControlFlow()\n                emitStatement(\"row.getTable().setRealmAny(%s, row.getObjectKey(), value.getNativePtr(), true)\", fieldColKeyVariableReference(field))\n                emitStatement(\"return\")\n\n            }\n            emitEmptyLine()\n            emitStatement(\"proxyState.getRealm\\$realm().checkIfValid()\")\n            emitEmptyLine()\n            beginControlFlow(\"if (value == null)\")\n                emitStatement(\"proxyState.getRow\\$realm().setNull(%s)\", fieldColKeyVariableReference(field))\n                emitStatement(\"return\")\n            endControlFlow()\n            emitStatement(\"value = ProxyUtils.copyToRealmIfNeeded(proxyState, value)\")\n            emitStatement(\"proxyState.getRow\\$realm().setRealmAny(%s, value.getNativePtr())\", fieldColKeyVariableReference(field))\n            endMethod()\n            // Setter - End\n        }\n    }\n\n    /**\n     * Emit Set/Get methods for RealmModel fields.\n     */\n    @Throws(IOException::class)\n    private fun emitRealmModel(writer: JavaWriter,\n            field: VariableElement,\n            fieldName: String,\n            fieldTypeCanonicalName: String) {\n        writer.apply {\n            // Getter - Start\n            emitAnnotation(\"Override\")\n            beginMethod(fieldTypeCanonicalName, metadata.getInternalGetter(fieldName), EnumSet.of(Modifier.PUBLIC))\n                emitStatement(\"proxyState.getRealm\\$realm().checkIfValid()\")\n                beginControlFlow(\"if (proxyState.getRow\\$realm().isNullLink(%s))\", fieldColKeyVariableReference(field))\n                    emitStatement(\"return null\")\n                endControlFlow()\n                emitStatement(\"return proxyState.getRealm\\$realm().get(%s.class, proxyState.getRow\\$realm().getLink(%s), false, Collections.<String>emptyList())\", fieldTypeCanonicalName, fieldColKeyVariableReference(field))\n            endMethod()\n            emitEmptyLine()\n            // Getter - End\n\n            // Setter - Start\n            val isEmbedded = Utils.isFieldTypeEmbedded(field.asType(), classCollection)\n            val linkedQualifiedClassName: QualifiedClassName = Utils.getFieldTypeQualifiedName(field)\n            val linkedProxyClass: SimpleClassName = Utils.getProxyClassSimpleName(field)\n            emitAnnotation(\"Override\")\n            beginMethod(\"void\", metadata.getInternalSetter(fieldName), EnumSet.of(Modifier.PUBLIC), fieldTypeCanonicalName, \"value\")\n                emitStatement(\"Realm realm = (Realm) proxyState.getRealm\\$realm()\")\n                emitCodeForUnderConstruction(writer, metadata.isPrimaryKey(field)) {\n                    // check excludeFields\n                    beginControlFlow(\"if (proxyState.getExcludeFields\\$realm().contains(\\\"%1\\$s\\\"))\", field.simpleName.toString())\n                        emitStatement(\"return\")\n                    endControlFlow()\n                    beginControlFlow(\"if (value != null && !RealmObject.isManaged(value))\")\n                        if (isEmbedded) {\n                            emitStatement(\"%1\\$s proxyObject = realm.createEmbeddedObject(%1\\$s.class, this, \\\"%2\\$s\\\")\", linkedQualifiedClassName, fieldName)\n                            emitStatement(\"%s.updateEmbeddedObject(realm, value, proxyObject, new HashMap<RealmModel, RealmObjectProxy>(), Collections.EMPTY_SET)\", linkedProxyClass)\n                            emitStatement(\"value = proxyObject\")\n                        } else {\n                            if (fieldTypeHasPrimaryKey(field.asType(), classCollection)) {\n                                emitStatement(\"value = realm.copyToRealmOrUpdate(value)\")\n                            } else {\n                                emitStatement(\"value = realm.copyToRealm(value)\")\n                            }\n                        }\n                    endControlFlow()\n\n                    // set value as default value\n                    emitStatement(\"final Row row = proxyState.getRow\\$realm()\")\n                    beginControlFlow(\"if (value == null)\")\n                        emitSingleLineComment(\"Table#nullifyLink() does not support default value. Just using Row.\")\n                        emitStatement(\"row.nullifyLink(%s)\", fieldColKeyVariableReference(field))\n                        emitStatement(\"return\")\n                    endControlFlow()\n                    emitStatement(\"proxyState.checkValidObject(value)\")\n                    emitStatement(\"row.getTable().setLink(%s, row.getObjectKey(), ((RealmObjectProxy) value).realmGet\\$proxyState().getRow\\$realm().getObjectKey(), true)\", fieldColKeyVariableReference(field))\n                    emitStatement(\"return\")\n                }\n                emitStatement(\"proxyState.getRealm\\$realm().checkIfValid()\")\n                beginControlFlow(\"if (value == null)\")\n                    emitStatement(\"proxyState.getRow\\$realm().nullifyLink(%s)\", fieldColKeyVariableReference(field))\n                    emitStatement(\"return\")\n                endControlFlow()\n\n                if (isEmbedded) {\n                    beginControlFlow(\"if (RealmObject.isManaged(value))\")\n                        emitStatement(\"proxyState.checkValidObject(value)\")\n                    endControlFlow()\n                    emitStatement(\"%1\\$s proxyObject = realm.createEmbeddedObject(%1\\$s.class, this, \\\"%2\\$s\\\")\", linkedQualifiedClassName, fieldName)\n                    emitStatement(\"%s.updateEmbeddedObject(realm, value, proxyObject, new HashMap<RealmModel, RealmObjectProxy>(), Collections.EMPTY_SET)\", linkedProxyClass)\n                } else {\n                    emitStatement(\"proxyState.checkValidObject(value)\")\n                    emitStatement(\"proxyState.getRow\\$realm().setLink(%s, ((RealmObjectProxy) value).realmGet\\$proxyState().getRow\\$realm().getObjectKey())\", fieldColKeyVariableReference(field))\n                }\n            endMethod()\n            // Setter - End\n        }\n    }\n\n    @Throws(IOException::class)\n    private fun emitRealmDictionary(\n            writer: JavaWriter,\n            field: VariableElement,\n            fieldName: String,\n            fieldTypeCanonicalName: String,\n            valueTypeMirror: TypeMirror\n    ) {\n        val forRealmAny = Utils.isRealmAny(valueTypeMirror)\n        val forRealmModel = Utils.isRealmModel(valueTypeMirror)\n\n        with(writer) {\n            val genericType: QualifiedClassName? = Utils.getGenericTypeQualifiedName(field)\n\n            // Getter\n            emitAnnotation(\"Override\")\n            beginMethod(fieldTypeCanonicalName, metadata.getInternalGetter(fieldName), EnumSet.of(Modifier.PUBLIC))\n                emitStatement(\"proxyState.getRealm\\$realm().checkIfValid()\")\n                emitSingleLineComment(\"use the cached value if available\")\n                beginControlFlow(\"if (${fieldName}RealmDictionary != null)\")\n                    emitStatement(\"return ${fieldName}RealmDictionary\")\n                nextControlFlow(\"else\")\n\n                    if (forRealmAny) {\n                        emitStatement(\"OsMap osMap = proxyState.getRow\\$realm().getRealmAnyMap(%s)\", fieldColKeyVariableReference(field))\n                    } else if (forRealmModel) {\n                        emitStatement(\"OsMap osMap = proxyState.getRow\\$realm().getModelMap(%s)\", fieldColKeyVariableReference(field))\n                    } else {\n                        emitStatement(\"OsMap osMap = proxyState.getRow\\$realm().getValueMap(%s, RealmFieldType.%s)\", fieldColKeyVariableReference(field), Utils.getValueDictionaryFieldType(field).name)\n                    }\n\n                    emitStatement(\"${fieldName}RealmDictionary = new RealmDictionary<%s>(proxyState.getRealm\\$realm(), osMap, %s.class)\", genericType, genericType)\n                    emitStatement(\"return ${fieldName}RealmDictionary\")\n                endControlFlow()\n            endMethod()\n            emitEmptyLine()\n\n            // Setter\n            emitAnnotation(\"Override\")\n            beginMethod(\"void\", metadata.getInternalSetter(fieldName), EnumSet.of(Modifier.PUBLIC), fieldTypeCanonicalName, \"value\")\n                emitCodeForUnderConstruction(writer, metadata.isPrimaryKey(field)) emitter@{\n                    // check excludeFields\n                    beginControlFlow(\"if (proxyState.getExcludeFields\\$realm().contains(\\\"%s\\\"))\", field.simpleName.toString())\n                        emitStatement(\"return\")\n                    endControlFlow()\n\n                    // Either realmAny, which may or may not contain RealmObjects inside...\n                    if (forRealmAny) {\n                        emitSingleLineComment(\"if the dictionary contains unmanaged RealmModel instances boxed in RealmAny objects, convert them to managed.\")\n                        beginControlFlow(\"if (value != null && !value.isManaged())\")\n                            emitStatement(\"final Realm realm = (Realm) proxyState.getRealm\\$realm()\")\n                            emitStatement(\"final RealmDictionary<%s> original = value\", genericType)\n                            emitStatement(\"value = new RealmDictionary<%s>()\", genericType)\n                            beginControlFlow(\"for (java.util.Map.Entry<String, %s> item : original.entrySet())\", genericType)\n                                emitStatement(\"String entryKey = item.getKey()\")\n                                emitStatement(\"%s entryValue = item.getValue()\", genericType)\n                                emitSingleLineComment(\"ensure (potential) RealmModel instances are copied to Realm if generic type is RealmAny\")\n                                beginControlFlow(\"if (entryValue == null)\")\n                                    emitStatement(\"value.put(entryKey, null)\")\n                                nextControlFlow(\"else if (entryValue.getType() == RealmAny.Type.OBJECT)\")\n                                    emitStatement(\"RealmModel realmModel = entryValue.asRealmModel(RealmModel.class)\")\n                                    emitStatement(\"RealmModel modelFromRealm = realm.copyToRealmOrUpdate(realmModel)\")\n                                    emitStatement(\"value.put(entryKey, RealmAny.valueOf(modelFromRealm))\")\n                                nextControlFlow(\"else\")\n                                    emitStatement(\"value.put(entryKey, entryValue)\")\n                                endControlFlow()\n                            endControlFlow()\n                        endControlFlow()\n                    } else if (forRealmModel) {\n                        // ... Or Realm Models\n                        emitSingleLineComment(\"if the dictionary contains unmanaged RealmModel instances, convert them to managed.\")\n                        beginControlFlow(\"if (value != null && !value.isManaged())\")\n                            emitStatement(\"final Realm realm = (Realm) proxyState.getRealm\\$realm()\")\n                            emitStatement(\"final RealmDictionary<%s> original = value\", genericType)\n                            emitStatement(\"value = new RealmDictionary<%s>()\", genericType)\n                            beginControlFlow(\"for (java.util.Map.Entry<String, %s> entry : original.entrySet())\", genericType)\n                                emitStatement(\"String entryKey = entry.getKey()\")\n                                emitStatement(\"%s entryValue = entry.getValue()\", genericType)\n                                beginControlFlow(\"if (entryValue == null || RealmObject.isManaged(entryValue))\")\n                                    emitStatement(\"value.put(entryKey, entryValue)\")\n                                nextControlFlow(\"else\")\n                                    emitStatement(\"value.put(entryKey, realm.copyToRealmOrUpdate(entryValue))\")\n                                endControlFlow()\n                            endControlFlow()\n                        endControlFlow()\n                    }\n                }\n\n                emitStatement(\"proxyState.getRealm\\$realm().checkIfValid()\")\n\n                if (forRealmAny) {\n                    emitStatement(\"OsMap osMap = proxyState.getRow\\$realm().getRealmAnyMap(%s)\", fieldColKeyVariableReference(field))\n                } else if (forRealmModel) {\n                    emitStatement(\"OsMap osMap = proxyState.getRow\\$realm().getModelMap(%s)\", fieldColKeyVariableReference(field))\n                } else {\n                    emitStatement(\"OsMap osMap = proxyState.getRow\\$realm().getValueMap(%s, RealmFieldType.%s)\", fieldColKeyVariableReference(field), Utils.getValueDictionaryFieldType(field).name)\n                }\n\n                beginControlFlow(\"if (value == null)\")\n                    emitStatement(\"return\")\n                endControlFlow()\n                emitStatement(\"osMap.clear()\")\n                beginControlFlow(\"for (java.util.Map.Entry<String, %s> item : value.entrySet())\", genericType)\n                    emitStatement(\"String entryKey = item.getKey()\")\n                    emitStatement(\"%s entryValue = item.getValue()\", genericType)\n\n                    if (forRealmAny) {\n                        beginControlFlow(\"if (entryValue == null)\")\n                            emitStatement(\"osMap.put(entryKey, null)\")\n                        nextControlFlow(\"else\")\n                            emitStatement(\"osMap.putRealmAny(entryKey, ProxyUtils.copyToRealmIfNeeded(proxyState, entryValue).getNativePtr())\")\n                        endControlFlow()\n                    } else if (forRealmModel) {\n                        beginControlFlow(\"if (entryValue == null)\")\n                            emitStatement(\"osMap.put(entryKey, null)\")\n                        nextControlFlow(\"else\")\n                            emitStatement(\"proxyState.checkValidObject(entryValue)\")\n                            emitStatement(\"osMap.putRow(entryKey, ((RealmObjectProxy) entryValue).realmGet\\$proxyState().getRow\\$realm().getObjectKey())\")\n                        endControlFlow()\n                    } else {\n                        emitStatement(\"osMap.put(entryKey, entryValue)\")\n                    }\n\n                endControlFlow()\n\n            endMethod()\n        }\n    }\n\n    @Throws(IOException::class)\n    private fun emitRealmSet(\n            writer: JavaWriter,\n            field: VariableElement,\n            fieldName: String,\n            fieldTypeCanonicalName: String,\n            valueTypeMirror: TypeMirror\n    ) {\n        val forRealmAny = Utils.isRealmAny(valueTypeMirror)\n        val forRealmModel = Utils.isRealmModel(valueTypeMirror)\n\n        with(writer) {\n            val genericType: QualifiedClassName? = Utils.getGenericTypeQualifiedName(field)\n\n            // Getter\n            emitAnnotation(\"Override\")\n            beginMethod(fieldTypeCanonicalName, metadata.getInternalGetter(fieldName), EnumSet.of(Modifier.PUBLIC))\n                emitStatement(\"proxyState.getRealm\\$realm().checkIfValid()\")\n                emitSingleLineComment(\"use the cached value if available\")\n                beginControlFlow(\"if (${fieldName}RealmSet != null)\")\n                    emitStatement(\"return ${fieldName}RealmSet\")\n                nextControlFlow(\"else\")\n\n                    if (forRealmAny) {\n                        emitStatement(\"OsSet osSet = proxyState.getRow\\$realm().getRealmAnySet(%s)\", fieldColKeyVariableReference(field))\n                    } else if (forRealmModel) {\n                        emitStatement(\"OsSet osSet = proxyState.getRow\\$realm().getModelSet(%s)\", fieldColKeyVariableReference(field))\n                    } else {\n                        emitStatement(\"OsSet osSet = proxyState.getRow\\$realm().getValueSet(%s, RealmFieldType.%s)\", fieldColKeyVariableReference(field), Utils.getValueSetFieldType(field).name)\n                    }\n\n                    emitStatement(\"${fieldName}RealmSet = new RealmSet<%s>(proxyState.getRealm\\$realm(), osSet, %s.class)\", genericType, genericType)\n                    emitStatement(\"return ${fieldName}RealmSet\")\n                endControlFlow()\n            endMethod()\n            emitEmptyLine()\n\n            // Setter\n            emitAnnotation(\"Override\")\n            beginMethod(\"void\", metadata.getInternalSetter(fieldName), EnumSet.of(Modifier.PUBLIC), fieldTypeCanonicalName, \"value\")\n\n            emitCodeForUnderConstruction(writer, metadata.isPrimaryKey(field)) emitter@{\n                // check excludeFields\n                beginControlFlow(\"if (proxyState.getExcludeFields\\$realm().contains(\\\"%s\\\"))\", field.simpleName.toString())\n                    emitStatement(\"return\")\n                endControlFlow()\n\n                // Either realmAny, which may or may not contain RealmObjects inside...\n                if (forRealmAny) {\n                    emitSingleLineComment(\"if the set contains unmanaged RealmModel instances boxed in RealmAny objects, convert them to managed.\")\n                    beginControlFlow(\"if (value != null && !value.isManaged())\")\n                        emitStatement(\"final Realm realm = (Realm) proxyState.getRealm\\$realm()\")\n                        emitStatement(\"final RealmSet<%s> original = value\", genericType)\n                        emitStatement(\"value = new RealmSet<%s>()\", genericType)\n                        beginControlFlow(\"for (%s item : original)\", genericType)\n                            emitStatement(\"value.add(ProxyUtils.copyToRealmIfNeeded(proxyState, item))\")\n                        endControlFlow()\n                    endControlFlow()\n                } else if (forRealmModel) {\n                    // ... Or Realm Models\n                    emitSingleLineComment(\"if the set contains unmanaged RealmModel instances, convert them to managed.\")\n                    beginControlFlow(\"if (value != null && !value.isManaged())\")\n                        emitStatement(\"final Realm realm = (Realm) proxyState.getRealm\\$realm()\")\n                        emitStatement(\"final RealmSet<%s> original = value\", genericType)\n                        emitStatement(\"value = new RealmSet<%s>()\", genericType)\n                        beginControlFlow(\"for (%s item : original)\", genericType)\n                            beginControlFlow(\"if (item == null || RealmObject.isManaged(item))\")\n                                emitStatement(\"value.add(item)\")\n                            nextControlFlow(\"else\")\n                                emitStatement(\"value.add(realm.copyToRealmOrUpdate(item))\")\n                            endControlFlow()\n                        endControlFlow()\n                    endControlFlow()\n                }\n            }\n\n            emitStatement(\"proxyState.getRealm\\$realm().checkIfValid()\")\n\n            when {\n                forRealmAny -> {\n                    emitStatement(\"OsSet osSet = proxyState.getRow\\$realm().getRealmAnySet(${fieldColKeyVariableReference(field)})\")\n                }\n                forRealmModel -> {\n                    emitStatement(\"OsSet osSet = proxyState.getRow\\$realm().getModelSet(%s)\", fieldColKeyVariableReference(field))\n                }\n                else -> {\n                    emitStatement(\"OsSet osSet = proxyState.getRow\\$realm().getValueSet(%s, RealmFieldType.%s)\", fieldColKeyVariableReference(field), Utils.getValueSetFieldType(field).name)\n                }\n            }\n\n            beginControlFlow(\"if (value == null)\")\n                emitStatement(\"return\")\n            endControlFlow()\n            emitSingleLineComment(\"We need to create a copy of the set before clearing as the input and target sets might be the same.\")\n            emitStatement(\"List<$genericType> unmanagedList = new ArrayList<>(value)\")\n            emitStatement(\"osSet.clear()\")\n            beginControlFlow(\"for (%s item : unmanagedList)\", genericType)\n\n            when {\n                forRealmAny -> {\n                    emitStatement(\"osSet.addRealmAny(ProxyUtils.copyToRealmIfNeeded(proxyState, item).getNativePtr())\")\n                }\n                forRealmModel -> {\n                    emitStatement(\"proxyState.checkValidObject(item)\")\n                    emitStatement(\"Row row\\$realm = ((RealmObjectProxy) item).realmGet\\$proxyState().getRow\\$realm()\")\n                    emitStatement(\"osSet.addRow(row\\$realm.getObjectKey())\")\n                }\n                else -> {\n                    emitStatement(\"osSet.add(item)\")\n                }\n            }\n\n            endControlFlow()\n\n            endMethod()\n        }\n    }\n\n    /**\n     * Emit Set/Get methods for Realm Model Lists and Lists of primitives.\n     */\n    @Throws(IOException::class)\n    private fun emitRealmList(\n            writer: JavaWriter,\n            field: VariableElement,\n            fieldName: String,\n            fieldTypeCanonicalName: String,\n            elementTypeMirror: TypeMirror?) {\n\n        val genericType: QualifiedClassName? = Utils.getGenericTypeQualifiedName(field)\n        val forRealmModel: Boolean = Utils.isRealmModel(elementTypeMirror)\n        val forRealmAny: Boolean = Utils.isRealmAny(elementTypeMirror)\n\n        writer.apply {\n            // Getter - Start\n            emitAnnotation(\"Override\")\n            beginMethod(fieldTypeCanonicalName, metadata.getInternalGetter(fieldName), EnumSet.of(Modifier.PUBLIC))\n                emitStatement(\"proxyState.getRealm\\$realm().checkIfValid()\")\n                emitSingleLineComment(\"use the cached value if available\")\n                beginControlFlow(\"if (${fieldName}RealmList != null)\")\n                    emitStatement(\"return ${fieldName}RealmList\")\n                nextControlFlow(\"else\")\n                    if (Utils.isRealmModelList(field)) {\n                        emitStatement(\"OsList osList = proxyState.getRow\\$realm().getModelList(%s)\", fieldColKeyVariableReference(field))\n                    } else {\n                        emitStatement(\"OsList osList = proxyState.getRow\\$realm().getValueList(%1\\$s, RealmFieldType.%2\\$s)\", fieldColKeyVariableReference(field), Utils.getValueListFieldType(field).name)\n                    }\n                    emitStatement(\"${fieldName}RealmList = new RealmList<%s>(%s.class, osList, proxyState.getRealm\\$realm())\", genericType, genericType)\n                    emitStatement(\"return ${fieldName}RealmList\")\n                endControlFlow()\n            endMethod()\n            emitEmptyLine()\n            // Getter - End\n\n            // Setter - Start\n            emitAnnotation(\"Override\")\n            beginMethod(\"void\", metadata.getInternalSetter(fieldName), EnumSet.of(Modifier.PUBLIC), fieldTypeCanonicalName, \"value\")\n            emitCodeForUnderConstruction(writer, metadata.isPrimaryKey(field)) emitter@{\n                // check excludeFields\n                beginControlFlow(\"if (proxyState.getExcludeFields\\$realm().contains(\\\"%1\\$s\\\"))\", field.simpleName.toString())\n                emitStatement(\"return\")\n                endControlFlow()\n\n                if (!forRealmModel) {\n                    return@emitter\n                }\n\n                emitSingleLineComment(\"if the list contains unmanaged RealmObjects, convert them to managed.\")\n                beginControlFlow(\"if (value != null && !value.isManaged())\")\n                    emitStatement(\"final Realm realm = (Realm) proxyState.getRealm\\$realm()\")\n                    emitStatement(\"final RealmList<%1\\$s> original = value\", genericType)\n                    emitStatement(\"value = new RealmList<%1\\$s>()\", genericType)\n                    beginControlFlow(\"for (%1\\$s item : original)\", genericType)\n                        beginControlFlow(\"if (item == null || RealmObject.isManaged(item))\")\n                            emitStatement(\"value.add(item)\")\n                        nextControlFlow(\"else\")\n                            val type = getGenericType(field) ?:\n                                throw IllegalArgumentException(\"Unable to derive generic type of ${fieldName}\")\n                            if (fieldTypeHasPrimaryKey(type, classCollection)) {\n                                emitStatement(\"value.add(realm.copyToRealmOrUpdate(item))\")\n                            } else {\n                                emitStatement(\"value.add(realm.copyToRealm(item))\");\n                            }\n                        endControlFlow()\n                    endControlFlow()\n                endControlFlow()\n\n                // LinkView currently does not support default value feature. Just fallback to normal code.\n            }\n\n            emitStatement(\"proxyState.getRealm\\$realm().checkIfValid()\")\n            if (Utils.isRealmModelList(field)) {\n                emitStatement(\"OsList osList = proxyState.getRow\\$realm().getModelList(%s)\", fieldColKeyVariableReference(field))\n            } else {\n                emitStatement(\"OsList osList = proxyState.getRow\\$realm().getValueList(%1\\$s, RealmFieldType.%2\\$s)\", fieldColKeyVariableReference(field), Utils.getValueListFieldType(field).name)\n            }\n            if (forRealmModel) {\n                // Model lists.\n                emitSingleLineComment(\"For lists of equal lengths, we need to set each element directly as clearing the receiver list can be wrong if the input and target list are the same.\")\n                    beginControlFlow(\"if (value != null && value.size() == osList.size())\")\n                        emitStatement(\"int objects = value.size()\")\n                        beginControlFlow(\"for (int i = 0; i < objects; i++)\")\n                            emitStatement(\"%s linkedObject = value.get(i)\", genericType)\n                            emitStatement(\"proxyState.checkValidObject(linkedObject)\")\n                            emitStatement(\"osList.setRow(i, ((RealmObjectProxy) linkedObject).realmGet\\$proxyState().getRow\\$realm().getObjectKey())\")\n                        endControlFlow()\n                    nextControlFlow(\"else\")\n                        emitStatement(\"osList.removeAll()\")\n                        beginControlFlow(\"if (value == null)\")\n                            emitStatement(\"return\")\n                        endControlFlow()\n                        emitStatement(\"int objects = value.size()\")\n                        beginControlFlow(\"for (int i = 0; i < objects; i++)\")\n                            emitStatement(\"%s linkedObject = value.get(i)\", genericType)\n                            emitStatement(\"proxyState.checkValidObject(linkedObject)\")\n                            emitStatement(\"osList.addRow(((RealmObjectProxy) linkedObject).realmGet\\$proxyState().getRow\\$realm().getObjectKey())\")\n                        endControlFlow()\n                    endControlFlow()\n            } else {\n                if(forRealmAny){\n                    beginControlFlow(\"if (value != null && !value.isManaged())\")\n                        emitStatement(\"final Realm realm = (Realm) proxyState.getRealm\\$realm()\")\n                        emitStatement(\"final RealmList<RealmAny> original = value\")\n                        emitStatement(\"value = new RealmList<RealmAny>()\")\n                        beginControlFlow(\"for (int i = 0; i < original.size(); i++)\")\n                            emitStatement(\"value.add(ProxyUtils.copyToRealmIfNeeded(proxyState, original.get(i)))\")\n                        endControlFlow()\n                    endControlFlow()\n                }\n\n                // Value lists\n                emitStatement(\"osList.removeAll()\")\n                beginControlFlow(\"if (value == null)\")\n                    emitStatement(\"return\")\n                    endControlFlow()\n                    beginControlFlow(\"for (%1\\$s item : value)\", genericType)\n                        beginControlFlow(\"if (item == null)\")\n                            emitStatement(if (metadata.isElementNullable(field)) \"osList.addNull()\" else \"throw new IllegalArgumentException(\\\"Storing 'null' into $fieldName' is not allowed by the schema.\\\")\")\n                        nextControlFlow(\"else\")\n                            emitStatement(getStatementForAppendingValueToOsList(\"osList\", \"item\", elementTypeMirror))\n                        endControlFlow()\n                    endControlFlow()\n            }\n            endMethod()\n            // Setter - End\n        }\n    }\n\n    private fun getStatementForAppendingValueToOsList(\n            osListVariableName: String,\n            valueVariableName: String,\n            elementTypeMirror: TypeMirror?): String {\n\n        val typeUtils = processingEnvironment.typeUtils\n        if (typeUtils.isSameType(elementTypeMirror, typeMirrors.STRING_MIRROR)) {\n            return \"$osListVariableName.addString($valueVariableName)\"\n        }\n        if ((typeUtils.isSameType(elementTypeMirror, typeMirrors.LONG_MIRROR)\n                        || typeUtils.isSameType(elementTypeMirror, typeMirrors.INTEGER_MIRROR)\n                        || typeUtils.isSameType(elementTypeMirror, typeMirrors.SHORT_MIRROR)\n                        || typeUtils.isSameType(elementTypeMirror, typeMirrors.BYTE_MIRROR))) {\n            return \"$osListVariableName.addLong($valueVariableName.longValue())\"\n        }\n        if (typeUtils.isSameType(elementTypeMirror, typeMirrors.BINARY_MIRROR)) {\n            return \"$osListVariableName.addBinary($valueVariableName)\"\n        }\n        if (typeUtils.isSameType(elementTypeMirror, typeMirrors.DATE_MIRROR)) {\n            return \"$osListVariableName.addDate($valueVariableName)\"\n        }\n        if (typeUtils.isSameType(elementTypeMirror, typeMirrors.BOOLEAN_MIRROR)) {\n            return \"$osListVariableName.addBoolean($valueVariableName)\"\n        }\n        if (typeUtils.isSameType(elementTypeMirror, typeMirrors.DOUBLE_MIRROR)) {\n            return \"$osListVariableName.addDouble($valueVariableName.doubleValue())\"\n        }\n        if (typeUtils.isSameType(elementTypeMirror, typeMirrors.FLOAT_MIRROR)) {\n            return \"$osListVariableName.addFloat($valueVariableName.floatValue())\"\n        }\n        if (typeUtils.isSameType(elementTypeMirror, typeMirrors.DECIMAL128_MIRROR)) {\n            return \"$osListVariableName.addDecimal128($valueVariableName)\"\n        }\n        if (typeUtils.isSameType(elementTypeMirror, typeMirrors.OBJECT_ID_MIRROR)) {\n            return \"$osListVariableName.addObjectId($valueVariableName)\"\n        }\n        if (typeUtils.isSameType(elementTypeMirror, typeMirrors.UUID_MIRROR)) {\n            return \"$osListVariableName.addUUID($valueVariableName)\"\n        }\n        if (typeUtils.isSameType(elementTypeMirror, typeMirrors.MIXED_MIRROR)) {\n            return \"$osListVariableName.addRealmAny($valueVariableName.getNativePtr())\"\n        }\n        throw RuntimeException(\"unexpected element type: $elementTypeMirror\")\n    }\n\n    @Throws(IOException::class)\n    private fun emitCodeForUnderConstruction(writer: JavaWriter, isPrimaryKey: Boolean, emitCode: () -> Unit) {\n        writer.apply {\n            beginControlFlow(\"if (proxyState.isUnderConstruction())\")\n                if (isPrimaryKey) {\n                    emitSingleLineComment(\"default value of the primary key is always ignored.\")\n                    emitStatement(\"return\")\n                } else {\n                    beginControlFlow(\"if (!proxyState.getAcceptDefaultValue\\$realm())\")\n                        emitStatement(\"return\")\n                    endControlFlow()\n                    emitCode()\n                }\n            endControlFlow()\n            emitEmptyLine()\n        }\n    }\n\n    // Note that because of bytecode hackery, this method may run before the constructor!\n    // It may even run before fields have been initialized.\n    @Throws(IOException::class)\n    private fun emitInjectContextMethod(writer: JavaWriter) {\n        writer.apply {\n            emitAnnotation(\"Override\")\n            beginMethod(\"void\",\"realm\\$injectObjectContext\", EnumSet.of(Modifier.PUBLIC))\n                beginControlFlow(\"if (this.proxyState != null)\")\n                    emitStatement(\"return\")\n                endControlFlow()\n                emitStatement(\"final BaseRealm.RealmObjectContext context = BaseRealm.objectContext.get()\")\n                emitStatement(\"this.columnInfo = (%1\\$s) context.getColumnInfo()\", columnInfoClassName())\n                emitStatement(\"this.proxyState = new ProxyState<%1\\$s>(this)\", qualifiedJavaClassName)\n                emitStatement(\"proxyState.setRealm\\$realm(context.getRealm())\")\n                emitStatement(\"proxyState.setRow\\$realm(context.getRow())\")\n                emitStatement(\"proxyState.setAcceptDefaultValue\\$realm(context.getAcceptDefaultValue())\")\n                emitStatement(\"proxyState.setExcludeFields\\$realm(context.getExcludeFields())\")\n            endMethod()\n            emitEmptyLine()\n        }\n    }\n\n    @Throws(IOException::class)\n    private fun emitBacklinkFieldAccessors(writer: JavaWriter) {\n        for (backlink in metadata.backlinkFields) {\n            val cacheFieldName = backlink.targetField + BACKLINKS_FIELD_EXTENSION\n            val realmResultsType = \"RealmResults<\" + backlink.sourceClass + \">\"\n            when (backlink.exposeAsRealmResults) {\n                true -> {\n                    // Getter, no setter\n                    writer.apply {\n                        emitAnnotation(\"Override\")\n                        beginMethod(realmResultsType, metadata.getInternalGetter(backlink.targetField), EnumSet.of(Modifier.PUBLIC))\n                        emitStatement(\"BaseRealm realm = proxyState.getRealm\\$realm()\")\n                        emitStatement(\"realm.checkIfValid()\")\n                        emitStatement(\"proxyState.getRow\\$realm().checkIfAttached()\")\n                        beginControlFlow(\"if ($cacheFieldName == null)\")\n                            emitStatement(\"$cacheFieldName = RealmResults.createBacklinkResults(realm, proxyState.getRow\\$realm(), %s.class, \\\"%s\\\")\", backlink.sourceClass, backlink.sourceField)\n                        endControlFlow()\n                        emitStatement(\"return $cacheFieldName\")\n                        endMethod()\n                        emitEmptyLine()\n                    }\n                }\n                false -> {\n                    // Getter, no setter\n                    writer.apply {\n                        emitAnnotation(\"Override\")\n                        beginMethod(backlink.sourceClass.toString(), metadata.getInternalGetter(backlink.targetField), EnumSet.of(Modifier.PUBLIC))\n                        emitStatement(\"BaseRealm realm = proxyState.getRealm\\$realm()\")\n                        emitStatement(\"realm.checkIfValid()\")\n                        emitStatement(\"proxyState.getRow\\$realm().checkIfAttached()\")\n                        beginControlFlow(\"if ($cacheFieldName == null)\")\n                            emitStatement(\"$cacheFieldName = RealmResults.createBacklinkResults(realm, proxyState.getRow\\$realm(), %s.class, \\\"%s\\\").first()\", backlink.sourceClass, backlink.sourceField)\n                        endControlFlow()\n                        emitStatement(\"return $cacheFieldName\") // TODO: Figure out the exact API for this\n                        endMethod()\n                        emitEmptyLine()\n                    }\n                }\n            }\n        }\n    }\n\n    @Throws(IOException::class)\n    private fun emitRealmObjectProxyImplementation(writer: JavaWriter) {\n        writer.apply {\n            emitAnnotation(\"Override\")\n            beginMethod(\"ProxyState<?>\", \"realmGet\\$proxyState\", EnumSet.of(Modifier.PUBLIC))\n                emitStatement(\"return proxyState\")\n            endMethod()\n            emitEmptyLine()\n        }\n    }\n\n    @Throws(IOException::class)\n    private fun emitCreateExpectedObjectSchemaInfo(writer: JavaWriter) {\n        writer.apply {\n            beginMethod(\"OsObjectSchemaInfo\", \"createExpectedObjectSchemaInfo\", EnumSet.of(Modifier.PRIVATE, Modifier.STATIC))\n                // Guess capacity for Arrays used by OsObjectSchemaInfo.\n                // Used to prevent array resizing at runtime\n                val persistedFields = metadata.fields.size\n                val computedFields = metadata.backlinkFields.size\n                val embeddedClass = if (metadata.embedded) \"true\" else \"false\"\n                val publicClassName = if (simpleJavaClassName.name != internalClassName) \"\\\"${simpleJavaClassName.name}\\\"\" else \"NO_ALIAS\"\n                emitStatement(\"OsObjectSchemaInfo.Builder builder = new OsObjectSchemaInfo.Builder($publicClassName, \\\"$internalClassName\\\", $embeddedClass, $persistedFields, $computedFields)\")\n\n                // For each field generate corresponding table index constant\n                for (field in metadata.fields) {\n                    val internalFieldName = field.internalFieldName\n                    val publicFieldName = if (field.javaName == internalFieldName) \"NO_ALIAS\" else \"\\\"${field.javaName}\\\"\"\n\n                    when (val fieldType = getRealmTypeChecked(field)) {\n                        Constants.RealmFieldType.NOTYPE -> {\n                            // Perhaps this should fail quickly?\n                        }\n                        Constants.RealmFieldType.OBJECT -> {\n                            val fieldTypeQualifiedName = Utils.getFieldTypeQualifiedName(field)\n                            val internalClassName = Utils.getReferencedTypeInternalClassNameStatement(fieldTypeQualifiedName, classCollection)\n                            emitStatement(\"builder.addPersistedLinkProperty(%s, \\\"%s\\\", RealmFieldType.OBJECT, %s)\", publicFieldName, internalFieldName, internalClassName)\n                        }\n                        Constants.RealmFieldType.LIST -> {\n                            val genericTypeQualifiedName = Utils.getGenericTypeQualifiedName(field)\n                            val internalClassName = Utils.getReferencedTypeInternalClassNameStatement(genericTypeQualifiedName, classCollection)\n                            emitStatement(\"builder.addPersistedLinkProperty(%s, \\\"%s\\\", RealmFieldType.LIST, %s)\", publicFieldName, internalFieldName, internalClassName)\n                        }\n                        Constants.RealmFieldType.INTEGER_LIST,\n                        Constants.RealmFieldType.BOOLEAN_LIST,\n                        Constants.RealmFieldType.STRING_LIST,\n                        Constants.RealmFieldType.BINARY_LIST,\n                        Constants.RealmFieldType.DATE_LIST,\n                        Constants.RealmFieldType.FLOAT_LIST,\n                        Constants.RealmFieldType.DECIMAL128_LIST,\n                        Constants.RealmFieldType.OBJECT_ID_LIST,\n                        Constants.RealmFieldType.UUID_LIST,\n                        Constants.RealmFieldType.MIXED_LIST,\n                        Constants.RealmFieldType.DOUBLE_LIST -> {\n                            val requiredFlag = if (metadata.isElementNullable(field)) \"!Property.REQUIRED\" else \"Property.REQUIRED\"\n                            emitStatement(\"builder.addPersistedValueListProperty(%s, \\\"%s\\\", %s, %s)\", publicFieldName, internalFieldName, fieldType.realmType, requiredFlag)\n                        }\n                        Constants.RealmFieldType.BACKLINK -> {\n                            throw IllegalArgumentException(\"LinkingObject field should not be added to metadata\")\n                        }\n                        Constants.RealmFieldType.INTEGER,\n                        Constants.RealmFieldType.FLOAT,\n                        Constants.RealmFieldType.DOUBLE,\n                        Constants.RealmFieldType.BOOLEAN,\n                        Constants.RealmFieldType.STRING,\n                        Constants.RealmFieldType.DATE,\n                        Constants.RealmFieldType.BINARY,\n                        Constants.RealmFieldType.DECIMAL128,\n                        Constants.RealmFieldType.OBJECT_ID,\n                        Constants.RealmFieldType.UUID,\n                        Constants.RealmFieldType.MIXED,\n                        Constants.RealmFieldType.REALM_INTEGER -> {\n                            val nullableFlag = (if (metadata.isNullable(field)) \"!\" else \"\") + \"Property.REQUIRED\"\n                            val indexedFlag = (if (metadata.isIndexed(field)) \"\" else \"!\") + \"Property.INDEXED\"\n                            val primaryKeyFlag = (if (metadata.isPrimaryKey(field)) \"\" else \"!\") + \"Property.PRIMARY_KEY\"\n                            emitStatement(\"builder.addPersistedProperty(%s, \\\"%s\\\", %s, %s, %s, %s)\", publicFieldName, internalFieldName, fieldType.realmType, primaryKeyFlag, indexedFlag, nullableFlag)\n                        }\n                        Constants.RealmFieldType.STRING_TO_BOOLEAN_MAP,\n                        Constants.RealmFieldType.STRING_TO_STRING_MAP,\n                        Constants.RealmFieldType.STRING_TO_INTEGER_MAP,\n                        Constants.RealmFieldType.STRING_TO_FLOAT_MAP,\n                        Constants.RealmFieldType.STRING_TO_DOUBLE_MAP,\n                        Constants.RealmFieldType.STRING_TO_BINARY_MAP,\n                        Constants.RealmFieldType.STRING_TO_DATE_MAP,\n                        Constants.RealmFieldType.STRING_TO_DECIMAL128_MAP,\n                        Constants.RealmFieldType.STRING_TO_OBJECT_ID_MAP,\n                        Constants.RealmFieldType.STRING_TO_UUID_MAP,\n                        Constants.RealmFieldType.STRING_TO_MIXED_MAP -> {\n                            val valueNullable = metadata.isDictionaryValueNullable(field)\n                            val requiredFlag = if (valueNullable) \"!Property.REQUIRED\" else \"Property.REQUIRED\"\n                            emitStatement(\"builder.addPersistedMapProperty(%s, \\\"%s\\\", %s, %s)\", publicFieldName, internalFieldName, fieldType.realmType, requiredFlag)\n                        }\n                        Constants.RealmFieldType.STRING_TO_LINK_MAP -> {\n                            val genericTypeQualifiedName = Utils.getGenericTypeQualifiedName(field)\n                            val internalClassName = Utils.getReferencedTypeInternalClassNameStatement(genericTypeQualifiedName, classCollection)\n                            emitStatement(\"builder.addPersistedLinkProperty(%s, \\\"%s\\\", RealmFieldType.STRING_TO_LINK_MAP, %s)\", publicFieldName, internalFieldName, internalClassName)\n                        }\n                        Constants.RealmFieldType.BOOLEAN_SET,\n                        Constants.RealmFieldType.STRING_SET,\n                        Constants.RealmFieldType.INTEGER_SET,\n                        Constants.RealmFieldType.FLOAT_SET,\n                        Constants.RealmFieldType.DOUBLE_SET,\n                        Constants.RealmFieldType.BINARY_SET,\n                        Constants.RealmFieldType.DATE_SET,\n                        Constants.RealmFieldType.DECIMAL128_SET,\n                        Constants.RealmFieldType.OBJECT_ID_SET,\n                        Constants.RealmFieldType.UUID_SET,\n                        Constants.RealmFieldType.MIXED_SET -> {\n                            val valueNullable = metadata.isSetValueNullable(field)\n                            val requiredFlag = if (valueNullable) \"!Property.REQUIRED\" else \"Property.REQUIRED\"\n                            emitStatement(\"builder.addPersistedSetProperty(%s, \\\"%s\\\", %s, %s)\", publicFieldName, internalFieldName, fieldType.realmType, requiredFlag)\n                        }\n                        Constants.RealmFieldType.LINK_SET -> {\n                            val genericTypeQualifiedName = Utils.getGenericTypeQualifiedName(field)\n                            val internalClassName = Utils.getReferencedTypeInternalClassNameStatement(genericTypeQualifiedName, classCollection)\n                            emitStatement(\"builder.addPersistedLinkProperty(${publicFieldName}, \\\"${internalFieldName}\\\", RealmFieldType.LINK_SET, ${internalClassName})\")\n                        }\n                    }\n                }\n                for (backlink in metadata.backlinkFields) {\n                    // Backlinks can only be created between classes in the current round of annotation processing\n                    // as the forward link cannot be created unless you know the type already.\n                    val sourceClass = classCollection.getClassFromQualifiedName(backlink.sourceClass!!)\n                    val targetField = backlink.targetField // Only in the model, so no internal name exists\n                    val internalSourceField = sourceClass.getInternalFieldName(backlink.sourceField!!)\n                    emitStatement(\"\"\"builder.addComputedLinkProperty(\"%s\", \"%s\", \"%s\")\"\"\", targetField, sourceClass.internalClassName, internalSourceField)\n                }\n                emitStatement(\"return builder.build()\")\n            endMethod()\n            emitEmptyLine()\n        }\n    }\n\n    @Throws(IOException::class)\n    private fun emitGetExpectedObjectSchemaInfo(writer: JavaWriter) {\n        writer.apply {\n            beginMethod(\"OsObjectSchemaInfo\", \"getExpectedObjectSchemaInfo\", EnumSet.of(Modifier.PUBLIC, Modifier.STATIC))\n                emitStatement(\"return expectedObjectSchemaInfo\")\n            endMethod()\n            emitEmptyLine()\n        }\n    }\n\n    @Throws(IOException::class)\n    private fun emitCreateColumnInfoMethod(writer: JavaWriter) {\n        writer.apply {\n            beginMethod(columnInfoClassName(), \"createColumnInfo\", EnumSet.of(Modifier.PUBLIC, Modifier.STATIC), \"OsSchemaInfo\", \"schemaInfo\")\n                emitStatement(\"return new %1\\$s(schemaInfo)\", columnInfoClassName())\n            endMethod()\n            emitEmptyLine()\n        }\n    }\n\n    @Throws(IOException::class)\n    private fun emitGetSimpleClassNameMethod(writer: JavaWriter) {\n        writer.apply {\n            beginMethod(\"String\", \"getSimpleClassName\", EnumSet.of(Modifier.PUBLIC, Modifier.STATIC))\n                emitStatement(\"return \\\"%s\\\"\", internalClassName)\n            endMethod()\n            emitEmptyLine()\n\n            // Helper class for the annotation processor so it can access the internal class name\n            // without needing to load the parent class (which we cannot do as it transitively loads\n            // native code, which cannot be loaded on the JVM).\n            beginType(\"ClassNameHelper\", \"class\", EnumSet.of(Modifier.PUBLIC, Modifier.STATIC, Modifier.FINAL))\n                emitField(\"String\", \"INTERNAL_CLASS_NAME\", EnumSet.of(Modifier.PUBLIC, Modifier.STATIC, Modifier.FINAL), \"\\\"$internalClassName\\\"\")\n            endType()\n            emitEmptyLine()\n        }\n    }\n\n    @Throws(IOException::class)\n    private fun emitNewProxyInstance(writer: JavaWriter) {\n        writer.apply {\n            beginMethod(generatedClassName, \"newProxyInstance\", EnumSet.of(Modifier.STATIC), \"BaseRealm\", \"realm\", \"Row\", \"row\")\n                emitSingleLineComment(\"Ignore default values to avoid creating unexpected objects from RealmModel/RealmList fields\")\n                emitStatement(\"final BaseRealm.RealmObjectContext objectContext = BaseRealm.objectContext.get()\")\n                emitStatement(\"objectContext.set(realm, row, realm.getSchema().getColumnInfo(%s.class), false, Collections.<String>emptyList())\", qualifiedJavaClassName)\n                emitStatement(\"%1\\$s obj = new %1\\$s()\", generatedClassName)\n                emitStatement(\"objectContext.clear()\")\n                emitStatement(\"return obj\")\n            endMethod()\n            emitEmptyLine()\n        }\n    }\n\n    @Throws(IOException::class)\n    private fun emitCopyOrUpdateMethod(writer: JavaWriter) {\n        writer.apply {\n            beginMethod(qualifiedJavaClassName,\"copyOrUpdate\", EnumSet.of(Modifier.PUBLIC, Modifier.STATIC),\n                    \"Realm\", \"realm\",\n                    columnInfoClassName(), \"columnInfo\",\n                    qualifiedJavaClassName.toString(), \"object\",\n                    \"boolean\", \"update\",\n                    \"Map<RealmModel,RealmObjectProxy>\", \"cache\",\n                    \"Set<ImportFlag>\", \"flags\")\n\n                beginControlFlow(\"if (object instanceof RealmObjectProxy && !RealmObject.isFrozen(object) && ((RealmObjectProxy) object).realmGet\\$proxyState().getRealm\\$realm() != null)\")\n                    emitStatement(\"final BaseRealm otherRealm = ((RealmObjectProxy) object).realmGet\\$proxyState().getRealm\\$realm()\")\n                    beginControlFlow(\"if (otherRealm.threadId != realm.threadId)\")\n                        emitStatement(\"throw new IllegalArgumentException(\\\"Objects which belong to Realm instances in other threads cannot be copied into this Realm instance.\\\")\")\n                    endControlFlow()\n\n                    // If object is already in the Realm there is nothing to update\n                    beginControlFlow(\"if (otherRealm.getPath().equals(realm.getPath()))\")\n                        emitStatement(\"return object\")\n                    endControlFlow()\n                endControlFlow()\n                emitStatement(\"final BaseRealm.RealmObjectContext objectContext = BaseRealm.objectContext.get()\")\n                emitStatement(\"RealmObjectProxy cachedRealmObject = cache.get(object)\")\n                beginControlFlow(\"if (cachedRealmObject != null)\")\n                    emitStatement(\"return (%s) cachedRealmObject\", qualifiedJavaClassName)\n                endControlFlow()\n                emitEmptyLine()\n\n                if (!metadata.hasPrimaryKey()) {\n                    emitStatement(\"return copy(realm, columnInfo, object, update, cache, flags)\")\n                } else {\n                    emitStatement(\"%s realmObject = null\", qualifiedJavaClassName)\n                    emitStatement(\"boolean canUpdate = update\")\n                    beginControlFlow(\"if (canUpdate)\")\n                        emitStatement(\"Table table = realm.getTable(%s.class)\", qualifiedJavaClassName)\n                        emitStatement(\"long pkColumnKey = %s\", fieldColKeyVariableReference(metadata.primaryKey))\n\n                        val primaryKeyGetter = metadata.primaryKeyGetter\n                        val primaryKeyElement = metadata.primaryKey\n                        if (metadata.isNullable(primaryKeyElement!!)) {\n                            if (Utils.isString(primaryKeyElement)) {\n                                emitStatement(\"String value = ((%s) object).%s()\", interfaceName, primaryKeyGetter)\n                                emitStatement(\"long objKey = Table.NO_MATCH\")\n                                beginControlFlow(\"if (value == null)\")\n                                    emitStatement(\"objKey = table.findFirstNull(pkColumnKey)\")\n                                nextControlFlow(\"else\")\n                                    emitStatement(\"objKey = table.findFirstString(pkColumnKey, value)\")\n                                endControlFlow()\n                            } else if (Utils.isObjectId(primaryKeyElement)) {\n                                emitStatement(\"org.bson.types.ObjectId value = ((%s) object).%s()\", interfaceName, primaryKeyGetter)\n                                emitStatement(\"long objKey = Table.NO_MATCH\")\n                                beginControlFlow(\"if (value == null)\")\n                                    emitStatement(\"objKey = table.findFirstNull(pkColumnKey)\")\n                                nextControlFlow(\"else\")\n                                    emitStatement(\"objKey = table.findFirstObjectId(pkColumnKey, value)\")\n                                endControlFlow()\n                            } else if (Utils.isUUID(primaryKeyElement)) {\n                                emitStatement(\"java.util.UUID value = ((%s) object).%s()\", interfaceName, primaryKeyGetter)\n                                emitStatement(\"long objKey = Table.NO_MATCH\")\n                                beginControlFlow(\"if (value == null)\")\n                                    emitStatement(\"objKey = table.findFirstNull(pkColumnKey)\")\n                                nextControlFlow(\"else\")\n                                    emitStatement(\"objKey = table.findFirstUUID(pkColumnKey, value)\")\n                                endControlFlow()\n                            } else {\n                                emitStatement(\"Number value = ((%s) object).%s()\", interfaceName, primaryKeyGetter)\n                                emitStatement(\"long objKey = Table.NO_MATCH\")\n                                beginControlFlow(\"if (value == null)\")\n                                    emitStatement(\"objKey = table.findFirstNull(pkColumnKey)\")\n                                nextControlFlow(\"else\")\n                                    emitStatement(\"objKey = table.findFirstLong(pkColumnKey, value.longValue())\")\n                                endControlFlow()\n                            }\n                        } else {\n                            if (Utils.isString(primaryKeyElement)) {\n                                emitStatement(\"long objKey = table.findFirstString(pkColumnKey, ((%s) object).%s())\", interfaceName, primaryKeyGetter)\n                            } else if (Utils.isObjectId(primaryKeyElement)) {\n                                emitStatement(\"long objKey = table.findFirstObjectId(pkColumnKey, ((%s) object).%s())\", interfaceName, primaryKeyGetter)\n                            } else if (Utils.isUUID(primaryKeyElement)) {\n                                emitStatement(\"long objKey = table.findFirstUUID(pkColumnKey, ((%s) object).%s())\", interfaceName, primaryKeyGetter)\n                            } else {\n                                emitStatement(\"long objKey = table.findFirstLong(pkColumnKey, ((%s) object).%s())\", interfaceName, primaryKeyGetter)\n                            }\n                        }\n\n                        beginControlFlow(\"if (objKey == Table.NO_MATCH)\")\n                            emitStatement(\"canUpdate = false\")\n                        nextControlFlow(\"else\")\n                            beginControlFlow(\"try\")\n                                emitStatement(\"objectContext.set(realm, table.getUncheckedRow(objKey), columnInfo, false, Collections.<String> emptyList())\")\n                                emitStatement(\"realmObject = new %s()\", generatedClassName)\n                                emitStatement(\"cache.put(object, (RealmObjectProxy) realmObject)\")\n                            nextControlFlow(\"finally\")\n                                emitStatement(\"objectContext.clear()\")\n                            endControlFlow()\n                        endControlFlow()\n                    endControlFlow()\n                    emitEmptyLine()\n                    emitStatement(\"return (canUpdate) ? update(realm, columnInfo, realmObject, object, cache, flags) : copy(realm, columnInfo, object, update, cache, flags)\")\n                }\n\n            endMethod()\n            emitEmptyLine()\n        }\n    }\n\n    @Throws(IOException::class)\n    private fun setTableValues(writer: JavaWriter, fieldType: String, fieldName: String, interfaceName: SimpleClassName, getter: String, isUpdate: Boolean) {\n        writer.apply {\n            when(fieldType) {\n                \"long\",\n                \"int\",\n                \"short\",\n                \"byte\" -> {\n                    emitStatement(\"Table.nativeSetLong(tableNativePtr, columnInfo.%sColKey, objKey, ((%s) object).%s(), false)\", fieldName, interfaceName, getter)\n                }\n                \"java.lang.Long\",\n                \"java.lang.Integer\",\n                \"java.lang.Short\",\n                \"java.lang.Byte\" -> {\n                    emitStatement(\"Number %s = ((%s) object).%s()\", getter, interfaceName, getter)\n                    beginControlFlow(\"if (%s != null)\", getter)\n                        emitStatement(\"Table.nativeSetLong(tableNativePtr, columnInfo.%sColKey, objKey, %s.longValue(), false)\", fieldName, getter)\n                        if (isUpdate) {\n                            nextControlFlow(\"else\")\n                                emitStatement(\"Table.nativeSetNull(tableNativePtr, columnInfo.%sColKey, objKey, false)\", fieldName)\n                        }\n                    endControlFlow()\n                }\n                \"io.realm.MutableRealmInteger\" -> {\n                    emitStatement(\"Long %s = ((%s) object).%s().get()\", getter, interfaceName, getter)\n                    beginControlFlow(\"if (%s != null)\", getter)\n                        emitStatement(\"Table.nativeSetLong(tableNativePtr, columnInfo.%sColKey, objKey, %s.longValue(), false)\", fieldName, getter)\n                        if (isUpdate) {\n                            nextControlFlow(\"else\")\n                            emitStatement(\"Table.nativeSetNull(tableNativePtr, columnInfo.%sColKey, objKey, false)\", fieldName)\n                        }\n                    endControlFlow()\n                }\n                \"double\" -> {\n                    emitStatement(\"Table.nativeSetDouble(tableNativePtr, columnInfo.%sColKey, objKey, ((%s) object).%s(), false)\", fieldName, interfaceName, getter)\n                }\n                \"java.lang.Double\" -> {\n                    emitStatement(\"Double %s = ((%s) object).%s()\", getter, interfaceName, getter)\n                    beginControlFlow(\"if (%s != null)\", getter)\n                        emitStatement(\"Table.nativeSetDouble(tableNativePtr, columnInfo.%sColKey, objKey, %s, false)\", fieldName, getter)\n                        if (isUpdate) {\n                            nextControlFlow(\"else\")\n                                emitStatement(\"Table.nativeSetNull(tableNativePtr, columnInfo.%sColKey, objKey, false)\", fieldName)\n                        }\n                    endControlFlow()\n                }\n                \"float\" -> {\n                    emitStatement(\"Table.nativeSetFloat(tableNativePtr, columnInfo.%sColKey, objKey, ((%s) object).%s(), false)\", fieldName, interfaceName, getter)\n                }\n                \"java.lang.Float\" -> {\n                    emitStatement(\"Float %s = ((%s) object).%s()\", getter, interfaceName, getter)\n                    beginControlFlow(\"if (%s != null)\", getter)\n                        emitStatement(\"Table.nativeSetFloat(tableNativePtr, columnInfo.%sColKey, objKey, %s, false)\", fieldName, getter)\n                        if (isUpdate) {\n                            nextControlFlow(\"else\")\n                                emitStatement(\"Table.nativeSetNull(tableNativePtr, columnInfo.%sColKey, objKey, false)\", fieldName)\n                        }\n                    endControlFlow()\n                }\n                \"boolean\" -> {\n                    emitStatement(\"Table.nativeSetBoolean(tableNativePtr, columnInfo.%sColKey, objKey, ((%s) object).%s(), false)\", fieldName, interfaceName, getter)\n                }\n                \"java.lang.Boolean\" -> {\n                    emitStatement(\"Boolean %s = ((%s) object).%s()\", getter, interfaceName, getter)\n                    beginControlFlow(\"if (%s != null)\", getter)\n                        emitStatement(\"Table.nativeSetBoolean(tableNativePtr, columnInfo.%sColKey, objKey, %s, false)\", fieldName, getter)\n                        if (isUpdate) {\n                            nextControlFlow(\"else\")\n                                emitStatement(\"Table.nativeSetNull(tableNativePtr, columnInfo.%sColKey, objKey, false)\", fieldName)\n                        }\n                    endControlFlow()\n                }\n                \"byte[]\" -> {\n                    emitStatement(\"byte[] %s = ((%s) object).%s()\", getter, interfaceName, getter)\n                    beginControlFlow(\"if (%s != null)\", getter)\n                        emitStatement(\"Table.nativeSetByteArray(tableNativePtr, columnInfo.%sColKey, objKey, %s, false)\", fieldName, getter)\n                        if (isUpdate) {\n                            nextControlFlow(\"else\")\n                                emitStatement(\"Table.nativeSetNull(tableNativePtr, columnInfo.%sColKey, objKey, false)\", fieldName)\n                        }\n                    endControlFlow()\n                }\n                \"java.util.Date\" -> {\n                    emitStatement(\"java.util.Date %s = ((%s) object).%s()\", getter, interfaceName, getter)\n                    beginControlFlow(\"if (%s != null)\", getter)\n                        emitStatement(\"Table.nativeSetTimestamp(tableNativePtr, columnInfo.%sColKey, objKey, %s.getTime(), false)\", fieldName, getter)\n                        if (isUpdate) {\n                            nextControlFlow(\"else\")\n                                emitStatement(\"Table.nativeSetNull(tableNativePtr, columnInfo.%sColKey, objKey, false)\", fieldName)\n                        }\n                    endControlFlow()\n                }\n                \"java.lang.String\" -> {\n                    emitStatement(\"String %s = ((%s) object).%s()\", getter, interfaceName, getter)\n                    beginControlFlow(\"if (%s != null)\", getter)\n                        emitStatement(\"Table.nativeSetString(tableNativePtr, columnInfo.%sColKey, objKey, %s, false)\", fieldName, getter)\n                        if (isUpdate) {\n                            nextControlFlow(\"else\")\n                                emitStatement(\"Table.nativeSetNull(tableNativePtr, columnInfo.%sColKey, objKey, false)\", fieldName)\n                        }\n                    endControlFlow()\n                }\n                \"org.bson.types.Decimal128\" -> {\n                    emitStatement(\"org.bson.types.Decimal128 %s = ((%s) object).%s()\", getter, interfaceName, getter)\n                    beginControlFlow(\"if (%s != null)\", getter)\n                        emitStatement(\"Table.nativeSetDecimal128(tableNativePtr, columnInfo.%1\\$sColKey, objKey, %2\\$s.getLow(), %2\\$s.getHigh(), false)\", fieldName, getter)\n                        if (isUpdate) {\n                            nextControlFlow(\"else\")\n                            emitStatement(\"Table.nativeSetNull(tableNativePtr, columnInfo.%sColKey, objKey, false)\", fieldName)\n                        }\n                    endControlFlow()\n                }\n                \"org.bson.types.ObjectId\" -> {\n                    emitStatement(\"org.bson.types.ObjectId %s = ((%s) object).%s()\", getter, interfaceName, getter)\n                    beginControlFlow(\"if (%s != null)\", getter)\n                        emitStatement(\"Table.nativeSetObjectId(tableNativePtr, columnInfo.%sColKey, objKey, %s.toString(), false)\", fieldName, getter)\n                        if (isUpdate) {\n                            nextControlFlow(\"else\")\n                            emitStatement(\"Table.nativeSetNull(tableNativePtr, columnInfo.%sColKey, objKey, false)\", fieldName)\n                        }\n                    endControlFlow()\n                }\n                \"java.util.UUID\" -> {\n                    emitStatement(\"java.util.UUID %s = ((%s) object).%s()\", getter, interfaceName, getter)\n                    beginControlFlow(\"if (%s != null)\", getter)\n                        emitStatement(\"Table.nativeSetUUID(tableNativePtr, columnInfo.%sColKey, objKey, %s.toString(), false)\", fieldName, getter)\n                        if (isUpdate) {\n                            nextControlFlow(\"else\")\n                            emitStatement(\"Table.nativeSetNull(tableNativePtr, columnInfo.%sColKey, objKey, false)\", fieldName)\n                        }\n                    endControlFlow()\n                }\n                else -> {\n                    throw IllegalStateException(\"Unsupported type $fieldType\")\n                }\n            }\n        }\n    }\n\n    @Throws(IOException::class)\n    private fun emitInsertInternal(writer: JavaWriter){\n        writer.apply {\n            addPrimaryKeyCheckIfNeeded(metadata, true, writer)\n            for (field in metadata.fields) {\n                val fieldName = field.simpleName.toString()\n                val fieldType = QualifiedClassName(field.asType().toString())\n                val getter = metadata.getInternalGetter(fieldName)\n\n                when {\n                    Utils.isRealmModel(field) -> {\n                        val isEmbedded = Utils.isFieldTypeEmbedded(field.asType(), classCollection)\n                        emitEmptyLine()\n                        emitStatement(\"%s %sObj = ((%s) object).%s()\", fieldType, fieldName, interfaceName, getter)\n                        beginControlFlow(\"if (%sObj != null)\", fieldName)\n                            emitStatement(\"Long cache%1\\$s = cache.get(%1\\$sObj)\", fieldName)\n                            if (isEmbedded) {\n                                beginControlFlow(\"if (cache%s != null)\", fieldName)\n                                    emitStatement(\"throw new IllegalArgumentException(\\\"Embedded objects can only have one parent pointing to them. This object was already copied, so another object is pointing to it: \\\" + cache%s.toString())\", fieldName)\n                                nextControlFlow(\"else\")\n                                    emitStatement(\"cache%1\\$s = %2\\$s.insert(realm, table, columnInfo.%3\\$sColKey, objKey, %3\\$sObj, cache)\", fieldName, Utils.getProxyClassSimpleName(field), fieldName)\n                                endControlFlow()\n                            } else {\n                                beginControlFlow(\"if (cache%s == null)\", fieldName)\n                                    emitStatement(\"cache%s = %s.insert(realm, %sObj, cache)\", fieldName, Utils.getProxyClassSimpleName(field), fieldName)\n                                endControlFlow()\n                                emitStatement(\"Table.nativeSetLink(tableNativePtr, columnInfo.%1\\$sColKey, objKey, cache%1\\$s, false)\", fieldName)\n                            }\n                        endControlFlow()\n                    }\n                    Utils.isRealmModelList(field) -> {\n                        val genericType: TypeMirror = Utils.getGenericType(field)!!\n                        val isEmbedded = Utils.isFieldTypeEmbedded(genericType, classCollection)\n                        emitEmptyLine()\n                        emitStatement(\"RealmList<%s> %sList = ((%s) object).%s()\", genericType, fieldName, interfaceName, getter)\n                        beginControlFlow(\"if (%sList != null)\", fieldName)\n                            emitStatement(\"OsList %1\\$sOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.%1\\$sColKey)\", fieldName)\n                            beginControlFlow(\"for (%1\\$s %2\\$sItem : %2\\$sList)\", genericType, fieldName)\n                                emitStatement(\"Long cacheItemIndex%1\\$s = cache.get(%1\\$sItem)\", fieldName)\n                                if (isEmbedded) {\n                                    beginControlFlow(\"if (cacheItemIndex%s != null)\", fieldName)\n                                        emitStatement(\"throw new IllegalArgumentException(\\\"Embedded objects can only have one parent pointing to them. This object was already copied, so another object is pointing to it: \\\" + cacheItemIndex%s.toString())\", fieldName)\n                                    nextControlFlow(\"else\")\n                                        emitStatement(\"cacheItemIndex%1\\$s = %2\\$s.insert(realm, table, columnInfo.%3\\$sColKey, objKey, %3\\$sItem, cache)\", fieldName, Utils.getProxyClassName(QualifiedClassName(genericType.toString())), fieldName)\n                                    endControlFlow()\n                                } else {\n                                    beginControlFlow(\"if (cacheItemIndex%s == null)\", fieldName)\n                                        emitStatement(\"cacheItemIndex%1\\$s = %2\\$s.insert(realm, %1\\$sItem, cache)\", fieldName, Utils.getProxyClassSimpleName(field))\n                                    endControlFlow()\n                                    emitStatement(\"%1\\$sOsList.addRow(cacheItemIndex%1\\$s)\", fieldName)\n                                }\n                            endControlFlow()\n                        endControlFlow()\n                    }\n                    Utils.isRealmValueList(field) -> {\n                        val genericType = Utils.getGenericTypeQualifiedName(field)\n                        val elementTypeMirror = TypeMirrors.getRealmListElementTypeMirror(field)\n                        emitEmptyLine()\n                        emitStatement(\"RealmList<%s> %sList = ((%s) object).%s()\", genericType, fieldName, interfaceName, getter)\n                        beginControlFlow(\"if (%sList != null)\", fieldName)\n                            emitStatement(\"OsList %1\\$sOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.%1\\$sColKey)\", fieldName)\n                            beginControlFlow(\"for (%1\\$s %2\\$sItem : %2\\$sList)\", genericType, fieldName)\n                                beginControlFlow(\"if (%1\\$sItem == null)\", fieldName)\n                                    emitStatement(fieldName + \"OsList.addNull()\")\n                                nextControlFlow(\"else\")\n                                    emitStatement(getStatementForAppendingValueToOsList(fieldName + \"OsList\", fieldName + \"Item\", elementTypeMirror))\n                                endControlFlow()\n                            endControlFlow()\n                        endControlFlow()\n                    }\n                    Utils.isRealmAny(field) -> {\n                        emitEmptyLine()\n\n                        emitStatement(\"RealmAny ${fieldName}RealmAny = ((${interfaceName}) object).${getter}()\")\n                        emitStatement(\"${fieldName}RealmAny = ProxyUtils.insert(${fieldName}RealmAny, realm, cache)\")\n                        emitStatement(\"Table.nativeSetRealmAny(tableNativePtr, columnInfo.${fieldName}ColKey, objKey, ${fieldName}RealmAny.getNativePtr(), false)\")\n                    }\n                    Utils.isRealmAnyList(field) -> {\n                        emitEmptyLine()\n\n                        emitStatement(\"RealmList<RealmAny> ${fieldName}UnmanagedList = ((${interfaceName}) object).${getter}()\")\n                        beginControlFlow(\"if (${fieldName}UnmanagedList != null)\")\n                            emitStatement(\"OsList ${fieldName}OsList = new OsList(table.getUncheckedRow(objKey), columnInfo.${fieldName}ColKey)\")\n                            beginControlFlow(\"for (int i = 0; i < ${fieldName}UnmanagedList.size(); i++)\")\n                                emitStatement(\"RealmAny realmAnyItem = ${fieldName}UnmanagedList.get(i)\")\n                                emitStatement(\"realmAnyItem = ProxyUtils.insert(realmAnyItem, realm, cache)\")\n                                emitStatement(\"${fieldName}OsList.addRealmAny(realmAnyItem.getNativePtr())\")\n                            endControlFlow()\n                        endControlFlow()\n                    }\n                    Utils.isRealmValueDictionary(field) -> {\n                        val genericType = Utils.getGenericTypeQualifiedName(field)\n                        val elementTypeMirror = TypeMirrors.getRealmDictionaryElementTypeMirror(field)\n                        emitEmptyLine()\n                        emitStatement(\"RealmDictionary<${genericType}> ${fieldName}UnmanagedDictionary = ((${interfaceName}) object).${getter}()\")\n                        beginControlFlow(\"if (${fieldName}UnmanagedDictionary != null)\", fieldName)\n                            emitStatement(\"OsMap ${fieldName}OsMap = new OsMap(table.getUncheckedRow(objKey), columnInfo.${fieldName}ColKey)\")\n\n                            emitStatement(\"java.util.Set<java.util.Map.Entry<String, ${genericType}>> entries = ${fieldName}UnmanagedDictionary.entrySet()\")\n                            beginControlFlow(\"for (java.util.Map.Entry<String, ${genericType}> entry : entries)\")\n                                emitStatement(\"String entryKey = entry.getKey()\")\n                                emitStatement(\"$genericType ${fieldName}UnmanagedEntryValue = entry.getValue()\")\n                                emitStatement(\"${fieldName}OsMap.put(entryKey, ${fieldName}UnmanagedEntryValue)\")\n                        endControlFlow()\n                        endControlFlow()\n                    }\n                    Utils.isRealmAnyDictionary(field) -> {\n                        val genericType = Utils.getGenericTypeQualifiedName(field)\n                        emitStatement(\"RealmDictionary<RealmAny> ${fieldName}UnmanagedDictionary = ((${interfaceName}) object).${getter}()\")\n                        beginControlFlow(\"if (${fieldName}UnmanagedDictionary != null)\")\n                            emitStatement(\"OsMap ${fieldName}OsMap = new OsMap(table.getUncheckedRow(objKey), columnInfo.${fieldName}ColKey)\")\n                            emitStatement(\"java.util.Set<java.util.Map.Entry<String, ${genericType}>> entries = ${fieldName}UnmanagedDictionary.entrySet()\")\n                            emitStatement(\"java.util.List<String> keys = new java.util.ArrayList<>()\")\n                            emitStatement(\"java.util.List<Long> realmAnyPointers = new java.util.ArrayList<>()\")\n                            beginControlFlow(\"for (java.util.Map.Entry<String, ${genericType}> entry : entries)\")\n                                emitStatement(\"RealmAny realmAnyItem = entry.getValue()\")\n                                emitStatement(\"realmAnyItem = ProxyUtils.insert(realmAnyItem, realm, cache)\")\n                                emitStatement(\"${fieldName}OsMap.putRealmAny(entry.getKey(), realmAnyItem.getNativePtr())\")\n                            endControlFlow()\n                        endControlFlow()\n                        emitEmptyLine()\n                    }\n                    Utils.isRealmModelDictionary(field) -> {\n                        val genericType: QualifiedClassName = Utils.getGenericTypeQualifiedName(field)!!\n                        val listElementType: TypeMirror = Utils.getGenericType(field)!!\n                        val isEmbedded = Utils.isFieldTypeEmbedded(listElementType, classCollection)\n                        val linkedProxyClass: SimpleClassName = Utils.getDictionaryGenericProxyClassSimpleName(field)\n\n                        emitStatement(\"RealmDictionary<${genericType}> ${fieldName}UnmanagedDictionary = ((${interfaceName}) object).${getter}()\")\n                        beginControlFlow(\"if (${fieldName}UnmanagedDictionary != null)\")\n                        emitStatement(\"OsMap ${fieldName}OsMap = new OsMap(table.getUncheckedRow(objKey), columnInfo.${fieldName}ColKey)\")\n                            emitStatement(\"java.util.Set<java.util.Map.Entry<String, ${genericType}>> entries = ${fieldName}UnmanagedDictionary.entrySet()\")\n                            beginControlFlow(\"for (java.util.Map.Entry<String, ${genericType}> entry : entries)\")\n                                emitStatement(\"String entryKey = entry.getKey()\")\n                                emitStatement(\"$genericType ${fieldName}UnmanagedEntryValue = entry.getValue()\")\n                                beginControlFlow(\"if(${fieldName}UnmanagedEntryValue == null)\")\n                                    emitStatement(\"${fieldName}OsMap.put(entryKey, null)\")\n                                nextControlFlow(\"else\")\n                                    // here goes the rest\n                                    emitStatement(\"Long cacheItemIndex${fieldName} = cache.get(${fieldName}UnmanagedEntryValue)\")\n                                    if (isEmbedded) {\n                                        beginControlFlow(\"if (cacheItemIndex${fieldName} != null)\")\n                                            emitStatement(\"\"\"throw new IllegalArgumentException(\"Embedded objects can only have one parent pointing to them. This object was already copied, so another object is pointing to it: cache${fieldName}.toString()\")\"\"\")\n                                        nextControlFlow(\"else\")\n                                            emitStatement(\"cacheItemIndex${fieldName} = ${linkedProxyClass}.insert(realm, table, columnInfo.${fieldName}ColKey, objKey, ${fieldName}UnmanagedEntryValue, cache)\")\n                                        endControlFlow()\n                                        emitStatement(\"${fieldName}OsMap.putRow(entryKey, cacheItemIndex${fieldName})\")\n                                    } else {\n                                        beginControlFlow(\"if (cacheItemIndex${fieldName} == null)\")\n                                            emitStatement(\"cacheItemIndex${fieldName} = ${linkedProxyClass}.insert(realm, ${fieldName}UnmanagedEntryValue, cache)\")\n                                        endControlFlow()\n                                        emitStatement(\"${fieldName}OsMap.putRow(entryKey, cacheItemIndex${fieldName})\")\n                                    }\n                                endControlFlow()\n                            endControlFlow()\n                        endControlFlow()\n                    }\n                    Utils.isRealmModelSet(field) -> {\n                        val genericType: TypeMirror = Utils.getGenericType(field)!!\n                        val isEmbedded = Utils.isFieldTypeEmbedded(genericType, classCollection)\n                        emitEmptyLine()\n                        emitStatement(\"RealmSet<${genericType}> ${fieldName}Set = ((${interfaceName}) object).${getter}()\")\n                        beginControlFlow(\"if (${fieldName}Set != null)\")\n                            emitStatement(\"OsSet ${fieldName}OsSet = new OsSet(table.getUncheckedRow(objKey), columnInfo.${fieldName}ColKey)\")\n                            beginControlFlow(\"for (${genericType} ${fieldName}Item: ${fieldName}Set)\")\n                                emitStatement(\"Long cacheItemIndex${fieldName} = cache.get(${fieldName}Item)\")\n                                if (isEmbedded) {\n                                    emitStatement(\"throw new IllegalArgumentException(\\\"Embedded objects can only have one parent pointing to them. This object was already copied, so another object is pointing to it: \\\" + cacheItemIndex${fieldName}.toString())\")\n                                } else {\n                                    beginControlFlow(\"if (cacheItemIndex${fieldName} == null)\")\n                                        emitStatement(\"cacheItemIndex${fieldName} = ${Utils.getSetGenericProxyClassSimpleName(field)}.insert(realm, ${fieldName}Item, cache)\")\n                                    endControlFlow()\n                                    emitStatement(\"${fieldName}OsSet.addRow(cacheItemIndex${fieldName})\")\n                                }\n                            endControlFlow()\n                        endControlFlow()\n                    }\n                    Utils.isRealmValueSet(field) -> {\n                        val genericType = Utils.getGenericTypeQualifiedName(field)\n                        emitEmptyLine()\n                        emitStatement(\"RealmSet<${genericType}> ${fieldName}Set = ((${interfaceName}) object).${getter}()\")\n                        beginControlFlow(\"if (${fieldName}Set != null)\")\n                            emitStatement(\"OsSet ${fieldName}OsSet = new OsSet(table.getUncheckedRow(objKey), columnInfo.${fieldName}ColKey)\")\n                            beginControlFlow(\"for (${genericType} ${fieldName}Item: ${fieldName}Set)\")\n                                beginControlFlow(\"if (${fieldName}Item == null)\")\n                                    emitStatement(fieldName + \"OsSet.add(($genericType) null)\")\n                                nextControlFlow(\"else\")\n                                    emitStatement(\"${fieldName}OsSet.add(${fieldName}Item)\")\n                                endControlFlow()\n                            endControlFlow()\n                        endControlFlow()\n                    }\n                    Utils.isRealmAnySet(field) -> {\n                        emitEmptyLine()\n\n                        emitStatement(\"RealmSet<RealmAny> ${fieldName}UnmanagedSet = ((${interfaceName}) object).${getter}()\")\n                        beginControlFlow(\"if (${fieldName}UnmanagedSet != null)\")\n                            emitStatement(\"OsSet ${fieldName}OsSet = new OsSet(table.getUncheckedRow(objKey), columnInfo.${fieldName}ColKey)\")\n                            beginControlFlow(\"for (RealmAny realmAnyItem: ${fieldName}UnmanagedSet)\")\n                                emitStatement(\"realmAnyItem = ProxyUtils.insert(realmAnyItem, realm, cache)\")\n                                emitStatement(\"${fieldName}OsSet.addRealmAny(realmAnyItem.getNativePtr())\")\n                            endControlFlow()\n                        endControlFlow()\n                    }\n                    else -> {\n                        if (metadata.primaryKey !== field) {\n                            setTableValues(writer, fieldType.toString(), fieldName, interfaceName, getter, false)\n                        }\n                    }\n                }\n            }\n        }\n    }\n\n    @Throws(IOException::class)\n    private fun emitInsertMethod(writer: JavaWriter) {\n        writer.apply {\n            val topLevelArgs = arrayOf(\"Realm\", \"realm\",\n                    qualifiedJavaClassName.toString(), \"object\",\n                    \"Map<RealmModel,Long>\", \"cache\")\n            val embeddedArgs = arrayOf(\"Realm\", \"realm\",\n                    \"Table\", \"parentObjectTable\",\n                    \"long\", \"parentColumnKey\",\n                    \"long\", \"parentObjectKey\",\n                    qualifiedJavaClassName.toString(), \"object\",\n                    \"Map<RealmModel,Long>\", \"cache\")\n            val args = if (metadata.embedded) embeddedArgs else topLevelArgs\n            beginMethod(\"long\",\"insert\", EnumSet.of(Modifier.PUBLIC, Modifier.STATIC), *args)\n\n            // If object is already in the Realm there is nothing to update, unless it is an embedded\n            // object. In which case we always update the underlying object.\n            if (!metadata.embedded) {\n                beginControlFlow(\"if (object instanceof RealmObjectProxy && !RealmObject.isFrozen(object) && ((RealmObjectProxy) object).realmGet\\$proxyState().getRealm\\$realm() != null && ((RealmObjectProxy) object).realmGet\\$proxyState().getRealm\\$realm().getPath().equals(realm.getPath()))\")\n                   emitStatement(\"return ((RealmObjectProxy) object).realmGet\\$proxyState().getRow\\$realm().getObjectKey()\")\n                endControlFlow()\n            }\n\n            emitStatement(\"Table table = realm.getTable(%s.class)\", qualifiedJavaClassName)\n            emitStatement(\"long tableNativePtr = table.getNativePtr()\")\n            emitStatement(\"%s columnInfo = (%s) realm.getSchema().getColumnInfo(%s.class)\", columnInfoClassName(), columnInfoClassName(), qualifiedJavaClassName)\n\n            if (metadata.hasPrimaryKey()) {\n                emitStatement(\"long pkColumnKey = %s\", fieldColKeyVariableReference(metadata.primaryKey))\n            }\n\n            emitInsertInternal(this)\n\n            emitStatement(\"return objKey\")\n            endMethod()\n            emitEmptyLine()\n        }\n    }\n\n    @Throws(IOException::class)\n    private fun emitInsertListMethod(writer: JavaWriter) {\n        writer.apply {\n            val topLevelArgs = arrayOf(\"Realm\", \"realm\",\n                    \"Iterator<? extends RealmModel>\", \"objects\",\n                    \"Map<RealmModel,Long>\", \"cache\")\n            val embeddedArgs = arrayOf(\"Realm\", \"realm\",\n                    \"Table\", \"parentObjectTable\",\n                    \"long\", \"parentColumnKey\",\n                    \"long\", \"parentObjectKey\",\n                    \"Iterator<? extends RealmModel>\", \"objects\",\n                    \"Map<RealmModel,Long>\", \"cache\")\n            val args = if (metadata.embedded) embeddedArgs else topLevelArgs\n\n            beginMethod(\"void\", \"insert\", EnumSet.of(Modifier.PUBLIC, Modifier.STATIC), *args)\n                emitStatement(\"Table table = realm.getTable(%s.class)\", qualifiedJavaClassName)\n                emitStatement(\"long tableNativePtr = table.getNativePtr()\")\n                emitStatement(\"%s columnInfo = (%s) realm.getSchema().getColumnInfo(%s.class)\", columnInfoClassName(), columnInfoClassName(), qualifiedJavaClassName)\n                if (metadata.hasPrimaryKey()) {\n                    emitStatement(\"long pkColumnKey = %s\", fieldColKeyVariableReference(metadata.primaryKey))\n                }\n                emitStatement(\"%s object = null\", qualifiedJavaClassName)\n\n                beginControlFlow(\"while (objects.hasNext())\")\n                    emitStatement(\"object = (%s) objects.next()\", qualifiedJavaClassName)\n                    beginControlFlow(\"if (cache.containsKey(object))\")\n                        emitStatement(\"continue\")\n                    endControlFlow()\n                    beginControlFlow(\"if (object instanceof RealmObjectProxy && !RealmObject.isFrozen(object) && ((RealmObjectProxy) object).realmGet\\$proxyState().getRealm\\$realm() != null && ((RealmObjectProxy) object).realmGet\\$proxyState().getRealm\\$realm().getPath().equals(realm.getPath()))\")\n                        emitStatement(\"cache.put(object, ((RealmObjectProxy) object).realmGet\\$proxyState().getRow\\$realm().getObjectKey())\")\n                        emitStatement(\"continue\")\n                    endControlFlow()\n\n                    emitInsertInternal(this)\n                endControlFlow()\n            endMethod()\n            emitEmptyLine()\n        }\n    }\n\n    @Throws(IOException::class)\n    private fun insertOrUpdateInternal(writer: JavaWriter){\n        writer.apply {\n            addPrimaryKeyCheckIfNeeded(metadata, false, writer)\n            for (field in metadata.fields) {\n                val fieldName = field.simpleName.toString()\n                val fieldType = QualifiedClassName(field.asType().toString())\n                val getter = metadata.getInternalGetter(fieldName)\n\n                when {\n                    Utils.isRealmModel(field) -> {\n                        val isEmbedded = Utils.isFieldTypeEmbedded(field.asType(), classCollection)\n                        emitEmptyLine()\n                        emitStatement(\"%s %sObj = ((%s) object).%s()\", fieldType, fieldName, interfaceName, getter)\n                        beginControlFlow(\"if (%sObj != null)\", fieldName)\n                            emitStatement(\"Long cache%1\\$s = cache.get(%1\\$sObj)\", fieldName)\n                            if (isEmbedded) {\n                                beginControlFlow(\"if (cache%s != null)\", fieldName)\n                                    emitStatement(\"throw new IllegalArgumentException(\\\"Embedded objects can only have one parent pointing to them. This object was already copied, so another object is pointing to it: \\\" + cache%s.toString())\", fieldName)\n                                nextControlFlow(\"else\")\n                                    emitStatement(\"cache%1\\$s = %2\\$s.insertOrUpdate(realm, table, columnInfo.%3\\$sColKey, objKey, %3\\$sObj, cache)\", fieldName, Utils.getProxyClassSimpleName(field), fieldName)\n                                endControlFlow()\n                            } else {\n                                beginControlFlow(\"if (cache%s == null)\", fieldName)\n                                    emitStatement(\"cache%1\\$s = %2\\$s.insertOrUpdate(realm, %1\\$sObj, cache)\", fieldName, Utils.getProxyClassSimpleName(field))\n                                endControlFlow()\n                                emitStatement(\"Table.nativeSetLink(tableNativePtr, columnInfo.%1\\$sColKey, objKey, cache%1\\$s, false)\", fieldName)\n                            }\n                        nextControlFlow(\"else\")\n                            // No need to throw exception here if the field is not nullable. A exception will be thrown in setter.\n                            emitStatement(\"Table.nativeNullifyLink(tableNativePtr, columnInfo.%sColKey, objKey)\", fieldName)\n                        endControlFlow()\n                    }\n                    Utils.isRealmModelList(field) -> {\n                        val genericType: TypeMirror = Utils.getGenericType(field)!!\n                        val isEmbedded = Utils.isFieldTypeEmbedded(genericType, classCollection)\n\n                        emitEmptyLine()\n                        emitStatement(\"OsList %1\\$sOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.%1\\$sColKey)\", fieldName)\n                        emitStatement(\"RealmList<%s> %sList = ((%s) object).%s()\", genericType, fieldName, interfaceName, getter)\n                        if (isEmbedded) {\n                            emitStatement(\"%1\\$sOsList.removeAll()\", fieldName)\n                            beginControlFlow(\"if (%sList != null)\", fieldName)\n                                beginControlFlow(\"for (%1\\$s %2\\$sItem : %2\\$sList)\", genericType, fieldName)\n                                    emitStatement(\"Long cacheItemIndex%1\\$s = cache.get(%1\\$sItem)\", fieldName)\n                                    beginControlFlow(\"if (cacheItemIndex%s != null)\", fieldName)\n                                        emitStatement(\"throw new IllegalArgumentException(\\\"Embedded objects can only have one parent pointing to them. This object was already copied, so another object is pointing to it: \\\" + cacheItemIndex%s.toString())\", fieldName)\n                                    nextControlFlow(\"else\")\n                                        emitStatement(\"cacheItemIndex%1\\$s = %2\\$s.insertOrUpdate(realm, table, columnInfo.%3\\$sColKey, objKey, %3\\$sItem, cache)\", fieldName, Utils.getProxyClassName(QualifiedClassName(genericType.toString())), fieldName)\n                                    endControlFlow()\n                                endControlFlow()\n                            endControlFlow()\n                        } else {\n                            beginControlFlow(\"if (%1\\$sList != null && %1\\$sList.size() == %1\\$sOsList.size())\", fieldName)\n                                emitSingleLineComment(\"For lists of equal lengths, we need to set each element directly as clearing the receiver list can be wrong if the input and target list are the same.\")\n                                emitStatement(\"int objectCount = %1\\$sList.size()\", fieldName)\n                                beginControlFlow(\"for (int i = 0; i < objectCount; i++)\")\n                                    emitStatement(\"%1\\$s %2\\$sItem = %2\\$sList.get(i)\", genericType, fieldName)\n                                    emitStatement(\"Long cacheItemIndex%1\\$s = cache.get(%1\\$sItem)\", fieldName)\n                                    beginControlFlow(\"if (cacheItemIndex%s == null)\", fieldName)\n                                        emitStatement(\"cacheItemIndex%1\\$s = %2\\$s.insertOrUpdate(realm, %1\\$sItem, cache)\", fieldName, Utils.getProxyClassSimpleName(field))\n                                    endControlFlow()\n                                    emitStatement(\"%1\\$sOsList.setRow(i, cacheItemIndex%1\\$s)\", fieldName)\n                                endControlFlow()\n                            nextControlFlow(\"else\")\n                                emitStatement(\"%1\\$sOsList.removeAll()\", fieldName)\n                                beginControlFlow(\"if (%sList != null)\", fieldName)\n                                    beginControlFlow(\"for (%1\\$s %2\\$sItem : %2\\$sList)\", genericType, fieldName)\n                                        emitStatement(\"Long cacheItemIndex%1\\$s = cache.get(%1\\$sItem)\", fieldName)\n                                        beginControlFlow(\"if (cacheItemIndex%s == null)\", fieldName)\n                                            emitStatement(\"cacheItemIndex%1\\$s = %2\\$s.insertOrUpdate(realm, %1\\$sItem, cache)\", fieldName, Utils.getProxyClassSimpleName(field))\n                                        endControlFlow()\n                                        emitStatement(\"%1\\$sOsList.addRow(cacheItemIndex%1\\$s)\", fieldName)\n                                    endControlFlow()\n                                endControlFlow()\n                            endControlFlow()\n                        }\n                        emitEmptyLine()\n                    }\n                    Utils.isRealmValueList(field) -> {\n                        val genericType = Utils.getGenericTypeQualifiedName(field)\n                        val elementTypeMirror = TypeMirrors.getRealmListElementTypeMirror(field)\n                        emitEmptyLine()\n                        emitStatement(\"OsList %1\\$sOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.%1\\$sColKey)\", fieldName)\n                        emitStatement(\"%1\\$sOsList.removeAll()\", fieldName)\n                        emitStatement(\"RealmList<%s> %sList = ((%s) object).%s()\", genericType, fieldName, interfaceName, getter)\n                        beginControlFlow(\"if (%sList != null)\", fieldName)\n                           beginControlFlow(\"for (%1\\$s %2\\$sItem : %2\\$sList)\", genericType, fieldName)\n                                beginControlFlow(\"if (%1\\$sItem == null)\", fieldName)\n                                    emitStatement(\"%1\\$sOsList.addNull()\", fieldName)\n                                nextControlFlow(\"else\")\n                                    emitStatement(getStatementForAppendingValueToOsList(fieldName + \"OsList\", fieldName + \"Item\", elementTypeMirror))\n                                endControlFlow()\n                            endControlFlow()\n                        endControlFlow()\n                        emitEmptyLine()\n                    }\n                    Utils.isRealmAny(field) -> {\n                        emitStatement(\"RealmAny ${fieldName}RealmAny = ((${interfaceName}) object).${getter}()\")\n                        emitStatement(\"${fieldName}RealmAny = ProxyUtils.insertOrUpdate(${fieldName}RealmAny, realm, cache)\")\n                        emitStatement(\"Table.nativeSetRealmAny(tableNativePtr, columnInfo.${fieldName}ColKey, objKey, ${fieldName}RealmAny.getNativePtr(), false)\")\n                    }\n                    Utils.isRealmAnyList(field) -> {\n                        emitEmptyLine()\n                        emitStatement(\"OsList ${fieldName}OsList = new OsList(table.getUncheckedRow(objKey), columnInfo.${fieldName}ColKey)\")\n                        emitStatement(\"RealmList<RealmAny> ${fieldName}List = ((${interfaceName}) object).${getter}()\")\n\n                        beginControlFlow(\"if (${fieldName}List != null && ${fieldName}List.size() == ${fieldName}OsList.size())\")\n                            emitSingleLineComment(\"For lists of equal lengths, we need to set each element directly as clearing the receiver list can be wrong if the input and target list are the same.\")\n                            emitStatement(\"int objectCount = ${fieldName}List.size()\")\n                            beginControlFlow(\"for (int i = 0; i < objectCount; i++)\")\n                                emitStatement(\"RealmAny ${fieldName}Item = ${fieldName}List.get(i)\")\n                                emitStatement(\"Long cacheItemIndex${fieldName} = cache.get(${fieldName}Item)\")\n                                beginControlFlow(\"if (cacheItemIndex${fieldName} == null)\")\n                                    emitStatement(\"${fieldName}Item = ProxyUtils.insertOrUpdate(${fieldName}Item, realm, cache)\")\n                                endControlFlow()\n                                emitStatement(\"${fieldName}OsList.setRealmAny(i, ${fieldName}Item.getNativePtr())\")\n                            endControlFlow()\n                        nextControlFlow(\"else\")\n                            emitStatement(\"${fieldName}OsList.removeAll()\")\n                            beginControlFlow(\"if (${fieldName}List != null)\")\n                                beginControlFlow(\"for (RealmAny ${fieldName}Item : ${fieldName}List)\")\n                                    emitStatement(\"Long cacheItemIndex${fieldName} = cache.get(${fieldName}Item)\")\n                                    beginControlFlow(\"if (cacheItemIndex${fieldName} == null)\")\n                                        emitStatement(\"${fieldName}Item = ProxyUtils.insertOrUpdate(${fieldName}Item, realm, cache)\")\n                                    endControlFlow()\n                                    emitStatement(\"${fieldName}OsList.addRealmAny(${fieldName}Item.getNativePtr())\")\n                                endControlFlow()\n                            endControlFlow()\n                        endControlFlow()\n                    }\n                    Utils.isRealmModelDictionary(field) -> {\n                        val genericType: QualifiedClassName = Utils.getGenericTypeQualifiedName(field)!!\n                        val dictElementType: TypeMirror = Utils.getGenericType(field)!!\n                        val isEmbedded = Utils.isFieldTypeEmbedded(dictElementType, classCollection)\n                        val linkedProxyClass: SimpleClassName = Utils.getDictionaryGenericProxyClassSimpleName(field)\n\n                        emitStatement(\"RealmDictionary<${genericType}> ${fieldName}UnmanagedDictionary = ((${interfaceName}) object).${getter}()\")\n                        beginControlFlow(\"if (${fieldName}UnmanagedDictionary != null)\")\n                        emitStatement(\"OsMap ${fieldName}OsMap = new OsMap(table.getUncheckedRow(objKey), columnInfo.${fieldName}ColKey)\")\n                            emitStatement(\"java.util.Set<java.util.Map.Entry<String, ${genericType}>> entries = ${fieldName}UnmanagedDictionary.entrySet()\")\n                            beginControlFlow(\"for (java.util.Map.Entry<String, ${genericType}> entry : entries)\")\n                                emitStatement(\"String entryKey = entry.getKey()\")\n                                emitStatement(\"$genericType ${fieldName}UnmanagedEntryValue = entry.getValue()\")\n                                beginControlFlow(\"if(${fieldName}UnmanagedEntryValue == null)\")\n                                    emitStatement(\"${fieldName}OsMap.put(entryKey, null)\")\n                                nextControlFlow(\"else\")\n                                    // here goes the rest\n                                    emitStatement(\"Long cacheItemIndex${fieldName} = cache.get(${fieldName}UnmanagedEntryValue)\")\n                                    if (isEmbedded) {\n                                        beginControlFlow(\"if (cacheItemIndex${fieldName} != null)\")\n                                            emitStatement(\"\"\"throw new IllegalArgumentException(\"Embedded objects can only have one parent pointing to them. This object was already copied, so another object is pointing to it: cache${fieldName}.toString()\")\"\"\")\n                                        nextControlFlow(\"else\")\n                                            emitStatement(\"cacheItemIndex${fieldName} = ${linkedProxyClass}.insertOrUpdate(realm, table, columnInfo.${fieldName}ColKey, objKey, ${fieldName}UnmanagedEntryValue, cache)\")\n                                        endControlFlow()\n                                        emitStatement(\"${fieldName}OsMap.putRow(entryKey, cacheItemIndex${fieldName})\")\n                                    } else {\n                                        beginControlFlow(\"if (cacheItemIndex${fieldName} == null)\")\n                                            emitStatement(\"cacheItemIndex${fieldName} = ${linkedProxyClass}.insertOrUpdate(realm, ${fieldName}UnmanagedEntryValue, cache)\")\n                                        endControlFlow()\n                                        emitStatement(\"${fieldName}OsMap.putRow(entryKey, cacheItemIndex${fieldName})\")\n                                    }\n                                endControlFlow()\n                            endControlFlow()\n                        endControlFlow()\n                    }\n                    Utils.isRealmValueDictionary(field) -> {\n                        val genericType = Utils.getGenericTypeQualifiedName(field)\n                        emitEmptyLine()\n                        emitStatement(\"RealmDictionary<${genericType}> ${fieldName}UnmanagedDictionary = ((${interfaceName}) object).${getter}()\")\n                        beginControlFlow(\"if (${fieldName}UnmanagedDictionary != null)\", fieldName)\n                            emitStatement(\"OsMap ${fieldName}OsMap = new OsMap(table.getUncheckedRow(objKey), columnInfo.${fieldName}ColKey)\")\n\n                            emitStatement(\"java.util.Set<java.util.Map.Entry<String, ${genericType}>> entries = ${fieldName}UnmanagedDictionary.entrySet()\")\n                            beginControlFlow(\"for (java.util.Map.Entry<String, ${genericType}> entry : entries)\")\n                                emitStatement(\"String entryKey = entry.getKey()\")\n                                emitStatement(\"$genericType ${fieldName}UnmanagedEntryValue = entry.getValue()\")\n                                emitStatement(\"${fieldName}OsMap.put(entryKey, ${fieldName}UnmanagedEntryValue)\")\n                        endControlFlow()\n                        endControlFlow()\n                    }\n                    Utils.isRealmAnyDictionary(field) -> {\n                        val genericType = Utils.getGenericTypeQualifiedName(field)\n                        emitStatement(\"RealmDictionary<RealmAny> ${fieldName}UnmanagedDictionary = ((${interfaceName}) object).${getter}()\")\n                        beginControlFlow(\"if (${fieldName}UnmanagedDictionary != null)\")\n                            emitStatement(\"OsMap ${fieldName}OsMap = new OsMap(table.getUncheckedRow(objKey), columnInfo.${fieldName}ColKey)\")\n                            emitStatement(\"java.util.Set<java.util.Map.Entry<String, ${genericType}>> entries = ${fieldName}UnmanagedDictionary.entrySet()\")\n                            emitStatement(\"java.util.List<String> keys = new java.util.ArrayList<>()\")\n                            emitStatement(\"java.util.List<Long> realmAnyPointers = new java.util.ArrayList<>()\")\n                            beginControlFlow(\"for (java.util.Map.Entry<String, ${genericType}> entry : entries)\")\n                                emitStatement(\"RealmAny realmAnyItem = entry.getValue()\")\n                                emitStatement(\"realmAnyItem = ProxyUtils.insertOrUpdate(realmAnyItem, realm, cache)\")\n                                emitStatement(\"${fieldName}OsMap.putRealmAny(entry.getKey(), realmAnyItem.getNativePtr())\")\n                            endControlFlow()\n                        endControlFlow()\n                        emitEmptyLine()\n                    }\n                    Utils.isRealmModelSet(field) -> {\n                        val genericType: TypeMirror = Utils.getGenericType(field)!!\n                        val isEmbedded = Utils.isFieldTypeEmbedded(genericType, classCollection)\n\n                        emitEmptyLine()\n                        emitStatement(\"OsSet %1\\$sOsSet = new OsSet(table.getUncheckedRow(objKey), columnInfo.%1\\$sColKey)\", fieldName)\n                        emitStatement(\"RealmSet<%s> %sSet = ((%s) object).%s()\", genericType, fieldName, interfaceName, getter)\n                        if (isEmbedded) {\n                            // throw not supported\n                            throw UnsupportedOperationException(\"Field $fieldName of type RealmSet<${genericType}>, RealmSet does not support embedded objects.\")\n                        } else {\n                            beginControlFlow(\"if (%1\\$sSet != null && %1\\$sSet.size() == %1\\$sOsSet.size())\", fieldName)\n                                emitSingleLineComment(\"For Sets of equal lengths, we need to set each element directly as clearing the receiver Set can be wrong if the input and target Set are the same.\")\n                                emitStatement(\"int objectCount = %1\\$sSet.size()\", fieldName)\n                                beginControlFlow(\"for (${genericType} ${fieldName}Item: ${fieldName}Set)\")\n                                    emitStatement(\"Long cacheItemIndex%1\\$s = cache.get(%1\\$sItem)\", fieldName)\n                                    beginControlFlow(\"if (cacheItemIndex%s == null)\", fieldName)\n                                        emitStatement(\"cacheItemIndex%1\\$s = %2\\$s.insertOrUpdate(realm, %1\\$sItem, cache)\", fieldName, Utils.getSetGenericProxyClassSimpleName(field))\n                                    endControlFlow()\n                                    emitStatement(\"%1\\$sOsSet.addRow(cacheItemIndex%1\\$s)\", fieldName)\n                                endControlFlow()\n                            nextControlFlow(\"else\")\n                                emitStatement(\"%1\\$sOsSet.clear()\", fieldName)\n                                beginControlFlow(\"if (%sSet != null)\", fieldName)\n                                    beginControlFlow(\"for (%1\\$s %2\\$sItem : %2\\$sSet)\", genericType, fieldName)\n                                        emitStatement(\"Long cacheItemIndex%1\\$s = cache.get(%1\\$sItem)\", fieldName)\n                                        beginControlFlow(\"if (cacheItemIndex%s == null)\", fieldName)\n                                            emitStatement(\"cacheItemIndex%1\\$s = %2\\$s.insertOrUpdate(realm, %1\\$sItem, cache)\", fieldName, Utils.getSetGenericProxyClassSimpleName(field))\n                                        endControlFlow()\n                                        emitStatement(\"%1\\$sOsSet.addRow(cacheItemIndex%1\\$s)\", fieldName)\n                                    endControlFlow()\n                                endControlFlow()\n                            endControlFlow()\n                        }\n                        emitEmptyLine()\n                    }\n                    Utils.isRealmValueSet(field) -> {\n                        val genericType = Utils.getGenericTypeQualifiedName(field)\n                        emitEmptyLine()\n                        emitStatement(\"OsSet %1\\$sOsSet = new OsSet(table.getUncheckedRow(objKey), columnInfo.%1\\$sColKey)\", fieldName)\n                        emitStatement(\"%1\\$sOsSet.clear()\", fieldName)\n                        emitStatement(\"RealmSet<%s> %sSet = ((%s) object).%s()\", genericType, fieldName, interfaceName, getter)\n                        beginControlFlow(\"if (%sSet != null)\", fieldName)\n                           beginControlFlow(\"for (%1\\$s %2\\$sItem : %2\\$sSet)\", genericType, fieldName)\n                                beginControlFlow(\"if (%1\\$sItem == null)\", fieldName)\n                                    emitStatement(\"%1\\$sOsSet.add(($genericType) null)\", fieldName)\n                                nextControlFlow(\"else\")\n                                    emitStatement(\"${fieldName}OsSet.add(${fieldName}Item)\")\n                                endControlFlow()\n                            endControlFlow()\n                        endControlFlow()\n                        emitEmptyLine()\n                    }\n                    Utils.isRealmAnySet(field) -> {\n                        emitEmptyLine()\n                        emitStatement(\"OsSet ${fieldName}OsSet = new OsSet(table.getUncheckedRow(objKey), columnInfo.${fieldName}ColKey)\")\n                        emitStatement(\"RealmSet<RealmAny> ${fieldName}Set = ((${interfaceName}) object).${getter}()\")\n\n                        beginControlFlow(\"if (${fieldName}Set != null && ${fieldName}Set.size() == ${fieldName}OsSet.size())\")\n                            emitSingleLineComment(\"For Sets of equal lengths, we need to set each element directly as clearing the receiver Set can be wrong if the input and target Set are the same.\")\n                            emitStatement(\"int objectCount = ${fieldName}Set.size()\")\n                            beginControlFlow(\"for (RealmAny ${fieldName}Item: ${fieldName}Set)\")\n                                emitStatement(\"Long cacheItemIndex${fieldName} = cache.get(${fieldName}Item)\")\n                                beginControlFlow(\"if (cacheItemIndex${fieldName} == null)\")\n                                    emitStatement(\"${fieldName}Item = ProxyUtils.insertOrUpdate(${fieldName}Item, realm, cache)\")\n                                endControlFlow()\n                                emitStatement(\"${fieldName}OsSet.addRealmAny(${fieldName}Item.getNativePtr())\")\n                            endControlFlow()\n                        nextControlFlow(\"else\")\n                            emitStatement(\"${fieldName}OsSet.clear()\")\n                            beginControlFlow(\"if (${fieldName}Set != null)\")\n                                beginControlFlow(\"for (RealmAny ${fieldName}Item : ${fieldName}Set)\")\n                                    emitStatement(\"Long cacheItemIndex${fieldName} = cache.get(${fieldName}Item)\")\n                                    beginControlFlow(\"if (cacheItemIndex${fieldName} == null)\")\n                                        emitStatement(\"${fieldName}Item = ProxyUtils.insertOrUpdate(${fieldName}Item, realm, cache)\")\n                                    endControlFlow()\n                                    emitStatement(\"${fieldName}OsSet.addRealmAny(${fieldName}Item.getNativePtr())\")\n                                endControlFlow()\n                            endControlFlow()\n                        endControlFlow()\n                    }\n                    else -> {\n                        if (metadata.primaryKey !== field) {\n                            setTableValues(writer, fieldType.toString(), fieldName, interfaceName, getter, true)\n                        }\n                    }\n                }\n            }\n        }\n    }\n\n    @Throws(IOException::class)\n    private fun emitInsertOrUpdateMethod(writer: JavaWriter) {\n        writer.apply {\n            val topLevelArgs = arrayOf(\"Realm\", \"realm\",\n                    qualifiedJavaClassName.toString(), \"object\",\n                    \"Map<RealmModel,Long>\", \"cache\")\n            val embeddedArgs = arrayOf(\"Realm\", \"realm\",\n                    \"Table\", \"parentObjectTable\",\n                    \"long\", \"parentColumnKey\",\n                    \"long\", \"parentObjectKey\",\n                    qualifiedJavaClassName.toString(), \"object\",\n                    \"Map<RealmModel,Long>\", \"cache\")\n            val args = if (metadata.embedded) embeddedArgs else topLevelArgs\n            beginMethod(\"long\", \"insertOrUpdate\", EnumSet.of(Modifier.PUBLIC, Modifier.STATIC), *args)\n\n            // If object is already in the Realm there is nothing to update\n            beginControlFlow(\"if (object instanceof RealmObjectProxy && !RealmObject.isFrozen(object) && ((RealmObjectProxy) object).realmGet\\$proxyState().getRealm\\$realm() != null && ((RealmObjectProxy) object).realmGet\\$proxyState().getRealm\\$realm().getPath().equals(realm.getPath()))\")\n                emitStatement(\"return ((RealmObjectProxy) object).realmGet\\$proxyState().getRow\\$realm().getObjectKey()\")\n            endControlFlow()\n            emitStatement(\"Table table = realm.getTable(%s.class)\", qualifiedJavaClassName)\n            emitStatement(\"long tableNativePtr = table.getNativePtr()\")\n            emitStatement(\"%s columnInfo = (%s) realm.getSchema().getColumnInfo(%s.class)\", columnInfoClassName(), columnInfoClassName(), qualifiedJavaClassName)\n            if (metadata.hasPrimaryKey()) {\n                emitStatement(\"long pkColumnKey = %s\", fieldColKeyVariableReference(metadata.primaryKey))\n            }\n            insertOrUpdateInternal(this)\n\n            emitStatement(\"return objKey\")\n            endMethod()\n            emitEmptyLine()\n        }\n    }\n\n    @Throws(IOException::class)\n    private fun emitInsertOrUpdateListMethod(writer: JavaWriter) {\n        writer.apply {\n            val topLevelArgs = arrayOf(\"Realm\", \"realm\",\n                    \"Iterator<? extends RealmModel>\", \"objects\",\n                    \"Map<RealmModel,Long>\", \"cache\")\n            val embeddedArgs = arrayOf(\"Realm\", \"realm\",\n                    \"Table\", \"parentObjectTable\",\n                    \"long\", \"parentColumnKey\",\n                    \"long\", \"parentObjectKey\",\n                    \"Iterator<? extends RealmModel>\", \"objects\",\n                    \"Map<RealmModel,Long>\", \"cache\")\n            val args = if (metadata.embedded) embeddedArgs else topLevelArgs\n\n            beginMethod(\"void\", \"insertOrUpdate\", EnumSet.of(Modifier.PUBLIC, Modifier.STATIC), *args)\n\n                emitStatement(\"Table table = realm.getTable(%s.class)\", qualifiedJavaClassName)\n                emitStatement(\"long tableNativePtr = table.getNativePtr()\")\n                emitStatement(\"%s columnInfo = (%s) realm.getSchema().getColumnInfo(%s.class)\", columnInfoClassName(), columnInfoClassName(), qualifiedJavaClassName)\n                if (metadata.hasPrimaryKey()) {\n                    emitStatement(\"long pkColumnKey = %s\", fieldColKeyVariableReference(metadata.primaryKey))\n                }\n                emitStatement(\"%s object = null\", qualifiedJavaClassName)\n                beginControlFlow(\"while (objects.hasNext())\")\n                    emitStatement(\"object = (%s) objects.next()\", qualifiedJavaClassName)\n                    beginControlFlow(\"if (cache.containsKey(object))\")\n                        emitStatement(\"continue\")\n                    endControlFlow()\n\n                    beginControlFlow(\"if (object instanceof RealmObjectProxy && !RealmObject.isFrozen(object) && ((RealmObjectProxy) object).realmGet\\$proxyState().getRealm\\$realm() != null && ((RealmObjectProxy) object).realmGet\\$proxyState().getRealm\\$realm().getPath().equals(realm.getPath()))\")\n                        emitStatement(\"cache.put(object, ((RealmObjectProxy) object).realmGet\\$proxyState().getRow\\$realm().getObjectKey())\")\n                        emitStatement(\"continue\")\n                    endControlFlow()\n\n                    insertOrUpdateInternal(this)\n                endControlFlow()\n            endMethod()\n            emitEmptyLine()\n        }\n    }\n\n    @Throws(IOException::class)\n    private fun addPrimaryKeyCheckIfNeeded(metadata: ClassMetaData, throwIfPrimaryKeyDuplicate: Boolean, writer: JavaWriter) {\n        writer.apply {\n            if (metadata.hasPrimaryKey()) {\n                val primaryKeyGetter = metadata.primaryKeyGetter\n                val primaryKeyElement = metadata.primaryKey\n                if (metadata.isNullable(primaryKeyElement!!)) {\n                    if (Utils.isString(primaryKeyElement)) {\n                        emitStatement(\"String primaryKeyValue = ((%s) object).%s()\", interfaceName, primaryKeyGetter)\n                        emitStatement(\"long objKey = Table.NO_MATCH\")\n                        beginControlFlow(\"if (primaryKeyValue == null)\")\n                            emitStatement(\"objKey = Table.nativeFindFirstNull(tableNativePtr, pkColumnKey)\")\n                        nextControlFlow(\"else\")\n                            emitStatement(\"objKey = Table.nativeFindFirstString(tableNativePtr, pkColumnKey, primaryKeyValue)\")\n                        endControlFlow()\n                    } else if (Utils.isObjectId(primaryKeyElement)) {\n                        emitStatement(\"org.bson.types.ObjectId primaryKeyValue = ((%s) object).%s()\", interfaceName, primaryKeyGetter)\n                        emitStatement(\"long objKey = Table.NO_MATCH\")\n                        beginControlFlow(\"if (primaryKeyValue == null)\")\n                            emitStatement(\"objKey = Table.nativeFindFirstNull(tableNativePtr, pkColumnKey)\")\n                        nextControlFlow(\"else\")\n                            emitStatement(\"objKey = Table.nativeFindFirstObjectId(tableNativePtr, pkColumnKey, primaryKeyValue.toString())\")\n                        endControlFlow()\n                    } else if (Utils.isUUID(primaryKeyElement)) {\n                        emitStatement(\"java.util.UUID primaryKeyValue = ((%s) object).%s()\", interfaceName, primaryKeyGetter)\n                        emitStatement(\"long objKey = Table.NO_MATCH\")\n                        beginControlFlow(\"if (primaryKeyValue == null)\")\n                            emitStatement(\"objKey = Table.nativeFindFirstNull(tableNativePtr, pkColumnKey)\")\n                        nextControlFlow(\"else\")\n                            emitStatement(\"objKey = Table.nativeFindFirstUUID(tableNativePtr, pkColumnKey, primaryKeyValue.toString())\")\n                        endControlFlow()\n                    } else {\n                        emitStatement(\"Object primaryKeyValue = ((%s) object).%s()\", interfaceName, primaryKeyGetter)\n                        emitStatement(\"long objKey = Table.NO_MATCH\")\n                        beginControlFlow(\"if (primaryKeyValue == null)\")\n                            emitStatement(\"objKey = Table.nativeFindFirstNull(tableNativePtr, pkColumnKey)\")\n                        nextControlFlow(\"else\")\n                            emitStatement(\"objKey = Table.nativeFindFirstInt(tableNativePtr, pkColumnKey, ((%s) object).%s())\", interfaceName, primaryKeyGetter)\n                        endControlFlow()\n                    }\n                } else {\n                    emitStatement(\"long objKey = Table.NO_MATCH\")\n                    emitStatement(\"Object primaryKeyValue = ((%s) object).%s()\", interfaceName, primaryKeyGetter)\n                    beginControlFlow(\"if (primaryKeyValue != null)\")\n                        if (Utils.isString(metadata.primaryKey)) {\n                            emitStatement(\"objKey = Table.nativeFindFirstString(tableNativePtr, pkColumnKey, (String)primaryKeyValue)\")\n                        } else if (Utils.isObjectId(metadata.primaryKey)) {\n                            emitStatement(\"objKey = Table.nativeFindFirstObjectId(tableNativePtr, pkColumnKey, ((org.bson.types.ObjectId)primaryKeyValue).toString())\")\n                        } else if (Utils.isUUID(metadata.primaryKey)) {\n                            emitStatement(\"objKey = Table.nativeFindFirstUUID(tableNativePtr, pkColumnKey, ((java.util.UUID)primaryKeyValue).toString())\")\n                        } else {\n                            emitStatement(\"objKey = Table.nativeFindFirstInt(tableNativePtr, pkColumnKey, ((%s) object).%s())\", interfaceName, primaryKeyGetter)\n                        }\n                    endControlFlow()\n                }\n\n                beginControlFlow(\"if (objKey == Table.NO_MATCH)\")\n                    if (Utils.isString(metadata.primaryKey) || Utils.isObjectId(metadata.primaryKey) || Utils.isUUID(metadata.primaryKey)) {\n                        emitStatement(\"objKey = OsObject.createRowWithPrimaryKey(table, pkColumnKey, primaryKeyValue)\")\n                    } else {\n                        emitStatement(\"objKey = OsObject.createRowWithPrimaryKey(table, pkColumnKey, ((%s) object).%s())\", interfaceName, primaryKeyGetter)\n                    }\n\n                    if (throwIfPrimaryKeyDuplicate) {\n                        nextControlFlow(\"else\")\n                        emitStatement(\"Table.throwDuplicatePrimaryKeyException(primaryKeyValue)\")\n                    }\n                endControlFlow()\n                emitStatement(\"cache.put(object, objKey)\")\n            } else {\n                if (metadata.embedded) {\n                    emitStatement(\"long objKey = OsObject.createEmbeddedObject(parentObjectTable, parentObjectKey, parentColumnKey)\")\n                    emitStatement(\"cache.put(object, objKey)\")\n                } else {\n                    emitStatement(\"long objKey = OsObject.createRow(table)\")\n                    emitStatement(\"cache.put(object, objKey)\")\n                }\n            }\n        }\n    }\n\n    @Throws(IOException::class)\n    private fun emitCopyMethod(writer: JavaWriter) {\n        writer.apply {\n            beginMethod(qualifiedJavaClassName, \"copy\", EnumSet.of(Modifier.PUBLIC, Modifier.STATIC),\n                    \"Realm\", \"realm\",\n                    columnInfoClassName(), \"columnInfo\",\n                    qualifiedJavaClassName.toString(), \"newObject\",\n                    \"boolean\", \"update\",\n                    \"Map<RealmModel,RealmObjectProxy>\", \"cache\",\n                    \"Set<ImportFlag>\", \"flags\"\n            )\n                emitStatement(\"RealmObjectProxy cachedRealmObject = cache.get(newObject)\")\n                beginControlFlow(\"if (cachedRealmObject != null)\")\n                    emitStatement(\"return (%s) cachedRealmObject\", qualifiedJavaClassName)\n                endControlFlow()\n                emitEmptyLine()\n                emitStatement(\"%1\\$s unmanagedSource = (%1\\$s) newObject\", interfaceName)\n                emitEmptyLine()\n                emitStatement(\"Table table = realm.getTable(%s.class)\", qualifiedJavaClassName)\n                emitStatement(\"OsObjectBuilder builder = new OsObjectBuilder(table, flags)\")\n\n                // Copy basic types\n                emitEmptyLine()\n                emitSingleLineComment(\"Add all non-\\\"object reference\\\" fields\")\n                for (field in metadata.getBasicTypeFields()) {\n                    val fieldColKey = fieldColKeyVariableReference(field)\n                    val fieldName = field.simpleName.toString()\n                    val getter = metadata.getInternalGetter(fieldName)\n                    emitStatement(\"builder.%s(%s, unmanagedSource.%s())\", OsObjectBuilderTypeHelper.getOsObjectBuilderName(field), fieldColKey, getter)\n                }\n\n                // Create the underlying object\n                emitEmptyLine()\n                emitSingleLineComment(\"Create the underlying object and cache it before setting any object/objectlist references\")\n                emitSingleLineComment(\"This will allow us to break any circular dependencies by using the object cache.\")\n                emitStatement(\"Row row = builder.createNewObject()\")\n                emitStatement(\"%s managedCopy = newProxyInstance(realm, row)\", generatedClassName)\n                emitStatement(\"cache.put(newObject, managedCopy)\")\n\n                // Copy all object references or lists-of-objects\n                emitEmptyLine()\n                if (metadata.objectReferenceFields.isNotEmpty()) {\n                    emitSingleLineComment(\"Finally add all fields that reference other Realm Objects, either directly or through a list\")\n                }\n                for (field in metadata.objectReferenceFields) {\n                    val fieldType = QualifiedClassName(field.asType())\n                    val fieldName: String = field.simpleName.toString()\n                    val getter: String = metadata.getInternalGetter(fieldName)\n                    val setter: String = metadata.getInternalSetter(fieldName)\n                    val parentPropertyType: Constants.RealmFieldType = getRealmType(field)\n\n                    when {\n                        Utils.isRealmModel(field) -> {\n                            val isEmbedded = Utils.isFieldTypeEmbedded(field.asType(), classCollection)\n                            val fieldColKey: String = fieldColKeyVariableReference(field)\n                            val linkedQualifiedClassName: QualifiedClassName = Utils.getFieldTypeQualifiedName(field)\n                            val linkedProxyClass: SimpleClassName = Utils.getProxyClassSimpleName(field)\n\n                            emitStatement(\"%s %sObj = unmanagedSource.%s()\", fieldType, fieldName, getter)\n                            beginControlFlow(\"if (%sObj == null)\", fieldName)\n                                emitStatement(\"managedCopy.%s(null)\", setter)\n                            nextControlFlow(\"else\")\n                                emitStatement(\"%s cache%s = (%s) cache.get(%sObj)\", fieldType, fieldName, fieldType, fieldName)\n\n                                if (isEmbedded) {\n                                    beginControlFlow(\"if (cache%s != null)\", fieldName)\n                                        emitStatement(\"throw new IllegalArgumentException(\\\"Embedded objects can only have one parent pointing to them. This object was already copied, so another object is pointing to it: cache%s.toString()\\\")\", fieldName)\n                                    nextControlFlow(\"else\")\n                                        emitStatement(\"long objKey = ((RealmObjectProxy) managedCopy).realmGet\\$proxyState().getRow\\$realm().createEmbeddedObject(%s, RealmFieldType.%s)\", fieldColKey, parentPropertyType.name)\n                                        emitStatement(\"Row linkedObjectRow = realm.getTable(%s.class).getUncheckedRow(objKey)\", linkedQualifiedClassName)\n                                        emitStatement(\"%s linkedObject = %s.newProxyInstance(realm, linkedObjectRow)\", linkedQualifiedClassName, linkedProxyClass)\n                                        emitStatement(\"cache.put(%sObj, (RealmObjectProxy) linkedObject)\", fieldName)\n                                        emitStatement(\"%s.updateEmbeddedObject(realm, %sObj, linkedObject, cache, flags)\", linkedProxyClass, fieldName)\n                                   endControlFlow()\n                                } else {\n                                    beginControlFlow(\"if (cache%s != null)\", fieldName)\n                                        emitStatement(\"managedCopy.%s(cache%s)\", setter, fieldName)\n                                    nextControlFlow(\"else\")\n                                        emitStatement(\"managedCopy.%s(%s.copyOrUpdate(realm, (%s) realm.getSchema().getColumnInfo(%s.class), %sObj, update, cache, flags))\", setter, linkedProxyClass, columnInfoClassName(field), linkedQualifiedClassName, fieldName)\n                                    endControlFlow()\n                                }\n\n                            // No need to throw exception here if the field is not nullable. A exception will be thrown in setter.\n                            endControlFlow()\n                            emitEmptyLine()\n                        }\n                        Utils.isRealmModelList(field) -> {\n                            val listElementType: TypeMirror = Utils.getGenericType(field)!!\n                            val genericType: QualifiedClassName = Utils.getGenericTypeQualifiedName(field)!!\n                            val linkedProxyClass: SimpleClassName = Utils.getProxyClassSimpleName(field)\n                            val isEmbedded = Utils.isFieldTypeEmbedded(listElementType, classCollection)\n\n                            emitStatement(\"RealmList<%s> %sUnmanagedList = unmanagedSource.%s()\", genericType, fieldName, getter)\n                            beginControlFlow(\"if (%sUnmanagedList != null)\", fieldName)\n                                emitStatement(\"RealmList<%s> %sManagedList = managedCopy.%s()\", genericType, fieldName, getter)\n                                // Clear is needed. See bug https://github.com/realm/realm-java/issues/4957\n                                emitStatement(\"%sManagedList.clear()\", fieldName)\n                                beginControlFlow(\"for (int i = 0; i < %sUnmanagedList.size(); i++)\", fieldName)\n                                    emitStatement(\"%1\\$s %2\\$sUnmanagedItem = %2\\$sUnmanagedList.get(i)\", genericType, fieldName)\n                                    emitStatement(\"%1\\$s cache%2\\$s = (%1\\$s) cache.get(%2\\$sUnmanagedItem)\", genericType, fieldName)\n\n                                    if (isEmbedded) {\n                                        beginControlFlow(\"if (cache%s != null)\", fieldName)\n                                            emitStatement(\"throw new IllegalArgumentException(\\\"Embedded objects can only have one parent pointing to them. This object was already copied, so another object is pointing to it: cache%s.toString()\\\")\", fieldName)\n                                        nextControlFlow(\"else\")\n                                            emitStatement(\"long objKey = %sManagedList.getOsList().createAndAddEmbeddedObject()\", fieldName)\n                                            emitStatement(\"Row linkedObjectRow = realm.getTable(%s.class).getUncheckedRow(objKey)\", genericType)\n                                            emitStatement(\"%s linkedObject = %s.newProxyInstance(realm, linkedObjectRow)\", genericType, linkedProxyClass)\n                                            emitStatement(\"cache.put(%sUnmanagedItem, (RealmObjectProxy) linkedObject)\", fieldName)\n                                            emitStatement(\"%s.updateEmbeddedObject(realm, %sUnmanagedItem, linkedObject, new HashMap<RealmModel, RealmObjectProxy>(), Collections.EMPTY_SET)\", linkedProxyClass, fieldName)\n                                        endControlFlow()\n\n                                    } else {\n                                        beginControlFlow(\"if (cache%s != null)\", fieldName)\n                                            emitStatement(\"%1\\$sManagedList.add(cache%1\\$s)\", fieldName)\n                                        nextControlFlow(\"else\")\n                                            emitStatement(\"%1\\$sManagedList.add(%2\\$s.copyOrUpdate(realm, (%3\\$s) realm.getSchema().getColumnInfo(%4\\$s.class), %1\\$sUnmanagedItem, update, cache, flags))\", fieldName, Utils.getProxyClassSimpleName(field), columnInfoClassName(field), Utils.getGenericTypeQualifiedName(field))\n                                        endControlFlow()\n                                    }\n\n                                endControlFlow()\n                            endControlFlow()\n                            emitEmptyLine()\n                        }\n                        Utils.isRealmAny(field) -> {\n                            emitStatement(\"RealmAny ${fieldName}RealmAny = unmanagedSource.${getter}()\")\n                            emitStatement(\"${fieldName}RealmAny = ProxyUtils.copyOrUpdate(${fieldName}RealmAny, realm, update, cache, flags)\")\n                            emitStatement(\"managedCopy.${setter}(${fieldName}RealmAny)\")\n                            emitEmptyLine()\n                        }\n                        Utils.isRealmAnyList(field) -> {\n                            emitStatement(\"RealmList<RealmAny> ${fieldName}UnmanagedList = unmanagedSource.${getter}()\")\n                            beginControlFlow(\"if (${fieldName}UnmanagedList != null)\")\n                                emitStatement(\"RealmList<RealmAny> ${fieldName}ManagedList = managedCopy.${getter}()\")\n                                emitStatement(\"${fieldName}ManagedList.clear()\")\n\n                                beginControlFlow(\"for (int i = 0; i < ${fieldName}UnmanagedList.size(); i++)\")\n                                    emitStatement(\"RealmAny realmAnyItem = ${fieldName}UnmanagedList.get(i)\")\n                                    emitStatement(\"realmAnyItem = ProxyUtils.copyOrUpdate(realmAnyItem, realm, update, cache, flags)\")\n                                    emitStatement(\"${fieldName}ManagedList.add(realmAnyItem)\")\n                                endControlFlow()\n                            endControlFlow()\n                            emitEmptyLine()\n                        }\n                        Utils.isRealmAnyDictionary(field) -> {\n                            val genericType = Utils.getGenericTypeQualifiedName(field)\n                            emitStatement(\"RealmDictionary<RealmAny> ${fieldName}UnmanagedDictionary = unmanagedSource.${getter}()\")\n                            beginControlFlow(\"if (${fieldName}UnmanagedDictionary != null)\")\n                                emitStatement(\"RealmDictionary<RealmAny> ${fieldName}ManagedDictionary = managedCopy.${getter}()\")\n                                emitStatement(\"java.util.Set<java.util.Map.Entry<String, ${genericType}>> entries = ${fieldName}UnmanagedDictionary.entrySet()\")\n                                emitStatement(\"java.util.List<String> keys = new java.util.ArrayList<>()\")\n                                emitStatement(\"java.util.List<Long> realmAnyPointers = new java.util.ArrayList<>()\")\n                                beginControlFlow(\"for (java.util.Map.Entry<String, ${genericType}> entry : entries)\")\n                                    emitStatement(\"RealmAny realmAnyItem = entry.getValue()\")\n                                    emitStatement(\"realmAnyItem = ProxyUtils.copyOrUpdate(realmAnyItem, realm, update, cache, flags)\")\n                                    emitStatement(\"${fieldName}ManagedDictionary.put(entry.getKey(), realmAnyItem)\")\n                                endControlFlow()\n                            endControlFlow()\n                            emitEmptyLine()\n                        }\n                        Utils.isRealmDictionary(field) -> {\n                            val genericType: QualifiedClassName = Utils.getGenericTypeQualifiedName(field)!!\n                            val listElementType: TypeMirror = Utils.getGenericType(field)!!\n                            val isEmbedded = Utils.isFieldTypeEmbedded(listElementType, classCollection)\n                            val linkedProxyClass: SimpleClassName = Utils.getDictionaryGenericProxyClassSimpleName(field)\n\n                            emitStatement(\"RealmDictionary<${genericType}> ${fieldName}UnmanagedDictionary = unmanagedSource.${getter}()\")\n                            beginControlFlow(\"if (${fieldName}UnmanagedDictionary != null)\")\n                                emitStatement(\"RealmDictionary<${genericType}> ${fieldName}ManagedDictionary = managedCopy.${getter}()\")\n                                // Mimicking lists, maybe not needed...?\n                                emitStatement(\"${fieldName}ManagedDictionary.clear()\")\n                                emitStatement(\"java.util.Set<java.util.Map.Entry<String, ${genericType}>> entries = ${fieldName}UnmanagedDictionary.entrySet()\")\n                                beginControlFlow(\"for (java.util.Map.Entry<String, ${genericType}> entry : entries)\")\n                                    emitStatement(\"String entryKey = entry.getKey()\")\n                                    emitStatement(\"$genericType ${fieldName}UnmanagedEntryValue = entry.getValue()\")\n                                    emitStatement(\"$genericType cache${fieldName} = (${genericType}) cache.get(${fieldName}UnmanagedEntryValue)\")\n\n                                    if (isEmbedded) {\n                                        beginControlFlow(\"if (cache${fieldName} != null)\")\n                                            emitStatement(\"\"\"throw new IllegalArgumentException(\"Embedded objects can only have one parent pointing to them. This object was already copied, so another object is pointing to it: cache${fieldName}.toString()\")\"\"\")\n                                        nextControlFlow(\"else\")\n                                            emitStatement(\"long objKey = ${fieldName}ManagedDictionary.getOsMap().createAndPutEmbeddedObject(entryKey)\")\n                                            emitStatement(\"Row linkedObjectRow = realm.getTable(${genericType}.class).getUncheckedRow(objKey)\")\n                                            emitStatement(\"$genericType linkedObject = ${linkedProxyClass}.newProxyInstance(realm, linkedObjectRow)\")\n                                            emitStatement(\"cache.put(${fieldName}UnmanagedEntryValue, (RealmObjectProxy) linkedObject)\")\n                                            emitStatement(\"${linkedProxyClass}.updateEmbeddedObject(realm, ${fieldName}UnmanagedEntryValue, linkedObject, new HashMap<RealmModel, RealmObjectProxy>(), Collections.EMPTY_SET)\")\n                                        endControlFlow()\n                                    } else {\n                                        beginControlFlow(\"if (cache${fieldName} != null)\")\n                                            emitStatement(\"${fieldName}ManagedDictionary.put(entryKey, cache${fieldName})\")\n                                        nextControlFlow(\"else\")\n                                            beginControlFlow(\"if (${fieldName}UnmanagedEntryValue == null)\")\n                                                emitStatement(\"${fieldName}ManagedDictionary.put(entryKey, null)\")\n                                            nextControlFlow(\"else\")\n                                                emitStatement(\n                                                        \"%sManagedDictionary.put(entryKey, %s.copyOrUpdate(realm, (%s) realm.getSchema().getColumnInfo(%s.class), %sUnmanagedEntryValue, update, cache, flags))\",\n                                                        fieldName,\n                                                        Utils.getDictionaryGenericProxyClassSimpleName(field),\n                                                        columnInfoClassNameDictionaryGeneric(field),\n                                                        Utils.getGenericTypeQualifiedName(field),\n                                                        fieldName\n                                                )\n                                            endControlFlow()\n                                        endControlFlow()\n                                    }\n                                endControlFlow()\n                            endControlFlow()\n                        }\n                        Utils.isRealmAnySet(field) -> {\n                            emitStatement(\"RealmSet<RealmAny> ${fieldName}UnmanagedSet = unmanagedSource.${getter}()\")\n                            beginControlFlow(\"if (${fieldName}UnmanagedSet != null)\")\n                                emitStatement(\"RealmSet<RealmAny> ${fieldName}ManagedSet = managedCopy.${getter}()\")\n                                emitStatement(\"${fieldName}ManagedSet.clear()\")\n\n                                beginControlFlow(\"for (RealmAny realmAnyItem: ${fieldName}UnmanagedSet)\")\n                                    emitStatement(\"realmAnyItem = ProxyUtils.copyOrUpdate(realmAnyItem, realm, update, cache, flags)\")\n                                    emitStatement(\"${fieldName}ManagedSet.add(realmAnyItem)\")\n                                endControlFlow()\n                            endControlFlow()\n                            emitEmptyLine()\n                        }\n                        Utils.isRealmModelSet(field) -> {\n                            val genericType: QualifiedClassName = Utils.getGenericTypeQualifiedName(field)!!\n                            val linkedProxyClass: SimpleClassName = Utils.getSetGenericProxyClassSimpleName(field)\n\n                            emitStatement(\"RealmSet<${genericType}> ${fieldName}UnmanagedSet = unmanagedSource.${getter}()\")\n                            beginControlFlow(\"if (${fieldName}UnmanagedSet != null)\")\n                                emitStatement(\"RealmSet<${genericType}> ${fieldName}ManagedSet = managedCopy.${getter}()\")\n                                // Clear is needed. See bug https://github.com/realm/realm-java/issues/4957\n                                emitStatement(\"${fieldName}ManagedSet.clear()\")\n                                beginControlFlow(\"for ($genericType ${fieldName}UnmanagedItem: ${fieldName}UnmanagedSet)\")\n                                    emitStatement(\"$genericType cache${fieldName} = (${genericType}) cache.get(${fieldName}UnmanagedItem)\")\n\n                                    beginControlFlow(\"if (cache${fieldName} != null)\")\n                                        emitStatement(\"${fieldName}ManagedSet.add(cache${fieldName})\")\n                                    nextControlFlow(\"else\")\n                                        emitStatement(\"${fieldName}ManagedSet.add(${linkedProxyClass}.copyOrUpdate(realm, (${columnInfoClassNameSetGeneric(field)}) realm.getSchema().getColumnInfo(${Utils.getGenericTypeQualifiedName(field)}.class), ${fieldName}UnmanagedItem, update, cache, flags))\")\n                                    endControlFlow()\n\n                                endControlFlow()\n                            endControlFlow()\n                            emitEmptyLine()\n                        }\n                        else -> {\n                            throw IllegalStateException(\"Unsupported field: $field\")\n                        }\n                    }\n                }\n                emitStatement(\"return managedCopy\")\n            endMethod()\n            emitEmptyLine()\n        }\n    }\n\n    @Throws(IOException::class)\n    private fun emitCreateDetachedCopyMethod(writer: JavaWriter) {\n        writer.apply {\n            beginMethod(qualifiedJavaClassName, \"createDetachedCopy\", EnumSet.of(Modifier.PUBLIC, Modifier.STATIC), qualifiedJavaClassName.toString(), \"realmObject\", \"int\", \"currentDepth\", \"int\", \"maxDepth\", \"Map<RealmModel, CacheData<RealmModel>>\", \"cache\")\n                beginControlFlow(\"if (currentDepth > maxDepth || realmObject == null)\")\n                    emitStatement(\"return null\")\n                endControlFlow()\n                emitStatement(\"CacheData<RealmModel> cachedObject = cache.get(realmObject)\")\n                emitStatement(\"%s unmanagedObject\", qualifiedJavaClassName)\n                beginControlFlow(\"if (cachedObject == null)\")\n                    emitStatement(\"unmanagedObject = new %s()\", qualifiedJavaClassName)\n                    emitStatement(\"cache.put(realmObject, new RealmObjectProxy.CacheData<RealmModel>(currentDepth, unmanagedObject))\")\n                nextControlFlow(\"else\")\n                    emitSingleLineComment(\"Reuse cached object or recreate it because it was encountered at a lower depth.\")\n                    beginControlFlow(\"if (currentDepth >= cachedObject.minDepth)\")\n                        emitStatement(\"return (%s) cachedObject.object\", qualifiedJavaClassName)\n                    endControlFlow()\n                    emitStatement(\"unmanagedObject = (%s) cachedObject.object\", qualifiedJavaClassName)\n                    emitStatement(\"cachedObject.minDepth = currentDepth\")\n                endControlFlow()\n\n                // may cause an unused variable warning if the object contains only null lists\n                emitStatement(\"%1\\$s unmanagedCopy = (%1\\$s) unmanagedObject\", interfaceName)\n                emitStatement(\"%1\\$s realmSource = (%1\\$s) realmObject\", interfaceName)\n                emitStatement(\"Realm objectRealm = (Realm) ((RealmObjectProxy) realmObject).realmGet\\$proxyState().getRealm\\$realm()\")\n\n                for (field in metadata.fields) {\n                    val fieldName = field.simpleName.toString()\n                    val setter = metadata.getInternalSetter(fieldName)\n                    val getter = metadata.getInternalGetter(fieldName)\n                    when {\n                        Utils.isRealmModel(field) -> {\n                            emitEmptyLine()\n                            emitSingleLineComment(\"Deep copy of %s\", fieldName)\n                            emitStatement(\"unmanagedCopy.%s(%s.createDetachedCopy(realmSource.%s(), currentDepth + 1, maxDepth, cache))\", setter, Utils.getProxyClassSimpleName(field), getter)\n                        }\n                        Utils.isRealmModelList(field) -> {\n                            emitEmptyLine()\n                            emitSingleLineComment(\"Deep copy of %s\", fieldName)\n                            beginControlFlow(\"if (currentDepth == maxDepth)\")\n                                emitStatement(\"unmanagedCopy.%s(null)\", setter)\n                            nextControlFlow(\"else\")\n                                emitStatement(\"RealmList<%s> managed%sList = realmSource.%s()\", Utils.getGenericTypeQualifiedName(field), fieldName, getter)\n                                emitStatement(\"RealmList<%1\\$s> unmanaged%2\\$sList = new RealmList<%1\\$s>()\", Utils.getGenericTypeQualifiedName(field), fieldName)\n                                emitStatement(\"unmanagedCopy.%s(unmanaged%sList)\", setter, fieldName)\n                                emitStatement(\"int nextDepth = currentDepth + 1\")\n                                emitStatement(\"int size = managed%sList.size()\", fieldName)\n                                beginControlFlow(\"for (int i = 0; i < size; i++)\")\n                                    emitStatement(\"%s item = %s.createDetachedCopy(managed%sList.get(i), nextDepth, maxDepth, cache)\", Utils.getGenericTypeQualifiedName(field), Utils.getProxyClassSimpleName(field), fieldName)\n                                    emitStatement(\"unmanaged%sList.add(item)\", fieldName)\n                                endControlFlow()\n                            endControlFlow()\n                        }\n                        Utils.isRealmValueList(field) -> {\n                            emitEmptyLine()\n                            emitStatement(\"unmanagedCopy.%1\\$s(new RealmList<%2\\$s>())\", setter, Utils.getGenericTypeQualifiedName(field))\n                            emitStatement(\"unmanagedCopy.%1\\$s().addAll(realmSource.%1\\$s())\", getter)\n                        }\n                        Utils.isMutableRealmInteger(field) -> // If the user initializes the unmanaged MutableRealmInteger to null, this will fail mysteriously.\n                            emitStatement(\"unmanagedCopy.%s().set(realmSource.%s().get())\", getter, getter)\n                        Utils.isRealmAny(field) -> {\n                            emitEmptyLine()\n                            emitSingleLineComment(\"Deep copy of %s\", fieldName)\n                            emitStatement(\"unmanagedCopy.${setter}(ProxyUtils.createDetachedCopy(realmSource.${getter}(), objectRealm, currentDepth + 1, maxDepth, cache))\")\n                        }\n                        Utils.isRealmAnyList(field) -> {\n                            emitEmptyLine()\n                            emitSingleLineComment(\"Deep copy of %s\", fieldName)\n                            beginControlFlow(\"if (currentDepth == maxDepth)\")\n                                emitStatement(\"unmanagedCopy.%s(null)\", setter)\n                            nextControlFlow(\"else\")\n                                emitStatement(\"RealmList<RealmAny> managed${fieldName}List = realmSource.${getter}()\", fieldName, getter)\n                                emitStatement(\"RealmList<RealmAny> unmanaged${fieldName}List = new RealmList<RealmAny>()\")\n                                emitStatement(\"unmanagedCopy.${setter}(unmanaged${fieldName}List)\")\n                                emitStatement(\"int nextDepth = currentDepth + 1\")\n                                emitStatement(\"int size = managed${fieldName}List.size()\")\n                                beginControlFlow(\"for (int i = 0; i < size; i++)\")\n                                    emitStatement(\"RealmAny item = ProxyUtils.createDetachedCopy(managed${fieldName}List.get(i), objectRealm, nextDepth, maxDepth, cache)\")\n                                    emitStatement(\"unmanaged${fieldName}List.add(item)\")\n                                endControlFlow()\n                            endControlFlow()\n                        }\n                        Utils.isRealmModelDictionary(field) -> {\n                            val proxyClassSimpleName = Utils.getDictionaryGenericProxyClassSimpleName(field)\n                            val genericType = requireNotNull(Utils.getGenericTypeQualifiedName(field))\n\n                            emitEmptyLine()\n                            emitSingleLineComment(\"Deep copy of $fieldName\")\n                            beginControlFlow(\"if (currentDepth == maxDepth)\")\n                                emitStatement(\"unmanagedCopy.${setter}(null)\")\n                            nextControlFlow(\"else\")\n                                emitStatement(\"RealmDictionary<${genericType}> managed${fieldName}Dictionary = realmSource.${getter}()\")\n                                emitStatement(\"RealmDictionary<${genericType}> unmanaged${fieldName}Dictionary = new RealmDictionary<${genericType}>()\")\n                                emitStatement(\"unmanagedCopy.${setter}(unmanaged${fieldName}Dictionary)\")\n                                emitStatement(\"int nextDepth = currentDepth + 1\")\n                                beginControlFlow(\"for (Map.Entry<String, ${genericType}> entry : managed${fieldName}Dictionary.entrySet())\")\n                                    emitStatement(\"$genericType detachedValue = ${proxyClassSimpleName}.createDetachedCopy(entry.getValue(), nextDepth, maxDepth, cache)\")\n                                    emitStatement(\"unmanaged${fieldName}Dictionary.put(entry.getKey(), detachedValue)\")\n                                endControlFlow()\n                            endControlFlow()\n                        }\n                        Utils.isRealmValueDictionary(field) -> {\n                            val genericType = requireNotNull(Utils.getGenericTypeQualifiedName(field))\n\n                            emitEmptyLine()\n                            emitStatement(\"unmanagedCopy.%1\\$s(new RealmDictionary<%2\\$s>())\", setter, Utils.getDictionaryValueTypeQualifiedName(field))\n                            emitStatement(\"RealmDictionary<${genericType}> managed${fieldName}Dictionary = realmSource.${getter}()\")\n                            beginControlFlow(\"for (Map.Entry<String, ${genericType}> entry : managed${fieldName}Dictionary.entrySet())\")\n                                emitStatement(\"unmanagedCopy.${getter}().put(entry.getKey(), entry.getValue())\")\n                            endControlFlow()\n                        }\n                        Utils.isRealmAnyDictionary(field) -> {\n                            emitEmptyLine()\n                            emitSingleLineComment(\"Deep copy of %s\", fieldName)\n                            beginControlFlow(\"if (currentDepth == maxDepth)\")\n                                emitStatement(\"unmanagedCopy.%s(null)\", setter)\n                            nextControlFlow(\"else\")\n                                emitStatement(\"RealmDictionary<RealmAny> managed${fieldName}Dictionary = realmSource.${getter}()\")\n                                emitStatement(\"RealmDictionary<RealmAny> unmanaged${fieldName}Dictionary = new RealmDictionary<RealmAny>()\")\n                                emitStatement(\"unmanagedCopy.${setter}(unmanaged${fieldName}Dictionary)\")\n                                emitStatement(\"int nextDepth = currentDepth + 1\")\n                            beginControlFlow(\"for (Map.Entry<String, RealmAny> entry : managed${fieldName}Dictionary.entrySet())\")\n                                emitStatement(\"RealmAny detachedValue = ProxyUtils.createDetachedCopy(entry.getValue(), objectRealm, nextDepth, maxDepth, cache)\")\n                                emitStatement(\"unmanaged${fieldName}Dictionary.put(entry.getKey(), detachedValue)\")\n                                endControlFlow()\n                            endControlFlow()\n                        }\n                        Utils.isRealmValueDictionary(field) -> {\n                            val genericType = requireNotNull(Utils.getGenericTypeQualifiedName(field))\n\n                            emitEmptyLine()\n                            emitStatement(\"unmanagedCopy.%1\\$s(new RealmSet<%2\\$s>())\", setter, Utils.getSetValueTypeQualifiedName(field))\n                            emitStatement(\"RealmSet<${genericType}> managed${fieldName}Set = realmSource.${getter}()\")\n                            beginControlFlow(\"for (${genericType} value : managed${fieldName}Set)\")\n                                emitStatement(\"unmanagedCopy.${getter}().add(value)\")\n                            endControlFlow()\n                        }\n                        else -> {\n                            emitStatement(\"unmanagedCopy.%s(realmSource.%s())\", setter, getter)\n                        }\n                    }\n                }\n                emitEmptyLine()\n                emitStatement(\"return unmanagedObject\")\n            endMethod()\n            emitEmptyLine()\n        }\n    }\n\n    @Throws(IOException::class)\n    private fun emitUpdateMethod(writer: JavaWriter) {\n        if (!metadata.hasPrimaryKey() && !metadata.embedded) {\n            return\n        }\n        writer.apply {\n            beginMethod(qualifiedJavaClassName, \"update\", EnumSet.of(Modifier.STATIC),\n                    \"Realm\", \"realm\", // Argument type & argument name\n                    columnInfoClassName(), \"columnInfo\",\n                    qualifiedJavaClassName.toString(), \"realmObject\",\n                    qualifiedJavaClassName.toString(), \"newObject\",\n                    \"Map<RealmModel, RealmObjectProxy>\", \"cache\",\n                    \"Set<ImportFlag>\", \"flags\"\n            )\n                emitStatement(\"%1\\$s realmObjectTarget = (%1\\$s) realmObject\", interfaceName)\n                emitStatement(\"%1\\$s realmObjectSource = (%1\\$s) newObject\", interfaceName)\n                emitStatement(\"Table table = realm.getTable(%s.class)\", qualifiedJavaClassName)\n                emitStatement(\"OsObjectBuilder builder = new OsObjectBuilder(table, flags)\")\n                for (field in metadata.fields) {\n                    val fieldType = QualifiedClassName(field.asType())\n                    val fieldName = field.simpleName.toString()\n                    val getter = metadata.getInternalGetter(fieldName)\n                    val fieldColKey = fieldColKeyVariableReference(field)\n                    val parentPropertyType: Constants.RealmFieldType = getRealmType(field)\n\n                    when {\n                        Utils.isRealmModel(field) -> {\n                            emitEmptyLine()\n                            emitStatement(\"%s %sObj = realmObjectSource.%s()\", fieldType, fieldName, getter)\n                            beginControlFlow(\"if (%sObj == null)\", fieldName)\n                                emitStatement(\"builder.addNull(%s)\", fieldColKeyVariableReference(field))\n                            nextControlFlow(\"else\")\n\n                            val isEmbedded = Utils.isFieldTypeEmbedded(field.asType(), classCollection)\n                            if (isEmbedded) {\n                                // Embedded objects are created in-place as we need to know the\n                                // parent object + the property containing it.\n                                // After this we know that changing values will always be considered\n                                // an \"update\n                                emitSingleLineComment(\"Embedded objects are created directly instead of using the builder.\")\n                                emitStatement(\"%s cache%s = (%s) cache.get(%sObj)\", fieldType, fieldName, fieldType, fieldName)\n                                beginControlFlow(\"if (cache%s != null)\", fieldName)\n                                    emitStatement(\"throw new IllegalArgumentException(\\\"Embedded objects can only have one parent pointing to them. This object was already copied, so another object is pointing to it: cache%s.toString()\\\")\", fieldName)\n                                endControlFlow()\n                                emitEmptyLine()\n                                emitStatement(\"long objKey = ((RealmObjectProxy) realmObject).realmGet\\$proxyState().getRow\\$realm().createEmbeddedObject(%s, RealmFieldType.%s)\", fieldColKey, parentPropertyType.name)\n                                emitStatement(\"Row row = realm.getTable(%s.class).getUncheckedRow(objKey)\", Utils.getFieldTypeQualifiedName(field))\n                                emitStatement(\"%s proxyObject = %s.newProxyInstance(realm, row)\", fieldType, Utils.getProxyClassSimpleName(field))\n                                emitStatement(\"cache.put(%sObj, (RealmObjectProxy) proxyObject)\", fieldName)\n                                emitStatement(\"%s.updateEmbeddedObject(realm, %sObj, proxyObject, cache, flags)\", Utils.getProxyClassSimpleName(field), fieldName)\n                            } else {\n                                // Non-embedded classes are updating using normal recursive bottom-up approach\n                                emitStatement(\"%s cache%s = (%s) cache.get(%sObj)\", fieldType, fieldName, fieldType, fieldName)\n                                beginControlFlow(\"if (cache%s != null)\", fieldName)\n                                    emitStatement(\"builder.addObject(%s, cache%s)\", fieldColKey, fieldName)\n                                nextControlFlow(\"else\")\n                                    emitStatement(\"builder.addObject(%s, %s.copyOrUpdate(realm, (%s) realm.getSchema().getColumnInfo(%s.class), %sObj, true, cache, flags))\", fieldColKey, Utils.getProxyClassSimpleName(field), columnInfoClassName(field), Utils.getFieldTypeQualifiedName(field), fieldName)\n                                endControlFlow()\n                            }\n\n                            // No need to throw exception here if the field is not nullable. A exception will be thrown in setter.\n                            endControlFlow()\n                        }\n                        Utils.isRealmModelList(field) -> {\n                            val genericType: QualifiedClassName = Utils.getRealmListType(field)!!\n                            val fieldTypeMetaData: TypeMirror = Utils.getGenericType(field)!!\n\n                            val isEmbedded = Utils.isFieldTypeEmbedded(fieldTypeMetaData, classCollection)\n                            val proxyClass: SimpleClassName = Utils.getProxyClassSimpleName(field)\n\n                            emitEmptyLine()\n                            emitStatement(\"RealmList<%s> %sUnmanagedList = realmObjectSource.%s()\", genericType, fieldName, getter)\n                            beginControlFlow(\"if (%sUnmanagedList != null)\", fieldName)\n                                emitStatement(\"RealmList<%s> %sManagedCopy = new RealmList<%s>()\", genericType, fieldName, genericType)\n\n                                if (isEmbedded) {\n                                    emitStatement(\"OsList targetList = realmObjectTarget.realmGet\\$%s().getOsList()\", fieldName)\n                                    emitStatement(\"targetList.deleteAll()\")\n                                    beginControlFlow(\"for (int i = 0; i < %sUnmanagedList.size(); i++)\", fieldName)\n                                        emitStatement(\"%1\\$s %2\\$sUnmanagedItem = %2\\$sUnmanagedList.get(i)\", genericType, fieldName)\n                                        emitStatement(\"%1\\$s cache%2\\$s = (%1\\$s) cache.get(%2\\$sUnmanagedItem)\", genericType, fieldName)\n                                        beginControlFlow(\"if (cache%s != null)\", fieldName)\n                                            emitStatement(\"throw new IllegalArgumentException(\\\"Embedded objects can only have one parent pointing to them. This object was already copied, so another object is pointing to it: cache%s.toString()\\\")\", fieldName)\n                                        nextControlFlow(\"else\")\n                                            emitStatement(\"long objKey = targetList.createAndAddEmbeddedObject()\")\n                                            emitStatement(\"Row row = realm.getTable(%s.class).getUncheckedRow(objKey)\", genericType)\n                                            emitStatement(\"%s proxyObject = %s.newProxyInstance(realm, row)\", genericType, proxyClass)\n                                            emitStatement(\"cache.put(%sUnmanagedItem, (RealmObjectProxy) proxyObject)\", fieldName)\n                                            emitStatement(\"%sManagedCopy.add(proxyObject)\", fieldName)\n                                            emitStatement(\"%s.updateEmbeddedObject(realm, %sUnmanagedItem, proxyObject, new HashMap<RealmModel, RealmObjectProxy>(), Collections.EMPTY_SET)\", Utils.getProxyClassSimpleName(field), fieldName)\n                                        endControlFlow()\n                                    endControlFlow()\n                                } else {\n                                    beginControlFlow(\"for (int i = 0; i < %sUnmanagedList.size(); i++)\", fieldName)\n                                        emitStatement(\"%1\\$s %2\\$sItem = %2\\$sUnmanagedList.get(i)\", genericType, fieldName)\n                                        emitStatement(\"%1\\$s cache%2\\$s = (%1\\$s) cache.get(%2\\$sItem)\", genericType, fieldName)\n                                        beginControlFlow(\"if (cache%s != null)\", fieldName)\n                                            emitStatement(\"%1\\$sManagedCopy.add(cache%1\\$s)\", fieldName)\n                                        nextControlFlow(\"else\")\n                                            emitStatement(\"%1\\$sManagedCopy.add(%2\\$s.copyOrUpdate(realm, (%3\\$s) realm.getSchema().getColumnInfo(%4\\$s.class), %1\\$sItem, true, cache, flags))\", fieldName, proxyClass, columnInfoClassName(field), genericType)\n                                        endControlFlow()\n                                    endControlFlow()\n                                    emitStatement(\"builder.addObjectList(%s, %sManagedCopy)\", fieldColKey, fieldName)\n                                }\n\n                            nextControlFlow(\"else\")\n                                emitStatement(\"builder.addObjectList(%s, new RealmList<%s>())\", fieldColKey, genericType)\n                            endControlFlow()\n                        }\n                        Utils.isRealmAny(field) -> {\n                            emitEmptyLine()\n\n                            emitStatement(\"RealmAny ${fieldName}RealmAny = realmObjectSource.${getter}()\")\n                            emitStatement(\"${fieldName}RealmAny = ProxyUtils.copyOrUpdate(${fieldName}RealmAny, realm, true, cache, flags)\")\n                            emitStatement(\"builder.addRealmAny(${fieldColKey}, ${fieldName}RealmAny.getNativePtr())\")\n                        }\n                        Utils.isRealmAnyList(field) -> {\n                            emitEmptyLine()\n\n                            emitStatement(\"RealmList<RealmAny> ${fieldName}UnmanagedList = realmObjectSource.${getter}()\")\n                            beginControlFlow(\"if (${fieldName}UnmanagedList != null)\")\n                                emitStatement(\"RealmList<RealmAny> ${fieldName}ManagedCopy = new RealmList<RealmAny>()\")\n                                beginControlFlow(\"for (int i = 0; i < ${fieldName}UnmanagedList.size(); i++)\")\n                                    emitStatement(\"RealmAny realmAnyItem = ${fieldName}UnmanagedList.get(i)\")\n                                    emitStatement(\"realmAnyItem = ProxyUtils.copyOrUpdate(realmAnyItem, realm, true, cache, flags)\")\n                                    emitStatement(\"${fieldName}ManagedCopy.add(realmAnyItem)\")\n                                endControlFlow()\n\n                                emitStatement(\"builder.addRealmAnyList(${fieldColKey}, ${fieldName}ManagedCopy)\")\n                            nextControlFlow(\"else\")\n                                emitStatement(\"builder.addRealmAnyList(${fieldColKey}, new RealmList<RealmAny>())\")\n                            endControlFlow()\n                        }\n                        Utils.isRealmAnyDictionary(field) -> {\n                            emitEmptyLine()\n\n                            val genericType = Utils.getGenericTypeQualifiedName(field)\n                            emitStatement(\"RealmDictionary<RealmAny> ${fieldName}UnmanagedDictionary = realmObjectSource.${getter}()\")\n                            beginControlFlow(\"if (${fieldName}UnmanagedDictionary != null)\")\n                                emitStatement(\"RealmDictionary<RealmAny> ${fieldName}ManagedDictionary = new RealmDictionary<>()\")\n                                emitStatement(\"java.util.Set<java.util.Map.Entry<String, ${genericType}>> entries = ${fieldName}UnmanagedDictionary.entrySet()\")\n                                emitStatement(\"java.util.List<String> keys = new java.util.ArrayList<>()\")\n                                emitStatement(\"java.util.List<Long> realmAnyPointers = new java.util.ArrayList<>()\")\n                                beginControlFlow(\"for (java.util.Map.Entry<String, ${genericType}> entry : entries)\")\n                                    emitStatement(\"RealmAny realmAnyItem = entry.getValue()\")\n                                    emitStatement(\"realmAnyItem = ProxyUtils.copyOrUpdate(realmAnyItem, realm, true, cache, flags)\")\n                                    emitStatement(\"${fieldName}ManagedDictionary.put(entry.getKey(), realmAnyItem)\")\n                                endControlFlow()\n                                emitStatement(\"builder.addRealmAnyValueDictionary(${fieldColKey}, ${fieldName}ManagedDictionary)\")\n                            nextControlFlow(\"else\")\n                                emitStatement(\"builder.addRealmAnyValueDictionary(${fieldColKey}, null)\")\n                            endControlFlow()\n                            emitEmptyLine()\n                        }\n                        Utils.isRealmModelDictionary(field) -> {\n                            emitEmptyLine()\n\n                            val genericType: QualifiedClassName = Utils.getGenericTypeQualifiedName(field)!!\n                            val listElementType: TypeMirror = Utils.getGenericType(field)!!\n                            val isEmbedded = Utils.isFieldTypeEmbedded(listElementType, classCollection)\n                            val linkedProxyClass: SimpleClassName = Utils.getDictionaryGenericProxyClassSimpleName(field)\n\n                            emitStatement(\"RealmDictionary<${genericType}> ${fieldName}UnmanagedDictionary = realmObjectSource.${getter}()\")\n                            beginControlFlow(\"if (${fieldName}UnmanagedDictionary != null)\")\n                                emitStatement(\"RealmDictionary<${genericType}> ${fieldName}ManagedDictionary = new RealmDictionary<>()\")\n                                emitStatement(\"java.util.Set<java.util.Map.Entry<String, ${genericType}>> entries = ${fieldName}UnmanagedDictionary.entrySet()\")\n                                beginControlFlow(\"for (java.util.Map.Entry<String, ${genericType}> entry : entries)\")\n                                    emitStatement(\"String entryKey = entry.getKey()\")\n                                    emitStatement(\"$genericType ${fieldName}UnmanagedEntryValue = entry.getValue()\")\n                                    emitStatement(\"$genericType cache${fieldName} = (${genericType}) cache.get(${fieldName}UnmanagedEntryValue)\")\n\n                                    if (isEmbedded) {\n                                        beginControlFlow(\"if (cache${fieldName} != null)\")\n                                            emitStatement(\"\"\"throw new IllegalArgumentException(\"Embedded objects can only have one parent pointing to them. This object was already copied, so another object is pointing to it: cache${fieldName}.toString()\")\"\"\")\n                                        nextControlFlow(\"else\")\n                                            emitStatement(\"long objKey = ${fieldName}ManagedDictionary.getOsMap().createAndPutEmbeddedObject(entryKey)\")\n                                            emitStatement(\"Row linkedObjectRow = realm.getTable(${genericType}.class).getUncheckedRow(objKey)\")\n                                            emitStatement(\"$genericType linkedObject = ${linkedProxyClass}.newProxyInstance(realm, linkedObjectRow)\")\n                                            emitStatement(\"cache.put(${fieldName}UnmanagedEntryValue, (RealmObjectProxy) linkedObject)\")\n                                            emitStatement(\"${linkedProxyClass}.updateEmbeddedObject(realm, ${fieldName}UnmanagedEntryValue, linkedObject, new HashMap<RealmModel, RealmObjectProxy>(), Collections.EMPTY_SET)\")\n                                        endControlFlow()\n                                    } else {\n                                        beginControlFlow(\"if (cache${fieldName} != null)\")\n                                            emitStatement(\"${fieldName}ManagedDictionary.put(entryKey, cache${fieldName})\")\n                                        nextControlFlow(\"else\")\n                                            beginControlFlow(\"if (${fieldName}UnmanagedEntryValue == null)\")\n                                                emitStatement(\"${fieldName}ManagedDictionary.put(entryKey, null)\")\n                                            nextControlFlow(\"else\")\n                                                emitStatement(\n                                                        \"%sManagedDictionary.put(entryKey, %s.copyOrUpdate(realm, (%s) realm.getSchema().getColumnInfo(%s.class), %sUnmanagedEntryValue, true, cache, flags))\",\n                                                        fieldName,\n                                                        Utils.getDictionaryGenericProxyClassSimpleName(field),\n                                                        columnInfoClassNameDictionaryGeneric(field),\n                                                        Utils.getGenericTypeQualifiedName(field),\n                                                        fieldName\n                                                )\n                                            endControlFlow()\n                                        endControlFlow()\n                                    }\n                                endControlFlow()\n                                emitStatement(\"builder.addObjectDictionary(${fieldColKey}, ${fieldName}ManagedDictionary)\")\n                            nextControlFlow(\"else\")\n                                emitStatement(\"builder.addObjectDictionary(${fieldColKey}, null)\")\n                            endControlFlow()\n                        }\n                        Utils.isRealmValueDictionary(field) -> {\n                            emitStatement(\"builder.${OsObjectBuilderTypeHelper.getOsObjectBuilderName(field)}(${fieldColKey}, realmObjectSource.${getter}())\")\n                        }\n                        Utils.isRealmAnySet(field) -> {\n                            emitEmptyLine()\n\n                            emitStatement(\"RealmSet<RealmAny> ${fieldName}UnmanagedSet = realmObjectSource.${getter}()\")\n                            beginControlFlow(\"if (${fieldName}UnmanagedSet != null)\")\n                                emitStatement(\"RealmSet<RealmAny> ${fieldName}ManagedCopy = new RealmSet<RealmAny>()\")\n                                beginControlFlow(\"for (RealmAny realmAnyItem: ${fieldName}UnmanagedSet)\")\n                                    emitStatement(\"realmAnyItem = ProxyUtils.copyOrUpdate(realmAnyItem, realm, true, cache, flags)\")\n                                    emitStatement(\"${fieldName}ManagedCopy.add(realmAnyItem)\")\n                                endControlFlow()\n\n                                emitStatement(\"builder.addRealmAnySet(${fieldColKey}, ${fieldName}ManagedCopy)\")\n                            nextControlFlow(\"else\")\n                                emitStatement(\"builder.addRealmAnySet(${fieldColKey}, new RealmSet<RealmAny>())\")\n                            endControlFlow()\n                        }\n                        Utils.isRealmModelSet(field) -> {\n                            val genericType: QualifiedClassName = Utils.getSetType(field)!!\n                            val proxyClass: SimpleClassName = Utils.getSetGenericProxyClassSimpleName(field)\n\n                            emitEmptyLine()\n                            emitStatement(\"RealmSet<${genericType}> ${fieldName}UnmanagedSet = realmObjectSource.${getter}()\")\n                            beginControlFlow(\"if (${fieldName}UnmanagedSet != null)\")\n                                emitStatement(\"RealmSet<${genericType}> ${fieldName}ManagedCopy = new RealmSet<${genericType}>()\")\n\n                                beginControlFlow(\"for (${genericType} ${fieldName}Item: ${fieldName}UnmanagedSet)\")\n                                    emitStatement(\"$genericType cache${fieldName} = (${genericType}) cache.get(${fieldName}Item)\")\n                                    beginControlFlow(\"if (cache${fieldName} != null)\")\n                                        emitStatement(\"${fieldName}ManagedCopy.add(cache${fieldName})\")\n                                    nextControlFlow(\"else\")\n                                        emitStatement(\"${fieldName}ManagedCopy.add(${proxyClass}.copyOrUpdate(realm, (${columnInfoClassNameSetGeneric(field)}) realm.getSchema().getColumnInfo(${genericType}.class), ${fieldName}Item, true, cache, flags))\")\n                                    endControlFlow()\n                                endControlFlow()\n                                emitStatement(\"builder.addObjectSet(${fieldColKey}, ${fieldName}ManagedCopy)\")\n\n                            nextControlFlow(\"else\")\n                                emitStatement(\"builder.addObjectSet(${fieldColKey}, new RealmSet<${genericType}>())\")\n                            endControlFlow()\n                        }\n                        Utils.isRealmValueSet(field) -> {\n                            emitStatement(\"builder.${OsObjectBuilderTypeHelper.getOsObjectBuilderName(field)}(${fieldColKey}, realmObjectSource.${getter}())\")\n                        }\n                        else -> {\n                            emitStatement(\"builder.%s(%s, realmObjectSource.%s())\", OsObjectBuilderTypeHelper.getOsObjectBuilderName(field), fieldColKey, getter)\n                        }\n                    }\n                }\n                emitEmptyLine()\n                if (metadata.embedded) {\n                    emitStatement(\"builder.updateExistingEmbeddedObject((RealmObjectProxy) realmObject)\")\n                } else {\n                    emitStatement(\"builder.updateExistingTopLevelObject()\")\n                }\n                emitStatement(\"return realmObject\")\n            endMethod()\n            emitEmptyLine()\n        }\n    }\n\n    @Throws(IOException::class)\n    private fun emitUpdateEmbeddedObjectMethod(writer: JavaWriter) {\n        if (!metadata.embedded) {\n            return\n        }\n\n        writer.apply {\n            beginMethod(\"void\", \"updateEmbeddedObject\", EnumSet.of(Modifier.STATIC, Modifier.PUBLIC),\n                    \"Realm\", \"realm\", // Argument type & argument name\n                    qualifiedJavaClassName.toString(), \"unmanagedObject\",\n                    qualifiedJavaClassName.toString(), \"managedObject\",\n                    \"Map<RealmModel, RealmObjectProxy>\", \"cache\",\n                    \"Set<ImportFlag>\", \"flags\"\n            )\n                emitStatement(\"update(realm, (%s) realm.getSchema().getColumnInfo(%s.class), managedObject, unmanagedObject, cache, flags)\", Utils.getSimpleColumnInfoClassName(metadata.qualifiedClassName), metadata.qualifiedClassName)\n            endMethod()\n            emitEmptyLine()\n        }\n    }\n\n    @Throws(IOException::class)\n    private fun emitToStringMethod(writer: JavaWriter) {\n        if (metadata.containsToString()) {\n            return\n        }\n        writer.apply {\n            emitAnnotation(\"Override\")\n            emitAnnotation(\"SuppressWarnings\", \"\\\"ArrayToString\\\"\")\n            beginMethod(\"String\", \"toString\", EnumSet.of(Modifier.PUBLIC))\n                beginControlFlow(\"if (!RealmObject.isValid(this))\")\n                    emitStatement(\"return \\\"Invalid object\\\"\")\n                endControlFlow()\n                emitStatement(\"StringBuilder stringBuilder = new StringBuilder(\\\"%s = proxy[\\\")\", simpleJavaClassName)\n\n                val fields = metadata.fields\n                var i = fields.size - 1\n                for (field in fields) {\n                    val fieldName = field.simpleName.toString()\n                    emitStatement(\"stringBuilder.append(\\\"{%s:\\\")\", fieldName)\n                    when {\n                        Utils.isRealmModel(field) -> {\n                            val fieldTypeSimpleName = Utils.getFieldTypeQualifiedName(field).getSimpleName()\n                            emitStatement(\"stringBuilder.append(%s() != null ? \\\"%s\\\" : \\\"null\\\")\", metadata.getInternalGetter(fieldName), fieldTypeSimpleName)\n                        }\n                        Utils.isRealmList(field) -> {\n                            val genericTypeSimpleName = Utils.getGenericTypeQualifiedName(field)?.getSimpleName()\n                            emitStatement(\"stringBuilder.append(\\\"RealmList<%s>[\\\").append(%s().size()).append(\\\"]\\\")\", genericTypeSimpleName, metadata.getInternalGetter(fieldName))\n                        }\n                        Utils.isMutableRealmInteger(field) -> {\n                            emitStatement(\"stringBuilder.append(%s().get())\", metadata.getInternalGetter(fieldName))\n                        }\n                        Utils.isByteArray(field) -> {\n                            if (metadata.isNullable(field)) {\n                                emitStatement(\"stringBuilder.append((%1\\$s() == null) ? \\\"null\\\" : \\\"binary(\\\" + %1\\$s().length + \\\")\\\")\", metadata.getInternalGetter(fieldName))\n                            } else {\n                                emitStatement(\"stringBuilder.append(\\\"binary(\\\" + %1\\$s().length + \\\")\\\")\", metadata.getInternalGetter(fieldName))\n                            }\n                        }\n                        Utils.isRealmAny(field) -> {\n                            emitStatement(\"stringBuilder.append((%1\\$s().isNull()) ? \\\"null\\\" : \\\"%s()\\\")\", metadata.getInternalGetter(fieldName), metadata.getInternalGetter(fieldName))\n                        }\n                        Utils.isRealmDictionary(field) -> {\n                            val genericTypeSimpleName: SimpleClassName? = Utils.getDictionaryValueTypeQualifiedName(field)?.getSimpleName()\n                            emitStatement(\"stringBuilder.append(\\\"RealmDictionary<%s>[\\\").append(%s().size()).append(\\\"]\\\")\", genericTypeSimpleName, metadata.getInternalGetter(fieldName))\n                        }\n                        Utils.isRealmSet(field) -> {\n                            val genericTypeSimpleName: SimpleClassName? = Utils.getSetValueTypeQualifiedName(field)?.getSimpleName()\n                            emitStatement(\"stringBuilder.append(\\\"RealmSet<%s>[\\\").append(%s().size()).append(\\\"]\\\")\", genericTypeSimpleName, metadata.getInternalGetter(fieldName))\n                        }\n                        else -> {\n                            if (metadata.isNullable(field)) {\n                                emitStatement(\"stringBuilder.append(%s() != null ? %s() : \\\"null\\\")\", metadata.getInternalGetter(fieldName), metadata.getInternalGetter(fieldName))\n                            } else {\n                                emitStatement(\"stringBuilder.append(%s())\", metadata.getInternalGetter(fieldName))\n                            }\n                        }\n                    }\n                    emitStatement(\"stringBuilder.append(\\\"}\\\")\")\n\n                    if (i-- > 0) {\n                        emitStatement(\"stringBuilder.append(\\\",\\\")\")\n                    }\n                }\n\n                emitStatement(\"stringBuilder.append(\\\"]\\\")\")\n                emitStatement(\"return stringBuilder.toString()\")\n            endMethod()\n            emitEmptyLine()\n        }\n    }\n\n    /**\n     * Currently, the hash value emitted from this could suddenly change as an object's index might\n     * alternate due to Realm Java using `Table#moveLastOver()`. Hash codes should therefore not\n     * be considered stable, i.e. don't save them in a HashSet or use them as a key in a HashMap.\n     */\n    @Throws(IOException::class)\n    private fun emitHashcodeMethod(writer: JavaWriter) {\n        if (metadata.containsHashCode()) {\n            return\n        }\n        writer.apply {\n            emitAnnotation(\"Override\")\n            beginMethod(\"int\", \"hashCode\", EnumSet.of(Modifier.PUBLIC))\n                emitStatement(\"String realmName = proxyState.getRealm\\$realm().getPath()\")\n                emitStatement(\"String tableName = proxyState.getRow\\$realm().getTable().getName()\")\n                emitStatement(\"long objKey = proxyState.getRow\\$realm().getObjectKey()\")\n                emitEmptyLine()\n                emitStatement(\"int result = 17\")\n                emitStatement(\"result = 31 * result + ((realmName != null) ? realmName.hashCode() : 0)\")\n                emitStatement(\"result = 31 * result + ((tableName != null) ? tableName.hashCode() : 0)\")\n                emitStatement(\"result = 31 * result + (int) (objKey ^ (objKey >>> 32))\")\n                emitStatement(\"return result\")\n            endMethod()\n            emitEmptyLine()\n        }\n    }\n\n    @Throws(IOException::class)\n    private fun emitEqualsMethod(writer: JavaWriter) {\n        if (metadata.containsEquals()) {\n            return\n        }\n        val proxyClassName = Utils.getProxyClassName(qualifiedJavaClassName)\n        val otherObjectVarName = \"a$simpleJavaClassName\"\n        writer.apply {\n            emitAnnotation(\"Override\")\n            beginMethod(\"boolean\", \"equals\", EnumSet.of(Modifier.PUBLIC), \"Object\", \"o\")\n                emitStatement(\"if (this == o) return true\")\n                emitStatement(\"if (o == null || getClass() != o.getClass()) return false\")\n                emitStatement(\"%s %s = (%s)o\", proxyClassName, otherObjectVarName, proxyClassName)  // FooRealmProxy aFoo = (FooRealmProxy)o\n                emitEmptyLine()\n                emitStatement(\"BaseRealm realm = proxyState.getRealm\\$realm()\")\n                emitStatement(\"BaseRealm otherRealm = %s.proxyState.getRealm\\$realm()\", otherObjectVarName)\n                emitStatement(\"String path = realm.getPath()\")\n                emitStatement(\"String otherPath = otherRealm.getPath()\")\n                emitStatement(\"if (path != null ? !path.equals(otherPath) : otherPath != null) return false\")\n                emitStatement(\"if (realm.isFrozen() != otherRealm.isFrozen()) return false\")\n                beginControlFlow(\"if (!realm.sharedRealm.getVersionID().equals(otherRealm.sharedRealm.getVersionID()))\")\n                    emitStatement(\"return false\")\n                endControlFlow()\n                emitEmptyLine()\n                emitStatement(\"String tableName = proxyState.getRow\\$realm().getTable().getName()\")\n                emitStatement(\"String otherTableName = %s.proxyState.getRow\\$realm().getTable().getName()\", otherObjectVarName)\n                emitStatement(\"if (tableName != null ? !tableName.equals(otherTableName) : otherTableName != null) return false\")\n                emitEmptyLine()\n                emitStatement(\"if (proxyState.getRow\\$realm().getObjectKey() != %s.proxyState.getRow\\$realm().getObjectKey()) return false\", otherObjectVarName)\n                emitEmptyLine()\n                emitStatement(\"return true\")\n            endMethod()\n        }\n    }\n\n    @Throws(IOException::class)\n    private fun emitCreateOrUpdateUsingJsonObject(writer: JavaWriter) {\n        writer.apply {\n            val embedded = metadata.embedded\n            emitAnnotation(\"SuppressWarnings\", \"\\\"cast\\\"\")\n            if (!embedded) {\n                beginMethod(qualifiedJavaClassName, \"createOrUpdateUsingJsonObject\", EnumSet.of(Modifier.PUBLIC, Modifier.STATIC), Arrays.asList(\"Realm\", \"realm\", \"JSONObject\", \"json\", \"boolean\", \"update\"), listOf(\"JSONException\"))\n            } else {\n                beginMethod(qualifiedJavaClassName, \"createOrUpdateEmbeddedUsingJsonObject\", EnumSet.of(Modifier.PUBLIC, Modifier.STATIC), Arrays.asList(\"Realm\", \"realm\", \"RealmModel\", \"parent\", \"String\", \"parentProperty\", \"JSONObject\", \"json\", \"boolean\", \"update\"), listOf(\"JSONException\"))\n            }\n\n                // Throw if model contains a dictionary field until we add support for it\n                if (containsDictionary(metadata.fields)) {\n                    emitStatement(\"throw new UnsupportedOperationException(\\\"Creation of RealmModels from JSON containing RealmDictionary properties is not supported yet.\\\")\")\n                    endMethod()\n                    emitEmptyLine()\n                    return@apply\n                }\n\n                // Throw if model contains a set field until we add support for it\n                if (containsSet(metadata.fields)) {\n                    emitStatement(\"throw new UnsupportedOperationException(\\\"Creation of RealmModels from JSON containing RealmSet properties is not supported yet.\\\")\")\n                    endMethod()\n                    emitEmptyLine()\n                    return@apply\n                }\n\n                val modelOrListCount = countModelOrListFields(metadata.fields)\n                if (modelOrListCount == 0) {\n                    emitStatement(\"final List<String> excludeFields = Collections.<String> emptyList()\")\n                } else {\n                    emitStatement(\"final List<String> excludeFields = new ArrayList<String>(%1\\$d)\", modelOrListCount)\n                }\n\n                if (!metadata.hasPrimaryKey()) {\n                    buildExcludeFieldsList(writer, metadata.fields)\n                    if (!embedded) {\n                        emitStatement(\"%s obj = realm.createObjectInternal(%s.class, true, excludeFields)\", qualifiedJavaClassName, qualifiedJavaClassName)\n                    } else {\n                        emitStatement(\"%s obj = realm.createEmbeddedObject(%s.class, parent, parentProperty)\", qualifiedJavaClassName, qualifiedJavaClassName)\n                    }\n                } else {\n                    var pkType = \"Long\"\n                    var jsonAccessorMethodSuffix = \"Long\"\n                    var findFirstCast = \"\"\n                    if (Utils.isString(metadata.primaryKey)) {\n                        pkType = \"String\"\n                        jsonAccessorMethodSuffix=  \"String\"\n                    } else if (Utils.isObjectId(metadata.primaryKey)) {\n                        pkType = \"ObjectId\"\n                        findFirstCast = \"(org.bson.types.ObjectId)\"\n                        jsonAccessorMethodSuffix = \"\"\n                    } else if (Utils.isUUID(metadata.primaryKey)) {\n                        pkType = \"UUID\"\n                        findFirstCast = \"(java.util.UUID)\"\n                        jsonAccessorMethodSuffix = \"\"\n                    }\n                    val nullableMetadata = if (Utils.isObjectId(metadata.primaryKey)) {\n                        \"objKey = table.findFirst%s(pkColumnKey, new org.bson.types.ObjectId((String)json.get%s(\\\"%s\\\")))\".format(pkType, jsonAccessorMethodSuffix, metadata.primaryKey!!.simpleName)\n                    } else {\n                        \"objKey = table.findFirst%s(pkColumnKey, %sjson.get%s(\\\"%s\\\"))\".format(pkType, findFirstCast, jsonAccessorMethodSuffix, metadata.primaryKey!!.simpleName)\n                    }\n                    val nonNullableMetadata = \"objKey = table.findFirst%s(pkColumnKey, %sjson.get%s(\\\"%s\\\"))\".format(pkType, findFirstCast, jsonAccessorMethodSuffix, metadata.primaryKey!!.simpleName)\n\n                    emitStatement(\"%s obj = null\", qualifiedJavaClassName)\n                    beginControlFlow(\"if (update)\")\n                        emitStatement(\"Table table = realm.getTable(%s.class)\", qualifiedJavaClassName)\n                        emitStatement(\"%s columnInfo = (%s) realm.getSchema().getColumnInfo(%s.class)\", columnInfoClassName(), columnInfoClassName(), qualifiedJavaClassName)\n                        emitStatement(\"long pkColumnKey = %s\", fieldColKeyVariableReference(metadata.primaryKey))\n                        emitStatement(\"long objKey = Table.NO_MATCH\")\n                        if (metadata.isNullable(metadata.primaryKey!!)) {\n                            beginControlFlow(\"if (json.isNull(\\\"%s\\\"))\", metadata.primaryKey!!.simpleName)\n                                emitStatement(\"objKey = table.findFirstNull(pkColumnKey)\")\n                            nextControlFlow(\"else\")\n                                emitStatement(nullableMetadata)\n                            endControlFlow()\n                        } else {\n                            beginControlFlow(\"if (!json.isNull(\\\"%s\\\"))\", metadata.primaryKey!!.simpleName)\n                                emitStatement(nonNullableMetadata)\n                            endControlFlow()\n                        }\n                        beginControlFlow(\"if (objKey != Table.NO_MATCH)\")\n                            emitStatement(\"final BaseRealm.RealmObjectContext objectContext = BaseRealm.objectContext.get()\")\n                            beginControlFlow(\"try\")\n                                emitStatement(\"objectContext.set(realm, table.getUncheckedRow(objKey), realm.getSchema().getColumnInfo(%s.class), false, Collections.<String> emptyList())\", qualifiedJavaClassName)\n                                emitStatement(\"obj = new %s()\", generatedClassName)\n                            nextControlFlow(\"finally\")\n                                emitStatement(\"objectContext.clear()\")\n                            endControlFlow()\n                        endControlFlow()\n                    endControlFlow()\n\n                    beginControlFlow(\"if (obj == null)\")\n                        buildExcludeFieldsList(writer, metadata.fields)\n                        val primaryKeyFieldType = QualifiedClassName(metadata.primaryKey!!.asType().toString())\n                        val primaryKeyFieldName = metadata.primaryKey!!.simpleName.toString()\n                        RealmJsonTypeHelper.emitCreateObjectWithPrimaryKeyValue(qualifiedJavaClassName, generatedClassName, primaryKeyFieldType, primaryKeyFieldName, writer)\n                    endControlFlow()\n                }\n                emitEmptyLine()\n                emitStatement(\"final %1\\$s objProxy = (%1\\$s) obj\", interfaceName)\n                for (field in metadata.fields) {\n                    val fieldName = field.simpleName.toString()\n                    val qualifiedFieldType = QualifiedClassName(field.asType().toString())\n                    if (metadata.isPrimaryKey(field)) {\n                        continue  // Primary key has already been set when adding new row or finding the existing row.\n                    }\n                    when {\n                        Utils.isRealmModel(field) -> {\n                            val isEmbedded = Utils.isFieldTypeEmbedded(field.asType(), classCollection)\n                            RealmJsonTypeHelper.emitFillRealmObjectWithJsonValue(\n                                    \"objProxy\",\n                                    metadata.getInternalSetter(fieldName),\n                                    fieldName,\n                                    qualifiedFieldType,\n                                    Utils.getProxyClassSimpleName(field),\n                                    isEmbedded,\n                                    writer)\n                        }\n                        Utils.isRealmModelList(field) -> {\n                            val fieldType = (field.asType() as DeclaredType).typeArguments[0]\n                            RealmJsonTypeHelper.emitFillRealmListWithJsonValue(\n                                    \"objProxy\",\n                                    metadata.getInternalGetter(fieldName),\n                                    metadata.getInternalSetter(fieldName),\n                                    fieldName,\n                                    (field.asType() as DeclaredType).typeArguments[0].toString(),\n                                    Utils.getProxyClassSimpleName(field),\n                                    Utils.isFieldTypeEmbedded(fieldType, classCollection),\n                                    writer)\n                        }\n                        Utils.isRealmValueList(field) || Utils.isRealmAnyList(field) -> emitStatement(\"ProxyUtils.setRealmListWithJsonObject(realm, objProxy.%1\\$s(), json, \\\"%2\\$s\\\", update)\", metadata.getInternalGetter(fieldName), fieldName)\n                        Utils.isMutableRealmInteger(field) -> RealmJsonTypeHelper.emitFillJavaTypeWithJsonValue(\n                                \"objProxy\",\n                                metadata.getInternalGetter(fieldName),\n                                fieldName,\n                                qualifiedFieldType,\n                                writer)\n                        Utils.isRealmDictionary(field) -> {\n                            // TODO: dictionary\n                            emitSingleLineComment(\"TODO: Dictionary\")\n                        }\n                        Utils.isRealmSet(field) -> {\n                            // TODO: sets\n                            emitSingleLineComment(\"TODO: Set\")\n                        }\n                        else -> RealmJsonTypeHelper.emitFillJavaTypeWithJsonValue(\n                                \"objProxy\",\n                                metadata.getInternalSetter(fieldName),\n                                fieldName,\n                                qualifiedFieldType,\n                                writer)\n                    }\n                }\n                emitStatement(\"return obj\")\n                endMethod()\n                emitEmptyLine()\n        }\n    }\n\n    @Throws(IOException::class)\n    private fun buildExcludeFieldsList(writer: JavaWriter, fields: Collection<RealmFieldElement>) {\n        writer.apply {\n            for (field in fields) {\n                if (Utils.isRealmModel(field) || Utils.isRealmList(field)) {\n                    val fieldName = field.simpleName.toString()\n                    beginControlFlow(\"if (json.has(\\\"%1\\$s\\\"))\", fieldName)\n                        emitStatement(\"excludeFields.add(\\\"%1\\$s\\\")\", fieldName)\n                    endControlFlow()\n                }\n            }\n        }\n    }\n\n    // Since we need to check the PK in stream before creating the object, this is now using copyToRealm\n    // instead of createObject() to avoid parsing the stream twice.\n    @Throws(IOException::class)\n    private fun emitCreateUsingJsonStream(writer: JavaWriter) {\n        writer.apply {\n            emitAnnotation(\"SuppressWarnings\", \"\\\"cast\\\"\")\n            emitAnnotation(\"TargetApi\", \"Build.VERSION_CODES.HONEYCOMB\")\n            beginMethod(qualifiedJavaClassName,\"createUsingJsonStream\", setOf(Modifier.PUBLIC, Modifier.STATIC), listOf(\"Realm\", \"realm\", \"JsonReader\", \"reader\"), listOf(\"IOException\"))\n\n            // Throw if model contains a dictionary field until we add support for it\n            if (containsDictionary(metadata.fields)) {\n                emitStatement(\"throw new UnsupportedOperationException(\\\"Creation of RealmModels from JSON containing RealmDictionary properties is not supported yet.\\\")\")\n                endMethod()\n                emitEmptyLine()\n                return@apply\n            }\n\n            // Throw if model contains a set field until we add support for it\n            if (containsSet(metadata.fields)) {\n                emitStatement(\"throw new UnsupportedOperationException(\\\"Creation of RealmModels from JSON containing RealmSet properties is not supported yet.\\\")\")\n                endMethod()\n                emitEmptyLine()\n                return@apply\n            }\n\n            if (metadata.hasPrimaryKey()) {\n                emitStatement(\"boolean jsonHasPrimaryKey = false\")\n            }\n            emitStatement(\"final %s obj = new %s()\", qualifiedJavaClassName, qualifiedJavaClassName)\n            emitStatement(\"final %1\\$s objProxy = (%1\\$s) obj\", interfaceName)\n            emitStatement(\"reader.beginObject()\")\n            beginControlFlow(\"while (reader.hasNext())\")\n                emitStatement(\"String name = reader.nextName()\")\n                beginControlFlow(\"if (false)\")\n                val fields = metadata.fields\n                for (field in fields) {\n                    val fieldName = field.simpleName.toString()\n                    val fieldType = QualifiedClassName(field.asType().toString())\n                    nextControlFlow(\"else if (name.equals(\\\"%s\\\"))\", fieldName)\n\n                    when {\n                        Utils.isRealmModel(field) -> {\n                            RealmJsonTypeHelper.emitFillRealmObjectFromStream(\n                                    \"objProxy\",\n                                    metadata.getInternalSetter(fieldName),\n                                    fieldName,\n                                    fieldType,\n                                    Utils.getProxyClassSimpleName(field),\n                                    writer)\n                        }\n                        Utils.isRealmModelList(field) -> {\n                            RealmJsonTypeHelper.emitFillRealmListFromStream(\n                                    \"objProxy\",\n                                    metadata.getInternalGetter(fieldName),\n                                    metadata.getInternalSetter(fieldName),\n                                    QualifiedClassName((field.asType() as DeclaredType).typeArguments[0].toString()),\n                                    Utils.getProxyClassSimpleName(field),\n                                    writer)\n                        }\n                        Utils.isRealmValueList(field) || Utils.isRealmAnyList(field) -> {\n                            emitStatement(\"objProxy.%1\\$s(ProxyUtils.createRealmListWithJsonStream(%2\\$s.class, reader))\", metadata.getInternalSetter(fieldName), Utils.getRealmListType(field))\n                        }\n                        Utils.isMutableRealmInteger(field) -> {\n                            RealmJsonTypeHelper.emitFillJavaTypeFromStream(\n                                    \"objProxy\",\n                                    metadata,\n                                    metadata.getInternalGetter(fieldName),\n                                    fieldName,\n                                    fieldType,\n                                    writer)\n                        }\n                        Utils.isRealmDictionary(field) -> {\n                            // TODO: add support for dictionary\n                            emitSingleLineComment(\"TODO: Dictionary\")\n                        }\n                        Utils.isRealmSet(field) -> {\n                            // TODO: add support for sets\n                            emitSingleLineComment(\"TODO: Set\")\n                        }\n                        else -> {\n                            RealmJsonTypeHelper.emitFillJavaTypeFromStream(\n                                    \"objProxy\",\n                                    metadata,\n                                    metadata.getInternalSetter(fieldName),\n                                    fieldName,\n                                    fieldType,\n                                    writer)\n                        }\n                    }\n                }\n\n                nextControlFlow(\"else\")\n                    emitStatement(\"reader.skipValue()\")\n                endControlFlow()\n            endControlFlow()\n            emitStatement(\"reader.endObject()\")\n            if (metadata.hasPrimaryKey()) {\n                beginControlFlow(\"if (!jsonHasPrimaryKey)\")\n                    emitStatement(Constants.STATEMENT_EXCEPTION_NO_PRIMARY_KEY_IN_JSON, metadata.primaryKey)\n                endControlFlow()\n            }\n            if (!metadata.embedded) {\n                if (metadata.hasPrimaryKey()) {\n                    emitStatement(\"return realm.copyToRealmOrUpdate(obj)\")\n                } else {\n                    emitStatement(\"return realm.copyToRealm(obj)\")\n                }\n            } else {\n                // Embedded objects are left unmanaged and assumed to be added by their parent. This\n                // is safe as json import is blocked for embedded objects without a parent.\n                emitStatement(\"return obj\")\n            }\n            endMethod()\n            emitEmptyLine()\n        }\n    }\n\n    private fun columnInfoClassName(): String {\n        return \"${simpleJavaClassName}ColumnInfo\"\n    }\n\n    /**\n     * Returns the name of the ColumnInfo class for the model class referenced in the field.\n     * I.e. for `com.test.Person`, it returns `Person.PersonColumnInfo`\n     */\n    private fun columnInfoClassName(field: VariableElement): String {\n        val qualifiedModelClassName = Utils.getModelClassQualifiedName(field)\n        return Utils.getSimpleColumnInfoClassName(qualifiedModelClassName)\n    }\n\n    private fun columnInfoClassNameDictionaryGeneric(field: VariableElement): String {\n        val qualifiedModelClassName = Utils.getDictionaryGenericModelClassQualifiedName(field)\n        return Utils.getSimpleColumnInfoClassName(qualifiedModelClassName)\n    }\n\n    private fun columnInfoClassNameSetGeneric(field: VariableElement): String {\n        val qualifiedModelClassName = Utils.getSetGenericModelClassQualifiedName(field)\n        return Utils.getSimpleColumnInfoClassName(qualifiedModelClassName)\n    }\n\n    private fun columnKeyVarName(variableElement: VariableElement): String {\n        return \"${variableElement.simpleName}ColKey\"\n    }\n\n    private fun mutableRealmIntegerFieldName(variableElement: VariableElement): String {\n        return \"${variableElement.simpleName}MutableRealmInteger\"\n    }\n\n    private fun realmAnyFieldName(variableElement: VariableElement): String {\n        return \"${variableElement.simpleName}RealmAny\"\n    }\n\n    private fun fieldColKeyVariableReference(variableElement: VariableElement?): String {\n        return \"columnInfo.${columnKeyVarName(variableElement!!)}\"\n    }\n\n    private fun getRealmType(field: VariableElement): Constants.RealmFieldType {\n        val fieldTypeCanonicalName: String = field.asType().toString()\n        val type: Constants.RealmFieldType? = Constants.JAVA_TO_REALM_TYPES[fieldTypeCanonicalName]\n        if (type != null) {\n            return type\n        }\n        if (Utils.isMutableRealmInteger(field)) {\n            return Constants.RealmFieldType.REALM_INTEGER\n        }\n        if (Utils.isRealmAny(field)){\n            return Constants.RealmFieldType.MIXED\n        }\n        if (Utils.isRealmModel(field)) {\n            return Constants.RealmFieldType.OBJECT\n        }\n        if (Utils.isRealmModelList(field)) {\n            return Constants.RealmFieldType.LIST\n        }\n        if (Utils.isRealmValueList(field) || Utils.isRealmAnyList(field)) {\n            return Utils.getValueListFieldType(field)\n        }\n        if (Utils.isRealmModelDictionary(field)) {\n            return Constants.RealmFieldType.STRING_TO_LINK_MAP\n        }\n        if (Utils.isRealmDictionary(field)) {\n            return Utils.getValueDictionaryFieldType(field)\n        }\n        if (Utils.isRealmModelSet(field)) {\n            return Constants.RealmFieldType.LINK_SET\n        }\n        if (Utils.isRealmSet(field)) {\n            return Utils.getValueSetFieldType(field)\n        }\n        return Constants.RealmFieldType.NOTYPE\n    }\n\n    private fun getRealmTypeChecked(field: VariableElement): Constants.RealmFieldType {\n        val type = getRealmType(field)\n        if (type === Constants.RealmFieldType.NOTYPE) {\n            throw IllegalStateException(\"Unsupported type \" + field.asType().toString())\n        }\n        return type\n    }\n\n    companion object {\n        private val OPTION_SUPPRESS_WARNINGS = \"realm.suppressWarnings\"\n        private val BACKLINKS_FIELD_EXTENSION = \"Backlinks\"\n\n        private val IMPORTS: List<String>\n\n        init {\n            val l = Arrays.asList(\n                    \"android.annotation.TargetApi\",\n                    \"android.os.Build\",\n                    \"android.util.JsonReader\",\n                    \"android.util.JsonToken\",\n                    \"io.realm.ImportFlag\",\n                    \"io.realm.exceptions.RealmMigrationNeededException\",\n                    \"io.realm.internal.ColumnInfo\",\n                    \"io.realm.internal.NativeContext\",\n                    \"io.realm.internal.OsList\",\n                    \"io.realm.internal.OsMap\",\n                    \"io.realm.internal.OsSet\",\n                    \"io.realm.internal.OsObject\",\n                    \"io.realm.internal.OsSchemaInfo\",\n                    \"io.realm.internal.OsObjectSchemaInfo\",\n                    \"io.realm.internal.Property\",\n                    \"io.realm.internal.core.NativeRealmAny\",\n                    \"io.realm.internal.objectstore.OsObjectBuilder\",\n                    \"io.realm.ProxyUtils\",\n                    \"io.realm.internal.RealmObjectProxy\",\n                    \"io.realm.internal.Row\",\n                    \"io.realm.internal.Table\",\n                    \"io.realm.internal.android.JsonUtils\",\n                    \"io.realm.log.RealmLog\",\n                    \"java.io.IOException\",\n                    \"java.util.ArrayList\",\n                    \"java.util.Collections\",\n                    \"java.util.List\",\n                    \"java.util.Iterator\",\n                    \"java.util.Date\",\n                    \"java.util.Map\",\n                    \"java.util.HashMap\",\n                    \"java.util.HashSet\",\n                    \"java.util.Set\",\n                    \"org.json.JSONObject\",\n                    \"org.json.JSONException\",\n                    \"org.json.JSONArray\")\n            IMPORTS = Collections.unmodifiableList(l)\n        }\n\n        private fun countModelOrListFields(fields: Collection<RealmFieldElement>): Int {\n            var count = 0\n            for (f in fields) {\n                if (Utils.isRealmModel(f) || Utils.isRealmList(f)) {\n                    count++\n                }\n            }\n            return count\n        }\n    }\n\n    private fun containsDictionary(fields: ArrayList<RealmFieldElement>): Boolean {\n        for (field in fields) {\n            if (Utils.isRealmDictionary(field)) {\n                return true\n            }\n        }\n        return false\n    }\n\n    private fun containsSet(fields: ArrayList<RealmFieldElement>): Boolean {\n        for (field in fields) {\n            if (Utils.isRealmSet(field)) {\n                return true\n            }\n        }\n        return false\n    }\n}\n"
  },
  {
    "path": "realm/realm-annotations-processor/src/main/java/io/realm/processor/RealmProxyInterfaceGenerator.kt",
    "content": "/*\n * Copyright 2019 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 */\npackage io.realm.processor\n\nimport com.squareup.javawriter.JavaWriter\n\nimport java.io.BufferedWriter\nimport java.io.IOException\nimport java.util.EnumSet\nimport java.util.Locale\n\nimport javax.annotation.processing.ProcessingEnvironment\nimport javax.lang.model.element.Modifier\n\nimport io.realm.annotations.Ignore\n\n\nclass RealmProxyInterfaceGenerator(private val processingEnvironment: ProcessingEnvironment, private val metaData: ClassMetaData) {\n\n    private val className: QualifiedClassName = metaData.qualifiedClassName\n\n    @Throws(IOException::class)\n    fun generate() {\n        val qualifiedGeneratedInterfaceName = String.format(Locale.US, \"%s.%s\", Constants.REALM_PACKAGE_NAME, Utils.getProxyInterfaceName(className))\n        val sourceFile = processingEnvironment.filer.createSourceFile(qualifiedGeneratedInterfaceName)\n        val writer = JavaWriter(BufferedWriter(sourceFile.openWriter()!!))\n        writer.apply {\n            indent = Constants.INDENT\n            emitPackage(Constants.REALM_PACKAGE_NAME)\n            emitEmptyLine()\n            beginType(qualifiedGeneratedInterfaceName, \"interface\", EnumSet.of(Modifier.PUBLIC))\n\n            for (field in metaData.fields) {\n                if (field.modifiers.contains(Modifier.STATIC) || field.getAnnotation(Ignore::class.java) != null) {\n                    continue\n                }\n                // The field is neither static nor ignored\n                val fieldName = field.simpleName.toString()\n                val fieldTypeCanonicalName = field.asType().toString()\n                beginMethod(fieldTypeCanonicalName, metaData.getInternalGetter(fieldName), EnumSet.of(Modifier.PUBLIC))\n                endMethod()\n\n                // MutableRealmIntegers do not have setters.\n                if (Utils.isMutableRealmInteger(field)) {\n                    continue\n                }\n                beginMethod(\"void\", metaData.getInternalSetter(fieldName), EnumSet.of(Modifier.PUBLIC), fieldTypeCanonicalName, \"value\")\n                endMethod()\n            }\n\n            // backlinks are final and have only a getter.\n            for (backlink in metaData.backlinkFields) {\n                beginMethod(backlink.targetFieldType, metaData.getInternalGetter(backlink.targetField), EnumSet.of(Modifier.PUBLIC))\n                endMethod()\n            }\n\n            endType()\n            close()\n        }\n    }\n}\n"
  },
  {
    "path": "realm/realm-annotations-processor/src/main/java/io/realm/processor/RealmProxyMediatorGenerator.kt",
    "content": "/*\n * Copyright 2019 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\npackage io.realm.processor\n\nimport com.squareup.javawriter.JavaWriter\nimport io.realm.annotations.RealmModule\nimport java.io.BufferedWriter\nimport java.io.IOException\nimport java.util.*\nimport javax.annotation.processing.ProcessingEnvironment\nimport javax.lang.model.element.Modifier\nimport javax.tools.JavaFileObject\n\nclass RealmProxyMediatorGenerator(private val processingEnvironment: ProcessingEnvironment,\n                                  private val className: SimpleClassName,\n                                  classesToValidate: Set<ClassMetaData>) {\n\n    private val qualifiedModelClasses = ArrayList<QualifiedClassName>()\n    private val qualifiedProxyClasses = ArrayList<QualifiedClassName>()\n    private val simpleModelClassNames = ArrayList<SimpleClassName>()\n    private val internalClassNames = ArrayList<String>()\n    private val embeddedClass = ArrayList<Boolean>()\n    private val primaryKeyClasses = mutableListOf<QualifiedClassName>()\n\n    init {\n        // Sort classes to ensure deterministic output. This is relevant when e.g. using Gradle\n        // Remote Cache since the order is not guaranteed between OS and Java versions.\n        for (metadata in classesToValidate.toSortedSet(compareByDescending { it.qualifiedClassName.name })) {\n            qualifiedModelClasses.add(metadata.qualifiedClassName)\n            val qualifiedProxyClassName = QualifiedClassName(\"${Constants.REALM_PACKAGE_NAME}.${Utils.getProxyClassName(metadata.qualifiedClassName)}\")\n            qualifiedProxyClasses.add(qualifiedProxyClassName)\n            simpleModelClassNames.add(metadata.simpleJavaClassName)\n            internalClassNames.add(metadata.internalClassName)\n            embeddedClass.add(metadata.embedded)\n            if(metadata.primaryKey != null) {\n                primaryKeyClasses.add(metadata.qualifiedClassName)\n            }\n        }\n    }\n\n    @Throws(IOException::class)\n    fun generate() {\n        val qualifiedGeneratedClassName: String = String.format(Locale.US, \"%s.%sMediator\", Constants.REALM_PACKAGE_NAME, className)\n        val sourceFile: JavaFileObject = processingEnvironment.filer.createSourceFile(qualifiedGeneratedClassName)\n        val imports = ArrayList(Arrays.asList(\"android.util.JsonReader\",\n                \"java.io.IOException\",\n                \"java.util.Collections\",\n                \"java.util.HashSet\",\n                \"java.util.List\",\n                \"java.util.Map\",\n                \"java.util.HashMap\",\n                \"java.util.Set\",\n                \"java.util.Iterator\",\n                \"java.util.Collection\",\n                \"io.realm.ImportFlag\",\n                \"io.realm.internal.ColumnInfo\",\n                \"io.realm.internal.RealmObjectProxy\",\n                \"io.realm.internal.RealmProxyMediator\",\n                \"io.realm.internal.Row\",\n                \"io.realm.internal.OsSchemaInfo\",\n                \"io.realm.internal.OsObjectSchemaInfo\",\n                \"org.json.JSONException\",\n                \"org.json.JSONObject\"))\n\n        val writer = JavaWriter(BufferedWriter(sourceFile.openWriter()))\n        writer.apply {\n            indent = \"    \"\n            emitPackage(Constants.REALM_PACKAGE_NAME)\n            emitEmptyLine()\n            emitImports(imports)\n            emitEmptyLine()\n            emitAnnotation(RealmModule::class.java)\n            beginType(qualifiedGeneratedClassName,      // full qualified name of the item to generate\n                    \"class\",                      // the type of the item\n                    emptySet(),                        // modifiers to apply\n                    \"RealmProxyMediator\")  // class to extend\n            emitEmptyLine()\n            emitFields(this)\n            emitGetExpectedObjectSchemaInfoMap(this)\n            emitCreateColumnInfoMethod(this)\n            emitGetSimpleClassNameMethod(this)\n            emitGetClazzClassNameMethod(this)\n            emitHasPrimaryKeyMethod(this)\n            emitNewInstanceMethod(this)\n            emitGetClassModelList(this)\n            emitCopyOrUpdateMethod(this)\n            emitInsertObjectToRealmMethod(this)\n            emitInsertListToRealmMethod(this)\n            emitInsertOrUpdateObjectToRealmMethod(this)\n            emitInsertOrUpdateListToRealmMethod(this)\n            emitCreteOrUpdateUsingJsonObject(this)\n            emitCreateUsingJsonStream(this)\n            emitCreateDetachedCopyMethod(this)\n            emitIsEmbeddedMethod(this)\n            emitUpdateEmbeddedObjectMethod(this)\n            endType()\n            close()\n        }\n    }\n\n    @Throws(IOException::class)\n    private fun emitFields(writer: JavaWriter) {\n        writer.apply {\n            emitField(\"Set<Class<? extends RealmModel>>\", \"MODEL_CLASSES\", EnumSet.of(Modifier.PRIVATE, Modifier.STATIC, Modifier.FINAL))\n            beginInitializer(true)\n            emitStatement(\"Set<Class<? extends RealmModel>> modelClasses = new HashSet<Class<? extends RealmModel>>(%s)\", qualifiedModelClasses.size)\n            for (clazz in qualifiedModelClasses) {\n                emitStatement(\"modelClasses.add(%s.class)\", clazz)\n            }\n            emitStatement(\"MODEL_CLASSES = Collections.unmodifiableSet(modelClasses)\")\n            endInitializer()\n            emitEmptyLine()\n        }\n    }\n\n    @Throws(IOException::class)\n    private fun emitGetExpectedObjectSchemaInfoMap(writer: JavaWriter) {\n        writer.apply {\n            emitAnnotation(\"Override\")\n            beginMethod(\"Map<Class<? extends RealmModel>, OsObjectSchemaInfo>\",\"getExpectedObjectSchemaInfoMap\", EnumSet.of(Modifier.PUBLIC))\n                emitStatement(\"Map<Class<? extends RealmModel>, OsObjectSchemaInfo> infoMap = new HashMap<Class<? extends RealmModel>, OsObjectSchemaInfo>(%s)\", qualifiedProxyClasses.size)\n                for (i in qualifiedProxyClasses.indices) {\n                    emitStatement(\"infoMap.put(%s.class, %s.getExpectedObjectSchemaInfo())\", qualifiedModelClasses[i], qualifiedProxyClasses[i])\n                }\n                emitStatement(\"return infoMap\")\n            endMethod()\n            emitEmptyLine()\n        }\n    }\n\n    @Throws(IOException::class)\n    private fun emitCreateColumnInfoMethod(writer: JavaWriter) {\n        writer.apply {\n            emitAnnotation(\"Override\")\n            beginMethod(\n                    \"ColumnInfo\",\n                    \"createColumnInfo\",\n                    EnumSet.of(Modifier.PUBLIC),\n                    \"Class<? extends RealmModel>\", \"clazz\", // Argument type & argument name\n                    \"OsSchemaInfo\", \"schemaInfo\"\n            )\n            emitMediatorShortCircuitSwitch(writer, emitStatement = { i: Int ->\n                emitStatement(\"return %s.createColumnInfo(schemaInfo)\", qualifiedProxyClasses[i])\n            })\n            endMethod()\n            emitEmptyLine()\n        }\n    }\n\n    @Throws(IOException::class)\n    private fun emitGetSimpleClassNameMethod(writer: JavaWriter) {\n        writer.apply {\n            emitAnnotation(\"Override\")\n            beginMethod(\n                    \"String\",\n                    \"getSimpleClassNameImpl\",\n                    EnumSet.of(Modifier.PUBLIC),\n                    \"Class<? extends RealmModel>\", \"clazz\"\n            )\n            emitMediatorShortCircuitSwitch(writer, emitStatement = { i: Int ->\n                emitStatement(\"return \\\"%s\\\"\", internalClassNames[i])\n            })\n            endMethod()\n            emitEmptyLine()\n        }\n    }\n\n    @Throws(IOException::class)\n    private fun emitGetClazzClassNameMethod(writer: JavaWriter) {\n        writer.apply {\n            emitAnnotation(\"Override\")\n            beginMethod(\n                    \"Class<? extends RealmModel>\",\n                    \"getClazzImpl\",\n                    EnumSet.of(Modifier.PUBLIC),\n                    \"String\", \"className\"\n            )\n            emitMediatorInverseShortCircuitSwitch(writer, emitStatement = { i: Int ->\n                emitStatement(\"return %s.class\", qualifiedModelClasses[i])\n            })\n            endMethod()\n            emitEmptyLine()\n        }\n    }\n\n    @Throws(IOException::class)\n    private fun emitHasPrimaryKeyMethod(writer: JavaWriter) {\n        writer.apply {\n            emitAnnotation(\"Override\")\n            beginMethod(\n                    \"boolean\",\n                    \"hasPrimaryKeyImpl\",\n                    EnumSet.of(Modifier.PUBLIC),\n                    \"Class<? extends RealmModel>\", \"clazz\"\n            )\n\n            if (primaryKeyClasses.size == 0) {\n                emitStatement(\"return false\")\n            } else {\n                val primaryKeyCondition = primaryKeyClasses.joinToString(\".class.isAssignableFrom(clazz)\\n|| \", \"\", \".class.isAssignableFrom(clazz)\")\n                emitStatement(\"return %s\", primaryKeyCondition)\n            }\n\n            endMethod()\n            emitEmptyLine()\n        }\n    }\n\n    @Throws(IOException::class)\n    private fun emitNewInstanceMethod(writer: JavaWriter) {\n        writer.apply {\n            emitAnnotation(\"Override\")\n            beginMethod(\n                    \"<E extends RealmModel> E\",\n                    \"newInstance\",\n                    EnumSet.of(Modifier.PUBLIC),\n                    \"Class<E>\", \"clazz\",\n                    \"Object\", \"baseRealm\",\n                    \"Row\", \"row\",\n                    \"ColumnInfo\", \"columnInfo\",\n                    \"boolean\", \"acceptDefaultValue\",\n                    \"List<String>\", \"excludeFields\"\n            )\n                emitStatement(\"final BaseRealm.RealmObjectContext objectContext = BaseRealm.objectContext.get()\")\n                beginControlFlow(\"try\")\n                    emitStatement(\"objectContext.set((BaseRealm) baseRealm, row, columnInfo, acceptDefaultValue, excludeFields)\")\n                    emitMediatorShortCircuitSwitch(writer, emitStatement = { i: Int ->\n                        emitStatement(\"return clazz.cast(new %s())\", qualifiedProxyClasses[i])\n                    })\n                nextControlFlow(\"finally\")\n                    emitStatement(\"objectContext.clear()\")\n                endControlFlow()\n            endMethod()\n            emitEmptyLine()\n        }\n    }\n\n    @Throws(IOException::class)\n    private fun emitGetClassModelList(writer: JavaWriter) {\n        writer.apply {\n            emitAnnotation(\"Override\")\n            beginMethod(\"Set<Class<? extends RealmModel>>\", \"getModelClasses\", EnumSet.of(Modifier.PUBLIC))\n                emitStatement(\"return MODEL_CLASSES\")\n            endMethod()\n            emitEmptyLine()\n        }\n    }\n\n    @Throws(IOException::class)\n    private fun emitCopyOrUpdateMethod(writer: JavaWriter) {\n        writer.apply {\n            emitAnnotation(\"Override\")\n            beginMethod(\n                    \"<E extends RealmModel> E\",\n                    \"copyOrUpdate\",\n                    EnumSet.of(Modifier.PUBLIC),\n                    \"Realm\", \"realm\",\n                    \"E\", \"obj\",\n                    \"boolean\", \"update\",\n                    \"Map<RealmModel, RealmObjectProxy>\", \"cache\",\n                    \"Set<ImportFlag>\", \"flags\"\n            )\n                emitSingleLineComment(\"This cast is correct because obj is either\")\n                emitSingleLineComment(\"generated by RealmProxy or the original type extending directly from RealmObject\")\n                emitStatement(\"@SuppressWarnings(\\\"unchecked\\\") Class<E> clazz = (Class<E>) ((obj instanceof RealmObjectProxy) ? obj.getClass().getSuperclass() : obj.getClass())\")\n                emitEmptyLine()\n                emitMediatorShortCircuitSwitch(writer, false) { i: Int ->\n                    emitStatement(\"%1\\$s columnInfo = (%1\\$s) realm.getSchema().getColumnInfo(%2\\$s.class)\", Utils.getSimpleColumnInfoClassName(qualifiedModelClasses[i]), qualifiedModelClasses[i])\n                    emitStatement(\"return clazz.cast(%s.copyOrUpdate(realm, columnInfo, (%s) obj, update, cache, flags))\", qualifiedProxyClasses[i], qualifiedModelClasses[i])\n                }\n            endMethod()\n            emitEmptyLine()\n        }\n    }\n\n    @Throws(IOException::class)\n    private fun emitInsertObjectToRealmMethod(writer: JavaWriter) {\n        writer.apply {\n            emitAnnotation(\"Override\")\n            beginMethod(\n                    \"long\",\n                    \"insert\",\n                    EnumSet.of(Modifier.PUBLIC),\n                    \"Realm\", \"realm\", \"RealmModel\", \"object\", \"Map<RealmModel, Long>\", \"cache\")\n\n                if (embeddedClass.contains(false)) {\n                    emitSingleLineComment(\"This cast is correct because obj is either\")\n                    emitSingleLineComment(\"generated by RealmProxy or the original type extending directly from RealmObject\")\n                    emitStatement(\"@SuppressWarnings(\\\"unchecked\\\") Class<RealmModel> clazz = (Class<RealmModel>) ((object instanceof RealmObjectProxy) ? object.getClass().getSuperclass() : object.getClass())\")\n                    emitEmptyLine()\n                    emitMediatorSwitch(writer, false, { i: Int ->\n                        if (embeddedClass[i]) {\n                            emitEmbeddedObjectsCannotBeCopiedException(writer)\n                        } else {\n                            emitStatement(\"return %s.insert(realm, (%s) object, cache)\", qualifiedProxyClasses[i], qualifiedModelClasses[i])\n                        }\n                    })\n                } else {\n                    emitEmbeddedObjectsCannotBeCopiedException(writer)\n                }\n\n            endMethod()\n            emitEmptyLine()\n        }\n    }\n\n    @Throws(IOException::class)\n    private fun emitInsertOrUpdateObjectToRealmMethod(writer: JavaWriter) {\n        writer.apply {\n            emitAnnotation(\"Override\")\n            beginMethod(\n                    \"long\",\n                    \"insertOrUpdate\",\n                    EnumSet.of(Modifier.PUBLIC),\n                    \"Realm\", \"realm\", \"RealmModel\", \"obj\", \"Map<RealmModel, Long>\", \"cache\")\n\n            if (embeddedClass.contains(false)) {\n                emitSingleLineComment(\"This cast is correct because obj is either\")\n                emitSingleLineComment(\"generated by RealmProxy or the original type extending directly from RealmObject\")\n                emitStatement(\"@SuppressWarnings(\\\"unchecked\\\") Class<RealmModel> clazz = (Class<RealmModel>) ((obj instanceof RealmObjectProxy) ? obj.getClass().getSuperclass() : obj.getClass())\")\n                emitEmptyLine()\n                emitMediatorSwitch(writer, false, { i: Int ->\n                    if (embeddedClass[i]) {\n                        emitEmbeddedObjectsCannotBeCopiedException(writer)\n                    } else {\n                        emitStatement(\"return %s.insertOrUpdate(realm, (%s) obj, cache)\", qualifiedProxyClasses[i], qualifiedModelClasses[i])\n                    }\n                })\n            } else {\n                emitEmbeddedObjectsCannotBeCopiedException(writer)\n            }\n            endMethod()\n            emitEmptyLine()\n        }\n    }\n\n    @Throws(IOException::class)\n    private fun emitInsertOrUpdateListToRealmMethod(writer: JavaWriter) {\n        writer.apply {\n            emitAnnotation(\"Override\")\n            beginMethod(\n                    \"void\",\n                    \"insertOrUpdate\",\n                    EnumSet.of(Modifier.PUBLIC),\n                    \"Realm\", \"realm\", \"Collection<? extends RealmModel>\", \"objects\")\n\n            if (embeddedClass.contains(false)) {\n                emitStatement(\"Iterator<? extends RealmModel> iterator = objects.iterator()\")\n                emitStatement(\"RealmModel object = null\")\n                emitStatement(\"Map<RealmModel, Long> cache = new HashMap<RealmModel, Long>(objects.size())\")\n\n                beginControlFlow(\"if (iterator.hasNext())\")\n                emitSingleLineComment(\" access the first element to figure out the clazz for the routing below\")\n                emitStatement(\"object = iterator.next()\")\n                emitSingleLineComment(\"This cast is correct because obj is either\")\n                emitSingleLineComment(\"generated by RealmProxy or the original type extending directly from RealmObject\")\n                emitStatement(\"@SuppressWarnings(\\\"unchecked\\\") Class<RealmModel> clazz = (Class<RealmModel>) ((object instanceof RealmObjectProxy) ? object.getClass().getSuperclass() : object.getClass())\")\n                emitEmptyLine()\n\n                emitMediatorSwitch(writer, false) { i: Int ->\n                    if (embeddedClass[i]) {\n                        emitEmbeddedObjectsCannotBeCopiedException(writer)\n                    } else {\n                        emitStatement(\"%s.insertOrUpdate(realm, (%s) object, cache)\", qualifiedProxyClasses[i], qualifiedModelClasses[i])\n                    }\n                }\n\n                beginControlFlow(\"if (iterator.hasNext())\")\n                emitMediatorSwitch(writer, false) { i: Int ->\n                    if (embeddedClass[i]) {\n                        emitEmbeddedObjectsCannotBeCopiedException(writer)\n                    } else {\n                        emitStatement(\"%s.insertOrUpdate(realm, iterator, cache)\", qualifiedProxyClasses[i])\n                    }\n                }\n                endControlFlow()\n                endControlFlow()\n            } else {\n                emitEmbeddedObjectsCannotBeCopiedException(writer)\n            }\n\n            endMethod()\n            emitEmptyLine()\n        }\n    }\n\n    private fun emitEmbeddedObjectsCannotBeCopiedException(writer: JavaWriter) {\n        writer.apply {\n            emitStatement(\"throw new IllegalArgumentException(\\\"Embedded objects cannot be copied into Realm by themselves. They need to be attached to a parent object\\\")\")\n        }\n    }\n\n    @Throws(IOException::class)\n    private fun emitInsertListToRealmMethod(writer: JavaWriter) {\n        writer.apply {\n            emitAnnotation(\"Override\")\n            beginMethod(\n                    \"void\",\n                    \"insert\",\n                    EnumSet.of(Modifier.PUBLIC),\n                    \"Realm\", \"realm\", \"Collection<? extends RealmModel>\", \"objects\")\n\n                if (embeddedClass.contains(false)) {\n                    emitStatement(\"Iterator<? extends RealmModel> iterator = objects.iterator()\")\n                    emitStatement(\"RealmModel object = null\")\n                    emitStatement(\"Map<RealmModel, Long> cache = new HashMap<RealmModel, Long>(objects.size())\")\n\n                    beginControlFlow(\"if (iterator.hasNext())\")\n                            .emitSingleLineComment(\" access the first element to figure out the clazz for the routing below\")\n                            .emitStatement(\"object = iterator.next()\")\n                            .emitSingleLineComment(\"This cast is correct because obj is either\")\n                            .emitSingleLineComment(\"generated by RealmProxy or the original type extending directly from RealmObject\")\n                            .emitStatement(\"@SuppressWarnings(\\\"unchecked\\\") Class<RealmModel> clazz = (Class<RealmModel>) ((object instanceof RealmObjectProxy) ? object.getClass().getSuperclass() : object.getClass())\")\n                            .emitEmptyLine()\n\n                    emitMediatorSwitch(writer, false, { i: Int ->\n                        if (embeddedClass[i]) {\n                            emitEmbeddedObjectsCannotBeCopiedException(writer)\n                        } else {\n                            emitStatement(\"%s.insert(realm, (%s) object, cache)\", qualifiedProxyClasses[i], qualifiedModelClasses[i])\n                        }\n                    })\n\n                    beginControlFlow(\"if (iterator.hasNext())\")\n                    emitMediatorSwitch(writer, false, { i: Int ->\n                        if (embeddedClass[i]) {\n                            emitEmbeddedObjectsCannotBeCopiedException(writer)\n                        } else {\n                            emitStatement(\"%s.insert(realm, iterator, cache)\", qualifiedProxyClasses[i])\n                        }\n                    })\n                    endControlFlow()\n                    endControlFlow()\n\n                } else {\n                    emitEmbeddedObjectsCannotBeCopiedException(writer)\n                }\n            endMethod()\n            emitEmptyLine()    \n        }\n    }\n\n    @Throws(IOException::class)\n    private fun emitCreteOrUpdateUsingJsonObject(writer: JavaWriter) {\n        writer.apply {\n            emitAnnotation(\"Override\")\n            beginMethod(\n                    \"<E extends RealmModel> E\",\n                    \"createOrUpdateUsingJsonObject\",\n                    EnumSet.of(Modifier.PUBLIC),\n                    Arrays.asList(\"Class<E>\", \"clazz\", \"Realm\", \"realm\", \"JSONObject\", \"json\", \"boolean\", \"update\"),\n                    Arrays.asList(\"JSONException\")\n            )\n                emitMediatorShortCircuitSwitch(writer, emitStatement = { i: Int ->\n                    if (!embeddedClass[i]) {\n                        emitStatement(\"return clazz.cast(%s.createOrUpdateUsingJsonObject(realm, json, update))\", qualifiedProxyClasses[i])\n                    } else {\n                        emitStatement(\"throw new IllegalArgumentException(\\\"Importing embedded classes from JSON without a parent is not allowed\\\")\")\n                    }\n                })\n            endMethod()\n            emitEmptyLine()\n        }\n    }\n\n    @Throws(IOException::class)\n    private fun emitCreateUsingJsonStream(writer: JavaWriter) {\n        writer.apply {\n            emitAnnotation(\"Override\")\n            beginMethod(\n                    \"<E extends RealmModel> E\",\n                    \"createUsingJsonStream\",\n                    EnumSet.of(Modifier.PUBLIC),\n                    Arrays.asList(\"Class<E>\", \"clazz\", \"Realm\", \"realm\", \"JsonReader\", \"reader\"),\n                    Arrays.asList(\"java.io.IOException\")\n            )\n                emitMediatorShortCircuitSwitch(writer, emitStatement = { i: Int ->\n                    if (!embeddedClass[i]) {\n                        emitStatement(\"return clazz.cast(%s.createUsingJsonStream(realm, reader))\", qualifiedProxyClasses[i])\n                    } else {\n                        emitStatement(\"throw new IllegalArgumentException(\\\"Importing embedded classes from JSON without a parent is not allowed\\\")\")\n                    }\n                })\n            endMethod()\n            emitEmptyLine()\n        }\n    }\n\n    @Throws(IOException::class)\n    private fun emitCreateDetachedCopyMethod(writer: JavaWriter) {\n        writer.apply {\n            emitAnnotation(\"Override\")\n            beginMethod(\n                    \"<E extends RealmModel> E\",\n                    \"createDetachedCopy\",\n                    EnumSet.of(Modifier.PUBLIC),\n                    \"E\", \"realmObject\", \"int\", \"maxDepth\", \"Map<RealmModel, RealmObjectProxy.CacheData<RealmModel>>\", \"cache\"\n            )\n                emitSingleLineComment(\"This cast is correct because obj is either\")\n                emitSingleLineComment(\"generated by RealmProxy or the original type extending directly from RealmObject\")\n                emitStatement(\"@SuppressWarnings(\\\"unchecked\\\") Class<E> clazz = (Class<E>) realmObject.getClass().getSuperclass()\")\n                emitEmptyLine()\n                emitMediatorShortCircuitSwitch(writer, false, { i: Int ->\n                    emitStatement(\"return clazz.cast(%s.createDetachedCopy((%s) realmObject, 0, maxDepth, cache))\",\n                            qualifiedProxyClasses[i], qualifiedModelClasses[i])\n                })\n            endMethod()\n            emitEmptyLine()   \n        }\n    }\n\n    @Throws(IOException::class)\n    private fun emitIsEmbeddedMethod(writer: JavaWriter) {\n        writer.apply {\n            emitAnnotation(\"Override\")\n            beginMethod(\n                    \"<E extends RealmModel> boolean\",\n                    \"isEmbedded\",\n                    EnumSet.of(Modifier.PUBLIC),\n                    \"Class<E>\", \"clazz\"\n            )\n            emitMediatorShortCircuitSwitch(writer, false, { i: Int ->\n                emitStatement(\"return %s\", if (embeddedClass[i]) \"true\" else \"false\")\n            })\n            endMethod()\n            emitEmptyLine()\n        }\n    }\n\n    @Throws(IOException::class)\n    private fun emitUpdateEmbeddedObjectMethod(writer: JavaWriter) {\n        writer.apply {\n            emitAnnotation(\"Override\")\n            beginMethod(\n                    \"<E extends RealmModel> void\",\n                    \"updateEmbeddedObject\",\n                    EnumSet.of(Modifier.PUBLIC),\n                    \"Realm\", \"realm\",\n                    \"E\", \"unmanagedObject\",\n                    \"E\", \"managedObject\",\n                    \"Map<RealmModel, RealmObjectProxy>\", \"cache\",\n                    \"Set<ImportFlag>\", \"flags\"\n            )\n\n            emitSingleLineComment(\"This cast is correct because obj is either\")\n            emitSingleLineComment(\"generated by RealmProxy or the original type extending directly from RealmObject\")\n            emitStatement(\"@SuppressWarnings(\\\"unchecked\\\") Class<E> clazz = (Class<E>) managedObject.getClass().getSuperclass()\")\n            emitEmptyLine()\n            emitMediatorSwitch(writer, false) { i: Int ->\n                if (embeddedClass[i]) {\n                    emitStatement(\"%1\\$s.updateEmbeddedObject(realm, (%2\\$s) unmanagedObject, (%2\\$s) managedObject, cache, flags)\", qualifiedProxyClasses[i], qualifiedModelClasses[i])\n                } else {\n                    emitStatement(\"throw getNotEmbeddedClassException(\\\"%s\\\")\", qualifiedModelClasses[i])\n                }\n            }\n            endMethod()\n            emitEmptyLine()\n        }\n    }\n\n\n    // Emits the control flow for selecting the appropriate proxy class based on the model class\n    // Currently it is just if..else, which is inefficient for large amounts amounts of model classes.\n    // Consider switching to HashMap or similar.\n    @Throws(IOException::class)\n    private fun emitMediatorSwitch(writer: JavaWriter, nullPointerCheck: Boolean, emitStatement: (index: Int) -> Unit) {\n        writer.apply {\n            if (nullPointerCheck) {\n                emitStatement(\"checkClass(clazz)\")\n                emitEmptyLine()\n            }\n            if (qualifiedModelClasses.isEmpty()) {\n                emitStatement(\"throw getMissingProxyClassException(clazz)\")\n            } else {\n                beginControlFlow(\"if (clazz.equals(%s.class))\", qualifiedModelClasses[0])\n                emitStatement(0)\n                for (i in 1 until qualifiedModelClasses.size) {\n                    nextControlFlow(\"else if (clazz.equals(%s.class))\", qualifiedModelClasses[i])\n                    emitStatement(i)\n                }\n                nextControlFlow(\"else\")\n                emitStatement(\"throw getMissingProxyClassException(clazz)\")\n                endControlFlow()\n            }\n        }\n    }\n\n    @Throws(IOException::class)\n    private fun emitMediatorShortCircuitSwitch(writer: JavaWriter, nullPointerCheck: Boolean = true, emitStatement: (index: Int) -> Unit) {\n        writer.apply {\n            if (nullPointerCheck) {\n                emitStatement(\"checkClass(clazz)\")\n                emitEmptyLine()\n            }\n            for (i in qualifiedModelClasses.indices) {\n                beginControlFlow(\"if (clazz.equals(%s.class))\", qualifiedModelClasses[i])\n                emitStatement(i)\n                endControlFlow()\n            }\n            emitStatement(\"throw getMissingProxyClassException(clazz)\")\n        }\n    }\n\n    @Throws(IOException::class)\n    private fun emitMediatorInverseShortCircuitSwitch(writer: JavaWriter, nullPointerCheck: Boolean = true, emitStatement: (index: Int) -> Unit) {\n        writer.apply {\n            if (nullPointerCheck) {\n                emitStatement(\"checkClassName(className)\")\n                emitEmptyLine()\n            }\n            for (i in qualifiedModelClasses.indices) {\n                beginControlFlow(\"if (className.equals(\\\"%s\\\"))\", internalClassNames[i])\n                emitStatement(i)\n                endControlFlow()\n            }\n            emitStatement(\"throw getMissingProxyClassException(className)\")\n        }\n    }\n\n}\n"
  },
  {
    "path": "realm/realm-annotations-processor/src/main/java/io/realm/processor/RealmVersionChecker.kt",
    "content": "/*\n * Copyright 2019 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\npackage io.realm.processor\n\nimport java.io.BufferedReader\nimport java.io.IOException\nimport java.io.InputStreamReader\nimport java.net.HttpURLConnection\nimport java.net.URL\n\nimport javax.annotation.processing.ProcessingEnvironment\nimport javax.tools.Diagnostic\n\n\nclass RealmVersionChecker private constructor(private val processingEnvironment: ProcessingEnvironment) {\n\n    private val REALM_ANDROID_DOWNLOAD_URL = \"https://static.realm.io/downloads/java/latest\"\n    private val VERSION_URL = \"https://static.realm.io/update/java?\"\n    private val REALM_VERSION = Version.VERSION\n    private val REALM_VERSION_PATTERN = \"\\\\d+\\\\.\\\\d+\\\\.\\\\d+\"\n    private val READ_TIMEOUT = 2000\n    private val CONNECT_TIMEOUT = 4000\n\n    fun executeRealmVersionUpdate() {\n        val backgroundThread = Thread(Runnable { launchRealmCheck() })\n        backgroundThread.start()\n        try {\n            backgroundThread.join((CONNECT_TIMEOUT + READ_TIMEOUT).toLong())\n        } catch (ignore: InterruptedException) {\n            // We ignore this exception on purpose not to break the build system if this class fails\n        }\n    }\n\n    private fun launchRealmCheck() {\n        //Check Realm version server\n        val latestVersionStr = checkLatestVersion()\n        if (latestVersionStr != REALM_VERSION) {\n            printMessage(\"Version $latestVersionStr of Realm is now available: $REALM_ANDROID_DOWNLOAD_URL\")\n        }\n    }\n\n    private fun checkLatestVersion(): String {\n        var result = REALM_VERSION\n        try {\n            val url = URL(VERSION_URL + REALM_VERSION)\n            val conn = url.openConnection() as HttpURLConnection\n            conn.connectTimeout = CONNECT_TIMEOUT\n            conn.readTimeout = READ_TIMEOUT\n            val rd = BufferedReader(InputStreamReader(conn.inputStream))\n            val latestVersion = rd.readLine()\n            // if the obtained string does not match the pattern, we are in a separate network.\n            if (latestVersion.matches(REALM_VERSION_PATTERN.toRegex())) {\n                result = latestVersion\n            }\n            rd.close()\n        } catch (e: IOException) {\n            // We ignore this exception on purpose not to break the build system if this class fails\n        }\n\n        return result\n    }\n\n    private fun printMessage(message: String) {\n        processingEnvironment.messager.printMessage(Diagnostic.Kind.OTHER, message)\n    }\n\n    companion object {\n        private var instance: RealmVersionChecker? = null\n        fun getInstance(env: ProcessingEnvironment): RealmVersionChecker {\n            if (instance == null) {\n                synchronized(RealmVersionChecker::class.java) {\n                    if (instance == null) {\n                        instance = RealmVersionChecker(env)\n                    }\n                }\n            }\n            return instance!!\n        }\n    }\n}\n"
  },
  {
    "path": "realm/realm-annotations-processor/src/main/java/io/realm/processor/TypeMirrors.kt",
    "content": "/*\n * Copyright 2019 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@file:JvmName(\"TypeMirrors\")\npackage io.realm.processor\n\nimport org.bson.types.Decimal128\nimport org.bson.types.ObjectId\nimport java.util.*\nimport javax.annotation.processing.ProcessingEnvironment\nimport javax.lang.model.element.VariableElement\nimport javax.lang.model.type.DeclaredType\nimport javax.lang.model.type.TypeKind\nimport javax.lang.model.type.TypeMirror\n\n/**\n * This class provides [TypeMirror] instances used in annotation processor.\n *\n * WARNING: Comparing type mirrors using either `==` or `equal()` can break when using incremental\n * annotation processing. Always use `Types.isSameType()` instead when comparing them.\n */\nclass TypeMirrors(env: ProcessingEnvironment) {\n\n    @JvmField val STRING_MIRROR: TypeMirror\n    @JvmField val BINARY_MIRROR: TypeMirror\n    @JvmField val BINARY_NON_PRIMITIVE_MIRROR: TypeMirror\n    @JvmField val BOOLEAN_MIRROR: TypeMirror\n    @JvmField val LONG_MIRROR: TypeMirror\n    @JvmField val INTEGER_MIRROR: TypeMirror\n    @JvmField val SHORT_MIRROR: TypeMirror\n    @JvmField val BYTE_MIRROR: TypeMirror\n    @JvmField val DOUBLE_MIRROR: TypeMirror\n    @JvmField val FLOAT_MIRROR: TypeMirror\n    @JvmField val DATE_MIRROR: TypeMirror\n    @JvmField val DECIMAL128_MIRROR: TypeMirror\n    @JvmField val OBJECT_ID_MIRROR: TypeMirror\n    @JvmField val UUID_MIRROR: TypeMirror\n    @JvmField val MIXED_MIRROR: TypeMirror\n\n    @JvmField val PRIMITIVE_LONG_MIRROR: TypeMirror\n    @JvmField val PRIMITIVE_INT_MIRROR: TypeMirror\n    @JvmField val PRIMITIVE_SHORT_MIRROR: TypeMirror\n    @JvmField val PRIMITIVE_BYTE_MIRROR: TypeMirror\n\n    init {\n        val typeUtils = env.typeUtils\n        val elementUtils = env.elementUtils\n\n        STRING_MIRROR = elementUtils.getTypeElement(\"java.lang.String\").asType()\n        BINARY_MIRROR = typeUtils.getArrayType(typeUtils.getPrimitiveType(TypeKind.BYTE))\n        BINARY_NON_PRIMITIVE_MIRROR = typeUtils.getArrayType(elementUtils.getTypeElement(Byte::class.javaObjectType.name).asType())\n        BOOLEAN_MIRROR = elementUtils.getTypeElement(Boolean::class.javaObjectType.name).asType()\n        LONG_MIRROR = elementUtils.getTypeElement(Long::class.javaObjectType.name).asType()\n        INTEGER_MIRROR = elementUtils.getTypeElement(Int::class.javaObjectType.name).asType()\n        SHORT_MIRROR = elementUtils.getTypeElement(Short::class.javaObjectType.name).asType()\n        BYTE_MIRROR = elementUtils.getTypeElement(Byte::class.javaObjectType.name).asType()\n        DOUBLE_MIRROR = elementUtils.getTypeElement(Double::class.javaObjectType.name).asType()\n        FLOAT_MIRROR = elementUtils.getTypeElement(Float::class.javaObjectType.name).asType()\n        DATE_MIRROR = elementUtils.getTypeElement(Date::class.javaObjectType.name).asType()\n        DECIMAL128_MIRROR = elementUtils.getTypeElement(Decimal128::class.javaObjectType.name).asType()\n        OBJECT_ID_MIRROR = elementUtils.getTypeElement(ObjectId::class.javaObjectType.name).asType()\n        UUID_MIRROR = elementUtils.getTypeElement(UUID::class.javaObjectType.name).asType()\n        MIXED_MIRROR = elementUtils.getTypeElement(\"io.realm.RealmAny\").asType()\n\n        PRIMITIVE_LONG_MIRROR = typeUtils.getPrimitiveType(TypeKind.LONG)\n        PRIMITIVE_INT_MIRROR = typeUtils.getPrimitiveType(TypeKind.INT)\n        PRIMITIVE_SHORT_MIRROR = typeUtils.getPrimitiveType(TypeKind.SHORT)\n        PRIMITIVE_BYTE_MIRROR = typeUtils.getPrimitiveType(TypeKind.BYTE)\n    }\n\n    companion object {\n        /**\n         * @return the [TypeMirror] of the elements in `RealmList`.\n         */\n        @JvmStatic\n        fun getRealmListElementTypeMirror(field: VariableElement): TypeMirror? {\n            if (!Utils.isRealmList(field)) {\n                return null\n            }\n            return getTypeArgument(field)\n        }\n\n        /**\n         * @return the [TypeMirror] of the elements in `RealmDictionary`.\n         */\n        @JvmStatic\n        fun getRealmDictionaryElementTypeMirror(field: VariableElement): TypeMirror? {\n            if (!Utils.isRealmDictionary(field)) {\n                return null\n            }\n            return getTypeArgument(field)\n        }\n\n        /**\n         * @return the [TypeMirror] of the elements in `RealmSet`.\n         */\n        @JvmStatic\n        fun getRealmSetElementTypeMirror(field: VariableElement): TypeMirror? {\n            if (!Utils.isRealmSet(field)) {\n                return null\n            }\n            return getTypeArgument(field)\n        }\n\n        private fun getTypeArgument(field: VariableElement): TypeMirror? {\n            val typeArguments = (field.asType() as DeclaredType).typeArguments\n            return if (typeArguments.isNotEmpty()) typeArguments[0] else null\n        }\n    }\n}\n"
  },
  {
    "path": "realm/realm-annotations-processor/src/main/java/io/realm/processor/Utils.kt",
    "content": "/*\n * Copyright 2019 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// Most of com.sun.tools.javac content has been marked internal with JDK 9\n@file:Suppress(\"JAVA_MODULE_DOES_NOT_EXPORT_PACKAGE\")\n\npackage io.realm.processor\n\nimport io.realm.annotations.RealmNamingPolicy\nimport io.realm.processor.nameconverter.*\nimport javax.annotation.processing.Messager\nimport javax.annotation.processing.ProcessingEnvironment\nimport javax.lang.model.element.*\nimport javax.lang.model.type.DeclaredType\nimport javax.lang.model.type.ReferenceType\nimport javax.lang.model.type.TypeKind\nimport javax.lang.model.type.TypeMirror\nimport javax.lang.model.util.Types\nimport javax.tools.Diagnostic\n\n/**\n * Utility methods working with the Realm processor.\n */\nobject Utils {\n\n    private lateinit var typeUtils: Types\n    private lateinit var messager: Messager\n    private lateinit var realmInteger: TypeMirror\n    private lateinit var realmAny: TypeMirror\n    private lateinit var realmList: DeclaredType\n    private lateinit var realmResults: DeclaredType\n    private lateinit var markerInterface: DeclaredType\n    private lateinit var realmModel: TypeMirror\n    private lateinit var realmDictionary: DeclaredType\n    private lateinit var realmSet: DeclaredType\n\n    fun initialize(env: ProcessingEnvironment) {\n        val elementUtils = env.elementUtils\n        typeUtils = env.typeUtils\n        messager = env.messager\n        realmInteger = elementUtils.getTypeElement(\"io.realm.MutableRealmInteger\").asType()\n        realmAny = elementUtils.getTypeElement(\"io.realm.RealmAny\").asType()\n        realmList = typeUtils.getDeclaredType(elementUtils.getTypeElement(\"io.realm.RealmList\"), typeUtils.getWildcardType(null, null))\n        realmResults = typeUtils.getDeclaredType(env.elementUtils.getTypeElement(\"io.realm.RealmResults\"), typeUtils.getWildcardType(null, null))\n        realmModel = elementUtils.getTypeElement(\"io.realm.RealmModel\").asType()\n        markerInterface = typeUtils.getDeclaredType(elementUtils.getTypeElement(\"io.realm.RealmModel\"))\n        realmDictionary = typeUtils.getDeclaredType(elementUtils.getTypeElement(\"io.realm.RealmDictionary\"), typeUtils.getWildcardType(null, null))\n        realmSet = typeUtils.getDeclaredType(elementUtils.getTypeElement(\"io.realm.RealmSet\"), typeUtils.getWildcardType(null, null))\n    }\n\n    /**\n     * @return true if the given element is the default public no arg constructor for a class.\n     */\n    fun isDefaultConstructor(constructor: Element): Boolean {\n        return if (constructor.modifiers.contains(Modifier.PUBLIC)) {\n            (constructor as ExecutableElement).parameters.isEmpty()\n        } else false\n    }\n\n    fun getProxyClassSimpleName(field: VariableElement): SimpleClassName {\n        return if (typeUtils.isAssignable(field.asType(), realmList)) {\n            getProxyClassName(getGenericTypeQualifiedName(field)!!)\n        } else {\n            getProxyClassName(getFieldTypeQualifiedName(field))\n        }\n    }\n\n    fun getDictionaryGenericProxyClassSimpleName(field: VariableElement): SimpleClassName {\n        return if (typeUtils.isAssignable(field.asType(), realmDictionary)) {\n            getProxyClassName(getGenericTypeQualifiedName(field)!!)\n        } else {\n            getProxyClassName(getFieldTypeQualifiedName(field))\n        }\n    }\n\n    fun getSetGenericProxyClassSimpleName(field: VariableElement): SimpleClassName {\n        return if (typeUtils.isAssignable(field.asType(), realmSet)) {\n            getProxyClassName(getGenericTypeQualifiedName(field)!!)\n        } else {\n            getProxyClassName(getFieldTypeQualifiedName(field))\n        }\n    }\n\n    fun getModelClassQualifiedName(field: VariableElement): QualifiedClassName {\n        return if (typeUtils.isAssignable(field.asType(), realmList)) {\n            getGenericTypeQualifiedName(field)!!\n        } else {\n            getFieldTypeQualifiedName(field)\n        }\n    }\n\n    fun getDictionaryGenericModelClassQualifiedName(field: VariableElement): QualifiedClassName {\n        return if (typeUtils.isAssignable(field.asType(), realmDictionary)) {\n            getGenericTypeQualifiedName(field)!!\n        } else {\n            getFieldTypeQualifiedName(field)\n        }\n    }\n\n    fun getSetGenericModelClassQualifiedName(field: VariableElement): QualifiedClassName {\n        return if (typeUtils.isAssignable(field.asType(), realmSet)) {\n            getGenericTypeQualifiedName(field)!!\n        } else {\n            getFieldTypeQualifiedName(field)\n        }\n    }\n\n    /**\n     * @return the proxy class name for a given clazz\n     */\n    fun getProxyClassName(className: QualifiedClassName): SimpleClassName {\n        return SimpleClassName(className.toString().replace(\".\", \"_\") + Constants.PROXY_SUFFIX)\n    }\n\n    /**\n     * @return `true` if a field is of type \"java.lang.String\", `false` otherwise.\n     * @throws IllegalArgumentException if the field is `null`.\n     */\n    fun isString(field: VariableElement?): Boolean {\n        if (field == null) {\n            throw IllegalArgumentException(\"Argument 'field' cannot be null.\")\n        }\n        return getFieldTypeQualifiedName(field).toString() == \"java.lang.String\"\n    }\n\n    /**\n     * @return `true` if a field is of type \"org.bson.types.ObjectId\", `false` otherwise.\n     * @throws IllegalArgumentException if the field is `null`.\n     */\n    fun isObjectId(field: VariableElement?): Boolean {\n        if (field == null) {\n            throw IllegalArgumentException(\"Argument 'field' cannot be null.\")\n        }\n        return getFieldTypeQualifiedName(field).toString() == \"org.bson.types.ObjectId\"\n    }\n\n    /**\n     * @return `true` if a field is of type \"java.util.UUID\", `false` otherwise.\n     * @throws IllegalArgumentException if the field is `null`.\n     */\n    fun isUUID(field: VariableElement?): Boolean {\n        if (field == null) {\n            throw IllegalArgumentException(\"Argument 'field' cannot be null.\")\n        }\n        return getFieldTypeQualifiedName(field).toString() == \"java.util.UUID\"\n    }\n\n    /**\n     * @return `true` if a field is a primitive type, `false` otherwise.\n     * @throws IllegalArgumentException if the typeString is `null`.\n     */\n    fun isPrimitiveType(typeString: String): Boolean {\n        return typeString == \"byte\" || typeString == \"short\" || typeString == \"int\" ||\n                typeString == \"long\" || typeString == \"float\" || typeString == \"double\" ||\n                typeString == \"boolean\" || typeString == \"char\"\n    }\n\n    fun isPrimitiveType(type: QualifiedClassName): Boolean {\n        return isPrimitiveType(type.toString())\n    }\n\n    /**\n     * @return `true` if a field is a boxed type, `false` otherwise.\n     * @throws IllegalArgumentException if the typeString is `null`.\n     */\n    fun isBoxedType(typeString: String?): Boolean {\n        if (typeString == null) {\n            throw IllegalArgumentException(\"Argument 'typeString' cannot be null.\")\n        }\n        return typeString == Byte::class.javaObjectType.name || typeString == Short::class.javaObjectType.name ||\n                typeString == Int::class.javaObjectType.name || typeString == Long::class.javaObjectType.name ||\n                typeString == Float::class.javaObjectType.name || typeString == Double::class.javaObjectType.name ||\n                typeString == Boolean::class.javaObjectType.name\n    }\n\n    /**\n     * @return `true` if a field is a type of primitive types, `false` otherwise.\n     * @throws IllegalArgumentException if the field is `null`.\n     */\n    fun isPrimitiveType(field: VariableElement?): Boolean {\n        if (field == null) {\n            throw IllegalArgumentException(\"Argument 'field' cannot be null.\")\n        }\n        return field.asType().kind.isPrimitive\n    }\n\n    /**\n     * @return `true` if a field is of type \"byte[]\", `false` otherwise.\n     * @throws IllegalArgumentException if the field is `null`.\n     */\n    fun isByteArray(field: VariableElement?): Boolean {\n        if (field == null) {\n            throw IllegalArgumentException(\"Argument 'field' cannot be null.\")\n        }\n        return getFieldTypeQualifiedName(field).toString() == \"byte[]\"\n    }\n\n    /**\n     * @return `true` if a given field type string is \"java.lang.String\", `false` otherwise.\n     * @throws IllegalArgumentException if the fieldType is `null`.\n     */\n    fun isString(fieldType: String?): Boolean {\n        if (fieldType == null) {\n            throw IllegalArgumentException(\"Argument 'fieldType' cannot be null.\")\n        }\n        return String::class.java.name == fieldType\n    }\n\n    /**\n     * @return `true` if a given type implement `RealmModel`, `false` otherwise.\n     */\n    fun isImplementingMarkerInterface(classElement: Element): Boolean {\n        return typeUtils.isAssignable(classElement.asType(), markerInterface)\n    }\n\n    /**\n     * @return `true` if a given field type is `MutableRealmInteger`, `false` otherwise.\n     */\n    fun isMutableRealmInteger(field: VariableElement): Boolean {\n        return typeUtils.isAssignable(field.asType(), realmInteger)\n    }\n\n    /**\n     * @return `true` if a given field type is `RealmAny`, `false` otherwise.\n     */\n    fun isRealmAny(field: VariableElement): Boolean {\n        return typeUtils.isAssignable(field.asType(), realmAny)\n    }\n\n    /**\n     * @return `true` if a given field type is `RealmList`, `false` otherwise.\n     */\n    fun isRealmList(field: VariableElement): Boolean {\n        return typeUtils.isAssignable(field.asType(), realmList)\n    }\n\n    /**\n     * @return `true` if a given field type is `RealmDictionary`, `false` otherwise.\n     */\n    fun isRealmDictionary(field: VariableElement): Boolean {\n        return typeUtils.isAssignable(field.asType(), realmDictionary)\n    }\n\n    /**\n     * @return `true` if a given field type is `RealmDictionary` and its element type is value type,\n     * `false` otherwise.\n     */\n    fun isRealmValueDictionary(field: VariableElement): Boolean {\n        val elementTypeMirror = TypeMirrors.getRealmDictionaryElementTypeMirror(field) ?: return false\n        return !isRealmModel(elementTypeMirror) && !isRealmAny(elementTypeMirror)\n    }\n\n    /**\n     * @return `true` if a given field type is `RealmDictionary<RealmModel>`, `false` otherwise.\n     */\n    fun isRealmModelDictionary(field: VariableElement): Boolean {\n        val elementTypeMirror = TypeMirrors.getRealmDictionaryElementTypeMirror(field) ?: return false\n        return isRealmModel(elementTypeMirror)\n    }\n\n    /**\n     * @return `true` if a given field type is `RealmDictionary` and its element type is `RealmAny`,\n     * `false` otherwise.\n     */\n    fun isRealmAnyDictionary(field: VariableElement): Boolean {\n        val elementTypeMirror = TypeMirrors.getRealmDictionaryElementTypeMirror(field) ?: return false\n        return isRealmAny(elementTypeMirror)\n    }\n\n    /**\n     * @return `true` if a given field type is `RealmSet`, `false` otherwise.\n     */\n    fun isRealmSet(field: VariableElement): Boolean {\n        return typeUtils.isAssignable(field.asType(), realmSet)\n    }\n\n    /**\n     * @return `true` if a given field type is `RealmSet<RealmModel>`, `false` otherwise.\n     */\n    fun isRealmModelSet(field: VariableElement): Boolean {\n        val elementTypeMirror = TypeMirrors.getRealmSetElementTypeMirror(field) ?: return false\n        return isRealmModel(elementTypeMirror)\n    }\n\n    /**\n     * @return `true` if a given field type is `RealmSet` and its element type is value type,\n     * `false` otherwise.\n     */\n    fun isRealmValueSet(field: VariableElement): Boolean {\n        val elementTypeMirror = TypeMirrors.getRealmSetElementTypeMirror(field) ?: return false\n        return !isRealmModel(elementTypeMirror) && !isRealmAny(elementTypeMirror)\n    }\n\n    /**\n     * @return `true` if a given field type is `RealmSet<RealmAny>`, `false` otherwise.\n     */\n    fun isRealmAnySet(field: VariableElement): Boolean {\n        val elementTypeMirror = TypeMirrors.getRealmSetElementTypeMirror(field) ?: return false\n        return isRealmAny(elementTypeMirror)\n    }\n\n    /**\n     * @param field [VariableElement] of a value list field.\n     * @return element type of the list field.\n     */\n    fun getValueListFieldType(field: VariableElement): Constants.RealmFieldType {\n        val elementTypeMirror = TypeMirrors.getRealmListElementTypeMirror(field)\n        return Constants.LIST_ELEMENT_TYPE_TO_REALM_TYPES[elementTypeMirror!!.toString()]\n                ?: throw IllegalArgumentException(\"Invalid type mirror '$elementTypeMirror' for field '$field'\")\n    }\n\n    /**\n     * @param field [VariableElement] of a value dictionary field.\n     * @return element type of the dictionary field.\n     */\n    fun getValueDictionaryFieldType(field: VariableElement): Constants.RealmFieldType {\n        val elementTypeMirror = TypeMirrors.getRealmDictionaryElementTypeMirror(field)\n        return Constants.DICTIONARY_ELEMENT_TYPE_TO_REALM_TYPES[elementTypeMirror!!.toString()]\n                ?: throw IllegalArgumentException(\"Invalid type mirror '$elementTypeMirror' for field '$field'\")\n    }\n\n    /**\n     * @param field [VariableElement] of a value set field.\n     * @return element type of the set field.\n     */\n    fun getValueSetFieldType(field: VariableElement): Constants.RealmFieldType {\n        val elementTypeMirror = TypeMirrors.getRealmSetElementTypeMirror(field)\n        return Constants.SET_ELEMENT_TYPE_TO_REALM_TYPES[elementTypeMirror!!.toString()]\n                ?: throw IllegalArgumentException(\"Invalid type mirror '$elementTypeMirror' for field '$field'\")\n    }\n\n    /**\n     * @return `true` if a given field type is `RealmList` and its element type is `RealmObject`,\n     * `false` otherwise.\n     */\n    fun isRealmModelList(field: VariableElement): Boolean {\n        val elementTypeMirror = TypeMirrors.getRealmListElementTypeMirror(field) ?: return false\n        return isRealmModel(elementTypeMirror)\n    }\n\n    /**\n     * @return `true` if a given field type is `RealmList` and its element type is `RealmAny`,\n     * `false` otherwise.\n     */\n    fun isRealmAnyList(field: VariableElement): Boolean {\n        val elementTypeMirror = TypeMirrors.getRealmListElementTypeMirror(field) ?: return false\n        return isRealmAny(elementTypeMirror)\n    }\n\n    /**\n     * @return `true` if a given field type is `RealmList` and its element type is value type,\n     * `false` otherwise.\n     */\n    fun isRealmValueList(field: VariableElement): Boolean {\n        val elementTypeMirror = TypeMirrors.getRealmListElementTypeMirror(field) ?: return false\n        return !isRealmModel(elementTypeMirror) && !isRealmAny(elementTypeMirror)\n    }\n\n    /**\n     * @return `true` if a given field type is `RealmModel`, `false` otherwise.\n     */\n    fun isRealmModel(field: Element): Boolean {\n        return isRealmModel(field.asType())\n    }\n\n    /**\n     * @return `true` if a given type is `RealmModel`, `false` otherwise.\n     */\n    fun isRealmModel(type: TypeMirror?): Boolean {\n        // This will return the wrong result if a model class doesn't exist at all, but\n        // the compiler will catch that eventually.\n        return typeUtils.isAssignable(type, realmModel)\n        //        // Not sure what is happening here, but typeUtils.isAssignable(\"Foo\", realmModel)\n        //        // returns true even if Foo doesn't exist. No idea why this is happening.\n        //        // For now punt on the problem and check the direct supertype which should be either\n        //        // RealmObject or RealmModel.\n        //        // Original implementation: ``\n        //        //\n        //        // Theory: It looks like if `type` has the internal TypeTag.ERROR (internal API) it\n        //        // automatically translate to being assignable to everything. Possible some Java Specification\n        //        // rule taking effect. In our case, however we can do better since all Realm classes\n        //        // must be in the same compilation unit, so we should be able to look the type up.\n        //        for (TypeMirror typeMirror : typeUtils.directSupertypes(type)) {\n        //            String supertype = typeMirror.toString();\n        //            if (supertype.equals(\"io.realm.RealmObject\") || supertype.equals(\"io.realm.RealmModel\")) {\n        //                return true;\n        //            }\n        //        }\n        //        return false;\n    }\n\n    /**\n     * @return `true` if a given type is `RealmAny`, `false` otherwise.\n     */\n    fun isRealmAny(type: TypeMirror?) = typeUtils.isAssignable(type, realmAny)\n\n    fun isRealmResults(field: VariableElement): Boolean {\n        return typeUtils.isAssignable(field.asType(), realmResults)\n    }\n\n    // get the fully-qualified type name for the generic type of a RealmResults\n    fun getRealmResultsType(field: VariableElement): QualifiedClassName? {\n        if (!isRealmResults(field)) {\n            return null\n        }\n        val type = getGenericTypeForContainer(field) ?: return null\n        return QualifiedClassName(type.toString())\n    }\n\n    // get the fully-qualified type name for the generic type of a RealmList\n    fun getRealmListType(field: VariableElement): QualifiedClassName? {\n        if (!isRealmList(field)) {\n            return null\n        }\n        val type = getGenericTypeForContainer(field) ?: return null\n        return QualifiedClassName(type.toString())\n    }\n\n    fun getDictionaryType(field: VariableElement): QualifiedClassName? {\n        if (!isRealmDictionary(field)) {\n            return null\n        }\n        val type = getGenericTypeForContainer(field) ?: return null\n        return QualifiedClassName(type.toString())\n    }\n\n    fun getSetType(field: VariableElement): QualifiedClassName? {\n        if (!isRealmSet(field)) {\n            return null\n        }\n        val type = getGenericTypeForContainer(field) ?: return null\n        return QualifiedClassName(type.toString())\n    }\n\n    // Note that, because subclassing subclasses of RealmObject is forbidden,\n    // there is no need to deal with constructs like:  <code>RealmResults&lt;? extends Foos&lt;</code>.\n    fun getGenericTypeForContainer(field: VariableElement): ReferenceType? {\n        var fieldType = field.asType()\n        var kind = fieldType.kind\n        if (kind != TypeKind.DECLARED) {\n            return null\n        }\n\n        val args = (fieldType as DeclaredType).typeArguments\n        if (args.size <= 0) {\n            return null\n        }\n\n        fieldType = args[0]\n        kind = fieldType.kind\n        // We also support RealmList<byte[]>\n        return if (kind != TypeKind.DECLARED && kind != TypeKind.ARRAY) {\n            null\n        } else fieldType as ReferenceType\n\n    }\n\n    /**\n     * @return the qualified type name for a field.\n     */\n    fun getFieldTypeQualifiedName(field: VariableElement): QualifiedClassName {\n        return QualifiedClassName(field.asType().toString())\n    }\n\n    /**\n     * @return the generic type for Lists of the form `List<type>`\n     */\n    fun getGenericTypeQualifiedName(field: VariableElement): QualifiedClassName? {\n        val fieldType = field.asType()\n        val typeArguments = (fieldType as DeclaredType).typeArguments\n        return if (typeArguments.isEmpty()) null else QualifiedClassName(typeArguments[0].toString())\n    }\n\n    /**\n     * @return the generic type for Dictionaries of the form `RealmDictionary<type>`\n     * Note: it applies to same types as RealmList.\n     */\n    fun getDictionaryValueTypeQualifiedName(field: VariableElement): QualifiedClassName? {\n        return getGenericTypeQualifiedName(field)\n    }\n\n    /**\n     * @return the generic type for Sets of the form `RealmSet<type>`\n     * Note: it applies to same types as RealmList.\n     */\n    fun getSetValueTypeQualifiedName(field: VariableElement): QualifiedClassName? {\n        return getGenericTypeQualifiedName(field)\n    }\n\n    /**\n     * Return generic type mirror if any.\n     */\n    fun getGenericType(field: VariableElement): TypeMirror? {\n        val fieldType = field.asType()\n        val typeArguments = (fieldType as DeclaredType).typeArguments\n        return if (typeArguments.isEmpty()) null else typeArguments[0]\n    }\n\n    /**\n     * Strips the package name from a fully qualified class name.\n     */\n    fun stripPackage(fullyQualifiedClassName: String): String {\n        val parts = fullyQualifiedClassName.split(\"\\\\.\".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()\n        return if (parts.isNotEmpty()) {\n            parts[parts.size - 1]\n        } else {\n            fullyQualifiedClassName\n        }\n    }\n\n    fun error(message: String?, element: Element) {\n        var e = element\n        if (element is RealmFieldElement) {\n            // Element is being cast to Symbol internally which breaks any implementors of the\n            // Element interface. This is a hack to work around that. Bad bad Oracle\n            e = element.fieldReference\n        }\n        messager.printMessage(Diagnostic.Kind.ERROR, message, e)\n    }\n\n    fun error(message: String?) {\n        messager.printMessage(Diagnostic.Kind.ERROR, message)\n    }\n\n    fun note(message: String?, element: Element) {\n        var e = element\n        if (element is RealmFieldElement) {\n            // Element is being cast to Symbol internally which breaks any implementors of the\n            // Element interface. This is a hack to work around that. Bad bad Oracle\n            e = element.fieldReference\n        }\n        messager.printMessage(Diagnostic.Kind.NOTE, message, e)\n    }\n\n    fun note(message: String?) {\n        messager.printMessage(Diagnostic.Kind.NOTE, message)\n    }\n\n    fun getSuperClass(classType: TypeElement): Element {\n        return typeUtils.asElement(classType.superclass)\n    }\n\n    /**\n     * Returns the interface name for proxy class interfaces\n     */\n    fun getProxyInterfaceName(qualifiedClassName: QualifiedClassName): SimpleClassName {\n        return SimpleClassName(qualifiedClassName.toString().replace(\".\", \"_\") + Constants.INTERFACE_SUFFIX)\n    }\n\n    fun getNameFormatter(policy: RealmNamingPolicy?): NameConverter {\n        if (policy == null) {\n            return IdentityConverter()\n        }\n        when (policy) {\n            RealmNamingPolicy.NO_POLICY -> return IdentityConverter()\n            RealmNamingPolicy.IDENTITY -> return IdentityConverter()\n            RealmNamingPolicy.LOWER_CASE_WITH_UNDERSCORES -> return LowerCaseWithSeparatorConverter('_')\n            RealmNamingPolicy.CAMEL_CASE -> return CamelCaseConverter()\n            RealmNamingPolicy.PASCAL_CASE -> return PascalCaseConverter()\n            else -> throw IllegalArgumentException(\"Unknown policy: $policy\")\n        }\n    }\n\n    /**\n     * Tries to find the internal class name for a referenced type. In model classes this can\n     * happen with either direct object references or using `RealmList` or `RealmResults`.\n     *\n     *\n     * This name is required by schema builders that operate on internal names and not the public ones.\n     *\n     *\n     * Finding the internal name is easy if the referenced type is included in the current round\n     * of annotation processing. In that case the internal name was also calculated in the same round\n     *\n     *\n     * If the referenced type was already compiled, e.g being included from library, then we need\n     * to get the name from the proxy class. Fortunately ProGuard should not have obfuscated any\n     * class files at this point, meaning we can look it up dynamically.\n     *\n     *\n     * If a name is looked up using the class loader, it also means that developers need to\n     * combine a library and app module of model classes at runtime in the RealmConfiguration, but\n     * this should be a valid use case.\n     *\n     * @param className type to lookup the internal name for.\n     * @param classCollection collection of classes found in the current round of annotation processing.\n     * @throws IllegalArgumentException If the internal name could not be looked up\n     * @return the statement that evalutes to the internal class name. This will either be a string\n     * constant or a reference to a static field in another class. In both cases, the return result\n     * should not be put in quotes.\n     */\n    fun getReferencedTypeInternalClassNameStatement(className: QualifiedClassName?, classCollection: ClassCollection): String {\n\n        // Attempt to lookup internal name in current round\n        if (classCollection.containsQualifiedClass(className)) {\n            val metadata = classCollection.getClassFromQualifiedName(className!!)\n            return \"\\\"\" + metadata.internalClassName + \"\\\"\"\n        }\n\n        // If we cannot find the name in the current processor round, we have to defer resolving the\n        // name to runtime. The reason being that the annotation processor can only access the\n        // compile type class path using Elements and Types which do not allow us to read\n        // field values.\n        //\n        // Doing it this way unfortunately means that if the class is not on the apps classpath\n        // a rather obscure class-not-found exception will be thrown when starting the app, but since\n        // this is probably a very niche use case that is acceptable for now.\n        //\n        // TODO: We could probably create an internal annotation like `@InternalName(\"__Permission\")`\n        // which should make it possible for the annotation processor to read the value from the\n        // proxy class, even for files in other jar files.\n        return \"io.realm.${getProxyClassName(className!!)}.ClassNameHelper.INTERNAL_CLASS_NAME\"\n    }\n\n    /**\n     * Returns a simple reference to the ColumnInfo class inside this model class, i.e. the package\n     * name is not prefixed.\n     */\n    fun getSimpleColumnInfoClassName(className: QualifiedClassName): String {\n        val simpleModelClassName = className.getSimpleName()\n        return \"${getProxyClassName(className)}.${simpleModelClassName}ColumnInfo\"\n    }\n\n    // Returns whether a type of a Realm field is embedded or not.\n    // For types which are part of this processing round we can look it up immediately from\n    // the metadata in the `classCollection`. For types defined in other modules we will\n    // have to use the slower approach of inspecting the `embedded` property of the\n    // RealmClass annotation using the compiler tool api.\n    fun isFieldTypeEmbedded(type: TypeMirror, classCollection: ClassCollection) : Boolean  {\n        val fieldType = QualifiedClassName(type)\n        val fieldTypeMetaData: ClassMetaData? = classCollection.getClassFromQualifiedNameOrNull(fieldType)\n        return fieldTypeMetaData?.embedded ?: type.isEmbedded()\n    }\n\n    private fun TypeMirror.isEmbedded() : Boolean {\n        var isEmbedded = false\n        if (this.kind === TypeKind.DECLARED) {\n            val declaredType: DeclaredType = this as DeclaredType\n            val typeElement = declaredType.asElement() as TypeElement\n            isEmbedded = typeElement.annotationMirrors.firstOrNull { annotation: AnnotationMirror ->\n                val annotationType = annotation.annotationType\n                if (annotationType.asElement().toString() == \"io.realm.annotations.RealmClass\") {\n                    for (entry: Map.Entry<ExecutableElement?, AnnotationValue?> in annotation.elementValues) {\n                        if (entry.key?.simpleName.toString() == \"embedded\") {\n                            return (entry.value?.value == true)\n                        }\n                    }\n                }\n                return false\n            } != null\n        }\n        return isEmbedded\n    }\n\n    // Returns whether a type has primary key field\n    // For types which are part of this processing round we can look it up immediately from\n    // the metadata in the `classCollection`. For types defined in other modules we will\n    // have to use the slower approach of inspecting the variable member `embedded` property of the\n    // RealmClass annotation using the compiler tool api.\n    fun fieldTypeHasPrimaryKey(type: TypeMirror, classCollection: ClassCollection): Boolean {\n        val fieldType = QualifiedClassName(type)\n        val fieldTypeMetaData: ClassMetaData? =\n            classCollection.getClassFromQualifiedNameOrNull(fieldType)\n        return fieldTypeMetaData?.hasPrimaryKey() ?: type.hasPrimaryKey()\n    }\n\n    private fun TypeMirror.hasPrimaryKey(): Boolean {\n        if (this.kind === TypeKind.DECLARED) {\n            val declaredType = this as DeclaredType\n            val typeElement = declaredType.asElement() as TypeElement\n            val classElements: MutableList<out Element> = typeElement.enclosedElements\n            return classElements\n                .filter { el: Element -> el.kind == ElementKind.FIELD}\n                .firstOrNull { el: Element ->\n                    return el.annotationMirrors.firstOrNull { annotation: AnnotationMirror ->\n                        val annotationType: DeclaredType = annotation.annotationType\n                        annotationType.asElement().toString() == \"io.realm.annotations.PrimaryKey\"\n                    } != null\n                } != null\n        }\n        return false\n    }\n}\n"
  },
  {
    "path": "realm/realm-annotations-processor/src/main/java/io/realm/processor/ext/JavaWriterExt.kt",
    "content": "/*\n * Copyright 2019 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 \npackage io.realm.processor.ext\n\nimport com.squareup.javawriter.JavaWriter\nimport io.realm.processor.QualifiedClassName\nimport io.realm.processor.SimpleClassName\nimport javax.lang.model.element.Modifier\n\nfun JavaWriter.beginType(type: QualifiedClassName,\n                         kind: String,\n                         modifiers: Set<Modifier>,\n                         extendsType: QualifiedClassName,\n                         implementsType: Array<String>): JavaWriter {\n    return this.beginType(type.toString(), kind, modifiers, extendsType.toString(), *implementsType)\n}\n\nfun JavaWriter.beginType(type: QualifiedClassName,\n                         kind: String,\n                         modifiers: Set<Modifier>,\n                         extendsType: QualifiedClassName,\n                         implementsType: Array<SimpleClassName>): JavaWriter {\n    val types: Array<String> = implementsType.map { it.toString() }.toTypedArray()\n    return this.beginType(type.toString(), kind, modifiers, extendsType.toString(), *types)\n}\n\nfun JavaWriter.beginMethod(returnType: QualifiedClassName,\n                           name: String,\n                           modifiers: Set<Modifier>,\n                           vararg parameters: String): JavaWriter {\n    return this.beginMethod(returnType.toString(), name, modifiers, *parameters)\n}\n\nfun JavaWriter.beginMethod(returnType: QualifiedClassName,\n                           name: String,\n                           modifiers: Set<Modifier>,\n                           parameters: List<String>,\n                           throwsTypes: List<String>): JavaWriter {\n    return this.beginMethod(returnType.toString(), name, modifiers, parameters, throwsTypes)\n}\n\n"
  },
  {
    "path": "realm/realm-annotations-processor/src/main/java/io/realm/processor/nameconverter/CamelCaseConverter.kt",
    "content": "/*\n * Copyright 2018 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 */\npackage io.realm.processor.nameconverter\n\n/**\n * Converter that converts input to \"camelCase\".\n */\nclass CamelCaseConverter : NameConverter {\n\n    private val tokenizer = WordTokenizer()\n\n    override fun convert(name: String): String {\n        val words = tokenizer.split(name)\n        val output = StringBuilder()\n        var firstWordEmitted = false\n        for (i in words.indices) {\n            val word = words[i].toLowerCase()\n            if (firstWordEmitted) {\n                val codepoint = word.codePointAt(0)\n                output.appendCodePoint(Character.toUpperCase(codepoint))\n                output.append(word.substring(Character.charCount(codepoint)))\n            } else {\n                output.append(word)\n                firstWordEmitted = true\n            }\n        }\n\n        return output.toString()\n    }\n}\n"
  },
  {
    "path": "realm/realm-annotations-processor/src/main/java/io/realm/processor/nameconverter/IdentityConverter.kt",
    "content": "/*\n * Copyright 2018 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 */\npackage io.realm.processor.nameconverter\n\n/**\n * Converter that doesn't do any conversion when translating from Java to Realm.\n *\n * @see io.realm.annotations.RealmNamingPolicy.IDENTITY\n */\nclass IdentityConverter : NameConverter {\n\n    override fun convert(name: String): String {\n        return name\n    }\n\n}\n"
  },
  {
    "path": "realm/realm-annotations-processor/src/main/java/io/realm/processor/nameconverter/LowerCaseWithSeparatorConverter.kt",
    "content": "/*\n * Copyright 2019 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 */\npackage io.realm.processor.nameconverter\n\n/**\n * Converter that converts input to lower case with a defined separator character.\n */\nclass LowerCaseWithSeparatorConverter(private val separator: Char) : NameConverter {\n\n    private val tokenizer = WordTokenizer()\n\n    override fun convert(name: String): String {\n        val words = tokenizer.split(name)\n        val output = StringBuilder()\n        for (i in words.indices) {\n            val word = words[i].toLowerCase()\n            output.append(word)\n            if (i < words.size - 1) {\n                output.append(separator)\n            }\n        }\n\n        return output.toString()\n    }\n}\n"
  },
  {
    "path": "realm/realm-annotations-processor/src/main/java/io/realm/processor/nameconverter/NameConverter.kt",
    "content": "/*\n * Copyright 2018 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 */\npackage io.realm.processor.nameconverter\n\n/**\n * Interface for converters that can implement a given naming policy.\n *\n * @see io.realm.annotations.RealmNamingPolicy\n */\ninterface NameConverter {\n    /**\n     * Converts the `name` so it matches the [io.realm.annotations.RealmNamingPolicy].\n     *\n     * @param name string to convert.\n     * @return the converted string.\n     */\n    fun convert(name: String): String\n}\n"
  },
  {
    "path": "realm/realm-annotations-processor/src/main/java/io/realm/processor/nameconverter/PascalCaseConverter.kt",
    "content": "/*\n * Copyright 2018 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 */\npackage io.realm.processor.nameconverter\n\n/**\n * Converter that converts input to \"PascalCase\".\n */\nclass PascalCaseConverter : NameConverter {\n\n    private val tokenizer = WordTokenizer()\n\n    override fun convert(name: String): String {\n        val words = tokenizer.split(name)\n        val output = StringBuilder()\n        for (i in words.indices) {\n            val word = words[i].toLowerCase()\n            val codepoint = word.codePointAt(0)\n            output.appendCodePoint(Character.toUpperCase(codepoint))\n            output.append(word.substring(Character.charCount(codepoint)))\n        }\n\n        return output.toString()\n    }\n}\n"
  },
  {
    "path": "realm/realm-annotations-processor/src/main/java/io/realm/processor/nameconverter/WordTokenizer.kt",
    "content": "/*\n * Copyright 2019 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 */\npackage io.realm.processor.nameconverter\n\nimport java.util.ArrayList\n\n/**\n * Segments a Java variable name into component words.\n *\n * Java variable names must follow the rules described in:\n * https://docs.oracle.com/javase/specs/jls/se7/html/jls-3.html#jls-3.8\n *\n * In this implementation we treat word separators as any of the following:\n *\n *  1. Anytime a `_` or `$` is encountered.\n *     Example is \"_FooBar\" or \"_Foo$Bar\" which both becomes \"Foo\" and \"Bar\".\n *\n *  2. Anytime you switch from a lower case character to an upper case character as identified by a\n *     `Character.isUpperCase(codepoint)` and `Character.isLowerCase(codepoint)`.\n *     Example is \"FooBar\" which becomes \"Foo\" and \"Bar\".\n *\n *  3. Anytime you switch from more than one uppercase character to a lower case one. As identified\n *     by `Character.isUpperCase(codepoint)` and `Character.isLowerCase(codepoint)`.\n *     Example is \"FOOBar\" which becomes \"FOO\" and \"Bar.\n *\n *  4. Some characters like emojiis are neither uppercase or lowercase characters, so they will\n *     not trigger any of the above rules.\n *     Examples are \"my😁\" and \"MY😁\" which are both treated as one word.\n *\n *  5. Hungarian notation, i.e. strings starting with lowercase \"m\" followed by uppercase letter\n *     is stripped and not considered part of any word.\n */\nclass WordTokenizer {\n\n    /**\n     * Segments a string into words as described above\n     */\n    internal fun split(str: String?): Array<String> {\n        if (str == null || str.isEmpty()) {\n            return arrayOf()\n        }\n\n        var previousCodepoint: Int?\n        var currentCodepoint: Int? = null\n        val length = str.length\n        var offset = 0\n        val currentWord = StringBuilder()\n        val words = ArrayList<String>()\n        var wordAllUpperCase: Boolean? = null\n        var lastCodePointCharLength = 0\n        while (offset < length) {\n            previousCodepoint = currentCodepoint\n            currentCodepoint = str.codePointAt(offset)\n            val currentCharCount = Character.charCount(currentCodepoint)\n            val previousCodePointUpperCase = previousCodepoint != null && Character.isUpperCase(previousCodepoint)\n            val previousCodePointLowerCase = previousCodepoint != null && Character.isLowerCase(previousCodepoint)\n            val currentCodePointUpperCase = Character.isUpperCase(currentCodepoint)\n            val currentCodePointLowerCase = Character.isLowerCase(currentCodepoint)\n\n            // Separator char encountered not part of any word, but indicate a boundary\n            if (currentCodepoint == '_'.toInt() || currentCodepoint == '$'.toInt()) {\n                if (currentWord.isNotEmpty()) {\n                    words.add(currentWord.toString())\n                    currentWord.setLength(0)\n                }\n\n                wordAllUpperCase = null\n                offset += currentCharCount\n                lastCodePointCharLength = 0\n                continue\n            }\n\n            // Change between lower case and upper case indicate a word boundary\n            if (previousCodePointLowerCase && currentCodePointUpperCase) {\n                if (currentWord.isNotEmpty()) {\n                    words.add(currentWord.toString())\n                    currentWord.setLength(0)\n                    currentWord.appendCodePoint(currentCodepoint)\n                }\n\n                wordAllUpperCase = true\n                offset += currentCharCount\n                lastCodePointCharLength = currentCharCount\n                continue\n            }\n\n            // Change between upper case and lower case indicated a word boundary on the previous\n            // char if multiple upper case characters where encountered.\n            if (currentWord.length > 1\n                    && wordAllUpperCase != null && wordAllUpperCase\n                    && previousCodePointUpperCase && currentCodePointLowerCase) {\n                words.add(currentWord.substring(0, currentWord.length - lastCodePointCharLength))\n                currentWord.substring(0, currentWord.length - lastCodePointCharLength)\n                currentWord.delete(0, currentWord.length - lastCodePointCharLength)\n                currentWord.appendCodePoint(currentCodepoint)\n\n                wordAllUpperCase = false\n                offset += currentCharCount\n                lastCodePointCharLength = currentCharCount\n                continue\n            }\n\n            // Add codepoint to current word\n            currentWord.appendCodePoint(currentCodepoint)\n            wordAllUpperCase = currentCodePointUpperCase && (wordAllUpperCase == null || wordAllUpperCase)\n            offset += currentCharCount\n            lastCodePointCharLength = currentCharCount\n        }\n\n        // Add final word when exiting loop\n        if (currentWord.length > 0) {\n            words.add(currentWord.toString())\n        }\n\n        // Remove hungarian notation if found\n        if (words[0] == \"m\") {\n            words.removeAt(0)\n        }\n\n        return words.toTypedArray()\n    }\n}\n"
  },
  {
    "path": "realm/realm-annotations-processor/src/main/resources/META-INF/gradle/incremental.annotation.processors",
    "content": "io.realm.processor.RealmProcessor,aggregating"
  },
  {
    "path": "realm/realm-annotations-processor/src/main/resources/META-INF/services/javax.annotation.processing.Processor",
    "content": "io.realm.processor.RealmProcessor"
  },
  {
    "path": "realm/realm-annotations-processor/src/main/templates/Version.java",
    "content": "package io.realm.processor;\n\npublic class Version {\n    public static final String VERSION = \"@version@\";\n}\n"
  },
  {
    "path": "realm/realm-annotations-processor/src/test/java/io/realm/processor/NameConverterTests.java",
    "content": "package io.realm.processor;\n\nimport static org.junit.Assert.assertEquals;\n\nimport org.junit.Test;\n\nimport java.util.LinkedHashMap;\nimport java.util.Map;\n\nimport io.realm.processor.nameconverter.CamelCaseConverter;\nimport io.realm.processor.nameconverter.LowerCaseWithSeparatorConverter;\nimport io.realm.processor.nameconverter.NameConverter;\nimport io.realm.processor.nameconverter.PascalCaseConverter;\n\npublic class NameConverterTests {\n\n    @Test\n    public void camelCase() {\n        NameConverter converter = new CamelCaseConverter();\n        Map<String, String> values = new LinkedHashMap<String, String>() {{\n            // <JavaName, InternalName>\n            put(\"camelCase\", \"camelCase\");\n            put(\"PascalCase\", \"pascalCase\");\n            put(\"mHungarianNotation\", \"hungarianNotation\");\n            put(\"_PascalCaseWithStartingSeparator\", \"pascalCaseWithStartingSeparator\");\n            put(\"_camelCaseWithStartingSeparator\", \"camelCaseWithStartingSeparator\");\n            put(\"ALL_CAPS_WITH_SEPARATOR\", \"allCapsWithSeparator\");\n            put(\"ALLCAPS\", \"allcaps\");\n            put(\"_ALL_CAPS_WITH_STARTING_SEPARATOR\", \"allCapsWithStartingSeparator\");\n            put(\"alllower\", \"alllower\");\n            put(\"all_lower_with_separator\", \"allLowerWithSeparator\");\n\n            // $ Separator\n            put(\"$generatedNames\", \"generatedNames\");\n            put(\"generatedNames$\", \"generatedNames\");\n            put(\"generated$Names\", \"generatedNames\");\n\n            // Non-ascii chars\n            put(\"πPi\", \"πPi\");\n            put(\"NonAsciiÆøÅ\", \"nonAsciiÆøÅ\");\n\n            // Multiple upper case letters\n            put(\"HTMLFile\", \"htmlFile\");\n            put(\"aHTMLFile\", \"aHtmlFile\");\n            put(\"_HTMLFile\", \"htmlFile\");\n\n            // Emojiis are neither upper case nor lower case (Smiley)\n            put(\"\\uD83D\\uDE01\", \"\\uD83D\\uDE01\");\n            put(\"m\\uD83D\\uDE01\", \"m\\uD83D\\uDE01\");\n            put(\"M\\uD83D\\uDE01\", \"m\\uD83D\\uDE01\");\n            put(\"\\uD83D\\uDE01Smiley\", \"\\uD83D\\uDE01smiley\");\n            put(\"_\\uD83D\\uDE01smiley\", \"\\uD83D\\uDE01smiley\");\n        }};\n\n        for (Map.Entry<String, String> entry : values.entrySet()) {\n            assertEquals(entry.getValue(), converter.convert(entry.getKey()));\n        }\n    }\n\n    @Test\n    public void pascalCase() {\n        NameConverter converter = new PascalCaseConverter();\n        Map<String, String> values = new LinkedHashMap<String, String>() {{\n            // <JavaName, InternalName>\n            put(\"camelCase\", \"CamelCase\");\n            put(\"PascalCase\", \"PascalCase\");\n            put(\"mHungarianNotation\", \"HungarianNotation\");\n            put(\"_PascalCaseWithStartingSeparator\", \"PascalCaseWithStartingSeparator\");\n            put(\"_camelCaseWithStartingSeparator\", \"CamelCaseWithStartingSeparator\");\n            put(\"ALL_CAPS_WITH_SEPARATOR\", \"AllCapsWithSeparator\");\n            put(\"ALLCAPS\", \"Allcaps\");\n            put(\"_ALL_CAPS_WITH_STARTING_SEPARATOR\", \"AllCapsWithStartingSeparator\");\n            put(\"alllower\", \"Alllower\");\n            put(\"all_lower_with_separator\", \"AllLowerWithSeparator\");\n\n            // $ Separator\n            put(\"$generatedNames\", \"GeneratedNames\");\n            put(\"generatedNames$\", \"GeneratedNames\");\n            put(\"generated$Names\", \"GeneratedNames\");\n\n            // Non-ascii chars\n            put(\"πPi\", \"ΠPi\");\n            put(\"NonAsciiÆøÅ\", \"NonAsciiÆøÅ\");\n\n            // Multiple upper case letters\n            put(\"HTMLFile\", \"HtmlFile\");\n            put(\"aHTMLFile\", \"AHtmlFile\");\n            put(\"_HTMLFile\", \"HtmlFile\");\n\n            // Emojiis are neither upper case nor lower case (Smiley)\n            put(\"\\uD83D\\uDE01\", \"\\uD83D\\uDE01\");\n            put(\"m\\uD83D\\uDE01\", \"M\\uD83D\\uDE01\");\n            put(\"M\\uD83D\\uDE01\", \"M\\uD83D\\uDE01\");\n            put(\"\\uD83D\\uDE01Smiley\", \"\\uD83D\\uDE01smiley\");\n            put(\"_\\uD83D\\uDE01smiley\", \"\\uD83D\\uDE01smiley\");\n        }};\n\n        for (Map.Entry<String, String> entry : values.entrySet()) {\n            assertEquals(entry.getValue(), converter.convert(entry.getKey()));\n        }\n    }\n\n    @Test\n    public void lowerCaseWithUnderscore() {\n        NameConverter converter = new LowerCaseWithSeparatorConverter('_');\n        Map<String, String> values = new LinkedHashMap<String, String>() {{\n            // <JavaName, InternalName>\n            // Common naming schemes using ASCII chars\n            put(\"camelCase\", \"camel_case\");\n            put(\"PascalCase\", \"pascal_case\");\n            put(\"mHungarianNotation\", \"hungarian_notation\");\n            put(\"_mHungarianNotation\", \"hungarian_notation\");\n            put(\"mHungarian_mNotation\", \"hungarian_m_notation\");\n            put(\"_PascalCaseWithStartingSeparator\", \"pascal_case_with_starting_separator\");\n            put(\"_camelCaseWithStartingSeparator\", \"camel_case_with_starting_separator\");\n            put(\"ALL_CAPS_WITH_SEPARATOR\", \"all_caps_with_separator\");\n            put(\"ALLCAPS\", \"allcaps\");\n            put(\"_ALL_CAPS_WITH_STARTING_SEPARATOR\", \"all_caps_with_starting_separator\");\n            put(\"alllower\", \"alllower\");\n            put(\"all_lower_with_separator\", \"all_lower_with_separator\");\n\n            // $ Separator\n            put(\"$generatedNames\", \"generated_names\");\n            put(\"generatedNames$\", \"generated_names\");\n            put(\"generated$Names\", \"generated_names\");\n\n            // Non-ascii chars\n            put(\"πPi\", \"π_pi\");\n            put(\"NonAsciiÆøÅ\", \"non_ascii_æø_å\");\n\n            // Multiple upper case letters\n            put(\"HTMLFile\", \"html_file\");\n            put(\"aHTMLFile\", \"a_html_file\");\n            put(\"_HTMLFile\", \"html_file\");\n\n            // Emojiis are neither upper case nor lower case (Smiley)\n            put(\"\\uD83D\\uDE01\", \"\\uD83D\\uDE01\");\n            put(\"m\\uD83D\\uDE01\", \"m\\uD83D\\uDE01\");\n            put(\"M\\uD83D\\uDE01\", \"m\\uD83D\\uDE01\");\n            put(\"\\uD83D\\uDE01Smiley\", \"\\uD83D\\uDE01smiley\");\n            put(\"_\\uD83D\\uDE01smiley\", \"\\uD83D\\uDE01smiley\");\n        }};\n\n        for (Map.Entry<String, String> entry : values.entrySet()) {\n            assertEquals(entry.getValue(), converter.convert(entry.getKey()));\n        }\n    }\n\n}\n"
  },
  {
    "path": "realm/realm-annotations-processor/src/test/java/io/realm/processor/RealmBacklinkProcessorTest.java",
    "content": "/*\n * Copyright 2017 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 */\npackage io.realm.processor;\n\nimport com.google.testing.compile.JavaFileObjects;\n\nimport org.junit.Test;\n\nimport java.io.IOException;\nimport java.util.Arrays;\n\nimport javax.lang.model.element.Modifier;\nimport javax.tools.JavaFileObject;\n\nimport static com.google.common.truth.Truth.assertAbout;\nimport static com.google.testing.compile.JavaSourceSubjectFactory.javaSource;\nimport static com.google.testing.compile.JavaSourcesSubjectFactory.javaSources;\n\npublic class RealmBacklinkProcessorTest {\n    private final JavaFileObject sourceClass = JavaFileObjects.forResource(\"some/test/BacklinkSource.java\");\n    private final JavaFileObject targetClass = JavaFileObjects.forResource(\"some/test/BacklinkTarget.java\");\n    private final JavaFileObject invalidResultsValueType = JavaFileObjects.forResource(\"some/test/InvalidResultsElementType.java\");\n\n    @Test\n    public void compileBacklinks() {\n        assertAbout(javaSources())\n                .that(Arrays.asList(sourceClass, targetClass))\n                .processedWith(new RealmProcessor())\n                .compilesWithoutError();\n    }\n\n    @Test\n    public void compileSyntheticBacklinks() throws IOException {\n        RealmSyntheticTestClass targetClass = createBacklinkTestClass().builder().build();\n        assertAbout(javaSources())\n                .that(Arrays.asList(sourceClass, targetClass))\n                .processedWith(new RealmProcessor())\n                .compilesWithoutError();\n    }\n\n    @Test\n    public void failOnLinkingObjectsWithInvalidFieldType() throws IOException {\n        RealmSyntheticTestClass targetClass = createBacklinkTestClass()\n                .type(\"BacklinkTarget\")\n                .builder().build();\n        assertAbout(javaSources())\n                .that(Arrays.asList(sourceClass, targetClass))\n                .processedWith(new RealmProcessor())\n                .failsToCompile()\n                .withErrorContaining(\"Fields annotated with @LinkingObjects must be RealmResults\");\n    }\n\n    @Test\n    public void failOnLinkingObjectsWithNonFinalField() throws IOException {\n        RealmSyntheticTestClass targetClass = createBacklinkTestClass()\n                // A field with a @LinkingObjects annotation must be final\n                .modifiers(Modifier.PUBLIC)\n                .builder().build();\n        assertAbout(javaSources())\n                .that(Arrays.asList(sourceClass, targetClass))\n                .processedWith(new RealmProcessor())\n                .failsToCompile()\n                .withErrorContaining(\"must be final\");\n    }\n\n    @Test\n    public void failsOnLinkingObjectsWithLinkedFields() throws IOException {\n        RealmSyntheticTestClass targetClass = createBacklinkTestClass()\n                // Defining a backlink more than one levels back is not supported.\n                // It can be queried though: `equalTo(\"selectedFieldParents.selectedFieldParents\")\n                .clearAnnotations()\n                .annotation(\"LinkingObjects(\\\"child.id\\\")\")\n                .builder().build();\n        assertAbout(javaSources())\n                .that(Arrays.asList(sourceClass, targetClass))\n                .processedWith(new RealmProcessor())\n                .failsToCompile()\n                .withErrorContaining(\"The use of '.' to specify fields in referenced classes is not supported\");\n    }\n\n    @Test\n    public void failsOnLinkingObjectsMissingFieldName() throws IOException {\n        RealmSyntheticTestClass targetClass = createBacklinkTestClass()\n                // No backlinked field specified\n                .clearAnnotations()\n                .annotation(\"LinkingObjects\")\n                .builder().build();\n        assertAbout(javaSources())\n                .that(Arrays.asList(sourceClass, targetClass))\n                .processedWith(new RealmProcessor())\n                .failsToCompile()\n                .withErrorContaining(\"must have a parameter identifying the link target\");\n    }\n\n    @Test\n    public void failsOnLinkingObjectsMissingGeneric() throws IOException {\n        RealmSyntheticTestClass targetClass = createBacklinkTestClass()\n                // No backlink generic param specified\n                .type(\"RealmResults\")\n                .builder().build();\n        assertAbout(javaSources())\n                .that(Arrays.asList(sourceClass, targetClass))\n                .processedWith(new RealmProcessor())\n                .failsToCompile()\n                .withErrorContaining(\"must specify a generic type\");\n    }\n\n    @Test\n    public void failsOnLinkingObjectsWithRequiredFields() throws IOException {\n        RealmSyntheticTestClass targetClass = createBacklinkTestClass()\n                // A backlinked field may not be @Required\n                .annotation(\"Required\")\n                .builder().build();\n        assertAbout(javaSources())\n                .that(Arrays.asList(sourceClass, targetClass))\n                .processedWith(new RealmProcessor())\n                .failsToCompile()\n                .withErrorContaining(\"The @LinkingObjects field \");\n    }\n\n    @Test\n    public void failsOnLinkingObjectsWithIgnoreFields() throws IOException {\n        RealmSyntheticTestClass targetClass = createBacklinkTestClass()\n                // An  @Ignored, backlinked field is completely ignored\n                .annotation(\"Ignore\")\n                .builder().build();\n        assertAbout(javaSources())\n                .that(Arrays.asList(sourceClass, targetClass))\n                .processedWith(new RealmProcessor())\n                .compilesWithoutError();\n    }\n\n    // TODO: This seems like a \"gottcha\".  We should warn.\n    @Test\n    public void ignoreStaticLinkingObjects() throws IOException {\n        RealmSyntheticTestClass targetClass = createBacklinkTestClass()\n                .modifiers(Modifier.PUBLIC, Modifier.STATIC)\n                .type(\"RealmResults\")\n                .clearAnnotations()\n                .annotation(\"LinkingObjects(\\\"xxx\\\")\")\n                .builder().build();\n        assertAbout(javaSources())\n                .that(Arrays.asList(sourceClass, targetClass))\n                .processedWith(new RealmProcessor())\n                .compilesWithoutError();\n    }\n\n    @Test\n    public void failsOnLinkingObjectsFieldNotFound() throws IOException {\n        RealmSyntheticTestClass targetClass = createBacklinkTestClass()\n                // The argument to the @LinkingObjects annotation must name a field in the source class\n                .clearAnnotations()\n                .annotation(\"LinkingObjects(\\\"xxx\\\")\")\n                .builder().build();\n        assertAbout(javaSources())\n                .that(Arrays.asList(sourceClass, targetClass))\n                .processedWith(new RealmProcessor())\n                .failsToCompile()\n                .withErrorContaining(\"does not exist in class\");\n    }\n\n    @Test\n    public void failsOnLinkingObjectsWithFieldWrongType() throws IOException {\n        RealmSyntheticTestClass targetClass = createBacklinkTestClass()\n                // The type of the field named in the @LinkingObjects annotation must match\n                // the generic type of the annotated field.  BacklinkSource.child is a Backlink,\n                // not a Backlinks_WrongType.\n                .builder().name(\"BacklinkTarget_WrongType\").build();\n        assertAbout(javaSources())\n                .that(Arrays.asList(sourceClass, targetClass))\n                .processedWith(new RealmProcessor())\n                .failsToCompile()\n                .withErrorContaining(\"instead of\");\n    }\n\n    // This method constructs a synthetic Backlink class that *should* compile correctly.\n    // It returns the ref to the backlinked Field.  Tests can modify the\n    // field in perverse ways, to verify failure modes.\n    private RealmSyntheticTestClass.Field createBacklinkTestClass() {\n        return new RealmSyntheticTestClass.Builder().name(\"BacklinkTarget\")\n                .field().name(\"id\").type(\"int\").builder()\n                .field()\n                    .name(\"parents\")\n                    .type(\"RealmResults<BacklinkSource>\")\n                    .modifiers(Modifier.PUBLIC, Modifier.FINAL)\n                    .annotation(\"LinkingObjects(\\\"child\\\")\")\n                    .initializer(\"null\")\n                    .hasGetter(false)\n                    .hasSetter(false);\n    }\n\n    @Test\n    public void failToCompileInvalidResultsElementType() {\n        assertAbout(javaSource())\n                .that(invalidResultsValueType)\n                .processedWith(new RealmProcessor())\n                .failsToCompile();\n    }\n\n    @Test\n    public void compileBacklinkClassesWithSimpleNameConflicts() {\n        assertAbout(javaSources())\n                .that(Arrays.asList(\n                        JavaFileObjects.forResource(\"some/test/BacklinkSelfReference.java\"),\n                        JavaFileObjects.forResource(\"some/test/conflict/BacklinkSelfReference.java\")\n                ))\n                .processedWith(new RealmProcessor())\n                .compilesWithoutError();\n    }\n}\n"
  },
  {
    "path": "realm/realm-annotations-processor/src/test/java/io/realm/processor/RealmCounterProcessorTest.java",
    "content": "/*\n * Copyright 2014-2017 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\npackage io.realm.processor;\n\nimport com.google.testing.compile.JavaFileObjects;\n\nimport org.junit.Ignore;\nimport org.junit.Test;\n\nimport java.io.IOException;\nimport java.util.Arrays;\n\nimport javax.lang.model.element.Modifier;\n\nimport static com.google.common.truth.Truth.assertAbout;\nimport static com.google.testing.compile.JavaSourcesSubjectFactory.javaSources;\n\n\npublic class RealmCounterProcessorTest {\n\n    @Test\n    public void compileMutableRealmInteger() throws IOException {\n        RealmSyntheticTestClass javaFileObject = createCounterTestClass()\n                .builder().build();\n        assertAbout(javaSources())\n                .that(Arrays.asList(javaFileObject))\n                .processedWith(new RealmProcessor())\n                .compilesWithoutError();\n    }\n\n    @Test\n    public void compileIgnoredMutableRealmInteger() throws IOException {\n        RealmSyntheticTestClass javaFileObject = createCounterTestClass()\n                .annotation(\"Ignore\")\n                .builder().build();\n        assertAbout(javaSources())\n                .that(Arrays.asList(javaFileObject))\n                .processedWith(new RealmProcessor())\n                .compilesWithoutError();\n    }\n\n    @Test\n    public void compileIndexedMutableRealmInteger() throws IOException {\n        RealmSyntheticTestClass javaFileObject = createCounterTestClass()\n                .annotation(\"Index\")\n                .builder().build();\n        assertAbout(javaSources())\n                .that(Arrays.asList(javaFileObject))\n                .processedWith(new RealmProcessor())\n                .compilesWithoutError();\n    }\n\n    @Test\n    public void compileRequiredMutableRealmInteger() throws IOException {\n        RealmSyntheticTestClass javaFileObject = createCounterTestClass()\n                .annotation(\"Required\")\n                .builder().build();\n        assertAbout(javaSources())\n                .that(Arrays.asList(javaFileObject))\n                .processedWith(new RealmProcessor())\n                .compilesWithoutError();\n    }\n\n    @Test\n    public void compileStaticMutableRealmInteger() throws IOException {\n        RealmSyntheticTestClass javaFileObject = createCounterTestClass()\n                .modifiers(Modifier.PRIVATE, Modifier.FINAL, Modifier.STATIC)\n                .builder().build();\n        assertAbout(javaSources())\n                .that(Arrays.asList(javaFileObject))\n                .processedWith(new RealmProcessor())\n                .compilesWithoutError();\n    }\n\n    @Test\n    public void failOnPKMutableRealmInteger() throws IOException {\n        RealmSyntheticTestClass javaFileObject = createCounterTestClass()\n                .annotation(\"PrimaryKey\")\n                .builder().build();\n        assertAbout(javaSources())\n                .that(Arrays.asList(javaFileObject))\n                .processedWith(new RealmProcessor())\n                .failsToCompile()\n                .withErrorContaining(\"cannot be used as primary key\");\n    }\n\n    @Test\n    public void failUnlessFinalMutableRealmInteger() throws IOException {\n        RealmSyntheticTestClass javaFileObject = createCounterTestClass()\n                .modifiers(Modifier.PRIVATE)\n                .builder().build();\n        assertAbout(javaSources())\n                .that(Arrays.asList(javaFileObject))\n                .processedWith(new RealmProcessor())\n                .failsToCompile()\n                .withErrorContaining(\"must be final\");\n    }\n\n    // This method constructs a synthetic Counter test class that *should* compile correctly.\n    // It returns the ref to the Counter Field.  Tests can modify the\n    // field in perverse ways, to verify failure modes.\n    private RealmSyntheticTestClass.Field createCounterTestClass() {\n        return new RealmSyntheticTestClass.Builder().name(\"Counter\")\n                .field().name(\"id\").type(\"int\").builder()\n                .field()\n                .name(\"columnMutableRealmInteger\")\n                .type(\"MutableRealmInteger\")\n                .modifiers(Modifier.PRIVATE, Modifier.FINAL)\n                .initializer(\"MutableRealmInteger.valueOf(0)\")\n                .hasSetter(false);\n    }\n}\n"
  },
  {
    "path": "realm/realm-annotations-processor/src/test/java/io/realm/processor/RealmEmbeddedObjectsTest.java",
    "content": "package io.realm.processor;\n\nimport com.google.testing.compile.JavaFileObjects;\n\nimport org.junit.Test;\n\nimport java.util.Arrays;\n\nimport static com.google.common.truth.Truth.assertAbout;\nimport static com.google.testing.compile.JavaSourceSubjectFactory.javaSource;\nimport static com.google.testing.compile.JavaSourcesSubjectFactory.javaSources;\n\npublic class RealmEmbeddedObjectsTest {\n\n    @Test\n    public void compileAndCompareEmbeddedObjectFile() {\n        assertAbout(javaSource())\n                .that(JavaFileObjects.forResource(\"some/test/EmbeddedClass.java\"))\n                .processedWith(new RealmProcessor())\n                .compilesWithoutError()\n                .and()\n                .generatesSources(JavaFileObjects.forResource(\"io/realm/some_test_EmbeddedClassRealmProxy.java\"));\n    }\n\n    @Test\n    public void compileAndCompareParentToEmbeddedObjectFile() {\n        assertAbout(javaSources())\n                .that(Arrays.asList(\n                        JavaFileObjects.forResource(\"some/test/EmbeddedClassSimpleParent.java\"),\n                        JavaFileObjects.forResource(\"some/test/EmbeddedClass.java\")\n                ))\n                .processedWith(new RealmProcessor())\n                .compilesWithoutError()\n                .and()\n                .generatesSources(JavaFileObjects.forResource(\"io/realm/some_test_EmbeddedClassSimpleParentRealmProxy.java\"));\n    }\n\n    @Test\n    public void compileWithSingleRequiredParent() {\n        assertAbout(javaSources())\n                .that(Arrays.asList(\n                    JavaFileObjects.forResource(\"some/test/EmbeddedClassParent.java\"),\n                    JavaFileObjects.forResource(\"some/test/EmbeddedClass.java\"),\n                    JavaFileObjects.forResource(\"some/test/EmbeddedClassOptionalParents.java\"),\n                    JavaFileObjects.forResource(\"some/test/EmbeddedClassRequiredParent.java\")\n                ))\n                .processedWith(new RealmProcessor())\n                .compilesWithoutError();\n    }\n\n\n    @Test\n    public void compileWithMultipleOptionalParents() {\n        assertAbout(javaSources())\n                .that(Arrays.asList(\n                        JavaFileObjects.forResource(\"some/test/EmbeddedClassParent.java\"),\n                        JavaFileObjects.forResource(\"some/test/EmbeddedClass.java\"),\n                        JavaFileObjects.forResource(\"some/test/EmbeddedClassRequiredParent.java\"),\n                        JavaFileObjects.forResource(\"some/test/EmbeddedClassOptionalParents.java\")\n                ))\n                .processedWith(new RealmProcessor())\n                .compilesWithoutError();\n    }\n\n    @Test\n    public void failToCompileIfSingleParentIsMissingFinal() {\n        assertAbout(javaSources())\n                .that(Arrays.asList(\n                        JavaFileObjects.forResource(\"some/test/EmbeddedClassParent.java\"),\n                        JavaFileObjects.forResource(\"some/test/EmbeddedClassMissingFinalOnLinkingObjects.java\")\n                ))\n                .processedWith(new RealmProcessor())\n                .failsToCompile()\n                .withErrorContaining(\"The @LinkingObjects field \\\"some.test.EmbeddedClassMissingFinalOnLinkingObjects.parent\\\" must be final.\");\n    }\n\n    // If a single parent type has multiple potential fields that can act as parent. Any\n    // @LinkingObject field in the child must designate the field name in the parent.\n    @Test\n    public void failToCompileIfMissingFieldDescriptor() {\n        assertAbout(javaSources())\n                .that(Arrays.asList(\n                        JavaFileObjects.forResource(\"some/test/EmbeddedClassParent.java\"),\n                        JavaFileObjects.forResource(\"some/test/EmbeddedClassMissingFieldDescription.java\")\n                ))\n                .processedWith(new RealmProcessor())\n                .failsToCompile()\n                .withErrorContaining(\"The @LinkingObjects annotation for the field \\\"some.test.EmbeddedClassMissingFieldDescription.parent1\\\" must have a parameter identifying the link target.\");\n    }\n\n\n    // @PrimaryKey is not allowed inside embedded classes\n    @Test\n    public void failToCompileWithPrimaryKey() {\n        assertAbout(javaSources())\n                .that(Arrays.asList(\n                        JavaFileObjects.forResource(\"some/test/EmbeddedClassPrimaryKey.java\")\n                ))\n                .processedWith(new RealmProcessor())\n                .failsToCompile()\n                .withErrorContaining(\"A model class marked as embedded cannot contain a @PrimaryKey.\");\n    }\n\n    // If a child has multiple potential parents, none of them are allowed to be marked\n    // @Required.\n    @Test\n    public void failToCompileWithMultipleRequiredParents() {\n        assertAbout(javaSources())\n                .that(Arrays.asList(\n                        JavaFileObjects.forResource(\"some/test/EmbeddedClassParent.java\"),\n                        JavaFileObjects.forResource(\"some/test/EmbeddedClassMultipleRequiredParents.java\")\n                ))\n                .processedWith(new RealmProcessor())\n                .failsToCompile()\n                .withErrorContaining(\"@Required cannot be used on @LinkingObjects field if multiple @LinkingParents are defined\");\n    }\n}\n"
  },
  {
    "path": "realm/realm-annotations-processor/src/test/java/io/realm/processor/RealmNameTest.java",
    "content": "package io.realm.processor;\n\nimport com.google.testing.compile.JavaFileObjects;\n\nimport org.junit.Test;\n\nimport java.util.Arrays;\n\nimport static com.google.common.truth.Truth.assertAbout;\nimport static com.google.testing.compile.JavaSourceSubjectFactory.javaSource;\nimport static com.google.testing.compile.JavaSourcesSubjectFactory.javaSources;\n\npublic class RealmNameTest {\n\n    // Check that a class only with class name policy compiles\n    @Test\n    public void compileOnlyClassNamePolicyFile() {\n        assertAbout(javaSource())\n                .that(JavaFileObjects.forResource(\"some/test/NamePolicyClassOnly.java\"))\n                .processedWith(new RealmProcessor())\n                .compilesWithoutError();\n    }\n\n    // Check that a class only with a field name policy compiles\n    @Test\n    public void compileOnlyFieldNamePolicyFile() {\n        assertAbout(javaSource())\n                .that(JavaFileObjects.forResource(\"some/test/NamePolicyFieldNameOnly.java\"))\n                .processedWith(new RealmProcessor())\n                .compilesWithoutError();\n    }\n\n    // Check that things compile if there is only a module with name policies defined\n    @Test\n    public void compileModuleWithNamePolicyFile() {\n        assertAbout(javaSource())\n                .that(JavaFileObjects.forResource(\"some/test/NamePolicyModule.java\"))\n                .processedWith(new RealmProcessor())\n                .compilesWithoutError();\n    }\n\n    // Check the effect of setting both module class/field name policies, class name, field\n    // name policy and explicit names on fields (i.e = Specific class name + field name should win.\n    @Test\n    public void compareProcessedNamingPolicyClassFile() {\n        assertAbout(javaSources())\n                .that(Arrays.asList(\n                    JavaFileObjects.forResource(\"some/test/NamePolicyModule.java\"),\n                    JavaFileObjects.forResource(\"some/test/NamePolicyMixedClassSettings.java\"),\n                    JavaFileObjects.forResource(\"some/test/NamePolicyFieldNameOnly.java\"),\n                    JavaFileObjects.forResource(\"some/test/NamePolicyClassOnly.java\")\n                ))\n                .processedWith(new RealmProcessor())\n                .compilesWithoutError()\n                .and()\n                .generatesSources(JavaFileObjects.forResource(\"io/realm/some_test_NamePolicyMixedClassSettingsRealmProxy.java\"));\n    }\n\n    // Check the effect of module default on a class with no settings itself\n    @Test\n    public void compareProcessedDefaultClassFile() {\n        assertAbout(javaSources())\n                .that(Arrays.asList(\n                        JavaFileObjects.forResource(\"some/test/NamePolicyModule.java\"),\n                        JavaFileObjects.forResource(\"some/test/NamePolicyModuleDefaults.java\")\n                ))\n                .processedWith(new RealmProcessor())\n                .compilesWithoutError()\n                .and()\n                .generatesSources(JavaFileObjects.forResource(\"io/realm/some_test_NamePolicyModuleDefaultsRealmProxy.java\"));\n    }\n\n    // Check that trying to compile two modules with different policies using `allClasses = true` will fail.\n    @Test\n    public void compileModulesWithConflictingPoliciesForAllClassesFails() {\n        assertAbout(javaSources())\n                .that(Arrays.asList(\n                        JavaFileObjects.forResource(\"some/test/NamePolicyConflictingModuleDefinitionsForAllClasses.java\"),\n                        JavaFileObjects.forResource(\"some/test/Simple.java\")\n                ))\n                .processedWith(new RealmProcessor())\n                .failsToCompile()\n                .withErrorContaining(\"disagree on the class naming policy\");\n    }\n\n    // Check that trying to compile two modules with different policies using `classes = { ... }` will fail.\n    @Test\n    public void compileModulesWithConflictingPoliciesForNamedClassesFails() {\n        assertAbout(javaSources())\n                .that(Arrays.asList(\n                        JavaFileObjects.forResource(\"some/test/NamePolicyConflictingModuleDefinitionsForNamedClasses.java\"),\n                        JavaFileObjects.forResource(\"some/test/Simple.java\")\n                ))\n                .processedWith(new RealmProcessor())\n                .failsToCompile()\n                .withErrorContaining(\"disagree on the class naming policy\");\n    }\n\n    // Check that trying to compile two modules with different policies using a mix of `allClasses`\n    // and `classes = { ... }` will fail.\n    @Test\n    public void compileModulesWithConflictingPoliciesAndMixedClassDefinitionsFails() {\n        assertAbout(javaSources())\n                .that(Arrays.asList(\n                        JavaFileObjects.forResource(\"some/test/NamePolicyConflictingModuleDefinitionsForMixedDefinitions.java\"),\n                        JavaFileObjects.forResource(\"some/test/Simple.java\")\n                ))\n                .processedWith(new RealmProcessor())\n                .failsToCompile()\n                .withErrorContaining(\"disagree on the class naming policy\");\n    }\n\n}\n"
  },
  {
    "path": "realm/realm-annotations-processor/src/test/java/io/realm/processor/RealmProcessorTest.java",
    "content": "/*\n * Copyright 2014-2017 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\npackage io.realm.processor;\n\nimport com.google.testing.compile.JavaFileObjects;\n\nimport org.junit.Ignore;\nimport org.junit.Test;\n\nimport java.io.IOException;\nimport java.util.Arrays;\n\nimport javax.tools.JavaFileObject;\n\nimport static com.google.common.truth.Truth.assertAbout;\nimport static com.google.testing.compile.JavaSourceSubjectFactory.javaSource;\nimport static com.google.testing.compile.JavaSourcesSubjectFactory.javaSources;\n\n\npublic class RealmProcessorTest {\n    private final JavaFileObject simpleModel = JavaFileObjects.forResource(\"some/test/Simple.java\");\n    private final JavaFileObject simpleProxy = JavaFileObjects.forResource(\"io/realm/some_test_SimpleRealmProxy.java\");\n    private final JavaFileObject allTypesModel = JavaFileObjects.forResource(\"some/test/AllTypes.java\");\n    private final JavaFileObject allTypesProxy = JavaFileObjects.forResource(\"io/realm/some_test_AllTypesRealmProxy.java\");\n    private final JavaFileObject allTypesDefaultModule = JavaFileObjects.forResource(\"io/realm/DefaultRealmModule.java\");\n    private final JavaFileObject allTypesDefaultMediator = JavaFileObjects.forResource(\"io/realm/DefaultRealmModuleMediator.java\");\n    private final JavaFileObject booleansModel = JavaFileObjects.forResource(\"some/test/Booleans.java\");\n    private final JavaFileObject booleansProxy = JavaFileObjects.forResource(\"io/realm/some_test_BooleansRealmProxy.java\");\n    private final JavaFileObject emptyModel = JavaFileObjects.forResource(\"some/test/Empty.java\");\n    private final JavaFileObject finalModel = JavaFileObjects.forResource(\"some/test/Final.java\");\n    private final JavaFileObject transientModel = JavaFileObjects.forResource(\"some/test/Transient.java\");\n    private final JavaFileObject volatileModel = JavaFileObjects.forResource(\"some/test/Volatile.java\");\n    private final JavaFileObject fieldNamesModel = JavaFileObjects.forResource(\"some/test/FieldNames.java\");\n    private final JavaFileObject customAccessorModel = JavaFileObjects.forResource(\"some/test/CustomAccessor.java\");\n    private final JavaFileObject nullTypesModel = JavaFileObjects.forResource(\"some/test/NullTypes.java\");\n    private final JavaFileObject nullTypesProxy = JavaFileObjects.forResource(\"io/realm/some_test_NullTypesRealmProxy.java\");\n    private final JavaFileObject missingGenericTypeModel = JavaFileObjects.forResource(\"some/test/MissingGenericType.java\");\n    private final JavaFileObject conflictingFieldNameModel = JavaFileObjects.forResource(\"some/test/ConflictingFieldName.java\");\n    private final JavaFileObject invalidRealmModelModel_1 = JavaFileObjects.forResource(\"some/test/InvalidModelRealmModel_1.java\");\n    private final JavaFileObject invalidRealmModelModel_2 = JavaFileObjects.forResource(\"some/test/InvalidModelRealmModel_2.java\");\n    private final JavaFileObject invalidRealmModelModel_3 = JavaFileObjects.forResource(\"some/test/InvalidModelRealmModel_3.java\");\n    private final JavaFileObject ValidModelPojo_ExtendingRealmObject = JavaFileObjects.forResource(\"some/test/ValidModelRealmModel_ExtendingRealmObject.java\");\n    private final JavaFileObject UseExtendRealmList = JavaFileObjects.forResource(\"some/test/UseExtendRealmList.java\");\n    private final JavaFileObject SimpleRealmModel = JavaFileObjects.forResource(\"some/test/SimpleRealmModel.java\");\n    private final JavaFileObject customInterface = JavaFileObjects.forResource(\"some/test/CustomInterface.java\");\n    private final JavaFileObject nonLatinName = JavaFileObjects.forResource(\"some/test/ÁrvíztűrőTükörfúrógép.java\");\n    private final JavaFileObject realmMapModel = JavaFileObjects.forResource(\"some/test/RealmMapModel.java\");\n    private final JavaFileObject realmDictionaryMissingGenericsModel = JavaFileObjects.forResource(\"some/test/RealmDictionaryMissingGenerics.java\");\n    private final JavaFileObject realmDictionaryModel = JavaFileObjects.forResource(\"some/test/RealmDictionaryModel.java\");\n    private final JavaFileObject realmDictionaryModelWrongType = JavaFileObjects.forResource(\"some/test/RealmDictionaryModelWrongType.java\");\n    private final JavaFileObject realmDictionaryModelRealmAnyRequired = JavaFileObjects.forResource(\"some/test/RealmDictionaryModelRealmAnyRequired.java\");\n    private final JavaFileObject realmDictionaryModelRealmModelRequired = JavaFileObjects.forResource(\"some/test/RealmDictionaryModelRealmModelRequired.java\");\n    private final JavaFileObject realmSetModel = JavaFileObjects.forResource(\"some/test/RealmSetModel.java\");\n    private final JavaFileObject realmSetModelWrongType = JavaFileObjects.forResource(\"some/test/RealmSetModelWrongType.java\");\n    private final JavaFileObject realmSetMissingGenericsModel = JavaFileObjects.forResource(\"some/test/RealmSetMissingGenerics.java\");\n    private final JavaFileObject embeddedObject = JavaFileObjects.forResource(\"some/test/EmbeddedObject.java\");\n\n    @Test\n    public void compileSimpleFile() {\n        assertAbout(javaSource())\n                .that(simpleModel)\n                .compilesWithoutError();\n    }\n\n    @Test\n    public void compileProcessedSimpleFile() {\n        assertAbout(javaSource())\n                .that(simpleModel)\n                .processedWith(new RealmProcessor())\n                .compilesWithoutError();\n    }\n\n    @Test\n    public void compileProcessedEmptyFile() {\n        assertAbout(javaSource())\n                .that(emptyModel)\n                .processedWith(new RealmProcessor())\n                .failsToCompile();\n    }\n\n    @Ignore(\"Disabled because it does not seem to find the generated interface file\")\n    @Test\n    public void compileSimpleProxyFile() {\n        assertAbout(javaSource())\n                .that(simpleProxy)\n                .compilesWithoutError();\n    }\n\n    @Test\n    public void compareProcessedSimpleFile() {\n        assertAbout(javaSource())\n                .that(simpleModel)\n                .processedWith(new RealmProcessor())\n                .compilesWithoutError()\n                .and()\n                .generatesSources(simpleProxy);\n    }\n\n    @Test\n    public void compileProcessedNullTypesFile() {\n        assertAbout(javaSource())\n                .that(nullTypesModel)\n                .processedWith(new RealmProcessor())\n                .compilesWithoutError();\n    }\n\n    @Test\n    public void compareProcessedNullTypesFile() {\n        assertAbout(javaSource())\n                .that(nullTypesModel)\n                .processedWith(new RealmProcessor())\n                .compilesWithoutError()\n                .and()\n                .generatesSources(nullTypesProxy);\n    }\n\n    @Test\n    public void compileAllTypesFile() {\n        assertAbout(javaSource())\n                .that(allTypesModel)\n                .compilesWithoutError();\n    }\n\n    @Test\n    public void compileProcessedAllTypesFile() {\n        assertAbout(javaSources())\n                .that(Arrays.asList(allTypesModel, simpleModel))\n                .processedWith(new RealmProcessor())\n                .compilesWithoutError();\n    }\n\n    @Test\n    public void compileAllTypesProxyFile() {\n        assertAbout(javaSource())\n                .that(allTypesModel)\n                .compilesWithoutError();\n    }\n\n    @Test\n    public void compareProcessedAllTypesFile() {\n        assertAbout(javaSources())\n                .that(Arrays.asList(allTypesModel, simpleModel))\n                .processedWith(new RealmProcessor())\n                .compilesWithoutError()\n                .and()\n                .generatesSources(allTypesDefaultModule, allTypesProxy, allTypesDefaultMediator);\n    }\n\n    @Test\n    public void compileAppModuleCustomClasses() {\n        assertAbout(javaSources())\n                .that(Arrays.asList(allTypesModel, simpleModel, JavaFileObjects.forResource(\"some/test/AppModuleCustomClasses.java\")))\n                .processedWith(new RealmProcessor())\n                .compilesWithoutError();\n    }\n\n    @Test\n    public void compileAppModuleAllClasses() {\n        assertAbout(javaSources())\n                .that(Arrays.asList(allTypesModel, simpleModel, JavaFileObjects.forResource(\"some/test/AppModuleAllClasses.java\")))\n                .processedWith(new RealmProcessor())\n                .compilesWithoutError();\n    }\n\n    @Test\n    public void compileLibraryModulesAllClasses() {\n        assertAbout(javaSources())\n                .that(Arrays.asList(allTypesModel, simpleModel, JavaFileObjects.forResource(\"some/test/LibraryModuleAllClasses.java\")))\n                .processedWith(new RealmProcessor())\n                .compilesWithoutError();\n    }\n\n    @Test\n    public void compileLibraryModulesCustomClasses() {\n        assertAbout(javaSources())\n                .that(Arrays.asList(allTypesModel, simpleModel, JavaFileObjects.forResource(\"some/test/LibraryModuleCustomClasses.java\")))\n                .processedWith(new RealmProcessor())\n                .compilesWithoutError();\n    }\n\n    @Test\n    public void compileAppModuleMixedParametersFail() {\n        assertAbout(javaSources())\n                .that(Arrays.asList(allTypesModel, JavaFileObjects.forResource(\n                        \"some/test/InvalidAllTypesModuleMixedParameters.java\")))\n                .processedWith(new RealmProcessor())\n                .failsToCompile();\n    }\n\n    @Test\n    public void compileAppModuleWrongTypeFail() {\n        assertAbout(javaSources())\n                .that(Arrays.asList(allTypesModel, JavaFileObjects.forResource(\n                        \"some/test/InvalidAllTypesModuleWrongType.java\")))\n                .processedWith(new RealmProcessor())\n                .failsToCompile();\n    }\n\n    @Test\n    public void compileLibraryModuleMixedParametersFail() {\n        assertAbout(javaSources())\n                .that(Arrays.asList(allTypesModel, JavaFileObjects.forResource(\"some/test/InvalidLibraryModuleMixedParameters.java\")))\n                .processedWith(new RealmProcessor())\n                .failsToCompile();\n    }\n\n    @Test\n    public void compileLibraryModuleWrongTypeFail() {\n        assertAbout(javaSources())\n                .that(Arrays.asList(allTypesModel, JavaFileObjects.forResource(\"some/test/InvalidLibraryModuleWrongType.java\")))\n                .processedWith(new RealmProcessor())\n                .failsToCompile();\n    }\n\n    @Test\n    public void compileBooleanFile() {\n        assertAbout(javaSource())\n                .that(booleansModel)\n                .compilesWithoutError();\n    }\n\n    @Test\n    public void compileProcessedBooleansFile() {\n        assertAbout(javaSource())\n                .that(booleansModel)\n                .processedWith(new RealmProcessor())\n                .compilesWithoutError();\n    }\n\n    @Test\n    public void compileBooleansProxyFile() {\n        assertAbout(javaSource())\n                .that(booleansModel)\n                .compilesWithoutError();\n    }\n\n    @Test\n    public void compareProcessedBooleansFile() {\n        assertAbout(javaSource())\n                .that(booleansModel)\n                .processedWith(new RealmProcessor())\n                .compilesWithoutError()\n                .and()\n                .generatesSources(booleansProxy);\n    }\n\n    @Test\n    public void compileMissingGenericType() {\n        assertAbout(javaSource())\n                .that(missingGenericTypeModel)\n                .processedWith(new RealmProcessor())\n                .failsToCompile();\n    }\n\n    @Test\n    @Ignore(\"Disabled because it does not find the generated Interface file\")\n    public void compileFieldNamesFiles() {\n        assertAbout(javaSource())\n                .that(fieldNamesModel)\n                .processedWith(new RealmProcessor())\n                .compilesWithoutError();\n    }\n\n    @Test\n    public void compileCustomAccessor() {\n        assertAbout(javaSource())\n                .that(customAccessorModel)\n                .processedWith(new RealmProcessor())\n                .failsToCompile();\n    }\n\n    // Supported \"Index\" annotation types\n    @Test\n    public void compileIndexTypes() throws IOException {\n        final String[] validIndexFieldTypes = {\"byte\", \"short\", \"int\", \"long\", \"boolean\", \"String\", \"java.util.Date\",\n                \"Byte\", \"Short\", \"Integer\", \"Long\", \"Boolean\", \"org.bson.types.ObjectId\", \"java.util.UUID\"};\n\n        for (String fieldType : validIndexFieldTypes) {\n            RealmSyntheticTestClass javaFileObject =\n                    new RealmSyntheticTestClass.Builder().name(\"ValidIndexType\").field(\"testField\", fieldType, \"Index\").build();\n            assertAbout(javaSource())\n                    .that(javaFileObject)\n                    .processedWith(new RealmProcessor())\n                    .compilesWithoutError();\n        }\n    }\n\n    // Unsupported \"Index\" annotation types\n    @Test\n    public void compileInvalidIndexTypes() throws IOException {\n        final String[] invalidIndexFieldTypes = {\"float\", \"double\", \"byte[]\", \"Simple\", \"RealmList\", \"Float\", \"Double\", \"org.bson.types.Decimal128\"};\n\n        for (String fieldType : invalidIndexFieldTypes) {\n            RealmSyntheticTestClass javaFileObject =\n                    new RealmSyntheticTestClass.Builder().name(\"InvalidIndexType\").field(\"testField\", fieldType, \"Index\").build();\n            assertAbout(javaSource())\n                    .that(javaFileObject)\n                    .processedWith(new RealmProcessor())\n                    .failsToCompile();\n        }\n    }\n\n    // Supported \"PrimaryKey\" annotation types\n    @Test\n    public void compilePrimaryKeyTypes() throws IOException {\n        final String[] validPrimaryKeyFieldTypes = {\"byte\", \"short\", \"int\", \"long\", \"String\", \"Byte\", \"Short\", \"Integer\", \"Long\", \"org.bson.types.ObjectId\", \"java.util.UUID\"};\n\n        for (String fieldType : validPrimaryKeyFieldTypes) {\n            RealmSyntheticTestClass javaFileObject =\n                    new RealmSyntheticTestClass.Builder().name(\"ValidPrimaryKeyType\").field(\"testField\", fieldType, \"PrimaryKey\").build();\n            assertAbout(javaSource())\n                    .that(javaFileObject)\n                    .processedWith(new RealmProcessor())\n                    .compilesWithoutError();\n        }\n    }\n\n    // Unsupported \"PrimaryKey\" annotation types\n    @Test\n    public void compileInvalidPrimaryKeyTypes() throws IOException {\n        final String[] invalidPrimaryKeyFieldTypes = {\"boolean\", \"java.util.Date\", \"Simple\", \"RealmList<Simple>\", \"Boolean\", \"org.bson.types.Decimal128\"};\n\n        for (String fieldType : invalidPrimaryKeyFieldTypes) {\n            RealmSyntheticTestClass javaFileObject =\n                    new RealmSyntheticTestClass.Builder().name(\"InvalidPrimaryKeyType\").field(\"testField\", fieldType, \"PrimaryKey\").build();\n            assertAbout(javaSource())\n                    .that(javaFileObject)\n                    .processedWith(new RealmProcessor())\n                    .failsToCompile();\n        }\n    }\n\n    // Supported \"Required\" annotation types\n    @Test\n    public void compileRequiredTypes() throws IOException {\n        final String[] validPrimaryKeyFieldTypes = {\"Byte\", \"Short\", \"Integer\", \"Long\", \"String\",\n                \"Float\", \"Double\", \"Boolean\", \"java.util.Date\", \"org.bson.types.ObjectId\", \"org.bson.types.Decimal128\", \"java.util.UUID\"};\n\n        for (String fieldType : validPrimaryKeyFieldTypes) {\n            RealmSyntheticTestClass javaFileObject =\n                    new RealmSyntheticTestClass.Builder().name(\"ValidRequiredType\").field(\"testField\", fieldType, \"Required\").build();\n            assertAbout(javaSource())\n                    .that(javaFileObject)\n                    .processedWith(new RealmProcessor())\n                    .compilesWithoutError();\n        }\n    }\n\n    // Not supported \"Required\" annotation types\n    @Test\n    public void compileInvalidRequiredTypes() throws IOException {\n        final String[] invalidRequiredAnnotationFieldTypes = {\"byte\", \"short\", \"int\", \"long\", \"float\", \"double\",\n                \"boolean\", \"RealmList<Simple>\", \"Simple\", \"RealmAny\", \"RealmList<RealmAny>\", \"RealmDictionary<Simple>\",\n                \"RealmDictionary<RealmAny>\", \"RealmSet<Simple>\", \"RealmSet<RealmAny>\"};\n\n        for (String fieldType : invalidRequiredAnnotationFieldTypes) {\n            RealmSyntheticTestClass javaFileObject = new RealmSyntheticTestClass.Builder()\n                    .name(\"InvalidRequiredType\")\n                    .field(\"testField\", fieldType, \"Required\")\n                    .build();\n            assertAbout(javaSources())\n                    .that(Arrays.asList(simpleModel, javaFileObject))\n                    .processedWith(new RealmProcessor())\n                    .failsToCompile();\n        }\n    }\n\n    @Test\n    public void compileSetWithEmbeddedObjectNotSupported() throws IOException {\n        RealmSyntheticTestClass.Builder builder = new RealmSyntheticTestClass.Builder()\n                .name(\"InvalidRequiredType\");\n\n        builder.field()\n                .name(\"embeddedSet\")\n                .type(\"RealmSet<EmbeddedObject>\");\n\n        assertAbout(javaSources())\n                .that(Arrays.asList(embeddedObject, builder.build()))\n                .processedWith(new RealmProcessor())\n                .failsToCompile();\n    }\n\n    @Test\n    public void compileConflictingFieldName() {\n        assertAbout(javaSource())\n                .that(conflictingFieldNameModel)\n                .processedWith(new RealmProcessor())\n                .compilesWithoutError();\n    }\n\n    @Test\n    public void failOnFinalFields() {\n        assertAbout(javaSource())\n                .that(finalModel)\n                .processedWith(new RealmProcessor())\n                .failsToCompile();\n    }\n\n    @Test\n    public void compileTransientFields() {\n        assertAbout(javaSource())\n                .that(transientModel)\n                .processedWith(new RealmProcessor())\n                .compilesWithoutError();\n    }\n\n    @Test\n    public void failOnVolatileFields() {\n        assertAbout(javaSource())\n                .that(volatileModel)\n                .processedWith(new RealmProcessor())\n                .failsToCompile();\n    }\n\n    // annotation without implementing RealmModel interface\n    @Test\n    public void failOnInvalidRealmModel_1() {\n        assertAbout(javaSource())\n                .that(invalidRealmModelModel_1)\n                .processedWith(new RealmProcessor())\n                .failsToCompile();\n    }\n\n    // it's not allowed to extend from another RealmObject\n    @Test\n    public void failOnInvalidRealmModel_2() {\n        assertAbout(javaSource())\n                .that(invalidRealmModelModel_2)\n                .processedWith(new RealmProcessor())\n                .failsToCompile();\n    }\n\n    // it's not allowed to extend from another RealmObject\n    @Test\n    public void failOnInvalidRealmModel_3() {\n        assertAbout(javaSource())\n                .that(invalidRealmModelModel_3)\n                .processedWith(new RealmProcessor())\n                .failsToCompile();\n    }\n\n    @Test\n    public void validRealmModelUsingInheritance() {\n        assertAbout(javaSource())\n                .that(ValidModelPojo_ExtendingRealmObject)\n                .processedWith(new RealmProcessor())\n                .compilesWithoutError();\n    }\n\n    @Test\n    public void canNotInheritRealmList() {\n        assertAbout(javaSource())\n                .that(UseExtendRealmList)\n                .processedWith(new RealmProcessor())\n                .failsToCompile();\n    }\n\n    @Test\n    public void compileWithRealmModelFieldInReamlModel() {\n        assertAbout(javaSource())\n                .that(SimpleRealmModel)\n                .processedWith(new RealmProcessor())\n                .compilesWithoutError();\n    }\n\n    @Test\n    public void compileWithInterfaceForList() {\n        assertAbout(javaSources())\n                .that(Arrays.asList(JavaFileObjects.forResource(\"some/test/InterfaceList.java\"), customInterface))\n                .processedWith(new RealmProcessor())\n                .failsToCompile();\n    }\n\n    @Test\n    public void compileWithInterfaceForObject() {\n        assertAbout(javaSources())\n                .that(Arrays.asList(JavaFileObjects.forResource(\"some/test/InterfaceObjectReference.java\"), customInterface))\n                .processedWith(new RealmProcessor())\n                .failsToCompile();\n    }\n\n    @Test\n    public void compareNonLatinName() {\n        assertAbout(javaSource())\n                .that(nonLatinName)\n                .processedWith(new RealmProcessor())\n                .compilesWithoutError();\n    }\n\n    @Test\n    public void compileRealmMapModelNotAllowed() {\n        assertAbout(javaSource())\n                .that(realmMapModel)\n                .processedWith(new RealmProcessor())\n                .failsToCompile();\n    }\n\n    @Test\n    public void compileRealmDictionaryMissingGenerics() {\n        assertAbout(javaSource())\n                .that(realmDictionaryMissingGenericsModel)\n                .processedWith(new RealmProcessor())\n                .failsToCompile();\n    }\n\n    @Test\n    public void compileRealmDictionaryModel() {\n        assertAbout(javaSource())\n                .that(realmDictionaryModel)\n                .processedWith(new RealmProcessor())\n                .compilesWithoutError();\n    }\n\n    @Test\n    public void compileRealmDictionaryModelWrongType() {\n        assertAbout(javaSource())\n                .that(realmDictionaryModelWrongType)\n                .processedWith(new RealmProcessor())\n                .failsToCompile();\n    }\n\n\n    @Test\n    public void compileRealmDictionaryModelRealmAnyRequiredFails() {\n        assertAbout(javaSource())\n                .that(realmDictionaryModelRealmAnyRequired)\n                .processedWith(new RealmProcessor())\n                .failsToCompile();\n    }\n\n    @Test\n    public void compileRealmDictionaryModelRealmModelRequiredFails() {\n        assertAbout(javaSource())\n                .that(realmDictionaryModelRealmModelRequired)\n                .processedWith(new RealmProcessor())\n                .failsToCompile();\n    }\n\n    @Test\n    public void compileRealmSetModel() {\n        assertAbout(javaSource())\n                .that(realmSetModel)\n                .processedWith(new RealmProcessor())\n                .compilesWithoutError();\n    }\n\n    @Test\n    public void compileRealmSetModelWrongType() {\n        assertAbout(javaSource())\n                .that(realmSetModelWrongType)\n                .processedWith(new RealmProcessor())\n                .failsToCompile();\n    }\n\n    @Test\n    public void compileRealmSetMissingGenerics() {\n        assertAbout(javaSource())\n                .that(realmSetMissingGenericsModel)\n                .processedWith(new RealmProcessor())\n                .failsToCompile();\n    }\n}\n"
  },
  {
    "path": "realm/realm-annotations-processor/src/test/java/io/realm/processor/RealmSyntheticTestClass.java",
    "content": "/*\n * Copyright 2015-2017 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\npackage io.realm.processor;\n\nimport com.squareup.javawriter.JavaWriter;\n\nimport java.io.IOException;\nimport java.io.StringWriter;\nimport java.net.URI;\nimport java.util.ArrayList;\nimport java.util.EnumSet;\nimport java.util.List;\n\nimport javax.lang.model.element.Modifier;\nimport javax.tools.SimpleJavaFileObject;\n\n// Helper class for creating RealmObject java files\npublic class RealmSyntheticTestClass extends SimpleJavaFileObject {\n    public static class Field {\n        private final Builder builder;\n        private String name;\n        private String type;\n        private String initializer;\n        private boolean hasGetter = true;\n        private boolean hasSetter = true;\n        private EnumSet<Modifier> modifiers = EnumSet.of(Modifier.PRIVATE);\n        private final List<String> annotations = new ArrayList<String>();\n\n        Field(Builder builder) {\n            this.builder = builder;\n        }\n\n        public Field name(String name) {\n            this.name = name.substring(0, 1).toUpperCase() + name.substring(1, name.length());\n            return this;\n        }\n\n        public Field type(String type) {\n            this.type = type;\n            return this;\n        }\n\n        public Field modifiers(Modifier... modifiers) {\n            this.modifiers = EnumSet.of(modifiers[0], modifiers); // yuk\n            return this;\n        }\n\n        public Field clearAnnotations() {\n            this.annotations.clear();\n            return this;\n        }\n\n        public Field annotation(String annotation) {\n            this.annotations.add(annotation);\n            return this;\n        }\n\n        public Field initializer(String initializer) {\n            this.initializer = initializer;\n            return this;\n        }\n\n        public Field hasGetter(boolean hasGetter) {\n            this.hasGetter = hasGetter;\n            return this;\n        }\n\n        public Field hasSetter(boolean hasSetter) {\n            this.hasSetter = hasSetter;\n            return this;\n        }\n\n        public Builder builder() {\n            return builder;\n        }\n    }\n\n    public static class Builder {\n        private final List<Field> fields = new ArrayList<Field>();\n        private String name;\n\n        public Builder name(String name) {\n            this.name = name;\n            return this;\n        }\n\n        // Note: this returns the new field, not the builder.\n        // To get the builder back, use Field.builder()\n        public Field field() {\n            Field f = new Field(this);\n            fields.add(f);\n            return f;\n        }\n\n        // Convenience method to support legacy usage\n        public Builder field(String name, String type, String annotation) {\n            field().name(name).type(type).annotation(annotation);\n            return this;\n        }\n\n        public RealmSyntheticTestClass build() throws IOException {\n            StringWriter stringWriter = new StringWriter();\n            JavaWriter writer = new JavaWriter(stringWriter);\n\n            // Package name\n            writer.emitPackage(\"some.test\");\n\n            // Import Realm classes\n            writer.emitImports(\"io.realm.*\");\n            writer.emitImports(\"io.realm.annotations.*\");\n\n            // Begin the class definition\n            writer.beginType(\n                    name,                        // full qualified name of the item to generate\n                    \"class\",                     // the type of the item\n                    EnumSet.of(Modifier.PUBLIC), // modifiers to apply\n                    \"RealmObject\")               // class to extend\n                    .emitEmptyLine();\n\n            for (Field field : fields) { generateField(writer, field); }\n\n            writer.endType();\n\n            return new RealmSyntheticTestClass(stringWriter, name);\n        }\n\n        private void generateField(JavaWriter writer, Field field) throws IOException {\n            if (field.name == null) { throw new IllegalArgumentException(\"A field must have a name\"); }\n            if (field.type == null) { throw new IllegalArgumentException(\"A field must have a type\"); }\n\n            // Declaration of field\n            for (String annotation : field.annotations) { writer.emitAnnotation(annotation); }\n            writer.emitField(field.type, field.name, field.modifiers, field.initializer);\n\n            if (field.hasSetter) { emitSetter(writer, field); }\n            if (field.hasGetter) { emitGetter(writer, field); }\n       }\n\n        private void emitSetter(JavaWriter writer, Field field) throws IOException {\n            // Setter\n            writer.beginMethod(\n                    \"void\", // Return type\n                    \"set\" + field.name, // Method name\n                    EnumSet.of(Modifier.PUBLIC), field.type, field.name); // Modifiers\n            writer.emitStatement(\"realmSet$\" + field.name + \"(\" + field.name + \")\");\n            writer.endMethod();\n\n            // Realm Setter\n            writer.beginMethod(\n                    \"void\", // Return type\n                    \"realmSet$\" + field.name, // Method name\n                    EnumSet.of(Modifier.PUBLIC), field.type, field.name); // Modifiers\n            writer.emitStatement(\"this.\" + field.name + \"=\" + field.name);\n            writer.endMethod();\n        }\n\n        private void emitGetter(JavaWriter writer, Field field) throws IOException {\n            // Getter\n            writer.beginMethod(\n                    field.type, // Return type\n                    \"get\" + field.name, // Method name\n                    EnumSet.of(Modifier.PUBLIC)); // Modifiers\n            writer.emitStatement(\"return realmGet$\" + field.name + \"()\");\n            writer.endMethod();\n\n            // Realm Getter\n            writer.beginMethod(\n                    field.type, // Return type\n                    \"realmGet$\" + field.name, // Method name\n                    EnumSet.of(Modifier.PUBLIC)); // Modifiers\n            writer.emitStatement(\"return \" + field.name);\n            writer.endMethod();\n        }\n    }\n\n    private final StringWriter stringWriter;\n\n    private RealmSyntheticTestClass(StringWriter stringWriter, String name) {\n        super(URI.create(name + \".java\"), Kind.SOURCE);\n        this.stringWriter = stringWriter;\n    }\n\n    @Override\n    public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {\n        return stringWriter.getBuffer();\n    }\n}\n"
  },
  {
    "path": "realm/realm-annotations-processor/src/test/java/io/realm/processor/ValueListProcessorTest.java",
    "content": "/*\n * Copyright 2017 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 */\npackage io.realm.processor;\n\nimport com.google.testing.compile.JavaFileObjects;\n\nimport org.junit.Ignore;\nimport org.junit.Test;\n\nimport javax.tools.JavaFileObject;\n\nimport static com.google.common.truth.Truth.assertAbout;\nimport static com.google.testing.compile.JavaSourceSubjectFactory.javaSource;\n\n\npublic class ValueListProcessorTest {\n    private final JavaFileObject valueList = JavaFileObjects.forResource(\"some/test/ValueList.java\");\n    private final JavaFileObject invalidListValueType = JavaFileObjects.forResource(\"some/test/InvalidListElementType.java\");\n\n    @Test\n    @Ignore(\"need to implement primitive list support in realm-library\")\n    public void compileValueList() {\n        assertAbout(javaSource())\n                .that(valueList)\n                .processedWith(new RealmProcessor())\n                .compilesWithoutError();\n    }\n\n    @Test\n    public void failToCompileInvalidListElementType() {\n        assertAbout(javaSource())\n                .that(invalidListValueType)\n                .processedWith(new RealmProcessor())\n                .failsToCompile();\n    }\n}\n"
  },
  {
    "path": "realm/realm-annotations-processor/src/test/resources/io/realm/DefaultRealmModule.java",
    "content": "package io.realm;\n\n\n@io.realm.annotations.RealmModule(allClasses = true)\nclass DefaultRealmModule {\n\n}\n"
  },
  {
    "path": "realm/realm-annotations-processor/src/test/resources/io/realm/DefaultRealmModuleMediator.java",
    "content": "package io.realm;\n\n\nimport android.util.JsonReader;\nimport io.realm.ImportFlag;\nimport io.realm.internal.ColumnInfo;\nimport io.realm.internal.OsObjectSchemaInfo;\nimport io.realm.internal.OsSchemaInfo;\nimport io.realm.internal.RealmObjectProxy;\nimport io.realm.internal.RealmProxyMediator;\nimport io.realm.internal.Row;\nimport java.io.IOException;\nimport java.util.Collection;\nimport java.util.Collections;\nimport java.util.HashMap;\nimport java.util.HashSet;\nimport java.util.Iterator;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Set;\nimport org.json.JSONException;\nimport org.json.JSONObject;\n\n@io.realm.annotations.RealmModule\nclass DefaultRealmModuleMediator extends RealmProxyMediator {\n\n    private static final Set<Class<? extends RealmModel>> MODEL_CLASSES;\n    static {\n        Set<Class<? extends RealmModel>> modelClasses = new HashSet<Class<? extends RealmModel>>(2);\n        modelClasses.add(some.test.Simple.class);\n        modelClasses.add(some.test.AllTypes.class);\n        MODEL_CLASSES = Collections.unmodifiableSet(modelClasses);\n    }\n\n    @Override\n    public Map<Class<? extends RealmModel>, OsObjectSchemaInfo> getExpectedObjectSchemaInfoMap() {\n        Map<Class<? extends RealmModel>, OsObjectSchemaInfo> infoMap = new HashMap<Class<? extends RealmModel>, OsObjectSchemaInfo>(2);\n        infoMap.put(some.test.Simple.class, io.realm.some_test_SimpleRealmProxy.getExpectedObjectSchemaInfo());\n        infoMap.put(some.test.AllTypes.class, io.realm.some_test_AllTypesRealmProxy.getExpectedObjectSchemaInfo());\n        return infoMap;\n    }\n\n    @Override\n    public ColumnInfo createColumnInfo(Class<? extends RealmModel> clazz, OsSchemaInfo schemaInfo) {\n        checkClass(clazz);\n\n        if (clazz.equals(some.test.Simple.class)) {\n            return io.realm.some_test_SimpleRealmProxy.createColumnInfo(schemaInfo);\n        }\n        if (clazz.equals(some.test.AllTypes.class)) {\n            return io.realm.some_test_AllTypesRealmProxy.createColumnInfo(schemaInfo);\n        }\n        throw getMissingProxyClassException(clazz);\n    }\n\n    @Override\n    public String getSimpleClassNameImpl(Class<? extends RealmModel> clazz) {\n        checkClass(clazz);\n\n        if (clazz.equals(some.test.Simple.class)) {\n            return \"Simple\";\n        }\n        if (clazz.equals(some.test.AllTypes.class)) {\n            return \"AllTypes\";\n        }\n        throw getMissingProxyClassException(clazz);\n    }\n\n    @Override\n    public Class<? extends RealmModel> getClazzImpl(String className) {\n        checkClassName(className);\n\n        if (className.equals(\"Simple\")) {\n            return some.test.Simple.class;\n        }\n        if (className.equals(\"AllTypes\")) {\n            return some.test.AllTypes.class;\n        }\n        throw getMissingProxyClassException(className);\n    }\n\n    @Override\n    public boolean hasPrimaryKeyImpl(Class<? extends RealmModel> clazz) {\n        return some.test.AllTypes.class.isAssignableFrom(clazz);\n    }\n\n    @Override\n    public <E extends RealmModel> E newInstance(Class<E> clazz, Object baseRealm, Row row, ColumnInfo columnInfo, boolean acceptDefaultValue, List<String> excludeFields) {\n        final BaseRealm.RealmObjectContext objectContext = BaseRealm.objectContext.get();\n        try {\n            objectContext.set((BaseRealm) baseRealm, row, columnInfo, acceptDefaultValue, excludeFields);\n            checkClass(clazz);\n\n            if (clazz.equals(some.test.Simple.class)) {\n                return clazz.cast(new io.realm.some_test_SimpleRealmProxy());\n            }\n            if (clazz.equals(some.test.AllTypes.class)) {\n                return clazz.cast(new io.realm.some_test_AllTypesRealmProxy());\n            }\n            throw getMissingProxyClassException(clazz);\n        } finally {\n            objectContext.clear();\n        }\n    }\n\n    @Override\n    public Set<Class<? extends RealmModel>> getModelClasses() {\n        return MODEL_CLASSES;\n    }\n\n    @Override\n    public <E extends RealmModel> E copyOrUpdate(Realm realm, E obj, boolean update, Map<RealmModel, RealmObjectProxy> cache, Set<ImportFlag> flags) {\n        // This cast is correct because obj is either\n        // generated by RealmProxy or the original type extending directly from RealmObject\n        @SuppressWarnings(\"unchecked\") Class<E> clazz = (Class<E>) ((obj instanceof RealmObjectProxy) ? obj.getClass().getSuperclass() : obj.getClass());\n\n        if (clazz.equals(some.test.Simple.class)) {\n            some_test_SimpleRealmProxy.SimpleColumnInfo columnInfo = (some_test_SimpleRealmProxy.SimpleColumnInfo) realm.getSchema().getColumnInfo(some.test.Simple.class);\n            return clazz.cast(io.realm.some_test_SimpleRealmProxy.copyOrUpdate(realm, columnInfo, (some.test.Simple) obj, update, cache, flags));\n        }\n        if (clazz.equals(some.test.AllTypes.class)) {\n            some_test_AllTypesRealmProxy.AllTypesColumnInfo columnInfo = (some_test_AllTypesRealmProxy.AllTypesColumnInfo) realm.getSchema().getColumnInfo(some.test.AllTypes.class);\n            return clazz.cast(io.realm.some_test_AllTypesRealmProxy.copyOrUpdate(realm, columnInfo, (some.test.AllTypes) obj, update, cache, flags));\n        }\n        throw getMissingProxyClassException(clazz);\n    }\n\n    @Override\n    public long insert(Realm realm, RealmModel object, Map<RealmModel, Long> cache) {\n        // This cast is correct because obj is either\n        // generated by RealmProxy or the original type extending directly from RealmObject\n        @SuppressWarnings(\"unchecked\") Class<RealmModel> clazz = (Class<RealmModel>) ((object instanceof RealmObjectProxy) ? object.getClass().getSuperclass() : object.getClass());\n\n        if (clazz.equals(some.test.Simple.class)) {\n            return io.realm.some_test_SimpleRealmProxy.insert(realm, (some.test.Simple) object, cache);\n        } else if (clazz.equals(some.test.AllTypes.class)) {\n            return io.realm.some_test_AllTypesRealmProxy.insert(realm, (some.test.AllTypes) object, cache);\n        } else {\n            throw getMissingProxyClassException(clazz);\n        }\n    }\n\n    @Override\n    public void insert(Realm realm, Collection<? extends RealmModel> objects) {\n        Iterator<? extends RealmModel> iterator = objects.iterator();\n        RealmModel object = null;\n        Map<RealmModel, Long> cache = new HashMap<RealmModel, Long>(objects.size());\n        if (iterator.hasNext()) {\n            //  access the first element to figure out the clazz for the routing below\n            object = iterator.next();\n            // This cast is correct because obj is either\n            // generated by RealmProxy or the original type extending directly from RealmObject\n            @SuppressWarnings(\"unchecked\") Class<RealmModel> clazz = (Class<RealmModel>) ((object instanceof RealmObjectProxy) ? object.getClass().getSuperclass() : object.getClass());\n\n            if (clazz.equals(some.test.Simple.class)) {\n                io.realm.some_test_SimpleRealmProxy.insert(realm, (some.test.Simple) object, cache);\n            } else if (clazz.equals(some.test.AllTypes.class)) {\n                io.realm.some_test_AllTypesRealmProxy.insert(realm, (some.test.AllTypes) object, cache);\n            } else {\n                throw getMissingProxyClassException(clazz);\n            }\n            if (iterator.hasNext()) {\n                if (clazz.equals(some.test.Simple.class)) {\n                    io.realm.some_test_SimpleRealmProxy.insert(realm, iterator, cache);\n                } else if (clazz.equals(some.test.AllTypes.class)) {\n                    io.realm.some_test_AllTypesRealmProxy.insert(realm, iterator, cache);\n                } else {\n                    throw getMissingProxyClassException(clazz);\n                }\n            }\n        }\n    }\n\n    @Override\n    public long insertOrUpdate(Realm realm, RealmModel obj, Map<RealmModel, Long> cache) {\n        // This cast is correct because obj is either\n        // generated by RealmProxy or the original type extending directly from RealmObject\n        @SuppressWarnings(\"unchecked\") Class<RealmModel> clazz = (Class<RealmModel>) ((obj instanceof RealmObjectProxy) ? obj.getClass().getSuperclass() : obj.getClass());\n\n        if (clazz.equals(some.test.Simple.class)) {\n            return io.realm.some_test_SimpleRealmProxy.insertOrUpdate(realm, (some.test.Simple) obj, cache);\n        } else if (clazz.equals(some.test.AllTypes.class)) {\n            return io.realm.some_test_AllTypesRealmProxy.insertOrUpdate(realm, (some.test.AllTypes) obj, cache);\n        } else {\n            throw getMissingProxyClassException(clazz);\n        }\n    }\n\n    @Override\n    public void insertOrUpdate(Realm realm, Collection<? extends RealmModel> objects) {\n        Iterator<? extends RealmModel> iterator = objects.iterator();\n        RealmModel object = null;\n        Map<RealmModel, Long> cache = new HashMap<RealmModel, Long>(objects.size());\n        if (iterator.hasNext()) {\n            //  access the first element to figure out the clazz for the routing below\n            object = iterator.next();\n            // This cast is correct because obj is either\n            // generated by RealmProxy or the original type extending directly from RealmObject\n            @SuppressWarnings(\"unchecked\") Class<RealmModel> clazz = (Class<RealmModel>) ((object instanceof RealmObjectProxy) ? object.getClass().getSuperclass() : object.getClass());\n\n            if (clazz.equals(some.test.Simple.class)) {\n                io.realm.some_test_SimpleRealmProxy.insertOrUpdate(realm, (some.test.Simple) object, cache);\n            } else if (clazz.equals(some.test.AllTypes.class)) {\n                io.realm.some_test_AllTypesRealmProxy.insertOrUpdate(realm, (some.test.AllTypes) object, cache);\n            } else {\n                throw getMissingProxyClassException(clazz);\n            }\n            if (iterator.hasNext()) {\n                if (clazz.equals(some.test.Simple.class)) {\n                    io.realm.some_test_SimpleRealmProxy.insertOrUpdate(realm, iterator, cache);\n                } else if (clazz.equals(some.test.AllTypes.class)) {\n                    io.realm.some_test_AllTypesRealmProxy.insertOrUpdate(realm, iterator, cache);\n                } else {\n                    throw getMissingProxyClassException(clazz);\n                }\n            }\n        }\n    }\n\n    @Override\n    public <E extends RealmModel> E createOrUpdateUsingJsonObject(Class<E> clazz, Realm realm, JSONObject json, boolean update)\n            throws JSONException {\n        checkClass(clazz);\n\n        if (clazz.equals(some.test.Simple.class)) {\n            return clazz.cast(io.realm.some_test_SimpleRealmProxy.createOrUpdateUsingJsonObject(realm, json, update));\n        }\n        if (clazz.equals(some.test.AllTypes.class)) {\n            return clazz.cast(io.realm.some_test_AllTypesRealmProxy.createOrUpdateUsingJsonObject(realm, json, update));\n        }\n        throw getMissingProxyClassException(clazz);\n    }\n\n    @Override\n    public <E extends RealmModel> E createUsingJsonStream(Class<E> clazz, Realm realm, JsonReader reader)\n            throws IOException {\n        checkClass(clazz);\n\n        if (clazz.equals(some.test.Simple.class)) {\n            return clazz.cast(io.realm.some_test_SimpleRealmProxy.createUsingJsonStream(realm, reader));\n        }\n        if (clazz.equals(some.test.AllTypes.class)) {\n            return clazz.cast(io.realm.some_test_AllTypesRealmProxy.createUsingJsonStream(realm, reader));\n        }\n        throw getMissingProxyClassException(clazz);\n    }\n\n    @Override\n    public <E extends RealmModel> E createDetachedCopy(E realmObject, int maxDepth, Map<RealmModel, RealmObjectProxy.CacheData<RealmModel>> cache) {\n        // This cast is correct because obj is either\n        // generated by RealmProxy or the original type extending directly from RealmObject\n        @SuppressWarnings(\"unchecked\") Class<E> clazz = (Class<E>) realmObject.getClass().getSuperclass();\n\n        if (clazz.equals(some.test.Simple.class)) {\n            return clazz.cast(io.realm.some_test_SimpleRealmProxy.createDetachedCopy((some.test.Simple) realmObject, 0, maxDepth, cache));\n        }\n        if (clazz.equals(some.test.AllTypes.class)) {\n            return clazz.cast(io.realm.some_test_AllTypesRealmProxy.createDetachedCopy((some.test.AllTypes) realmObject, 0, maxDepth, cache));\n        }\n        throw getMissingProxyClassException(clazz);\n    }\n\n    @Override\n    public <E extends RealmModel> boolean isEmbedded(Class<E> clazz) {\n        if (clazz.equals(some.test.Simple.class)) {\n            return false;\n        }\n        if (clazz.equals(some.test.AllTypes.class)) {\n            return false;\n        }\n        throw getMissingProxyClassException(clazz);\n    }\n\n    @Override\n    public <E extends RealmModel> void updateEmbeddedObject(Realm realm, E unmanagedObject, E managedObject, Map<RealmModel, RealmObjectProxy> cache, Set<ImportFlag> flags) {\n        // This cast is correct because obj is either\n        // generated by RealmProxy or the original type extending directly from RealmObject\n        @SuppressWarnings(\"unchecked\") Class<E> clazz = (Class<E>) managedObject.getClass().getSuperclass();\n\n        if (clazz.equals(some.test.Simple.class)) {\n            throw getNotEmbeddedClassException(\"some.test.Simple\");\n        } else if (clazz.equals(some.test.AllTypes.class)) {\n            throw getNotEmbeddedClassException(\"some.test.AllTypes\");\n        } else {\n            throw getMissingProxyClassException(clazz);\n        }\n    }\n\n}\n"
  },
  {
    "path": "realm/realm-annotations-processor/src/test/resources/io/realm/some_test_AllTypesRealmProxy-pre-dictionary.java",
    "content": "package io.realm;\n\n\nimport android.annotation.TargetApi;\nimport android.os.Build;\nimport android.util.JsonReader;\nimport android.util.JsonToken;\nimport io.realm.ImportFlag;\nimport io.realm.ProxyUtils;\nimport io.realm.exceptions.RealmMigrationNeededException;\nimport io.realm.internal.ColumnInfo;\nimport io.realm.internal.NativeContext;\nimport io.realm.internal.OsList;\nimport io.realm.internal.OsMap;\nimport io.realm.internal.OsObject;\nimport io.realm.internal.OsObjectSchemaInfo;\nimport io.realm.internal.OsSchemaInfo;\nimport io.realm.internal.Property;\nimport io.realm.internal.RealmObjectProxy;\nimport io.realm.internal.Row;\nimport io.realm.internal.Table;\nimport io.realm.internal.UncheckedRow;\nimport io.realm.internal.android.JsonUtils;\nimport io.realm.internal.core.NativeRealmAny;\nimport io.realm.internal.objectstore.OsObjectBuilder;\nimport io.realm.log.RealmLog;\nimport java.io.IOException;\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.Date;\nimport java.util.HashMap;\nimport java.util.HashSet;\nimport java.util.Iterator;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Set;\nimport org.json.JSONArray;\nimport org.json.JSONException;\nimport org.json.JSONObject;\n\n@SuppressWarnings(\"all\")\npublic class some_test_AllTypesRealmProxy extends some.test.AllTypes\n        implements RealmObjectProxy, some_test_AllTypesRealmProxyInterface {\n\n    static final class AllTypesColumnInfo extends ColumnInfo {\n        long columnStringColKey;\n        long columnLongColKey;\n        long columnFloatColKey;\n        long columnDoubleColKey;\n        long columnBooleanColKey;\n        long columnDecimal128ColKey;\n        long columnObjectIdColKey;\n        long columnUUIDColKey;\n        long columnDateColKey;\n        long columnRealmAnyColKey;\n        long columnBinaryColKey;\n        long columnMutableRealmIntegerColKey;\n        long columnObjectColKey;\n        long columnObjectWithoutPkColKey;\n        long columnRealmListColKey;\n        long columnRealmListNoPkColKey;\n        long columnRealmFinalListColKey;\n        long columnRealmFinalListNoPkColKey;\n        long columnStringListColKey;\n        long columnBinaryListColKey;\n        long columnBooleanListColKey;\n        long columnLongListColKey;\n        long columnIntegerListColKey;\n        long columnShortListColKey;\n        long columnByteListColKey;\n        long columnDoubleListColKey;\n        long columnFloatListColKey;\n        long columnDateListColKey;\n        long columnDecimal128ListColKey;\n        long columnObjectIdListColKey;\n        long columnUUIDListColKey;\n        long columnRealmAnyListColKey;\n        long columnRealmDictionaryColKey;\n        long columnBooleanDictionaryColKey;\n        long columnStringDictionaryColKey;\n        long columnIntegerDictionaryColKey;\n        long columnFloatDictionaryColKey;\n        long columnLongDictionaryColKey;\n        long columnShortDictionaryColKey;\n        long columnDoubleDictionaryColKey;\n        long columnByteDictionaryColKey;\n        long columnBinaryDictionaryColKey;\n        long columnDateDictionaryColKey;\n        long columnObjectIdDictionaryColKey;\n        long columnUUIDDictionaryColKey;\n        long columnDecimal128DictionaryColKey;\n        long columnRealmAnyDictionaryColKey;\n\n        AllTypesColumnInfo(OsSchemaInfo schemaInfo) {\n            super(47);\n            OsObjectSchemaInfo objectSchemaInfo = schemaInfo.getObjectSchemaInfo(\"AllTypes\");\n            this.columnStringColKey = addColumnDetails(\"columnString\", \"columnString\", objectSchemaInfo);\n            this.columnLongColKey = addColumnDetails(\"columnLong\", \"columnLong\", objectSchemaInfo);\n            this.columnFloatColKey = addColumnDetails(\"columnFloat\", \"columnFloat\", objectSchemaInfo);\n            this.columnDoubleColKey = addColumnDetails(\"columnDouble\", \"columnDouble\", objectSchemaInfo);\n            this.columnBooleanColKey = addColumnDetails(\"columnBoolean\", \"columnBoolean\", objectSchemaInfo);\n            this.columnDecimal128ColKey = addColumnDetails(\"columnDecimal128\", \"columnDecimal128\", objectSchemaInfo);\n            this.columnObjectIdColKey = addColumnDetails(\"columnObjectId\", \"columnObjectId\", objectSchemaInfo);\n            this.columnUUIDColKey = addColumnDetails(\"columnUUID\", \"columnUUID\", objectSchemaInfo);\n            this.columnDateColKey = addColumnDetails(\"columnDate\", \"columnDate\", objectSchemaInfo);\n            this.columnRealmAnyColKey = addColumnDetails(\"columnRealmAny\", \"columnRealmAny\", objectSchemaInfo);\n            this.columnBinaryColKey = addColumnDetails(\"columnBinary\", \"columnBinary\", objectSchemaInfo);\n            this.columnMutableRealmIntegerColKey = addColumnDetails(\"columnMutableRealmInteger\", \"columnMutableRealmInteger\", objectSchemaInfo);\n            this.columnObjectColKey = addColumnDetails(\"columnObject\", \"columnObject\", objectSchemaInfo);\n            this.columnObjectWithoutPkColKey = addColumnDetails(\"columnObjectWithoutPk\", \"columnObjectWithoutPk\", objectSchemaInfo);\n            this.columnRealmListColKey = addColumnDetails(\"columnRealmList\", \"columnRealmList\", objectSchemaInfo);\n            this.columnRealmListNoPkColKey = addColumnDetails(\"columnRealmListNoPk\", \"columnRealmListNoPk\", objectSchemaInfo);\n            this.columnRealmFinalListColKey = addColumnDetails(\"columnRealmFinalList\", \"columnRealmFinalList\", objectSchemaInfo);\n            this.columnRealmFinalListNoPkColKey = addColumnDetails(\"columnRealmFinalListNoPk\", \"columnRealmFinalListNoPk\", objectSchemaInfo);\n            this.columnStringListColKey = addColumnDetails(\"columnStringList\", \"columnStringList\", objectSchemaInfo);\n            this.columnBinaryListColKey = addColumnDetails(\"columnBinaryList\", \"columnBinaryList\", objectSchemaInfo);\n            this.columnBooleanListColKey = addColumnDetails(\"columnBooleanList\", \"columnBooleanList\", objectSchemaInfo);\n            this.columnLongListColKey = addColumnDetails(\"columnLongList\", \"columnLongList\", objectSchemaInfo);\n            this.columnIntegerListColKey = addColumnDetails(\"columnIntegerList\", \"columnIntegerList\", objectSchemaInfo);\n            this.columnShortListColKey = addColumnDetails(\"columnShortList\", \"columnShortList\", objectSchemaInfo);\n            this.columnByteListColKey = addColumnDetails(\"columnByteList\", \"columnByteList\", objectSchemaInfo);\n            this.columnDoubleListColKey = addColumnDetails(\"columnDoubleList\", \"columnDoubleList\", objectSchemaInfo);\n            this.columnFloatListColKey = addColumnDetails(\"columnFloatList\", \"columnFloatList\", objectSchemaInfo);\n            this.columnDateListColKey = addColumnDetails(\"columnDateList\", \"columnDateList\", objectSchemaInfo);\n            this.columnDecimal128ListColKey = addColumnDetails(\"columnDecimal128List\", \"columnDecimal128List\", objectSchemaInfo);\n            this.columnObjectIdListColKey = addColumnDetails(\"columnObjectIdList\", \"columnObjectIdList\", objectSchemaInfo);\n            this.columnUUIDListColKey = addColumnDetails(\"columnUUIDList\", \"columnUUIDList\", objectSchemaInfo);\n            this.columnRealmAnyListColKey = addColumnDetails(\"columnRealmAnyList\", \"columnRealmAnyList\", objectSchemaInfo);\n            this.columnRealmDictionaryColKey = addColumnDetails(\"columnRealmDictionary\", \"columnRealmDictionary\", objectSchemaInfo);\n            this.columnBooleanDictionaryColKey = addColumnDetails(\"columnBooleanDictionary\", \"columnBooleanDictionary\", objectSchemaInfo);\n            this.columnStringDictionaryColKey = addColumnDetails(\"columnStringDictionary\", \"columnStringDictionary\", objectSchemaInfo);\n            this.columnIntegerDictionaryColKey = addColumnDetails(\"columnIntegerDictionary\", \"columnIntegerDictionary\", objectSchemaInfo);\n            this.columnFloatDictionaryColKey = addColumnDetails(\"columnFloatDictionary\", \"columnFloatDictionary\", objectSchemaInfo);\n            this.columnLongDictionaryColKey = addColumnDetails(\"columnLongDictionary\", \"columnLongDictionary\", objectSchemaInfo);\n            this.columnShortDictionaryColKey = addColumnDetails(\"columnShortDictionary\", \"columnShortDictionary\", objectSchemaInfo);\n            this.columnDoubleDictionaryColKey = addColumnDetails(\"columnDoubleDictionary\", \"columnDoubleDictionary\", objectSchemaInfo);\n            this.columnByteDictionaryColKey = addColumnDetails(\"columnByteDictionary\", \"columnByteDictionary\", objectSchemaInfo);\n            this.columnBinaryDictionaryColKey = addColumnDetails(\"columnBinaryDictionary\", \"columnBinaryDictionary\", objectSchemaInfo);\n            this.columnDateDictionaryColKey = addColumnDetails(\"columnDateDictionary\", \"columnDateDictionary\", objectSchemaInfo);\n            this.columnObjectIdDictionaryColKey = addColumnDetails(\"columnObjectIdDictionary\", \"columnObjectIdDictionary\", objectSchemaInfo);\n            this.columnUUIDDictionaryColKey = addColumnDetails(\"columnUUIDDictionary\", \"columnUUIDDictionary\", objectSchemaInfo);\n            this.columnDecimal128DictionaryColKey = addColumnDetails(\"columnDecimal128Dictionary\", \"columnDecimal128Dictionary\", objectSchemaInfo);\n            this.columnRealmAnyDictionaryColKey = addColumnDetails(\"columnRealmAnyDictionary\", \"columnRealmAnyDictionary\", objectSchemaInfo);\n            addBacklinkDetails(schemaInfo, \"parentObjects\", \"AllTypes\", \"columnObject\");\n        }\n\n        AllTypesColumnInfo(ColumnInfo src, boolean mutable) {\n            super(src, mutable);\n            copy(src, this);\n        }\n\n        @Override\n        protected final ColumnInfo copy(boolean mutable) {\n            return new AllTypesColumnInfo(this, mutable);\n        }\n\n        @Override\n        protected final void copy(ColumnInfo rawSrc, ColumnInfo rawDst) {\n            final AllTypesColumnInfo src = (AllTypesColumnInfo) rawSrc;\n            final AllTypesColumnInfo dst = (AllTypesColumnInfo) rawDst;\n            dst.columnStringColKey = src.columnStringColKey;\n            dst.columnLongColKey = src.columnLongColKey;\n            dst.columnFloatColKey = src.columnFloatColKey;\n            dst.columnDoubleColKey = src.columnDoubleColKey;\n            dst.columnBooleanColKey = src.columnBooleanColKey;\n            dst.columnDecimal128ColKey = src.columnDecimal128ColKey;\n            dst.columnObjectIdColKey = src.columnObjectIdColKey;\n            dst.columnUUIDColKey = src.columnUUIDColKey;\n            dst.columnDateColKey = src.columnDateColKey;\n            dst.columnRealmAnyColKey = src.columnRealmAnyColKey;\n            dst.columnBinaryColKey = src.columnBinaryColKey;\n            dst.columnMutableRealmIntegerColKey = src.columnMutableRealmIntegerColKey;\n            dst.columnObjectColKey = src.columnObjectColKey;\n            dst.columnObjectWithoutPkColKey = src.columnObjectWithoutPkColKey;\n            dst.columnRealmListColKey = src.columnRealmListColKey;\n            dst.columnRealmListNoPkColKey = src.columnRealmListNoPkColKey;\n            dst.columnRealmFinalListColKey = src.columnRealmFinalListColKey;\n            dst.columnRealmFinalListNoPkColKey = src.columnRealmFinalListNoPkColKey;\n            dst.columnStringListColKey = src.columnStringListColKey;\n            dst.columnBinaryListColKey = src.columnBinaryListColKey;\n            dst.columnBooleanListColKey = src.columnBooleanListColKey;\n            dst.columnLongListColKey = src.columnLongListColKey;\n            dst.columnIntegerListColKey = src.columnIntegerListColKey;\n            dst.columnShortListColKey = src.columnShortListColKey;\n            dst.columnByteListColKey = src.columnByteListColKey;\n            dst.columnDoubleListColKey = src.columnDoubleListColKey;\n            dst.columnFloatListColKey = src.columnFloatListColKey;\n            dst.columnDateListColKey = src.columnDateListColKey;\n            dst.columnDecimal128ListColKey = src.columnDecimal128ListColKey;\n            dst.columnObjectIdListColKey = src.columnObjectIdListColKey;\n            dst.columnUUIDListColKey = src.columnUUIDListColKey;\n            dst.columnRealmAnyListColKey = src.columnRealmAnyListColKey;\n            dst.columnRealmDictionaryColKey = src.columnRealmDictionaryColKey;\n            dst.columnBooleanDictionaryColKey = src.columnBooleanDictionaryColKey;\n            dst.columnStringDictionaryColKey = src.columnStringDictionaryColKey;\n            dst.columnIntegerDictionaryColKey = src.columnIntegerDictionaryColKey;\n            dst.columnFloatDictionaryColKey = src.columnFloatDictionaryColKey;\n            dst.columnLongDictionaryColKey = src.columnLongDictionaryColKey;\n            dst.columnShortDictionaryColKey = src.columnShortDictionaryColKey;\n            dst.columnDoubleDictionaryColKey = src.columnDoubleDictionaryColKey;\n            dst.columnByteDictionaryColKey = src.columnByteDictionaryColKey;\n            dst.columnBinaryDictionaryColKey = src.columnBinaryDictionaryColKey;\n            dst.columnDateDictionaryColKey = src.columnDateDictionaryColKey;\n            dst.columnObjectIdDictionaryColKey = src.columnObjectIdDictionaryColKey;\n            dst.columnUUIDDictionaryColKey = src.columnUUIDDictionaryColKey;\n            dst.columnDecimal128DictionaryColKey = src.columnDecimal128DictionaryColKey;\n            dst.columnRealmAnyDictionaryColKey = src.columnRealmAnyDictionaryColKey;\n        }\n    }\n\n    private static final String NO_ALIAS = \"\";\n    private static final OsObjectSchemaInfo expectedObjectSchemaInfo = createExpectedObjectSchemaInfo();\n\n    private AllTypesColumnInfo columnInfo;\n    private ProxyState<some.test.AllTypes> proxyState;\n    private final MutableRealmInteger.Managed columnMutableRealmIntegerMutableRealmInteger = new MutableRealmInteger.Managed<some.test.AllTypes>() {\n        @Override protected ProxyState<some.test.AllTypes> getProxyState() { return proxyState; }\n        @Override protected long getColumnIndex() { return columnInfo.columnMutableRealmIntegerColKey; }\n    };\n    private RealmList<some.test.AllTypes> columnRealmListRealmList;\n    private RealmList<some.test.Simple> columnRealmListNoPkRealmList;\n    private RealmList<some.test.AllTypes> columnRealmFinalListRealmList;\n    private RealmList<some.test.Simple> columnRealmFinalListNoPkRealmList;\n    private RealmList<String> columnStringListRealmList;\n    private RealmList<byte[]> columnBinaryListRealmList;\n    private RealmList<Boolean> columnBooleanListRealmList;\n    private RealmList<Long> columnLongListRealmList;\n    private RealmList<Integer> columnIntegerListRealmList;\n    private RealmList<Short> columnShortListRealmList;\n    private RealmList<Byte> columnByteListRealmList;\n    private RealmList<Double> columnDoubleListRealmList;\n    private RealmList<Float> columnFloatListRealmList;\n    private RealmList<Date> columnDateListRealmList;\n    private RealmList<org.bson.types.Decimal128> columnDecimal128ListRealmList;\n    private RealmList<org.bson.types.ObjectId> columnObjectIdListRealmList;\n    private RealmList<java.util.UUID> columnUUIDListRealmList;\n    private RealmList<RealmAny> columnRealmAnyListRealmList;\n    private RealmDictionary<some.test.AllTypes> columnRealmDictionaryRealmDictionary;\n    private RealmDictionary<Boolean> columnBooleanDictionaryRealmDictionary;\n    private RealmDictionary<String> columnStringDictionaryRealmDictionary;\n    private RealmDictionary<Integer> columnIntegerDictionaryRealmDictionary;\n    private RealmDictionary<Float> columnFloatDictionaryRealmDictionary;\n    private RealmDictionary<Long> columnLongDictionaryRealmDictionary;\n    private RealmDictionary<Short> columnShortDictionaryRealmDictionary;\n    private RealmDictionary<Double> columnDoubleDictionaryRealmDictionary;\n    private RealmDictionary<Byte> columnByteDictionaryRealmDictionary;\n    private RealmDictionary<byte[]> columnBinaryDictionaryRealmDictionary;\n    private RealmDictionary<Date> columnDateDictionaryRealmDictionary;\n    private RealmDictionary<org.bson.types.ObjectId> columnObjectIdDictionaryRealmDictionary;\n    private RealmDictionary<java.util.UUID> columnUUIDDictionaryRealmDictionary;\n    private RealmDictionary<org.bson.types.Decimal128> columnDecimal128DictionaryRealmDictionary;\n    private RealmDictionary<RealmAny> columnRealmAnyDictionaryRealmDictionary;\n    private RealmResults<some.test.AllTypes> parentObjectsBacklinks;\n\n    some_test_AllTypesRealmProxy() {\n        proxyState.setConstructionFinished();\n    }\n\n    @Override\n    public void realm$injectObjectContext() {\n        if (this.proxyState != null) {\n            return;\n        }\n        final BaseRealm.RealmObjectContext context = BaseRealm.objectContext.get();\n        this.columnInfo = (AllTypesColumnInfo) context.getColumnInfo();\n        this.proxyState = new ProxyState<some.test.AllTypes>(this);\n        proxyState.setRealm$realm(context.getRealm());\n        proxyState.setRow$realm(context.getRow());\n        proxyState.setAcceptDefaultValue$realm(context.getAcceptDefaultValue());\n        proxyState.setExcludeFields$realm(context.getExcludeFields());\n    }\n\n    @Override\n    @SuppressWarnings(\"cast\")\n    public String realmGet$columnString() {\n        proxyState.getRealm$realm().checkIfValid();\n        return (java.lang.String) proxyState.getRow$realm().getString(columnInfo.columnStringColKey);\n    }\n\n    @Override\n    public void realmSet$columnString(String value) {\n        if (proxyState.isUnderConstruction()) {\n            // default value of the primary key is always ignored.\n            return;\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        throw new io.realm.exceptions.RealmException(\"Primary key field 'columnString' cannot be changed after object was created.\");\n    }\n\n    @Override\n    @SuppressWarnings(\"cast\")\n    public long realmGet$columnLong() {\n        proxyState.getRealm$realm().checkIfValid();\n        return (long) proxyState.getRow$realm().getLong(columnInfo.columnLongColKey);\n    }\n\n    @Override\n    public void realmSet$columnLong(long value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            final Row row = proxyState.getRow$realm();\n            row.getTable().setLong(columnInfo.columnLongColKey, row.getObjectKey(), value, true);\n            return;\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        proxyState.getRow$realm().setLong(columnInfo.columnLongColKey, value);\n    }\n\n    @Override\n    @SuppressWarnings(\"cast\")\n    public float realmGet$columnFloat() {\n        proxyState.getRealm$realm().checkIfValid();\n        return (float) proxyState.getRow$realm().getFloat(columnInfo.columnFloatColKey);\n    }\n\n    @Override\n    public void realmSet$columnFloat(float value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            final Row row = proxyState.getRow$realm();\n            row.getTable().setFloat(columnInfo.columnFloatColKey, row.getObjectKey(), value, true);\n            return;\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        proxyState.getRow$realm().setFloat(columnInfo.columnFloatColKey, value);\n    }\n\n    @Override\n    @SuppressWarnings(\"cast\")\n    public double realmGet$columnDouble() {\n        proxyState.getRealm$realm().checkIfValid();\n        return (double) proxyState.getRow$realm().getDouble(columnInfo.columnDoubleColKey);\n    }\n\n    @Override\n    public void realmSet$columnDouble(double value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            final Row row = proxyState.getRow$realm();\n            row.getTable().setDouble(columnInfo.columnDoubleColKey, row.getObjectKey(), value, true);\n            return;\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        proxyState.getRow$realm().setDouble(columnInfo.columnDoubleColKey, value);\n    }\n\n    @Override\n    @SuppressWarnings(\"cast\")\n    public boolean realmGet$columnBoolean() {\n        proxyState.getRealm$realm().checkIfValid();\n        return (boolean) proxyState.getRow$realm().getBoolean(columnInfo.columnBooleanColKey);\n    }\n\n    @Override\n    public void realmSet$columnBoolean(boolean value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            final Row row = proxyState.getRow$realm();\n            row.getTable().setBoolean(columnInfo.columnBooleanColKey, row.getObjectKey(), value, true);\n            return;\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        proxyState.getRow$realm().setBoolean(columnInfo.columnBooleanColKey, value);\n    }\n\n    @Override\n    @SuppressWarnings(\"cast\")\n    public org.bson.types.Decimal128 realmGet$columnDecimal128() {\n        proxyState.getRealm$realm().checkIfValid();\n        return (org.bson.types.Decimal128) proxyState.getRow$realm().getDecimal128(columnInfo.columnDecimal128ColKey);\n    }\n\n    @Override\n    public void realmSet$columnDecimal128(org.bson.types.Decimal128 value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            final Row row = proxyState.getRow$realm();\n            if (value == null) {\n                throw new IllegalArgumentException(\"Trying to set non-nullable field 'columnDecimal128' to null.\");\n            }\n            row.getTable().setDecimal128(columnInfo.columnDecimal128ColKey, row.getObjectKey(), value, true);\n            return;\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        if (value == null) {\n            throw new IllegalArgumentException(\"Trying to set non-nullable field 'columnDecimal128' to null.\");\n        }\n        proxyState.getRow$realm().setDecimal128(columnInfo.columnDecimal128ColKey, value);\n    }\n\n    @Override\n    @SuppressWarnings(\"cast\")\n    public org.bson.types.ObjectId realmGet$columnObjectId() {\n        proxyState.getRealm$realm().checkIfValid();\n        return (org.bson.types.ObjectId) proxyState.getRow$realm().getObjectId(columnInfo.columnObjectIdColKey);\n    }\n\n    @Override\n    public void realmSet$columnObjectId(org.bson.types.ObjectId value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            final Row row = proxyState.getRow$realm();\n            if (value == null) {\n                throw new IllegalArgumentException(\"Trying to set non-nullable field 'columnObjectId' to null.\");\n            }\n            row.getTable().setObjectId(columnInfo.columnObjectIdColKey, row.getObjectKey(), value, true);\n            return;\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        if (value == null) {\n            throw new IllegalArgumentException(\"Trying to set non-nullable field 'columnObjectId' to null.\");\n        }\n        proxyState.getRow$realm().setObjectId(columnInfo.columnObjectIdColKey, value);\n    }\n\n    @Override\n    @SuppressWarnings(\"cast\")\n    public java.util.UUID realmGet$columnUUID() {\n        proxyState.getRealm$realm().checkIfValid();\n        return (java.util.UUID) proxyState.getRow$realm().getUUID(columnInfo.columnUUIDColKey);\n    }\n\n    @Override\n    public void realmSet$columnUUID(java.util.UUID value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            final Row row = proxyState.getRow$realm();\n            if (value == null) {\n                throw new IllegalArgumentException(\"Trying to set non-nullable field 'columnUUID' to null.\");\n            }\n            row.getTable().setUUID(columnInfo.columnUUIDColKey, row.getObjectKey(), value, true);\n            return;\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        if (value == null) {\n            throw new IllegalArgumentException(\"Trying to set non-nullable field 'columnUUID' to null.\");\n        }\n        proxyState.getRow$realm().setUUID(columnInfo.columnUUIDColKey, value);\n    }\n\n    @Override\n    @SuppressWarnings(\"cast\")\n    public Date realmGet$columnDate() {\n        proxyState.getRealm$realm().checkIfValid();\n        return (java.util.Date) proxyState.getRow$realm().getDate(columnInfo.columnDateColKey);\n    }\n\n    @Override\n    public void realmSet$columnDate(Date value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            final Row row = proxyState.getRow$realm();\n            if (value == null) {\n                throw new IllegalArgumentException(\"Trying to set non-nullable field 'columnDate' to null.\");\n            }\n            row.getTable().setDate(columnInfo.columnDateColKey, row.getObjectKey(), value, true);\n            return;\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        if (value == null) {\n            throw new IllegalArgumentException(\"Trying to set non-nullable field 'columnDate' to null.\");\n        }\n        proxyState.getRow$realm().setDate(columnInfo.columnDateColKey, value);\n    }\n\n    @Override\n    public RealmAny realmGet$columnRealmAny() {\n        proxyState.getRealm$realm().checkIfValid();\n        NativeRealmAny nativeRealmAny = proxyState.getRow$realm().getNativeRealmAny(columnInfo.columnRealmAnyColKey);\n        return new RealmAny(RealmAnyOperator.fromNativeRealmAny(proxyState.getRealm$realm(), nativeRealmAny));\n    }\n\n    @Override\n    public void realmSet$columnRealmAny(RealmAny value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            if (proxyState.getExcludeFields$realm().contains(\"columnRealmAny\")) {\n                return;\n            }\n\n            value = ProxyUtils.copyToRealmIfNeeded(proxyState, value);\n\n            final Row row = proxyState.getRow$realm();\n            if (value == null) {\n                row.getTable().setNull(columnInfo.columnRealmAnyColKey, row.getObjectKey(), true);\n                return;\n            }\n            row.getTable().setRealmAny(columnInfo.columnRealmAnyColKey, row.getObjectKey(), value.getNativePtr(), true);\n            return;\n        }\n\n\n        proxyState.getRealm$realm().checkIfValid();\n\n        if (value == null) {\n            proxyState.getRow$realm().setNull(columnInfo.columnRealmAnyColKey);\n            return;\n        }\n        value = ProxyUtils.copyToRealmIfNeeded(proxyState, value);\n        proxyState.getRow$realm().setRealmAny(columnInfo.columnRealmAnyColKey, value.getNativePtr());\n    }\n\n    @Override\n    @SuppressWarnings(\"cast\")\n    public byte[] realmGet$columnBinary() {\n        proxyState.getRealm$realm().checkIfValid();\n        return (byte[]) proxyState.getRow$realm().getBinaryByteArray(columnInfo.columnBinaryColKey);\n    }\n\n    @Override\n    public void realmSet$columnBinary(byte[] value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            final Row row = proxyState.getRow$realm();\n            if (value == null) {\n                throw new IllegalArgumentException(\"Trying to set non-nullable field 'columnBinary' to null.\");\n            }\n            row.getTable().setBinaryByteArray(columnInfo.columnBinaryColKey, row.getObjectKey(), value, true);\n            return;\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        if (value == null) {\n            throw new IllegalArgumentException(\"Trying to set non-nullable field 'columnBinary' to null.\");\n        }\n        proxyState.getRow$realm().setBinaryByteArray(columnInfo.columnBinaryColKey, value);\n    }\n\n    @Override\n    public MutableRealmInteger realmGet$columnMutableRealmInteger() {\n        proxyState.getRealm$realm().checkIfValid();\n        return this.columnMutableRealmIntegerMutableRealmInteger;\n    }\n\n    @Override\n    public some.test.AllTypes realmGet$columnObject() {\n        proxyState.getRealm$realm().checkIfValid();\n        if (proxyState.getRow$realm().isNullLink(columnInfo.columnObjectColKey)) {\n            return null;\n        }\n        return proxyState.getRealm$realm().get(some.test.AllTypes.class, proxyState.getRow$realm().getLink(columnInfo.columnObjectColKey), false, Collections.<String>emptyList());\n    }\n\n    @Override\n    public void realmSet$columnObject(some.test.AllTypes value) {\n        Realm realm = (Realm) proxyState.getRealm$realm();\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            if (proxyState.getExcludeFields$realm().contains(\"columnObject\")) {\n                return;\n            }\n            if (value != null && !RealmObject.isManaged(value)) {\n                value = realm.copyToRealmOrUpdate(value);\n            }\n            final Row row = proxyState.getRow$realm();\n            if (value == null) {\n                // Table#nullifyLink() does not support default value. Just using Row.\n                row.nullifyLink(columnInfo.columnObjectColKey);\n                return;\n            }\n            proxyState.checkValidObject(value);\n            row.getTable().setLink(columnInfo.columnObjectColKey, row.getObjectKey(), ((RealmObjectProxy) value).realmGet$proxyState().getRow$realm().getObjectKey(), true);\n            return;\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        if (value == null) {\n            proxyState.getRow$realm().nullifyLink(columnInfo.columnObjectColKey);\n            return;\n        }\n        proxyState.checkValidObject(value);\n        proxyState.getRow$realm().setLink(columnInfo.columnObjectColKey, ((RealmObjectProxy) value).realmGet$proxyState().getRow$realm().getObjectKey());\n    }\n\n    @Override\n    public some.test.Simple realmGet$columnObjectWithoutPk() {\n        proxyState.getRealm$realm().checkIfValid();\n        if (proxyState.getRow$realm().isNullLink(columnInfo.columnObjectWithoutPkColKey)) {\n            return null;\n        }\n        return proxyState.getRealm$realm().get(some.test.Simple.class, proxyState.getRow$realm().getLink(columnInfo.columnObjectWithoutPkColKey), false, Collections.<String>emptyList());\n    }\n\n    @Override\n    public void realmSet$columnObjectWithoutPk(some.test.Simple value) {\n        Realm realm = (Realm) proxyState.getRealm$realm();\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            if (proxyState.getExcludeFields$realm().contains(\"columnObjectWithoutPk\")) {\n                return;\n            }\n            if (value != null && !RealmObject.isManaged(value)) {\n                value = realm.copyToRealm(value);\n            }\n            final Row row = proxyState.getRow$realm();\n            if (value == null) {\n                // Table#nullifyLink() does not support default value. Just using Row.\n                row.nullifyLink(columnInfo.columnObjectWithoutPkColKey);\n                return;\n            }\n            proxyState.checkValidObject(value);\n            row.getTable().setLink(columnInfo.columnObjectWithoutPkColKey, row.getObjectKey(), ((RealmObjectProxy) value).realmGet$proxyState().getRow$realm().getObjectKey(), true);\n            return;\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        if (value == null) {\n            proxyState.getRow$realm().nullifyLink(columnInfo.columnObjectWithoutPkColKey);\n            return;\n        }\n        proxyState.checkValidObject(value);\n        proxyState.getRow$realm().setLink(columnInfo.columnObjectWithoutPkColKey, ((RealmObjectProxy) value).realmGet$proxyState().getRow$realm().getObjectKey());\n    }\n\n    @Override\n    public RealmList<some.test.AllTypes> realmGet$columnRealmList() {\n        proxyState.getRealm$realm().checkIfValid();\n        // use the cached value if available\n        if (columnRealmListRealmList != null) {\n            return columnRealmListRealmList;\n        } else {\n            OsList osList = proxyState.getRow$realm().getModelList(columnInfo.columnRealmListColKey);\n            columnRealmListRealmList = new RealmList<some.test.AllTypes>(some.test.AllTypes.class, osList, proxyState.getRealm$realm());\n            return columnRealmListRealmList;\n        }\n    }\n\n    @Override\n    public void realmSet$columnRealmList(RealmList<some.test.AllTypes> value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            if (proxyState.getExcludeFields$realm().contains(\"columnRealmList\")) {\n                return;\n            }\n            // if the list contains unmanaged RealmObjects, convert them to managed.\n            if (value != null && !value.isManaged()) {\n                final Realm realm = (Realm) proxyState.getRealm$realm();\n                final RealmList<some.test.AllTypes> original = value;\n                value = new RealmList<some.test.AllTypes>();\n                for (some.test.AllTypes item : original) {\n                    if (item == null || RealmObject.isManaged(item)) {\n                        value.add(item);\n                    } else {\n                        value.add(realm.copyToRealmOrUpdate(item));\n                    }\n                }\n            }\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        OsList osList = proxyState.getRow$realm().getModelList(columnInfo.columnRealmListColKey);\n        // For lists of equal lengths, we need to set each element directly as clearing the receiver list can be wrong if the input and target list are the same.\n        if (value != null && value.size() == osList.size()) {\n            int objects = value.size();\n            for (int i = 0; i < objects; i++) {\n                some.test.AllTypes linkedObject = value.get(i);\n                proxyState.checkValidObject(linkedObject);\n                osList.setRow(i, ((RealmObjectProxy) linkedObject).realmGet$proxyState().getRow$realm().getObjectKey());\n            }\n        } else {\n            osList.removeAll();\n            if (value == null) {\n                return;\n            }\n            int objects = value.size();\n            for (int i = 0; i < objects; i++) {\n                some.test.AllTypes linkedObject = value.get(i);\n                proxyState.checkValidObject(linkedObject);\n                osList.addRow(((RealmObjectProxy) linkedObject).realmGet$proxyState().getRow$realm().getObjectKey());\n            }\n        }\n    }\n\n    @Override\n    public RealmList<some.test.Simple> realmGet$columnRealmListNoPk() {\n        proxyState.getRealm$realm().checkIfValid();\n        // use the cached value if available\n        if (columnRealmListNoPkRealmList != null) {\n            return columnRealmListNoPkRealmList;\n        } else {\n            OsList osList = proxyState.getRow$realm().getModelList(columnInfo.columnRealmListNoPkColKey);\n            columnRealmListNoPkRealmList = new RealmList<some.test.Simple>(some.test.Simple.class, osList, proxyState.getRealm$realm());\n            return columnRealmListNoPkRealmList;\n        }\n    }\n\n    @Override\n    public void realmSet$columnRealmListNoPk(RealmList<some.test.Simple> value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            if (proxyState.getExcludeFields$realm().contains(\"columnRealmListNoPk\")) {\n                return;\n            }\n            // if the list contains unmanaged RealmObjects, convert them to managed.\n            if (value != null && !value.isManaged()) {\n                final Realm realm = (Realm) proxyState.getRealm$realm();\n                final RealmList<some.test.Simple> original = value;\n                value = new RealmList<some.test.Simple>();\n                for (some.test.Simple item : original) {\n                    if (item == null || RealmObject.isManaged(item)) {\n                        value.add(item);\n                    } else {\n                        value.add(realm.copyToRealm(item));\n                    }\n                }\n            }\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        OsList osList = proxyState.getRow$realm().getModelList(columnInfo.columnRealmListNoPkColKey);\n        // For lists of equal lengths, we need to set each element directly as clearing the receiver list can be wrong if the input and target list are the same.\n        if (value != null && value.size() == osList.size()) {\n            int objects = value.size();\n            for (int i = 0; i < objects; i++) {\n                some.test.Simple linkedObject = value.get(i);\n                proxyState.checkValidObject(linkedObject);\n                osList.setRow(i, ((RealmObjectProxy) linkedObject).realmGet$proxyState().getRow$realm().getObjectKey());\n            }\n        } else {\n            osList.removeAll();\n            if (value == null) {\n                return;\n            }\n            int objects = value.size();\n            for (int i = 0; i < objects; i++) {\n                some.test.Simple linkedObject = value.get(i);\n                proxyState.checkValidObject(linkedObject);\n                osList.addRow(((RealmObjectProxy) linkedObject).realmGet$proxyState().getRow$realm().getObjectKey());\n            }\n        }\n    }\n\n    @Override\n    public RealmList<some.test.AllTypes> realmGet$columnRealmFinalList() {\n        proxyState.getRealm$realm().checkIfValid();\n        // use the cached value if available\n        if (columnRealmFinalListRealmList != null) {\n            return columnRealmFinalListRealmList;\n        } else {\n            OsList osList = proxyState.getRow$realm().getModelList(columnInfo.columnRealmFinalListColKey);\n            columnRealmFinalListRealmList = new RealmList<some.test.AllTypes>(some.test.AllTypes.class, osList, proxyState.getRealm$realm());\n            return columnRealmFinalListRealmList;\n        }\n    }\n\n    @Override\n    public void realmSet$columnRealmFinalList(RealmList<some.test.AllTypes> value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            if (proxyState.getExcludeFields$realm().contains(\"columnRealmFinalList\")) {\n                return;\n            }\n            // if the list contains unmanaged RealmObjects, convert them to managed.\n            if (value != null && !value.isManaged()) {\n                final Realm realm = (Realm) proxyState.getRealm$realm();\n                final RealmList<some.test.AllTypes> original = value;\n                value = new RealmList<some.test.AllTypes>();\n                for (some.test.AllTypes item : original) {\n                    if (item == null || RealmObject.isManaged(item)) {\n                        value.add(item);\n                    } else {\n                        value.add(realm.copyToRealmOrUpdate(item));\n                    }\n                }\n            }\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        OsList osList = proxyState.getRow$realm().getModelList(columnInfo.columnRealmFinalListColKey);\n        // For lists of equal lengths, we need to set each element directly as clearing the receiver list can be wrong if the input and target list are the same.\n        if (value != null && value.size() == osList.size()) {\n            int objects = value.size();\n            for (int i = 0; i < objects; i++) {\n                some.test.AllTypes linkedObject = value.get(i);\n                proxyState.checkValidObject(linkedObject);\n                osList.setRow(i, ((RealmObjectProxy) linkedObject).realmGet$proxyState().getRow$realm().getObjectKey());\n            }\n        } else {\n            osList.removeAll();\n            if (value == null) {\n                return;\n            }\n            int objects = value.size();\n            for (int i = 0; i < objects; i++) {\n                some.test.AllTypes linkedObject = value.get(i);\n                proxyState.checkValidObject(linkedObject);\n                osList.addRow(((RealmObjectProxy) linkedObject).realmGet$proxyState().getRow$realm().getObjectKey());\n            }\n        }\n    }\n\n    @Override\n    public RealmList<some.test.Simple> realmGet$columnRealmFinalListNoPk() {\n        proxyState.getRealm$realm().checkIfValid();\n        // use the cached value if available\n        if (columnRealmFinalListNoPkRealmList != null) {\n            return columnRealmFinalListNoPkRealmList;\n        } else {\n            OsList osList = proxyState.getRow$realm().getModelList(columnInfo.columnRealmFinalListNoPkColKey);\n            columnRealmFinalListNoPkRealmList = new RealmList<some.test.Simple>(some.test.Simple.class, osList, proxyState.getRealm$realm());\n            return columnRealmFinalListNoPkRealmList;\n        }\n    }\n\n    @Override\n    public void realmSet$columnRealmFinalListNoPk(RealmList<some.test.Simple> value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            if (proxyState.getExcludeFields$realm().contains(\"columnRealmFinalListNoPk\")) {\n                return;\n            }\n            // if the list contains unmanaged RealmObjects, convert them to managed.\n            if (value != null && !value.isManaged()) {\n                final Realm realm = (Realm) proxyState.getRealm$realm();\n                final RealmList<some.test.Simple> original = value;\n                value = new RealmList<some.test.Simple>();\n                for (some.test.Simple item : original) {\n                    if (item == null || RealmObject.isManaged(item)) {\n                        value.add(item);\n                    } else {\n                        value.add(realm.copyToRealm(item));\n                    }\n                }\n            }\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        OsList osList = proxyState.getRow$realm().getModelList(columnInfo.columnRealmFinalListNoPkColKey);\n        // For lists of equal lengths, we need to set each element directly as clearing the receiver list can be wrong if the input and target list are the same.\n        if (value != null && value.size() == osList.size()) {\n            int objects = value.size();\n            for (int i = 0; i < objects; i++) {\n                some.test.Simple linkedObject = value.get(i);\n                proxyState.checkValidObject(linkedObject);\n                osList.setRow(i, ((RealmObjectProxy) linkedObject).realmGet$proxyState().getRow$realm().getObjectKey());\n            }\n        } else {\n            osList.removeAll();\n            if (value == null) {\n                return;\n            }\n            int objects = value.size();\n            for (int i = 0; i < objects; i++) {\n                some.test.Simple linkedObject = value.get(i);\n                proxyState.checkValidObject(linkedObject);\n                osList.addRow(((RealmObjectProxy) linkedObject).realmGet$proxyState().getRow$realm().getObjectKey());\n            }\n        }\n    }\n\n    @Override\n    public RealmList<String> realmGet$columnStringList() {\n        proxyState.getRealm$realm().checkIfValid();\n        // use the cached value if available\n        if (columnStringListRealmList != null) {\n            return columnStringListRealmList;\n        } else {\n            OsList osList = proxyState.getRow$realm().getValueList(columnInfo.columnStringListColKey, RealmFieldType.STRING_LIST);\n            columnStringListRealmList = new RealmList<java.lang.String>(java.lang.String.class, osList, proxyState.getRealm$realm());\n            return columnStringListRealmList;\n        }\n    }\n\n    @Override\n    public void realmSet$columnStringList(RealmList<String> value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            if (proxyState.getExcludeFields$realm().contains(\"columnStringList\")) {\n                return;\n            }\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        OsList osList = proxyState.getRow$realm().getValueList(columnInfo.columnStringListColKey, RealmFieldType.STRING_LIST);\n        osList.removeAll();\n        if (value == null) {\n            return;\n        }\n        for (java.lang.String item : value) {\n            if (item == null) {\n                osList.addNull();\n            } else {\n                osList.addString(item);\n            }\n        }\n    }\n\n    @Override\n    public RealmList<byte[]> realmGet$columnBinaryList() {\n        proxyState.getRealm$realm().checkIfValid();\n        // use the cached value if available\n        if (columnBinaryListRealmList != null) {\n            return columnBinaryListRealmList;\n        } else {\n            OsList osList = proxyState.getRow$realm().getValueList(columnInfo.columnBinaryListColKey, RealmFieldType.BINARY_LIST);\n            columnBinaryListRealmList = new RealmList<byte[]>(byte[].class, osList, proxyState.getRealm$realm());\n            return columnBinaryListRealmList;\n        }\n    }\n\n    @Override\n    public void realmSet$columnBinaryList(RealmList<byte[]> value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            if (proxyState.getExcludeFields$realm().contains(\"columnBinaryList\")) {\n                return;\n            }\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        OsList osList = proxyState.getRow$realm().getValueList(columnInfo.columnBinaryListColKey, RealmFieldType.BINARY_LIST);\n        osList.removeAll();\n        if (value == null) {\n            return;\n        }\n        for (byte[] item : value) {\n            if (item == null) {\n                osList.addNull();\n            } else {\n                osList.addBinary(item);\n            }\n        }\n    }\n\n    @Override\n    public RealmList<Boolean> realmGet$columnBooleanList() {\n        proxyState.getRealm$realm().checkIfValid();\n        // use the cached value if available\n        if (columnBooleanListRealmList != null) {\n            return columnBooleanListRealmList;\n        } else {\n            OsList osList = proxyState.getRow$realm().getValueList(columnInfo.columnBooleanListColKey, RealmFieldType.BOOLEAN_LIST);\n            columnBooleanListRealmList = new RealmList<java.lang.Boolean>(java.lang.Boolean.class, osList, proxyState.getRealm$realm());\n            return columnBooleanListRealmList;\n        }\n    }\n\n    @Override\n    public void realmSet$columnBooleanList(RealmList<Boolean> value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            if (proxyState.getExcludeFields$realm().contains(\"columnBooleanList\")) {\n                return;\n            }\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        OsList osList = proxyState.getRow$realm().getValueList(columnInfo.columnBooleanListColKey, RealmFieldType.BOOLEAN_LIST);\n        osList.removeAll();\n        if (value == null) {\n            return;\n        }\n        for (java.lang.Boolean item : value) {\n            if (item == null) {\n                osList.addNull();\n            } else {\n                osList.addBoolean(item);\n            }\n        }\n    }\n\n    @Override\n    public RealmList<Long> realmGet$columnLongList() {\n        proxyState.getRealm$realm().checkIfValid();\n        // use the cached value if available\n        if (columnLongListRealmList != null) {\n            return columnLongListRealmList;\n        } else {\n            OsList osList = proxyState.getRow$realm().getValueList(columnInfo.columnLongListColKey, RealmFieldType.INTEGER_LIST);\n            columnLongListRealmList = new RealmList<java.lang.Long>(java.lang.Long.class, osList, proxyState.getRealm$realm());\n            return columnLongListRealmList;\n        }\n    }\n\n    @Override\n    public void realmSet$columnLongList(RealmList<Long> value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            if (proxyState.getExcludeFields$realm().contains(\"columnLongList\")) {\n                return;\n            }\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        OsList osList = proxyState.getRow$realm().getValueList(columnInfo.columnLongListColKey, RealmFieldType.INTEGER_LIST);\n        osList.removeAll();\n        if (value == null) {\n            return;\n        }\n        for (java.lang.Long item : value) {\n            if (item == null) {\n                osList.addNull();\n            } else {\n                osList.addLong(item.longValue());\n            }\n        }\n    }\n\n    @Override\n    public RealmList<Integer> realmGet$columnIntegerList() {\n        proxyState.getRealm$realm().checkIfValid();\n        // use the cached value if available\n        if (columnIntegerListRealmList != null) {\n            return columnIntegerListRealmList;\n        } else {\n            OsList osList = proxyState.getRow$realm().getValueList(columnInfo.columnIntegerListColKey, RealmFieldType.INTEGER_LIST);\n            columnIntegerListRealmList = new RealmList<java.lang.Integer>(java.lang.Integer.class, osList, proxyState.getRealm$realm());\n            return columnIntegerListRealmList;\n        }\n    }\n\n    @Override\n    public void realmSet$columnIntegerList(RealmList<Integer> value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            if (proxyState.getExcludeFields$realm().contains(\"columnIntegerList\")) {\n                return;\n            }\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        OsList osList = proxyState.getRow$realm().getValueList(columnInfo.columnIntegerListColKey, RealmFieldType.INTEGER_LIST);\n        osList.removeAll();\n        if (value == null) {\n            return;\n        }\n        for (java.lang.Integer item : value) {\n            if (item == null) {\n                osList.addNull();\n            } else {\n                osList.addLong(item.longValue());\n            }\n        }\n    }\n\n    @Override\n    public RealmList<Short> realmGet$columnShortList() {\n        proxyState.getRealm$realm().checkIfValid();\n        // use the cached value if available\n        if (columnShortListRealmList != null) {\n            return columnShortListRealmList;\n        } else {\n            OsList osList = proxyState.getRow$realm().getValueList(columnInfo.columnShortListColKey, RealmFieldType.INTEGER_LIST);\n            columnShortListRealmList = new RealmList<java.lang.Short>(java.lang.Short.class, osList, proxyState.getRealm$realm());\n            return columnShortListRealmList;\n        }\n    }\n\n    @Override\n    public void realmSet$columnShortList(RealmList<Short> value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            if (proxyState.getExcludeFields$realm().contains(\"columnShortList\")) {\n                return;\n            }\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        OsList osList = proxyState.getRow$realm().getValueList(columnInfo.columnShortListColKey, RealmFieldType.INTEGER_LIST);\n        osList.removeAll();\n        if (value == null) {\n            return;\n        }\n        for (java.lang.Short item : value) {\n            if (item == null) {\n                osList.addNull();\n            } else {\n                osList.addLong(item.longValue());\n            }\n        }\n    }\n\n    @Override\n    public RealmList<Byte> realmGet$columnByteList() {\n        proxyState.getRealm$realm().checkIfValid();\n        // use the cached value if available\n        if (columnByteListRealmList != null) {\n            return columnByteListRealmList;\n        } else {\n            OsList osList = proxyState.getRow$realm().getValueList(columnInfo.columnByteListColKey, RealmFieldType.INTEGER_LIST);\n            columnByteListRealmList = new RealmList<java.lang.Byte>(java.lang.Byte.class, osList, proxyState.getRealm$realm());\n            return columnByteListRealmList;\n        }\n    }\n\n    @Override\n    public void realmSet$columnByteList(RealmList<Byte> value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            if (proxyState.getExcludeFields$realm().contains(\"columnByteList\")) {\n                return;\n            }\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        OsList osList = proxyState.getRow$realm().getValueList(columnInfo.columnByteListColKey, RealmFieldType.INTEGER_LIST);\n        osList.removeAll();\n        if (value == null) {\n            return;\n        }\n        for (java.lang.Byte item : value) {\n            if (item == null) {\n                osList.addNull();\n            } else {\n                osList.addLong(item.longValue());\n            }\n        }\n    }\n\n    @Override\n    public RealmList<Double> realmGet$columnDoubleList() {\n        proxyState.getRealm$realm().checkIfValid();\n        // use the cached value if available\n        if (columnDoubleListRealmList != null) {\n            return columnDoubleListRealmList;\n        } else {\n            OsList osList = proxyState.getRow$realm().getValueList(columnInfo.columnDoubleListColKey, RealmFieldType.DOUBLE_LIST);\n            columnDoubleListRealmList = new RealmList<java.lang.Double>(java.lang.Double.class, osList, proxyState.getRealm$realm());\n            return columnDoubleListRealmList;\n        }\n    }\n\n    @Override\n    public void realmSet$columnDoubleList(RealmList<Double> value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            if (proxyState.getExcludeFields$realm().contains(\"columnDoubleList\")) {\n                return;\n            }\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        OsList osList = proxyState.getRow$realm().getValueList(columnInfo.columnDoubleListColKey, RealmFieldType.DOUBLE_LIST);\n        osList.removeAll();\n        if (value == null) {\n            return;\n        }\n        for (java.lang.Double item : value) {\n            if (item == null) {\n                osList.addNull();\n            } else {\n                osList.addDouble(item.doubleValue());\n            }\n        }\n    }\n\n    @Override\n    public RealmList<Float> realmGet$columnFloatList() {\n        proxyState.getRealm$realm().checkIfValid();\n        // use the cached value if available\n        if (columnFloatListRealmList != null) {\n            return columnFloatListRealmList;\n        } else {\n            OsList osList = proxyState.getRow$realm().getValueList(columnInfo.columnFloatListColKey, RealmFieldType.FLOAT_LIST);\n            columnFloatListRealmList = new RealmList<java.lang.Float>(java.lang.Float.class, osList, proxyState.getRealm$realm());\n            return columnFloatListRealmList;\n        }\n    }\n\n    @Override\n    public void realmSet$columnFloatList(RealmList<Float> value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            if (proxyState.getExcludeFields$realm().contains(\"columnFloatList\")) {\n                return;\n            }\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        OsList osList = proxyState.getRow$realm().getValueList(columnInfo.columnFloatListColKey, RealmFieldType.FLOAT_LIST);\n        osList.removeAll();\n        if (value == null) {\n            return;\n        }\n        for (java.lang.Float item : value) {\n            if (item == null) {\n                osList.addNull();\n            } else {\n                osList.addFloat(item.floatValue());\n            }\n        }\n    }\n\n    @Override\n    public RealmList<Date> realmGet$columnDateList() {\n        proxyState.getRealm$realm().checkIfValid();\n        // use the cached value if available\n        if (columnDateListRealmList != null) {\n            return columnDateListRealmList;\n        } else {\n            OsList osList = proxyState.getRow$realm().getValueList(columnInfo.columnDateListColKey, RealmFieldType.DATE_LIST);\n            columnDateListRealmList = new RealmList<java.util.Date>(java.util.Date.class, osList, proxyState.getRealm$realm());\n            return columnDateListRealmList;\n        }\n    }\n\n    @Override\n    public void realmSet$columnDateList(RealmList<Date> value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            if (proxyState.getExcludeFields$realm().contains(\"columnDateList\")) {\n                return;\n            }\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        OsList osList = proxyState.getRow$realm().getValueList(columnInfo.columnDateListColKey, RealmFieldType.DATE_LIST);\n        osList.removeAll();\n        if (value == null) {\n            return;\n        }\n        for (java.util.Date item : value) {\n            if (item == null) {\n                osList.addNull();\n            } else {\n                osList.addDate(item);\n            }\n        }\n    }\n\n    @Override\n    public RealmList<org.bson.types.Decimal128> realmGet$columnDecimal128List() {\n        proxyState.getRealm$realm().checkIfValid();\n        // use the cached value if available\n        if (columnDecimal128ListRealmList != null) {\n            return columnDecimal128ListRealmList;\n        } else {\n            OsList osList = proxyState.getRow$realm().getValueList(columnInfo.columnDecimal128ListColKey, RealmFieldType.DECIMAL128_LIST);\n            columnDecimal128ListRealmList = new RealmList<org.bson.types.Decimal128>(org.bson.types.Decimal128.class, osList, proxyState.getRealm$realm());\n            return columnDecimal128ListRealmList;\n        }\n    }\n\n    @Override\n    public void realmSet$columnDecimal128List(RealmList<org.bson.types.Decimal128> value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            if (proxyState.getExcludeFields$realm().contains(\"columnDecimal128List\")) {\n                return;\n            }\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        OsList osList = proxyState.getRow$realm().getValueList(columnInfo.columnDecimal128ListColKey, RealmFieldType.DECIMAL128_LIST);\n        osList.removeAll();\n        if (value == null) {\n            return;\n        }\n        for (org.bson.types.Decimal128 item : value) {\n            if (item == null) {\n                osList.addNull();\n            } else {\n                osList.addDecimal128(item);\n            }\n        }\n    }\n\n    @Override\n    public RealmList<org.bson.types.ObjectId> realmGet$columnObjectIdList() {\n        proxyState.getRealm$realm().checkIfValid();\n        // use the cached value if available\n        if (columnObjectIdListRealmList != null) {\n            return columnObjectIdListRealmList;\n        } else {\n            OsList osList = proxyState.getRow$realm().getValueList(columnInfo.columnObjectIdListColKey, RealmFieldType.OBJECT_ID_LIST);\n            columnObjectIdListRealmList = new RealmList<org.bson.types.ObjectId>(org.bson.types.ObjectId.class, osList, proxyState.getRealm$realm());\n            return columnObjectIdListRealmList;\n        }\n    }\n\n    @Override\n    public void realmSet$columnObjectIdList(RealmList<org.bson.types.ObjectId> value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            if (proxyState.getExcludeFields$realm().contains(\"columnObjectIdList\")) {\n                return;\n            }\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        OsList osList = proxyState.getRow$realm().getValueList(columnInfo.columnObjectIdListColKey, RealmFieldType.OBJECT_ID_LIST);\n        osList.removeAll();\n        if (value == null) {\n            return;\n        }\n        for (org.bson.types.ObjectId item : value) {\n            if (item == null) {\n                osList.addNull();\n            } else {\n                osList.addObjectId(item);\n            }\n        }\n    }\n\n    @Override\n    public RealmList<java.util.UUID> realmGet$columnUUIDList() {\n        proxyState.getRealm$realm().checkIfValid();\n        // use the cached value if available\n        if (columnUUIDListRealmList != null) {\n            return columnUUIDListRealmList;\n        } else {\n            OsList osList = proxyState.getRow$realm().getValueList(columnInfo.columnUUIDListColKey, RealmFieldType.UUID_LIST);\n            columnUUIDListRealmList = new RealmList<java.util.UUID>(java.util.UUID.class, osList, proxyState.getRealm$realm());\n            return columnUUIDListRealmList;\n        }\n    }\n\n    @Override\n    public void realmSet$columnUUIDList(RealmList<java.util.UUID> value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            if (proxyState.getExcludeFields$realm().contains(\"columnUUIDList\")) {\n                return;\n            }\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        OsList osList = proxyState.getRow$realm().getValueList(columnInfo.columnUUIDListColKey, RealmFieldType.UUID_LIST);\n        osList.removeAll();\n        if (value == null) {\n            return;\n        }\n        for (java.util.UUID item : value) {\n            if (item == null) {\n                osList.addNull();\n            } else {\n                osList.addUUID(item);\n            }\n        }\n    }\n\n    @Override\n    public RealmList<RealmAny> realmGet$columnRealmAnyList() {\n        proxyState.getRealm$realm().checkIfValid();\n        // use the cached value if available\n        if (columnRealmAnyListRealmList != null) {\n            return columnRealmAnyListRealmList;\n        } else {\n            OsList osList = proxyState.getRow$realm().getValueList(columnInfo.columnRealmAnyListColKey, RealmFieldType.MIXED_LIST);\n            columnRealmAnyListRealmList = new RealmList<io.realm.RealmAny>(io.realm.RealmAny.class, osList, proxyState.getRealm$realm());\n            return columnRealmAnyListRealmList;\n        }\n    }\n\n    @Override\n    public void realmSet$columnRealmAnyList(RealmList<RealmAny> value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            if (proxyState.getExcludeFields$realm().contains(\"columnRealmAnyList\")) {\n                return;\n            }\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        OsList osList = proxyState.getRow$realm().getValueList(columnInfo.columnRealmAnyListColKey, RealmFieldType.MIXED_LIST);\n        if (value != null && !value.isManaged()) {\n            final Realm realm = (Realm) proxyState.getRealm$realm();\n            final RealmList<RealmAny> original = value;\n            value = new RealmList<RealmAny>();\n            for (int i = 0; i < original.size(); i++) {\n                value.add(ProxyUtils.copyToRealmIfNeeded(proxyState, original.get(i)));\n            }\n        }\n        osList.removeAll();\n        if (value == null) {\n            return;\n        }\n        for (io.realm.RealmAny item : value) {\n            if (item == null) {\n                osList.addNull();\n            } else {\n                osList.addRealmAny(item.getNativePtr());\n            }\n        }\n    }\n\n    @Override\n    public RealmDictionary<some.test.AllTypes> realmGet$columnRealmDictionary() {\n        proxyState.getRealm$realm().checkIfValid();\n        // use the cached value if available\n        if (columnRealmDictionaryRealmDictionary != null) {\n            return columnRealmDictionaryRealmDictionary;\n        } else {\n            OsMap osMap = proxyState.getRow$realm().getModelMap(columnInfo.columnRealmDictionaryColKey);\n            columnRealmDictionaryRealmDictionary = new RealmDictionary<some.test.AllTypes>(proxyState.getRealm$realm(), osMap, some.test.AllTypes.class);\n            return columnRealmDictionaryRealmDictionary;\n        }\n    }\n\n    @Override\n    public void realmSet$columnRealmDictionary(RealmDictionary<some.test.AllTypes> value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            if (proxyState.getExcludeFields$realm().contains(\"columnRealmDictionary\")) {\n                return;\n            }\n            // if the dictionary contains unmanaged RealmModel instances, convert them to managed.\n            if (value != null && !value.isManaged()) {\n                final Realm realm = (Realm) proxyState.getRealm$realm();\n                final RealmDictionary<some.test.AllTypes> original = value;\n                value = new RealmDictionary<some.test.AllTypes>();\n                for (java.util.Map.Entry<String, some.test.AllTypes> entry : original.entrySet()) {\n                    String entryKey = entry.getKey();\n                    some.test.AllTypes entryValue = entry.getValue();\n                    if (entryValue == null || RealmObject.isManaged(entryValue)) {\n                        value.put(entryKey, entryValue);\n                    } else {\n                        value.put(entryKey, realm.copyToRealmOrUpdate(entryValue));\n                    }\n                }\n            }\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        OsMap osMap = proxyState.getRow$realm().getModelMap(columnInfo.columnRealmDictionaryColKey);\n        if (value == null) {\n            return;\n        }\n        osMap.clear();\n        for (java.util.Map.Entry<String, some.test.AllTypes> item : value.entrySet()) {\n            String entryKey = item.getKey();\n            some.test.AllTypes entryValue = item.getValue();\n            if (entryValue == null) {\n                osMap.put(entryKey, null);\n            } else {\n                osMap.putRow(entryKey, ((RealmObjectProxy) entryValue).realmGet$proxyState().getRow$realm().getObjectKey());\n            }\n        }\n    }\n\n    @Override\n    public RealmDictionary<Boolean> realmGet$columnBooleanDictionary() {\n        proxyState.getRealm$realm().checkIfValid();\n        // use the cached value if available\n        if (columnBooleanDictionaryRealmDictionary != null) {\n            return columnBooleanDictionaryRealmDictionary;\n        } else {\n            OsMap osMap = proxyState.getRow$realm().getValueMap(columnInfo.columnBooleanDictionaryColKey, RealmFieldType.STRING_TO_BOOLEAN_MAP);\n            columnBooleanDictionaryRealmDictionary = new RealmDictionary<java.lang.Boolean>(proxyState.getRealm$realm(), osMap, java.lang.Boolean.class);\n            return columnBooleanDictionaryRealmDictionary;\n        }\n    }\n\n    @Override\n    public void realmSet$columnBooleanDictionary(RealmDictionary<Boolean> value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            if (proxyState.getExcludeFields$realm().contains(\"columnBooleanDictionary\")) {\n                return;\n            }\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        OsMap osMap = proxyState.getRow$realm().getValueMap(columnInfo.columnBooleanDictionaryColKey, RealmFieldType.STRING_TO_BOOLEAN_MAP);\n        if (value == null) {\n            return;\n        }\n        osMap.clear();\n        for (java.util.Map.Entry<String, java.lang.Boolean> item : value.entrySet()) {\n            String entryKey = item.getKey();\n            java.lang.Boolean entryValue = item.getValue();\n            osMap.put(entryKey, entryValue);\n        }\n    }\n\n    @Override\n    public RealmDictionary<String> realmGet$columnStringDictionary() {\n        proxyState.getRealm$realm().checkIfValid();\n        // use the cached value if available\n        if (columnStringDictionaryRealmDictionary != null) {\n            return columnStringDictionaryRealmDictionary;\n        } else {\n            OsMap osMap = proxyState.getRow$realm().getValueMap(columnInfo.columnStringDictionaryColKey, RealmFieldType.STRING_TO_STRING_MAP);\n            columnStringDictionaryRealmDictionary = new RealmDictionary<java.lang.String>(proxyState.getRealm$realm(), osMap, java.lang.String.class);\n            return columnStringDictionaryRealmDictionary;\n        }\n    }\n\n    @Override\n    public void realmSet$columnStringDictionary(RealmDictionary<String> value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            if (proxyState.getExcludeFields$realm().contains(\"columnStringDictionary\")) {\n                return;\n            }\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        OsMap osMap = proxyState.getRow$realm().getValueMap(columnInfo.columnStringDictionaryColKey, RealmFieldType.STRING_TO_STRING_MAP);\n        if (value == null) {\n            return;\n        }\n        osMap.clear();\n        for (java.util.Map.Entry<String, java.lang.String> item : value.entrySet()) {\n            String entryKey = item.getKey();\n            java.lang.String entryValue = item.getValue();\n            osMap.put(entryKey, entryValue);\n        }\n    }\n\n    @Override\n    public RealmDictionary<Integer> realmGet$columnIntegerDictionary() {\n        proxyState.getRealm$realm().checkIfValid();\n        // use the cached value if available\n        if (columnIntegerDictionaryRealmDictionary != null) {\n            return columnIntegerDictionaryRealmDictionary;\n        } else {\n            OsMap osMap = proxyState.getRow$realm().getValueMap(columnInfo.columnIntegerDictionaryColKey, RealmFieldType.STRING_TO_INTEGER_MAP);\n            columnIntegerDictionaryRealmDictionary = new RealmDictionary<java.lang.Integer>(proxyState.getRealm$realm(), osMap, java.lang.Integer.class);\n            return columnIntegerDictionaryRealmDictionary;\n        }\n    }\n\n    @Override\n    public void realmSet$columnIntegerDictionary(RealmDictionary<Integer> value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            if (proxyState.getExcludeFields$realm().contains(\"columnIntegerDictionary\")) {\n                return;\n            }\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        OsMap osMap = proxyState.getRow$realm().getValueMap(columnInfo.columnIntegerDictionaryColKey, RealmFieldType.STRING_TO_INTEGER_MAP);\n        if (value == null) {\n            return;\n        }\n        osMap.clear();\n        for (java.util.Map.Entry<String, java.lang.Integer> item : value.entrySet()) {\n            String entryKey = item.getKey();\n            java.lang.Integer entryValue = item.getValue();\n            osMap.put(entryKey, entryValue);\n        }\n    }\n\n    @Override\n    public RealmDictionary<Float> realmGet$columnFloatDictionary() {\n        proxyState.getRealm$realm().checkIfValid();\n        // use the cached value if available\n        if (columnFloatDictionaryRealmDictionary != null) {\n            return columnFloatDictionaryRealmDictionary;\n        } else {\n            OsMap osMap = proxyState.getRow$realm().getValueMap(columnInfo.columnFloatDictionaryColKey, RealmFieldType.STRING_TO_FLOAT_MAP);\n            columnFloatDictionaryRealmDictionary = new RealmDictionary<java.lang.Float>(proxyState.getRealm$realm(), osMap, java.lang.Float.class);\n            return columnFloatDictionaryRealmDictionary;\n        }\n    }\n\n    @Override\n    public void realmSet$columnFloatDictionary(RealmDictionary<Float> value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            if (proxyState.getExcludeFields$realm().contains(\"columnFloatDictionary\")) {\n                return;\n            }\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        OsMap osMap = proxyState.getRow$realm().getValueMap(columnInfo.columnFloatDictionaryColKey, RealmFieldType.STRING_TO_FLOAT_MAP);\n        if (value == null) {\n            return;\n        }\n        osMap.clear();\n        for (java.util.Map.Entry<String, java.lang.Float> item : value.entrySet()) {\n            String entryKey = item.getKey();\n            java.lang.Float entryValue = item.getValue();\n            osMap.put(entryKey, entryValue);\n        }\n    }\n\n    @Override\n    public RealmDictionary<Long> realmGet$columnLongDictionary() {\n        proxyState.getRealm$realm().checkIfValid();\n        // use the cached value if available\n        if (columnLongDictionaryRealmDictionary != null) {\n            return columnLongDictionaryRealmDictionary;\n        } else {\n            OsMap osMap = proxyState.getRow$realm().getValueMap(columnInfo.columnLongDictionaryColKey, RealmFieldType.STRING_TO_INTEGER_MAP);\n            columnLongDictionaryRealmDictionary = new RealmDictionary<java.lang.Long>(proxyState.getRealm$realm(), osMap, java.lang.Long.class);\n            return columnLongDictionaryRealmDictionary;\n        }\n    }\n\n    @Override\n    public void realmSet$columnLongDictionary(RealmDictionary<Long> value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            if (proxyState.getExcludeFields$realm().contains(\"columnLongDictionary\")) {\n                return;\n            }\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        OsMap osMap = proxyState.getRow$realm().getValueMap(columnInfo.columnLongDictionaryColKey, RealmFieldType.STRING_TO_INTEGER_MAP);\n        if (value == null) {\n            return;\n        }\n        osMap.clear();\n        for (java.util.Map.Entry<String, java.lang.Long> item : value.entrySet()) {\n            String entryKey = item.getKey();\n            java.lang.Long entryValue = item.getValue();\n            osMap.put(entryKey, entryValue);\n        }\n    }\n\n    @Override\n    public RealmDictionary<Short> realmGet$columnShortDictionary() {\n        proxyState.getRealm$realm().checkIfValid();\n        // use the cached value if available\n        if (columnShortDictionaryRealmDictionary != null) {\n            return columnShortDictionaryRealmDictionary;\n        } else {\n            OsMap osMap = proxyState.getRow$realm().getValueMap(columnInfo.columnShortDictionaryColKey, RealmFieldType.STRING_TO_INTEGER_MAP);\n            columnShortDictionaryRealmDictionary = new RealmDictionary<java.lang.Short>(proxyState.getRealm$realm(), osMap, java.lang.Short.class);\n            return columnShortDictionaryRealmDictionary;\n        }\n    }\n\n    @Override\n    public void realmSet$columnShortDictionary(RealmDictionary<Short> value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            if (proxyState.getExcludeFields$realm().contains(\"columnShortDictionary\")) {\n                return;\n            }\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        OsMap osMap = proxyState.getRow$realm().getValueMap(columnInfo.columnShortDictionaryColKey, RealmFieldType.STRING_TO_INTEGER_MAP);\n        if (value == null) {\n            return;\n        }\n        osMap.clear();\n        for (java.util.Map.Entry<String, java.lang.Short> item : value.entrySet()) {\n            String entryKey = item.getKey();\n            java.lang.Short entryValue = item.getValue();\n            osMap.put(entryKey, entryValue);\n        }\n    }\n\n    @Override\n    public RealmDictionary<Double> realmGet$columnDoubleDictionary() {\n        proxyState.getRealm$realm().checkIfValid();\n        // use the cached value if available\n        if (columnDoubleDictionaryRealmDictionary != null) {\n            return columnDoubleDictionaryRealmDictionary;\n        } else {\n            OsMap osMap = proxyState.getRow$realm().getValueMap(columnInfo.columnDoubleDictionaryColKey, RealmFieldType.STRING_TO_DOUBLE_MAP);\n            columnDoubleDictionaryRealmDictionary = new RealmDictionary<java.lang.Double>(proxyState.getRealm$realm(), osMap, java.lang.Double.class);\n            return columnDoubleDictionaryRealmDictionary;\n        }\n    }\n\n    @Override\n    public void realmSet$columnDoubleDictionary(RealmDictionary<Double> value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            if (proxyState.getExcludeFields$realm().contains(\"columnDoubleDictionary\")) {\n                return;\n            }\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        OsMap osMap = proxyState.getRow$realm().getValueMap(columnInfo.columnDoubleDictionaryColKey, RealmFieldType.STRING_TO_DOUBLE_MAP);\n        if (value == null) {\n            return;\n        }\n        osMap.clear();\n        for (java.util.Map.Entry<String, java.lang.Double> item : value.entrySet()) {\n            String entryKey = item.getKey();\n            java.lang.Double entryValue = item.getValue();\n            osMap.put(entryKey, entryValue);\n        }\n    }\n\n    @Override\n    public RealmDictionary<Byte> realmGet$columnByteDictionary() {\n        proxyState.getRealm$realm().checkIfValid();\n        // use the cached value if available\n        if (columnByteDictionaryRealmDictionary != null) {\n            return columnByteDictionaryRealmDictionary;\n        } else {\n            OsMap osMap = proxyState.getRow$realm().getValueMap(columnInfo.columnByteDictionaryColKey, RealmFieldType.STRING_TO_INTEGER_MAP);\n            columnByteDictionaryRealmDictionary = new RealmDictionary<java.lang.Byte>(proxyState.getRealm$realm(), osMap, java.lang.Byte.class);\n            return columnByteDictionaryRealmDictionary;\n        }\n    }\n\n    @Override\n    public void realmSet$columnByteDictionary(RealmDictionary<Byte> value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            if (proxyState.getExcludeFields$realm().contains(\"columnByteDictionary\")) {\n                return;\n            }\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        OsMap osMap = proxyState.getRow$realm().getValueMap(columnInfo.columnByteDictionaryColKey, RealmFieldType.STRING_TO_INTEGER_MAP);\n        if (value == null) {\n            return;\n        }\n        osMap.clear();\n        for (java.util.Map.Entry<String, java.lang.Byte> item : value.entrySet()) {\n            String entryKey = item.getKey();\n            java.lang.Byte entryValue = item.getValue();\n            osMap.put(entryKey, entryValue);\n        }\n    }\n\n    @Override\n    public RealmDictionary<byte[]> realmGet$columnBinaryDictionary() {\n        proxyState.getRealm$realm().checkIfValid();\n        // use the cached value if available\n        if (columnBinaryDictionaryRealmDictionary != null) {\n            return columnBinaryDictionaryRealmDictionary;\n        } else {\n            OsMap osMap = proxyState.getRow$realm().getValueMap(columnInfo.columnBinaryDictionaryColKey, RealmFieldType.STRING_TO_BINARY_MAP);\n            columnBinaryDictionaryRealmDictionary = new RealmDictionary<byte[]>(proxyState.getRealm$realm(), osMap, byte[].class);\n            return columnBinaryDictionaryRealmDictionary;\n        }\n    }\n\n    @Override\n    public void realmSet$columnBinaryDictionary(RealmDictionary<byte[]> value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            if (proxyState.getExcludeFields$realm().contains(\"columnBinaryDictionary\")) {\n                return;\n            }\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        OsMap osMap = proxyState.getRow$realm().getValueMap(columnInfo.columnBinaryDictionaryColKey, RealmFieldType.STRING_TO_BINARY_MAP);\n        if (value == null) {\n            return;\n        }\n        osMap.clear();\n        for (java.util.Map.Entry<String, byte[]> item : value.entrySet()) {\n            String entryKey = item.getKey();\n            byte[] entryValue = item.getValue();\n            osMap.put(entryKey, entryValue);\n        }\n    }\n\n    @Override\n    public RealmDictionary<Date> realmGet$columnDateDictionary() {\n        proxyState.getRealm$realm().checkIfValid();\n        // use the cached value if available\n        if (columnDateDictionaryRealmDictionary != null) {\n            return columnDateDictionaryRealmDictionary;\n        } else {\n            OsMap osMap = proxyState.getRow$realm().getValueMap(columnInfo.columnDateDictionaryColKey, RealmFieldType.STRING_TO_DATE_MAP);\n            columnDateDictionaryRealmDictionary = new RealmDictionary<java.util.Date>(proxyState.getRealm$realm(), osMap, java.util.Date.class);\n            return columnDateDictionaryRealmDictionary;\n        }\n    }\n\n    @Override\n    public void realmSet$columnDateDictionary(RealmDictionary<Date> value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            if (proxyState.getExcludeFields$realm().contains(\"columnDateDictionary\")) {\n                return;\n            }\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        OsMap osMap = proxyState.getRow$realm().getValueMap(columnInfo.columnDateDictionaryColKey, RealmFieldType.STRING_TO_DATE_MAP);\n        if (value == null) {\n            return;\n        }\n        osMap.clear();\n        for (java.util.Map.Entry<String, java.util.Date> item : value.entrySet()) {\n            String entryKey = item.getKey();\n            java.util.Date entryValue = item.getValue();\n            osMap.put(entryKey, entryValue);\n        }\n    }\n\n    @Override\n    public RealmDictionary<org.bson.types.ObjectId> realmGet$columnObjectIdDictionary() {\n        proxyState.getRealm$realm().checkIfValid();\n        // use the cached value if available\n        if (columnObjectIdDictionaryRealmDictionary != null) {\n            return columnObjectIdDictionaryRealmDictionary;\n        } else {\n            OsMap osMap = proxyState.getRow$realm().getValueMap(columnInfo.columnObjectIdDictionaryColKey, RealmFieldType.STRING_TO_OBJECT_ID_MAP);\n            columnObjectIdDictionaryRealmDictionary = new RealmDictionary<org.bson.types.ObjectId>(proxyState.getRealm$realm(), osMap, org.bson.types.ObjectId.class);\n            return columnObjectIdDictionaryRealmDictionary;\n        }\n    }\n\n    @Override\n    public void realmSet$columnObjectIdDictionary(RealmDictionary<org.bson.types.ObjectId> value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            if (proxyState.getExcludeFields$realm().contains(\"columnObjectIdDictionary\")) {\n                return;\n            }\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        OsMap osMap = proxyState.getRow$realm().getValueMap(columnInfo.columnObjectIdDictionaryColKey, RealmFieldType.STRING_TO_OBJECT_ID_MAP);\n        if (value == null) {\n            return;\n        }\n        osMap.clear();\n        for (java.util.Map.Entry<String, org.bson.types.ObjectId> item : value.entrySet()) {\n            String entryKey = item.getKey();\n            org.bson.types.ObjectId entryValue = item.getValue();\n            osMap.put(entryKey, entryValue);\n        }\n    }\n\n    @Override\n    public RealmDictionary<java.util.UUID> realmGet$columnUUIDDictionary() {\n        proxyState.getRealm$realm().checkIfValid();\n        // use the cached value if available\n        if (columnUUIDDictionaryRealmDictionary != null) {\n            return columnUUIDDictionaryRealmDictionary;\n        } else {\n            OsMap osMap = proxyState.getRow$realm().getValueMap(columnInfo.columnUUIDDictionaryColKey, RealmFieldType.STRING_TO_UUID_MAP);\n            columnUUIDDictionaryRealmDictionary = new RealmDictionary<java.util.UUID>(proxyState.getRealm$realm(), osMap, java.util.UUID.class);\n            return columnUUIDDictionaryRealmDictionary;\n        }\n    }\n\n    @Override\n    public void realmSet$columnUUIDDictionary(RealmDictionary<java.util.UUID> value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            if (proxyState.getExcludeFields$realm().contains(\"columnUUIDDictionary\")) {\n                return;\n            }\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        OsMap osMap = proxyState.getRow$realm().getValueMap(columnInfo.columnUUIDDictionaryColKey, RealmFieldType.STRING_TO_UUID_MAP);\n        if (value == null) {\n            return;\n        }\n        osMap.clear();\n        for (java.util.Map.Entry<String, java.util.UUID> item : value.entrySet()) {\n            String entryKey = item.getKey();\n            java.util.UUID entryValue = item.getValue();\n            osMap.put(entryKey, entryValue);\n        }\n    }\n\n    @Override\n    public RealmDictionary<org.bson.types.Decimal128> realmGet$columnDecimal128Dictionary() {\n        proxyState.getRealm$realm().checkIfValid();\n        // use the cached value if available\n        if (columnDecimal128DictionaryRealmDictionary != null) {\n            return columnDecimal128DictionaryRealmDictionary;\n        } else {\n            OsMap osMap = proxyState.getRow$realm().getValueMap(columnInfo.columnDecimal128DictionaryColKey, RealmFieldType.STRING_TO_DECIMAL128_MAP);\n            columnDecimal128DictionaryRealmDictionary = new RealmDictionary<org.bson.types.Decimal128>(proxyState.getRealm$realm(), osMap, org.bson.types.Decimal128.class);\n            return columnDecimal128DictionaryRealmDictionary;\n        }\n    }\n\n    @Override\n    public void realmSet$columnDecimal128Dictionary(RealmDictionary<org.bson.types.Decimal128> value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            if (proxyState.getExcludeFields$realm().contains(\"columnDecimal128Dictionary\")) {\n                return;\n            }\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        OsMap osMap = proxyState.getRow$realm().getValueMap(columnInfo.columnDecimal128DictionaryColKey, RealmFieldType.STRING_TO_DECIMAL128_MAP);\n        if (value == null) {\n            return;\n        }\n        osMap.clear();\n        for (java.util.Map.Entry<String, org.bson.types.Decimal128> item : value.entrySet()) {\n            String entryKey = item.getKey();\n            org.bson.types.Decimal128 entryValue = item.getValue();\n            osMap.put(entryKey, entryValue);\n        }\n    }\n\n    @Override\n    public RealmDictionary<RealmAny> realmGet$columnRealmAnyDictionary() {\n        proxyState.getRealm$realm().checkIfValid();\n        // use the cached value if available\n        if (columnRealmAnyDictionaryRealmDictionary != null) {\n            return columnRealmAnyDictionaryRealmDictionary;\n        } else {\n            OsMap osMap = proxyState.getRow$realm().getRealmAnyMap(columnInfo.columnRealmAnyDictionaryColKey);\n            columnRealmAnyDictionaryRealmDictionary = new RealmDictionary<io.realm.RealmAny>(proxyState.getRealm$realm(), osMap, io.realm.RealmAny.class);\n            return columnRealmAnyDictionaryRealmDictionary;\n        }\n    }\n\n    @Override\n    public void realmSet$columnRealmAnyDictionary(RealmDictionary<RealmAny> value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            if (proxyState.getExcludeFields$realm().contains(\"columnRealmAnyDictionary\")) {\n                return;\n            }\n            // if the dictionary contains unmanaged RealmModel instances boxed in RealmAny objects, convert them to managed.\n            if (value != null && !value.isManaged()) {\n                final Realm realm = (Realm) proxyState.getRealm$realm();\n                final RealmDictionary<io.realm.RealmAny> original = value;\n                value = new RealmDictionary<io.realm.RealmAny>();\n                for (java.util.Map.Entry<String, io.realm.RealmAny> item : original.entrySet()) {\n                    String entryKey = item.getKey();\n                    io.realm.RealmAny entryValue = item.getValue();\n                    // ensure (potential) RealmModel instances are copied to Realm if generic type is RealmAny\n                    if (entryValue == null) {\n                        value.put(entryKey, null);\n                    } else if (entryValue.getType() == RealmAny.Type.OBJECT) {\n                        RealmModel realmModel = entryValue.asRealmModel(RealmModel.class);\n                        RealmModel modelFromRealm = realm.copyToRealmOrUpdate(realmModel);\n                        value.put(entryKey, RealmAny.valueOf(modelFromRealm));\n                    } else {\n                        value.put(entryKey, entryValue);\n                    }\n                }\n            }\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        OsMap osMap = proxyState.getRow$realm().getRealmAnyMap(columnInfo.columnRealmAnyDictionaryColKey);\n        if (value == null) {\n            return;\n        }\n        osMap.clear();\n        for (java.util.Map.Entry<String, io.realm.RealmAny> item : value.entrySet()) {\n            String entryKey = item.getKey();\n            io.realm.RealmAny entryValue = item.getValue();\n            if (entryValue == null) {\n                osMap.put(entryKey, null);\n            } else {\n                osMap.putRealmAny(entryKey, entryValue.getNativePtr());\n            }\n        }\n    }\n\n    @Override\n    public RealmResults<some.test.AllTypes> realmGet$parentObjects() {\n        BaseRealm realm = proxyState.getRealm$realm();\n        realm.checkIfValid();\n        proxyState.getRow$realm().checkIfAttached();\n        if (parentObjectsBacklinks == null) {\n            parentObjectsBacklinks = RealmResults.createBacklinkResults(realm, proxyState.getRow$realm(), some.test.AllTypes.class, \"columnObject\");\n        }\n        return parentObjectsBacklinks;\n    }\n\n    private static OsObjectSchemaInfo createExpectedObjectSchemaInfo() {\n        OsObjectSchemaInfo.Builder builder = new OsObjectSchemaInfo.Builder(NO_ALIAS, \"AllTypes\", false, 47, 1);\n        builder.addPersistedProperty(NO_ALIAS, \"columnString\", RealmFieldType.STRING, Property.PRIMARY_KEY, !Property.INDEXED, !Property.REQUIRED);\n        builder.addPersistedProperty(NO_ALIAS, \"columnLong\", RealmFieldType.INTEGER, !Property.PRIMARY_KEY, !Property.INDEXED, Property.REQUIRED);\n        builder.addPersistedProperty(NO_ALIAS, \"columnFloat\", RealmFieldType.FLOAT, !Property.PRIMARY_KEY, !Property.INDEXED, Property.REQUIRED);\n        builder.addPersistedProperty(NO_ALIAS, \"columnDouble\", RealmFieldType.DOUBLE, !Property.PRIMARY_KEY, !Property.INDEXED, Property.REQUIRED);\n        builder.addPersistedProperty(NO_ALIAS, \"columnBoolean\", RealmFieldType.BOOLEAN, !Property.PRIMARY_KEY, !Property.INDEXED, Property.REQUIRED);\n        builder.addPersistedProperty(NO_ALIAS, \"columnDecimal128\", RealmFieldType.DECIMAL128, !Property.PRIMARY_KEY, !Property.INDEXED, Property.REQUIRED);\n        builder.addPersistedProperty(NO_ALIAS, \"columnObjectId\", RealmFieldType.OBJECT_ID, !Property.PRIMARY_KEY, !Property.INDEXED, Property.REQUIRED);\n        builder.addPersistedProperty(NO_ALIAS, \"columnUUID\", RealmFieldType.UUID, !Property.PRIMARY_KEY, !Property.INDEXED, Property.REQUIRED);\n        builder.addPersistedProperty(NO_ALIAS, \"columnDate\", RealmFieldType.DATE, !Property.PRIMARY_KEY, !Property.INDEXED, Property.REQUIRED);\n        builder.addPersistedProperty(NO_ALIAS, \"columnRealmAny\", RealmFieldType.MIXED, !Property.PRIMARY_KEY, !Property.INDEXED, !Property.REQUIRED);\n        builder.addPersistedProperty(NO_ALIAS, \"columnBinary\", RealmFieldType.BINARY, !Property.PRIMARY_KEY, !Property.INDEXED, Property.REQUIRED);\n        builder.addPersistedProperty(NO_ALIAS, \"columnMutableRealmInteger\", RealmFieldType.INTEGER, !Property.PRIMARY_KEY, !Property.INDEXED, !Property.REQUIRED);\n        builder.addPersistedLinkProperty(NO_ALIAS, \"columnObject\", RealmFieldType.OBJECT, \"AllTypes\");\n        builder.addPersistedLinkProperty(NO_ALIAS, \"columnObjectWithoutPk\", RealmFieldType.OBJECT, \"Simple\");\n        builder.addPersistedLinkProperty(NO_ALIAS, \"columnRealmList\", RealmFieldType.LIST, \"AllTypes\");\n        builder.addPersistedLinkProperty(NO_ALIAS, \"columnRealmListNoPk\", RealmFieldType.LIST, \"Simple\");\n        builder.addPersistedLinkProperty(NO_ALIAS, \"columnRealmFinalList\", RealmFieldType.LIST, \"AllTypes\");\n        builder.addPersistedLinkProperty(NO_ALIAS, \"columnRealmFinalListNoPk\", RealmFieldType.LIST, \"Simple\");\n        builder.addPersistedValueListProperty(NO_ALIAS, \"columnStringList\", RealmFieldType.STRING_LIST, !Property.REQUIRED);\n        builder.addPersistedValueListProperty(NO_ALIAS, \"columnBinaryList\", RealmFieldType.BINARY_LIST, !Property.REQUIRED);\n        builder.addPersistedValueListProperty(NO_ALIAS, \"columnBooleanList\", RealmFieldType.BOOLEAN_LIST, !Property.REQUIRED);\n        builder.addPersistedValueListProperty(NO_ALIAS, \"columnLongList\", RealmFieldType.INTEGER_LIST, !Property.REQUIRED);\n        builder.addPersistedValueListProperty(NO_ALIAS, \"columnIntegerList\", RealmFieldType.INTEGER_LIST, !Property.REQUIRED);\n        builder.addPersistedValueListProperty(NO_ALIAS, \"columnShortList\", RealmFieldType.INTEGER_LIST, !Property.REQUIRED);\n        builder.addPersistedValueListProperty(NO_ALIAS, \"columnByteList\", RealmFieldType.INTEGER_LIST, !Property.REQUIRED);\n        builder.addPersistedValueListProperty(NO_ALIAS, \"columnDoubleList\", RealmFieldType.DOUBLE_LIST, !Property.REQUIRED);\n        builder.addPersistedValueListProperty(NO_ALIAS, \"columnFloatList\", RealmFieldType.FLOAT_LIST, !Property.REQUIRED);\n        builder.addPersistedValueListProperty(NO_ALIAS, \"columnDateList\", RealmFieldType.DATE_LIST, !Property.REQUIRED);\n        builder.addPersistedValueListProperty(NO_ALIAS, \"columnDecimal128List\", RealmFieldType.DECIMAL128_LIST, !Property.REQUIRED);\n        builder.addPersistedValueListProperty(NO_ALIAS, \"columnObjectIdList\", RealmFieldType.OBJECT_ID_LIST, !Property.REQUIRED);\n        builder.addPersistedValueListProperty(NO_ALIAS, \"columnUUIDList\", RealmFieldType.UUID_LIST, !Property.REQUIRED);\n        builder.addPersistedValueListProperty(NO_ALIAS, \"columnRealmAnyList\", RealmFieldType.MIXED_LIST, !Property.REQUIRED);\n        builder.addPersistedLinkProperty(NO_ALIAS, \"columnRealmDictionary\", RealmFieldType.STRING_TO_LINK_MAP, \"AllTypes\");\n        builder.addPersistedMapProperty(NO_ALIAS, \"columnBooleanDictionary\", RealmFieldType.STRING_TO_BOOLEAN_MAP, !Property.REQUIRED);\n        builder.addPersistedMapProperty(NO_ALIAS, \"columnStringDictionary\", RealmFieldType.STRING_TO_STRING_MAP, !Property.REQUIRED);\n        builder.addPersistedMapProperty(NO_ALIAS, \"columnIntegerDictionary\", RealmFieldType.STRING_TO_INTEGER_MAP, !Property.REQUIRED);\n        builder.addPersistedMapProperty(NO_ALIAS, \"columnFloatDictionary\", RealmFieldType.STRING_TO_FLOAT_MAP, !Property.REQUIRED);\n        builder.addPersistedMapProperty(NO_ALIAS, \"columnLongDictionary\", RealmFieldType.STRING_TO_INTEGER_MAP, !Property.REQUIRED);\n        builder.addPersistedMapProperty(NO_ALIAS, \"columnShortDictionary\", RealmFieldType.STRING_TO_INTEGER_MAP, !Property.REQUIRED);\n        builder.addPersistedMapProperty(NO_ALIAS, \"columnDoubleDictionary\", RealmFieldType.STRING_TO_DOUBLE_MAP, !Property.REQUIRED);\n        builder.addPersistedMapProperty(NO_ALIAS, \"columnByteDictionary\", RealmFieldType.STRING_TO_INTEGER_MAP, !Property.REQUIRED);\n        builder.addPersistedMapProperty(NO_ALIAS, \"columnBinaryDictionary\", RealmFieldType.STRING_TO_BINARY_MAP, !Property.REQUIRED);\n        builder.addPersistedMapProperty(NO_ALIAS, \"columnDateDictionary\", RealmFieldType.STRING_TO_DATE_MAP, !Property.REQUIRED);\n        builder.addPersistedMapProperty(NO_ALIAS, \"columnObjectIdDictionary\", RealmFieldType.STRING_TO_OBJECT_ID_MAP, !Property.REQUIRED);\n        builder.addPersistedMapProperty(NO_ALIAS, \"columnUUIDDictionary\", RealmFieldType.STRING_TO_UUID_MAP, !Property.REQUIRED);\n        builder.addPersistedMapProperty(NO_ALIAS, \"columnDecimal128Dictionary\", RealmFieldType.STRING_TO_DECIMAL128_MAP, !Property.REQUIRED);\n        builder.addPersistedMapProperty(NO_ALIAS, \"columnRealmAnyDictionary\", RealmFieldType.STRING_TO_MIXED_MAP, !Property.REQUIRED);\n\n        builder.addComputedLinkProperty(\"parentObjects\", \"AllTypes\", \"columnObject\");\n        return builder.build();\n    }\n\n    public static OsObjectSchemaInfo getExpectedObjectSchemaInfo() {\n        return expectedObjectSchemaInfo;\n    }\n\n    public static AllTypesColumnInfo createColumnInfo(OsSchemaInfo schemaInfo) {\n        return new AllTypesColumnInfo(schemaInfo);\n    }\n\n    public static String getSimpleClassName() {\n        return \"AllTypes\";\n    }\n\n    public static final class ClassNameHelper {\n        public static final String INTERNAL_CLASS_NAME = \"AllTypes\";\n    }\n\n    @SuppressWarnings(\"cast\")\n    public static some.test.AllTypes createOrUpdateUsingJsonObject(Realm realm, JSONObject json, boolean update)\n            throws JSONException {\n        final List<String> excludeFields = new ArrayList<String>(20);\n        some.test.AllTypes obj = null;\n        if (update) {\n            Table table = realm.getTable(some.test.AllTypes.class);\n            AllTypesColumnInfo columnInfo = (AllTypesColumnInfo) realm.getSchema().getColumnInfo(some.test.AllTypes.class);\n            long pkColumnKey = columnInfo.columnStringColKey;\n            long objKey = Table.NO_MATCH;\n            if (json.isNull(\"columnString\")) {\n                objKey = table.findFirstNull(pkColumnKey);\n            } else {\n                objKey = table.findFirstString(pkColumnKey, json.getString(\"columnString\"));\n            }\n            if (objKey != Table.NO_MATCH) {\n                final BaseRealm.RealmObjectContext objectContext = BaseRealm.objectContext.get();\n                try {\n                    objectContext.set(realm, table.getUncheckedRow(objKey), realm.getSchema().getColumnInfo(some.test.AllTypes.class), false, Collections.<String> emptyList());\n                    obj = new io.realm.some_test_AllTypesRealmProxy();\n                } finally {\n                    objectContext.clear();\n                }\n            }\n        }\n        if (obj == null) {\n            if (json.has(\"columnObject\")) {\n                excludeFields.add(\"columnObject\");\n            }\n            if (json.has(\"columnObjectWithoutPk\")) {\n                excludeFields.add(\"columnObjectWithoutPk\");\n            }\n            if (json.has(\"columnRealmList\")) {\n                excludeFields.add(\"columnRealmList\");\n            }\n            if (json.has(\"columnRealmListNoPk\")) {\n                excludeFields.add(\"columnRealmListNoPk\");\n            }\n            if (json.has(\"columnRealmFinalList\")) {\n                excludeFields.add(\"columnRealmFinalList\");\n            }\n            if (json.has(\"columnRealmFinalListNoPk\")) {\n                excludeFields.add(\"columnRealmFinalListNoPk\");\n            }\n            if (json.has(\"columnStringList\")) {\n                excludeFields.add(\"columnStringList\");\n            }\n            if (json.has(\"columnBinaryList\")) {\n                excludeFields.add(\"columnBinaryList\");\n            }\n            if (json.has(\"columnBooleanList\")) {\n                excludeFields.add(\"columnBooleanList\");\n            }\n            if (json.has(\"columnLongList\")) {\n                excludeFields.add(\"columnLongList\");\n            }\n            if (json.has(\"columnIntegerList\")) {\n                excludeFields.add(\"columnIntegerList\");\n            }\n            if (json.has(\"columnShortList\")) {\n                excludeFields.add(\"columnShortList\");\n            }\n            if (json.has(\"columnByteList\")) {\n                excludeFields.add(\"columnByteList\");\n            }\n            if (json.has(\"columnDoubleList\")) {\n                excludeFields.add(\"columnDoubleList\");\n            }\n            if (json.has(\"columnFloatList\")) {\n                excludeFields.add(\"columnFloatList\");\n            }\n            if (json.has(\"columnDateList\")) {\n                excludeFields.add(\"columnDateList\");\n            }\n            if (json.has(\"columnDecimal128List\")) {\n                excludeFields.add(\"columnDecimal128List\");\n            }\n            if (json.has(\"columnObjectIdList\")) {\n                excludeFields.add(\"columnObjectIdList\");\n            }\n            if (json.has(\"columnUUIDList\")) {\n                excludeFields.add(\"columnUUIDList\");\n            }\n            if (json.has(\"columnRealmAnyList\")) {\n                excludeFields.add(\"columnRealmAnyList\");\n            }\n            if (json.has(\"columnString\")) {\n                if (json.isNull(\"columnString\")) {\n                    obj = (io.realm.some_test_AllTypesRealmProxy) realm.createObjectInternal(some.test.AllTypes.class, null, true, excludeFields);\n                } else {\n                    obj = (io.realm.some_test_AllTypesRealmProxy) realm.createObjectInternal(some.test.AllTypes.class, json.getString(\"columnString\"), true, excludeFields);\n                }\n            } else {\n                throw new IllegalArgumentException(\"JSON object doesn't have the primary key field 'columnString'.\");\n            }\n        }\n\n        final some_test_AllTypesRealmProxyInterface objProxy = (some_test_AllTypesRealmProxyInterface) obj;\n        if (json.has(\"columnLong\")) {\n            if (json.isNull(\"columnLong\")) {\n                throw new IllegalArgumentException(\"Trying to set non-nullable field 'columnLong' to null.\");\n            } else {\n                objProxy.realmSet$columnLong((long) json.getLong(\"columnLong\"));\n            }\n        }\n        if (json.has(\"columnFloat\")) {\n            if (json.isNull(\"columnFloat\")) {\n                throw new IllegalArgumentException(\"Trying to set non-nullable field 'columnFloat' to null.\");\n            } else {\n                objProxy.realmSet$columnFloat((float) json.getDouble(\"columnFloat\"));\n            }\n        }\n        if (json.has(\"columnDouble\")) {\n            if (json.isNull(\"columnDouble\")) {\n                throw new IllegalArgumentException(\"Trying to set non-nullable field 'columnDouble' to null.\");\n            } else {\n                objProxy.realmSet$columnDouble((double) json.getDouble(\"columnDouble\"));\n            }\n        }\n        if (json.has(\"columnBoolean\")) {\n            if (json.isNull(\"columnBoolean\")) {\n                throw new IllegalArgumentException(\"Trying to set non-nullable field 'columnBoolean' to null.\");\n            } else {\n                objProxy.realmSet$columnBoolean((boolean) json.getBoolean(\"columnBoolean\"));\n            }\n        }\n        if (json.has(\"columnDecimal128\")) {\n            if (json.isNull(\"columnDecimal128\")) {\n                objProxy.realmSet$columnDecimal128(null);\n            } else {\n                Object decimal = json.get(\"columnDecimal128\");\n                if (decimal instanceof org.bson.types.Decimal128) {\n                    objProxy.realmSet$columnDecimal128((org.bson.types.Decimal128) decimal);\n                } else if (decimal instanceof String) {\n                    objProxy.realmSet$columnDecimal128(org.bson.types.Decimal128.parse((String)decimal));\n                } else if (decimal instanceof Integer) {\n                    objProxy.realmSet$columnDecimal128(new org.bson.types.Decimal128((Integer)(decimal)));\n                } else if (decimal instanceof Long) {\n                    objProxy.realmSet$columnDecimal128(new org.bson.types.Decimal128((Long)(decimal)));\n                } else if (decimal instanceof Double) {\n                    objProxy.realmSet$columnDecimal128(new org.bson.types.Decimal128(new java.math.BigDecimal((Double)(decimal))));\n                } else {\n                    throw new UnsupportedOperationException(decimal.getClass() + \" is not supported as a Decimal128 value\");\n                }\n            }\n        }\n        if (json.has(\"columnObjectId\")) {\n            if (json.isNull(\"columnObjectId\")) {\n                objProxy.realmSet$columnObjectId(null);\n            } else {\n                Object id = json.get(\"columnObjectId\");\n                if (id instanceof org.bson.types.ObjectId) {\n                    objProxy.realmSet$columnObjectId((org.bson.types.ObjectId) id);\n                } else {\n                    objProxy.realmSet$columnObjectId(new org.bson.types.ObjectId((String)id));\n                }\n            }\n        }\n        if (json.has(\"columnUUID\")) {\n            if (json.isNull(\"columnUUID\")) {\n                objProxy.realmSet$columnUUID(null);\n            } else {\n                Object id = json.get(\"columnUUID\");\n                if (id instanceof java.util.UUID) {\n                    objProxy.realmSet$columnUUID((java.util.UUID) id);\n                } else {\n                    objProxy.realmSet$columnUUID(java.util.UUID.fromString((String)id));\n                }\n            }\n        }\n        if (json.has(\"columnDate\")) {\n            if (json.isNull(\"columnDate\")) {\n                objProxy.realmSet$columnDate(null);\n            } else {\n                Object timestamp = json.get(\"columnDate\");\n                if (timestamp instanceof String) {\n                    objProxy.realmSet$columnDate(JsonUtils.stringToDate((String) timestamp));\n                } else {\n                    objProxy.realmSet$columnDate(new Date(json.getLong(\"columnDate\")));\n                }\n            }\n        }\n        if (json.has(\"columnRealmAny\")) {\n            if (json.isNull(\"columnRealmAny\")) {\n                objProxy.realmSet$columnRealmAny(null);\n            } else {\n                Object value = json.get(\"columnRealmAny\");\n                RealmAny realmAny;\n                if (value instanceof String) {\n                    realmAny = RealmAny.valueOf((String) value);\n                } else if (value instanceof Integer) {\n                    realmAny = RealmAny.valueOf((Integer) value);\n                } else if (value instanceof Long) {\n                    realmAny = RealmAny.valueOf((Long) value);\n                } else if (value instanceof Double) {\n                    realmAny = RealmAny.valueOf((Double) value);\n                } else if (value instanceof Boolean) {\n                    realmAny = RealmAny.valueOf((Boolean) value);\n                } else if (value instanceof RealmAny) {\n                    realmAny = (io.realm.RealmAny) value;\n                    realmAny = ProxyUtils.copyOrUpdate(realmAny, realm, update, new HashMap<>(), new HashSet<>());\n                } else {\n                    throw new IllegalArgumentException(String.format(\"Unsupported JSON type: %s\", value.getClass().getSimpleName()));\n                }\n                objProxy.realmSet$columnRealmAny(realmAny);\n            }\n        }\n        if (json.has(\"columnBinary\")) {\n            if (json.isNull(\"columnBinary\")) {\n                objProxy.realmSet$columnBinary(null);\n            } else {\n                objProxy.realmSet$columnBinary(JsonUtils.stringToBytes(json.getString(\"columnBinary\")));\n            }\n        }\n        if (json.has(\"columnMutableRealmInteger\")) {\n            objProxy.realmGet$columnMutableRealmInteger().set((json.isNull(\"columnMutableRealmInteger\")) ? null : json.getLong(\"columnMutableRealmInteger\"));\n        }\n        if (json.has(\"columnObject\")) {\n            if (json.isNull(\"columnObject\")) {\n                objProxy.realmSet$columnObject(null);\n            } else {\n                some.test.AllTypes columnObjectObj = some_test_AllTypesRealmProxy.createOrUpdateUsingJsonObject(realm, json.getJSONObject(\"columnObject\"), update);\n                objProxy.realmSet$columnObject(columnObjectObj);\n            }\n        }\n        if (json.has(\"columnObjectWithoutPk\")) {\n            if (json.isNull(\"columnObjectWithoutPk\")) {\n                objProxy.realmSet$columnObjectWithoutPk(null);\n            } else {\n                some.test.Simple columnObjectWithoutPkObj = some_test_SimpleRealmProxy.createOrUpdateUsingJsonObject(realm, json.getJSONObject(\"columnObjectWithoutPk\"), update);\n                objProxy.realmSet$columnObjectWithoutPk(columnObjectWithoutPkObj);\n            }\n        }\n        if (json.has(\"columnRealmList\")) {\n            if (json.isNull(\"columnRealmList\")) {\n                objProxy.realmSet$columnRealmList(null);\n            } else {\n                objProxy.realmGet$columnRealmList().clear();\n                JSONArray array = json.getJSONArray(\"columnRealmList\");\n                for (int i = 0; i < array.length(); i++) {\n                    some.test.AllTypes item = some_test_AllTypesRealmProxy.createOrUpdateUsingJsonObject(realm, array.getJSONObject(i), update);\n                    objProxy.realmGet$columnRealmList().add(item);\n                }\n            }\n        }\n        if (json.has(\"columnRealmListNoPk\")) {\n            if (json.isNull(\"columnRealmListNoPk\")) {\n                objProxy.realmSet$columnRealmListNoPk(null);\n            } else {\n                objProxy.realmGet$columnRealmListNoPk().clear();\n                JSONArray array = json.getJSONArray(\"columnRealmListNoPk\");\n                for (int i = 0; i < array.length(); i++) {\n                    some.test.Simple item = some_test_SimpleRealmProxy.createOrUpdateUsingJsonObject(realm, array.getJSONObject(i), update);\n                    objProxy.realmGet$columnRealmListNoPk().add(item);\n                }\n            }\n        }\n        if (json.has(\"columnRealmFinalList\")) {\n            if (json.isNull(\"columnRealmFinalList\")) {\n                objProxy.realmSet$columnRealmFinalList(null);\n            } else {\n                objProxy.realmGet$columnRealmFinalList().clear();\n                JSONArray array = json.getJSONArray(\"columnRealmFinalList\");\n                for (int i = 0; i < array.length(); i++) {\n                    some.test.AllTypes item = some_test_AllTypesRealmProxy.createOrUpdateUsingJsonObject(realm, array.getJSONObject(i), update);\n                    objProxy.realmGet$columnRealmFinalList().add(item);\n                }\n            }\n        }\n        if (json.has(\"columnRealmFinalListNoPk\")) {\n            if (json.isNull(\"columnRealmFinalListNoPk\")) {\n                objProxy.realmSet$columnRealmFinalListNoPk(null);\n            } else {\n                objProxy.realmGet$columnRealmFinalListNoPk().clear();\n                JSONArray array = json.getJSONArray(\"columnRealmFinalListNoPk\");\n                for (int i = 0; i < array.length(); i++) {\n                    some.test.Simple item = some_test_SimpleRealmProxy.createOrUpdateUsingJsonObject(realm, array.getJSONObject(i), update);\n                    objProxy.realmGet$columnRealmFinalListNoPk().add(item);\n                }\n            }\n        }\n        ProxyUtils.setRealmListWithJsonObject(realm, objProxy.realmGet$columnStringList(), json, \"columnStringList\", update);\n        ProxyUtils.setRealmListWithJsonObject(realm, objProxy.realmGet$columnBinaryList(), json, \"columnBinaryList\", update);\n        ProxyUtils.setRealmListWithJsonObject(realm, objProxy.realmGet$columnBooleanList(), json, \"columnBooleanList\", update);\n        ProxyUtils.setRealmListWithJsonObject(realm, objProxy.realmGet$columnLongList(), json, \"columnLongList\", update);\n        ProxyUtils.setRealmListWithJsonObject(realm, objProxy.realmGet$columnIntegerList(), json, \"columnIntegerList\", update);\n        ProxyUtils.setRealmListWithJsonObject(realm, objProxy.realmGet$columnShortList(), json, \"columnShortList\", update);\n        ProxyUtils.setRealmListWithJsonObject(realm, objProxy.realmGet$columnByteList(), json, \"columnByteList\", update);\n        ProxyUtils.setRealmListWithJsonObject(realm, objProxy.realmGet$columnDoubleList(), json, \"columnDoubleList\", update);\n        ProxyUtils.setRealmListWithJsonObject(realm, objProxy.realmGet$columnFloatList(), json, \"columnFloatList\", update);\n        ProxyUtils.setRealmListWithJsonObject(realm, objProxy.realmGet$columnDateList(), json, \"columnDateList\", update);\n        ProxyUtils.setRealmListWithJsonObject(realm, objProxy.realmGet$columnDecimal128List(), json, \"columnDecimal128List\", update);\n        ProxyUtils.setRealmListWithJsonObject(realm, objProxy.realmGet$columnObjectIdList(), json, \"columnObjectIdList\", update);\n        ProxyUtils.setRealmListWithJsonObject(realm, objProxy.realmGet$columnUUIDList(), json, \"columnUUIDList\", update);\n        ProxyUtils.setRealmListWithJsonObject(realm, objProxy.realmGet$columnRealmAnyList(), json, \"columnRealmAnyList\", update);\n        return obj;\n    }\n\n    @SuppressWarnings(\"cast\")\n    @TargetApi(Build.VERSION_CODES.HONEYCOMB)\n    public static some.test.AllTypes createUsingJsonStream(Realm realm, JsonReader reader)\n            throws IOException {\n        boolean jsonHasPrimaryKey = false;\n        final some.test.AllTypes obj = new some.test.AllTypes();\n        final some_test_AllTypesRealmProxyInterface objProxy = (some_test_AllTypesRealmProxyInterface) obj;\n        reader.beginObject();\n        while (reader.hasNext()) {\n            String name = reader.nextName();\n            if (false) {\n            } else if (name.equals(\"columnString\")) {\n                if (reader.peek() != JsonToken.NULL) {\n                    objProxy.realmSet$columnString((String) reader.nextString());\n                } else {\n                    reader.skipValue();\n                    objProxy.realmSet$columnString(null);\n                }\n                jsonHasPrimaryKey = true;\n            } else if (name.equals(\"columnLong\")) {\n                if (reader.peek() != JsonToken.NULL) {\n                    objProxy.realmSet$columnLong((long) reader.nextLong());\n                } else {\n                    reader.skipValue();\n                    throw new IllegalArgumentException(\"Trying to set non-nullable field 'columnLong' to null.\");\n                }\n            } else if (name.equals(\"columnFloat\")) {\n                if (reader.peek() != JsonToken.NULL) {\n                    objProxy.realmSet$columnFloat((float) reader.nextDouble());\n                } else {\n                    reader.skipValue();\n                    throw new IllegalArgumentException(\"Trying to set non-nullable field 'columnFloat' to null.\");\n                }\n            } else if (name.equals(\"columnDouble\")) {\n                if (reader.peek() != JsonToken.NULL) {\n                    objProxy.realmSet$columnDouble((double) reader.nextDouble());\n                } else {\n                    reader.skipValue();\n                    throw new IllegalArgumentException(\"Trying to set non-nullable field 'columnDouble' to null.\");\n                }\n            } else if (name.equals(\"columnBoolean\")) {\n                if (reader.peek() != JsonToken.NULL) {\n                    objProxy.realmSet$columnBoolean((boolean) reader.nextBoolean());\n                } else {\n                    reader.skipValue();\n                    throw new IllegalArgumentException(\"Trying to set non-nullable field 'columnBoolean' to null.\");\n                }\n            } else if (name.equals(\"columnDecimal128\")) {\n                if (reader.peek() == JsonToken.NULL) {\n                    reader.skipValue();\n                    objProxy.realmSet$columnDecimal128(null);\n                } else {\n                    objProxy.realmSet$columnDecimal128(org.bson.types.Decimal128.parse(reader.nextString()));\n                }\n            } else if (name.equals(\"columnObjectId\")) {\n                if (reader.peek() == JsonToken.NULL) {\n                    reader.skipValue();\n                    objProxy.realmSet$columnObjectId(null);\n                } else {\n                    objProxy.realmSet$columnObjectId(new org.bson.types.ObjectId(reader.nextString()));\n                }\n            } else if (name.equals(\"columnUUID\")) {\n                if (reader.peek() == JsonToken.NULL) {\n                    reader.skipValue();\n                    objProxy.realmSet$columnUUID(null);\n                } else {\n                    objProxy.realmSet$columnUUID(java.util.UUID.fromString(reader.nextString()));\n                }\n            } else if (name.equals(\"columnDate\")) {\n                if (reader.peek() == JsonToken.NULL) {\n                    reader.skipValue();\n                    objProxy.realmSet$columnDate(null);\n                } else if (reader.peek() == JsonToken.NUMBER) {\n                    long timestamp = reader.nextLong();\n                    if (timestamp > -1) {\n                        objProxy.realmSet$columnDate(new Date(timestamp));\n                    }\n                } else {\n                    objProxy.realmSet$columnDate(JsonUtils.stringToDate(reader.nextString()));\n                }\n            } else if (name.equals(\"columnRealmAny\")) {\n                if (reader.peek() == JsonToken.NULL) {\n                    reader.skipValue();\n                    objProxy.realmSet$columnRealmAny(RealmAny.nullValue());\n                } else if (reader.peek() == JsonToken.STRING) {\n                    objProxy.realmSet$columnRealmAny(RealmAny.valueOf(reader.nextString()));\n                } else if (reader.peek() == JsonToken.NUMBER) {\n                    String value = reader.nextString();\n                    if (value.contains(\".\")) {\n                        objProxy.realmSet$columnRealmAny(RealmAny.valueOf(Double.parseDouble(value)));\n                    } else {\n                        objProxy.realmSet$columnRealmAny(RealmAny.valueOf(Long.parseLong(value)));\n                    }\n                } else if (reader.peek() == JsonToken.BOOLEAN) {\n                    objProxy.realmSet$columnRealmAny(RealmAny.valueOf(reader.nextBoolean()));\n                }\n            } else if (name.equals(\"columnBinary\")) {\n                if (reader.peek() != JsonToken.NULL) {\n                    objProxy.realmSet$columnBinary(JsonUtils.stringToBytes(reader.nextString()));\n                } else {\n                    reader.skipValue();\n                    objProxy.realmSet$columnBinary(null);\n                }\n            } else if (name.equals(\"columnMutableRealmInteger\")) {\n                Long val = null;\n                if (reader.peek() != JsonToken.NULL) {\n                    val = reader.nextLong();\n                } else {\n                    reader.skipValue();\n                }\n                objProxy.realmGet$columnMutableRealmInteger().set(val);\n            } else if (name.equals(\"columnObject\")) {\n                if (reader.peek() == JsonToken.NULL) {\n                    reader.skipValue();\n                    objProxy.realmSet$columnObject(null);\n                } else {\n                    some.test.AllTypes columnObjectObj = some_test_AllTypesRealmProxy.createUsingJsonStream(realm, reader);\n                    objProxy.realmSet$columnObject(columnObjectObj);\n                }\n            } else if (name.equals(\"columnObjectWithoutPk\")) {\n                if (reader.peek() == JsonToken.NULL) {\n                    reader.skipValue();\n                    objProxy.realmSet$columnObjectWithoutPk(null);\n                } else {\n                    some.test.Simple columnObjectWithoutPkObj = some_test_SimpleRealmProxy.createUsingJsonStream(realm, reader);\n                    objProxy.realmSet$columnObjectWithoutPk(columnObjectWithoutPkObj);\n                }\n            } else if (name.equals(\"columnRealmList\")) {\n                if (reader.peek() == JsonToken.NULL) {\n                    reader.skipValue();\n                    objProxy.realmSet$columnRealmList(null);\n                } else {\n                    objProxy.realmSet$columnRealmList(new RealmList<some.test.AllTypes>());\n                    reader.beginArray();\n                    while (reader.hasNext()) {\n                        some.test.AllTypes item = some_test_AllTypesRealmProxy.createUsingJsonStream(realm, reader);\n                        objProxy.realmGet$columnRealmList().add(item);\n                    }\n                    reader.endArray();\n                }\n            } else if (name.equals(\"columnRealmListNoPk\")) {\n                if (reader.peek() == JsonToken.NULL) {\n                    reader.skipValue();\n                    objProxy.realmSet$columnRealmListNoPk(null);\n                } else {\n                    objProxy.realmSet$columnRealmListNoPk(new RealmList<some.test.Simple>());\n                    reader.beginArray();\n                    while (reader.hasNext()) {\n                        some.test.Simple item = some_test_SimpleRealmProxy.createUsingJsonStream(realm, reader);\n                        objProxy.realmGet$columnRealmListNoPk().add(item);\n                    }\n                    reader.endArray();\n                }\n            } else if (name.equals(\"columnRealmFinalList\")) {\n                if (reader.peek() == JsonToken.NULL) {\n                    reader.skipValue();\n                    objProxy.realmSet$columnRealmFinalList(null);\n                } else {\n                    objProxy.realmSet$columnRealmFinalList(new RealmList<some.test.AllTypes>());\n                    reader.beginArray();\n                    while (reader.hasNext()) {\n                        some.test.AllTypes item = some_test_AllTypesRealmProxy.createUsingJsonStream(realm, reader);\n                        objProxy.realmGet$columnRealmFinalList().add(item);\n                    }\n                    reader.endArray();\n                }\n            } else if (name.equals(\"columnRealmFinalListNoPk\")) {\n                if (reader.peek() == JsonToken.NULL) {\n                    reader.skipValue();\n                    objProxy.realmSet$columnRealmFinalListNoPk(null);\n                } else {\n                    objProxy.realmSet$columnRealmFinalListNoPk(new RealmList<some.test.Simple>());\n                    reader.beginArray();\n                    while (reader.hasNext()) {\n                        some.test.Simple item = some_test_SimpleRealmProxy.createUsingJsonStream(realm, reader);\n                        objProxy.realmGet$columnRealmFinalListNoPk().add(item);\n                    }\n                    reader.endArray();\n                }\n            } else if (name.equals(\"columnStringList\")) {\n                objProxy.realmSet$columnStringList(ProxyUtils.createRealmListWithJsonStream(java.lang.String.class, reader));\n            } else if (name.equals(\"columnBinaryList\")) {\n                objProxy.realmSet$columnBinaryList(ProxyUtils.createRealmListWithJsonStream(byte[].class, reader));\n            } else if (name.equals(\"columnBooleanList\")) {\n                objProxy.realmSet$columnBooleanList(ProxyUtils.createRealmListWithJsonStream(java.lang.Boolean.class, reader));\n            } else if (name.equals(\"columnLongList\")) {\n                objProxy.realmSet$columnLongList(ProxyUtils.createRealmListWithJsonStream(java.lang.Long.class, reader));\n            } else if (name.equals(\"columnIntegerList\")) {\n                objProxy.realmSet$columnIntegerList(ProxyUtils.createRealmListWithJsonStream(java.lang.Integer.class, reader));\n            } else if (name.equals(\"columnShortList\")) {\n                objProxy.realmSet$columnShortList(ProxyUtils.createRealmListWithJsonStream(java.lang.Short.class, reader));\n            } else if (name.equals(\"columnByteList\")) {\n                objProxy.realmSet$columnByteList(ProxyUtils.createRealmListWithJsonStream(java.lang.Byte.class, reader));\n            } else if (name.equals(\"columnDoubleList\")) {\n                objProxy.realmSet$columnDoubleList(ProxyUtils.createRealmListWithJsonStream(java.lang.Double.class, reader));\n            } else if (name.equals(\"columnFloatList\")) {\n                objProxy.realmSet$columnFloatList(ProxyUtils.createRealmListWithJsonStream(java.lang.Float.class, reader));\n            } else if (name.equals(\"columnDateList\")) {\n                objProxy.realmSet$columnDateList(ProxyUtils.createRealmListWithJsonStream(java.util.Date.class, reader));\n            } else if (name.equals(\"columnDecimal128List\")) {\n                objProxy.realmSet$columnDecimal128List(ProxyUtils.createRealmListWithJsonStream(org.bson.types.Decimal128.class, reader));\n            } else if (name.equals(\"columnObjectIdList\")) {\n                objProxy.realmSet$columnObjectIdList(ProxyUtils.createRealmListWithJsonStream(org.bson.types.ObjectId.class, reader));\n            } else if (name.equals(\"columnUUIDList\")) {\n                objProxy.realmSet$columnUUIDList(ProxyUtils.createRealmListWithJsonStream(java.util.UUID.class, reader));\n            } else if (name.equals(\"columnRealmAnyList\")) {\n                objProxy.realmSet$columnRealmAnyList(ProxyUtils.createRealmListWithJsonStream(io.realm.RealmAny.class, reader));\n            } else if (name.equals(\"columnRealmDictionary\")) {\n                // TODO: Dictionary\n            } else if (name.equals(\"columnBooleanDictionary\")) {\n                // TODO: Dictionary\n            } else if (name.equals(\"columnStringDictionary\")) {\n                // TODO: Dictionary\n            } else if (name.equals(\"columnIntegerDictionary\")) {\n                // TODO: Dictionary\n            } else if (name.equals(\"columnFloatDictionary\")) {\n                // TODO: Dictionary\n            } else if (name.equals(\"columnLongDictionary\")) {\n                // TODO: Dictionary\n            } else if (name.equals(\"columnShortDictionary\")) {\n                // TODO: Dictionary\n            } else if (name.equals(\"columnDoubleDictionary\")) {\n                // TODO: Dictionary\n            } else if (name.equals(\"columnByteDictionary\")) {\n                // TODO: Dictionary\n            } else if (name.equals(\"columnBinaryDictionary\")) {\n                // TODO: Dictionary\n            } else if (name.equals(\"columnDateDictionary\")) {\n                // TODO: Dictionary\n            } else if (name.equals(\"columnObjectIdDictionary\")) {\n                // TODO: Dictionary\n            } else if (name.equals(\"columnUUIDDictionary\")) {\n                // TODO: Dictionary\n            } else if (name.equals(\"columnDecimal128Dictionary\")) {\n                // TODO: Dictionary\n            } else if (name.equals(\"columnRealmAnyDictionary\")) {\n                // TODO: Dictionary\n            } else {\n                reader.skipValue();\n            }\n        }\n        reader.endObject();\n        if (!jsonHasPrimaryKey) {\n            throw new IllegalArgumentException(\"JSON object doesn't have the primary key field 'columnString'.\");\n        }\n        return realm.copyToRealmOrUpdate(obj);\n    }\n\n    static some_test_AllTypesRealmProxy newProxyInstance(BaseRealm realm, Row row) {\n        // Ignore default values to avoid creating unexpected objects from RealmModel/RealmList fields\n        final BaseRealm.RealmObjectContext objectContext = BaseRealm.objectContext.get();\n        objectContext.set(realm, row, realm.getSchema().getColumnInfo(some.test.AllTypes.class), false, Collections.<String>emptyList());\n        io.realm.some_test_AllTypesRealmProxy obj = new io.realm.some_test_AllTypesRealmProxy();\n        objectContext.clear();\n        return obj;\n    }\n\n    public static some.test.AllTypes copyOrUpdate(Realm realm, AllTypesColumnInfo columnInfo, some.test.AllTypes object, boolean update, Map<RealmModel,RealmObjectProxy> cache, Set<ImportFlag> flags) {\n        if (object instanceof RealmObjectProxy && !RealmObject.isFrozen(object) && ((RealmObjectProxy) object).realmGet$proxyState().getRealm$realm() != null) {\n            final BaseRealm otherRealm = ((RealmObjectProxy) object).realmGet$proxyState().getRealm$realm();\n            if (otherRealm.threadId != realm.threadId) {\n                throw new IllegalArgumentException(\"Objects which belong to Realm instances in other threads cannot be copied into this Realm instance.\");\n            }\n            if (otherRealm.getPath().equals(realm.getPath())) {\n                return object;\n            }\n        }\n        final BaseRealm.RealmObjectContext objectContext = BaseRealm.objectContext.get();\n        RealmObjectProxy cachedRealmObject = cache.get(object);\n        if (cachedRealmObject != null) {\n            return (some.test.AllTypes) cachedRealmObject;\n        }\n\n        some.test.AllTypes realmObject = null;\n        boolean canUpdate = update;\n        if (canUpdate) {\n            Table table = realm.getTable(some.test.AllTypes.class);\n            long pkColumnKey = columnInfo.columnStringColKey;\n            String value = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnString();\n            long objKey = Table.NO_MATCH;\n            if (value == null) {\n                objKey = table.findFirstNull(pkColumnKey);\n            } else {\n                objKey = table.findFirstString(pkColumnKey, value);\n            }\n            if (objKey == Table.NO_MATCH) {\n                canUpdate = false;\n            } else {\n                try {\n                    objectContext.set(realm, table.getUncheckedRow(objKey), columnInfo, false, Collections.<String> emptyList());\n                    realmObject = new io.realm.some_test_AllTypesRealmProxy();\n                    cache.put(object, (RealmObjectProxy) realmObject);\n                } finally {\n                    objectContext.clear();\n                }\n            }\n        }\n\n        return (canUpdate) ? update(realm, columnInfo, realmObject, object, cache, flags) : copy(realm, columnInfo, object, update, cache, flags);\n    }\n\n    public static some.test.AllTypes copy(Realm realm, AllTypesColumnInfo columnInfo, some.test.AllTypes newObject, boolean update, Map<RealmModel,RealmObjectProxy> cache, Set<ImportFlag> flags) {\n        RealmObjectProxy cachedRealmObject = cache.get(newObject);\n        if (cachedRealmObject != null) {\n            return (some.test.AllTypes) cachedRealmObject;\n        }\n\n        some_test_AllTypesRealmProxyInterface unmanagedSource = (some_test_AllTypesRealmProxyInterface) newObject;\n\n        Table table = realm.getTable(some.test.AllTypes.class);\n        OsObjectBuilder builder = new OsObjectBuilder(table, flags);\n\n        // Add all non-\"object reference\" fields\n        builder.addString(columnInfo.columnStringColKey, unmanagedSource.realmGet$columnString());\n        builder.addInteger(columnInfo.columnLongColKey, unmanagedSource.realmGet$columnLong());\n        builder.addFloat(columnInfo.columnFloatColKey, unmanagedSource.realmGet$columnFloat());\n        builder.addDouble(columnInfo.columnDoubleColKey, unmanagedSource.realmGet$columnDouble());\n        builder.addBoolean(columnInfo.columnBooleanColKey, unmanagedSource.realmGet$columnBoolean());\n        builder.addDecimal128(columnInfo.columnDecimal128ColKey, unmanagedSource.realmGet$columnDecimal128());\n        builder.addObjectId(columnInfo.columnObjectIdColKey, unmanagedSource.realmGet$columnObjectId());\n        builder.addUUID(columnInfo.columnUUIDColKey, unmanagedSource.realmGet$columnUUID());\n        builder.addDate(columnInfo.columnDateColKey, unmanagedSource.realmGet$columnDate());\n        builder.addByteArray(columnInfo.columnBinaryColKey, unmanagedSource.realmGet$columnBinary());\n        builder.addMutableRealmInteger(columnInfo.columnMutableRealmIntegerColKey, unmanagedSource.realmGet$columnMutableRealmInteger());\n        builder.addStringList(columnInfo.columnStringListColKey, unmanagedSource.realmGet$columnStringList());\n        builder.addByteArrayList(columnInfo.columnBinaryListColKey, unmanagedSource.realmGet$columnBinaryList());\n        builder.addBooleanList(columnInfo.columnBooleanListColKey, unmanagedSource.realmGet$columnBooleanList());\n        builder.addLongList(columnInfo.columnLongListColKey, unmanagedSource.realmGet$columnLongList());\n        builder.addIntegerList(columnInfo.columnIntegerListColKey, unmanagedSource.realmGet$columnIntegerList());\n        builder.addShortList(columnInfo.columnShortListColKey, unmanagedSource.realmGet$columnShortList());\n        builder.addByteList(columnInfo.columnByteListColKey, unmanagedSource.realmGet$columnByteList());\n        builder.addDoubleList(columnInfo.columnDoubleListColKey, unmanagedSource.realmGet$columnDoubleList());\n        builder.addFloatList(columnInfo.columnFloatListColKey, unmanagedSource.realmGet$columnFloatList());\n        builder.addDateList(columnInfo.columnDateListColKey, unmanagedSource.realmGet$columnDateList());\n        builder.addDecimal128List(columnInfo.columnDecimal128ListColKey, unmanagedSource.realmGet$columnDecimal128List());\n        builder.addObjectIdList(columnInfo.columnObjectIdListColKey, unmanagedSource.realmGet$columnObjectIdList());\n        builder.addUUIDList(columnInfo.columnUUIDListColKey, unmanagedSource.realmGet$columnUUIDList());\n        builder.addBooleanValueDictionary(columnInfo.columnBooleanDictionaryColKey, unmanagedSource.realmGet$columnBooleanDictionary());\n        builder.addStringValueDictionary(columnInfo.columnStringDictionaryColKey, unmanagedSource.realmGet$columnStringDictionary());\n        builder.addIntegerValueDictionary(columnInfo.columnIntegerDictionaryColKey, unmanagedSource.realmGet$columnIntegerDictionary());\n        builder.addFloatValueDictionary(columnInfo.columnFloatDictionaryColKey, unmanagedSource.realmGet$columnFloatDictionary());\n        builder.addLongValueDictionary(columnInfo.columnLongDictionaryColKey, unmanagedSource.realmGet$columnLongDictionary());\n        builder.addShortValueDictionary(columnInfo.columnShortDictionaryColKey, unmanagedSource.realmGet$columnShortDictionary());\n        builder.addDoubleValueDictionary(columnInfo.columnDoubleDictionaryColKey, unmanagedSource.realmGet$columnDoubleDictionary());\n        builder.addByteValueDictionary(columnInfo.columnByteDictionaryColKey, unmanagedSource.realmGet$columnByteDictionary());\n        builder.addBinaryValueDictionary(columnInfo.columnBinaryDictionaryColKey, unmanagedSource.realmGet$columnBinaryDictionary());\n        builder.addDateValueDictionary(columnInfo.columnDateDictionaryColKey, unmanagedSource.realmGet$columnDateDictionary());\n        builder.addObjectIdValueDictionary(columnInfo.columnObjectIdDictionaryColKey, unmanagedSource.realmGet$columnObjectIdDictionary());\n        builder.addUUIDValueDictionary(columnInfo.columnUUIDDictionaryColKey, unmanagedSource.realmGet$columnUUIDDictionary());\n        builder.addDecimal128ValueDictionary(columnInfo.columnDecimal128DictionaryColKey, unmanagedSource.realmGet$columnDecimal128Dictionary());\n\n        // Create the underlying object and cache it before setting any object/objectlist references\n        // This will allow us to break any circular dependencies by using the object cache.\n        Row row = builder.createNewObject();\n        io.realm.some_test_AllTypesRealmProxy managedCopy = newProxyInstance(realm, row);\n        cache.put(newObject, managedCopy);\n\n        // Finally add all fields that reference other Realm Objects, either directly or through a list\n        RealmAny columnRealmAnyRealmAny = unmanagedSource.realmGet$columnRealmAny();\n        columnRealmAnyRealmAny = ProxyUtils.copyOrUpdate(columnRealmAnyRealmAny, realm, update, cache, flags);\n        managedCopy.realmSet$columnRealmAny(columnRealmAnyRealmAny);\n\n        some.test.AllTypes columnObjectObj = unmanagedSource.realmGet$columnObject();\n        if (columnObjectObj == null) {\n            managedCopy.realmSet$columnObject(null);\n        } else {\n            some.test.AllTypes cachecolumnObject = (some.test.AllTypes) cache.get(columnObjectObj);\n            if (cachecolumnObject != null) {\n                managedCopy.realmSet$columnObject(cachecolumnObject);\n            } else {\n                managedCopy.realmSet$columnObject(some_test_AllTypesRealmProxy.copyOrUpdate(realm, (some_test_AllTypesRealmProxy.AllTypesColumnInfo) realm.getSchema().getColumnInfo(some.test.AllTypes.class), columnObjectObj, update, cache, flags));\n            }\n        }\n\n        some.test.Simple columnObjectWithoutPkObj = unmanagedSource.realmGet$columnObjectWithoutPk();\n        if (columnObjectWithoutPkObj == null) {\n            managedCopy.realmSet$columnObjectWithoutPk(null);\n        } else {\n            some.test.Simple cachecolumnObjectWithoutPk = (some.test.Simple) cache.get(columnObjectWithoutPkObj);\n            if (cachecolumnObjectWithoutPk != null) {\n                managedCopy.realmSet$columnObjectWithoutPk(cachecolumnObjectWithoutPk);\n            } else {\n                managedCopy.realmSet$columnObjectWithoutPk(some_test_SimpleRealmProxy.copyOrUpdate(realm, (some_test_SimpleRealmProxy.SimpleColumnInfo) realm.getSchema().getColumnInfo(some.test.Simple.class), columnObjectWithoutPkObj, update, cache, flags));\n            }\n        }\n\n        RealmList<some.test.AllTypes> columnRealmListUnmanagedList = unmanagedSource.realmGet$columnRealmList();\n        if (columnRealmListUnmanagedList != null) {\n            RealmList<some.test.AllTypes> columnRealmListManagedList = managedCopy.realmGet$columnRealmList();\n            columnRealmListManagedList.clear();\n            for (int i = 0; i < columnRealmListUnmanagedList.size(); i++) {\n                some.test.AllTypes columnRealmListUnmanagedItem = columnRealmListUnmanagedList.get(i);\n                some.test.AllTypes cachecolumnRealmList = (some.test.AllTypes) cache.get(columnRealmListUnmanagedItem);\n                if (cachecolumnRealmList != null) {\n                    columnRealmListManagedList.add(cachecolumnRealmList);\n                } else {\n                    columnRealmListManagedList.add(some_test_AllTypesRealmProxy.copyOrUpdate(realm, (some_test_AllTypesRealmProxy.AllTypesColumnInfo) realm.getSchema().getColumnInfo(some.test.AllTypes.class), columnRealmListUnmanagedItem, update, cache, flags));\n                }\n            }\n        }\n\n        RealmList<some.test.Simple> columnRealmListNoPkUnmanagedList = unmanagedSource.realmGet$columnRealmListNoPk();\n        if (columnRealmListNoPkUnmanagedList != null) {\n            RealmList<some.test.Simple> columnRealmListNoPkManagedList = managedCopy.realmGet$columnRealmListNoPk();\n            columnRealmListNoPkManagedList.clear();\n            for (int i = 0; i < columnRealmListNoPkUnmanagedList.size(); i++) {\n                some.test.Simple columnRealmListNoPkUnmanagedItem = columnRealmListNoPkUnmanagedList.get(i);\n                some.test.Simple cachecolumnRealmListNoPk = (some.test.Simple) cache.get(columnRealmListNoPkUnmanagedItem);\n                if (cachecolumnRealmListNoPk != null) {\n                    columnRealmListNoPkManagedList.add(cachecolumnRealmListNoPk);\n                } else {\n                    columnRealmListNoPkManagedList.add(some_test_SimpleRealmProxy.copyOrUpdate(realm, (some_test_SimpleRealmProxy.SimpleColumnInfo) realm.getSchema().getColumnInfo(some.test.Simple.class), columnRealmListNoPkUnmanagedItem, update, cache, flags));\n                }\n            }\n        }\n\n        RealmList<some.test.AllTypes> columnRealmFinalListUnmanagedList = unmanagedSource.realmGet$columnRealmFinalList();\n        if (columnRealmFinalListUnmanagedList != null) {\n            RealmList<some.test.AllTypes> columnRealmFinalListManagedList = managedCopy.realmGet$columnRealmFinalList();\n            columnRealmFinalListManagedList.clear();\n            for (int i = 0; i < columnRealmFinalListUnmanagedList.size(); i++) {\n                some.test.AllTypes columnRealmFinalListUnmanagedItem = columnRealmFinalListUnmanagedList.get(i);\n                some.test.AllTypes cachecolumnRealmFinalList = (some.test.AllTypes) cache.get(columnRealmFinalListUnmanagedItem);\n                if (cachecolumnRealmFinalList != null) {\n                    columnRealmFinalListManagedList.add(cachecolumnRealmFinalList);\n                } else {\n                    columnRealmFinalListManagedList.add(some_test_AllTypesRealmProxy.copyOrUpdate(realm, (some_test_AllTypesRealmProxy.AllTypesColumnInfo) realm.getSchema().getColumnInfo(some.test.AllTypes.class), columnRealmFinalListUnmanagedItem, update, cache, flags));\n                }\n            }\n        }\n\n        RealmList<some.test.Simple> columnRealmFinalListNoPkUnmanagedList = unmanagedSource.realmGet$columnRealmFinalListNoPk();\n        if (columnRealmFinalListNoPkUnmanagedList != null) {\n            RealmList<some.test.Simple> columnRealmFinalListNoPkManagedList = managedCopy.realmGet$columnRealmFinalListNoPk();\n            columnRealmFinalListNoPkManagedList.clear();\n            for (int i = 0; i < columnRealmFinalListNoPkUnmanagedList.size(); i++) {\n                some.test.Simple columnRealmFinalListNoPkUnmanagedItem = columnRealmFinalListNoPkUnmanagedList.get(i);\n                some.test.Simple cachecolumnRealmFinalListNoPk = (some.test.Simple) cache.get(columnRealmFinalListNoPkUnmanagedItem);\n                if (cachecolumnRealmFinalListNoPk != null) {\n                    columnRealmFinalListNoPkManagedList.add(cachecolumnRealmFinalListNoPk);\n                } else {\n                    columnRealmFinalListNoPkManagedList.add(some_test_SimpleRealmProxy.copyOrUpdate(realm, (some_test_SimpleRealmProxy.SimpleColumnInfo) realm.getSchema().getColumnInfo(some.test.Simple.class), columnRealmFinalListNoPkUnmanagedItem, update, cache, flags));\n                }\n            }\n        }\n\n        RealmList<RealmAny> columnRealmAnyListUnmanagedList = unmanagedSource.realmGet$columnRealmAnyList();\n        if (columnRealmAnyListUnmanagedList != null) {\n            RealmList<RealmAny> columnRealmAnyListManagedList = managedCopy.realmGet$columnRealmAnyList();\n            columnRealmAnyListManagedList.clear();\n            for (int i = 0; i < columnRealmAnyListUnmanagedList.size(); i++) {\n                RealmAny realmAnyItem = columnRealmAnyListUnmanagedList.get(i);\n                realmAnyItem = ProxyUtils.copyOrUpdate(realmAnyItem, realm, update, cache, flags);\n                columnRealmAnyListManagedList.add(realmAnyItem);\n            }\n        }\n\n        RealmDictionary<some.test.AllTypes> columnRealmDictionaryUnmanagedDictionary = unmanagedSource.realmGet$columnRealmDictionary();\n        if (columnRealmDictionaryUnmanagedDictionary != null) {\n            RealmDictionary<some.test.AllTypes> columnRealmDictionaryManagedDictionary = managedCopy.realmGet$columnRealmDictionary();\n            columnRealmDictionaryManagedDictionary.clear();\n            java.util.Set<java.util.Map.Entry<String, some.test.AllTypes>> entries = columnRealmDictionaryUnmanagedDictionary.entrySet();\n            for (java.util.Map.Entry<String, some.test.AllTypes> entry : entries) {\n                String entryKey = entry.getKey();\n                some.test.AllTypes columnRealmDictionaryUnmanagedEntryValue = entry.getValue();\n                some.test.AllTypes cachecolumnRealmDictionary = (some.test.AllTypes) cache.get(columnRealmDictionaryUnmanagedEntryValue);\n                if (cachecolumnRealmDictionary != null) {\n                    columnRealmDictionaryManagedDictionary.put(entryKey, cachecolumnRealmDictionary);\n                } else {\n                    if (columnRealmDictionaryUnmanagedEntryValue == null) {\n                        columnRealmDictionaryManagedDictionary.put(entryKey, null);\n                    } else {\n                        columnRealmDictionaryManagedDictionary.put(entryKey, some_test_AllTypesRealmProxy.copyOrUpdate(realm, (some_test_AllTypesRealmProxy.AllTypesColumnInfo) realm.getSchema().getColumnInfo(some.test.AllTypes.class), columnRealmDictionaryUnmanagedEntryValue, update, cache, flags));\n                    }\n                }\n            }\n        }\n        RealmDictionary<RealmAny> columnRealmAnyDictionaryUnmanagedDictionary = unmanagedSource.realmGet$columnRealmAnyDictionary();\n        if (columnRealmAnyDictionaryUnmanagedDictionary != null) {\n            RealmDictionary<RealmAny> columnRealmAnyDictionaryManagedDictionary = managedCopy.realmGet$columnRealmAnyDictionary();\n            java.util.Set<java.util.Map.Entry<String, io.realm.RealmAny>> entries = columnRealmAnyDictionaryUnmanagedDictionary.entrySet();\n            java.util.List<String> keys = new java.util.ArrayList<>();\n            java.util.List<Long> realmAnyPointers = new java.util.ArrayList<>();\n            for (java.util.Map.Entry<String, io.realm.RealmAny> entry : entries) {\n                RealmAny realmAnyItem = entry.getValue();\n                realmAnyItem = ProxyUtils.copyOrUpdate(realmAnyItem, realm, update, cache, flags);\n                columnRealmAnyDictionaryManagedDictionary.put(entry.getKey(), realmAnyItem);\n            }\n        }\n\n        return managedCopy;\n    }\n\n    public static long insert(Realm realm, some.test.AllTypes object, Map<RealmModel,Long> cache) {\n        if (object instanceof RealmObjectProxy && !RealmObject.isFrozen(object) && ((RealmObjectProxy) object).realmGet$proxyState().getRealm$realm() != null && ((RealmObjectProxy) object).realmGet$proxyState().getRealm$realm().getPath().equals(realm.getPath())) {\n            return ((RealmObjectProxy) object).realmGet$proxyState().getRow$realm().getObjectKey();\n        }\n        Table table = realm.getTable(some.test.AllTypes.class);\n        long tableNativePtr = table.getNativePtr();\n        AllTypesColumnInfo columnInfo = (AllTypesColumnInfo) realm.getSchema().getColumnInfo(some.test.AllTypes.class);\n        long pkColumnKey = columnInfo.columnStringColKey;\n        String primaryKeyValue = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnString();\n        long objKey = Table.NO_MATCH;\n        if (primaryKeyValue == null) {\n            objKey = Table.nativeFindFirstNull(tableNativePtr, pkColumnKey);\n        } else {\n            objKey = Table.nativeFindFirstString(tableNativePtr, pkColumnKey, primaryKeyValue);\n        }\n        if (objKey == Table.NO_MATCH) {\n            objKey = OsObject.createRowWithPrimaryKey(table, pkColumnKey, primaryKeyValue);\n        } else {\n            Table.throwDuplicatePrimaryKeyException(primaryKeyValue);\n        }\n        cache.put(object, objKey);\n        Table.nativeSetLong(tableNativePtr, columnInfo.columnLongColKey, objKey, ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnLong(), false);\n        Table.nativeSetFloat(tableNativePtr, columnInfo.columnFloatColKey, objKey, ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnFloat(), false);\n        Table.nativeSetDouble(tableNativePtr, columnInfo.columnDoubleColKey, objKey, ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnDouble(), false);\n        Table.nativeSetBoolean(tableNativePtr, columnInfo.columnBooleanColKey, objKey, ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnBoolean(), false);\n        org.bson.types.Decimal128 realmGet$columnDecimal128 = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnDecimal128();\n        if (realmGet$columnDecimal128 != null) {\n            Table.nativeSetDecimal128(tableNativePtr, columnInfo.columnDecimal128ColKey, objKey, realmGet$columnDecimal128.getLow(), realmGet$columnDecimal128.getHigh(), false);\n        }\n        org.bson.types.ObjectId realmGet$columnObjectId = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnObjectId();\n        if (realmGet$columnObjectId != null) {\n            Table.nativeSetObjectId(tableNativePtr, columnInfo.columnObjectIdColKey, objKey, realmGet$columnObjectId.toString(), false);\n        }\n        java.util.UUID realmGet$columnUUID = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnUUID();\n        if (realmGet$columnUUID != null) {\n            Table.nativeSetUUID(tableNativePtr, columnInfo.columnUUIDColKey, objKey, realmGet$columnUUID.toString(), false);\n        }\n        java.util.Date realmGet$columnDate = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnDate();\n        if (realmGet$columnDate != null) {\n            Table.nativeSetTimestamp(tableNativePtr, columnInfo.columnDateColKey, objKey, realmGet$columnDate.getTime(), false);\n        }\n\n        RealmAny columnRealmAnyRealmAny = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnRealmAny();\n        columnRealmAnyRealmAny = ProxyUtils.insert(columnRealmAnyRealmAny, realm, cache);\n        Table.nativeSetRealmAny(tableNativePtr, columnInfo.columnRealmAnyColKey, objKey, columnRealmAnyRealmAny.getNativePtr(), false);\n        byte[] realmGet$columnBinary = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnBinary();\n        if (realmGet$columnBinary != null) {\n            Table.nativeSetByteArray(tableNativePtr, columnInfo.columnBinaryColKey, objKey, realmGet$columnBinary, false);\n        }\n        Long realmGet$columnMutableRealmInteger = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnMutableRealmInteger().get();\n        if (realmGet$columnMutableRealmInteger != null) {\n            Table.nativeSetLong(tableNativePtr, columnInfo.columnMutableRealmIntegerColKey, objKey, realmGet$columnMutableRealmInteger.longValue(), false);\n        }\n\n        some.test.AllTypes columnObjectObj = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnObject();\n        if (columnObjectObj != null) {\n            Long cachecolumnObject = cache.get(columnObjectObj);\n            if (cachecolumnObject == null) {\n                cachecolumnObject = some_test_AllTypesRealmProxy.insert(realm, columnObjectObj, cache);\n            }\n            Table.nativeSetLink(tableNativePtr, columnInfo.columnObjectColKey, objKey, cachecolumnObject, false);\n        }\n\n        some.test.Simple columnObjectWithoutPkObj = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnObjectWithoutPk();\n        if (columnObjectWithoutPkObj != null) {\n            Long cachecolumnObjectWithoutPk = cache.get(columnObjectWithoutPkObj);\n            if (cachecolumnObjectWithoutPk == null) {\n                cachecolumnObjectWithoutPk = some_test_SimpleRealmProxy.insert(realm, columnObjectWithoutPkObj, cache);\n            }\n            Table.nativeSetLink(tableNativePtr, columnInfo.columnObjectWithoutPkColKey, objKey, cachecolumnObjectWithoutPk, false);\n        }\n\n        RealmList<some.test.AllTypes> columnRealmListList = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnRealmList();\n        if (columnRealmListList != null) {\n            OsList columnRealmListOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.columnRealmListColKey);\n            for (some.test.AllTypes columnRealmListItem : columnRealmListList) {\n                Long cacheItemIndexcolumnRealmList = cache.get(columnRealmListItem);\n                if (cacheItemIndexcolumnRealmList == null) {\n                    cacheItemIndexcolumnRealmList = some_test_AllTypesRealmProxy.insert(realm, columnRealmListItem, cache);\n                }\n                columnRealmListOsList.addRow(cacheItemIndexcolumnRealmList);\n            }\n        }\n\n        RealmList<some.test.Simple> columnRealmListNoPkList = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnRealmListNoPk();\n        if (columnRealmListNoPkList != null) {\n            OsList columnRealmListNoPkOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.columnRealmListNoPkColKey);\n            for (some.test.Simple columnRealmListNoPkItem : columnRealmListNoPkList) {\n                Long cacheItemIndexcolumnRealmListNoPk = cache.get(columnRealmListNoPkItem);\n                if (cacheItemIndexcolumnRealmListNoPk == null) {\n                    cacheItemIndexcolumnRealmListNoPk = some_test_SimpleRealmProxy.insert(realm, columnRealmListNoPkItem, cache);\n                }\n                columnRealmListNoPkOsList.addRow(cacheItemIndexcolumnRealmListNoPk);\n            }\n        }\n\n        RealmList<some.test.AllTypes> columnRealmFinalListList = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnRealmFinalList();\n        if (columnRealmFinalListList != null) {\n            OsList columnRealmFinalListOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.columnRealmFinalListColKey);\n            for (some.test.AllTypes columnRealmFinalListItem : columnRealmFinalListList) {\n                Long cacheItemIndexcolumnRealmFinalList = cache.get(columnRealmFinalListItem);\n                if (cacheItemIndexcolumnRealmFinalList == null) {\n                    cacheItemIndexcolumnRealmFinalList = some_test_AllTypesRealmProxy.insert(realm, columnRealmFinalListItem, cache);\n                }\n                columnRealmFinalListOsList.addRow(cacheItemIndexcolumnRealmFinalList);\n            }\n        }\n\n        RealmList<some.test.Simple> columnRealmFinalListNoPkList = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnRealmFinalListNoPk();\n        if (columnRealmFinalListNoPkList != null) {\n            OsList columnRealmFinalListNoPkOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.columnRealmFinalListNoPkColKey);\n            for (some.test.Simple columnRealmFinalListNoPkItem : columnRealmFinalListNoPkList) {\n                Long cacheItemIndexcolumnRealmFinalListNoPk = cache.get(columnRealmFinalListNoPkItem);\n                if (cacheItemIndexcolumnRealmFinalListNoPk == null) {\n                    cacheItemIndexcolumnRealmFinalListNoPk = some_test_SimpleRealmProxy.insert(realm, columnRealmFinalListNoPkItem, cache);\n                }\n                columnRealmFinalListNoPkOsList.addRow(cacheItemIndexcolumnRealmFinalListNoPk);\n            }\n        }\n\n        RealmList<java.lang.String> columnStringListList = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnStringList();\n        if (columnStringListList != null) {\n            OsList columnStringListOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.columnStringListColKey);\n            for (java.lang.String columnStringListItem : columnStringListList) {\n                if (columnStringListItem == null) {\n                    columnStringListOsList.addNull();\n                } else {\n                    columnStringListOsList.addString(columnStringListItem);\n                }\n            }\n        }\n\n        RealmList<byte[]> columnBinaryListList = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnBinaryList();\n        if (columnBinaryListList != null) {\n            OsList columnBinaryListOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.columnBinaryListColKey);\n            for (byte[] columnBinaryListItem : columnBinaryListList) {\n                if (columnBinaryListItem == null) {\n                    columnBinaryListOsList.addNull();\n                } else {\n                    columnBinaryListOsList.addBinary(columnBinaryListItem);\n                }\n            }\n        }\n\n        RealmList<java.lang.Boolean> columnBooleanListList = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnBooleanList();\n        if (columnBooleanListList != null) {\n            OsList columnBooleanListOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.columnBooleanListColKey);\n            for (java.lang.Boolean columnBooleanListItem : columnBooleanListList) {\n                if (columnBooleanListItem == null) {\n                    columnBooleanListOsList.addNull();\n                } else {\n                    columnBooleanListOsList.addBoolean(columnBooleanListItem);\n                }\n            }\n        }\n\n        RealmList<java.lang.Long> columnLongListList = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnLongList();\n        if (columnLongListList != null) {\n            OsList columnLongListOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.columnLongListColKey);\n            for (java.lang.Long columnLongListItem : columnLongListList) {\n                if (columnLongListItem == null) {\n                    columnLongListOsList.addNull();\n                } else {\n                    columnLongListOsList.addLong(columnLongListItem.longValue());\n                }\n            }\n        }\n\n        RealmList<java.lang.Integer> columnIntegerListList = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnIntegerList();\n        if (columnIntegerListList != null) {\n            OsList columnIntegerListOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.columnIntegerListColKey);\n            for (java.lang.Integer columnIntegerListItem : columnIntegerListList) {\n                if (columnIntegerListItem == null) {\n                    columnIntegerListOsList.addNull();\n                } else {\n                    columnIntegerListOsList.addLong(columnIntegerListItem.longValue());\n                }\n            }\n        }\n\n        RealmList<java.lang.Short> columnShortListList = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnShortList();\n        if (columnShortListList != null) {\n            OsList columnShortListOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.columnShortListColKey);\n            for (java.lang.Short columnShortListItem : columnShortListList) {\n                if (columnShortListItem == null) {\n                    columnShortListOsList.addNull();\n                } else {\n                    columnShortListOsList.addLong(columnShortListItem.longValue());\n                }\n            }\n        }\n\n        RealmList<java.lang.Byte> columnByteListList = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnByteList();\n        if (columnByteListList != null) {\n            OsList columnByteListOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.columnByteListColKey);\n            for (java.lang.Byte columnByteListItem : columnByteListList) {\n                if (columnByteListItem == null) {\n                    columnByteListOsList.addNull();\n                } else {\n                    columnByteListOsList.addLong(columnByteListItem.longValue());\n                }\n            }\n        }\n\n        RealmList<java.lang.Double> columnDoubleListList = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnDoubleList();\n        if (columnDoubleListList != null) {\n            OsList columnDoubleListOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.columnDoubleListColKey);\n            for (java.lang.Double columnDoubleListItem : columnDoubleListList) {\n                if (columnDoubleListItem == null) {\n                    columnDoubleListOsList.addNull();\n                } else {\n                    columnDoubleListOsList.addDouble(columnDoubleListItem.doubleValue());\n                }\n            }\n        }\n\n        RealmList<java.lang.Float> columnFloatListList = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnFloatList();\n        if (columnFloatListList != null) {\n            OsList columnFloatListOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.columnFloatListColKey);\n            for (java.lang.Float columnFloatListItem : columnFloatListList) {\n                if (columnFloatListItem == null) {\n                    columnFloatListOsList.addNull();\n                } else {\n                    columnFloatListOsList.addFloat(columnFloatListItem.floatValue());\n                }\n            }\n        }\n\n        RealmList<java.util.Date> columnDateListList = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnDateList();\n        if (columnDateListList != null) {\n            OsList columnDateListOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.columnDateListColKey);\n            for (java.util.Date columnDateListItem : columnDateListList) {\n                if (columnDateListItem == null) {\n                    columnDateListOsList.addNull();\n                } else {\n                    columnDateListOsList.addDate(columnDateListItem);\n                }\n            }\n        }\n\n        RealmList<org.bson.types.Decimal128> columnDecimal128ListList = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnDecimal128List();\n        if (columnDecimal128ListList != null) {\n            OsList columnDecimal128ListOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.columnDecimal128ListColKey);\n            for (org.bson.types.Decimal128 columnDecimal128ListItem : columnDecimal128ListList) {\n                if (columnDecimal128ListItem == null) {\n                    columnDecimal128ListOsList.addNull();\n                } else {\n                    columnDecimal128ListOsList.addDecimal128(columnDecimal128ListItem);\n                }\n            }\n        }\n\n        RealmList<org.bson.types.ObjectId> columnObjectIdListList = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnObjectIdList();\n        if (columnObjectIdListList != null) {\n            OsList columnObjectIdListOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.columnObjectIdListColKey);\n            for (org.bson.types.ObjectId columnObjectIdListItem : columnObjectIdListList) {\n                if (columnObjectIdListItem == null) {\n                    columnObjectIdListOsList.addNull();\n                } else {\n                    columnObjectIdListOsList.addObjectId(columnObjectIdListItem);\n                }\n            }\n        }\n\n        RealmList<java.util.UUID> columnUUIDListList = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnUUIDList();\n        if (columnUUIDListList != null) {\n            OsList columnUUIDListOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.columnUUIDListColKey);\n            for (java.util.UUID columnUUIDListItem : columnUUIDListList) {\n                if (columnUUIDListItem == null) {\n                    columnUUIDListOsList.addNull();\n                } else {\n                    columnUUIDListOsList.addUUID(columnUUIDListItem);\n                }\n            }\n        }\n\n        RealmList<RealmAny> columnRealmAnyListUnmanagedList = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnRealmAnyList();\n        if (columnRealmAnyListUnmanagedList != null) {\n            OsList columnRealmAnyListOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.columnRealmAnyListColKey);\n            for (int i = 0; i < columnRealmAnyListUnmanagedList.size(); i++) {\n                RealmAny realmAnyItem = columnRealmAnyListUnmanagedList.get(i);\n                realmAnyItem = ProxyUtils.insert(realmAnyItem, realm, cache);\n                columnRealmAnyListOsList.addRealmAny(realmAnyItem.getNativePtr());\n            }\n        }\n        return objKey;\n    }\n\n    public static void insert(Realm realm, Iterator<? extends RealmModel> objects, Map<RealmModel,Long> cache) {\n        Table table = realm.getTable(some.test.AllTypes.class);\n        long tableNativePtr = table.getNativePtr();\n        AllTypesColumnInfo columnInfo = (AllTypesColumnInfo) realm.getSchema().getColumnInfo(some.test.AllTypes.class);\n        long pkColumnKey = columnInfo.columnStringColKey;\n        some.test.AllTypes object = null;\n        while (objects.hasNext()) {\n            object = (some.test.AllTypes) objects.next();\n            if (cache.containsKey(object)) {\n                continue;\n            }\n            if (object instanceof RealmObjectProxy && !RealmObject.isFrozen(object) && ((RealmObjectProxy) object).realmGet$proxyState().getRealm$realm() != null && ((RealmObjectProxy) object).realmGet$proxyState().getRealm$realm().getPath().equals(realm.getPath())) {\n                cache.put(object, ((RealmObjectProxy) object).realmGet$proxyState().getRow$realm().getObjectKey());\n                continue;\n            }\n            String primaryKeyValue = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnString();\n            long objKey = Table.NO_MATCH;\n            if (primaryKeyValue == null) {\n                objKey = Table.nativeFindFirstNull(tableNativePtr, pkColumnKey);\n            } else {\n                objKey = Table.nativeFindFirstString(tableNativePtr, pkColumnKey, primaryKeyValue);\n            }\n            if (objKey == Table.NO_MATCH) {\n                objKey = OsObject.createRowWithPrimaryKey(table, pkColumnKey, primaryKeyValue);\n            } else {\n                Table.throwDuplicatePrimaryKeyException(primaryKeyValue);\n            }\n            cache.put(object, objKey);\n            Table.nativeSetLong(tableNativePtr, columnInfo.columnLongColKey, objKey, ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnLong(), false);\n            Table.nativeSetFloat(tableNativePtr, columnInfo.columnFloatColKey, objKey, ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnFloat(), false);\n            Table.nativeSetDouble(tableNativePtr, columnInfo.columnDoubleColKey, objKey, ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnDouble(), false);\n            Table.nativeSetBoolean(tableNativePtr, columnInfo.columnBooleanColKey, objKey, ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnBoolean(), false);\n            org.bson.types.Decimal128 realmGet$columnDecimal128 = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnDecimal128();\n            if (realmGet$columnDecimal128 != null) {\n                Table.nativeSetDecimal128(tableNativePtr, columnInfo.columnDecimal128ColKey, objKey, realmGet$columnDecimal128.getLow(), realmGet$columnDecimal128.getHigh(), false);\n            }\n            org.bson.types.ObjectId realmGet$columnObjectId = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnObjectId();\n            if (realmGet$columnObjectId != null) {\n                Table.nativeSetObjectId(tableNativePtr, columnInfo.columnObjectIdColKey, objKey, realmGet$columnObjectId.toString(), false);\n            }\n            java.util.UUID realmGet$columnUUID = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnUUID();\n            if (realmGet$columnUUID != null) {\n                Table.nativeSetUUID(tableNativePtr, columnInfo.columnUUIDColKey, objKey, realmGet$columnUUID.toString(), false);\n            }\n            java.util.Date realmGet$columnDate = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnDate();\n            if (realmGet$columnDate != null) {\n                Table.nativeSetTimestamp(tableNativePtr, columnInfo.columnDateColKey, objKey, realmGet$columnDate.getTime(), false);\n            }\n\n            RealmAny columnRealmAnyRealmAny = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnRealmAny();\n            columnRealmAnyRealmAny = ProxyUtils.insert(columnRealmAnyRealmAny, realm, cache);\n            Table.nativeSetRealmAny(tableNativePtr, columnInfo.columnRealmAnyColKey, objKey, columnRealmAnyRealmAny.getNativePtr(), false);\n            byte[] realmGet$columnBinary = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnBinary();\n            if (realmGet$columnBinary != null) {\n                Table.nativeSetByteArray(tableNativePtr, columnInfo.columnBinaryColKey, objKey, realmGet$columnBinary, false);\n            }\n            Long realmGet$columnMutableRealmInteger = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnMutableRealmInteger().get();\n            if (realmGet$columnMutableRealmInteger != null) {\n                Table.nativeSetLong(tableNativePtr, columnInfo.columnMutableRealmIntegerColKey, objKey, realmGet$columnMutableRealmInteger.longValue(), false);\n            }\n\n            some.test.AllTypes columnObjectObj = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnObject();\n            if (columnObjectObj != null) {\n                Long cachecolumnObject = cache.get(columnObjectObj);\n                if (cachecolumnObject == null) {\n                    cachecolumnObject = some_test_AllTypesRealmProxy.insert(realm, columnObjectObj, cache);\n                }\n                table.setLink(columnInfo.columnObjectColKey, objKey, cachecolumnObject, false);\n            }\n\n            some.test.Simple columnObjectWithoutPkObj = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnObjectWithoutPk();\n            if (columnObjectWithoutPkObj != null) {\n                Long cachecolumnObjectWithoutPk = cache.get(columnObjectWithoutPkObj);\n                if (cachecolumnObjectWithoutPk == null) {\n                    cachecolumnObjectWithoutPk = some_test_SimpleRealmProxy.insert(realm, columnObjectWithoutPkObj, cache);\n                }\n                table.setLink(columnInfo.columnObjectWithoutPkColKey, objKey, cachecolumnObjectWithoutPk, false);\n            }\n\n            RealmList<some.test.AllTypes> columnRealmListList = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnRealmList();\n            if (columnRealmListList != null) {\n                OsList columnRealmListOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.columnRealmListColKey);\n                for (some.test.AllTypes columnRealmListItem : columnRealmListList) {\n                    Long cacheItemIndexcolumnRealmList = cache.get(columnRealmListItem);\n                    if (cacheItemIndexcolumnRealmList == null) {\n                        cacheItemIndexcolumnRealmList = some_test_AllTypesRealmProxy.insert(realm, columnRealmListItem, cache);\n                    }\n                    columnRealmListOsList.addRow(cacheItemIndexcolumnRealmList);\n                }\n            }\n\n            RealmList<some.test.Simple> columnRealmListNoPkList = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnRealmListNoPk();\n            if (columnRealmListNoPkList != null) {\n                OsList columnRealmListNoPkOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.columnRealmListNoPkColKey);\n                for (some.test.Simple columnRealmListNoPkItem : columnRealmListNoPkList) {\n                    Long cacheItemIndexcolumnRealmListNoPk = cache.get(columnRealmListNoPkItem);\n                    if (cacheItemIndexcolumnRealmListNoPk == null) {\n                        cacheItemIndexcolumnRealmListNoPk = some_test_SimpleRealmProxy.insert(realm, columnRealmListNoPkItem, cache);\n                    }\n                    columnRealmListNoPkOsList.addRow(cacheItemIndexcolumnRealmListNoPk);\n                }\n            }\n\n            RealmList<some.test.AllTypes> columnRealmFinalListList = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnRealmFinalList();\n            if (columnRealmFinalListList != null) {\n                OsList columnRealmFinalListOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.columnRealmFinalListColKey);\n                for (some.test.AllTypes columnRealmFinalListItem : columnRealmFinalListList) {\n                    Long cacheItemIndexcolumnRealmFinalList = cache.get(columnRealmFinalListItem);\n                    if (cacheItemIndexcolumnRealmFinalList == null) {\n                        cacheItemIndexcolumnRealmFinalList = some_test_AllTypesRealmProxy.insert(realm, columnRealmFinalListItem, cache);\n                    }\n                    columnRealmFinalListOsList.addRow(cacheItemIndexcolumnRealmFinalList);\n                }\n            }\n\n            RealmList<some.test.Simple> columnRealmFinalListNoPkList = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnRealmFinalListNoPk();\n            if (columnRealmFinalListNoPkList != null) {\n                OsList columnRealmFinalListNoPkOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.columnRealmFinalListNoPkColKey);\n                for (some.test.Simple columnRealmFinalListNoPkItem : columnRealmFinalListNoPkList) {\n                    Long cacheItemIndexcolumnRealmFinalListNoPk = cache.get(columnRealmFinalListNoPkItem);\n                    if (cacheItemIndexcolumnRealmFinalListNoPk == null) {\n                        cacheItemIndexcolumnRealmFinalListNoPk = some_test_SimpleRealmProxy.insert(realm, columnRealmFinalListNoPkItem, cache);\n                    }\n                    columnRealmFinalListNoPkOsList.addRow(cacheItemIndexcolumnRealmFinalListNoPk);\n                }\n            }\n\n            RealmList<java.lang.String> columnStringListList = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnStringList();\n            if (columnStringListList != null) {\n                OsList columnStringListOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.columnStringListColKey);\n                for (java.lang.String columnStringListItem : columnStringListList) {\n                    if (columnStringListItem == null) {\n                        columnStringListOsList.addNull();\n                    } else {\n                        columnStringListOsList.addString(columnStringListItem);\n                    }\n                }\n            }\n\n            RealmList<byte[]> columnBinaryListList = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnBinaryList();\n            if (columnBinaryListList != null) {\n                OsList columnBinaryListOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.columnBinaryListColKey);\n                for (byte[] columnBinaryListItem : columnBinaryListList) {\n                    if (columnBinaryListItem == null) {\n                        columnBinaryListOsList.addNull();\n                    } else {\n                        columnBinaryListOsList.addBinary(columnBinaryListItem);\n                    }\n                }\n            }\n\n            RealmList<java.lang.Boolean> columnBooleanListList = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnBooleanList();\n            if (columnBooleanListList != null) {\n                OsList columnBooleanListOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.columnBooleanListColKey);\n                for (java.lang.Boolean columnBooleanListItem : columnBooleanListList) {\n                    if (columnBooleanListItem == null) {\n                        columnBooleanListOsList.addNull();\n                    } else {\n                        columnBooleanListOsList.addBoolean(columnBooleanListItem);\n                    }\n                }\n            }\n\n            RealmList<java.lang.Long> columnLongListList = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnLongList();\n            if (columnLongListList != null) {\n                OsList columnLongListOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.columnLongListColKey);\n                for (java.lang.Long columnLongListItem : columnLongListList) {\n                    if (columnLongListItem == null) {\n                        columnLongListOsList.addNull();\n                    } else {\n                        columnLongListOsList.addLong(columnLongListItem.longValue());\n                    }\n                }\n            }\n\n            RealmList<java.lang.Integer> columnIntegerListList = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnIntegerList();\n            if (columnIntegerListList != null) {\n                OsList columnIntegerListOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.columnIntegerListColKey);\n                for (java.lang.Integer columnIntegerListItem : columnIntegerListList) {\n                    if (columnIntegerListItem == null) {\n                        columnIntegerListOsList.addNull();\n                    } else {\n                        columnIntegerListOsList.addLong(columnIntegerListItem.longValue());\n                    }\n                }\n            }\n\n            RealmList<java.lang.Short> columnShortListList = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnShortList();\n            if (columnShortListList != null) {\n                OsList columnShortListOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.columnShortListColKey);\n                for (java.lang.Short columnShortListItem : columnShortListList) {\n                    if (columnShortListItem == null) {\n                        columnShortListOsList.addNull();\n                    } else {\n                        columnShortListOsList.addLong(columnShortListItem.longValue());\n                    }\n                }\n            }\n\n            RealmList<java.lang.Byte> columnByteListList = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnByteList();\n            if (columnByteListList != null) {\n                OsList columnByteListOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.columnByteListColKey);\n                for (java.lang.Byte columnByteListItem : columnByteListList) {\n                    if (columnByteListItem == null) {\n                        columnByteListOsList.addNull();\n                    } else {\n                        columnByteListOsList.addLong(columnByteListItem.longValue());\n                    }\n                }\n            }\n\n            RealmList<java.lang.Double> columnDoubleListList = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnDoubleList();\n            if (columnDoubleListList != null) {\n                OsList columnDoubleListOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.columnDoubleListColKey);\n                for (java.lang.Double columnDoubleListItem : columnDoubleListList) {\n                    if (columnDoubleListItem == null) {\n                        columnDoubleListOsList.addNull();\n                    } else {\n                        columnDoubleListOsList.addDouble(columnDoubleListItem.doubleValue());\n                    }\n                }\n            }\n\n            RealmList<java.lang.Float> columnFloatListList = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnFloatList();\n            if (columnFloatListList != null) {\n                OsList columnFloatListOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.columnFloatListColKey);\n                for (java.lang.Float columnFloatListItem : columnFloatListList) {\n                    if (columnFloatListItem == null) {\n                        columnFloatListOsList.addNull();\n                    } else {\n                        columnFloatListOsList.addFloat(columnFloatListItem.floatValue());\n                    }\n                }\n            }\n\n            RealmList<java.util.Date> columnDateListList = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnDateList();\n            if (columnDateListList != null) {\n                OsList columnDateListOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.columnDateListColKey);\n                for (java.util.Date columnDateListItem : columnDateListList) {\n                    if (columnDateListItem == null) {\n                        columnDateListOsList.addNull();\n                    } else {\n                        columnDateListOsList.addDate(columnDateListItem);\n                    }\n                }\n            }\n\n            RealmList<org.bson.types.Decimal128> columnDecimal128ListList = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnDecimal128List();\n            if (columnDecimal128ListList != null) {\n                OsList columnDecimal128ListOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.columnDecimal128ListColKey);\n                for (org.bson.types.Decimal128 columnDecimal128ListItem : columnDecimal128ListList) {\n                    if (columnDecimal128ListItem == null) {\n                        columnDecimal128ListOsList.addNull();\n                    } else {\n                        columnDecimal128ListOsList.addDecimal128(columnDecimal128ListItem);\n                    }\n                }\n            }\n\n            RealmList<org.bson.types.ObjectId> columnObjectIdListList = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnObjectIdList();\n            if (columnObjectIdListList != null) {\n                OsList columnObjectIdListOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.columnObjectIdListColKey);\n                for (org.bson.types.ObjectId columnObjectIdListItem : columnObjectIdListList) {\n                    if (columnObjectIdListItem == null) {\n                        columnObjectIdListOsList.addNull();\n                    } else {\n                        columnObjectIdListOsList.addObjectId(columnObjectIdListItem);\n                    }\n                }\n            }\n\n            RealmList<java.util.UUID> columnUUIDListList = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnUUIDList();\n            if (columnUUIDListList != null) {\n                OsList columnUUIDListOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.columnUUIDListColKey);\n                for (java.util.UUID columnUUIDListItem : columnUUIDListList) {\n                    if (columnUUIDListItem == null) {\n                        columnUUIDListOsList.addNull();\n                    } else {\n                        columnUUIDListOsList.addUUID(columnUUIDListItem);\n                    }\n                }\n            }\n\n            RealmList<RealmAny> columnRealmAnyListUnmanagedList = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnRealmAnyList();\n            if (columnRealmAnyListUnmanagedList != null) {\n                OsList columnRealmAnyListOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.columnRealmAnyListColKey);\n                for (int i = 0; i < columnRealmAnyListUnmanagedList.size(); i++) {\n                    RealmAny realmAnyItem = columnRealmAnyListUnmanagedList.get(i);\n                    realmAnyItem = ProxyUtils.insert(realmAnyItem, realm, cache);\n                    columnRealmAnyListOsList.addRealmAny(realmAnyItem.getNativePtr());\n                }\n            }\n        }\n    }\n\n    public static long insertOrUpdate(Realm realm, some.test.AllTypes object, Map<RealmModel,Long> cache) {\n        if (object instanceof RealmObjectProxy && !RealmObject.isFrozen(object) && ((RealmObjectProxy) object).realmGet$proxyState().getRealm$realm() != null && ((RealmObjectProxy) object).realmGet$proxyState().getRealm$realm().getPath().equals(realm.getPath())) {\n            return ((RealmObjectProxy) object).realmGet$proxyState().getRow$realm().getObjectKey();\n        }\n        Table table = realm.getTable(some.test.AllTypes.class);\n        long tableNativePtr = table.getNativePtr();\n        AllTypesColumnInfo columnInfo = (AllTypesColumnInfo) realm.getSchema().getColumnInfo(some.test.AllTypes.class);\n        long pkColumnKey = columnInfo.columnStringColKey;\n        String primaryKeyValue = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnString();\n        long objKey = Table.NO_MATCH;\n        if (primaryKeyValue == null) {\n            objKey = Table.nativeFindFirstNull(tableNativePtr, pkColumnKey);\n        } else {\n            objKey = Table.nativeFindFirstString(tableNativePtr, pkColumnKey, primaryKeyValue);\n        }\n        if (objKey == Table.NO_MATCH) {\n            objKey = OsObject.createRowWithPrimaryKey(table, pkColumnKey, primaryKeyValue);\n        }\n        cache.put(object, objKey);\n        Table.nativeSetLong(tableNativePtr, columnInfo.columnLongColKey, objKey, ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnLong(), false);\n        Table.nativeSetFloat(tableNativePtr, columnInfo.columnFloatColKey, objKey, ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnFloat(), false);\n        Table.nativeSetDouble(tableNativePtr, columnInfo.columnDoubleColKey, objKey, ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnDouble(), false);\n        Table.nativeSetBoolean(tableNativePtr, columnInfo.columnBooleanColKey, objKey, ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnBoolean(), false);\n        org.bson.types.Decimal128 realmGet$columnDecimal128 = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnDecimal128();\n        if (realmGet$columnDecimal128 != null) {\n            Table.nativeSetDecimal128(tableNativePtr, columnInfo.columnDecimal128ColKey, objKey, realmGet$columnDecimal128.getLow(), realmGet$columnDecimal128.getHigh(), false);\n        } else {\n            Table.nativeSetNull(tableNativePtr, columnInfo.columnDecimal128ColKey, objKey, false);\n        }\n        org.bson.types.ObjectId realmGet$columnObjectId = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnObjectId();\n        if (realmGet$columnObjectId != null) {\n            Table.nativeSetObjectId(tableNativePtr, columnInfo.columnObjectIdColKey, objKey, realmGet$columnObjectId.toString(), false);\n        } else {\n            Table.nativeSetNull(tableNativePtr, columnInfo.columnObjectIdColKey, objKey, false);\n        }\n        java.util.UUID realmGet$columnUUID = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnUUID();\n        if (realmGet$columnUUID != null) {\n            Table.nativeSetUUID(tableNativePtr, columnInfo.columnUUIDColKey, objKey, realmGet$columnUUID.toString(), false);\n        } else {\n            Table.nativeSetNull(tableNativePtr, columnInfo.columnUUIDColKey, objKey, false);\n        }\n        java.util.Date realmGet$columnDate = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnDate();\n        if (realmGet$columnDate != null) {\n            Table.nativeSetTimestamp(tableNativePtr, columnInfo.columnDateColKey, objKey, realmGet$columnDate.getTime(), false);\n        } else {\n            Table.nativeSetNull(tableNativePtr, columnInfo.columnDateColKey, objKey, false);\n        }\n        RealmAny columnRealmAnyRealmAny = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnRealmAny();\n        columnRealmAnyRealmAny = ProxyUtils.insertOrUpdate(columnRealmAnyRealmAny, realm, cache);\n        Table.nativeSetRealmAny(tableNativePtr, columnInfo.columnRealmAnyColKey, objKey, columnRealmAnyRealmAny.getNativePtr(), false);\n        byte[] realmGet$columnBinary = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnBinary();\n        if (realmGet$columnBinary != null) {\n            Table.nativeSetByteArray(tableNativePtr, columnInfo.columnBinaryColKey, objKey, realmGet$columnBinary, false);\n        } else {\n            Table.nativeSetNull(tableNativePtr, columnInfo.columnBinaryColKey, objKey, false);\n        }\n        Long realmGet$columnMutableRealmInteger = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnMutableRealmInteger().get();\n        if (realmGet$columnMutableRealmInteger != null) {\n            Table.nativeSetLong(tableNativePtr, columnInfo.columnMutableRealmIntegerColKey, objKey, realmGet$columnMutableRealmInteger.longValue(), false);\n        } else {\n            Table.nativeSetNull(tableNativePtr, columnInfo.columnMutableRealmIntegerColKey, objKey, false);\n        }\n\n        some.test.AllTypes columnObjectObj = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnObject();\n        if (columnObjectObj != null) {\n            Long cachecolumnObject = cache.get(columnObjectObj);\n            if (cachecolumnObject == null) {\n                cachecolumnObject = some_test_AllTypesRealmProxy.insertOrUpdate(realm, columnObjectObj, cache);\n            }\n            Table.nativeSetLink(tableNativePtr, columnInfo.columnObjectColKey, objKey, cachecolumnObject, false);\n        } else {\n            Table.nativeNullifyLink(tableNativePtr, columnInfo.columnObjectColKey, objKey);\n        }\n\n        some.test.Simple columnObjectWithoutPkObj = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnObjectWithoutPk();\n        if (columnObjectWithoutPkObj != null) {\n            Long cachecolumnObjectWithoutPk = cache.get(columnObjectWithoutPkObj);\n            if (cachecolumnObjectWithoutPk == null) {\n                cachecolumnObjectWithoutPk = some_test_SimpleRealmProxy.insertOrUpdate(realm, columnObjectWithoutPkObj, cache);\n            }\n            Table.nativeSetLink(tableNativePtr, columnInfo.columnObjectWithoutPkColKey, objKey, cachecolumnObjectWithoutPk, false);\n        } else {\n            Table.nativeNullifyLink(tableNativePtr, columnInfo.columnObjectWithoutPkColKey, objKey);\n        }\n\n        OsList columnRealmListOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.columnRealmListColKey);\n        RealmList<some.test.AllTypes> columnRealmListList = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnRealmList();\n        if (columnRealmListList != null && columnRealmListList.size() == columnRealmListOsList.size()) {\n            // For lists of equal lengths, we need to set each element directly as clearing the receiver list can be wrong if the input and target list are the same.\n            int objects = columnRealmListList.size();\n            for (int i = 0; i < objects; i++) {\n                some.test.AllTypes columnRealmListItem = columnRealmListList.get(i);\n                Long cacheItemIndexcolumnRealmList = cache.get(columnRealmListItem);\n                if (cacheItemIndexcolumnRealmList == null) {\n                    cacheItemIndexcolumnRealmList = some_test_AllTypesRealmProxy.insertOrUpdate(realm, columnRealmListItem, cache);\n                }\n                columnRealmListOsList.setRow(i, cacheItemIndexcolumnRealmList);\n            }\n        } else {\n            columnRealmListOsList.removeAll();\n            if (columnRealmListList != null) {\n                for (some.test.AllTypes columnRealmListItem : columnRealmListList) {\n                    Long cacheItemIndexcolumnRealmList = cache.get(columnRealmListItem);\n                    if (cacheItemIndexcolumnRealmList == null) {\n                        cacheItemIndexcolumnRealmList = some_test_AllTypesRealmProxy.insertOrUpdate(realm, columnRealmListItem, cache);\n                    }\n                    columnRealmListOsList.addRow(cacheItemIndexcolumnRealmList);\n                }\n            }\n        }\n\n\n        OsList columnRealmListNoPkOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.columnRealmListNoPkColKey);\n        RealmList<some.test.Simple> columnRealmListNoPkList = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnRealmListNoPk();\n        if (columnRealmListNoPkList != null && columnRealmListNoPkList.size() == columnRealmListNoPkOsList.size()) {\n            // For lists of equal lengths, we need to set each element directly as clearing the receiver list can be wrong if the input and target list are the same.\n            int objects = columnRealmListNoPkList.size();\n            for (int i = 0; i < objects; i++) {\n                some.test.Simple columnRealmListNoPkItem = columnRealmListNoPkList.get(i);\n                Long cacheItemIndexcolumnRealmListNoPk = cache.get(columnRealmListNoPkItem);\n                if (cacheItemIndexcolumnRealmListNoPk == null) {\n                    cacheItemIndexcolumnRealmListNoPk = some_test_SimpleRealmProxy.insertOrUpdate(realm, columnRealmListNoPkItem, cache);\n                }\n                columnRealmListNoPkOsList.setRow(i, cacheItemIndexcolumnRealmListNoPk);\n            }\n        } else {\n            columnRealmListNoPkOsList.removeAll();\n            if (columnRealmListNoPkList != null) {\n                for (some.test.Simple columnRealmListNoPkItem : columnRealmListNoPkList) {\n                    Long cacheItemIndexcolumnRealmListNoPk = cache.get(columnRealmListNoPkItem);\n                    if (cacheItemIndexcolumnRealmListNoPk == null) {\n                        cacheItemIndexcolumnRealmListNoPk = some_test_SimpleRealmProxy.insertOrUpdate(realm, columnRealmListNoPkItem, cache);\n                    }\n                    columnRealmListNoPkOsList.addRow(cacheItemIndexcolumnRealmListNoPk);\n                }\n            }\n        }\n\n\n        OsList columnRealmFinalListOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.columnRealmFinalListColKey);\n        RealmList<some.test.AllTypes> columnRealmFinalListList = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnRealmFinalList();\n        if (columnRealmFinalListList != null && columnRealmFinalListList.size() == columnRealmFinalListOsList.size()) {\n            // For lists of equal lengths, we need to set each element directly as clearing the receiver list can be wrong if the input and target list are the same.\n            int objects = columnRealmFinalListList.size();\n            for (int i = 0; i < objects; i++) {\n                some.test.AllTypes columnRealmFinalListItem = columnRealmFinalListList.get(i);\n                Long cacheItemIndexcolumnRealmFinalList = cache.get(columnRealmFinalListItem);\n                if (cacheItemIndexcolumnRealmFinalList == null) {\n                    cacheItemIndexcolumnRealmFinalList = some_test_AllTypesRealmProxy.insertOrUpdate(realm, columnRealmFinalListItem, cache);\n                }\n                columnRealmFinalListOsList.setRow(i, cacheItemIndexcolumnRealmFinalList);\n            }\n        } else {\n            columnRealmFinalListOsList.removeAll();\n            if (columnRealmFinalListList != null) {\n                for (some.test.AllTypes columnRealmFinalListItem : columnRealmFinalListList) {\n                    Long cacheItemIndexcolumnRealmFinalList = cache.get(columnRealmFinalListItem);\n                    if (cacheItemIndexcolumnRealmFinalList == null) {\n                        cacheItemIndexcolumnRealmFinalList = some_test_AllTypesRealmProxy.insertOrUpdate(realm, columnRealmFinalListItem, cache);\n                    }\n                    columnRealmFinalListOsList.addRow(cacheItemIndexcolumnRealmFinalList);\n                }\n            }\n        }\n\n\n        OsList columnRealmFinalListNoPkOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.columnRealmFinalListNoPkColKey);\n        RealmList<some.test.Simple> columnRealmFinalListNoPkList = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnRealmFinalListNoPk();\n        if (columnRealmFinalListNoPkList != null && columnRealmFinalListNoPkList.size() == columnRealmFinalListNoPkOsList.size()) {\n            // For lists of equal lengths, we need to set each element directly as clearing the receiver list can be wrong if the input and target list are the same.\n            int objects = columnRealmFinalListNoPkList.size();\n            for (int i = 0; i < objects; i++) {\n                some.test.Simple columnRealmFinalListNoPkItem = columnRealmFinalListNoPkList.get(i);\n                Long cacheItemIndexcolumnRealmFinalListNoPk = cache.get(columnRealmFinalListNoPkItem);\n                if (cacheItemIndexcolumnRealmFinalListNoPk == null) {\n                    cacheItemIndexcolumnRealmFinalListNoPk = some_test_SimpleRealmProxy.insertOrUpdate(realm, columnRealmFinalListNoPkItem, cache);\n                }\n                columnRealmFinalListNoPkOsList.setRow(i, cacheItemIndexcolumnRealmFinalListNoPk);\n            }\n        } else {\n            columnRealmFinalListNoPkOsList.removeAll();\n            if (columnRealmFinalListNoPkList != null) {\n                for (some.test.Simple columnRealmFinalListNoPkItem : columnRealmFinalListNoPkList) {\n                    Long cacheItemIndexcolumnRealmFinalListNoPk = cache.get(columnRealmFinalListNoPkItem);\n                    if (cacheItemIndexcolumnRealmFinalListNoPk == null) {\n                        cacheItemIndexcolumnRealmFinalListNoPk = some_test_SimpleRealmProxy.insertOrUpdate(realm, columnRealmFinalListNoPkItem, cache);\n                    }\n                    columnRealmFinalListNoPkOsList.addRow(cacheItemIndexcolumnRealmFinalListNoPk);\n                }\n            }\n        }\n\n\n        OsList columnStringListOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.columnStringListColKey);\n        columnStringListOsList.removeAll();\n        RealmList<java.lang.String> columnStringListList = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnStringList();\n        if (columnStringListList != null) {\n            for (java.lang.String columnStringListItem : columnStringListList) {\n                if (columnStringListItem == null) {\n                    columnStringListOsList.addNull();\n                } else {\n                    columnStringListOsList.addString(columnStringListItem);\n                }\n            }\n        }\n\n\n        OsList columnBinaryListOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.columnBinaryListColKey);\n        columnBinaryListOsList.removeAll();\n        RealmList<byte[]> columnBinaryListList = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnBinaryList();\n        if (columnBinaryListList != null) {\n            for (byte[] columnBinaryListItem : columnBinaryListList) {\n                if (columnBinaryListItem == null) {\n                    columnBinaryListOsList.addNull();\n                } else {\n                    columnBinaryListOsList.addBinary(columnBinaryListItem);\n                }\n            }\n        }\n\n\n        OsList columnBooleanListOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.columnBooleanListColKey);\n        columnBooleanListOsList.removeAll();\n        RealmList<java.lang.Boolean> columnBooleanListList = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnBooleanList();\n        if (columnBooleanListList != null) {\n            for (java.lang.Boolean columnBooleanListItem : columnBooleanListList) {\n                if (columnBooleanListItem == null) {\n                    columnBooleanListOsList.addNull();\n                } else {\n                    columnBooleanListOsList.addBoolean(columnBooleanListItem);\n                }\n            }\n        }\n\n\n        OsList columnLongListOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.columnLongListColKey);\n        columnLongListOsList.removeAll();\n        RealmList<java.lang.Long> columnLongListList = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnLongList();\n        if (columnLongListList != null) {\n            for (java.lang.Long columnLongListItem : columnLongListList) {\n                if (columnLongListItem == null) {\n                    columnLongListOsList.addNull();\n                } else {\n                    columnLongListOsList.addLong(columnLongListItem.longValue());\n                }\n            }\n        }\n\n\n        OsList columnIntegerListOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.columnIntegerListColKey);\n        columnIntegerListOsList.removeAll();\n        RealmList<java.lang.Integer> columnIntegerListList = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnIntegerList();\n        if (columnIntegerListList != null) {\n            for (java.lang.Integer columnIntegerListItem : columnIntegerListList) {\n                if (columnIntegerListItem == null) {\n                    columnIntegerListOsList.addNull();\n                } else {\n                    columnIntegerListOsList.addLong(columnIntegerListItem.longValue());\n                }\n            }\n        }\n\n\n        OsList columnShortListOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.columnShortListColKey);\n        columnShortListOsList.removeAll();\n        RealmList<java.lang.Short> columnShortListList = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnShortList();\n        if (columnShortListList != null) {\n            for (java.lang.Short columnShortListItem : columnShortListList) {\n                if (columnShortListItem == null) {\n                    columnShortListOsList.addNull();\n                } else {\n                    columnShortListOsList.addLong(columnShortListItem.longValue());\n                }\n            }\n        }\n\n\n        OsList columnByteListOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.columnByteListColKey);\n        columnByteListOsList.removeAll();\n        RealmList<java.lang.Byte> columnByteListList = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnByteList();\n        if (columnByteListList != null) {\n            for (java.lang.Byte columnByteListItem : columnByteListList) {\n                if (columnByteListItem == null) {\n                    columnByteListOsList.addNull();\n                } else {\n                    columnByteListOsList.addLong(columnByteListItem.longValue());\n                }\n            }\n        }\n\n\n        OsList columnDoubleListOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.columnDoubleListColKey);\n        columnDoubleListOsList.removeAll();\n        RealmList<java.lang.Double> columnDoubleListList = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnDoubleList();\n        if (columnDoubleListList != null) {\n            for (java.lang.Double columnDoubleListItem : columnDoubleListList) {\n                if (columnDoubleListItem == null) {\n                    columnDoubleListOsList.addNull();\n                } else {\n                    columnDoubleListOsList.addDouble(columnDoubleListItem.doubleValue());\n                }\n            }\n        }\n\n\n        OsList columnFloatListOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.columnFloatListColKey);\n        columnFloatListOsList.removeAll();\n        RealmList<java.lang.Float> columnFloatListList = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnFloatList();\n        if (columnFloatListList != null) {\n            for (java.lang.Float columnFloatListItem : columnFloatListList) {\n                if (columnFloatListItem == null) {\n                    columnFloatListOsList.addNull();\n                } else {\n                    columnFloatListOsList.addFloat(columnFloatListItem.floatValue());\n                }\n            }\n        }\n\n\n        OsList columnDateListOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.columnDateListColKey);\n        columnDateListOsList.removeAll();\n        RealmList<java.util.Date> columnDateListList = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnDateList();\n        if (columnDateListList != null) {\n            for (java.util.Date columnDateListItem : columnDateListList) {\n                if (columnDateListItem == null) {\n                    columnDateListOsList.addNull();\n                } else {\n                    columnDateListOsList.addDate(columnDateListItem);\n                }\n            }\n        }\n\n\n        OsList columnDecimal128ListOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.columnDecimal128ListColKey);\n        columnDecimal128ListOsList.removeAll();\n        RealmList<org.bson.types.Decimal128> columnDecimal128ListList = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnDecimal128List();\n        if (columnDecimal128ListList != null) {\n            for (org.bson.types.Decimal128 columnDecimal128ListItem : columnDecimal128ListList) {\n                if (columnDecimal128ListItem == null) {\n                    columnDecimal128ListOsList.addNull();\n                } else {\n                    columnDecimal128ListOsList.addDecimal128(columnDecimal128ListItem);\n                }\n            }\n        }\n\n\n        OsList columnObjectIdListOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.columnObjectIdListColKey);\n        columnObjectIdListOsList.removeAll();\n        RealmList<org.bson.types.ObjectId> columnObjectIdListList = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnObjectIdList();\n        if (columnObjectIdListList != null) {\n            for (org.bson.types.ObjectId columnObjectIdListItem : columnObjectIdListList) {\n                if (columnObjectIdListItem == null) {\n                    columnObjectIdListOsList.addNull();\n                } else {\n                    columnObjectIdListOsList.addObjectId(columnObjectIdListItem);\n                }\n            }\n        }\n\n\n        OsList columnUUIDListOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.columnUUIDListColKey);\n        columnUUIDListOsList.removeAll();\n        RealmList<java.util.UUID> columnUUIDListList = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnUUIDList();\n        if (columnUUIDListList != null) {\n            for (java.util.UUID columnUUIDListItem : columnUUIDListList) {\n                if (columnUUIDListItem == null) {\n                    columnUUIDListOsList.addNull();\n                } else {\n                    columnUUIDListOsList.addUUID(columnUUIDListItem);\n                }\n            }\n        }\n\n\n        OsList columnRealmAnyListOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.columnRealmAnyListColKey);\n        RealmList<RealmAny> columnRealmAnyListList = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnRealmAnyList();\n        if (columnRealmAnyListList != null && columnRealmAnyListList.size() == columnRealmAnyListOsList.size()) {\n            // For lists of equal lengths, we need to set each element directly as clearing the receiver list can be wrong if the input and target list are the same.\n            int objects = columnRealmAnyListList.size();\n            for (int i = 0; i < objects; i++) {\n                RealmAny columnRealmAnyListItem = columnRealmAnyListList.get(i);\n                Long cacheItemIndexcolumnRealmAnyList = cache.get(columnRealmAnyListItem);\n                if (cacheItemIndexcolumnRealmAnyList == null) {\n                    columnRealmAnyListItem = ProxyUtils.insertOrUpdate(columnRealmAnyListItem, realm, cache);\n                }\n                columnRealmAnyListOsList.setRealmAny(i, columnRealmAnyListItem.getNativePtr());\n            }\n        } else {\n            columnRealmAnyListOsList.removeAll();\n            if (columnRealmAnyListList != null) {\n                for (RealmAny columnRealmAnyListItem : columnRealmAnyListList) {\n                    Long cacheItemIndexcolumnRealmAnyList = cache.get(columnRealmAnyListItem);\n                    if (cacheItemIndexcolumnRealmAnyList == null) {\n                        columnRealmAnyListItem = ProxyUtils.insertOrUpdate(columnRealmAnyListItem, realm, cache);\n                    }\n                    columnRealmAnyListOsList.addRealmAny(columnRealmAnyListItem.getNativePtr());\n                }\n            }\n        }\n        return objKey;\n    }\n\n    public static void insertOrUpdate(Realm realm, Iterator<? extends RealmModel> objects, Map<RealmModel,Long> cache) {\n        Table table = realm.getTable(some.test.AllTypes.class);\n        long tableNativePtr = table.getNativePtr();\n        AllTypesColumnInfo columnInfo = (AllTypesColumnInfo) realm.getSchema().getColumnInfo(some.test.AllTypes.class);\n        long pkColumnKey = columnInfo.columnStringColKey;\n        some.test.AllTypes object = null;\n        while (objects.hasNext()) {\n            object = (some.test.AllTypes) objects.next();\n            if (cache.containsKey(object)) {\n                continue;\n            }\n            if (object instanceof RealmObjectProxy && !RealmObject.isFrozen(object) && ((RealmObjectProxy) object).realmGet$proxyState().getRealm$realm() != null && ((RealmObjectProxy) object).realmGet$proxyState().getRealm$realm().getPath().equals(realm.getPath())) {\n                cache.put(object, ((RealmObjectProxy) object).realmGet$proxyState().getRow$realm().getObjectKey());\n                continue;\n            }\n            String primaryKeyValue = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnString();\n            long objKey = Table.NO_MATCH;\n            if (primaryKeyValue == null) {\n                objKey = Table.nativeFindFirstNull(tableNativePtr, pkColumnKey);\n            } else {\n                objKey = Table.nativeFindFirstString(tableNativePtr, pkColumnKey, primaryKeyValue);\n            }\n            if (objKey == Table.NO_MATCH) {\n                objKey = OsObject.createRowWithPrimaryKey(table, pkColumnKey, primaryKeyValue);\n            }\n            cache.put(object, objKey);\n            Table.nativeSetLong(tableNativePtr, columnInfo.columnLongColKey, objKey, ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnLong(), false);\n            Table.nativeSetFloat(tableNativePtr, columnInfo.columnFloatColKey, objKey, ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnFloat(), false);\n            Table.nativeSetDouble(tableNativePtr, columnInfo.columnDoubleColKey, objKey, ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnDouble(), false);\n            Table.nativeSetBoolean(tableNativePtr, columnInfo.columnBooleanColKey, objKey, ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnBoolean(), false);\n            org.bson.types.Decimal128 realmGet$columnDecimal128 = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnDecimal128();\n            if (realmGet$columnDecimal128 != null) {\n                Table.nativeSetDecimal128(tableNativePtr, columnInfo.columnDecimal128ColKey, objKey, realmGet$columnDecimal128.getLow(), realmGet$columnDecimal128.getHigh(), false);\n            } else {\n                Table.nativeSetNull(tableNativePtr, columnInfo.columnDecimal128ColKey, objKey, false);\n            }\n            org.bson.types.ObjectId realmGet$columnObjectId = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnObjectId();\n            if (realmGet$columnObjectId != null) {\n                Table.nativeSetObjectId(tableNativePtr, columnInfo.columnObjectIdColKey, objKey, realmGet$columnObjectId.toString(), false);\n            } else {\n                Table.nativeSetNull(tableNativePtr, columnInfo.columnObjectIdColKey, objKey, false);\n            }\n            java.util.UUID realmGet$columnUUID = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnUUID();\n            if (realmGet$columnUUID != null) {\n                Table.nativeSetUUID(tableNativePtr, columnInfo.columnUUIDColKey, objKey, realmGet$columnUUID.toString(), false);\n            } else {\n                Table.nativeSetNull(tableNativePtr, columnInfo.columnUUIDColKey, objKey, false);\n            }\n            java.util.Date realmGet$columnDate = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnDate();\n            if (realmGet$columnDate != null) {\n                Table.nativeSetTimestamp(tableNativePtr, columnInfo.columnDateColKey, objKey, realmGet$columnDate.getTime(), false);\n            } else {\n                Table.nativeSetNull(tableNativePtr, columnInfo.columnDateColKey, objKey, false);\n            }\n            RealmAny columnRealmAnyRealmAny = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnRealmAny();\n            columnRealmAnyRealmAny = ProxyUtils.insertOrUpdate(columnRealmAnyRealmAny, realm, cache);\n            Table.nativeSetRealmAny(tableNativePtr, columnInfo.columnRealmAnyColKey, objKey, columnRealmAnyRealmAny.getNativePtr(), false);\n            byte[] realmGet$columnBinary = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnBinary();\n            if (realmGet$columnBinary != null) {\n                Table.nativeSetByteArray(tableNativePtr, columnInfo.columnBinaryColKey, objKey, realmGet$columnBinary, false);\n            } else {\n                Table.nativeSetNull(tableNativePtr, columnInfo.columnBinaryColKey, objKey, false);\n            }\n            Long realmGet$columnMutableRealmInteger = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnMutableRealmInteger().get();\n            if (realmGet$columnMutableRealmInteger != null) {\n                Table.nativeSetLong(tableNativePtr, columnInfo.columnMutableRealmIntegerColKey, objKey, realmGet$columnMutableRealmInteger.longValue(), false);\n            } else {\n                Table.nativeSetNull(tableNativePtr, columnInfo.columnMutableRealmIntegerColKey, objKey, false);\n            }\n\n            some.test.AllTypes columnObjectObj = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnObject();\n            if (columnObjectObj != null) {\n                Long cachecolumnObject = cache.get(columnObjectObj);\n                if (cachecolumnObject == null) {\n                    cachecolumnObject = some_test_AllTypesRealmProxy.insertOrUpdate(realm, columnObjectObj, cache);\n                }\n                Table.nativeSetLink(tableNativePtr, columnInfo.columnObjectColKey, objKey, cachecolumnObject, false);\n            } else {\n                Table.nativeNullifyLink(tableNativePtr, columnInfo.columnObjectColKey, objKey);\n            }\n\n            some.test.Simple columnObjectWithoutPkObj = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnObjectWithoutPk();\n            if (columnObjectWithoutPkObj != null) {\n                Long cachecolumnObjectWithoutPk = cache.get(columnObjectWithoutPkObj);\n                if (cachecolumnObjectWithoutPk == null) {\n                    cachecolumnObjectWithoutPk = some_test_SimpleRealmProxy.insertOrUpdate(realm, columnObjectWithoutPkObj, cache);\n                }\n                Table.nativeSetLink(tableNativePtr, columnInfo.columnObjectWithoutPkColKey, objKey, cachecolumnObjectWithoutPk, false);\n            } else {\n                Table.nativeNullifyLink(tableNativePtr, columnInfo.columnObjectWithoutPkColKey, objKey);\n            }\n\n            OsList columnRealmListOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.columnRealmListColKey);\n            RealmList<some.test.AllTypes> columnRealmListList = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnRealmList();\n            if (columnRealmListList != null && columnRealmListList.size() == columnRealmListOsList.size()) {\n                // For lists of equal lengths, we need to set each element directly as clearing the receiver list can be wrong if the input and target list are the same.\n                int objectCount = columnRealmListList.size();\n                for (int i = 0; i < objectCount; i++) {\n                    some.test.AllTypes columnRealmListItem = columnRealmListList.get(i);\n                    Long cacheItemIndexcolumnRealmList = cache.get(columnRealmListItem);\n                    if (cacheItemIndexcolumnRealmList == null) {\n                        cacheItemIndexcolumnRealmList = some_test_AllTypesRealmProxy.insertOrUpdate(realm, columnRealmListItem, cache);\n                    }\n                    columnRealmListOsList.setRow(i, cacheItemIndexcolumnRealmList);\n                }\n            } else {\n                columnRealmListOsList.removeAll();\n                if (columnRealmListList != null) {\n                    for (some.test.AllTypes columnRealmListItem : columnRealmListList) {\n                        Long cacheItemIndexcolumnRealmList = cache.get(columnRealmListItem);\n                        if (cacheItemIndexcolumnRealmList == null) {\n                            cacheItemIndexcolumnRealmList = some_test_AllTypesRealmProxy.insertOrUpdate(realm, columnRealmListItem, cache);\n                        }\n                        columnRealmListOsList.addRow(cacheItemIndexcolumnRealmList);\n                    }\n                }\n            }\n\n\n            OsList columnRealmListNoPkOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.columnRealmListNoPkColKey);\n            RealmList<some.test.Simple> columnRealmListNoPkList = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnRealmListNoPk();\n            if (columnRealmListNoPkList != null && columnRealmListNoPkList.size() == columnRealmListNoPkOsList.size()) {\n                // For lists of equal lengths, we need to set each element directly as clearing the receiver list can be wrong if the input and target list are the same.\n                int objectCount = columnRealmListNoPkList.size();\n                for (int i = 0; i < objectCount; i++) {\n                    some.test.Simple columnRealmListNoPkItem = columnRealmListNoPkList.get(i);\n                    Long cacheItemIndexcolumnRealmListNoPk = cache.get(columnRealmListNoPkItem);\n                    if (cacheItemIndexcolumnRealmListNoPk == null) {\n                        cacheItemIndexcolumnRealmListNoPk = some_test_SimpleRealmProxy.insertOrUpdate(realm, columnRealmListNoPkItem, cache);\n                    }\n                    columnRealmListNoPkOsList.setRow(i, cacheItemIndexcolumnRealmListNoPk);\n                }\n            } else {\n                columnRealmListNoPkOsList.removeAll();\n                if (columnRealmListNoPkList != null) {\n                    for (some.test.Simple columnRealmListNoPkItem : columnRealmListNoPkList) {\n                        Long cacheItemIndexcolumnRealmListNoPk = cache.get(columnRealmListNoPkItem);\n                        if (cacheItemIndexcolumnRealmListNoPk == null) {\n                            cacheItemIndexcolumnRealmListNoPk = some_test_SimpleRealmProxy.insertOrUpdate(realm, columnRealmListNoPkItem, cache);\n                        }\n                        columnRealmListNoPkOsList.addRow(cacheItemIndexcolumnRealmListNoPk);\n                    }\n                }\n            }\n\n\n            OsList columnRealmFinalListOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.columnRealmFinalListColKey);\n            RealmList<some.test.AllTypes> columnRealmFinalListList = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnRealmFinalList();\n            if (columnRealmFinalListList != null && columnRealmFinalListList.size() == columnRealmFinalListOsList.size()) {\n                // For lists of equal lengths, we need to set each element directly as clearing the receiver list can be wrong if the input and target list are the same.\n                int objectCount = columnRealmFinalListList.size();\n                for (int i = 0; i < objectCount; i++) {\n                    some.test.AllTypes columnRealmFinalListItem = columnRealmFinalListList.get(i);\n                    Long cacheItemIndexcolumnRealmFinalList = cache.get(columnRealmFinalListItem);\n                    if (cacheItemIndexcolumnRealmFinalList == null) {\n                        cacheItemIndexcolumnRealmFinalList = some_test_AllTypesRealmProxy.insertOrUpdate(realm, columnRealmFinalListItem, cache);\n                    }\n                    columnRealmFinalListOsList.setRow(i, cacheItemIndexcolumnRealmFinalList);\n                }\n            } else {\n                columnRealmFinalListOsList.removeAll();\n                if (columnRealmFinalListList != null) {\n                    for (some.test.AllTypes columnRealmFinalListItem : columnRealmFinalListList) {\n                        Long cacheItemIndexcolumnRealmFinalList = cache.get(columnRealmFinalListItem);\n                        if (cacheItemIndexcolumnRealmFinalList == null) {\n                            cacheItemIndexcolumnRealmFinalList = some_test_AllTypesRealmProxy.insertOrUpdate(realm, columnRealmFinalListItem, cache);\n                        }\n                        columnRealmFinalListOsList.addRow(cacheItemIndexcolumnRealmFinalList);\n                    }\n                }\n            }\n\n\n            OsList columnRealmFinalListNoPkOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.columnRealmFinalListNoPkColKey);\n            RealmList<some.test.Simple> columnRealmFinalListNoPkList = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnRealmFinalListNoPk();\n            if (columnRealmFinalListNoPkList != null && columnRealmFinalListNoPkList.size() == columnRealmFinalListNoPkOsList.size()) {\n                // For lists of equal lengths, we need to set each element directly as clearing the receiver list can be wrong if the input and target list are the same.\n                int objectCount = columnRealmFinalListNoPkList.size();\n                for (int i = 0; i < objectCount; i++) {\n                    some.test.Simple columnRealmFinalListNoPkItem = columnRealmFinalListNoPkList.get(i);\n                    Long cacheItemIndexcolumnRealmFinalListNoPk = cache.get(columnRealmFinalListNoPkItem);\n                    if (cacheItemIndexcolumnRealmFinalListNoPk == null) {\n                        cacheItemIndexcolumnRealmFinalListNoPk = some_test_SimpleRealmProxy.insertOrUpdate(realm, columnRealmFinalListNoPkItem, cache);\n                    }\n                    columnRealmFinalListNoPkOsList.setRow(i, cacheItemIndexcolumnRealmFinalListNoPk);\n                }\n            } else {\n                columnRealmFinalListNoPkOsList.removeAll();\n                if (columnRealmFinalListNoPkList != null) {\n                    for (some.test.Simple columnRealmFinalListNoPkItem : columnRealmFinalListNoPkList) {\n                        Long cacheItemIndexcolumnRealmFinalListNoPk = cache.get(columnRealmFinalListNoPkItem);\n                        if (cacheItemIndexcolumnRealmFinalListNoPk == null) {\n                            cacheItemIndexcolumnRealmFinalListNoPk = some_test_SimpleRealmProxy.insertOrUpdate(realm, columnRealmFinalListNoPkItem, cache);\n                        }\n                        columnRealmFinalListNoPkOsList.addRow(cacheItemIndexcolumnRealmFinalListNoPk);\n                    }\n                }\n            }\n\n\n            OsList columnStringListOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.columnStringListColKey);\n            columnStringListOsList.removeAll();\n            RealmList<java.lang.String> columnStringListList = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnStringList();\n            if (columnStringListList != null) {\n                for (java.lang.String columnStringListItem : columnStringListList) {\n                    if (columnStringListItem == null) {\n                        columnStringListOsList.addNull();\n                    } else {\n                        columnStringListOsList.addString(columnStringListItem);\n                    }\n                }\n            }\n\n\n            OsList columnBinaryListOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.columnBinaryListColKey);\n            columnBinaryListOsList.removeAll();\n            RealmList<byte[]> columnBinaryListList = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnBinaryList();\n            if (columnBinaryListList != null) {\n                for (byte[] columnBinaryListItem : columnBinaryListList) {\n                    if (columnBinaryListItem == null) {\n                        columnBinaryListOsList.addNull();\n                    } else {\n                        columnBinaryListOsList.addBinary(columnBinaryListItem);\n                    }\n                }\n            }\n\n\n            OsList columnBooleanListOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.columnBooleanListColKey);\n            columnBooleanListOsList.removeAll();\n            RealmList<java.lang.Boolean> columnBooleanListList = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnBooleanList();\n            if (columnBooleanListList != null) {\n                for (java.lang.Boolean columnBooleanListItem : columnBooleanListList) {\n                    if (columnBooleanListItem == null) {\n                        columnBooleanListOsList.addNull();\n                    } else {\n                        columnBooleanListOsList.addBoolean(columnBooleanListItem);\n                    }\n                }\n            }\n\n\n            OsList columnLongListOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.columnLongListColKey);\n            columnLongListOsList.removeAll();\n            RealmList<java.lang.Long> columnLongListList = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnLongList();\n            if (columnLongListList != null) {\n                for (java.lang.Long columnLongListItem : columnLongListList) {\n                    if (columnLongListItem == null) {\n                        columnLongListOsList.addNull();\n                    } else {\n                        columnLongListOsList.addLong(columnLongListItem.longValue());\n                    }\n                }\n            }\n\n\n            OsList columnIntegerListOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.columnIntegerListColKey);\n            columnIntegerListOsList.removeAll();\n            RealmList<java.lang.Integer> columnIntegerListList = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnIntegerList();\n            if (columnIntegerListList != null) {\n                for (java.lang.Integer columnIntegerListItem : columnIntegerListList) {\n                    if (columnIntegerListItem == null) {\n                        columnIntegerListOsList.addNull();\n                    } else {\n                        columnIntegerListOsList.addLong(columnIntegerListItem.longValue());\n                    }\n                }\n            }\n\n\n            OsList columnShortListOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.columnShortListColKey);\n            columnShortListOsList.removeAll();\n            RealmList<java.lang.Short> columnShortListList = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnShortList();\n            if (columnShortListList != null) {\n                for (java.lang.Short columnShortListItem : columnShortListList) {\n                    if (columnShortListItem == null) {\n                        columnShortListOsList.addNull();\n                    } else {\n                        columnShortListOsList.addLong(columnShortListItem.longValue());\n                    }\n                }\n            }\n\n\n            OsList columnByteListOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.columnByteListColKey);\n            columnByteListOsList.removeAll();\n            RealmList<java.lang.Byte> columnByteListList = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnByteList();\n            if (columnByteListList != null) {\n                for (java.lang.Byte columnByteListItem : columnByteListList) {\n                    if (columnByteListItem == null) {\n                        columnByteListOsList.addNull();\n                    } else {\n                        columnByteListOsList.addLong(columnByteListItem.longValue());\n                    }\n                }\n            }\n\n\n            OsList columnDoubleListOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.columnDoubleListColKey);\n            columnDoubleListOsList.removeAll();\n            RealmList<java.lang.Double> columnDoubleListList = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnDoubleList();\n            if (columnDoubleListList != null) {\n                for (java.lang.Double columnDoubleListItem : columnDoubleListList) {\n                    if (columnDoubleListItem == null) {\n                        columnDoubleListOsList.addNull();\n                    } else {\n                        columnDoubleListOsList.addDouble(columnDoubleListItem.doubleValue());\n                    }\n                }\n            }\n\n\n            OsList columnFloatListOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.columnFloatListColKey);\n            columnFloatListOsList.removeAll();\n            RealmList<java.lang.Float> columnFloatListList = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnFloatList();\n            if (columnFloatListList != null) {\n                for (java.lang.Float columnFloatListItem : columnFloatListList) {\n                    if (columnFloatListItem == null) {\n                        columnFloatListOsList.addNull();\n                    } else {\n                        columnFloatListOsList.addFloat(columnFloatListItem.floatValue());\n                    }\n                }\n            }\n\n\n            OsList columnDateListOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.columnDateListColKey);\n            columnDateListOsList.removeAll();\n            RealmList<java.util.Date> columnDateListList = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnDateList();\n            if (columnDateListList != null) {\n                for (java.util.Date columnDateListItem : columnDateListList) {\n                    if (columnDateListItem == null) {\n                        columnDateListOsList.addNull();\n                    } else {\n                        columnDateListOsList.addDate(columnDateListItem);\n                    }\n                }\n            }\n\n\n            OsList columnDecimal128ListOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.columnDecimal128ListColKey);\n            columnDecimal128ListOsList.removeAll();\n            RealmList<org.bson.types.Decimal128> columnDecimal128ListList = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnDecimal128List();\n            if (columnDecimal128ListList != null) {\n                for (org.bson.types.Decimal128 columnDecimal128ListItem : columnDecimal128ListList) {\n                    if (columnDecimal128ListItem == null) {\n                        columnDecimal128ListOsList.addNull();\n                    } else {\n                        columnDecimal128ListOsList.addDecimal128(columnDecimal128ListItem);\n                    }\n                }\n            }\n\n\n            OsList columnObjectIdListOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.columnObjectIdListColKey);\n            columnObjectIdListOsList.removeAll();\n            RealmList<org.bson.types.ObjectId> columnObjectIdListList = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnObjectIdList();\n            if (columnObjectIdListList != null) {\n                for (org.bson.types.ObjectId columnObjectIdListItem : columnObjectIdListList) {\n                    if (columnObjectIdListItem == null) {\n                        columnObjectIdListOsList.addNull();\n                    } else {\n                        columnObjectIdListOsList.addObjectId(columnObjectIdListItem);\n                    }\n                }\n            }\n\n\n            OsList columnUUIDListOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.columnUUIDListColKey);\n            columnUUIDListOsList.removeAll();\n            RealmList<java.util.UUID> columnUUIDListList = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnUUIDList();\n            if (columnUUIDListList != null) {\n                for (java.util.UUID columnUUIDListItem : columnUUIDListList) {\n                    if (columnUUIDListItem == null) {\n                        columnUUIDListOsList.addNull();\n                    } else {\n                        columnUUIDListOsList.addUUID(columnUUIDListItem);\n                    }\n                }\n            }\n\n\n            OsList columnRealmAnyListOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.columnRealmAnyListColKey);\n            RealmList<RealmAny> columnRealmAnyListList = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnRealmAnyList();\n            if (columnRealmAnyListList != null && columnRealmAnyListList.size() == columnRealmAnyListOsList.size()) {\n                // For lists of equal lengths, we need to set each element directly as clearing the receiver list can be wrong if the input and target list are the same.\n                int objectCount = columnRealmAnyListList.size();\n                for (int i = 0; i < objectCount; i++) {\n                    RealmAny columnRealmAnyListItem = columnRealmAnyListList.get(i);\n                    Long cacheItemIndexcolumnRealmAnyList = cache.get(columnRealmAnyListItem);\n                    if (cacheItemIndexcolumnRealmAnyList == null) {\n                        columnRealmAnyListItem = ProxyUtils.insertOrUpdate(columnRealmAnyListItem, realm, cache);\n                    }\n                    columnRealmAnyListOsList.setRealmAny(i, columnRealmAnyListItem.getNativePtr());\n                }\n            } else {\n                columnRealmAnyListOsList.removeAll();\n                if (columnRealmAnyListList != null) {\n                    for (RealmAny columnRealmAnyListItem : columnRealmAnyListList) {\n                        Long cacheItemIndexcolumnRealmAnyList = cache.get(columnRealmAnyListItem);\n                        if (cacheItemIndexcolumnRealmAnyList == null) {\n                            columnRealmAnyListItem = ProxyUtils.insertOrUpdate(columnRealmAnyListItem, realm, cache);\n                        }\n                        columnRealmAnyListOsList.addRealmAny(columnRealmAnyListItem.getNativePtr());\n                    }\n                }\n            }\n        }\n    }\n\n    public static some.test.AllTypes createDetachedCopy(some.test.AllTypes realmObject, int currentDepth, int maxDepth, Map<RealmModel, CacheData<RealmModel>> cache) {\n        if (currentDepth > maxDepth || realmObject == null) {\n            return null;\n        }\n        CacheData<RealmModel> cachedObject = cache.get(realmObject);\n        some.test.AllTypes unmanagedObject;\n        if (cachedObject == null) {\n            unmanagedObject = new some.test.AllTypes();\n            cache.put(realmObject, new RealmObjectProxy.CacheData<RealmModel>(currentDepth, unmanagedObject));\n        } else {\n            // Reuse cached object or recreate it because it was encountered at a lower depth.\n            if (currentDepth >= cachedObject.minDepth) {\n                return (some.test.AllTypes) cachedObject.object;\n            }\n            unmanagedObject = (some.test.AllTypes) cachedObject.object;\n            cachedObject.minDepth = currentDepth;\n        }\n        some_test_AllTypesRealmProxyInterface unmanagedCopy = (some_test_AllTypesRealmProxyInterface) unmanagedObject;\n        some_test_AllTypesRealmProxyInterface realmSource = (some_test_AllTypesRealmProxyInterface) realmObject;\n        Realm objectRealm = (Realm) ((RealmObjectProxy) realmObject).realmGet$proxyState().getRealm$realm();\n        unmanagedCopy.realmSet$columnString(realmSource.realmGet$columnString());\n        unmanagedCopy.realmSet$columnLong(realmSource.realmGet$columnLong());\n        unmanagedCopy.realmSet$columnFloat(realmSource.realmGet$columnFloat());\n        unmanagedCopy.realmSet$columnDouble(realmSource.realmGet$columnDouble());\n        unmanagedCopy.realmSet$columnBoolean(realmSource.realmGet$columnBoolean());\n        unmanagedCopy.realmSet$columnDecimal128(realmSource.realmGet$columnDecimal128());\n        unmanagedCopy.realmSet$columnObjectId(realmSource.realmGet$columnObjectId());\n        unmanagedCopy.realmSet$columnUUID(realmSource.realmGet$columnUUID());\n        unmanagedCopy.realmSet$columnDate(realmSource.realmGet$columnDate());\n\n        // Deep copy of columnRealmAny\n        unmanagedCopy.realmSet$columnRealmAny(ProxyUtils.createDetachedCopy(realmSource.realmGet$columnRealmAny(), objectRealm, currentDepth + 1, maxDepth, cache));\n        unmanagedCopy.realmSet$columnBinary(realmSource.realmGet$columnBinary());\n        unmanagedCopy.realmGet$columnMutableRealmInteger().set(realmSource.realmGet$columnMutableRealmInteger().get());\n\n        // Deep copy of columnObject\n        unmanagedCopy.realmSet$columnObject(some_test_AllTypesRealmProxy.createDetachedCopy(realmSource.realmGet$columnObject(), currentDepth + 1, maxDepth, cache));\n\n        // Deep copy of columnObjectWithoutPk\n        unmanagedCopy.realmSet$columnObjectWithoutPk(some_test_SimpleRealmProxy.createDetachedCopy(realmSource.realmGet$columnObjectWithoutPk(), currentDepth + 1, maxDepth, cache));\n\n        // Deep copy of columnRealmList\n        if (currentDepth == maxDepth) {\n            unmanagedCopy.realmSet$columnRealmList(null);\n        } else {\n            RealmList<some.test.AllTypes> managedcolumnRealmListList = realmSource.realmGet$columnRealmList();\n            RealmList<some.test.AllTypes> unmanagedcolumnRealmListList = new RealmList<some.test.AllTypes>();\n            unmanagedCopy.realmSet$columnRealmList(unmanagedcolumnRealmListList);\n            int nextDepth = currentDepth + 1;\n            int size = managedcolumnRealmListList.size();\n            for (int i = 0; i < size; i++) {\n                some.test.AllTypes item = some_test_AllTypesRealmProxy.createDetachedCopy(managedcolumnRealmListList.get(i), nextDepth, maxDepth, cache);\n                unmanagedcolumnRealmListList.add(item);\n            }\n        }\n\n        // Deep copy of columnRealmListNoPk\n        if (currentDepth == maxDepth) {\n            unmanagedCopy.realmSet$columnRealmListNoPk(null);\n        } else {\n            RealmList<some.test.Simple> managedcolumnRealmListNoPkList = realmSource.realmGet$columnRealmListNoPk();\n            RealmList<some.test.Simple> unmanagedcolumnRealmListNoPkList = new RealmList<some.test.Simple>();\n            unmanagedCopy.realmSet$columnRealmListNoPk(unmanagedcolumnRealmListNoPkList);\n            int nextDepth = currentDepth + 1;\n            int size = managedcolumnRealmListNoPkList.size();\n            for (int i = 0; i < size; i++) {\n                some.test.Simple item = some_test_SimpleRealmProxy.createDetachedCopy(managedcolumnRealmListNoPkList.get(i), nextDepth, maxDepth, cache);\n                unmanagedcolumnRealmListNoPkList.add(item);\n            }\n        }\n\n        // Deep copy of columnRealmFinalList\n        if (currentDepth == maxDepth) {\n            unmanagedCopy.realmSet$columnRealmFinalList(null);\n        } else {\n            RealmList<some.test.AllTypes> managedcolumnRealmFinalListList = realmSource.realmGet$columnRealmFinalList();\n            RealmList<some.test.AllTypes> unmanagedcolumnRealmFinalListList = new RealmList<some.test.AllTypes>();\n            unmanagedCopy.realmSet$columnRealmFinalList(unmanagedcolumnRealmFinalListList);\n            int nextDepth = currentDepth + 1;\n            int size = managedcolumnRealmFinalListList.size();\n            for (int i = 0; i < size; i++) {\n                some.test.AllTypes item = some_test_AllTypesRealmProxy.createDetachedCopy(managedcolumnRealmFinalListList.get(i), nextDepth, maxDepth, cache);\n                unmanagedcolumnRealmFinalListList.add(item);\n            }\n        }\n\n        // Deep copy of columnRealmFinalListNoPk\n        if (currentDepth == maxDepth) {\n            unmanagedCopy.realmSet$columnRealmFinalListNoPk(null);\n        } else {\n            RealmList<some.test.Simple> managedcolumnRealmFinalListNoPkList = realmSource.realmGet$columnRealmFinalListNoPk();\n            RealmList<some.test.Simple> unmanagedcolumnRealmFinalListNoPkList = new RealmList<some.test.Simple>();\n            unmanagedCopy.realmSet$columnRealmFinalListNoPk(unmanagedcolumnRealmFinalListNoPkList);\n            int nextDepth = currentDepth + 1;\n            int size = managedcolumnRealmFinalListNoPkList.size();\n            for (int i = 0; i < size; i++) {\n                some.test.Simple item = some_test_SimpleRealmProxy.createDetachedCopy(managedcolumnRealmFinalListNoPkList.get(i), nextDepth, maxDepth, cache);\n                unmanagedcolumnRealmFinalListNoPkList.add(item);\n            }\n        }\n\n        unmanagedCopy.realmSet$columnStringList(new RealmList<java.lang.String>());\n        unmanagedCopy.realmGet$columnStringList().addAll(realmSource.realmGet$columnStringList());\n\n        unmanagedCopy.realmSet$columnBinaryList(new RealmList<byte[]>());\n        unmanagedCopy.realmGet$columnBinaryList().addAll(realmSource.realmGet$columnBinaryList());\n\n        unmanagedCopy.realmSet$columnBooleanList(new RealmList<java.lang.Boolean>());\n        unmanagedCopy.realmGet$columnBooleanList().addAll(realmSource.realmGet$columnBooleanList());\n\n        unmanagedCopy.realmSet$columnLongList(new RealmList<java.lang.Long>());\n        unmanagedCopy.realmGet$columnLongList().addAll(realmSource.realmGet$columnLongList());\n\n        unmanagedCopy.realmSet$columnIntegerList(new RealmList<java.lang.Integer>());\n        unmanagedCopy.realmGet$columnIntegerList().addAll(realmSource.realmGet$columnIntegerList());\n\n        unmanagedCopy.realmSet$columnShortList(new RealmList<java.lang.Short>());\n        unmanagedCopy.realmGet$columnShortList().addAll(realmSource.realmGet$columnShortList());\n\n        unmanagedCopy.realmSet$columnByteList(new RealmList<java.lang.Byte>());\n        unmanagedCopy.realmGet$columnByteList().addAll(realmSource.realmGet$columnByteList());\n\n        unmanagedCopy.realmSet$columnDoubleList(new RealmList<java.lang.Double>());\n        unmanagedCopy.realmGet$columnDoubleList().addAll(realmSource.realmGet$columnDoubleList());\n\n        unmanagedCopy.realmSet$columnFloatList(new RealmList<java.lang.Float>());\n        unmanagedCopy.realmGet$columnFloatList().addAll(realmSource.realmGet$columnFloatList());\n\n        unmanagedCopy.realmSet$columnDateList(new RealmList<java.util.Date>());\n        unmanagedCopy.realmGet$columnDateList().addAll(realmSource.realmGet$columnDateList());\n\n        unmanagedCopy.realmSet$columnDecimal128List(new RealmList<org.bson.types.Decimal128>());\n        unmanagedCopy.realmGet$columnDecimal128List().addAll(realmSource.realmGet$columnDecimal128List());\n\n        unmanagedCopy.realmSet$columnObjectIdList(new RealmList<org.bson.types.ObjectId>());\n        unmanagedCopy.realmGet$columnObjectIdList().addAll(realmSource.realmGet$columnObjectIdList());\n\n        unmanagedCopy.realmSet$columnUUIDList(new RealmList<java.util.UUID>());\n        unmanagedCopy.realmGet$columnUUIDList().addAll(realmSource.realmGet$columnUUIDList());\n\n        // Deep copy of columnRealmAnyList\n        if (currentDepth == maxDepth) {\n            unmanagedCopy.realmSet$columnRealmAnyList(null);\n        } else {\n            RealmList<RealmAny> managedcolumnRealmAnyListList = realmSource.realmGet$columnRealmAnyList();\n            RealmList<RealmAny> unmanagedcolumnRealmAnyListList = new RealmList<RealmAny>();\n            unmanagedCopy.realmSet$columnRealmAnyList(unmanagedcolumnRealmAnyListList);\n            int nextDepth = currentDepth + 1;\n            int size = managedcolumnRealmAnyListList.size();\n            for (int i = 0; i < size; i++) {\n                RealmAny item = ProxyUtils.createDetachedCopy(managedcolumnRealmAnyListList.get(i), objectRealm, nextDepth, maxDepth, cache);\n                unmanagedcolumnRealmAnyListList.add(item);\n            }\n        }\n\n        // Deep copy of columnRealmDictionary\n        if (currentDepth == maxDepth) {\n            unmanagedCopy.realmSet$columnRealmDictionary(null);\n        } else {\n            RealmDictionary<some.test.AllTypes> managedcolumnRealmDictionaryDictionary = realmSource.realmGet$columnRealmDictionary();\n            RealmDictionary<some.test.AllTypes> unmanagedcolumnRealmDictionaryDictionary = new RealmDictionary<some.test.AllTypes>();\n            unmanagedCopy.realmSet$columnRealmDictionary(unmanagedcolumnRealmDictionaryDictionary);\n            int nextDepth = currentDepth + 1;\n            for (Map.Entry<String, some.test.AllTypes> entry : managedcolumnRealmDictionaryDictionary.entrySet()) {\n                some.test.AllTypes detachedValue = some_test_AllTypesRealmProxy.createDetachedCopy(entry.getValue(), nextDepth, maxDepth, cache);\n                unmanagedcolumnRealmDictionaryDictionary.put(entry.getKey(), detachedValue);\n            }\n        }\n\n        unmanagedCopy.realmSet$columnBooleanDictionary(new RealmDictionary<java.lang.Boolean>());\n        RealmDictionary<java.lang.Boolean> managedcolumnBooleanDictionaryDictionary = realmSource.realmGet$columnBooleanDictionary();\n        for (Map.Entry<String, java.lang.Boolean> entry : managedcolumnBooleanDictionaryDictionary.entrySet()) {\n            unmanagedCopy.realmGet$columnBooleanDictionary().put(entry.getKey(), entry.getValue());\n        }\n\n        unmanagedCopy.realmSet$columnStringDictionary(new RealmDictionary<java.lang.String>());\n        RealmDictionary<java.lang.String> managedcolumnStringDictionaryDictionary = realmSource.realmGet$columnStringDictionary();\n        for (Map.Entry<String, java.lang.String> entry : managedcolumnStringDictionaryDictionary.entrySet()) {\n            unmanagedCopy.realmGet$columnStringDictionary().put(entry.getKey(), entry.getValue());\n        }\n\n        unmanagedCopy.realmSet$columnIntegerDictionary(new RealmDictionary<java.lang.Integer>());\n        RealmDictionary<java.lang.Integer> managedcolumnIntegerDictionaryDictionary = realmSource.realmGet$columnIntegerDictionary();\n        for (Map.Entry<String, java.lang.Integer> entry : managedcolumnIntegerDictionaryDictionary.entrySet()) {\n            unmanagedCopy.realmGet$columnIntegerDictionary().put(entry.getKey(), entry.getValue());\n        }\n\n        unmanagedCopy.realmSet$columnFloatDictionary(new RealmDictionary<java.lang.Float>());\n        RealmDictionary<java.lang.Float> managedcolumnFloatDictionaryDictionary = realmSource.realmGet$columnFloatDictionary();\n        for (Map.Entry<String, java.lang.Float> entry : managedcolumnFloatDictionaryDictionary.entrySet()) {\n            unmanagedCopy.realmGet$columnFloatDictionary().put(entry.getKey(), entry.getValue());\n        }\n\n        unmanagedCopy.realmSet$columnLongDictionary(new RealmDictionary<java.lang.Long>());\n        RealmDictionary<java.lang.Long> managedcolumnLongDictionaryDictionary = realmSource.realmGet$columnLongDictionary();\n        for (Map.Entry<String, java.lang.Long> entry : managedcolumnLongDictionaryDictionary.entrySet()) {\n            unmanagedCopy.realmGet$columnLongDictionary().put(entry.getKey(), entry.getValue());\n        }\n\n        unmanagedCopy.realmSet$columnShortDictionary(new RealmDictionary<java.lang.Short>());\n        RealmDictionary<java.lang.Short> managedcolumnShortDictionaryDictionary = realmSource.realmGet$columnShortDictionary();\n        for (Map.Entry<String, java.lang.Short> entry : managedcolumnShortDictionaryDictionary.entrySet()) {\n            unmanagedCopy.realmGet$columnShortDictionary().put(entry.getKey(), entry.getValue());\n        }\n\n        unmanagedCopy.realmSet$columnDoubleDictionary(new RealmDictionary<java.lang.Double>());\n        RealmDictionary<java.lang.Double> managedcolumnDoubleDictionaryDictionary = realmSource.realmGet$columnDoubleDictionary();\n        for (Map.Entry<String, java.lang.Double> entry : managedcolumnDoubleDictionaryDictionary.entrySet()) {\n            unmanagedCopy.realmGet$columnDoubleDictionary().put(entry.getKey(), entry.getValue());\n        }\n\n        unmanagedCopy.realmSet$columnByteDictionary(new RealmDictionary<java.lang.Byte>());\n        RealmDictionary<java.lang.Byte> managedcolumnByteDictionaryDictionary = realmSource.realmGet$columnByteDictionary();\n        for (Map.Entry<String, java.lang.Byte> entry : managedcolumnByteDictionaryDictionary.entrySet()) {\n            unmanagedCopy.realmGet$columnByteDictionary().put(entry.getKey(), entry.getValue());\n        }\n\n        unmanagedCopy.realmSet$columnBinaryDictionary(new RealmDictionary<byte[]>());\n        RealmDictionary<byte[]> managedcolumnBinaryDictionaryDictionary = realmSource.realmGet$columnBinaryDictionary();\n        for (Map.Entry<String, byte[]> entry : managedcolumnBinaryDictionaryDictionary.entrySet()) {\n            unmanagedCopy.realmGet$columnBinaryDictionary().put(entry.getKey(), entry.getValue());\n        }\n\n        unmanagedCopy.realmSet$columnDateDictionary(new RealmDictionary<java.util.Date>());\n        RealmDictionary<java.util.Date> managedcolumnDateDictionaryDictionary = realmSource.realmGet$columnDateDictionary();\n        for (Map.Entry<String, java.util.Date> entry : managedcolumnDateDictionaryDictionary.entrySet()) {\n            unmanagedCopy.realmGet$columnDateDictionary().put(entry.getKey(), entry.getValue());\n        }\n\n        unmanagedCopy.realmSet$columnObjectIdDictionary(new RealmDictionary<org.bson.types.ObjectId>());\n        RealmDictionary<org.bson.types.ObjectId> managedcolumnObjectIdDictionaryDictionary = realmSource.realmGet$columnObjectIdDictionary();\n        for (Map.Entry<String, org.bson.types.ObjectId> entry : managedcolumnObjectIdDictionaryDictionary.entrySet()) {\n            unmanagedCopy.realmGet$columnObjectIdDictionary().put(entry.getKey(), entry.getValue());\n        }\n\n        unmanagedCopy.realmSet$columnUUIDDictionary(new RealmDictionary<java.util.UUID>());\n        RealmDictionary<java.util.UUID> managedcolumnUUIDDictionaryDictionary = realmSource.realmGet$columnUUIDDictionary();\n        for (Map.Entry<String, java.util.UUID> entry : managedcolumnUUIDDictionaryDictionary.entrySet()) {\n            unmanagedCopy.realmGet$columnUUIDDictionary().put(entry.getKey(), entry.getValue());\n        }\n\n        unmanagedCopy.realmSet$columnDecimal128Dictionary(new RealmDictionary<org.bson.types.Decimal128>());\n        RealmDictionary<org.bson.types.Decimal128> managedcolumnDecimal128DictionaryDictionary = realmSource.realmGet$columnDecimal128Dictionary();\n        for (Map.Entry<String, org.bson.types.Decimal128> entry : managedcolumnDecimal128DictionaryDictionary.entrySet()) {\n            unmanagedCopy.realmGet$columnDecimal128Dictionary().put(entry.getKey(), entry.getValue());\n        }\n\n        // Deep copy of columnRealmAnyDictionary\n        if (currentDepth == maxDepth) {\n            unmanagedCopy.realmSet$columnRealmAnyDictionary(null);\n        } else {\n            RealmDictionary<RealmAny> managedcolumnRealmAnyDictionaryDictionary = realmSource.realmGet$columnRealmAnyDictionary();\n            RealmDictionary<RealmAny> unmanagedcolumnRealmAnyDictionaryDictionary = new RealmDictionary<RealmAny>();\n            unmanagedCopy.realmSet$columnRealmAnyDictionary(unmanagedcolumnRealmAnyDictionaryDictionary);\n            int nextDepth = currentDepth + 1;\n            for (Map.Entry<String, RealmAny> entry : managedcolumnRealmAnyDictionaryDictionary.entrySet()) {\n                RealmAny detachedValue = ProxyUtils.createDetachedCopy(entry.getValue(), objectRealm, nextDepth, maxDepth, cache);\n                unmanagedcolumnRealmAnyDictionaryDictionary.put(entry.getKey(), detachedValue);\n            }\n        }\n\n        return unmanagedObject;\n    }\n\n    static some.test.AllTypes update(Realm realm, AllTypesColumnInfo columnInfo, some.test.AllTypes realmObject, some.test.AllTypes newObject, Map<RealmModel, RealmObjectProxy> cache, Set<ImportFlag> flags) {\n        some_test_AllTypesRealmProxyInterface realmObjectTarget = (some_test_AllTypesRealmProxyInterface) realmObject;\n        some_test_AllTypesRealmProxyInterface realmObjectSource = (some_test_AllTypesRealmProxyInterface) newObject;\n        Table table = realm.getTable(some.test.AllTypes.class);\n        OsObjectBuilder builder = new OsObjectBuilder(table, flags);\n        builder.addString(columnInfo.columnStringColKey, realmObjectSource.realmGet$columnString());\n        builder.addInteger(columnInfo.columnLongColKey, realmObjectSource.realmGet$columnLong());\n        builder.addFloat(columnInfo.columnFloatColKey, realmObjectSource.realmGet$columnFloat());\n        builder.addDouble(columnInfo.columnDoubleColKey, realmObjectSource.realmGet$columnDouble());\n        builder.addBoolean(columnInfo.columnBooleanColKey, realmObjectSource.realmGet$columnBoolean());\n        builder.addDecimal128(columnInfo.columnDecimal128ColKey, realmObjectSource.realmGet$columnDecimal128());\n        builder.addObjectId(columnInfo.columnObjectIdColKey, realmObjectSource.realmGet$columnObjectId());\n        builder.addUUID(columnInfo.columnUUIDColKey, realmObjectSource.realmGet$columnUUID());\n        builder.addDate(columnInfo.columnDateColKey, realmObjectSource.realmGet$columnDate());\n\n        RealmAny columnRealmAnyRealmAny = realmObjectSource.realmGet$columnRealmAny();\n        columnRealmAnyRealmAny = ProxyUtils.copyOrUpdate(columnRealmAnyRealmAny, realm, true, cache, flags);\n        builder.addRealmAny(columnInfo.columnRealmAnyColKey, columnRealmAnyRealmAny.getNativePtr());\n        builder.addByteArray(columnInfo.columnBinaryColKey, realmObjectSource.realmGet$columnBinary());\n        builder.addMutableRealmInteger(columnInfo.columnMutableRealmIntegerColKey, realmObjectSource.realmGet$columnMutableRealmInteger());\n\n        some.test.AllTypes columnObjectObj = realmObjectSource.realmGet$columnObject();\n        if (columnObjectObj == null) {\n            builder.addNull(columnInfo.columnObjectColKey);\n        } else {\n            some.test.AllTypes cachecolumnObject = (some.test.AllTypes) cache.get(columnObjectObj);\n            if (cachecolumnObject != null) {\n                builder.addObject(columnInfo.columnObjectColKey, cachecolumnObject);\n            } else {\n                builder.addObject(columnInfo.columnObjectColKey, some_test_AllTypesRealmProxy.copyOrUpdate(realm, (some_test_AllTypesRealmProxy.AllTypesColumnInfo) realm.getSchema().getColumnInfo(some.test.AllTypes.class), columnObjectObj, true, cache, flags));\n            }\n        }\n\n        some.test.Simple columnObjectWithoutPkObj = realmObjectSource.realmGet$columnObjectWithoutPk();\n        if (columnObjectWithoutPkObj == null) {\n            builder.addNull(columnInfo.columnObjectWithoutPkColKey);\n        } else {\n            some.test.Simple cachecolumnObjectWithoutPk = (some.test.Simple) cache.get(columnObjectWithoutPkObj);\n            if (cachecolumnObjectWithoutPk != null) {\n                builder.addObject(columnInfo.columnObjectWithoutPkColKey, cachecolumnObjectWithoutPk);\n            } else {\n                builder.addObject(columnInfo.columnObjectWithoutPkColKey, some_test_SimpleRealmProxy.copyOrUpdate(realm, (some_test_SimpleRealmProxy.SimpleColumnInfo) realm.getSchema().getColumnInfo(some.test.Simple.class), columnObjectWithoutPkObj, true, cache, flags));\n            }\n        }\n\n        RealmList<some.test.AllTypes> columnRealmListUnmanagedList = realmObjectSource.realmGet$columnRealmList();\n        if (columnRealmListUnmanagedList != null) {\n            RealmList<some.test.AllTypes> columnRealmListManagedCopy = new RealmList<some.test.AllTypes>();\n            for (int i = 0; i < columnRealmListUnmanagedList.size(); i++) {\n                some.test.AllTypes columnRealmListItem = columnRealmListUnmanagedList.get(i);\n                some.test.AllTypes cachecolumnRealmList = (some.test.AllTypes) cache.get(columnRealmListItem);\n                if (cachecolumnRealmList != null) {\n                    columnRealmListManagedCopy.add(cachecolumnRealmList);\n                } else {\n                    columnRealmListManagedCopy.add(some_test_AllTypesRealmProxy.copyOrUpdate(realm, (some_test_AllTypesRealmProxy.AllTypesColumnInfo) realm.getSchema().getColumnInfo(some.test.AllTypes.class), columnRealmListItem, true, cache, flags));\n                }\n            }\n            builder.addObjectList(columnInfo.columnRealmListColKey, columnRealmListManagedCopy);\n        } else {\n            builder.addObjectList(columnInfo.columnRealmListColKey, new RealmList<some.test.AllTypes>());\n        }\n\n        RealmList<some.test.Simple> columnRealmListNoPkUnmanagedList = realmObjectSource.realmGet$columnRealmListNoPk();\n        if (columnRealmListNoPkUnmanagedList != null) {\n            RealmList<some.test.Simple> columnRealmListNoPkManagedCopy = new RealmList<some.test.Simple>();\n            for (int i = 0; i < columnRealmListNoPkUnmanagedList.size(); i++) {\n                some.test.Simple columnRealmListNoPkItem = columnRealmListNoPkUnmanagedList.get(i);\n                some.test.Simple cachecolumnRealmListNoPk = (some.test.Simple) cache.get(columnRealmListNoPkItem);\n                if (cachecolumnRealmListNoPk != null) {\n                    columnRealmListNoPkManagedCopy.add(cachecolumnRealmListNoPk);\n                } else {\n                    columnRealmListNoPkManagedCopy.add(some_test_SimpleRealmProxy.copyOrUpdate(realm, (some_test_SimpleRealmProxy.SimpleColumnInfo) realm.getSchema().getColumnInfo(some.test.Simple.class), columnRealmListNoPkItem, true, cache, flags));\n                }\n            }\n            builder.addObjectList(columnInfo.columnRealmListNoPkColKey, columnRealmListNoPkManagedCopy);\n        } else {\n            builder.addObjectList(columnInfo.columnRealmListNoPkColKey, new RealmList<some.test.Simple>());\n        }\n\n        RealmList<some.test.AllTypes> columnRealmFinalListUnmanagedList = realmObjectSource.realmGet$columnRealmFinalList();\n        if (columnRealmFinalListUnmanagedList != null) {\n            RealmList<some.test.AllTypes> columnRealmFinalListManagedCopy = new RealmList<some.test.AllTypes>();\n            for (int i = 0; i < columnRealmFinalListUnmanagedList.size(); i++) {\n                some.test.AllTypes columnRealmFinalListItem = columnRealmFinalListUnmanagedList.get(i);\n                some.test.AllTypes cachecolumnRealmFinalList = (some.test.AllTypes) cache.get(columnRealmFinalListItem);\n                if (cachecolumnRealmFinalList != null) {\n                    columnRealmFinalListManagedCopy.add(cachecolumnRealmFinalList);\n                } else {\n                    columnRealmFinalListManagedCopy.add(some_test_AllTypesRealmProxy.copyOrUpdate(realm, (some_test_AllTypesRealmProxy.AllTypesColumnInfo) realm.getSchema().getColumnInfo(some.test.AllTypes.class), columnRealmFinalListItem, true, cache, flags));\n                }\n            }\n            builder.addObjectList(columnInfo.columnRealmFinalListColKey, columnRealmFinalListManagedCopy);\n        } else {\n            builder.addObjectList(columnInfo.columnRealmFinalListColKey, new RealmList<some.test.AllTypes>());\n        }\n\n        RealmList<some.test.Simple> columnRealmFinalListNoPkUnmanagedList = realmObjectSource.realmGet$columnRealmFinalListNoPk();\n        if (columnRealmFinalListNoPkUnmanagedList != null) {\n            RealmList<some.test.Simple> columnRealmFinalListNoPkManagedCopy = new RealmList<some.test.Simple>();\n            for (int i = 0; i < columnRealmFinalListNoPkUnmanagedList.size(); i++) {\n                some.test.Simple columnRealmFinalListNoPkItem = columnRealmFinalListNoPkUnmanagedList.get(i);\n                some.test.Simple cachecolumnRealmFinalListNoPk = (some.test.Simple) cache.get(columnRealmFinalListNoPkItem);\n                if (cachecolumnRealmFinalListNoPk != null) {\n                    columnRealmFinalListNoPkManagedCopy.add(cachecolumnRealmFinalListNoPk);\n                } else {\n                    columnRealmFinalListNoPkManagedCopy.add(some_test_SimpleRealmProxy.copyOrUpdate(realm, (some_test_SimpleRealmProxy.SimpleColumnInfo) realm.getSchema().getColumnInfo(some.test.Simple.class), columnRealmFinalListNoPkItem, true, cache, flags));\n                }\n            }\n            builder.addObjectList(columnInfo.columnRealmFinalListNoPkColKey, columnRealmFinalListNoPkManagedCopy);\n        } else {\n            builder.addObjectList(columnInfo.columnRealmFinalListNoPkColKey, new RealmList<some.test.Simple>());\n        }\n        builder.addStringList(columnInfo.columnStringListColKey, realmObjectSource.realmGet$columnStringList());\n        builder.addByteArrayList(columnInfo.columnBinaryListColKey, realmObjectSource.realmGet$columnBinaryList());\n        builder.addBooleanList(columnInfo.columnBooleanListColKey, realmObjectSource.realmGet$columnBooleanList());\n        builder.addLongList(columnInfo.columnLongListColKey, realmObjectSource.realmGet$columnLongList());\n        builder.addIntegerList(columnInfo.columnIntegerListColKey, realmObjectSource.realmGet$columnIntegerList());\n        builder.addShortList(columnInfo.columnShortListColKey, realmObjectSource.realmGet$columnShortList());\n        builder.addByteList(columnInfo.columnByteListColKey, realmObjectSource.realmGet$columnByteList());\n        builder.addDoubleList(columnInfo.columnDoubleListColKey, realmObjectSource.realmGet$columnDoubleList());\n        builder.addFloatList(columnInfo.columnFloatListColKey, realmObjectSource.realmGet$columnFloatList());\n        builder.addDateList(columnInfo.columnDateListColKey, realmObjectSource.realmGet$columnDateList());\n        builder.addDecimal128List(columnInfo.columnDecimal128ListColKey, realmObjectSource.realmGet$columnDecimal128List());\n        builder.addObjectIdList(columnInfo.columnObjectIdListColKey, realmObjectSource.realmGet$columnObjectIdList());\n        builder.addUUIDList(columnInfo.columnUUIDListColKey, realmObjectSource.realmGet$columnUUIDList());\n\n        RealmList<RealmAny> columnRealmAnyListUnmanagedList = realmObjectSource.realmGet$columnRealmAnyList();\n        if (columnRealmAnyListUnmanagedList != null) {\n            RealmList<RealmAny> columnRealmAnyListManagedCopy = new RealmList<RealmAny>();\n            for (int i = 0; i < columnRealmAnyListUnmanagedList.size(); i++) {\n                RealmAny realmAnyItem = columnRealmAnyListUnmanagedList.get(i);\n                realmAnyItem = ProxyUtils.copyOrUpdate(realmAnyItem, realm, true, cache, flags);\n                columnRealmAnyListManagedCopy.add(realmAnyItem);\n            }\n            builder.addRealmAnyList(columnInfo.columnRealmAnyListColKey, columnRealmAnyListManagedCopy);\n        } else {\n            builder.addRealmAnyList(columnInfo.columnRealmAnyListColKey, new RealmList<RealmAny>());\n        }\n\n        builder.updateExistingTopLevelObject();\n        return realmObject;\n    }\n\n    @Override\n    @SuppressWarnings(\"ArrayToString\")\n    public String toString() {\n        if (!RealmObject.isValid(this)) {\n            return \"Invalid object\";\n        }\n        StringBuilder stringBuilder = new StringBuilder(\"AllTypes = proxy[\");\n        stringBuilder.append(\"{columnString:\");\n        stringBuilder.append(realmGet$columnString() != null ? realmGet$columnString() : \"null\");\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{columnLong:\");\n        stringBuilder.append(realmGet$columnLong());\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{columnFloat:\");\n        stringBuilder.append(realmGet$columnFloat());\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{columnDouble:\");\n        stringBuilder.append(realmGet$columnDouble());\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{columnBoolean:\");\n        stringBuilder.append(realmGet$columnBoolean());\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{columnDecimal128:\");\n        stringBuilder.append(realmGet$columnDecimal128());\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{columnObjectId:\");\n        stringBuilder.append(realmGet$columnObjectId());\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{columnUUID:\");\n        stringBuilder.append(realmGet$columnUUID());\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{columnDate:\");\n        stringBuilder.append(realmGet$columnDate());\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{columnRealmAny:\");\n        stringBuilder.append((realmGet$columnRealmAny().isNull()) ? \"null\" : \"realmGet$columnRealmAny()\");\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{columnBinary:\");\n        stringBuilder.append(\"binary(\" + realmGet$columnBinary().length + \")\");\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{columnMutableRealmInteger:\");\n        stringBuilder.append(realmGet$columnMutableRealmInteger().get());\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{columnObject:\");\n        stringBuilder.append(realmGet$columnObject() != null ? \"AllTypes\" : \"null\");\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{columnObjectWithoutPk:\");\n        stringBuilder.append(realmGet$columnObjectWithoutPk() != null ? \"Simple\" : \"null\");\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{columnRealmList:\");\n        stringBuilder.append(\"RealmList<AllTypes>[\").append(realmGet$columnRealmList().size()).append(\"]\");\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{columnRealmListNoPk:\");\n        stringBuilder.append(\"RealmList<Simple>[\").append(realmGet$columnRealmListNoPk().size()).append(\"]\");\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{columnRealmFinalList:\");\n        stringBuilder.append(\"RealmList<AllTypes>[\").append(realmGet$columnRealmFinalList().size()).append(\"]\");\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{columnRealmFinalListNoPk:\");\n        stringBuilder.append(\"RealmList<Simple>[\").append(realmGet$columnRealmFinalListNoPk().size()).append(\"]\");\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{columnStringList:\");\n        stringBuilder.append(\"RealmList<String>[\").append(realmGet$columnStringList().size()).append(\"]\");\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{columnBinaryList:\");\n        stringBuilder.append(\"RealmList<byte[]>[\").append(realmGet$columnBinaryList().size()).append(\"]\");\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{columnBooleanList:\");\n        stringBuilder.append(\"RealmList<Boolean>[\").append(realmGet$columnBooleanList().size()).append(\"]\");\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{columnLongList:\");\n        stringBuilder.append(\"RealmList<Long>[\").append(realmGet$columnLongList().size()).append(\"]\");\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{columnIntegerList:\");\n        stringBuilder.append(\"RealmList<Integer>[\").append(realmGet$columnIntegerList().size()).append(\"]\");\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{columnShortList:\");\n        stringBuilder.append(\"RealmList<Short>[\").append(realmGet$columnShortList().size()).append(\"]\");\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{columnByteList:\");\n        stringBuilder.append(\"RealmList<Byte>[\").append(realmGet$columnByteList().size()).append(\"]\");\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{columnDoubleList:\");\n        stringBuilder.append(\"RealmList<Double>[\").append(realmGet$columnDoubleList().size()).append(\"]\");\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{columnFloatList:\");\n        stringBuilder.append(\"RealmList<Float>[\").append(realmGet$columnFloatList().size()).append(\"]\");\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{columnDateList:\");\n        stringBuilder.append(\"RealmList<Date>[\").append(realmGet$columnDateList().size()).append(\"]\");\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{columnDecimal128List:\");\n        stringBuilder.append(\"RealmList<Decimal128>[\").append(realmGet$columnDecimal128List().size()).append(\"]\");\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{columnObjectIdList:\");\n        stringBuilder.append(\"RealmList<ObjectId>[\").append(realmGet$columnObjectIdList().size()).append(\"]\");\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{columnUUIDList:\");\n        stringBuilder.append(\"RealmList<UUID>[\").append(realmGet$columnUUIDList().size()).append(\"]\");\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{columnRealmAnyList:\");\n        stringBuilder.append(\"RealmList<RealmAny>[\").append(realmGet$columnRealmAnyList().size()).append(\"]\");\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{columnRealmDictionary:\");\n        stringBuilder.append(\"RealmDictionary<AllTypes>[\").append(realmGet$columnRealmDictionary().size()).append(\"]\");\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{columnBooleanDictionary:\");\n        stringBuilder.append(\"RealmDictionary<Boolean>[\").append(realmGet$columnBooleanDictionary().size()).append(\"]\");\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{columnStringDictionary:\");\n        stringBuilder.append(\"RealmDictionary<String>[\").append(realmGet$columnStringDictionary().size()).append(\"]\");\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{columnIntegerDictionary:\");\n        stringBuilder.append(\"RealmDictionary<Integer>[\").append(realmGet$columnIntegerDictionary().size()).append(\"]\");\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{columnFloatDictionary:\");\n        stringBuilder.append(\"RealmDictionary<Float>[\").append(realmGet$columnFloatDictionary().size()).append(\"]\");\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{columnLongDictionary:\");\n        stringBuilder.append(\"RealmDictionary<Long>[\").append(realmGet$columnLongDictionary().size()).append(\"]\");\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{columnShortDictionary:\");\n        stringBuilder.append(\"RealmDictionary<Short>[\").append(realmGet$columnShortDictionary().size()).append(\"]\");\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{columnDoubleDictionary:\");\n        stringBuilder.append(\"RealmDictionary<Double>[\").append(realmGet$columnDoubleDictionary().size()).append(\"]\");\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{columnByteDictionary:\");\n        stringBuilder.append(\"RealmDictionary<Byte>[\").append(realmGet$columnByteDictionary().size()).append(\"]\");\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{columnBinaryDictionary:\");\n        stringBuilder.append(\"RealmDictionary<byte[]>[\").append(realmGet$columnBinaryDictionary().size()).append(\"]\");\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{columnDateDictionary:\");\n        stringBuilder.append(\"RealmDictionary<Date>[\").append(realmGet$columnDateDictionary().size()).append(\"]\");\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{columnObjectIdDictionary:\");\n        stringBuilder.append(\"RealmDictionary<ObjectId>[\").append(realmGet$columnObjectIdDictionary().size()).append(\"]\");\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{columnUUIDDictionary:\");\n        stringBuilder.append(\"RealmDictionary<UUID>[\").append(realmGet$columnUUIDDictionary().size()).append(\"]\");\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{columnDecimal128Dictionary:\");\n        stringBuilder.append(\"RealmDictionary<Decimal128>[\").append(realmGet$columnDecimal128Dictionary().size()).append(\"]\");\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{columnRealmAnyDictionary:\");\n        stringBuilder.append(\"RealmDictionary<RealmAny>[\").append(realmGet$columnRealmAnyDictionary().size()).append(\"]\");\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\"]\");\n        return stringBuilder.toString();\n    }\n\n    @Override\n    public ProxyState<?> realmGet$proxyState() {\n        return proxyState;\n    }\n\n    @Override\n    public int hashCode() {\n        String realmName = proxyState.getRealm$realm().getPath();\n        String tableName = proxyState.getRow$realm().getTable().getName();\n        long objKey = proxyState.getRow$realm().getObjectKey();\n\n        int result = 17;\n        result = 31 * result + ((realmName != null) ? realmName.hashCode() : 0);\n        result = 31 * result + ((tableName != null) ? tableName.hashCode() : 0);\n        result = 31 * result + (int) (objKey ^ (objKey >>> 32));\n        return result;\n    }\n\n    @Override\n    public boolean equals(Object o) {\n        if (this == o) return true;\n        if (o == null || getClass() != o.getClass()) return false;\n        some_test_AllTypesRealmProxy aAllTypes = (some_test_AllTypesRealmProxy)o;\n\n        BaseRealm realm = proxyState.getRealm$realm();\n        BaseRealm otherRealm = aAllTypes.proxyState.getRealm$realm();\n        String path = realm.getPath();\n        String otherPath = otherRealm.getPath();\n        if (path != null ? !path.equals(otherPath) : otherPath != null) return false;\n        if (realm.isFrozen() != otherRealm.isFrozen()) return false;\n        if (!realm.sharedRealm.getVersionID().equals(otherRealm.sharedRealm.getVersionID())) {\n            return false;\n        }\n\n        String tableName = proxyState.getRow$realm().getTable().getName();\n        String otherTableName = aAllTypes.proxyState.getRow$realm().getTable().getName();\n        if (tableName != null ? !tableName.equals(otherTableName) : otherTableName != null) return false;\n\n        if (proxyState.getRow$realm().getObjectKey() != aAllTypes.proxyState.getRow$realm().getObjectKey()) return false;\n\n        return true;\n    }\n}\n"
  },
  {
    "path": "realm/realm-annotations-processor/src/test/resources/io/realm/some_test_AllTypesRealmProxy.java",
    "content": "package io.realm;\n\n\nimport android.annotation.TargetApi;\nimport android.os.Build;\nimport android.util.JsonReader;\nimport android.util.JsonToken;\nimport io.realm.ImportFlag;\nimport io.realm.ProxyUtils;\nimport io.realm.exceptions.RealmMigrationNeededException;\nimport io.realm.internal.ColumnInfo;\nimport io.realm.internal.NativeContext;\nimport io.realm.internal.OsList;\nimport io.realm.internal.OsMap;\nimport io.realm.internal.OsObject;\nimport io.realm.internal.OsObjectSchemaInfo;\nimport io.realm.internal.OsSchemaInfo;\nimport io.realm.internal.OsSet;\nimport io.realm.internal.Property;\nimport io.realm.internal.RealmObjectProxy;\nimport io.realm.internal.Row;\nimport io.realm.internal.Table;\nimport io.realm.internal.UncheckedRow;\nimport io.realm.internal.android.JsonUtils;\nimport io.realm.internal.core.NativeRealmAny;\nimport io.realm.internal.objectstore.OsObjectBuilder;\nimport io.realm.log.RealmLog;\nimport java.io.IOException;\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.Date;\nimport java.util.HashMap;\nimport java.util.HashSet;\nimport java.util.Iterator;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Set;\nimport org.json.JSONArray;\nimport org.json.JSONException;\nimport org.json.JSONObject;\n\n@SuppressWarnings(\"all\")\npublic class some_test_AllTypesRealmProxy extends some.test.AllTypes\n        implements RealmObjectProxy, some_test_AllTypesRealmProxyInterface {\n\n    static final class AllTypesColumnInfo extends ColumnInfo {\n        long columnStringColKey;\n        long columnLongColKey;\n        long columnFloatColKey;\n        long columnDoubleColKey;\n        long columnBooleanColKey;\n        long columnDecimal128ColKey;\n        long columnObjectIdColKey;\n        long columnUUIDColKey;\n        long columnDateColKey;\n        long columnRealmAnyColKey;\n        long columnBinaryColKey;\n        long columnMutableRealmIntegerColKey;\n        long columnObjectColKey;\n        long columnObjectWithoutPkColKey;\n        long columnRealmListColKey;\n        long columnRealmListNoPkColKey;\n        long columnRealmFinalListColKey;\n        long columnRealmFinalListNoPkColKey;\n        long columnStringListColKey;\n        long columnBinaryListColKey;\n        long columnBooleanListColKey;\n        long columnLongListColKey;\n        long columnIntegerListColKey;\n        long columnShortListColKey;\n        long columnByteListColKey;\n        long columnDoubleListColKey;\n        long columnFloatListColKey;\n        long columnDateListColKey;\n        long columnDecimal128ListColKey;\n        long columnObjectIdListColKey;\n        long columnUUIDListColKey;\n        long columnRealmAnyListColKey;\n        long columnRealmDictionaryColKey;\n        long columnBooleanDictionaryColKey;\n        long columnStringDictionaryColKey;\n        long columnIntegerDictionaryColKey;\n        long columnFloatDictionaryColKey;\n        long columnLongDictionaryColKey;\n        long columnShortDictionaryColKey;\n        long columnDoubleDictionaryColKey;\n        long columnByteDictionaryColKey;\n        long columnBinaryDictionaryColKey;\n        long columnDateDictionaryColKey;\n        long columnObjectIdDictionaryColKey;\n        long columnUUIDDictionaryColKey;\n        long columnDecimal128DictionaryColKey;\n        long columnRealmAnyDictionaryColKey;\n\n        AllTypesColumnInfo(OsSchemaInfo schemaInfo) {\n            super(47);\n            OsObjectSchemaInfo objectSchemaInfo = schemaInfo.getObjectSchemaInfo(\"AllTypes\");\n            this.columnStringColKey = addColumnDetails(\"columnString\", \"columnString\", objectSchemaInfo);\n            this.columnLongColKey = addColumnDetails(\"columnLong\", \"columnLong\", objectSchemaInfo);\n            this.columnFloatColKey = addColumnDetails(\"columnFloat\", \"columnFloat\", objectSchemaInfo);\n            this.columnDoubleColKey = addColumnDetails(\"columnDouble\", \"columnDouble\", objectSchemaInfo);\n            this.columnBooleanColKey = addColumnDetails(\"columnBoolean\", \"columnBoolean\", objectSchemaInfo);\n            this.columnDecimal128ColKey = addColumnDetails(\"columnDecimal128\", \"columnDecimal128\", objectSchemaInfo);\n            this.columnObjectIdColKey = addColumnDetails(\"columnObjectId\", \"columnObjectId\", objectSchemaInfo);\n            this.columnUUIDColKey = addColumnDetails(\"columnUUID\", \"columnUUID\", objectSchemaInfo);\n            this.columnDateColKey = addColumnDetails(\"columnDate\", \"columnDate\", objectSchemaInfo);\n            this.columnRealmAnyColKey = addColumnDetails(\"columnRealmAny\", \"columnRealmAny\", objectSchemaInfo);\n            this.columnBinaryColKey = addColumnDetails(\"columnBinary\", \"columnBinary\", objectSchemaInfo);\n            this.columnMutableRealmIntegerColKey = addColumnDetails(\"columnMutableRealmInteger\", \"columnMutableRealmInteger\", objectSchemaInfo);\n            this.columnObjectColKey = addColumnDetails(\"columnObject\", \"columnObject\", objectSchemaInfo);\n            this.columnObjectWithoutPkColKey = addColumnDetails(\"columnObjectWithoutPk\", \"columnObjectWithoutPk\", objectSchemaInfo);\n            this.columnRealmListColKey = addColumnDetails(\"columnRealmList\", \"columnRealmList\", objectSchemaInfo);\n            this.columnRealmListNoPkColKey = addColumnDetails(\"columnRealmListNoPk\", \"columnRealmListNoPk\", objectSchemaInfo);\n            this.columnRealmFinalListColKey = addColumnDetails(\"columnRealmFinalList\", \"columnRealmFinalList\", objectSchemaInfo);\n            this.columnRealmFinalListNoPkColKey = addColumnDetails(\"columnRealmFinalListNoPk\", \"columnRealmFinalListNoPk\", objectSchemaInfo);\n            this.columnStringListColKey = addColumnDetails(\"columnStringList\", \"columnStringList\", objectSchemaInfo);\n            this.columnBinaryListColKey = addColumnDetails(\"columnBinaryList\", \"columnBinaryList\", objectSchemaInfo);\n            this.columnBooleanListColKey = addColumnDetails(\"columnBooleanList\", \"columnBooleanList\", objectSchemaInfo);\n            this.columnLongListColKey = addColumnDetails(\"columnLongList\", \"columnLongList\", objectSchemaInfo);\n            this.columnIntegerListColKey = addColumnDetails(\"columnIntegerList\", \"columnIntegerList\", objectSchemaInfo);\n            this.columnShortListColKey = addColumnDetails(\"columnShortList\", \"columnShortList\", objectSchemaInfo);\n            this.columnByteListColKey = addColumnDetails(\"columnByteList\", \"columnByteList\", objectSchemaInfo);\n            this.columnDoubleListColKey = addColumnDetails(\"columnDoubleList\", \"columnDoubleList\", objectSchemaInfo);\n            this.columnFloatListColKey = addColumnDetails(\"columnFloatList\", \"columnFloatList\", objectSchemaInfo);\n            this.columnDateListColKey = addColumnDetails(\"columnDateList\", \"columnDateList\", objectSchemaInfo);\n            this.columnDecimal128ListColKey = addColumnDetails(\"columnDecimal128List\", \"columnDecimal128List\", objectSchemaInfo);\n            this.columnObjectIdListColKey = addColumnDetails(\"columnObjectIdList\", \"columnObjectIdList\", objectSchemaInfo);\n            this.columnUUIDListColKey = addColumnDetails(\"columnUUIDList\", \"columnUUIDList\", objectSchemaInfo);\n            this.columnRealmAnyListColKey = addColumnDetails(\"columnRealmAnyList\", \"columnRealmAnyList\", objectSchemaInfo);\n            this.columnRealmDictionaryColKey = addColumnDetails(\"columnRealmDictionary\", \"columnRealmDictionary\", objectSchemaInfo);\n            this.columnBooleanDictionaryColKey = addColumnDetails(\"columnBooleanDictionary\", \"columnBooleanDictionary\", objectSchemaInfo);\n            this.columnStringDictionaryColKey = addColumnDetails(\"columnStringDictionary\", \"columnStringDictionary\", objectSchemaInfo);\n            this.columnIntegerDictionaryColKey = addColumnDetails(\"columnIntegerDictionary\", \"columnIntegerDictionary\", objectSchemaInfo);\n            this.columnFloatDictionaryColKey = addColumnDetails(\"columnFloatDictionary\", \"columnFloatDictionary\", objectSchemaInfo);\n            this.columnLongDictionaryColKey = addColumnDetails(\"columnLongDictionary\", \"columnLongDictionary\", objectSchemaInfo);\n            this.columnShortDictionaryColKey = addColumnDetails(\"columnShortDictionary\", \"columnShortDictionary\", objectSchemaInfo);\n            this.columnDoubleDictionaryColKey = addColumnDetails(\"columnDoubleDictionary\", \"columnDoubleDictionary\", objectSchemaInfo);\n            this.columnByteDictionaryColKey = addColumnDetails(\"columnByteDictionary\", \"columnByteDictionary\", objectSchemaInfo);\n            this.columnBinaryDictionaryColKey = addColumnDetails(\"columnBinaryDictionary\", \"columnBinaryDictionary\", objectSchemaInfo);\n            this.columnDateDictionaryColKey = addColumnDetails(\"columnDateDictionary\", \"columnDateDictionary\", objectSchemaInfo);\n            this.columnObjectIdDictionaryColKey = addColumnDetails(\"columnObjectIdDictionary\", \"columnObjectIdDictionary\", objectSchemaInfo);\n            this.columnUUIDDictionaryColKey = addColumnDetails(\"columnUUIDDictionary\", \"columnUUIDDictionary\", objectSchemaInfo);\n            this.columnDecimal128DictionaryColKey = addColumnDetails(\"columnDecimal128Dictionary\", \"columnDecimal128Dictionary\", objectSchemaInfo);\n            this.columnRealmAnyDictionaryColKey = addColumnDetails(\"columnRealmAnyDictionary\", \"columnRealmAnyDictionary\", objectSchemaInfo);\n            addBacklinkDetails(schemaInfo, \"parentObjects\", \"AllTypes\", \"columnObject\");\n        }\n\n        AllTypesColumnInfo(ColumnInfo src, boolean mutable) {\n            super(src, mutable);\n            copy(src, this);\n        }\n\n        @Override\n        protected final ColumnInfo copy(boolean mutable) {\n            return new AllTypesColumnInfo(this, mutable);\n        }\n\n        @Override\n        protected final void copy(ColumnInfo rawSrc, ColumnInfo rawDst) {\n            final AllTypesColumnInfo src = (AllTypesColumnInfo) rawSrc;\n            final AllTypesColumnInfo dst = (AllTypesColumnInfo) rawDst;\n            dst.columnStringColKey = src.columnStringColKey;\n            dst.columnLongColKey = src.columnLongColKey;\n            dst.columnFloatColKey = src.columnFloatColKey;\n            dst.columnDoubleColKey = src.columnDoubleColKey;\n            dst.columnBooleanColKey = src.columnBooleanColKey;\n            dst.columnDecimal128ColKey = src.columnDecimal128ColKey;\n            dst.columnObjectIdColKey = src.columnObjectIdColKey;\n            dst.columnUUIDColKey = src.columnUUIDColKey;\n            dst.columnDateColKey = src.columnDateColKey;\n            dst.columnRealmAnyColKey = src.columnRealmAnyColKey;\n            dst.columnBinaryColKey = src.columnBinaryColKey;\n            dst.columnMutableRealmIntegerColKey = src.columnMutableRealmIntegerColKey;\n            dst.columnObjectColKey = src.columnObjectColKey;\n            dst.columnObjectWithoutPkColKey = src.columnObjectWithoutPkColKey;\n            dst.columnRealmListColKey = src.columnRealmListColKey;\n            dst.columnRealmListNoPkColKey = src.columnRealmListNoPkColKey;\n            dst.columnRealmFinalListColKey = src.columnRealmFinalListColKey;\n            dst.columnRealmFinalListNoPkColKey = src.columnRealmFinalListNoPkColKey;\n            dst.columnStringListColKey = src.columnStringListColKey;\n            dst.columnBinaryListColKey = src.columnBinaryListColKey;\n            dst.columnBooleanListColKey = src.columnBooleanListColKey;\n            dst.columnLongListColKey = src.columnLongListColKey;\n            dst.columnIntegerListColKey = src.columnIntegerListColKey;\n            dst.columnShortListColKey = src.columnShortListColKey;\n            dst.columnByteListColKey = src.columnByteListColKey;\n            dst.columnDoubleListColKey = src.columnDoubleListColKey;\n            dst.columnFloatListColKey = src.columnFloatListColKey;\n            dst.columnDateListColKey = src.columnDateListColKey;\n            dst.columnDecimal128ListColKey = src.columnDecimal128ListColKey;\n            dst.columnObjectIdListColKey = src.columnObjectIdListColKey;\n            dst.columnUUIDListColKey = src.columnUUIDListColKey;\n            dst.columnRealmAnyListColKey = src.columnRealmAnyListColKey;\n            dst.columnRealmDictionaryColKey = src.columnRealmDictionaryColKey;\n            dst.columnBooleanDictionaryColKey = src.columnBooleanDictionaryColKey;\n            dst.columnStringDictionaryColKey = src.columnStringDictionaryColKey;\n            dst.columnIntegerDictionaryColKey = src.columnIntegerDictionaryColKey;\n            dst.columnFloatDictionaryColKey = src.columnFloatDictionaryColKey;\n            dst.columnLongDictionaryColKey = src.columnLongDictionaryColKey;\n            dst.columnShortDictionaryColKey = src.columnShortDictionaryColKey;\n            dst.columnDoubleDictionaryColKey = src.columnDoubleDictionaryColKey;\n            dst.columnByteDictionaryColKey = src.columnByteDictionaryColKey;\n            dst.columnBinaryDictionaryColKey = src.columnBinaryDictionaryColKey;\n            dst.columnDateDictionaryColKey = src.columnDateDictionaryColKey;\n            dst.columnObjectIdDictionaryColKey = src.columnObjectIdDictionaryColKey;\n            dst.columnUUIDDictionaryColKey = src.columnUUIDDictionaryColKey;\n            dst.columnDecimal128DictionaryColKey = src.columnDecimal128DictionaryColKey;\n            dst.columnRealmAnyDictionaryColKey = src.columnRealmAnyDictionaryColKey;\n        }\n    }\n\n    private static final String NO_ALIAS = \"\";\n    private static final OsObjectSchemaInfo expectedObjectSchemaInfo = createExpectedObjectSchemaInfo();\n\n    private AllTypesColumnInfo columnInfo;\n    private ProxyState<some.test.AllTypes> proxyState;\n    private final MutableRealmInteger.Managed columnMutableRealmIntegerMutableRealmInteger = new MutableRealmInteger.Managed<some.test.AllTypes>() {\n        @Override protected ProxyState<some.test.AllTypes> getProxyState() { return proxyState; }\n        @Override protected long getColumnIndex() { return columnInfo.columnMutableRealmIntegerColKey; }\n    };\n    private RealmList<some.test.AllTypes> columnRealmListRealmList;\n    private RealmList<some.test.Simple> columnRealmListNoPkRealmList;\n    private RealmList<some.test.AllTypes> columnRealmFinalListRealmList;\n    private RealmList<some.test.Simple> columnRealmFinalListNoPkRealmList;\n    private RealmList<String> columnStringListRealmList;\n    private RealmList<byte[]> columnBinaryListRealmList;\n    private RealmList<Boolean> columnBooleanListRealmList;\n    private RealmList<Long> columnLongListRealmList;\n    private RealmList<Integer> columnIntegerListRealmList;\n    private RealmList<Short> columnShortListRealmList;\n    private RealmList<Byte> columnByteListRealmList;\n    private RealmList<Double> columnDoubleListRealmList;\n    private RealmList<Float> columnFloatListRealmList;\n    private RealmList<Date> columnDateListRealmList;\n    private RealmList<org.bson.types.Decimal128> columnDecimal128ListRealmList;\n    private RealmList<org.bson.types.ObjectId> columnObjectIdListRealmList;\n    private RealmList<java.util.UUID> columnUUIDListRealmList;\n    private RealmList<RealmAny> columnRealmAnyListRealmList;\n    private RealmDictionary<some.test.AllTypes> columnRealmDictionaryRealmDictionary;\n    private RealmDictionary<Boolean> columnBooleanDictionaryRealmDictionary;\n    private RealmDictionary<String> columnStringDictionaryRealmDictionary;\n    private RealmDictionary<Integer> columnIntegerDictionaryRealmDictionary;\n    private RealmDictionary<Float> columnFloatDictionaryRealmDictionary;\n    private RealmDictionary<Long> columnLongDictionaryRealmDictionary;\n    private RealmDictionary<Short> columnShortDictionaryRealmDictionary;\n    private RealmDictionary<Double> columnDoubleDictionaryRealmDictionary;\n    private RealmDictionary<Byte> columnByteDictionaryRealmDictionary;\n    private RealmDictionary<byte[]> columnBinaryDictionaryRealmDictionary;\n    private RealmDictionary<Date> columnDateDictionaryRealmDictionary;\n    private RealmDictionary<org.bson.types.ObjectId> columnObjectIdDictionaryRealmDictionary;\n    private RealmDictionary<java.util.UUID> columnUUIDDictionaryRealmDictionary;\n    private RealmDictionary<org.bson.types.Decimal128> columnDecimal128DictionaryRealmDictionary;\n    private RealmDictionary<RealmAny> columnRealmAnyDictionaryRealmDictionary;\n    private RealmResults<some.test.AllTypes> parentObjectsBacklinks;\n\n    some_test_AllTypesRealmProxy() {\n        proxyState.setConstructionFinished();\n    }\n\n    @Override\n    public void realm$injectObjectContext() {\n        if (this.proxyState != null) {\n            return;\n        }\n        final BaseRealm.RealmObjectContext context = BaseRealm.objectContext.get();\n        this.columnInfo = (AllTypesColumnInfo) context.getColumnInfo();\n        this.proxyState = new ProxyState<some.test.AllTypes>(this);\n        proxyState.setRealm$realm(context.getRealm());\n        proxyState.setRow$realm(context.getRow());\n        proxyState.setAcceptDefaultValue$realm(context.getAcceptDefaultValue());\n        proxyState.setExcludeFields$realm(context.getExcludeFields());\n    }\n\n    @Override\n    @SuppressWarnings(\"cast\")\n    public String realmGet$columnString() {\n        proxyState.getRealm$realm().checkIfValid();\n        return (java.lang.String) proxyState.getRow$realm().getString(columnInfo.columnStringColKey);\n    }\n\n    @Override\n    public void realmSet$columnString(String value) {\n        if (proxyState.isUnderConstruction()) {\n            // default value of the primary key is always ignored.\n            return;\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        throw new io.realm.exceptions.RealmException(\"Primary key field 'columnString' cannot be changed after object was created.\");\n    }\n\n    @Override\n    @SuppressWarnings(\"cast\")\n    public long realmGet$columnLong() {\n        proxyState.getRealm$realm().checkIfValid();\n        return (long) proxyState.getRow$realm().getLong(columnInfo.columnLongColKey);\n    }\n\n    @Override\n    public void realmSet$columnLong(long value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            final Row row = proxyState.getRow$realm();\n            row.getTable().setLong(columnInfo.columnLongColKey, row.getObjectKey(), value, true);\n            return;\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        proxyState.getRow$realm().setLong(columnInfo.columnLongColKey, value);\n    }\n\n    @Override\n    @SuppressWarnings(\"cast\")\n    public float realmGet$columnFloat() {\n        proxyState.getRealm$realm().checkIfValid();\n        return (float) proxyState.getRow$realm().getFloat(columnInfo.columnFloatColKey);\n    }\n\n    @Override\n    public void realmSet$columnFloat(float value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            final Row row = proxyState.getRow$realm();\n            row.getTable().setFloat(columnInfo.columnFloatColKey, row.getObjectKey(), value, true);\n            return;\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        proxyState.getRow$realm().setFloat(columnInfo.columnFloatColKey, value);\n    }\n\n    @Override\n    @SuppressWarnings(\"cast\")\n    public double realmGet$columnDouble() {\n        proxyState.getRealm$realm().checkIfValid();\n        return (double) proxyState.getRow$realm().getDouble(columnInfo.columnDoubleColKey);\n    }\n\n    @Override\n    public void realmSet$columnDouble(double value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            final Row row = proxyState.getRow$realm();\n            row.getTable().setDouble(columnInfo.columnDoubleColKey, row.getObjectKey(), value, true);\n            return;\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        proxyState.getRow$realm().setDouble(columnInfo.columnDoubleColKey, value);\n    }\n\n    @Override\n    @SuppressWarnings(\"cast\")\n    public boolean realmGet$columnBoolean() {\n        proxyState.getRealm$realm().checkIfValid();\n        return (boolean) proxyState.getRow$realm().getBoolean(columnInfo.columnBooleanColKey);\n    }\n\n    @Override\n    public void realmSet$columnBoolean(boolean value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            final Row row = proxyState.getRow$realm();\n            row.getTable().setBoolean(columnInfo.columnBooleanColKey, row.getObjectKey(), value, true);\n            return;\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        proxyState.getRow$realm().setBoolean(columnInfo.columnBooleanColKey, value);\n    }\n\n    @Override\n    @SuppressWarnings(\"cast\")\n    public org.bson.types.Decimal128 realmGet$columnDecimal128() {\n        proxyState.getRealm$realm().checkIfValid();\n        return (org.bson.types.Decimal128) proxyState.getRow$realm().getDecimal128(columnInfo.columnDecimal128ColKey);\n    }\n\n    @Override\n    public void realmSet$columnDecimal128(org.bson.types.Decimal128 value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            final Row row = proxyState.getRow$realm();\n            if (value == null) {\n                throw new IllegalArgumentException(\"Trying to set non-nullable field 'columnDecimal128' to null.\");\n            }\n            row.getTable().setDecimal128(columnInfo.columnDecimal128ColKey, row.getObjectKey(), value, true);\n            return;\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        if (value == null) {\n            throw new IllegalArgumentException(\"Trying to set non-nullable field 'columnDecimal128' to null.\");\n        }\n        proxyState.getRow$realm().setDecimal128(columnInfo.columnDecimal128ColKey, value);\n    }\n\n    @Override\n    @SuppressWarnings(\"cast\")\n    public org.bson.types.ObjectId realmGet$columnObjectId() {\n        proxyState.getRealm$realm().checkIfValid();\n        return (org.bson.types.ObjectId) proxyState.getRow$realm().getObjectId(columnInfo.columnObjectIdColKey);\n    }\n\n    @Override\n    public void realmSet$columnObjectId(org.bson.types.ObjectId value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            final Row row = proxyState.getRow$realm();\n            if (value == null) {\n                throw new IllegalArgumentException(\"Trying to set non-nullable field 'columnObjectId' to null.\");\n            }\n            row.getTable().setObjectId(columnInfo.columnObjectIdColKey, row.getObjectKey(), value, true);\n            return;\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        if (value == null) {\n            throw new IllegalArgumentException(\"Trying to set non-nullable field 'columnObjectId' to null.\");\n        }\n        proxyState.getRow$realm().setObjectId(columnInfo.columnObjectIdColKey, value);\n    }\n\n    @Override\n    @SuppressWarnings(\"cast\")\n    public java.util.UUID realmGet$columnUUID() {\n        proxyState.getRealm$realm().checkIfValid();\n        return (java.util.UUID) proxyState.getRow$realm().getUUID(columnInfo.columnUUIDColKey);\n    }\n\n    @Override\n    public void realmSet$columnUUID(java.util.UUID value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            final Row row = proxyState.getRow$realm();\n            if (value == null) {\n                throw new IllegalArgumentException(\"Trying to set non-nullable field 'columnUUID' to null.\");\n            }\n            row.getTable().setUUID(columnInfo.columnUUIDColKey, row.getObjectKey(), value, true);\n            return;\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        if (value == null) {\n            throw new IllegalArgumentException(\"Trying to set non-nullable field 'columnUUID' to null.\");\n        }\n        proxyState.getRow$realm().setUUID(columnInfo.columnUUIDColKey, value);\n    }\n\n    @Override\n    @SuppressWarnings(\"cast\")\n    public Date realmGet$columnDate() {\n        proxyState.getRealm$realm().checkIfValid();\n        return (java.util.Date) proxyState.getRow$realm().getDate(columnInfo.columnDateColKey);\n    }\n\n    @Override\n    public void realmSet$columnDate(Date value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            final Row row = proxyState.getRow$realm();\n            if (value == null) {\n                throw new IllegalArgumentException(\"Trying to set non-nullable field 'columnDate' to null.\");\n            }\n            row.getTable().setDate(columnInfo.columnDateColKey, row.getObjectKey(), value, true);\n            return;\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        if (value == null) {\n            throw new IllegalArgumentException(\"Trying to set non-nullable field 'columnDate' to null.\");\n        }\n        proxyState.getRow$realm().setDate(columnInfo.columnDateColKey, value);\n    }\n\n    @Override\n    public RealmAny realmGet$columnRealmAny() {\n        proxyState.getRealm$realm().checkIfValid();\n        NativeRealmAny nativeRealmAny = proxyState.getRow$realm().getNativeRealmAny(columnInfo.columnRealmAnyColKey);\n        return new RealmAny(RealmAnyOperator.fromNativeRealmAny(proxyState.getRealm$realm(), nativeRealmAny));\n    }\n\n    @Override\n    public void realmSet$columnRealmAny(RealmAny value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            if (proxyState.getExcludeFields$realm().contains(\"columnRealmAny\")) {\n                return;\n            }\n\n            value = ProxyUtils.copyToRealmIfNeeded(proxyState, value);\n\n            final Row row = proxyState.getRow$realm();\n            if (value == null) {\n                row.getTable().setNull(columnInfo.columnRealmAnyColKey, row.getObjectKey(), true);\n                return;\n            }\n            row.getTable().setRealmAny(columnInfo.columnRealmAnyColKey, row.getObjectKey(), value.getNativePtr(), true);\n            return;\n        }\n\n\n        proxyState.getRealm$realm().checkIfValid();\n\n        if (value == null) {\n            proxyState.getRow$realm().setNull(columnInfo.columnRealmAnyColKey);\n            return;\n        }\n        value = ProxyUtils.copyToRealmIfNeeded(proxyState, value);\n        proxyState.getRow$realm().setRealmAny(columnInfo.columnRealmAnyColKey, value.getNativePtr());\n    }\n\n    @Override\n    @SuppressWarnings(\"cast\")\n    public byte[] realmGet$columnBinary() {\n        proxyState.getRealm$realm().checkIfValid();\n        return (byte[]) proxyState.getRow$realm().getBinaryByteArray(columnInfo.columnBinaryColKey);\n    }\n\n    @Override\n    public void realmSet$columnBinary(byte[] value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            final Row row = proxyState.getRow$realm();\n            if (value == null) {\n                throw new IllegalArgumentException(\"Trying to set non-nullable field 'columnBinary' to null.\");\n            }\n            row.getTable().setBinaryByteArray(columnInfo.columnBinaryColKey, row.getObjectKey(), value, true);\n            return;\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        if (value == null) {\n            throw new IllegalArgumentException(\"Trying to set non-nullable field 'columnBinary' to null.\");\n        }\n        proxyState.getRow$realm().setBinaryByteArray(columnInfo.columnBinaryColKey, value);\n    }\n\n    @Override\n    public MutableRealmInteger realmGet$columnMutableRealmInteger() {\n        proxyState.getRealm$realm().checkIfValid();\n        return this.columnMutableRealmIntegerMutableRealmInteger;\n    }\n\n    @Override\n    public some.test.AllTypes realmGet$columnObject() {\n        proxyState.getRealm$realm().checkIfValid();\n        if (proxyState.getRow$realm().isNullLink(columnInfo.columnObjectColKey)) {\n            return null;\n        }\n        return proxyState.getRealm$realm().get(some.test.AllTypes.class, proxyState.getRow$realm().getLink(columnInfo.columnObjectColKey), false, Collections.<String>emptyList());\n    }\n\n    @Override\n    public void realmSet$columnObject(some.test.AllTypes value) {\n        Realm realm = (Realm) proxyState.getRealm$realm();\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            if (proxyState.getExcludeFields$realm().contains(\"columnObject\")) {\n                return;\n            }\n            if (value != null && !RealmObject.isManaged(value)) {\n                value = realm.copyToRealmOrUpdate(value);\n            }\n            final Row row = proxyState.getRow$realm();\n            if (value == null) {\n                // Table#nullifyLink() does not support default value. Just using Row.\n                row.nullifyLink(columnInfo.columnObjectColKey);\n                return;\n            }\n            proxyState.checkValidObject(value);\n            row.getTable().setLink(columnInfo.columnObjectColKey, row.getObjectKey(), ((RealmObjectProxy) value).realmGet$proxyState().getRow$realm().getObjectKey(), true);\n            return;\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        if (value == null) {\n            proxyState.getRow$realm().nullifyLink(columnInfo.columnObjectColKey);\n            return;\n        }\n        proxyState.checkValidObject(value);\n        proxyState.getRow$realm().setLink(columnInfo.columnObjectColKey, ((RealmObjectProxy) value).realmGet$proxyState().getRow$realm().getObjectKey());\n    }\n\n    @Override\n    public some.test.Simple realmGet$columnObjectWithoutPk() {\n        proxyState.getRealm$realm().checkIfValid();\n        if (proxyState.getRow$realm().isNullLink(columnInfo.columnObjectWithoutPkColKey)) {\n            return null;\n        }\n        return proxyState.getRealm$realm().get(some.test.Simple.class, proxyState.getRow$realm().getLink(columnInfo.columnObjectWithoutPkColKey), false, Collections.<String>emptyList());\n    }\n\n    @Override\n    public void realmSet$columnObjectWithoutPk(some.test.Simple value) {\n        Realm realm = (Realm) proxyState.getRealm$realm();\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            if (proxyState.getExcludeFields$realm().contains(\"columnObjectWithoutPk\")) {\n                return;\n            }\n            if (value != null && !RealmObject.isManaged(value)) {\n                value = realm.copyToRealm(value);\n            }\n            final Row row = proxyState.getRow$realm();\n            if (value == null) {\n                // Table#nullifyLink() does not support default value. Just using Row.\n                row.nullifyLink(columnInfo.columnObjectWithoutPkColKey);\n                return;\n            }\n            proxyState.checkValidObject(value);\n            row.getTable().setLink(columnInfo.columnObjectWithoutPkColKey, row.getObjectKey(), ((RealmObjectProxy) value).realmGet$proxyState().getRow$realm().getObjectKey(), true);\n            return;\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        if (value == null) {\n            proxyState.getRow$realm().nullifyLink(columnInfo.columnObjectWithoutPkColKey);\n            return;\n        }\n        proxyState.checkValidObject(value);\n        proxyState.getRow$realm().setLink(columnInfo.columnObjectWithoutPkColKey, ((RealmObjectProxy) value).realmGet$proxyState().getRow$realm().getObjectKey());\n    }\n\n    @Override\n    public RealmList<some.test.AllTypes> realmGet$columnRealmList() {\n        proxyState.getRealm$realm().checkIfValid();\n        // use the cached value if available\n        if (columnRealmListRealmList != null) {\n            return columnRealmListRealmList;\n        } else {\n            OsList osList = proxyState.getRow$realm().getModelList(columnInfo.columnRealmListColKey);\n            columnRealmListRealmList = new RealmList<some.test.AllTypes>(some.test.AllTypes.class, osList, proxyState.getRealm$realm());\n            return columnRealmListRealmList;\n        }\n    }\n\n    @Override\n    public void realmSet$columnRealmList(RealmList<some.test.AllTypes> value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            if (proxyState.getExcludeFields$realm().contains(\"columnRealmList\")) {\n                return;\n            }\n            // if the list contains unmanaged RealmObjects, convert them to managed.\n            if (value != null && !value.isManaged()) {\n                final Realm realm = (Realm) proxyState.getRealm$realm();\n                final RealmList<some.test.AllTypes> original = value;\n                value = new RealmList<some.test.AllTypes>();\n                for (some.test.AllTypes item : original) {\n                    if (item == null || RealmObject.isManaged(item)) {\n                        value.add(item);\n                    } else {\n                        value.add(realm.copyToRealmOrUpdate(item));\n                    }\n                }\n            }\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        OsList osList = proxyState.getRow$realm().getModelList(columnInfo.columnRealmListColKey);\n        // For lists of equal lengths, we need to set each element directly as clearing the receiver list can be wrong if the input and target list are the same.\n        if (value != null && value.size() == osList.size()) {\n            int objects = value.size();\n            for (int i = 0; i < objects; i++) {\n                some.test.AllTypes linkedObject = value.get(i);\n                proxyState.checkValidObject(linkedObject);\n                osList.setRow(i, ((RealmObjectProxy) linkedObject).realmGet$proxyState().getRow$realm().getObjectKey());\n            }\n        } else {\n            osList.removeAll();\n            if (value == null) {\n                return;\n            }\n            int objects = value.size();\n            for (int i = 0; i < objects; i++) {\n                some.test.AllTypes linkedObject = value.get(i);\n                proxyState.checkValidObject(linkedObject);\n                osList.addRow(((RealmObjectProxy) linkedObject).realmGet$proxyState().getRow$realm().getObjectKey());\n            }\n        }\n    }\n\n    @Override\n    public RealmList<some.test.Simple> realmGet$columnRealmListNoPk() {\n        proxyState.getRealm$realm().checkIfValid();\n        // use the cached value if available\n        if (columnRealmListNoPkRealmList != null) {\n            return columnRealmListNoPkRealmList;\n        } else {\n            OsList osList = proxyState.getRow$realm().getModelList(columnInfo.columnRealmListNoPkColKey);\n            columnRealmListNoPkRealmList = new RealmList<some.test.Simple>(some.test.Simple.class, osList, proxyState.getRealm$realm());\n            return columnRealmListNoPkRealmList;\n        }\n    }\n\n    @Override\n    public void realmSet$columnRealmListNoPk(RealmList<some.test.Simple> value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            if (proxyState.getExcludeFields$realm().contains(\"columnRealmListNoPk\")) {\n                return;\n            }\n            // if the list contains unmanaged RealmObjects, convert them to managed.\n            if (value != null && !value.isManaged()) {\n                final Realm realm = (Realm) proxyState.getRealm$realm();\n                final RealmList<some.test.Simple> original = value;\n                value = new RealmList<some.test.Simple>();\n                for (some.test.Simple item : original) {\n                    if (item == null || RealmObject.isManaged(item)) {\n                        value.add(item);\n                    } else {\n                        value.add(realm.copyToRealm(item));\n                    }\n                }\n            }\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        OsList osList = proxyState.getRow$realm().getModelList(columnInfo.columnRealmListNoPkColKey);\n        // For lists of equal lengths, we need to set each element directly as clearing the receiver list can be wrong if the input and target list are the same.\n        if (value != null && value.size() == osList.size()) {\n            int objects = value.size();\n            for (int i = 0; i < objects; i++) {\n                some.test.Simple linkedObject = value.get(i);\n                proxyState.checkValidObject(linkedObject);\n                osList.setRow(i, ((RealmObjectProxy) linkedObject).realmGet$proxyState().getRow$realm().getObjectKey());\n            }\n        } else {\n            osList.removeAll();\n            if (value == null) {\n                return;\n            }\n            int objects = value.size();\n            for (int i = 0; i < objects; i++) {\n                some.test.Simple linkedObject = value.get(i);\n                proxyState.checkValidObject(linkedObject);\n                osList.addRow(((RealmObjectProxy) linkedObject).realmGet$proxyState().getRow$realm().getObjectKey());\n            }\n        }\n    }\n\n    @Override\n    public RealmList<some.test.AllTypes> realmGet$columnRealmFinalList() {\n        proxyState.getRealm$realm().checkIfValid();\n        // use the cached value if available\n        if (columnRealmFinalListRealmList != null) {\n            return columnRealmFinalListRealmList;\n        } else {\n            OsList osList = proxyState.getRow$realm().getModelList(columnInfo.columnRealmFinalListColKey);\n            columnRealmFinalListRealmList = new RealmList<some.test.AllTypes>(some.test.AllTypes.class, osList, proxyState.getRealm$realm());\n            return columnRealmFinalListRealmList;\n        }\n    }\n\n    @Override\n    public void realmSet$columnRealmFinalList(RealmList<some.test.AllTypes> value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            if (proxyState.getExcludeFields$realm().contains(\"columnRealmFinalList\")) {\n                return;\n            }\n            // if the list contains unmanaged RealmObjects, convert them to managed.\n            if (value != null && !value.isManaged()) {\n                final Realm realm = (Realm) proxyState.getRealm$realm();\n                final RealmList<some.test.AllTypes> original = value;\n                value = new RealmList<some.test.AllTypes>();\n                for (some.test.AllTypes item : original) {\n                    if (item == null || RealmObject.isManaged(item)) {\n                        value.add(item);\n                    } else {\n                        value.add(realm.copyToRealmOrUpdate(item));\n                    }\n                }\n            }\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        OsList osList = proxyState.getRow$realm().getModelList(columnInfo.columnRealmFinalListColKey);\n        // For lists of equal lengths, we need to set each element directly as clearing the receiver list can be wrong if the input and target list are the same.\n        if (value != null && value.size() == osList.size()) {\n            int objects = value.size();\n            for (int i = 0; i < objects; i++) {\n                some.test.AllTypes linkedObject = value.get(i);\n                proxyState.checkValidObject(linkedObject);\n                osList.setRow(i, ((RealmObjectProxy) linkedObject).realmGet$proxyState().getRow$realm().getObjectKey());\n            }\n        } else {\n            osList.removeAll();\n            if (value == null) {\n                return;\n            }\n            int objects = value.size();\n            for (int i = 0; i < objects; i++) {\n                some.test.AllTypes linkedObject = value.get(i);\n                proxyState.checkValidObject(linkedObject);\n                osList.addRow(((RealmObjectProxy) linkedObject).realmGet$proxyState().getRow$realm().getObjectKey());\n            }\n        }\n    }\n\n    @Override\n    public RealmList<some.test.Simple> realmGet$columnRealmFinalListNoPk() {\n        proxyState.getRealm$realm().checkIfValid();\n        // use the cached value if available\n        if (columnRealmFinalListNoPkRealmList != null) {\n            return columnRealmFinalListNoPkRealmList;\n        } else {\n            OsList osList = proxyState.getRow$realm().getModelList(columnInfo.columnRealmFinalListNoPkColKey);\n            columnRealmFinalListNoPkRealmList = new RealmList<some.test.Simple>(some.test.Simple.class, osList, proxyState.getRealm$realm());\n            return columnRealmFinalListNoPkRealmList;\n        }\n    }\n\n    @Override\n    public void realmSet$columnRealmFinalListNoPk(RealmList<some.test.Simple> value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            if (proxyState.getExcludeFields$realm().contains(\"columnRealmFinalListNoPk\")) {\n                return;\n            }\n            // if the list contains unmanaged RealmObjects, convert them to managed.\n            if (value != null && !value.isManaged()) {\n                final Realm realm = (Realm) proxyState.getRealm$realm();\n                final RealmList<some.test.Simple> original = value;\n                value = new RealmList<some.test.Simple>();\n                for (some.test.Simple item : original) {\n                    if (item == null || RealmObject.isManaged(item)) {\n                        value.add(item);\n                    } else {\n                        value.add(realm.copyToRealm(item));\n                    }\n                }\n            }\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        OsList osList = proxyState.getRow$realm().getModelList(columnInfo.columnRealmFinalListNoPkColKey);\n        // For lists of equal lengths, we need to set each element directly as clearing the receiver list can be wrong if the input and target list are the same.\n        if (value != null && value.size() == osList.size()) {\n            int objects = value.size();\n            for (int i = 0; i < objects; i++) {\n                some.test.Simple linkedObject = value.get(i);\n                proxyState.checkValidObject(linkedObject);\n                osList.setRow(i, ((RealmObjectProxy) linkedObject).realmGet$proxyState().getRow$realm().getObjectKey());\n            }\n        } else {\n            osList.removeAll();\n            if (value == null) {\n                return;\n            }\n            int objects = value.size();\n            for (int i = 0; i < objects; i++) {\n                some.test.Simple linkedObject = value.get(i);\n                proxyState.checkValidObject(linkedObject);\n                osList.addRow(((RealmObjectProxy) linkedObject).realmGet$proxyState().getRow$realm().getObjectKey());\n            }\n        }\n    }\n\n    @Override\n    public RealmList<String> realmGet$columnStringList() {\n        proxyState.getRealm$realm().checkIfValid();\n        // use the cached value if available\n        if (columnStringListRealmList != null) {\n            return columnStringListRealmList;\n        } else {\n            OsList osList = proxyState.getRow$realm().getValueList(columnInfo.columnStringListColKey, RealmFieldType.STRING_LIST);\n            columnStringListRealmList = new RealmList<java.lang.String>(java.lang.String.class, osList, proxyState.getRealm$realm());\n            return columnStringListRealmList;\n        }\n    }\n\n    @Override\n    public void realmSet$columnStringList(RealmList<String> value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            if (proxyState.getExcludeFields$realm().contains(\"columnStringList\")) {\n                return;\n            }\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        OsList osList = proxyState.getRow$realm().getValueList(columnInfo.columnStringListColKey, RealmFieldType.STRING_LIST);\n        osList.removeAll();\n        if (value == null) {\n            return;\n        }\n        for (java.lang.String item : value) {\n            if (item == null) {\n                osList.addNull();\n            } else {\n                osList.addString(item);\n            }\n        }\n    }\n\n    @Override\n    public RealmList<byte[]> realmGet$columnBinaryList() {\n        proxyState.getRealm$realm().checkIfValid();\n        // use the cached value if available\n        if (columnBinaryListRealmList != null) {\n            return columnBinaryListRealmList;\n        } else {\n            OsList osList = proxyState.getRow$realm().getValueList(columnInfo.columnBinaryListColKey, RealmFieldType.BINARY_LIST);\n            columnBinaryListRealmList = new RealmList<byte[]>(byte[].class, osList, proxyState.getRealm$realm());\n            return columnBinaryListRealmList;\n        }\n    }\n\n    @Override\n    public void realmSet$columnBinaryList(RealmList<byte[]> value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            if (proxyState.getExcludeFields$realm().contains(\"columnBinaryList\")) {\n                return;\n            }\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        OsList osList = proxyState.getRow$realm().getValueList(columnInfo.columnBinaryListColKey, RealmFieldType.BINARY_LIST);\n        osList.removeAll();\n        if (value == null) {\n            return;\n        }\n        for (byte[] item : value) {\n            if (item == null) {\n                osList.addNull();\n            } else {\n                osList.addBinary(item);\n            }\n        }\n    }\n\n    @Override\n    public RealmList<Boolean> realmGet$columnBooleanList() {\n        proxyState.getRealm$realm().checkIfValid();\n        // use the cached value if available\n        if (columnBooleanListRealmList != null) {\n            return columnBooleanListRealmList;\n        } else {\n            OsList osList = proxyState.getRow$realm().getValueList(columnInfo.columnBooleanListColKey, RealmFieldType.BOOLEAN_LIST);\n            columnBooleanListRealmList = new RealmList<java.lang.Boolean>(java.lang.Boolean.class, osList, proxyState.getRealm$realm());\n            return columnBooleanListRealmList;\n        }\n    }\n\n    @Override\n    public void realmSet$columnBooleanList(RealmList<Boolean> value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            if (proxyState.getExcludeFields$realm().contains(\"columnBooleanList\")) {\n                return;\n            }\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        OsList osList = proxyState.getRow$realm().getValueList(columnInfo.columnBooleanListColKey, RealmFieldType.BOOLEAN_LIST);\n        osList.removeAll();\n        if (value == null) {\n            return;\n        }\n        for (java.lang.Boolean item : value) {\n            if (item == null) {\n                osList.addNull();\n            } else {\n                osList.addBoolean(item);\n            }\n        }\n    }\n\n    @Override\n    public RealmList<Long> realmGet$columnLongList() {\n        proxyState.getRealm$realm().checkIfValid();\n        // use the cached value if available\n        if (columnLongListRealmList != null) {\n            return columnLongListRealmList;\n        } else {\n            OsList osList = proxyState.getRow$realm().getValueList(columnInfo.columnLongListColKey, RealmFieldType.INTEGER_LIST);\n            columnLongListRealmList = new RealmList<java.lang.Long>(java.lang.Long.class, osList, proxyState.getRealm$realm());\n            return columnLongListRealmList;\n        }\n    }\n\n    @Override\n    public void realmSet$columnLongList(RealmList<Long> value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            if (proxyState.getExcludeFields$realm().contains(\"columnLongList\")) {\n                return;\n            }\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        OsList osList = proxyState.getRow$realm().getValueList(columnInfo.columnLongListColKey, RealmFieldType.INTEGER_LIST);\n        osList.removeAll();\n        if (value == null) {\n            return;\n        }\n        for (java.lang.Long item : value) {\n            if (item == null) {\n                osList.addNull();\n            } else {\n                osList.addLong(item.longValue());\n            }\n        }\n    }\n\n    @Override\n    public RealmList<Integer> realmGet$columnIntegerList() {\n        proxyState.getRealm$realm().checkIfValid();\n        // use the cached value if available\n        if (columnIntegerListRealmList != null) {\n            return columnIntegerListRealmList;\n        } else {\n            OsList osList = proxyState.getRow$realm().getValueList(columnInfo.columnIntegerListColKey, RealmFieldType.INTEGER_LIST);\n            columnIntegerListRealmList = new RealmList<java.lang.Integer>(java.lang.Integer.class, osList, proxyState.getRealm$realm());\n            return columnIntegerListRealmList;\n        }\n    }\n\n    @Override\n    public void realmSet$columnIntegerList(RealmList<Integer> value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            if (proxyState.getExcludeFields$realm().contains(\"columnIntegerList\")) {\n                return;\n            }\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        OsList osList = proxyState.getRow$realm().getValueList(columnInfo.columnIntegerListColKey, RealmFieldType.INTEGER_LIST);\n        osList.removeAll();\n        if (value == null) {\n            return;\n        }\n        for (java.lang.Integer item : value) {\n            if (item == null) {\n                osList.addNull();\n            } else {\n                osList.addLong(item.longValue());\n            }\n        }\n    }\n\n    @Override\n    public RealmList<Short> realmGet$columnShortList() {\n        proxyState.getRealm$realm().checkIfValid();\n        // use the cached value if available\n        if (columnShortListRealmList != null) {\n            return columnShortListRealmList;\n        } else {\n            OsList osList = proxyState.getRow$realm().getValueList(columnInfo.columnShortListColKey, RealmFieldType.INTEGER_LIST);\n            columnShortListRealmList = new RealmList<java.lang.Short>(java.lang.Short.class, osList, proxyState.getRealm$realm());\n            return columnShortListRealmList;\n        }\n    }\n\n    @Override\n    public void realmSet$columnShortList(RealmList<Short> value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            if (proxyState.getExcludeFields$realm().contains(\"columnShortList\")) {\n                return;\n            }\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        OsList osList = proxyState.getRow$realm().getValueList(columnInfo.columnShortListColKey, RealmFieldType.INTEGER_LIST);\n        osList.removeAll();\n        if (value == null) {\n            return;\n        }\n        for (java.lang.Short item : value) {\n            if (item == null) {\n                osList.addNull();\n            } else {\n                osList.addLong(item.longValue());\n            }\n        }\n    }\n\n    @Override\n    public RealmList<Byte> realmGet$columnByteList() {\n        proxyState.getRealm$realm().checkIfValid();\n        // use the cached value if available\n        if (columnByteListRealmList != null) {\n            return columnByteListRealmList;\n        } else {\n            OsList osList = proxyState.getRow$realm().getValueList(columnInfo.columnByteListColKey, RealmFieldType.INTEGER_LIST);\n            columnByteListRealmList = new RealmList<java.lang.Byte>(java.lang.Byte.class, osList, proxyState.getRealm$realm());\n            return columnByteListRealmList;\n        }\n    }\n\n    @Override\n    public void realmSet$columnByteList(RealmList<Byte> value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            if (proxyState.getExcludeFields$realm().contains(\"columnByteList\")) {\n                return;\n            }\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        OsList osList = proxyState.getRow$realm().getValueList(columnInfo.columnByteListColKey, RealmFieldType.INTEGER_LIST);\n        osList.removeAll();\n        if (value == null) {\n            return;\n        }\n        for (java.lang.Byte item : value) {\n            if (item == null) {\n                osList.addNull();\n            } else {\n                osList.addLong(item.longValue());\n            }\n        }\n    }\n\n    @Override\n    public RealmList<Double> realmGet$columnDoubleList() {\n        proxyState.getRealm$realm().checkIfValid();\n        // use the cached value if available\n        if (columnDoubleListRealmList != null) {\n            return columnDoubleListRealmList;\n        } else {\n            OsList osList = proxyState.getRow$realm().getValueList(columnInfo.columnDoubleListColKey, RealmFieldType.DOUBLE_LIST);\n            columnDoubleListRealmList = new RealmList<java.lang.Double>(java.lang.Double.class, osList, proxyState.getRealm$realm());\n            return columnDoubleListRealmList;\n        }\n    }\n\n    @Override\n    public void realmSet$columnDoubleList(RealmList<Double> value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            if (proxyState.getExcludeFields$realm().contains(\"columnDoubleList\")) {\n                return;\n            }\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        OsList osList = proxyState.getRow$realm().getValueList(columnInfo.columnDoubleListColKey, RealmFieldType.DOUBLE_LIST);\n        osList.removeAll();\n        if (value == null) {\n            return;\n        }\n        for (java.lang.Double item : value) {\n            if (item == null) {\n                osList.addNull();\n            } else {\n                osList.addDouble(item.doubleValue());\n            }\n        }\n    }\n\n    @Override\n    public RealmList<Float> realmGet$columnFloatList() {\n        proxyState.getRealm$realm().checkIfValid();\n        // use the cached value if available\n        if (columnFloatListRealmList != null) {\n            return columnFloatListRealmList;\n        } else {\n            OsList osList = proxyState.getRow$realm().getValueList(columnInfo.columnFloatListColKey, RealmFieldType.FLOAT_LIST);\n            columnFloatListRealmList = new RealmList<java.lang.Float>(java.lang.Float.class, osList, proxyState.getRealm$realm());\n            return columnFloatListRealmList;\n        }\n    }\n\n    @Override\n    public void realmSet$columnFloatList(RealmList<Float> value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            if (proxyState.getExcludeFields$realm().contains(\"columnFloatList\")) {\n                return;\n            }\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        OsList osList = proxyState.getRow$realm().getValueList(columnInfo.columnFloatListColKey, RealmFieldType.FLOAT_LIST);\n        osList.removeAll();\n        if (value == null) {\n            return;\n        }\n        for (java.lang.Float item : value) {\n            if (item == null) {\n                osList.addNull();\n            } else {\n                osList.addFloat(item.floatValue());\n            }\n        }\n    }\n\n    @Override\n    public RealmList<Date> realmGet$columnDateList() {\n        proxyState.getRealm$realm().checkIfValid();\n        // use the cached value if available\n        if (columnDateListRealmList != null) {\n            return columnDateListRealmList;\n        } else {\n            OsList osList = proxyState.getRow$realm().getValueList(columnInfo.columnDateListColKey, RealmFieldType.DATE_LIST);\n            columnDateListRealmList = new RealmList<java.util.Date>(java.util.Date.class, osList, proxyState.getRealm$realm());\n            return columnDateListRealmList;\n        }\n    }\n\n    @Override\n    public void realmSet$columnDateList(RealmList<Date> value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            if (proxyState.getExcludeFields$realm().contains(\"columnDateList\")) {\n                return;\n            }\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        OsList osList = proxyState.getRow$realm().getValueList(columnInfo.columnDateListColKey, RealmFieldType.DATE_LIST);\n        osList.removeAll();\n        if (value == null) {\n            return;\n        }\n        for (java.util.Date item : value) {\n            if (item == null) {\n                osList.addNull();\n            } else {\n                osList.addDate(item);\n            }\n        }\n    }\n\n    @Override\n    public RealmList<org.bson.types.Decimal128> realmGet$columnDecimal128List() {\n        proxyState.getRealm$realm().checkIfValid();\n        // use the cached value if available\n        if (columnDecimal128ListRealmList != null) {\n            return columnDecimal128ListRealmList;\n        } else {\n            OsList osList = proxyState.getRow$realm().getValueList(columnInfo.columnDecimal128ListColKey, RealmFieldType.DECIMAL128_LIST);\n            columnDecimal128ListRealmList = new RealmList<org.bson.types.Decimal128>(org.bson.types.Decimal128.class, osList, proxyState.getRealm$realm());\n            return columnDecimal128ListRealmList;\n        }\n    }\n\n    @Override\n    public void realmSet$columnDecimal128List(RealmList<org.bson.types.Decimal128> value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            if (proxyState.getExcludeFields$realm().contains(\"columnDecimal128List\")) {\n                return;\n            }\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        OsList osList = proxyState.getRow$realm().getValueList(columnInfo.columnDecimal128ListColKey, RealmFieldType.DECIMAL128_LIST);\n        osList.removeAll();\n        if (value == null) {\n            return;\n        }\n        for (org.bson.types.Decimal128 item : value) {\n            if (item == null) {\n                osList.addNull();\n            } else {\n                osList.addDecimal128(item);\n            }\n        }\n    }\n\n    @Override\n    public RealmList<org.bson.types.ObjectId> realmGet$columnObjectIdList() {\n        proxyState.getRealm$realm().checkIfValid();\n        // use the cached value if available\n        if (columnObjectIdListRealmList != null) {\n            return columnObjectIdListRealmList;\n        } else {\n            OsList osList = proxyState.getRow$realm().getValueList(columnInfo.columnObjectIdListColKey, RealmFieldType.OBJECT_ID_LIST);\n            columnObjectIdListRealmList = new RealmList<org.bson.types.ObjectId>(org.bson.types.ObjectId.class, osList, proxyState.getRealm$realm());\n            return columnObjectIdListRealmList;\n        }\n    }\n\n    @Override\n    public void realmSet$columnObjectIdList(RealmList<org.bson.types.ObjectId> value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            if (proxyState.getExcludeFields$realm().contains(\"columnObjectIdList\")) {\n                return;\n            }\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        OsList osList = proxyState.getRow$realm().getValueList(columnInfo.columnObjectIdListColKey, RealmFieldType.OBJECT_ID_LIST);\n        osList.removeAll();\n        if (value == null) {\n            return;\n        }\n        for (org.bson.types.ObjectId item : value) {\n            if (item == null) {\n                osList.addNull();\n            } else {\n                osList.addObjectId(item);\n            }\n        }\n    }\n\n    @Override\n    public RealmList<java.util.UUID> realmGet$columnUUIDList() {\n        proxyState.getRealm$realm().checkIfValid();\n        // use the cached value if available\n        if (columnUUIDListRealmList != null) {\n            return columnUUIDListRealmList;\n        } else {\n            OsList osList = proxyState.getRow$realm().getValueList(columnInfo.columnUUIDListColKey, RealmFieldType.UUID_LIST);\n            columnUUIDListRealmList = new RealmList<java.util.UUID>(java.util.UUID.class, osList, proxyState.getRealm$realm());\n            return columnUUIDListRealmList;\n        }\n    }\n\n    @Override\n    public void realmSet$columnUUIDList(RealmList<java.util.UUID> value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            if (proxyState.getExcludeFields$realm().contains(\"columnUUIDList\")) {\n                return;\n            }\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        OsList osList = proxyState.getRow$realm().getValueList(columnInfo.columnUUIDListColKey, RealmFieldType.UUID_LIST);\n        osList.removeAll();\n        if (value == null) {\n            return;\n        }\n        for (java.util.UUID item : value) {\n            if (item == null) {\n                osList.addNull();\n            } else {\n                osList.addUUID(item);\n            }\n        }\n    }\n\n    @Override\n    public RealmList<RealmAny> realmGet$columnRealmAnyList() {\n        proxyState.getRealm$realm().checkIfValid();\n        // use the cached value if available\n        if (columnRealmAnyListRealmList != null) {\n            return columnRealmAnyListRealmList;\n        } else {\n            OsList osList = proxyState.getRow$realm().getValueList(columnInfo.columnRealmAnyListColKey, RealmFieldType.MIXED_LIST);\n            columnRealmAnyListRealmList = new RealmList<io.realm.RealmAny>(io.realm.RealmAny.class, osList, proxyState.getRealm$realm());\n            return columnRealmAnyListRealmList;\n        }\n    }\n\n    @Override\n    public void realmSet$columnRealmAnyList(RealmList<RealmAny> value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            if (proxyState.getExcludeFields$realm().contains(\"columnRealmAnyList\")) {\n                return;\n            }\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        OsList osList = proxyState.getRow$realm().getValueList(columnInfo.columnRealmAnyListColKey, RealmFieldType.MIXED_LIST);\n        if (value != null && !value.isManaged()) {\n            final Realm realm = (Realm) proxyState.getRealm$realm();\n            final RealmList<RealmAny> original = value;\n            value = new RealmList<RealmAny>();\n            for (int i = 0; i < original.size(); i++) {\n                value.add(ProxyUtils.copyToRealmIfNeeded(proxyState, original.get(i)));\n            }\n        }\n        osList.removeAll();\n        if (value == null) {\n            return;\n        }\n        for (io.realm.RealmAny item : value) {\n            if (item == null) {\n                osList.addNull();\n            } else {\n                osList.addRealmAny(item.getNativePtr());\n            }\n        }\n    }\n\n    @Override\n    public RealmDictionary<some.test.AllTypes> realmGet$columnRealmDictionary() {\n        proxyState.getRealm$realm().checkIfValid();\n        // use the cached value if available\n        if (columnRealmDictionaryRealmDictionary != null) {\n            return columnRealmDictionaryRealmDictionary;\n        } else {\n            OsMap osMap = proxyState.getRow$realm().getModelMap(columnInfo.columnRealmDictionaryColKey);\n            columnRealmDictionaryRealmDictionary = new RealmDictionary<some.test.AllTypes>(proxyState.getRealm$realm(), osMap, some.test.AllTypes.class);\n            return columnRealmDictionaryRealmDictionary;\n        }\n    }\n\n    @Override\n    public void realmSet$columnRealmDictionary(RealmDictionary<some.test.AllTypes> value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            if (proxyState.getExcludeFields$realm().contains(\"columnRealmDictionary\")) {\n                return;\n            }\n            // if the dictionary contains unmanaged RealmModel instances, convert them to managed.\n            if (value != null && !value.isManaged()) {\n                final Realm realm = (Realm) proxyState.getRealm$realm();\n                final RealmDictionary<some.test.AllTypes> original = value;\n                value = new RealmDictionary<some.test.AllTypes>();\n                for (java.util.Map.Entry<String, some.test.AllTypes> entry : original.entrySet()) {\n                    String entryKey = entry.getKey();\n                    some.test.AllTypes entryValue = entry.getValue();\n                    if (entryValue == null || RealmObject.isManaged(entryValue)) {\n                        value.put(entryKey, entryValue);\n                    } else {\n                        value.put(entryKey, realm.copyToRealmOrUpdate(entryValue));\n                    }\n                }\n            }\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        OsMap osMap = proxyState.getRow$realm().getModelMap(columnInfo.columnRealmDictionaryColKey);\n        if (value == null) {\n            return;\n        }\n        osMap.clear();\n        for (java.util.Map.Entry<String, some.test.AllTypes> item : value.entrySet()) {\n            String entryKey = item.getKey();\n            some.test.AllTypes entryValue = item.getValue();\n            if (entryValue == null) {\n                osMap.put(entryKey, null);\n            } else {\n                proxyState.checkValidObject(entryValue);\n                osMap.putRow(entryKey, ((RealmObjectProxy) entryValue).realmGet$proxyState().getRow$realm().getObjectKey());\n            }\n        }\n    }\n\n    @Override\n    public RealmDictionary<Boolean> realmGet$columnBooleanDictionary() {\n        proxyState.getRealm$realm().checkIfValid();\n        // use the cached value if available\n        if (columnBooleanDictionaryRealmDictionary != null) {\n            return columnBooleanDictionaryRealmDictionary;\n        } else {\n            OsMap osMap = proxyState.getRow$realm().getValueMap(columnInfo.columnBooleanDictionaryColKey, RealmFieldType.STRING_TO_BOOLEAN_MAP);\n            columnBooleanDictionaryRealmDictionary = new RealmDictionary<java.lang.Boolean>(proxyState.getRealm$realm(), osMap, java.lang.Boolean.class);\n            return columnBooleanDictionaryRealmDictionary;\n        }\n    }\n\n    @Override\n    public void realmSet$columnBooleanDictionary(RealmDictionary<Boolean> value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            if (proxyState.getExcludeFields$realm().contains(\"columnBooleanDictionary\")) {\n                return;\n            }\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        OsMap osMap = proxyState.getRow$realm().getValueMap(columnInfo.columnBooleanDictionaryColKey, RealmFieldType.STRING_TO_BOOLEAN_MAP);\n        if (value == null) {\n            return;\n        }\n        osMap.clear();\n        for (java.util.Map.Entry<String, java.lang.Boolean> item : value.entrySet()) {\n            String entryKey = item.getKey();\n            java.lang.Boolean entryValue = item.getValue();\n            osMap.put(entryKey, entryValue);\n        }\n    }\n\n    @Override\n    public RealmDictionary<String> realmGet$columnStringDictionary() {\n        proxyState.getRealm$realm().checkIfValid();\n        // use the cached value if available\n        if (columnStringDictionaryRealmDictionary != null) {\n            return columnStringDictionaryRealmDictionary;\n        } else {\n            OsMap osMap = proxyState.getRow$realm().getValueMap(columnInfo.columnStringDictionaryColKey, RealmFieldType.STRING_TO_STRING_MAP);\n            columnStringDictionaryRealmDictionary = new RealmDictionary<java.lang.String>(proxyState.getRealm$realm(), osMap, java.lang.String.class);\n            return columnStringDictionaryRealmDictionary;\n        }\n    }\n\n    @Override\n    public void realmSet$columnStringDictionary(RealmDictionary<String> value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            if (proxyState.getExcludeFields$realm().contains(\"columnStringDictionary\")) {\n                return;\n            }\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        OsMap osMap = proxyState.getRow$realm().getValueMap(columnInfo.columnStringDictionaryColKey, RealmFieldType.STRING_TO_STRING_MAP);\n        if (value == null) {\n            return;\n        }\n        osMap.clear();\n        for (java.util.Map.Entry<String, java.lang.String> item : value.entrySet()) {\n            String entryKey = item.getKey();\n            java.lang.String entryValue = item.getValue();\n            osMap.put(entryKey, entryValue);\n        }\n    }\n\n    @Override\n    public RealmDictionary<Integer> realmGet$columnIntegerDictionary() {\n        proxyState.getRealm$realm().checkIfValid();\n        // use the cached value if available\n        if (columnIntegerDictionaryRealmDictionary != null) {\n            return columnIntegerDictionaryRealmDictionary;\n        } else {\n            OsMap osMap = proxyState.getRow$realm().getValueMap(columnInfo.columnIntegerDictionaryColKey, RealmFieldType.STRING_TO_INTEGER_MAP);\n            columnIntegerDictionaryRealmDictionary = new RealmDictionary<java.lang.Integer>(proxyState.getRealm$realm(), osMap, java.lang.Integer.class);\n            return columnIntegerDictionaryRealmDictionary;\n        }\n    }\n\n    @Override\n    public void realmSet$columnIntegerDictionary(RealmDictionary<Integer> value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            if (proxyState.getExcludeFields$realm().contains(\"columnIntegerDictionary\")) {\n                return;\n            }\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        OsMap osMap = proxyState.getRow$realm().getValueMap(columnInfo.columnIntegerDictionaryColKey, RealmFieldType.STRING_TO_INTEGER_MAP);\n        if (value == null) {\n            return;\n        }\n        osMap.clear();\n        for (java.util.Map.Entry<String, java.lang.Integer> item : value.entrySet()) {\n            String entryKey = item.getKey();\n            java.lang.Integer entryValue = item.getValue();\n            osMap.put(entryKey, entryValue);\n        }\n    }\n\n    @Override\n    public RealmDictionary<Float> realmGet$columnFloatDictionary() {\n        proxyState.getRealm$realm().checkIfValid();\n        // use the cached value if available\n        if (columnFloatDictionaryRealmDictionary != null) {\n            return columnFloatDictionaryRealmDictionary;\n        } else {\n            OsMap osMap = proxyState.getRow$realm().getValueMap(columnInfo.columnFloatDictionaryColKey, RealmFieldType.STRING_TO_FLOAT_MAP);\n            columnFloatDictionaryRealmDictionary = new RealmDictionary<java.lang.Float>(proxyState.getRealm$realm(), osMap, java.lang.Float.class);\n            return columnFloatDictionaryRealmDictionary;\n        }\n    }\n\n    @Override\n    public void realmSet$columnFloatDictionary(RealmDictionary<Float> value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            if (proxyState.getExcludeFields$realm().contains(\"columnFloatDictionary\")) {\n                return;\n            }\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        OsMap osMap = proxyState.getRow$realm().getValueMap(columnInfo.columnFloatDictionaryColKey, RealmFieldType.STRING_TO_FLOAT_MAP);\n        if (value == null) {\n            return;\n        }\n        osMap.clear();\n        for (java.util.Map.Entry<String, java.lang.Float> item : value.entrySet()) {\n            String entryKey = item.getKey();\n            java.lang.Float entryValue = item.getValue();\n            osMap.put(entryKey, entryValue);\n        }\n    }\n\n    @Override\n    public RealmDictionary<Long> realmGet$columnLongDictionary() {\n        proxyState.getRealm$realm().checkIfValid();\n        // use the cached value if available\n        if (columnLongDictionaryRealmDictionary != null) {\n            return columnLongDictionaryRealmDictionary;\n        } else {\n            OsMap osMap = proxyState.getRow$realm().getValueMap(columnInfo.columnLongDictionaryColKey, RealmFieldType.STRING_TO_INTEGER_MAP);\n            columnLongDictionaryRealmDictionary = new RealmDictionary<java.lang.Long>(proxyState.getRealm$realm(), osMap, java.lang.Long.class);\n            return columnLongDictionaryRealmDictionary;\n        }\n    }\n\n    @Override\n    public void realmSet$columnLongDictionary(RealmDictionary<Long> value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            if (proxyState.getExcludeFields$realm().contains(\"columnLongDictionary\")) {\n                return;\n            }\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        OsMap osMap = proxyState.getRow$realm().getValueMap(columnInfo.columnLongDictionaryColKey, RealmFieldType.STRING_TO_INTEGER_MAP);\n        if (value == null) {\n            return;\n        }\n        osMap.clear();\n        for (java.util.Map.Entry<String, java.lang.Long> item : value.entrySet()) {\n            String entryKey = item.getKey();\n            java.lang.Long entryValue = item.getValue();\n            osMap.put(entryKey, entryValue);\n        }\n    }\n\n    @Override\n    public RealmDictionary<Short> realmGet$columnShortDictionary() {\n        proxyState.getRealm$realm().checkIfValid();\n        // use the cached value if available\n        if (columnShortDictionaryRealmDictionary != null) {\n            return columnShortDictionaryRealmDictionary;\n        } else {\n            OsMap osMap = proxyState.getRow$realm().getValueMap(columnInfo.columnShortDictionaryColKey, RealmFieldType.STRING_TO_INTEGER_MAP);\n            columnShortDictionaryRealmDictionary = new RealmDictionary<java.lang.Short>(proxyState.getRealm$realm(), osMap, java.lang.Short.class);\n            return columnShortDictionaryRealmDictionary;\n        }\n    }\n\n    @Override\n    public void realmSet$columnShortDictionary(RealmDictionary<Short> value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            if (proxyState.getExcludeFields$realm().contains(\"columnShortDictionary\")) {\n                return;\n            }\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        OsMap osMap = proxyState.getRow$realm().getValueMap(columnInfo.columnShortDictionaryColKey, RealmFieldType.STRING_TO_INTEGER_MAP);\n        if (value == null) {\n            return;\n        }\n        osMap.clear();\n        for (java.util.Map.Entry<String, java.lang.Short> item : value.entrySet()) {\n            String entryKey = item.getKey();\n            java.lang.Short entryValue = item.getValue();\n            osMap.put(entryKey, entryValue);\n        }\n    }\n\n    @Override\n    public RealmDictionary<Double> realmGet$columnDoubleDictionary() {\n        proxyState.getRealm$realm().checkIfValid();\n        // use the cached value if available\n        if (columnDoubleDictionaryRealmDictionary != null) {\n            return columnDoubleDictionaryRealmDictionary;\n        } else {\n            OsMap osMap = proxyState.getRow$realm().getValueMap(columnInfo.columnDoubleDictionaryColKey, RealmFieldType.STRING_TO_DOUBLE_MAP);\n            columnDoubleDictionaryRealmDictionary = new RealmDictionary<java.lang.Double>(proxyState.getRealm$realm(), osMap, java.lang.Double.class);\n            return columnDoubleDictionaryRealmDictionary;\n        }\n    }\n\n    @Override\n    public void realmSet$columnDoubleDictionary(RealmDictionary<Double> value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            if (proxyState.getExcludeFields$realm().contains(\"columnDoubleDictionary\")) {\n                return;\n            }\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        OsMap osMap = proxyState.getRow$realm().getValueMap(columnInfo.columnDoubleDictionaryColKey, RealmFieldType.STRING_TO_DOUBLE_MAP);\n        if (value == null) {\n            return;\n        }\n        osMap.clear();\n        for (java.util.Map.Entry<String, java.lang.Double> item : value.entrySet()) {\n            String entryKey = item.getKey();\n            java.lang.Double entryValue = item.getValue();\n            osMap.put(entryKey, entryValue);\n        }\n    }\n\n    @Override\n    public RealmDictionary<Byte> realmGet$columnByteDictionary() {\n        proxyState.getRealm$realm().checkIfValid();\n        // use the cached value if available\n        if (columnByteDictionaryRealmDictionary != null) {\n            return columnByteDictionaryRealmDictionary;\n        } else {\n            OsMap osMap = proxyState.getRow$realm().getValueMap(columnInfo.columnByteDictionaryColKey, RealmFieldType.STRING_TO_INTEGER_MAP);\n            columnByteDictionaryRealmDictionary = new RealmDictionary<java.lang.Byte>(proxyState.getRealm$realm(), osMap, java.lang.Byte.class);\n            return columnByteDictionaryRealmDictionary;\n        }\n    }\n\n    @Override\n    public void realmSet$columnByteDictionary(RealmDictionary<Byte> value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            if (proxyState.getExcludeFields$realm().contains(\"columnByteDictionary\")) {\n                return;\n            }\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        OsMap osMap = proxyState.getRow$realm().getValueMap(columnInfo.columnByteDictionaryColKey, RealmFieldType.STRING_TO_INTEGER_MAP);\n        if (value == null) {\n            return;\n        }\n        osMap.clear();\n        for (java.util.Map.Entry<String, java.lang.Byte> item : value.entrySet()) {\n            String entryKey = item.getKey();\n            java.lang.Byte entryValue = item.getValue();\n            osMap.put(entryKey, entryValue);\n        }\n    }\n\n    @Override\n    public RealmDictionary<byte[]> realmGet$columnBinaryDictionary() {\n        proxyState.getRealm$realm().checkIfValid();\n        // use the cached value if available\n        if (columnBinaryDictionaryRealmDictionary != null) {\n            return columnBinaryDictionaryRealmDictionary;\n        } else {\n            OsMap osMap = proxyState.getRow$realm().getValueMap(columnInfo.columnBinaryDictionaryColKey, RealmFieldType.STRING_TO_BINARY_MAP);\n            columnBinaryDictionaryRealmDictionary = new RealmDictionary<byte[]>(proxyState.getRealm$realm(), osMap, byte[].class);\n            return columnBinaryDictionaryRealmDictionary;\n        }\n    }\n\n    @Override\n    public void realmSet$columnBinaryDictionary(RealmDictionary<byte[]> value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            if (proxyState.getExcludeFields$realm().contains(\"columnBinaryDictionary\")) {\n                return;\n            }\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        OsMap osMap = proxyState.getRow$realm().getValueMap(columnInfo.columnBinaryDictionaryColKey, RealmFieldType.STRING_TO_BINARY_MAP);\n        if (value == null) {\n            return;\n        }\n        osMap.clear();\n        for (java.util.Map.Entry<String, byte[]> item : value.entrySet()) {\n            String entryKey = item.getKey();\n            byte[] entryValue = item.getValue();\n            osMap.put(entryKey, entryValue);\n        }\n    }\n\n    @Override\n    public RealmDictionary<Date> realmGet$columnDateDictionary() {\n        proxyState.getRealm$realm().checkIfValid();\n        // use the cached value if available\n        if (columnDateDictionaryRealmDictionary != null) {\n            return columnDateDictionaryRealmDictionary;\n        } else {\n            OsMap osMap = proxyState.getRow$realm().getValueMap(columnInfo.columnDateDictionaryColKey, RealmFieldType.STRING_TO_DATE_MAP);\n            columnDateDictionaryRealmDictionary = new RealmDictionary<java.util.Date>(proxyState.getRealm$realm(), osMap, java.util.Date.class);\n            return columnDateDictionaryRealmDictionary;\n        }\n    }\n\n    @Override\n    public void realmSet$columnDateDictionary(RealmDictionary<Date> value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            if (proxyState.getExcludeFields$realm().contains(\"columnDateDictionary\")) {\n                return;\n            }\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        OsMap osMap = proxyState.getRow$realm().getValueMap(columnInfo.columnDateDictionaryColKey, RealmFieldType.STRING_TO_DATE_MAP);\n        if (value == null) {\n            return;\n        }\n        osMap.clear();\n        for (java.util.Map.Entry<String, java.util.Date> item : value.entrySet()) {\n            String entryKey = item.getKey();\n            java.util.Date entryValue = item.getValue();\n            osMap.put(entryKey, entryValue);\n        }\n    }\n\n    @Override\n    public RealmDictionary<org.bson.types.ObjectId> realmGet$columnObjectIdDictionary() {\n        proxyState.getRealm$realm().checkIfValid();\n        // use the cached value if available\n        if (columnObjectIdDictionaryRealmDictionary != null) {\n            return columnObjectIdDictionaryRealmDictionary;\n        } else {\n            OsMap osMap = proxyState.getRow$realm().getValueMap(columnInfo.columnObjectIdDictionaryColKey, RealmFieldType.STRING_TO_OBJECT_ID_MAP);\n            columnObjectIdDictionaryRealmDictionary = new RealmDictionary<org.bson.types.ObjectId>(proxyState.getRealm$realm(), osMap, org.bson.types.ObjectId.class);\n            return columnObjectIdDictionaryRealmDictionary;\n        }\n    }\n\n    @Override\n    public void realmSet$columnObjectIdDictionary(RealmDictionary<org.bson.types.ObjectId> value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            if (proxyState.getExcludeFields$realm().contains(\"columnObjectIdDictionary\")) {\n                return;\n            }\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        OsMap osMap = proxyState.getRow$realm().getValueMap(columnInfo.columnObjectIdDictionaryColKey, RealmFieldType.STRING_TO_OBJECT_ID_MAP);\n        if (value == null) {\n            return;\n        }\n        osMap.clear();\n        for (java.util.Map.Entry<String, org.bson.types.ObjectId> item : value.entrySet()) {\n            String entryKey = item.getKey();\n            org.bson.types.ObjectId entryValue = item.getValue();\n            osMap.put(entryKey, entryValue);\n        }\n    }\n\n    @Override\n    public RealmDictionary<java.util.UUID> realmGet$columnUUIDDictionary() {\n        proxyState.getRealm$realm().checkIfValid();\n        // use the cached value if available\n        if (columnUUIDDictionaryRealmDictionary != null) {\n            return columnUUIDDictionaryRealmDictionary;\n        } else {\n            OsMap osMap = proxyState.getRow$realm().getValueMap(columnInfo.columnUUIDDictionaryColKey, RealmFieldType.STRING_TO_UUID_MAP);\n            columnUUIDDictionaryRealmDictionary = new RealmDictionary<java.util.UUID>(proxyState.getRealm$realm(), osMap, java.util.UUID.class);\n            return columnUUIDDictionaryRealmDictionary;\n        }\n    }\n\n    @Override\n    public void realmSet$columnUUIDDictionary(RealmDictionary<java.util.UUID> value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            if (proxyState.getExcludeFields$realm().contains(\"columnUUIDDictionary\")) {\n                return;\n            }\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        OsMap osMap = proxyState.getRow$realm().getValueMap(columnInfo.columnUUIDDictionaryColKey, RealmFieldType.STRING_TO_UUID_MAP);\n        if (value == null) {\n            return;\n        }\n        osMap.clear();\n        for (java.util.Map.Entry<String, java.util.UUID> item : value.entrySet()) {\n            String entryKey = item.getKey();\n            java.util.UUID entryValue = item.getValue();\n            osMap.put(entryKey, entryValue);\n        }\n    }\n\n    @Override\n    public RealmDictionary<org.bson.types.Decimal128> realmGet$columnDecimal128Dictionary() {\n        proxyState.getRealm$realm().checkIfValid();\n        // use the cached value if available\n        if (columnDecimal128DictionaryRealmDictionary != null) {\n            return columnDecimal128DictionaryRealmDictionary;\n        } else {\n            OsMap osMap = proxyState.getRow$realm().getValueMap(columnInfo.columnDecimal128DictionaryColKey, RealmFieldType.STRING_TO_DECIMAL128_MAP);\n            columnDecimal128DictionaryRealmDictionary = new RealmDictionary<org.bson.types.Decimal128>(proxyState.getRealm$realm(), osMap, org.bson.types.Decimal128.class);\n            return columnDecimal128DictionaryRealmDictionary;\n        }\n    }\n\n    @Override\n    public void realmSet$columnDecimal128Dictionary(RealmDictionary<org.bson.types.Decimal128> value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            if (proxyState.getExcludeFields$realm().contains(\"columnDecimal128Dictionary\")) {\n                return;\n            }\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        OsMap osMap = proxyState.getRow$realm().getValueMap(columnInfo.columnDecimal128DictionaryColKey, RealmFieldType.STRING_TO_DECIMAL128_MAP);\n        if (value == null) {\n            return;\n        }\n        osMap.clear();\n        for (java.util.Map.Entry<String, org.bson.types.Decimal128> item : value.entrySet()) {\n            String entryKey = item.getKey();\n            org.bson.types.Decimal128 entryValue = item.getValue();\n            osMap.put(entryKey, entryValue);\n        }\n    }\n\n    @Override\n    public RealmDictionary<RealmAny> realmGet$columnRealmAnyDictionary() {\n        proxyState.getRealm$realm().checkIfValid();\n        // use the cached value if available\n        if (columnRealmAnyDictionaryRealmDictionary != null) {\n            return columnRealmAnyDictionaryRealmDictionary;\n        } else {\n            OsMap osMap = proxyState.getRow$realm().getRealmAnyMap(columnInfo.columnRealmAnyDictionaryColKey);\n            columnRealmAnyDictionaryRealmDictionary = new RealmDictionary<io.realm.RealmAny>(proxyState.getRealm$realm(), osMap, io.realm.RealmAny.class);\n            return columnRealmAnyDictionaryRealmDictionary;\n        }\n    }\n\n    @Override\n    public void realmSet$columnRealmAnyDictionary(RealmDictionary<RealmAny> value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            if (proxyState.getExcludeFields$realm().contains(\"columnRealmAnyDictionary\")) {\n                return;\n            }\n            // if the dictionary contains unmanaged RealmModel instances boxed in RealmAny objects, convert them to managed.\n            if (value != null && !value.isManaged()) {\n                final Realm realm = (Realm) proxyState.getRealm$realm();\n                final RealmDictionary<io.realm.RealmAny> original = value;\n                value = new RealmDictionary<io.realm.RealmAny>();\n                for (java.util.Map.Entry<String, io.realm.RealmAny> item : original.entrySet()) {\n                    String entryKey = item.getKey();\n                    io.realm.RealmAny entryValue = item.getValue();\n                    // ensure (potential) RealmModel instances are copied to Realm if generic type is RealmAny\n                    if (entryValue == null) {\n                        value.put(entryKey, null);\n                    } else if (entryValue.getType() == RealmAny.Type.OBJECT) {\n                        RealmModel realmModel = entryValue.asRealmModel(RealmModel.class);\n                        RealmModel modelFromRealm = realm.copyToRealmOrUpdate(realmModel);\n                        value.put(entryKey, RealmAny.valueOf(modelFromRealm));\n                    } else {\n                        value.put(entryKey, entryValue);\n                    }\n                }\n            }\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        OsMap osMap = proxyState.getRow$realm().getRealmAnyMap(columnInfo.columnRealmAnyDictionaryColKey);\n        if (value == null) {\n            return;\n        }\n        osMap.clear();\n        for (java.util.Map.Entry<String, io.realm.RealmAny> item : value.entrySet()) {\n            String entryKey = item.getKey();\n            io.realm.RealmAny entryValue = item.getValue();\n            if (entryValue == null) {\n                osMap.put(entryKey, null);\n            } else {\n                osMap.putRealmAny(entryKey, ProxyUtils.copyToRealmIfNeeded(proxyState, entryValue).getNativePtr());\n            }\n        }\n    }\n\n    @Override\n    public RealmResults<some.test.AllTypes> realmGet$parentObjects() {\n        BaseRealm realm = proxyState.getRealm$realm();\n        realm.checkIfValid();\n        proxyState.getRow$realm().checkIfAttached();\n        if (parentObjectsBacklinks == null) {\n            parentObjectsBacklinks = RealmResults.createBacklinkResults(realm, proxyState.getRow$realm(), some.test.AllTypes.class, \"columnObject\");\n        }\n        return parentObjectsBacklinks;\n    }\n\n    private static OsObjectSchemaInfo createExpectedObjectSchemaInfo() {\n        OsObjectSchemaInfo.Builder builder = new OsObjectSchemaInfo.Builder(NO_ALIAS, \"AllTypes\", false, 47, 1);\n        builder.addPersistedProperty(NO_ALIAS, \"columnString\", RealmFieldType.STRING, Property.PRIMARY_KEY, !Property.INDEXED, !Property.REQUIRED);\n        builder.addPersistedProperty(NO_ALIAS, \"columnLong\", RealmFieldType.INTEGER, !Property.PRIMARY_KEY, !Property.INDEXED, Property.REQUIRED);\n        builder.addPersistedProperty(NO_ALIAS, \"columnFloat\", RealmFieldType.FLOAT, !Property.PRIMARY_KEY, !Property.INDEXED, Property.REQUIRED);\n        builder.addPersistedProperty(NO_ALIAS, \"columnDouble\", RealmFieldType.DOUBLE, !Property.PRIMARY_KEY, !Property.INDEXED, Property.REQUIRED);\n        builder.addPersistedProperty(NO_ALIAS, \"columnBoolean\", RealmFieldType.BOOLEAN, !Property.PRIMARY_KEY, !Property.INDEXED, Property.REQUIRED);\n        builder.addPersistedProperty(NO_ALIAS, \"columnDecimal128\", RealmFieldType.DECIMAL128, !Property.PRIMARY_KEY, !Property.INDEXED, Property.REQUIRED);\n        builder.addPersistedProperty(NO_ALIAS, \"columnObjectId\", RealmFieldType.OBJECT_ID, !Property.PRIMARY_KEY, !Property.INDEXED, Property.REQUIRED);\n        builder.addPersistedProperty(NO_ALIAS, \"columnUUID\", RealmFieldType.UUID, !Property.PRIMARY_KEY, !Property.INDEXED, Property.REQUIRED);\n        builder.addPersistedProperty(NO_ALIAS, \"columnDate\", RealmFieldType.DATE, !Property.PRIMARY_KEY, !Property.INDEXED, Property.REQUIRED);\n        builder.addPersistedProperty(NO_ALIAS, \"columnRealmAny\", RealmFieldType.MIXED, !Property.PRIMARY_KEY, !Property.INDEXED, !Property.REQUIRED);\n        builder.addPersistedProperty(NO_ALIAS, \"columnBinary\", RealmFieldType.BINARY, !Property.PRIMARY_KEY, !Property.INDEXED, Property.REQUIRED);\n        builder.addPersistedProperty(NO_ALIAS, \"columnMutableRealmInteger\", RealmFieldType.INTEGER, !Property.PRIMARY_KEY, !Property.INDEXED, !Property.REQUIRED);\n        builder.addPersistedLinkProperty(NO_ALIAS, \"columnObject\", RealmFieldType.OBJECT, \"AllTypes\");\n        builder.addPersistedLinkProperty(NO_ALIAS, \"columnObjectWithoutPk\", RealmFieldType.OBJECT, \"Simple\");\n        builder.addPersistedLinkProperty(NO_ALIAS, \"columnRealmList\", RealmFieldType.LIST, \"AllTypes\");\n        builder.addPersistedLinkProperty(NO_ALIAS, \"columnRealmListNoPk\", RealmFieldType.LIST, \"Simple\");\n        builder.addPersistedLinkProperty(NO_ALIAS, \"columnRealmFinalList\", RealmFieldType.LIST, \"AllTypes\");\n        builder.addPersistedLinkProperty(NO_ALIAS, \"columnRealmFinalListNoPk\", RealmFieldType.LIST, \"Simple\");\n        builder.addPersistedValueListProperty(NO_ALIAS, \"columnStringList\", RealmFieldType.STRING_LIST, !Property.REQUIRED);\n        builder.addPersistedValueListProperty(NO_ALIAS, \"columnBinaryList\", RealmFieldType.BINARY_LIST, !Property.REQUIRED);\n        builder.addPersistedValueListProperty(NO_ALIAS, \"columnBooleanList\", RealmFieldType.BOOLEAN_LIST, !Property.REQUIRED);\n        builder.addPersistedValueListProperty(NO_ALIAS, \"columnLongList\", RealmFieldType.INTEGER_LIST, !Property.REQUIRED);\n        builder.addPersistedValueListProperty(NO_ALIAS, \"columnIntegerList\", RealmFieldType.INTEGER_LIST, !Property.REQUIRED);\n        builder.addPersistedValueListProperty(NO_ALIAS, \"columnShortList\", RealmFieldType.INTEGER_LIST, !Property.REQUIRED);\n        builder.addPersistedValueListProperty(NO_ALIAS, \"columnByteList\", RealmFieldType.INTEGER_LIST, !Property.REQUIRED);\n        builder.addPersistedValueListProperty(NO_ALIAS, \"columnDoubleList\", RealmFieldType.DOUBLE_LIST, !Property.REQUIRED);\n        builder.addPersistedValueListProperty(NO_ALIAS, \"columnFloatList\", RealmFieldType.FLOAT_LIST, !Property.REQUIRED);\n        builder.addPersistedValueListProperty(NO_ALIAS, \"columnDateList\", RealmFieldType.DATE_LIST, !Property.REQUIRED);\n        builder.addPersistedValueListProperty(NO_ALIAS, \"columnDecimal128List\", RealmFieldType.DECIMAL128_LIST, !Property.REQUIRED);\n        builder.addPersistedValueListProperty(NO_ALIAS, \"columnObjectIdList\", RealmFieldType.OBJECT_ID_LIST, !Property.REQUIRED);\n        builder.addPersistedValueListProperty(NO_ALIAS, \"columnUUIDList\", RealmFieldType.UUID_LIST, !Property.REQUIRED);\n        builder.addPersistedValueListProperty(NO_ALIAS, \"columnRealmAnyList\", RealmFieldType.MIXED_LIST, !Property.REQUIRED);\n        builder.addPersistedLinkProperty(NO_ALIAS, \"columnRealmDictionary\", RealmFieldType.STRING_TO_LINK_MAP, \"AllTypes\");\n        builder.addPersistedMapProperty(NO_ALIAS, \"columnBooleanDictionary\", RealmFieldType.STRING_TO_BOOLEAN_MAP, !Property.REQUIRED);\n        builder.addPersistedMapProperty(NO_ALIAS, \"columnStringDictionary\", RealmFieldType.STRING_TO_STRING_MAP, !Property.REQUIRED);\n        builder.addPersistedMapProperty(NO_ALIAS, \"columnIntegerDictionary\", RealmFieldType.STRING_TO_INTEGER_MAP, !Property.REQUIRED);\n        builder.addPersistedMapProperty(NO_ALIAS, \"columnFloatDictionary\", RealmFieldType.STRING_TO_FLOAT_MAP, !Property.REQUIRED);\n        builder.addPersistedMapProperty(NO_ALIAS, \"columnLongDictionary\", RealmFieldType.STRING_TO_INTEGER_MAP, !Property.REQUIRED);\n        builder.addPersistedMapProperty(NO_ALIAS, \"columnShortDictionary\", RealmFieldType.STRING_TO_INTEGER_MAP, !Property.REQUIRED);\n        builder.addPersistedMapProperty(NO_ALIAS, \"columnDoubleDictionary\", RealmFieldType.STRING_TO_DOUBLE_MAP, !Property.REQUIRED);\n        builder.addPersistedMapProperty(NO_ALIAS, \"columnByteDictionary\", RealmFieldType.STRING_TO_INTEGER_MAP, !Property.REQUIRED);\n        builder.addPersistedMapProperty(NO_ALIAS, \"columnBinaryDictionary\", RealmFieldType.STRING_TO_BINARY_MAP, !Property.REQUIRED);\n        builder.addPersistedMapProperty(NO_ALIAS, \"columnDateDictionary\", RealmFieldType.STRING_TO_DATE_MAP, !Property.REQUIRED);\n        builder.addPersistedMapProperty(NO_ALIAS, \"columnObjectIdDictionary\", RealmFieldType.STRING_TO_OBJECT_ID_MAP, !Property.REQUIRED);\n        builder.addPersistedMapProperty(NO_ALIAS, \"columnUUIDDictionary\", RealmFieldType.STRING_TO_UUID_MAP, !Property.REQUIRED);\n        builder.addPersistedMapProperty(NO_ALIAS, \"columnDecimal128Dictionary\", RealmFieldType.STRING_TO_DECIMAL128_MAP, !Property.REQUIRED);\n        builder.addPersistedMapProperty(NO_ALIAS, \"columnRealmAnyDictionary\", RealmFieldType.STRING_TO_MIXED_MAP, !Property.REQUIRED);\n        builder.addComputedLinkProperty(\"parentObjects\", \"AllTypes\", \"columnObject\");\n        return builder.build();\n    }\n\n    public static OsObjectSchemaInfo getExpectedObjectSchemaInfo() {\n        return expectedObjectSchemaInfo;\n    }\n\n    public static AllTypesColumnInfo createColumnInfo(OsSchemaInfo schemaInfo) {\n        return new AllTypesColumnInfo(schemaInfo);\n    }\n\n    public static String getSimpleClassName() {\n        return \"AllTypes\";\n    }\n\n    public static final class ClassNameHelper {\n        public static final String INTERNAL_CLASS_NAME = \"AllTypes\";\n    }\n\n    @SuppressWarnings(\"cast\")\n    public static some.test.AllTypes createOrUpdateUsingJsonObject(Realm realm, JSONObject json, boolean update)\n            throws JSONException {\n        throw new UnsupportedOperationException(\"Creation of RealmModels from JSON containing RealmDictionary properties is not supported yet.\");\n    }\n\n    @SuppressWarnings(\"cast\")\n    @TargetApi(Build.VERSION_CODES.HONEYCOMB)\n    public static some.test.AllTypes createUsingJsonStream(Realm realm, JsonReader reader)\n            throws IOException {\n        throw new UnsupportedOperationException(\"Creation of RealmModels from JSON containing RealmDictionary properties is not supported yet.\");\n    }\n\n    static some_test_AllTypesRealmProxy newProxyInstance(BaseRealm realm, Row row) {\n        // Ignore default values to avoid creating unexpected objects from RealmModel/RealmList fields\n        final BaseRealm.RealmObjectContext objectContext = BaseRealm.objectContext.get();\n        objectContext.set(realm, row, realm.getSchema().getColumnInfo(some.test.AllTypes.class), false, Collections.<String>emptyList());\n        io.realm.some_test_AllTypesRealmProxy obj = new io.realm.some_test_AllTypesRealmProxy();\n        objectContext.clear();\n        return obj;\n    }\n\n    public static some.test.AllTypes copyOrUpdate(Realm realm, AllTypesColumnInfo columnInfo, some.test.AllTypes object, boolean update, Map<RealmModel,RealmObjectProxy> cache, Set<ImportFlag> flags) {\n        if (object instanceof RealmObjectProxy && !RealmObject.isFrozen(object) && ((RealmObjectProxy) object).realmGet$proxyState().getRealm$realm() != null) {\n            final BaseRealm otherRealm = ((RealmObjectProxy) object).realmGet$proxyState().getRealm$realm();\n            if (otherRealm.threadId != realm.threadId) {\n                throw new IllegalArgumentException(\"Objects which belong to Realm instances in other threads cannot be copied into this Realm instance.\");\n            }\n            if (otherRealm.getPath().equals(realm.getPath())) {\n                return object;\n            }\n        }\n        final BaseRealm.RealmObjectContext objectContext = BaseRealm.objectContext.get();\n        RealmObjectProxy cachedRealmObject = cache.get(object);\n        if (cachedRealmObject != null) {\n            return (some.test.AllTypes) cachedRealmObject;\n        }\n\n        some.test.AllTypes realmObject = null;\n        boolean canUpdate = update;\n        if (canUpdate) {\n            Table table = realm.getTable(some.test.AllTypes.class);\n            long pkColumnKey = columnInfo.columnStringColKey;\n            String value = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnString();\n            long objKey = Table.NO_MATCH;\n            if (value == null) {\n                objKey = table.findFirstNull(pkColumnKey);\n            } else {\n                objKey = table.findFirstString(pkColumnKey, value);\n            }\n            if (objKey == Table.NO_MATCH) {\n                canUpdate = false;\n            } else {\n                try {\n                    objectContext.set(realm, table.getUncheckedRow(objKey), columnInfo, false, Collections.<String> emptyList());\n                    realmObject = new io.realm.some_test_AllTypesRealmProxy();\n                    cache.put(object, (RealmObjectProxy) realmObject);\n                } finally {\n                    objectContext.clear();\n                }\n            }\n        }\n\n        return (canUpdate) ? update(realm, columnInfo, realmObject, object, cache, flags) : copy(realm, columnInfo, object, update, cache, flags);\n    }\n\n    public static some.test.AllTypes copy(Realm realm, AllTypesColumnInfo columnInfo, some.test.AllTypes newObject, boolean update, Map<RealmModel,RealmObjectProxy> cache, Set<ImportFlag> flags) {\n        RealmObjectProxy cachedRealmObject = cache.get(newObject);\n        if (cachedRealmObject != null) {\n            return (some.test.AllTypes) cachedRealmObject;\n        }\n\n        some_test_AllTypesRealmProxyInterface unmanagedSource = (some_test_AllTypesRealmProxyInterface) newObject;\n\n        Table table = realm.getTable(some.test.AllTypes.class);\n        OsObjectBuilder builder = new OsObjectBuilder(table, flags);\n\n        // Add all non-\"object reference\" fields\n        builder.addString(columnInfo.columnStringColKey, unmanagedSource.realmGet$columnString());\n        builder.addInteger(columnInfo.columnLongColKey, unmanagedSource.realmGet$columnLong());\n        builder.addFloat(columnInfo.columnFloatColKey, unmanagedSource.realmGet$columnFloat());\n        builder.addDouble(columnInfo.columnDoubleColKey, unmanagedSource.realmGet$columnDouble());\n        builder.addBoolean(columnInfo.columnBooleanColKey, unmanagedSource.realmGet$columnBoolean());\n        builder.addDecimal128(columnInfo.columnDecimal128ColKey, unmanagedSource.realmGet$columnDecimal128());\n        builder.addObjectId(columnInfo.columnObjectIdColKey, unmanagedSource.realmGet$columnObjectId());\n        builder.addUUID(columnInfo.columnUUIDColKey, unmanagedSource.realmGet$columnUUID());\n        builder.addDate(columnInfo.columnDateColKey, unmanagedSource.realmGet$columnDate());\n        builder.addByteArray(columnInfo.columnBinaryColKey, unmanagedSource.realmGet$columnBinary());\n        builder.addMutableRealmInteger(columnInfo.columnMutableRealmIntegerColKey, unmanagedSource.realmGet$columnMutableRealmInteger());\n        builder.addStringList(columnInfo.columnStringListColKey, unmanagedSource.realmGet$columnStringList());\n        builder.addByteArrayList(columnInfo.columnBinaryListColKey, unmanagedSource.realmGet$columnBinaryList());\n        builder.addBooleanList(columnInfo.columnBooleanListColKey, unmanagedSource.realmGet$columnBooleanList());\n        builder.addLongList(columnInfo.columnLongListColKey, unmanagedSource.realmGet$columnLongList());\n        builder.addIntegerList(columnInfo.columnIntegerListColKey, unmanagedSource.realmGet$columnIntegerList());\n        builder.addShortList(columnInfo.columnShortListColKey, unmanagedSource.realmGet$columnShortList());\n        builder.addByteList(columnInfo.columnByteListColKey, unmanagedSource.realmGet$columnByteList());\n        builder.addDoubleList(columnInfo.columnDoubleListColKey, unmanagedSource.realmGet$columnDoubleList());\n        builder.addFloatList(columnInfo.columnFloatListColKey, unmanagedSource.realmGet$columnFloatList());\n        builder.addDateList(columnInfo.columnDateListColKey, unmanagedSource.realmGet$columnDateList());\n        builder.addDecimal128List(columnInfo.columnDecimal128ListColKey, unmanagedSource.realmGet$columnDecimal128List());\n        builder.addObjectIdList(columnInfo.columnObjectIdListColKey, unmanagedSource.realmGet$columnObjectIdList());\n        builder.addUUIDList(columnInfo.columnUUIDListColKey, unmanagedSource.realmGet$columnUUIDList());\n        builder.addBooleanValueDictionary(columnInfo.columnBooleanDictionaryColKey, unmanagedSource.realmGet$columnBooleanDictionary());\n        builder.addStringValueDictionary(columnInfo.columnStringDictionaryColKey, unmanagedSource.realmGet$columnStringDictionary());\n        builder.addIntegerValueDictionary(columnInfo.columnIntegerDictionaryColKey, unmanagedSource.realmGet$columnIntegerDictionary());\n        builder.addFloatValueDictionary(columnInfo.columnFloatDictionaryColKey, unmanagedSource.realmGet$columnFloatDictionary());\n        builder.addLongValueDictionary(columnInfo.columnLongDictionaryColKey, unmanagedSource.realmGet$columnLongDictionary());\n        builder.addShortValueDictionary(columnInfo.columnShortDictionaryColKey, unmanagedSource.realmGet$columnShortDictionary());\n        builder.addDoubleValueDictionary(columnInfo.columnDoubleDictionaryColKey, unmanagedSource.realmGet$columnDoubleDictionary());\n        builder.addByteValueDictionary(columnInfo.columnByteDictionaryColKey, unmanagedSource.realmGet$columnByteDictionary());\n        builder.addBinaryValueDictionary(columnInfo.columnBinaryDictionaryColKey, unmanagedSource.realmGet$columnBinaryDictionary());\n        builder.addDateValueDictionary(columnInfo.columnDateDictionaryColKey, unmanagedSource.realmGet$columnDateDictionary());\n        builder.addObjectIdValueDictionary(columnInfo.columnObjectIdDictionaryColKey, unmanagedSource.realmGet$columnObjectIdDictionary());\n        builder.addUUIDValueDictionary(columnInfo.columnUUIDDictionaryColKey, unmanagedSource.realmGet$columnUUIDDictionary());\n        builder.addDecimal128ValueDictionary(columnInfo.columnDecimal128DictionaryColKey, unmanagedSource.realmGet$columnDecimal128Dictionary());\n\n        // Create the underlying object and cache it before setting any object/objectlist references\n        // This will allow us to break any circular dependencies by using the object cache.\n        Row row = builder.createNewObject();\n        io.realm.some_test_AllTypesRealmProxy managedCopy = newProxyInstance(realm, row);\n        cache.put(newObject, managedCopy);\n\n        // Finally add all fields that reference other Realm Objects, either directly or through a list\n        RealmAny columnRealmAnyRealmAny = unmanagedSource.realmGet$columnRealmAny();\n        columnRealmAnyRealmAny = ProxyUtils.copyOrUpdate(columnRealmAnyRealmAny, realm, update, cache, flags);\n        managedCopy.realmSet$columnRealmAny(columnRealmAnyRealmAny);\n\n        some.test.AllTypes columnObjectObj = unmanagedSource.realmGet$columnObject();\n        if (columnObjectObj == null) {\n            managedCopy.realmSet$columnObject(null);\n        } else {\n            some.test.AllTypes cachecolumnObject = (some.test.AllTypes) cache.get(columnObjectObj);\n            if (cachecolumnObject != null) {\n                managedCopy.realmSet$columnObject(cachecolumnObject);\n            } else {\n                managedCopy.realmSet$columnObject(some_test_AllTypesRealmProxy.copyOrUpdate(realm, (some_test_AllTypesRealmProxy.AllTypesColumnInfo) realm.getSchema().getColumnInfo(some.test.AllTypes.class), columnObjectObj, update, cache, flags));\n            }\n        }\n\n        some.test.Simple columnObjectWithoutPkObj = unmanagedSource.realmGet$columnObjectWithoutPk();\n        if (columnObjectWithoutPkObj == null) {\n            managedCopy.realmSet$columnObjectWithoutPk(null);\n        } else {\n            some.test.Simple cachecolumnObjectWithoutPk = (some.test.Simple) cache.get(columnObjectWithoutPkObj);\n            if (cachecolumnObjectWithoutPk != null) {\n                managedCopy.realmSet$columnObjectWithoutPk(cachecolumnObjectWithoutPk);\n            } else {\n                managedCopy.realmSet$columnObjectWithoutPk(some_test_SimpleRealmProxy.copyOrUpdate(realm, (some_test_SimpleRealmProxy.SimpleColumnInfo) realm.getSchema().getColumnInfo(some.test.Simple.class), columnObjectWithoutPkObj, update, cache, flags));\n            }\n        }\n\n        RealmList<some.test.AllTypes> columnRealmListUnmanagedList = unmanagedSource.realmGet$columnRealmList();\n        if (columnRealmListUnmanagedList != null) {\n            RealmList<some.test.AllTypes> columnRealmListManagedList = managedCopy.realmGet$columnRealmList();\n            columnRealmListManagedList.clear();\n            for (int i = 0; i < columnRealmListUnmanagedList.size(); i++) {\n                some.test.AllTypes columnRealmListUnmanagedItem = columnRealmListUnmanagedList.get(i);\n                some.test.AllTypes cachecolumnRealmList = (some.test.AllTypes) cache.get(columnRealmListUnmanagedItem);\n                if (cachecolumnRealmList != null) {\n                    columnRealmListManagedList.add(cachecolumnRealmList);\n                } else {\n                    columnRealmListManagedList.add(some_test_AllTypesRealmProxy.copyOrUpdate(realm, (some_test_AllTypesRealmProxy.AllTypesColumnInfo) realm.getSchema().getColumnInfo(some.test.AllTypes.class), columnRealmListUnmanagedItem, update, cache, flags));\n                }\n            }\n        }\n\n        RealmList<some.test.Simple> columnRealmListNoPkUnmanagedList = unmanagedSource.realmGet$columnRealmListNoPk();\n        if (columnRealmListNoPkUnmanagedList != null) {\n            RealmList<some.test.Simple> columnRealmListNoPkManagedList = managedCopy.realmGet$columnRealmListNoPk();\n            columnRealmListNoPkManagedList.clear();\n            for (int i = 0; i < columnRealmListNoPkUnmanagedList.size(); i++) {\n                some.test.Simple columnRealmListNoPkUnmanagedItem = columnRealmListNoPkUnmanagedList.get(i);\n                some.test.Simple cachecolumnRealmListNoPk = (some.test.Simple) cache.get(columnRealmListNoPkUnmanagedItem);\n                if (cachecolumnRealmListNoPk != null) {\n                    columnRealmListNoPkManagedList.add(cachecolumnRealmListNoPk);\n                } else {\n                    columnRealmListNoPkManagedList.add(some_test_SimpleRealmProxy.copyOrUpdate(realm, (some_test_SimpleRealmProxy.SimpleColumnInfo) realm.getSchema().getColumnInfo(some.test.Simple.class), columnRealmListNoPkUnmanagedItem, update, cache, flags));\n                }\n            }\n        }\n\n        RealmList<some.test.AllTypes> columnRealmFinalListUnmanagedList = unmanagedSource.realmGet$columnRealmFinalList();\n        if (columnRealmFinalListUnmanagedList != null) {\n            RealmList<some.test.AllTypes> columnRealmFinalListManagedList = managedCopy.realmGet$columnRealmFinalList();\n            columnRealmFinalListManagedList.clear();\n            for (int i = 0; i < columnRealmFinalListUnmanagedList.size(); i++) {\n                some.test.AllTypes columnRealmFinalListUnmanagedItem = columnRealmFinalListUnmanagedList.get(i);\n                some.test.AllTypes cachecolumnRealmFinalList = (some.test.AllTypes) cache.get(columnRealmFinalListUnmanagedItem);\n                if (cachecolumnRealmFinalList != null) {\n                    columnRealmFinalListManagedList.add(cachecolumnRealmFinalList);\n                } else {\n                    columnRealmFinalListManagedList.add(some_test_AllTypesRealmProxy.copyOrUpdate(realm, (some_test_AllTypesRealmProxy.AllTypesColumnInfo) realm.getSchema().getColumnInfo(some.test.AllTypes.class), columnRealmFinalListUnmanagedItem, update, cache, flags));\n                }\n            }\n        }\n\n        RealmList<some.test.Simple> columnRealmFinalListNoPkUnmanagedList = unmanagedSource.realmGet$columnRealmFinalListNoPk();\n        if (columnRealmFinalListNoPkUnmanagedList != null) {\n            RealmList<some.test.Simple> columnRealmFinalListNoPkManagedList = managedCopy.realmGet$columnRealmFinalListNoPk();\n            columnRealmFinalListNoPkManagedList.clear();\n            for (int i = 0; i < columnRealmFinalListNoPkUnmanagedList.size(); i++) {\n                some.test.Simple columnRealmFinalListNoPkUnmanagedItem = columnRealmFinalListNoPkUnmanagedList.get(i);\n                some.test.Simple cachecolumnRealmFinalListNoPk = (some.test.Simple) cache.get(columnRealmFinalListNoPkUnmanagedItem);\n                if (cachecolumnRealmFinalListNoPk != null) {\n                    columnRealmFinalListNoPkManagedList.add(cachecolumnRealmFinalListNoPk);\n                } else {\n                    columnRealmFinalListNoPkManagedList.add(some_test_SimpleRealmProxy.copyOrUpdate(realm, (some_test_SimpleRealmProxy.SimpleColumnInfo) realm.getSchema().getColumnInfo(some.test.Simple.class), columnRealmFinalListNoPkUnmanagedItem, update, cache, flags));\n                }\n            }\n        }\n\n        RealmList<RealmAny> columnRealmAnyListUnmanagedList = unmanagedSource.realmGet$columnRealmAnyList();\n        if (columnRealmAnyListUnmanagedList != null) {\n            RealmList<RealmAny> columnRealmAnyListManagedList = managedCopy.realmGet$columnRealmAnyList();\n            columnRealmAnyListManagedList.clear();\n            for (int i = 0; i < columnRealmAnyListUnmanagedList.size(); i++) {\n                RealmAny realmAnyItem = columnRealmAnyListUnmanagedList.get(i);\n                realmAnyItem = ProxyUtils.copyOrUpdate(realmAnyItem, realm, update, cache, flags);\n                columnRealmAnyListManagedList.add(realmAnyItem);\n            }\n        }\n\n        RealmDictionary<some.test.AllTypes> columnRealmDictionaryUnmanagedDictionary = unmanagedSource.realmGet$columnRealmDictionary();\n        if (columnRealmDictionaryUnmanagedDictionary != null) {\n            RealmDictionary<some.test.AllTypes> columnRealmDictionaryManagedDictionary = managedCopy.realmGet$columnRealmDictionary();\n            columnRealmDictionaryManagedDictionary.clear();\n            java.util.Set<java.util.Map.Entry<String, some.test.AllTypes>> entries = columnRealmDictionaryUnmanagedDictionary.entrySet();\n            for (java.util.Map.Entry<String, some.test.AllTypes> entry : entries) {\n                String entryKey = entry.getKey();\n                some.test.AllTypes columnRealmDictionaryUnmanagedEntryValue = entry.getValue();\n                some.test.AllTypes cachecolumnRealmDictionary = (some.test.AllTypes) cache.get(columnRealmDictionaryUnmanagedEntryValue);\n                if (cachecolumnRealmDictionary != null) {\n                    columnRealmDictionaryManagedDictionary.put(entryKey, cachecolumnRealmDictionary);\n                } else {\n                    if (columnRealmDictionaryUnmanagedEntryValue == null) {\n                        columnRealmDictionaryManagedDictionary.put(entryKey, null);\n                    } else {\n                        columnRealmDictionaryManagedDictionary.put(entryKey, some_test_AllTypesRealmProxy.copyOrUpdate(realm, (some_test_AllTypesRealmProxy.AllTypesColumnInfo) realm.getSchema().getColumnInfo(some.test.AllTypes.class), columnRealmDictionaryUnmanagedEntryValue, update, cache, flags));\n                    }\n                }\n            }\n        }\n        RealmDictionary<RealmAny> columnRealmAnyDictionaryUnmanagedDictionary = unmanagedSource.realmGet$columnRealmAnyDictionary();\n        if (columnRealmAnyDictionaryUnmanagedDictionary != null) {\n            RealmDictionary<RealmAny> columnRealmAnyDictionaryManagedDictionary = managedCopy.realmGet$columnRealmAnyDictionary();\n            java.util.Set<java.util.Map.Entry<String, io.realm.RealmAny>> entries = columnRealmAnyDictionaryUnmanagedDictionary.entrySet();\n            java.util.List<String> keys = new java.util.ArrayList<>();\n            java.util.List<Long> realmAnyPointers = new java.util.ArrayList<>();\n            for (java.util.Map.Entry<String, io.realm.RealmAny> entry : entries) {\n                RealmAny realmAnyItem = entry.getValue();\n                realmAnyItem = ProxyUtils.copyOrUpdate(realmAnyItem, realm, update, cache, flags);\n                columnRealmAnyDictionaryManagedDictionary.put(entry.getKey(), realmAnyItem);\n            }\n        }\n\n        return managedCopy;\n    }\n\n    public static long insert(Realm realm, some.test.AllTypes object, Map<RealmModel,Long> cache) {\n        if (object instanceof RealmObjectProxy && !RealmObject.isFrozen(object) && ((RealmObjectProxy) object).realmGet$proxyState().getRealm$realm() != null && ((RealmObjectProxy) object).realmGet$proxyState().getRealm$realm().getPath().equals(realm.getPath())) {\n            return ((RealmObjectProxy) object).realmGet$proxyState().getRow$realm().getObjectKey();\n        }\n        Table table = realm.getTable(some.test.AllTypes.class);\n        long tableNativePtr = table.getNativePtr();\n        AllTypesColumnInfo columnInfo = (AllTypesColumnInfo) realm.getSchema().getColumnInfo(some.test.AllTypes.class);\n        long pkColumnKey = columnInfo.columnStringColKey;\n        String primaryKeyValue = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnString();\n        long objKey = Table.NO_MATCH;\n        if (primaryKeyValue == null) {\n            objKey = Table.nativeFindFirstNull(tableNativePtr, pkColumnKey);\n        } else {\n            objKey = Table.nativeFindFirstString(tableNativePtr, pkColumnKey, primaryKeyValue);\n        }\n        if (objKey == Table.NO_MATCH) {\n            objKey = OsObject.createRowWithPrimaryKey(table, pkColumnKey, primaryKeyValue);\n        } else {\n            Table.throwDuplicatePrimaryKeyException(primaryKeyValue);\n        }\n        cache.put(object, objKey);\n        Table.nativeSetLong(tableNativePtr, columnInfo.columnLongColKey, objKey, ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnLong(), false);\n        Table.nativeSetFloat(tableNativePtr, columnInfo.columnFloatColKey, objKey, ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnFloat(), false);\n        Table.nativeSetDouble(tableNativePtr, columnInfo.columnDoubleColKey, objKey, ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnDouble(), false);\n        Table.nativeSetBoolean(tableNativePtr, columnInfo.columnBooleanColKey, objKey, ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnBoolean(), false);\n        org.bson.types.Decimal128 realmGet$columnDecimal128 = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnDecimal128();\n        if (realmGet$columnDecimal128 != null) {\n            Table.nativeSetDecimal128(tableNativePtr, columnInfo.columnDecimal128ColKey, objKey, realmGet$columnDecimal128.getLow(), realmGet$columnDecimal128.getHigh(), false);\n        }\n        org.bson.types.ObjectId realmGet$columnObjectId = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnObjectId();\n        if (realmGet$columnObjectId != null) {\n            Table.nativeSetObjectId(tableNativePtr, columnInfo.columnObjectIdColKey, objKey, realmGet$columnObjectId.toString(), false);\n        }\n        java.util.UUID realmGet$columnUUID = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnUUID();\n        if (realmGet$columnUUID != null) {\n            Table.nativeSetUUID(tableNativePtr, columnInfo.columnUUIDColKey, objKey, realmGet$columnUUID.toString(), false);\n        }\n        java.util.Date realmGet$columnDate = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnDate();\n        if (realmGet$columnDate != null) {\n            Table.nativeSetTimestamp(tableNativePtr, columnInfo.columnDateColKey, objKey, realmGet$columnDate.getTime(), false);\n        }\n\n        RealmAny columnRealmAnyRealmAny = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnRealmAny();\n        columnRealmAnyRealmAny = ProxyUtils.insert(columnRealmAnyRealmAny, realm, cache);\n        Table.nativeSetRealmAny(tableNativePtr, columnInfo.columnRealmAnyColKey, objKey, columnRealmAnyRealmAny.getNativePtr(), false);\n        byte[] realmGet$columnBinary = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnBinary();\n        if (realmGet$columnBinary != null) {\n            Table.nativeSetByteArray(tableNativePtr, columnInfo.columnBinaryColKey, objKey, realmGet$columnBinary, false);\n        }\n        Long realmGet$columnMutableRealmInteger = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnMutableRealmInteger().get();\n        if (realmGet$columnMutableRealmInteger != null) {\n            Table.nativeSetLong(tableNativePtr, columnInfo.columnMutableRealmIntegerColKey, objKey, realmGet$columnMutableRealmInteger.longValue(), false);\n        }\n\n        some.test.AllTypes columnObjectObj = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnObject();\n        if (columnObjectObj != null) {\n            Long cachecolumnObject = cache.get(columnObjectObj);\n            if (cachecolumnObject == null) {\n                cachecolumnObject = some_test_AllTypesRealmProxy.insert(realm, columnObjectObj, cache);\n            }\n            Table.nativeSetLink(tableNativePtr, columnInfo.columnObjectColKey, objKey, cachecolumnObject, false);\n        }\n\n        some.test.Simple columnObjectWithoutPkObj = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnObjectWithoutPk();\n        if (columnObjectWithoutPkObj != null) {\n            Long cachecolumnObjectWithoutPk = cache.get(columnObjectWithoutPkObj);\n            if (cachecolumnObjectWithoutPk == null) {\n                cachecolumnObjectWithoutPk = some_test_SimpleRealmProxy.insert(realm, columnObjectWithoutPkObj, cache);\n            }\n            Table.nativeSetLink(tableNativePtr, columnInfo.columnObjectWithoutPkColKey, objKey, cachecolumnObjectWithoutPk, false);\n        }\n\n        RealmList<some.test.AllTypes> columnRealmListList = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnRealmList();\n        if (columnRealmListList != null) {\n            OsList columnRealmListOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.columnRealmListColKey);\n            for (some.test.AllTypes columnRealmListItem : columnRealmListList) {\n                Long cacheItemIndexcolumnRealmList = cache.get(columnRealmListItem);\n                if (cacheItemIndexcolumnRealmList == null) {\n                    cacheItemIndexcolumnRealmList = some_test_AllTypesRealmProxy.insert(realm, columnRealmListItem, cache);\n                }\n                columnRealmListOsList.addRow(cacheItemIndexcolumnRealmList);\n            }\n        }\n\n        RealmList<some.test.Simple> columnRealmListNoPkList = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnRealmListNoPk();\n        if (columnRealmListNoPkList != null) {\n            OsList columnRealmListNoPkOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.columnRealmListNoPkColKey);\n            for (some.test.Simple columnRealmListNoPkItem : columnRealmListNoPkList) {\n                Long cacheItemIndexcolumnRealmListNoPk = cache.get(columnRealmListNoPkItem);\n                if (cacheItemIndexcolumnRealmListNoPk == null) {\n                    cacheItemIndexcolumnRealmListNoPk = some_test_SimpleRealmProxy.insert(realm, columnRealmListNoPkItem, cache);\n                }\n                columnRealmListNoPkOsList.addRow(cacheItemIndexcolumnRealmListNoPk);\n            }\n        }\n\n        RealmList<some.test.AllTypes> columnRealmFinalListList = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnRealmFinalList();\n        if (columnRealmFinalListList != null) {\n            OsList columnRealmFinalListOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.columnRealmFinalListColKey);\n            for (some.test.AllTypes columnRealmFinalListItem : columnRealmFinalListList) {\n                Long cacheItemIndexcolumnRealmFinalList = cache.get(columnRealmFinalListItem);\n                if (cacheItemIndexcolumnRealmFinalList == null) {\n                    cacheItemIndexcolumnRealmFinalList = some_test_AllTypesRealmProxy.insert(realm, columnRealmFinalListItem, cache);\n                }\n                columnRealmFinalListOsList.addRow(cacheItemIndexcolumnRealmFinalList);\n            }\n        }\n\n        RealmList<some.test.Simple> columnRealmFinalListNoPkList = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnRealmFinalListNoPk();\n        if (columnRealmFinalListNoPkList != null) {\n            OsList columnRealmFinalListNoPkOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.columnRealmFinalListNoPkColKey);\n            for (some.test.Simple columnRealmFinalListNoPkItem : columnRealmFinalListNoPkList) {\n                Long cacheItemIndexcolumnRealmFinalListNoPk = cache.get(columnRealmFinalListNoPkItem);\n                if (cacheItemIndexcolumnRealmFinalListNoPk == null) {\n                    cacheItemIndexcolumnRealmFinalListNoPk = some_test_SimpleRealmProxy.insert(realm, columnRealmFinalListNoPkItem, cache);\n                }\n                columnRealmFinalListNoPkOsList.addRow(cacheItemIndexcolumnRealmFinalListNoPk);\n            }\n        }\n\n        RealmList<java.lang.String> columnStringListList = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnStringList();\n        if (columnStringListList != null) {\n            OsList columnStringListOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.columnStringListColKey);\n            for (java.lang.String columnStringListItem : columnStringListList) {\n                if (columnStringListItem == null) {\n                    columnStringListOsList.addNull();\n                } else {\n                    columnStringListOsList.addString(columnStringListItem);\n                }\n            }\n        }\n\n        RealmList<byte[]> columnBinaryListList = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnBinaryList();\n        if (columnBinaryListList != null) {\n            OsList columnBinaryListOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.columnBinaryListColKey);\n            for (byte[] columnBinaryListItem : columnBinaryListList) {\n                if (columnBinaryListItem == null) {\n                    columnBinaryListOsList.addNull();\n                } else {\n                    columnBinaryListOsList.addBinary(columnBinaryListItem);\n                }\n            }\n        }\n\n        RealmList<java.lang.Boolean> columnBooleanListList = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnBooleanList();\n        if (columnBooleanListList != null) {\n            OsList columnBooleanListOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.columnBooleanListColKey);\n            for (java.lang.Boolean columnBooleanListItem : columnBooleanListList) {\n                if (columnBooleanListItem == null) {\n                    columnBooleanListOsList.addNull();\n                } else {\n                    columnBooleanListOsList.addBoolean(columnBooleanListItem);\n                }\n            }\n        }\n\n        RealmList<java.lang.Long> columnLongListList = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnLongList();\n        if (columnLongListList != null) {\n            OsList columnLongListOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.columnLongListColKey);\n            for (java.lang.Long columnLongListItem : columnLongListList) {\n                if (columnLongListItem == null) {\n                    columnLongListOsList.addNull();\n                } else {\n                    columnLongListOsList.addLong(columnLongListItem.longValue());\n                }\n            }\n        }\n\n        RealmList<java.lang.Integer> columnIntegerListList = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnIntegerList();\n        if (columnIntegerListList != null) {\n            OsList columnIntegerListOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.columnIntegerListColKey);\n            for (java.lang.Integer columnIntegerListItem : columnIntegerListList) {\n                if (columnIntegerListItem == null) {\n                    columnIntegerListOsList.addNull();\n                } else {\n                    columnIntegerListOsList.addLong(columnIntegerListItem.longValue());\n                }\n            }\n        }\n\n        RealmList<java.lang.Short> columnShortListList = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnShortList();\n        if (columnShortListList != null) {\n            OsList columnShortListOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.columnShortListColKey);\n            for (java.lang.Short columnShortListItem : columnShortListList) {\n                if (columnShortListItem == null) {\n                    columnShortListOsList.addNull();\n                } else {\n                    columnShortListOsList.addLong(columnShortListItem.longValue());\n                }\n            }\n        }\n\n        RealmList<java.lang.Byte> columnByteListList = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnByteList();\n        if (columnByteListList != null) {\n            OsList columnByteListOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.columnByteListColKey);\n            for (java.lang.Byte columnByteListItem : columnByteListList) {\n                if (columnByteListItem == null) {\n                    columnByteListOsList.addNull();\n                } else {\n                    columnByteListOsList.addLong(columnByteListItem.longValue());\n                }\n            }\n        }\n\n        RealmList<java.lang.Double> columnDoubleListList = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnDoubleList();\n        if (columnDoubleListList != null) {\n            OsList columnDoubleListOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.columnDoubleListColKey);\n            for (java.lang.Double columnDoubleListItem : columnDoubleListList) {\n                if (columnDoubleListItem == null) {\n                    columnDoubleListOsList.addNull();\n                } else {\n                    columnDoubleListOsList.addDouble(columnDoubleListItem.doubleValue());\n                }\n            }\n        }\n\n        RealmList<java.lang.Float> columnFloatListList = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnFloatList();\n        if (columnFloatListList != null) {\n            OsList columnFloatListOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.columnFloatListColKey);\n            for (java.lang.Float columnFloatListItem : columnFloatListList) {\n                if (columnFloatListItem == null) {\n                    columnFloatListOsList.addNull();\n                } else {\n                    columnFloatListOsList.addFloat(columnFloatListItem.floatValue());\n                }\n            }\n        }\n\n        RealmList<java.util.Date> columnDateListList = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnDateList();\n        if (columnDateListList != null) {\n            OsList columnDateListOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.columnDateListColKey);\n            for (java.util.Date columnDateListItem : columnDateListList) {\n                if (columnDateListItem == null) {\n                    columnDateListOsList.addNull();\n                } else {\n                    columnDateListOsList.addDate(columnDateListItem);\n                }\n            }\n        }\n\n        RealmList<org.bson.types.Decimal128> columnDecimal128ListList = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnDecimal128List();\n        if (columnDecimal128ListList != null) {\n            OsList columnDecimal128ListOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.columnDecimal128ListColKey);\n            for (org.bson.types.Decimal128 columnDecimal128ListItem : columnDecimal128ListList) {\n                if (columnDecimal128ListItem == null) {\n                    columnDecimal128ListOsList.addNull();\n                } else {\n                    columnDecimal128ListOsList.addDecimal128(columnDecimal128ListItem);\n                }\n            }\n        }\n\n        RealmList<org.bson.types.ObjectId> columnObjectIdListList = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnObjectIdList();\n        if (columnObjectIdListList != null) {\n            OsList columnObjectIdListOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.columnObjectIdListColKey);\n            for (org.bson.types.ObjectId columnObjectIdListItem : columnObjectIdListList) {\n                if (columnObjectIdListItem == null) {\n                    columnObjectIdListOsList.addNull();\n                } else {\n                    columnObjectIdListOsList.addObjectId(columnObjectIdListItem);\n                }\n            }\n        }\n\n        RealmList<java.util.UUID> columnUUIDListList = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnUUIDList();\n        if (columnUUIDListList != null) {\n            OsList columnUUIDListOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.columnUUIDListColKey);\n            for (java.util.UUID columnUUIDListItem : columnUUIDListList) {\n                if (columnUUIDListItem == null) {\n                    columnUUIDListOsList.addNull();\n                } else {\n                    columnUUIDListOsList.addUUID(columnUUIDListItem);\n                }\n            }\n        }\n\n        RealmList<RealmAny> columnRealmAnyListUnmanagedList = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnRealmAnyList();\n        if (columnRealmAnyListUnmanagedList != null) {\n            OsList columnRealmAnyListOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.columnRealmAnyListColKey);\n            for (int i = 0; i < columnRealmAnyListUnmanagedList.size(); i++) {\n                RealmAny realmAnyItem = columnRealmAnyListUnmanagedList.get(i);\n                realmAnyItem = ProxyUtils.insert(realmAnyItem, realm, cache);\n                columnRealmAnyListOsList.addRealmAny(realmAnyItem.getNativePtr());\n            }\n        }\n        RealmDictionary<some.test.AllTypes> columnRealmDictionaryUnmanagedDictionary = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnRealmDictionary();\n        if (columnRealmDictionaryUnmanagedDictionary != null) {\n            OsMap columnRealmDictionaryOsMap = new OsMap(table.getUncheckedRow(objKey), columnInfo.columnRealmDictionaryColKey);\n            java.util.Set<java.util.Map.Entry<String, some.test.AllTypes>> entries = columnRealmDictionaryUnmanagedDictionary.entrySet();\n            for (java.util.Map.Entry<String, some.test.AllTypes> entry : entries) {\n                String entryKey = entry.getKey();\n                some.test.AllTypes columnRealmDictionaryUnmanagedEntryValue = entry.getValue();\n                if(columnRealmDictionaryUnmanagedEntryValue == null) {\n                    columnRealmDictionaryOsMap.put(entryKey, null);\n                } else {\n                    Long cacheItemIndexcolumnRealmDictionary = cache.get(columnRealmDictionaryUnmanagedEntryValue);\n                    if (cacheItemIndexcolumnRealmDictionary == null) {\n                        cacheItemIndexcolumnRealmDictionary = some_test_AllTypesRealmProxy.insert(realm, columnRealmDictionaryUnmanagedEntryValue, cache);\n                    }\n                    columnRealmDictionaryOsMap.putRow(entryKey, cacheItemIndexcolumnRealmDictionary);\n                }\n            }\n        }\n\n        RealmDictionary<java.lang.Boolean> columnBooleanDictionaryUnmanagedDictionary = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnBooleanDictionary();\n        if (columnBooleanDictionaryUnmanagedDictionary != null) {\n            OsMap columnBooleanDictionaryOsMap = new OsMap(table.getUncheckedRow(objKey), columnInfo.columnBooleanDictionaryColKey);\n            java.util.Set<java.util.Map.Entry<String, java.lang.Boolean>> entries = columnBooleanDictionaryUnmanagedDictionary.entrySet();\n            for (java.util.Map.Entry<String, java.lang.Boolean> entry : entries) {\n                String entryKey = entry.getKey();\n                java.lang.Boolean columnBooleanDictionaryUnmanagedEntryValue = entry.getValue();\n                columnBooleanDictionaryOsMap.put(entryKey, columnBooleanDictionaryUnmanagedEntryValue);\n            }\n        }\n\n        RealmDictionary<java.lang.String> columnStringDictionaryUnmanagedDictionary = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnStringDictionary();\n        if (columnStringDictionaryUnmanagedDictionary != null) {\n            OsMap columnStringDictionaryOsMap = new OsMap(table.getUncheckedRow(objKey), columnInfo.columnStringDictionaryColKey);\n            java.util.Set<java.util.Map.Entry<String, java.lang.String>> entries = columnStringDictionaryUnmanagedDictionary.entrySet();\n            for (java.util.Map.Entry<String, java.lang.String> entry : entries) {\n                String entryKey = entry.getKey();\n                java.lang.String columnStringDictionaryUnmanagedEntryValue = entry.getValue();\n                columnStringDictionaryOsMap.put(entryKey, columnStringDictionaryUnmanagedEntryValue);\n            }\n        }\n\n        RealmDictionary<java.lang.Integer> columnIntegerDictionaryUnmanagedDictionary = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnIntegerDictionary();\n        if (columnIntegerDictionaryUnmanagedDictionary != null) {\n            OsMap columnIntegerDictionaryOsMap = new OsMap(table.getUncheckedRow(objKey), columnInfo.columnIntegerDictionaryColKey);\n            java.util.Set<java.util.Map.Entry<String, java.lang.Integer>> entries = columnIntegerDictionaryUnmanagedDictionary.entrySet();\n            for (java.util.Map.Entry<String, java.lang.Integer> entry : entries) {\n                String entryKey = entry.getKey();\n                java.lang.Integer columnIntegerDictionaryUnmanagedEntryValue = entry.getValue();\n                columnIntegerDictionaryOsMap.put(entryKey, columnIntegerDictionaryUnmanagedEntryValue);\n            }\n        }\n\n        RealmDictionary<java.lang.Float> columnFloatDictionaryUnmanagedDictionary = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnFloatDictionary();\n        if (columnFloatDictionaryUnmanagedDictionary != null) {\n            OsMap columnFloatDictionaryOsMap = new OsMap(table.getUncheckedRow(objKey), columnInfo.columnFloatDictionaryColKey);\n            java.util.Set<java.util.Map.Entry<String, java.lang.Float>> entries = columnFloatDictionaryUnmanagedDictionary.entrySet();\n            for (java.util.Map.Entry<String, java.lang.Float> entry : entries) {\n                String entryKey = entry.getKey();\n                java.lang.Float columnFloatDictionaryUnmanagedEntryValue = entry.getValue();\n                columnFloatDictionaryOsMap.put(entryKey, columnFloatDictionaryUnmanagedEntryValue);\n            }\n        }\n\n        RealmDictionary<java.lang.Long> columnLongDictionaryUnmanagedDictionary = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnLongDictionary();\n        if (columnLongDictionaryUnmanagedDictionary != null) {\n            OsMap columnLongDictionaryOsMap = new OsMap(table.getUncheckedRow(objKey), columnInfo.columnLongDictionaryColKey);\n            java.util.Set<java.util.Map.Entry<String, java.lang.Long>> entries = columnLongDictionaryUnmanagedDictionary.entrySet();\n            for (java.util.Map.Entry<String, java.lang.Long> entry : entries) {\n                String entryKey = entry.getKey();\n                java.lang.Long columnLongDictionaryUnmanagedEntryValue = entry.getValue();\n                columnLongDictionaryOsMap.put(entryKey, columnLongDictionaryUnmanagedEntryValue);\n            }\n        }\n\n        RealmDictionary<java.lang.Short> columnShortDictionaryUnmanagedDictionary = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnShortDictionary();\n        if (columnShortDictionaryUnmanagedDictionary != null) {\n            OsMap columnShortDictionaryOsMap = new OsMap(table.getUncheckedRow(objKey), columnInfo.columnShortDictionaryColKey);\n            java.util.Set<java.util.Map.Entry<String, java.lang.Short>> entries = columnShortDictionaryUnmanagedDictionary.entrySet();\n            for (java.util.Map.Entry<String, java.lang.Short> entry : entries) {\n                String entryKey = entry.getKey();\n                java.lang.Short columnShortDictionaryUnmanagedEntryValue = entry.getValue();\n                columnShortDictionaryOsMap.put(entryKey, columnShortDictionaryUnmanagedEntryValue);\n            }\n        }\n\n        RealmDictionary<java.lang.Double> columnDoubleDictionaryUnmanagedDictionary = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnDoubleDictionary();\n        if (columnDoubleDictionaryUnmanagedDictionary != null) {\n            OsMap columnDoubleDictionaryOsMap = new OsMap(table.getUncheckedRow(objKey), columnInfo.columnDoubleDictionaryColKey);\n            java.util.Set<java.util.Map.Entry<String, java.lang.Double>> entries = columnDoubleDictionaryUnmanagedDictionary.entrySet();\n            for (java.util.Map.Entry<String, java.lang.Double> entry : entries) {\n                String entryKey = entry.getKey();\n                java.lang.Double columnDoubleDictionaryUnmanagedEntryValue = entry.getValue();\n                columnDoubleDictionaryOsMap.put(entryKey, columnDoubleDictionaryUnmanagedEntryValue);\n            }\n        }\n\n        RealmDictionary<java.lang.Byte> columnByteDictionaryUnmanagedDictionary = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnByteDictionary();\n        if (columnByteDictionaryUnmanagedDictionary != null) {\n            OsMap columnByteDictionaryOsMap = new OsMap(table.getUncheckedRow(objKey), columnInfo.columnByteDictionaryColKey);\n            java.util.Set<java.util.Map.Entry<String, java.lang.Byte>> entries = columnByteDictionaryUnmanagedDictionary.entrySet();\n            for (java.util.Map.Entry<String, java.lang.Byte> entry : entries) {\n                String entryKey = entry.getKey();\n                java.lang.Byte columnByteDictionaryUnmanagedEntryValue = entry.getValue();\n                columnByteDictionaryOsMap.put(entryKey, columnByteDictionaryUnmanagedEntryValue);\n            }\n        }\n\n        RealmDictionary<byte[]> columnBinaryDictionaryUnmanagedDictionary = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnBinaryDictionary();\n        if (columnBinaryDictionaryUnmanagedDictionary != null) {\n            OsMap columnBinaryDictionaryOsMap = new OsMap(table.getUncheckedRow(objKey), columnInfo.columnBinaryDictionaryColKey);\n            java.util.Set<java.util.Map.Entry<String, byte[]>> entries = columnBinaryDictionaryUnmanagedDictionary.entrySet();\n            for (java.util.Map.Entry<String, byte[]> entry : entries) {\n                String entryKey = entry.getKey();\n                byte[] columnBinaryDictionaryUnmanagedEntryValue = entry.getValue();\n                columnBinaryDictionaryOsMap.put(entryKey, columnBinaryDictionaryUnmanagedEntryValue);\n            }\n        }\n\n        RealmDictionary<java.util.Date> columnDateDictionaryUnmanagedDictionary = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnDateDictionary();\n        if (columnDateDictionaryUnmanagedDictionary != null) {\n            OsMap columnDateDictionaryOsMap = new OsMap(table.getUncheckedRow(objKey), columnInfo.columnDateDictionaryColKey);\n            java.util.Set<java.util.Map.Entry<String, java.util.Date>> entries = columnDateDictionaryUnmanagedDictionary.entrySet();\n            for (java.util.Map.Entry<String, java.util.Date> entry : entries) {\n                String entryKey = entry.getKey();\n                java.util.Date columnDateDictionaryUnmanagedEntryValue = entry.getValue();\n                columnDateDictionaryOsMap.put(entryKey, columnDateDictionaryUnmanagedEntryValue);\n            }\n        }\n\n        RealmDictionary<org.bson.types.ObjectId> columnObjectIdDictionaryUnmanagedDictionary = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnObjectIdDictionary();\n        if (columnObjectIdDictionaryUnmanagedDictionary != null) {\n            OsMap columnObjectIdDictionaryOsMap = new OsMap(table.getUncheckedRow(objKey), columnInfo.columnObjectIdDictionaryColKey);\n            java.util.Set<java.util.Map.Entry<String, org.bson.types.ObjectId>> entries = columnObjectIdDictionaryUnmanagedDictionary.entrySet();\n            for (java.util.Map.Entry<String, org.bson.types.ObjectId> entry : entries) {\n                String entryKey = entry.getKey();\n                org.bson.types.ObjectId columnObjectIdDictionaryUnmanagedEntryValue = entry.getValue();\n                columnObjectIdDictionaryOsMap.put(entryKey, columnObjectIdDictionaryUnmanagedEntryValue);\n            }\n        }\n\n        RealmDictionary<java.util.UUID> columnUUIDDictionaryUnmanagedDictionary = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnUUIDDictionary();\n        if (columnUUIDDictionaryUnmanagedDictionary != null) {\n            OsMap columnUUIDDictionaryOsMap = new OsMap(table.getUncheckedRow(objKey), columnInfo.columnUUIDDictionaryColKey);\n            java.util.Set<java.util.Map.Entry<String, java.util.UUID>> entries = columnUUIDDictionaryUnmanagedDictionary.entrySet();\n            for (java.util.Map.Entry<String, java.util.UUID> entry : entries) {\n                String entryKey = entry.getKey();\n                java.util.UUID columnUUIDDictionaryUnmanagedEntryValue = entry.getValue();\n                columnUUIDDictionaryOsMap.put(entryKey, columnUUIDDictionaryUnmanagedEntryValue);\n            }\n        }\n\n        RealmDictionary<org.bson.types.Decimal128> columnDecimal128DictionaryUnmanagedDictionary = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnDecimal128Dictionary();\n        if (columnDecimal128DictionaryUnmanagedDictionary != null) {\n            OsMap columnDecimal128DictionaryOsMap = new OsMap(table.getUncheckedRow(objKey), columnInfo.columnDecimal128DictionaryColKey);\n            java.util.Set<java.util.Map.Entry<String, org.bson.types.Decimal128>> entries = columnDecimal128DictionaryUnmanagedDictionary.entrySet();\n            for (java.util.Map.Entry<String, org.bson.types.Decimal128> entry : entries) {\n                String entryKey = entry.getKey();\n                org.bson.types.Decimal128 columnDecimal128DictionaryUnmanagedEntryValue = entry.getValue();\n                columnDecimal128DictionaryOsMap.put(entryKey, columnDecimal128DictionaryUnmanagedEntryValue);\n            }\n        }\n        RealmDictionary<RealmAny> columnRealmAnyDictionaryUnmanagedDictionary = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnRealmAnyDictionary();\n        if (columnRealmAnyDictionaryUnmanagedDictionary != null) {\n            OsMap columnRealmAnyDictionaryOsMap = new OsMap(table.getUncheckedRow(objKey), columnInfo.columnRealmAnyDictionaryColKey);\n            java.util.Set<java.util.Map.Entry<String, io.realm.RealmAny>> entries = columnRealmAnyDictionaryUnmanagedDictionary.entrySet();\n            java.util.List<String> keys = new java.util.ArrayList<>();\n            java.util.List<Long> realmAnyPointers = new java.util.ArrayList<>();\n            for (java.util.Map.Entry<String, io.realm.RealmAny> entry : entries) {\n                RealmAny realmAnyItem = entry.getValue();\n                realmAnyItem = ProxyUtils.insert(realmAnyItem, realm, cache);\n                columnRealmAnyDictionaryOsMap.putRealmAny(entry.getKey(), realmAnyItem.getNativePtr());\n            }\n        }\n\n        return objKey;\n    }\n\n    public static void insert(Realm realm, Iterator<? extends RealmModel> objects, Map<RealmModel,Long> cache) {\n        Table table = realm.getTable(some.test.AllTypes.class);\n        long tableNativePtr = table.getNativePtr();\n        AllTypesColumnInfo columnInfo = (AllTypesColumnInfo) realm.getSchema().getColumnInfo(some.test.AllTypes.class);\n        long pkColumnKey = columnInfo.columnStringColKey;\n        some.test.AllTypes object = null;\n        while (objects.hasNext()) {\n            object = (some.test.AllTypes) objects.next();\n            if (cache.containsKey(object)) {\n                continue;\n            }\n            if (object instanceof RealmObjectProxy && !RealmObject.isFrozen(object) && ((RealmObjectProxy) object).realmGet$proxyState().getRealm$realm() != null && ((RealmObjectProxy) object).realmGet$proxyState().getRealm$realm().getPath().equals(realm.getPath())) {\n                cache.put(object, ((RealmObjectProxy) object).realmGet$proxyState().getRow$realm().getObjectKey());\n                continue;\n            }\n            String primaryKeyValue = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnString();\n            long objKey = Table.NO_MATCH;\n            if (primaryKeyValue == null) {\n                objKey = Table.nativeFindFirstNull(tableNativePtr, pkColumnKey);\n            } else {\n                objKey = Table.nativeFindFirstString(tableNativePtr, pkColumnKey, primaryKeyValue);\n            }\n            if (objKey == Table.NO_MATCH) {\n                objKey = OsObject.createRowWithPrimaryKey(table, pkColumnKey, primaryKeyValue);\n            } else {\n                Table.throwDuplicatePrimaryKeyException(primaryKeyValue);\n            }\n            cache.put(object, objKey);\n            Table.nativeSetLong(tableNativePtr, columnInfo.columnLongColKey, objKey, ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnLong(), false);\n            Table.nativeSetFloat(tableNativePtr, columnInfo.columnFloatColKey, objKey, ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnFloat(), false);\n            Table.nativeSetDouble(tableNativePtr, columnInfo.columnDoubleColKey, objKey, ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnDouble(), false);\n            Table.nativeSetBoolean(tableNativePtr, columnInfo.columnBooleanColKey, objKey, ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnBoolean(), false);\n            org.bson.types.Decimal128 realmGet$columnDecimal128 = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnDecimal128();\n            if (realmGet$columnDecimal128 != null) {\n                Table.nativeSetDecimal128(tableNativePtr, columnInfo.columnDecimal128ColKey, objKey, realmGet$columnDecimal128.getLow(), realmGet$columnDecimal128.getHigh(), false);\n            }\n            org.bson.types.ObjectId realmGet$columnObjectId = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnObjectId();\n            if (realmGet$columnObjectId != null) {\n                Table.nativeSetObjectId(tableNativePtr, columnInfo.columnObjectIdColKey, objKey, realmGet$columnObjectId.toString(), false);\n            }\n            java.util.UUID realmGet$columnUUID = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnUUID();\n            if (realmGet$columnUUID != null) {\n                Table.nativeSetUUID(tableNativePtr, columnInfo.columnUUIDColKey, objKey, realmGet$columnUUID.toString(), false);\n            }\n            java.util.Date realmGet$columnDate = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnDate();\n            if (realmGet$columnDate != null) {\n                Table.nativeSetTimestamp(tableNativePtr, columnInfo.columnDateColKey, objKey, realmGet$columnDate.getTime(), false);\n            }\n\n            RealmAny columnRealmAnyRealmAny = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnRealmAny();\n            columnRealmAnyRealmAny = ProxyUtils.insert(columnRealmAnyRealmAny, realm, cache);\n            Table.nativeSetRealmAny(tableNativePtr, columnInfo.columnRealmAnyColKey, objKey, columnRealmAnyRealmAny.getNativePtr(), false);\n            byte[] realmGet$columnBinary = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnBinary();\n            if (realmGet$columnBinary != null) {\n                Table.nativeSetByteArray(tableNativePtr, columnInfo.columnBinaryColKey, objKey, realmGet$columnBinary, false);\n            }\n            Long realmGet$columnMutableRealmInteger = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnMutableRealmInteger().get();\n            if (realmGet$columnMutableRealmInteger != null) {\n                Table.nativeSetLong(tableNativePtr, columnInfo.columnMutableRealmIntegerColKey, objKey, realmGet$columnMutableRealmInteger.longValue(), false);\n            }\n\n            some.test.AllTypes columnObjectObj = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnObject();\n            if (columnObjectObj != null) {\n                Long cachecolumnObject = cache.get(columnObjectObj);\n                if (cachecolumnObject == null) {\n                    cachecolumnObject = some_test_AllTypesRealmProxy.insert(realm, columnObjectObj, cache);\n                }\n                Table.nativeSetLink(tableNativePtr, columnInfo.columnObjectColKey, objKey, cachecolumnObject, false);\n            }\n\n            some.test.Simple columnObjectWithoutPkObj = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnObjectWithoutPk();\n            if (columnObjectWithoutPkObj != null) {\n                Long cachecolumnObjectWithoutPk = cache.get(columnObjectWithoutPkObj);\n                if (cachecolumnObjectWithoutPk == null) {\n                    cachecolumnObjectWithoutPk = some_test_SimpleRealmProxy.insert(realm, columnObjectWithoutPkObj, cache);\n                }\n                Table.nativeSetLink(tableNativePtr, columnInfo.columnObjectWithoutPkColKey, objKey, cachecolumnObjectWithoutPk, false);\n            }\n\n            RealmList<some.test.AllTypes> columnRealmListList = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnRealmList();\n            if (columnRealmListList != null) {\n                OsList columnRealmListOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.columnRealmListColKey);\n                for (some.test.AllTypes columnRealmListItem : columnRealmListList) {\n                    Long cacheItemIndexcolumnRealmList = cache.get(columnRealmListItem);\n                    if (cacheItemIndexcolumnRealmList == null) {\n                        cacheItemIndexcolumnRealmList = some_test_AllTypesRealmProxy.insert(realm, columnRealmListItem, cache);\n                    }\n                    columnRealmListOsList.addRow(cacheItemIndexcolumnRealmList);\n                }\n            }\n\n            RealmList<some.test.Simple> columnRealmListNoPkList = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnRealmListNoPk();\n            if (columnRealmListNoPkList != null) {\n                OsList columnRealmListNoPkOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.columnRealmListNoPkColKey);\n                for (some.test.Simple columnRealmListNoPkItem : columnRealmListNoPkList) {\n                    Long cacheItemIndexcolumnRealmListNoPk = cache.get(columnRealmListNoPkItem);\n                    if (cacheItemIndexcolumnRealmListNoPk == null) {\n                        cacheItemIndexcolumnRealmListNoPk = some_test_SimpleRealmProxy.insert(realm, columnRealmListNoPkItem, cache);\n                    }\n                    columnRealmListNoPkOsList.addRow(cacheItemIndexcolumnRealmListNoPk);\n                }\n            }\n\n            RealmList<some.test.AllTypes> columnRealmFinalListList = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnRealmFinalList();\n            if (columnRealmFinalListList != null) {\n                OsList columnRealmFinalListOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.columnRealmFinalListColKey);\n                for (some.test.AllTypes columnRealmFinalListItem : columnRealmFinalListList) {\n                    Long cacheItemIndexcolumnRealmFinalList = cache.get(columnRealmFinalListItem);\n                    if (cacheItemIndexcolumnRealmFinalList == null) {\n                        cacheItemIndexcolumnRealmFinalList = some_test_AllTypesRealmProxy.insert(realm, columnRealmFinalListItem, cache);\n                    }\n                    columnRealmFinalListOsList.addRow(cacheItemIndexcolumnRealmFinalList);\n                }\n            }\n\n            RealmList<some.test.Simple> columnRealmFinalListNoPkList = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnRealmFinalListNoPk();\n            if (columnRealmFinalListNoPkList != null) {\n                OsList columnRealmFinalListNoPkOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.columnRealmFinalListNoPkColKey);\n                for (some.test.Simple columnRealmFinalListNoPkItem : columnRealmFinalListNoPkList) {\n                    Long cacheItemIndexcolumnRealmFinalListNoPk = cache.get(columnRealmFinalListNoPkItem);\n                    if (cacheItemIndexcolumnRealmFinalListNoPk == null) {\n                        cacheItemIndexcolumnRealmFinalListNoPk = some_test_SimpleRealmProxy.insert(realm, columnRealmFinalListNoPkItem, cache);\n                    }\n                    columnRealmFinalListNoPkOsList.addRow(cacheItemIndexcolumnRealmFinalListNoPk);\n                }\n            }\n\n            RealmList<java.lang.String> columnStringListList = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnStringList();\n            if (columnStringListList != null) {\n                OsList columnStringListOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.columnStringListColKey);\n                for (java.lang.String columnStringListItem : columnStringListList) {\n                    if (columnStringListItem == null) {\n                        columnStringListOsList.addNull();\n                    } else {\n                        columnStringListOsList.addString(columnStringListItem);\n                    }\n                }\n            }\n\n            RealmList<byte[]> columnBinaryListList = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnBinaryList();\n            if (columnBinaryListList != null) {\n                OsList columnBinaryListOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.columnBinaryListColKey);\n                for (byte[] columnBinaryListItem : columnBinaryListList) {\n                    if (columnBinaryListItem == null) {\n                        columnBinaryListOsList.addNull();\n                    } else {\n                        columnBinaryListOsList.addBinary(columnBinaryListItem);\n                    }\n                }\n            }\n\n            RealmList<java.lang.Boolean> columnBooleanListList = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnBooleanList();\n            if (columnBooleanListList != null) {\n                OsList columnBooleanListOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.columnBooleanListColKey);\n                for (java.lang.Boolean columnBooleanListItem : columnBooleanListList) {\n                    if (columnBooleanListItem == null) {\n                        columnBooleanListOsList.addNull();\n                    } else {\n                        columnBooleanListOsList.addBoolean(columnBooleanListItem);\n                    }\n                }\n            }\n\n            RealmList<java.lang.Long> columnLongListList = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnLongList();\n            if (columnLongListList != null) {\n                OsList columnLongListOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.columnLongListColKey);\n                for (java.lang.Long columnLongListItem : columnLongListList) {\n                    if (columnLongListItem == null) {\n                        columnLongListOsList.addNull();\n                    } else {\n                        columnLongListOsList.addLong(columnLongListItem.longValue());\n                    }\n                }\n            }\n\n            RealmList<java.lang.Integer> columnIntegerListList = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnIntegerList();\n            if (columnIntegerListList != null) {\n                OsList columnIntegerListOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.columnIntegerListColKey);\n                for (java.lang.Integer columnIntegerListItem : columnIntegerListList) {\n                    if (columnIntegerListItem == null) {\n                        columnIntegerListOsList.addNull();\n                    } else {\n                        columnIntegerListOsList.addLong(columnIntegerListItem.longValue());\n                    }\n                }\n            }\n\n            RealmList<java.lang.Short> columnShortListList = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnShortList();\n            if (columnShortListList != null) {\n                OsList columnShortListOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.columnShortListColKey);\n                for (java.lang.Short columnShortListItem : columnShortListList) {\n                    if (columnShortListItem == null) {\n                        columnShortListOsList.addNull();\n                    } else {\n                        columnShortListOsList.addLong(columnShortListItem.longValue());\n                    }\n                }\n            }\n\n            RealmList<java.lang.Byte> columnByteListList = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnByteList();\n            if (columnByteListList != null) {\n                OsList columnByteListOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.columnByteListColKey);\n                for (java.lang.Byte columnByteListItem : columnByteListList) {\n                    if (columnByteListItem == null) {\n                        columnByteListOsList.addNull();\n                    } else {\n                        columnByteListOsList.addLong(columnByteListItem.longValue());\n                    }\n                }\n            }\n\n            RealmList<java.lang.Double> columnDoubleListList = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnDoubleList();\n            if (columnDoubleListList != null) {\n                OsList columnDoubleListOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.columnDoubleListColKey);\n                for (java.lang.Double columnDoubleListItem : columnDoubleListList) {\n                    if (columnDoubleListItem == null) {\n                        columnDoubleListOsList.addNull();\n                    } else {\n                        columnDoubleListOsList.addDouble(columnDoubleListItem.doubleValue());\n                    }\n                }\n            }\n\n            RealmList<java.lang.Float> columnFloatListList = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnFloatList();\n            if (columnFloatListList != null) {\n                OsList columnFloatListOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.columnFloatListColKey);\n                for (java.lang.Float columnFloatListItem : columnFloatListList) {\n                    if (columnFloatListItem == null) {\n                        columnFloatListOsList.addNull();\n                    } else {\n                        columnFloatListOsList.addFloat(columnFloatListItem.floatValue());\n                    }\n                }\n            }\n\n            RealmList<java.util.Date> columnDateListList = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnDateList();\n            if (columnDateListList != null) {\n                OsList columnDateListOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.columnDateListColKey);\n                for (java.util.Date columnDateListItem : columnDateListList) {\n                    if (columnDateListItem == null) {\n                        columnDateListOsList.addNull();\n                    } else {\n                        columnDateListOsList.addDate(columnDateListItem);\n                    }\n                }\n            }\n\n            RealmList<org.bson.types.Decimal128> columnDecimal128ListList = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnDecimal128List();\n            if (columnDecimal128ListList != null) {\n                OsList columnDecimal128ListOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.columnDecimal128ListColKey);\n                for (org.bson.types.Decimal128 columnDecimal128ListItem : columnDecimal128ListList) {\n                    if (columnDecimal128ListItem == null) {\n                        columnDecimal128ListOsList.addNull();\n                    } else {\n                        columnDecimal128ListOsList.addDecimal128(columnDecimal128ListItem);\n                    }\n                }\n            }\n\n            RealmList<org.bson.types.ObjectId> columnObjectIdListList = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnObjectIdList();\n            if (columnObjectIdListList != null) {\n                OsList columnObjectIdListOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.columnObjectIdListColKey);\n                for (org.bson.types.ObjectId columnObjectIdListItem : columnObjectIdListList) {\n                    if (columnObjectIdListItem == null) {\n                        columnObjectIdListOsList.addNull();\n                    } else {\n                        columnObjectIdListOsList.addObjectId(columnObjectIdListItem);\n                    }\n                }\n            }\n\n            RealmList<java.util.UUID> columnUUIDListList = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnUUIDList();\n            if (columnUUIDListList != null) {\n                OsList columnUUIDListOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.columnUUIDListColKey);\n                for (java.util.UUID columnUUIDListItem : columnUUIDListList) {\n                    if (columnUUIDListItem == null) {\n                        columnUUIDListOsList.addNull();\n                    } else {\n                        columnUUIDListOsList.addUUID(columnUUIDListItem);\n                    }\n                }\n            }\n\n            RealmList<RealmAny> columnRealmAnyListUnmanagedList = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnRealmAnyList();\n            if (columnRealmAnyListUnmanagedList != null) {\n                OsList columnRealmAnyListOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.columnRealmAnyListColKey);\n                for (int i = 0; i < columnRealmAnyListUnmanagedList.size(); i++) {\n                    RealmAny realmAnyItem = columnRealmAnyListUnmanagedList.get(i);\n                    realmAnyItem = ProxyUtils.insert(realmAnyItem, realm, cache);\n                    columnRealmAnyListOsList.addRealmAny(realmAnyItem.getNativePtr());\n                }\n            }\n            RealmDictionary<some.test.AllTypes> columnRealmDictionaryUnmanagedDictionary = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnRealmDictionary();\n            if (columnRealmDictionaryUnmanagedDictionary != null) {\n                OsMap columnRealmDictionaryOsMap = new OsMap(table.getUncheckedRow(objKey), columnInfo.columnRealmDictionaryColKey);\n                java.util.Set<java.util.Map.Entry<String, some.test.AllTypes>> entries = columnRealmDictionaryUnmanagedDictionary.entrySet();\n                for (java.util.Map.Entry<String, some.test.AllTypes> entry : entries) {\n                    String entryKey = entry.getKey();\n                    some.test.AllTypes columnRealmDictionaryUnmanagedEntryValue = entry.getValue();\n                    if(columnRealmDictionaryUnmanagedEntryValue == null) {\n                        columnRealmDictionaryOsMap.put(entryKey, null);\n                    } else {\n                        Long cacheItemIndexcolumnRealmDictionary = cache.get(columnRealmDictionaryUnmanagedEntryValue);\n                        if (cacheItemIndexcolumnRealmDictionary == null) {\n                            cacheItemIndexcolumnRealmDictionary = some_test_AllTypesRealmProxy.insert(realm, columnRealmDictionaryUnmanagedEntryValue, cache);\n                        }\n                        columnRealmDictionaryOsMap.putRow(entryKey, cacheItemIndexcolumnRealmDictionary);\n                    }\n                }\n            }\n\n            RealmDictionary<java.lang.Boolean> columnBooleanDictionaryUnmanagedDictionary = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnBooleanDictionary();\n            if (columnBooleanDictionaryUnmanagedDictionary != null) {\n                OsMap columnBooleanDictionaryOsMap = new OsMap(table.getUncheckedRow(objKey), columnInfo.columnBooleanDictionaryColKey);\n                java.util.Set<java.util.Map.Entry<String, java.lang.Boolean>> entries = columnBooleanDictionaryUnmanagedDictionary.entrySet();\n                for (java.util.Map.Entry<String, java.lang.Boolean> entry : entries) {\n                    String entryKey = entry.getKey();\n                    java.lang.Boolean columnBooleanDictionaryUnmanagedEntryValue = entry.getValue();\n                    columnBooleanDictionaryOsMap.put(entryKey, columnBooleanDictionaryUnmanagedEntryValue);\n                }\n            }\n\n            RealmDictionary<java.lang.String> columnStringDictionaryUnmanagedDictionary = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnStringDictionary();\n            if (columnStringDictionaryUnmanagedDictionary != null) {\n                OsMap columnStringDictionaryOsMap = new OsMap(table.getUncheckedRow(objKey), columnInfo.columnStringDictionaryColKey);\n                java.util.Set<java.util.Map.Entry<String, java.lang.String>> entries = columnStringDictionaryUnmanagedDictionary.entrySet();\n                for (java.util.Map.Entry<String, java.lang.String> entry : entries) {\n                    String entryKey = entry.getKey();\n                    java.lang.String columnStringDictionaryUnmanagedEntryValue = entry.getValue();\n                    columnStringDictionaryOsMap.put(entryKey, columnStringDictionaryUnmanagedEntryValue);\n                }\n            }\n\n            RealmDictionary<java.lang.Integer> columnIntegerDictionaryUnmanagedDictionary = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnIntegerDictionary();\n            if (columnIntegerDictionaryUnmanagedDictionary != null) {\n                OsMap columnIntegerDictionaryOsMap = new OsMap(table.getUncheckedRow(objKey), columnInfo.columnIntegerDictionaryColKey);\n                java.util.Set<java.util.Map.Entry<String, java.lang.Integer>> entries = columnIntegerDictionaryUnmanagedDictionary.entrySet();\n                for (java.util.Map.Entry<String, java.lang.Integer> entry : entries) {\n                    String entryKey = entry.getKey();\n                    java.lang.Integer columnIntegerDictionaryUnmanagedEntryValue = entry.getValue();\n                    columnIntegerDictionaryOsMap.put(entryKey, columnIntegerDictionaryUnmanagedEntryValue);\n                }\n            }\n\n            RealmDictionary<java.lang.Float> columnFloatDictionaryUnmanagedDictionary = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnFloatDictionary();\n            if (columnFloatDictionaryUnmanagedDictionary != null) {\n                OsMap columnFloatDictionaryOsMap = new OsMap(table.getUncheckedRow(objKey), columnInfo.columnFloatDictionaryColKey);\n                java.util.Set<java.util.Map.Entry<String, java.lang.Float>> entries = columnFloatDictionaryUnmanagedDictionary.entrySet();\n                for (java.util.Map.Entry<String, java.lang.Float> entry : entries) {\n                    String entryKey = entry.getKey();\n                    java.lang.Float columnFloatDictionaryUnmanagedEntryValue = entry.getValue();\n                    columnFloatDictionaryOsMap.put(entryKey, columnFloatDictionaryUnmanagedEntryValue);\n                }\n            }\n\n            RealmDictionary<java.lang.Long> columnLongDictionaryUnmanagedDictionary = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnLongDictionary();\n            if (columnLongDictionaryUnmanagedDictionary != null) {\n                OsMap columnLongDictionaryOsMap = new OsMap(table.getUncheckedRow(objKey), columnInfo.columnLongDictionaryColKey);\n                java.util.Set<java.util.Map.Entry<String, java.lang.Long>> entries = columnLongDictionaryUnmanagedDictionary.entrySet();\n                for (java.util.Map.Entry<String, java.lang.Long> entry : entries) {\n                    String entryKey = entry.getKey();\n                    java.lang.Long columnLongDictionaryUnmanagedEntryValue = entry.getValue();\n                    columnLongDictionaryOsMap.put(entryKey, columnLongDictionaryUnmanagedEntryValue);\n                }\n            }\n\n            RealmDictionary<java.lang.Short> columnShortDictionaryUnmanagedDictionary = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnShortDictionary();\n            if (columnShortDictionaryUnmanagedDictionary != null) {\n                OsMap columnShortDictionaryOsMap = new OsMap(table.getUncheckedRow(objKey), columnInfo.columnShortDictionaryColKey);\n                java.util.Set<java.util.Map.Entry<String, java.lang.Short>> entries = columnShortDictionaryUnmanagedDictionary.entrySet();\n                for (java.util.Map.Entry<String, java.lang.Short> entry : entries) {\n                    String entryKey = entry.getKey();\n                    java.lang.Short columnShortDictionaryUnmanagedEntryValue = entry.getValue();\n                    columnShortDictionaryOsMap.put(entryKey, columnShortDictionaryUnmanagedEntryValue);\n                }\n            }\n\n            RealmDictionary<java.lang.Double> columnDoubleDictionaryUnmanagedDictionary = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnDoubleDictionary();\n            if (columnDoubleDictionaryUnmanagedDictionary != null) {\n                OsMap columnDoubleDictionaryOsMap = new OsMap(table.getUncheckedRow(objKey), columnInfo.columnDoubleDictionaryColKey);\n                java.util.Set<java.util.Map.Entry<String, java.lang.Double>> entries = columnDoubleDictionaryUnmanagedDictionary.entrySet();\n                for (java.util.Map.Entry<String, java.lang.Double> entry : entries) {\n                    String entryKey = entry.getKey();\n                    java.lang.Double columnDoubleDictionaryUnmanagedEntryValue = entry.getValue();\n                    columnDoubleDictionaryOsMap.put(entryKey, columnDoubleDictionaryUnmanagedEntryValue);\n                }\n            }\n\n            RealmDictionary<java.lang.Byte> columnByteDictionaryUnmanagedDictionary = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnByteDictionary();\n            if (columnByteDictionaryUnmanagedDictionary != null) {\n                OsMap columnByteDictionaryOsMap = new OsMap(table.getUncheckedRow(objKey), columnInfo.columnByteDictionaryColKey);\n                java.util.Set<java.util.Map.Entry<String, java.lang.Byte>> entries = columnByteDictionaryUnmanagedDictionary.entrySet();\n                for (java.util.Map.Entry<String, java.lang.Byte> entry : entries) {\n                    String entryKey = entry.getKey();\n                    java.lang.Byte columnByteDictionaryUnmanagedEntryValue = entry.getValue();\n                    columnByteDictionaryOsMap.put(entryKey, columnByteDictionaryUnmanagedEntryValue);\n                }\n            }\n\n            RealmDictionary<byte[]> columnBinaryDictionaryUnmanagedDictionary = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnBinaryDictionary();\n            if (columnBinaryDictionaryUnmanagedDictionary != null) {\n                OsMap columnBinaryDictionaryOsMap = new OsMap(table.getUncheckedRow(objKey), columnInfo.columnBinaryDictionaryColKey);\n                java.util.Set<java.util.Map.Entry<String, byte[]>> entries = columnBinaryDictionaryUnmanagedDictionary.entrySet();\n                for (java.util.Map.Entry<String, byte[]> entry : entries) {\n                    String entryKey = entry.getKey();\n                    byte[] columnBinaryDictionaryUnmanagedEntryValue = entry.getValue();\n                    columnBinaryDictionaryOsMap.put(entryKey, columnBinaryDictionaryUnmanagedEntryValue);\n                }\n            }\n\n            RealmDictionary<java.util.Date> columnDateDictionaryUnmanagedDictionary = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnDateDictionary();\n            if (columnDateDictionaryUnmanagedDictionary != null) {\n                OsMap columnDateDictionaryOsMap = new OsMap(table.getUncheckedRow(objKey), columnInfo.columnDateDictionaryColKey);\n                java.util.Set<java.util.Map.Entry<String, java.util.Date>> entries = columnDateDictionaryUnmanagedDictionary.entrySet();\n                for (java.util.Map.Entry<String, java.util.Date> entry : entries) {\n                    String entryKey = entry.getKey();\n                    java.util.Date columnDateDictionaryUnmanagedEntryValue = entry.getValue();\n                    columnDateDictionaryOsMap.put(entryKey, columnDateDictionaryUnmanagedEntryValue);\n                }\n            }\n\n            RealmDictionary<org.bson.types.ObjectId> columnObjectIdDictionaryUnmanagedDictionary = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnObjectIdDictionary();\n            if (columnObjectIdDictionaryUnmanagedDictionary != null) {\n                OsMap columnObjectIdDictionaryOsMap = new OsMap(table.getUncheckedRow(objKey), columnInfo.columnObjectIdDictionaryColKey);\n                java.util.Set<java.util.Map.Entry<String, org.bson.types.ObjectId>> entries = columnObjectIdDictionaryUnmanagedDictionary.entrySet();\n                for (java.util.Map.Entry<String, org.bson.types.ObjectId> entry : entries) {\n                    String entryKey = entry.getKey();\n                    org.bson.types.ObjectId columnObjectIdDictionaryUnmanagedEntryValue = entry.getValue();\n                    columnObjectIdDictionaryOsMap.put(entryKey, columnObjectIdDictionaryUnmanagedEntryValue);\n                }\n            }\n\n            RealmDictionary<java.util.UUID> columnUUIDDictionaryUnmanagedDictionary = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnUUIDDictionary();\n            if (columnUUIDDictionaryUnmanagedDictionary != null) {\n                OsMap columnUUIDDictionaryOsMap = new OsMap(table.getUncheckedRow(objKey), columnInfo.columnUUIDDictionaryColKey);\n                java.util.Set<java.util.Map.Entry<String, java.util.UUID>> entries = columnUUIDDictionaryUnmanagedDictionary.entrySet();\n                for (java.util.Map.Entry<String, java.util.UUID> entry : entries) {\n                    String entryKey = entry.getKey();\n                    java.util.UUID columnUUIDDictionaryUnmanagedEntryValue = entry.getValue();\n                    columnUUIDDictionaryOsMap.put(entryKey, columnUUIDDictionaryUnmanagedEntryValue);\n                }\n            }\n\n            RealmDictionary<org.bson.types.Decimal128> columnDecimal128DictionaryUnmanagedDictionary = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnDecimal128Dictionary();\n            if (columnDecimal128DictionaryUnmanagedDictionary != null) {\n                OsMap columnDecimal128DictionaryOsMap = new OsMap(table.getUncheckedRow(objKey), columnInfo.columnDecimal128DictionaryColKey);\n                java.util.Set<java.util.Map.Entry<String, org.bson.types.Decimal128>> entries = columnDecimal128DictionaryUnmanagedDictionary.entrySet();\n                for (java.util.Map.Entry<String, org.bson.types.Decimal128> entry : entries) {\n                    String entryKey = entry.getKey();\n                    org.bson.types.Decimal128 columnDecimal128DictionaryUnmanagedEntryValue = entry.getValue();\n                    columnDecimal128DictionaryOsMap.put(entryKey, columnDecimal128DictionaryUnmanagedEntryValue);\n                }\n            }\n            RealmDictionary<RealmAny> columnRealmAnyDictionaryUnmanagedDictionary = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnRealmAnyDictionary();\n            if (columnRealmAnyDictionaryUnmanagedDictionary != null) {\n                OsMap columnRealmAnyDictionaryOsMap = new OsMap(table.getUncheckedRow(objKey), columnInfo.columnRealmAnyDictionaryColKey);\n                java.util.Set<java.util.Map.Entry<String, io.realm.RealmAny>> entries = columnRealmAnyDictionaryUnmanagedDictionary.entrySet();\n                java.util.List<String> keys = new java.util.ArrayList<>();\n                java.util.List<Long> realmAnyPointers = new java.util.ArrayList<>();\n                for (java.util.Map.Entry<String, io.realm.RealmAny> entry : entries) {\n                    RealmAny realmAnyItem = entry.getValue();\n                    realmAnyItem = ProxyUtils.insert(realmAnyItem, realm, cache);\n                    columnRealmAnyDictionaryOsMap.putRealmAny(entry.getKey(), realmAnyItem.getNativePtr());\n                }\n            }\n\n        }\n    }\n\n    public static long insertOrUpdate(Realm realm, some.test.AllTypes object, Map<RealmModel,Long> cache) {\n        if (object instanceof RealmObjectProxy && !RealmObject.isFrozen(object) && ((RealmObjectProxy) object).realmGet$proxyState().getRealm$realm() != null && ((RealmObjectProxy) object).realmGet$proxyState().getRealm$realm().getPath().equals(realm.getPath())) {\n            return ((RealmObjectProxy) object).realmGet$proxyState().getRow$realm().getObjectKey();\n        }\n        Table table = realm.getTable(some.test.AllTypes.class);\n        long tableNativePtr = table.getNativePtr();\n        AllTypesColumnInfo columnInfo = (AllTypesColumnInfo) realm.getSchema().getColumnInfo(some.test.AllTypes.class);\n        long pkColumnKey = columnInfo.columnStringColKey;\n        String primaryKeyValue = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnString();\n        long objKey = Table.NO_MATCH;\n        if (primaryKeyValue == null) {\n            objKey = Table.nativeFindFirstNull(tableNativePtr, pkColumnKey);\n        } else {\n            objKey = Table.nativeFindFirstString(tableNativePtr, pkColumnKey, primaryKeyValue);\n        }\n        if (objKey == Table.NO_MATCH) {\n            objKey = OsObject.createRowWithPrimaryKey(table, pkColumnKey, primaryKeyValue);\n        }\n        cache.put(object, objKey);\n        Table.nativeSetLong(tableNativePtr, columnInfo.columnLongColKey, objKey, ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnLong(), false);\n        Table.nativeSetFloat(tableNativePtr, columnInfo.columnFloatColKey, objKey, ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnFloat(), false);\n        Table.nativeSetDouble(tableNativePtr, columnInfo.columnDoubleColKey, objKey, ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnDouble(), false);\n        Table.nativeSetBoolean(tableNativePtr, columnInfo.columnBooleanColKey, objKey, ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnBoolean(), false);\n        org.bson.types.Decimal128 realmGet$columnDecimal128 = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnDecimal128();\n        if (realmGet$columnDecimal128 != null) {\n            Table.nativeSetDecimal128(tableNativePtr, columnInfo.columnDecimal128ColKey, objKey, realmGet$columnDecimal128.getLow(), realmGet$columnDecimal128.getHigh(), false);\n        } else {\n            Table.nativeSetNull(tableNativePtr, columnInfo.columnDecimal128ColKey, objKey, false);\n        }\n        org.bson.types.ObjectId realmGet$columnObjectId = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnObjectId();\n        if (realmGet$columnObjectId != null) {\n            Table.nativeSetObjectId(tableNativePtr, columnInfo.columnObjectIdColKey, objKey, realmGet$columnObjectId.toString(), false);\n        } else {\n            Table.nativeSetNull(tableNativePtr, columnInfo.columnObjectIdColKey, objKey, false);\n        }\n        java.util.UUID realmGet$columnUUID = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnUUID();\n        if (realmGet$columnUUID != null) {\n            Table.nativeSetUUID(tableNativePtr, columnInfo.columnUUIDColKey, objKey, realmGet$columnUUID.toString(), false);\n        } else {\n            Table.nativeSetNull(tableNativePtr, columnInfo.columnUUIDColKey, objKey, false);\n        }\n        java.util.Date realmGet$columnDate = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnDate();\n        if (realmGet$columnDate != null) {\n            Table.nativeSetTimestamp(tableNativePtr, columnInfo.columnDateColKey, objKey, realmGet$columnDate.getTime(), false);\n        } else {\n            Table.nativeSetNull(tableNativePtr, columnInfo.columnDateColKey, objKey, false);\n        }\n        RealmAny columnRealmAnyRealmAny = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnRealmAny();\n        columnRealmAnyRealmAny = ProxyUtils.insertOrUpdate(columnRealmAnyRealmAny, realm, cache);\n        Table.nativeSetRealmAny(tableNativePtr, columnInfo.columnRealmAnyColKey, objKey, columnRealmAnyRealmAny.getNativePtr(), false);\n        byte[] realmGet$columnBinary = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnBinary();\n        if (realmGet$columnBinary != null) {\n            Table.nativeSetByteArray(tableNativePtr, columnInfo.columnBinaryColKey, objKey, realmGet$columnBinary, false);\n        } else {\n            Table.nativeSetNull(tableNativePtr, columnInfo.columnBinaryColKey, objKey, false);\n        }\n        Long realmGet$columnMutableRealmInteger = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnMutableRealmInteger().get();\n        if (realmGet$columnMutableRealmInteger != null) {\n            Table.nativeSetLong(tableNativePtr, columnInfo.columnMutableRealmIntegerColKey, objKey, realmGet$columnMutableRealmInteger.longValue(), false);\n        } else {\n            Table.nativeSetNull(tableNativePtr, columnInfo.columnMutableRealmIntegerColKey, objKey, false);\n        }\n\n        some.test.AllTypes columnObjectObj = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnObject();\n        if (columnObjectObj != null) {\n            Long cachecolumnObject = cache.get(columnObjectObj);\n            if (cachecolumnObject == null) {\n                cachecolumnObject = some_test_AllTypesRealmProxy.insertOrUpdate(realm, columnObjectObj, cache);\n            }\n            Table.nativeSetLink(tableNativePtr, columnInfo.columnObjectColKey, objKey, cachecolumnObject, false);\n        } else {\n            Table.nativeNullifyLink(tableNativePtr, columnInfo.columnObjectColKey, objKey);\n        }\n\n        some.test.Simple columnObjectWithoutPkObj = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnObjectWithoutPk();\n        if (columnObjectWithoutPkObj != null) {\n            Long cachecolumnObjectWithoutPk = cache.get(columnObjectWithoutPkObj);\n            if (cachecolumnObjectWithoutPk == null) {\n                cachecolumnObjectWithoutPk = some_test_SimpleRealmProxy.insertOrUpdate(realm, columnObjectWithoutPkObj, cache);\n            }\n            Table.nativeSetLink(tableNativePtr, columnInfo.columnObjectWithoutPkColKey, objKey, cachecolumnObjectWithoutPk, false);\n        } else {\n            Table.nativeNullifyLink(tableNativePtr, columnInfo.columnObjectWithoutPkColKey, objKey);\n        }\n\n        OsList columnRealmListOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.columnRealmListColKey);\n        RealmList<some.test.AllTypes> columnRealmListList = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnRealmList();\n        if (columnRealmListList != null && columnRealmListList.size() == columnRealmListOsList.size()) {\n            // For lists of equal lengths, we need to set each element directly as clearing the receiver list can be wrong if the input and target list are the same.\n            int objectCount = columnRealmListList.size();\n            for (int i = 0; i < objectCount; i++) {\n                some.test.AllTypes columnRealmListItem = columnRealmListList.get(i);\n                Long cacheItemIndexcolumnRealmList = cache.get(columnRealmListItem);\n                if (cacheItemIndexcolumnRealmList == null) {\n                    cacheItemIndexcolumnRealmList = some_test_AllTypesRealmProxy.insertOrUpdate(realm, columnRealmListItem, cache);\n                }\n                columnRealmListOsList.setRow(i, cacheItemIndexcolumnRealmList);\n            }\n        } else {\n            columnRealmListOsList.removeAll();\n            if (columnRealmListList != null) {\n                for (some.test.AllTypes columnRealmListItem : columnRealmListList) {\n                    Long cacheItemIndexcolumnRealmList = cache.get(columnRealmListItem);\n                    if (cacheItemIndexcolumnRealmList == null) {\n                        cacheItemIndexcolumnRealmList = some_test_AllTypesRealmProxy.insertOrUpdate(realm, columnRealmListItem, cache);\n                    }\n                    columnRealmListOsList.addRow(cacheItemIndexcolumnRealmList);\n                }\n            }\n        }\n\n\n        OsList columnRealmListNoPkOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.columnRealmListNoPkColKey);\n        RealmList<some.test.Simple> columnRealmListNoPkList = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnRealmListNoPk();\n        if (columnRealmListNoPkList != null && columnRealmListNoPkList.size() == columnRealmListNoPkOsList.size()) {\n            // For lists of equal lengths, we need to set each element directly as clearing the receiver list can be wrong if the input and target list are the same.\n            int objectCount = columnRealmListNoPkList.size();\n            for (int i = 0; i < objectCount; i++) {\n                some.test.Simple columnRealmListNoPkItem = columnRealmListNoPkList.get(i);\n                Long cacheItemIndexcolumnRealmListNoPk = cache.get(columnRealmListNoPkItem);\n                if (cacheItemIndexcolumnRealmListNoPk == null) {\n                    cacheItemIndexcolumnRealmListNoPk = some_test_SimpleRealmProxy.insertOrUpdate(realm, columnRealmListNoPkItem, cache);\n                }\n                columnRealmListNoPkOsList.setRow(i, cacheItemIndexcolumnRealmListNoPk);\n            }\n        } else {\n            columnRealmListNoPkOsList.removeAll();\n            if (columnRealmListNoPkList != null) {\n                for (some.test.Simple columnRealmListNoPkItem : columnRealmListNoPkList) {\n                    Long cacheItemIndexcolumnRealmListNoPk = cache.get(columnRealmListNoPkItem);\n                    if (cacheItemIndexcolumnRealmListNoPk == null) {\n                        cacheItemIndexcolumnRealmListNoPk = some_test_SimpleRealmProxy.insertOrUpdate(realm, columnRealmListNoPkItem, cache);\n                    }\n                    columnRealmListNoPkOsList.addRow(cacheItemIndexcolumnRealmListNoPk);\n                }\n            }\n        }\n\n\n        OsList columnRealmFinalListOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.columnRealmFinalListColKey);\n        RealmList<some.test.AllTypes> columnRealmFinalListList = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnRealmFinalList();\n        if (columnRealmFinalListList != null && columnRealmFinalListList.size() == columnRealmFinalListOsList.size()) {\n            // For lists of equal lengths, we need to set each element directly as clearing the receiver list can be wrong if the input and target list are the same.\n            int objectCount = columnRealmFinalListList.size();\n            for (int i = 0; i < objectCount; i++) {\n                some.test.AllTypes columnRealmFinalListItem = columnRealmFinalListList.get(i);\n                Long cacheItemIndexcolumnRealmFinalList = cache.get(columnRealmFinalListItem);\n                if (cacheItemIndexcolumnRealmFinalList == null) {\n                    cacheItemIndexcolumnRealmFinalList = some_test_AllTypesRealmProxy.insertOrUpdate(realm, columnRealmFinalListItem, cache);\n                }\n                columnRealmFinalListOsList.setRow(i, cacheItemIndexcolumnRealmFinalList);\n            }\n        } else {\n            columnRealmFinalListOsList.removeAll();\n            if (columnRealmFinalListList != null) {\n                for (some.test.AllTypes columnRealmFinalListItem : columnRealmFinalListList) {\n                    Long cacheItemIndexcolumnRealmFinalList = cache.get(columnRealmFinalListItem);\n                    if (cacheItemIndexcolumnRealmFinalList == null) {\n                        cacheItemIndexcolumnRealmFinalList = some_test_AllTypesRealmProxy.insertOrUpdate(realm, columnRealmFinalListItem, cache);\n                    }\n                    columnRealmFinalListOsList.addRow(cacheItemIndexcolumnRealmFinalList);\n                }\n            }\n        }\n\n\n        OsList columnRealmFinalListNoPkOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.columnRealmFinalListNoPkColKey);\n        RealmList<some.test.Simple> columnRealmFinalListNoPkList = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnRealmFinalListNoPk();\n        if (columnRealmFinalListNoPkList != null && columnRealmFinalListNoPkList.size() == columnRealmFinalListNoPkOsList.size()) {\n            // For lists of equal lengths, we need to set each element directly as clearing the receiver list can be wrong if the input and target list are the same.\n            int objectCount = columnRealmFinalListNoPkList.size();\n            for (int i = 0; i < objectCount; i++) {\n                some.test.Simple columnRealmFinalListNoPkItem = columnRealmFinalListNoPkList.get(i);\n                Long cacheItemIndexcolumnRealmFinalListNoPk = cache.get(columnRealmFinalListNoPkItem);\n                if (cacheItemIndexcolumnRealmFinalListNoPk == null) {\n                    cacheItemIndexcolumnRealmFinalListNoPk = some_test_SimpleRealmProxy.insertOrUpdate(realm, columnRealmFinalListNoPkItem, cache);\n                }\n                columnRealmFinalListNoPkOsList.setRow(i, cacheItemIndexcolumnRealmFinalListNoPk);\n            }\n        } else {\n            columnRealmFinalListNoPkOsList.removeAll();\n            if (columnRealmFinalListNoPkList != null) {\n                for (some.test.Simple columnRealmFinalListNoPkItem : columnRealmFinalListNoPkList) {\n                    Long cacheItemIndexcolumnRealmFinalListNoPk = cache.get(columnRealmFinalListNoPkItem);\n                    if (cacheItemIndexcolumnRealmFinalListNoPk == null) {\n                        cacheItemIndexcolumnRealmFinalListNoPk = some_test_SimpleRealmProxy.insertOrUpdate(realm, columnRealmFinalListNoPkItem, cache);\n                    }\n                    columnRealmFinalListNoPkOsList.addRow(cacheItemIndexcolumnRealmFinalListNoPk);\n                }\n            }\n        }\n\n\n        OsList columnStringListOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.columnStringListColKey);\n        columnStringListOsList.removeAll();\n        RealmList<java.lang.String> columnStringListList = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnStringList();\n        if (columnStringListList != null) {\n            for (java.lang.String columnStringListItem : columnStringListList) {\n                if (columnStringListItem == null) {\n                    columnStringListOsList.addNull();\n                } else {\n                    columnStringListOsList.addString(columnStringListItem);\n                }\n            }\n        }\n\n\n        OsList columnBinaryListOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.columnBinaryListColKey);\n        columnBinaryListOsList.removeAll();\n        RealmList<byte[]> columnBinaryListList = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnBinaryList();\n        if (columnBinaryListList != null) {\n            for (byte[] columnBinaryListItem : columnBinaryListList) {\n                if (columnBinaryListItem == null) {\n                    columnBinaryListOsList.addNull();\n                } else {\n                    columnBinaryListOsList.addBinary(columnBinaryListItem);\n                }\n            }\n        }\n\n\n        OsList columnBooleanListOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.columnBooleanListColKey);\n        columnBooleanListOsList.removeAll();\n        RealmList<java.lang.Boolean> columnBooleanListList = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnBooleanList();\n        if (columnBooleanListList != null) {\n            for (java.lang.Boolean columnBooleanListItem : columnBooleanListList) {\n                if (columnBooleanListItem == null) {\n                    columnBooleanListOsList.addNull();\n                } else {\n                    columnBooleanListOsList.addBoolean(columnBooleanListItem);\n                }\n            }\n        }\n\n\n        OsList columnLongListOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.columnLongListColKey);\n        columnLongListOsList.removeAll();\n        RealmList<java.lang.Long> columnLongListList = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnLongList();\n        if (columnLongListList != null) {\n            for (java.lang.Long columnLongListItem : columnLongListList) {\n                if (columnLongListItem == null) {\n                    columnLongListOsList.addNull();\n                } else {\n                    columnLongListOsList.addLong(columnLongListItem.longValue());\n                }\n            }\n        }\n\n\n        OsList columnIntegerListOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.columnIntegerListColKey);\n        columnIntegerListOsList.removeAll();\n        RealmList<java.lang.Integer> columnIntegerListList = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnIntegerList();\n        if (columnIntegerListList != null) {\n            for (java.lang.Integer columnIntegerListItem : columnIntegerListList) {\n                if (columnIntegerListItem == null) {\n                    columnIntegerListOsList.addNull();\n                } else {\n                    columnIntegerListOsList.addLong(columnIntegerListItem.longValue());\n                }\n            }\n        }\n\n\n        OsList columnShortListOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.columnShortListColKey);\n        columnShortListOsList.removeAll();\n        RealmList<java.lang.Short> columnShortListList = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnShortList();\n        if (columnShortListList != null) {\n            for (java.lang.Short columnShortListItem : columnShortListList) {\n                if (columnShortListItem == null) {\n                    columnShortListOsList.addNull();\n                } else {\n                    columnShortListOsList.addLong(columnShortListItem.longValue());\n                }\n            }\n        }\n\n\n        OsList columnByteListOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.columnByteListColKey);\n        columnByteListOsList.removeAll();\n        RealmList<java.lang.Byte> columnByteListList = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnByteList();\n        if (columnByteListList != null) {\n            for (java.lang.Byte columnByteListItem : columnByteListList) {\n                if (columnByteListItem == null) {\n                    columnByteListOsList.addNull();\n                } else {\n                    columnByteListOsList.addLong(columnByteListItem.longValue());\n                }\n            }\n        }\n\n\n        OsList columnDoubleListOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.columnDoubleListColKey);\n        columnDoubleListOsList.removeAll();\n        RealmList<java.lang.Double> columnDoubleListList = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnDoubleList();\n        if (columnDoubleListList != null) {\n            for (java.lang.Double columnDoubleListItem : columnDoubleListList) {\n                if (columnDoubleListItem == null) {\n                    columnDoubleListOsList.addNull();\n                } else {\n                    columnDoubleListOsList.addDouble(columnDoubleListItem.doubleValue());\n                }\n            }\n        }\n\n\n        OsList columnFloatListOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.columnFloatListColKey);\n        columnFloatListOsList.removeAll();\n        RealmList<java.lang.Float> columnFloatListList = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnFloatList();\n        if (columnFloatListList != null) {\n            for (java.lang.Float columnFloatListItem : columnFloatListList) {\n                if (columnFloatListItem == null) {\n                    columnFloatListOsList.addNull();\n                } else {\n                    columnFloatListOsList.addFloat(columnFloatListItem.floatValue());\n                }\n            }\n        }\n\n\n        OsList columnDateListOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.columnDateListColKey);\n        columnDateListOsList.removeAll();\n        RealmList<java.util.Date> columnDateListList = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnDateList();\n        if (columnDateListList != null) {\n            for (java.util.Date columnDateListItem : columnDateListList) {\n                if (columnDateListItem == null) {\n                    columnDateListOsList.addNull();\n                } else {\n                    columnDateListOsList.addDate(columnDateListItem);\n                }\n            }\n        }\n\n\n        OsList columnDecimal128ListOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.columnDecimal128ListColKey);\n        columnDecimal128ListOsList.removeAll();\n        RealmList<org.bson.types.Decimal128> columnDecimal128ListList = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnDecimal128List();\n        if (columnDecimal128ListList != null) {\n            for (org.bson.types.Decimal128 columnDecimal128ListItem : columnDecimal128ListList) {\n                if (columnDecimal128ListItem == null) {\n                    columnDecimal128ListOsList.addNull();\n                } else {\n                    columnDecimal128ListOsList.addDecimal128(columnDecimal128ListItem);\n                }\n            }\n        }\n\n\n        OsList columnObjectIdListOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.columnObjectIdListColKey);\n        columnObjectIdListOsList.removeAll();\n        RealmList<org.bson.types.ObjectId> columnObjectIdListList = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnObjectIdList();\n        if (columnObjectIdListList != null) {\n            for (org.bson.types.ObjectId columnObjectIdListItem : columnObjectIdListList) {\n                if (columnObjectIdListItem == null) {\n                    columnObjectIdListOsList.addNull();\n                } else {\n                    columnObjectIdListOsList.addObjectId(columnObjectIdListItem);\n                }\n            }\n        }\n\n\n        OsList columnUUIDListOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.columnUUIDListColKey);\n        columnUUIDListOsList.removeAll();\n        RealmList<java.util.UUID> columnUUIDListList = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnUUIDList();\n        if (columnUUIDListList != null) {\n            for (java.util.UUID columnUUIDListItem : columnUUIDListList) {\n                if (columnUUIDListItem == null) {\n                    columnUUIDListOsList.addNull();\n                } else {\n                    columnUUIDListOsList.addUUID(columnUUIDListItem);\n                }\n            }\n        }\n\n\n        OsList columnRealmAnyListOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.columnRealmAnyListColKey);\n        RealmList<RealmAny> columnRealmAnyListList = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnRealmAnyList();\n        if (columnRealmAnyListList != null && columnRealmAnyListList.size() == columnRealmAnyListOsList.size()) {\n            // For lists of equal lengths, we need to set each element directly as clearing the receiver list can be wrong if the input and target list are the same.\n            int objectCount = columnRealmAnyListList.size();\n            for (int i = 0; i < objectCount; i++) {\n                RealmAny columnRealmAnyListItem = columnRealmAnyListList.get(i);\n                Long cacheItemIndexcolumnRealmAnyList = cache.get(columnRealmAnyListItem);\n                if (cacheItemIndexcolumnRealmAnyList == null) {\n                    columnRealmAnyListItem = ProxyUtils.insertOrUpdate(columnRealmAnyListItem, realm, cache);\n                }\n                columnRealmAnyListOsList.setRealmAny(i, columnRealmAnyListItem.getNativePtr());\n            }\n        } else {\n            columnRealmAnyListOsList.removeAll();\n            if (columnRealmAnyListList != null) {\n                for (RealmAny columnRealmAnyListItem : columnRealmAnyListList) {\n                    Long cacheItemIndexcolumnRealmAnyList = cache.get(columnRealmAnyListItem);\n                    if (cacheItemIndexcolumnRealmAnyList == null) {\n                        columnRealmAnyListItem = ProxyUtils.insertOrUpdate(columnRealmAnyListItem, realm, cache);\n                    }\n                    columnRealmAnyListOsList.addRealmAny(columnRealmAnyListItem.getNativePtr());\n                }\n            }\n        }\n        RealmDictionary<some.test.AllTypes> columnRealmDictionaryUnmanagedDictionary = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnRealmDictionary();\n        if (columnRealmDictionaryUnmanagedDictionary != null) {\n            OsMap columnRealmDictionaryOsMap = new OsMap(table.getUncheckedRow(objKey), columnInfo.columnRealmDictionaryColKey);\n            java.util.Set<java.util.Map.Entry<String, some.test.AllTypes>> entries = columnRealmDictionaryUnmanagedDictionary.entrySet();\n            for (java.util.Map.Entry<String, some.test.AllTypes> entry : entries) {\n                String entryKey = entry.getKey();\n                some.test.AllTypes columnRealmDictionaryUnmanagedEntryValue = entry.getValue();\n                if(columnRealmDictionaryUnmanagedEntryValue == null) {\n                    columnRealmDictionaryOsMap.put(entryKey, null);\n                } else {\n                    Long cacheItemIndexcolumnRealmDictionary = cache.get(columnRealmDictionaryUnmanagedEntryValue);\n                    if (cacheItemIndexcolumnRealmDictionary == null) {\n                        cacheItemIndexcolumnRealmDictionary = some_test_AllTypesRealmProxy.insertOrUpdate(realm, columnRealmDictionaryUnmanagedEntryValue, cache);\n                    }\n                    columnRealmDictionaryOsMap.putRow(entryKey, cacheItemIndexcolumnRealmDictionary);\n                }\n            }\n        }\n\n        RealmDictionary<java.lang.Boolean> columnBooleanDictionaryUnmanagedDictionary = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnBooleanDictionary();\n        if (columnBooleanDictionaryUnmanagedDictionary != null) {\n            OsMap columnBooleanDictionaryOsMap = new OsMap(table.getUncheckedRow(objKey), columnInfo.columnBooleanDictionaryColKey);\n            java.util.Set<java.util.Map.Entry<String, java.lang.Boolean>> entries = columnBooleanDictionaryUnmanagedDictionary.entrySet();\n            for (java.util.Map.Entry<String, java.lang.Boolean> entry : entries) {\n                String entryKey = entry.getKey();\n                java.lang.Boolean columnBooleanDictionaryUnmanagedEntryValue = entry.getValue();\n                columnBooleanDictionaryOsMap.put(entryKey, columnBooleanDictionaryUnmanagedEntryValue);\n            }\n        }\n\n        RealmDictionary<java.lang.String> columnStringDictionaryUnmanagedDictionary = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnStringDictionary();\n        if (columnStringDictionaryUnmanagedDictionary != null) {\n            OsMap columnStringDictionaryOsMap = new OsMap(table.getUncheckedRow(objKey), columnInfo.columnStringDictionaryColKey);\n            java.util.Set<java.util.Map.Entry<String, java.lang.String>> entries = columnStringDictionaryUnmanagedDictionary.entrySet();\n            for (java.util.Map.Entry<String, java.lang.String> entry : entries) {\n                String entryKey = entry.getKey();\n                java.lang.String columnStringDictionaryUnmanagedEntryValue = entry.getValue();\n                columnStringDictionaryOsMap.put(entryKey, columnStringDictionaryUnmanagedEntryValue);\n            }\n        }\n\n        RealmDictionary<java.lang.Integer> columnIntegerDictionaryUnmanagedDictionary = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnIntegerDictionary();\n        if (columnIntegerDictionaryUnmanagedDictionary != null) {\n            OsMap columnIntegerDictionaryOsMap = new OsMap(table.getUncheckedRow(objKey), columnInfo.columnIntegerDictionaryColKey);\n            java.util.Set<java.util.Map.Entry<String, java.lang.Integer>> entries = columnIntegerDictionaryUnmanagedDictionary.entrySet();\n            for (java.util.Map.Entry<String, java.lang.Integer> entry : entries) {\n                String entryKey = entry.getKey();\n                java.lang.Integer columnIntegerDictionaryUnmanagedEntryValue = entry.getValue();\n                columnIntegerDictionaryOsMap.put(entryKey, columnIntegerDictionaryUnmanagedEntryValue);\n            }\n        }\n\n        RealmDictionary<java.lang.Float> columnFloatDictionaryUnmanagedDictionary = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnFloatDictionary();\n        if (columnFloatDictionaryUnmanagedDictionary != null) {\n            OsMap columnFloatDictionaryOsMap = new OsMap(table.getUncheckedRow(objKey), columnInfo.columnFloatDictionaryColKey);\n            java.util.Set<java.util.Map.Entry<String, java.lang.Float>> entries = columnFloatDictionaryUnmanagedDictionary.entrySet();\n            for (java.util.Map.Entry<String, java.lang.Float> entry : entries) {\n                String entryKey = entry.getKey();\n                java.lang.Float columnFloatDictionaryUnmanagedEntryValue = entry.getValue();\n                columnFloatDictionaryOsMap.put(entryKey, columnFloatDictionaryUnmanagedEntryValue);\n            }\n        }\n\n        RealmDictionary<java.lang.Long> columnLongDictionaryUnmanagedDictionary = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnLongDictionary();\n        if (columnLongDictionaryUnmanagedDictionary != null) {\n            OsMap columnLongDictionaryOsMap = new OsMap(table.getUncheckedRow(objKey), columnInfo.columnLongDictionaryColKey);\n            java.util.Set<java.util.Map.Entry<String, java.lang.Long>> entries = columnLongDictionaryUnmanagedDictionary.entrySet();\n            for (java.util.Map.Entry<String, java.lang.Long> entry : entries) {\n                String entryKey = entry.getKey();\n                java.lang.Long columnLongDictionaryUnmanagedEntryValue = entry.getValue();\n                columnLongDictionaryOsMap.put(entryKey, columnLongDictionaryUnmanagedEntryValue);\n            }\n        }\n\n        RealmDictionary<java.lang.Short> columnShortDictionaryUnmanagedDictionary = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnShortDictionary();\n        if (columnShortDictionaryUnmanagedDictionary != null) {\n            OsMap columnShortDictionaryOsMap = new OsMap(table.getUncheckedRow(objKey), columnInfo.columnShortDictionaryColKey);\n            java.util.Set<java.util.Map.Entry<String, java.lang.Short>> entries = columnShortDictionaryUnmanagedDictionary.entrySet();\n            for (java.util.Map.Entry<String, java.lang.Short> entry : entries) {\n                String entryKey = entry.getKey();\n                java.lang.Short columnShortDictionaryUnmanagedEntryValue = entry.getValue();\n                columnShortDictionaryOsMap.put(entryKey, columnShortDictionaryUnmanagedEntryValue);\n            }\n        }\n\n        RealmDictionary<java.lang.Double> columnDoubleDictionaryUnmanagedDictionary = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnDoubleDictionary();\n        if (columnDoubleDictionaryUnmanagedDictionary != null) {\n            OsMap columnDoubleDictionaryOsMap = new OsMap(table.getUncheckedRow(objKey), columnInfo.columnDoubleDictionaryColKey);\n            java.util.Set<java.util.Map.Entry<String, java.lang.Double>> entries = columnDoubleDictionaryUnmanagedDictionary.entrySet();\n            for (java.util.Map.Entry<String, java.lang.Double> entry : entries) {\n                String entryKey = entry.getKey();\n                java.lang.Double columnDoubleDictionaryUnmanagedEntryValue = entry.getValue();\n                columnDoubleDictionaryOsMap.put(entryKey, columnDoubleDictionaryUnmanagedEntryValue);\n            }\n        }\n\n        RealmDictionary<java.lang.Byte> columnByteDictionaryUnmanagedDictionary = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnByteDictionary();\n        if (columnByteDictionaryUnmanagedDictionary != null) {\n            OsMap columnByteDictionaryOsMap = new OsMap(table.getUncheckedRow(objKey), columnInfo.columnByteDictionaryColKey);\n            java.util.Set<java.util.Map.Entry<String, java.lang.Byte>> entries = columnByteDictionaryUnmanagedDictionary.entrySet();\n            for (java.util.Map.Entry<String, java.lang.Byte> entry : entries) {\n                String entryKey = entry.getKey();\n                java.lang.Byte columnByteDictionaryUnmanagedEntryValue = entry.getValue();\n                columnByteDictionaryOsMap.put(entryKey, columnByteDictionaryUnmanagedEntryValue);\n            }\n        }\n\n        RealmDictionary<byte[]> columnBinaryDictionaryUnmanagedDictionary = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnBinaryDictionary();\n        if (columnBinaryDictionaryUnmanagedDictionary != null) {\n            OsMap columnBinaryDictionaryOsMap = new OsMap(table.getUncheckedRow(objKey), columnInfo.columnBinaryDictionaryColKey);\n            java.util.Set<java.util.Map.Entry<String, byte[]>> entries = columnBinaryDictionaryUnmanagedDictionary.entrySet();\n            for (java.util.Map.Entry<String, byte[]> entry : entries) {\n                String entryKey = entry.getKey();\n                byte[] columnBinaryDictionaryUnmanagedEntryValue = entry.getValue();\n                columnBinaryDictionaryOsMap.put(entryKey, columnBinaryDictionaryUnmanagedEntryValue);\n            }\n        }\n\n        RealmDictionary<java.util.Date> columnDateDictionaryUnmanagedDictionary = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnDateDictionary();\n        if (columnDateDictionaryUnmanagedDictionary != null) {\n            OsMap columnDateDictionaryOsMap = new OsMap(table.getUncheckedRow(objKey), columnInfo.columnDateDictionaryColKey);\n            java.util.Set<java.util.Map.Entry<String, java.util.Date>> entries = columnDateDictionaryUnmanagedDictionary.entrySet();\n            for (java.util.Map.Entry<String, java.util.Date> entry : entries) {\n                String entryKey = entry.getKey();\n                java.util.Date columnDateDictionaryUnmanagedEntryValue = entry.getValue();\n                columnDateDictionaryOsMap.put(entryKey, columnDateDictionaryUnmanagedEntryValue);\n            }\n        }\n\n        RealmDictionary<org.bson.types.ObjectId> columnObjectIdDictionaryUnmanagedDictionary = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnObjectIdDictionary();\n        if (columnObjectIdDictionaryUnmanagedDictionary != null) {\n            OsMap columnObjectIdDictionaryOsMap = new OsMap(table.getUncheckedRow(objKey), columnInfo.columnObjectIdDictionaryColKey);\n            java.util.Set<java.util.Map.Entry<String, org.bson.types.ObjectId>> entries = columnObjectIdDictionaryUnmanagedDictionary.entrySet();\n            for (java.util.Map.Entry<String, org.bson.types.ObjectId> entry : entries) {\n                String entryKey = entry.getKey();\n                org.bson.types.ObjectId columnObjectIdDictionaryUnmanagedEntryValue = entry.getValue();\n                columnObjectIdDictionaryOsMap.put(entryKey, columnObjectIdDictionaryUnmanagedEntryValue);\n            }\n        }\n\n        RealmDictionary<java.util.UUID> columnUUIDDictionaryUnmanagedDictionary = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnUUIDDictionary();\n        if (columnUUIDDictionaryUnmanagedDictionary != null) {\n            OsMap columnUUIDDictionaryOsMap = new OsMap(table.getUncheckedRow(objKey), columnInfo.columnUUIDDictionaryColKey);\n            java.util.Set<java.util.Map.Entry<String, java.util.UUID>> entries = columnUUIDDictionaryUnmanagedDictionary.entrySet();\n            for (java.util.Map.Entry<String, java.util.UUID> entry : entries) {\n                String entryKey = entry.getKey();\n                java.util.UUID columnUUIDDictionaryUnmanagedEntryValue = entry.getValue();\n                columnUUIDDictionaryOsMap.put(entryKey, columnUUIDDictionaryUnmanagedEntryValue);\n            }\n        }\n\n        RealmDictionary<org.bson.types.Decimal128> columnDecimal128DictionaryUnmanagedDictionary = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnDecimal128Dictionary();\n        if (columnDecimal128DictionaryUnmanagedDictionary != null) {\n            OsMap columnDecimal128DictionaryOsMap = new OsMap(table.getUncheckedRow(objKey), columnInfo.columnDecimal128DictionaryColKey);\n            java.util.Set<java.util.Map.Entry<String, org.bson.types.Decimal128>> entries = columnDecimal128DictionaryUnmanagedDictionary.entrySet();\n            for (java.util.Map.Entry<String, org.bson.types.Decimal128> entry : entries) {\n                String entryKey = entry.getKey();\n                org.bson.types.Decimal128 columnDecimal128DictionaryUnmanagedEntryValue = entry.getValue();\n                columnDecimal128DictionaryOsMap.put(entryKey, columnDecimal128DictionaryUnmanagedEntryValue);\n            }\n        }\n        RealmDictionary<RealmAny> columnRealmAnyDictionaryUnmanagedDictionary = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnRealmAnyDictionary();\n        if (columnRealmAnyDictionaryUnmanagedDictionary != null) {\n            OsMap columnRealmAnyDictionaryOsMap = new OsMap(table.getUncheckedRow(objKey), columnInfo.columnRealmAnyDictionaryColKey);\n            java.util.Set<java.util.Map.Entry<String, io.realm.RealmAny>> entries = columnRealmAnyDictionaryUnmanagedDictionary.entrySet();\n            java.util.List<String> keys = new java.util.ArrayList<>();\n            java.util.List<Long> realmAnyPointers = new java.util.ArrayList<>();\n            for (java.util.Map.Entry<String, io.realm.RealmAny> entry : entries) {\n                RealmAny realmAnyItem = entry.getValue();\n                realmAnyItem = ProxyUtils.insertOrUpdate(realmAnyItem, realm, cache);\n                columnRealmAnyDictionaryOsMap.putRealmAny(entry.getKey(), realmAnyItem.getNativePtr());\n            }\n        }\n\n        return objKey;\n    }\n\n    public static void insertOrUpdate(Realm realm, Iterator<? extends RealmModel> objects, Map<RealmModel,Long> cache) {\n        Table table = realm.getTable(some.test.AllTypes.class);\n        long tableNativePtr = table.getNativePtr();\n        AllTypesColumnInfo columnInfo = (AllTypesColumnInfo) realm.getSchema().getColumnInfo(some.test.AllTypes.class);\n        long pkColumnKey = columnInfo.columnStringColKey;\n        some.test.AllTypes object = null;\n        while (objects.hasNext()) {\n            object = (some.test.AllTypes) objects.next();\n            if (cache.containsKey(object)) {\n                continue;\n            }\n            if (object instanceof RealmObjectProxy && !RealmObject.isFrozen(object) && ((RealmObjectProxy) object).realmGet$proxyState().getRealm$realm() != null && ((RealmObjectProxy) object).realmGet$proxyState().getRealm$realm().getPath().equals(realm.getPath())) {\n                cache.put(object, ((RealmObjectProxy) object).realmGet$proxyState().getRow$realm().getObjectKey());\n                continue;\n            }\n            String primaryKeyValue = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnString();\n            long objKey = Table.NO_MATCH;\n            if (primaryKeyValue == null) {\n                objKey = Table.nativeFindFirstNull(tableNativePtr, pkColumnKey);\n            } else {\n                objKey = Table.nativeFindFirstString(tableNativePtr, pkColumnKey, primaryKeyValue);\n            }\n            if (objKey == Table.NO_MATCH) {\n                objKey = OsObject.createRowWithPrimaryKey(table, pkColumnKey, primaryKeyValue);\n            }\n            cache.put(object, objKey);\n            Table.nativeSetLong(tableNativePtr, columnInfo.columnLongColKey, objKey, ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnLong(), false);\n            Table.nativeSetFloat(tableNativePtr, columnInfo.columnFloatColKey, objKey, ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnFloat(), false);\n            Table.nativeSetDouble(tableNativePtr, columnInfo.columnDoubleColKey, objKey, ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnDouble(), false);\n            Table.nativeSetBoolean(tableNativePtr, columnInfo.columnBooleanColKey, objKey, ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnBoolean(), false);\n            org.bson.types.Decimal128 realmGet$columnDecimal128 = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnDecimal128();\n            if (realmGet$columnDecimal128 != null) {\n                Table.nativeSetDecimal128(tableNativePtr, columnInfo.columnDecimal128ColKey, objKey, realmGet$columnDecimal128.getLow(), realmGet$columnDecimal128.getHigh(), false);\n            } else {\n                Table.nativeSetNull(tableNativePtr, columnInfo.columnDecimal128ColKey, objKey, false);\n            }\n            org.bson.types.ObjectId realmGet$columnObjectId = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnObjectId();\n            if (realmGet$columnObjectId != null) {\n                Table.nativeSetObjectId(tableNativePtr, columnInfo.columnObjectIdColKey, objKey, realmGet$columnObjectId.toString(), false);\n            } else {\n                Table.nativeSetNull(tableNativePtr, columnInfo.columnObjectIdColKey, objKey, false);\n            }\n            java.util.UUID realmGet$columnUUID = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnUUID();\n            if (realmGet$columnUUID != null) {\n                Table.nativeSetUUID(tableNativePtr, columnInfo.columnUUIDColKey, objKey, realmGet$columnUUID.toString(), false);\n            } else {\n                Table.nativeSetNull(tableNativePtr, columnInfo.columnUUIDColKey, objKey, false);\n            }\n            java.util.Date realmGet$columnDate = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnDate();\n            if (realmGet$columnDate != null) {\n                Table.nativeSetTimestamp(tableNativePtr, columnInfo.columnDateColKey, objKey, realmGet$columnDate.getTime(), false);\n            } else {\n                Table.nativeSetNull(tableNativePtr, columnInfo.columnDateColKey, objKey, false);\n            }\n            RealmAny columnRealmAnyRealmAny = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnRealmAny();\n            columnRealmAnyRealmAny = ProxyUtils.insertOrUpdate(columnRealmAnyRealmAny, realm, cache);\n            Table.nativeSetRealmAny(tableNativePtr, columnInfo.columnRealmAnyColKey, objKey, columnRealmAnyRealmAny.getNativePtr(), false);\n            byte[] realmGet$columnBinary = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnBinary();\n            if (realmGet$columnBinary != null) {\n                Table.nativeSetByteArray(tableNativePtr, columnInfo.columnBinaryColKey, objKey, realmGet$columnBinary, false);\n            } else {\n                Table.nativeSetNull(tableNativePtr, columnInfo.columnBinaryColKey, objKey, false);\n            }\n            Long realmGet$columnMutableRealmInteger = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnMutableRealmInteger().get();\n            if (realmGet$columnMutableRealmInteger != null) {\n                Table.nativeSetLong(tableNativePtr, columnInfo.columnMutableRealmIntegerColKey, objKey, realmGet$columnMutableRealmInteger.longValue(), false);\n            } else {\n                Table.nativeSetNull(tableNativePtr, columnInfo.columnMutableRealmIntegerColKey, objKey, false);\n            }\n\n            some.test.AllTypes columnObjectObj = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnObject();\n            if (columnObjectObj != null) {\n                Long cachecolumnObject = cache.get(columnObjectObj);\n                if (cachecolumnObject == null) {\n                    cachecolumnObject = some_test_AllTypesRealmProxy.insertOrUpdate(realm, columnObjectObj, cache);\n                }\n                Table.nativeSetLink(tableNativePtr, columnInfo.columnObjectColKey, objKey, cachecolumnObject, false);\n            } else {\n                Table.nativeNullifyLink(tableNativePtr, columnInfo.columnObjectColKey, objKey);\n            }\n\n            some.test.Simple columnObjectWithoutPkObj = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnObjectWithoutPk();\n            if (columnObjectWithoutPkObj != null) {\n                Long cachecolumnObjectWithoutPk = cache.get(columnObjectWithoutPkObj);\n                if (cachecolumnObjectWithoutPk == null) {\n                    cachecolumnObjectWithoutPk = some_test_SimpleRealmProxy.insertOrUpdate(realm, columnObjectWithoutPkObj, cache);\n                }\n                Table.nativeSetLink(tableNativePtr, columnInfo.columnObjectWithoutPkColKey, objKey, cachecolumnObjectWithoutPk, false);\n            } else {\n                Table.nativeNullifyLink(tableNativePtr, columnInfo.columnObjectWithoutPkColKey, objKey);\n            }\n\n            OsList columnRealmListOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.columnRealmListColKey);\n            RealmList<some.test.AllTypes> columnRealmListList = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnRealmList();\n            if (columnRealmListList != null && columnRealmListList.size() == columnRealmListOsList.size()) {\n                // For lists of equal lengths, we need to set each element directly as clearing the receiver list can be wrong if the input and target list are the same.\n                int objectCount = columnRealmListList.size();\n                for (int i = 0; i < objectCount; i++) {\n                    some.test.AllTypes columnRealmListItem = columnRealmListList.get(i);\n                    Long cacheItemIndexcolumnRealmList = cache.get(columnRealmListItem);\n                    if (cacheItemIndexcolumnRealmList == null) {\n                        cacheItemIndexcolumnRealmList = some_test_AllTypesRealmProxy.insertOrUpdate(realm, columnRealmListItem, cache);\n                    }\n                    columnRealmListOsList.setRow(i, cacheItemIndexcolumnRealmList);\n                }\n            } else {\n                columnRealmListOsList.removeAll();\n                if (columnRealmListList != null) {\n                    for (some.test.AllTypes columnRealmListItem : columnRealmListList) {\n                        Long cacheItemIndexcolumnRealmList = cache.get(columnRealmListItem);\n                        if (cacheItemIndexcolumnRealmList == null) {\n                            cacheItemIndexcolumnRealmList = some_test_AllTypesRealmProxy.insertOrUpdate(realm, columnRealmListItem, cache);\n                        }\n                        columnRealmListOsList.addRow(cacheItemIndexcolumnRealmList);\n                    }\n                }\n            }\n\n\n            OsList columnRealmListNoPkOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.columnRealmListNoPkColKey);\n            RealmList<some.test.Simple> columnRealmListNoPkList = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnRealmListNoPk();\n            if (columnRealmListNoPkList != null && columnRealmListNoPkList.size() == columnRealmListNoPkOsList.size()) {\n                // For lists of equal lengths, we need to set each element directly as clearing the receiver list can be wrong if the input and target list are the same.\n                int objectCount = columnRealmListNoPkList.size();\n                for (int i = 0; i < objectCount; i++) {\n                    some.test.Simple columnRealmListNoPkItem = columnRealmListNoPkList.get(i);\n                    Long cacheItemIndexcolumnRealmListNoPk = cache.get(columnRealmListNoPkItem);\n                    if (cacheItemIndexcolumnRealmListNoPk == null) {\n                        cacheItemIndexcolumnRealmListNoPk = some_test_SimpleRealmProxy.insertOrUpdate(realm, columnRealmListNoPkItem, cache);\n                    }\n                    columnRealmListNoPkOsList.setRow(i, cacheItemIndexcolumnRealmListNoPk);\n                }\n            } else {\n                columnRealmListNoPkOsList.removeAll();\n                if (columnRealmListNoPkList != null) {\n                    for (some.test.Simple columnRealmListNoPkItem : columnRealmListNoPkList) {\n                        Long cacheItemIndexcolumnRealmListNoPk = cache.get(columnRealmListNoPkItem);\n                        if (cacheItemIndexcolumnRealmListNoPk == null) {\n                            cacheItemIndexcolumnRealmListNoPk = some_test_SimpleRealmProxy.insertOrUpdate(realm, columnRealmListNoPkItem, cache);\n                        }\n                        columnRealmListNoPkOsList.addRow(cacheItemIndexcolumnRealmListNoPk);\n                    }\n                }\n            }\n\n\n            OsList columnRealmFinalListOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.columnRealmFinalListColKey);\n            RealmList<some.test.AllTypes> columnRealmFinalListList = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnRealmFinalList();\n            if (columnRealmFinalListList != null && columnRealmFinalListList.size() == columnRealmFinalListOsList.size()) {\n                // For lists of equal lengths, we need to set each element directly as clearing the receiver list can be wrong if the input and target list are the same.\n                int objectCount = columnRealmFinalListList.size();\n                for (int i = 0; i < objectCount; i++) {\n                    some.test.AllTypes columnRealmFinalListItem = columnRealmFinalListList.get(i);\n                    Long cacheItemIndexcolumnRealmFinalList = cache.get(columnRealmFinalListItem);\n                    if (cacheItemIndexcolumnRealmFinalList == null) {\n                        cacheItemIndexcolumnRealmFinalList = some_test_AllTypesRealmProxy.insertOrUpdate(realm, columnRealmFinalListItem, cache);\n                    }\n                    columnRealmFinalListOsList.setRow(i, cacheItemIndexcolumnRealmFinalList);\n                }\n            } else {\n                columnRealmFinalListOsList.removeAll();\n                if (columnRealmFinalListList != null) {\n                    for (some.test.AllTypes columnRealmFinalListItem : columnRealmFinalListList) {\n                        Long cacheItemIndexcolumnRealmFinalList = cache.get(columnRealmFinalListItem);\n                        if (cacheItemIndexcolumnRealmFinalList == null) {\n                            cacheItemIndexcolumnRealmFinalList = some_test_AllTypesRealmProxy.insertOrUpdate(realm, columnRealmFinalListItem, cache);\n                        }\n                        columnRealmFinalListOsList.addRow(cacheItemIndexcolumnRealmFinalList);\n                    }\n                }\n            }\n\n\n            OsList columnRealmFinalListNoPkOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.columnRealmFinalListNoPkColKey);\n            RealmList<some.test.Simple> columnRealmFinalListNoPkList = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnRealmFinalListNoPk();\n            if (columnRealmFinalListNoPkList != null && columnRealmFinalListNoPkList.size() == columnRealmFinalListNoPkOsList.size()) {\n                // For lists of equal lengths, we need to set each element directly as clearing the receiver list can be wrong if the input and target list are the same.\n                int objectCount = columnRealmFinalListNoPkList.size();\n                for (int i = 0; i < objectCount; i++) {\n                    some.test.Simple columnRealmFinalListNoPkItem = columnRealmFinalListNoPkList.get(i);\n                    Long cacheItemIndexcolumnRealmFinalListNoPk = cache.get(columnRealmFinalListNoPkItem);\n                    if (cacheItemIndexcolumnRealmFinalListNoPk == null) {\n                        cacheItemIndexcolumnRealmFinalListNoPk = some_test_SimpleRealmProxy.insertOrUpdate(realm, columnRealmFinalListNoPkItem, cache);\n                    }\n                    columnRealmFinalListNoPkOsList.setRow(i, cacheItemIndexcolumnRealmFinalListNoPk);\n                }\n            } else {\n                columnRealmFinalListNoPkOsList.removeAll();\n                if (columnRealmFinalListNoPkList != null) {\n                    for (some.test.Simple columnRealmFinalListNoPkItem : columnRealmFinalListNoPkList) {\n                        Long cacheItemIndexcolumnRealmFinalListNoPk = cache.get(columnRealmFinalListNoPkItem);\n                        if (cacheItemIndexcolumnRealmFinalListNoPk == null) {\n                            cacheItemIndexcolumnRealmFinalListNoPk = some_test_SimpleRealmProxy.insertOrUpdate(realm, columnRealmFinalListNoPkItem, cache);\n                        }\n                        columnRealmFinalListNoPkOsList.addRow(cacheItemIndexcolumnRealmFinalListNoPk);\n                    }\n                }\n            }\n\n\n            OsList columnStringListOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.columnStringListColKey);\n            columnStringListOsList.removeAll();\n            RealmList<java.lang.String> columnStringListList = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnStringList();\n            if (columnStringListList != null) {\n                for (java.lang.String columnStringListItem : columnStringListList) {\n                    if (columnStringListItem == null) {\n                        columnStringListOsList.addNull();\n                    } else {\n                        columnStringListOsList.addString(columnStringListItem);\n                    }\n                }\n            }\n\n\n            OsList columnBinaryListOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.columnBinaryListColKey);\n            columnBinaryListOsList.removeAll();\n            RealmList<byte[]> columnBinaryListList = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnBinaryList();\n            if (columnBinaryListList != null) {\n                for (byte[] columnBinaryListItem : columnBinaryListList) {\n                    if (columnBinaryListItem == null) {\n                        columnBinaryListOsList.addNull();\n                    } else {\n                        columnBinaryListOsList.addBinary(columnBinaryListItem);\n                    }\n                }\n            }\n\n\n            OsList columnBooleanListOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.columnBooleanListColKey);\n            columnBooleanListOsList.removeAll();\n            RealmList<java.lang.Boolean> columnBooleanListList = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnBooleanList();\n            if (columnBooleanListList != null) {\n                for (java.lang.Boolean columnBooleanListItem : columnBooleanListList) {\n                    if (columnBooleanListItem == null) {\n                        columnBooleanListOsList.addNull();\n                    } else {\n                        columnBooleanListOsList.addBoolean(columnBooleanListItem);\n                    }\n                }\n            }\n\n\n            OsList columnLongListOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.columnLongListColKey);\n            columnLongListOsList.removeAll();\n            RealmList<java.lang.Long> columnLongListList = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnLongList();\n            if (columnLongListList != null) {\n                for (java.lang.Long columnLongListItem : columnLongListList) {\n                    if (columnLongListItem == null) {\n                        columnLongListOsList.addNull();\n                    } else {\n                        columnLongListOsList.addLong(columnLongListItem.longValue());\n                    }\n                }\n            }\n\n\n            OsList columnIntegerListOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.columnIntegerListColKey);\n            columnIntegerListOsList.removeAll();\n            RealmList<java.lang.Integer> columnIntegerListList = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnIntegerList();\n            if (columnIntegerListList != null) {\n                for (java.lang.Integer columnIntegerListItem : columnIntegerListList) {\n                    if (columnIntegerListItem == null) {\n                        columnIntegerListOsList.addNull();\n                    } else {\n                        columnIntegerListOsList.addLong(columnIntegerListItem.longValue());\n                    }\n                }\n            }\n\n\n            OsList columnShortListOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.columnShortListColKey);\n            columnShortListOsList.removeAll();\n            RealmList<java.lang.Short> columnShortListList = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnShortList();\n            if (columnShortListList != null) {\n                for (java.lang.Short columnShortListItem : columnShortListList) {\n                    if (columnShortListItem == null) {\n                        columnShortListOsList.addNull();\n                    } else {\n                        columnShortListOsList.addLong(columnShortListItem.longValue());\n                    }\n                }\n            }\n\n\n            OsList columnByteListOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.columnByteListColKey);\n            columnByteListOsList.removeAll();\n            RealmList<java.lang.Byte> columnByteListList = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnByteList();\n            if (columnByteListList != null) {\n                for (java.lang.Byte columnByteListItem : columnByteListList) {\n                    if (columnByteListItem == null) {\n                        columnByteListOsList.addNull();\n                    } else {\n                        columnByteListOsList.addLong(columnByteListItem.longValue());\n                    }\n                }\n            }\n\n\n            OsList columnDoubleListOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.columnDoubleListColKey);\n            columnDoubleListOsList.removeAll();\n            RealmList<java.lang.Double> columnDoubleListList = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnDoubleList();\n            if (columnDoubleListList != null) {\n                for (java.lang.Double columnDoubleListItem : columnDoubleListList) {\n                    if (columnDoubleListItem == null) {\n                        columnDoubleListOsList.addNull();\n                    } else {\n                        columnDoubleListOsList.addDouble(columnDoubleListItem.doubleValue());\n                    }\n                }\n            }\n\n\n            OsList columnFloatListOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.columnFloatListColKey);\n            columnFloatListOsList.removeAll();\n            RealmList<java.lang.Float> columnFloatListList = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnFloatList();\n            if (columnFloatListList != null) {\n                for (java.lang.Float columnFloatListItem : columnFloatListList) {\n                    if (columnFloatListItem == null) {\n                        columnFloatListOsList.addNull();\n                    } else {\n                        columnFloatListOsList.addFloat(columnFloatListItem.floatValue());\n                    }\n                }\n            }\n\n\n            OsList columnDateListOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.columnDateListColKey);\n            columnDateListOsList.removeAll();\n            RealmList<java.util.Date> columnDateListList = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnDateList();\n            if (columnDateListList != null) {\n                for (java.util.Date columnDateListItem : columnDateListList) {\n                    if (columnDateListItem == null) {\n                        columnDateListOsList.addNull();\n                    } else {\n                        columnDateListOsList.addDate(columnDateListItem);\n                    }\n                }\n            }\n\n\n            OsList columnDecimal128ListOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.columnDecimal128ListColKey);\n            columnDecimal128ListOsList.removeAll();\n            RealmList<org.bson.types.Decimal128> columnDecimal128ListList = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnDecimal128List();\n            if (columnDecimal128ListList != null) {\n                for (org.bson.types.Decimal128 columnDecimal128ListItem : columnDecimal128ListList) {\n                    if (columnDecimal128ListItem == null) {\n                        columnDecimal128ListOsList.addNull();\n                    } else {\n                        columnDecimal128ListOsList.addDecimal128(columnDecimal128ListItem);\n                    }\n                }\n            }\n\n\n            OsList columnObjectIdListOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.columnObjectIdListColKey);\n            columnObjectIdListOsList.removeAll();\n            RealmList<org.bson.types.ObjectId> columnObjectIdListList = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnObjectIdList();\n            if (columnObjectIdListList != null) {\n                for (org.bson.types.ObjectId columnObjectIdListItem : columnObjectIdListList) {\n                    if (columnObjectIdListItem == null) {\n                        columnObjectIdListOsList.addNull();\n                    } else {\n                        columnObjectIdListOsList.addObjectId(columnObjectIdListItem);\n                    }\n                }\n            }\n\n\n            OsList columnUUIDListOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.columnUUIDListColKey);\n            columnUUIDListOsList.removeAll();\n            RealmList<java.util.UUID> columnUUIDListList = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnUUIDList();\n            if (columnUUIDListList != null) {\n                for (java.util.UUID columnUUIDListItem : columnUUIDListList) {\n                    if (columnUUIDListItem == null) {\n                        columnUUIDListOsList.addNull();\n                    } else {\n                        columnUUIDListOsList.addUUID(columnUUIDListItem);\n                    }\n                }\n            }\n\n\n            OsList columnRealmAnyListOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.columnRealmAnyListColKey);\n            RealmList<RealmAny> columnRealmAnyListList = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnRealmAnyList();\n            if (columnRealmAnyListList != null && columnRealmAnyListList.size() == columnRealmAnyListOsList.size()) {\n                // For lists of equal lengths, we need to set each element directly as clearing the receiver list can be wrong if the input and target list are the same.\n                int objectCount = columnRealmAnyListList.size();\n                for (int i = 0; i < objectCount; i++) {\n                    RealmAny columnRealmAnyListItem = columnRealmAnyListList.get(i);\n                    Long cacheItemIndexcolumnRealmAnyList = cache.get(columnRealmAnyListItem);\n                    if (cacheItemIndexcolumnRealmAnyList == null) {\n                        columnRealmAnyListItem = ProxyUtils.insertOrUpdate(columnRealmAnyListItem, realm, cache);\n                    }\n                    columnRealmAnyListOsList.setRealmAny(i, columnRealmAnyListItem.getNativePtr());\n                }\n            } else {\n                columnRealmAnyListOsList.removeAll();\n                if (columnRealmAnyListList != null) {\n                    for (RealmAny columnRealmAnyListItem : columnRealmAnyListList) {\n                        Long cacheItemIndexcolumnRealmAnyList = cache.get(columnRealmAnyListItem);\n                        if (cacheItemIndexcolumnRealmAnyList == null) {\n                            columnRealmAnyListItem = ProxyUtils.insertOrUpdate(columnRealmAnyListItem, realm, cache);\n                        }\n                        columnRealmAnyListOsList.addRealmAny(columnRealmAnyListItem.getNativePtr());\n                    }\n                }\n            }\n            RealmDictionary<some.test.AllTypes> columnRealmDictionaryUnmanagedDictionary = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnRealmDictionary();\n            if (columnRealmDictionaryUnmanagedDictionary != null) {\n                OsMap columnRealmDictionaryOsMap = new OsMap(table.getUncheckedRow(objKey), columnInfo.columnRealmDictionaryColKey);\n                java.util.Set<java.util.Map.Entry<String, some.test.AllTypes>> entries = columnRealmDictionaryUnmanagedDictionary.entrySet();\n                for (java.util.Map.Entry<String, some.test.AllTypes> entry : entries) {\n                    String entryKey = entry.getKey();\n                    some.test.AllTypes columnRealmDictionaryUnmanagedEntryValue = entry.getValue();\n                    if(columnRealmDictionaryUnmanagedEntryValue == null) {\n                        columnRealmDictionaryOsMap.put(entryKey, null);\n                    } else {\n                        Long cacheItemIndexcolumnRealmDictionary = cache.get(columnRealmDictionaryUnmanagedEntryValue);\n                        if (cacheItemIndexcolumnRealmDictionary == null) {\n                            cacheItemIndexcolumnRealmDictionary = some_test_AllTypesRealmProxy.insertOrUpdate(realm, columnRealmDictionaryUnmanagedEntryValue, cache);\n                        }\n                        columnRealmDictionaryOsMap.putRow(entryKey, cacheItemIndexcolumnRealmDictionary);\n                    }\n                }\n            }\n\n            RealmDictionary<java.lang.Boolean> columnBooleanDictionaryUnmanagedDictionary = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnBooleanDictionary();\n            if (columnBooleanDictionaryUnmanagedDictionary != null) {\n                OsMap columnBooleanDictionaryOsMap = new OsMap(table.getUncheckedRow(objKey), columnInfo.columnBooleanDictionaryColKey);\n                java.util.Set<java.util.Map.Entry<String, java.lang.Boolean>> entries = columnBooleanDictionaryUnmanagedDictionary.entrySet();\n                for (java.util.Map.Entry<String, java.lang.Boolean> entry : entries) {\n                    String entryKey = entry.getKey();\n                    java.lang.Boolean columnBooleanDictionaryUnmanagedEntryValue = entry.getValue();\n                    columnBooleanDictionaryOsMap.put(entryKey, columnBooleanDictionaryUnmanagedEntryValue);\n                }\n            }\n\n            RealmDictionary<java.lang.String> columnStringDictionaryUnmanagedDictionary = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnStringDictionary();\n            if (columnStringDictionaryUnmanagedDictionary != null) {\n                OsMap columnStringDictionaryOsMap = new OsMap(table.getUncheckedRow(objKey), columnInfo.columnStringDictionaryColKey);\n                java.util.Set<java.util.Map.Entry<String, java.lang.String>> entries = columnStringDictionaryUnmanagedDictionary.entrySet();\n                for (java.util.Map.Entry<String, java.lang.String> entry : entries) {\n                    String entryKey = entry.getKey();\n                    java.lang.String columnStringDictionaryUnmanagedEntryValue = entry.getValue();\n                    columnStringDictionaryOsMap.put(entryKey, columnStringDictionaryUnmanagedEntryValue);\n                }\n            }\n\n            RealmDictionary<java.lang.Integer> columnIntegerDictionaryUnmanagedDictionary = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnIntegerDictionary();\n            if (columnIntegerDictionaryUnmanagedDictionary != null) {\n                OsMap columnIntegerDictionaryOsMap = new OsMap(table.getUncheckedRow(objKey), columnInfo.columnIntegerDictionaryColKey);\n                java.util.Set<java.util.Map.Entry<String, java.lang.Integer>> entries = columnIntegerDictionaryUnmanagedDictionary.entrySet();\n                for (java.util.Map.Entry<String, java.lang.Integer> entry : entries) {\n                    String entryKey = entry.getKey();\n                    java.lang.Integer columnIntegerDictionaryUnmanagedEntryValue = entry.getValue();\n                    columnIntegerDictionaryOsMap.put(entryKey, columnIntegerDictionaryUnmanagedEntryValue);\n                }\n            }\n\n            RealmDictionary<java.lang.Float> columnFloatDictionaryUnmanagedDictionary = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnFloatDictionary();\n            if (columnFloatDictionaryUnmanagedDictionary != null) {\n                OsMap columnFloatDictionaryOsMap = new OsMap(table.getUncheckedRow(objKey), columnInfo.columnFloatDictionaryColKey);\n                java.util.Set<java.util.Map.Entry<String, java.lang.Float>> entries = columnFloatDictionaryUnmanagedDictionary.entrySet();\n                for (java.util.Map.Entry<String, java.lang.Float> entry : entries) {\n                    String entryKey = entry.getKey();\n                    java.lang.Float columnFloatDictionaryUnmanagedEntryValue = entry.getValue();\n                    columnFloatDictionaryOsMap.put(entryKey, columnFloatDictionaryUnmanagedEntryValue);\n                }\n            }\n\n            RealmDictionary<java.lang.Long> columnLongDictionaryUnmanagedDictionary = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnLongDictionary();\n            if (columnLongDictionaryUnmanagedDictionary != null) {\n                OsMap columnLongDictionaryOsMap = new OsMap(table.getUncheckedRow(objKey), columnInfo.columnLongDictionaryColKey);\n                java.util.Set<java.util.Map.Entry<String, java.lang.Long>> entries = columnLongDictionaryUnmanagedDictionary.entrySet();\n                for (java.util.Map.Entry<String, java.lang.Long> entry : entries) {\n                    String entryKey = entry.getKey();\n                    java.lang.Long columnLongDictionaryUnmanagedEntryValue = entry.getValue();\n                    columnLongDictionaryOsMap.put(entryKey, columnLongDictionaryUnmanagedEntryValue);\n                }\n            }\n\n            RealmDictionary<java.lang.Short> columnShortDictionaryUnmanagedDictionary = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnShortDictionary();\n            if (columnShortDictionaryUnmanagedDictionary != null) {\n                OsMap columnShortDictionaryOsMap = new OsMap(table.getUncheckedRow(objKey), columnInfo.columnShortDictionaryColKey);\n                java.util.Set<java.util.Map.Entry<String, java.lang.Short>> entries = columnShortDictionaryUnmanagedDictionary.entrySet();\n                for (java.util.Map.Entry<String, java.lang.Short> entry : entries) {\n                    String entryKey = entry.getKey();\n                    java.lang.Short columnShortDictionaryUnmanagedEntryValue = entry.getValue();\n                    columnShortDictionaryOsMap.put(entryKey, columnShortDictionaryUnmanagedEntryValue);\n                }\n            }\n\n            RealmDictionary<java.lang.Double> columnDoubleDictionaryUnmanagedDictionary = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnDoubleDictionary();\n            if (columnDoubleDictionaryUnmanagedDictionary != null) {\n                OsMap columnDoubleDictionaryOsMap = new OsMap(table.getUncheckedRow(objKey), columnInfo.columnDoubleDictionaryColKey);\n                java.util.Set<java.util.Map.Entry<String, java.lang.Double>> entries = columnDoubleDictionaryUnmanagedDictionary.entrySet();\n                for (java.util.Map.Entry<String, java.lang.Double> entry : entries) {\n                    String entryKey = entry.getKey();\n                    java.lang.Double columnDoubleDictionaryUnmanagedEntryValue = entry.getValue();\n                    columnDoubleDictionaryOsMap.put(entryKey, columnDoubleDictionaryUnmanagedEntryValue);\n                }\n            }\n\n            RealmDictionary<java.lang.Byte> columnByteDictionaryUnmanagedDictionary = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnByteDictionary();\n            if (columnByteDictionaryUnmanagedDictionary != null) {\n                OsMap columnByteDictionaryOsMap = new OsMap(table.getUncheckedRow(objKey), columnInfo.columnByteDictionaryColKey);\n                java.util.Set<java.util.Map.Entry<String, java.lang.Byte>> entries = columnByteDictionaryUnmanagedDictionary.entrySet();\n                for (java.util.Map.Entry<String, java.lang.Byte> entry : entries) {\n                    String entryKey = entry.getKey();\n                    java.lang.Byte columnByteDictionaryUnmanagedEntryValue = entry.getValue();\n                    columnByteDictionaryOsMap.put(entryKey, columnByteDictionaryUnmanagedEntryValue);\n                }\n            }\n\n            RealmDictionary<byte[]> columnBinaryDictionaryUnmanagedDictionary = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnBinaryDictionary();\n            if (columnBinaryDictionaryUnmanagedDictionary != null) {\n                OsMap columnBinaryDictionaryOsMap = new OsMap(table.getUncheckedRow(objKey), columnInfo.columnBinaryDictionaryColKey);\n                java.util.Set<java.util.Map.Entry<String, byte[]>> entries = columnBinaryDictionaryUnmanagedDictionary.entrySet();\n                for (java.util.Map.Entry<String, byte[]> entry : entries) {\n                    String entryKey = entry.getKey();\n                    byte[] columnBinaryDictionaryUnmanagedEntryValue = entry.getValue();\n                    columnBinaryDictionaryOsMap.put(entryKey, columnBinaryDictionaryUnmanagedEntryValue);\n                }\n            }\n\n            RealmDictionary<java.util.Date> columnDateDictionaryUnmanagedDictionary = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnDateDictionary();\n            if (columnDateDictionaryUnmanagedDictionary != null) {\n                OsMap columnDateDictionaryOsMap = new OsMap(table.getUncheckedRow(objKey), columnInfo.columnDateDictionaryColKey);\n                java.util.Set<java.util.Map.Entry<String, java.util.Date>> entries = columnDateDictionaryUnmanagedDictionary.entrySet();\n                for (java.util.Map.Entry<String, java.util.Date> entry : entries) {\n                    String entryKey = entry.getKey();\n                    java.util.Date columnDateDictionaryUnmanagedEntryValue = entry.getValue();\n                    columnDateDictionaryOsMap.put(entryKey, columnDateDictionaryUnmanagedEntryValue);\n                }\n            }\n\n            RealmDictionary<org.bson.types.ObjectId> columnObjectIdDictionaryUnmanagedDictionary = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnObjectIdDictionary();\n            if (columnObjectIdDictionaryUnmanagedDictionary != null) {\n                OsMap columnObjectIdDictionaryOsMap = new OsMap(table.getUncheckedRow(objKey), columnInfo.columnObjectIdDictionaryColKey);\n                java.util.Set<java.util.Map.Entry<String, org.bson.types.ObjectId>> entries = columnObjectIdDictionaryUnmanagedDictionary.entrySet();\n                for (java.util.Map.Entry<String, org.bson.types.ObjectId> entry : entries) {\n                    String entryKey = entry.getKey();\n                    org.bson.types.ObjectId columnObjectIdDictionaryUnmanagedEntryValue = entry.getValue();\n                    columnObjectIdDictionaryOsMap.put(entryKey, columnObjectIdDictionaryUnmanagedEntryValue);\n                }\n            }\n\n            RealmDictionary<java.util.UUID> columnUUIDDictionaryUnmanagedDictionary = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnUUIDDictionary();\n            if (columnUUIDDictionaryUnmanagedDictionary != null) {\n                OsMap columnUUIDDictionaryOsMap = new OsMap(table.getUncheckedRow(objKey), columnInfo.columnUUIDDictionaryColKey);\n                java.util.Set<java.util.Map.Entry<String, java.util.UUID>> entries = columnUUIDDictionaryUnmanagedDictionary.entrySet();\n                for (java.util.Map.Entry<String, java.util.UUID> entry : entries) {\n                    String entryKey = entry.getKey();\n                    java.util.UUID columnUUIDDictionaryUnmanagedEntryValue = entry.getValue();\n                    columnUUIDDictionaryOsMap.put(entryKey, columnUUIDDictionaryUnmanagedEntryValue);\n                }\n            }\n\n            RealmDictionary<org.bson.types.Decimal128> columnDecimal128DictionaryUnmanagedDictionary = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnDecimal128Dictionary();\n            if (columnDecimal128DictionaryUnmanagedDictionary != null) {\n                OsMap columnDecimal128DictionaryOsMap = new OsMap(table.getUncheckedRow(objKey), columnInfo.columnDecimal128DictionaryColKey);\n                java.util.Set<java.util.Map.Entry<String, org.bson.types.Decimal128>> entries = columnDecimal128DictionaryUnmanagedDictionary.entrySet();\n                for (java.util.Map.Entry<String, org.bson.types.Decimal128> entry : entries) {\n                    String entryKey = entry.getKey();\n                    org.bson.types.Decimal128 columnDecimal128DictionaryUnmanagedEntryValue = entry.getValue();\n                    columnDecimal128DictionaryOsMap.put(entryKey, columnDecimal128DictionaryUnmanagedEntryValue);\n                }\n            }\n            RealmDictionary<RealmAny> columnRealmAnyDictionaryUnmanagedDictionary = ((some_test_AllTypesRealmProxyInterface) object).realmGet$columnRealmAnyDictionary();\n            if (columnRealmAnyDictionaryUnmanagedDictionary != null) {\n                OsMap columnRealmAnyDictionaryOsMap = new OsMap(table.getUncheckedRow(objKey), columnInfo.columnRealmAnyDictionaryColKey);\n                java.util.Set<java.util.Map.Entry<String, io.realm.RealmAny>> entries = columnRealmAnyDictionaryUnmanagedDictionary.entrySet();\n                java.util.List<String> keys = new java.util.ArrayList<>();\n                java.util.List<Long> realmAnyPointers = new java.util.ArrayList<>();\n                for (java.util.Map.Entry<String, io.realm.RealmAny> entry : entries) {\n                    RealmAny realmAnyItem = entry.getValue();\n                    realmAnyItem = ProxyUtils.insertOrUpdate(realmAnyItem, realm, cache);\n                    columnRealmAnyDictionaryOsMap.putRealmAny(entry.getKey(), realmAnyItem.getNativePtr());\n                }\n            }\n\n        }\n    }\n\n    public static some.test.AllTypes createDetachedCopy(some.test.AllTypes realmObject, int currentDepth, int maxDepth, Map<RealmModel, CacheData<RealmModel>> cache) {\n        if (currentDepth > maxDepth || realmObject == null) {\n            return null;\n        }\n        CacheData<RealmModel> cachedObject = cache.get(realmObject);\n        some.test.AllTypes unmanagedObject;\n        if (cachedObject == null) {\n            unmanagedObject = new some.test.AllTypes();\n            cache.put(realmObject, new RealmObjectProxy.CacheData<RealmModel>(currentDepth, unmanagedObject));\n        } else {\n            // Reuse cached object or recreate it because it was encountered at a lower depth.\n            if (currentDepth >= cachedObject.minDepth) {\n                return (some.test.AllTypes) cachedObject.object;\n            }\n            unmanagedObject = (some.test.AllTypes) cachedObject.object;\n            cachedObject.minDepth = currentDepth;\n        }\n        some_test_AllTypesRealmProxyInterface unmanagedCopy = (some_test_AllTypesRealmProxyInterface) unmanagedObject;\n        some_test_AllTypesRealmProxyInterface realmSource = (some_test_AllTypesRealmProxyInterface) realmObject;\n        Realm objectRealm = (Realm) ((RealmObjectProxy) realmObject).realmGet$proxyState().getRealm$realm();\n        unmanagedCopy.realmSet$columnString(realmSource.realmGet$columnString());\n        unmanagedCopy.realmSet$columnLong(realmSource.realmGet$columnLong());\n        unmanagedCopy.realmSet$columnFloat(realmSource.realmGet$columnFloat());\n        unmanagedCopy.realmSet$columnDouble(realmSource.realmGet$columnDouble());\n        unmanagedCopy.realmSet$columnBoolean(realmSource.realmGet$columnBoolean());\n        unmanagedCopy.realmSet$columnDecimal128(realmSource.realmGet$columnDecimal128());\n        unmanagedCopy.realmSet$columnObjectId(realmSource.realmGet$columnObjectId());\n        unmanagedCopy.realmSet$columnUUID(realmSource.realmGet$columnUUID());\n        unmanagedCopy.realmSet$columnDate(realmSource.realmGet$columnDate());\n\n        // Deep copy of columnRealmAny\n        unmanagedCopy.realmSet$columnRealmAny(ProxyUtils.createDetachedCopy(realmSource.realmGet$columnRealmAny(), objectRealm, currentDepth + 1, maxDepth, cache));\n        unmanagedCopy.realmSet$columnBinary(realmSource.realmGet$columnBinary());\n        unmanagedCopy.realmGet$columnMutableRealmInteger().set(realmSource.realmGet$columnMutableRealmInteger().get());\n\n        // Deep copy of columnObject\n        unmanagedCopy.realmSet$columnObject(some_test_AllTypesRealmProxy.createDetachedCopy(realmSource.realmGet$columnObject(), currentDepth + 1, maxDepth, cache));\n\n        // Deep copy of columnObjectWithoutPk\n        unmanagedCopy.realmSet$columnObjectWithoutPk(some_test_SimpleRealmProxy.createDetachedCopy(realmSource.realmGet$columnObjectWithoutPk(), currentDepth + 1, maxDepth, cache));\n\n        // Deep copy of columnRealmList\n        if (currentDepth == maxDepth) {\n            unmanagedCopy.realmSet$columnRealmList(null);\n        } else {\n            RealmList<some.test.AllTypes> managedcolumnRealmListList = realmSource.realmGet$columnRealmList();\n            RealmList<some.test.AllTypes> unmanagedcolumnRealmListList = new RealmList<some.test.AllTypes>();\n            unmanagedCopy.realmSet$columnRealmList(unmanagedcolumnRealmListList);\n            int nextDepth = currentDepth + 1;\n            int size = managedcolumnRealmListList.size();\n            for (int i = 0; i < size; i++) {\n                some.test.AllTypes item = some_test_AllTypesRealmProxy.createDetachedCopy(managedcolumnRealmListList.get(i), nextDepth, maxDepth, cache);\n                unmanagedcolumnRealmListList.add(item);\n            }\n        }\n\n        // Deep copy of columnRealmListNoPk\n        if (currentDepth == maxDepth) {\n            unmanagedCopy.realmSet$columnRealmListNoPk(null);\n        } else {\n            RealmList<some.test.Simple> managedcolumnRealmListNoPkList = realmSource.realmGet$columnRealmListNoPk();\n            RealmList<some.test.Simple> unmanagedcolumnRealmListNoPkList = new RealmList<some.test.Simple>();\n            unmanagedCopy.realmSet$columnRealmListNoPk(unmanagedcolumnRealmListNoPkList);\n            int nextDepth = currentDepth + 1;\n            int size = managedcolumnRealmListNoPkList.size();\n            for (int i = 0; i < size; i++) {\n                some.test.Simple item = some_test_SimpleRealmProxy.createDetachedCopy(managedcolumnRealmListNoPkList.get(i), nextDepth, maxDepth, cache);\n                unmanagedcolumnRealmListNoPkList.add(item);\n            }\n        }\n\n        // Deep copy of columnRealmFinalList\n        if (currentDepth == maxDepth) {\n            unmanagedCopy.realmSet$columnRealmFinalList(null);\n        } else {\n            RealmList<some.test.AllTypes> managedcolumnRealmFinalListList = realmSource.realmGet$columnRealmFinalList();\n            RealmList<some.test.AllTypes> unmanagedcolumnRealmFinalListList = new RealmList<some.test.AllTypes>();\n            unmanagedCopy.realmSet$columnRealmFinalList(unmanagedcolumnRealmFinalListList);\n            int nextDepth = currentDepth + 1;\n            int size = managedcolumnRealmFinalListList.size();\n            for (int i = 0; i < size; i++) {\n                some.test.AllTypes item = some_test_AllTypesRealmProxy.createDetachedCopy(managedcolumnRealmFinalListList.get(i), nextDepth, maxDepth, cache);\n                unmanagedcolumnRealmFinalListList.add(item);\n            }\n        }\n\n        // Deep copy of columnRealmFinalListNoPk\n        if (currentDepth == maxDepth) {\n            unmanagedCopy.realmSet$columnRealmFinalListNoPk(null);\n        } else {\n            RealmList<some.test.Simple> managedcolumnRealmFinalListNoPkList = realmSource.realmGet$columnRealmFinalListNoPk();\n            RealmList<some.test.Simple> unmanagedcolumnRealmFinalListNoPkList = new RealmList<some.test.Simple>();\n            unmanagedCopy.realmSet$columnRealmFinalListNoPk(unmanagedcolumnRealmFinalListNoPkList);\n            int nextDepth = currentDepth + 1;\n            int size = managedcolumnRealmFinalListNoPkList.size();\n            for (int i = 0; i < size; i++) {\n                some.test.Simple item = some_test_SimpleRealmProxy.createDetachedCopy(managedcolumnRealmFinalListNoPkList.get(i), nextDepth, maxDepth, cache);\n                unmanagedcolumnRealmFinalListNoPkList.add(item);\n            }\n        }\n\n        unmanagedCopy.realmSet$columnStringList(new RealmList<java.lang.String>());\n        unmanagedCopy.realmGet$columnStringList().addAll(realmSource.realmGet$columnStringList());\n\n        unmanagedCopy.realmSet$columnBinaryList(new RealmList<byte[]>());\n        unmanagedCopy.realmGet$columnBinaryList().addAll(realmSource.realmGet$columnBinaryList());\n\n        unmanagedCopy.realmSet$columnBooleanList(new RealmList<java.lang.Boolean>());\n        unmanagedCopy.realmGet$columnBooleanList().addAll(realmSource.realmGet$columnBooleanList());\n\n        unmanagedCopy.realmSet$columnLongList(new RealmList<java.lang.Long>());\n        unmanagedCopy.realmGet$columnLongList().addAll(realmSource.realmGet$columnLongList());\n\n        unmanagedCopy.realmSet$columnIntegerList(new RealmList<java.lang.Integer>());\n        unmanagedCopy.realmGet$columnIntegerList().addAll(realmSource.realmGet$columnIntegerList());\n\n        unmanagedCopy.realmSet$columnShortList(new RealmList<java.lang.Short>());\n        unmanagedCopy.realmGet$columnShortList().addAll(realmSource.realmGet$columnShortList());\n\n        unmanagedCopy.realmSet$columnByteList(new RealmList<java.lang.Byte>());\n        unmanagedCopy.realmGet$columnByteList().addAll(realmSource.realmGet$columnByteList());\n\n        unmanagedCopy.realmSet$columnDoubleList(new RealmList<java.lang.Double>());\n        unmanagedCopy.realmGet$columnDoubleList().addAll(realmSource.realmGet$columnDoubleList());\n\n        unmanagedCopy.realmSet$columnFloatList(new RealmList<java.lang.Float>());\n        unmanagedCopy.realmGet$columnFloatList().addAll(realmSource.realmGet$columnFloatList());\n\n        unmanagedCopy.realmSet$columnDateList(new RealmList<java.util.Date>());\n        unmanagedCopy.realmGet$columnDateList().addAll(realmSource.realmGet$columnDateList());\n\n        unmanagedCopy.realmSet$columnDecimal128List(new RealmList<org.bson.types.Decimal128>());\n        unmanagedCopy.realmGet$columnDecimal128List().addAll(realmSource.realmGet$columnDecimal128List());\n\n        unmanagedCopy.realmSet$columnObjectIdList(new RealmList<org.bson.types.ObjectId>());\n        unmanagedCopy.realmGet$columnObjectIdList().addAll(realmSource.realmGet$columnObjectIdList());\n\n        unmanagedCopy.realmSet$columnUUIDList(new RealmList<java.util.UUID>());\n        unmanagedCopy.realmGet$columnUUIDList().addAll(realmSource.realmGet$columnUUIDList());\n\n        // Deep copy of columnRealmAnyList\n        if (currentDepth == maxDepth) {\n            unmanagedCopy.realmSet$columnRealmAnyList(null);\n        } else {\n            RealmList<RealmAny> managedcolumnRealmAnyListList = realmSource.realmGet$columnRealmAnyList();\n            RealmList<RealmAny> unmanagedcolumnRealmAnyListList = new RealmList<RealmAny>();\n            unmanagedCopy.realmSet$columnRealmAnyList(unmanagedcolumnRealmAnyListList);\n            int nextDepth = currentDepth + 1;\n            int size = managedcolumnRealmAnyListList.size();\n            for (int i = 0; i < size; i++) {\n                RealmAny item = ProxyUtils.createDetachedCopy(managedcolumnRealmAnyListList.get(i), objectRealm, nextDepth, maxDepth, cache);\n                unmanagedcolumnRealmAnyListList.add(item);\n            }\n        }\n\n        // Deep copy of columnRealmDictionary\n        if (currentDepth == maxDepth) {\n            unmanagedCopy.realmSet$columnRealmDictionary(null);\n        } else {\n            RealmDictionary<some.test.AllTypes> managedcolumnRealmDictionaryDictionary = realmSource.realmGet$columnRealmDictionary();\n            RealmDictionary<some.test.AllTypes> unmanagedcolumnRealmDictionaryDictionary = new RealmDictionary<some.test.AllTypes>();\n            unmanagedCopy.realmSet$columnRealmDictionary(unmanagedcolumnRealmDictionaryDictionary);\n            int nextDepth = currentDepth + 1;\n            for (Map.Entry<String, some.test.AllTypes> entry : managedcolumnRealmDictionaryDictionary.entrySet()) {\n                some.test.AllTypes detachedValue = some_test_AllTypesRealmProxy.createDetachedCopy(entry.getValue(), nextDepth, maxDepth, cache);\n                unmanagedcolumnRealmDictionaryDictionary.put(entry.getKey(), detachedValue);\n            }\n        }\n\n        unmanagedCopy.realmSet$columnBooleanDictionary(new RealmDictionary<java.lang.Boolean>());\n        RealmDictionary<java.lang.Boolean> managedcolumnBooleanDictionaryDictionary = realmSource.realmGet$columnBooleanDictionary();\n        for (Map.Entry<String, java.lang.Boolean> entry : managedcolumnBooleanDictionaryDictionary.entrySet()) {\n            unmanagedCopy.realmGet$columnBooleanDictionary().put(entry.getKey(), entry.getValue());\n        }\n\n        unmanagedCopy.realmSet$columnStringDictionary(new RealmDictionary<java.lang.String>());\n        RealmDictionary<java.lang.String> managedcolumnStringDictionaryDictionary = realmSource.realmGet$columnStringDictionary();\n        for (Map.Entry<String, java.lang.String> entry : managedcolumnStringDictionaryDictionary.entrySet()) {\n            unmanagedCopy.realmGet$columnStringDictionary().put(entry.getKey(), entry.getValue());\n        }\n\n        unmanagedCopy.realmSet$columnIntegerDictionary(new RealmDictionary<java.lang.Integer>());\n        RealmDictionary<java.lang.Integer> managedcolumnIntegerDictionaryDictionary = realmSource.realmGet$columnIntegerDictionary();\n        for (Map.Entry<String, java.lang.Integer> entry : managedcolumnIntegerDictionaryDictionary.entrySet()) {\n            unmanagedCopy.realmGet$columnIntegerDictionary().put(entry.getKey(), entry.getValue());\n        }\n\n        unmanagedCopy.realmSet$columnFloatDictionary(new RealmDictionary<java.lang.Float>());\n        RealmDictionary<java.lang.Float> managedcolumnFloatDictionaryDictionary = realmSource.realmGet$columnFloatDictionary();\n        for (Map.Entry<String, java.lang.Float> entry : managedcolumnFloatDictionaryDictionary.entrySet()) {\n            unmanagedCopy.realmGet$columnFloatDictionary().put(entry.getKey(), entry.getValue());\n        }\n\n        unmanagedCopy.realmSet$columnLongDictionary(new RealmDictionary<java.lang.Long>());\n        RealmDictionary<java.lang.Long> managedcolumnLongDictionaryDictionary = realmSource.realmGet$columnLongDictionary();\n        for (Map.Entry<String, java.lang.Long> entry : managedcolumnLongDictionaryDictionary.entrySet()) {\n            unmanagedCopy.realmGet$columnLongDictionary().put(entry.getKey(), entry.getValue());\n        }\n\n        unmanagedCopy.realmSet$columnShortDictionary(new RealmDictionary<java.lang.Short>());\n        RealmDictionary<java.lang.Short> managedcolumnShortDictionaryDictionary = realmSource.realmGet$columnShortDictionary();\n        for (Map.Entry<String, java.lang.Short> entry : managedcolumnShortDictionaryDictionary.entrySet()) {\n            unmanagedCopy.realmGet$columnShortDictionary().put(entry.getKey(), entry.getValue());\n        }\n\n        unmanagedCopy.realmSet$columnDoubleDictionary(new RealmDictionary<java.lang.Double>());\n        RealmDictionary<java.lang.Double> managedcolumnDoubleDictionaryDictionary = realmSource.realmGet$columnDoubleDictionary();\n        for (Map.Entry<String, java.lang.Double> entry : managedcolumnDoubleDictionaryDictionary.entrySet()) {\n            unmanagedCopy.realmGet$columnDoubleDictionary().put(entry.getKey(), entry.getValue());\n        }\n\n        unmanagedCopy.realmSet$columnByteDictionary(new RealmDictionary<java.lang.Byte>());\n        RealmDictionary<java.lang.Byte> managedcolumnByteDictionaryDictionary = realmSource.realmGet$columnByteDictionary();\n        for (Map.Entry<String, java.lang.Byte> entry : managedcolumnByteDictionaryDictionary.entrySet()) {\n            unmanagedCopy.realmGet$columnByteDictionary().put(entry.getKey(), entry.getValue());\n        }\n\n        unmanagedCopy.realmSet$columnBinaryDictionary(new RealmDictionary<byte[]>());\n        RealmDictionary<byte[]> managedcolumnBinaryDictionaryDictionary = realmSource.realmGet$columnBinaryDictionary();\n        for (Map.Entry<String, byte[]> entry : managedcolumnBinaryDictionaryDictionary.entrySet()) {\n            unmanagedCopy.realmGet$columnBinaryDictionary().put(entry.getKey(), entry.getValue());\n        }\n\n        unmanagedCopy.realmSet$columnDateDictionary(new RealmDictionary<java.util.Date>());\n        RealmDictionary<java.util.Date> managedcolumnDateDictionaryDictionary = realmSource.realmGet$columnDateDictionary();\n        for (Map.Entry<String, java.util.Date> entry : managedcolumnDateDictionaryDictionary.entrySet()) {\n            unmanagedCopy.realmGet$columnDateDictionary().put(entry.getKey(), entry.getValue());\n        }\n\n        unmanagedCopy.realmSet$columnObjectIdDictionary(new RealmDictionary<org.bson.types.ObjectId>());\n        RealmDictionary<org.bson.types.ObjectId> managedcolumnObjectIdDictionaryDictionary = realmSource.realmGet$columnObjectIdDictionary();\n        for (Map.Entry<String, org.bson.types.ObjectId> entry : managedcolumnObjectIdDictionaryDictionary.entrySet()) {\n            unmanagedCopy.realmGet$columnObjectIdDictionary().put(entry.getKey(), entry.getValue());\n        }\n\n        unmanagedCopy.realmSet$columnUUIDDictionary(new RealmDictionary<java.util.UUID>());\n        RealmDictionary<java.util.UUID> managedcolumnUUIDDictionaryDictionary = realmSource.realmGet$columnUUIDDictionary();\n        for (Map.Entry<String, java.util.UUID> entry : managedcolumnUUIDDictionaryDictionary.entrySet()) {\n            unmanagedCopy.realmGet$columnUUIDDictionary().put(entry.getKey(), entry.getValue());\n        }\n\n        unmanagedCopy.realmSet$columnDecimal128Dictionary(new RealmDictionary<org.bson.types.Decimal128>());\n        RealmDictionary<org.bson.types.Decimal128> managedcolumnDecimal128DictionaryDictionary = realmSource.realmGet$columnDecimal128Dictionary();\n        for (Map.Entry<String, org.bson.types.Decimal128> entry : managedcolumnDecimal128DictionaryDictionary.entrySet()) {\n            unmanagedCopy.realmGet$columnDecimal128Dictionary().put(entry.getKey(), entry.getValue());\n        }\n\n        // Deep copy of columnRealmAnyDictionary\n        if (currentDepth == maxDepth) {\n            unmanagedCopy.realmSet$columnRealmAnyDictionary(null);\n        } else {\n            RealmDictionary<RealmAny> managedcolumnRealmAnyDictionaryDictionary = realmSource.realmGet$columnRealmAnyDictionary();\n            RealmDictionary<RealmAny> unmanagedcolumnRealmAnyDictionaryDictionary = new RealmDictionary<RealmAny>();\n            unmanagedCopy.realmSet$columnRealmAnyDictionary(unmanagedcolumnRealmAnyDictionaryDictionary);\n            int nextDepth = currentDepth + 1;\n            for (Map.Entry<String, RealmAny> entry : managedcolumnRealmAnyDictionaryDictionary.entrySet()) {\n                RealmAny detachedValue = ProxyUtils.createDetachedCopy(entry.getValue(), objectRealm, nextDepth, maxDepth, cache);\n                unmanagedcolumnRealmAnyDictionaryDictionary.put(entry.getKey(), detachedValue);\n            }\n        }\n\n        return unmanagedObject;\n    }\n\n    static some.test.AllTypes update(Realm realm, AllTypesColumnInfo columnInfo, some.test.AllTypes realmObject, some.test.AllTypes newObject, Map<RealmModel, RealmObjectProxy> cache, Set<ImportFlag> flags) {\n        some_test_AllTypesRealmProxyInterface realmObjectTarget = (some_test_AllTypesRealmProxyInterface) realmObject;\n        some_test_AllTypesRealmProxyInterface realmObjectSource = (some_test_AllTypesRealmProxyInterface) newObject;\n        Table table = realm.getTable(some.test.AllTypes.class);\n        OsObjectBuilder builder = new OsObjectBuilder(table, flags);\n        builder.addString(columnInfo.columnStringColKey, realmObjectSource.realmGet$columnString());\n        builder.addInteger(columnInfo.columnLongColKey, realmObjectSource.realmGet$columnLong());\n        builder.addFloat(columnInfo.columnFloatColKey, realmObjectSource.realmGet$columnFloat());\n        builder.addDouble(columnInfo.columnDoubleColKey, realmObjectSource.realmGet$columnDouble());\n        builder.addBoolean(columnInfo.columnBooleanColKey, realmObjectSource.realmGet$columnBoolean());\n        builder.addDecimal128(columnInfo.columnDecimal128ColKey, realmObjectSource.realmGet$columnDecimal128());\n        builder.addObjectId(columnInfo.columnObjectIdColKey, realmObjectSource.realmGet$columnObjectId());\n        builder.addUUID(columnInfo.columnUUIDColKey, realmObjectSource.realmGet$columnUUID());\n        builder.addDate(columnInfo.columnDateColKey, realmObjectSource.realmGet$columnDate());\n\n        RealmAny columnRealmAnyRealmAny = realmObjectSource.realmGet$columnRealmAny();\n        columnRealmAnyRealmAny = ProxyUtils.copyOrUpdate(columnRealmAnyRealmAny, realm, true, cache, flags);\n        builder.addRealmAny(columnInfo.columnRealmAnyColKey, columnRealmAnyRealmAny.getNativePtr());\n        builder.addByteArray(columnInfo.columnBinaryColKey, realmObjectSource.realmGet$columnBinary());\n        builder.addMutableRealmInteger(columnInfo.columnMutableRealmIntegerColKey, realmObjectSource.realmGet$columnMutableRealmInteger());\n\n        some.test.AllTypes columnObjectObj = realmObjectSource.realmGet$columnObject();\n        if (columnObjectObj == null) {\n            builder.addNull(columnInfo.columnObjectColKey);\n        } else {\n            some.test.AllTypes cachecolumnObject = (some.test.AllTypes) cache.get(columnObjectObj);\n            if (cachecolumnObject != null) {\n                builder.addObject(columnInfo.columnObjectColKey, cachecolumnObject);\n            } else {\n                builder.addObject(columnInfo.columnObjectColKey, some_test_AllTypesRealmProxy.copyOrUpdate(realm, (some_test_AllTypesRealmProxy.AllTypesColumnInfo) realm.getSchema().getColumnInfo(some.test.AllTypes.class), columnObjectObj, true, cache, flags));\n            }\n        }\n\n        some.test.Simple columnObjectWithoutPkObj = realmObjectSource.realmGet$columnObjectWithoutPk();\n        if (columnObjectWithoutPkObj == null) {\n            builder.addNull(columnInfo.columnObjectWithoutPkColKey);\n        } else {\n            some.test.Simple cachecolumnObjectWithoutPk = (some.test.Simple) cache.get(columnObjectWithoutPkObj);\n            if (cachecolumnObjectWithoutPk != null) {\n                builder.addObject(columnInfo.columnObjectWithoutPkColKey, cachecolumnObjectWithoutPk);\n            } else {\n                builder.addObject(columnInfo.columnObjectWithoutPkColKey, some_test_SimpleRealmProxy.copyOrUpdate(realm, (some_test_SimpleRealmProxy.SimpleColumnInfo) realm.getSchema().getColumnInfo(some.test.Simple.class), columnObjectWithoutPkObj, true, cache, flags));\n            }\n        }\n\n        RealmList<some.test.AllTypes> columnRealmListUnmanagedList = realmObjectSource.realmGet$columnRealmList();\n        if (columnRealmListUnmanagedList != null) {\n            RealmList<some.test.AllTypes> columnRealmListManagedCopy = new RealmList<some.test.AllTypes>();\n            for (int i = 0; i < columnRealmListUnmanagedList.size(); i++) {\n                some.test.AllTypes columnRealmListItem = columnRealmListUnmanagedList.get(i);\n                some.test.AllTypes cachecolumnRealmList = (some.test.AllTypes) cache.get(columnRealmListItem);\n                if (cachecolumnRealmList != null) {\n                    columnRealmListManagedCopy.add(cachecolumnRealmList);\n                } else {\n                    columnRealmListManagedCopy.add(some_test_AllTypesRealmProxy.copyOrUpdate(realm, (some_test_AllTypesRealmProxy.AllTypesColumnInfo) realm.getSchema().getColumnInfo(some.test.AllTypes.class), columnRealmListItem, true, cache, flags));\n                }\n            }\n            builder.addObjectList(columnInfo.columnRealmListColKey, columnRealmListManagedCopy);\n        } else {\n            builder.addObjectList(columnInfo.columnRealmListColKey, new RealmList<some.test.AllTypes>());\n        }\n\n        RealmList<some.test.Simple> columnRealmListNoPkUnmanagedList = realmObjectSource.realmGet$columnRealmListNoPk();\n        if (columnRealmListNoPkUnmanagedList != null) {\n            RealmList<some.test.Simple> columnRealmListNoPkManagedCopy = new RealmList<some.test.Simple>();\n            for (int i = 0; i < columnRealmListNoPkUnmanagedList.size(); i++) {\n                some.test.Simple columnRealmListNoPkItem = columnRealmListNoPkUnmanagedList.get(i);\n                some.test.Simple cachecolumnRealmListNoPk = (some.test.Simple) cache.get(columnRealmListNoPkItem);\n                if (cachecolumnRealmListNoPk != null) {\n                    columnRealmListNoPkManagedCopy.add(cachecolumnRealmListNoPk);\n                } else {\n                    columnRealmListNoPkManagedCopy.add(some_test_SimpleRealmProxy.copyOrUpdate(realm, (some_test_SimpleRealmProxy.SimpleColumnInfo) realm.getSchema().getColumnInfo(some.test.Simple.class), columnRealmListNoPkItem, true, cache, flags));\n                }\n            }\n            builder.addObjectList(columnInfo.columnRealmListNoPkColKey, columnRealmListNoPkManagedCopy);\n        } else {\n            builder.addObjectList(columnInfo.columnRealmListNoPkColKey, new RealmList<some.test.Simple>());\n        }\n\n        RealmList<some.test.AllTypes> columnRealmFinalListUnmanagedList = realmObjectSource.realmGet$columnRealmFinalList();\n        if (columnRealmFinalListUnmanagedList != null) {\n            RealmList<some.test.AllTypes> columnRealmFinalListManagedCopy = new RealmList<some.test.AllTypes>();\n            for (int i = 0; i < columnRealmFinalListUnmanagedList.size(); i++) {\n                some.test.AllTypes columnRealmFinalListItem = columnRealmFinalListUnmanagedList.get(i);\n                some.test.AllTypes cachecolumnRealmFinalList = (some.test.AllTypes) cache.get(columnRealmFinalListItem);\n                if (cachecolumnRealmFinalList != null) {\n                    columnRealmFinalListManagedCopy.add(cachecolumnRealmFinalList);\n                } else {\n                    columnRealmFinalListManagedCopy.add(some_test_AllTypesRealmProxy.copyOrUpdate(realm, (some_test_AllTypesRealmProxy.AllTypesColumnInfo) realm.getSchema().getColumnInfo(some.test.AllTypes.class), columnRealmFinalListItem, true, cache, flags));\n                }\n            }\n            builder.addObjectList(columnInfo.columnRealmFinalListColKey, columnRealmFinalListManagedCopy);\n        } else {\n            builder.addObjectList(columnInfo.columnRealmFinalListColKey, new RealmList<some.test.AllTypes>());\n        }\n\n        RealmList<some.test.Simple> columnRealmFinalListNoPkUnmanagedList = realmObjectSource.realmGet$columnRealmFinalListNoPk();\n        if (columnRealmFinalListNoPkUnmanagedList != null) {\n            RealmList<some.test.Simple> columnRealmFinalListNoPkManagedCopy = new RealmList<some.test.Simple>();\n            for (int i = 0; i < columnRealmFinalListNoPkUnmanagedList.size(); i++) {\n                some.test.Simple columnRealmFinalListNoPkItem = columnRealmFinalListNoPkUnmanagedList.get(i);\n                some.test.Simple cachecolumnRealmFinalListNoPk = (some.test.Simple) cache.get(columnRealmFinalListNoPkItem);\n                if (cachecolumnRealmFinalListNoPk != null) {\n                    columnRealmFinalListNoPkManagedCopy.add(cachecolumnRealmFinalListNoPk);\n                } else {\n                    columnRealmFinalListNoPkManagedCopy.add(some_test_SimpleRealmProxy.copyOrUpdate(realm, (some_test_SimpleRealmProxy.SimpleColumnInfo) realm.getSchema().getColumnInfo(some.test.Simple.class), columnRealmFinalListNoPkItem, true, cache, flags));\n                }\n            }\n            builder.addObjectList(columnInfo.columnRealmFinalListNoPkColKey, columnRealmFinalListNoPkManagedCopy);\n        } else {\n            builder.addObjectList(columnInfo.columnRealmFinalListNoPkColKey, new RealmList<some.test.Simple>());\n        }\n        builder.addStringList(columnInfo.columnStringListColKey, realmObjectSource.realmGet$columnStringList());\n        builder.addByteArrayList(columnInfo.columnBinaryListColKey, realmObjectSource.realmGet$columnBinaryList());\n        builder.addBooleanList(columnInfo.columnBooleanListColKey, realmObjectSource.realmGet$columnBooleanList());\n        builder.addLongList(columnInfo.columnLongListColKey, realmObjectSource.realmGet$columnLongList());\n        builder.addIntegerList(columnInfo.columnIntegerListColKey, realmObjectSource.realmGet$columnIntegerList());\n        builder.addShortList(columnInfo.columnShortListColKey, realmObjectSource.realmGet$columnShortList());\n        builder.addByteList(columnInfo.columnByteListColKey, realmObjectSource.realmGet$columnByteList());\n        builder.addDoubleList(columnInfo.columnDoubleListColKey, realmObjectSource.realmGet$columnDoubleList());\n        builder.addFloatList(columnInfo.columnFloatListColKey, realmObjectSource.realmGet$columnFloatList());\n        builder.addDateList(columnInfo.columnDateListColKey, realmObjectSource.realmGet$columnDateList());\n        builder.addDecimal128List(columnInfo.columnDecimal128ListColKey, realmObjectSource.realmGet$columnDecimal128List());\n        builder.addObjectIdList(columnInfo.columnObjectIdListColKey, realmObjectSource.realmGet$columnObjectIdList());\n        builder.addUUIDList(columnInfo.columnUUIDListColKey, realmObjectSource.realmGet$columnUUIDList());\n\n        RealmList<RealmAny> columnRealmAnyListUnmanagedList = realmObjectSource.realmGet$columnRealmAnyList();\n        if (columnRealmAnyListUnmanagedList != null) {\n            RealmList<RealmAny> columnRealmAnyListManagedCopy = new RealmList<RealmAny>();\n            for (int i = 0; i < columnRealmAnyListUnmanagedList.size(); i++) {\n                RealmAny realmAnyItem = columnRealmAnyListUnmanagedList.get(i);\n                realmAnyItem = ProxyUtils.copyOrUpdate(realmAnyItem, realm, true, cache, flags);\n                columnRealmAnyListManagedCopy.add(realmAnyItem);\n            }\n            builder.addRealmAnyList(columnInfo.columnRealmAnyListColKey, columnRealmAnyListManagedCopy);\n        } else {\n            builder.addRealmAnyList(columnInfo.columnRealmAnyListColKey, new RealmList<RealmAny>());\n        }\n\n        RealmDictionary<some.test.AllTypes> columnRealmDictionaryUnmanagedDictionary = realmObjectSource.realmGet$columnRealmDictionary();\n        if (columnRealmDictionaryUnmanagedDictionary != null) {\n            RealmDictionary<some.test.AllTypes> columnRealmDictionaryManagedDictionary = new RealmDictionary<>();\n            java.util.Set<java.util.Map.Entry<String, some.test.AllTypes>> entries = columnRealmDictionaryUnmanagedDictionary.entrySet();\n            for (java.util.Map.Entry<String, some.test.AllTypes> entry : entries) {\n                String entryKey = entry.getKey();\n                some.test.AllTypes columnRealmDictionaryUnmanagedEntryValue = entry.getValue();\n                some.test.AllTypes cachecolumnRealmDictionary = (some.test.AllTypes) cache.get(columnRealmDictionaryUnmanagedEntryValue);\n                if (cachecolumnRealmDictionary != null) {\n                    columnRealmDictionaryManagedDictionary.put(entryKey, cachecolumnRealmDictionary);\n                } else {\n                    if (columnRealmDictionaryUnmanagedEntryValue == null) {\n                        columnRealmDictionaryManagedDictionary.put(entryKey, null);\n                    } else {\n                        columnRealmDictionaryManagedDictionary.put(entryKey, some_test_AllTypesRealmProxy.copyOrUpdate(realm, (some_test_AllTypesRealmProxy.AllTypesColumnInfo) realm.getSchema().getColumnInfo(some.test.AllTypes.class), columnRealmDictionaryUnmanagedEntryValue, true, cache, flags));\n                    }\n                }\n            }\n            builder.addObjectDictionary(columnInfo.columnRealmDictionaryColKey, columnRealmDictionaryManagedDictionary);\n        } else {\n            builder.addObjectDictionary(columnInfo.columnRealmDictionaryColKey, null);\n        }\n        builder.addBooleanValueDictionary(columnInfo.columnBooleanDictionaryColKey, realmObjectSource.realmGet$columnBooleanDictionary());\n        builder.addStringValueDictionary(columnInfo.columnStringDictionaryColKey, realmObjectSource.realmGet$columnStringDictionary());\n        builder.addIntegerValueDictionary(columnInfo.columnIntegerDictionaryColKey, realmObjectSource.realmGet$columnIntegerDictionary());\n        builder.addFloatValueDictionary(columnInfo.columnFloatDictionaryColKey, realmObjectSource.realmGet$columnFloatDictionary());\n        builder.addLongValueDictionary(columnInfo.columnLongDictionaryColKey, realmObjectSource.realmGet$columnLongDictionary());\n        builder.addShortValueDictionary(columnInfo.columnShortDictionaryColKey, realmObjectSource.realmGet$columnShortDictionary());\n        builder.addDoubleValueDictionary(columnInfo.columnDoubleDictionaryColKey, realmObjectSource.realmGet$columnDoubleDictionary());\n        builder.addByteValueDictionary(columnInfo.columnByteDictionaryColKey, realmObjectSource.realmGet$columnByteDictionary());\n        builder.addBinaryValueDictionary(columnInfo.columnBinaryDictionaryColKey, realmObjectSource.realmGet$columnBinaryDictionary());\n        builder.addDateValueDictionary(columnInfo.columnDateDictionaryColKey, realmObjectSource.realmGet$columnDateDictionary());\n        builder.addObjectIdValueDictionary(columnInfo.columnObjectIdDictionaryColKey, realmObjectSource.realmGet$columnObjectIdDictionary());\n        builder.addUUIDValueDictionary(columnInfo.columnUUIDDictionaryColKey, realmObjectSource.realmGet$columnUUIDDictionary());\n        builder.addDecimal128ValueDictionary(columnInfo.columnDecimal128DictionaryColKey, realmObjectSource.realmGet$columnDecimal128Dictionary());\n\n        RealmDictionary<RealmAny> columnRealmAnyDictionaryUnmanagedDictionary = realmObjectSource.realmGet$columnRealmAnyDictionary();\n        if (columnRealmAnyDictionaryUnmanagedDictionary != null) {\n            RealmDictionary<RealmAny> columnRealmAnyDictionaryManagedDictionary = new RealmDictionary<>();\n            java.util.Set<java.util.Map.Entry<String, io.realm.RealmAny>> entries = columnRealmAnyDictionaryUnmanagedDictionary.entrySet();\n            java.util.List<String> keys = new java.util.ArrayList<>();\n            java.util.List<Long> realmAnyPointers = new java.util.ArrayList<>();\n            for (java.util.Map.Entry<String, io.realm.RealmAny> entry : entries) {\n                RealmAny realmAnyItem = entry.getValue();\n                realmAnyItem = ProxyUtils.copyOrUpdate(realmAnyItem, realm, true, cache, flags);\n                columnRealmAnyDictionaryManagedDictionary.put(entry.getKey(), realmAnyItem);\n            }\n            builder.addRealmAnyValueDictionary(columnInfo.columnRealmAnyDictionaryColKey, columnRealmAnyDictionaryManagedDictionary);\n        } else {\n            builder.addRealmAnyValueDictionary(columnInfo.columnRealmAnyDictionaryColKey, null);\n        }\n\n\n        builder.updateExistingTopLevelObject();\n        return realmObject;\n    }\n\n    @Override\n    @SuppressWarnings(\"ArrayToString\")\n    public String toString() {\n        if (!RealmObject.isValid(this)) {\n            return \"Invalid object\";\n        }\n        StringBuilder stringBuilder = new StringBuilder(\"AllTypes = proxy[\");\n        stringBuilder.append(\"{columnString:\");\n        stringBuilder.append(realmGet$columnString() != null ? realmGet$columnString() : \"null\");\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{columnLong:\");\n        stringBuilder.append(realmGet$columnLong());\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{columnFloat:\");\n        stringBuilder.append(realmGet$columnFloat());\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{columnDouble:\");\n        stringBuilder.append(realmGet$columnDouble());\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{columnBoolean:\");\n        stringBuilder.append(realmGet$columnBoolean());\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{columnDecimal128:\");\n        stringBuilder.append(realmGet$columnDecimal128());\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{columnObjectId:\");\n        stringBuilder.append(realmGet$columnObjectId());\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{columnUUID:\");\n        stringBuilder.append(realmGet$columnUUID());\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{columnDate:\");\n        stringBuilder.append(realmGet$columnDate());\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{columnRealmAny:\");\n        stringBuilder.append((realmGet$columnRealmAny().isNull()) ? \"null\" : \"realmGet$columnRealmAny()\");\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{columnBinary:\");\n        stringBuilder.append(\"binary(\" + realmGet$columnBinary().length + \")\");\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{columnMutableRealmInteger:\");\n        stringBuilder.append(realmGet$columnMutableRealmInteger().get());\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{columnObject:\");\n        stringBuilder.append(realmGet$columnObject() != null ? \"AllTypes\" : \"null\");\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{columnObjectWithoutPk:\");\n        stringBuilder.append(realmGet$columnObjectWithoutPk() != null ? \"Simple\" : \"null\");\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{columnRealmList:\");\n        stringBuilder.append(\"RealmList<AllTypes>[\").append(realmGet$columnRealmList().size()).append(\"]\");\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{columnRealmListNoPk:\");\n        stringBuilder.append(\"RealmList<Simple>[\").append(realmGet$columnRealmListNoPk().size()).append(\"]\");\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{columnRealmFinalList:\");\n        stringBuilder.append(\"RealmList<AllTypes>[\").append(realmGet$columnRealmFinalList().size()).append(\"]\");\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{columnRealmFinalListNoPk:\");\n        stringBuilder.append(\"RealmList<Simple>[\").append(realmGet$columnRealmFinalListNoPk().size()).append(\"]\");\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{columnStringList:\");\n        stringBuilder.append(\"RealmList<String>[\").append(realmGet$columnStringList().size()).append(\"]\");\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{columnBinaryList:\");\n        stringBuilder.append(\"RealmList<byte[]>[\").append(realmGet$columnBinaryList().size()).append(\"]\");\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{columnBooleanList:\");\n        stringBuilder.append(\"RealmList<Boolean>[\").append(realmGet$columnBooleanList().size()).append(\"]\");\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{columnLongList:\");\n        stringBuilder.append(\"RealmList<Long>[\").append(realmGet$columnLongList().size()).append(\"]\");\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{columnIntegerList:\");\n        stringBuilder.append(\"RealmList<Integer>[\").append(realmGet$columnIntegerList().size()).append(\"]\");\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{columnShortList:\");\n        stringBuilder.append(\"RealmList<Short>[\").append(realmGet$columnShortList().size()).append(\"]\");\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{columnByteList:\");\n        stringBuilder.append(\"RealmList<Byte>[\").append(realmGet$columnByteList().size()).append(\"]\");\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{columnDoubleList:\");\n        stringBuilder.append(\"RealmList<Double>[\").append(realmGet$columnDoubleList().size()).append(\"]\");\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{columnFloatList:\");\n        stringBuilder.append(\"RealmList<Float>[\").append(realmGet$columnFloatList().size()).append(\"]\");\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{columnDateList:\");\n        stringBuilder.append(\"RealmList<Date>[\").append(realmGet$columnDateList().size()).append(\"]\");\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{columnDecimal128List:\");\n        stringBuilder.append(\"RealmList<Decimal128>[\").append(realmGet$columnDecimal128List().size()).append(\"]\");\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{columnObjectIdList:\");\n        stringBuilder.append(\"RealmList<ObjectId>[\").append(realmGet$columnObjectIdList().size()).append(\"]\");\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{columnUUIDList:\");\n        stringBuilder.append(\"RealmList<UUID>[\").append(realmGet$columnUUIDList().size()).append(\"]\");\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{columnRealmAnyList:\");\n        stringBuilder.append(\"RealmList<RealmAny>[\").append(realmGet$columnRealmAnyList().size()).append(\"]\");\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{columnRealmDictionary:\");\n        stringBuilder.append(\"RealmDictionary<AllTypes>[\").append(realmGet$columnRealmDictionary().size()).append(\"]\");\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{columnBooleanDictionary:\");\n        stringBuilder.append(\"RealmDictionary<Boolean>[\").append(realmGet$columnBooleanDictionary().size()).append(\"]\");\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{columnStringDictionary:\");\n        stringBuilder.append(\"RealmDictionary<String>[\").append(realmGet$columnStringDictionary().size()).append(\"]\");\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{columnIntegerDictionary:\");\n        stringBuilder.append(\"RealmDictionary<Integer>[\").append(realmGet$columnIntegerDictionary().size()).append(\"]\");\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{columnFloatDictionary:\");\n        stringBuilder.append(\"RealmDictionary<Float>[\").append(realmGet$columnFloatDictionary().size()).append(\"]\");\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{columnLongDictionary:\");\n        stringBuilder.append(\"RealmDictionary<Long>[\").append(realmGet$columnLongDictionary().size()).append(\"]\");\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{columnShortDictionary:\");\n        stringBuilder.append(\"RealmDictionary<Short>[\").append(realmGet$columnShortDictionary().size()).append(\"]\");\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{columnDoubleDictionary:\");\n        stringBuilder.append(\"RealmDictionary<Double>[\").append(realmGet$columnDoubleDictionary().size()).append(\"]\");\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{columnByteDictionary:\");\n        stringBuilder.append(\"RealmDictionary<Byte>[\").append(realmGet$columnByteDictionary().size()).append(\"]\");\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{columnBinaryDictionary:\");\n        stringBuilder.append(\"RealmDictionary<byte[]>[\").append(realmGet$columnBinaryDictionary().size()).append(\"]\");\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{columnDateDictionary:\");\n        stringBuilder.append(\"RealmDictionary<Date>[\").append(realmGet$columnDateDictionary().size()).append(\"]\");\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{columnObjectIdDictionary:\");\n        stringBuilder.append(\"RealmDictionary<ObjectId>[\").append(realmGet$columnObjectIdDictionary().size()).append(\"]\");\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{columnUUIDDictionary:\");\n        stringBuilder.append(\"RealmDictionary<UUID>[\").append(realmGet$columnUUIDDictionary().size()).append(\"]\");\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{columnDecimal128Dictionary:\");\n        stringBuilder.append(\"RealmDictionary<Decimal128>[\").append(realmGet$columnDecimal128Dictionary().size()).append(\"]\");\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{columnRealmAnyDictionary:\");\n        stringBuilder.append(\"RealmDictionary<RealmAny>[\").append(realmGet$columnRealmAnyDictionary().size()).append(\"]\");\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\"]\");\n        return stringBuilder.toString();\n    }\n\n    @Override\n    public ProxyState<?> realmGet$proxyState() {\n        return proxyState;\n    }\n\n    @Override\n    public int hashCode() {\n        String realmName = proxyState.getRealm$realm().getPath();\n        String tableName = proxyState.getRow$realm().getTable().getName();\n        long objKey = proxyState.getRow$realm().getObjectKey();\n\n        int result = 17;\n        result = 31 * result + ((realmName != null) ? realmName.hashCode() : 0);\n        result = 31 * result + ((tableName != null) ? tableName.hashCode() : 0);\n        result = 31 * result + (int) (objKey ^ (objKey >>> 32));\n        return result;\n    }\n\n    @Override\n    public boolean equals(Object o) {\n        if (this == o) return true;\n        if (o == null || getClass() != o.getClass()) return false;\n        some_test_AllTypesRealmProxy aAllTypes = (some_test_AllTypesRealmProxy)o;\n\n        BaseRealm realm = proxyState.getRealm$realm();\n        BaseRealm otherRealm = aAllTypes.proxyState.getRealm$realm();\n        String path = realm.getPath();\n        String otherPath = otherRealm.getPath();\n        if (path != null ? !path.equals(otherPath) : otherPath != null) return false;\n        if (realm.isFrozen() != otherRealm.isFrozen()) return false;\n        if (!realm.sharedRealm.getVersionID().equals(otherRealm.sharedRealm.getVersionID())) {\n            return false;\n        }\n\n        String tableName = proxyState.getRow$realm().getTable().getName();\n        String otherTableName = aAllTypes.proxyState.getRow$realm().getTable().getName();\n        if (tableName != null ? !tableName.equals(otherTableName) : otherTableName != null) return false;\n\n        if (proxyState.getRow$realm().getObjectKey() != aAllTypes.proxyState.getRow$realm().getObjectKey()) return false;\n\n        return true;\n    }\n}\n"
  },
  {
    "path": "realm/realm-annotations-processor/src/test/resources/io/realm/some_test_BooleansRealmProxy.java",
    "content": "package io.realm;\n\n\nimport android.annotation.TargetApi;\nimport android.os.Build;\nimport android.util.JsonReader;\nimport android.util.JsonToken;\nimport io.realm.ImportFlag;\nimport io.realm.ProxyUtils;\nimport io.realm.exceptions.RealmMigrationNeededException;\nimport io.realm.internal.ColumnInfo;\nimport io.realm.internal.NativeContext;\nimport io.realm.internal.OsList;\nimport io.realm.internal.OsMap;\nimport io.realm.internal.OsObject;\nimport io.realm.internal.OsObjectSchemaInfo;\nimport io.realm.internal.OsSchemaInfo;\nimport io.realm.internal.OsSet;\nimport io.realm.internal.Property;\nimport io.realm.internal.RealmObjectProxy;\nimport io.realm.internal.Row;\nimport io.realm.internal.Table;\nimport io.realm.internal.android.JsonUtils;\nimport io.realm.internal.core.NativeRealmAny;\nimport io.realm.internal.objectstore.OsObjectBuilder;\nimport io.realm.log.RealmLog;\nimport java.io.IOException;\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.Date;\nimport java.util.HashMap;\nimport java.util.HashSet;\nimport java.util.Iterator;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Set;\nimport org.json.JSONArray;\nimport org.json.JSONException;\nimport org.json.JSONObject;\n\n@SuppressWarnings(\"all\")\npublic class some_test_BooleansRealmProxy extends some.test.Booleans\n        implements RealmObjectProxy, some_test_BooleansRealmProxyInterface {\n\n    static final class BooleansColumnInfo extends ColumnInfo {\n        long doneColKey;\n        long isReadyColKey;\n        long mCompletedColKey;\n        long anotherBooleanColKey;\n\n        BooleansColumnInfo(OsSchemaInfo schemaInfo) {\n            super(4);\n            OsObjectSchemaInfo objectSchemaInfo = schemaInfo.getObjectSchemaInfo(\"Booleans\");\n            this.doneColKey = addColumnDetails(\"done\", \"done\", objectSchemaInfo);\n            this.isReadyColKey = addColumnDetails(\"isReady\", \"isReady\", objectSchemaInfo);\n            this.mCompletedColKey = addColumnDetails(\"mCompleted\", \"mCompleted\", objectSchemaInfo);\n            this.anotherBooleanColKey = addColumnDetails(\"anotherBoolean\", \"anotherBoolean\", objectSchemaInfo);\n        }\n\n        BooleansColumnInfo(ColumnInfo src, boolean mutable) {\n            super(src, mutable);\n            copy(src, this);\n        }\n\n        @Override\n        protected final ColumnInfo copy(boolean mutable) {\n            return new BooleansColumnInfo(this, mutable);\n        }\n\n        @Override\n        protected final void copy(ColumnInfo rawSrc, ColumnInfo rawDst) {\n            final BooleansColumnInfo src = (BooleansColumnInfo) rawSrc;\n            final BooleansColumnInfo dst = (BooleansColumnInfo) rawDst;\n            dst.doneColKey = src.doneColKey;\n            dst.isReadyColKey = src.isReadyColKey;\n            dst.mCompletedColKey = src.mCompletedColKey;\n            dst.anotherBooleanColKey = src.anotherBooleanColKey;\n        }\n    }\n\n    private static final String NO_ALIAS = \"\";\n    private static final OsObjectSchemaInfo expectedObjectSchemaInfo = createExpectedObjectSchemaInfo();\n\n    private BooleansColumnInfo columnInfo;\n    private ProxyState<some.test.Booleans> proxyState;\n\n    some_test_BooleansRealmProxy() {\n        proxyState.setConstructionFinished();\n    }\n\n    @Override\n    public void realm$injectObjectContext() {\n        if (this.proxyState != null) {\n            return;\n        }\n        final BaseRealm.RealmObjectContext context = BaseRealm.objectContext.get();\n        this.columnInfo = (BooleansColumnInfo) context.getColumnInfo();\n        this.proxyState = new ProxyState<some.test.Booleans>(this);\n        proxyState.setRealm$realm(context.getRealm());\n        proxyState.setRow$realm(context.getRow());\n        proxyState.setAcceptDefaultValue$realm(context.getAcceptDefaultValue());\n        proxyState.setExcludeFields$realm(context.getExcludeFields());\n    }\n\n    @Override\n    @SuppressWarnings(\"cast\")\n    public boolean realmGet$done() {\n        proxyState.getRealm$realm().checkIfValid();\n        return (boolean) proxyState.getRow$realm().getBoolean(columnInfo.doneColKey);\n    }\n\n    @Override\n    public void realmSet$done(boolean value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            final Row row = proxyState.getRow$realm();\n            row.getTable().setBoolean(columnInfo.doneColKey, row.getObjectKey(), value, true);\n            return;\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        proxyState.getRow$realm().setBoolean(columnInfo.doneColKey, value);\n    }\n\n    @Override\n    @SuppressWarnings(\"cast\")\n    public boolean realmGet$isReady() {\n        proxyState.getRealm$realm().checkIfValid();\n        return (boolean) proxyState.getRow$realm().getBoolean(columnInfo.isReadyColKey);\n    }\n\n    @Override\n    public void realmSet$isReady(boolean value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            final Row row = proxyState.getRow$realm();\n            row.getTable().setBoolean(columnInfo.isReadyColKey, row.getObjectKey(), value, true);\n            return;\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        proxyState.getRow$realm().setBoolean(columnInfo.isReadyColKey, value);\n    }\n\n    @Override\n    @SuppressWarnings(\"cast\")\n    public boolean realmGet$mCompleted() {\n        proxyState.getRealm$realm().checkIfValid();\n        return (boolean) proxyState.getRow$realm().getBoolean(columnInfo.mCompletedColKey);\n    }\n\n    @Override\n    public void realmSet$mCompleted(boolean value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            final Row row = proxyState.getRow$realm();\n            row.getTable().setBoolean(columnInfo.mCompletedColKey, row.getObjectKey(), value, true);\n            return;\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        proxyState.getRow$realm().setBoolean(columnInfo.mCompletedColKey, value);\n    }\n\n    @Override\n    @SuppressWarnings(\"cast\")\n    public boolean realmGet$anotherBoolean() {\n        proxyState.getRealm$realm().checkIfValid();\n        return (boolean) proxyState.getRow$realm().getBoolean(columnInfo.anotherBooleanColKey);\n    }\n\n    @Override\n    public void realmSet$anotherBoolean(boolean value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            final Row row = proxyState.getRow$realm();\n            row.getTable().setBoolean(columnInfo.anotherBooleanColKey, row.getObjectKey(), value, true);\n            return;\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        proxyState.getRow$realm().setBoolean(columnInfo.anotherBooleanColKey, value);\n    }\n\n    private static OsObjectSchemaInfo createExpectedObjectSchemaInfo() {\n        OsObjectSchemaInfo.Builder builder = new OsObjectSchemaInfo.Builder(NO_ALIAS, \"Booleans\", false, 4, 0);\n        builder.addPersistedProperty(NO_ALIAS, \"done\", RealmFieldType.BOOLEAN, !Property.PRIMARY_KEY, !Property.INDEXED, Property.REQUIRED);\n        builder.addPersistedProperty(NO_ALIAS, \"isReady\", RealmFieldType.BOOLEAN, !Property.PRIMARY_KEY, !Property.INDEXED, Property.REQUIRED);\n        builder.addPersistedProperty(NO_ALIAS, \"mCompleted\", RealmFieldType.BOOLEAN, !Property.PRIMARY_KEY, !Property.INDEXED, Property.REQUIRED);\n        builder.addPersistedProperty(NO_ALIAS, \"anotherBoolean\", RealmFieldType.BOOLEAN, !Property.PRIMARY_KEY, !Property.INDEXED, Property.REQUIRED);\n        return builder.build();\n    }\n\n    public static OsObjectSchemaInfo getExpectedObjectSchemaInfo() {\n        return expectedObjectSchemaInfo;\n    }\n\n    public static BooleansColumnInfo createColumnInfo(OsSchemaInfo schemaInfo) {\n        return new BooleansColumnInfo(schemaInfo);\n    }\n\n    public static String getSimpleClassName() {\n        return \"Booleans\";\n    }\n\n    public static final class ClassNameHelper {\n        public static final String INTERNAL_CLASS_NAME = \"Booleans\";\n    }\n\n    @SuppressWarnings(\"cast\")\n    public static some.test.Booleans createOrUpdateUsingJsonObject(Realm realm, JSONObject json, boolean update)\n            throws JSONException {\n        final List<String> excludeFields = Collections.<String> emptyList();\n        some.test.Booleans obj = realm.createObjectInternal(some.test.Booleans.class, true, excludeFields);\n\n        final some_test_BooleansRealmProxyInterface objProxy = (some_test_BooleansRealmProxyInterface) obj;\n        if (json.has(\"done\")) {\n            if (json.isNull(\"done\")) {\n                throw new IllegalArgumentException(\"Trying to set non-nullable field 'done' to null.\");\n            } else {\n                objProxy.realmSet$done((boolean) json.getBoolean(\"done\"));\n            }\n        }\n        if (json.has(\"isReady\")) {\n            if (json.isNull(\"isReady\")) {\n                throw new IllegalArgumentException(\"Trying to set non-nullable field 'isReady' to null.\");\n            } else {\n                objProxy.realmSet$isReady((boolean) json.getBoolean(\"isReady\"));\n            }\n        }\n        if (json.has(\"mCompleted\")) {\n            if (json.isNull(\"mCompleted\")) {\n                throw new IllegalArgumentException(\"Trying to set non-nullable field 'mCompleted' to null.\");\n            } else {\n                objProxy.realmSet$mCompleted((boolean) json.getBoolean(\"mCompleted\"));\n            }\n        }\n        if (json.has(\"anotherBoolean\")) {\n            if (json.isNull(\"anotherBoolean\")) {\n                throw new IllegalArgumentException(\"Trying to set non-nullable field 'anotherBoolean' to null.\");\n            } else {\n                objProxy.realmSet$anotherBoolean((boolean) json.getBoolean(\"anotherBoolean\"));\n            }\n        }\n        return obj;\n    }\n\n    @SuppressWarnings(\"cast\")\n    @TargetApi(Build.VERSION_CODES.HONEYCOMB)\n    public static some.test.Booleans createUsingJsonStream(Realm realm, JsonReader reader)\n            throws IOException {\n        final some.test.Booleans obj = new some.test.Booleans();\n        final some_test_BooleansRealmProxyInterface objProxy = (some_test_BooleansRealmProxyInterface) obj;\n        reader.beginObject();\n        while (reader.hasNext()) {\n            String name = reader.nextName();\n            if (false) {\n            } else if (name.equals(\"done\")) {\n                if (reader.peek() != JsonToken.NULL) {\n                    objProxy.realmSet$done((boolean) reader.nextBoolean());\n                } else {\n                    reader.skipValue();\n                    throw new IllegalArgumentException(\"Trying to set non-nullable field 'done' to null.\");\n                }\n            } else if (name.equals(\"isReady\")) {\n                if (reader.peek() != JsonToken.NULL) {\n                    objProxy.realmSet$isReady((boolean) reader.nextBoolean());\n                } else {\n                    reader.skipValue();\n                    throw new IllegalArgumentException(\"Trying to set non-nullable field 'isReady' to null.\");\n                }\n            } else if (name.equals(\"mCompleted\")) {\n                if (reader.peek() != JsonToken.NULL) {\n                    objProxy.realmSet$mCompleted((boolean) reader.nextBoolean());\n                } else {\n                    reader.skipValue();\n                    throw new IllegalArgumentException(\"Trying to set non-nullable field 'mCompleted' to null.\");\n                }\n            } else if (name.equals(\"anotherBoolean\")) {\n                if (reader.peek() != JsonToken.NULL) {\n                    objProxy.realmSet$anotherBoolean((boolean) reader.nextBoolean());\n                } else {\n                    reader.skipValue();\n                    throw new IllegalArgumentException(\"Trying to set non-nullable field 'anotherBoolean' to null.\");\n                }\n            } else {\n                reader.skipValue();\n            }\n        }\n        reader.endObject();\n        return realm.copyToRealm(obj);\n    }\n\n    static some_test_BooleansRealmProxy newProxyInstance(BaseRealm realm, Row row) {\n        // Ignore default values to avoid creating unexpected objects from RealmModel/RealmList fields\n        final BaseRealm.RealmObjectContext objectContext = BaseRealm.objectContext.get();\n        objectContext.set(realm, row, realm.getSchema().getColumnInfo(some.test.Booleans.class), false, Collections.<String>emptyList());\n        io.realm.some_test_BooleansRealmProxy obj = new io.realm.some_test_BooleansRealmProxy();\n        objectContext.clear();\n        return obj;\n    }\n\n    public static some.test.Booleans copyOrUpdate(Realm realm, BooleansColumnInfo columnInfo, some.test.Booleans object, boolean update, Map<RealmModel,RealmObjectProxy> cache, Set<ImportFlag> flags) {\n        if (object instanceof RealmObjectProxy && !RealmObject.isFrozen(object) && ((RealmObjectProxy) object).realmGet$proxyState().getRealm$realm() != null) {\n            final BaseRealm otherRealm = ((RealmObjectProxy) object).realmGet$proxyState().getRealm$realm();\n            if (otherRealm.threadId != realm.threadId) {\n                throw new IllegalArgumentException(\"Objects which belong to Realm instances in other threads cannot be copied into this Realm instance.\");\n            }\n            if (otherRealm.getPath().equals(realm.getPath())) {\n                return object;\n            }\n        }\n        final BaseRealm.RealmObjectContext objectContext = BaseRealm.objectContext.get();\n        RealmObjectProxy cachedRealmObject = cache.get(object);\n        if (cachedRealmObject != null) {\n            return (some.test.Booleans) cachedRealmObject;\n        }\n\n        return copy(realm, columnInfo, object, update, cache, flags);\n    }\n\n    public static some.test.Booleans copy(Realm realm, BooleansColumnInfo columnInfo, some.test.Booleans newObject, boolean update, Map<RealmModel,RealmObjectProxy> cache, Set<ImportFlag> flags) {\n        RealmObjectProxy cachedRealmObject = cache.get(newObject);\n        if (cachedRealmObject != null) {\n            return (some.test.Booleans) cachedRealmObject;\n        }\n\n        some_test_BooleansRealmProxyInterface unmanagedSource = (some_test_BooleansRealmProxyInterface) newObject;\n\n        Table table = realm.getTable(some.test.Booleans.class);\n        OsObjectBuilder builder = new OsObjectBuilder(table, flags);\n\n        // Add all non-\"object reference\" fields\n        builder.addBoolean(columnInfo.doneColKey, unmanagedSource.realmGet$done());\n        builder.addBoolean(columnInfo.isReadyColKey, unmanagedSource.realmGet$isReady());\n        builder.addBoolean(columnInfo.mCompletedColKey, unmanagedSource.realmGet$mCompleted());\n        builder.addBoolean(columnInfo.anotherBooleanColKey, unmanagedSource.realmGet$anotherBoolean());\n\n        // Create the underlying object and cache it before setting any object/objectlist references\n        // This will allow us to break any circular dependencies by using the object cache.\n        Row row = builder.createNewObject();\n        io.realm.some_test_BooleansRealmProxy managedCopy = newProxyInstance(realm, row);\n        cache.put(newObject, managedCopy);\n\n        return managedCopy;\n    }\n\n    public static long insert(Realm realm, some.test.Booleans object, Map<RealmModel,Long> cache) {\n        if (object instanceof RealmObjectProxy && !RealmObject.isFrozen(object) && ((RealmObjectProxy) object).realmGet$proxyState().getRealm$realm() != null && ((RealmObjectProxy) object).realmGet$proxyState().getRealm$realm().getPath().equals(realm.getPath())) {\n            return ((RealmObjectProxy) object).realmGet$proxyState().getRow$realm().getObjectKey();\n        }\n        Table table = realm.getTable(some.test.Booleans.class);\n        long tableNativePtr = table.getNativePtr();\n        BooleansColumnInfo columnInfo = (BooleansColumnInfo) realm.getSchema().getColumnInfo(some.test.Booleans.class);\n        long objKey = OsObject.createRow(table);\n        cache.put(object, objKey);\n        Table.nativeSetBoolean(tableNativePtr, columnInfo.doneColKey, objKey, ((some_test_BooleansRealmProxyInterface) object).realmGet$done(), false);\n        Table.nativeSetBoolean(tableNativePtr, columnInfo.isReadyColKey, objKey, ((some_test_BooleansRealmProxyInterface) object).realmGet$isReady(), false);\n        Table.nativeSetBoolean(tableNativePtr, columnInfo.mCompletedColKey, objKey, ((some_test_BooleansRealmProxyInterface) object).realmGet$mCompleted(), false);\n        Table.nativeSetBoolean(tableNativePtr, columnInfo.anotherBooleanColKey, objKey, ((some_test_BooleansRealmProxyInterface) object).realmGet$anotherBoolean(), false);\n        return objKey;\n    }\n\n    public static void insert(Realm realm, Iterator<? extends RealmModel> objects, Map<RealmModel,Long> cache) {\n        Table table = realm.getTable(some.test.Booleans.class);\n        long tableNativePtr = table.getNativePtr();\n        BooleansColumnInfo columnInfo = (BooleansColumnInfo) realm.getSchema().getColumnInfo(some.test.Booleans.class);\n        some.test.Booleans object = null;\n        while (objects.hasNext()) {\n            object = (some.test.Booleans) objects.next();\n            if (cache.containsKey(object)) {\n                continue;\n            }\n            if (object instanceof RealmObjectProxy && !RealmObject.isFrozen(object) && ((RealmObjectProxy) object).realmGet$proxyState().getRealm$realm() != null && ((RealmObjectProxy) object).realmGet$proxyState().getRealm$realm().getPath().equals(realm.getPath())) {\n                cache.put(object, ((RealmObjectProxy) object).realmGet$proxyState().getRow$realm().getObjectKey());\n                continue;\n            }\n            long objKey = OsObject.createRow(table);\n            cache.put(object, objKey);\n            Table.nativeSetBoolean(tableNativePtr, columnInfo.doneColKey, objKey, ((some_test_BooleansRealmProxyInterface) object).realmGet$done(), false);\n            Table.nativeSetBoolean(tableNativePtr, columnInfo.isReadyColKey, objKey, ((some_test_BooleansRealmProxyInterface) object).realmGet$isReady(), false);\n            Table.nativeSetBoolean(tableNativePtr, columnInfo.mCompletedColKey, objKey, ((some_test_BooleansRealmProxyInterface) object).realmGet$mCompleted(), false);\n            Table.nativeSetBoolean(tableNativePtr, columnInfo.anotherBooleanColKey, objKey, ((some_test_BooleansRealmProxyInterface) object).realmGet$anotherBoolean(), false);\n        }\n    }\n\n    public static long insertOrUpdate(Realm realm, some.test.Booleans object, Map<RealmModel,Long> cache) {\n        if (object instanceof RealmObjectProxy && !RealmObject.isFrozen(object) && ((RealmObjectProxy) object).realmGet$proxyState().getRealm$realm() != null && ((RealmObjectProxy) object).realmGet$proxyState().getRealm$realm().getPath().equals(realm.getPath())) {\n            return ((RealmObjectProxy) object).realmGet$proxyState().getRow$realm().getObjectKey();\n        }\n        Table table = realm.getTable(some.test.Booleans.class);\n        long tableNativePtr = table.getNativePtr();\n        BooleansColumnInfo columnInfo = (BooleansColumnInfo) realm.getSchema().getColumnInfo(some.test.Booleans.class);\n        long objKey = OsObject.createRow(table);\n        cache.put(object, objKey);\n        Table.nativeSetBoolean(tableNativePtr, columnInfo.doneColKey, objKey, ((some_test_BooleansRealmProxyInterface) object).realmGet$done(), false);\n        Table.nativeSetBoolean(tableNativePtr, columnInfo.isReadyColKey, objKey, ((some_test_BooleansRealmProxyInterface) object).realmGet$isReady(), false);\n        Table.nativeSetBoolean(tableNativePtr, columnInfo.mCompletedColKey, objKey, ((some_test_BooleansRealmProxyInterface) object).realmGet$mCompleted(), false);\n        Table.nativeSetBoolean(tableNativePtr, columnInfo.anotherBooleanColKey, objKey, ((some_test_BooleansRealmProxyInterface) object).realmGet$anotherBoolean(), false);\n        return objKey;\n    }\n\n    public static void insertOrUpdate(Realm realm, Iterator<? extends RealmModel> objects, Map<RealmModel,Long> cache) {\n        Table table = realm.getTable(some.test.Booleans.class);\n        long tableNativePtr = table.getNativePtr();\n        BooleansColumnInfo columnInfo = (BooleansColumnInfo) realm.getSchema().getColumnInfo(some.test.Booleans.class);\n        some.test.Booleans object = null;\n        while (objects.hasNext()) {\n            object = (some.test.Booleans) objects.next();\n            if (cache.containsKey(object)) {\n                continue;\n            }\n            if (object instanceof RealmObjectProxy && !RealmObject.isFrozen(object) && ((RealmObjectProxy) object).realmGet$proxyState().getRealm$realm() != null && ((RealmObjectProxy) object).realmGet$proxyState().getRealm$realm().getPath().equals(realm.getPath())) {\n                cache.put(object, ((RealmObjectProxy) object).realmGet$proxyState().getRow$realm().getObjectKey());\n                continue;\n            }\n            long objKey = OsObject.createRow(table);\n            cache.put(object, objKey);\n            Table.nativeSetBoolean(tableNativePtr, columnInfo.doneColKey, objKey, ((some_test_BooleansRealmProxyInterface) object).realmGet$done(), false);\n            Table.nativeSetBoolean(tableNativePtr, columnInfo.isReadyColKey, objKey, ((some_test_BooleansRealmProxyInterface) object).realmGet$isReady(), false);\n            Table.nativeSetBoolean(tableNativePtr, columnInfo.mCompletedColKey, objKey, ((some_test_BooleansRealmProxyInterface) object).realmGet$mCompleted(), false);\n            Table.nativeSetBoolean(tableNativePtr, columnInfo.anotherBooleanColKey, objKey, ((some_test_BooleansRealmProxyInterface) object).realmGet$anotherBoolean(), false);\n        }\n    }\n\n    public static some.test.Booleans createDetachedCopy(some.test.Booleans realmObject, int currentDepth, int maxDepth, Map<RealmModel, CacheData<RealmModel>> cache) {\n        if (currentDepth > maxDepth || realmObject == null) {\n            return null;\n        }\n        CacheData<RealmModel> cachedObject = cache.get(realmObject);\n        some.test.Booleans unmanagedObject;\n        if (cachedObject == null) {\n            unmanagedObject = new some.test.Booleans();\n            cache.put(realmObject, new RealmObjectProxy.CacheData<RealmModel>(currentDepth, unmanagedObject));\n        } else {\n            // Reuse cached object or recreate it because it was encountered at a lower depth.\n            if (currentDepth >= cachedObject.minDepth) {\n                return (some.test.Booleans) cachedObject.object;\n            }\n            unmanagedObject = (some.test.Booleans) cachedObject.object;\n            cachedObject.minDepth = currentDepth;\n        }\n        some_test_BooleansRealmProxyInterface unmanagedCopy = (some_test_BooleansRealmProxyInterface) unmanagedObject;\n        some_test_BooleansRealmProxyInterface realmSource = (some_test_BooleansRealmProxyInterface) realmObject;\n        Realm objectRealm = (Realm) ((RealmObjectProxy) realmObject).realmGet$proxyState().getRealm$realm();\n        unmanagedCopy.realmSet$done(realmSource.realmGet$done());\n        unmanagedCopy.realmSet$isReady(realmSource.realmGet$isReady());\n        unmanagedCopy.realmSet$mCompleted(realmSource.realmGet$mCompleted());\n        unmanagedCopy.realmSet$anotherBoolean(realmSource.realmGet$anotherBoolean());\n\n        return unmanagedObject;\n    }\n\n    @Override\n    @SuppressWarnings(\"ArrayToString\")\n    public String toString() {\n        if (!RealmObject.isValid(this)) {\n            return \"Invalid object\";\n        }\n        StringBuilder stringBuilder = new StringBuilder(\"Booleans = proxy[\");\n        stringBuilder.append(\"{done:\");\n        stringBuilder.append(realmGet$done());\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{isReady:\");\n        stringBuilder.append(realmGet$isReady());\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{mCompleted:\");\n        stringBuilder.append(realmGet$mCompleted());\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{anotherBoolean:\");\n        stringBuilder.append(realmGet$anotherBoolean());\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\"]\");\n        return stringBuilder.toString();\n    }\n\n    @Override\n    public ProxyState<?> realmGet$proxyState() {\n        return proxyState;\n    }\n\n    @Override\n    public int hashCode() {\n        String realmName = proxyState.getRealm$realm().getPath();\n        String tableName = proxyState.getRow$realm().getTable().getName();\n        long objKey = proxyState.getRow$realm().getObjectKey();\n\n        int result = 17;\n        result = 31 * result + ((realmName != null) ? realmName.hashCode() : 0);\n        result = 31 * result + ((tableName != null) ? tableName.hashCode() : 0);\n        result = 31 * result + (int) (objKey ^ (objKey >>> 32));\n        return result;\n    }\n\n    @Override\n    public boolean equals(Object o) {\n        if (this == o) return true;\n        if (o == null || getClass() != o.getClass()) return false;\n        some_test_BooleansRealmProxy aBooleans = (some_test_BooleansRealmProxy)o;\n\n        BaseRealm realm = proxyState.getRealm$realm();\n        BaseRealm otherRealm = aBooleans.proxyState.getRealm$realm();\n        String path = realm.getPath();\n        String otherPath = otherRealm.getPath();\n        if (path != null ? !path.equals(otherPath) : otherPath != null) return false;\n        if (realm.isFrozen() != otherRealm.isFrozen()) return false;\n        if (!realm.sharedRealm.getVersionID().equals(otherRealm.sharedRealm.getVersionID())) {\n            return false;\n        }\n\n        String tableName = proxyState.getRow$realm().getTable().getName();\n        String otherTableName = aBooleans.proxyState.getRow$realm().getTable().getName();\n        if (tableName != null ? !tableName.equals(otherTableName) : otherTableName != null) return false;\n\n        if (proxyState.getRow$realm().getObjectKey() != aBooleans.proxyState.getRow$realm().getObjectKey()) return false;\n\n        return true;\n    }\n}\n"
  },
  {
    "path": "realm/realm-annotations-processor/src/test/resources/io/realm/some_test_EmbeddedClassRealmProxy.java",
    "content": "package io.realm;\n\n\nimport android.annotation.TargetApi;\nimport android.os.Build;\nimport android.util.JsonReader;\nimport android.util.JsonToken;\nimport io.realm.ImportFlag;\nimport io.realm.ProxyUtils;\nimport io.realm.exceptions.RealmMigrationNeededException;\nimport io.realm.internal.ColumnInfo;\nimport io.realm.internal.NativeContext;\nimport io.realm.internal.OsList;\nimport io.realm.internal.OsMap;\nimport io.realm.internal.OsObject;\nimport io.realm.internal.OsObjectSchemaInfo;\nimport io.realm.internal.OsSchemaInfo;\nimport io.realm.internal.OsSet;\nimport io.realm.internal.Property;\nimport io.realm.internal.RealmObjectProxy;\nimport io.realm.internal.Row;\nimport io.realm.internal.Table;\nimport io.realm.internal.android.JsonUtils;\nimport io.realm.internal.core.NativeRealmAny;\nimport io.realm.internal.objectstore.OsObjectBuilder;\nimport io.realm.log.RealmLog;\nimport java.io.IOException;\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.Date;\nimport java.util.HashMap;\nimport java.util.HashSet;\nimport java.util.Iterator;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Set;\nimport org.json.JSONArray;\nimport org.json.JSONException;\nimport org.json.JSONObject;\n\n@SuppressWarnings(\"all\")\npublic class some_test_EmbeddedClassRealmProxy extends some.test.EmbeddedClass\n        implements RealmObjectProxy, some_test_EmbeddedClassRealmProxyInterface {\n\n    static final class EmbeddedClassColumnInfo extends ColumnInfo {\n        long nameColKey;\n        long ageColKey;\n\n        EmbeddedClassColumnInfo(OsSchemaInfo schemaInfo) {\n            super(2);\n            OsObjectSchemaInfo objectSchemaInfo = schemaInfo.getObjectSchemaInfo(\"EmbeddedClass\");\n            this.nameColKey = addColumnDetails(\"name\", \"name\", objectSchemaInfo);\n            this.ageColKey = addColumnDetails(\"age\", \"age\", objectSchemaInfo);\n        }\n\n        EmbeddedClassColumnInfo(ColumnInfo src, boolean mutable) {\n            super(src, mutable);\n            copy(src, this);\n        }\n\n        @Override\n        protected final ColumnInfo copy(boolean mutable) {\n            return new EmbeddedClassColumnInfo(this, mutable);\n        }\n\n        @Override\n        protected final void copy(ColumnInfo rawSrc, ColumnInfo rawDst) {\n            final EmbeddedClassColumnInfo src = (EmbeddedClassColumnInfo) rawSrc;\n            final EmbeddedClassColumnInfo dst = (EmbeddedClassColumnInfo) rawDst;\n            dst.nameColKey = src.nameColKey;\n            dst.ageColKey = src.ageColKey;\n        }\n    }\n\n    private static final String NO_ALIAS = \"\";\n    private static final OsObjectSchemaInfo expectedObjectSchemaInfo = createExpectedObjectSchemaInfo();\n\n    private EmbeddedClassColumnInfo columnInfo;\n    private ProxyState<some.test.EmbeddedClass> proxyState;\n\n    some_test_EmbeddedClassRealmProxy() {\n        proxyState.setConstructionFinished();\n    }\n\n    @Override\n    public void realm$injectObjectContext() {\n        if (this.proxyState != null) {\n            return;\n        }\n        final BaseRealm.RealmObjectContext context = BaseRealm.objectContext.get();\n        this.columnInfo = (EmbeddedClassColumnInfo) context.getColumnInfo();\n        this.proxyState = new ProxyState<some.test.EmbeddedClass>(this);\n        proxyState.setRealm$realm(context.getRealm());\n        proxyState.setRow$realm(context.getRow());\n        proxyState.setAcceptDefaultValue$realm(context.getAcceptDefaultValue());\n        proxyState.setExcludeFields$realm(context.getExcludeFields());\n    }\n\n    @Override\n    @SuppressWarnings(\"cast\")\n    public String realmGet$name() {\n        proxyState.getRealm$realm().checkIfValid();\n        return (java.lang.String) proxyState.getRow$realm().getString(columnInfo.nameColKey);\n    }\n\n    @Override\n    public void realmSet$name(String value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            final Row row = proxyState.getRow$realm();\n            if (value == null) {\n                row.getTable().setNull(columnInfo.nameColKey, row.getObjectKey(), true);\n                return;\n            }\n            row.getTable().setString(columnInfo.nameColKey, row.getObjectKey(), value, true);\n            return;\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        if (value == null) {\n            proxyState.getRow$realm().setNull(columnInfo.nameColKey);\n            return;\n        }\n        proxyState.getRow$realm().setString(columnInfo.nameColKey, value);\n    }\n\n    @Override\n    @SuppressWarnings(\"cast\")\n    public int realmGet$age() {\n        proxyState.getRealm$realm().checkIfValid();\n        return (int) proxyState.getRow$realm().getLong(columnInfo.ageColKey);\n    }\n\n    @Override\n    public void realmSet$age(int value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            final Row row = proxyState.getRow$realm();\n            row.getTable().setLong(columnInfo.ageColKey, row.getObjectKey(), value, true);\n            return;\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        proxyState.getRow$realm().setLong(columnInfo.ageColKey, value);\n    }\n\n    private static OsObjectSchemaInfo createExpectedObjectSchemaInfo() {\n        OsObjectSchemaInfo.Builder builder = new OsObjectSchemaInfo.Builder(NO_ALIAS, \"EmbeddedClass\", true, 2, 0);\n        builder.addPersistedProperty(NO_ALIAS, \"name\", RealmFieldType.STRING, !Property.PRIMARY_KEY, !Property.INDEXED, !Property.REQUIRED);\n        builder.addPersistedProperty(NO_ALIAS, \"age\", RealmFieldType.INTEGER, !Property.PRIMARY_KEY, !Property.INDEXED, Property.REQUIRED);\n        return builder.build();\n    }\n\n    public static OsObjectSchemaInfo getExpectedObjectSchemaInfo() {\n        return expectedObjectSchemaInfo;\n    }\n\n    public static EmbeddedClassColumnInfo createColumnInfo(OsSchemaInfo schemaInfo) {\n        return new EmbeddedClassColumnInfo(schemaInfo);\n    }\n\n    public static String getSimpleClassName() {\n        return \"EmbeddedClass\";\n    }\n\n    public static final class ClassNameHelper {\n        public static final String INTERNAL_CLASS_NAME = \"EmbeddedClass\";\n    }\n\n    @SuppressWarnings(\"cast\")\n    public static some.test.EmbeddedClass createOrUpdateEmbeddedUsingJsonObject(Realm realm, RealmModel parent, String parentProperty, JSONObject json, boolean update)\n            throws JSONException {\n        final List<String> excludeFields = Collections.<String> emptyList();\n        some.test.EmbeddedClass obj = realm.createEmbeddedObject(some.test.EmbeddedClass.class, parent, parentProperty);\n\n        final some_test_EmbeddedClassRealmProxyInterface objProxy = (some_test_EmbeddedClassRealmProxyInterface) obj;\n        if (json.has(\"name\")) {\n            if (json.isNull(\"name\")) {\n                objProxy.realmSet$name(null);\n            } else {\n                objProxy.realmSet$name((String) json.getString(\"name\"));\n            }\n        }\n        if (json.has(\"age\")) {\n            if (json.isNull(\"age\")) {\n                throw new IllegalArgumentException(\"Trying to set non-nullable field 'age' to null.\");\n            } else {\n                objProxy.realmSet$age((int) json.getInt(\"age\"));\n            }\n        }\n        return obj;\n    }\n\n    @SuppressWarnings(\"cast\")\n    @TargetApi(Build.VERSION_CODES.HONEYCOMB)\n    public static some.test.EmbeddedClass createUsingJsonStream(Realm realm, JsonReader reader)\n            throws IOException {\n        final some.test.EmbeddedClass obj = new some.test.EmbeddedClass();\n        final some_test_EmbeddedClassRealmProxyInterface objProxy = (some_test_EmbeddedClassRealmProxyInterface) obj;\n        reader.beginObject();\n        while (reader.hasNext()) {\n            String name = reader.nextName();\n            if (false) {\n            } else if (name.equals(\"name\")) {\n                if (reader.peek() != JsonToken.NULL) {\n                    objProxy.realmSet$name((String) reader.nextString());\n                } else {\n                    reader.skipValue();\n                    objProxy.realmSet$name(null);\n                }\n            } else if (name.equals(\"age\")) {\n                if (reader.peek() != JsonToken.NULL) {\n                    objProxy.realmSet$age((int) reader.nextInt());\n                } else {\n                    reader.skipValue();\n                    throw new IllegalArgumentException(\"Trying to set non-nullable field 'age' to null.\");\n                }\n            } else {\n                reader.skipValue();\n            }\n        }\n        reader.endObject();\n        return obj;\n    }\n\n    static some_test_EmbeddedClassRealmProxy newProxyInstance(BaseRealm realm, Row row) {\n        // Ignore default values to avoid creating unexpected objects from RealmModel/RealmList fields\n        final BaseRealm.RealmObjectContext objectContext = BaseRealm.objectContext.get();\n        objectContext.set(realm, row, realm.getSchema().getColumnInfo(some.test.EmbeddedClass.class), false, Collections.<String>emptyList());\n        io.realm.some_test_EmbeddedClassRealmProxy obj = new io.realm.some_test_EmbeddedClassRealmProxy();\n        objectContext.clear();\n        return obj;\n    }\n\n    public static some.test.EmbeddedClass copyOrUpdate(Realm realm, EmbeddedClassColumnInfo columnInfo, some.test.EmbeddedClass object, boolean update, Map<RealmModel,RealmObjectProxy> cache, Set<ImportFlag> flags) {\n        if (object instanceof RealmObjectProxy && !RealmObject.isFrozen(object) && ((RealmObjectProxy) object).realmGet$proxyState().getRealm$realm() != null) {\n            final BaseRealm otherRealm = ((RealmObjectProxy) object).realmGet$proxyState().getRealm$realm();\n            if (otherRealm.threadId != realm.threadId) {\n                throw new IllegalArgumentException(\"Objects which belong to Realm instances in other threads cannot be copied into this Realm instance.\");\n            }\n            if (otherRealm.getPath().equals(realm.getPath())) {\n                return object;\n            }\n        }\n        final BaseRealm.RealmObjectContext objectContext = BaseRealm.objectContext.get();\n        RealmObjectProxy cachedRealmObject = cache.get(object);\n        if (cachedRealmObject != null) {\n            return (some.test.EmbeddedClass) cachedRealmObject;\n        }\n\n        return copy(realm, columnInfo, object, update, cache, flags);\n    }\n\n    public static some.test.EmbeddedClass copy(Realm realm, EmbeddedClassColumnInfo columnInfo, some.test.EmbeddedClass newObject, boolean update, Map<RealmModel,RealmObjectProxy> cache, Set<ImportFlag> flags) {\n        RealmObjectProxy cachedRealmObject = cache.get(newObject);\n        if (cachedRealmObject != null) {\n            return (some.test.EmbeddedClass) cachedRealmObject;\n        }\n\n        some_test_EmbeddedClassRealmProxyInterface unmanagedSource = (some_test_EmbeddedClassRealmProxyInterface) newObject;\n\n        Table table = realm.getTable(some.test.EmbeddedClass.class);\n        OsObjectBuilder builder = new OsObjectBuilder(table, flags);\n\n        // Add all non-\"object reference\" fields\n        builder.addString(columnInfo.nameColKey, unmanagedSource.realmGet$name());\n        builder.addInteger(columnInfo.ageColKey, unmanagedSource.realmGet$age());\n\n        // Create the underlying object and cache it before setting any object/objectlist references\n        // This will allow us to break any circular dependencies by using the object cache.\n        Row row = builder.createNewObject();\n        io.realm.some_test_EmbeddedClassRealmProxy managedCopy = newProxyInstance(realm, row);\n        cache.put(newObject, managedCopy);\n\n        return managedCopy;\n    }\n\n    public static long insert(Realm realm, Table parentObjectTable, long parentColumnKey, long parentObjectKey, some.test.EmbeddedClass object, Map<RealmModel,Long> cache) {\n        Table table = realm.getTable(some.test.EmbeddedClass.class);\n        long tableNativePtr = table.getNativePtr();\n        EmbeddedClassColumnInfo columnInfo = (EmbeddedClassColumnInfo) realm.getSchema().getColumnInfo(some.test.EmbeddedClass.class);\n        long objKey = OsObject.createEmbeddedObject(parentObjectTable, parentObjectKey, parentColumnKey);\n        cache.put(object, objKey);\n        String realmGet$name = ((some_test_EmbeddedClassRealmProxyInterface) object).realmGet$name();\n        if (realmGet$name != null) {\n            Table.nativeSetString(tableNativePtr, columnInfo.nameColKey, objKey, realmGet$name, false);\n        }\n        Table.nativeSetLong(tableNativePtr, columnInfo.ageColKey, objKey, ((some_test_EmbeddedClassRealmProxyInterface) object).realmGet$age(), false);\n        return objKey;\n    }\n\n    public static void insert(Realm realm, Table parentObjectTable, long parentColumnKey, long parentObjectKey, Iterator<? extends RealmModel> objects, Map<RealmModel,Long> cache) {\n        Table table = realm.getTable(some.test.EmbeddedClass.class);\n        long tableNativePtr = table.getNativePtr();\n        EmbeddedClassColumnInfo columnInfo = (EmbeddedClassColumnInfo) realm.getSchema().getColumnInfo(some.test.EmbeddedClass.class);\n        some.test.EmbeddedClass object = null;\n        while (objects.hasNext()) {\n            object = (some.test.EmbeddedClass) objects.next();\n            if (cache.containsKey(object)) {\n                continue;\n            }\n            if (object instanceof RealmObjectProxy && !RealmObject.isFrozen(object) && ((RealmObjectProxy) object).realmGet$proxyState().getRealm$realm() != null && ((RealmObjectProxy) object).realmGet$proxyState().getRealm$realm().getPath().equals(realm.getPath())) {\n                cache.put(object, ((RealmObjectProxy) object).realmGet$proxyState().getRow$realm().getObjectKey());\n                continue;\n            }\n            long objKey = OsObject.createEmbeddedObject(parentObjectTable, parentObjectKey, parentColumnKey);\n            cache.put(object, objKey);\n            String realmGet$name = ((some_test_EmbeddedClassRealmProxyInterface) object).realmGet$name();\n            if (realmGet$name != null) {\n                Table.nativeSetString(tableNativePtr, columnInfo.nameColKey, objKey, realmGet$name, false);\n            }\n            Table.nativeSetLong(tableNativePtr, columnInfo.ageColKey, objKey, ((some_test_EmbeddedClassRealmProxyInterface) object).realmGet$age(), false);\n        }\n    }\n\n    public static long insertOrUpdate(Realm realm, Table parentObjectTable, long parentColumnKey, long parentObjectKey, some.test.EmbeddedClass object, Map<RealmModel,Long> cache) {\n        if (object instanceof RealmObjectProxy && !RealmObject.isFrozen(object) && ((RealmObjectProxy) object).realmGet$proxyState().getRealm$realm() != null && ((RealmObjectProxy) object).realmGet$proxyState().getRealm$realm().getPath().equals(realm.getPath())) {\n            return ((RealmObjectProxy) object).realmGet$proxyState().getRow$realm().getObjectKey();\n        }\n        Table table = realm.getTable(some.test.EmbeddedClass.class);\n        long tableNativePtr = table.getNativePtr();\n        EmbeddedClassColumnInfo columnInfo = (EmbeddedClassColumnInfo) realm.getSchema().getColumnInfo(some.test.EmbeddedClass.class);\n        long objKey = OsObject.createEmbeddedObject(parentObjectTable, parentObjectKey, parentColumnKey);\n        cache.put(object, objKey);\n        String realmGet$name = ((some_test_EmbeddedClassRealmProxyInterface) object).realmGet$name();\n        if (realmGet$name != null) {\n            Table.nativeSetString(tableNativePtr, columnInfo.nameColKey, objKey, realmGet$name, false);\n        } else {\n            Table.nativeSetNull(tableNativePtr, columnInfo.nameColKey, objKey, false);\n        }\n        Table.nativeSetLong(tableNativePtr, columnInfo.ageColKey, objKey, ((some_test_EmbeddedClassRealmProxyInterface) object).realmGet$age(), false);\n        return objKey;\n    }\n\n    public static void insertOrUpdate(Realm realm, Table parentObjectTable, long parentColumnKey, long parentObjectKey, Iterator<? extends RealmModel> objects, Map<RealmModel,Long> cache) {\n        Table table = realm.getTable(some.test.EmbeddedClass.class);\n        long tableNativePtr = table.getNativePtr();\n        EmbeddedClassColumnInfo columnInfo = (EmbeddedClassColumnInfo) realm.getSchema().getColumnInfo(some.test.EmbeddedClass.class);\n        some.test.EmbeddedClass object = null;\n        while (objects.hasNext()) {\n            object = (some.test.EmbeddedClass) objects.next();\n            if (cache.containsKey(object)) {\n                continue;\n            }\n            if (object instanceof RealmObjectProxy && !RealmObject.isFrozen(object) && ((RealmObjectProxy) object).realmGet$proxyState().getRealm$realm() != null && ((RealmObjectProxy) object).realmGet$proxyState().getRealm$realm().getPath().equals(realm.getPath())) {\n                cache.put(object, ((RealmObjectProxy) object).realmGet$proxyState().getRow$realm().getObjectKey());\n                continue;\n            }\n            long objKey = OsObject.createEmbeddedObject(parentObjectTable, parentObjectKey, parentColumnKey);\n            cache.put(object, objKey);\n            String realmGet$name = ((some_test_EmbeddedClassRealmProxyInterface) object).realmGet$name();\n            if (realmGet$name != null) {\n                Table.nativeSetString(tableNativePtr, columnInfo.nameColKey, objKey, realmGet$name, false);\n            } else {\n                Table.nativeSetNull(tableNativePtr, columnInfo.nameColKey, objKey, false);\n            }\n            Table.nativeSetLong(tableNativePtr, columnInfo.ageColKey, objKey, ((some_test_EmbeddedClassRealmProxyInterface) object).realmGet$age(), false);\n        }\n    }\n\n    public static some.test.EmbeddedClass createDetachedCopy(some.test.EmbeddedClass realmObject, int currentDepth, int maxDepth, Map<RealmModel, CacheData<RealmModel>> cache) {\n        if (currentDepth > maxDepth || realmObject == null) {\n            return null;\n        }\n        CacheData<RealmModel> cachedObject = cache.get(realmObject);\n        some.test.EmbeddedClass unmanagedObject;\n        if (cachedObject == null) {\n            unmanagedObject = new some.test.EmbeddedClass();\n            cache.put(realmObject, new RealmObjectProxy.CacheData<RealmModel>(currentDepth, unmanagedObject));\n        } else {\n            // Reuse cached object or recreate it because it was encountered at a lower depth.\n            if (currentDepth >= cachedObject.minDepth) {\n                return (some.test.EmbeddedClass) cachedObject.object;\n            }\n            unmanagedObject = (some.test.EmbeddedClass) cachedObject.object;\n            cachedObject.minDepth = currentDepth;\n        }\n        some_test_EmbeddedClassRealmProxyInterface unmanagedCopy = (some_test_EmbeddedClassRealmProxyInterface) unmanagedObject;\n        some_test_EmbeddedClassRealmProxyInterface realmSource = (some_test_EmbeddedClassRealmProxyInterface) realmObject;\n        Realm objectRealm = (Realm) ((RealmObjectProxy) realmObject).realmGet$proxyState().getRealm$realm();\n        unmanagedCopy.realmSet$name(realmSource.realmGet$name());\n        unmanagedCopy.realmSet$age(realmSource.realmGet$age());\n\n        return unmanagedObject;\n    }\n\n    static some.test.EmbeddedClass update(Realm realm, EmbeddedClassColumnInfo columnInfo, some.test.EmbeddedClass realmObject, some.test.EmbeddedClass newObject, Map<RealmModel, RealmObjectProxy> cache, Set<ImportFlag> flags) {\n        some_test_EmbeddedClassRealmProxyInterface realmObjectTarget = (some_test_EmbeddedClassRealmProxyInterface) realmObject;\n        some_test_EmbeddedClassRealmProxyInterface realmObjectSource = (some_test_EmbeddedClassRealmProxyInterface) newObject;\n        Table table = realm.getTable(some.test.EmbeddedClass.class);\n        OsObjectBuilder builder = new OsObjectBuilder(table, flags);\n        builder.addString(columnInfo.nameColKey, realmObjectSource.realmGet$name());\n        builder.addInteger(columnInfo.ageColKey, realmObjectSource.realmGet$age());\n\n        builder.updateExistingEmbeddedObject((RealmObjectProxy) realmObject);\n        return realmObject;\n    }\n\n    public static void updateEmbeddedObject(Realm realm, some.test.EmbeddedClass unmanagedObject, some.test.EmbeddedClass managedObject, Map<RealmModel, RealmObjectProxy> cache, Set<ImportFlag> flags) {\n        update(realm, (some_test_EmbeddedClassRealmProxy.EmbeddedClassColumnInfo) realm.getSchema().getColumnInfo(some.test.EmbeddedClass.class), managedObject, unmanagedObject, cache, flags);\n    }\n\n    @Override\n    @SuppressWarnings(\"ArrayToString\")\n    public String toString() {\n        if (!RealmObject.isValid(this)) {\n            return \"Invalid object\";\n        }\n        StringBuilder stringBuilder = new StringBuilder(\"EmbeddedClass = proxy[\");\n        stringBuilder.append(\"{name:\");\n        stringBuilder.append(realmGet$name() != null ? realmGet$name() : \"null\");\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{age:\");\n        stringBuilder.append(realmGet$age());\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\"]\");\n        return stringBuilder.toString();\n    }\n\n    @Override\n    public ProxyState<?> realmGet$proxyState() {\n        return proxyState;\n    }\n\n    @Override\n    public int hashCode() {\n        String realmName = proxyState.getRealm$realm().getPath();\n        String tableName = proxyState.getRow$realm().getTable().getName();\n        long objKey = proxyState.getRow$realm().getObjectKey();\n\n        int result = 17;\n        result = 31 * result + ((realmName != null) ? realmName.hashCode() : 0);\n        result = 31 * result + ((tableName != null) ? tableName.hashCode() : 0);\n        result = 31 * result + (int) (objKey ^ (objKey >>> 32));\n        return result;\n    }\n\n    @Override\n    public boolean equals(Object o) {\n        if (this == o) return true;\n        if (o == null || getClass() != o.getClass()) return false;\n        some_test_EmbeddedClassRealmProxy aEmbeddedClass = (some_test_EmbeddedClassRealmProxy)o;\n\n        BaseRealm realm = proxyState.getRealm$realm();\n        BaseRealm otherRealm = aEmbeddedClass.proxyState.getRealm$realm();\n        String path = realm.getPath();\n        String otherPath = otherRealm.getPath();\n        if (path != null ? !path.equals(otherPath) : otherPath != null) return false;\n        if (realm.isFrozen() != otherRealm.isFrozen()) return false;\n        if (!realm.sharedRealm.getVersionID().equals(otherRealm.sharedRealm.getVersionID())) {\n            return false;\n        }\n\n        String tableName = proxyState.getRow$realm().getTable().getName();\n        String otherTableName = aEmbeddedClass.proxyState.getRow$realm().getTable().getName();\n        if (tableName != null ? !tableName.equals(otherTableName) : otherTableName != null) return false;\n\n        if (proxyState.getRow$realm().getObjectKey() != aEmbeddedClass.proxyState.getRow$realm().getObjectKey()) return false;\n\n        return true;\n    }\n}\n"
  },
  {
    "path": "realm/realm-annotations-processor/src/test/resources/io/realm/some_test_EmbeddedClassSimpleParentRealmProxy.java",
    "content": "package io.realm;\n\n\nimport android.annotation.TargetApi;\nimport android.os.Build;\nimport android.util.JsonReader;\nimport android.util.JsonToken;\nimport io.realm.ImportFlag;\nimport io.realm.ProxyUtils;\nimport io.realm.exceptions.RealmMigrationNeededException;\nimport io.realm.internal.ColumnInfo;\nimport io.realm.internal.NativeContext;\nimport io.realm.internal.OsList;\nimport io.realm.internal.OsMap;\nimport io.realm.internal.OsObject;\nimport io.realm.internal.OsObjectSchemaInfo;\nimport io.realm.internal.OsSchemaInfo;\nimport io.realm.internal.OsSet;\nimport io.realm.internal.Property;\nimport io.realm.internal.RealmObjectProxy;\nimport io.realm.internal.Row;\nimport io.realm.internal.Table;\nimport io.realm.internal.android.JsonUtils;\nimport io.realm.internal.core.NativeRealmAny;\nimport io.realm.internal.objectstore.OsObjectBuilder;\nimport io.realm.log.RealmLog;\nimport java.io.IOException;\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.Date;\nimport java.util.HashMap;\nimport java.util.HashSet;\nimport java.util.Iterator;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Set;\nimport org.json.JSONArray;\nimport org.json.JSONException;\nimport org.json.JSONObject;\n\n@SuppressWarnings(\"all\")\npublic class some_test_EmbeddedClassSimpleParentRealmProxy extends some.test.EmbeddedClassSimpleParent\n        implements RealmObjectProxy, some_test_EmbeddedClassSimpleParentRealmProxyInterface {\n\n    static final class EmbeddedClassSimpleParentColumnInfo extends ColumnInfo {\n        long idColKey;\n        long childColKey;\n        long childrenColKey;\n\n        EmbeddedClassSimpleParentColumnInfo(OsSchemaInfo schemaInfo) {\n            super(3);\n            OsObjectSchemaInfo objectSchemaInfo = schemaInfo.getObjectSchemaInfo(\"EmbeddedClassSimpleParent\");\n            this.idColKey = addColumnDetails(\"id\", \"id\", objectSchemaInfo);\n            this.childColKey = addColumnDetails(\"child\", \"child\", objectSchemaInfo);\n            this.childrenColKey = addColumnDetails(\"children\", \"children\", objectSchemaInfo);\n        }\n\n        EmbeddedClassSimpleParentColumnInfo(ColumnInfo src, boolean mutable) {\n            super(src, mutable);\n            copy(src, this);\n        }\n\n        @Override\n        protected final ColumnInfo copy(boolean mutable) {\n            return new EmbeddedClassSimpleParentColumnInfo(this, mutable);\n        }\n\n        @Override\n        protected final void copy(ColumnInfo rawSrc, ColumnInfo rawDst) {\n            final EmbeddedClassSimpleParentColumnInfo src = (EmbeddedClassSimpleParentColumnInfo) rawSrc;\n            final EmbeddedClassSimpleParentColumnInfo dst = (EmbeddedClassSimpleParentColumnInfo) rawDst;\n            dst.idColKey = src.idColKey;\n            dst.childColKey = src.childColKey;\n            dst.childrenColKey = src.childrenColKey;\n        }\n    }\n\n    private static final String NO_ALIAS = \"\";\n    private static final OsObjectSchemaInfo expectedObjectSchemaInfo = createExpectedObjectSchemaInfo();\n\n    private EmbeddedClassSimpleParentColumnInfo columnInfo;\n    private ProxyState<some.test.EmbeddedClassSimpleParent> proxyState;\n    private RealmList<some.test.EmbeddedClass> childrenRealmList;\n\n    some_test_EmbeddedClassSimpleParentRealmProxy() {\n        proxyState.setConstructionFinished();\n    }\n\n    @Override\n    public void realm$injectObjectContext() {\n        if (this.proxyState != null) {\n            return;\n        }\n        final BaseRealm.RealmObjectContext context = BaseRealm.objectContext.get();\n        this.columnInfo = (EmbeddedClassSimpleParentColumnInfo) context.getColumnInfo();\n        this.proxyState = new ProxyState<some.test.EmbeddedClassSimpleParent>(this);\n        proxyState.setRealm$realm(context.getRealm());\n        proxyState.setRow$realm(context.getRow());\n        proxyState.setAcceptDefaultValue$realm(context.getAcceptDefaultValue());\n        proxyState.setExcludeFields$realm(context.getExcludeFields());\n    }\n\n    @Override\n    @SuppressWarnings(\"cast\")\n    public String realmGet$id() {\n        proxyState.getRealm$realm().checkIfValid();\n        return (java.lang.String) proxyState.getRow$realm().getString(columnInfo.idColKey);\n    }\n\n    @Override\n    public void realmSet$id(String value) {\n        if (proxyState.isUnderConstruction()) {\n            // default value of the primary key is always ignored.\n            return;\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        throw new io.realm.exceptions.RealmException(\"Primary key field 'id' cannot be changed after object was created.\");\n    }\n\n    @Override\n    public some.test.EmbeddedClass realmGet$child() {\n        proxyState.getRealm$realm().checkIfValid();\n        if (proxyState.getRow$realm().isNullLink(columnInfo.childColKey)) {\n            return null;\n        }\n        return proxyState.getRealm$realm().get(some.test.EmbeddedClass.class, proxyState.getRow$realm().getLink(columnInfo.childColKey), false, Collections.<String>emptyList());\n    }\n\n    @Override\n    public void realmSet$child(some.test.EmbeddedClass value) {\n        Realm realm = (Realm) proxyState.getRealm$realm();\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            if (proxyState.getExcludeFields$realm().contains(\"child\")) {\n                return;\n            }\n            if (value != null && !RealmObject.isManaged(value)) {\n                some.test.EmbeddedClass proxyObject = realm.createEmbeddedObject(some.test.EmbeddedClass.class, this, \"child\");\n                some_test_EmbeddedClassRealmProxy.updateEmbeddedObject(realm, value, proxyObject, new HashMap<RealmModel, RealmObjectProxy>(), Collections.EMPTY_SET);\n                value = proxyObject;\n            }\n            final Row row = proxyState.getRow$realm();\n            if (value == null) {\n                // Table#nullifyLink() does not support default value. Just using Row.\n                row.nullifyLink(columnInfo.childColKey);\n                return;\n            }\n            proxyState.checkValidObject(value);\n            row.getTable().setLink(columnInfo.childColKey, row.getObjectKey(), ((RealmObjectProxy) value).realmGet$proxyState().getRow$realm().getObjectKey(), true);\n            return;\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        if (value == null) {\n            proxyState.getRow$realm().nullifyLink(columnInfo.childColKey);\n            return;\n        }\n        if (RealmObject.isManaged(value)) {\n            proxyState.checkValidObject(value);\n        }\n        some.test.EmbeddedClass proxyObject = realm.createEmbeddedObject(some.test.EmbeddedClass.class, this, \"child\");\n        some_test_EmbeddedClassRealmProxy.updateEmbeddedObject(realm, value, proxyObject, new HashMap<RealmModel, RealmObjectProxy>(), Collections.EMPTY_SET);\n    }\n\n    @Override\n    public RealmList<some.test.EmbeddedClass> realmGet$children() {\n        proxyState.getRealm$realm().checkIfValid();\n        // use the cached value if available\n        if (childrenRealmList != null) {\n            return childrenRealmList;\n        } else {\n            OsList osList = proxyState.getRow$realm().getModelList(columnInfo.childrenColKey);\n            childrenRealmList = new RealmList<some.test.EmbeddedClass>(some.test.EmbeddedClass.class, osList, proxyState.getRealm$realm());\n            return childrenRealmList;\n        }\n    }\n\n    @Override\n    public void realmSet$children(RealmList<some.test.EmbeddedClass> value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            if (proxyState.getExcludeFields$realm().contains(\"children\")) {\n                return;\n            }\n            // if the list contains unmanaged RealmObjects, convert them to managed.\n            if (value != null && !value.isManaged()) {\n                final Realm realm = (Realm) proxyState.getRealm$realm();\n                final RealmList<some.test.EmbeddedClass> original = value;\n                value = new RealmList<some.test.EmbeddedClass>();\n                for (some.test.EmbeddedClass item : original) {\n                    if (item == null || RealmObject.isManaged(item)) {\n                        value.add(item);\n                    } else {\n                        value.add(realm.copyToRealm(item));\n                    }\n                }\n            }\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        OsList osList = proxyState.getRow$realm().getModelList(columnInfo.childrenColKey);\n        // For lists of equal lengths, we need to set each element directly as clearing the receiver list can be wrong if the input and target list are the same.\n        if (value != null && value.size() == osList.size()) {\n            int objects = value.size();\n            for (int i = 0; i < objects; i++) {\n                some.test.EmbeddedClass linkedObject = value.get(i);\n                proxyState.checkValidObject(linkedObject);\n                osList.setRow(i, ((RealmObjectProxy) linkedObject).realmGet$proxyState().getRow$realm().getObjectKey());\n            }\n        } else {\n            osList.removeAll();\n            if (value == null) {\n                return;\n            }\n            int objects = value.size();\n            for (int i = 0; i < objects; i++) {\n                some.test.EmbeddedClass linkedObject = value.get(i);\n                proxyState.checkValidObject(linkedObject);\n                osList.addRow(((RealmObjectProxy) linkedObject).realmGet$proxyState().getRow$realm().getObjectKey());\n            }\n        }\n    }\n\n    private static OsObjectSchemaInfo createExpectedObjectSchemaInfo() {\n        OsObjectSchemaInfo.Builder builder = new OsObjectSchemaInfo.Builder(NO_ALIAS, \"EmbeddedClassSimpleParent\", false, 3, 0);\n        builder.addPersistedProperty(NO_ALIAS, \"id\", RealmFieldType.STRING, Property.PRIMARY_KEY, !Property.INDEXED, !Property.REQUIRED);\n        builder.addPersistedLinkProperty(NO_ALIAS, \"child\", RealmFieldType.OBJECT, \"EmbeddedClass\");\n        builder.addPersistedLinkProperty(NO_ALIAS, \"children\", RealmFieldType.LIST, \"EmbeddedClass\");\n        return builder.build();\n    }\n\n    public static OsObjectSchemaInfo getExpectedObjectSchemaInfo() {\n        return expectedObjectSchemaInfo;\n    }\n\n    public static EmbeddedClassSimpleParentColumnInfo createColumnInfo(OsSchemaInfo schemaInfo) {\n        return new EmbeddedClassSimpleParentColumnInfo(schemaInfo);\n    }\n\n    public static String getSimpleClassName() {\n        return \"EmbeddedClassSimpleParent\";\n    }\n\n    public static final class ClassNameHelper {\n        public static final String INTERNAL_CLASS_NAME = \"EmbeddedClassSimpleParent\";\n    }\n\n    @SuppressWarnings(\"cast\")\n    public static some.test.EmbeddedClassSimpleParent createOrUpdateUsingJsonObject(Realm realm, JSONObject json, boolean update)\n            throws JSONException {\n        final List<String> excludeFields = new ArrayList<String>(2);\n        some.test.EmbeddedClassSimpleParent obj = null;\n        if (update) {\n            Table table = realm.getTable(some.test.EmbeddedClassSimpleParent.class);\n            EmbeddedClassSimpleParentColumnInfo columnInfo = (EmbeddedClassSimpleParentColumnInfo) realm.getSchema().getColumnInfo(some.test.EmbeddedClassSimpleParent.class);\n            long pkColumnKey = columnInfo.idColKey;\n            long objKey = Table.NO_MATCH;\n            if (json.isNull(\"id\")) {\n                objKey = table.findFirstNull(pkColumnKey);\n            } else {\n                objKey = table.findFirstString(pkColumnKey, json.getString(\"id\"));\n            }\n            if (objKey != Table.NO_MATCH) {\n                final BaseRealm.RealmObjectContext objectContext = BaseRealm.objectContext.get();\n                try {\n                    objectContext.set(realm, table.getUncheckedRow(objKey), realm.getSchema().getColumnInfo(some.test.EmbeddedClassSimpleParent.class), false, Collections.<String> emptyList());\n                    obj = new io.realm.some_test_EmbeddedClassSimpleParentRealmProxy();\n                } finally {\n                    objectContext.clear();\n                }\n            }\n        }\n        if (obj == null) {\n            if (json.has(\"child\")) {\n                excludeFields.add(\"child\");\n            }\n            if (json.has(\"children\")) {\n                excludeFields.add(\"children\");\n            }\n            if (json.has(\"id\")) {\n                if (json.isNull(\"id\")) {\n                    obj = (io.realm.some_test_EmbeddedClassSimpleParentRealmProxy) realm.createObjectInternal(some.test.EmbeddedClassSimpleParent.class, null, true, excludeFields);\n                } else {\n                    obj = (io.realm.some_test_EmbeddedClassSimpleParentRealmProxy) realm.createObjectInternal(some.test.EmbeddedClassSimpleParent.class, json.getString(\"id\"), true, excludeFields);\n                }\n            } else {\n                throw new IllegalArgumentException(\"JSON object doesn't have the primary key field 'id'.\");\n            }\n        }\n\n        final some_test_EmbeddedClassSimpleParentRealmProxyInterface objProxy = (some_test_EmbeddedClassSimpleParentRealmProxyInterface) obj;\n        if (json.has(\"child\")) {\n            if (json.isNull(\"child\")) {\n                objProxy.realmSet$child(null);\n            } else {\n                some_test_EmbeddedClassRealmProxy.createOrUpdateEmbeddedUsingJsonObject(realm, (RealmModel)objProxy, \"child\", json.getJSONObject(\"child\"), update);\n            }\n        }\n        if (json.has(\"children\")) {\n            if (json.isNull(\"children\")) {\n                objProxy.realmSet$children(null);\n            } else {\n                objProxy.realmGet$children().clear();\n                JSONArray array = json.getJSONArray(\"children\");\n                for (int i = 0; i < array.length(); i++) {\n                    some_test_EmbeddedClassRealmProxy.createOrUpdateEmbeddedUsingJsonObject(realm, (RealmModel)objProxy, \"children\", array.getJSONObject(i), update);\n                }\n            }\n        }\n        return obj;\n    }\n\n    @SuppressWarnings(\"cast\")\n    @TargetApi(Build.VERSION_CODES.HONEYCOMB)\n    public static some.test.EmbeddedClassSimpleParent createUsingJsonStream(Realm realm, JsonReader reader)\n            throws IOException {\n        boolean jsonHasPrimaryKey = false;\n        final some.test.EmbeddedClassSimpleParent obj = new some.test.EmbeddedClassSimpleParent();\n        final some_test_EmbeddedClassSimpleParentRealmProxyInterface objProxy = (some_test_EmbeddedClassSimpleParentRealmProxyInterface) obj;\n        reader.beginObject();\n        while (reader.hasNext()) {\n            String name = reader.nextName();\n            if (false) {\n            } else if (name.equals(\"id\")) {\n                if (reader.peek() != JsonToken.NULL) {\n                    objProxy.realmSet$id((String) reader.nextString());\n                } else {\n                    reader.skipValue();\n                    objProxy.realmSet$id(null);\n                }\n                jsonHasPrimaryKey = true;\n            } else if (name.equals(\"child\")) {\n                if (reader.peek() == JsonToken.NULL) {\n                    reader.skipValue();\n                    objProxy.realmSet$child(null);\n                } else {\n                    some.test.EmbeddedClass childObj = some_test_EmbeddedClassRealmProxy.createUsingJsonStream(realm, reader);\n                    objProxy.realmSet$child(childObj);\n                }\n            } else if (name.equals(\"children\")) {\n                if (reader.peek() == JsonToken.NULL) {\n                    reader.skipValue();\n                    objProxy.realmSet$children(null);\n                } else {\n                    objProxy.realmSet$children(new RealmList<some.test.EmbeddedClass>());\n                    reader.beginArray();\n                    while (reader.hasNext()) {\n                        some.test.EmbeddedClass item = some_test_EmbeddedClassRealmProxy.createUsingJsonStream(realm, reader);\n                        objProxy.realmGet$children().add(item);\n                    }\n                    reader.endArray();\n                }\n            } else {\n                reader.skipValue();\n            }\n        }\n        reader.endObject();\n        if (!jsonHasPrimaryKey) {\n            throw new IllegalArgumentException(\"JSON object doesn't have the primary key field 'id'.\");\n        }\n        return realm.copyToRealmOrUpdate(obj);\n    }\n\n    static some_test_EmbeddedClassSimpleParentRealmProxy newProxyInstance(BaseRealm realm, Row row) {\n        // Ignore default values to avoid creating unexpected objects from RealmModel/RealmList fields\n        final BaseRealm.RealmObjectContext objectContext = BaseRealm.objectContext.get();\n        objectContext.set(realm, row, realm.getSchema().getColumnInfo(some.test.EmbeddedClassSimpleParent.class), false, Collections.<String>emptyList());\n        io.realm.some_test_EmbeddedClassSimpleParentRealmProxy obj = new io.realm.some_test_EmbeddedClassSimpleParentRealmProxy();\n        objectContext.clear();\n        return obj;\n    }\n\n    public static some.test.EmbeddedClassSimpleParent copyOrUpdate(Realm realm, EmbeddedClassSimpleParentColumnInfo columnInfo, some.test.EmbeddedClassSimpleParent object, boolean update, Map<RealmModel,RealmObjectProxy> cache, Set<ImportFlag> flags) {\n        if (object instanceof RealmObjectProxy && !RealmObject.isFrozen(object) && ((RealmObjectProxy) object).realmGet$proxyState().getRealm$realm() != null) {\n            final BaseRealm otherRealm = ((RealmObjectProxy) object).realmGet$proxyState().getRealm$realm();\n            if (otherRealm.threadId != realm.threadId) {\n                throw new IllegalArgumentException(\"Objects which belong to Realm instances in other threads cannot be copied into this Realm instance.\");\n            }\n            if (otherRealm.getPath().equals(realm.getPath())) {\n                return object;\n            }\n        }\n        final BaseRealm.RealmObjectContext objectContext = BaseRealm.objectContext.get();\n        RealmObjectProxy cachedRealmObject = cache.get(object);\n        if (cachedRealmObject != null) {\n            return (some.test.EmbeddedClassSimpleParent) cachedRealmObject;\n        }\n\n        some.test.EmbeddedClassSimpleParent realmObject = null;\n        boolean canUpdate = update;\n        if (canUpdate) {\n            Table table = realm.getTable(some.test.EmbeddedClassSimpleParent.class);\n            long pkColumnKey = columnInfo.idColKey;\n            String value = ((some_test_EmbeddedClassSimpleParentRealmProxyInterface) object).realmGet$id();\n            long objKey = Table.NO_MATCH;\n            if (value == null) {\n                objKey = table.findFirstNull(pkColumnKey);\n            } else {\n                objKey = table.findFirstString(pkColumnKey, value);\n            }\n            if (objKey == Table.NO_MATCH) {\n                canUpdate = false;\n            } else {\n                try {\n                    objectContext.set(realm, table.getUncheckedRow(objKey), columnInfo, false, Collections.<String> emptyList());\n                    realmObject = new io.realm.some_test_EmbeddedClassSimpleParentRealmProxy();\n                    cache.put(object, (RealmObjectProxy) realmObject);\n                } finally {\n                    objectContext.clear();\n                }\n            }\n        }\n\n        return (canUpdate) ? update(realm, columnInfo, realmObject, object, cache, flags) : copy(realm, columnInfo, object, update, cache, flags);\n    }\n\n    public static some.test.EmbeddedClassSimpleParent copy(Realm realm, EmbeddedClassSimpleParentColumnInfo columnInfo, some.test.EmbeddedClassSimpleParent newObject, boolean update, Map<RealmModel,RealmObjectProxy> cache, Set<ImportFlag> flags) {\n        RealmObjectProxy cachedRealmObject = cache.get(newObject);\n        if (cachedRealmObject != null) {\n            return (some.test.EmbeddedClassSimpleParent) cachedRealmObject;\n        }\n\n        some_test_EmbeddedClassSimpleParentRealmProxyInterface unmanagedSource = (some_test_EmbeddedClassSimpleParentRealmProxyInterface) newObject;\n\n        Table table = realm.getTable(some.test.EmbeddedClassSimpleParent.class);\n        OsObjectBuilder builder = new OsObjectBuilder(table, flags);\n\n        // Add all non-\"object reference\" fields\n        builder.addString(columnInfo.idColKey, unmanagedSource.realmGet$id());\n\n        // Create the underlying object and cache it before setting any object/objectlist references\n        // This will allow us to break any circular dependencies by using the object cache.\n        Row row = builder.createNewObject();\n        io.realm.some_test_EmbeddedClassSimpleParentRealmProxy managedCopy = newProxyInstance(realm, row);\n        cache.put(newObject, managedCopy);\n\n        // Finally add all fields that reference other Realm Objects, either directly or through a list\n        some.test.EmbeddedClass childObj = unmanagedSource.realmGet$child();\n        if (childObj == null) {\n            managedCopy.realmSet$child(null);\n        } else {\n            some.test.EmbeddedClass cachechild = (some.test.EmbeddedClass) cache.get(childObj);\n            if (cachechild != null) {\n                throw new IllegalArgumentException(\"Embedded objects can only have one parent pointing to them. This object was already copied, so another object is pointing to it: cachechild.toString()\");\n            } else {\n                long objKey = ((RealmObjectProxy) managedCopy).realmGet$proxyState().getRow$realm().createEmbeddedObject(columnInfo.childColKey, RealmFieldType.OBJECT);\n                Row linkedObjectRow = realm.getTable(some.test.EmbeddedClass.class).getUncheckedRow(objKey);\n                some.test.EmbeddedClass linkedObject = some_test_EmbeddedClassRealmProxy.newProxyInstance(realm, linkedObjectRow);\n                cache.put(childObj, (RealmObjectProxy) linkedObject);\n                some_test_EmbeddedClassRealmProxy.updateEmbeddedObject(realm, childObj, linkedObject, cache, flags);\n            }\n        }\n\n        RealmList<some.test.EmbeddedClass> childrenUnmanagedList = unmanagedSource.realmGet$children();\n        if (childrenUnmanagedList != null) {\n            RealmList<some.test.EmbeddedClass> childrenManagedList = managedCopy.realmGet$children();\n            childrenManagedList.clear();\n            for (int i = 0; i < childrenUnmanagedList.size(); i++) {\n                some.test.EmbeddedClass childrenUnmanagedItem = childrenUnmanagedList.get(i);\n                some.test.EmbeddedClass cachechildren = (some.test.EmbeddedClass) cache.get(childrenUnmanagedItem);\n                if (cachechildren != null) {\n                    throw new IllegalArgumentException(\"Embedded objects can only have one parent pointing to them. This object was already copied, so another object is pointing to it: cachechildren.toString()\");\n                } else {\n                    long objKey = childrenManagedList.getOsList().createAndAddEmbeddedObject();\n                    Row linkedObjectRow = realm.getTable(some.test.EmbeddedClass.class).getUncheckedRow(objKey);\n                    some.test.EmbeddedClass linkedObject = some_test_EmbeddedClassRealmProxy.newProxyInstance(realm, linkedObjectRow);\n                    cache.put(childrenUnmanagedItem, (RealmObjectProxy) linkedObject);\n                    some_test_EmbeddedClassRealmProxy.updateEmbeddedObject(realm, childrenUnmanagedItem, linkedObject, new HashMap<RealmModel, RealmObjectProxy>(), Collections.EMPTY_SET);\n                }\n            }\n        }\n\n        return managedCopy;\n    }\n\n    public static long insert(Realm realm, some.test.EmbeddedClassSimpleParent object, Map<RealmModel,Long> cache) {\n        if (object instanceof RealmObjectProxy && !RealmObject.isFrozen(object) && ((RealmObjectProxy) object).realmGet$proxyState().getRealm$realm() != null && ((RealmObjectProxy) object).realmGet$proxyState().getRealm$realm().getPath().equals(realm.getPath())) {\n            return ((RealmObjectProxy) object).realmGet$proxyState().getRow$realm().getObjectKey();\n        }\n        Table table = realm.getTable(some.test.EmbeddedClassSimpleParent.class);\n        long tableNativePtr = table.getNativePtr();\n        EmbeddedClassSimpleParentColumnInfo columnInfo = (EmbeddedClassSimpleParentColumnInfo) realm.getSchema().getColumnInfo(some.test.EmbeddedClassSimpleParent.class);\n        long pkColumnKey = columnInfo.idColKey;\n        String primaryKeyValue = ((some_test_EmbeddedClassSimpleParentRealmProxyInterface) object).realmGet$id();\n        long objKey = Table.NO_MATCH;\n        if (primaryKeyValue == null) {\n            objKey = Table.nativeFindFirstNull(tableNativePtr, pkColumnKey);\n        } else {\n            objKey = Table.nativeFindFirstString(tableNativePtr, pkColumnKey, primaryKeyValue);\n        }\n        if (objKey == Table.NO_MATCH) {\n            objKey = OsObject.createRowWithPrimaryKey(table, pkColumnKey, primaryKeyValue);\n        } else {\n            Table.throwDuplicatePrimaryKeyException(primaryKeyValue);\n        }\n        cache.put(object, objKey);\n\n        some.test.EmbeddedClass childObj = ((some_test_EmbeddedClassSimpleParentRealmProxyInterface) object).realmGet$child();\n        if (childObj != null) {\n            Long cachechild = cache.get(childObj);\n            if (cachechild != null) {\n                throw new IllegalArgumentException(\"Embedded objects can only have one parent pointing to them. This object was already copied, so another object is pointing to it: \" + cachechild.toString());\n            } else {\n                cachechild = some_test_EmbeddedClassRealmProxy.insert(realm, table, columnInfo.childColKey, objKey, childObj, cache);\n            }\n        }\n\n        RealmList<some.test.EmbeddedClass> childrenList = ((some_test_EmbeddedClassSimpleParentRealmProxyInterface) object).realmGet$children();\n        if (childrenList != null) {\n            OsList childrenOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.childrenColKey);\n            for (some.test.EmbeddedClass childrenItem : childrenList) {\n                Long cacheItemIndexchildren = cache.get(childrenItem);\n                if (cacheItemIndexchildren != null) {\n                    throw new IllegalArgumentException(\"Embedded objects can only have one parent pointing to them. This object was already copied, so another object is pointing to it: \" + cacheItemIndexchildren.toString());\n                } else {\n                    cacheItemIndexchildren = some_test_EmbeddedClassRealmProxy.insert(realm, table, columnInfo.childrenColKey, objKey, childrenItem, cache);\n                }\n            }\n        }\n        return objKey;\n    }\n\n    public static void insert(Realm realm, Iterator<? extends RealmModel> objects, Map<RealmModel,Long> cache) {\n        Table table = realm.getTable(some.test.EmbeddedClassSimpleParent.class);\n        long tableNativePtr = table.getNativePtr();\n        EmbeddedClassSimpleParentColumnInfo columnInfo = (EmbeddedClassSimpleParentColumnInfo) realm.getSchema().getColumnInfo(some.test.EmbeddedClassSimpleParent.class);\n        long pkColumnKey = columnInfo.idColKey;\n        some.test.EmbeddedClassSimpleParent object = null;\n        while (objects.hasNext()) {\n            object = (some.test.EmbeddedClassSimpleParent) objects.next();\n            if (cache.containsKey(object)) {\n                continue;\n            }\n            if (object instanceof RealmObjectProxy && !RealmObject.isFrozen(object) && ((RealmObjectProxy) object).realmGet$proxyState().getRealm$realm() != null && ((RealmObjectProxy) object).realmGet$proxyState().getRealm$realm().getPath().equals(realm.getPath())) {\n                cache.put(object, ((RealmObjectProxy) object).realmGet$proxyState().getRow$realm().getObjectKey());\n                continue;\n            }\n            String primaryKeyValue = ((some_test_EmbeddedClassSimpleParentRealmProxyInterface) object).realmGet$id();\n            long objKey = Table.NO_MATCH;\n            if (primaryKeyValue == null) {\n                objKey = Table.nativeFindFirstNull(tableNativePtr, pkColumnKey);\n            } else {\n                objKey = Table.nativeFindFirstString(tableNativePtr, pkColumnKey, primaryKeyValue);\n            }\n            if (objKey == Table.NO_MATCH) {\n                objKey = OsObject.createRowWithPrimaryKey(table, pkColumnKey, primaryKeyValue);\n            } else {\n                Table.throwDuplicatePrimaryKeyException(primaryKeyValue);\n            }\n            cache.put(object, objKey);\n\n            some.test.EmbeddedClass childObj = ((some_test_EmbeddedClassSimpleParentRealmProxyInterface) object).realmGet$child();\n            if (childObj != null) {\n                Long cachechild = cache.get(childObj);\n                if (cachechild != null) {\n                    throw new IllegalArgumentException(\"Embedded objects can only have one parent pointing to them. This object was already copied, so another object is pointing to it: \" + cachechild.toString());\n                } else {\n                    cachechild = some_test_EmbeddedClassRealmProxy.insert(realm, table, columnInfo.childColKey, objKey, childObj, cache);\n                }\n            }\n\n            RealmList<some.test.EmbeddedClass> childrenList = ((some_test_EmbeddedClassSimpleParentRealmProxyInterface) object).realmGet$children();\n            if (childrenList != null) {\n                OsList childrenOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.childrenColKey);\n                for (some.test.EmbeddedClass childrenItem : childrenList) {\n                    Long cacheItemIndexchildren = cache.get(childrenItem);\n                    if (cacheItemIndexchildren != null) {\n                        throw new IllegalArgumentException(\"Embedded objects can only have one parent pointing to them. This object was already copied, so another object is pointing to it: \" + cacheItemIndexchildren.toString());\n                    } else {\n                        cacheItemIndexchildren = some_test_EmbeddedClassRealmProxy.insert(realm, table, columnInfo.childrenColKey, objKey, childrenItem, cache);\n                    }\n                }\n            }\n        }\n    }\n\n    public static long insertOrUpdate(Realm realm, some.test.EmbeddedClassSimpleParent object, Map<RealmModel,Long> cache) {\n        if (object instanceof RealmObjectProxy && !RealmObject.isFrozen(object) && ((RealmObjectProxy) object).realmGet$proxyState().getRealm$realm() != null && ((RealmObjectProxy) object).realmGet$proxyState().getRealm$realm().getPath().equals(realm.getPath())) {\n            return ((RealmObjectProxy) object).realmGet$proxyState().getRow$realm().getObjectKey();\n        }\n        Table table = realm.getTable(some.test.EmbeddedClassSimpleParent.class);\n        long tableNativePtr = table.getNativePtr();\n        EmbeddedClassSimpleParentColumnInfo columnInfo = (EmbeddedClassSimpleParentColumnInfo) realm.getSchema().getColumnInfo(some.test.EmbeddedClassSimpleParent.class);\n        long pkColumnKey = columnInfo.idColKey;\n        String primaryKeyValue = ((some_test_EmbeddedClassSimpleParentRealmProxyInterface) object).realmGet$id();\n        long objKey = Table.NO_MATCH;\n        if (primaryKeyValue == null) {\n            objKey = Table.nativeFindFirstNull(tableNativePtr, pkColumnKey);\n        } else {\n            objKey = Table.nativeFindFirstString(tableNativePtr, pkColumnKey, primaryKeyValue);\n        }\n        if (objKey == Table.NO_MATCH) {\n            objKey = OsObject.createRowWithPrimaryKey(table, pkColumnKey, primaryKeyValue);\n        }\n        cache.put(object, objKey);\n\n        some.test.EmbeddedClass childObj = ((some_test_EmbeddedClassSimpleParentRealmProxyInterface) object).realmGet$child();\n        if (childObj != null) {\n            Long cachechild = cache.get(childObj);\n            if (cachechild != null) {\n                throw new IllegalArgumentException(\"Embedded objects can only have one parent pointing to them. This object was already copied, so another object is pointing to it: \" + cachechild.toString());\n            } else {\n                cachechild = some_test_EmbeddedClassRealmProxy.insertOrUpdate(realm, table, columnInfo.childColKey, objKey, childObj, cache);\n            }\n        } else {\n            Table.nativeNullifyLink(tableNativePtr, columnInfo.childColKey, objKey);\n        }\n\n        OsList childrenOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.childrenColKey);\n        RealmList<some.test.EmbeddedClass> childrenList = ((some_test_EmbeddedClassSimpleParentRealmProxyInterface) object).realmGet$children();\n        childrenOsList.removeAll();\n        if (childrenList != null) {\n            for (some.test.EmbeddedClass childrenItem : childrenList) {\n                Long cacheItemIndexchildren = cache.get(childrenItem);\n                if (cacheItemIndexchildren != null) {\n                    throw new IllegalArgumentException(\"Embedded objects can only have one parent pointing to them. This object was already copied, so another object is pointing to it: \" + cacheItemIndexchildren.toString());\n                } else {\n                    cacheItemIndexchildren = some_test_EmbeddedClassRealmProxy.insertOrUpdate(realm, table, columnInfo.childrenColKey, objKey, childrenItem, cache);\n                }\n            }\n        }\n\n        return objKey;\n    }\n\n    public static void insertOrUpdate(Realm realm, Iterator<? extends RealmModel> objects, Map<RealmModel,Long> cache) {\n        Table table = realm.getTable(some.test.EmbeddedClassSimpleParent.class);\n        long tableNativePtr = table.getNativePtr();\n        EmbeddedClassSimpleParentColumnInfo columnInfo = (EmbeddedClassSimpleParentColumnInfo) realm.getSchema().getColumnInfo(some.test.EmbeddedClassSimpleParent.class);\n        long pkColumnKey = columnInfo.idColKey;\n        some.test.EmbeddedClassSimpleParent object = null;\n        while (objects.hasNext()) {\n            object = (some.test.EmbeddedClassSimpleParent) objects.next();\n            if (cache.containsKey(object)) {\n                continue;\n            }\n            if (object instanceof RealmObjectProxy && !RealmObject.isFrozen(object) && ((RealmObjectProxy) object).realmGet$proxyState().getRealm$realm() != null && ((RealmObjectProxy) object).realmGet$proxyState().getRealm$realm().getPath().equals(realm.getPath())) {\n                cache.put(object, ((RealmObjectProxy) object).realmGet$proxyState().getRow$realm().getObjectKey());\n                continue;\n            }\n            String primaryKeyValue = ((some_test_EmbeddedClassSimpleParentRealmProxyInterface) object).realmGet$id();\n            long objKey = Table.NO_MATCH;\n            if (primaryKeyValue == null) {\n                objKey = Table.nativeFindFirstNull(tableNativePtr, pkColumnKey);\n            } else {\n                objKey = Table.nativeFindFirstString(tableNativePtr, pkColumnKey, primaryKeyValue);\n            }\n            if (objKey == Table.NO_MATCH) {\n                objKey = OsObject.createRowWithPrimaryKey(table, pkColumnKey, primaryKeyValue);\n            }\n            cache.put(object, objKey);\n\n            some.test.EmbeddedClass childObj = ((some_test_EmbeddedClassSimpleParentRealmProxyInterface) object).realmGet$child();\n            if (childObj != null) {\n                Long cachechild = cache.get(childObj);\n                if (cachechild != null) {\n                    throw new IllegalArgumentException(\"Embedded objects can only have one parent pointing to them. This object was already copied, so another object is pointing to it: \" + cachechild.toString());\n                } else {\n                    cachechild = some_test_EmbeddedClassRealmProxy.insertOrUpdate(realm, table, columnInfo.childColKey, objKey, childObj, cache);\n                }\n            } else {\n                Table.nativeNullifyLink(tableNativePtr, columnInfo.childColKey, objKey);\n            }\n\n            OsList childrenOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.childrenColKey);\n            RealmList<some.test.EmbeddedClass> childrenList = ((some_test_EmbeddedClassSimpleParentRealmProxyInterface) object).realmGet$children();\n            childrenOsList.removeAll();\n            if (childrenList != null) {\n                for (some.test.EmbeddedClass childrenItem : childrenList) {\n                    Long cacheItemIndexchildren = cache.get(childrenItem);\n                    if (cacheItemIndexchildren != null) {\n                        throw new IllegalArgumentException(\"Embedded objects can only have one parent pointing to them. This object was already copied, so another object is pointing to it: \" + cacheItemIndexchildren.toString());\n                    } else {\n                        cacheItemIndexchildren = some_test_EmbeddedClassRealmProxy.insertOrUpdate(realm, table, columnInfo.childrenColKey, objKey, childrenItem, cache);\n                    }\n                }\n            }\n\n        }\n    }\n\n    public static some.test.EmbeddedClassSimpleParent createDetachedCopy(some.test.EmbeddedClassSimpleParent realmObject, int currentDepth, int maxDepth, Map<RealmModel, CacheData<RealmModel>> cache) {\n        if (currentDepth > maxDepth || realmObject == null) {\n            return null;\n        }\n        CacheData<RealmModel> cachedObject = cache.get(realmObject);\n        some.test.EmbeddedClassSimpleParent unmanagedObject;\n        if (cachedObject == null) {\n            unmanagedObject = new some.test.EmbeddedClassSimpleParent();\n            cache.put(realmObject, new RealmObjectProxy.CacheData<RealmModel>(currentDepth, unmanagedObject));\n        } else {\n            // Reuse cached object or recreate it because it was encountered at a lower depth.\n            if (currentDepth >= cachedObject.minDepth) {\n                return (some.test.EmbeddedClassSimpleParent) cachedObject.object;\n            }\n            unmanagedObject = (some.test.EmbeddedClassSimpleParent) cachedObject.object;\n            cachedObject.minDepth = currentDepth;\n        }\n        some_test_EmbeddedClassSimpleParentRealmProxyInterface unmanagedCopy = (some_test_EmbeddedClassSimpleParentRealmProxyInterface) unmanagedObject;\n        some_test_EmbeddedClassSimpleParentRealmProxyInterface realmSource = (some_test_EmbeddedClassSimpleParentRealmProxyInterface) realmObject;\n        Realm objectRealm = (Realm) ((RealmObjectProxy) realmObject).realmGet$proxyState().getRealm$realm();\n        unmanagedCopy.realmSet$id(realmSource.realmGet$id());\n\n        // Deep copy of child\n        unmanagedCopy.realmSet$child(some_test_EmbeddedClassRealmProxy.createDetachedCopy(realmSource.realmGet$child(), currentDepth + 1, maxDepth, cache));\n\n        // Deep copy of children\n        if (currentDepth == maxDepth) {\n            unmanagedCopy.realmSet$children(null);\n        } else {\n            RealmList<some.test.EmbeddedClass> managedchildrenList = realmSource.realmGet$children();\n            RealmList<some.test.EmbeddedClass> unmanagedchildrenList = new RealmList<some.test.EmbeddedClass>();\n            unmanagedCopy.realmSet$children(unmanagedchildrenList);\n            int nextDepth = currentDepth + 1;\n            int size = managedchildrenList.size();\n            for (int i = 0; i < size; i++) {\n                some.test.EmbeddedClass item = some_test_EmbeddedClassRealmProxy.createDetachedCopy(managedchildrenList.get(i), nextDepth, maxDepth, cache);\n                unmanagedchildrenList.add(item);\n            }\n        }\n\n        return unmanagedObject;\n    }\n\n    static some.test.EmbeddedClassSimpleParent update(Realm realm, EmbeddedClassSimpleParentColumnInfo columnInfo, some.test.EmbeddedClassSimpleParent realmObject, some.test.EmbeddedClassSimpleParent newObject, Map<RealmModel, RealmObjectProxy> cache, Set<ImportFlag> flags) {\n        some_test_EmbeddedClassSimpleParentRealmProxyInterface realmObjectTarget = (some_test_EmbeddedClassSimpleParentRealmProxyInterface) realmObject;\n        some_test_EmbeddedClassSimpleParentRealmProxyInterface realmObjectSource = (some_test_EmbeddedClassSimpleParentRealmProxyInterface) newObject;\n        Table table = realm.getTable(some.test.EmbeddedClassSimpleParent.class);\n        OsObjectBuilder builder = new OsObjectBuilder(table, flags);\n        builder.addString(columnInfo.idColKey, realmObjectSource.realmGet$id());\n\n        some.test.EmbeddedClass childObj = realmObjectSource.realmGet$child();\n        if (childObj == null) {\n            builder.addNull(columnInfo.childColKey);\n        } else {\n            // Embedded objects are created directly instead of using the builder.\n            some.test.EmbeddedClass cachechild = (some.test.EmbeddedClass) cache.get(childObj);\n            if (cachechild != null) {\n                throw new IllegalArgumentException(\"Embedded objects can only have one parent pointing to them. This object was already copied, so another object is pointing to it: cachechild.toString()\");\n            }\n\n            long objKey = ((RealmObjectProxy) realmObject).realmGet$proxyState().getRow$realm().createEmbeddedObject(columnInfo.childColKey, RealmFieldType.OBJECT);\n            Row row = realm.getTable(some.test.EmbeddedClass.class).getUncheckedRow(objKey);\n            some.test.EmbeddedClass proxyObject = some_test_EmbeddedClassRealmProxy.newProxyInstance(realm, row);\n            cache.put(childObj, (RealmObjectProxy) proxyObject);\n            some_test_EmbeddedClassRealmProxy.updateEmbeddedObject(realm, childObj, proxyObject, cache, flags);\n        }\n\n        RealmList<some.test.EmbeddedClass> childrenUnmanagedList = realmObjectSource.realmGet$children();\n        if (childrenUnmanagedList != null) {\n            RealmList<some.test.EmbeddedClass> childrenManagedCopy = new RealmList<some.test.EmbeddedClass>();\n            OsList targetList = realmObjectTarget.realmGet$children().getOsList();\n            targetList.deleteAll();\n            for (int i = 0; i < childrenUnmanagedList.size(); i++) {\n                some.test.EmbeddedClass childrenUnmanagedItem = childrenUnmanagedList.get(i);\n                some.test.EmbeddedClass cachechildren = (some.test.EmbeddedClass) cache.get(childrenUnmanagedItem);\n                if (cachechildren != null) {\n                    throw new IllegalArgumentException(\"Embedded objects can only have one parent pointing to them. This object was already copied, so another object is pointing to it: cachechildren.toString()\");\n                } else {\n                    long objKey = targetList.createAndAddEmbeddedObject();\n                    Row row = realm.getTable(some.test.EmbeddedClass.class).getUncheckedRow(objKey);\n                    some.test.EmbeddedClass proxyObject = some_test_EmbeddedClassRealmProxy.newProxyInstance(realm, row);\n                    cache.put(childrenUnmanagedItem, (RealmObjectProxy) proxyObject);\n                    childrenManagedCopy.add(proxyObject);\n                    some_test_EmbeddedClassRealmProxy.updateEmbeddedObject(realm, childrenUnmanagedItem, proxyObject, new HashMap<RealmModel, RealmObjectProxy>(), Collections.EMPTY_SET);\n                }\n            }\n        } else {\n            builder.addObjectList(columnInfo.childrenColKey, new RealmList<some.test.EmbeddedClass>());\n        }\n\n        builder.updateExistingTopLevelObject();\n        return realmObject;\n    }\n\n    @Override\n    @SuppressWarnings(\"ArrayToString\")\n    public String toString() {\n        if (!RealmObject.isValid(this)) {\n            return \"Invalid object\";\n        }\n        StringBuilder stringBuilder = new StringBuilder(\"EmbeddedClassSimpleParent = proxy[\");\n        stringBuilder.append(\"{id:\");\n        stringBuilder.append(realmGet$id() != null ? realmGet$id() : \"null\");\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{child:\");\n        stringBuilder.append(realmGet$child() != null ? \"EmbeddedClass\" : \"null\");\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{children:\");\n        stringBuilder.append(\"RealmList<EmbeddedClass>[\").append(realmGet$children().size()).append(\"]\");\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\"]\");\n        return stringBuilder.toString();\n    }\n\n    @Override\n    public ProxyState<?> realmGet$proxyState() {\n        return proxyState;\n    }\n\n    @Override\n    public int hashCode() {\n        String realmName = proxyState.getRealm$realm().getPath();\n        String tableName = proxyState.getRow$realm().getTable().getName();\n        long objKey = proxyState.getRow$realm().getObjectKey();\n\n        int result = 17;\n        result = 31 * result + ((realmName != null) ? realmName.hashCode() : 0);\n        result = 31 * result + ((tableName != null) ? tableName.hashCode() : 0);\n        result = 31 * result + (int) (objKey ^ (objKey >>> 32));\n        return result;\n    }\n\n    @Override\n    public boolean equals(Object o) {\n        if (this == o) return true;\n        if (o == null || getClass() != o.getClass()) return false;\n        some_test_EmbeddedClassSimpleParentRealmProxy aEmbeddedClassSimpleParent = (some_test_EmbeddedClassSimpleParentRealmProxy)o;\n\n        BaseRealm realm = proxyState.getRealm$realm();\n        BaseRealm otherRealm = aEmbeddedClassSimpleParent.proxyState.getRealm$realm();\n        String path = realm.getPath();\n        String otherPath = otherRealm.getPath();\n        if (path != null ? !path.equals(otherPath) : otherPath != null) return false;\n        if (realm.isFrozen() != otherRealm.isFrozen()) return false;\n        if (!realm.sharedRealm.getVersionID().equals(otherRealm.sharedRealm.getVersionID())) {\n            return false;\n        }\n\n        String tableName = proxyState.getRow$realm().getTable().getName();\n        String otherTableName = aEmbeddedClassSimpleParent.proxyState.getRow$realm().getTable().getName();\n        if (tableName != null ? !tableName.equals(otherTableName) : otherTableName != null) return false;\n\n        if (proxyState.getRow$realm().getObjectKey() != aEmbeddedClassSimpleParent.proxyState.getRow$realm().getObjectKey()) return false;\n\n        return true;\n    }\n}\n"
  },
  {
    "path": "realm/realm-annotations-processor/src/test/resources/io/realm/some_test_NamePolicyMixedClassSettingsRealmProxy.java",
    "content": "package io.realm;\n\n\nimport android.annotation.TargetApi;\nimport android.os.Build;\nimport android.util.JsonReader;\nimport android.util.JsonToken;\nimport io.realm.ImportFlag;\nimport io.realm.ProxyUtils;\nimport io.realm.exceptions.RealmMigrationNeededException;\nimport io.realm.internal.ColumnInfo;\nimport io.realm.internal.NativeContext;\nimport io.realm.internal.OsList;\nimport io.realm.internal.OsMap;\nimport io.realm.internal.OsObject;\nimport io.realm.internal.OsObjectSchemaInfo;\nimport io.realm.internal.OsSchemaInfo;\nimport io.realm.internal.OsSet;\nimport io.realm.internal.Property;\nimport io.realm.internal.RealmObjectProxy;\nimport io.realm.internal.Row;\nimport io.realm.internal.Table;\nimport io.realm.internal.android.JsonUtils;\nimport io.realm.internal.core.NativeRealmAny;\nimport io.realm.internal.objectstore.OsObjectBuilder;\nimport io.realm.log.RealmLog;\nimport java.io.IOException;\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.Date;\nimport java.util.HashMap;\nimport java.util.HashSet;\nimport java.util.Iterator;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Set;\nimport org.json.JSONArray;\nimport org.json.JSONException;\nimport org.json.JSONObject;\n\n@SuppressWarnings(\"all\")\npublic class some_test_NamePolicyMixedClassSettingsRealmProxy extends some.test.NamePolicyMixedClassSettings\n        implements RealmObjectProxy, some_test_NamePolicyMixedClassSettingsRealmProxyInterface {\n\n    static final class NamePolicyMixedClassSettingsColumnInfo extends ColumnInfo {\n        long firstNameColKey;\n        long lastNameColKey;\n\n        NamePolicyMixedClassSettingsColumnInfo(OsSchemaInfo schemaInfo) {\n            super(2);\n            OsObjectSchemaInfo objectSchemaInfo = schemaInfo.getObjectSchemaInfo(\"customName\");\n            this.firstNameColKey = addColumnDetails(\"firstName\", \"first_name\", objectSchemaInfo);\n            this.lastNameColKey = addColumnDetails(\"lastName\", \"LastName\", objectSchemaInfo);\n        }\n\n        NamePolicyMixedClassSettingsColumnInfo(ColumnInfo src, boolean mutable) {\n            super(src, mutable);\n            copy(src, this);\n        }\n\n        @Override\n        protected final ColumnInfo copy(boolean mutable) {\n            return new NamePolicyMixedClassSettingsColumnInfo(this, mutable);\n        }\n\n        @Override\n        protected final void copy(ColumnInfo rawSrc, ColumnInfo rawDst) {\n            final NamePolicyMixedClassSettingsColumnInfo src = (NamePolicyMixedClassSettingsColumnInfo) rawSrc;\n            final NamePolicyMixedClassSettingsColumnInfo dst = (NamePolicyMixedClassSettingsColumnInfo) rawDst;\n            dst.firstNameColKey = src.firstNameColKey;\n            dst.lastNameColKey = src.lastNameColKey;\n        }\n    }\n\n    private static final String NO_ALIAS = \"\";\n    private static final OsObjectSchemaInfo expectedObjectSchemaInfo = createExpectedObjectSchemaInfo();\n\n    private NamePolicyMixedClassSettingsColumnInfo columnInfo;\n    private ProxyState<some.test.NamePolicyMixedClassSettings> proxyState;\n\n    some_test_NamePolicyMixedClassSettingsRealmProxy() {\n        proxyState.setConstructionFinished();\n    }\n\n    @Override\n    public void realm$injectObjectContext() {\n        if (this.proxyState != null) {\n            return;\n        }\n        final BaseRealm.RealmObjectContext context = BaseRealm.objectContext.get();\n        this.columnInfo = (NamePolicyMixedClassSettingsColumnInfo) context.getColumnInfo();\n        this.proxyState = new ProxyState<some.test.NamePolicyMixedClassSettings>(this);\n        proxyState.setRealm$realm(context.getRealm());\n        proxyState.setRow$realm(context.getRow());\n        proxyState.setAcceptDefaultValue$realm(context.getAcceptDefaultValue());\n        proxyState.setExcludeFields$realm(context.getExcludeFields());\n    }\n\n    @Override\n    @SuppressWarnings(\"cast\")\n    public String realmGet$firstName() {\n        proxyState.getRealm$realm().checkIfValid();\n        return (java.lang.String) proxyState.getRow$realm().getString(columnInfo.firstNameColKey);\n    }\n\n    @Override\n    public void realmSet$firstName(String value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            final Row row = proxyState.getRow$realm();\n            if (value == null) {\n                row.getTable().setNull(columnInfo.firstNameColKey, row.getObjectKey(), true);\n                return;\n            }\n            row.getTable().setString(columnInfo.firstNameColKey, row.getObjectKey(), value, true);\n            return;\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        if (value == null) {\n            proxyState.getRow$realm().setNull(columnInfo.firstNameColKey);\n            return;\n        }\n        proxyState.getRow$realm().setString(columnInfo.firstNameColKey, value);\n    }\n\n    @Override\n    @SuppressWarnings(\"cast\")\n    public String realmGet$lastName() {\n        proxyState.getRealm$realm().checkIfValid();\n        return (java.lang.String) proxyState.getRow$realm().getString(columnInfo.lastNameColKey);\n    }\n\n    @Override\n    public void realmSet$lastName(String value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            final Row row = proxyState.getRow$realm();\n            if (value == null) {\n                row.getTable().setNull(columnInfo.lastNameColKey, row.getObjectKey(), true);\n                return;\n            }\n            row.getTable().setString(columnInfo.lastNameColKey, row.getObjectKey(), value, true);\n            return;\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        if (value == null) {\n            proxyState.getRow$realm().setNull(columnInfo.lastNameColKey);\n            return;\n        }\n        proxyState.getRow$realm().setString(columnInfo.lastNameColKey, value);\n    }\n\n    private static OsObjectSchemaInfo createExpectedObjectSchemaInfo() {\n        OsObjectSchemaInfo.Builder builder = new OsObjectSchemaInfo.Builder(\"NamePolicyMixedClassSettings\", \"customName\", false, 2, 0);\n        builder.addPersistedProperty(\"firstName\", \"first_name\", RealmFieldType.STRING, !Property.PRIMARY_KEY, !Property.INDEXED, !Property.REQUIRED);\n        builder.addPersistedProperty(\"lastName\", \"LastName\", RealmFieldType.STRING, !Property.PRIMARY_KEY, !Property.INDEXED, !Property.REQUIRED);\n        return builder.build();\n    }\n\n    public static OsObjectSchemaInfo getExpectedObjectSchemaInfo() {\n        return expectedObjectSchemaInfo;\n    }\n\n    public static NamePolicyMixedClassSettingsColumnInfo createColumnInfo(OsSchemaInfo schemaInfo) {\n        return new NamePolicyMixedClassSettingsColumnInfo(schemaInfo);\n    }\n\n    public static String getSimpleClassName() {\n        return \"customName\";\n    }\n\n    public static final class ClassNameHelper {\n        public static final String INTERNAL_CLASS_NAME = \"customName\";\n    }\n\n    @SuppressWarnings(\"cast\")\n    public static some.test.NamePolicyMixedClassSettings createOrUpdateUsingJsonObject(Realm realm, JSONObject json, boolean update)\n            throws JSONException {\n        final List<String> excludeFields = Collections.<String> emptyList();\n        some.test.NamePolicyMixedClassSettings obj = realm.createObjectInternal(some.test.NamePolicyMixedClassSettings.class, true, excludeFields);\n\n        final some_test_NamePolicyMixedClassSettingsRealmProxyInterface objProxy = (some_test_NamePolicyMixedClassSettingsRealmProxyInterface) obj;\n        if (json.has(\"firstName\")) {\n            if (json.isNull(\"firstName\")) {\n                objProxy.realmSet$firstName(null);\n            } else {\n                objProxy.realmSet$firstName((String) json.getString(\"firstName\"));\n            }\n        }\n        if (json.has(\"lastName\")) {\n            if (json.isNull(\"lastName\")) {\n                objProxy.realmSet$lastName(null);\n            } else {\n                objProxy.realmSet$lastName((String) json.getString(\"lastName\"));\n            }\n        }\n        return obj;\n    }\n\n    @SuppressWarnings(\"cast\")\n    @TargetApi(Build.VERSION_CODES.HONEYCOMB)\n    public static some.test.NamePolicyMixedClassSettings createUsingJsonStream(Realm realm, JsonReader reader)\n            throws IOException {\n        final some.test.NamePolicyMixedClassSettings obj = new some.test.NamePolicyMixedClassSettings();\n        final some_test_NamePolicyMixedClassSettingsRealmProxyInterface objProxy = (some_test_NamePolicyMixedClassSettingsRealmProxyInterface) obj;\n        reader.beginObject();\n        while (reader.hasNext()) {\n            String name = reader.nextName();\n            if (false) {\n            } else if (name.equals(\"firstName\")) {\n                if (reader.peek() != JsonToken.NULL) {\n                    objProxy.realmSet$firstName((String) reader.nextString());\n                } else {\n                    reader.skipValue();\n                    objProxy.realmSet$firstName(null);\n                }\n            } else if (name.equals(\"lastName\")) {\n                if (reader.peek() != JsonToken.NULL) {\n                    objProxy.realmSet$lastName((String) reader.nextString());\n                } else {\n                    reader.skipValue();\n                    objProxy.realmSet$lastName(null);\n                }\n            } else {\n                reader.skipValue();\n            }\n        }\n        reader.endObject();\n        return realm.copyToRealm(obj);\n    }\n\n    static some_test_NamePolicyMixedClassSettingsRealmProxy newProxyInstance(BaseRealm realm, Row row) {\n        // Ignore default values to avoid creating unexpected objects from RealmModel/RealmList fields\n        final BaseRealm.RealmObjectContext objectContext = BaseRealm.objectContext.get();\n        objectContext.set(realm, row, realm.getSchema().getColumnInfo(some.test.NamePolicyMixedClassSettings.class), false, Collections.<String>emptyList());\n        io.realm.some_test_NamePolicyMixedClassSettingsRealmProxy obj = new io.realm.some_test_NamePolicyMixedClassSettingsRealmProxy();\n        objectContext.clear();\n        return obj;\n    }\n\n    public static some.test.NamePolicyMixedClassSettings copyOrUpdate(Realm realm, NamePolicyMixedClassSettingsColumnInfo columnInfo, some.test.NamePolicyMixedClassSettings object, boolean update, Map<RealmModel,RealmObjectProxy> cache, Set<ImportFlag> flags) {\n        if (object instanceof RealmObjectProxy && !RealmObject.isFrozen(object) && ((RealmObjectProxy) object).realmGet$proxyState().getRealm$realm() != null) {\n            final BaseRealm otherRealm = ((RealmObjectProxy) object).realmGet$proxyState().getRealm$realm();\n            if (otherRealm.threadId != realm.threadId) {\n                throw new IllegalArgumentException(\"Objects which belong to Realm instances in other threads cannot be copied into this Realm instance.\");\n            }\n            if (otherRealm.getPath().equals(realm.getPath())) {\n                return object;\n            }\n        }\n        final BaseRealm.RealmObjectContext objectContext = BaseRealm.objectContext.get();\n        RealmObjectProxy cachedRealmObject = cache.get(object);\n        if (cachedRealmObject != null) {\n            return (some.test.NamePolicyMixedClassSettings) cachedRealmObject;\n        }\n\n        return copy(realm, columnInfo, object, update, cache, flags);\n    }\n\n    public static some.test.NamePolicyMixedClassSettings copy(Realm realm, NamePolicyMixedClassSettingsColumnInfo columnInfo, some.test.NamePolicyMixedClassSettings newObject, boolean update, Map<RealmModel,RealmObjectProxy> cache, Set<ImportFlag> flags) {\n        RealmObjectProxy cachedRealmObject = cache.get(newObject);\n        if (cachedRealmObject != null) {\n            return (some.test.NamePolicyMixedClassSettings) cachedRealmObject;\n        }\n\n        some_test_NamePolicyMixedClassSettingsRealmProxyInterface unmanagedSource = (some_test_NamePolicyMixedClassSettingsRealmProxyInterface) newObject;\n\n        Table table = realm.getTable(some.test.NamePolicyMixedClassSettings.class);\n        OsObjectBuilder builder = new OsObjectBuilder(table, flags);\n\n        // Add all non-\"object reference\" fields\n        builder.addString(columnInfo.firstNameColKey, unmanagedSource.realmGet$firstName());\n        builder.addString(columnInfo.lastNameColKey, unmanagedSource.realmGet$lastName());\n\n        // Create the underlying object and cache it before setting any object/objectlist references\n        // This will allow us to break any circular dependencies by using the object cache.\n        Row row = builder.createNewObject();\n        io.realm.some_test_NamePolicyMixedClassSettingsRealmProxy managedCopy = newProxyInstance(realm, row);\n        cache.put(newObject, managedCopy);\n\n        return managedCopy;\n    }\n\n    public static long insert(Realm realm, some.test.NamePolicyMixedClassSettings object, Map<RealmModel,Long> cache) {\n        if (object instanceof RealmObjectProxy && !RealmObject.isFrozen(object) && ((RealmObjectProxy) object).realmGet$proxyState().getRealm$realm() != null && ((RealmObjectProxy) object).realmGet$proxyState().getRealm$realm().getPath().equals(realm.getPath())) {\n            return ((RealmObjectProxy) object).realmGet$proxyState().getRow$realm().getObjectKey();\n        }\n        Table table = realm.getTable(some.test.NamePolicyMixedClassSettings.class);\n        long tableNativePtr = table.getNativePtr();\n        NamePolicyMixedClassSettingsColumnInfo columnInfo = (NamePolicyMixedClassSettingsColumnInfo) realm.getSchema().getColumnInfo(some.test.NamePolicyMixedClassSettings.class);\n        long objKey = OsObject.createRow(table);\n        cache.put(object, objKey);\n        String realmGet$firstName = ((some_test_NamePolicyMixedClassSettingsRealmProxyInterface) object).realmGet$firstName();\n        if (realmGet$firstName != null) {\n            Table.nativeSetString(tableNativePtr, columnInfo.firstNameColKey, objKey, realmGet$firstName, false);\n        }\n        String realmGet$lastName = ((some_test_NamePolicyMixedClassSettingsRealmProxyInterface) object).realmGet$lastName();\n        if (realmGet$lastName != null) {\n            Table.nativeSetString(tableNativePtr, columnInfo.lastNameColKey, objKey, realmGet$lastName, false);\n        }\n        return objKey;\n    }\n\n    public static void insert(Realm realm, Iterator<? extends RealmModel> objects, Map<RealmModel,Long> cache) {\n        Table table = realm.getTable(some.test.NamePolicyMixedClassSettings.class);\n        long tableNativePtr = table.getNativePtr();\n        NamePolicyMixedClassSettingsColumnInfo columnInfo = (NamePolicyMixedClassSettingsColumnInfo) realm.getSchema().getColumnInfo(some.test.NamePolicyMixedClassSettings.class);\n        some.test.NamePolicyMixedClassSettings object = null;\n        while (objects.hasNext()) {\n            object = (some.test.NamePolicyMixedClassSettings) objects.next();\n            if (cache.containsKey(object)) {\n                continue;\n            }\n            if (object instanceof RealmObjectProxy && !RealmObject.isFrozen(object) && ((RealmObjectProxy) object).realmGet$proxyState().getRealm$realm() != null && ((RealmObjectProxy) object).realmGet$proxyState().getRealm$realm().getPath().equals(realm.getPath())) {\n                cache.put(object, ((RealmObjectProxy) object).realmGet$proxyState().getRow$realm().getObjectKey());\n                continue;\n            }\n            long objKey = OsObject.createRow(table);\n            cache.put(object, objKey);\n            String realmGet$firstName = ((some_test_NamePolicyMixedClassSettingsRealmProxyInterface) object).realmGet$firstName();\n            if (realmGet$firstName != null) {\n                Table.nativeSetString(tableNativePtr, columnInfo.firstNameColKey, objKey, realmGet$firstName, false);\n            }\n            String realmGet$lastName = ((some_test_NamePolicyMixedClassSettingsRealmProxyInterface) object).realmGet$lastName();\n            if (realmGet$lastName != null) {\n                Table.nativeSetString(tableNativePtr, columnInfo.lastNameColKey, objKey, realmGet$lastName, false);\n            }\n        }\n    }\n\n    public static long insertOrUpdate(Realm realm, some.test.NamePolicyMixedClassSettings object, Map<RealmModel,Long> cache) {\n        if (object instanceof RealmObjectProxy && !RealmObject.isFrozen(object) && ((RealmObjectProxy) object).realmGet$proxyState().getRealm$realm() != null && ((RealmObjectProxy) object).realmGet$proxyState().getRealm$realm().getPath().equals(realm.getPath())) {\n            return ((RealmObjectProxy) object).realmGet$proxyState().getRow$realm().getObjectKey();\n        }\n        Table table = realm.getTable(some.test.NamePolicyMixedClassSettings.class);\n        long tableNativePtr = table.getNativePtr();\n        NamePolicyMixedClassSettingsColumnInfo columnInfo = (NamePolicyMixedClassSettingsColumnInfo) realm.getSchema().getColumnInfo(some.test.NamePolicyMixedClassSettings.class);\n        long objKey = OsObject.createRow(table);\n        cache.put(object, objKey);\n        String realmGet$firstName = ((some_test_NamePolicyMixedClassSettingsRealmProxyInterface) object).realmGet$firstName();\n        if (realmGet$firstName != null) {\n            Table.nativeSetString(tableNativePtr, columnInfo.firstNameColKey, objKey, realmGet$firstName, false);\n        } else {\n            Table.nativeSetNull(tableNativePtr, columnInfo.firstNameColKey, objKey, false);\n        }\n        String realmGet$lastName = ((some_test_NamePolicyMixedClassSettingsRealmProxyInterface) object).realmGet$lastName();\n        if (realmGet$lastName != null) {\n            Table.nativeSetString(tableNativePtr, columnInfo.lastNameColKey, objKey, realmGet$lastName, false);\n        } else {\n            Table.nativeSetNull(tableNativePtr, columnInfo.lastNameColKey, objKey, false);\n        }\n        return objKey;\n    }\n\n    public static void insertOrUpdate(Realm realm, Iterator<? extends RealmModel> objects, Map<RealmModel,Long> cache) {\n        Table table = realm.getTable(some.test.NamePolicyMixedClassSettings.class);\n        long tableNativePtr = table.getNativePtr();\n        NamePolicyMixedClassSettingsColumnInfo columnInfo = (NamePolicyMixedClassSettingsColumnInfo) realm.getSchema().getColumnInfo(some.test.NamePolicyMixedClassSettings.class);\n        some.test.NamePolicyMixedClassSettings object = null;\n        while (objects.hasNext()) {\n            object = (some.test.NamePolicyMixedClassSettings) objects.next();\n            if (cache.containsKey(object)) {\n                continue;\n            }\n            if (object instanceof RealmObjectProxy && !RealmObject.isFrozen(object) && ((RealmObjectProxy) object).realmGet$proxyState().getRealm$realm() != null && ((RealmObjectProxy) object).realmGet$proxyState().getRealm$realm().getPath().equals(realm.getPath())) {\n                cache.put(object, ((RealmObjectProxy) object).realmGet$proxyState().getRow$realm().getObjectKey());\n                continue;\n            }\n            long objKey = OsObject.createRow(table);\n            cache.put(object, objKey);\n            String realmGet$firstName = ((some_test_NamePolicyMixedClassSettingsRealmProxyInterface) object).realmGet$firstName();\n            if (realmGet$firstName != null) {\n                Table.nativeSetString(tableNativePtr, columnInfo.firstNameColKey, objKey, realmGet$firstName, false);\n            } else {\n                Table.nativeSetNull(tableNativePtr, columnInfo.firstNameColKey, objKey, false);\n            }\n            String realmGet$lastName = ((some_test_NamePolicyMixedClassSettingsRealmProxyInterface) object).realmGet$lastName();\n            if (realmGet$lastName != null) {\n                Table.nativeSetString(tableNativePtr, columnInfo.lastNameColKey, objKey, realmGet$lastName, false);\n            } else {\n                Table.nativeSetNull(tableNativePtr, columnInfo.lastNameColKey, objKey, false);\n            }\n        }\n    }\n\n    public static some.test.NamePolicyMixedClassSettings createDetachedCopy(some.test.NamePolicyMixedClassSettings realmObject, int currentDepth, int maxDepth, Map<RealmModel, CacheData<RealmModel>> cache) {\n        if (currentDepth > maxDepth || realmObject == null) {\n            return null;\n        }\n        CacheData<RealmModel> cachedObject = cache.get(realmObject);\n        some.test.NamePolicyMixedClassSettings unmanagedObject;\n        if (cachedObject == null) {\n            unmanagedObject = new some.test.NamePolicyMixedClassSettings();\n            cache.put(realmObject, new RealmObjectProxy.CacheData<RealmModel>(currentDepth, unmanagedObject));\n        } else {\n            // Reuse cached object or recreate it because it was encountered at a lower depth.\n            if (currentDepth >= cachedObject.minDepth) {\n                return (some.test.NamePolicyMixedClassSettings) cachedObject.object;\n            }\n            unmanagedObject = (some.test.NamePolicyMixedClassSettings) cachedObject.object;\n            cachedObject.minDepth = currentDepth;\n        }\n        some_test_NamePolicyMixedClassSettingsRealmProxyInterface unmanagedCopy = (some_test_NamePolicyMixedClassSettingsRealmProxyInterface) unmanagedObject;\n        some_test_NamePolicyMixedClassSettingsRealmProxyInterface realmSource = (some_test_NamePolicyMixedClassSettingsRealmProxyInterface) realmObject;\n        Realm objectRealm = (Realm) ((RealmObjectProxy) realmObject).realmGet$proxyState().getRealm$realm();\n        unmanagedCopy.realmSet$firstName(realmSource.realmGet$firstName());\n        unmanagedCopy.realmSet$lastName(realmSource.realmGet$lastName());\n\n        return unmanagedObject;\n    }\n\n    @Override\n    @SuppressWarnings(\"ArrayToString\")\n    public String toString() {\n        if (!RealmObject.isValid(this)) {\n            return \"Invalid object\";\n        }\n        StringBuilder stringBuilder = new StringBuilder(\"NamePolicyMixedClassSettings = proxy[\");\n        stringBuilder.append(\"{firstName:\");\n        stringBuilder.append(realmGet$firstName() != null ? realmGet$firstName() : \"null\");\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{lastName:\");\n        stringBuilder.append(realmGet$lastName() != null ? realmGet$lastName() : \"null\");\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\"]\");\n        return stringBuilder.toString();\n    }\n\n    @Override\n    public ProxyState<?> realmGet$proxyState() {\n        return proxyState;\n    }\n\n    @Override\n    public int hashCode() {\n        String realmName = proxyState.getRealm$realm().getPath();\n        String tableName = proxyState.getRow$realm().getTable().getName();\n        long objKey = proxyState.getRow$realm().getObjectKey();\n\n        int result = 17;\n        result = 31 * result + ((realmName != null) ? realmName.hashCode() : 0);\n        result = 31 * result + ((tableName != null) ? tableName.hashCode() : 0);\n        result = 31 * result + (int) (objKey ^ (objKey >>> 32));\n        return result;\n    }\n\n    @Override\n    public boolean equals(Object o) {\n        if (this == o) return true;\n        if (o == null || getClass() != o.getClass()) return false;\n        some_test_NamePolicyMixedClassSettingsRealmProxy aNamePolicyMixedClassSettings = (some_test_NamePolicyMixedClassSettingsRealmProxy)o;\n\n        BaseRealm realm = proxyState.getRealm$realm();\n        BaseRealm otherRealm = aNamePolicyMixedClassSettings.proxyState.getRealm$realm();\n        String path = realm.getPath();\n        String otherPath = otherRealm.getPath();\n        if (path != null ? !path.equals(otherPath) : otherPath != null) return false;\n        if (realm.isFrozen() != otherRealm.isFrozen()) return false;\n        if (!realm.sharedRealm.getVersionID().equals(otherRealm.sharedRealm.getVersionID())) {\n            return false;\n        }\n\n        String tableName = proxyState.getRow$realm().getTable().getName();\n        String otherTableName = aNamePolicyMixedClassSettings.proxyState.getRow$realm().getTable().getName();\n        if (tableName != null ? !tableName.equals(otherTableName) : otherTableName != null) return false;\n\n        if (proxyState.getRow$realm().getObjectKey() != aNamePolicyMixedClassSettings.proxyState.getRow$realm().getObjectKey()) return false;\n\n        return true;\n    }\n}\n"
  },
  {
    "path": "realm/realm-annotations-processor/src/test/resources/io/realm/some_test_NamePolicyModuleDefaultsRealmProxy.java",
    "content": "package io.realm;\n\n\nimport android.annotation.TargetApi;\nimport android.os.Build;\nimport android.util.JsonReader;\nimport android.util.JsonToken;\nimport io.realm.ImportFlag;\nimport io.realm.ProxyUtils;\nimport io.realm.exceptions.RealmMigrationNeededException;\nimport io.realm.internal.ColumnInfo;\nimport io.realm.internal.NativeContext;\nimport io.realm.internal.OsList;\nimport io.realm.internal.OsMap;\nimport io.realm.internal.OsObject;\nimport io.realm.internal.OsObjectSchemaInfo;\nimport io.realm.internal.OsSchemaInfo;\nimport io.realm.internal.OsSet;\nimport io.realm.internal.Property;\nimport io.realm.internal.RealmObjectProxy;\nimport io.realm.internal.Row;\nimport io.realm.internal.Table;\nimport io.realm.internal.android.JsonUtils;\nimport io.realm.internal.core.NativeRealmAny;\nimport io.realm.internal.objectstore.OsObjectBuilder;\nimport io.realm.log.RealmLog;\nimport java.io.IOException;\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.Date;\nimport java.util.HashMap;\nimport java.util.HashSet;\nimport java.util.Iterator;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Set;\nimport org.json.JSONArray;\nimport org.json.JSONException;\nimport org.json.JSONObject;\n\n@SuppressWarnings(\"all\")\npublic class some_test_NamePolicyModuleDefaultsRealmProxy extends some.test.NamePolicyModuleDefaults\n        implements RealmObjectProxy, some_test_NamePolicyModuleDefaultsRealmProxyInterface {\n\n    static final class NamePolicyModuleDefaultsColumnInfo extends ColumnInfo {\n        long firstNameColKey;\n        long lastNameColKey;\n\n        NamePolicyModuleDefaultsColumnInfo(OsSchemaInfo schemaInfo) {\n            super(2);\n            OsObjectSchemaInfo objectSchemaInfo = schemaInfo.getObjectSchemaInfo(\"NamePolicyModuleDefaults\");\n            this.firstNameColKey = addColumnDetails(\"firstName\", \"FirstName\", objectSchemaInfo);\n            this.lastNameColKey = addColumnDetails(\"lastName\", \"LastName\", objectSchemaInfo);\n        }\n\n        NamePolicyModuleDefaultsColumnInfo(ColumnInfo src, boolean mutable) {\n            super(src, mutable);\n            copy(src, this);\n        }\n\n        @Override\n        protected final ColumnInfo copy(boolean mutable) {\n            return new NamePolicyModuleDefaultsColumnInfo(this, mutable);\n        }\n\n        @Override\n        protected final void copy(ColumnInfo rawSrc, ColumnInfo rawDst) {\n            final NamePolicyModuleDefaultsColumnInfo src = (NamePolicyModuleDefaultsColumnInfo) rawSrc;\n            final NamePolicyModuleDefaultsColumnInfo dst = (NamePolicyModuleDefaultsColumnInfo) rawDst;\n            dst.firstNameColKey = src.firstNameColKey;\n            dst.lastNameColKey = src.lastNameColKey;\n        }\n    }\n\n    private static final String NO_ALIAS = \"\";\n    private static final OsObjectSchemaInfo expectedObjectSchemaInfo = createExpectedObjectSchemaInfo();\n\n    private NamePolicyModuleDefaultsColumnInfo columnInfo;\n    private ProxyState<some.test.NamePolicyModuleDefaults> proxyState;\n\n    some_test_NamePolicyModuleDefaultsRealmProxy() {\n        proxyState.setConstructionFinished();\n    }\n\n    @Override\n    public void realm$injectObjectContext() {\n        if (this.proxyState != null) {\n            return;\n        }\n        final BaseRealm.RealmObjectContext context = BaseRealm.objectContext.get();\n        this.columnInfo = (NamePolicyModuleDefaultsColumnInfo) context.getColumnInfo();\n        this.proxyState = new ProxyState<some.test.NamePolicyModuleDefaults>(this);\n        proxyState.setRealm$realm(context.getRealm());\n        proxyState.setRow$realm(context.getRow());\n        proxyState.setAcceptDefaultValue$realm(context.getAcceptDefaultValue());\n        proxyState.setExcludeFields$realm(context.getExcludeFields());\n    }\n\n    @Override\n    @SuppressWarnings(\"cast\")\n    public String realmGet$firstName() {\n        proxyState.getRealm$realm().checkIfValid();\n        return (java.lang.String) proxyState.getRow$realm().getString(columnInfo.firstNameColKey);\n    }\n\n    @Override\n    public void realmSet$firstName(String value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            final Row row = proxyState.getRow$realm();\n            if (value == null) {\n                row.getTable().setNull(columnInfo.firstNameColKey, row.getObjectKey(), true);\n                return;\n            }\n            row.getTable().setString(columnInfo.firstNameColKey, row.getObjectKey(), value, true);\n            return;\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        if (value == null) {\n            proxyState.getRow$realm().setNull(columnInfo.firstNameColKey);\n            return;\n        }\n        proxyState.getRow$realm().setString(columnInfo.firstNameColKey, value);\n    }\n\n    @Override\n    @SuppressWarnings(\"cast\")\n    public String realmGet$lastName() {\n        proxyState.getRealm$realm().checkIfValid();\n        return (java.lang.String) proxyState.getRow$realm().getString(columnInfo.lastNameColKey);\n    }\n\n    @Override\n    public void realmSet$lastName(String value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            final Row row = proxyState.getRow$realm();\n            if (value == null) {\n                row.getTable().setNull(columnInfo.lastNameColKey, row.getObjectKey(), true);\n                return;\n            }\n            row.getTable().setString(columnInfo.lastNameColKey, row.getObjectKey(), value, true);\n            return;\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        if (value == null) {\n            proxyState.getRow$realm().setNull(columnInfo.lastNameColKey);\n            return;\n        }\n        proxyState.getRow$realm().setString(columnInfo.lastNameColKey, value);\n    }\n\n    private static OsObjectSchemaInfo createExpectedObjectSchemaInfo() {\n        OsObjectSchemaInfo.Builder builder = new OsObjectSchemaInfo.Builder(NO_ALIAS, \"NamePolicyModuleDefaults\", false, 2, 0);\n        builder.addPersistedProperty(\"firstName\" ,\"FirstName\", RealmFieldType.STRING, !Property.PRIMARY_KEY, !Property.INDEXED, !Property.REQUIRED);\n        builder.addPersistedProperty(\"lastName\" ,\"LastName\", RealmFieldType.STRING, !Property.PRIMARY_KEY, !Property.INDEXED, !Property.REQUIRED);\n        return builder.build();\n    }\n\n    public static OsObjectSchemaInfo getExpectedObjectSchemaInfo() {\n        return expectedObjectSchemaInfo;\n    }\n\n    public static NamePolicyModuleDefaultsColumnInfo createColumnInfo(OsSchemaInfo schemaInfo) {\n        return new NamePolicyModuleDefaultsColumnInfo(schemaInfo);\n    }\n\n    public static String getSimpleClassName() {\n        return \"NamePolicyModuleDefaults\";\n    }\n\n    public static final class ClassNameHelper {\n        public static final String INTERNAL_CLASS_NAME = \"NamePolicyModuleDefaults\";\n    }\n\n    @SuppressWarnings(\"cast\")\n    public static some.test.NamePolicyModuleDefaults createOrUpdateUsingJsonObject(Realm realm, JSONObject json, boolean update)\n            throws JSONException {\n        final List<String> excludeFields = Collections.<String> emptyList();\n        some.test.NamePolicyModuleDefaults obj = realm.createObjectInternal(some.test.NamePolicyModuleDefaults.class, true, excludeFields);\n\n        final some_test_NamePolicyModuleDefaultsRealmProxyInterface objProxy = (some_test_NamePolicyModuleDefaultsRealmProxyInterface) obj;\n        if (json.has(\"firstName\")) {\n            if (json.isNull(\"firstName\")) {\n                objProxy.realmSet$firstName(null);\n            } else {\n                objProxy.realmSet$firstName((String) json.getString(\"firstName\"));\n            }\n        }\n        if (json.has(\"lastName\")) {\n            if (json.isNull(\"lastName\")) {\n                objProxy.realmSet$lastName(null);\n            } else {\n                objProxy.realmSet$lastName((String) json.getString(\"lastName\"));\n            }\n        }\n        return obj;\n    }\n\n    @SuppressWarnings(\"cast\")\n    @TargetApi(Build.VERSION_CODES.HONEYCOMB)\n    public static some.test.NamePolicyModuleDefaults createUsingJsonStream(Realm realm, JsonReader reader)\n            throws IOException {\n        final some.test.NamePolicyModuleDefaults obj = new some.test.NamePolicyModuleDefaults();\n        final some_test_NamePolicyModuleDefaultsRealmProxyInterface objProxy = (some_test_NamePolicyModuleDefaultsRealmProxyInterface) obj;\n        reader.beginObject();\n        while (reader.hasNext()) {\n            String name = reader.nextName();\n            if (false) {\n            } else if (name.equals(\"firstName\")) {\n                if (reader.peek() != JsonToken.NULL) {\n                    objProxy.realmSet$firstName((String) reader.nextString());\n                } else {\n                    reader.skipValue();\n                    objProxy.realmSet$firstName(null);\n                }\n            } else if (name.equals(\"lastName\")) {\n                if (reader.peek() != JsonToken.NULL) {\n                    objProxy.realmSet$lastName((String) reader.nextString());\n                } else {\n                    reader.skipValue();\n                    objProxy.realmSet$lastName(null);\n                }\n            } else {\n                reader.skipValue();\n            }\n        }\n        reader.endObject();\n        return realm.copyToRealm(obj);\n    }\n\n    static some_test_NamePolicyModuleDefaultsRealmProxy newProxyInstance(BaseRealm realm, Row row) {\n        // Ignore default values to avoid creating unexpected objects from RealmModel/RealmList fields\n        final BaseRealm.RealmObjectContext objectContext = BaseRealm.objectContext.get();\n        objectContext.set(realm, row, realm.getSchema().getColumnInfo(some.test.NamePolicyModuleDefaults.class), false, Collections.<String>emptyList());\n        io.realm.some_test_NamePolicyModuleDefaultsRealmProxy obj = new io.realm.some_test_NamePolicyModuleDefaultsRealmProxy();\n        objectContext.clear();\n        return obj;\n    }\n\n    public static some.test.NamePolicyModuleDefaults copyOrUpdate(Realm realm, NamePolicyModuleDefaultsColumnInfo columnInfo, some.test.NamePolicyModuleDefaults object, boolean update, Map<RealmModel,RealmObjectProxy> cache, Set<ImportFlag> flags) {\n        if (object instanceof RealmObjectProxy && !RealmObject.isFrozen(object) && ((RealmObjectProxy) object).realmGet$proxyState().getRealm$realm() != null) {\n            final BaseRealm otherRealm = ((RealmObjectProxy) object).realmGet$proxyState().getRealm$realm();\n            if (otherRealm.threadId != realm.threadId) {\n                throw new IllegalArgumentException(\"Objects which belong to Realm instances in other threads cannot be copied into this Realm instance.\");\n            }\n            if (otherRealm.getPath().equals(realm.getPath())) {\n                return object;\n            }\n        }\n        final BaseRealm.RealmObjectContext objectContext = BaseRealm.objectContext.get();\n        RealmObjectProxy cachedRealmObject = cache.get(object);\n        if (cachedRealmObject != null) {\n            return (some.test.NamePolicyModuleDefaults) cachedRealmObject;\n        }\n\n        return copy(realm, columnInfo, object, update, cache, flags);\n    }\n\n    public static some.test.NamePolicyModuleDefaults copy(Realm realm, NamePolicyModuleDefaultsColumnInfo columnInfo, some.test.NamePolicyModuleDefaults newObject, boolean update, Map<RealmModel,RealmObjectProxy> cache, Set<ImportFlag> flags) {\n        RealmObjectProxy cachedRealmObject = cache.get(newObject);\n        if (cachedRealmObject != null) {\n            return (some.test.NamePolicyModuleDefaults) cachedRealmObject;\n        }\n\n        some_test_NamePolicyModuleDefaultsRealmProxyInterface unmanagedSource = (some_test_NamePolicyModuleDefaultsRealmProxyInterface) newObject;\n\n        Table table = realm.getTable(some.test.NamePolicyModuleDefaults.class);\n        OsObjectBuilder builder = new OsObjectBuilder(table, flags);\n\n        // Add all non-\"object reference\" fields\n        builder.addString(columnInfo.firstNameColKey, unmanagedSource.realmGet$firstName());\n        builder.addString(columnInfo.lastNameColKey, unmanagedSource.realmGet$lastName());\n\n        // Create the underlying object and cache it before setting any object/objectlist references\n        // This will allow us to break any circular dependencies by using the object cache.\n        Row row = builder.createNewObject();\n        io.realm.some_test_NamePolicyModuleDefaultsRealmProxy managedCopy = newProxyInstance(realm, row);\n        cache.put(newObject, managedCopy);\n\n        return managedCopy;\n    }\n\n    public static long insert(Realm realm, some.test.NamePolicyModuleDefaults object, Map<RealmModel,Long> cache) {\n        if (object instanceof RealmObjectProxy && !RealmObject.isFrozen(object) && ((RealmObjectProxy) object).realmGet$proxyState().getRealm$realm() != null && ((RealmObjectProxy) object).realmGet$proxyState().getRealm$realm().getPath().equals(realm.getPath())) {\n            return ((RealmObjectProxy) object).realmGet$proxyState().getRow$realm().getObjectKey();\n        }\n        Table table = realm.getTable(some.test.NamePolicyModuleDefaults.class);\n        long tableNativePtr = table.getNativePtr();\n        NamePolicyModuleDefaultsColumnInfo columnInfo = (NamePolicyModuleDefaultsColumnInfo) realm.getSchema().getColumnInfo(some.test.NamePolicyModuleDefaults.class);\n        long objKey = OsObject.createRow(table);\n        cache.put(object, objKey);\n        String realmGet$firstName = ((some_test_NamePolicyModuleDefaultsRealmProxyInterface) object).realmGet$firstName();\n        if (realmGet$firstName != null) {\n            Table.nativeSetString(tableNativePtr, columnInfo.firstNameColKey, objKey, realmGet$firstName, false);\n        }\n        String realmGet$lastName = ((some_test_NamePolicyModuleDefaultsRealmProxyInterface) object).realmGet$lastName();\n        if (realmGet$lastName != null) {\n            Table.nativeSetString(tableNativePtr, columnInfo.lastNameColKey, objKey, realmGet$lastName, false);\n        }\n        return objKey;\n    }\n\n    public static void insert(Realm realm, Iterator<? extends RealmModel> objects, Map<RealmModel,Long> cache) {\n        Table table = realm.getTable(some.test.NamePolicyModuleDefaults.class);\n        long tableNativePtr = table.getNativePtr();\n        NamePolicyModuleDefaultsColumnInfo columnInfo = (NamePolicyModuleDefaultsColumnInfo) realm.getSchema().getColumnInfo(some.test.NamePolicyModuleDefaults.class);\n        some.test.NamePolicyModuleDefaults object = null;\n        while (objects.hasNext()) {\n            object = (some.test.NamePolicyModuleDefaults) objects.next();\n            if (cache.containsKey(object)) {\n                continue;\n            }\n            if (object instanceof RealmObjectProxy && !RealmObject.isFrozen(object) && ((RealmObjectProxy) object).realmGet$proxyState().getRealm$realm() != null && ((RealmObjectProxy) object).realmGet$proxyState().getRealm$realm().getPath().equals(realm.getPath())) {\n                cache.put(object, ((RealmObjectProxy) object).realmGet$proxyState().getRow$realm().getObjectKey());\n                continue;\n            }\n            long objKey = OsObject.createRow(table);\n            cache.put(object, objKey);\n            String realmGet$firstName = ((some_test_NamePolicyModuleDefaultsRealmProxyInterface) object).realmGet$firstName();\n            if (realmGet$firstName != null) {\n                Table.nativeSetString(tableNativePtr, columnInfo.firstNameColKey, objKey, realmGet$firstName, false);\n            }\n            String realmGet$lastName = ((some_test_NamePolicyModuleDefaultsRealmProxyInterface) object).realmGet$lastName();\n            if (realmGet$lastName != null) {\n                Table.nativeSetString(tableNativePtr, columnInfo.lastNameColKey, objKey, realmGet$lastName, false);\n            }\n        }\n    }\n\n    public static long insertOrUpdate(Realm realm, some.test.NamePolicyModuleDefaults object, Map<RealmModel,Long> cache) {\n        if (object instanceof RealmObjectProxy && !RealmObject.isFrozen(object) && ((RealmObjectProxy) object).realmGet$proxyState().getRealm$realm() != null && ((RealmObjectProxy) object).realmGet$proxyState().getRealm$realm().getPath().equals(realm.getPath())) {\n            return ((RealmObjectProxy) object).realmGet$proxyState().getRow$realm().getObjectKey();\n        }\n        Table table = realm.getTable(some.test.NamePolicyModuleDefaults.class);\n        long tableNativePtr = table.getNativePtr();\n        NamePolicyModuleDefaultsColumnInfo columnInfo = (NamePolicyModuleDefaultsColumnInfo) realm.getSchema().getColumnInfo(some.test.NamePolicyModuleDefaults.class);\n        long objKey = OsObject.createRow(table);\n        cache.put(object, objKey);\n        String realmGet$firstName = ((some_test_NamePolicyModuleDefaultsRealmProxyInterface) object).realmGet$firstName();\n        if (realmGet$firstName != null) {\n            Table.nativeSetString(tableNativePtr, columnInfo.firstNameColKey, objKey, realmGet$firstName, false);\n        } else {\n            Table.nativeSetNull(tableNativePtr, columnInfo.firstNameColKey, objKey, false);\n        }\n        String realmGet$lastName = ((some_test_NamePolicyModuleDefaultsRealmProxyInterface) object).realmGet$lastName();\n        if (realmGet$lastName != null) {\n            Table.nativeSetString(tableNativePtr, columnInfo.lastNameColKey, objKey, realmGet$lastName, false);\n        } else {\n            Table.nativeSetNull(tableNativePtr, columnInfo.lastNameColKey, objKey, false);\n        }\n        return objKey;\n    }\n\n    public static void insertOrUpdate(Realm realm, Iterator<? extends RealmModel> objects, Map<RealmModel,Long> cache) {\n        Table table = realm.getTable(some.test.NamePolicyModuleDefaults.class);\n        long tableNativePtr = table.getNativePtr();\n        NamePolicyModuleDefaultsColumnInfo columnInfo = (NamePolicyModuleDefaultsColumnInfo) realm.getSchema().getColumnInfo(some.test.NamePolicyModuleDefaults.class);\n        some.test.NamePolicyModuleDefaults object = null;\n        while (objects.hasNext()) {\n            object = (some.test.NamePolicyModuleDefaults) objects.next();\n            if (cache.containsKey(object)) {\n                continue;\n            }\n            if (object instanceof RealmObjectProxy && !RealmObject.isFrozen(object) && ((RealmObjectProxy) object).realmGet$proxyState().getRealm$realm() != null && ((RealmObjectProxy) object).realmGet$proxyState().getRealm$realm().getPath().equals(realm.getPath())) {\n                cache.put(object, ((RealmObjectProxy) object).realmGet$proxyState().getRow$realm().getObjectKey());\n                continue;\n            }\n            long objKey = OsObject.createRow(table);\n            cache.put(object, objKey);\n            String realmGet$firstName = ((some_test_NamePolicyModuleDefaultsRealmProxyInterface) object).realmGet$firstName();\n            if (realmGet$firstName != null) {\n                Table.nativeSetString(tableNativePtr, columnInfo.firstNameColKey, objKey, realmGet$firstName, false);\n            } else {\n                Table.nativeSetNull(tableNativePtr, columnInfo.firstNameColKey, objKey, false);\n            }\n            String realmGet$lastName = ((some_test_NamePolicyModuleDefaultsRealmProxyInterface) object).realmGet$lastName();\n            if (realmGet$lastName != null) {\n                Table.nativeSetString(tableNativePtr, columnInfo.lastNameColKey, objKey, realmGet$lastName, false);\n            } else {\n                Table.nativeSetNull(tableNativePtr, columnInfo.lastNameColKey, objKey, false);\n            }\n        }\n    }\n\n    public static some.test.NamePolicyModuleDefaults createDetachedCopy(some.test.NamePolicyModuleDefaults realmObject, int currentDepth, int maxDepth, Map<RealmModel, CacheData<RealmModel>> cache) {\n        if (currentDepth > maxDepth || realmObject == null) {\n            return null;\n        }\n        CacheData<RealmModel> cachedObject = cache.get(realmObject);\n        some.test.NamePolicyModuleDefaults unmanagedObject;\n        if (cachedObject == null) {\n            unmanagedObject = new some.test.NamePolicyModuleDefaults();\n            cache.put(realmObject, new RealmObjectProxy.CacheData<RealmModel>(currentDepth, unmanagedObject));\n        } else {\n            // Reuse cached object or recreate it because it was encountered at a lower depth.\n            if (currentDepth >= cachedObject.minDepth) {\n                return (some.test.NamePolicyModuleDefaults) cachedObject.object;\n            }\n            unmanagedObject = (some.test.NamePolicyModuleDefaults) cachedObject.object;\n            cachedObject.minDepth = currentDepth;\n        }\n        some_test_NamePolicyModuleDefaultsRealmProxyInterface unmanagedCopy = (some_test_NamePolicyModuleDefaultsRealmProxyInterface) unmanagedObject;\n        some_test_NamePolicyModuleDefaultsRealmProxyInterface realmSource = (some_test_NamePolicyModuleDefaultsRealmProxyInterface) realmObject;\n        Realm objectRealm = (Realm) ((RealmObjectProxy) realmObject).realmGet$proxyState().getRealm$realm();\n        unmanagedCopy.realmSet$firstName(realmSource.realmGet$firstName());\n        unmanagedCopy.realmSet$lastName(realmSource.realmGet$lastName());\n\n        return unmanagedObject;\n    }\n\n    @Override\n    @SuppressWarnings(\"ArrayToString\")\n    public String toString() {\n        if (!RealmObject.isValid(this)) {\n            return \"Invalid object\";\n        }\n        StringBuilder stringBuilder = new StringBuilder(\"NamePolicyModuleDefaults = proxy[\");\n        stringBuilder.append(\"{firstName:\");\n        stringBuilder.append(realmGet$firstName() != null ? realmGet$firstName() : \"null\");\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{lastName:\");\n        stringBuilder.append(realmGet$lastName() != null ? realmGet$lastName() : \"null\");\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\"]\");\n        return stringBuilder.toString();\n    }\n\n    @Override\n    public ProxyState<?> realmGet$proxyState() {\n        return proxyState;\n    }\n\n    @Override\n    public int hashCode() {\n        String realmName = proxyState.getRealm$realm().getPath();\n        String tableName = proxyState.getRow$realm().getTable().getName();\n        long objKey = proxyState.getRow$realm().getObjectKey();\n\n        int result = 17;\n        result = 31 * result + ((realmName != null) ? realmName.hashCode() : 0);\n        result = 31 * result + ((tableName != null) ? tableName.hashCode() : 0);\n        result = 31 * result + (int) (objKey ^ (objKey >>> 32));\n        return result;\n    }\n\n    @Override\n    public boolean equals(Object o) {\n        if (this == o) return true;\n        if (o == null || getClass() != o.getClass()) return false;\n        some_test_NamePolicyModuleDefaultsRealmProxy aNamePolicyModuleDefaults = (some_test_NamePolicyModuleDefaultsRealmProxy)o;\n\n        BaseRealm realm = proxyState.getRealm$realm();\n        BaseRealm otherRealm = aNamePolicyModuleDefaults.proxyState.getRealm$realm();\n        String path = realm.getPath();\n        String otherPath = otherRealm.getPath();\n        if (path != null ? !path.equals(otherPath) : otherPath != null) return false;\n        if (realm.isFrozen() != otherRealm.isFrozen()) return false;\n        if (!realm.sharedRealm.getVersionID().equals(otherRealm.sharedRealm.getVersionID())) {\n            return false;\n        }\n\n        String tableName = proxyState.getRow$realm().getTable().getName();\n        String otherTableName = aNamePolicyModuleDefaults.proxyState.getRow$realm().getTable().getName();\n        if (tableName != null ? !tableName.equals(otherTableName) : otherTableName != null) return false;\n\n        if (proxyState.getRow$realm().getObjectKey() != aNamePolicyModuleDefaults.proxyState.getRow$realm().getObjectKey()) return false;\n\n        return true;\n    }\n}\n"
  },
  {
    "path": "realm/realm-annotations-processor/src/test/resources/io/realm/some_test_NullTypesRealmProxy.java",
    "content": "package io.realm;\n\n\nimport android.annotation.TargetApi;\nimport android.os.Build;\nimport android.util.JsonReader;\nimport android.util.JsonToken;\nimport io.realm.ImportFlag;\nimport io.realm.ProxyUtils;\nimport io.realm.exceptions.RealmMigrationNeededException;\nimport io.realm.internal.ColumnInfo;\nimport io.realm.internal.NativeContext;\nimport io.realm.internal.OsList;\nimport io.realm.internal.OsMap;\nimport io.realm.internal.OsObject;\nimport io.realm.internal.OsObjectSchemaInfo;\nimport io.realm.internal.OsSchemaInfo;\nimport io.realm.internal.OsSet;\nimport io.realm.internal.Property;\nimport io.realm.internal.RealmObjectProxy;\nimport io.realm.internal.Row;\nimport io.realm.internal.Table;\nimport io.realm.internal.android.JsonUtils;\nimport io.realm.internal.core.NativeRealmAny;\nimport io.realm.internal.objectstore.OsObjectBuilder;\nimport io.realm.log.RealmLog;\nimport java.io.IOException;\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.Date;\nimport java.util.HashMap;\nimport java.util.HashSet;\nimport java.util.Iterator;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Set;\nimport org.json.JSONArray;\nimport org.json.JSONException;\nimport org.json.JSONObject;\n\n@SuppressWarnings(\"all\")\npublic class some_test_NullTypesRealmProxy extends some.test.NullTypes\n        implements RealmObjectProxy, some_test_NullTypesRealmProxyInterface {\n\n    static final class NullTypesColumnInfo extends ColumnInfo {\n        long fieldStringNotNullColKey;\n        long fieldStringNullColKey;\n        long fieldBooleanNotNullColKey;\n        long fieldBooleanNullColKey;\n        long fieldBytesNotNullColKey;\n        long fieldBytesNullColKey;\n        long fieldByteNotNullColKey;\n        long fieldByteNullColKey;\n        long fieldShortNotNullColKey;\n        long fieldShortNullColKey;\n        long fieldIntegerNotNullColKey;\n        long fieldIntegerNullColKey;\n        long fieldLongNotNullColKey;\n        long fieldLongNullColKey;\n        long fieldFloatNotNullColKey;\n        long fieldFloatNullColKey;\n        long fieldDoubleNotNullColKey;\n        long fieldDoubleNullColKey;\n        long fieldDateNotNullColKey;\n        long fieldDateNullColKey;\n        long fieldDecimal128NotNullColKey;\n        long fieldDecimal128NullColKey;\n        long fieldObjectIdNotNullColKey;\n        long fieldObjectIdNullColKey;\n        long fieldObjectNullColKey;\n        long fieldStringListNotNullColKey;\n        long fieldStringListNullColKey;\n        long fieldBinaryListNotNullColKey;\n        long fieldBinaryListNullColKey;\n        long fieldBooleanListNotNullColKey;\n        long fieldBooleanListNullColKey;\n        long fieldLongListNotNullColKey;\n        long fieldLongListNullColKey;\n        long fieldIntegerListNotNullColKey;\n        long fieldIntegerListNullColKey;\n        long fieldShortListNotNullColKey;\n        long fieldShortListNullColKey;\n        long fieldByteListNotNullColKey;\n        long fieldByteListNullColKey;\n        long fieldDoubleListNotNullColKey;\n        long fieldDoubleListNullColKey;\n        long fieldFloatListNotNullColKey;\n        long fieldFloatListNullColKey;\n        long fieldDateListNotNullColKey;\n        long fieldDateListNullColKey;\n        long fieldDecimal128ListNotNullColKey;\n        long fieldDecimal128ListNullColKey;\n        long fieldObjectIdListNotNullColKey;\n        long fieldObjectIdListNullColKey;\n\n        NullTypesColumnInfo(OsSchemaInfo schemaInfo) {\n            super(49);\n            OsObjectSchemaInfo objectSchemaInfo = schemaInfo.getObjectSchemaInfo(\"NullTypes\");\n            this.fieldStringNotNullColKey = addColumnDetails(\"fieldStringNotNull\", \"fieldStringNotNull\", objectSchemaInfo);\n            this.fieldStringNullColKey = addColumnDetails(\"fieldStringNull\", \"fieldStringNull\", objectSchemaInfo);\n            this.fieldBooleanNotNullColKey = addColumnDetails(\"fieldBooleanNotNull\", \"fieldBooleanNotNull\", objectSchemaInfo);\n            this.fieldBooleanNullColKey = addColumnDetails(\"fieldBooleanNull\", \"fieldBooleanNull\", objectSchemaInfo);\n            this.fieldBytesNotNullColKey = addColumnDetails(\"fieldBytesNotNull\", \"fieldBytesNotNull\", objectSchemaInfo);\n            this.fieldBytesNullColKey = addColumnDetails(\"fieldBytesNull\", \"fieldBytesNull\", objectSchemaInfo);\n            this.fieldByteNotNullColKey = addColumnDetails(\"fieldByteNotNull\", \"fieldByteNotNull\", objectSchemaInfo);\n            this.fieldByteNullColKey = addColumnDetails(\"fieldByteNull\", \"fieldByteNull\", objectSchemaInfo);\n            this.fieldShortNotNullColKey = addColumnDetails(\"fieldShortNotNull\", \"fieldShortNotNull\", objectSchemaInfo);\n            this.fieldShortNullColKey = addColumnDetails(\"fieldShortNull\", \"fieldShortNull\", objectSchemaInfo);\n            this.fieldIntegerNotNullColKey = addColumnDetails(\"fieldIntegerNotNull\", \"fieldIntegerNotNull\", objectSchemaInfo);\n            this.fieldIntegerNullColKey = addColumnDetails(\"fieldIntegerNull\", \"fieldIntegerNull\", objectSchemaInfo);\n            this.fieldLongNotNullColKey = addColumnDetails(\"fieldLongNotNull\", \"fieldLongNotNull\", objectSchemaInfo);\n            this.fieldLongNullColKey = addColumnDetails(\"fieldLongNull\", \"fieldLongNull\", objectSchemaInfo);\n            this.fieldFloatNotNullColKey = addColumnDetails(\"fieldFloatNotNull\", \"fieldFloatNotNull\", objectSchemaInfo);\n            this.fieldFloatNullColKey = addColumnDetails(\"fieldFloatNull\", \"fieldFloatNull\", objectSchemaInfo);\n            this.fieldDoubleNotNullColKey = addColumnDetails(\"fieldDoubleNotNull\", \"fieldDoubleNotNull\", objectSchemaInfo);\n            this.fieldDoubleNullColKey = addColumnDetails(\"fieldDoubleNull\", \"fieldDoubleNull\", objectSchemaInfo);\n            this.fieldDateNotNullColKey = addColumnDetails(\"fieldDateNotNull\", \"fieldDateNotNull\", objectSchemaInfo);\n            this.fieldDateNullColKey = addColumnDetails(\"fieldDateNull\", \"fieldDateNull\", objectSchemaInfo);\n            this.fieldDecimal128NotNullColKey = addColumnDetails(\"fieldDecimal128NotNull\", \"fieldDecimal128NotNull\", objectSchemaInfo);\n            this.fieldDecimal128NullColKey = addColumnDetails(\"fieldDecimal128Null\", \"fieldDecimal128Null\", objectSchemaInfo);\n            this.fieldObjectIdNotNullColKey = addColumnDetails(\"fieldObjectIdNotNull\", \"fieldObjectIdNotNull\", objectSchemaInfo);\n            this.fieldObjectIdNullColKey = addColumnDetails(\"fieldObjectIdNull\", \"fieldObjectIdNull\", objectSchemaInfo);\n            this.fieldObjectNullColKey = addColumnDetails(\"fieldObjectNull\", \"fieldObjectNull\", objectSchemaInfo);\n            this.fieldStringListNotNullColKey = addColumnDetails(\"fieldStringListNotNull\", \"fieldStringListNotNull\", objectSchemaInfo);\n            this.fieldStringListNullColKey = addColumnDetails(\"fieldStringListNull\", \"fieldStringListNull\", objectSchemaInfo);\n            this.fieldBinaryListNotNullColKey = addColumnDetails(\"fieldBinaryListNotNull\", \"fieldBinaryListNotNull\", objectSchemaInfo);\n            this.fieldBinaryListNullColKey = addColumnDetails(\"fieldBinaryListNull\", \"fieldBinaryListNull\", objectSchemaInfo);\n            this.fieldBooleanListNotNullColKey = addColumnDetails(\"fieldBooleanListNotNull\", \"fieldBooleanListNotNull\", objectSchemaInfo);\n            this.fieldBooleanListNullColKey = addColumnDetails(\"fieldBooleanListNull\", \"fieldBooleanListNull\", objectSchemaInfo);\n            this.fieldLongListNotNullColKey = addColumnDetails(\"fieldLongListNotNull\", \"fieldLongListNotNull\", objectSchemaInfo);\n            this.fieldLongListNullColKey = addColumnDetails(\"fieldLongListNull\", \"fieldLongListNull\", objectSchemaInfo);\n            this.fieldIntegerListNotNullColKey = addColumnDetails(\"fieldIntegerListNotNull\", \"fieldIntegerListNotNull\", objectSchemaInfo);\n            this.fieldIntegerListNullColKey = addColumnDetails(\"fieldIntegerListNull\", \"fieldIntegerListNull\", objectSchemaInfo);\n            this.fieldShortListNotNullColKey = addColumnDetails(\"fieldShortListNotNull\", \"fieldShortListNotNull\", objectSchemaInfo);\n            this.fieldShortListNullColKey = addColumnDetails(\"fieldShortListNull\", \"fieldShortListNull\", objectSchemaInfo);\n            this.fieldByteListNotNullColKey = addColumnDetails(\"fieldByteListNotNull\", \"fieldByteListNotNull\", objectSchemaInfo);\n            this.fieldByteListNullColKey = addColumnDetails(\"fieldByteListNull\", \"fieldByteListNull\", objectSchemaInfo);\n            this.fieldDoubleListNotNullColKey = addColumnDetails(\"fieldDoubleListNotNull\", \"fieldDoubleListNotNull\", objectSchemaInfo);\n            this.fieldDoubleListNullColKey = addColumnDetails(\"fieldDoubleListNull\", \"fieldDoubleListNull\", objectSchemaInfo);\n            this.fieldFloatListNotNullColKey = addColumnDetails(\"fieldFloatListNotNull\", \"fieldFloatListNotNull\", objectSchemaInfo);\n            this.fieldFloatListNullColKey = addColumnDetails(\"fieldFloatListNull\", \"fieldFloatListNull\", objectSchemaInfo);\n            this.fieldDateListNotNullColKey = addColumnDetails(\"fieldDateListNotNull\", \"fieldDateListNotNull\", objectSchemaInfo);\n            this.fieldDateListNullColKey = addColumnDetails(\"fieldDateListNull\", \"fieldDateListNull\", objectSchemaInfo);\n            this.fieldDecimal128ListNotNullColKey = addColumnDetails(\"fieldDecimal128ListNotNull\", \"fieldDecimal128ListNotNull\", objectSchemaInfo);\n            this.fieldDecimal128ListNullColKey = addColumnDetails(\"fieldDecimal128ListNull\", \"fieldDecimal128ListNull\", objectSchemaInfo);\n            this.fieldObjectIdListNotNullColKey = addColumnDetails(\"fieldObjectIdListNotNull\", \"fieldObjectIdListNotNull\", objectSchemaInfo);\n            this.fieldObjectIdListNullColKey = addColumnDetails(\"fieldObjectIdListNull\", \"fieldObjectIdListNull\", objectSchemaInfo);\n        }\n\n        NullTypesColumnInfo(ColumnInfo src, boolean mutable) {\n            super(src, mutable);\n            copy(src, this);\n        }\n\n        @Override\n        protected final ColumnInfo copy(boolean mutable) {\n            return new NullTypesColumnInfo(this, mutable);\n        }\n\n        @Override\n        protected final void copy(ColumnInfo rawSrc, ColumnInfo rawDst) {\n            final NullTypesColumnInfo src = (NullTypesColumnInfo) rawSrc;\n            final NullTypesColumnInfo dst = (NullTypesColumnInfo) rawDst;\n            dst.fieldStringNotNullColKey = src.fieldStringNotNullColKey;\n            dst.fieldStringNullColKey = src.fieldStringNullColKey;\n            dst.fieldBooleanNotNullColKey = src.fieldBooleanNotNullColKey;\n            dst.fieldBooleanNullColKey = src.fieldBooleanNullColKey;\n            dst.fieldBytesNotNullColKey = src.fieldBytesNotNullColKey;\n            dst.fieldBytesNullColKey = src.fieldBytesNullColKey;\n            dst.fieldByteNotNullColKey = src.fieldByteNotNullColKey;\n            dst.fieldByteNullColKey = src.fieldByteNullColKey;\n            dst.fieldShortNotNullColKey = src.fieldShortNotNullColKey;\n            dst.fieldShortNullColKey = src.fieldShortNullColKey;\n            dst.fieldIntegerNotNullColKey = src.fieldIntegerNotNullColKey;\n            dst.fieldIntegerNullColKey = src.fieldIntegerNullColKey;\n            dst.fieldLongNotNullColKey = src.fieldLongNotNullColKey;\n            dst.fieldLongNullColKey = src.fieldLongNullColKey;\n            dst.fieldFloatNotNullColKey = src.fieldFloatNotNullColKey;\n            dst.fieldFloatNullColKey = src.fieldFloatNullColKey;\n            dst.fieldDoubleNotNullColKey = src.fieldDoubleNotNullColKey;\n            dst.fieldDoubleNullColKey = src.fieldDoubleNullColKey;\n            dst.fieldDateNotNullColKey = src.fieldDateNotNullColKey;\n            dst.fieldDateNullColKey = src.fieldDateNullColKey;\n            dst.fieldDecimal128NotNullColKey = src.fieldDecimal128NotNullColKey;\n            dst.fieldDecimal128NullColKey = src.fieldDecimal128NullColKey;\n            dst.fieldObjectIdNotNullColKey = src.fieldObjectIdNotNullColKey;\n            dst.fieldObjectIdNullColKey = src.fieldObjectIdNullColKey;\n            dst.fieldObjectNullColKey = src.fieldObjectNullColKey;\n            dst.fieldStringListNotNullColKey = src.fieldStringListNotNullColKey;\n            dst.fieldStringListNullColKey = src.fieldStringListNullColKey;\n            dst.fieldBinaryListNotNullColKey = src.fieldBinaryListNotNullColKey;\n            dst.fieldBinaryListNullColKey = src.fieldBinaryListNullColKey;\n            dst.fieldBooleanListNotNullColKey = src.fieldBooleanListNotNullColKey;\n            dst.fieldBooleanListNullColKey = src.fieldBooleanListNullColKey;\n            dst.fieldLongListNotNullColKey = src.fieldLongListNotNullColKey;\n            dst.fieldLongListNullColKey = src.fieldLongListNullColKey;\n            dst.fieldIntegerListNotNullColKey = src.fieldIntegerListNotNullColKey;\n            dst.fieldIntegerListNullColKey = src.fieldIntegerListNullColKey;\n            dst.fieldShortListNotNullColKey = src.fieldShortListNotNullColKey;\n            dst.fieldShortListNullColKey = src.fieldShortListNullColKey;\n            dst.fieldByteListNotNullColKey = src.fieldByteListNotNullColKey;\n            dst.fieldByteListNullColKey = src.fieldByteListNullColKey;\n            dst.fieldDoubleListNotNullColKey = src.fieldDoubleListNotNullColKey;\n            dst.fieldDoubleListNullColKey = src.fieldDoubleListNullColKey;\n            dst.fieldFloatListNotNullColKey = src.fieldFloatListNotNullColKey;\n            dst.fieldFloatListNullColKey = src.fieldFloatListNullColKey;\n            dst.fieldDateListNotNullColKey = src.fieldDateListNotNullColKey;\n            dst.fieldDateListNullColKey = src.fieldDateListNullColKey;\n            dst.fieldDecimal128ListNotNullColKey = src.fieldDecimal128ListNotNullColKey;\n            dst.fieldDecimal128ListNullColKey = src.fieldDecimal128ListNullColKey;\n            dst.fieldObjectIdListNotNullColKey = src.fieldObjectIdListNotNullColKey;\n            dst.fieldObjectIdListNullColKey = src.fieldObjectIdListNullColKey;\n        }\n    }\n\n    private static final String NO_ALIAS = \"\";\n    private static final OsObjectSchemaInfo expectedObjectSchemaInfo = createExpectedObjectSchemaInfo();\n\n    private NullTypesColumnInfo columnInfo;\n    private ProxyState<some.test.NullTypes> proxyState;\n    private RealmList<String> fieldStringListNotNullRealmList;\n    private RealmList<String> fieldStringListNullRealmList;\n    private RealmList<byte[]> fieldBinaryListNotNullRealmList;\n    private RealmList<byte[]> fieldBinaryListNullRealmList;\n    private RealmList<Boolean> fieldBooleanListNotNullRealmList;\n    private RealmList<Boolean> fieldBooleanListNullRealmList;\n    private RealmList<Long> fieldLongListNotNullRealmList;\n    private RealmList<Long> fieldLongListNullRealmList;\n    private RealmList<Integer> fieldIntegerListNotNullRealmList;\n    private RealmList<Integer> fieldIntegerListNullRealmList;\n    private RealmList<Short> fieldShortListNotNullRealmList;\n    private RealmList<Short> fieldShortListNullRealmList;\n    private RealmList<Byte> fieldByteListNotNullRealmList;\n    private RealmList<Byte> fieldByteListNullRealmList;\n    private RealmList<Double> fieldDoubleListNotNullRealmList;\n    private RealmList<Double> fieldDoubleListNullRealmList;\n    private RealmList<Float> fieldFloatListNotNullRealmList;\n    private RealmList<Float> fieldFloatListNullRealmList;\n    private RealmList<Date> fieldDateListNotNullRealmList;\n    private RealmList<Date> fieldDateListNullRealmList;\n    private RealmList<org.bson.types.Decimal128> fieldDecimal128ListNotNullRealmList;\n    private RealmList<org.bson.types.Decimal128> fieldDecimal128ListNullRealmList;\n    private RealmList<org.bson.types.ObjectId> fieldObjectIdListNotNullRealmList;\n    private RealmList<org.bson.types.ObjectId> fieldObjectIdListNullRealmList;\n\n    some_test_NullTypesRealmProxy() {\n        proxyState.setConstructionFinished();\n    }\n\n    @Override\n    public void realm$injectObjectContext() {\n        if (this.proxyState != null) {\n            return;\n        }\n        final BaseRealm.RealmObjectContext context = BaseRealm.objectContext.get();\n        this.columnInfo = (NullTypesColumnInfo) context.getColumnInfo();\n        this.proxyState = new ProxyState<some.test.NullTypes>(this);\n        proxyState.setRealm$realm(context.getRealm());\n        proxyState.setRow$realm(context.getRow());\n        proxyState.setAcceptDefaultValue$realm(context.getAcceptDefaultValue());\n        proxyState.setExcludeFields$realm(context.getExcludeFields());\n    }\n\n    @Override\n    @SuppressWarnings(\"cast\")\n    public String realmGet$fieldStringNotNull() {\n        proxyState.getRealm$realm().checkIfValid();\n        return (java.lang.String) proxyState.getRow$realm().getString(columnInfo.fieldStringNotNullColKey);\n    }\n\n    @Override\n    public void realmSet$fieldStringNotNull(String value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            final Row row = proxyState.getRow$realm();\n            if (value == null) {\n                throw new IllegalArgumentException(\"Trying to set non-nullable field 'fieldStringNotNull' to null.\");\n            }\n            row.getTable().setString(columnInfo.fieldStringNotNullColKey, row.getObjectKey(), value, true);\n            return;\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        if (value == null) {\n            throw new IllegalArgumentException(\"Trying to set non-nullable field 'fieldStringNotNull' to null.\");\n        }\n        proxyState.getRow$realm().setString(columnInfo.fieldStringNotNullColKey, value);\n    }\n\n    @Override\n    @SuppressWarnings(\"cast\")\n    public String realmGet$fieldStringNull() {\n        proxyState.getRealm$realm().checkIfValid();\n        return (java.lang.String) proxyState.getRow$realm().getString(columnInfo.fieldStringNullColKey);\n    }\n\n    @Override\n    public void realmSet$fieldStringNull(String value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            final Row row = proxyState.getRow$realm();\n            if (value == null) {\n                row.getTable().setNull(columnInfo.fieldStringNullColKey, row.getObjectKey(), true);\n                return;\n            }\n            row.getTable().setString(columnInfo.fieldStringNullColKey, row.getObjectKey(), value, true);\n            return;\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        if (value == null) {\n            proxyState.getRow$realm().setNull(columnInfo.fieldStringNullColKey);\n            return;\n        }\n        proxyState.getRow$realm().setString(columnInfo.fieldStringNullColKey, value);\n    }\n\n    @Override\n    @SuppressWarnings(\"cast\")\n    public Boolean realmGet$fieldBooleanNotNull() {\n        proxyState.getRealm$realm().checkIfValid();\n        return (boolean) proxyState.getRow$realm().getBoolean(columnInfo.fieldBooleanNotNullColKey);\n    }\n\n    @Override\n    public void realmSet$fieldBooleanNotNull(Boolean value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            final Row row = proxyState.getRow$realm();\n            if (value == null) {\n                throw new IllegalArgumentException(\"Trying to set non-nullable field 'fieldBooleanNotNull' to null.\");\n            }\n            row.getTable().setBoolean(columnInfo.fieldBooleanNotNullColKey, row.getObjectKey(), value, true);\n            return;\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        if (value == null) {\n            throw new IllegalArgumentException(\"Trying to set non-nullable field 'fieldBooleanNotNull' to null.\");\n        }\n        proxyState.getRow$realm().setBoolean(columnInfo.fieldBooleanNotNullColKey, value);\n    }\n\n    @Override\n    @SuppressWarnings(\"cast\")\n    public Boolean realmGet$fieldBooleanNull() {\n        proxyState.getRealm$realm().checkIfValid();\n        if (proxyState.getRow$realm().isNull(columnInfo.fieldBooleanNullColKey)) {\n            return null;\n        }\n        return (boolean) proxyState.getRow$realm().getBoolean(columnInfo.fieldBooleanNullColKey);\n    }\n\n    @Override\n    public void realmSet$fieldBooleanNull(Boolean value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            final Row row = proxyState.getRow$realm();\n            if (value == null) {\n                row.getTable().setNull(columnInfo.fieldBooleanNullColKey, row.getObjectKey(), true);\n                return;\n            }\n            row.getTable().setBoolean(columnInfo.fieldBooleanNullColKey, row.getObjectKey(), value, true);\n            return;\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        if (value == null) {\n            proxyState.getRow$realm().setNull(columnInfo.fieldBooleanNullColKey);\n            return;\n        }\n        proxyState.getRow$realm().setBoolean(columnInfo.fieldBooleanNullColKey, value);\n    }\n\n    @Override\n    @SuppressWarnings(\"cast\")\n    public byte[] realmGet$fieldBytesNotNull() {\n        proxyState.getRealm$realm().checkIfValid();\n        return (byte[]) proxyState.getRow$realm().getBinaryByteArray(columnInfo.fieldBytesNotNullColKey);\n    }\n\n    @Override\n    public void realmSet$fieldBytesNotNull(byte[] value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            final Row row = proxyState.getRow$realm();\n            if (value == null) {\n                throw new IllegalArgumentException(\"Trying to set non-nullable field 'fieldBytesNotNull' to null.\");\n            }\n            row.getTable().setBinaryByteArray(columnInfo.fieldBytesNotNullColKey, row.getObjectKey(), value, true);\n            return;\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        if (value == null) {\n            throw new IllegalArgumentException(\"Trying to set non-nullable field 'fieldBytesNotNull' to null.\");\n        }\n        proxyState.getRow$realm().setBinaryByteArray(columnInfo.fieldBytesNotNullColKey, value);\n    }\n\n    @Override\n    @SuppressWarnings(\"cast\")\n    public byte[] realmGet$fieldBytesNull() {\n        proxyState.getRealm$realm().checkIfValid();\n        return (byte[]) proxyState.getRow$realm().getBinaryByteArray(columnInfo.fieldBytesNullColKey);\n    }\n\n    @Override\n    public void realmSet$fieldBytesNull(byte[] value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            final Row row = proxyState.getRow$realm();\n            if (value == null) {\n                row.getTable().setNull(columnInfo.fieldBytesNullColKey, row.getObjectKey(), true);\n                return;\n            }\n            row.getTable().setBinaryByteArray(columnInfo.fieldBytesNullColKey, row.getObjectKey(), value, true);\n            return;\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        if (value == null) {\n            proxyState.getRow$realm().setNull(columnInfo.fieldBytesNullColKey);\n            return;\n        }\n        proxyState.getRow$realm().setBinaryByteArray(columnInfo.fieldBytesNullColKey, value);\n    }\n\n    @Override\n    @SuppressWarnings(\"cast\")\n    public Byte realmGet$fieldByteNotNull() {\n        proxyState.getRealm$realm().checkIfValid();\n        return (byte) proxyState.getRow$realm().getLong(columnInfo.fieldByteNotNullColKey);\n    }\n\n    @Override\n    public void realmSet$fieldByteNotNull(Byte value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            final Row row = proxyState.getRow$realm();\n            if (value == null) {\n                throw new IllegalArgumentException(\"Trying to set non-nullable field 'fieldByteNotNull' to null.\");\n            }\n            row.getTable().setLong(columnInfo.fieldByteNotNullColKey, row.getObjectKey(), value, true);\n            return;\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        if (value == null) {\n            throw new IllegalArgumentException(\"Trying to set non-nullable field 'fieldByteNotNull' to null.\");\n        }\n        proxyState.getRow$realm().setLong(columnInfo.fieldByteNotNullColKey, value);\n    }\n\n    @Override\n    @SuppressWarnings(\"cast\")\n    public Byte realmGet$fieldByteNull() {\n        proxyState.getRealm$realm().checkIfValid();\n        if (proxyState.getRow$realm().isNull(columnInfo.fieldByteNullColKey)) {\n            return null;\n        }\n        return (byte) proxyState.getRow$realm().getLong(columnInfo.fieldByteNullColKey);\n    }\n\n    @Override\n    public void realmSet$fieldByteNull(Byte value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            final Row row = proxyState.getRow$realm();\n            if (value == null) {\n                row.getTable().setNull(columnInfo.fieldByteNullColKey, row.getObjectKey(), true);\n                return;\n            }\n            row.getTable().setLong(columnInfo.fieldByteNullColKey, row.getObjectKey(), value, true);\n            return;\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        if (value == null) {\n            proxyState.getRow$realm().setNull(columnInfo.fieldByteNullColKey);\n            return;\n        }\n        proxyState.getRow$realm().setLong(columnInfo.fieldByteNullColKey, value);\n    }\n\n    @Override\n    @SuppressWarnings(\"cast\")\n    public Short realmGet$fieldShortNotNull() {\n        proxyState.getRealm$realm().checkIfValid();\n        return (short) proxyState.getRow$realm().getLong(columnInfo.fieldShortNotNullColKey);\n    }\n\n    @Override\n    public void realmSet$fieldShortNotNull(Short value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            final Row row = proxyState.getRow$realm();\n            if (value == null) {\n                throw new IllegalArgumentException(\"Trying to set non-nullable field 'fieldShortNotNull' to null.\");\n            }\n            row.getTable().setLong(columnInfo.fieldShortNotNullColKey, row.getObjectKey(), value, true);\n            return;\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        if (value == null) {\n            throw new IllegalArgumentException(\"Trying to set non-nullable field 'fieldShortNotNull' to null.\");\n        }\n        proxyState.getRow$realm().setLong(columnInfo.fieldShortNotNullColKey, value);\n    }\n\n    @Override\n    @SuppressWarnings(\"cast\")\n    public Short realmGet$fieldShortNull() {\n        proxyState.getRealm$realm().checkIfValid();\n        if (proxyState.getRow$realm().isNull(columnInfo.fieldShortNullColKey)) {\n            return null;\n        }\n        return (short) proxyState.getRow$realm().getLong(columnInfo.fieldShortNullColKey);\n    }\n\n    @Override\n    public void realmSet$fieldShortNull(Short value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            final Row row = proxyState.getRow$realm();\n            if (value == null) {\n                row.getTable().setNull(columnInfo.fieldShortNullColKey, row.getObjectKey(), true);\n                return;\n            }\n            row.getTable().setLong(columnInfo.fieldShortNullColKey, row.getObjectKey(), value, true);\n            return;\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        if (value == null) {\n            proxyState.getRow$realm().setNull(columnInfo.fieldShortNullColKey);\n            return;\n        }\n        proxyState.getRow$realm().setLong(columnInfo.fieldShortNullColKey, value);\n    }\n\n    @Override\n    @SuppressWarnings(\"cast\")\n    public Integer realmGet$fieldIntegerNotNull() {\n        proxyState.getRealm$realm().checkIfValid();\n        return (int) proxyState.getRow$realm().getLong(columnInfo.fieldIntegerNotNullColKey);\n    }\n\n    @Override\n    public void realmSet$fieldIntegerNotNull(Integer value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            final Row row = proxyState.getRow$realm();\n            if (value == null) {\n                throw new IllegalArgumentException(\"Trying to set non-nullable field 'fieldIntegerNotNull' to null.\");\n            }\n            row.getTable().setLong(columnInfo.fieldIntegerNotNullColKey, row.getObjectKey(), value, true);\n            return;\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        if (value == null) {\n            throw new IllegalArgumentException(\"Trying to set non-nullable field 'fieldIntegerNotNull' to null.\");\n        }\n        proxyState.getRow$realm().setLong(columnInfo.fieldIntegerNotNullColKey, value);\n    }\n\n    @Override\n    @SuppressWarnings(\"cast\")\n    public Integer realmGet$fieldIntegerNull() {\n        proxyState.getRealm$realm().checkIfValid();\n        if (proxyState.getRow$realm().isNull(columnInfo.fieldIntegerNullColKey)) {\n            return null;\n        }\n        return (int) proxyState.getRow$realm().getLong(columnInfo.fieldIntegerNullColKey);\n    }\n\n    @Override\n    public void realmSet$fieldIntegerNull(Integer value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            final Row row = proxyState.getRow$realm();\n            if (value == null) {\n                row.getTable().setNull(columnInfo.fieldIntegerNullColKey, row.getObjectKey(), true);\n                return;\n            }\n            row.getTable().setLong(columnInfo.fieldIntegerNullColKey, row.getObjectKey(), value, true);\n            return;\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        if (value == null) {\n            proxyState.getRow$realm().setNull(columnInfo.fieldIntegerNullColKey);\n            return;\n        }\n        proxyState.getRow$realm().setLong(columnInfo.fieldIntegerNullColKey, value);\n    }\n\n    @Override\n    @SuppressWarnings(\"cast\")\n    public Long realmGet$fieldLongNotNull() {\n        proxyState.getRealm$realm().checkIfValid();\n        return (long) proxyState.getRow$realm().getLong(columnInfo.fieldLongNotNullColKey);\n    }\n\n    @Override\n    public void realmSet$fieldLongNotNull(Long value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            final Row row = proxyState.getRow$realm();\n            if (value == null) {\n                throw new IllegalArgumentException(\"Trying to set non-nullable field 'fieldLongNotNull' to null.\");\n            }\n            row.getTable().setLong(columnInfo.fieldLongNotNullColKey, row.getObjectKey(), value, true);\n            return;\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        if (value == null) {\n            throw new IllegalArgumentException(\"Trying to set non-nullable field 'fieldLongNotNull' to null.\");\n        }\n        proxyState.getRow$realm().setLong(columnInfo.fieldLongNotNullColKey, value);\n    }\n\n    @Override\n    @SuppressWarnings(\"cast\")\n    public Long realmGet$fieldLongNull() {\n        proxyState.getRealm$realm().checkIfValid();\n        if (proxyState.getRow$realm().isNull(columnInfo.fieldLongNullColKey)) {\n            return null;\n        }\n        return (long) proxyState.getRow$realm().getLong(columnInfo.fieldLongNullColKey);\n    }\n\n    @Override\n    public void realmSet$fieldLongNull(Long value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            final Row row = proxyState.getRow$realm();\n            if (value == null) {\n                row.getTable().setNull(columnInfo.fieldLongNullColKey, row.getObjectKey(), true);\n                return;\n            }\n            row.getTable().setLong(columnInfo.fieldLongNullColKey, row.getObjectKey(), value, true);\n            return;\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        if (value == null) {\n            proxyState.getRow$realm().setNull(columnInfo.fieldLongNullColKey);\n            return;\n        }\n        proxyState.getRow$realm().setLong(columnInfo.fieldLongNullColKey, value);\n    }\n\n    @Override\n    @SuppressWarnings(\"cast\")\n    public Float realmGet$fieldFloatNotNull() {\n        proxyState.getRealm$realm().checkIfValid();\n        return (float) proxyState.getRow$realm().getFloat(columnInfo.fieldFloatNotNullColKey);\n    }\n\n    @Override\n    public void realmSet$fieldFloatNotNull(Float value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            final Row row = proxyState.getRow$realm();\n            if (value == null) {\n                throw new IllegalArgumentException(\"Trying to set non-nullable field 'fieldFloatNotNull' to null.\");\n            }\n            row.getTable().setFloat(columnInfo.fieldFloatNotNullColKey, row.getObjectKey(), value, true);\n            return;\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        if (value == null) {\n            throw new IllegalArgumentException(\"Trying to set non-nullable field 'fieldFloatNotNull' to null.\");\n        }\n        proxyState.getRow$realm().setFloat(columnInfo.fieldFloatNotNullColKey, value);\n    }\n\n    @Override\n    @SuppressWarnings(\"cast\")\n    public Float realmGet$fieldFloatNull() {\n        proxyState.getRealm$realm().checkIfValid();\n        if (proxyState.getRow$realm().isNull(columnInfo.fieldFloatNullColKey)) {\n            return null;\n        }\n        return (float) proxyState.getRow$realm().getFloat(columnInfo.fieldFloatNullColKey);\n    }\n\n    @Override\n    public void realmSet$fieldFloatNull(Float value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            final Row row = proxyState.getRow$realm();\n            if (value == null) {\n                row.getTable().setNull(columnInfo.fieldFloatNullColKey, row.getObjectKey(), true);\n                return;\n            }\n            row.getTable().setFloat(columnInfo.fieldFloatNullColKey, row.getObjectKey(), value, true);\n            return;\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        if (value == null) {\n            proxyState.getRow$realm().setNull(columnInfo.fieldFloatNullColKey);\n            return;\n        }\n        proxyState.getRow$realm().setFloat(columnInfo.fieldFloatNullColKey, value);\n    }\n\n    @Override\n    @SuppressWarnings(\"cast\")\n    public Double realmGet$fieldDoubleNotNull() {\n        proxyState.getRealm$realm().checkIfValid();\n        return (double) proxyState.getRow$realm().getDouble(columnInfo.fieldDoubleNotNullColKey);\n    }\n\n    @Override\n    public void realmSet$fieldDoubleNotNull(Double value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            final Row row = proxyState.getRow$realm();\n            if (value == null) {\n                throw new IllegalArgumentException(\"Trying to set non-nullable field 'fieldDoubleNotNull' to null.\");\n            }\n            row.getTable().setDouble(columnInfo.fieldDoubleNotNullColKey, row.getObjectKey(), value, true);\n            return;\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        if (value == null) {\n            throw new IllegalArgumentException(\"Trying to set non-nullable field 'fieldDoubleNotNull' to null.\");\n        }\n        proxyState.getRow$realm().setDouble(columnInfo.fieldDoubleNotNullColKey, value);\n    }\n\n    @Override\n    @SuppressWarnings(\"cast\")\n    public Double realmGet$fieldDoubleNull() {\n        proxyState.getRealm$realm().checkIfValid();\n        if (proxyState.getRow$realm().isNull(columnInfo.fieldDoubleNullColKey)) {\n            return null;\n        }\n        return (double) proxyState.getRow$realm().getDouble(columnInfo.fieldDoubleNullColKey);\n    }\n\n    @Override\n    public void realmSet$fieldDoubleNull(Double value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            final Row row = proxyState.getRow$realm();\n            if (value == null) {\n                row.getTable().setNull(columnInfo.fieldDoubleNullColKey, row.getObjectKey(), true);\n                return;\n            }\n            row.getTable().setDouble(columnInfo.fieldDoubleNullColKey, row.getObjectKey(), value, true);\n            return;\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        if (value == null) {\n            proxyState.getRow$realm().setNull(columnInfo.fieldDoubleNullColKey);\n            return;\n        }\n        proxyState.getRow$realm().setDouble(columnInfo.fieldDoubleNullColKey, value);\n    }\n\n    @Override\n    @SuppressWarnings(\"cast\")\n    public Date realmGet$fieldDateNotNull() {\n        proxyState.getRealm$realm().checkIfValid();\n        return (java.util.Date) proxyState.getRow$realm().getDate(columnInfo.fieldDateNotNullColKey);\n    }\n\n    @Override\n    public void realmSet$fieldDateNotNull(Date value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            final Row row = proxyState.getRow$realm();\n            if (value == null) {\n                throw new IllegalArgumentException(\"Trying to set non-nullable field 'fieldDateNotNull' to null.\");\n            }\n            row.getTable().setDate(columnInfo.fieldDateNotNullColKey, row.getObjectKey(), value, true);\n            return;\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        if (value == null) {\n            throw new IllegalArgumentException(\"Trying to set non-nullable field 'fieldDateNotNull' to null.\");\n        }\n        proxyState.getRow$realm().setDate(columnInfo.fieldDateNotNullColKey, value);\n    }\n\n    @Override\n    @SuppressWarnings(\"cast\")\n    public Date realmGet$fieldDateNull() {\n        proxyState.getRealm$realm().checkIfValid();\n        if (proxyState.getRow$realm().isNull(columnInfo.fieldDateNullColKey)) {\n            return null;\n        }\n        return (java.util.Date) proxyState.getRow$realm().getDate(columnInfo.fieldDateNullColKey);\n    }\n\n    @Override\n    public void realmSet$fieldDateNull(Date value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            final Row row = proxyState.getRow$realm();\n            if (value == null) {\n                row.getTable().setNull(columnInfo.fieldDateNullColKey, row.getObjectKey(), true);\n                return;\n            }\n            row.getTable().setDate(columnInfo.fieldDateNullColKey, row.getObjectKey(), value, true);\n            return;\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        if (value == null) {\n            proxyState.getRow$realm().setNull(columnInfo.fieldDateNullColKey);\n            return;\n        }\n        proxyState.getRow$realm().setDate(columnInfo.fieldDateNullColKey, value);\n    }\n\n    @Override\n    @SuppressWarnings(\"cast\")\n    public org.bson.types.Decimal128 realmGet$fieldDecimal128NotNull() {\n        proxyState.getRealm$realm().checkIfValid();\n        return (org.bson.types.Decimal128) proxyState.getRow$realm().getDecimal128(columnInfo.fieldDecimal128NotNullColKey);\n    }\n\n    @Override\n    public void realmSet$fieldDecimal128NotNull(org.bson.types.Decimal128 value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            final Row row = proxyState.getRow$realm();\n            if (value == null) {\n                throw new IllegalArgumentException(\"Trying to set non-nullable field 'fieldDecimal128NotNull' to null.\");\n            }\n            row.getTable().setDecimal128(columnInfo.fieldDecimal128NotNullColKey, row.getObjectKey(), value, true);\n            return;\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        if (value == null) {\n            throw new IllegalArgumentException(\"Trying to set non-nullable field 'fieldDecimal128NotNull' to null.\");\n        }\n        proxyState.getRow$realm().setDecimal128(columnInfo.fieldDecimal128NotNullColKey, value);\n    }\n\n    @Override\n    @SuppressWarnings(\"cast\")\n    public org.bson.types.Decimal128 realmGet$fieldDecimal128Null() {\n        proxyState.getRealm$realm().checkIfValid();\n        if (proxyState.getRow$realm().isNull(columnInfo.fieldDecimal128NullColKey)) {\n            return null;\n        }\n        return (org.bson.types.Decimal128) proxyState.getRow$realm().getDecimal128(columnInfo.fieldDecimal128NullColKey);\n    }\n\n    @Override\n    public void realmSet$fieldDecimal128Null(org.bson.types.Decimal128 value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            final Row row = proxyState.getRow$realm();\n            if (value == null) {\n                row.getTable().setNull(columnInfo.fieldDecimal128NullColKey, row.getObjectKey(), true);\n                return;\n            }\n            row.getTable().setDecimal128(columnInfo.fieldDecimal128NullColKey, row.getObjectKey(), value, true);\n            return;\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        if (value == null) {\n            proxyState.getRow$realm().setNull(columnInfo.fieldDecimal128NullColKey);\n            return;\n        }\n        proxyState.getRow$realm().setDecimal128(columnInfo.fieldDecimal128NullColKey, value);\n    }\n\n    @Override\n    @SuppressWarnings(\"cast\")\n    public org.bson.types.ObjectId realmGet$fieldObjectIdNotNull() {\n        proxyState.getRealm$realm().checkIfValid();\n        return (org.bson.types.ObjectId) proxyState.getRow$realm().getObjectId(columnInfo.fieldObjectIdNotNullColKey);\n    }\n\n    @Override\n    public void realmSet$fieldObjectIdNotNull(org.bson.types.ObjectId value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            final Row row = proxyState.getRow$realm();\n            if (value == null) {\n                throw new IllegalArgumentException(\"Trying to set non-nullable field 'fieldObjectIdNotNull' to null.\");\n            }\n            row.getTable().setObjectId(columnInfo.fieldObjectIdNotNullColKey, row.getObjectKey(), value, true);\n            return;\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        if (value == null) {\n            throw new IllegalArgumentException(\"Trying to set non-nullable field 'fieldObjectIdNotNull' to null.\");\n        }\n        proxyState.getRow$realm().setObjectId(columnInfo.fieldObjectIdNotNullColKey, value);\n    }\n\n    @Override\n    @SuppressWarnings(\"cast\")\n    public org.bson.types.ObjectId realmGet$fieldObjectIdNull() {\n        proxyState.getRealm$realm().checkIfValid();\n        if (proxyState.getRow$realm().isNull(columnInfo.fieldObjectIdNullColKey)) {\n            return null;\n        }\n        return (org.bson.types.ObjectId) proxyState.getRow$realm().getObjectId(columnInfo.fieldObjectIdNullColKey);\n    }\n\n    @Override\n    public void realmSet$fieldObjectIdNull(org.bson.types.ObjectId value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            final Row row = proxyState.getRow$realm();\n            if (value == null) {\n                row.getTable().setNull(columnInfo.fieldObjectIdNullColKey, row.getObjectKey(), true);\n                return;\n            }\n            row.getTable().setObjectId(columnInfo.fieldObjectIdNullColKey, row.getObjectKey(), value, true);\n            return;\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        if (value == null) {\n            proxyState.getRow$realm().setNull(columnInfo.fieldObjectIdNullColKey);\n            return;\n        }\n        proxyState.getRow$realm().setObjectId(columnInfo.fieldObjectIdNullColKey, value);\n    }\n\n    @Override\n    public some.test.NullTypes realmGet$fieldObjectNull() {\n        proxyState.getRealm$realm().checkIfValid();\n        if (proxyState.getRow$realm().isNullLink(columnInfo.fieldObjectNullColKey)) {\n            return null;\n        }\n        return proxyState.getRealm$realm().get(some.test.NullTypes.class, proxyState.getRow$realm().getLink(columnInfo.fieldObjectNullColKey), false, Collections.<String>emptyList());\n    }\n\n    @Override\n    public void realmSet$fieldObjectNull(some.test.NullTypes value) {\n        Realm realm = (Realm) proxyState.getRealm$realm();\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            if (proxyState.getExcludeFields$realm().contains(\"fieldObjectNull\")) {\n                return;\n            }\n            if (value != null && !RealmObject.isManaged(value)) {\n                value = realm.copyToRealm(value);\n            }\n            final Row row = proxyState.getRow$realm();\n            if (value == null) {\n                // Table#nullifyLink() does not support default value. Just using Row.\n                row.nullifyLink(columnInfo.fieldObjectNullColKey);\n                return;\n            }\n            proxyState.checkValidObject(value);\n            row.getTable().setLink(columnInfo.fieldObjectNullColKey, row.getObjectKey(), ((RealmObjectProxy) value).realmGet$proxyState().getRow$realm().getObjectKey(), true);\n            return;\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        if (value == null) {\n            proxyState.getRow$realm().nullifyLink(columnInfo.fieldObjectNullColKey);\n            return;\n        }\n        proxyState.checkValidObject(value);\n        proxyState.getRow$realm().setLink(columnInfo.fieldObjectNullColKey, ((RealmObjectProxy) value).realmGet$proxyState().getRow$realm().getObjectKey());\n    }\n\n    @Override\n    public RealmList<String> realmGet$fieldStringListNotNull() {\n        proxyState.getRealm$realm().checkIfValid();\n        // use the cached value if available\n        if (fieldStringListNotNullRealmList != null) {\n            return fieldStringListNotNullRealmList;\n        } else {\n            OsList osList = proxyState.getRow$realm().getValueList(columnInfo.fieldStringListNotNullColKey, RealmFieldType.STRING_LIST);\n            fieldStringListNotNullRealmList = new RealmList<java.lang.String>(java.lang.String.class, osList, proxyState.getRealm$realm());\n            return fieldStringListNotNullRealmList;\n        }\n    }\n\n    @Override\n    public void realmSet$fieldStringListNotNull(RealmList<String> value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            if (proxyState.getExcludeFields$realm().contains(\"fieldStringListNotNull\")) {\n                return;\n            }\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        OsList osList = proxyState.getRow$realm().getValueList(columnInfo.fieldStringListNotNullColKey, RealmFieldType.STRING_LIST);\n        osList.removeAll();\n        if (value == null) {\n            return;\n        }\n        for (java.lang.String item : value) {\n            if (item == null) {\n                throw new IllegalArgumentException(\"Storing 'null' into fieldStringListNotNull' is not allowed by the schema.\");\n            } else {\n                osList.addString(item);\n            }\n        }\n    }\n\n    @Override\n    public RealmList<String> realmGet$fieldStringListNull() {\n        proxyState.getRealm$realm().checkIfValid();\n        // use the cached value if available\n        if (fieldStringListNullRealmList != null) {\n            return fieldStringListNullRealmList;\n        } else {\n            OsList osList = proxyState.getRow$realm().getValueList(columnInfo.fieldStringListNullColKey, RealmFieldType.STRING_LIST);\n            fieldStringListNullRealmList = new RealmList<java.lang.String>(java.lang.String.class, osList, proxyState.getRealm$realm());\n            return fieldStringListNullRealmList;\n        }\n    }\n\n    @Override\n    public void realmSet$fieldStringListNull(RealmList<String> value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            if (proxyState.getExcludeFields$realm().contains(\"fieldStringListNull\")) {\n                return;\n            }\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        OsList osList = proxyState.getRow$realm().getValueList(columnInfo.fieldStringListNullColKey, RealmFieldType.STRING_LIST);\n        osList.removeAll();\n        if (value == null) {\n            return;\n        }\n        for (java.lang.String item : value) {\n            if (item == null) {\n                osList.addNull();\n            } else {\n                osList.addString(item);\n            }\n        }\n    }\n\n    @Override\n    public RealmList<byte[]> realmGet$fieldBinaryListNotNull() {\n        proxyState.getRealm$realm().checkIfValid();\n        // use the cached value if available\n        if (fieldBinaryListNotNullRealmList != null) {\n            return fieldBinaryListNotNullRealmList;\n        } else {\n            OsList osList = proxyState.getRow$realm().getValueList(columnInfo.fieldBinaryListNotNullColKey, RealmFieldType.BINARY_LIST);\n            fieldBinaryListNotNullRealmList = new RealmList<byte[]>(byte[].class, osList, proxyState.getRealm$realm());\n            return fieldBinaryListNotNullRealmList;\n        }\n    }\n\n    @Override\n    public void realmSet$fieldBinaryListNotNull(RealmList<byte[]> value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            if (proxyState.getExcludeFields$realm().contains(\"fieldBinaryListNotNull\")) {\n                return;\n            }\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        OsList osList = proxyState.getRow$realm().getValueList(columnInfo.fieldBinaryListNotNullColKey, RealmFieldType.BINARY_LIST);\n        osList.removeAll();\n        if (value == null) {\n            return;\n        }\n        for (byte[] item : value) {\n            if (item == null) {\n                throw new IllegalArgumentException(\"Storing 'null' into fieldBinaryListNotNull' is not allowed by the schema.\");\n            } else {\n                osList.addBinary(item);\n            }\n        }\n    }\n\n    @Override\n    public RealmList<byte[]> realmGet$fieldBinaryListNull() {\n        proxyState.getRealm$realm().checkIfValid();\n        // use the cached value if available\n        if (fieldBinaryListNullRealmList != null) {\n            return fieldBinaryListNullRealmList;\n        } else {\n            OsList osList = proxyState.getRow$realm().getValueList(columnInfo.fieldBinaryListNullColKey, RealmFieldType.BINARY_LIST);\n            fieldBinaryListNullRealmList = new RealmList<byte[]>(byte[].class, osList, proxyState.getRealm$realm());\n            return fieldBinaryListNullRealmList;\n        }\n    }\n\n    @Override\n    public void realmSet$fieldBinaryListNull(RealmList<byte[]> value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            if (proxyState.getExcludeFields$realm().contains(\"fieldBinaryListNull\")) {\n                return;\n            }\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        OsList osList = proxyState.getRow$realm().getValueList(columnInfo.fieldBinaryListNullColKey, RealmFieldType.BINARY_LIST);\n        osList.removeAll();\n        if (value == null) {\n            return;\n        }\n        for (byte[] item : value) {\n            if (item == null) {\n                osList.addNull();\n            } else {\n                osList.addBinary(item);\n            }\n        }\n    }\n\n    @Override\n    public RealmList<Boolean> realmGet$fieldBooleanListNotNull() {\n        proxyState.getRealm$realm().checkIfValid();\n        // use the cached value if available\n        if (fieldBooleanListNotNullRealmList != null) {\n            return fieldBooleanListNotNullRealmList;\n        } else {\n            OsList osList = proxyState.getRow$realm().getValueList(columnInfo.fieldBooleanListNotNullColKey, RealmFieldType.BOOLEAN_LIST);\n            fieldBooleanListNotNullRealmList = new RealmList<java.lang.Boolean>(java.lang.Boolean.class, osList, proxyState.getRealm$realm());\n            return fieldBooleanListNotNullRealmList;\n        }\n    }\n\n    @Override\n    public void realmSet$fieldBooleanListNotNull(RealmList<Boolean> value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            if (proxyState.getExcludeFields$realm().contains(\"fieldBooleanListNotNull\")) {\n                return;\n            }\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        OsList osList = proxyState.getRow$realm().getValueList(columnInfo.fieldBooleanListNotNullColKey, RealmFieldType.BOOLEAN_LIST);\n        osList.removeAll();\n        if (value == null) {\n            return;\n        }\n        for (java.lang.Boolean item : value) {\n            if (item == null) {\n                throw new IllegalArgumentException(\"Storing 'null' into fieldBooleanListNotNull' is not allowed by the schema.\");\n            } else {\n                osList.addBoolean(item);\n            }\n        }\n    }\n\n    @Override\n    public RealmList<Boolean> realmGet$fieldBooleanListNull() {\n        proxyState.getRealm$realm().checkIfValid();\n        // use the cached value if available\n        if (fieldBooleanListNullRealmList != null) {\n            return fieldBooleanListNullRealmList;\n        } else {\n            OsList osList = proxyState.getRow$realm().getValueList(columnInfo.fieldBooleanListNullColKey, RealmFieldType.BOOLEAN_LIST);\n            fieldBooleanListNullRealmList = new RealmList<java.lang.Boolean>(java.lang.Boolean.class, osList, proxyState.getRealm$realm());\n            return fieldBooleanListNullRealmList;\n        }\n    }\n\n    @Override\n    public void realmSet$fieldBooleanListNull(RealmList<Boolean> value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            if (proxyState.getExcludeFields$realm().contains(\"fieldBooleanListNull\")) {\n                return;\n            }\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        OsList osList = proxyState.getRow$realm().getValueList(columnInfo.fieldBooleanListNullColKey, RealmFieldType.BOOLEAN_LIST);\n        osList.removeAll();\n        if (value == null) {\n            return;\n        }\n        for (java.lang.Boolean item : value) {\n            if (item == null) {\n                osList.addNull();\n            } else {\n                osList.addBoolean(item);\n            }\n        }\n    }\n\n    @Override\n    public RealmList<Long> realmGet$fieldLongListNotNull() {\n        proxyState.getRealm$realm().checkIfValid();\n        // use the cached value if available\n        if (fieldLongListNotNullRealmList != null) {\n            return fieldLongListNotNullRealmList;\n        } else {\n            OsList osList = proxyState.getRow$realm().getValueList(columnInfo.fieldLongListNotNullColKey, RealmFieldType.INTEGER_LIST);\n            fieldLongListNotNullRealmList = new RealmList<java.lang.Long>(java.lang.Long.class, osList, proxyState.getRealm$realm());\n            return fieldLongListNotNullRealmList;\n        }\n    }\n\n    @Override\n    public void realmSet$fieldLongListNotNull(RealmList<Long> value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            if (proxyState.getExcludeFields$realm().contains(\"fieldLongListNotNull\")) {\n                return;\n            }\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        OsList osList = proxyState.getRow$realm().getValueList(columnInfo.fieldLongListNotNullColKey, RealmFieldType.INTEGER_LIST);\n        osList.removeAll();\n        if (value == null) {\n            return;\n        }\n        for (java.lang.Long item : value) {\n            if (item == null) {\n                throw new IllegalArgumentException(\"Storing 'null' into fieldLongListNotNull' is not allowed by the schema.\");\n            } else {\n                osList.addLong(item.longValue());\n            }\n        }\n    }\n\n    @Override\n    public RealmList<Long> realmGet$fieldLongListNull() {\n        proxyState.getRealm$realm().checkIfValid();\n        // use the cached value if available\n        if (fieldLongListNullRealmList != null) {\n            return fieldLongListNullRealmList;\n        } else {\n            OsList osList = proxyState.getRow$realm().getValueList(columnInfo.fieldLongListNullColKey, RealmFieldType.INTEGER_LIST);\n            fieldLongListNullRealmList = new RealmList<java.lang.Long>(java.lang.Long.class, osList, proxyState.getRealm$realm());\n            return fieldLongListNullRealmList;\n        }\n    }\n\n    @Override\n    public void realmSet$fieldLongListNull(RealmList<Long> value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            if (proxyState.getExcludeFields$realm().contains(\"fieldLongListNull\")) {\n                return;\n            }\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        OsList osList = proxyState.getRow$realm().getValueList(columnInfo.fieldLongListNullColKey, RealmFieldType.INTEGER_LIST);\n        osList.removeAll();\n        if (value == null) {\n            return;\n        }\n        for (java.lang.Long item : value) {\n            if (item == null) {\n                osList.addNull();\n            } else {\n                osList.addLong(item.longValue());\n            }\n        }\n    }\n\n    @Override\n    public RealmList<Integer> realmGet$fieldIntegerListNotNull() {\n        proxyState.getRealm$realm().checkIfValid();\n        // use the cached value if available\n        if (fieldIntegerListNotNullRealmList != null) {\n            return fieldIntegerListNotNullRealmList;\n        } else {\n            OsList osList = proxyState.getRow$realm().getValueList(columnInfo.fieldIntegerListNotNullColKey, RealmFieldType.INTEGER_LIST);\n            fieldIntegerListNotNullRealmList = new RealmList<java.lang.Integer>(java.lang.Integer.class, osList, proxyState.getRealm$realm());\n            return fieldIntegerListNotNullRealmList;\n        }\n    }\n\n    @Override\n    public void realmSet$fieldIntegerListNotNull(RealmList<Integer> value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            if (proxyState.getExcludeFields$realm().contains(\"fieldIntegerListNotNull\")) {\n                return;\n            }\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        OsList osList = proxyState.getRow$realm().getValueList(columnInfo.fieldIntegerListNotNullColKey, RealmFieldType.INTEGER_LIST);\n        osList.removeAll();\n        if (value == null) {\n            return;\n        }\n        for (java.lang.Integer item : value) {\n            if (item == null) {\n                throw new IllegalArgumentException(\"Storing 'null' into fieldIntegerListNotNull' is not allowed by the schema.\");\n            } else {\n                osList.addLong(item.longValue());\n            }\n        }\n    }\n\n    @Override\n    public RealmList<Integer> realmGet$fieldIntegerListNull() {\n        proxyState.getRealm$realm().checkIfValid();\n        // use the cached value if available\n        if (fieldIntegerListNullRealmList != null) {\n            return fieldIntegerListNullRealmList;\n        } else {\n            OsList osList = proxyState.getRow$realm().getValueList(columnInfo.fieldIntegerListNullColKey, RealmFieldType.INTEGER_LIST);\n            fieldIntegerListNullRealmList = new RealmList<java.lang.Integer>(java.lang.Integer.class, osList, proxyState.getRealm$realm());\n            return fieldIntegerListNullRealmList;\n        }\n    }\n\n    @Override\n    public void realmSet$fieldIntegerListNull(RealmList<Integer> value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            if (proxyState.getExcludeFields$realm().contains(\"fieldIntegerListNull\")) {\n                return;\n            }\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        OsList osList = proxyState.getRow$realm().getValueList(columnInfo.fieldIntegerListNullColKey, RealmFieldType.INTEGER_LIST);\n        osList.removeAll();\n        if (value == null) {\n            return;\n        }\n        for (java.lang.Integer item : value) {\n            if (item == null) {\n                osList.addNull();\n            } else {\n                osList.addLong(item.longValue());\n            }\n        }\n    }\n\n    @Override\n    public RealmList<Short> realmGet$fieldShortListNotNull() {\n        proxyState.getRealm$realm().checkIfValid();\n        // use the cached value if available\n        if (fieldShortListNotNullRealmList != null) {\n            return fieldShortListNotNullRealmList;\n        } else {\n            OsList osList = proxyState.getRow$realm().getValueList(columnInfo.fieldShortListNotNullColKey, RealmFieldType.INTEGER_LIST);\n            fieldShortListNotNullRealmList = new RealmList<java.lang.Short>(java.lang.Short.class, osList, proxyState.getRealm$realm());\n            return fieldShortListNotNullRealmList;\n        }\n    }\n\n    @Override\n    public void realmSet$fieldShortListNotNull(RealmList<Short> value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            if (proxyState.getExcludeFields$realm().contains(\"fieldShortListNotNull\")) {\n                return;\n            }\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        OsList osList = proxyState.getRow$realm().getValueList(columnInfo.fieldShortListNotNullColKey, RealmFieldType.INTEGER_LIST);\n        osList.removeAll();\n        if (value == null) {\n            return;\n        }\n        for (java.lang.Short item : value) {\n            if (item == null) {\n                throw new IllegalArgumentException(\"Storing 'null' into fieldShortListNotNull' is not allowed by the schema.\");\n            } else {\n                osList.addLong(item.longValue());\n            }\n        }\n    }\n\n    @Override\n    public RealmList<Short> realmGet$fieldShortListNull() {\n        proxyState.getRealm$realm().checkIfValid();\n        // use the cached value if available\n        if (fieldShortListNullRealmList != null) {\n            return fieldShortListNullRealmList;\n        } else {\n            OsList osList = proxyState.getRow$realm().getValueList(columnInfo.fieldShortListNullColKey, RealmFieldType.INTEGER_LIST);\n            fieldShortListNullRealmList = new RealmList<java.lang.Short>(java.lang.Short.class, osList, proxyState.getRealm$realm());\n            return fieldShortListNullRealmList;\n        }\n    }\n\n    @Override\n    public void realmSet$fieldShortListNull(RealmList<Short> value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            if (proxyState.getExcludeFields$realm().contains(\"fieldShortListNull\")) {\n                return;\n            }\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        OsList osList = proxyState.getRow$realm().getValueList(columnInfo.fieldShortListNullColKey, RealmFieldType.INTEGER_LIST);\n        osList.removeAll();\n        if (value == null) {\n            return;\n        }\n        for (java.lang.Short item : value) {\n            if (item == null) {\n                osList.addNull();\n            } else {\n                osList.addLong(item.longValue());\n            }\n        }\n    }\n\n    @Override\n    public RealmList<Byte> realmGet$fieldByteListNotNull() {\n        proxyState.getRealm$realm().checkIfValid();\n        // use the cached value if available\n        if (fieldByteListNotNullRealmList != null) {\n            return fieldByteListNotNullRealmList;\n        } else {\n            OsList osList = proxyState.getRow$realm().getValueList(columnInfo.fieldByteListNotNullColKey, RealmFieldType.INTEGER_LIST);\n            fieldByteListNotNullRealmList = new RealmList<java.lang.Byte>(java.lang.Byte.class, osList, proxyState.getRealm$realm());\n            return fieldByteListNotNullRealmList;\n        }\n    }\n\n    @Override\n    public void realmSet$fieldByteListNotNull(RealmList<Byte> value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            if (proxyState.getExcludeFields$realm().contains(\"fieldByteListNotNull\")) {\n                return;\n            }\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        OsList osList = proxyState.getRow$realm().getValueList(columnInfo.fieldByteListNotNullColKey, RealmFieldType.INTEGER_LIST);\n        osList.removeAll();\n        if (value == null) {\n            return;\n        }\n        for (java.lang.Byte item : value) {\n            if (item == null) {\n                throw new IllegalArgumentException(\"Storing 'null' into fieldByteListNotNull' is not allowed by the schema.\");\n            } else {\n                osList.addLong(item.longValue());\n            }\n        }\n    }\n\n    @Override\n    public RealmList<Byte> realmGet$fieldByteListNull() {\n        proxyState.getRealm$realm().checkIfValid();\n        // use the cached value if available\n        if (fieldByteListNullRealmList != null) {\n            return fieldByteListNullRealmList;\n        } else {\n            OsList osList = proxyState.getRow$realm().getValueList(columnInfo.fieldByteListNullColKey, RealmFieldType.INTEGER_LIST);\n            fieldByteListNullRealmList = new RealmList<java.lang.Byte>(java.lang.Byte.class, osList, proxyState.getRealm$realm());\n            return fieldByteListNullRealmList;\n        }\n    }\n\n    @Override\n    public void realmSet$fieldByteListNull(RealmList<Byte> value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            if (proxyState.getExcludeFields$realm().contains(\"fieldByteListNull\")) {\n                return;\n            }\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        OsList osList = proxyState.getRow$realm().getValueList(columnInfo.fieldByteListNullColKey, RealmFieldType.INTEGER_LIST);\n        osList.removeAll();\n        if (value == null) {\n            return;\n        }\n        for (java.lang.Byte item : value) {\n            if (item == null) {\n                osList.addNull();\n            } else {\n                osList.addLong(item.longValue());\n            }\n        }\n    }\n\n    @Override\n    public RealmList<Double> realmGet$fieldDoubleListNotNull() {\n        proxyState.getRealm$realm().checkIfValid();\n        // use the cached value if available\n        if (fieldDoubleListNotNullRealmList != null) {\n            return fieldDoubleListNotNullRealmList;\n        } else {\n            OsList osList = proxyState.getRow$realm().getValueList(columnInfo.fieldDoubleListNotNullColKey, RealmFieldType.DOUBLE_LIST);\n            fieldDoubleListNotNullRealmList = new RealmList<java.lang.Double>(java.lang.Double.class, osList, proxyState.getRealm$realm());\n            return fieldDoubleListNotNullRealmList;\n        }\n    }\n\n    @Override\n    public void realmSet$fieldDoubleListNotNull(RealmList<Double> value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            if (proxyState.getExcludeFields$realm().contains(\"fieldDoubleListNotNull\")) {\n                return;\n            }\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        OsList osList = proxyState.getRow$realm().getValueList(columnInfo.fieldDoubleListNotNullColKey, RealmFieldType.DOUBLE_LIST);\n        osList.removeAll();\n        if (value == null) {\n            return;\n        }\n        for (java.lang.Double item : value) {\n            if (item == null) {\n                throw new IllegalArgumentException(\"Storing 'null' into fieldDoubleListNotNull' is not allowed by the schema.\");\n            } else {\n                osList.addDouble(item.doubleValue());\n            }\n        }\n    }\n\n    @Override\n    public RealmList<Double> realmGet$fieldDoubleListNull() {\n        proxyState.getRealm$realm().checkIfValid();\n        // use the cached value if available\n        if (fieldDoubleListNullRealmList != null) {\n            return fieldDoubleListNullRealmList;\n        } else {\n            OsList osList = proxyState.getRow$realm().getValueList(columnInfo.fieldDoubleListNullColKey, RealmFieldType.DOUBLE_LIST);\n            fieldDoubleListNullRealmList = new RealmList<java.lang.Double>(java.lang.Double.class, osList, proxyState.getRealm$realm());\n            return fieldDoubleListNullRealmList;\n        }\n    }\n\n    @Override\n    public void realmSet$fieldDoubleListNull(RealmList<Double> value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            if (proxyState.getExcludeFields$realm().contains(\"fieldDoubleListNull\")) {\n                return;\n            }\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        OsList osList = proxyState.getRow$realm().getValueList(columnInfo.fieldDoubleListNullColKey, RealmFieldType.DOUBLE_LIST);\n        osList.removeAll();\n        if (value == null) {\n            return;\n        }\n        for (java.lang.Double item : value) {\n            if (item == null) {\n                osList.addNull();\n            } else {\n                osList.addDouble(item.doubleValue());\n            }\n        }\n    }\n\n    @Override\n    public RealmList<Float> realmGet$fieldFloatListNotNull() {\n        proxyState.getRealm$realm().checkIfValid();\n        // use the cached value if available\n        if (fieldFloatListNotNullRealmList != null) {\n            return fieldFloatListNotNullRealmList;\n        } else {\n            OsList osList = proxyState.getRow$realm().getValueList(columnInfo.fieldFloatListNotNullColKey, RealmFieldType.FLOAT_LIST);\n            fieldFloatListNotNullRealmList = new RealmList<java.lang.Float>(java.lang.Float.class, osList, proxyState.getRealm$realm());\n            return fieldFloatListNotNullRealmList;\n        }\n    }\n\n    @Override\n    public void realmSet$fieldFloatListNotNull(RealmList<Float> value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            if (proxyState.getExcludeFields$realm().contains(\"fieldFloatListNotNull\")) {\n                return;\n            }\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        OsList osList = proxyState.getRow$realm().getValueList(columnInfo.fieldFloatListNotNullColKey, RealmFieldType.FLOAT_LIST);\n        osList.removeAll();\n        if (value == null) {\n            return;\n        }\n        for (java.lang.Float item : value) {\n            if (item == null) {\n                throw new IllegalArgumentException(\"Storing 'null' into fieldFloatListNotNull' is not allowed by the schema.\");\n            } else {\n                osList.addFloat(item.floatValue());\n            }\n        }\n    }\n\n    @Override\n    public RealmList<Float> realmGet$fieldFloatListNull() {\n        proxyState.getRealm$realm().checkIfValid();\n        // use the cached value if available\n        if (fieldFloatListNullRealmList != null) {\n            return fieldFloatListNullRealmList;\n        } else {\n            OsList osList = proxyState.getRow$realm().getValueList(columnInfo.fieldFloatListNullColKey, RealmFieldType.FLOAT_LIST);\n            fieldFloatListNullRealmList = new RealmList<java.lang.Float>(java.lang.Float.class, osList, proxyState.getRealm$realm());\n            return fieldFloatListNullRealmList;\n        }\n    }\n\n    @Override\n    public void realmSet$fieldFloatListNull(RealmList<Float> value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            if (proxyState.getExcludeFields$realm().contains(\"fieldFloatListNull\")) {\n                return;\n            }\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        OsList osList = proxyState.getRow$realm().getValueList(columnInfo.fieldFloatListNullColKey, RealmFieldType.FLOAT_LIST);\n        osList.removeAll();\n        if (value == null) {\n            return;\n        }\n        for (java.lang.Float item : value) {\n            if (item == null) {\n                osList.addNull();\n            } else {\n                osList.addFloat(item.floatValue());\n            }\n        }\n    }\n\n    @Override\n    public RealmList<Date> realmGet$fieldDateListNotNull() {\n        proxyState.getRealm$realm().checkIfValid();\n        // use the cached value if available\n        if (fieldDateListNotNullRealmList != null) {\n            return fieldDateListNotNullRealmList;\n        } else {\n            OsList osList = proxyState.getRow$realm().getValueList(columnInfo.fieldDateListNotNullColKey, RealmFieldType.DATE_LIST);\n            fieldDateListNotNullRealmList = new RealmList<java.util.Date>(java.util.Date.class, osList, proxyState.getRealm$realm());\n            return fieldDateListNotNullRealmList;\n        }\n    }\n\n    @Override\n    public void realmSet$fieldDateListNotNull(RealmList<Date> value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            if (proxyState.getExcludeFields$realm().contains(\"fieldDateListNotNull\")) {\n                return;\n            }\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        OsList osList = proxyState.getRow$realm().getValueList(columnInfo.fieldDateListNotNullColKey, RealmFieldType.DATE_LIST);\n        osList.removeAll();\n        if (value == null) {\n            return;\n        }\n        for (java.util.Date item : value) {\n            if (item == null) {\n                throw new IllegalArgumentException(\"Storing 'null' into fieldDateListNotNull' is not allowed by the schema.\");\n            } else {\n                osList.addDate(item);\n            }\n        }\n    }\n\n    @Override\n    public RealmList<Date> realmGet$fieldDateListNull() {\n        proxyState.getRealm$realm().checkIfValid();\n        // use the cached value if available\n        if (fieldDateListNullRealmList != null) {\n            return fieldDateListNullRealmList;\n        } else {\n            OsList osList = proxyState.getRow$realm().getValueList(columnInfo.fieldDateListNullColKey, RealmFieldType.DATE_LIST);\n            fieldDateListNullRealmList = new RealmList<java.util.Date>(java.util.Date.class, osList, proxyState.getRealm$realm());\n            return fieldDateListNullRealmList;\n        }\n    }\n\n    @Override\n    public void realmSet$fieldDateListNull(RealmList<Date> value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            if (proxyState.getExcludeFields$realm().contains(\"fieldDateListNull\")) {\n                return;\n            }\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        OsList osList = proxyState.getRow$realm().getValueList(columnInfo.fieldDateListNullColKey, RealmFieldType.DATE_LIST);\n        osList.removeAll();\n        if (value == null) {\n            return;\n        }\n        for (java.util.Date item : value) {\n            if (item == null) {\n                osList.addNull();\n            } else {\n                osList.addDate(item);\n            }\n        }\n    }\n\n    @Override\n    public RealmList<org.bson.types.Decimal128> realmGet$fieldDecimal128ListNotNull() {\n        proxyState.getRealm$realm().checkIfValid();\n        // use the cached value if available\n        if (fieldDecimal128ListNotNullRealmList != null) {\n            return fieldDecimal128ListNotNullRealmList;\n        } else {\n            OsList osList = proxyState.getRow$realm().getValueList(columnInfo.fieldDecimal128ListNotNullColKey, RealmFieldType.DECIMAL128_LIST);\n            fieldDecimal128ListNotNullRealmList = new RealmList<org.bson.types.Decimal128>(org.bson.types.Decimal128.class, osList, proxyState.getRealm$realm());\n            return fieldDecimal128ListNotNullRealmList;\n        }\n    }\n\n    @Override\n    public void realmSet$fieldDecimal128ListNotNull(RealmList<org.bson.types.Decimal128> value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            if (proxyState.getExcludeFields$realm().contains(\"fieldDecimal128ListNotNull\")) {\n                return;\n            }\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        OsList osList = proxyState.getRow$realm().getValueList(columnInfo.fieldDecimal128ListNotNullColKey, RealmFieldType.DECIMAL128_LIST);\n        osList.removeAll();\n        if (value == null) {\n            return;\n        }\n        for (org.bson.types.Decimal128 item : value) {\n            if (item == null) {\n                throw new IllegalArgumentException(\"Storing 'null' into fieldDecimal128ListNotNull' is not allowed by the schema.\");\n            } else {\n                osList.addDecimal128(item);\n            }\n        }\n    }\n\n    @Override\n    public RealmList<org.bson.types.Decimal128> realmGet$fieldDecimal128ListNull() {\n        proxyState.getRealm$realm().checkIfValid();\n        // use the cached value if available\n        if (fieldDecimal128ListNullRealmList != null) {\n            return fieldDecimal128ListNullRealmList;\n        } else {\n            OsList osList = proxyState.getRow$realm().getValueList(columnInfo.fieldDecimal128ListNullColKey, RealmFieldType.DECIMAL128_LIST);\n            fieldDecimal128ListNullRealmList = new RealmList<org.bson.types.Decimal128>(org.bson.types.Decimal128.class, osList, proxyState.getRealm$realm());\n            return fieldDecimal128ListNullRealmList;\n        }\n    }\n\n    @Override\n    public void realmSet$fieldDecimal128ListNull(RealmList<org.bson.types.Decimal128> value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            if (proxyState.getExcludeFields$realm().contains(\"fieldDecimal128ListNull\")) {\n                return;\n            }\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        OsList osList = proxyState.getRow$realm().getValueList(columnInfo.fieldDecimal128ListNullColKey, RealmFieldType.DECIMAL128_LIST);\n        osList.removeAll();\n        if (value == null) {\n            return;\n        }\n        for (org.bson.types.Decimal128 item : value) {\n            if (item == null) {\n                osList.addNull();\n            } else {\n                osList.addDecimal128(item);\n            }\n        }\n    }\n\n    @Override\n    public RealmList<org.bson.types.ObjectId> realmGet$fieldObjectIdListNotNull() {\n        proxyState.getRealm$realm().checkIfValid();\n        // use the cached value if available\n        if (fieldObjectIdListNotNullRealmList != null) {\n            return fieldObjectIdListNotNullRealmList;\n        } else {\n            OsList osList = proxyState.getRow$realm().getValueList(columnInfo.fieldObjectIdListNotNullColKey, RealmFieldType.OBJECT_ID_LIST);\n            fieldObjectIdListNotNullRealmList = new RealmList<org.bson.types.ObjectId>(org.bson.types.ObjectId.class, osList, proxyState.getRealm$realm());\n            return fieldObjectIdListNotNullRealmList;\n        }\n    }\n\n    @Override\n    public void realmSet$fieldObjectIdListNotNull(RealmList<org.bson.types.ObjectId> value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            if (proxyState.getExcludeFields$realm().contains(\"fieldObjectIdListNotNull\")) {\n                return;\n            }\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        OsList osList = proxyState.getRow$realm().getValueList(columnInfo.fieldObjectIdListNotNullColKey, RealmFieldType.OBJECT_ID_LIST);\n        osList.removeAll();\n        if (value == null) {\n            return;\n        }\n        for (org.bson.types.ObjectId item : value) {\n            if (item == null) {\n                throw new IllegalArgumentException(\"Storing 'null' into fieldObjectIdListNotNull' is not allowed by the schema.\");\n            } else {\n                osList.addObjectId(item);\n            }\n        }\n    }\n\n    @Override\n    public RealmList<org.bson.types.ObjectId> realmGet$fieldObjectIdListNull() {\n        proxyState.getRealm$realm().checkIfValid();\n        // use the cached value if available\n        if (fieldObjectIdListNullRealmList != null) {\n            return fieldObjectIdListNullRealmList;\n        } else {\n            OsList osList = proxyState.getRow$realm().getValueList(columnInfo.fieldObjectIdListNullColKey, RealmFieldType.OBJECT_ID_LIST);\n            fieldObjectIdListNullRealmList = new RealmList<org.bson.types.ObjectId>(org.bson.types.ObjectId.class, osList, proxyState.getRealm$realm());\n            return fieldObjectIdListNullRealmList;\n        }\n    }\n\n    @Override\n    public void realmSet$fieldObjectIdListNull(RealmList<org.bson.types.ObjectId> value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            if (proxyState.getExcludeFields$realm().contains(\"fieldObjectIdListNull\")) {\n                return;\n            }\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        OsList osList = proxyState.getRow$realm().getValueList(columnInfo.fieldObjectIdListNullColKey, RealmFieldType.OBJECT_ID_LIST);\n        osList.removeAll();\n        if (value == null) {\n            return;\n        }\n        for (org.bson.types.ObjectId item : value) {\n            if (item == null) {\n                osList.addNull();\n            } else {\n                osList.addObjectId(item);\n            }\n        }\n    }\n\n    private static OsObjectSchemaInfo createExpectedObjectSchemaInfo() {\n        OsObjectSchemaInfo.Builder builder = new OsObjectSchemaInfo.Builder(NO_ALIAS, \"NullTypes\", false, 49, 0);\n        builder.addPersistedProperty(NO_ALIAS, \"fieldStringNotNull\", RealmFieldType.STRING, !Property.PRIMARY_KEY, !Property.INDEXED, Property.REQUIRED);\n        builder.addPersistedProperty(NO_ALIAS, \"fieldStringNull\", RealmFieldType.STRING, !Property.PRIMARY_KEY, !Property.INDEXED, !Property.REQUIRED);\n        builder.addPersistedProperty(NO_ALIAS, \"fieldBooleanNotNull\", RealmFieldType.BOOLEAN, !Property.PRIMARY_KEY, !Property.INDEXED, Property.REQUIRED);\n        builder.addPersistedProperty(NO_ALIAS, \"fieldBooleanNull\", RealmFieldType.BOOLEAN, !Property.PRIMARY_KEY, !Property.INDEXED, !Property.REQUIRED);\n        builder.addPersistedProperty(NO_ALIAS, \"fieldBytesNotNull\", RealmFieldType.BINARY, !Property.PRIMARY_KEY, !Property.INDEXED, Property.REQUIRED);\n        builder.addPersistedProperty(NO_ALIAS, \"fieldBytesNull\", RealmFieldType.BINARY, !Property.PRIMARY_KEY, !Property.INDEXED, !Property.REQUIRED);\n        builder.addPersistedProperty(NO_ALIAS, \"fieldByteNotNull\", RealmFieldType.INTEGER, !Property.PRIMARY_KEY, !Property.INDEXED, Property.REQUIRED);\n        builder.addPersistedProperty(NO_ALIAS, \"fieldByteNull\", RealmFieldType.INTEGER, !Property.PRIMARY_KEY, !Property.INDEXED, !Property.REQUIRED);\n        builder.addPersistedProperty(NO_ALIAS, \"fieldShortNotNull\", RealmFieldType.INTEGER, !Property.PRIMARY_KEY, !Property.INDEXED, Property.REQUIRED);\n        builder.addPersistedProperty(NO_ALIAS, \"fieldShortNull\", RealmFieldType.INTEGER, !Property.PRIMARY_KEY, !Property.INDEXED, !Property.REQUIRED);\n        builder.addPersistedProperty(NO_ALIAS, \"fieldIntegerNotNull\", RealmFieldType.INTEGER, !Property.PRIMARY_KEY, !Property.INDEXED, Property.REQUIRED);\n        builder.addPersistedProperty(NO_ALIAS, \"fieldIntegerNull\", RealmFieldType.INTEGER, !Property.PRIMARY_KEY, !Property.INDEXED, !Property.REQUIRED);\n        builder.addPersistedProperty(NO_ALIAS, \"fieldLongNotNull\", RealmFieldType.INTEGER, !Property.PRIMARY_KEY, !Property.INDEXED, Property.REQUIRED);\n        builder.addPersistedProperty(NO_ALIAS, \"fieldLongNull\", RealmFieldType.INTEGER, !Property.PRIMARY_KEY, !Property.INDEXED, !Property.REQUIRED);\n        builder.addPersistedProperty(NO_ALIAS, \"fieldFloatNotNull\", RealmFieldType.FLOAT, !Property.PRIMARY_KEY, !Property.INDEXED, Property.REQUIRED);\n        builder.addPersistedProperty(NO_ALIAS, \"fieldFloatNull\", RealmFieldType.FLOAT, !Property.PRIMARY_KEY, !Property.INDEXED, !Property.REQUIRED);\n        builder.addPersistedProperty(NO_ALIAS, \"fieldDoubleNotNull\", RealmFieldType.DOUBLE, !Property.PRIMARY_KEY, !Property.INDEXED, Property.REQUIRED);\n        builder.addPersistedProperty(NO_ALIAS, \"fieldDoubleNull\", RealmFieldType.DOUBLE, !Property.PRIMARY_KEY, !Property.INDEXED, !Property.REQUIRED);\n        builder.addPersistedProperty(NO_ALIAS, \"fieldDateNotNull\", RealmFieldType.DATE, !Property.PRIMARY_KEY, !Property.INDEXED, Property.REQUIRED);\n        builder.addPersistedProperty(NO_ALIAS, \"fieldDateNull\", RealmFieldType.DATE, !Property.PRIMARY_KEY, !Property.INDEXED, !Property.REQUIRED);\n        builder.addPersistedProperty(NO_ALIAS, \"fieldDecimal128NotNull\", RealmFieldType.DECIMAL128, !Property.PRIMARY_KEY, !Property.INDEXED, Property.REQUIRED);\n        builder.addPersistedProperty(NO_ALIAS, \"fieldDecimal128Null\", RealmFieldType.DECIMAL128, !Property.PRIMARY_KEY, !Property.INDEXED, !Property.REQUIRED);\n        builder.addPersistedProperty(NO_ALIAS, \"fieldObjectIdNotNull\", RealmFieldType.OBJECT_ID, !Property.PRIMARY_KEY, !Property.INDEXED, Property.REQUIRED);\n        builder.addPersistedProperty(NO_ALIAS, \"fieldObjectIdNull\", RealmFieldType.OBJECT_ID, !Property.PRIMARY_KEY, !Property.INDEXED, !Property.REQUIRED);\n        builder.addPersistedLinkProperty(NO_ALIAS, \"fieldObjectNull\", RealmFieldType.OBJECT, \"NullTypes\");\n        builder.addPersistedValueListProperty(NO_ALIAS, \"fieldStringListNotNull\", RealmFieldType.STRING_LIST, Property.REQUIRED);\n        builder.addPersistedValueListProperty(NO_ALIAS, \"fieldStringListNull\", RealmFieldType.STRING_LIST, !Property.REQUIRED);\n        builder.addPersistedValueListProperty(NO_ALIAS, \"fieldBinaryListNotNull\", RealmFieldType.BINARY_LIST, Property.REQUIRED);\n        builder.addPersistedValueListProperty(NO_ALIAS, \"fieldBinaryListNull\", RealmFieldType.BINARY_LIST, !Property.REQUIRED);\n        builder.addPersistedValueListProperty(NO_ALIAS, \"fieldBooleanListNotNull\", RealmFieldType.BOOLEAN_LIST, Property.REQUIRED);\n        builder.addPersistedValueListProperty(NO_ALIAS, \"fieldBooleanListNull\", RealmFieldType.BOOLEAN_LIST, !Property.REQUIRED);\n        builder.addPersistedValueListProperty(NO_ALIAS, \"fieldLongListNotNull\", RealmFieldType.INTEGER_LIST, Property.REQUIRED);\n        builder.addPersistedValueListProperty(NO_ALIAS, \"fieldLongListNull\", RealmFieldType.INTEGER_LIST, !Property.REQUIRED);\n        builder.addPersistedValueListProperty(NO_ALIAS, \"fieldIntegerListNotNull\", RealmFieldType.INTEGER_LIST, Property.REQUIRED);\n        builder.addPersistedValueListProperty(NO_ALIAS, \"fieldIntegerListNull\", RealmFieldType.INTEGER_LIST, !Property.REQUIRED);\n        builder.addPersistedValueListProperty(NO_ALIAS, \"fieldShortListNotNull\", RealmFieldType.INTEGER_LIST, Property.REQUIRED);\n        builder.addPersistedValueListProperty(NO_ALIAS, \"fieldShortListNull\", RealmFieldType.INTEGER_LIST, !Property.REQUIRED);\n        builder.addPersistedValueListProperty(NO_ALIAS, \"fieldByteListNotNull\", RealmFieldType.INTEGER_LIST, Property.REQUIRED);\n        builder.addPersistedValueListProperty(NO_ALIAS, \"fieldByteListNull\", RealmFieldType.INTEGER_LIST, !Property.REQUIRED);\n        builder.addPersistedValueListProperty(NO_ALIAS, \"fieldDoubleListNotNull\", RealmFieldType.DOUBLE_LIST, Property.REQUIRED);\n        builder.addPersistedValueListProperty(NO_ALIAS, \"fieldDoubleListNull\", RealmFieldType.DOUBLE_LIST, !Property.REQUIRED);\n        builder.addPersistedValueListProperty(NO_ALIAS, \"fieldFloatListNotNull\", RealmFieldType.FLOAT_LIST, Property.REQUIRED);\n        builder.addPersistedValueListProperty(NO_ALIAS, \"fieldFloatListNull\", RealmFieldType.FLOAT_LIST, !Property.REQUIRED);\n        builder.addPersistedValueListProperty(NO_ALIAS, \"fieldDateListNotNull\", RealmFieldType.DATE_LIST, Property.REQUIRED);\n        builder.addPersistedValueListProperty(NO_ALIAS, \"fieldDateListNull\", RealmFieldType.DATE_LIST, !Property.REQUIRED);\n        builder.addPersistedValueListProperty(NO_ALIAS, \"fieldDecimal128ListNotNull\", RealmFieldType.DECIMAL128_LIST, Property.REQUIRED);\n        builder.addPersistedValueListProperty(NO_ALIAS, \"fieldDecimal128ListNull\", RealmFieldType.DECIMAL128_LIST, !Property.REQUIRED);\n        builder.addPersistedValueListProperty(NO_ALIAS, \"fieldObjectIdListNotNull\", RealmFieldType.OBJECT_ID_LIST, Property.REQUIRED);\n        builder.addPersistedValueListProperty(NO_ALIAS, \"fieldObjectIdListNull\", RealmFieldType.OBJECT_ID_LIST, !Property.REQUIRED);\n        return builder.build();\n    }\n\n    public static OsObjectSchemaInfo getExpectedObjectSchemaInfo() {\n        return expectedObjectSchemaInfo;\n    }\n\n    public static NullTypesColumnInfo createColumnInfo(OsSchemaInfo schemaInfo) {\n        return new NullTypesColumnInfo(schemaInfo);\n    }\n\n    public static String getSimpleClassName() {\n        return \"NullTypes\";\n    }\n\n    public static final class ClassNameHelper {\n        public static final String INTERNAL_CLASS_NAME = \"NullTypes\";\n    }\n\n    @SuppressWarnings(\"cast\")\n    public static some.test.NullTypes createOrUpdateUsingJsonObject(Realm realm, JSONObject json, boolean update)\n            throws JSONException {\n        final List<String> excludeFields = new ArrayList<String>(25);\n        if (json.has(\"fieldObjectNull\")) {\n            excludeFields.add(\"fieldObjectNull\");\n        }\n        if (json.has(\"fieldStringListNotNull\")) {\n            excludeFields.add(\"fieldStringListNotNull\");\n        }\n        if (json.has(\"fieldStringListNull\")) {\n            excludeFields.add(\"fieldStringListNull\");\n        }\n        if (json.has(\"fieldBinaryListNotNull\")) {\n            excludeFields.add(\"fieldBinaryListNotNull\");\n        }\n        if (json.has(\"fieldBinaryListNull\")) {\n            excludeFields.add(\"fieldBinaryListNull\");\n        }\n        if (json.has(\"fieldBooleanListNotNull\")) {\n            excludeFields.add(\"fieldBooleanListNotNull\");\n        }\n        if (json.has(\"fieldBooleanListNull\")) {\n            excludeFields.add(\"fieldBooleanListNull\");\n        }\n        if (json.has(\"fieldLongListNotNull\")) {\n            excludeFields.add(\"fieldLongListNotNull\");\n        }\n        if (json.has(\"fieldLongListNull\")) {\n            excludeFields.add(\"fieldLongListNull\");\n        }\n        if (json.has(\"fieldIntegerListNotNull\")) {\n            excludeFields.add(\"fieldIntegerListNotNull\");\n        }\n        if (json.has(\"fieldIntegerListNull\")) {\n            excludeFields.add(\"fieldIntegerListNull\");\n        }\n        if (json.has(\"fieldShortListNotNull\")) {\n            excludeFields.add(\"fieldShortListNotNull\");\n        }\n        if (json.has(\"fieldShortListNull\")) {\n            excludeFields.add(\"fieldShortListNull\");\n        }\n        if (json.has(\"fieldByteListNotNull\")) {\n            excludeFields.add(\"fieldByteListNotNull\");\n        }\n        if (json.has(\"fieldByteListNull\")) {\n            excludeFields.add(\"fieldByteListNull\");\n        }\n        if (json.has(\"fieldDoubleListNotNull\")) {\n            excludeFields.add(\"fieldDoubleListNotNull\");\n        }\n        if (json.has(\"fieldDoubleListNull\")) {\n            excludeFields.add(\"fieldDoubleListNull\");\n        }\n        if (json.has(\"fieldFloatListNotNull\")) {\n            excludeFields.add(\"fieldFloatListNotNull\");\n        }\n        if (json.has(\"fieldFloatListNull\")) {\n            excludeFields.add(\"fieldFloatListNull\");\n        }\n        if (json.has(\"fieldDateListNotNull\")) {\n            excludeFields.add(\"fieldDateListNotNull\");\n        }\n        if (json.has(\"fieldDateListNull\")) {\n            excludeFields.add(\"fieldDateListNull\");\n        }\n        if (json.has(\"fieldDecimal128ListNotNull\")) {\n            excludeFields.add(\"fieldDecimal128ListNotNull\");\n        }\n        if (json.has(\"fieldDecimal128ListNull\")) {\n            excludeFields.add(\"fieldDecimal128ListNull\");\n        }\n        if (json.has(\"fieldObjectIdListNotNull\")) {\n            excludeFields.add(\"fieldObjectIdListNotNull\");\n        }\n        if (json.has(\"fieldObjectIdListNull\")) {\n            excludeFields.add(\"fieldObjectIdListNull\");\n        }\n        some.test.NullTypes obj = realm.createObjectInternal(some.test.NullTypes.class, true, excludeFields);\n\n        final some_test_NullTypesRealmProxyInterface objProxy = (some_test_NullTypesRealmProxyInterface) obj;\n        if (json.has(\"fieldStringNotNull\")) {\n            if (json.isNull(\"fieldStringNotNull\")) {\n                objProxy.realmSet$fieldStringNotNull(null);\n            } else {\n                objProxy.realmSet$fieldStringNotNull((String) json.getString(\"fieldStringNotNull\"));\n            }\n        }\n        if (json.has(\"fieldStringNull\")) {\n            if (json.isNull(\"fieldStringNull\")) {\n                objProxy.realmSet$fieldStringNull(null);\n            } else {\n                objProxy.realmSet$fieldStringNull((String) json.getString(\"fieldStringNull\"));\n            }\n        }\n        if (json.has(\"fieldBooleanNotNull\")) {\n            if (json.isNull(\"fieldBooleanNotNull\")) {\n                objProxy.realmSet$fieldBooleanNotNull(null);\n            } else {\n                objProxy.realmSet$fieldBooleanNotNull((boolean) json.getBoolean(\"fieldBooleanNotNull\"));\n            }\n        }\n        if (json.has(\"fieldBooleanNull\")) {\n            if (json.isNull(\"fieldBooleanNull\")) {\n                objProxy.realmSet$fieldBooleanNull(null);\n            } else {\n                objProxy.realmSet$fieldBooleanNull((boolean) json.getBoolean(\"fieldBooleanNull\"));\n            }\n        }\n        if (json.has(\"fieldBytesNotNull\")) {\n            if (json.isNull(\"fieldBytesNotNull\")) {\n                objProxy.realmSet$fieldBytesNotNull(null);\n            } else {\n                objProxy.realmSet$fieldBytesNotNull(JsonUtils.stringToBytes(json.getString(\"fieldBytesNotNull\")));\n            }\n        }\n        if (json.has(\"fieldBytesNull\")) {\n            if (json.isNull(\"fieldBytesNull\")) {\n                objProxy.realmSet$fieldBytesNull(null);\n            } else {\n                objProxy.realmSet$fieldBytesNull(JsonUtils.stringToBytes(json.getString(\"fieldBytesNull\")));\n            }\n        }\n        if (json.has(\"fieldByteNotNull\")) {\n            if (json.isNull(\"fieldByteNotNull\")) {\n                objProxy.realmSet$fieldByteNotNull(null);\n            } else {\n                objProxy.realmSet$fieldByteNotNull((byte) json.getInt(\"fieldByteNotNull\"));\n            }\n        }\n        if (json.has(\"fieldByteNull\")) {\n            if (json.isNull(\"fieldByteNull\")) {\n                objProxy.realmSet$fieldByteNull(null);\n            } else {\n                objProxy.realmSet$fieldByteNull((byte) json.getInt(\"fieldByteNull\"));\n            }\n        }\n        if (json.has(\"fieldShortNotNull\")) {\n            if (json.isNull(\"fieldShortNotNull\")) {\n                objProxy.realmSet$fieldShortNotNull(null);\n            } else {\n                objProxy.realmSet$fieldShortNotNull((short) json.getInt(\"fieldShortNotNull\"));\n            }\n        }\n        if (json.has(\"fieldShortNull\")) {\n            if (json.isNull(\"fieldShortNull\")) {\n                objProxy.realmSet$fieldShortNull(null);\n            } else {\n                objProxy.realmSet$fieldShortNull((short) json.getInt(\"fieldShortNull\"));\n            }\n        }\n        if (json.has(\"fieldIntegerNotNull\")) {\n            if (json.isNull(\"fieldIntegerNotNull\")) {\n                objProxy.realmSet$fieldIntegerNotNull(null);\n            } else {\n                objProxy.realmSet$fieldIntegerNotNull((int) json.getInt(\"fieldIntegerNotNull\"));\n            }\n        }\n        if (json.has(\"fieldIntegerNull\")) {\n            if (json.isNull(\"fieldIntegerNull\")) {\n                objProxy.realmSet$fieldIntegerNull(null);\n            } else {\n                objProxy.realmSet$fieldIntegerNull((int) json.getInt(\"fieldIntegerNull\"));\n            }\n        }\n        if (json.has(\"fieldLongNotNull\")) {\n            if (json.isNull(\"fieldLongNotNull\")) {\n                objProxy.realmSet$fieldLongNotNull(null);\n            } else {\n                objProxy.realmSet$fieldLongNotNull((long) json.getLong(\"fieldLongNotNull\"));\n            }\n        }\n        if (json.has(\"fieldLongNull\")) {\n            if (json.isNull(\"fieldLongNull\")) {\n                objProxy.realmSet$fieldLongNull(null);\n            } else {\n                objProxy.realmSet$fieldLongNull((long) json.getLong(\"fieldLongNull\"));\n            }\n        }\n        if (json.has(\"fieldFloatNotNull\")) {\n            if (json.isNull(\"fieldFloatNotNull\")) {\n                objProxy.realmSet$fieldFloatNotNull(null);\n            } else {\n                objProxy.realmSet$fieldFloatNotNull((float) json.getDouble(\"fieldFloatNotNull\"));\n            }\n        }\n        if (json.has(\"fieldFloatNull\")) {\n            if (json.isNull(\"fieldFloatNull\")) {\n                objProxy.realmSet$fieldFloatNull(null);\n            } else {\n                objProxy.realmSet$fieldFloatNull((float) json.getDouble(\"fieldFloatNull\"));\n            }\n        }\n        if (json.has(\"fieldDoubleNotNull\")) {\n            if (json.isNull(\"fieldDoubleNotNull\")) {\n                objProxy.realmSet$fieldDoubleNotNull(null);\n            } else {\n                objProxy.realmSet$fieldDoubleNotNull((double) json.getDouble(\"fieldDoubleNotNull\"));\n            }\n        }\n        if (json.has(\"fieldDoubleNull\")) {\n            if (json.isNull(\"fieldDoubleNull\")) {\n                objProxy.realmSet$fieldDoubleNull(null);\n            } else {\n                objProxy.realmSet$fieldDoubleNull((double) json.getDouble(\"fieldDoubleNull\"));\n            }\n        }\n        if (json.has(\"fieldDateNotNull\")) {\n            if (json.isNull(\"fieldDateNotNull\")) {\n                objProxy.realmSet$fieldDateNotNull(null);\n            } else {\n                Object timestamp = json.get(\"fieldDateNotNull\");\n                if (timestamp instanceof String) {\n                    objProxy.realmSet$fieldDateNotNull(JsonUtils.stringToDate((String) timestamp));\n                } else {\n                    objProxy.realmSet$fieldDateNotNull(new Date(json.getLong(\"fieldDateNotNull\")));\n                }\n            }\n        }\n        if (json.has(\"fieldDateNull\")) {\n            if (json.isNull(\"fieldDateNull\")) {\n                objProxy.realmSet$fieldDateNull(null);\n            } else {\n                Object timestamp = json.get(\"fieldDateNull\");\n                if (timestamp instanceof String) {\n                    objProxy.realmSet$fieldDateNull(JsonUtils.stringToDate((String) timestamp));\n                } else {\n                    objProxy.realmSet$fieldDateNull(new Date(json.getLong(\"fieldDateNull\")));\n                }\n            }\n        }\n        if (json.has(\"fieldDecimal128NotNull\")) {\n            if (json.isNull(\"fieldDecimal128NotNull\")) {\n                objProxy.realmSet$fieldDecimal128NotNull(null);\n            } else {\n                Object decimal = json.get(\"fieldDecimal128NotNull\");\n                if (decimal instanceof org.bson.types.Decimal128) {\n                    objProxy.realmSet$fieldDecimal128NotNull((org.bson.types.Decimal128) decimal);\n                } else if (decimal instanceof String) {\n                    objProxy.realmSet$fieldDecimal128NotNull(org.bson.types.Decimal128.parse((String)decimal));\n                } else if (decimal instanceof Integer) {\n                    objProxy.realmSet$fieldDecimal128NotNull(new org.bson.types.Decimal128((Integer)(decimal)));\n                } else if (decimal instanceof Long) {\n                    objProxy.realmSet$fieldDecimal128NotNull(new org.bson.types.Decimal128((Long)(decimal)));\n                } else if (decimal instanceof Double) {\n                    objProxy.realmSet$fieldDecimal128NotNull(new org.bson.types.Decimal128(new java.math.BigDecimal((Double)(decimal))));\n                } else {\n                    throw new UnsupportedOperationException(decimal.getClass() + \" is not supported as a Decimal128 value\");\n                }\n            }\n        }\n        if (json.has(\"fieldDecimal128Null\")) {\n            if (json.isNull(\"fieldDecimal128Null\")) {\n                objProxy.realmSet$fieldDecimal128Null(null);\n            } else {\n                Object decimal = json.get(\"fieldDecimal128Null\");\n                if (decimal instanceof org.bson.types.Decimal128) {\n                    objProxy.realmSet$fieldDecimal128Null((org.bson.types.Decimal128) decimal);\n                } else if (decimal instanceof String) {\n                    objProxy.realmSet$fieldDecimal128Null(org.bson.types.Decimal128.parse((String)decimal));\n                } else if (decimal instanceof Integer) {\n                    objProxy.realmSet$fieldDecimal128Null(new org.bson.types.Decimal128((Integer)(decimal)));\n                } else if (decimal instanceof Long) {\n                    objProxy.realmSet$fieldDecimal128Null(new org.bson.types.Decimal128((Long)(decimal)));\n                } else if (decimal instanceof Double) {\n                    objProxy.realmSet$fieldDecimal128Null(new org.bson.types.Decimal128(new java.math.BigDecimal((Double)(decimal))));\n                } else {\n                    throw new UnsupportedOperationException(decimal.getClass() + \" is not supported as a Decimal128 value\");\n                }\n            }\n        }\n        if (json.has(\"fieldObjectIdNotNull\")) {\n            if (json.isNull(\"fieldObjectIdNotNull\")) {\n                objProxy.realmSet$fieldObjectIdNotNull(null);\n            } else {\n                Object id = json.get(\"fieldObjectIdNotNull\");\n                if (id instanceof org.bson.types.ObjectId) {\n                    objProxy.realmSet$fieldObjectIdNotNull((org.bson.types.ObjectId) id);\n                } else {\n                    objProxy.realmSet$fieldObjectIdNotNull(new org.bson.types.ObjectId((String)id));\n                }\n            }\n        }\n        if (json.has(\"fieldObjectIdNull\")) {\n            if (json.isNull(\"fieldObjectIdNull\")) {\n                objProxy.realmSet$fieldObjectIdNull(null);\n            } else {\n                Object id = json.get(\"fieldObjectIdNull\");\n                if (id instanceof org.bson.types.ObjectId) {\n                    objProxy.realmSet$fieldObjectIdNull((org.bson.types.ObjectId) id);\n                } else {\n                    objProxy.realmSet$fieldObjectIdNull(new org.bson.types.ObjectId((String)id));\n                }\n            }\n        }\n        if (json.has(\"fieldObjectNull\")) {\n            if (json.isNull(\"fieldObjectNull\")) {\n                objProxy.realmSet$fieldObjectNull(null);\n            } else {\n                some.test.NullTypes fieldObjectNullObj = some_test_NullTypesRealmProxy.createOrUpdateUsingJsonObject(realm, json.getJSONObject(\"fieldObjectNull\"), update);\n                objProxy.realmSet$fieldObjectNull(fieldObjectNullObj);\n            }\n        }\n        ProxyUtils.setRealmListWithJsonObject(realm, objProxy.realmGet$fieldStringListNotNull(), json, \"fieldStringListNotNull\", update);\n        ProxyUtils.setRealmListWithJsonObject(realm, objProxy.realmGet$fieldStringListNull(), json, \"fieldStringListNull\", update);\n        ProxyUtils.setRealmListWithJsonObject(realm, objProxy.realmGet$fieldBinaryListNotNull(), json, \"fieldBinaryListNotNull\", update);\n        ProxyUtils.setRealmListWithJsonObject(realm, objProxy.realmGet$fieldBinaryListNull(), json, \"fieldBinaryListNull\", update);\n        ProxyUtils.setRealmListWithJsonObject(realm, objProxy.realmGet$fieldBooleanListNotNull(), json, \"fieldBooleanListNotNull\", update);\n        ProxyUtils.setRealmListWithJsonObject(realm, objProxy.realmGet$fieldBooleanListNull(), json, \"fieldBooleanListNull\", update);\n        ProxyUtils.setRealmListWithJsonObject(realm, objProxy.realmGet$fieldLongListNotNull(), json, \"fieldLongListNotNull\", update);\n        ProxyUtils.setRealmListWithJsonObject(realm, objProxy.realmGet$fieldLongListNull(), json, \"fieldLongListNull\", update);\n        ProxyUtils.setRealmListWithJsonObject(realm, objProxy.realmGet$fieldIntegerListNotNull(), json, \"fieldIntegerListNotNull\", update);\n        ProxyUtils.setRealmListWithJsonObject(realm, objProxy.realmGet$fieldIntegerListNull(), json, \"fieldIntegerListNull\", update);\n        ProxyUtils.setRealmListWithJsonObject(realm, objProxy.realmGet$fieldShortListNotNull(), json, \"fieldShortListNotNull\", update);\n        ProxyUtils.setRealmListWithJsonObject(realm, objProxy.realmGet$fieldShortListNull(), json, \"fieldShortListNull\", update);\n        ProxyUtils.setRealmListWithJsonObject(realm, objProxy.realmGet$fieldByteListNotNull(), json, \"fieldByteListNotNull\", update);\n        ProxyUtils.setRealmListWithJsonObject(realm, objProxy.realmGet$fieldByteListNull(), json, \"fieldByteListNull\", update);\n        ProxyUtils.setRealmListWithJsonObject(realm, objProxy.realmGet$fieldDoubleListNotNull(), json, \"fieldDoubleListNotNull\", update);\n        ProxyUtils.setRealmListWithJsonObject(realm, objProxy.realmGet$fieldDoubleListNull(), json, \"fieldDoubleListNull\", update);\n        ProxyUtils.setRealmListWithJsonObject(realm, objProxy.realmGet$fieldFloatListNotNull(), json, \"fieldFloatListNotNull\", update);\n        ProxyUtils.setRealmListWithJsonObject(realm, objProxy.realmGet$fieldFloatListNull(), json, \"fieldFloatListNull\", update);\n        ProxyUtils.setRealmListWithJsonObject(realm, objProxy.realmGet$fieldDateListNotNull(), json, \"fieldDateListNotNull\", update);\n        ProxyUtils.setRealmListWithJsonObject(realm, objProxy.realmGet$fieldDateListNull(), json, \"fieldDateListNull\", update);\n        ProxyUtils.setRealmListWithJsonObject(realm, objProxy.realmGet$fieldDecimal128ListNotNull(), json, \"fieldDecimal128ListNotNull\", update);\n        ProxyUtils.setRealmListWithJsonObject(realm, objProxy.realmGet$fieldDecimal128ListNull(), json, \"fieldDecimal128ListNull\", update);\n        ProxyUtils.setRealmListWithJsonObject(realm, objProxy.realmGet$fieldObjectIdListNotNull(), json, \"fieldObjectIdListNotNull\", update);\n        ProxyUtils.setRealmListWithJsonObject(realm, objProxy.realmGet$fieldObjectIdListNull(), json, \"fieldObjectIdListNull\", update);\n        return obj;\n    }\n\n    @SuppressWarnings(\"cast\")\n    @TargetApi(Build.VERSION_CODES.HONEYCOMB)\n    public static some.test.NullTypes createUsingJsonStream(Realm realm, JsonReader reader)\n            throws IOException {\n        final some.test.NullTypes obj = new some.test.NullTypes();\n        final some_test_NullTypesRealmProxyInterface objProxy = (some_test_NullTypesRealmProxyInterface) obj;\n        reader.beginObject();\n        while (reader.hasNext()) {\n            String name = reader.nextName();\n            if (false) {\n            } else if (name.equals(\"fieldStringNotNull\")) {\n                if (reader.peek() != JsonToken.NULL) {\n                    objProxy.realmSet$fieldStringNotNull((String) reader.nextString());\n                } else {\n                    reader.skipValue();\n                    objProxy.realmSet$fieldStringNotNull(null);\n                }\n            } else if (name.equals(\"fieldStringNull\")) {\n                if (reader.peek() != JsonToken.NULL) {\n                    objProxy.realmSet$fieldStringNull((String) reader.nextString());\n                } else {\n                    reader.skipValue();\n                    objProxy.realmSet$fieldStringNull(null);\n                }\n            } else if (name.equals(\"fieldBooleanNotNull\")) {\n                if (reader.peek() != JsonToken.NULL) {\n                    objProxy.realmSet$fieldBooleanNotNull((boolean) reader.nextBoolean());\n                } else {\n                    reader.skipValue();\n                    objProxy.realmSet$fieldBooleanNotNull(null);\n                }\n            } else if (name.equals(\"fieldBooleanNull\")) {\n                if (reader.peek() != JsonToken.NULL) {\n                    objProxy.realmSet$fieldBooleanNull((boolean) reader.nextBoolean());\n                } else {\n                    reader.skipValue();\n                    objProxy.realmSet$fieldBooleanNull(null);\n                }\n            } else if (name.equals(\"fieldBytesNotNull\")) {\n                if (reader.peek() != JsonToken.NULL) {\n                    objProxy.realmSet$fieldBytesNotNull(JsonUtils.stringToBytes(reader.nextString()));\n                } else {\n                    reader.skipValue();\n                    objProxy.realmSet$fieldBytesNotNull(null);\n                }\n            } else if (name.equals(\"fieldBytesNull\")) {\n                if (reader.peek() != JsonToken.NULL) {\n                    objProxy.realmSet$fieldBytesNull(JsonUtils.stringToBytes(reader.nextString()));\n                } else {\n                    reader.skipValue();\n                    objProxy.realmSet$fieldBytesNull(null);\n                }\n            } else if (name.equals(\"fieldByteNotNull\")) {\n                if (reader.peek() != JsonToken.NULL) {\n                    objProxy.realmSet$fieldByteNotNull((byte) reader.nextInt());\n                } else {\n                    reader.skipValue();\n                    objProxy.realmSet$fieldByteNotNull(null);\n                }\n            } else if (name.equals(\"fieldByteNull\")) {\n                if (reader.peek() != JsonToken.NULL) {\n                    objProxy.realmSet$fieldByteNull((byte) reader.nextInt());\n                } else {\n                    reader.skipValue();\n                    objProxy.realmSet$fieldByteNull(null);\n                }\n            } else if (name.equals(\"fieldShortNotNull\")) {\n                if (reader.peek() != JsonToken.NULL) {\n                    objProxy.realmSet$fieldShortNotNull((short) reader.nextInt());\n                } else {\n                    reader.skipValue();\n                    objProxy.realmSet$fieldShortNotNull(null);\n                }\n            } else if (name.equals(\"fieldShortNull\")) {\n                if (reader.peek() != JsonToken.NULL) {\n                    objProxy.realmSet$fieldShortNull((short) reader.nextInt());\n                } else {\n                    reader.skipValue();\n                    objProxy.realmSet$fieldShortNull(null);\n                }\n            } else if (name.equals(\"fieldIntegerNotNull\")) {\n                if (reader.peek() != JsonToken.NULL) {\n                    objProxy.realmSet$fieldIntegerNotNull((int) reader.nextInt());\n                } else {\n                    reader.skipValue();\n                    objProxy.realmSet$fieldIntegerNotNull(null);\n                }\n            } else if (name.equals(\"fieldIntegerNull\")) {\n                if (reader.peek() != JsonToken.NULL) {\n                    objProxy.realmSet$fieldIntegerNull((int) reader.nextInt());\n                } else {\n                    reader.skipValue();\n                    objProxy.realmSet$fieldIntegerNull(null);\n                }\n            } else if (name.equals(\"fieldLongNotNull\")) {\n                if (reader.peek() != JsonToken.NULL) {\n                    objProxy.realmSet$fieldLongNotNull((long) reader.nextLong());\n                } else {\n                    reader.skipValue();\n                    objProxy.realmSet$fieldLongNotNull(null);\n                }\n            } else if (name.equals(\"fieldLongNull\")) {\n                if (reader.peek() != JsonToken.NULL) {\n                    objProxy.realmSet$fieldLongNull((long) reader.nextLong());\n                } else {\n                    reader.skipValue();\n                    objProxy.realmSet$fieldLongNull(null);\n                }\n            } else if (name.equals(\"fieldFloatNotNull\")) {\n                if (reader.peek() != JsonToken.NULL) {\n                    objProxy.realmSet$fieldFloatNotNull((float) reader.nextDouble());\n                } else {\n                    reader.skipValue();\n                    objProxy.realmSet$fieldFloatNotNull(null);\n                }\n            } else if (name.equals(\"fieldFloatNull\")) {\n                if (reader.peek() != JsonToken.NULL) {\n                    objProxy.realmSet$fieldFloatNull((float) reader.nextDouble());\n                } else {\n                    reader.skipValue();\n                    objProxy.realmSet$fieldFloatNull(null);\n                }\n            } else if (name.equals(\"fieldDoubleNotNull\")) {\n                if (reader.peek() != JsonToken.NULL) {\n                    objProxy.realmSet$fieldDoubleNotNull((double) reader.nextDouble());\n                } else {\n                    reader.skipValue();\n                    objProxy.realmSet$fieldDoubleNotNull(null);\n                }\n            } else if (name.equals(\"fieldDoubleNull\")) {\n                if (reader.peek() != JsonToken.NULL) {\n                    objProxy.realmSet$fieldDoubleNull((double) reader.nextDouble());\n                } else {\n                    reader.skipValue();\n                    objProxy.realmSet$fieldDoubleNull(null);\n                }\n            } else if (name.equals(\"fieldDateNotNull\")) {\n                if (reader.peek() == JsonToken.NULL) {\n                    reader.skipValue();\n                    objProxy.realmSet$fieldDateNotNull(null);\n                } else if (reader.peek() == JsonToken.NUMBER) {\n                    long timestamp = reader.nextLong();\n                    if (timestamp > -1) {\n                        objProxy.realmSet$fieldDateNotNull(new Date(timestamp));\n                    }\n                } else {\n                    objProxy.realmSet$fieldDateNotNull(JsonUtils.stringToDate(reader.nextString()));\n                }\n            } else if (name.equals(\"fieldDateNull\")) {\n                if (reader.peek() == JsonToken.NULL) {\n                    reader.skipValue();\n                    objProxy.realmSet$fieldDateNull(null);\n                } else if (reader.peek() == JsonToken.NUMBER) {\n                    long timestamp = reader.nextLong();\n                    if (timestamp > -1) {\n                        objProxy.realmSet$fieldDateNull(new Date(timestamp));\n                    }\n                } else {\n                    objProxy.realmSet$fieldDateNull(JsonUtils.stringToDate(reader.nextString()));\n                }\n            } else if (name.equals(\"fieldDecimal128NotNull\")) {\n                if (reader.peek() == JsonToken.NULL) {\n                    reader.skipValue();\n                    objProxy.realmSet$fieldDecimal128NotNull(null);\n                } else {\n                    objProxy.realmSet$fieldDecimal128NotNull(org.bson.types.Decimal128.parse(reader.nextString()));\n                }\n            } else if (name.equals(\"fieldDecimal128Null\")) {\n                if (reader.peek() == JsonToken.NULL) {\n                    reader.skipValue();\n                    objProxy.realmSet$fieldDecimal128Null(null);\n                } else {\n                    objProxy.realmSet$fieldDecimal128Null(org.bson.types.Decimal128.parse(reader.nextString()));\n                }\n            } else if (name.equals(\"fieldObjectIdNotNull\")) {\n                if (reader.peek() == JsonToken.NULL) {\n                    reader.skipValue();\n                    objProxy.realmSet$fieldObjectIdNotNull(null);\n                } else {\n                    objProxy.realmSet$fieldObjectIdNotNull(new org.bson.types.ObjectId(reader.nextString()));\n                }\n            } else if (name.equals(\"fieldObjectIdNull\")) {\n                if (reader.peek() == JsonToken.NULL) {\n                    reader.skipValue();\n                    objProxy.realmSet$fieldObjectIdNull(null);\n                } else {\n                    objProxy.realmSet$fieldObjectIdNull(new org.bson.types.ObjectId(reader.nextString()));\n                }\n            } else if (name.equals(\"fieldObjectNull\")) {\n                if (reader.peek() == JsonToken.NULL) {\n                    reader.skipValue();\n                    objProxy.realmSet$fieldObjectNull(null);\n                } else {\n                    some.test.NullTypes fieldObjectNullObj = some_test_NullTypesRealmProxy.createUsingJsonStream(realm, reader);\n                    objProxy.realmSet$fieldObjectNull(fieldObjectNullObj);\n                }\n            } else if (name.equals(\"fieldStringListNotNull\")) {\n                objProxy.realmSet$fieldStringListNotNull(ProxyUtils.createRealmListWithJsonStream(java.lang.String.class, reader));\n            } else if (name.equals(\"fieldStringListNull\")) {\n                objProxy.realmSet$fieldStringListNull(ProxyUtils.createRealmListWithJsonStream(java.lang.String.class, reader));\n            } else if (name.equals(\"fieldBinaryListNotNull\")) {\n                objProxy.realmSet$fieldBinaryListNotNull(ProxyUtils.createRealmListWithJsonStream(byte[].class, reader));\n            } else if (name.equals(\"fieldBinaryListNull\")) {\n                objProxy.realmSet$fieldBinaryListNull(ProxyUtils.createRealmListWithJsonStream(byte[].class, reader));\n            } else if (name.equals(\"fieldBooleanListNotNull\")) {\n                objProxy.realmSet$fieldBooleanListNotNull(ProxyUtils.createRealmListWithJsonStream(java.lang.Boolean.class, reader));\n            } else if (name.equals(\"fieldBooleanListNull\")) {\n                objProxy.realmSet$fieldBooleanListNull(ProxyUtils.createRealmListWithJsonStream(java.lang.Boolean.class, reader));\n            } else if (name.equals(\"fieldLongListNotNull\")) {\n                objProxy.realmSet$fieldLongListNotNull(ProxyUtils.createRealmListWithJsonStream(java.lang.Long.class, reader));\n            } else if (name.equals(\"fieldLongListNull\")) {\n                objProxy.realmSet$fieldLongListNull(ProxyUtils.createRealmListWithJsonStream(java.lang.Long.class, reader));\n            } else if (name.equals(\"fieldIntegerListNotNull\")) {\n                objProxy.realmSet$fieldIntegerListNotNull(ProxyUtils.createRealmListWithJsonStream(java.lang.Integer.class, reader));\n            } else if (name.equals(\"fieldIntegerListNull\")) {\n                objProxy.realmSet$fieldIntegerListNull(ProxyUtils.createRealmListWithJsonStream(java.lang.Integer.class, reader));\n            } else if (name.equals(\"fieldShortListNotNull\")) {\n                objProxy.realmSet$fieldShortListNotNull(ProxyUtils.createRealmListWithJsonStream(java.lang.Short.class, reader));\n            } else if (name.equals(\"fieldShortListNull\")) {\n                objProxy.realmSet$fieldShortListNull(ProxyUtils.createRealmListWithJsonStream(java.lang.Short.class, reader));\n            } else if (name.equals(\"fieldByteListNotNull\")) {\n                objProxy.realmSet$fieldByteListNotNull(ProxyUtils.createRealmListWithJsonStream(java.lang.Byte.class, reader));\n            } else if (name.equals(\"fieldByteListNull\")) {\n                objProxy.realmSet$fieldByteListNull(ProxyUtils.createRealmListWithJsonStream(java.lang.Byte.class, reader));\n            } else if (name.equals(\"fieldDoubleListNotNull\")) {\n                objProxy.realmSet$fieldDoubleListNotNull(ProxyUtils.createRealmListWithJsonStream(java.lang.Double.class, reader));\n            } else if (name.equals(\"fieldDoubleListNull\")) {\n                objProxy.realmSet$fieldDoubleListNull(ProxyUtils.createRealmListWithJsonStream(java.lang.Double.class, reader));\n            } else if (name.equals(\"fieldFloatListNotNull\")) {\n                objProxy.realmSet$fieldFloatListNotNull(ProxyUtils.createRealmListWithJsonStream(java.lang.Float.class, reader));\n            } else if (name.equals(\"fieldFloatListNull\")) {\n                objProxy.realmSet$fieldFloatListNull(ProxyUtils.createRealmListWithJsonStream(java.lang.Float.class, reader));\n            } else if (name.equals(\"fieldDateListNotNull\")) {\n                objProxy.realmSet$fieldDateListNotNull(ProxyUtils.createRealmListWithJsonStream(java.util.Date.class, reader));\n            } else if (name.equals(\"fieldDateListNull\")) {\n                objProxy.realmSet$fieldDateListNull(ProxyUtils.createRealmListWithJsonStream(java.util.Date.class, reader));\n            } else if (name.equals(\"fieldDecimal128ListNotNull\")) {\n                objProxy.realmSet$fieldDecimal128ListNotNull(ProxyUtils.createRealmListWithJsonStream(org.bson.types.Decimal128.class, reader));\n            } else if (name.equals(\"fieldDecimal128ListNull\")) {\n                objProxy.realmSet$fieldDecimal128ListNull(ProxyUtils.createRealmListWithJsonStream(org.bson.types.Decimal128.class, reader));\n            } else if (name.equals(\"fieldObjectIdListNotNull\")) {\n                objProxy.realmSet$fieldObjectIdListNotNull(ProxyUtils.createRealmListWithJsonStream(org.bson.types.ObjectId.class, reader));\n            } else if (name.equals(\"fieldObjectIdListNull\")) {\n                objProxy.realmSet$fieldObjectIdListNull(ProxyUtils.createRealmListWithJsonStream(org.bson.types.ObjectId.class, reader));\n            } else {\n                reader.skipValue();\n            }\n        }\n        reader.endObject();\n        return realm.copyToRealm(obj);\n    }\n\n    static some_test_NullTypesRealmProxy newProxyInstance(BaseRealm realm, Row row) {\n        // Ignore default values to avoid creating unexpected objects from RealmModel/RealmList fields\n        final BaseRealm.RealmObjectContext objectContext = BaseRealm.objectContext.get();\n        objectContext.set(realm, row, realm.getSchema().getColumnInfo(some.test.NullTypes.class), false, Collections.<String>emptyList());\n        io.realm.some_test_NullTypesRealmProxy obj = new io.realm.some_test_NullTypesRealmProxy();\n        objectContext.clear();\n        return obj;\n    }\n\n    public static some.test.NullTypes copyOrUpdate(Realm realm, NullTypesColumnInfo columnInfo, some.test.NullTypes object, boolean update, Map<RealmModel,RealmObjectProxy> cache, Set<ImportFlag> flags) {\n        if (object instanceof RealmObjectProxy && !RealmObject.isFrozen(object) && ((RealmObjectProxy) object).realmGet$proxyState().getRealm$realm() != null) {\n            final BaseRealm otherRealm = ((RealmObjectProxy) object).realmGet$proxyState().getRealm$realm();\n            if (otherRealm.threadId != realm.threadId) {\n                throw new IllegalArgumentException(\"Objects which belong to Realm instances in other threads cannot be copied into this Realm instance.\");\n            }\n            if (otherRealm.getPath().equals(realm.getPath())) {\n                return object;\n            }\n        }\n        final BaseRealm.RealmObjectContext objectContext = BaseRealm.objectContext.get();\n        RealmObjectProxy cachedRealmObject = cache.get(object);\n        if (cachedRealmObject != null) {\n            return (some.test.NullTypes) cachedRealmObject;\n        }\n\n        return copy(realm, columnInfo, object, update, cache, flags);\n    }\n\n    public static some.test.NullTypes copy(Realm realm, NullTypesColumnInfo columnInfo, some.test.NullTypes newObject, boolean update, Map<RealmModel,RealmObjectProxy> cache, Set<ImportFlag> flags) {\n        RealmObjectProxy cachedRealmObject = cache.get(newObject);\n        if (cachedRealmObject != null) {\n            return (some.test.NullTypes) cachedRealmObject;\n        }\n\n        some_test_NullTypesRealmProxyInterface unmanagedSource = (some_test_NullTypesRealmProxyInterface) newObject;\n\n        Table table = realm.getTable(some.test.NullTypes.class);\n        OsObjectBuilder builder = new OsObjectBuilder(table, flags);\n\n        // Add all non-\"object reference\" fields\n        builder.addString(columnInfo.fieldStringNotNullColKey, unmanagedSource.realmGet$fieldStringNotNull());\n        builder.addString(columnInfo.fieldStringNullColKey, unmanagedSource.realmGet$fieldStringNull());\n        builder.addBoolean(columnInfo.fieldBooleanNotNullColKey, unmanagedSource.realmGet$fieldBooleanNotNull());\n        builder.addBoolean(columnInfo.fieldBooleanNullColKey, unmanagedSource.realmGet$fieldBooleanNull());\n        builder.addByteArray(columnInfo.fieldBytesNotNullColKey, unmanagedSource.realmGet$fieldBytesNotNull());\n        builder.addByteArray(columnInfo.fieldBytesNullColKey, unmanagedSource.realmGet$fieldBytesNull());\n        builder.addInteger(columnInfo.fieldByteNotNullColKey, unmanagedSource.realmGet$fieldByteNotNull());\n        builder.addInteger(columnInfo.fieldByteNullColKey, unmanagedSource.realmGet$fieldByteNull());\n        builder.addInteger(columnInfo.fieldShortNotNullColKey, unmanagedSource.realmGet$fieldShortNotNull());\n        builder.addInteger(columnInfo.fieldShortNullColKey, unmanagedSource.realmGet$fieldShortNull());\n        builder.addInteger(columnInfo.fieldIntegerNotNullColKey, unmanagedSource.realmGet$fieldIntegerNotNull());\n        builder.addInteger(columnInfo.fieldIntegerNullColKey, unmanagedSource.realmGet$fieldIntegerNull());\n        builder.addInteger(columnInfo.fieldLongNotNullColKey, unmanagedSource.realmGet$fieldLongNotNull());\n        builder.addInteger(columnInfo.fieldLongNullColKey, unmanagedSource.realmGet$fieldLongNull());\n        builder.addFloat(columnInfo.fieldFloatNotNullColKey, unmanagedSource.realmGet$fieldFloatNotNull());\n        builder.addFloat(columnInfo.fieldFloatNullColKey, unmanagedSource.realmGet$fieldFloatNull());\n        builder.addDouble(columnInfo.fieldDoubleNotNullColKey, unmanagedSource.realmGet$fieldDoubleNotNull());\n        builder.addDouble(columnInfo.fieldDoubleNullColKey, unmanagedSource.realmGet$fieldDoubleNull());\n        builder.addDate(columnInfo.fieldDateNotNullColKey, unmanagedSource.realmGet$fieldDateNotNull());\n        builder.addDate(columnInfo.fieldDateNullColKey, unmanagedSource.realmGet$fieldDateNull());\n        builder.addDecimal128(columnInfo.fieldDecimal128NotNullColKey, unmanagedSource.realmGet$fieldDecimal128NotNull());\n        builder.addDecimal128(columnInfo.fieldDecimal128NullColKey, unmanagedSource.realmGet$fieldDecimal128Null());\n        builder.addObjectId(columnInfo.fieldObjectIdNotNullColKey, unmanagedSource.realmGet$fieldObjectIdNotNull());\n        builder.addObjectId(columnInfo.fieldObjectIdNullColKey, unmanagedSource.realmGet$fieldObjectIdNull());\n        builder.addStringList(columnInfo.fieldStringListNotNullColKey, unmanagedSource.realmGet$fieldStringListNotNull());\n        builder.addStringList(columnInfo.fieldStringListNullColKey, unmanagedSource.realmGet$fieldStringListNull());\n        builder.addByteArrayList(columnInfo.fieldBinaryListNotNullColKey, unmanagedSource.realmGet$fieldBinaryListNotNull());\n        builder.addByteArrayList(columnInfo.fieldBinaryListNullColKey, unmanagedSource.realmGet$fieldBinaryListNull());\n        builder.addBooleanList(columnInfo.fieldBooleanListNotNullColKey, unmanagedSource.realmGet$fieldBooleanListNotNull());\n        builder.addBooleanList(columnInfo.fieldBooleanListNullColKey, unmanagedSource.realmGet$fieldBooleanListNull());\n        builder.addLongList(columnInfo.fieldLongListNotNullColKey, unmanagedSource.realmGet$fieldLongListNotNull());\n        builder.addLongList(columnInfo.fieldLongListNullColKey, unmanagedSource.realmGet$fieldLongListNull());\n        builder.addIntegerList(columnInfo.fieldIntegerListNotNullColKey, unmanagedSource.realmGet$fieldIntegerListNotNull());\n        builder.addIntegerList(columnInfo.fieldIntegerListNullColKey, unmanagedSource.realmGet$fieldIntegerListNull());\n        builder.addShortList(columnInfo.fieldShortListNotNullColKey, unmanagedSource.realmGet$fieldShortListNotNull());\n        builder.addShortList(columnInfo.fieldShortListNullColKey, unmanagedSource.realmGet$fieldShortListNull());\n        builder.addByteList(columnInfo.fieldByteListNotNullColKey, unmanagedSource.realmGet$fieldByteListNotNull());\n        builder.addByteList(columnInfo.fieldByteListNullColKey, unmanagedSource.realmGet$fieldByteListNull());\n        builder.addDoubleList(columnInfo.fieldDoubleListNotNullColKey, unmanagedSource.realmGet$fieldDoubleListNotNull());\n        builder.addDoubleList(columnInfo.fieldDoubleListNullColKey, unmanagedSource.realmGet$fieldDoubleListNull());\n        builder.addFloatList(columnInfo.fieldFloatListNotNullColKey, unmanagedSource.realmGet$fieldFloatListNotNull());\n        builder.addFloatList(columnInfo.fieldFloatListNullColKey, unmanagedSource.realmGet$fieldFloatListNull());\n        builder.addDateList(columnInfo.fieldDateListNotNullColKey, unmanagedSource.realmGet$fieldDateListNotNull());\n        builder.addDateList(columnInfo.fieldDateListNullColKey, unmanagedSource.realmGet$fieldDateListNull());\n        builder.addDecimal128List(columnInfo.fieldDecimal128ListNotNullColKey, unmanagedSource.realmGet$fieldDecimal128ListNotNull());\n        builder.addDecimal128List(columnInfo.fieldDecimal128ListNullColKey, unmanagedSource.realmGet$fieldDecimal128ListNull());\n        builder.addObjectIdList(columnInfo.fieldObjectIdListNotNullColKey, unmanagedSource.realmGet$fieldObjectIdListNotNull());\n        builder.addObjectIdList(columnInfo.fieldObjectIdListNullColKey, unmanagedSource.realmGet$fieldObjectIdListNull());\n\n        // Create the underlying object and cache it before setting any object/objectlist references\n        // This will allow us to break any circular dependencies by using the object cache.\n        Row row = builder.createNewObject();\n        io.realm.some_test_NullTypesRealmProxy managedCopy = newProxyInstance(realm, row);\n        cache.put(newObject, managedCopy);\n\n        // Finally add all fields that reference other Realm Objects, either directly or through a list\n        some.test.NullTypes fieldObjectNullObj = unmanagedSource.realmGet$fieldObjectNull();\n        if (fieldObjectNullObj == null) {\n            managedCopy.realmSet$fieldObjectNull(null);\n        } else {\n            some.test.NullTypes cachefieldObjectNull = (some.test.NullTypes) cache.get(fieldObjectNullObj);\n            if (cachefieldObjectNull != null) {\n                managedCopy.realmSet$fieldObjectNull(cachefieldObjectNull);\n            } else {\n                managedCopy.realmSet$fieldObjectNull(some_test_NullTypesRealmProxy.copyOrUpdate(realm, (some_test_NullTypesRealmProxy.NullTypesColumnInfo) realm.getSchema().getColumnInfo(some.test.NullTypes.class), fieldObjectNullObj, update, cache, flags));\n            }\n        }\n\n        return managedCopy;\n    }\n\n    public static long insert(Realm realm, some.test.NullTypes object, Map<RealmModel,Long> cache) {\n        if (object instanceof RealmObjectProxy && !RealmObject.isFrozen(object) && ((RealmObjectProxy) object).realmGet$proxyState().getRealm$realm() != null && ((RealmObjectProxy) object).realmGet$proxyState().getRealm$realm().getPath().equals(realm.getPath())) {\n            return ((RealmObjectProxy) object).realmGet$proxyState().getRow$realm().getObjectKey();\n        }\n        Table table = realm.getTable(some.test.NullTypes.class);\n        long tableNativePtr = table.getNativePtr();\n        NullTypesColumnInfo columnInfo = (NullTypesColumnInfo) realm.getSchema().getColumnInfo(some.test.NullTypes.class);\n        long objKey = OsObject.createRow(table);\n        cache.put(object, objKey);\n        String realmGet$fieldStringNotNull = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldStringNotNull();\n        if (realmGet$fieldStringNotNull != null) {\n            Table.nativeSetString(tableNativePtr, columnInfo.fieldStringNotNullColKey, objKey, realmGet$fieldStringNotNull, false);\n        }\n        String realmGet$fieldStringNull = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldStringNull();\n        if (realmGet$fieldStringNull != null) {\n            Table.nativeSetString(tableNativePtr, columnInfo.fieldStringNullColKey, objKey, realmGet$fieldStringNull, false);\n        }\n        Boolean realmGet$fieldBooleanNotNull = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldBooleanNotNull();\n        if (realmGet$fieldBooleanNotNull != null) {\n            Table.nativeSetBoolean(tableNativePtr, columnInfo.fieldBooleanNotNullColKey, objKey, realmGet$fieldBooleanNotNull, false);\n        }\n        Boolean realmGet$fieldBooleanNull = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldBooleanNull();\n        if (realmGet$fieldBooleanNull != null) {\n            Table.nativeSetBoolean(tableNativePtr, columnInfo.fieldBooleanNullColKey, objKey, realmGet$fieldBooleanNull, false);\n        }\n        byte[] realmGet$fieldBytesNotNull = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldBytesNotNull();\n        if (realmGet$fieldBytesNotNull != null) {\n            Table.nativeSetByteArray(tableNativePtr, columnInfo.fieldBytesNotNullColKey, objKey, realmGet$fieldBytesNotNull, false);\n        }\n        byte[] realmGet$fieldBytesNull = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldBytesNull();\n        if (realmGet$fieldBytesNull != null) {\n            Table.nativeSetByteArray(tableNativePtr, columnInfo.fieldBytesNullColKey, objKey, realmGet$fieldBytesNull, false);\n        }\n        Number realmGet$fieldByteNotNull = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldByteNotNull();\n        if (realmGet$fieldByteNotNull != null) {\n            Table.nativeSetLong(tableNativePtr, columnInfo.fieldByteNotNullColKey, objKey, realmGet$fieldByteNotNull.longValue(), false);\n        }\n        Number realmGet$fieldByteNull = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldByteNull();\n        if (realmGet$fieldByteNull != null) {\n            Table.nativeSetLong(tableNativePtr, columnInfo.fieldByteNullColKey, objKey, realmGet$fieldByteNull.longValue(), false);\n        }\n        Number realmGet$fieldShortNotNull = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldShortNotNull();\n        if (realmGet$fieldShortNotNull != null) {\n            Table.nativeSetLong(tableNativePtr, columnInfo.fieldShortNotNullColKey, objKey, realmGet$fieldShortNotNull.longValue(), false);\n        }\n        Number realmGet$fieldShortNull = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldShortNull();\n        if (realmGet$fieldShortNull != null) {\n            Table.nativeSetLong(tableNativePtr, columnInfo.fieldShortNullColKey, objKey, realmGet$fieldShortNull.longValue(), false);\n        }\n        Number realmGet$fieldIntegerNotNull = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldIntegerNotNull();\n        if (realmGet$fieldIntegerNotNull != null) {\n            Table.nativeSetLong(tableNativePtr, columnInfo.fieldIntegerNotNullColKey, objKey, realmGet$fieldIntegerNotNull.longValue(), false);\n        }\n        Number realmGet$fieldIntegerNull = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldIntegerNull();\n        if (realmGet$fieldIntegerNull != null) {\n            Table.nativeSetLong(tableNativePtr, columnInfo.fieldIntegerNullColKey, objKey, realmGet$fieldIntegerNull.longValue(), false);\n        }\n        Number realmGet$fieldLongNotNull = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldLongNotNull();\n        if (realmGet$fieldLongNotNull != null) {\n            Table.nativeSetLong(tableNativePtr, columnInfo.fieldLongNotNullColKey, objKey, realmGet$fieldLongNotNull.longValue(), false);\n        }\n        Number realmGet$fieldLongNull = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldLongNull();\n        if (realmGet$fieldLongNull != null) {\n            Table.nativeSetLong(tableNativePtr, columnInfo.fieldLongNullColKey, objKey, realmGet$fieldLongNull.longValue(), false);\n        }\n        Float realmGet$fieldFloatNotNull = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldFloatNotNull();\n        if (realmGet$fieldFloatNotNull != null) {\n            Table.nativeSetFloat(tableNativePtr, columnInfo.fieldFloatNotNullColKey, objKey, realmGet$fieldFloatNotNull, false);\n        }\n        Float realmGet$fieldFloatNull = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldFloatNull();\n        if (realmGet$fieldFloatNull != null) {\n            Table.nativeSetFloat(tableNativePtr, columnInfo.fieldFloatNullColKey, objKey, realmGet$fieldFloatNull, false);\n        }\n        Double realmGet$fieldDoubleNotNull = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldDoubleNotNull();\n        if (realmGet$fieldDoubleNotNull != null) {\n            Table.nativeSetDouble(tableNativePtr, columnInfo.fieldDoubleNotNullColKey, objKey, realmGet$fieldDoubleNotNull, false);\n        }\n        Double realmGet$fieldDoubleNull = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldDoubleNull();\n        if (realmGet$fieldDoubleNull != null) {\n            Table.nativeSetDouble(tableNativePtr, columnInfo.fieldDoubleNullColKey, objKey, realmGet$fieldDoubleNull, false);\n        }\n        java.util.Date realmGet$fieldDateNotNull = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldDateNotNull();\n        if (realmGet$fieldDateNotNull != null) {\n            Table.nativeSetTimestamp(tableNativePtr, columnInfo.fieldDateNotNullColKey, objKey, realmGet$fieldDateNotNull.getTime(), false);\n        }\n        java.util.Date realmGet$fieldDateNull = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldDateNull();\n        if (realmGet$fieldDateNull != null) {\n            Table.nativeSetTimestamp(tableNativePtr, columnInfo.fieldDateNullColKey, objKey, realmGet$fieldDateNull.getTime(), false);\n        }\n        org.bson.types.Decimal128 realmGet$fieldDecimal128NotNull = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldDecimal128NotNull();\n        if (realmGet$fieldDecimal128NotNull != null) {\n            Table.nativeSetDecimal128(tableNativePtr, columnInfo.fieldDecimal128NotNullColKey, objKey, realmGet$fieldDecimal128NotNull.getLow(), realmGet$fieldDecimal128NotNull.getHigh(), false);\n        }\n        org.bson.types.Decimal128 realmGet$fieldDecimal128Null = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldDecimal128Null();\n        if (realmGet$fieldDecimal128Null != null) {\n            Table.nativeSetDecimal128(tableNativePtr, columnInfo.fieldDecimal128NullColKey, objKey, realmGet$fieldDecimal128Null.getLow(), realmGet$fieldDecimal128Null.getHigh(), false);\n        }\n        org.bson.types.ObjectId realmGet$fieldObjectIdNotNull = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldObjectIdNotNull();\n        if (realmGet$fieldObjectIdNotNull != null) {\n            Table.nativeSetObjectId(tableNativePtr, columnInfo.fieldObjectIdNotNullColKey, objKey, realmGet$fieldObjectIdNotNull.toString(), false);\n        }\n        org.bson.types.ObjectId realmGet$fieldObjectIdNull = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldObjectIdNull();\n        if (realmGet$fieldObjectIdNull != null) {\n            Table.nativeSetObjectId(tableNativePtr, columnInfo.fieldObjectIdNullColKey, objKey, realmGet$fieldObjectIdNull.toString(), false);\n        }\n\n        some.test.NullTypes fieldObjectNullObj = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldObjectNull();\n        if (fieldObjectNullObj != null) {\n            Long cachefieldObjectNull = cache.get(fieldObjectNullObj);\n            if (cachefieldObjectNull == null) {\n                cachefieldObjectNull = some_test_NullTypesRealmProxy.insert(realm, fieldObjectNullObj, cache);\n            }\n            Table.nativeSetLink(tableNativePtr, columnInfo.fieldObjectNullColKey, objKey, cachefieldObjectNull, false);\n        }\n\n        RealmList<java.lang.String> fieldStringListNotNullList = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldStringListNotNull();\n        if (fieldStringListNotNullList != null) {\n            OsList fieldStringListNotNullOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.fieldStringListNotNullColKey);\n            for (java.lang.String fieldStringListNotNullItem : fieldStringListNotNullList) {\n                if (fieldStringListNotNullItem == null) {\n                    fieldStringListNotNullOsList.addNull();\n                } else {\n                    fieldStringListNotNullOsList.addString(fieldStringListNotNullItem);\n                }\n            }\n        }\n\n        RealmList<java.lang.String> fieldStringListNullList = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldStringListNull();\n        if (fieldStringListNullList != null) {\n            OsList fieldStringListNullOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.fieldStringListNullColKey);\n            for (java.lang.String fieldStringListNullItem : fieldStringListNullList) {\n                if (fieldStringListNullItem == null) {\n                    fieldStringListNullOsList.addNull();\n                } else {\n                    fieldStringListNullOsList.addString(fieldStringListNullItem);\n                }\n            }\n        }\n\n        RealmList<byte[]> fieldBinaryListNotNullList = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldBinaryListNotNull();\n        if (fieldBinaryListNotNullList != null) {\n            OsList fieldBinaryListNotNullOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.fieldBinaryListNotNullColKey);\n            for (byte[] fieldBinaryListNotNullItem : fieldBinaryListNotNullList) {\n                if (fieldBinaryListNotNullItem == null) {\n                    fieldBinaryListNotNullOsList.addNull();\n                } else {\n                    fieldBinaryListNotNullOsList.addBinary(fieldBinaryListNotNullItem);\n                }\n            }\n        }\n\n        RealmList<byte[]> fieldBinaryListNullList = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldBinaryListNull();\n        if (fieldBinaryListNullList != null) {\n            OsList fieldBinaryListNullOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.fieldBinaryListNullColKey);\n            for (byte[] fieldBinaryListNullItem : fieldBinaryListNullList) {\n                if (fieldBinaryListNullItem == null) {\n                    fieldBinaryListNullOsList.addNull();\n                } else {\n                    fieldBinaryListNullOsList.addBinary(fieldBinaryListNullItem);\n                }\n            }\n        }\n\n        RealmList<java.lang.Boolean> fieldBooleanListNotNullList = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldBooleanListNotNull();\n        if (fieldBooleanListNotNullList != null) {\n            OsList fieldBooleanListNotNullOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.fieldBooleanListNotNullColKey);\n            for (java.lang.Boolean fieldBooleanListNotNullItem : fieldBooleanListNotNullList) {\n                if (fieldBooleanListNotNullItem == null) {\n                    fieldBooleanListNotNullOsList.addNull();\n                } else {\n                    fieldBooleanListNotNullOsList.addBoolean(fieldBooleanListNotNullItem);\n                }\n            }\n        }\n\n        RealmList<java.lang.Boolean> fieldBooleanListNullList = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldBooleanListNull();\n        if (fieldBooleanListNullList != null) {\n            OsList fieldBooleanListNullOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.fieldBooleanListNullColKey);\n            for (java.lang.Boolean fieldBooleanListNullItem : fieldBooleanListNullList) {\n                if (fieldBooleanListNullItem == null) {\n                    fieldBooleanListNullOsList.addNull();\n                } else {\n                    fieldBooleanListNullOsList.addBoolean(fieldBooleanListNullItem);\n                }\n            }\n        }\n\n        RealmList<java.lang.Long> fieldLongListNotNullList = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldLongListNotNull();\n        if (fieldLongListNotNullList != null) {\n            OsList fieldLongListNotNullOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.fieldLongListNotNullColKey);\n            for (java.lang.Long fieldLongListNotNullItem : fieldLongListNotNullList) {\n                if (fieldLongListNotNullItem == null) {\n                    fieldLongListNotNullOsList.addNull();\n                } else {\n                    fieldLongListNotNullOsList.addLong(fieldLongListNotNullItem.longValue());\n                }\n            }\n        }\n\n        RealmList<java.lang.Long> fieldLongListNullList = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldLongListNull();\n        if (fieldLongListNullList != null) {\n            OsList fieldLongListNullOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.fieldLongListNullColKey);\n            for (java.lang.Long fieldLongListNullItem : fieldLongListNullList) {\n                if (fieldLongListNullItem == null) {\n                    fieldLongListNullOsList.addNull();\n                } else {\n                    fieldLongListNullOsList.addLong(fieldLongListNullItem.longValue());\n                }\n            }\n        }\n\n        RealmList<java.lang.Integer> fieldIntegerListNotNullList = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldIntegerListNotNull();\n        if (fieldIntegerListNotNullList != null) {\n            OsList fieldIntegerListNotNullOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.fieldIntegerListNotNullColKey);\n            for (java.lang.Integer fieldIntegerListNotNullItem : fieldIntegerListNotNullList) {\n                if (fieldIntegerListNotNullItem == null) {\n                    fieldIntegerListNotNullOsList.addNull();\n                } else {\n                    fieldIntegerListNotNullOsList.addLong(fieldIntegerListNotNullItem.longValue());\n                }\n            }\n        }\n\n        RealmList<java.lang.Integer> fieldIntegerListNullList = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldIntegerListNull();\n        if (fieldIntegerListNullList != null) {\n            OsList fieldIntegerListNullOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.fieldIntegerListNullColKey);\n            for (java.lang.Integer fieldIntegerListNullItem : fieldIntegerListNullList) {\n                if (fieldIntegerListNullItem == null) {\n                    fieldIntegerListNullOsList.addNull();\n                } else {\n                    fieldIntegerListNullOsList.addLong(fieldIntegerListNullItem.longValue());\n                }\n            }\n        }\n\n        RealmList<java.lang.Short> fieldShortListNotNullList = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldShortListNotNull();\n        if (fieldShortListNotNullList != null) {\n            OsList fieldShortListNotNullOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.fieldShortListNotNullColKey);\n            for (java.lang.Short fieldShortListNotNullItem : fieldShortListNotNullList) {\n                if (fieldShortListNotNullItem == null) {\n                    fieldShortListNotNullOsList.addNull();\n                } else {\n                    fieldShortListNotNullOsList.addLong(fieldShortListNotNullItem.longValue());\n                }\n            }\n        }\n\n        RealmList<java.lang.Short> fieldShortListNullList = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldShortListNull();\n        if (fieldShortListNullList != null) {\n            OsList fieldShortListNullOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.fieldShortListNullColKey);\n            for (java.lang.Short fieldShortListNullItem : fieldShortListNullList) {\n                if (fieldShortListNullItem == null) {\n                    fieldShortListNullOsList.addNull();\n                } else {\n                    fieldShortListNullOsList.addLong(fieldShortListNullItem.longValue());\n                }\n            }\n        }\n\n        RealmList<java.lang.Byte> fieldByteListNotNullList = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldByteListNotNull();\n        if (fieldByteListNotNullList != null) {\n            OsList fieldByteListNotNullOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.fieldByteListNotNullColKey);\n            for (java.lang.Byte fieldByteListNotNullItem : fieldByteListNotNullList) {\n                if (fieldByteListNotNullItem == null) {\n                    fieldByteListNotNullOsList.addNull();\n                } else {\n                    fieldByteListNotNullOsList.addLong(fieldByteListNotNullItem.longValue());\n                }\n            }\n        }\n\n        RealmList<java.lang.Byte> fieldByteListNullList = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldByteListNull();\n        if (fieldByteListNullList != null) {\n            OsList fieldByteListNullOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.fieldByteListNullColKey);\n            for (java.lang.Byte fieldByteListNullItem : fieldByteListNullList) {\n                if (fieldByteListNullItem == null) {\n                    fieldByteListNullOsList.addNull();\n                } else {\n                    fieldByteListNullOsList.addLong(fieldByteListNullItem.longValue());\n                }\n            }\n        }\n\n        RealmList<java.lang.Double> fieldDoubleListNotNullList = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldDoubleListNotNull();\n        if (fieldDoubleListNotNullList != null) {\n            OsList fieldDoubleListNotNullOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.fieldDoubleListNotNullColKey);\n            for (java.lang.Double fieldDoubleListNotNullItem : fieldDoubleListNotNullList) {\n                if (fieldDoubleListNotNullItem == null) {\n                    fieldDoubleListNotNullOsList.addNull();\n                } else {\n                    fieldDoubleListNotNullOsList.addDouble(fieldDoubleListNotNullItem.doubleValue());\n                }\n            }\n        }\n\n        RealmList<java.lang.Double> fieldDoubleListNullList = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldDoubleListNull();\n        if (fieldDoubleListNullList != null) {\n            OsList fieldDoubleListNullOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.fieldDoubleListNullColKey);\n            for (java.lang.Double fieldDoubleListNullItem : fieldDoubleListNullList) {\n                if (fieldDoubleListNullItem == null) {\n                    fieldDoubleListNullOsList.addNull();\n                } else {\n                    fieldDoubleListNullOsList.addDouble(fieldDoubleListNullItem.doubleValue());\n                }\n            }\n        }\n\n        RealmList<java.lang.Float> fieldFloatListNotNullList = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldFloatListNotNull();\n        if (fieldFloatListNotNullList != null) {\n            OsList fieldFloatListNotNullOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.fieldFloatListNotNullColKey);\n            for (java.lang.Float fieldFloatListNotNullItem : fieldFloatListNotNullList) {\n                if (fieldFloatListNotNullItem == null) {\n                    fieldFloatListNotNullOsList.addNull();\n                } else {\n                    fieldFloatListNotNullOsList.addFloat(fieldFloatListNotNullItem.floatValue());\n                }\n            }\n        }\n\n        RealmList<java.lang.Float> fieldFloatListNullList = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldFloatListNull();\n        if (fieldFloatListNullList != null) {\n            OsList fieldFloatListNullOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.fieldFloatListNullColKey);\n            for (java.lang.Float fieldFloatListNullItem : fieldFloatListNullList) {\n                if (fieldFloatListNullItem == null) {\n                    fieldFloatListNullOsList.addNull();\n                } else {\n                    fieldFloatListNullOsList.addFloat(fieldFloatListNullItem.floatValue());\n                }\n            }\n        }\n\n        RealmList<java.util.Date> fieldDateListNotNullList = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldDateListNotNull();\n        if (fieldDateListNotNullList != null) {\n            OsList fieldDateListNotNullOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.fieldDateListNotNullColKey);\n            for (java.util.Date fieldDateListNotNullItem : fieldDateListNotNullList) {\n                if (fieldDateListNotNullItem == null) {\n                    fieldDateListNotNullOsList.addNull();\n                } else {\n                    fieldDateListNotNullOsList.addDate(fieldDateListNotNullItem);\n                }\n            }\n        }\n\n        RealmList<java.util.Date> fieldDateListNullList = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldDateListNull();\n        if (fieldDateListNullList != null) {\n            OsList fieldDateListNullOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.fieldDateListNullColKey);\n            for (java.util.Date fieldDateListNullItem : fieldDateListNullList) {\n                if (fieldDateListNullItem == null) {\n                    fieldDateListNullOsList.addNull();\n                } else {\n                    fieldDateListNullOsList.addDate(fieldDateListNullItem);\n                }\n            }\n        }\n\n        RealmList<org.bson.types.Decimal128> fieldDecimal128ListNotNullList = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldDecimal128ListNotNull();\n        if (fieldDecimal128ListNotNullList != null) {\n            OsList fieldDecimal128ListNotNullOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.fieldDecimal128ListNotNullColKey);\n            for (org.bson.types.Decimal128 fieldDecimal128ListNotNullItem : fieldDecimal128ListNotNullList) {\n                if (fieldDecimal128ListNotNullItem == null) {\n                    fieldDecimal128ListNotNullOsList.addNull();\n                } else {\n                    fieldDecimal128ListNotNullOsList.addDecimal128(fieldDecimal128ListNotNullItem);\n                }\n            }\n        }\n\n        RealmList<org.bson.types.Decimal128> fieldDecimal128ListNullList = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldDecimal128ListNull();\n        if (fieldDecimal128ListNullList != null) {\n            OsList fieldDecimal128ListNullOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.fieldDecimal128ListNullColKey);\n            for (org.bson.types.Decimal128 fieldDecimal128ListNullItem : fieldDecimal128ListNullList) {\n                if (fieldDecimal128ListNullItem == null) {\n                    fieldDecimal128ListNullOsList.addNull();\n                } else {\n                    fieldDecimal128ListNullOsList.addDecimal128(fieldDecimal128ListNullItem);\n                }\n            }\n        }\n\n        RealmList<org.bson.types.ObjectId> fieldObjectIdListNotNullList = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldObjectIdListNotNull();\n        if (fieldObjectIdListNotNullList != null) {\n            OsList fieldObjectIdListNotNullOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.fieldObjectIdListNotNullColKey);\n            for (org.bson.types.ObjectId fieldObjectIdListNotNullItem : fieldObjectIdListNotNullList) {\n                if (fieldObjectIdListNotNullItem == null) {\n                    fieldObjectIdListNotNullOsList.addNull();\n                } else {\n                    fieldObjectIdListNotNullOsList.addObjectId(fieldObjectIdListNotNullItem);\n                }\n            }\n        }\n\n        RealmList<org.bson.types.ObjectId> fieldObjectIdListNullList = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldObjectIdListNull();\n        if (fieldObjectIdListNullList != null) {\n            OsList fieldObjectIdListNullOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.fieldObjectIdListNullColKey);\n            for (org.bson.types.ObjectId fieldObjectIdListNullItem : fieldObjectIdListNullList) {\n                if (fieldObjectIdListNullItem == null) {\n                    fieldObjectIdListNullOsList.addNull();\n                } else {\n                    fieldObjectIdListNullOsList.addObjectId(fieldObjectIdListNullItem);\n                }\n            }\n        }\n        return objKey;\n    }\n\n    public static void insert(Realm realm, Iterator<? extends RealmModel> objects, Map<RealmModel,Long> cache) {\n        Table table = realm.getTable(some.test.NullTypes.class);\n        long tableNativePtr = table.getNativePtr();\n        NullTypesColumnInfo columnInfo = (NullTypesColumnInfo) realm.getSchema().getColumnInfo(some.test.NullTypes.class);\n        some.test.NullTypes object = null;\n        while (objects.hasNext()) {\n            object = (some.test.NullTypes) objects.next();\n            if (cache.containsKey(object)) {\n                continue;\n            }\n            if (object instanceof RealmObjectProxy && !RealmObject.isFrozen(object) && ((RealmObjectProxy) object).realmGet$proxyState().getRealm$realm() != null && ((RealmObjectProxy) object).realmGet$proxyState().getRealm$realm().getPath().equals(realm.getPath())) {\n                cache.put(object, ((RealmObjectProxy) object).realmGet$proxyState().getRow$realm().getObjectKey());\n                continue;\n            }\n            long objKey = OsObject.createRow(table);\n            cache.put(object, objKey);\n            String realmGet$fieldStringNotNull = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldStringNotNull();\n            if (realmGet$fieldStringNotNull != null) {\n                Table.nativeSetString(tableNativePtr, columnInfo.fieldStringNotNullColKey, objKey, realmGet$fieldStringNotNull, false);\n            }\n            String realmGet$fieldStringNull = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldStringNull();\n            if (realmGet$fieldStringNull != null) {\n                Table.nativeSetString(tableNativePtr, columnInfo.fieldStringNullColKey, objKey, realmGet$fieldStringNull, false);\n            }\n            Boolean realmGet$fieldBooleanNotNull = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldBooleanNotNull();\n            if (realmGet$fieldBooleanNotNull != null) {\n                Table.nativeSetBoolean(tableNativePtr, columnInfo.fieldBooleanNotNullColKey, objKey, realmGet$fieldBooleanNotNull, false);\n            }\n            Boolean realmGet$fieldBooleanNull = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldBooleanNull();\n            if (realmGet$fieldBooleanNull != null) {\n                Table.nativeSetBoolean(tableNativePtr, columnInfo.fieldBooleanNullColKey, objKey, realmGet$fieldBooleanNull, false);\n            }\n            byte[] realmGet$fieldBytesNotNull = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldBytesNotNull();\n            if (realmGet$fieldBytesNotNull != null) {\n                Table.nativeSetByteArray(tableNativePtr, columnInfo.fieldBytesNotNullColKey, objKey, realmGet$fieldBytesNotNull, false);\n            }\n            byte[] realmGet$fieldBytesNull = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldBytesNull();\n            if (realmGet$fieldBytesNull != null) {\n                Table.nativeSetByteArray(tableNativePtr, columnInfo.fieldBytesNullColKey, objKey, realmGet$fieldBytesNull, false);\n            }\n            Number realmGet$fieldByteNotNull = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldByteNotNull();\n            if (realmGet$fieldByteNotNull != null) {\n                Table.nativeSetLong(tableNativePtr, columnInfo.fieldByteNotNullColKey, objKey, realmGet$fieldByteNotNull.longValue(), false);\n            }\n            Number realmGet$fieldByteNull = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldByteNull();\n            if (realmGet$fieldByteNull != null) {\n                Table.nativeSetLong(tableNativePtr, columnInfo.fieldByteNullColKey, objKey, realmGet$fieldByteNull.longValue(), false);\n            }\n            Number realmGet$fieldShortNotNull = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldShortNotNull();\n            if (realmGet$fieldShortNotNull != null) {\n                Table.nativeSetLong(tableNativePtr, columnInfo.fieldShortNotNullColKey, objKey, realmGet$fieldShortNotNull.longValue(), false);\n            }\n            Number realmGet$fieldShortNull = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldShortNull();\n            if (realmGet$fieldShortNull != null) {\n                Table.nativeSetLong(tableNativePtr, columnInfo.fieldShortNullColKey, objKey, realmGet$fieldShortNull.longValue(), false);\n            }\n            Number realmGet$fieldIntegerNotNull = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldIntegerNotNull();\n            if (realmGet$fieldIntegerNotNull != null) {\n                Table.nativeSetLong(tableNativePtr, columnInfo.fieldIntegerNotNullColKey, objKey, realmGet$fieldIntegerNotNull.longValue(), false);\n            }\n            Number realmGet$fieldIntegerNull = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldIntegerNull();\n            if (realmGet$fieldIntegerNull != null) {\n                Table.nativeSetLong(tableNativePtr, columnInfo.fieldIntegerNullColKey, objKey, realmGet$fieldIntegerNull.longValue(), false);\n            }\n            Number realmGet$fieldLongNotNull = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldLongNotNull();\n            if (realmGet$fieldLongNotNull != null) {\n                Table.nativeSetLong(tableNativePtr, columnInfo.fieldLongNotNullColKey, objKey, realmGet$fieldLongNotNull.longValue(), false);\n            }\n            Number realmGet$fieldLongNull = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldLongNull();\n            if (realmGet$fieldLongNull != null) {\n                Table.nativeSetLong(tableNativePtr, columnInfo.fieldLongNullColKey, objKey, realmGet$fieldLongNull.longValue(), false);\n            }\n            Float realmGet$fieldFloatNotNull = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldFloatNotNull();\n            if (realmGet$fieldFloatNotNull != null) {\n                Table.nativeSetFloat(tableNativePtr, columnInfo.fieldFloatNotNullColKey, objKey, realmGet$fieldFloatNotNull, false);\n            }\n            Float realmGet$fieldFloatNull = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldFloatNull();\n            if (realmGet$fieldFloatNull != null) {\n                Table.nativeSetFloat(tableNativePtr, columnInfo.fieldFloatNullColKey, objKey, realmGet$fieldFloatNull, false);\n            }\n            Double realmGet$fieldDoubleNotNull = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldDoubleNotNull();\n            if (realmGet$fieldDoubleNotNull != null) {\n                Table.nativeSetDouble(tableNativePtr, columnInfo.fieldDoubleNotNullColKey, objKey, realmGet$fieldDoubleNotNull, false);\n            }\n            Double realmGet$fieldDoubleNull = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldDoubleNull();\n            if (realmGet$fieldDoubleNull != null) {\n                Table.nativeSetDouble(tableNativePtr, columnInfo.fieldDoubleNullColKey, objKey, realmGet$fieldDoubleNull, false);\n            }\n            java.util.Date realmGet$fieldDateNotNull = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldDateNotNull();\n            if (realmGet$fieldDateNotNull != null) {\n                Table.nativeSetTimestamp(tableNativePtr, columnInfo.fieldDateNotNullColKey, objKey, realmGet$fieldDateNotNull.getTime(), false);\n            }\n            java.util.Date realmGet$fieldDateNull = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldDateNull();\n            if (realmGet$fieldDateNull != null) {\n                Table.nativeSetTimestamp(tableNativePtr, columnInfo.fieldDateNullColKey, objKey, realmGet$fieldDateNull.getTime(), false);\n            }\n            org.bson.types.Decimal128 realmGet$fieldDecimal128NotNull = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldDecimal128NotNull();\n            if (realmGet$fieldDecimal128NotNull != null) {\n                Table.nativeSetDecimal128(tableNativePtr, columnInfo.fieldDecimal128NotNullColKey, objKey, realmGet$fieldDecimal128NotNull.getLow(), realmGet$fieldDecimal128NotNull.getHigh(), false);\n            }\n            org.bson.types.Decimal128 realmGet$fieldDecimal128Null = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldDecimal128Null();\n            if (realmGet$fieldDecimal128Null != null) {\n                Table.nativeSetDecimal128(tableNativePtr, columnInfo.fieldDecimal128NullColKey, objKey, realmGet$fieldDecimal128Null.getLow(), realmGet$fieldDecimal128Null.getHigh(), false);\n            }\n            org.bson.types.ObjectId realmGet$fieldObjectIdNotNull = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldObjectIdNotNull();\n            if (realmGet$fieldObjectIdNotNull != null) {\n                Table.nativeSetObjectId(tableNativePtr, columnInfo.fieldObjectIdNotNullColKey, objKey, realmGet$fieldObjectIdNotNull.toString(), false);\n            }\n            org.bson.types.ObjectId realmGet$fieldObjectIdNull = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldObjectIdNull();\n            if (realmGet$fieldObjectIdNull != null) {\n                Table.nativeSetObjectId(tableNativePtr, columnInfo.fieldObjectIdNullColKey, objKey, realmGet$fieldObjectIdNull.toString(), false);\n            }\n\n            some.test.NullTypes fieldObjectNullObj = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldObjectNull();\n            if (fieldObjectNullObj != null) {\n                Long cachefieldObjectNull = cache.get(fieldObjectNullObj);\n                if (cachefieldObjectNull == null) {\n                    cachefieldObjectNull = some_test_NullTypesRealmProxy.insert(realm, fieldObjectNullObj, cache);\n                }\n                Table.nativeSetLink(tableNativePtr, columnInfo.fieldObjectNullColKey, objKey, cachefieldObjectNull, false);\n            }\n\n            RealmList<java.lang.String> fieldStringListNotNullList = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldStringListNotNull();\n            if (fieldStringListNotNullList != null) {\n                OsList fieldStringListNotNullOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.fieldStringListNotNullColKey);\n                for (java.lang.String fieldStringListNotNullItem : fieldStringListNotNullList) {\n                    if (fieldStringListNotNullItem == null) {\n                        fieldStringListNotNullOsList.addNull();\n                    } else {\n                        fieldStringListNotNullOsList.addString(fieldStringListNotNullItem);\n                    }\n                }\n            }\n\n            RealmList<java.lang.String> fieldStringListNullList = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldStringListNull();\n            if (fieldStringListNullList != null) {\n                OsList fieldStringListNullOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.fieldStringListNullColKey);\n                for (java.lang.String fieldStringListNullItem : fieldStringListNullList) {\n                    if (fieldStringListNullItem == null) {\n                        fieldStringListNullOsList.addNull();\n                    } else {\n                        fieldStringListNullOsList.addString(fieldStringListNullItem);\n                    }\n                }\n            }\n\n            RealmList<byte[]> fieldBinaryListNotNullList = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldBinaryListNotNull();\n            if (fieldBinaryListNotNullList != null) {\n                OsList fieldBinaryListNotNullOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.fieldBinaryListNotNullColKey);\n                for (byte[] fieldBinaryListNotNullItem : fieldBinaryListNotNullList) {\n                    if (fieldBinaryListNotNullItem == null) {\n                        fieldBinaryListNotNullOsList.addNull();\n                    } else {\n                        fieldBinaryListNotNullOsList.addBinary(fieldBinaryListNotNullItem);\n                    }\n                }\n            }\n\n            RealmList<byte[]> fieldBinaryListNullList = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldBinaryListNull();\n            if (fieldBinaryListNullList != null) {\n                OsList fieldBinaryListNullOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.fieldBinaryListNullColKey);\n                for (byte[] fieldBinaryListNullItem : fieldBinaryListNullList) {\n                    if (fieldBinaryListNullItem == null) {\n                        fieldBinaryListNullOsList.addNull();\n                    } else {\n                        fieldBinaryListNullOsList.addBinary(fieldBinaryListNullItem);\n                    }\n                }\n            }\n\n            RealmList<java.lang.Boolean> fieldBooleanListNotNullList = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldBooleanListNotNull();\n            if (fieldBooleanListNotNullList != null) {\n                OsList fieldBooleanListNotNullOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.fieldBooleanListNotNullColKey);\n                for (java.lang.Boolean fieldBooleanListNotNullItem : fieldBooleanListNotNullList) {\n                    if (fieldBooleanListNotNullItem == null) {\n                        fieldBooleanListNotNullOsList.addNull();\n                    } else {\n                        fieldBooleanListNotNullOsList.addBoolean(fieldBooleanListNotNullItem);\n                    }\n                }\n            }\n\n            RealmList<java.lang.Boolean> fieldBooleanListNullList = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldBooleanListNull();\n            if (fieldBooleanListNullList != null) {\n                OsList fieldBooleanListNullOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.fieldBooleanListNullColKey);\n                for (java.lang.Boolean fieldBooleanListNullItem : fieldBooleanListNullList) {\n                    if (fieldBooleanListNullItem == null) {\n                        fieldBooleanListNullOsList.addNull();\n                    } else {\n                        fieldBooleanListNullOsList.addBoolean(fieldBooleanListNullItem);\n                    }\n                }\n            }\n\n            RealmList<java.lang.Long> fieldLongListNotNullList = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldLongListNotNull();\n            if (fieldLongListNotNullList != null) {\n                OsList fieldLongListNotNullOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.fieldLongListNotNullColKey);\n                for (java.lang.Long fieldLongListNotNullItem : fieldLongListNotNullList) {\n                    if (fieldLongListNotNullItem == null) {\n                        fieldLongListNotNullOsList.addNull();\n                    } else {\n                        fieldLongListNotNullOsList.addLong(fieldLongListNotNullItem.longValue());\n                    }\n                }\n            }\n\n            RealmList<java.lang.Long> fieldLongListNullList = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldLongListNull();\n            if (fieldLongListNullList != null) {\n                OsList fieldLongListNullOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.fieldLongListNullColKey);\n                for (java.lang.Long fieldLongListNullItem : fieldLongListNullList) {\n                    if (fieldLongListNullItem == null) {\n                        fieldLongListNullOsList.addNull();\n                    } else {\n                        fieldLongListNullOsList.addLong(fieldLongListNullItem.longValue());\n                    }\n                }\n            }\n\n            RealmList<java.lang.Integer> fieldIntegerListNotNullList = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldIntegerListNotNull();\n            if (fieldIntegerListNotNullList != null) {\n                OsList fieldIntegerListNotNullOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.fieldIntegerListNotNullColKey);\n                for (java.lang.Integer fieldIntegerListNotNullItem : fieldIntegerListNotNullList) {\n                    if (fieldIntegerListNotNullItem == null) {\n                        fieldIntegerListNotNullOsList.addNull();\n                    } else {\n                        fieldIntegerListNotNullOsList.addLong(fieldIntegerListNotNullItem.longValue());\n                    }\n                }\n            }\n\n            RealmList<java.lang.Integer> fieldIntegerListNullList = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldIntegerListNull();\n            if (fieldIntegerListNullList != null) {\n                OsList fieldIntegerListNullOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.fieldIntegerListNullColKey);\n                for (java.lang.Integer fieldIntegerListNullItem : fieldIntegerListNullList) {\n                    if (fieldIntegerListNullItem == null) {\n                        fieldIntegerListNullOsList.addNull();\n                    } else {\n                        fieldIntegerListNullOsList.addLong(fieldIntegerListNullItem.longValue());\n                    }\n                }\n            }\n\n            RealmList<java.lang.Short> fieldShortListNotNullList = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldShortListNotNull();\n            if (fieldShortListNotNullList != null) {\n                OsList fieldShortListNotNullOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.fieldShortListNotNullColKey);\n                for (java.lang.Short fieldShortListNotNullItem : fieldShortListNotNullList) {\n                    if (fieldShortListNotNullItem == null) {\n                        fieldShortListNotNullOsList.addNull();\n                    } else {\n                        fieldShortListNotNullOsList.addLong(fieldShortListNotNullItem.longValue());\n                    }\n                }\n            }\n\n            RealmList<java.lang.Short> fieldShortListNullList = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldShortListNull();\n            if (fieldShortListNullList != null) {\n                OsList fieldShortListNullOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.fieldShortListNullColKey);\n                for (java.lang.Short fieldShortListNullItem : fieldShortListNullList) {\n                    if (fieldShortListNullItem == null) {\n                        fieldShortListNullOsList.addNull();\n                    } else {\n                        fieldShortListNullOsList.addLong(fieldShortListNullItem.longValue());\n                    }\n                }\n            }\n\n            RealmList<java.lang.Byte> fieldByteListNotNullList = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldByteListNotNull();\n            if (fieldByteListNotNullList != null) {\n                OsList fieldByteListNotNullOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.fieldByteListNotNullColKey);\n                for (java.lang.Byte fieldByteListNotNullItem : fieldByteListNotNullList) {\n                    if (fieldByteListNotNullItem == null) {\n                        fieldByteListNotNullOsList.addNull();\n                    } else {\n                        fieldByteListNotNullOsList.addLong(fieldByteListNotNullItem.longValue());\n                    }\n                }\n            }\n\n            RealmList<java.lang.Byte> fieldByteListNullList = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldByteListNull();\n            if (fieldByteListNullList != null) {\n                OsList fieldByteListNullOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.fieldByteListNullColKey);\n                for (java.lang.Byte fieldByteListNullItem : fieldByteListNullList) {\n                    if (fieldByteListNullItem == null) {\n                        fieldByteListNullOsList.addNull();\n                    } else {\n                        fieldByteListNullOsList.addLong(fieldByteListNullItem.longValue());\n                    }\n                }\n            }\n\n            RealmList<java.lang.Double> fieldDoubleListNotNullList = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldDoubleListNotNull();\n            if (fieldDoubleListNotNullList != null) {\n                OsList fieldDoubleListNotNullOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.fieldDoubleListNotNullColKey);\n                for (java.lang.Double fieldDoubleListNotNullItem : fieldDoubleListNotNullList) {\n                    if (fieldDoubleListNotNullItem == null) {\n                        fieldDoubleListNotNullOsList.addNull();\n                    } else {\n                        fieldDoubleListNotNullOsList.addDouble(fieldDoubleListNotNullItem.doubleValue());\n                    }\n                }\n            }\n\n            RealmList<java.lang.Double> fieldDoubleListNullList = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldDoubleListNull();\n            if (fieldDoubleListNullList != null) {\n                OsList fieldDoubleListNullOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.fieldDoubleListNullColKey);\n                for (java.lang.Double fieldDoubleListNullItem : fieldDoubleListNullList) {\n                    if (fieldDoubleListNullItem == null) {\n                        fieldDoubleListNullOsList.addNull();\n                    } else {\n                        fieldDoubleListNullOsList.addDouble(fieldDoubleListNullItem.doubleValue());\n                    }\n                }\n            }\n\n            RealmList<java.lang.Float> fieldFloatListNotNullList = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldFloatListNotNull();\n            if (fieldFloatListNotNullList != null) {\n                OsList fieldFloatListNotNullOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.fieldFloatListNotNullColKey);\n                for (java.lang.Float fieldFloatListNotNullItem : fieldFloatListNotNullList) {\n                    if (fieldFloatListNotNullItem == null) {\n                        fieldFloatListNotNullOsList.addNull();\n                    } else {\n                        fieldFloatListNotNullOsList.addFloat(fieldFloatListNotNullItem.floatValue());\n                    }\n                }\n            }\n\n            RealmList<java.lang.Float> fieldFloatListNullList = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldFloatListNull();\n            if (fieldFloatListNullList != null) {\n                OsList fieldFloatListNullOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.fieldFloatListNullColKey);\n                for (java.lang.Float fieldFloatListNullItem : fieldFloatListNullList) {\n                    if (fieldFloatListNullItem == null) {\n                        fieldFloatListNullOsList.addNull();\n                    } else {\n                        fieldFloatListNullOsList.addFloat(fieldFloatListNullItem.floatValue());\n                    }\n                }\n            }\n\n            RealmList<java.util.Date> fieldDateListNotNullList = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldDateListNotNull();\n            if (fieldDateListNotNullList != null) {\n                OsList fieldDateListNotNullOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.fieldDateListNotNullColKey);\n                for (java.util.Date fieldDateListNotNullItem : fieldDateListNotNullList) {\n                    if (fieldDateListNotNullItem == null) {\n                        fieldDateListNotNullOsList.addNull();\n                    } else {\n                        fieldDateListNotNullOsList.addDate(fieldDateListNotNullItem);\n                    }\n                }\n            }\n\n            RealmList<java.util.Date> fieldDateListNullList = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldDateListNull();\n            if (fieldDateListNullList != null) {\n                OsList fieldDateListNullOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.fieldDateListNullColKey);\n                for (java.util.Date fieldDateListNullItem : fieldDateListNullList) {\n                    if (fieldDateListNullItem == null) {\n                        fieldDateListNullOsList.addNull();\n                    } else {\n                        fieldDateListNullOsList.addDate(fieldDateListNullItem);\n                    }\n                }\n            }\n\n            RealmList<org.bson.types.Decimal128> fieldDecimal128ListNotNullList = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldDecimal128ListNotNull();\n            if (fieldDecimal128ListNotNullList != null) {\n                OsList fieldDecimal128ListNotNullOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.fieldDecimal128ListNotNullColKey);\n                for (org.bson.types.Decimal128 fieldDecimal128ListNotNullItem : fieldDecimal128ListNotNullList) {\n                    if (fieldDecimal128ListNotNullItem == null) {\n                        fieldDecimal128ListNotNullOsList.addNull();\n                    } else {\n                        fieldDecimal128ListNotNullOsList.addDecimal128(fieldDecimal128ListNotNullItem);\n                    }\n                }\n            }\n\n            RealmList<org.bson.types.Decimal128> fieldDecimal128ListNullList = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldDecimal128ListNull();\n            if (fieldDecimal128ListNullList != null) {\n                OsList fieldDecimal128ListNullOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.fieldDecimal128ListNullColKey);\n                for (org.bson.types.Decimal128 fieldDecimal128ListNullItem : fieldDecimal128ListNullList) {\n                    if (fieldDecimal128ListNullItem == null) {\n                        fieldDecimal128ListNullOsList.addNull();\n                    } else {\n                        fieldDecimal128ListNullOsList.addDecimal128(fieldDecimal128ListNullItem);\n                    }\n                }\n            }\n\n            RealmList<org.bson.types.ObjectId> fieldObjectIdListNotNullList = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldObjectIdListNotNull();\n            if (fieldObjectIdListNotNullList != null) {\n                OsList fieldObjectIdListNotNullOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.fieldObjectIdListNotNullColKey);\n                for (org.bson.types.ObjectId fieldObjectIdListNotNullItem : fieldObjectIdListNotNullList) {\n                    if (fieldObjectIdListNotNullItem == null) {\n                        fieldObjectIdListNotNullOsList.addNull();\n                    } else {\n                        fieldObjectIdListNotNullOsList.addObjectId(fieldObjectIdListNotNullItem);\n                    }\n                }\n            }\n\n            RealmList<org.bson.types.ObjectId> fieldObjectIdListNullList = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldObjectIdListNull();\n            if (fieldObjectIdListNullList != null) {\n                OsList fieldObjectIdListNullOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.fieldObjectIdListNullColKey);\n                for (org.bson.types.ObjectId fieldObjectIdListNullItem : fieldObjectIdListNullList) {\n                    if (fieldObjectIdListNullItem == null) {\n                        fieldObjectIdListNullOsList.addNull();\n                    } else {\n                        fieldObjectIdListNullOsList.addObjectId(fieldObjectIdListNullItem);\n                    }\n                }\n            }\n        }\n    }\n\n    public static long insertOrUpdate(Realm realm, some.test.NullTypes object, Map<RealmModel,Long> cache) {\n        if (object instanceof RealmObjectProxy && !RealmObject.isFrozen(object) && ((RealmObjectProxy) object).realmGet$proxyState().getRealm$realm() != null && ((RealmObjectProxy) object).realmGet$proxyState().getRealm$realm().getPath().equals(realm.getPath())) {\n            return ((RealmObjectProxy) object).realmGet$proxyState().getRow$realm().getObjectKey();\n        }\n        Table table = realm.getTable(some.test.NullTypes.class);\n        long tableNativePtr = table.getNativePtr();\n        NullTypesColumnInfo columnInfo = (NullTypesColumnInfo) realm.getSchema().getColumnInfo(some.test.NullTypes.class);\n        long objKey = OsObject.createRow(table);\n        cache.put(object, objKey);\n        String realmGet$fieldStringNotNull = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldStringNotNull();\n        if (realmGet$fieldStringNotNull != null) {\n            Table.nativeSetString(tableNativePtr, columnInfo.fieldStringNotNullColKey, objKey, realmGet$fieldStringNotNull, false);\n        } else {\n            Table.nativeSetNull(tableNativePtr, columnInfo.fieldStringNotNullColKey, objKey, false);\n        }\n        String realmGet$fieldStringNull = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldStringNull();\n        if (realmGet$fieldStringNull != null) {\n            Table.nativeSetString(tableNativePtr, columnInfo.fieldStringNullColKey, objKey, realmGet$fieldStringNull, false);\n        } else {\n            Table.nativeSetNull(tableNativePtr, columnInfo.fieldStringNullColKey, objKey, false);\n        }\n        Boolean realmGet$fieldBooleanNotNull = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldBooleanNotNull();\n        if (realmGet$fieldBooleanNotNull != null) {\n            Table.nativeSetBoolean(tableNativePtr, columnInfo.fieldBooleanNotNullColKey, objKey, realmGet$fieldBooleanNotNull, false);\n        } else {\n            Table.nativeSetNull(tableNativePtr, columnInfo.fieldBooleanNotNullColKey, objKey, false);\n        }\n        Boolean realmGet$fieldBooleanNull = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldBooleanNull();\n        if (realmGet$fieldBooleanNull != null) {\n            Table.nativeSetBoolean(tableNativePtr, columnInfo.fieldBooleanNullColKey, objKey, realmGet$fieldBooleanNull, false);\n        } else {\n            Table.nativeSetNull(tableNativePtr, columnInfo.fieldBooleanNullColKey, objKey, false);\n        }\n        byte[] realmGet$fieldBytesNotNull = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldBytesNotNull();\n        if (realmGet$fieldBytesNotNull != null) {\n            Table.nativeSetByteArray(tableNativePtr, columnInfo.fieldBytesNotNullColKey, objKey, realmGet$fieldBytesNotNull, false);\n        } else {\n            Table.nativeSetNull(tableNativePtr, columnInfo.fieldBytesNotNullColKey, objKey, false);\n        }\n        byte[] realmGet$fieldBytesNull = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldBytesNull();\n        if (realmGet$fieldBytesNull != null) {\n            Table.nativeSetByteArray(tableNativePtr, columnInfo.fieldBytesNullColKey, objKey, realmGet$fieldBytesNull, false);\n        } else {\n            Table.nativeSetNull(tableNativePtr, columnInfo.fieldBytesNullColKey, objKey, false);\n        }\n        Number realmGet$fieldByteNotNull = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldByteNotNull();\n        if (realmGet$fieldByteNotNull != null) {\n            Table.nativeSetLong(tableNativePtr, columnInfo.fieldByteNotNullColKey, objKey, realmGet$fieldByteNotNull.longValue(), false);\n        } else {\n            Table.nativeSetNull(tableNativePtr, columnInfo.fieldByteNotNullColKey, objKey, false);\n        }\n        Number realmGet$fieldByteNull = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldByteNull();\n        if (realmGet$fieldByteNull != null) {\n            Table.nativeSetLong(tableNativePtr, columnInfo.fieldByteNullColKey, objKey, realmGet$fieldByteNull.longValue(), false);\n        } else {\n            Table.nativeSetNull(tableNativePtr, columnInfo.fieldByteNullColKey, objKey, false);\n        }\n        Number realmGet$fieldShortNotNull = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldShortNotNull();\n        if (realmGet$fieldShortNotNull != null) {\n            Table.nativeSetLong(tableNativePtr, columnInfo.fieldShortNotNullColKey, objKey, realmGet$fieldShortNotNull.longValue(), false);\n        } else {\n            Table.nativeSetNull(tableNativePtr, columnInfo.fieldShortNotNullColKey, objKey, false);\n        }\n        Number realmGet$fieldShortNull = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldShortNull();\n        if (realmGet$fieldShortNull != null) {\n            Table.nativeSetLong(tableNativePtr, columnInfo.fieldShortNullColKey, objKey, realmGet$fieldShortNull.longValue(), false);\n        } else {\n            Table.nativeSetNull(tableNativePtr, columnInfo.fieldShortNullColKey, objKey, false);\n        }\n        Number realmGet$fieldIntegerNotNull = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldIntegerNotNull();\n        if (realmGet$fieldIntegerNotNull != null) {\n            Table.nativeSetLong(tableNativePtr, columnInfo.fieldIntegerNotNullColKey, objKey, realmGet$fieldIntegerNotNull.longValue(), false);\n        } else {\n            Table.nativeSetNull(tableNativePtr, columnInfo.fieldIntegerNotNullColKey, objKey, false);\n        }\n        Number realmGet$fieldIntegerNull = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldIntegerNull();\n        if (realmGet$fieldIntegerNull != null) {\n            Table.nativeSetLong(tableNativePtr, columnInfo.fieldIntegerNullColKey, objKey, realmGet$fieldIntegerNull.longValue(), false);\n        } else {\n            Table.nativeSetNull(tableNativePtr, columnInfo.fieldIntegerNullColKey, objKey, false);\n        }\n        Number realmGet$fieldLongNotNull = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldLongNotNull();\n        if (realmGet$fieldLongNotNull != null) {\n            Table.nativeSetLong(tableNativePtr, columnInfo.fieldLongNotNullColKey, objKey, realmGet$fieldLongNotNull.longValue(), false);\n        } else {\n            Table.nativeSetNull(tableNativePtr, columnInfo.fieldLongNotNullColKey, objKey, false);\n        }\n        Number realmGet$fieldLongNull = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldLongNull();\n        if (realmGet$fieldLongNull != null) {\n            Table.nativeSetLong(tableNativePtr, columnInfo.fieldLongNullColKey, objKey, realmGet$fieldLongNull.longValue(), false);\n        } else {\n            Table.nativeSetNull(tableNativePtr, columnInfo.fieldLongNullColKey, objKey, false);\n        }\n        Float realmGet$fieldFloatNotNull = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldFloatNotNull();\n        if (realmGet$fieldFloatNotNull != null) {\n            Table.nativeSetFloat(tableNativePtr, columnInfo.fieldFloatNotNullColKey, objKey, realmGet$fieldFloatNotNull, false);\n        } else {\n            Table.nativeSetNull(tableNativePtr, columnInfo.fieldFloatNotNullColKey, objKey, false);\n        }\n        Float realmGet$fieldFloatNull = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldFloatNull();\n        if (realmGet$fieldFloatNull != null) {\n            Table.nativeSetFloat(tableNativePtr, columnInfo.fieldFloatNullColKey, objKey, realmGet$fieldFloatNull, false);\n        } else {\n            Table.nativeSetNull(tableNativePtr, columnInfo.fieldFloatNullColKey, objKey, false);\n        }\n        Double realmGet$fieldDoubleNotNull = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldDoubleNotNull();\n        if (realmGet$fieldDoubleNotNull != null) {\n            Table.nativeSetDouble(tableNativePtr, columnInfo.fieldDoubleNotNullColKey, objKey, realmGet$fieldDoubleNotNull, false);\n        } else {\n            Table.nativeSetNull(tableNativePtr, columnInfo.fieldDoubleNotNullColKey, objKey, false);\n        }\n        Double realmGet$fieldDoubleNull = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldDoubleNull();\n        if (realmGet$fieldDoubleNull != null) {\n            Table.nativeSetDouble(tableNativePtr, columnInfo.fieldDoubleNullColKey, objKey, realmGet$fieldDoubleNull, false);\n        } else {\n            Table.nativeSetNull(tableNativePtr, columnInfo.fieldDoubleNullColKey, objKey, false);\n        }\n        java.util.Date realmGet$fieldDateNotNull = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldDateNotNull();\n        if (realmGet$fieldDateNotNull != null) {\n            Table.nativeSetTimestamp(tableNativePtr, columnInfo.fieldDateNotNullColKey, objKey, realmGet$fieldDateNotNull.getTime(), false);\n        } else {\n            Table.nativeSetNull(tableNativePtr, columnInfo.fieldDateNotNullColKey, objKey, false);\n        }\n        java.util.Date realmGet$fieldDateNull = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldDateNull();\n        if (realmGet$fieldDateNull != null) {\n            Table.nativeSetTimestamp(tableNativePtr, columnInfo.fieldDateNullColKey, objKey, realmGet$fieldDateNull.getTime(), false);\n        } else {\n            Table.nativeSetNull(tableNativePtr, columnInfo.fieldDateNullColKey, objKey, false);\n        }\n        org.bson.types.Decimal128 realmGet$fieldDecimal128NotNull = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldDecimal128NotNull();\n        if (realmGet$fieldDecimal128NotNull != null) {\n            Table.nativeSetDecimal128(tableNativePtr, columnInfo.fieldDecimal128NotNullColKey, objKey, realmGet$fieldDecimal128NotNull.getLow(), realmGet$fieldDecimal128NotNull.getHigh(), false);\n        } else {\n            Table.nativeSetNull(tableNativePtr, columnInfo.fieldDecimal128NotNullColKey, objKey, false);\n        }\n        org.bson.types.Decimal128 realmGet$fieldDecimal128Null = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldDecimal128Null();\n        if (realmGet$fieldDecimal128Null != null) {\n            Table.nativeSetDecimal128(tableNativePtr, columnInfo.fieldDecimal128NullColKey, objKey, realmGet$fieldDecimal128Null.getLow(), realmGet$fieldDecimal128Null.getHigh(), false);\n        } else {\n            Table.nativeSetNull(tableNativePtr, columnInfo.fieldDecimal128NullColKey, objKey, false);\n        }\n        org.bson.types.ObjectId realmGet$fieldObjectIdNotNull = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldObjectIdNotNull();\n        if (realmGet$fieldObjectIdNotNull != null) {\n            Table.nativeSetObjectId(tableNativePtr, columnInfo.fieldObjectIdNotNullColKey, objKey, realmGet$fieldObjectIdNotNull.toString(), false);\n        } else {\n            Table.nativeSetNull(tableNativePtr, columnInfo.fieldObjectIdNotNullColKey, objKey, false);\n        }\n        org.bson.types.ObjectId realmGet$fieldObjectIdNull = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldObjectIdNull();\n        if (realmGet$fieldObjectIdNull != null) {\n            Table.nativeSetObjectId(tableNativePtr, columnInfo.fieldObjectIdNullColKey, objKey, realmGet$fieldObjectIdNull.toString(), false);\n        } else {\n            Table.nativeSetNull(tableNativePtr, columnInfo.fieldObjectIdNullColKey, objKey, false);\n        }\n\n        some.test.NullTypes fieldObjectNullObj = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldObjectNull();\n        if (fieldObjectNullObj != null) {\n            Long cachefieldObjectNull = cache.get(fieldObjectNullObj);\n            if (cachefieldObjectNull == null) {\n                cachefieldObjectNull = some_test_NullTypesRealmProxy.insertOrUpdate(realm, fieldObjectNullObj, cache);\n            }\n            Table.nativeSetLink(tableNativePtr, columnInfo.fieldObjectNullColKey, objKey, cachefieldObjectNull, false);\n        } else {\n            Table.nativeNullifyLink(tableNativePtr, columnInfo.fieldObjectNullColKey, objKey);\n        }\n\n        OsList fieldStringListNotNullOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.fieldStringListNotNullColKey);\n        fieldStringListNotNullOsList.removeAll();\n        RealmList<java.lang.String> fieldStringListNotNullList = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldStringListNotNull();\n        if (fieldStringListNotNullList != null) {\n            for (java.lang.String fieldStringListNotNullItem : fieldStringListNotNullList) {\n                if (fieldStringListNotNullItem == null) {\n                    fieldStringListNotNullOsList.addNull();\n                } else {\n                    fieldStringListNotNullOsList.addString(fieldStringListNotNullItem);\n                }\n            }\n        }\n\n\n        OsList fieldStringListNullOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.fieldStringListNullColKey);\n        fieldStringListNullOsList.removeAll();\n        RealmList<java.lang.String> fieldStringListNullList = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldStringListNull();\n        if (fieldStringListNullList != null) {\n            for (java.lang.String fieldStringListNullItem : fieldStringListNullList) {\n                if (fieldStringListNullItem == null) {\n                    fieldStringListNullOsList.addNull();\n                } else {\n                    fieldStringListNullOsList.addString(fieldStringListNullItem);\n                }\n            }\n        }\n\n\n        OsList fieldBinaryListNotNullOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.fieldBinaryListNotNullColKey);\n        fieldBinaryListNotNullOsList.removeAll();\n        RealmList<byte[]> fieldBinaryListNotNullList = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldBinaryListNotNull();\n        if (fieldBinaryListNotNullList != null) {\n            for (byte[] fieldBinaryListNotNullItem : fieldBinaryListNotNullList) {\n                if (fieldBinaryListNotNullItem == null) {\n                    fieldBinaryListNotNullOsList.addNull();\n                } else {\n                    fieldBinaryListNotNullOsList.addBinary(fieldBinaryListNotNullItem);\n                }\n            }\n        }\n\n\n        OsList fieldBinaryListNullOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.fieldBinaryListNullColKey);\n        fieldBinaryListNullOsList.removeAll();\n        RealmList<byte[]> fieldBinaryListNullList = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldBinaryListNull();\n        if (fieldBinaryListNullList != null) {\n            for (byte[] fieldBinaryListNullItem : fieldBinaryListNullList) {\n                if (fieldBinaryListNullItem == null) {\n                    fieldBinaryListNullOsList.addNull();\n                } else {\n                    fieldBinaryListNullOsList.addBinary(fieldBinaryListNullItem);\n                }\n            }\n        }\n\n\n        OsList fieldBooleanListNotNullOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.fieldBooleanListNotNullColKey);\n        fieldBooleanListNotNullOsList.removeAll();\n        RealmList<java.lang.Boolean> fieldBooleanListNotNullList = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldBooleanListNotNull();\n        if (fieldBooleanListNotNullList != null) {\n            for (java.lang.Boolean fieldBooleanListNotNullItem : fieldBooleanListNotNullList) {\n                if (fieldBooleanListNotNullItem == null) {\n                    fieldBooleanListNotNullOsList.addNull();\n                } else {\n                    fieldBooleanListNotNullOsList.addBoolean(fieldBooleanListNotNullItem);\n                }\n            }\n        }\n\n\n        OsList fieldBooleanListNullOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.fieldBooleanListNullColKey);\n        fieldBooleanListNullOsList.removeAll();\n        RealmList<java.lang.Boolean> fieldBooleanListNullList = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldBooleanListNull();\n        if (fieldBooleanListNullList != null) {\n            for (java.lang.Boolean fieldBooleanListNullItem : fieldBooleanListNullList) {\n                if (fieldBooleanListNullItem == null) {\n                    fieldBooleanListNullOsList.addNull();\n                } else {\n                    fieldBooleanListNullOsList.addBoolean(fieldBooleanListNullItem);\n                }\n            }\n        }\n\n\n        OsList fieldLongListNotNullOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.fieldLongListNotNullColKey);\n        fieldLongListNotNullOsList.removeAll();\n        RealmList<java.lang.Long> fieldLongListNotNullList = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldLongListNotNull();\n        if (fieldLongListNotNullList != null) {\n            for (java.lang.Long fieldLongListNotNullItem : fieldLongListNotNullList) {\n                if (fieldLongListNotNullItem == null) {\n                    fieldLongListNotNullOsList.addNull();\n                } else {\n                    fieldLongListNotNullOsList.addLong(fieldLongListNotNullItem.longValue());\n                }\n            }\n        }\n\n\n        OsList fieldLongListNullOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.fieldLongListNullColKey);\n        fieldLongListNullOsList.removeAll();\n        RealmList<java.lang.Long> fieldLongListNullList = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldLongListNull();\n        if (fieldLongListNullList != null) {\n            for (java.lang.Long fieldLongListNullItem : fieldLongListNullList) {\n                if (fieldLongListNullItem == null) {\n                    fieldLongListNullOsList.addNull();\n                } else {\n                    fieldLongListNullOsList.addLong(fieldLongListNullItem.longValue());\n                }\n            }\n        }\n\n\n        OsList fieldIntegerListNotNullOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.fieldIntegerListNotNullColKey);\n        fieldIntegerListNotNullOsList.removeAll();\n        RealmList<java.lang.Integer> fieldIntegerListNotNullList = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldIntegerListNotNull();\n        if (fieldIntegerListNotNullList != null) {\n            for (java.lang.Integer fieldIntegerListNotNullItem : fieldIntegerListNotNullList) {\n                if (fieldIntegerListNotNullItem == null) {\n                    fieldIntegerListNotNullOsList.addNull();\n                } else {\n                    fieldIntegerListNotNullOsList.addLong(fieldIntegerListNotNullItem.longValue());\n                }\n            }\n        }\n\n\n        OsList fieldIntegerListNullOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.fieldIntegerListNullColKey);\n        fieldIntegerListNullOsList.removeAll();\n        RealmList<java.lang.Integer> fieldIntegerListNullList = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldIntegerListNull();\n        if (fieldIntegerListNullList != null) {\n            for (java.lang.Integer fieldIntegerListNullItem : fieldIntegerListNullList) {\n                if (fieldIntegerListNullItem == null) {\n                    fieldIntegerListNullOsList.addNull();\n                } else {\n                    fieldIntegerListNullOsList.addLong(fieldIntegerListNullItem.longValue());\n                }\n            }\n        }\n\n\n        OsList fieldShortListNotNullOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.fieldShortListNotNullColKey);\n        fieldShortListNotNullOsList.removeAll();\n        RealmList<java.lang.Short> fieldShortListNotNullList = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldShortListNotNull();\n        if (fieldShortListNotNullList != null) {\n            for (java.lang.Short fieldShortListNotNullItem : fieldShortListNotNullList) {\n                if (fieldShortListNotNullItem == null) {\n                    fieldShortListNotNullOsList.addNull();\n                } else {\n                    fieldShortListNotNullOsList.addLong(fieldShortListNotNullItem.longValue());\n                }\n            }\n        }\n\n\n        OsList fieldShortListNullOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.fieldShortListNullColKey);\n        fieldShortListNullOsList.removeAll();\n        RealmList<java.lang.Short> fieldShortListNullList = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldShortListNull();\n        if (fieldShortListNullList != null) {\n            for (java.lang.Short fieldShortListNullItem : fieldShortListNullList) {\n                if (fieldShortListNullItem == null) {\n                    fieldShortListNullOsList.addNull();\n                } else {\n                    fieldShortListNullOsList.addLong(fieldShortListNullItem.longValue());\n                }\n            }\n        }\n\n\n        OsList fieldByteListNotNullOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.fieldByteListNotNullColKey);\n        fieldByteListNotNullOsList.removeAll();\n        RealmList<java.lang.Byte> fieldByteListNotNullList = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldByteListNotNull();\n        if (fieldByteListNotNullList != null) {\n            for (java.lang.Byte fieldByteListNotNullItem : fieldByteListNotNullList) {\n                if (fieldByteListNotNullItem == null) {\n                    fieldByteListNotNullOsList.addNull();\n                } else {\n                    fieldByteListNotNullOsList.addLong(fieldByteListNotNullItem.longValue());\n                }\n            }\n        }\n\n\n        OsList fieldByteListNullOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.fieldByteListNullColKey);\n        fieldByteListNullOsList.removeAll();\n        RealmList<java.lang.Byte> fieldByteListNullList = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldByteListNull();\n        if (fieldByteListNullList != null) {\n            for (java.lang.Byte fieldByteListNullItem : fieldByteListNullList) {\n                if (fieldByteListNullItem == null) {\n                    fieldByteListNullOsList.addNull();\n                } else {\n                    fieldByteListNullOsList.addLong(fieldByteListNullItem.longValue());\n                }\n            }\n        }\n\n\n        OsList fieldDoubleListNotNullOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.fieldDoubleListNotNullColKey);\n        fieldDoubleListNotNullOsList.removeAll();\n        RealmList<java.lang.Double> fieldDoubleListNotNullList = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldDoubleListNotNull();\n        if (fieldDoubleListNotNullList != null) {\n            for (java.lang.Double fieldDoubleListNotNullItem : fieldDoubleListNotNullList) {\n                if (fieldDoubleListNotNullItem == null) {\n                    fieldDoubleListNotNullOsList.addNull();\n                } else {\n                    fieldDoubleListNotNullOsList.addDouble(fieldDoubleListNotNullItem.doubleValue());\n                }\n            }\n        }\n\n\n        OsList fieldDoubleListNullOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.fieldDoubleListNullColKey);\n        fieldDoubleListNullOsList.removeAll();\n        RealmList<java.lang.Double> fieldDoubleListNullList = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldDoubleListNull();\n        if (fieldDoubleListNullList != null) {\n            for (java.lang.Double fieldDoubleListNullItem : fieldDoubleListNullList) {\n                if (fieldDoubleListNullItem == null) {\n                    fieldDoubleListNullOsList.addNull();\n                } else {\n                    fieldDoubleListNullOsList.addDouble(fieldDoubleListNullItem.doubleValue());\n                }\n            }\n        }\n\n\n        OsList fieldFloatListNotNullOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.fieldFloatListNotNullColKey);\n        fieldFloatListNotNullOsList.removeAll();\n        RealmList<java.lang.Float> fieldFloatListNotNullList = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldFloatListNotNull();\n        if (fieldFloatListNotNullList != null) {\n            for (java.lang.Float fieldFloatListNotNullItem : fieldFloatListNotNullList) {\n                if (fieldFloatListNotNullItem == null) {\n                    fieldFloatListNotNullOsList.addNull();\n                } else {\n                    fieldFloatListNotNullOsList.addFloat(fieldFloatListNotNullItem.floatValue());\n                }\n            }\n        }\n\n\n        OsList fieldFloatListNullOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.fieldFloatListNullColKey);\n        fieldFloatListNullOsList.removeAll();\n        RealmList<java.lang.Float> fieldFloatListNullList = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldFloatListNull();\n        if (fieldFloatListNullList != null) {\n            for (java.lang.Float fieldFloatListNullItem : fieldFloatListNullList) {\n                if (fieldFloatListNullItem == null) {\n                    fieldFloatListNullOsList.addNull();\n                } else {\n                    fieldFloatListNullOsList.addFloat(fieldFloatListNullItem.floatValue());\n                }\n            }\n        }\n\n\n        OsList fieldDateListNotNullOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.fieldDateListNotNullColKey);\n        fieldDateListNotNullOsList.removeAll();\n        RealmList<java.util.Date> fieldDateListNotNullList = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldDateListNotNull();\n        if (fieldDateListNotNullList != null) {\n            for (java.util.Date fieldDateListNotNullItem : fieldDateListNotNullList) {\n                if (fieldDateListNotNullItem == null) {\n                    fieldDateListNotNullOsList.addNull();\n                } else {\n                    fieldDateListNotNullOsList.addDate(fieldDateListNotNullItem);\n                }\n            }\n        }\n\n\n        OsList fieldDateListNullOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.fieldDateListNullColKey);\n        fieldDateListNullOsList.removeAll();\n        RealmList<java.util.Date> fieldDateListNullList = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldDateListNull();\n        if (fieldDateListNullList != null) {\n            for (java.util.Date fieldDateListNullItem : fieldDateListNullList) {\n                if (fieldDateListNullItem == null) {\n                    fieldDateListNullOsList.addNull();\n                } else {\n                    fieldDateListNullOsList.addDate(fieldDateListNullItem);\n                }\n            }\n        }\n\n\n        OsList fieldDecimal128ListNotNullOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.fieldDecimal128ListNotNullColKey);\n        fieldDecimal128ListNotNullOsList.removeAll();\n        RealmList<org.bson.types.Decimal128> fieldDecimal128ListNotNullList = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldDecimal128ListNotNull();\n        if (fieldDecimal128ListNotNullList != null) {\n            for (org.bson.types.Decimal128 fieldDecimal128ListNotNullItem : fieldDecimal128ListNotNullList) {\n                if (fieldDecimal128ListNotNullItem == null) {\n                    fieldDecimal128ListNotNullOsList.addNull();\n                } else {\n                    fieldDecimal128ListNotNullOsList.addDecimal128(fieldDecimal128ListNotNullItem);\n                }\n            }\n        }\n\n\n        OsList fieldDecimal128ListNullOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.fieldDecimal128ListNullColKey);\n        fieldDecimal128ListNullOsList.removeAll();\n        RealmList<org.bson.types.Decimal128> fieldDecimal128ListNullList = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldDecimal128ListNull();\n        if (fieldDecimal128ListNullList != null) {\n            for (org.bson.types.Decimal128 fieldDecimal128ListNullItem : fieldDecimal128ListNullList) {\n                if (fieldDecimal128ListNullItem == null) {\n                    fieldDecimal128ListNullOsList.addNull();\n                } else {\n                    fieldDecimal128ListNullOsList.addDecimal128(fieldDecimal128ListNullItem);\n                }\n            }\n        }\n\n\n        OsList fieldObjectIdListNotNullOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.fieldObjectIdListNotNullColKey);\n        fieldObjectIdListNotNullOsList.removeAll();\n        RealmList<org.bson.types.ObjectId> fieldObjectIdListNotNullList = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldObjectIdListNotNull();\n        if (fieldObjectIdListNotNullList != null) {\n            for (org.bson.types.ObjectId fieldObjectIdListNotNullItem : fieldObjectIdListNotNullList) {\n                if (fieldObjectIdListNotNullItem == null) {\n                    fieldObjectIdListNotNullOsList.addNull();\n                } else {\n                    fieldObjectIdListNotNullOsList.addObjectId(fieldObjectIdListNotNullItem);\n                }\n            }\n        }\n\n\n        OsList fieldObjectIdListNullOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.fieldObjectIdListNullColKey);\n        fieldObjectIdListNullOsList.removeAll();\n        RealmList<org.bson.types.ObjectId> fieldObjectIdListNullList = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldObjectIdListNull();\n        if (fieldObjectIdListNullList != null) {\n            for (org.bson.types.ObjectId fieldObjectIdListNullItem : fieldObjectIdListNullList) {\n                if (fieldObjectIdListNullItem == null) {\n                    fieldObjectIdListNullOsList.addNull();\n                } else {\n                    fieldObjectIdListNullOsList.addObjectId(fieldObjectIdListNullItem);\n                }\n            }\n        }\n\n        return objKey;\n    }\n\n    public static void insertOrUpdate(Realm realm, Iterator<? extends RealmModel> objects, Map<RealmModel,Long> cache) {\n        Table table = realm.getTable(some.test.NullTypes.class);\n        long tableNativePtr = table.getNativePtr();\n        NullTypesColumnInfo columnInfo = (NullTypesColumnInfo) realm.getSchema().getColumnInfo(some.test.NullTypes.class);\n        some.test.NullTypes object = null;\n        while (objects.hasNext()) {\n            object = (some.test.NullTypes) objects.next();\n            if (cache.containsKey(object)) {\n                continue;\n            }\n            if (object instanceof RealmObjectProxy && !RealmObject.isFrozen(object) && ((RealmObjectProxy) object).realmGet$proxyState().getRealm$realm() != null && ((RealmObjectProxy) object).realmGet$proxyState().getRealm$realm().getPath().equals(realm.getPath())) {\n                cache.put(object, ((RealmObjectProxy) object).realmGet$proxyState().getRow$realm().getObjectKey());\n                continue;\n            }\n            long objKey = OsObject.createRow(table);\n            cache.put(object, objKey);\n            String realmGet$fieldStringNotNull = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldStringNotNull();\n            if (realmGet$fieldStringNotNull != null) {\n                Table.nativeSetString(tableNativePtr, columnInfo.fieldStringNotNullColKey, objKey, realmGet$fieldStringNotNull, false);\n            } else {\n                Table.nativeSetNull(tableNativePtr, columnInfo.fieldStringNotNullColKey, objKey, false);\n            }\n            String realmGet$fieldStringNull = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldStringNull();\n            if (realmGet$fieldStringNull != null) {\n                Table.nativeSetString(tableNativePtr, columnInfo.fieldStringNullColKey, objKey, realmGet$fieldStringNull, false);\n            } else {\n                Table.nativeSetNull(tableNativePtr, columnInfo.fieldStringNullColKey, objKey, false);\n            }\n            Boolean realmGet$fieldBooleanNotNull = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldBooleanNotNull();\n            if (realmGet$fieldBooleanNotNull != null) {\n                Table.nativeSetBoolean(tableNativePtr, columnInfo.fieldBooleanNotNullColKey, objKey, realmGet$fieldBooleanNotNull, false);\n            } else {\n                Table.nativeSetNull(tableNativePtr, columnInfo.fieldBooleanNotNullColKey, objKey, false);\n            }\n            Boolean realmGet$fieldBooleanNull = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldBooleanNull();\n            if (realmGet$fieldBooleanNull != null) {\n                Table.nativeSetBoolean(tableNativePtr, columnInfo.fieldBooleanNullColKey, objKey, realmGet$fieldBooleanNull, false);\n            } else {\n                Table.nativeSetNull(tableNativePtr, columnInfo.fieldBooleanNullColKey, objKey, false);\n            }\n            byte[] realmGet$fieldBytesNotNull = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldBytesNotNull();\n            if (realmGet$fieldBytesNotNull != null) {\n                Table.nativeSetByteArray(tableNativePtr, columnInfo.fieldBytesNotNullColKey, objKey, realmGet$fieldBytesNotNull, false);\n            } else {\n                Table.nativeSetNull(tableNativePtr, columnInfo.fieldBytesNotNullColKey, objKey, false);\n            }\n            byte[] realmGet$fieldBytesNull = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldBytesNull();\n            if (realmGet$fieldBytesNull != null) {\n                Table.nativeSetByteArray(tableNativePtr, columnInfo.fieldBytesNullColKey, objKey, realmGet$fieldBytesNull, false);\n            } else {\n                Table.nativeSetNull(tableNativePtr, columnInfo.fieldBytesNullColKey, objKey, false);\n            }\n            Number realmGet$fieldByteNotNull = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldByteNotNull();\n            if (realmGet$fieldByteNotNull != null) {\n                Table.nativeSetLong(tableNativePtr, columnInfo.fieldByteNotNullColKey, objKey, realmGet$fieldByteNotNull.longValue(), false);\n            } else {\n                Table.nativeSetNull(tableNativePtr, columnInfo.fieldByteNotNullColKey, objKey, false);\n            }\n            Number realmGet$fieldByteNull = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldByteNull();\n            if (realmGet$fieldByteNull != null) {\n                Table.nativeSetLong(tableNativePtr, columnInfo.fieldByteNullColKey, objKey, realmGet$fieldByteNull.longValue(), false);\n            } else {\n                Table.nativeSetNull(tableNativePtr, columnInfo.fieldByteNullColKey, objKey, false);\n            }\n            Number realmGet$fieldShortNotNull = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldShortNotNull();\n            if (realmGet$fieldShortNotNull != null) {\n                Table.nativeSetLong(tableNativePtr, columnInfo.fieldShortNotNullColKey, objKey, realmGet$fieldShortNotNull.longValue(), false);\n            } else {\n                Table.nativeSetNull(tableNativePtr, columnInfo.fieldShortNotNullColKey, objKey, false);\n            }\n            Number realmGet$fieldShortNull = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldShortNull();\n            if (realmGet$fieldShortNull != null) {\n                Table.nativeSetLong(tableNativePtr, columnInfo.fieldShortNullColKey, objKey, realmGet$fieldShortNull.longValue(), false);\n            } else {\n                Table.nativeSetNull(tableNativePtr, columnInfo.fieldShortNullColKey, objKey, false);\n            }\n            Number realmGet$fieldIntegerNotNull = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldIntegerNotNull();\n            if (realmGet$fieldIntegerNotNull != null) {\n                Table.nativeSetLong(tableNativePtr, columnInfo.fieldIntegerNotNullColKey, objKey, realmGet$fieldIntegerNotNull.longValue(), false);\n            } else {\n                Table.nativeSetNull(tableNativePtr, columnInfo.fieldIntegerNotNullColKey, objKey, false);\n            }\n            Number realmGet$fieldIntegerNull = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldIntegerNull();\n            if (realmGet$fieldIntegerNull != null) {\n                Table.nativeSetLong(tableNativePtr, columnInfo.fieldIntegerNullColKey, objKey, realmGet$fieldIntegerNull.longValue(), false);\n            } else {\n                Table.nativeSetNull(tableNativePtr, columnInfo.fieldIntegerNullColKey, objKey, false);\n            }\n            Number realmGet$fieldLongNotNull = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldLongNotNull();\n            if (realmGet$fieldLongNotNull != null) {\n                Table.nativeSetLong(tableNativePtr, columnInfo.fieldLongNotNullColKey, objKey, realmGet$fieldLongNotNull.longValue(), false);\n            } else {\n                Table.nativeSetNull(tableNativePtr, columnInfo.fieldLongNotNullColKey, objKey, false);\n            }\n            Number realmGet$fieldLongNull = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldLongNull();\n            if (realmGet$fieldLongNull != null) {\n                Table.nativeSetLong(tableNativePtr, columnInfo.fieldLongNullColKey, objKey, realmGet$fieldLongNull.longValue(), false);\n            } else {\n                Table.nativeSetNull(tableNativePtr, columnInfo.fieldLongNullColKey, objKey, false);\n            }\n            Float realmGet$fieldFloatNotNull = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldFloatNotNull();\n            if (realmGet$fieldFloatNotNull != null) {\n                Table.nativeSetFloat(tableNativePtr, columnInfo.fieldFloatNotNullColKey, objKey, realmGet$fieldFloatNotNull, false);\n            } else {\n                Table.nativeSetNull(tableNativePtr, columnInfo.fieldFloatNotNullColKey, objKey, false);\n            }\n            Float realmGet$fieldFloatNull = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldFloatNull();\n            if (realmGet$fieldFloatNull != null) {\n                Table.nativeSetFloat(tableNativePtr, columnInfo.fieldFloatNullColKey, objKey, realmGet$fieldFloatNull, false);\n            } else {\n                Table.nativeSetNull(tableNativePtr, columnInfo.fieldFloatNullColKey, objKey, false);\n            }\n            Double realmGet$fieldDoubleNotNull = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldDoubleNotNull();\n            if (realmGet$fieldDoubleNotNull != null) {\n                Table.nativeSetDouble(tableNativePtr, columnInfo.fieldDoubleNotNullColKey, objKey, realmGet$fieldDoubleNotNull, false);\n            } else {\n                Table.nativeSetNull(tableNativePtr, columnInfo.fieldDoubleNotNullColKey, objKey, false);\n            }\n            Double realmGet$fieldDoubleNull = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldDoubleNull();\n            if (realmGet$fieldDoubleNull != null) {\n                Table.nativeSetDouble(tableNativePtr, columnInfo.fieldDoubleNullColKey, objKey, realmGet$fieldDoubleNull, false);\n            } else {\n                Table.nativeSetNull(tableNativePtr, columnInfo.fieldDoubleNullColKey, objKey, false);\n            }\n            java.util.Date realmGet$fieldDateNotNull = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldDateNotNull();\n            if (realmGet$fieldDateNotNull != null) {\n                Table.nativeSetTimestamp(tableNativePtr, columnInfo.fieldDateNotNullColKey, objKey, realmGet$fieldDateNotNull.getTime(), false);\n            } else {\n                Table.nativeSetNull(tableNativePtr, columnInfo.fieldDateNotNullColKey, objKey, false);\n            }\n            java.util.Date realmGet$fieldDateNull = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldDateNull();\n            if (realmGet$fieldDateNull != null) {\n                Table.nativeSetTimestamp(tableNativePtr, columnInfo.fieldDateNullColKey, objKey, realmGet$fieldDateNull.getTime(), false);\n            } else {\n                Table.nativeSetNull(tableNativePtr, columnInfo.fieldDateNullColKey, objKey, false);\n            }\n            org.bson.types.Decimal128 realmGet$fieldDecimal128NotNull = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldDecimal128NotNull();\n            if (realmGet$fieldDecimal128NotNull != null) {\n                Table.nativeSetDecimal128(tableNativePtr, columnInfo.fieldDecimal128NotNullColKey, objKey, realmGet$fieldDecimal128NotNull.getLow(), realmGet$fieldDecimal128NotNull.getHigh(), false);\n            } else {\n                Table.nativeSetNull(tableNativePtr, columnInfo.fieldDecimal128NotNullColKey, objKey, false);\n            }\n            org.bson.types.Decimal128 realmGet$fieldDecimal128Null = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldDecimal128Null();\n            if (realmGet$fieldDecimal128Null != null) {\n                Table.nativeSetDecimal128(tableNativePtr, columnInfo.fieldDecimal128NullColKey, objKey, realmGet$fieldDecimal128Null.getLow(), realmGet$fieldDecimal128Null.getHigh(), false);\n            } else {\n                Table.nativeSetNull(tableNativePtr, columnInfo.fieldDecimal128NullColKey, objKey, false);\n            }\n            org.bson.types.ObjectId realmGet$fieldObjectIdNotNull = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldObjectIdNotNull();\n            if (realmGet$fieldObjectIdNotNull != null) {\n                Table.nativeSetObjectId(tableNativePtr, columnInfo.fieldObjectIdNotNullColKey, objKey, realmGet$fieldObjectIdNotNull.toString(), false);\n            } else {\n                Table.nativeSetNull(tableNativePtr, columnInfo.fieldObjectIdNotNullColKey, objKey, false);\n            }\n            org.bson.types.ObjectId realmGet$fieldObjectIdNull = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldObjectIdNull();\n            if (realmGet$fieldObjectIdNull != null) {\n                Table.nativeSetObjectId(tableNativePtr, columnInfo.fieldObjectIdNullColKey, objKey, realmGet$fieldObjectIdNull.toString(), false);\n            } else {\n                Table.nativeSetNull(tableNativePtr, columnInfo.fieldObjectIdNullColKey, objKey, false);\n            }\n\n            some.test.NullTypes fieldObjectNullObj = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldObjectNull();\n            if (fieldObjectNullObj != null) {\n                Long cachefieldObjectNull = cache.get(fieldObjectNullObj);\n                if (cachefieldObjectNull == null) {\n                    cachefieldObjectNull = some_test_NullTypesRealmProxy.insertOrUpdate(realm, fieldObjectNullObj, cache);\n                }\n                Table.nativeSetLink(tableNativePtr, columnInfo.fieldObjectNullColKey, objKey, cachefieldObjectNull, false);\n            } else {\n                Table.nativeNullifyLink(tableNativePtr, columnInfo.fieldObjectNullColKey, objKey);\n            }\n\n            OsList fieldStringListNotNullOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.fieldStringListNotNullColKey);\n            fieldStringListNotNullOsList.removeAll();\n            RealmList<java.lang.String> fieldStringListNotNullList = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldStringListNotNull();\n            if (fieldStringListNotNullList != null) {\n                for (java.lang.String fieldStringListNotNullItem : fieldStringListNotNullList) {\n                    if (fieldStringListNotNullItem == null) {\n                        fieldStringListNotNullOsList.addNull();\n                    } else {\n                        fieldStringListNotNullOsList.addString(fieldStringListNotNullItem);\n                    }\n                }\n            }\n\n\n            OsList fieldStringListNullOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.fieldStringListNullColKey);\n            fieldStringListNullOsList.removeAll();\n            RealmList<java.lang.String> fieldStringListNullList = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldStringListNull();\n            if (fieldStringListNullList != null) {\n                for (java.lang.String fieldStringListNullItem : fieldStringListNullList) {\n                    if (fieldStringListNullItem == null) {\n                        fieldStringListNullOsList.addNull();\n                    } else {\n                        fieldStringListNullOsList.addString(fieldStringListNullItem);\n                    }\n                }\n            }\n\n\n            OsList fieldBinaryListNotNullOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.fieldBinaryListNotNullColKey);\n            fieldBinaryListNotNullOsList.removeAll();\n            RealmList<byte[]> fieldBinaryListNotNullList = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldBinaryListNotNull();\n            if (fieldBinaryListNotNullList != null) {\n                for (byte[] fieldBinaryListNotNullItem : fieldBinaryListNotNullList) {\n                    if (fieldBinaryListNotNullItem == null) {\n                        fieldBinaryListNotNullOsList.addNull();\n                    } else {\n                        fieldBinaryListNotNullOsList.addBinary(fieldBinaryListNotNullItem);\n                    }\n                }\n            }\n\n\n            OsList fieldBinaryListNullOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.fieldBinaryListNullColKey);\n            fieldBinaryListNullOsList.removeAll();\n            RealmList<byte[]> fieldBinaryListNullList = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldBinaryListNull();\n            if (fieldBinaryListNullList != null) {\n                for (byte[] fieldBinaryListNullItem : fieldBinaryListNullList) {\n                    if (fieldBinaryListNullItem == null) {\n                        fieldBinaryListNullOsList.addNull();\n                    } else {\n                        fieldBinaryListNullOsList.addBinary(fieldBinaryListNullItem);\n                    }\n                }\n            }\n\n\n            OsList fieldBooleanListNotNullOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.fieldBooleanListNotNullColKey);\n            fieldBooleanListNotNullOsList.removeAll();\n            RealmList<java.lang.Boolean> fieldBooleanListNotNullList = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldBooleanListNotNull();\n            if (fieldBooleanListNotNullList != null) {\n                for (java.lang.Boolean fieldBooleanListNotNullItem : fieldBooleanListNotNullList) {\n                    if (fieldBooleanListNotNullItem == null) {\n                        fieldBooleanListNotNullOsList.addNull();\n                    } else {\n                        fieldBooleanListNotNullOsList.addBoolean(fieldBooleanListNotNullItem);\n                    }\n                }\n            }\n\n\n            OsList fieldBooleanListNullOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.fieldBooleanListNullColKey);\n            fieldBooleanListNullOsList.removeAll();\n            RealmList<java.lang.Boolean> fieldBooleanListNullList = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldBooleanListNull();\n            if (fieldBooleanListNullList != null) {\n                for (java.lang.Boolean fieldBooleanListNullItem : fieldBooleanListNullList) {\n                    if (fieldBooleanListNullItem == null) {\n                        fieldBooleanListNullOsList.addNull();\n                    } else {\n                        fieldBooleanListNullOsList.addBoolean(fieldBooleanListNullItem);\n                    }\n                }\n            }\n\n\n            OsList fieldLongListNotNullOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.fieldLongListNotNullColKey);\n            fieldLongListNotNullOsList.removeAll();\n            RealmList<java.lang.Long> fieldLongListNotNullList = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldLongListNotNull();\n            if (fieldLongListNotNullList != null) {\n                for (java.lang.Long fieldLongListNotNullItem : fieldLongListNotNullList) {\n                    if (fieldLongListNotNullItem == null) {\n                        fieldLongListNotNullOsList.addNull();\n                    } else {\n                        fieldLongListNotNullOsList.addLong(fieldLongListNotNullItem.longValue());\n                    }\n                }\n            }\n\n\n            OsList fieldLongListNullOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.fieldLongListNullColKey);\n            fieldLongListNullOsList.removeAll();\n            RealmList<java.lang.Long> fieldLongListNullList = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldLongListNull();\n            if (fieldLongListNullList != null) {\n                for (java.lang.Long fieldLongListNullItem : fieldLongListNullList) {\n                    if (fieldLongListNullItem == null) {\n                        fieldLongListNullOsList.addNull();\n                    } else {\n                        fieldLongListNullOsList.addLong(fieldLongListNullItem.longValue());\n                    }\n                }\n            }\n\n\n            OsList fieldIntegerListNotNullOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.fieldIntegerListNotNullColKey);\n            fieldIntegerListNotNullOsList.removeAll();\n            RealmList<java.lang.Integer> fieldIntegerListNotNullList = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldIntegerListNotNull();\n            if (fieldIntegerListNotNullList != null) {\n                for (java.lang.Integer fieldIntegerListNotNullItem : fieldIntegerListNotNullList) {\n                    if (fieldIntegerListNotNullItem == null) {\n                        fieldIntegerListNotNullOsList.addNull();\n                    } else {\n                        fieldIntegerListNotNullOsList.addLong(fieldIntegerListNotNullItem.longValue());\n                    }\n                }\n            }\n\n\n            OsList fieldIntegerListNullOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.fieldIntegerListNullColKey);\n            fieldIntegerListNullOsList.removeAll();\n            RealmList<java.lang.Integer> fieldIntegerListNullList = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldIntegerListNull();\n            if (fieldIntegerListNullList != null) {\n                for (java.lang.Integer fieldIntegerListNullItem : fieldIntegerListNullList) {\n                    if (fieldIntegerListNullItem == null) {\n                        fieldIntegerListNullOsList.addNull();\n                    } else {\n                        fieldIntegerListNullOsList.addLong(fieldIntegerListNullItem.longValue());\n                    }\n                }\n            }\n\n\n            OsList fieldShortListNotNullOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.fieldShortListNotNullColKey);\n            fieldShortListNotNullOsList.removeAll();\n            RealmList<java.lang.Short> fieldShortListNotNullList = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldShortListNotNull();\n            if (fieldShortListNotNullList != null) {\n                for (java.lang.Short fieldShortListNotNullItem : fieldShortListNotNullList) {\n                    if (fieldShortListNotNullItem == null) {\n                        fieldShortListNotNullOsList.addNull();\n                    } else {\n                        fieldShortListNotNullOsList.addLong(fieldShortListNotNullItem.longValue());\n                    }\n                }\n            }\n\n\n            OsList fieldShortListNullOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.fieldShortListNullColKey);\n            fieldShortListNullOsList.removeAll();\n            RealmList<java.lang.Short> fieldShortListNullList = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldShortListNull();\n            if (fieldShortListNullList != null) {\n                for (java.lang.Short fieldShortListNullItem : fieldShortListNullList) {\n                    if (fieldShortListNullItem == null) {\n                        fieldShortListNullOsList.addNull();\n                    } else {\n                        fieldShortListNullOsList.addLong(fieldShortListNullItem.longValue());\n                    }\n                }\n            }\n\n\n            OsList fieldByteListNotNullOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.fieldByteListNotNullColKey);\n            fieldByteListNotNullOsList.removeAll();\n            RealmList<java.lang.Byte> fieldByteListNotNullList = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldByteListNotNull();\n            if (fieldByteListNotNullList != null) {\n                for (java.lang.Byte fieldByteListNotNullItem : fieldByteListNotNullList) {\n                    if (fieldByteListNotNullItem == null) {\n                        fieldByteListNotNullOsList.addNull();\n                    } else {\n                        fieldByteListNotNullOsList.addLong(fieldByteListNotNullItem.longValue());\n                    }\n                }\n            }\n\n\n            OsList fieldByteListNullOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.fieldByteListNullColKey);\n            fieldByteListNullOsList.removeAll();\n            RealmList<java.lang.Byte> fieldByteListNullList = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldByteListNull();\n            if (fieldByteListNullList != null) {\n                for (java.lang.Byte fieldByteListNullItem : fieldByteListNullList) {\n                    if (fieldByteListNullItem == null) {\n                        fieldByteListNullOsList.addNull();\n                    } else {\n                        fieldByteListNullOsList.addLong(fieldByteListNullItem.longValue());\n                    }\n                }\n            }\n\n\n            OsList fieldDoubleListNotNullOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.fieldDoubleListNotNullColKey);\n            fieldDoubleListNotNullOsList.removeAll();\n            RealmList<java.lang.Double> fieldDoubleListNotNullList = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldDoubleListNotNull();\n            if (fieldDoubleListNotNullList != null) {\n                for (java.lang.Double fieldDoubleListNotNullItem : fieldDoubleListNotNullList) {\n                    if (fieldDoubleListNotNullItem == null) {\n                        fieldDoubleListNotNullOsList.addNull();\n                    } else {\n                        fieldDoubleListNotNullOsList.addDouble(fieldDoubleListNotNullItem.doubleValue());\n                    }\n                }\n            }\n\n\n            OsList fieldDoubleListNullOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.fieldDoubleListNullColKey);\n            fieldDoubleListNullOsList.removeAll();\n            RealmList<java.lang.Double> fieldDoubleListNullList = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldDoubleListNull();\n            if (fieldDoubleListNullList != null) {\n                for (java.lang.Double fieldDoubleListNullItem : fieldDoubleListNullList) {\n                    if (fieldDoubleListNullItem == null) {\n                        fieldDoubleListNullOsList.addNull();\n                    } else {\n                        fieldDoubleListNullOsList.addDouble(fieldDoubleListNullItem.doubleValue());\n                    }\n                }\n            }\n\n\n            OsList fieldFloatListNotNullOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.fieldFloatListNotNullColKey);\n            fieldFloatListNotNullOsList.removeAll();\n            RealmList<java.lang.Float> fieldFloatListNotNullList = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldFloatListNotNull();\n            if (fieldFloatListNotNullList != null) {\n                for (java.lang.Float fieldFloatListNotNullItem : fieldFloatListNotNullList) {\n                    if (fieldFloatListNotNullItem == null) {\n                        fieldFloatListNotNullOsList.addNull();\n                    } else {\n                        fieldFloatListNotNullOsList.addFloat(fieldFloatListNotNullItem.floatValue());\n                    }\n                }\n            }\n\n\n            OsList fieldFloatListNullOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.fieldFloatListNullColKey);\n            fieldFloatListNullOsList.removeAll();\n            RealmList<java.lang.Float> fieldFloatListNullList = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldFloatListNull();\n            if (fieldFloatListNullList != null) {\n                for (java.lang.Float fieldFloatListNullItem : fieldFloatListNullList) {\n                    if (fieldFloatListNullItem == null) {\n                        fieldFloatListNullOsList.addNull();\n                    } else {\n                        fieldFloatListNullOsList.addFloat(fieldFloatListNullItem.floatValue());\n                    }\n                }\n            }\n\n\n            OsList fieldDateListNotNullOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.fieldDateListNotNullColKey);\n            fieldDateListNotNullOsList.removeAll();\n            RealmList<java.util.Date> fieldDateListNotNullList = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldDateListNotNull();\n            if (fieldDateListNotNullList != null) {\n                for (java.util.Date fieldDateListNotNullItem : fieldDateListNotNullList) {\n                    if (fieldDateListNotNullItem == null) {\n                        fieldDateListNotNullOsList.addNull();\n                    } else {\n                        fieldDateListNotNullOsList.addDate(fieldDateListNotNullItem);\n                    }\n                }\n            }\n\n\n            OsList fieldDateListNullOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.fieldDateListNullColKey);\n            fieldDateListNullOsList.removeAll();\n            RealmList<java.util.Date> fieldDateListNullList = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldDateListNull();\n            if (fieldDateListNullList != null) {\n                for (java.util.Date fieldDateListNullItem : fieldDateListNullList) {\n                    if (fieldDateListNullItem == null) {\n                        fieldDateListNullOsList.addNull();\n                    } else {\n                        fieldDateListNullOsList.addDate(fieldDateListNullItem);\n                    }\n                }\n            }\n\n\n            OsList fieldDecimal128ListNotNullOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.fieldDecimal128ListNotNullColKey);\n            fieldDecimal128ListNotNullOsList.removeAll();\n            RealmList<org.bson.types.Decimal128> fieldDecimal128ListNotNullList = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldDecimal128ListNotNull();\n            if (fieldDecimal128ListNotNullList != null) {\n                for (org.bson.types.Decimal128 fieldDecimal128ListNotNullItem : fieldDecimal128ListNotNullList) {\n                    if (fieldDecimal128ListNotNullItem == null) {\n                        fieldDecimal128ListNotNullOsList.addNull();\n                    } else {\n                        fieldDecimal128ListNotNullOsList.addDecimal128(fieldDecimal128ListNotNullItem);\n                    }\n                }\n            }\n\n\n            OsList fieldDecimal128ListNullOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.fieldDecimal128ListNullColKey);\n            fieldDecimal128ListNullOsList.removeAll();\n            RealmList<org.bson.types.Decimal128> fieldDecimal128ListNullList = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldDecimal128ListNull();\n            if (fieldDecimal128ListNullList != null) {\n                for (org.bson.types.Decimal128 fieldDecimal128ListNullItem : fieldDecimal128ListNullList) {\n                    if (fieldDecimal128ListNullItem == null) {\n                        fieldDecimal128ListNullOsList.addNull();\n                    } else {\n                        fieldDecimal128ListNullOsList.addDecimal128(fieldDecimal128ListNullItem);\n                    }\n                }\n            }\n\n\n            OsList fieldObjectIdListNotNullOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.fieldObjectIdListNotNullColKey);\n            fieldObjectIdListNotNullOsList.removeAll();\n            RealmList<org.bson.types.ObjectId> fieldObjectIdListNotNullList = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldObjectIdListNotNull();\n            if (fieldObjectIdListNotNullList != null) {\n                for (org.bson.types.ObjectId fieldObjectIdListNotNullItem : fieldObjectIdListNotNullList) {\n                    if (fieldObjectIdListNotNullItem == null) {\n                        fieldObjectIdListNotNullOsList.addNull();\n                    } else {\n                        fieldObjectIdListNotNullOsList.addObjectId(fieldObjectIdListNotNullItem);\n                    }\n                }\n            }\n\n\n            OsList fieldObjectIdListNullOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.fieldObjectIdListNullColKey);\n            fieldObjectIdListNullOsList.removeAll();\n            RealmList<org.bson.types.ObjectId> fieldObjectIdListNullList = ((some_test_NullTypesRealmProxyInterface) object).realmGet$fieldObjectIdListNull();\n            if (fieldObjectIdListNullList != null) {\n                for (org.bson.types.ObjectId fieldObjectIdListNullItem : fieldObjectIdListNullList) {\n                    if (fieldObjectIdListNullItem == null) {\n                        fieldObjectIdListNullOsList.addNull();\n                    } else {\n                        fieldObjectIdListNullOsList.addObjectId(fieldObjectIdListNullItem);\n                    }\n                }\n            }\n\n        }\n    }\n\n    public static some.test.NullTypes createDetachedCopy(some.test.NullTypes realmObject, int currentDepth, int maxDepth, Map<RealmModel, CacheData<RealmModel>> cache) {\n        if (currentDepth > maxDepth || realmObject == null) {\n            return null;\n        }\n        CacheData<RealmModel> cachedObject = cache.get(realmObject);\n        some.test.NullTypes unmanagedObject;\n        if (cachedObject == null) {\n            unmanagedObject = new some.test.NullTypes();\n            cache.put(realmObject, new RealmObjectProxy.CacheData<RealmModel>(currentDepth, unmanagedObject));\n        } else {\n            // Reuse cached object or recreate it because it was encountered at a lower depth.\n            if (currentDepth >= cachedObject.minDepth) {\n                return (some.test.NullTypes) cachedObject.object;\n            }\n            unmanagedObject = (some.test.NullTypes) cachedObject.object;\n            cachedObject.minDepth = currentDepth;\n        }\n        some_test_NullTypesRealmProxyInterface unmanagedCopy = (some_test_NullTypesRealmProxyInterface) unmanagedObject;\n        some_test_NullTypesRealmProxyInterface realmSource = (some_test_NullTypesRealmProxyInterface) realmObject;\n        Realm objectRealm = (Realm) ((RealmObjectProxy) realmObject).realmGet$proxyState().getRealm$realm();\n        unmanagedCopy.realmSet$fieldStringNotNull(realmSource.realmGet$fieldStringNotNull());\n        unmanagedCopy.realmSet$fieldStringNull(realmSource.realmGet$fieldStringNull());\n        unmanagedCopy.realmSet$fieldBooleanNotNull(realmSource.realmGet$fieldBooleanNotNull());\n        unmanagedCopy.realmSet$fieldBooleanNull(realmSource.realmGet$fieldBooleanNull());\n        unmanagedCopy.realmSet$fieldBytesNotNull(realmSource.realmGet$fieldBytesNotNull());\n        unmanagedCopy.realmSet$fieldBytesNull(realmSource.realmGet$fieldBytesNull());\n        unmanagedCopy.realmSet$fieldByteNotNull(realmSource.realmGet$fieldByteNotNull());\n        unmanagedCopy.realmSet$fieldByteNull(realmSource.realmGet$fieldByteNull());\n        unmanagedCopy.realmSet$fieldShortNotNull(realmSource.realmGet$fieldShortNotNull());\n        unmanagedCopy.realmSet$fieldShortNull(realmSource.realmGet$fieldShortNull());\n        unmanagedCopy.realmSet$fieldIntegerNotNull(realmSource.realmGet$fieldIntegerNotNull());\n        unmanagedCopy.realmSet$fieldIntegerNull(realmSource.realmGet$fieldIntegerNull());\n        unmanagedCopy.realmSet$fieldLongNotNull(realmSource.realmGet$fieldLongNotNull());\n        unmanagedCopy.realmSet$fieldLongNull(realmSource.realmGet$fieldLongNull());\n        unmanagedCopy.realmSet$fieldFloatNotNull(realmSource.realmGet$fieldFloatNotNull());\n        unmanagedCopy.realmSet$fieldFloatNull(realmSource.realmGet$fieldFloatNull());\n        unmanagedCopy.realmSet$fieldDoubleNotNull(realmSource.realmGet$fieldDoubleNotNull());\n        unmanagedCopy.realmSet$fieldDoubleNull(realmSource.realmGet$fieldDoubleNull());\n        unmanagedCopy.realmSet$fieldDateNotNull(realmSource.realmGet$fieldDateNotNull());\n        unmanagedCopy.realmSet$fieldDateNull(realmSource.realmGet$fieldDateNull());\n        unmanagedCopy.realmSet$fieldDecimal128NotNull(realmSource.realmGet$fieldDecimal128NotNull());\n        unmanagedCopy.realmSet$fieldDecimal128Null(realmSource.realmGet$fieldDecimal128Null());\n        unmanagedCopy.realmSet$fieldObjectIdNotNull(realmSource.realmGet$fieldObjectIdNotNull());\n        unmanagedCopy.realmSet$fieldObjectIdNull(realmSource.realmGet$fieldObjectIdNull());\n\n        // Deep copy of fieldObjectNull\n        unmanagedCopy.realmSet$fieldObjectNull(some_test_NullTypesRealmProxy.createDetachedCopy(realmSource.realmGet$fieldObjectNull(), currentDepth + 1, maxDepth, cache));\n\n        unmanagedCopy.realmSet$fieldStringListNotNull(new RealmList<java.lang.String>());\n        unmanagedCopy.realmGet$fieldStringListNotNull().addAll(realmSource.realmGet$fieldStringListNotNull());\n\n        unmanagedCopy.realmSet$fieldStringListNull(new RealmList<java.lang.String>());\n        unmanagedCopy.realmGet$fieldStringListNull().addAll(realmSource.realmGet$fieldStringListNull());\n\n        unmanagedCopy.realmSet$fieldBinaryListNotNull(new RealmList<byte[]>());\n        unmanagedCopy.realmGet$fieldBinaryListNotNull().addAll(realmSource.realmGet$fieldBinaryListNotNull());\n\n        unmanagedCopy.realmSet$fieldBinaryListNull(new RealmList<byte[]>());\n        unmanagedCopy.realmGet$fieldBinaryListNull().addAll(realmSource.realmGet$fieldBinaryListNull());\n\n        unmanagedCopy.realmSet$fieldBooleanListNotNull(new RealmList<java.lang.Boolean>());\n        unmanagedCopy.realmGet$fieldBooleanListNotNull().addAll(realmSource.realmGet$fieldBooleanListNotNull());\n\n        unmanagedCopy.realmSet$fieldBooleanListNull(new RealmList<java.lang.Boolean>());\n        unmanagedCopy.realmGet$fieldBooleanListNull().addAll(realmSource.realmGet$fieldBooleanListNull());\n\n        unmanagedCopy.realmSet$fieldLongListNotNull(new RealmList<java.lang.Long>());\n        unmanagedCopy.realmGet$fieldLongListNotNull().addAll(realmSource.realmGet$fieldLongListNotNull());\n\n        unmanagedCopy.realmSet$fieldLongListNull(new RealmList<java.lang.Long>());\n        unmanagedCopy.realmGet$fieldLongListNull().addAll(realmSource.realmGet$fieldLongListNull());\n\n        unmanagedCopy.realmSet$fieldIntegerListNotNull(new RealmList<java.lang.Integer>());\n        unmanagedCopy.realmGet$fieldIntegerListNotNull().addAll(realmSource.realmGet$fieldIntegerListNotNull());\n\n        unmanagedCopy.realmSet$fieldIntegerListNull(new RealmList<java.lang.Integer>());\n        unmanagedCopy.realmGet$fieldIntegerListNull().addAll(realmSource.realmGet$fieldIntegerListNull());\n\n        unmanagedCopy.realmSet$fieldShortListNotNull(new RealmList<java.lang.Short>());\n        unmanagedCopy.realmGet$fieldShortListNotNull().addAll(realmSource.realmGet$fieldShortListNotNull());\n\n        unmanagedCopy.realmSet$fieldShortListNull(new RealmList<java.lang.Short>());\n        unmanagedCopy.realmGet$fieldShortListNull().addAll(realmSource.realmGet$fieldShortListNull());\n\n        unmanagedCopy.realmSet$fieldByteListNotNull(new RealmList<java.lang.Byte>());\n        unmanagedCopy.realmGet$fieldByteListNotNull().addAll(realmSource.realmGet$fieldByteListNotNull());\n\n        unmanagedCopy.realmSet$fieldByteListNull(new RealmList<java.lang.Byte>());\n        unmanagedCopy.realmGet$fieldByteListNull().addAll(realmSource.realmGet$fieldByteListNull());\n\n        unmanagedCopy.realmSet$fieldDoubleListNotNull(new RealmList<java.lang.Double>());\n        unmanagedCopy.realmGet$fieldDoubleListNotNull().addAll(realmSource.realmGet$fieldDoubleListNotNull());\n\n        unmanagedCopy.realmSet$fieldDoubleListNull(new RealmList<java.lang.Double>());\n        unmanagedCopy.realmGet$fieldDoubleListNull().addAll(realmSource.realmGet$fieldDoubleListNull());\n\n        unmanagedCopy.realmSet$fieldFloatListNotNull(new RealmList<java.lang.Float>());\n        unmanagedCopy.realmGet$fieldFloatListNotNull().addAll(realmSource.realmGet$fieldFloatListNotNull());\n\n        unmanagedCopy.realmSet$fieldFloatListNull(new RealmList<java.lang.Float>());\n        unmanagedCopy.realmGet$fieldFloatListNull().addAll(realmSource.realmGet$fieldFloatListNull());\n\n        unmanagedCopy.realmSet$fieldDateListNotNull(new RealmList<java.util.Date>());\n        unmanagedCopy.realmGet$fieldDateListNotNull().addAll(realmSource.realmGet$fieldDateListNotNull());\n\n        unmanagedCopy.realmSet$fieldDateListNull(new RealmList<java.util.Date>());\n        unmanagedCopy.realmGet$fieldDateListNull().addAll(realmSource.realmGet$fieldDateListNull());\n\n        unmanagedCopy.realmSet$fieldDecimal128ListNotNull(new RealmList<org.bson.types.Decimal128>());\n        unmanagedCopy.realmGet$fieldDecimal128ListNotNull().addAll(realmSource.realmGet$fieldDecimal128ListNotNull());\n\n        unmanagedCopy.realmSet$fieldDecimal128ListNull(new RealmList<org.bson.types.Decimal128>());\n        unmanagedCopy.realmGet$fieldDecimal128ListNull().addAll(realmSource.realmGet$fieldDecimal128ListNull());\n\n        unmanagedCopy.realmSet$fieldObjectIdListNotNull(new RealmList<org.bson.types.ObjectId>());\n        unmanagedCopy.realmGet$fieldObjectIdListNotNull().addAll(realmSource.realmGet$fieldObjectIdListNotNull());\n\n        unmanagedCopy.realmSet$fieldObjectIdListNull(new RealmList<org.bson.types.ObjectId>());\n        unmanagedCopy.realmGet$fieldObjectIdListNull().addAll(realmSource.realmGet$fieldObjectIdListNull());\n\n        return unmanagedObject;\n    }\n\n    @Override\n    @SuppressWarnings(\"ArrayToString\")\n    public String toString() {\n        if (!RealmObject.isValid(this)) {\n            return \"Invalid object\";\n        }\n        StringBuilder stringBuilder = new StringBuilder(\"NullTypes = proxy[\");\n        stringBuilder.append(\"{fieldStringNotNull:\");\n        stringBuilder.append(realmGet$fieldStringNotNull());\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{fieldStringNull:\");\n        stringBuilder.append(realmGet$fieldStringNull() != null ? realmGet$fieldStringNull() : \"null\");\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{fieldBooleanNotNull:\");\n        stringBuilder.append(realmGet$fieldBooleanNotNull());\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{fieldBooleanNull:\");\n        stringBuilder.append(realmGet$fieldBooleanNull() != null ? realmGet$fieldBooleanNull() : \"null\");\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{fieldBytesNotNull:\");\n        stringBuilder.append(\"binary(\" + realmGet$fieldBytesNotNull().length + \")\");\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{fieldBytesNull:\");\n        stringBuilder.append((realmGet$fieldBytesNull() == null) ? \"null\" : \"binary(\" + realmGet$fieldBytesNull().length + \")\");\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{fieldByteNotNull:\");\n        stringBuilder.append(realmGet$fieldByteNotNull());\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{fieldByteNull:\");\n        stringBuilder.append(realmGet$fieldByteNull() != null ? realmGet$fieldByteNull() : \"null\");\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{fieldShortNotNull:\");\n        stringBuilder.append(realmGet$fieldShortNotNull());\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{fieldShortNull:\");\n        stringBuilder.append(realmGet$fieldShortNull() != null ? realmGet$fieldShortNull() : \"null\");\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{fieldIntegerNotNull:\");\n        stringBuilder.append(realmGet$fieldIntegerNotNull());\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{fieldIntegerNull:\");\n        stringBuilder.append(realmGet$fieldIntegerNull() != null ? realmGet$fieldIntegerNull() : \"null\");\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{fieldLongNotNull:\");\n        stringBuilder.append(realmGet$fieldLongNotNull());\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{fieldLongNull:\");\n        stringBuilder.append(realmGet$fieldLongNull() != null ? realmGet$fieldLongNull() : \"null\");\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{fieldFloatNotNull:\");\n        stringBuilder.append(realmGet$fieldFloatNotNull());\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{fieldFloatNull:\");\n        stringBuilder.append(realmGet$fieldFloatNull() != null ? realmGet$fieldFloatNull() : \"null\");\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{fieldDoubleNotNull:\");\n        stringBuilder.append(realmGet$fieldDoubleNotNull());\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{fieldDoubleNull:\");\n        stringBuilder.append(realmGet$fieldDoubleNull() != null ? realmGet$fieldDoubleNull() : \"null\");\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{fieldDateNotNull:\");\n        stringBuilder.append(realmGet$fieldDateNotNull());\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{fieldDateNull:\");\n        stringBuilder.append(realmGet$fieldDateNull() != null ? realmGet$fieldDateNull() : \"null\");\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{fieldDecimal128NotNull:\");\n        stringBuilder.append(realmGet$fieldDecimal128NotNull());\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{fieldDecimal128Null:\");\n        stringBuilder.append(realmGet$fieldDecimal128Null() != null ? realmGet$fieldDecimal128Null() : \"null\");\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{fieldObjectIdNotNull:\");\n        stringBuilder.append(realmGet$fieldObjectIdNotNull());\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{fieldObjectIdNull:\");\n        stringBuilder.append(realmGet$fieldObjectIdNull() != null ? realmGet$fieldObjectIdNull() : \"null\");\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{fieldObjectNull:\");\n        stringBuilder.append(realmGet$fieldObjectNull() != null ? \"NullTypes\" : \"null\");\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{fieldStringListNotNull:\");\n        stringBuilder.append(\"RealmList<String>[\").append(realmGet$fieldStringListNotNull().size()).append(\"]\");\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{fieldStringListNull:\");\n        stringBuilder.append(\"RealmList<String>[\").append(realmGet$fieldStringListNull().size()).append(\"]\");\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{fieldBinaryListNotNull:\");\n        stringBuilder.append(\"RealmList<byte[]>[\").append(realmGet$fieldBinaryListNotNull().size()).append(\"]\");\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{fieldBinaryListNull:\");\n        stringBuilder.append(\"RealmList<byte[]>[\").append(realmGet$fieldBinaryListNull().size()).append(\"]\");\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{fieldBooleanListNotNull:\");\n        stringBuilder.append(\"RealmList<Boolean>[\").append(realmGet$fieldBooleanListNotNull().size()).append(\"]\");\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{fieldBooleanListNull:\");\n        stringBuilder.append(\"RealmList<Boolean>[\").append(realmGet$fieldBooleanListNull().size()).append(\"]\");\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{fieldLongListNotNull:\");\n        stringBuilder.append(\"RealmList<Long>[\").append(realmGet$fieldLongListNotNull().size()).append(\"]\");\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{fieldLongListNull:\");\n        stringBuilder.append(\"RealmList<Long>[\").append(realmGet$fieldLongListNull().size()).append(\"]\");\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{fieldIntegerListNotNull:\");\n        stringBuilder.append(\"RealmList<Integer>[\").append(realmGet$fieldIntegerListNotNull().size()).append(\"]\");\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{fieldIntegerListNull:\");\n        stringBuilder.append(\"RealmList<Integer>[\").append(realmGet$fieldIntegerListNull().size()).append(\"]\");\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{fieldShortListNotNull:\");\n        stringBuilder.append(\"RealmList<Short>[\").append(realmGet$fieldShortListNotNull().size()).append(\"]\");\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{fieldShortListNull:\");\n        stringBuilder.append(\"RealmList<Short>[\").append(realmGet$fieldShortListNull().size()).append(\"]\");\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{fieldByteListNotNull:\");\n        stringBuilder.append(\"RealmList<Byte>[\").append(realmGet$fieldByteListNotNull().size()).append(\"]\");\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{fieldByteListNull:\");\n        stringBuilder.append(\"RealmList<Byte>[\").append(realmGet$fieldByteListNull().size()).append(\"]\");\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{fieldDoubleListNotNull:\");\n        stringBuilder.append(\"RealmList<Double>[\").append(realmGet$fieldDoubleListNotNull().size()).append(\"]\");\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{fieldDoubleListNull:\");\n        stringBuilder.append(\"RealmList<Double>[\").append(realmGet$fieldDoubleListNull().size()).append(\"]\");\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{fieldFloatListNotNull:\");\n        stringBuilder.append(\"RealmList<Float>[\").append(realmGet$fieldFloatListNotNull().size()).append(\"]\");\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{fieldFloatListNull:\");\n        stringBuilder.append(\"RealmList<Float>[\").append(realmGet$fieldFloatListNull().size()).append(\"]\");\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{fieldDateListNotNull:\");\n        stringBuilder.append(\"RealmList<Date>[\").append(realmGet$fieldDateListNotNull().size()).append(\"]\");\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{fieldDateListNull:\");\n        stringBuilder.append(\"RealmList<Date>[\").append(realmGet$fieldDateListNull().size()).append(\"]\");\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{fieldDecimal128ListNotNull:\");\n        stringBuilder.append(\"RealmList<Decimal128>[\").append(realmGet$fieldDecimal128ListNotNull().size()).append(\"]\");\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{fieldDecimal128ListNull:\");\n        stringBuilder.append(\"RealmList<Decimal128>[\").append(realmGet$fieldDecimal128ListNull().size()).append(\"]\");\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{fieldObjectIdListNotNull:\");\n        stringBuilder.append(\"RealmList<ObjectId>[\").append(realmGet$fieldObjectIdListNotNull().size()).append(\"]\");\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\",\");\n        stringBuilder.append(\"{fieldObjectIdListNull:\");\n        stringBuilder.append(\"RealmList<ObjectId>[\").append(realmGet$fieldObjectIdListNull().size()).append(\"]\");\n        stringBuilder.append(\"}\");\n        stringBuilder.append(\"]\");\n        return stringBuilder.toString();\n    }\n\n    @Override\n    public ProxyState<?> realmGet$proxyState() {\n        return proxyState;\n    }\n\n    @Override\n    public int hashCode() {\n        String realmName = proxyState.getRealm$realm().getPath();\n        String tableName = proxyState.getRow$realm().getTable().getName();\n        long objKey = proxyState.getRow$realm().getObjectKey();\n\n        int result = 17;\n        result = 31 * result + ((realmName != null) ? realmName.hashCode() : 0);\n        result = 31 * result + ((tableName != null) ? tableName.hashCode() : 0);\n        result = 31 * result + (int) (objKey ^ (objKey >>> 32));\n        return result;\n    }\n\n    @Override\n    public boolean equals(Object o) {\n        if (this == o) return true;\n        if (o == null || getClass() != o.getClass()) return false;\n        some_test_NullTypesRealmProxy aNullTypes = (some_test_NullTypesRealmProxy)o;\n\n        BaseRealm realm = proxyState.getRealm$realm();\n        BaseRealm otherRealm = aNullTypes.proxyState.getRealm$realm();\n        String path = realm.getPath();\n        String otherPath = otherRealm.getPath();\n        if (path != null ? !path.equals(otherPath) : otherPath != null) return false;\n        if (realm.isFrozen() != otherRealm.isFrozen()) return false;\n        if (!realm.sharedRealm.getVersionID().equals(otherRealm.sharedRealm.getVersionID())) {\n            return false;\n        }\n\n        String tableName = proxyState.getRow$realm().getTable().getName();\n        String otherTableName = aNullTypes.proxyState.getRow$realm().getTable().getName();\n        if (tableName != null ? !tableName.equals(otherTableName) : otherTableName != null) return false;\n\n        if (proxyState.getRow$realm().getObjectKey() != aNullTypes.proxyState.getRow$realm().getObjectKey()) return false;\n\n        return true;\n    }\n}\n"
  },
  {
    "path": "realm/realm-annotations-processor/src/test/resources/io/realm/some_test_SimpleRealmProxy.java",
    "content": "package io.realm;\n\n\nimport android.annotation.TargetApi;\nimport android.os.Build;\nimport android.util.JsonReader;\nimport android.util.JsonToken;\nimport io.realm.ImportFlag;\nimport io.realm.ProxyUtils;\nimport io.realm.exceptions.RealmMigrationNeededException;\nimport io.realm.internal.ColumnInfo;\nimport io.realm.internal.NativeContext;\nimport io.realm.internal.OsList;\nimport io.realm.internal.OsMap;\nimport io.realm.internal.OsObject;\nimport io.realm.internal.OsObjectSchemaInfo;\nimport io.realm.internal.OsSchemaInfo;\nimport io.realm.internal.OsSet;\nimport io.realm.internal.Property;\nimport io.realm.internal.RealmObjectProxy;\nimport io.realm.internal.Row;\nimport io.realm.internal.Table;\nimport io.realm.internal.android.JsonUtils;\nimport io.realm.internal.core.NativeRealmAny;\nimport io.realm.internal.objectstore.OsObjectBuilder;\nimport io.realm.log.RealmLog;\nimport java.io.IOException;\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.Date;\nimport java.util.HashMap;\nimport java.util.HashSet;\nimport java.util.Iterator;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Set;\nimport org.json.JSONArray;\nimport org.json.JSONException;\nimport org.json.JSONObject;\n\n@SuppressWarnings(\"all\")\npublic class some_test_SimpleRealmProxy extends some.test.Simple\n        implements RealmObjectProxy, some_test_SimpleRealmProxyInterface {\n\n    static final class SimpleColumnInfo extends ColumnInfo {\n        long nameColKey;\n        long ageColKey;\n\n        SimpleColumnInfo(OsSchemaInfo schemaInfo) {\n            super(2);\n            OsObjectSchemaInfo objectSchemaInfo = schemaInfo.getObjectSchemaInfo(\"Simple\");\n            this.nameColKey = addColumnDetails(\"name\", \"name\", objectSchemaInfo);\n            this.ageColKey = addColumnDetails(\"age\", \"age\", objectSchemaInfo);\n        }\n\n        SimpleColumnInfo(ColumnInfo src, boolean mutable) {\n            super(src, mutable);\n            copy(src, this);\n        }\n\n        @Override\n        protected final ColumnInfo copy(boolean mutable) {\n            return new SimpleColumnInfo(this, mutable);\n        }\n\n        @Override\n        protected final void copy(ColumnInfo rawSrc, ColumnInfo rawDst) {\n            final SimpleColumnInfo src = (SimpleColumnInfo) rawSrc;\n            final SimpleColumnInfo dst = (SimpleColumnInfo) rawDst;\n            dst.nameColKey = src.nameColKey;\n            dst.ageColKey = src.ageColKey;\n        }\n    }\n\n    private static final String NO_ALIAS = \"\";\n    private static final OsObjectSchemaInfo expectedObjectSchemaInfo = createExpectedObjectSchemaInfo();\n\n    private SimpleColumnInfo columnInfo;\n    private ProxyState<some.test.Simple> proxyState;\n\n    some_test_SimpleRealmProxy() {\n        proxyState.setConstructionFinished();\n    }\n\n    @Override\n    public void realm$injectObjectContext() {\n        if (this.proxyState != null) {\n            return;\n        }\n        final BaseRealm.RealmObjectContext context = BaseRealm.objectContext.get();\n        this.columnInfo = (SimpleColumnInfo) context.getColumnInfo();\n        this.proxyState = new ProxyState<some.test.Simple>(this);\n        proxyState.setRealm$realm(context.getRealm());\n        proxyState.setRow$realm(context.getRow());\n        proxyState.setAcceptDefaultValue$realm(context.getAcceptDefaultValue());\n        proxyState.setExcludeFields$realm(context.getExcludeFields());\n    }\n\n    @Override\n    @SuppressWarnings(\"cast\")\n    public String realmGet$name() {\n        proxyState.getRealm$realm().checkIfValid();\n        return (java.lang.String) proxyState.getRow$realm().getString(columnInfo.nameColKey);\n    }\n\n    @Override\n    public void realmSet$name(String value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            final Row row = proxyState.getRow$realm();\n            if (value == null) {\n                row.getTable().setNull(columnInfo.nameColKey, row.getObjectKey(), true);\n                return;\n            }\n            row.getTable().setString(columnInfo.nameColKey, row.getObjectKey(), value, true);\n            return;\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        if (value == null) {\n            proxyState.getRow$realm().setNull(columnInfo.nameColKey);\n            return;\n        }\n        proxyState.getRow$realm().setString(columnInfo.nameColKey, value);\n    }\n\n    @Override\n    @SuppressWarnings(\"cast\")\n    public int realmGet$age() {\n        proxyState.getRealm$realm().checkIfValid();\n        return (int) proxyState.getRow$realm().getLong(columnInfo.ageColKey);\n    }\n\n    @Override\n    public void realmSet$age(int value) {\n        if (proxyState.isUnderConstruction()) {\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n            final Row row = proxyState.getRow$realm();\n            row.getTable().setLong(columnInfo.ageColKey, row.getObjectKey(), value, true);\n            return;\n        }\n\n        proxyState.getRealm$realm().checkIfValid();\n        proxyState.getRow$realm().setLong(columnInfo.ageColKey, value);\n    }\n\n    private static OsObjectSchemaInfo createExpectedObjectSchemaInfo() {\n        OsObjectSchemaInfo.Builder builder = new OsObjectSchemaInfo.Builder(NO_ALIAS, \"Simple\", false, 2, 0);\n        builder.addPersistedProperty(NO_ALIAS, \"name\", RealmFieldType.STRING, !Property.PRIMARY_KEY, !Property.INDEXED, !Property.REQUIRED);\n        builder.addPersistedProperty(NO_ALIAS, \"age\", RealmFieldType.INTEGER, !Property.PRIMARY_KEY, !Property.INDEXED, Property.REQUIRED);\n        return builder.build();\n    }\n\n    public static OsObjectSchemaInfo getExpectedObjectSchemaInfo() {\n        return expectedObjectSchemaInfo;\n    }\n\n    public static SimpleColumnInfo createColumnInfo(OsSchemaInfo schemaInfo) {\n        return new SimpleColumnInfo(schemaInfo);\n    }\n\n    public static String getSimpleClassName() {\n        return \"Simple\";\n    }\n\n    public static final class ClassNameHelper {\n        public static final String INTERNAL_CLASS_NAME = \"Simple\";\n    }\n\n    @SuppressWarnings(\"cast\")\n    public static some.test.Simple createOrUpdateUsingJsonObject(Realm realm, JSONObject json, boolean update)\n            throws JSONException {\n        final List<String> excludeFields = Collections.<String> emptyList();\n        some.test.Simple obj = realm.createObjectInternal(some.test.Simple.class, true, excludeFields);\n\n        final some_test_SimpleRealmProxyInterface objProxy = (some_test_SimpleRealmProxyInterface) obj;\n        if (json.has(\"name\")) {\n            if (json.isNull(\"name\")) {\n                objProxy.realmSet$name(null);\n            } else {\n                objProxy.realmSet$name((String) json.getString(\"name\"));\n            }\n        }\n        if (json.has(\"age\")) {\n            if (json.isNull(\"age\")) {\n                throw new IllegalArgumentException(\"Trying to set non-nullable field 'age' to null.\");\n            } else {\n                objProxy.realmSet$age((int) json.getInt(\"age\"));\n            }\n        }\n        return obj;\n    }\n\n    @SuppressWarnings(\"cast\")\n    @TargetApi(Build.VERSION_CODES.HONEYCOMB)\n    public static some.test.Simple createUsingJsonStream(Realm realm, JsonReader reader)\n            throws IOException {\n        final some.test.Simple obj = new some.test.Simple();\n        final some_test_SimpleRealmProxyInterface objProxy = (some_test_SimpleRealmProxyInterface) obj;\n        reader.beginObject();\n        while (reader.hasNext()) {\n            String name = reader.nextName();\n            if (false) {\n            } else if (name.equals(\"name\")) {\n                if (reader.peek() != JsonToken.NULL) {\n                    objProxy.realmSet$name((String) reader.nextString());\n                } else {\n                    reader.skipValue();\n                    objProxy.realmSet$name(null);\n                }\n            } else if (name.equals(\"age\")) {\n                if (reader.peek() != JsonToken.NULL) {\n                    objProxy.realmSet$age((int) reader.nextInt());\n                } else {\n                    reader.skipValue();\n                    throw new IllegalArgumentException(\"Trying to set non-nullable field 'age' to null.\");\n                }\n            } else {\n                reader.skipValue();\n            }\n        }\n        reader.endObject();\n        return realm.copyToRealm(obj);\n    }\n\n    static some_test_SimpleRealmProxy newProxyInstance(BaseRealm realm, Row row) {\n        // Ignore default values to avoid creating unexpected objects from RealmModel/RealmList fields\n        final BaseRealm.RealmObjectContext objectContext = BaseRealm.objectContext.get();\n        objectContext.set(realm, row, realm.getSchema().getColumnInfo(some.test.Simple.class), false, Collections.<String>emptyList());\n        io.realm.some_test_SimpleRealmProxy obj = new io.realm.some_test_SimpleRealmProxy();\n        objectContext.clear();\n        return obj;\n    }\n\n    public static some.test.Simple copyOrUpdate(Realm realm, SimpleColumnInfo columnInfo, some.test.Simple object, boolean update, Map<RealmModel,RealmObjectProxy> cache, Set<ImportFlag> flags) {\n        if (object instanceof RealmObjectProxy && !RealmObject.isFrozen(object) && ((RealmObjectProxy) object).realmGet$proxyState().getRealm$realm() != null) {\n            final BaseRealm otherRealm = ((RealmObjectProxy) object).realmGet$proxyState().getRealm$realm();\n            if (otherRealm.threadId != realm.threadId) {\n                throw new IllegalArgumentException(\"Objects which belong to Realm instances in other threads cannot be copied into this Realm instance.\");\n            }\n            if (otherRealm.getPath().equals(realm.getPath())) {\n                return object;\n            }\n        }\n        final BaseRealm.RealmObjectContext objectContext = BaseRealm.objectContext.get();\n        RealmObjectProxy cachedRealmObject = cache.get(object);\n        if (cachedRealmObject != null) {\n            return (some.test.Simple) cachedRealmObject;\n        }\n\n        return copy(realm, columnInfo, object, update, cache, flags);\n    }\n\n    public static some.test.Simple copy(Realm realm, SimpleColumnInfo columnInfo, some.test.Simple newObject, boolean update, Map<RealmModel,RealmObjectProxy> cache, Set<ImportFlag> flags) {\n        RealmObjectProxy cachedRealmObject = cache.get(newObject);\n        if (cachedRealmObject != null) {\n            return (some.test.Simple) cachedRealmObject;\n        }\n\n        some_test_SimpleRealmProxyInterface unmanagedSource = (some_test_SimpleRealmProxyInterface) newObject;\n\n        Table table = realm.getTable(some.test.Simple.class);\n        OsObjectBuilder builder = new OsObjectBuilder(table, flags);\n\n        // Add all non-\"object reference\" fields\n        builder.addString(columnInfo.nameColKey, unmanagedSource.realmGet$name());\n        builder.addInteger(columnInfo.ageColKey, unmanagedSource.realmGet$age());\n\n        // Create the underlying object and cache it before setting any object/objectlist references\n        // This will allow us to break any circular dependencies by using the object cache.\n        Row row = builder.createNewObject();\n        io.realm.some_test_SimpleRealmProxy managedCopy = newProxyInstance(realm, row);\n        cache.put(newObject, managedCopy);\n\n        return managedCopy;\n    }\n\n    public static long insert(Realm realm, some.test.Simple object, Map<RealmModel,Long> cache) {\n        if (object instanceof RealmObjectProxy && !RealmObject.isFrozen(object) && ((RealmObjectProxy) object).realmGet$proxyState().getRealm$realm() != null && ((RealmObjectProxy) object).realmGet$proxyState().getRealm$realm().getPath().equals(realm.getPath())) {\n            return ((RealmObjectProxy) object).realmGet$proxyState().getRow$realm().getObjectKey();\n        }\n        Table table = realm.getTable(some.test.Simple.class);\n        long tableNativePtr = table.getNativePtr();\n        SimpleColumnInfo columnInfo = (SimpleColumnInfo) realm.getSchema().getColumnInfo(some.test.Simple.class);\n        long objKey = OsObject.createRow(table);\n        cache.put(object, objKey);\n        String realmGet$name = ((some_test_SimpleRealmProxyInterface) object).realmGet$name();\n        if (realmGet$name != null) {\n            Table.nativeSetString(tableNativePtr, columnInfo.nameColKey, objKey, realmGet$name, false);\n        }\n        Table.nativeSetLong(tableNativePtr, columnInfo.ageColKey, objKey, ((some_test_SimpleRealmProxyInterface) object).realmGet$age(), false);\n        return objKey;\n    }\n\n    public static void insert(Realm realm, Iterator<? extends RealmModel> objects, Map<RealmModel,Long> cache) {\n        Table table = realm.getTable(some.test.Simple.class);\n        long tableNativePtr = table.getNativePtr();\n        SimpleColumnInfo columnInfo = (SimpleColumnInfo) realm.getSchema().getColumnInfo(some.test.Simple.class);\n        some.test.Simple object = null;\n        while (objects.hasNext()) {\n            object = (some.test.Simple) objects.next();\n            if (cache.containsKey(object)) {\n                continue;\n            }\n            if (object instanceof RealmObjectProxy && !RealmObject.isFrozen(object) && ((RealmObjectProxy) object).realmGet$proxyState().getRealm$realm() != null && ((RealmObjectProxy) object).realmGet$proxyState().getRealm$realm().getPath().equals(realm.getPath())) {\n                cache.put(object, ((RealmObjectProxy) object).realmGet$proxyState().getRow$realm().getObjectKey());\n                continue;\n            }\n            long objKey = OsObject.createRow(table);\n            cache.put(object, objKey);\n            String realmGet$name = ((some_test_SimpleRealmProxyInterface) object).realmGet$name();\n            if (realmGet$name != null) {\n                Table.nativeSetString(tableNativePtr, columnInfo.nameColKey, objKey, realmGet$name, false);\n            }\n            Table.nativeSetLong(tableNativePtr, columnInfo.ageColKey, objKey, ((some_test_SimpleRealmProxyInterface) object).realmGet$age(), false);\n        }\n    }\n\n    public static long insertOrUpdate(Realm realm, some.test.Simple object, Map<RealmModel,Long> cache) {\n        if (object instanceof RealmObjectProxy && !RealmObject.isFrozen(object) && ((RealmObjectProxy) object).realmGet$proxyState().getRealm$realm() != null && ((RealmObjectProxy) object).realmGet$proxyState().getRealm$realm().getPath().equals(realm.getPath())) {\n            return ((RealmObjectProxy) object).realmGet$proxyState().getRow$realm().getObjectKey();\n        }\n        Table table = realm.getTable(some.test.Simple.class);\n        long tableNativePtr = table.getNativePtr();\n        SimpleColumnInfo columnInfo = (SimpleColumnInfo) realm.getSchema().getColumnInfo(some.test.Simple.class);\n        long objKey = OsObject.createRow(table);\n        cache.put(object, objKey);\n        String realmGet$name = ((some_test_SimpleRealmProxyInterface) object).realmGet$name();\n        if (realmGet$name != null) {\n            Table.nativeSetString(tableNativePtr, columnInfo.nameColKey, objKey, realmGet$name, false);\n        } else {\n            Table.nativeSetNull(tableNativePtr, columnInfo.nameColKey, objKey, false);\n        }\n        Table.nativeSetLong(tableNativePtr, columnInfo.ageColKey, objKey, ((some_test_SimpleRealmProxyInterface) object).realmGet$age(), false);\n        return objKey;\n    }\n\n    public static void insertOrUpdate(Realm realm, Iterator<? extends RealmModel> objects, Map<RealmModel,Long> cache) {\n        Table table = realm.getTable(some.test.Simple.class);\n        long tableNativePtr = table.getNativePtr();\n        SimpleColumnInfo columnInfo = (SimpleColumnInfo) realm.getSchema().getColumnInfo(some.test.Simple.class);\n        some.test.Simple object = null;\n        while (objects.hasNext()) {\n            object = (some.test.Simple) objects.next();\n            if (cache.containsKey(object)) {\n                continue;\n            }\n            if (object instanceof RealmObjectProxy && !RealmObject.isFrozen(object) && ((RealmObjectProxy) object).realmGet$proxyState().getRealm$realm() != null && ((RealmObjectProxy) object).realmGet$proxyState().getRealm$realm().getPath().equals(realm.getPath())) {\n                cache.put(object, ((RealmObjectProxy) object).realmGet$proxyState().getRow$realm().getObjectKey());\n                continue;\n            }\n            long objKey = OsObject.createRow(table);\n            cache.put(object, objKey);\n            String realmGet$name = ((some_test_SimpleRealmProxyInterface) object).realmGet$name();\n            if (realmGet$name != null) {\n                Table.nativeSetString(tableNativePtr, columnInfo.nameColKey, objKey, realmGet$name, false);\n            } else {\n                Table.nativeSetNull(tableNativePtr, columnInfo.nameColKey, objKey, false);\n            }\n            Table.nativeSetLong(tableNativePtr, columnInfo.ageColKey, objKey, ((some_test_SimpleRealmProxyInterface) object).realmGet$age(), false);\n        }\n    }\n\n    public static some.test.Simple createDetachedCopy(some.test.Simple realmObject, int currentDepth, int maxDepth, Map<RealmModel, CacheData<RealmModel>> cache) {\n        if (currentDepth > maxDepth || realmObject == null) {\n            return null;\n        }\n        CacheData<RealmModel> cachedObject = cache.get(realmObject);\n        some.test.Simple unmanagedObject;\n        if (cachedObject == null) {\n            unmanagedObject = new some.test.Simple();\n            cache.put(realmObject, new RealmObjectProxy.CacheData<RealmModel>(currentDepth, unmanagedObject));\n        } else {\n            // Reuse cached object or recreate it because it was encountered at a lower depth.\n            if (currentDepth >= cachedObject.minDepth) {\n                return (some.test.Simple) cachedObject.object;\n            }\n            unmanagedObject = (some.test.Simple) cachedObject.object;\n            cachedObject.minDepth = currentDepth;\n        }\n        some_test_SimpleRealmProxyInterface unmanagedCopy = (some_test_SimpleRealmProxyInterface) unmanagedObject;\n        some_test_SimpleRealmProxyInterface realmSource = (some_test_SimpleRealmProxyInterface) realmObject;\n        Realm objectRealm = (Realm) ((RealmObjectProxy) realmObject).realmGet$proxyState().getRealm$realm();\n        unmanagedCopy.realmSet$name(realmSource.realmGet$name());\n        unmanagedCopy.realmSet$age(realmSource.realmGet$age());\n\n        return unmanagedObject;\n    }\n\n    @Override\n    public ProxyState<?> realmGet$proxyState() {\n        return proxyState;\n    }\n\n}\n"
  },
  {
    "path": "realm/realm-annotations-processor/src/test/resources/some/test/AllTypes.java",
    "content": "/*\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\npackage some.test;\n\nimport org.bson.types.Decimal128;\nimport org.bson.types.ObjectId;\n\nimport java.util.Date;\nimport java.util.UUID;\n\nimport io.realm.RealmAny;\nimport io.realm.MutableRealmInteger;\nimport io.realm.RealmDictionary;\nimport io.realm.RealmList;\nimport io.realm.RealmObject;\nimport io.realm.RealmResults;\nimport io.realm.annotations.LinkingObjects;\nimport io.realm.annotations.PrimaryKey;\nimport io.realm.annotations.Required;\n\npublic class AllTypes extends RealmObject {\n\n    public static final String TAG = \"AllTypes\";\n    public static final String FIELD_PARENTS = \"columnObject\";\n\n    @PrimaryKey\n    private String columnString;\n\n    private long columnLong;\n    private float columnFloat;\n    private double columnDouble;\n    private boolean columnBoolean;\n    @Required\n    private Decimal128 columnDecimal128;\n    @Required\n    private ObjectId columnObjectId;\n    @Required\n    private UUID columnUUID;\n\n    @Required\n    private Date columnDate;\n\n    private RealmAny columnRealmAny;\n\n    @Required\n    private byte[] columnBinary;\n\n    private final MutableRealmInteger columnMutableRealmInteger = MutableRealmInteger.valueOf(0);\n\n    private AllTypes columnObject;\n    private Simple columnObjectWithoutPk;\n\n    private RealmList<AllTypes> columnRealmList;\n    private RealmList<Simple> columnRealmListNoPk;\n\n    private final RealmList<AllTypes> columnRealmFinalList = new RealmList<>();\n    private final RealmList<Simple> columnRealmFinalListNoPk = new RealmList<>();\n\n    private RealmList<String> columnStringList;\n    private RealmList<byte[]> columnBinaryList;\n    private RealmList<Boolean> columnBooleanList;\n    private RealmList<Long> columnLongList;\n    private RealmList<Integer> columnIntegerList;\n    private RealmList<Short> columnShortList;\n    private RealmList<Byte> columnByteList;\n    private RealmList<Double> columnDoubleList;\n    private RealmList<Float> columnFloatList;\n    private RealmList<Date> columnDateList;\n    private RealmList<Decimal128> columnDecimal128List;\n    private RealmList<ObjectId> columnObjectIdList;\n    private RealmList<UUID> columnUUIDList;\n    private RealmList<RealmAny> columnRealmAnyList;\n\n    private RealmDictionary<AllTypes> columnRealmDictionary;\n\n    private RealmDictionary<Boolean> columnBooleanDictionary;\n    private RealmDictionary<String> columnStringDictionary;\n    private RealmDictionary<Integer> columnIntegerDictionary;\n    private RealmDictionary<Float> columnFloatDictionary;\n    private RealmDictionary<Long> columnLongDictionary;\n    private RealmDictionary<Short> columnShortDictionary;\n    private RealmDictionary<Double> columnDoubleDictionary;\n    private RealmDictionary<Byte> columnByteDictionary;\n    private RealmDictionary<byte[]> columnBinaryDictionary;\n    private RealmDictionary<Date> columnDateDictionary;\n    private RealmDictionary<ObjectId> columnObjectIdDictionary;\n    private RealmDictionary<UUID> columnUUIDDictionary;\n    private RealmDictionary<Decimal128> columnDecimal128Dictionary;\n    private RealmDictionary<RealmAny> columnRealmAnyDictionary;\n\n    @LinkingObjects(FIELD_PARENTS)\n    private final RealmResults<AllTypes> parentObjects = null;\n\n    public String getColumnString() {\n        return realmGet$columnString();\n    }\n\n    public void setColumnString(String columnString) {\n        realmSet$columnString(columnString);\n    }\n\n    public String realmGet$columnString() {\n        return columnString;\n    }\n\n    public void realmSet$columnString(String columnString) {\n        this.columnString = columnString;\n    }\n\n    public long getColumnLong() {\n        return realmGet$columnLong();\n    }\n\n    public void setColumnLong(long columnLong) {\n        realmSet$columnLong(columnLong);\n    }\n\n    public long realmGet$columnLong() {\n        return columnLong;\n    }\n\n    public void realmSet$columnLong(long columnLong) {\n        this.columnLong = columnLong;\n    }\n\n    public float getColumnFloat() {\n        return realmGet$columnFloat();\n    }\n\n    public void setColumnFloat(float columnFloat) {\n        realmSet$columnFloat(columnFloat);\n    }\n\n    public float realmGet$columnFloat() {\n        return columnFloat;\n    }\n\n    public void realmSet$columnFloat(float columnFloat) {\n        this.columnFloat = columnFloat;\n    }\n\n    public double getColumnDouble() {\n        return realmGet$columnDouble();\n    }\n\n    public void setColumnDouble(double columnDouble) {\n        realmSet$columnDouble(columnDouble);\n    }\n\n    public double realmGet$columnDouble() {\n        return columnDouble;\n    }\n\n    public void realmSet$columnDouble(double columnDouble) {\n        this.columnDouble = columnDouble;\n    }\n\n    public boolean isColumnBoolean() {\n        return realmGet$columnBoolean();\n    }\n\n    public void setColumnBoolean(boolean columnBoolean) {\n        realmSet$columnBoolean(columnBoolean);\n    }\n\n    public boolean realmGet$columnBoolean() {\n        return columnBoolean;\n    }\n\n    public void realmSet$columnBoolean(boolean columnBoolean) {\n        this.columnBoolean = columnBoolean;\n    }\n\n    public Date getColumnDate() {\n        return realmGet$columnDate();\n    }\n\n    public void setColumnDate(Date columnDate) {\n        realmSet$columnDate(columnDate);\n    }\n\n    public Date realmGet$columnDate() {\n        return columnDate;\n    }\n\n    public void realmSet$columnDate(Date columnDate) {\n        this.columnDate = columnDate;\n    }\n\n    public byte[] getColumnBinary() {\n        return realmGet$columnBinary();\n    }\n\n    public void setColumnBinary(byte[] columnBinary) {\n        realmSet$columnBinary(columnBinary);\n    }\n\n    public byte[] realmGet$columnBinary() {\n        return columnBinary;\n    }\n\n    public void realmSet$columnBinary(byte[] columnBinary) {\n        this.columnBinary = columnBinary;\n    }\n\n    public AllTypes getColumnObject() {\n        return realmGet$columnObject();\n    }\n\n    public void setColumnObject(AllTypes columnObject) {\n        realmSet$columnObject(columnObject);\n    }\n\n    public AllTypes realmGet$columnObject() {\n        return columnObject;\n    }\n\n    public void realmSet$columnObject(AllTypes columnObject) {\n        this.columnObject = columnObject;\n    }\n\n    public RealmList<AllTypes> getColumnRealmList() {\n        return realmGet$columnRealmList();\n    }\n\n    public void setColumnRealmList(RealmList<AllTypes> columnRealmList) {\n        realmSet$columnRealmList(columnRealmList);\n    }\n\n    public RealmList<AllTypes> realmGet$columnRealmList() {\n        return columnRealmList;\n    }\n\n    public void realmSet$columnRealmList(RealmList<AllTypes> columnRealmList) {\n        this.columnRealmList = columnRealmList;\n    }\n\n    public MutableRealmInteger getColumnMutableRealmInteger() {\n        return realmGet$columnMutableRealmInteger();\n    }\n\n    public MutableRealmInteger realmGet$columnMutableRealmInteger() {\n        return columnMutableRealmInteger;\n    }\n\n    public RealmAny getColumnRealmAny() {\n        return realmGet$columnRealmAny();\n    }\n\n    public RealmAny realmGet$columnRealmAny() {\n        return columnRealmAny;\n    }\n\n    public RealmDictionary<AllTypes> getColumnRealmDictionary() {\n        return columnRealmDictionary;\n    }\n\n    public void setColumnRealmDictionary(RealmDictionary<AllTypes> columnRealmDictionary) {\n        this.columnRealmDictionary = columnRealmDictionary;\n    }\n\n    public RealmDictionary<Boolean> getColumnBooleanDictionary() {\n        return columnBooleanDictionary;\n    }\n\n    public void setColumnBooleanDictionary(RealmDictionary<Boolean> columnBooleanDictionary) {\n        this.columnBooleanDictionary = columnBooleanDictionary;\n    }\n\n    public RealmDictionary<String> getColumnStringDictionary() {\n        return columnStringDictionary;\n    }\n\n    public void setColumnStringDictionary(RealmDictionary<String> columnStringDictionary) {\n        this.columnStringDictionary = columnStringDictionary;\n    }\n\n    public RealmDictionary<Integer> getColumnIntegerDictionary() {\n        return columnIntegerDictionary;\n    }\n\n    public void setColumnIntegerDictionary(RealmDictionary<Integer> columnIntegerDictionary) {\n        this.columnIntegerDictionary = columnIntegerDictionary;\n    }\n\n    public RealmDictionary<Float> getColumnFloatDictionary() {\n        return columnFloatDictionary;\n    }\n\n    public void setColumnFloatDictionary(RealmDictionary<Float> columnFloatDictionary) {\n        this.columnFloatDictionary = columnFloatDictionary;\n    }\n\n    public RealmDictionary<Long> getColumnLongDictionary() {\n        return columnLongDictionary;\n    }\n\n    public void setColumnLongDictionary(RealmDictionary<Long> columnLongDictionary) {\n        this.columnLongDictionary = columnLongDictionary;\n    }\n\n    public RealmDictionary<Short> getColumnShortDictionary() {\n        return columnShortDictionary;\n    }\n\n    public void setColumnShortDictionary(RealmDictionary<Short> columnShortDictionary) {\n        this.columnShortDictionary = columnShortDictionary;\n    }\n\n    public RealmDictionary<Double> getColumnDoubleDictionary() {\n        return columnDoubleDictionary;\n    }\n\n    public void setColumnDoubleDictionary(RealmDictionary<Double> columnDoubleDictionary) {\n        this.columnDoubleDictionary = columnDoubleDictionary;\n    }\n\n    public RealmDictionary<Byte> getColumnByteDictionary() {\n        return columnByteDictionary;\n    }\n\n    public void setColumnByteDictionary(RealmDictionary<Byte> columnByteDictionary) {\n        this.columnByteDictionary = columnByteDictionary;\n    }\n\n    public RealmDictionary<byte[]> getColumnBinaryDictionary() {\n        return columnBinaryDictionary;\n    }\n\n    public void setColumnBinaryDictionary(RealmDictionary<byte[]> columnBinaryDictionary) {\n        this.columnBinaryDictionary = columnBinaryDictionary;\n    }\n\n    public RealmDictionary<Date> getColumnDateDictionary() {\n        return columnDateDictionary;\n    }\n\n    public void setColumnDateDictionary(RealmDictionary<Date> columnDateDictionary) {\n        this.columnDateDictionary = columnDateDictionary;\n    }\n\n    public RealmDictionary<ObjectId> getColumnObjectIdDictionary() {\n        return columnObjectIdDictionary;\n    }\n\n    public void setColumnObjectIdDictionary(RealmDictionary<ObjectId> columnObjectIdDictionary) {\n        this.columnObjectIdDictionary = columnObjectIdDictionary;\n    }\n\n    public RealmDictionary<UUID> getColumnUUIDDictionary() {\n        return columnUUIDDictionary;\n    }\n\n    public void setColumnUUIDDictionary(RealmDictionary<UUID> columnUUIDDictionary) {\n        this.columnUUIDDictionary = columnUUIDDictionary;\n    }\n\n    public RealmDictionary<Decimal128> getColumnDecimal128Dictionary() {\n        return columnDecimal128Dictionary;\n    }\n\n    public void setColumnDecimal128Dictionary(RealmDictionary<Decimal128> columnDecimal128Dictionary) {\n        this.columnDecimal128Dictionary = columnDecimal128Dictionary;\n    }\n\n    public RealmDictionary<RealmAny> getColumnRealmAnyDictionary() {\n        return columnRealmAnyDictionary;\n    }\n\n    public void setColumnRealmAnyDictionary(RealmDictionary<RealmAny> columnRealmAnyDictionary) {\n        this.columnRealmAnyDictionary = columnRealmAnyDictionary;\n    }\n}\n"
  },
  {
    "path": "realm/realm-annotations-processor/src/test/resources/some/test/AppModuleAllClasses.java",
    "content": "/*\n * Copyright 2015 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\npackage some.test;\n\nimport java.util.Date;\n\nimport io.realm.RealmList;\nimport io.realm.RealmObject;\nimport io.realm.annotations.PrimaryKey;\nimport io.realm.annotations.RealmModule;\n\n@RealmModule(allClasses = true)\npublic class AppModuleAllClasses {\n\n}\n"
  },
  {
    "path": "realm/realm-annotations-processor/src/test/resources/some/test/AppModuleCustomClasses.java",
    "content": "/*\n * Copyright 2015 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\npackage some.test;\n\nimport java.util.Date;\n\nimport io.realm.RealmList;\nimport io.realm.RealmObject;\nimport io.realm.annotations.PrimaryKey;\nimport io.realm.annotations.RealmModule;\n\n@RealmModule(classes = { AllTypes.class, Simple.class })\npublic class AppModuleCustomClasses {\n\n}\n"
  },
  {
    "path": "realm/realm-annotations-processor/src/test/resources/some/test/BacklinkSelfReference.java",
    "content": "package some.test;\n\nimport io.realm.RealmList;\nimport io.realm.RealmObject;\nimport io.realm.RealmResults;\nimport io.realm.annotations.LinkingObjects;\n\npublic class BacklinkSelfReference extends RealmObject {\n\n    public String id;\n    public BacklinkSelfReference self;\n\n    @LinkingObjects(\"self\")\n    final RealmResults<BacklinkSelfReference> parents = null;\n}\n"
  },
  {
    "path": "realm/realm-annotations-processor/src/test/resources/some/test/BacklinkSource.java",
    "content": "package some.test;\n\nimport io.realm.RealmList;\nimport io.realm.RealmObject;\n\npublic class BacklinkSource extends RealmObject {\n    private String id;\n    private BacklinkTarget child;\n    private RealmList<BacklinkTarget> children;\n}\n"
  },
  {
    "path": "realm/realm-annotations-processor/src/test/resources/some/test/BacklinkTarget.java",
    "content": "package some.test;\n\nimport io.realm.RealmObject;\nimport io.realm.RealmResults;\nimport io.realm.annotations.LinkingObjects;\n\npublic class BacklinkTarget extends RealmObject {\n    private int id;\n\n    @LinkingObjects(\"child\")\n    private final RealmResults<BacklinkSource> simpleParents = null;\n\n    @LinkingObjects(\"children\")\n    private final RealmResults<BacklinkSource> listParents = null;\n}\n"
  },
  {
    "path": "realm/realm-annotations-processor/src/test/resources/some/test/Booleans.java",
    "content": "/*\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\npackage some.test;\n\nimport io.realm.RealmObject;\n\npublic class Booleans extends RealmObject {\n    private boolean done;\n    private boolean isReady;\n    private boolean mCompleted;\n    private boolean anotherBoolean;\n\n    public boolean isDone() {\n        return realmGet$done();\n    }\n\n    public void setDone(boolean done) {\n        realmSet$done(done);\n    }\n\n    public boolean realmGet$done() {\n        return done;\n    }\n\n    public void realmSet$done(boolean done) {\n        this.done = done;\n    }\n\n    public boolean isReady() {\n        return realmGet$isReady();\n    }\n\n    public void setIsReady(boolean isReady) {\n        realmSet$isReady(isReady);\n    }\n\n    public boolean realmGet$isReady() {\n        return isReady;\n    }\n\n    public void realmSet$isReady(boolean isReady) {\n        this.isReady = isReady;\n    }\n\n    public boolean ismCompleted() {\n        return realmGet$mCompleted();\n    }\n\n    public void setMCompleted(boolean mCompleted) {\n        realmSet$mCompleted(mCompleted);\n    }\n\n    public boolean realmGet$mCompleted() {\n        return mCompleted;\n    }\n\n    public void realmSet$mCompleted(boolean mCompleted) {\n        this.mCompleted = mCompleted;\n    }\n\n    public boolean getAnotherBoolean() {\n        return realmGet$anotherBoolean();\n    }\n\n    public void setAnotherBoolean(boolean anotherBoolean) {\n        realmSet$anotherBoolean(anotherBoolean);\n    }\n\n    public boolean realmGet$anotherBoolean() {\n        return anotherBoolean;\n    }\n\n    public void realmSet$anotherBoolean(boolean anotherBoolean) {\n        this.anotherBoolean = anotherBoolean;\n    }\n}\n"
  },
  {
    "path": "realm/realm-annotations-processor/src/test/resources/some/test/ConflictingFieldName.java",
    "content": "/*\n * Copyright 2016 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\npackage some.test;\n\nimport io.realm.RealmObject;\n\n\nimport io.realm.RealmObject;\n\npublic class ConflictingFieldName extends RealmObject {\n    private String realm;\n    private String row;\n    private String listeners;\n    private String pendingQuery;\n    private String isCompleted;\n    private String currentTableVersion;\n\n    public String getRealmString() {\n        return realm;\n    }\n\n    public void setRealmString(String realm) {\n        this.realm = realm;\n    }\n\n    public String getRow() {\n        return row;\n    }\n\n    public void setRow(String row) {\n        this.row = row;\n    }\n\n    public String getListeners() {\n        return listeners;\n    }\n\n    public void setListeners(String listeners) {\n        this.listeners = listeners;\n    }\n\n    public String getPendingQuery() {\n        return pendingQuery;\n    }\n\n    public void setPendingQuery(String pendingQuery) {\n        this.pendingQuery = pendingQuery;\n    }\n\n    public String getIsCompleted() {\n        return isCompleted;\n    }\n\n    public void setIsCompleted(String isCompleted) {\n        this.isCompleted = isCompleted;\n    }\n\n    public String getCurrentTableVersion() {\n        return currentTableVersion;\n    }\n\n    public void setCurrentTableVersion(String currentTableVersion) {\n        this.currentTableVersion = currentTableVersion;\n    }\n}\n"
  },
  {
    "path": "realm/realm-annotations-processor/src/test/resources/some/test/CustomAccessor.java",
    "content": "package some.test;\n\nimport io.realm.RealmObject;\n\npublic class CustomAccessor extends RealmObject {\n\n    public String getColumnString() {\n        return \"No associated field\";\n    }\n}\n"
  },
  {
    "path": "realm/realm-annotations-processor/src/test/resources/some/test/CustomInterface.java",
    "content": "/*\n * Copyright 2016 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\npackage some.test;\n\nimport io.realm.RealmModel;\n\n// Any interface that extends RealmModel is still a RealmModel interface, so the annotation\n// processor should accept it.\npublic interface CustomInterface extends RealmModel {\n}\n\n"
  },
  {
    "path": "realm/realm-annotations-processor/src/test/resources/some/test/EmbeddedClass.java",
    "content": "/*\n * Copyright 2020 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 */\npackage some.test;\n\nimport io.realm.RealmObject;\nimport io.realm.RealmResults;\nimport io.realm.annotations.RealmClass;\n\n@RealmClass(embedded = true)\npublic class EmbeddedClass extends RealmObject {\n    public String name;\n    public int age;\n}\n"
  },
  {
    "path": "realm/realm-annotations-processor/src/test/resources/some/test/EmbeddedClassMissingFieldDescription.java",
    "content": "/*\n * Copyright 2020 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 */\npackage some.test;\n\nimport io.realm.RealmObject;\nimport io.realm.RealmResults;\nimport io.realm.annotations.LinkingObjects;\nimport io.realm.annotations.RealmClass;\nimport io.realm.annotations.Required;\n\n@RealmClass(embedded = true)\npublic class EmbeddedClassMissingFieldDescription extends RealmObject {\n    public String name;\n    public int age;\n\n    @LinkingObjects\n    public final EmbeddedClassParent parent1 = new EmbeddedClassParent();\n}\n"
  },
  {
    "path": "realm/realm-annotations-processor/src/test/resources/some/test/EmbeddedClassMissingFinalOnLinkingObjects.java",
    "content": "/*\n * Copyright 2020 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 */\npackage some.test;\n\nimport io.realm.RealmObject;\nimport io.realm.RealmResults;\nimport io.realm.annotations.LinkingObjects;\nimport io.realm.annotations.RealmClass;\nimport io.realm.annotations.Required;\n\n@RealmClass(embedded = true)\npublic class EmbeddedClassMissingFinalOnLinkingObjects extends RealmObject {\n    public String name;\n    public int age;\n\n    @LinkingObjects(\"child5\")\n    public EmbeddedClassParent parent;\n}\n"
  },
  {
    "path": "realm/realm-annotations-processor/src/test/resources/some/test/EmbeddedClassMultipleRequiredParents.java",
    "content": "/*\n * Copyright 2020 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 */\npackage some.test;\n\nimport io.realm.RealmObject;\nimport io.realm.RealmResults;\nimport io.realm.annotations.LinkingObjects;\nimport io.realm.annotations.RealmClass;\nimport io.realm.annotations.Required;\n\n@RealmClass(embedded = true)\npublic class EmbeddedClassMultipleRequiredParents extends RealmObject {\n    public String name;\n    public int age;\n\n    // If multiple @LinkingObjects are defined\n    // the @Required annotation is not allowed.\n    @Required\n    @LinkingObjects(\"child6\")\n    public final EmbeddedClassParent parent1 = new EmbeddedClassParent();\n\n    @Required\n    @LinkingObjects(\"child7\")\n    public final EmbeddedClassParent parent2 = new EmbeddedClassParent();\n}\n"
  },
  {
    "path": "realm/realm-annotations-processor/src/test/resources/some/test/EmbeddedClassOptionalParents.java",
    "content": "/*\n * Copyright 2020 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 */\npackage some.test;\n\nimport io.realm.RealmObject;\nimport io.realm.RealmResults;\nimport io.realm.annotations.LinkingObjects;\nimport io.realm.annotations.RealmClass;\nimport io.realm.annotations.Required;\n\n@RealmClass(embedded = true)\npublic class EmbeddedClassOptionalParents extends RealmObject {\n    public String name;\n    public int age;\n\n    // If multiple @LinkingObjects are defined\n    // They are not treated as @Required.\n    // This mostly impact Kotlin model classes\n    @LinkingObjects(\"child3\")\n    public final EmbeddedClassParent parent1 = new EmbeddedClassParent(); // Field must be final, because parent cannot change once set\n\n    @LinkingObjects(\"child4\")\n    public final EmbeddedClassParent parent2 = new EmbeddedClassParent(); // Field must be final, because parent cannot change once set\n}\n"
  },
  {
    "path": "realm/realm-annotations-processor/src/test/resources/some/test/EmbeddedClassParent.java",
    "content": "/*\n * Copyright 2020 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 */\npackage some.test;\n\nimport io.realm.RealmObject;\nimport io.realm.RealmResults;\nimport io.realm.annotations.LinkingObjects;\nimport io.realm.annotations.RealmClass;\n\n// This class is only for creating the correct type hiearchy when testing Embedded Objects\n// This class can work as a parent for all legal embedded object classes\npublic class EmbeddedClassParent extends RealmObject {\n    public String name;\n    public int age;\n\n    // Valid single children references\n    public EmbeddedClass child1;\n    public EmbeddedClassRequiredParent child2;\n    public EmbeddedClassOptionalParents child3;\n    public EmbeddedClassOptionalParents child4;\n}\n"
  },
  {
    "path": "realm/realm-annotations-processor/src/test/resources/some/test/EmbeddedClassPrimaryKey.java",
    "content": "/*\n * Copyright 2020 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 */\npackage some.test;\n\nimport io.realm.RealmObject;\nimport io.realm.RealmResults;\nimport io.realm.annotations.LinkingObjects;\nimport io.realm.annotations.PrimaryKey;\nimport io.realm.annotations.RealmClass;\n\n@RealmClass(embedded = true)\npublic class EmbeddedClassPrimaryKey extends RealmObject {\n    @PrimaryKey // This is not allowed in embedded classes\n    public String name;\n    public int age;\n}\n"
  },
  {
    "path": "realm/realm-annotations-processor/src/test/resources/some/test/EmbeddedClassRequiredParent.java",
    "content": "/*\n * Copyright 2020 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 */\npackage some.test;\n\nimport io.realm.RealmObject;\nimport io.realm.RealmResults;\nimport io.realm.annotations.LinkingObjects;\nimport io.realm.annotations.RealmClass;\nimport io.realm.annotations.Required;\n\n@RealmClass(embedded = true)\npublic class EmbeddedClassRequiredParent extends RealmObject {\n    public String name;\n    public int age;\n\n    @Required // Optional, is implied if only a single @LinkingObjects parent is defined\n    @LinkingObjects(\"child2\")\n    public final EmbeddedClassParent parent = new EmbeddedClassParent(); // Field must be final, because parent cannot change once set\n}\n"
  },
  {
    "path": "realm/realm-annotations-processor/src/test/resources/some/test/EmbeddedClassSimpleParent.java",
    "content": "/*\n * Copyright 2020 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 */\npackage some.test;\n\nimport io.realm.RealmList;\nimport io.realm.RealmObject;\nimport io.realm.RealmResults;\nimport io.realm.annotations.LinkingObjects;\nimport io.realm.annotations.PrimaryKey;\nimport io.realm.annotations.RealmClass;\n\n// Simple parent of embedded objects. Used to verify the output of the annotation processor.\npublic class EmbeddedClassSimpleParent extends RealmObject {\n    @PrimaryKey\n    public String id;\n    public EmbeddedClass child;\n    public RealmList<EmbeddedClass> children;\n\n}\n"
  },
  {
    "path": "realm/realm-annotations-processor/src/test/resources/some/test/EmbeddedObject.java",
    "content": "/*\n * Copyright 2020 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\npackage some.test;\n\nimport io.realm.RealmDictionary;\nimport io.realm.RealmObject;\nimport io.realm.annotations.RealmClass;\n\n\n@RealmClass(embedded = true)\npublic class EmbeddedObject extends RealmObject {\n    private String stringColumn;\n}\n"
  },
  {
    "path": "realm/realm-annotations-processor/src/test/resources/some/test/Empty.java",
    "content": "/*\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\npackage some.test;\n\nimport io.realm.RealmObject;\n\npublic class Empty extends RealmObject {\n}\n"
  },
  {
    "path": "realm/realm-annotations-processor/src/test/resources/some/test/ExtendRealmList.java",
    "content": "/*\n * Copyright 2016 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\npackage some.test;\n\nimport io.realm.RealmModel;\nimport io.realm.RealmObject;\nimport io.realm.RealmList;\n\npublic class ExtendRealmList<E extends RealmModel> extends RealmList<E> {\n}\n"
  },
  {
    "path": "realm/realm-annotations-processor/src/test/resources/some/test/FieldNames.java",
    "content": "/*\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\npackage some.test;\n\nimport io.realm.RealmObject;\nimport some.test.Simple;\n\n/**\n * All field names should be allowed. This means that annnotation processor\n * should add a suffix to all fieldNames to avoid naming conflict with\n * internal processor variabels.\n *\n * This class list field names that has caused problems.\n */\npublic class FieldNames extends RealmObject implements FieldNamesRealmProxyInterface {\n\n    private Simple name;\n    private Simple cache;\n\n    public Simple getName() {\n        return realmGet$name();\n    }\n\n    public void setName(Simple name) {\n        realmSet$name(name);\n    }\n\n    public Simple realmGet$name() {\n        return name;\n    }\n\n    public void realmSet$name(Simple name) {\n        this.name = name;\n    }\n\n    public Simple getCache() {\n        return realmGet$cache();\n    }\n\n    public void setCache(Simple cache) {\n        realmSet$cache(cache);\n    }\n\n    public Simple realmGet$cache() {\n        return cache;\n    }\n\n    public void realmSet$cache(Simple cache) {\n        this.cache = cache;\n    }\n}\n"
  },
  {
    "path": "realm/realm-annotations-processor/src/test/resources/some/test/FieldRealmResults.java",
    "content": "package some.test;\n\nimport io.realm.RealmObject;\nimport io.realm.RealmResults;\n\npublic class FieldRealmResults extends RealmObject {\n\n    // RealmResults should only be allowed if combined with a @LinkingObjects annotation\n    private RealmResults<FieldRealmResults> results;\n}\n"
  },
  {
    "path": "realm/realm-annotations-processor/src/test/resources/some/test/Final.java",
    "content": "/*\n * Copyright 2016 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\npackage some.test;\n\nimport io.realm.RealmObject;\n\npublic class Final extends RealmObject {\n    private final String name;\n    private int age;\n\n    public String getName() {\n        return realmGet$name();\n    }\n\n    public void setName(String name) {\n        realmSet$name(name);\n    }\n\n    public String realmGet$name() {\n        return name;\n    }\n\n    public void realmSet$name(String name) {\n        this.name = name;\n    }\n\n    public int getAge() {\n        return realmGet$age();\n    }\n\n    public void setAge(int age) {\n        realmSet$age(age);\n    }\n\n    public int realmGet$age() {\n        return age;\n    }\n\n    public void realmSet$age(int age) {\n        this.age = age;\n    }\n\n    @Override\n    public String toString() {\n        return \"Simple{\" +\n                \"name='\" + name + '\\'' +\n                \", age=\" + age +\n                '}';\n    }\n\n    @Override\n    public boolean equals(Object o) {\n        if (this == o) return true;\n        if (o == null || getClass() != o.getClass()) return false;\n\n        Simple simple = (Simple) o;\n\n        if (age != simple.age) return false;\n        if (name != null ? !name.equals(simple.name) : simple.name != null) return false;\n\n        return true;\n    }\n\n    @Override\n    public int hashCode() {\n        int result = name != null ? name.hashCode() : 0;\n        result = 31 * result + age;\n        return result;\n    }\n}\n"
  },
  {
    "path": "realm/realm-annotations-processor/src/test/resources/some/test/InterfaceList.java",
    "content": "/*\n * Copyright 2016 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\npackage some.test;\n\nimport io.realm.RealmList;\nimport io.realm.RealmModel;\nimport io.realm.annotations.RealmClass;\n\n@RealmClass\npublic class InterfaceList implements CustomInterface {\n    String name;\n    RealmList<CustomInterface> realmList;  // Polymorphism, not yet supported.\n}\n"
  },
  {
    "path": "realm/realm-annotations-processor/src/test/resources/some/test/InterfaceObjectReference.java",
    "content": "/*\n * Copyright 2016 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\npackage some.test;\n\nimport io.realm.RealmList;\nimport io.realm.RealmModel;\nimport io.realm.annotations.RealmClass;\n\n@RealmClass\npublic class InterfaceObjectReference implements CustomInterface {\n    String name;\n    CustomInterface obj; // Polymorphism, not yet supported.\n}\n"
  },
  {
    "path": "realm/realm-annotations-processor/src/test/resources/some/test/InvalidAllTypesModuleMixedParameters.java",
    "content": "/*\n * Copyright 2015 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\npackage some.test;\n\nimport java.util.Date;\n\nimport io.realm.RealmList;\nimport io.realm.RealmObject;\nimport io.realm.annotations.PrimaryKey;\nimport io.realm.annotations.RealmModule;\n\n// Setting both allClasses and classes is not allowed at the same time\n@RealmModule(allClasses = true, classes = { AllTypes.class })\npublic class InvalidAllTypesModuleMixedParameters {\n\n}\n"
  },
  {
    "path": "realm/realm-annotations-processor/src/test/resources/some/test/InvalidAllTypesModuleWrongType.java",
    "content": "/*\n * Copyright 2015 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\npackage some.test;\n\nimport java.util.Date;\n\nimport io.realm.RealmList;\nimport io.realm.RealmObject;\nimport io.realm.annotations.PrimaryKey;\nimport io.realm.annotations.RealmModule;\n\n// Object is not a RealmObject which the Annotation Processor should be able to detect.\n@RealmModule(classes = { Object.class, AllTypes.class })\npublic class InvalidAllTypesModuleWrongType {\n\n}\n"
  },
  {
    "path": "realm/realm-annotations-processor/src/test/resources/some/test/InvalidLibraryModuleMixedParameters.java",
    "content": "/*\n * Copyright 2015 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\npackage some.test;\n\nimport java.util.Date;\n\nimport io.realm.RealmList;\nimport io.realm.RealmObject;\nimport io.realm.annotations.PrimaryKey;\nimport io.realm.annotations.RealmModule;\n\n// Setting both allClasses and classes is not allowed at the same time\n@RealmModule(library = true, allClasses = true, classes = { AllTypes.class })\npublic class InvalidLibraryModuleMixedParameters {\n\n}\n"
  },
  {
    "path": "realm/realm-annotations-processor/src/test/resources/some/test/InvalidLibraryModuleWrongType.java",
    "content": "/*\n * Copyright 2015 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\npackage some.test;\n\nimport java.util.Date;\n\nimport io.realm.RealmList;\nimport io.realm.RealmObject;\nimport io.realm.annotations.PrimaryKey;\nimport io.realm.annotations.RealmModule;\n\n// Object is not a RealmObject which the Annotation Processor should be able to detect.\n@RealmModule(library = true, classes = { Object.class, AllTypes.class })\npublic class InvalidLibraryModuleWrongType {\n\n}\n"
  },
  {
    "path": "realm/realm-annotations-processor/src/test/resources/some/test/InvalidListElementType.java",
    "content": "/*\n * Copyright 2017 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\npackage some.test;\n\nimport java.math.BigInteger;\n\nimport io.realm.RealmList;\nimport io.realm.RealmObject;\nimport io.realm.RealmResults;\nimport io.realm.annotations.LinkingObjects;\n\npublic class InvalidListElementType extends RealmObject {\n    public RealmList<BigInteger> bigIntegerList;\n}\n"
  },
  {
    "path": "realm/realm-annotations-processor/src/test/resources/some/test/InvalidModelRealmModel_1.java",
    "content": "/*\n * Copyright 2016 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\npackage some.test;\n\nimport io.realm.RealmModel;\nimport io.realm.annotations.RealmClass;\n\n// Invalid POJO, this uses the annotation but doesn't implements the RealmModel interface\n@RealmClass\npublic class InvalidModelRealmModel_1 {\n    public String id;\n}\n"
  },
  {
    "path": "realm/realm-annotations-processor/src/test/resources/some/test/InvalidModelRealmModel_2.java",
    "content": "/*\n * Copyright 2016 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\npackage some.test;\n\nimport io.realm.RealmModel;\nimport io.realm.annotations.RealmClass;\n// it's not allowed to extend from another RealmObject\npublic class InvalidModelRealmModel_2 extends Booleans {\n    public String id;\n}\n"
  },
  {
    "path": "realm/realm-annotations-processor/src/test/resources/some/test/InvalidModelRealmModel_3.java",
    "content": "/*\n * Copyright 2016 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\npackage some.test;\n\nimport io.realm.RealmModel;\nimport io.realm.RealmObject;\nimport io.realm.annotations.RealmClass;\n\n// Invalid POJO, you can't extends from another class besides RealmObject\n@RealmClass\npublic class InvalidModelRealmModel_3 extends Booleans implements RealmModel {\n    public String id;\n}\n"
  },
  {
    "path": "realm/realm-annotations-processor/src/test/resources/some/test/InvalidResultsElementType.java",
    "content": "/*\n * Copyright 2017 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\npackage some.test;\n\nimport java.math.BigInteger;\n\nimport io.realm.RealmList;\nimport io.realm.RealmObject;\nimport io.realm.RealmResults;\nimport io.realm.annotations.LinkingObjects;\n\npublic class InvalidResultsElementType extends RealmObject {\n    public InvalidResultsElementType child;\n\n    @LinkingObjects(\"child\")\n    public RealmResults<BigInteger> bigIntegerBacklinks;\n}\n"
  },
  {
    "path": "realm/realm-annotations-processor/src/test/resources/some/test/LibraryModuleAllClasses.java",
    "content": "/*\n * Copyright 2015 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\npackage some.test;\n\nimport java.util.Date;\n\nimport io.realm.RealmList;\nimport io.realm.RealmObject;\nimport io.realm.annotations.PrimaryKey;\nimport io.realm.annotations.RealmModule;\n\n@RealmModule(library = true, allClasses = true)\npublic class LibraryModuleAllClasses {\n\n}\n"
  },
  {
    "path": "realm/realm-annotations-processor/src/test/resources/some/test/LibraryModuleCustomClasses.java",
    "content": "/*\n * Copyright 2015 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\npackage some.test;\n\nimport java.util.Date;\n\nimport io.realm.RealmList;\nimport io.realm.RealmObject;\nimport io.realm.annotations.PrimaryKey;\nimport io.realm.annotations.RealmModule;\n\n@RealmModule(library = true, classes = { AllTypes.class })\npublic class LibraryModuleCustomClasses {\n\n}\n"
  },
  {
    "path": "realm/realm-annotations-processor/src/test/resources/some/test/MissingGenericType.java",
    "content": "/*\n * Copyright 2015 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\npackage some.test;\n\nimport io.realm.RealmObject;\nimport io.realm.RealmList;\n\nclass MissingGenericType extends RealmObject {\n    private RealmList list; // this is an error!\n\n    public RealmList getList() {\n        return list;\n    }\n\n    public void setList(RealmList list) {\n        this.list = list;\n    }\n}"
  },
  {
    "path": "realm/realm-annotations-processor/src/test/resources/some/test/NamePolicyClassOnly.java",
    "content": "/*\n * Copyright 2018 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 */\npackage some.test;\n\nimport io.realm.annotations.RealmClass;\nimport io.realm.RealmObject;\nimport io.realm.annotations.RealmField;\nimport io.realm.annotations.RealmNamingPolicy;\n\n/**\n * Class with only a custom name\n */\n@RealmClass(\"customName\")\npublic class NamePolicyClassOnly extends RealmObject {\n\n    public String firstName;\n    public String lastName;\n}\n"
  },
  {
    "path": "realm/realm-annotations-processor/src/test/resources/some/test/NamePolicyConflictingModuleDefinitionsForAllClasses.java",
    "content": "/*\n * Copyright 2018 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\nimport io.realm.annotations.RealmModule;\nimport io.realm.annotations.RealmNamingPolicy;\nimport some.test.AllTypes;\n\npublic class NamePolicyConflictingModuleDefinitionsForAllClasses {\n\n    @RealmModule(allClasses = true,\n            classNamingPolicy = RealmNamingPolicy.IDENTITY,\n            fieldNamingPolicy = RealmNamingPolicy.IDENTITY)\n    public class MyModule1 {\n\n    }\n\n    @RealmModule(allClasses = true,\n            classNamingPolicy = RealmNamingPolicy.CAMEL_CASE,\n            fieldNamingPolicy = RealmNamingPolicy.CAMEL_CASE)\n    public class MyModule2 {\n\n    }\n\n}\n"
  },
  {
    "path": "realm/realm-annotations-processor/src/test/resources/some/test/NamePolicyConflictingModuleDefinitionsForMixedDefinitions.java",
    "content": "/*\n * Copyright 2018 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\nimport io.realm.annotations.RealmModule;\nimport io.realm.annotations.RealmNamingPolicy;\nimport some.test.Simple;\n\npublic class NamePolicyConflictingModuleDefinitionsForMixedDefinitions {\n\n    @RealmModule(classes = { Simple.class },\n            classNamingPolicy = RealmNamingPolicy.IDENTITY,\n            fieldNamingPolicy = RealmNamingPolicy.IDENTITY)\n    public class MyModule1 {\n\n    }\n\n    @RealmModule(allClasses = true,\n            classNamingPolicy = RealmNamingPolicy.CAMEL_CASE,\n            fieldNamingPolicy = RealmNamingPolicy.CAMEL_CASE)\n    public class MyModule2 {\n\n    }\n\n}\n"
  },
  {
    "path": "realm/realm-annotations-processor/src/test/resources/some/test/NamePolicyConflictingModuleDefinitionsForNamedClasses.java",
    "content": "/*\n * Copyright 2018 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\nimport io.realm.annotations.RealmModule;\nimport io.realm.annotations.RealmNamingPolicy;\nimport some.test.Simple;\n\npublic class NamePolicyConflictingModuleDefinitionsForNamedClasses {\n\n    @RealmModule(classes = { Simple.class },\n            classNamingPolicy = RealmNamingPolicy.IDENTITY,\n            fieldNamingPolicy = RealmNamingPolicy.IDENTITY)\n    public class MyModule1 {\n\n    }\n\n    @RealmModule(classes = { Simple.class },\n            classNamingPolicy = RealmNamingPolicy.CAMEL_CASE,\n            fieldNamingPolicy = RealmNamingPolicy.CAMEL_CASE)\n    public class MyModule2 {\n\n    }\n\n}\n"
  },
  {
    "path": "realm/realm-annotations-processor/src/test/resources/some/test/NamePolicyFieldNameOnly.java",
    "content": "/*\n * Copyright 2018 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 */\npackage some.test;\n\nimport io.realm.annotations.RealmClass;\nimport io.realm.RealmObject;\nimport io.realm.annotations.RealmField;\nimport io.realm.annotations.RealmNamingPolicy;\n\n/**\n * Class with only a field name annotation\n */\npublic class NamePolicyFieldNameOnly extends RealmObject {\n\n    @RealmField(\"first_name\")\n    public String firstName;\n    public String lastName;\n}\n"
  },
  {
    "path": "realm/realm-annotations-processor/src/test/resources/some/test/NamePolicyMixedClassSettings.java",
    "content": "/*\n * Copyright 2018 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 */\npackage some.test;\n\nimport io.realm.annotations.RealmClass;\nimport io.realm.RealmObject;\nimport io.realm.annotations.RealmField;\nimport io.realm.annotations.RealmNamingPolicy;\n\n/**\n * Class with mixed settings class/field name settings\n */\n@RealmClass(name = \"customName\", fieldNamingPolicy = RealmNamingPolicy.PASCAL_CASE)\npublic class NamePolicyMixedClassSettings extends RealmObject {\n\n    @RealmField(name = \"first_name\")\n    public String firstName;\n    public String lastName;\n}\n"
  },
  {
    "path": "realm/realm-annotations-processor/src/test/resources/some/test/NamePolicyModule.java",
    "content": "/*\n * Copyright 2018 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 */\npackage some.test;\n\nimport io.realm.annotations.RealmModule;\nimport io.realm.annotations.RealmNamingPolicy;\n\n@RealmModule(allClasses = true, classNamingPolicy = RealmNamingPolicy.PASCAL_CASE, fieldNamingPolicy = RealmNamingPolicy.PASCAL_CASE)\npublic class NamePolicyModule {\n\n}\n"
  },
  {
    "path": "realm/realm-annotations-processor/src/test/resources/some/test/NamePolicyModuleDefaults.java",
    "content": "/*\n * Copyright 2018 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 */\npackage some.test;\n\nimport io.realm.RealmObject;\nimport io.realm.annotations.RealmField;\nimport io.realm.annotations.RealmNamingPolicy;\n\n/**\n * Class which inherit all naming policies from the module.\n */\npublic class NamePolicyModuleDefaults extends RealmObject {\n    public String firstName;\n    public String lastName;\n}\n"
  },
  {
    "path": "realm/realm-annotations-processor/src/test/resources/some/test/NoAccessors.java",
    "content": "/*\n * Copyright 2015 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\npackage io.realm.entities;\n\nimport java.util.Date;\n\nimport io.realm.RealmList;\nimport io.realm.RealmObject;\nimport some.test.AllTypes;\n\npublic class NoAccessors extends RealmObject {\n    private String columnString;\n    private long columnLong;\n    private float columnFloat;\n    private double columnDouble;\n    private boolean columnBoolean;\n    private Date columnDate;\n    private byte[] columnBinary;\n    private AllTypes columnRealmObject;\n    private RealmList<AllTypes> columnRealmList;\n}\n"
  },
  {
    "path": "realm/realm-annotations-processor/src/test/resources/some/test/NullTypes.java",
    "content": "/*\n * Copyright 2015 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\npackage some.test;\n\nimport org.bson.types.Decimal128;\nimport org.bson.types.ObjectId;\n\nimport java.lang.String;\nimport java.util.Date;\n\nimport io.realm.RealmList;\nimport io.realm.RealmObject;\nimport io.realm.annotations.Required;\n\npublic class NullTypes extends RealmObject {\n    @Required\n    private String fieldStringNotNull;\n    private String fieldStringNull;\n\n    @Required\n    private Boolean fieldBooleanNotNull;\n    private Boolean fieldBooleanNull;\n\n    @Required\n    private byte[] fieldBytesNotNull;\n    private byte[] fieldBytesNull;\n\n    @Required\n    private Byte fieldByteNotNull;\n    private Byte fieldByteNull;\n\n    @Required\n    private Short fieldShortNotNull;\n    private Short fieldShortNull;\n\n    @Required\n    private Integer fieldIntegerNotNull;\n    private Integer fieldIntegerNull;\n\n    @Required\n    private Long fieldLongNotNull;\n    private Long fieldLongNull;\n\n    @Required\n    private Float fieldFloatNotNull;\n    private Float fieldFloatNull;\n\n    @Required\n    private Double fieldDoubleNotNull;\n    private Double fieldDoubleNull;\n\n    @Required\n    private Date fieldDateNotNull;\n    private Date fieldDateNull;\n\n    @Required\n    private Decimal128 fieldDecimal128NotNull;\n    private Decimal128 fieldDecimal128Null;\n\n    @Required\n    private ObjectId fieldObjectIdNotNull;\n    private ObjectId fieldObjectIdNull;\n\n    private NullTypes fieldObjectNull;\n\n    @Required\n    private RealmList<String> fieldStringListNotNull;\n    private RealmList<String> fieldStringListNull;\n\n    @Required\n    private RealmList<byte[]> fieldBinaryListNotNull;\n    private RealmList<byte[]> fieldBinaryListNull;\n\n    @Required\n    private RealmList<Boolean> fieldBooleanListNotNull;\n    private RealmList<Boolean> fieldBooleanListNull;\n\n    @Required\n    private RealmList<Long> fieldLongListNotNull;\n    private RealmList<Long> fieldLongListNull;\n\n    @Required\n    private RealmList<Integer> fieldIntegerListNotNull;\n    private RealmList<Integer> fieldIntegerListNull;\n\n    @Required\n    private RealmList<Short> fieldShortListNotNull;\n    private RealmList<Short> fieldShortListNull;\n\n    @Required\n    private RealmList<Byte> fieldByteListNotNull;\n    private RealmList<Byte> fieldByteListNull;\n\n    @Required\n    private RealmList<Double> fieldDoubleListNotNull;\n    private RealmList<Double> fieldDoubleListNull;\n\n    @Required\n    private RealmList<Float> fieldFloatListNotNull;\n    private RealmList<Float> fieldFloatListNull;\n\n    @Required\n    private RealmList<Date> fieldDateListNotNull;\n    private RealmList<Date> fieldDateListNull;\n\n    @Required\n    private RealmList<Decimal128> fieldDecimal128ListNotNull;\n    private RealmList<Decimal128> fieldDecimal128ListNull;\n\n    @Required\n    private RealmList<ObjectId> fieldObjectIdListNotNull;\n    private RealmList<ObjectId> fieldObjectIdListNull;\n\n    public String getFieldStringNotNull() {\n        return realmGet$fieldStringNotNull();\n    }\n\n    public void setFieldStringNotNull(String fieldStringNotNull) {\n        realmSet$fieldStringNotNull(fieldStringNotNull);\n    }\n\n    public String realmGet$fieldStringNotNull() {\n        return fieldStringNotNull;\n    }\n\n    public void realmSet$fieldStringNotNull(String fieldStringNotNull) {\n        this.fieldStringNotNull = fieldStringNotNull;\n    }\n\n    public String getFieldStringNull() {\n        return realmGet$fieldStringNull();\n    }\n\n    public void setFieldStringNull(String fieldStringNull) {\n        realmSet$fieldStringNull(fieldStringNull);\n    }\n\n    public String realmGet$fieldStringNull() {\n        return fieldStringNull;\n    }\n\n    public void realmSet$fieldStringNull(String fieldStringNull) {\n        this.fieldStringNull = fieldStringNull;\n    }\n\n    public Boolean getFieldBooleanNotNull() {\n        return realmGet$fieldBooleanNotNull();\n    }\n\n    public void setFieldBooleanNotNull(Boolean fieldBooleanNotNull) {\n        realmSet$fieldBooleanNotNull(fieldBooleanNotNull);\n    }\n\n    public Boolean realmGet$fieldBooleanNotNull() {\n        return fieldBooleanNotNull;\n    }\n\n    public void realmSet$fieldBooleanNotNull(Boolean fieldBooleanNotNull) {\n        this.fieldBooleanNotNull = fieldBooleanNotNull;\n    }\n\n    public Boolean getFieldBooleanNull() {\n        return realmGet$fieldBooleanNull();\n    }\n\n    public void setFieldBooleanNull(Boolean fieldBooleanNull) {\n        realmSet$fieldBooleanNull(fieldBooleanNull);\n    }\n\n    public Boolean realmGet$fieldBooleanNull() {\n        return fieldBooleanNull;\n    }\n\n    public void realmSet$fieldBooleanNull(Boolean fieldBooleanNull) {\n        this.fieldBooleanNull = fieldBooleanNull;\n    }\n\n    public byte[] getFieldBytesNotNull() {\n        return realmGet$fieldBytesNotNull();\n    }\n\n    public void setFieldBytesNotNull(byte[] fieldBytesNotNull) {\n        realmSet$fieldBytesNotNull(fieldBytesNotNull);\n    }\n\n    public byte[] realmGet$fieldBytesNotNull() {\n        return fieldBytesNotNull;\n    }\n\n    public void realmSet$fieldBytesNotNull(byte[] fieldBytesNotNull) {\n        this.fieldBytesNotNull = fieldBytesNotNull;\n    }\n\n    public byte[] getFieldBytesNull() {\n        return realmGet$fieldBytesNull();\n    }\n\n    public void setFieldBytesNull(byte[] fieldBytesNull) {\n        realmSet$fieldBytesNull(fieldBytesNull);\n    }\n\n    public byte[] realmGet$fieldBytesNull() {\n        return fieldBytesNull;\n    }\n\n    public void realmSet$fieldBytesNull(byte[] fieldBytesNull) {\n        this.fieldBytesNull = fieldBytesNull;\n    }\n\n    public Byte getFieldByteNotNull() {\n        return realmGet$fieldByteNotNull();\n    }\n\n    public void setFieldByteNotNull(Byte fieldByteNotNull) {\n        realmSet$fieldByteNotNull(fieldByteNotNull);\n    }\n\n    public Byte realmGet$fieldByteNotNull() {\n        return fieldByteNotNull;\n    }\n\n    public void realmSet$fieldByteNotNull(Byte fieldByteNotNull) {\n        this.fieldByteNotNull = fieldByteNotNull;\n    }\n\n    public Byte getFieldByteNull() {\n        return realmGet$fieldByteNull();\n    }\n\n    public void setFieldByteNull(Byte fieldByteNull) {\n        realmSet$fieldByteNull(fieldByteNull);\n    }\n\n    public Byte realmGet$fieldByteNull() {\n        return fieldByteNull;\n    }\n\n    public void realmSet$fieldByteNull(Byte fieldByteNull) {\n        this.fieldByteNull = fieldByteNull;\n    }\n\n    public Short getFieldShortNotNull() {\n        return realmGet$fieldShortNotNull();\n    }\n\n    public void setFieldShortNotNull(Short fieldShortNotNull) {\n        realmSet$fieldShortNotNull(fieldShortNotNull);\n    }\n\n    public Short realmGet$fieldShortNotNull() {\n        return fieldShortNotNull;\n    }\n\n    public void realmSet$fieldShortNotNull(Short fieldShortNotNull) {\n        this.fieldShortNotNull = fieldShortNotNull;\n    }\n\n    public Short getFieldShortNull() {\n        return realmGet$fieldShortNull();\n    }\n\n    public void setFieldShortNull(Short fieldShortNull) {\n        realmSet$fieldShortNull(fieldShortNull);\n    }\n\n    public Short realmGet$fieldShortNull() {\n        return fieldShortNull;\n    }\n\n    public void realmSet$fieldShortNull(Short fieldShortNull) {\n        this.fieldShortNull = fieldShortNull;\n    }\n\n    public Integer getFieldIntegerNotNull() {\n        return realmGet$fieldIntegerNotNull();\n    }\n\n    public void setFieldIntegerNotNull(Integer fieldIntegerNotNull) {\n        realmSet$fieldIntegerNotNull(fieldIntegerNotNull);\n    }\n\n    public Integer realmGet$fieldIntegerNotNull() {\n        return fieldIntegerNotNull;\n    }\n\n    public void realmSet$fieldIntegerNotNull(Integer fieldIntegerNotNull) {\n        this.fieldIntegerNotNull = fieldIntegerNotNull;\n    }\n\n    public Integer getFieldIntegerNull() {\n        return realmGet$fieldIntegerNull();\n    }\n\n    public void setFieldIntegerNull(Integer fieldIntegerNull) {\n        realmSet$fieldIntegerNull(fieldIntegerNull);\n    }\n\n    public Integer realmGet$fieldIntegerNull() {\n        return fieldIntegerNull;\n    }\n\n    public void realmSet$fieldIntegerNull(Integer fieldIntegerNull) {\n        this.fieldIntegerNull = fieldIntegerNull;\n    }\n\n    public Long getFieldLongNotNull() {\n        return realmGet$fieldLongNotNull();\n    }\n\n    public void setFieldLongNotNull(Long fieldLongNotNull) {\n        realmSet$fieldLongNotNull(fieldLongNotNull);\n    }\n\n    public Long realmGet$fieldLongNotNull() {\n        return fieldLongNotNull;\n    }\n\n    public void realmSet$fieldLongNotNull(Long fieldLongNotNull) {\n        this.fieldLongNotNull = fieldLongNotNull;\n    }\n\n    public Long getFieldLongNull() {\n        return realmGet$fieldLongNull();\n    }\n\n    public void setFieldLongNull(Long fieldLongNull) {\n        realmSet$fieldLongNull(fieldLongNull);\n    }\n\n    public Long realmGet$fieldLongNull() {\n        return fieldLongNull;\n    }\n\n    public void realmSet$fieldLongNull(Long fieldLongNull) {\n        this.fieldLongNull = fieldLongNull;\n    }\n\n    public Float getFieldFloatNotNull() {\n        return realmGet$fieldFloatNotNull();\n    }\n\n    public void setFieldFloatNotNull(Float fieldFloatNotNull) {\n        realmSet$fieldFloatNotNull(fieldFloatNotNull);\n    }\n\n    public Float realmGet$fieldFloatNotNull() {\n        return fieldFloatNotNull;\n    }\n\n    public void realmSet$fieldFloatNotNull(Float fieldFloatNotNull) {\n        this.fieldFloatNotNull = fieldFloatNotNull;\n    }\n\n    public Float getFieldFloatNull() {\n        return realmGet$fieldFloatNull();\n    }\n\n    public void setFieldFloatNull(Float fieldFloatNull) {\n        realmSet$fieldFloatNull(fieldFloatNull);\n    }\n\n    public Float realmGet$fieldFloatNull() {\n        return fieldFloatNull;\n    }\n\n    public void realmSet$fieldFloatNull(Float fieldFloatNull) {\n        this.fieldFloatNull = fieldFloatNull;\n    }\n\n    public Double getFieldDoubleNotNull() {\n        return realmGet$fieldDoubleNotNull();\n    }\n\n    public void setFieldDoubleNotNull(Double fieldDoubleNotNull) {\n        realmSet$fieldDoubleNotNull(fieldDoubleNotNull);\n    }\n\n    public Double realmGet$fieldDoubleNotNull() {\n        return fieldDoubleNotNull;\n    }\n\n    public void realmSet$fieldDoubleNotNull(Double fieldDoubleNotNull) {\n        this.fieldDoubleNotNull = fieldDoubleNotNull;\n    }\n\n    public Double getFieldDoubleNull() {\n        return realmGet$fieldDoubleNull();\n    }\n\n    public void setFieldDoubleNull(Double fieldDoubleNull) {\n        realmSet$fieldDoubleNull(fieldDoubleNull);\n    }\n\n    public Double realmGet$fieldDoubleNull() {\n        return fieldDoubleNull;\n    }\n\n    public void realmSet$fieldDoubleNull(Double fieldDoubleNull) {\n        this.fieldDoubleNull = fieldDoubleNull;\n    }\n\n    public Date getFieldDateNotNull() {\n        return realmGet$fieldDateNotNull();\n    }\n\n    public void setFieldDateNotNull(Date fieldDateNotNull) {\n        realmSet$fieldDateNotNull(fieldDateNotNull);\n    }\n\n    public Date realmGet$fieldDateNotNull() {\n        return fieldDateNotNull;\n    }\n\n    public void realmSet$fieldDateNotNull(Date fieldDateNotNull) {\n        this.fieldDateNotNull = fieldDateNotNull;\n    }\n\n    public Date getFieldDateNull() {\n        return realmGet$fieldDateNull();\n    }\n\n    public void setFieldDateNull(Date fieldDateNull) {\n        realmSet$fieldDateNull(fieldDateNull);\n    }\n\n    public Date realmGet$fieldDateNull() {\n        return fieldDateNull;\n    }\n\n    public void realmSet$fieldDateNull(Date fieldDateNull) {\n        this.fieldDateNull = fieldDateNull;\n    }\n\n    public NullTypes getFieldObjectNull() {\n        return realmGet$fieldObjectNull();\n    }\n\n    public void setFieldObjectNull(NullTypes fieldObjectNull) {\n        realmSet$fieldObjectNull(fieldObjectNull);\n    }\n\n    public NullTypes realmGet$fieldObjectNull() {\n        return fieldObjectNull;\n    }\n\n    public void realmSet$fieldObjectNull(NullTypes fieldObjectNull) {\n        this.fieldObjectNull = fieldObjectNull;\n    }\n}\n"
  },
  {
    "path": "realm/realm-annotations-processor/src/test/resources/some/test/RealmDictionaryMissingGenerics.java",
    "content": "/*\n * Copyright 2020 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\npackage some.test;\n\nimport io.realm.RealmDictionary;\nimport io.realm.RealmObject;\n\n/**\n * Dictionaries must specify a generic type. With this class we check that the annotation processor\n * detects this class has a RealmDictionary field missing the required type and therefore should\n * fail in compile time.\n */\npublic class RealmDictionaryMissingGenerics extends RealmObject {\n\n    private RealmDictionary dictionary; // this is an error!\n}\n"
  },
  {
    "path": "realm/realm-annotations-processor/src/test/resources/some/test/RealmDictionaryModel.java",
    "content": "/*\n * Copyright 2020 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\npackage some.test;\n\nimport org.bson.types.Decimal128;\nimport org.bson.types.ObjectId;\n\nimport java.util.Date;\nimport java.util.UUID;\n\nimport io.realm.RealmAny;\nimport io.realm.RealmDictionary;\nimport io.realm.RealmObject;\nimport io.realm.annotations.Required;\n\npublic class RealmDictionaryModel extends RealmObject {\n\n    private final RealmDictionary<Boolean> immutableRealmDictionaryField = new RealmDictionary();\n\n    @Required private RealmDictionary<Boolean> myRequiredBooleanRealmDictionary;\n    @Required private RealmDictionary<String> myRequiredStringRealmDictionary;\n    @Required private RealmDictionary<Integer> myRequiredIntegerRealmDictionary;\n    @Required private RealmDictionary<Float> myRequiredFloatRealmDictionary;\n    @Required private RealmDictionary<Long> myRequiredLongRealmDictionary;\n    @Required private RealmDictionary<Short> myRequiredShortRealmDictionary;\n    @Required private RealmDictionary<Byte> myRequiredByteRealmDictionary;\n    @Required private RealmDictionary<Double> myRequiredDoubleRealmDictionary;\n    @Required private RealmDictionary<Date> myRequiredDateRealmDictionary;\n    @Required private RealmDictionary<byte[]> myRequiredPrimitiveBinaryRealmDictionary;\n    @Required private RealmDictionary<ObjectId> myRequiredObjectIdRealmDictionary;\n    @Required private RealmDictionary<UUID> myRequiredUUIDRealmDictionary;\n    @Required private RealmDictionary<Decimal128> myRequiredDecimal128IdRealmDictionary;\n\n    private RealmDictionary<RealmDictionaryModel> myRealmDictionaryModel;\n    private RealmDictionary<RealmAny> myRealmAnyRealmDictionary;\n    private RealmDictionary<Boolean> myBooleanRealmDictionary;\n    private RealmDictionary<String> myStringRealmDictionary;\n    private RealmDictionary<Integer> myIntegerRealmDictionary;\n    private RealmDictionary<Float> myFloatRealmDictionary;\n    private RealmDictionary<Long> myLongRealmDictionary;\n    private RealmDictionary<Short> myShortRealmDictionary;\n    private RealmDictionary<Byte> myByteRealmDictionary;\n    private RealmDictionary<Double> myDoubleRealmDictionary;\n    private RealmDictionary<Date> myDateRealmDictionary;\n    private RealmDictionary<byte[]> myBinaryRealmDictionary;\n    private RealmDictionary<ObjectId> myObjectIdRealmDictionary;\n    private RealmDictionary<UUID> myUUIDRealmDictionary;\n    private RealmDictionary<Decimal128> myDecimal128IdRealmDictionary;\n\n    public RealmDictionary<Boolean> getMyRequiredBooleanRealmDictionary() {\n        return myRequiredBooleanRealmDictionary;\n    }\n\n    public void setMyRequiredBooleanRealmDictionary(RealmDictionary<Boolean> myRequiredBooleanRealmDictionary) {\n        this.myRequiredBooleanRealmDictionary = myRequiredBooleanRealmDictionary;\n    }\n\n    public RealmDictionary<String> getMyRequiredStringRealmDictionary() {\n        return myRequiredStringRealmDictionary;\n    }\n\n    public void setMyRequiredStringRealmDictionary(RealmDictionary<String> myRequiredStringRealmDictionary) {\n        this.myRequiredStringRealmDictionary = myRequiredStringRealmDictionary;\n    }\n\n    public RealmDictionary<Integer> getMyRequiredIntegerRealmDictionary() {\n        return myRequiredIntegerRealmDictionary;\n    }\n\n    public void setMyRequiredIntegerRealmDictionary(RealmDictionary<Integer> myRequiredIntegerRealmDictionary) {\n        this.myRequiredIntegerRealmDictionary = myRequiredIntegerRealmDictionary;\n    }\n\n    public RealmDictionary<Float> getMyRequiredFloatRealmDictionary() {\n        return myRequiredFloatRealmDictionary;\n    }\n\n    public void setMyRequiredFloatRealmDictionary(RealmDictionary<Float> myRequiredFloatRealmDictionary) {\n        this.myRequiredFloatRealmDictionary = myRequiredFloatRealmDictionary;\n    }\n\n    public RealmDictionary<Long> getMyRequiredLongRealmDictionary() {\n        return myRequiredLongRealmDictionary;\n    }\n\n    public void setMyRequiredLongRealmDictionary(RealmDictionary<Long> myRequiredLongRealmDictionary) {\n        this.myRequiredLongRealmDictionary = myRequiredLongRealmDictionary;\n    }\n\n    public RealmDictionary<Short> getMyRequiredShortRealmDictionary() {\n        return myRequiredShortRealmDictionary;\n    }\n\n    public void setMyRequiredShortRealmDictionary(RealmDictionary<Short> myRequiredShortRealmDictionary) {\n        this.myRequiredShortRealmDictionary = myRequiredShortRealmDictionary;\n    }\n\n    public RealmDictionary<Byte> getMyRequiredByteRealmDictionary() {\n        return myRequiredByteRealmDictionary;\n    }\n\n    public void setMyRequiredByteRealmDictionary(RealmDictionary<Byte> myRequiredByteRealmDictionary) {\n        this.myRequiredByteRealmDictionary = myRequiredByteRealmDictionary;\n    }\n\n    public RealmDictionary<Double> getMyRequiredDoubleRealmDictionary() {\n        return myRequiredDoubleRealmDictionary;\n    }\n\n    public void setMyRequiredDoubleRealmDictionary(RealmDictionary<Double> myRequiredDoubleRealmDictionary) {\n        this.myRequiredDoubleRealmDictionary = myRequiredDoubleRealmDictionary;\n    }\n\n    public RealmDictionary<Date> getMyRequiredDateRealmDictionary() {\n        return myRequiredDateRealmDictionary;\n    }\n\n    public void setMyRequiredDateRealmDictionary(RealmDictionary<Date> myRequiredDateRealmDictionary) {\n        this.myRequiredDateRealmDictionary = myRequiredDateRealmDictionary;\n    }\n\n    public RealmDictionary<byte[]> getMyRequiredPrimitiveBinaryRealmDictionary() {\n        return myRequiredPrimitiveBinaryRealmDictionary;\n    }\n\n    public void setMyRequiredPrimitiveBinaryRealmDictionary(RealmDictionary<byte[]> myRequiredPrimitiveBinaryRealmDictionary) {\n        this.myRequiredPrimitiveBinaryRealmDictionary = myRequiredPrimitiveBinaryRealmDictionary;\n    }\n\n    public RealmDictionary<ObjectId> getMyRequiredObjectIdRealmDictionary() {\n        return myRequiredObjectIdRealmDictionary;\n    }\n\n    public void setMyRequiredObjectIdRealmDictionary(RealmDictionary<ObjectId> myRequiredObjectIdRealmDictionary) {\n        this.myRequiredObjectIdRealmDictionary = myRequiredObjectIdRealmDictionary;\n    }\n\n    public RealmDictionary<UUID> getMyRequiredUUIDRealmDictionary() {\n        return myRequiredUUIDRealmDictionary;\n    }\n\n    public void setMyRequiredUUIDRealmDictionary(RealmDictionary<UUID> myRequiredUUIDRealmDictionary) {\n        this.myRequiredUUIDRealmDictionary = myRequiredUUIDRealmDictionary;\n    }\n\n    public RealmDictionary<Decimal128> getMyRequiredDecimal128IdRealmDictionary() {\n        return myRequiredDecimal128IdRealmDictionary;\n    }\n\n    public void setMyRequiredDecimal128IdRealmDictionary(RealmDictionary<Decimal128> myRequiredDecimal128IdRealmDictionary) {\n        this.myRequiredDecimal128IdRealmDictionary = myRequiredDecimal128IdRealmDictionary;\n    }\n\n    public RealmDictionary<RealmDictionaryModel> getMyRealmDictionaryModel() {\n        return myRealmDictionaryModel;\n    }\n\n    public void setMyRealmDictionaryModel(RealmDictionary<RealmDictionaryModel> myRealmDictionaryModel) {\n        this.myRealmDictionaryModel = myRealmDictionaryModel;\n    }\n\n    public RealmDictionary<Boolean> getImmutableRealmDictionaryField() {\n        return immutableRealmDictionaryField;\n    }\n\n    public RealmDictionary<RealmAny> getMyRealmAnyRealmDictionary() {\n        return myRealmAnyRealmDictionary;\n    }\n\n    public void setMyRealmAnyRealmDictionary(RealmDictionary<RealmAny> myRealmAnyRealmDictionary) {\n        this.myRealmAnyRealmDictionary = myRealmAnyRealmDictionary;\n    }\n\n    public RealmDictionary<Boolean> getMyBooleanRealmDictionary() {\n        return myBooleanRealmDictionary;\n    }\n\n    public void setMyBooleanRealmDictionary(RealmDictionary<Boolean> myBooleanRealmDictionary) {\n        this.myBooleanRealmDictionary = myBooleanRealmDictionary;\n    }\n\n    public RealmDictionary<String> getMyStringRealmDictionary() {\n        return myStringRealmDictionary;\n    }\n\n    public void setMyStringRealmDictionary(RealmDictionary<String> myStringRealmDictionary) {\n        this.myStringRealmDictionary = myStringRealmDictionary;\n    }\n\n    public RealmDictionary<Integer> getMyIntegerRealmDictionary() {\n        return myIntegerRealmDictionary;\n    }\n\n    public void setMyIntegerRealmDictionary(RealmDictionary<Integer> myIntegerRealmDictionary) {\n        this.myIntegerRealmDictionary = myIntegerRealmDictionary;\n    }\n\n    public RealmDictionary<Float> getMyFloatRealmDictionary() {\n        return myFloatRealmDictionary;\n    }\n\n    public void setMyFloatRealmDictionary(RealmDictionary<Float> myFloatRealmDictionary) {\n        this.myFloatRealmDictionary = myFloatRealmDictionary;\n    }\n\n    public RealmDictionary<Long> getMyLongRealmDictionary() {\n        return myLongRealmDictionary;\n    }\n\n    public void setMyLongRealmDictionary(RealmDictionary<Long> myLongRealmDictionary) {\n        this.myLongRealmDictionary = myLongRealmDictionary;\n    }\n\n    public RealmDictionary<Short> getMyShortRealmDictionary() {\n        return myShortRealmDictionary;\n    }\n\n    public void setMyShortRealmDictionary(RealmDictionary<Short> myShortRealmDictionary) {\n        this.myShortRealmDictionary = myShortRealmDictionary;\n    }\n\n    public RealmDictionary<Byte> getMyByteRealmDictionary() {\n        return myByteRealmDictionary;\n    }\n\n    public void setMyByteRealmDictionary(RealmDictionary<Byte> myByteRealmDictionary) {\n        this.myByteRealmDictionary = myByteRealmDictionary;\n    }\n\n    public RealmDictionary<Date> getMyDateRealmDictionary() {\n        return myDateRealmDictionary;\n    }\n\n    public void setMyDateRealmDictionary(RealmDictionary<Date> myDateRealmDictionary) {\n        this.myDateRealmDictionary = myDateRealmDictionary;\n    }\n\n    public RealmDictionary<Double> getMyDoubleRealmDictionary() {\n        return myDoubleRealmDictionary;\n    }\n\n    public void setMyDoubleRealmDictionary(RealmDictionary<Double> myDoubleRealmDictionary) {\n        this.myDoubleRealmDictionary = myDoubleRealmDictionary;\n    }\n\n    public RealmDictionary<byte[]> getMyBinaryRealmDictionary() {\n        return myBinaryRealmDictionary;\n    }\n\n    public void setBinaryRealmDictionary(RealmDictionary<byte[]> myBinaryRealmDictionary) {\n        this.myBinaryRealmDictionary = myBinaryRealmDictionary;\n    }\n\n    public RealmDictionary<ObjectId> getMyObjectIdRealmDictionary() {\n        return myObjectIdRealmDictionary;\n    }\n\n    public void setMyObjectIdRealmDictionary(RealmDictionary<ObjectId> myObjectIdRealmDictionary) {\n        this.myObjectIdRealmDictionary = myObjectIdRealmDictionary;\n    }\n\n    public RealmDictionary<UUID> getMyUUIDRealmDictionary() {\n        return myUUIDRealmDictionary;\n    }\n\n    public void setMyUUIDRealmDictionary(RealmDictionary<UUID> myUUIDRealmDictionary) {\n        this.myUUIDRealmDictionary = myUUIDRealmDictionary;\n    }\n\n    public RealmDictionary<Decimal128> getMyDecimal128IdRealmDictionary() {\n        return myDecimal128IdRealmDictionary;\n    }\n\n    public void setMyDecimal128IdRealmDictionary(RealmDictionary<Decimal128> myDecimal128IdRealmDictionary) {\n        this.myDecimal128IdRealmDictionary = myDecimal128IdRealmDictionary;\n    }\n}\n"
  },
  {
    "path": "realm/realm-annotations-processor/src/test/resources/some/test/RealmDictionaryModelRealmAnyRequired.java",
    "content": "/*\n * Copyright 2020 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\npackage some.test;\n\nimport io.realm.RealmAny;\nimport io.realm.RealmDictionary;\nimport io.realm.RealmObject;\nimport io.realm.annotations.Required;\n\npublic class RealmDictionaryModelRealmAnyRequired extends RealmObject {\n\n    @Required private RealmDictionary<RealmAny> myRequiredRealmAnyRealmDictionary;\n\n    public RealmDictionary<RealmAny> getMyRequiredRealmAnyRealmDictionary() {\n        return myRequiredRealmAnyRealmDictionary;\n    }\n\n    public void setMyRequiredRealmAnyRealmDictionary(RealmDictionary<RealmAny> myRequiredRealmAnyRealmDictionary) {\n        this.myRequiredRealmAnyRealmDictionary = myRequiredRealmAnyRealmDictionary;\n    }\n}\n"
  },
  {
    "path": "realm/realm-annotations-processor/src/test/resources/some/test/RealmDictionaryModelRealmModelRequired.java",
    "content": "/*\n * Copyright 2020 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\npackage some.test;\n\nimport io.realm.RealmDictionary;\nimport io.realm.RealmObject;\nimport io.realm.annotations.Required;\n\npublic class RealmDictionaryModelRealmModelRequired extends RealmObject {\n\n    @Required private RealmDictionary<RealmDictionaryModel> myRequiredRealmAnyRealmDictionary;\n\n    public RealmDictionary<RealmDictionaryModel> getMyRequiredRealmAnyRealmDictionary() {\n        return myRequiredRealmAnyRealmDictionary;\n    }\n\n    public void setMyRequiredRealmAnyRealmDictionary(RealmDictionary<RealmDictionaryModel> myRequiredRealmAnyRealmDictionary) {\n        this.myRequiredRealmAnyRealmDictionary = myRequiredRealmAnyRealmDictionary;\n    }\n}\n"
  },
  {
    "path": "realm/realm-annotations-processor/src/test/resources/some/test/RealmDictionaryModelWrongType.java",
    "content": "/*\n * Copyright 2020 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\npackage some.test;\n\nimport io.realm.RealmDictionary;\nimport io.realm.RealmObject;\n\npublic class RealmDictionaryModelWrongType extends RealmObject {\n\n    private RealmDictionary<Exception> myDictionary;\n\n    public RealmDictionary<Exception> getMyDictionary() {\n        return myDictionary;\n    }\n\n    public void setMyDictionary(RealmDictionary<Exception> dictionary) {\n        this.myDictionary = dictionary;\n    }\n}\n"
  },
  {
    "path": "realm/realm-annotations-processor/src/test/resources/some/test/RealmMapModel.java",
    "content": "/*\n * Copyright 2020 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\npackage some.test;\n\nimport io.realm.RealmAny;\nimport io.realm.RealmMap;\nimport io.realm.RealmObject;\n\n/**\n * At this moment, RealmMaps aren't supported directly until other keys than String are supported.\n */\npublic class RealmMapModel extends RealmObject {\n\n    private RealmMap<String, RealmAny> myMap;      // this currently fails\n\n    public RealmMap<String, RealmAny> getMyMap() {\n        return myMap;\n    }\n\n    public void setMyMap(RealmMap<String, RealmAny> map) {\n        this.myMap = map;\n    }\n}\n"
  },
  {
    "path": "realm/realm-annotations-processor/src/test/resources/some/test/RealmSetMissingGenerics.java",
    "content": "/*\n * Copyright 2020 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\npackage some.test;\n\nimport io.realm.RealmObject;\nimport io.realm.RealmSet;\n\n/**\n * Sets must specify a generic type. With this class we check that the annotation processor\n * detects this class has a RealmSet field missing the required type and therefore should\n * fail in compile time.\n */\npublic class RealmSetMissingGenerics extends RealmObject {\n\n    private RealmSet set; // this is an error!\n}\n"
  },
  {
    "path": "realm/realm-annotations-processor/src/test/resources/some/test/RealmSetModel.java",
    "content": "/*\n * Copyright 2020 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\npackage some.test;\n\nimport org.bson.types.Decimal128;\nimport org.bson.types.ObjectId;\n\nimport java.util.Date;\nimport java.util.UUID;\n\nimport io.realm.RealmSet;\nimport io.realm.RealmObject;\n\npublic class RealmSetModel extends RealmObject {\n\n    private RealmSet<String> stringSet;\n    private RealmSet<Integer> integerSet;\n    private RealmSet<Long> longSet;\n    private RealmSet<Short> shortSet;\n    private RealmSet<Byte> byteSet;\n    private RealmSet<byte[]> binarySet;\n    private RealmSet<ObjectId> objectIdSet;\n    private RealmSet<UUID> uuidSet;\n    private RealmSet<Float> floatSet;\n    private RealmSet<Double> doubleSet;\n    private RealmSet<Boolean> booleanSet;\n    private RealmSet<Date> dateSet;\n    private RealmSet<Decimal128> decimal128Set;\n    private RealmSet<RealmSetModel> objectSet;\n\n    public RealmSet<String> getStringSet() {\n        return stringSet;\n    }\n\n    public void setStringSet(RealmSet<String> stringSet) {\n        this.stringSet = stringSet;\n    }\n\n    public RealmSet<Integer> getIntegerSet() {\n        return integerSet;\n    }\n\n    public void setIntegerSet(RealmSet<Integer> integerSet) {\n        this.integerSet = integerSet;\n    }\n\n    public RealmSet<Long> getLongSet() {\n        return longSet;\n    }\n\n    public void setLongSet(RealmSet<Long> longSet) {\n        this.longSet = longSet;\n    }\n\n    public RealmSet<Short> getShortSet() {\n        return shortSet;\n    }\n\n    public void setShortSet(RealmSet<Short> shortSet) {\n        this.shortSet = shortSet;\n    }\n\n    public RealmSet<Byte> getByteSet() {\n        return byteSet;\n    }\n\n    public void setByteSet(RealmSet<Byte> byteSet) {\n        this.byteSet = byteSet;\n    }\n\n    public RealmSet<byte[]> getBinarySet() {\n        return binarySet;\n    }\n\n    public void setBinarySet(RealmSet<byte[]> binarySet) {\n        this.binarySet = binarySet;\n    }\n\n    public RealmSet<ObjectId> getObjectIdSet() {\n        return objectIdSet;\n    }\n\n    public void setObjectIdSet(RealmSet<ObjectId> objectIdSet) {\n        this.objectIdSet = objectIdSet;\n    }\n\n    public RealmSet<UUID> getUuidSet() {\n        return uuidSet;\n    }\n\n    public void setUuidSet(RealmSet<UUID> uuidSet) {\n        this.uuidSet = uuidSet;\n    }\n\n    public RealmSet<Float> getFloatSet() {\n        return floatSet;\n    }\n\n    public void setFloatSet(RealmSet<Float> floatSet) {\n        this.floatSet = floatSet;\n    }\n\n    public RealmSet<Double> getDoubleSet() {\n        return doubleSet;\n    }\n\n    public void setDoubleSet(RealmSet<Double> doubleSet) {\n        this.doubleSet = doubleSet;\n    }\n\n    public RealmSet<Boolean> getBooleanSet() {\n        return booleanSet;\n    }\n\n    public void setBooleanSet(RealmSet<Boolean> booleanSet) {\n        this.booleanSet = booleanSet;\n    }\n\n    public RealmSet<Date> getDateSet() {\n        return dateSet;\n    }\n\n    public void setDateSet(RealmSet<Date> dateSet) {\n        this.dateSet = dateSet;\n    }\n\n    public RealmSet<Decimal128> getDecimal128Set() {\n        return decimal128Set;\n    }\n\n    public void setDecimal128Set(RealmSet<Decimal128> decimal128Set) {\n        this.decimal128Set = decimal128Set;\n    }\n\n    public RealmSet<RealmSetModel> getObjectSet() {\n        return objectSet;\n    }\n\n    public void setObjectSet(RealmSet<RealmSetModel> objectSet) {\n        this.objectSet = objectSet;\n    }\n}\n"
  },
  {
    "path": "realm/realm-annotations-processor/src/test/resources/some/test/RealmSetModelWrongType.java",
    "content": "/*\n * Copyright 2020 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\npackage some.test;\n\nimport io.realm.RealmObject;\nimport io.realm.RealmSet;\n\npublic class RealmSetModelWrongType extends RealmObject {\n\n    private RealmSet<Exception> set;        // Usupported type -> fails\n\n    public RealmSet<Exception> getSet() {\n        return set;\n    }\n\n    public void setSet(RealmSet<Exception> set) {\n        this.set = set;\n    }\n}\n"
  },
  {
    "path": "realm/realm-annotations-processor/src/test/resources/some/test/Simple.java",
    "content": "/*\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\npackage some.test;\n\nimport io.realm.RealmObject;\n\npublic class Simple extends RealmObject {\n    private String name;\n    private int age;\n\n    public String getName() {\n        return realmGet$name();\n    }\n\n    public void setName(String name) {\n        realmSet$name(name);\n    }\n\n    public String realmGet$name() {\n        return name;\n    }\n\n    public void realmSet$name(String name) {\n        this.name = name;\n    }\n\n    public int getAge() {\n        return realmGet$age();\n    }\n\n    public void setAge(int age) {\n        realmSet$age(age);\n    }\n\n    public int realmGet$age() {\n        return age;\n    }\n\n    public void realmSet$age(int age) {\n        this.age = age;\n    }\n\n    @Override\n    public String toString() {\n        return \"Simple{\" +\n                \"name='\" + name + '\\'' +\n                \", age=\" + age +\n                '}';\n    }\n\n    @Override\n    public boolean equals(Object o) {\n        if (this == o) return true;\n        if (o == null || getClass() != o.getClass()) return false;\n\n        Simple simple = (Simple) o;\n\n        if (age != simple.age) return false;\n        if (name != null ? !name.equals(simple.name) : simple.name != null) return false;\n\n        return true;\n    }\n\n    @Override\n    public int hashCode() {\n        int result = name != null ? name.hashCode() : 0;\n        result = 31 * result + age;\n        return result;\n    }\n}\n"
  },
  {
    "path": "realm/realm-annotations-processor/src/test/resources/some/test/SimpleRealmModel.java",
    "content": "/*\n * Copyright 2016 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\npackage some.test;\n\nimport io.realm.RealmList;\nimport io.realm.RealmModel;\nimport io.realm.annotations.RealmClass;\n\n// Object implements RealmModel and annotated by @RealmClase can be used as a field and element of RealmList\n@RealmClass\npublic class SimpleRealmModel implements RealmModel {\n    String name;\n    RealmList<SimpleRealmModel> realmList;\n    SimpleRealmModel simpleRealmModel;\n}"
  },
  {
    "path": "realm/realm-annotations-processor/src/test/resources/some/test/Transient.java",
    "content": "/*\n * Copyright 2016 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\npackage some.test;\n\nimport io.realm.RealmObject;\n\npublic class Transient extends RealmObject {\n    private transient String name;\n    private int age;\n\n    public String getName() {\n        return name;\n    }\n\n    public void setName(String name) {\n        this.name = name;\n    }\n\n    public int getAge() {\n        return realmGet$age();\n    }\n\n    public void setAge(int age) {\n        realmSet$age(age);\n    }\n\n    public int realmGet$age() {\n        return age;\n    }\n\n    public void realmSet$age(int age) {\n        this.age = age;\n    }\n}\n"
  },
  {
    "path": "realm/realm-annotations-processor/src/test/resources/some/test/UseExtendRealmList.java",
    "content": "/*\n * Copyright 2016 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\npackage some.test;\n\nimport io.realm.RealmModel;\nimport io.realm.RealmObject;\nimport io.realm.RealmList;\n\npublic class UseExtendRealmList extends RealmObject {\n    private ExtendRealmList<UseExtendRealmList> extendRealmList;\n\n    public ExtendRealmList<UseExtendRealmList> extendRealmList() {\n        return extendRealmList;\n    }\n\n    public void realmSet$extendRealmList(ExtendRealmList<UseExtendRealmList> extendRealmList) {\n        this.extendRealmList = extendRealmList;\n    }\n}\n"
  },
  {
    "path": "realm/realm-annotations-processor/src/test/resources/some/test/ValidModelRealmModel_ExtendingRealmObject.java",
    "content": "/*\n * Copyright 2016 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\npackage some.test;\n\nimport io.realm.RealmModel;\nimport io.realm.RealmObject;\nimport io.realm.annotations.RealmClass;\n\n// This is valid, although weird, you should either use composition or inheritance\n@RealmClass\npublic class ValidModelRealmModel_ExtendingRealmObject extends RealmObject implements RealmModel {\n    public String id;\n}\n"
  },
  {
    "path": "realm/realm-annotations-processor/src/test/resources/some/test/ValueList.java",
    "content": "/*\n * Copyright 2017 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\npackage some.test;\n\nimport io.realm.RealmList;\nimport io.realm.RealmObject;\nimport io.realm.RealmResults;\nimport io.realm.annotations.LinkingObjects;\n\npublic class ValueList extends RealmObject {\n    public RealmList<String> stringList;\n    public RealmList<byte[]> binaryList;\n    public RealmList<Boolean> booleanList;\n    public RealmList<Long> longList;\n    public RealmList<Integer> integerList;\n    public RealmList<Short> shortList;\n    public RealmList<Byte> byteList;\n    public RealmList<Double> doubleList;\n    public RealmList<Float> floatList;\n    public RealmList<Date> integerList;\n}\n"
  },
  {
    "path": "realm/realm-annotations-processor/src/test/resources/some/test/Volatile.java",
    "content": "/*\n * Copyright 2016 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\npackage some.test;\n\nimport io.realm.RealmObject;\n\npublic class Volatile extends RealmObject {\n    private volatile String name;\n    private int age;\n\n    public String getName() {\n        return realmGet$name();\n    }\n\n    public void setName(String name) {\n        realmSet$name(name);\n    }\n\n    public String realmGet$name() {\n        return name;\n    }\n\n    public void realmSet$name(String name) {\n        this.name = name;\n    }\n\n    public int getAge() {\n        return realmGet$age();\n    }\n\n    public void setAge(int age) {\n        realmSet$age(age);\n    }\n\n    public int realmGet$age() {\n        return age;\n    }\n\n    public void realmSet$age(int age) {\n        this.age = age;\n    }\n\n    @Override\n    public String toString() {\n        return \"Simple{\" +\n                \"name='\" + name + '\\'' +\n                \", age=\" + age +\n                '}';\n    }\n\n    @Override\n    public boolean equals(Object o) {\n        if (this == o) return true;\n        if (o == null || getClass() != o.getClass()) return false;\n\n        Simple simple = (Simple) o;\n\n        if (age != simple.age) return false;\n        if (name != null ? !name.equals(simple.name) : simple.name != null) return false;\n\n        return true;\n    }\n\n    @Override\n    public int hashCode() {\n        int result = name != null ? name.hashCode() : 0;\n        result = 31 * result + age;\n        return result;\n    }\n}\n"
  },
  {
    "path": "realm/realm-annotations-processor/src/test/resources/some/test/conflict/BacklinkSelfReference.java",
    "content": "package some.test.conflict;\n\nimport io.realm.RealmList;\nimport io.realm.RealmObject;\nimport io.realm.annotations.LinkingObjects;\nimport io.realm.annotations.RealmClass;\n\n// Test Backlink resolution when there is simple class name conflicts, but not internal name conflicts.\n@RealmClass(name = \"!BacklinkSelfReference\")\npublic class BacklinkSelfReference extends RealmObject {\n    public String name;\n}\n"
  },
  {
    "path": "realm/realm-annotations-processor/src/test/resources/some/test/ÁrvíztűrőTükörfúrógép.java",
    "content": "/*\n * Copyright 2017 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\npackage some.test;\n\nimport io.realm.RealmObject;\n\n\n/**\n * A model class to test non latin class name.\n */\npublic class ÁrvíztűrőTükörfúrógép extends RealmObject {\n    public String name;\n    public long 델타;\n    public long Δέλτα;\n    public float 貸借対照表;\n}\n"
  },
  {
    "path": "realm/realm-library/build.gradle",
    "content": "import java.security.MessageDigest\n\napply plugin: 'com.android.library'\napply plugin: 'kotlin-android'\napply plugin: 'kotlin-kapt'\napply plugin: 'com.github.spotbugs-base'\napply plugin: 'pmd'\napply plugin: 'checkstyle'\napply plugin: 'com.github.kt3k.coveralls'\napply plugin: 'de.undercouch.download'\n// FIXME: https://github.com/realm/realm-java/issues/7551\n//apply plugin: 'net.ltgt.errorprone'\n\ndef properties = new Properties()\nproperties.load(new FileInputStream(\"${projectDir}/../../dependencies.list\"))\n\next.ccachePath = project.findProperty('ccachePath') ?: System.getenv('NDK_CCACHE')\next.lcachePath = project.findProperty('lcachePath') ?: System.getenv('NDK_LCACHE')\n\nkapt {\n    correctErrorTypes = true\n}\n\nandroid {\n    compileSdkVersion rootProject.ext.compileSdkVersion\n    buildToolsVersion rootProject.ext.buildToolsVersion\n\n    defaultConfig {\n        minSdkVersion rootProject.ext.minSdkVersion\n        targetSdkVersion rootProject.ext.compileSdkVersion\n        versionName version\n        project.archivesBaseName = \"realm-android-library\"\n        testInstrumentationRunner \"androidx.test.runner.AndroidJUnitRunner\"\n        multiDexEnabled true\n        externalNativeBuild {\n            cmake {\n                if (project.ccachePath) arguments \"-DNDK_CCACHE=$project.ccachePath\"\n                if (project.lcachePath) arguments \"-DNDK_LCACHE=$project.lcachePath\"\n                if (project.hasProperty('buildTargetABIs') && !project.getProperty('buildTargetABIs').trim().isEmpty()) {\n                    abiFilters(*project.getProperty('buildTargetABIs').trim().split('\\\\s*,\\\\s*'))\n                } else {\n                    // \"armeabi\" and \"mips\" are no longer supported by the NDK\n                    abiFilters 'x86', 'x86_64', 'armeabi-v7a', 'arm64-v8a'\n                }\n\n                arguments \"-DREALM_JAVA_BUILD_CORE_FROM_SOURCE=${project.hasProperty('buildCore') && project.getProperty('buildCore').toBoolean()}\"\n                arguments \"-DCMAKE_INTERPROCEDURAL_OPTIMIZATION=${!project.hasProperty('enableLTO') || project.getProperty('enableLTO').toBoolean()}\"\n                targets \"realm-jni\"\n            }\n        }\n        // For running test as 32-bit only\n        // ndk {\n        //    abiFilters 'armeabi-v7a', 'x86'\n        // }\n\n        buildConfigField \"String\", \"VERSION_NAME\", \"\\\"${version}\\\"\"\n\n        buildTypes {\n            debug {\n                javaCompileOptions.with {\n                    annotationProcessorOptions.arguments += ['realm.suppressWarnings': 'false']\n                }\n            }\n        }\n    }\n\n    ndkVersion = project.findProperty('ndkVersion')\n\n    externalNativeBuild {\n        cmake {\n            version = properties.getProperty('CMAKE')\n            path 'src/main/cpp/CMakeLists.txt'\n        }\n    }\n\n    buildTypes {\n        debug {\n            // FIXME: If enabled, crashes with https://issuetracker.google.com/issues/37116868\n            testCoverageEnabled = false\n            // minifyEnabled = true;\n            // proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'\n        }\n\n        release {\n            externalNativeBuild {\n                cmake {\n                }\n            }\n            // minifyEnabled = true;\n        }\n    }\n\n    sourceSets {\n        testObjectServer {\n            java.srcDirs += ['src/testObjectServer/kotlin']\n        }\n        androidTest {\n            java.srcDirs += ['src/androidTest/kotlin', 'src/testUtils/java', 'src/testUtils/kotlin']\n        }\n        androidTestObjectServer {\n            java.srcDirs += [ 'src/syncIntegrationTest/kotlin',\n                              'src/androidTestObjectServer/kotlin',\n                              'src/syncTestUtils/java',\n                              'src/syncTestUtils/kotlin' ]\n            assets.srcDirs += ['src/syncIntegrationTest/assets/']\n        }\n    }\n\n    compileOptions {\n        sourceCompatibility JavaVersion.VERSION_1_8\n        targetCompatibility JavaVersion.VERSION_1_8\n    }\n\n    kotlinOptions {\n        jvmTarget = JavaVersion.VERSION_1_8\n    }\n\n    packagingOptions {\n        exclude 'META-INF/NOTICE.txt'\n        exclude 'META-INF/LICENSE.txt'\n        // We did strip with cmake for release build.\n        // Please, Gradle, you are not that smart! Pleas DO NOT strip debug symbols for debug build!\n        doNotStrip \"*/*/*.so\"\n\n        // Use compressed shared libraries to support 16 KB ELF alignment\n        jniLibs {\n            useLegacyPackaging = true\n        }\n    }\n\n    lintOptions {\n        abortOnError false\n    }\n\n    flavorDimensions 'api'\n\n    productFlavors {\n        base {\n            dimension 'api'\n            externalNativeBuild {\n                cmake {\n                    arguments \"-DREALM_FLAVOR=base\"\n                }\n            }\n            consumerProguardFiles 'proguard-rules-consumer-common.pro', 'proguard-rules-consumer-base.pro'\n            proguardFiles 'proguard-rules-build-common.pro'\n        }\n        objectServer {\n            dimension 'api'\n            externalNativeBuild {\n                cmake {\n                    arguments \"-DREALM_FLAVOR=objectServer\"\n                }\n            }\n            consumerProguardFiles 'proguard-rules-consumer-common.pro', 'proguard-rules-consumer-objectServer.pro'\n            proguardFiles 'proguard-rules-build-common.pro', 'proguard-rules-build-objectServer.pro'\n        }\n    }\n}\n\nio.realm.transformer.RealmTransformerKt.registerRealmTransformerTask(project)\n// TODO RealmBuildTransformer only supports stripping symbols from Jars so must be applied\n//  after the accessor transformer (that combines all inputs into one common Jar)\nio.realm.buildtransformer.RealmBuildTransformer.@Companion.register(\n        project,\n        \"base\",\n        \"io.realm.internal.annotations.ObjectServer\",\n)\n\nproject.afterEvaluate {\n    tasks.withType(JavaCompile) {\n        options.compilerArgs << '-Werror'\n    }\n\n    android.productFlavors.all { flavor ->\n        tasks.all { task ->\n            if (task.name == \"publish${flavor.name.capitalize()}PublicationPublicationToMavenLocal\") {\n                task.dependsOn \"assemble${flavor.name.capitalize()}\"\n            }\n        }\n    }\n}\n\n// enable @ParametersAreNonnullByDefault annotation. See https://blog.jetbrains.com/kotlin/2017/09/kotlin-1-1-50-is-out/\ntasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).all {\n    kotlinOptions {\n        freeCompilerArgs = [\"-Xjsr305=strict\"]\n    }\n}\n\ncoveralls.jacocoReportPath = \"${buildDir}/reports/coverage/debug/report.xml\"\n\nrepositories {\n    maven { url \"https://jitpack.io\" }\n    mavenCentral()\n}\n\ndependencies {\n    compileOnly \"io.reactivex.rxjava2:rxjava:${properties.getProperty('RXJAVA_DEPENDENCY')}\"\n    compileOnly 'com.github.spotbugs:spotbugs-annotations:4.1.2'\n    compileOnly \"org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version\"\n    compileOnly \"org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutines_android_version\"\n    compileOnly \"org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutines_android_version\"\n    androidTestImplementation \"org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutines_android_version\"\n    androidTestImplementation \"org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutines_android_version\"\n\n    testImplementation 'junit:junit:4.12'\n    testImplementation \"org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version\"\n    testImplementation \"org.jetbrains.kotlin:kotlin-test:$kotlin_version\"\n\n    api \"io.realm:realm-annotations:${version}\"\n    implementation 'com.google.code.findbugs:jsr305:3.0.2'\n    implementation 'com.getkeepsafe.relinker:relinker:1.4.3'\n    api \"org.mongodb:bson:${properties.getProperty('BSON_DEPENDENCY')}\"\n    implementation(\"io.reactivex.rxjava2:rxandroid:${properties.getProperty('RXANDROID_DEPENDENCY')}\") {\n        exclude group: 'io.reactivex.rxjava2', module: 'rxjava'\n    }\n\n    androidTestImplementation \"androidx.multidex:multidex:2.0.1\"\n\n    kapt project(':realm-annotations-processor') // See https://github.com/realm/realm-java/issues/5799\n    objectServerImplementation 'com.squareup.okhttp3:okhttp:3.12.0' // Going above this requires minSDK 21\n    kaptAndroidTest project(':realm-annotations-processor')\n    androidTestImplementation \"org.jetbrains.kotlin:kotlin-test:$kotlin_version\"\n    androidTestImplementation \"io.reactivex.rxjava2:rxjava:${properties.getProperty('RXJAVA_DEPENDENCY')}\"\n    androidTestImplementation \"io.reactivex.rxjava2:rxandroid:${properties.getProperty('RXANDROID_DEPENDENCY')}\"\n    androidTestImplementation 'androidx.test.ext:junit:1.1.1'\n    androidTestImplementation 'androidx.test:rules:1.2.0'\n    androidTestImplementation 'com.google.dexmaker:dexmaker:1.2'\n    androidTestImplementation 'com.google.dexmaker:dexmaker-mockito:1.2'\n    androidTestImplementation 'org.hamcrest:hamcrest-library:1.3'\n    androidTestImplementation \"org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version\"\n    androidTestImplementation \"org.jetbrains.kotlin:kotlin-reflect:$kotlin_version\"\n    androidTestImplementation \"org.skyscreamer:jsonassert:1.5.0\"\n    androidTestImplementation project(':kotlin-extensions')\n\n    // specify error prone version to prevent sudden failure\n//    errorprone 'com.google.errorprone:error_prone_core:2.8.1'\n}\n\ntask sourcesJar(type: Jar) {\n    from android.sourceSets.objectServer.java.srcDirs\n    from android.sourceSets.main.java.srcDirs\n    classifier = 'sources'\n}\n\ntask javadoc(type: Javadoc) {\n    failOnError false\n    dependsOn(\"compileObjectServerReleaseJavaWithJavac\")\n    source android.sourceSets.objectServer.java.srcDirs\n    source android.sourceSets.main.java.srcDirs\n    source \"../../realm-annotations/src/main/java\"\n    classpath += project.files(android.getBootClasspath().join(File.pathSeparator))\n\n    options {\n        title = \"Realm ${project.version}\"\n        memberLevel = JavadocMemberLevel.PUBLIC\n        docEncoding = 'UTF-8'\n        encoding = 'UTF-8'\n        charSet = 'UTF-8'\n        locale = 'en_US'\n        overview = 'src/overview.html'\n\n        links \"https://docs.oracle.com/javase/7/docs/api/\"\n        links \"http://reactivex.io/RxJava/javadoc/\"\n        links \"https://developer.android.com/reference\"\n        links \"https://www.javadoc.io/doc/org.mongodb/bson/${properties.getProperty('BSON_DEPENDENCY')}/\"\n    }\n    exclude '**/internal/**'\n    exclude '**/BuildConfig.java'\n    exclude '**/R.java'\n    exclude '**/*.kt'\n    doLast {\n        copy {\n            from \"src/realm-java-overview.png\"\n            into \"$buildDir/docs/javadoc\"\n        }\n    }\n}\n\ntask javadocJar(type: Jar, dependsOn: javadoc) {\n    classifier = 'javadoc'\n    from javadoc.destinationDir\n}\n\n// See https://spotbugs-gradle-plugin.netlify.app/com/github/spotbugs/snom/spotbugsextension\nspotbugs {\n    toolVersion = '4.1.1'\n    ignoreFailures = false\n    effort = \"default\"\n    reportLevel = \"medium\"\n    excludeFilter = file(\"${projectDir}/../config/findbugs/findbugs-filter.xml\")\n}\n\n// See https://spotbugs.readthedocs.io/en/latest/migration.html#findbugs-gradle-plugin\ntask spotbugsMain(type: com.github.spotbugs.snom.SpotBugsTask) {\n    dependsOn 'assemble'\n    group = 'verification'\n    classes = fileTree(\"build/intermediates/javac/\")\n\n    reports {\n        xml.enabled = false\n        html.enabled = true\n    }\n}\n\ntask pmd(type: Pmd) {\n    group = 'verification'\n\n    source = fileTree('src/main/java') + fileTree('src/objectServer/java')\n    ruleSetFiles = files(\"${projectDir}/../config/pmd/ruleset.xml\")\n\n    ruleSets = []\n\n    reports {\n        xml.enabled = false\n        html.enabled = true\n    }\n}\n\n// Configure Checkstyle\n// Android sourceSets are not sourceSets, so we can't confgure this with the DSL.\ntask checkstyle(type: Checkstyle) {\n    group = 'verification'\n    configFile file(\"${projectDir}/../config/checkstyle/checkstyle.xml\")\n\n    source fileTree('src/main/java') + fileTree('src/objectServer/java')\n    include '**/*.java'\n    exclude '**/gen/**'\n\n    // empty classpath\n    classpath = files()\n\n    reports {\n        xml.enabled = false\n        html.enabled = true\n    }\n}\n\napply from: \"${rootDir}/../mavencentral-publications.gradle\"\n\npublishing {\n    publications {\n        basePublication(MavenPublication) {\n            groupId 'io.realm'\n            artifactId 'realm-android-library'\n            version project.version\n            artifact file(\"${rootDir}/realm-library/build/outputs/aar/realm-android-library-base-release.aar\")\n            artifact sourcesJar\n            artifact javadocJar\n            populatePom(\n                    it,\n                    'realm-android-library',\n                    'Realm is a mobile database: Build better apps, faster.',\n                    createPomDependencies([\"baseImplementation\", \"implementation\", \"baseApi\", \"api\"])\n            )\n        }\n\n        objectServerPublication(MavenPublication) {\n            groupId 'io.realm'\n            artifactId 'realm-android-library-object-server'\n            version project.version\n            artifact file(\"${rootDir}/realm-library/build/outputs/aar/realm-android-library-objectServer-release.aar\")\n            artifact sourcesJar\n            artifact javadocJar\n            populatePom(\n                    it,\n                    'realm-android-library-object-server',\n                    'Realm is a mobile database: Build better apps, faster.',\n                    createPomDependencies([\"objectServerImplementation\", \"implementation\", \"objectServerApi\", \"api\"])\n            )\n        }\n    }\n}\n\nartifacts {\n    archives javadocJar\n    archives sourcesJar\n}\n\npublishToMavenLocal.dependsOn assemble\n\nif (project.hasProperty('dontCleanJniFiles')) {\n    project.afterEvaluate {\n        tasks.all { task ->\n            if (task.name.startsWith('externalNativeBuildClean')) {\n                task.enabled = false\n            }\n        }\n    }\n} else {\n    task cleanExternalBuildFiles(type: Delete) {\n        delete project.file('.externalNativeBuild')\n        delete project.file('.cxx')\n        // Clean .so files that were created by old build script (realm/realm-jni/build.gradle).\n        delete project.file('src/main/jniLibs')\n    }\n    clean.dependsOn cleanExternalBuildFiles\n}\n\nproject.afterEvaluate {\n    android.libraryVariants.all { variant ->\n        if (project.hasProperty('buildTargetABIs') && project.getProperty('buildTargetABIs').trim().isEmpty()) {\n            variant.externalNativeBuildProviders[0].configure {\n                enabled = false\n            }\n        }\n\n        // all Java files must be compiled before native build\n        // See https://github.com/android/ndk-samples/issues/284\n        variant.externalNativeBuildProviders[0].configure { externalNativeBuildTask ->\n            externalNativeBuildTask.taskDependencies.getDependencies(externalNativeBuildTask)\n                .findAll { it.name.startsWith(\"buildCMake\") }\n                .forEach { externalNativeBuildDependency ->\n                    externalNativeBuildDependency.dependsOn \"compile${variant.name.capitalize()}JavaWithJavac\"\n                }\n        }\n        // as of android gradle plugin 3.0.0-alpha5, generateJsonModel* triggers native build. Java files must be compiled before them.\n        android.buildTypes.all { buildType ->\n            tasks[\"generateJsonModel${variant.name.capitalize()}\"].dependsOn \"compile${variant.flavorName.capitalize()}${buildType.name.capitalize()}JavaWithJavac\"\n        }\n\n        // Java compiler to generate JNI headers.\n        def generatedJNIHeadersPath = \"$buildDir/intermediates/javac/${variant.name}/jni_include\"\n        tasks[\"compile${variant.name.capitalize()}JavaWithJavac\"].with {\n            options.compilerArgs += [\"-h\", file(generatedJNIHeadersPath)]\n            // Add generated headers into the build cache.\n            outputs.dir(generatedJNIHeadersPath)\n        }\n\n        // Set javaDoc task's classpath with the project compiled classes and its dependencies\n        if(variant.name == \"objectServerRelease\") {\n            def javaCompile = variant.javaCompileProvider.get()\n            javadoc.classpath += files(\n                    javaCompile.destinationDir, // All intermediate Realm compiled classes\n                    javaCompile.classpath.files // Dependencies\n            )\n        }\n    }\n}\n\nstatic def getValueFromPropertiesFile(File propFile, String key) {\n    if (!propFile.isFile() || !propFile.canRead()) {\n        return null\n    }\n    def prop = new Properties()\n    def reader = propFile.newReader()\n    try {\n        prop.load(reader)\n    } finally {\n        reader.close()\n    }\n    return prop.get(key)\n}\n"
  },
  {
    "path": "realm/realm-library/gradle.properties",
    "content": ""
  },
  {
    "path": "realm/realm-library/proguard-rules-build-common.pro",
    "content": "# Common proguard configuration for building the Base and ObjectServer variants\n# Note: This is for _building the Realm library, not for consuming it.\n"
  },
  {
    "path": "realm/realm-library/proguard-rules-build-objectServer.pro",
    "content": "# Proguard configuration specific for building the ObjectServer variant.\n# Note: This is for _building the Realm library, not for consuming it.\n"
  },
  {
    "path": "realm/realm-library/proguard-rules-consumer-base.pro",
    "content": "# It's OK not to exist SyncObjectServerFacade in base library.\n-dontnote io.realm.internal.SyncObjectServerFacade\n\n"
  },
  {
    "path": "realm/realm-library/proguard-rules-consumer-common.pro",
    "content": "-keep class io.realm.annotations.RealmModule\n-keep @io.realm.annotations.RealmModule class *\n-keep @interface io.realm.annotations.RealmModule { *; }\n-keep class io.realm.annotations.RealmModule { *; }\n\n-keep class io.realm.internal.Keep\n-keep @io.realm.internal.Keep class * { *; }\n\n-keep class io.realm.internal.KeepMember\n-keep @io.realm.internal.KeepMember class * { @io.realm.internal.KeepMember *; }\n\n-dontwarn javax.**\n-dontwarn io.realm.**\n-dontwarn io.reactivex.android.**\n\n-keep class io.realm.RealmCollection\n-keep class io.realm.OrderedRealmCollection\n-keepclasseswithmembernames class io.realm.** {\n    native <methods>;\n}\n\n-dontnote rx.Observable\n\n# Referenced from JNI\n-keep class org.bson.types.Decimal128 {\n    public static org.bson.types.Decimal128 fromIEEE754BIDEncoding(...);\n}\n-keep class org.bson.types.ObjectId {\n    <init>(...);\n}\n"
  },
  {
    "path": "realm/realm-library/proguard-rules-consumer-objectServer.pro",
    "content": "-dontnote android.security.KeyStore\n-dontwarn okio.Okio\n-dontwarn okio.DeflaterSink\n\n-dontnote com.android.org.conscrypt.SSLParametersImpl\n-dontnote org.apache.harmony.xnet.provider.jsse.SSLParametersImpl\n-dontnote sun.security.ssl.SSLContextImpl\n\n# See https://github.com/square/okhttp/issues/3922\n-dontwarn okhttp3.internal.platform.*\n\n# Referenced from JNI\n-keep class io.realm.internal.objectstore.OsJavaNetworkTransport$Response {\n    int getHttpResponseCode();\n    int getCustomResponseCode();\n    java.lang.String[] getJNIFriendlyHeaders();\n    java.lang.String getBody();\n}\n\n-keep class io.realm.internal.objectstore.OsJavaNetworkTransport$Request {\n    <init>(...);\n}\n\n-keep class io.realm.internal.OsSharedRealm$SchemaChangedCallback {\n    void onSchemaChanged();\n}\n\n-keep class io.realm.internal.objectstore.OsApp {\n    io.realm.internal.objectstore.OsJavaNetworkTransport getNetworkTransport();\n}\n\n-keep class io.realm.internal.objectstore.OsSubscriptionSet$StateChangeCallback {\n    *;\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/AndroidManifest.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<manifest package=\"io.realm.test\"\n          xmlns:android=\"http://schemas.android.com/apk/res/android\"\n          xmlns:tools=\"http://schemas.android.com/tools\">\n\n    <uses-permission android:name=\"android.permission.INTERNET\"/>\n    <uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>\n    <uses-permission android:name=\"android.permission.WRITE_EXTERNAL_STORAGE\"/>\n    <uses-permission android:name=\"android.permission.READ_EXTERNAL_STORAGE\"/>\n    <uses-permission android:name=\"android.permission.SET_DEBUG_APP\"/>\n\n    <uses-sdk\n        android:minSdkVersion=\"16\"\n        android:targetSdkVersion=\"29\"/>\n\n    <application\n        android:debuggable=\"true\"\n        android:largeHeap=\"true\"\n        android:networkSecurityConfig=\"@xml/network_security_config\">\n        <uses-library android:name=\"android.test.runner\"/>\n\n        <service\n            android:name=\"io.realm.services.RemoteProcessService\"\n            android:enabled=\"true\"\n            android:exported=\"true\"\n            android:process=\":remote\">\n        </service>\n\n         <!--\n          FIXME: Manifest merger doesn't seem to work correctly with test flavours.\n          Figure out why. For now place services here\n          -->\n        <service\n            android:name=\"io.realm.objectserver.ProcessCommitTests$SimpleCommitRemoteService\"\n            android:enabled=\"true\"\n            android:exported=\"true\"\n            android:process=\":remote\">\n        </service>\n        <service\n            android:name=\"io.realm.objectserver.ProcessCommitTests$ALotCommitsRemoteService\"\n            android:enabled=\"true\"\n            android:exported=\"true\"\n            android:process=\":remote\">\n        </service>\n    </application>\n\n</manifest>\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/assets/all_simple_types.json",
    "content": "{\n\t\"columnString\" : \"String\",\n\t\"columnLong\" : 1,\n\t\"columnFloat\" : 1.23,\n\t\"columnDouble\" : 1.23,\n\t\"columnBoolean\" : true,\n\t\"columnBinary\" : \"AQID\"\n}"
  },
  {
    "path": "realm/realm-library/src/androidTest/assets/all_types_invalid.json",
    "content": "{\n  \"columnString\" : null,"
  },
  {
    "path": "realm/realm-library/src/androidTest/assets/all_types_null.json",
    "content": "{\n\t\"columnString\" : null,\n\t\"columnLong\" : null,\n\t\"columnFloat\" : null,\n\t\"columnDouble\" : null,\n\t\"columnBoolean\" : null,\n\t\"columnBinary\" : null,\n\t\"columnDate\" : null,\n\t\"columnRealmObject\" : null,\n\t\"columnRealmList\" : null\n}"
  },
  {
    "path": "realm/realm-library/src/androidTest/assets/all_types_primary_key_field_only.json",
    "content": "{\n\t\"columnLong\" : 1\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/assets/all_types_primary_key_null.json",
    "content": "{\n\t\"columnString\" : null,\n\t\"columnLong\" : 1,\n\t\"columnFloat\" : null,\n\t\"columnDouble\" : null,\n\t\"columnBoolean\" : null,\n\t\"columnBinary\" : null,\n\t\"columnDate\" : null,\n\t\"columnRealmObject\" : null,\n\t\"columnRealmList\" : null\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/assets/array.json",
    "content": "[\n    { \"name\" : \"Fido-1\" },\n    { \"name\" : \"Fido-2\" },\n    { \"name\" : \"Fido-3\" }\n]"
  },
  {
    "path": "realm/realm-library/src/androidTest/assets/date_as_iso8601_string.json",
    "content": "{\n    \"columnDate\" : \"2007-08-13T215123.789+02:00\"\n}"
  },
  {
    "path": "realm/realm-library/src/androidTest/assets/date_as_long.json",
    "content": "{\n    \"columnDate\" : 1000\n}"
  },
  {
    "path": "realm/realm-library/src/androidTest/assets/date_as_string.json",
    "content": "{\n    \"columnDate\" : \"/Date(1000)/\"\n}"
  },
  {
    "path": "realm/realm-library/src/androidTest/assets/decimal128_as_double.json",
    "content": "{\n    \"columnDecimal128\" : 0.30000001192092896\n}"
  },
  {
    "path": "realm/realm-library/src/androidTest/assets/decimal128_as_int.json",
    "content": "{\n    \"columnDecimal128\" : -42\n}"
  },
  {
    "path": "realm/realm-library/src/androidTest/assets/decimal128_as_long.json",
    "content": "{\n    \"columnDecimal128\" : -32361122672259149\n}"
  },
  {
    "path": "realm/realm-library/src/androidTest/assets/decimal128_as_string.json",
    "content": "{\n    \"columnDecimal128\" : \"32361122672259149\"\n}"
  },
  {
    "path": "realm/realm-library/src/androidTest/assets/empty.json",
    "content": "{ }\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/assets/ios/README.md",
    "content": "This folder contains various Realm databases created on iOS and can be used to test interop with\nRealm-Android. The databases are generated using the below iOS code.\n\n(02/18-2016) Note that we should match the core version (0.96.0) used in Cocoa (0.98.0) for Java (0.87.4).\n\n### HOWTO\n\n1. Checkout realm-cocoa.\n2. `cd examples/ios/objc`\n3. `pod install`\n4. `open RealmExamples.xcworkspace` in XCode\n5. Rename `/Simple/AppDelegate.m` to `/Simple/AppDelegate.mm` and replace the content with the below code.  \n4. Run Simple project.\n5. Copy/paste output Realm files into Java unit tests asset directory.\n\n### DISABLE DEBUGGING:\n\n1. Click on spinner that chooses which Example to run.\n2. At the bottom should be a button called \"Edit Scheme\".\n3. Choose \"Run\" if not selected already.\n4. Remove check in \"Debug executable\".\n5. Save and run.\n\nSee the Log for where the output files are located.\n\n```objective-c  \n#import \"AppDelegate.h\"\n#import <Realm/Realm.h>\n#include <limits>\nusing namespace std;\n\n@interface IOSChild : RLMObject\n@property NSString *name;\n@end\nRLM_ARRAY_TYPE(IOSChild)\n\n@implementation IOSChild\n@end\n\n@interface IOSAllTypes : RLMObject\n@property long id;\n@property bool boolCol;\n@property short shortCol;\n@property int intCol;\n@property long longCol;\n@property int64_t longLongCol;\n@property float floatCol;\n@property double doubleCol;\n@property NSData *byteCol;\n@property NSString *stringCol;\n@property NSDate *dateCol;\n@property IOSChild *child;\n@property RLMArray<IOSChild> *children;\n@end\nRLM_ARRAY_TYPE(AllTypes)\n\n@implementation IOSAllTypes\n+ (NSString *)primaryKey {\n    return @\"id\";\n}\n@end\n\n@implementation AppDelegate\n\n+ (int64_t) realm_from_nsdate:(NSDate *)nsdate {\n    return static_cast<int64_t>([nsdate timeIntervalSince1970]);\n}\n\n+ (NSString *)getRealmFilePath:(NSString *)realmName {\n    NSString *documentsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)objectAtIndex:0];\n    return [documentsDirectory stringByAppendingPathComponent:realmName];\n}\n\n+ (RLMRealm *)appDefaultRealm:(NSString *) realmName {\n    NSString* allTypesRealm = [AppDelegate getRealmFilePath:realmName];\n    [[NSFileManager defaultManager] removeItemAtPath:allTypesRealm error:nil];\n    RLMRealm *realm = [RLMRealm realmWithURL:[NSURL fileURLWithPath:allTypesRealm]];\n    return realm;\n}\n\n- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {\n\n    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];\n    self.window.rootViewController = [[UIViewController alloc] init];\n    [self.window makeKeyAndVisible];\n\n    NSLog(@\"Documents Directory: %@\", [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject]);\n\n    const NSString *version = @\"6.0.0-beta.2\";\n    const unsigned char no_bytes[] = {};\n    const unsigned char bytes[] = {1,2,3};\n\n    RLMRealm *realm = [AppDelegate appDefaultRealm:[NSString stringWithFormat:@\"%@-alltypes.realm\", version]];\n    [realm beginWriteTransaction];\n    for (int i = 0; i < 10; i++) {\n        IOSAllTypes *obj = [[IOSAllTypes alloc] init];\n        obj.id = i + 1;\n        obj.boolCol = TRUE;\n        obj.shortCol = 1 + i;\n        obj.intCol = 10 + i;\n        obj.longCol = 100 + i;\n        obj.longLongCol = 100000000 + i;\n        obj.floatCol = 1.23 + i;\n        obj.doubleCol = 1.234 + i;\n        obj.byteCol = [NSData dataWithBytes:bytes length:sizeof(bytes)];\n        obj.stringCol = [NSString stringWithFormat: @\"%@ %d\", @\"String\", i];\n        obj.dateCol = [NSDate dateWithTimeIntervalSince1970: (1000 + i)];\n\n        obj.child = [[IOSChild alloc] init];\n        obj.child.name = @\"Foo\";\n        for (int j = 0; j < 10; j++) {\n            IOSChild *c = [[IOSChild alloc] init];\n            c.name = [NSString stringWithFormat: @\"Name: %d\", i];\n            [obj.children addObject:c];\n        }\n        [realm addObject:obj];\n    }\n    [realm commitWriteTransaction];\n\n    realm = [AppDelegate appDefaultRealm:[NSString stringWithFormat:@\"%@-alltypes-default.realm\", version]];\n    [realm beginWriteTransaction];\n    IOSAllTypes *obj = [[IOSAllTypes alloc] init];\n    obj.byteCol = [NSData dataWithBytes:no_bytes length:sizeof(no_bytes)];\n    obj.stringCol = @\"\";\n    obj.dateCol = [NSDate dateWithTimeIntervalSince1970: 0];\n    [realm addObject:obj];\n    [realm commitWriteTransaction];\n\n    realm = [AppDelegate appDefaultRealm:[NSString stringWithFormat:@\"%@-alltypes-null-value.realm\", version]];\n    [realm beginWriteTransaction];\n    obj = [[IOSAllTypes alloc] init];\n    obj.byteCol = nil;\n    obj.stringCol = nil;\n    obj.dateCol = nil;\n    obj.child = nil;\n    obj.children = nil;\n    [realm addObject:obj];\n    [realm commitWriteTransaction];\n\n    realm = [AppDelegate appDefaultRealm:[NSString stringWithFormat:@\"%@-alltypes-min.realm\", version]];\n    [realm beginWriteTransaction];\n    obj = [[IOSAllTypes alloc] init];\n    obj.boolCol = FALSE;\n    obj.shortCol = SHRT_MIN;\n    obj.intCol = INT_MIN;\n    obj.longCol = LONG_MIN;\n    obj.longLongCol = std::numeric_limits<int64_t>::min();\n    obj.floatCol = -FLT_MAX;\n    obj.doubleCol = -DBL_MAX;\n    obj.byteCol = [NSData dataWithBytes:no_bytes length:sizeof(no_bytes)];\n    obj.stringCol = @\"\";\n    obj.dateCol = [NSDate dateWithTimeIntervalSinceReferenceDate:-DBL_MAX];\n    [realm addObject:obj];\n    [realm commitWriteTransaction];\n    NSLog(@\"%@, obj.longLongCol : 0x%llx\\n\",[NSString stringWithFormat:@\"%@-alltypes-min.realm\", version], obj.longLongCol);\n    NSLog(@\"%@, obj.dateCol : 0x%llx\\n\",[NSString stringWithFormat:@\"%@-alltypes-min.realm\", version], [AppDelegate realm_from_nsdate:obj.dateCol]);\n\n    realm = [AppDelegate appDefaultRealm:[NSString stringWithFormat:@\"%@-alltypes-max.realm\", version]];\n    [realm beginWriteTransaction];\n    obj = [[IOSAllTypes alloc] init];\n    obj.boolCol = TRUE;\n    obj.shortCol = SHRT_MAX;\n    obj.intCol = INT_MAX;\n    obj.longCol = LONG_MAX;\n    obj.longLongCol = std::numeric_limits<int64_t>::max();\n    obj.floatCol = FLT_MAX;\n    obj.doubleCol = DBL_MAX;\n    obj.byteCol = [NSData dataWithBytes:no_bytes length:sizeof(no_bytes)];\n    obj.stringCol = @\"\";\n    obj.dateCol = [NSDate dateWithTimeIntervalSinceReferenceDate:DBL_MAX];\n    [realm addObject:obj];\n    [realm commitWriteTransaction];\n    NSLog(@\"%@, obj.longLongCol : 0x%llx\\n\",[NSString stringWithFormat:@\"%@-alltypes-max.realm\", version], obj.longLongCol);\n    NSLog(@\"%@, obj.dateCol : 0x%llx\\n\",[NSString stringWithFormat:@\"%@-alltypes-max.realm\", version], [AppDelegate realm_from_nsdate:obj.dateCol]);\n\n    uint8_t buffer[64];\n    for (int i = 0; i < sizeof(buffer); i++) {\n        buffer[i] = 1;\n    }\n    NSData *keyData = [[NSData alloc] initWithBytes:buffer length:sizeof(buffer)]; // Zerofilled byte array\n    NSError *error;\n    RLMRealmConfiguration *config = [RLMRealmConfiguration defaultConfiguration];\n    config.fileURL = [NSURL fileURLWithPath:[AppDelegate getRealmFilePath:[NSString stringWithFormat:@\"%@-alltypes-default-encrypted.realm\", version]]];\n    config.encryptionKey = keyData;\n    config.readOnly = NO;\n    realm = [RLMRealm realmWithConfiguration:config error:&error];\n    [realm beginWriteTransaction];\n    obj = [[IOSAllTypes alloc] init];\n    obj.byteCol = [NSData dataWithBytes:no_bytes length:sizeof(no_bytes)];\n    obj.stringCol = @\"\";\n    obj.dateCol = [NSDate dateWithTimeIntervalSince1970: 0];\n    [realm addObject:obj];\n    [realm commitWriteTransaction];\n\n    NSLog(@\"Done\");\n    return YES;\n}\n@end\n\n```"
  },
  {
    "path": "realm/realm-library/src/androidTest/assets/list_alltypes_primarykey.json",
    "content": "[\n    {\n    \t\"columnString\" : \"Foo\",\n        \"columnLong\" : 1,\n        \"columnFloat\" : 1.23,\n        \"columnDouble\" : 1.234,\n        \"columnBoolean\" : false,\n        \"columnBinary\" : \"AQID\",\n        \"columnDate\" : 1000,\n        \"columnRealmObject\" : {\n            \"id\" : 1,\n            \"name\" : \"Dog1\"\n        },\n        \"columnRealmList\" : [\n            {\n                \"id\" : 2,\n                \"name\" : \"Dog2\"\n            },\n            {\n                \"id\" : 3,\n                \"name\" : \"Dog3\"\n            }\n        ],\n        \"columnDecimal128\" : -42,\n        \"columnObjectId\": \"789ABCDEF0123456789ABCDE\",\n        \"columnUUID\": \"027ba5ca-aa12-4afa-9219-e20cc3018599\",\n        \"columnRealmAny\": 5\n    },\n    {\n        \"columnString\" : \"Bar\",\n        \"columnLong\" : 1,\n        \"columnFloat\" : 2.23,\n        \"columnDouble\" : 2.234,\n        \"columnBoolean\" : true,\n        \"columnBinary\" : \"AQID\",\n        \"columnDate\" : 2000,\n        \"columnRealmObject\" : {\n            \"id\" : 4,\n            \"name\" : \"Dog4\"\n        },\n        \"columnRealmList\" : [\n            {\n                \"id\" : 5,\n                \"name\" : \"Dog5\"\n            },\n            {\n                \"id\" : 6,\n                \"name\" : \"Dog6\"\n            }\n        ],\n        \"columnDecimal128\" : -43,\n        \"columnObjectId\": \"789ABCDEF0123456789ABCDA\",\n        \"columnUUID\": \"027ba5ca-aa12-4afa-9219-e20cc3018590\",\n        \"columnRealmAny\": \"hello world\"\n    }\n]\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/assets/mutablerealminteger-int.json",
    "content": "{\n  \"columnNullableMutableRealmInteger\": 22\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/assets/mutablerealminteger-long.json",
    "content": "{\n  \"columnNullableMutableRealmInteger\": 8589934592\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/assets/mutablerealminteger-null.json",
    "content": "{\n  \"columnNullableMutableRealmInteger\": null\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/assets/mutablerealminteger-required-null.json",
    "content": "{\n  \"columnNonNullableMutableRealmInteger\": null\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/assets/nulltypes.json",
    "content": "[\n  {\n    \"id\": 1,\n    \"fieldStringNotNull\": \"\",\n    \"fieldStringNull\": null,\n    \"fieldBytesNotNull\": \"\",\n    \"fieldBytesNull\": null,\n    \"fieldBooleanNotNull\": false,\n    \"fieldBooleanNull\": null,\n    \"fieldByteNotNull\": 0,\n    \"fieldByteNull\": null,\n    \"fieldShortNotNull\": 0,\n    \"fieldShortNull\": null,\n    \"fieldIntegerNotNull\": 0,\n    \"fieldIntegerNull\": null,\n    \"fieldLongNotNull\": 0,\n    \"fieldLongNull\": null,\n    \"fieldFloatNotNull\": 0,\n    \"fieldFloatNull\": null,\n    \"fieldDoubleNotNull\": 0,\n    \"fieldDoubleNull\":null,\n    \"fieldDateNotNull\": 0,\n    \"fieldDateNull\": null,\n    \"fieldObjectNull\": null,\n    \"fieldDecimal128Null\": null,\n    \"fieldDecimal128NotNull\": -42,\n    \"fieldObjectIdNull\": null,\n    \"fieldObjectIdNotNull\": \"789ABCDEF0123456789ABCDE\",\n    \"fieldUUIDNull\": null,\n    \"fieldUUIDNotNull\": \"027ba5ca-aa12-4afa-9219-e20cc3018599\"\n  },\n  {\n    \"id\": 2,\n    \"fieldStringNotNull\": \"\",\n    \"fieldStringNull\": \"\",\n    \"fieldBytesNotNull\": \"\",\n    \"fieldBytesNull\": \"\",\n    \"fieldBooleanNotNull\": false,\n    \"fieldBooleanNull\": false,\n    \"fieldByteNotNull\": 0,\n    \"fieldByteNull\": 0,\n    \"fieldShortNotNull\": 0,\n    \"fieldShortNull\": 0,\n    \"fieldIntegerNotNull\": 0,\n    \"fieldIntegerNull\": 0,\n    \"fieldLongNotNull\": 0,\n    \"fieldLongNull\": 0,\n    \"fieldFloatNotNull\": 0,\n    \"fieldFloatNull\": 0,\n    \"fieldDoubleNotNull\": 0,\n    \"fieldDoubleNull\":0,\n    \"fieldDateNotNull\": 0,\n    \"fieldDateNull\": 0,\n    \"fieldObjectNull\": {\n      \"id\": 3,\n      \"fieldStringNotNull\": \"\",\n      \"fieldStringNull\": \"\",\n      \"fieldBytesNotNull\": \"\",\n      \"fieldBytesNull\": \"\",\n      \"fieldBooleanNotNull\": false,\n      \"fieldBooleanNull\": false,\n      \"fieldByteNotNull\": 0,\n      \"fieldByteNull\": 0,\n      \"fieldShortNotNull\": 0,\n      \"fieldShortNull\": 0,\n      \"fieldIntegerNotNull\": 0,\n      \"fieldIntegerNull\": 0,\n      \"fieldLongNotNull\": 0,\n      \"fieldLongNull\": 0,\n      \"fieldFloatNotNull\": 0,\n      \"fieldFloatNull\": 0,\n      \"fieldDoubleNotNull\": 0,\n      \"fieldDoubleNull\":0,\n      \"fieldDateNotNull\": 0,\n      \"fieldDateNull\": 0,\n      \"fieldObjectNull\": null,\n      \"fieldDecimal128Null\": 0,\n      \"fieldDecimal128NotNull\": 0,\n      \"fieldObjectIdNull\": \"789ABCDEF0123456789ABCDE\",\n      \"fieldObjectIdNotNull\": \"789ABCDEF0123456789ABCDE\",\n      \"fieldUUIDNull\": \"027ba5ca-aa12-4afa-9219-e20cc3018599\",\n      \"fieldUUIDNotNull\": \"027ba5ca-aa12-4afa-9219-e20cc3018599\"\n    },\n    \"fieldDecimal128Null\": 0,\n    \"fieldDecimal128NotNull\": 0,\n    \"fieldObjectIdNull\": \"789ABCDEF0123456789ABCDE\",\n    \"fieldObjectIdNotNull\": \"789ABCDEF0123456789ABCDE\",\n    \"fieldUUIDNull\": \"027ba5ca-aa12-4afa-9219-e20cc3018599\",\n    \"fieldUUIDNotNull\": \"027ba5ca-aa12-4afa-9219-e20cc3018599\"\n  }\n]\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/assets/nulltypes_invalid.json",
    "content": "[\n  {\n    \"id\": 1,\n    \"fieldStringNotNull\": null\n  },\n  {\n    \"id\": 2,\n    \"fieldBytesNotNull\": null\n  },\n  {\n    \"id\": 3,\n    \"fieldBooleanNotNull\": null\n  },\n  {\n    \"id\": 4,\n    \"fieldByteNotNull\": null\n  },\n  {\n    \"id\": 5,\n    \"fieldShortNotNull\": null\n  },\n  {\n    \"id\": 6,\n    \"fieldIntegerNotNull\": null\n  },\n  {\n    \"id\": 7,\n    \"fieldLongNotNull\": null\n  },\n  {\n    \"id\": 8,\n    \"fieldFloatNotNull\": null\n  },\n  {\n    \"id\": 9,\n    \"fieldDoubleNotNull\": null\n  },\n  {\n    \"id\": 10,\n    \"fieldDateNotNull\": null\n  },\n  {\n    \"id\": 11,\n    \"fieldDecimal128NotNull\": null\n  },\n  {\n    \"id\": 12,\n    \"fieldObjectIdNotNull\": null\n  },\n  {\n    \"id\": 13,\n    \"fieldUUIDNotNull\": null\n  }\n]\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/assets/objectid_as_string.json",
    "content": "{\n    \"columnObjectId\" : \"789ABCDEF0123456789ABCDE\"\n}"
  },
  {
    "path": "realm/realm-library/src/androidTest/assets/other_json_object.json",
    "content": "{\n\t\"I\" : null,\n\t\"aM\" : null,\n\t\"nOt\" : null,\n\t\"a\" : null,\n\t\"fiElD\" : null\n}"
  },
  {
    "path": "realm/realm-library/src/androidTest/assets/realmlist.json",
    "content": "{\n    \"columnRealmList\" : [\n        { \"name\" : \"Fido-1\" },\n        { \"name\" : \"Fido-2\" },\n        { \"name\" : \"Fido-3\" }\n    ]\n}"
  },
  {
    "path": "realm/realm-library/src/androidTest/assets/realmlist_empty.json",
    "content": "{\n    \"columnRealmList\" : []\n}"
  },
  {
    "path": "realm/realm-library/src/androidTest/assets/single_child_object.json",
    "content": "{\n    \"columnRealmObject\" : { \"name\" : \"Fido\" }\n}"
  },
  {
    "path": "realm/realm-library/src/androidTest/assets/unicode_codepoints.csv",
    "content": "0000\n0001\n0002\n0003\n0004\n0005\n0006\n0007\n0008\n0009\n000A\n000B\n000C\n000D\n000E\n000F\n0010\n0011\n0012\n0013\n0014\n0015\n0016\n0017\n0018\n0019\n001A\n001B\n001C\n001D\n001E\n001F\n0020\n0021\n0022\n0023\n0024\n0025\n0026\n0027\n0028\n0029\n002A\n002B\n002C\n002D\n002E\n002F\n0030\n0031\n0032\n0033\n0034\n0035\n0036\n0037\n0038\n0039\n003A\n003B\n003C\n003D\n003E\n003F\n0040\n0041\n0042\n0043\n0044\n0045\n0046\n0047\n0048\n0049\n004A\n004B\n004C\n004D\n004E\n004F\n0050\n0051\n0052\n0053\n0054\n0055\n0056\n0057\n0058\n0059\n005A\n005B\n005C\n005D\n005E\n005F\n0060\n0061\n0062\n0063\n0064\n0065\n0066\n0067\n0068\n0069\n006A\n006B\n006C\n006D\n006E\n006F\n0070\n0071\n0072\n0073\n0074\n0075\n0076\n0077\n0078\n0079\n007A\n007B\n007C\n007D\n007E\n007F\n0080\n0081\n0082\n0083\n0084\n0085\n0086\n0087\n0088\n0089\n008A\n008B\n008C\n008D\n008E\n008F\n0090\n0091\n0092\n0093\n0094\n0095\n0096\n0097\n0098\n0099\n009A\n009B\n009C\n009D\n009E\n009F\n00A0\n00A1\n00A2\n00A3\n00A4\n00A5\n00A6\n00A7\n00A8\n00A9\n00AA\n00AB\n00AC\n00AD\n00AE\n00AF\n00B0\n00B1\n00B2\n00B3\n00B4\n00B5\n00B6\n00B7\n00B8\n00B9\n00BA\n00BB\n00BC\n00BD\n00BE\n00BF\n00C0\n00C1\n00C2\n00C3\n00C4\n00C5\n00C6\n00C7\n00C8\n00C9\n00CA\n00CB\n00CC\n00CD\n00CE\n00CF\n00D0\n00D1\n00D2\n00D3\n00D4\n00D5\n00D6\n00D7\n00D8\n00D9\n00DA\n00DB\n00DC\n00DD\n00DE\n00DF\n00E0\n00E1\n00E2\n00E3\n00E4\n00E5\n00E6\n00E7\n00E8\n00E9\n00EA\n00EB\n00EC\n00ED\n00EE\n00EF\n00F0\n00F1\n00F2\n00F3\n00F4\n00F5\n00F6\n00F7\n00F8\n00F9\n00FA\n00FB\n00FC\n00FD\n00FE\n00FF\n0100\n0101\n0102\n0103\n0104\n0105\n0106\n0107\n0108\n0109\n010A\n010B\n010C\n010D\n010E\n010F\n0110\n0111\n0112\n0113\n0114\n0115\n0116\n0117\n0118\n0119\n011A\n011B\n011C\n011D\n011E\n011F\n0120\n0121\n0122\n0123\n0124\n0125\n0126\n0127\n0128\n0129\n012A\n012B\n012C\n012D\n012E\n012F\n0130\n0131\n0132\n0133\n0134\n0135\n0136\n0137\n0138\n0139\n013A\n013B\n013C\n013D\n013E\n013F\n0140\n0141\n0142\n0143\n0144\n0145\n0146\n0147\n0148\n0149\n014A\n014B\n014C\n014D\n014E\n014F\n0150\n0151\n0152\n0153\n0154\n0155\n0156\n0157\n0158\n0159\n015A\n015B\n015C\n015D\n015E\n015F\n0160\n0161\n0162\n0163\n0164\n0165\n0166\n0167\n0168\n0169\n016A\n016B\n016C\n016D\n016E\n016F\n0170\n0171\n0172\n0173\n0174\n0175\n0176\n0177\n0178\n0179\n017A\n017B\n017C\n017D\n017E\n017F\n0180\n0181\n0182\n0183\n0184\n0185\n0186\n0187\n0188\n0189\n018A\n018B\n018C\n018D\n018E\n018F\n0190\n0191\n0192\n0193\n0194\n0195\n0196\n0197\n0198\n0199\n019A\n019B\n019C\n019D\n019E\n019F\n01A0\n01A1\n01A2\n01A3\n01A4\n01A5\n01A6\n01A7\n01A8\n01A9\n01AA\n01AB\n01AC\n01AD\n01AE\n01AF\n01B0\n01B1\n01B2\n01B3\n01B4\n01B5\n01B6\n01B7\n01B8\n01B9\n01BA\n01BB\n01BC\n01BD\n01BE\n01BF\n01C0\n01C1\n01C2\n01C3\n01C4\n01C5\n01C6\n01C7\n01C8\n01C9\n01CA\n01CB\n01CC\n01CD\n01CE\n01CF\n01D0\n01D1\n01D2\n01D3\n01D4\n01D5\n01D6\n01D7\n01D8\n01D9\n01DA\n01DB\n01DC\n01DD\n01DE\n01DF\n01E0\n01E1\n01E2\n01E3\n01E4\n01E5\n01E6\n01E7\n01E8\n01E9\n01EA\n01EB\n01EC\n01ED\n01EE\n01EF\n01F0\n01F1\n01F2\n01F3\n01F4\n01F5\n01F6\n01F7\n01F8\n01F9\n01FA\n01FB\n01FC\n01FD\n01FE\n01FF\n0200\n0201\n0202\n0203\n0204\n0205\n0206\n0207\n0208\n0209\n020A\n020B\n020C\n020D\n020E\n020F\n0210\n0211\n0212\n0213\n0214\n0215\n0216\n0217\n0218\n0219\n021A\n021B\n021C\n021D\n021E\n021F\n0220\n0221\n0222\n0223\n0224\n0225\n0226\n0227\n0228\n0229\n022A\n022B\n022C\n022D\n022E\n022F\n0230\n0231\n0232\n0233\n0234\n0235\n0236\n0237\n0238\n0239\n023A\n023B\n023C\n023D\n023E\n023F\n0240\n0241\n0242\n0243\n0244\n0245\n0246\n0247\n0248\n0249\n024A\n024B\n024C\n024D\n024E\n024F\n0250\n0251\n0252\n0253\n0254\n0255\n0256\n0257\n0258\n0259\n025A\n025B\n025C\n025D\n025E\n025F\n0260\n0261\n0262\n0263\n0264\n0265\n0266\n0267\n0268\n0269\n026A\n026B\n026C\n026D\n026E\n026F\n0270\n0271\n0272\n0273\n0274\n0275\n0276\n0277\n0278\n0279\n027A\n027B\n027C\n027D\n027E\n027F\n0280\n0281\n0282\n0283\n0284\n0285\n0286\n0287\n0288\n0289\n028A\n028B\n028C\n028D\n028E\n028F\n0290\n0291\n0292\n0293\n0294\n0295\n0296\n0297\n0298\n0299\n029A\n029B\n029C\n029D\n029E\n029F\n02A0\n02A1\n02A2\n02A3\n02A4\n02A5\n02A6\n02A7\n02A8\n02A9\n02AA\n02AB\n02AC\n02AD\n02AE\n02AF\n02B0\n02B1\n02B2\n02B3\n02B4\n02B5\n02B6\n02B7\n02B8\n02B9\n02BA\n02BB\n02BC\n02BD\n02BE\n02BF\n02C0\n02C1\n02C2\n02C3\n02C4\n02C5\n02C6\n02C7\n02C8\n02C9\n02CA\n02CB\n02CC\n02CD\n02CE\n02CF\n02D0\n02D1\n02D2\n02D3\n02D4\n02D5\n02D6\n02D7\n02D8\n02D9\n02DA\n02DB\n02DC\n02DD\n02DE\n02DF\n02E0\n02E1\n02E2\n02E3\n02E4\n02E5\n02E6\n02E7\n02E8\n02E9\n02EA\n02EB\n02EC\n02ED\n02EE\n02EF\n02F0\n02F1\n02F2\n02F3\n02F4\n02F5\n02F6\n02F7\n02F8\n02F9\n02FA\n02FB\n02FC\n02FD\n02FE\n02FF\n0300\n0301\n0302\n0303\n0304\n0305\n0306\n0307\n0308\n0309\n030A\n030B\n030C\n030D\n030E\n030F\n0310\n0311\n0312\n0313\n0314\n0315\n0316\n0317\n0318\n0319\n031A\n031B\n031C\n031D\n031E\n031F\n0320\n0321\n0322\n0323\n0324\n0325\n0326\n0327\n0328\n0329\n032A\n032B\n032C\n032D\n032E\n032F\n0330\n0331\n0332\n0333\n0334\n0335\n0336\n0337\n0338\n0339\n033A\n033B\n033C\n033D\n033E\n033F\n0340\n0341\n0342\n0343\n0344\n0345\n0346\n0347\n0348\n0349\n034A\n034B\n034C\n034D\n034E\n034F\n0350\n0351\n0352\n0353\n0354\n0355\n0356\n0357\n0358\n0359\n035A\n035B\n035C\n035D\n035E\n035F\n0360\n0361\n0362\n0363\n0364\n0365\n0366\n0367\n0368\n0369\n036A\n036B\n036C\n036D\n036E\n036F\n0370\n0371\n0372\n0373\n0374\n0375\n0376\n0377\n037A\n037B\n037C\n037D\n037E\n037F\n0384\n0385\n0386\n0387\n0388\n0389\n038A\n038C\n038E\n038F\n0390\n0391\n0392\n0393\n0394\n0395\n0396\n0397\n0398\n0399\n039A\n039B\n039C\n039D\n039E\n039F\n03A0\n03A1\n03A3\n03A4\n03A5\n03A6\n03A7\n03A8\n03A9\n03AA\n03AB\n03AC\n03AD\n03AE\n03AF\n03B0\n03B1\n03B2\n03B3\n03B4\n03B5\n03B6\n03B7\n03B8\n03B9\n03BA\n03BB\n03BC\n03BD\n03BE\n03BF\n03C0\n03C1\n03C2\n03C3\n03C4\n03C5\n03C6\n03C7\n03C8\n03C9\n03CA\n03CB\n03CC\n03CD\n03CE\n03CF\n03D0\n03D1\n03D2\n03D3\n03D4\n03D5\n03D6\n03D7\n03D8\n03D9\n03DA\n03DB\n03DC\n03DD\n03DE\n03DF\n03E0\n03E1\n03E2\n03E3\n03E4\n03E5\n03E6\n03E7\n03E8\n03E9\n03EA\n03EB\n03EC\n03ED\n03EE\n03EF\n03F0\n03F1\n03F2\n03F3\n03F4\n03F5\n03F6\n03F7\n03F8\n03F9\n03FA\n03FB\n03FC\n03FD\n03FE\n03FF\n0400\n0401\n0402\n0403\n0404\n0405\n0406\n0407\n0408\n0409\n040A\n040B\n040C\n040D\n040E\n040F\n0410\n0411\n0412\n0413\n0414\n0415\n0416\n0417\n0418\n0419\n041A\n041B\n041C\n041D\n041E\n041F\n0420\n0421\n0422\n0423\n0424\n0425\n0426\n0427\n0428\n0429\n042A\n042B\n042C\n042D\n042E\n042F\n0430\n0431\n0432\n0433\n0434\n0435\n0436\n0437\n0438\n0439\n043A\n043B\n043C\n043D\n043E\n043F\n0440\n0441\n0442\n0443\n0444\n0445\n0446\n0447\n0448\n0449\n044A\n044B\n044C\n044D\n044E\n044F\n0450\n0451\n0452\n0453\n0454\n0455\n0456\n0457\n0458\n0459\n045A\n045B\n045C\n045D\n045E\n045F\n0460\n0461\n0462\n0463\n0464\n0465\n0466\n0467\n0468\n0469\n046A\n046B\n046C\n046D\n046E\n046F\n0470\n0471\n0472\n0473\n0474\n0475\n0476\n0477\n0478\n0479\n047A\n047B\n047C\n047D\n047E\n047F\n0480\n0481\n0482\n0483\n0484\n0485\n0486\n0487\n0488\n0489\n048A\n048B\n048C\n048D\n048E\n048F\n0490\n0491\n0492\n0493\n0494\n0495\n0496\n0497\n0498\n0499\n049A\n049B\n049C\n049D\n049E\n049F\n04A0\n04A1\n04A2\n04A3\n04A4\n04A5\n04A6\n04A7\n04A8\n04A9\n04AA\n04AB\n04AC\n04AD\n04AE\n04AF\n04B0\n04B1\n04B2\n04B3\n04B4\n04B5\n04B6\n04B7\n04B8\n04B9\n04BA\n04BB\n04BC\n04BD\n04BE\n04BF\n04C0\n04C1\n04C2\n04C3\n04C4\n04C5\n04C6\n04C7\n04C8\n04C9\n04CA\n04CB\n04CC\n04CD\n04CE\n04CF\n04D0\n04D1\n04D2\n04D3\n04D4\n04D5\n04D6\n04D7\n04D8\n04D9\n04DA\n04DB\n04DC\n04DD\n04DE\n04DF\n04E0\n04E1\n04E2\n04E3\n04E4\n04E5\n04E6\n04E7\n04E8\n04E9\n04EA\n04EB\n04EC\n04ED\n04EE\n04EF\n04F0\n04F1\n04F2\n04F3\n04F4\n04F5\n04F6\n04F7\n04F8\n04F9\n04FA\n04FB\n04FC\n04FD\n04FE\n04FF\n0500\n0501\n0502\n0503\n0504\n0505\n0506\n0507\n0508\n0509\n050A\n050B\n050C\n050D\n050E\n050F\n0510\n0511\n0512\n0513\n0514\n0515\n0516\n0517\n0518\n0519\n051A\n051B\n051C\n051D\n051E\n051F\n0520\n0521\n0522\n0523\n0524\n0525\n0526\n0527\n0528\n0529\n052A\n052B\n052C\n052D\n052E\n052F\n0531\n0532\n0533\n0534\n0535\n0536\n0537\n0538\n0539\n053A\n053B\n053C\n053D\n053E\n053F\n0540\n0541\n0542\n0543\n0544\n0545\n0546\n0547\n0548\n0549\n054A\n054B\n054C\n054D\n054E\n054F\n0550\n0551\n0552\n0553\n0554\n0555\n0556\n0559\n055A\n055B\n055C\n055D\n055E\n055F\n0561\n0562\n0563\n0564\n0565\n0566\n0567\n0568\n0569\n056A\n056B\n056C\n056D\n056E\n056F\n0570\n0571\n0572\n0573\n0574\n0575\n0576\n0577\n0578\n0579\n057A\n057B\n057C\n057D\n057E\n057F\n0580\n0581\n0582\n0583\n0584\n0585\n0586\n0587\n0589\n058A\n058D\n058E\n058F\n0591\n0592\n0593\n0594\n0595\n0596\n0597\n0598\n0599\n059A\n059B\n059C\n059D\n059E\n059F\n05A0\n05A1\n05A2\n05A3\n05A4\n05A5\n05A6\n05A7\n05A8\n05A9\n05AA\n05AB\n05AC\n05AD\n05AE\n05AF\n05B0\n05B1\n05B2\n05B3\n05B4\n05B5\n05B6\n05B7\n05B8\n05B9\n05BA\n05BB\n05BC\n05BD\n05BE\n05BF\n05C0\n05C1\n05C2\n05C3\n05C4\n05C5\n05C6\n05C7\n05D0\n05D1\n05D2\n05D3\n05D4\n05D5\n05D6\n05D7\n05D8\n05D9\n05DA\n05DB\n05DC\n05DD\n05DE\n05DF\n05E0\n05E1\n05E2\n05E3\n05E4\n05E5\n05E6\n05E7\n05E8\n05E9\n05EA\n05F0\n05F1\n05F2\n05F3\n05F4\n0600\n0601\n0602\n0603\n0604\n0605\n0606\n0607\n0608\n0609\n060A\n060B\n060C\n060D\n060E\n060F\n0610\n0611\n0612\n0613\n0614\n0615\n0616\n0617\n0618\n0619\n061A\n061B\n061C\n061E\n061F\n0620\n0621\n0622\n0623\n0624\n0625\n0626\n0627\n0628\n0629\n062A\n062B\n062C\n062D\n062E\n062F\n0630\n0631\n0632\n0633\n0634\n0635\n0636\n0637\n0638\n0639\n063A\n063B\n063C\n063D\n063E\n063F\n0640\n0641\n0642\n0643\n0644\n0645\n0646\n0647\n0648\n0649\n064A\n064B\n064C\n064D\n064E\n064F\n0650\n0651\n0652\n0653\n0654\n0655\n0656\n0657\n0658\n0659\n065A\n065B\n065C\n065D\n065E\n065F\n0660\n0661\n0662\n0663\n0664\n0665\n0666\n0667\n0668\n0669\n066A\n066B\n066C\n066D\n066E\n066F\n0670\n0671\n0672\n0673\n0674\n0675\n0676\n0677\n0678\n0679\n067A\n067B\n067C\n067D\n067E\n067F\n0680\n0681\n0682\n0683\n0684\n0685\n0686\n0687\n0688\n0689\n068A\n068B\n068C\n068D\n068E\n068F\n0690\n0691\n0692\n0693\n0694\n0695\n0696\n0697\n0698\n0699\n069A\n069B\n069C\n069D\n069E\n069F\n06A0\n06A1\n06A2\n06A3\n06A4\n06A5\n06A6\n06A7\n06A8\n06A9\n06AA\n06AB\n06AC\n06AD\n06AE\n06AF\n06B0\n06B1\n06B2\n06B3\n06B4\n06B5\n06B6\n06B7\n06B8\n06B9\n06BA\n06BB\n06BC\n06BD\n06BE\n06BF\n06C0\n06C1\n06C2\n06C3\n06C4\n06C5\n06C6\n06C7\n06C8\n06C9\n06CA\n06CB\n06CC\n06CD\n06CE\n06CF\n06D0\n06D1\n06D2\n06D3\n06D4\n06D5\n06D6\n06D7\n06D8\n06D9\n06DA\n06DB\n06DC\n06DD\n06DE\n06DF\n06E0\n06E1\n06E2\n06E3\n06E4\n06E5\n06E6\n06E7\n06E8\n06E9\n06EA\n06EB\n06EC\n06ED\n06EE\n06EF\n06F0\n06F1\n06F2\n06F3\n06F4\n06F5\n06F6\n06F7\n06F8\n06F9\n06FA\n06FB\n06FC\n06FD\n06FE\n06FF\n0700\n0701\n0702\n0703\n0704\n0705\n0706\n0707\n0708\n0709\n070A\n070B\n070C\n070D\n070F\n0710\n0711\n0712\n0713\n0714\n0715\n0716\n0717\n0718\n0719\n071A\n071B\n071C\n071D\n071E\n071F\n0720\n0721\n0722\n0723\n0724\n0725\n0726\n0727\n0728\n0729\n072A\n072B\n072C\n072D\n072E\n072F\n0730\n0731\n0732\n0733\n0734\n0735\n0736\n0737\n0738\n0739\n073A\n073B\n073C\n073D\n073E\n073F\n0740\n0741\n0742\n0743\n0744\n0745\n0746\n0747\n0748\n0749\n074A\n074D\n074E\n074F\n0750\n0751\n0752\n0753\n0754\n0755\n0756\n0757\n0758\n0759\n075A\n075B\n075C\n075D\n075E\n075F\n0760\n0761\n0762\n0763\n0764\n0765\n0766\n0767\n0768\n0769\n076A\n076B\n076C\n076D\n076E\n076F\n0770\n0771\n0772\n0773\n0774\n0775\n0776\n0777\n0778\n0779\n077A\n077B\n077C\n077D\n077E\n077F\n0780\n0781\n0782\n0783\n0784\n0785\n0786\n0787\n0788\n0789\n078A\n078B\n078C\n078D\n078E\n078F\n0790\n0791\n0792\n0793\n0794\n0795\n0796\n0797\n0798\n0799\n079A\n079B\n079C\n079D\n079E\n079F\n07A0\n07A1\n07A2\n07A3\n07A4\n07A5\n07A6\n07A7\n07A8\n07A9\n07AA\n07AB\n07AC\n07AD\n07AE\n07AF\n07B0\n07B1\n07C0\n07C1\n07C2\n07C3\n07C4\n07C5\n07C6\n07C7\n07C8\n07C9\n07CA\n07CB\n07CC\n07CD\n07CE\n07CF\n07D0\n07D1\n07D2\n07D3\n07D4\n07D5\n07D6\n07D7\n07D8\n07D9\n07DA\n07DB\n07DC\n07DD\n07DE\n07DF\n07E0\n07E1\n07E2\n07E3\n07E4\n07E5\n07E6\n07E7\n07E8\n07E9\n07EA\n07EB\n07EC\n07ED\n07EE\n07EF\n07F0\n07F1\n07F2\n07F3\n07F4\n07F5\n07F6\n07F7\n07F8\n07F9\n07FA\n0800\n0801\n0802\n0803\n0804\n0805\n0806\n0807\n0808\n0809\n080A\n080B\n080C\n080D\n080E\n080F\n0810\n0811\n0812\n0813\n0814\n0815\n0816\n0817\n0818\n0819\n081A\n081B\n081C\n081D\n081E\n081F\n0820\n0821\n0822\n0823\n0824\n0825\n0826\n0827\n0828\n0829\n082A\n082B\n082C\n082D\n0830\n0831\n0832\n0833\n0834\n0835\n0836\n0837\n0838\n0839\n083A\n083B\n083C\n083D\n083E\n0840\n0841\n0842\n0843\n0844\n0845\n0846\n0847\n0848\n0849\n084A\n084B\n084C\n084D\n084E\n084F\n0850\n0851\n0852\n0853\n0854\n0855\n0856\n0857\n0858\n0859\n085A\n085B\n085E\n08A0\n08A1\n08A2\n08A3\n08A4\n08A5\n08A6\n08A7\n08A8\n08A9\n08AA\n08AB\n08AC\n08AD\n08AE\n08AF\n08B0\n08B1\n08B2\n08E4\n08E5\n08E6\n08E7\n08E8\n08E9\n08EA\n08EB\n08EC\n08ED\n08EE\n08EF\n08F0\n08F1\n08F2\n08F3\n08F4\n08F5\n08F6\n08F7\n08F8\n08F9\n08FA\n08FB\n08FC\n08FD\n08FE\n08FF\n0900\n0901\n0902\n0903\n0904\n0905\n0906\n0907\n0908\n0909\n090A\n090B\n090C\n090D\n090E\n090F\n0910\n0911\n0912\n0913\n0914\n0915\n0916\n0917\n0918\n0919\n091A\n091B\n091C\n091D\n091E\n091F\n0920\n0921\n0922\n0923\n0924\n0925\n0926\n0927\n0928\n0929\n092A\n092B\n092C\n092D\n092E\n092F\n0930\n0931\n0932\n0933\n0934\n0935\n0936\n0937\n0938\n0939\n093A\n093B\n093C\n093D\n093E\n093F\n0940\n0941\n0942\n0943\n0944\n0945\n0946\n0947\n0948\n0949\n094A\n094B\n094C\n094D\n094E\n094F\n0950\n0951\n0952\n0953\n0954\n0955\n0956\n0957\n0958\n0959\n095A\n095B\n095C\n095D\n095E\n095F\n0960\n0961\n0962\n0963\n0964\n0965\n0966\n0967\n0968\n0969\n096A\n096B\n096C\n096D\n096E\n096F\n0970\n0971\n0972\n0973\n0974\n0975\n0976\n0977\n0978\n0979\n097A\n097B\n097C\n097D\n097E\n097F\n0980\n0981\n0982\n0983\n0985\n0986\n0987\n0988\n0989\n098A\n098B\n098C\n098F\n0990\n0993\n0994\n0995\n0996\n0997\n0998\n0999\n099A\n099B\n099C\n099D\n099E\n099F\n09A0\n09A1\n09A2\n09A3\n09A4\n09A5\n09A6\n09A7\n09A8\n09AA\n09AB\n09AC\n09AD\n09AE\n09AF\n09B0\n09B2\n09B6\n09B7\n09B8\n09B9\n09BC\n09BD\n09BE\n09BF\n09C0\n09C1\n09C2\n09C3\n09C4\n09C7\n09C8\n09CB\n09CC\n09CD\n09CE\n09D7\n09DC\n09DD\n09DF\n09E0\n09E1\n09E2\n09E3\n09E6\n09E7\n09E8\n09E9\n09EA\n09EB\n09EC\n09ED\n09EE\n09EF\n09F0\n09F1\n09F2\n09F3\n09F4\n09F5\n09F6\n09F7\n09F8\n09F9\n09FA\n09FB\n0A01\n0A02\n0A03\n0A05\n0A06\n0A07\n0A08\n0A09\n0A0A\n0A0F\n0A10\n0A13\n0A14\n0A15\n0A16\n0A17\n0A18\n0A19\n0A1A\n0A1B\n0A1C\n0A1D\n0A1E\n0A1F\n0A20\n0A21\n0A22\n0A23\n0A24\n0A25\n0A26\n0A27\n0A28\n0A2A\n0A2B\n0A2C\n0A2D\n0A2E\n0A2F\n0A30\n0A32\n0A33\n0A35\n0A36\n0A38\n0A39\n0A3C\n0A3E\n0A3F\n0A40\n0A41\n0A42\n0A47\n0A48\n0A4B\n0A4C\n0A4D\n0A51\n0A59\n0A5A\n0A5B\n0A5C\n0A5E\n0A66\n0A67\n0A68\n0A69\n0A6A\n0A6B\n0A6C\n0A6D\n0A6E\n0A6F\n0A70\n0A71\n0A72\n0A73\n0A74\n0A75\n0A81\n0A82\n0A83\n0A85\n0A86\n0A87\n0A88\n0A89\n0A8A\n0A8B\n0A8C\n0A8D\n0A8F\n0A90\n0A91\n0A93\n0A94\n0A95\n0A96\n0A97\n0A98\n0A99\n0A9A\n0A9B\n0A9C\n0A9D\n0A9E\n0A9F\n0AA0\n0AA1\n0AA2\n0AA3\n0AA4\n0AA5\n0AA6\n0AA7\n0AA8\n0AAA\n0AAB\n0AAC\n0AAD\n0AAE\n0AAF\n0AB0\n0AB2\n0AB3\n0AB5\n0AB6\n0AB7\n0AB8\n0AB9\n0ABC\n0ABD\n0ABE\n0ABF\n0AC0\n0AC1\n0AC2\n0AC3\n0AC4\n0AC5\n0AC7\n0AC8\n0AC9\n0ACB\n0ACC\n0ACD\n0AD0\n0AE0\n0AE1\n0AE2\n0AE3\n0AE6\n0AE7\n0AE8\n0AE9\n0AEA\n0AEB\n0AEC\n0AED\n0AEE\n0AEF\n0AF0\n0AF1\n0B01\n0B02\n0B03\n0B05\n0B06\n0B07\n0B08\n0B09\n0B0A\n0B0B\n0B0C\n0B0F\n0B10\n0B13\n0B14\n0B15\n0B16\n0B17\n0B18\n0B19\n0B1A\n0B1B\n0B1C\n0B1D\n0B1E\n0B1F\n0B20\n0B21\n0B22\n0B23\n0B24\n0B25\n0B26\n0B27\n0B28\n0B2A\n0B2B\n0B2C\n0B2D\n0B2E\n0B2F\n0B30\n0B32\n0B33\n0B35\n0B36\n0B37\n0B38\n0B39\n0B3C\n0B3D\n0B3E\n0B3F\n0B40\n0B41\n0B42\n0B43\n0B44\n0B47\n0B48\n0B4B\n0B4C\n0B4D\n0B56\n0B57\n0B5C\n0B5D\n0B5F\n0B60\n0B61\n0B62\n0B63\n0B66\n0B67\n0B68\n0B69\n0B6A\n0B6B\n0B6C\n0B6D\n0B6E\n0B6F\n0B70\n0B71\n0B72\n0B73\n0B74\n0B75\n0B76\n0B77\n0B82\n0B83\n0B85\n0B86\n0B87\n0B88\n0B89\n0B8A\n0B8E\n0B8F\n0B90\n0B92\n0B93\n0B94\n0B95\n0B99\n0B9A\n0B9C\n0B9E\n0B9F\n0BA3\n0BA4\n0BA8\n0BA9\n0BAA\n0BAE\n0BAF\n0BB0\n0BB1\n0BB2\n0BB3\n0BB4\n0BB5\n0BB6\n0BB7\n0BB8\n0BB9\n0BBE\n0BBF\n0BC0\n0BC1\n0BC2\n0BC6\n0BC7\n0BC8\n0BCA\n0BCB\n0BCC\n0BCD\n0BD0\n0BD7\n0BE6\n0BE7\n0BE8\n0BE9\n0BEA\n0BEB\n0BEC\n0BED\n0BEE\n0BEF\n0BF0\n0BF1\n0BF2\n0BF3\n0BF4\n0BF5\n0BF6\n0BF7\n0BF8\n0BF9\n0BFA\n0C00\n0C01\n0C02\n0C03\n0C05\n0C06\n0C07\n0C08\n0C09\n0C0A\n0C0B\n0C0C\n0C0E\n0C0F\n0C10\n0C12\n0C13\n0C14\n0C15\n0C16\n0C17\n0C18\n0C19\n0C1A\n0C1B\n0C1C\n0C1D\n0C1E\n0C1F\n0C20\n0C21\n0C22\n0C23\n0C24\n0C25\n0C26\n0C27\n0C28\n0C2A\n0C2B\n0C2C\n0C2D\n0C2E\n0C2F\n0C30\n0C31\n0C32\n0C33\n0C34\n0C35\n0C36\n0C37\n0C38\n0C39\n0C3D\n0C3E\n0C3F\n0C40\n0C41\n0C42\n0C43\n0C44\n0C46\n0C47\n0C48\n0C4A\n0C4B\n0C4C\n0C4D\n0C55\n0C56\n0C58\n0C59\n0C60\n0C61\n0C62\n0C63\n0C66\n0C67\n0C68\n0C69\n0C6A\n0C6B\n0C6C\n0C6D\n0C6E\n0C6F\n0C78\n0C79\n0C7A\n0C7B\n0C7C\n0C7D\n0C7E\n0C7F\n0C81\n0C82\n0C83\n0C85\n0C86\n0C87\n0C88\n0C89\n0C8A\n0C8B\n0C8C\n0C8E\n0C8F\n0C90\n0C92\n0C93\n0C94\n0C95\n0C96\n0C97\n0C98\n0C99\n0C9A\n0C9B\n0C9C\n0C9D\n0C9E\n0C9F\n0CA0\n0CA1\n0CA2\n0CA3\n0CA4\n0CA5\n0CA6\n0CA7\n0CA8\n0CAA\n0CAB\n0CAC\n0CAD\n0CAE\n0CAF\n0CB0\n0CB1\n0CB2\n0CB3\n0CB5\n0CB6\n0CB7\n0CB8\n0CB9\n0CBC\n0CBD\n0CBE\n0CBF\n0CC0\n0CC1\n0CC2\n0CC3\n0CC4\n0CC6\n0CC7\n0CC8\n0CCA\n0CCB\n0CCC\n0CCD\n0CD5\n0CD6\n0CDE\n0CE0\n0CE1\n0CE2\n0CE3\n0CE6\n0CE7\n0CE8\n0CE9\n0CEA\n0CEB\n0CEC\n0CED\n0CEE\n0CEF\n0CF1\n0CF2\n0D01\n0D02\n0D03\n0D05\n0D06\n0D07\n0D08\n0D09\n0D0A\n0D0B\n0D0C\n0D0E\n0D0F\n0D10\n0D12\n0D13\n0D14\n0D15\n0D16\n0D17\n0D18\n0D19\n0D1A\n0D1B\n0D1C\n0D1D\n0D1E\n0D1F\n0D20\n0D21\n0D22\n0D23\n0D24\n0D25\n0D26\n0D27\n0D28\n0D29\n0D2A\n0D2B\n0D2C\n0D2D\n0D2E\n0D2F\n0D30\n0D31\n0D32\n0D33\n0D34\n0D35\n0D36\n0D37\n0D38\n0D39\n0D3A\n0D3D\n0D3E\n0D3F\n0D40\n0D41\n0D42\n0D43\n0D44\n0D46\n0D47\n0D48\n0D4A\n0D4B\n0D4C\n0D4D\n0D4E\n0D57\n0D60\n0D61\n0D62\n0D63\n0D66\n0D67\n0D68\n0D69\n0D6A\n0D6B\n0D6C\n0D6D\n0D6E\n0D6F\n0D70\n0D71\n0D72\n0D73\n0D74\n0D75\n0D79\n0D7A\n0D7B\n0D7C\n0D7D\n0D7E\n0D7F\n0D82\n0D83\n0D85\n0D86\n0D87\n0D88\n0D89\n0D8A\n0D8B\n0D8C\n0D8D\n0D8E\n0D8F\n0D90\n0D91\n0D92\n0D93\n0D94\n0D95\n0D96\n0D9A\n0D9B\n0D9C\n0D9D\n0D9E\n0D9F\n0DA0\n0DA1\n0DA2\n0DA3\n0DA4\n0DA5\n0DA6\n0DA7\n0DA8\n0DA9\n0DAA\n0DAB\n0DAC\n0DAD\n0DAE\n0DAF\n0DB0\n0DB1\n0DB3\n0DB4\n0DB5\n0DB6\n0DB7\n0DB8\n0DB9\n0DBA\n0DBB\n0DBD\n0DC0\n0DC1\n0DC2\n0DC3\n0DC4\n0DC5\n0DC6\n0DCA\n0DCF\n0DD0\n0DD1\n0DD2\n0DD3\n0DD4\n0DD6\n0DD8\n0DD9\n0DDA\n0DDB\n0DDC\n0DDD\n0DDE\n0DDF\n0DE6\n0DE7\n0DE8\n0DE9\n0DEA\n0DEB\n0DEC\n0DED\n0DEE\n0DEF\n0DF2\n0DF3\n0DF4\n0E01\n0E02\n0E03\n0E04\n0E05\n0E06\n0E07\n0E08\n0E09\n0E0A\n0E0B\n0E0C\n0E0D\n0E0E\n0E0F\n0E10\n0E11\n0E12\n0E13\n0E14\n0E15\n0E16\n0E17\n0E18\n0E19\n0E1A\n0E1B\n0E1C\n0E1D\n0E1E\n0E1F\n0E20\n0E21\n0E22\n0E23\n0E24\n0E25\n0E26\n0E27\n0E28\n0E29\n0E2A\n0E2B\n0E2C\n0E2D\n0E2E\n0E2F\n0E30\n0E31\n0E32\n0E33\n0E34\n0E35\n0E36\n0E37\n0E38\n0E39\n0E3A\n0E3F\n0E40\n0E41\n0E42\n0E43\n0E44\n0E45\n0E46\n0E47\n0E48\n0E49\n0E4A\n0E4B\n0E4C\n0E4D\n0E4E\n0E4F\n0E50\n0E51\n0E52\n0E53\n0E54\n0E55\n0E56\n0E57\n0E58\n0E59\n0E5A\n0E5B\n0E81\n0E82\n0E84\n0E87\n0E88\n0E8A\n0E8D\n0E94\n0E95\n0E96\n0E97\n0E99\n0E9A\n0E9B\n0E9C\n0E9D\n0E9E\n0E9F\n0EA1\n0EA2\n0EA3\n0EA5\n0EA7\n0EAA\n0EAB\n0EAD\n0EAE\n0EAF\n0EB0\n0EB1\n0EB2\n0EB3\n0EB4\n0EB5\n0EB6\n0EB7\n0EB8\n0EB9\n0EBB\n0EBC\n0EBD\n0EC0\n0EC1\n0EC2\n0EC3\n0EC4\n0EC6\n0EC8\n0EC9\n0ECA\n0ECB\n0ECC\n0ECD\n0ED0\n0ED1\n0ED2\n0ED3\n0ED4\n0ED5\n0ED6\n0ED7\n0ED8\n0ED9\n0EDC\n0EDD\n0EDE\n0EDF\n0F00\n0F01\n0F02\n0F03\n0F04\n0F05\n0F06\n0F07\n0F08\n0F09\n0F0A\n0F0B\n0F0C\n0F0D\n0F0E\n0F0F\n0F10\n0F11\n0F12\n0F13\n0F14\n0F15\n0F16\n0F17\n0F18\n0F19\n0F1A\n0F1B\n0F1C\n0F1D\n0F1E\n0F1F\n0F20\n0F21\n0F22\n0F23\n0F24\n0F25\n0F26\n0F27\n0F28\n0F29\n0F2A\n0F2B\n0F2C\n0F2D\n0F2E\n0F2F\n0F30\n0F31\n0F32\n0F33\n0F34\n0F35\n0F36\n0F37\n0F38\n0F39\n0F3A\n0F3B\n0F3C\n0F3D\n0F3E\n0F3F\n0F40\n0F41\n0F42\n0F43\n0F44\n0F45\n0F46\n0F47\n0F49\n0F4A\n0F4B\n0F4C\n0F4D\n0F4E\n0F4F\n0F50\n0F51\n0F52\n0F53\n0F54\n0F55\n0F56\n0F57\n0F58\n0F59\n0F5A\n0F5B\n0F5C\n0F5D\n0F5E\n0F5F\n0F60\n0F61\n0F62\n0F63\n0F64\n0F65\n0F66\n0F67\n0F68\n0F69\n0F6A\n0F6B\n0F6C\n0F71\n0F72\n0F73\n0F74\n0F75\n0F76\n0F77\n0F78\n0F79\n0F7A\n0F7B\n0F7C\n0F7D\n0F7E\n0F7F\n0F80\n0F81\n0F82\n0F83\n0F84\n0F85\n0F86\n0F87\n0F88\n0F89\n0F8A\n0F8B\n0F8C\n0F8D\n0F8E\n0F8F\n0F90\n0F91\n0F92\n0F93\n0F94\n0F95\n0F96\n0F97\n0F99\n0F9A\n0F9B\n0F9C\n0F9D\n0F9E\n0F9F\n0FA0\n0FA1\n0FA2\n0FA3\n0FA4\n0FA5\n0FA6\n0FA7\n0FA8\n0FA9\n0FAA\n0FAB\n0FAC\n0FAD\n0FAE\n0FAF\n0FB0\n0FB1\n0FB2\n0FB3\n0FB4\n0FB5\n0FB6\n0FB7\n0FB8\n0FB9\n0FBA\n0FBB\n0FBC\n0FBE\n0FBF\n0FC0\n0FC1\n0FC2\n0FC3\n0FC4\n0FC5\n0FC6\n0FC7\n0FC8\n0FC9\n0FCA\n0FCB\n0FCC\n0FCE\n0FCF\n0FD0\n0FD1\n0FD2\n0FD3\n0FD4\n0FD5\n0FD6\n0FD7\n0FD8\n0FD9\n0FDA\n1000\n1001\n1002\n1003\n1004\n1005\n1006\n1007\n1008\n1009\n100A\n100B\n100C\n100D\n100E\n100F\n1010\n1011\n1012\n1013\n1014\n1015\n1016\n1017\n1018\n1019\n101A\n101B\n101C\n101D\n101E\n101F\n1020\n1021\n1022\n1023\n1024\n1025\n1026\n1027\n1028\n1029\n102A\n102B\n102C\n102D\n102E\n102F\n1030\n1031\n1032\n1033\n1034\n1035\n1036\n1037\n1038\n1039\n103A\n103B\n103C\n103D\n103E\n103F\n1040\n1041\n1042\n1043\n1044\n1045\n1046\n1047\n1048\n1049\n104A\n104B\n104C\n104D\n104E\n104F\n1050\n1051\n1052\n1053\n1054\n1055\n1056\n1057\n1058\n1059\n105A\n105B\n105C\n105D\n105E\n105F\n1060\n1061\n1062\n1063\n1064\n1065\n1066\n1067\n1068\n1069\n106A\n106B\n106C\n106D\n106E\n106F\n1070\n1071\n1072\n1073\n1074\n1075\n1076\n1077\n1078\n1079\n107A\n107B\n107C\n107D\n107E\n107F\n1080\n1081\n1082\n1083\n1084\n1085\n1086\n1087\n1088\n1089\n108A\n108B\n108C\n108D\n108E\n108F\n1090\n1091\n1092\n1093\n1094\n1095\n1096\n1097\n1098\n1099\n109A\n109B\n109C\n109D\n109E\n109F\n10A0\n10A1\n10A2\n10A3\n10A4\n10A5\n10A6\n10A7\n10A8\n10A9\n10AA\n10AB\n10AC\n10AD\n10AE\n10AF\n10B0\n10B1\n10B2\n10B3\n10B4\n10B5\n10B6\n10B7\n10B8\n10B9\n10BA\n10BB\n10BC\n10BD\n10BE\n10BF\n10C0\n10C1\n10C2\n10C3\n10C4\n10C5\n10C7\n10CD\n10D0\n10D1\n10D2\n10D3\n10D4\n10D5\n10D6\n10D7\n10D8\n10D9\n10DA\n10DB\n10DC\n10DD\n10DE\n10DF\n10E0\n10E1\n10E2\n10E3\n10E4\n10E5\n10E6\n10E7\n10E8\n10E9\n10EA\n10EB\n10EC\n10ED\n10EE\n10EF\n10F0\n10F1\n10F2\n10F3\n10F4\n10F5\n10F6\n10F7\n10F8\n10F9\n10FA\n10FB\n10FC\n10FD\n10FE\n10FF\n1100\n1101\n1102\n1103\n1104\n1105\n1106\n1107\n1108\n1109\n110A\n110B\n110C\n110D\n110E\n110F\n1110\n1111\n1112\n1113\n1114\n1115\n1116\n1117\n1118\n1119\n111A\n111B\n111C\n111D\n111E\n111F\n1120\n1121\n1122\n1123\n1124\n1125\n1126\n1127\n1128\n1129\n112A\n112B\n112C\n112D\n112E\n112F\n1130\n1131\n1132\n1133\n1134\n1135\n1136\n1137\n1138\n1139\n113A\n113B\n113C\n113D\n113E\n113F\n1140\n1141\n1142\n1143\n1144\n1145\n1146\n1147\n1148\n1149\n114A\n114B\n114C\n114D\n114E\n114F\n1150\n1151\n1152\n1153\n1154\n1155\n1156\n1157\n1158\n1159\n115A\n115B\n115C\n115D\n115E\n115F\n1160\n1161\n1162\n1163\n1164\n1165\n1166\n1167\n1168\n1169\n116A\n116B\n116C\n116D\n116E\n116F\n1170\n1171\n1172\n1173\n1174\n1175\n1176\n1177\n1178\n1179\n117A\n117B\n117C\n117D\n117E\n117F\n1180\n1181\n1182\n1183\n1184\n1185\n1186\n1187\n1188\n1189\n118A\n118B\n118C\n118D\n118E\n118F\n1190\n1191\n1192\n1193\n1194\n1195\n1196\n1197\n1198\n1199\n119A\n119B\n119C\n119D\n119E\n119F\n11A0\n11A1\n11A2\n11A3\n11A4\n11A5\n11A6\n11A7\n11A8\n11A9\n11AA\n11AB\n11AC\n11AD\n11AE\n11AF\n11B0\n11B1\n11B2\n11B3\n11B4\n11B5\n11B6\n11B7\n11B8\n11B9\n11BA\n11BB\n11BC\n11BD\n11BE\n11BF\n11C0\n11C1\n11C2\n11C3\n11C4\n11C5\n11C6\n11C7\n11C8\n11C9\n11CA\n11CB\n11CC\n11CD\n11CE\n11CF\n11D0\n11D1\n11D2\n11D3\n11D4\n11D5\n11D6\n11D7\n11D8\n11D9\n11DA\n11DB\n11DC\n11DD\n11DE\n11DF\n11E0\n11E1\n11E2\n11E3\n11E4\n11E5\n11E6\n11E7\n11E8\n11E9\n11EA\n11EB\n11EC\n11ED\n11EE\n11EF\n11F0\n11F1\n11F2\n11F3\n11F4\n11F5\n11F6\n11F7\n11F8\n11F9\n11FA\n11FB\n11FC\n11FD\n11FE\n11FF\n1200\n1201\n1202\n1203\n1204\n1205\n1206\n1207\n1208\n1209\n120A\n120B\n120C\n120D\n120E\n120F\n1210\n1211\n1212\n1213\n1214\n1215\n1216\n1217\n1218\n1219\n121A\n121B\n121C\n121D\n121E\n121F\n1220\n1221\n1222\n1223\n1224\n1225\n1226\n1227\n1228\n1229\n122A\n122B\n122C\n122D\n122E\n122F\n1230\n1231\n1232\n1233\n1234\n1235\n1236\n1237\n1238\n1239\n123A\n123B\n123C\n123D\n123E\n123F\n1240\n1241\n1242\n1243\n1244\n1245\n1246\n1247\n1248\n124A\n124B\n124C\n124D\n1250\n1251\n1252\n1253\n1254\n1255\n1256\n1258\n125A\n125B\n125C\n125D\n1260\n1261\n1262\n1263\n1264\n1265\n1266\n1267\n1268\n1269\n126A\n126B\n126C\n126D\n126E\n126F\n1270\n1271\n1272\n1273\n1274\n1275\n1276\n1277\n1278\n1279\n127A\n127B\n127C\n127D\n127E\n127F\n1280\n1281\n1282\n1283\n1284\n1285\n1286\n1287\n1288\n128A\n128B\n128C\n128D\n1290\n1291\n1292\n1293\n1294\n1295\n1296\n1297\n1298\n1299\n129A\n129B\n129C\n129D\n129E\n129F\n12A0\n12A1\n12A2\n12A3\n12A4\n12A5\n12A6\n12A7\n12A8\n12A9\n12AA\n12AB\n12AC\n12AD\n12AE\n12AF\n12B0\n12B2\n12B3\n12B4\n12B5\n12B8\n12B9\n12BA\n12BB\n12BC\n12BD\n12BE\n12C0\n12C2\n12C3\n12C4\n12C5\n12C8\n12C9\n12CA\n12CB\n12CC\n12CD\n12CE\n12CF\n12D0\n12D1\n12D2\n12D3\n12D4\n12D5\n12D6\n12D8\n12D9\n12DA\n12DB\n12DC\n12DD\n12DE\n12DF\n12E0\n12E1\n12E2\n12E3\n12E4\n12E5\n12E6\n12E7\n12E8\n12E9\n12EA\n12EB\n12EC\n12ED\n12EE\n12EF\n12F0\n12F1\n12F2\n12F3\n12F4\n12F5\n12F6\n12F7\n12F8\n12F9\n12FA\n12FB\n12FC\n12FD\n12FE\n12FF\n1300\n1301\n1302\n1303\n1304\n1305\n1306\n1307\n1308\n1309\n130A\n130B\n130C\n130D\n130E\n130F\n1310\n1312\n1313\n1314\n1315\n1318\n1319\n131A\n131B\n131C\n131D\n131E\n131F\n1320\n1321\n1322\n1323\n1324\n1325\n1326\n1327\n1328\n1329\n132A\n132B\n132C\n132D\n132E\n132F\n1330\n1331\n1332\n1333\n1334\n1335\n1336\n1337\n1338\n1339\n133A\n133B\n133C\n133D\n133E\n133F\n1340\n1341\n1342\n1343\n1344\n1345\n1346\n1347\n1348\n1349\n134A\n134B\n134C\n134D\n134E\n134F\n1350\n1351\n1352\n1353\n1354\n1355\n1356\n1357\n1358\n1359\n135A\n135D\n135E\n135F\n1360\n1361\n1362\n1363\n1364\n1365\n1366\n1367\n1368\n1369\n136A\n136B\n136C\n136D\n136E\n136F\n1370\n1371\n1372\n1373\n1374\n1375\n1376\n1377\n1378\n1379\n137A\n137B\n137C\n1380\n1381\n1382\n1383\n1384\n1385\n1386\n1387\n1388\n1389\n138A\n138B\n138C\n138D\n138E\n138F\n1390\n1391\n1392\n1393\n1394\n1395\n1396\n1397\n1398\n1399\n13A0\n13A1\n13A2\n13A3\n13A4\n13A5\n13A6\n13A7\n13A8\n13A9\n13AA\n13AB\n13AC\n13AD\n13AE\n13AF\n13B0\n13B1\n13B2\n13B3\n13B4\n13B5\n13B6\n13B7\n13B8\n13B9\n13BA\n13BB\n13BC\n13BD\n13BE\n13BF\n13C0\n13C1\n13C2\n13C3\n13C4\n13C5\n13C6\n13C7\n13C8\n13C9\n13CA\n13CB\n13CC\n13CD\n13CE\n13CF\n13D0\n13D1\n13D2\n13D3\n13D4\n13D5\n13D6\n13D7\n13D8\n13D9\n13DA\n13DB\n13DC\n13DD\n13DE\n13DF\n13E0\n13E1\n13E2\n13E3\n13E4\n13E5\n13E6\n13E7\n13E8\n13E9\n13EA\n13EB\n13EC\n13ED\n13EE\n13EF\n13F0\n13F1\n13F2\n13F3\n13F4\n1400\n1401\n1402\n1403\n1404\n1405\n1406\n1407\n1408\n1409\n140A\n140B\n140C\n140D\n140E\n140F\n1410\n1411\n1412\n1413\n1414\n1415\n1416\n1417\n1418\n1419\n141A\n141B\n141C\n141D\n141E\n141F\n1420\n1421\n1422\n1423\n1424\n1425\n1426\n1427\n1428\n1429\n142A\n142B\n142C\n142D\n142E\n142F\n1430\n1431\n1432\n1433\n1434\n1435\n1436\n1437\n1438\n1439\n143A\n143B\n143C\n143D\n143E\n143F\n1440\n1441\n1442\n1443\n1444\n1445\n1446\n1447\n1448\n1449\n144A\n144B\n144C\n144D\n144E\n144F\n1450\n1451\n1452\n1453\n1454\n1455\n1456\n1457\n1458\n1459\n145A\n145B\n145C\n145D\n145E\n145F\n1460\n1461\n1462\n1463\n1464\n1465\n1466\n1467\n1468\n1469\n146A\n146B\n146C\n146D\n146E\n146F\n1470\n1471\n1472\n1473\n1474\n1475\n1476\n1477\n1478\n1479\n147A\n147B\n147C\n147D\n147E\n147F\n1480\n1481\n1482\n1483\n1484\n1485\n1486\n1487\n1488\n1489\n148A\n148B\n148C\n148D\n148E\n148F\n1490\n1491\n1492\n1493\n1494\n1495\n1496\n1497\n1498\n1499\n149A\n149B\n149C\n149D\n149E\n149F\n14A0\n14A1\n14A2\n14A3\n14A4\n14A5\n14A6\n14A7\n14A8\n14A9\n14AA\n14AB\n14AC\n14AD\n14AE\n14AF\n14B0\n14B1\n14B2\n14B3\n14B4\n14B5\n14B6\n14B7\n14B8\n14B9\n14BA\n14BB\n14BC\n14BD\n14BE\n14BF\n14C0\n14C1\n14C2\n14C3\n14C4\n14C5\n14C6\n14C7\n14C8\n14C9\n14CA\n14CB\n14CC\n14CD\n14CE\n14CF\n14D0\n14D1\n14D2\n14D3\n14D4\n14D5\n14D6\n14D7\n14D8\n14D9\n14DA\n14DB\n14DC\n14DD\n14DE\n14DF\n14E0\n14E1\n14E2\n14E3\n14E4\n14E5\n14E6\n14E7\n14E8\n14E9\n14EA\n14EB\n14EC\n14ED\n14EE\n14EF\n14F0\n14F1\n14F2\n14F3\n14F4\n14F5\n14F6\n14F7\n14F8\n14F9\n14FA\n14FB\n14FC\n14FD\n14FE\n14FF\n1500\n1501\n1502\n1503\n1504\n1505\n1506\n1507\n1508\n1509\n150A\n150B\n150C\n150D\n150E\n150F\n1510\n1511\n1512\n1513\n1514\n1515\n1516\n1517\n1518\n1519\n151A\n151B\n151C\n151D\n151E\n151F\n1520\n1521\n1522\n1523\n1524\n1525\n1526\n1527\n1528\n1529\n152A\n152B\n152C\n152D\n152E\n152F\n1530\n1531\n1532\n1533\n1534\n1535\n1536\n1537\n1538\n1539\n153A\n153B\n153C\n153D\n153E\n153F\n1540\n1541\n1542\n1543\n1544\n1545\n1546\n1547\n1548\n1549\n154A\n154B\n154C\n154D\n154E\n154F\n1550\n1551\n1552\n1553\n1554\n1555\n1556\n1557\n1558\n1559\n155A\n155B\n155C\n155D\n155E\n155F\n1560\n1561\n1562\n1563\n1564\n1565\n1566\n1567\n1568\n1569\n156A\n156B\n156C\n156D\n156E\n156F\n1570\n1571\n1572\n1573\n1574\n1575\n1576\n1577\n1578\n1579\n157A\n157B\n157C\n157D\n157E\n157F\n1580\n1581\n1582\n1583\n1584\n1585\n1586\n1587\n1588\n1589\n158A\n158B\n158C\n158D\n158E\n158F\n1590\n1591\n1592\n1593\n1594\n1595\n1596\n1597\n1598\n1599\n159A\n159B\n159C\n159D\n159E\n159F\n15A0\n15A1\n15A2\n15A3\n15A4\n15A5\n15A6\n15A7\n15A8\n15A9\n15AA\n15AB\n15AC\n15AD\n15AE\n15AF\n15B0\n15B1\n15B2\n15B3\n15B4\n15B5\n15B6\n15B7\n15B8\n15B9\n15BA\n15BB\n15BC\n15BD\n15BE\n15BF\n15C0\n15C1\n15C2\n15C3\n15C4\n15C5\n15C6\n15C7\n15C8\n15C9\n15CA\n15CB\n15CC\n15CD\n15CE\n15CF\n15D0\n15D1\n15D2\n15D3\n15D4\n15D5\n15D6\n15D7\n15D8\n15D9\n15DA\n15DB\n15DC\n15DD\n15DE\n15DF\n15E0\n15E1\n15E2\n15E3\n15E4\n15E5\n15E6\n15E7\n15E8\n15E9\n15EA\n15EB\n15EC\n15ED\n15EE\n15EF\n15F0\n15F1\n15F2\n15F3\n15F4\n15F5\n15F6\n15F7\n15F8\n15F9\n15FA\n15FB\n15FC\n15FD\n15FE\n15FF\n1600\n1601\n1602\n1603\n1604\n1605\n1606\n1607\n1608\n1609\n160A\n160B\n160C\n160D\n160E\n160F\n1610\n1611\n1612\n1613\n1614\n1615\n1616\n1617\n1618\n1619\n161A\n161B\n161C\n161D\n161E\n161F\n1620\n1621\n1622\n1623\n1624\n1625\n1626\n1627\n1628\n1629\n162A\n162B\n162C\n162D\n162E\n162F\n1630\n1631\n1632\n1633\n1634\n1635\n1636\n1637\n1638\n1639\n163A\n163B\n163C\n163D\n163E\n163F\n1640\n1641\n1642\n1643\n1644\n1645\n1646\n1647\n1648\n1649\n164A\n164B\n164C\n164D\n164E\n164F\n1650\n1651\n1652\n1653\n1654\n1655\n1656\n1657\n1658\n1659\n165A\n165B\n165C\n165D\n165E\n165F\n1660\n1661\n1662\n1663\n1664\n1665\n1666\n1667\n1668\n1669\n166A\n166B\n166C\n166D\n166E\n166F\n1670\n1671\n1672\n1673\n1674\n1675\n1676\n1677\n1678\n1679\n167A\n167B\n167C\n167D\n167E\n167F\n1680\n1681\n1682\n1683\n1684\n1685\n1686\n1687\n1688\n1689\n168A\n168B\n168C\n168D\n168E\n168F\n1690\n1691\n1692\n1693\n1694\n1695\n1696\n1697\n1698\n1699\n169A\n169B\n169C\n16A0\n16A1\n16A2\n16A3\n16A4\n16A5\n16A6\n16A7\n16A8\n16A9\n16AA\n16AB\n16AC\n16AD\n16AE\n16AF\n16B0\n16B1\n16B2\n16B3\n16B4\n16B5\n16B6\n16B7\n16B8\n16B9\n16BA\n16BB\n16BC\n16BD\n16BE\n16BF\n16C0\n16C1\n16C2\n16C3\n16C4\n16C5\n16C6\n16C7\n16C8\n16C9\n16CA\n16CB\n16CC\n16CD\n16CE\n16CF\n16D0\n16D1\n16D2\n16D3\n16D4\n16D5\n16D6\n16D7\n16D8\n16D9\n16DA\n16DB\n16DC\n16DD\n16DE\n16DF\n16E0\n16E1\n16E2\n16E3\n16E4\n16E5\n16E6\n16E7\n16E8\n16E9\n16EA\n16EB\n16EC\n16ED\n16EE\n16EF\n16F0\n16F1\n16F2\n16F3\n16F4\n16F5\n16F6\n16F7\n16F8\n1700\n1701\n1702\n1703\n1704\n1705\n1706\n1707\n1708\n1709\n170A\n170B\n170C\n170E\n170F\n1710\n1711\n1712\n1713\n1714\n1720\n1721\n1722\n1723\n1724\n1725\n1726\n1727\n1728\n1729\n172A\n172B\n172C\n172D\n172E\n172F\n1730\n1731\n1732\n1733\n1734\n1735\n1736\n1740\n1741\n1742\n1743\n1744\n1745\n1746\n1747\n1748\n1749\n174A\n174B\n174C\n174D\n174E\n174F\n1750\n1751\n1752\n1753\n1760\n1761\n1762\n1763\n1764\n1765\n1766\n1767\n1768\n1769\n176A\n176B\n176C\n176E\n176F\n1770\n1772\n1773\n1780\n1781\n1782\n1783\n1784\n1785\n1786\n1787\n1788\n1789\n178A\n178B\n178C\n178D\n178E\n178F\n1790\n1791\n1792\n1793\n1794\n1795\n1796\n1797\n1798\n1799\n179A\n179B\n179C\n179D\n179E\n179F\n17A0\n17A1\n17A2\n17A3\n17A4\n17A5\n17A6\n17A7\n17A8\n17A9\n17AA\n17AB\n17AC\n17AD\n17AE\n17AF\n17B0\n17B1\n17B2\n17B3\n17B4\n17B5\n17B6\n17B7\n17B8\n17B9\n17BA\n17BB\n17BC\n17BD\n17BE\n17BF\n17C0\n17C1\n17C2\n17C3\n17C4\n17C5\n17C6\n17C7\n17C8\n17C9\n17CA\n17CB\n17CC\n17CD\n17CE\n17CF\n17D0\n17D1\n17D2\n17D3\n17D4\n17D5\n17D6\n17D7\n17D8\n17D9\n17DA\n17DB\n17DC\n17DD\n17E0\n17E1\n17E2\n17E3\n17E4\n17E5\n17E6\n17E7\n17E8\n17E9\n17F0\n17F1\n17F2\n17F3\n17F4\n17F5\n17F6\n17F7\n17F8\n17F9\n1800\n1801\n1802\n1803\n1804\n1805\n1806\n1807\n1808\n1809\n180A\n180B\n180C\n180D\n180E\n1810\n1811\n1812\n1813\n1814\n1815\n1816\n1817\n1818\n1819\n1820\n1821\n1822\n1823\n1824\n1825\n1826\n1827\n1828\n1829\n182A\n182B\n182C\n182D\n182E\n182F\n1830\n1831\n1832\n1833\n1834\n1835\n1836\n1837\n1838\n1839\n183A\n183B\n183C\n183D\n183E\n183F\n1840\n1841\n1842\n1843\n1844\n1845\n1846\n1847\n1848\n1849\n184A\n184B\n184C\n184D\n184E\n184F\n1850\n1851\n1852\n1853\n1854\n1855\n1856\n1857\n1858\n1859\n185A\n185B\n185C\n185D\n185E\n185F\n1860\n1861\n1862\n1863\n1864\n1865\n1866\n1867\n1868\n1869\n186A\n186B\n186C\n186D\n186E\n186F\n1870\n1871\n1872\n1873\n1874\n1875\n1876\n1877\n1880\n1881\n1882\n1883\n1884\n1885\n1886\n1887\n1888\n1889\n188A\n188B\n188C\n188D\n188E\n188F\n1890\n1891\n1892\n1893\n1894\n1895\n1896\n1897\n1898\n1899\n189A\n189B\n189C\n189D\n189E\n189F\n18A0\n18A1\n18A2\n18A3\n18A4\n18A5\n18A6\n18A7\n18A8\n18A9\n18AA\n18B0\n18B1\n18B2\n18B3\n18B4\n18B5\n18B6\n18B7\n18B8\n18B9\n18BA\n18BB\n18BC\n18BD\n18BE\n18BF\n18C0\n18C1\n18C2\n18C3\n18C4\n18C5\n18C6\n18C7\n18C8\n18C9\n18CA\n18CB\n18CC\n18CD\n18CE\n18CF\n18D0\n18D1\n18D2\n18D3\n18D4\n18D5\n18D6\n18D7\n18D8\n18D9\n18DA\n18DB\n18DC\n18DD\n18DE\n18DF\n18E0\n18E1\n18E2\n18E3\n18E4\n18E5\n18E6\n18E7\n18E8\n18E9\n18EA\n18EB\n18EC\n18ED\n18EE\n18EF\n18F0\n18F1\n18F2\n18F3\n18F4\n18F5\n1900\n1901\n1902\n1903\n1904\n1905\n1906\n1907\n1908\n1909\n190A\n190B\n190C\n190D\n190E\n190F\n1910\n1911\n1912\n1913\n1914\n1915\n1916\n1917\n1918\n1919\n191A\n191B\n191C\n191D\n191E\n1920\n1921\n1922\n1923\n1924\n1925\n1926\n1927\n1928\n1929\n192A\n192B\n1930\n1931\n1932\n1933\n1934\n1935\n1936\n1937\n1938\n1939\n193A\n193B\n1940\n1944\n1945\n1946\n1947\n1948\n1949\n194A\n194B\n194C\n194D\n194E\n194F\n1950\n1951\n1952\n1953\n1954\n1955\n1956\n1957\n1958\n1959\n195A\n195B\n195C\n195D\n195E\n195F\n1960\n1961\n1962\n1963\n1964\n1965\n1966\n1967\n1968\n1969\n196A\n196B\n196C\n196D\n1970\n1971\n1972\n1973\n1974\n1980\n1981\n1982\n1983\n1984\n1985\n1986\n1987\n1988\n1989\n198A\n198B\n198C\n198D\n198E\n198F\n1990\n1991\n1992\n1993\n1994\n1995\n1996\n1997\n1998\n1999\n199A\n199B\n199C\n199D\n199E\n199F\n19A0\n19A1\n19A2\n19A3\n19A4\n19A5\n19A6\n19A7\n19A8\n19A9\n19AA\n19AB\n19B0\n19B1\n19B2\n19B3\n19B4\n19B5\n19B6\n19B7\n19B8\n19B9\n19BA\n19BB\n19BC\n19BD\n19BE\n19BF\n19C0\n19C1\n19C2\n19C3\n19C4\n19C5\n19C6\n19C7\n19C8\n19C9\n19D0\n19D1\n19D2\n19D3\n19D4\n19D5\n19D6\n19D7\n19D8\n19D9\n19DA\n19DE\n19DF\n19E0\n19E1\n19E2\n19E3\n19E4\n19E5\n19E6\n19E7\n19E8\n19E9\n19EA\n19EB\n19EC\n19ED\n19EE\n19EF\n19F0\n19F1\n19F2\n19F3\n19F4\n19F5\n19F6\n19F7\n19F8\n19F9\n19FA\n19FB\n19FC\n19FD\n19FE\n19FF\n1A00\n1A01\n1A02\n1A03\n1A04\n1A05\n1A06\n1A07\n1A08\n1A09\n1A0A\n1A0B\n1A0C\n1A0D\n1A0E\n1A0F\n1A10\n1A11\n1A12\n1A13\n1A14\n1A15\n1A16\n1A17\n1A18\n1A19\n1A1A\n1A1B\n1A1E\n1A1F\n1A20\n1A21\n1A22\n1A23\n1A24\n1A25\n1A26\n1A27\n1A28\n1A29\n1A2A\n1A2B\n1A2C\n1A2D\n1A2E\n1A2F\n1A30\n1A31\n1A32\n1A33\n1A34\n1A35\n1A36\n1A37\n1A38\n1A39\n1A3A\n1A3B\n1A3C\n1A3D\n1A3E\n1A3F\n1A40\n1A41\n1A42\n1A43\n1A44\n1A45\n1A46\n1A47\n1A48\n1A49\n1A4A\n1A4B\n1A4C\n1A4D\n1A4E\n1A4F\n1A50\n1A51\n1A52\n1A53\n1A54\n1A55\n1A56\n1A57\n1A58\n1A59\n1A5A\n1A5B\n1A5C\n1A5D\n1A5E\n1A60\n1A61\n1A62\n1A63\n1A64\n1A65\n1A66\n1A67\n1A68\n1A69\n1A6A\n1A6B\n1A6C\n1A6D\n1A6E\n1A6F\n1A70\n1A71\n1A72\n1A73\n1A74\n1A75\n1A76\n1A77\n1A78\n1A79\n1A7A\n1A7B\n1A7C\n1A7F\n1A80\n1A81\n1A82\n1A83\n1A84\n1A85\n1A86\n1A87\n1A88\n1A89\n1A90\n1A91\n1A92\n1A93\n1A94\n1A95\n1A96\n1A97\n1A98\n1A99\n1AA0\n1AA1\n1AA2\n1AA3\n1AA4\n1AA5\n1AA6\n1AA7\n1AA8\n1AA9\n1AAA\n1AAB\n1AAC\n1AAD\n1AB0\n1AB1\n1AB2\n1AB3\n1AB4\n1AB5\n1AB6\n1AB7\n1AB8\n1AB9\n1ABA\n1ABB\n1ABC\n1ABD\n1ABE\n1B00\n1B01\n1B02\n1B03\n1B04\n1B05\n1B06\n1B07\n1B08\n1B09\n1B0A\n1B0B\n1B0C\n1B0D\n1B0E\n1B0F\n1B10\n1B11\n1B12\n1B13\n1B14\n1B15\n1B16\n1B17\n1B18\n1B19\n1B1A\n1B1B\n1B1C\n1B1D\n1B1E\n1B1F\n1B20\n1B21\n1B22\n1B23\n1B24\n1B25\n1B26\n1B27\n1B28\n1B29\n1B2A\n1B2B\n1B2C\n1B2D\n1B2E\n1B2F\n1B30\n1B31\n1B32\n1B33\n1B34\n1B35\n1B36\n1B37\n1B38\n1B39\n1B3A\n1B3B\n1B3C\n1B3D\n1B3E\n1B3F\n1B40\n1B41\n1B42\n1B43\n1B44\n1B45\n1B46\n1B47\n1B48\n1B49\n1B4A\n1B4B\n1B50\n1B51\n1B52\n1B53\n1B54\n1B55\n1B56\n1B57\n1B58\n1B59\n1B5A\n1B5B\n1B5C\n1B5D\n1B5E\n1B5F\n1B60\n1B61\n1B62\n1B63\n1B64\n1B65\n1B66\n1B67\n1B68\n1B69\n1B6A\n1B6B\n1B6C\n1B6D\n1B6E\n1B6F\n1B70\n1B71\n1B72\n1B73\n1B74\n1B75\n1B76\n1B77\n1B78\n1B79\n1B7A\n1B7B\n1B7C\n1B80\n1B81\n1B82\n1B83\n1B84\n1B85\n1B86\n1B87\n1B88\n1B89\n1B8A\n1B8B\n1B8C\n1B8D\n1B8E\n1B8F\n1B90\n1B91\n1B92\n1B93\n1B94\n1B95\n1B96\n1B97\n1B98\n1B99\n1B9A\n1B9B\n1B9C\n1B9D\n1B9E\n1B9F\n1BA0\n1BA1\n1BA2\n1BA3\n1BA4\n1BA5\n1BA6\n1BA7\n1BA8\n1BA9\n1BAA\n1BAB\n1BAC\n1BAD\n1BAE\n1BAF\n1BB0\n1BB1\n1BB2\n1BB3\n1BB4\n1BB5\n1BB6\n1BB7\n1BB8\n1BB9\n1BBA\n1BBB\n1BBC\n1BBD\n1BBE\n1BBF\n1BC0\n1BC1\n1BC2\n1BC3\n1BC4\n1BC5\n1BC6\n1BC7\n1BC8\n1BC9\n1BCA\n1BCB\n1BCC\n1BCD\n1BCE\n1BCF\n1BD0\n1BD1\n1BD2\n1BD3\n1BD4\n1BD5\n1BD6\n1BD7\n1BD8\n1BD9\n1BDA\n1BDB\n1BDC\n1BDD\n1BDE\n1BDF\n1BE0\n1BE1\n1BE2\n1BE3\n1BE4\n1BE5\n1BE6\n1BE7\n1BE8\n1BE9\n1BEA\n1BEB\n1BEC\n1BED\n1BEE\n1BEF\n1BF0\n1BF1\n1BF2\n1BF3\n1BFC\n1BFD\n1BFE\n1BFF\n1C00\n1C01\n1C02\n1C03\n1C04\n1C05\n1C06\n1C07\n1C08\n1C09\n1C0A\n1C0B\n1C0C\n1C0D\n1C0E\n1C0F\n1C10\n1C11\n1C12\n1C13\n1C14\n1C15\n1C16\n1C17\n1C18\n1C19\n1C1A\n1C1B\n1C1C\n1C1D\n1C1E\n1C1F\n1C20\n1C21\n1C22\n1C23\n1C24\n1C25\n1C26\n1C27\n1C28\n1C29\n1C2A\n1C2B\n1C2C\n1C2D\n1C2E\n1C2F\n1C30\n1C31\n1C32\n1C33\n1C34\n1C35\n1C36\n1C37\n1C3B\n1C3C\n1C3D\n1C3E\n1C3F\n1C40\n1C41\n1C42\n1C43\n1C44\n1C45\n1C46\n1C47\n1C48\n1C49\n1C4D\n1C4E\n1C4F\n1C50\n1C51\n1C52\n1C53\n1C54\n1C55\n1C56\n1C57\n1C58\n1C59\n1C5A\n1C5B\n1C5C\n1C5D\n1C5E\n1C5F\n1C60\n1C61\n1C62\n1C63\n1C64\n1C65\n1C66\n1C67\n1C68\n1C69\n1C6A\n1C6B\n1C6C\n1C6D\n1C6E\n1C6F\n1C70\n1C71\n1C72\n1C73\n1C74\n1C75\n1C76\n1C77\n1C78\n1C79\n1C7A\n1C7B\n1C7C\n1C7D\n1C7E\n1C7F\n1CC0\n1CC1\n1CC2\n1CC3\n1CC4\n1CC5\n1CC6\n1CC7\n1CD0\n1CD1\n1CD2\n1CD3\n1CD4\n1CD5\n1CD6\n1CD7\n1CD8\n1CD9\n1CDA\n1CDB\n1CDC\n1CDD\n1CDE\n1CDF\n1CE0\n1CE1\n1CE2\n1CE3\n1CE4\n1CE5\n1CE6\n1CE7\n1CE8\n1CE9\n1CEA\n1CEB\n1CEC\n1CED\n1CEE\n1CEF\n1CF0\n1CF1\n1CF2\n1CF3\n1CF4\n1CF5\n1CF6\n1CF8\n1CF9\n1D00\n1D01\n1D02\n1D03\n1D04\n1D05\n1D06\n1D07\n1D08\n1D09\n1D0A\n1D0B\n1D0C\n1D0D\n1D0E\n1D0F\n1D10\n1D11\n1D12\n1D13\n1D14\n1D15\n1D16\n1D17\n1D18\n1D19\n1D1A\n1D1B\n1D1C\n1D1D\n1D1E\n1D1F\n1D20\n1D21\n1D22\n1D23\n1D24\n1D25\n1D26\n1D27\n1D28\n1D29\n1D2A\n1D2B\n1D2C\n1D2D\n1D2E\n1D2F\n1D30\n1D31\n1D32\n1D33\n1D34\n1D35\n1D36\n1D37\n1D38\n1D39\n1D3A\n1D3B\n1D3C\n1D3D\n1D3E\n1D3F\n1D40\n1D41\n1D42\n1D43\n1D44\n1D45\n1D46\n1D47\n1D48\n1D49\n1D4A\n1D4B\n1D4C\n1D4D\n1D4E\n1D4F\n1D50\n1D51\n1D52\n1D53\n1D54\n1D55\n1D56\n1D57\n1D58\n1D59\n1D5A\n1D5B\n1D5C\n1D5D\n1D5E\n1D5F\n1D60\n1D61\n1D62\n1D63\n1D64\n1D65\n1D66\n1D67\n1D68\n1D69\n1D6A\n1D6B\n1D6C\n1D6D\n1D6E\n1D6F\n1D70\n1D71\n1D72\n1D73\n1D74\n1D75\n1D76\n1D77\n1D78\n1D79\n1D7A\n1D7B\n1D7C\n1D7D\n1D7E\n1D7F\n1D80\n1D81\n1D82\n1D83\n1D84\n1D85\n1D86\n1D87\n1D88\n1D89\n1D8A\n1D8B\n1D8C\n1D8D\n1D8E\n1D8F\n1D90\n1D91\n1D92\n1D93\n1D94\n1D95\n1D96\n1D97\n1D98\n1D99\n1D9A\n1D9B\n1D9C\n1D9D\n1D9E\n1D9F\n1DA0\n1DA1\n1DA2\n1DA3\n1DA4\n1DA5\n1DA6\n1DA7\n1DA8\n1DA9\n1DAA\n1DAB\n1DAC\n1DAD\n1DAE\n1DAF\n1DB0\n1DB1\n1DB2\n1DB3\n1DB4\n1DB5\n1DB6\n1DB7\n1DB8\n1DB9\n1DBA\n1DBB\n1DBC\n1DBD\n1DBE\n1DBF\n1DC0\n1DC1\n1DC2\n1DC3\n1DC4\n1DC5\n1DC6\n1DC7\n1DC8\n1DC9\n1DCA\n1DCB\n1DCC\n1DCD\n1DCE\n1DCF\n1DD0\n1DD1\n1DD2\n1DD3\n1DD4\n1DD5\n1DD6\n1DD7\n1DD8\n1DD9\n1DDA\n1DDB\n1DDC\n1DDD\n1DDE\n1DDF\n1DE0\n1DE1\n1DE2\n1DE3\n1DE4\n1DE5\n1DE6\n1DE7\n1DE8\n1DE9\n1DEA\n1DEB\n1DEC\n1DED\n1DEE\n1DEF\n1DF0\n1DF1\n1DF2\n1DF3\n1DF4\n1DF5\n1DFC\n1DFD\n1DFE\n1DFF\n1E00\n1E01\n1E02\n1E03\n1E04\n1E05\n1E06\n1E07\n1E08\n1E09\n1E0A\n1E0B\n1E0C\n1E0D\n1E0E\n1E0F\n1E10\n1E11\n1E12\n1E13\n1E14\n1E15\n1E16\n1E17\n1E18\n1E19\n1E1A\n1E1B\n1E1C\n1E1D\n1E1E\n1E1F\n1E20\n1E21\n1E22\n1E23\n1E24\n1E25\n1E26\n1E27\n1E28\n1E29\n1E2A\n1E2B\n1E2C\n1E2D\n1E2E\n1E2F\n1E30\n1E31\n1E32\n1E33\n1E34\n1E35\n1E36\n1E37\n1E38\n1E39\n1E3A\n1E3B\n1E3C\n1E3D\n1E3E\n1E3F\n1E40\n1E41\n1E42\n1E43\n1E44\n1E45\n1E46\n1E47\n1E48\n1E49\n1E4A\n1E4B\n1E4C\n1E4D\n1E4E\n1E4F\n1E50\n1E51\n1E52\n1E53\n1E54\n1E55\n1E56\n1E57\n1E58\n1E59\n1E5A\n1E5B\n1E5C\n1E5D\n1E5E\n1E5F\n1E60\n1E61\n1E62\n1E63\n1E64\n1E65\n1E66\n1E67\n1E68\n1E69\n1E6A\n1E6B\n1E6C\n1E6D\n1E6E\n1E6F\n1E70\n1E71\n1E72\n1E73\n1E74\n1E75\n1E76\n1E77\n1E78\n1E79\n1E7A\n1E7B\n1E7C\n1E7D\n1E7E\n1E7F\n1E80\n1E81\n1E82\n1E83\n1E84\n1E85\n1E86\n1E87\n1E88\n1E89\n1E8A\n1E8B\n1E8C\n1E8D\n1E8E\n1E8F\n1E90\n1E91\n1E92\n1E93\n1E94\n1E95\n1E96\n1E97\n1E98\n1E99\n1E9A\n1E9B\n1E9C\n1E9D\n1E9E\n1E9F\n1EA0\n1EA1\n1EA2\n1EA3\n1EA4\n1EA5\n1EA6\n1EA7\n1EA8\n1EA9\n1EAA\n1EAB\n1EAC\n1EAD\n1EAE\n1EAF\n1EB0\n1EB1\n1EB2\n1EB3\n1EB4\n1EB5\n1EB6\n1EB7\n1EB8\n1EB9\n1EBA\n1EBB\n1EBC\n1EBD\n1EBE\n1EBF\n1EC0\n1EC1\n1EC2\n1EC3\n1EC4\n1EC5\n1EC6\n1EC7\n1EC8\n1EC9\n1ECA\n1ECB\n1ECC\n1ECD\n1ECE\n1ECF\n1ED0\n1ED1\n1ED2\n1ED3\n1ED4\n1ED5\n1ED6\n1ED7\n1ED8\n1ED9\n1EDA\n1EDB\n1EDC\n1EDD\n1EDE\n1EDF\n1EE0\n1EE1\n1EE2\n1EE3\n1EE4\n1EE5\n1EE6\n1EE7\n1EE8\n1EE9\n1EEA\n1EEB\n1EEC\n1EED\n1EEE\n1EEF\n1EF0\n1EF1\n1EF2\n1EF3\n1EF4\n1EF5\n1EF6\n1EF7\n1EF8\n1EF9\n1EFA\n1EFB\n1EFC\n1EFD\n1EFE\n1EFF\n1F00\n1F01\n1F02\n1F03\n1F04\n1F05\n1F06\n1F07\n1F08\n1F09\n1F0A\n1F0B\n1F0C\n1F0D\n1F0E\n1F0F\n1F10\n1F11\n1F12\n1F13\n1F14\n1F15\n1F18\n1F19\n1F1A\n1F1B\n1F1C\n1F1D\n1F20\n1F21\n1F22\n1F23\n1F24\n1F25\n1F26\n1F27\n1F28\n1F29\n1F2A\n1F2B\n1F2C\n1F2D\n1F2E\n1F2F\n1F30\n1F31\n1F32\n1F33\n1F34\n1F35\n1F36\n1F37\n1F38\n1F39\n1F3A\n1F3B\n1F3C\n1F3D\n1F3E\n1F3F\n1F40\n1F41\n1F42\n1F43\n1F44\n1F45\n1F48\n1F49\n1F4A\n1F4B\n1F4C\n1F4D\n1F50\n1F51\n1F52\n1F53\n1F54\n1F55\n1F56\n1F57\n1F59\n1F5B\n1F5D\n1F5F\n1F60\n1F61\n1F62\n1F63\n1F64\n1F65\n1F66\n1F67\n1F68\n1F69\n1F6A\n1F6B\n1F6C\n1F6D\n1F6E\n1F6F\n1F70\n1F71\n1F72\n1F73\n1F74\n1F75\n1F76\n1F77\n1F78\n1F79\n1F7A\n1F7B\n1F7C\n1F7D\n1F80\n1F81\n1F82\n1F83\n1F84\n1F85\n1F86\n1F87\n1F88\n1F89\n1F8A\n1F8B\n1F8C\n1F8D\n1F8E\n1F8F\n1F90\n1F91\n1F92\n1F93\n1F94\n1F95\n1F96\n1F97\n1F98\n1F99\n1F9A\n1F9B\n1F9C\n1F9D\n1F9E\n1F9F\n1FA0\n1FA1\n1FA2\n1FA3\n1FA4\n1FA5\n1FA6\n1FA7\n1FA8\n1FA9\n1FAA\n1FAB\n1FAC\n1FAD\n1FAE\n1FAF\n1FB0\n1FB1\n1FB2\n1FB3\n1FB4\n1FB6\n1FB7\n1FB8\n1FB9\n1FBA\n1FBB\n1FBC\n1FBD\n1FBE\n1FBF\n1FC0\n1FC1\n1FC2\n1FC3\n1FC4\n1FC6\n1FC7\n1FC8\n1FC9\n1FCA\n1FCB\n1FCC\n1FCD\n1FCE\n1FCF\n1FD0\n1FD1\n1FD2\n1FD3\n1FD6\n1FD7\n1FD8\n1FD9\n1FDA\n1FDB\n1FDD\n1FDE\n1FDF\n1FE0\n1FE1\n1FE2\n1FE3\n1FE4\n1FE5\n1FE6\n1FE7\n1FE8\n1FE9\n1FEA\n1FEB\n1FEC\n1FED\n1FEE\n1FEF\n1FF2\n1FF3\n1FF4\n1FF6\n1FF7\n1FF8\n1FF9\n1FFA\n1FFB\n1FFC\n1FFD\n1FFE\n2000\n2001\n2002\n2003\n2004\n2005\n2006\n2007\n2008\n2009\n200A\n200B\n200C\n200D\n200E\n200F\n2010\n2011\n2012\n2013\n2014\n2015\n2016\n2017\n2018\n2019\n201A\n201B\n201C\n201D\n201E\n201F\n2020\n2021\n2022\n2023\n2024\n2025\n2026\n2027\n2028\n2029\n202A\n202B\n202C\n202D\n202E\n202F\n2030\n2031\n2032\n2033\n2034\n2035\n2036\n2037\n2038\n2039\n203A\n203B\n203C\n203D\n203E\n203F\n2040\n2041\n2042\n2043\n2044\n2045\n2046\n2047\n2048\n2049\n204A\n204B\n204C\n204D\n204E\n204F\n2050\n2051\n2052\n2053\n2054\n2055\n2056\n2057\n2058\n2059\n205A\n205B\n205C\n205D\n205E\n205F\n2060\n2061\n2062\n2063\n2064\n2066\n2067\n2068\n2069\n206A\n206B\n206C\n206D\n206E\n206F\n2070\n2071\n2074\n2075\n2076\n2077\n2078\n2079\n207A\n207B\n207C\n207D\n207E\n207F\n2080\n2081\n2082\n2083\n2084\n2085\n2086\n2087\n2088\n2089\n208A\n208B\n208C\n208D\n208E\n2090\n2091\n2092\n2093\n2094\n2095\n2096\n2097\n2098\n2099\n209A\n209B\n209C\n20A0\n20A1\n20A2\n20A3\n20A4\n20A5\n20A6\n20A7\n20A8\n20A9\n20AA\n20AB\n20AC\n20AD\n20AE\n20AF\n20B0\n20B1\n20B2\n20B3\n20B4\n20B5\n20B6\n20B7\n20B8\n20B9\n20BA\n20BB\n20BC\n20BD\n20D0\n20D1\n20D2\n20D3\n20D4\n20D5\n20D6\n20D7\n20D8\n20D9\n20DA\n20DB\n20DC\n20DD\n20DE\n20DF\n20E0\n20E1\n20E2\n20E3\n20E4\n20E5\n20E6\n20E7\n20E8\n20E9\n20EA\n20EB\n20EC\n20ED\n20EE\n20EF\n20F0\n2100\n2101\n2102\n2103\n2104\n2105\n2106\n2107\n2108\n2109\n210A\n210B\n210C\n210D\n210E\n210F\n2110\n2111\n2112\n2113\n2114\n2115\n2116\n2117\n2118\n2119\n211A\n211B\n211C\n211D\n211E\n211F\n2120\n2121\n2122\n2123\n2124\n2125\n2126\n2127\n2128\n2129\n212A\n212B\n212C\n212D\n212E\n212F\n2130\n2131\n2132\n2133\n2134\n2135\n2136\n2137\n2138\n2139\n213A\n213B\n213C\n213D\n213E\n213F\n2140\n2141\n2142\n2143\n2144\n2145\n2146\n2147\n2148\n2149\n214A\n214B\n214C\n214D\n214E\n214F\n2150\n2151\n2152\n2153\n2154\n2155\n2156\n2157\n2158\n2159\n215A\n215B\n215C\n215D\n215E\n215F\n2160\n2161\n2162\n2163\n2164\n2165\n2166\n2167\n2168\n2169\n216A\n216B\n216C\n216D\n216E\n216F\n2170\n2171\n2172\n2173\n2174\n2175\n2176\n2177\n2178\n2179\n217A\n217B\n217C\n217D\n217E\n217F\n2180\n2181\n2182\n2183\n2184\n2185\n2186\n2187\n2188\n2189\n2190\n2191\n2192\n2193\n2194\n2195\n2196\n2197\n2198\n2199\n219A\n219B\n219C\n219D\n219E\n219F\n21A0\n21A1\n21A2\n21A3\n21A4\n21A5\n21A6\n21A7\n21A8\n21A9\n21AA\n21AB\n21AC\n21AD\n21AE\n21AF\n21B0\n21B1\n21B2\n21B3\n21B4\n21B5\n21B6\n21B7\n21B8\n21B9\n21BA\n21BB\n21BC\n21BD\n21BE\n21BF\n21C0\n21C1\n21C2\n21C3\n21C4\n21C5\n21C6\n21C7\n21C8\n21C9\n21CA\n21CB\n21CC\n21CD\n21CE\n21CF\n21D0\n21D1\n21D2\n21D3\n21D4\n21D5\n21D6\n21D7\n21D8\n21D9\n21DA\n21DB\n21DC\n21DD\n21DE\n21DF\n21E0\n21E1\n21E2\n21E3\n21E4\n21E5\n21E6\n21E7\n21E8\n21E9\n21EA\n21EB\n21EC\n21ED\n21EE\n21EF\n21F0\n21F1\n21F2\n21F3\n21F4\n21F5\n21F6\n21F7\n21F8\n21F9\n21FA\n21FB\n21FC\n21FD\n21FE\n21FF\n2200\n2201\n2202\n2203\n2204\n2205\n2206\n2207\n2208\n2209\n220A\n220B\n220C\n220D\n220E\n220F\n2210\n2211\n2212\n2213\n2214\n2215\n2216\n2217\n2218\n2219\n221A\n221B\n221C\n221D\n221E\n221F\n2220\n2221\n2222\n2223\n2224\n2225\n2226\n2227\n2228\n2229\n222A\n222B\n222C\n222D\n222E\n222F\n2230\n2231\n2232\n2233\n2234\n2235\n2236\n2237\n2238\n2239\n223A\n223B\n223C\n223D\n223E\n223F\n2240\n2241\n2242\n2243\n2244\n2245\n2246\n2247\n2248\n2249\n224A\n224B\n224C\n224D\n224E\n224F\n2250\n2251\n2252\n2253\n2254\n2255\n2256\n2257\n2258\n2259\n225A\n225B\n225C\n225D\n225E\n225F\n2260\n2261\n2262\n2263\n2264\n2265\n2266\n2267\n2268\n2269\n226A\n226B\n226C\n226D\n226E\n226F\n2270\n2271\n2272\n2273\n2274\n2275\n2276\n2277\n2278\n2279\n227A\n227B\n227C\n227D\n227E\n227F\n2280\n2281\n2282\n2283\n2284\n2285\n2286\n2287\n2288\n2289\n228A\n228B\n228C\n228D\n228E\n228F\n2290\n2291\n2292\n2293\n2294\n2295\n2296\n2297\n2298\n2299\n229A\n229B\n229C\n229D\n229E\n229F\n22A0\n22A1\n22A2\n22A3\n22A4\n22A5\n22A6\n22A7\n22A8\n22A9\n22AA\n22AB\n22AC\n22AD\n22AE\n22AF\n22B0\n22B1\n22B2\n22B3\n22B4\n22B5\n22B6\n22B7\n22B8\n22B9\n22BA\n22BB\n22BC\n22BD\n22BE\n22BF\n22C0\n22C1\n22C2\n22C3\n22C4\n22C5\n22C6\n22C7\n22C8\n22C9\n22CA\n22CB\n22CC\n22CD\n22CE\n22CF\n22D0\n22D1\n22D2\n22D3\n22D4\n22D5\n22D6\n22D7\n22D8\n22D9\n22DA\n22DB\n22DC\n22DD\n22DE\n22DF\n22E0\n22E1\n22E2\n22E3\n22E4\n22E5\n22E6\n22E7\n22E8\n22E9\n22EA\n22EB\n22EC\n22ED\n22EE\n22EF\n22F0\n22F1\n22F2\n22F3\n22F4\n22F5\n22F6\n22F7\n22F8\n22F9\n22FA\n22FB\n22FC\n22FD\n22FE\n22FF\n2300\n2301\n2302\n2303\n2304\n2305\n2306\n2307\n2308\n2309\n230A\n230B\n230C\n230D\n230E\n230F\n2310\n2311\n2312\n2313\n2314\n2315\n2316\n2317\n2318\n2319\n231A\n231B\n231C\n231D\n231E\n231F\n2320\n2321\n2322\n2323\n2324\n2325\n2326\n2327\n2328\n2329\n232A\n232B\n232C\n232D\n232E\n232F\n2330\n2331\n2332\n2333\n2334\n2335\n2336\n2337\n2338\n2339\n233A\n233B\n233C\n233D\n233E\n233F\n2340\n2341\n2342\n2343\n2344\n2345\n2346\n2347\n2348\n2349\n234A\n234B\n234C\n234D\n234E\n234F\n2350\n2351\n2352\n2353\n2354\n2355\n2356\n2357\n2358\n2359\n235A\n235B\n235C\n235D\n235E\n235F\n2360\n2361\n2362\n2363\n2364\n2365\n2366\n2367\n2368\n2369\n236A\n236B\n236C\n236D\n236E\n236F\n2370\n2371\n2372\n2373\n2374\n2375\n2376\n2377\n2378\n2379\n237A\n237B\n237C\n237D\n237E\n237F\n2380\n2381\n2382\n2383\n2384\n2385\n2386\n2387\n2388\n2389\n238A\n238B\n238C\n238D\n238E\n238F\n2390\n2391\n2392\n2393\n2394\n2395\n2396\n2397\n2398\n2399\n239A\n239B\n239C\n239D\n239E\n239F\n23A0\n23A1\n23A2\n23A3\n23A4\n23A5\n23A6\n23A7\n23A8\n23A9\n23AA\n23AB\n23AC\n23AD\n23AE\n23AF\n23B0\n23B1\n23B2\n23B3\n23B4\n23B5\n23B6\n23B7\n23B8\n23B9\n23BA\n23BB\n23BC\n23BD\n23BE\n23BF\n23C0\n23C1\n23C2\n23C3\n23C4\n23C5\n23C6\n23C7\n23C8\n23C9\n23CA\n23CB\n23CC\n23CD\n23CE\n23CF\n23D0\n23D1\n23D2\n23D3\n23D4\n23D5\n23D6\n23D7\n23D8\n23D9\n23DA\n23DB\n23DC\n23DD\n23DE\n23DF\n23E0\n23E1\n23E2\n23E3\n23E4\n23E5\n23E6\n23E7\n23E8\n23E9\n23EA\n23EB\n23EC\n23ED\n23EE\n23EF\n23F0\n23F1\n23F2\n23F3\n23F4\n23F5\n23F6\n23F7\n23F8\n23F9\n23FA\n2400\n2401\n2402\n2403\n2404\n2405\n2406\n2407\n2408\n2409\n240A\n240B\n240C\n240D\n240E\n240F\n2410\n2411\n2412\n2413\n2414\n2415\n2416\n2417\n2418\n2419\n241A\n241B\n241C\n241D\n241E\n241F\n2420\n2421\n2422\n2423\n2424\n2425\n2426\n2440\n2441\n2442\n2443\n2444\n2445\n2446\n2447\n2448\n2449\n244A\n2460\n2461\n2462\n2463\n2464\n2465\n2466\n2467\n2468\n2469\n246A\n246B\n246C\n246D\n246E\n246F\n2470\n2471\n2472\n2473\n2474\n2475\n2476\n2477\n2478\n2479\n247A\n247B\n247C\n247D\n247E\n247F\n2480\n2481\n2482\n2483\n2484\n2485\n2486\n2487\n2488\n2489\n248A\n248B\n248C\n248D\n248E\n248F\n2490\n2491\n2492\n2493\n2494\n2495\n2496\n2497\n2498\n2499\n249A\n249B\n249C\n249D\n249E\n249F\n24A0\n24A1\n24A2\n24A3\n24A4\n24A5\n24A6\n24A7\n24A8\n24A9\n24AA\n24AB\n24AC\n24AD\n24AE\n24AF\n24B0\n24B1\n24B2\n24B3\n24B4\n24B5\n24B6\n24B7\n24B8\n24B9\n24BA\n24BB\n24BC\n24BD\n24BE\n24BF\n24C0\n24C1\n24C2\n24C3\n24C4\n24C5\n24C6\n24C7\n24C8\n24C9\n24CA\n24CB\n24CC\n24CD\n24CE\n24CF\n24D0\n24D1\n24D2\n24D3\n24D4\n24D5\n24D6\n24D7\n24D8\n24D9\n24DA\n24DB\n24DC\n24DD\n24DE\n24DF\n24E0\n24E1\n24E2\n24E3\n24E4\n24E5\n24E6\n24E7\n24E8\n24E9\n24EA\n24EB\n24EC\n24ED\n24EE\n24EF\n24F0\n24F1\n24F2\n24F3\n24F4\n24F5\n24F6\n24F7\n24F8\n24F9\n24FA\n24FB\n24FC\n24FD\n24FE\n24FF\n2500\n2501\n2502\n2503\n2504\n2505\n2506\n2507\n2508\n2509\n250A\n250B\n250C\n250D\n250E\n250F\n2510\n2511\n2512\n2513\n2514\n2515\n2516\n2517\n2518\n2519\n251A\n251B\n251C\n251D\n251E\n251F\n2520\n2521\n2522\n2523\n2524\n2525\n2526\n2527\n2528\n2529\n252A\n252B\n252C\n252D\n252E\n252F\n2530\n2531\n2532\n2533\n2534\n2535\n2536\n2537\n2538\n2539\n253A\n253B\n253C\n253D\n253E\n253F\n2540\n2541\n2542\n2543\n2544\n2545\n2546\n2547\n2548\n2549\n254A\n254B\n254C\n254D\n254E\n254F\n2550\n2551\n2552\n2553\n2554\n2555\n2556\n2557\n2558\n2559\n255A\n255B\n255C\n255D\n255E\n255F\n2560\n2561\n2562\n2563\n2564\n2565\n2566\n2567\n2568\n2569\n256A\n256B\n256C\n256D\n256E\n256F\n2570\n2571\n2572\n2573\n2574\n2575\n2576\n2577\n2578\n2579\n257A\n257B\n257C\n257D\n257E\n257F\n2580\n2581\n2582\n2583\n2584\n2585\n2586\n2587\n2588\n2589\n258A\n258B\n258C\n258D\n258E\n258F\n2590\n2591\n2592\n2593\n2594\n2595\n2596\n2597\n2598\n2599\n259A\n259B\n259C\n259D\n259E\n259F\n25A0\n25A1\n25A2\n25A3\n25A4\n25A5\n25A6\n25A7\n25A8\n25A9\n25AA\n25AB\n25AC\n25AD\n25AE\n25AF\n25B0\n25B1\n25B2\n25B3\n25B4\n25B5\n25B6\n25B7\n25B8\n25B9\n25BA\n25BB\n25BC\n25BD\n25BE\n25BF\n25C0\n25C1\n25C2\n25C3\n25C4\n25C5\n25C6\n25C7\n25C8\n25C9\n25CA\n25CB\n25CC\n25CD\n25CE\n25CF\n25D0\n25D1\n25D2\n25D3\n25D4\n25D5\n25D6\n25D7\n25D8\n25D9\n25DA\n25DB\n25DC\n25DD\n25DE\n25DF\n25E0\n25E1\n25E2\n25E3\n25E4\n25E5\n25E6\n25E7\n25E8\n25E9\n25EA\n25EB\n25EC\n25ED\n25EE\n25EF\n25F0\n25F1\n25F2\n25F3\n25F4\n25F5\n25F6\n25F7\n25F8\n25F9\n25FA\n25FB\n25FC\n25FD\n25FE\n25FF\n2600\n2601\n2602\n2603\n2604\n2605\n2606\n2607\n2608\n2609\n260A\n260B\n260C\n260D\n260E\n260F\n2610\n2611\n2612\n2613\n2614\n2615\n2616\n2617\n2618\n2619\n261A\n261B\n261C\n261D\n261E\n261F\n2620\n2621\n2622\n2623\n2624\n2625\n2626\n2627\n2628\n2629\n262A\n262B\n262C\n262D\n262E\n262F\n2630\n2631\n2632\n2633\n2634\n2635\n2636\n2637\n2638\n2639\n263A\n263B\n263C\n263D\n263E\n263F\n2640\n2641\n2642\n2643\n2644\n2645\n2646\n2647\n2648\n2649\n264A\n264B\n264C\n264D\n264E\n264F\n2650\n2651\n2652\n2653\n2654\n2655\n2656\n2657\n2658\n2659\n265A\n265B\n265C\n265D\n265E\n265F\n2660\n2661\n2662\n2663\n2664\n2665\n2666\n2667\n2668\n2669\n266A\n266B\n266C\n266D\n266E\n266F\n2670\n2671\n2672\n2673\n2674\n2675\n2676\n2677\n2678\n2679\n267A\n267B\n267C\n267D\n267E\n267F\n2680\n2681\n2682\n2683\n2684\n2685\n2686\n2687\n2688\n2689\n268A\n268B\n268C\n268D\n268E\n268F\n2690\n2691\n2692\n2693\n2694\n2695\n2696\n2697\n2698\n2699\n269A\n269B\n269C\n269D\n269E\n269F\n26A0\n26A1\n26A2\n26A3\n26A4\n26A5\n26A6\n26A7\n26A8\n26A9\n26AA\n26AB\n26AC\n26AD\n26AE\n26AF\n26B0\n26B1\n26B2\n26B3\n26B4\n26B5\n26B6\n26B7\n26B8\n26B9\n26BA\n26BB\n26BC\n26BD\n26BE\n26BF\n26C0\n26C1\n26C2\n26C3\n26C4\n26C5\n26C6\n26C7\n26C8\n26C9\n26CA\n26CB\n26CC\n26CD\n26CE\n26CF\n26D0\n26D1\n26D2\n26D3\n26D4\n26D5\n26D6\n26D7\n26D8\n26D9\n26DA\n26DB\n26DC\n26DD\n26DE\n26DF\n26E0\n26E1\n26E2\n26E3\n26E4\n26E5\n26E6\n26E7\n26E8\n26E9\n26EA\n26EB\n26EC\n26ED\n26EE\n26EF\n26F0\n26F1\n26F2\n26F3\n26F4\n26F5\n26F6\n26F7\n26F8\n26F9\n26FA\n26FB\n26FC\n26FD\n26FE\n26FF\n2700\n2701\n2702\n2703\n2704\n2705\n2706\n2707\n2708\n2709\n270A\n270B\n270C\n270D\n270E\n270F\n2710\n2711\n2712\n2713\n2714\n2715\n2716\n2717\n2718\n2719\n271A\n271B\n271C\n271D\n271E\n271F\n2720\n2721\n2722\n2723\n2724\n2725\n2726\n2727\n2728\n2729\n272A\n272B\n272C\n272D\n272E\n272F\n2730\n2731\n2732\n2733\n2734\n2735\n2736\n2737\n2738\n2739\n273A\n273B\n273C\n273D\n273E\n273F\n2740\n2741\n2742\n2743\n2744\n2745\n2746\n2747\n2748\n2749\n274A\n274B\n274C\n274D\n274E\n274F\n2750\n2751\n2752\n2753\n2754\n2755\n2756\n2757\n2758\n2759\n275A\n275B\n275C\n275D\n275E\n275F\n2760\n2761\n2762\n2763\n2764\n2765\n2766\n2767\n2768\n2769\n276A\n276B\n276C\n276D\n276E\n276F\n2770\n2771\n2772\n2773\n2774\n2775\n2776\n2777\n2778\n2779\n277A\n277B\n277C\n277D\n277E\n277F\n2780\n2781\n2782\n2783\n2784\n2785\n2786\n2787\n2788\n2789\n278A\n278B\n278C\n278D\n278E\n278F\n2790\n2791\n2792\n2793\n2794\n2795\n2796\n2797\n2798\n2799\n279A\n279B\n279C\n279D\n279E\n279F\n27A0\n27A1\n27A2\n27A3\n27A4\n27A5\n27A6\n27A7\n27A8\n27A9\n27AA\n27AB\n27AC\n27AD\n27AE\n27AF\n27B0\n27B1\n27B2\n27B3\n27B4\n27B5\n27B6\n27B7\n27B8\n27B9\n27BA\n27BB\n27BC\n27BD\n27BE\n27BF\n27C0\n27C1\n27C2\n27C3\n27C4\n27C5\n27C6\n27C7\n27C8\n27C9\n27CA\n27CB\n27CC\n27CD\n27CE\n27CF\n27D0\n27D1\n27D2\n27D3\n27D4\n27D5\n27D6\n27D7\n27D8\n27D9\n27DA\n27DB\n27DC\n27DD\n27DE\n27DF\n27E0\n27E1\n27E2\n27E3\n27E4\n27E5\n27E6\n27E7\n27E8\n27E9\n27EA\n27EB\n27EC\n27ED\n27EE\n27EF\n27F0\n27F1\n27F2\n27F3\n27F4\n27F5\n27F6\n27F7\n27F8\n27F9\n27FA\n27FB\n27FC\n27FD\n27FE\n27FF\n2800\n2801\n2802\n2803\n2804\n2805\n2806\n2807\n2808\n2809\n280A\n280B\n280C\n280D\n280E\n280F\n2810\n2811\n2812\n2813\n2814\n2815\n2816\n2817\n2818\n2819\n281A\n281B\n281C\n281D\n281E\n281F\n2820\n2821\n2822\n2823\n2824\n2825\n2826\n2827\n2828\n2829\n282A\n282B\n282C\n282D\n282E\n282F\n2830\n2831\n2832\n2833\n2834\n2835\n2836\n2837\n2838\n2839\n283A\n283B\n283C\n283D\n283E\n283F\n2840\n2841\n2842\n2843\n2844\n2845\n2846\n2847\n2848\n2849\n284A\n284B\n284C\n284D\n284E\n284F\n2850\n2851\n2852\n2853\n2854\n2855\n2856\n2857\n2858\n2859\n285A\n285B\n285C\n285D\n285E\n285F\n2860\n2861\n2862\n2863\n2864\n2865\n2866\n2867\n2868\n2869\n286A\n286B\n286C\n286D\n286E\n286F\n2870\n2871\n2872\n2873\n2874\n2875\n2876\n2877\n2878\n2879\n287A\n287B\n287C\n287D\n287E\n287F\n2880\n2881\n2882\n2883\n2884\n2885\n2886\n2887\n2888\n2889\n288A\n288B\n288C\n288D\n288E\n288F\n2890\n2891\n2892\n2893\n2894\n2895\n2896\n2897\n2898\n2899\n289A\n289B\n289C\n289D\n289E\n289F\n28A0\n28A1\n28A2\n28A3\n28A4\n28A5\n28A6\n28A7\n28A8\n28A9\n28AA\n28AB\n28AC\n28AD\n28AE\n28AF\n28B0\n28B1\n28B2\n28B3\n28B4\n28B5\n28B6\n28B7\n28B8\n28B9\n28BA\n28BB\n28BC\n28BD\n28BE\n28BF\n28C0\n28C1\n28C2\n28C3\n28C4\n28C5\n28C6\n28C7\n28C8\n28C9\n28CA\n28CB\n28CC\n28CD\n28CE\n28CF\n28D0\n28D1\n28D2\n28D3\n28D4\n28D5\n28D6\n28D7\n28D8\n28D9\n28DA\n28DB\n28DC\n28DD\n28DE\n28DF\n28E0\n28E1\n28E2\n28E3\n28E4\n28E5\n28E6\n28E7\n28E8\n28E9\n28EA\n28EB\n28EC\n28ED\n28EE\n28EF\n28F0\n28F1\n28F2\n28F3\n28F4\n28F5\n28F6\n28F7\n28F8\n28F9\n28FA\n28FB\n28FC\n28FD\n28FE\n28FF\n2900\n2901\n2902\n2903\n2904\n2905\n2906\n2907\n2908\n2909\n290A\n290B\n290C\n290D\n290E\n290F\n2910\n2911\n2912\n2913\n2914\n2915\n2916\n2917\n2918\n2919\n291A\n291B\n291C\n291D\n291E\n291F\n2920\n2921\n2922\n2923\n2924\n2925\n2926\n2927\n2928\n2929\n292A\n292B\n292C\n292D\n292E\n292F\n2930\n2931\n2932\n2933\n2934\n2935\n2936\n2937\n2938\n2939\n293A\n293B\n293C\n293D\n293E\n293F\n2940\n2941\n2942\n2943\n2944\n2945\n2946\n2947\n2948\n2949\n294A\n294B\n294C\n294D\n294E\n294F\n2950\n2951\n2952\n2953\n2954\n2955\n2956\n2957\n2958\n2959\n295A\n295B\n295C\n295D\n295E\n295F\n2960\n2961\n2962\n2963\n2964\n2965\n2966\n2967\n2968\n2969\n296A\n296B\n296C\n296D\n296E\n296F\n2970\n2971\n2972\n2973\n2974\n2975\n2976\n2977\n2978\n2979\n297A\n297B\n297C\n297D\n297E\n297F\n2980\n2981\n2982\n2983\n2984\n2985\n2986\n2987\n2988\n2989\n298A\n298B\n298C\n298D\n298E\n298F\n2990\n2991\n2992\n2993\n2994\n2995\n2996\n2997\n2998\n2999\n299A\n299B\n299C\n299D\n299E\n299F\n29A0\n29A1\n29A2\n29A3\n29A4\n29A5\n29A6\n29A7\n29A8\n29A9\n29AA\n29AB\n29AC\n29AD\n29AE\n29AF\n29B0\n29B1\n29B2\n29B3\n29B4\n29B5\n29B6\n29B7\n29B8\n29B9\n29BA\n29BB\n29BC\n29BD\n29BE\n29BF\n29C0\n29C1\n29C2\n29C3\n29C4\n29C5\n29C6\n29C7\n29C8\n29C9\n29CA\n29CB\n29CC\n29CD\n29CE\n29CF\n29D0\n29D1\n29D2\n29D3\n29D4\n29D5\n29D6\n29D7\n29D8\n29D9\n29DA\n29DB\n29DC\n29DD\n29DE\n29DF\n29E0\n29E1\n29E2\n29E3\n29E4\n29E5\n29E6\n29E7\n29E8\n29E9\n29EA\n29EB\n29EC\n29ED\n29EE\n29EF\n29F0\n29F1\n29F2\n29F3\n29F4\n29F5\n29F6\n29F7\n29F8\n29F9\n29FA\n29FB\n29FC\n29FD\n29FE\n29FF\n2A00\n2A01\n2A02\n2A03\n2A04\n2A05\n2A06\n2A07\n2A08\n2A09\n2A0A\n2A0B\n2A0C\n2A0D\n2A0E\n2A0F\n2A10\n2A11\n2A12\n2A13\n2A14\n2A15\n2A16\n2A17\n2A18\n2A19\n2A1A\n2A1B\n2A1C\n2A1D\n2A1E\n2A1F\n2A20\n2A21\n2A22\n2A23\n2A24\n2A25\n2A26\n2A27\n2A28\n2A29\n2A2A\n2A2B\n2A2C\n2A2D\n2A2E\n2A2F\n2A30\n2A31\n2A32\n2A33\n2A34\n2A35\n2A36\n2A37\n2A38\n2A39\n2A3A\n2A3B\n2A3C\n2A3D\n2A3E\n2A3F\n2A40\n2A41\n2A42\n2A43\n2A44\n2A45\n2A46\n2A47\n2A48\n2A49\n2A4A\n2A4B\n2A4C\n2A4D\n2A4E\n2A4F\n2A50\n2A51\n2A52\n2A53\n2A54\n2A55\n2A56\n2A57\n2A58\n2A59\n2A5A\n2A5B\n2A5C\n2A5D\n2A5E\n2A5F\n2A60\n2A61\n2A62\n2A63\n2A64\n2A65\n2A66\n2A67\n2A68\n2A69\n2A6A\n2A6B\n2A6C\n2A6D\n2A6E\n2A6F\n2A70\n2A71\n2A72\n2A73\n2A74\n2A75\n2A76\n2A77\n2A78\n2A79\n2A7A\n2A7B\n2A7C\n2A7D\n2A7E\n2A7F\n2A80\n2A81\n2A82\n2A83\n2A84\n2A85\n2A86\n2A87\n2A88\n2A89\n2A8A\n2A8B\n2A8C\n2A8D\n2A8E\n2A8F\n2A90\n2A91\n2A92\n2A93\n2A94\n2A95\n2A96\n2A97\n2A98\n2A99\n2A9A\n2A9B\n2A9C\n2A9D\n2A9E\n2A9F\n2AA0\n2AA1\n2AA2\n2AA3\n2AA4\n2AA5\n2AA6\n2AA7\n2AA8\n2AA9\n2AAA\n2AAB\n2AAC\n2AAD\n2AAE\n2AAF\n2AB0\n2AB1\n2AB2\n2AB3\n2AB4\n2AB5\n2AB6\n2AB7\n2AB8\n2AB9\n2ABA\n2ABB\n2ABC\n2ABD\n2ABE\n2ABF\n2AC0\n2AC1\n2AC2\n2AC3\n2AC4\n2AC5\n2AC6\n2AC7\n2AC8\n2AC9\n2ACA\n2ACB\n2ACC\n2ACD\n2ACE\n2ACF\n2AD0\n2AD1\n2AD2\n2AD3\n2AD4\n2AD5\n2AD6\n2AD7\n2AD8\n2AD9\n2ADA\n2ADB\n2ADC\n2ADD\n2ADE\n2ADF\n2AE0\n2AE1\n2AE2\n2AE3\n2AE4\n2AE5\n2AE6\n2AE7\n2AE8\n2AE9\n2AEA\n2AEB\n2AEC\n2AED\n2AEE\n2AEF\n2AF0\n2AF1\n2AF2\n2AF3\n2AF4\n2AF5\n2AF6\n2AF7\n2AF8\n2AF9\n2AFA\n2AFB\n2AFC\n2AFD\n2AFE\n2AFF\n2B00\n2B01\n2B02\n2B03\n2B04\n2B05\n2B06\n2B07\n2B08\n2B09\n2B0A\n2B0B\n2B0C\n2B0D\n2B0E\n2B0F\n2B10\n2B11\n2B12\n2B13\n2B14\n2B15\n2B16\n2B17\n2B18\n2B19\n2B1A\n2B1B\n2B1C\n2B1D\n2B1E\n2B1F\n2B20\n2B21\n2B22\n2B23\n2B24\n2B25\n2B26\n2B27\n2B28\n2B29\n2B2A\n2B2B\n2B2C\n2B2D\n2B2E\n2B2F\n2B30\n2B31\n2B32\n2B33\n2B34\n2B35\n2B36\n2B37\n2B38\n2B39\n2B3A\n2B3B\n2B3C\n2B3D\n2B3E\n2B3F\n2B40\n2B41\n2B42\n2B43\n2B44\n2B45\n2B46\n2B47\n2B48\n2B49\n2B4A\n2B4B\n2B4C\n2B4D\n2B4E\n2B4F\n2B50\n2B51\n2B52\n2B53\n2B54\n2B55\n2B56\n2B57\n2B58\n2B59\n2B5A\n2B5B\n2B5C\n2B5D\n2B5E\n2B5F\n2B60\n2B61\n2B62\n2B63\n2B64\n2B65\n2B66\n2B67\n2B68\n2B69\n2B6A\n2B6B\n2B6C\n2B6D\n2B6E\n2B6F\n2B70\n2B71\n2B72\n2B73\n2B76\n2B77\n2B78\n2B79\n2B7A\n2B7B\n2B7C\n2B7D\n2B7E\n2B7F\n2B80\n2B81\n2B82\n2B83\n2B84\n2B85\n2B86\n2B87\n2B88\n2B89\n2B8A\n2B8B\n2B8C\n2B8D\n2B8E\n2B8F\n2B90\n2B91\n2B92\n2B93\n2B94\n2B95\n2B98\n2B99\n2B9A\n2B9B\n2B9C\n2B9D\n2B9E\n2B9F\n2BA0\n2BA1\n2BA2\n2BA3\n2BA4\n2BA5\n2BA6\n2BA7\n2BA8\n2BA9\n2BAA\n2BAB\n2BAC\n2BAD\n2BAE\n2BAF\n2BB0\n2BB1\n2BB2\n2BB3\n2BB4\n2BB5\n2BB6\n2BB7\n2BB8\n2BB9\n2BBD\n2BBE\n2BBF\n2BC0\n2BC1\n2BC2\n2BC3\n2BC4\n2BC5\n2BC6\n2BC7\n2BC8\n2BCA\n2BCB\n2BCC\n2BCD\n2BCE\n2BCF\n2BD0\n2BD1\n2C00\n2C01\n2C02\n2C03\n2C04\n2C05\n2C06\n2C07\n2C08\n2C09\n2C0A\n2C0B\n2C0C\n2C0D\n2C0E\n2C0F\n2C10\n2C11\n2C12\n2C13\n2C14\n2C15\n2C16\n2C17\n2C18\n2C19\n2C1A\n2C1B\n2C1C\n2C1D\n2C1E\n2C1F\n2C20\n2C21\n2C22\n2C23\n2C24\n2C25\n2C26\n2C27\n2C28\n2C29\n2C2A\n2C2B\n2C2C\n2C2D\n2C2E\n2C30\n2C31\n2C32\n2C33\n2C34\n2C35\n2C36\n2C37\n2C38\n2C39\n2C3A\n2C3B\n2C3C\n2C3D\n2C3E\n2C3F\n2C40\n2C41\n2C42\n2C43\n2C44\n2C45\n2C46\n2C47\n2C48\n2C49\n2C4A\n2C4B\n2C4C\n2C4D\n2C4E\n2C4F\n2C50\n2C51\n2C52\n2C53\n2C54\n2C55\n2C56\n2C57\n2C58\n2C59\n2C5A\n2C5B\n2C5C\n2C5D\n2C5E\n2C60\n2C61\n2C62\n2C63\n2C64\n2C65\n2C66\n2C67\n2C68\n2C69\n2C6A\n2C6B\n2C6C\n2C6D\n2C6E\n2C6F\n2C70\n2C71\n2C72\n2C73\n2C74\n2C75\n2C76\n2C77\n2C78\n2C79\n2C7A\n2C7B\n2C7C\n2C7D\n2C7E\n2C7F\n2C80\n2C81\n2C82\n2C83\n2C84\n2C85\n2C86\n2C87\n2C88\n2C89\n2C8A\n2C8B\n2C8C\n2C8D\n2C8E\n2C8F\n2C90\n2C91\n2C92\n2C93\n2C94\n2C95\n2C96\n2C97\n2C98\n2C99\n2C9A\n2C9B\n2C9C\n2C9D\n2C9E\n2C9F\n2CA0\n2CA1\n2CA2\n2CA3\n2CA4\n2CA5\n2CA6\n2CA7\n2CA8\n2CA9\n2CAA\n2CAB\n2CAC\n2CAD\n2CAE\n2CAF\n2CB0\n2CB1\n2CB2\n2CB3\n2CB4\n2CB5\n2CB6\n2CB7\n2CB8\n2CB9\n2CBA\n2CBB\n2CBC\n2CBD\n2CBE\n2CBF\n2CC0\n2CC1\n2CC2\n2CC3\n2CC4\n2CC5\n2CC6\n2CC7\n2CC8\n2CC9\n2CCA\n2CCB\n2CCC\n2CCD\n2CCE\n2CCF\n2CD0\n2CD1\n2CD2\n2CD3\n2CD4\n2CD5\n2CD6\n2CD7\n2CD8\n2CD9\n2CDA\n2CDB\n2CDC\n2CDD\n2CDE\n2CDF\n2CE0\n2CE1\n2CE2\n2CE3\n2CE4\n2CE5\n2CE6\n2CE7\n2CE8\n2CE9\n2CEA\n2CEB\n2CEC\n2CED\n2CEE\n2CEF\n2CF0\n2CF1\n2CF2\n2CF3\n2CF9\n2CFA\n2CFB\n2CFC\n2CFD\n2CFE\n2CFF\n2D00\n2D01\n2D02\n2D03\n2D04\n2D05\n2D06\n2D07\n2D08\n2D09\n2D0A\n2D0B\n2D0C\n2D0D\n2D0E\n2D0F\n2D10\n2D11\n2D12\n2D13\n2D14\n2D15\n2D16\n2D17\n2D18\n2D19\n2D1A\n2D1B\n2D1C\n2D1D\n2D1E\n2D1F\n2D20\n2D21\n2D22\n2D23\n2D24\n2D25\n2D27\n2D2D\n2D30\n2D31\n2D32\n2D33\n2D34\n2D35\n2D36\n2D37\n2D38\n2D39\n2D3A\n2D3B\n2D3C\n2D3D\n2D3E\n2D3F\n2D40\n2D41\n2D42\n2D43\n2D44\n2D45\n2D46\n2D47\n2D48\n2D49\n2D4A\n2D4B\n2D4C\n2D4D\n2D4E\n2D4F\n2D50\n2D51\n2D52\n2D53\n2D54\n2D55\n2D56\n2D57\n2D58\n2D59\n2D5A\n2D5B\n2D5C\n2D5D\n2D5E\n2D5F\n2D60\n2D61\n2D62\n2D63\n2D64\n2D65\n2D66\n2D67\n2D6F\n2D70\n2D7F\n2D80\n2D81\n2D82\n2D83\n2D84\n2D85\n2D86\n2D87\n2D88\n2D89\n2D8A\n2D8B\n2D8C\n2D8D\n2D8E\n2D8F\n2D90\n2D91\n2D92\n2D93\n2D94\n2D95\n2D96\n2DA0\n2DA1\n2DA2\n2DA3\n2DA4\n2DA5\n2DA6\n2DA8\n2DA9\n2DAA\n2DAB\n2DAC\n2DAD\n2DAE\n2DB0\n2DB1\n2DB2\n2DB3\n2DB4\n2DB5\n2DB6\n2DB8\n2DB9\n2DBA\n2DBB\n2DBC\n2DBD\n2DBE\n2DC0\n2DC1\n2DC2\n2DC3\n2DC4\n2DC5\n2DC6\n2DC8\n2DC9\n2DCA\n2DCB\n2DCC\n2DCD\n2DCE\n2DD0\n2DD1\n2DD2\n2DD3\n2DD4\n2DD5\n2DD6\n2DD8\n2DD9\n2DDA\n2DDB\n2DDC\n2DDD\n2DDE\n2DE0\n2DE1\n2DE2\n2DE3\n2DE4\n2DE5\n2DE6\n2DE7\n2DE8\n2DE9\n2DEA\n2DEB\n2DEC\n2DED\n2DEE\n2DEF\n2DF0\n2DF1\n2DF2\n2DF3\n2DF4\n2DF5\n2DF6\n2DF7\n2DF8\n2DF9\n2DFA\n2DFB\n2DFC\n2DFD\n2DFE\n2DFF\n2E00\n2E01\n2E02\n2E03\n2E04\n2E05\n2E06\n2E07\n2E08\n2E09\n2E0A\n2E0B\n2E0C\n2E0D\n2E0E\n2E0F\n2E10\n2E11\n2E12\n2E13\n2E14\n2E15\n2E16\n2E17\n2E18\n2E19\n2E1A\n2E1B\n2E1C\n2E1D\n2E1E\n2E1F\n2E20\n2E21\n2E22\n2E23\n2E24\n2E25\n2E26\n2E27\n2E28\n2E29\n2E2A\n2E2B\n2E2C\n2E2D\n2E2E\n2E2F\n2E30\n2E31\n2E32\n2E33\n2E34\n2E35\n2E36\n2E37\n2E38\n2E39\n2E3A\n2E3B\n2E3C\n2E3D\n2E3E\n2E3F\n2E40\n2E41\n2E42\n2E80\n2E81\n2E82\n2E83\n2E84\n2E85\n2E86\n2E87\n2E88\n2E89\n2E8A\n2E8B\n2E8C\n2E8D\n2E8E\n2E8F\n2E90\n2E91\n2E92\n2E93\n2E94\n2E95\n2E96\n2E97\n2E98\n2E99\n2E9B\n2E9C\n2E9D\n2E9E\n2E9F\n2EA0\n2EA1\n2EA2\n2EA3\n2EA4\n2EA5\n2EA6\n2EA7\n2EA8\n2EA9\n2EAA\n2EAB\n2EAC\n2EAD\n2EAE\n2EAF\n2EB0\n2EB1\n2EB2\n2EB3\n2EB4\n2EB5\n2EB6\n2EB7\n2EB8\n2EB9\n2EBA\n2EBB\n2EBC\n2EBD\n2EBE\n2EBF\n2EC0\n2EC1\n2EC2\n2EC3\n2EC4\n2EC5\n2EC6\n2EC7\n2EC8\n2EC9\n2ECA\n2ECB\n2ECC\n2ECD\n2ECE\n2ECF\n2ED0\n2ED1\n2ED2\n2ED3\n2ED4\n2ED5\n2ED6\n2ED7\n2ED8\n2ED9\n2EDA\n2EDB\n2EDC\n2EDD\n2EDE\n2EDF\n2EE0\n2EE1\n2EE2\n2EE3\n2EE4\n2EE5\n2EE6\n2EE7\n2EE8\n2EE9\n2EEA\n2EEB\n2EEC\n2EED\n2EEE\n2EEF\n2EF0\n2EF1\n2EF2\n2EF3\n2F00\n2F01\n2F02\n2F03\n2F04\n2F05\n2F06\n2F07\n2F08\n2F09\n2F0A\n2F0B\n2F0C\n2F0D\n2F0E\n2F0F\n2F10\n2F11\n2F12\n2F13\n2F14\n2F15\n2F16\n2F17\n2F18\n2F19\n2F1A\n2F1B\n2F1C\n2F1D\n2F1E\n2F1F\n2F20\n2F21\n2F22\n2F23\n2F24\n2F25\n2F26\n2F27\n2F28\n2F29\n2F2A\n2F2B\n2F2C\n2F2D\n2F2E\n2F2F\n2F30\n2F31\n2F32\n2F33\n2F34\n2F35\n2F36\n2F37\n2F38\n2F39\n2F3A\n2F3B\n2F3C\n2F3D\n2F3E\n2F3F\n2F40\n2F41\n2F42\n2F43\n2F44\n2F45\n2F46\n2F47\n2F48\n2F49\n2F4A\n2F4B\n2F4C\n2F4D\n2F4E\n2F4F\n2F50\n2F51\n2F52\n2F53\n2F54\n2F55\n2F56\n2F57\n2F58\n2F59\n2F5A\n2F5B\n2F5C\n2F5D\n2F5E\n2F5F\n2F60\n2F61\n2F62\n2F63\n2F64\n2F65\n2F66\n2F67\n2F68\n2F69\n2F6A\n2F6B\n2F6C\n2F6D\n2F6E\n2F6F\n2F70\n2F71\n2F72\n2F73\n2F74\n2F75\n2F76\n2F77\n2F78\n2F79\n2F7A\n2F7B\n2F7C\n2F7D\n2F7E\n2F7F\n2F80\n2F81\n2F82\n2F83\n2F84\n2F85\n2F86\n2F87\n2F88\n2F89\n2F8A\n2F8B\n2F8C\n2F8D\n2F8E\n2F8F\n2F90\n2F91\n2F92\n2F93\n2F94\n2F95\n2F96\n2F97\n2F98\n2F99\n2F9A\n2F9B\n2F9C\n2F9D\n2F9E\n2F9F\n2FA0\n2FA1\n2FA2\n2FA3\n2FA4\n2FA5\n2FA6\n2FA7\n2FA8\n2FA9\n2FAA\n2FAB\n2FAC\n2FAD\n2FAE\n2FAF\n2FB0\n2FB1\n2FB2\n2FB3\n2FB4\n2FB5\n2FB6\n2FB7\n2FB8\n2FB9\n2FBA\n2FBB\n2FBC\n2FBD\n2FBE\n2FBF\n2FC0\n2FC1\n2FC2\n2FC3\n2FC4\n2FC5\n2FC6\n2FC7\n2FC8\n2FC9\n2FCA\n2FCB\n2FCC\n2FCD\n2FCE\n2FCF\n2FD0\n2FD1\n2FD2\n2FD3\n2FD4\n2FD5\n2FF0\n2FF1\n2FF2\n2FF3\n2FF4\n2FF5\n2FF6\n2FF7\n2FF8\n2FF9\n2FFA\n2FFB\n3000\n3001\n3002\n3003\n3004\n3005\n3006\n3007\n3008\n3009\n300A\n300B\n300C\n300D\n300E\n300F\n3010\n3011\n3012\n3013\n3014\n3015\n3016\n3017\n3018\n3019\n301A\n301B\n301C\n301D\n301E\n301F\n3020\n3021\n3022\n3023\n3024\n3025\n3026\n3027\n3028\n3029\n302A\n302B\n302C\n302D\n302E\n302F\n3030\n3031\n3032\n3033\n3034\n3035\n3036\n3037\n3038\n3039\n303A\n303B\n303C\n303D\n303E\n303F\n3041\n3042\n3043\n3044\n3045\n3046\n3047\n3048\n3049\n304A\n304B\n304C\n304D\n304E\n304F\n3050\n3051\n3052\n3053\n3054\n3055\n3056\n3057\n3058\n3059\n305A\n305B\n305C\n305D\n305E\n305F\n3060\n3061\n3062\n3063\n3064\n3065\n3066\n3067\n3068\n3069\n306A\n306B\n306C\n306D\n306E\n306F\n3070\n3071\n3072\n3073\n3074\n3075\n3076\n3077\n3078\n3079\n307A\n307B\n307C\n307D\n307E\n307F\n3080\n3081\n3082\n3083\n3084\n3085\n3086\n3087\n3088\n3089\n308A\n308B\n308C\n308D\n308E\n308F\n3090\n3091\n3092\n3093\n3094\n3095\n3096\n3099\n309A\n309B\n309C\n309D\n309E\n309F\n30A0\n30A1\n30A2\n30A3\n30A4\n30A5\n30A6\n30A7\n30A8\n30A9\n30AA\n30AB\n30AC\n30AD\n30AE\n30AF\n30B0\n30B1\n30B2\n30B3\n30B4\n30B5\n30B6\n30B7\n30B8\n30B9\n30BA\n30BB\n30BC\n30BD\n30BE\n30BF\n30C0\n30C1\n30C2\n30C3\n30C4\n30C5\n30C6\n30C7\n30C8\n30C9\n30CA\n30CB\n30CC\n30CD\n30CE\n30CF\n30D0\n30D1\n30D2\n30D3\n30D4\n30D5\n30D6\n30D7\n30D8\n30D9\n30DA\n30DB\n30DC\n30DD\n30DE\n30DF\n30E0\n30E1\n30E2\n30E3\n30E4\n30E5\n30E6\n30E7\n30E8\n30E9\n30EA\n30EB\n30EC\n30ED\n30EE\n30EF\n30F0\n30F1\n30F2\n30F3\n30F4\n30F5\n30F6\n30F7\n30F8\n30F9\n30FA\n30FB\n30FC\n30FD\n30FE\n30FF\n3105\n3106\n3107\n3108\n3109\n310A\n310B\n310C\n310D\n310E\n310F\n3110\n3111\n3112\n3113\n3114\n3115\n3116\n3117\n3118\n3119\n311A\n311B\n311C\n311D\n311E\n311F\n3120\n3121\n3122\n3123\n3124\n3125\n3126\n3127\n3128\n3129\n312A\n312B\n312C\n312D\n3131\n3132\n3133\n3134\n3135\n3136\n3137\n3138\n3139\n313A\n313B\n313C\n313D\n313E\n313F\n3140\n3141\n3142\n3143\n3144\n3145\n3146\n3147\n3148\n3149\n314A\n314B\n314C\n314D\n314E\n314F\n3150\n3151\n3152\n3153\n3154\n3155\n3156\n3157\n3158\n3159\n315A\n315B\n315C\n315D\n315E\n315F\n3160\n3161\n3162\n3163\n3164\n3165\n3166\n3167\n3168\n3169\n316A\n316B\n316C\n316D\n316E\n316F\n3170\n3171\n3172\n3173\n3174\n3175\n3176\n3177\n3178\n3179\n317A\n317B\n317C\n317D\n317E\n317F\n3180\n3181\n3182\n3183\n3184\n3185\n3186\n3187\n3188\n3189\n318A\n318B\n318C\n318D\n318E\n3190\n3191\n3192\n3193\n3194\n3195\n3196\n3197\n3198\n3199\n319A\n319B\n319C\n319D\n319E\n319F\n31A0\n31A1\n31A2\n31A3\n31A4\n31A5\n31A6\n31A7\n31A8\n31A9\n31AA\n31AB\n31AC\n31AD\n31AE\n31AF\n31B0\n31B1\n31B2\n31B3\n31B4\n31B5\n31B6\n31B7\n31B8\n31B9\n31BA\n31C0\n31C1\n31C2\n31C3\n31C4\n31C5\n31C6\n31C7\n31C8\n31C9\n31CA\n31CB\n31CC\n31CD\n31CE\n31CF\n31D0\n31D1\n31D2\n31D3\n31D4\n31D5\n31D6\n31D7\n31D8\n31D9\n31DA\n31DB\n31DC\n31DD\n31DE\n31DF\n31E0\n31E1\n31E2\n31E3\n31F0\n31F1\n31F2\n31F3\n31F4\n31F5\n31F6\n31F7\n31F8\n31F9\n31FA\n31FB\n31FC\n31FD\n31FE\n31FF\n3200\n3201\n3202\n3203\n3204\n3205\n3206\n3207\n3208\n3209\n320A\n320B\n320C\n320D\n320E\n320F\n3210\n3211\n3212\n3213\n3214\n3215\n3216\n3217\n3218\n3219\n321A\n321B\n321C\n321D\n321E\n3220\n3221\n3222\n3223\n3224\n3225\n3226\n3227\n3228\n3229\n322A\n322B\n322C\n322D\n322E\n322F\n3230\n3231\n3232\n3233\n3234\n3235\n3236\n3237\n3238\n3239\n323A\n323B\n323C\n323D\n323E\n323F\n3240\n3241\n3242\n3243\n3244\n3245\n3246\n3247\n3248\n3249\n324A\n324B\n324C\n324D\n324E\n324F\n3250\n3251\n3252\n3253\n3254\n3255\n3256\n3257\n3258\n3259\n325A\n325B\n325C\n325D\n325E\n325F\n3260\n3261\n3262\n3263\n3264\n3265\n3266\n3267\n3268\n3269\n326A\n326B\n326C\n326D\n326E\n326F\n3270\n3271\n3272\n3273\n3274\n3275\n3276\n3277\n3278\n3279\n327A\n327B\n327C\n327D\n327E\n327F\n3280\n3281\n3282\n3283\n3284\n3285\n3286\n3287\n3288\n3289\n328A\n328B\n328C\n328D\n328E\n328F\n3290\n3291\n3292\n3293\n3294\n3295\n3296\n3297\n3298\n3299\n329A\n329B\n329C\n329D\n329E\n329F\n32A0\n32A1\n32A2\n32A3\n32A4\n32A5\n32A6\n32A7\n32A8\n32A9\n32AA\n32AB\n32AC\n32AD\n32AE\n32AF\n32B0\n32B1\n32B2\n32B3\n32B4\n32B5\n32B6\n32B7\n32B8\n32B9\n32BA\n32BB\n32BC\n32BD\n32BE\n32BF\n32C0\n32C1\n32C2\n32C3\n32C4\n32C5\n32C6\n32C7\n32C8\n32C9\n32CA\n32CB\n32CC\n32CD\n32CE\n32CF\n32D0\n32D1\n32D2\n32D3\n32D4\n32D5\n32D6\n32D7\n32D8\n32D9\n32DA\n32DB\n32DC\n32DD\n32DE\n32DF\n32E0\n32E1\n32E2\n32E3\n32E4\n32E5\n32E6\n32E7\n32E8\n32E9\n32EA\n32EB\n32EC\n32ED\n32EE\n32EF\n32F0\n32F1\n32F2\n32F3\n32F4\n32F5\n32F6\n32F7\n32F8\n32F9\n32FA\n32FB\n32FC\n32FD\n32FE\n3300\n3301\n3302\n3303\n3304\n3305\n3306\n3307\n3308\n3309\n330A\n330B\n330C\n330D\n330E\n330F\n3310\n3311\n3312\n3313\n3314\n3315\n3316\n3317\n3318\n3319\n331A\n331B\n331C\n331D\n331E\n331F\n3320\n3321\n3322\n3323\n3324\n3325\n3326\n3327\n3328\n3329\n332A\n332B\n332C\n332D\n332E\n332F\n3330\n3331\n3332\n3333\n3334\n3335\n3336\n3337\n3338\n3339\n333A\n333B\n333C\n333D\n333E\n333F\n3340\n3341\n3342\n3343\n3344\n3345\n3346\n3347\n3348\n3349\n334A\n334B\n334C\n334D\n334E\n334F\n3350\n3351\n3352\n3353\n3354\n3355\n3356\n3357\n3358\n3359\n335A\n335B\n335C\n335D\n335E\n335F\n3360\n3361\n3362\n3363\n3364\n3365\n3366\n3367\n3368\n3369\n336A\n336B\n336C\n336D\n336E\n336F\n3370\n3371\n3372\n3373\n3374\n3375\n3376\n3377\n3378\n3379\n337A\n337B\n337C\n337D\n337E\n337F\n3380\n3381\n3382\n3383\n3384\n3385\n3386\n3387\n3388\n3389\n338A\n338B\n338C\n338D\n338E\n338F\n3390\n3391\n3392\n3393\n3394\n3395\n3396\n3397\n3398\n3399\n339A\n339B\n339C\n339D\n339E\n339F\n33A0\n33A1\n33A2\n33A3\n33A4\n33A5\n33A6\n33A7\n33A8\n33A9\n33AA\n33AB\n33AC\n33AD\n33AE\n33AF\n33B0\n33B1\n33B2\n33B3\n33B4\n33B5\n33B6\n33B7\n33B8\n33B9\n33BA\n33BB\n33BC\n33BD\n33BE\n33BF\n33C0\n33C1\n33C2\n33C3\n33C4\n33C5\n33C6\n33C7\n33C8\n33C9\n33CA\n33CB\n33CC\n33CD\n33CE\n33CF\n33D0\n33D1\n33D2\n33D3\n33D4\n33D5\n33D6\n33D7\n33D8\n33D9\n33DA\n33DB\n33DC\n33DD\n33DE\n33DF\n33E0\n33E1\n33E2\n33E3\n33E4\n33E5\n33E6\n33E7\n33E8\n33E9\n33EA\n33EB\n33EC\n33ED\n33EE\n33EF\n33F0\n33F1\n33F2\n33F3\n33F4\n33F5\n33F6\n33F7\n33F8\n33F9\n33FA\n33FB\n33FC\n33FD\n33FE\n33FF\n3400\n4DB5\n4DC0\n4DC1\n4DC2\n4DC3\n4DC4\n4DC5\n4DC6\n4DC7\n4DC8\n4DC9\n4DCA\n4DCB\n4DCC\n4DCD\n4DCE\n4DCF\n4DD0\n4DD1\n4DD2\n4DD3\n4DD4\n4DD5\n4DD6\n4DD7\n4DD8\n4DD9\n4DDA\n4DDB\n4DDC\n4DDD\n4DDE\n4DDF\n4DE0\n4DE1\n4DE2\n4DE3\n4DE4\n4DE5\n4DE6\n4DE7\n4DE8\n4DE9\n4DEA\n4DEB\n4DEC\n4DED\n4DEE\n4DEF\n4DF0\n4DF1\n4DF2\n4DF3\n4DF4\n4DF5\n4DF6\n4DF7\n4DF8\n4DF9\n4DFA\n4DFB\n4DFC\n4DFD\n4DFE\n4DFF\n4E00\n9FCC\nA000\nA001\nA002\nA003\nA004\nA005\nA006\nA007\nA008\nA009\nA00A\nA00B\nA00C\nA00D\nA00E\nA00F\nA010\nA011\nA012\nA013\nA014\nA015\nA016\nA017\nA018\nA019\nA01A\nA01B\nA01C\nA01D\nA01E\nA01F\nA020\nA021\nA022\nA023\nA024\nA025\nA026\nA027\nA028\nA029\nA02A\nA02B\nA02C\nA02D\nA02E\nA02F\nA030\nA031\nA032\nA033\nA034\nA035\nA036\nA037\nA038\nA039\nA03A\nA03B\nA03C\nA03D\nA03E\nA03F\nA040\nA041\nA042\nA043\nA044\nA045\nA046\nA047\nA048\nA049\nA04A\nA04B\nA04C\nA04D\nA04E\nA04F\nA050\nA051\nA052\nA053\nA054\nA055\nA056\nA057\nA058\nA059\nA05A\nA05B\nA05C\nA05D\nA05E\nA05F\nA060\nA061\nA062\nA063\nA064\nA065\nA066\nA067\nA068\nA069\nA06A\nA06B\nA06C\nA06D\nA06E\nA06F\nA070\nA071\nA072\nA073\nA074\nA075\nA076\nA077\nA078\nA079\nA07A\nA07B\nA07C\nA07D\nA07E\nA07F\nA080\nA081\nA082\nA083\nA084\nA085\nA086\nA087\nA088\nA089\nA08A\nA08B\nA08C\nA08D\nA08E\nA08F\nA090\nA091\nA092\nA093\nA094\nA095\nA096\nA097\nA098\nA099\nA09A\nA09B\nA09C\nA09D\nA09E\nA09F\nA0A0\nA0A1\nA0A2\nA0A3\nA0A4\nA0A5\nA0A6\nA0A7\nA0A8\nA0A9\nA0AA\nA0AB\nA0AC\nA0AD\nA0AE\nA0AF\nA0B0\nA0B1\nA0B2\nA0B3\nA0B4\nA0B5\nA0B6\nA0B7\nA0B8\nA0B9\nA0BA\nA0BB\nA0BC\nA0BD\nA0BE\nA0BF\nA0C0\nA0C1\nA0C2\nA0C3\nA0C4\nA0C5\nA0C6\nA0C7\nA0C8\nA0C9\nA0CA\nA0CB\nA0CC\nA0CD\nA0CE\nA0CF\nA0D0\nA0D1\nA0D2\nA0D3\nA0D4\nA0D5\nA0D6\nA0D7\nA0D8\nA0D9\nA0DA\nA0DB\nA0DC\nA0DD\nA0DE\nA0DF\nA0E0\nA0E1\nA0E2\nA0E3\nA0E4\nA0E5\nA0E6\nA0E7\nA0E8\nA0E9\nA0EA\nA0EB\nA0EC\nA0ED\nA0EE\nA0EF\nA0F0\nA0F1\nA0F2\nA0F3\nA0F4\nA0F5\nA0F6\nA0F7\nA0F8\nA0F9\nA0FA\nA0FB\nA0FC\nA0FD\nA0FE\nA0FF\nA100\nA101\nA102\nA103\nA104\nA105\nA106\nA107\nA108\nA109\nA10A\nA10B\nA10C\nA10D\nA10E\nA10F\nA110\nA111\nA112\nA113\nA114\nA115\nA116\nA117\nA118\nA119\nA11A\nA11B\nA11C\nA11D\nA11E\nA11F\nA120\nA121\nA122\nA123\nA124\nA125\nA126\nA127\nA128\nA129\nA12A\nA12B\nA12C\nA12D\nA12E\nA12F\nA130\nA131\nA132\nA133\nA134\nA135\nA136\nA137\nA138\nA139\nA13A\nA13B\nA13C\nA13D\nA13E\nA13F\nA140\nA141\nA142\nA143\nA144\nA145\nA146\nA147\nA148\nA149\nA14A\nA14B\nA14C\nA14D\nA14E\nA14F\nA150\nA151\nA152\nA153\nA154\nA155\nA156\nA157\nA158\nA159\nA15A\nA15B\nA15C\nA15D\nA15E\nA15F\nA160\nA161\nA162\nA163\nA164\nA165\nA166\nA167\nA168\nA169\nA16A\nA16B\nA16C\nA16D\nA16E\nA16F\nA170\nA171\nA172\nA173\nA174\nA175\nA176\nA177\nA178\nA179\nA17A\nA17B\nA17C\nA17D\nA17E\nA17F\nA180\nA181\nA182\nA183\nA184\nA185\nA186\nA187\nA188\nA189\nA18A\nA18B\nA18C\nA18D\nA18E\nA18F\nA190\nA191\nA192\nA193\nA194\nA195\nA196\nA197\nA198\nA199\nA19A\nA19B\nA19C\nA19D\nA19E\nA19F\nA1A0\nA1A1\nA1A2\nA1A3\nA1A4\nA1A5\nA1A6\nA1A7\nA1A8\nA1A9\nA1AA\nA1AB\nA1AC\nA1AD\nA1AE\nA1AF\nA1B0\nA1B1\nA1B2\nA1B3\nA1B4\nA1B5\nA1B6\nA1B7\nA1B8\nA1B9\nA1BA\nA1BB\nA1BC\nA1BD\nA1BE\nA1BF\nA1C0\nA1C1\nA1C2\nA1C3\nA1C4\nA1C5\nA1C6\nA1C7\nA1C8\nA1C9\nA1CA\nA1CB\nA1CC\nA1CD\nA1CE\nA1CF\nA1D0\nA1D1\nA1D2\nA1D3\nA1D4\nA1D5\nA1D6\nA1D7\nA1D8\nA1D9\nA1DA\nA1DB\nA1DC\nA1DD\nA1DE\nA1DF\nA1E0\nA1E1\nA1E2\nA1E3\nA1E4\nA1E5\nA1E6\nA1E7\nA1E8\nA1E9\nA1EA\nA1EB\nA1EC\nA1ED\nA1EE\nA1EF\nA1F0\nA1F1\nA1F2\nA1F3\nA1F4\nA1F5\nA1F6\nA1F7\nA1F8\nA1F9\nA1FA\nA1FB\nA1FC\nA1FD\nA1FE\nA1FF\nA200\nA201\nA202\nA203\nA204\nA205\nA206\nA207\nA208\nA209\nA20A\nA20B\nA20C\nA20D\nA20E\nA20F\nA210\nA211\nA212\nA213\nA214\nA215\nA216\nA217\nA218\nA219\nA21A\nA21B\nA21C\nA21D\nA21E\nA21F\nA220\nA221\nA222\nA223\nA224\nA225\nA226\nA227\nA228\nA229\nA22A\nA22B\nA22C\nA22D\nA22E\nA22F\nA230\nA231\nA232\nA233\nA234\nA235\nA236\nA237\nA238\nA239\nA23A\nA23B\nA23C\nA23D\nA23E\nA23F\nA240\nA241\nA242\nA243\nA244\nA245\nA246\nA247\nA248\nA249\nA24A\nA24B\nA24C\nA24D\nA24E\nA24F\nA250\nA251\nA252\nA253\nA254\nA255\nA256\nA257\nA258\nA259\nA25A\nA25B\nA25C\nA25D\nA25E\nA25F\nA260\nA261\nA262\nA263\nA264\nA265\nA266\nA267\nA268\nA269\nA26A\nA26B\nA26C\nA26D\nA26E\nA26F\nA270\nA271\nA272\nA273\nA274\nA275\nA276\nA277\nA278\nA279\nA27A\nA27B\nA27C\nA27D\nA27E\nA27F\nA280\nA281\nA282\nA283\nA284\nA285\nA286\nA287\nA288\nA289\nA28A\nA28B\nA28C\nA28D\nA28E\nA28F\nA290\nA291\nA292\nA293\nA294\nA295\nA296\nA297\nA298\nA299\nA29A\nA29B\nA29C\nA29D\nA29E\nA29F\nA2A0\nA2A1\nA2A2\nA2A3\nA2A4\nA2A5\nA2A6\nA2A7\nA2A8\nA2A9\nA2AA\nA2AB\nA2AC\nA2AD\nA2AE\nA2AF\nA2B0\nA2B1\nA2B2\nA2B3\nA2B4\nA2B5\nA2B6\nA2B7\nA2B8\nA2B9\nA2BA\nA2BB\nA2BC\nA2BD\nA2BE\nA2BF\nA2C0\nA2C1\nA2C2\nA2C3\nA2C4\nA2C5\nA2C6\nA2C7\nA2C8\nA2C9\nA2CA\nA2CB\nA2CC\nA2CD\nA2CE\nA2CF\nA2D0\nA2D1\nA2D2\nA2D3\nA2D4\nA2D5\nA2D6\nA2D7\nA2D8\nA2D9\nA2DA\nA2DB\nA2DC\nA2DD\nA2DE\nA2DF\nA2E0\nA2E1\nA2E2\nA2E3\nA2E4\nA2E5\nA2E6\nA2E7\nA2E8\nA2E9\nA2EA\nA2EB\nA2EC\nA2ED\nA2EE\nA2EF\nA2F0\nA2F1\nA2F2\nA2F3\nA2F4\nA2F5\nA2F6\nA2F7\nA2F8\nA2F9\nA2FA\nA2FB\nA2FC\nA2FD\nA2FE\nA2FF\nA300\nA301\nA302\nA303\nA304\nA305\nA306\nA307\nA308\nA309\nA30A\nA30B\nA30C\nA30D\nA30E\nA30F\nA310\nA311\nA312\nA313\nA314\nA315\nA316\nA317\nA318\nA319\nA31A\nA31B\nA31C\nA31D\nA31E\nA31F\nA320\nA321\nA322\nA323\nA324\nA325\nA326\nA327\nA328\nA329\nA32A\nA32B\nA32C\nA32D\nA32E\nA32F\nA330\nA331\nA332\nA333\nA334\nA335\nA336\nA337\nA338\nA339\nA33A\nA33B\nA33C\nA33D\nA33E\nA33F\nA340\nA341\nA342\nA343\nA344\nA345\nA346\nA347\nA348\nA349\nA34A\nA34B\nA34C\nA34D\nA34E\nA34F\nA350\nA351\nA352\nA353\nA354\nA355\nA356\nA357\nA358\nA359\nA35A\nA35B\nA35C\nA35D\nA35E\nA35F\nA360\nA361\nA362\nA363\nA364\nA365\nA366\nA367\nA368\nA369\nA36A\nA36B\nA36C\nA36D\nA36E\nA36F\nA370\nA371\nA372\nA373\nA374\nA375\nA376\nA377\nA378\nA379\nA37A\nA37B\nA37C\nA37D\nA37E\nA37F\nA380\nA381\nA382\nA383\nA384\nA385\nA386\nA387\nA388\nA389\nA38A\nA38B\nA38C\nA38D\nA38E\nA38F\nA390\nA391\nA392\nA393\nA394\nA395\nA396\nA397\nA398\nA399\nA39A\nA39B\nA39C\nA39D\nA39E\nA39F\nA3A0\nA3A1\nA3A2\nA3A3\nA3A4\nA3A5\nA3A6\nA3A7\nA3A8\nA3A9\nA3AA\nA3AB\nA3AC\nA3AD\nA3AE\nA3AF\nA3B0\nA3B1\nA3B2\nA3B3\nA3B4\nA3B5\nA3B6\nA3B7\nA3B8\nA3B9\nA3BA\nA3BB\nA3BC\nA3BD\nA3BE\nA3BF\nA3C0\nA3C1\nA3C2\nA3C3\nA3C4\nA3C5\nA3C6\nA3C7\nA3C8\nA3C9\nA3CA\nA3CB\nA3CC\nA3CD\nA3CE\nA3CF\nA3D0\nA3D1\nA3D2\nA3D3\nA3D4\nA3D5\nA3D6\nA3D7\nA3D8\nA3D9\nA3DA\nA3DB\nA3DC\nA3DD\nA3DE\nA3DF\nA3E0\nA3E1\nA3E2\nA3E3\nA3E4\nA3E5\nA3E6\nA3E7\nA3E8\nA3E9\nA3EA\nA3EB\nA3EC\nA3ED\nA3EE\nA3EF\nA3F0\nA3F1\nA3F2\nA3F3\nA3F4\nA3F5\nA3F6\nA3F7\nA3F8\nA3F9\nA3FA\nA3FB\nA3FC\nA3FD\nA3FE\nA3FF\nA400\nA401\nA402\nA403\nA404\nA405\nA406\nA407\nA408\nA409\nA40A\nA40B\nA40C\nA40D\nA40E\nA40F\nA410\nA411\nA412\nA413\nA414\nA415\nA416\nA417\nA418\nA419\nA41A\nA41B\nA41C\nA41D\nA41E\nA41F\nA420\nA421\nA422\nA423\nA424\nA425\nA426\nA427\nA428\nA429\nA42A\nA42B\nA42C\nA42D\nA42E\nA42F\nA430\nA431\nA432\nA433\nA434\nA435\nA436\nA437\nA438\nA439\nA43A\nA43B\nA43C\nA43D\nA43E\nA43F\nA440\nA441\nA442\nA443\nA444\nA445\nA446\nA447\nA448\nA449\nA44A\nA44B\nA44C\nA44D\nA44E\nA44F\nA450\nA451\nA452\nA453\nA454\nA455\nA456\nA457\nA458\nA459\nA45A\nA45B\nA45C\nA45D\nA45E\nA45F\nA460\nA461\nA462\nA463\nA464\nA465\nA466\nA467\nA468\nA469\nA46A\nA46B\nA46C\nA46D\nA46E\nA46F\nA470\nA471\nA472\nA473\nA474\nA475\nA476\nA477\nA478\nA479\nA47A\nA47B\nA47C\nA47D\nA47E\nA47F\nA480\nA481\nA482\nA483\nA484\nA485\nA486\nA487\nA488\nA489\nA48A\nA48B\nA48C\nA490\nA491\nA492\nA493\nA494\nA495\nA496\nA497\nA498\nA499\nA49A\nA49B\nA49C\nA49D\nA49E\nA49F\nA4A0\nA4A1\nA4A2\nA4A3\nA4A4\nA4A5\nA4A6\nA4A7\nA4A8\nA4A9\nA4AA\nA4AB\nA4AC\nA4AD\nA4AE\nA4AF\nA4B0\nA4B1\nA4B2\nA4B3\nA4B4\nA4B5\nA4B6\nA4B7\nA4B8\nA4B9\nA4BA\nA4BB\nA4BC\nA4BD\nA4BE\nA4BF\nA4C0\nA4C1\nA4C2\nA4C3\nA4C4\nA4C5\nA4C6\nA4D0\nA4D1\nA4D2\nA4D3\nA4D4\nA4D5\nA4D6\nA4D7\nA4D8\nA4D9\nA4DA\nA4DB\nA4DC\nA4DD\nA4DE\nA4DF\nA4E0\nA4E1\nA4E2\nA4E3\nA4E4\nA4E5\nA4E6\nA4E7\nA4E8\nA4E9\nA4EA\nA4EB\nA4EC\nA4ED\nA4EE\nA4EF\nA4F0\nA4F1\nA4F2\nA4F3\nA4F4\nA4F5\nA4F6\nA4F7\nA4F8\nA4F9\nA4FA\nA4FB\nA4FC\nA4FD\nA4FE\nA4FF\nA500\nA501\nA502\nA503\nA504\nA505\nA506\nA507\nA508\nA509\nA50A\nA50B\nA50C\nA50D\nA50E\nA50F\nA510\nA511\nA512\nA513\nA514\nA515\nA516\nA517\nA518\nA519\nA51A\nA51B\nA51C\nA51D\nA51E\nA51F\nA520\nA521\nA522\nA523\nA524\nA525\nA526\nA527\nA528\nA529\nA52A\nA52B\nA52C\nA52D\nA52E\nA52F\nA530\nA531\nA532\nA533\nA534\nA535\nA536\nA537\nA538\nA539\nA53A\nA53B\nA53C\nA53D\nA53E\nA53F\nA540\nA541\nA542\nA543\nA544\nA545\nA546\nA547\nA548\nA549\nA54A\nA54B\nA54C\nA54D\nA54E\nA54F\nA550\nA551\nA552\nA553\nA554\nA555\nA556\nA557\nA558\nA559\nA55A\nA55B\nA55C\nA55D\nA55E\nA55F\nA560\nA561\nA562\nA563\nA564\nA565\nA566\nA567\nA568\nA569\nA56A\nA56B\nA56C\nA56D\nA56E\nA56F\nA570\nA571\nA572\nA573\nA574\nA575\nA576\nA577\nA578\nA579\nA57A\nA57B\nA57C\nA57D\nA57E\nA57F\nA580\nA581\nA582\nA583\nA584\nA585\nA586\nA587\nA588\nA589\nA58A\nA58B\nA58C\nA58D\nA58E\nA58F\nA590\nA591\nA592\nA593\nA594\nA595\nA596\nA597\nA598\nA599\nA59A\nA59B\nA59C\nA59D\nA59E\nA59F\nA5A0\nA5A1\nA5A2\nA5A3\nA5A4\nA5A5\nA5A6\nA5A7\nA5A8\nA5A9\nA5AA\nA5AB\nA5AC\nA5AD\nA5AE\nA5AF\nA5B0\nA5B1\nA5B2\nA5B3\nA5B4\nA5B5\nA5B6\nA5B7\nA5B8\nA5B9\nA5BA\nA5BB\nA5BC\nA5BD\nA5BE\nA5BF\nA5C0\nA5C1\nA5C2\nA5C3\nA5C4\nA5C5\nA5C6\nA5C7\nA5C8\nA5C9\nA5CA\nA5CB\nA5CC\nA5CD\nA5CE\nA5CF\nA5D0\nA5D1\nA5D2\nA5D3\nA5D4\nA5D5\nA5D6\nA5D7\nA5D8\nA5D9\nA5DA\nA5DB\nA5DC\nA5DD\nA5DE\nA5DF\nA5E0\nA5E1\nA5E2\nA5E3\nA5E4\nA5E5\nA5E6\nA5E7\nA5E8\nA5E9\nA5EA\nA5EB\nA5EC\nA5ED\nA5EE\nA5EF\nA5F0\nA5F1\nA5F2\nA5F3\nA5F4\nA5F5\nA5F6\nA5F7\nA5F8\nA5F9\nA5FA\nA5FB\nA5FC\nA5FD\nA5FE\nA5FF\nA600\nA601\nA602\nA603\nA604\nA605\nA606\nA607\nA608\nA609\nA60A\nA60B\nA60C\nA60D\nA60E\nA60F\nA610\nA611\nA612\nA613\nA614\nA615\nA616\nA617\nA618\nA619\nA61A\nA61B\nA61C\nA61D\nA61E\nA61F\nA620\nA621\nA622\nA623\nA624\nA625\nA626\nA627\nA628\nA629\nA62A\nA62B\nA640\nA641\nA642\nA643\nA644\nA645\nA646\nA647\nA648\nA649\nA64A\nA64B\nA64C\nA64D\nA64E\nA64F\nA650\nA651\nA652\nA653\nA654\nA655\nA656\nA657\nA658\nA659\nA65A\nA65B\nA65C\nA65D\nA65E\nA65F\nA660\nA661\nA662\nA663\nA664\nA665\nA666\nA667\nA668\nA669\nA66A\nA66B\nA66C\nA66D\nA66E\nA66F\nA670\nA671\nA672\nA673\nA674\nA675\nA676\nA677\nA678\nA679\nA67A\nA67B\nA67C\nA67D\nA67E\nA67F\nA680\nA681\nA682\nA683\nA684\nA685\nA686\nA687\nA688\nA689\nA68A\nA68B\nA68C\nA68D\nA68E\nA68F\nA690\nA691\nA692\nA693\nA694\nA695\nA696\nA697\nA698\nA699\nA69A\nA69B\nA69C\nA69D\nA69F\nA6A0\nA6A1\nA6A2\nA6A3\nA6A4\nA6A5\nA6A6\nA6A7\nA6A8\nA6A9\nA6AA\nA6AB\nA6AC\nA6AD\nA6AE\nA6AF\nA6B0\nA6B1\nA6B2\nA6B3\nA6B4\nA6B5\nA6B6\nA6B7\nA6B8\nA6B9\nA6BA\nA6BB\nA6BC\nA6BD\nA6BE\nA6BF\nA6C0\nA6C1\nA6C2\nA6C3\nA6C4\nA6C5\nA6C6\nA6C7\nA6C8\nA6C9\nA6CA\nA6CB\nA6CC\nA6CD\nA6CE\nA6CF\nA6D0\nA6D1\nA6D2\nA6D3\nA6D4\nA6D5\nA6D6\nA6D7\nA6D8\nA6D9\nA6DA\nA6DB\nA6DC\nA6DD\nA6DE\nA6DF\nA6E0\nA6E1\nA6E2\nA6E3\nA6E4\nA6E5\nA6E6\nA6E7\nA6E8\nA6E9\nA6EA\nA6EB\nA6EC\nA6ED\nA6EE\nA6EF\nA6F0\nA6F1\nA6F2\nA6F3\nA6F4\nA6F5\nA6F6\nA6F7\nA700\nA701\nA702\nA703\nA704\nA705\nA706\nA707\nA708\nA709\nA70A\nA70B\nA70C\nA70D\nA70E\nA70F\nA710\nA711\nA712\nA713\nA714\nA715\nA716\nA717\nA718\nA719\nA71A\nA71B\nA71C\nA71D\nA71E\nA71F\nA720\nA721\nA722\nA723\nA724\nA725\nA726\nA727\nA728\nA729\nA72A\nA72B\nA72C\nA72D\nA72E\nA72F\nA730\nA731\nA732\nA733\nA734\nA735\nA736\nA737\nA738\nA739\nA73A\nA73B\nA73C\nA73D\nA73E\nA73F\nA740\nA741\nA742\nA743\nA744\nA745\nA746\nA747\nA748\nA749\nA74A\nA74B\nA74C\nA74D\nA74E\nA74F\nA750\nA751\nA752\nA753\nA754\nA755\nA756\nA757\nA758\nA759\nA75A\nA75B\nA75C\nA75D\nA75E\nA75F\nA760\nA761\nA762\nA763\nA764\nA765\nA766\nA767\nA768\nA769\nA76A\nA76B\nA76C\nA76D\nA76E\nA76F\nA770\nA771\nA772\nA773\nA774\nA775\nA776\nA777\nA778\nA779\nA77A\nA77B\nA77C\nA77D\nA77E\nA77F\nA780\nA781\nA782\nA783\nA784\nA785\nA786\nA787\nA788\nA789\nA78A\nA78B\nA78C\nA78D\nA78E\nA790\nA791\nA792\nA793\nA794\nA795\nA796\nA797\nA798\nA799\nA79A\nA79B\nA79C\nA79D\nA79E\nA79F\nA7A0\nA7A1\nA7A2\nA7A3\nA7A4\nA7A5\nA7A6\nA7A7\nA7A8\nA7A9\nA7AA\nA7AB\nA7AC\nA7AD\nA7B0\nA7B1\nA7F7\nA7F8\nA7F9\nA7FA\nA7FB\nA7FC\nA7FD\nA7FE\nA7FF\nA800\nA801\nA802\nA803\nA804\nA805\nA806\nA807\nA808\nA809\nA80A\nA80B\nA80C\nA80D\nA80E\nA80F\nA810\nA811\nA812\nA813\nA814\nA815\nA816\nA817\nA818\nA819\nA81A\nA81B\nA81C\nA81D\nA81E\nA81F\nA820\nA821\nA822\nA823\nA824\nA825\nA826\nA827\nA828\nA829\nA82A\nA82B\nA830\nA831\nA832\nA833\nA834\nA835\nA836\nA837\nA838\nA839\nA840\nA841\nA842\nA843\nA844\nA845\nA846\nA847\nA848\nA849\nA84A\nA84B\nA84C\nA84D\nA84E\nA84F\nA850\nA851\nA852\nA853\nA854\nA855\nA856\nA857\nA858\nA859\nA85A\nA85B\nA85C\nA85D\nA85E\nA85F\nA860\nA861\nA862\nA863\nA864\nA865\nA866\nA867\nA868\nA869\nA86A\nA86B\nA86C\nA86D\nA86E\nA86F\nA870\nA871\nA872\nA873\nA874\nA875\nA876\nA877\nA880\nA881\nA882\nA883\nA884\nA885\nA886\nA887\nA888\nA889\nA88A\nA88B\nA88C\nA88D\nA88E\nA88F\nA890\nA891\nA892\nA893\nA894\nA895\nA896\nA897\nA898\nA899\nA89A\nA89B\nA89C\nA89D\nA89E\nA89F\nA8A0\nA8A1\nA8A2\nA8A3\nA8A4\nA8A5\nA8A6\nA8A7\nA8A8\nA8A9\nA8AA\nA8AB\nA8AC\nA8AD\nA8AE\nA8AF\nA8B0\nA8B1\nA8B2\nA8B3\nA8B4\nA8B5\nA8B6\nA8B7\nA8B8\nA8B9\nA8BA\nA8BB\nA8BC\nA8BD\nA8BE\nA8BF\nA8C0\nA8C1\nA8C2\nA8C3\nA8C4\nA8CE\nA8CF\nA8D0\nA8D1\nA8D2\nA8D3\nA8D4\nA8D5\nA8D6\nA8D7\nA8D8\nA8D9\nA8E0\nA8E1\nA8E2\nA8E3\nA8E4\nA8E5\nA8E6\nA8E7\nA8E8\nA8E9\nA8EA\nA8EB\nA8EC\nA8ED\nA8EE\nA8EF\nA8F0\nA8F1\nA8F2\nA8F3\nA8F4\nA8F5\nA8F6\nA8F7\nA8F8\nA8F9\nA8FA\nA8FB\nA900\nA901\nA902\nA903\nA904\nA905\nA906\nA907\nA908\nA909\nA90A\nA90B\nA90C\nA90D\nA90E\nA90F\nA910\nA911\nA912\nA913\nA914\nA915\nA916\nA917\nA918\nA919\nA91A\nA91B\nA91C\nA91D\nA91E\nA91F\nA920\nA921\nA922\nA923\nA924\nA925\nA926\nA927\nA928\nA929\nA92A\nA92B\nA92C\nA92D\nA92E\nA92F\nA930\nA931\nA932\nA933\nA934\nA935\nA936\nA937\nA938\nA939\nA93A\nA93B\nA93C\nA93D\nA93E\nA93F\nA940\nA941\nA942\nA943\nA944\nA945\nA946\nA947\nA948\nA949\nA94A\nA94B\nA94C\nA94D\nA94E\nA94F\nA950\nA951\nA952\nA953\nA95F\nA960\nA961\nA962\nA963\nA964\nA965\nA966\nA967\nA968\nA969\nA96A\nA96B\nA96C\nA96D\nA96E\nA96F\nA970\nA971\nA972\nA973\nA974\nA975\nA976\nA977\nA978\nA979\nA97A\nA97B\nA97C\nA980\nA981\nA982\nA983\nA984\nA985\nA986\nA987\nA988\nA989\nA98A\nA98B\nA98C\nA98D\nA98E\nA98F\nA990\nA991\nA992\nA993\nA994\nA995\nA996\nA997\nA998\nA999\nA99A\nA99B\nA99C\nA99D\nA99E\nA99F\nA9A0\nA9A1\nA9A2\nA9A3\nA9A4\nA9A5\nA9A6\nA9A7\nA9A8\nA9A9\nA9AA\nA9AB\nA9AC\nA9AD\nA9AE\nA9AF\nA9B0\nA9B1\nA9B2\nA9B3\nA9B4\nA9B5\nA9B6\nA9B7\nA9B8\nA9B9\nA9BA\nA9BB\nA9BC\nA9BD\nA9BE\nA9BF\nA9C0\nA9C1\nA9C2\nA9C3\nA9C4\nA9C5\nA9C6\nA9C7\nA9C8\nA9C9\nA9CA\nA9CB\nA9CC\nA9CD\nA9CF\nA9D0\nA9D1\nA9D2\nA9D3\nA9D4\nA9D5\nA9D6\nA9D7\nA9D8\nA9D9\nA9DE\nA9DF\nA9E0\nA9E1\nA9E2\nA9E3\nA9E4\nA9E5\nA9E6\nA9E7\nA9E8\nA9E9\nA9EA\nA9EB\nA9EC\nA9ED\nA9EE\nA9EF\nA9F0\nA9F1\nA9F2\nA9F3\nA9F4\nA9F5\nA9F6\nA9F7\nA9F8\nA9F9\nA9FA\nA9FB\nA9FC\nA9FD\nA9FE\nAA00\nAA01\nAA02\nAA03\nAA04\nAA05\nAA06\nAA07\nAA08\nAA09\nAA0A\nAA0B\nAA0C\nAA0D\nAA0E\nAA0F\nAA10\nAA11\nAA12\nAA13\nAA14\nAA15\nAA16\nAA17\nAA18\nAA19\nAA1A\nAA1B\nAA1C\nAA1D\nAA1E\nAA1F\nAA20\nAA21\nAA22\nAA23\nAA24\nAA25\nAA26\nAA27\nAA28\nAA29\nAA2A\nAA2B\nAA2C\nAA2D\nAA2E\nAA2F\nAA30\nAA31\nAA32\nAA33\nAA34\nAA35\nAA36\nAA40\nAA41\nAA42\nAA43\nAA44\nAA45\nAA46\nAA47\nAA48\nAA49\nAA4A\nAA4B\nAA4C\nAA4D\nAA50\nAA51\nAA52\nAA53\nAA54\nAA55\nAA56\nAA57\nAA58\nAA59\nAA5C\nAA5D\nAA5E\nAA5F\nAA60\nAA61\nAA62\nAA63\nAA64\nAA65\nAA66\nAA67\nAA68\nAA69\nAA6A\nAA6B\nAA6C\nAA6D\nAA6E\nAA6F\nAA70\nAA71\nAA72\nAA73\nAA74\nAA75\nAA76\nAA77\nAA78\nAA79\nAA7A\nAA7B\nAA7C\nAA7D\nAA7E\nAA7F\nAA80\nAA81\nAA82\nAA83\nAA84\nAA85\nAA86\nAA87\nAA88\nAA89\nAA8A\nAA8B\nAA8C\nAA8D\nAA8E\nAA8F\nAA90\nAA91\nAA92\nAA93\nAA94\nAA95\nAA96\nAA97\nAA98\nAA99\nAA9A\nAA9B\nAA9C\nAA9D\nAA9E\nAA9F\nAAA0\nAAA1\nAAA2\nAAA3\nAAA4\nAAA5\nAAA6\nAAA7\nAAA8\nAAA9\nAAAA\nAAAB\nAAAC\nAAAD\nAAAE\nAAAF\nAAB0\nAAB1\nAAB2\nAAB3\nAAB4\nAAB5\nAAB6\nAAB7\nAAB8\nAAB9\nAABA\nAABB\nAABC\nAABD\nAABE\nAABF\nAAC0\nAAC1\nAAC2\nAADB\nAADC\nAADD\nAADE\nAADF\nAAE0\nAAE1\nAAE2\nAAE3\nAAE4\nAAE5\nAAE6\nAAE7\nAAE8\nAAE9\nAAEA\nAAEB\nAAEC\nAAED\nAAEE\nAAEF\nAAF0\nAAF1\nAAF2\nAAF3\nAAF4\nAAF5\nAAF6\nAB01\nAB02\nAB03\nAB04\nAB05\nAB06\nAB09\nAB0A\nAB0B\nAB0C\nAB0D\nAB0E\nAB11\nAB12\nAB13\nAB14\nAB15\nAB16\nAB20\nAB21\nAB22\nAB23\nAB24\nAB25\nAB26\nAB28\nAB29\nAB2A\nAB2B\nAB2C\nAB2D\nAB2E\nAB30\nAB31\nAB32\nAB33\nAB34\nAB35\nAB36\nAB37\nAB38\nAB39\nAB3A\nAB3B\nAB3C\nAB3D\nAB3E\nAB3F\nAB40\nAB41\nAB42\nAB43\nAB44\nAB45\nAB46\nAB47\nAB48\nAB49\nAB4A\nAB4B\nAB4C\nAB4D\nAB4E\nAB4F\nAB50\nAB51\nAB52\nAB53\nAB54\nAB55\nAB56\nAB57\nAB58\nAB59\nAB5A\nAB5B\nAB5C\nAB5D\nAB5E\nAB5F\nAB64\nAB65\nABC0\nABC1\nABC2\nABC3\nABC4\nABC5\nABC6\nABC7\nABC8\nABC9\nABCA\nABCB\nABCC\nABCD\nABCE\nABCF\nABD0\nABD1\nABD2\nABD3\nABD4\nABD5\nABD6\nABD7\nABD8\nABD9\nABDA\nABDB\nABDC\nABDD\nABDE\nABDF\nABE0\nABE1\nABE2\nABE3\nABE4\nABE5\nABE6\nABE7\nABE8\nABE9\nABEA\nABEB\nABEC\nABED\nABF0\nABF1\nABF2\nABF3\nABF4\nABF5\nABF6\nABF7\nABF8\nABF9\nAC00\nD7A3\nD7B0\nD7B1\nD7B2\nD7B3\nD7B4\nD7B5\nD7B6\nD7B7\nD7B8\nD7B9\nD7BA\nD7BB\nD7BC\nD7BD\nD7BE\nD7BF\nD7C0\nD7C1\nD7C2\nD7C3\nD7C4\nD7C5\nD7C6\nD7CB\nD7CC\nD7CD\nD7CE\nD7CF\nD7D0\nD7D1\nD7D2\nD7D3\nD7D4\nD7D5\nD7D6\nD7D7\nD7D8\nD7D9\nD7DA\nD7DB\nD7DC\nD7DD\nD7DE\nD7DF\nD7E0\nD7E1\nD7E2\nD7E3\nD7E4\nD7E5\nD7E6\nD7E7\nD7E8\nD7E9\nD7EA\nD7EB\nD7EC\nD7ED\nD7EE\nD7EF\nD7F0\nD7F1\nD7F2\nD7F3\nD7F4\nD7F5\nD7F6\nD7F7\nD7F8\nD7F9\nD7FA\nD7FB\nE000\nF8FF\nF900\nF901\nF902\nF903\nF904\nF905\nF906\nF907\nF908\nF909\nF90A\nF90B\nF90C\nF90D\nF90E\nF90F\nF910\nF911\nF912\nF913\nF914\nF915\nF916\nF917\nF918\nF919\nF91A\nF91B\nF91C\nF91D\nF91E\nF91F\nF920\nF921\nF922\nF923\nF924\nF925\nF926\nF927\nF928\nF929\nF92A\nF92B\nF92C\nF92D\nF92E\nF92F\nF930\nF931\nF932\nF933\nF934\nF935\nF936\nF937\nF938\nF939\nF93A\nF93B\nF93C\nF93D\nF93E\nF93F\nF940\nF941\nF942\nF943\nF944\nF945\nF946\nF947\nF948\nF949\nF94A\nF94B\nF94C\nF94D\nF94E\nF94F\nF950\nF951\nF952\nF953\nF954\nF955\nF956\nF957\nF958\nF959\nF95A\nF95B\nF95C\nF95D\nF95E\nF95F\nF960\nF961\nF962\nF963\nF964\nF965\nF966\nF967\nF968\nF969\nF96A\nF96B\nF96C\nF96D\nF96E\nF96F\nF970\nF971\nF972\nF973\nF974\nF975\nF976\nF977\nF978\nF979\nF97A\nF97B\nF97C\nF97D\nF97E\nF97F\nF980\nF981\nF982\nF983\nF984\nF985\nF986\nF987\nF988\nF989\nF98A\nF98B\nF98C\nF98D\nF98E\nF98F\nF990\nF991\nF992\nF993\nF994\nF995\nF996\nF997\nF998\nF999\nF99A\nF99B\nF99C\nF99D\nF99E\nF99F\nF9A0\nF9A1\nF9A2\nF9A3\nF9A4\nF9A5\nF9A6\nF9A7\nF9A8\nF9A9\nF9AA\nF9AB\nF9AC\nF9AD\nF9AE\nF9AF\nF9B0\nF9B1\nF9B2\nF9B3\nF9B4\nF9B5\nF9B6\nF9B7\nF9B8\nF9B9\nF9BA\nF9BB\nF9BC\nF9BD\nF9BE\nF9BF\nF9C0\nF9C1\nF9C2\nF9C3\nF9C4\nF9C5\nF9C6\nF9C7\nF9C8\nF9C9\nF9CA\nF9CB\nF9CC\nF9CD\nF9CE\nF9CF\nF9D0\nF9D1\nF9D2\nF9D3\nF9D4\nF9D5\nF9D6\nF9D7\nF9D8\nF9D9\nF9DA\nF9DB\nF9DC\nF9DD\nF9DE\nF9DF\nF9E0\nF9E1\nF9E2\nF9E3\nF9E4\nF9E5\nF9E6\nF9E7\nF9E8\nF9E9\nF9EA\nF9EB\nF9EC\nF9ED\nF9EE\nF9EF\nF9F0\nF9F1\nF9F2\nF9F3\nF9F4\nF9F5\nF9F6\nF9F7\nF9F8\nF9F9\nF9FA\nF9FB\nF9FC\nF9FD\nF9FE\nF9FF\nFA00\nFA01\nFA02\nFA03\nFA04\nFA05\nFA06\nFA07\nFA08\nFA09\nFA0A\nFA0B\nFA0C\nFA0D\nFA0E\nFA0F\nFA10\nFA11\nFA12\nFA13\nFA14\nFA15\nFA16\nFA17\nFA18\nFA19\nFA1A\nFA1B\nFA1C\nFA1D\nFA1E\nFA1F\nFA20\nFA21\nFA22\nFA23\nFA24\nFA25\nFA26\nFA27\nFA28\nFA29\nFA2A\nFA2B\nFA2C\nFA2D\nFA2E\nFA2F\nFA30\nFA31\nFA32\nFA33\nFA34\nFA35\nFA36\nFA37\nFA38\nFA39\nFA3A\nFA3B\nFA3C\nFA3D\nFA3E\nFA3F\nFA40\nFA41\nFA42\nFA43\nFA44\nFA45\nFA46\nFA47\nFA48\nFA49\nFA4A\nFA4B\nFA4C\nFA4D\nFA4E\nFA4F\nFA50\nFA51\nFA52\nFA53\nFA54\nFA55\nFA56\nFA57\nFA58\nFA59\nFA5A\nFA5B\nFA5C\nFA5D\nFA5E\nFA5F\nFA60\nFA61\nFA62\nFA63\nFA64\nFA65\nFA66\nFA67\nFA68\nFA69\nFA6A\nFA6B\nFA6C\nFA6D\nFA70\nFA71\nFA72\nFA73\nFA74\nFA75\nFA76\nFA77\nFA78\nFA79\nFA7A\nFA7B\nFA7C\nFA7D\nFA7E\nFA7F\nFA80\nFA81\nFA82\nFA83\nFA84\nFA85\nFA86\nFA87\nFA88\nFA89\nFA8A\nFA8B\nFA8C\nFA8D\nFA8E\nFA8F\nFA90\nFA91\nFA92\nFA93\nFA94\nFA95\nFA96\nFA97\nFA98\nFA99\nFA9A\nFA9B\nFA9C\nFA9D\nFA9E\nFA9F\nFAA0\nFAA1\nFAA2\nFAA3\nFAA4\nFAA5\nFAA6\nFAA7\nFAA8\nFAA9\nFAAA\nFAAB\nFAAC\nFAAD\nFAAE\nFAAF\nFAB0\nFAB1\nFAB2\nFAB3\nFAB4\nFAB5\nFAB6\nFAB7\nFAB8\nFAB9\nFABA\nFABB\nFABC\nFABD\nFABE\nFABF\nFAC0\nFAC1\nFAC2\nFAC3\nFAC4\nFAC5\nFAC6\nFAC7\nFAC8\nFAC9\nFACA\nFACB\nFACC\nFACD\nFACE\nFACF\nFAD0\nFAD1\nFAD2\nFAD3\nFAD4\nFAD5\nFAD6\nFAD7\nFAD8\nFAD9\nFB00\nFB01\nFB02\nFB03\nFB04\nFB05\nFB06\nFB13\nFB14\nFB15\nFB16\nFB17\nFB1D\nFB1E\nFB1F\nFB20\nFB21\nFB22\nFB23\nFB24\nFB25\nFB26\nFB27\nFB28\nFB29\nFB2A\nFB2B\nFB2C\nFB2D\nFB2E\nFB2F\nFB30\nFB31\nFB32\nFB33\nFB34\nFB35\nFB36\nFB38\nFB39\nFB3A\nFB3B\nFB3C\nFB3E\nFB40\nFB41\nFB43\nFB44\nFB46\nFB47\nFB48\nFB49\nFB4A\nFB4B\nFB4C\nFB4D\nFB4E\nFB4F\nFB50\nFB51\nFB52\nFB53\nFB54\nFB55\nFB56\nFB57\nFB58\nFB59\nFB5A\nFB5B\nFB5C\nFB5D\nFB5E\nFB5F\nFB60\nFB61\nFB62\nFB63\nFB64\nFB65\nFB66\nFB67\nFB68\nFB69\nFB6A\nFB6B\nFB6C\nFB6D\nFB6E\nFB6F\nFB70\nFB71\nFB72\nFB73\nFB74\nFB75\nFB76\nFB77\nFB78\nFB79\nFB7A\nFB7B\nFB7C\nFB7D\nFB7E\nFB7F\nFB80\nFB81\nFB82\nFB83\nFB84\nFB85\nFB86\nFB87\nFB88\nFB89\nFB8A\nFB8B\nFB8C\nFB8D\nFB8E\nFB8F\nFB90\nFB91\nFB92\nFB93\nFB94\nFB95\nFB96\nFB97\nFB98\nFB99\nFB9A\nFB9B\nFB9C\nFB9D\nFB9E\nFB9F\nFBA0\nFBA1\nFBA2\nFBA3\nFBA4\nFBA5\nFBA6\nFBA7\nFBA8\nFBA9\nFBAA\nFBAB\nFBAC\nFBAD\nFBAE\nFBAF\nFBB0\nFBB1\nFBB2\nFBB3\nFBB4\nFBB5\nFBB6\nFBB7\nFBB8\nFBB9\nFBBA\nFBBB\nFBBC\nFBBD\nFBBE\nFBBF\nFBC0\nFBC1\nFBD3\nFBD4\nFBD5\nFBD6\nFBD7\nFBD8\nFBD9\nFBDA\nFBDB\nFBDC\nFBDD\nFBDE\nFBDF\nFBE0\nFBE1\nFBE2\nFBE3\nFBE4\nFBE5\nFBE6\nFBE7\nFBE8\nFBE9\nFBEA\nFBEB\nFBEC\nFBED\nFBEE\nFBEF\nFBF0\nFBF1\nFBF2\nFBF3\nFBF4\nFBF5\nFBF6\nFBF7\nFBF8\nFBF9\nFBFA\nFBFB\nFBFC\nFBFD\nFBFE\nFBFF\nFC00\nFC01\nFC02\nFC03\nFC04\nFC05\nFC06\nFC07\nFC08\nFC09\nFC0A\nFC0B\nFC0C\nFC0D\nFC0E\nFC0F\nFC10\nFC11\nFC12\nFC13\nFC14\nFC15\nFC16\nFC17\nFC18\nFC19\nFC1A\nFC1B\nFC1C\nFC1D\nFC1E\nFC1F\nFC20\nFC21\nFC22\nFC23\nFC24\nFC25\nFC26\nFC27\nFC28\nFC29\nFC2A\nFC2B\nFC2C\nFC2D\nFC2E\nFC2F\nFC30\nFC31\nFC32\nFC33\nFC34\nFC35\nFC36\nFC37\nFC38\nFC39\nFC3A\nFC3B\nFC3C\nFC3D\nFC3E\nFC3F\nFC40\nFC41\nFC42\nFC43\nFC44\nFC45\nFC46\nFC47\nFC48\nFC49\nFC4A\nFC4B\nFC4C\nFC4D\nFC4E\nFC4F\nFC50\nFC51\nFC52\nFC53\nFC54\nFC55\nFC56\nFC57\nFC58\nFC59\nFC5A\nFC5B\nFC5C\nFC5D\nFC5E\nFC5F\nFC60\nFC61\nFC62\nFC63\nFC64\nFC65\nFC66\nFC67\nFC68\nFC69\nFC6A\nFC6B\nFC6C\nFC6D\nFC6E\nFC6F\nFC70\nFC71\nFC72\nFC73\nFC74\nFC75\nFC76\nFC77\nFC78\nFC79\nFC7A\nFC7B\nFC7C\nFC7D\nFC7E\nFC7F\nFC80\nFC81\nFC82\nFC83\nFC84\nFC85\nFC86\nFC87\nFC88\nFC89\nFC8A\nFC8B\nFC8C\nFC8D\nFC8E\nFC8F\nFC90\nFC91\nFC92\nFC93\nFC94\nFC95\nFC96\nFC97\nFC98\nFC99\nFC9A\nFC9B\nFC9C\nFC9D\nFC9E\nFC9F\nFCA0\nFCA1\nFCA2\nFCA3\nFCA4\nFCA5\nFCA6\nFCA7\nFCA8\nFCA9\nFCAA\nFCAB\nFCAC\nFCAD\nFCAE\nFCAF\nFCB0\nFCB1\nFCB2\nFCB3\nFCB4\nFCB5\nFCB6\nFCB7\nFCB8\nFCB9\nFCBA\nFCBB\nFCBC\nFCBD\nFCBE\nFCBF\nFCC0\nFCC1\nFCC2\nFCC3\nFCC4\nFCC5\nFCC6\nFCC7\nFCC8\nFCC9\nFCCA\nFCCB\nFCCC\nFCCD\nFCCE\nFCCF\nFCD0\nFCD1\nFCD2\nFCD3\nFCD4\nFCD5\nFCD6\nFCD7\nFCD8\nFCD9\nFCDA\nFCDB\nFCDC\nFCDD\nFCDE\nFCDF\nFCE0\nFCE1\nFCE2\nFCE3\nFCE4\nFCE5\nFCE6\nFCE7\nFCE8\nFCE9\nFCEA\nFCEB\nFCEC\nFCED\nFCEE\nFCEF\nFCF0\nFCF1\nFCF2\nFCF3\nFCF4\nFCF5\nFCF6\nFCF7\nFCF8\nFCF9\nFCFA\nFCFB\nFCFC\nFCFD\nFCFE\nFCFF\nFD00\nFD01\nFD02\nFD03\nFD04\nFD05\nFD06\nFD07\nFD08\nFD09\nFD0A\nFD0B\nFD0C\nFD0D\nFD0E\nFD0F\nFD10\nFD11\nFD12\nFD13\nFD14\nFD15\nFD16\nFD17\nFD18\nFD19\nFD1A\nFD1B\nFD1C\nFD1D\nFD1E\nFD1F\nFD20\nFD21\nFD22\nFD23\nFD24\nFD25\nFD26\nFD27\nFD28\nFD29\nFD2A\nFD2B\nFD2C\nFD2D\nFD2E\nFD2F\nFD30\nFD31\nFD32\nFD33\nFD34\nFD35\nFD36\nFD37\nFD38\nFD39\nFD3A\nFD3B\nFD3C\nFD3D\nFD3E\nFD3F\nFD50\nFD51\nFD52\nFD53\nFD54\nFD55\nFD56\nFD57\nFD58\nFD59\nFD5A\nFD5B\nFD5C\nFD5D\nFD5E\nFD5F\nFD60\nFD61\nFD62\nFD63\nFD64\nFD65\nFD66\nFD67\nFD68\nFD69\nFD6A\nFD6B\nFD6C\nFD6D\nFD6E\nFD6F\nFD70\nFD71\nFD72\nFD73\nFD74\nFD75\nFD76\nFD77\nFD78\nFD79\nFD7A\nFD7B\nFD7C\nFD7D\nFD7E\nFD7F\nFD80\nFD81\nFD82\nFD83\nFD84\nFD85\nFD86\nFD87\nFD88\nFD89\nFD8A\nFD8B\nFD8C\nFD8D\nFD8E\nFD8F\nFD92\nFD93\nFD94\nFD95\nFD96\nFD97\nFD98\nFD99\nFD9A\nFD9B\nFD9C\nFD9D\nFD9E\nFD9F\nFDA0\nFDA1\nFDA2\nFDA3\nFDA4\nFDA5\nFDA6\nFDA7\nFDA8\nFDA9\nFDAA\nFDAB\nFDAC\nFDAD\nFDAE\nFDAF\nFDB0\nFDB1\nFDB2\nFDB3\nFDB4\nFDB5\nFDB6\nFDB7\nFDB8\nFDB9\nFDBA\nFDBB\nFDBC\nFDBD\nFDBE\nFDBF\nFDC0\nFDC1\nFDC2\nFDC3\nFDC4\nFDC5\nFDC6\nFDC7\nFDF0\nFDF1\nFDF2\nFDF3\nFDF4\nFDF5\nFDF6\nFDF7\nFDF8\nFDF9\nFDFA\nFDFB\nFDFC\nFDFD\nFE00\nFE01\nFE02\nFE03\nFE04\nFE05\nFE06\nFE07\nFE08\nFE09\nFE0A\nFE0B\nFE0C\nFE0D\nFE0E\nFE0F\nFE10\nFE11\nFE12\nFE13\nFE14\nFE15\nFE16\nFE17\nFE18\nFE19\nFE20\nFE21\nFE22\nFE23\nFE24\nFE25\nFE26\nFE27\nFE28\nFE29\nFE2A\nFE2B\nFE2C\nFE2D\nFE30\nFE31\nFE32\nFE33\nFE34\nFE35\nFE36\nFE37\nFE38\nFE39\nFE3A\nFE3B\nFE3C\nFE3D\nFE3E\nFE3F\nFE40\nFE41\nFE42\nFE43\nFE44\nFE45\nFE46\nFE47\nFE48\nFE49\nFE4A\nFE4B\nFE4C\nFE4D\nFE4E\nFE4F\nFE50\nFE51\nFE52\nFE54\nFE55\nFE56\nFE57\nFE58\nFE59\nFE5A\nFE5B\nFE5C\nFE5D\nFE5E\nFE5F\nFE60\nFE61\nFE62\nFE63\nFE64\nFE65\nFE66\nFE68\nFE69\nFE6A\nFE6B\nFE70\nFE71\nFE72\nFE73\nFE74\nFE76\nFE77\nFE78\nFE79\nFE7A\nFE7B\nFE7C\nFE7D\nFE7E\nFE7F\nFE80\nFE81\nFE82\nFE83\nFE84\nFE85\nFE86\nFE87\nFE88\nFE89\nFE8A\nFE8B\nFE8C\nFE8D\nFE8E\nFE8F\nFE90\nFE91\nFE92\nFE93\nFE94\nFE95\nFE96\nFE97\nFE98\nFE99\nFE9A\nFE9B\nFE9C\nFE9D\nFE9E\nFE9F\nFEA0\nFEA1\nFEA2\nFEA3\nFEA4\nFEA5\nFEA6\nFEA7\nFEA8\nFEA9\nFEAA\nFEAB\nFEAC\nFEAD\nFEAE\nFEAF\nFEB0\nFEB1\nFEB2\nFEB3\nFEB4\nFEB5\nFEB6\nFEB7\nFEB8\nFEB9\nFEBA\nFEBB\nFEBC\nFEBD\nFEBE\nFEBF\nFEC0\nFEC1\nFEC2\nFEC3\nFEC4\nFEC5\nFEC6\nFEC7\nFEC8\nFEC9\nFECA\nFECB\nFECC\nFECD\nFECE\nFECF\nFED0\nFED1\nFED2\nFED3\nFED4\nFED5\nFED6\nFED7\nFED8\nFED9\nFEDA\nFEDB\nFEDC\nFEDD\nFEDE\nFEDF\nFEE0\nFEE1\nFEE2\nFEE3\nFEE4\nFEE5\nFEE6\nFEE7\nFEE8\nFEE9\nFEEA\nFEEB\nFEEC\nFEED\nFEEE\nFEEF\nFEF0\nFEF1\nFEF2\nFEF3\nFEF4\nFEF5\nFEF6\nFEF7\nFEF8\nFEF9\nFEFA\nFEFB\nFEFC\nFEFF\nFF01\nFF02\nFF03\nFF04\nFF05\nFF06\nFF07\nFF08\nFF09\nFF0A\nFF0B\nFF0C\nFF0D\nFF0E\nFF0F\nFF10\nFF11\nFF12\nFF13\nFF14\nFF15\nFF16\nFF17\nFF18\nFF19\nFF1A\nFF1B\nFF1C\nFF1D\nFF1E\nFF1F\nFF20\nFF21\nFF22\nFF23\nFF24\nFF25\nFF26\nFF27\nFF28\nFF29\nFF2A\nFF2B\nFF2C\nFF2D\nFF2E\nFF2F\nFF30\nFF31\nFF32\nFF33\nFF34\nFF35\nFF36\nFF37\nFF38\nFF39\nFF3A\nFF3B\nFF3C\nFF3D\nFF3E\nFF3F\nFF40\nFF41\nFF42\nFF43\nFF44\nFF45\nFF46\nFF47\nFF48\nFF49\nFF4A\nFF4B\nFF4C\nFF4D\nFF4E\nFF4F\nFF50\nFF51\nFF52\nFF53\nFF54\nFF55\nFF56\nFF57\nFF58\nFF59\nFF5A\nFF5B\nFF5C\nFF5D\nFF5E\nFF5F\nFF60\nFF61\nFF62\nFF63\nFF64\nFF65\nFF66\nFF67\nFF68\nFF69\nFF6A\nFF6B\nFF6C\nFF6D\nFF6E\nFF6F\nFF70\nFF71\nFF72\nFF73\nFF74\nFF75\nFF76\nFF77\nFF78\nFF79\nFF7A\nFF7B\nFF7C\nFF7D\nFF7E\nFF7F\nFF80\nFF81\nFF82\nFF83\nFF84\nFF85\nFF86\nFF87\nFF88\nFF89\nFF8A\nFF8B\nFF8C\nFF8D\nFF8E\nFF8F\nFF90\nFF91\nFF92\nFF93\nFF94\nFF95\nFF96\nFF97\nFF98\nFF99\nFF9A\nFF9B\nFF9C\nFF9D\nFF9E\nFF9F\nFFA0\nFFA1\nFFA2\nFFA3\nFFA4\nFFA5\nFFA6\nFFA7\nFFA8\nFFA9\nFFAA\nFFAB\nFFAC\nFFAD\nFFAE\nFFAF\nFFB0\nFFB1\nFFB2\nFFB3\nFFB4\nFFB5\nFFB6\nFFB7\nFFB8\nFFB9\nFFBA\nFFBB\nFFBC\nFFBD\nFFBE\nFFC2\nFFC3\nFFC4\nFFC5\nFFC6\nFFC7\nFFCA\nFFCB\nFFCC\nFFCD\nFFCE\nFFCF\nFFD2\nFFD3\nFFD4\nFFD5\nFFD6\nFFD7\nFFDA\nFFDB\nFFDC\nFFE0\nFFE1\nFFE2\nFFE3\nFFE4\nFFE5\nFFE6\nFFE8\nFFE9\nFFEA\nFFEB\nFFEC\nFFED\nFFEE\nFFF9\nFFFA\nFFFB\nFFFC\nFFFD\n10000\n10001\n10002\n10003\n10004\n10005\n10006\n10007\n10008\n10009\n1000A\n1000B\n1000D\n1000E\n1000F\n10010\n10011\n10012\n10013\n10014\n10015\n10016\n10017\n10018\n10019\n1001A\n1001B\n1001C\n1001D\n1001E\n1001F\n10020\n10021\n10022\n10023\n10024\n10025\n10026\n10028\n10029\n1002A\n1002B\n1002C\n1002D\n1002E\n1002F\n10030\n10031\n10032\n10033\n10034\n10035\n10036\n10037\n10038\n10039\n1003A\n1003C\n1003D\n1003F\n10040\n10041\n10042\n10043\n10044\n10045\n10046\n10047\n10048\n10049\n1004A\n1004B\n1004C\n1004D\n10050\n10051\n10052\n10053\n10054\n10055\n10056\n10057\n10058\n10059\n1005A\n1005B\n1005C\n1005D\n10080\n10081\n10082\n10083\n10084\n10085\n10086\n10087\n10088\n10089\n1008A\n1008B\n1008C\n1008D\n1008E\n1008F\n10090\n10091\n10092\n10093\n10094\n10095\n10096\n10097\n10098\n10099\n1009A\n1009B\n1009C\n1009D\n1009E\n1009F\n100A0\n100A1\n100A2\n100A3\n100A4\n100A5\n100A6\n100A7\n100A8\n100A9\n100AA\n100AB\n100AC\n100AD\n100AE\n100AF\n100B0\n100B1\n100B2\n100B3\n100B4\n100B5\n100B6\n100B7\n100B8\n100B9\n100BA\n100BB\n100BC\n100BD\n100BE\n100BF\n100C0\n100C1\n100C2\n100C3\n100C4\n100C5\n100C6\n100C7\n100C8\n100C9\n100CA\n100CB\n100CC\n100CD\n100CE\n100CF\n100D0\n100D1\n100D2\n100D3\n100D4\n100D5\n100D6\n100D7\n100D8\n100D9\n100DA\n100DB\n100DC\n100DD\n100DE\n100DF\n100E0\n100E1\n100E2\n100E3\n100E4\n100E5\n100E6\n100E7\n100E8\n100E9\n100EA\n100EB\n100EC\n100ED\n100EE\n100EF\n100F0\n100F1\n100F2\n100F3\n100F4\n100F5\n100F6\n100F7\n100F8\n100F9\n100FA\n10100\n10101\n10102\n10107\n10108\n10109\n1010A\n1010B\n1010C\n1010D\n1010E\n1010F\n10110\n10111\n10112\n10113\n10114\n10115\n10116\n10117\n10118\n10119\n1011A\n1011B\n1011C\n1011D\n1011E\n1011F\n10120\n10121\n10122\n10123\n10124\n10125\n10126\n10127\n10128\n10129\n1012A\n1012B\n1012C\n1012D\n1012E\n1012F\n10130\n10131\n10132\n10133\n10137\n10138\n10139\n1013A\n1013B\n1013C\n1013D\n1013E\n1013F\n10140\n10141\n10142\n10143\n10144\n10145\n10146\n10147\n10148\n10149\n1014A\n1014B\n1014C\n1014D\n1014E\n1014F\n10150\n10151\n10152\n10153\n10154\n10155\n10156\n10157\n10158\n10159\n1015A\n1015B\n1015C\n1015D\n1015E\n1015F\n10160\n10161\n10162\n10163\n10164\n10165\n10166\n10167\n10168\n10169\n1016A\n1016B\n1016C\n1016D\n1016E\n1016F\n10170\n10171\n10172\n10173\n10174\n10175\n10176\n10177\n10178\n10179\n1017A\n1017B\n1017C\n1017D\n1017E\n1017F\n10180\n10181\n10182\n10183\n10184\n10185\n10186\n10187\n10188\n10189\n1018A\n1018B\n1018C\n10190\n10191\n10192\n10193\n10194\n10195\n10196\n10197\n10198\n10199\n1019A\n1019B\n101A0\n101D0\n101D1\n101D2\n101D3\n101D4\n101D5\n101D6\n101D7\n101D8\n101D9\n101DA\n101DB\n101DC\n101DD\n101DE\n101DF\n101E0\n101E1\n101E2\n101E3\n101E4\n101E5\n101E6\n101E7\n101E8\n101E9\n101EA\n101EB\n101EC\n101ED\n101EE\n101EF\n101F0\n101F1\n101F2\n101F3\n101F4\n101F5\n101F6\n101F7\n101F8\n101F9\n101FA\n101FB\n101FC\n101FD\n10280\n10281\n10282\n10283\n10284\n10285\n10286\n10287\n10288\n10289\n1028A\n1028B\n1028C\n1028D\n1028E\n1028F\n10290\n10291\n10292\n10293\n10294\n10295\n10296\n10297\n10298\n10299\n1029A\n1029B\n1029C\n102A0\n102A1\n102A2\n102A3\n102A4\n102A5\n102A6\n102A7\n102A8\n102A9\n102AA\n102AB\n102AC\n102AD\n102AE\n102AF\n102B0\n102B1\n102B2\n102B3\n102B4\n102B5\n102B6\n102B7\n102B8\n102B9\n102BA\n102BB\n102BC\n102BD\n102BE\n102BF\n102C0\n102C1\n102C2\n102C3\n102C4\n102C5\n102C6\n102C7\n102C8\n102C9\n102CA\n102CB\n102CC\n102CD\n102CE\n102CF\n102D0\n102E0\n102E1\n102E2\n102E3\n102E4\n102E5\n102E6\n102E7\n102E8\n102E9\n102EA\n102EB\n102EC\n102ED\n102EE\n102EF\n102F0\n102F1\n102F2\n102F3\n102F4\n102F5\n102F6\n102F7\n102F8\n102F9\n102FA\n102FB\n10300\n10301\n10302\n10303\n10304\n10305\n10306\n10307\n10308\n10309\n1030A\n1030B\n1030C\n1030D\n1030E\n1030F\n10310\n10311\n10312\n10313\n10314\n10315\n10316\n10317\n10318\n10319\n1031A\n1031B\n1031C\n1031D\n1031E\n1031F\n10320\n10321\n10322\n10323\n10330\n10331\n10332\n10333\n10334\n10335\n10336\n10337\n10338\n10339\n1033A\n1033B\n1033C\n1033D\n1033E\n1033F\n10340\n10341\n10342\n10343\n10344\n10345\n10346\n10347\n10348\n10349\n1034A\n10350\n10351\n10352\n10353\n10354\n10355\n10356\n10357\n10358\n10359\n1035A\n1035B\n1035C\n1035D\n1035E\n1035F\n10360\n10361\n10362\n10363\n10364\n10365\n10366\n10367\n10368\n10369\n1036A\n1036B\n1036C\n1036D\n1036E\n1036F\n10370\n10371\n10372\n10373\n10374\n10375\n10376\n10377\n10378\n10379\n1037A\n10380\n10381\n10382\n10383\n10384\n10385\n10386\n10387\n10388\n10389\n1038A\n1038B\n1038C\n1038D\n1038E\n1038F\n10390\n10391\n10392\n10393\n10394\n10395\n10396\n10397\n10398\n10399\n1039A\n1039B\n1039C\n1039D\n1039F\n103A0\n103A1\n103A2\n103A3\n103A4\n103A5\n103A6\n103A7\n103A8\n103A9\n103AA\n103AB\n103AC\n103AD\n103AE\n103AF\n103B0\n103B1\n103B2\n103B3\n103B4\n103B5\n103B6\n103B7\n103B8\n103B9\n103BA\n103BB\n103BC\n103BD\n103BE\n103BF\n103C0\n103C1\n103C2\n103C3\n103C8\n103C9\n103CA\n103CB\n103CC\n103CD\n103CE\n103CF\n103D0\n103D1\n103D2\n103D3\n103D4\n103D5\n10400\n10401\n10402\n10403\n10404\n10405\n10406\n10407\n10408\n10409\n1040A\n1040B\n1040C\n1040D\n1040E\n1040F\n10410\n10411\n10412\n10413\n10414\n10415\n10416\n10417\n10418\n10419\n1041A\n1041B\n1041C\n1041D\n1041E\n1041F\n10420\n10421\n10422\n10423\n10424\n10425\n10426\n10427\n10428\n10429\n1042A\n1042B\n1042C\n1042D\n1042E\n1042F\n10430\n10431\n10432\n10433\n10434\n10435\n10436\n10437\n10438\n10439\n1043A\n1043B\n1043C\n1043D\n1043E\n1043F\n10440\n10441\n10442\n10443\n10444\n10445\n10446\n10447\n10448\n10449\n1044A\n1044B\n1044C\n1044D\n1044E\n1044F\n10450\n10451\n10452\n10453\n10454\n10455\n10456\n10457\n10458\n10459\n1045A\n1045B\n1045C\n1045D\n1045E\n1045F\n10460\n10461\n10462\n10463\n10464\n10465\n10466\n10467\n10468\n10469\n1046A\n1046B\n1046C\n1046D\n1046E\n1046F\n10470\n10471\n10472\n10473\n10474\n10475\n10476\n10477\n10478\n10479\n1047A\n1047B\n1047C\n1047D\n1047E\n1047F\n10480\n10481\n10482\n10483\n10484\n10485\n10486\n10487\n10488\n10489\n1048A\n1048B\n1048C\n1048D\n1048E\n1048F\n10490\n10491\n10492\n10493\n10494\n10495\n10496\n10497\n10498\n10499\n1049A\n1049B\n1049C\n1049D\n104A0\n104A1\n104A2\n104A3\n104A4\n104A5\n104A6\n104A7\n104A8\n104A9\n10500\n10501\n10502\n10503\n10504\n10505\n10506\n10507\n10508\n10509\n1050A\n1050B\n1050C\n1050D\n1050E\n1050F\n10510\n10511\n10512\n10513\n10514\n10515\n10516\n10517\n10518\n10519\n1051A\n1051B\n1051C\n1051D\n1051E\n1051F\n10520\n10521\n10522\n10523\n10524\n10525\n10526\n10527\n10530\n10531\n10532\n10533\n10534\n10535\n10536\n10537\n10538\n10539\n1053A\n1053B\n1053C\n1053D\n1053E\n1053F\n10540\n10541\n10542\n10543\n10544\n10545\n10546\n10547\n10548\n10549\n1054A\n1054B\n1054C\n1054D\n1054E\n1054F\n10550\n10551\n10552\n10553\n10554\n10555\n10556\n10557\n10558\n10559\n1055A\n1055B\n1055C\n1055D\n1055E\n1055F\n10560\n10561\n10562\n10563\n1056F\n10600\n10601\n10602\n10603\n10604\n10605\n10606\n10607\n10608\n10609\n1060A\n1060B\n1060C\n1060D\n1060E\n1060F\n10610\n10611\n10612\n10613\n10614\n10615\n10616\n10617\n10618\n10619\n1061A\n1061B\n1061C\n1061D\n1061E\n1061F\n10620\n10621\n10622\n10623\n10624\n10625\n10626\n10627\n10628\n10629\n1062A\n1062B\n1062C\n1062D\n1062E\n1062F\n10630\n10631\n10632\n10633\n10634\n10635\n10636\n10637\n10638\n10639\n1063A\n1063B\n1063C\n1063D\n1063E\n1063F\n10640\n10641\n10642\n10643\n10644\n10645\n10646\n10647\n10648\n10649\n1064A\n1064B\n1064C\n1064D\n1064E\n1064F\n10650\n10651\n10652\n10653\n10654\n10655\n10656\n10657\n10658\n10659\n1065A\n1065B\n1065C\n1065D\n1065E\n1065F\n10660\n10661\n10662\n10663\n10664\n10665\n10666\n10667\n10668\n10669\n1066A\n1066B\n1066C\n1066D\n1066E\n1066F\n10670\n10671\n10672\n10673\n10674\n10675\n10676\n10677\n10678\n10679\n1067A\n1067B\n1067C\n1067D\n1067E\n1067F\n10680\n10681\n10682\n10683\n10684\n10685\n10686\n10687\n10688\n10689\n1068A\n1068B\n1068C\n1068D\n1068E\n1068F\n10690\n10691\n10692\n10693\n10694\n10695\n10696\n10697\n10698\n10699\n1069A\n1069B\n1069C\n1069D\n1069E\n1069F\n106A0\n106A1\n106A2\n106A3\n106A4\n106A5\n106A6\n106A7\n106A8\n106A9\n106AA\n106AB\n106AC\n106AD\n106AE\n106AF\n106B0\n106B1\n106B2\n106B3\n106B4\n106B5\n106B6\n106B7\n106B8\n106B9\n106BA\n106BB\n106BC\n106BD\n106BE\n106BF\n106C0\n106C1\n106C2\n106C3\n106C4\n106C5\n106C6\n106C7\n106C8\n106C9\n106CA\n106CB\n106CC\n106CD\n106CE\n106CF\n106D0\n106D1\n106D2\n106D3\n106D4\n106D5\n106D6\n106D7\n106D8\n106D9\n106DA\n106DB\n106DC\n106DD\n106DE\n106DF\n106E0\n106E1\n106E2\n106E3\n106E4\n106E5\n106E6\n106E7\n106E8\n106E9\n106EA\n106EB\n106EC\n106ED\n106EE\n106EF\n106F0\n106F1\n106F2\n106F3\n106F4\n106F5\n106F6\n106F7\n106F8\n106F9\n106FA\n106FB\n106FC\n106FD\n106FE\n106FF\n10700\n10701\n10702\n10703\n10704\n10705\n10706\n10707\n10708\n10709\n1070A\n1070B\n1070C\n1070D\n1070E\n1070F\n10710\n10711\n10712\n10713\n10714\n10715\n10716\n10717\n10718\n10719\n1071A\n1071B\n1071C\n1071D\n1071E\n1071F\n10720\n10721\n10722\n10723\n10724\n10725\n10726\n10727\n10728\n10729\n1072A\n1072B\n1072C\n1072D\n1072E\n1072F\n10730\n10731\n10732\n10733\n10734\n10735\n10736\n10740\n10741\n10742\n10743\n10744\n10745\n10746\n10747\n10748\n10749\n1074A\n1074B\n1074C\n1074D\n1074E\n1074F\n10750\n10751\n10752\n10753\n10754\n10755\n10760\n10761\n10762\n10763\n10764\n10765\n10766\n10767\n10800\n10801\n10802\n10803\n10804\n10805\n10808\n1080A\n1080B\n1080C\n1080D\n1080E\n1080F\n10810\n10811\n10812\n10813\n10814\n10815\n10816\n10817\n10818\n10819\n1081A\n1081B\n1081C\n1081D\n1081E\n1081F\n10820\n10821\n10822\n10823\n10824\n10825\n10826\n10827\n10828\n10829\n1082A\n1082B\n1082C\n1082D\n1082E\n1082F\n10830\n10831\n10832\n10833\n10834\n10835\n10837\n10838\n1083C\n1083F\n10840\n10841\n10842\n10843\n10844\n10845\n10846\n10847\n10848\n10849\n1084A\n1084B\n1084C\n1084D\n1084E\n1084F\n10850\n10851\n10852\n10853\n10854\n10855\n10857\n10858\n10859\n1085A\n1085B\n1085C\n1085D\n1085E\n1085F\n10860\n10861\n10862\n10863\n10864\n10865\n10866\n10867\n10868\n10869\n1086A\n1086B\n1086C\n1086D\n1086E\n1086F\n10870\n10871\n10872\n10873\n10874\n10875\n10876\n10877\n10878\n10879\n1087A\n1087B\n1087C\n1087D\n1087E\n1087F\n10880\n10881\n10882\n10883\n10884\n10885\n10886\n10887\n10888\n10889\n1088A\n1088B\n1088C\n1088D\n1088E\n1088F\n10890\n10891\n10892\n10893\n10894\n10895\n10896\n10897\n10898\n10899\n1089A\n1089B\n1089C\n1089D\n1089E\n108A7\n108A8\n108A9\n108AA\n108AB\n108AC\n108AD\n108AE\n108AF\n10900\n10901\n10902\n10903\n10904\n10905\n10906\n10907\n10908\n10909\n1090A\n1090B\n1090C\n1090D\n1090E\n1090F\n10910\n10911\n10912\n10913\n10914\n10915\n10916\n10917\n10918\n10919\n1091A\n1091B\n1091F\n10920\n10921\n10922\n10923\n10924\n10925\n10926\n10927\n10928\n10929\n1092A\n1092B\n1092C\n1092D\n1092E\n1092F\n10930\n10931\n10932\n10933\n10934\n10935\n10936\n10937\n10938\n10939\n1093F\n10980\n10981\n10982\n10983\n10984\n10985\n10986\n10987\n10988\n10989\n1098A\n1098B\n1098C\n1098D\n1098E\n1098F\n10990\n10991\n10992\n10993\n10994\n10995\n10996\n10997\n10998\n10999\n1099A\n1099B\n1099C\n1099D\n1099E\n1099F\n109A0\n109A1\n109A2\n109A3\n109A4\n109A5\n109A6\n109A7\n109A8\n109A9\n109AA\n109AB\n109AC\n109AD\n109AE\n109AF\n109B0\n109B1\n109B2\n109B3\n109B4\n109B5\n109B6\n109B7\n109BE\n109BF\n10A00\n10A01\n10A02\n10A03\n10A05\n10A06\n10A0C\n10A0D\n10A0E\n10A0F\n10A10\n10A11\n10A12\n10A13\n10A15\n10A16\n10A17\n10A19\n10A1A\n10A1B\n10A1C\n10A1D\n10A1E\n10A1F\n10A20\n10A21\n10A22\n10A23\n10A24\n10A25\n10A26\n10A27\n10A28\n10A29\n10A2A\n10A2B\n10A2C\n10A2D\n10A2E\n10A2F\n10A30\n10A31\n10A32\n10A33\n10A38\n10A39\n10A3A\n10A3F\n10A40\n10A41\n10A42\n10A43\n10A44\n10A45\n10A46\n10A47\n10A50\n10A51\n10A52\n10A53\n10A54\n10A55\n10A56\n10A57\n10A58\n10A60\n10A61\n10A62\n10A63\n10A64\n10A65\n10A66\n10A67\n10A68\n10A69\n10A6A\n10A6B\n10A6C\n10A6D\n10A6E\n10A6F\n10A70\n10A71\n10A72\n10A73\n10A74\n10A75\n10A76\n10A77\n10A78\n10A79\n10A7A\n10A7B\n10A7C\n10A7D\n10A7E\n10A7F\n10A80\n10A81\n10A82\n10A83\n10A84\n10A85\n10A86\n10A87\n10A88\n10A89\n10A8A\n10A8B\n10A8C\n10A8D\n10A8E\n10A8F\n10A90\n10A91\n10A92\n10A93\n10A94\n10A95\n10A96\n10A97\n10A98\n10A99\n10A9A\n10A9B\n10A9C\n10A9D\n10A9E\n10A9F\n10AC0\n10AC1\n10AC2\n10AC3\n10AC4\n10AC5\n10AC6\n10AC7\n10AC8\n10AC9\n10ACA\n10ACB\n10ACC\n10ACD\n10ACE\n10ACF\n10AD0\n10AD1\n10AD2\n10AD3\n10AD4\n10AD5\n10AD6\n10AD7\n10AD8\n10AD9\n10ADA\n10ADB\n10ADC\n10ADD\n10ADE\n10ADF\n10AE0\n10AE1\n10AE2\n10AE3\n10AE4\n10AE5\n10AE6\n10AEB\n10AEC\n10AED\n10AEE\n10AEF\n10AF0\n10AF1\n10AF2\n10AF3\n10AF4\n10AF5\n10AF6\n10B00\n10B01\n10B02\n10B03\n10B04\n10B05\n10B06\n10B07\n10B08\n10B09\n10B0A\n10B0B\n10B0C\n10B0D\n10B0E\n10B0F\n10B10\n10B11\n10B12\n10B13\n10B14\n10B15\n10B16\n10B17\n10B18\n10B19\n10B1A\n10B1B\n10B1C\n10B1D\n10B1E\n10B1F\n10B20\n10B21\n10B22\n10B23\n10B24\n10B25\n10B26\n10B27\n10B28\n10B29\n10B2A\n10B2B\n10B2C\n10B2D\n10B2E\n10B2F\n10B30\n10B31\n10B32\n10B33\n10B34\n10B35\n10B39\n10B3A\n10B3B\n10B3C\n10B3D\n10B3E\n10B3F\n10B40\n10B41\n10B42\n10B43\n10B44\n10B45\n10B46\n10B47\n10B48\n10B49\n10B4A\n10B4B\n10B4C\n10B4D\n10B4E\n10B4F\n10B50\n10B51\n10B52\n10B53\n10B54\n10B55\n10B58\n10B59\n10B5A\n10B5B\n10B5C\n10B5D\n10B5E\n10B5F\n10B60\n10B61\n10B62\n10B63\n10B64\n10B65\n10B66\n10B67\n10B68\n10B69\n10B6A\n10B6B\n10B6C\n10B6D\n10B6E\n10B6F\n10B70\n10B71\n10B72\n10B78\n10B79\n10B7A\n10B7B\n10B7C\n10B7D\n10B7E\n10B7F\n10B80\n10B81\n10B82\n10B83\n10B84\n10B85\n10B86\n10B87\n10B88\n10B89\n10B8A\n10B8B\n10B8C\n10B8D\n10B8E\n10B8F\n10B90\n10B91\n10B99\n10B9A\n10B9B\n10B9C\n10BA9\n10BAA\n10BAB\n10BAC\n10BAD\n10BAE\n10BAF\n10C00\n10C01\n10C02\n10C03\n10C04\n10C05\n10C06\n10C07\n10C08\n10C09\n10C0A\n10C0B\n10C0C\n10C0D\n10C0E\n10C0F\n10C10\n10C11\n10C12\n10C13\n10C14\n10C15\n10C16\n10C17\n10C18\n10C19\n10C1A\n10C1B\n10C1C\n10C1D\n10C1E\n10C1F\n10C20\n10C21\n10C22\n10C23\n10C24\n10C25\n10C26\n10C27\n10C28\n10C29\n10C2A\n10C2B\n10C2C\n10C2D\n10C2E\n10C2F\n10C30\n10C31\n10C32\n10C33\n10C34\n10C35\n10C36\n10C37\n10C38\n10C39\n10C3A\n10C3B\n10C3C\n10C3D\n10C3E\n10C3F\n10C40\n10C41\n10C42\n10C43\n10C44\n10C45\n10C46\n10C47\n10C48\n10E60\n10E61\n10E62\n10E63\n10E64\n10E65\n10E66\n10E67\n10E68\n10E69\n10E6A\n10E6B\n10E6C\n10E6D\n10E6E\n10E6F\n10E70\n10E71\n10E72\n10E73\n10E74\n10E75\n10E76\n10E77\n10E78\n10E79\n10E7A\n10E7B\n10E7C\n10E7D\n10E7E\n11000\n11001\n11002\n11003\n11004\n11005\n11006\n11007\n11008\n11009\n1100A\n1100B\n1100C\n1100D\n1100E\n1100F\n11010\n11011\n11012\n11013\n11014\n11015\n11016\n11017\n11018\n11019\n1101A\n1101B\n1101C\n1101D\n1101E\n1101F\n11020\n11021\n11022\n11023\n11024\n11025\n11026\n11027\n11028\n11029\n1102A\n1102B\n1102C\n1102D\n1102E\n1102F\n11030\n11031\n11032\n11033\n11034\n11035\n11036\n11037\n11038\n11039\n1103A\n1103B\n1103C\n1103D\n1103E\n1103F\n11040\n11041\n11042\n11043\n11044\n11045\n11046\n11047\n11048\n11049\n1104A\n1104B\n1104C\n1104D\n11052\n11053\n11054\n11055\n11056\n11057\n11058\n11059\n1105A\n1105B\n1105C\n1105D\n1105E\n1105F\n11060\n11061\n11062\n11063\n11064\n11065\n11066\n11067\n11068\n11069\n1106A\n1106B\n1106C\n1106D\n1106E\n1106F\n1107F\n11080\n11081\n11082\n11083\n11084\n11085\n11086\n11087\n11088\n11089\n1108A\n1108B\n1108C\n1108D\n1108E\n1108F\n11090\n11091\n11092\n11093\n11094\n11095\n11096\n11097\n11098\n11099\n1109A\n1109B\n1109C\n1109D\n1109E\n1109F\n110A0\n110A1\n110A2\n110A3\n110A4\n110A5\n110A6\n110A7\n110A8\n110A9\n110AA\n110AB\n110AC\n110AD\n110AE\n110AF\n110B0\n110B1\n110B2\n110B3\n110B4\n110B5\n110B6\n110B7\n110B8\n110B9\n110BA\n110BB\n110BC\n110BD\n110BE\n110BF\n110C0\n110C1\n110D0\n110D1\n110D2\n110D3\n110D4\n110D5\n110D6\n110D7\n110D8\n110D9\n110DA\n110DB\n110DC\n110DD\n110DE\n110DF\n110E0\n110E1\n110E2\n110E3\n110E4\n110E5\n110E6\n110E7\n110E8\n110F0\n110F1\n110F2\n110F3\n110F4\n110F5\n110F6\n110F7\n110F8\n110F9\n11100\n11101\n11102\n11103\n11104\n11105\n11106\n11107\n11108\n11109\n1110A\n1110B\n1110C\n1110D\n1110E\n1110F\n11110\n11111\n11112\n11113\n11114\n11115\n11116\n11117\n11118\n11119\n1111A\n1111B\n1111C\n1111D\n1111E\n1111F\n11120\n11121\n11122\n11123\n11124\n11125\n11126\n11127\n11128\n11129\n1112A\n1112B\n1112C\n1112D\n1112E\n1112F\n11130\n11131\n11132\n11133\n11134\n11136\n11137\n11138\n11139\n1113A\n1113B\n1113C\n1113D\n1113E\n1113F\n11140\n11141\n11142\n11143\n11150\n11151\n11152\n11153\n11154\n11155\n11156\n11157\n11158\n11159\n1115A\n1115B\n1115C\n1115D\n1115E\n1115F\n11160\n11161\n11162\n11163\n11164\n11165\n11166\n11167\n11168\n11169\n1116A\n1116B\n1116C\n1116D\n1116E\n1116F\n11170\n11171\n11172\n11173\n11174\n11175\n11176\n11180\n11181\n11182\n11183\n11184\n11185\n11186\n11187\n11188\n11189\n1118A\n1118B\n1118C\n1118D\n1118E\n1118F\n11190\n11191\n11192\n11193\n11194\n11195\n11196\n11197\n11198\n11199\n1119A\n1119B\n1119C\n1119D\n1119E\n1119F\n111A0\n111A1\n111A2\n111A3\n111A4\n111A5\n111A6\n111A7\n111A8\n111A9\n111AA\n111AB\n111AC\n111AD\n111AE\n111AF\n111B0\n111B1\n111B2\n111B3\n111B4\n111B5\n111B6\n111B7\n111B8\n111B9\n111BA\n111BB\n111BC\n111BD\n111BE\n111BF\n111C0\n111C1\n111C2\n111C3\n111C4\n111C5\n111C6\n111C7\n111C8\n111CD\n111D0\n111D1\n111D2\n111D3\n111D4\n111D5\n111D6\n111D7\n111D8\n111D9\n111DA\n111E1\n111E2\n111E3\n111E4\n111E5\n111E6\n111E7\n111E8\n111E9\n111EA\n111EB\n111EC\n111ED\n111EE\n111EF\n111F0\n111F1\n111F2\n111F3\n111F4\n11200\n11201\n11202\n11203\n11204\n11205\n11206\n11207\n11208\n11209\n1120A\n1120B\n1120C\n1120D\n1120E\n1120F\n11210\n11211\n11213\n11214\n11215\n11216\n11217\n11218\n11219\n1121A\n1121B\n1121C\n1121D\n1121E\n1121F\n11220\n11221\n11222\n11223\n11224\n11225\n11226\n11227\n11228\n11229\n1122A\n1122B\n1122C\n1122D\n1122E\n1122F\n11230\n11231\n11232\n11233\n11234\n11235\n11236\n11237\n11238\n11239\n1123A\n1123B\n1123C\n1123D\n112B0\n112B1\n112B2\n112B3\n112B4\n112B5\n112B6\n112B7\n112B8\n112B9\n112BA\n112BB\n112BC\n112BD\n112BE\n112BF\n112C0\n112C1\n112C2\n112C3\n112C4\n112C5\n112C6\n112C7\n112C8\n112C9\n112CA\n112CB\n112CC\n112CD\n112CE\n112CF\n112D0\n112D1\n112D2\n112D3\n112D4\n112D5\n112D6\n112D7\n112D8\n112D9\n112DA\n112DB\n112DC\n112DD\n112DE\n112DF\n112E0\n112E1\n112E2\n112E3\n112E4\n112E5\n112E6\n112E7\n112E8\n112E9\n112EA\n112F0\n112F1\n112F2\n112F3\n112F4\n112F5\n112F6\n112F7\n112F8\n112F9\n11301\n11302\n11303\n11305\n11306\n11307\n11308\n11309\n1130A\n1130B\n1130C\n1130F\n11310\n11313\n11314\n11315\n11316\n11317\n11318\n11319\n1131A\n1131B\n1131C\n1131D\n1131E\n1131F\n11320\n11321\n11322\n11323\n11324\n11325\n11326\n11327\n11328\n1132A\n1132B\n1132C\n1132D\n1132E\n1132F\n11330\n11332\n11333\n11335\n11336\n11337\n11338\n11339\n1133C\n1133D\n1133E\n1133F\n11340\n11341\n11342\n11343\n11344\n11347\n11348\n1134B\n1134C\n1134D\n11357\n1135D\n1135E\n1135F\n11360\n11361\n11362\n11363\n11366\n11367\n11368\n11369\n1136A\n1136B\n1136C\n11370\n11371\n11372\n11373\n11374\n11480\n11481\n11482\n11483\n11484\n11485\n11486\n11487\n11488\n11489\n1148A\n1148B\n1148C\n1148D\n1148E\n1148F\n11490\n11491\n11492\n11493\n11494\n11495\n11496\n11497\n11498\n11499\n1149A\n1149B\n1149C\n1149D\n1149E\n1149F\n114A0\n114A1\n114A2\n114A3\n114A4\n114A5\n114A6\n114A7\n114A8\n114A9\n114AA\n114AB\n114AC\n114AD\n114AE\n114AF\n114B0\n114B1\n114B2\n114B3\n114B4\n114B5\n114B6\n114B7\n114B8\n114B9\n114BA\n114BB\n114BC\n114BD\n114BE\n114BF\n114C0\n114C1\n114C2\n114C3\n114C4\n114C5\n114C6\n114C7\n114D0\n114D1\n114D2\n114D3\n114D4\n114D5\n114D6\n114D7\n114D8\n114D9\n11580\n11581\n11582\n11583\n11584\n11585\n11586\n11587\n11588\n11589\n1158A\n1158B\n1158C\n1158D\n1158E\n1158F\n11590\n11591\n11592\n11593\n11594\n11595\n11596\n11597\n11598\n11599\n1159A\n1159B\n1159C\n1159D\n1159E\n1159F\n115A0\n115A1\n115A2\n115A3\n115A4\n115A5\n115A6\n115A7\n115A8\n115A9\n115AA\n115AB\n115AC\n115AD\n115AE\n115AF\n115B0\n115B1\n115B2\n115B3\n115B4\n115B5\n115B8\n115B9\n115BA\n115BB\n115BC\n115BD\n115BE\n115BF\n115C0\n115C1\n115C2\n115C3\n115C4\n115C5\n115C6\n115C7\n115C8\n115C9\n11600\n11601\n11602\n11603\n11604\n11605\n11606\n11607\n11608\n11609\n1160A\n1160B\n1160C\n1160D\n1160E\n1160F\n11610\n11611\n11612\n11613\n11614\n11615\n11616\n11617\n11618\n11619\n1161A\n1161B\n1161C\n1161D\n1161E\n1161F\n11620\n11621\n11622\n11623\n11624\n11625\n11626\n11627\n11628\n11629\n1162A\n1162B\n1162C\n1162D\n1162E\n1162F\n11630\n11631\n11632\n11633\n11634\n11635\n11636\n11637\n11638\n11639\n1163A\n1163B\n1163C\n1163D\n1163E\n1163F\n11640\n11641\n11642\n11643\n11644\n11650\n11651\n11652\n11653\n11654\n11655\n11656\n11657\n11658\n11659\n11680\n11681\n11682\n11683\n11684\n11685\n11686\n11687\n11688\n11689\n1168A\n1168B\n1168C\n1168D\n1168E\n1168F\n11690\n11691\n11692\n11693\n11694\n11695\n11696\n11697\n11698\n11699\n1169A\n1169B\n1169C\n1169D\n1169E\n1169F\n116A0\n116A1\n116A2\n116A3\n116A4\n116A5\n116A6\n116A7\n116A8\n116A9\n116AA\n116AB\n116AC\n116AD\n116AE\n116AF\n116B0\n116B1\n116B2\n116B3\n116B4\n116B5\n116B6\n116B7\n116C0\n116C1\n116C2\n116C3\n116C4\n116C5\n116C6\n116C7\n116C8\n116C9\n118A0\n118A1\n118A2\n118A3\n118A4\n118A5\n118A6\n118A7\n118A8\n118A9\n118AA\n118AB\n118AC\n118AD\n118AE\n118AF\n118B0\n118B1\n118B2\n118B3\n118B4\n118B5\n118B6\n118B7\n118B8\n118B9\n118BA\n118BB\n118BC\n118BD\n118BE\n118BF\n118C0\n118C1\n118C2\n118C3\n118C4\n118C5\n118C6\n118C7\n118C8\n118C9\n118CA\n118CB\n118CC\n118CD\n118CE\n118CF\n118D0\n118D1\n118D2\n118D3\n118D4\n118D5\n118D6\n118D7\n118D8\n118D9\n118DA\n118DB\n118DC\n118DD\n118DE\n118DF\n118E0\n118E1\n118E2\n118E3\n118E4\n118E5\n118E6\n118E7\n118E8\n118E9\n118EA\n118EB\n118EC\n118ED\n118EE\n118EF\n118F0\n118F1\n118F2\n118FF\n11AC0\n11AC1\n11AC2\n11AC3\n11AC4\n11AC5\n11AC6\n11AC7\n11AC8\n11AC9\n11ACA\n11ACB\n11ACC\n11ACD\n11ACE\n11ACF\n11AD0\n11AD1\n11AD2\n11AD3\n11AD4\n11AD5\n11AD6\n11AD7\n11AD8\n11AD9\n11ADA\n11ADB\n11ADC\n11ADD\n11ADE\n11ADF\n11AE0\n11AE1\n11AE2\n11AE3\n11AE4\n11AE5\n11AE6\n11AE7\n11AE8\n11AE9\n11AEA\n11AEB\n11AEC\n11AED\n11AEE\n11AEF\n11AF0\n11AF1\n11AF2\n11AF3\n11AF4\n11AF5\n11AF6\n11AF7\n11AF8\n12000\n12001\n12002\n12003\n12004\n12005\n12006\n12007\n12008\n12009\n1200A\n1200B\n1200C\n1200D\n1200E\n1200F\n12010\n12011\n12012\n12013\n12014\n12015\n12016\n12017\n12018\n12019\n1201A\n1201B\n1201C\n1201D\n1201E\n1201F\n12020\n12021\n12022\n12023\n12024\n12025\n12026\n12027\n12028\n12029\n1202A\n1202B\n1202C\n1202D\n1202E\n1202F\n12030\n12031\n12032\n12033\n12034\n12035\n12036\n12037\n12038\n12039\n1203A\n1203B\n1203C\n1203D\n1203E\n1203F\n12040\n12041\n12042\n12043\n12044\n12045\n12046\n12047\n12048\n12049\n1204A\n1204B\n1204C\n1204D\n1204E\n1204F\n12050\n12051\n12052\n12053\n12054\n12055\n12056\n12057\n12058\n12059\n1205A\n1205B\n1205C\n1205D\n1205E\n1205F\n12060\n12061\n12062\n12063\n12064\n12065\n12066\n12067\n12068\n12069\n1206A\n1206B\n1206C\n1206D\n1206E\n1206F\n12070\n12071\n12072\n12073\n12074\n12075\n12076\n12077\n12078\n12079\n1207A\n1207B\n1207C\n1207D\n1207E\n1207F\n12080\n12081\n12082\n12083\n12084\n12085\n12086\n12087\n12088\n12089\n1208A\n1208B\n1208C\n1208D\n1208E\n1208F\n12090\n12091\n12092\n12093\n12094\n12095\n12096\n12097\n12098\n12099\n1209A\n1209B\n1209C\n1209D\n1209E\n1209F\n120A0\n120A1\n120A2\n120A3\n120A4\n120A5\n120A6\n120A7\n120A8\n120A9\n120AA\n120AB\n120AC\n120AD\n120AE\n120AF\n120B0\n120B1\n120B2\n120B3\n120B4\n120B5\n120B6\n120B7\n120B8\n120B9\n120BA\n120BB\n120BC\n120BD\n120BE\n120BF\n120C0\n120C1\n120C2\n120C3\n120C4\n120C5\n120C6\n120C7\n120C8\n120C9\n120CA\n120CB\n120CC\n120CD\n120CE\n120CF\n120D0\n120D1\n120D2\n120D3\n120D4\n120D5\n120D6\n120D7\n120D8\n120D9\n120DA\n120DB\n120DC\n120DD\n120DE\n120DF\n120E0\n120E1\n120E2\n120E3\n120E4\n120E5\n120E6\n120E7\n120E8\n120E9\n120EA\n120EB\n120EC\n120ED\n120EE\n120EF\n120F0\n120F1\n120F2\n120F3\n120F4\n120F5\n120F6\n120F7\n120F8\n120F9\n120FA\n120FB\n120FC\n120FD\n120FE\n120FF\n12100\n12101\n12102\n12103\n12104\n12105\n12106\n12107\n12108\n12109\n1210A\n1210B\n1210C\n1210D\n1210E\n1210F\n12110\n12111\n12112\n12113\n12114\n12115\n12116\n12117\n12118\n12119\n1211A\n1211B\n1211C\n1211D\n1211E\n1211F\n12120\n12121\n12122\n12123\n12124\n12125\n12126\n12127\n12128\n12129\n1212A\n1212B\n1212C\n1212D\n1212E\n1212F\n12130\n12131\n12132\n12133\n12134\n12135\n12136\n12137\n12138\n12139\n1213A\n1213B\n1213C\n1213D\n1213E\n1213F\n12140\n12141\n12142\n12143\n12144\n12145\n12146\n12147\n12148\n12149\n1214A\n1214B\n1214C\n1214D\n1214E\n1214F\n12150\n12151\n12152\n12153\n12154\n12155\n12156\n12157\n12158\n12159\n1215A\n1215B\n1215C\n1215D\n1215E\n1215F\n12160\n12161\n12162\n12163\n12164\n12165\n12166\n12167\n12168\n12169\n1216A\n1216B\n1216C\n1216D\n1216E\n1216F\n12170\n12171\n12172\n12173\n12174\n12175\n12176\n12177\n12178\n12179\n1217A\n1217B\n1217C\n1217D\n1217E\n1217F\n12180\n12181\n12182\n12183\n12184\n12185\n12186\n12187\n12188\n12189\n1218A\n1218B\n1218C\n1218D\n1218E\n1218F\n12190\n12191\n12192\n12193\n12194\n12195\n12196\n12197\n12198\n12199\n1219A\n1219B\n1219C\n1219D\n1219E\n1219F\n121A0\n121A1\n121A2\n121A3\n121A4\n121A5\n121A6\n121A7\n121A8\n121A9\n121AA\n121AB\n121AC\n121AD\n121AE\n121AF\n121B0\n121B1\n121B2\n121B3\n121B4\n121B5\n121B6\n121B7\n121B8\n121B9\n121BA\n121BB\n121BC\n121BD\n121BE\n121BF\n121C0\n121C1\n121C2\n121C3\n121C4\n121C5\n121C6\n121C7\n121C8\n121C9\n121CA\n121CB\n121CC\n121CD\n121CE\n121CF\n121D0\n121D1\n121D2\n121D3\n121D4\n121D5\n121D6\n121D7\n121D8\n121D9\n121DA\n121DB\n121DC\n121DD\n121DE\n121DF\n121E0\n121E1\n121E2\n121E3\n121E4\n121E5\n121E6\n121E7\n121E8\n121E9\n121EA\n121EB\n121EC\n121ED\n121EE\n121EF\n121F0\n121F1\n121F2\n121F3\n121F4\n121F5\n121F6\n121F7\n121F8\n121F9\n121FA\n121FB\n121FC\n121FD\n121FE\n121FF\n12200\n12201\n12202\n12203\n12204\n12205\n12206\n12207\n12208\n12209\n1220A\n1220B\n1220C\n1220D\n1220E\n1220F\n12210\n12211\n12212\n12213\n12214\n12215\n12216\n12217\n12218\n12219\n1221A\n1221B\n1221C\n1221D\n1221E\n1221F\n12220\n12221\n12222\n12223\n12224\n12225\n12226\n12227\n12228\n12229\n1222A\n1222B\n1222C\n1222D\n1222E\n1222F\n12230\n12231\n12232\n12233\n12234\n12235\n12236\n12237\n12238\n12239\n1223A\n1223B\n1223C\n1223D\n1223E\n1223F\n12240\n12241\n12242\n12243\n12244\n12245\n12246\n12247\n12248\n12249\n1224A\n1224B\n1224C\n1224D\n1224E\n1224F\n12250\n12251\n12252\n12253\n12254\n12255\n12256\n12257\n12258\n12259\n1225A\n1225B\n1225C\n1225D\n1225E\n1225F\n12260\n12261\n12262\n12263\n12264\n12265\n12266\n12267\n12268\n12269\n1226A\n1226B\n1226C\n1226D\n1226E\n1226F\n12270\n12271\n12272\n12273\n12274\n12275\n12276\n12277\n12278\n12279\n1227A\n1227B\n1227C\n1227D\n1227E\n1227F\n12280\n12281\n12282\n12283\n12284\n12285\n12286\n12287\n12288\n12289\n1228A\n1228B\n1228C\n1228D\n1228E\n1228F\n12290\n12291\n12292\n12293\n12294\n12295\n12296\n12297\n12298\n12299\n1229A\n1229B\n1229C\n1229D\n1229E\n1229F\n122A0\n122A1\n122A2\n122A3\n122A4\n122A5\n122A6\n122A7\n122A8\n122A9\n122AA\n122AB\n122AC\n122AD\n122AE\n122AF\n122B0\n122B1\n122B2\n122B3\n122B4\n122B5\n122B6\n122B7\n122B8\n122B9\n122BA\n122BB\n122BC\n122BD\n122BE\n122BF\n122C0\n122C1\n122C2\n122C3\n122C4\n122C5\n122C6\n122C7\n122C8\n122C9\n122CA\n122CB\n122CC\n122CD\n122CE\n122CF\n122D0\n122D1\n122D2\n122D3\n122D4\n122D5\n122D6\n122D7\n122D8\n122D9\n122DA\n122DB\n122DC\n122DD\n122DE\n122DF\n122E0\n122E1\n122E2\n122E3\n122E4\n122E5\n122E6\n122E7\n122E8\n122E9\n122EA\n122EB\n122EC\n122ED\n122EE\n122EF\n122F0\n122F1\n122F2\n122F3\n122F4\n122F5\n122F6\n122F7\n122F8\n122F9\n122FA\n122FB\n122FC\n122FD\n122FE\n122FF\n12300\n12301\n12302\n12303\n12304\n12305\n12306\n12307\n12308\n12309\n1230A\n1230B\n1230C\n1230D\n1230E\n1230F\n12310\n12311\n12312\n12313\n12314\n12315\n12316\n12317\n12318\n12319\n1231A\n1231B\n1231C\n1231D\n1231E\n1231F\n12320\n12321\n12322\n12323\n12324\n12325\n12326\n12327\n12328\n12329\n1232A\n1232B\n1232C\n1232D\n1232E\n1232F\n12330\n12331\n12332\n12333\n12334\n12335\n12336\n12337\n12338\n12339\n1233A\n1233B\n1233C\n1233D\n1233E\n1233F\n12340\n12341\n12342\n12343\n12344\n12345\n12346\n12347\n12348\n12349\n1234A\n1234B\n1234C\n1234D\n1234E\n1234F\n12350\n12351\n12352\n12353\n12354\n12355\n12356\n12357\n12358\n12359\n1235A\n1235B\n1235C\n1235D\n1235E\n1235F\n12360\n12361\n12362\n12363\n12364\n12365\n12366\n12367\n12368\n12369\n1236A\n1236B\n1236C\n1236D\n1236E\n1236F\n12370\n12371\n12372\n12373\n12374\n12375\n12376\n12377\n12378\n12379\n1237A\n1237B\n1237C\n1237D\n1237E\n1237F\n12380\n12381\n12382\n12383\n12384\n12385\n12386\n12387\n12388\n12389\n1238A\n1238B\n1238C\n1238D\n1238E\n1238F\n12390\n12391\n12392\n12393\n12394\n12395\n12396\n12397\n12398\n12400\n12401\n12402\n12403\n12404\n12405\n12406\n12407\n12408\n12409\n1240A\n1240B\n1240C\n1240D\n1240E\n1240F\n12410\n12411\n12412\n12413\n12414\n12415\n12416\n12417\n12418\n12419\n1241A\n1241B\n1241C\n1241D\n1241E\n1241F\n12420\n12421\n12422\n12423\n12424\n12425\n12426\n12427\n12428\n12429\n1242A\n1242B\n1242C\n1242D\n1242E\n1242F\n12430\n12431\n12432\n12433\n12434\n12435\n12436\n12437\n12438\n12439\n1243A\n1243B\n1243C\n1243D\n1243E\n1243F\n12440\n12441\n12442\n12443\n12444\n12445\n12446\n12447\n12448\n12449\n1244A\n1244B\n1244C\n1244D\n1244E\n1244F\n12450\n12451\n12452\n12453\n12454\n12455\n12456\n12457\n12458\n12459\n1245A\n1245B\n1245C\n1245D\n1245E\n1245F\n12460\n12461\n12462\n12463\n12464\n12465\n12466\n12467\n12468\n12469\n1246A\n1246B\n1246C\n1246D\n1246E\n12470\n12471\n12472\n12473\n12474\n13000\n13001\n13002\n13003\n13004\n13005\n13006\n13007\n13008\n13009\n1300A\n1300B\n1300C\n1300D\n1300E\n1300F\n13010\n13011\n13012\n13013\n13014\n13015\n13016\n13017\n13018\n13019\n1301A\n1301B\n1301C\n1301D\n1301E\n1301F\n13020\n13021\n13022\n13023\n13024\n13025\n13026\n13027\n13028\n13029\n1302A\n1302B\n1302C\n1302D\n1302E\n1302F\n13030\n13031\n13032\n13033\n13034\n13035\n13036\n13037\n13038\n13039\n1303A\n1303B\n1303C\n1303D\n1303E\n1303F\n13040\n13041\n13042\n13043\n13044\n13045\n13046\n13047\n13048\n13049\n1304A\n1304B\n1304C\n1304D\n1304E\n1304F\n13050\n13051\n13052\n13053\n13054\n13055\n13056\n13057\n13058\n13059\n1305A\n1305B\n1305C\n1305D\n1305E\n1305F\n13060\n13061\n13062\n13063\n13064\n13065\n13066\n13067\n13068\n13069\n1306A\n1306B\n1306C\n1306D\n1306E\n1306F\n13070\n13071\n13072\n13073\n13074\n13075\n13076\n13077\n13078\n13079\n1307A\n1307B\n1307C\n1307D\n1307E\n1307F\n13080\n13081\n13082\n13083\n13084\n13085\n13086\n13087\n13088\n13089\n1308A\n1308B\n1308C\n1308D\n1308E\n1308F\n13090\n13091\n13092\n13093\n13094\n13095\n13096\n13097\n13098\n13099\n1309A\n1309B\n1309C\n1309D\n1309E\n1309F\n130A0\n130A1\n130A2\n130A3\n130A4\n130A5\n130A6\n130A7\n130A8\n130A9\n130AA\n130AB\n130AC\n130AD\n130AE\n130AF\n130B0\n130B1\n130B2\n130B3\n130B4\n130B5\n130B6\n130B7\n130B8\n130B9\n130BA\n130BB\n130BC\n130BD\n130BE\n130BF\n130C0\n130C1\n130C2\n130C3\n130C4\n130C5\n130C6\n130C7\n130C8\n130C9\n130CA\n130CB\n130CC\n130CD\n130CE\n130CF\n130D0\n130D1\n130D2\n130D3\n130D4\n130D5\n130D6\n130D7\n130D8\n130D9\n130DA\n130DB\n130DC\n130DD\n130DE\n130DF\n130E0\n130E1\n130E2\n130E3\n130E4\n130E5\n130E6\n130E7\n130E8\n130E9\n130EA\n130EB\n130EC\n130ED\n130EE\n130EF\n130F0\n130F1\n130F2\n130F3\n130F4\n130F5\n130F6\n130F7\n130F8\n130F9\n130FA\n130FB\n130FC\n130FD\n130FE\n130FF\n13100\n13101\n13102\n13103\n13104\n13105\n13106\n13107\n13108\n13109\n1310A\n1310B\n1310C\n1310D\n1310E\n1310F\n13110\n13111\n13112\n13113\n13114\n13115\n13116\n13117\n13118\n13119\n1311A\n1311B\n1311C\n1311D\n1311E\n1311F\n13120\n13121\n13122\n13123\n13124\n13125\n13126\n13127\n13128\n13129\n1312A\n1312B\n1312C\n1312D\n1312E\n1312F\n13130\n13131\n13132\n13133\n13134\n13135\n13136\n13137\n13138\n13139\n1313A\n1313B\n1313C\n1313D\n1313E\n1313F\n13140\n13141\n13142\n13143\n13144\n13145\n13146\n13147\n13148\n13149\n1314A\n1314B\n1314C\n1314D\n1314E\n1314F\n13150\n13151\n13152\n13153\n13154\n13155\n13156\n13157\n13158\n13159\n1315A\n1315B\n1315C\n1315D\n1315E\n1315F\n13160\n13161\n13162\n13163\n13164\n13165\n13166\n13167\n13168\n13169\n1316A\n1316B\n1316C\n1316D\n1316E\n1316F\n13170\n13171\n13172\n13173\n13174\n13175\n13176\n13177\n13178\n13179\n1317A\n1317B\n1317C\n1317D\n1317E\n1317F\n13180\n13181\n13182\n13183\n13184\n13185\n13186\n13187\n13188\n13189\n1318A\n1318B\n1318C\n1318D\n1318E\n1318F\n13190\n13191\n13192\n13193\n13194\n13195\n13196\n13197\n13198\n13199\n1319A\n1319B\n1319C\n1319D\n1319E\n1319F\n131A0\n131A1\n131A2\n131A3\n131A4\n131A5\n131A6\n131A7\n131A8\n131A9\n131AA\n131AB\n131AC\n131AD\n131AE\n131AF\n131B0\n131B1\n131B2\n131B3\n131B4\n131B5\n131B6\n131B7\n131B8\n131B9\n131BA\n131BB\n131BC\n131BD\n131BE\n131BF\n131C0\n131C1\n131C2\n131C3\n131C4\n131C5\n131C6\n131C7\n131C8\n131C9\n131CA\n131CB\n131CC\n131CD\n131CE\n131CF\n131D0\n131D1\n131D2\n131D3\n131D4\n131D5\n131D6\n131D7\n131D8\n131D9\n131DA\n131DB\n131DC\n131DD\n131DE\n131DF\n131E0\n131E1\n131E2\n131E3\n131E4\n131E5\n131E6\n131E7\n131E8\n131E9\n131EA\n131EB\n131EC\n131ED\n131EE\n131EF\n131F0\n131F1\n131F2\n131F3\n131F4\n131F5\n131F6\n131F7\n131F8\n131F9\n131FA\n131FB\n131FC\n131FD\n131FE\n131FF\n13200\n13201\n13202\n13203\n13204\n13205\n13206\n13207\n13208\n13209\n1320A\n1320B\n1320C\n1320D\n1320E\n1320F\n13210\n13211\n13212\n13213\n13214\n13215\n13216\n13217\n13218\n13219\n1321A\n1321B\n1321C\n1321D\n1321E\n1321F\n13220\n13221\n13222\n13223\n13224\n13225\n13226\n13227\n13228\n13229\n1322A\n1322B\n1322C\n1322D\n1322E\n1322F\n13230\n13231\n13232\n13233\n13234\n13235\n13236\n13237\n13238\n13239\n1323A\n1323B\n1323C\n1323D\n1323E\n1323F\n13240\n13241\n13242\n13243\n13244\n13245\n13246\n13247\n13248\n13249\n1324A\n1324B\n1324C\n1324D\n1324E\n1324F\n13250\n13251\n13252\n13253\n13254\n13255\n13256\n13257\n13258\n13259\n1325A\n1325B\n1325C\n1325D\n1325E\n1325F\n13260\n13261\n13262\n13263\n13264\n13265\n13266\n13267\n13268\n13269\n1326A\n1326B\n1326C\n1326D\n1326E\n1326F\n13270\n13271\n13272\n13273\n13274\n13275\n13276\n13277\n13278\n13279\n1327A\n1327B\n1327C\n1327D\n1327E\n1327F\n13280\n13281\n13282\n13283\n13284\n13285\n13286\n13287\n13288\n13289\n1328A\n1328B\n1328C\n1328D\n1328E\n1328F\n13290\n13291\n13292\n13293\n13294\n13295\n13296\n13297\n13298\n13299\n1329A\n1329B\n1329C\n1329D\n1329E\n1329F\n132A0\n132A1\n132A2\n132A3\n132A4\n132A5\n132A6\n132A7\n132A8\n132A9\n132AA\n132AB\n132AC\n132AD\n132AE\n132AF\n132B0\n132B1\n132B2\n132B3\n132B4\n132B5\n132B6\n132B7\n132B8\n132B9\n132BA\n132BB\n132BC\n132BD\n132BE\n132BF\n132C0\n132C1\n132C2\n132C3\n132C4\n132C5\n132C6\n132C7\n132C8\n132C9\n132CA\n132CB\n132CC\n132CD\n132CE\n132CF\n132D0\n132D1\n132D2\n132D3\n132D4\n132D5\n132D6\n132D7\n132D8\n132D9\n132DA\n132DB\n132DC\n132DD\n132DE\n132DF\n132E0\n132E1\n132E2\n132E3\n132E4\n132E5\n132E6\n132E7\n132E8\n132E9\n132EA\n132EB\n132EC\n132ED\n132EE\n132EF\n132F0\n132F1\n132F2\n132F3\n132F4\n132F5\n132F6\n132F7\n132F8\n132F9\n132FA\n132FB\n132FC\n132FD\n132FE\n132FF\n13300\n13301\n13302\n13303\n13304\n13305\n13306\n13307\n13308\n13309\n1330A\n1330B\n1330C\n1330D\n1330E\n1330F\n13310\n13311\n13312\n13313\n13314\n13315\n13316\n13317\n13318\n13319\n1331A\n1331B\n1331C\n1331D\n1331E\n1331F\n13320\n13321\n13322\n13323\n13324\n13325\n13326\n13327\n13328\n13329\n1332A\n1332B\n1332C\n1332D\n1332E\n1332F\n13330\n13331\n13332\n13333\n13334\n13335\n13336\n13337\n13338\n13339\n1333A\n1333B\n1333C\n1333D\n1333E\n1333F\n13340\n13341\n13342\n13343\n13344\n13345\n13346\n13347\n13348\n13349\n1334A\n1334B\n1334C\n1334D\n1334E\n1334F\n13350\n13351\n13352\n13353\n13354\n13355\n13356\n13357\n13358\n13359\n1335A\n1335B\n1335C\n1335D\n1335E\n1335F\n13360\n13361\n13362\n13363\n13364\n13365\n13366\n13367\n13368\n13369\n1336A\n1336B\n1336C\n1336D\n1336E\n1336F\n13370\n13371\n13372\n13373\n13374\n13375\n13376\n13377\n13378\n13379\n1337A\n1337B\n1337C\n1337D\n1337E\n1337F\n13380\n13381\n13382\n13383\n13384\n13385\n13386\n13387\n13388\n13389\n1338A\n1338B\n1338C\n1338D\n1338E\n1338F\n13390\n13391\n13392\n13393\n13394\n13395\n13396\n13397\n13398\n13399\n1339A\n1339B\n1339C\n1339D\n1339E\n1339F\n133A0\n133A1\n133A2\n133A3\n133A4\n133A5\n133A6\n133A7\n133A8\n133A9\n133AA\n133AB\n133AC\n133AD\n133AE\n133AF\n133B0\n133B1\n133B2\n133B3\n133B4\n133B5\n133B6\n133B7\n133B8\n133B9\n133BA\n133BB\n133BC\n133BD\n133BE\n133BF\n133C0\n133C1\n133C2\n133C3\n133C4\n133C5\n133C6\n133C7\n133C8\n133C9\n133CA\n133CB\n133CC\n133CD\n133CE\n133CF\n133D0\n133D1\n133D2\n133D3\n133D4\n133D5\n133D6\n133D7\n133D8\n133D9\n133DA\n133DB\n133DC\n133DD\n133DE\n133DF\n133E0\n133E1\n133E2\n133E3\n133E4\n133E5\n133E6\n133E7\n133E8\n133E9\n133EA\n133EB\n133EC\n133ED\n133EE\n133EF\n133F0\n133F1\n133F2\n133F3\n133F4\n133F5\n133F6\n133F7\n133F8\n133F9\n133FA\n133FB\n133FC\n133FD\n133FE\n133FF\n13400\n13401\n13402\n13403\n13404\n13405\n13406\n13407\n13408\n13409\n1340A\n1340B\n1340C\n1340D\n1340E\n1340F\n13410\n13411\n13412\n13413\n13414\n13415\n13416\n13417\n13418\n13419\n1341A\n1341B\n1341C\n1341D\n1341E\n1341F\n13420\n13421\n13422\n13423\n13424\n13425\n13426\n13427\n13428\n13429\n1342A\n1342B\n1342C\n1342D\n1342E\n16800\n16801\n16802\n16803\n16804\n16805\n16806\n16807\n16808\n16809\n1680A\n1680B\n1680C\n1680D\n1680E\n1680F\n16810\n16811\n16812\n16813\n16814\n16815\n16816\n16817\n16818\n16819\n1681A\n1681B\n1681C\n1681D\n1681E\n1681F\n16820\n16821\n16822\n16823\n16824\n16825\n16826\n16827\n16828\n16829\n1682A\n1682B\n1682C\n1682D\n1682E\n1682F\n16830\n16831\n16832\n16833\n16834\n16835\n16836\n16837\n16838\n16839\n1683A\n1683B\n1683C\n1683D\n1683E\n1683F\n16840\n16841\n16842\n16843\n16844\n16845\n16846\n16847\n16848\n16849\n1684A\n1684B\n1684C\n1684D\n1684E\n1684F\n16850\n16851\n16852\n16853\n16854\n16855\n16856\n16857\n16858\n16859\n1685A\n1685B\n1685C\n1685D\n1685E\n1685F\n16860\n16861\n16862\n16863\n16864\n16865\n16866\n16867\n16868\n16869\n1686A\n1686B\n1686C\n1686D\n1686E\n1686F\n16870\n16871\n16872\n16873\n16874\n16875\n16876\n16877\n16878\n16879\n1687A\n1687B\n1687C\n1687D\n1687E\n1687F\n16880\n16881\n16882\n16883\n16884\n16885\n16886\n16887\n16888\n16889\n1688A\n1688B\n1688C\n1688D\n1688E\n1688F\n16890\n16891\n16892\n16893\n16894\n16895\n16896\n16897\n16898\n16899\n1689A\n1689B\n1689C\n1689D\n1689E\n1689F\n168A0\n168A1\n168A2\n168A3\n168A4\n168A5\n168A6\n168A7\n168A8\n168A9\n168AA\n168AB\n168AC\n168AD\n168AE\n168AF\n168B0\n168B1\n168B2\n168B3\n168B4\n168B5\n168B6\n168B7\n168B8\n168B9\n168BA\n168BB\n168BC\n168BD\n168BE\n168BF\n168C0\n168C1\n168C2\n168C3\n168C4\n168C5\n168C6\n168C7\n168C8\n168C9\n168CA\n168CB\n168CC\n168CD\n168CE\n168CF\n168D0\n168D1\n168D2\n168D3\n168D4\n168D5\n168D6\n168D7\n168D8\n168D9\n168DA\n168DB\n168DC\n168DD\n168DE\n168DF\n168E0\n168E1\n168E2\n168E3\n168E4\n168E5\n168E6\n168E7\n168E8\n168E9\n168EA\n168EB\n168EC\n168ED\n168EE\n168EF\n168F0\n168F1\n168F2\n168F3\n168F4\n168F5\n168F6\n168F7\n168F8\n168F9\n168FA\n168FB\n168FC\n168FD\n168FE\n168FF\n16900\n16901\n16902\n16903\n16904\n16905\n16906\n16907\n16908\n16909\n1690A\n1690B\n1690C\n1690D\n1690E\n1690F\n16910\n16911\n16912\n16913\n16914\n16915\n16916\n16917\n16918\n16919\n1691A\n1691B\n1691C\n1691D\n1691E\n1691F\n16920\n16921\n16922\n16923\n16924\n16925\n16926\n16927\n16928\n16929\n1692A\n1692B\n1692C\n1692D\n1692E\n1692F\n16930\n16931\n16932\n16933\n16934\n16935\n16936\n16937\n16938\n16939\n1693A\n1693B\n1693C\n1693D\n1693E\n1693F\n16940\n16941\n16942\n16943\n16944\n16945\n16946\n16947\n16948\n16949\n1694A\n1694B\n1694C\n1694D\n1694E\n1694F\n16950\n16951\n16952\n16953\n16954\n16955\n16956\n16957\n16958\n16959\n1695A\n1695B\n1695C\n1695D\n1695E\n1695F\n16960\n16961\n16962\n16963\n16964\n16965\n16966\n16967\n16968\n16969\n1696A\n1696B\n1696C\n1696D\n1696E\n1696F\n16970\n16971\n16972\n16973\n16974\n16975\n16976\n16977\n16978\n16979\n1697A\n1697B\n1697C\n1697D\n1697E\n1697F\n16980\n16981\n16982\n16983\n16984\n16985\n16986\n16987\n16988\n16989\n1698A\n1698B\n1698C\n1698D\n1698E\n1698F\n16990\n16991\n16992\n16993\n16994\n16995\n16996\n16997\n16998\n16999\n1699A\n1699B\n1699C\n1699D\n1699E\n1699F\n169A0\n169A1\n169A2\n169A3\n169A4\n169A5\n169A6\n169A7\n169A8\n169A9\n169AA\n169AB\n169AC\n169AD\n169AE\n169AF\n169B0\n169B1\n169B2\n169B3\n169B4\n169B5\n169B6\n169B7\n169B8\n169B9\n169BA\n169BB\n169BC\n169BD\n169BE\n169BF\n169C0\n169C1\n169C2\n169C3\n169C4\n169C5\n169C6\n169C7\n169C8\n169C9\n169CA\n169CB\n169CC\n169CD\n169CE\n169CF\n169D0\n169D1\n169D2\n169D3\n169D4\n169D5\n169D6\n169D7\n169D8\n169D9\n169DA\n169DB\n169DC\n169DD\n169DE\n169DF\n169E0\n169E1\n169E2\n169E3\n169E4\n169E5\n169E6\n169E7\n169E8\n169E9\n169EA\n169EB\n169EC\n169ED\n169EE\n169EF\n169F0\n169F1\n169F2\n169F3\n169F4\n169F5\n169F6\n169F7\n169F8\n169F9\n169FA\n169FB\n169FC\n169FD\n169FE\n169FF\n16A00\n16A01\n16A02\n16A03\n16A04\n16A05\n16A06\n16A07\n16A08\n16A09\n16A0A\n16A0B\n16A0C\n16A0D\n16A0E\n16A0F\n16A10\n16A11\n16A12\n16A13\n16A14\n16A15\n16A16\n16A17\n16A18\n16A19\n16A1A\n16A1B\n16A1C\n16A1D\n16A1E\n16A1F\n16A20\n16A21\n16A22\n16A23\n16A24\n16A25\n16A26\n16A27\n16A28\n16A29\n16A2A\n16A2B\n16A2C\n16A2D\n16A2E\n16A2F\n16A30\n16A31\n16A32\n16A33\n16A34\n16A35\n16A36\n16A37\n16A38\n16A40\n16A41\n16A42\n16A43\n16A44\n16A45\n16A46\n16A47\n16A48\n16A49\n16A4A\n16A4B\n16A4C\n16A4D\n16A4E\n16A4F\n16A50\n16A51\n16A52\n16A53\n16A54\n16A55\n16A56\n16A57\n16A58\n16A59\n16A5A\n16A5B\n16A5C\n16A5D\n16A5E\n16A60\n16A61\n16A62\n16A63\n16A64\n16A65\n16A66\n16A67\n16A68\n16A69\n16A6E\n16A6F\n16AD0\n16AD1\n16AD2\n16AD3\n16AD4\n16AD5\n16AD6\n16AD7\n16AD8\n16AD9\n16ADA\n16ADB\n16ADC\n16ADD\n16ADE\n16ADF\n16AE0\n16AE1\n16AE2\n16AE3\n16AE4\n16AE5\n16AE6\n16AE7\n16AE8\n16AE9\n16AEA\n16AEB\n16AEC\n16AED\n16AF0\n16AF1\n16AF2\n16AF3\n16AF4\n16AF5\n16B00\n16B01\n16B02\n16B03\n16B04\n16B05\n16B06\n16B07\n16B08\n16B09\n16B0A\n16B0B\n16B0C\n16B0D\n16B0E\n16B0F\n16B10\n16B11\n16B12\n16B13\n16B14\n16B15\n16B16\n16B17\n16B18\n16B19\n16B1A\n16B1B\n16B1C\n16B1D\n16B1E\n16B1F\n16B20\n16B21\n16B22\n16B23\n16B24\n16B25\n16B26\n16B27\n16B28\n16B29\n16B2A\n16B2B\n16B2C\n16B2D\n16B2E\n16B2F\n16B30\n16B31\n16B32\n16B33\n16B34\n16B35\n16B36\n16B37\n16B38\n16B39\n16B3A\n16B3B\n16B3C\n16B3D\n16B3E\n16B3F\n16B40\n16B41\n16B42\n16B43\n16B44\n16B45\n16B50\n16B51\n16B52\n16B53\n16B54\n16B55\n16B56\n16B57\n16B58\n16B59\n16B5B\n16B5C\n16B5D\n16B5E\n16B5F\n16B60\n16B61\n16B63\n16B64\n16B65\n16B66\n16B67\n16B68\n16B69\n16B6A\n16B6B\n16B6C\n16B6D\n16B6E\n16B6F\n16B70\n16B71\n16B72\n16B73\n16B74\n16B75\n16B76\n16B77\n16B7D\n16B7E\n16B7F\n16B80\n16B81\n16B82\n16B83\n16B84\n16B85\n16B86\n16B87\n16B88\n16B89\n16B8A\n16B8B\n16B8C\n16B8D\n16B8E\n16B8F\n16F00\n16F01\n16F02\n16F03\n16F04\n16F05\n16F06\n16F07\n16F08\n16F09\n16F0A\n16F0B\n16F0C\n16F0D\n16F0E\n16F0F\n16F10\n16F11\n16F12\n16F13\n16F14\n16F15\n16F16\n16F17\n16F18\n16F19\n16F1A\n16F1B\n16F1C\n16F1D\n16F1E\n16F1F\n16F20\n16F21\n16F22\n16F23\n16F24\n16F25\n16F26\n16F27\n16F28\n16F29\n16F2A\n16F2B\n16F2C\n16F2D\n16F2E\n16F2F\n16F30\n16F31\n16F32\n16F33\n16F34\n16F35\n16F36\n16F37\n16F38\n16F39\n16F3A\n16F3B\n16F3C\n16F3D\n16F3E\n16F3F\n16F40\n16F41\n16F42\n16F43\n16F44\n16F50\n16F51\n16F52\n16F53\n16F54\n16F55\n16F56\n16F57\n16F58\n16F59\n16F5A\n16F5B\n16F5C\n16F5D\n16F5E\n16F5F\n16F60\n16F61\n16F62\n16F63\n16F64\n16F65\n16F66\n16F67\n16F68\n16F69\n16F6A\n16F6B\n16F6C\n16F6D\n16F6E\n16F6F\n16F70\n16F71\n16F72\n16F73\n16F74\n16F75\n16F76\n16F77\n16F78\n16F79\n16F7A\n16F7B\n16F7C\n16F7D\n16F7E\n16F8F\n16F90\n16F91\n16F92\n16F93\n16F94\n16F95\n16F96\n16F97\n16F98\n16F99\n16F9A\n16F9B\n16F9C\n16F9D\n16F9E\n16F9F\n1B000\n1B001\n1BC00\n1BC01\n1BC02\n1BC03\n1BC04\n1BC05\n1BC06\n1BC07\n1BC08\n1BC09\n1BC0A\n1BC0B\n1BC0C\n1BC0D\n1BC0E\n1BC0F\n1BC10\n1BC11\n1BC12\n1BC13\n1BC14\n1BC15\n1BC16\n1BC17\n1BC18\n1BC19\n1BC1A\n1BC1B\n1BC1C\n1BC1D\n1BC1E\n1BC1F\n1BC20\n1BC21\n1BC22\n1BC23\n1BC24\n1BC25\n1BC26\n1BC27\n1BC28\n1BC29\n1BC2A\n1BC2B\n1BC2C\n1BC2D\n1BC2E\n1BC2F\n1BC30\n1BC31\n1BC32\n1BC33\n1BC34\n1BC35\n1BC36\n1BC37\n1BC38\n1BC39\n1BC3A\n1BC3B\n1BC3C\n1BC3D\n1BC3E\n1BC3F\n1BC40\n1BC41\n1BC42\n1BC43\n1BC44\n1BC45\n1BC46\n1BC47\n1BC48\n1BC49\n1BC4A\n1BC4B\n1BC4C\n1BC4D\n1BC4E\n1BC4F\n1BC50\n1BC51\n1BC52\n1BC53\n1BC54\n1BC55\n1BC56\n1BC57\n1BC58\n1BC59\n1BC5A\n1BC5B\n1BC5C\n1BC5D\n1BC5E\n1BC5F\n1BC60\n1BC61\n1BC62\n1BC63\n1BC64\n1BC65\n1BC66\n1BC67\n1BC68\n1BC69\n1BC6A\n1BC70\n1BC71\n1BC72\n1BC73\n1BC74\n1BC75\n1BC76\n1BC77\n1BC78\n1BC79\n1BC7A\n1BC7B\n1BC7C\n1BC80\n1BC81\n1BC82\n1BC83\n1BC84\n1BC85\n1BC86\n1BC87\n1BC88\n1BC90\n1BC91\n1BC92\n1BC93\n1BC94\n1BC95\n1BC96\n1BC97\n1BC98\n1BC99\n1BC9C\n1BC9D\n1BC9E\n1BC9F\n1BCA0\n1BCA1\n1BCA2\n1BCA3\n1D000\n1D001\n1D002\n1D003\n1D004\n1D005\n1D006\n1D007\n1D008\n1D009\n1D00A\n1D00B\n1D00C\n1D00D\n1D00E\n1D00F\n1D010\n1D011\n1D012\n1D013\n1D014\n1D015\n1D016\n1D017\n1D018\n1D019\n1D01A\n1D01B\n1D01C\n1D01D\n1D01E\n1D01F\n1D020\n1D021\n1D022\n1D023\n1D024\n1D025\n1D026\n1D027\n1D028\n1D029\n1D02A\n1D02B\n1D02C\n1D02D\n1D02E\n1D02F\n1D030\n1D031\n1D032\n1D033\n1D034\n1D035\n1D036\n1D037\n1D038\n1D039\n1D03A\n1D03B\n1D03C\n1D03D\n1D03E\n1D03F\n1D040\n1D041\n1D042\n1D043\n1D044\n1D045\n1D046\n1D047\n1D048\n1D049\n1D04A\n1D04B\n1D04C\n1D04D\n1D04E\n1D04F\n1D050\n1D051\n1D052\n1D053\n1D054\n1D055\n1D056\n1D057\n1D058\n1D059\n1D05A\n1D05B\n1D05C\n1D05D\n1D05E\n1D05F\n1D060\n1D061\n1D062\n1D063\n1D064\n1D065\n1D066\n1D067\n1D068\n1D069\n1D06A\n1D06B\n1D06C\n1D06D\n1D06E\n1D06F\n1D070\n1D071\n1D072\n1D073\n1D074\n1D075\n1D076\n1D077\n1D078\n1D079\n1D07A\n1D07B\n1D07C\n1D07D\n1D07E\n1D07F\n1D080\n1D081\n1D082\n1D083\n1D084\n1D085\n1D086\n1D087\n1D088\n1D089\n1D08A\n1D08B\n1D08C\n1D08D\n1D08E\n1D08F\n1D090\n1D091\n1D092\n1D093\n1D094\n1D095\n1D096\n1D097\n1D098\n1D099\n1D09A\n1D09B\n1D09C\n1D09D\n1D09E\n1D09F\n1D0A0\n1D0A1\n1D0A2\n1D0A3\n1D0A4\n1D0A5\n1D0A6\n1D0A7\n1D0A8\n1D0A9\n1D0AA\n1D0AB\n1D0AC\n1D0AD\n1D0AE\n1D0AF\n1D0B0\n1D0B1\n1D0B2\n1D0B3\n1D0B4\n1D0B5\n1D0B6\n1D0B7\n1D0B8\n1D0B9\n1D0BA\n1D0BB\n1D0BC\n1D0BD\n1D0BE\n1D0BF\n1D0C0\n1D0C1\n1D0C2\n1D0C3\n1D0C4\n1D0C5\n1D0C6\n1D0C7\n1D0C8\n1D0C9\n1D0CA\n1D0CB\n1D0CC\n1D0CD\n1D0CE\n1D0CF\n1D0D0\n1D0D1\n1D0D2\n1D0D3\n1D0D4\n1D0D5\n1D0D6\n1D0D7\n1D0D8\n1D0D9\n1D0DA\n1D0DB\n1D0DC\n1D0DD\n1D0DE\n1D0DF\n1D0E0\n1D0E1\n1D0E2\n1D0E3\n1D0E4\n1D0E5\n1D0E6\n1D0E7\n1D0E8\n1D0E9\n1D0EA\n1D0EB\n1D0EC\n1D0ED\n1D0EE\n1D0EF\n1D0F0\n1D0F1\n1D0F2\n1D0F3\n1D0F4\n1D0F5\n1D100\n1D101\n1D102\n1D103\n1D104\n1D105\n1D106\n1D107\n1D108\n1D109\n1D10A\n1D10B\n1D10C\n1D10D\n1D10E\n1D10F\n1D110\n1D111\n1D112\n1D113\n1D114\n1D115\n1D116\n1D117\n1D118\n1D119\n1D11A\n1D11B\n1D11C\n1D11D\n1D11E\n1D11F\n1D120\n1D121\n1D122\n1D123\n1D124\n1D125\n1D126\n1D129\n1D12A\n1D12B\n1D12C\n1D12D\n1D12E\n1D12F\n1D130\n1D131\n1D132\n1D133\n1D134\n1D135\n1D136\n1D137\n1D138\n1D139\n1D13A\n1D13B\n1D13C\n1D13D\n1D13E\n1D13F\n1D140\n1D141\n1D142\n1D143\n1D144\n1D145\n1D146\n1D147\n1D148\n1D149\n1D14A\n1D14B\n1D14C\n1D14D\n1D14E\n1D14F\n1D150\n1D151\n1D152\n1D153\n1D154\n1D155\n1D156\n1D157\n1D158\n1D159\n1D15A\n1D15B\n1D15C\n1D15D\n1D15E\n1D15F\n1D160\n1D161\n1D162\n1D163\n1D164\n1D165\n1D166\n1D167\n1D168\n1D169\n1D16A\n1D16B\n1D16C\n1D16D\n1D16E\n1D16F\n1D170\n1D171\n1D172\n1D173\n1D174\n1D175\n1D176\n1D177\n1D178\n1D179\n1D17A\n1D17B\n1D17C\n1D17D\n1D17E\n1D17F\n1D180\n1D181\n1D182\n1D183\n1D184\n1D185\n1D186\n1D187\n1D188\n1D189\n1D18A\n1D18B\n1D18C\n1D18D\n1D18E\n1D18F\n1D190\n1D191\n1D192\n1D193\n1D194\n1D195\n1D196\n1D197\n1D198\n1D199\n1D19A\n1D19B\n1D19C\n1D19D\n1D19E\n1D19F\n1D1A0\n1D1A1\n1D1A2\n1D1A3\n1D1A4\n1D1A5\n1D1A6\n1D1A7\n1D1A8\n1D1A9\n1D1AA\n1D1AB\n1D1AC\n1D1AD\n1D1AE\n1D1AF\n1D1B0\n1D1B1\n1D1B2\n1D1B3\n1D1B4\n1D1B5\n1D1B6\n1D1B7\n1D1B8\n1D1B9\n1D1BA\n1D1BB\n1D1BC\n1D1BD\n1D1BE\n1D1BF\n1D1C0\n1D1C1\n1D1C2\n1D1C3\n1D1C4\n1D1C5\n1D1C6\n1D1C7\n1D1C8\n1D1C9\n1D1CA\n1D1CB\n1D1CC\n1D1CD\n1D1CE\n1D1CF\n1D1D0\n1D1D1\n1D1D2\n1D1D3\n1D1D4\n1D1D5\n1D1D6\n1D1D7\n1D1D8\n1D1D9\n1D1DA\n1D1DB\n1D1DC\n1D1DD\n1D200\n1D201\n1D202\n1D203\n1D204\n1D205\n1D206\n1D207\n1D208\n1D209\n1D20A\n1D20B\n1D20C\n1D20D\n1D20E\n1D20F\n1D210\n1D211\n1D212\n1D213\n1D214\n1D215\n1D216\n1D217\n1D218\n1D219\n1D21A\n1D21B\n1D21C\n1D21D\n1D21E\n1D21F\n1D220\n1D221\n1D222\n1D223\n1D224\n1D225\n1D226\n1D227\n1D228\n1D229\n1D22A\n1D22B\n1D22C\n1D22D\n1D22E\n1D22F\n1D230\n1D231\n1D232\n1D233\n1D234\n1D235\n1D236\n1D237\n1D238\n1D239\n1D23A\n1D23B\n1D23C\n1D23D\n1D23E\n1D23F\n1D240\n1D241\n1D242\n1D243\n1D244\n1D245\n1D300\n1D301\n1D302\n1D303\n1D304\n1D305\n1D306\n1D307\n1D308\n1D309\n1D30A\n1D30B\n1D30C\n1D30D\n1D30E\n1D30F\n1D310\n1D311\n1D312\n1D313\n1D314\n1D315\n1D316\n1D317\n1D318\n1D319\n1D31A\n1D31B\n1D31C\n1D31D\n1D31E\n1D31F\n1D320\n1D321\n1D322\n1D323\n1D324\n1D325\n1D326\n1D327\n1D328\n1D329\n1D32A\n1D32B\n1D32C\n1D32D\n1D32E\n1D32F\n1D330\n1D331\n1D332\n1D333\n1D334\n1D335\n1D336\n1D337\n1D338\n1D339\n1D33A\n1D33B\n1D33C\n1D33D\n1D33E\n1D33F\n1D340\n1D341\n1D342\n1D343\n1D344\n1D345\n1D346\n1D347\n1D348\n1D349\n1D34A\n1D34B\n1D34C\n1D34D\n1D34E\n1D34F\n1D350\n1D351\n1D352\n1D353\n1D354\n1D355\n1D356\n1D360\n1D361\n1D362\n1D363\n1D364\n1D365\n1D366\n1D367\n1D368\n1D369\n1D36A\n1D36B\n1D36C\n1D36D\n1D36E\n1D36F\n1D370\n1D371\n1D400\n1D401\n1D402\n1D403\n1D404\n1D405\n1D406\n1D407\n1D408\n1D409\n1D40A\n1D40B\n1D40C\n1D40D\n1D40E\n1D40F\n1D410\n1D411\n1D412\n1D413\n1D414\n1D415\n1D416\n1D417\n1D418\n1D419\n1D41A\n1D41B\n1D41C\n1D41D\n1D41E\n1D41F\n1D420\n1D421\n1D422\n1D423\n1D424\n1D425\n1D426\n1D427\n1D428\n1D429\n1D42A\n1D42B\n1D42C\n1D42D\n1D42E\n1D42F\n1D430\n1D431\n1D432\n1D433\n1D434\n1D435\n1D436\n1D437\n1D438\n1D439\n1D43A\n1D43B\n1D43C\n1D43D\n1D43E\n1D43F\n1D440\n1D441\n1D442\n1D443\n1D444\n1D445\n1D446\n1D447\n1D448\n1D449\n1D44A\n1D44B\n1D44C\n1D44D\n1D44E\n1D44F\n1D450\n1D451\n1D452\n1D453\n1D454\n1D456\n1D457\n1D458\n1D459\n1D45A\n1D45B\n1D45C\n1D45D\n1D45E\n1D45F\n1D460\n1D461\n1D462\n1D463\n1D464\n1D465\n1D466\n1D467\n1D468\n1D469\n1D46A\n1D46B\n1D46C\n1D46D\n1D46E\n1D46F\n1D470\n1D471\n1D472\n1D473\n1D474\n1D475\n1D476\n1D477\n1D478\n1D479\n1D47A\n1D47B\n1D47C\n1D47D\n1D47E\n1D47F\n1D480\n1D481\n1D482\n1D483\n1D484\n1D485\n1D486\n1D487\n1D488\n1D489\n1D48A\n1D48B\n1D48C\n1D48D\n1D48E\n1D48F\n1D490\n1D491\n1D492\n1D493\n1D494\n1D495\n1D496\n1D497\n1D498\n1D499\n1D49A\n1D49B\n1D49C\n1D49E\n1D49F\n1D4A2\n1D4A5\n1D4A6\n1D4A9\n1D4AA\n1D4AB\n1D4AC\n1D4AE\n1D4AF\n1D4B0\n1D4B1\n1D4B2\n1D4B3\n1D4B4\n1D4B5\n1D4B6\n1D4B7\n1D4B8\n1D4B9\n1D4BB\n1D4BD\n1D4BE\n1D4BF\n1D4C0\n1D4C1\n1D4C2\n1D4C3\n1D4C5\n1D4C6\n1D4C7\n1D4C8\n1D4C9\n1D4CA\n1D4CB\n1D4CC\n1D4CD\n1D4CE\n1D4CF\n1D4D0\n1D4D1\n1D4D2\n1D4D3\n1D4D4\n1D4D5\n1D4D6\n1D4D7\n1D4D8\n1D4D9\n1D4DA\n1D4DB\n1D4DC\n1D4DD\n1D4DE\n1D4DF\n1D4E0\n1D4E1\n1D4E2\n1D4E3\n1D4E4\n1D4E5\n1D4E6\n1D4E7\n1D4E8\n1D4E9\n1D4EA\n1D4EB\n1D4EC\n1D4ED\n1D4EE\n1D4EF\n1D4F0\n1D4F1\n1D4F2\n1D4F3\n1D4F4\n1D4F5\n1D4F6\n1D4F7\n1D4F8\n1D4F9\n1D4FA\n1D4FB\n1D4FC\n1D4FD\n1D4FE\n1D4FF\n1D500\n1D501\n1D502\n1D503\n1D504\n1D505\n1D507\n1D508\n1D509\n1D50A\n1D50D\n1D50E\n1D50F\n1D510\n1D511\n1D512\n1D513\n1D514\n1D516\n1D517\n1D518\n1D519\n1D51A\n1D51B\n1D51C\n1D51E\n1D51F\n1D520\n1D521\n1D522\n1D523\n1D524\n1D525\n1D526\n1D527\n1D528\n1D529\n1D52A\n1D52B\n1D52C\n1D52D\n1D52E\n1D52F\n1D530\n1D531\n1D532\n1D533\n1D534\n1D535\n1D536\n1D537\n1D538\n1D539\n1D53B\n1D53C\n1D53D\n1D53E\n1D540\n1D541\n1D542\n1D543\n1D544\n1D546\n1D54A\n1D54B\n1D54C\n1D54D\n1D54E\n1D54F\n1D550\n1D552\n1D553\n1D554\n1D555\n1D556\n1D557\n1D558\n1D559\n1D55A\n1D55B\n1D55C\n1D55D\n1D55E\n1D55F\n1D560\n1D561\n1D562\n1D563\n1D564\n1D565\n1D566\n1D567\n1D568\n1D569\n1D56A\n1D56B\n1D56C\n1D56D\n1D56E\n1D56F\n1D570\n1D571\n1D572\n1D573\n1D574\n1D575\n1D576\n1D577\n1D578\n1D579\n1D57A\n1D57B\n1D57C\n1D57D\n1D57E\n1D57F\n1D580\n1D581\n1D582\n1D583\n1D584\n1D585\n1D586\n1D587\n1D588\n1D589\n1D58A\n1D58B\n1D58C\n1D58D\n1D58E\n1D58F\n1D590\n1D591\n1D592\n1D593\n1D594\n1D595\n1D596\n1D597\n1D598\n1D599\n1D59A\n1D59B\n1D59C\n1D59D\n1D59E\n1D59F\n1D5A0\n1D5A1\n1D5A2\n1D5A3\n1D5A4\n1D5A5\n1D5A6\n1D5A7\n1D5A8\n1D5A9\n1D5AA\n1D5AB\n1D5AC\n1D5AD\n1D5AE\n1D5AF\n1D5B0\n1D5B1\n1D5B2\n1D5B3\n1D5B4\n1D5B5\n1D5B6\n1D5B7\n1D5B8\n1D5B9\n1D5BA\n1D5BB\n1D5BC\n1D5BD\n1D5BE\n1D5BF\n1D5C0\n1D5C1\n1D5C2\n1D5C3\n1D5C4\n1D5C5\n1D5C6\n1D5C7\n1D5C8\n1D5C9\n1D5CA\n1D5CB\n1D5CC\n1D5CD\n1D5CE\n1D5CF\n1D5D0\n1D5D1\n1D5D2\n1D5D3\n1D5D4\n1D5D5\n1D5D6\n1D5D7\n1D5D8\n1D5D9\n1D5DA\n1D5DB\n1D5DC\n1D5DD\n1D5DE\n1D5DF\n1D5E0\n1D5E1\n1D5E2\n1D5E3\n1D5E4\n1D5E5\n1D5E6\n1D5E7\n1D5E8\n1D5E9\n1D5EA\n1D5EB\n1D5EC\n1D5ED\n1D5EE\n1D5EF\n1D5F0\n1D5F1\n1D5F2\n1D5F3\n1D5F4\n1D5F5\n1D5F6\n1D5F7\n1D5F8\n1D5F9\n1D5FA\n1D5FB\n1D5FC\n1D5FD\n1D5FE\n1D5FF\n1D600\n1D601\n1D602\n1D603\n1D604\n1D605\n1D606\n1D607\n1D608\n1D609\n1D60A\n1D60B\n1D60C\n1D60D\n1D60E\n1D60F\n1D610\n1D611\n1D612\n1D613\n1D614\n1D615\n1D616\n1D617\n1D618\n1D619\n1D61A\n1D61B\n1D61C\n1D61D\n1D61E\n1D61F\n1D620\n1D621\n1D622\n1D623\n1D624\n1D625\n1D626\n1D627\n1D628\n1D629\n1D62A\n1D62B\n1D62C\n1D62D\n1D62E\n1D62F\n1D630\n1D631\n1D632\n1D633\n1D634\n1D635\n1D636\n1D637\n1D638\n1D639\n1D63A\n1D63B\n1D63C\n1D63D\n1D63E\n1D63F\n1D640\n1D641\n1D642\n1D643\n1D644\n1D645\n1D646\n1D647\n1D648\n1D649\n1D64A\n1D64B\n1D64C\n1D64D\n1D64E\n1D64F\n1D650\n1D651\n1D652\n1D653\n1D654\n1D655\n1D656\n1D657\n1D658\n1D659\n1D65A\n1D65B\n1D65C\n1D65D\n1D65E\n1D65F\n1D660\n1D661\n1D662\n1D663\n1D664\n1D665\n1D666\n1D667\n1D668\n1D669\n1D66A\n1D66B\n1D66C\n1D66D\n1D66E\n1D66F\n1D670\n1D671\n1D672\n1D673\n1D674\n1D675\n1D676\n1D677\n1D678\n1D679\n1D67A\n1D67B\n1D67C\n1D67D\n1D67E\n1D67F\n1D680\n1D681\n1D682\n1D683\n1D684\n1D685\n1D686\n1D687\n1D688\n1D689\n1D68A\n1D68B\n1D68C\n1D68D\n1D68E\n1D68F\n1D690\n1D691\n1D692\n1D693\n1D694\n1D695\n1D696\n1D697\n1D698\n1D699\n1D69A\n1D69B\n1D69C\n1D69D\n1D69E\n1D69F\n1D6A0\n1D6A1\n1D6A2\n1D6A3\n1D6A4\n1D6A5\n1D6A8\n1D6A9\n1D6AA\n1D6AB\n1D6AC\n1D6AD\n1D6AE\n1D6AF\n1D6B0\n1D6B1\n1D6B2\n1D6B3\n1D6B4\n1D6B5\n1D6B6\n1D6B7\n1D6B8\n1D6B9\n1D6BA\n1D6BB\n1D6BC\n1D6BD\n1D6BE\n1D6BF\n1D6C0\n1D6C1\n1D6C2\n1D6C3\n1D6C4\n1D6C5\n1D6C6\n1D6C7\n1D6C8\n1D6C9\n1D6CA\n1D6CB\n1D6CC\n1D6CD\n1D6CE\n1D6CF\n1D6D0\n1D6D1\n1D6D2\n1D6D3\n1D6D4\n1D6D5\n1D6D6\n1D6D7\n1D6D8\n1D6D9\n1D6DA\n1D6DB\n1D6DC\n1D6DD\n1D6DE\n1D6DF\n1D6E0\n1D6E1\n1D6E2\n1D6E3\n1D6E4\n1D6E5\n1D6E6\n1D6E7\n1D6E8\n1D6E9\n1D6EA\n1D6EB\n1D6EC\n1D6ED\n1D6EE\n1D6EF\n1D6F0\n1D6F1\n1D6F2\n1D6F3\n1D6F4\n1D6F5\n1D6F6\n1D6F7\n1D6F8\n1D6F9\n1D6FA\n1D6FB\n1D6FC\n1D6FD\n1D6FE\n1D6FF\n1D700\n1D701\n1D702\n1D703\n1D704\n1D705\n1D706\n1D707\n1D708\n1D709\n1D70A\n1D70B\n1D70C\n1D70D\n1D70E\n1D70F\n1D710\n1D711\n1D712\n1D713\n1D714\n1D715\n1D716\n1D717\n1D718\n1D719\n1D71A\n1D71B\n1D71C\n1D71D\n1D71E\n1D71F\n1D720\n1D721\n1D722\n1D723\n1D724\n1D725\n1D726\n1D727\n1D728\n1D729\n1D72A\n1D72B\n1D72C\n1D72D\n1D72E\n1D72F\n1D730\n1D731\n1D732\n1D733\n1D734\n1D735\n1D736\n1D737\n1D738\n1D739\n1D73A\n1D73B\n1D73C\n1D73D\n1D73E\n1D73F\n1D740\n1D741\n1D742\n1D743\n1D744\n1D745\n1D746\n1D747\n1D748\n1D749\n1D74A\n1D74B\n1D74C\n1D74D\n1D74E\n1D74F\n1D750\n1D751\n1D752\n1D753\n1D754\n1D755\n1D756\n1D757\n1D758\n1D759\n1D75A\n1D75B\n1D75C\n1D75D\n1D75E\n1D75F\n1D760\n1D761\n1D762\n1D763\n1D764\n1D765\n1D766\n1D767\n1D768\n1D769\n1D76A\n1D76B\n1D76C\n1D76D\n1D76E\n1D76F\n1D770\n1D771\n1D772\n1D773\n1D774\n1D775\n1D776\n1D777\n1D778\n1D779\n1D77A\n1D77B\n1D77C\n1D77D\n1D77E\n1D77F\n1D780\n1D781\n1D782\n1D783\n1D784\n1D785\n1D786\n1D787\n1D788\n1D789\n1D78A\n1D78B\n1D78C\n1D78D\n1D78E\n1D78F\n1D790\n1D791\n1D792\n1D793\n1D794\n1D795\n1D796\n1D797\n1D798\n1D799\n1D79A\n1D79B\n1D79C\n1D79D\n1D79E\n1D79F\n1D7A0\n1D7A1\n1D7A2\n1D7A3\n1D7A4\n1D7A5\n1D7A6\n1D7A7\n1D7A8\n1D7A9\n1D7AA\n1D7AB\n1D7AC\n1D7AD\n1D7AE\n1D7AF\n1D7B0\n1D7B1\n1D7B2\n1D7B3\n1D7B4\n1D7B5\n1D7B6\n1D7B7\n1D7B8\n1D7B9\n1D7BA\n1D7BB\n1D7BC\n1D7BD\n1D7BE\n1D7BF\n1D7C0\n1D7C1\n1D7C2\n1D7C3\n1D7C4\n1D7C5\n1D7C6\n1D7C7\n1D7C8\n1D7C9\n1D7CA\n1D7CB\n1D7CE\n1D7CF\n1D7D0\n1D7D1\n1D7D2\n1D7D3\n1D7D4\n1D7D5\n1D7D6\n1D7D7\n1D7D8\n1D7D9\n1D7DA\n1D7DB\n1D7DC\n1D7DD\n1D7DE\n1D7DF\n1D7E0\n1D7E1\n1D7E2\n1D7E3\n1D7E4\n1D7E5\n1D7E6\n1D7E7\n1D7E8\n1D7E9\n1D7EA\n1D7EB\n1D7EC\n1D7ED\n1D7EE\n1D7EF\n1D7F0\n1D7F1\n1D7F2\n1D7F3\n1D7F4\n1D7F5\n1D7F6\n1D7F7\n1D7F8\n1D7F9\n1D7FA\n1D7FB\n1D7FC\n1D7FD\n1D7FE\n1D7FF\n1E800\n1E801\n1E802\n1E803\n1E804\n1E805\n1E806\n1E807\n1E808\n1E809\n1E80A\n1E80B\n1E80C\n1E80D\n1E80E\n1E80F\n1E810\n1E811\n1E812\n1E813\n1E814\n1E815\n1E816\n1E817\n1E818\n1E819\n1E81A\n1E81B\n1E81C\n1E81D\n1E81E\n1E81F\n1E820\n1E821\n1E822\n1E823\n1E824\n1E825\n1E826\n1E827\n1E828\n1E829\n1E82A\n1E82B\n1E82C\n1E82D\n1E82E\n1E82F\n1E830\n1E831\n1E832\n1E833\n1E834\n1E835\n1E836\n1E837\n1E838\n1E839\n1E83A\n1E83B\n1E83C\n1E83D\n1E83E\n1E83F\n1E840\n1E841\n1E842\n1E843\n1E844\n1E845\n1E846\n1E847\n1E848\n1E849\n1E84A\n1E84B\n1E84C\n1E84D\n1E84E\n1E84F\n1E850\n1E851\n1E852\n1E853\n1E854\n1E855\n1E856\n1E857\n1E858\n1E859\n1E85A\n1E85B\n1E85C\n1E85D\n1E85E\n1E85F\n1E860\n1E861\n1E862\n1E863\n1E864\n1E865\n1E866\n1E867\n1E868\n1E869\n1E86A\n1E86B\n1E86C\n1E86D\n1E86E\n1E86F\n1E870\n1E871\n1E872\n1E873\n1E874\n1E875\n1E876\n1E877\n1E878\n1E879\n1E87A\n1E87B\n1E87C\n1E87D\n1E87E\n1E87F\n1E880\n1E881\n1E882\n1E883\n1E884\n1E885\n1E886\n1E887\n1E888\n1E889\n1E88A\n1E88B\n1E88C\n1E88D\n1E88E\n1E88F\n1E890\n1E891\n1E892\n1E893\n1E894\n1E895\n1E896\n1E897\n1E898\n1E899\n1E89A\n1E89B\n1E89C\n1E89D\n1E89E\n1E89F\n1E8A0\n1E8A1\n1E8A2\n1E8A3\n1E8A4\n1E8A5\n1E8A6\n1E8A7\n1E8A8\n1E8A9\n1E8AA\n1E8AB\n1E8AC\n1E8AD\n1E8AE\n1E8AF\n1E8B0\n1E8B1\n1E8B2\n1E8B3\n1E8B4\n1E8B5\n1E8B6\n1E8B7\n1E8B8\n1E8B9\n1E8BA\n1E8BB\n1E8BC\n1E8BD\n1E8BE\n1E8BF\n1E8C0\n1E8C1\n1E8C2\n1E8C3\n1E8C4\n1E8C7\n1E8C8\n1E8C9\n1E8CA\n1E8CB\n1E8CC\n1E8CD\n1E8CE\n1E8CF\n1E8D0\n1E8D1\n1E8D2\n1E8D3\n1E8D4\n1E8D5\n1E8D6\n1EE00\n1EE01\n1EE02\n1EE03\n1EE05\n1EE06\n1EE07\n1EE08\n1EE09\n1EE0A\n1EE0B\n1EE0C\n1EE0D\n1EE0E\n1EE0F\n1EE10\n1EE11\n1EE12\n1EE13\n1EE14\n1EE15\n1EE16\n1EE17\n1EE18\n1EE19\n1EE1A\n1EE1B\n1EE1C\n1EE1D\n1EE1E\n1EE1F\n1EE21\n1EE22\n1EE24\n1EE27\n1EE29\n1EE2A\n1EE2B\n1EE2C\n1EE2D\n1EE2E\n1EE2F\n1EE30\n1EE31\n1EE32\n1EE34\n1EE35\n1EE36\n1EE37\n1EE39\n1EE3B\n1EE42\n1EE47\n1EE49\n1EE4B\n1EE4D\n1EE4E\n1EE4F\n1EE51\n1EE52\n1EE54\n1EE57\n1EE59\n1EE5B\n1EE5D\n1EE5F\n1EE61\n1EE62\n1EE64\n1EE67\n1EE68\n1EE69\n1EE6A\n1EE6C\n1EE6D\n1EE6E\n1EE6F\n1EE70\n1EE71\n1EE72\n1EE74\n1EE75\n1EE76\n1EE77\n1EE79\n1EE7A\n1EE7B\n1EE7C\n1EE7E\n1EE80\n1EE81\n1EE82\n1EE83\n1EE84\n1EE85\n1EE86\n1EE87\n1EE88\n1EE89\n1EE8B\n1EE8C\n1EE8D\n1EE8E\n1EE8F\n1EE90\n1EE91\n1EE92\n1EE93\n1EE94\n1EE95\n1EE96\n1EE97\n1EE98\n1EE99\n1EE9A\n1EE9B\n1EEA1\n1EEA2\n1EEA3\n1EEA5\n1EEA6\n1EEA7\n1EEA8\n1EEA9\n1EEAB\n1EEAC\n1EEAD\n1EEAE\n1EEAF\n1EEB0\n1EEB1\n1EEB2\n1EEB3\n1EEB4\n1EEB5\n1EEB6\n1EEB7\n1EEB8\n1EEB9\n1EEBA\n1EEBB\n1EEF0\n1EEF1\n1F000\n1F001\n1F002\n1F003\n1F004\n1F005\n1F006\n1F007\n1F008\n1F009\n1F00A\n1F00B\n1F00C\n1F00D\n1F00E\n1F00F\n1F010\n1F011\n1F012\n1F013\n1F014\n1F015\n1F016\n1F017\n1F018\n1F019\n1F01A\n1F01B\n1F01C\n1F01D\n1F01E\n1F01F\n1F020\n1F021\n1F022\n1F023\n1F024\n1F025\n1F026\n1F027\n1F028\n1F029\n1F02A\n1F02B\n1F030\n1F031\n1F032\n1F033\n1F034\n1F035\n1F036\n1F037\n1F038\n1F039\n1F03A\n1F03B\n1F03C\n1F03D\n1F03E\n1F03F\n1F040\n1F041\n1F042\n1F043\n1F044\n1F045\n1F046\n1F047\n1F048\n1F049\n1F04A\n1F04B\n1F04C\n1F04D\n1F04E\n1F04F\n1F050\n1F051\n1F052\n1F053\n1F054\n1F055\n1F056\n1F057\n1F058\n1F059\n1F05A\n1F05B\n1F05C\n1F05D\n1F05E\n1F05F\n1F060\n1F061\n1F062\n1F063\n1F064\n1F065\n1F066\n1F067\n1F068\n1F069\n1F06A\n1F06B\n1F06C\n1F06D\n1F06E\n1F06F\n1F070\n1F071\n1F072\n1F073\n1F074\n1F075\n1F076\n1F077\n1F078\n1F079\n1F07A\n1F07B\n1F07C\n1F07D\n1F07E\n1F07F\n1F080\n1F081\n1F082\n1F083\n1F084\n1F085\n1F086\n1F087\n1F088\n1F089\n1F08A\n1F08B\n1F08C\n1F08D\n1F08E\n1F08F\n1F090\n1F091\n1F092\n1F093\n1F0A0\n1F0A1\n1F0A2\n1F0A3\n1F0A4\n1F0A5\n1F0A6\n1F0A7\n1F0A8\n1F0A9\n1F0AA\n1F0AB\n1F0AC\n1F0AD\n1F0AE\n1F0B1\n1F0B2\n1F0B3\n1F0B4\n1F0B5\n1F0B6\n1F0B7\n1F0B8\n1F0B9\n1F0BA\n1F0BB\n1F0BC\n1F0BD\n1F0BE\n1F0BF\n1F0C1\n1F0C2\n1F0C3\n1F0C4\n1F0C5\n1F0C6\n1F0C7\n1F0C8\n1F0C9\n1F0CA\n1F0CB\n1F0CC\n1F0CD\n1F0CE\n1F0CF\n1F0D1\n1F0D2\n1F0D3\n1F0D4\n1F0D5\n1F0D6\n1F0D7\n1F0D8\n1F0D9\n1F0DA\n1F0DB\n1F0DC\n1F0DD\n1F0DE\n1F0DF\n1F0E0\n1F0E1\n1F0E2\n1F0E3\n1F0E4\n1F0E5\n1F0E6\n1F0E7\n1F0E8\n1F0E9\n1F0EA\n1F0EB\n1F0EC\n1F0ED\n1F0EE\n1F0EF\n1F0F0\n1F0F1\n1F0F2\n1F0F3\n1F0F4\n1F0F5\n1F100\n1F101\n1F102\n1F103\n1F104\n1F105\n1F106\n1F107\n1F108\n1F109\n1F10A\n1F10B\n1F10C\n1F110\n1F111\n1F112\n1F113\n1F114\n1F115\n1F116\n1F117\n1F118\n1F119\n1F11A\n1F11B\n1F11C\n1F11D\n1F11E\n1F11F\n1F120\n1F121\n1F122\n1F123\n1F124\n1F125\n1F126\n1F127\n1F128\n1F129\n1F12A\n1F12B\n1F12C\n1F12D\n1F12E\n1F130\n1F131\n1F132\n1F133\n1F134\n1F135\n1F136\n1F137\n1F138\n1F139\n1F13A\n1F13B\n1F13C\n1F13D\n1F13E\n1F13F\n1F140\n1F141\n1F142\n1F143\n1F144\n1F145\n1F146\n1F147\n1F148\n1F149\n1F14A\n1F14B\n1F14C\n1F14D\n1F14E\n1F14F\n1F150\n1F151\n1F152\n1F153\n1F154\n1F155\n1F156\n1F157\n1F158\n1F159\n1F15A\n1F15B\n1F15C\n1F15D\n1F15E\n1F15F\n1F160\n1F161\n1F162\n1F163\n1F164\n1F165\n1F166\n1F167\n1F168\n1F169\n1F16A\n1F16B\n1F170\n1F171\n1F172\n1F173\n1F174\n1F175\n1F176\n1F177\n1F178\n1F179\n1F17A\n1F17B\n1F17C\n1F17D\n1F17E\n1F17F\n1F180\n1F181\n1F182\n1F183\n1F184\n1F185\n1F186\n1F187\n1F188\n1F189\n1F18A\n1F18B\n1F18C\n1F18D\n1F18E\n1F18F\n1F190\n1F191\n1F192\n1F193\n1F194\n1F195\n1F196\n1F197\n1F198\n1F199\n1F19A\n1F1E6\n1F1E7\n1F1E8\n1F1E9\n1F1EA\n1F1EB\n1F1EC\n1F1ED\n1F1EE\n1F1EF\n1F1F0\n1F1F1\n1F1F2\n1F1F3\n1F1F4\n1F1F5\n1F1F6\n1F1F7\n1F1F8\n1F1F9\n1F1FA\n1F1FB\n1F1FC\n1F1FD\n1F1FE\n1F1FF\n1F200\n1F201\n1F202\n1F210\n1F211\n1F212\n1F213\n1F214\n1F215\n1F216\n1F217\n1F218\n1F219\n1F21A\n1F21B\n1F21C\n1F21D\n1F21E\n1F21F\n1F220\n1F221\n1F222\n1F223\n1F224\n1F225\n1F226\n1F227\n1F228\n1F229\n1F22A\n1F22B\n1F22C\n1F22D\n1F22E\n1F22F\n1F230\n1F231\n1F232\n1F233\n1F234\n1F235\n1F236\n1F237\n1F238\n1F239\n1F23A\n1F240\n1F241\n1F242\n1F243\n1F244\n1F245\n1F246\n1F247\n1F248\n1F250\n1F251\n1F300\n1F301\n1F302\n1F303\n1F304\n1F305\n1F306\n1F307\n1F308\n1F309\n1F30A\n1F30B\n1F30C\n1F30D\n1F30E\n1F30F\n1F310\n1F311\n1F312\n1F313\n1F314\n1F315\n1F316\n1F317\n1F318\n1F319\n1F31A\n1F31B\n1F31C\n1F31D\n1F31E\n1F31F\n1F320\n1F321\n1F322\n1F323\n1F324\n1F325\n1F326\n1F327\n1F328\n1F329\n1F32A\n1F32B\n1F32C\n1F330\n1F331\n1F332\n1F333\n1F334\n1F335\n1F336\n1F337\n1F338\n1F339\n1F33A\n1F33B\n1F33C\n1F33D\n1F33E\n1F33F\n1F340\n1F341\n1F342\n1F343\n1F344\n1F345\n1F346\n1F347\n1F348\n1F349\n1F34A\n1F34B\n1F34C\n1F34D\n1F34E\n1F34F\n1F350\n1F351\n1F352\n1F353\n1F354\n1F355\n1F356\n1F357\n1F358\n1F359\n1F35A\n1F35B\n1F35C\n1F35D\n1F35E\n1F35F\n1F360\n1F361\n1F362\n1F363\n1F364\n1F365\n1F366\n1F367\n1F368\n1F369\n1F36A\n1F36B\n1F36C\n1F36D\n1F36E\n1F36F\n1F370\n1F371\n1F372\n1F373\n1F374\n1F375\n1F376\n1F377\n1F378\n1F379\n1F37A\n1F37B\n1F37C\n1F37D\n1F380\n1F381\n1F382\n1F383\n1F384\n1F385\n1F386\n1F387\n1F388\n1F389\n1F38A\n1F38B\n1F38C\n1F38D\n1F38E\n1F38F\n1F390\n1F391\n1F392\n1F393\n1F394\n1F395\n1F396\n1F397\n1F398\n1F399\n1F39A\n1F39B\n1F39C\n1F39D\n1F39E\n1F39F\n1F3A0\n1F3A1\n1F3A2\n1F3A3\n1F3A4\n1F3A5\n1F3A6\n1F3A7\n1F3A8\n1F3A9\n1F3AA\n1F3AB\n1F3AC\n1F3AD\n1F3AE\n1F3AF\n1F3B0\n1F3B1\n1F3B2\n1F3B3\n1F3B4\n1F3B5\n1F3B6\n1F3B7\n1F3B8\n1F3B9\n1F3BA\n1F3BB\n1F3BC\n1F3BD\n1F3BE\n1F3BF\n1F3C0\n1F3C1\n1F3C2\n1F3C3\n1F3C4\n1F3C5\n1F3C6\n1F3C7\n1F3C8\n1F3C9\n1F3CA\n1F3CB\n1F3CC\n1F3CD\n1F3CE\n1F3D4\n1F3D5\n1F3D6\n1F3D7\n1F3D8\n1F3D9\n1F3DA\n1F3DB\n1F3DC\n1F3DD\n1F3DE\n1F3DF\n1F3E0\n1F3E1\n1F3E2\n1F3E3\n1F3E4\n1F3E5\n1F3E6\n1F3E7\n1F3E8\n1F3E9\n1F3EA\n1F3EB\n1F3EC\n1F3ED\n1F3EE\n1F3EF\n1F3F0\n1F3F1\n1F3F2\n1F3F3\n1F3F4\n1F3F5\n1F3F6\n1F3F7\n1F400\n1F401\n1F402\n1F403\n1F404\n1F405\n1F406\n1F407\n1F408\n1F409\n1F40A\n1F40B\n1F40C\n1F40D\n1F40E\n1F40F\n1F410\n1F411\n1F412\n1F413\n1F414\n1F415\n1F416\n1F417\n1F418\n1F419\n1F41A\n1F41B\n1F41C\n1F41D\n1F41E\n1F41F\n1F420\n1F421\n1F422\n1F423\n1F424\n1F425\n1F426\n1F427\n1F428\n1F429\n1F42A\n1F42B\n1F42C\n1F42D\n1F42E\n1F42F\n1F430\n1F431\n1F432\n1F433\n1F434\n1F435\n1F436\n1F437\n1F438\n1F439\n1F43A\n1F43B\n1F43C\n1F43D\n1F43E\n1F43F\n1F440\n1F441\n1F442\n1F443\n1F444\n1F445\n1F446\n1F447\n1F448\n1F449\n1F44A\n1F44B\n1F44C\n1F44D\n1F44E\n1F44F\n1F450\n1F451\n1F452\n1F453\n1F454\n1F455\n1F456\n1F457\n1F458\n1F459\n1F45A\n1F45B\n1F45C\n1F45D\n1F45E\n1F45F\n1F460\n1F461\n1F462\n1F463\n1F464\n1F465\n1F466\n1F467\n1F468\n1F469\n1F46A\n1F46B\n1F46C\n1F46D\n1F46E\n1F46F\n1F470\n1F471\n1F472\n1F473\n1F474\n1F475\n1F476\n1F477\n1F478\n1F479\n1F47A\n1F47B\n1F47C\n1F47D\n1F47E\n1F47F\n1F480\n1F481\n1F482\n1F483\n1F484\n1F485\n1F486\n1F487\n1F488\n1F489\n1F48A\n1F48B\n1F48C\n1F48D\n1F48E\n1F48F\n1F490\n1F491\n1F492\n1F493\n1F494\n1F495\n1F496\n1F497\n1F498\n1F499\n1F49A\n1F49B\n1F49C\n1F49D\n1F49E\n1F49F\n1F4A0\n1F4A1\n1F4A2\n1F4A3\n1F4A4\n1F4A5\n1F4A6\n1F4A7\n1F4A8\n1F4A9\n1F4AA\n1F4AB\n1F4AC\n1F4AD\n1F4AE\n1F4AF\n1F4B0\n1F4B1\n1F4B2\n1F4B3\n1F4B4\n1F4B5\n1F4B6\n1F4B7\n1F4B8\n1F4B9\n1F4BA\n1F4BB\n1F4BC\n1F4BD\n1F4BE\n1F4BF\n1F4C0\n1F4C1\n1F4C2\n1F4C3\n1F4C4\n1F4C5\n1F4C6\n1F4C7\n1F4C8\n1F4C9\n1F4CA\n1F4CB\n1F4CC\n1F4CD\n1F4CE\n1F4CF\n1F4D0\n1F4D1\n1F4D2\n1F4D3\n1F4D4\n1F4D5\n1F4D6\n1F4D7\n1F4D8\n1F4D9\n1F4DA\n1F4DB\n1F4DC\n1F4DD\n1F4DE\n1F4DF\n1F4E0\n1F4E1\n1F4E2\n1F4E3\n1F4E4\n1F4E5\n1F4E6\n1F4E7\n1F4E8\n1F4E9\n1F4EA\n1F4EB\n1F4EC\n1F4ED\n1F4EE\n1F4EF\n1F4F0\n1F4F1\n1F4F2\n1F4F3\n1F4F4\n1F4F5\n1F4F6\n1F4F7\n1F4F8\n1F4F9\n1F4FA\n1F4FB\n1F4FC\n1F4FD\n1F4FE\n1F500\n1F501\n1F502\n1F503\n1F504\n1F505\n1F506\n1F507\n1F508\n1F509\n1F50A\n1F50B\n1F50C\n1F50D\n1F50E\n1F50F\n1F510\n1F511\n1F512\n1F513\n1F514\n1F515\n1F516\n1F517\n1F518\n1F519\n1F51A\n1F51B\n1F51C\n1F51D\n1F51E\n1F51F\n1F520\n1F521\n1F522\n1F523\n1F524\n1F525\n1F526\n1F527\n1F528\n1F529\n1F52A\n1F52B\n1F52C\n1F52D\n1F52E\n1F52F\n1F530\n1F531\n1F532\n1F533\n1F534\n1F535\n1F536\n1F537\n1F538\n1F539\n1F53A\n1F53B\n1F53C\n1F53D\n1F53E\n1F53F\n1F540\n1F541\n1F542\n1F543\n1F544\n1F545\n1F546\n1F547\n1F548\n1F549\n1F54A\n1F550\n1F551\n1F552\n1F553\n1F554\n1F555\n1F556\n1F557\n1F558\n1F559\n1F55A\n1F55B\n1F55C\n1F55D\n1F55E\n1F55F\n1F560\n1F561\n1F562\n1F563\n1F564\n1F565\n1F566\n1F567\n1F568\n1F569\n1F56A\n1F56B\n1F56C\n1F56D\n1F56E\n1F56F\n1F570\n1F571\n1F572\n1F573\n1F574\n1F575\n1F576\n1F577\n1F578\n1F579\n1F57B\n1F57C\n1F57D\n1F57E\n1F57F\n1F580\n1F581\n1F582\n1F583\n1F584\n1F585\n1F586\n1F587\n1F588\n1F589\n1F58A\n1F58B\n1F58C\n1F58D\n1F58E\n1F58F\n1F590\n1F591\n1F592\n1F593\n1F594\n1F595\n1F596\n1F597\n1F598\n1F599\n1F59A\n1F59B\n1F59C\n1F59D\n1F59E\n1F59F\n1F5A0\n1F5A1\n1F5A2\n1F5A3\n1F5A5\n1F5A6\n1F5A7\n1F5A8\n1F5A9\n1F5AA\n1F5AB\n1F5AC\n1F5AD\n1F5AE\n1F5AF\n1F5B0\n1F5B1\n1F5B2\n1F5B3\n1F5B4\n1F5B5\n1F5B6\n1F5B7\n1F5B8\n1F5B9\n1F5BA\n1F5BB\n1F5BC\n1F5BD\n1F5BE\n1F5BF\n1F5C0\n1F5C1\n1F5C2\n1F5C3\n1F5C4\n1F5C5\n1F5C6\n1F5C7\n1F5C8\n1F5C9\n1F5CA\n1F5CB\n1F5CC\n1F5CD\n1F5CE\n1F5CF\n1F5D0\n1F5D1\n1F5D2\n1F5D3\n1F5D4\n1F5D5\n1F5D6\n1F5D7\n1F5D8\n1F5D9\n1F5DA\n1F5DB\n1F5DC\n1F5DD\n1F5DE\n1F5DF\n1F5E0\n1F5E1\n1F5E2\n1F5E3\n1F5E4\n1F5E5\n1F5E6\n1F5E7\n1F5E8\n1F5E9\n1F5EA\n1F5EB\n1F5EC\n1F5ED\n1F5EE\n1F5EF\n1F5F0\n1F5F1\n1F5F2\n1F5F3\n1F5F4\n1F5F5\n1F5F6\n1F5F7\n1F5F8\n1F5F9\n1F5FA\n1F5FB\n1F5FC\n1F5FD\n1F5FE\n1F5FF\n1F600\n1F601\n1F602\n1F603\n1F604\n1F605\n1F606\n1F607\n1F608\n1F609\n1F60A\n1F60B\n1F60C\n1F60D\n1F60E\n1F60F\n1F610\n1F611\n1F612\n1F613\n1F614\n1F615\n1F616\n1F617\n1F618\n1F619\n1F61A\n1F61B\n1F61C\n1F61D\n1F61E\n1F61F\n1F620\n1F621\n1F622\n1F623\n1F624\n1F625\n1F626\n1F627\n1F628\n1F629\n1F62A\n1F62B\n1F62C\n1F62D\n1F62E\n1F62F\n1F630\n1F631\n1F632\n1F633\n1F634\n1F635\n1F636\n1F637\n1F638\n1F639\n1F63A\n1F63B\n1F63C\n1F63D\n1F63E\n1F63F\n1F640\n1F641\n1F642\n1F645\n1F646\n1F647\n1F648\n1F649\n1F64A\n1F64B\n1F64C\n1F64D\n1F64E\n1F64F\n1F650\n1F651\n1F652\n1F653\n1F654\n1F655\n1F656\n1F657\n1F658\n1F659\n1F65A\n1F65B\n1F65C\n1F65D\n1F65E\n1F65F\n1F660\n1F661\n1F662\n1F663\n1F664\n1F665\n1F666\n1F667\n1F668\n1F669\n1F66A\n1F66B\n1F66C\n1F66D\n1F66E\n1F66F\n1F670\n1F671\n1F672\n1F673\n1F674\n1F675\n1F676\n1F677\n1F678\n1F679\n1F67A\n1F67B\n1F67C\n1F67D\n1F67E\n1F67F\n1F680\n1F681\n1F682\n1F683\n1F684\n1F685\n1F686\n1F687\n1F688\n1F689\n1F68A\n1F68B\n1F68C\n1F68D\n1F68E\n1F68F\n1F690\n1F691\n1F692\n1F693\n1F694\n1F695\n1F696\n1F697\n1F698\n1F699\n1F69A\n1F69B\n1F69C\n1F69D\n1F69E\n1F69F\n1F6A0\n1F6A1\n1F6A2\n1F6A3\n1F6A4\n1F6A5\n1F6A6\n1F6A7\n1F6A8\n1F6A9\n1F6AA\n1F6AB\n1F6AC\n1F6AD\n1F6AE\n1F6AF\n1F6B0\n1F6B1\n1F6B2\n1F6B3\n1F6B4\n1F6B5\n1F6B6\n1F6B7\n1F6B8\n1F6B9\n1F6BA\n1F6BB\n1F6BC\n1F6BD\n1F6BE\n1F6BF\n1F6C0\n1F6C1\n1F6C2\n1F6C3\n1F6C4\n1F6C5\n1F6C6\n1F6C7\n1F6C8\n1F6C9\n1F6CA\n1F6CB\n1F6CC\n1F6CD\n1F6CE\n1F6CF\n1F6E0\n1F6E1\n1F6E2\n1F6E3\n1F6E4\n1F6E5\n1F6E6\n1F6E7\n1F6E8\n1F6E9\n1F6EA\n1F6EB\n1F6EC\n1F6F0\n1F6F1\n1F6F2\n1F6F3\n1F700\n1F701\n1F702\n1F703\n1F704\n1F705\n1F706\n1F707\n1F708\n1F709\n1F70A\n1F70B\n1F70C\n1F70D\n1F70E\n1F70F\n1F710\n1F711\n1F712\n1F713\n1F714\n1F715\n1F716\n1F717\n1F718\n1F719\n1F71A\n1F71B\n1F71C\n1F71D\n1F71E\n1F71F\n1F720\n1F721\n1F722\n1F723\n1F724\n1F725\n1F726\n1F727\n1F728\n1F729\n1F72A\n1F72B\n1F72C\n1F72D\n1F72E\n1F72F\n1F730\n1F731\n1F732\n1F733\n1F734\n1F735\n1F736\n1F737\n1F738\n1F739\n1F73A\n1F73B\n1F73C\n1F73D\n1F73E\n1F73F\n1F740\n1F741\n1F742\n1F743\n1F744\n1F745\n1F746\n1F747\n1F748\n1F749\n1F74A\n1F74B\n1F74C\n1F74D\n1F74E\n1F74F\n1F750\n1F751\n1F752\n1F753\n1F754\n1F755\n1F756\n1F757\n1F758\n1F759\n1F75A\n1F75B\n1F75C\n1F75D\n1F75E\n1F75F\n1F760\n1F761\n1F762\n1F763\n1F764\n1F765\n1F766\n1F767\n1F768\n1F769\n1F76A\n1F76B\n1F76C\n1F76D\n1F76E\n1F76F\n1F770\n1F771\n1F772\n1F773\n1F780\n1F781\n1F782\n1F783\n1F784\n1F785\n1F786\n1F787\n1F788\n1F789\n1F78A\n1F78B\n1F78C\n1F78D\n1F78E\n1F78F\n1F790\n1F791\n1F792\n1F793\n1F794\n1F795\n1F796\n1F797\n1F798\n1F799\n1F79A\n1F79B\n1F79C\n1F79D\n1F79E\n1F79F\n1F7A0\n1F7A1\n1F7A2\n1F7A3\n1F7A4\n1F7A5\n1F7A6\n1F7A7\n1F7A8\n1F7A9\n1F7AA\n1F7AB\n1F7AC\n1F7AD\n1F7AE\n1F7AF\n1F7B0\n1F7B1\n1F7B2\n1F7B3\n1F7B4\n1F7B5\n1F7B6\n1F7B7\n1F7B8\n1F7B9\n1F7BA\n1F7BB\n1F7BC\n1F7BD\n1F7BE\n1F7BF\n1F7C0\n1F7C1\n1F7C2\n1F7C3\n1F7C4\n1F7C5\n1F7C6\n1F7C7\n1F7C8\n1F7C9\n1F7CA\n1F7CB\n1F7CC\n1F7CD\n1F7CE\n1F7CF\n1F7D0\n1F7D1\n1F7D2\n1F7D3\n1F7D4\n1F800\n1F801\n1F802\n1F803\n1F804\n1F805\n1F806\n1F807\n1F808\n1F809\n1F80A\n1F80B\n1F810\n1F811\n1F812\n1F813\n1F814\n1F815\n1F816\n1F817\n1F818\n1F819\n1F81A\n1F81B\n1F81C\n1F81D\n1F81E\n1F81F\n1F820\n1F821\n1F822\n1F823\n1F824\n1F825\n1F826\n1F827\n1F828\n1F829\n1F82A\n1F82B\n1F82C\n1F82D\n1F82E\n1F82F\n1F830\n1F831\n1F832\n1F833\n1F834\n1F835\n1F836\n1F837\n1F838\n1F839\n1F83A\n1F83B\n1F83C\n1F83D\n1F83E\n1F83F\n1F840\n1F841\n1F842\n1F843\n1F844\n1F845\n1F846\n1F847\n1F850\n1F851\n1F852\n1F853\n1F854\n1F855\n1F856\n1F857\n1F858\n1F859\n1F860\n1F861\n1F862\n1F863\n1F864\n1F865\n1F866\n1F867\n1F868\n1F869\n1F86A\n1F86B\n1F86C\n1F86D\n1F86E\n1F86F\n1F870\n1F871\n1F872\n1F873\n1F874\n1F875\n1F876\n1F877\n1F878\n1F879\n1F87A\n1F87B\n1F87C\n1F87D\n1F87E\n1F87F\n1F880\n1F881\n1F882\n1F883\n1F884\n1F885\n1F886\n1F887\n1F890\n1F891\n1F892\n1F893\n1F894\n1F895\n1F896\n1F897\n1F898\n1F899\n1F89A\n1F89B\n1F89C\n1F89D\n1F89E\n1F89F\n1F8A0\n1F8A1\n1F8A2\n1F8A3\n1F8A4\n1F8A5\n1F8A6\n1F8A7\n1F8A8\n1F8A9\n1F8AA\n1F8AB\n1F8AC\n1F8AD\n20000\n2A6D6\n2A700\n2B734\n2B740\n2B81D\n2F800\n2F801\n2F802\n2F803\n2F804\n2F805\n2F806\n2F807\n2F808\n2F809\n2F80A\n2F80B\n2F80C\n2F80D\n2F80E\n2F80F\n2F810\n2F811\n2F812\n2F813\n2F814\n2F815\n2F816\n2F817\n2F818\n2F819\n2F81A\n2F81B\n2F81C\n2F81D\n2F81E\n2F81F\n2F820\n2F821\n2F822\n2F823\n2F824\n2F825\n2F826\n2F827\n2F828\n2F829\n2F82A\n2F82B\n2F82C\n2F82D\n2F82E\n2F82F\n2F830\n2F831\n2F832\n2F833\n2F834\n2F835\n2F836\n2F837\n2F838\n2F839\n2F83A\n2F83B\n2F83C\n2F83D\n2F83E\n2F83F\n2F840\n2F841\n2F842\n2F843\n2F844\n2F845\n2F846\n2F847\n2F848\n2F849\n2F84A\n2F84B\n2F84C\n2F84D\n2F84E\n2F84F\n2F850\n2F851\n2F852\n2F853\n2F854\n2F855\n2F856\n2F857\n2F858\n2F859\n2F85A\n2F85B\n2F85C\n2F85D\n2F85E\n2F85F\n2F860\n2F861\n2F862\n2F863\n2F864\n2F865\n2F866\n2F867\n2F868\n2F869\n2F86A\n2F86B\n2F86C\n2F86D\n2F86E\n2F86F\n2F870\n2F871\n2F872\n2F873\n2F874\n2F875\n2F876\n2F877\n2F878\n2F879\n2F87A\n2F87B\n2F87C\n2F87D\n2F87E\n2F87F\n2F880\n2F881\n2F882\n2F883\n2F884\n2F885\n2F886\n2F887\n2F888\n2F889\n2F88A\n2F88B\n2F88C\n2F88D\n2F88E\n2F88F\n2F890\n2F891\n2F892\n2F893\n2F894\n2F895\n2F896\n2F897\n2F898\n2F899\n2F89A\n2F89B\n2F89C\n2F89D\n2F89E\n2F89F\n2F8A0\n2F8A1\n2F8A2\n2F8A3\n2F8A4\n2F8A5\n2F8A6\n2F8A7\n2F8A8\n2F8A9\n2F8AA\n2F8AB\n2F8AC\n2F8AD\n2F8AE\n2F8AF\n2F8B0\n2F8B1\n2F8B2\n2F8B3\n2F8B4\n2F8B5\n2F8B6\n2F8B7\n2F8B8\n2F8B9\n2F8BA\n2F8BB\n2F8BC\n2F8BD\n2F8BE\n2F8BF\n2F8C0\n2F8C1\n2F8C2\n2F8C3\n2F8C4\n2F8C5\n2F8C6\n2F8C7\n2F8C8\n2F8C9\n2F8CA\n2F8CB\n2F8CC\n2F8CD\n2F8CE\n2F8CF\n2F8D0\n2F8D1\n2F8D2\n2F8D3\n2F8D4\n2F8D5\n2F8D6\n2F8D7\n2F8D8\n2F8D9\n2F8DA\n2F8DB\n2F8DC\n2F8DD\n2F8DE\n2F8DF\n2F8E0\n2F8E1\n2F8E2\n2F8E3\n2F8E4\n2F8E5\n2F8E6\n2F8E7\n2F8E8\n2F8E9\n2F8EA\n2F8EB\n2F8EC\n2F8ED\n2F8EE\n2F8EF\n2F8F0\n2F8F1\n2F8F2\n2F8F3\n2F8F4\n2F8F5\n2F8F6\n2F8F7\n2F8F8\n2F8F9\n2F8FA\n2F8FB\n2F8FC\n2F8FD\n2F8FE\n2F8FF\n2F900\n2F901\n2F902\n2F903\n2F904\n2F905\n2F906\n2F907\n2F908\n2F909\n2F90A\n2F90B\n2F90C\n2F90D\n2F90E\n2F90F\n2F910\n2F911\n2F912\n2F913\n2F914\n2F915\n2F916\n2F917\n2F918\n2F919\n2F91A\n2F91B\n2F91C\n2F91D\n2F91E\n2F91F\n2F920\n2F921\n2F922\n2F923\n2F924\n2F925\n2F926\n2F927\n2F928\n2F929\n2F92A\n2F92B\n2F92C\n2F92D\n2F92E\n2F92F\n2F930\n2F931\n2F932\n2F933\n2F934\n2F935\n2F936\n2F937\n2F938\n2F939\n2F93A\n2F93B\n2F93C\n2F93D\n2F93E\n2F93F\n2F940\n2F941\n2F942\n2F943\n2F944\n2F945\n2F946\n2F947\n2F948\n2F949\n2F94A\n2F94B\n2F94C\n2F94D\n2F94E\n2F94F\n2F950\n2F951\n2F952\n2F953\n2F954\n2F955\n2F956\n2F957\n2F958\n2F959\n2F95A\n2F95B\n2F95C\n2F95D\n2F95E\n2F95F\n2F960\n2F961\n2F962\n2F963\n2F964\n2F965\n2F966\n2F967\n2F968\n2F969\n2F96A\n2F96B\n2F96C\n2F96D\n2F96E\n2F96F\n2F970\n2F971\n2F972\n2F973\n2F974\n2F975\n2F976\n2F977\n2F978\n2F979\n2F97A\n2F97B\n2F97C\n2F97D\n2F97E\n2F97F\n2F980\n2F981\n2F982\n2F983\n2F984\n2F985\n2F986\n2F987\n2F988\n2F989\n2F98A\n2F98B\n2F98C\n2F98D\n2F98E\n2F98F\n2F990\n2F991\n2F992\n2F993\n2F994\n2F995\n2F996\n2F997\n2F998\n2F999\n2F99A\n2F99B\n2F99C\n2F99D\n2F99E\n2F99F\n2F9A0\n2F9A1\n2F9A2\n2F9A3\n2F9A4\n2F9A5\n2F9A6\n2F9A7\n2F9A8\n2F9A9\n2F9AA\n2F9AB\n2F9AC\n2F9AD\n2F9AE\n2F9AF\n2F9B0\n2F9B1\n2F9B2\n2F9B3\n2F9B4\n2F9B5\n2F9B6\n2F9B7\n2F9B8\n2F9B9\n2F9BA\n2F9BB\n2F9BC\n2F9BD\n2F9BE\n2F9BF\n2F9C0\n2F9C1\n2F9C2\n2F9C3\n2F9C4\n2F9C5\n2F9C6\n2F9C7\n2F9C8\n2F9C9\n2F9CA\n2F9CB\n2F9CC\n2F9CD\n2F9CE\n2F9CF\n2F9D0\n2F9D1\n2F9D2\n2F9D3\n2F9D4\n2F9D5\n2F9D6\n2F9D7\n2F9D8\n2F9D9\n2F9DA\n2F9DB\n2F9DC\n2F9DD\n2F9DE\n2F9DF\n2F9E0\n2F9E1\n2F9E2\n2F9E3\n2F9E4\n2F9E5\n2F9E6\n2F9E7\n2F9E8\n2F9E9\n2F9EA\n2F9EB\n2F9EC\n2F9ED\n2F9EE\n2F9EF\n2F9F0\n2F9F1\n2F9F2\n2F9F3\n2F9F4\n2F9F5\n2F9F6\n2F9F7\n2F9F8\n2F9F9\n2F9FA\n2F9FB\n2F9FC\n2F9FD\n2F9FE\n2F9FF\n2FA00\n2FA01\n2FA02\n2FA03\n2FA04\n2FA05\n2FA06\n2FA07\n2FA08\n2FA09\n2FA0A\n2FA0B\n2FA0C\n2FA0D\n2FA0E\n2FA0F\n2FA10\n2FA11\n2FA12\n2FA13\n2FA14\n2FA15\n2FA16\n2FA17\n2FA18\n2FA19\n2FA1A\n2FA1B\n2FA1C\n2FA1D\nE0001\nE0020\nE0021\nE0022\nE0023\nE0024\nE0025\nE0026\nE0027\nE0028\nE0029\nE002A\nE002B\nE002C\nE002D\nE002E\nE002F\nE0030\nE0031\nE0032\nE0033\nE0034\nE0035\nE0036\nE0037\nE0038\nE0039\nE003A\nE003B\nE003C\nE003D\nE003E\nE003F\nE0040\nE0041\nE0042\nE0043\nE0044\nE0045\nE0046\nE0047\nE0048\nE0049\nE004A\nE004B\nE004C\nE004D\nE004E\nE004F\nE0050\nE0051\nE0052\nE0053\nE0054\nE0055\nE0056\nE0057\nE0058\nE0059\nE005A\nE005B\nE005C\nE005D\nE005E\nE005F\nE0060\nE0061\nE0062\nE0063\nE0064\nE0065\nE0066\nE0067\nE0068\nE0069\nE006A\nE006B\nE006C\nE006D\nE006E\nE006F\nE0070\nE0071\nE0072\nE0073\nE0074\nE0075\nE0076\nE0077\nE0078\nE0079\nE007A\nE007B\nE007C\nE007D\nE007E\nE007F\nE0100\nE0101\nE0102\nE0103\nE0104\nE0105\nE0106\nE0107\nE0108\nE0109\nE010A\nE010B\nE010C\nE010D\nE010E\nE010F\nE0110\nE0111\nE0112\nE0113\nE0114\nE0115\nE0116\nE0117\nE0118\nE0119\nE011A\nE011B\nE011C\nE011D\nE011E\nE011F\nE0120\nE0121\nE0122\nE0123\nE0124\nE0125\nE0126\nE0127\nE0128\nE0129\nE012A\nE012B\nE012C\nE012D\nE012E\nE012F\nE0130\nE0131\nE0132\nE0133\nE0134\nE0135\nE0136\nE0137\nE0138\nE0139\nE013A\nE013B\nE013C\nE013D\nE013E\nE013F\nE0140\nE0141\nE0142\nE0143\nE0144\nE0145\nE0146\nE0147\nE0148\nE0149\nE014A\nE014B\nE014C\nE014D\nE014E\nE014F\nE0150\nE0151\nE0152\nE0153\nE0154\nE0155\nE0156\nE0157\nE0158\nE0159\nE015A\nE015B\nE015C\nE015D\nE015E\nE015F\nE0160\nE0161\nE0162\nE0163\nE0164\nE0165\nE0166\nE0167\nE0168\nE0169\nE016A\nE016B\nE016C\nE016D\nE016E\nE016F\nE0170\nE0171\nE0172\nE0173\nE0174\nE0175\nE0176\nE0177\nE0178\nE0179\nE017A\nE017B\nE017C\nE017D\nE017E\nE017F\nE0180\nE0181\nE0182\nE0183\nE0184\nE0185\nE0186\nE0187\nE0188\nE0189\nE018A\nE018B\nE018C\nE018D\nE018E\nE018F\nE0190\nE0191\nE0192\nE0193\nE0194\nE0195\nE0196\nE0197\nE0198\nE0199\nE019A\nE019B\nE019C\nE019D\nE019E\nE019F\nE01A0\nE01A1\nE01A2\nE01A3\nE01A4\nE01A5\nE01A6\nE01A7\nE01A8\nE01A9\nE01AA\nE01AB\nE01AC\nE01AD\nE01AE\nE01AF\nE01B0\nE01B1\nE01B2\nE01B3\nE01B4\nE01B5\nE01B6\nE01B7\nE01B8\nE01B9\nE01BA\nE01BB\nE01BC\nE01BD\nE01BE\nE01BF\nE01C0\nE01C1\nE01C2\nE01C3\nE01C4\nE01C5\nE01C6\nE01C7\nE01C8\nE01C9\nE01CA\nE01CB\nE01CC\nE01CD\nE01CE\nE01CF\nE01D0\nE01D1\nE01D2\nE01D3\nE01D4\nE01D5\nE01D6\nE01D7\nE01D8\nE01D9\nE01DA\nE01DB\nE01DC\nE01DD\nE01DE\nE01DF\nE01E0\nE01E1\nE01E2\nE01E3\nE01E4\nE01E5\nE01E6\nE01E7\nE01E8\nE01E9\nE01EA\nE01EB\nE01EC\nE01ED\nE01EE\nE01EF\nF0000\nFFFFD\n100000\n10FFFD"
  },
  {
    "path": "realm/realm-library/src/androidTest/assets/uuid_as_string.json",
    "content": "{\n    \"columnUUID\" : \"027ba5ca-aa12-4afa-9219-e20cc3018599\"\n}"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/ThreadStressTests.java",
    "content": "/*\n * Copyright 2019 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\nimport android.os.Handler;\nimport android.os.HandlerThread;\nimport android.os.Looper;\nimport android.text.TextUtils;\n\nimport org.junit.After;\nimport org.junit.Before;\nimport org.junit.Rule;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.junit.runners.Parameterized;\n\nimport java.util.ArrayList;\nimport java.util.Date;\nimport java.util.List;\nimport java.util.Random;\nimport java.util.concurrent.CopyOnWriteArrayList;\nimport java.util.concurrent.CountDownLatch;\nimport java.util.concurrent.ExecutionException;\nimport java.util.concurrent.ExecutorService;\nimport java.util.concurrent.Executors;\nimport java.util.concurrent.Future;\nimport java.util.concurrent.atomic.AtomicInteger;\nimport java.util.concurrent.atomic.AtomicReference;\n\nimport io.realm.Realm;\nimport io.realm.RealmConfiguration;\nimport io.realm.RealmResults;\nimport io.realm.TestHelper;\nimport io.realm.TestRealmConfigurationFactory;\nimport io.realm.entities.AllTypes;\nimport io.realm.entities.NonLatinFieldNames;\nimport io.realm.log.LogLevel;\nimport io.realm.log.RealmLog;\n\nimport static org.junit.Assert.assertFalse;\nimport static org.junit.Assert.assertNull;\n\n/**\n * Class used to stress test multiple actions across different threads.\n * This doesn't attempt to test correctness beyond \"Don't Crash\".\n *\n * Some error level logging is done during the run of this. This is mostly to make\n * it clearer what has happened in the case a run actually did crash, and doesn't indicate\n * problems with the test as such.\n */\n@RunWith(Parameterized.class)\npublic class ThreadStressTests {\n\n    @Parameterized.Parameters(name = \"Encryption: {0}, ReuseThreads: {1}\")\n    public static List<Boolean[]> parameters() {\n        ArrayList<Boolean[]> list = new ArrayList<>();\n        list.add(new Boolean[] { Boolean.TRUE, Boolean.TRUE });\n        list.add(new Boolean[] { Boolean.TRUE, Boolean.FALSE });\n        list.add(new Boolean[] { Boolean.FALSE, Boolean.TRUE });\n        list.add(new Boolean[] { Boolean.FALSE, Boolean.FALSE });\n        return list;\n    }\n\n    @Rule\n    public final TestRealmConfigurationFactory configFactory = new TestRealmConfigurationFactory();\n\n    @Parameterized.Parameter\n    public boolean reuseThreads;\n    @Parameterized.Parameter(1)\n    public boolean useEncryption;\n\n    private int originalLogLevel;\n    private final static int MAX_THREADS = 100;\n    private final static int MAX_CREATE = 1000;\n    private ExecutorService executor;\n    private RealmConfiguration realmConfig;\n    private Random random;\n    private List<Future> threads = new CopyOnWriteArrayList<>();\n    private AtomicInteger workerThreadId = new AtomicInteger(0);\n\n    enum CRUDAction {\n        CREATE,\n        READ,\n        UPDATE,\n        DELETE\n    }\n\n    public interface AsyncTaskRunner {\n        void run(Realm realm, CountDownLatch success);\n    }\n\n    public interface TaskRunner {\n        void run(Realm realm);\n    }\n\n    @Before\n    public void setUp() {\n        originalLogLevel = RealmLog.getLevel();\n        RealmLog.setLevel(LogLevel.INFO);\n        long seed = System.currentTimeMillis();\n        RealmLog.info(\"Starting stress test with seed: \" + seed);\n        random = new Random(seed);\n        RealmConfiguration.Builder builder = configFactory.createConfigurationBuilder();\n        if (useEncryption) {\n            builder.encryptionKey(TestHelper.getRandomKey(seed));\n        }\n        realmConfig = configFactory.createConfiguration();\n        Realm.deleteRealm(realmConfig);\n        executor = Executors.newFixedThreadPool(reuseThreads ? Math.max(random.nextInt(MAX_THREADS), 1) : MAX_THREADS);\n    }\n\n    @After\n    public void tearDown() {\n        RealmLog.setLevel(originalLogLevel);\n    }\n\n    private void populateTestRealm(Realm realm, int objects) {\n        boolean inTransaction = realm.isInTransaction();\n        if (!inTransaction) {\n            realm.beginTransaction();\n        }\n        realm.deleteAll();\n        for (int i = 0; i < objects; ++i) {\n            AllTypes allTypes = realm.createObject(AllTypes.class);\n            allTypes.setColumnLong(i);\n            allTypes.setColumnBoolean((i % 3) == 0);\n            allTypes.setColumnBinary(new byte[] {1, 2, 3});\n            allTypes.setColumnDate(new Date());\n            allTypes.setColumnDouble(Math.PI);\n            allTypes.setColumnFloat(1.234567F + i);\n\n            allTypes.setColumnString(\"test data \" + i);\n            allTypes.setColumnLong(i);\n            NonLatinFieldNames nonLatinFieldNames = realm.createObject(NonLatinFieldNames.class);\n            nonLatinFieldNames.set델타(i);\n            nonLatinFieldNames.setΔέλτα(i);\n            nonLatinFieldNames.set베타(1.234567F + i);\n            nonLatinFieldNames.setΒήτα(1.234567F + i);\n        }\n        if (!inTransaction) {\n            realm.commitTransaction();\n        }\n    }\n\n    private void populateTestRealm(Realm realm) {\n        populateTestRealm(realm, 1000);\n    }\n\n    @Test\n    public void threadStressTest() throws ExecutionException, InterruptedException {\n        Realm realm = Realm.getInstance(realmConfig);\n        populateTestRealm(realm);\n        try {\n            for (int i = 0; i < MAX_THREADS; i++) {\n                CRUDAction action = CRUDAction.values()[random.nextInt(4)];\n                Runnable task = null;\n                switch(action) {\n                    case CREATE:\n                        task = createObjects(random.nextInt(MAX_CREATE), random.nextBoolean());\n                        break;\n                    case READ:\n                        task = readObjects(random.nextBoolean());\n                        break;\n                    case UPDATE:\n                        task = updateObjects(random.nextBoolean(), random.nextBoolean());\n                        break;\n                    case DELETE:\n                        task = deleteObjects(random.nextBoolean(), random.nextBoolean());\n                        break;\n                }\n                threads.add(executor.submit(task));\n            }\n            for (Future task : threads) {\n                task.get();\n            }\n        } catch (Error e) {\n            RealmLog.error(e);\n            throw e;\n        }\n        realm.close();\n    }\n\n    private Runnable createObjects(int objectsCount, boolean asyncTransaction) {\n        if (asyncTransaction) {\n            return createTaskInHandlerThread((realm, success) -> {\n                RealmLog.info(\"Creating objects (async): \" + Thread.currentThread().getName());\n                realm.executeTransactionAsync(bgRealm -> populateTestRealm(bgRealm, objectsCount), success::countDown);\n            });\n        } else {\n            return createTaskInThread((realm) -> {\n                RealmLog.info(\"Creating objects: \" + Thread.currentThread().getName());\n                populateTestRealm(realm, objectsCount);\n            });\n        }\n    }\n\n    private Runnable deleteObjects(boolean filterObjects, boolean asyncTransaction) {\n        TaskRunner delete = realm -> {\n            if (filterObjects) {\n                realm.where(AllTypes.class)\n                        .lessThan(AllTypes.FIELD_LONG, realm.where(AllTypes.class).count()/2)\n                        .equalTo(AllTypes.FIELD_BOOLEAN, true)\n                        .findAll()\n                        .deleteAllFromRealm();\n            } else {\n                realm.delete(AllTypes.class);\n            }\n        };\n\n        if (asyncTransaction) {\n            return createTaskInHandlerThread(((realm, success) -> {\n                RealmLog.info(\"Deleting objects (async): \" + Thread.currentThread().getName());\n                realm.executeTransactionAsync(delete::run, success::countDown);\n            }));\n        } else {\n            return createTaskInThread((realm) -> {\n                RealmLog.info(\"Deleting objects: \" + Thread.currentThread().getName());\n                realm.executeTransaction(delete::run);\n            });\n        }\n    }\n\n\n    private Runnable updateObjects(boolean filterObjects, boolean asyncTransaction) {\n        TaskRunner update = realm -> {\n            RealmResults<AllTypes> results;\n            if (filterObjects) {\n                results = realm.where(AllTypes.class)\n                        .lessThan(AllTypes.FIELD_LONG, random.nextInt((int) realm.where(AllTypes.class).count() + 1))\n                        .equalTo(AllTypes.FIELD_BOOLEAN, random.nextBoolean())\n                        .findAll();\n            } else {\n                results = realm.where(AllTypes.class).findAll();\n            }\n\n            results.setString(AllTypes.FIELD_STRING, \"Updated: \" + Thread.currentThread().getName());\n            results.setBoolean(AllTypes.FIELD_BOOLEAN, random.nextBoolean());\n        };\n\n        if (asyncTransaction) {\n            return createTaskInHandlerThread(((realm, success) -> {\n                RealmLog.info(\"Updating objects (async): \" + Thread.currentThread().getName());\n                realm.executeTransactionAsync(update::run, success::countDown);\n            }));\n        } else {\n            return createTaskInThread((realm) -> {\n                RealmLog.info(\"Updating objects: \" + Thread.currentThread().getName());\n                realm.executeTransaction(update::run);\n            });\n        }\n    }\n\n    private Runnable readObjects(boolean asyncQuery) {\n        if (asyncQuery) {\n            return createTaskInHandlerThread(new AsyncTaskRunner() {\n                private RealmResults<AllTypes> liveResults;\n                @Override\n                public void run(Realm realm, CountDownLatch success) {\n                    RealmLog.info(\"Reading objects (async): \" + Thread.currentThread().getName());\n                    liveResults = realm.where(AllTypes.class)\n                            .lessThan(AllTypes.FIELD_LONG, random.nextInt((int) realm.where(AllTypes.class).count() + 1))\n                            .equalTo(AllTypes.FIELD_BOOLEAN, random.nextBoolean())\n                            .findAllAsync();\n                    liveResults.addChangeListener((updatedResults, changeSet) -> {\n                        for (AllTypes result : updatedResults) {\n                            assertFalse(TextUtils.isEmpty(result.getColumnString()));\n                        }\n                        if (updatedResults.isLoaded()) {\n                            RealmLog.info(\"Query finished on: \" + Thread.currentThread().getName());\n                            success.countDown();\n                        }\n                    });\n                }\n            });\n        } else {\n            return createTaskInThread((realm) -> {\n                RealmLog.info(\"Reading objects: \" + Thread.currentThread().getName());\n                RealmResults<AllTypes> results = realm.where(AllTypes.class)\n                        .lessThan(AllTypes.FIELD_LONG, random.nextInt((int) realm.where(AllTypes.class).count() + 1))\n                        .equalTo(AllTypes.FIELD_BOOLEAN, random.nextBoolean())\n                        .findAll();\n                for (AllTypes result : results) {\n                    assertFalse(TextUtils.isEmpty(result.getColumnString()));\n                }\n            });\n        }\n    }\n\n    private Runnable createTaskInThread(TaskRunner runnable) {\n        return () -> {\n            Realm realm = Realm.getInstance(realmConfig);\n            runnable.run(realm);\n            realm.close();\n        };\n    }\n\n    private Runnable createTaskInHandlerThread(AsyncTaskRunner wrapper) {\n        return new Runnable() {\n            CountDownLatch successLatch = new CountDownLatch(1);\n            CountDownLatch closeLatch = new CountDownLatch(1);\n            volatile Handler handler;\n            volatile HandlerThread handlerThread;\n            AtomicReference<Realm> realm = new AtomicReference<>(null);\n            AsyncTaskRunner wrapperStrongRef = wrapper;\n\n            @Override\n            public void run() {\n                handlerThread = new HandlerThread(\"HandlerWorker: \" + workerThreadId.incrementAndGet());\n                handlerThread.start();\n                Looper looper = handlerThread.getLooper();\n                handler = new Handler(looper);\n                handler.post(() -> {\n                    realm.set(Realm.getInstance(realmConfig));\n                    wrapperStrongRef.run(realm.get(), successLatch);\n                });\n\n                TestHelper.awaitOrFail(successLatch);\n                handler.post(() -> {\n                    realm.get().close();\n                    closeLatch.countDown();\n                });\n                TestHelper.awaitOrFail(closeLatch);\n                handlerThread.quitSafely();\n            }\n        };\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/BulkInsertTests.java",
    "content": "/*\n * Copyright 2014-2016 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\npackage io.realm;\n\nimport org.bson.types.Decimal128;\nimport org.bson.types.ObjectId;\nimport org.junit.After;\nimport org.junit.Before;\nimport org.junit.Rule;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\n\nimport java.math.BigDecimal;\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.Collections;\nimport java.util.Date;\nimport java.util.List;\nimport java.util.UUID;\n\nimport androidx.test.ext.junit.runners.AndroidJUnit4;\nimport io.realm.entities.AllJavaTypes;\nimport io.realm.entities.AllTypes;\nimport io.realm.entities.AllTypesPrimaryKey;\nimport io.realm.entities.AnimalModule;\nimport io.realm.entities.Cat;\nimport io.realm.entities.CatOwner;\nimport io.realm.entities.CyclicType;\nimport io.realm.entities.CyclicTypePrimaryKey;\nimport io.realm.entities.Dog;\nimport io.realm.entities.DogPrimaryKey;\nimport io.realm.entities.HumanModule;\nimport io.realm.entities.NoPrimaryKeyWithPrimaryKeyObjectRelation;\nimport io.realm.entities.NullTypes;\nimport io.realm.entities.Owner;\nimport io.realm.entities.PrimaryKeyAsBoxedShort;\nimport io.realm.entities.PrimaryKeyAsLong;\nimport io.realm.entities.PrimaryKeyAsString;\nimport io.realm.entities.PrimaryKeyWithNoPrimaryKeyObjectRelation;\nimport io.realm.entities.pojo.AllTypesRealmModel;\nimport io.realm.entities.pojo.InvalidRealmModel;\nimport io.realm.exceptions.RealmException;\nimport io.realm.exceptions.RealmPrimaryKeyConstraintException;\nimport io.realm.internal.modules.CompositeMediator;\nimport io.realm.internal.modules.FilterableMediator;\n\nimport static io.realm.internal.test.ExtraTests.assertArrayEquals;\nimport static org.junit.Assert.assertEquals;\nimport static org.junit.Assert.assertFalse;\nimport static org.junit.Assert.assertNotNull;\nimport static org.junit.Assert.assertNotSame;\nimport static org.junit.Assert.assertNull;\nimport static org.junit.Assert.fail;\n\n@RunWith(AndroidJUnit4.class)\npublic class BulkInsertTests {\n    @Rule\n    public final TestRealmConfigurationFactory configFactory = new TestRealmConfigurationFactory();\n\n    private Realm realm;\n\n    @Before\n    public void setUp() {\n        RealmConfiguration realmConfig = configFactory.createConfiguration();\n        realm = Realm.getInstance(realmConfig);\n    }\n\n    @After\n    public void tearDown() {\n        if (realm != null) {\n            realm.close();\n        }\n    }\n\n    @Test\n    public void insert() {\n        AllJavaTypes obj = new AllJavaTypes();\n        obj.setFieldIgnored(\"cookie\");\n        obj.setFieldId(42);\n        obj.setFieldLong(42);\n        obj.setFieldString(\"obj1\");\n\n        RealmList<AllJavaTypes> list = new RealmList<AllJavaTypes>();\n        list.add(obj);\n\n        Date date = new Date();\n\n        AllJavaTypes allTypes = new AllJavaTypes();\n        allTypes.setFieldString(\"String\");\n        allTypes.setFieldId(1L);\n        allTypes.setFieldLong(1L);\n        allTypes.setFieldFloat(1F);\n        allTypes.setFieldDouble(1D);\n        allTypes.setFieldBoolean(true);\n        allTypes.setFieldDate(date);\n        allTypes.setFieldBinary(new byte[]{1, 2, 3});\n        allTypes.setFieldObject(obj);\n        allTypes.setFieldList(list);\n\n        realm.beginTransaction();\n        realm.insert(allTypes);\n        realm.commitTransaction();\n\n        AllJavaTypes realmTypes = realm.where(AllJavaTypes.class).findFirst();\n\n        assertNotNull(realmTypes);\n        assertNotSame(allTypes, realmTypes); // Objects should not be considered equal\n        assertEquals(allTypes.getFieldString(), realmTypes.getFieldString()); // But they contain the same data\n        assertEquals(allTypes.getFieldLong(), realmTypes.getFieldLong());\n        assertEquals(allTypes.getFieldFloat(), realmTypes.getFieldFloat(), 0);\n        assertEquals(allTypes.getFieldDouble(), realmTypes.getFieldDouble(), 0);\n        assertEquals(allTypes.isFieldBoolean(), realmTypes.isFieldBoolean());\n        assertEquals(allTypes.getFieldDate(), realmTypes.getFieldDate());\n        assertArrayEquals(allTypes.getFieldBinary(), realmTypes.getFieldBinary());\n        assertEquals(allTypes.getFieldObject().getFieldString(), obj.getFieldString());\n        assertEquals(list.size(), realmTypes.getFieldList().size());\n        assertEquals(list.get(0).getFieldString(), realmTypes.getFieldList().get(0).getFieldString());\n        assertEquals(list.get(0).getFieldLong(), realmTypes.getFieldList().get(0).getFieldLong());\n        assertNull(realmTypes.getFieldList().get(0).getFieldIgnored());\n        assertNull(realmTypes.getFieldDecimal128());\n        assertNull(realmTypes.getFieldObjectId());\n        assertNull(realmTypes.getFieldUUID());\n        assertEquals(0, realmTypes.getFieldDecimal128List().size());\n        assertEquals(0, realmTypes.getFieldObjectIdList().size());\n        assertEquals(0, realmTypes.getFieldUUIDList().size());\n\n\n        // Makes sure Dog was not inserted twice in the recursive process.\n        assertEquals(2, realm.where(AllJavaTypes.class).findAll().size());\n    }\n\n    @Test\n    public void insert_realmModel() {\n        AllTypesRealmModel allTypes = new AllTypesRealmModel();\n        allTypes.columnLong = 10;\n        allTypes.columnBoolean = false;\n        allTypes.columnBinary = new byte[]{1, 2, 3};\n        allTypes.columnDate = new Date();\n        allTypes.columnDouble = Math.PI;\n        allTypes.columnFloat = 1.234567f;\n        allTypes.columnString = \"test data\";\n        allTypes.columnByte = 0x2A;\n        allTypes.columnDecimal128 = new Decimal128(BigDecimal.TEN);\n        allTypes.columnObjectId = new ObjectId(TestHelper.generateObjectIdHexString(7));\n        allTypes.columnUUID = UUID.fromString(TestHelper.generateUUIDString(7));\n\n        realm.beginTransaction();\n        realm.insert(allTypes);\n        realm.commitTransaction();\n\n        AllTypesRealmModel first = realm.where(AllTypesRealmModel.class).findFirst();\n        assertNotNull(first);\n        assertEquals(allTypes.columnString, first.columnString);\n        assertEquals(allTypes.columnLong, first.columnLong);\n        assertEquals(allTypes.columnBoolean, first.columnBoolean);\n        assertArrayEquals(allTypes.columnBinary, first.columnBinary);\n        assertEquals(allTypes.columnDate, first.columnDate);\n        assertEquals(allTypes.columnDouble, first.columnDouble, 0.0000001);\n        assertEquals(allTypes.columnFloat, first.columnFloat, 0.0000001);\n        assertEquals(allTypes.columnByte, first.columnByte);\n        assertEquals(allTypes.columnDecimal128, first.columnDecimal128);\n        assertEquals(allTypes.columnObjectId, first.columnObjectId);\n        assertEquals(allTypes.columnUUID, first.columnUUID);\n    }\n\n    @Test\n    public void insert_invalidRealmModel() {\n        InvalidRealmModel invalidRealmModel = new InvalidRealmModel();\n\n        realm.beginTransaction();\n        try {\n            realm.insert(invalidRealmModel);\n            fail(\"Expected Missing Proxy Class Exception\");\n        } catch (RealmException ignored) {\n        } finally {\n            realm.cancelTransaction();\n        }\n    }\n\n    @Test\n    public void insertOrUpdate_nullTypes() {\n        NullTypes nullTypes1 = new NullTypes();\n        nullTypes1.setId(1);\n        nullTypes1.setFieldIntegerNull(1);\n        nullTypes1.setFieldFloatNull(2F);\n        nullTypes1.setFieldDoubleNull(3D);\n        nullTypes1.setFieldBooleanNull(true);\n        nullTypes1.setFieldStringNull(\"4\");\n        nullTypes1.setFieldDateNull(new Date(12345));\n        nullTypes1.setFieldDecimal128Null(new Decimal128(BigDecimal.TEN));\n        nullTypes1.setFieldObjectIdNull(new ObjectId(TestHelper.generateObjectIdHexString(7)));\n        nullTypes1.setFieldUUIDNull(UUID.fromString(TestHelper.generateUUIDString(7)));\n\n        realm.beginTransaction();\n        realm.insert(nullTypes1);\n        realm.commitTransaction();\n\n        NullTypes first = realm.where(NullTypes.class).findFirst();\n\n        assertNotNull(first);\n        assertEquals(nullTypes1.getId(), first.getId());\n        assertEquals(nullTypes1.getFieldIntegerNull(), first.getFieldIntegerNull());\n        assertEquals(nullTypes1.getFieldFloatNull(), first.getFieldFloatNull());\n        assertEquals(nullTypes1.getFieldDoubleNull(), first.getFieldDoubleNull());\n        assertEquals(nullTypes1.getFieldBooleanNull(), first.getFieldBooleanNull());\n        assertEquals(nullTypes1.getFieldStringNull(), first.getFieldStringNull());\n        assertEquals(nullTypes1.getFieldDateNull(), first.getFieldDateNull());\n        assertEquals(nullTypes1.getFieldDecimal128Null(), first.getFieldDecimal128Null());\n        assertEquals(nullTypes1.getFieldObjectIdNull(), first.getFieldObjectIdNull());\n        assertEquals(nullTypes1.getFieldUUIDNull(), first.getFieldUUIDNull());\n\n        NullTypes nullTypes2 = new NullTypes();\n        nullTypes2.setId(2);\n\n        NullTypes nullTypes3 = new NullTypes();\n        nullTypes3.setId(3);\n\n        nullTypes1 = new NullTypes();\n        nullTypes1.setId(1);\n        nullTypes1.setFieldIntegerNull(null);\n        nullTypes1.setFieldFloatNull(null);\n        nullTypes1.setFieldDoubleNull(null);\n        nullTypes1.setFieldBooleanNull(null);\n        nullTypes1.setFieldStringNull(null);\n        nullTypes1.setFieldDateNull(null);\n        nullTypes1.setFieldDecimal128Null(null);\n        nullTypes1.setFieldObjectIdNull(null);\n        nullTypes1.setFieldUUIDNull(null);\n        nullTypes1.setFieldListNull(new RealmList<NullTypes>());\n        nullTypes1.getFieldListNull().add(nullTypes2);\n        nullTypes1.getFieldListNull().add(nullTypes3);\n\n        OrderedRealmCollection<NullTypes> collection = new RealmList<NullTypes>();\n        collection.add(nullTypes2);\n        collection.add(nullTypes1);\n        collection.add(nullTypes3);\n\n        realm.beginTransaction();\n        realm.insertOrUpdate(collection);\n        realm.commitTransaction();\n\n        first = realm.where(NullTypes.class).equalTo(\"id\", 1).findFirst();\n\n        assertNotNull(first);\n        assertEquals(nullTypes1.getId(), first.getId());\n        assertNull(first.getFieldIntegerNull());\n        assertNull(first.getFieldFloatNull());\n        assertNull(first.getFieldDoubleNull());\n        assertNull(first.getFieldBooleanNull());\n        assertNull(first.getFieldStringNull());\n        assertNull(first.getFieldDateNull());\n        assertNull(first.getFieldDecimal128Null());\n        assertNull(first.getFieldObjectIdNull());\n        assertNull(first.getFieldUUIDNull());\n        assertEquals(2, first.getFieldListNull().size());\n        assertEquals(2, first.getFieldListNull().get(0).getId());\n        assertEquals(3, first.getFieldListNull().get(1).getId());\n    }\n\n    @Test\n    public void insert_cyclicType() {\n        CyclicType oneCyclicType = new CyclicType();\n        oneCyclicType.setName(\"One\");\n        CyclicType anotherCyclicType = new CyclicType();\n        anotherCyclicType.setName(\"Two\");\n        oneCyclicType.setObject(anotherCyclicType);\n        anotherCyclicType.setObject(oneCyclicType);\n\n        realm.beginTransaction();\n        realm.insert(Arrays.asList(oneCyclicType, anotherCyclicType));\n        realm.commitTransaction();\n\n        RealmResults<CyclicType> realmObjects = realm.where(CyclicType.class).sort(CyclicType.FIELD_NAME).findAll();\n        assertNotNull(realmObjects);\n        assertEquals(2, realmObjects.size());\n        assertEquals(\"One\", realmObjects.get(0).getName());\n        assertEquals(\"Two\", realmObjects.get(0).getObject().getName());\n    }\n\n    @Test\n    public void insertOrUpdate_cyclicType() {\n        CyclicTypePrimaryKey oneCyclicType = new CyclicTypePrimaryKey(1, \"One\");\n        CyclicTypePrimaryKey anotherCyclicType = new CyclicTypePrimaryKey(2, \"Two\");\n        oneCyclicType.setObject(anotherCyclicType);\n        anotherCyclicType.setObject(oneCyclicType);\n\n        realm.beginTransaction();\n        realm.insertOrUpdate(Arrays.asList(oneCyclicType, anotherCyclicType));\n        realm.commitTransaction();\n\n        RealmResults<CyclicTypePrimaryKey> realmObjects = realm.where(CyclicTypePrimaryKey.class).sort(\"name\").findAll();\n        assertNotNull(realmObjects);\n        assertEquals(2, realmObjects.size());\n        assertEquals(\"One\", realmObjects.get(0).getName());\n        assertEquals(\"Two\", realmObjects.get(0).getObject().getName());\n\n        CyclicTypePrimaryKey updatedCyclicType = new CyclicTypePrimaryKey(2, \"updated\");\n\n        realm.beginTransaction();\n        realm.insertOrUpdate(updatedCyclicType);\n        realm.commitTransaction();\n\n        assertEquals(\"One\", realmObjects.get(0).getName());\n        assertEquals(\"updated\", realmObjects.get(0).getObject().getName());\n        assertEquals(2, realm.where(CyclicTypePrimaryKey.class).count());\n    }\n\n    @Test\n    public void insertOrUpdate_cyclicDependenciesFromOtherRealm() {\n        RealmConfiguration config1 = configFactory.createConfiguration(\"realm1\");\n        RealmConfiguration config2 = configFactory.createConfiguration(\"realm2\");\n\n        Realm realm1 = Realm.getInstance(config1);\n        Realm realm2 = Realm.getInstance(config2);\n\n        realm1.beginTransaction();\n        Owner owner = realm1.createObject(Owner.class);\n        owner.setName(\"Kiba\");\n        Dog dog = realm1.createObject(Dog.class);\n        dog.setName(\"Akamaru\");\n        owner.getDogs().add(dog);\n        dog.setOwner(owner);\n        realm1.commitTransaction();\n\n        // Copies object with relations from realm1 to realm2.\n        realm2.beginTransaction();\n        realm2.insertOrUpdate(owner);\n        realm2.commitTransaction();\n\n        assertEquals(1, realm1.where(Owner.class).count());\n        assertEquals(1, realm1.where(Owner.class).findFirst().getDogs().size());\n        assertEquals(1, realm1.where(Dog.class).count());\n\n        assertEquals(realm1.where(Owner.class).count(), realm2.where(Owner.class).count());\n        assertEquals(realm1.where(Dog.class).count(), realm2.where(Dog.class).count());\n\n        assertEquals(1, realm2.where(Owner.class).findFirst().getDogs().size());\n\n        assertEquals(realm1.where(Owner.class).findFirst().getName(), realm2.where(Owner.class).findFirst().getName());\n\n        assertEquals(realm1.where(Owner.class).findFirst().getDogs().first().getName()\n                , realm2.where(Owner.class).findFirst().getDogs().first().getName());\n\n        realm1.close();\n        realm2.close();\n    }\n\n    @Test\n    public void insert_nullPrimaryKey() {\n        PrimaryKeyAsString primaryKeyAsString = new PrimaryKeyAsString();\n        primaryKeyAsString.setId(19);\n\n        realm.beginTransaction();\n        realm.insertOrUpdate(primaryKeyAsString);\n        realm.commitTransaction();\n\n        primaryKeyAsString = realm.where(PrimaryKeyAsString.class).isNull(\"name\").findFirst();\n        assertNotNull(primaryKeyAsString);\n        assertNull(primaryKeyAsString.getName());\n        assertEquals(19, primaryKeyAsString.getId());\n\n        PrimaryKeyAsBoxedShort primaryKeyAsShort = new PrimaryKeyAsBoxedShort();\n        primaryKeyAsShort.setName(\"42\");\n\n        realm.beginTransaction();\n        realm.insertOrUpdate(primaryKeyAsShort);\n        realm.commitTransaction();\n\n        primaryKeyAsShort = realm.where(PrimaryKeyAsBoxedShort.class).isNull(\"id\").findFirst();\n        assertNotNull(primaryKeyAsShort);\n        assertNull(primaryKeyAsShort.getId());\n        assertEquals(\"42\", primaryKeyAsShort.getName());\n    }\n\n    @Test\n    public void insert_duplicatedPrimaryKeyFails() {\n\n        // Single object with 2 references to two objects with the same ID\n        AllJavaTypes obj = new AllJavaTypes(2);\n        obj.setFieldList(new RealmList<AllJavaTypes>(new AllJavaTypes(1), new AllJavaTypes(1)));\n        realm.beginTransaction();\n        try {\n            realm.insert(obj);\n            fail();\n        } catch (RealmPrimaryKeyConstraintException ignored) {\n        } finally {\n            realm.cancelTransaction();\n        }\n\n        // Two objects with the same ID in a list\n        realm.beginTransaction();\n        try {\n            realm.insert(Arrays.asList(new AllJavaTypes(1), new AllJavaTypes(1)));\n            fail();\n        } catch (RealmPrimaryKeyConstraintException ignored) {\n        } finally {\n            realm.cancelTransaction();\n        }\n    }\n\n    @Test\n    public void insertOrUpdate() {\n        realm.executeTransaction(new Realm.Transaction() {\n            @Override\n            public void execute(Realm realm) {\n                AllTypesPrimaryKey obj = new AllTypesPrimaryKey();\n                obj.setColumnString(\"Foo\");\n                obj.setColumnLong(1);\n                obj.setColumnFloat(1.23F);\n                obj.setColumnDouble(1.234D);\n                obj.setColumnBoolean(false);\n                obj.setColumnBinary(new byte[]{1, 2, 3});\n                obj.setColumnDate(new Date(1000));\n                obj.setColumnRealmObject(new DogPrimaryKey(1, \"Dog1\"));\n                obj.setColumnRealmList(new RealmList<DogPrimaryKey>(new DogPrimaryKey(2, \"Dog2\")));\n                obj.setColumnBoxedBoolean(true);\n                realm.insert(obj);\n\n                AllTypesPrimaryKey obj2 = new AllTypesPrimaryKey();\n                obj2.setColumnString(\"Bar\");\n                obj2.setColumnLong(1);\n                obj2.setColumnFloat(2.23F);\n                obj2.setColumnDouble(2.234D);\n                obj2.setColumnBoolean(true);\n                obj2.setColumnBinary(new byte[]{2, 3, 4});\n                obj2.setColumnDate(new Date(2000));\n                obj2.setColumnRealmObject(new DogPrimaryKey(3, \"Dog3\"));\n                obj2.setColumnRealmList(new RealmList<DogPrimaryKey>(new DogPrimaryKey(4, \"Dog4\")));\n                obj2.setColumnBoxedBoolean(false);\n                realm.insertOrUpdate(obj2);\n            }\n        });\n\n        assertEquals(1, realm.where(AllTypesPrimaryKey.class).count());\n        AllTypesPrimaryKey obj = realm.where(AllTypesPrimaryKey.class).findFirst();\n\n        // Checks that the only element has all its properties updated.\n        assertNotNull(obj);\n        assertEquals(\"Bar\", obj.getColumnString());\n        assertEquals(1, obj.getColumnLong());\n        assertEquals(2.23F, obj.getColumnFloat(), 0);\n        assertEquals(2.234D, obj.getColumnDouble(), 0);\n        assertEquals(true, obj.isColumnBoolean());\n        assertArrayEquals(new byte[]{2, 3, 4}, obj.getColumnBinary());\n        assertEquals(new Date(2000), obj.getColumnDate());\n        assertEquals(\"Dog3\", obj.getColumnRealmObject().getName());\n        assertEquals(1, obj.getColumnRealmList().size());\n        assertEquals(\"Dog4\", obj.getColumnRealmList().get(0).getName());\n        assertEquals(4, realm.where(DogPrimaryKey.class).findAll().size());\n        assertFalse(obj.getColumnBoxedBoolean());\n    }\n\n    @Test\n    public void insert_list() {\n        Dog dog1 = new Dog();\n        dog1.setName(\"Dog 1\");\n        Dog dog2 = new Dog();\n        dog2.setName(\"Dog 2\");\n        RealmList<Dog> list = new RealmList<Dog>();\n        list.addAll(Arrays.asList(dog1, dog2));\n\n        realm.beginTransaction();\n        realm.insert(list);\n        realm.commitTransaction();\n\n\n        RealmResults<Dog> copiedList = realm.where(Dog.class).findAll();\n\n        assertEquals(2, copiedList.size());\n        assertEquals(dog1.getName(), copiedList.get(0).getName());\n        assertEquals(dog2.getName(), copiedList.get(1).getName());\n    }\n\n    @Test\n    public void insert_emptyList() {\n        realm.executeTransaction(new Realm.Transaction() {\n            @Override\n            public void execute(Realm realm) {\n                realm.insert(Collections.<PrimaryKeyAsLong>emptyList());\n            }\n        });\n        assertEquals(0, realm.where(PrimaryKeyAsLong.class).count());\n    }\n\n    /**\n     * Added to reproduce https://github.com/realm/realm-java/issues/3103\n     */\n    @Test\n    public void insert_emptyListWithCompositeMediator() {\n        final RealmConfiguration config = configFactory.createConfigurationBuilder()\n                .modules(new HumanModule(), new AnimalModule())\n                .name(\"composite.realm\")\n                .build();\n        Realm.deleteRealm(config);\n\n        assertEquals(config.getSchemaMediator().getClass(), CompositeMediator.class);\n\n        final Realm realm = Realm.getInstance(config);\n        //noinspection TryFinallyCanBeTryWithResources\n        try {\n            realm.executeTransaction(new Realm.Transaction() {\n                @Override\n                public void execute(Realm realm) {\n                    realm.insert(Collections.<Cat>emptyList());\n                }\n            });\n            assertEquals(0, realm.where(Cat.class).count());\n        } finally {\n            realm.close();\n        }\n    }\n\n    /**\n     * Added to reproduce https://github.com/realm/realm-java/issues/3103\n     */\n    @Test\n    public void insert_emptyListWithFilterableMediator() {\n        //noinspection unchecked\n        final RealmConfiguration config = configFactory.createConfigurationBuilder()\n                .schema(CatOwner.class, Cat.class, Owner.class, DogPrimaryKey.class, Dog.class)\n                .name(\"filterable.realm\")\n                .build();\n        Realm.deleteRealm(config);\n\n        assertEquals(config.getSchemaMediator().getClass(), FilterableMediator.class);\n\n        final Realm realm = Realm.getInstance(config);\n        //noinspection TryFinallyCanBeTryWithResources\n        try {\n            realm.executeTransaction(new Realm.Transaction() {\n                @Override\n                public void execute(Realm realm) {\n                    realm.insert(Collections.<Cat>emptyList());\n                }\n            });\n            assertEquals(0, realm.where(Cat.class).count());\n        } finally {\n            realm.close();\n        }\n    }\n\n    @Test\n    public void insertOrUpdate_list() {\n        realm.executeTransaction(new Realm.Transaction() {\n            @Override\n            public void execute(Realm realm) {\n                PrimaryKeyAsLong obj = new PrimaryKeyAsLong();\n                obj.setId(1);\n                obj.setName(\"Foo\");\n                realm.copyToRealm(obj);\n\n                PrimaryKeyAsLong obj2 = new PrimaryKeyAsLong();\n                obj2.setId(1);\n                obj2.setName(\"Bar\");\n\n                PrimaryKeyAsLong obj3 = new PrimaryKeyAsLong();\n                obj3.setId(1);\n                obj3.setName(\"Baz\");\n\n                realm.insertOrUpdate(Arrays.asList(obj2, obj3));\n            }\n        });\n\n        assertEquals(1, realm.where(PrimaryKeyAsLong.class).count());\n        PrimaryKeyAsLong first = realm.where(PrimaryKeyAsLong.class).findFirst();\n        assertNotNull(first);\n        assertEquals(\"Baz\", first.getName());\n    }\n\n    @Test\n    public void insertOrUpdate_emptyList() {\n        realm.executeTransaction(new Realm.Transaction() {\n            @Override\n            public void execute(Realm realm) {\n                realm.insertOrUpdate(Collections.<PrimaryKeyAsLong>emptyList());\n            }\n        });\n        assertEquals(0, realm.where(PrimaryKeyAsLong.class).count());\n    }\n\n    /**\n     * Added to reproduce https://github.com/realm/realm-java/issues/3103\n     */\n    @Test\n    public void insertOrUpdate_emptyListWithCompositeMediator() {\n        final RealmConfiguration config = configFactory.createConfigurationBuilder()\n                .modules(new HumanModule(), new AnimalModule())\n                .name(\"composite.realm\")\n                .build();\n        Realm.deleteRealm(config);\n\n        assertEquals(config.getSchemaMediator().getClass(), CompositeMediator.class);\n\n        final Realm realm = Realm.getInstance(config);\n        //noinspection TryFinallyCanBeTryWithResources\n        try {\n            realm.executeTransaction(new Realm.Transaction() {\n                @Override\n                public void execute(Realm realm) {\n                    realm.insertOrUpdate(Collections.<Cat>emptyList());\n                }\n            });\n            assertEquals(0, realm.where(Cat.class).count());\n        } finally {\n            realm.close();\n        }\n    }\n\n    /**\n     * Added to reproduce https://github.com/realm/realm-java/issues/3103\n     */\n    @Test\n    public void insertOrUpdate_emptyListWithFilterableMediator() {\n        //noinspection unchecked\n        final RealmConfiguration config = configFactory.createConfigurationBuilder()\n                .schema(CatOwner.class, Cat.class, Owner.class, DogPrimaryKey.class, Dog.class)\n                .name(\"filterable.realm\")\n                .build();\n        Realm.deleteRealm(config);\n\n        assertEquals(config.getSchemaMediator().getClass(), FilterableMediator.class);\n\n        final Realm realm = Realm.getInstance(config);\n        //noinspection TryFinallyCanBeTryWithResources\n        try {\n            realm.executeTransaction(new Realm.Transaction() {\n                @Override\n                public void execute(Realm realm) {\n                    realm.insertOrUpdate(Collections.<Cat>emptyList());\n                }\n            });\n            assertEquals(0, realm.where(Cat.class).count());\n        } finally {\n            realm.close();\n        }\n    }\n\n    @Test\n    public void insertOrUpdate_mixingPrimaryKeyAndNoPrimaryKeyModels() {\n        AllTypes objB_no_pk = new AllTypes();\n        objB_no_pk.setColumnString(\"B\");\n\n        PrimaryKeyWithNoPrimaryKeyObjectRelation objA_pk = new PrimaryKeyWithNoPrimaryKeyObjectRelation();\n        objA_pk.setColumnString(\"A\");\n        objA_pk.setColumnRealmObjectNoPK(objB_no_pk);\n\n        realm.beginTransaction();\n        realm.insert(objA_pk);\n        realm.commitTransaction();\n\n        RealmResults<PrimaryKeyWithNoPrimaryKeyObjectRelation> all = realm.where(PrimaryKeyWithNoPrimaryKeyObjectRelation.class).findAll();\n        assertEquals(1, all.size());\n        assertEquals(\"A\", all.get(0).getColumnString());\n        assertEquals(8, all.get(0).getColumnInt());\n        assertNotNull(all.get(0).getColumnRealmObjectNoPK());\n        assertEquals(\"B\", all.get(0).getColumnRealmObjectNoPK().getColumnString());\n        assertEquals(1, realm.where(AllTypes.class).findAll().size());\n\n        objA_pk.setColumnInt(42);\n        objB_no_pk.setColumnString(\"updated B\");\n\n        realm.beginTransaction();\n        realm.insertOrUpdate(objA_pk);\n        realm.commitTransaction();\n\n        all = realm.where(PrimaryKeyWithNoPrimaryKeyObjectRelation.class).findAll();\n        assertEquals(1, all.size());\n        assertEquals(\"A\", all.get(0).getColumnString());\n        assertEquals(42, all.get(0).getColumnInt());\n        assertNotNull(all.get(0).getColumnRealmObjectNoPK());\n        assertEquals(\"updated B\", all.get(0).getColumnRealmObjectNoPK().getColumnString());\n        // Since AllTypes doesn't have a PK we now have two instances.\n        assertEquals(2, realm.where(AllTypes.class).findAll().size());\n    }\n\n\n    @Test\n    public void insertOrUpdate_mixingNoPrimaryKeyAndPrimaryKeyModels() {\n        AllTypesPrimaryKey objB_pk = new AllTypesPrimaryKey();\n        objB_pk.setColumnLong(7);\n        objB_pk.setColumnString(\"B\");\n\n        NoPrimaryKeyWithPrimaryKeyObjectRelation objA_no_pk = new NoPrimaryKeyWithPrimaryKeyObjectRelation();\n        objA_no_pk.setColumnRealmObjectPK(objB_pk);\n        objA_no_pk.setColumnString(\"A\");\n\n        realm.beginTransaction();\n        realm.insert(objA_no_pk);\n        realm.commitTransaction();\n\n        RealmResults<NoPrimaryKeyWithPrimaryKeyObjectRelation> all = realm.where(NoPrimaryKeyWithPrimaryKeyObjectRelation.class).findAll();\n        assertEquals(1, all.size());\n        assertEquals(\"A\", all.get(0).getColumnString());\n        assertEquals(8, all.get(0).getColumnInt());\n        assertNotNull(all.get(0).getColumnRealmObjectPK());\n        assertEquals(7, all.get(0).getColumnRealmObjectPK().getColumnLong());\n        assertEquals(\"B\", all.get(0).getColumnRealmObjectPK().getColumnString());\n        assertEquals(1, realm.where(AllTypesPrimaryKey.class).findAll().size());\n\n        objA_no_pk.setColumnString(\"different A\");\n        objA_no_pk.setColumnInt(42); // Should insert a new instance\n        // Updates (since it has a PK) now both AllTypesPrimaryKey points to the same objB_pk instance.\n        objB_pk.setColumnString(\"updated B\");\n\n        realm.beginTransaction();\n        realm.insertOrUpdate(objA_no_pk);\n        realm.commitTransaction();\n\n        all = realm.where(NoPrimaryKeyWithPrimaryKeyObjectRelation.class).sort(\"columnString\").findAll();\n        assertEquals(2, all.size());\n        assertEquals(\"A\", all.get(0).getColumnString());\n        assertEquals(8, all.get(0).getColumnInt());\n        assertEquals(\"different A\", all.get(1).getColumnString());\n        assertEquals(42, all.get(1).getColumnInt());\n\n        assertNotNull(all.get(0).getColumnRealmObjectPK());\n        assertNotNull(all.get(1).getColumnRealmObjectPK());\n\n        assertEquals(7, all.get(0).getColumnRealmObjectPK().getColumnLong());\n        assertEquals(7, all.get(1).getColumnRealmObjectPK().getColumnLong());\n        assertEquals(\"updated B\", all.get(0).getColumnRealmObjectPK().getColumnString());\n        assertEquals(\"updated B\", all.get(1).getColumnRealmObjectPK().getColumnString());\n        assertEquals(1, realm.where(AllTypesPrimaryKey.class).findAll().size());\n    }\n\n    @Test\n    public void insertOrUpdate_mixingPrimaryAndNoPrimaryKeyList() {\n        NoPrimaryKeyWithPrimaryKeyObjectRelation objA_no_pk = new NoPrimaryKeyWithPrimaryKeyObjectRelation();\n        objA_no_pk.setColumnString(\"A\");\n        NoPrimaryKeyWithPrimaryKeyObjectRelation objB_no_pk = new NoPrimaryKeyWithPrimaryKeyObjectRelation();\n        objB_no_pk.setColumnString(\"B\");\n        AllTypesPrimaryKey objC_pk = new AllTypesPrimaryKey();\n        objC_pk.setColumnLong(7);\n        objC_pk.setColumnString(\"C\");\n        AllTypesPrimaryKey objD_pk = new AllTypesPrimaryKey();\n        objD_pk.setColumnLong(7);\n        objD_pk.setColumnString(\"D\");\n\n        objA_no_pk.setColumnRealmObjectPK(objC_pk);\n        objB_no_pk.setColumnRealmObjectPK(objD_pk);\n\n        ArrayList<NoPrimaryKeyWithPrimaryKeyObjectRelation> objects = new ArrayList<NoPrimaryKeyWithPrimaryKeyObjectRelation>(2);\n        objects.add(objA_no_pk);\n        objects.add(objB_no_pk);\n\n        realm.beginTransaction();\n        realm.insertOrUpdate(objects);\n        realm.commitTransaction();\n\n        RealmResults<NoPrimaryKeyWithPrimaryKeyObjectRelation> all = realm.where(NoPrimaryKeyWithPrimaryKeyObjectRelation.class)\n                .sort(\"columnString\", Sort.DESCENDING)\n                .findAll();\n        assertEquals(2, all.size());\n        assertEquals(\"B\", all.get(0).getColumnString());\n        assertEquals(\"A\", all.get(1).getColumnString());\n\n        assertNotNull(all.get(0).getColumnRealmObjectPK());\n        assertNotNull(all.get(1).getColumnRealmObjectPK());\n\n        assertEquals(\"D\", all.get(0).getColumnRealmObjectPK().getColumnString());\n        assertEquals(\"D\", all.get(1).getColumnRealmObjectPK().getColumnString());\n\n        assertEquals(1, realm.where(AllTypesPrimaryKey.class).findAll().size());\n    }\n\n    // Any omitted argument should not end in a SIGSEGV but an exception.\n\n    @Test\n    public void insert_nullObject() {\n        AllTypes nullObject = null;\n\n        realm.beginTransaction();\n        try {\n            //noinspection ConstantConditions\n            realm.insert(nullObject);\n            fail(\"Should trigger NullPointerException\");\n        } catch (IllegalArgumentException ignore) {\n\n        } finally {\n            realm.cancelTransaction();\n        }\n    }\n\n    @Test\n    public void inset_nullList() {\n        List<AllTypes> nullObjects = null;\n\n        realm.beginTransaction();\n        try {\n            //noinspection ConstantConditions\n            realm.insert(nullObjects);\n            fail(\"Should trigger IllegalArgumentException\");\n        } catch (IllegalArgumentException ignore) {\n\n        } finally {\n            realm.cancelTransaction();\n        }\n    }\n\n    @Test\n    public void insert_listWithNullElement() {\n        Dog dog1 = new Dog();\n        dog1.setName(\"Dog 1\");\n        Dog dog2 = new Dog();\n        dog2.setName(\"Dog 2\");\n        ArrayList<Dog> list = new ArrayList<Dog>();\n        list.addAll(Arrays.asList(dog1, null, dog2));\n\n        realm.beginTransaction();\n        try {\n            realm.insert(list);\n            fail(\"Should trigger IllegalArgumentException\");\n        } catch (NullPointerException ignore) {\n\n        } finally {\n            realm.cancelTransaction();\n        }\n    }\n\n    // Inserting a managed object will result in it being copied or updated again.\n    @Test\n    public void insertOrUpdate_managedObject() {\n        AllJavaTypes obj = new AllJavaTypes();\n        obj.setFieldId(42);\n        obj.setFieldIgnored(\"cookie\");\n        obj.setFieldLong(42);\n        obj.setFieldString(\"obj1\");\n\n        realm.beginTransaction();\n        AllJavaTypes managedAllJavaTypes = realm.copyToRealm(obj);\n        realm.commitTransaction();\n\n        realm.beginTransaction();\n\n        AllJavaTypes filedObject = new AllJavaTypes();\n        filedObject.setFieldLong(8);\n        filedObject = realm.copyToRealm(filedObject);\n        managedAllJavaTypes.setFieldObject(filedObject);\n        managedAllJavaTypes.setFieldString(\"updated\");\n\n        realm.insertOrUpdate(managedAllJavaTypes);\n        realm.commitTransaction();\n\n        AllJavaTypes first = realm.where(AllJavaTypes.class).equalTo(AllJavaTypes.FIELD_LONG, 42).findFirst();\n        assertNotNull(first);\n        assertEquals(42, first.getFieldLong(), 0);\n        assertEquals(\"updated\", first.getFieldString());\n        assertNull(first.getFieldIgnored());\n        assertNotNull(first.getFieldObject());\n        assertEquals(8, first.getFieldObject().getFieldLong());\n\n        assertEquals(2, realm.where(AllJavaTypes.class).findAll().size());\n    }\n\n    @Test\n    public void insertOrUpdate_linkingManagedToUnmanagedObject() {\n        realm.beginTransaction();\n        AllJavaTypes managedAllJavaTypes = realm.createObject(AllJavaTypes.class, 42);\n        realm.commitTransaction();\n\n        AllJavaTypes unmanagedObject = new AllJavaTypes(8);\n        unmanagedObject.setFieldObject(managedAllJavaTypes);//Linking managed object to unmanaged object\n\n        realm.beginTransaction();\n        realm.insertOrUpdate(unmanagedObject);\n        realm.commitTransaction();\n\n        AllJavaTypes first = realm.where(AllJavaTypes.class).equalTo(AllJavaTypes.FIELD_ID, 8).findFirst();\n        assertNotNull(first);\n        assertEquals(8, first.getFieldId(), 0);\n        assertNotNull(first.getFieldObject());\n        assertEquals(42, first.getFieldObject().getFieldId());\n        assertEquals(2, realm.where(AllJavaTypes.class).count());\n    }\n\n    @Test\n    public void insertManagedObjectWillNotDuplicate() {\n        realm.beginTransaction();\n        Dog managedRealmObject = realm.createObject(Dog.class);\n        managedRealmObject.setName(\"dog1\");\n        realm.commitTransaction();\n\n        realm.beginTransaction();\n        realm.insert(managedRealmObject);\n        realm.commitTransaction();\n\n        assertEquals(1, realm.where(Dog.class).count());\n    }\n\n    @Test\n    public void insertOrUpdate_collectionOfManagedObjects() {\n        realm.beginTransaction();\n        AllTypesPrimaryKey allTypes = realm.createObject(AllTypesPrimaryKey.class, 0);\n        allTypes.getColumnRealmList().add(realm.createObject(DogPrimaryKey.class, 0));\n        realm.commitTransaction();\n        assertEquals(1, allTypes.getColumnRealmList().size());\n\n        List<AllTypesPrimaryKey>  list = new ArrayList<AllTypesPrimaryKey>();\n        // Although there are two same objects in the list, none of them should be saved to the db since they are managed\n        // already.\n        list.add(allTypes);\n        list.add(allTypes);\n\n        realm.beginTransaction();\n        realm.insertOrUpdate(list);\n        realm.commitTransaction();\n        allTypes = realm.where(AllTypesPrimaryKey.class).findFirst();\n        assertNotNull(allTypes);\n        assertEquals(1, allTypes.getColumnRealmList().size());\n    }\n\n    // To reproduce https://github.com/realm/realm-java/issues/3105.\n    @Test\n    public void insertOrUpdate_shouldNotClearRealmList() {\n        realm.beginTransaction();\n        AllTypesPrimaryKey allTypes = realm.createObject(AllTypesPrimaryKey.class, 0);\n        allTypes.getColumnRealmList().add(realm.createObject(DogPrimaryKey.class, 0));\n        realm.commitTransaction();\n        assertEquals(1, allTypes.getColumnRealmList().size());\n\n        realm.beginTransaction();\n        realm.insertOrUpdate(allTypes);\n        realm.commitTransaction();\n        allTypes = realm.where(AllTypesPrimaryKey.class).findFirst();\n        assertNotNull(allTypes);\n        assertEquals(1, allTypes.getColumnRealmList().size());\n    }\n\n    @Test\n    public void insertOrUpdate_ownList() {\n        realm.beginTransaction();\n        AllJavaTypes managedObj = realm.createObject(AllJavaTypes.class, 1);\n        managedObj.getFieldList().add(managedObj);\n        AllJavaTypes unmanagedObj = realm.copyFromRealm(managedObj);\n        unmanagedObj.setFieldList(managedObj.getFieldList());\n\n        // Check single object insert\n        realm.insertOrUpdate(unmanagedObj);\n        managedObj = realm.where(AllJavaTypes.class).findFirst();\n        assertEquals(1, managedObj.getFieldList().size());\n        assertEquals(1, managedObj.getFieldList().first().getFieldId());\n\n        // Check collection insert\n        realm.insertOrUpdate(Arrays.asList(unmanagedObj));\n        managedObj = realm.where(AllJavaTypes.class).findFirst();\n        assertEquals(1, managedObj.getFieldList().size());\n        assertEquals(1, managedObj.getFieldList().first().getFieldId());\n    }\n\n    @Test\n    public void insert_collectionOfManagedObjects() {\n        realm.beginTransaction();\n        AllTypes allTypes = realm.createObject(AllTypes.class);\n        allTypes.getColumnRealmList().add(realm.createObject(Dog.class));\n        realm.commitTransaction();\n        assertEquals(1, allTypes.getColumnRealmList().size());\n\n        List<AllTypes>  list = new ArrayList<AllTypes>();\n        // Although there are two same objects in the list, none of them should be saved to the db since they are managed\n        // already.\n        list.add(allTypes);\n        list.add(allTypes);\n\n        realm.beginTransaction();\n        realm.insert(list);\n        realm.commitTransaction();\n        assertEquals(1, realm.where(AllTypes.class).count());\n        allTypes = realm.where(AllTypes.class).findFirst();\n        assertNotNull(allTypes);\n        assertEquals(1, allTypes.getColumnRealmList().size());\n    }\n\n    @Test(expected = IllegalStateException.class)\n    public void insert_collection_notInTransaction() {\n        realm.insert(Arrays.asList(new AllTypes(), new AllTypes()));\n    }\n\n    @Test(expected = IllegalStateException.class)\n    public void insert_object_notInTransaction() {\n        realm.insert(new AllTypes());\n    }\n\n    @Test(expected = IllegalStateException.class)\n    public void insertOrUpdate_collection_notInTransaction() {\n        realm.insert(Arrays.asList(new AllTypesPrimaryKey(), new AllTypesPrimaryKey()));\n    }\n\n    @Test(expected = IllegalStateException.class)\n    public void insertOrUpdate_object_notInTransaction() {\n        realm.insert(new AllTypes());\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/CollectionTests.java",
    "content": "/*\n * Copyright 2016 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\npackage io.realm;\n\nimport java.util.Date;\nimport java.util.concurrent.TimeUnit;\n\nimport io.realm.entities.AllJavaTypes;\nimport io.realm.entities.CyclicType;\nimport io.realm.entities.NonLatinFieldNames;\nimport io.realm.entities.NullTypes;\n\n/**\n * Super class for all RealmCollection related tests.\n * This class only contains configuration and helper methods.\n */\npublic abstract class CollectionTests {\n\n    protected final static long YEAR_MILLIS = TimeUnit.DAYS.toMillis(365);\n\n    // Enumerates all known collection classes from the Realm API.\n    protected enum CollectionClass {\n        MANAGED_REALMLIST, UNMANAGED_REALMLIST, REALMRESULTS,\n        REALMRESULTS_SNAPSHOT_RESULTS_BASE, REALMRESULTS_SNAPSHOT_LIST_BASE\n\n    }\n\n    // Enumerates all current supported collections that can be in unmanaged mode.\n    protected enum UnManagedCollection {\n        UNMANAGED_REALMLIST\n    }\n\n    // Enumerates all current supported collections that can be managed by Realm.\n    protected enum ManagedCollection {\n        MANAGED_REALMLIST, REALMRESULTS, REALMRESULTS_SNAPSHOT_RESULTS_BASE, REALMRESULTS_SNAPSHOT_LIST_BASE\n    }\n\n    // Enumerates all methods from the RealmCollection interface that depend on Realm API's.\n    protected enum RealmCollectionMethod {\n        WHERE, MIN, MAX, SUM, AVERAGE, MIN_DATE, MAX_DATE, DELETE_ALL_FROM_REALM, IS_VALID,\n        IS_MANAGED, IS_FROZEN, FREEZE\n    }\n\n    // Enumerates all methods from the Collection interface\n    protected enum CollectionMethod {\n        ADD_OBJECT, ADD_ALL_OBJECTS, CLEAR, CONTAINS, CONTAINS_ALL, EQUALS, HASHCODE, IS_EMPTY, ITERATOR, REMOVE_OBJECT,\n        REMOVE_ALL, RETAIN_ALL, SIZE, TO_ARRAY, TO_ARRAY_INPUT\n    }\n\n    // Enumerates all methods on the List interface and OrderedRealmCollection interface that doesn't depend on Realm\n    // API's.\n    protected enum ListMethod {\n        FIRST, LAST, ADD_INDEX, ADD_ALL_INDEX, GET_INDEX, INDEX_OF, LAST_INDEX_OF, LIST_ITERATOR, LIST_ITERATOR_INDEX, REMOVE_INDEX,\n        SET, SUBLIST\n    }\n\n    // Enumerates all methods from the OrderedRealmCollection interface that depend on Realm API's.\n    protected enum OrderedRealmCollectionMethod {\n        DELETE_INDEX, DELETE_FIRST, DELETE_LAST, SORT, SORT_FIELD, SORT_2FIELDS, SORT_MULTI, CREATE_SNAPSHOT\n    }\n\n    // Enumerates all methods that can mutate a RealmCollection.\n    protected enum CollectionMutatorMethod {\n        DELETE_ALL, ADD_OBJECT, ADD_ALL_OBJECTS, CLEAR, REMOVE_OBJECT, REMOVE_ALL, RETAIN_ALL\n    }\n\n    // Enumerates all methods that can mutate a RealmOrderedCollection.\n    protected enum OrderedCollectionMutatorMethod {\n        DELETE_INDEX, DELETE_FIRST, DELETE_LAST, ADD_INDEX, ADD_ALL_INDEX, SET, REMOVE_INDEX\n    }\n\n    protected void populateRealm(Realm realm, int objects) {\n        realm.beginTransaction();\n        realm.delete(AllJavaTypes.class);\n        realm.delete(NonLatinFieldNames.class);\n        if (objects > 0) {\n            for (int i = 0; i < objects; i++) {\n                AllJavaTypes obj = realm.createObject(AllJavaTypes.class, i);\n                fillObject(i, objects, obj);\n                NonLatinFieldNames nonLatinFieldNames = realm.createObject(NonLatinFieldNames.class);\n                nonLatinFieldNames.set델타(i);\n                nonLatinFieldNames.setΔέλτα(i);\n                // Sets the linked object to itself.\n                obj.setFieldObject(obj);\n            }\n\n            // Adds all items to the RealmList on the first object.\n            AllJavaTypes firstObj = realm.where(AllJavaTypes.class).equalTo(AllJavaTypes.FIELD_ID, 0).findFirst();\n            RealmResults<AllJavaTypes> listData = realm.where(AllJavaTypes.class).sort(AllJavaTypes.FIELD_ID, Sort.ASCENDING).findAll();\n            RealmList<AllJavaTypes> list = firstObj.getFieldList();\n            for (int i = 0; i < listData.size(); i++) {\n                list.add(listData.get(i));\n            }\n        }\n        realm.commitTransaction();\n    }\n\n    protected RealmList<AllJavaTypes> populateInMemoryList(int objects) {\n        RealmList<AllJavaTypes> list = new RealmList<AllJavaTypes>();\n        for (int i = 0; i < objects; i++) {\n            AllJavaTypes obj = new AllJavaTypes();\n            fillObject(i, objects, obj);\n            list.add(obj);\n        }\n        return list;\n    }\n\n    private void fillObject(int index, int totalObjects, AllJavaTypes obj) {\n        obj.setFieldLong(index);\n        obj.setFieldInt(index);\n        obj.setFieldBoolean(((index % 2) == 0));\n        obj.setFieldBinary(new byte[]{1, 2, 3});\n        obj.setFieldDate(new Date(YEAR_MILLIS * 20 * (index - totalObjects / 2)));\n        obj.setFieldDouble(Math.PI + index);\n        obj.setFieldFloat(1.234567f + index);\n        obj.setFieldString(\"test data \" + index);\n    }\n\n    // Creates a collection that is based on a RealmList that was deleted.\n    protected OrderedRealmCollection<CyclicType> populateCollectionOnDeletedLinkView(Realm realm, ManagedCollection collectionClass) {\n        realm.beginTransaction();\n        CyclicType parent = realm.createObject(CyclicType.class);\n        for (int i = 0; i < 10; i++) {\n            CyclicType child = new CyclicType();\n            child.setName(\"name_\" + i);\n            child.setObject(parent);\n            parent.getObjects().add(child);\n        }\n        realm.commitTransaction();\n\n        OrderedRealmCollection<CyclicType> result;\n        switch (collectionClass) {\n            case MANAGED_REALMLIST:\n                result = parent.getObjects();\n                break;\n            case REALMRESULTS:\n                result = parent.getObjects().where().equalTo(CyclicType.FIELD_NAME, \"name_0\").findAll();\n                break;\n            default:\n                throw new AssertionError(\"Unknown collection: \" + collectionClass);\n        }\n\n        realm.beginTransaction();\n        parent.deleteFromRealm();\n        realm.commitTransaction();\n        return result;\n    }\n\n    // Creates a number of objects that mix null and real values for number type fields.\n    protected void populatePartialNullRowsForNumericTesting(Realm realm) {\n        NullTypes nullTypes1 = new NullTypes();\n        nullTypes1.setId(1);\n        nullTypes1.setFieldIntegerNull(1);\n        nullTypes1.setFieldFloatNull(2F);\n        nullTypes1.setFieldDoubleNull(3D);\n        nullTypes1.setFieldBooleanNull(true);\n        nullTypes1.setFieldStringNull(\"4\");\n        nullTypes1.setFieldDateNull(new Date(12345));\n\n        NullTypes nullTypes2 = new NullTypes();\n        nullTypes2.setId(2);\n\n        NullTypes nullTypes3 = new NullTypes();\n        nullTypes3.setId(3);\n        nullTypes3.setFieldIntegerNull(0);\n        nullTypes3.setFieldFloatNull(0F);\n        nullTypes3.setFieldDoubleNull(0D);\n        nullTypes3.setFieldBooleanNull(false);\n        nullTypes3.setFieldStringNull(\"0\");\n        nullTypes3.setFieldDateNull(new Date(0));\n\n        realm.beginTransaction();\n        realm.copyToRealm(nullTypes1);\n        realm.copyToRealm(nullTypes2);\n        realm.copyToRealm(nullTypes3);\n        realm.commitTransaction();\n    }\n\n    // Creates a list of AllJavaTypes with its `fieldString` field set to a given value.\n    protected OrderedRealmCollection<AllJavaTypes> createStringCollection(Realm realm, ManagedCollection collectionClass, String... args) {\n        realm.beginTransaction();\n        realm.deleteAll();\n        OrderedRealmCollection<AllJavaTypes> orderedCollection;\n        switch (collectionClass) {\n            case REALMRESULTS_SNAPSHOT_RESULTS_BASE:\n            case REALMRESULTS:\n                int id = 0;\n                for (String arg : args) {\n                    AllJavaTypes obj = realm.createObject(AllJavaTypes.class, id++);\n                    obj.setFieldString(arg);\n                }\n                realm.commitTransaction();\n                    orderedCollection = realm.where(AllJavaTypes.class).sort(AllJavaTypes.FIELD_STRING).findAll();\n                break;\n\n            case REALMRESULTS_SNAPSHOT_LIST_BASE:\n            case MANAGED_REALMLIST:\n                AllJavaTypes first = realm.createObject(AllJavaTypes.class, 0);\n                first.setFieldString(args[0]);\n                first.getFieldList().add(first);\n                for (int i = 1; i < args.length; i++) {\n                    AllJavaTypes obj = realm.createObject(AllJavaTypes.class, i);\n                    obj.setFieldString(args[i]);\n                    first.getFieldList().add(obj);\n                }\n                realm.commitTransaction();\n                orderedCollection = first.getFieldList();\n                break;\n\n            default:\n                throw new AssertionError(\"Unknown collection: \" + collectionClass);\n        }\n\n        if (isSnapshot(collectionClass)) {\n            orderedCollection = orderedCollection.createSnapshot();\n        }\n\n        return orderedCollection;\n    }\n\n    boolean isSnapshot(ManagedCollection collectionClass) {\n        return collectionClass == ManagedCollection.REALMRESULTS_SNAPSHOT_LIST_BASE ||\n                collectionClass == ManagedCollection.REALMRESULTS_SNAPSHOT_RESULTS_BASE;\n    }\n\n    boolean isSnapshot(CollectionClass collectionClass) {\n        return collectionClass == CollectionClass.REALMRESULTS_SNAPSHOT_LIST_BASE ||\n                collectionClass == CollectionClass.REALMRESULTS_SNAPSHOT_RESULTS_BASE;\n    }\n\n    boolean isRealmList(ManagedCollection collectionClass) {\n        return collectionClass == ManagedCollection.MANAGED_REALMLIST;\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/ColumnInfoTests.java",
    "content": "/*\n * Copyright 2016 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 */\npackage io.realm;\n\nimport androidx.test.ext.junit.runners.AndroidJUnit4;\n\nimport org.junit.After;\nimport org.junit.Before;\nimport org.junit.Rule;\nimport org.junit.Test;\nimport org.junit.rules.ExpectedException;\nimport org.junit.runner.RunWith;\n\nimport io.realm.entities.Cat;\nimport io.realm.internal.RealmProxyMediator;\n\nimport static junit.framework.Assert.assertEquals;\nimport static junit.framework.Assert.assertNotSame;\nimport static junit.framework.Assert.fail;\nimport static org.junit.Assert.assertFalse;\n\n\n@RunWith(AndroidJUnit4.class)\npublic class ColumnInfoTests {\n    @Rule\n    public final TestRealmConfigurationFactory configFactory = new TestRealmConfigurationFactory();\n    @Rule\n    public final ExpectedException thrown = ExpectedException.none();\n\n    private Realm realm;\n    private RealmProxyMediator mediator;\n\n    @Before\n    public void setUp() {\n        RealmConfiguration config = configFactory.createConfiguration();\n        realm = Realm.getInstance(config);\n        mediator = realm.getConfiguration().getSchemaMediator();\n    }\n\n    @After\n    public void tearDown() {\n        if (realm != null) {\n            realm.close();\n        }\n    }\n\n    @Test\n    public void copyColumnInfoFrom_checkIndex() {\n        io_realm_entities_CatRealmProxy.CatColumnInfo sourceColumnInfo\n                = (io_realm_entities_CatRealmProxy.CatColumnInfo) mediator.createColumnInfo(Cat.class, realm.sharedRealm.getSchemaInfo());\n        io_realm_entities_CatRealmProxy.CatColumnInfo targetColumnInfo\n                = (io_realm_entities_CatRealmProxy.CatColumnInfo) mediator.createColumnInfo(Cat.class, realm.sharedRealm.getSchemaInfo());\n\n        // Checks precondition.\n        assertNotSame(sourceColumnInfo, targetColumnInfo);\n        assertFalse(sourceColumnInfo.getColumnKeysMap().equals(targetColumnInfo.getColumnKeysMap()));\n\n        sourceColumnInfo.nameColKey = 1;\n        sourceColumnInfo.ageColKey = 2;\n        sourceColumnInfo.heightColKey = 3;\n        sourceColumnInfo.weightColKey = 4;\n        sourceColumnInfo.hasTailColKey = 5;\n        sourceColumnInfo.birthdayColKey = 6;\n        sourceColumnInfo.ownerColKey = 7;\n        sourceColumnInfo.scaredOfDogColKey = 8;\n\n        targetColumnInfo.nameColKey = 0;\n        targetColumnInfo.ageColKey = 0;\n        targetColumnInfo.heightColKey = 0;\n        targetColumnInfo.weightColKey = 0;\n        targetColumnInfo.hasTailColKey = 0;\n        targetColumnInfo.birthdayColKey = 0;\n        targetColumnInfo.ownerColKey = 0;\n        targetColumnInfo.scaredOfDogColKey = 0;\n\n        targetColumnInfo.copyFrom(sourceColumnInfo);\n\n        assertEquals(sourceColumnInfo.nameColKey, targetColumnInfo.nameColKey);\n        assertEquals(sourceColumnInfo.ageColKey, targetColumnInfo.ageColKey);\n        assertEquals(sourceColumnInfo.heightColKey, targetColumnInfo.heightColKey);\n        assertEquals(sourceColumnInfo.weightColKey, targetColumnInfo.weightColKey);\n        assertEquals(sourceColumnInfo.hasTailColKey, targetColumnInfo.hasTailColKey);\n        assertEquals(sourceColumnInfo.birthdayColKey, targetColumnInfo.birthdayColKey);\n        assertEquals(sourceColumnInfo.ownerColKey, targetColumnInfo.ownerColKey);\n        assertEquals(sourceColumnInfo.scaredOfDogColKey, targetColumnInfo.scaredOfDogColKey);\n    }\n\n    @Test\n    public void copy_differentInstanceSameValues() {\n        final io_realm_entities_CatRealmProxy.CatColumnInfo columnInfo\n                = (io_realm_entities_CatRealmProxy.CatColumnInfo) mediator.createColumnInfo(Cat.class, realm.sharedRealm.getSchemaInfo());\n\n        columnInfo.nameColKey = 1;\n        columnInfo.ageColKey = 2;\n        columnInfo.heightColKey = 3;\n        columnInfo.weightColKey = 4;\n        columnInfo.hasTailColKey = 5;\n        columnInfo.birthdayColKey = 6;\n        columnInfo.ownerColKey = 7;\n        columnInfo.scaredOfDogColKey = 8;\n\n        io_realm_entities_CatRealmProxy.CatColumnInfo copy = (io_realm_entities_CatRealmProxy.CatColumnInfo) columnInfo.copy(true);\n\n        // verify that the copy is identical\n        assertNotSame(columnInfo, copy);\n        assertEquals(columnInfo.getColumnKeysMap(), copy.getColumnKeysMap());\n        assertEquals(columnInfo.nameColKey, copy.nameColKey);\n        assertEquals(columnInfo.ageColKey, copy.ageColKey);\n        assertEquals(columnInfo.heightColKey, copy.heightColKey);\n        assertEquals(columnInfo.weightColKey, copy.weightColKey);\n        assertEquals(columnInfo.hasTailColKey, copy.hasTailColKey);\n        assertEquals(columnInfo.birthdayColKey, copy.birthdayColKey);\n        assertEquals(columnInfo.ownerColKey, copy.ownerColKey);\n        assertEquals(columnInfo.scaredOfDogColKey, copy.scaredOfDogColKey);\n\n        // Modify original object\n        columnInfo.nameColKey = 0;\n        columnInfo.ageColKey = 0;\n        columnInfo.heightColKey = 0;\n        columnInfo.weightColKey = 0;\n        columnInfo.hasTailColKey = 0;\n        columnInfo.birthdayColKey = 0;\n        columnInfo.ownerColKey = 0;\n        columnInfo.scaredOfDogColKey = 0;\n\n        // the copy should not change\n        assertEquals(1, copy.nameColKey);\n        assertEquals(2, copy.ageColKey);\n        assertEquals(3, copy.heightColKey);\n        assertEquals(4, copy.weightColKey);\n        assertEquals(5, copy.hasTailColKey);\n        assertEquals(6, copy.birthdayColKey);\n        assertEquals(7, copy.ownerColKey);\n        assertEquals(8, copy.scaredOfDogColKey);\n    }\n\n    @Test\n    public void copy_immutableThrows() {\n        final io_realm_entities_CatRealmProxy.CatColumnInfo original\n                = (io_realm_entities_CatRealmProxy.CatColumnInfo) mediator.createColumnInfo(Cat.class, realm.sharedRealm.getSchemaInfo());\n\n        io_realm_entities_CatRealmProxy.CatColumnInfo copy = (io_realm_entities_CatRealmProxy.CatColumnInfo) original.copy(false);\n        try {\n            copy.copyFrom(original);\n            fail(\"Attempt to copy to an immutable ColumnInfo should throwS\");\n        } catch (UnsupportedOperationException ignore) {\n        }\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/CustomRealmNameTests.java",
    "content": "/*\n * Copyright 2018 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 */\npackage io.realm;\n\nimport androidx.test.ext.junit.runners.AndroidJUnit4;\n\nimport org.junit.After;\nimport org.junit.Before;\nimport org.junit.Ignore;\nimport org.junit.Rule;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\n\nimport io.realm.entities.realmname.ClassNameOverrideModulePolicy;\nimport io.realm.entities.realmname.ClassWithPolicy;\nimport io.realm.entities.realmname.ClassWithValueDefinedNames;\nimport io.realm.entities.realmname.CustomRealmNamesModule;\nimport io.realm.entities.realmname.FieldNameOverrideClassPolicy;\n\nimport static org.junit.Assert.assertEquals;\nimport static org.junit.Assert.assertFalse;\nimport static org.junit.Assert.assertNotNull;\nimport static org.junit.Assert.assertTrue;\nimport static org.junit.Assert.fail;\n\n/**\n * This class contains tests for checking that changing the internal Realm name\n * works correctly.\n */\n@RunWith(AndroidJUnit4.class)\npublic class CustomRealmNameTests {\n\n    @Rule\n    public final TestRealmConfigurationFactory configFactory = new TestRealmConfigurationFactory();\n    private Realm realm;\n    private DynamicRealm dynamicRealm;\n\n    @Before\n    public void setUp() {\n        RealmConfiguration config = configFactory.createConfigurationBuilder()\n                .modules(new CustomRealmNamesModule())\n                .build();\n        realm = Realm.getInstance(config);\n        dynamicRealm = DynamicRealm.getInstance(config);\n    }\n\n\n    @After\n    public void tearDown() {\n        if (realm != null && !realm.isClosed()) {\n            realm.close();\n        }\n        if (dynamicRealm != null && !dynamicRealm.isClosed()) {\n            dynamicRealm.close();\n        }\n    }\n\n    //\n    // Build checks\n    //\n\n    // Check that the module policy is used as the default for class and field names\n    @Test\n    public void modulePolicy_defaultPolicy() {\n        assertTrue(realm.getSchema().contains(\"default_policy_from_module\"));\n        RealmObjectSchema classSchema = realm.getSchema().get(\"default_policy_from_module\");\n        assertTrue(classSchema.hasField(\"camel_case\"));\n    }\n\n    // Check that field name policies on classes override those from modules\n    @Test\n    public void classFieldPolicy_overrideModuleFieldPolicy() {\n        assertTrue(realm.getSchema().contains(ClassWithPolicy.CLASS_NAME));\n        RealmObjectSchema classSchema = realm.getSchema().get(ClassWithPolicy.CLASS_NAME);\n        for (String field : ClassWithPolicy.ALL_FIELDS) {\n            assertTrue(field + \" was not found.\", classSchema.hasField(field));\n        }\n    }\n\n    // Check that explicit class name override both module and class policies\n    @Test\n    public void className_overrideModuleClassPolicy() {\n        assertTrue(realm.getSchema().contains(ClassNameOverrideModulePolicy.CLASS_NAME));\n    }\n\n    // Check that a explicitly setting a field name overrides a class field name policy\n    @Test\n    public void fieldName_overrideClassPolicy() {\n        RealmObjectSchema classSchema = realm.getSchema().get(FieldNameOverrideClassPolicy.CLASS_NAME);\n        assertTrue(classSchema.hasField(FieldNameOverrideClassPolicy.FIELD_CAMEL_CASE));\n    }\n\n    // Check that a explicitly setting a field name overrides a module field name policy\n    @Test\n    public void fieldName_overrideModulePolicy() {\n        RealmObjectSchema classSchema = realm.getSchema().get(FieldNameOverrideClassPolicy.CLASS_NAME);\n        assertTrue(classSchema.hasField(FieldNameOverrideClassPolicy.FIELD_CAMEL_CASE));\n    }\n\n    //\n    // Query tests\n    //\n    // Mostly smoke test, as we only want to test that the query system correctly maps between\n    // Java field names and cores.\n    //\n    @Test\n    public void typedQueryWithJavaNames() {\n        RealmResults<ClassWithPolicy> results = realm.where(ClassWithPolicy.class)\n                .equalTo(\"camelCase\", \"foo\") // Java name in model class\n                .equalTo(\"parents.PascalCase\", 1) // Backlinks also uses java names\n                .sort(\"mHungarian\") // Sorting uses Java names\n                .distinct(\"customName\") // Distinct uses Java names\n                .findAll();\n        assertTrue(results.isEmpty());\n    }\n\n    @Test\n    public void typedQueryWithInternalNamesThrows() {\n\n        // Normal predicates\n        try {\n            realm.where(ClassWithPolicy.class).equalTo(ClassWithPolicy.FIELD_CAMEL_CASE, \"\");\n        } catch (IllegalArgumentException ignore) {\n        }\n\n        // Sorting\n        try {\n            realm.where(ClassWithPolicy.class).sort(ClassWithPolicy.FIELD_CAMEL_CASE);\n        } catch (IllegalArgumentException ignore) {\n        }\n\n        // Distinct\n        try {\n            realm.where(ClassWithPolicy.class).distinct(ClassWithPolicy.FIELD_CAMEL_CASE);\n        } catch (IllegalArgumentException ignore) {\n        }\n\n        // Backlinks do not exist as internal fields that can be queried\n    }\n\n\n    @Test\n    public void dynamicQueryWithInternalNames() {\n        // Backlink queries not supported on dynamic queries\n        RealmResults<DynamicRealmObject> results = dynamicRealm.where(ClassWithPolicy.CLASS_NAME)\n                .equalTo(ClassWithPolicy.FIELD_CAMEL_CASE, \"foo\") // Normal queries use internal names\n                .sort(ClassWithPolicy.FIELD_M_HUNGARIAN) // Sorting uses internal names\n                .distinct(ClassWithPolicy.FIELD_CUSTOM_NAME) // Distinct uses internal names\n                .findAll();\n        assertTrue(results.isEmpty());\n    }\n\n    @Test\n    public void dynamicQueryWithJavaNamesThrows() {\n        try {\n            dynamicRealm.where(ClassWithPolicy.CLASS_NAME).equalTo(\"camelCase\", \"\");\n        } catch (IllegalArgumentException ignore) {\n        }\n\n        // Sorting\n        try {\n            dynamicRealm.where(ClassWithPolicy.CLASS_NAME).sort(\"camelCase\");\n        } catch (IllegalArgumentException ignore) {\n        }\n\n        // Distinct\n        try {\n            dynamicRealm.where(ClassWithPolicy.CLASS_NAME).distinct(\"camelCase\");\n        } catch (IllegalArgumentException ignore) {\n        }\n    }\n\n    //\n    // Schema tests\n    //\n    @Test\n    public void typedSchemaReturnsInternalNames() {\n        RealmSchema schema = realm.getSchema();\n        assertTrue(schema.contains(ClassWithPolicy.CLASS_NAME));\n        RealmObjectSchema classSchema = schema.get(ClassWithPolicy.CLASS_NAME);\n        assertEquals(ClassWithPolicy.ALL_FIELDS.size(), classSchema.getFieldNames().size());\n        for (String fieldName : ClassWithPolicy.ALL_FIELDS) {\n            assertTrue(\"Could not find: \" + fieldName, classSchema.hasField(fieldName));\n        }\n    }\n\n    @Test\n    public void dynamicSchemaReturnsInternalNames() {\n        RealmSchema schema = realm.getSchema();\n        assertTrue(schema.contains(ClassWithPolicy.CLASS_NAME));\n        RealmObjectSchema classSchema = schema.get(ClassWithPolicy.CLASS_NAME);\n        assertEquals(ClassWithPolicy.ALL_FIELDS.size(), classSchema.getFieldNames().size());\n        for (String fieldName : ClassWithPolicy.ALL_FIELDS) {\n            assertTrue(\"Could not find: \" + fieldName, classSchema.hasField(fieldName));\n        }\n    }\n\n    // Verify that names using the default value() parameter on annotations are used correctly\n    @Test\n    public void valueParameterDefinedNamesInsteadOfExplicit() {\n        RealmSchema schema = realm.getSchema();\n        assertTrue(schema.contains(ClassWithValueDefinedNames.REALM_CLASS_NAME));\n        assertFalse(schema.contains(ClassWithValueDefinedNames.JAVA_CLASS_NAME));\n\n        RealmObjectSchema classSchema = schema.get(ClassWithValueDefinedNames.REALM_CLASS_NAME);\n        assertTrue(classSchema.hasField(ClassWithValueDefinedNames.REALM_FIELD_NAME));\n        assertFalse(classSchema.hasField(ClassWithValueDefinedNames.JAVA_FIELD_NAME));\n    }\n\n    //\n    // Dynamic Realm tests\n    //\n    @Test\n    public void createObjects() {\n        dynamicRealm.executeTransaction(r -> {\n            // Use internal name\n            DynamicRealmObject obj = r.createObject(ClassWithPolicy.CLASS_NAME);\n            assertNotNull(obj);\n        });\n    }\n\n\n    //\n    // Realm tests\n    //\n    @Test\n    public void copyOrUpdate() {\n        realm.executeTransaction(r -> {\n            ClassWithPolicy obj = new ClassWithPolicy();\n            try {\n                r.copyToRealmOrUpdate(obj); // Verify that we correctly check that a primary key is missing\n                fail();\n            } catch (IllegalArgumentException e) {\n                assertTrue(e.getMessage().startsWith(\"A RealmObject with no @PrimaryKey cannot be updated\"));\n            }\n        });\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/DynamicRealmAsyncQueryTests.kt",
    "content": "/*\n * Copyright 2020 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 */\npackage io.realm\n\nimport androidx.test.ext.junit.runners.AndroidJUnit4\nimport io.realm.TestHelper.TestLogger\nimport io.realm.entities.AllTypes\nimport io.realm.entities.Owner\nimport io.realm.internal.async.RealmThreadPoolExecutor\nimport io.realm.log.LogLevel\nimport io.realm.log.RealmLog\nimport io.realm.rule.BlockingLooperThread\nimport org.junit.Before\nimport org.junit.Rule\nimport org.junit.Test\nimport org.junit.rules.ExpectedException\nimport org.junit.runner.RunWith\nimport java.util.concurrent.atomic.AtomicInteger\nimport kotlin.test.assertEquals\nimport kotlin.test.assertNull\nimport kotlin.test.assertTrue\nimport kotlin.test.fail\n\n@RunWith(AndroidJUnit4::class)\nclass DynamicRealmAsyncQueryTests {\n\n    @get:Rule\n    val configFactory = TestRealmConfigurationFactory()\n    @get:Rule\n    val thrown: ExpectedException = ExpectedException.none()\n\n    private val looperThread = BlockingLooperThread()\n\n    private lateinit var config: RealmConfiguration\n\n    @Before\n    fun setUp() {\n        config = configFactory.createConfiguration()\n\n        // Initializes schema. DynamicRealm will not do that, so let a normal Realm create the file first.\n        Realm.getInstance(config).close()\n    }\n\n    // ****************************\n    // ****  Async transaction  ***\n    // ****************************\n    // Starts asynchronously a transaction to insert one element.\n    @Test\n    fun executeTransactionAsync() = looperThread.runBlocking {\n        val realm = DynamicRealm.getInstance(config)\n                .also { looperThread.closeAfterTest(it) }\n\n        assertEquals(0, realm.where(Owner.CLASS_NAME).count())\n\n        realm.executeTransactionAsync({ transactionRealm ->\n            val owner = transactionRealm.createObject(Owner.CLASS_NAME)\n            owner.setString(Owner.FIELD_NAME, \"Owner\")\n        }, {\n            assertEquals(1, realm.where(Owner.CLASS_NAME).count())\n            assertEquals(\"Owner\", realm.where(Owner.CLASS_NAME).findFirst()!!.getString(Owner.FIELD_NAME))\n            looperThread.testComplete()\n        }) { error ->\n            fail(error.message)\n        }\n    }\n\n    @Test\n    fun executeTransactionAsync_onSuccess() = looperThread.runBlocking {\n        val realm = DynamicRealm.getInstance(config)\n                .also { looperThread.closeAfterTest(it) }\n\n        assertEquals(0, realm.where(Owner.CLASS_NAME).count())\n\n        realm.executeTransactionAsync(DynamicRealm.Transaction { transactionRealm ->\n            val owner = transactionRealm.createObject(Owner.CLASS_NAME)\n            owner.setString(Owner.FIELD_NAME, \"Owner\")\n        }, DynamicRealm.Transaction.OnSuccess {\n            assertEquals(1, realm.where(Owner.CLASS_NAME).count())\n            assertEquals(\"Owner\", realm.where(Owner.CLASS_NAME).findFirst()!!.getString(Owner.FIELD_NAME))\n            looperThread.testComplete()\n        })\n    }\n\n    @Test\n    fun executeTransactionAsync_onSuccessCallerRealmClosed() = looperThread.runBlocking {\n        val realm = DynamicRealm.getInstance(config)\n\n        assertEquals(0, realm.where(Owner.CLASS_NAME).count())\n        realm.executeTransactionAsync(DynamicRealm.Transaction { transactionRealm ->\n            val owner = transactionRealm.createObject(Owner.CLASS_NAME)\n            owner.setString(Owner.FIELD_NAME, \"Owner\")\n        }, DynamicRealm.Transaction.OnSuccess {\n            assertTrue(realm.isClosed)\n\n            DynamicRealm.getInstance(config).use { newRealm ->\n                assertEquals(1, newRealm.where(Owner.CLASS_NAME).count())\n                assertEquals(\"Owner\", newRealm.where(Owner.CLASS_NAME).findFirst()!!.getString(Owner.FIELD_NAME))\n            }\n\n            looperThread.testComplete()\n        })\n        realm.close()\n    }\n\n    @Test\n    fun executeTransactionAsync_onError() = looperThread.runBlocking {\n        val realm = DynamicRealm.getInstance(config)\n                .also { looperThread.closeAfterTest(it) }\n\n        val runtimeException = RuntimeException(\"Oh! What a Terrible Failure\")\n\n        assertEquals(0, realm.where(Owner.CLASS_NAME).count())\n\n        realm.executeTransactionAsync({\n            throw runtimeException\n        }) { error ->\n            assertEquals(0, realm.where(Owner.CLASS_NAME).count())\n            assertNull(realm.where(Owner.CLASS_NAME).findFirst())\n            assertEquals(runtimeException, error)\n\n            looperThread.testComplete()\n        }\n    }\n\n    @Test\n    fun executeTransactionAsync_onErrorCallerRealmClosed() = looperThread.runBlocking {\n        val realm = DynamicRealm.getInstance(config)\n        val runtimeException = RuntimeException(\"Oh! What a Terrible Failure\")\n\n        assertEquals(0, realm.where(Owner.CLASS_NAME).count())\n\n        realm.executeTransactionAsync({\n            throw runtimeException\n        }) { error ->\n            assertTrue(realm.isClosed)\n\n            DynamicRealm.getInstance(config).use { newRealm ->\n                assertEquals(0, newRealm.where(Owner.CLASS_NAME).count())\n                assertNull(newRealm.where(Owner.CLASS_NAME).findFirst())\n                assertEquals(runtimeException, error)\n            }\n\n            looperThread.testComplete()\n        }\n        realm.close()\n    }\n\n    @Test\n    fun executeTransactionAsync_NoCallbacks() = looperThread.runBlocking {\n        val realm = DynamicRealm.getInstance(config)\n                .also { looperThread.closeAfterTest(it) }\n\n        assertEquals(0, realm.where(Owner.CLASS_NAME).count())\n\n        realm.executeTransactionAsync { transactionRealm ->\n            val owner = transactionRealm.createObject(Owner.CLASS_NAME)\n            owner.setString(Owner.FIELD_NAME, \"Owner\")\n        }\n\n        realm.addChangeListener { listenerRealm ->\n            assertEquals(\"Owner\", listenerRealm.where(Owner.CLASS_NAME).findFirst()!!.getString(Owner.FIELD_NAME))\n\n            looperThread.testComplete()\n        }\n    }\n\n    // Tests that an async transaction that throws when call cancelTransaction manually.\n    @Test\n    fun executeTransactionAsync_cancelTransactionInside() = looperThread.runBlocking {\n        val testLogger = TestLogger(LogLevel.DEBUG)\n        RealmLog.add(testLogger)\n\n        val realm = DynamicRealm.getInstance(config)\n                .also { looperThread.closeAfterTest(it) }\n\n        assertEquals(0, realm.where(Owner.CLASS_NAME).count())\n\n        realm.executeTransactionAsync({ transactionRealm ->\n            val owner = transactionRealm.createObject(Owner.CLASS_NAME)\n            owner.setString(Owner.FIELD_NAME, \"Owner\")\n            transactionRealm.cancelTransaction()\n        }, {\n            fail(\"Should not reach success if runtime exception is thrown in callback.\")\n        }) { error ->\n            // Ensure we are giving developers quality messages in the logs.\n            assertTrue(testLogger.message.contains(\"Exception has been thrown: Can't commit a non-existing write transaction\"))\n            assertTrue(error is java.lang.IllegalStateException)\n\n            RealmLog.remove(testLogger)\n\n            looperThread.testComplete()\n        }\n    }\n\n    // Tests if the background Realm is closed when transaction success returned.\n    @Test\n    fun executeTransactionAsync_realmClosedOnSuccess() = looperThread.runBlocking {\n        val realm = DynamicRealm.getInstance(config)\n                .also { looperThread.closeAfterTest(it) }\n\n        val counter = AtomicInteger(100)\n\n        val cacheCallback = RealmCache.Callback { count ->\n            assertEquals(1, count.toLong())\n            if (counter.decrementAndGet() == 0) {\n                looperThread.testComplete()\n            }\n        }\n\n        val onSuccessCallback = object : DynamicRealm.Transaction.OnSuccess {\n            override fun onSuccess() {\n                RealmCache.invokeWithGlobalRefCount(realm.getConfiguration(), cacheCallback)\n                if (counter.get() == 0) {\n                    // Finishes testing.\n                    return\n                }\n                realm.executeTransactionAsync(DynamicRealm.Transaction {\n                    // no-op\n                }, this)\n            }\n        }\n        realm.executeTransactionAsync(DynamicRealm.Transaction {\n            // no-op\n        }, onSuccessCallback)\n    }\n\n    // Tests if the background Realm is closed when transaction error returned.\n    @Test\n    fun executeTransaction_async_realmClosedOnError() = looperThread.runBlocking {\n        val realm = DynamicRealm.getInstance(config)\n                .also { looperThread.closeAfterTest(it) }\n\n        val counter = AtomicInteger(100)\n\n        val cacheCallback = RealmCache.Callback { count ->\n            assertEquals(1, count.toLong())\n            if (counter.decrementAndGet() == 0) {\n                looperThread.testComplete()\n            }\n        }\n\n        val onErrorCallback = object : DynamicRealm.Transaction.OnError {\n            override fun onError(error: Throwable) {\n                RealmCache.invokeWithGlobalRefCount(realm.getConfiguration(), cacheCallback)\n                if (counter.get() == 0) {\n                    // Finishes testing.\n                    return\n                }\n                realm.executeTransactionAsync(DynamicRealm.Transaction { throw RuntimeException(\"Dummy exception\") }, this)\n            }\n        }\n\n        realm.executeTransactionAsync(DynamicRealm.Transaction {\n            throw RuntimeException(\"Dummy exception\")\n        }, onErrorCallback)\n    }\n\n    // Test case for https://github.com/realm/realm-java/issues/1893\n    // Ensures that onSuccess is called with the correct Realm version for async transaction.\n    @Test\n    fun executeTransactionAsync_asyncQuery() = looperThread.runBlocking {\n        val realm = DynamicRealm.getInstance(config)\n                .also { looperThread.closeAfterTest(it) }\n\n        val results = realm.where(AllTypes.CLASS_NAME).findAllAsync()\n\n        assertEquals(0, results.size.toLong())\n\n        realm.executeTransactionAsync({ transactionRealm ->\n            transactionRealm.createObject(AllTypes.CLASS_NAME)\n        }, {\n            assertEquals(1, realm.where(AllTypes.CLASS_NAME).count())\n\n            // We cannot guarantee the async results get delivered from OS.\n            if (results.isLoaded) {\n                assertEquals(1, results.size.toLong())\n            } else {\n                assertEquals(0, results.size.toLong())\n            }\n\n            looperThread.testComplete()\n        }) {\n            fail(it.message)\n        }\n    }\n\n    @Test\n    fun executeTransactionAsync_onSuccessOnNonLooperThreadThrows() {\n        DynamicRealm.getInstance(config).use { realm ->\n            thrown.expect(IllegalStateException::class.java)\n            realm.executeTransactionAsync(DynamicRealm.Transaction {\n                // no-op\n            }, DynamicRealm.Transaction.OnSuccess {\n                // no-op\n            })\n        }\n    }\n\n    @Test\n    fun executeTransactionAsync_onErrorOnNonLooperThreadThrows() {\n        DynamicRealm.getInstance(config).use { realm ->\n            thrown.expect(IllegalStateException::class.java)\n            realm.executeTransactionAsync(DynamicRealm.Transaction {\n                // no-op\n            }, DynamicRealm.Transaction.OnError {\n                // no-op\n            })\n        }\n    }\n\n    // https://github.com/realm/realm-java/issues/4595#issuecomment-298830411\n    // onSuccess might commit another transaction which will call didChange. So before calling async transaction\n    // callbacks, the callback should be cleared.\n    @Test\n    @Throws(NoSuchFieldException::class, IllegalAccessException::class)\n    fun executeTransactionAsync_callbacksShouldBeClearedBeforeCalling() = looperThread.runBlocking {\n        val callbackCounter = AtomicInteger(0)\n        val foregroundRealm = DynamicRealm.getInstance(config)\n                .also { looperThread.closeAfterTest(it) }\n\n        // Use single thread executor\n        TestHelper.replaceRealmThreadExecutor(RealmThreadPoolExecutor.newSingleThreadExecutor())\n\n        // To reproduce the issue, the posted callback needs to arrived before the Object Store did_change called.\n        // We just disable the auto refresh here then the did_change won't be called.\n        foregroundRealm.isAutoRefresh = false\n        foregroundRealm.executeTransactionAsync(DynamicRealm.Transaction { transactionRealm ->\n            transactionRealm.createObject(AllTypes.CLASS_NAME)\n        }, DynamicRealm.Transaction.OnSuccess {\n            // This will be called first and only once\n            assertEquals(0, callbackCounter.getAndIncrement().toLong())\n\n            // This transaction should never trigger the onSuccess.\n            foregroundRealm.beginTransaction()\n            foregroundRealm.createObject(AllTypes.CLASS_NAME)\n            foregroundRealm.commitTransaction()\n        })\n\n        foregroundRealm.executeTransactionAsync(DynamicRealm.Transaction { transactionRealm ->\n            transactionRealm.createObject(AllTypes.CLASS_NAME)\n        }, DynamicRealm.Transaction.OnSuccess {\n            // This will be called 2nd and only once\n            assertEquals(1, callbackCounter.getAndIncrement().toLong())\n\n            looperThread.testComplete()\n        })\n\n        // Wait for all async tasks finish to ensure the async transaction posted callback will arrive first.\n        TestHelper.resetRealmThreadExecutor()\n        looperThread.postRunnable(Runnable {\n            // Manually call refresh, so the did_change will be triggered.\n            foregroundRealm.sharedRealm.refresh()\n        })\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/DynamicRealmObjectTests.java",
    "content": "/*\n * Copyright 2015 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\npackage io.realm;\n\nimport org.bson.types.Decimal128;\nimport org.bson.types.ObjectId;\nimport org.hamcrest.Matchers;\nimport org.junit.After;\nimport org.junit.Before;\nimport org.junit.Rule;\nimport org.junit.Test;\nimport org.junit.rules.ExpectedException;\nimport org.junit.runner.RunWith;\n\nimport java.lang.reflect.Field;\nimport java.math.BigDecimal;\nimport java.text.ParseException;\nimport java.util.Arrays;\nimport java.util.Date;\nimport java.util.List;\nimport java.util.UUID;\nimport java.util.concurrent.CountDownLatch;\nimport java.util.concurrent.atomic.AtomicReference;\n\nimport androidx.test.ext.junit.runners.AndroidJUnit4;\nimport io.realm.entities.AllJavaTypes;\nimport io.realm.entities.AllTypes;\nimport io.realm.entities.CyclicType;\nimport io.realm.entities.Dog;\nimport io.realm.entities.NullTypes;\nimport io.realm.entities.NullablePrimitiveFields;\nimport io.realm.entities.Owner;\nimport io.realm.entities.PrimaryKeyAsBoxedByte;\nimport io.realm.entities.PrimaryKeyAsBoxedInteger;\nimport io.realm.entities.PrimaryKeyAsBoxedLong;\nimport io.realm.entities.PrimaryKeyAsBoxedShort;\nimport io.realm.entities.PrimaryKeyAsByte;\nimport io.realm.entities.PrimaryKeyAsInteger;\nimport io.realm.entities.PrimaryKeyAsLong;\nimport io.realm.entities.PrimaryKeyAsShort;\nimport io.realm.entities.PrimaryKeyAsString;\nimport io.realm.exceptions.RealmException;\n\nimport static org.junit.Assert.assertArrayEquals;\nimport static org.junit.Assert.assertEquals;\nimport static org.junit.Assert.assertFalse;\nimport static org.junit.Assert.assertNotNull;\nimport static org.junit.Assert.assertNull;\nimport static org.junit.Assert.assertSame;\nimport static org.junit.Assert.assertThat;\nimport static org.junit.Assert.assertTrue;\nimport static org.junit.Assert.fail;\n\n@RunWith(AndroidJUnit4.class)\npublic class DynamicRealmObjectTests {\n    @Rule\n    public final TestRealmConfigurationFactory configFactory = new TestRealmConfigurationFactory();\n    @Rule\n    public final ExpectedException thrown = ExpectedException.none();\n\n    private Realm realm;\n    private DynamicRealm dynamicRealm;\n    private AllJavaTypes typedObj;\n    // DynamicRealmObject constructed from a typed RealmObject\n    private DynamicRealmObject dObjTyped;\n    // DynamicRealmObject queried from DynamicRealm\n    private DynamicRealmObject dObjDynamic;\n\n    @Before\n    public void setUp() {\n        RealmConfiguration realmConfig = configFactory.createConfiguration();\n        realm = Realm.getInstance(realmConfig);\n        realm.beginTransaction();\n        typedObj = realm.createObject(AllJavaTypes.class, 1);\n        typedObj.setFieldString(\"str\");\n        typedObj.setFieldShort((short) 1);\n        typedObj.setFieldInt(1);\n        typedObj.setFieldLong(1);\n        typedObj.setFieldByte((byte) 4);\n        typedObj.setFieldFloat(1.23f);\n        typedObj.setFieldDouble(1.234d);\n        typedObj.setFieldBinary(new byte[]{1, 2, 3});\n        typedObj.setFieldBoolean(true);\n        typedObj.setFieldDate(new Date(1000));\n        typedObj.setFieldDecimal128(new Decimal128(BigDecimal.TEN));\n        typedObj.setFieldObjectId(new ObjectId(TestHelper.generateObjectIdHexString(7)));\n        typedObj.setFieldUUID(UUID.randomUUID());\n        typedObj.setFieldObject(typedObj);\n        typedObj.getFieldList().add(typedObj);\n        typedObj.getFieldIntegerList().add(1);\n        typedObj.getFieldStringList().add(\"str\");\n        typedObj.getFieldBooleanList().add(true);\n        typedObj.getFieldFloatList().add(1.23F);\n        typedObj.getFieldDoubleList().add(1.234D);\n        typedObj.getFieldBinaryList().add(new byte[] {1, 2, 3});\n        typedObj.getFieldDateList().add(new Date(1000));\n        dObjTyped = new DynamicRealmObject(typedObj);\n        realm.commitTransaction();\n\n        dynamicRealm = DynamicRealm.getInstance(realm.getConfiguration());\n        dObjDynamic = dynamicRealm.where(AllJavaTypes.CLASS_NAME).findFirst();\n    }\n\n    @After\n    public void tearDown() {\n        if (realm != null) {\n            realm.close();\n        }\n        if (dynamicRealm != null) {\n            dynamicRealm.close();\n        }\n    }\n\n    // Types supported by the DynamicRealmObject.\n    private enum SupportedType {\n        BOOLEAN, SHORT, INT, LONG, BYTE, FLOAT, DOUBLE, STRING, BINARY, DATE, OBJECT, DECIMAL128, OBJECT_ID, UUID, LIST,\n        LIST_INTEGER, LIST_STRING, LIST_BOOLEAN, LIST_FLOAT, LIST_DOUBLE, LIST_BINARY, LIST_DATE, LIST_DECIMAL128,\n        LIST_OBJECT_ID, LIST_UUID\n    }\n\n    private enum ThreadConfinedMethods {\n        GET_BOOLEAN, GET_BYTE, GET_SHORT, GET_INT, GET_LONG, GET_FLOAT, GET_DOUBLE, GET_UUID,\n        GET_BLOB, GET_STRING, GET_DATE, GET_DECIMAL128, GET_OBJECT_ID, GET_OBJECT, GET_LIST, GET_PRIMITIVE_LIST, GET,\n\n        SET_BOOLEAN, SET_BYTE, SET_SHORT, SET_INT, SET_LONG, SET_FLOAT, SET_DOUBLE, SET_UUID,\n        SET_BLOB, SET_STRING, SET_DATE, SET_DECIMAL128, SET_OBJECT_ID, SET_OBJECT, SET_LIST, SET_PRIMITIVE_LIST, SET,\n\n        IS_NULL, SET_NULL,\n\n        HAS_FIELD, GET_FIELD_NAMES, GET_TYPE, GET_FIELD_TYPE,\n\n        HASH_CODE, EQUALS, TO_STRING,\n    }\n\n    @SuppressWarnings({\"ResultOfMethodCallIgnored\", \"EqualsWithItself\", \"SelfEquals\"})\n    private static void callThreadConfinedMethod(DynamicRealmObject obj, ThreadConfinedMethods method) {\n        switch (method) {\n            case GET_BOOLEAN:           obj.getBoolean(AllJavaTypes.FIELD_BOOLEAN);                 break;\n            case GET_BYTE:              obj.getByte(AllJavaTypes.FIELD_BYTE);                       break;\n            case GET_SHORT:             obj.getShort(AllJavaTypes.FIELD_SHORT);                     break;\n            case GET_INT:               obj.getInt(AllJavaTypes.FIELD_INT);                         break;\n            case GET_LONG:              obj.getLong(AllJavaTypes.FIELD_LONG);                       break;\n            case GET_FLOAT:             obj.getFloat(AllJavaTypes.FIELD_FLOAT);                     break;\n            case GET_DOUBLE:            obj.getDouble(AllJavaTypes.FIELD_DOUBLE);                   break;\n            case GET_BLOB:              obj.getBlob(AllJavaTypes.FIELD_BINARY);                     break;\n            case GET_STRING:            obj.getString(AllJavaTypes.FIELD_STRING);                   break;\n            case GET_DATE:              obj.getDate(AllJavaTypes.FIELD_DATE);                       break;\n            case GET_DECIMAL128:        obj.getDate(AllJavaTypes.FIELD_DECIMAL128);                 break;\n            case GET_OBJECT_ID:         obj.getDate(AllJavaTypes.FIELD_OBJECT_ID);                  break;\n            case GET_UUID:              obj.getDate(AllJavaTypes.FIELD_UUID);                       break;\n            case GET_OBJECT:            obj.getObject(AllJavaTypes.FIELD_OBJECT);                   break;\n            case GET_LIST:              obj.getList(AllJavaTypes.FIELD_LIST);                       break;\n            case GET_PRIMITIVE_LIST:    obj.getList(AllJavaTypes.FIELD_STRING_LIST, String.class);  break;\n            case GET:                   obj.get(AllJavaTypes.FIELD_LONG);                           break;\n\n            case SET_BOOLEAN:           obj.setBoolean(AllJavaTypes.FIELD_BOOLEAN, true);                           break;\n            case SET_BYTE:              obj.setByte(AllJavaTypes.FIELD_BYTE,       (byte) 1);                       break;\n            case SET_SHORT:             obj.setShort(AllJavaTypes.FIELD_SHORT,     (short) 1);                      break;\n            case SET_INT:               obj.setInt(AllJavaTypes.FIELD_INT,         1);                              break;\n            case SET_LONG:              obj.setLong(AllJavaTypes.FIELD_LONG,       1L);                             break;\n            case SET_FLOAT:             obj.setFloat(AllJavaTypes.FIELD_FLOAT,     1F);                             break;\n            case SET_DOUBLE:            obj.setDouble(AllJavaTypes.FIELD_DOUBLE,   1D);                             break;\n            case SET_BLOB:              obj.setBlob(AllJavaTypes.FIELD_BINARY,     new byte[] {1, 2, 3});           break;\n            case SET_STRING:            obj.setString(AllJavaTypes.FIELD_STRING,   \"12345\");                        break;\n            case SET_DATE:              obj.setDate(AllJavaTypes.FIELD_DATE,       new Date(1L));                   break;\n            case SET_DECIMAL128:        obj.setDecimal128(AllJavaTypes.FIELD_DECIMAL128, new Decimal128(BigDecimal.ONE)); break;\n            case SET_OBJECT_ID:         obj.setObjectId(AllJavaTypes.FIELD_OBJECT_ID, new ObjectId(TestHelper.generateObjectIdHexString(5))); break;\n            case SET_UUID:              obj.setUUID(AllJavaTypes.FIELD_UUID, UUID.randomUUID());                break;\n            case SET_OBJECT:            obj.setObject(AllJavaTypes.FIELD_OBJECT,   obj);                            break;\n            case SET_LIST:              obj.setList(AllJavaTypes.FIELD_LIST,       new RealmList<>(obj));           break;\n            case SET_PRIMITIVE_LIST:    obj.setList(AllJavaTypes.FIELD_STRING_LIST,new RealmList<String>(\"foo\"));   break;\n            case SET:                   obj.set(AllJavaTypes.FIELD_LONG,           1L);                             break;\n\n            case IS_NULL:     obj.isNull(AllJavaTypes.FIELD_OBJECT);           break;\n            case SET_NULL:    obj.setNull(AllJavaTypes.FIELD_OBJECT);          break;\n\n            case HAS_FIELD:       obj.hasField(AllJavaTypes.FIELD_OBJECT);     break;\n            case GET_FIELD_NAMES: obj.getFieldNames();                         break;\n            case GET_TYPE:        obj.getType();                               break;\n            case GET_FIELD_TYPE:  obj.getFieldType(AllJavaTypes.FIELD_OBJECT); break;\n\n            case HASH_CODE:   obj.hashCode();  break;\n            case EQUALS:      obj.equals(obj); break;\n            case TO_STRING:   obj.toString();  break;\n\n            default:\n                throw new AssertionError(\"missing case for \" + method);\n        }\n    }\n\n    @Test\n    public void callThreadConfinedMethodsFromWrongThread() throws Throwable {\n\n        dynamicRealm.beginTransaction();\n        dynamicRealm.deleteAll();\n        final DynamicRealmObject obj = dynamicRealm.createObject(AllJavaTypes.CLASS_NAME, 100L);\n        dynamicRealm.commitTransaction();\n\n        final AtomicReference<Throwable> throwableFromThread = new AtomicReference<Throwable>();\n        final CountDownLatch testFinished = new CountDownLatch(1);\n\n        final String expectedMessage;\n        //noinspection TryWithIdenticalCatches\n        try {\n            final Field expectedMessageField = BaseRealm.class.getDeclaredField(\"INCORRECT_THREAD_MESSAGE\");\n            expectedMessageField.setAccessible(true);\n            expectedMessage = (String) expectedMessageField.get(null);\n        } catch (NoSuchFieldException e) {\n            throw new AssertionError(e);\n        } catch (IllegalAccessException e) {\n            throw new AssertionError(e);\n        }\n\n        final Thread thread = new Thread(\"callThreadConfinedMethodsFromWrongThread\") {\n            @Override\n            public void run() {\n                try {\n                    for (ThreadConfinedMethods method : ThreadConfinedMethods.values()) {\n                        try {\n                            callThreadConfinedMethod(obj, method);\n                            fail(\"IllegalStateException must be thrown.\");\n                        } catch (IllegalStateException e) {\n                            if (expectedMessage.equals(e.getMessage())) {\n                                // expected exception\n                                continue;\n                            }\n                            throwableFromThread.set(e);\n                            return;\n                        }\n                    }\n                } finally {\n                    testFinished.countDown();\n                }\n            }\n        };\n        thread.start();\n\n        TestHelper.awaitOrFail(testFinished);\n        final Throwable throwable = throwableFromThread.get();\n        if (throwable != null) {\n            throw throwable;\n        }\n    }\n\n\n    @Test (expected = IllegalArgumentException.class)\n    public void constructor_nullThrows () {\n        new DynamicRealmObject((RealmObject)null);\n    }\n\n    @Test (expected = IllegalArgumentException.class)\n    public void constructor_dynamicObjectThrows () {\n        new DynamicRealmObject(dObjTyped);\n    }\n\n    @Test\n    public void constructor_deletedObjectThrows() {\n        realm.beginTransaction();\n        typedObj.deleteFromRealm();\n        realm.commitTransaction();\n        thrown.expect(IllegalArgumentException.class);\n        new DynamicRealmObject(typedObj);\n    }\n\n    @Test (expected = IllegalArgumentException.class)\n    public void constructor_unmanagedObjectThrows() {\n        new DynamicRealmObject(new AllTypes());\n    }\n\n    // Tests that all getters fail if given invalid field name.\n    @Test\n    public void typedGetter_illegalFieldNameThrows() {\n        // Sets arguments.\n        String linkedField = AllJavaTypes.FIELD_OBJECT + \".\" + AllJavaTypes.FIELD_STRING;\n        List<String> arguments = Arrays.asList(null, \"foo\", AllJavaTypes.FIELD_STRING, linkedField);\n        List<String> stringArguments = Arrays.asList(null, \"foo\", AllJavaTypes.FIELD_BOOLEAN, linkedField);\n\n        // Tests all getters.\n        for (SupportedType type : SupportedType.values()) {\n\n            // We cannot modularize everything, so STRING is a special case with its own set\n            // of failing values. Only difference is the wrong type column has to be different.\n            List<String> args = (type == SupportedType.STRING) ? stringArguments : arguments;\n            try {\n                callGetter(dObjTyped, type, args);\n                fail();\n            } catch (IllegalArgumentException ignored) {\n            }\n            try {\n                callGetter(dObjDynamic, type, args);\n                fail();\n            } catch (IllegalArgumentException ignored) {\n            }\n        }\n    }\n\n    @Test\n    public void typedGetter_wrongUnderlyingTypeThrows() {\n        for (SupportedType type : SupportedType.values()) {\n            try {\n                // Makes sure we hit the wrong underlying type for all types.\n                if (type == SupportedType.DOUBLE) {\n                    callGetter(dObjTyped, type, Arrays.asList(AllJavaTypes.FIELD_STRING));\n                } else {\n                    callGetter(dObjTyped, type, Arrays.asList(AllJavaTypes.FIELD_DOUBLE));\n                }\n                fail(type + \" failed to throw.\");\n            } catch (IllegalArgumentException ignored) {\n            }\n            try {\n                // Makes sure we hit the wrong underlying type for all types.\n                if (type == SupportedType.DOUBLE) {\n                    callGetter(dObjDynamic, type, Arrays.asList(AllJavaTypes.FIELD_STRING));\n                } else {\n                    callGetter(dObjDynamic, type, Arrays.asList(AllJavaTypes.FIELD_DOUBLE));\n                }\n                fail(type + \" failed to throw.\");\n            } catch (IllegalArgumentException ignored) {\n            }\n        }\n    }\n\n    // Helper method for calling getters with different field names.\n    private static void callGetter(DynamicRealmObject target, SupportedType type, List<String> fieldNames) {\n        for (String fieldName : fieldNames) {\n            switch (type) {\n                case BOOLEAN: target.getBoolean(fieldName); break;\n                case SHORT: target.getShort(fieldName); break;\n                case INT: target.getInt(fieldName); break;\n                case LONG: target.getLong(fieldName); break;\n                case BYTE: target.getByte(fieldName); break;\n                case FLOAT: target.getFloat(fieldName); break;\n                case DOUBLE: target.getDouble(fieldName); break;\n                case STRING: target.getString(fieldName); break;\n                case BINARY: target.getBlob(fieldName); break;\n                case DATE: target.getDate(fieldName); break;\n                case DECIMAL128: target.getDecimal128(fieldName); break;\n                case OBJECT_ID: target.getObjectId(fieldName); break;\n                case UUID: target.getUUID(fieldName); break;\n                case OBJECT: target.getObject(fieldName); break;\n                case LIST:\n                case LIST_INTEGER:\n                case LIST_STRING:\n                case LIST_BOOLEAN:\n                case LIST_FLOAT:\n                case LIST_DOUBLE:\n                case LIST_BINARY:\n                case LIST_DATE:\n                case LIST_DECIMAL128:\n                case LIST_OBJECT_ID:\n                case LIST_UUID:\n                    target.getList(fieldName);\n                    break;\n                default:\n                    fail();\n            }\n        }\n    }\n\n    // Tests that all getters fail if given an invalid field name.\n    @Test\n    public void typedSetter_illegalFieldNameThrows() {\n\n        // Sets arguments.\n        String linkedField = AllJavaTypes.FIELD_OBJECT + \".\" + AllJavaTypes.FIELD_STRING;\n        List<String> arguments = Arrays.asList(null, \"foo\", AllJavaTypes.FIELD_STRING, linkedField);\n        List<String> stringArguments = Arrays.asList(null, \"foo\", AllJavaTypes.FIELD_BOOLEAN, linkedField);\n\n        // Tests all getters.\n        for (SupportedType type : SupportedType.values()) {\n            List<String> args = (type == SupportedType.STRING) ? stringArguments : arguments;\n            try {\n                callSetter(dObjTyped, type, args);\n                fail();\n            } catch (IllegalArgumentException ignored) {\n            }\n            try {\n                callSetter(dObjDynamic, type, args);\n                fail();\n            } catch (IllegalArgumentException ignored) {\n            }\n        }\n    }\n\n    @Test\n    public void typedSetter_wrongUnderlyingTypeThrows() {\n        for (SupportedType type : SupportedType.values()) {\n            realm.beginTransaction();\n            try {\n                // Makes sure we hit the wrong underlying type for all types.\n                if (type == SupportedType.STRING) {\n                    callSetter(dObjTyped, type, Arrays.asList(AllJavaTypes.FIELD_BOOLEAN));\n                } else {\n                    callSetter(dObjTyped, type, Arrays.asList(AllJavaTypes.FIELD_STRING));\n                }\n                fail();\n            } catch (IllegalArgumentException ignored) {\n            } finally {\n                realm.cancelTransaction();\n            }\n            dynamicRealm.beginTransaction();\n            try {\n                // Makes sure we hit the wrong underlying type for all types.\n                if (type == SupportedType.STRING) {\n                    callSetter(dObjDynamic, type, Arrays.asList(AllJavaTypes.FIELD_BOOLEAN));\n                } else {\n                    callSetter(dObjDynamic, type, Arrays.asList(AllJavaTypes.FIELD_STRING));\n                }\n                fail();\n            } catch (IllegalArgumentException ignored) {\n            } finally {\n                dynamicRealm.cancelTransaction();\n            }\n        }\n    }\n\n    private void callSetterOnPrimaryKey(String className, DynamicRealmObject object) {\n        switch (className) {\n            case PrimaryKeyAsByte.CLASS_NAME:\n                object.setByte(PrimaryKeyAsByte.FIELD_ID, (byte) 42);\n                break;\n            case PrimaryKeyAsShort.CLASS_NAME:\n                object.setShort(PrimaryKeyAsShort.FIELD_ID, (short) 42);\n                break;\n            case PrimaryKeyAsInteger.CLASS_NAME:\n                object.setInt(PrimaryKeyAsInteger.FIELD_ID, 42);\n                break;\n            case PrimaryKeyAsLong.CLASS_NAME:\n                object.setLong(PrimaryKeyAsLong.FIELD_ID, 42);\n                break;\n            case PrimaryKeyAsString.CLASS_NAME:\n                object.setString(PrimaryKeyAsString.FIELD_PRIMARY_KEY, \"42\");\n                break;\n            default:\n                fail();\n        }\n    }\n\n    @Test\n    public void typedSetter_changePrimaryKeyThrows() {\n        final String[] primaryKeyClasses = {PrimaryKeyAsByte.CLASS_NAME, PrimaryKeyAsShort.CLASS_NAME,\n                PrimaryKeyAsInteger.CLASS_NAME, PrimaryKeyAsLong.CLASS_NAME, PrimaryKeyAsString.CLASS_NAME};\n        for (String pkClass : primaryKeyClasses) {\n            dynamicRealm.beginTransaction();\n            DynamicRealmObject object;\n            if (pkClass.equals(PrimaryKeyAsString.CLASS_NAME)) {\n                object = dynamicRealm.createObject(pkClass, \"\");\n            } else {\n                object = dynamicRealm.createObject(pkClass, 0);\n            }\n\n            try {\n                callSetterOnPrimaryKey(pkClass, object);\n                fail();\n            } catch (IllegalArgumentException ignored) {\n            }\n            dynamicRealm.cancelTransaction();\n        }\n    }\n\n    // Helper method for calling setters with different field names.\n    private static void callSetter(DynamicRealmObject target, SupportedType type, List<String> fieldNames) {\n        for (String fieldName : fieldNames) {\n            switch (type) {\n                case BOOLEAN: target.setBoolean(fieldName, false); break;\n                case SHORT: target.setShort(fieldName, (short) 1); break;\n                case INT: target.setInt(fieldName, 1); break;\n                case LONG: target.setLong(fieldName, 1L); break;\n                case BYTE: target.setByte(fieldName, (byte) 4); break;\n                case FLOAT: target.setFloat(fieldName, 1.23f); break;\n                case DOUBLE: target.setDouble(fieldName, 1.23d); break;\n                case STRING: target.setString(fieldName, \"foo\"); break;\n                case BINARY: target.setBlob(fieldName, new byte[]{}); break;\n                case DATE: target.getDate(fieldName); break;\n                case DECIMAL128: target.getDecimal128(fieldName); break;\n                case OBJECT_ID: target.getObjectId(fieldName); break;\n                case UUID: target.getUUID(fieldName); break;\n                case OBJECT: target.setObject(fieldName, null); target.setObject(fieldName, target); break;\n                case LIST: target.setList(fieldName, new RealmList<DynamicRealmObject>()); break;\n                case LIST_INTEGER: target.setList(fieldName, new RealmList<Integer>(1)); break;\n                case LIST_STRING: target.setList(fieldName, new RealmList<String>(\"foo\")); break;\n                case LIST_BOOLEAN: target.setList(fieldName, new RealmList<Boolean>(true)); break;\n                case LIST_FLOAT: target.setList(fieldName, new RealmList<Float>(1.23F)); break;\n                case LIST_DOUBLE: target.setList(fieldName, new RealmList<Double>(1.234D)); break;\n                case LIST_BINARY: target.setList(fieldName, new RealmList<byte[]>(new byte[]{})); break;\n                case LIST_DATE: target.setList(fieldName, new RealmList<Date>(new Date())); break;\n                case LIST_DECIMAL128: target.setList(fieldName, new RealmList<>(new Decimal128(BigDecimal.ONE))); break;\n                case LIST_OBJECT_ID: target.setList(fieldName, new RealmList<>(new ObjectId(TestHelper.generateObjectIdHexString(7)))); break;\n                case LIST_UUID: target.setList(fieldName, new RealmList<>(UUID.randomUUID())); break;\n                default:\n                    fail();\n            }\n        }\n    }\n\n    // Tests all typed setters/setters.\n    @Test\n    public void typedGettersAndSetters() {\n        realm.beginTransaction();\n        AllJavaTypes obj = realm.createObject(AllJavaTypes.class, 0);\n        DynamicRealmObject dObj = new DynamicRealmObject(obj);\n        try {\n            for (SupportedType type : SupportedType.values()) {\n                switch (type) {\n                    case BOOLEAN:\n                        dObj.setBoolean(AllJavaTypes.FIELD_BOOLEAN, true);\n                        assertTrue(dObj.getBoolean(AllJavaTypes.FIELD_BOOLEAN));\n                        break;\n                    case SHORT:\n                        dObj.setShort(AllJavaTypes.FIELD_SHORT, (short) 42);\n                        assertEquals(42, dObj.getShort(AllJavaTypes.FIELD_SHORT));\n                        break;\n                    case INT:\n                        dObj.setInt(AllJavaTypes.FIELD_INT, 42);\n                        assertEquals(42, dObj.getInt(AllJavaTypes.FIELD_INT));\n                        break;\n                    case LONG:\n                        dObj.setLong(AllJavaTypes.FIELD_LONG, 42L);\n                        assertEquals(42, dObj.getLong(AllJavaTypes.FIELD_LONG));\n                        break;\n                    case BYTE:\n                        dObj.setByte(AllJavaTypes.FIELD_BYTE, (byte) 4);\n                        assertEquals(4, dObj.getByte(AllJavaTypes.FIELD_BYTE));\n                        break;\n                    case FLOAT:\n                        dObj.setFloat(AllJavaTypes.FIELD_FLOAT, 1.23f);\n                        assertEquals(1.23f, dObj.getFloat(AllJavaTypes.FIELD_FLOAT), 0f);\n                        break;\n                    case DOUBLE:\n                        dObj.setDouble(AllJavaTypes.FIELD_DOUBLE, 1.234d);\n                        assertEquals(1.234d, dObj.getDouble(AllJavaTypes.FIELD_DOUBLE), 0d);\n                        break;\n                    case STRING:\n                        dObj.setString(AllJavaTypes.FIELD_STRING, \"str\");\n                        assertEquals(\"str\", dObj.getString(AllJavaTypes.FIELD_STRING));\n                        break;\n                    case BINARY:\n                        dObj.setBlob(AllJavaTypes.FIELD_BINARY, new byte[]{1, 2, 3});\n                        assertArrayEquals(new byte[]{1, 2, 3}, dObj.getBlob(AllJavaTypes.FIELD_BINARY));\n                        break;\n                    case DATE:\n                        dObj.setDate(AllJavaTypes.FIELD_DATE, new Date(1000));\n                        assertEquals(new Date(1000), dObj.getDate(AllJavaTypes.FIELD_DATE));\n                        break;\n                    case DECIMAL128:\n                        dObj.setDecimal128(AllJavaTypes.FIELD_DECIMAL128, new Decimal128(BigDecimal.ONE));\n                        assertEquals(new Decimal128(BigDecimal.ONE), dObj.getDecimal128(AllJavaTypes.FIELD_DECIMAL128));\n                        break;\n                    case OBJECT_ID:\n                        dObj.setObjectId(AllJavaTypes.FIELD_OBJECT_ID, new ObjectId(TestHelper.generateObjectIdHexString(0)));\n                        assertEquals(new ObjectId(TestHelper.generateObjectIdHexString(0)), dObj.getObjectId(AllJavaTypes.FIELD_OBJECT_ID));\n                        break;\n                    case UUID:\n                        String uuid = UUID.randomUUID().toString();\n                        dObj.setUUID(AllJavaTypes.FIELD_UUID, UUID.fromString(uuid));\n                        assertEquals(UUID.fromString(uuid), dObj.getUUID(AllJavaTypes.FIELD_UUID));\n                        break;\n                    case OBJECT:\n                        dObj.setObject(AllJavaTypes.FIELD_OBJECT, dObj);\n                        assertEquals(dObj, dObj.getObject(AllJavaTypes.FIELD_OBJECT));\n                        break;\n                    case LIST_INTEGER:\n                        checkSetGetValueList(dObj, AllJavaTypes.FIELD_INTEGER_LIST, Integer.class, new RealmList<>(null, 1));\n                        break;\n                    case LIST_STRING:\n                        checkSetGetValueList(dObj, AllJavaTypes.FIELD_STRING_LIST, String.class, new RealmList<>(null, \"foo\"));\n                        break;\n                    case LIST_BOOLEAN:\n                        checkSetGetValueList(dObj, AllJavaTypes.FIELD_BOOLEAN_LIST, Boolean.class, new RealmList<>(null, true));\n                        break;\n                    case LIST_FLOAT:\n                        checkSetGetValueList(dObj, AllJavaTypes.FIELD_FLOAT_LIST, Float.class, new RealmList<>(null, 1.23F));\n                        break;\n                    case LIST_DOUBLE:\n                        checkSetGetValueList(dObj, AllJavaTypes.FIELD_DOUBLE_LIST, Double.class, new RealmList<>(null, 1.234D));\n                        break;\n                    case LIST_BINARY:\n                        checkSetGetValueList(dObj, AllJavaTypes.FIELD_BINARY_LIST, byte[].class, new RealmList<>(null, new byte[] {1, 2, 3}));\n                        break;\n                    case LIST_DATE:\n                        checkSetGetValueList(dObj, AllJavaTypes.FIELD_DATE_LIST, Date.class, new RealmList<>(null, new Date(1000)));\n                        break;\n                    case LIST_DECIMAL128:\n                        checkSetGetValueList(dObj, AllJavaTypes.FIELD_DECIMAL128_LIST, Decimal128.class, new RealmList<>(null, new Decimal128(BigDecimal.ONE)));\n                        break;\n                    case LIST_OBJECT_ID:\n                        checkSetGetValueList(dObj, AllJavaTypes.FIELD_OBJECT_ID_LIST, ObjectId.class, new RealmList<>(null, new ObjectId(TestHelper.generateObjectIdHexString(0))));\n                        break;\n                    case LIST_UUID:\n                        checkSetGetValueList(dObj, AllJavaTypes.FIELD_UUID_LIST, UUID.class, new RealmList<>(null, UUID.randomUUID()));\n                        break;\n                    case LIST:\n                        // Ignores. See testGetList/testSetList.\n                        break;\n                    default:\n                        fail();\n                }\n            }\n        } finally {\n            realm.cancelTransaction();\n        }\n    }\n\n    private <E> void checkSetGetValueList(DynamicRealmObject obj, String fieldName, Class<E> primitiveType, RealmList<E> list) {\n        obj.set(fieldName, list);\n        assertArrayEquals(list.toArray(), obj.getList(fieldName, primitiveType).toArray());\n    }\n\n    @Test\n    public void setter_null() {\n        realm.beginTransaction();\n        NullTypes obj = realm.createObject(NullTypes.class, 0);\n        DynamicRealmObject dObj = new DynamicRealmObject(obj);\n        try {\n            for (SupportedType type : SupportedType.values()) {\n                switch (type) {\n                    case OBJECT:\n                        NullTypes childObj = new NullTypes();\n                        childObj.setId(1);\n                        DynamicRealmObject dynamicChildObject = new DynamicRealmObject(realm.copyToRealm(childObj));\n                        dObj.setObject(NullTypes.FIELD_OBJECT_NULL, dynamicChildObject);\n                        assertNotNull(dObj.getObject(NullTypes.FIELD_OBJECT_NULL));\n                        dObj.setNull(NullTypes.FIELD_OBJECT_NULL);\n                        assertNull(dObj.getObject(NullTypes.FIELD_OBJECT_NULL));\n                        break;\n                    case LIST:\n                        try {\n                            dObj.setNull(NullTypes.FIELD_LIST_NULL);\n                            fail();\n                        } catch (IllegalArgumentException ignored) {\n                        }\n                        break;\n                    case LIST_INTEGER:\n                        try {\n                            dObj.setNull(NullTypes.FIELD_INTEGER_LIST_NULL);\n                            fail();\n                        } catch (IllegalArgumentException ignored) {\n                        }\n                        break;\n                    case LIST_STRING:\n                        try {\n                            dObj.setNull(NullTypes.FIELD_STRING_LIST_NULL);\n                            fail();\n                        } catch (IllegalArgumentException ignored) {\n                        }\n                        break;\n                    case LIST_BOOLEAN:\n                        try {\n                            dObj.setNull(NullTypes.FIELD_BOOLEAN_LIST_NULL);\n                            fail();\n                        } catch (IllegalArgumentException ignored) {\n                        }\n                        break;\n                    case LIST_FLOAT:\n                        try {\n                            dObj.setNull(NullTypes.FIELD_FLOAT_LIST_NULL);\n                            fail();\n                        } catch (IllegalArgumentException ignored) {\n                        }\n                        break;\n                    case LIST_DOUBLE:\n                        try {\n                            dObj.setNull(NullTypes.FIELD_DOUBLE_LIST_NULL);\n                            fail();\n                        } catch (IllegalArgumentException ignored) {\n                        }\n                        break;\n                    case LIST_BINARY:\n                        try {\n                            dObj.setNull(NullTypes.FIELD_BINARY_LIST_NULL);\n                            fail();\n                        } catch (IllegalArgumentException ignored) {\n                        }\n                        break;\n                    case LIST_DATE:\n                        try {\n                            dObj.setNull(NullTypes.FIELD_DATE_LIST_NULL);\n                            fail();\n                        } catch (IllegalArgumentException ignored) {\n                        }\n                        break;\n                    case LIST_DECIMAL128:\n                        try {\n                            dObj.setNull(NullTypes.FIELD_DECIMAL128_LIST_NULL);\n                            fail();\n                        } catch (IllegalArgumentException ignored) {\n                        }\n                        break;\n                    case LIST_OBJECT_ID:\n                        try {\n                            dObj.setNull(NullTypes.FIELD_OBJECT_ID_LIST_NULL);\n                            fail();\n                        } catch (IllegalArgumentException ignored) {\n                        }\n                        break;\n                    case LIST_UUID:\n                        try {\n                            dObj.setNull(NullTypes.FIELD_UUID_LIST_NULL);\n                            fail();\n                        } catch (IllegalArgumentException ignored) {\n                        }\n                        break;\n                    case BOOLEAN:\n                        dObj.setNull(NullTypes.FIELD_BOOLEAN_NULL);\n                        assertTrue(dObj.isNull(NullTypes.FIELD_BOOLEAN_NULL));\n                        break;\n                    case BYTE:\n                        dObj.setNull(NullTypes.FIELD_BYTE_NULL);\n                        assertTrue(dObj.isNull(NullTypes.FIELD_BYTE_NULL));\n                        break;\n                    case SHORT:\n                        dObj.setNull(NullTypes.FIELD_SHORT_NULL);\n                        assertTrue(dObj.isNull(NullTypes.FIELD_SHORT_NULL));\n                        break;\n                    case INT:\n                        dObj.setNull(NullTypes.FIELD_INTEGER_NULL);\n                        assertTrue(dObj.isNull(NullTypes.FIELD_INTEGER_NULL));\n                        break;\n                    case LONG:\n                        dObj.setNull(NullTypes.FIELD_LONG_NULL);\n                        assertTrue(dObj.isNull(NullTypes.FIELD_LONG_NULL));\n                        break;\n                    case FLOAT:\n                        dObj.setNull(NullTypes.FIELD_FLOAT_NULL);\n                        assertTrue(dObj.isNull(NullTypes.FIELD_FLOAT_NULL));\n                        break;\n                    case DOUBLE:\n                        dObj.setNull(NullTypes.FIELD_DOUBLE_NULL);\n                        assertTrue(dObj.isNull(NullTypes.FIELD_DOUBLE_NULL));\n                        break;\n                    case STRING:\n                        dObj.setNull(NullTypes.FIELD_STRING_NULL);\n                        assertTrue(dObj.isNull(NullTypes.FIELD_STRING_NULL));\n                        break;\n                    case BINARY:\n                        dObj.setNull(NullTypes.FIELD_BYTES_NULL);\n                        assertTrue(dObj.isNull(NullTypes.FIELD_BYTES_NULL));\n                        break;\n                    case DATE:\n                        dObj.setNull(NullTypes.FIELD_DATE_NULL);\n                        assertTrue(dObj.isNull(NullTypes.FIELD_DATE_NULL));\n                        break;\n                    case DECIMAL128:\n                        dObj.setNull(NullTypes.FIELD_DECIMAL128_NULL);\n                        assertTrue(dObj.isNull(NullTypes.FIELD_DECIMAL128_NULL));\n                        break;\n                    case OBJECT_ID:\n                        dObj.setNull(NullTypes.FIELD_OBJECT_ID_NULL);\n                        assertTrue(dObj.isNull(NullTypes.FIELD_OBJECT_ID_NULL));\n                        break;\n                    case UUID:\n                        dObj.setNull(NullTypes.FIELD_UUID_NULL);\n                        assertTrue(dObj.isNull(NullTypes.FIELD_UUID_NULL));\n                        break;\n                    default:\n                        fail(\"Unknown type: \" + type);\n                }\n            }\n        } finally {\n            realm.cancelTransaction();\n        }\n    }\n\n    @Test\n    public void setter_nullOnRequiredFieldsThrows() {\n        realm.beginTransaction();\n        NullTypes obj = realm.createObject(NullTypes.class, 0);\n        DynamicRealmObject dObj = new DynamicRealmObject(obj);\n        try {\n            for (SupportedType type : SupportedType.values()) {\n                String fieldName = null;\n                try {\n                    switch (type) {\n                        case OBJECT: continue; // Ignore\n                        case LIST: fieldName = NullTypes.FIELD_LIST_NULL; break;\n                        case LIST_INTEGER: fieldName = NullTypes.FIELD_INTEGER_LIST_NULL; break;\n                        case LIST_STRING: fieldName = NullTypes.FIELD_STRING_LIST_NULL; break;\n                        case LIST_BOOLEAN: fieldName = NullTypes.FIELD_BOOLEAN_LIST_NULL; break;\n                        case LIST_FLOAT: fieldName = NullTypes.FIELD_FLOAT_LIST_NULL; break;\n                        case LIST_DOUBLE: fieldName = NullTypes.FIELD_DOUBLE_LIST_NULL; break;\n                        case LIST_BINARY: fieldName = NullTypes.FIELD_BINARY_LIST_NULL; break;\n                        case LIST_DATE: fieldName = NullTypes.FIELD_DATE_LIST_NULL; break;\n                        case LIST_DECIMAL128: fieldName = NullTypes.FIELD_DECIMAL128_LIST_NULL; break;\n                        case LIST_OBJECT_ID: fieldName = NullTypes.FIELD_OBJECT_ID_LIST_NULL; break;\n                        case LIST_UUID: fieldName = NullTypes.FIELD_UUID_LIST_NULL; break;\n                        case BOOLEAN: fieldName = NullTypes.FIELD_BOOLEAN_NOT_NULL; break;\n                        case BYTE: fieldName = NullTypes.FIELD_BYTE_NOT_NULL; break;\n                        case SHORT: fieldName = NullTypes.FIELD_SHORT_NOT_NULL; break;\n                        case INT: fieldName = NullTypes.FIELD_INTEGER_NOT_NULL; break;\n                        case LONG: fieldName = NullTypes.FIELD_LONG_NOT_NULL; break;\n                        case FLOAT: fieldName = NullTypes.FIELD_FLOAT_NOT_NULL; break;\n                        case DOUBLE: fieldName = NullTypes.FIELD_DOUBLE_NOT_NULL; break;\n                        case STRING: fieldName = NullTypes.FIELD_STRING_NOT_NULL; break;\n                        case BINARY: fieldName = NullTypes.FIELD_BYTES_NOT_NULL; break;\n                        case DATE: fieldName = NullTypes.FIELD_DATE_NOT_NULL; break;\n                        case DECIMAL128: fieldName = NullTypes.FIELD_DECIMAL128_NOT_NULL; break;\n                        case OBJECT_ID: fieldName = NullTypes.FIELD_OBJECT_ID_NOT_NULL; break;\n                        case UUID: fieldName = NullTypes.FIELD_UUID_NOT_NULL; break;\n                        default:\n                            fail(\"Unknown type: \" + type);\n                    }\n\n                    dObj.setNull(fieldName);\n                    fail(\"Setting value to null should throw: \" + type);\n                } catch (IllegalArgumentException ignored) {\n                    assertTrue(ignored.getMessage().contains(fieldName));\n                }\n            }\n        } finally {\n            realm.cancelTransaction();\n        }\n    }\n\n    // Tests types where you can set null using the typed setter instead of using setNull().\n    @Test\n    public void typedSetter_null() {\n        realm.beginTransaction();\n        NullTypes obj = realm.createObject(NullTypes.class, 0);\n        DynamicRealmObject dObj = new DynamicRealmObject(obj);\n        try {\n            for (SupportedType type : SupportedType.values()) {\n                switch (type) {\n                    case OBJECT:\n                        dObj.setObject(NullTypes.FIELD_OBJECT_NULL, null);\n                        assertNull(dObj.getObject(NullTypes.FIELD_OBJECT_NULL));\n                        break;\n                    case LIST:\n                        try {\n                            dObj.setList(NullTypes.FIELD_LIST_NULL, null);\n                            fail();\n                        } catch (IllegalArgumentException ignored) {\n                        }\n                        break;\n                    case LIST_INTEGER:\n                        try {\n                            dObj.setList(NullTypes.FIELD_INTEGER_LIST_NULL, null);\n                            fail();\n                        } catch (IllegalArgumentException ignored) {\n                        }\n                        break;\n                    case LIST_STRING:\n                        try {\n                            dObj.setList(NullTypes.FIELD_STRING_LIST_NULL, null);\n                            fail();\n                        } catch (IllegalArgumentException ignored) {\n                        }\n                        break;\n                    case LIST_BOOLEAN:\n                        try {\n                            dObj.setList(NullTypes.FIELD_BOOLEAN_LIST_NULL, null);\n                            fail();\n                        } catch (IllegalArgumentException ignored) {\n                        }\n                        break;\n                    case LIST_FLOAT:\n                        try {\n                            dObj.setList(NullTypes.FIELD_FLOAT_LIST_NULL, null);\n                            fail();\n                        } catch (IllegalArgumentException ignored) {\n                        }\n                        break;\n                    case LIST_DOUBLE:\n                        try {\n                            dObj.setList(NullTypes.FIELD_DOUBLE_LIST_NULL, null);\n                            fail();\n                        } catch (IllegalArgumentException ignored) {\n                        }\n                        break;\n                    case LIST_BINARY:\n                        try {\n                            dObj.setList(NullTypes.FIELD_BINARY_LIST_NULL, null);\n                            fail();\n                        } catch (IllegalArgumentException ignored) {\n                        }\n                        break;\n                    case LIST_DATE:\n                        try {\n                            dObj.setList(NullTypes.FIELD_DATE_LIST_NULL, null);\n                            fail();\n                        } catch (IllegalArgumentException ignored) {\n                        }\n                        break;\n                    case DATE:\n                        dObj.setDate(NullTypes.FIELD_DATE_NULL, null);\n                        assertNull(dObj.getDate(NullTypes.FIELD_DATE_NULL));\n                        break;\n                    case STRING:\n                        dObj.setString(NullTypes.FIELD_STRING_NULL, null);\n                        assertNull(dObj.getString(NullTypes.FIELD_STRING_NULL));\n                        break;\n                    case BINARY:\n                        dObj.setBlob(NullTypes.FIELD_BYTES_NULL, null);\n                        assertNull(dObj.getBlob(NullTypes.FIELD_BYTES_NULL));\n                        break;\n                    case BOOLEAN:\n                    case SHORT:\n                    case INT:\n                    case LONG:\n                    case FLOAT:\n                    case DOUBLE:\n                    default:\n                        // The typed setters for these cannot accept null as input.\n                }\n            }\n        } finally {\n            realm.cancelTransaction();\n        }\n    }\n\n    @Test\n    public void setNull_changePrimaryKeyThrows() {\n        final String[] primaryKeyClasses = {PrimaryKeyAsBoxedByte.CLASS_NAME, PrimaryKeyAsBoxedShort.CLASS_NAME,\n                PrimaryKeyAsBoxedInteger.CLASS_NAME, PrimaryKeyAsBoxedLong.CLASS_NAME, PrimaryKeyAsString.CLASS_NAME};\n        for (String pkClass : primaryKeyClasses) {\n            dynamicRealm.beginTransaction();\n            DynamicRealmObject object;\n            boolean isStringPK = pkClass.equals(PrimaryKeyAsString.CLASS_NAME);\n            if (isStringPK) {\n                object = dynamicRealm.createObject(pkClass, \"\");\n            } else {\n                object = dynamicRealm.createObject(pkClass, 0);\n            }\n\n            try {\n                object.setNull(isStringPK ? PrimaryKeyAsString.FIELD_PRIMARY_KEY : \"id\");\n                fail();\n            } catch (IllegalArgumentException ignored) {\n            }\n            dynamicRealm.cancelTransaction();\n        }\n    }\n\n    @Test\n    public void setObject_differentType() {\n        realm.beginTransaction();\n        DynamicRealmObject dog = new DynamicRealmObject(realm.createObject(Dog.class));\n        DynamicRealmObject owner = new DynamicRealmObject(realm.createObject(Owner.class));\n        owner.setString(\"name\", \"John\");\n        dog.setObject(\"owner\", owner);\n        realm.commitTransaction();\n\n        owner = dog.getObject(\"owner\");\n        assertNotNull(owner);\n        assertEquals(\"John\", owner.getString(\"name\"));\n    }\n\n    @Test\n    public void setObject_wrongTypeThrows() {\n        realm.beginTransaction();\n        AllJavaTypes obj = realm.createObject(AllJavaTypes.class, 0);\n        Dog otherObj = realm.createObject(Dog.class);\n        DynamicRealmObject dynamicObj = new DynamicRealmObject(obj);\n        DynamicRealmObject dynamicWrongType = new DynamicRealmObject(otherObj);\n        thrown.expect(IllegalArgumentException.class);\n        dynamicObj.setObject(AllJavaTypes.FIELD_OBJECT, dynamicWrongType);\n    }\n\n    @Test\n    public void setObject_objectBelongToTypedRealmThrows() {\n        dynamicRealm.beginTransaction();\n\n        thrown.expect(IllegalArgumentException.class);\n        thrown.expectMessage(\"Cannot add an object from another Realm instance.\");\n        dynamicRealm.where(AllJavaTypes.CLASS_NAME).findFirst().setObject(AllJavaTypes.FIELD_OBJECT, dObjTyped);\n\n        dynamicRealm.cancelTransaction();\n    }\n\n    @Test\n    public void setObject_objectBelongToDiffThreadRealmThrows() {\n        final CountDownLatch finishedLatch = new CountDownLatch(1);\n\n        new Thread(new Runnable() {\n            @Override\n            public void run() {\n                DynamicRealm dynamicRealm = DynamicRealm.getInstance(realm.getConfiguration());\n                dynamicRealm.beginTransaction();\n\n                try {\n                    // ExpectedException doesn't work in another thread.\n                    dynamicRealm.where(AllJavaTypes.CLASS_NAME).findFirst()\n                            .setObject(AllJavaTypes.FIELD_OBJECT, dObjDynamic);\n                    fail();\n                } catch (IllegalArgumentException expected) {\n                    assertEquals(\"Cannot add an object from another Realm instance.\", expected.getMessage());\n                }\n\n                dynamicRealm.cancelTransaction();\n                dynamicRealm.close();\n                finishedLatch.countDown();\n            }\n        }).start();\n        TestHelper.awaitOrFail(finishedLatch);\n    }\n\n    @Test\n    public void setList_listWithDynamicRealmObject() {\n        DynamicRealm dynamicRealm = DynamicRealm.getInstance(realm.configuration);\n        dynamicRealm.beginTransaction();\n\n        DynamicRealmObject allTypes = dynamicRealm.createObject(AllTypes.CLASS_NAME);\n        allTypes.setString(AllTypes.FIELD_STRING, \"bender\");\n\n        DynamicRealmObject dog = dynamicRealm.createObject(Dog.CLASS_NAME);\n        dog.setString(Dog.FIELD_NAME, \"nibbler\");\n\n        RealmList<DynamicRealmObject> list = new RealmList<DynamicRealmObject>();\n        list.add(dog);\n        allTypes.setList(AllTypes.FIELD_REALMLIST, list);\n\n        dynamicRealm.commitTransaction();\n\n        allTypes = dynamicRealm.where(AllTypes.CLASS_NAME)\n                .equalTo(AllTypes.FIELD_STRING, \"bender\")\n                .findFirst();\n        assertEquals(\"nibbler\", allTypes.getList(AllTypes.FIELD_REALMLIST).first().get(Dog.FIELD_NAME));\n        dynamicRealm.close();\n    }\n\n    @Test\n    public void setList_managedRealmList() {\n        dynamicRealm.executeTransaction(new DynamicRealm.Transaction() {\n            @Override\n            public void execute(DynamicRealm realm) {\n                realm.deleteAll();\n\n                DynamicRealmObject allTypes = realm.createObject(AllTypes.CLASS_NAME);\n                allTypes.setString(AllTypes.FIELD_STRING, \"bender\");\n\n                DynamicRealmObject anotherAllTypes;\n                {\n                    anotherAllTypes = realm.createObject(AllTypes.CLASS_NAME);\n                    anotherAllTypes.setString(AllTypes.FIELD_STRING, \"bender2\");\n                    DynamicRealmObject dog = realm.createObject(Dog.CLASS_NAME);\n                    dog.setString(Dog.FIELD_NAME, \"nibbler\");\n                    anotherAllTypes.getList(AllTypes.FIELD_REALMLIST).add(dog);\n                }\n\n                // set managed RealmList\n                allTypes.setList(AllTypes.FIELD_REALMLIST, anotherAllTypes.getList(AllTypes.FIELD_REALMLIST));\n            }\n        });\n\n        DynamicRealmObject allTypes = dynamicRealm.where(AllTypes.CLASS_NAME)\n                .equalTo(AllTypes.FIELD_STRING, \"bender\")\n                .findFirst();\n        assertEquals(1, allTypes.getList(AllTypes.FIELD_REALMLIST).size());\n        assertEquals(\"nibbler\", allTypes.getList(AllTypes.FIELD_REALMLIST).first().get(Dog.FIELD_NAME));\n\n        // Check if allTypes and anotherAllTypes share the same Dog object.\n        dynamicRealm.executeTransaction(new DynamicRealm.Transaction() {\n            @Override\n            public void execute(DynamicRealm realm) {\n                DynamicRealmObject anotherAllTypes = dynamicRealm.where(AllTypes.CLASS_NAME)\n                        .equalTo(AllTypes.FIELD_STRING, \"bender2\")\n                        .findFirst();\n                anotherAllTypes.getList(AllTypes.FIELD_REALMLIST).first()\n                        .setString(Dog.FIELD_NAME, \"nibbler_modified\");\n            }\n        });\n\n        assertEquals(\"nibbler_modified\", allTypes.getList(AllTypes.FIELD_REALMLIST).first().get(Dog.FIELD_NAME));\n    }\n\n    @Test\n    public void setList_elementBelongToTypedRealmThrows() {\n        RealmList<DynamicRealmObject> list = new RealmList<DynamicRealmObject>();\n        list.add(dObjTyped);\n\n        dynamicRealm.beginTransaction();\n\n        thrown.expect(IllegalArgumentException.class);\n        thrown.expectMessage(\"Each element in 'list' must belong to the same Realm instance.\");\n        dynamicRealm.where(AllJavaTypes.CLASS_NAME).findFirst().setList(AllJavaTypes.FIELD_LIST, list);\n\n        dynamicRealm.cancelTransaction();\n    }\n\n    @Test\n    public void setList_elementBelongToDiffThreadRealmThrows() {\n        final CountDownLatch finishedLatch = new CountDownLatch(1);\n        new Thread(new Runnable() {\n            @Override\n            public void run() {\n                DynamicRealm dynamicRealm = DynamicRealm.getInstance(realm.getConfiguration());\n                RealmList<DynamicRealmObject> list = new RealmList<DynamicRealmObject>();\n                list.add(dObjDynamic);\n\n                dynamicRealm.beginTransaction();\n\n                try {\n                    // ExpectedException doesn't work in another thread.\n                    dynamicRealm.where(AllJavaTypes.CLASS_NAME).findFirst().setList(AllJavaTypes.FIELD_LIST, list);\n                    fail();\n                } catch (IllegalArgumentException expected) {\n                    assertEquals(\"Each element in 'list' must belong to the same Realm instance.\", expected.getMessage());\n                }\n\n                dynamicRealm.cancelTransaction();\n                dynamicRealm.close();\n                finishedLatch.countDown();\n            }\n        }).start();\n        TestHelper.awaitOrFail(finishedLatch);\n    }\n\n    @Test\n    public void setList_wrongTypeThrows() {\n        realm.beginTransaction();\n        AllTypes wrongObj = realm.createObject(AllTypes.class);\n        DynamicRealmObject wrongDynamicObject = new DynamicRealmObject(wrongObj);\n        RealmList<DynamicRealmObject> wrongDynamicList = wrongDynamicObject.getList(AllTypes.FIELD_REALMLIST);\n        thrown.expect(IllegalArgumentException.class);\n        dObjTyped.setList(AllJavaTypes.FIELD_LIST, wrongDynamicList);\n    }\n\n    @Test\n    public void setList_javaModelClassesThrowProperErrorMessage() {\n        dynamicRealm.beginTransaction();\n        try {\n            dObjDynamic.setList(AllJavaTypes.FIELD_LIST, new RealmList<>(typedObj));\n            fail();\n        } catch (IllegalArgumentException e) {\n            assertTrue(e.getMessage().contains(\"RealmList must contain `DynamicRealmObject's, not Java model classes.\"));\n        }\n    }\n\n    @Test\n    public void setList_objectsOwnList() {\n        dynamicRealm.beginTransaction();\n\n        // Test model classes\n        int originalSize = dObjDynamic.getList(AllJavaTypes.FIELD_LIST).size();\n        dObjDynamic.setList(AllJavaTypes.FIELD_LIST, dObjDynamic.getList(AllJavaTypes.FIELD_LIST));\n        assertEquals(originalSize, dObjDynamic.getList(AllJavaTypes.FIELD_LIST).size());\n\n        // Smoke test value lists\n        originalSize = dObjDynamic.getList(AllJavaTypes.FIELD_STRING_LIST, String.class).size();\n        dObjDynamic.setList(AllJavaTypes.FIELD_STRING_LIST, dObjDynamic.getList(AllJavaTypes.FIELD_STRING_LIST, String.class));\n        assertEquals(originalSize, dObjDynamic.getList(AllJavaTypes.FIELD_STRING_LIST, String.class).size());\n    }\n\n    @Test\n    public void untypedSetter_listWrongTypeThrows() {\n        realm.beginTransaction();\n        AllTypes wrongObj = realm.createObject(AllTypes.class);\n        thrown.expect(IllegalArgumentException.class);\n        dObjTyped.set(AllJavaTypes.FIELD_LIST, wrongObj.getColumnRealmList());\n    }\n\n    @Test\n    public void untypedSetter_listRealmAnyTypesThrows() {\n        realm.beginTransaction();\n        AllJavaTypes obj1 = realm.createObject(AllJavaTypes.class, 2);\n        CyclicType obj2 = realm.createObject(CyclicType.class);\n\n        RealmList<DynamicRealmObject> list = new RealmList<DynamicRealmObject>();\n        list.add(new DynamicRealmObject(obj1));\n        list.add(new DynamicRealmObject(obj2));\n        thrown.expect(IllegalArgumentException.class);\n        dObjTyped.set(AllJavaTypes.FIELD_LIST, list);\n    }\n\n    // List is not a simple getter, tests separately.\n    @Test\n    public void getList() {\n        realm.beginTransaction();\n        AllTypes obj = realm.createObject(AllTypes.class);\n        Dog dog = realm.createObject(Dog.class);\n        dog.setName(\"fido\");\n        obj.getColumnRealmList().add(dog);\n        realm.commitTransaction();\n\n        DynamicRealmObject dynamicAllTypes = new DynamicRealmObject(obj);\n        RealmList<DynamicRealmObject> list = dynamicAllTypes.getList(AllTypes.FIELD_REALMLIST);\n        DynamicRealmObject listObject = list.get(0);\n\n        assertEquals(1, list.size());\n        assertEquals(Dog.CLASS_NAME, listObject.getType());\n        assertEquals(\"fido\", listObject.getString(Dog.FIELD_NAME));\n    }\n\n\n    @Test\n    public void untypedGetterSetter() {\n        realm.beginTransaction();\n        AllJavaTypes obj = realm.createObject(AllJavaTypes.class, 0);\n        DynamicRealmObject dObj = new DynamicRealmObject(obj);\n        try {\n            for (SupportedType type : SupportedType.values()) {\n                switch (type) {\n                    case BOOLEAN:\n                        dObj.set(AllJavaTypes.FIELD_BOOLEAN, true);\n                        assertTrue((Boolean) dObj.get(AllJavaTypes.FIELD_BOOLEAN));\n                        break;\n                    case SHORT:\n                        dObj.set(AllJavaTypes.FIELD_SHORT, (short) 42);\n                        assertEquals(Long.parseLong(\"42\"), dObj.<Long> get(AllJavaTypes.FIELD_SHORT).longValue());\n                        break;\n                    case INT:\n                        dObj.set(AllJavaTypes.FIELD_INT, 42);\n                        assertEquals(Long.parseLong(\"42\"), dObj.<Long> get(AllJavaTypes.FIELD_INT).longValue());\n                        break;\n                    case LONG:\n                        dObj.set(AllJavaTypes.FIELD_LONG, 42L);\n                        assertEquals(Long.parseLong(\"42\"), dObj.<Long> get(AllJavaTypes.FIELD_LONG).longValue());\n                        break;\n                    case BYTE:\n                        dObj.set(AllJavaTypes.FIELD_BYTE, (byte) 4);\n                        assertEquals(Long.parseLong(\"4\"), dObj.<Long> get(AllJavaTypes.FIELD_BYTE).longValue());\n                        break;\n                    case FLOAT:\n                        dObj.set(AllJavaTypes.FIELD_FLOAT, 1.23f);\n                        assertEquals(Float.parseFloat(\"1.23\"), dObj.<Float> get(AllJavaTypes.FIELD_FLOAT), Float.MIN_NORMAL);\n                        break;\n                    case DOUBLE:\n                        dObj.set(AllJavaTypes.FIELD_DOUBLE, 1.234d);\n                        assertEquals(Double.parseDouble(\"1.234\"), dObj.<Double>get(AllJavaTypes.FIELD_DOUBLE), Double.MIN_NORMAL);\n                        break;\n                    case STRING:\n                        dObj.set(AllJavaTypes.FIELD_STRING, \"str\");\n                        assertEquals(\"str\", dObj.get(AllJavaTypes.FIELD_STRING));\n                        break;\n                    case BINARY:\n                        dObj.set(AllJavaTypes.FIELD_BINARY, new byte[]{1, 2, 3});\n                        assertArrayEquals(new byte[]{1, 2, 3}, (byte[]) dObj.get(AllJavaTypes.FIELD_BINARY));\n                        break;\n                    case DATE:\n                        dObj.set(AllJavaTypes.FIELD_DATE, new Date(1000));\n                        assertEquals(new Date(1000), dObj.get(AllJavaTypes.FIELD_DATE));\n                        break;\n                    case DECIMAL128:\n                        dObj.set(AllJavaTypes.FIELD_DECIMAL128, new Decimal128(BigDecimal.ONE));\n                        assertEquals(new Decimal128(BigDecimal.ONE), dObj.get(AllJavaTypes.FIELD_DECIMAL128));\n                        break;\n                    case OBJECT_ID:\n                        dObj.set(AllJavaTypes.FIELD_OBJECT_ID, new ObjectId(TestHelper.generateObjectIdHexString(7)));\n                        assertEquals(new ObjectId(TestHelper.generateObjectIdHexString(7)), dObj.get(AllJavaTypes.FIELD_OBJECT_ID));\n                        break;\n                    case UUID:\n                        String uuid = UUID.randomUUID().toString();\n                        dObj.set(AllJavaTypes.FIELD_UUID, UUID.fromString(uuid));\n                        assertEquals(UUID.fromString(uuid), dObj.get(AllJavaTypes.FIELD_UUID));\n                        break;\n                    case OBJECT:\n                        dObj.set(AllJavaTypes.FIELD_OBJECT, dObj);\n                        assertEquals(dObj, dObj.get(AllJavaTypes.FIELD_OBJECT));\n                        break;\n                    case LIST: {\n                        RealmList<DynamicRealmObject> newList = new RealmList<DynamicRealmObject>();\n                        newList.add(dObj);\n                        dObj.set(AllJavaTypes.FIELD_LIST, newList);\n                        RealmList<DynamicRealmObject> list = dObj.getList(AllJavaTypes.FIELD_LIST);\n                        assertEquals(1, list.size());\n                        assertEquals(dObj, list.get(0));\n                        break;\n                    }\n                    case LIST_INTEGER: {\n                        RealmList<Integer> newList = new RealmList<>(null, 1);\n                        dObj.set(AllJavaTypes.FIELD_INTEGER_LIST, newList);\n                        RealmList<Integer> list = dObj.getList(AllJavaTypes.FIELD_INTEGER_LIST, Integer.class);\n                        assertEquals(2, list.size());\n                        assertArrayEquals(newList.toArray(), list.toArray());\n                        break;\n                    }\n                    case LIST_STRING: {\n                        RealmList<String> newList = new RealmList<>(null, \"Foo\");\n                        dObj.set(AllJavaTypes.FIELD_STRING_LIST, newList);\n                        RealmList<String> list = dObj.getList(AllJavaTypes.FIELD_STRING_LIST, String.class);\n                        assertEquals(2, list.size());\n                        assertArrayEquals(newList.toArray(), list.toArray());\n                        break;\n                    }\n                    case LIST_BOOLEAN: {\n                        RealmList<Boolean> newList = new RealmList<>(null, true);\n                        dObj.set(AllJavaTypes.FIELD_BOOLEAN_LIST, newList);\n                        RealmList<Boolean> list = dObj.getList(AllJavaTypes.FIELD_BOOLEAN_LIST, Boolean.class);\n                        assertEquals(2, list.size());\n                        assertArrayEquals(newList.toArray(), list.toArray());\n                        break;\n                    }\n                    case LIST_FLOAT: {\n                        RealmList<Float> newList = new RealmList<>(null, 1.23F);\n                        dObj.set(AllJavaTypes.FIELD_FLOAT_LIST, newList);\n                        RealmList<Float> list = dObj.getList(AllJavaTypes.FIELD_FLOAT_LIST, Float.class);\n                        assertEquals(2, list.size());\n                        assertArrayEquals(newList.toArray(), list.toArray());\n                        break;\n                    }\n                    case LIST_DOUBLE: {\n                        RealmList<Double> newList = new RealmList<>(null, 1.24D);\n                        dObj.set(AllJavaTypes.FIELD_DOUBLE_LIST, newList);\n                        RealmList<Double> list = dObj.getList(AllJavaTypes.FIELD_DOUBLE_LIST, Double.class);\n                        assertEquals(2, list.size());\n                        assertArrayEquals(newList.toArray(), list.toArray());\n                        break;\n                    }\n                    case LIST_BINARY: {\n                        RealmList<byte[]> newList = new RealmList<>(null, new byte[] {1, 2, 3});\n                        dObj.set(AllJavaTypes.FIELD_BINARY_LIST, newList);\n                        RealmList<byte[]> list = dObj.getList(AllJavaTypes.FIELD_BINARY_LIST, byte[].class);\n                        assertEquals(2, list.size());\n                        assertArrayEquals(newList.toArray(), list.toArray());\n                        break;\n                    }\n                    case LIST_DATE: {\n                        RealmList<Date> newList = new RealmList<>(null, new Date(1000));\n                        dObj.set(AllJavaTypes.FIELD_DATE_LIST, newList);\n                        RealmList<Date> list = dObj.getList(AllJavaTypes.FIELD_DATE_LIST, Date.class);\n                        assertEquals(2, list.size());\n                        assertArrayEquals(newList.toArray(), list.toArray());\n                        break;\n                    }\n                    case LIST_DECIMAL128: {\n                        RealmList<Decimal128> newList = new RealmList<>(null, new Decimal128(BigDecimal.ONE));\n                        dObj.set(AllJavaTypes.FIELD_DECIMAL128_LIST, newList);\n                        RealmList<Decimal128> list = dObj.getList(AllJavaTypes.FIELD_DECIMAL128_LIST, Decimal128.class);\n                        assertEquals(2, list.size());\n                        assertArrayEquals(newList.toArray(), list.toArray());\n                        break;\n                    }\n                    case LIST_OBJECT_ID: {\n                        RealmList<ObjectId> newList = new RealmList<>(null, new ObjectId(TestHelper.generateObjectIdHexString(0)));\n                        dObj.set(AllJavaTypes.FIELD_OBJECT_ID_LIST, newList);\n                        RealmList<ObjectId> list = dObj.getList(AllJavaTypes.FIELD_OBJECT_ID_LIST, ObjectId.class);\n                        assertEquals(2, list.size());\n                        assertArrayEquals(newList.toArray(), list.toArray());\n                        break;\n                    }\n                    case LIST_UUID: {\n                        RealmList<UUID> newList = new RealmList<>(null, UUID.randomUUID());\n                        dObj.set(AllJavaTypes.FIELD_UUID_LIST, newList);\n                        RealmList<UUID> list = dObj.getList(AllJavaTypes.FIELD_UUID_LIST, UUID.class);\n                        assertEquals(2, list.size());\n                        assertArrayEquals(newList.toArray(), list.toArray());\n                        break;\n                    }\n                    default:\n                        fail();\n                }\n            }\n        } finally {\n            realm.cancelTransaction();\n        }\n    }\n\n    @Test\n    public void untypedSetter_usingStringConversion() {\n        realm.beginTransaction();\n        AllJavaTypes obj = realm.createObject(AllJavaTypes.class, 0);\n        DynamicRealmObject dObj = new DynamicRealmObject(obj);\n        try {\n            for (SupportedType type : SupportedType.values()) {\n                switch (type) {\n                    case BOOLEAN:\n                        dObj.set(AllJavaTypes.FIELD_BOOLEAN, \"true\");\n                        assertTrue(dObj.getBoolean(AllJavaTypes.FIELD_BOOLEAN));\n                        break;\n                    case SHORT:\n                        dObj.set(AllJavaTypes.FIELD_SHORT, \"42\");\n                        assertEquals((short) 42, dObj.getShort(AllJavaTypes.FIELD_SHORT));\n                        break;\n                    case INT:\n                        dObj.set(AllJavaTypes.FIELD_INT, \"42\");\n                        assertEquals(42, dObj.getInt(AllJavaTypes.FIELD_INT));\n                        break;\n                    case LONG:\n                        dObj.set(AllJavaTypes.FIELD_LONG, \"42\");\n                        assertEquals((long) 42, dObj.getLong(AllJavaTypes.FIELD_LONG));\n                        break;\n                    case FLOAT:\n                        dObj.set(AllJavaTypes.FIELD_FLOAT, \"1.23\");\n                        assertEquals(1.23f, dObj.getFloat(AllJavaTypes.FIELD_FLOAT), 0f);\n                        break;\n                    case DOUBLE:\n                        dObj.set(AllJavaTypes.FIELD_DOUBLE, \"1.234\");\n                        assertEquals(1.234d, dObj.getDouble(AllJavaTypes.FIELD_DOUBLE), 0f);\n                        break;\n                    case DATE:\n                        dObj.set(AllJavaTypes.FIELD_DATE, \"1000\");\n                        assertEquals(new Date(1000), dObj.getDate(AllJavaTypes.FIELD_DATE));\n                        break;\n                    case DECIMAL128:\n                        dObj.set(AllJavaTypes.FIELD_DECIMAL128, \"1\");\n                        assertEquals(new Decimal128(BigDecimal.ONE), dObj.get(AllJavaTypes.FIELD_DECIMAL128));\n                        break;\n                    case OBJECT_ID:\n                        dObj.set(AllJavaTypes.FIELD_OBJECT_ID, TestHelper.generateObjectIdHexString(7));\n                        assertEquals(new ObjectId(TestHelper.generateObjectIdHexString(7)), dObj.get(AllJavaTypes.FIELD_OBJECT_ID));\n                        break;\n                    case UUID:\n                        String uuid = UUID.randomUUID().toString();\n                        dObj.set(AllJavaTypes.FIELD_UUID, UUID.fromString(uuid));\n                        assertEquals(UUID.fromString(uuid), dObj.get(AllJavaTypes.FIELD_UUID));\n                        break;\n                    // These types don't have a string representation that can be parsed.\n                    case OBJECT:\n                    case LIST:\n                    case LIST_INTEGER:\n                    case LIST_STRING:\n                    case LIST_BOOLEAN:\n                    case LIST_FLOAT:\n                    case LIST_DOUBLE:\n                    case LIST_BINARY:\n                    case LIST_DATE:\n                    case LIST_DECIMAL128:\n                    case LIST_OBJECT_ID:\n                    case LIST_UUID:\n                    case STRING:\n                    case BINARY:\n                    case BYTE:\n                        break;\n                    default:\n                        fail(\"Unknown type: \" + type);\n                        break;\n                }\n            }\n        } finally {\n            realm.cancelTransaction();\n        }\n    }\n\n    @Test\n    public void untypedSetter_illegalImplicitConversionThrows() {\n        realm.beginTransaction();\n        AllJavaTypes obj = realm.createObject(AllJavaTypes.class, 0);\n        DynamicRealmObject dObj = new DynamicRealmObject(obj);\n        try {\n            for (SupportedType type : SupportedType.values()) {\n                try {\n                    switch (type) {\n                        case SHORT:\n                            dObj.set(AllJavaTypes.FIELD_SHORT, \"foo\");\n                            break;\n                        case INT:\n                            dObj.set(AllJavaTypes.FIELD_INT, \"foo\");\n                            break;\n                        case LONG:\n                            dObj.set(AllJavaTypes.FIELD_ID, \"foo\");\n                            break;\n                        case FLOAT:\n                            dObj.set(AllJavaTypes.FIELD_FLOAT, \"foo\");\n                            break;\n                        case DOUBLE:\n                            dObj.set(AllJavaTypes.FIELD_DOUBLE, \"foo\");\n                            break;\n                        case DATE:\n                            dObj.set(AllJavaTypes.FIELD_DATE, \"foo\");\n                            break;\n                        case DECIMAL128:\n                            dObj.set(AllJavaTypes.FIELD_DECIMAL128, \"foo\");\n                            break;\n                        case OBJECT_ID:\n                            dObj.set(AllJavaTypes.FIELD_OBJECT_ID, \"foo\");\n                            break;\n                        case UUID:\n                            dObj.set(AllJavaTypes.FIELD_UUID, \"foo\");\n                            break;\n                        // These types don't have a string representation that can be parsed.\n                        case BOOLEAN: // Boolean is special as it returns false for all strings != \"true\"\n                        case BYTE:\n                        case OBJECT:\n                        case LIST:\n                        case LIST_INTEGER:\n                        case LIST_STRING:\n                        case LIST_BOOLEAN:\n                        case LIST_FLOAT:\n                        case LIST_DOUBLE:\n                        case LIST_BINARY:\n                        case LIST_DATE:\n                        case LIST_DECIMAL128:\n                        case LIST_OBJECT_ID:\n                        case LIST_UUID:\n                        case STRING:\n                        case BINARY:\n                            continue;\n\n                        default:\n                            fail(\"Unknown type: \" + type);\n                    }\n                    fail(type + \" failed\");\n                } catch (IllegalArgumentException ignored) {\n                } catch (RealmException e) {\n                    if (!(e.getCause() instanceof ParseException)) {\n                        // Providing \"foo\" to the date parser will blow up with a RealmException\n                        // and the cause will be a ParseException.\n                        fail(type + \" failed\");\n                    }\n                }\n            }\n        } finally {\n            realm.cancelTransaction();\n        }\n    }\n\n    private void testChangePrimaryKeyThroughUntypedSetter(String value) {\n        final String[] primaryKeyClasses = {PrimaryKeyAsBoxedByte.CLASS_NAME, PrimaryKeyAsBoxedShort.CLASS_NAME,\n                PrimaryKeyAsBoxedInteger.CLASS_NAME, PrimaryKeyAsBoxedLong.CLASS_NAME, PrimaryKeyAsString.CLASS_NAME};\n        for (String pkClass : primaryKeyClasses) {\n            dynamicRealm.beginTransaction();\n            DynamicRealmObject object;\n            boolean isStringPK = pkClass.equals(PrimaryKeyAsString.CLASS_NAME);\n            if (isStringPK) {\n                object = dynamicRealm.createObject(pkClass, \"\");\n            } else {\n                object = dynamicRealm.createObject(pkClass, 0);\n            }\n\n            try {\n                object.set(isStringPK ? PrimaryKeyAsString.FIELD_PRIMARY_KEY : \"id\", value);\n                fail();\n            } catch (IllegalArgumentException ignored) {\n            }\n            dynamicRealm.cancelTransaction();\n        }\n    }\n\n    @Test\n    public void untypedSetter_setValue_changePrimaryKeyThrows() {\n        testChangePrimaryKeyThroughUntypedSetter(\"42\");\n    }\n\n    @Test\n    public void untypedSetter_setNull_changePrimaryKeyThrows() {\n        testChangePrimaryKeyThroughUntypedSetter(null);\n    }\n\n    @Test\n    public void isNull_nullNotSupportedField() {\n        assertFalse(dObjTyped.isNull(AllJavaTypes.FIELD_INT));\n    }\n\n    @Test\n    public void isNull_true() {\n        realm.beginTransaction();\n        AllJavaTypes obj = realm.createObject(AllJavaTypes.class, 0);\n        realm.commitTransaction();\n\n        assertTrue(new DynamicRealmObject(obj).isNull(AllJavaTypes.FIELD_OBJECT));\n    }\n\n    @Test\n    public void isNull_false() {\n        assertFalse(dObjTyped.isNull(AllJavaTypes.FIELD_OBJECT));\n    }\n\n    @Test\n    public void getFieldNames() {\n        String[] expectedKeys = {AllJavaTypes.FIELD_STRING, AllJavaTypes.FIELD_ID, AllJavaTypes.FIELD_LONG,\n                AllJavaTypes.FIELD_SHORT, AllJavaTypes.FIELD_INT, AllJavaTypes.FIELD_BYTE, AllJavaTypes.FIELD_FLOAT,\n                AllJavaTypes.FIELD_DOUBLE, AllJavaTypes.FIELD_BOOLEAN, AllJavaTypes.FIELD_DATE,\n                AllJavaTypes.FIELD_BINARY, AllJavaTypes.FIELD_DECIMAL128, AllJavaTypes.FIELD_OBJECT_ID, AllJavaTypes.FIELD_UUID,\n                AllJavaTypes.FIELD_REALM_ANY, AllJavaTypes.FIELD_OBJECT, AllJavaTypes.FIELD_LIST,\n                AllJavaTypes.FIELD_STRING_LIST, AllJavaTypes.FIELD_BINARY_LIST, AllJavaTypes.FIELD_BOOLEAN_LIST,\n                AllJavaTypes.FIELD_LONG_LIST, AllJavaTypes.FIELD_INTEGER_LIST, AllJavaTypes.FIELD_SHORT_LIST,\n                AllJavaTypes.FIELD_BYTE_LIST, AllJavaTypes.FIELD_DOUBLE_LIST, AllJavaTypes.FIELD_FLOAT_LIST,\n                AllJavaTypes.FIELD_DATE_LIST, AllJavaTypes.FIELD_DECIMAL128_LIST, AllJavaTypes.FIELD_OBJECT_ID_LIST,\n                AllJavaTypes.FIELD_UUID_LIST, AllJavaTypes.FIELD_REALM_ANY_LIST};\n        String[] keys = dObjTyped.getFieldNames();\n        // After the stable ID support, primary key field will be inserted first before others. So even FIELD_STRING is\n        // the first defined field in the class, it will be inserted after FIELD_ID.\n        // See ObjectStore::add_initial_columns #if REALM_HAVE_SYNC_STABLE_IDS branch.\n        assertEquals(expectedKeys.length, keys.length);\n        assertThat(Arrays.asList(expectedKeys), Matchers.hasItems(keys));\n    }\n\n    @Test\n    public void hasField_false() {\n        assertFalse(dObjTyped.hasField(null));\n        assertFalse(dObjTyped.hasField(\"\"));\n        assertFalse(dObjTyped.hasField(\"foo\"));\n        assertFalse(dObjTyped.hasField(\"foo.bar\"));\n        assertFalse(dObjTyped.hasField(TestHelper.getRandomString(65)));\n    }\n\n    @Test\n    public void hasField_true() {\n        assertTrue(dObjTyped.hasField(AllJavaTypes.FIELD_STRING));\n    }\n\n    @Test\n    public void getFieldType() {\n        assertEquals(RealmFieldType.STRING, dObjTyped.getFieldType(AllJavaTypes.FIELD_STRING));\n        assertEquals(RealmFieldType.BINARY, dObjTyped.getFieldType(AllJavaTypes.FIELD_BINARY));\n        assertEquals(RealmFieldType.BOOLEAN, dObjTyped.getFieldType(AllJavaTypes.FIELD_BOOLEAN));\n        assertEquals(RealmFieldType.DATE, dObjTyped.getFieldType(AllJavaTypes.FIELD_DATE));\n        assertEquals(RealmFieldType.OBJECT_ID, dObjTyped.getFieldType(AllJavaTypes.FIELD_OBJECT_ID));\n        assertEquals(RealmFieldType.DECIMAL128, dObjTyped.getFieldType(AllJavaTypes.FIELD_DECIMAL128));\n        assertEquals(RealmFieldType.UUID, dObjTyped.getFieldType(AllJavaTypes.FIELD_UUID));\n        assertEquals(RealmFieldType.DOUBLE, dObjTyped.getFieldType(AllJavaTypes.FIELD_DOUBLE));\n        assertEquals(RealmFieldType.FLOAT, dObjTyped.getFieldType(AllJavaTypes.FIELD_FLOAT));\n        assertEquals(RealmFieldType.OBJECT, dObjTyped.getFieldType(AllJavaTypes.FIELD_OBJECT));\n        assertEquals(RealmFieldType.LIST, dObjTyped.getFieldType(AllJavaTypes.FIELD_LIST));\n        assertEquals(RealmFieldType.INTEGER, dObjTyped.getFieldType(AllJavaTypes.FIELD_BYTE));\n        assertEquals(RealmFieldType.INTEGER, dObjTyped.getFieldType(AllJavaTypes.FIELD_SHORT));\n        assertEquals(RealmFieldType.INTEGER, dObjTyped.getFieldType(AllJavaTypes.FIELD_INT));\n        assertEquals(RealmFieldType.INTEGER, dObjTyped.getFieldType(AllJavaTypes.FIELD_LONG));\n        assertEquals(RealmFieldType.INTEGER_LIST, dObjTyped.getFieldType(AllJavaTypes.FIELD_INTEGER_LIST));\n        assertEquals(RealmFieldType.STRING_LIST, dObjTyped.getFieldType(AllJavaTypes.FIELD_STRING_LIST));\n        assertEquals(RealmFieldType.BOOLEAN_LIST, dObjTyped.getFieldType(AllJavaTypes.FIELD_BOOLEAN_LIST));\n        assertEquals(RealmFieldType.FLOAT_LIST, dObjTyped.getFieldType(AllJavaTypes.FIELD_FLOAT_LIST));\n        assertEquals(RealmFieldType.DOUBLE_LIST, dObjTyped.getFieldType(AllJavaTypes.FIELD_DOUBLE_LIST));\n        assertEquals(RealmFieldType.BINARY_LIST, dObjTyped.getFieldType(AllJavaTypes.FIELD_BINARY_LIST));\n        assertEquals(RealmFieldType.DATE_LIST, dObjTyped.getFieldType(AllJavaTypes.FIELD_DATE_LIST));\n        assertEquals(RealmFieldType.OBJECT_ID_LIST, dObjTyped.getFieldType(AllJavaTypes.FIELD_OBJECT_ID_LIST));\n        assertEquals(RealmFieldType.DECIMAL128_LIST, dObjTyped.getFieldType(AllJavaTypes.FIELD_DECIMAL128_LIST));\n        assertEquals(RealmFieldType.UUID_LIST, dObjTyped.getFieldType(AllJavaTypes.FIELD_UUID_LIST));\n    }\n\n    @Test\n    public void equals() {\n        AllJavaTypes obj1 = realm.where(AllJavaTypes.class).findFirst();\n        AllJavaTypes obj2 = realm.where(AllJavaTypes.class).findFirst();\n        DynamicRealmObject dObj1 = new DynamicRealmObject(obj1);\n        DynamicRealmObject dObj2 = new DynamicRealmObject(obj2);\n        assertTrue(dObj1.equals(dObj2));\n    }\n\n    @Test\n    public void equals_standardAndDynamicObjectsNotEqual() {\n        AllJavaTypes standardObj = realm.where(AllJavaTypes.class).findFirst();\n        //noinspection EqualsBetweenInconvertibleTypes\n        assertFalse(dObjTyped.equals(standardObj));\n    }\n\n    @Test\n    public void hashcode() {\n        AllJavaTypes standardObj = realm.where(AllJavaTypes.class).findFirst();\n        DynamicRealmObject dObj1 = new DynamicRealmObject(standardObj);\n        assertEquals(standardObj.hashCode(), dObj1.hashCode());\n    }\n\n    @Test\n    public void toString_test() {\n        // Checks that toString() doesn't crash, and does simple formatting checks. We cannot compare to a set String as\n        // eg. the byte array will be allocated each time it is accessed.\n        String str = dObjTyped.toString();\n        assertTrue(str.startsWith(\"AllJavaTypes = dynamic[\"));\n        assertTrue(str.endsWith(\"}]\"));\n    }\n\n    @Test\n    public void toString_nullValues() {\n        dynamicRealm.beginTransaction();\n        final DynamicRealmObject obj = dynamicRealm.createObject(NullTypes.CLASS_NAME, 0);\n        dynamicRealm.commitTransaction();\n\n        String str = obj.toString();\n        assertTrue(str.contains(NullTypes.FIELD_STRING_NULL + \":null\"));\n        assertTrue(str.contains(NullTypes.FIELD_BYTES_NULL + \":null\"));\n        assertTrue(str.contains(NullTypes.FIELD_BOOLEAN_NULL + \":null\"));\n        assertTrue(str.contains(NullTypes.FIELD_BYTE_NULL + \":null\"));\n        assertTrue(str.contains(NullTypes.FIELD_SHORT_NULL + \":null\"));\n        assertTrue(str.contains(NullTypes.FIELD_INTEGER_NULL + \":null\"));\n        assertTrue(str.contains(NullTypes.FIELD_LONG_NULL + \":null\"));\n        assertTrue(str.contains(NullTypes.FIELD_FLOAT_NULL + \":null\"));\n        assertTrue(str.contains(NullTypes.FIELD_DOUBLE_NULL + \":null\"));\n        assertTrue(str.contains(NullTypes.FIELD_DATE_NULL + \":null\"));\n        assertTrue(str.contains(NullTypes.FIELD_OBJECT_ID_NULL + \":null\"));\n        assertTrue(str.contains(NullTypes.FIELD_DECIMAL128_NULL + \":null\"));\n        assertTrue(str.contains(NullTypes.FIELD_UUID_NULL + \":null\"));\n        assertTrue(str.contains(NullTypes.FIELD_OBJECT_NULL + \":null\"));\n        assertTrue(str.contains(NullTypes.FIELD_LIST_NULL + \":RealmList<NullTypes>[0]\"));\n        assertTrue(str.contains(NullTypes.FIELD_INTEGER_LIST_NULL + \":RealmList<Long>[0]\"));\n        assertTrue(str.contains(NullTypes.FIELD_STRING_LIST_NULL + \":RealmList<String>[0]\"));\n        assertTrue(str.contains(NullTypes.FIELD_BOOLEAN_LIST_NULL + \":RealmList<Boolean>[0]\"));\n        assertTrue(str.contains(NullTypes.FIELD_FLOAT_LIST_NULL + \":RealmList<Float>[0]\"));\n        assertTrue(str.contains(NullTypes.FIELD_DOUBLE_LIST_NULL + \":RealmList<Double>[0]\"));\n        assertTrue(str.contains(NullTypes.FIELD_BINARY_LIST_NULL + \":RealmList<byte[]>[0]\"));\n        assertTrue(str.contains(NullTypes.FIELD_DATE_LIST_NULL + \":RealmList<Date>[0]\"));\n        assertTrue(str.contains(NullTypes.FIELD_OBJECT_ID_LIST_NULL + \":RealmList<ObjectId>[0]\"));\n        assertTrue(str.contains(NullTypes.FIELD_DECIMAL128_LIST_NULL + \":RealmList<Decimal128>[0]\"));\n        assertTrue(str.contains(NullTypes.FIELD_UUID_LIST_NULL + \":RealmList<UUID>[0]\"));\n    }\n\n    @Test\n    public void testExceptionMessage() {\n        // Tests for https://github.com/realm/realm-java/issues/2141\n        realm.beginTransaction();\n        AllTypes obj = realm.createObject(AllTypes.class);\n        realm.commitTransaction();\n\n        DynamicRealmObject o = new DynamicRealmObject(obj);\n        try {\n            o.getFloat(\"nonExisting\"); // Notes that \"o\" does not have \"nonExisting\" field.\n            fail();\n        } catch (IllegalArgumentException e) {\n            assertEquals(\"Illegal Argument: Field not found: nonExisting\", e.getMessage());\n        }\n    }\n\n    @Test\n    public void getDynamicRealm() {\n        realm.beginTransaction();\n        realm.createObject(AllTypes.class);\n        realm.commitTransaction();\n\n        dynamicRealm.refresh();\n        final DynamicRealmObject object = dynamicRealm.where(AllTypes.CLASS_NAME).findFirst();\n\n        assertSame(dynamicRealm, object.getDynamicRealm());\n    }\n\n    @Test\n    public void getRealm() {\n        realm.beginTransaction();\n        realm.createObject(AllTypes.class);\n        realm.commitTransaction();\n\n        dynamicRealm.refresh();\n        final DynamicRealmObject object = dynamicRealm.where(AllTypes.CLASS_NAME).findFirst();\n\n        thrown.expect(IllegalStateException.class);\n        object.getRealm();\n    }\n\n    @Test\n    public void getRealm_closedObjectThrows() {\n        realm.beginTransaction();\n        realm.createObject(AllTypes.class);\n        realm.commitTransaction();\n\n        dynamicRealm.refresh();\n        final DynamicRealmObject object = dynamicRealm.where(AllTypes.CLASS_NAME).findFirst();\n        dynamicRealm.close();\n        dynamicRealm = null;\n\n        try {\n            object.getDynamicRealm();\n            fail();\n        } catch (IllegalStateException e) {\n            assertEquals(BaseRealm.CLOSED_REALM_MESSAGE, e.getMessage());\n        }\n    }\n\n    @Test\n    public void getRealmConfiguration_deletedObjectThrows() {\n        realm.beginTransaction();\n        realm.createObject(AllTypes.class);\n        realm.commitTransaction();\n\n        dynamicRealm.refresh();\n        final DynamicRealmObject object = dynamicRealm.where(AllTypes.CLASS_NAME).findFirst();\n        dynamicRealm.beginTransaction();\n        object.deleteFromRealm();\n        dynamicRealm.commitTransaction();\n\n        try {\n            object.getDynamicRealm();\n            fail();\n        } catch (IllegalStateException e) {\n            assertEquals(RealmObject.MSG_DELETED_OBJECT, e.getMessage());\n        }\n    }\n\n    @Test\n    public void getRealm_illegalThreadThrows() throws Throwable {\n        realm.beginTransaction();\n        realm.createObject(AllTypes.class);\n        realm.commitTransaction();\n\n        dynamicRealm.refresh();\n        final DynamicRealmObject object = dynamicRealm.where(AllTypes.CLASS_NAME).findFirst();\n\n        final CountDownLatch threadFinished = new CountDownLatch(1);\n        final Thread thread = new Thread(new Runnable() {\n            @Override\n            public void run() {\n                try {\n                    object.getDynamicRealm();\n                    fail();\n                } catch (IllegalStateException e) {\n                    assertEquals(BaseRealm.INCORRECT_THREAD_MESSAGE, e.getMessage());\n                } finally {\n                    threadFinished.countDown();\n                }\n            }\n        });\n        thread.start();\n        TestHelper.awaitOrFail(threadFinished);\n    }\n\n    @Test\n    public void getNullableFields() {\n        realm.executeTransaction(realm -> {\n            NullablePrimitiveFields primitiveNullables = realm.createObject(NullablePrimitiveFields.class);\n            primitiveNullables.setFieldBoolean(null);\n\n            assertNull(primitiveNullables.getFieldBoolean());\n            assertNull(primitiveNullables.getFieldInt());\n            assertNull(primitiveNullables.getFieldFloat());\n            assertNull(primitiveNullables.getFieldDouble());\n            assertNull(primitiveNullables.getFieldString());\n            assertNull(primitiveNullables.getFieldBinary());\n            assertNull(primitiveNullables.getFieldDate());\n            assertNull(primitiveNullables.getFieldObjectId());\n            assertNull(primitiveNullables.getFieldDecimal128());\n            assertNull(primitiveNullables.getFieldUUID());\n            assertTrue(primitiveNullables.getFieldRealmAny().isNull());\n\n            realm.delete(AllJavaTypes.class);\n            AllJavaTypes allJavaTypes = realm.createObject(AllJavaTypes.class, UUID.randomUUID().getLeastSignificantBits());\n\n            assertNull(allJavaTypes.getFieldObject());\n            allJavaTypes.getFieldBooleanList().add(null);\n            allJavaTypes.getFieldIntegerList().add(null);\n            allJavaTypes.getFieldFloatList().add(null);\n            allJavaTypes.getFieldDoubleList().add(null);\n            allJavaTypes.getFieldStringList().add(null);\n            allJavaTypes.getFieldBinaryList().add(null);\n            allJavaTypes.getFieldDateList().add(null);\n            allJavaTypes.getFieldObjectIdList().add(null);\n            allJavaTypes.getFieldDecimal128List().add(null);\n            allJavaTypes.getFieldUUIDList().add(null);\n            allJavaTypes.getFieldRealmAnyList().add(null);\n\n        });\n        realm.close();\n        dynamicRealm.refresh();\n\n        DynamicRealmObject primitiveNullables = dynamicRealm.where(NullablePrimitiveFields.CLASS_NAME).findFirst();\n        DynamicRealmObject allJavaTypes = dynamicRealm.where(AllJavaTypes.CLASS_NAME).findFirst();\n\n        for (RealmFieldType value : RealmFieldType.values()) {\n            switch (value) {\n                case INTEGER:\n                    assertNull(primitiveNullables.get(NullablePrimitiveFields.FIELD_INT));\n                    break;\n                case BOOLEAN:\n                    assertNull(primitiveNullables.get(NullablePrimitiveFields.FIELD_BOOLEAN));\n                    break;\n                case STRING:\n                    assertNull(primitiveNullables.get(NullablePrimitiveFields.FIELD_STRING));\n                    break;\n                case BINARY:\n                    assertNull(primitiveNullables.get(NullablePrimitiveFields.FIELD_BINARY));\n                    break;\n                case DATE:\n                    assertNull(primitiveNullables.get(NullablePrimitiveFields.FIELD_DATE));\n                    break;\n                case FLOAT:\n                    assertNull(primitiveNullables.get(NullablePrimitiveFields.FIELD_FLOAT));\n                    break;\n                case DOUBLE:\n                    assertNull(primitiveNullables.get(NullablePrimitiveFields.FIELD_DOUBLE));\n                    break;\n                case OBJECT:\n                    assertNull(allJavaTypes.get(AllJavaTypes.FIELD_OBJECT));\n                    break;\n                case DECIMAL128:\n                    assertNull(primitiveNullables.get(NullablePrimitiveFields.FIELD_DECIMAL128));\n                    break;\n                case OBJECT_ID:\n                    assertNull(primitiveNullables.get(NullablePrimitiveFields.FIELD_OBJECT_ID));\n                    break;\n                case UUID:\n                    assertNull(primitiveNullables.get(NullablePrimitiveFields.FIELD_UUID));\n                    break;\n                case MIXED:\n                    assertNull(primitiveNullables.get(NullablePrimitiveFields.FIELD_REALM_ANY));\n                    break;\n                case INTEGER_LIST:\n                    assertNull(allJavaTypes.getList(AllJavaTypes.FIELD_INTEGER_LIST, Integer.class).get(0));\n                    break;\n                case BOOLEAN_LIST:\n                    assertNull(allJavaTypes.getList(AllJavaTypes.FIELD_BOOLEAN_LIST, Boolean.class).get(0));\n                    break;\n                case STRING_LIST:\n                    assertNull(allJavaTypes.getList(AllJavaTypes.FIELD_STRING_LIST, String.class).get(0));\n                    break;\n                case BINARY_LIST:\n                    assertNull(allJavaTypes.getList(AllJavaTypes.FIELD_BINARY_LIST, byte[].class).get(0));\n                    break;\n                case DATE_LIST:\n                    assertNull(allJavaTypes.getList(AllJavaTypes.FIELD_DATE_LIST, Date.class).get(0));\n                    break;\n                case FLOAT_LIST:\n                    assertNull(allJavaTypes.getList(AllJavaTypes.FIELD_FLOAT_LIST, Float.class).get(0));\n                    break;\n                case DOUBLE_LIST:\n                    assertNull(allJavaTypes.getList(AllJavaTypes.FIELD_DOUBLE_LIST, Double.class).get(0));\n                    break;\n                case DECIMAL128_LIST:\n                    assertNull(allJavaTypes.getList(AllJavaTypes.FIELD_DECIMAL128_LIST, Decimal128.class).get(0));\n                    break;\n                case OBJECT_ID_LIST:\n                    assertNull(allJavaTypes.getList(AllJavaTypes.FIELD_OBJECT_ID_LIST, ObjectId.class).get(0));\n                    break;\n                case UUID_LIST:\n                    assertNull(allJavaTypes.getList(AllJavaTypes.FIELD_UUID_LIST, UUID.class).get(0));\n                    break;\n                case MIXED_LIST:\n                    assertTrue(allJavaTypes.getList(AllJavaTypes.FIELD_REALM_ANY_LIST, RealmAny.class).get(0).isNull());\n                    break;\n                case TYPED_LINK:\n                case LIST:\n                case LINKING_OBJECTS:\n                    // Realm lists and back links cannot be null\n                    break;\n                case STRING_TO_MIXED_MAP:\n                case STRING_TO_BOOLEAN_MAP:\n                case STRING_TO_STRING_MAP:\n                case STRING_TO_INTEGER_MAP:\n                case STRING_TO_FLOAT_MAP:\n                case STRING_TO_DOUBLE_MAP:\n                case STRING_TO_BINARY_MAP:\n                case STRING_TO_DATE_MAP:\n                case STRING_TO_OBJECT_ID_MAP:\n                case STRING_TO_UUID_MAP:\n                case STRING_TO_DECIMAL128_MAP:\n                case STRING_TO_LINK_MAP:\n                case BOOLEAN_SET:\n                case STRING_SET:\n                case INTEGER_SET:\n                case FLOAT_SET:\n                case DOUBLE_SET:\n                case BINARY_SET:\n                case DATE_SET:\n                case DECIMAL128_SET:\n                case OBJECT_ID_SET:\n                case UUID_SET:\n                case LINK_SET:\n                case MIXED_SET:\n                    // TODO: fix this when adding dynamic support for dictionaries\n                    break;\n                default:\n                    fail(\"Not testing all types\");\n            }\n        }\n        dynamicRealm.close();\n    }\n\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/DynamicRealmTests.java",
    "content": "/*\n * Copyright 2016 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\npackage io.realm;\n\nimport androidx.test.annotation.UiThreadTest;\nimport androidx.test.ext.junit.runners.AndroidJUnit4;\n\nimport org.junit.After;\nimport org.junit.Before;\nimport org.junit.Ignore;\nimport org.junit.Rule;\nimport org.junit.Test;\nimport org.junit.rules.ExpectedException;\nimport org.junit.runner.RunWith;\n\nimport java.util.Date;\nimport java.util.Objects;\nimport java.util.concurrent.atomic.AtomicInteger;\nimport java.util.concurrent.atomic.AtomicReference;\n\nimport io.realm.entities.AllTypes;\nimport io.realm.entities.Cat;\nimport io.realm.entities.Dog;\nimport io.realm.entities.DogPrimaryKey;\nimport io.realm.entities.Owner;\nimport io.realm.entities.PrimaryKeyAsBoxedByte;\nimport io.realm.entities.PrimaryKeyAsBoxedInteger;\nimport io.realm.entities.PrimaryKeyAsBoxedLong;\nimport io.realm.entities.PrimaryKeyAsBoxedShort;\nimport io.realm.entities.PrimaryKeyAsString;\nimport io.realm.exceptions.RealmException;\nimport io.realm.log.RealmLog;\nimport io.realm.rule.RunInLooperThread;\nimport io.realm.rule.RunTestInLooperThread;\n\nimport static org.junit.Assert.assertEquals;\nimport static org.junit.Assert.assertFalse;\nimport static org.junit.Assert.assertNotNull;\nimport static org.junit.Assert.assertTrue;\nimport static org.junit.Assert.fail;\n\n@RunWith(AndroidJUnit4.class)\npublic class DynamicRealmTests {\n\n    @Rule\n    public final RunInLooperThread looperThread = new RunInLooperThread();\n\n    @Rule\n    public final TestRealmConfigurationFactory configFactory = new TestRealmConfigurationFactory();\n\n    @Rule\n    public final ExpectedException thrown = ExpectedException.none();\n\n    private RealmConfiguration defaultConfig;\n    private DynamicRealm realm;\n\n    @Before\n    public void setUp() {\n        defaultConfig = configFactory.createConfiguration();\n\n        // Initializes schema. DynamicRealm will not do that, so let a normal Realm create the file first.\n        Realm.getInstance(defaultConfig).close();\n        realm = DynamicRealm.getInstance(defaultConfig);\n    }\n\n    @After\n    public void tearDown() {\n        if (realm != null) {\n            realm.close();\n        }\n    }\n\n    private void populateTestRealm(DynamicRealm realm, int objects) {\n        boolean autoRefreshEnabled = realm.isAutoRefresh();\n        if (autoRefreshEnabled) {\n            realm.setAutoRefresh(false);\n        }\n        realm.beginTransaction();\n        realm.deleteAll();\n        for (int i = 0; i < objects; ++i) {\n            DynamicRealmObject allTypes = realm.createObject(AllTypes.CLASS_NAME);\n            allTypes.setBoolean(AllTypes.FIELD_BOOLEAN, (i % 3) == 0);\n            allTypes.setBlob(AllTypes.FIELD_BINARY, new byte[]{1, 2, 3});\n            allTypes.setDate(AllTypes.FIELD_DATE, new Date());\n            allTypes.setDouble(AllTypes.FIELD_DOUBLE, Math.PI + i);\n            allTypes.setFloat(AllTypes.FIELD_FLOAT, 1.234567F + i);\n            allTypes.setString(AllTypes.FIELD_STRING, \"test data \" + i);\n            allTypes.setLong(AllTypes.FIELD_LONG, i);\n            allTypes.getList(AllTypes.FIELD_REALMLIST).add(realm.createObject(Dog.CLASS_NAME));\n            allTypes.getList(AllTypes.FIELD_REALMLIST).add(realm.createObject(Dog.CLASS_NAME));\n        }\n        realm.commitTransaction();\n        if (autoRefreshEnabled) {\n            realm.setAutoRefresh(true);\n        }\n    }\n\n    // Tests that the SharedGroupManager is not reused across Realm/DynamicRealm on the same thread.\n    // This is done by starting a write transaction in one Realm and verifying that none of the data\n    // written (but not committed) is available in the other Realm.\n    @Test\n    public void separateSharedGroups() {\n        Realm typedRealm = Realm.getInstance(defaultConfig);\n        DynamicRealm dynamicRealm = DynamicRealm.getInstance(defaultConfig);\n\n        assertEquals(0, typedRealm.where(AllTypes.class).count());\n        assertEquals(0, dynamicRealm.where(AllTypes.CLASS_NAME).count());\n\n        typedRealm.beginTransaction();\n        try {\n            typedRealm.createObject(AllTypes.class);\n            assertEquals(1, typedRealm.where(AllTypes.class).count());\n            assertEquals(0, dynamicRealm.where(AllTypes.CLASS_NAME).count());\n            typedRealm.cancelTransaction();\n        } finally {\n            typedRealm.close();\n            dynamicRealm.close();\n        }\n    }\n\n    // Tests that Realms can only be deleted after all Typed and Dynamic instances are closed.\n    @Test\n    public void deleteRealm_ThrowsIfDynamicRealmIsOpen() {\n        realm.close(); // Close Realm opened in setUp();\n        Realm typedRealm = Realm.getInstance(defaultConfig);\n        DynamicRealm dynamicRealm = DynamicRealm.getInstance(defaultConfig);\n\n        typedRealm.close();\n        try {\n            Realm.deleteRealm(defaultConfig);\n            fail();\n        } catch (IllegalStateException ignored) {\n        }\n\n        dynamicRealm.close();\n        assertTrue(Realm.deleteRealm(defaultConfig));\n    }\n\n    // Test that Realms can only be deleted after all Typed and Dynamic instances are closed.\n    @Test\n    public void deleteRealm_throwsIfTypedRealmIsOpen() {\n        realm.close(); // Close Realm opened in setUp();\n        Realm typedRealm = Realm.getInstance(defaultConfig);\n        DynamicRealm dynamicRealm = DynamicRealm.getInstance(defaultConfig);\n\n        dynamicRealm.close();\n        try {\n            Realm.deleteRealm(defaultConfig);\n            fail();\n        } catch (IllegalStateException ignored) {\n        }\n\n        typedRealm.close();\n        assertTrue(Realm.deleteRealm(defaultConfig));\n    }\n\n    @Test\n    public void createObject() {\n        realm.beginTransaction();\n        DynamicRealmObject obj = realm.createObject(AllTypes.CLASS_NAME);\n        realm.commitTransaction();\n        assertTrue(obj.isValid());\n    }\n\n    @Test\n    public void createObject_withPrimaryKey() {\n        realm.beginTransaction();\n        DynamicRealmObject dog = realm.createObject(DogPrimaryKey.CLASS_NAME, 42);\n        assertEquals(42, dog.getLong(\"id\"));\n        realm.cancelTransaction();\n    }\n\n    @Test\n    public void createObject_withNullStringPrimaryKey() {\n        realm.beginTransaction();\n        realm.createObject(PrimaryKeyAsString.CLASS_NAME, (String) null);\n        realm.commitTransaction();\n\n        assertEquals(1, realm.where(PrimaryKeyAsString.CLASS_NAME).equalTo(PrimaryKeyAsString.FIELD_PRIMARY_KEY, (String) null).count());\n    }\n\n    @Test\n    public void createObject_withNullBytePrimaryKey() {\n        realm.beginTransaction();\n        realm.createObject(PrimaryKeyAsBoxedByte.CLASS_NAME, (Byte) null);\n        realm.commitTransaction();\n\n        assertEquals(1, realm.where(PrimaryKeyAsBoxedByte.CLASS_NAME).equalTo(PrimaryKeyAsBoxedByte.FIELD_PRIMARY_KEY, (Byte) null).count());\n    }\n\n    @Test\n    public void createObject_withNullShortPrimaryKey() {\n        realm.beginTransaction();\n        realm.createObject(PrimaryKeyAsBoxedShort.CLASS_NAME, (Short) null);\n        realm.commitTransaction();\n\n        assertEquals(1, realm.where(PrimaryKeyAsBoxedShort.CLASS_NAME).equalTo(PrimaryKeyAsBoxedShort.FIELD_PRIMARY_KEY, (Short) null).count());\n    }\n\n    @Test\n    public void createObject_withNullIntegerPrimaryKey() {\n        realm.beginTransaction();\n        realm.createObject(PrimaryKeyAsBoxedInteger.CLASS_NAME, (Integer) null);\n        realm.commitTransaction();\n\n        assertEquals(1, realm.where(PrimaryKeyAsBoxedInteger.CLASS_NAME).equalTo(PrimaryKeyAsBoxedInteger.FIELD_PRIMARY_KEY, (Integer) null).count());\n    }\n\n    @Test\n    public void createObject_withNullLongPrimaryKey() {\n        realm.beginTransaction();\n        realm.createObject(PrimaryKeyAsBoxedLong.CLASS_NAME, (Long) null);\n        realm.commitTransaction();\n\n        assertEquals(1, realm.where(PrimaryKeyAsBoxedLong.CLASS_NAME).equalTo(PrimaryKeyAsBoxedLong.FIELD_PRIMARY_KEY, (Long) null).count());\n    }\n\n    @Test(expected = IllegalArgumentException.class)\n    public void createObject_illegalPrimaryKeyValue() {\n        realm.beginTransaction();\n        realm.createObject(DogPrimaryKey.CLASS_NAME, \"bar\");\n    }\n\n    @Test(expected = RealmException.class)\n    public void createObject_absentPrimaryKeyThrows() {\n        realm.beginTransaction();\n        realm.createObject(DogPrimaryKey.CLASS_NAME);\n    }\n\n    @Test\n    public void where() {\n        realm.beginTransaction();\n        realm.createObject(AllTypes.CLASS_NAME);\n        realm.commitTransaction();\n\n        RealmResults<DynamicRealmObject> results = realm.where(AllTypes.CLASS_NAME).findAll();\n        assertEquals(1, results.size());\n    }\n\n    @Test(expected = IllegalArgumentException.class)\n    public void delete_type_invalidName() {\n        realm.beginTransaction();\n        realm.delete(\"I don't exist\");\n    }\n\n    @Test(expected = IllegalStateException.class)\n    public void delete_type_outsideTransactionClearOutsideTransactionThrows() {\n        realm.delete(AllTypes.CLASS_NAME);\n    }\n\n    @Test\n    public void delete_type() {\n        realm.beginTransaction();\n        realm.createObject(AllTypes.CLASS_NAME);\n        realm.commitTransaction();\n\n        assertEquals(1, realm.where(AllTypes.CLASS_NAME).count());\n        realm.beginTransaction();\n        realm.delete(AllTypes.CLASS_NAME);\n        realm.commitTransaction();\n        assertEquals(0, realm.where(AllTypes.CLASS_NAME).count());\n    }\n\n    @Test(expected = IllegalArgumentException.class)\n    public void executeTransaction_null() {\n        realm.executeTransaction(null);\n    }\n\n    @Test\n    public void executeTransaction() {\n        assertEquals(0, realm.where(Owner.CLASS_NAME).count());\n        realm.executeTransaction(new DynamicRealm.Transaction() {\n            @Override\n            public void execute(DynamicRealm realm) {\n                DynamicRealmObject owner = realm.createObject(Owner.CLASS_NAME);\n                owner.setString(\"name\", \"Owner\");\n            }\n        });\n\n        RealmResults<DynamicRealmObject> allObjects = realm.where(Owner.CLASS_NAME).findAll();\n        assertEquals(1, allObjects.size());\n        assertEquals(\"Owner\", allObjects.get(0).getString(\"name\"));\n    }\n\n    @Test\n    public void executeTransaction_cancelled() {\n        final AtomicReference<RuntimeException> thrownException = new AtomicReference<RuntimeException>(null);\n\n        assertEquals(0, realm.where(Owner.CLASS_NAME).count());\n        try {\n            realm.executeTransaction(new DynamicRealm.Transaction() {\n                @Override\n                public void execute(DynamicRealm realm) {\n                    DynamicRealmObject owner = realm.createObject(Owner.CLASS_NAME);\n                    owner.setString(\"name\", \"Owner\");\n                    thrownException.set(new RuntimeException(\"Boom\"));\n                    throw thrownException.get();\n                }\n            });\n        } catch (RuntimeException e) {\n            //noinspection ThrowableResultOfMethodCallIgnored\n            assertTrue(e == thrownException.get());\n        }\n        assertEquals(0, realm.where(Owner.CLASS_NAME).count());\n    }\n\n    @Test\n    public void executeTransaction_warningIfManuallyCancelled() {\n        assertEquals(0, realm.where(\"Owner\").count());\n        TestHelper.TestLogger testLogger = new TestHelper.TestLogger();\n        try {\n            RealmLog.add(testLogger);\n            realm.executeTransaction(new DynamicRealm.Transaction() {\n                @Override\n                public void execute(DynamicRealm realm) {\n                    DynamicRealmObject owner = realm.createObject(\"Owner\");\n                    owner.setString(\"name\", \"Owner\");\n                    realm.cancelTransaction();\n                    throw new RuntimeException(\"Boom\");\n                }\n            });\n        } catch (RuntimeException ignored) {\n            // Ensures that we pass a valuable error message to the logger for developers.\n            assertEquals(\"Could not cancel transaction, not currently in a transaction.\", testLogger.message);\n        } finally {\n            RealmLog.remove(testLogger);\n        }\n        assertEquals(0, realm.where(\"Owner\").count());\n    }\n\n    @Test\n    @UiThreadTest\n    public void executeTransaction_mainThreadWritesAllowed() {\n        RealmConfiguration configuration = configFactory.createConfigurationBuilder()\n                .allowWritesOnUiThread(true)\n                .name(\"ui_realm\")\n                .build();\n\n        // Initializes schema. DynamicRealm will not do that, so let a normal Realm create the file first.\n        Realm.getInstance(configuration).close();\n\n        DynamicRealm uiRealm = DynamicRealm.getInstance(configuration);\n        uiRealm.executeTransaction(new DynamicRealm.Transaction() {\n            @Override\n            public void execute(DynamicRealm realm) {\n                DynamicRealmObject owner = realm.createObject(Owner.CLASS_NAME);\n                owner.setString(\"name\", \"Mortimer Smith\");\n            }\n        });\n\n        RealmResults<DynamicRealmObject> results = uiRealm.where(Owner.CLASS_NAME).equalTo(\"name\", \"Mortimer Smith\").findAll();\n        assertEquals(1, results.size());\n        assertNotNull(results.first());\n        assertEquals(\"Mortimer Smith\", Objects.requireNonNull(results.first()).getString(Dog.FIELD_NAME));\n\n        uiRealm.close();\n    }\n\n    @Test\n    @UiThreadTest\n    public void executeTransaction_mainThreadWritesNotAllowed() {\n        RealmConfiguration configuration = configFactory.createConfigurationBuilder()\n                .allowWritesOnUiThread(false)\n                .name(\"ui_realm\")\n                .build();\n\n        // Initializes schema. DynamicRealm will not do that, so let a normal Realm create the file first.\n        Realm.getInstance(configuration).close();\n\n        // Try-with-resources\n        try (DynamicRealm uiRealm = DynamicRealm.getInstance(configuration);) {\n            uiRealm.executeTransaction(new DynamicRealm.Transaction() {\n                @Override\n                public void execute(DynamicRealm realm) {\n                    // no-op\n                }\n            });\n            fail(\"the call to executeTransaction should have failed, this line should not be reached.\");\n        } catch (RealmException e) {\n            assertTrue(Objects.requireNonNull(e.getMessage()).contains(\"allowWritesOnUiThread\"));\n        }\n    }\n\n    @Test\n    public void findFirst() {\n        populateTestRealm(realm, 10);\n        final DynamicRealmObject allTypes = realm.where(AllTypes.CLASS_NAME)\n                .between(AllTypes.FIELD_LONG, 4, 9)\n                .findFirst();\n        assertEquals(\"test data 4\", allTypes.getString(AllTypes.FIELD_STRING));\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void findFirstAsync() {\n        final DynamicRealm dynamicRealm = initializeDynamicRealm();\n        final DynamicRealmObject allTypes = dynamicRealm.where(AllTypes.CLASS_NAME)\n                .between(AllTypes.FIELD_LONG, 4, 9)\n                .findFirstAsync();\n        assertFalse(allTypes.isLoaded());\n        looperThread.keepStrongReference(allTypes);\n        allTypes.addChangeListener(new RealmChangeListener<DynamicRealmObject>() {\n            @Override\n            public void onChange(DynamicRealmObject object) {\n                assertEquals(\"test data 4\", allTypes.getString(AllTypes.FIELD_STRING));\n                dynamicRealm.close();\n                looperThread.testComplete();\n            }\n        });\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void findAllAsync() {\n        final DynamicRealm dynamicRealm = initializeDynamicRealm();\n        final RealmResults<DynamicRealmObject> allTypes = dynamicRealm.where(AllTypes.CLASS_NAME)\n                .between(AllTypes.FIELD_LONG, 4, 9)\n                .findAllAsync();\n\n        assertFalse(allTypes.isLoaded());\n        assertEquals(0, allTypes.size());\n\n        allTypes.addChangeListener(new RealmChangeListener<RealmResults<DynamicRealmObject>>() {\n            @Override\n            public void onChange(RealmResults<DynamicRealmObject> object) {\n                assertEquals(6, allTypes.size());\n                for (int i = 0; i < allTypes.size(); i++) {\n                    assertEquals(\"test data \" + (4 + i), allTypes.get(i).getString(AllTypes.FIELD_STRING));\n                }\n                dynamicRealm.close();\n                looperThread.testComplete();\n            }\n        });\n        looperThread.keepStrongReference(allTypes);\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void sort_async() {\n        final DynamicRealm dynamicRealm = initializeDynamicRealm();\n        final RealmResults<DynamicRealmObject> allTypes = dynamicRealm.where(AllTypes.CLASS_NAME)\n                .between(AllTypes.FIELD_LONG, 0, 4)\n                .sort(AllTypes.FIELD_STRING, Sort.DESCENDING)\n                .findAllAsync();\n        assertFalse(allTypes.isLoaded());\n        assertEquals(0, allTypes.size());\n\n        allTypes.addChangeListener(new RealmChangeListener<RealmResults<DynamicRealmObject>>() {\n            @Override\n            public void onChange(RealmResults<DynamicRealmObject> object) {\n                assertEquals(5, allTypes.size());\n                for (int i = 0; i < 5; i++) {\n                    int iteration = (4 - i);\n                    assertEquals(\"test data \" + iteration, allTypes.get(4 - iteration).getString(AllTypes.FIELD_STRING));\n                }\n                dynamicRealm.close();\n                looperThread.testComplete();\n            }\n        });\n        looperThread.keepStrongReference(allTypes);\n    }\n\n    // Initializes a Dynamic Realm used by the *Async tests and keeps it ref in the looperThread.\n    private DynamicRealm initializeDynamicRealm() {\n        RealmConfiguration defaultConfig = looperThread.getConfiguration();\n        final DynamicRealm dynamicRealm = DynamicRealm.getInstance(defaultConfig);\n        populateTestRealm(dynamicRealm, 10);\n        looperThread.keepStrongReference(dynamicRealm);\n        return dynamicRealm;\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void sort_async_usingMultipleFields() {\n        final DynamicRealm dynamicRealm = initializeDynamicRealm();\n\n        dynamicRealm.setAutoRefresh(false);\n        dynamicRealm.beginTransaction();\n        dynamicRealm.delete(AllTypes.CLASS_NAME);\n        for (int i = 0; i < 5; ) {\n            DynamicRealmObject allTypes = dynamicRealm.createObject(AllTypes.CLASS_NAME);\n            allTypes.set(AllTypes.FIELD_LONG, i);\n            allTypes.set(AllTypes.FIELD_STRING, \"data \" + i % 3);\n\n            allTypes = dynamicRealm.createObject(AllTypes.CLASS_NAME);\n            allTypes.set(AllTypes.FIELD_LONG, i);\n            allTypes.set(AllTypes.FIELD_STRING, \"data \" + (++i % 3));\n        }\n        dynamicRealm.commitTransaction();\n        dynamicRealm.setAutoRefresh(true);\n\n        // Sorts first set by using: String[ASC], Long[DESC].\n        final RealmResults<DynamicRealmObject> realmResults1 = dynamicRealm.where(AllTypes.CLASS_NAME)\n                .sort(\n                        new String[]{AllTypes.FIELD_STRING, AllTypes.FIELD_LONG},\n                        new Sort[]{Sort.ASCENDING, Sort.DESCENDING}\n                )\n                .findAllAsync();\n\n        // Sorts second set by using: String[DESC], Long[ASC].\n        final RealmResults<DynamicRealmObject> realmResults2 = dynamicRealm.where(AllTypes.CLASS_NAME)\n                .between(AllTypes.FIELD_LONG, 0, 5)\n                .sort(\n                        new String[]{AllTypes.FIELD_STRING, AllTypes.FIELD_LONG},\n                        new Sort[]{Sort.DESCENDING, Sort.ASCENDING}\n                )\n                .findAllAsync();\n\n        final Runnable signalCallbackDone = new Runnable() {\n            final AtomicInteger callbacksDone = new AtomicInteger(2);\n            @Override\n            public void run() {\n                if (callbacksDone.decrementAndGet() == 0) {\n                    dynamicRealm.close();\n                    looperThread.testComplete();\n                }\n            }\n        };\n\n        realmResults1.addChangeListener(new RealmChangeListener<RealmResults<DynamicRealmObject>>() {\n            @Override\n            public void onChange(RealmResults<DynamicRealmObject> object) {\n                assertEquals(\"data 0\", realmResults1.get(0).get(AllTypes.FIELD_STRING));\n                assertEquals(3L, realmResults1.get(0).<Long> get(AllTypes.FIELD_LONG).longValue());\n                assertEquals(\"data 0\", realmResults1.get(1).get(AllTypes.FIELD_STRING));\n                assertEquals(2L, realmResults1.get(1).<Long> get(AllTypes.FIELD_LONG).longValue());\n                assertEquals(\"data 0\", realmResults1.get(2).get(AllTypes.FIELD_STRING));\n                assertEquals(0L, realmResults1.get(2).<Long> get(AllTypes.FIELD_LONG).longValue());\n\n                assertEquals(\"data 1\", realmResults1.get(3).get(AllTypes.FIELD_STRING));\n                assertEquals(4L, realmResults1.get(3).<Long> get(AllTypes.FIELD_LONG).longValue());\n                assertEquals(\"data 1\", realmResults1.get(4).get(AllTypes.FIELD_STRING));\n                assertEquals(3L, realmResults1.get(4).<Long> get(AllTypes.FIELD_LONG).longValue());\n                assertEquals(\"data 1\", realmResults1.get(5).get(AllTypes.FIELD_STRING));\n                assertEquals(1L, realmResults1.get(5).<Long> get(AllTypes.FIELD_LONG).longValue());\n                assertEquals(\"data 1\", realmResults1.get(6).get(AllTypes.FIELD_STRING));\n                assertEquals(0L, realmResults1.get(6).<Long> get(AllTypes.FIELD_LONG).longValue());\n\n                assertEquals(\"data 2\", realmResults1.get(7).get(AllTypes.FIELD_STRING));\n                assertEquals(4L, realmResults1.get(7).<Long> get(AllTypes.FIELD_LONG).longValue());\n                assertEquals(\"data 2\", realmResults1.get(8).get(AllTypes.FIELD_STRING));\n                assertEquals(2L, realmResults1.get(8).<Long> get(AllTypes.FIELD_LONG).longValue());\n                assertEquals(\"data 2\", realmResults1.get(9).get(AllTypes.FIELD_STRING));\n                assertEquals(1L, realmResults1.get(9).<Long> get(AllTypes.FIELD_LONG).longValue());\n\n                signalCallbackDone.run();\n            }\n        });\n\n        realmResults2.addChangeListener(new RealmChangeListener<RealmResults<DynamicRealmObject>>() {\n            @Override\n            public void onChange(RealmResults<DynamicRealmObject> object) {\n                assertEquals(\"data 2\", realmResults2.get(0).get(AllTypes.FIELD_STRING));\n                assertEquals(1L, realmResults2.get(0).<Long> get(AllTypes.FIELD_LONG).longValue());\n                assertEquals(\"data 2\", realmResults2.get(1).get(AllTypes.FIELD_STRING));\n                assertEquals(2L, realmResults2.get(1).<Long> get(AllTypes.FIELD_LONG).longValue());\n                assertEquals(\"data 2\", realmResults2.get(2).get(AllTypes.FIELD_STRING));\n                assertEquals(4L, realmResults2.get(2).<Long> get(AllTypes.FIELD_LONG).longValue());\n\n                assertEquals(\"data 1\", realmResults2.get(3).get(AllTypes.FIELD_STRING));\n                assertEquals(0L, realmResults2.get(3).<Long> get(AllTypes.FIELD_LONG).longValue());\n                assertEquals(\"data 1\", realmResults2.get(4).get(AllTypes.FIELD_STRING));\n                assertEquals(1L, realmResults2.get(4).<Long> get(AllTypes.FIELD_LONG).longValue());\n                assertEquals(\"data 1\", realmResults2.get(5).get(AllTypes.FIELD_STRING));\n                assertEquals(3L, realmResults2.get(5).<Long> get(AllTypes.FIELD_LONG).longValue());\n                assertEquals(\"data 1\", realmResults2.get(6).get(AllTypes.FIELD_STRING));\n                assertEquals(4L, realmResults2.get(6).<Long> get(AllTypes.FIELD_LONG).longValue());\n\n                assertEquals(\"data 0\", realmResults2.get(7).get(AllTypes.FIELD_STRING));\n                assertEquals(0L, realmResults2.get(7).<Long> get(AllTypes.FIELD_LONG).longValue());\n                assertEquals(\"data 0\", realmResults2.get(8).get(AllTypes.FIELD_STRING));\n                assertEquals(2L, realmResults2.get(8).<Long> get(AllTypes.FIELD_LONG).longValue());\n                assertEquals(\"data 0\", realmResults2.get(9).get(AllTypes.FIELD_STRING));\n                assertEquals(3L, realmResults2.get(9).<Long> get(AllTypes.FIELD_LONG).longValue());\n\n                signalCallbackDone.run();\n            }\n        });\n        looperThread.keepStrongReference(realmResults1);\n        looperThread.keepStrongReference(realmResults2);\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void accessingDynamicRealmObjectBeforeAsyncQueryCompleted() {\n        final DynamicRealm dynamicRealm = initializeDynamicRealm();\n        final DynamicRealmObject dynamicRealmObject = dynamicRealm.where(AllTypes.CLASS_NAME)\n                .between(AllTypes.FIELD_LONG, 4, 9)\n                .findFirstAsync();\n        assertFalse(dynamicRealmObject.isLoaded());\n        assertFalse(dynamicRealmObject.isValid());\n        try {\n            dynamicRealmObject.getObject(AllTypes.FIELD_BINARY);\n            fail(\"trying to access a DynamicRealmObject property should throw\");\n        } catch (IllegalStateException ignored) {\n        } finally {\n            dynamicRealm.close();\n            looperThread.testComplete();\n        }\n    }\n\n    @Test\n    public void deleteAll() {\n        realm.beginTransaction();\n        realm.createObject(AllTypes.CLASS_NAME);\n        DynamicRealmObject cat = realm.createObject(Cat.CLASS_NAME);\n        DynamicRealmObject owner = realm.createObject(Owner.CLASS_NAME);\n        owner.setObject(\"cat\", cat);\n        realm.getSchema().create(\"TestRemoveAll\").addField(\"Field1\", String.class);\n        realm.createObject(\"TestRemoveAll\");\n        realm.commitTransaction();\n\n        assertEquals(1, realm.where(AllTypes.CLASS_NAME).count());\n        assertEquals(1, realm.where(Owner.CLASS_NAME).count());\n        assertEquals(1, realm.where(Cat.CLASS_NAME).count());\n        assertEquals(1, realm.where(\"TestRemoveAll\").count());\n\n        realm.beginTransaction();\n        realm.deleteAll();\n        realm.commitTransaction();\n\n        assertEquals(0, realm.where(AllTypes.CLASS_NAME).count());\n        assertEquals(0, realm.where(Owner.CLASS_NAME).count());\n        assertEquals(0, realm.where(Cat.CLASS_NAME).count());\n        assertEquals(0, realm.where(\"TestRemoveAll\").count());\n        assertTrue(realm.isEmpty());\n    }\n\n    @Test\n    public void realmListRemoveAllFromRealm() {\n        populateTestRealm(realm, 1);\n        RealmList<DynamicRealmObject> list = realm.where(AllTypes.CLASS_NAME).findFirst().getList(AllTypes.FIELD_REALMLIST);\n        assertEquals(2, list.size());\n\n        realm.beginTransaction();\n        list.deleteAllFromRealm();\n        realm.commitTransaction();\n\n        assertEquals(0, list.size());\n        assertEquals(0, realm.where(Dog.CLASS_NAME).count());\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void addChangeListener_throwOnAddingNullListenerFromLooperThread() {\n        final DynamicRealm dynamicRealm = initializeDynamicRealm();\n\n        //noinspection TryFinallyCanBeTryWithResources\n        try {\n            dynamicRealm.addChangeListener(null);\n            fail(\"adding null change listener must throw an exception.\");\n        } catch (IllegalArgumentException ignore) {\n        } finally {\n            dynamicRealm.close();\n            looperThread.testComplete();\n        }\n    }\n\n    @Test\n    public void addChangeListener_throwOnAddingNullListenerFromNonLooperThread() throws Throwable {\n        TestHelper.executeOnNonLooperThread(new TestHelper.Task() {\n            @Override\n            public void run() throws Exception {\n                final DynamicRealm dynamicRealm = DynamicRealm.getInstance(defaultConfig);\n\n                //noinspection TryFinallyCanBeTryWithResources\n                try {\n                    dynamicRealm.addChangeListener(null);\n                    fail(\"adding null change listener must throw an exception.\");\n                } catch (IllegalArgumentException ignore) {\n                } finally {\n                    dynamicRealm.close();\n                }\n            }\n        });\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void removeChangeListener_throwOnRemovingNullListenerFromLooperThread() {\n        final DynamicRealm dynamicRealm = initializeDynamicRealm();\n\n        //noinspection TryFinallyCanBeTryWithResources\n        try {\n            dynamicRealm.removeChangeListener(null);\n            fail(\"removing null change listener must throw an exception.\");\n        } catch (IllegalArgumentException ignore) {\n        } finally {\n            dynamicRealm.close();\n            looperThread.testComplete();\n        }\n    }\n\n    @Test\n    public void removeChangeListener_throwOnRemovingNullListenerFromNonLooperThread() throws Throwable {\n        TestHelper.executeOnNonLooperThread(new TestHelper.Task() {\n            @Override\n            public void run() throws Exception {\n                final DynamicRealm dynamicRealm = DynamicRealm.getInstance(defaultConfig);\n\n                //noinspection TryFinallyCanBeTryWithResources\n                try {\n                    dynamicRealm.removeChangeListener(null);\n                    fail(\"removing null change listener must throw an exception.\");\n                } catch (IllegalArgumentException ignore) {\n                } finally {\n                    dynamicRealm.close();\n                }\n            }\n        });\n    }\n\n    @Test\n    public void equalTo_noFieldObjectShouldThrow() {\n        final String className = \"NoField\";\n        RealmConfiguration emptyConfig = configFactory.createConfiguration(\"empty\");\n        DynamicRealm dynamicRealm = DynamicRealm.getInstance(emptyConfig);\n        dynamicRealm.beginTransaction();\n        dynamicRealm.getSchema().create(className);\n        dynamicRealm.commitTransaction();\n\n        thrown.expect(IllegalArgumentException.class);\n        thrown.expectMessage(\"Illegal Argument: 'NoField' has no property 'nonExisting'\");\n        dynamicRealm.where(className).equalTo(\"nonExisting\", 1);\n    }\n\n    @Test(expected = IllegalStateException.class)\n    public void getInstanceAsync_nonLooperThreadShouldThrow() {\n        DynamicRealm.getInstanceAsync(defaultConfig, new DynamicRealm.Callback() {\n            @Override\n            public void onSuccess(DynamicRealm realm) {\n                fail();\n            }\n        });\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void getInstanceAsync_nullConfigShouldThrow() {\n        try {\n            //noinspection ConstantConditions\n            DynamicRealm.getInstanceAsync(null, new DynamicRealm.Callback() {\n                @Override\n                public void onSuccess(DynamicRealm realm) {\n                    fail();\n                }\n            });\n        } catch (IllegalArgumentException ignored) {\n        }\n        looperThread.testComplete();\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void getInstanceAsync_nullCallbackShouldThrow() {\n        try {\n            //noinspection ConstantConditions\n            DynamicRealm.getInstanceAsync(defaultConfig, null);\n        } catch (IllegalArgumentException ignored) {\n        }\n        looperThread.testComplete();\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/FrozenObjectsTests.java",
    "content": "/*\n * Copyright 2019 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 */\npackage io.realm;\n\nimport androidx.test.ext.junit.runners.AndroidJUnit4;\n\nimport org.bson.types.Decimal128;\nimport org.bson.types.ObjectId;\nimport org.junit.After;\nimport org.junit.Before;\nimport org.junit.Rule;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\n\nimport java.math.BigDecimal;\nimport java.util.Arrays;\n\nimport javax.annotation.Nullable;\n\nimport io.realm.entities.AllJavaTypes;\nimport io.realm.entities.AllTypes;\nimport io.realm.entities.Dog;\nimport io.realm.rule.RunInLooperThread;\nimport io.realm.rule.RunTestInLooperThread;\n\nimport static org.junit.Assert.assertEquals;\nimport static org.junit.Assert.assertFalse;\nimport static org.junit.Assert.assertNotEquals;\nimport static org.junit.Assert.assertTrue;\nimport static org.junit.Assert.fail;\n\n/**\n * Class testing that the frozen objects feature works correctly.\n */\n@RunWith(AndroidJUnit4.class)\npublic class FrozenObjectsTests {\n\n    private static final int DATA_SIZE = 10;\n\n    @Rule\n    public final TestRealmConfigurationFactory configFactory = new TestRealmConfigurationFactory();\n    @Rule\n    public final RunInLooperThread looperThread = new RunInLooperThread();\n\n    private RealmConfiguration realmConfig;\n    private Realm realm;\n    private Realm frozenRealm;\n\n    @Before\n    public void setUp() {\n        realmConfig = configFactory.createConfiguration();\n        realm = Realm.getInstance(realmConfig);\n        frozenRealm = realm.freeze();\n    }\n\n    @After\n    public void tearDown() {\n        realm.close(); // This also closes the frozen Realm\n    }\n\n    @Test\n    public void deleteFrozenRealm() {\n        RealmConfiguration config = configFactory.createConfigurationBuilder().name(\"deletable.realm\").build();\n        Realm realm = Realm.getInstance(config);\n        frozenRealm = realm.freeze();\n        try {\n            Realm.deleteRealm(config);\n        } catch (IllegalStateException ignore) {\n        }\n        realm.close();\n        assertTrue(Realm.deleteRealm(config));\n    }\n\n    @Test\n    public void freezeRealm() {\n        assertFalse(realm.isFrozen());\n        Realm frozenRealm = realm.freeze();\n        assertEquals(realm.getPath(), frozenRealm.getPath());\n        assertTrue(frozenRealm.isFrozen());\n        frozenRealm.close();\n    }\n\n    @Test\n    public void freezeDynamicRealm() {\n        DynamicRealm dynamicRealm = DynamicRealm.getInstance(realmConfig);\n        DynamicRealm frozenDynamicRealm = dynamicRealm.freeze();\n        assertEquals(dynamicRealm.getPath(), frozenDynamicRealm.getPath());\n        assertTrue(frozenRealm.isFrozen());\n        dynamicRealm.close();\n        assertFalse(frozenDynamicRealm.isClosed());\n        frozenDynamicRealm.close();\n    }\n\n    @Test\n    public void frozenRealmsCannotStartTransactions() {\n        try {\n            frozenRealm.beginTransaction();\n            fail();\n        } catch (IllegalStateException ignore) {\n        }\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void addingRealmChangeListenerThrows() {\n        try {\n            frozenRealm.addChangeListener(new RealmChangeListener<Realm>() {\n                @Override\n                public void onChange(Realm realm) {\n                }\n            });\n            fail();\n        } catch (IllegalStateException ignore) {\n            looperThread.testComplete();\n        }\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void addingResultsChangeListenerThrows() {\n        RealmResults<AllTypes> results = frozenRealm.where(AllTypes.class).findAll();\n        try {\n            results.addChangeListener(new OrderedRealmCollectionChangeListener<RealmResults<AllTypes>>() {\n                @Override\n                public void onChange(RealmResults<AllTypes> allTypes, OrderedCollectionChangeSet changeSet) {\n                }\n            });\n            fail();\n        } catch (IllegalStateException ignore) {\n            looperThread.testComplete();\n        }\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void addingListChangeListenerThrows() {\n        realm.executeTransaction(r -> {\n            r.createObject(AllTypes.class);\n        });\n\n        Realm frozenRealm = realm.freeze();\n        AllTypes obj = frozenRealm.where(AllTypes.class).findFirst();\n        try {\n            obj.getColumnStringList().addChangeListener(new OrderedRealmCollectionChangeListener<RealmList<String>>() {\n                @Override\n                public void onChange(RealmList<String> strings, OrderedCollectionChangeSet changeSet) {\n                }\n            });\n            fail();\n        } catch (IllegalStateException ignore) {\n        }\n\n        try {\n            obj.getColumnRealmList().addChangeListener(new OrderedRealmCollectionChangeListener<RealmList<Dog>>() {\n                @Override\n                public void onChange(RealmList<Dog> dogs, OrderedCollectionChangeSet changeSet) {\n                }\n            });\n            fail();\n        } catch (IllegalStateException ignore) {\n        }\n        frozenRealm.close();\n        looperThread.testComplete();\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void addingObjectChangeListenerThrows() {\n        realm.executeTransaction(r -> {\n            r.createObject(AllTypes.class);\n        });\n        Realm frozenRealm = realm.freeze();\n        AllTypes obj = frozenRealm.where(AllTypes.class).findFirst();\n        try {\n            obj.addChangeListener(new RealmObjectChangeListener<RealmModel>() {\n                @Override\n                public void onChange(RealmModel realmModel, @Nullable ObjectChangeSet changeSet) {\n\n                }\n            });\n            fail();\n        } catch (IllegalStateException ignore) {\n            frozenRealm.close();\n            looperThread.testComplete();\n        }\n    }\n\n    @Test\n    public void removingChangeListeners() {\n        frozenRealm.removeAllChangeListeners();\n        frozenRealm.removeChangeListener(new RealmChangeListener<Realm>() {\n            @Override\n            public void onChange(Realm realm) {\n            }\n        });\n    }\n\n    @Test\n    public void refreshThrows() {\n        try {\n            frozenRealm.refresh();\n            fail();\n        } catch (IllegalStateException ignore) {\n        }\n    }\n\n    @Test\n    public void writeToFrozenObjectThrows() {\n        realm.beginTransaction();\n        try {\n            frozenRealm.createObject(AllTypes.class);\n            fail();\n        } catch (IllegalStateException ignore) {\n        } finally {\n            realm.cancelTransaction();\n        }\n\n        realm.beginTransaction();\n        try {\n            frozenRealm.insert(new AllTypes());\n            fail();\n        } catch (IllegalStateException ignore) {\n        } finally {\n            realm.cancelTransaction();\n        }\n\n        realm.beginTransaction();\n        try {\n            frozenRealm.copyToRealm(new AllTypes());\n            fail();\n        } catch (IllegalStateException ignore) {\n        } finally {\n            realm.cancelTransaction();\n        }\n\n        realm.executeTransaction(r -> {\n            r.createObject(AllTypes.class);\n        });\n        Realm frozenRealm = realm.freeze();\n        AllTypes obj = frozenRealm.where(AllTypes.class).findFirst();\n        realm.beginTransaction();\n        try {\n            obj.setColumnString(\"Foo\");\n            fail();\n        } catch (IllegalStateException ignore) {\n        } finally {\n            realm.cancelTransaction();\n        }\n\n        try {\n            frozenRealm.executeTransactionAsync(r -> {  /* Do nothing */ });\n        } catch (IllegalStateException ignore) {\n        } finally {\n            frozenRealm.close();\n        }\n    }\n\n    @Test\n    public void freezingPinsRealmVersion() {\n        assertTrue(frozenRealm.isEmpty());\n        assertTrue(realm.isEmpty());\n\n        realm.executeTransaction(r -> {\n            r.createObject(AllTypes.class);\n        });\n\n        assertTrue(frozenRealm.isEmpty());\n        assertFalse(realm.isEmpty());\n    }\n\n    @Test\n    public void readFrozenRealmAcrossThreads() throws InterruptedException {\n        Thread t = new Thread(() -> {\n            assertTrue(frozenRealm.isEmpty());\n            assertTrue(frozenRealm.isFrozen());\n        });\n        t.start();\n        t.join();\n    }\n\n    @Test\n    public void queryFrozenRealmAcrossThreads() throws InterruptedException {\n        final Realm frozenRealm = createDataForFrozenRealm(DATA_SIZE);\n        Thread t = new Thread(() -> {\n            RealmResults<AllTypes> results = frozenRealm.where(AllTypes.class).findAll();\n            assertEquals(DATA_SIZE, results.size());\n        });\n        t.start();\n        t.join();\n    }\n\n    @Test\n    public void canReadFrozenResultsAcrossThreads() throws InterruptedException {\n        Realm frozenRealm = createDataForFrozenRealm(DATA_SIZE);\n        RealmResults<AllTypes> results = frozenRealm.where(AllTypes.class).findAll();\n        Thread t = new Thread(() -> {\n            assertEquals(DATA_SIZE, results.size());\n            assertTrue(results.isFrozen());\n        });\n        t.start();\n        t.join();\n    }\n\n    @Test\n    public void canReadFrozenListsAcrossThreads() throws InterruptedException {\n        Realm frozenRealm = createDataForFrozenRealm(DATA_SIZE);\n        RealmList<Dog> list = frozenRealm.where(AllTypes.class).findFirst().getColumnRealmList();\n        Thread t = new Thread(() -> {\n            assertEquals(5, list.size());\n            assertTrue(list.isFrozen());\n        });\n        t.start();\n        t.join();\n    }\n\n    @Test\n    public void canReadFrozenObjectsAcrossThreads() throws InterruptedException {\n        Realm frozenRealm = createDataForFrozenRealm(DATA_SIZE);\n        AllTypes obj = frozenRealm.where(AllTypes.class).sort(AllTypes.FIELD_LONG).findFirst();\n        Thread t = new Thread(() -> {\n            assertEquals(0, obj.getColumnLong());\n            assertEquals(\"String 0\", obj.getColumnString());\n            assertTrue(obj.isFrozen());\n        });\n        t.start();\n        t.join();\n    }\n\n    @Test\n    public void frozenObjectsReturnsFrozenRealms() {\n        Realm frozenRealm = createDataForFrozenRealm(DATA_SIZE);\n        RealmResults<AllTypes> results = frozenRealm.where(AllTypes.class).findAll();\n        AllTypes obj = results.first();\n        RealmList<Dog> list = obj.getColumnRealmList();\n\n        assertTrue(results.getRealm().isFrozen());\n        assertTrue(obj.getRealm().isFrozen());\n        assertTrue(list.getRealm().isFrozen());\n    }\n\n    @Test\n    public void freezeResults() throws InterruptedException {\n        Realm realm = createDataForLiveRealm(DATA_SIZE);\n        RealmResults<AllTypes> results = realm.where(AllTypes.class).findAll();\n        RealmResults<AllTypes> frozenResults = results.freeze();\n        assertEquals(DATA_SIZE, frozenResults.size());\n        assertTrue(frozenResults.isFrozen());\n        assertTrue(frozenResults.isValid());\n        assertTrue(frozenResults.isLoaded());\n\n        Thread t = new Thread(() -> {\n            assertEquals(DATA_SIZE, frozenResults.size());\n            assertTrue(frozenResults.isFrozen());\n            assertEquals(1, frozenResults.where().equalTo(AllTypes.FIELD_LONG, 1).findAll().size());\n        });\n        t.start();\n        t.join();\n    }\n\n    @Test\n    public void freezeDynamicResults() throws InterruptedException {\n        Realm realm = createDataForLiveRealm(DATA_SIZE);\n        DynamicRealm dynRealm = DynamicRealm.getInstance(realm.getConfiguration());\n        RealmResults<DynamicRealmObject> results = dynRealm.where(AllTypes.CLASS_NAME).findAll();\n        RealmResults<DynamicRealmObject> frozenResults = results.freeze();\n        assertEquals(DATA_SIZE, frozenResults.size());\n        assertTrue(frozenResults.isFrozen());\n        assertTrue(frozenResults.isValid());\n        assertTrue(frozenResults.isLoaded());\n\n        Thread t = new Thread(() -> {\n            assertEquals(DATA_SIZE, frozenResults.size());\n            assertTrue(frozenResults.isFrozen());\n            assertEquals(1, frozenResults.where().equalTo(AllTypes.FIELD_LONG, 1).findAll().size());\n        });\n        t.start();\n        t.join();\n        dynRealm.close();\n    }\n\n    @Test\n    public void freezeSnapshot() {\n        Realm realm = createDataForLiveRealm(DATA_SIZE);\n        RealmResults<AllTypes> results = realm.where(AllTypes.class).findAll();\n        OrderedRealmCollectionSnapshot<AllTypes> snapshot = results.createSnapshot();\n        try {\n            snapshot.freeze();\n            fail();\n        } catch(UnsupportedOperationException ignored) {\n        }\n    }\n\n    @Test\n    public void freezeDynamicSnapshot() {\n        Realm realm = createDataForLiveRealm(DATA_SIZE);\n        DynamicRealm dynRealm = DynamicRealm.getInstance(realm.getConfiguration());\n        RealmResults<DynamicRealmObject> results = dynRealm.where(AllTypes.CLASS_NAME).findAll();\n        OrderedRealmCollectionSnapshot<DynamicRealmObject> snapshot = results.createSnapshot();\n        try {\n            snapshot.freeze();\n            fail();\n        } catch(UnsupportedOperationException ignored) {\n        } finally {\n            dynRealm.close();\n        }\n    }\n\n    @Test\n    public void freezeLists() throws InterruptedException {\n        Realm realm = createDataForLiveRealm(DATA_SIZE);\n        AllTypes obj = realm.where(AllTypes.class).findFirst();\n        RealmList<Dog> frozenObjectList = obj.getColumnRealmList().freeze();\n        RealmList<String> frozenStringList = obj.getColumnStringList().freeze();\n        Thread t = new Thread(() -> {\n            assertEquals(5, frozenObjectList.size());\n            assertTrue(frozenObjectList.isFrozen());\n            assertEquals(1, frozenObjectList.where().equalTo(Dog.FIELD_NAME, \"Dog 1\").findAll().size());\n\n            assertEquals(3, frozenStringList.size());\n            assertTrue(frozenStringList.isFrozen());\n            assertEquals(\"Foo\", frozenStringList.first());\n        });\n        t.start();\n        t.join();\n    }\n\n    @Test\n    public void freezeDynamicList() throws InterruptedException {\n        Realm realm = createDataForLiveRealm(DATA_SIZE);\n        DynamicRealm dynRealm = DynamicRealm.getInstance(realm.getConfiguration());\n        DynamicRealmObject obj = dynRealm.where(AllTypes.CLASS_NAME).findFirst();\n        RealmList<DynamicRealmObject> frozenObjectList = obj.getList(AllTypes.FIELD_REALMLIST).freeze();\n        RealmList<String> frozenStringList = obj.getList(AllTypes.FIELD_STRING_LIST, String.class).freeze();\n        Thread t = new Thread(() -> {\n            assertEquals(5, frozenObjectList.size());\n            assertTrue(frozenObjectList.isFrozen());\n            assertEquals(1, frozenObjectList.where().equalTo(Dog.FIELD_NAME, \"Dog 1\").findAll().size());\n\n            assertEquals(3, frozenStringList.size());\n            assertTrue(frozenStringList.isFrozen());\n            assertEquals(\"Foo\", frozenStringList.first());\n        });\n        t.start();\n        t.join();\n        dynRealm.close();\n    }\n\n    @Test\n    public void freezeObject() throws InterruptedException {\n        Realm realm = createDataForLiveRealm(DATA_SIZE);\n        AllTypes obj = realm.where(AllTypes.class).sort(AllTypes.FIELD_LONG).findFirst();\n        AllTypes frozenObj = obj.freeze();\n        Thread t = new Thread(() -> {\n            assertTrue(frozenObj.isFrozen());\n            assertEquals(0, frozenObj.getColumnLong());\n            assertTrue(frozenObj.getColumnRealmList().isFrozen());\n            assertTrue(frozenObj.getColumnRealmObject().isFrozen());\n        });\n        t.start();\n        t.join();\n    }\n\n    @Test\n    public void freezeDynamicObject() throws InterruptedException {\n        Realm realm = createDataForLiveRealm(DATA_SIZE);\n        DynamicRealm dynRealm = DynamicRealm.getInstance(realm.getConfiguration());\n        DynamicRealmObject obj = dynRealm.where(AllTypes.CLASS_NAME).sort(AllTypes.FIELD_LONG).findFirst();\n        DynamicRealmObject frozenObj = obj.freeze();\n        Thread t = new Thread(() -> {\n            assertTrue(frozenObj.isFrozen());\n            assertEquals(0, frozenObj.getLong(AllTypes.FIELD_LONG));\n            assertTrue(frozenObj.getList(AllTypes.FIELD_REALMLIST).isFrozen());\n            assertTrue(frozenObj.getObject(AllTypes.FIELD_REALMOBJECT).isFrozen());\n        });\n        t.start();\n        t.join();\n        dynRealm.close();\n        assertTrue(Realm.getGlobalInstanceCount(realm.getConfiguration()) > 0);\n    }\n\n    @Test\n    public void freezeDeletedObject() {\n        Realm realm = createDataForLiveRealm(DATA_SIZE);\n        AllTypes obj = realm.where(AllTypes.class).sort(AllTypes.FIELD_LONG).findFirst();\n        realm.executeTransaction(r -> {\n            obj.deleteFromRealm();\n        });\n        AllTypes frozenObj = obj.freeze();\n        assertFalse(frozenObj.isValid());\n        assertTrue(frozenObj.isFrozen());\n        assertTrue(frozenObj.isLoaded());\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void freezePendingObject() {\n        Realm realm = createDataForLiveRealm(DATA_SIZE);\n        AllTypes obj = realm.where(AllTypes.class).sort(AllTypes.FIELD_LONG).findFirstAsync();\n\n        AllTypes frozenObj = obj.freeze();\n        assertFalse(frozenObj.isValid());\n        assertFalse(frozenObj.isLoaded());\n        assertTrue(frozenObj.isFrozen());\n        looperThread.testComplete();\n    }\n\n    @Test\n    public void frozenRealms_notEqualToLiveRealm() {\n        assertNotEquals(realm, frozenRealm);\n    }\n\n    @Test\n    public void frozenRealm_notEqualToFrozenRealmAtOtherVersion() {\n        realm.beginTransaction();\n        realm.commitTransaction();\n        Realm otherFrozenRealm = realm.freeze();\n        try {\n            assertNotEquals(frozenRealm, otherFrozenRealm);\n        } finally {\n            otherFrozenRealm.close();\n        }\n    }\n\n    @Test\n    public void frozenRealm_equalToFrozenRealmAtSameVersion() throws InterruptedException {\n        Realm otherFrozenRealm = realm.freeze();\n        assertEquals(frozenRealm, otherFrozenRealm); // Same thread\n\n        Thread t = new Thread(() -> {\n            Realm bgRealm = Realm.getInstance(realmConfig);\n            Realm otherThreadFrozenRealm = bgRealm.freeze();\n            try {\n                assertEquals(frozenRealm, otherThreadFrozenRealm);\n            } finally {\n                bgRealm.close();\n            }\n        });\n        t.start();\n        t.join();\n    }\n\n    @Test\n    public void frozenRealm_closeFromOtherThread() throws InterruptedException {\n        assertFalse(frozenRealm.isClosed());\n        Thread t = new Thread(() -> {\n            frozenRealm.close();\n            assertTrue(frozenRealm.isClosed());\n        });\n        t.start();\n        t.join();\n    }\n\n    @Test\n    public void copyToRealm() throws InterruptedException {\n        Realm realm = createDataForLiveRealm(DATA_SIZE);\n        AllTypes frozenObject = realm.where(AllTypes.class).sort(AllTypes.FIELD_LONG).findFirst().freeze();\n\n        Thread t = new Thread(() -> {\n            Realm bgRealm = Realm.getInstance(realm.getConfiguration());\n            bgRealm.beginTransaction();\n            AllTypes copiedObject = bgRealm.copyToRealm(frozenObject);\n            bgRealm.commitTransaction();\n\n            assertEquals(DATA_SIZE + 1, bgRealm.where(AllTypes.class).count());\n            assertEquals(frozenObject.getColumnLong(), copiedObject.getColumnLong());\n            assertEquals(frozenObject.getColumnString(), copiedObject.getColumnString());\n            assertEquals(frozenObject.getColumnRealmList().size(), copiedObject.getColumnRealmList().size());\n            bgRealm.close();\n        });\n        t.start();\n        t.join();\n    }\n\n    @Test\n    public void copyToRealmOrUpdate() throws InterruptedException {\n        realm.executeTransaction(r -> {\n            r.createObject(AllJavaTypes.class, 42);\n        });\n        AllJavaTypes frozenObject = realm.where(AllJavaTypes.class).equalTo(AllJavaTypes.FIELD_ID, 42).findFirst().freeze();\n\n        Thread t = new Thread(() -> {\n            Realm bgRealm = Realm.getInstance(realm.getConfiguration());\n            bgRealm.beginTransaction();\n            AllJavaTypes copiedObject = bgRealm.copyToRealmOrUpdate(frozenObject);\n            bgRealm.commitTransaction();\n\n            assertEquals(1, bgRealm.where(AllJavaTypes.class).count());\n            assertEquals(frozenObject.getFieldLong(), copiedObject.getFieldLong());\n            bgRealm.close();\n        });\n        t.start();\n        t.join();\n    }\n\n    @Test\n    public void insert() throws InterruptedException {\n        Realm realm = createDataForLiveRealm(DATA_SIZE);\n        AllTypes frozenObject = realm.where(AllTypes.class).sort(AllTypes.FIELD_LONG).findFirst().freeze();\n\n        Thread t = new Thread(() -> {\n            Realm bgRealm = Realm.getInstance(realm.getConfiguration());\n            bgRealm.beginTransaction();\n            bgRealm.insert(frozenObject);\n            bgRealm.commitTransaction();\n\n            assertEquals(DATA_SIZE + 1, bgRealm.where(AllTypes.class).count());\n            bgRealm.close();\n        });\n        t.start();\n        t.join();\n    }\n\n    @Test\n    public void insertList() throws InterruptedException {\n        Realm realm = createDataForLiveRealm(DATA_SIZE);\n        AllTypes frozenObject1 = realm.where(AllTypes.class).sort(AllTypes.FIELD_LONG, Sort.ASCENDING).findFirst().freeze();\n        AllTypes frozenObject2 = realm.where(AllTypes.class).sort(AllTypes.FIELD_LONG, Sort.DESCENDING).findFirst().freeze();\n\n        Thread t = new Thread(() -> {\n            Realm bgRealm = Realm.getInstance(realm.getConfiguration());\n            bgRealm.beginTransaction();\n            bgRealm.insert(Arrays.asList(frozenObject1, frozenObject2));\n            bgRealm.commitTransaction();\n\n            assertEquals(DATA_SIZE + 2, bgRealm.where(AllTypes.class).count());\n            bgRealm.close();\n        });\n        t.start();\n        t.join();\n    }\n\n    @Test\n    public void insertOrUpdate() throws InterruptedException {\n        realm.executeTransaction(r -> {\n            r.createObject(AllJavaTypes.class, 42);\n        });\n        AllJavaTypes frozenObject = realm.where(AllJavaTypes.class).equalTo(AllJavaTypes.FIELD_ID, 42).findFirst().freeze();\n\n        Thread t = new Thread(() -> {\n            Realm bgRealm = Realm.getInstance(realm.getConfiguration());\n            bgRealm.beginTransaction();\n            bgRealm.insertOrUpdate(frozenObject);\n            bgRealm.commitTransaction();\n            assertEquals(1, bgRealm.where(AllJavaTypes.class).count());\n            bgRealm.close();\n        });\n        t.start();\n        t.join();\n    }\n\n    @Test\n    public void insertOrUpdateList() throws InterruptedException {\n        realm.executeTransaction(r -> {\n            r.createObject(AllJavaTypes.class, 42);\n            r.createObject(AllJavaTypes.class, 43);\n        });\n\n        // Create two Java objects pointing to the same underlying Realm object in order to verify\n        // that insertOrUpdate works correctly both for the same Java object but also for two\n        // different Java objects representing the same Realm Object.\n        AllJavaTypes frozenObject1 = realm.where(AllJavaTypes.class).equalTo(AllJavaTypes.FIELD_ID, 42).findFirst().freeze();\n        AllJavaTypes frozenObject2 = realm.where(AllJavaTypes.class).equalTo(AllJavaTypes.FIELD_ID, 42).findFirst().freeze();\n\n        Thread t = new Thread(() -> {\n            Realm bgRealm = Realm.getInstance(realm.getConfiguration());\n            bgRealm.beginTransaction();\n            bgRealm.insertOrUpdate(Arrays.asList(frozenObject1, frozenObject1, frozenObject2));\n            bgRealm.commitTransaction();\n            assertEquals(2, bgRealm.where(AllJavaTypes.class).count());\n            bgRealm.close();\n        });\n        t.start();\n        t.join();\n    }\n\n    @Test\n    public void realmObject_equals() throws InterruptedException {\n        realm = createDataForLiveRealm(DATA_SIZE);\n        AllTypes obj1 = realm.where(AllTypes.class).sort(AllTypes.FIELD_LONG).findFirst();\n        AllTypes obj2 = realm.where(AllTypes.class).sort(AllTypes.FIELD_LONG).findFirst();\n        AllTypes obj1Frozen = obj1.freeze();\n        AllTypes obj2Frozen = obj2.freeze();\n\n        assertEquals(obj1, obj2);\n        assertEquals(obj1Frozen, obj2Frozen);\n        assertFalse(obj1.equals(obj1Frozen));\n        Thread t = new Thread(() -> {\n            Realm bgRealm = Realm.getInstance(realm.getConfiguration());\n            AllTypes bgObj1 = bgRealm.where(AllTypes.class).sort(AllTypes.FIELD_LONG).findFirst();\n            AllTypes bgObj1Frozen = bgObj1.freeze();\n            assertEquals(obj1Frozen, obj2Frozen);\n            assertEquals(obj1Frozen, bgObj1Frozen);\n            bgRealm.close();\n        });\n        t.start();\n        t.join();\n    }\n\n    @Test\n    public void realmObject_returnsFrozenRealm() {\n        realm = createDataForLiveRealm(DATA_SIZE);\n        AllTypes obj = realm.where(AllTypes.class).sort(AllTypes.FIELD_LONG).findFirst().freeze();\n        assertTrue(obj.getRealm().isFrozen());\n    }\n\n    @Test\n    public void realmList_returnsFrozenRealm() {\n        realm = createDataForLiveRealm(DATA_SIZE);\n        RealmResults<AllTypes> results = realm.where(AllTypes.class).sort(AllTypes.FIELD_LONG).findAll().freeze();\n        assertTrue(results.getRealm().isFrozen());\n    }\n\n    @Test\n    public void realmResults_returnsFrozenRealm() {\n        realm = createDataForLiveRealm(DATA_SIZE);\n        RealmList<Dog> list = realm.where(AllTypes.class).sort(AllTypes.FIELD_LONG).findFirst().getColumnRealmList().freeze();\n        assertTrue(list.getRealm().isFrozen());\n    }\n\n    private Realm createDataForFrozenRealm(int dataSize) {\n        return createDataForLiveRealm(dataSize).freeze();\n    }\n\n    private Realm createDataForLiveRealm(int dataSize) {\n        realm.executeTransaction(r -> {\n\n            RealmList<Dog> list = new RealmList<>();\n            for (int i = 0; i < 5; i++) {\n                list.add(r.copyToRealm(new Dog(\"Dog \" + i)));\n            }\n            for (int i = 0; i < dataSize; i++) {\n                AllTypes obj = new AllTypes();\n                obj.setColumnString(\"String \" + i);\n                obj.setColumnLong(i);\n                obj.setColumnRealmList(list);\n                obj.setColumnStringList(new RealmList<>(\"Foo\", \"Bar\", \"Baz\"));\n                obj.setColumnRealmObject(r.copyToRealm(new Dog(\"Dog 42\")));\n                obj.setColumnObjectId(new ObjectId(TestHelper.randomObjectIdHexString()));\n                obj.setColumnDecimal128(new Decimal128(new BigDecimal(i + \".23456789\")));\n                r.insert(obj);\n            }\n        });\n        return realm;\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/GCTests.java",
    "content": "/*\n * Copyright 2016 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\npackage io.realm;\n\n\nimport androidx.test.ext.junit.runners.AndroidJUnit4;\n\nimport org.junit.After;\nimport org.junit.Before;\nimport org.junit.Rule;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\n\nimport io.realm.entities.AllTypes;\nimport io.realm.entities.Dog;\n\nimport static junit.framework.TestCase.assertNotNull;\n\n// This test is for the fact we don't have locks for native objects creation that when finalizer/phantom thread free the\n// native object, the same Realm could have some native objects creation at the same time.\n// If the native object's destructor is not thread safe, there is a big chance that those tests crash with a seg-fault.\n// test_destructor_thread_safety.cpp in core tests the similar things.\n@RunWith(AndroidJUnit4.class)\npublic class GCTests {\n    @Rule\n    public final TestRealmConfigurationFactory configFactory = new TestRealmConfigurationFactory();\n\n    private RealmConfiguration realmConfig;\n\n    @Before\n    public void setUp() {\n        realmConfig = configFactory.createConfiguration();\n        Realm realm = Realm.getInstance(realmConfig);\n        realm.beginTransaction();\n        realm.createObject(AllTypes.class).getColumnRealmList().add(realm.createObject(Dog.class));\n        realm.commitTransaction();\n        realm.close();\n\n    }\n\n    @After\n    public void tearDown() {\n    }\n\n    @Test\n    public void createRealmResults() {\n        for (int i = 0; i < 100; i++) {\n            Realm realm = Realm.getInstance(realmConfig);\n            for (int j = 0; j < 1000; j++) {\n                realm.where(AllTypes.class).findAll();\n            }\n            realm.close();\n        }\n    }\n\n    @Test\n    public void createRealmResultsFromRealmResults() {\n        for (int i = 0; i < 100; i++) {\n            Realm realm = Realm.getInstance(realmConfig);\n            for (int j = 0; j < 1000; j++) {\n                realm.where(AllTypes.class).findAll().where().findAll();\n            }\n            realm.close();\n        }\n    }\n\n    @Test\n    public void createRealmResultsFromRealmList() {\n        for (int i = 0; i < 100; i++) {\n            Realm realm = Realm.getInstance(realmConfig);\n            for (int j = 0; j < 1000; j++) {\n                AllTypes allTypes = realm.where(AllTypes.class).findFirst();\n                assertNotNull(allTypes);\n                allTypes.getColumnRealmList().where().findAll();\n            }\n            realm.close();\n        }\n    }\n\n    @Test\n    public void createRealmObject() {\n        for (int i = 0; i < 100; i++) {\n            Realm realm = Realm.getInstance(realmConfig);\n            for (int j = 0; j < 1000; j++) {\n                realm.where(AllTypes.class).findFirst();\n            }\n            realm.close();\n        }\n    }\n\n    @Test\n    public void createRealmObjectFromRealmResults() {\n        for (int i = 0; i < 100; i++) {\n            Realm realm = Realm.getInstance(realmConfig);\n            for (int j = 0; j < 1000; j++) {\n                assertNotNull(realm.where(AllTypes.class).findAll().first());\n            }\n            realm.close();\n        }\n    }\n\n    @Test\n    public void createRealmObjectsFromRealmList() {\n        for (int i = 0; i < 100; i++) {\n            Realm realm = Realm.getInstance(realmConfig);\n            for (int j = 0; j < 1000; j++) {\n                AllTypes allTypes = realm.where(AllTypes.class).findFirst();\n                assertNotNull(allTypes);\n                assertNotNull(allTypes.getColumnRealmList().first());\n            }\n            realm.close();\n        }\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/IOSRealmTests.java",
    "content": "/*\n * Copyright 2015 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\npackage io.realm;\n\nimport android.content.Context;\n\nimport androidx.test.ext.junit.runners.AndroidJUnit4;\nimport androidx.test.platform.app.InstrumentationRegistry;\n\nimport org.junit.After;\nimport org.junit.Before;\nimport org.junit.Ignore;\nimport org.junit.Rule;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\n\nimport java.io.IOException;\nimport java.util.Date;\n\nimport io.realm.entities.IOSAllTypes;\nimport io.realm.entities.IOSChild;\nimport io.realm.internal.OsObjectStore;\nimport io.realm.internal.Table;\n\nimport static io.realm.internal.test.ExtraTests.assertArrayEquals;\nimport static org.junit.Assert.assertEquals;\nimport static org.junit.Assert.assertFalse;\nimport static org.junit.Assert.assertNull;\nimport static org.junit.Assert.assertTrue;\n\n/**\n * This class test interoperability with Realms created on iOS.\n */\n@RunWith(AndroidJUnit4.class)\npublic class IOSRealmTests {\n\n    @Rule\n    public final TestRealmConfigurationFactory configFactory = new TestRealmConfigurationFactory();\n\n    private static final String[] IOS_VERSIONS = new String[] {\"6.0.0-beta.2\"};\n    private static final String REALM_NAME = \"alltypes.realm\";\n    private Realm realm;\n    private Context context;\n\n    @Before\n    public void setUp() {\n        RealmConfiguration defaultConfiguration = configFactory.createConfigurationBuilder()\n                .name(REALM_NAME)\n                .schema(IOSAllTypes.class, IOSChild.class)\n                .build();\n        Realm.setDefaultConfiguration(defaultConfiguration);\n        context = InstrumentationRegistry.getInstrumentation().getContext();\n    }\n\n    @After\n    public void tearDown() {\n        Realm.removeDefaultConfiguration();\n        if (realm != null) {\n            realm.close();\n        }\n    }\n\n    @Test\n    public void iOSDataTypes() throws IOException {\n        for (String iosVersion : IOS_VERSIONS) {\n            configFactory.copyRealmFromAssets(context,\n                    \"ios/\" + iosVersion + \"-alltypes.realm\", REALM_NAME);\n            realm = Realm.getDefaultInstance();\n            RealmResults<IOSAllTypes> result = realm.where(IOSAllTypes.class).sort(\"id\", Sort.ASCENDING).findAll();\n            // Verifies metadata.\n            Table table = realm.getTable(IOSAllTypes.class);\n            assertEquals(\"id\", OsObjectStore.getPrimaryKeyForObject(realm.getSharedRealm(), IOSAllTypes.CLASS_NAME));\n            assertTrue(table.hasSearchIndex(table.getColumnKey(\"id\")));\n            // Iterative check.\n            for (int i = 0; i < 10; i++) {\n                IOSAllTypes obj = result.get(i);\n                assertTrue(obj.isBoolCol());\n                assertEquals(i + 1, obj.getShortCol());\n                assertEquals(10 + i, obj.getIntCol());\n                assertEquals(100 + i, obj.getLongCol());\n                assertEquals(100000000L + (long)i, obj.getLongLongCol());\n                assertEquals(1.23F + (float)i, obj.getFloatCol(), 0F);\n                assertEquals(1.234D + (double)i, obj.getDoubleCol(), 0D);\n                assertArrayEquals(new byte[]{1, 2, 3}, obj.getByteCol());\n                assertEquals(\"String \" + Integer.toString(i), obj.getStringCol());\n                assertEquals(new Date((1000L + i) * 1000), obj.getDateCol());\n                assertEquals(\"Foo\", result.get(i).getChild().getName());\n                assertEquals(10, result.get(i).getChildren().size());\n                for (int j = 0; j < 10; j++) {\n                    assertEquals(\"Name: \" + Integer.toString(i), result.get(i).getChildren().get(j).getName());\n                }\n            }\n        }\n    }\n\n    @Test\n    public void iOSDataTypesDefaultValues() throws IOException {\n        for (String iosVersion : IOS_VERSIONS) {\n            configFactory.copyRealmFromAssets(context,\n                    \"ios/\" + iosVersion + \"-alltypes-default.realm\", REALM_NAME);\n            realm = Realm.getDefaultInstance();\n\n            IOSAllTypes obj = realm.where(IOSAllTypes.class).findFirst();\n            assertFalse(obj.isBoolCol());\n            assertEquals(0, obj.getShortCol());\n            assertEquals(0, obj.getIntCol());\n            assertEquals(0, obj.getLongCol());\n            assertEquals(0L, obj.getLongLongCol());\n            assertEquals(0.0F, obj.getFloatCol(), 0F);\n            assertEquals(0.0D, obj.getDoubleCol(), 0D);\n            assertArrayEquals(new byte[0], obj.getByteCol());\n            assertEquals(\"\", obj.getStringCol());\n            assertEquals(new Date(0), obj.getDateCol());\n            assertNull(obj.getChild());\n            assertEquals(0, obj.getChildren().size());\n        }\n    }\n\n    @Test\n    public void iOSDataTypesNullValues() throws IOException {\n        for (String iosVersion : IOS_VERSIONS) {\n            configFactory.copyRealmFromAssets(context,\n                    \"ios/\" + iosVersion + \"-alltypes-null-value.realm\", REALM_NAME);\n            realm = Realm.getDefaultInstance();\n\n            IOSAllTypes obj = realm.where(IOSAllTypes.class).findFirst();\n            assertEquals(null, obj.getByteCol());\n            assertEquals(null, obj.getStringCol());\n            assertEquals(null, obj.getDateCol());\n            assertEquals(null, obj.getChild());\n            assertEquals(new RealmList<IOSChild>(), obj.getChildren());\n        }\n    }\n\n    @Test\n    @SuppressWarnings(\"ConstantOverflow\")\n    public void iOSDataTypesMinimumValues() throws IOException {\n        for (String iosVersion : IOS_VERSIONS) {\n            configFactory.copyRealmFromAssets(context,\n                    \"ios/\" + iosVersion + \"-alltypes-min.realm\", REALM_NAME);\n            realm = Realm.getDefaultInstance();\n\n            IOSAllTypes obj = realm.where(IOSAllTypes.class).findFirst();\n            assertFalse(obj.isBoolCol());\n            assertEquals(Short.MIN_VALUE, obj.getShortCol());\n            assertEquals(Integer.MIN_VALUE, obj.getIntCol());\n            assertEquals(Long.MIN_VALUE, obj.getLongCol());\n            assertEquals(Long.MIN_VALUE, obj.getLongLongCol());\n            assertEquals(-Float.MAX_VALUE, obj.getFloatCol(), 0F);\n            assertEquals(-Double.MAX_VALUE, obj.getDoubleCol(), 0D);\n            assertArrayEquals(new byte[0], obj.getByteCol());\n            assertEquals(\"\", obj.getStringCol());\n            assertEquals(Long.MIN_VALUE, obj.getDateCol().getTime());\n        }\n    }\n\n    @Test\n    public void iOSDataTypesMaximumValues() throws IOException {\n        for (String iosVersion : IOS_VERSIONS) {\n            configFactory.copyRealmFromAssets(context,\n                    \"ios/\" + iosVersion + \"-alltypes-max.realm\", REALM_NAME);\n            realm = Realm.getDefaultInstance();\n\n            IOSAllTypes obj = realm.where(IOSAllTypes.class).findFirst();\n            assertEquals(Short.MAX_VALUE, obj.getShortCol());\n            assertEquals(Integer.MAX_VALUE, obj.getIntCol());\n            assertEquals(Long.MAX_VALUE, obj.getLongCol());\n            assertEquals(Long.MAX_VALUE, obj.getLongLongCol());\n            assertEquals(Float.MAX_VALUE, obj.getFloatCol(), 0F);\n            assertEquals(Double.MAX_VALUE, obj.getDoubleCol(), 0D);\n            assertArrayEquals(new byte[0], obj.getByteCol());\n            assertEquals(\"\", obj.getStringCol());\n            assertEquals(Long.MAX_VALUE, obj.getDateCol().getTime());\n        }\n    }\n\n    @Test\n    public void iOSEncryptedRealm() throws IOException {\n        for (String iosVersion : IOS_VERSIONS) {\n            configFactory.copyRealmFromAssets(context,\n                    \"ios/\" + iosVersion + \"-alltypes-default-encrypted.realm\", REALM_NAME);\n            RealmConfiguration realmConfig = configFactory.createConfigurationBuilder()\n                    .name(REALM_NAME)\n                    .encryptionKey(getIOSKey())\n                    .schema(IOSAllTypes.class, IOSChild.class)\n                    .build();\n            realm = Realm.getInstance(realmConfig);\n\n            IOSAllTypes obj = realm.where(IOSAllTypes.class).findFirst();\n            assertFalse(obj.isBoolCol());\n            assertEquals(0, obj.getShortCol());\n            assertEquals(0, obj.getIntCol());\n            assertEquals(0L, obj.getLongCol());\n            assertEquals(0.0F, obj.getFloatCol(), 0F);\n            assertEquals(0.0D, obj.getDoubleCol(), 0D);\n            assertArrayEquals(new byte[0], obj.getByteCol());\n            assertEquals(\"\", obj.getStringCol());\n            assertEquals(new Date(0), obj.getDateCol());\n            assertNull(obj.getChild());\n            assertEquals(0, obj.getChildren().size());\n        }\n    }\n\n    private byte[] getIOSKey() {\n        byte[] keyData = new byte[Realm.ENCRYPTION_KEY_LENGTH];\n        for (int i = 0; i < keyData.length; i++) {\n            keyData[i] = 1;\n        }\n        return keyData;\n    }\n    \n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/LinkingObjectsDynamicTests.java",
    "content": "/*\n * Copyright 2017 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\npackage io.realm;\n\nimport org.junit.After;\nimport org.junit.Before;\nimport org.junit.Rule;\nimport org.junit.Test;\nimport org.junit.rules.ExpectedException;\nimport org.junit.runner.RunWith;\n\nimport java.util.Locale;\n\nimport androidx.test.ext.junit.runners.AndroidJUnit4;\nimport io.realm.entities.AllJavaTypes;\nimport io.realm.entities.BacklinksSource;\nimport io.realm.entities.BacklinksTarget;\nimport io.realm.entities.Cat;\nimport io.realm.entities.Owner;\nimport io.realm.rule.RunInLooperThread;\nimport io.realm.rule.RunTestInLooperThread;\n\nimport static org.junit.Assert.assertEquals;\nimport static org.junit.Assert.assertFalse;\nimport static org.junit.Assert.assertNotNull;\nimport static org.junit.Assert.assertTrue;\nimport static org.junit.Assert.fail;\n\n\n@RunWith(AndroidJUnit4.class)\npublic class LinkingObjectsDynamicTests {\n\n    @Rule\n    public final TestRealmConfigurationFactory configFactory = new TestRealmConfigurationFactory();\n\n    @Rule\n    public final RunInLooperThread looperThread = new RunInLooperThread();\n    @Rule\n    public final ExpectedException thrown = ExpectedException.none();\n\n    private Realm realm;\n    private DynamicRealm dynamicRealm;\n\n    @Before\n    public void setUp() {\n        RealmConfiguration realmConfig = configFactory.createConfiguration();\n        realm = Realm.getInstance(realmConfig);\n        dynamicRealm = DynamicRealm.getInstance(realmConfig);\n    }\n\n    @After\n    public void tearDown() {\n        if (realm != null) {\n            realm.close();\n        }\n\n        if (dynamicRealm != null) {\n            dynamicRealm.close();\n        }\n    }\n\n    @Test\n    public void linkingObjects_classIsNull() throws Exception {\n        dynamicRealm.beginTransaction();\n        final DynamicRealmObject object = dynamicRealm.createObject(AllJavaTypes.CLASS_NAME, 1L);\n        dynamicRealm.commitTransaction();\n\n        try {\n            object.linkingObjects(null, AllJavaTypes.FIELD_INT);\n            fail();\n        } catch (IllegalArgumentException expected) {\n            assertEquals(RealmSchema.EMPTY_STRING_MSG, expected.getMessage());\n        }\n    }\n\n    @Test\n    public void linkingObjects_fieldIsNull() throws Exception {\n        dynamicRealm.beginTransaction();\n        final DynamicRealmObject object = dynamicRealm.createObject(AllJavaTypes.CLASS_NAME, 1L);\n        dynamicRealm.commitTransaction();\n\n        try {\n            object.linkingObjects(AllJavaTypes.CLASS_NAME, null);\n            fail();\n        } catch (IllegalArgumentException expected) {\n            assertEquals(\"Non-null 'srcFieldName' required.\", expected.getMessage());\n        }\n    }\n\n    @Test\n    public void linkingObjects_nonExistentClass() {\n        dynamicRealm.beginTransaction();\n        final DynamicRealmObject object = dynamicRealm.createObject(AllJavaTypes.CLASS_NAME, 1L);\n        dynamicRealm.commitTransaction();\n\n        try {\n            object.linkingObjects(\"ThisClassDoesNotExist\", AllJavaTypes.FIELD_INT);\n            fail();\n        } catch (IllegalArgumentException expected) {\n            assertTrue(expected.getMessage().startsWith(\"Class not found\"));\n        }\n    }\n\n    @Test\n    public void linkingObjects_nonExistentField() {\n        dynamicRealm.beginTransaction();\n        final DynamicRealmObject object = dynamicRealm.createObject(AllJavaTypes.CLASS_NAME, 1L);\n        dynamicRealm.commitTransaction();\n\n        try {\n            object.linkingObjects(AllJavaTypes.CLASS_NAME, \"fieldNotExist\");\n            fail();\n        } catch (IllegalArgumentException expected) {\n            final String expectedMessage = String.format(Locale.ENGLISH,\n                    \"Field name '%s' does not exist on schema for '%s'\",\n                    \"fieldNotExist\", AllJavaTypes.CLASS_NAME);\n            assertEquals(expectedMessage, expected.getMessage());\n        }\n    }\n\n    @Test\n    public void linkingObjects_ignoredExistentField() {\n        dynamicRealm.beginTransaction();\n        final DynamicRealmObject object = dynamicRealm.createObject(AllJavaTypes.CLASS_NAME, 1L);\n        dynamicRealm.commitTransaction();\n\n        try {\n            object.linkingObjects(AllJavaTypes.CLASS_NAME, AllJavaTypes.FIELD_IGNORED);\n            fail();\n        } catch (IllegalArgumentException expected) {\n            final String expectedMessage = String.format(Locale.ENGLISH,\n                    \"Field name '%s' does not exist on schema for '%s'\",\n                    AllJavaTypes.FIELD_IGNORED, AllJavaTypes.CLASS_NAME);\n            assertEquals(expectedMessage, expected.getMessage());\n        }\n    }\n\n    @Test\n    public void linkingObjects_linkQueryNotSupported() throws Exception {\n        dynamicRealm.beginTransaction();\n        final DynamicRealmObject object = dynamicRealm.createObject(AllJavaTypes.CLASS_NAME, 1L);\n        dynamicRealm.commitTransaction();\n\n        try {\n            object.linkingObjects(AllJavaTypes.CLASS_NAME, AllJavaTypes.FIELD_OBJECT + \".\" + AllJavaTypes.FIELD_OBJECT);\n            fail();\n        } catch (IllegalArgumentException expected) {\n            assertEquals(DynamicRealmObject.MSG_LINK_QUERY_NOT_SUPPORTED, expected.getMessage());\n        }\n    }\n\n    @Test\n    public void linkingObjects_invalidFieldType() {\n        dynamicRealm.beginTransaction();\n        final DynamicRealmObject object = dynamicRealm.createObject(AllJavaTypes.CLASS_NAME, 1L);\n        dynamicRealm.commitTransaction();\n\n        for (RealmFieldType fieldType : RealmFieldType.values()) {\n            if(fieldType == RealmFieldType.TYPED_LINK)\n                continue;\n\n            try {\n                switch (fieldType) {\n                    // skip valid types\n                    case OBJECT: // fall-through\n                    case LIST:\n                        continue;\n                        // skip special case\n                    case LINKING_OBJECTS:\n                        continue;\n                    case INTEGER:\n                        object.linkingObjects(AllJavaTypes.CLASS_NAME, AllJavaTypes.FIELD_INT);\n                        break;\n                    case BOOLEAN:\n                        object.linkingObjects(AllJavaTypes.CLASS_NAME, AllJavaTypes.FIELD_BOOLEAN);\n                        break;\n                    case STRING:\n                        object.linkingObjects(AllJavaTypes.CLASS_NAME, AllJavaTypes.FIELD_STRING);\n                        break;\n                    case BINARY:\n                        object.linkingObjects(AllJavaTypes.CLASS_NAME, AllJavaTypes.FIELD_BINARY);\n                        break;\n                    case DATE:\n                        object.linkingObjects(AllJavaTypes.CLASS_NAME, AllJavaTypes.FIELD_DATE);\n                        break;\n                    case FLOAT:\n                        object.linkingObjects(AllJavaTypes.CLASS_NAME, AllJavaTypes.FIELD_FLOAT);\n                        break;\n                    case DOUBLE:\n                        object.linkingObjects(AllJavaTypes.CLASS_NAME, AllJavaTypes.FIELD_DOUBLE);\n                        break;\n                    case DECIMAL128:\n                        object.linkingObjects(AllJavaTypes.CLASS_NAME, AllJavaTypes.FIELD_DECIMAL128);\n                        break;\n                    case OBJECT_ID:\n                        object.linkingObjects(AllJavaTypes.CLASS_NAME, AllJavaTypes.FIELD_OBJECT_ID);\n                        break;\n                    case UUID:\n                        object.linkingObjects(AllJavaTypes.CLASS_NAME, AllJavaTypes.FIELD_UUID);\n                        break;\n                    case MIXED:\n                        object.linkingObjects(AllJavaTypes.CLASS_NAME, AllJavaTypes.FIELD_REALM_ANY);\n                        break;\n                    case INTEGER_LIST:\n                        object.linkingObjects(AllJavaTypes.CLASS_NAME, AllJavaTypes.FIELD_INTEGER_LIST);\n                        break;\n                    case BOOLEAN_LIST:\n                        object.linkingObjects(AllJavaTypes.CLASS_NAME, AllJavaTypes.FIELD_BOOLEAN_LIST);\n                        break;\n                    case STRING_LIST:\n                        object.linkingObjects(AllJavaTypes.CLASS_NAME, AllJavaTypes.FIELD_STRING_LIST);\n                        break;\n                    case BINARY_LIST:\n                        object.linkingObjects(AllJavaTypes.CLASS_NAME, AllJavaTypes.FIELD_BINARY_LIST);\n                        break;\n                    case DATE_LIST:\n                        object.linkingObjects(AllJavaTypes.CLASS_NAME, AllJavaTypes.FIELD_DATE_LIST);\n                        break;\n                    case FLOAT_LIST:\n                        object.linkingObjects(AllJavaTypes.CLASS_NAME, AllJavaTypes.FIELD_FLOAT_LIST);\n                        break;\n                    case DOUBLE_LIST:\n                        object.linkingObjects(AllJavaTypes.CLASS_NAME, AllJavaTypes.FIELD_DOUBLE_LIST);\n                        break;\n                    case DECIMAL128_LIST:\n                        object.linkingObjects(AllJavaTypes.CLASS_NAME, AllJavaTypes.FIELD_DECIMAL128_LIST);\n                        break;\n                    case OBJECT_ID_LIST:\n                        object.linkingObjects(AllJavaTypes.CLASS_NAME, AllJavaTypes.FIELD_OBJECT_ID_LIST);\n                        break;\n                    case UUID_LIST:\n                        object.linkingObjects(AllJavaTypes.CLASS_NAME, AllJavaTypes.FIELD_UUID_LIST);\n                        break;\n                    case MIXED_LIST:\n                        object.linkingObjects(AllJavaTypes.CLASS_NAME, AllJavaTypes.FIELD_REALM_ANY_LIST);\n                        break;\n                    case STRING_TO_MIXED_MAP:\n                    case STRING_TO_BOOLEAN_MAP:\n                    case STRING_TO_STRING_MAP:\n                    case STRING_TO_INTEGER_MAP:\n                    case STRING_TO_FLOAT_MAP:\n                    case STRING_TO_DOUBLE_MAP:\n                    case STRING_TO_BINARY_MAP:\n                    case STRING_TO_DATE_MAP:\n                    case STRING_TO_OBJECT_ID_MAP:\n                    case STRING_TO_UUID_MAP:\n                    case STRING_TO_DECIMAL128_MAP:\n                    case STRING_TO_LINK_MAP:\n                    case BOOLEAN_SET:\n                    case STRING_SET:\n                    case INTEGER_SET:\n                    case FLOAT_SET:\n                    case DOUBLE_SET:\n                    case BINARY_SET:\n                    case DATE_SET:\n                    case DECIMAL128_SET:\n                    case OBJECT_ID_SET:\n                    case UUID_SET:\n                    case LINK_SET:\n                    case MIXED_SET:\n                        // TODO: https://github.com/realm/realm-java/issues/7382\n                        // TODO: https://github.com/realm/realm-java/issues/7383\n                        throw new IllegalArgumentException(\"Unexpected field type\");\n                    default:\n                        fail(\"unknown type: \" + fieldType);\n                        break;\n                }\n                fail();\n            } catch (IllegalArgumentException expected) {\n                assertTrue(expected.getMessage().startsWith(\"Unexpected field type\"));\n            }\n        }\n\n        // Linking Object fields are implicit and do not exist.\n        for (String field : new String[]{AllJavaTypes.FIELD_LO_OBJECT, AllJavaTypes.FIELD_LO_LIST}) {\n            try {\n                object.linkingObjects(AllJavaTypes.CLASS_NAME, field);\n                fail();\n            } catch (IllegalArgumentException expected) {\n                assertTrue(expected.getMessage().contains(\"does not exist\"));\n            }\n        }\n    }\n\n    @Test\n    public void linkingObjects_linkedByOBJECT_backlinksDefinedInModel() {\n        final int numSourceOfTarget1 = 3;\n        final int numSourceOfTarget2 = 2;\n        realm.executeTransaction(new Realm.Transaction() {\n            @Override\n            public void execute(Realm realm) {\n                final BacklinksTarget target1 = realm.createObject(BacklinksTarget.class);\n                target1.setId(1);\n\n                // create sources of target1\n                for (int i = 0; i < numSourceOfTarget1; i++) {\n                    final BacklinksSource source = realm.createObject(BacklinksSource.class);\n                    source.setName(\"source\" + i + \"_target1\");\n                    source.setChild(target1);\n                }\n\n                final BacklinksTarget target2 = realm.createObject(BacklinksTarget.class);\n                target2.setId(2);\n\n                // create sources of target2\n                for (int i = 0; i < numSourceOfTarget2; i++) {\n                    final BacklinksSource source = realm.createObject(BacklinksSource.class);\n                    source.setName(\"source\" + i + \"_target2\");\n                    source.setChild(target2);\n                }\n\n                // target3 has no owner\n                final BacklinksTarget target3 = realm.createObject(BacklinksTarget.class);\n                target3.setId(3);\n            }\n        });\n\n        dynamicRealm.refresh();\n\n        final DynamicRealmObject target1 = dynamicRealm.where(BacklinksTarget.CLASS_NAME).equalTo(BacklinksTarget.FIELD_ID, 1).findFirst();\n        final RealmResults<DynamicRealmObject> target1Sources = target1.linkingObjects(BacklinksSource.CLASS_NAME, BacklinksSource.FIELD_CHILD);\n        assertNotNull(target1Sources);\n        assertEquals(numSourceOfTarget1, target1Sources.size());\n        for (DynamicRealmObject target1Source : target1Sources) {\n            assertEquals(BacklinksSource.CLASS_NAME, target1Source.getType());\n            assertTrue(target1Source.getString(BacklinksSource.FIELD_NAME).endsWith(\"_target1\"));\n            assertEquals(target1, target1Source.getObject(BacklinksSource.FIELD_CHILD));\n        }\n\n        final DynamicRealmObject target2 = dynamicRealm.where(BacklinksTarget.CLASS_NAME).equalTo(BacklinksTarget.FIELD_ID, 2).findFirst();\n        final RealmResults<DynamicRealmObject> target2Sources = target2.linkingObjects(BacklinksSource.CLASS_NAME, BacklinksSource.FIELD_CHILD);\n        assertNotNull(target2Sources);\n        assertEquals(numSourceOfTarget2, target2Sources.size());\n        for (DynamicRealmObject target2Source : target2Sources) {\n            assertEquals(BacklinksSource.CLASS_NAME, target2Source.getType());\n            assertTrue(target2Source.getString(BacklinksSource.FIELD_NAME).endsWith(\"_target2\"));\n            assertEquals(target2, target2Source.getObject(BacklinksSource.FIELD_CHILD));\n        }\n\n        final DynamicRealmObject target3 = dynamicRealm.where(BacklinksTarget.CLASS_NAME).equalTo(BacklinksTarget.FIELD_ID, 3).findFirst();\n        final RealmResults<DynamicRealmObject> target3Sources = target3.linkingObjects(BacklinksSource.CLASS_NAME, BacklinksSource.FIELD_CHILD);\n        assertNotNull(target3Sources);\n        assertTrue(target3Sources.isEmpty());\n    }\n\n    @Test\n    public void linkingObjects_linkedByOBJECT_backlinksNotDefinedInModel() {\n        final int numOwnersOfCat1 = 3;\n        final int numOwnersOfCat2 = 2;\n        realm.executeTransaction(new Realm.Transaction() {\n            @Override\n            public void execute(Realm realm) {\n                final Cat cat1 = realm.createObject(Cat.class);\n                cat1.setName(\"cat1\");\n\n                // create owners of cat1\n                for (int i = 0; i < numOwnersOfCat1; i++) {\n                    final Owner owner = realm.createObject(Owner.class);\n                    owner.setName(\"owner\" + i + \"_cat1\");\n                    owner.setCat(cat1);\n                }\n\n                final Cat cat2 = realm.createObject(Cat.class);\n                cat2.setName(\"cat2\");\n\n                // create owners of cat2\n                for (int i = 0; i < numOwnersOfCat2; i++) {\n                    final Owner owner = realm.createObject(Owner.class);\n                    owner.setName(\"owner\" + i + \"_cat2\");\n                    owner.setCat(cat2);\n                }\n\n                // cat3 has no owner\n                final Cat cat3 = realm.createObject(Cat.class);\n                cat3.setName(\"cat3\");\n            }\n        });\n\n        dynamicRealm.refresh();\n\n        final DynamicRealmObject cat1 = dynamicRealm.where(Cat.CLASS_NAME).equalTo(Cat.FIELD_NAME, \"cat1\").findFirst();\n        final RealmResults<DynamicRealmObject> cat1Owners = cat1.linkingObjects(Owner.CLASS_NAME, Owner.FIELD_CAT);\n        assertNotNull(cat1Owners);\n        assertEquals(numOwnersOfCat1, cat1Owners.size());\n        for (DynamicRealmObject cat1Owner : cat1Owners) {\n            assertEquals(Owner.CLASS_NAME, cat1Owner.getType());\n            assertTrue(cat1Owner.getString(Owner.FIELD_NAME).endsWith(\"_cat1\"));\n            assertEquals(cat1, cat1Owner.getObject(Owner.FIELD_CAT));\n        }\n\n        final DynamicRealmObject cat2 = dynamicRealm.where(Cat.CLASS_NAME).equalTo(Cat.FIELD_NAME, \"cat2\").findFirst();\n        final RealmResults<DynamicRealmObject> cat2Owners = cat2.linkingObjects(Owner.CLASS_NAME, Owner.FIELD_CAT);\n        assertNotNull(cat2Owners);\n        assertEquals(numOwnersOfCat2, cat2Owners.size());\n        for (DynamicRealmObject cat2Owner : cat2Owners) {\n            assertEquals(Owner.CLASS_NAME, cat2Owner.getType());\n            assertTrue(cat2Owner.getString(Owner.FIELD_NAME).endsWith(\"_cat2\"));\n            assertEquals(cat2, cat2Owner.getObject(Owner.FIELD_CAT));\n        }\n\n        final DynamicRealmObject cat3 = dynamicRealm.where(Cat.CLASS_NAME).equalTo(Cat.FIELD_NAME, \"cat3\").findFirst();\n        final RealmResults<DynamicRealmObject> cat3Owners = cat3.linkingObjects(Owner.CLASS_NAME, Owner.FIELD_CAT);\n        assertNotNull(cat3Owners);\n        assertTrue(cat3Owners.isEmpty());\n    }\n\n    @Test\n    public void linkingObjects_linkedByLIST() {\n        //           source100          source200        source300\n        //            //    \\\\          \\\\ || //\n        //        target1   target2     target2\n        //\n        //  // = list ref\n        realm.executeTransaction(new Realm.Transaction() {\n            @Override\n            public void execute(Realm realm) {\n                final AllJavaTypes target1 = realm.createObject(AllJavaTypes.class, 1L);\n                final AllJavaTypes target2 = realm.createObject(AllJavaTypes.class, 2L);\n                final AllJavaTypes target3 = realm.createObject(AllJavaTypes.class, 3L);\n\n                final AllJavaTypes source100 = realm.createObject(AllJavaTypes.class, 100L);\n                source100.getFieldList().add(target1);\n                source100.getFieldList().add(target2);\n\n                // list contains three target2s\n                final AllJavaTypes source200 = realm.createObject(AllJavaTypes.class, 200L);\n                source200.getFieldList().add(target2);\n                source200.getFieldList().add(target2);\n                source200.getFieldList().add(target2);\n            }\n        });\n\n        dynamicRealm.refresh();\n\n        final DynamicRealmObject target1 = dynamicRealm.where(AllJavaTypes.CLASS_NAME).equalTo(AllJavaTypes.FIELD_ID, 1L).findFirst();\n        final DynamicRealmObject target2 = dynamicRealm.where(AllJavaTypes.CLASS_NAME).equalTo(AllJavaTypes.FIELD_ID, 2L).findFirst();\n        final DynamicRealmObject target3 = dynamicRealm.where(AllJavaTypes.CLASS_NAME).equalTo(AllJavaTypes.FIELD_ID, 3L).findFirst();\n\n        // tests sources of target1\n        final RealmResults<DynamicRealmObject> target1Sources = target1.linkingObjects(AllJavaTypes.CLASS_NAME, AllJavaTypes.FIELD_LIST);\n        assertNotNull(target1Sources);\n        assertEquals(1, target1Sources.size());\n        assertEquals(AllJavaTypes.CLASS_NAME, target1Sources.first().getType());\n        assertEquals(100L, target1Sources.first().getLong(AllJavaTypes.FIELD_ID));\n        assertTrue(target1Sources.first().getList(AllJavaTypes.FIELD_LIST).contains(target1));\n        assertTrue(target1Sources.first().getList(AllJavaTypes.FIELD_LIST).contains(target2));\n        assertFalse(target1Sources.first().getList(AllJavaTypes.FIELD_LIST).contains(target3));\n\n        // tests sources of target2\n        final RealmResults<DynamicRealmObject> target2Sources = target2.linkingObjects(AllJavaTypes.CLASS_NAME, AllJavaTypes.FIELD_LIST);\n        assertNotNull(target2Sources);\n        // if a source (in this test, source200) contains multiple references to a target in one RealmList, those must not be aggregated.\n        assertEquals(4, target2Sources.size());\n        boolean source100Found = false;\n        boolean source200Found = false;\n        for (DynamicRealmObject target2Source : target2Sources) {\n            final long idValue = target2Source.getLong(AllJavaTypes.FIELD_ID);\n            if (idValue == 100L) {\n                source100Found = true;\n            } else if (idValue == 200L) {\n                source200Found = true;\n            } else {\n                fail(\"unexpected id value: \" + idValue);\n            }\n\n            assertEquals(AllJavaTypes.CLASS_NAME, target2Source.getType());\n            assertTrue(target2Source.getList(AllJavaTypes.FIELD_LIST).contains(target2));\n            assertFalse(target2Source.getList(AllJavaTypes.FIELD_LIST).contains(target3));\n        }\n        assertTrue(source100Found);\n        assertTrue(source200Found);\n\n        // tests sources of target3\n        final RealmResults<DynamicRealmObject> target3Sources = target3.linkingObjects(AllJavaTypes.CLASS_NAME, AllJavaTypes.FIELD_LIST);\n        assertNotNull(target3Sources);\n        assertTrue(target3Sources.isEmpty());\n\n        dynamicRealm.executeTransaction(new DynamicRealm.Transaction() {\n            @Override\n            public void execute(DynamicRealm realm) {\n                final DynamicRealmObject source200 = dynamicRealm.where(AllJavaTypes.CLASS_NAME).equalTo(AllJavaTypes.FIELD_ID, 200L).findFirst();\n                // remove last reference in the list\n                source200.getList(AllJavaTypes.FIELD_LIST).remove(2);\n            }\n        });\n\n        // backlinks are also updated\n        assertEquals(3, target2Sources.size());\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void linkingObjects_IllegalStateException_ifNotYetLoaded() {\n        final Realm realm = looperThread.getRealm();\n\n        realm.executeTransaction(new Realm.Transaction() {\n            @Override\n            public void execute(Realm realm) {\n                final BacklinksTarget target1 = realm.createObject(BacklinksTarget.class);\n                target1.setId(1);\n\n                final BacklinksSource source = realm.createObject(BacklinksSource.class);\n                source.setChild(target1);\n            }\n        });\n\n        final DynamicRealm dynamicRealm = DynamicRealm.getInstance(looperThread.getConfiguration());\n        looperThread.closeAfterTest(dynamicRealm);\n        final DynamicRealmObject targetAsync = dynamicRealm.where(BacklinksTarget.CLASS_NAME)\n                .equalTo(BacklinksTarget.FIELD_ID, 1L).findFirstAsync();\n        // precondition\n        assertFalse(targetAsync.isLoaded());\n\n        try {\n            targetAsync.linkingObjects(BacklinksSource.CLASS_NAME, BacklinksSource.FIELD_CHILD);\n            fail();\n        } catch (IllegalStateException ignored) {\n        }\n        looperThread.testComplete();\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void linkingObjects_IllegalStateException_ifDeleted() {\n        final Realm realm = looperThread.getRealm();\n\n        realm.executeTransaction(new Realm.Transaction() {\n            @Override\n            public void execute(Realm realm) {\n                final BacklinksTarget target1 = realm.createObject(BacklinksTarget.class);\n                target1.setId(1);\n\n                final BacklinksSource source = realm.createObject(BacklinksSource.class);\n                source.setChild(target1);\n            }\n        });\n\n        final DynamicRealm dynamicRealm = DynamicRealm.getInstance(looperThread.getConfiguration());\n        looperThread.closeAfterTest(dynamicRealm);\n        final DynamicRealmObject target = dynamicRealm.where(BacklinksTarget.CLASS_NAME)\n                .equalTo(BacklinksTarget.FIELD_ID, 1L).findFirst();\n\n        dynamicRealm.executeTransaction(new DynamicRealm.Transaction() {\n            @Override\n            public void execute(DynamicRealm realm) {\n                target.deleteFromRealm();\n            }\n        });\n\n        // precondition\n        assertFalse(target.isValid());\n\n        try {\n            target.linkingObjects(BacklinksSource.CLASS_NAME, BacklinksSource.FIELD_CHILD);\n            fail();\n        } catch (IllegalStateException ignored) {\n        }\n        looperThread.testComplete();\n    }\n\n    @Test\n    public void dynamicQuery_invalidSyntax() {\n        String[] invalidBacklinks = new String[]{\n                \"linkingObject(x\",\n                \"linkingObject(x.y\",\n                \"linkingObject(x.y)\",\n                \"linkingObject(x.y).\",\n                \"linkingObject(x.y)..z\",\n                \"linkingObject(x.y).linkingObjects(x1.y1).z\"\n        };\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/LinkingObjectsManagedTests.java",
    "content": "/*\n * Copyright 2016 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\npackage io.realm;\n\nimport android.content.Context;\nimport androidx.test.platform.app.InstrumentationRegistry;\nimport androidx.test.ext.junit.runners.AndroidJUnit4;\n\nimport org.hamcrest.CoreMatchers;\nimport org.junit.After;\nimport org.junit.Before;\nimport org.junit.Rule;\nimport org.junit.Test;\nimport org.junit.rules.ExpectedException;\nimport org.junit.runner.RunWith;\n\nimport java.io.IOException;\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.UUID;\nimport java.util.concurrent.atomic.AtomicInteger;\n\nimport io.realm.entities.AllJavaTypes;\nimport io.realm.entities.BacklinkWithOverridenNames;\nimport io.realm.entities.BacklinksSource;\nimport io.realm.entities.BacklinksTarget;\nimport io.realm.exceptions.RealmException;\nimport io.realm.exceptions.RealmMigrationNeededException;\nimport io.realm.internal.OsObjectSchemaInfo;\nimport io.realm.internal.Property;\nimport io.realm.internal.RealmProxyMediator;\nimport io.realm.rule.RunInLooperThread;\nimport io.realm.rule.RunTestInLooperThread;\n\nimport static org.junit.Assert.assertEquals;\nimport static org.junit.Assert.assertFalse;\nimport static org.junit.Assert.assertNotNull;\nimport static org.junit.Assert.assertThat;\nimport static org.junit.Assert.assertTrue;\nimport static org.junit.Assert.fail;\nimport static org.mockito.Mockito.spy;\nimport static org.mockito.Mockito.when;\n\n\n@RunWith(AndroidJUnit4.class)\npublic class LinkingObjectsManagedTests {\n    private interface PostConditions {\n        void run(Realm realm);\n    }\n\n    @Rule\n    public final TestRealmConfigurationFactory configFactory = new TestRealmConfigurationFactory();\n    @Rule\n    public final RunInLooperThread looperThread = new RunInLooperThread();\n    @Rule\n    public final ExpectedException thrown = ExpectedException.none();\n\n    private Realm realm;\n    private Context context;\n\n    @Before\n    public void setUp() {\n        context = InstrumentationRegistry.getInstrumentation().getContext();\n\n        RealmConfiguration realmConfig = configFactory.createConfiguration();\n        realm = Realm.getInstance(realmConfig);\n    }\n\n    @After\n    public void tearDown() {\n        if (realm != null) {\n            realm.close();\n        }\n    }\n\n    // Setting the linked object field creates the correct backlink\n    @Test\n    public void basic_singleBacklinkObject() {\n        realm.beginTransaction();\n        AllJavaTypes child = realm.createObject(AllJavaTypes.class, 1);\n        AllJavaTypes parent = realm.createObject(AllJavaTypes.class, 2);\n        parent.setFieldObject(child);\n        realm.commitTransaction();\n\n        assertEquals(1, child.getObjectParents().size());\n        assertTrue(child.getObjectParents().contains(parent));\n    }\n\n    // Setting a linked list field creates the correct backlink\n    @Test\n    public void basic_singleBacklinkList() {\n        realm.beginTransaction();\n        AllJavaTypes child = realm.createObject(AllJavaTypes.class, 1);\n        AllJavaTypes parent = realm.createObject(AllJavaTypes.class, 2);\n        parent.getFieldList().add(child);\n        realm.commitTransaction();\n\n        assertEquals(1, child.getListParents().size());\n        assertTrue(child.getListParents().contains(parent));\n    }\n\n    // Setting multiple object links creates multiple backlinks\n    @Test\n    public void basic_multipleBacklinksObject() {\n        realm.beginTransaction();\n        AllJavaTypes child = realm.createObject(AllJavaTypes.class, 1);\n        AllJavaTypes parent1 = realm.createObject(AllJavaTypes.class, 2);\n        AllJavaTypes parent2 = realm.createObject(AllJavaTypes.class, 3);\n        parent1.setFieldObject(child);\n        parent2.setFieldObject(child);\n        realm.commitTransaction();\n        assertEquals(2, child.getObjectParents().size());\n    }\n\n    // Setting multiple list links creates multiple backlinks\n    @Test\n    public void basic_multipleBacklinksList() {\n        realm.beginTransaction();\n        AllJavaTypes child = realm.createObject(AllJavaTypes.class, 1);\n        AllJavaTypes parent1 = realm.createObject(AllJavaTypes.class, 2);\n        AllJavaTypes parent2 = realm.createObject(AllJavaTypes.class, 3);\n        parent1.getFieldList().add(child);\n        parent2.getFieldList().add(child);\n        realm.commitTransaction();\n        assertEquals(2, child.getListParents().size());\n    }\n\n    // Adding multiple list links creates multiple backlinks,\n    // even if the links are to a single object\n    @Test\n    public void basic_multipleReferencesFromParentList() {\n        realm.beginTransaction();\n        AllJavaTypes child = realm.createObject(AllJavaTypes.class, 1);\n        AllJavaTypes parent = realm.createObject(AllJavaTypes.class, 2);\n        parent.getFieldList().add(child);\n        parent.getFieldList().add(child);\n        realm.commitTransaction();\n\n        // One entry for each reference, so two references from a LinkList will\n        // result in two backlinks.\n        assertEquals(2, child.getListParents().size());\n\n        assertEquals(parent, child.getListParents().first());\n        assertEquals(parent, child.getListParents().last());\n    }\n\n    // This test reproduces https://github.com/realm/realm-java/issues/4487\n    @Test\n    public void issue4487_checkIfTableIsCorrect() {\n        realm.beginTransaction();\n        final BacklinksTarget target = realm.createObject(BacklinksTarget.class);\n        target.setId(1);\n        final BacklinksSource source = realm.createObject(BacklinksSource.class);\n        source.setChild(target);\n        realm.commitTransaction();\n\n        final RealmResults<BacklinksSource> parents = target.getParents();\n        final BacklinksSource sourceFromBacklinks = parents.first();\n\n        assertEquals(source, sourceFromBacklinks);\n    }\n\n    // A listener registered on the backlinked object should not be called after the listener is removed\n    @Test\n    @RunTestInLooperThread\n    public void notification_notSentAfterUnregisterListenerModelObject() {\n        final Realm looperThreadRealm = looperThread.getRealm();\n\n        looperThreadRealm.beginTransaction();\n        AllJavaTypes child = looperThreadRealm.createObject(AllJavaTypes.class, 10);\n        looperThreadRealm.commitTransaction();\n\n        RealmChangeListener<AllJavaTypes> listener = new RealmChangeListener<AllJavaTypes>() {\n            @Override\n            public void onChange(AllJavaTypes object) {\n                fail(\"Not expecting notification after unregister\");\n            }\n        };\n        child.addChangeListener(listener);\n        child.removeChangeListener(listener);\n\n        looperThreadRealm.beginTransaction();\n        AllJavaTypes parent = looperThreadRealm.createObject(AllJavaTypes.class, 1);\n        parent.setFieldObject(child);\n        looperThreadRealm.commitTransaction();\n\n        verifyPostConditions(\n                looperThreadRealm,\n                new PostConditions() {\n                    @Override\n                    public void run(Realm realm) {\n                        assertEquals(2, looperThreadRealm.where(AllJavaTypes.class).findAll().size());\n                    }\n                },\n                child,\n                parent);\n    }\n\n    // A listener registered on the backlinked field should be called when a commit adds a backlink\n    @Test\n    @RunTestInLooperThread\n    public void notification_onCommitRealmResults() {\n        final Realm looperThreadRealm = looperThread.getRealm();\n\n        looperThreadRealm.beginTransaction();\n        AllJavaTypes child = looperThreadRealm.createObject(AllJavaTypes.class, 10);\n        looperThreadRealm.commitTransaction();\n\n        final AtomicInteger counter = new AtomicInteger(0);\n        RealmChangeListener<RealmResults<AllJavaTypes>> listener = new RealmChangeListener<RealmResults<AllJavaTypes>>() {\n            @Override\n            public void onChange(RealmResults<AllJavaTypes> object) {\n                counter.incrementAndGet();\n            }\n        };\n        child.getObjectParents().addChangeListener(listener);\n\n        looperThreadRealm.beginTransaction();\n        AllJavaTypes parent = looperThreadRealm.createObject(AllJavaTypes.class, 1);\n        parent.setFieldObject(child);\n        looperThreadRealm.commitTransaction();\n\n        verifyPostConditions(\n                looperThreadRealm,\n                new PostConditions() {\n                    @Override\n                    public void run(Realm realm) {\n                        assertEquals(2, looperThreadRealm.where(AllJavaTypes.class).findAll().size());\n                        assertEquals(1, counter.get());\n                    }\n                },\n                child,\n                parent);\n    }\n\n    // A listener registered on the backlinked field should not be called after the listener is removed\n    @Test\n    @RunTestInLooperThread\n    public void notification_notSentAfterUnregisterListenerRealmResults() {\n        final Realm looperThreadRealm = looperThread.getRealm();\n\n        looperThreadRealm.beginTransaction();\n        AllJavaTypes child = looperThreadRealm.createObject(AllJavaTypes.class, 10);\n        looperThreadRealm.commitTransaction();\n\n        RealmChangeListener<RealmResults<AllJavaTypes>> listener = new RealmChangeListener<RealmResults<AllJavaTypes>>() {\n            @Override\n            public void onChange(RealmResults<AllJavaTypes> object) {\n                fail(\"Not expecting notification after unregister\");\n            }\n        };\n        RealmResults<AllJavaTypes> objParents = child.getObjectParents();\n        objParents.addChangeListener(listener);\n        objParents.removeChangeListener(listener);\n\n        looperThreadRealm.beginTransaction();\n        AllJavaTypes parent = looperThreadRealm.createObject(AllJavaTypes.class, 1);\n        parent.setFieldObject(child);\n        looperThreadRealm.commitTransaction();\n\n        verifyPostConditions(\n                looperThreadRealm,\n                new PostConditions() {\n                    @Override\n                    public void run(Realm realm) {\n                        assertEquals(2, looperThreadRealm.where(AllJavaTypes.class).findAll().size());\n                    }\n                },\n                child,\n                parent);\n    }\n\n    // A listener registered on the backlinked object should be called when a backlinked object is deleted\n    @Test\n    @RunTestInLooperThread\n    public void notification_onDeleteRealmResults() {\n        final Realm looperThreadRealm = looperThread.getRealm();\n\n        looperThreadRealm.beginTransaction();\n        AllJavaTypes child = looperThreadRealm.createObject(AllJavaTypes.class, 10);\n        AllJavaTypes parent = looperThreadRealm.createObject(AllJavaTypes.class, 1);\n        parent.setFieldObject(child);\n        looperThreadRealm.commitTransaction();\n\n        final AtomicInteger counter = new AtomicInteger(0);\n        RealmChangeListener<RealmResults<AllJavaTypes>> listener = new RealmChangeListener<RealmResults<AllJavaTypes>>() {\n            @Override\n            public void onChange(RealmResults<AllJavaTypes> object) {\n                counter.incrementAndGet();\n            }\n        };\n        child.getObjectParents().addChangeListener(listener);\n\n        looperThreadRealm.beginTransaction();\n        looperThreadRealm.where(AllJavaTypes.class).equalTo(\"fieldId\", 1).findAll().deleteAllFromRealm();\n        looperThreadRealm.commitTransaction();\n\n        verifyPostConditions(\n                looperThreadRealm,\n                new PostConditions() {\n                    @Override\n                    public void run(Realm realm) {\n                        assertEquals(1, looperThreadRealm.where(AllJavaTypes.class).findAll().size());\n                        assertEquals(1, counter.get());\n                    }\n                },\n                child,\n                parent);\n    }\n\n    // A listener registered on the backlinked object should not called for an unrelated change\n    @Test\n    @RunTestInLooperThread\n    public void notification_notSentOnUnrelatedChangeRealmResults() {\n        final Realm looperThreadRealm = looperThread.getRealm();\n\n        looperThreadRealm.beginTransaction();\n        AllJavaTypes child = looperThreadRealm.createObject(AllJavaTypes.class, 10);\n        AllJavaTypes parent = looperThreadRealm.createObject(AllJavaTypes.class, 1);\n        looperThreadRealm.commitTransaction();\n\n        RealmChangeListener<RealmResults<AllJavaTypes>> listener = new RealmChangeListener<RealmResults<AllJavaTypes>>() {\n            @Override\n            public void onChange(RealmResults<AllJavaTypes> object) {\n                fail(\"Not expecting notification after unregister\");\n            }\n        };\n        child.getObjectParents().addChangeListener(listener);\n\n        looperThreadRealm.beginTransaction();\n        looperThreadRealm.where(AllJavaTypes.class).equalTo(\"fieldId\", 1).findAll().deleteAllFromRealm();\n        looperThreadRealm.commitTransaction();\n\n        verifyPostConditions(\n                looperThreadRealm,\n                new PostConditions() {\n                    @Override\n                    public void run(Realm realm) {\n                        assertEquals(1, looperThreadRealm.where(AllJavaTypes.class).findAll().size());\n                    }\n                },\n                child,\n                parent);\n    }\n\n    // Fields annotated with @LinkingObjects should not be affected by JSON updates\n    @Test\n    public void json_updateObject() {\n        realm.beginTransaction();\n        AllJavaTypes child = realm.createObject(AllJavaTypes.class, 1);\n        AllJavaTypes parent = realm.createObject(AllJavaTypes.class, 2);\n        parent.setFieldObject(child);\n        realm.commitTransaction();\n\n        RealmResults<AllJavaTypes> parents = child.getObjectParents();\n        assertNotNull(parents);\n        assertEquals(1, parents.size());\n        assertTrue(parents.contains(parent));\n\n        realm.beginTransaction();\n        try {\n            realm.createOrUpdateAllFromJson(AllJavaTypes.class, \"[{ \\\"fieldId\\\" : 1, \\\"objectParents\\\" : null }]\");\n        } catch (RealmException e) {\n            fail(\"Failed loading JSON\" + e);\n        }\n        realm.commitTransaction();\n\n        parents = child.getObjectParents();\n        assertNotNull(parents);\n        assertEquals(1, parents.size());\n        assertTrue(parents.contains(parent));\n    }\n\n    // Fields annotated with @LinkingObjects should not be affected by JSON updates\n    @Test\n    public void json_updateList() {\n        realm.beginTransaction();\n        AllJavaTypes child = realm.createObject(AllJavaTypes.class, 1);\n        AllJavaTypes parent = realm.createObject(AllJavaTypes.class, 2);\n        parent.getFieldList().add(child);\n        realm.commitTransaction();\n\n        RealmResults<AllJavaTypes> parents = child.getListParents();\n        assertNotNull(parents);\n        assertEquals(1, parents.size());\n        assertTrue(parents.contains(parent));\n\n        realm.beginTransaction();\n        try {\n            realm.createOrUpdateAllFromJson(AllJavaTypes.class, \"[{ \\\"fieldId\\\" : 1, \\\"listParents\\\" : null }]\");\n        } catch (RealmException e) {\n            fail(\"Failed loading JSON\" + e);\n        }\n        realm.commitTransaction();\n\n        parents = child.getListParents();\n        assertNotNull(parents);\n        assertEquals(1, parents.size());\n        assertTrue(parents.contains(parent));\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void linkingObjects_IllegalStateException_ifNotYetLoaded() {\n        final Realm realm = looperThread.getRealm();\n\n        realm.executeTransaction(new Realm.Transaction() {\n            @Override\n            public void execute(Realm realm) {\n                final BacklinksTarget target = realm.createObject(BacklinksTarget.class);\n                target.setId(1);\n\n                final BacklinksSource source = realm.createObject(BacklinksSource.class);\n                source.setChild(target);\n            }\n        });\n\n\n        final BacklinksTarget targetAsync = realm.where(BacklinksTarget.class)\n                .equalTo(BacklinksTarget.FIELD_ID, 1L).findFirstAsync();\n        // precondition\n        assertFalse(targetAsync.isLoaded());\n\n        try {\n            //noinspection ResultOfMethodCallIgnored\n            targetAsync.getParents();\n            fail();\n        } catch (IllegalStateException ignore) {\n        }\n        looperThread.testComplete();\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void linkingObjects_IllegalStateException_ifDeleted() {\n        final Realm realm = looperThread.getRealm();\n\n        realm.executeTransaction(new Realm.Transaction() {\n            @Override\n            public void execute(Realm realm) {\n                final BacklinksTarget target = realm.createObject(BacklinksTarget.class);\n                target.setId(1);\n\n                final BacklinksSource source = realm.createObject(BacklinksSource.class);\n                source.setChild(target);\n            }\n        });\n\n        final BacklinksTarget target = realm.where(BacklinksTarget.class)\n                .equalTo(BacklinksTarget.FIELD_ID, 1L).findFirst();\n\n        assertNotNull(target);\n\n        realm.executeTransaction(new Realm.Transaction() {\n            @Override\n            public void execute(Realm realm) {\n                target.deleteFromRealm();\n            }\n        });\n\n        // precondition\n        assertFalse(target.isValid());\n\n        try {\n            //noinspection ResultOfMethodCallIgnored\n            target.getParents();\n            fail();\n        } catch (IllegalStateException ignore) {\n        }\n        looperThread.testComplete();\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void linkingObjects_IllegalStateException_ifDeletedIndirectly() {\n        final Realm realm = looperThread.getRealm();\n\n        realm.executeTransaction(new Realm.Transaction() {\n            @Override\n            public void execute(Realm realm) {\n                final BacklinksTarget target1 = realm.createObject(BacklinksTarget.class);\n                target1.setId(1);\n\n                final BacklinksSource source = realm.createObject(BacklinksSource.class);\n                source.setChild(target1);\n            }\n        });\n\n        final BacklinksTarget target = realm.where(BacklinksTarget.class)\n                .equalTo(BacklinksTarget.FIELD_ID, 1L).findFirst();\n\n        realm.executeTransaction(new Realm.Transaction() {\n            @Override\n            public void execute(Realm realm) {\n                // delete target object indirectly\n                realm.where(BacklinksTarget.class).findAll().deleteAllFromRealm();\n            }\n        });\n\n        assertNotNull(target);\n\n        // precondition\n        assertFalse(target.isValid());\n\n        try {\n            //noinspection ResultOfMethodCallIgnored\n            target.getParents();\n            fail();\n        } catch (IllegalStateException ignore) {\n        }\n        looperThread.testComplete();\n    }\n\n    /**\n     * Table validation should fail if the backlinked column already exists in the target table.\n     * The realm `backlinks-fieldInUse.realm` contains the classes `BacklinksSource` and `BacklinksTarget`\n     * except that in the definition of {@code BacklinksTarget}, the field parent is defined as:\n     * <pre>\n     * {@code\n     *     private RealmList<BacklinksSource> parents;\n     * }\n     * </pre>\n     *\n     * <p/>\n     * The backlinked field does exist but it is list of links to {@code BacklinksSource} children\n     * not a list of backlinks to  {@code BacklinksSource} parents of which the {@code BacklinksTarget}\n     * is a child.\n     */\n    @Test\n    public void migration_backlinkedFieldInUse() {\n        final String realmName = \"backlinks-fieldInUse.realm\";\n\n        RealmConfiguration realmConfig = configFactory.createConfigurationBuilder()\n                .name(realmName)\n                .schema(BacklinksSource.class, BacklinksTarget.class)\n                .build();\n\n        try {\n            configFactory.copyRealmFromAssets(context, realmName, realmName);\n\n            Realm localRealm = Realm.getInstance(realmConfig);\n            localRealm.close();\n            fail(\"A migration should have been required\");\n        } catch (IOException e) {\n            fail(\"Failed copying realm\");\n        } catch (RealmMigrationNeededException expected) {\n            assertThat(expected.getMessage(),\n                    CoreMatchers.allOf(\n                            CoreMatchers.containsString(\"Property 'BacklinksSource.name' has been added\"),\n                            CoreMatchers.containsString(\"Property 'BacklinksTarget.parents' has been removed\")));\n        } finally {\n            Realm.deleteRealm(realmConfig);\n        }\n    }\n\n    /**\n     * Schema validation should fail if the backlinked column points to a non-existent class.\n     * Since the configuration contains only the single class `BacklinksTarget`, basic validation passes.\n     * The computed property validation, however, should fail, seeking the `BacklinksSource` table.\n     */\n    @Test\n    public void migration_backlinkedSourceClassDoesntExist() throws IOException {\n        final String realmName = \"backlinks-missingSourceClass.realm\";\n        RealmConfiguration realmConfig = configFactory.createConfigurationBuilder()\n                .name(realmName)\n                .schema(BacklinksTarget.class)\n                .build();\n\n        try {\n            Realm localRealm = Realm.getInstance(realmConfig);\n            localRealm.close();\n            fail();\n        } catch (IllegalStateException expected) {\n            assertThat(expected.getMessage(), CoreMatchers.containsString(\n                    \"Property 'BacklinksTarget.parents' of type 'linking objects' has unknown object type 'BacklinksSource'\"));\n        }\n    }\n\n    /**\n     * Schema validation should fail if the backlinked column points to a non-existent field in the source class.\n     */\n    @Test\n    public void migration_backlinkedSourceFieldDoesntExist() throws ClassNotFoundException {\n        final String realmName = \"backlinks-missingSourceField.realm\";\n        RealmConfiguration realmConfig = configFactory.createConfigurationBuilder()\n                .name(realmName)\n                .schema(BacklinksTarget.class, BacklinksSource.class)\n                .build();\n\n        // Mock the schema info so the only difference compared with the original schema is that the LinkingObject field\n        // points to BacklinksSource.childNotExist.\n        OsObjectSchemaInfo targetSchemaInfo = new OsObjectSchemaInfo.Builder(\"BacklinksTarget\", false, 1, 1)\n                .addPersistedProperty(\"id\", \"\",RealmFieldType.INTEGER, !Property.PRIMARY_KEY, !Property.INDEXED, Property.REQUIRED)\n                .addComputedLinkProperty(\"parents\", \"BacklinksSource\", \"childNotExist\" /*\"child\" is the original value*/)\n                .build();\n        OsObjectSchemaInfo sourceSchemaInfo = new OsObjectSchemaInfo.Builder(\"BacklinksSource\", false, 2, 0)\n                .addPersistedProperty(\"name\", \"\",RealmFieldType.STRING, !Property.PRIMARY_KEY, !Property.INDEXED, !Property.REQUIRED)\n                .addPersistedLinkProperty(\"child\", \"\",RealmFieldType.OBJECT, \"BacklinksTarget\")\n                .build();\n        Map<Class<? extends RealmModel>, OsObjectSchemaInfo> infoMap =\n                new HashMap<Class<? extends RealmModel>, OsObjectSchemaInfo>();\n        infoMap.put(BacklinksTarget.class, targetSchemaInfo);\n        infoMap.put(BacklinksSource.class, sourceSchemaInfo);\n\n        RealmProxyMediator mediator = spy(realmConfig.getSchemaMediator());\n        when(mediator.getExpectedObjectSchemaInfoMap()).thenReturn(infoMap);\n        RealmConfiguration spyConfig = spy(realmConfig);\n        when(spyConfig.getSchemaMediator()).thenReturn(mediator);\n\n        try {\n            Realm localRealm = Realm.getInstance(spyConfig);\n            localRealm.close();\n            fail();\n        } catch (IllegalStateException expected) {\n            assertThat(expected.getMessage(), CoreMatchers.containsString(\n                    \"Property 'BacklinksSource.childNotExist' declared as origin of linking objects property 'BacklinksTarget.parents' does not exist\"\n            ));\n        }\n    }\n\n    /**\n     * Table validation should fail if the backlinked column points to a field of the wrong type.\n     */\n    @Test\n    public void migration_backlinkedSourceFieldWrongType() {\n        final String realmName = \"backlinks-sourceFieldWrongType.realm\";\n\n        RealmConfiguration realmConfig = configFactory.createConfigurationBuilder()\n                .name(realmName)\n                .schema(BacklinksTarget.class, BacklinksSource.class)\n                .build();\n\n        // Mock the schema info so the only difference compared with the original schema is that BacklinksSource.child\n        // type is changed to BacklinksSource from BacklinksTarget.\n        OsObjectSchemaInfo targetSchemaInfo = new OsObjectSchemaInfo.Builder(\"BacklinksTarget\", false, 0, 1)\n                .addComputedLinkProperty(\"parents\", \"BacklinksSource\", \"child\")\n                .build();\n        OsObjectSchemaInfo sourceSchemaInfo = new OsObjectSchemaInfo.Builder(\"BacklinksSource\", false, 2, 0)\n                .addPersistedProperty(\"\", \"name\", RealmFieldType.STRING, !Property.PRIMARY_KEY, !Property.INDEXED, !Property.REQUIRED)\n                .addPersistedLinkProperty(\"\",\"child\", RealmFieldType.OBJECT,\n                        \"BacklinksSource\"/*\"BacklinksTarget\" is the original value*/)\n                .build();\n        Map<Class<? extends RealmModel>, OsObjectSchemaInfo> infoMap =\n                new HashMap<Class<? extends RealmModel>, OsObjectSchemaInfo>();\n        infoMap.put(BacklinksTarget.class, targetSchemaInfo);\n        infoMap.put(BacklinksSource.class, sourceSchemaInfo);\n\n        RealmProxyMediator mediator = spy(realmConfig.getSchemaMediator());\n        when(mediator.getExpectedObjectSchemaInfoMap()).thenReturn(infoMap);\n        RealmConfiguration spyConfig = spy(realmConfig);\n        when(spyConfig.getSchemaMediator()).thenReturn(mediator);\n\n        Realm localRealm = null;\n        try {\n            localRealm = Realm.getInstance(spyConfig);\n            fail();\n        } catch (IllegalStateException expected) {\n            assertThat(expected.getMessage(), CoreMatchers.containsString(\n                    \"Property 'BacklinksSource.child' declared as origin of linking objects property 'BacklinksTarget.parents' links to type 'BacklinksSource'\"\n            ));\n        } finally {\n            if (localRealm != null) {\n                localRealm.close();\n            }\n        }\n    }\n\n    // Distinct works for backlinks\n    @Test\n    public void query_multipleReferencesWithDistinct() {\n        realm.beginTransaction();\n        AllJavaTypes child = realm.createObject(AllJavaTypes.class, 1);\n        AllJavaTypes parent = realm.createObject(AllJavaTypes.class, 2);\n        parent.getFieldList().add(child);\n        parent.getFieldList().add(child);\n        realm.commitTransaction();\n\n        assertEquals(2, child.getListParents().size());\n\n        RealmResults<AllJavaTypes> distinctParents = child.getListParents().where().distinct(\"fieldId\").findAll();\n        assertEquals(1, distinctParents.size());\n        assertTrue(child.getListParents().contains(parent));\n    }\n\n\n    @Test\n    public void copyToRealm_modelWithRenamedTargetFields() {\n        realm.beginTransaction();\n        BacklinkWithOverridenNames obj = new BacklinkWithOverridenNames(UUID.randomUUID().toString());\n        realm.copyToRealmOrUpdate(obj);\n        realm.commitTransaction();\n        assertEquals(1, realm.where(BacklinkWithOverridenNames.class).count());\n    }\n\n    @Test\n    public void insert_modelWithRenamedTargetFields() {\n        realm.beginTransaction();\n        BacklinkWithOverridenNames obj = new BacklinkWithOverridenNames(UUID.randomUUID().toString());\n        realm.insertOrUpdate(obj);\n        realm.commitTransaction();\n        assertEquals(1, realm.where(BacklinkWithOverridenNames.class).count());\n    }\n\n    @Test\n    public void query_modelWithRenamedFields() {\n        assertEquals(0, realm.where(BacklinkWithOverridenNames.class).equalTo(\"child.id\", \"foo\").count());\n        assertEquals(0, realm.where(BacklinkWithOverridenNames.class).equalTo(\"parents.id\", \"foo\").count());\n    }\n\n\n    // Based on a quick conversation with Christian Melchior and Mark Rowe,\n    // it appears that notifications are enqueued, briefly, on a non-Java\n    // thread.  That makes their delivery onto the looper thread unpredictable.\n    // Fortunately, it appears that beginning a transaction forces the delivery of\n    // any outstanding notifications.\n    // The closure passed to this method will be run *after* the body of the test\n    // completes, and *after* the notifications have been delivered.  Because the\n    // test method has been popped off the stack any objects referenced only from\n    // the stack are subject to GC.  To hang on to them, until the test completes,\n    // just pass them to the final vararg to this method.\n    // @zaki50 has some evidence that notifications are delivered on a commit.\n    // If that is the case, we may be able to eliminate the ugly begin-commit\n    // that is the prologue to this method.\n    private void verifyPostConditions(final Realm realm, final PostConditions test, final Object... refs) {\n        realm.beginTransaction();\n        realm.commitTransaction();\n\n        // Runnable is guaranteed to be enqueued on the Looper queue, after the notifications\n        for (Object ref : refs) {\n            looperThread.keepStrongReference(ref);\n        }\n        looperThread.postRunnable(\n                new Runnable() {\n                    @Override\n                    public void run() {\n                        test.run(realm);\n                        looperThread.testComplete();\n                    }\n                });\n    }\n}\n\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/LinkingObjectsQueryTests.java",
    "content": "/*\n * Copyright 2017 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 */\npackage io.realm;\n\nimport org.bson.types.Decimal128;\nimport org.bson.types.ObjectId;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\n\nimport java.math.BigDecimal;\nimport java.util.Date;\n\nimport androidx.test.ext.junit.runners.AndroidJUnit4;\nimport io.realm.entities.AllJavaTypesUnsupportedTypes;\nimport io.realm.entities.BacklinksTarget;\nimport io.realm.entities.NullTypes;\n\nimport static org.junit.Assert.assertEquals;\nimport static org.junit.Assert.assertTrue;\nimport static org.junit.Assert.fail;\n\n@RunWith(AndroidJUnit4.class)\npublic class LinkingObjectsQueryTests extends QueryTests {\n\n    // All the basic tests for is[Not](Equal|Null) are in RealmQueryTests\n\n\n    // Query on a field descriptor starting with a backlink\n    // Build a simple object graph.\n    // The test objects are:\n    //             gen1\n    //             / \\\n    //         gen2A gen2B\n    //           \\\\   //\n    //            gen3\n    //  /  = object ref\n    //  // = list ref\n    @Test\n    public void query_startWithBacklink() {\n        realm.beginTransaction();\n        AllJavaTypesUnsupportedTypes gen1 = realm.createObject(AllJavaTypesUnsupportedTypes.class, 10);\n\n        AllJavaTypesUnsupportedTypes gen2A = realm.createObject(AllJavaTypesUnsupportedTypes.class, 1);\n        gen2A.setFieldObject(gen1);\n\n        AllJavaTypesUnsupportedTypes gen2B = realm.createObject(AllJavaTypesUnsupportedTypes.class, 2);\n        gen2B.setFieldObject(gen1);\n\n        AllJavaTypesUnsupportedTypes gen3 = realm.createObject(AllJavaTypesUnsupportedTypes.class, 3);\n        RealmList<AllJavaTypesUnsupportedTypes> parents = gen3.getFieldList();\n        parents.add(gen2A);\n        parents.add(gen2B);\n\n        realm.commitTransaction();\n\n        // row 0: backlink to rows 1 and 2; row 1 link to row 0, included\n        // row 1: no backlink, not included\n        // row 2: no backlink, not included\n        // row 3: no backlink, not included\n        // summary: 1 row (gen1)\n        RealmResults<AllJavaTypesUnsupportedTypes> result = realm.where(AllJavaTypesUnsupportedTypes.class)\n                .greaterThan(AllJavaTypesUnsupportedTypes.FIELD_LO_OBJECT + \".\" + AllJavaTypesUnsupportedTypes.FIELD_OBJECT + \".\" + AllJavaTypesUnsupportedTypes.FIELD_ID, 1)\n                .findAll();\n        assertEquals(1, result.size());\n        assertTrue(result.contains(gen1));\n    }\n\n    // Query on a field descriptor that has a backlink in the middle\n    // Build a simple object graph.\n    // The test objects are:\n    //             gen1\n    //             / \\\n    //         gen2A gen2B\n    //           \\\\   //\n    //            gen3\n    //  /  = object ref\n    //  // = list ref\n    @Test\n    public void query_backlinkInMiddle() {\n        realm.beginTransaction();\n        AllJavaTypesUnsupportedTypes gen1 = realm.createObject(AllJavaTypesUnsupportedTypes.class, 10);\n\n        AllJavaTypesUnsupportedTypes gen2A = realm.createObject(AllJavaTypesUnsupportedTypes.class, 1);\n        gen2A.setFieldObject(gen1);\n\n        AllJavaTypesUnsupportedTypes gen2B = realm.createObject(AllJavaTypesUnsupportedTypes.class, 2);\n        gen2B.setFieldObject(gen1);\n\n        AllJavaTypesUnsupportedTypes gen3 = realm.createObject(AllJavaTypesUnsupportedTypes.class, 3);\n        RealmList<AllJavaTypesUnsupportedTypes> parents = gen3.getFieldList();\n        parents.add(gen2A);\n        parents.add(gen2B);\n\n        realm.commitTransaction();\n\n        // row 0: no link, not included\n        // row 1: link to row 0, backlink to rows 1 and 2, row 2 has id < 2, included\n        // row 2: link to row 0, backlink to rows 1 and 2, row 2 has id < 2, included\n        // row 3: no link, not included\n        // summary: 2 rows (gen2A and gen2B)\n        RealmResults<AllJavaTypesUnsupportedTypes> result = realm.where(AllJavaTypesUnsupportedTypes.class)\n                .lessThan(AllJavaTypesUnsupportedTypes.FIELD_OBJECT + \".\" + AllJavaTypesUnsupportedTypes.FIELD_LO_OBJECT + \".\" + AllJavaTypesUnsupportedTypes.FIELD_ID, 2)\n                .findAll();\n        assertEquals(2, result.size());\n        assertTrue(result.contains(gen2A));\n        assertTrue(result.contains(gen2B));\n    }\n\n    // Tests isNotNull on link's nullable field.\n    @Test\n    public void isNull_object() {\n        populateTestRealmForNullTests(realm);\n\n        // 1 String\n        assertEquals(1, realm.where(NullTypes.class).isNull(\n                NullTypes.FIELD_LO_OBJECT + \".\" + NullTypes.FIELD_STRING_NULL).count());\n        // 2 Bytes\n        assertEquals(1, realm.where(NullTypes.class).isNull(\n                NullTypes.FIELD_LO_OBJECT + \".\" + NullTypes.FIELD_BYTES_NULL).count());\n        // 3 Boolean\n        assertEquals(1, realm.where(NullTypes.class).isNull(\n                NullTypes.FIELD_LO_OBJECT + \".\" + NullTypes.FIELD_BOOLEAN_NULL).count());\n        // 4 Byte\n        assertEquals(1, realm.where(NullTypes.class).isNull(\n                NullTypes.FIELD_LO_OBJECT + \".\" + NullTypes.FIELD_BYTE_NULL).count());\n        // 5 Short\n        assertEquals(1, realm.where(NullTypes.class).isNull(\n                NullTypes.FIELD_LO_OBJECT + \".\" + NullTypes.FIELD_SHORT_NULL).count());\n        // 6 Integer\n        assertEquals(1, realm.where(NullTypes.class).isNull(\n                NullTypes.FIELD_LO_OBJECT + \".\" + NullTypes.FIELD_INTEGER_NULL).count());\n        // 7 Long\n        assertEquals(1, realm.where(NullTypes.class).isNull(\n                NullTypes.FIELD_LO_OBJECT + \".\" + NullTypes.FIELD_LONG_NULL).count());\n        // 8 Float\n        assertEquals(1, realm.where(NullTypes.class).isNull(\n                NullTypes.FIELD_LO_OBJECT + \".\" + NullTypes.FIELD_FLOAT_NULL).count());\n        // 9 Double\n        assertEquals(1, realm.where(NullTypes.class).isNull(\n                NullTypes.FIELD_LO_OBJECT + \".\" + NullTypes.FIELD_DOUBLE_NULL).count());\n        // 10 Date\n        assertEquals(1, realm.where(NullTypes.class).isNull(\n                NullTypes.FIELD_LO_OBJECT + \".\" + NullTypes.FIELD_DATE_NULL).count());\n        // Decimal128\n        assertEquals(1, realm.where(NullTypes.class).isNull(\n                NullTypes.FIELD_LO_OBJECT + \".\" + NullTypes.FIELD_DECIMAL128_NULL).count());\n        // ObjectId\n        assertEquals(1, realm.where(NullTypes.class).isNull(\n                NullTypes.FIELD_LO_OBJECT + \".\" + NullTypes.FIELD_OBJECT_ID_NULL).count());\n    }\n\n    // Tests isNull on link's nullable field.\n    @Test\n    public void isNull_list() {\n        populateTestRealmForNullTests(realm);\n\n        // 1 String\n        assertEquals(1, realm.where(NullTypes.class).isNull(\n                NullTypes.FIELD_LO_LIST + \".\" + NullTypes.FIELD_STRING_NULL).count());\n        // 2 Bytes\n        assertEquals(1, realm.where(NullTypes.class).isNull(\n                NullTypes.FIELD_LO_LIST + \".\" + NullTypes.FIELD_BYTES_NULL).count());\n        // 3 Boolean\n        assertEquals(1, realm.where(NullTypes.class).isNull(\n                NullTypes.FIELD_LO_LIST + \".\" + NullTypes.FIELD_BOOLEAN_NULL).count());\n        // 4 Byte\n        assertEquals(1, realm.where(NullTypes.class).isNull(\n                NullTypes.FIELD_LO_LIST + \".\" + NullTypes.FIELD_BYTE_NULL).count());\n        // 5 Short\n        assertEquals(1, realm.where(NullTypes.class).isNull(\n                NullTypes.FIELD_LO_LIST + \".\" + NullTypes.FIELD_SHORT_NULL).count());\n        // 6 Integer\n        assertEquals(1, realm.where(NullTypes.class).isNull(\n                NullTypes.FIELD_LO_LIST + \".\" + NullTypes.FIELD_INTEGER_NULL).count());\n        // 7 Long\n        assertEquals(1, realm.where(NullTypes.class).isNull(\n                NullTypes.FIELD_LO_LIST + \".\" + NullTypes.FIELD_LONG_NULL).count());\n        // 8 Float\n        assertEquals(1, realm.where(NullTypes.class).isNull(\n                NullTypes.FIELD_LO_LIST + \".\" + NullTypes.FIELD_FLOAT_NULL).count());\n        // 9 Double\n        assertEquals(1, realm.where(NullTypes.class).isNull(\n                NullTypes.FIELD_LO_LIST + \".\" + NullTypes.FIELD_DOUBLE_NULL).count());\n        // 10 Date\n        assertEquals(1, realm.where(NullTypes.class).isNull(\n                NullTypes.FIELD_LO_LIST + \".\" + NullTypes.FIELD_DATE_NULL).count());\n        // 10 Decimal128\n        assertEquals(1, realm.where(NullTypes.class).isNull(\n                NullTypes.FIELD_LO_LIST + \".\" + NullTypes.FIELD_DECIMAL128_NULL).count());\n        // 10 ObjectId\n        assertEquals(1, realm.where(NullTypes.class).isNull(\n                NullTypes.FIELD_LO_LIST + \".\" + NullTypes.FIELD_OBJECT_ID_NULL).count());\n    }\n\n    @Test\n    public void isNull_unsupported() {\n        // Tests for other unsupported null types are in RealmQueryTests\n        try {\n            realm.where(NullTypes.class).isNull(NullTypes.FIELD_LO_OBJECT);\n            fail(\"isNull should throw on type LINKING_OBJECT(14) targeting an OBJECT\");\n        } catch (IllegalArgumentException expected) {\n            assertTrue(expected.getMessage().contains(\"Illegal Argument: Cannot compare linklist ('@links.NullTypes.fieldObjectNull')\"));\n        }\n        try {\n            realm.where(NullTypes.class).isNull(NullTypes.FIELD_LO_LIST);\n            fail(\"isNull should throw on type LINKING_OBJECT(14) targeting a LIST\");\n        } catch (IllegalArgumentException expected) {\n            assertTrue(expected.getMessage().contains(\"Illegal Argument: Cannot compare linklist ('@links.NullTypes.fieldListNull')\"));\n        }\n    }\n\n    @Test\n    public void isNull_unsupportedLinkedTypes() {\n        // Tests for other unsupported null types are in RealmQueryTests\n        try {\n            realm.where(NullTypes.class).isNull(NullTypes.FIELD_OBJECT_NULL + \".\" + NullTypes.FIELD_LO_OBJECT);\n            fail(\"isNull should throw on nested linked fields (LINKING_OBJECT => OBJECT)\");\n        } catch (IllegalArgumentException expected) {\n            assertTrue(expected.getMessage().contains(\"Illegal Argument: Cannot compare linklist ('fieldObjectNull.@links.NullTypes.fieldObjectNull') with NULL\"));\n        }\n        try {\n            realm.where(NullTypes.class).isNull(NullTypes.FIELD_OBJECT_NULL + \".\" + NullTypes.FIELD_LO_LIST);\n            fail(\"isNull should throw on nested linked fields (LINKING_OBJECT => LIST)\");\n        } catch (IllegalArgumentException expected) {\n            assertTrue(expected.getMessage().contains(\"Illegal Argument: Cannot compare linklist ('fieldObjectNull.@links.NullTypes.fieldListNull') with NULL\"));\n        }\n    }\n\n    // Tests isNotNull on link's nullable field.\n    @Test\n    public void isNotNull_object() {\n        populateTestRealmForNullTests(realm);\n\n        // 1 String\n        assertEquals(1, realm.where(NullTypes.class).isNotNull(\n                NullTypes.FIELD_LO_OBJECT + \".\" + NullTypes.FIELD_STRING_NULL).count());\n        // 2 Bytes\n        assertEquals(1, realm.where(NullTypes.class).isNotNull(\n                NullTypes.FIELD_LO_OBJECT + \".\" + NullTypes.FIELD_BYTES_NULL).count());\n        // 3 Boolean\n        assertEquals(1, realm.where(NullTypes.class).isNotNull(\n                NullTypes.FIELD_LO_OBJECT + \".\" + NullTypes.FIELD_BOOLEAN_NULL).count());\n        // 4 Byte\n        assertEquals(1, realm.where(NullTypes.class).isNotNull(\n                NullTypes.FIELD_LO_OBJECT + \".\" + NullTypes.FIELD_BYTE_NULL).count());\n        // 5 Short\n        assertEquals(1, realm.where(NullTypes.class).isNotNull(\n                NullTypes.FIELD_LO_OBJECT + \".\" + NullTypes.FIELD_SHORT_NULL).count());\n        // 6 Integer\n        assertEquals(1, realm.where(NullTypes.class).isNotNull(\n                NullTypes.FIELD_LO_OBJECT + \".\" + NullTypes.FIELD_INTEGER_NULL).count());\n        // 7 Long\n        assertEquals(1, realm.where(NullTypes.class).isNotNull(\n                NullTypes.FIELD_LO_OBJECT + \".\" + NullTypes.FIELD_LONG_NULL).count());\n        // 8 Float\n        assertEquals(1, realm.where(NullTypes.class).isNotNull(\n                NullTypes.FIELD_LO_OBJECT + \".\" + NullTypes.FIELD_FLOAT_NULL).count());\n        // 9 Double\n        assertEquals(1, realm.where(NullTypes.class).isNotNull(\n                NullTypes.FIELD_LO_OBJECT + \".\" + NullTypes.FIELD_DOUBLE_NULL).count());\n        // 10 Date\n        assertEquals(1, realm.where(NullTypes.class).isNotNull(\n                NullTypes.FIELD_LO_OBJECT + \".\" + NullTypes.FIELD_DATE_NULL).count());\n        // 11 Decimal128\n        assertEquals(1, realm.where(NullTypes.class).isNotNull(\n                NullTypes.FIELD_LO_OBJECT + \".\" + NullTypes.FIELD_DECIMAL128_NULL).count());\n        // 12 ObjectId\n        assertEquals(1, realm.where(NullTypes.class).isNotNull(\n                NullTypes.FIELD_LO_OBJECT + \".\" + NullTypes.FIELD_OBJECT_ID_NULL).count());\n    }\n\n    // Tests isNotNull on link's nullable field.\n    @Test\n    public void isNotNull_list() {\n        populateTestRealmForNullTests(realm);\n\n        // 1 String\n        assertEquals(1, realm.where(NullTypes.class).isNotNull(\n                NullTypes.FIELD_LO_LIST + \".\" + NullTypes.FIELD_STRING_NULL).count());\n        // 2 Bytes\n        assertEquals(1, realm.where(NullTypes.class).isNotNull(\n                NullTypes.FIELD_LO_LIST + \".\" + NullTypes.FIELD_BYTES_NULL).count());\n        // 3 Boolean\n        assertEquals(1, realm.where(NullTypes.class).isNotNull(\n                NullTypes.FIELD_LO_LIST + \".\" + NullTypes.FIELD_BOOLEAN_NULL).count());\n        // 4 Byte\n        assertEquals(1, realm.where(NullTypes.class).isNotNull(\n                NullTypes.FIELD_LO_LIST + \".\" + NullTypes.FIELD_BYTE_NULL).count());\n        // 5 Short\n        assertEquals(1, realm.where(NullTypes.class).isNotNull(\n                NullTypes.FIELD_LO_LIST + \".\" + NullTypes.FIELD_SHORT_NULL).count());\n        // 6 Integer\n        assertEquals(1, realm.where(NullTypes.class).isNotNull(\n                NullTypes.FIELD_LO_LIST + \".\" + NullTypes.FIELD_INTEGER_NULL).count());\n        // 7 Long\n        assertEquals(1, realm.where(NullTypes.class).isNotNull(\n                NullTypes.FIELD_LO_LIST + \".\" + NullTypes.FIELD_LONG_NULL).count());\n        // 8 Float\n        assertEquals(1, realm.where(NullTypes.class).isNotNull(\n                NullTypes.FIELD_LO_LIST + \".\" + NullTypes.FIELD_FLOAT_NULL).count());\n        // 9 Double\n        assertEquals(1, realm.where(NullTypes.class).isNotNull(\n                NullTypes.FIELD_LO_LIST + \".\" + NullTypes.FIELD_DOUBLE_NULL).count());\n        // 10 Date\n        assertEquals(1, realm.where(NullTypes.class).isNotNull(\n                NullTypes.FIELD_LO_LIST + \".\" + NullTypes.FIELD_DATE_NULL).count());\n        // 11 Decimal128\n        assertEquals(1, realm.where(NullTypes.class).isNotNull(\n                NullTypes.FIELD_LO_LIST + \".\" + NullTypes.FIELD_DECIMAL128_NULL).count());\n        // 12 ObjectId\n        assertEquals(1, realm.where(NullTypes.class).isNotNull(\n                NullTypes.FIELD_LO_LIST + \".\" + NullTypes.FIELD_OBJECT_ID_NULL).count());\n\n    }\n\n    @Test\n    public void isNotNull_unsupported() {\n        // Tests for other unsupported not null types are in RealmQueryTests\n\n        try {\n            realm.where(NullTypes.class).isNotNull(NullTypes.FIELD_LO_OBJECT);\n            fail(\"isNotNull should throw on type LINKING_OBJECT(14) targeting an OBJECT\");\n        } catch (IllegalArgumentException expected) {\n            assertTrue(expected.getMessage().contains(\"Illegal Argument: Cannot compare linklist ('@links.NullTypes.fieldObjectNull')\"));\n        }\n        try {\n            realm.where(NullTypes.class).isNotNull(NullTypes.FIELD_LO_LIST);\n            fail(\"isNotNull should throw on type LINKING_OBJECT(14) targeting a LIST\");\n        } catch (IllegalArgumentException expected) {\n            assertTrue(expected.getMessage().contains(\"Illegal Argument: Cannot compare linklist ('@links.NullTypes.fieldListNull')\"));\n        }\n    }\n\n    @Test\n    public void isNotNull_unsupportedLinkedTypes() {\n        // Tests for other unsupported not null types are in RealmQueryTests\n        try {\n            realm.where(NullTypes.class).isNotNull(NullTypes.FIELD_OBJECT_NULL + \".\" + NullTypes.FIELD_LO_OBJECT);\n            fail(\"isNotNull should throw on nested linked fields (LINKING_OBJECT => OBJECT)\");\n        } catch (IllegalArgumentException expected) {\n            assertTrue(expected.getMessage().contains(\"Illegal Argument: Cannot compare linklist ('fieldObjectNull.@links.NullTypes.fieldObjectNull')\"));\n        }\n        try {\n            realm.where(NullTypes.class).isNotNull(NullTypes.FIELD_OBJECT_NULL + \".\" + NullTypes.FIELD_LO_LIST);\n            fail(\"isNotNull should throw on nested linked fields (LINKING_OBJECT => LIST)\");\n        } catch (IllegalArgumentException expected) {\n            assertTrue(expected.getMessage().contains(\"Illegal Argument: Cannot compare linklist ('fieldObjectNull.@links.NullTypes.fieldListNull'\"));\n        }\n    }\n\n    @Test\n    public void isEmpty_linkingObjects() {\n        createIsEmptyDataSet(realm);\n        for (RealmFieldType type : SUPPORTED_IS_EMPTY_TYPES) {\n            switch (type) {\n                case LINKING_OBJECTS:\n                    // Row 0: backlink to row 0; not included\n                    // Row 1: backlink to row 1; not included\n                    // Row 2: no backlink; included\n                    assertEquals(1, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_OBJECT).count());\n                    // Only row 1 has a linklist (and a backlink)\n                    assertEquals(1, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_LIST).count());\n                    break;\n                default:\n                    // tested in RealmQueryTests\n            }\n        }\n    }\n\n    @Test\n    public void isEmpty_multipleModelClasses() {\n        createLinkedDataSet(realm);\n        assertEquals(1, realm.where(BacklinksTarget.class).isEmpty(BacklinksTarget.FIELD_PARENTS).count());\n    }\n\n    @Test(expected = IllegalArgumentException.class)\n    public void equalTo_linkingObjectLast() {\n        createLinkedDataSet(realm);\n        realm.where(BacklinksTarget.class).equalTo(BacklinksTarget.FIELD_PARENTS, \"parents\");\n    }\n\n    @Test\n    public void isEmpty_acrossLink() {\n        createIsEmptyDataSet(realm);\n        for (RealmFieldType type : SUPPORTED_IS_EMPTY_TYPES) {\n            switch (type) {\n                case LINKING_OBJECTS:\n                    // Rows 0 and 1 are not included as they are linked to another row through FIELD_OBJECT\n                    // Row 2 is included (no link)\n                    assertEquals(0, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_OBJECT + \".\" + AllJavaTypesUnsupportedTypes.FIELD_LO_OBJECT).count());\n                    // Row 0 has link to row 0 which has a backlink (list); not included\n                    // Row 1 has link to row 1 which has a backlink (list); not included\n                    // Row 2 has no link; no included\n                    assertEquals(0, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_OBJECT + \".\" + AllJavaTypesUnsupportedTypes.FIELD_LO_LIST).count());\n                    break;\n                default:\n                    // tested in RealmQueryTests\n            }\n        }\n    }\n\n    @Test\n    public void isEmpty_acrossLinkingObjectObjectLink() {\n        createIsEmptyDataSet(realm);\n        for (RealmFieldType type : SUPPORTED_IS_EMPTY_TYPES) {\n            switch (type) {\n                case STRING:\n                    assertEquals(1, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_OBJECT + \".\" + AllJavaTypesUnsupportedTypes.FIELD_STRING).count());\n                    break;\n                case BINARY:\n                    assertEquals(1, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_OBJECT + \".\" + AllJavaTypesUnsupportedTypes.FIELD_BINARY).count());\n                    break;\n                case LIST:\n                    // Row 0: backlink to row 0, linklist is empty; included\n                    // Row 1: backlink to row 1, linklist to row 0; not included\n                    // Row 2: no backlink; not included\n                    assertEquals(1, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_OBJECT + \".\" + AllJavaTypesUnsupportedTypes.FIELD_LIST).count());\n                    break;\n                case LINKING_OBJECTS:\n                    // Both row 0 and 1 have a link/backlink; not included\n                    // row 2 has no link/backlink and an empty list; not included\n                    assertEquals(0, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_OBJECT + \".\" + AllJavaTypesUnsupportedTypes.FIELD_LO_OBJECT).count());\n                    assertEquals(0, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_OBJECT + \".\" + AllJavaTypesUnsupportedTypes.FIELD_LO_LIST).count());\n                    break;\n                case OBJECT:\n                    assertEquals(0, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_OBJECT + \".\" + AllJavaTypesUnsupportedTypes.FIELD_OBJECT).count());\n                    break;\n                case INTEGER_LIST:\n                    assertEquals(2, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_OBJECT + \".\" + AllJavaTypesUnsupportedTypes.FIELD_INTEGER_LIST).count());\n                    break;\n                case BOOLEAN_LIST:\n                    assertEquals(2, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_OBJECT + \".\" + AllJavaTypesUnsupportedTypes.FIELD_BOOLEAN_LIST).count());\n                    break;\n                case STRING_LIST:\n                    assertEquals(2, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_OBJECT + \".\" + AllJavaTypesUnsupportedTypes.FIELD_STRING_LIST).count());\n                    break;\n                case BINARY_LIST:\n                    assertEquals(2, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_OBJECT + \".\" + AllJavaTypesUnsupportedTypes.FIELD_BINARY_LIST).count());\n                    break;\n                case DATE_LIST:\n                    assertEquals(2, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_OBJECT + \".\" + AllJavaTypesUnsupportedTypes.FIELD_DATE_LIST).count());\n                    break;\n                case FLOAT_LIST:\n                    assertEquals(2, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_OBJECT + \".\" + AllJavaTypesUnsupportedTypes.FIELD_FLOAT_LIST).count());\n                    break;\n                case DOUBLE_LIST:\n                    assertEquals(2, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_OBJECT + \".\" + AllJavaTypesUnsupportedTypes.FIELD_DOUBLE_LIST).count());\n                    break;\n                case DECIMAL128_LIST:\n                    assertEquals(2, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_OBJECT + \".\" + AllJavaTypesUnsupportedTypes.FIELD_DECIMAL128_LIST).count());\n                    break;\n                case OBJECT_ID_LIST:\n                    assertEquals(2, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_OBJECT + \".\" + AllJavaTypesUnsupportedTypes.FIELD_OBJECT_ID_LIST).count());\n                    break;\n                case UUID_LIST:\n                    assertEquals(2, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_OBJECT + \".\" + AllJavaTypesUnsupportedTypes.FIELD_UUID_LIST).count());\n                    break;\n                case MIXED_LIST:\n                    assertEquals(2, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_OBJECT + \".\" + AllJavaTypesUnsupportedTypes.FIELD_REALM_ANY_LIST).count());\n                    break;\n                case STRING_TO_MIXED_MAP:\n                    assertEquals(2, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_OBJECT + \".\" + AllJavaTypesUnsupportedTypes.FIELD_REALM_ANY_DICTIONARY).count());\n                    break;\n                case STRING_TO_BOOLEAN_MAP:\n                    assertEquals(2, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_OBJECT + \".\" + AllJavaTypesUnsupportedTypes.FIELD_BOOLEAN_DICTIONARY).count());\n                    break;\n                case STRING_TO_STRING_MAP:\n                    assertEquals(2, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_OBJECT + \".\" + AllJavaTypesUnsupportedTypes.FIELD_STRING_DICTIONARY).count());\n                    break;\n                case STRING_TO_INTEGER_MAP:\n                    assertEquals(2, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_OBJECT + \".\" + AllJavaTypesUnsupportedTypes.FIELD_INTEGER_DICTIONARY).count());\n                    break;\n                case STRING_TO_FLOAT_MAP:\n                    assertEquals(2, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_OBJECT + \".\" + AllJavaTypesUnsupportedTypes.FIELD_FLOAT_DICTIONARY).count());\n                    break;\n                case STRING_TO_DOUBLE_MAP:\n                    assertEquals(2, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_OBJECT + \".\" + AllJavaTypesUnsupportedTypes.FIELD_DOUBLE_DICTIONARY).count());\n                    break;\n                case STRING_TO_BINARY_MAP:\n                    assertEquals(2, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_OBJECT + \".\" + AllJavaTypesUnsupportedTypes.FIELD_BINARY_DICTIONARY).count());\n                    break;\n                case STRING_TO_DATE_MAP:\n                    assertEquals(2, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_OBJECT + \".\" + AllJavaTypesUnsupportedTypes.FIELD_DATE_DICTIONARY).count());\n                    break;\n                case STRING_TO_OBJECT_ID_MAP:\n                    assertEquals(2, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_OBJECT + \".\" + AllJavaTypesUnsupportedTypes.FIELD_OBJECT_ID_DICTIONARY).count());\n                    break;\n                case STRING_TO_UUID_MAP:\n                    assertEquals(2, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_OBJECT + \".\" + AllJavaTypesUnsupportedTypes.FIELD_UUID_DICTIONARY).count());\n                    break;\n                case STRING_TO_DECIMAL128_MAP:\n                    assertEquals(2, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_OBJECT + \".\" + AllJavaTypesUnsupportedTypes.FIELD_DECIMAL128_DICTIONARY).count());\n                    break;\n                case STRING_TO_LINK_MAP:\n                    assertEquals(2, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_OBJECT + \".\" + AllJavaTypesUnsupportedTypes.FIELD_LINK_DICTIONARY).count());\n                    break;\n                case MIXED_SET:\n                    assertEquals(2, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_OBJECT + \".\" + AllJavaTypesUnsupportedTypes.FIELD_REALM_ANY_SET).count());\n                    break;\n                case BOOLEAN_SET:\n                    assertEquals(2, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_OBJECT + \".\" + AllJavaTypesUnsupportedTypes.FIELD_BOOLEAN_SET).count());\n                    break;\n                case STRING_SET:\n                    assertEquals(2, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_OBJECT + \".\" + AllJavaTypesUnsupportedTypes.FIELD_STRING_SET).count());\n                    break;\n                case INTEGER_SET:\n                    assertEquals(2, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_OBJECT + \".\" + AllJavaTypesUnsupportedTypes.FIELD_INTEGER_SET).count());\n                    break;\n                case FLOAT_SET:\n                    assertEquals(2, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_OBJECT + \".\" + AllJavaTypesUnsupportedTypes.FIELD_FLOAT_SET).count());\n                    break;\n                case DOUBLE_SET:\n                    assertEquals(2, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_OBJECT + \".\" + AllJavaTypesUnsupportedTypes.FIELD_DOUBLE_SET).count());\n                    break;\n                case BINARY_SET:\n                    assertEquals(2, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_OBJECT + \".\" + AllJavaTypesUnsupportedTypes.FIELD_BINARY_SET).count());\n                    break;\n                case DATE_SET:\n                    assertEquals(2, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_OBJECT + \".\" + AllJavaTypesUnsupportedTypes.FIELD_DATE_SET).count());\n                    break;\n                case OBJECT_ID_SET:\n                    assertEquals(2, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_OBJECT + \".\" + AllJavaTypesUnsupportedTypes.FIELD_OBJECT_ID_SET).count());\n                    break;\n                case UUID_SET:\n                    assertEquals(2, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_OBJECT + \".\" + AllJavaTypesUnsupportedTypes.FIELD_UUID_SET).count());\n                    break;\n                case DECIMAL128_SET:\n                    assertEquals(2, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_OBJECT + \".\" + AllJavaTypesUnsupportedTypes.FIELD_DECIMAL128_SET).count());\n                    break;\n                case LINK_SET:\n                    assertEquals(2, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_OBJECT + \".\" + AllJavaTypesUnsupportedTypes.FIELD_LINK_SET).count());\n                    break;\n                default:\n                    fail(\"Unknown type: \" + type);\n            }\n        }\n    }\n\n    @Test\n    public void isEmpty_acrossLinkingObjectListLink() {\n        createIsEmptyDataSet(realm);\n        assertEquals(3, realm.where(AllJavaTypesUnsupportedTypes.class).findAll().size());\n        for (RealmFieldType type : SUPPORTED_IS_EMPTY_TYPES) {\n            switch (type) {\n                case STRING:\n                    // Row 2 included (has no backlink)\n                    assertEquals(1, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_LIST + \".\" + AllJavaTypesUnsupportedTypes.FIELD_STRING).count());\n                    break;\n                case BINARY:\n                    // Row 2 included (has no backlink)\n                    assertEquals(1, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_LIST + \".\" + AllJavaTypesUnsupportedTypes.FIELD_BINARY).count());\n                    break;\n                case LIST:\n                    assertEquals(0, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_LIST + \".\" + AllJavaTypesUnsupportedTypes.FIELD_LIST).count());\n                    break;\n                case LINKING_OBJECTS:\n                    // Row 0: Backlink (list) to row 1, row 1 backlink to row 1; not included\n                    // Row 1: Backlink (list) to row 2, row 2 no backlink; included\n                    // Row 2: No backlink (list); not included\n                    assertEquals(1, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_LIST + \".\" + AllJavaTypesUnsupportedTypes.FIELD_LO_OBJECT).count());\n\n                    // Step 1:\n                    //  Row 0 skipped; FIELD_LO_LIST.count > 0\n                    //  Row 1 included; FIELD_LO_LIST.count() == 0\n                    //\n                    // Step 2: now checking Row 2\n                    // Row 0 not included: goes to Row 1 where FIELD_LO_LIST.count() == 0\n                    assertEquals(1, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_LIST + \".\" + AllJavaTypesUnsupportedTypes.FIELD_LO_LIST).count());\n                    break;\n                case OBJECT:\n                    assertEquals(1, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_LIST + \".\" + AllJavaTypesUnsupportedTypes.FIELD_OBJECT).count());\n                    break;\n                case INTEGER_LIST:\n                    assertEquals(2, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_LIST + \".\" + AllJavaTypesUnsupportedTypes.FIELD_INTEGER_LIST).count());\n                    break;\n                case BOOLEAN_LIST:\n                    assertEquals(2, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_LIST + \".\" + AllJavaTypesUnsupportedTypes.FIELD_BOOLEAN_LIST).count());\n                    break;\n                case STRING_LIST:\n                    assertEquals(2, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_LIST + \".\" + AllJavaTypesUnsupportedTypes.FIELD_STRING_LIST).count());\n                    break;\n                case BINARY_LIST:\n                    assertEquals(2, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_LIST + \".\" + AllJavaTypesUnsupportedTypes.FIELD_BINARY_LIST).count());\n                    break;\n                case DATE_LIST:\n                    assertEquals(2, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_LIST + \".\" + AllJavaTypesUnsupportedTypes.FIELD_DATE_LIST).count());\n                    break;\n                case FLOAT_LIST:\n                    assertEquals(2, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_LIST + \".\" + AllJavaTypesUnsupportedTypes.FIELD_FLOAT_LIST).count());\n                    break;\n                case DOUBLE_LIST:\n                    assertEquals(2, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_LIST + \".\" + AllJavaTypesUnsupportedTypes.FIELD_DOUBLE_LIST).count());\n                    break;\n                case DECIMAL128_LIST:\n                    assertEquals(2, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_LIST + \".\" + AllJavaTypesUnsupportedTypes.FIELD_DECIMAL128_LIST).count());\n                    break;\n                case OBJECT_ID_LIST:\n                    assertEquals(2, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_LIST + \".\" + AllJavaTypesUnsupportedTypes.FIELD_OBJECT_ID_LIST).count());\n                    break;\n                case UUID_LIST:\n                    assertEquals(2, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_LIST + \".\" + AllJavaTypesUnsupportedTypes.FIELD_UUID_LIST).count());\n                    break;\n                case MIXED_LIST:\n                    assertEquals(2, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_LIST + \".\" + AllJavaTypesUnsupportedTypes.FIELD_REALM_ANY_LIST).count());\n                    break;\n                case STRING_TO_MIXED_MAP:\n                    assertEquals(2, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_LIST + \".\" + AllJavaTypesUnsupportedTypes.FIELD_REALM_ANY_DICTIONARY).count());\n                    break;\n                case STRING_TO_BOOLEAN_MAP:\n                    assertEquals(2, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_LIST + \".\" + AllJavaTypesUnsupportedTypes.FIELD_BOOLEAN_DICTIONARY).count());\n                    break;\n                case STRING_TO_STRING_MAP:\n                    assertEquals(2, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_LIST + \".\" + AllJavaTypesUnsupportedTypes.FIELD_STRING_DICTIONARY).count());\n                    break;\n                case STRING_TO_INTEGER_MAP:\n                    assertEquals(2, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_LIST + \".\" + AllJavaTypesUnsupportedTypes.FIELD_INTEGER_DICTIONARY).count());\n                    break;\n                case STRING_TO_FLOAT_MAP:\n                    assertEquals(2, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_LIST + \".\" + AllJavaTypesUnsupportedTypes.FIELD_FLOAT_DICTIONARY).count());\n                    break;\n                case STRING_TO_DOUBLE_MAP:\n                    assertEquals(2, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_LIST + \".\" + AllJavaTypesUnsupportedTypes.FIELD_DOUBLE_DICTIONARY).count());\n                    break;\n                case STRING_TO_BINARY_MAP:\n                    assertEquals(2, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_LIST + \".\" + AllJavaTypesUnsupportedTypes.FIELD_BINARY_DICTIONARY).count());\n                    break;\n                case STRING_TO_DATE_MAP:\n                    assertEquals(2, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_LIST + \".\" + AllJavaTypesUnsupportedTypes.FIELD_DATE_DICTIONARY).count());\n                    break;\n                case STRING_TO_OBJECT_ID_MAP:\n                    assertEquals(2, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_LIST + \".\" + AllJavaTypesUnsupportedTypes.FIELD_OBJECT_ID_DICTIONARY).count());\n                    break;\n                case STRING_TO_UUID_MAP:\n                    assertEquals(2, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_LIST + \".\" + AllJavaTypesUnsupportedTypes.FIELD_UUID_DICTIONARY).count());\n                    break;\n                case STRING_TO_DECIMAL128_MAP:\n                    assertEquals(2, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_LIST + \".\" + AllJavaTypesUnsupportedTypes.FIELD_DECIMAL128_DICTIONARY).count());\n                    break;\n                case STRING_TO_LINK_MAP:\n                    assertEquals(2, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_LIST + \".\" + AllJavaTypesUnsupportedTypes.FIELD_LINK_DICTIONARY).count());\n                    break;\n                case INTEGER_SET:\n                    assertEquals(2, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_LIST + \".\" + AllJavaTypesUnsupportedTypes.FIELD_INTEGER_SET).count());\n                    break;\n                case BOOLEAN_SET:\n                    assertEquals(2, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_LIST + \".\" + AllJavaTypesUnsupportedTypes.FIELD_BOOLEAN_SET).count());\n                    break;\n                case STRING_SET:\n                    assertEquals(2, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_LIST + \".\" + AllJavaTypesUnsupportedTypes.FIELD_STRING_SET).count());\n                    break;\n                case BINARY_SET:\n                    assertEquals(2, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_LIST + \".\" + AllJavaTypesUnsupportedTypes.FIELD_BINARY_SET).count());\n                    break;\n                case DATE_SET:\n                    assertEquals(2, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_LIST + \".\" + AllJavaTypesUnsupportedTypes.FIELD_DATE_SET).count());\n                    break;\n                case FLOAT_SET:\n                    assertEquals(2, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_LIST + \".\" + AllJavaTypesUnsupportedTypes.FIELD_FLOAT_SET).count());\n                    break;\n                case DOUBLE_SET:\n                    assertEquals(2, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_LIST + \".\" + AllJavaTypesUnsupportedTypes.FIELD_DOUBLE_SET).count());\n                    break;\n                case DECIMAL128_SET:\n                    assertEquals(2, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_LIST + \".\" + AllJavaTypesUnsupportedTypes.FIELD_DECIMAL128_SET).count());\n                    break;\n                case OBJECT_ID_SET:\n                    assertEquals(2, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_LIST + \".\" + AllJavaTypesUnsupportedTypes.FIELD_OBJECT_ID_SET).count());\n                    break;\n                case UUID_SET:\n                    assertEquals(2, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_LIST + \".\" + AllJavaTypesUnsupportedTypes.FIELD_UUID_SET).count());\n                    break;\n                case MIXED_SET:\n                    assertEquals(2, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_LIST + \".\" + AllJavaTypesUnsupportedTypes.FIELD_REALM_ANY_SET).count());\n                    break;\n                case LINK_SET:\n                    assertEquals(2, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_LIST + \".\" + AllJavaTypesUnsupportedTypes.FIELD_REALM_ANY_SET).count());\n                    break;\n                default:\n                    fail(\"Unknown type: \" + type);\n            }\n        }\n    }\n\n    @Test\n    public void isNotEmpty() {\n        createIsNotEmptyDataSet(realm);\n        for (RealmFieldType type : SUPPORTED_IS_NOT_EMPTY_TYPES) {\n            switch (type) {\n                case LINKING_OBJECTS:\n                    // Row 0 and 1 have a link/backlink so no row is empty\n                    assertEquals(0, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_OBJECT).count());\n                    assertEquals(1, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_LIST).count());\n                    break;\n                default:\n                    // tested in RealmQueryTests\n            }\n        }\n    }\n\n    @Test\n    public void isNotEmpty_acrossLink() {\n        createIsNotEmptyDataSet(realm);\n        for (RealmFieldType type : SUPPORTED_IS_NOT_EMPTY_TYPES) {\n            switch (type) {\n                case LINKING_OBJECTS:\n                    // tested in LinkingObjectsQueryTests;\n                    // Row 0 and Row 1 have link/backlink - no empty\n                    assertEquals(0, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_OBJECT + \".\" + AllJavaTypesUnsupportedTypes.FIELD_LO_OBJECT).count());\n                    assertEquals(1, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_OBJECT + \".\" + AllJavaTypesUnsupportedTypes.FIELD_LO_LIST).count());\n                    break;\n                default:\n                    // tested in RealmQueryTests\n            }\n        }\n    }\n\n    @Test\n    public void isNotEmpty_acrossLinkingObjectObjectLink() {\n        createIsEmptyDataSet(realm);\n        for (RealmFieldType type : SUPPORTED_IS_EMPTY_TYPES) {\n            switch (type) {\n                case STRING:\n                    // Row 0: Follow link to row 0, and FIELD_STRING is empty (\"\")\n                    // Row 1: Follow link to row 1, and FIELD_STRING is not empty (\"Foo\")\n                    assertEquals(1, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_OBJECT + \".\" + AllJavaTypesUnsupportedTypes.FIELD_STRING).count());\n                    break;\n                case BINARY:\n                    assertEquals(1, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_OBJECT + \".\" + AllJavaTypesUnsupportedTypes.FIELD_BINARY).count());\n                    break;\n                case LIST:\n                    assertEquals(1, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_OBJECT + \".\" + AllJavaTypesUnsupportedTypes.FIELD_LIST).count());\n                    break;\n                case LINKING_OBJECTS:\n                    // Both row 0 and 1 have a link/backlink\n                    assertEquals(2, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_OBJECT + \".\" + AllJavaTypesUnsupportedTypes.FIELD_LO_OBJECT).count());\n\n                    // Row 0: Backlink to row 0, backlink list to row 1; included\n                    // Row 1: Backlink to row 1, backlink list to row 2; included\n                    // Row 2: No backlink; not empty\n                    assertEquals(2, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_OBJECT + \".\" + AllJavaTypesUnsupportedTypes.FIELD_LO_LIST).count());\n                    break;\n                case OBJECT:\n                    assertEquals(2, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_OBJECT + \".\" + AllJavaTypesUnsupportedTypes.FIELD_OBJECT).count());\n                    break;\n                case INTEGER_LIST:\n                    assertEquals(0, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_OBJECT + \".\" + AllJavaTypesUnsupportedTypes.FIELD_INTEGER_LIST).count());\n                    break;\n                case BOOLEAN_LIST:\n                    assertEquals(0, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_OBJECT + \".\" + AllJavaTypesUnsupportedTypes.FIELD_BOOLEAN_LIST).count());\n                    break;\n                case STRING_LIST:\n                    assertEquals(0, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_OBJECT + \".\" + AllJavaTypesUnsupportedTypes.FIELD_STRING_LIST).count());\n                    break;\n                case BINARY_LIST:\n                    assertEquals(0, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_OBJECT + \".\" + AllJavaTypesUnsupportedTypes.FIELD_BINARY_LIST).count());\n                    break;\n                case DATE_LIST:\n                    assertEquals(0, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_OBJECT + \".\" + AllJavaTypesUnsupportedTypes.FIELD_DATE_LIST).count());\n                    break;\n                case FLOAT_LIST:\n                    assertEquals(0, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_OBJECT + \".\" + AllJavaTypesUnsupportedTypes.FIELD_FLOAT_LIST).count());\n                    break;\n                case DOUBLE_LIST:\n                    assertEquals(0, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_OBJECT + \".\" + AllJavaTypesUnsupportedTypes.FIELD_DOUBLE_LIST).count());\n                    break;\n                case DECIMAL128_LIST:\n                    assertEquals(0, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_OBJECT + \".\" + AllJavaTypesUnsupportedTypes.FIELD_DECIMAL128_LIST).count());\n                    break;\n                case OBJECT_ID_LIST:\n                    assertEquals(0, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_OBJECT + \".\" + AllJavaTypesUnsupportedTypes.FIELD_OBJECT_ID_LIST).count());\n                    break;\n                case UUID_LIST:\n                    assertEquals(0, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_OBJECT + \".\" + AllJavaTypesUnsupportedTypes.FIELD_UUID_LIST).count());\n                    break;\n                case MIXED_LIST:\n                    assertEquals(0, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_OBJECT + \".\" + AllJavaTypesUnsupportedTypes.FIELD_REALM_ANY_LIST).count());\n                    break;\n                case STRING_TO_MIXED_MAP:\n                    assertEquals(0, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_OBJECT + \".\" + AllJavaTypesUnsupportedTypes.FIELD_REALM_ANY_DICTIONARY).count());\n                    break;\n                case STRING_TO_BOOLEAN_MAP:\n                    assertEquals(0, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_OBJECT + \".\" + AllJavaTypesUnsupportedTypes.FIELD_BOOLEAN_DICTIONARY).count());\n                    break;\n                case STRING_TO_STRING_MAP:\n                    assertEquals(0, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_OBJECT + \".\" + AllJavaTypesUnsupportedTypes.FIELD_STRING_DICTIONARY).count());\n                    break;\n                case STRING_TO_INTEGER_MAP:\n                    assertEquals(0, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_OBJECT + \".\" + AllJavaTypesUnsupportedTypes.FIELD_INTEGER_DICTIONARY).count());\n                    break;\n                case STRING_TO_FLOAT_MAP:\n                    assertEquals(0, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_OBJECT + \".\" + AllJavaTypesUnsupportedTypes.FIELD_FLOAT_DICTIONARY).count());\n                    break;\n                case STRING_TO_DOUBLE_MAP:\n                    assertEquals(0, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_OBJECT + \".\" + AllJavaTypesUnsupportedTypes.FIELD_DOUBLE_DICTIONARY).count());\n                    break;\n                case STRING_TO_BINARY_MAP:\n                    assertEquals(0, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_OBJECT + \".\" + AllJavaTypesUnsupportedTypes.FIELD_BINARY_DICTIONARY).count());\n                    break;\n                case STRING_TO_DATE_MAP:\n                    assertEquals(0, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_OBJECT + \".\" + AllJavaTypesUnsupportedTypes.FIELD_DATE_DICTIONARY).count());\n                    break;\n                case STRING_TO_OBJECT_ID_MAP:\n                    assertEquals(0, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_OBJECT + \".\" + AllJavaTypesUnsupportedTypes.FIELD_OBJECT_ID_DICTIONARY).count());\n                    break;\n                case STRING_TO_UUID_MAP:\n                    assertEquals(0, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_OBJECT + \".\" + AllJavaTypesUnsupportedTypes.FIELD_UUID_DICTIONARY).count());\n                    break;\n                case STRING_TO_DECIMAL128_MAP:\n                    assertEquals(0, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_OBJECT + \".\" + AllJavaTypesUnsupportedTypes.FIELD_DECIMAL128_DICTIONARY).count());\n                    break;\n                case STRING_TO_LINK_MAP:\n                    assertEquals(0, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_OBJECT + \".\" + AllJavaTypesUnsupportedTypes.FIELD_LINK_DICTIONARY).count());\n                    break;\n                case INTEGER_SET:\n                    assertEquals(0, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_OBJECT + \".\" + AllJavaTypesUnsupportedTypes.FIELD_INTEGER_SET).count());\n                    break;\n                case BOOLEAN_SET:\n                    assertEquals(0, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_OBJECT + \".\" + AllJavaTypesUnsupportedTypes.FIELD_BOOLEAN_SET).count());\n                    break;\n                case STRING_SET:\n                    assertEquals(0, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_OBJECT + \".\" + AllJavaTypesUnsupportedTypes.FIELD_STRING_SET).count());\n                    break;\n                case BINARY_SET:\n                    assertEquals(0, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_OBJECT + \".\" + AllJavaTypesUnsupportedTypes.FIELD_BINARY_SET).count());\n                    break;\n                case DATE_SET:\n                    assertEquals(0, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_OBJECT + \".\" + AllJavaTypesUnsupportedTypes.FIELD_DATE_SET).count());\n                    break;\n                case FLOAT_SET:\n                    assertEquals(0, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_OBJECT + \".\" + AllJavaTypesUnsupportedTypes.FIELD_FLOAT_SET).count());\n                    break;\n                case DOUBLE_SET:\n                    assertEquals(0, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_OBJECT + \".\" + AllJavaTypesUnsupportedTypes.FIELD_DOUBLE_SET).count());\n                    break;\n                case DECIMAL128_SET:\n                    assertEquals(0, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_OBJECT + \".\" + AllJavaTypesUnsupportedTypes.FIELD_DECIMAL128_SET).count());\n                    break;\n                case OBJECT_ID_SET:\n                    assertEquals(0, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_OBJECT + \".\" + AllJavaTypesUnsupportedTypes.FIELD_OBJECT_ID_SET).count());\n                    break;\n                case UUID_SET:\n                    assertEquals(0, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_OBJECT + \".\" + AllJavaTypesUnsupportedTypes.FIELD_UUID_SET).count());\n                    break;\n                case MIXED_SET:\n                    assertEquals(0, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_OBJECT + \".\" + AllJavaTypesUnsupportedTypes.FIELD_REALM_ANY_SET).count());\n                    break;\n                case LINK_SET:\n                    assertEquals(0, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_OBJECT + \".\" + AllJavaTypesUnsupportedTypes.FIELD_REALM_ANY_SET).count());\n                    break;\n                default:\n                    // Do nothing\n                     fail(\"Unknown type: \" + type);\n            }\n        }\n    }\n\n    @Test\n    public void isNotEmpty_acrossLinkingObjectListLink() {\n        createIsEmptyDataSet(realm);\n        assertEquals(3, realm.where(AllJavaTypesUnsupportedTypes.class).findAll().size());\n        for (RealmFieldType type : SUPPORTED_IS_EMPTY_TYPES) {\n            switch (type) {\n                case STRING:\n                    // Row 0: Backlink list to row 1, string not empty (\"Foo\"); included\n                    // Row 1: Backlink list to row 2, string is empty; not included\n                    // Row 2: No backlink list; not included\n                    assertEquals(1, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_LIST + \".\" + AllJavaTypesUnsupportedTypes.FIELD_STRING).count());\n                    break;\n                case BINARY:\n                    assertEquals(1, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_LIST + \".\" + AllJavaTypesUnsupportedTypes.FIELD_BINARY).count());\n                    break;\n                case LIST:\n                    // Row 0: Backlink list to row 1, list to row 0; included\n                    // Row 1: Backlink list to row 2, list to row 1; included\n                    // Row 2: No backlink list; not included\n                    assertEquals(2, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_LIST + \".\" + AllJavaTypesUnsupportedTypes.FIELD_LIST).count());\n                    break;\n                case LINKING_OBJECTS:\n                    assertEquals(1, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_LIST + \".\" + AllJavaTypesUnsupportedTypes.FIELD_LO_OBJECT).count());\n\n                    // Row 0: Backlink list to row 1, backlink list to row 2; included\n                    // Row 1: Backlink list to row 2, empty backlink list; not included\n                    // Row 2: Empty backlink list; not included\n                    assertEquals(1, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_LIST + \".\" + AllJavaTypesUnsupportedTypes.FIELD_LO_LIST).count());\n                    break;\n                case OBJECT:\n                    assertEquals(1, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_LIST + \".\" + AllJavaTypesUnsupportedTypes.FIELD_OBJECT).count());\n                    break;\n                case INTEGER_LIST:\n                    assertEquals(0, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_LIST + \".\" + AllJavaTypesUnsupportedTypes.FIELD_INTEGER_LIST).count());\n                    break;\n                case BOOLEAN_LIST:\n                    assertEquals(0, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_LIST + \".\" + AllJavaTypesUnsupportedTypes.FIELD_BOOLEAN_LIST).count());\n                    break;\n                case STRING_LIST:\n                    assertEquals(0, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_LIST + \".\" + AllJavaTypesUnsupportedTypes.FIELD_STRING_LIST).count());\n                    break;\n                case BINARY_LIST:\n                    assertEquals(0, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_LIST + \".\" + AllJavaTypesUnsupportedTypes.FIELD_BINARY_LIST).count());\n                    break;\n                case DATE_LIST:\n                    assertEquals(0, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_LIST + \".\" + AllJavaTypesUnsupportedTypes.FIELD_DATE_LIST).count());\n                    break;\n                case FLOAT_LIST:\n                    assertEquals(0, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_LIST + \".\" + AllJavaTypesUnsupportedTypes.FIELD_FLOAT_LIST).count());\n                    break;\n                case DOUBLE_LIST:\n                    assertEquals(0, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_LIST + \".\" + AllJavaTypesUnsupportedTypes.FIELD_DOUBLE_LIST).count());\n                    break;\n                case DECIMAL128_LIST:\n                    assertEquals(0, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_LIST + \".\" + AllJavaTypesUnsupportedTypes.FIELD_DECIMAL128_LIST).count());\n                    break;\n                case OBJECT_ID_LIST:\n                    assertEquals(0, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_LIST + \".\" + AllJavaTypesUnsupportedTypes.FIELD_OBJECT_ID_LIST).count());\n                    break;\n                case UUID_LIST:\n                    assertEquals(0, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_LIST + \".\" + AllJavaTypesUnsupportedTypes.FIELD_UUID_LIST).count());\n                    break;\n                case MIXED_LIST:\n                    assertEquals(0, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_LIST + \".\" + AllJavaTypesUnsupportedTypes.FIELD_REALM_ANY_LIST).count());\n                    break;\n                case STRING_TO_MIXED_MAP:\n                    assertEquals(0, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_LIST + \".\" + AllJavaTypesUnsupportedTypes.FIELD_REALM_ANY_DICTIONARY).count());\n                    break;\n                case STRING_TO_BOOLEAN_MAP:\n                    assertEquals(0, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_LIST + \".\" + AllJavaTypesUnsupportedTypes.FIELD_BOOLEAN_DICTIONARY).count());\n                    break;\n                case STRING_TO_STRING_MAP:\n                    assertEquals(0, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_LIST + \".\" + AllJavaTypesUnsupportedTypes.FIELD_STRING_DICTIONARY).count());\n                    break;\n                case STRING_TO_INTEGER_MAP:\n                    assertEquals(0, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_LIST + \".\" + AllJavaTypesUnsupportedTypes.FIELD_INTEGER_DICTIONARY).count());\n                    break;\n                case STRING_TO_FLOAT_MAP:\n                    assertEquals(0, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_LIST + \".\" + AllJavaTypesUnsupportedTypes.FIELD_FLOAT_DICTIONARY).count());\n                    break;\n                case STRING_TO_DOUBLE_MAP:\n                    assertEquals(0, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_LIST + \".\" + AllJavaTypesUnsupportedTypes.FIELD_DOUBLE_DICTIONARY).count());\n                    break;\n                case STRING_TO_BINARY_MAP:\n                    assertEquals(0, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_LIST + \".\" + AllJavaTypesUnsupportedTypes.FIELD_BINARY_DICTIONARY).count());\n                    break;\n                case STRING_TO_DATE_MAP:\n                    assertEquals(0, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_LIST + \".\" + AllJavaTypesUnsupportedTypes.FIELD_DATE_DICTIONARY).count());\n                    break;\n                case STRING_TO_OBJECT_ID_MAP:\n                    assertEquals(0, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_LIST + \".\" + AllJavaTypesUnsupportedTypes.FIELD_OBJECT_ID_DICTIONARY).count());\n                    break;\n                case STRING_TO_UUID_MAP:\n                    assertEquals(0, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_LIST + \".\" + AllJavaTypesUnsupportedTypes.FIELD_UUID_DICTIONARY).count());\n                    break;\n                case STRING_TO_DECIMAL128_MAP:\n                    assertEquals(0, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_LIST + \".\" + AllJavaTypesUnsupportedTypes.FIELD_DECIMAL128_DICTIONARY).count());\n                    break;\n                case STRING_TO_LINK_MAP:\n                    assertEquals(0, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_LIST + \".\" + AllJavaTypesUnsupportedTypes.FIELD_LINK_DICTIONARY).count());\n                    break;\n                case INTEGER_SET:\n                    assertEquals(0, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_LIST + \".\" + AllJavaTypesUnsupportedTypes.FIELD_INTEGER_SET).count());\n                    break;\n                case BOOLEAN_SET:\n                    assertEquals(0, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_LIST + \".\" + AllJavaTypesUnsupportedTypes.FIELD_BOOLEAN_SET).count());\n                    break;\n                case STRING_SET:\n                    assertEquals(0, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_LIST + \".\" + AllJavaTypesUnsupportedTypes.FIELD_STRING_SET).count());\n                    break;\n                case BINARY_SET:\n                    assertEquals(0, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_LIST + \".\" + AllJavaTypesUnsupportedTypes.FIELD_BINARY_LIST).count());\n                    break;\n                case DATE_SET:\n                    assertEquals(0, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_LIST + \".\" + AllJavaTypesUnsupportedTypes.FIELD_DATE_LIST).count());\n                    break;\n                case FLOAT_SET:\n                    assertEquals(0, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_LIST + \".\" + AllJavaTypesUnsupportedTypes.FIELD_FLOAT_LIST).count());\n                    break;\n                case DOUBLE_SET:\n                    assertEquals(0, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_LIST + \".\" + AllJavaTypesUnsupportedTypes.FIELD_DOUBLE_LIST).count());\n                    break;\n                case DECIMAL128_SET:\n                    assertEquals(0, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_LIST + \".\" + AllJavaTypesUnsupportedTypes.FIELD_DECIMAL128_LIST).count());\n                    break;\n                case OBJECT_ID_SET:\n                    assertEquals(0, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_LIST + \".\" + AllJavaTypesUnsupportedTypes.FIELD_OBJECT_ID_LIST).count());\n                    break;\n                case UUID_SET:\n                    assertEquals(0, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_LIST + \".\" + AllJavaTypesUnsupportedTypes.FIELD_UUID_LIST).count());\n                    break;\n                case MIXED_SET:\n                    assertEquals(0, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_LIST + \".\" + AllJavaTypesUnsupportedTypes.FIELD_REALM_ANY_LIST).count());\n                    break;\n                case LINK_SET:\n                    assertEquals(0, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_LIST + \".\" + AllJavaTypesUnsupportedTypes.FIELD_REALM_ANY_LIST).count());\n                    break;\n                default:\n                    fail(\"Unknown type: \" + type);\n            }\n        }\n    }\n\n    // Similar to the version in TestHelper, but with more Backlinks\n    // Creates 3 NullTypes objects. The objects are self-referenced (link) in\n    // order to test link queries.\n    //\n    // +-+--------+------+---------+--------+--------------------+----------+\n    // | | string | link | numeric | binary | numeric (not null) | linklist |\n    // +-+--------+------+---------+--------+--------------------+----------+\n    // |0| Fish   |    0 |       1 |    {0} |                  1 |      [0] |\n    // |1| null   |    2 |    null |   null |                  0 |      [2] |\n    // |2| Horse  | null |       3 |  {1,2} |                  3 |     null |\n    // +-+--------+------+---------+--------+--------------------+----------+\n    private void populateTestRealmForNullTests(Realm testRealm) {\n        // 1 String\n        String[] words = {\"Fish\", null, \"Horse\"};\n        // 2 Bytes\n        byte[][] binaries = {new byte[]{0}, null, new byte[]{1, 2}};\n        // 3 Boolean\n        Boolean[] booleans = {false, null, true};\n        // Numeric fields will be 1, 0/null, 3\n        // 10 Date\n        Date[] dates = {new Date(0), null, new Date(10000)};\n        NullTypes[] nullTypesArray = new NullTypes[3];\n\n        Decimal128[] decimals = {new Decimal128(BigDecimal.TEN), null, new Decimal128(BigDecimal.ONE)};\n\n        ObjectId[] ids = {new ObjectId(TestHelper.generateObjectIdHexString(10)), null, new ObjectId(TestHelper.generateObjectIdHexString(1))};\n\n        testRealm.beginTransaction();\n        for (int i = 0; i < 3; i++) {\n            NullTypes nullTypes = new NullTypes();\n            nullTypes.setId(i + 1);\n            // 1 String\n            nullTypes.setFieldStringNull(words[i]);\n            if (words[i] != null) {\n                nullTypes.setFieldStringNotNull(words[i]);\n            }\n            // 2 Bytes\n            nullTypes.setFieldBytesNull(binaries[i]);\n            if (binaries[i] != null) {\n                nullTypes.setFieldBytesNotNull(binaries[i]);\n            }\n            // 3 Boolean\n            nullTypes.setFieldBooleanNull(booleans[i]);\n            if (booleans[i] != null) {\n                nullTypes.setFieldBooleanNotNull(booleans[i]);\n            }\n            if (i != 1) {\n                int n = i + 1;\n                // 4 Byte\n                nullTypes.setFieldByteNull((byte) n);\n                nullTypes.setFieldByteNotNull((byte) n);\n                // 5 Short\n                nullTypes.setFieldShortNull((short) n);\n                nullTypes.setFieldShortNotNull((short) n);\n                // 6 Integer\n                nullTypes.setFieldIntegerNull(n);\n                nullTypes.setFieldIntegerNotNull(n);\n                // 7 Long\n                nullTypes.setFieldLongNull((long) n);\n                nullTypes.setFieldLongNotNull((long) n);\n                // 8 Float\n                nullTypes.setFieldFloatNull((float) n);\n                nullTypes.setFieldFloatNotNull((float) n);\n                // 9 Double\n                nullTypes.setFieldDoubleNull((double) n);\n                nullTypes.setFieldDoubleNotNull((double) n);\n            }\n            // 10 Date\n            nullTypes.setFieldDateNull(dates[i]);\n            if (dates[i] != null) {\n                nullTypes.setFieldDateNotNull(dates[i]);\n            }\n\n            nullTypes.setFieldDecimal128Null(decimals[i]);\n\n            nullTypes.setFieldObjectIdNull(ids[i]);\n\n            nullTypesArray[i] = testRealm.copyToRealm(nullTypes);\n        }\n        nullTypesArray[0].setFieldObjectNull(nullTypesArray[0]);\n        nullTypesArray[1].setFieldObjectNull(nullTypesArray[2]);\n        nullTypesArray[2].setFieldObjectNull(null);\n\n        nullTypesArray[0].getFieldListNull().add(nullTypesArray[1]);\n        nullTypesArray[1].getFieldListNull().add(nullTypesArray[2]);\n        nullTypesArray[2].getFieldListNull().clear(); // just to be sure\n        testRealm.commitTransaction();\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/LinkingObjectsUnmanagedTests.java",
    "content": "/*\n * Copyright 2017 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\npackage io.realm;\n\nimport androidx.test.ext.junit.runners.AndroidJUnit4;\n\nimport org.junit.After;\nimport org.junit.Before;\nimport org.junit.Rule;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\n\nimport io.realm.entities.AllJavaTypes;\n\nimport static org.junit.Assert.assertEquals;\nimport static org.junit.Assert.assertNotNull;\nimport static org.junit.Assert.assertNull;\n\n@RunWith(AndroidJUnit4.class)\npublic class LinkingObjectsUnmanagedTests {\n\n    @Rule\n    public final TestRealmConfigurationFactory configFactory = new TestRealmConfigurationFactory();\n\n    private Realm realm;\n\n    @Before\n    public void setUp() {\n        RealmConfiguration realmConfig = configFactory.createConfiguration();\n        realm = Realm.getInstance(realmConfig);\n    }\n\n    @After\n    public void tearDown() {\n        if (realm != null) {\n            realm.close();\n        }\n    }\n\n    // When unmanaged, an object's backlinks fields have their initialized value (probably null).\n    @Test\n    public void copyFromRealm() {\n        realm.beginTransaction();\n        AllJavaTypes child = realm.createObject(AllJavaTypes.class, 1);\n        AllJavaTypes parent = realm.createObject(AllJavaTypes.class, 2);\n        parent.setFieldObject(child);\n        realm.commitTransaction();\n        assertEquals(1, child.getObjectParents().size());\n        assertEquals(parent, child.getObjectParents().first());\n\n        AllJavaTypes unmanagedChild = realm.copyFromRealm(child);\n        assertNull(unmanagedChild.getObjectParents());\n    }\n\n    // Test round-trip\n    @Test\n    public void copyToAndFromRealm() {\n        AllJavaTypes unmanagedChild = new AllJavaTypes(1);\n        assertNull(unmanagedChild.getObjectParents());\n\n        realm.beginTransaction();\n        AllJavaTypes parent = realm.createObject(AllJavaTypes.class, 2);\n        AllJavaTypes child = realm.copyToRealm(unmanagedChild);\n        parent.setFieldObject(child);\n        realm.commitTransaction();\n\n        // When managed, an object's backlinks fields get live.\n        RealmResults<AllJavaTypes> parents = child.getObjectParents();\n        assertNotNull(parents);\n        assertEquals(1, parents.size());\n        assertEquals(parent, parents.first());\n\n        unmanagedChild = realm.copyFromRealm(child);\n        assertEquals(unmanagedChild.getFieldId(), 1);\n        assertEquals(new AllJavaTypes().getObjectParents(), unmanagedChild.getObjectParents());\n\n        RealmResults<AllJavaTypes> queryResults = realm.where(AllJavaTypes.class).equalTo(\"fieldId\", 1).findAll();\n        assertEquals(1, queryResults.size());\n\n        child = queryResults.first();\n        parents = child.getObjectParents();\n        assertNotNull(parents);\n        assertEquals(1, parents.size());\n        assertEquals(parent, parents.first());\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/ManagedOrderedRealmCollectionTests.java",
    "content": "/*\n * Copyright 2016 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\npackage io.realm;\n\nimport org.junit.After;\nimport org.junit.Before;\nimport org.junit.Rule;\nimport org.junit.Test;\nimport org.junit.rules.ExpectedException;\nimport org.junit.runner.RunWith;\nimport org.junit.runners.Parameterized;\n\nimport java.util.Arrays;\nimport java.util.Collections;\nimport java.util.List;\nimport java.util.concurrent.Callable;\nimport java.util.concurrent.ExecutionException;\nimport java.util.concurrent.ExecutorService;\nimport java.util.concurrent.Executors;\nimport java.util.concurrent.Future;\n\nimport io.realm.entities.AllJavaTypes;\nimport io.realm.entities.Dog;\nimport io.realm.entities.NullTypes;\nimport io.realm.entities.Owner;\n\nimport static org.junit.Assert.assertEquals;\nimport static org.junit.Assert.assertFalse;\nimport static org.junit.Assert.assertTrue;\nimport static org.junit.Assert.fail;\n\n/**\n * Test class for all methods specific to OrderedRealmCollections that are not implementation specific.\n *\n * Methods tested in this class:\n *\n * # OrderedRealmCollection\n *\n * - E first()\n * - E last()\n * + void sort(String field)\n * + void sort(String field, Sort sortOrder)\n * + void sort(String field1, Sort sortOrder1, String field2, Sort sortOrder2)\n * + void sort(String[] fields, Sort[] sortOrders)\n * + void deleteFromRealm(int location)\n * + void deleteFirstFromRealm()\n * + void deleteLastFromRealm();\n *\n * # List\n *\n *  - void add(int location, E object);\n *  - boolean addAll(int location, Collection<? extends E> collection);\n *  - E get(int location);\n *  - int indexOf(Object object);\n *  - int lastIndexOf(Object object);\n *  - ListIterator<E> listIterator();\n *  - ListIterator<E> listIterator(int location);\n *  - E remove(int location);\n *  - E set(int location, E object);\n *  - List<E> subList(int start, int end);\n *\n * # RealmCollection\n *\n * - RealmQuery<E> where();\n * - Number min(String fieldName);\n * - Number max(String fieldName);\n * - Number sum(String fieldName);\n * - double average(String fieldName);\n * - Date maxDate(String fieldName);\n * - Date minDate(String fieldName);\n * - void deleteAllFromRealm();\n * - boolean isLoaded();\n * - boolean load();\n * - boolean isValid();\n * - BaseRealm getRealm();\n *\n * # Collection\n *\n * - public boolean add(E object);\n * - public boolean addAll(Collection<? extends E> collection);\n * - public void deleteAll();\n * - public boolean contains(Object object);\n * - public boolean containsAll(Collection<?> collection);\n * - public boolean equals(Object object);\n * - public int hashCode();\n * - public boolean isEmpty();\n * - public Iterator<E> iterator();\n * - public boolean remove(Object object);\n * - public boolean removeAll(Collection<?> collection);\n * - public boolean retainAll(Collection<?> collection);\n * - public int size();\n * - public Object[] toArray();\n * - public <T> T[] toArray(T[] array);\n *\n * @see RealmCollectionTests\n * @see ManagedRealmCollectionTests\n * @see UnManagedRealmCollectionTests\n */\n\n@RunWith(Parameterized.class)\npublic class ManagedOrderedRealmCollectionTests extends CollectionTests {\n\n    private static final int TEST_SIZE = 10;\n    private final static int TEST_DATA_FIRST_HALF = (int) ((TEST_SIZE / 2.0D) - 1);\n    private final static int TEST_DATA_LAST_HALF = (int) ((TEST_SIZE / 2.0D) + 1);\n\n    @Rule\n    public final TestRealmConfigurationFactory configFactory = new TestRealmConfigurationFactory();\n    @Rule\n    public final ExpectedException thrown = ExpectedException.none();\n\n    private final ManagedCollection collectionClass;\n    private Realm realm;\n    private OrderedRealmCollection<AllJavaTypes> collection;\n\n    @Parameterized.Parameters(name = \"{0}\")\n    public static List<ManagedCollection> data() {\n        return Arrays.asList(ManagedCollection.values());\n    }\n\n    public ManagedOrderedRealmCollectionTests(ManagedCollection collectionType) {\n        this.collectionClass = collectionType;\n    }\n\n    @Before\n    public void setup() {\n        realm = Realm.getInstance(configFactory.createConfiguration());\n        populateRealm(realm, TEST_SIZE);\n        collection = createCollection(collectionClass);\n    }\n\n    @After\n    public void tearDown() {\n        realm.close();\n    }\n\n    OrderedRealmCollection<AllJavaTypes> createCollection(ManagedCollection collectionClass) {\n        OrderedRealmCollection<AllJavaTypes> orderedCollection;\n        switch (collectionClass) {\n            case REALMRESULTS_SNAPSHOT_LIST_BASE:\n            case MANAGED_REALMLIST:\n                orderedCollection = realm.where(AllJavaTypes.class)\n                        .equalTo(AllJavaTypes.FIELD_LONG, 0)\n                        .findFirst()\n                        .getFieldList();\n                break;\n\n            case REALMRESULTS_SNAPSHOT_RESULTS_BASE:\n            case REALMRESULTS:\n                orderedCollection = realm.where(AllJavaTypes.class).findAll();\n                break;\n\n            default:\n                throw new AssertionError(\"Unsupported class: \" + collectionClass);\n        }\n        if (isSnapshot(collectionClass)) {\n            orderedCollection = orderedCollection.createSnapshot();\n        }\n        return orderedCollection;\n    }\n\n    private OrderedRealmCollection<NullTypes> createEmptyCollection(Realm realm, ManagedCollection collectionClass) {\n        OrderedRealmCollection<NullTypes> orderedCollection;\n        switch (collectionClass) {\n            case REALMRESULTS_SNAPSHOT_LIST_BASE:\n            case MANAGED_REALMLIST:\n                realm.beginTransaction();\n                NullTypes obj = realm.createObject(NullTypes.class, 0);\n                realm.commitTransaction();\n                orderedCollection = obj.getFieldListNull();\n                break;\n\n            case REALMRESULTS_SNAPSHOT_RESULTS_BASE:\n            case REALMRESULTS:\n                orderedCollection = realm.where(NullTypes.class).findAll();\n                break;\n            default:\n                throw new AssertionError(\"Unknown collection: \" + collectionClass);\n        }\n\n        if (isSnapshot(collectionClass)) {\n            orderedCollection = orderedCollection.createSnapshot();\n        }\n        return orderedCollection;\n    }\n\n    @Test\n    public void sort_twoFields() {\n        if (isSnapshot(collectionClass)) {\n            thrown.expect(UnsupportedOperationException.class);\n        }\n        OrderedRealmCollection<AllJavaTypes> sortedList = collection.sort(AllJavaTypes.FIELD_BOOLEAN, Sort.ASCENDING, AllJavaTypes.FIELD_LONG, Sort.DESCENDING);\n        AllJavaTypes obj = sortedList.first();\n        assertFalse(obj.isFieldBoolean());\n        assertEquals(TEST_SIZE - 1, obj.getFieldLong());\n    }\n\n    @Test\n    public void sort_boolean() {\n        if (isSnapshot(collectionClass)) {\n            thrown.expect(UnsupportedOperationException.class);\n        }\n        OrderedRealmCollection<AllJavaTypes> sortedList = collection.sort(AllJavaTypes.FIELD_BOOLEAN, Sort.DESCENDING);\n        assertEquals(TEST_SIZE, sortedList.size());\n        assertEquals(false, sortedList.last().isFieldBoolean());\n        assertEquals(true, sortedList.first().isFieldBoolean());\n        assertEquals(true, sortedList.get(TEST_DATA_FIRST_HALF).isFieldBoolean());\n        assertEquals(false, sortedList.get(TEST_DATA_LAST_HALF).isFieldBoolean());\n\n        RealmResults<AllJavaTypes> reverseList = sortedList.sort(AllJavaTypes.FIELD_BOOLEAN, Sort.ASCENDING);\n        assertEquals(TEST_SIZE, reverseList.size());\n        assertEquals(true, reverseList.last().isFieldBoolean());\n        assertEquals(false, reverseList.first().isFieldBoolean());\n        assertEquals(false, reverseList.get(TEST_DATA_FIRST_HALF).isFieldBoolean());\n        assertEquals(true, reverseList.get(TEST_DATA_LAST_HALF).isFieldBoolean());\n\n        RealmResults<AllJavaTypes> reserveSortedList = reverseList.sort(AllJavaTypes.FIELD_BOOLEAN, Sort.DESCENDING);\n        assertEquals(TEST_SIZE, reserveSortedList.size());\n        assertEquals(reserveSortedList.first(), sortedList.first());\n    }\n\n    @Test\n    public void sort_string() {\n        if (isSnapshot(collectionClass)) {\n            thrown.expect(UnsupportedOperationException.class);\n        }\n        OrderedRealmCollection<AllJavaTypes> resultList = collection;\n        OrderedRealmCollection<AllJavaTypes> sortedList = createCollection(collectionClass);\n        sortedList = sortedList.sort(AllJavaTypes.FIELD_STRING, Sort.DESCENDING);\n\n        assertEquals(resultList.size(), sortedList.size());\n        assertEquals(TEST_SIZE, sortedList.size());\n        assertEquals(resultList.first().getFieldString(), sortedList.last().getFieldString());\n\n        RealmResults<AllJavaTypes> reverseList = sortedList.sort(AllJavaTypes.FIELD_STRING, Sort.ASCENDING);\n        assertEquals(TEST_SIZE, reverseList.size());\n        assertEquals(resultList.first().getFieldString(), reverseList.first().getFieldString());\n\n        int numberOfDigits = 1 + ((int) Math.log10(TEST_SIZE));\n        int largestNumber = 1;\n        largestNumber = (int) (largestNumber * Math.pow(10, numberOfDigits - 1));\n        largestNumber = largestNumber - 1;\n        assertEquals(resultList.get(largestNumber).getFieldString(), reverseList.last().getFieldString());\n        RealmResults<AllJavaTypes> reverseSortedList = reverseList.sort(AllJavaTypes.FIELD_STRING, Sort.DESCENDING);\n        assertEquals(TEST_SIZE, reverseSortedList.size());\n    }\n\n    @Test\n    public void sort_double() {\n        if (isSnapshot(collectionClass)) {\n            thrown.expect(UnsupportedOperationException.class);\n        }\n        OrderedRealmCollection<AllJavaTypes> resultList = collection;\n        OrderedRealmCollection<AllJavaTypes> sortedList = createCollection(collectionClass);\n        sortedList = sortedList.sort(AllJavaTypes.FIELD_DOUBLE, Sort.DESCENDING);\n        assertEquals(resultList.size(), sortedList.size());\n        assertEquals(TEST_SIZE, sortedList.size());\n        assertEquals(resultList.first().getFieldDouble(), sortedList.last().getFieldDouble(), 0D);\n\n        RealmResults<AllJavaTypes> reverseList = sortedList.sort(AllJavaTypes.FIELD_DOUBLE, Sort.ASCENDING);\n        assertEquals(TEST_SIZE, reverseList.size());\n        assertEquals(resultList.first().getFieldDouble(), reverseList.first().getFieldDouble(), 0D);\n        assertEquals(resultList.last().getFieldDouble(), reverseList.last().getFieldDouble(), 0D);\n\n        RealmResults<AllJavaTypes> reverseSortedList = reverseList.sort(AllJavaTypes.FIELD_DOUBLE, Sort.DESCENDING);\n        assertEquals(TEST_SIZE, reverseSortedList.size());\n    }\n\n    @Test\n    public void sort_float() {\n        if (isSnapshot(collectionClass)) {\n            thrown.expect(UnsupportedOperationException.class);\n        }\n        OrderedRealmCollection<AllJavaTypes> resultList = collection;\n        OrderedRealmCollection<AllJavaTypes> sortedList = createCollection(collectionClass);\n        sortedList = sortedList.sort(AllJavaTypes.FIELD_FLOAT, Sort.DESCENDING);\n        assertEquals(resultList.size(), sortedList.size());\n        assertEquals(TEST_SIZE, sortedList.size());\n        assertEquals(resultList.first().getFieldFloat(), sortedList.last().getFieldFloat(), 0D);\n\n        RealmResults<AllJavaTypes> reverseList = sortedList.sort(AllJavaTypes.FIELD_FLOAT, Sort.ASCENDING);\n        assertEquals(TEST_SIZE, reverseList.size());\n        assertEquals(resultList.first().getFieldFloat(), reverseList.first().getFieldFloat(), 0D);\n        assertEquals(resultList.last().getFieldFloat(), reverseList.last().getFieldFloat(), 0D);\n\n        RealmResults<AllJavaTypes> reverseSortedList = reverseList.sort(AllJavaTypes.FIELD_FLOAT, Sort.DESCENDING);\n        assertEquals(TEST_SIZE, reverseSortedList.size());\n    }\n\n    private void doTestSortOnColumnWithPartialNullValues(String fieldName,\n                                                         OrderedRealmCollection<NullTypes> original,\n                                                         OrderedRealmCollection<NullTypes> copy) {\n\n        RealmResults<NullTypes> sortedList = copy.sort(fieldName, Sort.ASCENDING);\n        assertEquals(\"Should have same size\", original.size(), sortedList.size());\n        // Null should always be the first one in the ascending sorted list.\n        assertEquals(2, sortedList.first().getId());\n        assertEquals(1, sortedList.last().getId());\n\n        // Descending\n        sortedList = sortedList.sort(fieldName, Sort.DESCENDING);\n        assertEquals(\"Should have same size\", original.size(), sortedList.size());\n        assertEquals(1, sortedList.first().getId());\n        // Null should always be the last one in the descending sorted list.\n        assertEquals(2, sortedList.last().getId());\n    }\n\n    @Test\n    public void sort_rowsWithPartialNullValues() {\n        if (isSnapshot(collectionClass)) {\n            thrown.expect(UnsupportedOperationException.class);\n        }\n        populatePartialNullRowsForNumericTesting(realm);\n        OrderedRealmCollection<NullTypes> original;\n        OrderedRealmCollection<NullTypes> copy;\n        switch (collectionClass) {\n            case REALMRESULTS_SNAPSHOT_LIST_BASE:\n            case MANAGED_REALMLIST:\n                realm.beginTransaction();\n                RealmResults<NullTypes> objects = realm.where(NullTypes.class).findAll();\n                NullTypes parent = realm.createObject(NullTypes.class, 0);\n                for (int i = 0; i < objects.size(); i++) {\n                    NullTypes object = objects.get(i);\n                    if (object.getId() != 0) {\n                        parent.getFieldListNull().add(object);\n                    }\n                }\n                realm.commitTransaction();\n                original = parent.getFieldListNull().where().findAll();\n                copy = parent.getFieldListNull();\n                break;\n\n            case REALMRESULTS_SNAPSHOT_RESULTS_BASE:\n            case REALMRESULTS:\n                original = realm.where(NullTypes.class).findAll();\n                copy = realm.where(NullTypes.class).findAll();\n                break;\n\n            default:\n                throw new AssertionError(\"Unknown collection class: \" + collectionClass);\n        }\n\n        if (isSnapshot(collectionClass)) {\n            copy = copy.createSnapshot();\n        }\n\n        // 1 String\n        doTestSortOnColumnWithPartialNullValues(NullTypes.FIELD_STRING_NULL, original, copy);\n\n        // 3 Boolean\n        doTestSortOnColumnWithPartialNullValues(NullTypes.FIELD_BOOLEAN_NULL, original, copy);\n\n        // 6 Integer\n        doTestSortOnColumnWithPartialNullValues(NullTypes.FIELD_INTEGER_NULL, original, copy);\n\n        // 7 Float\n        doTestSortOnColumnWithPartialNullValues(NullTypes.FIELD_FLOAT_NULL, original, copy);\n\n        // 8 Double\n        doTestSortOnColumnWithPartialNullValues(NullTypes.FIELD_DOUBLE_NULL, original, copy);\n\n        // 10 Date\n        doTestSortOnColumnWithPartialNullValues(NullTypes.FIELD_DATE_NULL, original, copy);\n    }\n\n    @Test\n    public void sort_nonExistingColumn() {\n        if (isSnapshot(collectionClass)) {\n            thrown.expect(UnsupportedOperationException.class);\n        } else {\n            thrown.expect(IllegalArgumentException.class);\n        }\n        collection.sort(\"Non-existing\");\n    }\n\n    @Test\n    public void sort_danishCharacters() {\n        if (isSnapshot(collectionClass)) {\n            thrown.expect(UnsupportedOperationException.class);\n        }\n        OrderedRealmCollection<AllJavaTypes> collection = createStringCollection(realm, collectionClass,\n                \"Æble\",\n                \"Øl\",\n                \"Århus\"\n        );\n\n        collection = collection.sort(AllJavaTypes.FIELD_STRING);\n\n        assertEquals(3, collection.size());\n        assertEquals(\"Æble\", collection.get(0).getFieldString());\n        assertEquals(\"Øl\", collection.get(1).getFieldString());\n        assertEquals(\"Århus\", collection.get(2).getFieldString());\n\n        collection = collection.sort(AllJavaTypes.FIELD_STRING, Sort.DESCENDING);\n        assertEquals(3, collection.size());\n        assertEquals(\"Århus\", collection.get(0).getFieldString());\n        assertEquals(\"Øl\", collection.get(1).getFieldString());\n        assertEquals(\"Æble\", collection.get(2).getFieldString());\n    }\n\n    @Test\n    public void sort_russianCharacters() {\n        if (isSnapshot(collectionClass)) {\n            thrown.expect(UnsupportedOperationException.class);\n        }\n        OrderedRealmCollection<AllJavaTypes> collection = createStringCollection(realm, collectionClass,\n                \"Санкт-Петербург\",\n                \"Москва\",\n                \"Новороссийск\"\n        );\n\n        collection = collection.sort(AllJavaTypes.FIELD_STRING);\n\n        assertEquals(3, collection.size());\n        assertEquals(\"Москва\", collection.get(0).getFieldString());\n        assertEquals(\"Новороссийск\", collection.get(1).getFieldString());\n        assertEquals(\"Санкт-Петербург\", collection.get(2).getFieldString());\n\n        collection = collection.sort(AllJavaTypes.FIELD_STRING, Sort.DESCENDING);\n        assertEquals(3, collection.size());\n        assertEquals(\"Санкт-Петербург\", collection.get(0).getFieldString());\n        assertEquals(\"Новороссийск\", collection.get(1).getFieldString());\n        assertEquals(\"Москва\", collection.get(2).getFieldString());\n    }\n\n    @Test\n    public void sort_greekCharacters() {\n        if (isSnapshot(collectionClass)) {\n            thrown.expect(UnsupportedOperationException.class);\n        }\n        OrderedRealmCollection<AllJavaTypes> collection = createStringCollection(realm, collectionClass,\n                \"αύριο\",\n                \"ημέρες\",\n                \"δοκιμές\"\n        );\n\n        collection = collection.sort(AllJavaTypes.FIELD_STRING);\n\n        assertEquals(3, collection.size());\n        assertEquals(\"αύριο\", collection.get(0).getFieldString());\n        assertEquals(\"δοκιμές\", collection.get(1).getFieldString());\n        assertEquals(\"ημέρες\", collection.get(2).getFieldString());\n\n        collection = collection.sort(AllJavaTypes.FIELD_STRING, Sort.DESCENDING);\n        assertEquals(3, collection.size());\n        assertEquals(\"ημέρες\", collection.get(0).getFieldString());\n        assertEquals(\"δοκιμές\", collection.get(1).getFieldString());\n        assertEquals(\"αύριο\", collection.get(2).getFieldString());\n    }\n\n    // No sorting order defined. There are Korean, Arabic and Chinese characters.\n    @Test\n    public void sort_manyDifferentCharacters() {\n        if (isSnapshot(collectionClass)) {\n            thrown.expect(UnsupportedOperationException.class);\n        }\n        OrderedRealmCollection<AllJavaTypes> collection = createStringCollection(realm, collectionClass,\n                \"단위\",\n                \"테스트\",\n                \"وحدة\",\n                \"اختبار\",\n                \"单位\",\n                \"试验\",\n                \"單位\",\n                \"測試\"\n        );\n\n        collection.sort(AllJavaTypes.FIELD_STRING);\n        assertEquals(8, collection.size());\n\n        collection.sort(AllJavaTypes.FIELD_STRING, Sort.DESCENDING);\n        assertEquals(8, collection.size());\n    }\n\n    @Test\n    public void sort_twoLanguages() {\n        if (isSnapshot(collectionClass)) {\n            thrown.expect(UnsupportedOperationException.class);\n        }\n        OrderedRealmCollection<AllJavaTypes> collection = createStringCollection(realm, collectionClass,\n                \"test\",\n                \"αύριο\",\n                \"work\"\n        );\n\n        try {\n            collection.sort(AllJavaTypes.FIELD_STRING);\n        } catch (IllegalArgumentException e) {\n            fail(\"Failed to sort with two kinds of alphabets\");\n        }\n    }\n\n    @Test\n    public void sort_usingChildObject() {\n        if (isSnapshot(collectionClass)) {\n            thrown.expect(UnsupportedOperationException.class);\n        }\n        OrderedRealmCollection<AllJavaTypes> resultList = collection;\n        OrderedRealmCollection<AllJavaTypes> sortedList = createCollection(collectionClass);\n        sortedList = sortedList.sort(AllJavaTypes.FIELD_OBJECT + \".\" + AllJavaTypes.FIELD_LONG, Sort.DESCENDING);\n        assertEquals(\"Should have same size\", resultList.size(), sortedList.size());\n        assertEquals(TEST_SIZE, sortedList.size());\n        assertEquals(\"First excepted to be last\", resultList.first().getFieldLong(), sortedList.last().getFieldLong());\n\n        sortedList = sortedList.sort(AllJavaTypes.FIELD_OBJECT + \".\" + AllJavaTypes.FIELD_LONG, Sort.ASCENDING);\n        assertEquals(TEST_SIZE, sortedList.size());\n        assertEquals(\"First excepted to be first\", resultList.first().getFieldLong(), sortedList.first().getFieldLong());\n        assertEquals(\"Last excepted to be last\", resultList.last().getFieldLong(), sortedList.last().getFieldLong());\n\n        sortedList = sortedList.sort(AllJavaTypes.FIELD_OBJECT + \".\" + AllJavaTypes.FIELD_LONG, Sort.DESCENDING);\n        assertEquals(TEST_SIZE, sortedList.size());\n    }\n\n    @Test\n    public void sort_nullArguments() {\n        if (isSnapshot(collectionClass)) {\n            thrown.expect(UnsupportedOperationException.class);\n        }\n        OrderedRealmCollection<AllJavaTypes> result = collection;\n        try {\n            result.sort((String) null);\n            fail(\"Sorting with a null field name should throw an IllegalArgumentException\");\n        } catch (IllegalArgumentException ignored) {\n        }\n        try {\n            result.sort((String) null, null);\n            fail();\n        } catch (IllegalArgumentException ignored) {\n        }\n    }\n\n    @Test\n    public void sort_emptyResults() {\n        if (isSnapshot(collectionClass)) {\n            thrown.expect(UnsupportedOperationException.class);\n        }\n        OrderedRealmCollection<NullTypes> collection = createEmptyCollection(realm, collectionClass);\n        assertEquals(0, collection.size());\n        collection.sort(NullTypes.FIELD_STRING_NULL);\n        assertEquals(0, collection.size());\n    }\n\n    @Test\n    public void sort_singleField() {\n        if (isSnapshot(collectionClass)) {\n            thrown.expect(UnsupportedOperationException.class);\n        }\n        RealmResults<AllJavaTypes> sortedList = collection.sort(new String[]{AllJavaTypes.FIELD_LONG}, new Sort[]{Sort.DESCENDING});\n        assertEquals(TEST_SIZE, sortedList.size());\n        assertEquals(TEST_SIZE - 1, sortedList.first().getFieldLong());\n        assertEquals(0, sortedList.last().getFieldLong());\n    }\n\n    @Test\n    public void sort_date() {\n        if (isSnapshot(collectionClass)) {\n            thrown.expect(UnsupportedOperationException.class);\n        }\n        OrderedRealmCollection<AllJavaTypes> resultList = collection;\n        OrderedRealmCollection<AllJavaTypes> sortedList = createCollection(collectionClass);\n        sortedList = sortedList.sort(AllJavaTypes.FIELD_DATE, Sort.DESCENDING);\n        assertEquals(resultList.size(), sortedList.size());\n        assertEquals(TEST_SIZE, sortedList.size());\n        assertEquals(resultList.first().getFieldDate(), sortedList.last().getFieldDate());\n\n        sortedList = sortedList.sort(AllJavaTypes.FIELD_DATE, Sort.ASCENDING);\n        assertEquals(TEST_SIZE, sortedList.size());\n        assertEquals(resultList.first().getFieldDate(), sortedList.first().getFieldDate());\n        assertEquals(resultList.last().getFieldDate(), sortedList.last().getFieldDate());\n\n        sortedList = sortedList.sort(AllJavaTypes.FIELD_DATE, Sort.DESCENDING);\n        assertEquals(TEST_SIZE, sortedList.size());\n    }\n\n    @Test\n    public void sort_long() {\n        if (isSnapshot(collectionClass)) {\n            thrown.expect(UnsupportedOperationException.class);\n        }\n        OrderedRealmCollection<AllJavaTypes> resultList = collection;\n        OrderedRealmCollection<AllJavaTypes> sortedList = createCollection(collectionClass);\n        sortedList = sortedList.sort(AllJavaTypes.FIELD_LONG, Sort.DESCENDING);\n        assertEquals(\"Should have same size\", resultList.size(), sortedList.size());\n        assertEquals(TEST_SIZE, sortedList.size());\n        assertEquals(\"First excepted to be last\", resultList.first().getFieldLong(), sortedList.last().getFieldLong());\n\n        sortedList = sortedList.sort(AllJavaTypes.FIELD_LONG, Sort.ASCENDING);\n        assertEquals(TEST_SIZE, sortedList.size());\n        assertEquals(\"First excepted to be first\", resultList.first().getFieldLong(), sortedList.first().getFieldLong());\n        assertEquals(\"Last excepted to be last\", resultList.last().getFieldLong(), sortedList.last().getFieldLong());\n\n        sortedList = sortedList.sort(AllJavaTypes.FIELD_LONG, Sort.DESCENDING);\n        assertEquals(TEST_SIZE, sortedList.size());\n    }\n\n    @Test\n    public void deleteFromRealm() {\n        OrderedRealmCollection<Dog> collection = createNonCyclicCollection(realm, collectionClass);\n        assertEquals(1, collection.get(1).getAge());\n\n        int[] indexToDelete = {TEST_SIZE/2, TEST_SIZE - 2, 0};\n        int currentSize = TEST_SIZE;\n\n        for (int i = 0; i < indexToDelete.length; i++) {\n            int index = indexToDelete[i];\n            realm.beginTransaction();\n            Dog dog = collection.get(index);\n            collection.deleteFromRealm(index);\n            realm.commitTransaction();\n            if (isSnapshot(collectionClass)) {\n                assertEquals(TEST_SIZE, collection.size());\n                assertFalse(collection.get(index).isValid());\n            } else {\n                assertEquals(currentSize- 1, collection.size());\n            }\n            assertFalse(dog.isValid());\n            assertEquals(currentSize- 1, realm.where(Dog.class).count());\n            currentSize -= 1;\n        }\n    }\n\n    @Test\n    public void deleteFromRealm_invalidIndex() {\n        Integer[] indexes = new Integer[] { Integer.MIN_VALUE, -1, TEST_SIZE, Integer.MAX_VALUE };\n        for (Integer index : indexes) {\n            try {\n                realm.beginTransaction();\n                collection.deleteFromRealm(index);\n                fail(\"Index should have thrown exception: \" + index);\n            } catch (ArrayIndexOutOfBoundsException ignored) {\n            } finally {\n                realm.cancelTransaction();\n            }\n        }\n    }\n\n    @Test\n    public void deleteFirstFromRealm() {\n        OrderedRealmCollection<Dog> collection = createNonCyclicCollection(realm, collectionClass);\n        assertEquals(0, collection.get(0).getAge());\n\n        realm.beginTransaction();\n        Dog dog = collection.first();\n        assertTrue(collection.deleteFirstFromRealm());\n        realm.commitTransaction();\n        if (isSnapshot(collectionClass)) {\n            assertEquals(TEST_SIZE, collection.size());\n            assertFalse(collection.first().isValid());\n        } else {\n            assertEquals(TEST_SIZE - 1, collection.size());\n            assertEquals(1, collection.get(0).getAge());\n        }\n        assertFalse(dog.isValid());\n        assertEquals(TEST_SIZE - 1, realm.where(Dog.class).count());\n    }\n\n    private OrderedRealmCollection<Dog> createNonCyclicCollection(Realm realm, ManagedCollection collectionClass) {\n        realm.beginTransaction();\n        realm.deleteAll();\n        OrderedRealmCollection<Dog> orderedCollection;\n        switch (collectionClass) {\n            case REALMRESULTS_SNAPSHOT_RESULTS_BASE:\n            case MANAGED_REALMLIST:\n                Owner owner = realm.createObject(Owner.class);\n                RealmList<Dog> dogs = owner.getDogs();\n                for (int i = 0; i < TEST_SIZE; i++) {\n                    Dog dog = realm.createObject(Dog.class);\n                    dog.setName(\"Dog \" + i);\n                    dog.setAge(i);\n                    dogs.add(dog);\n                }\n                realm.commitTransaction();\n                orderedCollection = dogs;\n                break;\n\n            case REALMRESULTS_SNAPSHOT_LIST_BASE:\n            case REALMRESULTS:\n                for (int i = 0; i < TEST_SIZE; i++) {\n                    Dog dog = realm.createObject(Dog.class);\n                    dog.setAge(i);\n                    dog.setName(\"Dog \" + i);\n                }\n                realm.commitTransaction();\n                orderedCollection = realm.where(Dog.class).sort(Dog.FIELD_AGE).findAll();\n                break;\n\n            default:\n                throw new AssertionError(\"Unknown collection class: \" + collectionClass);\n        }\n        if (isSnapshot(collectionClass)) {\n            orderedCollection = orderedCollection.createSnapshot();\n        }\n        return orderedCollection;\n    }\n\n    @Test\n    public void deleteFirstFromRealm_emptyCollection() {\n        OrderedRealmCollection<NullTypes> collection = createEmptyCollection(realm, collectionClass);\n        realm.beginTransaction();\n        assertFalse(collection.deleteFirstFromRealm());\n        realm.commitTransaction();\n        assertEquals(0, collection.size());\n    }\n\n    @Test\n    public void deleteLastFromRealm() {\n        assertEquals(TEST_SIZE - 1, collection.last().getFieldLong());\n        realm.beginTransaction();\n        AllJavaTypes allJavaTypes = collection.last();\n        assertTrue(collection.deleteLastFromRealm());\n        realm.commitTransaction();\n        if (isSnapshot(collectionClass)) {\n            assertEquals(TEST_SIZE, collection.size());\n            assertFalse(collection.last().isValid());\n        } else {\n            assertEquals(TEST_SIZE - 1, collection.size());\n            assertEquals(TEST_SIZE - 2, collection.last().getFieldLong());\n        }\n        assertFalse(allJavaTypes.isValid());\n        assertEquals(TEST_SIZE - 1, realm.where(AllJavaTypes.class).count());\n    }\n\n    @Test\n    public void deleteLastFromRealm_emptyCollection() {\n        OrderedRealmCollection<NullTypes> collection = createEmptyCollection(realm, collectionClass);\n        realm.beginTransaction();\n        assertFalse(collection.deleteLastFromRealm());\n        realm.commitTransaction();\n        assertEquals(0, collection.size());\n    }\n\n    // Tests all methods that mutate data throw correctly if not inside an transaction.\n    // Due to implementation details both UnsupportedOperation and IllegalState is accepted at this level.\n    @Test\n    public void mutableMethodsOutsideTransactions() {\n\n        for (OrderedCollectionMutatorMethod method : OrderedCollectionMutatorMethod.values()) {\n\n            // Define expected exception\n            Class<? extends Throwable> expected = IllegalStateException.class;\n            if (collectionClass == ManagedCollection.REALMRESULTS || isSnapshot(collectionClass)) {\n                switch (method) {\n                    case ADD_INDEX:\n                    case ADD_ALL_INDEX:\n                    case SET:\n                    case REMOVE_INDEX:\n                        expected = UnsupportedOperationException.class;\n                        break;\n                    default:\n                        // Uses default exception.\n                }\n            }\n\n            try {\n                switch (method) {\n                    case DELETE_INDEX: collection.deleteFromRealm(0); break;\n                    case DELETE_FIRST: collection.deleteFirstFromRealm(); break;\n                    case DELETE_LAST: collection.deleteLastFromRealm(); break;\n                    case ADD_INDEX: collection.add(0, new AllJavaTypes()); break;\n                    case ADD_ALL_INDEX: collection.addAll(0, Collections.singletonList(new AllJavaTypes())); break;\n                    case SET: collection.set(0, new AllJavaTypes()); break;\n                    case REMOVE_INDEX: collection.remove(0); break;\n                }\n                fail(\"Unknown method or it failed to throw: \" + method);\n            } catch (IllegalStateException e) {\n                assertEquals(expected, e.getClass());\n            } catch (UnsupportedOperationException e) {\n                assertEquals(expected, e.getClass());\n            }\n        }\n    }\n\n    @Test\n    public void methodsThrowOnWrongThread() throws ExecutionException, InterruptedException {\n        for (OrderedRealmCollectionMethod method : OrderedRealmCollectionMethod.values()) {\n            assertTrue(method + \" failed\", runMethodOnWrongThread(method));\n        }\n\n        for (ListMethod method : ListMethod.values()) {\n            assertTrue(method + \" failed\", runMethodOnWrongThread(method));\n        }\n    }\n\n    private boolean runMethodOnWrongThread(final OrderedRealmCollectionMethod method) throws ExecutionException, InterruptedException {\n        realm.beginTransaction();\n        ExecutorService executorService = Executors.newSingleThreadExecutor();\n        Future<Boolean> future = executorService.submit(new Callable<Boolean>() {\n            @Override\n            public Boolean call() throws Exception {\n                // Defines expected exception.\n                Class<? extends Throwable> expected = IllegalStateException.class;\n                if (isSnapshot(collectionClass)) {\n                    switch (method) {\n                        case SORT:\n                        case SORT_FIELD:\n                        case SORT_2FIELDS:\n                        case SORT_MULTI:\n                            expected = UnsupportedOperationException.class;\n                            break;\n                        default:\n                            break;\n                    }\n                }\n\n                try {\n                    switch (method) {\n                        case DELETE_INDEX: collection.deleteFromRealm(0); break;\n                        case DELETE_FIRST: collection.deleteFirstFromRealm(); break;\n                        case DELETE_LAST: collection.deleteLastFromRealm(); break;\n                        case SORT: collection.sort(AllJavaTypes.FIELD_STRING); break;\n                        case SORT_FIELD: collection.sort(AllJavaTypes.FIELD_STRING, Sort.ASCENDING); break;\n                        case SORT_2FIELDS: collection.sort(AllJavaTypes.FIELD_STRING, Sort.ASCENDING, AllJavaTypes.FIELD_LONG, Sort.DESCENDING); break;\n                        case SORT_MULTI: collection.sort(new String[] { AllJavaTypes.FIELD_STRING }, new Sort[] { Sort.ASCENDING }); break;\n                        case CREATE_SNAPSHOT: collection.createSnapshot(); break;\n                    }\n                    return false;\n                } catch (Throwable t) {\n                    return t.getClass().equals(expected);\n                }\n            }\n        });\n        Boolean result = future.get();\n        realm.cancelTransaction();\n        return result;\n    }\n\n    private boolean runMethodOnWrongThread(final ListMethod method) throws ExecutionException, InterruptedException {\n        realm.beginTransaction();\n        ExecutorService executorService = Executors.newSingleThreadExecutor();\n        Future<Boolean> future = executorService.submit(new Callable<Boolean>() {\n            @Override\n            public Boolean call() throws Exception {\n                // Defines expected exception.\n                Class<? extends Throwable> expected = IllegalStateException.class;\n                if (collectionClass == ManagedCollection.REALMRESULTS || isSnapshot(collectionClass)) {\n                    switch (method) {\n                        case ADD_INDEX:\n                        case ADD_ALL_INDEX:\n                        case SET:\n                        case REMOVE_INDEX:\n                            expected = UnsupportedOperationException.class;\n                            break;\n                        default:\n                            // Uses default exception.\n                    }\n                }\n\n                try {\n                    switch (method) {\n                        case FIRST: collection.first(); break;\n                        case LAST: collection.last(); break;\n                        case ADD_INDEX: collection.add(0, new AllJavaTypes()); break;\n                        case ADD_ALL_INDEX: collection.addAll(0, Collections.singletonList(new AllJavaTypes())); break;\n                        case GET_INDEX: collection.get(0); break;\n                        case INDEX_OF: collection.indexOf(new AllJavaTypes()); break;\n                        case LAST_INDEX_OF: collection.lastIndexOf(new AllJavaTypes()); break;\n                        case LIST_ITERATOR: collection.listIterator(); break;\n                        case LIST_ITERATOR_INDEX: collection.listIterator(0); break;\n                        case REMOVE_INDEX: collection.remove(0); break;\n                        case SET: collection.set(0, new AllJavaTypes()); break;\n                        case SUBLIST: collection.subList(0, 1); break;\n                    }\n                    return false;\n                } catch (Throwable t) {\n                    if (!t.getClass().equals(expected)) {\n                        return false;\n                    }\n                }\n                return true;\n            }\n        });\n        Boolean result = future.get();\n        realm.cancelTransaction();\n        return result;\n    }\n\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/ManagedRealmCollectionTests.java",
    "content": "/*\n * Copyright 2016 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\npackage io.realm;\n\nimport org.hamcrest.CoreMatchers;\nimport org.junit.After;\nimport org.junit.Before;\nimport org.junit.Rule;\nimport org.junit.Test;\nimport org.junit.rules.ExpectedException;\nimport org.junit.runner.RunWith;\nimport org.junit.runners.Parameterized;\n\nimport java.util.Arrays;\nimport java.util.Collections;\nimport java.util.Date;\nimport java.util.List;\nimport java.util.concurrent.Callable;\nimport java.util.concurrent.ExecutionException;\nimport java.util.concurrent.ExecutorService;\nimport java.util.concurrent.Executors;\nimport java.util.concurrent.Future;\n\nimport io.realm.entities.AllJavaTypes;\nimport io.realm.entities.NonLatinFieldNames;\nimport io.realm.entities.NullTypes;\n\nimport static org.junit.Assert.assertEquals;\nimport static org.junit.Assert.assertFalse;\nimport static org.junit.Assert.assertNull;\nimport static org.junit.Assert.assertTrue;\nimport static org.junit.Assert.fail;\n\n/**\n * Test class for all methods part of the the {@link RealmCollection} interface.\n * This class only tests collections that are managed by Realm. See {@link UnManagedRealmCollectionTests} for\n * all tests targeting unmanaged collections.\n *\n * Methods tested in this class:\n *\n * # RealmCollection\n *\n * + RealmQuery<E> where();\n * + Number min(String fieldName);\n * + Number max(String fieldName);\n * + Number sum(String fieldName);\n * + double average(String fieldName);\n * + Date maxDate(String fieldName);\n * + Date minDate(String fieldName);\n * + void deleteAllFromRealm();\n * + boolean isLoaded();\n * + boolean load();\n * + boolean isValid();\n * + BaseRealm getRealm();\n *\n * # Collection\n *\n * - public boolean add(E object);\n * - public boolean addAll(Collection<? extends E> collection);\n * - public void deleteAll();\n * - public boolean contains(Object object);\n * - public boolean containsAll(Collection<?> collection);\n * - public boolean equals(Object object);\n * - public int hashCode();\n * - public boolean isEmpty();\n * - public Iterator<E> iterator();\n * - public boolean remove(Object object);\n * - public boolean removeAll(Collection<?> collection);\n * - public boolean retainAll(Collection<?> collection);\n * - public int size();\n * - public Object[] toArray();\n * - public <T> T[] toArray(T[] array);\n */\n@RunWith(Parameterized.class)\npublic class ManagedRealmCollectionTests extends CollectionTests {\n\n    private static final int TEST_SIZE = 10;\n\n    @Rule\n    public final TestRealmConfigurationFactory configFactory = new TestRealmConfigurationFactory();\n    @Rule\n    public final ExpectedException thrown = ExpectedException.none();\n\n    private final ManagedCollection collectionClass;\n    private Realm realm;\n\n    // Collections used for testing\n    private RealmCollection<AllJavaTypes> collection;\n\n    @Parameterized.Parameters(name = \"{0}\")\n    public static List<ManagedCollection> data() {\n        return Arrays.asList(ManagedCollection.values());\n    }\n\n    public ManagedRealmCollectionTests(ManagedCollection collectionType) {\n        this.collectionClass = collectionType;\n    }\n\n    @Before\n    public void setup() {\n        realm = Realm.getInstance(configFactory.createConfiguration());\n        populateRealm(realm, TEST_SIZE);\n        collection = createCollection(collectionClass);\n    }\n\n    @After\n    public void tearDown() {\n        realm.close();\n    }\n\n    private OrderedRealmCollection<AllJavaTypes> createCollection(ManagedCollection collectionClass) {\n        OrderedRealmCollection<AllJavaTypes> orderedCollection;\n        switch (collectionClass) {\n            case REALMRESULTS_SNAPSHOT_LIST_BASE:\n            case MANAGED_REALMLIST:\n                orderedCollection = realm.where(AllJavaTypes.class)\n                        .equalTo(AllJavaTypes.FIELD_LONG, 0)\n                        .findFirst()\n                        .getFieldList();\n                break;\n\n            case REALMRESULTS_SNAPSHOT_RESULTS_BASE:\n            case REALMRESULTS:\n                orderedCollection = realm.where(AllJavaTypes.class)\n                        .sort(AllJavaTypes.FIELD_LONG, Sort.ASCENDING)\n                        .findAll();\n                break;\n\n            default:\n                throw new AssertionError(\"Unsupported class: \" + collectionClass);\n        }\n        if (isSnapshot(collectionClass)) {\n            orderedCollection = orderedCollection.createSnapshot();\n        }\n        return orderedCollection;\n    }\n\n    private OrderedRealmCollection<NullTypes> createEmptyCollection(Realm realm, ManagedCollection collectionClass) {\n        OrderedRealmCollection<NullTypes> orderedCollection;\n        switch (collectionClass) {\n            case REALMRESULTS_SNAPSHOT_LIST_BASE:\n            case MANAGED_REALMLIST:\n                realm.beginTransaction();\n                NullTypes obj = realm.createObject(NullTypes.class, 0);\n                realm.commitTransaction();\n                orderedCollection = obj.getFieldListNull();\n                break;\n\n            case REALMRESULTS_SNAPSHOT_RESULTS_BASE:\n            case REALMRESULTS:\n                orderedCollection = realm.where(NullTypes.class).findAll();\n                break;\n            default:\n                throw new AssertionError(\"Unknown collection: \" + collectionClass);\n        }\n\n        if (isSnapshot(collectionClass)) {\n            orderedCollection = orderedCollection.createSnapshot();\n        }\n        return orderedCollection;\n    }\n\n    private OrderedRealmCollection<NullTypes> createAllNullRowsForNumericTesting(Realm realm, ManagedCollection collectionClass) {\n        TestHelper.populateAllNullRowsForNumericTesting(realm);\n        OrderedRealmCollection<NullTypes> orderedCollection;\n        switch (collectionClass) {\n            case REALMRESULTS_SNAPSHOT_LIST_BASE:\n            case MANAGED_REALMLIST:\n                RealmResults<NullTypes> results = realm.where(NullTypes.class).findAll();\n                RealmList<NullTypes> list = results.get(0).getFieldListNull();\n                realm.beginTransaction();\n                for (int i = 0; i < results.size(); i++) {\n                    list.add(results.get(i));\n                }\n                realm.commitTransaction();\n                orderedCollection = list;\n                break;\n\n            case REALMRESULTS_SNAPSHOT_RESULTS_BASE:\n            case REALMRESULTS:\n                orderedCollection = realm.where(NullTypes.class).findAll();\n                break;\n            default:\n                throw new AssertionError(\"Unknown collection: \" + collectionClass);\n        }\n\n        if (isSnapshot(collectionClass)) {\n            orderedCollection = orderedCollection.createSnapshot();\n        }\n\n        return orderedCollection;\n    }\n\n    private OrderedRealmCollection<NullTypes> createPartialNullRowsForNumericTesting(Realm realm, ManagedCollection collectionClass) {\n        populatePartialNullRowsForNumericTesting(realm);\n        OrderedRealmCollection<NullTypes> orderedCollection;\n        switch (collectionClass) {\n            case REALMRESULTS_SNAPSHOT_LIST_BASE:\n            case MANAGED_REALMLIST:\n                RealmResults<NullTypes> results = realm.where(NullTypes.class).findAll();\n                RealmList<NullTypes> list = results.get(0).getFieldListNull();\n                realm.beginTransaction();\n                int size = results.size();\n                for (int i = 0; i < size; i++) {\n                    list.add(results.get(i));\n                }\n                realm.commitTransaction();\n                orderedCollection = list;\n                break;\n\n            case REALMRESULTS_SNAPSHOT_RESULTS_BASE:\n            case REALMRESULTS:\n                orderedCollection = realm.where(NullTypes.class).findAll();\n                break;\n            default:\n                throw new AssertionError(\"Unknown collection: \" + collectionClass);\n        }\n\n        if (isSnapshot(collectionClass)) {\n            orderedCollection = orderedCollection.createSnapshot();\n        }\n        return orderedCollection;\n    }\n\n    // PRE-CONDITION: populateRealm() was called as part of setUp()\n    private OrderedRealmCollection<NonLatinFieldNames> createNonLatinCollection(Realm realm, ManagedCollection collectionClass) {\n        OrderedRealmCollection<NonLatinFieldNames> orderedCollection;\n        switch (collectionClass) {\n            case REALMRESULTS_SNAPSHOT_LIST_BASE:\n            case MANAGED_REALMLIST:\n                realm.beginTransaction();\n                RealmResults<NonLatinFieldNames> results = realm.where(NonLatinFieldNames.class).findAll();\n                RealmList<NonLatinFieldNames> list = results.get(0).getChildren();\n                for (int i = 0; i < results.size(); i++) {\n                    list.add(results.get(i));\n                }\n                realm.commitTransaction();\n                orderedCollection = list;\n                break;\n\n            case REALMRESULTS_SNAPSHOT_RESULTS_BASE:\n            case REALMRESULTS:\n                orderedCollection = realm.where(NonLatinFieldNames.class).findAll();\n                break;\n\n            default:\n                throw new AssertionError(\"Unknown collection: \" + collectionClass);\n        }\n\n        if (isSnapshot(collectionClass)) {\n            orderedCollection = orderedCollection.createSnapshot();\n        }\n        return orderedCollection;\n    }\n\n    @Test\n    public void where() {\n        if (isSnapshot(collectionClass)) {\n            thrown.expect(UnsupportedOperationException.class);\n        }\n        RealmResults<AllJavaTypes> results = collection.where().findAll();\n        assertEquals(TEST_SIZE, results.size());\n    }\n\n    @Test\n    public void where_contains() {\n        RealmQuery<AllJavaTypes> query = realm.where(AllJavaTypes.class).findAll().where();\n        AllJavaTypes item = query.findFirst();\n        assertTrue(\"Item should exist in results.\", query.findAll().contains(item));\n    }\n\n    @Test\n    public void where_contains_null() {\n        RealmQuery<AllJavaTypes> query = realm.where(AllJavaTypes.class).findAll().where();\n        assertFalse(\"Should not contain a null item.\", query.findAll().contains(null));\n    }\n\n    @Test\n    public void where_shouldNotContainRemovedItem() {\n        RealmQuery<AllJavaTypes> query = realm.where(AllJavaTypes.class).findAll().where();\n        AllJavaTypes item = realm.where(AllJavaTypes.class).findFirst();\n        realm.beginTransaction();\n        item.deleteFromRealm();\n        realm.commitTransaction();\n        assertFalse(\"Should not contain a removed item.\", query.findAll().contains(item));\n    }\n\n    /**\n     * Tests to see if a particular item that does exist in the same Realm does not\n     * exist in the result set of another query.\n     */\n    @Test\n    public void where_lessThanGreaterThan() {\n        RealmResults<AllJavaTypes> items = realm.where(AllJavaTypes.class).lessThan(AllJavaTypes.FIELD_LONG, 1000).findAll();\n        AllJavaTypes anotherType = realm.where(AllJavaTypes.class).greaterThan(AllJavaTypes.FIELD_LONG, 1000).findFirst();\n        assertFalse(\"Should not be able to find item in another result list.\", items.contains(anotherType));\n    }\n\n    @Test\n    public void where_equalTo_manyConditions() {\n        RealmQuery<AllJavaTypes> query = realm.where(AllJavaTypes.class);\n        query.equalTo(AllJavaTypes.FIELD_LONG, 0);\n        for (int i = 1; i < TEST_SIZE; i++) {\n            query.or().equalTo(AllJavaTypes.FIELD_LONG, i);\n        }\n        RealmResults<AllJavaTypes> allTypesRealmResults = query.findAll();\n        assertEquals(TEST_SIZE, allTypesRealmResults.size());\n    }\n\n    @Test\n    public void where_findAll_size() {\n        RealmResults<AllJavaTypes> results = realm.where(AllJavaTypes.class).findAll();\n        assertEquals(TEST_SIZE, results.size());\n\n        // Querying a RealmResults should find objects that fulfill the condition.\n        RealmResults<AllJavaTypes> onedigits = results.where().lessThan(AllJavaTypes.FIELD_LONG, 10).findAll();\n        assertEquals(Math.min(10, TEST_SIZE), onedigits.size());\n\n        // If no objects fulfill conditions, the result has zero objects.\n        RealmResults<AllJavaTypes> none = results.where().greaterThan(AllJavaTypes.FIELD_LONG, TEST_SIZE).findAll();\n        assertEquals(0, none.size());\n\n        // Querying a result with zero objects must give zero objects.\n        RealmResults<AllJavaTypes> stillNone = none.where().greaterThan(AllJavaTypes.FIELD_LONG, TEST_SIZE).findAll();\n        assertEquals(0, stillNone.size());\n    }\n\n    @Test\n    public void where_sort() {\n        RealmResults<AllJavaTypes> results = realm.where(AllJavaTypes.class).sort(AllJavaTypes.FIELD_LONG, Sort.ASCENDING).findAll();\n        assertEquals(TEST_SIZE, results.size());\n        //noinspection ConstantConditions\n        assertEquals(0, results.first().getFieldLong());\n        //noinspection ConstantConditions\n        assertEquals(TEST_SIZE - 1, results.last().getFieldLong());\n\n        RealmResults<AllJavaTypes> reverseList = realm.where(AllJavaTypes.class).sort(AllJavaTypes.FIELD_LONG, Sort.DESCENDING).findAll();\n        assertEquals(TEST_SIZE, reverseList.size());\n        //noinspection ConstantConditions\n        assertEquals(0, reverseList.last().getFieldLong());\n        //noinspection ConstantConditions\n        assertEquals(TEST_SIZE - 1, reverseList.first().getFieldLong());\n\n        try {\n            realm.where(AllJavaTypes.class).sort(\"invalid\", Sort.DESCENDING).findAll();\n            fail();\n        } catch (IllegalArgumentException ignored) {\n        }\n    }\n\n    @Test\n    public void where_queryDateField() {\n        RealmQuery<AllJavaTypes> query = realm.where(AllJavaTypes.class).equalTo(AllJavaTypes.FIELD_DATE, new Date(YEAR_MILLIS * 20));\n        RealmResults<AllJavaTypes> all = query.findAll();\n        assertEquals(1, query.count());\n        assertEquals(1, all.size());\n\n        // before 1901\n        query = realm.where(AllJavaTypes.class).equalTo(AllJavaTypes.FIELD_DATE, new Date(YEAR_MILLIS * -100));\n        all = query.findAll();\n        assertEquals(1, query.count());\n        assertEquals(1, all.size());\n\n        // after 2038\n        query = realm.where(AllJavaTypes.class).equalTo(AllJavaTypes.FIELD_DATE, new Date(YEAR_MILLIS * 80));\n        all = query.findAll();\n        assertEquals(1, query.count());\n        assertEquals(1, all.size());\n    }\n\n    @Test\n    public void min() {\n        Number minimum = collection.min(AllJavaTypes.FIELD_LONG);\n        assertEquals(0, minimum.intValue());\n    }\n\n    // Tests min on empty columns.\n    @Test\n    public void min_emptyNonNullFields() {\n        OrderedRealmCollection<NullTypes> results = createEmptyCollection(realm, collectionClass);\n        assertNull(results.min(NullTypes.FIELD_INTEGER_NOT_NULL));\n        assertNull(results.min(NullTypes.FIELD_FLOAT_NOT_NULL));\n        assertNull(results.min(NullTypes.FIELD_DOUBLE_NOT_NULL));\n        assertNull(results.minDate(NullTypes.FIELD_DATE_NOT_NULL));\n    }\n\n    // Tests min on nullable rows with all null values.\n    @Test\n    public void min_emptyNullFields() {\n        OrderedRealmCollection<NullTypes> results = createAllNullRowsForNumericTesting(realm, collectionClass);\n        assertNull(results.max(NullTypes.FIELD_INTEGER_NULL));\n        assertNull(results.max(NullTypes.FIELD_FLOAT_NULL));\n        assertNull(results.max(NullTypes.FIELD_DOUBLE_NULL));\n        assertNull(results.maxDate(NullTypes.FIELD_DATE_NULL));\n    }\n\n    // Tests min on nullable rows with partial null values.\n    @Test\n    public void min_partialNullRows() {\n        OrderedRealmCollection<NullTypes> results = createPartialNullRowsForNumericTesting(realm, collectionClass);\n        assertEquals(0, results.min(NullTypes.FIELD_INTEGER_NULL).intValue());\n        assertEquals(0f, results.min(NullTypes.FIELD_FLOAT_NULL).floatValue(), 0f);\n        assertEquals(0d, results.min(NullTypes.FIELD_DOUBLE_NULL).doubleValue(), 0d);\n    }\n\n    @Test\n    public void max() {\n        Number maximum = collection.max(AllJavaTypes.FIELD_LONG);\n        assertEquals(TEST_SIZE - 1, maximum.intValue());\n    }\n\n    // Tests max on empty columns.\n    @Test\n    public void max_emptyNonNullFields() {\n        OrderedRealmCollection<NullTypes> results = createEmptyCollection(realm, collectionClass);\n        assertNull(results.max(NullTypes.FIELD_INTEGER_NOT_NULL));\n        assertNull(results.max(NullTypes.FIELD_FLOAT_NOT_NULL));\n        assertNull(results.max(NullTypes.FIELD_DOUBLE_NOT_NULL));\n        assertNull(results.maxDate(NullTypes.FIELD_DATE_NOT_NULL));\n    }\n\n    // Tests max on nullable rows with all null values.\n    @Test\n    public void max_emptyNullFields() {\n        OrderedRealmCollection<NullTypes> results = createAllNullRowsForNumericTesting(realm, collectionClass);\n        assertNull(results.max(NullTypes.FIELD_INTEGER_NULL));\n        assertNull(results.max(NullTypes.FIELD_FLOAT_NULL));\n        assertNull(results.max(NullTypes.FIELD_DOUBLE_NULL));\n        assertNull(results.maxDate(NullTypes.FIELD_DATE_NULL));\n    }\n\n    // Tests max on nullable rows with partial null values.\n    @Test\n    public void max_partialNullRows() {\n        OrderedRealmCollection<NullTypes> results = createPartialNullRowsForNumericTesting(realm, collectionClass);\n        assertEquals(1, results.max(NullTypes.FIELD_INTEGER_NULL).intValue());\n        assertEquals(2f, results.max(NullTypes.FIELD_FLOAT_NULL).floatValue(), 0f);\n        assertEquals(3d, results.max(NullTypes.FIELD_DOUBLE_NULL).doubleValue(), 0d);\n    }\n\n    @Test\n    public void sum() {\n        Number sum = collection.sum(AllJavaTypes.FIELD_LONG);\n        // Sum of numbers 0 to M-1: (M-1)*M/2\n        assertEquals((TEST_SIZE - 1) * TEST_SIZE / 2, sum.intValue());\n    }\n\n    // Tests sum on nullable rows with all null values.\n    @Test\n    public void sum_nullRows() {\n        OrderedRealmCollection<NullTypes> resultList = createAllNullRowsForNumericTesting(realm, collectionClass);\n        assertEquals(0, resultList.sum(NullTypes.FIELD_INTEGER_NULL).intValue());\n        assertEquals(0f, resultList.sum(NullTypes.FIELD_FLOAT_NULL).floatValue(), 0f);\n        assertEquals(0d, resultList.sum(NullTypes.FIELD_DOUBLE_NULL).doubleValue(), 0d);\n    }\n\n    // Tests sum on nullable rows with partial null values.\n    @Test\n    public void sum_partialNullRows() {\n        OrderedRealmCollection<NullTypes> resultList = createPartialNullRowsForNumericTesting(realm, collectionClass);\n\n        assertEquals(1, resultList.sum(NullTypes.FIELD_INTEGER_NULL).intValue());\n        assertEquals(2f, resultList.sum(NullTypes.FIELD_FLOAT_NULL).floatValue(), 0f);\n        assertEquals(3d, resultList.sum(NullTypes.FIELD_DOUBLE_NULL).doubleValue(), 0d);\n    }\n\n    @Test\n    public void sum_nonLatinColumnNames() {\n        OrderedRealmCollection<NonLatinFieldNames> resultList = createNonLatinCollection(realm, collectionClass);\n\n        Number sum = resultList.sum(NonLatinFieldNames.FIELD_LONG_KOREAN_CHAR);\n        // Sum of numbers 0 to M-1: (M-1)*M/2\n        assertEquals((TEST_SIZE - 1) * TEST_SIZE / 2, sum.intValue());\n\n        sum = resultList.sum(NonLatinFieldNames.FIELD_LONG_GREEK_CHAR);\n        // Sum of numbers 0 to M-1: (M-1)*M/2\n        assertEquals((TEST_SIZE - 1) * TEST_SIZE / 2, sum.intValue());\n    }\n\n    @Test\n    public void avg() {\n        double N = (double) TEST_SIZE;\n\n        // Sum of numbers 1 to M: M*(M+1)/2\n        // See setUp() for values of fields.\n        // N = TEST_DATA_SIZE\n\n        // Type: double; a = Math.PI\n        // a, a+1, ..., a+i, ..., a+N-1\n        // sum = Math.PI*N + N*(N-1)/2\n        // average = sum/N = Math.PI+(N-1)/2\n        double average = Math.PI + (N - 1.0) * 0.5;\n        assertEquals(average, collection.average(AllJavaTypes.FIELD_DOUBLE), 0.0001);\n\n        // Type: long\n        // 0, 1, ..., N-1\n        // sum = N*(N-1)/2\n        // average = sum/N = (N-1)/2\n        assertEquals(0.5 * (N - 1), collection.average(AllJavaTypes.FIELD_LONG), 0.0001);\n\n        // Type: float; b = 1.234567\n        // b, b+1, ..., b+i, ..., b+N-1\n        // sum = b*N + N*(N-1)/2\n        // average = sum/N = b + (N-1)/2\n        assertEquals(1.234567 + 0.5 * (N - 1.0), collection.average(AllJavaTypes.FIELD_FLOAT), 0.0001);\n    }\n\n    // Tests average on empty columns.\n    @Test\n    public void avg_emptyNonNullFields() {\n        OrderedRealmCollection<NullTypes> resultList = createEmptyCollection(realm, collectionClass);\n        assertEquals(0d, resultList.average(NullTypes.FIELD_INTEGER_NOT_NULL), 0d);\n        assertEquals(0d, resultList.average(NullTypes.FIELD_FLOAT_NOT_NULL), 0d);\n        assertEquals(0d, resultList.average(NullTypes.FIELD_DOUBLE_NOT_NULL), 0d);\n    }\n\n    // Tests average on nullable rows with all null values.\n    @Test\n    public void avg_emptyNullFields() {\n        OrderedRealmCollection<NullTypes> resultList = createEmptyCollection(realm, collectionClass);\n        assertEquals(0d, resultList.average(NullTypes.FIELD_INTEGER_NULL), 0d);\n        assertEquals(0d, resultList.average(NullTypes.FIELD_FLOAT_NULL), 0d);\n        assertEquals(0d, resultList.average(NullTypes.FIELD_DOUBLE_NULL), 0d);\n    }\n\n    // Tests average on nullable rows with partial null values.\n    @Test\n    public void avg_partialNullRows() {\n        OrderedRealmCollection<NullTypes> resultList = createPartialNullRowsForNumericTesting(realm, collectionClass);\n        assertEquals(0.5d, resultList.average(NullTypes.FIELD_INTEGER_NULL), 0d);\n        assertEquals(1.0d, resultList.average(NullTypes.FIELD_FLOAT_NULL), 0d);\n        assertEquals(1.5d, resultList.average(NullTypes.FIELD_DOUBLE_NULL), 0d);\n    }\n\n    @Test\n    public void maxDate() {\n        assertEquals(TEST_SIZE, collection.size());\n        assertEquals(new Date(YEAR_MILLIS * 20 * (TEST_SIZE / 2 - 1)), collection.maxDate(AllJavaTypes.FIELD_DATE));\n    }\n\n    @Test\n    public void minDate() {\n        assertEquals(TEST_SIZE, collection.size());\n        assertEquals(new Date(-YEAR_MILLIS * 20 * TEST_SIZE / 2), collection.minDate(AllJavaTypes.FIELD_DATE));\n    }\n\n    // Deletes the last row in the collection then tests the aggregates methods.\n    // Since deletion will turn the corresponding object into invalid for collection snapshot, this tests if the\n    // aggregates methods ignore the invalid rows and return the correct result.\n    @Test\n    public void aggregates_deleteLastRow() {\n        assertTrue(TEST_SIZE > 3);\n        assertEquals(TEST_SIZE, collection.size());\n        realm.beginTransaction();\n        realm.where(AllJavaTypes.class).equalTo(AllJavaTypes.FIELD_LONG, TEST_SIZE - 1).findFirst().deleteFromRealm();\n        realm.commitTransaction();\n\n        int sizeAfterRemove = TEST_SIZE - 1;\n\n        assertEquals(0, collection.min(AllJavaTypes.FIELD_LONG).intValue());\n        assertEquals(sizeAfterRemove - 1, collection.max(AllJavaTypes.FIELD_LONG).intValue());\n        // Sum of numbers 0 to M-1: (M-1)*M/2\n        assertEquals((sizeAfterRemove - 1) * sizeAfterRemove / 2, collection.sum(AllJavaTypes.FIELD_LONG).intValue());\n        double average = Math.PI + (sizeAfterRemove - 1.0) * 0.5;\n        assertEquals(average, collection.average(AllJavaTypes.FIELD_DOUBLE), 0.0001);\n        assertEquals(new Date(YEAR_MILLIS * 20 * (sizeAfterRemove / 2 - 1)), collection.maxDate(AllJavaTypes.FIELD_DATE));\n        assertEquals(new Date(-YEAR_MILLIS * 20 * TEST_SIZE / 2), collection.minDate(AllJavaTypes.FIELD_DATE));\n    }\n\n    @Test\n    public void realmMethods_invalidFieldNames() {\n        String[] fieldNames = new String[] {\n                null, \"\", \"foo\", AllJavaTypes.FIELD_STRING + \".foo\", TestHelper.getRandomString(65)\n        };\n\n        for (RealmCollectionMethod realmMethod : RealmCollectionMethod.values()) {\n            for (String fieldName : fieldNames) {\n                try {\n                    switch (realmMethod) {\n                        case MIN: collection.min(fieldName); break;\n                        case MAX: collection.max(fieldName); break;\n                        case SUM: collection.sum(fieldName); break;\n                        case AVERAGE: collection.average(fieldName); break;\n                        case MIN_DATE: collection.minDate(fieldName); break;\n                        case MAX_DATE: collection.maxDate(fieldName); break;\n\n                        // These methods doesn't take any arguments.\n                        // Just skip them.\n                        case WHERE:\n                        case DELETE_ALL_FROM_REALM:\n                        case IS_VALID:\n                        case IS_MANAGED:\n                        case IS_FROZEN:\n                        case FREEZE:\n                            continue;\n\n                        default:\n                            fail(\"Unknown method: \" + realmMethod);\n\n                    }\n                    fail(realmMethod + \" did not throw an exception for input: \" + fieldName);\n                } catch (IllegalArgumentException ignored) {\n                }\n            }\n        }\n    }\n\n    @Test\n    public void realmMethods_invalidFieldType() {\n        String fieldName = AllJavaTypes.FIELD_STRING;\n        for (RealmCollectionMethod realmMethod : RealmCollectionMethod.values()) {\n            try {\n                switch (realmMethod) {\n                    case MIN: collection.min(fieldName); break;\n                    case MAX: collection.max(fieldName); break;\n                    case SUM: collection.sum(fieldName); break;\n                    case AVERAGE: collection.average(fieldName); break;\n                    case MIN_DATE: collection.minDate(fieldName); break;\n                    case MAX_DATE: collection.maxDate(fieldName); break;\n\n                    // These methods doesn't take any arguments.\n                    // Just skip them.\n                    case WHERE:\n                    case DELETE_ALL_FROM_REALM:\n                    case IS_VALID:\n                    case IS_MANAGED:\n                    case IS_FROZEN:\n                    case FREEZE:\n                        continue;\n\n                    default:\n                        fail(\"Unknown method: \" + realmMethod);\n\n                }\n                fail(realmMethod + \" did not throw an exception for input: \" + fieldName);\n            } catch (IllegalArgumentException ignored) {\n            }\n        }\n    }\n\n    @Test\n    public void deleteAllFromRealm() {\n        // If we have a self-referencing collection, removing all objects will crash\n        // any following method. To avoid that scenario we make sure to use a collection\n        // without cycles.\n        int size = TEST_SIZE;\n        if (collectionClass == ManagedCollection.MANAGED_REALMLIST) {\n            RealmList list = (RealmList) collection;\n            realm.beginTransaction();\n            list.remove(0); // Breaks the cycle.\n            realm.commitTransaction();\n            size = TEST_SIZE - 1;\n        }\n\n        assertEquals(size, collection.size());\n        realm.beginTransaction();\n        assertTrue(collection.deleteAllFromRealm());\n        realm.commitTransaction();\n        if (isSnapshot(collectionClass)) {\n            assertEquals(TEST_SIZE, collection.size());\n        } else {\n            assertEquals(0, collection.size());\n        }\n        if (isRealmList(collectionClass)) {\n            // The parent object was not deleted\n            assertEquals(1, realm.where(AllJavaTypes.class).count());\n        } else {\n            assertEquals(0, realm.where(AllJavaTypes.class).count());\n        }\n    }\n\n    @Test(expected = IllegalStateException.class)\n    public void deleteAllFromRealm_outsideTransaction() {\n        collection.deleteAllFromRealm();\n    }\n\n    @Test\n    public void deleteAllFromRealm_emptyList() {\n        OrderedRealmCollection<NullTypes> collection = createEmptyCollection(realm, collectionClass);\n\n        realm.beginTransaction();\n        assertFalse(collection.deleteAllFromRealm());\n        realm.commitTransaction();\n        assertEquals(0, collection.size());\n    }\n\n    @Test\n    public void deleteAllFromRealm_invalidList() {\n        realm.close();\n        thrown.expect(IllegalStateException.class);\n        thrown.expectMessage(CoreMatchers.containsString(\n                \"This Realm instance has already been closed, making it unusable.\"));\n        collection.deleteAllFromRealm();\n    }\n\n    @Test\n    public void isLoaded() {\n        // RealmCollections are currently always loaded. Only exception is RealmResults.\n        // See RealmResultsTests for extended tests on this.\n        assertTrue(collection.isLoaded());\n    }\n\n    @Test\n    public void load() {\n        // RealmCollections are currently always loaded, so this just returns true. Only exception is RealmResults.\n        // See RealmResultsTests for extended tests on this.\n        assertTrue(collection.load());\n    }\n\n    @Test\n    public void isValid() {\n        assertTrue(collection.isValid());\n    }\n\n    @Test\n    public void isValid_realmClosed() {\n        realm.close();\n        assertFalse(collection.isValid());\n    }\n\n    @Test\n    public void isManaged() {\n        assertTrue(collection.isManaged());\n    }\n\n    @Test\n    public void contains_deletedRealmObject() {\n        AllJavaTypes obj = collection.iterator().next();\n        realm.beginTransaction();\n        obj.deleteFromRealm();\n        realm.commitTransaction();\n\n        assertFalse(collection.contains(obj));\n    }\n\n    @Test\n    public void equals_sameRealmObjectsDifferentCollection() {\n        assertTrue(collection.equals(createCollection(collectionClass)));\n    }\n\n    // Tests all methods that mutate data throw correctly if not inside an transaction.\n    // Due to implementation details both UnsupportedOperation and IllegalState is accepted at this level.\n    @Test\n    public void mutableMethodsOutsideTransactions() {\n        for (CollectionMutatorMethod method : CollectionMutatorMethod.values()) {\n\n            // Defines expected exception.\n            Class<? extends Throwable> expected = IllegalStateException.class;\n            if (collectionClass == ManagedCollection.REALMRESULTS || isSnapshot(collectionClass)) {\n                switch (method) {\n                    case ADD_OBJECT:\n                    case ADD_ALL_OBJECTS:\n                    case CLEAR:\n                    case REMOVE_OBJECT:\n                    case REMOVE_ALL:\n                    case RETAIN_ALL:\n                        expected = UnsupportedOperationException.class;\n                        break;\n                    default:\n                        // use default exception\n                }\n            }\n\n            try {\n                switch (method) {\n                    case DELETE_ALL: collection.deleteAllFromRealm(); break;\n                    case ADD_OBJECT: collection.add(new AllJavaTypes()); break;\n                    case ADD_ALL_OBJECTS: collection.addAll(Collections.singletonList(new AllJavaTypes())); break;\n                    case CLEAR: collection.clear(); break;\n                    case REMOVE_OBJECT: collection.remove(new AllJavaTypes()); break;\n                    case REMOVE_ALL: collection.removeAll(Collections.singletonList(new AllJavaTypes())); break;\n                    case RETAIN_ALL: collection.retainAll(Collections.singletonList(new AllJavaTypes())); break;\n                }\n                fail(\"Unknown method or it failed to throw: \" + method);\n            } catch (IllegalStateException e) {\n                assertEquals(expected, e.getClass());\n            } catch (UnsupportedOperationException e) {\n                assertEquals(expected, e.getClass());\n            }\n        }\n    }\n\n    @Test\n    public void methodsThrowOnWrongThread() throws ExecutionException, InterruptedException {\n        realm.beginTransaction();\n        AllJavaTypes allJavaTypes = realm.createObject(AllJavaTypes.class, 42);\n        realm.commitTransaction();\n        for (RealmCollectionMethod method : RealmCollectionMethod.values()) {\n            assertTrue(method + \" failed\", runMethodOnWrongThread(method));\n        }\n        for (CollectionMethod method : CollectionMethod.values()) {\n            assertTrue(method + \" failed\", runMethodOnWrongThread(method, allJavaTypes));\n        }\n    }\n\n    private boolean runMethodOnWrongThread(final RealmCollectionMethod method)\n            throws ExecutionException, InterruptedException {\n        realm.beginTransaction();\n        ExecutorService executorService = Executors.newSingleThreadExecutor();\n        Future<Boolean> future = executorService.submit(new Callable<Boolean>() {\n            @Override\n            public Boolean call() throws Exception {\n                try {\n                    switch (method) {\n                        case WHERE: collection.where(); break;\n                        case MIN: collection.min(AllJavaTypes.FIELD_LONG); break;\n                        case MAX: collection.min(AllJavaTypes.FIELD_LONG); break;\n                        case SUM: collection.sum(AllJavaTypes.FIELD_LONG); break;\n                        case AVERAGE: collection.average(AllJavaTypes.FIELD_LONG); break;\n                        case MIN_DATE: collection.minDate(AllJavaTypes.FIELD_DATE); break;\n                        case MAX_DATE: collection.maxDate(AllJavaTypes.FIELD_DATE); break;\n                        case DELETE_ALL_FROM_REALM: collection.deleteAllFromRealm(); break;\n                        case IS_VALID: collection.isValid(); break;\n                        case IS_MANAGED: collection.isManaged(); return true;\n\n                        // These methods are threadsafe pr. design\n                        case IS_FROZEN:\n                        case FREEZE:\n                            return true;\n                    }\n                    return false;\n                } catch (IllegalStateException ignored) {\n                    return true;\n                } catch (UnsupportedOperationException ignored) {\n                    return (method == RealmCollectionMethod.WHERE && isSnapshot(collectionClass));\n                }\n            }\n        });\n        Boolean result = future.get();\n        realm.cancelTransaction();\n        return result;\n    }\n\n    private boolean runMethodOnWrongThread(final CollectionMethod method, final AllJavaTypes tempObject)\n            throws ExecutionException, InterruptedException {\n        realm.beginTransaction();\n        ExecutorService executorService = Executors.newSingleThreadExecutor();\n        Future<Boolean> future = executorService.submit(new Callable<Boolean>() {\n            @Override\n            public Boolean call() throws Exception {\n\n                // Defines expected exception.\n                Class<? extends Throwable> expected = IllegalStateException.class;\n                if (collectionClass == ManagedCollection.REALMRESULTS || isSnapshot(collectionClass)) {\n                    switch (method) {\n                        case ADD_OBJECT:\n                        case ADD_ALL_OBJECTS:\n                        case CLEAR:\n                        case REMOVE_OBJECT:\n                        case REMOVE_ALL:\n                        case RETAIN_ALL:\n                            expected = UnsupportedOperationException.class;\n                            break;\n                        default:\n                            // use default exception\n                    }\n                }\n\n                try {\n                    switch (method) {\n                        case ADD_OBJECT: collection.add(new AllJavaTypes()); break;\n                        case ADD_ALL_OBJECTS: collection.addAll(Collections.singletonList(new AllJavaTypes())); break;\n                        case CLEAR: collection.clear(); break;\n                        case CONTAINS: collection.contains(tempObject); break;\n                        case CONTAINS_ALL: collection.containsAll(Collections.singletonList(tempObject)); break;\n                        case EQUALS:\n                            //noinspection ResultOfMethodCallIgnored\n                            collection.equals(createCollection(collectionClass)); break;\n                        case HASHCODE:\n                            //noinspection ResultOfMethodCallIgnored\n                            collection.hashCode();\n                            break;\n                        case IS_EMPTY: collection.isEmpty(); break;\n                        case ITERATOR: return true; // Creating an iterator should be safe. Accessing it will fail, but tested elsewhere.\n                        case REMOVE_OBJECT: collection.remove(new AllJavaTypes()); break;\n                        case REMOVE_ALL: collection.removeAll(Collections.singletonList(new AllJavaTypes())); break;\n                        case RETAIN_ALL: collection.retainAll(Collections.singletonList(new AllJavaTypes())); break;\n                        case SIZE: collection.size(); break;\n                        case TO_ARRAY: collection.toArray(); break;\n                        case TO_ARRAY_INPUT: collection.toArray(new Object[collection.size()]); break;\n                    }\n                    return false;\n                } catch (Throwable t) {\n                    if (!t.getClass().equals(expected)) {\n                        return false;\n                    }\n                }\n                return true;\n            }\n        });\n        Boolean result = future.get();\n        realm.cancelTransaction();\n        return result;\n    }\n\n}\n\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/ManagedRealmListForValueTests.java",
    "content": "/*\n * Copyright 2017 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\npackage io.realm;\n\nimport org.junit.After;\nimport org.junit.Before;\nimport org.junit.Rule;\nimport org.junit.Test;\nimport org.junit.rules.ExpectedException;\nimport org.junit.runner.RunWith;\nimport org.junit.runners.Parameterized;\n\nimport java.nio.charset.Charset;\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.Collection;\nimport java.util.Collections;\nimport java.util.Date;\nimport java.util.List;\nimport java.util.concurrent.atomic.AtomicInteger;\n\nimport javax.annotation.Nullable;\n\nimport io.realm.entities.NullTypes;\nimport io.realm.internal.Table;\nimport io.realm.rule.RunInLooperThread;\nimport io.realm.rule.RunTestInLooperThread;\n\nimport static io.realm.ManagedRealmListForValueTests.ListType.BINARY_LIST;\nimport static io.realm.ManagedRealmListForValueTests.ListType.BOOLEAN_LIST;\nimport static io.realm.ManagedRealmListForValueTests.ListType.BYTE_LIST;\nimport static io.realm.ManagedRealmListForValueTests.ListType.DATE_LIST;\nimport static io.realm.ManagedRealmListForValueTests.ListType.DOUBLE_LIST;\nimport static io.realm.ManagedRealmListForValueTests.ListType.FLOAT_LIST;\nimport static io.realm.ManagedRealmListForValueTests.ListType.INTEGER_LIST;\nimport static io.realm.ManagedRealmListForValueTests.ListType.LONG_LIST;\nimport static io.realm.ManagedRealmListForValueTests.ListType.SHORT_LIST;\nimport static io.realm.ManagedRealmListForValueTests.ListType.STRING_LIST;\nimport static org.hamcrest.CoreMatchers.is;\nimport static org.junit.Assert.assertArrayEquals;\nimport static org.junit.Assert.assertEquals;\nimport static org.junit.Assert.assertFalse;\nimport static org.junit.Assert.assertNotNull;\nimport static org.junit.Assert.assertNull;\nimport static org.junit.Assert.assertTrue;\nimport static org.junit.Assert.fail;\n\n/**\n * Unit tests specific for RealmList with value elements.\n */\n@RunWith(Parameterized.class)\npublic class ManagedRealmListForValueTests extends CollectionTests {\n\n    static final int NON_NULL_TEST_SIZE = 10;\n    static final int NULLABLE_TEST_SIZE = NON_NULL_TEST_SIZE * 2;\n\n    enum ListType {\n        STRING_LIST(String.class.getName()),\n        BOOLEAN_LIST(Boolean.class.getName()),\n        BINARY_LIST(byte[].class.getSimpleName()/* using simple name since array class is a bit special */),\n        LONG_LIST(Long.class.getName()),\n        INTEGER_LIST(Integer.class.getName()),\n        SHORT_LIST(Short.class.getName()),\n        BYTE_LIST(Byte.class.getName()),\n        DOUBLE_LIST(Double.class.getName()),\n        FLOAT_LIST(Float.class.getName()),\n        DATE_LIST(Date.class.getName());\n\n        private final String valueTypeName;\n\n        ListType(String valueTypeName) {\n            this.valueTypeName = valueTypeName;\n        }\n\n        public String getValueTypeName() {\n            return valueTypeName;\n        }\n    }\n\n    @Parameterized.Parameters(name = \"{index}: Type: {0}, Nullable?: {1}\")\n    public static Collection<Object[]> parameters() {\n        final List<Object[]> paramsList = new ArrayList<>();\n        for (ListType listType : ListType.values()) {\n            paramsList.add(new Object[] {listType, Boolean.TRUE});\n            paramsList.add(new Object[] {listType, Boolean.FALSE});\n        }\n        return paramsList;\n    }\n\n    @Rule\n    public final TestRealmConfigurationFactory configFactory = new TestRealmConfigurationFactory();\n    @Rule\n    public ExpectedException thrown = ExpectedException.none();\n    @Rule\n    public final RunInLooperThread looperThread = new RunInLooperThread();\n\n    @Parameterized.Parameter\n    public ListType listType;\n\n    @Parameterized.Parameter(1)\n    public Boolean isTypeNullable;\n\n    private Realm realm;\n    private NullTypes object;\n    private RealmList list;\n\n    @SuppressWarnings(\"unchecked\")\n    @Before\n    public void setUp() throws Exception {\n        final RealmConfiguration.Builder configurationBuilder = configFactory.createConfigurationBuilder();\n        configurationBuilder.schema(NullTypes.class);\n        RealmConfiguration realmConfig = configurationBuilder.build();\n\n        realm = Realm.getInstance(realmConfig);\n\n        realm.beginTransaction();\n        object = realm.createObject(NullTypes.class, 0);\n        for (ListType type : ListType.values()) {\n            for (int i = 0; i < NON_NULL_TEST_SIZE; i++) {\n                switch (type) {\n                    case STRING_LIST: {\n                        final RealmList nonnull = object.getFieldStringListNotNull();\n                        nonnull.add(generateValue(STRING_LIST, i));\n                        final RealmList nullable = object.getFieldStringListNull();\n                        nullable.add(\"\" + i);\n                        nullable.add(null);\n                    }\n                    break;\n                    case BOOLEAN_LIST: {\n                        final RealmList nonnull = object.getFieldBooleanListNotNull();\n                        nonnull.add(generateValue(BOOLEAN_LIST, i));\n                        final RealmList nullable = object.getFieldBooleanListNull();\n                        nullable.add(nonnull.last());\n                        nullable.add(null);\n                    }\n                    break;\n                    case BINARY_LIST: {\n                        final RealmList nonnull = object.getFieldBinaryListNotNull();\n                        nonnull.add(generateValue(BINARY_LIST, i));\n                        final RealmList nullable = object.getFieldBinaryListNull();\n                        nullable.add(nonnull.last());\n                        nullable.add(null);\n                    }\n                    break;\n                    case LONG_LIST: {\n                        final RealmList nonnull = object.getFieldLongListNotNull();\n                        nonnull.add(generateValue(LONG_LIST, i));\n                        final RealmList nullable = object.getFieldLongListNull();\n                        nullable.add(nonnull.last());\n                        nullable.add(null);\n                    }\n                    break;\n                    case INTEGER_LIST: {\n                        final RealmList nonnull = object.getFieldIntegerListNotNull();\n                        nonnull.add(generateValue(INTEGER_LIST, i));\n                        final RealmList nullable = object.getFieldIntegerListNull();\n                        nullable.add(nonnull.last());\n                        nullable.add(null);\n                    }\n                    break;\n                    case SHORT_LIST: {\n                        final RealmList nonnull = object.getFieldShortListNotNull();\n                        nonnull.add(generateValue(SHORT_LIST, i));\n                        final RealmList nullable = object.getFieldShortListNull();\n                        nullable.add(nonnull.last());\n                        nullable.add(null);\n                    }\n                    break;\n                    case BYTE_LIST: {\n                        final RealmList nonnull = object.getFieldByteListNotNull();\n                        nonnull.add(generateValue(BYTE_LIST, i));\n                        final RealmList nullable = object.getFieldByteListNull();\n                        nullable.add(nonnull.last());\n                        nullable.add(null);\n                    }\n                    break;\n                    case DOUBLE_LIST: {\n                        final RealmList nonnull = object.getFieldDoubleListNotNull();\n                        nonnull.add(generateValue(DOUBLE_LIST, i));\n                        final RealmList nullable = object.getFieldDoubleListNull();\n                        nullable.add(nonnull.last());\n                        nullable.add(null);\n                    }\n                    break;\n                    case FLOAT_LIST: {\n                        final RealmList nonnull = object.getFieldFloatListNotNull();\n                        nonnull.add(generateValue(FLOAT_LIST, i));\n                        final RealmList nullable = object.getFieldFloatListNull();\n                        nullable.add(nonnull.last());\n                        nullable.add(null);\n                    }\n                    break;\n                    case DATE_LIST: {\n                        final RealmList nonnull = object.getFieldDateListNotNull();\n                        nonnull.add(generateValue(DATE_LIST, i));\n                        final RealmList nullable = object.getFieldDateListNull();\n                        nullable.add(nonnull.last());\n                        nullable.add(null);\n                    }\n                    break;\n                    default:\n                        throw new AssertionError(\"unexpected value type: \" + listType.name());\n                }\n            }\n        }\n        realm.commitTransaction();\n\n        list = getListFor(object, listType, isTypeNullable);\n    }\n\n    static RealmList<?> getListFor(NullTypes object, ListType listType, boolean nullable) {\n        switch (listType) {\n            case STRING_LIST:\n                return nullable ? object.getFieldStringListNull() : object.getFieldStringListNotNull();\n            case BOOLEAN_LIST:\n                return nullable ? object.getFieldBooleanListNull() : object.getFieldBooleanListNotNull();\n            case BINARY_LIST:\n                return nullable ? object.getFieldBinaryListNull() : object.getFieldBinaryListNotNull();\n            case LONG_LIST:\n                return nullable ? object.getFieldLongListNull() : object.getFieldLongListNotNull();\n            case INTEGER_LIST:\n                return nullable ? object.getFieldIntegerListNull() : object.getFieldIntegerListNotNull();\n            case SHORT_LIST:\n                return nullable ? object.getFieldShortListNull() : object.getFieldShortListNotNull();\n            case BYTE_LIST:\n                return nullable ? object.getFieldByteListNull() : object.getFieldByteListNotNull();\n            case DOUBLE_LIST:\n                return nullable ? object.getFieldDoubleListNull() : object.getFieldDoubleListNotNull();\n            case FLOAT_LIST:\n                return nullable ? object.getFieldFloatListNull() : object.getFieldFloatListNotNull();\n            case DATE_LIST:\n                return nullable ? object.getFieldDateListNull() : object.getFieldDateListNotNull();\n            default:\n                throw new AssertionError(\"unexpected value type: \" + listType.name());\n        }\n    }\n\n    @After\n    public void tearDown() throws Exception {\n        if (realm != null) {\n            realm.close();\n        }\n    }\n\n    static Object generateValue(ListType listType, int i) {\n        switch (listType) {\n            case STRING_LIST:\n                return \"\" + i;\n            case BOOLEAN_LIST:\n                return i % 2 == 0 ? Boolean.FALSE : Boolean.TRUE;\n            case BINARY_LIST:\n                return new byte[] {(byte) i};\n            case LONG_LIST:\n                return (long) i;\n            case INTEGER_LIST:\n                return i;\n            case SHORT_LIST:\n                return (short) i;\n            case BYTE_LIST:\n                return (byte) i;\n            case DOUBLE_LIST:\n                return (double) i;\n            case FLOAT_LIST:\n                return (float) i;\n            case DATE_LIST:\n                return new Date(i);\n            default:\n                throw new AssertionError(\"unexpected value type: \" + listType.name());\n        }\n    }\n\n    private static Object generateHugeValue(ListType listType, int size) {\n        final byte[] bytes = new byte[size];\n        switch (listType) {\n            case STRING_LIST:\n                Arrays.fill(bytes, (byte) 'a');\n                return new String(bytes, Charset.forName(\"US-ASCII\"));\n            case BINARY_LIST:\n                return bytes;\n            default:\n                throw new AssertionError(\"'generateHugeValue' does not support this type: \" + listType.name());\n        }\n    }\n\n    private void assertValueEquals(@Nullable Object expected, @Nullable Object actual) {\n        assertValueEquals(null, expected, actual);\n    }\n\n    private void assertValueEquals(@SuppressWarnings(\"SameParameterValue\") @Nullable String message, @Nullable Object expected, @Nullable Object actual) {\n        if (listType == BINARY_LIST) {\n            assertArrayEquals(message, (byte[]) expected, (byte[]) actual);\n        } else {\n            assertEquals(message, expected, actual);\n        }\n    }\n\n    @Test\n    public void readValues() {\n        for (int i = 0; i < NON_NULL_TEST_SIZE; i++) {\n            switch (listType) {\n                case STRING_LIST: {\n                    assertEquals(generateValue(STRING_LIST, i), list.get(isTypeNullable ? (i * 2) : i));\n                }\n                break;\n                case BOOLEAN_LIST: {\n                    assertEquals(generateValue(BOOLEAN_LIST, i), list.get(isTypeNullable ? (i * 2) : i));\n                }\n                break;\n                case BINARY_LIST: {\n                    assertArrayEquals((byte[]) generateValue(BINARY_LIST, i), (byte[]) list.get(isTypeNullable ? (i * 2) : i));\n                }\n                break;\n                case LONG_LIST: {\n                    //noinspection UnnecessaryBoxing\n                    assertEquals(generateValue(LONG_LIST, i), list.get(isTypeNullable ? (i * 2) : i));\n                }\n                break;\n                case INTEGER_LIST: {\n                    //noinspection UnnecessaryBoxing\n                    assertEquals(generateValue(INTEGER_LIST, i), list.get(isTypeNullable ? (i * 2) : i));\n                }\n                break;\n                case SHORT_LIST: {\n                    //noinspection UnnecessaryBoxing\n                    assertEquals(generateValue(SHORT_LIST, i), list.get(isTypeNullable ? (i * 2) : i));\n                }\n                break;\n                case BYTE_LIST: {\n                    //noinspection UnnecessaryBoxing\n                    assertEquals(generateValue(BYTE_LIST, i), list.get(isTypeNullable ? (i * 2) : i));\n                }\n                break;\n                case DOUBLE_LIST: {\n                    //noinspection UnnecessaryBoxing\n                    assertEquals(generateValue(DOUBLE_LIST, i), list.get(isTypeNullable ? (i * 2) : i));\n                }\n                break;\n                case FLOAT_LIST: {\n                    //noinspection UnnecessaryBoxing\n                    assertEquals(generateValue(FLOAT_LIST, i), list.get(isTypeNullable ? (i * 2) : i));\n                }\n                break;\n                case DATE_LIST: {\n                    assertEquals(generateValue(DATE_LIST, i), list.get(isTypeNullable ? (i * 2) : i));\n                }\n                break;\n                default:\n                    throw new AssertionError(\"unexpected value type: \" + listType.name());\n            }\n            if (isTypeNullable) {\n                assertNull(list.get(i * 2 + 1));\n            }\n        }\n    }\n\n    @Test\n    public void isValid() {\n        assertTrue(list.isValid());\n\n        realm.close();\n\n        assertFalse(list.isValid());\n    }\n\n    @Test\n    public void isValid_whenParentRemoved() {\n        realm.beginTransaction();\n        object.deleteFromRealm();\n        realm.commitTransaction();\n\n        // RealmList contained in removed object is invalid.\n        assertFalse(list.isValid());\n    }\n\n    @Test\n    public void add_exceedingSizeLimitValueThrows() {\n        if (listType != STRING_LIST && listType != BINARY_LIST) {\n            return;\n        }\n\n        final int sizeLimit;\n        switch (listType) {\n            case STRING_LIST:\n                sizeLimit = Table.MAX_STRING_SIZE;\n                break;\n            case BINARY_LIST:\n                sizeLimit = Table.MAX_BINARY_SIZE;\n                break;\n            default:\n                throw new AssertionError(\"Unexpected list type: \" + listType.name());\n        }\n\n        realm.executeTransaction(new Realm.Transaction() {\n            @Override\n            public void execute(Realm realm) {\n                //noinspection unchecked\n                list.add(generateHugeValue(listType, sizeLimit));\n            }\n        });\n\n        realm.executeTransaction(new Realm.Transaction() {\n            @Override\n            public void execute(Realm realm) {\n                final long sizeBeforeException = list.size();\n                thrown.expect(IllegalArgumentException.class);\n                try {\n                    //noinspection unchecked\n                    list.add(generateHugeValue(listType, sizeLimit + 1));\n                } finally {\n                    // FIXME This assertion fails now. Code will be fixed in master branch first.\n                    assertEquals(sizeBeforeException, list.size());\n                }\n            }\n        });\n    }\n\n    @Test\n    public void move_outOfBoundsLowerThrows() {\n        realm.beginTransaction();\n        try {\n            list.move(0, -1);\n            fail(\"Indexes < 0 should throw an exception\");\n        } catch (IndexOutOfBoundsException ignored) {\n        } finally {\n            realm.cancelTransaction();\n        }\n    }\n\n    @Test\n    public void move_outOfBoundsHigherThrows() {\n        realm.beginTransaction();\n        try {\n            list.move(list.size() - 1, list.size());\n            fail(\"Indexes >= size() should throw an exception\");\n        } catch (IndexOutOfBoundsException ignored) {\n            ignored.printStackTrace();\n        } finally {\n            realm.cancelTransaction();\n        }\n    }\n\n    @Test\n    public void clear_then_add() {\n        realm.beginTransaction();\n        list.clear();\n\n        assertTrue(list.isEmpty());\n\n        //noinspection unchecked\n        list.add(generateValue(listType, -100));\n\n        realm.commitTransaction();\n\n        assertEquals(1, list.size());\n    }\n\n    @Test\n    public void size() {\n        assertEquals(isTypeNullable ? NULLABLE_TEST_SIZE : NON_NULL_TEST_SIZE, list.size());\n    }\n\n    @Test\n    public void remove_nonNullByIndex() {\n        final int targetIndex = 6;\n\n        realm.executeTransaction(new Realm.Transaction() {\n            @Override\n            public void execute(Realm realm) {\n                final Object removed = list.remove(targetIndex);\n                final int dataIndex = isTypeNullable ? targetIndex / 2 : targetIndex;\n                assertValueEquals(generateValue(listType, dataIndex), removed);\n            }\n        });\n\n        assertEquals(isTypeNullable ? (NULLABLE_TEST_SIZE - 1) : (NON_NULL_TEST_SIZE - 1), list.size());\n        for (int i = 0; i < list.size(); i++) {\n            final int originalIndex = i < targetIndex ? i : i + 1;\n            if (isTypeNullable) {\n                if (originalIndex % 2 == 1) {\n                    assertNull(list.get(i));\n                } else {\n                    assertValueEquals(generateValue(listType, originalIndex / 2), list.get(i));\n                }\n            } else {\n                assertValueEquals(generateValue(listType, originalIndex), list.get(i));\n            }\n        }\n    }\n\n    @Test\n    public void remove_nullByIndex() {\n        if (!isTypeNullable) {\n            return;\n        }\n\n        final int targetIndex = 7;\n        realm.executeTransaction(new Realm.Transaction() {\n            @Override\n            public void execute(Realm realm) {\n                assertNull(list.remove(targetIndex));\n                assertEquals(NULLABLE_TEST_SIZE - 1, list.size());\n            }\n        });\n\n        for (int i = 0; i < list.size(); i++) {\n            final int originalIndex = i < targetIndex ? i : i + 1;\n            if (originalIndex % 2 == 1) {\n                assertNull(list.get(i));\n            } else {\n                assertValueEquals(generateValue(listType, originalIndex / 2), list.get(i));\n            }\n        }\n    }\n\n    @Test\n    public void remove_first() {\n        realm.executeTransaction(new Realm.Transaction() {\n            @Override\n            public void execute(Realm realm) {\n                final Object removed = list.remove(0);\n                assertValueEquals(generateValue(listType, 0), removed);\n            }\n        });\n\n        assertEquals((isTypeNullable ? NULLABLE_TEST_SIZE : NON_NULL_TEST_SIZE) - 1, list.size());\n    }\n\n    @Test\n    public void remove_last() {\n        realm.executeTransaction(new Realm.Transaction() {\n            @Override\n            public void execute(Realm realm) {\n                final Object removed = list.remove((isTypeNullable ? NULLABLE_TEST_SIZE : NON_NULL_TEST_SIZE) - 1);\n                if (isTypeNullable) {\n                    assertNull(removed);\n                } else {\n                    assertValueEquals(generateValue(listType, NON_NULL_TEST_SIZE - 1), removed);\n                }\n            }\n        });\n\n        assertEquals((isTypeNullable ? NULLABLE_TEST_SIZE : NON_NULL_TEST_SIZE) - 1, list.size());\n    }\n\n    @Test\n    public void remove_fromEmptyListThrows() {\n        realm.executeTransaction(new Realm.Transaction() {\n            @Override\n            public void execute(Realm realm) {\n                list.clear();\n                thrown.expect(IndexOutOfBoundsException.class);\n                list.remove(0);\n            }\n        });\n    }\n\n    @Test\n    public void remove_byObject() {\n        final Object value = list.get(0);\n        final int initialSize = list.size();\n\n        realm.executeTransaction(new Realm.Transaction() {\n            @Override\n            public void execute(Realm realm) {\n                if (listType == BINARY_LIST) {\n                    assertFalse(list.remove(value));  // since 'equals()' never return true against binary array.\n                } else {\n                    assertTrue(list.remove(value));\n                }\n            }\n        });\n\n        assertEquals((listType == BINARY_LIST) ? initialSize : (initialSize - 1), list.size());\n    }\n\n    @Test\n    public void remove_byNull() {\n        final int initialSize = list.size();\n\n        realm.executeTransaction(new Realm.Transaction() {\n            @Override\n            public void execute(Realm realm) {\n                if (isTypeNullable) {\n                    assertTrue(list.remove(null));\n                } else {\n                    assertFalse(list.remove(null));\n                }\n            }\n        });\n\n        assertEquals(isTypeNullable ? (initialSize - 1) : initialSize, list.size());\n    }\n\n    @Test\n    public void deleteFirst() {\n        realm.executeTransaction(new Realm.Transaction() {\n            @Override\n            public void execute(Realm realm) {\n                assertTrue(list.deleteFirstFromRealm());\n            }\n        });\n\n        assertEquals(isTypeNullable ? (NULLABLE_TEST_SIZE - 1) : (NON_NULL_TEST_SIZE - 1), list.size());\n        for (int i = 0; i < list.size(); i++) {\n            final int originalIndex = i + 1;\n            if (isTypeNullable) {\n                if (originalIndex % 2 == 1) {\n                    assertNull(list.get(i));\n                } else {\n                    assertValueEquals(generateValue(listType, originalIndex / 2), list.get(i));\n                }\n            } else {\n                assertValueEquals(generateValue(listType, originalIndex), list.get(i));\n            }\n        }\n    }\n\n    @Test\n    public void deleteLast() {\n        realm.executeTransaction(new Realm.Transaction() {\n            @Override\n            public void execute(Realm realm) {\n                assertTrue(list.deleteLastFromRealm());\n            }\n        });\n\n        assertEquals(isTypeNullable ? (NULLABLE_TEST_SIZE - 1) : (NON_NULL_TEST_SIZE - 1), list.size());\n        for (int i = 0; i < list.size(); i++) {\n            if (isTypeNullable) {\n                if (i % 2 == 1) {\n                    assertNull(list.get(i));\n                } else {\n                    assertValueEquals(generateValue(listType, i / 2), list.get(i));\n                }\n            } else {\n                assertValueEquals(generateValue(listType, i), list.get(i));\n            }\n        }\n    }\n\n    @Test\n    public void addAt_afterContainerObjectRemoved() {\n        realm.executeTransaction(new Realm.Transaction() {\n            @Override\n            public void execute(Realm realm) {\n                object.deleteFromRealm();\n            }\n        });\n\n        thrown.expect(IllegalStateException.class);\n        //noinspection unchecked\n        list.add(generateValue(listType, 100));\n    }\n\n    @Test\n    public void addAt_invalidIndex() {\n        final int initialSize = list.size();\n        try {\n            realm.beginTransaction();\n            //noinspection unchecked\n            list.add(initialSize + 1, generateValue(listType, 1000));\n            fail();\n        } catch (IndexOutOfBoundsException e) {\n            // make sure that the size is not changed\n            assertEquals(initialSize, list.size());\n        }\n    }\n\n    @Test\n    public void set_afterContainerObjectRemoved() {\n        realm.executeTransaction(new Realm.Transaction() {\n            @Override\n            public void execute(Realm realm) {\n                object.deleteFromRealm();\n            }\n        });\n\n        thrown.expect(IllegalStateException.class);\n        //noinspection unchecked\n        list.set(0, generateValue(listType, 100));\n    }\n\n    @Test\n    public void set_invalidIndex() {\n        final int initialSize = list.size();\n        try {\n            realm.beginTransaction();\n            //noinspection unchecked\n            list.set(initialSize, generateValue(listType, 1000));\n            fail();\n        } catch (IndexOutOfBoundsException e) {\n            // make sure that the size is not changed\n            assertEquals(initialSize, list.size());\n        }\n    }\n\n    @Test\n    public void move_afterContainerObjectRemoved() {\n        realm.executeTransaction(new Realm.Transaction() {\n            @Override\n            public void execute(Realm realm) {\n                object.deleteFromRealm();\n            }\n        });\n\n        thrown.expect(IllegalStateException.class);\n        list.move(0, 1);\n    }\n\n    @Test\n    public void clear_afterContainerObjectRemoved() {\n        realm.executeTransaction(new Realm.Transaction() {\n            @Override\n            public void execute(Realm realm) {\n                object.deleteFromRealm();\n            }\n        });\n\n        thrown.expect(IllegalStateException.class);\n        list.clear();\n    }\n\n    @Test\n    public void remove_atAfterContainerObjectRemoved() {\n        realm.executeTransaction(new Realm.Transaction() {\n            @Override\n            public void execute(Realm realm) {\n                object.deleteFromRealm();\n            }\n        });\n\n        thrown.expect(IllegalStateException.class);\n        list.remove(0);\n    }\n\n    @Test\n    public void remove_objectAfterContainerObjectRemoved() {\n        realm.executeTransaction(new Realm.Transaction() {\n            @Override\n            public void execute(Realm realm) {\n                object.deleteFromRealm();\n            }\n        });\n\n        thrown.expect(IllegalStateException.class);\n        list.remove(generateValue(listType, 4));\n    }\n\n    @Test\n    public void remove_unsupportedTypeIgnored() {\n        final int initialSize = list.size();\n\n        final List<Object> unsupportedValues = Arrays.<Object>asList(\n                new int[] {0},\n                new StringBuilder(\"0\")\n        );\n        realm.executeTransaction(new Realm.Transaction() {\n            @Override\n            public void execute(Realm realm) {\n                for (Object unsupportedValue : unsupportedValues) {\n                    //noinspection UseBulkOperation\n                    assertFalse(list.remove(unsupportedValue));\n                }\n            }\n        });\n\n        assertEquals(initialSize, list.size());\n    }\n\n    @Test\n    public void removeAll() {\n        final List<Object> toBeRemoved = Arrays.asList(\n                null,\n                generateValue(listType, 2),\n                generateValue(listType, 4));\n        realm.executeTransaction(new Realm.Transaction() {\n            @Override\n            public void execute(Realm realm) {\n                if (!isTypeNullable && listType == BINARY_LIST) {\n                    //noinspection unchecked\n                    assertFalse(list.removeAll(toBeRemoved)); // since 'equals()' never return true against binary array.\n                } else {\n                    //noinspection unchecked\n                    assertTrue(list.removeAll(toBeRemoved));\n                }\n            }\n        });\n\n        switch (listType) {\n            case BINARY_LIST:\n                assertEquals(NON_NULL_TEST_SIZE, list.size());\n                break;\n            case BOOLEAN_LIST:\n                assertEquals(NON_NULL_TEST_SIZE / 2, list.size());\n                break;\n            default:\n                assertEquals(NON_NULL_TEST_SIZE - 2, list.size());\n                break;\n        }\n    }\n\n    @Test\n    public void removeAll_unsupportedTypeIgnored() {\n        final int initialSize = list.size();\n\n        final List<Object> unsupportedValues = Arrays.<Object>asList(\n                new int[] {0},\n                new StringBuilder(\"0\")\n        );\n        realm.executeTransaction(new Realm.Transaction() {\n            @Override\n            public void execute(Realm realm) {\n                //noinspection unchecked\n                assertFalse(list.removeAll(unsupportedValues));\n            }\n        });\n\n        assertEquals(initialSize, list.size());\n    }\n\n    @Test\n    public void removeAll_afterContainerObjectRemoved() {\n        realm.executeTransaction(new Realm.Transaction() {\n            @Override\n            public void execute(Realm realm) {\n                object.deleteFromRealm();\n            }\n        });\n\n        thrown.expect(IllegalStateException.class);\n        //noinspection unchecked\n        list.removeAll(Collections.emptyList());\n    }\n\n    @Test\n    public void get_afterContainerObjectRemoved() {\n        realm.executeTransaction(new Realm.Transaction() {\n            @Override\n            public void execute(Realm realm) {\n                object.deleteFromRealm();\n            }\n        });\n\n        thrown.expect(IllegalStateException.class);\n        list.get(0);\n    }\n\n    @Test\n    public void first_afterContainerObjectRemoved() {\n        realm.executeTransaction(new Realm.Transaction() {\n            @Override\n            public void execute(Realm realm) {\n                object.deleteFromRealm();\n            }\n        });\n\n        thrown.expect(IllegalStateException.class);\n        list.first();\n    }\n\n    @Test\n    public void last_afterContainerObjectRemoved() {\n        realm.executeTransaction(new Realm.Transaction() {\n            @Override\n            public void execute(Realm realm) {\n                object.deleteFromRealm();\n            }\n        });\n\n        thrown.expect(IllegalStateException.class);\n        list.last();\n    }\n\n    @Test\n    public void size_afterContainerObjectRemoved() {\n        realm.executeTransaction(new Realm.Transaction() {\n            @Override\n            public void execute(Realm realm) {\n                object.deleteFromRealm();\n            }\n        });\n\n        thrown.expect(IllegalStateException.class);\n        list.size();\n    }\n\n    @Test(expected = UnsupportedOperationException.class)\n    public void where() {\n        list.where();\n    }\n\n    @Test\n    public void toString_() {\n        final StringBuilder sb = new StringBuilder(\"RealmList<\").append(listType.getValueTypeName()).append(\">@[\");\n        final String separator = \",\";\n        for (int i = 0; i < NON_NULL_TEST_SIZE; i++) {\n            final Object value = generateValue(listType, i);\n\n            if (value instanceof byte[]) {\n                sb.append(\"byte[\").append(((byte[]) value).length).append(\"]\");\n            } else {\n                sb.append(value);\n            }\n            sb.append(separator);\n            if (isTypeNullable) {\n                sb.append(\"null\").append(separator);\n            }\n        }\n        sb.setLength(sb.length() - separator.length());\n        sb.append(\"]\");\n\n        assertEquals(sb.toString(), list.toString());\n    }\n\n    @Test\n    public void toString_AfterContainerObjectRemoved() {\n        realm.executeTransaction(new Realm.Transaction() {\n            @Override\n            public void execute(Realm realm) {\n                object.deleteFromRealm();\n            }\n        });\n        assertEquals(\"RealmList<\" + listType.getValueTypeName() + \">@[invalid]\", list.toString());\n    }\n\n    @Test\n    public void deleteAllFromRealm() {\n        realm.executeTransaction(new Realm.Transaction() {\n            @Override\n            public void execute(Realm realm) {\n                list.deleteAllFromRealm();\n            }\n        });\n\n        assertEquals(0, list.size());\n    }\n\n    @Test\n    public void deleteAllFromRealm_outsideTransaction() {\n        try {\n            list.deleteAllFromRealm();\n            fail();\n        } catch (IllegalStateException e) {\n            assertTrue(e.getMessage().contains(\"Cannot modify managed List outside of a write transaction.\"));\n        }\n    }\n\n    @Test\n    public void deleteAllFromRealm_emptyList() {\n        realm.executeTransaction(new Realm.Transaction() {\n            @Override\n            public void execute(Realm realm) {\n                list.deleteAllFromRealm();\n            }\n        });\n        assertEquals(0, list.size());\n\n        // The dogs is empty now.\n        realm.executeTransaction(new Realm.Transaction() {\n            @Override\n            public void execute(Realm realm) {\n                list.deleteAllFromRealm();\n            }\n        });\n        assertEquals(0, list.size());\n    }\n\n    @Test\n    public void deleteAllFromRealm_invalidListShouldThrow() {\n        realm.close();\n        realm = null;\n\n        thrown.expect(IllegalStateException.class);\n        thrown.expectMessage(is(\"This Realm instance has already been closed, making it unusable.\"));\n        list.deleteAllFromRealm();\n    }\n\n    @Test\n    public void add_null_nonNullableListThrows() {\n        if (isTypeNullable) {\n            return;\n        }\n\n        realm.beginTransaction();\n        final int initialSize = list.size();\n        try {\n            thrown.expect(IllegalArgumentException.class);\n            //noinspection unchecked\n            list.add(null);\n        } finally {\n            assertEquals(initialSize, list.size());\n        }\n    }\n\n    @Test\n    public void addAt_null_nonNullableListThrows() {\n        if (isTypeNullable) {\n            return;\n        }\n\n        realm.beginTransaction();\n        final int initialSize = list.size();\n        try {\n            thrown.expect(IllegalArgumentException.class);\n            //noinspection unchecked\n            list.add(1, null);\n        } finally {\n            assertEquals(initialSize, list.size());\n        }\n    }\n\n    @Test\n    public void set_null_nonNullableListThrows() {\n        if (isTypeNullable) {\n            return;\n        }\n\n        realm.beginTransaction();\n        final int initialSize = list.size();\n        try {\n            thrown.expect(IllegalArgumentException.class);\n            //noinspection unchecked\n            list.set(0, null);\n        } finally {\n            assertEquals(initialSize, list.size());\n        }\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void changeListener_forAddObject() {\n        Realm realm = looperThread.getRealm();\n        realm.executeTransaction(new Realm.Transaction() {\n            @Override\n            public void execute(Realm realm) {\n                object = realm.createObject(NullTypes.class, 1000);\n                list = getListFor(object, listType, isTypeNullable);\n\n                // add 3 elements as an initial data\n                //noinspection unchecked\n                list.add(generateValue(listType, 0));\n                //noinspection unchecked\n                list.add(generateValue(listType, 100));\n                //noinspection unchecked\n                list.add(generateValue(listType, 200));\n            }\n        });\n\n        final AtomicInteger listenerCalledCount = new AtomicInteger(0);\n        //noinspection unchecked\n        list.addChangeListener(new RealmChangeListener<RealmList<Object>>() {\n            @Override\n            public void onChange(RealmList<Object> element) {\n                assertEquals(0, listenerCalledCount.getAndIncrement());\n            }\n        });\n        //noinspection unchecked\n        list.addChangeListener(new OrderedRealmCollectionChangeListener<RealmList<Object>>() {\n            @Override\n            public void onChange(RealmList<Object> collection, @Nullable OrderedCollectionChangeSet changes) {\n                assertNotNull(changes);\n                assertEquals(1, changes.getInsertions().length);\n                assertEquals(0, changes.getDeletions().length);\n                assertEquals(0, changes.getChanges().length);\n                assertEquals(3, changes.getInsertions()[0]);\n                assertEquals(1, listenerCalledCount.getAndIncrement());\n            }\n        });\n\n        realm.beginTransaction();\n        //noinspection unchecked\n        list.add(generateValue(listType, 100));\n        realm.commitTransaction();\n\n        assertEquals(2, listenerCalledCount.get());\n        looperThread.testComplete();\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void changeListener_forAddAt() {\n        Realm realm = looperThread.getRealm();\n        realm.executeTransaction(new Realm.Transaction() {\n            @Override\n            public void execute(Realm realm) {\n                object = realm.createObject(NullTypes.class, 1000);\n                list = getListFor(object, listType, isTypeNullable);\n\n                // add 3 elements as an initial data\n                //noinspection unchecked\n                list.add(generateValue(listType, 0));\n                //noinspection unchecked\n                list.add(generateValue(listType, 100));\n                //noinspection unchecked\n                list.add(generateValue(listType, 200));\n            }\n        });\n\n        final AtomicInteger listenerCalledCount = new AtomicInteger(0);\n        //noinspection unchecked\n        list.addChangeListener(new RealmChangeListener<RealmList<Object>>() {\n            @Override\n            public void onChange(RealmList<Object> element) {\n                assertEquals(0, listenerCalledCount.getAndIncrement());\n            }\n        });\n        //noinspection unchecked\n        list.addChangeListener(new OrderedRealmCollectionChangeListener<RealmList<Object>>() {\n            @Override\n            public void onChange(RealmList<Object> collection, @Nullable OrderedCollectionChangeSet changes) {\n                assertNotNull(changes);\n                assertEquals(1, changes.getInsertions().length);\n                assertEquals(0, changes.getDeletions().length);\n                assertEquals(0, changes.getChanges().length);\n                assertEquals(1, changes.getInsertions()[0]);\n                assertEquals(1, listenerCalledCount.getAndIncrement());\n            }\n        });\n\n        realm.beginTransaction();\n        //noinspection unchecked\n        list.add(1, generateValue(listType, 500));\n        realm.commitTransaction();\n\n        assertEquals(2, listenerCalledCount.get());\n        looperThread.testComplete();\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void changeListener_forSet() {\n        Realm realm = looperThread.getRealm();\n        realm.executeTransaction(new Realm.Transaction() {\n            @Override\n            public void execute(Realm realm) {\n                object = realm.createObject(NullTypes.class, 1000);\n                list = getListFor(object, listType, isTypeNullable);\n\n                // add 3 elements as an initial data\n                //noinspection unchecked\n                list.add(generateValue(listType, 0));\n                //noinspection unchecked\n                list.add(generateValue(listType, 100));\n                //noinspection unchecked\n                list.add(generateValue(listType, 200));\n            }\n        });\n\n        final AtomicInteger listenerCalledCount = new AtomicInteger(0);\n        //noinspection unchecked\n        list.addChangeListener(new RealmChangeListener<RealmList<Object>>() {\n            @Override\n            public void onChange(RealmList<Object> element) {\n                assertEquals(0, listenerCalledCount.getAndIncrement());\n            }\n        });\n        //noinspection unchecked\n        list.addChangeListener(new OrderedRealmCollectionChangeListener<RealmList<Object>>() {\n            @Override\n            public void onChange(RealmList<Object> collection, @Nullable OrderedCollectionChangeSet changes) {\n                assertNotNull(changes);\n                assertEquals(0, changes.getInsertions().length);\n                assertEquals(0, changes.getDeletions().length);\n                assertEquals(1, changes.getChanges().length);\n                assertEquals(1, changes.getChanges()[0]);\n                assertEquals(1, listenerCalledCount.getAndIncrement());\n            }\n        });\n\n        realm.beginTransaction();\n        //noinspection unchecked\n        list.set(1, generateValue(listType, 500));\n        realm.commitTransaction();\n\n        assertEquals(2, listenerCalledCount.get());\n        looperThread.testComplete();\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void changeListener_forRemoveAt() {\n        Realm realm = looperThread.getRealm();\n        realm.executeTransaction(new Realm.Transaction() {\n            @Override\n            public void execute(Realm realm) {\n                object = realm.createObject(NullTypes.class, 1000);\n                list = getListFor(object, listType, isTypeNullable);\n\n                // add 3 elements as an initial data\n                //noinspection unchecked\n                list.add(generateValue(listType, 0));\n                //noinspection unchecked\n                list.add(generateValue(listType, 100));\n                //noinspection unchecked\n                list.add(generateValue(listType, 200));\n            }\n        });\n\n        final AtomicInteger listenerCalledCount = new AtomicInteger(0);\n        //noinspection unchecked\n        list.addChangeListener(new RealmChangeListener<RealmList<Object>>() {\n            @Override\n            public void onChange(RealmList<Object> element) {\n                assertEquals(0, listenerCalledCount.getAndIncrement());\n            }\n        });\n        //noinspection unchecked\n        list.addChangeListener(new OrderedRealmCollectionChangeListener<RealmList<Object>>() {\n            @Override\n            public void onChange(RealmList<Object> collection, @Nullable OrderedCollectionChangeSet changes) {\n                assertNotNull(changes);\n                assertEquals(0, changes.getInsertions().length);\n                assertEquals(1, changes.getDeletions().length);\n                assertEquals(0, changes.getChanges().length);\n                assertEquals(1, changes.getDeletions()[0]);\n                assertEquals(1, listenerCalledCount.getAndIncrement());\n            }\n        });\n\n        realm.beginTransaction();\n        //noinspection unchecked\n        if (listType == BINARY_LIST) {\n            assertArrayEquals((byte[]) generateValue(listType, 100), (byte[]) list.remove(1));\n        } else {\n            assertEquals(generateValue(listType, 100), list.remove(1));\n        }\n        realm.commitTransaction();\n\n        assertEquals(2, listenerCalledCount.get());\n        looperThread.testComplete();\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void changeListener_forRemoveObject() {\n        if (listType == BINARY_LIST) {\n            // 'removeAll()' never remove byte array element since 'equals()' never return true against byte array.\n            looperThread.testComplete();\n            return;\n        }\n\n        Realm realm = looperThread.getRealm();\n        realm.executeTransaction(new Realm.Transaction() {\n            @Override\n            public void execute(Realm realm) {\n                object = realm.createObject(NullTypes.class, 1000);\n                list = getListFor(object, listType, isTypeNullable);\n\n                // add 3 elements as an initial data\n                //noinspection unchecked\n                list.add(generateValue(listType, 0));\n                //noinspection unchecked\n                list.add(generateValue(listType, 101));\n                //noinspection unchecked\n                list.add(generateValue(listType, 200));\n            }\n        });\n\n        final AtomicInteger listenerCalledCount = new AtomicInteger(0);\n        //noinspection unchecked\n        list.addChangeListener(new RealmChangeListener<RealmList<Object>>() {\n            @Override\n            public void onChange(RealmList<Object> element) {\n                assertEquals(0, listenerCalledCount.getAndIncrement());\n            }\n        });\n        //noinspection unchecked\n        list.addChangeListener(new OrderedRealmCollectionChangeListener<RealmList<Object>>() {\n            @Override\n            public void onChange(RealmList<Object> collection, @Nullable OrderedCollectionChangeSet changes) {\n                assertNotNull(changes);\n                assertEquals(0, changes.getInsertions().length);\n                assertEquals(1, changes.getDeletions().length);\n                assertEquals(0, changes.getChanges().length);\n                assertEquals(1, changes.getDeletions()[0]);\n                assertEquals(1, listenerCalledCount.getAndIncrement());\n            }\n        });\n\n        realm.beginTransaction();\n        //noinspection unchecked\n        assertTrue(list.remove(generateValue(listType, 101)));\n        realm.commitTransaction();\n\n        assertEquals(2, listenerCalledCount.get());\n        looperThread.testComplete();\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void changeListener_forRemoveAll() {\n        if (listType == BINARY_LIST) {\n            // 'removeAll()' never remove byte array element since 'equals()' never return true against byte array.\n            looperThread.testComplete();\n            return;\n        }\n\n        Realm realm = looperThread.getRealm();\n        realm.executeTransaction(new Realm.Transaction() {\n            @Override\n            public void execute(Realm realm) {\n                object = realm.createObject(NullTypes.class, 1000);\n                list = getListFor(object, listType, isTypeNullable);\n\n                // add 3 elements as an initial data\n                //noinspection unchecked\n                list.add(generateValue(listType, 0));\n                //noinspection unchecked\n                list.add(generateValue(listType, 100));\n                //noinspection unchecked\n                list.add(generateValue(listType, 200));\n            }\n        });\n\n        final AtomicInteger listenerCalledCount = new AtomicInteger(0);\n        //noinspection unchecked\n        list.addChangeListener(new RealmChangeListener<RealmList<Object>>() {\n            @Override\n            public void onChange(RealmList<Object> element) {\n                assertEquals(0, listenerCalledCount.getAndIncrement());\n            }\n        });\n        //noinspection unchecked\n        list.addChangeListener(new OrderedRealmCollectionChangeListener<RealmList<Object>>() {\n            @Override\n            public void onChange(RealmList<Object> collection, @Nullable OrderedCollectionChangeSet changes) {\n                assertNotNull(changes);\n                assertEquals(0, changes.getInsertions().length);\n                assertEquals(listType == BOOLEAN_LIST ? 3 : 2, changes.getDeletions().length);\n                assertEquals(0, changes.getChanges().length);\n                assertEquals(1, changes.getDeletionRanges().length);\n                assertEquals(listType == BOOLEAN_LIST ? 0 : 1, changes.getDeletionRanges()[0].startIndex);\n                assertEquals(listType == BOOLEAN_LIST ? 3 : 2, changes.getDeletionRanges()[0].length);\n                assertEquals(1, listenerCalledCount.getAndIncrement());\n            }\n        });\n\n        realm.beginTransaction();\n        //noinspection unchecked\n\n        final boolean removed = list.removeAll(Arrays.asList(generateValue(listType, 100), generateValue(listType, 200), generateValue(listType, 300)));\n        assertTrue(removed);\n        realm.commitTransaction();\n\n        assertEquals(2, listenerCalledCount.get());\n        looperThread.testComplete();\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void changeListener_forDeleteAt() {\n        Realm realm = looperThread.getRealm();\n        realm.executeTransaction(new Realm.Transaction() {\n            @Override\n            public void execute(Realm realm) {\n                object = realm.createObject(NullTypes.class, 1000);\n                list = getListFor(object, listType, isTypeNullable);\n\n                // add 3 elements as an initial data\n                //noinspection unchecked\n                list.add(generateValue(listType, 0));\n                //noinspection unchecked\n                list.add(generateValue(listType, 100));\n                //noinspection unchecked\n                list.add(generateValue(listType, 200));\n            }\n        });\n\n        final AtomicInteger listenerCalledCount = new AtomicInteger(0);\n        //noinspection unchecked\n        list.addChangeListener(new RealmChangeListener<RealmList<Object>>() {\n            @Override\n            public void onChange(RealmList<Object> element) {\n                assertEquals(0, listenerCalledCount.getAndIncrement());\n            }\n        });\n        //noinspection unchecked\n        list.addChangeListener(new OrderedRealmCollectionChangeListener<RealmList<Object>>() {\n            @Override\n            public void onChange(RealmList<Object> collection, @Nullable OrderedCollectionChangeSet changes) {\n                assertNotNull(changes);\n                assertEquals(0, changes.getInsertions().length);\n                assertEquals(1, changes.getDeletions().length);\n                assertEquals(0, changes.getChanges().length);\n                assertEquals(1, changes.getDeletions()[0]);\n                assertEquals(1, listenerCalledCount.getAndIncrement());\n            }\n        });\n\n        realm.beginTransaction();\n        //noinspection unchecked\n        list.deleteFromRealm(1);\n        realm.commitTransaction();\n\n        assertEquals(2, listenerCalledCount.get());\n        looperThread.testComplete();\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void changeListener_forDeleteAll() {\n        Realm realm = looperThread.getRealm();\n        realm.executeTransaction(new Realm.Transaction() {\n            @Override\n            public void execute(Realm realm) {\n                object = realm.createObject(NullTypes.class, 1000);\n                list = getListFor(object, listType, isTypeNullable);\n\n                // add 3 elements as an initial data\n                //noinspection unchecked\n                list.add(generateValue(listType, 0));\n                //noinspection unchecked\n                list.add(generateValue(listType, 100));\n                //noinspection unchecked\n                list.add(generateValue(listType, 200));\n            }\n        });\n\n        final AtomicInteger listenerCalledCount = new AtomicInteger(0);\n        //noinspection unchecked\n        list.addChangeListener(new RealmChangeListener<RealmList<Object>>() {\n            @Override\n            public void onChange(RealmList<Object> element) {\n                assertEquals(0, listenerCalledCount.getAndIncrement());\n            }\n        });\n        //noinspection unchecked\n        list.addChangeListener(new OrderedRealmCollectionChangeListener<RealmList<Object>>() {\n            @Override\n            public void onChange(RealmList<Object> collection, @Nullable OrderedCollectionChangeSet changes) {\n                assertNotNull(changes);\n                assertEquals(0, changes.getInsertions().length);\n                assertEquals(3, changes.getDeletions().length);\n                assertEquals(0, changes.getChanges().length);\n                assertEquals(1, changes.getDeletionRanges().length);\n                assertEquals(0, changes.getDeletionRanges()[0].startIndex);\n                assertEquals(3, changes.getDeletionRanges()[0].length);\n                assertEquals(1, listenerCalledCount.getAndIncrement());\n            }\n        });\n\n        realm.beginTransaction();\n        //noinspection unchecked\n        list.deleteAllFromRealm();\n        realm.commitTransaction();\n\n        assertEquals(2, listenerCalledCount.get());\n        looperThread.testComplete();\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void removeAllChangeListeners() {\n        Realm realm = looperThread.getRealm();\n        realm.executeTransaction(new Realm.Transaction() {\n            @Override\n            public void execute(Realm realm) {\n                object = realm.createObject(NullTypes.class, 1000);\n                list = getListFor(object, listType, isTypeNullable);\n            }\n        });\n\n        //noinspection unchecked\n        list.addChangeListener(new RealmChangeListener<RealmList<Object>>() {\n            @Override\n            public void onChange(RealmList<Object> element) {\n                fail();\n            }\n        });\n        //noinspection unchecked\n        list.addChangeListener(new OrderedRealmCollectionChangeListener<RealmList<Object>>() {\n            @Override\n            public void onChange(RealmList<Object> collection, @Nullable OrderedCollectionChangeSet changes) {\n                fail();\n            }\n        });\n\n        list.removeAllChangeListeners();\n\n        final AtomicInteger listenerCalledCount = new AtomicInteger(0);\n        // This one is added after removal, so it should be triggered.\n        //noinspection unchecked\n        list.addChangeListener(new RealmChangeListener<RealmList<Object>>() {\n            @Override\n            public void onChange(RealmList<Object> element) {\n                listenerCalledCount.incrementAndGet();\n                looperThread.testComplete();\n            }\n        });\n\n        // This should trigger the listener if there is any.\n        realm.beginTransaction();\n        //noinspection unchecked\n        list.add(generateValue(listType, 500));\n        realm.commitTransaction();\n\n        assertEquals(1, listenerCalledCount.get());\n    }\n\n    @SuppressWarnings(\"unchecked\")\n    @Test\n    @RunTestInLooperThread\n    public void removeChangeListener() {\n        Realm realm = looperThread.getRealm();\n        realm.executeTransaction(new Realm.Transaction() {\n            @Override\n            public void execute(Realm realm) {\n                object = realm.createObject(NullTypes.class, 1000);\n                list = getListFor(object, listType, isTypeNullable);\n            }\n        });\n\n        final AtomicInteger listenerCalledCount = new AtomicInteger(0);\n        RealmChangeListener<RealmList<Object>> listener1 = new RealmChangeListener<RealmList<Object>>() {\n            @Override\n            public void onChange(RealmList<Object> element) {\n                fail();\n            }\n        };\n        OrderedRealmCollectionChangeListener<RealmList<Object>> listener2 =\n                new OrderedRealmCollectionChangeListener<RealmList<Object>>() {\n                    @Override\n                    public void onChange(RealmList<Object> collection, @Nullable OrderedCollectionChangeSet changes) {\n                        assertEquals(0, listenerCalledCount.getAndIncrement());\n                        looperThread.testComplete();\n                    }\n                };\n\n        list.addChangeListener(listener1);\n        list.addChangeListener(listener2);\n\n        list.removeChangeListener(listener1);\n\n        // This should trigger the listener if there is any.\n        realm.beginTransaction();\n        list.add(generateValue(listType, 500));\n        realm.commitTransaction();\n        assertEquals(1, listenerCalledCount.get());\n    }\n\n    @Test\n    public void createSnapshot() {\n        thrown.expect(UnsupportedOperationException.class);\n        thrown.expectMessage(is(RealmList.ALLOWED_ONLY_FOR_REALM_MODEL_ELEMENT_MESSAGE));\n        list.createSnapshot();\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/ManagedRealmListForValue_toArrayTests.java",
    "content": "/*\n * Copyright 2017 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\npackage io.realm;\n\nimport org.junit.After;\nimport org.junit.Before;\nimport org.junit.Rule;\nimport org.junit.Test;\nimport org.junit.rules.ExpectedException;\nimport org.junit.runner.RunWith;\nimport org.junit.runners.Parameterized;\n\nimport java.util.ArrayList;\nimport java.util.Collection;\nimport java.util.Date;\nimport java.util.List;\n\nimport io.realm.ManagedRealmListForValueTests.ListType;\nimport io.realm.entities.NullTypes;\nimport io.realm.rule.RunInLooperThread;\n\nimport static io.realm.ManagedRealmListForValueTests.ListType.BINARY_LIST;\nimport static io.realm.ManagedRealmListForValueTests.ListType.BOOLEAN_LIST;\nimport static io.realm.ManagedRealmListForValueTests.ListType.BYTE_LIST;\nimport static io.realm.ManagedRealmListForValueTests.ListType.DATE_LIST;\nimport static io.realm.ManagedRealmListForValueTests.ListType.DOUBLE_LIST;\nimport static io.realm.ManagedRealmListForValueTests.ListType.FLOAT_LIST;\nimport static io.realm.ManagedRealmListForValueTests.ListType.INTEGER_LIST;\nimport static io.realm.ManagedRealmListForValueTests.ListType.LONG_LIST;\nimport static io.realm.ManagedRealmListForValueTests.ListType.SHORT_LIST;\nimport static io.realm.ManagedRealmListForValueTests.ListType.STRING_LIST;\nimport static io.realm.ManagedRealmListForValueTests.NON_NULL_TEST_SIZE;\nimport static io.realm.ManagedRealmListForValueTests.NULLABLE_TEST_SIZE;\nimport static io.realm.ManagedRealmListForValueTests.generateValue;\nimport static io.realm.ManagedRealmListForValueTests.getListFor;\nimport static org.junit.Assert.assertArrayEquals;\nimport static org.junit.Assert.assertEquals;\nimport static org.junit.Assert.assertNull;\nimport static org.junit.Assert.assertTrue;\n\n/**\n * Unit tests specific for RealmList with value elements.\n */\n@RunWith(Parameterized.class)\npublic class ManagedRealmListForValue_toArrayTests extends CollectionTests {\n\n    @Parameterized.Parameters(name = \"{index}: Type: {0}, Nullable?: {1}\")\n    public static Collection<Object[]> parameters() {\n        final List<Object[]> paramsList = new ArrayList<>();\n        for (ListType listType : ListType.values()) {\n            paramsList.add(new Object[] {listType, Boolean.TRUE});\n            paramsList.add(new Object[] {listType, Boolean.FALSE});\n        }\n        return paramsList;\n    }\n\n    @Rule\n    public final TestRealmConfigurationFactory configFactory = new TestRealmConfigurationFactory();\n    @Rule\n    public ExpectedException thrown = ExpectedException.none();\n    @Rule\n    public final RunInLooperThread looperThread = new RunInLooperThread();\n\n    @Parameterized.Parameter\n    public ListType listType;\n\n    @Parameterized.Parameter(1)\n    public Boolean typeIsNullable;\n\n    private Realm realm;\n    private RealmList list;\n\n    @SuppressWarnings(\"unchecked\")\n    @Before\n    public void setUp() throws Exception {\n        final RealmConfiguration.Builder configurationBuilder = configFactory.createConfigurationBuilder();\n        configurationBuilder.schema(NullTypes.class);\n        RealmConfiguration realmConfig = configurationBuilder.build();\n\n        realm = Realm.getInstance(realmConfig);\n\n        realm.beginTransaction();\n        final NullTypes object = realm.createObject(NullTypes.class, 0);\n        for (ListType type : ListType.values()) {\n            for (int i = 0; i < NON_NULL_TEST_SIZE; i++) {\n                switch (type) {\n                    case STRING_LIST: {\n                        final RealmList nonnull = object.getFieldStringListNotNull();\n                        nonnull.add(generateValue(STRING_LIST, i));\n                        final RealmList nullable = object.getFieldStringListNull();\n                        nullable.add(\"\" + i);\n                        nullable.add(null);\n                    }\n                    break;\n                    case BOOLEAN_LIST: {\n                        final RealmList nonnull = object.getFieldBooleanListNotNull();\n                        nonnull.add(generateValue(BOOLEAN_LIST, i));\n                        final RealmList nullable = object.getFieldBooleanListNull();\n                        nullable.add(nonnull.last());\n                        nullable.add(null);\n                    }\n                    break;\n                    case BINARY_LIST: {\n                        final RealmList nonnull = object.getFieldBinaryListNotNull();\n                        nonnull.add(generateValue(BINARY_LIST, i));\n                        final RealmList nullable = object.getFieldBinaryListNull();\n                        nullable.add(nonnull.last());\n                        nullable.add(null);\n                    }\n                    break;\n                    case LONG_LIST: {\n                        final RealmList nonnull = object.getFieldLongListNotNull();\n                        nonnull.add(generateValue(LONG_LIST, i));\n                        final RealmList nullable = object.getFieldLongListNull();\n                        nullable.add(nonnull.last());\n                        nullable.add(null);\n                    }\n                    break;\n                    case INTEGER_LIST: {\n                        final RealmList nonnull = object.getFieldIntegerListNotNull();\n                        nonnull.add(generateValue(INTEGER_LIST, i));\n                        final RealmList nullable = object.getFieldIntegerListNull();\n                        nullable.add(nonnull.last());\n                        nullable.add(null);\n                    }\n                    break;\n                    case SHORT_LIST: {\n                        final RealmList nonnull = object.getFieldShortListNotNull();\n                        nonnull.add(generateValue(SHORT_LIST, i));\n                        final RealmList nullable = object.getFieldShortListNull();\n                        nullable.add(nonnull.last());\n                        nullable.add(null);\n                    }\n                    break;\n                    case BYTE_LIST: {\n                        final RealmList nonnull = object.getFieldByteListNotNull();\n                        nonnull.add(generateValue(BYTE_LIST, i));\n                        final RealmList nullable = object.getFieldByteListNull();\n                        nullable.add(nonnull.last());\n                        nullable.add(null);\n                    }\n                    break;\n                    case DOUBLE_LIST: {\n                        final RealmList nonnull = object.getFieldDoubleListNotNull();\n                        nonnull.add(generateValue(DOUBLE_LIST, i));\n                        final RealmList nullable = object.getFieldDoubleListNull();\n                        nullable.add(nonnull.last());\n                        nullable.add(null);\n                    }\n                    break;\n                    case FLOAT_LIST: {\n                        final RealmList nonnull = object.getFieldFloatListNotNull();\n                        nonnull.add(generateValue(FLOAT_LIST, i));\n                        final RealmList nullable = object.getFieldFloatListNull();\n                        nullable.add(nonnull.last());\n                        nullable.add(null);\n                    }\n                    break;\n                    case DATE_LIST: {\n                        final RealmList nonnull = object.getFieldDateListNotNull();\n                        nonnull.add(generateValue(DATE_LIST, i));\n                        final RealmList nullable = object.getFieldDateListNull();\n                        nullable.add(nonnull.last());\n                        nullable.add(null);\n                    }\n                    break;\n                    default:\n                        throw new AssertionError(\"unexpected value type: \" + listType.name());\n                }\n            }\n        }\n        realm.commitTransaction();\n\n        list = getListFor(object, listType, typeIsNullable);\n    }\n\n    @After\n    public void tearDown() throws Exception {\n        if (realm != null) {\n            realm.close();\n        }\n    }\n\n    @Test\n    public void toArray() {\n        final Object[] expected = new Object[typeIsNullable ? NULLABLE_TEST_SIZE : NON_NULL_TEST_SIZE];\n        for (int i = 0; i < NON_NULL_TEST_SIZE; i++) {\n            if (typeIsNullable) {\n                expected[i * 2] = generateValue(listType, i);\n                expected[i * 2 + 1] = null;\n            } else {\n                expected[i] = generateValue(listType, i);\n            }\n        }\n\n        if (listType != BINARY_LIST) {\n            assertArrayEquals(expected, list.toArray());\n        } else {\n            final Object[] array = list.toArray();\n            assertEquals(expected.length, array.length);\n            for (int i = 0; i < expected.length; i++) {\n                if (expected[i] == null) {\n                    assertNull(array[i]);\n                } else {\n                    assertTrue(array[i] instanceof byte[]);\n                    assertArrayEquals((byte[]) expected[i], (byte[]) array[i]);\n                }\n            }\n        }\n    }\n\n    @Test\n    public void toArray_withStringArray() {\n        if (listType != STRING_LIST) {\n            thrown.expect(ArrayStoreException.class);\n            list.toArray(new String[0]);\n            // should not reach here\n            return;\n        }\n\n        final String[] expected = new String[typeIsNullable ? NULLABLE_TEST_SIZE : NON_NULL_TEST_SIZE];\n        for (int i = 0; i < NON_NULL_TEST_SIZE; i++) {\n            if (typeIsNullable) {\n                expected[i * 2] = (String) generateValue(STRING_LIST, i);\n                expected[i * 2 + 1] = null;\n            } else {\n                expected[i] = (String) generateValue(STRING_LIST, i);\n            }\n        }\n        final Object[] returnedArray = list.toArray(new String[0]);\n        assertEquals(String.class, returnedArray.getClass().getComponentType());\n        assertArrayEquals(expected, returnedArray);\n    }\n\n    @Test\n    public void toArray_withBooleanArray() {\n        if (listType != BOOLEAN_LIST) {\n            thrown.expect(ArrayStoreException.class);\n            list.toArray(new Boolean[0]);\n            // should not reach here\n            return;\n        }\n\n        final Boolean[] expected = new Boolean[typeIsNullable ? NULLABLE_TEST_SIZE : NON_NULL_TEST_SIZE];\n        for (int i = 0; i < NON_NULL_TEST_SIZE; i++) {\n            if (typeIsNullable) {\n                expected[i * 2] = (Boolean) generateValue(BOOLEAN_LIST, i);\n                expected[i * 2 + 1] = null;\n            } else {\n                expected[i] = (Boolean) generateValue(BOOLEAN_LIST, i);\n            }\n        }\n\n        final Object[] returnedArray = list.toArray(new Boolean[0]);\n        assertEquals(Boolean.class, returnedArray.getClass().getComponentType());\n        assertArrayEquals(expected, returnedArray);\n    }\n\n    @Test\n    public void toArray_withBinaryArray() {\n        if (listType != BINARY_LIST) {\n            thrown.expect(ArrayStoreException.class);\n            list.toArray(new byte[0][]);\n            // should not reach here\n            return;\n        }\n\n        final byte[][] expected = new byte[typeIsNullable ? NULLABLE_TEST_SIZE : NON_NULL_TEST_SIZE][];\n        for (int i = 0; i < NON_NULL_TEST_SIZE; i++) {\n            if (typeIsNullable) {\n                expected[i * 2] = (byte[]) generateValue(BINARY_LIST, i);\n                expected[i * 2 + 1] = null;\n            } else {\n                expected[i] = (byte[]) generateValue(BINARY_LIST, i);\n            }\n        }\n        final Object[] returnedArray = list.toArray(new byte[0][]);\n        assertEquals(byte[].class, returnedArray.getClass().getComponentType());\n\n        assertEquals(expected.length, returnedArray.length);\n        for (int i = 0; i < expected.length; i++) {\n            if (expected[i] == null) {\n                assertNull(returnedArray[i]);\n            } else {\n                assertTrue(returnedArray[i] instanceof byte[]);\n                assertArrayEquals(expected[i], (byte[]) returnedArray[i]);\n            }\n        }\n    }\n\n    @Test\n    public void toArray_withLongArray() {\n        if (listType != LONG_LIST) {\n            thrown.expect(ArrayStoreException.class);\n            list.toArray(new Long[0]);\n            // should not reach here\n            return;\n        }\n\n        final Long[] expected = new Long[typeIsNullable ? NULLABLE_TEST_SIZE : NON_NULL_TEST_SIZE];\n        for (int i = 0; i < NON_NULL_TEST_SIZE; i++) {\n            if (typeIsNullable) {\n                expected[i * 2] = (Long) generateValue(LONG_LIST, i);\n                expected[i * 2 + 1] = null;\n            } else {\n                expected[i] = (Long) generateValue(LONG_LIST, i);\n            }\n        }\n        final Object[] returnedArray = list.toArray(new Long[0]);\n        assertEquals(Long.class, returnedArray.getClass().getComponentType());\n        assertArrayEquals(expected, returnedArray);\n    }\n\n    @Test\n    public void toArray_withIntegerArray() {\n        if (listType != INTEGER_LIST) {\n            thrown.expect(ArrayStoreException.class);\n            list.toArray(new Integer[0]);\n            // should not reach here\n            return;\n        }\n\n        final Integer[] expected = new Integer[typeIsNullable ? NULLABLE_TEST_SIZE : NON_NULL_TEST_SIZE];\n        for (int i = 0; i < NON_NULL_TEST_SIZE; i++) {\n            if (typeIsNullable) {\n                expected[i * 2] = (Integer) generateValue(INTEGER_LIST, i);\n                expected[i * 2 + 1] = null;\n            } else {\n                expected[i] = (Integer) generateValue(INTEGER_LIST, i);\n            }\n        }\n        final Object[] returnedArray = list.toArray(new Integer[0]);\n        assertEquals(Integer.class, returnedArray.getClass().getComponentType());\n        assertArrayEquals(expected, returnedArray);\n    }\n\n    @Test\n    public void toArray_withShortArray() {\n        if (listType != SHORT_LIST) {\n            thrown.expect(ArrayStoreException.class);\n            list.toArray(new Short[0]);\n            // should not reach here\n            return;\n        }\n\n        final Short[] expected = new Short[typeIsNullable ? NULLABLE_TEST_SIZE : NON_NULL_TEST_SIZE];\n        for (int i = 0; i < NON_NULL_TEST_SIZE; i++) {\n            if (typeIsNullable) {\n                expected[i * 2] = (Short) generateValue(SHORT_LIST, i);\n                expected[i * 2 + 1] = null;\n            } else {\n                expected[i] = (Short) generateValue(SHORT_LIST, i);\n            }\n        }\n        final Object[] returnedArray = list.toArray(new Short[0]);\n        assertEquals(Short.class, returnedArray.getClass().getComponentType());\n        assertArrayEquals(expected, returnedArray);\n    }\n\n    @Test\n    public void toArray_withByteArray() {\n        if (listType != BYTE_LIST) {\n            thrown.expect(ArrayStoreException.class);\n            list.toArray(new Byte[0]);\n            // should not reach here\n            return;\n        }\n\n        final Byte[] expected = new Byte[typeIsNullable ? NULLABLE_TEST_SIZE : NON_NULL_TEST_SIZE];\n        for (int i = 0; i < NON_NULL_TEST_SIZE; i++) {\n            if (typeIsNullable) {\n                expected[i * 2] = (Byte) generateValue(BYTE_LIST, i);\n                expected[i * 2 + 1] = null;\n            } else {\n                expected[i] = (Byte) generateValue(BYTE_LIST, i);\n            }\n        }\n        final Object[] returnedArray = list.toArray(new Byte[0]);\n        assertEquals(Byte.class, returnedArray.getClass().getComponentType());\n        assertArrayEquals(expected, returnedArray);\n    }\n\n    @Test\n    public void toArray_withDoubleArray() {\n        if (listType != DOUBLE_LIST) {\n            thrown.expect(ArrayStoreException.class);\n            list.toArray(new Double[0]);\n            // should not reach here\n            return;\n        }\n\n        final Double[] expected = new Double[typeIsNullable ? NULLABLE_TEST_SIZE : NON_NULL_TEST_SIZE];\n        for (int i = 0; i < NON_NULL_TEST_SIZE; i++) {\n            if (typeIsNullable) {\n                expected[i * 2] = (Double) generateValue(DOUBLE_LIST, i);\n                expected[i * 2 + 1] = null;\n            } else {\n                expected[i] = (Double) generateValue(DOUBLE_LIST, i);\n            }\n        }\n        final Object[] returnedArray = list.toArray(new Double[0]);\n        assertEquals(Double.class, returnedArray.getClass().getComponentType());\n        assertArrayEquals(expected, returnedArray);\n    }\n\n    @Test\n    public void toArray_withFloatArray() {\n        if (listType != FLOAT_LIST) {\n            thrown.expect(ArrayStoreException.class);\n            list.toArray(new Float[0]);\n            // should not reach here\n            return;\n        }\n\n        final Float[] expected = new Float[typeIsNullable ? NULLABLE_TEST_SIZE : NON_NULL_TEST_SIZE];\n        for (int i = 0; i < NON_NULL_TEST_SIZE; i++) {\n            if (typeIsNullable) {\n                expected[i * 2] = (Float) generateValue(FLOAT_LIST, i);\n                expected[i * 2 + 1] = null;\n            } else {\n                expected[i] = (Float) generateValue(FLOAT_LIST, i);\n            }\n        }\n        final Object[] returnedArray = list.toArray(new Float[0]);\n        assertEquals(Float.class, returnedArray.getClass().getComponentType());\n        assertArrayEquals(expected, returnedArray);\n    }\n\n    @Test\n    public void toArray_withDateArray() {\n        if (listType != DATE_LIST) {\n            thrown.expect(ArrayStoreException.class);\n            list.toArray(new Date[0]);\n            // should not reach here\n            return;\n        }\n\n        final Date[] expected = new Date[typeIsNullable ? NULLABLE_TEST_SIZE : NON_NULL_TEST_SIZE];\n        for (int i = 0; i < NON_NULL_TEST_SIZE; i++) {\n            if (typeIsNullable) {\n                expected[i * 2] = (Date) generateValue(DATE_LIST, i);\n                expected[i * 2 + 1] = null;\n            } else {\n                expected[i] = (Date) generateValue(DATE_LIST, i);\n            }\n        }\n        final Object[] returnedArray = list.toArray(new Date[0]);\n        assertEquals(Date.class, returnedArray.getClass().getComponentType());\n        assertArrayEquals(expected, returnedArray);\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/MediatorTest.java",
    "content": "/*\n * Copyright 2015 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\npackage io.realm;\n\nimport androidx.test.ext.junit.runners.AndroidJUnit4;\n\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\n\nimport java.util.Arrays;\n\nimport io.realm.annotations.RealmModule;\nimport io.realm.entities.AllTypes;\nimport io.realm.entities.AnimalModule;\nimport io.realm.entities.Cat;\nimport io.realm.entities.CatOwner;\nimport io.realm.entities.Dog;\nimport io.realm.entities.HumanModule;\nimport io.realm.internal.modules.CompositeMediator;\nimport io.realm.internal.modules.FilterableMediator;\n\nimport static org.junit.Assert.assertEquals;\nimport static org.junit.Assert.assertFalse;\nimport static org.junit.Assert.assertTrue;\n\n@RunWith(AndroidJUnit4.class)\npublic class MediatorTest {\n\n    @SuppressWarnings(\"AssertEqualsBetweenInconvertibleTypes\")\n    @Test\n    public void mediatorsEquality() {\n        final DefaultRealmModuleMediator defaultMediator = new DefaultRealmModuleMediator();\n        final CompositeMediator compositeMediator = new CompositeMediator(defaultMediator);\n        final FilterableMediator filterableMediator = new FilterableMediator(defaultMediator, defaultMediator.getModelClasses());\n\n        assertEquals(defaultMediator, defaultMediator);\n        assertEquals(defaultMediator.hashCode(), defaultMediator.hashCode());\n        assertEquals(defaultMediator, compositeMediator);\n        assertEquals(defaultMediator.hashCode(), compositeMediator.hashCode());\n        assertEquals(defaultMediator, filterableMediator);\n        assertEquals(defaultMediator.hashCode(), filterableMediator.hashCode());\n\n        assertEquals(compositeMediator, defaultMediator);\n        assertEquals(compositeMediator.hashCode(), defaultMediator.hashCode());\n        assertEquals(compositeMediator, compositeMediator);\n        assertEquals(compositeMediator.hashCode(), compositeMediator.hashCode());\n        assertEquals(compositeMediator, filterableMediator);\n        assertEquals(compositeMediator.hashCode(), filterableMediator.hashCode());\n\n        assertEquals(filterableMediator, defaultMediator);\n        assertEquals(filterableMediator.hashCode(), defaultMediator.hashCode());\n        assertEquals(filterableMediator, compositeMediator);\n        assertEquals(filterableMediator.hashCode(), compositeMediator.hashCode());\n        assertEquals(filterableMediator, filterableMediator);\n        assertEquals(filterableMediator.hashCode(), filterableMediator.hashCode());\n    }\n\n    @Test\n    public void compositeMediatorModelClassesCount() {\n        final CompositeMediator mediator = new CompositeMediator(\n                new HumanModuleMediator(),\n                new AnimalModuleMediator()\n        );\n\n        final int modelsInHumanModule = HumanModule.class.getAnnotation(RealmModule.class).classes().length;\n        final int modelsInAnimalModule = AnimalModule.class.getAnnotation(RealmModule.class).classes().length;\n\n        assertEquals(modelsInHumanModule + modelsInAnimalModule, mediator.getModelClasses().size());\n    }\n\n    @Test\n    public void filterableMediatorModelClassesCount() {\n        //noinspection unchecked\n        final FilterableMediator mediator = new FilterableMediator(new AnimalModuleMediator(), Arrays.<Class<? extends RealmModel>>asList(Cat.class, CatOwner.class));\n\n        assertTrue(mediator.getModelClasses().contains(Cat.class));\n        // CatOwner is not a member of AnimalModuleMediator\n        assertFalse(mediator.getModelClasses().contains(CatOwner.class));\n        assertFalse(mediator.getModelClasses().contains(Dog.class));\n        assertFalse(mediator.getModelClasses().contains(AllTypes.class));\n    }\n\n    @Test\n    public void defaultMediatorWasTransformed() {\n        final DefaultRealmModuleMediator defaultMediator = new DefaultRealmModuleMediator();\n        assertTrue(defaultMediator.transformerApplied());\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/MutableRealmIntegerTests.java",
    "content": "/*\n * Copyright 2017 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 */\npackage io.realm;\n\nimport android.content.Context;\nimport androidx.test.platform.app.InstrumentationRegistry;\nimport androidx.test.ext.junit.runners.AndroidJUnit4;\n\nimport org.json.JSONException;\nimport org.json.JSONObject;\nimport org.junit.After;\nimport org.junit.Before;\nimport org.junit.Rule;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\n\nimport java.io.IOException;\nimport java.io.InputStream;\n\nimport io.realm.entities.MutableRealmIntegerTypes;\nimport io.realm.rule.RunInLooperThread;\n\nimport static junit.framework.Assert.assertEquals;\nimport static junit.framework.Assert.assertFalse;\nimport static junit.framework.Assert.assertTrue;\nimport static junit.framework.Assert.fail;\n\n\n@RunWith(AndroidJUnit4.class)\npublic class MutableRealmIntegerTests {\n\n    @Rule\n    public final TestRealmConfigurationFactory configFactory = new TestRealmConfigurationFactory();\n    @Rule\n    public final RunInLooperThread looperThread = new RunInLooperThread();\n\n    private Realm realm;\n\n    @Before\n    public void setUp() throws Exception {\n        RealmConfiguration realmConfig = configFactory.createConfiguration();\n        realm = Realm.getInstance(realmConfig);\n    }\n\n    @After\n    public void tearDown() throws Exception {\n        if (realm != null) {\n            if (realm.isInTransaction()) {\n                realm.cancelTransaction();\n            }\n            realm.close();\n        }\n    }\n\n    /**\n     * Validate basic functions: set, increment and decrement.\n     */\n    @Test\n    public void basic_unmanaged() {\n        testBasic(MutableRealmInteger.ofNull(), MutableRealmInteger.ofNull());\n    }\n\n    /**\n     * Validate basic equality semantics.\n     */\n    @Test\n    public void equality_unmanaged() {\n        testEquality(new MutableRealmIntegerTypes(), new MutableRealmIntegerTypes());\n    }\n\n    /**\n     * Validate basic nullability semantics.\n     */\n    @Test\n    public void nullability_unmanaged() {\n        testNullability(new MutableRealmIntegerTypes());\n    }\n\n    /**\n     * Validate basic validity/managed semantics.\n     */\n    @Test\n    public void validAndManaged_unmanaged() {\n        testValidityAndManagement(new MutableRealmIntegerTypes());\n    }\n\n    /**\n     * Validate basic functions: set, increment and decrement.\n     */\n    @Test\n    public void basic_managed() {\n        realm.beginTransaction();\n        MutableRealmIntegerTypes c1 = realm.createObject(MutableRealmIntegerTypes.class);\n        MutableRealmIntegerTypes c2 = realm.createObject(MutableRealmIntegerTypes.class);\n        realm.commitTransaction();\n\n        realm.beginTransaction();\n        testBasic(c1.columnNullableMutableRealmInteger, c2.columnNullableMutableRealmInteger);\n        realm.commitTransaction();\n    }\n\n    /**\n     * Validate basic equality semantics.\n     */\n    @Test\n    public void equality_managed() {\n        realm.beginTransaction();\n        MutableRealmIntegerTypes c1 = realm.createObject(MutableRealmIntegerTypes.class);\n        MutableRealmIntegerTypes c2 = realm.createObject(MutableRealmIntegerTypes.class);\n        realm.commitTransaction();\n\n        realm.beginTransaction();\n        testEquality(c1, c2);\n        realm.commitTransaction();\n    }\n\n    /**\n     * Validate basic nullability semantics.\n     */\n    @Test\n    public void nullability_managed() {\n        realm.beginTransaction();\n        MutableRealmIntegerTypes c1 = realm.createObject(MutableRealmIntegerTypes.class);\n        realm.commitTransaction();\n\n        realm.beginTransaction();\n        testNullability(c1);\n        realm.commitTransaction();\n    }\n\n    /**\n     * Validate basic validity/managed semantics.\n     */\n    @Test\n    public void validAndManaged_managed() {\n        realm.beginTransaction();\n        MutableRealmIntegerTypes c1 = realm.createObject(MutableRealmIntegerTypes.class);\n        realm.commitTransaction();\n\n        realm.beginTransaction();\n        testValidityAndManagement(c1);\n        realm.commitTransaction();\n    }\n\n    /**\n     * {@literal @}Required MutableRealmIntegers should not be nullable.\n     * There are other tests testing nullabilty: just need to test @Required here.\n     * There is no attempt to control the nullability of an unmanaged MutableRealmInteger.\n     * An attempt to copy an unmanaged model object with a null-valued MutableRealmInteger\n     * into an @Required field should fail.\n     */\n    @Test\n    public void required() {\n        realm.beginTransaction();\n        MutableRealmIntegerTypes c1 = realm.createObject(MutableRealmIntegerTypes.class);\n        realm.commitTransaction();\n\n        assertFalse(\n                realm.getSchema().get(\"MutableRealmIntegerTypes\")\n                        .isNullable(MutableRealmIntegerTypes.FIELD_NONNULLABLE_MUTABLEREALMINTEGER));\n\n        realm.beginTransaction();\n        try {\n            c1.columnNonNullableMutableRealmInteger.set(null);\n            fail(\"should not be able to set an @Required MutableRealmInteger null\");\n        } catch(IllegalArgumentException ignore) {\n            checkException(ignore, \"is not nullable\");\n        }\n        realm.commitTransaction();\n\n        c1 = new MutableRealmIntegerTypes();\n        c1.columnNonNullableMutableRealmInteger.set(null);\n        realm.beginTransaction();\n        try {\n            MutableRealmIntegerTypes c2 = realm.copyToRealm(c1);\n            fail(\"should not be able to copy a null value to a @Required MutableRealmInteger\");\n        } catch(IllegalArgumentException ignore) {\n            checkException(ignore, \"Missing value for property\");\n        }\n        realm.commitTransaction();\n    }\n\n\n    /**\n     * MutableRealmIntegers annotated with {@literal @}Index should have indices.\n     * Without {@literal @}Index they should not.\n     */\n    @Test\n    public void indexed() {\n        realm.beginTransaction();\n        MutableRealmIntegerTypes c1 = realm.createObject(MutableRealmIntegerTypes.class);\n        realm.commitTransaction();\n\n        assertTrue(\n                realm.getSchema().get(\"MutableRealmIntegerTypes\")\n                        .hasIndex(MutableRealmIntegerTypes.FIELD_INDEXED_MUTABLEREALMINTEGER));\n        assertFalse(\n                realm.getSchema().get(\"MutableRealmIntegerTypes\")\n                        .hasIndex(MutableRealmIntegerTypes.FIELD_NULLABLE_MUTABLEEALMINTEGER));\n    }\n\n    /**\n     * Be absolutely certain that we can actually compare two longs.\n     */\n    @Test\n    public void compareTo_unmanaged() {\n        MutableRealmInteger ri1 = MutableRealmInteger.valueOf(0);\n        MutableRealmInteger ri2 = MutableRealmInteger.valueOf(Long.MAX_VALUE);\n        assertEquals(-1, ri1.compareTo(ri2));\n\n        ri2.decrement(Long.MAX_VALUE);\n        assertEquals(0, ri1.compareTo(ri2));\n\n        ri2.decrement(Long.MAX_VALUE);\n        assertEquals(1, ri1.compareTo(ri2));\n    }\n\n    /**\n     * Be absolutely certain that we can actually compare two longs.\n     */\n    @Test\n    public void compareTo_managed() {\n        realm.beginTransaction();\n        MutableRealmInteger ri1 = realm.createObject(MutableRealmIntegerTypes.class).getColumnNullableMutableRealmInteger();\n        ri1.set(0);\n        MutableRealmInteger ri2 = realm.createObject(MutableRealmIntegerTypes.class).getColumnNullableMutableRealmInteger();\n        ri2.set(Long.MAX_VALUE);\n        realm.commitTransaction();\n        assertEquals(-1, ri1.compareTo(ri2));\n\n        realm.beginTransaction();\n        ri2.decrement(Long.MAX_VALUE);\n        realm.commitTransaction();\n        assertEquals(0, ri1.compareTo(ri2));\n\n        realm.beginTransaction();\n        ri2.decrement(Long.MAX_VALUE);\n        realm.commitTransaction();\n        assertEquals(1, ri1.compareTo(ri2));\n    }\n\n    /**\n     * Assure that an attempt to change the value of a managed MutableRealmInteger, outside a transaction, fails.\n     */\n    @Test\n    public void updateOutsideTransactionThrows() {\n        realm.beginTransaction();\n        realm.createObject(MutableRealmIntegerTypes.class).getColumnNullableMutableRealmInteger().set(42);\n        realm.commitTransaction();\n\n        MutableRealmInteger managedRI = realm.where(MutableRealmIntegerTypes.class).findFirst().getColumnNullableMutableRealmInteger();\n        try {\n            managedRI.set(1);\n            fail(\"Setting a managed MutableRealmInteger outside a transaction should fail\");\n        } catch (IllegalStateException e) {\n            checkTransactionException(e);\n        }\n\n        try {\n            managedRI.increment(1);\n            fail(\"Incrementing a managed MutableRealmInteger outside a transaction should fail\");\n        } catch (IllegalStateException e) {\n            checkTransactionException(e);\n        }\n\n        try {\n            managedRI.decrement(1);\n            fail(\"Decrementing a managed MutableRealmInteger outside a transaction should fail\");\n        } catch (IllegalStateException e) {\n            checkTransactionException(e);\n        }\n    }\n\n    /**\n     * Assure that changes to a MutableRealmInteger acquired from a managed object are reflected in the object.\n     */\n    @Test\n    public void isLive() {\n        realm.beginTransaction();\n        realm.createObject(MutableRealmIntegerTypes.class).getColumnNullableMutableRealmInteger().set(42);\n        realm.commitTransaction();\n\n        MutableRealmInteger managedRI = realm.where(MutableRealmIntegerTypes.class).findFirst().getColumnNullableMutableRealmInteger();\n\n        realm.beginTransaction();\n        MutableRealmInteger ri = realm.where(MutableRealmIntegerTypes.class).findFirst().getColumnNullableMutableRealmInteger();\n        ri.set(37);\n        ri.increment(17);\n        ri.decrement(7);\n        realm.commitTransaction();\n\n        assertEquals(Long.valueOf(47), managedRI.get());\n    }\n\n    /**\n     * Assure that changes to a MutableRealmInteger acquired from a managed object are reflected in the object.\n     */\n    @Test\n    public void copyToIsLive() {\n        MutableRealmIntegerTypes obj = new MutableRealmIntegerTypes();\n        MutableRealmInteger unmanagedRI = obj.getColumnNullableMutableRealmInteger();\n        unmanagedRI.set(42L);\n\n        realm.beginTransaction();\n        MutableRealmInteger managedRI = realm.copyToRealm(obj).getColumnNullableMutableRealmInteger();\n        realm.commitTransaction();\n\n        realm.beginTransaction();\n        MutableRealmInteger ri = realm.where(MutableRealmIntegerTypes.class).findFirst().getColumnNullableMutableRealmInteger();\n        ri.set(37);\n        ri.increment(17);\n        ri.decrement(7);\n        realm.commitTransaction();\n\n        assertEquals(Long.valueOf(42L), unmanagedRI.get());\n        assertEquals(Long.valueOf(47L), managedRI.get());\n    }\n\n    /**\n     * Assure that a MutableRealmInteger acquired from an unmanaged object is not affected by changes in the Realm.\n     */\n    @Test\n    public void copyFromIsNotLive() {\n        realm.beginTransaction();\n        realm.createObject(MutableRealmIntegerTypes.class).getColumnNullableMutableRealmInteger().set(42L);\n        realm.commitTransaction();\n\n        MutableRealmIntegerTypes obj = realm.where(MutableRealmIntegerTypes.class).findFirst();\n        MutableRealmInteger managedRI = obj.getColumnNullableMutableRealmInteger();\n        MutableRealmInteger unmanagedRI = realm.copyFromRealm(obj).getColumnNullableMutableRealmInteger();\n\n        realm.beginTransaction();\n        MutableRealmInteger ri = realm.where(MutableRealmIntegerTypes.class).findFirst().getColumnNullableMutableRealmInteger();\n        ri.set(37);\n        ri.increment(17);\n        ri.decrement(7);\n        realm.commitTransaction();\n\n        assertEquals(Long.valueOf(42L), unmanagedRI.get());\n        assertEquals(Long.valueOf(47L), managedRI.get());\n    }\n\n    @Test\n    public void testJSON() throws JSONException {\n        JSONObject json = new JSONObject();\n        realm.beginTransaction();\n        MutableRealmIntegerTypes obj = realm.createObjectFromJson(MutableRealmIntegerTypes.class, json);\n        realm.commitTransaction();\n        assertTrue(obj.columnNullableMutableRealmInteger.isNull());\n\n        json = new JSONObject();\n        json.put(\"columnNullableMutableRealmInteger\", 8589934592L);\n        realm.beginTransaction();\n        obj = realm.createObjectFromJson(MutableRealmIntegerTypes.class, json);\n        realm.commitTransaction();\n        assertEquals(Long.valueOf(8589934592L), obj.columnNullableMutableRealmInteger.get());\n\n        json = new JSONObject();\n        json.put(\"columnNullableMutableRealmInteger\", 22);\n        realm.beginTransaction();\n        obj = realm.createObjectFromJson(MutableRealmIntegerTypes.class, json);\n        realm.commitTransaction();\n        assertEquals(Long.valueOf(22), obj.columnNullableMutableRealmInteger.get());\n\n        json = new JSONObject();\n        json.put(\"columnNullableMutableRealmInteger\", JSONObject.NULL);\n        realm.beginTransaction();\n        obj = realm.createObjectFromJson(MutableRealmIntegerTypes.class, json);\n        realm.commitTransaction();\n        assertTrue(obj.columnNullableMutableRealmInteger.isNull());\n\n        json = new JSONObject();\n        json.put(\"columnNonNullableMutableRealmInteger\", JSONObject.NULL);\n        realm.beginTransaction();\n        try {\n            obj = realm.createObjectFromJson(MutableRealmIntegerTypes.class, json);\n            fail(\"Attempt to set @Required Mutable Realm Integer null, from JSON, should fail\");\n        } catch (IllegalArgumentException ignore) {\n            checkException(ignore, \"is not nullable\");\n        }\n        realm.commitTransaction();\n    }\n\n    @Test\n    public void testStream() throws IOException {\n        Context context = InstrumentationRegistry.getInstrumentation().getTargetContext();\n\n        InputStream in = TestHelper.loadJsonFromAssets(context, \"empty.json\");\n        realm.beginTransaction();\n        MutableRealmIntegerTypes obj = realm.createObjectFromJson(MutableRealmIntegerTypes.class, in);\n        realm.commitTransaction();\n        assertTrue(obj.columnNullableMutableRealmInteger.isNull());\n\n        in = TestHelper.loadJsonFromAssets(context, \"mutablerealminteger-long.json\");\n        realm.beginTransaction();\n        obj = realm.createObjectFromJson(MutableRealmIntegerTypes.class, in);\n        realm.commitTransaction();\n        assertEquals(Long.valueOf(8589934592L), obj.columnNullableMutableRealmInteger.get());\n\n        in = TestHelper.loadJsonFromAssets(context, \"mutablerealminteger-int.json\");\n        realm.beginTransaction();\n        obj = realm.createObjectFromJson(MutableRealmIntegerTypes.class, in);\n        realm.commitTransaction();\n        assertEquals(Long.valueOf(22), obj.columnNullableMutableRealmInteger.get());\n\n        in = TestHelper.loadJsonFromAssets(context, \"mutablerealminteger-null.json\");\n        realm.beginTransaction();\n        obj = realm.createObjectFromJson(MutableRealmIntegerTypes.class, in);\n        realm.commitTransaction();\n        assertTrue(obj.columnNullableMutableRealmInteger.isNull());\n\n        in = TestHelper.loadJsonFromAssets(context, \"mutablerealminteger-required-null.json\");\n        realm.beginTransaction();\n        try {\n            obj = realm.createObjectFromJson(MutableRealmIntegerTypes.class, in);\n            fail(\"Attempt to set @Required Mutable Realm Integer null, from JSON, should fail\");\n        } catch (IllegalArgumentException ignore) {\n            checkException(ignore, \"Missing value for property\");\n        }\n        realm.commitTransaction();\n    }\n\n    private void checkTransactionException(Exception e) {\n        checkException(e, \"only be done from inside a transaction\");\n    }\n\n    private void checkException(Exception e, String expected) {\n        assertTrue(e.getMessage().contains(expected));\n    }\n\n    /**\n     * Test basic arithmetic: set, increment, decrement and equals.\n     * Since the implementations of managed and unmanaged MutableRealmIntegers are completely\n     * different these tests should be run on both implementations.\n     *\n     * @param r1 a MutableRealmInteger\n     * @param r2 another MutableRealmInteger\n     */\n    @SuppressWarnings({\"ReferenceEquality\", \"EqualsIncompatibleType\"})\n    private void testBasic(MutableRealmInteger r1, MutableRealmInteger r2) {\n        assertFalse(r1 == r2);\n\n        r1.set(10);\n        r2.set(Long.valueOf(10));\n        assertEquals(r1, r2);\n        assertEquals(r2, r1);\n\n        r1.set(15);\n        r1.decrement(2);\n        r2.increment(3);\n        assertEquals(r1, r2);\n\n        MutableRealmInteger r3 = r1;\n        r1.set(19);\n        assertEquals(19, r3.get().intValue());\n\n        assertFalse(r2.equals(r3));\n        assertFalse(r3.equals(r2));\n    }\n\n    /**\n     * Thorough tests of equality, as defined <a href=\"https://github.com/realm/realm-java/issues/4266#issuecomment-308772718\">here</a>\n     * and in subsequent comments.  The general principles are:\n     * <ul>\n     *     <li>MutableRealmInteger.equals tests the value of the wrapped integer<./li>\n     *     <li>All references to a single MutableRealmInteger must be {@code .equals} to the same thing.</li>\n     *     <li>Except when set to {@code null} MutableRealmInteger does not distinguish boxed and primitive types.</li>\n     * </ul>\n     * Since the implementations of managed and unmanaged MutableRealmIntegers are completely\n     * different these tests should be run on both implementations.\n     *\n     * @param c1 a MutableRealmIntegerTypes\n     * @param c2 another MutableRealmIntegerTypes\n     */\n    @SuppressWarnings({\"ReferenceEquality\", \"EqualsIncompatibleType\"})\n    private void testEquality(MutableRealmIntegerTypes c1, MutableRealmIntegerTypes c2) {\n        assertFalse(c1 == c2);\n\n        c1.columnNullableMutableRealmInteger.set(7);\n        c2.columnNullableMutableRealmInteger.set(Long.valueOf(7));\n        assertTrue(c1.columnNullableMutableRealmInteger != c2.columnNullableMutableRealmInteger);\n        assertTrue(c1.columnNullableMutableRealmInteger.equals(c2.columnNullableMutableRealmInteger));\n\n        MutableRealmInteger r1 = c1.columnNullableMutableRealmInteger;\n        r1.increment(1);\n        assertTrue(r1.equals(c1.columnNullableMutableRealmInteger));\n        assertTrue(r1 == c1.columnNullableMutableRealmInteger);\n        assertTrue(c1.columnNullableMutableRealmInteger.get().equals(8L));\n        assertFalse(c1.columnNullableMutableRealmInteger.get().equals(c2.columnNullableMutableRealmInteger.get()));\n        assertTrue(c1.columnNullableMutableRealmInteger.get().intValue() == 8);\n\n        Long n = c1.columnNullableMutableRealmInteger.get();\n        assertTrue(n.equals(Long.valueOf(8)));\n        assertTrue(n.equals(c1.columnNullableMutableRealmInteger.get()));\n        assertTrue(n.intValue() == c1.columnNullableMutableRealmInteger.get().intValue());\n\n        c1.columnNullableMutableRealmInteger.increment(1);\n        assertFalse(n.intValue() == c1.columnNullableMutableRealmInteger.get().intValue());\n        assertFalse(n.intValue() == r1.get().intValue());\n    }\n\n    /**\n     * Thorough tests of nullability, as defined <a href=\"https://github.com/realm/realm-java/issues/4266#issuecomment-308772718\">here</a>\n     * and in subsequent comments.  The general principles are:\n     * <ul>\n     *     <li>Unless @Required, MutableRealmIntegers are nullable.</li>\n     *     <li>0L and null are distinct values.</li>\n     *     <li>All references to a single MutableRealmInteger must be {@code null} if any are./li>\n     *     <li>A null value cannot be incremented or decremented/li>\n     * </ul>\n     * Since the implementations of managed and unmanaged MutableRealmIntegers are completely\n     * different these tests should be run on both implementations.\n     *\n     * @param c1 a MutableRealmIntegerTypes\n     */\n    private void testNullability(MutableRealmIntegerTypes c1) {\n        MutableRealmInteger r1 = c1.columnNullableMutableRealmInteger;\n\n        c1.columnNullableMutableRealmInteger.set(0L);\n        assertFalse(c1.columnNullableMutableRealmInteger.isNull());\n        assertFalse(r1.isNull());\n\n        c1.columnNullableMutableRealmInteger.set(null);\n        assertFalse(c1.columnNullableMutableRealmInteger == null);\n        assertTrue(c1.columnNullableMutableRealmInteger.isNull());\n        assertTrue(r1.isNull());\n\n        assertTrue(c1.columnNullableMutableRealmInteger.get() == null);\n        assertTrue(r1.get() == null);\n\n        try {\n            c1.columnNullableMutableRealmInteger.increment(5);\n            fail(\"Attempt to increment a null valued MutableRealmInteger should throw ISE\");\n        } catch (IllegalStateException ignore) {\n            checkException(ignore, \"Set its value first\");\n        }\n        try {\n            c1.columnNullableMutableRealmInteger.decrement(5);\n            fail(\"Attempt to decrement a null valued MutableRealmInteger should throw ISE\");\n        } catch (IllegalStateException ignore) {\n            checkException(ignore, \"Set its value first\");\n        }\n    }\n\n    private void testValidityAndManagement(MutableRealmIntegerTypes c1) {\n        MutableRealmInteger r1 = c1.columnNullableMutableRealmInteger;\n        assertTrue(r1.isManaged() == c1.isManaged());\n        assertTrue(r1.isValid() == c1.isValid());\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/NotificationsTest.java",
    "content": "/*\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\npackage io.realm;\n\nimport static org.junit.Assert.assertEquals;\nimport static org.junit.Assert.assertFalse;\nimport static org.junit.Assert.assertNotNull;\nimport static org.junit.Assert.assertTrue;\nimport static org.junit.Assert.fail;\n\nimport android.os.Handler;\nimport android.os.HandlerThread;\nimport android.os.Looper;\nimport android.util.Log;\n\nimport androidx.test.annotation.UiThreadTest;\nimport androidx.test.ext.junit.runners.AndroidJUnit4;\nimport androidx.test.rule.UiThreadTestRule;\n\nimport junit.framework.AssertionFailedError;\n\nimport org.junit.After;\nimport org.junit.Before;\nimport org.junit.Ignore;\nimport org.junit.Rule;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\n\nimport java.util.concurrent.Callable;\nimport java.util.concurrent.CountDownLatch;\nimport java.util.concurrent.ExecutionException;\nimport java.util.concurrent.ExecutorService;\nimport java.util.concurrent.Executors;\nimport java.util.concurrent.Future;\nimport java.util.concurrent.TimeUnit;\nimport java.util.concurrent.TimeoutException;\nimport java.util.concurrent.atomic.AtomicBoolean;\nimport java.util.concurrent.atomic.AtomicInteger;\n\nimport io.realm.entities.AllJavaTypes;\nimport io.realm.entities.AllTypes;\nimport io.realm.entities.Dog;\nimport io.realm.log.RealmLog;\nimport io.realm.log.RealmLogger;\nimport io.realm.rule.RunInLooperThread;\nimport io.realm.rule.RunTestInLooperThread;\n\n@RunWith(AndroidJUnit4.class)\npublic class NotificationsTest {\n\n    @Rule\n    public final UiThreadTestRule uiThreadTestRule = new UiThreadTestRule();\n    @Rule\n    public final RunInLooperThread looperThread = new RunInLooperThread();\n    @Rule\n    public final TestRealmConfigurationFactory configFactory = new TestRealmConfigurationFactory();\n\n    private Realm realm;\n    private RealmConfiguration realmConfig;\n\n    @Before\n    public void setUp() {\n        realmConfig = configFactory.createConfiguration();\n    }\n\n    @After\n    public void tearDown() {\n        Realm.asyncTaskExecutor.resume();\n        if (realm != null) {\n            realm.close();\n        }\n    }\n\n    @Test\n    public void setAutoRefresh_failsOnNonLooperThread() throws ExecutionException, InterruptedException {\n        ExecutorService executorService = Executors.newSingleThreadExecutor();\n        Future<Boolean> future = executorService.submit(new Callable<Boolean>() {\n            @Override\n            public Boolean call() throws Exception {\n                Realm realm = Realm.getInstance(realmConfig);\n                boolean autoRefresh = realm.isAutoRefresh();\n                assertFalse(autoRefresh);\n                try {\n                    realm.setAutoRefresh(true);\n                    return false;\n                } catch (IllegalStateException ignored) {\n                    return true;\n                } finally {\n                    realm.close();\n                }\n            }\n        });\n\n        assertTrue(future.get());\n        RealmCache.invokeWithGlobalRefCount(realmConfig, new TestHelper.ExpectedCountCallback(0));\n    }\n\n    @Test\n    public void setAutoRefresh_onHandlerThread() throws ExecutionException, InterruptedException {\n        ExecutorService executorService = Executors.newSingleThreadExecutor();\n        Future<Boolean> future = executorService.submit(new Callable<Boolean>() {\n            @Override\n            public Boolean call() throws Exception {\n                Looper.prepare();\n                Realm realm = Realm.getInstance(realmConfig);\n                assertTrue(realm.isAutoRefresh());\n                realm.setAutoRefresh(false);\n                assertFalse(realm.isAutoRefresh());\n                realm.setAutoRefresh(true);\n                assertTrue(realm.isAutoRefresh());\n                realm.close();\n                return true;\n            }\n        });\n\n        assertTrue(future.get());\n        RealmCache.invokeWithGlobalRefCount(realmConfig, new TestHelper.ExpectedCountCallback(0));\n    }\n\n    @Test\n    @UiThreadTest\n    public void removeChangeListener() throws InterruptedException, ExecutionException {\n        final AtomicInteger counter = new AtomicInteger(0);\n        RealmChangeListener<Realm> listener = new RealmChangeListener<Realm>() {\n            @Override\n            public void onChange(Realm object) {\n                counter.incrementAndGet();\n            }\n        };\n\n        realm = Realm.getInstance(realmConfig);\n        realm.addChangeListener(listener);\n        realm.removeChangeListener(listener);\n\n        realm.beginTransaction();\n        realm.createObject(AllTypes.class);\n        realm.commitTransaction();\n\n        assertEquals(0, counter.get());\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void addChangeListener_duplicatedListener() {\n        final AtomicInteger counter = new AtomicInteger(0);\n        RealmChangeListener<Realm> listener = new RealmChangeListener<Realm>() {\n            @Override\n            public void onChange(Realm object) {\n                counter.incrementAndGet();\n            }\n        };\n\n        Realm realm = looperThread.getRealm();\n        realm.addChangeListener(listener);\n        realm.addChangeListener(listener);\n        realm.addChangeListener(new RealmChangeListener<Realm>() {\n            @Override\n            public void onChange(Realm object) {\n                assertEquals(1, counter.get());\n                looperThread.testComplete();\n            }\n        });\n\n        realm.beginTransaction();\n        realm.createObject(AllTypes.class);\n        realm.commitTransaction();\n    }\n\n    @Test\n    public void notificationsNumber() throws InterruptedException, ExecutionException {\n        final CountDownLatch isReady = new CountDownLatch(1);\n        final CountDownLatch isRealmOpen = new CountDownLatch(1);\n        final AtomicInteger counter = new AtomicInteger(0);\n        final Looper[] looper = new Looper[1];\n        final RealmChangeListener<Realm> listener = new RealmChangeListener<Realm>() {\n            @Override\n            public void onChange(Realm object) {\n                counter.incrementAndGet();\n            }\n        };\n\n        ExecutorService executorService = Executors.newSingleThreadExecutor();\n        Future<Boolean> future = executorService.submit(new Callable<Boolean>() {\n            @Override\n            public Boolean call() throws Exception {\n                Realm realm = null;\n                try {\n                    Looper.prepare();\n                    looper[0] = Looper.myLooper();\n                    realm = Realm.getInstance(realmConfig);\n                    realm.addChangeListener(listener);\n                    isReady.countDown();\n                    Looper.loop();\n                } finally {\n                    if (realm != null) {\n                        realm.close();\n                        isRealmOpen.countDown();\n                    }\n                }\n                return true;\n            }\n        });\n\n        // Waits until the looper in the background thread is started.\n        TestHelper.awaitOrFail(isReady);\n\n        // Triggers OnRealmChanged on background thread.\n        realm = Realm.getInstance(realmConfig);\n        realm.beginTransaction();\n        Dog dog = realm.createObject(Dog.class);\n        dog.setName(\"Rex\");\n        realm.commitTransaction();\n        realm.close();\n\n        try {\n            future.get(1, TimeUnit.SECONDS);\n        } catch (TimeoutException ignore) {\n        } finally {\n            looper[0].quit();\n        }\n\n        // Waits until the Looper thread is actually closed.\n        TestHelper.awaitOrFail(isRealmOpen);\n\n        assertEquals(1, counter.get());\n        RealmCache.invokeWithGlobalRefCount(realmConfig, new TestHelper.ExpectedCountCallback(0));\n    }\n\n    @Test\n    public void closeClearingHandlerMessages() throws InterruptedException, TimeoutException, ExecutionException {\n        final int TEST_SIZE = 10;\n        final CountDownLatch backgroundLooperStarted = new CountDownLatch(1);\n        final CountDownLatch addHandlerMessages = new CountDownLatch(1);\n\n        ExecutorService executorService = Executors.newSingleThreadExecutor();\n        Future<Boolean> future = executorService.submit(new Callable<Boolean>() {\n            @Override\n            public Boolean call() throws Exception {\n                Looper.prepare(); // Fake background thread with a looper, eg. a IntentService.\n                Realm realm = Realm.getInstance(realmConfig);\n                backgroundLooperStarted.countDown();\n\n                // Random operation in the client code.\n                final RealmResults<Dog> dogs = realm.where(Dog.class).findAll();\n                if (dogs.size() != 0) {\n                    return false;\n                }\n                // Wait for main thread to add update messages.\n                addHandlerMessages.await(TestHelper.VERY_SHORT_WAIT_SECS, TimeUnit.SECONDS);\n\n                // Creates a Handler for the thread now. All message and references for the notification handler will be\n                // cleared once we call close().\n                Handler threadHandler = new Handler(Looper.myLooper());\n                realm.close(); // Close native resources + associated handlers.\n\n                // Looper now reads the update message from the main thread if the Handler was not\n                // cleared. This will cause an IllegalStateException and should not happen.\n                // If it works correctly. The looper will just block on an empty message queue.\n                // This is normal behavior but is bad for testing, so we add a custom quit message\n                // at the end so we can evaluate results faster.\n                // 500 ms delay is to make sure the notification daemon thread gets time to send notification.\n                threadHandler.postDelayed(new Runnable() {\n                    @Override\n                    public void run() {\n                        TestHelper.quitLooperOrFail();\n                    }\n                }, 500);\n\n                try {\n                    Looper.loop();\n                } catch (IllegalStateException e) {\n                    return false;\n                }\n                return true;\n            }\n        });\n\n        // Waits until the looper is started on a background thread.\n        backgroundLooperStarted.await(TestHelper.VERY_SHORT_WAIT_SECS, TimeUnit.SECONDS);\n\n        // Executes a transaction that will trigger a Realm update.\n        Realm realm = Realm.getInstance(realmConfig);\n        realm.beginTransaction();\n        for (int i = 0; i < TEST_SIZE; i++) {\n            Dog dog = realm.createObject(Dog.class);\n            dog.setName(\"Rex \" + i);\n        }\n        realm.commitTransaction();\n        assertEquals(TEST_SIZE, realm.where(Dog.class).count());\n        realm.close();\n        addHandlerMessages.countDown();\n\n        // Checks that messages was properly cleared.\n        // It looks like getting this future sometimes takes a while for some reason. Setting to\n        // 10s. now.\n        Boolean result = future.get(10, TimeUnit.SECONDS);\n        assertTrue(result);\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void globalListener_looperThread_triggeredByLocalCommit() {\n        final AtomicInteger success = new AtomicInteger(0);\n        Realm realm = looperThread.getRealm();\n        realm.addChangeListener(new RealmChangeListener<Realm>() {\n            @Override\n            public void onChange(Realm object) {\n                assertEquals(0, success.getAndIncrement());\n                looperThread.testComplete();\n            }\n        });\n        realm.beginTransaction();\n        realm.createObject(AllTypes.class);\n        realm.commitTransaction();\n        assertEquals(1, success.get());\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void globalListener_looperThread_triggeredByRemoteCommit() {\n        final AtomicInteger success = new AtomicInteger(0);\n        Realm realm = looperThread.getRealm();\n        realm.addChangeListener(new RealmChangeListener<Realm>() {\n            @Override\n            public void onChange(Realm object) {\n                assertEquals(1, success.get());\n                looperThread.testComplete();\n            }\n        });\n        realm.executeTransactionAsync(new Realm.Transaction() {\n            @Override\n            public void execute(Realm realm) {\n                realm.createObject(AllTypes.class);\n            }\n        });\n        assertEquals(0, success.getAndIncrement());\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void emptyCommitTriggerChangeListener() {\n        final RealmChangeListener<Realm> listener = new RealmChangeListener<Realm>() {\n            @Override\n            public void onChange(Realm object) {\n                looperThread.testComplete();\n            }\n        };\n        Realm realm = looperThread.getRealm();\n        realm.addChangeListener(listener);\n        realm.beginTransaction();\n        realm.commitTransaction();\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void addRemoveListenerConcurrency() {\n        final Realm realm = looperThread.getRealm();\n        final AtomicInteger counter1 = new AtomicInteger(0);\n        final AtomicInteger counter2 = new AtomicInteger(0);\n        final AtomicInteger counter3 = new AtomicInteger(0);\n\n        // At least we need 2 listeners existing in the list to make sure\n        // the iterator.next get called.\n\n        // This one will be added when listener2's onChange called.\n        final RealmChangeListener<Realm> listener1 = new RealmChangeListener<Realm>() {\n            @Override\n            public void onChange(Realm object) {\n                // Step 7: Last listener called. Should only be called once.\n                counter1.incrementAndGet();\n\n                // after listener2.onChange\n                // Since duplicated entries will be ignored, we still have:\n                // [listener2, listener1].\n                assertEquals(1, counter1.get());\n                assertEquals(2, counter2.get());\n                assertEquals(1, counter3.get());\n                looperThread.testComplete();\n            }\n        };\n\n        // This one will be existing in the list all the time.\n        final RealmChangeListener<Realm> listener2 = new RealmChangeListener<Realm>() {\n            @Override\n            public void onChange(Realm object) {\n                // Step 3: Listener2 called\n                // Listener state [listener2, listener3, listener1].\n                // Listener 1 will not be called this time around.\n                counter2.incrementAndGet();\n                realm.addChangeListener(listener1);\n            }\n        };\n\n        // This one will be removed after first transaction\n        RealmChangeListener<Realm> listener3 = new RealmChangeListener<Realm>() {\n            @Override\n            public void onChange(Realm object) {\n                // Step 4: Listener3 called\n                // Listener state [listener2, listener1].\n                counter3.incrementAndGet();\n                realm.removeChangeListener(this);\n\n                // Step 5: Asserts proper state\n                // [listener2, listener1].\n                assertEquals(0, counter1.get());\n                assertEquals(1, counter2.get());\n                assertEquals(1, counter3.get());\n\n                // Step 6: Triggers next round of changes on [listener2, listener1].\n                realm.beginTransaction();\n                realm.createObject(AllTypes.class);\n                realm.commitTransaction();\n            }\n        };\n\n        // Step 1: Adds initial listeners\n        // Listener state [listener2, listener3].\n        realm.addChangeListener(listener2);\n        realm.addChangeListener(listener3);\n\n        // Step 2: Triggers change listeners.\n        realm.beginTransaction();\n        realm.createObject(AllTypes.class);\n        realm.commitTransaction();\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void realmNotificationOrder() {\n        // Tests that global notifications are called in the order they are added\n        // Test both ways to check accidental ordering from unordered collections.\n        final AtomicInteger listenerACalled = new AtomicInteger(0);\n        final AtomicInteger listenerBCalled = new AtomicInteger(0);\n        final Realm realm = looperThread.getRealm();\n\n        final RealmChangeListener<Realm> listenerA = new RealmChangeListener<Realm>() {\n\n            @Override\n            public void onChange(Realm object) {\n                int called = listenerACalled.incrementAndGet();\n                if (called == 2) {\n                    assertEquals(2, listenerBCalled.get());\n                    looperThread.testComplete();\n                }\n            }\n        };\n        final RealmChangeListener<Realm> listenerB = new RealmChangeListener<Realm>() {\n            @Override\n            public void onChange(Realm object) {\n                listenerBCalled.incrementAndGet();\n                if (listenerBCalled.get() == 1) {\n                    // 2. Reverse order.\n                    realm.removeAllChangeListeners();\n                    realm.addChangeListener(this);\n                    realm.addChangeListener(listenerA);\n                    // Async transaction to avoid endless recursion.\n                    realm.executeTransactionAsync(new Realm.Transaction() {\n                        @Override\n                        public void execute(Realm realm) {\n                        }\n                    });\n                } else if (listenerBCalled.get() == 2) {\n                    assertEquals(1, listenerACalled.get());\n                }\n            }\n        };\n\n        // 1. Adds initial ordering.\n        realm.addChangeListener(listenerA);\n        realm.addChangeListener(listenerB);\n\n        realm.beginTransaction();\n        realm.commitTransaction();\n    }\n\n    // Tests that if the same configuration is used on 2 different Looper threads that each gets its own Handler. This\n    // prevents commitTransaction from accidentally posting messages to Handlers which might reference a closed Realm.\n    @Test\n    public void doNotUseClosedHandler() throws InterruptedException {\n        final CountDownLatch handlerNotified = new CountDownLatch(1);\n        final CountDownLatch backgroundThread1Started = new CountDownLatch(1);\n        final CountDownLatch backgroundThread2Closed = new CountDownLatch(1);\n\n        // Creates Handler on Thread1 by opening a Realm instance.\n        new Thread(\"thread1\") {\n\n            @Override\n            public void run() {\n                Looper.prepare();\n                final Realm realm = Realm.getInstance(realmConfig);\n                RealmChangeListener<Realm> listener = new RealmChangeListener<Realm>() {\n                    @Override\n                    public void onChange(Realm object) {\n                        realm.close();\n                        handlerNotified.countDown();\n                    }\n                };\n                realm.addChangeListener(listener);\n                backgroundThread1Started.countDown();\n                Looper.loop();\n            }\n        }.start();\n\n        // Creates Handler on Thread2 for the same Realm path and closes the Realm instance again.\n        new Thread(\"thread2\") {\n            @Override\n            public void run() {\n                Looper.prepare();\n                Realm realm = Realm.getInstance(realmConfig);\n                RealmChangeListener<Realm> listener = new RealmChangeListener<Realm>() {\n                    @Override\n                    public void onChange(Realm object) {\n                        fail(\"This handler should not be notified\");\n                    }\n                };\n                realm.addChangeListener(listener);\n                realm.close();\n                backgroundThread2Closed.countDown();\n                Looper.loop();\n            }\n\n        }.start();\n\n        TestHelper.awaitOrFail(backgroundThread1Started);\n        TestHelper.awaitOrFail(backgroundThread2Closed);\n        Realm realm = Realm.getInstance(realmConfig);\n        realm.beginTransaction();\n        realm.commitTransaction();\n        // Any REALM_CHANGED message should now only reach the open Handler on Thread1.\n        try {\n            // TODO: Waiting a few seconds is not a reliable condition. Figure out a better way for this.\n            if (!handlerNotified.await(TestHelper.SHORT_WAIT_SECS,  TimeUnit.SECONDS)) {\n                fail(\"Handler didn't receive message\");\n            }\n        } finally {\n            realm.close();\n        }\n    }\n\n    // Tests that we handle a Looper thread quiting it's looper before it is done executing the current loop ( = Realm.close()\n    // isn't called yet).\n    @Test\n    public void looperThreadQuitsLooperEarly() throws InterruptedException {\n        final CountDownLatch backgroundLooperStartedAndStopped = new CountDownLatch(1);\n        final CountDownLatch mainThreadCommitCompleted = new CountDownLatch(1);\n        final CountDownLatch backgroundThreadStopped = new CountDownLatch(1);\n\n        // Starts background looper and let it hang.\n        ExecutorService executorService = Executors.newSingleThreadExecutor();\n        //noinspection unused\n        final Future<?> future = executorService.submit(new Runnable() {\n            @Override\n            public void run() {\n                Looper.prepare(); // Fake background thread with a looper, eg. a IntentService.\n\n                Realm realm = Realm.getInstance(realmConfig);\n                realm.setAutoRefresh(false);\n                TestHelper.quitLooperOrFail();\n                backgroundLooperStartedAndStopped.countDown();\n                // This will prevent backgroundThreadStopped from being called.\n                TestHelper.awaitOrFail(mainThreadCommitCompleted);\n                realm.close();\n                backgroundThreadStopped.countDown();\n            }\n        });\n\n        // Creates a commit on another thread.\n        TestHelper.awaitOrFail(backgroundLooperStartedAndStopped);\n        Realm realm = Realm.getInstance(realmConfig);\n        RealmLogger logger = TestHelper.getFailureLogger(Log.WARN);\n        RealmLog.add(logger);\n\n        realm.beginTransaction();\n        realm.commitTransaction(); // If the Handler on the background is notified it will trigger a Log warning.\n        mainThreadCommitCompleted.countDown();\n        TestHelper.awaitOrFail(backgroundThreadStopped);\n\n        realm.close();\n        RealmLog.remove(logger);\n    }\n\n    @Test\n    public void handlerThreadShouldReceiveNotification() throws ExecutionException, InterruptedException {\n        final AssertionFailedError[] assertionFailedErrors = new AssertionFailedError[1];\n        final CountDownLatch backgroundThreadReady = new CountDownLatch(1);\n        final CountDownLatch numberOfInvocation = new CountDownLatch(1);\n\n        HandlerThread handlerThread = new HandlerThread(\"handlerThread\");\n        handlerThread.start();\n        Handler handler = new Handler(handlerThread.getLooper());\n        handler.post(new Runnable() {\n            @Override\n            public void run() {\n                try {\n                    assertEquals(\"handlerThread\", Thread.currentThread().getName());\n                } catch (AssertionFailedError e) {\n                    assertionFailedErrors[0] = e;\n                }\n                final Realm backgroundRealm = Realm.getInstance(realmConfig);\n                backgroundRealm.addChangeListener(new RealmChangeListener<Realm>() {\n                    @Override\n                    public void onChange(Realm object) {\n                        backgroundRealm.close();\n                        numberOfInvocation.countDown();\n                    }\n                });\n                backgroundThreadReady.countDown();\n            }\n        });\n        TestHelper.awaitOrFail(backgroundThreadReady);\n        // At this point the background thread started & registered the listener.\n\n        Realm realm = Realm.getInstance(realmConfig);\n        realm.beginTransaction();\n        realm.createObject(AllTypes.class);\n        realm.commitTransaction();\n\n        TestHelper.awaitOrFail(numberOfInvocation);\n        realm.close();\n        handlerThread.quit();\n        if (assertionFailedErrors[0] != null) {\n            throw assertionFailedErrors[0];\n        }\n    }\n\n    @Test\n    @Ignore(\"Fails for some reason when deleting the realm file in tearDown, even though all instances are seemingly closed correctly.\")\n    public void nonLooperThreadShouldNotifyLooperThreadAboutCommit() {\n        final CountDownLatch mainThreadReady = new CountDownLatch(1);\n        final CountDownLatch backgroundThreadClosed = new CountDownLatch(1);\n        final CountDownLatch numberOfInvocation = new CountDownLatch(1);\n        Thread thread = new Thread() {\n            @Override\n            public void run() {\n                TestHelper.awaitOrFail(mainThreadReady);\n                Realm realm = Realm.getInstance(realmConfig);\n                realm.beginTransaction();\n                realm.createObject(AllTypes.class);\n                realm.commitTransaction();\n                realm.close();\n                backgroundThreadClosed.countDown();\n            }\n        };\n        thread.start();\n\n        HandlerThread mainThread = new HandlerThread(\"mainThread\");\n        mainThread.start();\n        Handler handler = new Handler(mainThread.getLooper());\n        handler.post(new Runnable() {\n            @Override\n            public void run() {\n                final Realm mainRealm = Realm.getInstance(realmConfig);\n                mainRealm.addChangeListener(new RealmChangeListener<Realm>() {\n                    @Override\n                    public void onChange(Realm object) {\n                        mainRealm.close();\n                        numberOfInvocation.countDown();\n                    }\n                });\n                mainThreadReady.countDown();\n            }\n        });\n\n        TestHelper.awaitOrFail(numberOfInvocation);\n        TestHelper.awaitOrFail(backgroundThreadClosed);\n        mainThread.quit();\n    }\n\n    // The presence of async RealmResults block any `REALM_CHANGE` notification causing historically the Realm\n    // to advance to the latest version. We make sure in this test that all Realm listeners will be notified\n    // regardless of the presence of an async RealmResults that will delay the `REALM_CHANGE` sometimes.\n    @Test\n    @RunTestInLooperThread\n    public void asyncRealmResultsShouldNotBlockBackgroundCommitNotification() {\n        final Realm realm = looperThread.getRealm();\n        final RealmResults<Dog> dogs = realm.where(Dog.class).findAllAsync();\n        final AtomicBoolean resultsListenerDone = new AtomicBoolean(false);\n        final AtomicBoolean realmListenerDone = new AtomicBoolean(false);\n\n        looperThread.keepStrongReference(dogs);\n        assertTrue(dogs.load());\n        assertEquals(0, dogs.size());\n        dogs.addChangeListener(new RealmChangeListener<RealmResults<Dog>>() {\n            @Override\n            public void onChange(RealmResults<Dog> results) {\n                if (dogs.size() == 2) {\n                    // Results has the latest changes.\n                    resultsListenerDone.set(true);\n                    if (realmListenerDone.get()) {\n                        looperThread.testComplete();\n                    }\n                }\n            }\n        });\n\n        realm.addChangeListener(new RealmChangeListener<Realm>() {\n            @Override\n            public void onChange(Realm element) {\n                if (dogs.size() == 1) {\n                    // Step 2. Creates the second dog.\n                    realm.executeTransactionAsync(new Realm.Transaction() {\n                        @Override\n                        public void execute(Realm realm) {\n                            realm.createObject(Dog.class);\n                        }\n                    });\n                } else if (dogs.size() == 2) {\n                    // Realm listener can see the latest changes.\n                    realmListenerDone.set(true);\n                    if (resultsListenerDone.get()) {\n                        looperThread.testComplete();\n                    }\n                }\n            }\n        });\n\n        // Step 1. Creates the first dog.\n        realm.executeTransactionAsync(new Realm.Transaction() {\n            @Override\n            public void execute(Realm realm) {\n                realm.createObject(Dog.class);\n            }\n        });\n    }\n\n    // The presence of async RealmResults blocks any `REALM_CHANGE` notification . We make sure in this test that all\n    // Realm listeners will be notified regardless of the presence of an async RealmObject. RealmObjects are special\n    // in the sense that once you got a row accessor to that object, it is automatically up to date as soon as you\n    // call advance_read().\n    @Test\n    @RunTestInLooperThread\n    public void asyncRealmObjectShouldNotBlockBackgroundCommitNotification() {\n        final AtomicInteger numberOfRealmCallbackInvocation = new AtomicInteger(0);\n        final CountDownLatch signalClosedRealm = new CountDownLatch(1);\n        final Realm realm = looperThread.getRealm();\n        realm.addChangeListener(new RealmChangeListener<Realm>() {\n            @Override\n            public void onChange(final Realm realm) {\n                switch (numberOfRealmCallbackInvocation.incrementAndGet()) {\n                    case 1: {\n                        // First commit.\n                        Dog dog = realm.where(Dog.class).findFirstAsync();\n                        assertTrue(dog.load());\n                        dog.addChangeListener(new RealmChangeListener<Dog>() {\n                            @Override\n                            public void onChange(Dog dog) {\n                            }\n                        });\n\n                        new Thread() {\n                            @Override\n                            public void run() {\n                                Realm threadRealm = Realm.getInstance(realm.getConfiguration());\n                                threadRealm.beginTransaction();\n                                threadRealm.createObject(Dog.class);\n                                threadRealm.commitTransaction();\n                                threadRealm.close();\n                                signalClosedRealm.countDown();\n                            }\n                        }.start();\n                        break;\n                    }\n                    case 2: {\n                        // Finishes test.\n                        TestHelper.awaitOrFail(signalClosedRealm);\n                        looperThread.testComplete();\n                        break;\n                    }\n                }\n            }\n        });\n\n        looperThread.postRunnable(new Runnable() {\n            @Override\n            public void run() {\n                realm.beginTransaction();\n                realm.createObject(Dog.class);\n                realm.commitTransaction();\n            }\n        });\n    }\n\n    public static class PopulateOneAllTypes implements RunInLooperThread.RunnableBefore {\n\n        @Override\n        public void run(RealmConfiguration realmConfig) {\n            Realm realm = Realm.getInstance(realmConfig);\n            realm.executeTransaction(new Realm.Transaction() {\n                @Override\n                public void execute(Realm realm) {\n                    realm.createObject(AllTypes.class);\n                }\n            });\n            realm.close();\n        }\n    }\n\n    @Test\n    @RunTestInLooperThread(before = PopulateOneAllTypes.class)\n    public void realmListener_realmResultShouldBeSynced() {\n        final Realm realm = looperThread.getRealm();\n        final RealmResults<AllTypes> results = realm.where(AllTypes.class).findAll();\n        assertEquals(1, results.size());\n\n        realm.executeTransactionAsync(new Realm.Transaction() {\n            @Override\n            public void execute(Realm realm) {\n                AllTypes allTypes = realm.where(AllTypes.class).findFirst();\n                assertNotNull(allTypes);\n                allTypes.deleteFromRealm();\n                assertEquals(0, realm.where(AllTypes.class).count());\n            }\n        });\n\n        realm.addChangeListener(new RealmChangeListener<Realm>() {\n            @Override\n            public void onChange(Realm element) {\n                // Changes event triggered by deletion in async transaction.\n                assertEquals(0, realm.where(AllTypes.class).count());\n                assertEquals(0, results.size());\n                looperThread.testComplete();\n            }\n        });\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void accessingSyncRealmResultInsideAsyncResultListener() {\n        final Realm realm = looperThread.getRealm();\n        final AtomicInteger asyncResultCallback = new AtomicInteger(0);\n\n        final RealmResults<AllTypes> syncResults = realm.where(AllTypes.class).findAll();\n\n        RealmResults<AllTypes> results = realm.where(AllTypes.class).findAllAsync();\n        looperThread.keepStrongReference(results);\n        results.addChangeListener(new RealmChangeListener<RealmResults<AllTypes>>() {\n            @Override\n            public void onChange(RealmResults<AllTypes> results) {\n                switch (asyncResultCallback.incrementAndGet()) {\n                    case 1:\n                        // Called when first async query completes.\n                        assertEquals(0, results.size());\n                        realm.executeTransactionAsync(new Realm.Transaction() {\n                            @Override\n                            public void execute(Realm realm) {\n                                realm.createObject(AllTypes.class);\n                            }\n                        });\n                        break;\n\n                    case 2:\n                        // Called after async transaction completes, A REALM_CHANGED event has been triggered,\n                        // async queries have rerun, and listeners are triggered again.\n                        assertEquals(1, results.size());\n                        assertEquals(1, syncResults.size()); // If syncResults is not in sync yet, this will fail.\n                        looperThread.testComplete();\n                        break;\n                }\n            }\n        });\n    }\n\n    // If RealmResults are updated just before their change listener are notified, one change listener might\n    // reference another RealmResults that have been advance_read, but not yet called sync_if_needed.\n    // This can result in accessing detached rows and other errors.\n    @Test\n    @RunTestInLooperThread\n    public void accessingSyncRealmResultsInsideAnotherResultListener() {\n        final Realm realm = looperThread.getRealm();\n        final RealmResults<AllTypes> syncResults1 = realm.where(AllTypes.class).findAll();\n        final RealmResults<AllTypes> syncResults2 = realm.where(AllTypes.class).findAll();\n\n        looperThread.keepStrongReference(syncResults1);\n        syncResults1.addChangeListener(new RealmChangeListener<RealmResults<AllTypes>>() {\n            @Override\n            public void onChange(RealmResults<AllTypes> element) {\n                assertEquals(1, syncResults1.size());\n                assertEquals(1, syncResults2.size()); // If syncResults2 is not in sync yet, this will fail.\n                looperThread.testComplete();\n            }\n        });\n\n        realm.beginTransaction();\n        realm.createObject(AllTypes.class);\n        realm.commitTransaction();\n    }\n\n    @Test\n    @RunTestInLooperThread(threadName = \"IntentService[1]\")\n    public void listenersNotAllowedOnIntentServiceThreads() {\n        final Realm realm = looperThread.getRealm();\n        realm.beginTransaction();\n        AllTypes obj = realm.createObject(AllTypes.class);\n        realm.commitTransaction();\n        RealmResults<AllTypes> results = realm.where(AllTypes.class).findAll();\n\n        // Global listener\n        try {\n            realm.addChangeListener(new RealmChangeListener<Realm>() {\n                @Override\n                public void onChange(Realm element) {\n\n                }\n            });\n            fail();\n        } catch (IllegalStateException ignored) {\n        }\n\n        // RealmResults listener\n        try {\n            results.addChangeListener(new RealmChangeListener<RealmResults<AllTypes>>() {\n                @Override\n                public void onChange(RealmResults<AllTypes> element) {\n\n                }\n            });\n            fail();\n        } catch (IllegalStateException ignored) {\n        }\n\n        // Object listener\n        try {\n            obj.addChangeListener(new RealmChangeListener<RealmModel>() {\n                @Override\n                public void onChange(RealmModel element) {\n\n                }\n            });\n            fail();\n        } catch (IllegalStateException ignored) {\n        }\n\n        looperThread.testComplete();\n    }\n\n    @Test\n    public void listenersNotAllowedOnNonLooperThreads() {\n        realm = Realm.getInstance(realmConfig);\n        realm.beginTransaction();\n        AllTypes obj = realm.createObject(AllTypes.class);\n        realm.commitTransaction();\n        RealmResults<AllTypes> results = realm.where(AllTypes.class).findAll();\n\n        // Global listener\n        try {\n            realm.addChangeListener(new RealmChangeListener<Realm>() {\n                @Override\n                public void onChange(Realm element) {\n\n                }\n            });\n            fail();\n        } catch (IllegalStateException ignored) {\n        }\n\n        // RealmResults listener\n        try {\n            results.addChangeListener(new RealmChangeListener<RealmResults<AllTypes>>() {\n                @Override\n                public void onChange(RealmResults<AllTypes> element) {\n\n                }\n            });\n            fail();\n        } catch (IllegalStateException ignored) {\n        }\n\n        // Object listener\n        try {\n            obj.addChangeListener(new RealmChangeListener<RealmModel>() {\n                @Override\n                public void onChange(RealmModel element) {\n\n                }\n            });\n            fail();\n        } catch (IllegalStateException ignored) {\n        }\n    }\n\n    // Checks that we can attach change listeners to queries involving `limit()` and that\n    // they do the right thing\n    @Test\n    @RunTestInLooperThread\n    public void limitedQueryResult_fromTable_finegrainedListener() {\n        realm = looperThread.getRealm();\n        realm.executeTransaction(r -> {\n            for (int i = 0; i < 5; i++) {\n                r.createObject(AllTypes.class).setColumnLong(i % 5);\n            }\n        });\n        RealmResults<AllTypes> results = realm.where(AllTypes.class)\n                .sort(AllTypes.FIELD_LONG, Sort.DESCENDING) // [4, 4, 3, 3, 2, 2, 1, 1, 0, 0]\n                .distinct(AllTypes.FIELD_LONG) // [4, 3, 2, 1, 0]\n                .limit(2) // [4, 3]\n                .findAll();\n        looperThread.keepStrongReference(results);\n        results.addChangeListener((objects, changeSet) -> {\n            assertEquals(2, objects.size());\n            assertEquals(5, objects.first().getColumnLong());\n            assertEquals(4, objects.last().getColumnLong());\n            assertEquals(1, changeSet.getInsertions().length);\n            assertEquals(0, changeSet.getInsertions()[0]);\n            assertEquals(1, changeSet.getDeletions().length);\n            assertEquals(1, changeSet.getDeletions()[0]);\n            assertEquals(0, changeSet.getChanges().length);\n            looperThread.testComplete();\n        });\n\n        realm.executeTransaction(new Realm.Transaction() {\n            @Override\n            public void execute(Realm realm) {\n                realm.createObject(AllTypes.class).setColumnLong(5);\n            }\n        });\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void limitedQueryResult_fromTable_finegrainedListener_withModifications() {\n        realm = looperThread.getRealm();\n        realm.executeTransaction(r -> {\n            for (int i = 0; i < 5; i++) {\n                r.createObject(AllTypes.class).setColumnLong(i % 5);\n            }\n        });\n        RealmResults<AllTypes> results = realm.where(AllTypes.class)\n                .sort(AllTypes.FIELD_LONG, Sort.DESCENDING) // [4, 4, 3, 3, 2, 2, 1, 1, 0, 0]\n                .distinct(AllTypes.FIELD_LONG) // [4, 3, 2, 1, 0]\n                .limit(2) // [4, 3]\n                .findAll();\n        looperThread.keepStrongReference(results);\n        results.addChangeListener((objects, changeSet) -> {\n            assertEquals(2, objects.size());\n            assertEquals(6, objects.first().getColumnLong());\n            assertEquals(5, objects.last().getColumnLong());\n            assertEquals(1, changeSet.getInsertions().length);\n            assertEquals(0, changeSet.getInsertions()[0]);\n            assertEquals(1, changeSet.getDeletions().length);\n            assertEquals(1, changeSet.getDeletions()[0]);\n            assertEquals(1, changeSet.getChanges().length);\n            assertEquals(1, changeSet.getChanges()[0]);\n            looperThread.testComplete();\n        });\n\n        realm.executeTransaction(new Realm.Transaction() {\n            @Override\n            public void execute(Realm realm) {\n                realm.createObject(AllTypes.class).setColumnLong(6);\n                for (AllTypes obj : realm.where(AllTypes.class).equalTo(AllTypes.FIELD_LONG, 4).findAll()) {\n                    obj.setColumnLong(5);\n                }\n            }\n        });\n    }\n\n    // Checks that we can attach change listeners to queries involving `limit()` and that\n    // they do the right thing\n    @Test\n    @RunTestInLooperThread\n    public void limitedQueryResult_fromTable_simpleChangeListener() {\n        realm = looperThread.getRealm();\n        realm.executeTransaction(r -> {\n            for (int i = 0; i < 5; i++) {\n                r.createObject(AllTypes.class).setColumnLong(i % 5);\n            }\n        });\n        RealmResults<AllTypes> results = realm.where(AllTypes.class)\n                .sort(AllTypes.FIELD_LONG, Sort.DESCENDING) // [4, 4, 3, 3, 2, 2, 1, 1, 0, 0]\n                .distinct(AllTypes.FIELD_LONG) // [4, 3, 2, 1, 0]\n                .limit(2) // [4, 3]\n                .findAll();\n        looperThread.keepStrongReference(results);\n        results.addChangeListener((objects) -> {\n            assertEquals(2, objects.size());\n            assertEquals(5, objects.first().getColumnLong());\n            assertEquals(4, objects.last().getColumnLong());\n            looperThread.testComplete();\n        });\n\n        realm.executeTransaction(new Realm.Transaction() {\n            @Override\n            public void execute(Realm realm) {\n                realm.createObject(AllTypes.class).setColumnLong(5);\n            }\n        });\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void diffedUpdates_ignoredFieldsAreNotListedAsChanged() {\n        realm = looperThread.getRealm();\n        AllJavaTypes obj;\n        realm.beginTransaction();\n        AllJavaTypes childObject = realm.copyToRealm(new AllJavaTypes(1));\n        obj = realm.copyToRealmOrUpdate(new AllJavaTypes(42));\n        obj.setFieldObject(childObject);\n        obj.setFieldList(new RealmList<>(childObject));\n        looperThread.keepStrongReference(obj);\n        realm.commitTransaction();\n        obj.addChangeListener((RealmObjectChangeListener<AllJavaTypes>) (object, changeSet) -> {\n            assertEquals(1, changeSet.getChangedFields().length);\n            assertEquals(\"fieldString\", changeSet.getChangedFields()[0]);\n            looperThread.testComplete();\n        });\n\n        realm.beginTransaction();\n        AllJavaTypes updatedObj = new AllJavaTypes(42);\n        updatedObj.setFieldString(\"updated\");\n        updatedObj.setFieldObject(childObject);\n        updatedObj.setFieldList(new RealmList<>(childObject));\n        realm.copyToRealmOrUpdate(updatedObj, ImportFlag.CHECK_SAME_VALUES_BEFORE_SET);\n        realm.commitTransaction();\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/ObjectChangeSetTests.java",
    "content": "/*\n * Copyright 2017 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\npackage io.realm;\n\nimport androidx.test.ext.junit.runners.AndroidJUnit4;\n\nimport org.junit.Rule;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\n\nimport java.util.Arrays;\nimport java.util.Date;\nimport java.util.List;\nimport java.util.concurrent.atomic.AtomicBoolean;\nimport java.util.concurrent.atomic.AtomicInteger;\n\nimport io.realm.entities.AllTypes;\nimport io.realm.entities.Dog;\nimport io.realm.entities.Owner;\nimport io.realm.rule.RunInLooperThread;\nimport io.realm.rule.RunTestInLooperThread;\n\nimport static junit.framework.Assert.assertEquals;\nimport static junit.framework.Assert.assertNotNull;\nimport static junit.framework.Assert.fail;\nimport static junit.framework.TestCase.assertFalse;\nimport static org.junit.Assert.assertNull;\nimport static org.junit.Assert.assertTrue;\n\n\n// Tests for detailed change notification on RealmObject.\n@RunWith(AndroidJUnit4.class)\npublic class ObjectChangeSetTests {\n\n    @Rule\n    public final RunInLooperThread looperThread = new RunInLooperThread();\n\n    public static class PopulateOneAllTypes implements RunInLooperThread.RunnableBefore {\n\n        @Override\n        public void run(RealmConfiguration realmConfig) {\n            Realm realm = Realm.getInstance(realmConfig);\n            realm.executeTransaction(new Realm.Transaction() {\n                @Override\n                public void execute(Realm realm) {\n                    AllTypes allTypes = realm.createObject(AllTypes.class);\n                    allTypes.setColumnRealmObject(realm.createObject(Dog.class));\n                    allTypes.getColumnRealmList().add(realm.createObject(Dog.class));\n                }\n            });\n            realm.close();\n        }\n    }\n\n    private void checkDeleted(AllTypes allTypes) {\n        allTypes.addChangeListener(new RealmObjectChangeListener<AllTypes>() {\n            @Override\n            public void onChange(AllTypes object, ObjectChangeSet changeSet) {\n                assertEquals(0, changeSet.getChangedFields().length);\n                assertFalse(object.isValid());\n                assertTrue(changeSet.isDeleted());\n                looperThread.testComplete();\n            }\n        });\n        looperThread.keepStrongReference(allTypes);\n    }\n\n    private void checkChangedField(AllTypes allTypes, final String... fieldNames) {\n        assertNotNull(fieldNames);\n        allTypes.addChangeListener(new RealmObjectChangeListener<RealmModel>() {\n            @Override\n            public void onChange(RealmModel object, ObjectChangeSet changeSet) {\n                assertEquals(fieldNames.length, changeSet.getChangedFields().length);\n                List<String> changedFields = Arrays.asList(changeSet.getChangedFields());\n                for (String name : fieldNames) {\n                    assertTrue(changeSet.isFieldChanged(name));\n                    assertFalse(changeSet.isFieldChanged(name + \"NotThere\"));\n                    if (!changedFields.contains(name)) {\n                        fail(\"Cannot find field \" + name + \" in field changes.\");\n                    }\n                }\n                looperThread.testComplete();\n            }\n        });\n        looperThread.keepStrongReference(allTypes);\n    }\n\n    private void listenerShouldNotBeCalled(AllTypes allTypes) {\n        allTypes.addChangeListener(new RealmObjectChangeListener<RealmModel>() {\n            @Override\n            public void onChange(RealmModel object, ObjectChangeSet changeSet) {\n                fail();\n            }\n        });\n        looperThread.postRunnableDelayed(new Runnable() {\n            @Override\n            public void run() {\n                looperThread.testComplete();\n            }\n        }, 100);\n    }\n\n    @Test\n    @RunTestInLooperThread(before = PopulateOneAllTypes.class)\n    public void objectDeleted() {\n        Realm realm = looperThread.getRealm();\n        AllTypes allTypes = realm.where(AllTypes.class).findFirst();\n        checkDeleted(allTypes);\n        realm.beginTransaction();\n        allTypes.deleteFromRealm();\n        realm.commitTransaction();\n    }\n\n    @Test\n    @RunTestInLooperThread(before = PopulateOneAllTypes.class)\n    public void changeLongField() {\n        Realm realm = looperThread.getRealm();\n        AllTypes allTypes = realm.where(AllTypes.class).findFirst();\n        checkChangedField(allTypes, AllTypes.FIELD_LONG);\n        realm.beginTransaction();\n        allTypes.setColumnLong(42);\n        realm.commitTransaction();\n    }\n\n    @Test\n    @RunTestInLooperThread(before = PopulateOneAllTypes.class)\n    public void changeStringField() {\n        Realm realm = looperThread.getRealm();\n        AllTypes allTypes = realm.where(AllTypes.class).findFirst();\n        checkChangedField(allTypes, AllTypes.FIELD_STRING);\n        realm.beginTransaction();\n        allTypes.setColumnString(\"42\");\n        realm.commitTransaction();\n    }\n\n    @Test\n    @RunTestInLooperThread(before = PopulateOneAllTypes.class)\n    public void changeFloatField() {\n        Realm realm = looperThread.getRealm();\n        AllTypes allTypes = realm.where(AllTypes.class).findFirst();\n        checkChangedField(allTypes, AllTypes.FIELD_FLOAT);\n        realm.beginTransaction();\n        allTypes.setColumnFloat(42.0f);\n        realm.commitTransaction();\n    }\n\n    @Test\n    @RunTestInLooperThread(before = PopulateOneAllTypes.class)\n    public void changeDoubleField() {\n        Realm realm = looperThread.getRealm();\n        AllTypes allTypes = realm.where(AllTypes.class).findFirst();\n        checkChangedField(allTypes, AllTypes.FIELD_DOUBLE);\n        realm.beginTransaction();\n        allTypes.setColumnDouble(42.0d);\n        realm.commitTransaction();\n    }\n\n    @Test\n    @RunTestInLooperThread(before = PopulateOneAllTypes.class)\n    public void changeBooleanField() {\n        Realm realm = looperThread.getRealm();\n        AllTypes allTypes = realm.where(AllTypes.class).findFirst();\n        checkChangedField(allTypes, AllTypes.FIELD_BOOLEAN);\n        realm.beginTransaction();\n        allTypes.setColumnBoolean(true);\n        realm.commitTransaction();\n    }\n\n    @Test\n    @RunTestInLooperThread(before = PopulateOneAllTypes.class)\n    public void changeDateField() {\n        Realm realm = looperThread.getRealm();\n        AllTypes allTypes = realm.where(AllTypes.class).findFirst();\n        checkChangedField(allTypes, AllTypes.FIELD_DATE);\n        realm.beginTransaction();\n        allTypes.setColumnDate(new Date());\n        realm.commitTransaction();\n    }\n\n    @Test\n    @RunTestInLooperThread(before = PopulateOneAllTypes.class)\n    public void changeBinaryField() {\n        Realm realm = looperThread.getRealm();\n        AllTypes allTypes = realm.where(AllTypes.class).findFirst();\n        checkChangedField(allTypes, AllTypes.FIELD_BINARY);\n        realm.beginTransaction();\n        allTypes.setColumnBinary(new byte[] { 42 });\n        realm.commitTransaction();\n    }\n\n    @Test\n    @RunTestInLooperThread(before = PopulateOneAllTypes.class)\n    public void changeLinkFieldSetNewObject() {\n        Realm realm = looperThread.getRealm();\n        AllTypes allTypes = realm.where(AllTypes.class).findFirst();\n        checkChangedField(allTypes, AllTypes.FIELD_REALMOBJECT);\n        realm.beginTransaction();\n        allTypes.setColumnRealmObject(realm.createObject(Dog.class));\n        realm.commitTransaction();\n    }\n\n    @Test\n    @RunTestInLooperThread(before = PopulateOneAllTypes.class)\n    public void changeLinkFieldSetNull() {\n        Realm realm = looperThread.getRealm();\n        AllTypes allTypes = realm.where(AllTypes.class).findFirst();\n        checkChangedField(allTypes, AllTypes.FIELD_REALMOBJECT);\n        realm.beginTransaction();\n        allTypes.setColumnRealmObject(null);\n        realm.commitTransaction();\n    }\n\n    @Test\n    @RunTestInLooperThread(before = PopulateOneAllTypes.class)\n    public void changeLinkFieldRemoveObject() {\n        Realm realm = looperThread.getRealm();\n        AllTypes allTypes = realm.where(AllTypes.class).findFirst();\n        checkChangedField(allTypes, AllTypes.FIELD_REALMOBJECT);\n        realm.beginTransaction();\n        allTypes.getColumnRealmObject().deleteFromRealm();\n        realm.commitTransaction();\n    }\n\n    @Test\n    @RunTestInLooperThread(before = PopulateOneAllTypes.class)\n    public void changeLinkFieldOriginalObjectChanged_notTrigger() {\n        Realm realm = looperThread.getRealm();\n        AllTypes allTypes = realm.where(AllTypes.class).findFirst();\n        listenerShouldNotBeCalled(allTypes);\n        realm.beginTransaction();\n        allTypes.getColumnRealmObject().setAge(42);\n        realm.commitTransaction();\n    }\n\n    @Test\n    @RunTestInLooperThread(before = PopulateOneAllTypes.class)\n    public void changeLinkListAddObject() {\n        Realm realm = looperThread.getRealm();\n        AllTypes allTypes = realm.where(AllTypes.class).findFirst();\n        checkChangedField(allTypes, AllTypes.FIELD_REALMLIST);\n        realm.beginTransaction();\n        allTypes.getColumnRealmList().add(realm.createObject(Dog.class));\n        realm.commitTransaction();\n    }\n\n    @Test\n    @RunTestInLooperThread(before = PopulateOneAllTypes.class)\n    public void changeLinkListClear() {\n        Realm realm = looperThread.getRealm();\n        AllTypes allTypes = realm.where(AllTypes.class).findFirst();\n        checkChangedField(allTypes, AllTypes.FIELD_REALMLIST);\n        realm.beginTransaction();\n        allTypes.getColumnRealmList().clear();\n        realm.commitTransaction();\n    }\n\n    @Test\n    @RunTestInLooperThread(before = PopulateOneAllTypes.class)\n    public void changeAllFields() {\n        Realm realm = looperThread.getRealm();\n        AllTypes allTypes = realm.where(AllTypes.class).findFirst();\n        checkChangedField(allTypes, AllTypes.FIELD_LONG, AllTypes.FIELD_REALMLIST, AllTypes.FIELD_REALMOBJECT,\n                AllTypes.FIELD_DOUBLE, AllTypes.FIELD_FLOAT, AllTypes.FIELD_STRING, AllTypes.FIELD_BOOLEAN,\n                AllTypes.FIELD_BINARY, AllTypes.FIELD_DATE);\n        realm.beginTransaction();\n        allTypes.setColumnLong(42);\n        allTypes.getColumnRealmList().add(realm.createObject(Dog.class));\n        allTypes.setColumnRealmObject(realm.createObject(Dog.class));\n        allTypes.setColumnDouble(42.0d);\n        allTypes.setColumnFloat(42.0f);\n        allTypes.setColumnString(\"42\");\n        allTypes.setColumnBoolean(true);\n        allTypes.setColumnBinary(new byte[] { 42 });\n        allTypes.setColumnDate(new Date());\n        realm.commitTransaction();\n    }\n\n    // Relevant to https://github.com/realm/realm-java/issues/4437\n    // When the object listener triggered at the 2nd time, the local ref m_field_names_array has not been reset and it\n    // contains an invalid local ref which has been released before.\n    @Test\n    @RunTestInLooperThread(before = PopulateOneAllTypes.class)\n    public void changeDifferentFieldOneAfterAnother() {\n        Realm realm = looperThread.getRealm();\n        AllTypes allTypes = realm.where(AllTypes.class).findFirst();\n        final AtomicBoolean stringChanged = new AtomicBoolean(false);\n        final AtomicBoolean longChanged = new AtomicBoolean(false);\n        final AtomicBoolean floatChanged = new AtomicBoolean(false);\n\n        allTypes.addChangeListener(new RealmObjectChangeListener<RealmModel>() {\n            @Override\n            public void onChange(RealmModel object, ObjectChangeSet changeSet) {\n                assertEquals(1, changeSet.getChangedFields().length);\n                if (changeSet.isFieldChanged(AllTypes.FIELD_STRING)) {\n                    assertFalse(stringChanged.get());\n                    stringChanged.set(true);\n                } else if (changeSet.isFieldChanged(AllTypes.FIELD_LONG)) {\n                    assertFalse(longChanged.get());\n                    longChanged.set(true);\n                } else if (changeSet.isFieldChanged(AllTypes.FIELD_FLOAT)) {\n                    assertTrue(stringChanged.get());\n                    assertTrue(longChanged.get());\n                    assertFalse(floatChanged.get());\n                    floatChanged.set(true);\n                    looperThread.testComplete();\n                } else {\n                    fail();\n                }\n            }\n        });\n\n        realm.beginTransaction();\n        allTypes.setColumnString(\"42\");\n        realm.commitTransaction();\n\n        realm.beginTransaction();\n        allTypes.setColumnLong(42);\n        realm.commitTransaction();\n\n        realm.beginTransaction();\n        allTypes.setColumnFloat(42.0f);\n        realm.commitTransaction();\n    }\n\n    @Test\n    @RunTestInLooperThread(before = PopulateOneAllTypes.class)\n    public void findFirstAsync_changeSetIsNullWhenQueryReturns() {\n        Realm realm = looperThread.getRealm();\n        AllTypes allTypes = realm.where(AllTypes.class).findFirstAsync();\n        allTypes.addChangeListener(new RealmObjectChangeListener<AllTypes>() {\n            @Override\n            public void onChange(AllTypes object, ObjectChangeSet changeSet) {\n                assertTrue(object.isValid());\n                assertNull(changeSet);\n                looperThread.testComplete();\n            }\n        });\n    }\n\n    // Due to the fact that Object Store disallow adding notification block inside a transaction, the pending query\n    // for findFirstAsync needs to be executed first then move the listener from collection to the object before begin\n    // transaction.\n    @Test\n    @RunTestInLooperThread(before = PopulateOneAllTypes.class)\n    public void findFirstAsync_queryExecutedByLocalCommit() {\n        Realm realm = looperThread.getRealm();\n        final AtomicInteger listenerCounter = new AtomicInteger(0);\n        final AllTypes allTypes = realm.where(AllTypes.class).findFirstAsync();\n        allTypes.addChangeListener(new RealmObjectChangeListener<AllTypes>() {\n            @Override\n            public void onChange(AllTypes object, ObjectChangeSet changeSet) {\n                int counter = listenerCounter.getAndIncrement();\n                switch (counter) {\n                    case 0:\n                        assertTrue(object.isValid());\n                        assertNull(changeSet);\n                        break;\n                    case 1:\n                        assertFalse(object.isValid());\n                        assertTrue(changeSet.isDeleted());\n                        assertEquals(0, changeSet.getChangedFields().length);\n                        looperThread.testComplete();\n                        break;\n                    default:\n                        fail();\n                }\n            }\n        });\n        realm.beginTransaction();\n        allTypes.deleteFromRealm();\n        realm.commitTransaction();\n    }\n\n    // When there are more than 512 fields change, the JNI local ref table size limitation may be reached.\n    @Test\n    @RunTestInLooperThread\n    public void moreFieldsChangedThanLocalRefTableSize() {\n        final String CLASS_NAME = \"ManyFields\";\n        final int FIELD_COUNT = 1024;\n        RealmConfiguration config = looperThread.createConfiguration(\"many_fields\");\n        final DynamicRealm realm = DynamicRealm.getInstance(config);\n\n        realm.beginTransaction();\n        RealmSchema schema = realm.getSchema();\n        RealmObjectSchema objectSchema = schema.create(CLASS_NAME);\n        for (int i = 0; i < FIELD_COUNT; i++) {\n            objectSchema.addField(\"field\" + i, int.class);\n        }\n        DynamicRealmObject obj = realm.createObject(CLASS_NAME);\n        realm.commitTransaction();\n\n        obj.addChangeListener(new RealmObjectChangeListener<DynamicRealmObject>() {\n            @Override\n            public void onChange(DynamicRealmObject object, ObjectChangeSet changeSet) {\n                assertEquals(FIELD_COUNT, changeSet.getChangedFields().length);\n                realm.close();\n                looperThread.testComplete();\n            }\n        });\n\n        realm.beginTransaction();\n        for (int i = 0; i < FIELD_COUNT; i++) {\n            obj.setInt(\"field\" + i, 42);\n        }\n        realm.commitTransaction();\n    }\n\n    // For https://github.com/realm/realm-java/issues/4474\n    @Test\n    @RunTestInLooperThread\n    public void allParentObjectShouldBeInChangeSet() {\n        Realm realm = looperThread.getRealm();\n\n        realm.beginTransaction();\n        Owner owner = realm.createObject(Owner.class);\n        Dog dog1 = realm.createObject(Dog.class);\n        dog1.setOwner(owner);\n        dog1.setHasTail(true);\n        owner.getDogs().add(dog1);\n        Dog dog2 = realm.createObject(Dog.class);\n        dog2.setOwner(owner);\n        dog2.setHasTail(true);\n        owner.getDogs().add(dog2);\n        Dog dog3 = realm.createObject(Dog.class);\n        dog3.setOwner(owner);\n        dog3.setHasTail(true);\n        owner.getDogs().add(dog3);\n\n        realm.commitTransaction();\n\n        RealmResults<Dog> dogs = realm.where(Dog.class).equalTo(Dog.FIELD_HAS_TAIL, true).findAll();\n        looperThread.keepStrongReference(dogs);\n        dogs.addChangeListener(new OrderedRealmCollectionChangeListener<RealmResults<Dog>>() {\n            @Override\n            public void onChange(RealmResults<Dog> collection, OrderedCollectionChangeSet changeSet) {\n                assertEquals(1, changeSet.getDeletions().length);\n                assertEquals(0, changeSet.getInsertions().length);\n\n                assertEquals(1, changeSet.getChangeRanges().length);\n                assertEquals(0, changeSet.getChangeRanges()[0].startIndex);\n                assertEquals(2, changeSet.getChangeRanges()[0].length);\n\n                looperThread.testComplete();\n            }\n        });\n\n        realm.beginTransaction();\n        dog3.setHasTail(false);\n        realm.commitTransaction();\n        looperThread.testComplete();\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/OrderedCollectionChangeSetTests.java",
    "content": "/*\n * Copyright 2017 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\npackage io.realm;\n\nimport org.junit.After;\nimport org.junit.Before;\nimport org.junit.Rule;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.junit.runners.Parameterized;\n\nimport java.util.Arrays;\nimport java.util.List;\n\nimport javax.annotation.Nullable;\n\nimport io.realm.entities.Dog;\nimport io.realm.entities.Owner;\nimport io.realm.rule.RunInLooperThread;\nimport io.realm.rule.RunTestInLooperThread;\n\nimport static junit.framework.Assert.assertEquals;\nimport static junit.framework.Assert.assertNotNull;\nimport static junit.framework.Assert.assertSame;\nimport static junit.framework.Assert.fail;\nimport static org.junit.Assert.assertArrayEquals;\nimport static org.junit.Assert.assertNotEquals;\nimport static org.junit.Assert.assertTrue;\n\n\n// Tests for the ordered collection fine grained notifications for both RealmResults and RealmList.\n@SuppressWarnings(\"ConstantConditions\") // Suppress the null return value warnings for RealmList.get()\n@RunWith(Parameterized.class)\npublic class OrderedCollectionChangeSetTests {\n\n    private enum ObservablesType {\n        REALM_RESULTS, REALM_LIST\n    }\n\n    private interface ChangesCheck {\n        void check(OrderedCollectionChangeSet changeSet);\n    }\n\n    @Rule\n    public final TestRealmConfigurationFactory configFactory = new TestRealmConfigurationFactory();\n    @Rule\n    public final RunInLooperThread looperThread = new RunInLooperThread();\n\n    private final ObservablesType type;\n\n    @Parameterized.Parameters(name = \"{0}\")\n    public static List<ObservablesType> data() {\n        return Arrays.asList(ObservablesType.values());\n    }\n\n    public OrderedCollectionChangeSetTests(ObservablesType type) {\n        this.type = type;\n    }\n\n    @Before\n    public void setUp() {\n    }\n\n    @After\n    public void tearDown() {\n    }\n\n    private void populateData(Realm realm, int testSize) {\n        Owner owner = null;\n        realm.beginTransaction();\n        if (type == ObservablesType.REALM_LIST) {\n            owner = realm.createObject(Owner.class);\n        }\n        for (int i = 0; i < testSize; i++) {\n            Dog dog = realm.createObject(Dog.class);\n            dog.setAge(i);\n            if (type == ObservablesType.REALM_LIST) {\n                owner.getDogs().add(dog);\n            }\n        }\n        realm.commitTransaction();\n    }\n\n    // The args should be [startIndex1, length1, startIndex2, length2, ...]\n    private void checkRanges(OrderedCollectionChangeSet.Range[] ranges, int... indexAndLen) {\n        if ((indexAndLen.length % 2 != 0)) {\n            fail(\"The 'indexAndLen' array length is not an even number.\");\n        }\n        if (ranges.length != indexAndLen.length / 2) {\n            fail(\"The lengths of 'ranges' and 'indexAndLen' don't match.\");\n        }\n        for (int i = 0; i < ranges.length; i++) {\n            OrderedCollectionChangeSet.Range range = ranges[i];\n            int startIndex = indexAndLen[i * 2];\n            int length = indexAndLen[i * 2 + 1];\n            if (range.startIndex != startIndex || range.length != length) {\n                fail(\"Range at index \" + i + \" doesn't match start index \" + startIndex + \" length \" + length + \".\");\n            }\n        }\n    }\n\n    // Deletes Dogs objects which's columnLong is in the indices array.\n    private void deleteObjects(Realm realm, int... indices) {\n        for (int index : indices) {\n            realm.where(Dog.class).equalTo(Dog.FIELD_AGE, index).findFirst().deleteFromRealm();\n        }\n    }\n\n    // Creates Dogs objects with columnLong set to the value elements in indices array.\n    private void createObjects(Realm realm, int... indices) {\n        for (int index : indices) {\n            Dog dog = realm.createObject(Dog.class);\n            dog.setAge(index);\n            if (type == ObservablesType.REALM_LIST) {\n                Owner owner = realm.where(Owner.class).findFirst();\n                assertNotNull(owner);\n                RealmList<Dog> dogs = owner.getDogs();\n                boolean added = false;\n                // Insert the newly created dog to the RealmList by the order of age.\n                for (int i = 0; i < dogs.size(); i++) {\n                    if (dog.getAge() <= dogs.get(i).getAge()) {\n                        dogs.add(i, dog);\n                        added = true;\n                        break;\n                    }\n                }\n                if (!added) {\n                    dogs.add(dog);\n                }\n            }\n        }\n    }\n\n    // Modifies Dogs objects which's columnLong is in the indices array.\n    private void modifyObjects(Realm realm, int... indices) {\n        for (int index : indices) {\n            Dog obj = realm.where(Dog.class).equalTo(Dog.FIELD_AGE, index).findFirst();\n            assertNotNull(obj);\n            obj.setName(\"modified\");\n        }\n    }\n\n    private void moveObjects(Realm realm, int originAge, int newAge) {\n        if (type == ObservablesType.REALM_LIST) {\n            // For RealmList we need to:\n            // 1. Find the object by the original age and move it to the new place where it should be with the new age\n            //    set -- the RealmList is sorted by age.\n            // 2. Set the object's age with new value.\n            RealmList<Dog> dogs = realm.where(Owner.class).findFirst().getDogs();\n            int originIdx = -1;\n            int newIdx = -1;\n            for (int i = 0; i < dogs.size(); i++) {\n                Dog dog = dogs.get(i);\n                assertNotNull(dog);\n                if (dog.getAge() == originAge) {\n                    originIdx = i;\n                    break;\n                }\n            }\n            assertNotEquals(-1, originIdx);\n            for (int i = 0; i < dogs.size(); i++) {\n                if (i == originIdx) {\n                    // not precise code, but good enough for testing.\n                    continue;\n                }\n                if (newAge <= dogs.get(i).getAge()) {\n                    newIdx = i;\n                    break;\n                }\n            }\n            if (newIdx == -1) {\n                newIdx = dogs.size() - 1;\n            }\n            dogs.get(originIdx).setAge(newAge);\n            dogs.move(originIdx, newIdx);\n        } else {\n            // Since the RealmResults is sorted by age, just simply set the object's age with new value.\n            realm.where(Dog.class).equalTo(Dog.FIELD_AGE, originAge).findFirst().setAge(newAge);\n        }\n    }\n\n    private OrderedRealmCollection<Dog> getTestingCollection(Realm realm) {\n        switch (type) {\n            case REALM_RESULTS:\n                RealmResults<Dog> results = realm.where(Dog.class).sort(Dog.FIELD_AGE).findAll();\n                looperThread.keepStrongReference(results);\n                return results;\n            case REALM_LIST:\n                RealmList<Dog> list = realm.where(Owner.class).findFirst().getDogs();\n                looperThread.keepStrongReference(list);\n                return list;\n        }\n        fail();\n        return null;\n    }\n\n    private void registerCheckListener(Realm realm, final ChangesCheck changesCheck) {\n        switch (type) {\n            case REALM_RESULTS:\n                RealmResults<Dog> results = (RealmResults<Dog>) getTestingCollection(realm);\n                results.addChangeListener(new OrderedRealmCollectionChangeListener<RealmResults<Dog>>() {\n                    @Override\n                    public void onChange(RealmResults<Dog> collection, @Nullable OrderedCollectionChangeSet changeSet) {\n                        changesCheck.check(changeSet);\n                    }\n                });\n                break;\n            case REALM_LIST:\n                RealmList<Dog> list = (RealmList<Dog>) getTestingCollection(realm);\n                looperThread.keepStrongReference(list);\n                list.addChangeListener(new OrderedRealmCollectionChangeListener<RealmList<Dog>>() {\n                    @Override\n                    public void onChange(RealmList<Dog> collection, @Nullable OrderedCollectionChangeSet changeSet) {\n                        changesCheck.check(changeSet);\n                    }\n                });\n                break;\n        }\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void deletion() {\n        Realm realm = looperThread.getRealm();\n        populateData(realm, 10);\n\n        final ChangesCheck changesCheck = new ChangesCheck() {\n            @Override\n            public void check(OrderedCollectionChangeSet changeSet) {\n                checkRanges(changeSet.getDeletionRanges(),\n                        0, 1,\n                        2, 3,\n                        8, 2);\n                assertArrayEquals(changeSet.getDeletions(), new int[] {0, 2, 3, 4, 8, 9});\n                assertEquals(0, changeSet.getChangeRanges().length);\n                assertEquals(0, changeSet.getInsertionRanges().length);\n                assertEquals(0, changeSet.getChanges().length);\n                assertEquals(0, changeSet.getInsertions().length);\n                looperThread.testComplete();\n            }\n        };\n\n        registerCheckListener(realm, changesCheck);\n\n        realm.beginTransaction();\n        deleteObjects(realm,\n                0,\n                2, 3, 4,\n                8, 9);\n        realm.commitTransaction();\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void insertion() {\n        Realm realm = looperThread.getRealm();\n        populateData(realm, 0); // We need to create the owner.\n        realm.beginTransaction();\n        createObjects(realm, 0, 2, 5, 6, 7, 9);\n        realm.commitTransaction();\n\n        ChangesCheck changesCheck = new ChangesCheck() {\n            @Override\n            public void check(OrderedCollectionChangeSet changeSet) {\n                checkRanges(changeSet.getInsertionRanges(),\n                        1, 1,\n                        3, 2,\n                        8, 1);\n                assertArrayEquals(changeSet.getInsertions(), new int[] {1, 3, 4, 8});\n                assertEquals(0, changeSet.getChangeRanges().length);\n                assertEquals(0, changeSet.getDeletionRanges().length);\n                assertEquals(0, changeSet.getChanges().length);\n                assertEquals(0, changeSet.getDeletions().length);\n                looperThread.testComplete();\n            }\n        };\n        registerCheckListener(realm, changesCheck);\n\n        realm.beginTransaction();\n        createObjects(realm,\n                1,\n                3, 4,\n                8);\n        realm.commitTransaction();\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void changes() {\n        Realm realm = looperThread.getRealm();\n        populateData(realm, 10);\n        ChangesCheck changesCheck = new ChangesCheck() {\n            @Override\n            public void check(OrderedCollectionChangeSet changeSet) {\n                checkRanges(changeSet.getChangeRanges(),\n                        0, 1,\n                        2, 3,\n                        8, 2);\n                assertArrayEquals(changeSet.getChanges(), new int[] {0, 2, 3, 4, 8, 9});\n                assertEquals(0, changeSet.getInsertionRanges().length);\n                assertEquals(0, changeSet.getDeletionRanges().length);\n                assertEquals(0, changeSet.getInsertions().length);\n                assertEquals(0, changeSet.getDeletions().length);\n                looperThread.testComplete();\n            }\n        };\n\n        registerCheckListener(realm, changesCheck);\n\n        realm.beginTransaction();\n        modifyObjects(realm,\n                0,\n                2, 3, 4,\n                8, 9);\n        realm.commitTransaction();\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void moves() {\n        Realm realm = looperThread.getRealm();\n        populateData(realm, 10);\n        ChangesCheck changesCheck = new ChangesCheck() {\n            @Override\n            public void check(OrderedCollectionChangeSet changeSet) {\n                checkRanges(changeSet.getDeletionRanges(),\n                        0, 1,\n                        9, 1);\n                assertArrayEquals(changeSet.getDeletions(), new int[] {0, 9});\n                checkRanges(changeSet.getInsertionRanges(),\n                        0, 1,\n                        9, 1);\n                assertArrayEquals(changeSet.getInsertions(), new int[] {0, 9});\n                assertEquals(0, changeSet.getChangeRanges().length);\n                assertEquals(0, changeSet.getChanges().length);\n                looperThread.testComplete();\n            }\n        };\n        registerCheckListener(realm, changesCheck);\n\n        realm.beginTransaction();\n        moveObjects(realm, 0, 10);\n        moveObjects(realm, 9, 0);\n        realm.commitTransaction();\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void realmAny_changes() {\n        Realm realm = looperThread.getRealm();\n        populateData(realm, 10);\n        ChangesCheck changesCheck = new ChangesCheck() {\n            @Override\n            public void check(OrderedCollectionChangeSet changeSet) {\n                checkRanges(changeSet.getDeletionRanges(),\n                        0, 2,\n                        5, 1);\n                assertArrayEquals(changeSet.getDeletions(), new int[] {0, 1, 5});\n\n                checkRanges(changeSet.getInsertionRanges(),\n                        0, 2,\n                        9, 2);\n                assertArrayEquals(changeSet.getInsertions(), new int[] {0, 1, 9, 10});\n\n                checkRanges(changeSet.getChangeRanges(),\n                        3, 2,\n                        8, 1);\n                assertArrayEquals(changeSet.getChanges(), new int[] {3, 4, 8});\n\n                looperThread.testComplete();\n            }\n        };\n\n        registerCheckListener(realm, changesCheck);\n\n        realm.beginTransaction();\n        createObjects(realm, 11, 12, -1, -2);\n        deleteObjects(realm, 0, 1, 5);\n        modifyObjects(realm, 12, 3, 4, 9);\n        realm.commitTransaction();\n        // After transaction, '*' means the object has been modified. 12 has been modified as well, but it is created\n        // and modified in the same transaction, should not be counted in the changes range.\n        // [-1, -2, 2, *3, *4, 6, 7, 8, *9, 11, 12]\n    }\n\n    // Change some objects then delete them. Only deletion changes should be sent.\n    @Test\n    @RunTestInLooperThread\n    public void changes_then_delete() {\n        Realm realm = looperThread.getRealm();\n        populateData(realm, 10);\n        ChangesCheck changesCheck = new ChangesCheck() {\n            @Override\n            public void check(OrderedCollectionChangeSet changeSet) {\n                checkRanges(changeSet.getDeletionRanges(),\n                        0, 2,\n                        5, 1);\n                assertArrayEquals(changeSet.getDeletions(), new int[] {0, 1, 5});\n\n                assertEquals(0, changeSet.getInsertionRanges().length);\n                assertEquals(0, changeSet.getInsertions().length);\n                assertEquals(0, changeSet.getChangeRanges().length);\n                assertEquals(0, changeSet.getChanges().length);\n\n                looperThread.testComplete();\n            }\n        };\n        registerCheckListener(realm, changesCheck);\n\n        realm.beginTransaction();\n        modifyObjects(realm, 0, 1, 5);\n        deleteObjects(realm, 0, 1, 5);\n        realm.commitTransaction();\n    }\n\n    // Insert some objects then delete them in the same transaction, the listener should not be triggered.\n    @Test\n    @RunTestInLooperThread\n    public void insert_then_delete() {\n        Realm realm = looperThread.getRealm();\n        populateData(realm, 10);\n        ChangesCheck changesCheck = new ChangesCheck() {\n            @Override\n            public void check(OrderedCollectionChangeSet changeSet) {\n                fail(\"The listener should not be triggered since the collection has no changes compared with before.\");\n            }\n        };\n\n        registerCheckListener(realm, changesCheck);\n\n        looperThread.postRunnableDelayed(new Runnable() {\n            @Override\n            public void run() {\n                looperThread.testComplete();\n            }\n        }, 1000);\n\n        realm.beginTransaction();\n        createObjects(realm, 10, 11);\n        deleteObjects(realm, 10, 11);\n        realm.commitTransaction();\n    }\n\n    // The change set should be empty when the async query returns at the first time.\n    @Test\n    @RunTestInLooperThread\n    public void initialChangeSet_findAllAsync() {\n        if (type == ObservablesType.REALM_LIST) {\n            looperThread.testComplete();\n            return;\n        }\n\n        Realm realm = looperThread.getRealm();\n        populateData(realm, 10);\n        final RealmResults<Dog> results = realm.where(Dog.class).sort(Dog.FIELD_AGE).findAllAsync();\n        looperThread.keepStrongReference(results);\n        results.addChangeListener((collection, changeSet) -> {\n            assertSame(collection, results);\n            assertEquals(10, collection.size());\n            assertEquals(OrderedCollectionChangeSet.State.INITIAL, changeSet.getState());\n            assertEquals(0, changeSet.getInsertions().length);\n            assertEquals(0, changeSet.getChanges().length);\n            assertEquals(0, changeSet.getDeletions().length);\n            looperThread.testComplete();\n        });\n    }\n\n    // The change set should be empty when the async query returns at the first time.\n    @Test\n    @RunTestInLooperThread\n    public void initialChangeSet_findAll() {\n        if (type == ObservablesType.REALM_LIST) {\n            looperThread.testComplete();\n            return;\n        }\n\n        Realm realm = looperThread.getRealm();\n        populateData(realm, 10);\n        final RealmResults<Dog> results = realm.where(Dog.class).sort(Dog.FIELD_AGE).findAll();\n        looperThread.keepStrongReference(results);\n        results.addChangeListener((collection, changeSet) -> {\n            assertSame(collection, results);\n            assertEquals(11, collection.size());\n            assertEquals(OrderedCollectionChangeSet.State.UPDATE, changeSet.getState());\n            assertEquals(1, changeSet.getInsertions().length);\n            looperThread.testComplete();\n        });\n\n        realm.executeTransaction(r -> {\n            r.createObject(Dog.class);\n        });\n    }\n\n    // To reproduce https://github.com/realm/realm-java/issues/5507\n    // 1. Add listener to a collection\n    // A. change the collection in a background thread\n    // 2. Remove the listener\n    // 3. Add another listener\n    // 4. the listener added in step 3 should be triggered with change set in step A\n    @Test\n    @RunTestInLooperThread\n    public void addChangeListener_bug5507() throws InterruptedException {\n        // FIXME: See https://github.com/realm/realm-object-store/issues/605\n        if (type == ObservablesType.REALM_RESULTS) {\n            looperThread.testComplete();\n            return;\n        }\n\n        Realm realm = looperThread.getRealm();\n        populateData(realm, 1);\n\n        OrderedRealmCollectionChangeListener<OrderedRealmCollection<Dog>> listener1 =\n                new OrderedRealmCollectionChangeListener<OrderedRealmCollection<Dog>>() {\n            @Override\n            public void onChange(OrderedRealmCollection<Dog> dogs, @Nullable OrderedCollectionChangeSet changeSet) {\n                fail();\n            }\n        };\n\n        OrderedRealmCollection<Dog> dogs = getTestingCollection(realm);\n        assertEquals(1, dogs.size());\n\n        if (type == ObservablesType.REALM_LIST) {\n            //noinspection unchecked\n            ((RealmList) dogs).addChangeListener(listener1);\n        } else {\n            //noinspection unchecked\n            ((RealmResults) dogs).addChangeListener(listener1);\n        }\n\n        Thread bgThread = new Thread(new Runnable() {\n            @Override\n            public void run() {\n                Realm realm = Realm.getInstance(looperThread.getConfiguration());\n                realm.beginTransaction();\n                createObjects(realm, 2);\n                realm.commitTransaction();\n                realm.close();\n            }\n        });\n        bgThread.start();\n        bgThread.join();\n\n        if (type == ObservablesType.REALM_LIST) {\n            //noinspection unchecked\n            ((RealmList) dogs).removeChangeListener(listener1);\n        } else {\n            //noinspection unchecked\n            ((RealmResults) dogs).removeChangeListener(listener1);\n        }\n\n        OrderedRealmCollectionChangeListener<OrderedRealmCollection<Dog>> listener2 =\n                new OrderedRealmCollectionChangeListener<OrderedRealmCollection<Dog>>() {\n                    @Override\n                    public void onChange(OrderedRealmCollection<Dog> dogs, @Nullable OrderedCollectionChangeSet changeSet) {\n                        assertEquals(2, dogs.size());\n                        looperThread.testComplete();\n                    }\n                };\n\n        if (type == ObservablesType.REALM_LIST) {\n            //noinspection unchecked\n            ((RealmList) dogs).addChangeListener(listener2);\n        } else {\n            //noinspection unchecked\n            ((RealmResults) dogs).addChangeListener(listener2);\n        }\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/OrderedRealmCollectionIteratorTests.java",
    "content": "/*\n * Copyright 2016 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\npackage io.realm;\n\nimport androidx.test.annotation.UiThreadTest;\nimport androidx.test.rule.UiThreadTestRule;\n\nimport org.junit.After;\nimport org.junit.Before;\nimport org.junit.Rule;\nimport org.junit.Test;\nimport org.junit.rules.ExpectedException;\nimport org.junit.runner.RunWith;\nimport org.junit.runners.Parameterized;\n\nimport java.util.Arrays;\nimport java.util.Collections;\nimport java.util.ConcurrentModificationException;\nimport java.util.Iterator;\nimport java.util.List;\nimport java.util.ListIterator;\nimport java.util.NoSuchElementException;\nimport java.util.concurrent.CountDownLatch;\n\nimport io.realm.entities.AllJavaTypes;\n\nimport static org.junit.Assert.assertEquals;\nimport static org.junit.Assert.assertFalse;\nimport static org.junit.Assert.assertNotEquals;\nimport static org.junit.Assert.assertNotNull;\nimport static org.junit.Assert.assertTrue;\nimport static org.junit.Assert.fail;\n\n@RunWith(Parameterized.class)\npublic class OrderedRealmCollectionIteratorTests extends CollectionTests {\n\n    private static final int TEST_SIZE = 10;\n\n    @Rule\n    public final UiThreadTestRule uiThreadTestRule = new UiThreadTestRule();\n    @Rule\n    public final TestRealmConfigurationFactory configFactory = new TestRealmConfigurationFactory();\n    @Rule\n    public final ExpectedException thrown = ExpectedException.none();\n\n    private final CollectionClass collectionClass;\n    private Realm realm;\n    private OrderedRealmCollection<AllJavaTypes> collection;\n\n    @Parameterized.Parameters(name = \"{0}\")\n    public static List<CollectionClass> data() {\n        return Arrays.asList(CollectionClass.values());\n    }\n\n    public OrderedRealmCollectionIteratorTests(CollectionClass collectionType) {\n        this.collectionClass = collectionType;\n    }\n\n    @Before\n    public void setup() {\n        realm = Realm.getInstance(configFactory.createConfiguration());\n        collection = createCollection(realm, collectionClass, TEST_SIZE);\n    }\n\n    @After\n    public void tearDown() {\n        realm.close();\n    }\n\n    private OrderedRealmCollection<AllJavaTypes> createCollection(Realm realm, CollectionClass collectionClass, int sampleSize) {\n        OrderedRealmCollection<AllJavaTypes> orderedCollection;\n\n        switch (collectionClass) {\n            case REALMRESULTS_SNAPSHOT_LIST_BASE:\n            case MANAGED_REALMLIST:\n                boolean isEmpty = (sampleSize == 0);\n                int newSampleSize = (isEmpty) ? 2 : sampleSize;\n                populateRealm(realm, newSampleSize);\n                orderedCollection = realm.where(AllJavaTypes.class)\n                        .equalTo(AllJavaTypes.FIELD_LONG, isEmpty ? 1 : 0)\n                        .findFirst()\n                        .getFieldList();\n                break;\n\n            case UNMANAGED_REALMLIST:\n                populateRealm(realm, sampleSize);\n                RealmResults<AllJavaTypes> objects = realm.where(AllJavaTypes.class)\n                        .sort(AllJavaTypes.FIELD_LONG, Sort.ASCENDING)\n                        .findAll();\n                RealmList<AllJavaTypes> inMemoryList = new RealmList<AllJavaTypes>();\n                inMemoryList.addAll(objects);\n                return inMemoryList;\n\n            case REALMRESULTS_SNAPSHOT_RESULTS_BASE:\n            case REALMRESULTS:\n                populateRealm(realm, sampleSize);\n                orderedCollection = realm.where(AllJavaTypes.class)\n                        .sort(AllJavaTypes.FIELD_LONG, Sort.ASCENDING)\n                        .findAll();\n                break;\n\n            default:\n                throw new AssertionError(\"Unsupported class: \" + collectionClass);\n        }\n        if (isSnapshot(collectionClass)) {\n            orderedCollection = orderedCollection.createSnapshot();\n        }\n        return orderedCollection;\n    }\n\n    private void createNewObject() {\n        Number currentMax = realm.where(AllJavaTypes.class).max(AllJavaTypes.FIELD_ID);\n        long nextId = 0;\n        if (currentMax != null) {\n            nextId = currentMax.longValue() + 1;\n        }\n\n        realm.beginTransaction();\n        realm.createObject(AllJavaTypes.class, nextId);\n        realm.commitTransaction();\n    }\n\n    /**\n     * Helper method for checking if the unit test isn't supported for the current collectionClass.\n     *\n     * @param unsupportedTypes list of unsupported test types\n     * @return {@code true} if the unit test should be aborted, {@code false} if it should continue.\n     */\n    private boolean skipTest(CollectionClass... unsupportedTypes) {\n        //noinspection ForLoopReplaceableByForEach\n        for (int i = 0; i < unsupportedTypes.length; i++) {\n            if (unsupportedTypes[i].equals(collectionClass)) {\n                return true;\n            }\n        }\n        return false;\n    }\n\n    private void assertResultsOrSnapshot() {\n        if (collectionClass != CollectionClass.REALMRESULTS && !isSnapshot(collectionClass))  {\n            fail(\"Collection class \" + collectionClass + \"is not results or snapshot.\");\n        }\n    }\n\n    private void assertRealmList() {\n        if (collectionClass != CollectionClass.UNMANAGED_REALMLIST &&\n                collectionClass != CollectionClass.MANAGED_REALMLIST)  {\n            fail(\"Collection class \" + collectionClass + \"is not RealmList.\");\n        }\n    }\n\n    @Test\n    public void iterator() {\n        Iterator<AllJavaTypes> it = collection.iterator();\n        int i = 0;\n        while (it.hasNext()) {\n            AllJavaTypes item = it.next();\n            assertEquals(\"Failed at index: \" + i, i, item.getFieldLong());\n            i++;\n        }\n        assertEquals(TEST_SIZE, collection.size());\n        assertEquals(TEST_SIZE, i);\n    }\n\n    @Test\n    public void iterator_empty() {\n        collection = createCollection(realm, collectionClass, 0);\n        Iterator<AllJavaTypes> it = collection.iterator();\n        assertFalse(it.hasNext());\n        assertEquals(0, collection.size());\n    }\n\n    @Test\n    public void iterator_oneElement() {\n        collection = createCollection(realm, collectionClass, 1);\n        Iterator<AllJavaTypes> it = collection.iterator();\n        //noinspection WhileLoopReplaceableByForEach\n        int i = 0;\n        while (it.hasNext()) {\n            AllJavaTypes item = it.next();\n            assertEquals(0, item.getFieldLong());\n            i++;\n        }\n        assertEquals(1, collection.size());\n        assertEquals(1, i);\n    }\n\n    @Test\n    public void iterator_unrelatedTransactionBeforeNextItem() {\n        Iterator<AllJavaTypes> it = collection.iterator();\n        int i = 0;\n        while (it.hasNext()) {\n            AllJavaTypes item = it.next();\n            assertEquals(\"Failed at index: \" + i, i, item.getFieldLong());\n            i++;\n\n            // Committing unrelated transactions while iterating should not effect the current iterator.\n            createNewObject();\n        }\n    }\n\n    @Test\n    public void iterator_closedRealm_methodsThrows() {\n        if (skipTest(CollectionClass.UNMANAGED_REALMLIST)) {\n            return;\n        }\n\n        Iterator<AllJavaTypes> it = collection.iterator();\n        realm.close();\n        try {\n            it.hasNext();\n            fail();\n        } catch (IllegalStateException ignored) {\n        }\n\n        try {\n            it.next();\n            fail();\n        } catch (IllegalStateException ignored) {\n        }\n\n        try {\n            it.remove();\n            fail();\n        } catch (IllegalStateException e) {\n            assertEquals(CollectionClass.MANAGED_REALMLIST, collectionClass);\n        } catch (UnsupportedOperationException e) {\n            assertResultsOrSnapshot();\n        }\n    }\n\n    @Test\n    public void iterator_remove_beforeNext() {\n        Iterator<AllJavaTypes> it = collection.iterator();\n        realm.beginTransaction();\n\n        try {\n            it.remove();\n            fail();\n        } catch (UnsupportedOperationException e) {\n            assertResultsOrSnapshot();\n        } catch (IllegalStateException ignored) {\n            assertRealmList();\n        }\n    }\n\n    @Test\n    public void iterator_remove() {\n        Iterator<AllJavaTypes> it = collection.iterator();\n        AllJavaTypes obj = it.next();\n        assertEquals(\"test data 0\", obj.getFieldString());\n        realm.beginTransaction();\n\n        try {\n            it.remove();\n        } catch (UnsupportedOperationException e) {\n            // RealmResults doesn't support remove.\n            assertResultsOrSnapshot();\n            return;\n        }\n\n        // Unmanaged objects are always invalid, but cannot be GC'ed while we have a reference.\n        // managed objects should not be deleted (= invalid).\n        assertNotEquals(CollectionClass.REALMRESULTS, collectionClass);\n        assertTrue(obj.isValid());\n        assertEquals(\"test data 1\", collection.iterator().next().getFieldString());\n        assertEquals(TEST_SIZE - 1, collection.size());\n    }\n\n    @Test\n    public void iterator_deleteManagedObjectIndirectly() {\n        realm.beginTransaction();\n        Iterator<AllJavaTypes> it = collection.iterator();\n        it.next(); // First item is a cyclic reference to the entire graph, avoid deleting that.\n        it.next().deleteFromRealm();\n        realm.commitTransaction();\n\n        switch (collectionClass) {\n            // Snapshot\n            case REALMRESULTS_SNAPSHOT_RESULTS_BASE:\n            case REALMRESULTS_SNAPSHOT_LIST_BASE:\n                assertFalse(collection.get(1).isValid());\n                break;\n            // Managed RealmLists are directly associated with their table. Thus any indirect deletion will\n            // also remove it from the LinkView.\n            case MANAGED_REALMLIST:\n            case REALMRESULTS:\n                assertEquals(TEST_SIZE - 1, collection.size());\n                break;\n\n            // Unmanaged collections are not affected by changes to Realm.\n            case UNMANAGED_REALMLIST:\n                assertEquals(TEST_SIZE, collection.size());\n                break;\n\n            default:\n                fail();\n        }\n    }\n\n    @Test\n    public void iterator_removeCalledTwice() {\n        if (skipTest(CollectionClass.REALMRESULTS, CollectionClass.REALMRESULTS_SNAPSHOT_LIST_BASE,\n                CollectionClass.REALMRESULTS_SNAPSHOT_RESULTS_BASE)) {\n            return; // remove() not supported by RealmResults.\n        }\n\n        Iterator<AllJavaTypes> it = collection.iterator();\n        it.next();\n        realm.beginTransaction();\n        it.remove();\n\n        thrown.expect(IllegalStateException.class);\n        it.remove();\n    }\n\n    @Test\n    public void listIterator_empty() {\n        collection = createCollection(realm, collectionClass, 0);\n        ListIterator<AllJavaTypes> it = collection.listIterator();\n\n        assertFalse(it.hasPrevious());\n        assertFalse(it.hasNext());\n        assertEquals(0, it.nextIndex());\n        assertEquals(-1, it.previousIndex());\n\n        try {\n            it.next();\n            fail();\n        } catch (NoSuchElementException ignored) {\n        }\n\n        try {\n            it.previous();\n            fail();\n        } catch (NoSuchElementException ignored) {\n        }\n    }\n\n    @Test\n    public void listIterator_oneElement() {\n        collection = createCollection(realm, collectionClass, 1);\n        ListIterator<AllJavaTypes> it = collection.listIterator();\n\n        // Tests beginning of the list.\n        assertFalse(it.hasPrevious());\n        assertTrue(it.hasNext());\n        assertEquals(-1, it.previousIndex());\n        assertEquals(0, it.nextIndex());\n\n        // Tests end of the list.\n        AllJavaTypes firstObject = it.next();\n        assertEquals(0, firstObject.getFieldLong());\n        assertTrue(it.hasPrevious());\n        assertFalse(it.hasNext());\n        assertEquals(0, it.previousIndex());\n        assertEquals(1, it.nextIndex());\n    }\n\n    @Test\n    public void listIterator_manyElements() {\n        ListIterator<AllJavaTypes> it = collection.listIterator();\n\n        // Tests beginning of the list.\n        assertFalse(it.hasPrevious());\n        assertTrue(it.hasNext());\n        assertEquals(-1, it.previousIndex());\n        assertEquals(0, it.nextIndex());\n\n        // Tests 1st element in the list.\n        AllJavaTypes firstObject = it.next();\n        assertEquals(0, firstObject.getFieldLong());\n        assertTrue(it.hasPrevious());\n        assertEquals(0, it.previousIndex());\n\n        // Moves to second last element.\n        for (int i = 1; i < TEST_SIZE - 1; i++) {\n            it.next();\n        }\n        assertTrue(it.hasPrevious());\n        assertTrue(it.hasNext());\n        assertEquals(TEST_SIZE - 1, it.nextIndex());\n\n        // Tests end of the list.\n        AllJavaTypes lastObject = it.next();\n        assertEquals(TEST_SIZE - 1, lastObject.getFieldLong());\n        assertTrue(it.hasPrevious());\n        assertFalse(it.hasNext());\n        assertEquals(TEST_SIZE, it.nextIndex());\n    }\n\n    @Test\n    public void listIterator_defaultStartIndex() {\n        ListIterator<AllJavaTypes> it1 = collection.listIterator(0);\n        ListIterator<AllJavaTypes> it2 = collection.listIterator();\n\n        assertEquals(it1.previousIndex(), it2.previousIndex());\n        assertEquals(it1.nextIndex(), it2.nextIndex());\n    }\n\n    @Test\n    public void listIterator_startIndex() {\n        int i = TEST_SIZE / 2;\n        ListIterator<AllJavaTypes> it = collection.listIterator(i);\n\n        assertTrue(it.hasPrevious());\n        assertTrue(it.hasNext());\n        assertEquals(i - 1, it.previousIndex());\n        assertEquals(i, it.nextIndex());\n        AllJavaTypes nextObject = it.next();\n        assertEquals(i, nextObject.getFieldLong());\n    }\n\n    @Test\n    public void listIterator_remove_beforeNext() {\n        Iterator<AllJavaTypes> it = collection.listIterator();\n        realm.beginTransaction();\n\n        try {\n            it.remove();\n            fail();\n        } catch (IllegalStateException e) {\n            assertRealmList();\n        } catch (UnsupportedOperationException e) {\n            assertResultsOrSnapshot();\n        }\n    }\n\n    @Test\n    public void listIterator_remove_calledTwice() {\n        Iterator<AllJavaTypes> it = collection.listIterator();\n        it.next();\n        realm.beginTransaction();\n\n        switch (collectionClass) {\n            case MANAGED_REALMLIST:\n            case UNMANAGED_REALMLIST:\n                it.remove();\n                thrown.expect(IllegalStateException.class);\n                it.remove();\n                break;\n            case REALMRESULTS_SNAPSHOT_LIST_BASE:\n            case REALMRESULTS_SNAPSHOT_RESULTS_BASE:\n            case REALMRESULTS:\n                try {\n                    it.remove(); // Method not supported.\n                    fail();\n                } catch (UnsupportedOperationException ignored) {\n                }\n                break;\n            default:\n                fail(\"Unknown collection class: \" + collectionClass);\n        }\n    }\n\n    @Test\n    public void listIterator_transactionBeforeNextItem() {\n        Iterator<AllJavaTypes> it = collection.listIterator();\n        int i = 0;\n        while (it.hasNext()) {\n            AllJavaTypes item = it.next();\n            assertEquals(\"Failed at index: \" + i, i, item.getFieldLong());\n            i++;\n\n            // Committing transactions while iterating should not effect the current iterator if on a looper thread.\n            createNewObject();\n        }\n    }\n\n    @Test\n    public void listIterator_closedRealm_methods() {\n        if (skipTest(CollectionClass.UNMANAGED_REALMLIST)) {\n            return;\n        }\n\n        int location = TEST_SIZE / 2;\n        ListIterator<AllJavaTypes> it = collection.listIterator(location);\n        realm.close();\n\n        try {\n            assertEquals(location - 1, it.previousIndex());\n        } catch (IllegalStateException e) {\n            fail();\n        }\n\n        try {\n            assertEquals(location, it.nextIndex());\n        } catch (IllegalStateException e) {\n            fail();\n        }\n\n        try {\n            assertTrue(it.hasNext());\n        } catch (IllegalStateException ignored) {\n        }\n\n        try {\n            it.next();\n            fail();\n        } catch (IllegalStateException ignored) {\n        }\n\n        try {\n            it.previous();\n            fail();\n        } catch (IllegalStateException ignored) {\n        }\n\n        try {\n            it.remove();\n            fail();\n        } catch (IllegalStateException e) {\n            assertRealmList();\n        } catch (UnsupportedOperationException ignored) {\n            assertResultsOrSnapshot();\n        }\n    }\n\n    @Test\n    public void listIterator_deleteManagedObjectIndirectly() {\n        if (skipTest(CollectionClass.REALMRESULTS_SNAPSHOT_LIST_BASE,\n                CollectionClass.REALMRESULTS_SNAPSHOT_RESULTS_BASE)) {\n            return;\n        }\n\n        realm.beginTransaction();\n        ListIterator<AllJavaTypes> it = collection.listIterator();\n        it.next();\n        it.next().deleteFromRealm();\n        realm.commitTransaction();\n\n        switch (collectionClass) {\n            case MANAGED_REALMLIST:\n            case REALMRESULTS:\n                assertEquals(TEST_SIZE - 1, collection.size());\n                break;\n            case UNMANAGED_REALMLIST:\n                assertEquals(TEST_SIZE, collection.size());\n                break;\n            default:\n                fail();\n                return;\n        }\n        it.previous();\n        AllJavaTypes types = it.next(); // Iterator can still access the deleted object\n\n        //noinspection SimplifiableConditionalExpression\n        assertTrue(collectionClass == CollectionClass.MANAGED_REALMLIST ? types.isValid() : !types.isValid());\n    }\n\n    @Test\n    public void listIterator_remove_realmList_doesNotDeleteObject() {\n        if (skipTest(CollectionClass.REALMRESULTS, CollectionClass.REALMRESULTS_SNAPSHOT_LIST_BASE,\n                CollectionClass.REALMRESULTS_SNAPSHOT_RESULTS_BASE)) {\n            return;\n        }\n        ListIterator<AllJavaTypes> it = collection.listIterator();\n        AllJavaTypes obj = it.next();\n        assertEquals(\"test data 0\", obj.getFieldString());\n        realm.beginTransaction();\n        it.remove();\n        assertTrue(obj.isValid());\n    }\n\n    @Test\n    public void listIterator_remove_nonRealmList_throwUnsupported() {\n        if (skipTest(CollectionClass.MANAGED_REALMLIST, CollectionClass.UNMANAGED_REALMLIST)) {\n           return;\n        }\n        ListIterator<AllJavaTypes> it = collection.listIterator();\n        AllJavaTypes obj = it.next();\n        assertEquals(\"test data 0\", obj.getFieldString());\n        realm.beginTransaction();\n        thrown.expect(UnsupportedOperationException.class);\n        it.remove();\n    }\n\n    @Test\n    public void listIterator_set() {\n        if (skipTest(CollectionClass.REALMRESULTS, CollectionClass.REALMRESULTS_SNAPSHOT_RESULTS_BASE,\n                CollectionClass.REALMRESULTS_SNAPSHOT_LIST_BASE)) {\n            return;\n        }\n\n        realm.beginTransaction();\n        ListIterator<AllJavaTypes> it = collection.listIterator();\n\n        // Calling set() before next() should throw.\n        try {\n            it.set(new AllJavaTypes());\n            fail();\n        } catch (IllegalStateException ignored) {\n        }\n\n        AllJavaTypes obj = it.next();\n        assertEquals(0, obj.getFieldLong());\n        it.set(new AllJavaTypes(42));\n\n        it.next();\n        it.previous(); // A big ListIterator WTF!, but it is by design.\n        obj = it.previous();\n        assertEquals(42, obj.getFieldLong());\n    }\n\n    @Test\n    public void listIterator_add() {\n        if (skipTest(CollectionClass.REALMRESULTS, CollectionClass.REALMRESULTS_SNAPSHOT_RESULTS_BASE,\n                CollectionClass.REALMRESULTS_SNAPSHOT_LIST_BASE)) {\n            return;\n        }\n\n        realm.beginTransaction();\n        ListIterator<AllJavaTypes> it = collection.listIterator();\n\n        // The element is inserted immediately before the element that would be returned by next(), if any, and after\n        // the element that would be returned by previous(), if any. (If the list contains no elements, the new element\n        // becomes the sole element on the list.)\n        it.add(new AllJavaTypes(4242));\n        AllJavaTypes obj = collection.first();\n        assertNotNull(obj);\n        assertEquals(4242, obj.getFieldLong());\n\n        obj = it.next();\n        assertEquals(0, obj.getFieldLong());\n        it.add(new AllJavaTypes(42));\n        obj = it.previous();\n        assertEquals(42, obj.getFieldLong());\n    }\n\n    @Test\n    public void listIterator_unsupportedMethods() {\n        ListIterator<AllJavaTypes> it = collection.listIterator();\n        try {\n            it.remove();\n            fail();\n        } catch (UnsupportedOperationException e) {\n            assertResultsOrSnapshot();\n        } catch (IllegalStateException e) { // since next() was never called.\n            assertRealmList();\n        }\n\n        try {\n            it.add(null);\n            if (collectionClass != CollectionClass.UNMANAGED_REALMLIST) {\n                fail();\n            }\n        } catch (UnsupportedOperationException e) {\n            assertResultsOrSnapshot();\n        } catch (IllegalArgumentException e) {\n            if (collectionClass == CollectionClass.UNMANAGED_REALMLIST) {\n                fail();\n            }\n            assertRealmList();\n        }\n\n        try {\n            it.set(new AllJavaTypes());\n            fail();\n        } catch (UnsupportedOperationException e) {\n            assertResultsOrSnapshot();\n        } catch (IllegalStateException e) { // since the collection is empty\n            assertRealmList();\n        }\n    }\n\n    @Test\n    public void iterator_outsideChangeToSizeThrowsConcurrentModification() {\n        if (skipTest(CollectionClass.REALMRESULTS, CollectionClass.REALMRESULTS_SNAPSHOT_RESULTS_BASE,\n                CollectionClass.REALMRESULTS_SNAPSHOT_LIST_BASE)) {\n            return;\n        }\n\n        // Tests all standard collection methods.\n        for (CollectionMethod method : CollectionMethod.values()) {\n            collection = createCollection(realm, collectionClass, TEST_SIZE);\n            realm.beginTransaction();\n            Iterator<AllJavaTypes> it = collection.iterator();\n            switch (method) {\n                case ADD_OBJECT: collection.add(new AllJavaTypes(TEST_SIZE)); break;\n                case ADD_ALL_OBJECTS: collection.addAll(Collections.singletonList(new AllJavaTypes(TEST_SIZE))); break;\n                case CLEAR: collection.clear(); break;\n                case REMOVE_OBJECT: collection.remove(collection.get(0)); break;\n                case REMOVE_ALL: collection.removeAll(Collections.singletonList(collection.get(0))); break;\n                case RETAIN_ALL: collection.retainAll(Collections.singletonList(collection.get(0))); break;\n\n                // Does not impact size, so does not trigger ConcurrentModificationException.\n                case CONTAINS:\n                case CONTAINS_ALL:\n                case EQUALS:\n                case HASHCODE:\n                case IS_EMPTY:\n                case ITERATOR:\n                case SIZE:\n                case TO_ARRAY:\n                case TO_ARRAY_INPUT:\n                    realm.cancelTransaction();\n                    continue;\n                default:\n                    fail(\"Unknown method: \" + method);\n            }\n            checkIteratorThrowsConcurrentModification(realm, method.toString(), it);\n        }\n\n        for (ListMethod method : ListMethod.values()) {\n            collection = createCollection(realm, collectionClass, TEST_SIZE);\n            realm.beginTransaction();\n            Iterator<AllJavaTypes> it = collection.iterator();\n            switch (method) {\n                case ADD_INDEX: collection.add(0, new AllJavaTypes(TEST_SIZE)); break;\n                case ADD_ALL_INDEX: collection.addAll(0, Collections.singleton(new AllJavaTypes(TEST_SIZE))); break;\n                case REMOVE_INDEX: collection.remove(0); break;\n\n                // Does not impact size, so does not trigger ConcurrentModificationException.\n                case FIRST:\n                case LAST:\n                case GET_INDEX:\n                case INDEX_OF:\n                case LAST_INDEX_OF:\n                case LIST_ITERATOR:\n                case LIST_ITERATOR_INDEX:\n                case SET:\n                case SUBLIST:\n                    realm.cancelTransaction();\n                    continue;\n\n                default:\n                    fail(\"Unknown method: \" + method);\n            }\n            checkIteratorThrowsConcurrentModification(realm, method.toString(), it);\n        }\n    }\n\n    @Test\n    public void iterator_outsideChangeToSizeThrowsConcurrentModification_managedCollection() {\n        if (skipTest(CollectionClass.REALMRESULTS, CollectionClass.UNMANAGED_REALMLIST,\n                CollectionClass.REALMRESULTS_SNAPSHOT_LIST_BASE, CollectionClass.REALMRESULTS_SNAPSHOT_RESULTS_BASE)) {\n            return;\n        }\n\n        // Tests all RealmCollection methods.\n        for (RealmCollectionMethod method : RealmCollectionMethod.values()) {\n            collection = createCollection(realm, collectionClass, TEST_SIZE);\n            realm.beginTransaction();\n            collection.remove(0); // Removes object creating circular dependency which will crash deleteAll.\n            Iterator<AllJavaTypes> it = collection.iterator();\n            switch (method) {\n                case DELETE_ALL_FROM_REALM:\n                    collection.deleteAllFromRealm(); break;\n\n                // Does not impact size, so does not trigger ConcurrentModificationException.\n                case WHERE:\n                case MIN:\n                case MAX:\n                case SUM:\n                case AVERAGE:\n                case MIN_DATE:\n                case MAX_DATE:\n                case IS_VALID:\n                case IS_MANAGED:\n                case IS_FROZEN:\n                case FREEZE:\n                    realm.cancelTransaction();\n                    continue;\n\n                default:\n                    fail(\"Unknown method: \" + method);\n            }\n            checkIteratorThrowsConcurrentModification(realm, method.toString(), it);\n        }\n\n        // Tests all OrderedRealmCollection methods.\n        for (OrderedRealmCollectionMethod method : OrderedRealmCollectionMethod.values()) {\n            collection = createCollection(realm, collectionClass, TEST_SIZE);\n            realm.beginTransaction();\n            Iterator<AllJavaTypes> it = collection.iterator();\n            switch (method) {\n                case DELETE_INDEX: collection.deleteFromRealm(0); break;\n                case DELETE_FIRST: collection.deleteFirstFromRealm(); break;\n                case DELETE_LAST: collection.deleteLastFromRealm(); break;\n\n                // Does not impact size, so does not trigger ConcurrentModificationException.\n                case SORT:\n                case SORT_FIELD:\n                case SORT_2FIELDS:\n                case SORT_MULTI:\n                case CREATE_SNAPSHOT:\n                    realm.cancelTransaction();\n                    continue;\n                default:\n                    fail(\"Unknown method: \" + method);\n\n            }\n            checkIteratorThrowsConcurrentModification(realm, method.toString(), it);\n        }\n    }\n\n\n    private void checkIteratorThrowsConcurrentModification(Realm realm, String method, Iterator<AllJavaTypes> it) {\n        try {\n            it.next();\n            fail(\"Method should have thrown: \" + method);\n        } catch (ConcurrentModificationException ignored) {\n        } catch (Exception e) {\n            throw new RuntimeException(\"Method failed: \" + method, e);\n        } finally {\n            realm.cancelTransaction();\n        }\n    }\n\n    // Accessing RealmResults iterator after receving remote change notification will throw.\n    // But it is valid operation for snapshot.\n    @Test\n    public void iterator_realmResultsThrowConcurrentModification_snapshotJustWorks() {\n        if (skipTest(CollectionClass.MANAGED_REALMLIST, CollectionClass.UNMANAGED_REALMLIST)) {\n            return;\n        }\n\n        // Verifies that ConcurrentModification is correctly detected on non-looper threads.\n        Iterator<AllJavaTypes> it = collection.iterator();\n        final CountDownLatch bgDone = new CountDownLatch(1);\n        new Thread(new Runnable() {\n            @Override\n            public void run() {\n                Realm bgRealm = Realm.getInstance(realm.getConfiguration());\n                bgRealm.beginTransaction();\n                bgRealm.createObject(AllJavaTypes.class, TEST_SIZE);\n                bgRealm.commitTransaction();\n                bgRealm.close();\n                bgDone.countDown();\n            }\n        }).start();\n        TestHelper.awaitOrFail(bgDone);\n        realm.refresh();\n        try {\n            it.next();\n            assertEquals(TEST_SIZE, collection.size());\n        } catch (ConcurrentModificationException ignored) {\n            assertEquals(collectionClass, CollectionClass.REALMRESULTS);\n        }\n    }\n\n    @Test\n    public void useCase_simpleIterator_modifyQueryResult_innerTransaction() {\n        if (skipTest(CollectionClass.MANAGED_REALMLIST, CollectionClass.UNMANAGED_REALMLIST,\n                CollectionClass.REALMRESULTS)) {\n            return;\n        }\n\n        assertEquals(TEST_SIZE, collection.size());\n        for (int i = 0; i < collection.size(); i++) {\n            realm.beginTransaction();\n            AllJavaTypes obj = collection.get(i);\n            obj.setFieldLong(obj.getFieldLong() + TEST_SIZE);\n            realm.commitTransaction();\n        }\n\n        // Verifies that all elements were modified.\n        assertEquals(0, realm.where(AllJavaTypes.class).lessThan(AllJavaTypes.FIELD_LONG, TEST_SIZE).count());\n    }\n\n    @Test\n    public void useCase_simpleIterator_modifyQueryResult_outerTransaction() {\n        if (skipTest(CollectionClass.MANAGED_REALMLIST, CollectionClass.UNMANAGED_REALMLIST,\n                CollectionClass.REALMRESULTS)) {\n            return;\n        }\n\n        assertEquals(TEST_SIZE, collection.size());\n        realm.beginTransaction();\n        for (int i = 0; i < collection.size(); i++) {\n            AllJavaTypes obj = collection.get(i);\n            obj.setFieldLong(obj.getFieldLong() + TEST_SIZE);\n        }\n        realm.commitTransaction();\n\n        // Verifies that all elements were modified.\n        assertEquals(0, realm.where(AllJavaTypes.class).lessThan(AllJavaTypes.FIELD_LONG, TEST_SIZE).count());\n    }\n\n    @Test\n    public void useCase_forEachIterator_modifyQueryResult_innerTransaction() {\n        if (skipTest(CollectionClass.MANAGED_REALMLIST, CollectionClass.UNMANAGED_REALMLIST)) {\n            return;\n        }\n\n        assertEquals(TEST_SIZE, collection.size());\n        for (AllJavaTypes obj : collection) {\n            realm.beginTransaction();\n            obj.setFieldLong(obj.getFieldLong() + TEST_SIZE);\n            realm.commitTransaction();\n        }\n\n        // Verifies that all elements were modified.\n        assertEquals(0, realm.where(AllJavaTypes.class).lessThan(AllJavaTypes.FIELD_LONG, TEST_SIZE).count());\n    }\n\n    @Test\n    public void useCase_forEachIterator_modifyQueryResult_outerTransaction() {\n        if (skipTest(CollectionClass.MANAGED_REALMLIST, CollectionClass.UNMANAGED_REALMLIST)) {\n            return;\n        }\n\n        assertEquals(TEST_SIZE, collection.size());\n        realm.beginTransaction();\n        for (AllJavaTypes obj : collection) {\n            obj.setFieldLong(obj.getFieldLong() + TEST_SIZE);\n        }\n        realm.commitTransaction();\n\n        // Verifies that all elements were modified.\n        assertEquals(0, realm.where(AllJavaTypes.class).lessThan(AllJavaTypes.FIELD_LONG, TEST_SIZE).count());\n    }\n\n    @Test\n    @UiThreadTest\n    public void useCase_simpleIterator_modifyQueryResult_innerTransaction_looperThread() {\n        if (skipTest(CollectionClass.MANAGED_REALMLIST, CollectionClass.UNMANAGED_REALMLIST,\n                CollectionClass.REALMRESULTS)) {\n            return;\n        }\n\n        assertEquals(TEST_SIZE, collection.size());\n        for (int i = 0; i < collection.size(); i++) {\n            realm.beginTransaction();\n            AllJavaTypes obj = collection.get(i);\n            obj.setFieldLong(obj.getFieldLong() + TEST_SIZE);\n            realm.commitTransaction();\n        }\n\n        // Verifies that all elements were modified.\n        assertEquals(0, realm.where(AllJavaTypes.class).lessThan(AllJavaTypes.FIELD_LONG, TEST_SIZE).count());\n    }\n\n    @Test\n    @UiThreadTest\n    public void useCase_simpleIterator_modifyQueryResult_outerTransaction_looperThread() {\n        if (skipTest(CollectionClass.MANAGED_REALMLIST, CollectionClass.UNMANAGED_REALMLIST,\n                CollectionClass.REALMRESULTS)) {\n            return;\n        }\n\n        assertEquals(TEST_SIZE, collection.size());\n        realm.beginTransaction();\n        for (int i = 0; i < collection.size(); i++) {\n            AllJavaTypes obj = collection.get(i);\n            obj.setFieldLong(obj.getFieldLong() + TEST_SIZE);\n        }\n        realm.commitTransaction();\n\n        // Verifies that all elements were modified.\n        assertEquals(0, realm.where(AllJavaTypes.class).lessThan(AllJavaTypes.FIELD_LONG, TEST_SIZE).count());\n    }\n\n    @Test\n    @UiThreadTest\n    public void useCase_forEachIterator_modifyQueryResult_innerTransaction_looperThread() {\n        if (skipTest(CollectionClass.MANAGED_REALMLIST, CollectionClass.UNMANAGED_REALMLIST)) {\n            return;\n        }\n\n        assertEquals(TEST_SIZE, collection.size());\n        for (AllJavaTypes obj : collection) {\n            realm.beginTransaction();\n            obj.setFieldLong(obj.getFieldLong() + TEST_SIZE);\n            realm.commitTransaction();\n        }\n\n        // Verifies that all elements were modified.\n        assertEquals(0, realm.where(AllJavaTypes.class).lessThan(AllJavaTypes.FIELD_LONG, TEST_SIZE).count());\n    }\n\n    @Test\n    @UiThreadTest\n    public void useCase_forEachIterator_modifyQueryResult_outerTransaction_looperThread() {\n        if (skipTest(CollectionClass.MANAGED_REALMLIST, CollectionClass.UNMANAGED_REALMLIST)) {\n            return;\n        }\n\n        assertEquals(TEST_SIZE, collection.size());\n        realm.beginTransaction();\n        for (AllJavaTypes obj : collection) {\n            obj.setFieldLong(obj.getFieldLong() + TEST_SIZE);\n        }\n        realm.commitTransaction();\n\n        // Verifies that all elements were modified.\n        assertEquals(0, realm.where(AllJavaTypes.class).lessThan(AllJavaTypes.FIELD_LONG, TEST_SIZE).count());\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/OrderedRealmCollectionSnapshotTests.java",
    "content": "/*\n * Copyright 2017 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\npackage io.realm;\n\n\nimport androidx.test.ext.junit.runners.AndroidJUnit4;\n\nimport org.junit.After;\nimport org.junit.Before;\nimport org.junit.Rule;\nimport org.junit.Test;\nimport org.junit.rules.ExpectedException;\nimport org.junit.runner.RunWith;\n\nimport io.realm.entities.AllTypes;\n\nimport static junit.framework.Assert.assertFalse;\nimport static junit.framework.Assert.assertTrue;\n\n/**\n * Unit tests specific for {@link OrderedRealmCollectionSnapshot} that cannot be covered by\n * {@link OrderedRealmCollectionTests}, {@link ManagedRealmCollectionTests}, {@link UnManagedRealmCollectionTests} or\n * {@link RealmCollectionTests}.\n */\n@RunWith(AndroidJUnit4.class)\npublic class OrderedRealmCollectionSnapshotTests {\n\n    @Rule\n    public final TestRealmConfigurationFactory configFactory = new TestRealmConfigurationFactory();\n    @Rule\n    public final ExpectedException thrown = ExpectedException.none();\n\n    private static final int TEST_SIZE = 10;\n    private Realm realm;\n    private OrderedRealmCollection<AllTypes> snapshot;\n\n    @Before\n    public void setup() {\n        realm = Realm.getInstance(configFactory.createConfiguration());\n        populateRealm(realm, TEST_SIZE);\n        snapshot = realm.where(AllTypes.class).findAll().createSnapshot();\n    }\n\n    @After\n    public void tearDown() {\n        realm.close();\n    }\n\n    private void populateRealm(Realm realm, int testSize) {\n        realm.beginTransaction();\n        for (int i = 0; i < testSize; i++) {\n            AllTypes allTypes = realm.createObject(AllTypes.class);\n            allTypes.setColumnLong(i);\n        }\n        realm.commitTransaction();\n    }\n\n    @Test\n    public void deleteFromRealm_twice() {\n        realm.beginTransaction();\n        snapshot.deleteFromRealm(0);\n        snapshot.deleteFromRealm(0);\n        realm.commitTransaction();\n        assertFalse(snapshot.get(0).isValid());\n    }\n\n    @Test\n    public void deleteFirstFromRealm_twice() {\n        realm.beginTransaction();\n        assertTrue(snapshot.deleteFirstFromRealm());\n        assertFalse(snapshot.deleteFirstFromRealm());\n        realm.commitTransaction();\n    }\n\n    @Test\n    public void deleteLastFromRealm_twice() {\n        realm.beginTransaction();\n        assertTrue(snapshot.deleteLastFromRealm());\n        assertFalse(snapshot.deleteLastFromRealm());\n        realm.commitTransaction();\n    }\n\n    @Test\n    public void deleteAllFromRealmTwice() {\n        realm.beginTransaction();\n        assertTrue(snapshot.deleteAllFromRealm());\n        assertTrue(snapshot.deleteAllFromRealm());\n        realm.commitTransaction();\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/OrderedRealmCollectionTests.java",
    "content": "/*\n * Copyright 2016 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\npackage io.realm;\n\nimport android.util.Pair;\n\nimport org.junit.After;\nimport org.junit.Before;\nimport org.junit.Rule;\nimport org.junit.Test;\nimport org.junit.rules.ExpectedException;\nimport org.junit.runner.RunWith;\nimport org.junit.runners.Parameterized;\n\nimport java.util.Arrays;\nimport java.util.Collections;\nimport java.util.List;\n\nimport io.realm.entities.AllJavaTypes;\n\nimport static org.junit.Assert.assertEquals;\nimport static org.junit.Assert.assertSame;\nimport static org.junit.Assert.fail;\n\n/**\n * Test class for all methods specific to OrderedRealmCollections no matter if they are managed or unmanaged.\n *\n * Methods tested in this class:\n *\n * # RealmOrderedCollection\n *\n * + E first();\n * + E last();\n * - void sort(String field);\n * - void sort(String field, Sort sortOrder);\n * - void sort(String field1, Sort sortOrder1, String field2, Sort sortOrder2);\n * - void sort(String[] fields, Sort[] sortOrders);\n * - void deleteFromRealm(int location);\n * - void deleteFirstFromRealm();\n * - void deleteLastFromRealm();\n * - OrderedRealmCollectionSnapshot createSnapshot();\n *\n * # List\n *\n *  - void add(int location, E object);\n *  - boolean addAll(int location, Collection<? extends E> collection);\n *  + E get(int location);\n *  + int indexOf(Object object);\n *  + int lastIndexOf(Object object);\n *  - ListIterator<E> listIterator();\n *  - ListIterator<E> listIterator(int location);\n *  - E remove(int location);\n *  - E set(int location, E object);\n *  + List<E> subList(int start, int end);\n *\n * # RealmCollection\n *\n * - RealmQuery<E> where();\n * - Number min(String fieldName);\n * - Number max(String fieldName);\n * - Number sum(String fieldName);\n * - double average(String fieldName);\n * - Date maxDate(String fieldName);\n * - Date minDate(String fieldName);\n * - void deleteAllFromRealm();\n * - boolean isLoaded();\n * - boolean load();\n * - boolean isValid();\n * - BaseRealm getRealm();\n *\n * # Collection\n *\n * - public boolean add(E object);\n * - public boolean addAll(Collection<? extends E> collection);\n * - public void deleteAll();\n * - public boolean contains(Object object);\n * - public boolean containsAll(Collection<?> collection);\n * - public boolean equals(Object object);\n * - public int hashCode();\n * - public boolean isEmpty();\n * - public Iterator<E> iterator();\n * - public boolean remove(Object object);\n * - public boolean removeAll(Collection<?> collection);\n * - public boolean retainAll(Collection<?> collection);\n * - public int size();\n * - public Object[] toArray();\n * - public <T> T[] toArray(T[] array);\n *\n * @see RealmCollectionTests\n * @see ManagedRealmCollectionTests\n * @see UnManagedRealmCollectionTests\n */\n@RunWith(Parameterized.class)\npublic class OrderedRealmCollectionTests extends CollectionTests {\n\n    private static final int TEST_SIZE = 10;\n\n    @Rule\n    public final TestRealmConfigurationFactory configFactory = new TestRealmConfigurationFactory();\n    @Rule\n    public final ExpectedException thrown = ExpectedException.none();\n\n    private final CollectionClass collectionClass;\n    private Realm realm;\n    private OrderedRealmCollection<AllJavaTypes> collection;\n\n    @Parameterized.Parameters(name = \"{0}\")\n    public static List<CollectionClass> data() {\n        return Arrays.asList(CollectionClass.values());\n    }\n\n    public OrderedRealmCollectionTests(CollectionClass collectionType) {\n        this.collectionClass = collectionType;\n    }\n\n    @Before\n    public void setup() {\n        realm = Realm.getInstance(configFactory.createConfiguration());\n        collection = createCollection(realm, collectionClass);\n    }\n\n    @After\n    public void tearDown() {\n        realm.close();\n    }\n\n    private OrderedRealmCollection<AllJavaTypes> createCollection(Realm realm, CollectionClass collectionClass) {\n        OrderedRealmCollection<AllJavaTypes> orderedCollection;\n        switch (collectionClass) {\n            case REALMRESULTS_SNAPSHOT_LIST_BASE:\n            case MANAGED_REALMLIST:\n                populateRealm(realm, TEST_SIZE);\n                orderedCollection = realm.where(AllJavaTypes.class)\n                        .equalTo(AllJavaTypes.FIELD_LONG, 0)\n                        .findFirst()\n                        .getFieldList();\n                break;\n\n            case UNMANAGED_REALMLIST:\n                return populateInMemoryList(TEST_SIZE);\n\n            case REALMRESULTS_SNAPSHOT_RESULTS_BASE:\n            case REALMRESULTS:\n                populateRealm(realm, TEST_SIZE);\n                orderedCollection = realm.where(AllJavaTypes.class).findAll();\n                break;\n\n            default:\n                throw new AssertionError(\"Unsupported class: \" + collectionClass);\n        }\n        if (isSnapshot(collectionClass)) {\n            orderedCollection = orderedCollection.createSnapshot();\n        }\n        return orderedCollection;\n    }\n\n    private OrderedRealmCollection<AllJavaTypes> createEmptyCollection(Realm realm, CollectionClass collectionClass) {\n        OrderedRealmCollection<AllJavaTypes> orderedCollection;\n        switch (collectionClass) {\n            case REALMRESULTS_SNAPSHOT_LIST_BASE:\n            case MANAGED_REALMLIST:\n                orderedCollection = realm.where(AllJavaTypes.class)\n                        .equalTo(AllJavaTypes.FIELD_LONG, 1)\n                        .findFirst()\n                        .getFieldList();\n                break;\n\n            case UNMANAGED_REALMLIST:\n                return new RealmList<AllJavaTypes>();\n\n            case REALMRESULTS_SNAPSHOT_RESULTS_BASE:\n            case REALMRESULTS:\n                orderedCollection = realm.where(AllJavaTypes.class).equalTo(AllJavaTypes.FIELD_LONG, -1).findAll();\n                break;\n\n            default:\n                throw new AssertionError(\"Unsupported class: \" + collectionClass);\n        }\n        if (isSnapshot(collectionClass)) {\n            orderedCollection = orderedCollection.createSnapshot();\n        }\n        return orderedCollection;\n    }\n\n    private Pair<AllJavaTypes, OrderedRealmCollection<AllJavaTypes>> createCollectionWithMultipleCopies(Realm realm, CollectionClass collectionClass) {\n\n        OrderedRealmCollection<AllJavaTypes>  orderedCollection;\n        AllJavaTypes obj;\n        switch (collectionClass) {\n            case REALMRESULTS_SNAPSHOT_LIST_BASE:\n            case MANAGED_REALMLIST:\n                obj = realm.where(AllJavaTypes.class)\n                        .equalTo(AllJavaTypes.FIELD_LONG, 1)\n                        .findFirst();\n                RealmList<AllJavaTypes> list = obj.getFieldList();\n                realm.beginTransaction();\n                list.add(obj);\n                realm.commitTransaction();\n                orderedCollection = list;\n                break;\n\n            case UNMANAGED_REALMLIST:\n                obj = new AllJavaTypes(1);\n                return new Pair<AllJavaTypes, OrderedRealmCollection<AllJavaTypes>>(obj, new RealmList<AllJavaTypes>(obj, obj));\n\n            case REALMRESULTS_SNAPSHOT_RESULTS_BASE:\n            case REALMRESULTS:\n                RealmResults<AllJavaTypes> result = realm.where(AllJavaTypes.class).equalTo(AllJavaTypes.FIELD_LONG, 1).findAll();\n                obj = result.first();\n                orderedCollection = result;\n                break;\n\n            default:\n                throw new AssertionError(\"Unsupported class: \" + collectionClass);\n        }\n\n        if (isSnapshot(collectionClass)) {\n            orderedCollection = orderedCollection.createSnapshot();\n        }\n\n        return new Pair<AllJavaTypes, OrderedRealmCollection<AllJavaTypes>>(obj, orderedCollection);\n    }\n\n    @Test\n    public void first() {\n        assertEquals(collection.get(0), collection.first());\n    }\n\n    @Test\n    public void first_emptyCollection() {\n        collection = createEmptyCollection(realm, collectionClass);\n        try {\n            collection.first();\n            fail();\n        } catch (IndexOutOfBoundsException ignored) {\n        }\n    }\n\n    @Test\n    public void first_withDefault() {\n        AllJavaTypes defaultObject = new AllJavaTypes();\n        collection = createEmptyCollection(realm, collectionClass);\n        assertEquals(defaultObject, collection.first(defaultObject));\n        assertEquals(null, collection.first(null)); // Null is an acceptable default\n    }\n\n    @Test\n    public void last() {\n        assertEquals(collection.get(TEST_SIZE - 1), collection.last());\n    }\n\n    @Test\n    public void last_emptyCollection() {\n        collection = createEmptyCollection(realm, collectionClass);\n        try {\n            collection.last();\n            fail();\n        } catch (IndexOutOfBoundsException ignored) {\n        }\n    }\n\n    @Test\n    public void last_withDefault() {\n        AllJavaTypes defaultObject = new AllJavaTypes();\n        collection = createEmptyCollection(realm, collectionClass);\n        assertEquals(defaultObject, collection.last(defaultObject));\n        assertEquals(null, collection.last(null)); // Null is an acceptable default\n    }\n\n    @Test\n    public void get_validIndex() {\n        AllJavaTypes first = collection.get(0);\n        assertEquals(0, first.getFieldInt());\n\n        AllJavaTypes last = collection.get(TEST_SIZE - 1);\n        assertEquals(TEST_SIZE - 1, last.getFieldInt());\n    }\n\n    @Test\n    public void get_indexOutOfBounds() {\n        List<Integer> indexes = Arrays.asList(-1, TEST_SIZE, Integer.MAX_VALUE, Integer.MIN_VALUE);\n        for (Integer index : indexes) {\n            try {\n                collection.get(index);\n                fail(index + \" did not throw the expected Exception.\");\n            } catch (IndexOutOfBoundsException ignored) {\n            }\n        }\n    }\n\n    @Test\n    public void indexOf() {\n        AllJavaTypes obj = collection.get(1);\n        assertEquals(1, collection.indexOf(obj));\n    }\n\n    @Test\n    public void indexOf_null() {\n        assertEquals(-1, collection.indexOf(null));\n    }\n\n    @Test\n    public void indexOf_objectNotInRealm() {\n        assertEquals(-1, collection.indexOf(new AllJavaTypes()));\n    }\n\n    @Test\n    public void lastIndexOf() {\n        Pair<AllJavaTypes, OrderedRealmCollection<AllJavaTypes>> data = createCollectionWithMultipleCopies(realm, collectionClass);\n        AllJavaTypes obj = data.first;\n        collection = data.second;\n        int lastIndex = collection.lastIndexOf(obj);\n        assertEquals(collection.size() - 1, lastIndex);\n    }\n\n    @Test\n    public void lastIndexOf_null() {\n        assertEquals(-1, collection.lastIndexOf(null));\n    }\n\n    @Test\n    public void lastIndexOf_objectNotInRealm() {\n        assertEquals(-1, collection.lastIndexOf(new AllJavaTypes()));\n    }\n\n    @Test\n    public void subList() {\n        List<AllJavaTypes> list = collection.subList(0, 5);\n        assertEquals(5, list.size());\n        assertEquals(list.get(0), collection.get(0));\n        assertEquals(list.get(4), collection.get(4));\n    }\n\n    @Test(expected = IndexOutOfBoundsException.class)\n    public void subList_invalidStartIndex() {\n        collection.subList(-1, TEST_SIZE);\n    }\n\n    @Test(expected = IndexOutOfBoundsException.class)\n    public void subList_invalidEnd() {\n        collection.subList(0, TEST_SIZE + 1);\n    }\n\n    // Checks that all relevant methods throw a correct IndexOutOfBounds\n    @Test\n    public void methods_indexOutOfBounds() {\n        collection = createEmptyCollection(realm, collectionClass);\n\n        for (ListMethod method : ListMethod.values()) {\n            realm.beginTransaction();\n            try {\n                switch (method) {\n                    case ADD_INDEX: collection.add(1, new AllJavaTypes()); break;\n                    case ADD_ALL_INDEX: collection.addAll(1, Collections.singleton(new AllJavaTypes())); break;\n                    case GET_INDEX: collection.get(1); break;\n                    case LIST_ITERATOR_INDEX: collection.listIterator(1); break;\n                    case REMOVE_INDEX: collection.remove(1); break;\n                    case SET: collection.set(1, new AllJavaTypes()); break;\n                    case SUBLIST: collection.subList(1, 2); break;\n\n                    // Cannot fail with IndexOutOfBounds\n                    case FIRST:\n                    case LAST:\n                    case INDEX_OF:\n                    case LAST_INDEX_OF:\n                    case LIST_ITERATOR:\n                        continue;\n                }\n                fail(method + \" did not throw an exception\");\n            } catch (IndexOutOfBoundsException ignored) {\n            } catch (UnsupportedOperationException ignored) {\n            } finally {\n                realm.cancelTransaction();\n            }\n        }\n\n        for (OrderedRealmCollectionMethod method : OrderedRealmCollectionMethod.values()) {\n            realm.beginTransaction();\n            try {\n                switch (method) {\n                    case DELETE_INDEX: collection.deleteFromRealm(1); break;\n\n                    // Cannot fail with IndexOutOfBounds\n                    case DELETE_FIRST:\n                    case DELETE_LAST:\n                    case SORT:\n                    case SORT_FIELD:\n                    case SORT_2FIELDS:\n                    case SORT_MULTI:\n                    case CREATE_SNAPSHOT:\n                        continue;\n                }\n                fail(method + \" did not throw an exception\");\n            } catch (IndexOutOfBoundsException ignored) {\n            } catch (UnsupportedOperationException ignored) {\n            } finally {\n                realm.cancelTransaction();\n            }\n        }\n    }\n\n    @Test\n    public void createSnapshot() {\n        if (collectionClass == CollectionClass.UNMANAGED_REALMLIST) {\n            thrown.expect(UnsupportedOperationException.class);\n        }\n        OrderedRealmCollectionSnapshot snapshot = collection.createSnapshot();\n        switch (collectionClass) {\n            case REALMRESULTS_SNAPSHOT_LIST_BASE:\n            case REALMRESULTS_SNAPSHOT_RESULTS_BASE:\n                // Creating snapshot from a snapshot will just return the same object.\n                assertSame(collection, snapshot);\n                break;\n            case MANAGED_REALMLIST:\n            case REALMRESULTS:\n                int sizeBeforeChange = collection.size();\n                realm.beginTransaction();\n                collection.deleteLastFromRealm();\n                realm.commitTransaction();\n                assertEquals(sizeBeforeChange - 1, collection.size());\n                assertEquals(sizeBeforeChange, snapshot.size());\n                break;\n            default:\n                break;\n        }\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/QueryTests.java",
    "content": "/*\n * Copyright 2017 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 */\npackage io.realm;\n\nimport org.bson.types.Decimal128;\nimport org.bson.types.ObjectId;\nimport org.junit.After;\nimport org.junit.Before;\nimport org.junit.Rule;\nimport org.junit.rules.ExpectedException;\n\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.Collection;\nimport java.util.Collections;\nimport java.util.Date;\nimport java.util.HashSet;\nimport java.util.List;\nimport java.util.UUID;\nimport java.util.concurrent.TimeUnit;\n\nimport androidx.test.core.app.ApplicationProvider;\nimport androidx.test.rule.UiThreadTestRule;\n\nimport javax.annotation.Nullable;\n\nimport io.realm.entities.AllJavaTypesUnsupportedTypes;\nimport io.realm.entities.BacklinksSource;\nimport io.realm.entities.BacklinksTarget;\nimport io.realm.rule.RunInLooperThread;\n\n\npublic abstract class QueryTests {\n    public static final int TEST_DATA_SIZE = 10;\n    public static final int TEST_NO_PRIMARY_KEY_NULL_TYPES_SIZE = 200;\n\n    public static final long DECADE_MILLIS = 10 * TimeUnit.DAYS.toMillis(365);\n\n    @Rule\n    public final TestRealmConfigurationFactory configFactory = new TestRealmConfigurationFactory();\n    @Rule\n    public final ExpectedException thrown = ExpectedException.none();\n    @Rule\n    public final RunInLooperThread looperThread = new RunInLooperThread();\n    @Rule\n    public final UiThreadTestRule uiThreadTestRule = new UiThreadTestRule();\n\n    protected static final List<RealmFieldType> SUPPORTED_IS_EMPTY_TYPES;\n    protected static final List<RealmFieldType> NOT_SUPPORTED_IS_EMPTY_TYPES;\n    protected static final List<RealmFieldType> SUPPORTED_IS_NOT_EMPTY_TYPES;\n    protected static final List<RealmFieldType> NOT_SUPPORTED_IS_NOT_EMPTY_TYPES;\n\n    static {\n        ArrayList<RealmFieldType> list = new ArrayList<>(Arrays.asList(\n                RealmFieldType.STRING,\n                RealmFieldType.BINARY,\n                RealmFieldType.LIST,\n                RealmFieldType.OBJECT,\n                RealmFieldType.INTEGER_LIST,\n                RealmFieldType.BOOLEAN_LIST,\n                RealmFieldType.STRING_LIST,\n                RealmFieldType.BINARY_LIST,\n                RealmFieldType.DATE_LIST,\n                RealmFieldType.FLOAT_LIST,\n                RealmFieldType.DOUBLE_LIST,\n                RealmFieldType.DECIMAL128_LIST,\n                RealmFieldType.OBJECT_ID_LIST,\n                RealmFieldType.UUID_LIST,\n                RealmFieldType.MIXED_LIST,\n                RealmFieldType.LINKING_OBJECTS,\n                RealmFieldType.STRING_TO_INTEGER_MAP,\n                RealmFieldType.STRING_TO_BOOLEAN_MAP,\n                RealmFieldType.STRING_TO_STRING_MAP,\n                RealmFieldType.STRING_TO_BINARY_MAP,\n                RealmFieldType.STRING_TO_DATE_MAP,\n                RealmFieldType.STRING_TO_FLOAT_MAP,\n                RealmFieldType.STRING_TO_DOUBLE_MAP,\n                RealmFieldType.STRING_TO_DECIMAL128_MAP,\n                RealmFieldType.STRING_TO_OBJECT_ID_MAP,\n                RealmFieldType.STRING_TO_UUID_MAP,\n                RealmFieldType.STRING_TO_MIXED_MAP,\n                RealmFieldType.STRING_TO_LINK_MAP,\n                RealmFieldType.INTEGER_SET,\n                RealmFieldType.BOOLEAN_SET,\n                RealmFieldType.STRING_SET,\n                RealmFieldType.BINARY_SET,\n                RealmFieldType.DATE_SET,\n                RealmFieldType.FLOAT_SET,\n                RealmFieldType.DOUBLE_SET,\n                RealmFieldType.DECIMAL128_SET,\n                RealmFieldType.OBJECT_ID_SET,\n                RealmFieldType.UUID_SET,\n                RealmFieldType.MIXED_SET,\n                RealmFieldType.LINK_SET\n        ));\n\n        SUPPORTED_IS_EMPTY_TYPES = Collections.unmodifiableList(list);\n        SUPPORTED_IS_NOT_EMPTY_TYPES = Collections.unmodifiableList(list);\n\n        list = new ArrayList<>(Arrays.asList(RealmFieldType.values()));\n        list.removeAll(SUPPORTED_IS_EMPTY_TYPES);\n        list.remove(RealmFieldType.TYPED_LINK);\n        list.remove(RealmFieldType.LINK_SET);\n\n        NOT_SUPPORTED_IS_EMPTY_TYPES = Collections.unmodifiableList(list);\n        NOT_SUPPORTED_IS_NOT_EMPTY_TYPES = Collections.unmodifiableList(list);\n    }\n\n    protected Realm realm;\n\n    @Before\n    public void setUp() throws Exception {\n        Realm.init(ApplicationProvider.getApplicationContext());\n        configFactory.create(); // Creates temporary folder (unsure why this is needed when Running RealmQueryTests independently.\n        RealmConfiguration realmConfig = configFactory.createSchemaConfiguration(true, io.realm.entities.conflict.AllJavaTypes.class);\n        realm = Realm.getInstance(realmConfig);\n    }\n\n    @After\n    public void tearDown() throws Exception {\n        if (realm != null) {\n            realm.close();\n        }\n    }\n\n    @SuppressWarnings(\"unchecked\")\n    protected final void createIsEmptyDataSet(Realm realm) {\n        realm.beginTransaction();\n\n        AllJavaTypesUnsupportedTypes emptyValues = new AllJavaTypesUnsupportedTypes();\n        emptyValues.setFieldId(1);\n        emptyValues.setFieldString(\"\");\n        emptyValues.setFieldBinary(new byte[0]);\n        emptyValues.setFieldObject(emptyValues);\n        emptyValues.setFieldList(new RealmList<>());\n        emptyValues.setColumnRealmDictionary(new RealmDictionary<>());\n\n        AllJavaTypesUnsupportedTypes emptyValuesManaged = realm.copyToRealm(emptyValues);\n        AllJavaTypesUnsupportedTypes nonEmpty = new AllJavaTypesUnsupportedTypes();\n        nonEmpty.setFieldId(2);\n        nonEmpty.setFieldString(\"Foo\");\n        nonEmpty.setFieldBinary(new byte[] {1, 2, 3});\n        nonEmpty.setFieldObject(nonEmpty);\n        nonEmpty.setFieldList(new RealmList<>(emptyValuesManaged));\n\n        AllJavaTypesUnsupportedTypes nonEmptyManaged = realm.copyToRealmOrUpdate(nonEmpty);\n        AllJavaTypesUnsupportedTypes emptyValues2 = new AllJavaTypesUnsupportedTypes();\n        emptyValues2.setFieldId(3);\n        emptyValues2.setFieldString(\"\");\n        emptyValues2.setFieldBinary(new byte[0]);\n        emptyValues2.setFieldObject(null);\n        emptyValues2.setFieldList(new RealmList<>(nonEmptyManaged));\n        emptyValues2.setColumnRealmDictionary(new RealmDictionary<>());\n        realm.copyToRealm(emptyValues2);\n\n        realm.commitTransaction();\n    }\n\n    protected final void createLinkedDataSet(Realm realm) {\n        realm.beginTransaction();\n\n        realm.delete(BacklinksSource.class);\n        realm.delete(BacklinksTarget.class);\n\n        BacklinksTarget target1 = realm.createObject(BacklinksTarget.class);\n        target1.setId(1);\n\n        BacklinksTarget target2 = realm.createObject(BacklinksTarget.class);\n        target2.setId(2);\n\n        BacklinksTarget target3 = realm.createObject(BacklinksTarget.class);\n        target3.setId(3);\n\n\n        BacklinksSource source1 = realm.createObject(BacklinksSource.class);\n        source1.setName(\"1\");\n        source1.setChild(target1);\n\n        BacklinksSource source2 = realm.createObject(BacklinksSource.class);\n        source2.setName(\"2\");\n        source2.setChild(target2);\n\n        BacklinksSource source3 = realm.createObject(BacklinksSource.class);\n        source3.setName(\"3\");\n\n        BacklinksSource source4 = realm.createObject(BacklinksSource.class);\n        source4.setName(\"4\");\n        source4.setChild(target1);\n\n        realm.commitTransaction();\n    }\n\n    @SuppressWarnings(\"unchecked\")\n    protected final void createIsNotEmptyDataSet(Realm realm) {\n        realm.beginTransaction();\n\n        AllJavaTypesUnsupportedTypes emptyValues = new AllJavaTypesUnsupportedTypes();\n        emptyValues.setFieldId(1);\n        emptyValues.setFieldString(\"\");\n        emptyValues.setFieldBinary(new byte[0]);\n        emptyValues.setFieldObject(emptyValues);\n        emptyValues.setFieldList(new RealmList<>());\n        realm.copyToRealm(emptyValues);\n\n        AllJavaTypesUnsupportedTypes notEmpty = new AllJavaTypesUnsupportedTypes();\n        notEmpty.setFieldId(2);\n        notEmpty.setFieldString(\"Foo\");\n        notEmpty.setFieldBinary(new byte[] {1, 2, 3});\n        notEmpty.setFieldObject(notEmpty);\n\n        notEmpty.setFieldList(new RealmList<>(emptyValues));\n        notEmpty.setFieldIntegerList(new RealmList<>(1));\n        notEmpty.setFieldBooleanList(new RealmList<>(true));\n        notEmpty.setFieldStringList(new RealmList<>(\"hello\"));\n        notEmpty.setFieldBinaryList(new RealmList<>(new byte[1]));\n        notEmpty.setFieldDateList(new RealmList<>(new Date()));\n        notEmpty.setFieldFloatList(new RealmList<>(1F));\n        notEmpty.setFieldDoubleList(new RealmList<>(1.0));\n        notEmpty.setFieldDecimal128List(new RealmList<>(new Decimal128(1L)));\n        notEmpty.setFieldObjectIdList(new RealmList<>(new ObjectId()));\n        notEmpty.setFieldUUIDList(new RealmList<>(UUID.randomUUID()));\n        notEmpty.setFieldRealmAnyList(new RealmList<>(RealmAny.valueOf(1)));\n\n        notEmpty.setColumnRealmDictionary((RealmDictionary<AllJavaTypesUnsupportedTypes>) getDictionary(RealmFieldType.STRING_TO_LINK_MAP, notEmpty));\n        notEmpty.setColumnIntegerDictionary((RealmDictionary<Integer>) getDictionary(RealmFieldType.STRING_TO_INTEGER_MAP));\n        notEmpty.setColumnBooleanDictionary((RealmDictionary<Boolean>) getDictionary(RealmFieldType.STRING_TO_BOOLEAN_MAP));\n        notEmpty.setColumnStringDictionary((RealmDictionary<String>) getDictionary(RealmFieldType.STRING_TO_STRING_MAP));\n        notEmpty.setColumnBinaryDictionary((RealmDictionary<byte[]>) getDictionary(RealmFieldType.STRING_TO_BINARY_MAP));\n        notEmpty.setColumnDateDictionary((RealmDictionary<Date>) getDictionary(RealmFieldType.STRING_TO_DATE_MAP));\n        notEmpty.setColumnFloatDictionary((RealmDictionary<Float>) getDictionary(RealmFieldType.STRING_TO_FLOAT_MAP));\n        notEmpty.setColumnDoubleDictionary((RealmDictionary<Double>) getDictionary(RealmFieldType.STRING_TO_DOUBLE_MAP));\n        notEmpty.setColumnDecimal128Dictionary((RealmDictionary<Decimal128>) getDictionary(RealmFieldType.STRING_TO_DECIMAL128_MAP));\n        notEmpty.setColumnObjectIdDictionary((RealmDictionary<ObjectId>) getDictionary(RealmFieldType.STRING_TO_OBJECT_ID_MAP));\n        notEmpty.setColumnUUIDDictionary((RealmDictionary<UUID>) getDictionary(RealmFieldType.STRING_TO_UUID_MAP));\n        notEmpty.setColumnRealmAnyDictionary((RealmDictionary<RealmAny>) getDictionary(RealmFieldType.STRING_TO_MIXED_MAP));\n\n        notEmpty.setColumnRealmSet((RealmSet<AllJavaTypesUnsupportedTypes>) getSet(RealmFieldType.LINK_SET, notEmpty));\n        notEmpty.setColumnIntegerSet((RealmSet<Integer>) getSet(RealmFieldType.INTEGER_SET));\n        notEmpty.setColumnBooleanSet((RealmSet<Boolean>) getSet(RealmFieldType.BOOLEAN_SET));\n        notEmpty.setColumnStringSet((RealmSet<String>) getSet(RealmFieldType.STRING_SET));\n        notEmpty.setColumnBinarySet((RealmSet<byte[]>) getSet(RealmFieldType.BINARY_SET));\n        notEmpty.setColumnDateSet((RealmSet<Date>) getSet(RealmFieldType.DATE_SET));\n        notEmpty.setColumnFloatSet((RealmSet<Float>) getSet(RealmFieldType.FLOAT_SET));\n        notEmpty.setColumnDoubleSet((RealmSet<Double>) getSet(RealmFieldType.DOUBLE_SET));\n        notEmpty.setColumnDecimal128Set((RealmSet<Decimal128>) getSet(RealmFieldType.DECIMAL128_SET));\n        notEmpty.setColumnObjectIdSet((RealmSet<ObjectId>) getSet(RealmFieldType.OBJECT_ID_SET));\n        notEmpty.setColumnUUIDSet((RealmSet<UUID>) getSet(RealmFieldType.UUID_SET));\n        notEmpty.setColumnRealmAnySet((RealmSet<RealmAny>) getSet(RealmFieldType.MIXED_SET));\n\n        realm.copyToRealmOrUpdate(notEmpty);\n\n        realm.commitTransaction();\n    }\n\n    private RealmSet<?> getSet(RealmFieldType type) {\n        return getSet(type, null);\n    }\n\n    private RealmSet<?> getSet(RealmFieldType type, @Nullable AllJavaTypesUnsupportedTypes obj) {\n        switch (type) {\n            case INTEGER_SET: {\n                RealmSet<Integer> set = new RealmSet<>();\n                set.add(1);\n                return set;\n            }\n            case BOOLEAN_SET: {\n                RealmSet<Boolean> set = new RealmSet<>();\n                set.add(true);\n                return set;\n            }\n            case STRING_SET: {\n                RealmSet<String> set = new RealmSet<>();\n                set.add(\"VALUE\");\n                return set;\n            }\n            case BINARY_SET: {\n                RealmSet<byte[]> set = new RealmSet<>();\n                set.add(new byte[1]);\n                return set;\n            }\n            case DATE_SET: {\n                RealmSet<Date> set = new RealmSet<>();\n                set.add(new Date());\n                return set;\n            }\n            case FLOAT_SET: {\n                RealmSet<Float> set = new RealmSet<>();\n                set.add(1.0F);\n                return set;\n            }\n            case DOUBLE_SET: {\n                RealmSet<Double> set = new RealmSet<>();\n                set.add(1D);\n                return set;\n            }\n            case DECIMAL128_SET: {\n                RealmSet<Decimal128> set = new RealmSet<>();\n                set.add(new Decimal128(1L));\n                return set;\n            }\n            case OBJECT_ID_SET: {\n                RealmSet<ObjectId> set = new RealmSet<>();\n                set.add(new ObjectId());\n                return set;\n            }\n            case UUID_SET: {\n                RealmSet<UUID> set = new RealmSet<>();\n                set.add(UUID.randomUUID());\n                return set;\n            }\n            case LINK_SET: {\n                RealmSet<AllJavaTypesUnsupportedTypes> set = new RealmSet<>();\n                set.add(obj);\n                return set;\n            }\n            case MIXED_SET: {\n                RealmSet<RealmAny> set = new RealmSet<>();\n                set.add(RealmAny.valueOf(1));\n                return set;\n            }\n            default:\n                throw new IllegalStateException(\"Unexpected value: \" + type);\n        }\n    }\n\n    private RealmDictionary<?> getDictionary(RealmFieldType type) {\n        return getDictionary(type, null);\n    }\n\n    private RealmDictionary<?> getDictionary(RealmFieldType type, @Nullable AllJavaTypesUnsupportedTypes obj) {\n        switch (type) {\n            case STRING_TO_INTEGER_MAP: {\n                RealmDictionary<Integer> dict = new RealmDictionary<>();\n                dict.put(\"KEY\", 1);\n                return dict;\n            }\n            case STRING_TO_BOOLEAN_MAP: {\n                RealmDictionary<Boolean> dict = new RealmDictionary<>();\n                dict.put(\"KEY\", true);\n                return dict;\n            }\n            case STRING_TO_STRING_MAP: {\n                RealmDictionary<String> dict = new RealmDictionary<>();\n                dict.put(\"KEY\", \"VALUE\");\n                return dict;\n            }\n            case STRING_TO_BINARY_MAP: {\n                RealmDictionary<byte[]> dict = new RealmDictionary<>();\n                dict.put(\"KEY\", new byte[1]);\n                return dict;\n            }\n            case STRING_TO_DATE_MAP: {\n                RealmDictionary<Date> dict = new RealmDictionary<>();\n                dict.put(\"KEY\", new Date());\n                return dict;\n            }\n            case STRING_TO_FLOAT_MAP: {\n                RealmDictionary<Float> dict = new RealmDictionary<>();\n                dict.put(\"KEY\", 1.0F);\n                return dict;\n            }\n            case STRING_TO_DOUBLE_MAP: {\n                RealmDictionary<Double> dict = new RealmDictionary<>();\n                dict.put(\"KEY\", 1D);\n                return dict;\n            }\n            case STRING_TO_DECIMAL128_MAP: {\n                RealmDictionary<Decimal128> dict = new RealmDictionary<>();\n                dict.put(\"KEY\", new Decimal128(1L));\n                return dict;\n            }\n            case STRING_TO_OBJECT_ID_MAP: {\n                RealmDictionary<ObjectId> dict = new RealmDictionary<>();\n                dict.put(\"KEY\", new ObjectId());\n                return dict;\n            }\n            case STRING_TO_UUID_MAP: {\n                RealmDictionary<UUID> dict = new RealmDictionary<>();\n                dict.put(\"KEY\", UUID.randomUUID());\n                return dict;\n            }\n            case STRING_TO_MIXED_MAP: {\n                RealmDictionary<RealmAny> dict = new RealmDictionary<>();\n                dict.put(\"KEY\", RealmAny.valueOf(1));\n                return dict;\n            }\n            case STRING_TO_LINK_MAP: {\n                RealmDictionary<AllJavaTypesUnsupportedTypes> dict = new RealmDictionary<>();\n                dict.put(\"KEY\", obj);\n                return dict;\n            }\n            default:\n                throw new IllegalStateException(\"Unexpected value: \" + type);\n        }\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/RealmAnnotationTests.java",
    "content": "/*\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\npackage io.realm;\n\nimport androidx.test.ext.junit.runners.AndroidJUnit4;\n\nimport org.junit.After;\nimport org.junit.Before;\nimport org.junit.Rule;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\n\nimport io.realm.entities.AnnotationIndexTypes;\nimport io.realm.entities.AnnotationNameConventions;\nimport io.realm.entities.AnnotationTypes;\nimport io.realm.entities.PrimaryKeyAsLong;\nimport io.realm.entities.PrimaryKeyAsString;\nimport io.realm.exceptions.RealmPrimaryKeyConstraintException;\nimport io.realm.internal.OsObjectStore;\nimport io.realm.internal.Table;\n\nimport static org.junit.Assert.assertEquals;\nimport static org.junit.Assert.assertFalse;\nimport static org.junit.Assert.assertNotNull;\nimport static org.junit.Assert.assertTrue;\nimport static org.junit.Assert.fail;\n\n@RunWith(AndroidJUnit4.class)\npublic class RealmAnnotationTests {\n    private Realm realm;\n\n    @Rule\n    public final TestRealmConfigurationFactory configFactory = new TestRealmConfigurationFactory();\n\n    @Before\n    public void setUp() {\n        RealmConfiguration realmConfig = configFactory.createConfiguration();\n        realm = Realm.getInstance(realmConfig);\n        realm.beginTransaction();\n        AnnotationTypes object = realm.createObject(AnnotationTypes.class, 0);\n        object.setNotIndexString(\"String 1\");\n        object.setIndexString(\"String 2\");\n        object.setIgnoreString(\"String 3\");\n        object.setTransientString(\"String 4\");\n        realm.commitTransaction();\n    }\n\n    @After\n    public void tearDown() {\n        if (realm != null) {\n            realm.close();\n        }\n    }\n\n    @Test\n    public void ignore() {\n        Table table = realm.getTable(AnnotationTypes.class);\n        assertEquals(-1, table.getColumnKey(AnnotationTypes.FIELD_IGNORE_STRING));\n        assertEquals(-1, table.getColumnKey(AnnotationTypes.FIELD_TRANSIENT_STRING));\n    }\n\n    // Tests if \"index\" annotation works with supported types.\n    @Test\n    public void index() {\n        Table table = realm.getTable(AnnotationIndexTypes.class);\n\n        assertTrue(table.hasSearchIndex(table.getColumnKey(\"indexString\")));\n        assertFalse(table.hasSearchIndex(table.getColumnKey(\"notIndexString\")));\n\n        assertTrue(table.hasSearchIndex(table.getColumnKey(\"indexInt\")));\n        assertFalse(table.hasSearchIndex(table.getColumnKey(\"notIndexInt\")));\n\n        assertTrue(table.hasSearchIndex(table.getColumnKey(\"indexByte\")));\n        assertFalse(table.hasSearchIndex(table.getColumnKey(\"notIndexByte\")));\n\n        assertTrue(table.hasSearchIndex(table.getColumnKey(\"indexShort\")));\n        assertFalse(table.hasSearchIndex(table.getColumnKey(\"notIndexShort\")));\n\n        assertTrue(table.hasSearchIndex(table.getColumnKey(\"indexLong\")));\n        assertFalse(table.hasSearchIndex(table.getColumnKey(\"notIndexLong\")));\n\n        assertTrue(table.hasSearchIndex(table.getColumnKey(\"indexBoolean\")));\n        assertFalse(table.hasSearchIndex(table.getColumnKey(\"notIndexBoolean\")));\n\n        assertTrue(table.hasSearchIndex(table.getColumnKey(\"indexDate\")));\n        assertFalse(table.hasSearchIndex(table.getColumnKey(\"notIndexDate\")));\n    }\n\n    @Test\n    public void primaryKey_checkPrimaryKeyOnCreate() {\n        realm.beginTransaction();\n        try {\n            realm.createObject(AnnotationTypes.class, 0);\n            fail(\"Two empty objects cannot be created on the same table if a primary key is defined\");\n        } catch (RealmPrimaryKeyConstraintException ignored) {\n        } finally {\n            realm.cancelTransaction();\n        }\n    }\n\n    @Test\n    public void primaryKey_errorOnInsertingSameObject() {\n        try {\n            realm.beginTransaction();\n            realm.createObject(AnnotationTypes.class, 1);\n            realm.createObject(AnnotationTypes.class, 1);\n            fail(\"Inserting two objects with same primary key should fail\");\n        } catch (RealmPrimaryKeyConstraintException ignored) {\n        } finally {\n            realm.cancelTransaction();\n        }\n    }\n\n    @Test\n    public void string_primaryKey_isIndexed() {\n        // Before Core 6 only String primary keys did not have a Index as a default\n        // With Core 10, primary keys do not need indexes in general and they where removed (file\n        // format 21), but it turned out this was causing problems with performance when upgrading\n        // Realm files. In pathological cases, upgrades could take minutes, so this decision was\n        // reverted and indexes was re-added in file format v22.\n        Table table = realm.getTable(PrimaryKeyAsString.class);\n        assertNotNull(OsObjectStore.getPrimaryKeyForObject(realm.getSharedRealm(), PrimaryKeyAsString.CLASS_NAME));\n        assertTrue(table.hasSearchIndex(table.getColumnKey(\"name\")));\n\n        table = realm.getTable(PrimaryKeyAsLong.class);\n        assertNotNull(OsObjectStore.getPrimaryKeyForObject(realm.getSharedRealm(), PrimaryKeyAsLong.CLASS_NAME));\n        assertTrue(table.hasSearchIndex(table.getColumnKey(\"id\")));\n    }\n\n    // Annotation processor honors common naming conventions.\n    // We check if setters and getters are generated and working.\n    @Test\n    public void namingConvention() {\n        realm.beginTransaction();\n        realm.delete(AnnotationNameConventions.class);\n        AnnotationNameConventions anc1 = realm.createObject(AnnotationNameConventions.class);\n        anc1.setHasObject(true);\n        anc1.setId_object(1);\n        anc1.setmObject(2);\n        anc1.setObject_id(3);\n        anc1.setObject(true);\n        realm.commitTransaction();\n\n        AnnotationNameConventions anc2 = realm.where(AnnotationNameConventions.class).findFirst();\n        assertTrue(anc2.isHasObject());\n        assertEquals(1, anc2.getId_object());\n        assertEquals(2, anc2.getmObject());\n        assertEquals(3, anc2.getObject_id());\n        assertTrue(anc2.isObject());\n        realm.close();\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/RealmAsyncQueryTests.java",
    "content": "/*\n * Copyright 2015 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\npackage io.realm;\n\nimport android.os.SystemClock;\n\nimport androidx.test.ext.junit.runners.AndroidJUnit4;\n\nimport org.junit.Rule;\nimport org.junit.Test;\nimport org.junit.rules.ExpectedException;\nimport org.junit.runner.RunWith;\n\nimport java.util.Date;\nimport java.util.Random;\nimport java.util.concurrent.CountDownLatch;\nimport java.util.concurrent.atomic.AtomicBoolean;\nimport java.util.concurrent.atomic.AtomicInteger;\n\nimport io.realm.entities.AllJavaTypes;\nimport io.realm.entities.AllTypes;\nimport io.realm.entities.AnnotationIndexTypes;\nimport io.realm.entities.Dog;\nimport io.realm.entities.NonLatinFieldNames;\nimport io.realm.entities.Owner;\nimport io.realm.internal.async.RealmThreadPoolExecutor;\nimport io.realm.log.LogLevel;\nimport io.realm.log.RealmLog;\nimport io.realm.rule.RunInLooperThread;\nimport io.realm.rule.RunTestInLooperThread;\nimport io.realm.util.RealmBackgroundTask;\n\nimport static org.junit.Assert.assertEquals;\nimport static org.junit.Assert.assertFalse;\nimport static org.junit.Assert.assertNotNull;\nimport static org.junit.Assert.assertNull;\nimport static org.junit.Assert.assertTrue;\nimport static org.junit.Assert.fail;\n\n@RunWith(AndroidJUnit4.class)\npublic class RealmAsyncQueryTests {\n    @Rule\n    public final RunInLooperThread looperThread = new RunInLooperThread();\n    @Rule\n    public final TestRealmConfigurationFactory configFactory = new TestRealmConfigurationFactory();\n    @Rule\n    public final ExpectedException thrown = ExpectedException.none();\n\n\n    // ****************************\n    // ****  Async transaction  ***\n    // ****************************\n\n    // Starts asynchronously a transaction to insert one element.\n    @Test\n    @RunTestInLooperThread\n    public void executeTransactionAsync() throws Throwable {\n        final Realm realm = looperThread.getRealm();\n        assertEquals(0, realm.where(Owner.class).count());\n\n        realm.executeTransactionAsync(new Realm.Transaction() {\n            @Override\n            public void execute(Realm realm) {\n                Owner owner = realm.createObject(Owner.class);\n                owner.setName(\"Owner\");\n            }\n        }, new Realm.Transaction.OnSuccess() {\n            @Override\n            public void onSuccess() {\n                assertEquals(1, realm.where(Owner.class).count());\n                assertEquals(\"Owner\", realm.where(Owner.class).findFirst().getName());\n                looperThread.testComplete();\n            }\n        }, new Realm.Transaction.OnError() {\n\n            @Override\n            public void onError(Throwable error) {\n                fail(error.getMessage());\n            }\n        });\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void executeTransactionAsync_onSuccess() throws Throwable {\n        final Realm realm = looperThread.getRealm();\n        assertEquals(0, realm.where(Owner.class).count());\n\n        realm.executeTransactionAsync(new Realm.Transaction() {\n            @Override\n            public void execute(Realm realm) {\n                Owner owner = realm.createObject(Owner.class);\n                owner.setName(\"Owner\");\n            }\n        }, new Realm.Transaction.OnSuccess() {\n            @Override\n            public void onSuccess() {\n                assertEquals(1, realm.where(Owner.class).count());\n                assertEquals(\"Owner\", realm.where(Owner.class).findFirst().getName());\n                looperThread.testComplete();\n            }\n        });\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void executeTransactionAsync_onSuccessCallerRealmClosed() throws Throwable {\n        final Realm realm = looperThread.getRealm();\n        assertEquals(0, realm.where(Owner.class).count());\n\n        realm.executeTransactionAsync(new Realm.Transaction() {\n            @Override\n            public void execute(Realm realm) {\n                Owner owner = realm.createObject(Owner.class);\n                owner.setName(\"Owner\");\n            }\n        }, new Realm.Transaction.OnSuccess() {\n            @Override\n            public void onSuccess() {\n                assertTrue(realm.isClosed());\n                Realm newRealm = Realm.getInstance(looperThread.getConfiguration());\n                assertEquals(1, newRealm.where(Owner.class).count());\n                assertEquals(\"Owner\", newRealm.where(Owner.class).findFirst().getName());\n                newRealm.close();\n                looperThread.testComplete();\n            }\n        });\n        realm.close();\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void executeTransactionAsync_onError() throws Throwable {\n        final Realm realm = looperThread.getRealm();\n        final RuntimeException runtimeException = new RuntimeException(\"Oh! What a Terrible Failure\");\n        assertEquals(0, realm.where(Owner.class).count());\n\n        realm.executeTransactionAsync(new Realm.Transaction() {\n            @Override\n            public void execute(Realm realm) {\n                throw runtimeException;\n            }\n        }, new Realm.Transaction.OnError() {\n            @Override\n            public void onError(Throwable error) {\n                assertEquals(0, realm.where(Owner.class).count());\n                assertNull(realm.where(Owner.class).findFirst());\n                assertEquals(runtimeException, error);\n                looperThread.testComplete();\n            }\n        });\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void executeTransactionAsync_onErrorCallerRealmClosed() throws Throwable {\n        final Realm realm = looperThread.getRealm();\n        final RuntimeException runtimeException = new RuntimeException(\"Oh! What a Terrible Failure\");\n        assertEquals(0, realm.where(Owner.class).count());\n\n        realm.executeTransactionAsync(new Realm.Transaction() {\n            @Override\n            public void execute(Realm realm) {\n                throw runtimeException;\n            }\n        }, new Realm.Transaction.OnError() {\n            @Override\n            public void onError(Throwable error) {\n                assertTrue(realm.isClosed());\n                Realm newRealm = Realm.getInstance(looperThread.getConfiguration());\n                assertEquals(0, newRealm.where(Owner.class).count());\n                assertNull(newRealm.where(Owner.class).findFirst());\n                assertEquals(runtimeException, error);\n                newRealm.close();\n                looperThread.testComplete();\n            }\n        });\n        realm.close();\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void executeTransactionAsync_NoCallbacks() throws Throwable {\n        final Realm realm = looperThread.getRealm();\n        assertEquals(0, realm.where(Owner.class).count());\n\n        realm.executeTransactionAsync(new Realm.Transaction() {\n            @Override\n            public void execute(Realm realm) {\n                Owner owner = realm.createObject(Owner.class);\n                owner.setName(\"Owner\");\n            }\n        });\n        realm.addChangeListener(new RealmChangeListener<Realm>() {\n            @Override\n            public void onChange(Realm object) {\n                assertEquals(\"Owner\", realm.where(Owner.class).findFirst().getName());\n                looperThread.testComplete();\n            }\n        });\n    }\n\n    // Tests that an async transaction that throws when call cancelTransaction manually.\n    @Test\n    @RunTestInLooperThread\n    public void executeTransactionAsync_cancelTransactionInside() throws Throwable {\n        final TestHelper.TestLogger testLogger = new TestHelper.TestLogger(LogLevel.DEBUG);\n        RealmLog.add(testLogger);\n\n        final Realm realm = looperThread.getRealm();\n\n        assertEquals(0, realm.where(Owner.class).count());\n\n        realm.executeTransactionAsync(new Realm.Transaction() {\n            @Override\n            public void execute(Realm realm) {\n                Owner owner = realm.createObject(Owner.class);\n                owner.setName(\"Owner\");\n                realm.cancelTransaction();\n            }\n        }, new Realm.Transaction.OnSuccess() {\n            @Override\n            public void onSuccess() {\n                fail(\"Should not reach success if runtime exception is thrown in callback.\");\n            }\n        }, new Realm.Transaction.OnError() {\n            @Override\n            public void onError(Throwable error) {\n                // Ensure we are giving developers quality messages in the logs.\n                assertTrue(testLogger.message.contains(\n                        \"Exception has been thrown: Can't commit a non-existing write transaction\"));\n                assertTrue(error instanceof IllegalStateException);\n                RealmLog.remove(testLogger);\n                looperThread.testComplete();\n            }\n        });\n    }\n\n    // Tests if the background Realm is closed when transaction success returned.\n    @Test\n    @RunTestInLooperThread\n    public void executeTransactionAsync_realmClosedOnSuccess() {\n        final AtomicInteger counter = new AtomicInteger(100);\n        final Realm realm = looperThread.getRealm();\n        final RealmCache.Callback cacheCallback = new RealmCache.Callback() {\n            @Override\n            public void onResult(int count) {\n                assertEquals(1, count);\n                if (counter.decrementAndGet() == 0) {\n                    realm.close();\n                    looperThread.testComplete();\n                }\n            }\n        };\n        final Realm.Transaction.OnSuccess transactionCallback = new Realm.Transaction.OnSuccess() {\n            @Override\n            public void onSuccess() {\n                RealmCache.invokeWithGlobalRefCount(realm.getConfiguration(), cacheCallback);\n                if (counter.get() == 0) {\n                    // Finishes testing.\n                    return;\n                }\n                realm.executeTransactionAsync(new Realm.Transaction() {\n                    @Override\n                    public void execute(Realm realm) {\n                    }\n                }, this);\n            }\n        };\n\n        realm.executeTransactionAsync(new Realm.Transaction() {\n            @Override\n            public void execute(Realm realm) {\n            }\n        }, transactionCallback);\n    }\n\n    // Tests if the background Realm is closed when transaction error returned.\n    @Test\n    @RunTestInLooperThread\n    public void executeTransaction_async_realmClosedOnError() {\n        final AtomicInteger counter = new AtomicInteger(100);\n        final Realm realm = looperThread.getRealm();\n        final RealmCache.Callback cacheCallback = new RealmCache.Callback() {\n            @Override\n            public void onResult(int count) {\n                assertEquals(1, count);\n                if (counter.decrementAndGet() == 0) {\n                    realm.close();\n                    looperThread.testComplete();\n                }\n            }\n        };\n        final Realm.Transaction.OnError transactionCallback = new Realm.Transaction.OnError() {\n            @Override\n            public void onError(Throwable error) {\n                RealmCache.invokeWithGlobalRefCount(realm.getConfiguration(), cacheCallback);\n                if (counter.get() == 0) {\n                    // Finishes testing.\n                    return;\n                }\n                realm.executeTransactionAsync(new Realm.Transaction() {\n                    @Override\n                    public void execute(Realm realm) {\n                        throw new RuntimeException(\"Dummy exception\");\n                    }\n                }, this);\n            }\n        };\n\n        realm.executeTransactionAsync(new Realm.Transaction() {\n            @Override\n            public void execute(Realm realm) {\n                throw new RuntimeException(\"Dummy exception\");\n            }\n        }, transactionCallback);\n    }\n\n    // Test case for https://github.com/realm/realm-java/issues/1893\n    // Ensures that onSuccess is called with the correct Realm version for async transaction.\n    @Test\n    @RunTestInLooperThread\n    public void executeTransactionAsync_asyncQuery() {\n        final Realm realm = looperThread.getRealm();\n        final RealmResults<AllTypes> results = realm.where(AllTypes.class).findAllAsync();\n        assertEquals(0, results.size());\n\n        realm.executeTransactionAsync(new Realm.Transaction() {\n            @Override\n            public void execute(Realm realm) {\n                realm.createObject(AllTypes.class);\n            }\n        }, new Realm.Transaction.OnSuccess() {\n            @Override\n            public void onSuccess() {\n                assertEquals(1, realm.where(AllTypes.class).count());\n                // We cannot guarantee the async results get delivered from OS.\n                if (results.isLoaded()) {\n                    assertEquals(1, results.size());\n                } else {\n                    assertEquals(0, results.size());\n                }\n                looperThread.testComplete();\n            }\n        }, new Realm.Transaction.OnError() {\n            @Override\n            public void onError(Throwable error) {\n                fail();\n            }\n        });\n    }\n\n    @Test\n    public void executeTransactionAsync_onSuccessOnNonLooperThreadThrows() {\n        Realm realm = Realm.getInstance(configFactory.createConfiguration());\n        thrown.expect(IllegalStateException.class);\n        try {\n            realm.executeTransactionAsync(new Realm.Transaction() {\n                @Override\n                public void execute(Realm realm) {\n\n                }\n            }, new Realm.Transaction.OnSuccess() {\n                @Override\n                public void onSuccess() {\n                }\n            });\n        } finally {\n            realm.close();\n        }\n    }\n\n    @Test\n    public void executeTransactionAsync_onErrorOnNonLooperThreadThrows() {\n        Realm realm = Realm.getInstance(configFactory.createConfiguration());\n        thrown.expect(IllegalStateException.class);\n        try {\n            realm.executeTransactionAsync(new Realm.Transaction() {\n                @Override\n                public void execute(Realm realm) {\n\n                }\n            }, new Realm.Transaction.OnError() {\n                @Override\n                public void onError(Throwable error) {\n                }\n            });\n        } finally {\n            realm.close();\n        }\n    }\n\n    // https://github.com/realm/realm-java/issues/4595#issuecomment-298830411\n    // onSuccess might commit another transaction which will call didChange. So before calling async transaction\n    // callbacks, the callback should be cleared.\n    @Test\n    @RunTestInLooperThread\n    public void executeTransactionAsync_callbacksShouldBeClearedBeforeCalling()\n            throws NoSuchFieldException, IllegalAccessException {\n        final AtomicInteger callbackCounter = new AtomicInteger(0);\n        final Realm foregroundRealm = looperThread.getRealm();\n\n        // Use single thread executor\n        TestHelper.replaceRealmThreadExecutor(RealmThreadPoolExecutor.newSingleThreadExecutor());\n\n        // To reproduce the issue, the posted callback needs to arrived before the Object Store did_change called.\n        // We just disable the auto refresh here then the did_change won't be called.\n        foregroundRealm.setAutoRefresh(false);\n        foregroundRealm.executeTransactionAsync(new Realm.Transaction() {\n            @Override\n            public void execute(Realm realm) {\n                realm.createObject(AllTypes.class);\n            }\n        }, new Realm.Transaction.OnSuccess() {\n            @Override\n            public void onSuccess() {\n                // This will be called first and only once\n                assertEquals(0, callbackCounter.getAndIncrement());\n\n                // This transaction should never trigger the onSuccess.\n                foregroundRealm.beginTransaction();\n                foregroundRealm.createObject(AllTypes.class);\n                foregroundRealm.commitTransaction();\n            }\n        });\n\n        foregroundRealm.executeTransactionAsync(new Realm.Transaction() {\n            @Override\n            public void execute(Realm realm) {\n                realm.createObject(AllTypes.class);\n            }\n        }, new Realm.Transaction.OnSuccess() {\n            @Override\n            public void onSuccess() {\n                // This will be called 2nd and only once\n                assertEquals(1, callbackCounter.getAndIncrement());\n                looperThread.testComplete();\n            }\n        });\n\n        // Wait for all async tasks finish to ensure the async transaction posted callback will arrive first.\n        TestHelper.resetRealmThreadExecutor();\n        looperThread.postRunnable(new Runnable() {\n            @Override\n            public void run() {\n                // Manually call refresh, so the did_change will be triggered.\n                foregroundRealm.sharedRealm.refresh();\n            }\n        });\n    }\n\n    // ************************************\n    // *** promises based async queries ***\n    // ************************************\n\n    // Finds element [0-4] asynchronously then waits for the promise to be loaded.\n    @Test\n    @RunTestInLooperThread\n    public void findAllAsync() throws Throwable {\n        final Realm realm = looperThread.getRealm();\n        populateTestRealm(realm, 10);\n        final RealmResults<AllTypes> results = realm.where(AllTypes.class)\n                .between(\"columnLong\", 0, 4)\n                .findAllAsync();\n\n        assertFalse(results.isLoaded());\n        assertEquals(0, results.size());\n\n        looperThread.keepStrongReference(results);\n        results.addChangeListener(new RealmChangeListener<RealmResults<AllTypes>>() {\n            @Override\n            public void onChange(RealmResults<AllTypes> object) {\n                assertTrue(results.isLoaded());\n                assertEquals(5, results.size());\n                assertTrue(results.get(0).isValid());\n                looperThread.testComplete();\n            }\n        });\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void accessingRealmListOnUnloadedRealmObjectShouldThrow() {\n        Realm realm = looperThread.getRealm();\n        populateTestRealm(realm, 10);\n        final AllTypes results = realm.where(AllTypes.class)\n                .equalTo(\"columnLong\", 0)\n                .findFirstAsync();\n\n        assertFalse(results.isLoaded());\n        try {\n            results.getColumnRealmList();\n            fail(\"Accessing property on an empty row\");\n        } catch (IllegalStateException ignored) {\n        }\n        looperThread.testComplete();\n    }\n\n    @Test\n    public void unmanagedObjectAsyncBehaviour() {\n        Dog dog = new Dog();\n        dog.setName(\"Akamaru\");\n        dog.setAge(10);\n\n        assertTrue(dog.isLoaded());\n        assertTrue(dog.isValid());\n        assertFalse(dog.isManaged());\n    }\n\n    @Test\n    public void findAllAsync_throwsOnNonLooperThread() throws Throwable {\n        Realm realm = Realm.getInstance(configFactory.createConfiguration());\n        try {\n            realm.where(AllTypes.class).findAllAsync();\n            fail();\n        } catch (IllegalStateException ignored) {\n        } finally {\n            realm.close();\n        }\n    }\n\n    // finding elements [0-4] asynchronously then wait for the promise to be loaded\n    // using a callback to be notified when the data is loaded\n    @Test\n    @RunTestInLooperThread\n    public void findAllAsync_withNotification() throws Throwable {\n        Realm realm = looperThread.getRealm();\n        populateTestRealm(realm, 10);\n        final RealmResults<AllTypes> results = realm.where(AllTypes.class)\n                .between(\"columnLong\", 0, 4)\n                .findAllAsync();\n\n        results.addChangeListener(new RealmChangeListener<RealmResults<AllTypes>>() {\n            @Override\n            public void onChange(RealmResults<AllTypes> object) {\n                assertTrue(results.isLoaded());\n                assertEquals(5, results.size());\n                assertTrue(results.get(4).isValid());\n                looperThread.testComplete();\n            }\n        });\n        looperThread.keepStrongReference(results);\n\n        assertFalse(results.isLoaded());\n        assertEquals(0, results.size());\n    }\n\n    // Transforms an async query into sync by calling load to force\n    // the blocking behaviour.\n    @Test\n    @RunTestInLooperThread\n    public void findAllAsync_forceLoad() throws Throwable {\n        Realm realm = looperThread.getRealm();\n        populateTestRealm(realm, 10);\n        final RealmResults<AllTypes> realmResults = realm.where(AllTypes.class)\n                .between(\"columnLong\", 0, 4)\n                .findAllAsync();\n\n        looperThread.keepStrongReference(realmResults);\n        // Notification should be called as well.\n        realmResults.addChangeListener(new RealmChangeListener<RealmResults<AllTypes>>() {\n            @Override\n            public void onChange(RealmResults<AllTypes> object) {\n                assertTrue(realmResults.isLoaded());\n                assertEquals(5, realmResults.size());\n                looperThread.testComplete();\n\n            }\n        });\n\n        assertFalse(realmResults.isLoaded());\n        assertEquals(0, realmResults.size());\n\n        boolean successful = realmResults.load();\n\n        assertTrue(successful);\n        assertTrue(realmResults.isLoaded());\n        assertEquals(5, realmResults.size());\n    }\n\n    // **********************************\n    // *** 'findFirst' async queries  ***\n    // **********************************\n\n    // Similar UC as #testFindAllAsync using 'findFirst'.\n    @Test\n    @RunTestInLooperThread\n    public void findFirstAsync() {\n        Realm realm = looperThread.getRealm();\n        populateTestRealm(realm, 10);\n\n        final AllTypes asyncObj = realm.where(AllTypes.class).findFirstAsync();\n        assertFalse(asyncObj.isValid());\n        assertFalse(asyncObj.isLoaded());\n        looperThread.keepStrongReference(asyncObj);\n        asyncObj.addChangeListener(new RealmChangeListener<AllTypes>() {\n            @Override\n            public void onChange(AllTypes object) {\n                assertTrue(asyncObj.isLoaded());\n                assertTrue(asyncObj.isValid());\n                looperThread.testComplete();\n            }\n        });\n    }\n\n    // When there is no object match the query condition, findFirstAsync should return with an invalid row.\n    @Test\n    @RunTestInLooperThread\n    public void findFirstAsync_initialEmptyRow() throws Throwable {\n        Realm realm = looperThread.getRealm();\n        final AllTypes firstAsync = realm.where(AllTypes.class).findFirstAsync();\n        looperThread.keepStrongReference(firstAsync);\n        firstAsync.addChangeListener(new RealmChangeListener<AllTypes>() {\n            @Override\n            public void onChange(AllTypes object) {\n                assertTrue(firstAsync.isLoaded());\n                assertFalse(firstAsync.isValid());\n                looperThread.testComplete();\n            }\n        });\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void findFirstAsync_updatedIfSyncRealmObjectIsUpdated() throws Throwable {\n        populateTestRealm(looperThread.getRealm(), 1);\n        AllTypes firstSync = looperThread.getRealm().where(AllTypes.class).findFirst();\n        assertEquals(0, firstSync.getColumnLong());\n        assertEquals(\"test data 0\", firstSync.getColumnString());\n\n        final AllTypes firstAsync = looperThread.getRealm().where(AllTypes.class).findFirstAsync();\n        assertTrue(firstAsync.load());\n        assertTrue(firstAsync.isLoaded());\n        assertTrue(firstAsync.isValid());\n        assertEquals(0, firstAsync.getColumnLong());\n        assertEquals(\"test data 0\", firstAsync.getColumnString());\n\n        looperThread.keepStrongReference(firstAsync);\n        firstAsync.addChangeListener(new RealmChangeListener<AllTypes>() {\n            @Override\n            public void onChange(AllTypes object) {\n                assertEquals(\"Galacticon\", firstAsync.getColumnString());\n                looperThread.testComplete();\n            }\n        });\n\n        looperThread.getRealm().beginTransaction();\n        firstSync.setColumnString(\"Galacticon\");\n        looperThread.getRealm().commitTransaction();\n    }\n\n    // Finds elements [0-4] asynchronously then waits for the promise to be loaded\n    // using a callback to be notified when the data is loaded.\n    @Test\n    @RunTestInLooperThread\n    public void findFirstAsync_withNotification() throws Throwable {\n        Realm realm = looperThread.getRealm();\n        populateTestRealm(realm, 10);\n        final AllTypes realmResults = realm.where(AllTypes.class)\n                .between(\"columnLong\", 4, 9)\n                .findFirstAsync();\n\n        looperThread.keepStrongReference(realmResults);\n        realmResults.addChangeListener(new RealmChangeListener<AllTypes>() {\n            @Override\n            public void onChange(AllTypes object) {\n                assertTrue(realmResults.isLoaded());\n                assertTrue(realmResults.isValid());\n                assertEquals(\"test data 4\", realmResults.getColumnString());\n                looperThread.testComplete();\n            }\n        });\n\n        assertFalse(realmResults.isLoaded());\n        assertFalse(realmResults.isValid());\n        try {\n            realmResults.setColumnString(\"should fail\");\n            fail(\"Accessing an unloaded object should throw\");\n        } catch (IllegalStateException ignored) {\n        }\n    }\n\n    // load should trigger the listener with empty change set.\n    @Test\n    @RunTestInLooperThread\n    public void findFirstAsync_forceLoad() throws Throwable {\n        final AtomicBoolean listenerCalled = new AtomicBoolean(false);\n        Realm realm = looperThread.getRealm();\n        populateTestRealm(realm, 10);\n        final AllTypes realmResults = realm.where(AllTypes.class)\n                .between(\"columnLong\", 4, 9)\n                .findFirstAsync();\n\n        assertFalse(realmResults.isLoaded());\n\n        realmResults.addChangeListener(new RealmObjectChangeListener<RealmModel>() {\n            @Override\n            public void onChange(RealmModel object, ObjectChangeSet changeSet) {\n                assertNull(changeSet);\n                assertFalse(listenerCalled.get());\n                listenerCalled.set(true);\n            }\n        });\n\n        assertTrue(realmResults.load());\n        assertTrue(realmResults.isLoaded());\n        assertEquals(\"test data 4\", realmResults.getColumnString());\n\n        assertTrue(listenerCalled.get());\n        looperThread.testComplete();\n    }\n\n    // For issue https://github.com/realm/realm-java/issues/4495\n    @Test\n    @RunTestInLooperThread\n    public void findFirstAsync_twoListenersOnSameInvalidObjectsCauseNPE() {\n        final Realm realm = looperThread.getRealm();\n        final AllTypes allTypes = realm.where(AllTypes.class).findFirstAsync();\n        final AtomicBoolean firstListenerCalled = new AtomicBoolean(false);\n        looperThread.keepStrongReference(allTypes);\n\n        allTypes.addChangeListener(new RealmChangeListener<AllTypes>() {\n            @Override\n            public void onChange(AllTypes element) {\n                allTypes.removeChangeListener(this);\n                assertFalse(firstListenerCalled.getAndSet(true));\n                if (!element.isValid()) {\n                    realm.beginTransaction();\n                    realm.createObject(AllTypes.class);\n                    realm.commitTransaction();\n                }\n            }\n        });\n\n        allTypes.addChangeListener(new RealmChangeListener<AllTypes>() {\n            @Override\n            public void onChange(AllTypes element) {\n                allTypes.removeChangeListener(this);\n                assertTrue(firstListenerCalled.get());\n                assertFalse(element.isValid());\n                looperThread.testComplete();\n            }\n        });\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void findFirstAsync_withSorting() {\n        Realm realm = looperThread.getRealm();\n        realm.beginTransaction();\n        realm.insert(new Dog(\"Milo\"));\n        realm.insert(new Dog(\"Fido\"));\n        realm.insert(new Dog(\"Bella\"));\n        realm.commitTransaction();\n\n        Dog dog = realm.where(Dog.class).sort(\"name\").findFirstAsync();\n        dog.addChangeListener((Dog d) -> {\n            assertTrue(d.isValid());\n            assertEquals(\"Bella\", d.getName());\n            looperThread.testComplete();\n        });\n        looperThread.keepStrongReference(dog);\n    }\n\n    // **************************************\n    // *** 'findAllSorted' async queries  ***\n    // **************************************\n\n    // similar UC as #testFindAllAsync using 'findAllSorted'\n    @Test\n    @RunTestInLooperThread\n    public void sort_async() throws Throwable {\n        final Realm realm = looperThread.getRealm();\n        populateTestRealm(realm, 10);\n\n        final RealmResults<AllTypes> results = realm.where(AllTypes.class)\n                .between(\"columnLong\", 0, 4)\n                .sort(\"columnString\", Sort.DESCENDING)\n                .findAllAsync();\n\n        assertFalse(results.isLoaded());\n        assertEquals(0, results.size());\n\n        looperThread.keepStrongReference(results);\n        results.addChangeListener(new RealmChangeListener<RealmResults<AllTypes>>() {\n            @Override\n            public void onChange(RealmResults<AllTypes> object) {\n                assertTrue(results.isLoaded());\n                assertEquals(5, results.size());\n                for (int i = 0; i < 5; i++) {\n                    int iteration = (4 - i);\n                    assertEquals(\"test data \" + iteration, results.get(4 - iteration).getColumnString());\n                }\n                looperThread.testComplete();\n            }\n        });\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void combiningAsyncAndSync() {\n        populateTestRealm(looperThread.getRealm(), 10);\n\n        final RealmResults<AllTypes> allTypesAsync = looperThread.getRealm().where(AllTypes.class).greaterThan(\"columnLong\", 5).findAllAsync();\n        final RealmResults<AllTypes> allTypesSync = allTypesAsync.where().greaterThan(\"columnLong\", 3).findAll();\n\n        // Call where() on an async results will load query. But to maintain the pre version 2.4.0 behaviour of\n        // RealmResults.load(), we still treat it as a not loaded results.\n        assertEquals(0, allTypesAsync.size());\n        assertEquals(4, allTypesSync.size()); // columnLong > 5 && columnLong > 3\n        allTypesAsync.addChangeListener(new RealmChangeListener<RealmResults<AllTypes>>() {\n            @Override\n            public void onChange(RealmResults<AllTypes> object) {\n                assertEquals(4, allTypesAsync.size());\n                assertEquals(4, allTypesSync.size());\n                looperThread.testComplete();\n            }\n        });\n        looperThread.keepStrongReference(allTypesAsync);\n    }\n\n    // Keeps advancing the Realm by sending 1 commit for each frame (16ms).\n    // The async queries should keep up with the modification.\n    @Test\n    @RunTestInLooperThread\n    public void stressTestBackgroundCommits() throws Throwable {\n        final int NUMBER_OF_COMMITS = 100;\n        final CountDownLatch bgRealmClosed = new CountDownLatch(1);\n        final long[] latestLongValue = new long[1];\n        final float[] latestFloatValue = new float[1];\n\n        // Starts a background thread that pushes a commit every 16ms.\n        final Thread backgroundThread = new Thread() {\n            @Override\n            public void run() {\n                Random random = new Random(System.currentTimeMillis());\n                Realm backgroundThreadRealm = Realm.getInstance(looperThread.getRealm().getConfiguration());\n                for (int i = 0; i < NUMBER_OF_COMMITS; i++) {\n                    backgroundThreadRealm.beginTransaction();\n                    AllTypes object = backgroundThreadRealm.createObject(AllTypes.class);\n                    latestLongValue[0] = random.nextInt(100);\n                    latestFloatValue[0] = random.nextFloat();\n                    object.setColumnFloat(latestFloatValue[0]);\n                    object.setColumnLong(latestLongValue[0]);\n                    backgroundThreadRealm.commitTransaction();\n\n                    // Waits 16ms. Before adding the next commit.\n                    SystemClock.sleep(16);\n                }\n                backgroundThreadRealm.close();\n                bgRealmClosed.countDown();\n            }\n        };\n\n        final RealmResults<AllTypes> allAsync = looperThread.getRealm().where(AllTypes.class).findAllAsync();\n        allAsync.addChangeListener(new RealmChangeListener<RealmResults<AllTypes>>() {\n            @Override\n            public void onChange(RealmResults<AllTypes> object) {\n                assertTrue(allAsync.isLoaded());\n                if (allAsync.size() == NUMBER_OF_COMMITS) {\n                    AllTypes lastInserted = looperThread.getRealm().where(AllTypes.class)\n                            .equalTo(\"columnLong\", latestLongValue[0])\n                            .equalTo(\"columnFloat\", latestFloatValue[0])\n                            .findFirst();\n                    assertNotNull(lastInserted);\n                    TestHelper.awaitOrFail(bgRealmClosed);\n                    looperThread.testComplete();\n                }\n            }\n        });\n        looperThread.keepStrongReference(allAsync);\n\n        looperThread.postRunnableDelayed(new Runnable() {\n            @Override\n            public void run() {\n                backgroundThread.start();\n            }\n        }, 16);\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void distinct_async() throws Throwable {\n        Realm realm = looperThread.getRealm();\n        final long numberOfBlocks = 25;\n        final long numberOfObjects = 10; // Must be greater than 1\n        populateForDistinct(realm, numberOfBlocks, numberOfObjects, false);\n\n        final RealmResults<AnnotationIndexTypes> distinctBool = realm.where(AnnotationIndexTypes.class).distinct(\"indexBoolean\").findAllAsync();\n        final RealmResults<AnnotationIndexTypes> distinctLong = realm.where(AnnotationIndexTypes.class).distinct(\"indexLong\").findAllAsync();\n        final RealmResults<AnnotationIndexTypes> distinctDate = realm.where(AnnotationIndexTypes.class).distinct(\"indexDate\").findAllAsync();\n        final RealmResults<AnnotationIndexTypes> distinctString = realm.where(AnnotationIndexTypes.class).distinct(\"indexString\").findAllAsync();\n\n        assertFalse(distinctBool.isLoaded());\n        assertTrue(distinctBool.isValid());\n        assertTrue(distinctBool.isEmpty());\n\n        assertFalse(distinctLong.isLoaded());\n        assertTrue(distinctLong.isValid());\n        assertTrue(distinctLong.isEmpty());\n\n        assertFalse(distinctDate.isLoaded());\n        assertTrue(distinctDate.isValid());\n        assertTrue(distinctDate.isEmpty());\n\n        assertFalse(distinctString.isLoaded());\n        assertTrue(distinctString.isValid());\n        assertTrue(distinctString.isEmpty());\n\n        final Runnable changeListenerDone = new Runnable() {\n            final AtomicInteger signalCallbackFinished = new AtomicInteger(4);\n            @Override\n            public void run() {\n                if (signalCallbackFinished.decrementAndGet() == 0) {\n                    looperThread.testComplete();\n                }\n            }\n        };\n\n        looperThread.keepStrongReference(distinctBool);\n        looperThread.keepStrongReference(distinctLong);\n        looperThread.keepStrongReference(distinctDate);\n        looperThread.keepStrongReference(distinctString);\n        distinctBool.addChangeListener(new RealmChangeListener<RealmResults<AnnotationIndexTypes>>() {\n            @Override\n            public void onChange(RealmResults<AnnotationIndexTypes> object) {\n                assertEquals(2, distinctBool.size());\n                changeListenerDone.run();\n            }\n        });\n\n        distinctLong.addChangeListener(new RealmChangeListener<RealmResults<AnnotationIndexTypes>>() {\n            @Override\n            public void onChange(RealmResults<AnnotationIndexTypes> object) {\n                assertEquals(numberOfBlocks, distinctLong.size());\n                changeListenerDone.run();\n            }\n        });\n\n        distinctDate.addChangeListener(new RealmChangeListener<RealmResults<AnnotationIndexTypes>>() {\n            @Override\n            public void onChange(RealmResults<AnnotationIndexTypes> object) {\n                assertEquals(numberOfBlocks, distinctDate.size());\n                changeListenerDone.run();\n            }\n        });\n\n        distinctString.addChangeListener(new RealmChangeListener<RealmResults<AnnotationIndexTypes>>() {\n            @Override\n            public void onChange(RealmResults<AnnotationIndexTypes> object) {\n                assertEquals(numberOfBlocks, distinctString.size());\n                changeListenerDone.run();\n            }\n        });\n    }\n\n    @Test\n    @RunTestInLooperThread()\n    public void distinct_async_rememberQueryParams() {\n        final Realm realm = looperThread.getRealm();\n        realm.beginTransaction();\n        final int TEST_SIZE = 10;\n        for (int i = 0; i < TEST_SIZE; i++) {\n            realm.createObject(AllJavaTypes.class, i);\n        }\n        realm.commitTransaction();\n\n        RealmResults<AllJavaTypes> results = realm.where(AllJavaTypes.class)\n                .notEqualTo(AllJavaTypes.FIELD_ID, TEST_SIZE / 2)\n                .distinct(AllJavaTypes.FIELD_ID)\n                .findAllAsync();\n\n        results.addChangeListener(new RealmChangeListener<RealmResults<AllJavaTypes>>() {\n            @Override\n            public void onChange(RealmResults<AllJavaTypes> results) {\n                assertEquals(TEST_SIZE - 1, results.size());\n                assertEquals(0, results.where().equalTo(AllJavaTypes.FIELD_ID, TEST_SIZE / 2).count());\n                looperThread.testComplete();\n            }\n        });\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void distinctAsync_notIndexedFields() throws Throwable {\n        Realm realm = looperThread.getRealm();\n        final long numberOfBlocks = 25;\n        final long numberOfObjects = 10; // Must be greater than 1\n        populateForDistinct(realm, numberOfBlocks, numberOfObjects, false);\n\n        final RealmResults<AnnotationIndexTypes> distinctBool = realm.where(AnnotationIndexTypes.class)\n                .distinct(AnnotationIndexTypes.FIELD_NOT_INDEX_BOOL)\n                .findAllAsync();\n        final RealmResults<AnnotationIndexTypes> distinctLong = realm.where(AnnotationIndexTypes.class)\n                .distinct(AnnotationIndexTypes.FIELD_NOT_INDEX_LONG)\n                .findAllAsync();\n        final RealmResults<AnnotationIndexTypes> distinctDate = realm.where(AnnotationIndexTypes.class)\n                .distinct(AnnotationIndexTypes.FIELD_NOT_INDEX_DATE)\n                .findAllAsync();\n        final RealmResults<AnnotationIndexTypes> distinctString = realm.where(AnnotationIndexTypes.class)\n                .distinct(AnnotationIndexTypes.FIELD_INDEX_STRING)\n                .findAllAsync();\n\n        assertFalse(distinctBool.isLoaded());\n        assertTrue(distinctBool.isValid());\n        assertTrue(distinctBool.isEmpty());\n\n        assertFalse(distinctLong.isLoaded());\n        assertTrue(distinctLong.isValid());\n        assertTrue(distinctLong.isEmpty());\n\n        assertFalse(distinctDate.isLoaded());\n        assertTrue(distinctDate.isValid());\n        assertTrue(distinctDate.isEmpty());\n\n        assertFalse(distinctString.isLoaded());\n        assertTrue(distinctString.isValid());\n        assertTrue(distinctString.isEmpty());\n\n        final Runnable changeListenerDone = new Runnable() {\n            final AtomicInteger signalCallbackFinished = new AtomicInteger(4);\n            @Override\n            public void run() {\n                if (signalCallbackFinished.decrementAndGet() == 0) {\n                    looperThread.testComplete();\n                }\n            }\n        };\n\n        looperThread.keepStrongReference(distinctBool);\n        looperThread.keepStrongReference(distinctLong);\n        looperThread.keepStrongReference(distinctDate);\n        looperThread.keepStrongReference(distinctString);\n        distinctBool.addChangeListener(new RealmChangeListener<RealmResults<AnnotationIndexTypes>>() {\n            @Override\n            public void onChange(RealmResults<AnnotationIndexTypes> object) {\n                assertEquals(2, distinctBool.size());\n                changeListenerDone.run();\n            }\n        });\n\n        distinctLong.addChangeListener(new RealmChangeListener<RealmResults<AnnotationIndexTypes>>() {\n            @Override\n            public void onChange(RealmResults<AnnotationIndexTypes> object) {\n                assertEquals(numberOfBlocks, distinctLong.size());\n                changeListenerDone.run();\n            }\n        });\n\n        distinctDate.addChangeListener(new RealmChangeListener<RealmResults<AnnotationIndexTypes>>() {\n            @Override\n            public void onChange(RealmResults<AnnotationIndexTypes> object) {\n                assertEquals(numberOfBlocks, distinctDate.size());\n                changeListenerDone.run();\n            }\n        });\n\n        distinctString.addChangeListener(new RealmChangeListener<RealmResults<AnnotationIndexTypes>>() {\n            @Override\n            public void onChange(RealmResults<AnnotationIndexTypes> object) {\n                assertEquals(numberOfBlocks, distinctString.size());\n                changeListenerDone.run();\n            }\n        });\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void distinctAsync_noneExistingField() throws Throwable {\n        Realm realm = looperThread.getRealm();\n        final long numberOfBlocks = 25;\n        final long numberOfObjects = 10; // Must be greater than 1\n        populateForDistinct(realm, numberOfBlocks, numberOfObjects, false);\n\n        try {\n            realm.where(AnnotationIndexTypes.class).distinct(\"doesNotExist\").findAllAsync();\n            fail();\n        } catch (IllegalArgumentException ignored) {\n            looperThread.testComplete();\n        }\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void batchUpdateDifferentTypeOfQueries() {\n        final Realm realm = looperThread.getRealm();\n        realm.beginTransaction();\n        for (int i = 0; i < 5; ) {\n            AllTypes allTypes = realm.createObject(AllTypes.class);\n            allTypes.setColumnLong(i);\n            allTypes.setColumnString(\"data \" + i % 3);\n\n            allTypes = realm.createObject(AllTypes.class);\n            allTypes.setColumnLong(i);\n            allTypes.setColumnString(\"data \" + (++i % 3));\n        }\n        final long numberOfBlocks = 25;\n        final long numberOfObjects = 10; // Must be greater than 1\n        realm.commitTransaction();\n        populateForDistinct(realm, numberOfBlocks, numberOfObjects, false);\n\n        RealmResults<AllTypes> findAllAsync = realm.where(AllTypes.class).findAllAsync();\n        RealmResults<AllTypes> findAllSorted = realm.where(AllTypes.class).sort(\"columnString\", Sort.ASCENDING).findAllAsync();\n        RealmResults<AllTypes> findAllSortedMulti = realm.where(AllTypes.class).sort(new String[]{\"columnString\", \"columnLong\"},\n                new Sort[]{Sort.ASCENDING, Sort.DESCENDING}).findAllAsync();\n        RealmResults<AnnotationIndexTypes> findDistinct = realm.where(AnnotationIndexTypes.class).distinct(\"indexString\").findAllAsync();\n\n        looperThread.keepStrongReference(findAllAsync);\n        looperThread.keepStrongReference(findAllSorted);\n        looperThread.keepStrongReference(findAllSortedMulti);\n        looperThread.keepStrongReference(findDistinct);\n\n        final CountDownLatch queriesCompleted = new CountDownLatch(4);\n        final CountDownLatch bgRealmClosedLatch = new CountDownLatch(1);\n        final AtomicInteger batchUpdateCompleted = new AtomicInteger(0);\n        final AtomicInteger findAllAsyncInvocation = new AtomicInteger(0);\n        final AtomicInteger findAllSortedInvocation = new AtomicInteger(0);\n        final AtomicInteger findAllSortedMultiInvocation = new AtomicInteger(0);\n        final AtomicInteger findDistinctInvocation = new AtomicInteger(0);\n\n        findAllAsync.addChangeListener(new RealmChangeListener<RealmResults<AllTypes>>() {\n            @Override\n            public void onChange(RealmResults<AllTypes> object) {\n                switch (findAllAsyncInvocation.incrementAndGet()) {\n                    case 1: {\n                        queriesCompleted.countDown();\n                        break;\n                    }\n                    case 2: {\n                        if (batchUpdateCompleted.incrementAndGet() == 4) {\n                            looperThread.testComplete(bgRealmClosedLatch);\n                        }\n                        break;\n                    }\n                }\n            }\n        });\n\n        findAllSorted.addChangeListener(new RealmChangeListener<RealmResults<AllTypes>>() {\n            @Override\n            public void onChange(RealmResults<AllTypes> object) {\n                switch (findAllSortedInvocation.incrementAndGet()) {\n                    case 1: {\n                        queriesCompleted.countDown();\n                        break;\n                    }\n                    case 2: {\n                        if (batchUpdateCompleted.incrementAndGet() == 4) {\n                            looperThread.testComplete(bgRealmClosedLatch);\n                        }\n                        break;\n                    }\n                }\n            }\n        });\n\n        findAllSortedMulti.addChangeListener(new RealmChangeListener<RealmResults<AllTypes>>() {\n            @Override\n            public void onChange(RealmResults<AllTypes> object) {\n                switch (findAllSortedMultiInvocation.incrementAndGet()) {\n                    case 1: {\n                        queriesCompleted.countDown();\n                        break;\n                    }\n                    case 2: {\n                        if (batchUpdateCompleted.incrementAndGet() == 4) {\n                            looperThread.testComplete(bgRealmClosedLatch);\n                        }\n                        break;\n                    }\n                }\n            }\n        });\n\n        findDistinct.addChangeListener(new RealmChangeListener<RealmResults<AnnotationIndexTypes>>() {\n            @Override\n            public void onChange(RealmResults<AnnotationIndexTypes> object) {\n                switch (findDistinctInvocation.incrementAndGet()) {\n                    case 1: {\n                        queriesCompleted.countDown();\n                        break;\n                    }\n                    case 2: {\n                        if (batchUpdateCompleted.incrementAndGet() == 4) {\n                            looperThread.testComplete(bgRealmClosedLatch);\n                        }\n                        break;\n                    }\n                }\n            }\n        });\n\n        // Waits for the queries to complete then sends a commit from\n        // another thread to trigger a batch update of the 4 queries.\n        new Thread() {\n            @Override\n            public void run() {\n                TestHelper.awaitOrFail(queriesCompleted);\n                Realm bgRealm = Realm.getInstance(realm.getConfiguration());\n\n                bgRealm.beginTransaction();\n                bgRealm.createObject(AllTypes.class);\n                bgRealm.createObject(AnnotationIndexTypes.class);\n                bgRealm.commitTransaction();\n\n                bgRealm.close();\n                bgRealmClosedLatch.countDown();\n            }\n        }.start();\n    }\n\n    // This test makes sure that Async queries update when using link.\n    @Test\n    @RunTestInLooperThread\n    public void queryingLinkHandover() throws Throwable {\n        final AtomicInteger numberOfInvocations = new AtomicInteger(0);\n        final Realm realm = looperThread.getRealm();\n\n        final RealmResults<Dog> allAsync = realm.where(Dog.class).equalTo(\"owner.name\", \"kiba\").findAllAsync();\n        looperThread.keepStrongReference(allAsync);\n        allAsync.addChangeListener(new RealmChangeListener<RealmResults<Dog>>() {\n            @Override\n            public void onChange(RealmResults<Dog> object) {\n                switch (numberOfInvocations.incrementAndGet()) {\n                    case 1:\n                        assertEquals(0, allAsync.size());\n                        assertTrue(allAsync.isLoaded());\n                        assertTrue(allAsync.isValid());\n                        assertTrue(allAsync.isEmpty());\n                        new RealmBackgroundTask(realm.getConfiguration()) {\n                            @Override\n                            public void doInBackground(Realm realm) {\n                                realm.beginTransaction();\n                                Dog dog = realm.createObject(Dog.class);\n                                dog.setAge(10);\n                                dog.setName(\"Akamaru\");\n                                Owner kiba = realm.createObject(Owner.class);\n                                kiba.setName(\"kiba\");\n                                dog.setOwner(kiba);\n                                realm.commitTransaction();\n                            }\n                        }.awaitOrFail();\n                        break;\n\n                    case 2:\n                        assertEquals(1, realm.where(Dog.class).count());\n                        assertEquals(1, realm.where(Owner.class).count());\n                        assertEquals(1, allAsync.size());\n                        assertTrue(allAsync.isLoaded());\n                        assertTrue(allAsync.isValid());\n                        assertFalse(allAsync.isEmpty());\n                        assertEquals(1, allAsync.size());\n                        assertEquals(\"Akamaru\", allAsync.get(0).getName());\n                        assertEquals(\"kiba\", allAsync.get(0).getOwner().getName());\n                        looperThread.testComplete();\n                        break;\n                }\n            }\n        });\n    }\n\n    // Test case for https://github.com/realm/realm-java/issues/2417\n    // Ensures that a UnreachableVersion exception during handover doesn't crash the app or cause a segfault.\n    // NOTE: This test is not checking the same thing after the OS results integration. Just keep it for an additional\n    // test for async.\n    @Test\n    @RunTestInLooperThread\n    public void badVersion_syncTransaction() throws NoSuchFieldException, IllegalAccessException {\n        final AtomicInteger listenerCount = new AtomicInteger(0);\n        Realm realm = looperThread.getRealm();\n\n        // 1. Makes sure that async query is not started.\n        final RealmResults<AllTypes> result = realm.where(AllTypes.class).sort(AllTypes.FIELD_STRING).findAllAsync();\n        looperThread.keepStrongReference(result);\n        result.addChangeListener(new RealmChangeListener<RealmResults<AllTypes>>() {\n            @Override\n            public void onChange(RealmResults<AllTypes> object) {\n                assertTrue(result.isValid());\n                assertTrue(result.isLoaded());\n                switch (listenerCount.getAndIncrement()) {\n                    case 0:\n                        // Triggered by beginTransaction\n                        assertEquals(0, result.size());\n                        break;\n                    case 1:\n                        // 4. The commit in #2, should result in a refresh being triggered, which means this callback will\n                        // be notified once the updated async queries has run.\n                        assertEquals(1, result.size());\n                        looperThread.testComplete();\n                        break;\n                    default:\n                        fail();\n                        break;\n                }\n            }\n        });\n\n        // 2. Advances the caller Realm, invalidating the version in the handover object.\n        realm.beginTransaction();\n        assertTrue(result.isLoaded());\n        realm.createObject(AllTypes.class);\n        realm.commitTransaction();\n\n        // 3. The async query should now (hopefully) fail with a BadVersion.\n        // NOTE: Step 3 is from the original test. After integration of Object Store Results, it has been loaded already\n        //       when beginTransaction.\n        result.load();\n    }\n\n    // This test reproduces the issue in https://secure.helpscout.net/conversation/244053233/6163/?folderId=366141\n    // First it creates 512 async queries, then trigger a transaction to make the queries gets update with\n    // nativeBatchUpdateQueries. It should not exceed the limits of local ref map size in JNI.\n    // NOTE: This test is not checking the same thing after the OS results integration. Just keep it for an additional\n    // test for async.\n    @Test\n    @RunTestInLooperThread\n    public void batchUpdate_localRefIsDeletedInLoopOfNativeBatchUpdateQueries() {\n        final Realm realm = looperThread.getRealm();\n        // For Android, the size of local ref map is 512. Uses 1024 for more pressure.\n        final int TEST_COUNT = 1024;\n        final AtomicBoolean updatesTriggered = new AtomicBoolean(false);\n        // The first time onChange gets called for every results.\n        final AtomicInteger firstOnChangeCounter = new AtomicInteger(0);\n        // The second time onChange gets called for every results which is triggered by the transaction.\n        final AtomicInteger secondOnChangeCounter = new AtomicInteger(0);\n\n        final RealmChangeListener<RealmResults<AllTypes>> listener = new RealmChangeListener<RealmResults<AllTypes>>() {\n            @Override\n            public void onChange(RealmResults<AllTypes> element) {\n                if (updatesTriggered.get())  {\n                    // Step 4: Test finished after all results's onChange gets called the 2nd time.\n                    int count  = secondOnChangeCounter.addAndGet(1);\n                    if (count == TEST_COUNT) {\n                        realm.removeAllChangeListeners();\n                        looperThread.testComplete();\n                    }\n                } else {\n                    int count  = firstOnChangeCounter.addAndGet(1);\n                    if (count == TEST_COUNT) {\n                        // Step 3: Commits the transaction to trigger queries updates.\n                        updatesTriggered.set(true);\n                        realm.executeTransactionAsync(new Realm.Transaction() {\n                            @Override\n                            public void execute(Realm realm) {\n                                realm.createObject(AllTypes.class);\n                            }\n                        });\n                    } else {\n                        // Step 2: Creates 2nd - TEST_COUNT queries.\n                        RealmResults<AllTypes> results = realm.where(AllTypes.class).findAllAsync();\n                        results.addChangeListener(this);\n                        looperThread.keepStrongReference(results);\n                    }\n                }\n            }\n        };\n        // Step 1. Creates first async to kick the test start.\n        RealmResults<AllTypes> results = realm.where(AllTypes.class).findAllAsync();\n        results.addChangeListener(listener);\n        looperThread.keepStrongReference(results);\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void freezeAsyncResults() {\n        int DATA_SIZE = 10;\n        Realm realm = looperThread.getRealm();\n        populateTestRealm(realm, DATA_SIZE);\n        RealmResults<AllTypes> results = realm.where(AllTypes.class).findAllAsync();\n        looperThread.keepStrongReference(results);\n        assertFalse(results.isLoaded());\n        assertTrue(results.isValid());\n        assertEquals(0, results.size());\n        assertFalse(results.isFrozen());\n\n        RealmResults<AllTypes> frozenResults = results.freeze();\n        assertTrue(frozenResults.isFrozen());\n        assertFalse(frozenResults.isLoaded());\n        assertTrue(frozenResults.isValid());\n        assertEquals(0, frozenResults.size());\n\n        results.addChangeListener(new RealmChangeListener<RealmResults<AllTypes>>() {\n            @Override\n            public void onChange(RealmResults<AllTypes> results) {\n                assertTrue(results.isLoaded());\n                assertTrue(results.isValid());\n                assertEquals(DATA_SIZE, results.size());\n\n                assertFalse(frozenResults.isLoaded());\n                assertTrue(frozenResults.isValid());\n                assertEquals(0, frozenResults.size());\n                looperThread.testComplete();\n            }\n        });\n    }\n\n    // *** Helper methods ***\n\n    private void populateTestRealm(final Realm testRealm, int objects) {\n        testRealm.setAutoRefresh(false);\n        testRealm.beginTransaction();\n        testRealm.deleteAll();\n        for (int i = 0; i < objects; ++i) {\n            AllTypes allTypes = testRealm.createObject(AllTypes.class);\n            allTypes.setColumnBoolean((i % 3) == 0);\n            allTypes.setColumnBinary(new byte[]{1, 2, 3});\n            allTypes.setColumnDate(new Date());\n            allTypes.setColumnDouble(Math.PI);\n            allTypes.setColumnFloat(1.234567f + i);\n            allTypes.setColumnString(\"test data \" + i);\n            allTypes.setColumnLong(i);\n            NonLatinFieldNames nonLatinFieldNames = testRealm.createObject(NonLatinFieldNames.class);\n            nonLatinFieldNames.set델타(i);\n            nonLatinFieldNames.setΔέλτα(i);\n            nonLatinFieldNames.set베타(1.234567f + i);\n            nonLatinFieldNames.setΒήτα(1.234567f + i);\n        }\n        testRealm.commitTransaction();\n        testRealm.setAutoRefresh(true);\n    }\n\n    private void populateForDistinct(Realm realm, long numberOfBlocks, long numberOfObjects, boolean withNull) {\n        realm.beginTransaction();\n        for (int i = 0; i < numberOfObjects * numberOfBlocks; i++) {\n            for (int j = 0; j < numberOfBlocks; j++) {\n                AnnotationIndexTypes obj = realm.createObject(AnnotationIndexTypes.class);\n                obj.setIndexBoolean(j % 2 == 0);\n                obj.setIndexLong(j);\n                obj.setIndexDate(withNull ? null : new Date(1000L * j));\n                obj.setIndexString(withNull ? null : \"Test \" + j);\n                obj.setNotIndexBoolean(j % 2 == 0);\n                obj.setNotIndexLong(j);\n                obj.setNotIndexDate(withNull ? null : new Date(1000L * j));\n                obj.setNotIndexString(withNull ? null : \"Test \" + j);\n            }\n        }\n        realm.commitTransaction();\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/RealmCacheTests.java",
    "content": "/*\n * Copyright 2015 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\npackage io.realm;\n\nimport android.content.Context;\nimport androidx.test.platform.app.InstrumentationRegistry;\nimport androidx.test.ext.junit.runners.AndroidJUnit4;\n\nimport org.junit.Before;\nimport org.junit.Rule;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\n\nimport java.io.File;\nimport java.io.IOException;\nimport java.util.concurrent.CountDownLatch;\nimport java.util.concurrent.atomic.AtomicBoolean;\nimport java.util.concurrent.atomic.AtomicReference;\n\nimport io.realm.entities.AllJavaTypes;\nimport io.realm.entities.AllTypes;\nimport io.realm.entities.StringOnly;\nimport io.realm.exceptions.RealmFileException;\nimport io.realm.rule.RunInLooperThread;\nimport io.realm.rule.RunTestInLooperThread;\n\nimport static org.junit.Assert.assertEquals;\nimport static org.junit.Assert.assertFalse;\nimport static org.junit.Assert.assertNotNull;\nimport static org.junit.Assert.assertNull;\nimport static org.junit.Assert.assertSame;\nimport static org.junit.Assert.assertTrue;\nimport static org.junit.Assert.fail;\n\n@RunWith(AndroidJUnit4.class)\npublic class RealmCacheTests {\n\n    @Rule\n    public final RunInLooperThread looperThread = new RunInLooperThread();\n    @Rule\n    public final TestRealmConfigurationFactory configFactory = new TestRealmConfigurationFactory();\n\n    private RealmConfiguration defaultConfig;\n    private Context context;\n\n    @Before\n    public void setUp() {\n        defaultConfig = configFactory.createConfiguration();\n        context = InstrumentationRegistry.getInstrumentation().getContext();\n    }\n\n    // Tests that the closed Realm isn't kept in the Realm instance cache.\n    @Test\n    public void typedRealmCacheIsCleared() {\n        Realm typedRealm = Realm.getInstance(defaultConfig);\n        DynamicRealm dynamicRealm = DynamicRealm.getInstance(defaultConfig);\n\n        typedRealm.close(); // Still a dynamic instance open, but the typed Realm cache must still be cleared.\n        dynamicRealm.close();\n\n        Realm typedRealm1 = Realm.getInstance(defaultConfig);\n        try {\n            assertFalse(typedRealm == typedRealm1); // Must be different instance.\n            // If cache isn't cleared this would crash because of a closed shared group.\n            assertEquals(0, typedRealm1.where(AllTypes.class).count());\n        } finally {\n            typedRealm1.close();\n        }\n    }\n\n    // Tests that the closed DynamicRealms isn't kept in the DynamicRealm instance cache.\n    @Test\n    public void dynamicRealmCacheIsCleared() {\n        DynamicRealm dynamicRealm = DynamicRealm.getInstance(defaultConfig);\n        Realm typedRealm = Realm.getInstance(defaultConfig);\n\n        dynamicRealm.close(); // Still an instance open, but DynamicRealm cache must still be cleared.\n        typedRealm.close();\n\n        DynamicRealm dynamicRealm1 = DynamicRealm.getInstance(defaultConfig);\n        try {\n            // If cache isn't cleared this would crash because of a closed shared group.\n            assertFalse(dynamicRealm == dynamicRealm1);\n            assertEquals(0, dynamicRealm1.getVersion());\n        } finally {\n            dynamicRealm1.close();\n        }\n    }\n\n    @Test\n    public void getInstanceClearsCacheWhenFailed() {\n        String REALM_NAME = \"invalid_cache.realm\";\n        RealmConfiguration configA = configFactory.createConfiguration(REALM_NAME,\n                TestHelper.getRandomKey(42));\n        RealmConfiguration configB = configFactory.createConfiguration(REALM_NAME,\n                TestHelper.getRandomKey(43));\n\n        Realm realm = Realm.getInstance(configA); // Creates starting Realm with key 1.\n        realm.close();\n        try {\n            Realm.getInstance(configB); // Tries to open with key 2.\n            fail();\n        } catch (RealmFileException expected) {\n            assertEquals(RealmFileException.Kind.ACCESS_ERROR, expected.getKind());\n            // Deletes Realm so key 2 works. This should work as a Realm shouldn't be cached\n            // if initialization failed.\n            assertTrue(Realm.deleteRealm(configA));\n            realm = Realm.getInstance(configB);\n            realm.close();\n        }\n    }\n\n    @Test\n    public void realmCache() {\n        Realm realm = Realm.getInstance(defaultConfig);\n        Realm newRealm = Realm.getInstance(defaultConfig);\n        try {\n            assertEquals(realm, newRealm);\n        } finally {\n            realm.close();\n            newRealm.close();\n        }\n    }\n\n    // We should not cache wrong configurations.\n    @Test\n    public void dontCacheWrongConfigurations() throws IOException {\n        Realm testRealm;\n        String REALM_NAME = \"encrypted.realm\";\n\n        RealmConfiguration wrongConfig = configFactory.createConfigurationBuilder()\n                .name(REALM_NAME)\n                .encryptionKey(TestHelper.SHA512(\"foo\"))\n                .schema(StringOnly.class)\n                .build();\n\n        RealmConfiguration rightConfig = configFactory.createConfigurationBuilder()\n                .name(REALM_NAME)\n                .encryptionKey(TestHelper.SHA512(\"realm\"))\n                .schema(StringOnly.class)\n                .build();\n\n        // Create the realm with proper key.\n        testRealm = Realm.getInstance(rightConfig);\n        assertNotNull(testRealm);\n        testRealm.close();\n\n        // Opens Realm with wrong key.\n        try {\n            Realm.getInstance(wrongConfig);\n            fail();\n        } catch (RealmFileException expected) {\n            assertEquals(RealmFileException.Kind.ACCESS_ERROR, expected.getKind());\n        }\n\n        // Tries again with proper key.\n        testRealm = Realm.getInstance(rightConfig);\n        assertNotNull(testRealm);\n        testRealm.close();\n    }\n\n    @Test\n    public void deletingRealmAlsoClearsConfigurationCache() throws IOException {\n        String REALM_NAME = \"encrypted.realm\";\n        byte[] oldPassword = TestHelper.SHA512(\"realm\");\n        byte[] newPassword = TestHelper.SHA512(\"realm-copy\");\n\n        RealmConfiguration config = configFactory.createConfigurationBuilder()\n                .name(REALM_NAME)\n                .encryptionKey(oldPassword)\n                .schema(StringOnly.class)\n                .build();\n\n        // 1. Writes a copy of the encrypted Realm to a new file.\n        Realm testRealm = Realm.getInstance(config);\n        File copiedRealm = new File(config.getRealmDirectory(), \"encrypted-copy.realm\");\n        if (copiedRealm.exists()) {\n            assertTrue(copiedRealm.delete());\n        }\n        testRealm.writeEncryptedCopyTo(copiedRealm, newPassword);\n        testRealm.close();\n\n        // 2. Deletes the old Realm.\n        assertTrue(Realm.deleteRealm(config));\n\n        // 3. Renames the new file to the old file name.\n        assertTrue(copiedRealm.renameTo(new File(config.getRealmDirectory(), REALM_NAME)));\n\n        // 4. Tries to open the file again with the new password.\n        // If the configuration cache wasn't cleared this would fail as we would detect two\n        // configurations with 2 different passwords pointing to the same file.\n        RealmConfiguration newConfig = configFactory.createConfigurationBuilder()\n                .name(REALM_NAME)\n                .encryptionKey(newPassword)\n                .schema(StringOnly.class)\n                .build();\n\n        testRealm = Realm.getInstance(newConfig);\n        assertNotNull(testRealm);\n        testRealm.close();\n    }\n\n    // Tests that if the same Realm file is opened on multiple threads, we only need to validate the\n    // schema on the first thread\n    // When there is a transaction holding by a typed Realm in one thread, getInstance from the\n    // other thread should not be blocked since we have cached the schemas already.\n    @Test\n    public void getInstance_shouldNotBeBlockedByTransactionInAnotherThread()\n            throws InterruptedException {\n        Realm realm = Realm.getInstance(defaultConfig);\n        final CountDownLatch latch = new CountDownLatch(1);\n        realm.beginTransaction();\n\n        Thread thread = new Thread(new Runnable() {\n            @Override\n            public void run() {\n                Realm realm = Realm.getInstance(defaultConfig);\n                realm.close();\n                latch.countDown();\n            }\n        });\n        thread.start();\n        TestHelper.awaitOrFail(latch);\n        realm.cancelTransaction();\n        realm.close();\n    }\n\n    @Test\n    public void differentThreadsDifferentInstance() throws InterruptedException {\n        final CountDownLatch closeLatch = new CountDownLatch(1);\n\n        final Realm realmA = Realm.getInstance(defaultConfig);\n\n        Thread thread = new Thread(new Runnable() {\n            @Override\n            public void run() {\n                Realm realmB = Realm.getInstance(defaultConfig);\n                assertFalse(realmA == realmB);\n                RealmCache.invokeWithGlobalRefCount(defaultConfig,\n                        new TestHelper.ExpectedCountCallback(2));\n                realmB.close();\n                closeLatch.countDown();\n            }\n        });\n        thread.start();\n\n        TestHelper.awaitOrFail(closeLatch);\n        RealmCache.invokeWithGlobalRefCount(defaultConfig, new TestHelper.ExpectedCountCallback(1));\n        realmA.close();\n        RealmCache.invokeWithGlobalRefCount(defaultConfig, new TestHelper.ExpectedCountCallback(0));\n    }\n\n    @Test\n    public void getInstance_differentConfigurationsShouldNotBlockEachOther() throws InterruptedException {\n        final CountDownLatch bgThreadStarted = new CountDownLatch(1);\n        final CountDownLatch realm2CreatedLatch = new CountDownLatch(1);\n\n        final RealmConfiguration config1 = configFactory.createConfigurationBuilder()\n                .name(\"config1.realm\")\n                .schema(AllJavaTypes.class)\n                .initialData(new Realm.Transaction() {\n                    @Override\n                    public void execute(Realm realm) {\n                        bgThreadStarted.countDown();\n                        TestHelper.awaitOrFail(realm2CreatedLatch);\n                    }\n                })\n                .build();\n\n        RealmConfiguration config2 = configFactory.createConfigurationBuilder()\n                .name(\"config2.realm\")\n                .schema(AllJavaTypes.class)\n                .build();\n\n        Thread thread = new Thread(new Runnable() {\n            @Override\n            public void run() {\n                Realm realm = Realm.getInstance(config1);\n                realm.close();\n            }\n        });\n        thread.start();\n\n        TestHelper.awaitOrFail(bgThreadStarted);\n        Realm realm = Realm.getInstance(config2);\n        realm2CreatedLatch.countDown();\n        realm.close();\n        thread.join();\n    }\n\n    @Test\n    public void releaseCacheInOneThread() {\n        // Tests release typed Realm instance.\n        Realm realmA = RealmCache.createRealmOrGetFromCache(defaultConfig, Realm.class);\n        Realm realmB = RealmCache.createRealmOrGetFromCache(defaultConfig, Realm.class);\n        realmA.close();\n        assertNotNull(realmA.sharedRealm);\n        realmB.close();\n        assertNull(realmB.sharedRealm);\n        // No crash but warning in the log.\n        realmB.close();\n\n        // Tests release dynamic Realm instance.\n        DynamicRealm dynamicRealmA = RealmCache.createRealmOrGetFromCache(defaultConfig,\n                DynamicRealm.class);\n        DynamicRealm dynamicRealmB = RealmCache.createRealmOrGetFromCache(defaultConfig,\n                DynamicRealm.class);\n        dynamicRealmA.close();\n        assertNotNull(dynamicRealmA.sharedRealm);\n        dynamicRealmB.close();\n        assertNull(dynamicRealmB.sharedRealm);\n        // No crash but warning in the log.\n        dynamicRealmB.close();\n\n        // Tests both typed Realm and dynamic Realm in same thread.\n        realmA = RealmCache.createRealmOrGetFromCache(defaultConfig, Realm.class);\n        dynamicRealmA = RealmCache.createRealmOrGetFromCache(defaultConfig, DynamicRealm.class);\n        realmA.close();\n        assertNull(realmA.sharedRealm);\n        dynamicRealmA.close();\n        assertNull(realmA.sharedRealm);\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void getInstanceAsync_typedRealm() {\n        final RealmConfiguration configuration = looperThread.createConfiguration();\n        final AtomicBoolean realmCreated = new AtomicBoolean(false);\n        Realm.getInstanceAsync(configuration, new Realm.Callback() {\n            @Override\n            public void onSuccess(Realm realm) {\n                realmCreated.set(true);\n                assertEquals(1, Realm.getLocalInstanceCount(configuration));\n                realm.close();\n                looperThread.testComplete();\n            }\n        });\n        assertFalse(realmCreated.get());\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void getInstanceAsync_dynamicRealm() {\n        final RealmConfiguration configuration = looperThread.createConfiguration();\n        final AtomicBoolean realmCreated = new AtomicBoolean(false);\n        DynamicRealm.getInstanceAsync(configuration, new DynamicRealm.Callback() {\n            @Override\n            public void onSuccess(DynamicRealm realm) {\n                realmCreated.set(true);\n                assertEquals(1, Realm.getLocalInstanceCount(configuration));\n                realm.close();\n                looperThread.testComplete();\n            }\n        });\n        assertFalse(realmCreated.get());\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void getInstanceAsync_callbackDeliveredInFollowingEventLoopWhenLocalCacheExist() {\n        final RealmConfiguration configuration = looperThread.createConfiguration();\n        final AtomicBoolean realmCreated = new AtomicBoolean(false);\n        final Realm localRealm = Realm.getInstance(configuration);\n        Realm.getInstanceAsync(configuration, new Realm.Callback() {\n            @Override\n            public void onSuccess(Realm realm) {\n                realmCreated.set(true);\n                assertEquals(2, Realm.getLocalInstanceCount(configuration));\n                assertSame(realm, localRealm);\n                realm.close();\n                localRealm.close();\n                looperThread.testComplete();\n            }\n        });\n        assertFalse(realmCreated.get());\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void getInstanceAsync_callbackDeliveredInFollowingEventLoopWhenGlobalCacheExist() throws InterruptedException {\n        final RealmConfiguration configuration = looperThread.createConfiguration();\n        final AtomicBoolean realmCreated = new AtomicBoolean(false);\n        final CountDownLatch globalRealmCreated = new CountDownLatch(1);\n        final CountDownLatch getAsyncFinishedLatch = new CountDownLatch(1);\n\n        final Thread thread = new Thread(new Runnable() {\n            @Override\n            public void run() {\n                Realm realm = Realm.getInstance(configuration);\n                globalRealmCreated.countDown();\n                TestHelper.awaitOrFail(getAsyncFinishedLatch);\n                realm.close();\n            }\n        });\n        thread.start();\n\n        TestHelper.awaitOrFail(globalRealmCreated);\n        Realm.getInstanceAsync(configuration, new Realm.Callback() {\n            @Override\n            public void onSuccess(Realm realm) {\n                realmCreated.set(true);\n                assertEquals(1, Realm.getLocalInstanceCount(configuration));\n                realm.close();\n                getAsyncFinishedLatch.countDown();\n                try {\n                    thread.join();\n                } catch (InterruptedException e) {\n                    fail();\n                }\n                looperThread.testComplete();\n            }\n        });\n        assertFalse(realmCreated.get());\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void getInstanceAsync_typedRealmShouldStillBeInitializedInBGIfOnlyDynamicRealmExists() {\n        final RealmConfiguration configuration = looperThread.createConfiguration();\n        final DynamicRealm dynamicRealm = DynamicRealm.getInstance(configuration);\n        final AtomicBoolean realmCreated = new AtomicBoolean(false);\n\n        Realm.getInstanceAsync(configuration, new Realm.Callback() {\n            @Override\n            public void onSuccess(Realm realm) {\n                realmCreated.set(false);\n                assertEquals(2, Realm.getLocalInstanceCount(configuration));\n                dynamicRealm.close();\n                realm.close();\n                looperThread.testComplete();\n            }\n        });\n        // Callback should not be called immediately since we need to create column indices cache in bg thread.\n        // Only a local dynamic Realm instance existing at this time.\n        assertFalse(realmCreated.get());\n        assertEquals(1, Realm.getLocalInstanceCount(configuration));\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void getInstanceAsync_onError() {\n        final RealmConfiguration configuration =\n                looperThread.createConfigurationBuilder()\n                .assetFile(\"NotExistingFile\")\n                .build();\n        Realm.getInstanceAsync(configuration, new Realm.Callback() {\n            @Override\n            public void onSuccess(Realm realm) {\n                fail();\n            }\n\n            @Override\n            public void onError(Throwable exception) {\n                assertTrue(exception instanceof RealmFileException);\n                looperThread.testComplete();\n            }\n        });\n    }\n\n    // If the async task is canceled before the posted event to create Realm instance in caller thread, the event should\n    // just be ignored.\n    @Test\n    @RunTestInLooperThread\n    public void getInstanceAsync_cancelBeforePostShouldNotCreateRealmInstanceOnTheCallerThread() {\n        final AtomicReference<RealmAsyncTask> realmAsyncTasks = new AtomicReference<>();\n        final Runnable finishedRunnable = new Runnable() {\n            @Override\n            public void run() {\n                looperThread.testComplete();\n            }\n        };\n        final RealmConfiguration configuration = looperThread.createConfigurationBuilder()\n                .name(\"will_be_canceled\")\n                .initialData(new Realm.Transaction() {\n                    @Override\n                    public void execute(Realm realm) {\n                        // The BG thread started to initial the first Realm instance. Post an event to the caller's\n                        // queue to cancel the task before the event to create the Realm instance in caller thread.\n                        looperThread.postRunnable(new Runnable() {\n                            @Override\n                            public void run() {\n                                assertNotNull(realmAsyncTasks.get());\n                                realmAsyncTasks.get().cancel();\n                                // Wait the async task to be terminated.\n                                TestHelper.waitRealmThreadExecutorFinish();\n                                // Finish the test.\n                                looperThread.postRunnable(finishedRunnable);\n                            }\n                        });\n                    }\n                })\n                .build();\n\n        realmAsyncTasks.set(Realm.getInstanceAsync(configuration, new Realm.Callback() {\n            @Override\n            public void onSuccess(Realm realm) {\n                fail();\n            }\n        }));\n    }\n\n    // The DynamicRealm and Realm with the same Realm path should share the same RealmCache\n    @Test\n    public void typedRealmAndDynamicRealmShareTheSameCache() {\n        final String DB_NAME = \"same_name.realm\";\n        RealmConfiguration config1 = configFactory.createConfigurationBuilder()\n                .name(DB_NAME)\n                .build();\n\n        RealmConfiguration config2 = configFactory.createConfigurationBuilder()\n                .name(DB_NAME)\n                .initialData(new Realm.Transaction() {\n                    @Override\n                    public void execute(Realm realm) {\n                        // Because of config1 doesn't have initialData block, these two configurations are not the same.\n                        // So if a Realm is created with config1, then create another Realm with config2 should just\n                        // fail before executing this block.\n                        fail();\n                    }\n                })\n                .build();\n\n        DynamicRealm dynamicRealm = DynamicRealm.getInstance(config1);\n        Realm realm = null;\n        try {\n            realm = Realm.getInstance(config2);\n            fail();\n        } catch (IllegalArgumentException ignored) {\n        } finally {\n            dynamicRealm.close();\n            if (realm != null) {\n                realm.close();\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/RealmChangeListenerTests.java",
    "content": "/*\n * Copyright 2016 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\npackage io.realm;\n\nimport org.hamcrest.CoreMatchers;\nimport org.junit.After;\nimport org.junit.Before;\nimport org.junit.Rule;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\n\nimport androidx.test.ext.junit.runners.AndroidJUnit4;\nimport androidx.test.rule.UiThreadTestRule;\n\nimport io.realm.entities.AllTypes;\nimport io.realm.entities.BacklinksSource;\nimport io.realm.entities.BacklinksTarget;\nimport io.realm.entities.Cat;\nimport io.realm.entities.StringOnly;\nimport io.realm.entities.pojo.AllTypesRealmModel;\nimport io.realm.log.RealmLog;\nimport io.realm.rule.RunInLooperThread;\nimport io.realm.rule.RunTestInLooperThread;\n\nimport static org.hamcrest.MatcherAssert.assertThat;\nimport static org.junit.Assert.assertEquals;\nimport static org.junit.Assert.assertFalse;\nimport static org.junit.Assert.assertNotNull;\nimport static org.junit.Assert.assertTrue;\n\n@RunWith(AndroidJUnit4.class)\npublic class RealmChangeListenerTests {\n    @Rule\n    public final UiThreadTestRule uiThreadTestRule = new UiThreadTestRule();\n    @Rule\n    public final RunInLooperThread looperThread = new RunInLooperThread();\n    @Rule\n    public final TestRealmConfigurationFactory configFactory = new TestRealmConfigurationFactory();\n\n    private Realm realm;\n    private RealmConfiguration realmConfig;\n\n    @Before\n    public void setUp() {\n        realmConfig = configFactory.createConfiguration();\n    }\n\n    @After\n    public void tearDown() {\n        if (realm != null) {\n            realm.close();\n        }\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void returnedRealmIsNotNull() {\n        Realm realm = looperThread.getRealm();\n        realm.addChangeListener(new RealmChangeListener<Realm>() {\n            @Override\n            public void onChange(Realm realm) {\n                assertNotNull(realm);\n                assertFalse(realm.isClosed());\n                looperThread.testComplete();\n            }\n        });\n        realm.beginTransaction();\n        realm.commitTransaction();\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void returnedDynamicRealmIsNotNull() {\n        final DynamicRealm dynamicRealm = DynamicRealm.getInstance(looperThread.getConfiguration());\n        dynamicRealm.addChangeListener(new RealmChangeListener<DynamicRealm>() {\n            @Override\n            public void onChange(DynamicRealm dynRealm) {\n                assertNotNull(dynRealm);\n                assertFalse(dynRealm.isClosed());\n                dynRealm.close();\n                looperThread.testComplete();\n            }\n        });\n        dynamicRealm.beginTransaction();\n        dynamicRealm.commitTransaction();\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void returnedRealmResultsIsNotNull() {\n        Realm realm = looperThread.getRealm();\n        RealmResults<Cat> cats = realm.where(Cat.class).findAll();\n        looperThread.keepStrongReference(cats);\n        cats.addChangeListener(new RealmChangeListener<RealmResults<Cat>>() {\n            @Override\n            public void onChange(RealmResults<Cat> result) {\n                assertEquals(\"cat1\", result.first().getName());\n                looperThread.testComplete();\n            }\n        });\n        realm.beginTransaction();\n        Cat cat = realm.createObject(Cat.class);\n        cat.setName(\"cat1\");\n        realm.commitTransaction();\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void returnedRealmResultsOfModelIsNotNull() {\n        Realm realm = looperThread.getRealm();\n        RealmResults<AllTypesRealmModel> alltypes = realm.where(AllTypesRealmModel.class).findAll();\n        looperThread.keepStrongReference(alltypes);\n        alltypes.addChangeListener(new RealmChangeListener<RealmResults<AllTypesRealmModel>>() {\n            @Override\n            public void onChange(RealmResults<AllTypesRealmModel> result) {\n                assertEquals(\"data 1\", result.first().columnString);\n                looperThread.testComplete();\n            }\n        });\n\n        realm.beginTransaction();\n        AllTypesRealmModel model = realm.createObject(AllTypesRealmModel.class, 0);\n        model.columnString = \"data 1\";\n        realm.commitTransaction();\n    }\n\n\n    @Test\n    @RunTestInLooperThread\n    public void returnedRealmObjectIsNotNull() {\n        Realm realm = looperThread.getRealm();\n        realm.beginTransaction();\n        Cat cat = realm.createObject(Cat.class);\n        realm.commitTransaction();\n\n        looperThread.keepStrongReference(cat);\n        cat.addChangeListener(new RealmChangeListener<Cat>() {\n            @Override\n            public void onChange(Cat object) {\n                assertEquals(\"cat1\", object.getName());\n                looperThread.testComplete();\n            }\n        });\n\n        realm.beginTransaction();\n        cat.setName(\"cat1\");\n        realm.commitTransaction();\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void returnedRealmModelIsNotNull() {\n        Realm realm = looperThread.getRealm();\n        realm.beginTransaction();\n        AllTypesRealmModel model = realm.createObject(AllTypesRealmModel.class, 0);\n        realm.commitTransaction();\n\n        looperThread.keepStrongReference(model);\n        RealmObject.addChangeListener(model, new RealmChangeListener<AllTypesRealmModel>() {\n            @Override\n            public void onChange(AllTypesRealmModel object) {\n                assertEquals(\"model1\", object.columnString);\n                looperThread.testComplete();\n            }\n        });\n\n        realm.beginTransaction();\n        model.columnString = \"model1\";\n        realm.commitTransaction();\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void returnedDynamicRealmObjectIsNotNull() {\n        Realm realm = Realm.getInstance(looperThread.getConfiguration());\n        realm.close();\n\n        final DynamicRealm dynamicRealm = DynamicRealm.getInstance(looperThread.getConfiguration());\n        dynamicRealm.beginTransaction();\n        DynamicRealmObject allTypes = dynamicRealm.createObject(AllTypes.CLASS_NAME);\n        dynamicRealm.commitTransaction();\n\n        looperThread.keepStrongReference(allTypes);\n        allTypes.addChangeListener(new RealmChangeListener<DynamicRealmObject>() {\n            @Override\n            public void onChange(DynamicRealmObject object) {\n                assertEquals(\"test data 1\", object.getString(AllTypes.FIELD_STRING));\n                dynamicRealm.close();\n                looperThread.testComplete();\n            }\n        });\n        dynamicRealm.beginTransaction();\n        allTypes.setString(AllTypes.FIELD_STRING, \"test data 1\");\n        dynamicRealm.commitTransaction();\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void returnedDynamicRealmResultsIsNotNull() {\n        Realm realm = Realm.getInstance(looperThread.getConfiguration());\n        realm.close();\n\n        final DynamicRealm dynamicRealm = DynamicRealm.getInstance(looperThread.getConfiguration());\n        RealmResults<DynamicRealmObject> all = dynamicRealm.where(AllTypes.CLASS_NAME).findAll();\n        looperThread.keepStrongReference(all);\n        all.addChangeListener(new RealmChangeListener<RealmResults<DynamicRealmObject>>() {\n            @Override\n            public void onChange(RealmResults<DynamicRealmObject> result) {\n                assertEquals(\"test data 1\", result.first().getString(AllTypes.FIELD_STRING));\n                dynamicRealm.close();\n                looperThread.testComplete();\n            }\n        });\n\n        dynamicRealm.beginTransaction();\n        DynamicRealmObject allTypes = dynamicRealm.createObject(AllTypes.CLASS_NAME);\n        allTypes.setString(AllTypes.FIELD_STRING, \"test data 1\");\n        dynamicRealm.commitTransaction();\n    }\n\n    // 1. adding a listener on the children\n    // 2. modify parent\n    // 3. at least one child is modified\n    // 4. listener is not triggered (backlink)\n    // FIXME: will break when https://github.com/realm/realm-java/issues/4875 is solved\n    @Test\n    @RunTestInLooperThread\n    public void listenerOnChildChangeParent() {\n        final long[] nCalls = {0};\n        final Realm realm = Realm.getInstance(looperThread.getConfiguration());\n        TestHelper.populateLinkedDataSet(realm);\n\n        RealmResults<BacklinksTarget> backlinksTargets = realm.where(BacklinksTarget.class).findAll();\n        assertEquals(3, backlinksTargets.size());\n        assertTrue(backlinksTargets.last().getParents().isEmpty());\n        assertEquals(2, backlinksTargets.first().getParents().size());\n\n        looperThread.keepStrongReference(backlinksTargets);\n\n        backlinksTargets.addChangeListener(new RealmChangeListener<RealmResults<BacklinksTarget>>() {\n            @Override\n            public void onChange(RealmResults<BacklinksTarget> backlinksTargets) {\n                nCalls[0]++;\n            }\n        });\n\n        realm.beginTransaction();\n        BacklinksTarget target = backlinksTargets.last();\n        realm.where(BacklinksSource.class).findFirst().setChild(target);\n        realm.commitTransaction();\n\n        // backlinks are updated\n        assertEquals(1, backlinksTargets.last().getParents().size());\n        assertEquals(1, backlinksTargets.first().getParents().size());\n        assertEquals(0, nCalls[0]);\n        realm.close();\n        looperThread.testComplete();\n    }\n\n    // 1. adding a listener if on the parent\n    // 2. modify child\n    // 3. listener is triggered (forward link)\n    @Test\n    @RunTestInLooperThread\n    public void listenerOnParentChangeChild() {\n        final long[] nCalls = {0};\n        final Realm realm = Realm.getInstance(looperThread.getConfiguration());\n        TestHelper.populateLinkedDataSet(realm);\n\n        RealmResults<BacklinksSource> backlinksSources = realm.where(BacklinksSource.class).findAll();\n        assertEquals(4, backlinksSources.size());\n\n        looperThread.keepStrongReference(backlinksSources);\n        backlinksSources.addChangeListener(new RealmChangeListener<RealmResults<BacklinksSource>>() {\n            @Override\n            public void onChange(RealmResults<BacklinksSource> backlinksSources) {\n                nCalls[0]++;\n            }\n        });\n\n        realm.beginTransaction();\n        BacklinksTarget backlinksTarget = realm.where(BacklinksTarget.class).findFirst();\n        backlinksTarget.setId(42);\n        realm.commitTransaction();\n\n        assertEquals(42, backlinksSources.first().getChild().getId());\n        assertEquals(1, nCalls[0]);\n\n        realm.close();\n        looperThread.testComplete();\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void removeListenerOnInvalidObjectShouldWarn() {\n        realm = Realm.getInstance(realmConfig);\n        RealmChangeListener<StringOnly> listener = realmModel -> {\n        };\n        RealmChangeListener<RealmResults<StringOnly>> listenerAll = realmModel -> {\n        };\n\n        realm.beginTransaction();\n        StringOnly stringOnly = realm.createObject(StringOnly.class);\n        realm.commitTransaction();\n\n        stringOnly.addChangeListener(listener);\n\n        RealmResults<StringOnly> all = realm.where(StringOnly.class).findAll();\n        all.addChangeListener(listenerAll);\n\n        realm.close();\n\n        // add a custom logger to capture expected warning message\n        TestHelper.TestLogger testLogger = new TestHelper.TestLogger();\n        RealmLog.add(testLogger);\n\n        stringOnly.removeChangeListener(listener);\n        assertThat(testLogger.message, CoreMatchers.containsString(\n                \"Calling removeChangeListener on a closed Realm \" + realm.getPath() + \", make sure to close all listeners before closing the Realm.\"));\n\n        testLogger.message = \"\";\n        stringOnly.removeAllChangeListeners();\n        assertThat(testLogger.message, CoreMatchers.containsString(\n                \"Calling removeChangeListener on a closed Realm \" + realm.getPath() + \", make sure to close all listeners before closing the Realm.\"));\n\n\n        testLogger.message = \"\";\n        all.removeChangeListener(listenerAll);\n        assertThat(testLogger.message, CoreMatchers.containsString(\n                \"Calling removeChangeListener on a closed Realm \" + realm.getPath() + \", make sure to close all listeners before closing the Realm.\"));\n\n        testLogger.message = \"\";\n        all.removeAllChangeListeners();\n        assertThat(testLogger.message, CoreMatchers.containsString(\n                \"Calling removeChangeListener on a closed Realm \" + realm.getPath() + \", make sure to close all listeners before closing the Realm.\"));\n\n        RealmLog.remove(testLogger);\n\n        looperThread.testComplete();\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/RealmCollectionTests.java",
    "content": "/*\n * Copyright 2016 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\npackage io.realm;\n\nimport org.junit.After;\nimport org.junit.Before;\nimport org.junit.Rule;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.junit.runners.Parameterized;\n\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.Collections;\nimport java.util.Iterator;\nimport java.util.List;\n\nimport io.realm.entities.AllJavaTypes;\nimport io.realm.entities.CustomMethods;\nimport io.realm.entities.Dog;\nimport io.realm.entities.NullTypes;\n\nimport static org.junit.Assert.assertEquals;\nimport static org.junit.Assert.assertFalse;\nimport static org.junit.Assert.assertTrue;\n\n/**\n * Test class for all methods part of the the {@link RealmCollection} interface.\n * This class only tests methods that have the same behavior no matter if the collection is managed or not.\n *\n * Methods tested in this class:\n *\n * # RealmCollection\n *\n * - RealmQuery<E> where();\n * - Number min(String fieldName);\n * - Number max(String fieldName);\n * - Number sum(String fieldName);\n * - double average(String fieldName);\n * - Date maxDate(String fieldName);\n * - Date minDate(String fieldName);\n * - void deleteAllFromRealm();\n * - boolean isLoaded();\n * - boolean load();\n * - boolean isValid();\n * - BaseRealm getRealm();\n *\n * # Collection\n *\n * - public boolean add(E object);\n * - public boolean addAll(Collection<? extends E> collection);\n * - public void deleteAll();\n * + public boolean contains(Object object);\n * + public boolean containsAll(Collection<?> collection);\n * + public boolean equals(Object object);\n * + public int hashCode();\n * + public boolean isEmpty();\n * - public Iterator<E> iterator();\n * + public boolean remove(Object object);\n * + public boolean removeAll(Collection<?> collection);\n * + public boolean retainAll(Collection<?> collection);\n * + public int size();\n * + public Object[] toArray();\n * + public <T> T[] toArray(T[] array);\n **\n * @see ManagedRealmCollectionTests\n * @see UnManagedRealmCollectionTests\n */\n@RunWith(Parameterized.class)\npublic class RealmCollectionTests extends CollectionTests {\n\n    private static final int TEST_SIZE = 10;\n\n    @Rule\n    public final TestRealmConfigurationFactory configFactory = new TestRealmConfigurationFactory();\n\n    private final CollectionClass collectionClass;\n    private Realm realm;\n    private RealmCollection<AllJavaTypes> collection;\n\n    @Parameterized.Parameters(name = \"{0}\")\n    public static List<CollectionClass> data() {\n        return Arrays.asList(CollectionClass.values());\n    }\n\n    public RealmCollectionTests(CollectionClass collectionType) {\n        this.collectionClass = collectionType;\n    }\n\n    @Before\n    public void setup() {\n        realm = Realm.getInstance(configFactory.createConfiguration());\n        collection = createCollection(collectionClass);\n    }\n\n    @After\n    public void tearDown() {\n        realm.close();\n    }\n    \n    private RealmCollection<AllJavaTypes> createCollection(CollectionClass collectionClass) {\n        OrderedRealmCollection<AllJavaTypes> orderedCollection;\n        switch (collectionClass) {\n            case REALMRESULTS_SNAPSHOT_LIST_BASE:\n            case MANAGED_REALMLIST:\n                populateRealm(realm, TEST_SIZE);\n                orderedCollection = realm.where(AllJavaTypes.class)\n                        .equalTo(AllJavaTypes.FIELD_LONG, 0)\n                        .findFirst()\n                        .getFieldList();\n                break;\n\n            case UNMANAGED_REALMLIST:\n                return populateInMemoryList(TEST_SIZE);\n\n            case REALMRESULTS_SNAPSHOT_RESULTS_BASE:\n            case REALMRESULTS:\n                populateRealm(realm, TEST_SIZE);\n                orderedCollection = realm.where(AllJavaTypes.class).findAll();\n                break;\n\n            default:\n                throw new AssertionError(\"Unsupported class: \" + collectionClass);\n        }\n        if (isSnapshot(collectionClass)) {\n            orderedCollection = orderedCollection.createSnapshot();\n        }\n        return orderedCollection;\n    }\n\n    private RealmCollection<CustomMethods> createCustomMethodsCollection(Realm realm, CollectionClass collectionClass) {\n        OrderedRealmCollection<CustomMethods> orderedCollection;\n\n        switch (collectionClass) {\n            case REALMRESULTS_SNAPSHOT_LIST_BASE:\n            case MANAGED_REALMLIST:\n                realm.beginTransaction();\n                CustomMethods top = realm.createObject(CustomMethods.class);\n                top.setName(\"Top\");\n                for (int i = 0; i < TEST_SIZE; i++) {\n                    top.getMethods().add(new CustomMethods(\"Child\" + i));\n                }\n                realm.commitTransaction();\n                orderedCollection = top.getMethods();\n                break;\n\n            case UNMANAGED_REALMLIST:\n                RealmList<CustomMethods> list = new RealmList<CustomMethods>();\n                for (int i = 0; i < TEST_SIZE; i++) {\n                    list.add(new CustomMethods(\"Child\" + i));\n                }\n                return list;\n\n            case REALMRESULTS_SNAPSHOT_RESULTS_BASE:\n            case REALMRESULTS:\n                realm.beginTransaction();\n                for (int i = 0; i < TEST_SIZE; i++) {\n                    realm.copyToRealm(new CustomMethods(\"Child\" + i));\n                }\n                realm.commitTransaction();\n                orderedCollection = realm.where(CustomMethods.class).findAll();\n                break;\n\n            default:\n                throw new AssertionError(\"Unsupported class: \" + collectionClass);\n        }\n\n        if (isSnapshot(collectionClass)) {\n            orderedCollection = orderedCollection.createSnapshot();\n        }\n        return orderedCollection;\n    }\n\n    private OrderedRealmCollection<NullTypes> createEmptyCollection(Realm realm, CollectionClass collectionClass) {\n        OrderedRealmCollection<NullTypes> orderedCollection;\n        switch (collectionClass) {\n            case REALMRESULTS_SNAPSHOT_LIST_BASE:\n            case MANAGED_REALMLIST:\n                realm.beginTransaction();\n                NullTypes obj = realm.createObject(NullTypes.class, 0);\n                realm.commitTransaction();\n                orderedCollection = obj.getFieldListNull();\n                break;\n\n            case UNMANAGED_REALMLIST:\n                return new RealmList<NullTypes>();\n\n            case REALMRESULTS_SNAPSHOT_RESULTS_BASE:\n            case REALMRESULTS:\n                orderedCollection = realm.where(NullTypes.class).findAll();\n                break;\n\n            default:\n                throw new AssertionError(\"Unknown collection: \" + collectionClass);\n        }\n\n        if (isSnapshot(collectionClass)) {\n            orderedCollection = orderedCollection.createSnapshot();\n        }\n        return orderedCollection;\n    }\n\n    @Test\n    public void contains() {\n        AllJavaTypes obj = collection.iterator().next();\n        assertTrue(collection.contains(obj));\n    }\n\n    @Test\n    public void contains_realmObjectFromOtherRealm() {\n        Realm realm2 = Realm.getInstance(configFactory.createConfiguration(\"other_realm.realm\"));\n        populateRealm(realm2, TEST_SIZE);\n        AllJavaTypes otherRealmObj = realm2.where(AllJavaTypes.class).equalTo(AllJavaTypes.FIELD_LONG, 0).findFirst();\n\n        try {\n            assertFalse(collection.contains(otherRealmObj));\n        } finally {\n            realm2.close();\n        }\n    }\n\n    @Test\n    @SuppressWarnings(\"CollectionIncompatibleType\")\n    public void contains_wrongType() {\n        //noinspection SuspiciousMethodCalls\n        assertFalse(collection.contains(new Dog()));\n    }\n\n    @Test\n    public void contains_null() {\n        assertFalse(collection.contains(null));\n    }\n\n    // Test that the custom equal methods is being used when testing if an object is part of the\n    // collection\n    @Test\n    public void contains_customEqualMethod() {\n        RealmCollection<CustomMethods> collection = createCustomMethodsCollection(realm, collectionClass);\n        // This custom equals method will only consider the field `name` when comparing objects.\n        // So this unmanaged version should be equal to any object with the same value, managed\n        // or not.\n        assertTrue(collection.contains(new CustomMethods(\"Child0\")));\n        assertTrue(collection.contains(new CustomMethods(\"Child\" + (TEST_SIZE - 1))));\n        assertFalse(collection.contains(new CustomMethods(\"Child\" + TEST_SIZE)));\n    }\n\n    @Test\n    public void containsAll() {\n        Iterator<AllJavaTypes> it = collection.iterator();\n        List<AllJavaTypes> list = Arrays.asList(it.next(), it.next());\n        assertTrue(collection.containsAll(list));\n    }\n\n    @Test\n    public void containsAll_emptyInput() {\n        assertTrue(collection.containsAll(Collections.emptyList()));\n    }\n\n    @Test(expected = NullPointerException.class)\n    public void containsAll_nullInput() {\n        collection.containsAll(null);\n    }\n\n    @Test\n    public void equals() {\n        ArrayList<AllJavaTypes> newList = new ArrayList<AllJavaTypes>();\n        newList.addAll(collection);\n\n        assertTrue(collection.equals(collection));\n        assertTrue(collection.equals(newList));\n        assertFalse(collection.equals(Collections.emptyList()));\n        assertFalse(collection.equals(null));\n    }\n\n    @Test\n    public void hashCode_allObjects() {\n        ArrayList<AllJavaTypes> newList = new ArrayList<AllJavaTypes>();\n        newList.addAll(collection);\n\n        assertTrue(collection.hashCode() == newList.hashCode());\n        assertFalse(collection.hashCode() == Collections.emptyList().hashCode());\n    }\n\n    @Test\n    public void isEmpty() {\n        assertFalse(collection.isEmpty());\n        RealmCollection<NullTypes> collection = createEmptyCollection(realm, collectionClass);\n        assertTrue(collection.isEmpty());\n    }\n\n    @Test\n    public void size() {\n        assertEquals(TEST_SIZE, collection.size());\n    }\n\n    @Test\n    public void toArray() {\n        Object[] array = collection.toArray();\n        assertEquals(TEST_SIZE, array.length);\n        assertEquals(collection.iterator().next(), array[0]);\n    }\n\n    @Test\n    public void toArray_inputArray() {\n        AllJavaTypes[] array = new AllJavaTypes[collection.size()];\n        collection.toArray(array);\n        assertEquals(TEST_SIZE, array.length);\n        assertEquals(collection.iterator().next(), array[0]);\n    }\n\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/RealmConfigurationTests.java",
    "content": "/*\n * Copyright 2015 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\npackage io.realm;\n\nimport android.content.Context;\n\nimport androidx.test.ext.junit.runners.AndroidJUnit4;\nimport androidx.test.platform.app.InstrumentationRegistry;\n\nimport org.junit.After;\nimport org.junit.Before;\nimport org.junit.Rule;\nimport org.junit.Test;\nimport org.junit.rules.ExpectedException;\nimport org.junit.runner.RunWith;\nimport org.mockito.Mockito;\n\nimport java.io.File;\nimport java.io.IOException;\nimport java.util.Arrays;\nimport java.util.Set;\n\nimport javax.annotation.Nonnull;\n\nimport io.reactivex.Flowable;\nimport io.reactivex.Observable;\nimport io.reactivex.Single;\nimport io.realm.coroutines.FlowFactory;\nimport io.realm.entities.AllTypes;\nimport io.realm.entities.AllTypesModelModule;\nimport io.realm.entities.AnimalModule;\nimport io.realm.entities.AssetFileModule;\nimport io.realm.entities.Cat;\nimport io.realm.entities.CatOwner;\nimport io.realm.entities.Dog;\nimport io.realm.entities.HumanModule;\nimport io.realm.entities.Owner;\nimport io.realm.entities.StringAndInt;\nimport io.realm.entities.StringOnly;\nimport io.realm.exceptions.RealmException;\nimport io.realm.exceptions.RealmFileException;\nimport io.realm.exceptions.RealmMigrationNeededException;\nimport io.realm.internal.modules.CompositeMediator;\nimport io.realm.internal.modules.FilterableMediator;\nimport io.realm.rx.CollectionChange;\nimport io.realm.rx.ObjectChange;\nimport io.realm.rx.RealmObservableFactory;\nimport io.realm.rx.RxObservableFactory;\nimport kotlinx.coroutines.flow.Flow;\n\nimport static org.junit.Assert.assertArrayEquals;\nimport static org.junit.Assert.assertEquals;\nimport static org.junit.Assert.assertFalse;\nimport static org.junit.Assert.assertNotEquals;\nimport static org.junit.Assert.assertNotNull;\nimport static org.junit.Assert.assertNotSame;\nimport static org.junit.Assert.assertNull;\nimport static org.junit.Assert.assertSame;\nimport static org.junit.Assert.assertTrue;\nimport static org.junit.Assert.fail;\nimport static org.mockito.Mockito.mock;\nimport static org.mockito.Mockito.never;\nimport static org.mockito.Mockito.times;\nimport static org.mockito.Mockito.verify;\n\n@RunWith(AndroidJUnit4.class)\npublic class RealmConfigurationTests {\n    @Rule\n    public final TestRealmConfigurationFactory configFactory = new TestRealmConfigurationFactory();\n\n    @Rule\n    public final ExpectedException thrown = ExpectedException.none();\n\n    private Context context;\n    private RealmConfiguration defaultConfig;\n    private Realm realm;\n\n    @Before\n    public void setUp() {\n        context = InstrumentationRegistry.getInstrumentation().getTargetContext();\n        defaultConfig = configFactory.createConfiguration();\n    }\n\n    @After\n    public void tearDown() throws Exception {\n        if (realm != null) {\n            realm.close();\n        }\n    }\n\n    @Test\n    public void setDefaultConfiguration_nullThrows() {\n        try {\n            Realm.setDefaultConfiguration(null);\n            fail();\n        } catch (IllegalArgumentException ignored) {\n        }\n    }\n\n    @Test\n    public void getDefaultConfiguration_returnsTheSameObjectThatSetDefaultConfigurationSet() {\n        final RealmConfiguration config = new RealmConfiguration.Builder().build();\n        Realm.setDefaultConfiguration(config);\n\n        assertSame(config, Realm.getDefaultConfiguration());\n    }\n\n    @Test\n    public void getDefaultConfiguration_returnsNullAfterRemoveDefaultConfiguration() {\n        final RealmConfiguration defaultConfiguration = Realm.getDefaultConfiguration();\n        try {\n            Realm.removeDefaultConfiguration();\n\n            assertNull(Realm.getDefaultConfiguration());\n        } finally {\n            Realm.setDefaultConfiguration(defaultConfiguration);\n        }\n    }\n\n    @Test\n    public void getInstance_nullConfigThrows() {\n        try {\n            Realm.getInstance((RealmConfiguration) null);\n            fail();\n        } catch (IllegalArgumentException ignored) {\n        }\n    }\n\n    @Test\n    public void constructBuilder_nullNameThrows() {\n        try {\n            configFactory.createConfigurationBuilder().name(null);\n            fail();\n        } catch (IllegalArgumentException ignored) {\n        }\n    }\n\n    @Test\n    public void constructBuilder_emptyNameThrows() {\n        try {\n            configFactory.createConfigurationBuilder().name(\"\");\n            fail();\n        } catch (IllegalArgumentException ignored) {\n        }\n    }\n\n    @Test(expected = IllegalArgumentException.class)\n    public void directory_null() {\n        configFactory.createConfigurationBuilder().directory(null);\n    }\n\n    @Test\n    public void directory_writeProtectedDir() {\n        File dir = new File(\"/\");\n        thrown.expect(IllegalArgumentException.class);\n        configFactory.createConfigurationBuilder().directory(dir);\n    }\n\n    @Test\n    public void directory_dirIsAFile() throws IOException {\n        File dir = configFactory.getRoot();\n        File file = new File(dir, \"dummyfile\");\n        assertTrue(file.createNewFile());\n        thrown.expect(IllegalArgumentException.class);\n        configFactory.createConfigurationBuilder().directory(file);\n    }\n\n    @Test\n    public void getInstance_idForHashCollision() {\n        // Ea.hashCode() == FB.hashCode()\n        RealmConfiguration configA = configFactory.createConfiguration(\"Ea\");\n        RealmConfiguration configB = configFactory.createConfiguration(\"FB\");\n\n        Realm r1 = Realm.getInstance(configA);\n        Realm r2 = Realm.getInstance(configB);\n        assertNotSame(r1, r2);\n        r1.close();\n        r2.close();\n    }\n\n    @Test\n    public void constructBuilder_nullKeyThrows() {\n        try {\n            configFactory.createConfigurationBuilder().encryptionKey(null);\n            fail();\n        } catch (IllegalArgumentException ignored) {\n        }\n    }\n\n    @Test\n    public void constructBuilder_wrongKeyLengthThrows() {\n        byte[][] wrongKeys = new byte[][] {\n                new byte[0],\n                new byte[Realm.ENCRYPTION_KEY_LENGTH - 1],\n                new byte[Realm.ENCRYPTION_KEY_LENGTH + 1]\n        };\n        for (byte[] key : wrongKeys) {\n            try {\n                configFactory.createConfigurationBuilder().encryptionKey(key);\n                fail(\"Key with length \" + key.length + \" should throw an exception\");\n            } catch (IllegalArgumentException ignored) {\n            }\n        }\n    }\n\n    @Test\n    public void constructBuilder_negativeVersionThrows() {\n        try {\n            configFactory.createConfigurationBuilder().schemaVersion(-1);\n            fail();\n        } catch (IllegalArgumentException ignored) {\n        }\n    }\n\n    @Test\n    public void constructBuilder_versionLessThanDiscVersionThrows() {\n        realm = Realm.getInstance(configFactory.createConfigurationBuilder()\n                .directory(configFactory.getRoot())\n                .schemaVersion(42)\n                .build());\n        realm.close();\n\n        int[] wrongVersions = new int[] { 0, 1, 41 };\n        for (int version : wrongVersions) {\n            try {\n                realm = Realm.getInstance(configFactory.createConfigurationBuilder()\n                        .directory(configFactory.getRoot())\n                        .schemaVersion(version)\n                        .build());\n                fail(\"Version \" + version + \" should throw an exception\");\n            } catch (IllegalArgumentException ignored) {\n            }\n        }\n    }\n\n    @Test\n    public void constructBuilder_versionEqualWhenSchemaChangesThrows() {\n        // Creates initial Realm.\n        RealmConfiguration config = configFactory.createConfigurationBuilder()\n                .directory(configFactory.getRoot())\n                .schemaVersion(42)\n                .schema(StringOnly.class)\n                .build();\n        Realm.getInstance(config).close();\n\n        // Creates new instance with a configuration containing another schema.\n        try {\n            config = configFactory.createConfigurationBuilder()\n                    .directory(configFactory.getRoot())\n                    .schemaVersion(42)\n                    .schema(StringAndInt.class)\n                    .build();\n            realm = Realm.getInstance(config);\n            fail(\"A migration should be required\");\n        } catch (RealmMigrationNeededException ignored) {\n        }\n    }\n\n    // Only Dog is included in the schema definition, but in order to create Dog, the Owner has to be defined as well.\n    @Test\n    public void schemaDoesNotContainAllDefinedObjectShouldThrow() {\n        RealmConfiguration config = configFactory.createConfigurationBuilder()\n                .directory(configFactory.getRoot())\n                .schema(Dog.class)\n                .build();\n        thrown.expect(IllegalStateException.class);\n        realm = Realm.getInstance(config);\n    }\n\n    @Test\n    public void migration_nullThrows() {\n        try {\n            configFactory.createConfigurationBuilder().migration(null).build();\n            fail();\n        } catch (IllegalArgumentException ignored) {\n        }\n    }\n\n    @Test\n    public void modules_nonRealmModulesThrows() {\n        // Tests first argument.\n        try {\n            configFactory.createConfigurationBuilder().modules(new Object());\n            fail();\n        } catch (IllegalArgumentException ignored) {\n        }\n\n        // Tests second argument.\n        try {\n            configFactory.createConfigurationBuilder().modules(Realm.getDefaultModule(), new Object());\n            fail();\n        } catch (IllegalArgumentException ignored) {\n        }\n    }\n\n    @Test\n    public void modules() {\n        RealmConfiguration realmConfig = configFactory.createConfigurationBuilder()\n                .directory(configFactory.getRoot())\n                .modules(new AllTypesModelModule(), (Object) null)\n                .build();\n        realm = Realm.getInstance(realmConfig);\n        assertNotNull(realm.getTable(AllTypes.class));\n    }\n\n    @Test\n    public void setDefaultConfiguration() {\n        Realm.setDefaultConfiguration(defaultConfig);\n        realm = Realm.getDefaultInstance();\n        assertEquals(defaultConfig, realm.getConfiguration());\n    }\n\n    @Test\n    public void getInstance() {\n        realm = Realm.getInstance(defaultConfig);\n        assertEquals(defaultConfig, realm.getConfiguration());\n    }\n\n    @Test\n    public void standardSetup() {\n        RealmConfiguration config = configFactory.createConfigurationBuilder()\n                .directory(configFactory.getRoot())\n                .name(\"foo.realm\")\n                .encryptionKey(TestHelper.getRandomKey())\n                .schemaVersion(42)\n                .migration(new RealmMigration() {\n                    @Override\n                    public void migrate(DynamicRealm realm, long oldVersion, long newVersion) {\n                        // no-op\n                    }\n                })\n                .deleteRealmIfMigrationNeeded()\n                .build();\n\n        Realm.deleteRealm(config);\n        realm = Realm.getInstance(config);\n        assertTrue(realm.getPath().endsWith(\"foo.realm\"));\n        assertEquals(42, realm.getVersion());\n    }\n\n    @Test\n    public void deleteRealmIfMigrationNeeded() {\n        // Populates v0 of a Realm with an object.\n        RealmConfiguration config = configFactory.createConfigurationBuilder()\n                .directory(configFactory.getRoot())\n                .schema(StringOnly.class)\n                .schemaVersion(0)\n                .build();\n        Realm.deleteRealm(config);\n        realm = Realm.getInstance(config);\n        realm.beginTransaction();\n        realm.copyToRealm(new StringOnly());\n        realm.commitTransaction();\n        assertEquals(1, realm.where(StringOnly.class).count());\n        realm.close();\n\n        // Changes schema and verifies that Realm has been cleared.\n        config = configFactory.createConfigurationBuilder()\n                .directory(configFactory.getRoot())\n                .schema(StringOnly.class, StringAndInt.class)\n                .schemaVersion(1)\n                .deleteRealmIfMigrationNeeded()\n                .build();\n        realm = Realm.getInstance(config);\n        assertEquals(0, realm.where(StringOnly.class).count());\n    }\n\n    @Test\n    public void deleteRealmIfMigrationNeeded_failsWhenAssetFileProvided() {\n        Context context = InstrumentationRegistry.getInstrumentation().getContext();\n\n        // Has a builder instance to isolate codepath.\n        RealmConfiguration.Builder builder = configFactory.createConfigurationBuilder();\n        try {\n            builder\n                    .assetFile(\"asset_file.realm\")\n                    .deleteRealmIfMigrationNeeded();\n            fail();\n        } catch (IllegalStateException expected) {\n            assertEquals(\"Realm cannot clear its schema when previously configured to use an asset file by calling assetFile().\",\n                    expected.getMessage());\n        }\n    }\n\n    @Test\n    public void upgradeVersionWithNoMigration() {\n        realm = Realm.getInstance(defaultConfig);\n        assertEquals(0, realm.getVersion());\n        realm.close();\n\n        // Version upgrades only without any actual schema changes will just succeed, and the schema version will be\n        // set to the new one.\n        realm = Realm.getInstance(configFactory.createConfigurationBuilder()\n                .directory(configFactory.getRoot())\n                .schemaVersion(42)\n                .build());\n        assertEquals(42, realm.getVersion());\n    }\n\n    @Test\n    public void equals() {\n        RealmConfiguration config1 = configFactory.createConfiguration();\n        RealmConfiguration config2 = configFactory.createConfiguration();\n        assertTrue(config1.equals(config2));\n    }\n\n    @Test\n    public void equals_respectReadOnly() {\n        RealmConfiguration config1 = configFactory.createConfigurationBuilder().assetFile(\"foo\").build();\n        RealmConfiguration config2 = configFactory.createConfigurationBuilder().assetFile(\"foo\").readOnly().build();\n        assertFalse(config1.equals(config2));\n    }\n\n    @Test\n    public void equalsWhenRxJavaUnavailable() {\n        // Test for https://github.com/realm/realm-java/issues/2416\n        RealmConfiguration config1 = configFactory.createConfigurationBuilder().directory(configFactory.getRoot()).build();\n        TestHelper.emulateRxJavaUnavailable(config1);\n        RealmConfiguration config2 = configFactory.createConfigurationBuilder().directory(configFactory.getRoot()).build();\n        TestHelper.emulateRxJavaUnavailable(config2);\n        assertTrue(config1.equals(config2));\n    }\n\n    @Test\n    public void hashCode_Test() {\n        RealmConfiguration config1 = configFactory.createConfigurationBuilder().directory(configFactory.getRoot()).build();\n        RealmConfiguration config2 = configFactory.createConfigurationBuilder().directory(configFactory.getRoot()).build();\n        assertEquals(config1.hashCode(), config2.hashCode());\n    }\n\n    @Test\n    public void equals_withCustomModules() {\n        RealmConfiguration config1 = configFactory.createConfigurationBuilder()\n                .directory(configFactory.getRoot())\n                .modules(new HumanModule(), new AnimalModule())\n                .build();\n\n        RealmConfiguration config2 = configFactory.createConfigurationBuilder()\n                .directory(configFactory.getRoot())\n                .modules(new AnimalModule(), new HumanModule())\n                .build();\n\n        assertTrue(config1.equals(config2));\n    }\n\n    @Test\n    public void hashCode_withCustomModules() {\n        RealmConfiguration config1 = configFactory.createConfigurationBuilder()\n                .directory(configFactory.getRoot())\n                .modules(new HumanModule(), new AnimalModule())\n                .build();\n        RealmConfiguration config2 = configFactory.createConfigurationBuilder()\n                .directory(configFactory.getRoot())\n                .modules(new AnimalModule(), new HumanModule())\n                .build();\n\n        assertEquals(config1.hashCode(), config2.hashCode());\n    }\n\n    @Test\n    public void hashCode_withDifferentRxObservableFactory() {\n        RealmConfiguration config1 = configFactory.createConfigurationBuilder()\n                .directory(configFactory.getRoot())\n                .rxFactory(new RealmObservableFactory(false))\n                .build();\n        RealmConfiguration config2 = configFactory.createConfigurationBuilder()\n                .directory(configFactory.getRoot())\n                .rxFactory(new RealmObservableFactory(false) {\n                    @Override\n                    public int hashCode() {\n                        return super.hashCode() + 1;\n                    }\n                })\n                .build();\n\n        assertNotEquals(config1.hashCode(), config2.hashCode());\n    }\n\n    @Test\n    public void equals_configurationsReturnCachedRealm() {\n        Realm realm1 = Realm.getInstance(configFactory.createConfigurationBuilder().directory(configFactory.getRoot()).build());\n        Realm realm2 = Realm.getInstance(configFactory.createConfigurationBuilder().directory(configFactory.getRoot()).build());\n        try {\n            assertEquals(realm1, realm2);\n        } finally {\n            realm1.close();\n            realm2.close();\n        }\n    }\n\n    @Test\n    public void schemaVersion_differentVersionsThrows() {\n        RealmConfiguration config1 = configFactory.createConfigurationBuilder().directory(configFactory.getRoot()).schemaVersion(1).build();\n        RealmConfiguration config2 = configFactory.createConfigurationBuilder().directory(configFactory.getRoot()).schemaVersion(2).build();\n\n        Realm realm1 = Realm.getInstance(config1);\n        try {\n            Realm.getInstance(config2);\n            fail();\n        } catch (IllegalArgumentException ignored) {\n        } finally {\n            realm1.close();\n        }\n    }\n\n    @Test\n    public void encryptionKey_differentEncryptionKeysThrows() {\n        RealmConfiguration config1 = configFactory.createConfigurationBuilder()\n                .directory(configFactory.getRoot())\n                .encryptionKey(TestHelper.getRandomKey())\n                .build();\n        RealmConfiguration config2 = configFactory.createConfigurationBuilder()\n                .directory(configFactory.getRoot())\n                .encryptionKey(TestHelper.getRandomKey())\n                .build();\n\n        Realm realm1 = Realm.getInstance(config1);\n        try {\n            realm = Realm.getInstance(config2);\n            fail();\n        } catch (IllegalArgumentException ignored) {\n        } finally {\n            realm1.close();\n        }\n    }\n\n    @Test\n    public void schema_differentSchemasThrows() {\n        RealmConfiguration config1 = configFactory.createConfigurationBuilder()\n                .directory(configFactory.getRoot())\n                .schema(StringOnly.class)\n                .build();\n        RealmConfiguration config2 = configFactory.createConfigurationBuilder()\n                .directory(configFactory.getRoot())\n                .schema(StringAndInt.class).build();\n\n        Realm realm1 = Realm.getInstance(config1);\n        try {\n            Realm.getInstance(config2);\n            fail();\n        } catch (IllegalArgumentException ignored) {\n        } finally {\n            realm1.close();\n        }\n    }\n\n    // Creates Realm instances with same name but different durabilities is not allowed.\n    @Test\n    public void inMemory_differentDurabilityThrows() {\n        RealmConfiguration config1 = configFactory.createConfigurationBuilder()\n                .directory(configFactory.getRoot())\n                .inMemory()\n                .build();\n        RealmConfiguration config2 = configFactory.createConfigurationBuilder()\n                .directory(configFactory.getRoot())\n                .build();\n\n        // Creates In-memory Realm first.\n        Realm realm1 = Realm.getInstance(config1);\n        try {\n            // On-disk Realm then. Not allowed!\n            Realm.getInstance(config2);\n            fail();\n        } catch (IllegalArgumentException ignored) {\n        } finally {\n            realm1.close();\n        }\n\n        // Creates on-disk Realm first.\n        realm1 = Realm.getInstance(config2);\n        try {\n            // In-memory Realm then. Not allowed!\n            Realm.getInstance(config1);\n            fail();\n        } catch (IllegalArgumentException ignored) {\n        } finally {\n            realm1.close();\n        }\n    }\n\n    // It is allowed to create multiple Realm with same name but in different directory.\n    @Test\n    public void constructBuilder_differentDirSameName() throws IOException {\n        RealmConfiguration config1 = configFactory.createConfigurationBuilder().directory(configFactory.getRoot()).build();\n        RealmConfiguration config2 = configFactory.createConfigurationBuilder().directory(configFactory.newFolder()).build();\n\n        Realm realm1 = Realm.getInstance(config1);\n        Realm realm2 = Realm.getInstance(config2);\n        realm1.close();\n        realm2.close();\n    }\n\n    @Test\n    public void encryptionKey_keyStorage() throws Exception {\n        // Generates a key and uses it in a RealmConfiguration.\n        byte[] oldKey = TestHelper.getRandomKey(12345);\n        byte[] key = oldKey;\n        RealmConfiguration config = configFactory.createConfigurationBuilder()\n                .directory(configFactory.getRoot())\n                .encryptionKey(key)\n                .build();\n\n        // Generates a different key and assigns it to the same variable.\n        byte[] newKey = TestHelper.getRandomKey(67890);\n        assertFalse(Arrays.equals(key, newKey));\n        key = newKey;\n        assertArrayEquals(key, newKey);\n\n        // Ensures that the stored key did not change.\n        assertArrayEquals(oldKey, config.getEncryptionKey());\n    }\n\n    @Test\n    public void modelClassesForDefaultMediator() throws Exception {\n        final Set<Class<? extends RealmModel>> realmClasses = defaultConfig.getRealmObjectClasses();\n\n        assertTrue(realmClasses.contains(AllTypes.class));\n\n        // Tests returned Set is unmodifiable.\n        try {\n            realmClasses.add(AllTypes.class);\n            fail();\n        } catch (UnsupportedOperationException ignored) {\n        }\n    }\n\n    @Test\n    public void modelClasses_forGeneratedMediator() throws Exception {\n        final RealmConfiguration config = configFactory.createConfigurationBuilder()\n                .directory(configFactory.getRoot())\n                .modules(new HumanModule())\n                .build();\n        assertTrue(config.getSchemaMediator() instanceof HumanModuleMediator);\n\n        final Set<Class<? extends RealmModel>> realmClasses = config.getRealmObjectClasses();\n\n        assertFalse(realmClasses.contains(AllTypes.class));\n        assertTrue(realmClasses.contains(CatOwner.class));\n        assertFalse(realmClasses.contains(Cat.class));\n\n        // Tests returned Set is unmodifiable.\n        try {\n            realmClasses.add(AllTypes.class);\n            fail();\n        } catch (UnsupportedOperationException ignored) {\n        }\n    }\n\n    @Test\n    public void modelClasses_forCompositeMediator() throws Exception {\n        final RealmConfiguration config = configFactory.createConfigurationBuilder()\n                .directory(configFactory.getRoot())\n                .modules(new HumanModule(), new AnimalModule())\n                .build();\n        assertTrue(config.getSchemaMediator() instanceof CompositeMediator);\n\n        final Set<Class<? extends RealmModel>> realmClasses = config.getRealmObjectClasses();\n\n        assertFalse(realmClasses.contains(AllTypes.class));\n        assertTrue(realmClasses.contains(CatOwner.class));\n        assertTrue(realmClasses.contains(Cat.class));\n\n        // Tests returned Set is unmodifiable.\n        try {\n            realmClasses.add(AllTypes.class);\n            fail();\n        } catch (UnsupportedOperationException ignored) {\n        }\n    }\n\n    @Test\n    public void modelClasses_forFilterableMediator() throws Exception {\n        //noinspection unchecked\n        final RealmConfiguration config = configFactory.createConfigurationBuilder()\n                .directory(configFactory.getRoot())\n                .schema(AllTypes.class, CatOwner.class)\n                .build();\n        assertTrue(config.getSchemaMediator() instanceof FilterableMediator);\n\n        final Set<Class<? extends RealmModel>> realmClasses = config.getRealmObjectClasses();\n\n        assertTrue(realmClasses.contains(AllTypes.class));\n        assertTrue(realmClasses.contains(CatOwner.class));\n        assertFalse(realmClasses.contains(Cat.class));\n\n        // Tests returned Set is unmodifiable.\n        try {\n            realmClasses.add(AllTypes.class);\n            fail();\n        } catch (UnsupportedOperationException ignored) {\n        }\n    }\n\n    @Test\n    public void rxFactory() {\n        final RxObservableFactory dummyFactory = new RxObservableFactory() {\n            @Override\n            public Flowable<Realm> from(Realm realm) {\n                return null;\n            }\n\n            @Override\n            public Flowable<DynamicRealm> from(DynamicRealm realm) {\n                return null;\n            }\n\n            @Override\n            public <E> Flowable<RealmResults<E>> from(Realm realm, RealmResults<E> results) {\n                return null;\n            }\n\n            @Override\n            public <E> Observable<CollectionChange<RealmResults<E>>> changesetsFrom(Realm realm, RealmResults<E> results) {\n                return null;\n            }\n\n            @Override\n            public <E> Flowable<RealmResults<E>> from(DynamicRealm realm, RealmResults<E> results) {\n                return null;\n            }\n\n            @Override\n            public <E> Observable<CollectionChange<RealmResults<E>>> changesetsFrom(DynamicRealm realm, RealmResults<E> results) {\n                return null;\n            }\n\n            @Override\n            public <E> Flowable<RealmList<E>> from(Realm realm, RealmList<E> list) {\n                return null;\n            }\n\n            @Override\n            public <E> Observable<CollectionChange<RealmList<E>>> changesetsFrom(Realm realm, RealmList<E> list) {\n                return null;\n            }\n\n            @Override\n            public <E> Flowable<RealmList<E>> from(DynamicRealm realm, RealmList<E> list) {\n                return null;\n            }\n\n            @Override\n            public <E> Observable<CollectionChange<RealmList<E>>> changesetsFrom(DynamicRealm realm, RealmList<E> list) {\n                return null;\n            }\n\n            @Override\n            public <E extends RealmModel> Flowable<E> from(Realm realm, E object) {\n                return null;\n            }\n\n            @Override\n            public <E extends RealmModel> Observable<ObjectChange<E>> changesetsFrom(Realm realm, E object) {\n                return null;\n            }\n\n            @Override\n            public Flowable<DynamicRealmObject> from(DynamicRealm realm, DynamicRealmObject object) {\n                return null;\n            }\n\n            @Override\n            public Observable<ObjectChange<DynamicRealmObject>> changesetsFrom(DynamicRealm realm, DynamicRealmObject object) {\n                return null;\n            }\n\n            @Override\n            public <E> Single<RealmQuery<E>> from(Realm realm, RealmQuery<E> query) {\n                return null;\n            }\n\n            @Override\n            public <E> Single<RealmQuery<E>> from(DynamicRealm realm, RealmQuery<E> query) {\n                return null;\n            }\n        };\n\n        RealmConfiguration configuration1 = configFactory.createConfigurationBuilder()\n                .rxFactory(dummyFactory)\n                .build();\n        assertTrue(configuration1.getRxFactory() == dummyFactory);\n\n        RealmConfiguration configuration2 = configFactory.createConfigurationBuilder()\n                .build();\n        assertNotNull(configuration2.getRxFactory());\n        assertFalse(configuration2.getRxFactory() == dummyFactory);\n    }\n\n    @Test\n    public void rxFactory_nullThrows() {\n        RealmConfiguration.Builder builder = configFactory.createConfigurationBuilder();\n        try {\n            builder.rxFactory(null);\n            fail(\"Setting a null factory from Java should fail.\");\n        } catch (IllegalArgumentException e) {\n            assertTrue(e.getMessage().contains(\"null\"));\n        }\n    }\n\n    @Test\n    public void flowFactory_defaultNotNull() {\n        RealmConfiguration configuration = configFactory.createConfigurationBuilder()\n                .build();\n        assertNotNull(configuration.getFlowFactory());\n    }\n\n    @Test\n    public void flowFactory() {\n        final FlowFactory dummyFactory = new FlowFactory() {\n            @Override\n            public Flow<Realm> from(@Nonnull Realm realm) {\n                return null;\n            }\n\n            @Override\n            public Flow<DynamicRealm> from(@Nonnull DynamicRealm dynamicRealm) {\n                return null;\n            }\n\n            @Override\n            public <T> Flow<RealmResults<T>> from(@Nonnull Realm realm, @Nonnull RealmResults<T> results) {\n                return null;\n            }\n\n            @Override\n            public <T> Flow<CollectionChange<RealmResults<T>>> changesetFrom(@Nonnull Realm realm, @Nonnull RealmResults<T> results) {\n                return null;\n            }\n\n            @Override\n            public <T> Flow<RealmResults<T>> from(@Nonnull DynamicRealm dynamicRealm, @Nonnull RealmResults<T> results) {\n                return null;\n            }\n\n            @Override\n            public <T> Flow<CollectionChange<RealmResults<T>>> changesetFrom(@Nonnull DynamicRealm dynamicRealm, @Nonnull RealmResults<T> results) {\n                return null;\n            }\n\n            @Override\n            public <T> Flow<RealmList<T>> from(@Nonnull Realm realm, @Nonnull RealmList<T> realmList) {\n                return null;\n            }\n\n            @Override\n            public <T> Flow<CollectionChange<RealmList<T>>> changesetFrom(@Nonnull Realm realm, @Nonnull RealmList<T> list) {\n                return null;\n            }\n\n            @Override\n            public <T> Flow<RealmList<T>> from(@Nonnull DynamicRealm dynamicRealm, @Nonnull RealmList<T> realmList) {\n                return null;\n            }\n\n            @Override\n            public <T> Flow<CollectionChange<RealmList<T>>> changesetFrom(@Nonnull DynamicRealm dynamicRealm, @Nonnull RealmList<T> list) {\n                return null;\n            }\n\n            @Override\n            public <T extends RealmModel> Flow<T> from(@Nonnull Realm realm, @Nonnull T realmObject) {\n                return null;\n            }\n\n            @Override\n            public <T extends RealmModel> Flow<ObjectChange<T>> changesetFrom(@Nonnull Realm realm, @Nonnull T realmObject) {\n                return null;\n            }\n\n            @Override\n            public Flow<DynamicRealmObject> from(@Nonnull DynamicRealm dynamicRealm, @Nonnull DynamicRealmObject dynamicRealmObject) {\n                return null;\n            }\n\n            @Override\n            public Flow<ObjectChange<DynamicRealmObject>> changesetFrom(@Nonnull DynamicRealm dynamicRealm, @Nonnull DynamicRealmObject dynamicRealmObject) {\n                return null;\n            }\n        };\n\n        RealmConfiguration configuration1 = configFactory.createConfigurationBuilder()\n                .flowFactory(dummyFactory)\n                .build();\n        assertTrue(configuration1.getFlowFactory() == dummyFactory);\n\n        RealmConfiguration configuration2 = configFactory.createConfigurationBuilder()\n                .build();\n        assertNotNull(configuration2.getFlowFactory());\n        assertFalse(configuration2.getFlowFactory() == dummyFactory);\n    }\n\n    @Test\n    public void flowFactory_nullThrows() {\n        try {\n            configFactory.createConfigurationBuilder()\n                    .flowFactory(null);\n            fail(\"Setting a null factory from Java should fail.\");\n        } catch (IllegalArgumentException e) {\n            assertTrue(e.getMessage().contains(\"null\"));\n        }\n    }\n\n    @Test\n    public void initialDataTransactionEqual() {\n        final Realm.Transaction transaction = new Realm.Transaction() {\n            @Override\n            public void execute(final Realm realm) {\n            }\n        };\n\n        RealmConfiguration configuration = configFactory.createConfigurationBuilder()\n                .initialData(transaction)\n                .build();\n\n        assertEquals(transaction, configuration.getInitialDataTransaction());\n    }\n\n    @Test\n    public void initialDataTransactionNull() {\n        assertNull(defaultConfig.getInitialDataTransaction());\n\n        realm = Realm.getInstance(defaultConfig);\n        assertTrue(realm.isEmpty());\n    }\n\n    @Test\n    public void initialDataTransactionNotNull() {\n        // Removes default instance.\n        Realm.deleteRealm(defaultConfig);\n\n        RealmConfiguration configuration = configFactory.createConfigurationBuilder()\n                .initialData(new Realm.Transaction() {\n                    @Override\n                    public void execute(final Realm realm) {\n                        realm.createObject(AllTypes.class);\n                        realm.createObject(Owner.class).setCat(realm.createObject(Cat.class));\n                    }\n                }).build();\n\n        realm = Realm.getInstance(configuration);\n\n        // First time check for initial data.\n        assertEquals(1, realm.where(AllTypes.class).count());\n        assertEquals(1, realm.where(Owner.class).count());\n        assertEquals(1, realm.where(Cat.class).count());\n\n        realm.beginTransaction();\n        realm.delete(AllTypes.class);\n        realm.commitTransaction();\n\n        assertEquals(0, realm.where(AllTypes.class).count());\n\n        realm.close();\n        realm = Realm.getInstance(configuration);\n        // Checks if there is still the same data.\n        assertEquals(0, realm.where(AllTypes.class).count());\n        assertEquals(1, realm.where(Owner.class).count());\n        assertEquals(1, realm.where(Cat.class).count());\n    }\n\n    @Test\n    public void initialDataTransactionExecutionCount() {\n        // Removes default instance.\n        Realm.deleteRealm(defaultConfig);\n\n        Realm.Transaction transaction = mock(Realm.Transaction.class);\n        RealmConfiguration configuration = configFactory.createConfigurationBuilder()\n                .initialData(transaction)\n                .build();\n\n        realm = Realm.getInstance(configuration);\n        realm.close();\n        verify(transaction, times(1)).execute(Mockito.any(Realm.class));\n\n        realm = Realm.getInstance(configuration);\n        realm.close();\n        verify(transaction, never()).execute(realm);\n    }\n\n    @Test\n    public void initialDataTransactionAssetFile() throws IOException {\n        // Removes default instance.\n        Realm.deleteRealm(defaultConfig);\n\n        Context context = InstrumentationRegistry.getInstrumentation().getContext();\n        configFactory.copyRealmFromAssets(context, \"asset_file.realm\", Realm.DEFAULT_REALM_NAME);\n        assertTrue(new File(configFactory.getRoot(), Realm.DEFAULT_REALM_NAME).exists());\n\n        Realm.Transaction transaction = mock(Realm.Transaction.class);\n        RealmConfiguration configuration = configFactory.createConfigurationBuilder()\n                .modules(new AssetFileModule())\n                .initialData(transaction)\n                .build();\n\n        realm = Realm.getInstance(configuration);\n        realm.close();\n        verify(transaction, never()).execute(realm);\n    }\n\n    @Test\n    public void initialDataTransactionThrows() {\n        final RuntimeException exception = new RuntimeException();\n\n        RealmConfiguration configuration = configFactory.createConfigurationBuilder()\n                .initialData(new Realm.Transaction() {\n                    @Override\n                    public void execute(final Realm realm) {\n                        throw exception;\n                    }\n                }).build();\n\n        assertFalse(new File(configuration.getPath()).exists());\n\n        Realm realm = null;\n        try {\n            realm = Realm.getInstance(configuration);\n            fail();\n        } catch (RuntimeException expected) {\n            assertSame(exception, expected);\n        } finally {\n            if (realm != null) {\n                realm.close();\n            }\n        }\n\n        DynamicRealm dynamicRealm = DynamicRealm.getInstance(configuration);\n        try {\n            // The schema should not be initialized.\n            assertNull(dynamicRealm.getSchema().get(StringOnly.CLASS_NAME));\n        } finally {\n            dynamicRealm.close();\n        }\n    }\n\n    @Test\n    public void assetFileNullAndEmptyFileName() {\n        try {\n            configFactory.createConfigurationBuilder().assetFile(null).build();\n            fail();\n        } catch (IllegalArgumentException ignored) {\n        }\n\n        try {\n            configFactory.createConfigurationBuilder().assetFile(\"\").build();\n            fail();\n        } catch (IllegalArgumentException ignored) {\n        }\n    }\n\n    @Test\n    public void assetFileWithInMemoryConfig() {\n        // Ensures that there is no data.\n        Realm.deleteRealm(configFactory.createConfigurationBuilder().build());\n\n        try {\n            configFactory.createConfigurationBuilder().assetFile(\"asset_file.realm\").inMemory().build();\n            fail();\n        } catch (RealmException ignored) {\n        }\n    }\n\n    @Test\n    public void assetFileFakeFile() {\n        // Ensures that there is no data.\n        Realm.deleteRealm(configFactory.createConfigurationBuilder().build());\n\n        RealmConfiguration configuration = configFactory.createConfigurationBuilder().assetFile(\"no_file\").build();\n        try {\n            Realm.getInstance(configuration);\n            fail();\n        } catch (RealmFileException expected) {\n            assertEquals(RealmFileException.Kind.ACCESS_ERROR, expected.getKind());\n        }\n    }\n\n    @Test\n    public void assetFileValidFile() throws IOException {\n        // Ensures that there is no data.\n        Realm.deleteRealm(configFactory.createConfigurationBuilder().build());\n\n        RealmConfiguration configuration = new RealmConfiguration\n                .Builder(context)\n                .modules(new AssetFileModule())\n                .assetFile(\"asset_file.realm\")\n                .build();\n        Realm.deleteRealm(configuration);\n\n        File realmFile = new File(configuration.getPath());\n        assertFalse(realmFile.exists());\n\n        realm = Realm.getInstance(configuration);\n        assertTrue(realmFile.exists());\n\n        // Asset file has 10 Owners and 10 Cats, checks if data is present.\n        assertEquals(10, realm.where(Owner.class).count());\n        assertEquals(10, realm.where(Cat.class).count());\n\n        realm.close();\n\n        // Copies original file to another location.\n        configFactory.copyRealmFromAssets(context, \"asset_file.realm\", \"asset_file_copy.realm\");\n        File copyFromAsset = new File(configFactory.getRoot(), \"asset_file_copy.realm\");\n        assertTrue(copyFromAsset.exists());\n\n        Realm.deleteRealm(configuration);\n        assertFalse(realmFile.exists());\n    }\n\n    @Test\n    public void assetFile_failsWhenDeleteRealmIfMigrationNeededConfigured() {\n        Context context = InstrumentationRegistry.getInstrumentation().getContext();\n\n        // Has a builder instance to isolate codepath.\n        RealmConfiguration.Builder builder = configFactory.createConfigurationBuilder();\n        try {\n            builder\n                    .deleteRealmIfMigrationNeeded()\n                    .assetFile(\"asset_file.realm\");\n            fail();\n        } catch (IllegalStateException expected) {\n            assertEquals(\"Realm cannot use an asset file when previously configured to clear its schema in migration by calling deleteRealmIfMigrationNeeded().\",\n                    expected.getMessage());\n        }\n    }\n\n    private static class MigrationWithNoEquals implements RealmMigration {\n        @Override\n        public void migrate(DynamicRealm realm, long oldVersion, long newVersion) {\n            // Does nothing.\n        }\n    }\n\n    @Test\n    public void detectMissingEqualsInCustomMigration() {\n        RealmConfiguration config1 = configFactory.createConfigurationBuilder().migration(new MigrationWithNoEquals()).build();\n        RealmConfiguration config2 = configFactory.createConfigurationBuilder().migration(new MigrationWithNoEquals()).build();\n\n        Realm realm = Realm.getInstance(config1);\n        try {\n            Realm.getInstance(config2);\n            fail();\n        } catch (IllegalArgumentException e) {\n            assertTrue(e.getMessage().contains(\"The most likely cause is that equals() and hashCode() are not overridden\"));\n        } finally {\n            realm.close();\n        }\n    }\n\n    @Test\n    public void readOnly_initialTransaction_throws() {\n        // Check assetFile(), then initialTransaction();\n        RealmConfiguration.Builder config = new RealmConfiguration.Builder()\n                .assetFile(\"foo\")\n                .readOnly()\n                .initialData(new Realm.Transaction() {\n                    @Override\n                    public void execute(Realm realm) {\n                        // Do nothing\n                    }\n                });\n\n        try {\n            config.build();\n            fail();\n        } catch (IllegalStateException ignored) {\n        }\n    }\n\n    @Test\n    public void readOnly_deleteRealmIfMigrationRequired_throws() {\n        try {\n            // This test doesn't actually fail on 'deleteRealmIfMigrationNeeded' + 'readOnly' but on\n            // 'assetFile' + 'deleteRealmIfMigrationNeed()'. This test is primarely here to prevent this\n            // case from accidentally parsing in the future.\n            new RealmConfiguration.Builder()\n                    .assetFile(\"foo\")\n                    .readOnly()\n                    .deleteRealmIfMigrationNeeded()\n                    .build();\n            fail();\n        } catch (IllegalStateException ignored) {\n        }\n    }\n\n    @Test\n    public void readOnly_compactOnLaunch_throws() {\n        try {\n            new RealmConfiguration.Builder()\n                    .assetFile(\"foo\")\n                    .readOnly()\n                    .compactOnLaunch(new CompactOnLaunchCallback() {\n                        @Override\n                        public boolean shouldCompact(long totalBytes, long usedBytes) {\n                            return false;\n                        }\n                    })\n                    .build();\n            fail();\n        } catch (IllegalStateException ignored) {\n        }\n    }\n\n    @Test\n    public void maxNumberOfActiveVersions() {\n        RealmConfiguration config = new RealmConfiguration.Builder()\n                .maxNumberOfActiveVersions(42)\n                .build();\n        assertEquals(42, config.getMaxNumberOfActiveVersions());\n    }\n\n    @Test\n    public void maxNumberOfActiveVersions_throwsIfZeroOrNegative() {\n        RealmConfiguration.Builder builder = new RealmConfiguration.Builder();\n        try {\n            builder.maxNumberOfActiveVersions(0);\n        } catch (IllegalArgumentException ignore) {\n        }\n\n        try {\n            builder.maxNumberOfActiveVersions(-1);\n        } catch (IllegalArgumentException ignore) {\n        }\n    }\n\n    @Test\n    public void allowQueriesOnUiThread_defaultsToTrue() {\n        RealmConfiguration configuration = new RealmConfiguration.Builder().build();\n        assertTrue(configuration.isAllowQueriesOnUiThread());\n    }\n\n    @Test\n    public void allowQueriesOnUiThread_explicitFalse() {\n        RealmConfiguration configuration = new RealmConfiguration.Builder()\n                .allowQueriesOnUiThread(false)\n                .build();\n        assertFalse(configuration.isAllowQueriesOnUiThread());\n    }\n\n    @Test\n    public void allowQueriesOnUiThread_explicitTrue() {\n        RealmConfiguration configuration = new RealmConfiguration.Builder()\n                .allowQueriesOnUiThread(true)\n                .build();\n        assertTrue(configuration.isAllowQueriesOnUiThread());\n    }\n\n    @Test\n    public void allowWritesOnUiThread_defaultsToFalse() {\n        RealmConfiguration configuration = new RealmConfiguration.Builder().build();\n        assertFalse(configuration.isAllowWritesOnUiThread());\n    }\n\n    @Test\n    public void allowWritesOnUiThread_explicitFalse() {\n        RealmConfiguration configuration = new RealmConfiguration.Builder()\n                .allowWritesOnUiThread(false)\n                .build();\n        assertFalse(configuration.isAllowWritesOnUiThread());\n    }\n\n    @Test\n    public void allowWritesOnUiThread_explicitTrue() {\n        RealmConfiguration configuration = new RealmConfiguration.Builder()\n                .allowWritesOnUiThread(true)\n                .build();\n        assertTrue(configuration.isAllowWritesOnUiThread());\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/RealmInMemoryTest.java",
    "content": "/*\n * Copyright 2015 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\npackage io.realm;\n\nimport androidx.test.ext.junit.runners.AndroidJUnit4;\n\nimport junit.framework.AssertionFailedError;\n\nimport org.junit.After;\nimport org.junit.Before;\nimport org.junit.Ignore;\nimport org.junit.Rule;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\n\nimport java.io.File;\nimport java.util.concurrent.CountDownLatch;\nimport java.util.concurrent.ExecutionException;\nimport java.util.concurrent.TimeUnit;\n\nimport io.realm.entities.Dog;\nimport io.realm.exceptions.RealmFileException;\n\nimport static junit.framework.Assert.assertEquals;\nimport static junit.framework.Assert.assertTrue;\nimport static junit.framework.Assert.fail;\n\n@Ignore(\"FIXME: See https://github.com/realm/realm-java/issues/6790\")\n@RunWith(AndroidJUnit4.class)\npublic class RealmInMemoryTest {\n\n    @Rule\n    public final TestRealmConfigurationFactory configFactory = new TestRealmConfigurationFactory();\n\n    private final static String IDENTIFIER = \"InMemRealmTest\";\n\n    private Realm testRealm;\n    private RealmConfiguration inMemConf;\n\n    @Before\n    public void setUp() {\n        RealmConfiguration onDiskConf = configFactory.createConfigurationBuilder()\n                .name(IDENTIFIER)\n                .build();\n        inMemConf = configFactory.createConfigurationBuilder()\n                .name(IDENTIFIER)\n                .inMemory()\n                .build();\n\n        // Deletes the same name Realm file just in case.\n        Realm.deleteRealm(onDiskConf);\n        testRealm = Realm.getInstance(inMemConf);\n    }\n\n    @After\n    public void tearDown() {\n        if (testRealm != null) {\n            testRealm.close();\n        }\n    }\n\n    // Tests the in-memory Realm by creating one instance, adding a record, then closes the instance.\n    // By the next time in-memory Realm instance with the same name created, it should be empty.\n    @Test\n    public void inMemoryRealm() {\n        testRealm.beginTransaction();\n        Dog dog = testRealm.createObject(Dog.class);\n        dog.setName(\"DinoDog\");\n        testRealm.commitTransaction();\n\n        assertEquals(1, testRealm.where(Dog.class).count());\n        assertEquals(\"DinoDog\", testRealm.where(Dog.class).findFirst().getName());\n\n        testRealm.close();\n        // After all references to the in-mem-realm closed,\n        // in-mem-realm with same identifier should create a fresh new instance.\n        testRealm = Realm.getInstance(inMemConf);\n        assertEquals(0, testRealm.where(Dog.class).count());\n    }\n\n    // Two in-memory Realms with different names should not affect each other.\n    @Test\n    public void inMemoryRealmWithDifferentNames() {\n        testRealm.beginTransaction();\n        Dog dog = testRealm.createObject(Dog.class);\n        dog.setName(\"DinoDog\");\n        testRealm.commitTransaction();\n\n        // Creates the 2nd in-memory Realm with a different name. To make sure they are not affecting each other.\n        RealmConfiguration inMemConf2 = configFactory.createConfigurationBuilder()\n                .name(IDENTIFIER + \"2\")\n                .inMemory()\n                .build();\n        Realm testRealm2 = Realm.getInstance(inMemConf2);\n        testRealm2.beginTransaction();\n        Dog dog2 = testRealm2.createObject(Dog.class);\n        dog2.setName(\"UFODog\");\n        testRealm2.commitTransaction();\n\n        assertEquals(1, testRealm.where(Dog.class).count());\n        //noinspection ConstantConditions\n        assertEquals(\"DinoDog\", testRealm.where(Dog.class).findFirst().getName());\n        assertEquals(1, testRealm2.where(Dog.class).count());\n        //noinspection ConstantConditions\n        assertEquals(\"UFODog\", testRealm2.where(Dog.class).findFirst().getName());\n\n        testRealm2.close();\n    }\n\n    // Tests deleteRealm called on a in-memory Realm instance.\n    @Test\n    public void delete() {\n        RealmConfiguration configuration = testRealm.getConfiguration();\n        try {\n            Realm.deleteRealm(configuration);\n            fail(\"Realm.deleteRealm should fail with illegal state\");\n        } catch (IllegalStateException ignored) {\n        }\n\n        // Nothing should happen when delete a closed in-mem-realm.\n        testRealm.close();\n        testRealm = null;\n        assertTrue(Realm.deleteRealm(configuration));\n    }\n\n    // Tests if an in-memory Realm can be written to disk with/without encryption.\n    @Test\n    public void writeCopyTo() {\n        byte[] key = TestHelper.getRandomKey();\n        String fileName = IDENTIFIER + \".realm\";\n        String encFileName = IDENTIFIER + \".enc.realm\";\n        RealmConfiguration conf = configFactory.createConfigurationBuilder()\n                .name(fileName)\n                .build();\n        RealmConfiguration encConf = configFactory.createConfigurationBuilder()\n                .name(encFileName)\n                .encryptionKey(key)\n                .build();\n\n        Realm.deleteRealm(conf);\n        Realm.deleteRealm(encConf);\n\n        testRealm.beginTransaction();\n        Dog dog = testRealm.createObject(Dog.class);\n        dog.setName(\"DinoDog\");\n        testRealm.commitTransaction();\n\n        // Tests a normal Realm file.\n        testRealm.writeCopyTo(new File(configFactory.getRoot(), fileName));\n        Realm onDiskRealm = Realm.getInstance(conf);\n        assertEquals(1, onDiskRealm.where(Dog.class).count());\n        onDiskRealm.close();\n\n        // Tests a encrypted Realm file.\n        testRealm.writeEncryptedCopyTo(new File(configFactory.getRoot(), encFileName), key);\n        onDiskRealm = Realm.getInstance(encConf);\n        assertEquals(1, onDiskRealm.where(Dog.class).count());\n        onDiskRealm.close();\n        // Tests with a wrong key to see if it fails as expected.\n        try {\n            RealmConfiguration wrongKeyConf = configFactory.createConfigurationBuilder()\n                    .name(encFileName)\n                    .encryptionKey(TestHelper.getRandomKey(42))\n                    .build();\n            Realm.getInstance(wrongKeyConf);\n            fail(\"Realm.getInstance should fail with RealmFileException\");\n        } catch (RealmFileException expected) {\n            assertEquals(RealmFileException.Kind.ACCESS_ERROR, expected.getKind());\n        }\n    }\n\n    // Tests writeCopyTo result when called in a transaction.\n    @Test\n    public void writeCopyToInTransaction() {\n        String fileName = IDENTIFIER + \".realm\";\n        RealmConfiguration conf = configFactory.createConfigurationBuilder()\n                .name(fileName)\n                .build();\n\n        Realm.deleteRealm(conf);\n\n        testRealm.beginTransaction();\n        Dog dog = testRealm.createObject(Dog.class);\n        dog.setName(\"DinoDog\");\n\n        // Write copy to destination file in transaction.\n        // Check if the new data would be written into the file.\n        testRealm.writeCopyTo(new File(configFactory.getRoot(), fileName));\n        Realm onDiskRealm = Realm.getInstance(conf);\n        assertEquals(1, onDiskRealm.where(Dog.class).count());\n\n        testRealm.commitTransaction();\n\n        assertEquals(1, testRealm.where(Dog.class).count());\n        onDiskRealm.close();\n    }\n\n\n    // Test below scenario:\n    // 1. Creates a in-memory Realm instance in the main thread.\n    // 2. Creates a in-memory Realm with same name in another thread.\n    // 3. Closes the in-memory Realm instance in the main thread and the Realm data should not be released since\n    //    another instance is still held by the other thread.\n    // 4. Closes the in-memory Realm instance and the Realm data should be released since no more instance with the\n    //    specific name exists.\n    @Test\n    public void multiThread() throws InterruptedException, ExecutionException {\n        final CountDownLatch workerCommittedLatch = new CountDownLatch(1);\n        final CountDownLatch workerClosedLatch = new CountDownLatch(1);\n        final CountDownLatch realmInMainClosedLatch = new CountDownLatch(1);\n        final AssertionFailedError threadError[] = new AssertionFailedError[1];\n\n        // Step 2.\n        Thread workerThread = new Thread(new Runnable() {\n            @Override\n            public void run() {\n                Realm realm = Realm.getInstance(inMemConf);\n                realm.beginTransaction();\n                Dog dog = realm.createObject(Dog.class);\n                dog.setName(\"DinoDog\");\n                realm.commitTransaction();\n\n                try {\n                    assertEquals(1, realm.where(Dog.class).count());\n                } catch (AssertionFailedError afe) {\n                    threadError[0] = afe;\n                    realm.close();\n                    return;\n                }\n                workerCommittedLatch.countDown();\n\n                // Waits until Realm instance closed in main thread.\n                try {\n                    realmInMainClosedLatch.await(TestHelper.SHORT_WAIT_SECS, TimeUnit.SECONDS);\n                } catch (InterruptedException e) {\n                    threadError[0] = new AssertionFailedError(\"Worker thread was interrupted.\");\n                    realm.close();\n                    return;\n                }\n\n                realm.close();\n                workerClosedLatch.countDown();\n            }\n        });\n        workerThread.start();\n\n\n        // Waits until the worker thread started.\n        workerCommittedLatch.await(TestHelper.SHORT_WAIT_SECS, TimeUnit.SECONDS);\n        if (threadError[0] != null) {\n            throw threadError[0];\n        }\n\n        // Refreshes will be ran in the next loop, manually refreshes it here.\n        testRealm.refresh();\n        assertEquals(1, testRealm.where(Dog.class).count());\n\n        // Step 3.\n        // Releases the main thread Realm reference, and the worker thread holds the reference still.\n        testRealm.close();\n\n        // Step 4.\n        // Creates a new Realm reference in main thread and checks the data.\n        testRealm = Realm.getInstance(inMemConf);\n        assertEquals(1, testRealm.where(Dog.class).count());\n        testRealm.close();\n\n        // Let the worker thread continue.\n        realmInMainClosedLatch.countDown();\n\n        // Waits until the worker thread finished.\n        workerClosedLatch.await(TestHelper.SHORT_WAIT_SECS, TimeUnit.SECONDS);\n        if (threadError[0] != null) {\n            throw threadError[0];\n        }\n\n        // Since all previous Realm instances has been closed before, below will create a fresh new in-mem-realm instance.\n        testRealm = Realm.getInstance(inMemConf);\n        assertEquals(0, testRealm.where(Dog.class).count());\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/RealmInterprocessTest.java",
    "content": "/*\n * Copyright 2015 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\npackage io.realm;\n\nimport android.annotation.SuppressLint;\nimport android.app.ActivityManager;\nimport android.content.ComponentName;\nimport android.content.Context;\nimport android.content.Intent;\nimport android.content.ServiceConnection;\nimport android.os.Bundle;\nimport android.os.Handler;\nimport android.os.IBinder;\nimport android.os.Looper;\nimport android.os.Message;\nimport android.os.Messenger;\nimport android.os.RemoteException;\nimport androidx.test.platform.app.InstrumentationRegistry;\nimport androidx.test.ext.junit.runners.AndroidJUnit4;\n\nimport org.junit.After;\nimport org.junit.Before;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\n\nimport java.util.List;\nimport java.util.concurrent.CountDownLatch;\nimport java.util.concurrent.TimeUnit;\nimport java.util.concurrent.atomic.AtomicInteger;\n\nimport io.realm.entities.AllTypes;\nimport io.realm.entities.AllTypesModelModule;\nimport io.realm.log.RealmLog;\nimport io.realm.rule.BlockingLooperThread;\nimport io.realm.services.RemoteProcessService;\nimport kotlin.Unit;\nimport kotlin.jvm.functions.Function0;\n\nimport static org.junit.Assert.assertEquals;\nimport static org.junit.Assert.assertTrue;\nimport static org.junit.Assert.fail;\n\n\n// This is built for testing multi processes related cases.\n// To build a test case, create an InterprocessHandler in your test case. This handler will run in the newly\n// created thread's Looper. Remember to call Looper.loop() to start handling messages.\n// Pass the first thing you want to run to the constructor which will be posted to the beginning of the message queue.\n// And add steps you want to run in the remote process in RemoteProcessService.\n// Write the comments of the test case like this:\n// A-Z means steps running from remote service process.\n// 1-9xx means steps running from the main local process.\n// eg.: A. Open a Realm\n//      1. Open two Realms\n//      B. Open three Realms\n//      2. assertTrue(\"OK, remote process win. You can open more Realms than I do in the main local process\", false);\n@RunWith(AndroidJUnit4.class)\npublic class RealmInterprocessTest {\n\n    private Realm testRealm;\n    private Messenger remoteMessenger;\n    private Messenger localMessenger;\n    private CountDownLatch serviceStartLatch;\n    private final ServiceConnection serviceConnection = new ServiceConnection() {\n        @Override\n        public void onServiceConnected(ComponentName componentName, IBinder iBinder) {\n            remoteMessenger = new Messenger(iBinder);\n            if (serviceStartLatch != null) {\n                serviceStartLatch.countDown();\n            }\n        }\n\n        @Override\n        public void onServiceDisconnected(ComponentName componentName) {\n            if (serviceStartLatch != null && serviceStartLatch.getCount() > 1) {\n                serviceStartLatch.countDown();\n            }\n            serviceStartLatch = null;\n        }\n    };\n\n    BlockingLooperThread looperThread = new BlockingLooperThread();\n\n    // Helper handler to make it easy to interact with remote service process.\n    @SuppressLint(\"HandlerLeak\") // SuppressLint bug, doesn't work\n    private class InterprocessHandler extends Handler {\n        // Timeout Watchdog. In case the service crashed or expected response is not returned.\n        // It is very important to feed the dog after the expected message arrived.\n        private final static int timeout = 10_000;\n        private volatile boolean isTimeout = true;\n        private Runnable timeoutRunnable = new Runnable() {\n            @Override\n            public void run() {\n                if (isTimeout) {\n                    assertTrue(\"Timeout happened\", false);\n                } else {\n                    isTimeout = true;\n                    postDelayed(timeoutRunnable, timeout);\n                }\n            }\n        };\n\n        protected void clearTimeoutFlag() {\n            isTimeout = false;\n        }\n\n        protected void done() {\n            Looper.myLooper().quit();\n        }\n\n        public InterprocessHandler(Runnable startRunnable) {\n            super(Looper.myLooper());\n            localMessenger = new Messenger(this);\n            // To have the first step from main process run.\n            post(startRunnable);\n            // Starts watchdog.\n            postDelayed(timeoutRunnable, timeout);\n        }\n\n        @Override\n        public void handleMessage(Message msg) {\n            Bundle bundle = msg.getData();\n            String error = bundle.getString(RemoteProcessService.BUNDLE_KEY_ERROR);\n            if (error != null) {\n                // Asserts and shows error from service process.\n                assertTrue(error, false);\n            }\n        }\n    }\n\n    @Before\n    public void setUp() throws Exception {\n        Realm.init(InstrumentationRegistry.getInstrumentation().getTargetContext());\n        Realm.deleteRealm(getConfiguration());\n\n        // Starts the testing service.\n        serviceStartLatch = new CountDownLatch(1);\n        Intent intent = new Intent(getContext(), RemoteProcessService.class);\n        getContext().bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE);\n        assertTrue(serviceStartLatch.await(TestHelper.SHORT_WAIT_SECS, TimeUnit.SECONDS));\n    }\n\n    private RealmConfiguration getConfiguration() {\n        return new RealmConfiguration.Builder(getContext()).modules(new AllTypesModelModule()).build();\n    }\n\n    @After\n    public void tearDown() throws Exception {\n        int counter = 10;\n        getContext().unbindService(serviceConnection);\n        remoteMessenger = null;\n\n        // Kills the remote process.\n        ActivityManager.RunningAppProcessInfo info = getRemoteProcessInfo();\n        if (info != null) {\n            android.os.Process.killProcess(info.pid);\n        }\n        while (getRemoteProcessInfo() != null) {\n            if (counter == 0) {\n                assertTrue(\"The remote service process is still alive.\", false);\n            }\n            Thread.sleep(300);\n            counter--;\n        }\n    }\n\n    // Calls this to trigger the next step of service process.\n    private void triggerServiceStep(RemoteProcessService.Step step) {\n        Message msg = Message.obtain(null, step.message);\n        msg.replyTo = localMessenger;\n        try {\n            remoteMessenger.send(msg);\n        } catch (RemoteException e) {\n            assertTrue(false);\n        }\n    }\n\n    // Returns the service info if it is alive.\n    // When this method returns null, it doesn't mean the remote process is not existed. An 'empty' process could\n    // be retained by the system to be used next time.\n    // Use getRemoteProcessInfo if you want to check the existence of remote process.\n    private ActivityManager.RunningServiceInfo getServiceInfo() {\n        ActivityManager manager = (ActivityManager) getContext().getSystemService(Context.ACTIVITY_SERVICE);\n        List<ActivityManager.RunningServiceInfo> serviceInfoList = manager.getRunningServices(Integer.MAX_VALUE);\n        for (ActivityManager.RunningServiceInfo service : serviceInfoList) {\n            if (RemoteProcessService.class.getName().equals(service.service.getClassName())) {\n                return service;\n            }\n        }\n        return null;\n    }\n\n    private Context getContext() {\n        return InstrumentationRegistry.getInstrumentation().getTargetContext();\n    }\n\n    // Gets the remote process info if it is alive.\n    private ActivityManager.RunningAppProcessInfo getRemoteProcessInfo() {\n        ActivityManager manager = (ActivityManager) getContext().getSystemService(Context.ACTIVITY_SERVICE);\n        List<ActivityManager.RunningAppProcessInfo> processInfoList = manager.getRunningAppProcesses();\n        for (ActivityManager.RunningAppProcessInfo info : processInfoList) {\n            if (info.processName.equals(getContext().getPackageName() + \":remote\")) {\n                return info;\n            }\n        }\n\n        return null;\n    }\n\n    // A. Opens a realm, closes it, then calls Runtime.getRuntime().exit(0).\n    // 1. Waits 3 seconds to see if the service process existed.\n    @Test\n    public void exitProcess() {\n        looperThread.runBlocking(\"testThread\", true, new Function0<Unit>() {\n            @Override\n            public Unit invoke() {\n                new InterprocessHandler(new Runnable() {\n                    @Override\n                    public void run() {\n                        // Step A\n                        triggerServiceStep(RemoteProcessService.stepExitProcess_A);\n                    }\n                }) {\n\n                    @SuppressWarnings(\"ConstantConditions\")\n                    final int servicePid = getServiceInfo().pid;\n\n                    @Override\n                    public void handleMessage(Message msg) {\n                        super.handleMessage(msg);\n                        if (msg.what == RemoteProcessService.stepExitProcess_A.message) {\n                            // Step 1\n                            clearTimeoutFlag();\n                            try {\n                                // Timeout is 5 seconds. 3 (6x500ms) seconds should be enough to quit the process.\n                                for (int i = 1; i <= 6; i++) {\n                                    // We need to retrieve the service's pid again since the system might restart it automatically.\n                                    ActivityManager.RunningAppProcessInfo processInfo = getRemoteProcessInfo();\n                                    if (processInfo != null && processInfo.pid == servicePid && i >= 6) {\n                                        // The process is still alive.\n                                        fail(\"Process is still alive\");\n                                    } else if (processInfo == null || processInfo.pid != servicePid) {\n                                        // The process is gone.\n                                        break;\n                                    }\n                                    Thread.sleep(500);\n                                }\n                            } catch (InterruptedException e) {\n                                e.printStackTrace();\n                                assertTrue(false);\n                            }\n                            looperThread.testComplete();\n                        }\n                    }\n                };\n                return Unit.INSTANCE;\n            }\n        });\n    }\n\n    // 1. Main process creates Realm, write one object.\n    // A. Service process opens Realm, check if there is one and only one object.\n    @Test\n    public void createInitialRealm() throws InterruptedException {\n        looperThread.runBlocking(\"testThread\", true, new Function0<Unit>() {\n            @Override\n            public Unit invoke() {\n                new InterprocessHandler(new Runnable() {\n                    @Override\n                    public void run() {\n                        // Step 1\n                        testRealm = Realm.getInstance(getConfiguration());\n                        looperThread.closeAfterTest(testRealm);\n                        assertEquals(0, testRealm.where(AllTypes.class).count());\n                        testRealm.beginTransaction();\n                        testRealm.createObject(AllTypes.class);\n                        testRealm.commitTransaction();\n\n                        // Step A\n                        triggerServiceStep(RemoteProcessService.stepCreateInitialRealm_A);\n                    }\n                }) {\n\n                    @Override\n                    public void handleMessage(Message msg) {\n                        super.handleMessage(msg);\n                        if (msg.what == RemoteProcessService.stepCreateInitialRealm_A.message) {\n                            clearTimeoutFlag();\n                            looperThread.testComplete();\n                        } else {\n                            assertTrue(false);\n                        }\n                    }\n                };\n                return Unit.INSTANCE;\n            }\n        });\n    }\n\n    @Test\n    public void interprocessNotifications() {\n        looperThread.runBlocking(\"testThread\", true, new Function0<Unit>() {\n            private RealmResults<AllTypes> results;\n            private AtomicInteger updateCount = new AtomicInteger(0);\n\n            @Override\n            public Unit invoke() {\n                new InterprocessHandler(new Runnable() {\n                    @Override\n                    public void run() {\n                        testRealm = Realm.getInstance(getConfiguration());\n                        looperThread.closeAfterTest(testRealm);\n                        results = testRealm.where(AllTypes.class).findAll();\n                        assertEquals(0, results.size());\n                        results.addChangeListener(new RealmChangeListener<RealmResults<AllTypes>>() {\n                            @Override\n                            public void onChange(RealmResults<AllTypes> allTypes) {\n                                switch(updateCount.incrementAndGet()) {\n                                    case 1: {\n                                        assertEquals(1, results.size());\n                                        break;\n                                    }\n                                    case 2: {\n                                        assertEquals(2, results.size());\n                                        looperThread.testComplete();\n                                        break;\n                                    }\n                                }\n                            }\n                        });\n                        triggerServiceStep(RemoteProcessService.stepCreateObjects);\n                    }\n                }) {\n                    @Override\n                    public void handleMessage(Message msg) {\n                        super.handleMessage(msg);\n                        if (msg.what == RemoteProcessService.stepCreateObjects.message) {\n                            clearTimeoutFlag();\n                        } else {\n                            assertTrue(false);\n                        }\n                    }\n                };\n                return Unit.INSTANCE;\n            }\n        });\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/RealmJsonAbsentPrimaryKeyTests.java",
    "content": "/*\n * Copyright 2016 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\npackage io.realm;\n\nimport android.os.Build;\n\nimport org.json.JSONArray;\nimport org.json.JSONException;\nimport org.json.JSONObject;\nimport org.junit.After;\nimport org.junit.Before;\nimport org.junit.Rule;\nimport org.junit.Test;\nimport org.junit.rules.ExpectedException;\nimport org.junit.runner.RunWith;\nimport org.junit.runners.Parameterized;\n\nimport java.io.IOException;\nimport java.util.Arrays;\n\nimport io.realm.entities.PrimaryKeyAsBoxedByte;\nimport io.realm.entities.PrimaryKeyAsBoxedInteger;\nimport io.realm.entities.PrimaryKeyAsBoxedLong;\nimport io.realm.entities.PrimaryKeyAsBoxedShort;\nimport io.realm.entities.PrimaryKeyAsObjectId;\nimport io.realm.entities.PrimaryKeyAsString;\nimport io.realm.entities.PrimaryKeyAsUUID;\n\nimport static org.hamcrest.number.OrderingComparison.greaterThanOrEqualTo;\nimport static org.junit.Assume.assumeThat;\n\n@RunWith(Parameterized.class)\npublic class RealmJsonAbsentPrimaryKeyTests {\n    @Rule\n    public final TestRealmConfigurationFactory configFactory = new TestRealmConfigurationFactory();\n    @Rule\n    public final ExpectedException thrown = ExpectedException.none();\n\n    protected Realm realm;\n\n    @Before\n    public void setUp() {\n        RealmConfiguration realmConfig = configFactory.createConfiguration();\n        realm = Realm.getInstance(realmConfig);\n    }\n\n    @After\n    public void tearDown() {\n        if (realm != null) {\n            realm.close();\n        }\n    }\n\n    // Parameters for testing absent primary key value. PrimaryKey field is absent.\n    @Parameterized.Parameters\n    public static Iterable<Object[]> data() {\n        return Arrays.asList(new Object[][]{\n            {PrimaryKeyAsBoxedByte.class,    \"{ \\\"name\\\":\\\"HaHaHaHaHaHaHaHaH\\\" }\"},\n            {PrimaryKeyAsBoxedShort.class,   \"{ \\\"name\\\":\\\"KeyValueTestIsFun\\\" }\"},\n            {PrimaryKeyAsBoxedInteger.class, \"{ \\\"name\\\":\\\"FunValueTestIsKey\\\" }\"},\n            {PrimaryKeyAsBoxedLong.class,    \"{ \\\"name\\\":\\\"NameAsBoxedLong-!\\\" }\"},\n            {PrimaryKeyAsString.class,       \"{ \\\"id\\\":2429214 }\"},\n            {PrimaryKeyAsObjectId.class,     \"{ \\\"name\\\":\\\"789ABCDEF0123456789ABCDE\\\" }\"},\n            {PrimaryKeyAsUUID.class,         \"{ \\\"name\\\":\\\"NameAsBoxedLong-!\\\" }\"}\n        });\n    }\n\n    final private Class<? extends RealmObject> clazz;\n    final private String jsonString;\n\n    public RealmJsonAbsentPrimaryKeyTests(Class<? extends RealmObject> clazz, String jsonString) {\n        this.jsonString = jsonString;\n        this.clazz = clazz;\n    }\n\n    // Tests absent primary key value for createObjectFromJson().\n    @Test\n    public void createObjectFromJson_primaryKey_isAbsent_fromJsonObject() throws JSONException {\n        realm.beginTransaction();\n        thrown.expect(IllegalArgumentException.class);\n        realm.createObjectFromJson(clazz, new JSONObject(jsonString));\n        realm.commitTransaction();\n    }\n\n    // Tests absent primary key value for createOrUpdateObjectFromJson().\n    @Test\n    public void createOrUpdateObjectFromJson_primaryKey_isAbsent_fromJsonObject() throws JSONException {\n        realm.beginTransaction();\n        thrown.expect(IllegalArgumentException.class);\n        realm.createOrUpdateObjectFromJson(clazz, new JSONObject(jsonString));\n        realm.commitTransaction();\n    }\n\n    // Tests absent primary key value for createAllFromJson().\n    @Test\n    public void createAllFromJson_primaryKey_isAbsent_fromJsonObject() throws JSONException {\n        JSONArray jsonArray = new JSONArray();\n        jsonArray.put(new JSONObject(jsonString));\n        realm.beginTransaction();\n        thrown.expect(IllegalArgumentException.class);\n        realm.createAllFromJson(clazz, jsonArray);\n        realm.commitTransaction();\n    }\n\n    // Tests absent primary key value for createOrUpdateAllFromJson().\n    @Test\n    public void createOrUpdateAllFromJson_primaryKey_isAbsent_fromJsonObject() throws JSONException {\n        JSONArray jsonArray = new JSONArray();\n        jsonArray.put(new JSONObject(jsonString));\n        realm.beginTransaction();\n        thrown.expect(IllegalArgumentException.class);\n        realm.createOrUpdateAllFromJson(clazz, jsonArray);\n        realm.commitTransaction();\n    }\n\n    // Tests absent primary key value for createObjectFromJson() stream version.\n    @Test\n    public void createObjectFromJson_primaryKey_isAbsent_fromJsonStream() throws JSONException, IOException {\n        assumeThat(Build.VERSION.SDK_INT, greaterThanOrEqualTo(Build.VERSION_CODES.HONEYCOMB));\n\n        realm.beginTransaction();\n        thrown.expect(IllegalArgumentException.class);\n        realm.createObjectFromJson(clazz, TestHelper.stringToStream(jsonString));\n        realm.commitTransaction();\n    }\n\n    // Tests absent primary key value for createOrUpdateObjectFromJson() stream version.\n    @Test\n    public void createOrUpdateObjectFromJson_primaryKey_isAbsent_fromJsonStream() throws JSONException, IOException {\n        realm.beginTransaction();\n        thrown.expect(IllegalArgumentException.class);\n        realm.createOrUpdateObjectFromJson(clazz, TestHelper.stringToStream(jsonString));\n        realm.commitTransaction();\n    }\n\n    // Tests absent primary key value for createAllFromJson() stream version.\n    @Test\n    public void createAllFromJson_primaryKey_isAbsent_fromJsonStream() throws JSONException, IOException {\n        assumeThat(Build.VERSION.SDK_INT, greaterThanOrEqualTo(Build.VERSION_CODES.HONEYCOMB));\n\n        JSONArray jsonArray = new JSONArray();\n        jsonArray.put(new JSONObject(jsonString));\n        realm.beginTransaction();\n        thrown.expect(IllegalArgumentException.class);\n        realm.createAllFromJson(clazz, TestHelper.stringToStream(jsonArray.toString()));\n        realm.commitTransaction();\n    }\n\n    // Tests absent primary key value for createOrUpdateAllFromJson() stream version.\n    @Test\n    public void createOrUpdateAllFromJson_primaryKey_isAbsent_fromJsonStream() throws JSONException, IOException {\n        assumeThat(Build.VERSION.SDK_INT, greaterThanOrEqualTo(Build.VERSION_CODES.HONEYCOMB));\n\n        JSONArray jsonArray = new JSONArray();\n        jsonArray.put(new JSONObject(jsonString));\n        realm.beginTransaction();\n        thrown.expect(IllegalArgumentException.class);\n        realm.createOrUpdateAllFromJson(clazz, TestHelper.stringToStream(jsonArray.toString()));\n        realm.commitTransaction();\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/RealmJsonNullPrimaryKeyTests.java",
    "content": "/*\n * Copyright 2016 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\npackage io.realm;\n\nimport org.json.JSONException;\nimport org.json.JSONObject;\nimport org.junit.After;\nimport org.junit.Before;\nimport org.junit.Rule;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.junit.runners.Parameterized;\n\nimport java.util.Arrays;\n\nimport io.realm.entities.PrimaryKeyAsBoxedByte;\nimport io.realm.entities.PrimaryKeyAsBoxedInteger;\nimport io.realm.entities.PrimaryKeyAsBoxedLong;\nimport io.realm.entities.PrimaryKeyAsBoxedShort;\nimport io.realm.entities.PrimaryKeyAsObjectId;\nimport io.realm.entities.PrimaryKeyAsString;\nimport io.realm.entities.PrimaryKeyAsUUID;\nimport io.realm.objectid.NullPrimaryKey;\n\nimport static org.junit.Assert.assertEquals;\nimport static org.junit.Assert.assertNull;\n\n@RunWith(Parameterized.class)\npublic class RealmJsonNullPrimaryKeyTests {\n    @Rule\n    public final TestRealmConfigurationFactory configFactory = new TestRealmConfigurationFactory();\n\n    protected Realm realm;\n\n    @Before\n    public void setUp() {\n        RealmConfiguration realmConfig = configFactory.createConfiguration();\n        realm = Realm.getInstance(realmConfig);\n    }\n\n    @After\n    public void tearDown() {\n        if (realm != null) {\n            realm.close();\n        }\n    }\n\n    // Parameters for testing null primary key value. PrimaryKey field is explicitly null.\n    @Parameterized.Parameters\n    public static Iterable<Object[]> data() {\n        return Arrays.asList(new Object[][] {\n                {PrimaryKeyAsBoxedByte.class, \"OhThisIsNullKey?!\", \"{ \\\"id\\\":null, \\\"name\\\":\\\"OhThisIsNullKey?!\\\" }\"},\n                {PrimaryKeyAsBoxedShort.class, \"YouBetItIsNullKey\", \"{ \\\"id\\\":null, \\\"name\\\":\\\"YouBetItIsNullKey\\\" }\"},\n                {PrimaryKeyAsBoxedInteger.class, \"Gosh Didnt KnowIt\", \"{ \\\"id\\\":null, \\\"name\\\":\\\"Gosh Didnt KnowIt\\\" }\"},\n                {PrimaryKeyAsBoxedLong.class, \"?YOUNOWKNOWRIGHT?\", \"{ \\\"id\\\":null, \\\"name\\\":\\\"?YOUNOWKNOWRIGHT?\\\" }\"},\n                {PrimaryKeyAsString.class, \"4299121\", \"{ \\\"name\\\":null, \\\"id\\\":4299121  }\"},\n                {PrimaryKeyAsUUID.class, \"-!dlroWolleH\", \"{ \\\"id\\\":null, \\\"name\\\":\\\"-!dlroWolleH\\\" }\"},\n                {PrimaryKeyAsObjectId.class, \"Samsquanch\", \"{ \\\"id\\\":null, \\\"name\\\":\\\"Samsquanch\\\" }\"},\n        });\n    }\n\n    final private Class<? extends RealmObject> clazz;\n    final private String secondaryFieldValue;\n    final private String jsonString;\n\n    public RealmJsonNullPrimaryKeyTests(Class<? extends RealmObject> clazz, String secondFieldValue, String jsonString) {\n        this.jsonString = jsonString;\n        this.secondaryFieldValue = secondFieldValue;\n        this.clazz = clazz;\n    }\n\n    // Tests null primary key value for createObjectFromJson().\n    @Test\n    public void createObjectFromJson_primaryKey_isNull_fromJsonObject() throws JSONException {\n        realm.beginTransaction();\n        realm.createObjectFromJson(clazz, new JSONObject(jsonString));\n        realm.commitTransaction();\n\n        // PrimaryKeyAsString\n        if (clazz.equals(PrimaryKeyAsString.class)) {\n            RealmResults<PrimaryKeyAsString> results = realm.where(PrimaryKeyAsString.class).findAll();\n            assertEquals(1, results.size());\n            assertEquals(Long.valueOf(secondaryFieldValue).longValue(), results.first().getId());\n            assertNull(results.first().getName());\n\n            // PrimaryKeyAsObjectId\n        } else if (clazz.equals(PrimaryKeyAsUUID.class)) {\n            RealmResults<PrimaryKeyAsUUID> results = realm.where(PrimaryKeyAsUUID.class).findAll();\n            assertEquals(1, results.size());\n            assertEquals(null, results.first().getId());\n            assertEquals(secondaryFieldValue, results.first().getName());\n\n            // PrimaryKeyAsNumber\n        } else {\n            // Other types\n            RealmResults results = realm.where(clazz).findAll();\n            assertEquals(1, results.size());\n            assertNull(((NullPrimaryKey) results.first()).getId());\n            assertEquals(secondaryFieldValue, ((NullPrimaryKey) results.first()).getName());\n        }\n    }\n\n    // Tests null primary key value for createOrUpdateObjectFromJson().\n    @Test\n    public void createOrUpdateObjectFromJson_primaryKey_isNull_fromJsonObject() throws JSONException {\n        realm.beginTransaction();\n        realm.createOrUpdateObjectFromJson(clazz, new JSONObject(jsonString));\n        realm.commitTransaction();\n\n        // PrimaryKeyAsString\n        if (clazz.equals(PrimaryKeyAsString.class)) {\n            RealmResults<PrimaryKeyAsString> results = realm.where(PrimaryKeyAsString.class).findAll();\n            assertEquals(1, results.size());\n            assertEquals(Long.valueOf(secondaryFieldValue).longValue(), results.first().getId());\n            assertEquals(null, results.first().getName());\n\n            // PrimaryKeyAsUUID\n        } else if (clazz.equals(PrimaryKeyAsUUID.class)) {\n            RealmResults<PrimaryKeyAsUUID> results = realm.where(PrimaryKeyAsUUID.class).findAll();\n            assertEquals(1, results.size());\n            assertEquals(null, results.first().getId());\n            assertEquals(secondaryFieldValue, results.first().getName());\n\n        // PrimaryKeyAsNumber\n        } else {\n            // Other types\n            RealmResults results = realm.where(clazz).findAll();\n            assertEquals(1, results.size());\n            assertEquals(null, ((NullPrimaryKey) results.first()).getId());\n            assertEquals(secondaryFieldValue, ((NullPrimaryKey) results.first()).getName());\n        }\n    }\n\n    // Tests null primary key value for createObject() -> createOrUpdateObjectFromJson().\n    @Test\n    public void createOrUpdateObjectFromJson_primaryKey_isNull_updateFromJsonObject() throws JSONException {\n        realm.beginTransaction();\n        realm.createObject(clazz, null); // name = null, id =null\n        realm.createOrUpdateObjectFromJson(clazz, new JSONObject(jsonString));\n        realm.commitTransaction();\n\n        // PrimaryKeyAsString\n        if (clazz.equals(PrimaryKeyAsString.class)) {\n            RealmResults<PrimaryKeyAsString> results = realm.where(PrimaryKeyAsString.class).findAll();\n            assertEquals(1, results.size());\n            assertEquals(Long.valueOf(secondaryFieldValue).longValue(), results.first().getId());\n            assertEquals(null, results.first().getName());\n\n            // PrimaryKeyAsUUID\n        } else if (clazz.equals(PrimaryKeyAsUUID.class)) {\n            RealmResults<PrimaryKeyAsUUID> results = realm.where(PrimaryKeyAsUUID.class).findAll();\n            assertEquals(1, results.size());\n            assertEquals(null, results.first().getId());\n            assertEquals(secondaryFieldValue, results.first().getName());\n\n            // PrimaryKeyAsNumber\n        } else {\n            // Other types\n            RealmResults results = realm.where(clazz).findAll();\n            assertEquals(1, results.size());\n            assertEquals(null, ((NullPrimaryKey) results.first()).getId());\n            assertEquals(secondaryFieldValue, ((NullPrimaryKey) results.first()).getName());\n        }\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/RealmJsonTests.java",
    "content": "/*\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\npackage io.realm;\n\nimport android.content.Context;\nimport android.os.Build;\nimport android.util.Base64;\n\nimport org.bson.types.Decimal128;\nimport org.bson.types.ObjectId;\nimport org.json.JSONArray;\nimport org.json.JSONException;\nimport org.json.JSONObject;\nimport org.junit.After;\nimport org.junit.Before;\nimport org.junit.Rule;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\n\nimport java.io.ByteArrayInputStream;\nimport java.io.IOException;\nimport java.io.InputStream;\nimport java.math.BigDecimal;\nimport java.nio.charset.Charset;\nimport java.nio.charset.StandardCharsets;\nimport java.text.DateFormat;\nimport java.text.SimpleDateFormat;\nimport java.util.Arrays;\nimport java.util.Calendar;\nimport java.util.Date;\nimport java.util.GregorianCalendar;\nimport java.util.TimeZone;\nimport java.util.UUID;\n\nimport javax.annotation.Nullable;\n\nimport androidx.test.ext.junit.runners.AndroidJUnit4;\nimport androidx.test.platform.app.InstrumentationRegistry;\nimport io.realm.entities.AllTypes;\nimport io.realm.entities.AllTypesPrimaryKey;\nimport io.realm.entities.AnnotationTypes;\nimport io.realm.entities.DefaultValueOfField;\nimport io.realm.entities.Dog;\nimport io.realm.entities.NoPrimaryKeyNullTypes;\nimport io.realm.entities.NullTypes;\nimport io.realm.entities.OwnerPrimaryKey;\nimport io.realm.entities.PrimaryKeyAsObjectId;\nimport io.realm.entities.PrimitiveListTypes;\nimport io.realm.entities.RandomPrimaryKey;\nimport io.realm.exceptions.RealmException;\nimport io.realm.internal.Util;\n\nimport static io.realm.internal.test.ExtraTests.assertArrayEquals;\nimport static org.hamcrest.number.OrderingComparison.greaterThanOrEqualTo;\nimport static org.junit.Assert.assertEquals;\nimport static org.junit.Assert.assertFalse;\nimport static org.junit.Assert.assertNotNull;\nimport static org.junit.Assert.assertNull;\nimport static org.junit.Assert.assertTrue;\nimport static org.junit.Assert.fail;\nimport static org.junit.Assume.assumeThat;\n\n@RunWith(AndroidJUnit4.class)\npublic class RealmJsonTests {\n    private static final Charset UTF_8 = Charset.forName(\"UTF-8\");\n\n    @Rule\n    public final TestRealmConfigurationFactory configFactory = new TestRealmConfigurationFactory();\n\n    protected Realm realm;\n    private Context context;\n\n    @Before\n    public void setUp() {\n        context = InstrumentationRegistry.getInstrumentation().getTargetContext();\n        RealmConfiguration realmConfig = configFactory.createConfiguration();\n        realm = Realm.getInstance(realmConfig);\n    }\n\n    @After\n    public void tearDown() {\n        if (realm != null) {\n            realm.close();\n        }\n    }\n\n    private InputStream convertJsonObjectToStream(JSONObject obj) {\n        return new ByteArrayInputStream(obj.toString().getBytes(UTF_8));\n    }\n\n    // Asserts that the list of AllTypesPrimaryKey objects where inserted and updated properly.\n    private void assertAllTypesPrimaryKeyUpdated() {\n        assertEquals(1, realm.where(AllTypesPrimaryKey.class).count());\n        AllTypesPrimaryKey obj = realm.where(AllTypesPrimaryKey.class).findFirst();\n        assertEquals(\"Bar\", obj.getColumnString());\n        assertEquals(2.23F, obj.getColumnFloat(), 0F);\n        assertEquals(2.234D, obj.getColumnDouble(), 0D);\n        assertEquals(true, obj.isColumnBoolean());\n        assertArrayEquals(new byte[]{1, 2, 3}, obj.getColumnBinary());\n        assertEquals(new Date(2000), obj.getColumnDate());\n        assertEquals(new ObjectId(\"789ABCDEF0123456789ABCDA\"), obj.getColumnObjectId());\n        assertEquals(new Decimal128(-43), obj.getColumnDecimal128());\n        assertEquals(UUID.fromString(\"027ba5ca-aa12-4afa-9219-e20cc3018590\"), obj.getColumnUUID());\n        assertEquals(RealmAny.valueOf(\"hello world\"), obj.getColumnRealmAny());\n        assertEquals(\"Dog4\", obj.getColumnRealmObject().getName());\n        assertEquals(2, obj.getColumnRealmList().size());\n        assertEquals(\"Dog5\", obj.getColumnRealmList().get(0).getName());\n    }\n\n    // Checks the imported object from nulltyps.json[0].\n    private void checkNullableValuesAreNull(NullTypes nullTypes1) {\n        // 1 String\n        assertNull(nullTypes1.getFieldStringNull());\n        assertEquals(\"\", nullTypes1.getFieldStringNotNull());\n        // 2 Bytes\n        assertNull(nullTypes1.getFieldBytesNull());\n        assertTrue(Arrays.equals(new byte[0], nullTypes1.getFieldBytesNotNull()));\n        // 3 Boolean\n        assertNull(nullTypes1.getFieldBooleanNull());\n        assertFalse(nullTypes1.getFieldBooleanNotNull());\n        // 4 Byte\n        assertNull(nullTypes1.getFieldByteNull());\n        assertEquals(0, nullTypes1.getFieldByteNotNull().byteValue());\n        // 5 Short\n        assertNull(nullTypes1.getFieldShortNull());\n        assertEquals(0, nullTypes1.getFieldShortNotNull().shortValue());\n        // 6 Integer\n        assertNull(nullTypes1.getFieldIntegerNull());\n        assertEquals(0, nullTypes1.getFieldIntegerNotNull().intValue());\n        // 7 Long\n        assertNull(nullTypes1.getFieldLongNull());\n        assertEquals(0, nullTypes1.getFieldLongNotNull().longValue());\n        // 8 Float\n        assertNull(nullTypes1.getFieldFloatNull());\n        assertEquals((Float)0F, nullTypes1.getFieldFloatNotNull());\n        // 9 Double\n        assertNull(nullTypes1.getFieldDoubleNull());\n        assertEquals((Double)0D, nullTypes1.getFieldDoubleNotNull());\n        // 10 Date\n        assertNull(nullTypes1.getFieldDateNull());\n        assertEquals(new Date(0), nullTypes1.getFieldDateNotNull());\n        // 11 RealmObject\n        assertNull(nullTypes1.getFieldObjectNull());\n        // 12 ObjectId\n        assertNull(nullTypes1.getFieldObjectIdNull());\n        assertEquals(new ObjectId(\"789ABCDEF0123456789ABCDE\"), nullTypes1.getFieldObjectIdNotNull());\n        // 13 Decimal128\n        assertNull(nullTypes1.getFieldDecimal128Null());\n        assertEquals(new Decimal128(-42), nullTypes1.getFieldDecimal128NotNull());\n        // 14 UUID\n        assertNull(nullTypes1.getFieldUUIDNull());\n        assertEquals(UUID.fromString(\"027ba5ca-aa12-4afa-9219-e20cc3018599\"), nullTypes1.getFieldUUIDNotNull());\n    }\n\n    // Checks the imported object from nulltyps.json[1].\n    private void checkNullableValuesAreNotNull(NullTypes nullTypes2) {\n        // 1 String\n        assertEquals(\"\", nullTypes2.getFieldStringNull());\n        assertEquals(\"\", nullTypes2.getFieldStringNotNull());\n        // 2 Bytes\n        assertTrue(Arrays.equals(new byte[0], nullTypes2.getFieldBytesNull()));\n        assertTrue(Arrays.equals(new byte[0], nullTypes2.getFieldBytesNotNull()));\n        // 3 Boolean\n        assertFalse(nullTypes2.getFieldBooleanNull());\n        assertFalse(nullTypes2.getFieldBooleanNotNull());\n        // 4 Byte\n        assertEquals(0, nullTypes2.getFieldByteNull().byteValue());\n        assertEquals(0, nullTypes2.getFieldByteNotNull().byteValue());\n        // 5 Short\n        assertEquals(0, nullTypes2.getFieldShortNull().shortValue());\n        assertEquals(0, nullTypes2.getFieldShortNotNull().shortValue());\n        // 6 Integer\n        assertEquals(0, nullTypes2.getFieldIntegerNull().intValue());\n        assertEquals(0, nullTypes2.getFieldIntegerNotNull().intValue());\n        // 7 Long\n        assertEquals(0, nullTypes2.getFieldLongNull().longValue());\n        assertEquals(0, nullTypes2.getFieldLongNotNull().longValue());\n        // 8 Float\n        assertEquals((Float)0F, nullTypes2.getFieldFloatNull());\n        assertEquals((Float)0F, nullTypes2.getFieldFloatNotNull());\n        // 9 Double\n        assertEquals((Double)0D, nullTypes2.getFieldDoubleNull());\n        assertEquals((Double)0D, nullTypes2.getFieldDoubleNotNull());\n        // 10 Date\n        assertEquals(new Date(0), nullTypes2.getFieldDateNull());\n        assertEquals(new Date(0), nullTypes2.getFieldDateNotNull());\n        // 11 RealmObject\n        assertTrue(nullTypes2.getFieldObjectNull() != null);\n        // 12 ObjectId\n        assertTrue(nullTypes2.getFieldObjectIdNull() != null);\n        assertEquals(new ObjectId(\"789ABCDEF0123456789ABCDE\"), nullTypes2.getFieldObjectIdNotNull());\n        // 13 Decimal128\n        assertTrue(nullTypes2.getFieldDecimal128Null() != null);\n        assertEquals(new Decimal128(0), nullTypes2.getFieldDecimal128NotNull());\n        // 14 UUID\n        assertTrue(nullTypes2.getFieldUUIDNull() != null);\n        assertEquals(UUID.fromString(\"027ba5ca-aa12-4afa-9219-e20cc3018599\"), nullTypes2.getFieldUUIDNotNull());\n    }\n\n    @Test\n    public void createObject_fromJsonNullObject() {\n        realm.createObjectFromJson(AllTypes.class, (JSONObject) null);\n        assertEquals(0, realm.where(AllTypes.class).count());\n    }\n\n    @Test\n    public void createAllFromJson_nullArray() {\n        realm.createAllFromJson(AllTypes.class, (JSONArray) null);\n        assertEquals(0, realm.where(AllTypes.class).count());\n\n    }\n\n    @Test\n    public void createObjectFromJson_allSimpleObjectAllTypes() throws JSONException {\n        JSONObject json = new JSONObject();\n\n        ObjectId objectId = new ObjectId(new Date(20));\n        Decimal128 decimal128 = new Decimal128(300);\n        UUID uuid = UUID.randomUUID();\n        RealmAny realmAny = RealmAny.valueOf(\"Hello world\");\n\n        json.put(\"columnString\", \"String\");\n        json.put(\"columnLong\", 1L);\n        json.put(\"columnFloat\", 1.23F);\n        json.put(\"columnDouble\", 1.23D);\n        json.put(\"columnBoolean\", true);\n        json.put(\"columnBinary\", new String(Base64.encode(new byte[] {1,2,3}, Base64.DEFAULT), UTF_8));\n        json.put(\"columnObjectId\", objectId);\n        json.put(\"columnDecimal128\", decimal128);\n        json.put(\"columnUUID\", uuid);\n        json.put(\"columnRealmAny\", realmAny);\n\n        realm.beginTransaction();\n        realm.createObjectFromJson(AllTypes.class, json);\n        realm.commitTransaction();\n        AllTypes obj = realm.where(AllTypes.class).findFirst();\n\n        // Checks that all primitive types are imported correctly.\n        assertEquals(\"String\", obj.getColumnString());\n        assertEquals(1L, obj.getColumnLong());\n        assertEquals(1.23F, obj.getColumnFloat(), 0F);\n        assertEquals(1.23D, obj.getColumnDouble(), 0D);\n        assertEquals(true, obj.isColumnBoolean());\n        assertArrayEquals(new byte[]{1, 2, 3}, obj.getColumnBinary());\n        assertEquals(objectId, obj.getColumnObjectId());\n        assertEquals(decimal128, obj.getColumnDecimal128());\n        assertEquals(uuid, obj.getColumnUUID());\n        assertEquals(realmAny, obj.getColumnRealmAny());\n    }\n\n    @Test\n    public void createObjectFromJson_dateAsLong() throws JSONException {\n        JSONObject json = new JSONObject();\n        json.put(\"columnDate\", 1000L); // Realm operates at seconds level granularity.\n\n        realm.beginTransaction();\n        realm.createObjectFromJson(AllTypes.class, json);\n        realm.commitTransaction();\n\n        AllTypes obj = realm.where(AllTypes.class).findFirst();\n        assertEquals(new Date(1000), obj.getColumnDate());\n    }\n\n    @Test\n    public void createObjectFromJson_dateAsString() throws JSONException {\n        JSONObject json = new JSONObject();\n        json.put(\"columnDate\", \"/Date(1000)/\");\n\n        realm.beginTransaction();\n        realm.createObjectFromJson(AllTypes.class, json);\n        realm.commitTransaction();\n\n        AllTypes obj = realm.where(AllTypes.class).findFirst();\n        assertEquals(new Date(1000), obj.getColumnDate());\n    }\n\n    @Test\n    public void createObjectFromJson_decimal128() throws JSONException {\n        JSONObject json = new JSONObject();\n        json.put(\"columnDecimal128\", new Decimal128(BigDecimal.TEN));\n\n        realm.beginTransaction();\n        realm.createObjectFromJson(AllTypes.class, json);\n        realm.commitTransaction();\n\n        AllTypes obj = realm.where(AllTypes.class).findFirst();\n        assertEquals(new Decimal128(BigDecimal.TEN), obj.getColumnDecimal128());\n    }\n\n    @Test\n    public void createUsingJsonStream_decimal128() throws JSONException {\n        JSONObject json = new JSONObject();\n        json.put(\"columnDecimal128\", new Decimal128(BigDecimal.TEN));\n\n        realm.beginTransaction();\n        realm.createObjectFromJson(AllTypes.class, json);\n        realm.commitTransaction();\n\n        AllTypes obj = realm.where(AllTypes.class).findFirst();\n        assertEquals(new Decimal128(BigDecimal.TEN), obj.getColumnDecimal128());\n    }\n\n    @Test\n    public void createObjectFromJson_decimal128AsInt() throws JSONException {\n        JSONObject json = new JSONObject();\n        json.put(\"columnDecimal128\", -42);\n\n        realm.beginTransaction();\n        realm.createObjectFromJson(AllTypes.class, json);\n        realm.commitTransaction();\n\n        AllTypes obj = realm.where(AllTypes.class).findFirst();\n        assertEquals(new Decimal128(-42), obj.getColumnDecimal128());\n    }\n\n    @Test\n    public void createObjectFromJson_decimal128AsLong() throws JSONException {\n        JSONObject json = new JSONObject();\n        json.put(\"columnDecimal128\", -32361122672259149L);\n\n        realm.beginTransaction();\n        realm.createObjectFromJson(AllTypes.class, json);\n        realm.commitTransaction();\n\n        AllTypes obj = realm.where(AllTypes.class).findFirst();\n        assertEquals(new Decimal128(-32361122672259149L), obj.getColumnDecimal128());\n    }\n\n    @Test\n    public void createObjectFromJson_decimal128AsDouble() throws JSONException {\n        JSONObject json = new JSONObject();\n        json.put(\"columnDecimal128\", 0.30000001192092896D);\n\n        realm.beginTransaction();\n        realm.createObjectFromJson(AllTypes.class, json);\n        realm.commitTransaction();\n\n        AllTypes obj = realm.where(AllTypes.class).findFirst();\n        assertEquals(new Decimal128(new BigDecimal(0.30000001192092896D)), obj.getColumnDecimal128());\n    }\n\n    @Test\n    public void createObjectFromJson_decimal128AsString() throws JSONException {\n        JSONObject json = new JSONObject();\n        json.put(\"columnDecimal128\", \"32361122672259149\");\n\n        realm.beginTransaction();\n        realm.createObjectFromJson(AllTypes.class, json);\n        realm.commitTransaction();\n\n        AllTypes obj = realm.where(AllTypes.class).findFirst();\n        assertEquals(Decimal128.parse(\"32361122672259149\"), obj.getColumnDecimal128());\n    }\n\n    @Test\n    public void createObjectFromJson_objectId() throws JSONException {\n        JSONObject json = new JSONObject();\n        String idHex = TestHelper.generateObjectIdHexString(7);\n        json.put(\"columnObjectId\", new ObjectId(idHex));\n\n        realm.beginTransaction();\n        realm.createObjectFromJson(AllTypes.class, json);\n        realm.commitTransaction();\n\n        AllTypes obj = realm.where(AllTypes.class).findFirst();\n        assertEquals(new ObjectId(idHex), obj.getColumnObjectId());\n    }\n\n    @Test\n    public void createObjectFromJson_objectIdAsString() throws JSONException {\n        JSONObject json = new JSONObject();\n        String idHex = TestHelper.generateObjectIdHexString(7);\n        json.put(\"columnObjectId\", idHex);\n\n        realm.beginTransaction();\n        realm.createObjectFromJson(AllTypes.class, json);\n        realm.commitTransaction();\n\n        AllTypes obj = realm.where(AllTypes.class).findFirst();\n        assertEquals(new ObjectId(idHex), obj.getColumnObjectId());\n    }\n\n    @Test\n    public void createObjectFromJson_uuid() throws JSONException {\n        JSONObject json = new JSONObject();\n        String uuid = \"027ba5ca-aa12-4afa-9219-e20cc3018599\";\n\n        json.put(\"columnUUID\", UUID.fromString(uuid));\n\n        realm.beginTransaction();\n        realm.createObjectFromJson(AllTypes.class, json);\n        realm.commitTransaction();\n\n        AllTypes obj = realm.where(AllTypes.class).findFirst();\n        assertEquals(UUID.fromString(uuid), obj.getColumnUUID());\n    }\n\n    @Test\n    public void createObjectFromJson_uuidAsString() throws JSONException {\n        JSONObject json = new JSONObject();\n        String uuid = \"027ba5ca-aa12-4afa-9219-e20cc3018599\";\n        json.put(\"columnUUID\", uuid);\n\n        realm.beginTransaction();\n        realm.createObjectFromJson(AllTypes.class, json);\n        realm.commitTransaction();\n\n        AllTypes obj = realm.where(AllTypes.class).findFirst();\n        assertEquals(UUID.fromString(uuid), obj.getColumnUUID());\n    }\n\n    @Test\n    public void createObjectFromJson_realmAnyAsString() throws JSONException {\n        JSONObject json = new JSONObject();\n        String aString = \"027ba5ca-aa12-4afa-9219-e20cc3018599\";\n        json.put(\"columnRealmAny\", aString);\n\n        realm.beginTransaction();\n        realm.createObjectFromJson(AllTypes.class, json);\n        realm.commitTransaction();\n\n        AllTypes obj = realm.where(AllTypes.class).findFirst();\n        assertEquals(RealmAny.valueOf(aString), obj.getColumnRealmAny());\n    }\n\n    @Test\n    public void createObjectFromJson_realmAnyAsInteger() throws JSONException {\n        JSONObject json = new JSONObject();\n        int anInteger = 20;\n        json.put(\"columnRealmAny\", anInteger);\n\n        realm.beginTransaction();\n        realm.createObjectFromJson(AllTypes.class, json);\n        realm.commitTransaction();\n\n        AllTypes obj = realm.where(AllTypes.class).findFirst();\n        assertEquals(RealmAny.valueOf(anInteger), obj.getColumnRealmAny());\n    }\n\n    @Test\n    public void createObjectFromJson_realmAnyAsFloat() throws JSONException {\n        JSONObject json = new JSONObject();\n        float aFloat = 10.f;\n        json.put(\"columnRealmAny\", aFloat);\n\n        realm.beginTransaction();\n        realm.createObjectFromJson(AllTypes.class, json);\n        realm.commitTransaction();\n\n        AllTypes obj = realm.where(AllTypes.class).findFirst();\n        assertEquals(RealmAny.valueOf(Double.valueOf(aFloat)), obj.getColumnRealmAny());\n    }\n\n    @Test\n    public void createObjectFromJson_realmAnyAsDouble() throws JSONException {\n        JSONObject json = new JSONObject();\n        double aDouble = 20.;\n        json.put(\"columnRealmAny\", aDouble);\n\n        realm.beginTransaction();\n        realm.createObjectFromJson(AllTypes.class, json);\n        realm.commitTransaction();\n\n        AllTypes obj = realm.where(AllTypes.class).findFirst();\n        assertEquals(RealmAny.valueOf(aDouble), obj.getColumnRealmAny());\n    }\n\n    @Test\n    public void createObjectFromJson_realmAnyAsNull() throws JSONException {\n        JSONObject json = new JSONObject();\n        json.put(\"columnRealmAny\", null);\n\n        realm.beginTransaction();\n        realm.createObjectFromJson(AllTypes.class, json);\n        realm.commitTransaction();\n\n        AllTypes obj = realm.where(AllTypes.class).findFirst();\n        assertEquals(RealmAny.nullValue(), obj.getColumnRealmAny());\n        assertEquals(RealmAny.valueOf((Byte) null), obj.getColumnRealmAny());\n    }\n\n    @Test\n    public void createObjectFromJson_dateAsStringTimeZone() throws JSONException {\n        // Oct 03 2015 14:45.33\n        JSONObject json = new JSONObject();\n        json.put(\"columnDate\", \"/Date(1443854733376+0800)/\");\n\n        realm.beginTransaction();\n        realm.createObjectFromJson(AllTypes.class, json);\n        realm.commitTransaction();\n\n        AllTypes obj = realm.where(AllTypes.class).findFirst();\n        Calendar cal = GregorianCalendar.getInstance();\n        cal.setTimeZone(TimeZone.getTimeZone(\"Australia/West\"));\n        cal.set(2015, Calendar.OCTOBER, 03, 14, 45, 33);\n        cal.set(Calendar.MILLISECOND, 376);\n        Date convDate = obj.getColumnDate();\n\n        assertEquals(convDate.getTime(), cal.getTimeInMillis());\n    }\n\n    @Test\n    public void createObjectFromJson_childObject() throws JSONException {\n        JSONObject allTypesObject = new JSONObject();\n        JSONObject dogObject = new JSONObject();\n        dogObject.put(\"name\", \"Fido\");\n        allTypesObject.put(\"columnRealmObject\", dogObject);\n\n        realm.beginTransaction();\n        realm.createObjectFromJson(AllTypes.class, allTypesObject);\n        realm.commitTransaction();\n\n        AllTypes obj = realm.where(AllTypes.class).findFirst();\n        assertEquals(\"Fido\", obj.getColumnRealmObject().getName());\n    }\n\n    @Test\n    public void createObjectFromJson_childObjectList() throws JSONException {\n        JSONObject allTypesObject = new JSONObject();\n        JSONObject dog1 = new JSONObject(); dog1.put(\"name\", \"Fido-1\");\n        JSONObject dog2 = new JSONObject(); dog2.put(\"name\", \"Fido-2\");\n        JSONObject dog3 = new JSONObject(); dog3.put(\"name\", \"Fido-3\");\n        JSONArray dogList = new JSONArray();\n        dogList.put(dog1);\n        dogList.put(dog2);\n        dogList.put(dog3);\n        allTypesObject.put(\"columnRealmList\", dogList);\n\n        realm.beginTransaction();\n        realm.createObjectFromJson(AllTypes.class, allTypesObject);\n        realm.commitTransaction();\n\n        AllTypes obj = realm.where(AllTypes.class).findFirst();\n        assertEquals(3, obj.getColumnRealmList().size());\n        assertEquals(\"Fido-3\", obj.getColumnRealmList().get(2).getName());\n    }\n\n    @Test\n    public void createObjectFromJson_emptyChildObjectList() throws JSONException {\n        JSONObject allTypesObject = new JSONObject();\n        JSONArray dogList = new JSONArray();\n        allTypesObject.put(\"columnRealmList\", dogList);\n\n        realm.beginTransaction();\n        realm.createObjectFromJson(AllTypes.class, allTypesObject);\n        realm.commitTransaction();\n\n        AllTypes obj = realm.where(AllTypes.class).findFirst();\n        assertEquals(0, obj.getColumnRealmList().size());\n    }\n\n    @Test\n    public void createObjectFromJson_stringSimpleObject() {\n        realm.beginTransaction();\n        Dog dog = realm.createObjectFromJson(Dog.class, \"{ name: \\\"Foo\\\" }\");\n        realm.commitTransaction();\n\n        assertEquals(\"Foo\", dog.getName());\n        assertEquals(\"Foo\", realm.where(Dog.class).findFirst().getName());\n    }\n\n    @Test\n    public void createObjectFromJson_stringFaultyJsonThrows() {\n        realm.beginTransaction();\n        try {\n            realm.createObjectFromJson(Dog.class, \"{ name \\\"Foo\\\" }\");\n            fail(\"Faulty JSON should result in a RealmException\");\n        } catch (RealmException ignored) {\n        } finally {\n            realm.commitTransaction();\n        }\n    }\n\n    @Test\n    public void createObjectFromJson_stringNull() {\n        realm.beginTransaction();\n        Dog dog = realm.createObjectFromJson(Dog.class, (String) null);\n        realm.commitTransaction();\n\n        //noinspection ConstantConditions\n        assertNull(dog);\n        assertEquals(0, realm.where(Dog.class).count());\n    }\n\n    @Test\n    public void createAllFromJson_jsonArrayEmpty() {\n        JSONArray array = new JSONArray();\n        realm.beginTransaction();\n        realm.createAllFromJson(AllTypes.class, array);\n        realm.commitTransaction();\n\n        assertEquals(0, realm.where(AllTypes.class).count());\n    }\n\n    @Test\n    public void createAllFromJson_jsonArray() throws JSONException {\n        JSONObject dog1 = new JSONObject(); dog1.put(\"name\", \"Fido-1\");\n        JSONObject dog2 = new JSONObject(); dog2.put(\"name\", \"Fido-2\");\n        JSONObject dog3 = new JSONObject(); dog3.put(\"name\", \"Fido-3\");\n        JSONArray dogList = new JSONArray();\n        dogList.put(dog1);\n        dogList.put(dog2);\n        dogList.put(dog3);\n\n        realm.beginTransaction();\n        realm.createAllFromJson(Dog.class, dogList);\n        realm.commitTransaction();\n\n        assertEquals(3, realm.where(Dog.class).count());\n        assertEquals(1, realm.where(Dog.class).equalTo(\"name\", \"Fido-3\").findAll().size());\n    }\n\n    @Test\n    public void createFromJson_respectDefaultValues() throws JSONException {\n        final long fieldLongPrimaryKeyValue = DefaultValueOfField.FIELD_LONG_PRIMARY_KEY_DEFAULT_VALUE + 1;\n\n        // Step 1: Prepares almost empty JSON.\n        final JSONObject json = new JSONObject();\n        json.put(DefaultValueOfField.FIELD_LONG_PRIMARY_KEY, fieldLongPrimaryKeyValue);\n\n        // Step 2: Updates with almost empty JSONObject.\n        realm.beginTransaction();\n        final DefaultValueOfField managedObj = realm.createOrUpdateObjectFromJson(DefaultValueOfField.class, json);\n        realm.commitTransaction();\n\n        // Step 3: Checks that default values are applied.\n        assertEquals(DefaultValueOfField.FIELD_IGNORED_DEFAULT_VALUE,\n                managedObj.getFieldIgnored());\n        assertEquals(DefaultValueOfField.FIELD_STRING_DEFAULT_VALUE, managedObj.getFieldString());\n        assertFalse(Util.isEmptyString(managedObj.getFieldRandomString()));\n        assertEquals(DefaultValueOfField.FIELD_SHORT_DEFAULT_VALUE, managedObj.getFieldShort());\n        assertEquals(DefaultValueOfField.FIELD_INT_DEFAULT_VALUE, managedObj.getFieldInt());\n        assertEquals(fieldLongPrimaryKeyValue, managedObj.getFieldLongPrimaryKey());\n        assertEquals(DefaultValueOfField.FIELD_LONG_DEFAULT_VALUE, managedObj.getFieldLong());\n        assertEquals(DefaultValueOfField.FIELD_BYTE_DEFAULT_VALUE, managedObj.getFieldByte());\n        assertEquals(DefaultValueOfField.FIELD_FLOAT_DEFAULT_VALUE, managedObj.getFieldFloat(), 0f);\n        assertEquals(DefaultValueOfField.FIELD_DOUBLE_DEFAULT_VALUE, managedObj.getFieldDouble(), 0d);\n        assertEquals(DefaultValueOfField.FIELD_BOOLEAN_DEFAULT_VALUE, managedObj.isFieldBoolean());\n        assertEquals(DefaultValueOfField.FIELD_DATE_DEFAULT_VALUE, managedObj.getFieldDate());\n        assertEquals(DefaultValueOfField.FIELD_OBJECT_ID_DEFAULT_VALUE, managedObj.getFieldObjectId());\n        assertEquals(DefaultValueOfField.FIELD_DECIMAL128_DEFAULT_VALUE, managedObj.getFieldDecimal128());\n        assertEquals(DefaultValueOfField.FIELD_UUID_DEFAULT_VALUE, managedObj.getFieldUUID());\n        assertEquals(DefaultValueOfField.FIELD_REALM_ANY_DEFAULT_VALUE, managedObj.getFieldRealmAny());\n        assertArrayEquals(DefaultValueOfField.FIELD_BINARY_DEFAULT_VALUE, managedObj.getFieldBinary());\n        assertArrayEquals(DefaultValueOfField.FIELD_BYTE_LIST_DEFAULT_VALUE.toArray(), managedObj.getFieldByteList().toArray());\n        assertArrayEquals(DefaultValueOfField.FIELD_SHORT_LIST_DEFAULT_VALUE.toArray(), managedObj.getFieldShortList().toArray());\n        assertArrayEquals(DefaultValueOfField.FIELD_INTEGER_LIST_DEFAULT_VALUE.toArray(), managedObj.getFieldIntegerList().toArray());\n        assertArrayEquals(DefaultValueOfField.FIELD_LONG_LIST_DEFAULT_VALUE.toArray(), managedObj.getFieldLongList().toArray());\n        assertArrayEquals(DefaultValueOfField.FIELD_BOOLEAN_LIST_DEFAULT_VALUE.toArray(), managedObj.getFieldBooleanList().toArray());\n        assertArrayEquals(DefaultValueOfField.FIELD_BINARY_LIST_DEFAULT_VALUE.toArray(), managedObj.getFieldBinaryList().toArray());\n        assertArrayEquals(DefaultValueOfField.FIELD_STRING_LIST_DEFAULT_VALUE.toArray(), managedObj.getFieldStringList().toArray());\n        assertArrayEquals(DefaultValueOfField.FIELD_DATE_LIST_DEFAULT_VALUE.toArray(), managedObj.getFieldDateList().toArray());\n        assertArrayEquals(DefaultValueOfField.FIELD_OBJECT_ID_LIST_DEFAULT_VALUE.toArray(), managedObj.getFieldObjectIdList().toArray());\n        assertArrayEquals(DefaultValueOfField.FIELD_DECIMAL128_LIST_DEFAULT_VALUE.toArray(), managedObj.getFieldDecimal128List().toArray());\n        assertArrayEquals(DefaultValueOfField.FIELD_UUID_LIST_DEFAULT_VALUE.toArray(), managedObj.getFieldUUIDList().toArray());\n        assertArrayEquals(DefaultValueOfField.FIELD_REALM_ANY_LIST_DEFAULT_VALUE.toArray(), managedObj.getFieldRealmAnyList().toArray());\n        assertEquals(RandomPrimaryKey.FIELD_INT_DEFAULT_VALUE, managedObj.getFieldObject().getFieldInt());\n        assertEquals(1, managedObj.getFieldList().size());\n        assertEquals(RandomPrimaryKey.FIELD_INT_DEFAULT_VALUE, managedObj.getFieldList().first().getFieldInt());\n\n        // Makes sure that excess object by default value is not created.\n        assertEquals(2, realm.where(RandomPrimaryKey.class).count());\n    }\n\n    @Test\n    public void createFromJson_defaultValuesAreIgnored() throws JSONException {\n        final long fieldLongPrimaryKeyValue = DefaultValueOfField.FIELD_LONG_PRIMARY_KEY_DEFAULT_VALUE + 1;\n\n        // Step 1: Prepares JSON.\n        final String fieldIgnoredValue = DefaultValueOfField.FIELD_IGNORED_DEFAULT_VALUE + \".modified\";\n        final String fieldStringValue = DefaultValueOfField.FIELD_STRING_DEFAULT_VALUE + \".modified\";\n        final String fieldRandomStringValue = \"non-random\";\n        final short fieldShortValue = (short) (DefaultValueOfField.FIELD_SHORT_DEFAULT_VALUE + 1);\n        final int fieldIntValue = DefaultValueOfField.FIELD_INT_DEFAULT_VALUE + 1;\n        final long fieldLongValue = DefaultValueOfField.FIELD_LONG_DEFAULT_VALUE + 1;\n        final byte fieldByteValue = (byte) (DefaultValueOfField.FIELD_BYTE_DEFAULT_VALUE + 1);\n        final float fieldFloatValue = DefaultValueOfField.FIELD_FLOAT_DEFAULT_VALUE + 1;\n        final double fieldDoubleValue = DefaultValueOfField.FIELD_DOUBLE_DEFAULT_VALUE + 1;\n        final boolean fieldBooleanValue = !DefaultValueOfField.FIELD_BOOLEAN_DEFAULT_VALUE;\n        final Date fieldDateValue = new Date(DefaultValueOfField.FIELD_DATE_DEFAULT_VALUE.getTime() + 1);\n        final ObjectId fieldObjectIdValue = new ObjectId(new Date(20));\n        final Decimal128 fieldDecimal128Value = new Decimal128(20);\n        final UUID fieldUUIDValue = UUID.randomUUID();\n        final RealmAny fieldRealmAnyValue = RealmAny.valueOf((float) 20);\n        final byte[] fieldBinaryValue = {(byte) (DefaultValueOfField.FIELD_BINARY_DEFAULT_VALUE[0] - 1)};\n        final int fieldObjectIntValue = RandomPrimaryKey.FIELD_INT_DEFAULT_VALUE + 1;\n        final int fieldListIntValue = RandomPrimaryKey.FIELD_INT_DEFAULT_VALUE + 2;\n\n        final JSONObject json = new JSONObject();\n        json.put(DefaultValueOfField.FIELD_LONG_PRIMARY_KEY, fieldLongPrimaryKeyValue);\n        json.put(DefaultValueOfField.FIELD_IGNORED, fieldIgnoredValue);\n        json.put(DefaultValueOfField.FIELD_STRING, fieldStringValue);\n        json.put(DefaultValueOfField.FIELD_RANDOM_STRING, fieldRandomStringValue);\n        json.put(DefaultValueOfField.FIELD_SHORT, fieldShortValue);\n        json.put(DefaultValueOfField.FIELD_INT, fieldIntValue);\n        json.put(DefaultValueOfField.FIELD_LONG, fieldLongValue);\n        json.put(DefaultValueOfField.FIELD_BYTE, fieldByteValue);\n        json.put(DefaultValueOfField.FIELD_FLOAT, fieldFloatValue);\n        json.put(DefaultValueOfField.FIELD_DOUBLE, fieldDoubleValue);\n        json.put(DefaultValueOfField.FIELD_BOOLEAN, fieldBooleanValue);\n        json.put(DefaultValueOfField.FIELD_DATE, getISO8601Date(fieldDateValue));\n        json.put(DefaultValueOfField.FIELD_OBJECT_ID, fieldObjectIdValue);\n        json.put(DefaultValueOfField.FIELD_DECIMAL128, fieldDecimal128Value);\n        json.put(DefaultValueOfField.FIELD_UUID, fieldUUIDValue);\n        json.put(DefaultValueOfField.FIELD_REALM_ANY, fieldRealmAnyValue);\n        json.put(DefaultValueOfField.FIELD_BINARY, Base64.encodeToString(fieldBinaryValue, Base64.DEFAULT));\n        // Value for 'fieldObject'\n        final JSONObject fieldObjectJson = new JSONObject();\n        fieldObjectJson.put(RandomPrimaryKey.FIELD_RANDOM_PRIMARY_KEY, \"pk of fieldObject\");\n        fieldObjectJson.put(RandomPrimaryKey.FIELD_INT, fieldObjectIntValue);\n        json.put(DefaultValueOfField.FIELD_OBJECT, fieldObjectJson);\n        // Value for 'fieldList'\n        final JSONArray fieldListArrayJson = new JSONArray();\n        final JSONObject fieldListItem0Json = new JSONObject();\n        fieldListItem0Json.put(RandomPrimaryKey.FIELD_RANDOM_PRIMARY_KEY, \"pk1 of fieldList\");\n        fieldListItem0Json.put(RandomPrimaryKey.FIELD_INT, fieldListIntValue);\n        fieldListArrayJson.put(fieldListItem0Json);\n        final JSONObject fieldListItem1Json = new JSONObject();\n        fieldListItem1Json.put(RandomPrimaryKey.FIELD_RANDOM_PRIMARY_KEY, \"pk2 of fieldList\");\n        fieldListItem1Json.put(RandomPrimaryKey.FIELD_INT, fieldListIntValue + 1);\n        fieldListArrayJson.put(fieldListItem1Json);\n        json.put(DefaultValueOfField.FIELD_LIST, fieldListArrayJson);\n\n        // Step 3: Updates with JSONObject.\n        realm.beginTransaction();\n        final DefaultValueOfField managedObj = realm.createOrUpdateObjectFromJson(DefaultValueOfField.class, json);\n        realm.commitTransaction();\n\n        // Step 4: Checks that properly created.\n        assertEquals(DefaultValueOfField.FIELD_IGNORED_DEFAULT_VALUE /* not fieldIgnoredValue */,\n                managedObj.getFieldIgnored());\n        assertEquals(fieldStringValue, managedObj.getFieldString());\n        assertEquals(fieldRandomStringValue, managedObj.getFieldRandomString());\n        assertEquals(fieldShortValue, managedObj.getFieldShort());\n        assertEquals(fieldIntValue, managedObj.getFieldInt());\n        assertEquals(fieldLongPrimaryKeyValue, managedObj.getFieldLongPrimaryKey());\n        assertEquals(fieldLongValue, managedObj.getFieldLong());\n        assertEquals(fieldByteValue, managedObj.getFieldByte());\n        assertEquals(fieldFloatValue, managedObj.getFieldFloat(), 0f);\n        assertEquals(fieldDoubleValue, managedObj.getFieldDouble(), 0d);\n        assertEquals(fieldBooleanValue, managedObj.isFieldBoolean());\n        assertEquals(fieldObjectIdValue, managedObj.getFieldObjectId());\n        assertEquals(fieldDecimal128Value, managedObj.getFieldDecimal128());\n        assertEquals(fieldUUIDValue, managedObj.getFieldUUID());\n        assertEquals(fieldRealmAnyValue, managedObj.getFieldRealmAny());\n        assertEquals(fieldDateValue, managedObj.getFieldDate());\n        assertTrue(Arrays.equals(fieldBinaryValue, managedObj.getFieldBinary()));\n        assertEquals(fieldObjectJson.getString(RandomPrimaryKey.FIELD_RANDOM_PRIMARY_KEY),\n                managedObj.getFieldObject().getFieldRandomPrimaryKey());\n        assertEquals(fieldObjectIntValue, managedObj.getFieldObject().getFieldInt());\n        assertEquals(2, managedObj.getFieldList().size());\n        assertEquals(fieldListItem0Json.get(RandomPrimaryKey.FIELD_RANDOM_PRIMARY_KEY),\n                managedObj.getFieldList().get(0).getFieldRandomPrimaryKey());\n        assertEquals(fieldListIntValue, managedObj.getFieldList().get(0).getFieldInt());\n        assertEquals(fieldListItem1Json.get(RandomPrimaryKey.FIELD_RANDOM_PRIMARY_KEY),\n                managedObj.getFieldList().get(1).getFieldRandomPrimaryKey());\n        assertEquals(fieldListIntValue + 1, managedObj.getFieldList().get(1).getFieldInt());\n\n        // Makes sure that excess object by default value is not created.\n        assertEquals(3, realm.where(RandomPrimaryKey.class).count());\n    }\n\n    private String getISO8601Date(Date date) {\n        TimeZone tz = TimeZone.getTimeZone(\"UTC\");\n        DateFormat df = new SimpleDateFormat(\"yyyy-MM-dd'T'HH:mm:ss.SSS'Z'\"); // Quoted \"Z\" to indicate UTC, no timezone offset\n        df.setTimeZone(tz);\n        return df.format(date);\n    }\n\n    @Test\n    public void updateFromJson_defaultValuesAreIgnored() throws JSONException {\n        final long fieldLongPrimaryKeyValue = DefaultValueOfField.FIELD_LONG_PRIMARY_KEY_DEFAULT_VALUE + 1;\n\n        // Step 1: Creates an object with default values.\n        final DefaultValueOfField original;\n        realm.beginTransaction(); {\n            original = realm.createObject(DefaultValueOfField.class, fieldLongPrimaryKeyValue);\n        }\n        realm.commitTransaction();\n\n        // Step 2: Prepares JSON.\n        final String fieldIgnoredValue = DefaultValueOfField.FIELD_IGNORED_DEFAULT_VALUE + \".modified\";\n        final String fieldStringValue = DefaultValueOfField.FIELD_STRING_DEFAULT_VALUE + \".modified\";\n        final String fieldRandomStringValue = \"non-random\";\n        final short fieldShortValue = (short) (DefaultValueOfField.FIELD_SHORT_DEFAULT_VALUE + 1);\n        final int fieldIntValue = DefaultValueOfField.FIELD_INT_DEFAULT_VALUE + 1;\n        final long fieldLongValue = DefaultValueOfField.FIELD_LONG_DEFAULT_VALUE + 1;\n        final byte fieldByteValue = (byte) (DefaultValueOfField.FIELD_BYTE_DEFAULT_VALUE + 1);\n        final float fieldFloatValue = DefaultValueOfField.FIELD_FLOAT_DEFAULT_VALUE + 1;\n        final double fieldDoubleValue = DefaultValueOfField.FIELD_DOUBLE_DEFAULT_VALUE + 1;\n        final boolean fieldBooleanValue = !DefaultValueOfField.FIELD_BOOLEAN_DEFAULT_VALUE;\n        final Date fieldDateValue = new Date(DefaultValueOfField.FIELD_DATE_DEFAULT_VALUE.getTime() + 1);\n        final byte[] fieldBinaryValue = {(byte) (DefaultValueOfField.FIELD_BINARY_DEFAULT_VALUE[0] - 1)};\n        final int fieldObjectIntValue = RandomPrimaryKey.FIELD_INT_DEFAULT_VALUE + 1;\n        final int fieldListIntValue = RandomPrimaryKey.FIELD_INT_DEFAULT_VALUE + 2;\n\n        final JSONObject json = new JSONObject();\n        json.put(DefaultValueOfField.FIELD_LONG_PRIMARY_KEY, fieldLongPrimaryKeyValue);\n        json.put(DefaultValueOfField.FIELD_IGNORED, fieldIgnoredValue);\n        json.put(DefaultValueOfField.FIELD_STRING, fieldStringValue);\n        json.put(DefaultValueOfField.FIELD_RANDOM_STRING, fieldRandomStringValue);\n        json.put(DefaultValueOfField.FIELD_SHORT, fieldShortValue);\n        json.put(DefaultValueOfField.FIELD_INT, fieldIntValue);\n        json.put(DefaultValueOfField.FIELD_LONG, fieldLongValue);\n        json.put(DefaultValueOfField.FIELD_BYTE, fieldByteValue);\n        json.put(DefaultValueOfField.FIELD_FLOAT, fieldFloatValue);\n        json.put(DefaultValueOfField.FIELD_DOUBLE, fieldDoubleValue);\n        json.put(DefaultValueOfField.FIELD_BOOLEAN, fieldBooleanValue);\n        json.put(DefaultValueOfField.FIELD_DATE, getISO8601Date(fieldDateValue));\n        json.put(DefaultValueOfField.FIELD_BINARY, Base64.encodeToString(fieldBinaryValue, Base64.DEFAULT));\n        // value for 'fieldObject'\n        final JSONObject fieldObjectJson = new JSONObject();\n        fieldObjectJson.put(RandomPrimaryKey.FIELD_RANDOM_PRIMARY_KEY,\n                original.getFieldObject().getFieldRandomPrimaryKey());\n        fieldObjectJson.put(RandomPrimaryKey.FIELD_INT, fieldObjectIntValue);\n        json.put(DefaultValueOfField.FIELD_OBJECT, fieldObjectJson);\n        // Value for 'fieldList'\n        final JSONArray fieldListArrayJson = new JSONArray();\n        final JSONObject fieldListItem0Json = new JSONObject(); // To be added.\n        fieldListItem0Json.put(RandomPrimaryKey.FIELD_RANDOM_PRIMARY_KEY,  \"unique value\");\n        fieldListItem0Json.put(RandomPrimaryKey.FIELD_INT, fieldListIntValue);\n        fieldListArrayJson.put(fieldListItem0Json);\n        final JSONObject fieldListItem1Json = new JSONObject(); // To be updated.\n        fieldListItem1Json.put(RandomPrimaryKey.FIELD_RANDOM_PRIMARY_KEY,\n                original.getFieldList().first().getFieldRandomPrimaryKey());\n        fieldListItem1Json.put(RandomPrimaryKey.FIELD_INT, fieldListIntValue + 1);\n        fieldListArrayJson.put(fieldListItem1Json);\n        json.put(DefaultValueOfField.FIELD_LIST, fieldListArrayJson);\n\n        // Step 3: Updates with JSONObject.\n        realm.beginTransaction();\n        final DefaultValueOfField managedObj = realm.createOrUpdateObjectFromJson(DefaultValueOfField.class, json);\n        realm.commitTransaction();\n\n        // Step 4: Checks that properly updated.\n        assertEquals(DefaultValueOfField.FIELD_IGNORED_DEFAULT_VALUE /* not fieldIgnoredValue */,\n                managedObj.getFieldIgnored());\n        assertEquals(fieldStringValue, managedObj.getFieldString());\n        assertEquals(fieldRandomStringValue, managedObj.getFieldRandomString());\n        assertEquals(fieldShortValue, managedObj.getFieldShort());\n        assertEquals(fieldIntValue, managedObj.getFieldInt());\n        assertEquals(fieldLongPrimaryKeyValue, managedObj.getFieldLongPrimaryKey());\n        assertEquals(fieldLongValue, managedObj.getFieldLong());\n        assertEquals(fieldByteValue, managedObj.getFieldByte());\n        assertEquals(fieldFloatValue, managedObj.getFieldFloat(), 0f);\n        assertEquals(fieldDoubleValue, managedObj.getFieldDouble(), 0d);\n        assertEquals(fieldBooleanValue, managedObj.isFieldBoolean());\n        assertEquals(fieldDateValue, managedObj.getFieldDate());\n        assertTrue(Arrays.equals(fieldBinaryValue, managedObj.getFieldBinary()));\n        assertEquals(fieldObjectIntValue, managedObj.getFieldObject().getFieldInt());\n        assertEquals(2, managedObj.getFieldList().size());\n        assertEquals(\"unique value\", managedObj.getFieldList().get(0).getFieldRandomPrimaryKey());\n        assertEquals(fieldListIntValue, managedObj.getFieldList().get(0).getFieldInt());\n        assertEquals(fieldListItem1Json.get(RandomPrimaryKey.FIELD_RANDOM_PRIMARY_KEY),\n                managedObj.getFieldList().get(1).getFieldRandomPrimaryKey());\n        assertEquals(fieldListIntValue + 1, managedObj.getFieldList().get(1).getFieldInt());\n\n        // Makes sure that excess object by default value is not created.\n        assertEquals(3/* 2 updated + 1 added*/, realm.where(RandomPrimaryKey.class).count());\n    }\n\n    // Tests if Json object doesn't have the field, then the field should have default value.\n    @Test\n    public void createObjectFromJson_noValues() throws JSONException {\n        JSONObject json = new JSONObject();\n        json.put(\"noThingHere\", JSONObject.NULL);\n\n        realm.beginTransaction();\n        realm.createObjectFromJson(AllTypes.class, json);\n        realm.commitTransaction();\n\n        // Checks that all primitive types are imported correctly.\n        AllTypes obj = realm.where(AllTypes.class).findFirst();\n        assertEquals(\"\", obj.getColumnString());\n        assertEquals(0L, obj.getColumnLong());\n        assertEquals(0F, obj.getColumnFloat(), 0F);\n        assertEquals(0D, obj.getColumnDouble(), 0D);\n        assertEquals(false, obj.isColumnBoolean());\n        assertEquals(new Date(0), obj.getColumnDate());\n        assertArrayEquals(new byte[0], obj.getColumnBinary());\n        assertNull(obj.getColumnRealmObject());\n        assertEquals(0, obj.getColumnRealmList().size());\n    }\n\n    // Tests that given an exception everything up to the exception is saved.\n    @Test\n    public void createObjectFromJson_jsonException() throws JSONException {\n        JSONObject json = new JSONObject();\n        json.put(\"columnString\", \"Foo\");\n        json.put(\"columnDate\", \"Boom\");\n\n        realm.beginTransaction();\n        try {\n            realm.createObjectFromJson(AllTypes.class, json);\n            fail();\n        } catch (RealmException ignored) {\n        } finally {\n            realm.commitTransaction();\n        }\n\n        AllTypes obj = realm.where(AllTypes.class).findFirst();\n        assertEquals(\"Foo\", obj.getColumnString());\n        assertEquals(new Date(0), obj.getColumnDate());\n    }\n\n    @Test\n    public void createObjectFromJson_respectIgnoredFields() throws JSONException {\n        JSONObject json = new JSONObject();\n        json.put(\"id\", 0);\n        json.put(\"indexString\", \"Foo\");\n        json.put(\"notIndexString\", \"Bar\");\n        json.put(\"ignoreString\", \"Baz\");\n\n        realm.beginTransaction();\n        realm.createObjectFromJson(AnnotationTypes.class, json);\n        realm.commitTransaction();\n\n        AnnotationTypes annotationsObject = realm.where(AnnotationTypes.class).findFirst();\n        assertEquals(\"Foo\", annotationsObject.getIndexString());\n        assertEquals(null, annotationsObject.getIgnoreString());\n    }\n\n    @Test\n    public void createAllFromJson_stringArraySimpleArray() {\n        realm.beginTransaction();\n        realm.createAllFromJson(Dog.class, \"[{ name: \\\"Foo\\\" }, { name: \\\"Bar\\\" }]\");\n        realm.commitTransaction();\n\n        assertEquals(2, realm.where(Dog.class).count());\n    }\n\n    @Test\n    public void createAllFromJson_stringArrayFaultyJsonThrows() {\n        realm.beginTransaction();\n        try {\n            realm.createAllFromJson(Dog.class, \"[{ name : \\\"Foo\\\" ]\");\n            fail(\"Faulty JSON should result in a RealmException\");\n        } catch (RealmException ignored) {\n        } finally {\n            realm.commitTransaction();\n        }\n    }\n\n    @Test\n    public void createAllFromJson_stringArrayNull() {\n        realm.beginTransaction();\n        realm.createAllFromJson(Dog.class, (String) null);\n        realm.commitTransaction();\n\n        assertEquals(0, realm.where(Dog.class).count());\n    }\n\n    @Test\n    public void createAllFromJson_stringEmptyArray() {\n        realm.beginTransaction();\n        realm.createAllFromJson(Dog.class, \"\");\n        realm.commitTransaction();\n        assertEquals(0, realm.where(Dog.class).count());\n    }\n\n    @Test\n    public void createAllFromJson_stringNullClass() {\n        realm.beginTransaction();\n        realm.createAllFromJson(null, \"[{ name: \\\"Foo\\\" }]\");\n        realm.commitTransaction();\n\n        assertEquals(0, realm.where(Dog.class).count());\n    }\n\n\n    @Test\n    public void createAllFromJson_streamNull() throws IOException {\n        assumeThat(Build.VERSION.SDK_INT, greaterThanOrEqualTo(Build.VERSION_CODES.HONEYCOMB));\n\n        realm.createAllFromJson(AllTypes.class, (InputStream) null);\n        assertEquals(0, realm.where(AllTypes.class).count());\n    }\n\n    @Test\n    public void createObjectFromJson_streamAllSimpleTypes() throws IOException {\n        assumeThat(Build.VERSION.SDK_INT, greaterThanOrEqualTo(Build.VERSION_CODES.HONEYCOMB));\n\n        InputStream in = TestHelper.loadJsonFromAssets(context, \"all_simple_types.json\");\n        realm.beginTransaction();\n        realm.createObjectFromJson(AllTypes.class, in);\n        realm.commitTransaction();\n        in.close();\n\n        // Checks that all primitive types are imported correctly.\n        AllTypes obj = realm.where(AllTypes.class).findFirst();\n        assertEquals(\"String\", obj.getColumnString());\n        assertEquals(1L, obj.getColumnLong());\n        assertEquals(1.23F, obj.getColumnFloat(), 0F);\n        assertEquals(1.23D, obj.getColumnDouble(), 0D);\n        assertEquals(true, obj.isColumnBoolean());\n        assertArrayEquals(new byte[]{1, 2, 3}, obj.getColumnBinary());\n    }\n\n    @Test\n    public void createObjectFromJson_streamDateAsLong() throws IOException {\n        assumeThat(Build.VERSION.SDK_INT, greaterThanOrEqualTo(Build.VERSION_CODES.HONEYCOMB));\n\n        InputStream in = TestHelper.loadJsonFromAssets(context, \"date_as_long.json\");\n        realm.beginTransaction();\n        realm.createObjectFromJson(AllTypes.class, in);\n        realm.commitTransaction();\n        in.close();\n\n        // Checks that all primitive types are imported correctly.\n        AllTypes obj = realm.where(AllTypes.class).findFirst();\n        assertEquals(new Date(1000), obj.getColumnDate());\n    }\n\n    @Test\n    public void createObjectFromJson_streamDecimal128AsInt() throws IOException {\n        assumeThat(Build.VERSION.SDK_INT, greaterThanOrEqualTo(Build.VERSION_CODES.HONEYCOMB));\n\n        InputStream in = TestHelper.loadJsonFromAssets(context, \"decimal128_as_int.json\");\n        realm.beginTransaction();\n        realm.createObjectFromJson(AllTypes.class, in);\n        realm.commitTransaction();\n        in.close();\n\n        AllTypes obj = realm.where(AllTypes.class).findFirst();\n        assertEquals(new Decimal128(-42), obj.getColumnDecimal128());\n    }\n\n    @Test\n    public void createObjectFromJson_streamDecimal128AsLong() throws IOException {\n        assumeThat(Build.VERSION.SDK_INT, greaterThanOrEqualTo(Build.VERSION_CODES.HONEYCOMB));\n\n        InputStream in = TestHelper.loadJsonFromAssets(context, \"decimal128_as_long.json\");\n        realm.beginTransaction();\n        realm.createObjectFromJson(AllTypes.class, in);\n        realm.commitTransaction();\n        in.close();\n\n        AllTypes obj = realm.where(AllTypes.class).findFirst();\n        assertEquals(new Decimal128(-32361122672259149L), obj.getColumnDecimal128());\n    }\n\n    @Test\n    public void createObjectFromJson_streamDecimal128AsDouble() throws IOException {\n        assumeThat(Build.VERSION.SDK_INT, greaterThanOrEqualTo(Build.VERSION_CODES.HONEYCOMB));\n\n        InputStream in = TestHelper.loadJsonFromAssets(context, \"decimal128_as_double.json\");\n        realm.beginTransaction();\n        realm.createObjectFromJson(AllTypes.class, in);\n        realm.commitTransaction();\n        in.close();\n\n        AllTypes obj = realm.where(AllTypes.class).findFirst();\n        assertEquals(Decimal128.parse(\"0.30000001192092896\"), obj.getColumnDecimal128());\n    }\n\n    @Test\n    public void createObjectFromJson_streamDecimal128AsString() throws IOException {\n        assumeThat(Build.VERSION.SDK_INT, greaterThanOrEqualTo(Build.VERSION_CODES.HONEYCOMB));\n\n        InputStream in = TestHelper.loadJsonFromAssets(context, \"decimal128_as_string.json\");\n        realm.beginTransaction();\n        realm.createObjectFromJson(AllTypes.class, in);\n        realm.commitTransaction();\n        in.close();\n\n        AllTypes obj = realm.where(AllTypes.class).findFirst();\n        assertEquals(Decimal128.parse(\"32361122672259149\"), obj.getColumnDecimal128());\n    }\n\n    @Test\n    public void createObjectFromJson_streamObjectIdAsString() throws IOException {\n        assumeThat(Build.VERSION.SDK_INT, greaterThanOrEqualTo(Build.VERSION_CODES.HONEYCOMB));\n\n        InputStream in = TestHelper.loadJsonFromAssets(context, \"objectid_as_string.json\");\n        realm.beginTransaction();\n        realm.createObjectFromJson(AllTypes.class, in);\n        realm.commitTransaction();\n        in.close();\n\n        AllTypes obj = realm.where(AllTypes.class).findFirst();\n        assertEquals(new ObjectId(\"789ABCDEF0123456789ABCDE\"), obj.getColumnObjectId());\n    }\n\n    @Test\n    public void createObjectFromJson_streamUUIDAsString() throws IOException {\n        assumeThat(Build.VERSION.SDK_INT, greaterThanOrEqualTo(Build.VERSION_CODES.HONEYCOMB));\n\n        InputStream in = TestHelper.loadJsonFromAssets(context, \"uuid_as_string.json\");\n        realm.beginTransaction();\n        realm.createObjectFromJson(AllTypes.class, in);\n        realm.commitTransaction();\n        in.close();\n\n        AllTypes obj = realm.where(AllTypes.class).findFirst();\n        assertEquals(UUID.fromString(\"027ba5ca-aa12-4afa-9219-e20cc3018599\"), obj.getColumnUUID());\n    }\n\n    @Test\n    public void createObjectFromJson_streamRealmAnyAsString() throws IOException {\n        assumeThat(Build.VERSION.SDK_INT, greaterThanOrEqualTo(Build.VERSION_CODES.HONEYCOMB));\n\n        InputStream in = new ByteArrayInputStream(\"{\\\"columnRealmAny\\\" : \\\"hello world\\\"}\".getBytes(StandardCharsets.US_ASCII));\n\n        realm.beginTransaction();\n        realm.createObjectFromJson(AllTypes.class, in);\n        realm.commitTransaction();\n        in.close();\n\n        AllTypes obj = realm.where(AllTypes.class).findFirst();\n        assertEquals(RealmAny.valueOf(\"hello world\"), obj.getColumnRealmAny());\n    }\n\n    @Test\n    public void createObjectFromJson_streamRealmAnyAsInteger() throws IOException {\n        assumeThat(Build.VERSION.SDK_INT, greaterThanOrEqualTo(Build.VERSION_CODES.HONEYCOMB));\n\n        InputStream in = new ByteArrayInputStream(\"{\\\"columnRealmAny\\\" : 10}\".getBytes(StandardCharsets.US_ASCII));\n\n        realm.beginTransaction();\n        realm.createObjectFromJson(AllTypes.class, in);\n        realm.commitTransaction();\n        in.close();\n\n        AllTypes obj = realm.where(AllTypes.class).findFirst();\n        assertEquals(RealmAny.valueOf(10), obj.getColumnRealmAny());\n    }\n\n    @Test\n    public void createObjectFromJson_streamRealmAnyAsDouble() throws IOException {\n        assumeThat(Build.VERSION.SDK_INT, greaterThanOrEqualTo(Build.VERSION_CODES.HONEYCOMB));\n\n        InputStream in = new ByteArrayInputStream(\"{\\\"columnRealmAny\\\" : 10.0}\".getBytes(StandardCharsets.US_ASCII));\n\n        realm.beginTransaction();\n        realm.createObjectFromJson(AllTypes.class, in);\n        realm.commitTransaction();\n        in.close();\n\n        AllTypes obj = realm.where(AllTypes.class).findFirst();\n        assertEquals(RealmAny.valueOf(10.d), obj.getColumnRealmAny());\n    }\n\n    @Test\n    public void createObjectFromJson_streamRealmAnyAsNull() throws IOException {\n        assumeThat(Build.VERSION.SDK_INT, greaterThanOrEqualTo(Build.VERSION_CODES.HONEYCOMB));\n\n        InputStream in = new ByteArrayInputStream(\"{\\\"columnRealmAny\\\" : null}\".getBytes(StandardCharsets.US_ASCII));\n\n        realm.beginTransaction();\n        realm.createObjectFromJson(AllTypes.class, in);\n        realm.commitTransaction();\n        in.close();\n\n        AllTypes obj = realm.where(AllTypes.class).findFirst();\n        assertEquals(RealmAny.nullValue(), obj.getColumnRealmAny());\n    }\n\n    @Test\n    public void createObjectFromJson_streamDateAsString() throws IOException {\n        assumeThat(Build.VERSION.SDK_INT, greaterThanOrEqualTo(Build.VERSION_CODES.HONEYCOMB));\n\n        InputStream in = TestHelper.loadJsonFromAssets(context, \"date_as_string.json\");\n        realm.beginTransaction();\n        realm.createObjectFromJson(AllTypes.class, in);\n        realm.commitTransaction();\n        in.close();\n\n        // Checks that all primitive types are imported correctly.\n        AllTypes obj = realm.where(AllTypes.class).findFirst();\n        assertEquals(new Date(1000), obj.getColumnDate());\n    }\n\n    @Test\n    public void createObjectFromJson_streamDateAsISO8601String() throws IOException {\n        assumeThat(Build.VERSION.SDK_INT, greaterThanOrEqualTo(Build.VERSION_CODES.HONEYCOMB));\n\n        InputStream in = TestHelper.loadJsonFromAssets(context, \"date_as_iso8601_string.json\");\n        realm.beginTransaction();\n        realm.createObjectFromJson(AllTypes.class, in);\n        realm.commitTransaction();\n        in.close();\n\n        Calendar cal = new GregorianCalendar(2007, 8 - 1, 13, 19, 51, 23);\n        cal.setTimeZone(TimeZone.getTimeZone(\"GMT\"));\n        cal.set(Calendar.MILLISECOND, 789);\n        Date date = cal.getTime();\n\n        // Checks that all primitive types are imported correctly.\n        AllTypes obj = realm.where(AllTypes.class).findFirst();\n        assertEquals(date, obj.getColumnDate());\n    }\n\n    @Test\n    public void createObjectFromJson_streamChildObject() throws IOException {\n        assumeThat(Build.VERSION.SDK_INT, greaterThanOrEqualTo(Build.VERSION_CODES.HONEYCOMB));\n\n        InputStream in = TestHelper.loadJsonFromAssets(context, \"single_child_object.json\");\n        realm.beginTransaction();\n        realm.createObjectFromJson(AllTypes.class, in);\n        realm.commitTransaction();\n        in.close();\n\n        AllTypes obj = realm.where(AllTypes.class).findFirst();\n        assertEquals(\"Fido\", obj.getColumnRealmObject().getName());\n    }\n\n    @Test\n    public void createObjectFromJson_streamEmptyChildObjectList() throws IOException {\n        assumeThat(Build.VERSION.SDK_INT, greaterThanOrEqualTo(Build.VERSION_CODES.HONEYCOMB));\n\n        InputStream in = TestHelper.loadJsonFromAssets(context, \"realmlist_empty.json\");\n        realm.beginTransaction();\n        realm.createObjectFromJson(AllTypes.class, in);\n        realm.commitTransaction();\n        in.close();\n\n        AllTypes obj = realm.where(AllTypes.class).findFirst();\n        assertEquals(0, obj.getColumnRealmList().size());\n    }\n\n    @Test\n    public void createObjectFromJson_streamChildObjectList() throws IOException {\n        assumeThat(Build.VERSION.SDK_INT, greaterThanOrEqualTo(Build.VERSION_CODES.HONEYCOMB));\n\n        InputStream in = TestHelper.loadJsonFromAssets(context, \"realmlist.json\");\n        realm.beginTransaction();\n        realm.createObjectFromJson(AllTypes.class, in);\n        realm.commitTransaction();\n        in.close();\n\n        assertEquals(3, realm.where(Dog.class).count());\n        assertEquals(1, realm.where(Dog.class).equalTo(\"name\", \"Fido-3\").findAll().size());\n    }\n\n    @Test\n    public void createAllFromJson_streamArray() throws IOException {\n        assumeThat(Build.VERSION.SDK_INT, greaterThanOrEqualTo(Build.VERSION_CODES.HONEYCOMB));\n\n        InputStream in = TestHelper.loadJsonFromAssets(context, \"array.json\");\n        realm.beginTransaction();\n        realm.createAllFromJson(Dog.class, in);\n        realm.commitTransaction();\n\n        assertEquals(3, realm.where(Dog.class).count());\n        assertEquals(1, realm.where(Dog.class).equalTo(\"name\", \"Fido-3\").findAll().size());\n    }\n\n\n    // Tests if Json object doesn't have the field, then the field should have default value. Stream version.\n    @Test\n    public void createObjectFromJson_streamNoValues() throws IOException {\n        assumeThat(Build.VERSION.SDK_INT, greaterThanOrEqualTo(Build.VERSION_CODES.HONEYCOMB));\n\n        InputStream in = TestHelper.loadJsonFromAssets(context, \"other_json_object.json\");\n        realm.beginTransaction();\n        realm.createObjectFromJson(AllTypes.class, in);\n        realm.commitTransaction();\n        in.close();\n\n        // Checks that all primitive types are imported correctly.\n        AllTypes obj = realm.where(AllTypes.class).findFirst();\n        assertEquals(\"\", obj.getColumnString());\n        assertEquals(0L, obj.getColumnLong());\n        assertEquals(0F, obj.getColumnFloat(), 0F);\n        assertEquals(0D, obj.getColumnDouble(), 0D);\n        assertEquals(false, obj.isColumnBoolean());\n        assertEquals(new Date(0), obj.getColumnDate());\n        assertArrayEquals(new byte[0], obj.getColumnBinary());\n        assertNull(obj.getColumnRealmObject());\n        assertEquals(0, obj.getColumnRealmList().size());\n    }\n\n    @Test\n    public void createObjectFromJson_streamNullClass() throws IOException {\n        assumeThat(Build.VERSION.SDK_INT, greaterThanOrEqualTo(Build.VERSION_CODES.HONEYCOMB));\n\n        InputStream in = TestHelper.loadJsonFromAssets(context, \"array.json\");\n        realm.beginTransaction();\n        assertNull(realm.createObjectFromJson(null, in));\n        realm.commitTransaction();\n        in.close();\n    }\n\n    @Test\n    public void createObjectFromJson_streamNullJson() throws IOException {\n        assumeThat(Build.VERSION.SDK_INT, greaterThanOrEqualTo(Build.VERSION_CODES.HONEYCOMB));\n\n        InputStream in = TestHelper.loadJsonFromAssets(context, \"all_types_invalid.json\");\n        realm.beginTransaction();\n        try {\n            realm.createObjectFromJson(AnnotationTypes.class, in);\n            fail();\n        } catch (RealmException ignored) {\n        } finally {\n            realm.commitTransaction();\n            in.close();\n        }\n    }\n\n    @Test\n    public void createObjectFromJson_streamNullInputStream() throws IOException {\n        assumeThat(Build.VERSION.SDK_INT, greaterThanOrEqualTo(Build.VERSION_CODES.HONEYCOMB));\n\n        realm.beginTransaction();\n        assertNull(realm.createObjectFromJson(AnnotationTypes.class, (InputStream) null));\n        realm.commitTransaction();\n    }\n\n    /**\n     * Tests updating a existing object with JSON stream. Only primary key in JSON.\n     * No value should be changed.\n     */\n    @Test\n    public void createOrUpdateObjectFromJson_streamNullValues() throws IOException {\n        assumeThat(Build.VERSION.SDK_INT, greaterThanOrEqualTo(Build.VERSION_CODES.HONEYCOMB));\n\n        AllTypesPrimaryKey obj = new AllTypesPrimaryKey();\n        Date date = new Date(0);\n\n        ObjectId objectId = new ObjectId(new Date(20));\n        Decimal128 decimal128 = new Decimal128(300);\n        UUID uuid = UUID.randomUUID();\n        RealmAny realmAny = RealmAny.valueOf(\"Hello world\");\n\n        obj.setColumnLong(1); // ID\n        obj.setColumnBinary(new byte[]{1});\n        obj.setColumnBoolean(true);\n        obj.setColumnDate(date);\n        obj.setColumnDouble(1);\n        obj.setColumnFloat(1);\n        obj.setColumnString(\"1\");\n        obj.setColumnObjectId(objectId);\n        obj.setColumnDecimal128(decimal128);\n        obj.setColumnUUID(uuid);\n        obj.setColumnRealmAny(realmAny);\n\n        realm.beginTransaction();\n        realm.copyToRealm(obj);\n        realm.commitTransaction();\n\n        InputStream in = TestHelper.loadJsonFromAssets(context, \"all_types_primary_key_field_only.json\");\n        realm.beginTransaction();\n        realm.createOrUpdateObjectFromJson(AllTypesPrimaryKey.class, in);\n        realm.commitTransaction();\n        in.close();\n\n        // Checks that all primitive types are imported correctly.\n        obj = realm.where(AllTypesPrimaryKey.class).findFirst();\n        assertEquals(\"1\", obj.getColumnString());\n        assertEquals(1L, obj.getColumnLong());\n        assertEquals(1F, obj.getColumnFloat(), 0F);\n        assertEquals(1D, obj.getColumnDouble(), 0D);\n        assertEquals(true, obj.isColumnBoolean());\n        assertEquals(date, obj.getColumnDate());\n        assertEquals(objectId, obj.getColumnObjectId());\n        assertEquals(decimal128, obj.getColumnDecimal128());\n        assertEquals(uuid, obj.getColumnUUID());\n        assertEquals(realmAny, obj.getColumnRealmAny());\n        assertArrayEquals(new byte[]{1}, obj.getColumnBinary());\n        assertNull(obj.getColumnRealmObject());\n        assertEquals(0, obj.getColumnRealmList().size());\n    }\n\n    @Test\n    public void createOrUpdateObjectFromJson_streamNullClass() throws IOException {\n        assumeThat(Build.VERSION.SDK_INT, greaterThanOrEqualTo(Build.VERSION_CODES.HONEYCOMB));\n\n        InputStream in = TestHelper.loadJsonFromAssets(context, \"all_types_primary_key_field_only.json\");\n        realm.beginTransaction();\n        assertNull(realm.createOrUpdateObjectFromJson(null, in));\n        realm.commitTransaction();\n        in.close();\n    }\n\n    @Test\n    public void createOrUpdateObjectFromJson_streamInvalidJson() throws IOException {\n        assumeThat(Build.VERSION.SDK_INT, greaterThanOrEqualTo(Build.VERSION_CODES.HONEYCOMB));\n\n        AllTypesPrimaryKey obj = new AllTypesPrimaryKey();\n        obj.setColumnLong(1);\n        realm.beginTransaction();\n        realm.copyToRealm(obj);\n        realm.commitTransaction();\n\n        InputStream in = TestHelper.loadJsonFromAssets(context, \"all_types_invalid.json\");\n        realm.beginTransaction();\n        try {\n            realm.createOrUpdateObjectFromJson(AllTypesPrimaryKey.class, in);\n            fail();\n        } catch (RealmException ignored) {\n        } finally {\n            realm.commitTransaction();\n            in.close();\n        }\n    }\n\n    @Test\n    public void createOrUpdateObjectFromJson_streamNoPrimaryKeyThrows() throws IOException {\n        assumeThat(Build.VERSION.SDK_INT, greaterThanOrEqualTo(Build.VERSION_CODES.HONEYCOMB));\n\n        try {\n            realm.createOrUpdateObjectFromJson(AllTypes.class, new TestHelper.StubInputStream());\n            fail();\n        } catch (IllegalArgumentException ignored) {\n        }\n    }\n\n    @Test\n    public void createOrUpdateAllFromJson_streamInvalidJSonCurlyBracketThrows() throws IOException {\n        assumeThat(Build.VERSION.SDK_INT, greaterThanOrEqualTo(Build.VERSION_CODES.HONEYCOMB));\n\n        try {\n            realm.createOrUpdateAllFromJson(AllTypesPrimaryKey.class, TestHelper.stringToStream(\"{\"));\n            fail();\n        } catch (RealmException ignored) {\n        }\n    }\n\n    @Test\n    public void createOrUpdateObjectFromJson_streamIgnoreUnsetProperties() throws IOException {\n        assumeThat(Build.VERSION.SDK_INT, greaterThanOrEqualTo(Build.VERSION_CODES.HONEYCOMB));\n\n        realm.beginTransaction();\n        realm.createOrUpdateAllFromJson(AllTypesPrimaryKey.class, TestHelper.loadJsonFromAssets(context, \"list_alltypes_primarykey.json\"));\n        realm.commitTransaction();\n\n        // No-op as no properties should be updated.\n        realm.beginTransaction();\n        realm.createOrUpdateObjectFromJson(AllTypesPrimaryKey.class, TestHelper.stringToStream(\"{ \\\"columnLong\\\":1 }\"));\n        realm.commitTransaction();\n\n        assertAllTypesPrimaryKeyUpdated();\n    }\n\n    @Test\n    public void createOrUpdateObjectFromJson_inputStream() throws IOException {\n        assumeThat(Build.VERSION.SDK_INT, greaterThanOrEqualTo(Build.VERSION_CODES.HONEYCOMB));\n\n        realm.beginTransaction();\n\n        AllTypesPrimaryKey obj = new AllTypesPrimaryKey();\n        obj.setColumnLong(1);\n        obj.setColumnString(\"Foo\");\n        realm.copyToRealm(obj);\n\n        InputStream in = TestHelper.stringToStream(\"{ \\\"columnLong\\\" : 1, \\\"columnString\\\" : \\\"bar\\\" }\");\n        AllTypesPrimaryKey newObj = realm.createOrUpdateObjectFromJson(AllTypesPrimaryKey.class, in);\n        realm.commitTransaction();\n\n        assertEquals(1, realm.where(AllTypesPrimaryKey.class).count());\n        assertEquals(\"bar\", newObj.getColumnString());\n    }\n\n    /**\n     * Checks that using createOrUpdateObject will set the primary key directly instead of first setting\n     * it to the default value (which can fail).\n     */\n    @Test\n    public void createOrUpdateObjectFromJson_objectWithPrimaryKeySetValueDirectlyFromStream() throws JSONException, IOException {\n        assumeThat(Build.VERSION.SDK_INT, greaterThanOrEqualTo(Build.VERSION_CODES.HONEYCOMB));\n\n        InputStream stream = TestHelper.stringToStream(\"{\\\"id\\\": 1, \\\"name\\\": \\\"bar\\\"}\");\n        realm.beginTransaction();\n        realm.createObject(OwnerPrimaryKey.class, 0); // id = 0\n        realm.createOrUpdateObjectFromJson(OwnerPrimaryKey.class, stream);\n        realm.commitTransaction();\n\n        RealmResults<OwnerPrimaryKey> owners = realm.where(OwnerPrimaryKey.class).findAll();\n        assertEquals(2, owners.size());\n        assertEquals(1, owners.get(1).getId());\n        assertEquals(\"bar\", owners.get(1).getName());\n    }\n\n    // Tests updating a existing object with JSON object with only primary key.\n    // No value should be changed.\n    @Test\n    public void createOrUpdateObjectFromJson_objectNullValues() throws IOException {\n        AllTypesPrimaryKey obj = new AllTypesPrimaryKey();\n        Date date = new Date(0);\n\n        ObjectId objectId = new ObjectId(new Date(20));\n        Decimal128 decimal128 = new Decimal128(300);\n        UUID uuid = UUID.randomUUID();\n        RealmAny realmAny = RealmAny.valueOf(\"Hello world\");\n\n        obj.setColumnLong(1); // ID\n        obj.setColumnBinary(new byte[]{1});\n        obj.setColumnBoolean(true);\n        obj.setColumnDate(date);\n        obj.setColumnDouble(1);\n        obj.setColumnFloat(1);\n        obj.setColumnString(\"1\");\n        obj.setColumnObjectId(objectId);\n        obj.setColumnDecimal128(decimal128);\n        obj.setColumnUUID(uuid);\n        obj.setColumnRealmAny(realmAny);\n\n        realm.beginTransaction();\n        realm.copyToRealm(obj);\n        realm.commitTransaction();\n\n        String json = TestHelper.streamToString(TestHelper.loadJsonFromAssets(context, \"all_types_primary_key_field_only.json\"));\n        realm.beginTransaction();\n        realm.createOrUpdateObjectFromJson(AllTypesPrimaryKey.class, json);\n        realm.commitTransaction();\n\n        // Checks that all primitive types are imported correctly.\n        obj = realm.where(AllTypesPrimaryKey.class).findFirst();\n        assertEquals(\"1\", obj.getColumnString());\n        assertEquals(1L, obj.getColumnLong());\n        assertEquals(1F, obj.getColumnFloat(), 0F);\n        assertEquals(1D, obj.getColumnDouble(), 0D);\n        assertEquals(true, obj.isColumnBoolean());\n        assertEquals(date, obj.getColumnDate());\n        assertEquals(objectId, obj.getColumnObjectId());\n        assertEquals(decimal128, obj.getColumnDecimal128());\n        assertEquals(uuid, obj.getColumnUUID());\n        assertEquals(realmAny, obj.getColumnRealmAny());\n        assertArrayEquals(new byte[]{1}, obj.getColumnBinary());\n        assertNull(obj.getColumnRealmObject());\n        assertEquals(0, obj.getColumnRealmList().size());\n    }\n\n    @Test\n    public void createOrUpdateObjectFromJson_stringNoPrimaryKeyThrows() throws IOException {\n        try {\n            realm.createOrUpdateObjectFromJson(AllTypes.class, \"{}\");\n            fail();\n        } catch (IllegalArgumentException ignored) {\n        }\n    }\n\n    @Test\n    public void createOrUpdateObjectFromJson_objectIgnoreUnsetProperties() throws IOException {\n        String json = TestHelper.streamToString(TestHelper.loadJsonFromAssets(context, \"list_alltypes_primarykey.json\"));\n\n        realm.beginTransaction();\n        realm.createOrUpdateAllFromJson(AllTypesPrimaryKey.class, json);\n        realm.commitTransaction();\n\n        // No-op as no properties should be updated\n        realm.beginTransaction();\n        realm.createOrUpdateObjectFromJson(AllTypesPrimaryKey.class, \"{ \\\"columnLong\\\":1 }\");\n        realm.commitTransaction();\n\n        assertAllTypesPrimaryKeyUpdated();\n    }\n\n    @Test\n    public void createOrUpdateObjectFromJson_inputString() throws IOException {\n        TestHelper.populateSimpleAllTypesPrimaryKey(realm);\n\n        realm.beginTransaction();\n        AllTypesPrimaryKey newObj = realm.createOrUpdateObjectFromJson(AllTypesPrimaryKey.class, \"{ \\\"columnLong\\\" : 1, \\\"columnString\\\" : \\\"bar\\\" }\");\n        realm.commitTransaction();\n\n        assertEquals(1, realm.where(AllTypesPrimaryKey.class).count());\n        assertEquals(\"bar\", newObj.getColumnString());\n    }\n\n    @Test\n    public void createOrUpdateObjectFromJson_inputStringNullClass() throws IOException {\n        TestHelper.populateSimpleAllTypesPrimaryKey(realm);\n\n        realm.beginTransaction();\n        assertNull(realm.createOrUpdateObjectFromJson(null, \"{ \\\"columnLong\\\" : 1, \\\"columnString\\\" : \\\"bar\\\" }\"));\n        realm.commitTransaction();\n    }\n\n    @Test\n    public void createOrUpdateObjectFromJson_nullInputString() throws IOException {\n        TestHelper.populateSimpleAllTypesPrimaryKey(realm);\n\n        realm.beginTransaction();\n        assertNull(realm.createOrUpdateObjectFromJson(AllTypesPrimaryKey.class, (String) null));\n        realm.commitTransaction();\n    }\n\n    @Test\n    public void createOrUpdateObjectFromJson_emptyInputString() throws IOException {\n        TestHelper.populateSimpleAllTypesPrimaryKey(realm);\n\n        realm.beginTransaction();\n        assertNull(realm.createOrUpdateObjectFromJson(AllTypesPrimaryKey.class, \"\"));\n        realm.commitTransaction();\n    }\n\n    @Test\n    public void createOrUpdateObjectFromJson_invalidInputString() throws IOException {\n        TestHelper.populateSimpleAllTypesPrimaryKey(realm);\n\n        realm.beginTransaction();\n        try {\n            realm.createOrUpdateObjectFromJson(AllTypesPrimaryKey.class, \"{ \\\"columnLong\\\" : 1,\");\n            fail();\n        } catch (RealmException ignored) {\n        } finally {\n            realm.commitTransaction();\n        }\n    }\n\n    @Test\n    public void createOrUpdateObjectFromJson_noPrimaryKeyThrows() {\n        try {\n            realm.createOrUpdateObjectFromJson(AllTypes.class, new JSONObject());\n            fail();\n        } catch (IllegalArgumentException ignored) {\n        }\n    }\n\n    @Test\n    public void createOrUpdateObjectFromJson_withJsonObject() throws JSONException {\n        TestHelper.populateSimpleAllTypesPrimaryKey(realm);\n\n        realm.beginTransaction();\n        JSONObject json = new JSONObject();\n        json.put(\"columnLong\", 1);\n        json.put(\"columnString\", \"bar\");\n        AllTypesPrimaryKey newObj = realm.createOrUpdateObjectFromJson(AllTypesPrimaryKey.class, json);\n\n        realm.commitTransaction();\n\n        assertEquals(1, realm.where(AllTypesPrimaryKey.class).count());\n        assertEquals(\"bar\", newObj.getColumnString());\n    }\n\n    @Test\n    public void createOrUpdateObjectFromJson_jsonObjectNullClass() throws JSONException {\n        TestHelper.populateSimpleAllTypesPrimaryKey(realm);\n\n        realm.beginTransaction();\n        JSONObject json = new JSONObject();\n        json.put(\"columnLong\", 1);\n        json.put(\"columnString\", \"bar\");\n        assertNull(realm.createOrUpdateObjectFromJson(null, json));\n        realm.commitTransaction();\n\n        AllTypesPrimaryKey obj2 = realm.where(AllTypesPrimaryKey.class).findFirst();\n        assertEquals(\"Foo\", obj2.getColumnString());\n    }\n\n    @Test\n    public void createOrUpdateObjectFromJson_nullJsonObject() throws JSONException {\n        realm.beginTransaction();\n        assertNull(realm.createOrUpdateObjectFromJson(AllTypesPrimaryKey.class, (JSONObject) null));\n        realm.commitTransaction();\n        assertEquals(0, realm.where(AllTypesPrimaryKey.class).count());\n    }\n\n    @Test\n    public void createOrUpdateObjectFromJson_invalidJsonObject() throws JSONException {\n        TestHelper.populateSimpleAllTypesPrimaryKey(realm);\n\n        realm.beginTransaction();\n        JSONObject json = new JSONObject();\n        json.put(\"columnLong\", \"A\");\n        try {\n            realm.createOrUpdateObjectFromJson(AllTypesPrimaryKey.class, json);\n            fail();\n        } catch (RealmException ignored) {\n        } finally {\n            realm.commitTransaction();\n        }\n        AllTypesPrimaryKey obj2 = realm.where(AllTypesPrimaryKey.class).findFirst();\n        assertEquals(\"Foo\", obj2.getColumnString());\n    }\n\n    /**\n     * Checks that using createOrUpdateObject will set the primary key directly instead of first setting\n     * it to the default value (which can fail).\n     */\n    @Test\n    public void createOrUpdateObjectFromJson_objectWithPrimaryKeySetValueDirectlyFromJsonObject() throws JSONException {\n        JSONObject newObject = new JSONObject(\"{\\\"id\\\": 1, \\\"name\\\": \\\"bar\\\"}\");\n        realm.beginTransaction();\n        realm.createObject(OwnerPrimaryKey.class, 0); // id = 0\n        realm.createOrUpdateObjectFromJson(OwnerPrimaryKey.class, newObject);\n        realm.commitTransaction();\n\n        RealmResults<OwnerPrimaryKey> owners = realm.where(OwnerPrimaryKey.class).findAll();\n        assertEquals(2, owners.size());\n        assertEquals(1, owners.get(1).getId());\n        assertEquals(\"bar\", owners.get(1).getName());\n    }\n\n    @Test\n    public void createOrUpdateAllFromJson_jsonArrayNoPrimaryKeyThrows() {\n        try {\n            realm.createOrUpdateAllFromJson(AllTypes.class, new JSONArray());\n            fail();\n        } catch (IllegalArgumentException ignored) {\n        }\n    }\n\n    @Test\n    public void createOrUpdateAllFromJson_jsonNullClass() {\n        realm.createOrUpdateAllFromJson(null, new JSONArray());\n        assertEquals(0, realm.where(AllTypes.class).count());\n    }\n\n    @Test\n    public void createOrUpdateAllFromJson_jsonNullJson() {\n        realm.createOrUpdateAllFromJson(AllTypes.class, (JSONArray) null);\n        assertEquals(0, realm.where(AllTypes.class).count());\n    }\n\n    @Test\n    public void createOrUpdateAllFromJson_streamNoPrimaryKeyThrows() throws IOException {\n        assumeThat(Build.VERSION.SDK_INT, greaterThanOrEqualTo(Build.VERSION_CODES.HONEYCOMB));\n\n        try {\n            realm.createOrUpdateAllFromJson(AllTypes.class, new TestHelper.StubInputStream());\n            fail();\n        } catch (IllegalArgumentException ignored) {\n        }\n    }\n\n    @Test\n    public void createOrUpdateAllFromJson_streamInvalidJSonBracketThrows() throws IOException {\n        assumeThat(Build.VERSION.SDK_INT, greaterThanOrEqualTo(Build.VERSION_CODES.HONEYCOMB));\n\n        try {\n            realm.createOrUpdateAllFromJson(AllTypesPrimaryKey.class, TestHelper.stringToStream(\"[\"));\n            fail();\n        } catch (RealmException ignored) {\n        }\n    }\n\n    @Test\n    public void createOrUpdateAllFromJson_stringNoPrimaryKeyThrows() throws IOException {\n        try {\n            realm.createOrUpdateAllFromJson(AllTypes.class, \"{}\");\n            fail();\n        } catch (IllegalArgumentException ignored) {\n        }\n    }\n\n    @Test\n    public void createOrUpdateAllFromJson_inputStringNullClass() {\n        realm.beginTransaction();\n        realm.createOrUpdateAllFromJson((Class<AllTypesPrimaryKey>) null, \"{ \\\"columnLong\\\" : 1 }\");\n        realm.commitTransaction();\n        assertEquals(0, realm.where(AllTypesPrimaryKey.class).count());\n    }\n\n    @Test\n    public void createOrUpdateAllFromJson_inputStringNullJson() {\n        realm.beginTransaction();\n        realm.createOrUpdateAllFromJson(AllTypesPrimaryKey.class, (String) null);\n        realm.commitTransaction();\n        assertEquals(0, realm.where(AllTypesPrimaryKey.class).count());\n    }\n\n    @Test\n    public void createOrUpdateAllFromJson_inputStringEmptyJson() {\n        realm.beginTransaction();\n        realm.createOrUpdateAllFromJson(AllTypesPrimaryKey.class, \"\");\n        realm.commitTransaction();\n        assertEquals(0, realm.where(AllTypesPrimaryKey.class).count());\n    }\n\n    @Test\n    public void createOrUpdateAllFromJson_inputStringInvalidJson() {\n        realm.beginTransaction();\n        try {\n            realm.createOrUpdateAllFromJson(AllTypesPrimaryKey.class, \"{ \\\"columnLong\\\" : 1\");\n            fail();\n        } catch (RealmException ignored) {\n        } finally {\n            realm.commitTransaction();\n        }\n    }\n\n    @Test\n    public void createOrUpdateAllFromJson_jsonArray() throws JSONException, IOException {\n        String json = TestHelper.streamToString(TestHelper.loadJsonFromAssets(context, \"list_alltypes_primarykey.json\"));\n        JSONArray array = new JSONArray(json);\n        realm.beginTransaction();\n        realm.createOrUpdateAllFromJson(AllTypesPrimaryKey.class, array);\n        realm.commitTransaction();\n\n        assertAllTypesPrimaryKeyUpdated();\n    }\n\n    @Test\n    public void createOrUpdateAllFromJson_inputStream() throws IOException {\n        assumeThat(Build.VERSION.SDK_INT, greaterThanOrEqualTo(Build.VERSION_CODES.HONEYCOMB));\n\n        realm.beginTransaction();\n        realm.createOrUpdateAllFromJson(AllTypesPrimaryKey.class, TestHelper.loadJsonFromAssets(context, \"list_alltypes_primarykey.json\"));\n        realm.commitTransaction();\n\n        assertAllTypesPrimaryKeyUpdated();\n    }\n\n    @Test\n    public void createOrUpdateAllFromJson_inputString() throws IOException {\n        String json = TestHelper.streamToString(TestHelper.loadJsonFromAssets(context, \"list_alltypes_primarykey.json\"));\n        realm.beginTransaction();\n        realm.createOrUpdateAllFromJson(AllTypesPrimaryKey.class, json);\n        realm.commitTransaction();\n\n        assertAllTypesPrimaryKeyUpdated();\n    }\n\n    @Test\n    public void createOrUpdateObjectFromJson_objectIdPK() throws JSONException {\n        String stringId = \"789ABCDEF0123456789ABCDE\";\n        JSONObject jsonObject = new JSONObject(\"{\\\"id\\\": \\\"\"+ stringId + \"\\\", \\\"name\\\": \\\"bar\\\"}\");\n        realm.beginTransaction();\n        realm.createOrUpdateObjectFromJson(PrimaryKeyAsObjectId.class, jsonObject);\n        realm.commitTransaction();\n\n        RealmResults<PrimaryKeyAsObjectId> owners = realm.where(PrimaryKeyAsObjectId.class).findAll();\n        assertEquals(1, owners.size());\n        assertEquals(new ObjectId(stringId), owners.get(0).getId());\n        assertEquals(\"bar\", owners.get(0).getName());\n    }\n\n    // Tests creating objects from Json, all nullable fields with null values or non-null values.\n    @Test\n    public void createAllFromJson_nullTypesJsonWithNulls() throws IOException, JSONException {\n        String json = TestHelper.streamToString(TestHelper.loadJsonFromAssets(context, \"nulltypes.json\"));\n        JSONArray array = new JSONArray(json);\n        realm.beginTransaction();\n        realm.createAllFromJson(NullTypes.class, array);\n        realm.commitTransaction();\n\n        RealmResults<NullTypes> nullTypesRealmResults = realm.where(NullTypes.class).findAll();\n        assertEquals(3, nullTypesRealmResults.size());\n\n        NullTypes nullTypes1 = nullTypesRealmResults.where().equalTo(\"id\", 1).findFirst();\n        checkNullableValuesAreNull(nullTypes1);\n\n        NullTypes nullTypes2 = nullTypesRealmResults.where().equalTo(\"id\", 2).findFirst();\n        checkNullableValuesAreNotNull(nullTypes2);\n    }\n\n    // Tests creating objects form JSON stream, all nullable fields with null values or non-null values.\n    @Test\n    public void createAllFromJson_nullTypesStreamJSONWithNulls() throws IOException {\n        assumeThat(Build.VERSION.SDK_INT, greaterThanOrEqualTo(Build.VERSION_CODES.HONEYCOMB));\n\n        realm.beginTransaction();\n        realm.createAllFromJson(NullTypes.class, TestHelper.loadJsonFromAssets(context, \"nulltypes.json\"));\n        realm.commitTransaction();\n\n        RealmResults<NullTypes> nullTypesRealmResults = realm.where(NullTypes.class).findAll();\n        assertEquals(3, nullTypesRealmResults.size());\n\n        NullTypes nullTypes1 = nullTypesRealmResults.where().equalTo(\"id\", 1).findFirst();\n        checkNullableValuesAreNull(nullTypes1);\n\n        NullTypes nullTypes2 = nullTypesRealmResults.where().equalTo(\"id\", 2).findFirst();\n        checkNullableValuesAreNotNull(nullTypes2);\n    }\n\n    /**\n     * Tests a nullable field already has a non-null value, update it through JSON with null value\n     * of the corresponding field.\n     */\n    @Test\n    public void createObjectFromJson_updateNullTypesJSONWithNulls() throws IOException, JSONException {\n        String json = TestHelper.streamToString(TestHelper.loadJsonFromAssets(context, \"nulltypes.json\"));\n        // Nullable fields with values\n        JSONArray jsonArray = new JSONArray(json);\n        JSONObject jsonObject = jsonArray.getJSONObject(1);\n        jsonObject.put(\"id\", 1);\n\n        // Now object with id 1 has values for all nullable fields.\n        realm.beginTransaction();\n        realm.createObjectFromJson(NullTypes.class, jsonObject);\n        realm.commitTransaction();\n\n        RealmResults<NullTypes> nullTypesRealmResults = realm.where(NullTypes.class).findAll();\n        assertEquals(2, nullTypesRealmResults.size());\n        checkNullableValuesAreNotNull(nullTypesRealmResults.where().equalTo(\"id\", 1).findFirst());\n\n        // Updates object with id 1, nullable fields should have null values.\n        JSONArray array = new JSONArray(json);\n        realm.beginTransaction();\n        realm.createOrUpdateAllFromJson(NullTypes.class, array);\n        realm.commitTransaction();\n\n        nullTypesRealmResults = realm.where(NullTypes.class).findAll();\n        assertEquals(3, nullTypesRealmResults.size());\n\n        NullTypes nullTypes1 = nullTypesRealmResults.where().equalTo(\"id\", 1).findFirst();\n        checkNullableValuesAreNull(nullTypes1);\n    }\n\n    /**\n     * If JSON has a field with value null, and corresponding object's field is not nullable,\n     * an exception should be throw.\n     */\n    @Test\n    public void createObjectFromJson_nullTypesJSONToNotNullFields() throws IOException, JSONException {\n        String json = TestHelper.streamToString(TestHelper.loadJsonFromAssets(context, \"nulltypes_invalid.json\"));\n        JSONArray array = new JSONArray(json);\n        realm.beginTransaction();\n\n        // 1 String\n        try {\n            realm.createObjectFromJson(NullTypes.class, array.getJSONObject(0));\n            fail();\n        } catch (IllegalArgumentException ignored) {\n            assertTrue(ignored.getMessage().contains(NullTypes.FIELD_STRING_NOT_NULL));\n        } catch (Exception e) {\n            fail(\"Unexpected exception: \" + e);\n        }\n\n        // 2 Bytes\n        try {\n            realm.createObjectFromJson(NullTypes.class, array.getJSONObject(1));\n            fail();\n        } catch (IllegalArgumentException ignored) {\n            assertTrue(ignored.getMessage().contains(NullTypes.FIELD_BYTES_NOT_NULL));\n        } catch (Exception e) {\n            fail(\"Unexpected exception: \" + e);\n        }\n\n        // 3 Boolean\n        try {\n            realm.createObjectFromJson(NullTypes.class, array.getJSONObject(2));\n            fail();\n        } catch (IllegalArgumentException ignored) {\n        } catch (Exception e) {\n            fail(\"Unexpected exception: \" + e);\n        }\n\n        // 4 Byte\n        try {\n            realm.createObjectFromJson(NullTypes.class, array.getJSONObject(3));\n            fail();\n        } catch (IllegalArgumentException ignored) {\n            assertTrue(ignored.getMessage().contains(NullTypes.FIELD_BYTE_NOT_NULL));\n        } catch (Exception e) {\n            fail(\"Unexpected exception: \" + e);\n        }\n\n        // 5 Short\n        try {\n            realm.createObjectFromJson(NullTypes.class, array.getJSONObject(4));\n            fail();\n        } catch (IllegalArgumentException ignored) {\n            assertTrue(ignored.getMessage().contains(NullTypes.FIELD_SHORT_NOT_NULL));\n        } catch (Exception e) {\n            fail(\"Unexpected exception: \" + e);\n        }\n\n        // 6 Integer\n        try {\n            realm.createObjectFromJson(NullTypes.class, array.getJSONObject(5));\n            fail();\n        } catch (IllegalArgumentException ignored) {\n            assertTrue(ignored.getMessage().contains(NullTypes.FIELD_INTEGER_NOT_NULL));\n        } catch (Exception e) {\n            fail(\"Unexpected exception: \" + e);\n        }\n\n        // 7 Long\n        try {\n            realm.createObjectFromJson(NullTypes.class, array.getJSONObject(6));\n            fail();\n        } catch (IllegalArgumentException ignored) {\n            assertTrue(ignored.getMessage().contains(NullTypes.FIELD_LONG_NOT_NULL));\n        } catch (Exception e) {\n            fail(\"Unexpected exception: \" + e);\n        }\n\n        // 8 Float\n        try {\n            realm.createObjectFromJson(NullTypes.class, array.getJSONObject(7));\n            fail();\n        } catch (IllegalArgumentException ignored) {\n            assertTrue(ignored.getMessage().contains(NullTypes.FIELD_FLOAT_NOT_NULL));\n        } catch (Exception e) {\n            fail(\"Unexpected exception: \" + e);\n        }\n\n        // 9 Double\n        try {\n            realm.createObjectFromJson(NullTypes.class, array.getJSONObject(8));\n            fail();\n        } catch (IllegalArgumentException ignored) {\n            assertTrue(ignored.getMessage().contains(NullTypes.FIELD_DOUBLE_NOT_NULL));\n        } catch (Exception e) {\n            fail(\"Unexpected exception: \" + e);\n        }\n\n        // 10 Date\n        try {\n            realm.createObjectFromJson(NullTypes.class, array.getJSONObject(9));\n            fail();\n        } catch (IllegalArgumentException ignored) {\n            assertTrue(ignored.getMessage().contains(NullTypes.FIELD_DATE_NOT_NULL));\n        } catch (Exception e) {\n            fail(\"Unexpected exception: \" + e);\n        }\n\n        // 11 Decimal128\n        try {\n            realm.createObjectFromJson(NullTypes.class, array.getJSONObject(10));\n            fail();\n        } catch (IllegalArgumentException ignored) {\n            assertTrue(ignored.getMessage().contains(NullTypes.FIELD_DECIMAL128_NOT_NULL));\n        } catch (Exception e) {\n            fail(\"Unexpected exception: \" + e);\n        }\n\n        // 12 ObjectId\n        try {\n            realm.createObjectFromJson(NullTypes.class, array.getJSONObject(11));\n            fail();\n        } catch (IllegalArgumentException ignored) {\n            assertTrue(ignored.getMessage().contains(NullTypes.FIELD_OBJECT_ID_NOT_NULL));\n        } catch (Exception e) {\n            fail(\"Unexpected exception: \" + e);\n        }\n\n        // 13 UUID\n        try {\n            realm.createObjectFromJson(NullTypes.class, array.getJSONObject(12));\n            fail();\n        } catch (IllegalArgumentException ignored) {\n            assertTrue(ignored.getMessage().contains(NullTypes.FIELD_UUID_NOT_NULL));\n        } catch (Exception e) {\n            fail(\"Unexpected exception: \" + e);\n        }\n\n        realm.cancelTransaction();\n    }\n\n    /**\n     * If JSON has a field with value null, and corresponding object's field is not nullable,\n     * an exception should be throw. Stream version.\n     */\n    @Test\n    public void createObjectFromJson_nullTypesJSONStreamToNotNullFields() throws IOException, JSONException {\n        assumeThat(Build.VERSION.SDK_INT, greaterThanOrEqualTo(Build.VERSION_CODES.HONEYCOMB));\n\n        String json = TestHelper.streamToString(TestHelper.loadJsonFromAssets(context, \"nulltypes_invalid.json\"));\n        JSONArray array = new JSONArray(json);\n\n        // 1 String\n        try {\n            realm.beginTransaction();\n            realm.createObjectFromJson(NoPrimaryKeyNullTypes.class, convertJsonObjectToStream(array.getJSONObject(0)));\n            fail();\n        } catch (IllegalArgumentException ignored) {\n            assertTrue(ignored.getMessage().contains(NullTypes.FIELD_STRING_NOT_NULL));\n        } finally {\n            realm.cancelTransaction();\n        }\n        // 2 Bytes\n        try {\n            realm.beginTransaction();\n            realm.createObjectFromJson(NoPrimaryKeyNullTypes.class, convertJsonObjectToStream(array.getJSONObject(1)));\n            fail();\n        } catch (IllegalArgumentException ignored) {\n            assertTrue(ignored.getMessage().contains(NullTypes.FIELD_BYTES_NOT_NULL));\n        } finally {\n            realm.cancelTransaction();\n        }\n        // 3 Boolean\n        try {\n            realm.beginTransaction();\n            realm.createObjectFromJson(NoPrimaryKeyNullTypes.class, convertJsonObjectToStream(array.getJSONObject(2)));\n            fail();\n        } catch (IllegalArgumentException ignored) {\n            assertTrue(ignored.getMessage().contains(NullTypes.FIELD_BOOLEAN_NOT_NULL));\n        } finally {\n            realm.cancelTransaction();\n        }\n        // 4 Byte\n        try {\n            realm.beginTransaction();\n            realm.createObjectFromJson(NoPrimaryKeyNullTypes.class, convertJsonObjectToStream(array.getJSONObject(3)));\n            fail();\n        } catch (IllegalArgumentException ignored) {\n            assertTrue(ignored.getMessage().contains(NullTypes.FIELD_BYTE_NOT_NULL));\n        } finally {\n            realm.cancelTransaction();\n        }\n        // 5 Short\n        try {\n            realm.beginTransaction();\n            realm.createObjectFromJson(NoPrimaryKeyNullTypes.class, convertJsonObjectToStream(array.getJSONObject(4)));\n            fail();\n        } catch (IllegalArgumentException ignored) {\n            assertTrue(ignored.getMessage().contains(NullTypes.FIELD_SHORT_NOT_NULL));\n        } finally {\n            realm.cancelTransaction();\n        }\n        // 6 Integer\n        try {\n            realm.beginTransaction();\n            realm.createObjectFromJson(NoPrimaryKeyNullTypes.class, convertJsonObjectToStream(array.getJSONObject(5)));\n            fail();\n        } catch (IllegalArgumentException ignored) {\n            assertTrue(ignored.getMessage().contains(NullTypes.FIELD_INTEGER_NOT_NULL));\n        } finally {\n            realm.cancelTransaction();\n        }\n        // 7 Long\n        try {\n            realm.beginTransaction();\n            realm.createObjectFromJson(NoPrimaryKeyNullTypes.class, convertJsonObjectToStream(array.getJSONObject(6)));\n            fail();\n        } catch (IllegalArgumentException ignored) {\n            assertTrue(ignored.getMessage().contains(NullTypes.FIELD_LONG_NOT_NULL));\n        } finally {\n            realm.cancelTransaction();\n        }\n        // 8 Float\n        try {\n            realm.beginTransaction();\n            realm.createObjectFromJson(NoPrimaryKeyNullTypes.class, convertJsonObjectToStream(array.getJSONObject(7)));\n            fail();\n        } catch (IllegalArgumentException ignored) {\n            assertTrue(ignored.getMessage().contains(NullTypes.FIELD_FLOAT_NOT_NULL));\n        } finally {\n            realm.cancelTransaction();\n        }\n        // 9 Double\n        try {\n            realm.beginTransaction();\n            realm.createObjectFromJson(NoPrimaryKeyNullTypes.class, convertJsonObjectToStream(array.getJSONObject(8)));\n            fail();\n        } catch (IllegalArgumentException ignored) {\n            assertTrue(ignored.getMessage().contains(NullTypes.FIELD_DOUBLE_NOT_NULL));\n        } finally {\n            realm.cancelTransaction();\n        }\n        // 10 Date\n        try {\n            realm.beginTransaction();\n            realm.createObjectFromJson(NoPrimaryKeyNullTypes.class, convertJsonObjectToStream(array.getJSONObject(9)));\n            fail();\n        } catch (IllegalArgumentException ignored) {\n            assertTrue(ignored.getMessage().contains(NullTypes.FIELD_DATE_NOT_NULL));\n        } finally {\n            realm.cancelTransaction();\n        }\n        // 11 Decimal128\n        try {\n            realm.beginTransaction();\n            realm.createObjectFromJson(NoPrimaryKeyNullTypes.class, convertJsonObjectToStream(array.getJSONObject(10)));\n            fail();\n        } catch (IllegalArgumentException ignored) {\n            assertTrue(ignored.getMessage().contains(NullTypes.FIELD_DECIMAL128_NOT_NULL));\n        } finally {\n            realm.cancelTransaction();\n        }\n        // 12 ObjectId\n        try {\n            realm.beginTransaction();\n            realm.createObjectFromJson(NoPrimaryKeyNullTypes.class, convertJsonObjectToStream(array.getJSONObject(11)));\n            fail();\n        } catch (IllegalArgumentException ignored) {\n            assertTrue(ignored.getMessage().contains(NullTypes.FIELD_OBJECT_ID_NOT_NULL));\n        } finally {\n            realm.cancelTransaction();\n        }\n        // 13 UUID\n        try {\n            realm.beginTransaction();\n            realm.createObjectFromJson(NoPrimaryKeyNullTypes.class, convertJsonObjectToStream(array.getJSONObject(12)));\n            fail();\n        } catch (IllegalArgumentException ignored) {\n            assertTrue(ignored.getMessage().contains(NullTypes.FIELD_UUID_NOT_NULL));\n        } finally {\n            realm.cancelTransaction();\n        }\n    }\n\n    /**\n     * Checks that using createOrUpdateObject will set the primary key directly instead of first setting\n     * it to the default value (which can fail).\n     */\n    @Test\n    public void createObjectFromJson_objectWithPrimaryKeySetValueDirectlyFromJsonObject() throws JSONException {\n        JSONObject newObject = new JSONObject(\"{\\\"id\\\": 1, \\\"name\\\": \\\"bar\\\"}\");\n        realm.beginTransaction();\n        realm.createObject(OwnerPrimaryKey.class, 0); // id = 0\n        realm.createObjectFromJson(OwnerPrimaryKey.class, newObject);\n        realm.commitTransaction();\n\n        RealmResults<OwnerPrimaryKey> owners = realm.where(OwnerPrimaryKey.class).findAll();\n        assertEquals(2, owners.size());\n        assertEquals(1, owners.get(1).getId());\n        assertEquals(\"bar\", owners.get(1).getName());\n    }\n\n    @Test\n    public void createObjectFromJson_objectNullClass() throws JSONException {\n        JSONObject newObject = new JSONObject(\"{\\\"id\\\": 1, \\\"name\\\": \\\"bar\\\"}\");\n        realm.beginTransaction();\n        assertNull(realm.createObjectFromJson(null, newObject));\n        realm.commitTransaction();\n    }\n\n    /**\n     * createObject using primary keys doesn't work if the Check that using createOrUpdateObject\n     * will set the primary key directly instead of first setting it to the default value (which can fail).\n     */\n    @Test\n    public void createObjectFromJson_objectWithPrimaryKeySetValueDirectlyFromStream() throws JSONException, IOException {\n        assumeThat(Build.VERSION.SDK_INT, greaterThanOrEqualTo(Build.VERSION_CODES.HONEYCOMB));\n\n        InputStream stream = TestHelper.stringToStream(\"{\\\"id\\\": 1, \\\"name\\\": \\\"bar\\\"}\");\n        realm.beginTransaction();\n        realm.createObject(OwnerPrimaryKey.class, 0); // id = 0\n        realm.createObjectFromJson(OwnerPrimaryKey.class, stream);\n        realm.commitTransaction();\n\n        RealmResults<OwnerPrimaryKey> owners = realm.where(OwnerPrimaryKey.class).findAll();\n        assertEquals(2, owners.size());\n        assertEquals(1, owners.get(1).getId());\n        assertEquals(\"bar\", owners.get(1).getName());\n    }\n\n    private void testPrimitiveListWithValues(String fieldName, Object[] values) throws JSONException, IOException {\n        testPrimitiveListWithValues(fieldName, values, values);\n    }\n\n    private void testPrimitiveListWithValues(String fieldName, @Nullable Object[] valuesToSave, Object[] valuesToLoad)\n            throws JSONException, IOException {\n        JSONObject jsonObject = new JSONObject();\n        JSONArray jsonArray = valuesToSave != null ? new JSONArray(valuesToSave) : null;\n        jsonObject.put(fieldName, jsonArray);\n\n        // Test from JSONObject\n        realm.beginTransaction();\n        PrimitiveListTypes primitiveListTypes = realm.createObjectFromJson(PrimitiveListTypes.class, jsonObject);\n        realm.commitTransaction();\n        assertNotNull(primitiveListTypes);\n        assertArrayEquals(valuesToLoad, primitiveListTypes.getList(fieldName).toArray());\n\n        // Test from JSONStream\n        realm.beginTransaction();\n        primitiveListTypes = realm.createObjectFromJson(PrimitiveListTypes.class, convertJsonObjectToStream(jsonObject));\n        realm.commitTransaction();\n        assertNotNull(primitiveListTypes);\n        assertArrayEquals(valuesToLoad, primitiveListTypes.getList(fieldName).toArray());\n    }\n\n    @Test\n    public void createObjectFromJson_primitiveList_realmAnyValues() throws JSONException, IOException {\n        testPrimitiveListWithValues(PrimitiveListTypes.FIELD_STRING_LIST, new String[] {\"a\", null, \"bc\"});\n        testPrimitiveListWithValues(PrimitiveListTypes.FIELD_BOOLEAN_LIST, new Boolean[] {true, null, false});\n        testPrimitiveListWithValues(PrimitiveListTypes.FIELD_DOUBLE_LIST, new Double[] {1.0d, null, 2.0d});\n        testPrimitiveListWithValues(PrimitiveListTypes.FIELD_FLOAT_LIST, new Float[] {1.0f, null, 2.0f});\n        testPrimitiveListWithValues(PrimitiveListTypes.FIELD_BYTE_LIST, new Byte[] {1, null, 2});\n        testPrimitiveListWithValues(PrimitiveListTypes.FIELD_SHORT_LIST, new Short[] {1, null, 2});\n        testPrimitiveListWithValues(PrimitiveListTypes.FIELD_INT_LIST, new Integer[] {1, null, 2});\n        testPrimitiveListWithValues(PrimitiveListTypes.FIELD_LONG_LIST, new Long[] {1L, null, 2L});\n\n        // Date as integer\n        testPrimitiveListWithValues(PrimitiveListTypes.FIELD_DATE_LIST,\n                new Integer[] {0, null, 1},\n                new Date[] {new Date(0), null, new Date(1)});\n        // Date as String\n        testPrimitiveListWithValues(PrimitiveListTypes.FIELD_DATE_LIST,\n                new String [] {\"/Date(1000)/\", null, \"/Date(2000)/\"},\n                new Date[] {new Date(1000), null, new Date(2000)});\n        // Date as String timezone\n        // Oct 03 2015 14:45.33\n        Calendar cal = GregorianCalendar.getInstance();\n        cal.setTimeZone(TimeZone.getTimeZone(\"Australia/West\"));\n        cal.set(2015, Calendar.OCTOBER, 3, 14, 45, 33);\n        cal.set(Calendar.MILLISECOND, 376);\n        testPrimitiveListWithValues(PrimitiveListTypes.FIELD_DATE_LIST,\n                new String [] {\"/Date(1443854733376+0800)/\", null},\n                new Date[] {cal.getTime(), null});\n\n\n        testPrimitiveListWithValues(PrimitiveListTypes.FIELD_BINARY_LIST,\n                new String[] {new String(Base64.encode(new byte[] {1, 2, 3}, Base64.DEFAULT), UTF_8),\n                        null, new String(Base64.encode(new byte[] {4, 5, 6}, Base64.DEFAULT), UTF_8)},\n                new byte[][] {new byte[]{1, 2, 3}, null, new byte[]{4, 5, 6}});\n\n        testPrimitiveListWithValues(PrimitiveListTypes.FIELD_OBJECT_ID_LIST,\n                new String[] {\"789ABCDEF0123456789ABCDA\", null, \"789ABCDEF0123456789ABCDB\"},\n                new ObjectId[] {new ObjectId(\"789ABCDEF0123456789ABCDA\"), null, new ObjectId(\"789ABCDEF0123456789ABCDB\")});\n\n        testPrimitiveListWithValues(PrimitiveListTypes.FIELD_DECIMAL128_LIST,\n                new Integer[] {0, null, 1},\n                new Decimal128[] {new Decimal128(0), null, new Decimal128(1)});\n\n        testPrimitiveListWithValues(PrimitiveListTypes.FIELD_UUID_LIST,\n                new String[] {\"027ba5ca-aa12-4afa-9219-e20cc3018599\", null, \"027ba5ca-aa12-4afa-9219-e20cc3018590\"},\n                new UUID[] {UUID.fromString(\"027ba5ca-aa12-4afa-9219-e20cc3018599\"), null, UUID.fromString(\"027ba5ca-aa12-4afa-9219-e20cc3018590\")});\n\n        testPrimitiveListWithValues(PrimitiveListTypes.FIELD_REALM_ANY_LIST,\n                new Object[] {0, null, \"hello world\"},\n                new RealmAny[] {RealmAny.valueOf(0), RealmAny.nullValue(), RealmAny.valueOf(\"hello world\")});\n    }\n\n    // Null list will be saved as empty list since We don't support nullable RealmList\n    @Test\n    public void createObjectFromJson_primitiveList_nullList() throws IOException, JSONException {\n        testPrimitiveListWithValues(PrimitiveListTypes.FIELD_STRING_LIST, null, new String[0]);\n        testPrimitiveListWithValues(PrimitiveListTypes.FIELD_BOOLEAN_LIST, null, new Boolean[0]);\n        testPrimitiveListWithValues(PrimitiveListTypes.FIELD_DOUBLE_LIST, null, new Double[0]);\n        testPrimitiveListWithValues(PrimitiveListTypes.FIELD_FLOAT_LIST, null, new Float[0]);\n        testPrimitiveListWithValues(PrimitiveListTypes.FIELD_BYTE_LIST, null, new Byte[0]);\n        testPrimitiveListWithValues(PrimitiveListTypes.FIELD_SHORT_LIST, null, new Short[0]);\n        testPrimitiveListWithValues(PrimitiveListTypes.FIELD_INT_LIST, null, new Integer[0]);\n        testPrimitiveListWithValues(PrimitiveListTypes.FIELD_LONG_LIST, null, new Long[0]);\n        testPrimitiveListWithValues(PrimitiveListTypes.FIELD_DATE_LIST, null, new Date[0]);\n        testPrimitiveListWithValues(PrimitiveListTypes.FIELD_OBJECT_ID_LIST, null, new Date[0]);\n        testPrimitiveListWithValues(PrimitiveListTypes.FIELD_DECIMAL128_LIST, null, new Date[0]);\n        testPrimitiveListWithValues(PrimitiveListTypes.FIELD_UUID_LIST, null, new Date[0]);\n        testPrimitiveListWithValues(PrimitiveListTypes.FIELD_REALM_ANY_LIST, null, new Date[0]);\n        testPrimitiveListWithValues(PrimitiveListTypes.FIELD_OBJECT_ID_LIST, null, new ObjectId[0]);\n        testPrimitiveListWithValues(PrimitiveListTypes.FIELD_DECIMAL128_LIST, null, new Decimal128[0]);\n        testPrimitiveListWithValues(PrimitiveListTypes.FIELD_BYTE_LIST, null, new byte[0][]);\n    }\n\n    private void testRequiredPrimitiveListWithNullValue(String fieldName) throws JSONException, IOException {\n        JSONObject jsonObject = new JSONObject();\n        JSONArray jsonArray =new JSONArray();\n        jsonArray.put(null);\n        jsonObject.put(fieldName, jsonArray);\n\n        // Test from JSONObject\n        realm.beginTransaction();\n        try {\n            realm.createObjectFromJson(PrimitiveListTypes.class, jsonObject);\n            fail();\n        } catch (IllegalArgumentException ignored) {\n            ignored.printStackTrace();\n        } finally {\n            realm.cancelTransaction();\n        }\n\n        // Test from JSONStream\n        realm.beginTransaction();\n        try {\n            realm.createObjectFromJson(PrimitiveListTypes.class, convertJsonObjectToStream(jsonObject));\n            fail();\n        } catch (IllegalArgumentException ignored) {\n            ignored.printStackTrace();\n        } finally {\n            realm.cancelTransaction();\n        }\n    }\n\n    private void testOptionalPrimitiveListWithNullValue(String fieldName) throws JSONException, IOException {\n        JSONObject jsonObject = new JSONObject();\n        JSONArray jsonArray =new JSONArray();\n        jsonArray.put(null);\n        jsonObject.put(fieldName, jsonArray);\n\n        // Test from JSONObject\n        realm.beginTransaction();\n        realm.createObjectFromJson(PrimitiveListTypes.class, jsonObject);\n        realm.cancelTransaction();\n\n        // Test from JSONStream\n        realm.beginTransaction();\n        PrimitiveListTypes objectFromJson = realm.createObjectFromJson(PrimitiveListTypes.class, convertJsonObjectToStream(jsonObject));\n        realm.cancelTransaction();\n    }\n\n    @Test\n    public void createObjectFromJson_primitiveList_nullValueForRequiredField() throws IOException, JSONException {\n        testRequiredPrimitiveListWithNullValue(PrimitiveListTypes.FIELD_REQUIRED_STRING_LIST);\n        testRequiredPrimitiveListWithNullValue(PrimitiveListTypes.FIELD_REQUIRED_BOOLEAN_LIST);\n        testRequiredPrimitiveListWithNullValue(PrimitiveListTypes.FIELD_REQUIRED_DOUBLE_LIST);\n        testRequiredPrimitiveListWithNullValue(PrimitiveListTypes.FIELD_REQUIRED_FLOAT_LIST);\n        testRequiredPrimitiveListWithNullValue(PrimitiveListTypes.FIELD_REQUIRED_BYTE_LIST);\n        testRequiredPrimitiveListWithNullValue(PrimitiveListTypes.FIELD_REQUIRED_SHORT_LIST);\n        testRequiredPrimitiveListWithNullValue(PrimitiveListTypes.FIELD_REQUIRED_INT_LIST);\n        testRequiredPrimitiveListWithNullValue(PrimitiveListTypes.FIELD_REQUIRED_LONG_LIST);\n        testRequiredPrimitiveListWithNullValue(PrimitiveListTypes.FIELD_REQUIRED_DATE_LIST);\n        testRequiredPrimitiveListWithNullValue(PrimitiveListTypes.FIELD_REQUIRED_BYTE_LIST);\n        testRequiredPrimitiveListWithNullValue(PrimitiveListTypes.FIELD_REQUIRED_OBJECT_ID_LIST);\n        testRequiredPrimitiveListWithNullValue(PrimitiveListTypes.FIELD_REQUIRED_DECIMAL128_LIST);\n        testRequiredPrimitiveListWithNullValue(PrimitiveListTypes.FIELD_REQUIRED_UUID_LIST);\n    }\n\n    @Test\n    public void createObjectFromJson_primitiveList_nullValueForOptionalField() throws IOException, JSONException {\n        testOptionalPrimitiveListWithNullValue(PrimitiveListTypes.FIELD_STRING_LIST);\n        testOptionalPrimitiveListWithNullValue(PrimitiveListTypes.FIELD_BOOLEAN_LIST);\n        testOptionalPrimitiveListWithNullValue(PrimitiveListTypes.FIELD_DOUBLE_LIST);\n        testOptionalPrimitiveListWithNullValue(PrimitiveListTypes.FIELD_FLOAT_LIST);\n        testOptionalPrimitiveListWithNullValue(PrimitiveListTypes.FIELD_BYTE_LIST);\n        testOptionalPrimitiveListWithNullValue(PrimitiveListTypes.FIELD_SHORT_LIST);\n        testOptionalPrimitiveListWithNullValue(PrimitiveListTypes.FIELD_INT_LIST);\n        testOptionalPrimitiveListWithNullValue(PrimitiveListTypes.FIELD_LONG_LIST);\n        testOptionalPrimitiveListWithNullValue(PrimitiveListTypes.FIELD_DATE_LIST);\n        testOptionalPrimitiveListWithNullValue(PrimitiveListTypes.FIELD_BYTE_LIST);\n        testOptionalPrimitiveListWithNullValue(PrimitiveListTypes.FIELD_OBJECT_ID_LIST);\n        testOptionalPrimitiveListWithNullValue(PrimitiveListTypes.FIELD_DECIMAL128_LIST);\n        testOptionalPrimitiveListWithNullValue(PrimitiveListTypes.FIELD_UUID_LIST);\n        testOptionalPrimitiveListWithNullValue(PrimitiveListTypes.FIELD_REALM_ANY_LIST);\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/RealmLinkTests.java",
    "content": "/*\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\npackage io.realm;\n\nimport androidx.test.ext.junit.runners.AndroidJUnit4;\n\nimport org.junit.After;\nimport org.junit.Before;\nimport org.junit.Rule;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\n\nimport java.util.Date;\n\nimport io.realm.entities.AllTypes;\nimport io.realm.entities.Cat;\nimport io.realm.entities.Dog;\nimport io.realm.entities.Owner;\n\nimport static org.junit.Assert.assertEquals;\nimport static org.junit.Assert.fail;\n\n@RunWith(AndroidJUnit4.class)\npublic class RealmLinkTests {\n\n    @Rule\n    public final TestRealmConfigurationFactory configFactory = new TestRealmConfigurationFactory();\n\n    private Realm testRealm;\n    private RealmConfiguration realmConfig;\n\n    @Before\n    public void setUp() {\n        realmConfig = configFactory.createConfiguration();\n        testRealm = Realm.getInstance(realmConfig);\n\n        populate();\n    }\n\n    private void populate() {\n        testRealm.beginTransaction();\n        testRealm.delete(Dog.class);\n        testRealm.delete(Cat.class);\n        testRealm.delete(Owner.class);\n\n        Dog dog1 = testRealm.createObject(Dog.class);\n        dog1.setName(\"Pluto\");\n        dog1.setAge(5);\n        dog1.setHeight(1.2f);\n        dog1.setWeight(9.9);\n        dog1.setHasTail(true);\n        dog1.setBirthday(new Date(2000));\n\n        Dog dog2 = testRealm.createObject(Dog.class);\n        dog2.setName(\"Fido\");\n        dog2.setAge(10);\n        dog2.setHeight(0.7f);\n        dog2.setWeight(11.3);\n        dog2.setHasTail(true);\n        dog2.setBirthday(new Date(4000));\n\n        Cat cat = testRealm.createObject(Cat.class);\n        cat.setName(\"Blackie\");\n        cat.setAge(12);\n        cat.setHeight(0.3f);\n        cat.setWeight(1.1);\n        cat.setHasTail(true);\n        cat.setBirthday(new Date(6000));\n\n        Owner owner = testRealm.createObject(Owner.class);\n        owner.setName(\"Tim\");\n        owner.getDogs().add(dog1);\n        owner.getDogs().add(dog2);\n        owner.setCat(cat);\n\n        cat.setOwner(owner);\n        dog1.setOwner(owner);\n        dog2.setOwner(owner);\n\n        testRealm.commitTransaction();\n    }\n\n    @After\n    public void tearDown() {\n        if (testRealm != null) {\n            testRealm.close();\n        }\n    }\n\n    @Test\n    public void objects() {\n        RealmResults<Owner> owners = testRealm.where(Owner.class).findAll();\n        assertEquals(1, owners.size());\n        assertEquals(2, owners.first().getDogs().size());\n        assertEquals(\"Pluto\", owners.first().getDogs().first().getName());\n        assertEquals(\"Fido\", owners.first().getDogs().last().getName());\n        assertEquals(\"Blackie\", owners.first().getCat().getName());\n        assertEquals(12, owners.first().getCat().getAge());\n\n        RealmResults<Dog> dogs = testRealm.where(Dog.class).findAll();\n        assertEquals(2, dogs.size());\n        for (Dog dog : dogs) {\n            assertEquals(\"Tim\", dog.getOwner().getName());\n        }\n\n        RealmResults<Cat> cats = testRealm.where(Cat.class).findAll();\n        assertEquals(1, cats.size());\n        assertEquals(\"Tim\", cats.first().getOwner().getName());\n    }\n\n\n    @Test\n    public void reamListQuery() {\n        RealmResults<Owner> owners = testRealm.where(Owner.class).findAll();\n        RealmResults<Dog> dogs = owners.get(0).getDogs().where().contains(\"name\", \"o\").findAll();\n        assertEquals(2, dogs.size());\n        assertEquals(\"Pluto\", dogs.get(0).getName());\n        assertEquals(\"Fido\", dogs.get(1).getName());\n    }\n\n    @Test\n    public void querySingleRelationBoolean() {\n        RealmResults<Owner> owners = testRealm.where(Owner.class).equalTo(\"cat.hasTail\", true).findAll();\n        assertEquals(1, owners.size());\n        assertEquals(12, owners.first().getCat().getAge());\n\n        RealmResults<Owner> none = testRealm.where(Owner.class).equalTo(\"cat.hasTail\", false).findAll();\n        assertEquals(0, none.size());\n    }\n\n    @Test\n    public void querySingleRelationInteger() {\n        RealmResults<Owner> owners1 = testRealm.where(Owner.class).equalTo(\"cat.age\", 12).findAll();\n        assertEquals(1, owners1.size());\n        assertEquals(12, owners1.first().getCat().getAge());\n\n        RealmResults<Owner> none1 = testRealm.where(Owner.class).equalTo(\"cat.age\", 13).findAll();\n        assertEquals(0, none1.size());\n\n        RealmResults<Owner> owners2 = testRealm.where(Owner.class).notEqualTo(\"cat.age\", 13).findAll();\n        assertEquals(1, owners2.size());\n        assertEquals(12, owners2.first().getCat().getAge());\n\n        RealmResults<Owner> none2 = testRealm.where(Owner.class).notEqualTo(\"cat.age\", 12).findAll();\n        assertEquals(0, none2.size());\n\n        RealmResults<Owner> owners3 = testRealm.where(Owner.class).greaterThan(\"cat.age\", 5).findAll();\n        assertEquals(1, owners3.size());\n        assertEquals(12, owners3.first().getCat().getAge());\n\n        RealmResults<Owner> owners4 = testRealm.where(Owner.class).greaterThanOrEqualTo(\"cat.age\", 5).findAll();\n        assertEquals(1, owners4.size());\n        assertEquals(12, owners4.first().getCat().getAge());\n\n        RealmResults<Owner> owners5 = testRealm.where(Owner.class).lessThan(\"cat.age\", 20).findAll();\n        assertEquals(1, owners5.size());\n        assertEquals(12, owners5.first().getCat().getAge());\n\n        RealmResults<Owner> owners6 = testRealm.where(Owner.class).lessThanOrEqualTo(\"cat.age\", 20).findAll();\n        assertEquals(1, owners6.size());\n        assertEquals(12, owners6.first().getCat().getAge());\n\n        RealmResults<Owner> owners7 = testRealm.where(Owner.class).between(\"cat.age\", 1, 20).findAll();\n        assertEquals(1, owners7.size());\n        assertEquals(12, owners7.first().getCat().getAge());\n    }\n\n    @Test\n    public void querySingleRelationDate() {\n        RealmResults<Owner> owners1 = testRealm.where(Owner.class).equalTo(\"cat.birthday\", new Date(6000)).findAll();\n        assertEquals(1, owners1.size());\n        assertEquals(12, owners1.first().getCat().getAge());\n\n        RealmResults<Owner> none1 = testRealm.where(Owner.class).equalTo(\"cat.birthday\", new Date(1000)).findAll();\n        assertEquals(0, none1.size());\n\n        RealmResults<Owner> owners2 = testRealm.where(Owner.class).notEqualTo(\"cat.birthday\", new Date(1000)).findAll();\n        assertEquals(1, owners2.size());\n        assertEquals(12, owners2.first().getCat().getAge());\n\n        RealmResults<Owner> none2 = testRealm.where(Owner.class).notEqualTo(\"cat.birthday\", new Date(6000)).findAll();\n        assertEquals(0, none2.size());\n\n        RealmResults<Owner> owners3 = testRealm.where(Owner.class).greaterThan(\"cat.birthday\", new Date(5)).findAll();\n        assertEquals(1, owners3.size());\n        assertEquals(12, owners3.first().getCat().getAge());\n\n        RealmResults<Owner> owners4 = testRealm.where(Owner.class).greaterThanOrEqualTo(\"cat.birthday\", new Date(5)).findAll();\n        assertEquals(1, owners4.size());\n        assertEquals(12, owners4.first().getCat().getAge());\n\n        RealmResults<Owner> owners5 = testRealm.where(Owner.class).lessThan(\"cat.birthday\", new Date(10000)).findAll();\n        assertEquals(1, owners5.size());\n        assertEquals(12, owners5.first().getCat().getAge());\n\n        RealmResults<Owner> owners6 = testRealm.where(Owner.class).lessThanOrEqualTo(\"cat.birthday\", new Date(10000)).findAll();\n        assertEquals(1, owners6.size());\n        assertEquals(12, owners6.first().getCat().getAge());\n\n        RealmResults<Owner> owners7 = testRealm.where(Owner.class).between(\"cat.birthday\", new Date(1), new Date(10000)).findAll();\n        assertEquals(1, owners7.size());\n        assertEquals(12, owners7.first().getCat().getAge());\n    }\n\n    @Test\n    public void querySingleRelationFloat() {\n        RealmResults<Owner> owners1 = testRealm.where(Owner.class).greaterThanOrEqualTo(\"cat.height\", 0.2f).findAll();\n        assertEquals(1, owners1.size());\n        assertEquals(12, owners1.first().getCat().getAge());\n\n        RealmResults<Owner> owners2 = testRealm.where(Owner.class).greaterThan(\"cat.height\", 0.2f).findAll();\n        assertEquals(1, owners2.size());\n        assertEquals(12, owners2.first().getCat().getAge());\n\n        RealmResults<Owner> owners3 = testRealm.where(Owner.class).lessThan(\"cat.height\", 2.2f).findAll();\n        assertEquals(1, owners3.size());\n        assertEquals(12, owners3.first().getCat().getAge());\n\n        RealmResults<Owner> owners4 = testRealm.where(Owner.class).lessThanOrEqualTo(\"cat.height\", 2.2f).findAll();\n        assertEquals(1, owners4.size());\n        assertEquals(12, owners4.first().getCat().getAge());\n\n        RealmResults<Owner> owners5 = testRealm.where(Owner.class).notEqualTo(\"cat.height\", 0.2f).findAll();\n        assertEquals(1, owners5.size());\n        assertEquals(12, owners5.first().getCat().getAge());\n\n        RealmResults<Owner> owners6 = testRealm.where(Owner.class).greaterThanOrEqualTo(\"cat.height\", 0.3f).findAll();\n        assertEquals(1, owners6.size());\n        assertEquals(12, owners6.first().getCat().getAge());\n\n        RealmResults<Owner> owners7 = testRealm.where(Owner.class).between(\"cat.height\", 0.2f, 2.2f).findAll();\n        assertEquals(1, owners7.size());\n        assertEquals(12, owners7.first().getCat().getAge());\n    }\n\n    @Test\n    public void querySingleRelationDouble() {\n        RealmResults<Owner> owners1 = testRealm.where(Owner.class).greaterThanOrEqualTo(\"cat.weight\", 0.2).findAll();\n        assertEquals(1, owners1.size());\n        assertEquals(12, owners1.first().getCat().getAge());\n\n        RealmResults<Owner> owners2 = testRealm.where(Owner.class).greaterThan(\"cat.weight\", 0.2).findAll();\n        assertEquals(1, owners2.size());\n        assertEquals(12, owners2.first().getCat().getAge());\n\n        RealmResults<Owner> owners3 = testRealm.where(Owner.class).lessThan(\"cat.weight\", 2.2).findAll();\n        assertEquals(1, owners3.size());\n        assertEquals(12, owners3.first().getCat().getAge());\n\n        RealmResults<Owner> owners4 = testRealm.where(Owner.class).lessThanOrEqualTo(\"cat.weight\", 2.2).findAll();\n        assertEquals(1, owners4.size());\n        assertEquals(12, owners4.first().getCat().getAge());\n\n        RealmResults<Owner> owners5 = testRealm.where(Owner.class).notEqualTo(\"cat.weight\", 0.2).findAll();\n        assertEquals(1, owners5.size());\n        assertEquals(12, owners5.first().getCat().getAge());\n\n        RealmResults<Owner> owners6 = testRealm.where(Owner.class).greaterThanOrEqualTo(\"cat.weight\", 0.3).findAll();\n        assertEquals(1, owners6.size());\n        assertEquals(12, owners6.first().getCat().getAge());\n\n        RealmResults<Owner> owners7 = testRealm.where(Owner.class).between(\"cat.weight\", 0.2, 2.2).findAll();\n        assertEquals(1, owners7.size());\n        assertEquals(12, owners7.first().getCat().getAge());\n    }\n\n    @Test\n    public void querySingleRelationString() {\n        RealmResults<Owner> owners1 = testRealm.where(Owner.class).equalTo(\"cat.name\", \"Blackie\").findAll();\n        assertEquals(1, owners1.size());\n\n        RealmResults<Owner> none1 = testRealm.where(Owner.class).equalTo(\"cat.name\", \"Max\").findAll();\n        assertEquals(0, none1.size());\n\n        RealmResults<Owner> owners2 = testRealm.where(Owner.class).notEqualTo(\"cat.name\", \"Max\").findAll();\n        assertEquals(1, owners2.size());\n\n        RealmResults<Owner> none2 = testRealm.where(Owner.class).notEqualTo(\"cat.name\", \"Blackie\").findAll();\n        assertEquals(0, none2.size());\n\n        RealmResults<Owner> owners3 = testRealm.where(Owner.class).beginsWith(\"cat.name\", \"Blackie\").findAll();\n        assertEquals(1, owners3.size());\n\n        RealmResults<Owner> owners4 = testRealm.where(Owner.class).endsWith(\"cat.name\", \"Blackie\").findAll();\n        assertEquals(1, owners4.size());\n\n        RealmResults<Owner> owners5 = testRealm.where(Owner.class).contains(\"cat.name\", \"Blackie\").findAll();\n        assertEquals(1, owners5.size());\n\n        RealmResults<Owner> owners6 = testRealm.where(Owner.class).equalTo(\"cat.name\", \"blackIE\", Case.INSENSITIVE).findAll();\n        assertEquals(1, owners6.size());\n    }\n\n    @Test\n    public void queryMultipleRelationsBoolean() {\n        RealmResults<Owner> owners = testRealm.where(Owner.class).equalTo(\"dogs.hasTail\", true).findAll();\n        assertEquals(1, owners.size());\n\n        RealmResults<Owner> none = testRealm.where(Owner.class).notEqualTo(\"dogs.hasTail\", true).findAll();\n        assertEquals(0, none.size());\n    }\n\n    @Test\n    public void queryMultipleRelationsInteger() {\n        RealmResults<Owner> owners1 = testRealm.where(Owner.class).equalTo(\"dogs.age\", 10).findAll();\n        assertEquals(1, owners1.size());\n\n        RealmResults<Owner> none1 = testRealm.where(Owner.class).equalTo(\"dogs.age\", 7).findAll();\n        assertEquals(0, none1.size());\n\n        RealmResults<Owner> owners2 = testRealm.where(Owner.class).notEqualTo(\"dogs.age\", 10).findAll();\n        assertEquals(1, owners2.size());\n\n        RealmResults<Owner> all1 = testRealm.where(Owner.class).notEqualTo(\"dogs.age\", 7).findAll();\n        assertEquals(1, all1.size());\n\n        RealmResults<Owner> owners3 = testRealm.where(Owner.class).greaterThan(\"dogs.age\", 9).findAll();\n        assertEquals(1, owners3.size());\n\n        RealmResults<Owner> owners4 = testRealm.where(Owner.class).greaterThanOrEqualTo(\"dogs.age\", 9).findAll();\n        assertEquals(1, owners4.size());\n\n        RealmResults<Owner> owners5 = testRealm.where(Owner.class).lessThan(\"dogs.age\", 9).findAll();\n        assertEquals(1, owners5.size());\n\n        RealmResults<Owner> owners6 = testRealm.where(Owner.class).lessThanOrEqualTo(\"dogs.age\", 9).findAll();\n        assertEquals(1, owners6.size());\n\n        RealmResults<Owner> owners7 = testRealm.where(Owner.class).between(\"dogs.age\", 9, 11).findAll();\n        assertEquals(1, owners7.size());\n    }\n\n    @Test\n    public void queryMultipleRelationsDate() {\n        RealmResults<Owner> owners1 = testRealm.where(Owner.class).equalTo(\"dogs.birthday\", new Date(2000)).findAll();\n        assertEquals(1, owners1.size());\n\n        RealmResults<Owner> none1 = testRealm.where(Owner.class).equalTo(\"dogs.birthday\", new Date(7)).findAll();\n        assertEquals(0, none1.size());\n\n        RealmResults<Owner> owners2 = testRealm.where(Owner.class).notEqualTo(\"dogs.birthday\", new Date(10)).findAll();\n        assertEquals(1, owners2.size());\n\n        RealmResults<Owner> all1 = testRealm.where(Owner.class).notEqualTo(\"dogs.birthday\", new Date(7)).findAll();\n        assertEquals(1, all1.size());\n\n        RealmResults<Owner> owners3 = testRealm.where(Owner.class).greaterThan(\"dogs.birthday\", new Date(9)).findAll();\n        assertEquals(1, owners3.size());\n\n        RealmResults<Owner> owners4 = testRealm.where(Owner.class).greaterThanOrEqualTo(\"dogs.birthday\", new Date(9)).findAll();\n        assertEquals(1, owners4.size());\n\n        RealmResults<Owner> owners5 = testRealm.where(Owner.class).lessThan(\"dogs.birthday\", new Date(10000)).findAll();\n        assertEquals(1, owners5.size());\n\n        RealmResults<Owner> owners6 = testRealm.where(Owner.class).lessThanOrEqualTo(\"dogs.birthday\", new Date(10000)).findAll();\n        assertEquals(1, owners6.size());\n\n        RealmResults<Owner> owners7 = testRealm.where(Owner.class).between(\"dogs.birthday\", new Date(1000), new Date(3000)).findAll();\n        assertEquals(1, owners7.size());\n    }\n\n    @Test\n    public void queryMultipleRelationsFloat() {\n        RealmResults<Owner> owners1 = testRealm.where(Owner.class).greaterThanOrEqualTo(\"dogs.height\", 0.2f).findAll();\n        assertEquals(1, owners1.size());\n        assertEquals(12, owners1.first().getCat().getAge());\n\n        RealmResults<Owner> owners2 = testRealm.where(Owner.class).greaterThan(\"dogs.height\", 0.2f).findAll();\n        assertEquals(1, owners2.size());\n        assertEquals(12, owners2.first().getCat().getAge());\n\n        RealmResults<Owner> owners3 = testRealm.where(Owner.class).lessThan(\"dogs.height\", 2.2f).findAll();\n        assertEquals(1, owners3.size());\n        assertEquals(12, owners3.first().getCat().getAge());\n\n        RealmResults<Owner> owners4 = testRealm.where(Owner.class).lessThanOrEqualTo(\"dogs.height\", 2.2f).findAll();\n        assertEquals(1, owners4.size());\n        assertEquals(12, owners4.first().getCat().getAge());\n\n        RealmResults<Owner> owners5 = testRealm.where(Owner.class).notEqualTo(\"dogs.height\", 0.2f).findAll();\n        assertEquals(1, owners5.size());\n        assertEquals(12, owners5.first().getCat().getAge());\n\n        RealmResults<Owner> owners6 = testRealm.where(Owner.class).greaterThanOrEqualTo(\"dogs.height\", 0.3f).findAll();\n        assertEquals(1, owners6.size());\n        assertEquals(12, owners6.first().getCat().getAge());\n\n        RealmResults<Owner> owners7 = testRealm.where(Owner.class).between(\"dogs.height\", 0.2f, 2.2f).findAll();\n        assertEquals(1, owners7.size());\n        assertEquals(12, owners7.first().getCat().getAge());\n    }\n\n    @Test\n    public void queryMultipleRelationsDouble() {\n        RealmResults<Owner> owners1 = testRealm.where(Owner.class).greaterThanOrEqualTo(\"dogs.weight\", 0.2).findAll();\n        assertEquals(1, owners1.size());\n        assertEquals(12, owners1.first().getCat().getAge());\n\n        RealmResults<Owner> owners2 = testRealm.where(Owner.class).greaterThan(\"dogs.weight\", 0.2).findAll();\n        assertEquals(1, owners2.size());\n        assertEquals(12, owners2.first().getCat().getAge());\n\n        RealmResults<Owner> owners3 = testRealm.where(Owner.class).lessThan(\"dogs.weight\", 12.2).findAll();\n        assertEquals(1, owners3.size());\n        assertEquals(12, owners3.first().getCat().getAge());\n\n        RealmResults<Owner> owners4 = testRealm.where(Owner.class).lessThanOrEqualTo(\"dogs.weight\", 12.2).findAll();\n        assertEquals(1, owners4.size());\n        assertEquals(12, owners4.first().getCat().getAge());\n\n        RealmResults<Owner> owners5 = testRealm.where(Owner.class).notEqualTo(\"dogs.weight\", 0.2).findAll();\n        assertEquals(1, owners5.size());\n        assertEquals(12, owners5.first().getCat().getAge());\n\n        RealmResults<Owner> owners6 = testRealm.where(Owner.class).greaterThanOrEqualTo(\"dogs.weight\", 0.3).findAll();\n        assertEquals(1, owners6.size());\n        assertEquals(12, owners6.first().getCat().getAge());\n\n        RealmResults<Owner> owners7 = testRealm.where(Owner.class).between(\"dogs.weight\", 0.2, 12.2).findAll();\n        assertEquals(1, owners7.size());\n        assertEquals(12, owners7.first().getCat().getAge());\n    }\n\n    @Test\n    public void queryMultipleRelationsString() {\n        RealmResults<Owner> owners1 = testRealm.where(Owner.class).equalTo(\"dogs.name\", \"Pluto\").findAll();\n        assertEquals(1, owners1.size());\n\n        RealmResults<Owner> none1 = testRealm.where(Owner.class).equalTo(\"dogs.name\", \"King\").findAll();\n        assertEquals(0, none1.size());\n\n        RealmResults<Owner> owners2 = testRealm.where(Owner.class).notEqualTo(\"dogs.name\", \"King\").findAll();\n        assertEquals(1, owners2.size());\n\n        RealmResults<Owner> none2 = testRealm.where(Owner.class).notEqualTo(\"dogs.name\", \"Pluto\").findAll();\n        assertEquals(0, none1.size());\n\n        RealmResults<Owner> owners3 = testRealm.where(Owner.class).beginsWith(\"dogs.name\", \"Blackie\").findAll();\n        assertEquals(0, owners3.size());\n\n        RealmResults<Owner> owners4 = testRealm.where(Owner.class).endsWith(\"dogs.name\", \"Blackie\").findAll();\n        assertEquals(0, owners4.size());\n\n        RealmResults<Owner> owners5 = testRealm.where(Owner.class).contains(\"dogs.name\", \"Blackie\").findAll();\n        assertEquals(0, owners5.size());\n    }\n\n    @Test\n    public void queryShouldFail() {\n        try {\n            RealmResults<Owner> owners = testRealm.where(Owner.class).equalTo(\"cat..hasTail\", true).findAll();\n            fail(\"Should throw Exception (double dot)\");\n        } catch (IllegalArgumentException ignored) {\n        }\n        try {\n            RealmResults<Owner> owners = testRealm.where(Owner.class).equalTo(\".cat.hasTail\", true).findAll();\n            fail(\"Should throw Exception (initial dot)\");\n        } catch (IllegalArgumentException ignored) {\n        }\n        try {\n            RealmResults<Owner> owners = testRealm.where(Owner.class).equalTo(\"cat.hasTail.\", true).findAll();\n            fail(\"Should throw Exception (final dot)\");\n        } catch (IllegalArgumentException ignored) {\n        }\n        try {\n            RealmResults<Owner> owners = testRealm.where(Owner.class).equalTo(\"not.there\", true).findAll();\n            fail(\"Should throw Exception (non-existent column)\");\n        } catch (IllegalArgumentException ignored) {\n        }\n    }\n\n    @Test\n    public void where() throws Exception {\n        RealmResults<Owner> owners = testRealm.where(Owner.class).findAll();\n        RealmResults<Dog> dogs = owners.first().getDogs().where().equalTo(\"name\", \"Pluto\").findAll();\n        assertEquals(1, dogs.size());\n        assertEquals(\"Pluto\", dogs.first().getName());\n        assertEquals(5, dogs.first().getAge());\n\n        RealmResults<Dog> none = owners.first().getDogs().where().equalTo(\"name\", \"Mars\").findAll();\n        assertEquals(0, none.size());\n    }\n\n    @Test\n    public void subquery() {\n        RealmResults<Owner> owners = testRealm.where(Owner.class).equalTo(\"dogs.name\", \"Pluto\").findAll();\n        RealmResults<Owner> subOwners = owners.where().equalTo(\"cat.name\", \"Blackie\").findAll();\n        assertEquals(1, subOwners.size());\n    }\n\n    @Test\n    public void linkIsNull() {\n        RealmResults<Owner> owners1 = testRealm.where(Owner.class).isNull(\"cat\").findAll();\n        assertEquals(0, owners1.size());\n\n        testRealm.beginTransaction();\n        testRealm.delete(Cat.class);\n        testRealm.commitTransaction();\n\n        RealmResults<Owner> owners2 = testRealm.where(Owner.class).isNull(\"cat\").findAll();\n        assertEquals(1, owners2.size());\n\n        RealmResults<Owner> owners3 = testRealm.where(Owner.class).isNull(\"dogs.birthday\").findAll();\n        assertEquals(0, owners3.size());\n    }\n\n    @Test\n    public void linkIsNotNull() {\n        RealmResults<Owner> owners1 = testRealm.where(Owner.class).isNotNull(\"cat\").findAll();\n        assertEquals(1, owners1.size());\n\n        testRealm.beginTransaction();\n        testRealm.delete(Cat.class);\n        testRealm.commitTransaction();\n\n        RealmResults<Owner> owners2 = testRealm.where(Owner.class).isNotNull(\"cat\").findAll();\n        assertEquals(0, owners2.size());\n\n        RealmResults<Owner> owners3 = testRealm.where(Owner.class).isNotNull(\"dogs.birthday\").findAll();\n        assertEquals(1, owners3.size());\n    }\n\n    @Test\n    public void isEmpty() {\n        RealmResults<Owner> owners1 = testRealm.where(Owner.class).isEmpty(\"cat.name\").findAll();\n        assertEquals(0, owners1.size());\n\n        RealmResults<Owner> owners2 = testRealm.where(Owner.class).isEmpty(\"dogs.name\").findAll();\n        assertEquals(0, owners2.size());\n    }\n\n    @Test\n    public void isNotEmpty() {\n        RealmResults<Owner> owners1 = testRealm.where(Owner.class).isNotEmpty(\"cat.name\").findAll();\n        assertEquals(1, owners1.size());\n\n        RealmResults<Owner> owners2 = testRealm.where(Owner.class).isNotEmpty(\"dogs.name\").findAll();\n        assertEquals(1, owners2.size());\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/RealmListTests.java",
    "content": "/*\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\npackage io.realm;\n\nimport androidx.test.ext.junit.runners.AndroidJUnit4;\n\nimport org.hamcrest.CoreMatchers;\nimport org.junit.After;\nimport org.junit.Before;\nimport org.junit.Rule;\nimport org.junit.Test;\nimport org.junit.rules.ExpectedException;\nimport org.junit.runner.RunWith;\n\nimport java.util.Collections;\nimport java.util.List;\nimport java.util.concurrent.CountDownLatch;\nimport java.util.concurrent.atomic.AtomicInteger;\nimport java.util.concurrent.atomic.AtomicReference;\n\nimport io.realm.entities.AllTypes;\nimport io.realm.entities.Cat;\nimport io.realm.entities.CyclicType;\nimport io.realm.entities.CyclicTypePrimaryKey;\nimport io.realm.entities.Dog;\nimport io.realm.entities.Owner;\nimport io.realm.internal.RealmObjectProxy;\nimport io.realm.rule.RunInLooperThread;\nimport io.realm.rule.RunTestInLooperThread;\n\nimport static org.junit.Assert.assertEquals;\nimport static org.junit.Assert.assertFalse;\nimport static org.junit.Assert.assertNotNull;\nimport static org.junit.Assert.assertNull;\nimport static org.junit.Assert.assertThat;\nimport static org.junit.Assert.assertTrue;\nimport static org.junit.Assert.fail;\n\n/**\n * Unit tests specific for RealmList that cannot be covered by {@link OrderedRealmCollectionTests},\n * {@link ManagedRealmCollectionTests}, {@link UnManagedRealmCollectionTests} or {@link RealmCollectionTests}.\n */\n@RunWith(AndroidJUnit4.class)\npublic class RealmListTests extends CollectionTests {\n\n    private static final int TEST_SIZE = 10;\n\n    @Rule\n    public final TestRealmConfigurationFactory configFactory = new TestRealmConfigurationFactory();\n    @Rule\n    public ExpectedException thrown = ExpectedException.none();\n    @Rule\n    public final RunInLooperThread looperThread = new RunInLooperThread();\n\n    private Realm realm;\n    private RealmList<Dog> collection;\n\n    @Before\n    public void setUp() throws Exception {\n        RealmConfiguration realmConfig = configFactory.createConfiguration();\n        realm = Realm.getInstance(realmConfig);\n\n        realm.beginTransaction();\n        Owner owner = realm.createObject(Owner.class);\n        owner.setName(\"Owner\");\n        for (int i = 0; i < TEST_SIZE; i++) {\n            Dog dog = realm.createObject(Dog.class);\n            dog.setName(\"Dog \" + i);\n            owner.getDogs().add(dog);\n        }\n        realm.commitTransaction();\n        collection = owner.getDogs();\n    }\n\n    @After\n    public void tearDown() throws Exception {\n        if (realm != null) {\n            realm.close();\n        }\n    }\n\n    private RealmList<Dog> createUnmanagedDogList() {\n        RealmList<Dog> list = new RealmList<Dog>();\n        for (int i = 0; i < TEST_SIZE; i++) {\n            list.add(new Dog(\"Dog \" + i));\n        }\n        return list;\n    }\n\n    private RealmList<Dog> createDeletedRealmList() {\n        Owner owner = realm.where(Owner.class).findFirst();\n        //noinspection ConstantConditions\n        RealmList<Dog> dogs = owner.getDogs();\n\n        realm.beginTransaction();\n        owner.deleteFromRealm();\n        realm.commitTransaction();\n        return dogs;\n    }\n\n    //noinspection TryWithIdenticalCatches\n    /*********************************************************\n     * Unmanaged mode tests                                  *\n     *********************************************************/\n\n    @Test(expected = IllegalArgumentException.class)\n    public void constructor_unmanaged_null() {\n        AllTypes[] args = null;\n        //noinspection ConstantConditions\n        new RealmList<AllTypes>(args);\n    }\n\n    @Test\n    public void isValid_unmanagedMode() {\n        //noinspection MismatchedQueryAndUpdateOfCollection\n        RealmList<AllTypes> list = new RealmList<AllTypes>();\n        assertTrue(list.isValid());\n    }\n\n    @Test\n    public void add_unmanagedMode() {\n        RealmList<AllTypes> list = new RealmList<AllTypes>();\n        AllTypes object = new AllTypes();\n        object.setColumnString(\"String\");\n        list.add(object);\n        assertEquals(1, list.size());\n        assertEquals(object, list.get(0));\n    }\n\n    @Test\n    public void add_nullInUnmanagedMode() {\n        final RealmList<AllTypes> list = new RealmList<>();\n        assertTrue(list.add(null));\n        assertEquals(1, list.size());\n    }\n\n    @Test\n    public void add_managedObjectInUnmanagedMode() {\n        RealmList<AllTypes> list = new RealmList<AllTypes>();\n        realm.beginTransaction();\n        AllTypes managedAllTypes = realm.createObject(AllTypes.class);\n        realm.commitTransaction();\n        list.add(managedAllTypes);\n\n        assertEquals(managedAllTypes, list.get(0));\n    }\n\n    @Test\n    public void add_unmanagedObjectAtIndexInUnmanagedMode() {\n        RealmList<AllTypes> list = new RealmList<AllTypes>();\n        AllTypes object = new AllTypes();\n        object.setColumnString(\"String\");\n        list.add(0, object);\n        assertEquals(1, list.size());\n        assertEquals(object, list.get(0));\n    }\n\n    @Test\n    public void add_managedObjectAtIndexInUnmanagedMode() {\n        RealmList<AllTypes> list = new RealmList<AllTypes>();\n        list.add(new AllTypes());\n        realm.beginTransaction();\n        AllTypes managedAllTypes = realm.createObject(AllTypes.class);\n        realm.commitTransaction();\n        list.add(0, managedAllTypes);\n\n        assertEquals(managedAllTypes, list.get(0));\n    }\n\n    @Test\n    public void add_objectAtIndexInManagedMode() {\n        realm.beginTransaction();\n        Dog obj = collection.get(0);\n        collection.add(0, new Dog(\"Dog 42\"));\n        realm.commitTransaction();\n        assertEquals(obj.getName(), collection.get(1).getName());\n        assertEquals(\"Dog 42\", collection.get(0).getName());\n    }\n\n    @Test\n    public void add_objectAtInvalidIndexInManagedModeThrows() {\n        final int initialDogCount = realm.where(Dog.class).findAll().size();\n\n        realm.beginTransaction();\n        try {\n            final int invalidIndex = collection.size() + 1;\n            collection.add(invalidIndex, new Dog(\"Dog 42\"));\n            fail();\n        } catch (IndexOutOfBoundsException e) {\n            assertEquals(initialDogCount, realm.where(Dog.class).findAll().size());\n        }\n    }\n\n    @Test\n    public void add_nullAtIndexInUnmanagedMode() {\n        final RealmList<AllTypes> list = new RealmList<>();\n        list.add(0, null);\n        assertEquals(1, list.size());\n    }\n\n    @Test\n    public void set_unmanagedMode() {\n        RealmList<Dog> list = new RealmList<Dog>();\n        Dog dog1 = new Dog(\"dog1\");\n        Dog dog2 = new Dog(\"dog2\");\n        list.add(dog1);\n        assertEquals(dog1, list.set(0, dog2));\n        assertEquals(1, list.size());\n    }\n\n    @Test\n    public void set_managedMode() {\n        realm.beginTransaction();\n        try {\n            RealmList<Dog> list = realm.createObject(Owner.class).getDogs();\n            Dog dog1 = realm.createObject(Dog.class);\n            dog1.setName(\"dog1\");\n            Dog dog2 = realm.createObject(Dog.class);\n            dog2.setName(\"dog2\");\n            list.add(dog1);\n            assertEquals(dog1, list.set(0, dog2));\n            assertEquals(1, list.size());\n        } finally {\n            realm.cancelTransaction();\n        }\n    }\n\n    @Test\n    public void set_nullInUnmanagedMode() {\n        RealmList<AllTypes> list = new RealmList<>();\n        list.add(new AllTypes());\n        assertNotNull(list.set(0, null));\n    }\n\n    @Test\n    public void set_managedObjectInUnmanagedMode() {\n        RealmList<AllTypes> list = new RealmList<AllTypes>();\n        list.add(new AllTypes());\n        realm.beginTransaction();\n        AllTypes managedAllTypes = realm.createObject(AllTypes.class);\n        realm.commitTransaction();\n        list.set(0, managedAllTypes);\n\n        assertEquals(managedAllTypes, list.get(0));\n    }\n\n    @Test\n    public void clear_unmanagedMode() {\n        RealmList<AllTypes> list = new RealmList<AllTypes>();\n        list.add(new AllTypes());\n        assertEquals(1, list.size());\n        list.clear();\n        assertTrue(list.isEmpty());\n    }\n\n    @Test\n    public void remove_unmanagedMode() {\n        RealmList<AllTypes> list = new RealmList<AllTypes>();\n        AllTypes object1 = new AllTypes();\n        list.add(object1);\n        AllTypes object2 = list.remove(0);\n        assertEquals(object1, object2);\n    }\n\n    // Tests move where oldPosition > newPosition.\n    @Test\n    public void move_down() {\n        Owner owner = realm.where(Owner.class).findFirst();\n        Dog dog1 = owner.getDogs().get(1);\n        Dog dog2 = owner.getDogs().get(0);\n        realm.beginTransaction();\n        owner.getDogs().move(1, 0);\n        realm.commitTransaction();\n\n        assertEquals(TEST_SIZE, owner.getDogs().size());\n        assertEquals(0, owner.getDogs().indexOf(dog1));\n        assertEquals(1, owner.getDogs().indexOf(dog2));\n    }\n\n    // Tests move where oldPosition < newPosition.\n    @Test\n    public void move_up() {\n        Owner owner = realm.where(Owner.class).findFirst();\n        Dog dog1 = owner.getDogs().get(0);\n        Dog dog2 = owner.getDogs().get(1);\n        realm.beginTransaction();\n        owner.getDogs().move(0, 1);\n        realm.commitTransaction();\n\n        assertEquals(TEST_SIZE, owner.getDogs().size());\n        assertEquals(1, owner.getDogs().indexOf(dog1));\n        assertEquals(0, owner.getDogs().indexOf(dog2));\n    }\n\n    // Tests move where oldPosition > newPosition.\n    @Test\n    public void move_downInUnmanagedMode() {\n        RealmList<Dog> dogs = createUnmanagedDogList();\n        Dog dog1 = dogs.get(1);\n        Dog dog2 = dogs.get(0);\n\n        dogs.move(1, 0);\n\n        assertEquals(TEST_SIZE, dogs.size());\n        assertEquals(0, dogs.indexOf(dog1));\n        assertEquals(1, dogs.indexOf(dog2));\n    }\n\n    // Tests move where oldPosition < newPosition.\n    @Test\n    public void move_upInUnmanagedMode() {\n        RealmList<Dog> dogs = createUnmanagedDogList();\n        Dog dog1 = dogs.get(0);\n        Dog dog2 = dogs.get(1);\n\n        dogs.move(0, 1);\n\n        assertEquals(TEST_SIZE, dogs.size());\n        assertEquals(1, dogs.indexOf(dog1));\n        assertEquals(0, dogs.indexOf(dog2));\n    }\n\n    /*********************************************************\n     * Managed mode tests                                    *\n     *********************************************************/\n\n    @Test\n    public void isValid() {\n        Owner owner = realm.where(Owner.class).findFirst();\n        RealmList<Dog> dogs = owner.getDogs();\n\n        assertTrue(dogs.isValid());\n\n        realm.close();\n        assertFalse(dogs.isValid());\n    }\n\n    @Test\n    public void isValid_whenParentRemoved() {\n        Owner owner = realm.where(Owner.class).findFirst();\n        RealmList<Dog> dogs = owner.getDogs();\n\n        realm.beginTransaction();\n        owner.deleteFromRealm();\n        realm.commitTransaction();\n\n        // RealmList contained in removed object is invalid.\n        assertFalse(dogs.isValid());\n    }\n\n    @Test\n    public void move_outOfBoundsLowerThrows() {\n        Owner owner = realm.where(Owner.class).findFirst();\n        realm.beginTransaction();\n        try {\n            owner.getDogs().move(0, -1);\n            fail(\"Indexes < 0 should throw an exception\");\n        } catch (IndexOutOfBoundsException ignored) {\n        } finally {\n            realm.cancelTransaction();\n        }\n    }\n\n    @Test\n    public void move_outOfBoundsHigherThrows() {\n        Owner owner = realm.where(Owner.class).findFirst();\n        realm.beginTransaction();\n        try {\n            int lastIndex = TEST_SIZE - 1;\n            int outOfBoundsIndex = TEST_SIZE;\n            owner.getDogs().move(lastIndex, outOfBoundsIndex);\n            fail(\"Indexes >= size() should throw an exception\");\n        } catch (IndexOutOfBoundsException ignored) {\n            ignored.printStackTrace();\n        } finally {\n            realm.cancelTransaction();\n        }\n    }\n\n    @Test\n    public void add_managedObjectToManagedList() {\n        realm.beginTransaction();\n        realm.delete(Owner.class);\n        Owner owner = realm.createObject(Owner.class);\n        Dog dog = realm.createObject(Dog.class);\n        owner.getDogs().add(dog);\n        realm.commitTransaction();\n\n        assertEquals(1, realm.where(Owner.class).findFirst().getDogs().size());\n    }\n\n    // Tests that add correctly uses Realm.copyToRealm() on unmanaged objects.\n    @Test\n    public void add_unmanagedObjectToManagedList() {\n        realm.beginTransaction();\n        CyclicType parent = realm.createObject(CyclicType.class);\n        RealmList<CyclicType> children = parent.getObjects();\n        children.add(new CyclicType());\n        realm.commitTransaction();\n        assertEquals(1, realm.where(CyclicType.class).findFirst().getObjects().size());\n    }\n\n    // Makes sure that unmanaged objects with a primary key are added using copyToRealmOrUpdate.\n    @Test\n    public void add_unmanagedPrimaryKeyObjectToManagedList() {\n        realm.beginTransaction();\n        realm.copyToRealm(new CyclicTypePrimaryKey(2, \"original\"));\n        RealmList<CyclicTypePrimaryKey> children = realm.copyToRealm(new CyclicTypePrimaryKey(1)).getObjects();\n        children.add(new CyclicTypePrimaryKey(2, \"new\"));\n        realm.commitTransaction();\n\n        assertEquals(1, realm.where(CyclicTypePrimaryKey.class).equalTo(\"id\", 1).findFirst().getObjects().size());\n        assertEquals(\"new\", realm.where(CyclicTypePrimaryKey.class).equalTo(\"id\", 2).findFirst().getName());\n    }\n\n    // Tests that set correctly uses Realm.copyToRealm() on unmanaged objects.\n    @Test\n    public void set_unmanagedObjectToManagedList() {\n        realm.beginTransaction();\n        CyclicType parent = realm.copyToRealm(new CyclicType(\"Parent\"));\n        RealmList<CyclicType> children = parent.getObjects();\n        children.add(new CyclicType());\n        children.add(new CyclicType(\"original\"));\n        children.add(new CyclicType());\n        children.set(1, new CyclicType(\"updated\"));\n        realm.commitTransaction();\n\n        RealmList<CyclicType> list = realm.where(CyclicType.class).findFirst().getObjects();\n        assertEquals(3, list.size());\n        assertEquals(\"updated\", list.get(1).getName());\n        assertEquals(5, realm.where(CyclicType.class).count());\n    }\n\n    // Tests that set correctly uses Realm.copyToRealmOrUpdate() on unmanaged objects with a primary key.\n    @Test\n    public void set_unmanagedPrimaryKeyObjectToManagedList() {\n        realm.beginTransaction();\n        CyclicTypePrimaryKey parent = realm.copyToRealm(new CyclicTypePrimaryKey(1, \"Parent\"));\n        RealmList<CyclicTypePrimaryKey> children = parent.getObjects();\n        children.add(new CyclicTypePrimaryKey(2));\n        children.add(new CyclicTypePrimaryKey(3, \"original\"));\n        children.add(new CyclicTypePrimaryKey(4));\n        children.set(1, new CyclicTypePrimaryKey(3, \"updated\"));\n        realm.commitTransaction();\n\n        RealmList<CyclicTypePrimaryKey> list = realm.where(CyclicTypePrimaryKey.class).findFirst().getObjects();\n        assertEquals(3, list.size());\n        assertEquals(\"updated\", list.get(1).getName());\n    }\n\n    @Test\n    public void add_nullToManagedListThrows() {\n        realm.beginTransaction();\n        Owner owner = realm.createObject(Owner.class);\n        thrown.expect(IllegalArgumentException.class);\n        owner.getDogs().add(null);\n    }\n\n    @Test\n    public void size() {\n        Owner owner = realm.where(Owner.class).findFirst();\n        assertEquals(TEST_SIZE, owner.getDogs().size());\n    }\n\n    @Test\n    public void getObjects() {\n        Owner owner = realm.where(Owner.class).findFirst();\n        RealmList<Dog> dogs = owner.getDogs();\n\n        assertNotNull(dogs);\n        assertEquals(\"Dog 1\", dogs.get(1).getName());\n    }\n\n    @Test\n    public void remove_byIndex() {\n        Owner owner = realm.where(Owner.class).findFirst();\n        RealmList<Dog> dogs = owner.getDogs();\n        Dog dog5 = dogs.get(5);\n\n        realm.beginTransaction();\n        Dog removedDog = dogs.remove(5);\n        realm.commitTransaction();\n\n        assertEquals(dog5, removedDog);\n        assertEquals(TEST_SIZE - 1, dogs.size());\n        assertEquals(TEST_SIZE, realm.where(Dog.class).count());\n    }\n\n    @Test\n    public void remove_first() {\n        Owner owner = realm.where(Owner.class).findFirst();\n        RealmList<Dog> dogs = owner.getDogs();\n\n        realm.beginTransaction();\n        dogs.remove(0);\n        realm.commitTransaction();\n\n        assertEquals(TEST_SIZE - 1, dogs.size());\n        assertEquals(TEST_SIZE, realm.where(Dog.class).count());\n    }\n\n    @Test\n    public void remove_last() {\n        Owner owner = realm.where(Owner.class).findFirst();\n        RealmList<Dog> dogs = owner.getDogs();\n\n        realm.beginTransaction();\n        dogs.remove(TEST_SIZE - 1);\n        realm.commitTransaction();\n\n        assertEquals(TEST_SIZE - 1, dogs.size());\n        assertEquals(TEST_SIZE, realm.where(Dog.class).count());\n    }\n\n    @Test\n    public void remove_fromEmptyListThrows() {\n        Owner owner = realm.where(Owner.class).findFirst();\n        RealmList<Dog> dogs = owner.getDogs();\n\n        realm.beginTransaction();\n        dogs.clear();\n        thrown.expect(IndexOutOfBoundsException.class);\n        dogs.remove(0);\n    }\n\n    @Test\n    public void remove_byObject() {\n        Owner owner = realm.where(Owner.class).findFirst();\n        RealmList<Dog> dogs = owner.getDogs();\n        Dog dog = dogs.get(0);\n\n        realm.beginTransaction();\n        boolean result = dogs.remove(dog);\n        realm.commitTransaction();\n\n        assertTrue(result);\n        assertEquals(TEST_SIZE - 1, dogs.size());\n        assertEquals(TEST_SIZE, realm.where(Dog.class).count());\n    }\n\n    @Test\n    public void add_atAfterContainerObjectRemoved() {\n        RealmList<Dog> dogs = createDeletedRealmList();\n\n        realm.beginTransaction();\n        Dog dog = realm.createObject(Dog.class);\n        dog.setName(\"Dog\");\n        thrown.expect(IllegalStateException.class);\n        dogs.add(0, dog);\n    }\n\n    @Test\n    public void add_afterContainerObjectRemoved() {\n        RealmList<Dog> dogs = createDeletedRealmList();\n\n        realm.beginTransaction();\n        Dog dog = realm.createObject(Dog.class);\n        dog.setName(\"Dog\");\n        thrown.expect(IllegalStateException.class);\n        dogs.add(dog);\n    }\n\n    @Test\n    public void set_afterContainerObjectRemoved() {\n        RealmList<Dog> dogs = createDeletedRealmList();\n\n        realm.beginTransaction();\n        Dog dog = realm.createObject(Dog.class);\n        dog.setName(\"Dog\");\n        thrown.expect(IllegalStateException.class);\n        dogs.set(0, dog);\n    }\n\n    @Test\n    public void move_afterContainerObjectRemoved() {\n        RealmList<Dog> dogs = createDeletedRealmList();\n\n        realm.beginTransaction();\n        thrown.expect(IllegalStateException.class);\n        dogs.move(0, 1);\n    }\n\n    @Test\n    public void clear_afterContainerObjectRemoved() {\n        RealmList<Dog> dogs = createDeletedRealmList();\n\n        realm.beginTransaction();\n        thrown.expect(IllegalStateException.class);\n        dogs.clear();\n    }\n\n    @Test\n    public void remove_atAfterContainerObjectRemoved() {\n        RealmList<Dog> dogs = createDeletedRealmList();\n\n        realm.beginTransaction();\n        Dog dog = realm.createObject(Dog.class);\n        dog.setName(\"Dog\");\n        thrown.expect(IllegalStateException.class);\n        dogs.remove(0);\n    }\n\n    @Test\n    public void remove_objectAfterContainerObjectRemoved() {\n        RealmList<Dog> dogs = createDeletedRealmList();\n\n        realm.beginTransaction();\n        Dog dog = realm.createObject(Dog.class);\n        dog.setName(\"Dog\");\n        thrown.expect(IllegalStateException.class);\n        dogs.remove(dog);\n    }\n\n    @Test\n    public void removeAll_managedMode() {\n        realm.beginTransaction();\n        List<Dog> objectsToRemove = Collections.singletonList(collection.get(0));\n        assertTrue(collection.removeAll(objectsToRemove));\n        assertFalse(collection.contains(objectsToRemove.get(0)));\n    }\n\n    @Test\n    @SuppressWarnings(\"CollectionIncompatibleType\")\n    public void removeAll_managedMode_wrongClass() {\n        realm.beginTransaction();\n        //noinspection SuspiciousMethodCalls\n        assertFalse(collection.removeAll(Collections.singletonList(new Cat())));\n    }\n\n    @Test\n    @SuppressWarnings(\"CollectionIncompatibleType\")\n    public void removeAll_unmanaged_wrongClass() {\n        RealmList<Dog> list = createUnmanagedDogList();\n        //noinspection SuspiciousMethodCalls\n        assertFalse(list.removeAll(Collections.singletonList(new Cat())));\n    }\n\n    @Test\n    public void removeAll_afterContainerObjectRemoved() {\n        RealmList<Dog> dogs = createDeletedRealmList();\n\n        realm.beginTransaction();\n        thrown.expect(IllegalStateException.class);\n        dogs.removeAll(Collections.<Dog>emptyList());\n    }\n\n    @Test\n    public void removeAll_outsideTransaction() {\n        List<Dog> objectsToRemove = Collections.singletonList(collection.get(0));\n        thrown.expect(IllegalStateException.class);\n        thrown.expectMessage(CoreMatchers.containsString(\"Objects can only be removed from inside a write transaction\"));\n        collection.removeAll(objectsToRemove);\n    }\n\n    @Test\n    public void get_afterContainerObjectRemoved() {\n        RealmList<Dog> dogs = createDeletedRealmList();\n        thrown.expect(IllegalStateException.class);\n        dogs.get(0);\n    }\n\n    @Test\n    public void first_afterContainerObjectRemoved() {\n        RealmList<Dog> dogs = createDeletedRealmList();\n\n        thrown.expect(IllegalStateException.class);\n        dogs.first();\n    }\n\n    @Test\n    public void last_afterContainerObjectRemoved() {\n        RealmList<Dog> dogs = createDeletedRealmList();\n\n        thrown.expect(IllegalStateException.class);\n        dogs.last();\n    }\n\n    @Test\n    public void size_afterContainerObjectRemoved() {\n        RealmList<Dog> dogs = createDeletedRealmList();\n\n        thrown.expect(IllegalStateException.class);\n        dogs.size();\n    }\n\n    @Test\n    public void where_afterContainerObjectRemoved() {\n        RealmList<Dog> dogs = createDeletedRealmList();\n\n        thrown.expect(IllegalStateException.class);\n        dogs.where();\n    }\n\n    @Test\n    public void toString_AfterContainerObjectRemoved() {\n        RealmList<Dog> dogs = createDeletedRealmList();\n        assertEquals(\"RealmList<Dog>@[invalid]\", dogs.toString());\n    }\n\n    @Test\n    public void toString_managedMode() {\n        StringBuilder sb = new StringBuilder(\"RealmList<Dog>@[\");\n        for (int i = 0; i < collection.size() - 1; i++) {\n            sb.append(((RealmObjectProxy) (collection.get(i))).realmGet$proxyState().getRow$realm().getObjectKey());\n            sb.append(\",\");\n        }\n        sb.append(((RealmObjectProxy)collection.get(TEST_SIZE - 1)).realmGet$proxyState().getRow$realm().getObjectKey());\n        sb.append(\"]\");\n\n        assertEquals(sb.toString(), collection.toString());\n    }\n\n    @Test\n    public void query() {\n        Owner owner = realm.where(Owner.class).findFirst();\n        RealmList<Dog> dogs = owner.getDogs();\n        Dog firstDog = dogs.where().equalTo(\"name\", \"Dog 0\").findFirst();\n\n        assertNotNull(firstDog);\n    }\n\n    @Test\n    public void clear() {\n        Owner owner = realm.where(Owner.class).findFirst();\n        realm.beginTransaction();\n        assertEquals(TEST_SIZE, owner.getDogs().size());\n        owner.getDogs().clear();\n        assertEquals(0, owner.getDogs().size());\n        realm.commitTransaction();\n    }\n\n    @Test\n    public void clear_notDeleting() {\n        Owner owner = realm.where(Owner.class).findFirst();\n        realm.beginTransaction();\n        assertEquals(TEST_SIZE, realm.where(Dog.class).count());\n        owner.getDogs().clear();\n        assertEquals(TEST_SIZE, realm.where(Dog.class).count());\n        realm.commitTransaction();\n    }\n\n    @Test\n    public void setList_clearsOldItems() {\n        realm.beginTransaction();\n        CyclicType one = realm.copyToRealm(new CyclicType());\n        CyclicType two = realm.copyToRealm(new CyclicType());\n\n        assertEquals(0, two.getObjects().size());\n        two.setObjects(new RealmList<CyclicType>(one));\n        assertEquals(1, two.getObjects().size());\n        two.setObjects(new RealmList<CyclicType>(one, two));\n        assertEquals(2, two.getObjects().size());\n    }\n\n    @Test\n    public void realmMethods_onDeletedLinkView() {\n        OrderedRealmCollection<CyclicType> results = populateCollectionOnDeletedLinkView(realm, ManagedCollection.MANAGED_REALMLIST);\n\n        for (RealmCollectionMethod method : RealmCollectionMethod.values()) {\n            try {\n                switch (method) {\n                    case WHERE: results.where(); break;\n                    case MIN: results.min(CyclicType.FIELD_ID); break;\n                    case MAX: results.max(CyclicType.FIELD_ID); break;\n                    case SUM: results.sum(CyclicType.FIELD_ID); break;\n                    case AVERAGE: results.average(CyclicType.FIELD_ID); break;\n                    case MIN_DATE: results.minDate(CyclicType.FIELD_DATE); break;\n                    case MAX_DATE: results.maxDate(CyclicType.FIELD_DATE); break;\n                    case DELETE_ALL_FROM_REALM: results.deleteAllFromRealm(); break;\n                    case IS_VALID: continue; // Does not throw.\n                    case IS_MANAGED: continue; // Does not throw.\n                    case IS_FROZEN: continue; // Does not throw\n                    case FREEZE: results.freeze(); break;\n                }\n                fail(method + \" should have thrown an Exception.\");\n            } catch (IllegalStateException ignored) {\n            }\n        }\n\n        for (OrderedRealmCollectionMethod method : OrderedRealmCollectionMethod.values()) {\n            realm.beginTransaction();\n            try {\n                switch (method) {\n                    case DELETE_INDEX: results.deleteFromRealm(0); break;\n                    case DELETE_FIRST: results.deleteFirstFromRealm(); break;\n                    case DELETE_LAST: results.deleteLastFromRealm(); break;\n                    case SORT: results.sort(CyclicType.FIELD_NAME); break;\n                    case SORT_FIELD: results.sort(CyclicType.FIELD_NAME, Sort.ASCENDING); break;\n                    case SORT_2FIELDS: results.sort(CyclicType.FIELD_NAME, Sort.ASCENDING, CyclicType.FIELD_DATE, Sort.DESCENDING); break;\n                    case SORT_MULTI: results.sort(new String[] { CyclicType.FIELD_NAME, CyclicType.FIELD_DATE }, new Sort[] { Sort.ASCENDING, Sort.DESCENDING}); break;\n                    case CREATE_SNAPSHOT: results.createSnapshot(); break;\n                }\n                fail(method + \" should have thrown an Exception\");\n            } catch (IllegalStateException ignored) {\n            } finally {\n                realm.cancelTransaction();\n            }\n        }\n    }\n\n    @Test\n    public void add_set_objectFromOtherThread() {\n        final CountDownLatch finishedLatch = new CountDownLatch(1);\n        final Dog dog = realm.where(Dog.class).findFirst();\n        final String expectedMsg = \"Cannot pass an object from another Realm instance.\";\n\n        new Thread(new Runnable() {\n            @Override\n            public void run() {\n                Realm realm = Realm.getInstance(RealmListTests.this.realm.getConfiguration());\n                realm.beginTransaction();\n                RealmList<Dog> list = realm.createObject(Owner.class).getDogs();\n                list.add(realm.createObject(Dog.class));\n                try {\n                    list.add(dog);\n                    fail();\n                } catch (IllegalArgumentException expected) {\n                    assertEquals(expectedMsg, expected.getMessage());\n                }\n\n                try {\n                    list.add(0, dog);\n                    fail();\n                } catch (IllegalArgumentException expected) {\n                    assertEquals(expectedMsg, expected.getMessage());\n                }\n\n                try {\n                    list.set(0, dog);\n                    fail();\n                } catch (IllegalArgumentException expected) {\n                    assertEquals(expectedMsg, expected.getMessage());\n                }\n\n                realm.cancelTransaction();\n                realm.close();\n                finishedLatch.countDown();\n            }\n        }).start();\n        TestHelper.awaitOrFail(finishedLatch);\n    }\n\n    @Test\n    public void add_set_dynamicObjectFromOtherThread() throws Throwable {\n        final CountDownLatch finishedLatch = new CountDownLatch(1);\n        DynamicRealm dynamicRealm = DynamicRealm.getInstance(realm.getConfiguration());\n        final DynamicRealmObject dynDog = dynamicRealm.where(Dog.CLASS_NAME).findFirst();\n        final String expectedMsg = \"Cannot pass an object to a Realm instance created in another thread.\";\n\n        final AtomicReference<Throwable> thrownErrorRef = new AtomicReference<>();\n\n        new Thread(new Runnable() {\n            @Override\n            public void run() {\n                DynamicRealm dynamicRealm = DynamicRealm.getInstance(realm.getConfiguration());\n                dynamicRealm.beginTransaction();\n                try {\n                    RealmList<DynamicRealmObject> list = dynamicRealm.createObject(Owner.CLASS_NAME)\n                            .getList(Owner.FIELD_DOGS);\n                    list.add(dynamicRealm.createObject(Dog.CLASS_NAME));\n\n                    try {\n                        list.add(dynDog);\n                        fail();\n                    } catch (IllegalStateException expected) {\n                        assertEquals(expectedMsg, expected.getMessage());\n                    }\n\n                    try {\n                        list.add(0, dynDog);\n                        fail();\n                    } catch (IllegalStateException expected) {\n                        assertEquals(expectedMsg, expected.getMessage());\n                    }\n\n                    try {\n                        list.set(0, dynDog);\n                        fail();\n                    } catch (IllegalStateException expected) {\n                        assertEquals(expectedMsg, expected.getMessage());\n                    }\n                } catch (Throwable throwable) {\n                    thrownErrorRef.set(throwable);\n                } finally {\n                    dynamicRealm.cancelTransaction();\n                    dynamicRealm.close();\n                    finishedLatch.countDown();\n                }\n            }\n        }).start();\n        TestHelper.awaitOrFail(finishedLatch);\n        dynamicRealm.close();\n\n        final Throwable thrown = thrownErrorRef.get();\n        if (thrown != null) {\n            throw thrown;\n        }\n    }\n\n    @Test\n    public void add_set_withWrongDynamicObjectType() {\n        final String expectedMsg = \"The object has a different type from list's. Type of the list is 'Dog',\" +\n                        \" type of object is 'Cat'.\";\n        DynamicRealm dynamicRealm = DynamicRealm.getInstance(realm.getConfiguration());\n\n        dynamicRealm.beginTransaction();\n        RealmList<DynamicRealmObject> list = dynamicRealm.createObject(Owner.CLASS_NAME)\n                .getList(Owner.FIELD_DOGS);\n        list.add(dynamicRealm.createObject(Dog.CLASS_NAME));\n        DynamicRealmObject dynCat = dynamicRealm.createObject(Cat.CLASS_NAME);\n\n        try {\n            list.add(dynCat);\n            fail();\n        } catch (IllegalArgumentException expected) {\n            assertEquals(expectedMsg, expected.getMessage());\n\n        }\n\n        try {\n            list.add(0, dynCat);\n            fail();\n        } catch (IllegalArgumentException expected) {\n            assertEquals(expectedMsg, expected.getMessage());\n\n        }\n\n        try {\n            list.set(0, dynCat);\n            fail();\n        } catch (IllegalArgumentException expected) {\n            assertEquals(expectedMsg, expected.getMessage());\n\n        }\n\n        dynamicRealm.cancelTransaction();\n        dynamicRealm.close();\n    }\n\n    @Test\n    public void add_set_dynamicObjectCreatedFromTypedRealm() {\n        final String expectedMsg = \"Cannot pass DynamicRealmObject between Realm instances.\";\n        //noinspection ConstantConditions\n        DynamicRealmObject dynDog = new DynamicRealmObject(realm.where(Dog.class).findFirst());\n        DynamicRealm dynamicRealm = DynamicRealm.getInstance(realm.getConfiguration());\n\n        dynamicRealm.beginTransaction();\n        RealmList<DynamicRealmObject> list = dynamicRealm.createObject(Owner.CLASS_NAME)\n                .getList(Owner.FIELD_DOGS);\n        list.add(dynamicRealm.createObject(Dog.CLASS_NAME));\n\n        try {\n            list.add(dynDog);\n            fail();\n        } catch (IllegalArgumentException expected) {\n            assertEquals(expectedMsg, expected.getMessage());\n        }\n\n        try {\n            list.add(0, dynDog);\n            fail();\n        } catch (IllegalArgumentException expected) {\n            assertEquals(expectedMsg, expected.getMessage());\n        }\n\n        try {\n            list.set(0, dynDog);\n            fail();\n        } catch (IllegalArgumentException expected) {\n            assertEquals(expectedMsg, expected.getMessage());\n        }\n\n        dynamicRealm.cancelTransaction();\n        dynamicRealm.close();\n    }\n\n    private RealmList<Dog> prepareRealmListInLooperThread() {\n        Realm realm = looperThread.getRealm();\n        realm.beginTransaction();\n        Owner owner = realm.createObject(Owner.class);\n        owner.setName(\"Owner\");\n        for (int i = 0; i < TEST_SIZE; i++) {\n            Dog dog = realm.createObject(Dog.class);\n            dog.setName(\"Dog \" + i);\n            owner.getDogs().add(dog);\n        }\n        realm.commitTransaction();\n        return owner.getDogs();\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void addChangeListener() {\n        collection = prepareRealmListInLooperThread();\n        Realm realm = looperThread.getRealm();\n        final AtomicInteger listenerCalledCount = new AtomicInteger(0);\n        collection.addChangeListener(new RealmChangeListener<RealmList<Dog>>() {\n            @Override\n            public void onChange(RealmList<Dog> element) {\n                assertEquals(0, listenerCalledCount.getAndIncrement());\n            }\n        });\n        collection.addChangeListener(new OrderedRealmCollectionChangeListener<RealmList<Dog>>() {\n            @Override\n            public void onChange(RealmList<Dog> collection, OrderedCollectionChangeSet changes) {\n                assertEquals(1, listenerCalledCount.getAndIncrement());\n            }\n        });\n        realm.beginTransaction();\n        collection.get(0).setAge(42);\n        realm.commitTransaction();\n\n        // This should trigger the listener.\n        realm.beginTransaction();\n        realm.cancelTransaction();\n        assertEquals(2, listenerCalledCount.get());\n        looperThread.testComplete();\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void removeAllChangeListeners() {\n        collection = prepareRealmListInLooperThread();\n        Realm realm = looperThread.getRealm();\n        final AtomicInteger listenerCalledCount = new AtomicInteger(0);\n        collection.addChangeListener(new RealmChangeListener<RealmList<Dog>>() {\n            @Override\n            public void onChange(RealmList<Dog> element) {\n                fail();\n            }\n        });\n        collection.addChangeListener(new OrderedRealmCollectionChangeListener<RealmList<Dog>>() {\n            @Override\n            public void onChange(RealmList<Dog> collection, OrderedCollectionChangeSet changes) {\n                fail();\n            }\n        });\n\n        collection.removeAllChangeListeners();\n\n        // This one is added after removal, so it should be triggered.\n        collection.addChangeListener(new RealmChangeListener<RealmList<Dog>>() {\n            @Override\n            public void onChange(RealmList<Dog> element) {\n                listenerCalledCount.incrementAndGet();\n                looperThread.testComplete();\n            }\n        });\n\n        // This should trigger the listener if there is any.\n        realm.beginTransaction();\n        collection.get(0).setAge(42);\n        realm.commitTransaction();\n\n        assertEquals(1, listenerCalledCount.get());\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void removeChangeListener() {\n        collection = prepareRealmListInLooperThread();\n        Realm realm = looperThread.getRealm();\n        final AtomicInteger listenerCalledCount = new AtomicInteger(0);\n        RealmChangeListener<RealmList<Dog>> listener1 = new RealmChangeListener<RealmList<Dog>>() {\n            @Override\n            public void onChange(RealmList<Dog> element) {\n                fail();\n            }\n        };\n        OrderedRealmCollectionChangeListener<RealmList<Dog>> listener2 =\n                new OrderedRealmCollectionChangeListener<RealmList<Dog>>() {\n                    @Override\n                    public void onChange(RealmList<Dog> collection, OrderedCollectionChangeSet changes) {\n                        assertEquals(0, listenerCalledCount.getAndIncrement());\n                        looperThread.testComplete();\n                    }\n                };\n\n        collection.addChangeListener(listener1);\n        collection.addChangeListener(listener2);\n\n        collection.removeChangeListener(listener1);\n\n        // This should trigger the listener if there is any.\n        realm.beginTransaction();\n        collection.get(0).setAge(42);\n        realm.commitTransaction();\n        assertEquals(1, listenerCalledCount.get());\n    }\n\n    // https://github.com/realm/realm-java/issues/4554\n    @Test\n    public void createSnapshot_shouldUseTargetTable() {\n        int sizeBefore = collection.size();\n        OrderedRealmCollectionSnapshot<Dog> snapshot = collection.createSnapshot();\n        realm.beginTransaction();\n        snapshot.get(0).deleteFromRealm();\n        realm.commitTransaction();\n        assertEquals(sizeBefore - 1, collection.size());\n\n        assertNotNull(collection.getOsList());\n        assertEquals(collection.getOsList().getTargetTable().getName(), snapshot.getTable().getName());\n    }\n\n    @Test\n    public void getRealm() {\n        assertTrue(realm == collection.getRealm());\n    }\n\n    @Test\n    public void getRealm_throwsIfDynamicRealm() {\n        DynamicRealm dRealm = DynamicRealm.getInstance(realm.getConfiguration());\n        DynamicRealmObject obj = dRealm.where(Owner.CLASS_NAME).findFirst();\n        RealmList<DynamicRealmObject> list = obj.getList(\"dogs\");\n        try {\n            list.getRealm();\n            fail();\n        } catch (IllegalStateException ignore) {\n        } finally {\n            dRealm.close();\n        }\n    }\n\n    @Test\n    public void getRealm_throwsIfRealmClosed() {\n        realm.close();\n        try {\n            collection.getRealm();\n            fail();\n        } catch (IllegalStateException ignore) {\n        }\n    }\n\n    @Test\n    public void getRealm_returnsNullForUnmanagedList() {\n        assertNull(new RealmList().getRealm());\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/RealmMigrationTests.java",
    "content": "/*\n * Copyright 2015 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\npackage io.realm;\n\nimport android.content.Context;\n\nimport org.bson.types.ObjectId;\nimport org.hamcrest.CoreMatchers;\nimport org.junit.After;\nimport org.junit.Before;\nimport org.junit.Rule;\nimport org.junit.Test;\nimport org.junit.rules.ExpectedException;\nimport org.junit.runner.RunWith;\n\nimport java.io.File;\nimport java.io.FileNotFoundException;\nimport java.io.IOException;\nimport java.util.Date;\nimport java.util.Locale;\nimport java.util.UUID;\nimport java.util.concurrent.atomic.AtomicBoolean;\n\nimport androidx.test.ext.junit.runners.AndroidJUnit4;\nimport androidx.test.platform.app.InstrumentationRegistry;\n\nimport io.realm.annotations.PrimaryKey;\nimport io.realm.annotations.RealmClass;\nimport io.realm.entities.AllTypes;\nimport io.realm.entities.AnnotationTypes;\nimport io.realm.entities.CatOwner;\nimport io.realm.entities.Dog;\nimport io.realm.entities.FieldOrder;\nimport io.realm.entities.RealmAnyIndexed;\nimport io.realm.entities.RealmAnyNotIndexed;\nimport io.realm.entities.RealmAnyRealmListWithPK;\nimport io.realm.entities.NullTypes;\nimport io.realm.entities.ObjectIdPrimaryKey;\nimport io.realm.entities.PrimaryKeyAsBoxedByte;\nimport io.realm.entities.PrimaryKeyAsBoxedInteger;\nimport io.realm.entities.PrimaryKeyAsBoxedLong;\nimport io.realm.entities.PrimaryKeyAsBoxedShort;\nimport io.realm.entities.PrimaryKeyAsByte;\nimport io.realm.entities.PrimaryKeyAsInteger;\nimport io.realm.entities.PrimaryKeyAsLong;\nimport io.realm.entities.PrimaryKeyAsShort;\nimport io.realm.entities.PrimaryKeyAsString;\nimport io.realm.entities.PrimaryKeyAsUUID;\nimport io.realm.entities.StringOnly;\nimport io.realm.entities.StringOnlyRequired;\nimport io.realm.entities.Thread;\nimport io.realm.entities.embedded.EmbeddedSimpleChild;\nimport io.realm.entities.embedded.EmbeddedSimpleParent;\nimport io.realm.entities.migration.HandleBackLinksChild1;\nimport io.realm.entities.migration.HandleBackLinksChild2;\nimport io.realm.entities.migration.HandleBackLinksParent1;\nimport io.realm.entities.migration.HandleBackLinksParent2;\nimport io.realm.entities.migration.MigrationClassRenamed;\nimport io.realm.entities.migration.MigrationCore6PKStringIndexedByDefault;\nimport io.realm.entities.migration.MigrationFieldRenameAndAdd;\nimport io.realm.entities.migration.MigrationFieldRenamed;\nimport io.realm.entities.migration.MigrationFieldTypeToInt;\nimport io.realm.entities.migration.MigrationFieldTypeToInteger;\nimport io.realm.entities.migration.MigrationIndexedFieldRenamed;\nimport io.realm.entities.migration.MigrationPosteriorIndexOnly;\nimport io.realm.entities.migration.MigrationPriorIndexOnly;\nimport io.realm.exceptions.RealmMigrationNeededException;\nimport io.realm.internal.OsObjectStore;\nimport io.realm.internal.Table;\nimport io.realm.migration.MigrationPrimaryKey;\n\nimport static org.junit.Assert.assertEquals;\nimport static org.junit.Assert.assertFalse;\nimport static org.junit.Assert.assertNotNull;\nimport static org.junit.Assert.assertNull;\nimport static org.junit.Assert.assertSame;\nimport static org.junit.Assert.assertThat;\nimport static org.junit.Assert.assertTrue;\nimport static org.junit.Assert.fail;\n\n@RunWith(AndroidJUnit4.class)\npublic class RealmMigrationTests {\n\n    @Rule\n    public final TestRealmConfigurationFactory configFactory = new TestRealmConfigurationFactory();\n    @Rule\n    public final ExpectedException thrown = ExpectedException.none();\n\n    private Realm realm;\n    private Context context;\n\n    @Before\n    public void setup() {\n        context = InstrumentationRegistry.getInstrumentation().getContext();\n    }\n\n    @After\n    public void tearDown() {\n        if (realm != null) {\n            realm.close();\n        }\n    }\n\n    private void assertPKField(Realm realm, String className, String expectedName) {\n        String pkField = OsObjectStore.getPrimaryKeyForObject(realm.sharedRealm, className);\n        assertNotNull(pkField);\n        RealmObjectSchema objectSchema = realm.getSchema().get(className);\n        assertNotNull(objectSchema);\n        assertTrue(objectSchema.hasField(expectedName));\n        assertEquals(expectedName, pkField);\n    }\n\n    @Test\n    public void getInstance_realmClosedAfterMigrationException() throws IOException {\n        String REALM_NAME = \"default0.realm\";\n        RealmConfiguration realmConfig = configFactory.createConfiguration(REALM_NAME);\n        configFactory.copyRealmFromAssets(context, REALM_NAME, REALM_NAME);\n        try {\n            Realm.getInstance(realmConfig);\n            fail(\"A migration should be triggered\");\n        } catch (RealmMigrationNeededException expected) {\n            Realm.deleteRealm(realmConfig); // Deletes old realm.\n        }\n\n        // This should recreate the Realm with proper schema.\n        Realm realm = Realm.getInstance(realmConfig);\n        int result = realm.where(AllTypes.class).equalTo(\"columnString\", \"Foo\").findAll().size();\n        assertEquals(0, result);\n        realm.close();\n    }\n\n    // If a migration creates a different ordering of columns on Realm A, while another ordering is generated by\n    // creating a new Realm B. Global column indices will not work. They must be calculated for each Realm.\n    @Test\n    public void localColumnIndices() throws IOException {\n        String MIGRATED_REALM = \"migrated.realm\";\n        String NEW_REALM = \"new.realm\";\n\n        // Migrates old Realm to proper schema.\n\n        // V1 config\n        RealmConfiguration v1Config = configFactory.createConfigurationBuilder()\n                .name(MIGRATED_REALM)\n                .schema(StringOnly.class)\n                .schemaVersion(1)\n                .build();\n        Realm oldRealm = Realm.getInstance(v1Config);\n        oldRealm.close();\n\n        // V2 config\n        RealmMigration migration = new RealmMigration() {\n            @Override\n            public void migrate(DynamicRealm realm, long oldVersion, long newVersion) {\n                RealmSchema schema = realm.getSchema();\n                schema.create(\"FieldOrder\")\n                        .addField(\"field2\", int.class)\n                        .addField(\"field1\", boolean.class);\n            }\n        };\n\n        RealmConfiguration v2Config = configFactory.createConfigurationBuilder()\n                .name(MIGRATED_REALM)\n                .schema(StringOnly.class, FieldOrder.class)\n                .schemaVersion(2)\n                .migration(migration)\n                .build();\n        oldRealm = Realm.getInstance(v2Config);\n\n        // Creates new Realm which will cause column indices to be recalculated based on the order in the java file\n        // instead of the migration.\n        RealmConfiguration newConfig = configFactory.createConfigurationBuilder()\n                .name(NEW_REALM)\n                .schemaVersion(2)\n                .schema(StringOnly.class, FieldOrder.class)\n                .build();\n        Realm newRealm = Realm.getInstance(newConfig);\n        newRealm.close();\n\n        // Tries to query migrated realm. With local column indices this will work. With global it will fail.\n        assertEquals(0, oldRealm.where(FieldOrder.class).equalTo(\"field1\", true).findAll().size());\n        oldRealm.close();\n    }\n\n    @Test\n    public void notSettingIndexThrows() {\n\n        // Creates v0 of the Realm.\n        RealmConfiguration originalConfig = configFactory.createConfigurationBuilder()\n                .schema(StringOnly.class)\n                .build();\n        Realm.getInstance(originalConfig).close();\n\n        // Creates v1 of the Realm.\n        RealmMigration migration = new RealmMigration() {\n            @Override\n            public void migrate(DynamicRealm realm, long oldVersion, long newVersion) {\n                RealmSchema schema = realm.getSchema();\n                schema.create(\"AnnotationTypes\")\n                        .addField(\"id\", long.class, FieldAttribute.PRIMARY_KEY)\n                        .addField(\"indexString\", String.class) // Forgets to set @Index.\n                        .addField(\"notIndexString\", String.class);\n            }\n        };\n\n        RealmConfiguration realmConfig = configFactory.createConfigurationBuilder()\n                .schemaVersion(1)\n                .schema(StringOnly.class, AnnotationTypes.class)\n                .migration(migration)\n                .build();\n        try {\n            realm = Realm.getInstance(realmConfig);\n            fail();\n        } catch (RealmMigrationNeededException ignored) {\n        } finally {\n            if (realm != null) {\n                realm.close();\n            }\n        }\n    }\n\n    @Test\n    public void addingPrimaryKeyThrows() {\n\n        // Creates v0 of the Realm.\n        RealmConfiguration originalConfig = configFactory.createConfigurationBuilder()\n                .schema(Thread.class)\n                .build();\n        Realm.getInstance(originalConfig).close();\n\n        RealmMigration migration = new RealmMigration() {\n            @Override\n            public void migrate(DynamicRealm realm, long oldVersion, long newVersion) {\n                RealmSchema schema = realm.getSchema();\n                schema.create(\"AnnotationTypes\")\n                        .addField(\"id\", long.class) // Forgets to set @PrimaryKey.\n                        .addField(\"indexString\", String.class, FieldAttribute.INDEXED)\n                        .addField(\"notIndexString\", String.class);\n            }\n        };\n\n        // Creates v1 of the Realm.\n        RealmConfiguration realmConfig = configFactory.createConfigurationBuilder()\n                .schemaVersion(1)\n                .schema(Thread.class, AnnotationTypes.class)\n                .migration(migration)\n                .build();\n        try {\n            realm = Realm.getInstance(realmConfig);\n            fail();\n        } catch (RealmMigrationNeededException e) {\n            assertThat(e.getMessage(), CoreMatchers.containsString(\n                    \"Primary Key for class 'AnnotationTypes' has been added\"));\n        } finally {\n            if (realm != null) {\n                realm.close();\n            }\n        }\n    }\n\n    @Test\n    public void removingPrimaryKeyThrows() {\n\n        // Creates v0 of the Realm.\n        RealmConfiguration originalConfig = configFactory.createConfigurationBuilder()\n                .schema(Thread.class)\n                .build();\n        Realm.getInstance(originalConfig).close();\n\n        RealmMigration migration = new RealmMigration() {\n            @Override\n            public void migrate(DynamicRealm realm, long oldVersion, long newVersion) {\n                RealmSchema schema = realm.getSchema();\n                schema.create(\"StringOnly\")\n                        .addField(\"chars\", String.class, FieldAttribute.PRIMARY_KEY);\n            }\n        };\n\n        // Creates v1 of the Realm.\n        RealmConfiguration realmConfig = configFactory.createConfigurationBuilder()\n                .schemaVersion(1)\n                .schema(Thread.class, StringOnly.class)\n                .migration(migration)\n                .build();\n        try {\n            realm = Realm.getInstance(realmConfig);\n            fail();\n        } catch (RealmMigrationNeededException e) {\n            assertThat(e.getMessage(),\n                    CoreMatchers.containsString(\"Primary Key for class 'StringOnly' has been removed.\"));\n        } finally {\n            if (realm != null) {\n                realm.close();\n            }\n        }\n    }\n\n    @Test\n    public void changingPrimaryKeyThrows() {\n\n        // Creates v0 of the Realm.\n        RealmConfiguration originalConfig = configFactory.createConfigurationBuilder()\n                .schema(Thread.class)\n                .build();\n        Realm.getInstance(originalConfig).close();\n\n        RealmMigration migration = new RealmMigration() {\n            @Override\n            public void migrate(DynamicRealm realm, long oldVersion, long newVersion) {\n                RealmSchema schema = realm.getSchema();\n                schema.create(\"PrimaryKeyAsString\")\n                        .addField(\"id\", long.class, FieldAttribute.PRIMARY_KEY) // Initial @PrimaryKey is on the int.\n                        .addField(\"name\", String.class);\n            }\n        };\n\n        // Creates v1 of the Realm.\n        RealmConfiguration realmConfig = configFactory.createConfigurationBuilder()\n                .schemaVersion(1)\n                .schema(Thread.class, PrimaryKeyAsString.class)\n                .migration(migration)\n                .build();\n        try {\n            realm = Realm.getInstance(realmConfig);\n            fail();\n        } catch (RealmMigrationNeededException e) {\n            assertThat(e.getMessage(), CoreMatchers.containsString(\n                    \"Primary Key for class 'PrimaryKeyAsString' has changed from 'id' to 'name'.\"));\n        } finally {\n            if (realm != null) {\n                realm.close();\n            }\n        }\n    }\n\n    /**\n     * Builds a temporary schema to be modified later in a migration. {@link MigrationPrimaryKey} is\n     * the base class when specified.\n     *\n     * <p>MigrationPrimaryKey is supposed to be a RealmObject, but that would hamper our steps toward\n     * testing migrations as Realm looks for it in migration. It is thus set to be an interface.\n     *\n     * @param className a class whose schema is to be re-created\n     * @param createBase create a schema named \"MigrationPrimaryKey\" instead of {@code className} if {@code true}\n     */\n    private void buildInitialMigrationSchema(final String className, final boolean createBase) {\n        RealmConfiguration config = configFactory.createConfigurationBuilder().build();\n        // Init the schema\n        Realm.getInstance(config).close();\n\n        DynamicRealm realm = DynamicRealm.getInstance(config);\n        realm.beginTransaction();\n        // First, removes an existing schema.\n        realm.getSchema().remove(className);\n        // Then recreates the deleted schema or builds a base schema.\n        realm.getSchema()\n                .create(createBase ? MigrationPrimaryKey.CLASS_NAME : className)\n                .addField(MigrationPrimaryKey.FIELD_FIRST,   Byte.class)\n                .addField(MigrationPrimaryKey.FIELD_SECOND,  Short.class)\n                .addField(MigrationPrimaryKey.FIELD_PRIMARY, String.class, FieldAttribute.PRIMARY_KEY)\n                .addField(MigrationPrimaryKey.FIELD_FOURTH,  Integer.class)\n                .addField(MigrationPrimaryKey.FIELD_FIFTH,   Long.class);\n        realm.commitTransaction();\n        realm.close();\n    }\n\n    // Tests to show renaming a class does not hinder its PK field's attribute.\n    @Test\n    public void renameClassTransferPrimaryKey() {\n        buildInitialMigrationSchema(MigrationClassRenamed.CLASS_NAME, true);\n\n        RealmMigration migration = new RealmMigration() {\n            @Override\n            public void migrate(DynamicRealm realm, long oldVersion, long newVersion) {\n                realm.getSchema()\n                        .rename(MigrationPrimaryKey.CLASS_NAME, MigrationClassRenamed.CLASS_NAME);\n            }\n        };\n        RealmConfiguration realmConfig = configFactory.createConfigurationBuilder()\n                .schemaVersion(1)\n                .schema(MigrationClassRenamed.class)\n                .migration(migration)\n                .build();\n        Realm realm = Realm.getInstance(realmConfig);\n\n        Table table = realm.getSchema().getTable(MigrationClassRenamed.class);\n        assertEquals(MigrationClassRenamed.DEFAULT_FIELDS_COUNT, table.getColumnCount());\n        assertPKField(realm, MigrationClassRenamed.CLASS_NAME, MigrationClassRenamed.FIELD_PRIMARY);\n        // Old schema does not exist.\n        assertNull(realm.getSchema().get(MigrationPrimaryKey.CLASS_NAME));\n    }\n\n    @Test\n    public void rename_noSimilarPrimaryKeyWithOldSchema() {\n        buildInitialMigrationSchema(MigrationClassRenamed.CLASS_NAME, true);\n\n        RealmMigration migration = new RealmMigration() {\n            @Override\n            public void migrate(DynamicRealm realm, long oldVersion, long newVersion) {\n                // Let us rename the old schema.\n                realm.getSchema()\n                        .rename(MigrationPrimaryKey.CLASS_NAME, MigrationClassRenamed.CLASS_NAME);\n\n                // Then recreates the original schema to see if Realm is going to get confused.\n                // Unlike the first time with buildInitialMigrationSchema(), we will not have a primary key.\n                realm.getSchema()\n                        .create(MigrationPrimaryKey.CLASS_NAME)\n                        .addField(MigrationPrimaryKey.FIELD_FIRST,   Byte.class)\n                        .addField(MigrationPrimaryKey.FIELD_SECOND,  Short.class)\n                        .addField(MigrationPrimaryKey.FIELD_PRIMARY, String.class)\n                        .addField(MigrationPrimaryKey.FIELD_FOURTH,  Integer.class)\n                        .addField(MigrationPrimaryKey.FIELD_FIFTH,   Long.class);\n            }\n        };\n        RealmConfiguration realmConfig = configFactory.createConfigurationBuilder()\n                .schemaVersion(1)\n                .schema(MigrationClassRenamed.class)\n                .migration(migration)\n                .build();\n        // Trigger migration\n        Realm realm = Realm.getInstance(realmConfig);\n        realm.close();\n\n        DynamicRealm dynamicRealm = DynamicRealm.getInstance(realmConfig);\n        try {\n            assertTrue(dynamicRealm.getSchema().get(MigrationClassRenamed.CLASS_NAME).hasPrimaryKey());\n            assertFalse(dynamicRealm.getSchema().get(MigrationPrimaryKey.CLASS_NAME).hasPrimaryKey());\n        } finally {\n            dynamicRealm.close();\n        }\n    }\n\n    // Test to show that renaming a class does not effect the primary key.\n    @Test\n    public void setClassName_transferPrimaryKey() {\n        buildInitialMigrationSchema(MigrationClassRenamed.CLASS_NAME, true);\n\n        RealmMigration migration = new RealmMigration() {\n            @Override\n            public void migrate(DynamicRealm realm, long oldVersion, long newVersion) {\n                realm.getSchema()\n                        .get(MigrationPrimaryKey.CLASS_NAME)\n                        .setClassName(MigrationClassRenamed.CLASS_NAME);\n            }\n        };\n        RealmConfiguration realmConfig = configFactory.createConfigurationBuilder()\n                .schemaVersion(1)\n                .schema(MigrationClassRenamed.class)\n                .migration(migration)\n                .build();\n        Realm realm = Realm.getInstance(realmConfig);\n\n        Table table = realm.getSchema().getTable(MigrationClassRenamed.class);\n        assertEquals(MigrationClassRenamed.DEFAULT_FIELDS_COUNT, table.getColumnCount());\n        assertPKField(realm, MigrationClassRenamed.CLASS_NAME, MigrationClassRenamed.FIELD_PRIMARY);\n        // Old schema does not exist.\n        assertNull(realm.getSchema().get(MigrationPrimaryKey.CLASS_NAME));\n    }\n\n    @Test\n    public void setClassName_noSimilarPrimaryKeyWithOldSchema() {\n        buildInitialMigrationSchema(MigrationClassRenamed.CLASS_NAME, true);\n\n        RealmMigration migration = new RealmMigration() {\n            @Override\n            public void migrate(DynamicRealm realm, long oldVersion, long newVersion) {\n                // Let us set a new class name.\n                realm.getSchema()\n                        .get(MigrationPrimaryKey.CLASS_NAME)\n                        .setClassName(MigrationClassRenamed.CLASS_NAME);\n\n                // Then recreates the original schema to see if Realm is going to get confused.\n                // Unlike the first time with buildInitialMigrationSchema(), we will not have a primary key.\n                realm.getSchema()\n                        .create(MigrationPrimaryKey.CLASS_NAME)\n                        .addField(MigrationPrimaryKey.FIELD_FIRST,   Byte.class)\n                        .addField(MigrationPrimaryKey.FIELD_SECOND,  Short.class)\n                        .addField(MigrationPrimaryKey.FIELD_PRIMARY, String.class)\n                        .addField(MigrationPrimaryKey.FIELD_FOURTH,  Integer.class)\n                        .addField(MigrationPrimaryKey.FIELD_FIFTH,   Long.class);\n            }\n        };\n        RealmConfiguration realmConfig = configFactory.createConfigurationBuilder()\n                .schemaVersion(1)\n                .schema(MigrationClassRenamed.class)\n                .migration(migration)\n                .build();\n        Realm realm = Realm.getInstance(realmConfig);\n        realm.close();\n\n        // We cannot access 'MigrationPrimaryKey' from a typed Realm since it is not part of the pre-defined schema.\n        DynamicRealm dynamicRealm = DynamicRealm.getInstance(realmConfig);\n        try {\n            assertTrue(dynamicRealm.getSchema().get(MigrationClassRenamed.CLASS_NAME).hasPrimaryKey());\n            assertFalse(dynamicRealm.getSchema().get(MigrationPrimaryKey.CLASS_NAME).hasPrimaryKey());\n        } finally {\n            dynamicRealm.close();\n        }\n    }\n\n    @Test\n    public void setClassName_throwOnLongClassName() {\n        RealmConfiguration config = configFactory.createConfigurationBuilder().build();\n        // Creates the first version of schema.\n        Realm.getInstance(config).close();\n        DynamicRealm realm = DynamicRealm.getInstance(config);\n        realm.beginTransaction();\n        realm.getSchema().create(MigrationPrimaryKey.CLASS_NAME);\n        realm.commitTransaction();\n        realm.close();\n\n        final String tooLongClassName = \"MigrationNameIsLongerThan57Char_ThisShouldThrowAnException\";\n        assertEquals(58, tooLongClassName.length());\n\n        // Gets ready for the 2nd version migration.\n        RealmMigration migration = new RealmMigration() {\n            @Override\n            public void migrate(DynamicRealm realm, long oldVersion, long newVersion) {\n                realm.getSchema()\n                        .get(MigrationPrimaryKey.CLASS_NAME)\n                        .setClassName(tooLongClassName);\n            }\n        };\n        RealmConfiguration realmConfig = configFactory.createConfigurationBuilder()\n                .schemaVersion(1)\n                .migration(migration)\n                .build();\n\n        // Creating Realm instance fails.\n        try {\n            Realm.getInstance(realmConfig);\n            fail();\n        } catch (IllegalArgumentException expected) {\n            assertEquals(\n                    String.format(Locale.US,\n                            \"Class name is too long. Limit is %1$d characters: '%2$s' (%3$d)\",\n                            tooLongClassName.length() - 1,\n                            tooLongClassName,\n                            tooLongClassName.length()),\n                    expected.getMessage());\n        }\n    }\n\n    // Removing fields before a pk field does not affect the pk.\n    @Test\n    public void removeFieldsBeforePrimaryKey() {\n        buildInitialMigrationSchema(MigrationPosteriorIndexOnly.CLASS_NAME, false);\n\n        RealmMigration migration = new RealmMigration() {\n            @Override\n            public void migrate(DynamicRealm realm, long oldVersion, long newVersion) {\n                realm.getSchema().get(MigrationPosteriorIndexOnly.CLASS_NAME)\n                        .removeField(MigrationPrimaryKey.FIELD_FIRST)\n                        .removeField(MigrationPrimaryKey.FIELD_SECOND);\n            }\n        };\n        RealmConfiguration realmConfig = configFactory.createConfigurationBuilder()\n                .schemaVersion(1)\n                .schema(MigrationPosteriorIndexOnly.class)\n                .migration(migration)\n                .build();\n        Realm realm = Realm.getInstance(realmConfig);\n        Table table = realm.getSchema().getTable(MigrationPosteriorIndexOnly.class);\n\n        assertEquals(MigrationPosteriorIndexOnly.DEFAULT_FIELDS_COUNT, table.getColumnCount());\n        assertPKField(realm, MigrationPosteriorIndexOnly.CLASS_NAME, MigrationPosteriorIndexOnly.FIELD_PRIMARY);\n    }\n\n    // Removing fields after a pk field does not affect the pk.\n    @Test\n    public void removeFieldsAfterPrimaryKey() {\n        buildInitialMigrationSchema(MigrationPriorIndexOnly.CLASS_NAME, false);\n\n        RealmMigration migration = new RealmMigration() {\n            @Override\n            public void migrate(DynamicRealm realm, long oldVersion, long newVersion) {\n                realm.getSchema().get(MigrationPriorIndexOnly.CLASS_NAME)\n                        .removeField(MigrationPrimaryKey.FIELD_FOURTH)\n                        .removeField(MigrationPrimaryKey.FIELD_FIFTH);\n            }\n        };\n        RealmConfiguration realmConfig = configFactory.createConfigurationBuilder()\n                .schemaVersion(1)\n                .schema(MigrationPriorIndexOnly.class)\n                .migration(migration)\n                .build();\n        Realm realm = Realm.getInstance(realmConfig);\n        Table table = realm.getSchema().getTable(MigrationPriorIndexOnly.class);\n\n        assertEquals(MigrationPriorIndexOnly.DEFAULT_FIELDS_COUNT, table.getColumnCount());\n        assertPKField(realm, MigrationPriorIndexOnly.CLASS_NAME, MigrationPriorIndexOnly.FIELD_PRIMARY);\n    }\n\n    // Renaming the class should also rename the the class entry in the pk metadata table that tracks primary keys.\n    @Test\n    public void renamePrimaryKeyFieldInMigration() {\n        buildInitialMigrationSchema(MigrationFieldRenamed.CLASS_NAME, false);\n\n        RealmMigration migration = new RealmMigration() {\n            @Override\n            public void migrate(DynamicRealm realm, long oldVersion, long newVersion) {\n                realm.getSchema().get(MigrationFieldRenamed.CLASS_NAME)\n                        .renameField(MigrationPrimaryKey.FIELD_PRIMARY, MigrationFieldRenamed.FIELD_PRIMARY);\n            }\n        };\n        RealmConfiguration realmConfig = configFactory.createConfigurationBuilder()\n                .schemaVersion(1)\n                .schema(MigrationFieldRenamed.class)\n                .migration(migration)\n                .build();\n        Realm realm = Realm.getInstance(realmConfig);\n\n        Table table = realm.getSchema().getTable(MigrationFieldRenamed.class);\n        assertEquals(MigrationFieldRenamed.DEFAULT_FIELDS_COUNT, table.getColumnCount());\n        assertPKField(realm, MigrationFieldRenamed.CLASS_NAME, MigrationFieldRenamed.FIELD_PRIMARY);\n    }\n\n    private void createObjectsWithOldPrimaryKey(final String className, final boolean insertNullValue) {\n        DynamicRealm realm = DynamicRealm.getInstance(configFactory.createConfigurationBuilder().build());\n        try {\n            realm.executeTransaction(new DynamicRealm.Transaction() {\n                @Override\n                public void execute(DynamicRealm realm) {\n                    realm.createObject(className, \"12\");\n                    if (insertNullValue) {\n                        realm.createObject(className, null);\n                    }\n                }\n            });\n        } finally {\n            realm.close();\n        }\n    }\n\n    // This is to test how PK type can change to non-nullable int in migration.\n    @Test\n    public void modifyPrimaryKeyFieldTypeToIntInMigration() {\n        final String TEMP_FIELD_ID = \"temp_id\";\n        buildInitialMigrationSchema(MigrationFieldTypeToInt.CLASS_NAME, false);\n        // create objects with the schema provided\n        createObjectsWithOldPrimaryKey(MigrationFieldTypeToInt.CLASS_NAME, true);\n\n        RealmMigration migration = new RealmMigration() {\n            @Override\n            public void migrate(DynamicRealm realm, long oldVersion, long newVersion) {\n                realm.getSchema().get(MigrationFieldTypeToInt.CLASS_NAME)\n                        .addField(\"temp_id\", int.class)\n                        .transform(new RealmObjectSchema.Function() {\n                            @Override\n                            public void apply(DynamicRealmObject obj) {\n                                String fieldValue = obj.getString(MigrationPrimaryKey.FIELD_PRIMARY);\n                                if (fieldValue != null && fieldValue.length() != 0) {\n                                    obj.setInt(TEMP_FIELD_ID, Integer.parseInt(fieldValue));\n                                } else {\n                                    // Since this cannot be accepted as proper pk value, we'll delete it.\n                                    // *You can modify with some other value such as 0, but that's not\n                                    // counted in this scenario.\n                                    obj.deleteFromRealm();\n                                }\n                            }\n                        })\n                        .removeField(MigrationPrimaryKey.FIELD_PRIMARY)\n                        .renameField(TEMP_FIELD_ID, MigrationFieldTypeToInt.FIELD_PRIMARY)\n                        .addPrimaryKey(MigrationFieldTypeToInt.FIELD_PRIMARY);\n            }\n        };\n        RealmConfiguration realmConfig = configFactory.createConfigurationBuilder()\n                .schemaVersion(1)\n                .schema(MigrationFieldTypeToInt.class)\n                .migration(migration)\n                .build();\n        Realm realm = Realm.getInstance(realmConfig);\n\n        Table table = realm.getSchema().getTable(MigrationFieldTypeToInt.class);\n        assertEquals(MigrationFieldTypeToInt.DEFAULT_FIELDS_COUNT, table.getColumnCount());\n        assertPKField(realm, MigrationFieldTypeToInt.CLASS_NAME, MigrationFieldTypeToInt.FIELD_PRIMARY);\n\n        assertEquals(1, realm.where(MigrationFieldTypeToInt.class).count());\n        assertEquals(12, realm.where(MigrationFieldTypeToInt.class).findFirst().fieldIntPrimary);\n    }\n\n    // This is to test how PK type can change to nullable Integer in migration.\n    @Test\n    public void modifyPrimaryKeyFieldTypeToIntegerInMigration() {\n        final String TEMP_FIELD_ID = \"temp_id\";\n        buildInitialMigrationSchema(MigrationFieldTypeToInteger.CLASS_NAME, false);\n        // Creates objects with the schema provided.\n        createObjectsWithOldPrimaryKey(MigrationFieldTypeToInteger.CLASS_NAME, true);\n\n        RealmMigration migration = new RealmMigration() {\n            @Override\n            public void migrate(DynamicRealm realm, long oldVersion, long newVersion) {\n                realm.getSchema().get(MigrationFieldTypeToInteger.CLASS_NAME)\n                        .addField(\"temp_id\", Integer.class)\n                        .transform(new RealmObjectSchema.Function() {\n                            @Override\n                            public void apply(DynamicRealmObject obj) {\n                                String fieldValue = obj.getString(MigrationPrimaryKey.FIELD_PRIMARY);\n                                if (fieldValue != null && fieldValue.length() != 0) {\n                                    obj.setInt(TEMP_FIELD_ID, Integer.parseInt(fieldValue));\n                                } else {\n                                    obj.setNull(TEMP_FIELD_ID);\n                                }\n                            }\n                        })\n                        .removeField(MigrationPrimaryKey.FIELD_PRIMARY)\n                        .renameField(TEMP_FIELD_ID, MigrationFieldTypeToInteger.FIELD_PRIMARY)\n                        .addPrimaryKey(MigrationFieldTypeToInteger.FIELD_PRIMARY);\n            }\n        };\n        RealmConfiguration realmConfig = configFactory.createConfigurationBuilder()\n                .schemaVersion(1)\n                .schema(MigrationFieldTypeToInteger.class)\n                .migration(migration)\n                .build();\n        Realm realm = Realm.getInstance(realmConfig);\n\n        Table table = realm.getSchema().getTable(MigrationFieldTypeToInteger.class);\n        assertEquals(MigrationFieldTypeToInteger.DEFAULT_FIELDS_COUNT, table.getColumnCount());\n        assertPKField(realm, MigrationFieldTypeToInteger.CLASS_NAME, MigrationFieldTypeToInteger.FIELD_PRIMARY);\n\n        assertEquals(2, realm.where(MigrationFieldTypeToInteger.class).count());\n\n        // not-null value\n        assertEquals(1, realm.where(MigrationFieldTypeToInteger.class)\n                             .equalTo(MigrationFieldTypeToInteger.FIELD_PRIMARY, Integer.valueOf(12))\n                             .count());\n\n        // null value\n        assertEquals(1, realm.where(MigrationFieldTypeToInteger.class)\n                             .equalTo(MigrationFieldTypeToInteger.FIELD_PRIMARY, (Integer) null)\n                             .count());\n    }\n\n    @Test\n    public void modifyPrimaryKeyFieldTypeFromIntToStringInMigration() {\n        RealmMigration migration = new RealmMigration() {\n            @Override\n            public void migrate(DynamicRealm realm, long oldVersion, long newVersion) {\n                RealmObjectSchema objectSchema  = realm.getSchema().get(PrimaryKeyAsString.CLASS_NAME);\n                assertNotNull(objectSchema);\n                assertEquals(PrimaryKeyAsString.FIELD_ID, objectSchema.getPrimaryKey());\n                objectSchema.removePrimaryKey().addPrimaryKey(PrimaryKeyAsString.FIELD_PRIMARY_KEY);\n            }\n        };\n\n        RealmConfiguration configuration = configFactory.createConfigurationBuilder()\n                .schema(PrimaryKeyAsString.class)\n                .schemaVersion(1)\n                .migration(migration)\n                .build();\n\n        // Create the schema and set the int field as primary key\n        DynamicRealm dynamicRealm = DynamicRealm.getInstance(configuration);\n        dynamicRealm.beginTransaction();\n        RealmSchema schema = dynamicRealm.getSchema();\n        schema.create(PrimaryKeyAsString.CLASS_NAME)\n                .addField(PrimaryKeyAsString.FIELD_ID, long.class, FieldAttribute.PRIMARY_KEY)\n                .addField(PrimaryKeyAsString.FIELD_PRIMARY_KEY, String.class);\n        dynamicRealm.createObject(PrimaryKeyAsString.CLASS_NAME, 0)\n                .setString(PrimaryKeyAsString.FIELD_PRIMARY_KEY, \"string0\");\n        dynamicRealm.createObject(PrimaryKeyAsString.CLASS_NAME, 1)\n                .setString(PrimaryKeyAsString.FIELD_PRIMARY_KEY, \"string1\");\n        dynamicRealm.setVersion(0);\n        dynamicRealm.commitTransaction();\n\n        // Run migration\n        realm = Realm.getInstance(configuration);\n        RealmObjectSchema objectSchema = realm.getSchema().get(PrimaryKeyAsString.CLASS_NAME);\n        assertNotNull(objectSchema);\n        assertEquals(PrimaryKeyAsString.FIELD_PRIMARY_KEY, objectSchema.getPrimaryKey());\n        RealmResults<PrimaryKeyAsString> results = realm.where(PrimaryKeyAsString.class)\n                .sort(PrimaryKeyAsString.FIELD_ID)\n                .findAll();\n        assertEquals(2, results.size());\n        assertEquals(\"string0\", results.get(0).getName());\n        assertEquals(\"string1\", results.get(1).getName());\n    }\n\n    @Test\n    public void modifyPrimaryKeyFieldTypeFromStringToInt() {\n        RealmMigration migration = new RealmMigration() {\n            @Override\n            public void migrate(DynamicRealm realm, long oldVersion, long newVersion) {\n                RealmObjectSchema objectSchema  = realm.getSchema().get(PrimaryKeyAsInteger.CLASS_NAME);\n                assertNotNull(objectSchema);\n                assertEquals(PrimaryKeyAsInteger.FIELD_NAME, objectSchema.getPrimaryKey());\n                objectSchema.removePrimaryKey().addPrimaryKey(PrimaryKeyAsInteger.FIELD_ID);\n            }\n        };\n\n        RealmConfiguration configuration = configFactory.createConfigurationBuilder()\n                .schema(PrimaryKeyAsInteger.class)\n                .schemaVersion(1)\n                .migration(migration)\n                .build();\n\n        // Create the schema and set the String field as primary key\n        DynamicRealm dynamicRealm = DynamicRealm.getInstance(configuration);\n        dynamicRealm.beginTransaction();\n        RealmSchema schema = dynamicRealm.getSchema();\n        schema.create(PrimaryKeyAsInteger.CLASS_NAME)\n                .addField(PrimaryKeyAsInteger.FIELD_ID, int.class)\n                .addField(PrimaryKeyAsInteger.FIELD_NAME, String.class, FieldAttribute.PRIMARY_KEY);\n        dynamicRealm.createObject(PrimaryKeyAsInteger.CLASS_NAME, \"string0\")\n                .setInt(PrimaryKeyAsInteger.FIELD_ID, 0);\n        dynamicRealm.createObject(PrimaryKeyAsInteger.CLASS_NAME, \"string1\")\n                .setInt(PrimaryKeyAsInteger.FIELD_ID, 1);\n        dynamicRealm.setVersion(0);\n        dynamicRealm.commitTransaction();\n\n        // Run migration\n        realm = Realm.getInstance(configuration);\n\n        RealmObjectSchema objectSchema = realm.getSchema().get(PrimaryKeyAsInteger.CLASS_NAME);\n        assertNotNull(objectSchema);\n        assertEquals(PrimaryKeyAsInteger.FIELD_ID, objectSchema.getPrimaryKey());\n        RealmResults<PrimaryKeyAsInteger> results = realm.where(PrimaryKeyAsInteger.class)\n                .sort(PrimaryKeyAsInteger.FIELD_ID)\n                .findAll();\n        assertEquals(2, results.size());\n        assertEquals(0, results.get(0).getId());\n        assertEquals(1, results.get(1).getId());\n    }\n\n    @Test\n    public void settingPrimaryKeyWithObjectSchema() {\n        // Creates v0 of the Realm.\n        RealmConfiguration originalConfig = configFactory.createConfigurationBuilder()\n                .schema(StringOnly.class)\n                .build();\n        Realm.getInstance(originalConfig).close();\n\n        RealmMigration migration = new RealmMigration() {\n            @Override\n            public void migrate(DynamicRealm realm, long oldVersion, long newVersion) {\n                RealmSchema schema = realm.getSchema();\n                schema.create(\"AnnotationTypes\")\n                        .addField(\"id\", long.class)\n                        .addPrimaryKey(\"id\")    // Uses addPrimaryKey() instead of adding FieldAttribute.PrimaryKey.\n                        .addField(\"indexString\", String.class)\n                        .addIndex(\"indexString\") // Uses addIndex() instead of FieldAttribute.Index.\n                        .addField(\"notIndexString\", String.class);\n            }\n        };\n\n        // Creates v1 of the Realm.\n        RealmConfiguration realmConfig = configFactory.createConfigurationBuilder()\n                .schemaVersion(1)\n                .schema(StringOnly.class, AnnotationTypes.class)\n                .migration(migration)\n                .build();\n\n        realm = Realm.getInstance(realmConfig);\n        RealmObjectSchema schema = realm.getSchema().get(\"AnnotationTypes\");\n        assertTrue(schema.hasPrimaryKey());\n        assertTrue(schema.hasIndex(\"id\"));\n        realm.close();\n    }\n\n    @Test\n    public void setAnnotations() {\n\n        // Creates v0 of the Realm.\n        RealmConfiguration originalConfig = configFactory.createConfigurationBuilder()\n                .schema(StringOnly.class)\n                .build();\n        Realm.getInstance(originalConfig).close();\n\n        RealmMigration migration = new RealmMigration() {\n            @Override\n            public void migrate(DynamicRealm realm, long oldVersion, long newVersion) {\n                RealmSchema schema = realm.getSchema();\n                schema.create(\"AnnotationTypes\")\n                        .addField(\"id\", long.class, FieldAttribute.PRIMARY_KEY)\n                        .addField(\"indexString\", String.class, FieldAttribute.INDEXED)\n                        .addField(\"notIndexString\", String.class);\n            }\n        };\n\n        RealmConfiguration realmConfig = configFactory.createConfigurationBuilder()\n                .schemaVersion(1)\n                .schema(StringOnly.class, AnnotationTypes.class)\n                .migration(migration)\n                .build();\n\n        realm = Realm.getInstance(realmConfig);\n        Table table = realm.getTable(AnnotationTypes.class);\n        assertEquals(3, table.getColumnCount());\n        assertEquals(\"id\", OsObjectStore.getPrimaryKeyForObject(realm.getSharedRealm(), \"AnnotationTypes\"));\n        assertTrue(table.hasSearchIndex(table.getColumnKey(\"id\")));\n        assertTrue(table.hasSearchIndex(table.getColumnKey(\"indexString\")));\n    }\n\n    @Test\n    public void migrationException_getPath() throws IOException {\n        configFactory.copyRealmFromAssets(context, \"default0.realm\", Realm.DEFAULT_REALM_NAME);\n        File realm = new File(configFactory.getRoot(), Realm.DEFAULT_REALM_NAME);\n        try {\n            Realm.getInstance(configFactory.createConfiguration());\n            fail();\n        } catch (RealmMigrationNeededException expected) {\n            assertEquals(expected.getPath(), realm.getAbsolutePath());\n        }\n    }\n\n    // Check if the RealmList type change can trigger a RealmMigrationNeededException.\n    @Test\n    public void migrationException_realmListChanged() throws IOException {\n        RealmConfiguration config = configFactory.createConfiguration();\n        // Initialize the schema with RealmList<Cat>\n        Realm.getInstance(configFactory.createConfiguration()).close();\n\n        DynamicRealm dynamicRealm = DynamicRealm.getInstance(config);\n        dynamicRealm.beginTransaction();\n        // Change the RealmList type to RealmList<Dog>\n        RealmObjectSchema dogSchema = dynamicRealm.getSchema().get(Dog.CLASS_NAME);\n        RealmObjectSchema ownerSchema = dynamicRealm.getSchema().get(CatOwner.CLASS_NAME);\n        ownerSchema.removeField(CatOwner.FIELD_CATS);\n        ownerSchema.addRealmListField(CatOwner.FIELD_CATS, dogSchema);\n        dynamicRealm.commitTransaction();\n        dynamicRealm.close();\n\n        try {\n            realm = Realm.getInstance(config);\n            fail();\n        } catch (RealmMigrationNeededException ignored) {\n            assertThat(ignored.getMessage(),\n                    CoreMatchers.containsString(\"Property 'CatOwner.cats' has been changed from 'array<Dog>' to 'array<Cat>'\"));\n        }\n    }\n\n    // Pre-null Realms will leave columns not-nullable after the underlying storage engine has\n    // migrated the file format. But @Required must be added, and forgetting so will give you\n    // a RealmMigrationNeeded exception.\n    @Test\n    public void openPreNullRealmRequiredMissing() throws IOException {\n        configFactory.copyRealmFromAssets(context,\n                \"string-only-pre-null-0.82.2.realm\", Realm.DEFAULT_REALM_NAME);\n        RealmMigration realmMigration = new RealmMigration() {\n            @Override\n            public void migrate(DynamicRealm realm, long oldVersion, long newVersion) {\n                // Intentionally lefts empty.\n            }\n        };\n\n        try {\n            RealmConfiguration realmConfig = configFactory.createConfigurationBuilder()\n                    .schemaVersion(0)\n                    .schema(StringOnly.class)\n                    .migration(realmMigration)\n                    .build();\n            Realm realm = Realm.getInstance(realmConfig);\n            realm.close();\n            fail();\n        } catch (RealmMigrationNeededException e) {\n            assertThat(e.getMessage(), CoreMatchers.containsString(\n                    \"Property 'StringOnly.chars' has been made optional\"));\n        }\n    }\n\n    // Pre-null Realms will leave columns not-nullable after the underlying storage engine has\n    // migrated the file format. An explicit migration step to convert to nullable, and the\n    // old class (without @Required) can be used,\n    @Test\n    public void migratePreNull() throws IOException {\n        final AtomicBoolean migrationCalled = new AtomicBoolean(false);\n        configFactory.copyRealmFromAssets(context,\n                \"string-only-pre-null-0.82.2.realm\", Realm.DEFAULT_REALM_NAME);\n        RealmMigration migration = new RealmMigration() {\n            @Override\n            public void migrate(DynamicRealm realm, long oldVersion, long newVersion) {\n                RealmObjectSchema objectSchema = realm.getSchema().get(StringOnly.CLASS_NAME);\n                objectSchema.setRequired(StringOnly.FIELD_CHARS, false);\n                migrationCalled.set(true);\n            }\n        };\n\n        RealmConfiguration realmConfig = configFactory.createConfigurationBuilder()\n                .schemaVersion(1)\n                .schema(StringOnly.class)\n                .migration(migration)\n                .build();\n        Realm realm = Realm.getInstance(realmConfig);\n        assertTrue(migrationCalled.get());\n\n        StringOnly stringOnly = realm.where(StringOnly.class).findFirst();\n        assertNotNull(stringOnly);\n        // This object was created with 0.82.2\n        assertEquals(\"String_set_with_0.82.2\", stringOnly.getChars());\n        realm.beginTransaction();\n        stringOnly.setChars(null);\n        realm.commitTransaction();\n        realm.close();\n    }\n\n    // Pre-null Realms will leave columns not-nullable after the underlying storage engine has\n    // migrated the file format. If the user adds the @Required annotation to a field and does not\n    // change the schema version, no migration is needed. But then, null cannot be used as a value.\n    @Test\n    public void openPreNullWithRequired() throws IOException {\n        configFactory.copyRealmFromAssets(context, \"string-only-required-pre-null-0.82.2.realm\", Realm.DEFAULT_REALM_NAME);\n        RealmConfiguration realmConfig = configFactory.createConfigurationBuilder()\n                .schemaVersion(0)\n                .schema(StringOnlyRequired.class)\n                .build();\n        Realm realm = Realm.getInstance(realmConfig);\n\n        StringOnlyRequired stringOnlyRequired = realm.where(StringOnlyRequired.class).findFirst();\n        assertNotNull(stringOnlyRequired);\n        // This object was created with 0.82.2\n        assertEquals(\"String_set_with_0.82.2\", stringOnlyRequired.getChars());\n\n        realm.beginTransaction();\n        try {\n            stringOnlyRequired.setChars(null);\n            fail();\n        } catch (IllegalArgumentException expected) {\n            assertThat(expected.getMessage(),\n                    CoreMatchers.containsString(\"Trying to set non-nullable field 'chars' to null.\"));\n        }\n        realm.cancelTransaction();\n\n        realm.close();\n    }\n\n    // If a required field was nullable before, a RealmMigrationNeededException should be thrown.\n    @Test\n    public void notSettingRequiredForNotNullableThrows() {\n        String[] notNullableFields = {NullTypes.FIELD_STRING_NOT_NULL, NullTypes.FIELD_BYTES_NOT_NULL,\n                NullTypes.FIELD_BOOLEAN_NOT_NULL, NullTypes.FIELD_BYTE_NOT_NULL, NullTypes.FIELD_SHORT_NOT_NULL,\n                NullTypes.FIELD_INTEGER_NOT_NULL, NullTypes.FIELD_LONG_NOT_NULL, NullTypes.FIELD_FLOAT_NOT_NULL,\n                NullTypes.FIELD_DOUBLE_NOT_NULL, NullTypes.FIELD_DATE_NOT_NULL};\n        for (final String field : notNullableFields) {\n            final RealmMigration migration = new RealmMigration() {\n                @Override\n                public void migrate(DynamicRealm realm, long oldVersion, long newVersion) {\n                    if (oldVersion == 0) { // 0 after initNullTypesTableExcludes\n                        // No @Required for not nullable field\n                        RealmObjectSchema nullTypesSchema = realm.getSchema().get(NullTypes.CLASS_NAME);\n                        if (field.equals(NullTypes.FIELD_STRING_NOT_NULL)) {\n                            // 1 String\n                            nullTypesSchema.addField(field, String.class);\n                        } else if (field.equals(NullTypes.FIELD_BYTES_NOT_NULL)) {\n                            // 2 Bytes\n                            nullTypesSchema.addField(field, byte[].class);\n                        } else if (field.equals(NullTypes.FIELD_BOOLEAN_NOT_NULL)) {\n                            // 3 Boolean\n                            nullTypesSchema.addField(field, Boolean.class);\n                            //table.addColumn(RealmFieldType.BOOLEAN, field, Table.NULLABLE);\n                        } else if (field.equals(NullTypes.FIELD_BYTE_NOT_NULL) ||\n                                field.equals(NullTypes.FIELD_SHORT_NOT_NULL) ||\n                                field.equals(NullTypes.FIELD_INTEGER_NOT_NULL) ||\n                                field.equals(NullTypes.FIELD_LONG_NOT_NULL)) {\n                            // 4 Byte 5 Short 6 Integer 7 Long\n                            nullTypesSchema.addField(field, Integer.class);\n                        } else if (field.equals(NullTypes.FIELD_FLOAT_NOT_NULL)) {\n                            // 8 Float\n                            nullTypesSchema.addField(field, Float.class);\n                        } else if (field.equals(NullTypes.FIELD_DOUBLE_NOT_NULL)) {\n                            // 9 Double\n                            nullTypesSchema.addField(field, Double.class);\n                        } else if (field.equals(NullTypes.FIELD_DATE_NOT_NULL)) {\n                            // 10 Date\n                            nullTypesSchema.addField(field, Date.class);\n                        }\n                        // 11 Object skipped\n                    }\n                }\n            };\n\n            @SuppressWarnings(\"unchecked\")\n            RealmConfiguration realmConfig = configFactory.createConfigurationBuilder()\n                    .schemaVersion(1)\n                    .name(field)\n                    .schema(NullTypes.class)\n                    .migration(migration)\n                    .build();\n            Realm.deleteRealm(realmConfig);\n            // Prepares the version 0 db.\n            DynamicRealm dynamicRealm = DynamicRealm.getInstance(realmConfig);\n            TestHelper.initNullTypesTableExcludes(dynamicRealm, field);\n            dynamicRealm.close();\n\n            try {\n                realm = Realm.getInstance(realmConfig);\n                fail(\"Failed on \" + field);\n            } catch (RealmMigrationNeededException e) {\n                assertThat(e.getMessage(), CoreMatchers.containsString(\n                        String.format(Locale.US, \"Property 'NullTypes.%s' has been made required\", field)));\n            }\n        }\n    }\n\n    // If a field is not required but was not nullable before, a RealmMigrationNeededException should be thrown.\n    @Test\n    public void settingRequiredForNullableThrows() {\n        String[] notNullableFields = {NullTypes.FIELD_STRING_NULL, NullTypes.FIELD_BYTES_NULL,\n                NullTypes.FIELD_BOOLEAN_NULL, NullTypes.FIELD_BYTE_NULL, NullTypes.FIELD_SHORT_NULL,\n                NullTypes.FIELD_INTEGER_NULL, NullTypes.FIELD_LONG_NULL, NullTypes.FIELD_FLOAT_NULL,\n                NullTypes.FIELD_DOUBLE_NULL, NullTypes.FIELD_DATE_NULL};\n        for (final String field : notNullableFields) {\n            final RealmMigration migration = new RealmMigration() {\n                @Override\n                public void migrate(DynamicRealm realm, long oldVersion, long newVersion) {\n                    if (oldVersion == 0) { // 0 after initNullTypesTableExcludes\n                        // No @Required for not nullable field\n                        RealmObjectSchema nullTypesSchema = realm.getSchema().get(NullTypes.CLASS_NAME);\n                        if (field.equals(NullTypes.FIELD_STRING_NULL)) {\n                            // 1 String\n                            nullTypesSchema.addField(field, String.class, FieldAttribute.REQUIRED);\n                        } else if (field.equals(NullTypes.FIELD_BYTES_NULL)) {\n                            // 2 Bytes\n                            nullTypesSchema.addField(field, byte[].class, FieldAttribute.REQUIRED);\n                        } else if (field.equals(NullTypes.FIELD_BOOLEAN_NULL)) {\n                            // 3 Boolean\n                            nullTypesSchema.addField(field, boolean.class);\n                        } else if (field.equals(NullTypes.FIELD_BYTE_NULL) ||\n                                field.equals(NullTypes.FIELD_SHORT_NULL) ||\n                                field.equals(NullTypes.FIELD_INTEGER_NULL) ||\n                                field.equals(NullTypes.FIELD_LONG_NULL)) {\n                            // 4 Byte 5 Short 6 Integer 7 Long\n                            nullTypesSchema.addField(field, int.class);\n                        } else if (field.equals(NullTypes.FIELD_FLOAT_NULL)) {\n                            // 8 Float\n                            nullTypesSchema.addField(field, float.class);\n                        } else if (field.equals(NullTypes.FIELD_DOUBLE_NULL)) {\n                            // 9 Double\n                            nullTypesSchema.addField(field, double.class);\n                        } else if (field.equals(NullTypes.FIELD_DATE_NULL)) {\n                            // 10 Date\n                            nullTypesSchema.addField(field, Date.class, FieldAttribute.REQUIRED);\n                        }\n                        // 11 Object skipped\n                    }\n                }\n            };\n\n            @SuppressWarnings(\"unchecked\")\n            RealmConfiguration realmConfig = configFactory.createConfigurationBuilder()\n                    .schemaVersion(1)\n                    .name(field)\n                    .schema(NullTypes.class)\n                    .migration(migration)\n                    .build();\n            Realm.deleteRealm(realmConfig);\n            // Prepares the version 0 db.\n            DynamicRealm dynamicRealm = DynamicRealm.getInstance(realmConfig);\n            TestHelper.initNullTypesTableExcludes(dynamicRealm, field);\n            dynamicRealm.close();\n\n            try {\n                realm = Realm.getInstance(realmConfig);\n                fail(\"Failed on \" + field);\n            } catch (RealmMigrationNeededException e) {\n                assertThat(e.getMessage(), CoreMatchers.containsString(\n                        String.format(Locale.US, \"Property 'NullTypes.%s' has been made optional\", field)));\n            }\n        }\n    }\n\n    // Tests older Realms for setting Boxed type primary keys fields nullable in migration process to support Realm Version 0.89+.\n    @Test\n    public void settingNullableToPrimaryKey() throws IOException {\n        final long SCHEMA_VERSION = 67;\n        final Class[] classes = {PrimaryKeyAsBoxedByte.class, PrimaryKeyAsBoxedShort.class, PrimaryKeyAsBoxedInteger.class, PrimaryKeyAsBoxedLong.class, PrimaryKeyAsString.class};\n        for (final Class clazz : classes) {\n            final AtomicBoolean didMigrate = new AtomicBoolean(false);\n            RealmMigration migration = new RealmMigration() {\n                @Override\n                public void migrate(DynamicRealm realm, long oldVersion, long newVersion) {\n                    RealmObjectSchema schema = realm.getSchema().get(clazz.getSimpleName());\n                    if (clazz == PrimaryKeyAsString.class) {\n                        schema.setNullable(\"name\", true);\n                    } else {\n                        schema.setNullable(\"id\", true);\n                    }\n                    didMigrate.set(true);\n                }\n            };\n            RealmConfiguration realmConfig = configFactory.createConfigurationBuilder()\n                    .schemaVersion(SCHEMA_VERSION)\n                    .schema(clazz)\n                    .migration(migration)\n                    .build();\n            Realm.deleteRealm(realmConfig);\n            configFactory.copyRealmFromAssets(context, \"default-notnullable-primarykey.realm\", Realm.DEFAULT_REALM_NAME);\n            Realm.migrateRealm(realmConfig);\n            realm = Realm.getInstance(realmConfig);\n            RealmObjectSchema schema = realm.getSchema().get(clazz.getSimpleName());\n            assertEquals(SCHEMA_VERSION, realm.getVersion());\n            assertTrue(didMigrate.get());\n            if (clazz == PrimaryKeyAsString.class) {\n                assertEquals(true, schema.isNullable(PrimaryKeyAsString.FIELD_PRIMARY_KEY));\n            } else {\n                assertEquals(true, schema.isNullable(\"id\"));\n            }\n            realm.close();\n        }\n    }\n\n    // Not-setting older boxed type PrimaryKey field nullable to see if migration fails in order to support Realm version 0.89+.\n    @Test\n    public void notSettingNullableToPrimaryKeyThrows() throws IOException {\n        configFactory.copyRealmFromAssets(context, \"default-notnullable-primarykey.realm\", Realm.DEFAULT_REALM_NAME);\n        final Class[] classes = {PrimaryKeyAsString.class, PrimaryKeyAsBoxedByte.class, PrimaryKeyAsBoxedShort.class, PrimaryKeyAsBoxedInteger.class, PrimaryKeyAsBoxedLong.class};\n        for (final Class clazz : classes) {\n            try {\n                RealmConfiguration realmConfig = configFactory.createConfigurationBuilder()\n                        .schemaVersion(0)\n                        .schema(clazz)\n                        .migration(new RealmMigration() {\n                            @Override\n                            public void migrate(DynamicRealm realm, long oldVersion, long newVersion) {\n                                // Intentionally lefts empty to preserve not-nullablility of PrimaryKey on old schema.\n                            }\n                        })\n                        .build();\n                Realm realm = Realm.getInstance(realmConfig);\n                realm.close();\n                fail();\n            } catch (RealmMigrationNeededException expected) {\n                String pkFieldName = \"id\";\n                if (clazz == PrimaryKeyAsString.class) {\n                    pkFieldName = \"name\";\n                }\n                assertThat(expected.getMessage(), CoreMatchers.containsString(String.format(Locale.US,\n                        \"Property '%s.%s' has been made optional\", clazz.getSimpleName(), pkFieldName)));\n            }\n        }\n    }\n\n    // Migrates a nullable field containing null value to non-nullable PrimaryKey field throws Realm version 0.89+.\n    @Test\n    public void migrating_nullableField_toward_notNullable_PrimaryKeyThrows() throws IOException {\n        configFactory.copyRealmFromAssets(context, \"default-nullable-primarykey.realm\", Realm.DEFAULT_REALM_NAME);\n        final Class[] classes = {PrimaryKeyAsByte.class, PrimaryKeyAsShort.class, PrimaryKeyAsInteger.class, PrimaryKeyAsLong.class};\n        for (final Class clazz : classes) {\n            try {\n                RealmConfiguration realmConfig = configFactory.createConfigurationBuilder()\n                        .schema(clazz)\n                        .build();\n                Realm realm = Realm.getInstance(realmConfig);\n                realm.close();\n                fail();\n            } catch (RealmMigrationNeededException expected) {\n                assertThat(expected.getMessage(), CoreMatchers.containsString(\n                        String.format(\"Property '%s.%s' has been made required\", clazz.getSimpleName(), \"id\")));\n            }\n        }\n    }\n\n    @Test\n    public void realmOpenBeforeMigrationThrows() throws FileNotFoundException {\n        RealmConfiguration config = configFactory.createConfiguration();\n        realm = Realm.getInstance(config);\n\n        try {\n            // Triggers manual migration. This can potentially change the schema, so should only be allowed when\n            // no-one else is working on the Realm.\n            Realm.migrateRealm(config, new RealmMigration() {\n                @Override\n                public void migrate(DynamicRealm realm, long oldVersion, long newVersion) {\n                    // Does nothing.\n                }\n            });\n            fail();\n        } catch (IllegalStateException ignored) {\n        }\n    }\n\n    @Test\n    public void migrateRealm_config_nonExistingRealmFile() throws FileNotFoundException {\n        RealmConfiguration config = configFactory.createConfigurationBuilder().migration(new RealmMigration() {\n            @Override\n            public void migrate(DynamicRealm realm, long oldVersion, long newVersion) {\n\n            }\n        }).build();\n        thrown.expect(FileNotFoundException.class);\n        Realm.migrateRealm(config);\n    }\n\n    @Test\n    public void migrateRealm_configMigration_nonExistingRealmFile() throws FileNotFoundException {\n        RealmMigration migration = new RealmMigration() {\n            @Override\n            public void migrate(DynamicRealm realm, long oldVersion, long newVersion) {\n\n            }\n        };\n        RealmConfiguration config = configFactory.createConfiguration();\n        thrown.expect(FileNotFoundException.class);\n        Realm.migrateRealm(config, migration);\n    }\n\n    @Test\n    public void renameAndAddField() {\n        final Class<MigrationFieldRenameAndAdd> schemaClass = MigrationFieldRenameAndAdd.class;\n\n        RealmMigration migration = new RealmMigration() {\n            @Override\n            public void migrate(DynamicRealm realm, long oldVersion, long newVersion) {\n                realm.getSchema().get(schemaClass.getSimpleName())\n                        .renameField(\"string1\", \"string2\")\n                        .addField(\"string1\", String.class);\n            }\n        };\n\n        RealmConfiguration config = configFactory.createConfigurationBuilder()\n                .schema(schemaClass)\n                .schemaVersion(2)\n                .migration(migration)\n                .assetFile(\"rename-and-add.realm\")\n                .build();\n        Realm realm = Realm.getInstance(config);\n\n        RealmObjectSchema schema = realm.getSchema().get(schemaClass.getSimpleName());\n        assertTrue(schema.hasField(\"string1\"));\n        assertTrue(schema.hasField(\"string2\"));\n        realm.close();\n    }\n\n    @Test\n    public void renameAndAddIndexedField() {\n        final Class<MigrationIndexedFieldRenamed> schemaClass = MigrationIndexedFieldRenamed.class;\n        final int oldTestVal = 7;\n        final Long testVal = Long.valueOf(293);\n\n        RealmMigration migration = new RealmMigration() {\n            @Override\n            public void migrate(DynamicRealm realm, long oldVersion, long newVersion) {\n                realm.getSchema().get(schemaClass.getSimpleName())\n                        .renameField(\"testField\", \"oldTestField\")\n                        .addField(\"testField\", Long.class);\n            }\n        };\n\n        RealmConfiguration config = configFactory.createConfigurationBuilder()\n                .schema(schemaClass)\n                .schemaVersion(2)\n                .migration(migration)\n                .assetFile(\"rename-and-add-indexed.realm\")\n                .build();\n        realm = Realm.getInstance(config);\n\n        realm.beginTransaction();\n        MigrationIndexedFieldRenamed obj = realm.createObject(schemaClass, 2);\n        obj.oldTestField = oldTestVal;\n        obj.testField = testVal;\n        realm.commitTransaction();\n\n        RealmObjectSchema schema = realm.getSchema().get(schemaClass.getSimpleName());\n        assertTrue(schema.hasField(\"testField\"));\n        assertTrue(schema.hasField(\"oldTestField\"));\n        assertTrue(schema.hasIndex(\"oldTestField\"));\n\n        RealmResults<MigrationIndexedFieldRenamed> result = realm.where(schemaClass).equalTo(\"id\", 2).findAll();\n        assertEquals(\"There should be an object with PK=2\", 1, result.size());\n        assertEquals(\"Unexpected oldTestField value\", oldTestVal, result.first().oldTestField);\n        assertEquals(\"Unexpected testField value\", testVal, result.first().testField);\n\n        realm.close();\n    }\n\n    // Tests that if a migration is required and no migration block was provided, then the\n    // original RealmMigrationNeededException is thrown instead of IllegalArgumentException\n    @Test\n    public void migrationRequired_throwsOriginalException() {\n        RealmConfiguration config = configFactory.createConfigurationBuilder()\n                // .migration() No migration block provided, but one is required\n                .assetFile(\"default0.realm\") // This Realm does not have the correct schema\n                .build();\n\n        Realm realm = null;\n        try {\n            realm = Realm.getInstance(config);\n            fail();\n        } catch (RealmMigrationNeededException ignored) {\n        } finally {\n            if (realm != null) {\n                realm.close();\n            }\n        }\n    }\n\n    private void createEmptyRealmVersion0(RealmConfiguration configuration)  {\n        assertFalse(new File(configuration.getPath()).exists());\n\n        DynamicRealm realm = DynamicRealm.getInstance(configuration);\n        realm.beginTransaction();\n        realm.setVersion(0);\n        realm.commitTransaction();\n        realm.close();\n    }\n\n    @Test\n    public void migrationRequired_throwsExceptionInTheMigrationBlock() {\n        final RuntimeException exception = new RuntimeException(\"TEST\");\n\n        RealmMigration migration = new RealmMigration() {\n            @Override\n            public void migrate(DynamicRealm realm, long oldVersion, long newVersion) {\n                // The transaction should be canceled and this model should not be created.\n                RealmObjectSchema objectSchema = realm.getSchema().create(StringOnly.CLASS_NAME);\n                objectSchema.addField(StringOnly.FIELD_CHARS, String.class);\n                throw exception;\n            }\n        };\n        RealmConfiguration config = configFactory.createConfigurationBuilder()\n                .migration(migration)\n                .schemaVersion(1)\n                .schema(StringOnly.class)\n                .build();\n        createEmptyRealmVersion0(config);\n\n        Realm realm = null;\n        try {\n            realm = Realm.getInstance(config);\n            fail();\n        } catch (RuntimeException expected) {\n            assertSame(exception, expected);\n        } finally {\n            if (realm != null) {\n                realm.close();\n            }\n        }\n\n        DynamicRealm dynamicRealm = DynamicRealm.getInstance(config);\n        try {\n            assertEquals(0, dynamicRealm.getVersion());\n            assertNull(dynamicRealm.getSchema().get(StringOnly.CLASS_NAME));\n        } finally {\n            dynamicRealm.close();\n        }\n    }\n\n    // File format 9 (up to Core5) added an index automatically to the primary key, in Core6\n    // (File format 10) string based PK are not indexed because the search index is derived from\n    // the ObjectKey. So the Index was stripped if found. However, this turned out to cause other bugs: https://github.com/realm/realm-core/pull/3893\n    // In file format 11, the index is thus re-added for String primary keys.\n    @Test\n    public void core5AutomaticIndexOnStringPKShouldOpenInCore6() throws IOException {\n        configFactory.copyRealmFromAssets(context,\n                \"core6_string_pk_indexed.realm\", \"core6.realm\");\n        Realm realm = Realm.getInstance(configFactory.createConfigurationBuilder()\n                .name(\"core6.realm\")\n                .schema(MigrationCore6PKStringIndexedByDefault.class)\n                .build());\n        assertFalse(realm.isEmpty());\n        // Upgrading to Core 10 will retain all indexes on primary keys.\n        assertTrue(realm.getSchema().get(\"MigrationCore6PKStringIndexedByDefault\").hasIndex(\"name\"));\n        MigrationCore6PKStringIndexedByDefault first = realm.where(MigrationCore6PKStringIndexedByDefault.class).findFirst();\n        assertNotNull(first);\n        assertEquals(\"Foo\", first.name);\n    }\n\n    @Test\n    public void migrateRealm_addPrimaryKey_objectId() {\n        // Creates v0 of the Realm.\n        RealmConfiguration originalConfig = configFactory.createConfigurationBuilder()\n                .schema(StringOnly.class)\n                .build();\n        Realm.getInstance(originalConfig).close();\n\n        RealmMigration migration = new RealmMigration() {\n            @Override\n            public void migrate(DynamicRealm realm, long oldVersion, long newVersion) {\n                RealmSchema schema = realm.getSchema();\n                schema.create(ObjectIdPrimaryKey.CLASS_NAME)\n                        .addField(ObjectIdPrimaryKey.PROPERTY_OBJECT_ID, ObjectId.class)\n                        .addPrimaryKey(ObjectIdPrimaryKey.PROPERTY_OBJECT_ID);\n            }\n        };\n\n        // Creates v1 of the Realm.\n        RealmConfiguration realmConfig = configFactory.createConfigurationBuilder()\n                .schemaVersion(1)\n                .schema(StringOnly.class, ObjectIdPrimaryKey.class)\n                .migration(migration)\n                .build();\n\n        realm = Realm.getInstance(realmConfig);\n        RealmObjectSchema schema = realm.getSchema().get(ObjectIdPrimaryKey.CLASS_NAME);\n        assertTrue(schema.hasPrimaryKey());\n        assertTrue(schema.hasIndex(ObjectIdPrimaryKey.PROPERTY_OBJECT_ID));\n        realm.close();\n    }\n\n    @Test\n    public void migrateRealm_addPrimaryKey_UUID() {\n        // Creates v0 of the Realm.\n        RealmConfiguration originalConfig = configFactory.createConfigurationBuilder()\n                .schema(StringOnly.class)\n                .build();\n        Realm.getInstance(originalConfig).close();\n\n        RealmMigration migration = new RealmMigration() {\n            @Override\n            public void migrate(DynamicRealm realm, long oldVersion, long newVersion) {\n                RealmSchema schema = realm.getSchema();\n                schema.create(PrimaryKeyAsUUID.CLASS_NAME)\n                        .addField(PrimaryKeyAsUUID.FIELD_PRIMARY_KEY, UUID.class)\n                        .addPrimaryKey(PrimaryKeyAsUUID.FIELD_PRIMARY_KEY)\n                        .addField(PrimaryKeyAsUUID.FIELD_NAME, String.class);\n            }\n        };\n\n        // Creates v1 of the Realm.\n        RealmConfiguration realmConfig = configFactory.createConfigurationBuilder()\n                .schemaVersion(1)\n                .schema(StringOnly.class, PrimaryKeyAsUUID.class)\n                .migration(migration)\n                .build();\n\n        realm = Realm.getInstance(realmConfig);\n        RealmObjectSchema schema = realm.getSchema().get(PrimaryKeyAsUUID.CLASS_NAME);\n        assertTrue(schema.hasPrimaryKey());\n        assertTrue(schema.hasIndex(PrimaryKeyAsUUID.FIELD_PRIMARY_KEY));\n        realm.close();\n    }\n\n    @Test\n    public void migrateRealm_realmAnyNotIndexed() {\n        // Creates v0 of the Realm.\n        RealmConfiguration originalConfig = configFactory.createConfigurationBuilder()\n                .schema(StringOnly.class)\n                .build();\n\n        Realm.getInstance(originalConfig).close();\n\n        RealmMigration migration = new RealmMigration() {\n            @Override\n            public void migrate(DynamicRealm realm, long oldVersion, long newVersion) {\n                RealmSchema schema = realm.getSchema();\n                schema.create(RealmAnyNotIndexed.CLASS_NAME)\n                        .addField(RealmAnyNotIndexed.FIELD_REALM_ANY, RealmAny.class);\n            }\n        };\n\n        // Creates v1 of the Realm.\n        RealmConfiguration realmConfig = configFactory\n                .createConfigurationBuilder()\n                .schemaVersion(1)\n                .schema(StringOnly.class, RealmAnyNotIndexed.class)\n                .migration(migration)\n                .build();\n\n        realm = Realm.getInstance(realmConfig);\n        RealmObjectSchema objectSchema = realm.getSchema().get(RealmAnyNotIndexed.CLASS_NAME);\n        assertTrue(objectSchema.hasField(RealmAnyNotIndexed.FIELD_REALM_ANY));\n        assertFalse(objectSchema.hasIndex(RealmAnyNotIndexed.FIELD_REALM_ANY));\n        realm.close();\n    }\n\n    @Test(expected = IllegalStateException.class)\n    public void migrateRealm_realmAnyDeleteLinkedTable() {\n        // Creates v0 of the Realm.\n        RealmConfiguration originalConfig = configFactory.createConfigurationBuilder()\n                .schema(StringOnly.class, RealmAnyNotIndexed.class)\n                .build();\n\n        Realm realm = Realm.getInstance(originalConfig);\n\n        realm.executeTransaction(transactionRealm -> {\n            RealmAnyNotIndexed realmAnyNotIndexed = new RealmAnyNotIndexed();\n            StringOnly stringOnly = new StringOnly();\n            stringOnly.setChars(\"hello world\");\n            realmAnyNotIndexed.setRealmAny(RealmAny.valueOf(stringOnly));\n\n            transactionRealm.copyToRealm(realmAnyNotIndexed);\n        });\n\n        RealmResults<RealmAnyNotIndexed> results = realm.where(RealmAnyNotIndexed.class).findAll();\n        assertEquals(1, results.size());\n        assertNotNull(results.get(0));\n\n        RealmAny realmAny = results.get(0).getRealmAny();\n        assertEquals(RealmAny.Type.OBJECT, realmAny.getType());\n        assertEquals(StringOnly.class, realmAny.getValueClass());\n\n        realm.close();\n\n        RealmMigration migration = new RealmMigration() {\n            @Override\n            public void migrate(DynamicRealm realm, long oldVersion, long newVersion) {\n                RealmSchema schema = realm.getSchema();\n                schema.remove(StringOnly.CLASS_NAME);\n            }\n        };\n\n        // Creates v1 of the Realm.\n        RealmConfiguration realmConfig = configFactory\n                .createConfigurationBuilder()\n                .schemaVersion(1)\n                .schema(RealmAnyNotIndexed.class)\n                .migration(migration)\n                .build();\n\n        realm = Realm.getInstance(realmConfig);\n    }\n\n    @Test\n    public void migrateRealm_realmAnyIndexed() {\n        // Creates v0 of the Realm.\n        RealmConfiguration originalConfig = configFactory.createConfigurationBuilder()\n                .schema(StringOnly.class)\n                .build();\n\n        Realm.getInstance(originalConfig).close();\n\n        RealmMigration migration = new RealmMigration() {\n            @Override\n            public void migrate(DynamicRealm realm, long oldVersion, long newVersion) {\n                RealmSchema schema = realm.getSchema();\n                schema.create(RealmAnyIndexed.CLASS_NAME)\n                        .addField(RealmAnyIndexed.FIELD_REALM_ANY, RealmAny.class, FieldAttribute.INDEXED);\n            }\n        };\n\n        // Creates v1 of the Realm.\n        RealmConfiguration realmConfig = configFactory\n                .createConfigurationBuilder()\n                .schemaVersion(1)\n                .schema(StringOnly.class, RealmAnyIndexed.class)\n                .migration(migration)\n                .build();\n\n        realm = Realm.getInstance(realmConfig);\n        RealmObjectSchema objectSchema = realm.getSchema().get(RealmAnyIndexed.CLASS_NAME);\n\n        assertTrue(objectSchema.hasField(RealmAnyIndexed.FIELD_REALM_ANY));\n        assertTrue(objectSchema.hasIndex(RealmAnyIndexed.FIELD_REALM_ANY));\n\n        realm.close();\n    }\n\n    @Test\n    public void migrateRealm_realmAnyList() {\n        // Creates v0 of the Realm.\n        RealmConfiguration originalConfig = configFactory.createConfigurationBuilder()\n                .schema(StringOnly.class)\n                .build();\n\n        Realm.getInstance(originalConfig).close();\n\n        RealmMigration migration = new RealmMigration() {\n            @Override\n            public void migrate(DynamicRealm realm, long oldVersion, long newVersion) {\n                RealmSchema schema = realm.getSchema();\n                schema.create(RealmAnyRealmListWithPK.CLASS_NAME)\n                        .addField(RealmAnyRealmListWithPK.PK, long.class, FieldAttribute.PRIMARY_KEY)\n                        .addRealmListField(RealmAnyRealmListWithPK.FIELD_REALM_ANY, RealmAny.class);\n            }\n        };\n\n        // Creates v1 of the Realm.\n        RealmConfiguration realmConfig = configFactory\n                .createConfigurationBuilder()\n                .schemaVersion(1)\n                .schema(StringOnly.class, RealmAnyRealmListWithPK.class)\n                .migration(migration)\n                .build();\n\n        realm = Realm.getInstance(realmConfig);\n        RealmObjectSchema objectSchema = realm.getSchema().get(RealmAnyRealmListWithPK.CLASS_NAME);\n        assertTrue(objectSchema.hasField(RealmAnyRealmListWithPK.FIELD_REALM_ANY));\n        assertEquals(RealmFieldType.MIXED_LIST, objectSchema.getFieldType(RealmAnyRealmListWithPK.FIELD_REALM_ANY));\n        assertTrue(objectSchema.hasPrimaryKey());\n        realm.close();\n    }\n\n    @Test\n    public void migrate_embeddedObject(){\n        // Create schema v0\n        RealmConfiguration originalConfig = configFactory.createConfigurationBuilder()\n                .schema(StringOnly.class)\n                .build();\n\n        Realm.getInstance(originalConfig).close();\n\n        RealmMigration migration = new RealmMigration() {\n            @Override\n            public void migrate(DynamicRealm realm, long oldVersion, long newVersion) {\n                RealmSchema schema = realm.getSchema();\n                RealmObjectSchema embeddedSimpleChildSchema = schema\n                        .create(EmbeddedSimpleChild.NAME)\n                        .addField(\"childId\", String.class, FieldAttribute.REQUIRED);\n\n                schema.create(EmbeddedSimpleParent.NAME)\n                        .addField(\"_id\", String.class, FieldAttribute.PRIMARY_KEY, FieldAttribute.REQUIRED)\n                        .addRealmObjectField(EmbeddedSimpleParent.CHILD, embeddedSimpleChildSchema);\n\n                embeddedSimpleChildSchema.setEmbedded(true);\n            }\n        };\n\n        // Create schema v1\n        RealmConfiguration realmConfig = configFactory\n                .createConfigurationBuilder()\n                .schemaVersion(1)\n                .schema(StringOnly.class, EmbeddedSimpleParent.class, EmbeddedSimpleChild.class)\n                .migration(migration)\n                .build();\n\n        realm = Realm.getInstance(realmConfig);\n    }\n\n    @Test\n    public void migrate_embeddedObject_deleteOrphans() {\n        RealmConfiguration config1 = configFactory.createConfigurationBuilder()\n                .schema(HandleBackLinksParent1.class, HandleBackLinksChild1.class)\n                .schemaVersion(1)\n                .build();\n\n        Realm realm1 = Realm.getInstance(config1);\n        realm1.executeTransaction(realm -> {\n            HandleBackLinksChild1 child = new HandleBackLinksChild1();\n            HandleBackLinksParent1 parent = new HandleBackLinksParent1();\n            parent.child = child;\n            HandleBackLinksChild1 orphan = new HandleBackLinksChild1();\n            realm.insertOrUpdate(parent);\n            realm.insertOrUpdate(orphan);\n        });\n        long parentCountV1 = realm1.where(HandleBackLinksParent1.class)\n                .count();\n        assertEquals(1L, parentCountV1);\n        long childCountV1 = realm1.where(HandleBackLinksChild1.class)\n                .count();\n        assertEquals(2L, childCountV1);\n        realm1.close();\n\n        RealmMigration migration = (realm, oldVersion, newVersion) -> {\n            RealmSchema schema = realm.getSchema();\n            if (oldVersion == 1L) {\n                RealmObjectSchema parent = schema.get(\"HandleBackLinksParent1\");\n                assertNotNull(parent);\n                RealmObjectSchema child = schema.get(\"HandleBackLinksChild1\");\n                assertNotNull(child);\n                try {\n                    child.setEmbedded(true);\n                } catch (Exception e) {\n                    assertEquals(IllegalStateException.class, e.getClass());\n                    assertEquals(\"Cannot convert 'HandleBackLinksChild1' to embedded: at least one object has no incoming links and would be deleted.\", e.getMessage());\n                }\n                child.setEmbedded(true, true);\n\n                // Rename classes to avoid conflicts with all other tests\n                parent.setClassName(\"HandleBackLinksParent2\");\n                child.setClassName(\"HandleBackLinksChild2\");\n            }\n        };\n\n        // Create schema v2\n        RealmConfiguration config2 = configFactory.createConfigurationBuilder()\n                .schema(HandleBackLinksParent2.class, HandleBackLinksChild2.class)\n                .schemaVersion(2)\n                .migration(migration)\n                .build();\n\n        // The orphan child is erased\n        Realm realm2 = Realm.getInstance(config2);\n        long parentCountV2 = realm2.where(HandleBackLinksParent2.class)\n                .count();\n        assertEquals(1L, parentCountV2);\n        long childCountV2 = realm2.where(HandleBackLinksChild2.class)\n                .count();\n        assertEquals(1L, childCountV2);\n        realm2.close();\n    }\n\n    @Test\n    public void migrate_embeddedObject_clonesChildWhenReferencedMoreThanOnce() {\n        RealmConfiguration config1 = configFactory.createConfigurationBuilder()\n                .schema(HandleBackLinksParent1.class, HandleBackLinksChild1.class)\n                .schemaVersion(1)\n                .build();\n\n        Realm realm1 = Realm.getInstance(config1);\n        HandleBackLinksChild1 child = new HandleBackLinksChild1();\n        HandleBackLinksParent1 parent1 = new HandleBackLinksParent1();\n        HandleBackLinksParent1 parent2 = new HandleBackLinksParent1();\n        realm1.executeTransaction(realm -> {\n            // Copy child and set it as children for both parents.\n            // Now the managed child has two parents. This will not be allowed after converting it\n            // to an embedded object and will result into the child object being duplicated so that\n            // both parents can have a reference to a separate and different embedded object.\n            HandleBackLinksChild1 managedChild = realm.copyToRealm(child);\n            parent1.id = 1L;\n            parent1.child = managedChild;\n            realm.insert(parent1);\n            parent2.id = 2L;\n            parent2.child = managedChild;\n            realm.insert(parent2);\n        });\n        long parentCountV1 = realm1.where(HandleBackLinksParent1.class)\n                .count();\n        assertEquals(2L, parentCountV1);\n        long childCountV1 = realm1.where(HandleBackLinksChild1.class)\n                .count();\n        assertEquals(1L, childCountV1);\n        realm1.close();\n\n        RealmMigration migration = (realm, oldVersion, newVersion) -> {\n            RealmSchema schema = realm.getSchema();\n            if (oldVersion == 1L) {\n                RealmObjectSchema parentSchema = schema.get(\"HandleBackLinksParent1\");\n                assertNotNull(parentSchema);\n                RealmObjectSchema childSchema = schema.get(\"HandleBackLinksChild1\");\n                assertNotNull(childSchema);\n                childSchema.setEmbedded(true, true);\n\n                // Rename classes to avoid conflicts with all other tests\n                parentSchema.setClassName(\"HandleBackLinksParent2\");\n                childSchema.setClassName(\"HandleBackLinksChild2\");\n            }\n        };\n\n        // Create schema v2\n        RealmConfiguration config2 = configFactory.createConfigurationBuilder()\n                .schema(HandleBackLinksParent2.class, HandleBackLinksChild2.class)\n                .schemaVersion(2)\n                .migration(migration)\n                .build();\n\n        // After the migration the only child class is embedded and will not be allowed to have two parents\n        // so the child object will be duplicated\n        Realm realm2 = Realm.getInstance(config2);\n        long parentCountV2 = realm2.where(HandleBackLinksParent2.class)\n                .count();\n        assertEquals(2L, parentCountV2);\n        long childCountV2 = realm2.where(HandleBackLinksChild2.class)\n                .count();\n        assertEquals(2L, childCountV2);\n        realm2.close();\n    }\n\n    // TODO Add unit tests for default nullability\n    // TODO Add unit tests for default Indexing for Primary keys\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/RealmModelTests.java",
    "content": "/*\n * Copyright 2016 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\npackage io.realm;\n\nimport android.content.Context;\nimport android.os.Build;\nimport androidx.test.platform.app.InstrumentationRegistry;\nimport androidx.test.ext.junit.runners.AndroidJUnit4;\n\nimport org.junit.After;\nimport org.junit.Assert;\nimport org.junit.Before;\nimport org.junit.Rule;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\n\nimport java.io.IOException;\nimport java.util.Date;\n\nimport io.realm.entities.AllTypes;\nimport io.realm.entities.pojo.AllTypesRealmModel;\nimport io.realm.entities.pojo.InvalidRealmModel;\nimport io.realm.entities.pojo.PojoWithRealmListOfRealmObject;\nimport io.realm.entities.pojo.RealmModelWithRealmListOfRealmModel;\nimport io.realm.entities.pojo.RealmModelWithRealmModelField;\nimport io.realm.entities.pojo.RealmObjectWithRealmListOfRealmModel;\nimport io.realm.entities.pojo.RealmObjectWithRealmModelField;\nimport io.realm.exceptions.RealmException;\nimport io.realm.rule.RunInLooperThread;\nimport io.realm.rule.RunTestInLooperThread;\n\nimport static io.realm.internal.test.ExtraTests.assertArrayEquals;\nimport static org.hamcrest.number.OrderingComparison.greaterThanOrEqualTo;\nimport static org.junit.Assert.assertEquals;\nimport static org.junit.Assert.assertNotNull;\nimport static org.junit.Assert.assertTrue;\nimport static org.junit.Assume.assumeThat;\n\n// Tests API methods when using a model class implementing RealmModel instead\n// of extending RealmObject.\n@RunWith(AndroidJUnit4.class)\npublic class RealmModelTests {\n    private final static int TEST_DATA_SIZE = 10;\n\n    private Context context;\n    private Realm realm;\n\n    @Rule\n    public final TestRealmConfigurationFactory configFactory = new TestRealmConfigurationFactory();\n\n    @Rule\n    public final RunInLooperThread looperThread = new RunInLooperThread();\n\n    @Before\n    public void setUp() {\n        // Injecting the Instrumentation instance is required\n        // for your test to run with AndroidJUnitRunner.\n        context = InstrumentationRegistry.getInstrumentation().getContext();\n        RealmConfiguration realmConfig = configFactory.createConfiguration();\n        realm = Realm.getInstance(realmConfig);\n    }\n\n    @After\n    public void tearDown() {\n        if (realm != null) {\n            realm.close();\n        }\n    }\n\n    private void populateTestRealm(Realm realm, int objects) {\n        realm.beginTransaction();\n        realm.delete(AllTypesRealmModel.class);\n        for (int i = 0; i < objects; ++i) {\n            AllTypesRealmModel allTypes = new AllTypesRealmModel();\n            allTypes.columnLong = i;\n            allTypes.columnBoolean = (i % 3) == 0;\n            allTypes.columnBinary = new byte[]{1, 2, 3};\n            allTypes.columnDate = new Date();\n            allTypes.columnDouble = Math.PI + i;\n            allTypes.columnFloat = 1.234567f;\n            allTypes.columnString = \"test data \";\n            allTypes.columnByte = 0x2A;\n            realm.copyToRealm(allTypes);\n        }\n        realm.commitTransaction();\n    }\n\n    @Test\n    public void createObject() {\n        for (int i = 1; i < 43; i++) { // Using i = 0 as PK will crash subsequent createObject\n                                       // since createObject uses default values.\n            realm.beginTransaction();\n            realm.createObject(AllTypesRealmModel.class, i);\n            realm.commitTransaction();\n        }\n\n        long size = realm.where(AllTypesRealmModel.class).count();\n        assertEquals(\"Realm.get is returning wrong result set\", 42, size);\n    }\n\n    @Test\n    public void copyToRealm() {\n        populateTestRealm(realm, TEST_DATA_SIZE);\n        long size = realm.where(AllTypesRealmModel.class).count();\n        assertEquals(\"Realm.get is returning wrong result set\", TEST_DATA_SIZE, size);\n    }\n\n\n    @Test\n    public void copyFromRealm() {\n        populateTestRealm(realm, TEST_DATA_SIZE);\n\n        AllTypesRealmModel realmObject = realm.where(AllTypesRealmModel.class)\n                .sort(AllTypesRealmModel.FIELD_LONG)\n                .findAll()\n                .first();\n        AllTypesRealmModel unmanagedObject = realm.copyFromRealm(realmObject);\n        assertArrayEquals(realmObject.columnBinary, unmanagedObject.columnBinary);\n        assertEquals(realmObject.columnString, unmanagedObject.columnString);\n        assertEquals(realmObject.columnLong, unmanagedObject.columnLong);\n        assertEquals(realmObject.columnFloat, unmanagedObject.columnFloat, 0.00000000001);\n        assertEquals(realmObject.columnDouble, unmanagedObject.columnDouble, 0.00000000001);\n        assertEquals(realmObject.columnBoolean, unmanagedObject.columnBoolean);\n        assertEquals(realmObject.columnDate, unmanagedObject.columnDate);\n        assertEquals(realmObject.hashCode(), unmanagedObject.hashCode());\n\n    }\n\n    @Test\n    public void copyToRealmOrUpdate() {\n        realm.executeTransaction(new Realm.Transaction() {\n            @Override\n            public void execute(Realm realm) {\n                AllTypesRealmModel obj = new AllTypesRealmModel();\n                obj.columnLong = 1;\n                realm.copyToRealm(obj);\n\n                AllTypesRealmModel obj2 = new AllTypesRealmModel();\n                obj2.columnLong = 1;\n                obj2.columnString = \"Foo\";\n                realm.copyToRealmOrUpdate(obj2);\n            }\n        });\n\n        assertEquals(1, realm.where(AllTypesRealmModel.class).count());\n\n        AllTypesRealmModel obj = realm.where(AllTypesRealmModel.class).findFirst();\n        assertNotNull(obj);\n        assertEquals(\"Foo\", obj.columnString);\n    }\n\n    @Test\n    public void createOrUpdateAllFromJson() throws IOException {\n        assumeThat(Build.VERSION.SDK_INT, greaterThanOrEqualTo(Build.VERSION_CODES.HONEYCOMB));\n\n        realm.beginTransaction();\n        realm.createOrUpdateAllFromJson(AllTypesRealmModel.class, TestHelper.loadJsonFromAssets(context, \"list_alltypes_primarykey.json\"));\n        realm.commitTransaction();\n\n        assertEquals(1, realm.where(AllTypesRealmModel.class).count());\n        AllTypesRealmModel obj = realm.where(AllTypesRealmModel.class).findFirst();\n        assertNotNull(obj);\n        assertEquals(\"Bar\", obj.columnString);\n        assertEquals(2.23F, obj.columnFloat, 0.000000001);\n        assertEquals(2.234D, obj.columnDouble, 0.000000001);\n        assertEquals(true, obj.columnBoolean);\n        assertArrayEquals(new byte[]{1, 2, 3}, obj.columnBinary);\n        assertEquals(new Date(2000), obj.columnDate);\n        assertEquals(\"Dog4\", obj.columnRealmObject.getName());\n        assertEquals(2, obj.columnRealmList.size());\n        assertEquals(\"Dog5\", obj.columnRealmList.get(0).getName());\n    }\n\n    // 'where' with filed selection.\n    @Test\n    public void query() {\n        populateTestRealm(realm, TEST_DATA_SIZE);\n\n        assertEquals(5, realm.where(AllTypesRealmModel.class).greaterThanOrEqualTo(AllTypesRealmModel.FIELD_DOUBLE, 8.1415).count());\n    }\n\n    // Async where with filed selection.\n    @Test\n    @RunTestInLooperThread\n    public void async_query() {\n        Realm realm = looperThread.getRealm();\n        populateTestRealm(realm, TEST_DATA_SIZE);\n\n        final RealmResults<AllTypesRealmModel> allTypesRealmModels = realm.where(AllTypesRealmModel.class).distinct(AllTypesRealmModel.FIELD_STRING).findAllAsync();\n        looperThread.keepStrongReference(allTypesRealmModels);\n        allTypesRealmModels.addChangeListener(new RealmChangeListener<RealmResults<AllTypesRealmModel>>() {\n            @Override\n            public void onChange(RealmResults<AllTypesRealmModel> object) {\n                assertEquals(1, allTypesRealmModels.size());\n                looperThread.testComplete();\n            }\n        });\n    }\n\n    @Test\n    public void dynamicObject() {\n        populateTestRealm(realm, TEST_DATA_SIZE);\n\n        AllTypesRealmModel typedObj = realm.where(AllTypesRealmModel.class).findFirst();\n        assertNotNull(typedObj);\n        DynamicRealmObject dObj = new DynamicRealmObject(typedObj);\n\n        realm.beginTransaction();\n        dObj.setByte(AllTypesRealmModel.FIELD_BYTE, (byte) 42);\n        assertEquals(42, dObj.getLong(AllTypesRealmModel.FIELD_BYTE));\n        assertEquals(42, typedObj.columnByte);\n\n        dObj.setBlob(AllTypesRealmModel.FIELD_BINARY, new byte[]{1, 2, 3});\n        Assert.assertArrayEquals(new byte[]{1, 2, 3}, dObj.getBlob(AllTypesRealmModel.FIELD_BINARY));\n        Assert.assertArrayEquals(new byte[]{1, 2, 3}, typedObj.columnBinary);\n        realm.cancelTransaction();\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void dynamicRealm() {\n        populateTestRealm(looperThread.getRealm(), TEST_DATA_SIZE);\n        final DynamicRealm dynamicRealm = DynamicRealm.getInstance(looperThread.getConfiguration());\n\n        dynamicRealm.beginTransaction();\n        DynamicRealmObject dog = dynamicRealm.createObject(AllTypesRealmModel.CLASS_NAME, 42);\n        assertEquals(42, dog.getLong(AllTypesRealmModel.FIELD_LONG));\n        dynamicRealm.commitTransaction();\n\n        RealmResults<DynamicRealmObject> allAsync = dynamicRealm.where(AllTypesRealmModel.CLASS_NAME).equalTo(AllTypesRealmModel.FIELD_LONG, 42).findAll();\n        allAsync.load();\n        assertTrue(allAsync.isLoaded());\n        assertEquals(1, allAsync.size());\n\n        dynamicRealm.beginTransaction();\n        allAsync.deleteAllFromRealm();\n        dynamicRealm.commitTransaction();\n\n        RealmResults<DynamicRealmObject> results = dynamicRealm.where(AllTypesRealmModel.CLASS_NAME).findAll();\n        assertEquals(TEST_DATA_SIZE, results.size());\n        for (int i = 0; i < TEST_DATA_SIZE; i++) {\n            assertEquals(Math.PI + i, results.get(i).getDouble(AllTypesRealmModel.FIELD_DOUBLE), 0.0000001);\n            assertEquals((i % 3) == 0, results.get(i).getBoolean(AllTypesRealmModel.FIELD_BOOLEAN));\n        }\n        dynamicRealm.close();\n        looperThread.testComplete();\n    }\n\n    // Exception expected when using in schema model not annotated.\n    // A valid model need to implement the interface RealmModel and annotate the class with @RealmClass.\n    // We expect in this test a runtime exception 'InvalidRealmModel is not part of the schema for this Realm.'.\n    @Test(expected = RealmException.class)\n    public void invalidModelDefinition() {\n        realm.beginTransaction();\n        realm.createObject(InvalidRealmModel.class);\n        realm.commitTransaction();\n    }\n\n    // Tests the behaviour of a RealmModel, containing a RealmList\n    // of other RealmModel, in managed and unmanaged mode.\n    @Test\n    public void realmModelWithRealmListOfRealmModel() {\n        RealmList<AllTypesRealmModel> allTypesRealmModels = new RealmList<AllTypesRealmModel>();\n        AllTypesRealmModel allTypePojo;\n        for (int i = 0; i < 10; i++) {\n            allTypePojo = new AllTypesRealmModel();\n            allTypePojo.columnLong = i;\n            allTypesRealmModels.add(allTypePojo);\n        }\n        AllTypesRealmModel pojo1 = allTypesRealmModels.get(1);\n        assertEquals(1, pojo1.columnLong);\n        allTypesRealmModels.move(1, 0);\n        assertEquals(0, allTypesRealmModels.indexOf(pojo1));\n\n        RealmModelWithRealmListOfRealmModel model = new RealmModelWithRealmListOfRealmModel();\n        model.setColumnRealmList(allTypesRealmModels);\n\n        realm.beginTransaction();\n        realm.copyToRealm(model);\n        realm.commitTransaction();\n\n        RealmResults<RealmModelWithRealmListOfRealmModel> all = realm.where(RealmModelWithRealmListOfRealmModel.class).findAll();\n        assertEquals(1, all.size());\n        assertEquals(10, all.first().getColumnRealmList().size());\n        assertEquals(1, all.first().getColumnRealmList().first().columnLong);\n    }\n\n    // Tests the behaviour of a RealmModel, containing a RealmList\n    // of RealmObject, in managed and unmanaged mode.\n    @Test\n    public void realmModelWithRealmListOfRealmObject() {\n        RealmList<AllTypes> allTypes = new RealmList<AllTypes>();\n        AllTypes allType;\n        for (int i = 0; i < 10; i++) {\n            allType = new AllTypes();\n            allType.setColumnLong(i);\n            allTypes.add(allType);\n        }\n        AllTypes pojo1 = allTypes.get(1);\n        assertEquals(1, pojo1.getColumnLong());\n        allTypes.move(1, 0);\n        assertEquals(0, allTypes.indexOf(pojo1));\n\n        PojoWithRealmListOfRealmObject model = new PojoWithRealmListOfRealmObject();\n        model.setColumnRealmList(allTypes);\n\n        realm.beginTransaction();\n        realm.copyToRealm(model);\n        realm.commitTransaction();\n\n        RealmResults<PojoWithRealmListOfRealmObject> all = realm.where(PojoWithRealmListOfRealmObject.class).findAll();\n        assertEquals(1, all.size());\n        assertEquals(10, all.first().getColumnRealmList().size());\n        assertEquals(1, all.first().getColumnRealmList().first().getColumnLong());\n    }\n\n    // Tests the behaviour of a RealmObject, containing a RealmList\n    // of RealmModel, in managed and unmanaged mode.\n    @Test\n    public void realmObjectWithRealmListOfRealmModel() {\n        RealmList<AllTypesRealmModel> allTypesRealmModel = new RealmList<AllTypesRealmModel>();\n        AllTypesRealmModel allTypePojo;\n        for (int i = 0; i < 10; i++) {\n            allTypePojo = new AllTypesRealmModel();\n            allTypePojo.columnLong = i;\n            allTypesRealmModel.add(allTypePojo);\n        }\n        AllTypesRealmModel pojo1 = allTypesRealmModel.get(1);\n        assertEquals(1, pojo1.columnLong);\n        allTypesRealmModel.move(1, 0);\n        assertEquals(0, allTypesRealmModel.indexOf(pojo1));\n\n        RealmObjectWithRealmListOfRealmModel model = new RealmObjectWithRealmListOfRealmModel();\n        model.setColumnRealmList(allTypesRealmModel);\n\n        realm.beginTransaction();\n        realm.copyToRealm(model);\n        realm.commitTransaction();\n\n        RealmResults<RealmObjectWithRealmListOfRealmModel> all = realm.where(RealmObjectWithRealmListOfRealmModel.class).findAll();\n        assertEquals(1, all.size());\n        assertEquals(10, all.first().getColumnRealmList().size());\n        assertEquals(1, all.first().getColumnRealmList().first().columnLong);\n    }\n\n    // Tests the behaviour of a RealmModel, containing a RealmModel field.\n    @Test\n    public void realmModelWithRealmModelField() {\n        RealmModelWithRealmModelField realmModelWithRealmModelField = new RealmModelWithRealmModelField();\n        AllTypesRealmModel allTypePojo = new AllTypesRealmModel();\n        allTypePojo.columnLong = 42;\n        realmModelWithRealmModelField.setAllTypesRealmModel(allTypePojo);\n\n        realm.beginTransaction();\n        realm.copyToRealm(realmModelWithRealmModelField);\n        realm.commitTransaction();\n\n        RealmResults<RealmModelWithRealmModelField> all = realm.where(RealmModelWithRealmModelField.class).findAll();\n        assertEquals(1, all.size());\n        assertEquals(42, all.first().getAllTypesRealmModel().columnLong);\n    }\n\n    // Tests the behaviour of a RealmObject, containing a RealmModel field.\n    @Test\n    public void realmObjectWithRealmModelField() {\n        RealmObjectWithRealmModelField realmObjectWithRealmModelField = new RealmObjectWithRealmModelField();\n        AllTypesRealmModel allTypePojo = new AllTypesRealmModel();\n        allTypePojo.columnLong = 42;\n        realmObjectWithRealmModelField.setAllTypesRealmModel(allTypePojo);\n\n        realm.beginTransaction();\n        realm.copyToRealm(realmObjectWithRealmModelField);\n        realm.commitTransaction();\n\n        RealmResults<RealmObjectWithRealmModelField> all = realm.where(RealmObjectWithRealmModelField.class).findAll();\n        assertEquals(1, all.size());\n        assertEquals(42, all.first().getAllTypesRealmModel().columnLong);\n    }\n}\n\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/RealmNullPrimaryKeyTests.java",
    "content": "/*\n * Copyright 2016 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\npackage io.realm;\n\nimport org.junit.After;\nimport org.junit.Before;\nimport org.junit.Rule;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.junit.runners.Parameterized;\n\nimport java.lang.reflect.InvocationTargetException;\nimport java.util.Arrays;\n\nimport io.realm.entities.PrimaryKeyAsBoxedByte;\nimport io.realm.entities.PrimaryKeyAsBoxedInteger;\nimport io.realm.entities.PrimaryKeyAsBoxedLong;\nimport io.realm.entities.PrimaryKeyAsBoxedShort;\nimport io.realm.entities.PrimaryKeyAsString;\nimport io.realm.exceptions.RealmPrimaryKeyConstraintException;\nimport io.realm.objectid.NullPrimaryKey;\n\nimport static org.junit.Assert.assertEquals;\nimport static org.junit.Assert.assertTrue;\nimport static org.junit.Assert.fail;\n\n@RunWith(Parameterized.class)\npublic class RealmNullPrimaryKeyTests {\n    @Rule\n    public final TestRealmConfigurationFactory configFactory = new TestRealmConfigurationFactory();\n\n    protected Realm realm;\n\n    @Before\n    public void setUp() {\n        RealmConfiguration realmConfig = configFactory.createConfiguration();\n        realm = Realm.getInstance(realmConfig);\n    }\n\n    @After\n    public void tearDown() {\n        if (realm != null) {\n            realm.close();\n        }\n    }\n\n    /**\n     * Base parameters for testing null-primary key value. The parameters are aligned in an order of\n     * 1) a test target class, 2) a primary key field class, 3) a secondary field class, 4) a secondary\n     * field value, and 5) an update value, accommodating {@interface NullPrimaryKey} to condense unit tests.\n     */\n    @Parameterized.Parameters\n    public static Iterable<Object[]> data() {\n        return Arrays.asList(new Object[][]{\n            // 1) Test target class          2) PK Class    3) 2nd Class  4) 2nd field value   5) 2nd field value for update\n            {PrimaryKeyAsString.class,       String.class,  long.class,   Long.valueOf(492412), Long.valueOf(991241)},\n            {PrimaryKeyAsBoxedByte.class,    Byte.class,    String.class, \"This-Is-Second-One\", \"Gosh Didnt KnowIt\"},\n            {PrimaryKeyAsBoxedShort.class,   Short.class,   String.class, \"AnyValueIsAccepted\", \"?YOUNOWKNOWRIGHT?\"},\n            {PrimaryKeyAsBoxedInteger.class, Integer.class, String.class, \"PlayWithSeondFied!\", \"HaHaHaHaHaHaHaHaH\"},\n            {PrimaryKeyAsBoxedLong.class,    Long.class,    String.class, \"Let's name a value\", \"KeyValueTestIsFun\"}\n        });\n    }\n\n    final private Class<? extends RealmObject> testClazz;\n    final private Class primaryKeyFieldType;\n    final private Class secondaryFieldType;\n    final private Object secondaryFieldValue;\n    final private Object updatingFieldValue;\n\n    public RealmNullPrimaryKeyTests(Class<? extends RealmObject> testClazz, Class primaryKeyFieldType, Class secondaryFieldType, Object secondaryFieldValue, Object updatingFieldValue) {\n        this.testClazz = testClazz;\n        this.primaryKeyFieldType = primaryKeyFieldType;\n        this.secondaryFieldType = secondaryFieldType;\n        this.secondaryFieldValue = secondaryFieldValue;\n        this.updatingFieldValue = updatingFieldValue;\n    }\n\n    // Adds a PrimaryKey object to a realm with values for its PrimaryKey field and secondary field.\n    private RealmObject addPrimaryKeyObjectToTestRealm(Realm testRealm) throws NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException {\n        RealmObject obj = (RealmObject) testClazz.getConstructor(primaryKeyFieldType, secondaryFieldType).newInstance(null, secondaryFieldValue);\n        testRealm.beginTransaction();\n        testRealm.copyToRealm(obj);\n        testRealm.commitTransaction();\n        return obj;\n    }\n\n    // Creates a RealmObject with null primarykey.\n    private void createNullPrimaryKeyObjectFromTestRealm(Realm testRealm) {\n        testRealm.beginTransaction();\n\n        RealmObject obj = testRealm.createObject(testClazz, null);\n        if (testClazz.equals(PrimaryKeyAsString.class)) {\n            ((PrimaryKeyAsString)obj).setId((long) secondaryFieldValue);\n        } else {\n            ((NullPrimaryKey)obj).setName(secondaryFieldValue);\n        }\n\n        testRealm.commitTransaction();\n    }\n\n    // Updates existing null PrimaryKey object with a new updating value.\n    private void updatePrimaryKeyObject(Realm testRealm, RealmObject realmObject) {\n        if (testClazz.equals(PrimaryKeyAsString.class)) {\n            ((PrimaryKeyAsString) realmObject).setId((long) updatingFieldValue);\n        } else {\n            ((NullPrimaryKey) realmObject).setName(updatingFieldValue);\n        }\n\n        testRealm.beginTransaction();\n        testRealm.copyToRealmOrUpdate(realmObject);\n        testRealm.commitTransaction();\n    }\n\n    // @PrimaryKey annotation accept null value properly as a primary key value for Realm version 0.89.1+.\n    @Test\n    public void copyToRealm_primaryKeyIsNull() throws NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException {\n        addPrimaryKeyObjectToTestRealm(realm);\n\n        if (testClazz.equals(PrimaryKeyAsString.class)) {\n            RealmResults<PrimaryKeyAsString> results = realm.where(PrimaryKeyAsString.class).findAll();\n            assertEquals(1, results.size());\n            assertEquals(null, results.first().getName());\n            assertEquals(secondaryFieldValue, results.first().getId());\n\n        } else {\n            RealmResults results = realm.where(testClazz).findAll();\n            assertEquals(1, results.size());\n            assertEquals(null, ((NullPrimaryKey) results.first()).getId());\n            assertEquals(secondaryFieldValue, ((NullPrimaryKey) results.first()).getName());\n        }\n    }\n\n    // @PrimaryKey annotation accept & update null value properly as a primary key value for Realm version 0.89.1+.\n    @Test\n    public void copyToRealmOrUpdate_primaryKeyFieldIsNull() throws NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException {\n        RealmObject obj = addPrimaryKeyObjectToTestRealm(realm);\n\n        if (testClazz.equals(PrimaryKeyAsString.class)) {\n            RealmResults<PrimaryKeyAsString> results = realm.where(PrimaryKeyAsString.class).findAll();\n            assertEquals(1, results.size());\n            assertEquals(null, results.first().getName());\n            assertEquals(secondaryFieldValue, results.first().getId());\n\n        } else {\n            RealmResults results = realm.where(testClazz).findAll();\n            assertEquals(1, results.size());\n            assertEquals(null, ((NullPrimaryKey) results.first()).getId());\n            assertEquals(secondaryFieldValue, ((NullPrimaryKey) results.first()).getName());\n\n        }\n\n        // Commits to the Realm.\n        updatePrimaryKeyObject(realm, obj);\n\n        if (testClazz.equals(PrimaryKeyAsString.class)) {\n            assertEquals(updatingFieldValue, realm.where(PrimaryKeyAsString.class).findFirst().getId());\n        } else {\n            assertEquals(updatingFieldValue, ((NullPrimaryKey) realm.where(testClazz).findFirst()).getName());\n        }\n    }\n\n    // @PrimaryKey annotation creates null value properly as a primary key value for Realm version 0.89.1+.\n    @Test\n    public void createObject_primaryKeyFieldIsNull() {\n        createNullPrimaryKeyObjectFromTestRealm(realm);\n\n        if (testClazz.equals(PrimaryKeyAsString.class)) {\n            RealmResults<PrimaryKeyAsString> results = realm.where(PrimaryKeyAsString.class).findAll();\n            assertEquals(1, results.size());\n            assertEquals(null, results.first().getName());\n            assertEquals(secondaryFieldValue, results.first().getId());\n\n        } else {\n            RealmResults results = realm.where(testClazz).findAll();\n            assertEquals(1, results.size());\n            assertEquals(null, ((NullPrimaryKey) results.first()).getId());\n            assertEquals(secondaryFieldValue, ((NullPrimaryKey) results.first()).getName());\n        }\n    }\n\n    // @PrimaryKey annotation checked duplicated null value properly as a primary key value for Realm version 0.89.1+.\n    @Test\n    public void createObject_duplicatedNullPrimaryKeyThrows() throws NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException {\n        addPrimaryKeyObjectToTestRealm(realm);\n\n        realm.beginTransaction();\n        try {\n            realm.createObject(testClazz, null);\n            fail(\"Null value as primary key already exists.\");\n        } catch (RealmPrimaryKeyConstraintException expected) {\n            assertTrue(\"Exception message is: \" + expected.getMessage(),\n                    expected.getMessage().contains(\"Primary key value already exists: 'null' .\"));\n        } finally {\n            realm.cancelTransaction();\n        }\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/RealmObjectSchemaTests.java",
    "content": "/*\n * Copyright 2015 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\npackage io.realm;\n\nimport org.bson.types.Decimal128;\nimport org.bson.types.ObjectId;\nimport org.hamcrest.CoreMatchers;\nimport org.junit.After;\nimport org.junit.Before;\nimport org.junit.Rule;\nimport org.junit.Test;\nimport org.junit.rules.ExpectedException;\nimport org.junit.runner.RunWith;\nimport org.junit.runners.Parameterized;\n\nimport java.util.Arrays;\nimport java.util.Date;\nimport java.util.List;\nimport java.util.Set;\nimport java.util.UUID;\n\nimport io.realm.entities.AllJavaTypes;\nimport io.realm.entities.CyclicType;\nimport io.realm.entities.Dog;\nimport io.realm.entities.NonLatinFieldNames;\nimport io.realm.internal.Table;\n\nimport static org.junit.Assert.assertArrayEquals;\nimport static org.junit.Assert.assertEquals;\nimport static org.junit.Assert.assertFalse;\nimport static org.junit.Assert.assertNull;\nimport static org.junit.Assert.assertThat;\nimport static org.junit.Assert.assertTrue;\nimport static org.junit.Assert.fail;\n\n@RunWith(Parameterized.class)\npublic class RealmObjectSchemaTests {\n\n    private enum ObjectSchemaType {\n        MUTABLE, IMMUTABLE\n    }\n\n    @Rule\n    public final TestRealmConfigurationFactory configFactory = new TestRealmConfigurationFactory();\n    @Rule\n    public final ExpectedException thrown = ExpectedException.none();\n\n    private RealmObjectSchema DOG_SCHEMA;\n    private BaseRealm realm;\n    private RealmObjectSchema schema;\n    private RealmSchema realmSchema;\n    private ObjectSchemaType type;\n\n    @Parameterized.Parameters(name = \"{0}\")\n    public static List<ObjectSchemaType> data() {\n        return Arrays.asList(ObjectSchemaType.values());\n    }\n\n    public RealmObjectSchemaTests(ObjectSchemaType type) {\n        this.type = type;\n    }\n\n    @Before\n    public void setUp() {\n        RealmConfiguration realmConfig = configFactory.createConfiguration();\n        Realm.getInstance(realmConfig).close(); // Creates Schema.\n\n        realm = DynamicRealm.getInstance(realmConfig);\n        realm.beginTransaction();\n        realm.getSchema().create(\"NewClass\");\n        realm.commitTransaction();\n        realm.close();\n\n        if (type == ObjectSchemaType.MUTABLE)  {\n            realm = DynamicRealm.getInstance(realmConfig);\n            realmSchema = realm.getSchema();\n            DOG_SCHEMA = realmSchema.get(\"Dog\");\n            schema = realmSchema.get(\"NewClass\");\n        } else {\n            realm = Realm.getInstance(realmConfig);\n            realmSchema = realm.getSchema();\n            DOG_SCHEMA = realmSchema.get(\"Dog\");\n            schema = realmSchema.get(\"Dog\");\n        }\n        realm.beginTransaction();\n    }\n\n    @After\n    public void tearDown() {\n        if (realm.isInTransaction()) {\n            realm.cancelTransaction();\n        }\n        realm.close();\n    }\n\n    public enum SchemaFieldType {\n        SIMPLE, OBJECT, LIST\n    }\n\n    // Enumerate all standard field types\n    public enum FieldType {\n        STRING(String.class, true),\n        SHORT(Short.class, true), PRIMITIVE_SHORT(short.class, false),\n        INT(Integer.class, true), PRIMITIVE_INT(int.class, false),\n        LONG(Long.class, true), PRIMITIVE_LONG(long.class, false),\n        BYTE(Byte.class, true), PRIMITIVE_BYTE(byte.class, false),\n        BOOLEAN(Boolean.class, true), PRIMITIVE_BOOLEAN(boolean.class, false),\n        FLOAT(Float.class, true), PRIMITIVE_FLOAT(float.class, false),\n        DOUBLE(Double.class, true), PRIMITIVE_DOUBLE(double.class, false),\n        BLOB(byte[].class, true),\n        DATE(Date.class, true),\n        OBJECT_ID(ObjectId.class, true),\n        DECIMAL128(Decimal128.class, true),\n        UUID(UUID.class, true),\n        OBJECT(RealmObject.class, false),\n        MIXED(RealmAny.class, true);\n\n        final Class<?> clazz;\n        final boolean defaultNullable;\n\n        FieldType(Class<?> clazz, boolean defaultNullable) {\n            this.clazz = clazz;\n            this.defaultNullable = defaultNullable;\n        }\n\n        public Class<?> getType() {\n            return clazz;\n        }\n\n        public boolean isNullable() {\n            return defaultNullable;\n        }\n    }\n\n    // Enumerate all list types\n    public enum FieldListType {\n        STRING_LIST(String.class, true),\n        SHORT_LIST(Short.class, true), PRIMITIVE_SHORT_LIST(short.class, false),\n        INT_LIST(Integer.class, true), PRIMITIVE_INT_LIST(int.class, false),\n        LONG_LIST(Long.class, true), PRIMITIVE_LONG_LIST(long.class, false),\n        BYTE_LIST(Byte.class, true), PRIMITIVE_BYTE_LIST(byte.class, false),\n        BOOLEAN_LIST(Boolean.class, true), PRIMITIVE_BOOLEAN_LIST(boolean.class, false),\n        FLOAT_LIST(Float.class, true), PRIMITIVE_FLOAT_LIST(float.class, false),\n        DOUBLE_LIST(Double.class, true), PRIMITIVE_DOUBLE_LIST(double.class, false),\n        BLOB_LIST(byte[].class, true),\n        DATE_LIST(Date.class, true),\n        OBJECT_ID_LIST(ObjectId.class, true),\n        DECIMAL128_LIST(Decimal128.class, true),\n        UUID_LIST(UUID.class, true),\n        MIXED_LIST(RealmAny.class, true),\n        LIST(RealmList.class, false); // List of Realm Objects\n\n        final Class<?> clazz;\n        final boolean defaultNullable;\n\n        FieldListType(Class<?> clazz, boolean defaultNullable) {\n            this.clazz = clazz;\n            this.defaultNullable = defaultNullable;\n        }\n\n        public Class<?> getType() {\n            return clazz;\n        }\n\n        public boolean isNullable() {\n            return defaultNullable;\n        }\n    }\n\n    // Enumerate all dictionary types\n    public enum FieldDictionaryType {\n        STRING_DICTIONARY(String.class, true),\n        SHORT_DICTIONARY(Short.class, true), PRIMITIVE_SHORT_DICTIONARY(short.class, false),\n        INT_DICTIONARY(Integer.class, true), PRIMITIVE_INT_DICTIONARY(int.class, false),\n        LONG_DICTIONARY(Long.class, true), PRIMITIVE_LONG_DICTIONARY(long.class, false),\n        BYTE_DICTIONARY(Byte.class, true), PRIMITIVE_BYTE_DICTIONARY(byte.class, false),\n        BOOLEAN_DICTIONARY(Boolean.class, true), PRIMITIVE_BOOLEAN_DICTIONARY(boolean.class, false),\n        FLOAT_DICTIONARY(Float.class, true), PRIMITIVE_FLOAT_DICTIONARY(float.class, false),\n        DOUBLE_DICTIONARY(Double.class, true), PRIMITIVE_DOUBLE_DICTIONARY(double.class, false),\n        BLOB_DICTIONARY(byte[].class, true),\n        DATE_DICTIONARY(Date.class, true),\n        OBJECT_ID_DICTIONARY(ObjectId.class, true),\n        DECIMAL128_DICTIONARY(Decimal128.class, true),\n        UUID_DICTIONARY(UUID.class, true),\n        MIXED_DICTIONARY(RealmAny.class, true),\n        DICTIONARY(RealmDictionary.class, false); // Dictionary of Realm Objects\n\n        final Class<?> clazz;\n        final boolean defaultNullable;\n\n        FieldDictionaryType(Class<?> clazz, boolean defaultNullable) {\n            this.clazz = clazz;\n            this.defaultNullable = defaultNullable;\n        }\n\n        public Class<?> getType() {\n            return clazz;\n        }\n\n        public boolean isNullable() {\n            return defaultNullable;\n        }\n    }\n\n    public enum IndexFieldType {\n        STRING(String.class, true),\n        SHORT(Short.class, true), PRIMITIVE_SHORT(short.class, false),\n        INT(Integer.class, true), PRIMITIVE_INT(int.class, false),\n        LONG(Long.class, true), PRIMITIVE_LONG(long.class, false),\n        BYTE(Byte.class, true), PRIMITIVE_BYTE(byte.class, false),\n        BOOLEAN(Boolean.class, true), PRIMITIVE_BOOLEAN(boolean.class, false),\n        OBJECT_ID(ObjectId.class, true),\n        UUID(UUID.class, true),\n        MIXED(RealmAny.class, true),\n        DATE(Date.class, true);\n\n        private final Class<?> clazz;\n        private final boolean nullable;\n\n        public Class<?> getType() {\n            return clazz;\n        }\n\n        public boolean isNullable() {\n            return nullable;\n        }\n\n        IndexFieldType(Class<?> clazz, boolean nullable) {\n            this.clazz = clazz;\n            this.nullable = nullable;\n        }\n    }\n\n    public enum InvalidIndexFieldType {\n        FLOAT(Float.class), PRIMITIVE_FLOAT(float.class),\n        DOUBLE(Double.class), PRIMITIVE_DOUBLE(double.class),\n        BLOB(byte[].class),\n        OBJECT(RealmObject.class),\n        LIST(RealmList.class);\n\n        private final Class<?> clazz;\n\n        public Class<?> getType() {\n            return clazz;\n        }\n\n        InvalidIndexFieldType(Class<?> clazz) {\n            this.clazz = clazz;\n        }\n    }\n\n    // TODO These should also be allowed? BOOLEAN, DATE\n    public enum PrimaryKeyFieldType {\n        STRING(String.class, true),\n        SHORT(Short.class, true), PRIMITIVE_SHORT(short.class, false),\n        INT(Integer.class, true), PRIMITIVE_INT(int.class, false),\n        LONG(Long.class, true), PRIMITIVE_LONG(long.class, false),\n        BYTE(Byte.class, true), PRIMITIVE_BYTE(byte.class, false),\n        OBJECT_ID(ObjectId.class, true),\n        UUID(UUID.class, true);\n\n        private final Class<?> clazz;\n        private final boolean nullable;\n\n        public Class<?> getType() {\n            return clazz;\n        }\n\n        public boolean isNullable() {\n            return nullable;\n        }\n\n        PrimaryKeyFieldType(Class<?> clazz, boolean nullable) {\n            this.clazz = clazz;\n            this.nullable = nullable;\n        }\n    }\n\n    public enum InvalidPrimaryKeyFieldType {\n        BOOLEAN(Boolean.class), PRIMITIVE_BOOLEAN(boolean.class),\n        FLOAT(Float.class), PRIMITIVE_FLOAT(float.class),\n        DOUBLE(Double.class), PRIMITIVE_DOUBLE(double.class),\n        BLOB(byte[].class),\n        DATE(Date.class),\n        DECIMAL128(Decimal128.class),\n        MIXED(RealmAny.class),\n        OBJECT(RealmObject.class),\n        LIST(RealmList.class);\n\n        private final Class<?> clazz;\n\n        public Class<?> getType() {\n            return clazz;\n        }\n\n        InvalidPrimaryKeyFieldType(Class<?> clazz) {\n            this.clazz = clazz;\n        }\n    }\n\n    @Test\n    public void addRemoveField() {\n        if (type == ObjectSchemaType.IMMUTABLE) {\n            try {\n                schema.addField(\"test\", int.class);\n                fail();\n            } catch (UnsupportedOperationException ignore) {\n            }\n            try {\n                schema.addRealmObjectField(\"test\", DOG_SCHEMA);\n                fail();\n            } catch (UnsupportedOperationException ignore) {\n            }\n            try {\n                schema.addRealmListField(\"test\", DOG_SCHEMA);\n                fail();\n            } catch (UnsupportedOperationException ignore) {\n            }\n\n            try {\n                schema.removeField(\"test\");\n                fail();\n            } catch (UnsupportedOperationException ignore) {\n            }\n            return;\n        }\n        String fieldName = \"foo\";\n        for (FieldType fieldType : FieldType.values()) {\n            switch (fieldType) {\n                case OBJECT:\n                    schema.addRealmObjectField(fieldName, DOG_SCHEMA);\n                    checkAddedAndRemovable(fieldName);\n                    break;\n                default:\n                    // All simple fields\n                    schema.addField(fieldName, fieldType.getType());\n                    checkAddedAndRemovable(fieldName);\n            }\n        }\n        for (FieldListType fieldType : FieldListType.values()) {\n            switch (fieldType) {\n                case LIST:\n                    schema.addRealmListField(fieldName, DOG_SCHEMA);\n                    checkAddedAndRemovable(fieldName);\n                    break;\n                default:\n                    // All primitive lists\n                    schema.addRealmListField(fieldName, fieldType.getType());\n                    checkAddedAndRemovable(fieldName);\n            }\n        }\n        for (FieldDictionaryType fieldType: FieldDictionaryType.values()) {\n            switch (fieldType) {\n                case DICTIONARY:\n                    schema.addRealmDictionaryField(fieldName, DOG_SCHEMA);\n                    checkAddedAndRemovable(fieldName);\n                    break;\n                default:\n                    // All primitive dictionaries\n                    schema.addRealmDictionaryField(fieldName, fieldType.getType());\n                    checkAddedAndRemovable(fieldName);\n            }\n        }\n    }\n\n    // Checks that field is actually added and that it can be removed again.\n    private void checkAddedAndRemovable(String fieldName) {\n        assertTrue(schema.hasField(fieldName));\n        schema.removeField(fieldName);\n        assertFalse(schema.hasField(fieldName));\n    }\n\n    @Test\n    public void addField_nameAlreadyExistsThrows() {\n        if (type == ObjectSchemaType.IMMUTABLE) {\n            return;\n        }\n        for (SchemaFieldType schemaFieldType : SchemaFieldType.values()) {\n            switch (schemaFieldType) {\n                case SIMPLE:\n                    checkAddFieldTwice(AllJavaTypes.FIELD_STRING, new FieldRunnable() {\n                        @Override\n                        public void run(String fieldName) {\n                            schema.addField(fieldName, String.class);\n                        }\n                    });\n                    break;\n                case OBJECT:\n                    checkAddFieldTwice(AllJavaTypes.FIELD_OBJECT, new FieldRunnable() {\n                        @Override\n                        public void run(String fieldName) {\n                            schema.addRealmObjectField(fieldName, DOG_SCHEMA);\n                        }\n                    });\n                    break;\n                case LIST:\n                    checkAddFieldTwice(AllJavaTypes.FIELD_LIST, new FieldRunnable() {\n                        @Override\n                        public void run(String fieldName) {\n                            schema.addRealmListField(fieldName, DOG_SCHEMA);\n                        }\n                    });\n                    break;\n                default:\n                    fail(\"Unknown type: \" + schemaFieldType);\n            }\n        }\n    }\n\n    @Test\n    public void addField_realmModelThrows() {\n        if (type == ObjectSchemaType.IMMUTABLE) {\n            return;\n        }\n        try {\n            schema.addField(\"test\", Dog.class);\n            fail();\n        } catch (IllegalArgumentException e) {\n            assertThat(e.getMessage(), CoreMatchers.containsString(\n                    \"Use 'addRealmObjectField()' instead to add fields that link to other RealmObjects:\"));\n        }\n    }\n\n    private void checkAddFieldTwice(String fieldName, FieldRunnable runnable) {\n        runnable.run(fieldName);\n        try {\n            runnable.run(fieldName);\n            fail(\"Was able to add field twice: \" + fieldName);\n        } catch (IllegalArgumentException ignored) {\n        }\n    }\n\n\n    @Test\n    public void addField_illegalFieldNameThrows() {\n        if (type == ObjectSchemaType.IMMUTABLE) {\n            return;\n        }\n        String[] fieldNames = new String[] { null, \"\", \"foo.bar\", TestHelper.getRandomString(65) };\n        for (SchemaFieldType schemaFieldType : SchemaFieldType.values()) {\n            for (String fieldName : fieldNames) {\n                try {\n                    switch(schemaFieldType) {\n                        case SIMPLE: schema.addField(fieldName, String.class); break;\n                        case OBJECT: schema.addRealmObjectField(fieldName, DOG_SCHEMA); break;\n                        case LIST: schema.addRealmListField(fieldName, DOG_SCHEMA); break;\n                        default:\n                            fail(\"Unknown type: \" + schemaFieldType);\n                    }\n                    fail(schemaFieldType + \" didn't throw\");\n                } catch (IllegalArgumentException ignored) {\n                }\n            }\n        }\n    }\n\n    @Test\n    public void requiredFieldAttribute() {\n        if (type == ObjectSchemaType.IMMUTABLE) {\n            return;\n        }\n        String fieldName = \"foo\";\n        for (FieldType fieldType : FieldType.values()) {\n            switch (fieldType) {\n                case OBJECT:\n                case MIXED:\n                    continue; // Not possible.\n                default:\n                    // All simple types\n                    schema.addField(fieldName, fieldType.getType(), FieldAttribute.REQUIRED);\n                    assertTrue(schema.isRequired(fieldName));\n                    schema.removeField(fieldName);\n            }\n        }\n        for (FieldListType fieldType : FieldListType.values()) {\n            switch(fieldType) {\n                case LIST:\n                case MIXED_LIST:\n                    continue; // Not possible.\n                default:\n                    // All simple list types\n                    schema.addRealmListField(fieldName, fieldType.getType());\n                    if (fieldType.isNullable()) {\n                        schema.setRequired(fieldName, true);\n                    }\n                    assertTrue(fieldName + \" should be required\", schema.isRequired(fieldName));\n                    schema.removeField(fieldName);\n            }\n        }\n    }\n\n    @Test\n    public void indexedFieldAttribute() {\n        if (type == ObjectSchemaType.IMMUTABLE) {\n            return;\n        }\n        for (IndexFieldType fieldType : IndexFieldType.values()) {\n            String fieldName = \"foo\";\n            switch (fieldType) {\n                default:\n                    schema.addField(fieldName, fieldType.getType(), FieldAttribute.INDEXED);\n                    assertTrue(fieldType + \" failed\", schema.hasIndex(fieldName));\n            }\n            schema.removeField(fieldName);\n        }\n    }\n\n    @Test\n    public void invalidIndexedFieldAttributeThrows() {\n        if (type == ObjectSchemaType.IMMUTABLE) {\n            return;\n        }\n        for (InvalidIndexFieldType fieldType : InvalidIndexFieldType.values()) {\n            String fieldName = \"foo\";\n            try {\n                schema.addField(fieldName, fieldType.getType(), FieldAttribute.INDEXED);\n                fail(fieldType + \" should not be allowed to be indexed\");\n            } catch (IllegalArgumentException ignored) {\n            }\n        }\n\n        // Probe for all variants of primitive lists\n        try {\n            schema.addRealmListField(\"foo\", String.class);\n        } catch (IllegalArgumentException ignored) {\n        }\n    }\n\n    @Test\n    public void primaryKeyFieldAttribute() {\n        if (type == ObjectSchemaType.IMMUTABLE) {\n            return;\n        }\n        for (PrimaryKeyFieldType fieldType : PrimaryKeyFieldType.values()) {\n            String fieldName = \"foo\";\n            schema.addField(fieldName, fieldType.getType(), FieldAttribute.PRIMARY_KEY);\n            assertTrue(schema.hasPrimaryKey());\n            assertTrue(schema.isPrimaryKey(fieldName));\n            assertEquals(fieldName, schema.getPrimaryKey());\n            switch (fieldType) {\n                case BYTE:\n                case SHORT:\n                case INT:\n                case LONG:\n                case OBJECT_ID:\n                case UUID:\n                case STRING:\n                    assertTrue(schema.isNullable(fieldName));\n                    break;\n                default:\n                    assertFalse(schema.isNullable(fieldName));\n            }\n            schema.removeField(fieldName);\n        }\n    }\n\n    @Test\n    public void invalidPrimaryKeyFieldAttributeThrows() {\n        if (type == ObjectSchemaType.IMMUTABLE) {\n            return;\n        }\n        for (InvalidPrimaryKeyFieldType fieldType : InvalidPrimaryKeyFieldType.values()) {\n            String fieldName = \"foo\";\n            try {\n                schema.addField(fieldName, fieldType.getType(), FieldAttribute.PRIMARY_KEY);\n                fail(fieldType + \" should not be allowed to be a primary key\");\n            } catch (IllegalArgumentException ignored) {\n            }\n        }\n\n        try {\n            schema.addRealmListField(\"foo\", schema);\n        } catch (IllegalArgumentException ignored) {\n        }\n\n        // Probe for all variants of primitive lists\n        try {\n            schema.addRealmListField(\"foo\", String.class);\n        } catch (IllegalArgumentException ignored) {\n        }\n    }\n\n    @Test\n    public void addPrimaryKeyFieldModifier_alreadyExistsThrows() {\n        if (type == ObjectSchemaType.IMMUTABLE) {\n            return;\n        }\n        for (PrimaryKeyFieldType fieldType : PrimaryKeyFieldType.values()) {\n            String fieldName = \"foo\";\n            schema.addField(fieldName, fieldType.getType());\n            schema.addPrimaryKey(fieldName);\n            try {\n                schema.addPrimaryKey(fieldName);\n                fail();\n            } catch (IllegalStateException ignored) {\n                schema.removePrimaryKey();\n            }\n            schema.removeField(fieldName);\n        }\n    }\n\n    @Test\n    public void addPrimaryKeyFieldModifier_illegalFieldTypeThrows() {\n        if (type == ObjectSchemaType.IMMUTABLE) {\n            return;\n        }\n        String fieldName = \"foo\";\n        for (InvalidPrimaryKeyFieldType fieldType : InvalidPrimaryKeyFieldType.values()) {\n            switch (fieldType) {\n                case OBJECT: schema.addRealmObjectField(fieldName, DOG_SCHEMA); break;\n                case LIST: schema.addRealmListField(fieldName, DOG_SCHEMA); break;\n                default: schema.addField(fieldName, fieldType.getType());\n            }\n            try {\n                schema.addPrimaryKey(fieldName);\n                fail(fieldType + \" should not be a legal primary key\");\n            } catch (IllegalArgumentException ignored) {\n            }\n            schema.removeField(fieldName);\n        }\n    }\n\n    @Test\n    public void addPrimaryKeyFieldModifier_duplicateValues() {\n        if (type == ObjectSchemaType.IMMUTABLE) {\n            return;\n        }\n        for (PrimaryKeyFieldType fieldType : PrimaryKeyFieldType.values()) {\n            final String fieldName = \"foo\";\n            schema.addField(fieldName, fieldType.getType());\n\n            // Creates multiple objects with same values.\n            ((DynamicRealm)realm).createObject(schema.getClassName());\n            ((DynamicRealm)realm).createObject(schema.getClassName());\n\n            try {\n                schema.addPrimaryKey(fieldName);\n                fail();\n            } catch (IllegalArgumentException e) {\n                // Checks if message reports correct field name.\n                assertThat(e.getMessage(), CoreMatchers.containsString(fieldName));\n            }\n            schema.removeField(fieldName);\n        }\n    }\n\n    @Test\n    public void addIndexFieldModifier_illegalFieldTypeThrows() {\n        if (type == ObjectSchemaType.IMMUTABLE) {\n            return;\n        }\n        String fieldName = \"foo\";\n        for (InvalidIndexFieldType fieldType : InvalidIndexFieldType.values()) {\n            switch (fieldType) {\n                case OBJECT: schema.addRealmObjectField(fieldName, DOG_SCHEMA); break;\n                case LIST: schema.addRealmListField(fieldName, DOG_SCHEMA); break;\n                default: schema.addField(fieldName, fieldType.getType());\n            }\n            try {\n                schema.addIndex(fieldName);\n                fail(fieldType + \" should not be allowed to be indexed.\");\n            } catch (IllegalArgumentException ignored) {\n            }\n            schema.removeField(fieldName);\n        }\n    }\n\n    @Test\n    public void addIndexFieldModifier_alreadyIndexedThrows() {\n        if (type == ObjectSchemaType.IMMUTABLE) {\n            return;\n        }\n        for (IndexFieldType fieldType : IndexFieldType.values()) {\n            String fieldName = \"foo\";\n            schema.addField(fieldName, fieldType.getType());\n            schema.addIndex(fieldName);\n            try {\n                schema.addIndex(fieldName);\n                fail();\n            } catch (IllegalStateException ignored) {\n            }\n            schema.removeField(fieldName);\n        }\n    }\n\n    @Test\n    public void setNullable_trueAndFalse() {\n        if (type == ObjectSchemaType.IMMUTABLE) {\n            thrown.expect(UnsupportedOperationException.class);\n            schema.setNullable(\"test\", true);\n            return;\n        }\n        String fieldName = \"foo\";\n        for (FieldType fieldType : FieldType.values()) {\n            switch (fieldType) {\n                case OBJECT:\n                case MIXED:\n                    // Objects are always nullable and cannot be changed.\n                    schema.addRealmObjectField(fieldName, schema);\n                    assertTrue(schema.isNullable(fieldName));\n                    try {\n                        schema.setNullable(fieldName, false);\n                        fail();\n                    } catch (IllegalArgumentException ignored) {\n                    }\n                    break;\n                default:\n                    // All simple types.\n                    schema.addField(fieldName, fieldType.getType());\n                    assertEquals(fieldType.isNullable(), schema.isNullable(fieldName));\n                    schema.setNullable(fieldName, !fieldType.isNullable());\n                    assertEquals(!fieldType.isNullable(), schema.isNullable(fieldName));\n            }\n            schema.removeField(fieldName);\n        }\n        for (FieldListType fieldType : FieldListType.values()) {\n            switch (fieldType) {\n                case LIST:\n                case MIXED_LIST:\n                    // Lists are not nullable and cannot be configured to be so.\n                    schema.addRealmListField(fieldName, schema);\n                    assertFalse(schema.isNullable(fieldName));\n                    try {\n                        schema.setNullable(fieldName, true);\n                        fail();\n                    } catch (IllegalArgumentException ignored) {\n                    }\n                    break;\n                default:\n                    // All simple list types.\n                    schema.addRealmListField(fieldName, fieldType.getType());\n                    assertEquals(\"Type: \" + fieldType, fieldType.isNullable(), schema.isNullable(fieldName));\n                    schema.setNullable(fieldName, !fieldType.isNullable());\n                    assertEquals(\"Type: \" + fieldType, !fieldType.isNullable(), schema.isNullable(fieldName));\n            }\n            schema.removeField(fieldName);\n        }\n    }\n\n    @Test\n    public void setRequired_trueAndFalse() {\n        if (type == ObjectSchemaType.IMMUTABLE) {\n            thrown.expect(UnsupportedOperationException.class);\n            schema.setRequired(\"test\", true);\n            return;\n        }\n        String fieldName = \"foo\";\n        for (FieldType fieldType : FieldType.values()) {\n            switch (fieldType) {\n                case OBJECT:\n                case MIXED:\n                    // Objects are always nullable and cannot be configured otherwise.\n                    schema.addRealmObjectField(fieldName, schema);\n                    assertFalse(schema.isRequired((fieldName)));\n                    try {\n                        schema.setRequired(fieldName, false);\n                        fail();\n                    } catch (IllegalArgumentException ignored) {\n                    }\n                    break;\n                default:\n                    // All simple types.\n                    schema.addField(fieldName, fieldType.getType());\n                    assertEquals(!fieldType.isNullable(), schema.isRequired(fieldName));\n                    schema.setRequired(fieldName, fieldType.isNullable());\n                    assertEquals(fieldType.isNullable(), schema.isRequired(fieldName));\n            }\n            schema.removeField(fieldName);\n        }\n        for (FieldListType fieldType : FieldListType.values()) {\n            switch (fieldType) {\n                case LIST:\n                case MIXED_LIST:\n                    // Lists are always non-nullable and cannot be configured otherwise.\n                    schema.addRealmListField(fieldName, schema);\n                    assertTrue(schema.isRequired((fieldName)));\n                    try {\n                        schema.setRequired(fieldName, true);\n                        fail();\n                    } catch (IllegalArgumentException ignored) {\n                    }\n                    break;\n                default:\n                    // All simple list types.\n                    schema.addRealmListField(fieldName, fieldType.getType());\n                    assertEquals(!fieldType.isNullable(), schema.isRequired(fieldName));\n                    schema.setRequired(fieldName, fieldType.isNullable());\n                    assertEquals(fieldType.isNullable(), schema.isRequired(fieldName));\n            }\n            schema.removeField(fieldName);\n        }\n    }\n\n    // When converting a nullable field to required, the null values of the field will be set to the default value\n    // according to the field type.\n    @Test\n    public void setRequired_nullValueBecomesDefaultValue() {\n        if (type == ObjectSchemaType.IMMUTABLE) {\n            return;\n        }\n        for (FieldType fieldType : FieldType.values()) {\n            String fieldName = fieldType.name();\n            switch (fieldType) {\n                case OBJECT:\n                case MIXED:\n                    // Skip always nullable fields\n                    break;\n                default:\n                    // Skip not-nullable fields .\n                    if (!fieldType.isNullable()) {\n                        break;\n                    }\n                    schema.addField(fieldName, fieldType.getType());\n                    DynamicRealmObject object = ((DynamicRealm)realm).createObject(schema.getClassName());\n                    assertTrue(object.isNull(fieldName));\n                    schema.setRequired(fieldName, true);\n                    assertFalse(object.isNull(fieldName));\n                    if (fieldType == FieldType.BLOB) {\n                        assertEquals(0, object.getBlob(fieldName).length);\n                    } else if (fieldType == FieldType.BOOLEAN) {\n                        assertFalse(object.getBoolean(fieldName));\n                    } else if (fieldType == FieldType.STRING) {\n                        assertEquals(0, object.getString(fieldName).length());\n                    } else if (fieldType == FieldType.FLOAT) {\n                        assertEquals(0.0F, object.getFloat(fieldName), 0F);\n                    } else if (fieldType == FieldType.DOUBLE) {\n                        assertEquals(0.0D, object.getDouble(fieldName), 0D);\n                    } else if (fieldType == FieldType.DATE) {\n                        assertEquals(new Date(0), object.getDate(fieldName));\n                    }  else if (fieldType == FieldType.OBJECT_ID) {\n                        assertEquals(new ObjectId(\"000000000000000000000000\"), object.getObjectId(fieldName));\n                    }  else if (fieldType == FieldType.DECIMAL128) {\n                        assertEquals(Decimal128.parse(\"0\"), object.getDecimal128(fieldName));\n                    } else if (fieldType == FieldType.UUID) {\n                        assertEquals(UUID.fromString(\"00000000-0000-0000-0000-000000000000\"), object.getUUID(fieldName));\n                    } else {\n                        assertEquals(0, object.getInt(fieldName));\n                    }\n                    break;\n            }\n        }\n        for (FieldListType fieldType : FieldListType.values()) {\n            switch(fieldType) {\n                case LIST:\n                    // Skip always non-nullable fields.\n                    break;\n                case STRING_LIST:\n                    checkListValueConversionToDefaultValue(String.class, \"\");\n                    break;\n                case SHORT_LIST:\n                    checkListValueConversionToDefaultValue(Short.class, (short) 0);\n                    break;\n                case INT_LIST:\n                    checkListValueConversionToDefaultValue(Integer.class, 0);\n                    break;\n                case LONG_LIST:\n                    checkListValueConversionToDefaultValue(Long.class, 0L);\n                    break;\n                case BYTE_LIST:\n                    checkListValueConversionToDefaultValue(Byte.class, (byte) 0);\n                    break;\n                case BOOLEAN_LIST:\n                    checkListValueConversionToDefaultValue(Boolean.class, false);\n                    break;\n                case FLOAT_LIST:\n                    checkListValueConversionToDefaultValue(Float.class, 0.0F);\n                    break;\n                case DOUBLE_LIST:\n                    checkListValueConversionToDefaultValue(Double.class, 0.0D);\n                    break;\n                case BLOB_LIST:\n                    checkListValueConversionToDefaultValue(byte[].class, new byte[0]);\n                    break;\n                case DATE_LIST:\n                    checkListValueConversionToDefaultValue(Date.class, new Date(0));\n                    break;\n                case OBJECT_ID_LIST:\n                    checkListValueConversionToDefaultValue(ObjectId.class, new ObjectId(\"000000000000000000000000\"));\n                    break;\n                case DECIMAL128_LIST:\n                    checkListValueConversionToDefaultValue(Decimal128.class, Decimal128.parse(\"0\"));\n                    break;\n                case UUID_LIST:\n                    checkListValueConversionToDefaultValue(UUID.class, UUID.fromString(\"00000000-0000-0000-0000-000000000000\"));\n                    break;\n                case PRIMITIVE_INT_LIST:\n                case PRIMITIVE_LONG_LIST:\n                case PRIMITIVE_BYTE_LIST:\n                case PRIMITIVE_BOOLEAN_LIST:\n                case PRIMITIVE_FLOAT_LIST:\n                case PRIMITIVE_DOUBLE_LIST:\n                case PRIMITIVE_SHORT_LIST:\n                case MIXED_LIST:\n                    // Skip not-nullable fields\n                    break;\n                default:\n                    throw new IllegalArgumentException(\"Unknown type: \" + fieldType);\n            }\n        }\n    }\n\n    // Checks that null values in a value list are correctly converted to default values\n    // when field is set to required.\n    private <E> void checkListValueConversionToDefaultValue(Class<E> type, Object defaultValue) {\n        schema.addRealmListField(\"foo\", type);\n        DynamicRealmObject obj = ((DynamicRealm) realm).createObject(schema.getClassName());\n        RealmList<E> list = new RealmList<>();\n        list.add(null);\n        obj.setList(\"foo\", list);\n        assertNull(obj.getList(\"foo\", type).first());\n\n        // Convert from nullable to required\n        schema.setRequired(\"foo\", true);\n        if (defaultValue instanceof byte[]) {\n            assertArrayEquals((byte[]) defaultValue, (byte[]) obj.getList(\"foo\", type).first());\n        } else {\n            assertEquals(defaultValue, obj.getList(\"foo\", type).first());\n        }\n\n        // Convert back again\n        schema.setRequired(\"foo\", false);\n        if (defaultValue instanceof byte[]) {\n            //noinspection ConstantConditions\n            assertArrayEquals((byte[]) defaultValue, (byte[]) obj.getList(\"foo\", type).first());\n        } else {\n            assertEquals(defaultValue, obj.getList(\"foo\", type).first());\n        }\n\n        // Cleanup\n        schema.removeField(\"foo\");\n    }\n\n    // Special test for making sure that binary data in all forms are transformed correctly\n    // when moving between nullable and required states.\n    @Test\n    public void binaryData_nullabilityConversions() {\n        if (type == ObjectSchemaType.IMMUTABLE) {\n            return;\n        }\n        schema.addRealmListField(\"foo\", byte[].class);\n\n        DynamicRealmObject obj = ((DynamicRealm) realm).createObject(schema.getClassName());\n        RealmList<byte[]> list = obj.getList(\"foo\", byte[].class);\n        assertTrue(list.size() == 0);\n\n        // Initial content (nullable)\n        list.add(null);\n        list.add(new byte[] {1, 2, 3});\n        assertNull(list.get(0));\n        assertArrayEquals(new byte[] {1, 2, 3}, list.get(1));\n\n        // Transform to required\n        schema.setRequired(\"foo\", true);\n        list = obj.getList(\"foo\", byte[].class);\n        assertEquals(0, list.get(0).length);\n        assertArrayEquals(new byte[] {1, 2, 3}, list.get(1));\n\n        // Transform back to nullable\n        schema.setRequired(\"foo\", false);\n        list = obj.getList(\"foo\", byte[].class);\n        assertEquals(0, list.get(0).length);\n        assertArrayEquals(new byte[] {1, 2, 3}, list.get(1));\n    }\n\n    @Test\n    public void setRequired_true_onPrimaryKeyField_containsNullValues_shouldThrow() {\n        if (type == ObjectSchemaType.IMMUTABLE) {\n            return;\n        }\n        for (PrimaryKeyFieldType fieldType : PrimaryKeyFieldType.values()) {\n            String className = fieldType.getType().getSimpleName() + \"Class\";\n            String fieldName = \"primaryKey\";\n            schema = realmSchema.create(className);\n            if (!fieldType.isNullable()) {\n                continue;\n            }\n            schema.addField(fieldName, fieldType.getType(), FieldAttribute.PRIMARY_KEY);\n            DynamicRealmObject object = ((DynamicRealm)realm).createObject(schema.getClassName(), null);\n            assertTrue(object.isNull(fieldName));\n            try {\n                schema.setRequired(fieldName, true);\n                fail();\n            } catch (IllegalStateException expected) {\n                assertThat(expected.getMessage(),\n                        CoreMatchers.containsString(\n                                String.format(\"Objects in 'class_%s' has null value(s) in property '%s'\", className, fieldName)\n                        )\n                );\n            }\n            realmSchema.remove(className);\n        }\n    }\n\n    private void setRequired_onPrimaryKeyField(boolean isRequired) {\n        for (PrimaryKeyFieldType fieldType : PrimaryKeyFieldType.values()) {\n            String className = fieldType.getType().getSimpleName() + \"Class\";\n            String fieldName = \"primaryKey\";\n            schema = realmSchema.create(className);\n            if (!fieldType.isNullable()) {\n                continue;\n            }\n            if (isRequired) {\n                schema.addField(fieldName, fieldType.getType(), FieldAttribute.PRIMARY_KEY);\n            } else {\n                schema.addField(fieldName, fieldType.getType(), FieldAttribute.PRIMARY_KEY, FieldAttribute.REQUIRED);\n            }\n\n            if(fieldType == PrimaryKeyFieldType.OBJECT_ID){\n                ((DynamicRealm)realm).createObject(schema.getClassName(), TestHelper.generateObjectIdHexString(1));\n                ((DynamicRealm)realm).createObject(schema.getClassName(), TestHelper.generateObjectIdHexString(2));\n            } else if(fieldType == PrimaryKeyFieldType.UUID){\n                ((DynamicRealm)realm).createObject(schema.getClassName(), TestHelper.generateUUIDString(1));\n                ((DynamicRealm)realm).createObject(schema.getClassName(), TestHelper.generateUUIDString(2));\n            } else {\n                ((DynamicRealm)realm).createObject(schema.getClassName(), \"1\");\n                ((DynamicRealm)realm).createObject(schema.getClassName(), \"2\");\n            }\n\n            assertTrue(schema.hasPrimaryKey());\n            assertTrue(schema.hasIndex(fieldName));\n\n            schema.setRequired(fieldName, isRequired);\n            assertTrue(schema.hasPrimaryKey());\n            assertTrue(schema.hasIndex(fieldName));\n\n            RealmResults<DynamicRealmObject> results = ((DynamicRealm)realm).where(className).sort(fieldName).findAll();\n            assertEquals(2, results.size());\n            if (fieldType == PrimaryKeyFieldType.STRING) {\n                assertEquals(\"1\", results.get(0).getString(fieldName));\n                assertEquals(\"2\", results.get(1).getString(fieldName));\n            } else if (fieldType == PrimaryKeyFieldType.OBJECT_ID) {\n                assertEquals(new ObjectId(TestHelper.generateObjectIdHexString(1)), results.get(0).getObjectId(fieldName));\n                assertEquals(new ObjectId(TestHelper.generateObjectIdHexString(2)), results.get(1).getObjectId(fieldName));\n            } else if (fieldType == PrimaryKeyFieldType.UUID) {\n                assertEquals(UUID.fromString(TestHelper.generateUUIDString(1)), results.get(0).getUUID(fieldName));\n                assertEquals(UUID.fromString(TestHelper.generateUUIDString(2)), results.get(1).getUUID(fieldName));\n            } else {\n                assertEquals(1, results.get(0).getLong(fieldName));\n                assertEquals(2, results.get(1).getLong(fieldName));\n            }\n            realmSchema.remove(className);\n        }\n    }\n\n    @Test\n    public void setRequired_true_onPrimaryKeyField() {\n        if (type == ObjectSchemaType.IMMUTABLE) {\n            return;\n        }\n        setRequired_onPrimaryKeyField(true);\n    }\n\n    @Test\n    public void setRequired_false_onPrimaryKeyField() {\n        if (type == ObjectSchemaType.IMMUTABLE) {\n            return;\n        }\n        setRequired_onPrimaryKeyField(false);\n    }\n\n    private void setRequired_onIndexedField(boolean toRequired) {\n        String fieldName = \"IndexedField\";\n        for (IndexFieldType fieldType : IndexFieldType.values()) {\n            if (!fieldType.isNullable() || (fieldType == IndexFieldType.MIXED)) {\n                continue;\n            }\n            if (toRequired) {\n                schema.addField(fieldName, fieldType.getType(), FieldAttribute.INDEXED);\n            } else {\n                schema.addField(fieldName, fieldType.getType(), FieldAttribute.INDEXED, FieldAttribute.REQUIRED);\n            }\n            assertTrue(schema.hasIndex(fieldName));\n            schema.setRequired(fieldName, toRequired);\n            assertTrue(schema.hasIndex(fieldName));\n            schema.removeField(fieldName);\n        }\n    }\n\n    @Test\n    public void setRequired_true_onIndexedField() {\n        if (type == ObjectSchemaType.IMMUTABLE) {\n            return;\n        }\n        setRequired_onIndexedField(true);\n    }\n\n    @Test\n    public void setRequired_false_onIndexedField() {\n        if (type == ObjectSchemaType.IMMUTABLE) {\n            return;\n        }\n        setRequired_onIndexedField(false);\n    }\n\n    @Test\n    public void setPrimaryKey_trueAndFalse() {\n        if (type == ObjectSchemaType.IMMUTABLE) {\n            try {\n                schema.addPrimaryKey(\"test\");\n                fail();\n            } catch (UnsupportedOperationException ignore){\n\n            }\n            try {\n                schema.removePrimaryKey();\n                fail();\n            } catch (UnsupportedOperationException ignore){\n            }\n            return;\n        }\n        for (PrimaryKeyFieldType fieldType : PrimaryKeyFieldType.values()) {\n            String fieldName = \"foo\";\n            schema.addField(fieldName, fieldType.getType());\n            schema.addPrimaryKey(fieldName);\n            assertTrue(schema.hasPrimaryKey());\n            assertTrue(schema.isPrimaryKey(fieldName));\n            assertTrue(schema.hasIndex(fieldName));\n            schema.removePrimaryKey();\n            assertFalse(schema.hasPrimaryKey());\n            assertFalse(schema.isPrimaryKey(fieldName));\n            assertFalse(schema.hasIndex(fieldName));\n            schema.removeField(fieldName);\n        }\n    }\n\n    @Test\n    public void removeNonExistingPrimaryKeyThrows() {\n        if (type == ObjectSchemaType.IMMUTABLE) {\n            return;\n        }\n        String fieldName = \"foo\";\n        schema.addField(fieldName, String.class);\n\n        thrown.expect(IllegalStateException.class);\n        schema.removePrimaryKey();\n    }\n\n    @Test\n    public void setIndex_trueAndFalse() {\n        if (type == ObjectSchemaType.IMMUTABLE) {\n            try {\n                schema.addIndex(\"test\");\n                fail();\n            } catch (UnsupportedOperationException ignore) {\n            }\n            try {\n                schema.removeIndex(\"test\");\n                fail();\n            } catch (UnsupportedOperationException ignore) {\n            }\n            return;\n        }\n        for (IndexFieldType fieldType : IndexFieldType.values()) {\n            String fieldName = \"foo\";\n            schema.addField(fieldName, fieldType.getType(), FieldAttribute.INDEXED);\n            assertTrue(schema.hasIndex(fieldName));\n            schema.removeIndex(fieldName);\n            assertFalse(schema.hasIndex(fieldName));\n            schema.removeField(fieldName);\n        }\n    }\n\n    @Test\n    public void removeNonExistingIndexThrows() {\n        if (type == ObjectSchemaType.IMMUTABLE) {\n            return;\n        }\n        String fieldName = \"foo\";\n        schema.addField(fieldName, String.class);\n\n        thrown.expect(IllegalStateException.class);\n        schema.removeIndex(fieldName);\n    }\n\n    @Test\n    public void removeField() {\n        if (type == ObjectSchemaType.IMMUTABLE) {\n            thrown.expect(UnsupportedOperationException.class);\n            DOG_SCHEMA.removeField(Dog.FIELD_HEIGHT);\n            return;\n        }\n        String fieldName = \"foo\";\n        schema.addField(fieldName, String.class);\n        assertTrue(schema.hasField(fieldName));\n        schema.removeField(fieldName);\n        assertFalse(schema.hasField(fieldName));\n    }\n\n    @Test\n    public void removeField_withPrimaryKey() {\n        if (type == ObjectSchemaType.IMMUTABLE) {\n            return;\n        }\n        String fieldName = \"foo\";\n        schema.addField(fieldName, String.class, FieldAttribute.PRIMARY_KEY);\n        assertTrue(schema.hasField(fieldName));\n        assertTrue(schema.hasPrimaryKey());\n        assertTrue(schema.isPrimaryKey(fieldName));\n        schema.removeField(fieldName);\n        assertFalse(schema.hasPrimaryKey());\n    }\n\n    @Test\n    public void removeField_nonExistingFieldThrows() {\n        if (type == ObjectSchemaType.IMMUTABLE) {\n            return;\n        }\n        String fieldName = \"foo\";\n\n        thrown.expect(IllegalStateException.class);\n        schema.removeField(fieldName);\n    }\n\n    @Test\n    public void renameField() {\n        if (type == ObjectSchemaType.IMMUTABLE) {\n            thrown.expect(UnsupportedOperationException.class);\n            schema.renameField(\"test\", \"test1\");\n            return;\n        }\n        String oldFieldName = \"old\";\n        String newFieldName = \"new\";\n        schema.addField(oldFieldName, String.class);\n        assertTrue(schema.hasField(oldFieldName));\n        assertFalse(schema.hasField(newFieldName));\n        schema.renameField(oldFieldName, newFieldName);\n        assertFalse(schema.hasField(oldFieldName));\n        assertTrue(schema.hasField(newFieldName));\n    }\n\n    @Test\n    public void renameField_nonExistingFieldThrows() {\n        if (type == ObjectSchemaType.IMMUTABLE) {\n            return;\n        }\n        String oldFieldName = \"old\";\n        String newFieldName = \"new\";\n\n        thrown.expect(IllegalArgumentException.class);\n        schema.renameField(oldFieldName, newFieldName);\n    }\n\n    @Test\n    public void renameField_toIllegalNameThrows() {\n        if (type == ObjectSchemaType.IMMUTABLE) {\n            return;\n        }\n        String oldFieldName = \"old\";\n        String newFieldName = \"\";\n        schema.addField(oldFieldName, String.class);\n\n        thrown.expect(IllegalArgumentException.class);\n        schema.renameField(oldFieldName, newFieldName);\n    }\n\n    @Test\n    public void renameField_withPrimaryKey() {\n        if (type == ObjectSchemaType.IMMUTABLE) {\n            return;\n        }\n        String fieldName = \"foo\";\n        schema.addField(fieldName, String.class, FieldAttribute.PRIMARY_KEY);\n        assertTrue(schema.hasField(fieldName));\n        assertTrue(schema.hasPrimaryKey());\n        assertTrue(schema.isPrimaryKey(fieldName));\n\n        schema.renameField(fieldName, \"bar\");\n        assertTrue(schema.hasPrimaryKey());\n\n        assertEquals(\"bar\", schema.getPrimaryKey());\n    }\n\n    @Test\n    public void setGetClassName() {\n        final String[] validClassNames = {\n                TestHelper.getRandomString(1),\n                \"Darby\",\n                TestHelper.getRandomString(Table.CLASS_NAME_MAX_LENGTH)\n        };\n\n        if (type == ObjectSchemaType.IMMUTABLE) {\n            thrown.expect(UnsupportedOperationException.class);\n            DOG_SCHEMA.setClassName(validClassNames[0]);\n            return;\n        }\n\n        assertEquals(\"Dog\", DOG_SCHEMA.getClassName());\n        for (String validClassName : validClassNames) {\n            DOG_SCHEMA.setClassName(validClassName);\n            assertEquals(validClassName, DOG_SCHEMA.getClassName());\n            assertTrue(realmSchema.contains(validClassName));\n        }\n    }\n\n    @Test\n    public void transform() {\n        if (type == ObjectSchemaType.IMMUTABLE) {\n            thrown.expect(UnsupportedOperationException.class);\n            DOG_SCHEMA.transform(new RealmObjectSchema.Function() {\n                @Override\n                public void apply(DynamicRealmObject obj) {\n                }\n            });\n            return;\n        }\n        String className = DOG_SCHEMA.getClassName();\n        DynamicRealmObject dog1 = ((DynamicRealm)realm).createObject(className);\n        dog1.setInt(\"age\", 1);\n        DynamicRealmObject dog2 = ((DynamicRealm)realm).createObject(className);\n        dog2.setInt(\"age\", 2);\n\n        DOG_SCHEMA.transform(new RealmObjectSchema.Function() {\n            @Override\n            public void apply(DynamicRealmObject obj) {\n                obj.setInt(\"age\", obj.getInt(\"age\") + 1);\n            }\n        });\n        assertEquals(5, ((DynamicRealm)realm).where(\"Dog\").sum(\"age\").intValue());    }\n\n    @Test\n    public void transformObjectReferences() {\n        if (type == ObjectSchemaType.IMMUTABLE) {\n            return;\n        }\n        String className = DOG_SCHEMA.getClassName();\n        DynamicRealmObject dog1 = ((DynamicRealm)realm).createObject(className);\n        dog1.setInt(\"age\", 1);\n\n        DOG_SCHEMA.transform(new RealmObjectSchema.Function() {\n            @Override\n            public void apply(DynamicRealmObject dog) {\n                DynamicRealmObject owner = ((DynamicRealm)realm).createObject(\"Owner\");\n                owner.setString(\"name\", \"John\");\n                dog.setObject(\"owner\", owner);\n            }\n        });\n        //noinspection ConstantConditions\n        assertEquals(\"John\", ((DynamicRealm)realm).where(\"Dog\").findFirst().getObject(\"owner\").getString(\"name\"));\n    }\n\n    @Test\n    public void transform_deleteObjects() {\n        if (type == ObjectSchemaType.IMMUTABLE) {\n            return;\n        }\n\n        RealmObjectSchema classSchema = realm.getSchema().get(\"CyclicType\");\n\n        Runnable transform = () -> classSchema.transform(obj -> {\n            if (obj.getInt(CyclicType.FIELD_ID) % 2 == 0) {\n                obj.getObject(CyclicType.FIELD_OBJECT).deleteFromRealm();\n                obj.deleteFromRealm();\n            }\n        });\n\n        String className = classSchema.getClassName();\n        for (int i = 0; i < 10; i++) {\n            DynamicRealmObject parentObj = ((DynamicRealm)realm).createObject(className);\n            DynamicRealmObject childObj = ((DynamicRealm)realm).createObject(className);\n            parentObj.setLong(CyclicType.FIELD_ID, i);\n            parentObj.setObject(CyclicType.FIELD_OBJECT, childObj);\n            childObj.setLong(CyclicType.FIELD_ID, i + 100);\n        }\n        assertEquals(20, ((DynamicRealm) realm).where((className)).count());\n        transform.run();\n        assertEquals(10, ((DynamicRealm) realm).where((className)).count());\n    }\n\n    @Test\n    public void getFieldNames() {\n        Set<String> fieldNames = DOG_SCHEMA.getFieldNames();\n        assertEquals(7, fieldNames.size());\n        assertTrue(fieldNames.contains(\"name\"));\n        assertTrue(fieldNames.contains(\"age\"));\n        assertTrue(fieldNames.contains(\"height\"));\n        assertTrue(fieldNames.contains(\"weight\"));\n        assertTrue(fieldNames.contains(\"hasTail\"));\n        assertTrue(fieldNames.contains(\"birthday\"));\n        assertTrue(fieldNames.contains(\"owner\"));\n    }\n\n    @Test\n    public void getFieldType() {\n        schema = realmSchema.get(\"AllJavaTypes\");\n        assertEquals(RealmFieldType.STRING, schema.getFieldType(AllJavaTypes.FIELD_STRING));\n        assertEquals(RealmFieldType.BINARY, schema.getFieldType(AllJavaTypes.FIELD_BINARY));\n        assertEquals(RealmFieldType.BOOLEAN, schema.getFieldType(AllJavaTypes.FIELD_BOOLEAN));\n        assertEquals(RealmFieldType.DATE, schema.getFieldType(AllJavaTypes.FIELD_DATE));\n        assertEquals(RealmFieldType.DOUBLE, schema.getFieldType(AllJavaTypes.FIELD_DOUBLE));\n        assertEquals(RealmFieldType.FLOAT, schema.getFieldType(AllJavaTypes.FIELD_FLOAT));\n        assertEquals(RealmFieldType.OBJECT, schema.getFieldType(AllJavaTypes.FIELD_OBJECT));\n        assertEquals(RealmFieldType.LIST, schema.getFieldType(AllJavaTypes.FIELD_LIST));\n        assertEquals(RealmFieldType.INTEGER, schema.getFieldType(AllJavaTypes.FIELD_BYTE));\n        assertEquals(RealmFieldType.INTEGER, schema.getFieldType(AllJavaTypes.FIELD_SHORT));\n        assertEquals(RealmFieldType.INTEGER, schema.getFieldType(AllJavaTypes.FIELD_INT));\n        assertEquals(RealmFieldType.INTEGER, schema.getFieldType(AllJavaTypes.FIELD_LONG));\n        assertEquals(RealmFieldType.OBJECT_ID, schema.getFieldType(AllJavaTypes.FIELD_OBJECT_ID));\n        assertEquals(RealmFieldType.DECIMAL128, schema.getFieldType(AllJavaTypes.FIELD_DECIMAL128));\n        assertEquals(RealmFieldType.UUID, schema.getFieldType(AllJavaTypes.FIELD_UUID));\n        assertEquals(RealmFieldType.MIXED, schema.getFieldType(AllJavaTypes.FIELD_REALM_ANY));\n    }\n\n    @Test(expected = IllegalArgumentException.class)\n    public void getFieldType_Throws() {\n        schema.getFieldType(\"I don't exist\");\n    }\n\n    @Test(expected = IllegalArgumentException.class)\n    public void hasIndex_nonExistFieldThrows() {\n        schema.hasIndex(\"I don't exist\");\n    }\n\n    @Test(expected = IllegalArgumentException.class)\n    public void isRequired_nonExistFieldThrows() {\n        schema.isRequired(\"I don't exist\");\n    }\n\n    @Test(expected = IllegalArgumentException.class)\n    public void isNullable_nonExistFieldThrows() {\n        schema.isNullable(\"I don't exist\");\n    }\n\n    @Test(expected = IllegalArgumentException.class)\n    public void isPrimaryKey_nonExistFieldThrows() {\n        schema.isPrimaryKey(\"I don't exist\");\n    }\n\n    @Test(expected = IllegalStateException.class)\n    public void getPrimaryKey_nonExistFieldThrows() {\n        schema.getPrimaryKey();\n    }\n\n    @Test\n    public void getFieldIndex() {\n        final String className = \"NoField\";\n        final String fieldName = \"field\";\n        RealmConfiguration emptyConfig = configFactory.createConfiguration(\"empty\");\n        DynamicRealm dynamicRealm = DynamicRealm.getInstance(emptyConfig);\n        dynamicRealm.beginTransaction();\n        RealmObjectSchema objectSchema = dynamicRealm.getSchema().create(className);\n\n        assertTrue(objectSchema.getFieldColumnKey(fieldName) < 0);\n\n        objectSchema.addField(fieldName, long.class);\n        //noinspection ConstantConditions\n        assertTrue(objectSchema.getFieldColumnKey(fieldName) >= 0);\n\n        objectSchema.removeField(fieldName);\n        assertTrue(objectSchema.getFieldColumnKey(fieldName) < 0);\n\n        dynamicRealm.cancelTransaction();\n        dynamicRealm.close();\n    }\n\n    @Test\n    public void getFieldType_nonLatinName() {\n        RealmObjectSchema objSchema = realm.getSchema().get(NonLatinFieldNames.class.getSimpleName());\n        assertEquals(RealmFieldType.INTEGER, objSchema.getFieldType(NonLatinFieldNames.FIELD_LONG_GREEK_CHAR));\n    }\n\n    @Test\n    public void addList_modelClassThrowsWithProperError() {\n        if (type == ObjectSchemaType.IMMUTABLE) {\n            return;\n        }\n\n        try {\n            schema.addRealmListField(\"field\", AllJavaTypes.class);\n            fail();\n        } catch (IllegalArgumentException e) {\n            assertTrue(e.getMessage().contains(\"Use 'addRealmListField(String name, RealmObjectSchema schema)' instead\"));\n        }\n    }\n\n\n    private interface FieldRunnable {\n        void run(String fieldName);\n    }\n\n    // Tests https://github.com/realm/realm-studio/issues/5899\n    @Test\n    public void setRequired_keepExistingRowsIfPrimaryKey() {\n        if (type == ObjectSchemaType.IMMUTABLE) {\n            return;\n        }\n        DynamicRealm dynRealm = (DynamicRealm) realm;\n        String className = \"NewClass\";\n        String fieldName = \"field\";\n\n        // Check all primary key types\n        for (PrimaryKeyFieldType fieldType : PrimaryKeyFieldType.values()) {\n            schema.addField(fieldName, fieldType.getType(), FieldAttribute.PRIMARY_KEY); // primary key field\n\n            // Hackish way to add sample data, only treat string differently\n            for (int i = 0; i < 5; i++) {\n                Object primaryKeyValue;\n                if (fieldType == PrimaryKeyFieldType.STRING) {\n                    primaryKeyValue = Integer.toString(i);\n                } else if (fieldType == PrimaryKeyFieldType.OBJECT_ID) {\n                    primaryKeyValue = new ObjectId(TestHelper.generateObjectIdHexString(i));\n                } else if (fieldType == PrimaryKeyFieldType.UUID) {\n                    primaryKeyValue = UUID.fromString(TestHelper.generateUUIDString(i));\n                } else {\n                    primaryKeyValue = i;\n                }\n\n                dynRealm.createObject(className, primaryKeyValue);\n            }\n\n            // Verify that sample data is intact before swapping nullability state\n            String errMsg = String.format(String.format(\"Count mismatch for FieldType = %s and Nullable = %s\", fieldType.getType(), schema.isNullable(fieldName)));\n            assertEquals(errMsg, 5, dynRealm.where(className).count());\n\n            // Swap nullability state\n            schema.setRequired(fieldName, !schema.isRequired(fieldName));\n            errMsg = String.format(String.format(\"Count mismatch for FieldType = %s and Nullable = %s\", fieldType.getType(), schema.isNullable(fieldName)));\n            assertEquals(errMsg, 5, dynRealm.where(className).count());\n\n            // Cleanup\n            dynRealm.delete(className);\n            schema.removeField(fieldName);\n        }\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/RealmObjectTests.java",
    "content": "/*\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\npackage io.realm;\n\nimport org.hamcrest.CoreMatchers;\nimport org.junit.After;\nimport org.junit.Before;\nimport org.junit.Rule;\nimport org.junit.Test;\nimport org.junit.rules.ExpectedException;\nimport org.junit.runner.RunWith;\n\nimport java.io.FileNotFoundException;\nimport java.nio.charset.Charset;\nimport java.util.Arrays;\nimport java.util.Calendar;\nimport java.util.Date;\nimport java.util.concurrent.Callable;\nimport java.util.concurrent.CountDownLatch;\nimport java.util.concurrent.ExecutionException;\nimport java.util.concurrent.ExecutorService;\nimport java.util.concurrent.Executors;\nimport java.util.concurrent.Future;\nimport java.util.concurrent.atomic.AtomicInteger;\nimport java.util.concurrent.atomic.AtomicReference;\n\nimport androidx.test.ext.junit.runners.AndroidJUnit4;\nimport androidx.test.rule.UiThreadTestRule;\nimport io.realm.entities.AllJavaTypes;\nimport io.realm.entities.AllTypes;\nimport io.realm.entities.AllTypesPrimaryKey;\nimport io.realm.entities.ConflictingFieldName;\nimport io.realm.entities.CustomMethods;\nimport io.realm.entities.CyclicType;\nimport io.realm.entities.Dog;\nimport io.realm.entities.NonLatinFieldNames;\nimport io.realm.entities.NullTypes;\nimport io.realm.entities.StringAndInt;\nimport io.realm.entities.pojo.AllTypesRealmModel;\nimport io.realm.exceptions.RealmException;\nimport io.realm.internal.RealmObjectProxy;\nimport io.realm.internal.Row;\nimport io.realm.internal.Table;\nimport io.realm.rule.RunInLooperThread;\nimport io.realm.rule.RunTestInLooperThread;\n\nimport static io.realm.internal.test.ExtraTests.assertArrayEquals;\nimport static org.junit.Assert.assertEquals;\nimport static org.junit.Assert.assertFalse;\nimport static org.junit.Assert.assertNotEquals;\nimport static org.junit.Assert.assertNotNull;\nimport static org.junit.Assert.assertNull;\nimport static org.junit.Assert.assertSame;\nimport static org.junit.Assert.assertThat;\nimport static org.junit.Assert.assertTrue;\nimport static org.junit.Assert.fail;\n\n\n@RunWith(AndroidJUnit4.class)\npublic class RealmObjectTests {\n\n    private static final int TEST_SIZE = 5;\n    private static final boolean REMOVE_FIRST = true;\n    private static final boolean REMOVE_LAST = false;\n\n    @Rule\n    public final TestRealmConfigurationFactory configFactory = new TestRealmConfigurationFactory();\n    @Rule\n    public final ExpectedException thrown = ExpectedException.none();\n    @Rule\n    public final RunInLooperThread looperThread = new RunInLooperThread();\n    @Rule\n    public final UiThreadTestRule uiThreadTestRule = new UiThreadTestRule();\n\n    private Realm realm;\n    private RealmConfiguration realmConfig;\n\n    private Dog createManagedDogObjectFromRealmInstance(Realm testRealm) {\n        testRealm.beginTransaction();\n        Dog dog = testRealm.createObject(Dog.class);\n        testRealm.commitTransaction();\n        return dog;\n    }\n\n    @Before\n    public void setUp() {\n        realmConfig = configFactory.createConfiguration();\n        realm = Realm.getInstance(realmConfig);\n    }\n\n    @After\n    public void tearDown() {\n        if (realm != null) {\n            realm.close();\n        }\n    }\n\n    @Test\n    public void row_isValid() {\n        realm.beginTransaction();\n        RealmObjectProxy realmObject = (RealmObjectProxy) realm.createObject(AllTypes.class);\n        Row row = realmObject.realmGet$proxyState().getRow$realm();\n        realm.commitTransaction();\n\n        assertNotNull(\"RealmObject.realmGetRow returns zero \", row);\n        assertEquals(26, row.getColumnCount());     // Update this value when adding new fields to AllTypes\n    }\n\n    @Test\n    public void stringEncoding() {\n        String[] strings = {\"ABCD\", \"ÆØÅ\", \"Ö∫Ë\", \"ΠΑΟΚ\", \"Здравей\"};\n\n        realm.beginTransaction();\n        realm.delete(AllTypes.class);\n\n        for (String str : strings) {\n            AllTypes obj1 = realm.createObject(AllTypes.class);\n            obj1.setColumnString(str);\n        }\n        realm.commitTransaction();\n\n        RealmResults<AllTypes> objects = realm.where(AllTypes.class).findAll();\n        assertEquals(strings.length, objects.size());\n        int i = 0;\n        for (AllTypes obj : objects) {\n            String s = obj.getColumnString();\n            assertEquals(strings[i], s);\n            i++;\n        }\n    }\n\n    // Invalid surrogate pairs:\n    // Both high and low should lead to an IllegalArgumentException.\n    @Test\n    public void invalidSurrogates() {\n        String high = \"Invalid high surrogate \\uD83C\\uD83C\\uDF51\";\n        String low = \"Invalid low surrogate \\uD83C\\uDF51\\uDF51\";\n\n        realm.beginTransaction();\n        realm.delete(AllTypes.class);\n        realm.commitTransaction();\n\n        realm.beginTransaction();\n        try {\n            AllTypes highSurrogate = realm.createObject(AllTypes.class);\n            highSurrogate.setColumnString(high);\n            fail();\n        } catch (IllegalArgumentException ignored) {}\n        realm.cancelTransaction();\n\n        realm.beginTransaction();\n        try {\n            AllTypes lowSurrogate = realm.createObject(AllTypes.class);\n            lowSurrogate.setColumnString(low);\n            fail();\n        } catch (IllegalArgumentException ignored) {}\n        realm.cancelTransaction();\n    }\n\n    // Removes original object and sees if has been removed.\n    @Test\n    public void deleteFromRealm() {\n        realm.beginTransaction();\n        Dog rex = realm.createObject(Dog.class);\n        rex.setName(\"Rex\");\n        Dog fido = realm.createObject(Dog.class);\n        fido.setName(\"Fido\");\n        realm.commitTransaction();\n\n        RealmResults<Dog> allDogsBefore = realm.where(Dog.class).equalTo(\"name\", \"Rex\").findAll();\n        assertEquals(1, allDogsBefore.size());\n\n        realm.beginTransaction();\n        rex.deleteFromRealm();\n        realm.commitTransaction();\n\n        RealmResults<Dog> allDogsAfter = realm.where(Dog.class).equalTo(\"name\", \"Rex\").findAll();\n        assertEquals(0, allDogsAfter.size());\n\n        fido.getName();\n        try {\n            rex.getName();\n            realm.close();\n            fail();\n        } catch (IllegalStateException ignored) {}\n\n        // Deleting rex twice should fail.\n        realm.beginTransaction();\n        try {\n            rex.deleteFromRealm();\n            realm.close();\n            fail();\n        } catch (IllegalStateException ignored) {}\n        realm.commitTransaction();\n        realm.close();\n    }\n\n    @Test\n    public void deleteFromRealm_twiceThrows() {\n        realm.beginTransaction();\n        Dog dog = realm.createObject(Dog.class);\n        dog.setAge(42);\n        realm.commitTransaction();\n\n        realm.beginTransaction();\n        assertTrue(dog.isValid());\n        dog.deleteFromRealm();\n        assertFalse(dog.isValid());\n\n        try {\n            dog.deleteFromRealm();\n            fail();\n        } catch (IllegalStateException ignored) {\n        }\n    }\n\n    @Test\n    public void deleteFromRealm_throwOnUnmanagedObject() {\n        Dog dog = new Dog();\n\n        try {\n            dog.deleteFromRealm();\n            fail(\"Failed on deleting a RealmObject from null Row.\");\n        } catch (IllegalArgumentException ignored) {\n        }\n    }\n\n    // Queries for an object, removes it and sees it has been removed from realm.\n    @Test\n    public void deleteFromRealm_removedFromResults() {\n        realm.beginTransaction();\n        realm.delete(Dog.class);\n        Dog dogToAdd = realm.createObject(Dog.class);\n        dogToAdd.setName(\"Rex\");\n        realm.commitTransaction();\n\n        assertEquals(1, realm.where(Dog.class).count());\n\n        Dog dogToRemove = realm.where(Dog.class).findFirst();\n        assertNotNull(dogToRemove);\n        realm.beginTransaction();\n        dogToRemove.deleteFromRealm();\n        realm.commitTransaction();\n\n        assertEquals(0, realm.where(Dog.class).count());\n        try {\n            dogToAdd.getName();\n            realm.close();\n            fail();\n        } catch (IllegalStateException ignored) {\n        }\n        try {\n            dogToRemove.getName();\n            realm.close();\n            fail();\n        } catch (IllegalStateException ignored) {\n        }\n        realm.close();\n    }\n\n    private void removeOneByOne(boolean removeFromFront) {\n        // Creates test data.\n        realm.beginTransaction();\n        realm.delete(Dog.class);\n        for (int i = 0; i < TEST_SIZE; i++) {\n            realm.createObject(Dog.class);\n        }\n        realm.commitTransaction();\n\n        // Checks initial size.\n        RealmResults<Dog> dogs = realm.where(Dog.class).findAll();\n        OrderedRealmCollectionSnapshot<Dog> snapshot = dogs.createSnapshot();\n        assertEquals(TEST_SIZE, snapshot.size());\n\n        // Checks that calling deleteFromRealm doesn't remove the object from the RealmResult.\n        realm.beginTransaction();\n        for (int i = 0; i < TEST_SIZE; i++) {\n            snapshot.get(removeFromFront ? i : TEST_SIZE - 1 - i).deleteFromRealm();\n        }\n        realm.commitTransaction();\n\n        assertEquals(TEST_SIZE, snapshot.size());\n        assertEquals(0, dogs.size());\n    }\n\n    // Tests calling deleteFromRealm on a OrderedRealmCollectionSnapshot instead of RealmResults.remove().\n    @Test\n    public void deleteFromRealm_atPosition() {\n        removeOneByOne(REMOVE_FIRST);\n        removeOneByOne(REMOVE_LAST);\n    }\n\n    private enum Method {\n        METHOD_GETTER,\n        METHOD_SETTER,\n        METHOD_DELETE_FROM_REALM\n    }\n\n    private boolean runMethodOnWrongThread(final Method method) throws ExecutionException, InterruptedException {\n        final AllTypes allTypes = realm.where(AllTypes.class).findFirst();\n        ExecutorService executorService = Executors.newSingleThreadExecutor();\n        Future<Boolean> future = executorService.submit(new Callable<Boolean>() {\n            @Override\n            public Boolean call() throws Exception {\n                try {\n                    switch (method) {\n                        case METHOD_GETTER:\n                            allTypes.getColumnFloat();\n                            break;\n                        case METHOD_SETTER:\n                            allTypes.setColumnFloat(1.0f);\n                            break;\n                        case METHOD_DELETE_FROM_REALM:\n                            allTypes.deleteFromRealm();\n                            break;\n                    }\n                    return false;\n                } catch (IllegalStateException ignored) {\n                    return true;\n                }\n            }\n        });\n\n        return future.get();\n    }\n\n    @Test\n    public void methodsThrowOnWrongThread() throws ExecutionException, InterruptedException {\n        realm.beginTransaction();\n        realm.createObject(AllTypes.class);\n        realm.commitTransaction();\n\n        for (Method method : Method.values()) {\n            assertTrue(runMethodOnWrongThread(method));\n        }\n    }\n\n    @Test\n    public void equals_sameObjectDifferentInstance() {\n        realm.beginTransaction();\n        CyclicType ct = realm.createObject(CyclicType.class);\n        ct.setName(\"Foo\");\n        realm.commitTransaction();\n\n        CyclicType ct1 = realm.where(CyclicType.class).findFirst();\n        CyclicType ct2 = realm.where(CyclicType.class).findFirst();\n\n        assertTrue(ct1.equals(ct2));\n        assertTrue(ct2.equals(ct1));\n    }\n\n    @Test\n    public void equals_differentObjects() {\n        realm.beginTransaction();\n        CyclicType objA = realm.createObject(CyclicType.class);\n        objA.setName(\"Foo\");\n        CyclicType objB = realm.createObject(CyclicType.class);\n        objB.setName(\"Bar\");\n        realm.commitTransaction();\n\n        assertFalse(objA.equals(objB));\n        assertFalse(objB.equals(objA));\n    }\n\n    @Test\n    public void equals_afterModification() {\n        realm.beginTransaction();\n        CyclicType ct = realm.createObject(CyclicType.class);\n        ct.setName(\"Foo\");\n        realm.commitTransaction();\n\n        CyclicType ct1 = realm.where(CyclicType.class).findFirst();\n        CyclicType ct2 = realm.where(CyclicType.class).findFirst();\n\n        realm.beginTransaction();\n        ct1.setName(\"Baz\");\n        realm.commitTransaction();\n\n        assertTrue(ct1.equals(ct2));\n        assertTrue(ct2.equals(ct1));\n    }\n\n    @Test\n    public void equals_unmanagedObject() {\n        realm.beginTransaction();\n        CyclicType ct1 = realm.createObject(CyclicType.class);\n        ct1.setName(\"Foo\");\n        realm.commitTransaction();\n\n        CyclicType ct2 = new CyclicType();\n        ct2.setName(\"Bar\");\n\n        assertFalse(ct1.equals(ct2));\n        assertFalse(ct2.equals(ct1));\n    }\n\n    @Test\n    public void equals_cyclicObject() {\n        realm.beginTransaction();\n        CyclicType foo = createCyclicData();\n        realm.commitTransaction();\n\n        assertEquals(foo, realm.where(CyclicType.class).equalTo(\"name\", \"Foo\").findFirst());\n    }\n\n    @Test\n    public void equals_plainCustomMethod() {\n        realm.beginTransaction();\n        CustomMethods cm = realm.createObject(CustomMethods.class);\n        cm.setName(\"Foo\");\n        realm.commitTransaction();\n\n        CustomMethods cm1 = realm.where(CustomMethods.class).findFirst();\n        CustomMethods cm2 = realm.where(CustomMethods.class).findFirst();\n        assertTrue(cm1.equals(cm2));\n    }\n\n    @Test\n    public void equals_unmanagedCustomMethod() {\n        CustomMethods cm1 = new CustomMethods();\n        cm1.setName(\"Bar\");\n        CustomMethods cm2 = new CustomMethods();\n        cm2.setName(\"Bar\");\n        assertTrue(cm1.equals(cm2));\n    }\n\n    @Test\n    public void equals_realmAnyCustomMethod() {\n        CustomMethods cm1 = new CustomMethods();\n        cm1.setName(\"Bar\");\n        CustomMethods cm2 = new CustomMethods();\n        cm2.setName(\"Bar\");\n\n        realm.beginTransaction();\n        realm.deleteAll();\n        realm.copyToRealm(cm1);\n        realm.commitTransaction();\n\n        CustomMethods cm3 = realm.where(CustomMethods.class).findFirst();\n        assertTrue(cm3.equals(cm2));\n        assertTrue(cm2.equals(cm3));\n    }\n\n    @Test\n    public void toString_cyclicObject() {\n        realm.beginTransaction();\n        CyclicType foo = createCyclicData();\n        realm.commitTransaction();\n        assertEquals(\n                \"CyclicType = proxy[{id:0},{name:Foo},{date:null},{object:CyclicType},{otherObject:null},{objects:RealmList<CyclicType>[0]}]\",\n                foo.toString());\n    }\n\n    @Test\n    public void toString_customMethod() {\n        realm.beginTransaction();\n        CustomMethods cm = realm.createObject(CustomMethods.class);\n        cm.setName(\"Foo\");\n        realm.commitTransaction();\n        String expected = CustomMethods.CUSTOM_TO_STRING;\n        assertEquals(expected, cm.toString());\n    }\n\n    // Test for https://github.com/realm/realm-java/issues/7084\n    @Test\n    public void toString_nullBinary() {\n        realm.beginTransaction();\n        AllJavaTypes obj = realm.createObject(AllJavaTypes.class, 1);\n        obj.setFieldBinary(null);\n        realm.commitTransaction();\n        String desc = obj.toString();\n        assertTrue(desc.contains(\"fieldBinary:null\"));\n    }\n\n    @Test\n    public void hashCode_cyclicObject() {\n        realm.beginTransaction();\n        final CyclicType foo = createCyclicData();\n        realm.commitTransaction();\n\n        // Checks that the hash code is always the same between multiple calls.\n        assertEquals(foo.hashCode(), foo.hashCode());\n        // Checks that the hash code is the same among same object.\n        assertEquals(foo.hashCode(), realm.where(CyclicType.class).equalTo(\"name\", foo.getName()).findFirst().hashCode());\n        // Hash code is different from other objects.\n        assertNotEquals(foo.getObject().hashCode(), foo.hashCode());\n\n        final int originalHashCode = foo.hashCode();\n        realm.executeTransaction(new Realm.Transaction() {\n            @Override\n            public void execute(Realm realm) {\n                foo.setName(foo.getName() + \"1234\");\n            }\n        });\n        // Checks that Updating the value of its field does not affect the hash code.\n        assertEquals(originalHashCode, foo.hashCode());\n\n        // Checks the hash code of the object from a Realm in different file name.\n        RealmConfiguration realmConfig_differentName = configFactory.createConfiguration(\n                \"another_\" + realmConfig.getRealmFileName());\n        Realm realm_differentName = Realm.getInstance(realmConfig_differentName);\n        //noinspection TryFinallyCanBeTryWithResources\n        try {\n            realm_differentName.beginTransaction();\n            CyclicType fooFromDifferentName = createCyclicData(realm_differentName);\n            realm_differentName.commitTransaction();\n\n            assertNotEquals(fooFromDifferentName.hashCode(), foo.hashCode());\n        } finally {\n            realm_differentName.close();\n        }\n\n        // Checks the hash code of the object from a Realm in different directory.\n        RealmConfiguration realmConfig_differentPath = configFactory.createConfiguration(\n                \"anotherDir\", realmConfig.getRealmFileName());\n        Realm realm_differentPath = Realm.getInstance(realmConfig_differentPath);\n        //noinspection TryFinallyCanBeTryWithResources\n        try {\n            realm_differentPath.beginTransaction();\n            CyclicType fooFromDifferentPath = createCyclicData(realm_differentPath);\n            realm_differentPath.commitTransaction();\n\n            assertNotEquals(fooFromDifferentPath.hashCode(), foo.hashCode());\n        } finally {\n            realm_differentPath.close();\n        }\n    }\n\n    @Test\n    public void hashCode_customMethod() {\n        realm.beginTransaction();\n        CustomMethods cm = realm.createObject(CustomMethods.class);\n        cm.setName(\"Foo\");\n        realm.commitTransaction();\n        assertEquals(CustomMethods.HASHCODE, cm.hashCode());\n    }\n\n    private CyclicType createCyclicData(Realm realm) {\n        CyclicType foo = realm.createObject(CyclicType.class);\n        foo.setName(\"Foo\");\n        CyclicType bar = realm.createObject(CyclicType.class);\n        bar.setName(\"Bar\");\n\n        // Setups cycle on normal object references.\n        foo.setObject(bar);\n        bar.setObject(foo);\n        return foo;\n    }\n\n    private CyclicType createCyclicData() {\n        return createCyclicData(realm);\n    }\n\n    @Test\n    public void dateType() {\n        long testDatesValid[] = {Long.MIN_VALUE, -1001, -1000, -1, 0, 1, 1000, 1001, Long.MAX_VALUE};\n\n        realm.beginTransaction();\n        for (long value : testDatesValid) {\n            AllTypes allTypes = realm.createObject(AllTypes.class);\n            allTypes.setColumnDate(new Date(value));\n        }\n        realm.commitTransaction();\n\n        int i = 0;\n        for (AllTypes allTypes : realm.where(AllTypes.class).findAll()) {\n            assertEquals(\"Item \" + i, new Date(testDatesValid[i]), allTypes.getColumnDate());\n            i++;\n        }\n    }\n\n    private Date newDate(int year, int month, int dayOfMonth) {\n        Calendar cal = Calendar.getInstance();\n        cal.set(Calendar.YEAR, year);\n        cal.set(Calendar.MONTH, month);\n        cal.set(Calendar.DAY_OF_MONTH, dayOfMonth);\n        cal.set(Calendar.HOUR, 0);\n        cal.set(Calendar.MINUTE, 0);\n        cal.set(Calendar.MILLISECOND, 0);\n        return cal.getTime();\n    }\n\n    @Test\n    public void setter_outsideTransactionThrows() {\n        realm.beginTransaction();\n        Dog dog = realm.createObject(Dog.class);\n        realm.commitTransaction();\n\n        thrown.expect(IllegalStateException.class);\n        dog.setName(\"Rex\");\n    }\n\n    @Test\n    public void setter_link_null() {\n        realm.beginTransaction();\n        CyclicType objA = realm.createObject(CyclicType.class);\n        objA.setName(\"Foo\");\n        CyclicType objB = realm.createObject(CyclicType.class);\n        objB.setName(\"Bar\");\n\n        objA.setObject(objB);\n\n        assertNotNull(objA.getObject());\n\n        try {\n            objA.setObject(null);\n        } catch (NullPointerException nullPointer) {\n            fail();\n        }\n        realm.commitTransaction();\n        assertNull(objA.getObject());\n    }\n\n    @Test\n    public void setter_link_unmanagedObject() {\n        CyclicType unmanaged = new CyclicType();\n\n        realm.beginTransaction();\n        try {\n            CyclicType target = realm.createObject(CyclicType.class);\n\n            try {\n                target.setObject(unmanaged);\n                fail();\n            } catch (IllegalArgumentException ignored) {\n            }\n        } finally {\n            realm.cancelTransaction();\n        }\n    }\n\n    @Test\n    public void setter_link_deletedObject() {\n        realm.beginTransaction();\n        try {\n            CyclicType target = realm.createObject(CyclicType.class);\n\n            CyclicType removed = realm.createObject(CyclicType.class);\n            removed.deleteFromRealm();\n\n            try {\n                target.setObject(removed);\n                fail();\n            } catch (IllegalArgumentException ignored) {\n            }\n        } finally {\n            realm.cancelTransaction();\n        }\n    }\n\n    @Test\n    public void setter_link_closedObject() {\n        realm.beginTransaction();\n        CyclicType closed = realm.createObject(CyclicType.class);\n        realm.commitTransaction();\n        realm.close();\n        assertTrue(realm.isClosed());\n\n        realm = Realm.getInstance(realmConfig);\n        realm.beginTransaction();\n        try {\n            CyclicType target = realm.createObject(CyclicType.class);\n\n            try {\n                target.setObject(closed);\n                fail();\n            } catch (IllegalArgumentException ignored) {\n            }\n        } finally {\n            realm.cancelTransaction();\n        }\n    }\n\n    @Test\n    public void setter_link_objectFromOtherRealm() {\n        RealmConfiguration config = configFactory.createConfiguration(\"another.realm\");\n        Realm anotherRealm = Realm.getInstance(config);\n        //noinspection TryFinallyCanBeTryWithResources\n        try {\n            anotherRealm.beginTransaction();\n            CyclicType objFromAnotherRealm = anotherRealm.createObject(CyclicType.class);\n            anotherRealm.commitTransaction();\n\n            realm.beginTransaction();\n            try {\n                CyclicType target = realm.createObject(CyclicType.class);\n\n                try {\n                    target.setObject(objFromAnotherRealm);\n                    fail();\n                } catch (IllegalArgumentException ignored) {\n                }\n            } finally {\n                realm.cancelTransaction();\n            }\n        } finally {\n            anotherRealm.close();\n        }\n    }\n\n    @Test\n    public void setter_link_objectFromAnotherThread() throws InterruptedException {\n        final CountDownLatch createLatch = new CountDownLatch(1);\n        final CountDownLatch testEndLatch = new CountDownLatch(1);\n\n        final AtomicReference<CyclicType> objFromAnotherThread = new AtomicReference<CyclicType>();\n\n        java.lang.Thread thread = new java.lang.Thread() {\n            @Override\n            public void run() {\n                Realm realm = Realm.getInstance(realmConfig);\n\n                // 1. Creates an object.\n                realm.beginTransaction();\n                objFromAnotherThread.set(realm.createObject(CyclicType.class));\n                realm.commitTransaction();\n\n                createLatch.countDown();\n                TestHelper.awaitOrFail(testEndLatch);\n\n                // 3. Closes Realm in this thread and finishes.\n                realm.close();\n            }\n        };\n        thread.start();\n\n        TestHelper.awaitOrFail(createLatch);\n        // 2. Sets created object to target.\n        realm.beginTransaction();\n        try {\n            CyclicType target = realm.createObject(CyclicType.class);\n            try {\n                target.setObject(objFromAnotherThread.get());\n                fail();\n            } catch (IllegalArgumentException ignored) {\n            }\n        } finally {\n            testEndLatch.countDown();\n            realm.cancelTransaction();\n        }\n\n        // Waits for finishing the thread.\n        thread.join();\n    }\n\n    @Test\n    public void setter_list_withUnmanagedObject() {\n        CyclicType unmanaged = new CyclicType();\n\n        realm.beginTransaction();\n        try {\n            CyclicType target = realm.createObject(CyclicType.class);\n\n            RealmList<CyclicType> list = new RealmList<CyclicType>();\n            list.add(realm.createObject(CyclicType.class));\n            list.add(unmanaged); // List contains an unmanaged object\n            list.add(realm.createObject(CyclicType.class));\n\n            try {\n                target.setObjects(list);\n                fail();\n            } catch (IllegalArgumentException ignored) {\n            }\n        } finally {\n            realm.cancelTransaction();\n        }\n    }\n\n    @Test\n    public void setter_list_withDeletedObject() {\n        realm.beginTransaction();\n        try {\n            CyclicType target = realm.createObject(CyclicType.class);\n\n            CyclicType removed = realm.createObject(CyclicType.class);\n            removed.deleteFromRealm();\n\n            RealmList<CyclicType> list = new RealmList<CyclicType>();\n            list.add(realm.createObject(CyclicType.class));\n            list.add(removed); // List contains a deleted object.\n            list.add(realm.createObject(CyclicType.class));\n\n            try {\n                target.setObjects(list);\n                fail();\n            } catch (IllegalArgumentException ignored) {\n            }\n        } finally {\n            realm.cancelTransaction();\n        }\n    }\n\n    @Test\n    public void setter_list_withClosedObject() {\n        realm.beginTransaction();\n        CyclicType closed = realm.createObject(CyclicType.class);\n        realm.commitTransaction();\n        realm.close();\n        assertTrue(realm.isClosed());\n\n        realm = Realm.getInstance(realmConfig);\n        realm.beginTransaction();\n        try {\n            CyclicType target = realm.createObject(CyclicType.class);\n\n            RealmList<CyclicType> list = new RealmList<CyclicType>();\n            list.add(realm.createObject(CyclicType.class));\n            list.add(closed); // List contains a closed object.\n            list.add(realm.createObject(CyclicType.class));\n\n            try {\n                target.setObjects(list);\n                fail();\n            } catch (IllegalArgumentException ignored) {\n            }\n        } finally {\n            realm.cancelTransaction();\n        }\n    }\n\n    @Test\n    public void setter_list_withObjectFromAnotherRealm() {\n        RealmConfiguration config = configFactory.createConfiguration(\"another.realm\");\n        Realm anotherRealm = Realm.getInstance(config);\n        //noinspection TryFinallyCanBeTryWithResources\n        try {\n            anotherRealm.beginTransaction();\n            CyclicType objFromAnotherRealm = anotherRealm.createObject(CyclicType.class);\n            anotherRealm.commitTransaction();\n\n            realm.beginTransaction();\n            try {\n                CyclicType target = realm.createObject(CyclicType.class);\n\n                RealmList<CyclicType> list = new RealmList<CyclicType>();\n                list.add(realm.createObject(CyclicType.class));\n                list.add(objFromAnotherRealm); // List contains an object from another Realm.\n                list.add(realm.createObject(CyclicType.class));\n\n                try {\n                    target.setObjects(list);\n                    fail();\n                } catch (IllegalArgumentException ignored) {\n                }\n            } finally {\n                realm.cancelTransaction();\n            }\n        } finally {\n            anotherRealm.close();\n        }\n    }\n\n    @Test\n    public void setter_list_withObjectFromAnotherThread() throws InterruptedException {\n        final CountDownLatch createLatch = new CountDownLatch(1);\n        final CountDownLatch testEndLatch = new CountDownLatch(1);\n\n        final AtomicReference<CyclicType> objFromAnotherThread = new AtomicReference<CyclicType>();\n\n        java.lang.Thread thread = new java.lang.Thread() {\n            @Override\n            public void run() {\n                Realm realm = Realm.getInstance(realmConfig);\n\n                // 1. Creates an object.\n                realm.beginTransaction();\n                objFromAnotherThread.set(realm.createObject(CyclicType.class));\n                realm.commitTransaction();\n\n                createLatch.countDown();\n                TestHelper.awaitOrFail(testEndLatch);\n\n                // 3. Close Realm in this thread and finishes.\n                realm.close();\n            }\n        };\n        thread.start();\n\n        TestHelper.awaitOrFail(createLatch);\n        // 2. Sets created object to target.\n        realm.beginTransaction();\n        try {\n            CyclicType target = realm.createObject(CyclicType.class);\n\n            RealmList<CyclicType> list = new RealmList<CyclicType>();\n            list.add(realm.createObject(CyclicType.class));\n            list.add(objFromAnotherThread.get()); // List contains an object from another thread.\n            list.add(realm.createObject(CyclicType.class));\n\n            try {\n                target.setObjects(list);\n                fail();\n            } catch (IllegalArgumentException ignored) {\n            }\n        } finally {\n            testEndLatch.countDown();\n            realm.cancelTransaction();\n        }\n\n        // Waits for finishing the thread.\n        thread.join();\n    }\n\n    @Test\n    public void setter_list_ownList() {\n        // Create initial list\n        realm.beginTransaction();\n        RealmList<AllJavaTypes> allTypesRealmModels = new RealmList<>();\n        for (int i = 0; i < 2; i++) {\n            allTypesRealmModels.add(new AllJavaTypes(i));\n        }\n        AllJavaTypes model = new AllJavaTypes(2);\n        model.setFieldList(allTypesRealmModels);\n        model = realm.copyToRealm(model);\n        realm.commitTransaction();\n        assertEquals(2, model.getFieldList().size());\n\n        // Check that setting own list does not clear it by accident.\n        realm.beginTransaction();\n        model.setFieldList(model.getFieldList());\n        realm.commitTransaction();\n        assertEquals(2, model.getFieldList().size());\n\n        // Check that a unmanaged list throws the correct exception\n        realm.beginTransaction();\n        RealmList<AllJavaTypes> unmanagedList = new RealmList<>();\n        unmanagedList.addAll(realm.copyFromRealm(model.getFieldList()));\n        try {\n            model.setFieldList(unmanagedList);\n            fail();\n        } catch (IllegalArgumentException ignored) {\n        }\n    }\n\n    @Test\n    public void classNameConflictsWithFrameworkClass() {\n        // The model class' name (Thread) clashed with a common Java class.\n        // The annotation process must be able to handle that.\n        realm.beginTransaction();\n        @SuppressWarnings(\"unused\")\n        io.realm.entities.Thread thread = realm.createObject(io.realm.entities.Thread.class);\n        realm.commitTransaction();\n    }\n\n    @Test\n    public void isValid_unmanagedObject() {\n        AllTypes allTypes = new AllTypes();\n        assertTrue(allTypes.isValid());\n    }\n\n    @Test\n    public void isValid_closedRealm() {\n        RealmConfiguration otherConfig = configFactory.createConfiguration(\"other-realm\");\n        Realm testRealm = Realm.getInstance(otherConfig);\n        testRealm.beginTransaction();\n        AllTypes allTypes = testRealm.createObject(AllTypes.class);\n        assertTrue(allTypes.isValid());\n        testRealm.commitTransaction();\n        testRealm.close();\n        assertFalse(allTypes.isValid());\n    }\n\n    @Test\n    public void isValid_deletedObject() {\n        realm.beginTransaction();\n        AllTypes allTypes = realm.createObject(AllTypes.class);\n        assertTrue(allTypes.isValid());\n        realm.delete(AllTypes.class);\n        realm.commitTransaction();\n        assertFalse(allTypes.isValid());\n    }\n\n    @Test\n    public void isValid_managedObject() {\n        realm.beginTransaction();\n        AllTypes allTypes = realm.createObject(AllTypes.class);\n        assertTrue(allTypes.isValid());\n        realm.commitTransaction();\n        assertTrue(allTypes.isValid());\n    }\n\n    @Test\n    public void isValid_null() {\n        //noinspection ConstantConditions\n        assertFalse(RealmObject.isValid(null));\n    }\n\n    // Stores and retrieves null values for nullable fields.\n    @Test\n    public void set_get_nullOnNullableFields() {\n        realm.beginTransaction();\n        NullTypes nullTypes = realm.createObject(NullTypes.class, 0);\n        // 1 String\n        nullTypes.setFieldStringNull(null);\n        // 2 Bytes\n        nullTypes.setFieldBytesNull(null);\n        // 3 Boolean\n        nullTypes.setFieldBooleanNull(null);\n        // 4 Byte\n        nullTypes.setFieldByteNull(null);\n        // 5 Short\n        nullTypes.setFieldShortNull(null);\n        // 6 Integer\n        nullTypes.setFieldIntegerNull(null);\n        // 7 Long\n        nullTypes.setFieldLongNull(null);\n        // 8 Float\n        nullTypes.setFieldFloatNull(null);\n        // 9 Double\n        nullTypes.setFieldDoubleNull(null);\n        // 10 Date\n        nullTypes.setFieldDateNull(null);\n        realm.commitTransaction();\n\n        nullTypes = realm.where(NullTypes.class).findFirst();\n        // 1 String\n        assertNull(nullTypes.getFieldStringNull());\n        // 2 Bytes\n        assertNull(nullTypes.getFieldBytesNull());\n        // 3 Boolean\n        assertNull(nullTypes.getFieldBooleanNull());\n        // 4 Byte\n        assertNull(nullTypes.getFieldByteNull());\n        // 5 Short\n        assertNull(nullTypes.getFieldShortNull());\n        // 6 Integer\n        assertNull(nullTypes.getFieldIntegerNull());\n        // 7 Long\n        assertNull(nullTypes.getFieldLongNull());\n        // 8 Float\n        assertNull(nullTypes.getFieldFloatNull());\n        // 9 Double\n        assertNull(nullTypes.getFieldDoubleNull());\n        // 10 Date\n        assertNull(nullTypes.getFieldDateNull());\n    }\n\n    // Stores and retrieves non-null values when field can contain null strings.\n    @Test\n    public void get_set_nonNullValueOnNullableFields() {\n        final String testString = \"FooBar\";\n        final byte[] testBytes = new byte[] {42};\n        final Date testDate = newDate(2000, 1, 1);\n        realm.beginTransaction();\n        NullTypes nullTypes = realm.createObject(NullTypes.class, 0);\n        // 1 String\n        nullTypes.setFieldStringNull(testString);\n        // 2 Bytes\n        nullTypes.setFieldBytesNull(testBytes);\n        // 3 Boolean\n        nullTypes.setFieldBooleanNull(true);\n        // 4 Byte\n        nullTypes.setFieldByteNull((byte) 42);\n        // 5 Short\n        nullTypes.setFieldShortNull((short) 42);\n        // 6 Integer\n        nullTypes.setFieldIntegerNull(42);\n        // 7 Long\n        nullTypes.setFieldLongNull(42L);\n        // 8 Float\n        nullTypes.setFieldFloatNull(42.42F);\n        // 9 Double\n        nullTypes.setFieldDoubleNull(42.42D);\n        // 10 Date\n        nullTypes.setFieldDateNull(testDate);\n        realm.commitTransaction();\n\n        nullTypes = realm.where(NullTypes.class).findFirst();\n        // 1 String\n        assertEquals(testString, nullTypes.getFieldStringNull());\n        // 2 Bytes\n        assertArrayEquals(testBytes, nullTypes.getFieldBytesNull());\n        // 3 Boolean\n        assertTrue(nullTypes.getFieldBooleanNull());\n        // 4 Byte\n        assertEquals((byte) 42, (byte) nullTypes.getFieldByteNull().intValue());\n        // 5 Short\n        assertEquals((short) 42, (short) nullTypes.getFieldShortNull().intValue());\n        // 6 Integer\n        assertEquals(42, nullTypes.getFieldIntegerNull().intValue());\n        // 7 Long\n        assertEquals(42L, nullTypes.getFieldLongNull().longValue());\n        // 8 Float\n        assertEquals(42.42F, nullTypes.getFieldFloatNull(), 0.0F);\n        // 9 Double\n        assertEquals(42.42D, nullTypes.getFieldDoubleNull(), 0.0D);\n        // 10 Date\n        assertEquals(testDate.getTime(), nullTypes.getFieldDateNull().getTime());\n    }\n\n    // Tries to store null values in non-nullable fields.\n    @Test\n    public void set_nullValuesToNonNullableFields() {\n        try {\n            realm.beginTransaction();\n            NullTypes nullTypes = realm.createObject(NullTypes.class, 0);\n            // 1 String\n            try {\n                nullTypes.setFieldStringNotNull(null);\n                fail();\n            } catch (IllegalArgumentException ignored) {\n            }\n            // 2 Bytes\n            try {\n                nullTypes.setFieldBytesNotNull(null);\n                fail();\n            } catch (IllegalArgumentException ignored) {\n            }\n            // 3 Boolean\n            try {\n                nullTypes.setFieldBooleanNotNull(null);\n                fail();\n            } catch (IllegalArgumentException ignored) {\n            }\n            // 4 Byte\n            try {\n                nullTypes.setFieldByteNotNull(null);\n                fail();\n            } catch (IllegalArgumentException ignored) {\n            }\n            // 5 Short\n            try {\n                nullTypes.setFieldShortNotNull(null);\n                fail();\n            } catch (IllegalArgumentException ignored) {\n            }\n            // 6 Integer\n            try {\n                nullTypes.setFieldIntegerNotNull(null);\n                fail();\n            } catch (IllegalArgumentException ignored) {\n            }\n            // 7 Long\n            try {\n                nullTypes.setFieldLongNotNull(null);\n                fail();\n            } catch (IllegalArgumentException ignored) {\n            }\n            // 8 Float\n            try {\n                nullTypes.setFieldFloatNotNull(null);\n                fail();\n            } catch (IllegalArgumentException ignored) {\n            }\n            // 9 Double\n            try {\n                nullTypes.setFieldDoubleNotNull(null);\n                fail();\n            } catch (IllegalArgumentException ignored) {\n            }\n            // 10 Date\n            try {\n                nullTypes.setFieldDateNotNull(null);\n                fail();\n            } catch (IllegalArgumentException ignored) {\n            }\n        } finally {\n            realm.cancelTransaction();\n        }\n    }\n\n    @Test\n    public void defaultValuesForNewObject() {\n        realm.beginTransaction();\n        NullTypes nullTypes = realm.createObject(NullTypes.class, 0);\n        realm.commitTransaction();\n\n        assertNotNull(nullTypes);\n        assertEquals(0, nullTypes.getId());\n        // 1 String\n        assertEquals(\"\", nullTypes.getFieldStringNotNull());\n        assertNull(nullTypes.getFieldStringNull());\n        // 2 Bytes\n        assertArrayEquals(new byte[0], nullTypes.getFieldBytesNotNull());\n        assertNull(nullTypes.getFieldByteNull());\n        // 3 Boolean\n        assertFalse(nullTypes.getFieldBooleanNotNull());\n        assertNull(nullTypes.getFieldBooleanNull());\n        // 4 Byte\n        assertEquals(0, nullTypes.getFieldByteNotNull().byteValue());\n        assertNull(nullTypes.getFieldByteNull());\n        // 5 Short\n        assertEquals(0, nullTypes.getFieldShortNotNull().shortValue());\n        assertNull(nullTypes.getFieldShortNull());\n        // 6 Integer\n        assertEquals(0, nullTypes.getFieldIntegerNotNull().intValue());\n        assertNull(nullTypes.getFieldIntegerNull());\n        // 7 Long\n        assertEquals(0, nullTypes.getFieldLongNotNull().longValue());\n        assertNull(nullTypes.getFieldLongNull());\n        // 8 Float\n        assertEquals(0F, nullTypes.getFieldFloatNotNull(), 0.0F);\n        assertNull(nullTypes.getFieldFloatNull());\n        // 9 Double\n        assertEquals(0D, nullTypes.getFieldDoubleNotNull(), 0.0D);\n        assertNull(nullTypes.getFieldDoubleNull());\n        // 10 Date\n        assertEquals(new Date(0), nullTypes.getFieldDateNotNull());\n        assertNull(nullTypes.getFieldDateNull());\n    }\n\n    @Test\n    public void getter_afterDeleteFromOtherThreadThrows() {\n        final CountDownLatch bgRealmDone = new CountDownLatch(1);\n        realm.beginTransaction();\n        final AllTypes obj = realm.createObject(AllTypes.class);\n        realm.commitTransaction();\n\n        new Thread(new Runnable() {\n            @Override\n            public void run() {\n                Realm bgRealm = Realm.getInstance(realm.getConfiguration());\n                bgRealm.beginTransaction();\n                bgRealm.delete(AllTypes.class);\n                bgRealm.commitTransaction();\n                bgRealm.close();\n                bgRealmDone.countDown();\n            }\n        }).start();\n        TestHelper.awaitOrFail(bgRealmDone);\n        realm.refresh();\n\n        // Object should no longer be available.\n        assertFalse(obj.isValid());\n        try {\n            obj.getColumnLong();\n            fail();\n        } catch (IllegalStateException ignored) {\n        }\n    }\n\n    @Test\n    public void isValid() {\n        realm.beginTransaction();\n        Dog dog = realm.createObject(Dog.class);\n        dog.setName(\"Fido\");\n        realm.commitTransaction();\n\n        assertTrue(dog.isValid());\n\n        realm.beginTransaction();\n        dog.deleteFromRealm();\n        realm.commitTransaction();\n\n        assertFalse(dog.isValid());\n    }\n\n    @Test\n    public void isManaged_managedObject() {\n        realm.beginTransaction();\n        Dog dog = realm.createObject(Dog.class);\n        realm.commitTransaction();\n\n        assertTrue(dog.isManaged());\n    }\n\n    @Test\n    public void isManaged_unmanagedObject() {\n        Dog dog = new Dog();\n        assertFalse(dog.isManaged());\n    }\n\n    // Tests NaN value on float and double columns.\n    @Test\n    public void float_double_NaN() {\n        realm.beginTransaction();\n        AllTypes allTypes = realm.createObject(AllTypes.class);\n        allTypes.setColumnFloat(Float.NaN);\n        allTypes.setColumnDouble(Double.NaN);\n        realm.commitTransaction();\n        assertEquals(Float.NaN, realm.where(AllTypes.class).findFirst().getColumnFloat(), 0.0F);\n        assertEquals(Double.NaN, realm.where(AllTypes.class).findFirst().getColumnDouble(), 0.0D);\n        // NaN != NaN !!!\n        assertEquals(0, realm.where(AllTypes.class).equalTo(\"columnFloat\", Float.NaN).count());\n        assertEquals(0, realm.where(AllTypes.class).equalTo(\"columnDouble\", Double.NaN).count());\n    }\n\n    // Tests max value on float and double columns.\n    @Test\n    public void float_double_maxValue() {\n        realm.beginTransaction();\n        AllTypes allTypes = realm.createObject(AllTypes.class);\n        allTypes.setColumnFloat(Float.MAX_VALUE);\n        allTypes.setColumnDouble(Double.MAX_VALUE);\n        realm.commitTransaction();\n        assertEquals(Float.MAX_VALUE, realm.where(AllTypes.class).findFirst().getColumnFloat(), 0.0F);\n        assertEquals(Double.MAX_VALUE, realm.where(AllTypes.class).findFirst().getColumnDouble(), 0.0D);\n        assertEquals(1, realm.where(AllTypes.class).equalTo(\"columnFloat\", Float.MAX_VALUE).count());\n        assertEquals(1, realm.where(AllTypes.class).equalTo(\"columnDouble\", Double.MAX_VALUE).count());\n    }\n\n    // Tests min normal value on float and double columns.\n    @Test\n    public void float_double_minNormal() {\n        realm.beginTransaction();\n        AllTypes allTypes = realm.createObject(AllTypes.class);\n        allTypes.setColumnFloat(Float.MIN_NORMAL);\n        allTypes.setColumnDouble(Double.MIN_NORMAL);\n        realm.commitTransaction();\n        assertEquals(Float.MIN_NORMAL, realm.where(AllTypes.class).findFirst().getColumnFloat(), 0.0F);\n        assertEquals(Double.MIN_NORMAL, realm.where(AllTypes.class).findFirst().getColumnDouble(), 0.0D);\n        assertEquals(1, realm.where(AllTypes.class).equalTo(\"columnFloat\", Float.MIN_NORMAL).count());\n        assertEquals(1, realm.where(AllTypes.class).equalTo(\"columnDouble\", Double.MIN_NORMAL).count());\n    }\n\n    // Tests min value on float and double columns.\n    @Test\n    public void float_double_minValue() {\n        realm.beginTransaction();\n        AllTypes allTypes = realm.createObject(AllTypes.class);\n        allTypes.setColumnFloat(Float.MIN_VALUE);\n        allTypes.setColumnDouble(Double.MIN_VALUE);\n        realm.commitTransaction();\n        assertEquals(Float.MIN_VALUE, realm.where(AllTypes.class).findFirst().getColumnFloat(), 0.0F);\n        assertEquals(Double.MIN_VALUE, realm.where(AllTypes.class).findFirst().getColumnDouble(), 0.0D);\n        assertEquals(1, realm.where(AllTypes.class).equalTo(\"columnFloat\", Float.MIN_VALUE).count());\n        assertEquals(1, realm.where(AllTypes.class).equalTo(\"columnDouble\", Double.MIN_VALUE).count());\n    }\n\n    // Tests negative infinity value on float and double columns.\n    @Test\n    public void float_double_negativeInfinity() {\n        realm.beginTransaction();\n        AllTypes allTypes = realm.createObject(AllTypes.class);\n        allTypes.setColumnFloat(Float.NEGATIVE_INFINITY);\n        allTypes.setColumnDouble(Double.NEGATIVE_INFINITY);\n        realm.commitTransaction();\n        assertEquals(Float.NEGATIVE_INFINITY, realm.where(AllTypes.class).findFirst().getColumnFloat(), 0.0F);\n        assertEquals(Double.NEGATIVE_INFINITY, realm.where(AllTypes.class).findFirst().getColumnDouble(), 0.0D);\n        assertEquals(1, realm.where(AllTypes.class).equalTo(\"columnFloat\", Float.NEGATIVE_INFINITY).count());\n        assertEquals(1, realm.where(AllTypes.class).equalTo(\"columnDouble\", Double.NEGATIVE_INFINITY).count());\n    }\n\n    // Tests positive infinity value on float and double columns.\n    @Test\n    public void float_double_positiveInfinity() {\n        realm.beginTransaction();\n        AllTypes allTypes = realm.createObject(AllTypes.class);\n        allTypes.setColumnFloat(Float.POSITIVE_INFINITY);\n        allTypes.setColumnDouble(Double.POSITIVE_INFINITY);\n        realm.commitTransaction();\n        assertEquals(Float.POSITIVE_INFINITY, realm.where(AllTypes.class).findFirst().getColumnFloat(), 0.0F);\n        assertEquals(Double.POSITIVE_INFINITY, realm.where(AllTypes.class).findFirst().getColumnDouble(), 0.0D);\n        assertEquals(1, realm.where(AllTypes.class).equalTo(\"columnFloat\", Float.POSITIVE_INFINITY).count());\n        assertEquals(1, realm.where(AllTypes.class).equalTo(\"columnDouble\", Double.POSITIVE_INFINITY).count());\n    }\n\n    private RealmConfiguration prepareColumnSwappedRealm() throws FileNotFoundException {\n\n        final RealmConfiguration columnSwappedRealmConfigForV0 = configFactory.createConfigurationBuilder()\n                .name(\"columnSwapped.realm\")\n                .migration(new RealmMigration() {\n                    @Override\n                    public void migrate(DynamicRealm realm, long oldVersion, long newVersion) {\n                        final Table table = realm.getSchema().getTable(StringAndInt.class);\n                        final long strColKey = table.getColumnKey(\"str\");\n                        final long numberColKey = table.getColumnKey(\"number\");\n\n                        for (String columnName :table.getColumnNames()) {\n                            table.removeColumn(table.getColumnKey(columnName));\n                        }\n                        final long newStrIndex;\n                        // Swaps column indices.\n                        if (strColKey < numberColKey) {\n                            table.addColumn(RealmFieldType.INTEGER, \"number\");\n                            newStrIndex = table.addColumn(RealmFieldType.STRING, \"str\");\n                        } else {\n                            newStrIndex = table.addColumn(RealmFieldType.STRING, \"str\");\n                            table.addColumn(RealmFieldType.INTEGER, \"number\");\n                        }\n                        table.convertColumnToNullable(newStrIndex);\n                    }\n                })\n                .build();\n\n        final RealmConfiguration columnSwappedRealmConfigForV1 = configFactory.createConfigurationBuilder()\n                .name(\"columnSwapped.realm\")\n                .migration(new RealmMigration() {\n                    @Override\n                    public void migrate(DynamicRealm realm, long oldVersion, long newVersion) {\n                        // Does nothing.\n                    }\n                })\n                .schemaVersion(1L)\n                .build();\n\n        Realm.deleteRealm(columnSwappedRealmConfigForV0);\n        Realm.getInstance(columnSwappedRealmConfigForV0).close();\n        Realm.migrateRealm(columnSwappedRealmConfigForV0);\n        return columnSwappedRealmConfigForV1;\n    }\n\n    @Test\n    public void realmProxy_columnIndex() throws FileNotFoundException {\n        final RealmConfiguration configForSwapped = prepareColumnSwappedRealm();\n\n        // Opens swapped Realm in order to load column index.\n        Realm.getInstance(configForSwapped).close();\n\n        realm.executeTransaction(new Realm.Transaction() {\n            @Override\n            public void execute(Realm realm) {\n                final StringAndInt obj = RealmObjectTests.this.realm.createObject(StringAndInt.class);\n                /*\n                 * If https://github.com/realm/realm-java/issues/1611 issue exists,\n                 * setter/getter of RealmObjectProxy uses last loaded column index for every Realm.\n                 */\n                obj.setStr(\"foo\");\n                obj.getStr();\n            }\n        });\n    }\n\n    @Test\n    public void conflictingFieldName_readAndUpdate() {\n        final ConflictingFieldName unmanaged = new ConflictingFieldName();\n        unmanaged.setRealmString(\"realm\");\n        unmanaged.setRow(\"row\");\n        unmanaged.setIsCompleted(\"isCompleted\");\n        unmanaged.setListeners(\"listeners\");\n        unmanaged.setPendingQuery(\"pendingQuery\");\n        unmanaged.setCurrentTableVersion(\"currentTableVersion\");\n\n        realm.executeTransaction(new Realm.Transaction() {\n            @Override\n            public void execute(Realm realm) {\n                realm.copyToRealm(unmanaged);\n            }\n        });\n\n        // Tests those values are persisted.\n        final ConflictingFieldName managed = realm.where(ConflictingFieldName.class).findFirst();\n        assertEquals(\"realm\", managed.getRealmString());\n        assertEquals(\"row\", managed.getRow());\n        assertEquals(\"isCompleted\", managed.getIsCompleted());\n        assertEquals(\"listeners\", managed.getListeners());\n        assertEquals(\"pendingQuery\", managed.getPendingQuery());\n        assertEquals(\"currentTableVersion\", managed.getCurrentTableVersion());\n\n        // Tests those values can be updated.\n        realm.executeTransaction(new Realm.Transaction() {\n            @Override\n            public void execute(Realm realm) {\n                managed.setRealmString(\"realm_updated\");\n                managed.setRow(\"row_updated\");\n                managed.setIsCompleted(\"isCompleted_updated\");\n                managed.setListeners(\"listeners_updated\");\n                managed.setPendingQuery(\"pendingQuery_updated\");\n                managed.setCurrentTableVersion(\"currentTableVersion_updated\");\n            }\n        });\n\n        assertEquals(\"realm_updated\", managed.getRealmString());\n        assertEquals(\"row_updated\", managed.getRow());\n        assertEquals(\"isCompleted_updated\", managed.getIsCompleted());\n        assertEquals(\"listeners_updated\", managed.getListeners());\n        assertEquals(\"pendingQuery_updated\", managed.getPendingQuery());\n        assertEquals(\"currentTableVersion_updated\", managed.getCurrentTableVersion());\n    }\n\n    // Setting a not-nullable field to null is an error.\n    // TODO Move this to RealmObjectTests?\n    @Test\n    public void setter_nullValueInRequiredField() {\n        TestHelper.populateTestRealmForNullTests(realm);\n        RealmResults<NullTypes> list = realm.where(NullTypes.class).findAll();\n\n        // 1 String\n        try {\n            realm.beginTransaction();\n            list.first().setFieldStringNotNull(null);\n            fail();\n        } catch (IllegalArgumentException ignored) {\n            assertTrue(ignored.getMessage().contains(NullTypes.FIELD_STRING_NOT_NULL));\n        } finally {\n            realm.cancelTransaction();\n        }\n\n        // 2 Bytes\n        try {\n            realm.beginTransaction();\n            list.first().setFieldBytesNotNull(null);\n            fail();\n        } catch (IllegalArgumentException ignored) {\n            assertTrue(ignored.getMessage().contains(NullTypes.FIELD_BYTES_NOT_NULL));\n        } finally {\n            realm.cancelTransaction();\n        }\n\n        // 3 Boolean\n        try {\n            realm.beginTransaction();\n            list.first().setFieldBooleanNotNull(null);\n            fail();\n        } catch (IllegalArgumentException ignored) {\n            assertTrue(ignored.getMessage().contains(NullTypes.FIELD_BOOLEAN_NOT_NULL));\n        } finally {\n            realm.cancelTransaction();\n        }\n\n        // 4 Byte\n        try {\n            realm.beginTransaction();\n            list.first().setFieldByteNotNull(null);\n            fail();\n        } catch (IllegalArgumentException ignored) {\n            assertTrue(ignored.getMessage().contains(NullTypes.FIELD_BYTE_NOT_NULL));\n        } finally {\n            realm.cancelTransaction();\n        }\n\n        // 5 Short 6 Integer 7 Long are skipped for this case, same with Bytes\n\n        // 8 Float\n        try {\n            realm.beginTransaction();\n            list.first().setFieldFloatNotNull(null);\n            fail();\n        } catch (IllegalArgumentException ignored) {\n            assertTrue(ignored.getMessage().contains(NullTypes.FIELD_FLOAT_NOT_NULL));\n        } finally {\n            realm.cancelTransaction();\n        }\n\n        // 9 Double\n        try {\n            realm.beginTransaction();\n            list.first().setFieldDoubleNotNull(null);\n            fail();\n        } catch (IllegalArgumentException ignored) {\n            assertTrue(ignored.getMessage().contains(NullTypes.FIELD_DOUBLE_NOT_NULL));\n        } finally {\n            realm.cancelTransaction();\n        }\n\n        // 10 Date\n        try {\n            realm.beginTransaction();\n            list.first().setFieldDateNotNull(null);\n            fail();\n        } catch (IllegalArgumentException ignored) {\n            assertTrue(ignored.getMessage().contains(NullTypes.FIELD_DATE_NOT_NULL));\n        } finally {\n            realm.cancelTransaction();\n        }\n    }\n\n    // Setting a nullable field to null is not an error.\n    // TODO Move this to RealmObjectsTest?\n    @Test\n    public void setter_nullValueInNullableField() {\n        TestHelper.populateTestRealmForNullTests(realm);\n        RealmResults<NullTypes> list = realm.where(NullTypes.class).findAll();\n\n        // 1 String\n        realm.beginTransaction();\n        list.first().setFieldStringNull(null);\n        realm.commitTransaction();\n        assertNull(realm.where(NullTypes.class).findFirst().getFieldStringNull());\n\n        // 2 Bytes\n        realm.beginTransaction();\n        list.first().setFieldBytesNull(null);\n        realm.commitTransaction();\n        assertNull(realm.where(NullTypes.class).findFirst().getFieldBytesNull());\n\n        // 3 Boolean\n        realm.beginTransaction();\n        list.first().setFieldBooleanNull(null);\n        realm.commitTransaction();\n        assertNull(realm.where(NullTypes.class).findFirst().getFieldBooleanNull());\n\n        // 4 Byte\n        // 5 Short 6 Integer 7 Long are skipped\n        realm.beginTransaction();\n        list.first().setFieldByteNull(null);\n        realm.commitTransaction();\n        assertNull(realm.where(NullTypes.class).findFirst().getFieldByteNull());\n\n        // 8 Float\n        realm.beginTransaction();\n        list.first().setFieldFloatNull(null);\n        realm.commitTransaction();\n        assertNull(realm.where(NullTypes.class).findFirst().getFieldFloatNull());\n\n        // 9 Double\n        realm.beginTransaction();\n        list.first().setFieldDoubleNull(null);\n        realm.commitTransaction();\n        assertNull(realm.where(NullTypes.class).findFirst().getFieldDoubleNull());\n\n        // 10 Date\n        realm.beginTransaction();\n        list.first().setFieldDateNull(null);\n        realm.commitTransaction();\n        assertNull(realm.where(NullTypes.class).findFirst().getFieldDateNull());\n    }\n\n    @Test\n    public void setter_changePrimaryKeyThrows() {\n        realm.beginTransaction();\n        AllJavaTypes allJavaTypes = realm.createObject(AllJavaTypes.class, 42);\n        thrown.expect(RealmException.class);\n        allJavaTypes.setFieldId(111);\n        realm.cancelTransaction();\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void addChangeListener_throwOnAddingNullListenerFromLooperThread() {\n        final Realm realm = looperThread.getRealm();\n        Dog dog = createManagedDogObjectFromRealmInstance(realm);\n\n        try {\n            dog.addChangeListener((RealmChangeListener) null);\n            fail(\"adding null change listener must throw an exception.\");\n        } catch (IllegalArgumentException ignore) {\n        }\n\n        try {\n            dog.addChangeListener((RealmObjectChangeListener) null);\n            fail(\"adding null change listener must throw an exception.\");\n        } catch (IllegalArgumentException ignore) {\n        }\n\n        looperThread.testComplete();\n    }\n\n    @Test\n    public void addChangeListener_throwOnAddingNullListenerFromNonLooperThread() throws Throwable {\n        final Dog dog = createManagedDogObjectFromRealmInstance(realm);\n\n        try {\n            dog.addChangeListener((RealmChangeListener) null);\n            fail(\"adding null change listener must throw an exception.\");\n        } catch (IllegalArgumentException ignore) {\n        }\n\n        try {\n            dog.addChangeListener((RealmObjectChangeListener) null);\n            fail(\"adding null change listener must throw an exception.\");\n        } catch (IllegalArgumentException ignore) {\n        }\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void changeListener_triggeredWhenObjectIsDeleted() {\n        final Realm realm = looperThread.getRealm();\n        realm.beginTransaction();\n        AllTypes obj = realm.createObject(AllTypes.class);\n        realm.commitTransaction();\n\n        obj.addChangeListener(new RealmChangeListener<AllTypes>() {\n            @Override\n            public void onChange(AllTypes obj) {\n                assertFalse(obj.isValid());\n                looperThread.testComplete();\n            }\n        });\n\n        realm.beginTransaction();\n        obj.deleteFromRealm();\n        realm.commitTransaction();\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void addChangeListener_throwOnUnmanagedObject() {\n        Dog dog = new Dog();\n\n        try {\n            dog.addChangeListener(new RealmChangeListener<Dog>() {\n                @Override\n                public void onChange(Dog object) {\n                }\n            });\n            fail(\"adding change listener on unmanaged object must throw an exception.\");\n        } catch (IllegalArgumentException ignore) {\n        }\n\n        try {\n            dog.addChangeListener(new RealmObjectChangeListener<Dog>() {\n                @Override\n                public void onChange(Dog object, ObjectChangeSet changeSet) {\n                }\n            });\n            fail(\"adding change listener on unmanaged object must throw an exception.\");\n        } catch (IllegalArgumentException ignore) {\n        }\n\n        looperThread.testComplete();\n    }\n\n    // Object Store will throw when adding change listener inside a transaction.\n    @Test\n    @RunTestInLooperThread\n    public void addChangeListener_throwInsiderTransaction() {\n        Realm realm = looperThread.getRealm();\n\n        realm.beginTransaction();\n        Dog dog = realm.createObject(Dog.class);\n        try {\n            dog.addChangeListener(new RealmChangeListener<Dog>() {\n                @Override\n                public void onChange(Dog element) {\n                    fail();\n                }\n            });\n        } catch (IllegalStateException ignored) {\n        }\n\n        try {\n            dog.addChangeListener(new RealmObjectChangeListener<Dog>() {\n                @Override\n                public void onChange(Dog object, ObjectChangeSet changeSet) {\n                    fail();\n                }\n            });\n        } catch (IllegalStateException ignored) {\n        }\n        realm.cancelTransaction();\n\n        looperThread.testComplete();\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void removeChangeListener_throwOnRemovingNullListenerFromLooperThread() {\n        final Realm realm = looperThread.getRealm();\n        Dog dog = createManagedDogObjectFromRealmInstance(realm);\n\n        try {\n            dog.removeChangeListener((RealmChangeListener) null);\n            fail(\"removing null change listener must throw an exception.\");\n        } catch (IllegalArgumentException ignore) {\n        }\n\n        try {\n            dog.removeChangeListener((RealmObjectChangeListener) null);\n            fail(\"removing null change listener must throw an exception.\");\n        } catch (IllegalArgumentException ignore) {\n        }\n\n        looperThread.testComplete();\n    }\n\n    @Test\n    public void removeChangeListener_throwOnRemovingNullListenerFromNonLooperThread() throws Throwable {\n        final Dog dog = createManagedDogObjectFromRealmInstance(realm);\n\n        try {\n            dog.removeChangeListener((RealmChangeListener) null);\n            fail(\"removing null change listener must throw an exception.\");\n        } catch (IllegalArgumentException ignore) {\n        }\n\n        try {\n            dog.removeChangeListener((RealmObjectChangeListener) null);\n            fail(\"removing null change listener must throw an exception.\");\n        } catch (IllegalArgumentException ignore) {\n        }\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void removeChangeListener_insideTransaction() {\n        Realm realm = looperThread.getRealm();\n        final Dog dog = createManagedDogObjectFromRealmInstance(realm);\n        RealmChangeListener<Dog> realmChangeListener = new RealmChangeListener<Dog>() {\n            @Override\n            public void onChange(Dog element) {\n            }\n        };\n        RealmObjectChangeListener<Dog> realmObjectChangeListener = new RealmObjectChangeListener<Dog>() {\n            @Override\n            public void onChange(Dog object, ObjectChangeSet changeSet) {\n            }\n        };\n\n        dog.addChangeListener(realmChangeListener);\n        dog.addChangeListener(realmObjectChangeListener);\n\n        realm.beginTransaction();\n        dog.removeChangeListener(realmChangeListener);\n        dog.removeChangeListener(realmObjectChangeListener);\n        realm.cancelTransaction();\n        looperThread.testComplete();\n    }\n\n    /**\n     * This test is to see if RealmObject.removeChangeListeners() works as it is intended.\n     */\n    @Test\n    @RunTestInLooperThread\n    public void removeAllChangeListeners() {\n        final Realm realm = looperThread.getRealm();\n        realm.beginTransaction();\n        Dog dog = realm.createObject(Dog.class);\n        dog.setAge(13);\n        realm.commitTransaction();\n        dog.addChangeListener(new RealmChangeListener<Dog>() {\n            @Override\n            public void onChange(Dog object) {\n                fail();\n            }\n        });\n        dog.addChangeListener(new RealmObjectChangeListener<Dog>() {\n            @Override\n            public void onChange(Dog object, ObjectChangeSet changeSet) {\n                fail();\n            }\n        });\n        dog.removeAllChangeListeners();\n\n        realm.beginTransaction();\n        Dog sameDog = realm.where(Dog.class).equalTo(Dog.FIELD_AGE, 13).findFirst();\n        sameDog.setName(\"Jesper\");\n        realm.commitTransaction();\n        // Try to trigger the listeners.\n        realm.sharedRealm.refresh();\n        looperThread.testComplete();\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void removeAllChangeListeners_thenAdd() {\n        final Realm realm = looperThread.getRealm();\n        realm.beginTransaction();\n        Dog dog = realm.createObject(Dog.class);\n        dog.setAge(13);\n        realm.commitTransaction();\n        dog.addChangeListener(new RealmChangeListener<Dog>() {\n            @Override\n            public void onChange(Dog object) {\n                fail();\n            }\n        });\n        dog.removeAllChangeListeners();\n\n        dog.addChangeListener(new RealmChangeListener<Dog>() {\n            @Override\n            public void onChange(Dog dog) {\n                assertEquals(14, dog.getAge());\n                looperThread.testComplete();\n            }\n        });\n\n        realm.beginTransaction();\n        dog.setAge(14);\n        realm.commitTransaction();\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void removeChangeListener_throwOnUnmanagedObject() {\n        Dog dog = new Dog();\n        RealmChangeListener listener = new RealmChangeListener<Dog>() {\n            @Override\n            public void onChange(Dog object) {\n            }\n        };\n        RealmObjectChangeListener objectChangeListener = new RealmObjectChangeListener<Dog>() {\n            @Override\n            public void onChange(Dog object, ObjectChangeSet changeSet) {\n            }\n        };\n\n        try {\n            dog.removeChangeListener(listener);\n            fail(\"Failed to remove a listener from null Realm.\");\n        } catch (IllegalArgumentException ignore) {\n        }\n\n        try {\n            dog.removeChangeListener(objectChangeListener);\n            fail(\"Failed to remove a listener from null Realm.\");\n        } catch (IllegalArgumentException ignore) {\n        }\n\n        looperThread.testComplete();\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void removeAllChangeListeners_throwOnUnmanagedObject() {\n        Dog dog = new Dog();\n\n        try {\n            dog.removeAllChangeListeners();\n            fail(\"Failed to remove null listener.\");\n        } catch (IllegalArgumentException ignore) {\n            looperThread.testComplete();\n        }\n    }\n\n    // Bug https://github.com/realm/realm-java/issues/2569\n    @Test\n    @RunTestInLooperThread\n    public void addChangeListener_returnedObjectOfCopyToRealmOrUpdate() {\n        Realm realm = looperThread.getRealm();\n        realm.beginTransaction();\n        realm.createObject(AllTypesPrimaryKey.class, 1);\n\n        AllTypesPrimaryKey allTypesPrimaryKey = new AllTypesPrimaryKey();\n        allTypesPrimaryKey.setColumnLong(1);\n        allTypesPrimaryKey.setColumnFloat(0f);\n        allTypesPrimaryKey = realm.copyToRealmOrUpdate(allTypesPrimaryKey);\n        realm.commitTransaction();\n\n        looperThread.keepStrongReference(allTypesPrimaryKey);\n        allTypesPrimaryKey.addChangeListener(new RealmChangeListener<AllTypesPrimaryKey>() {\n            @Override\n            public void onChange(AllTypesPrimaryKey element) {\n                assertEquals(42.0f, element.getColumnFloat(), 0f);\n                looperThread.testComplete();\n            }\n        });\n\n        // Change the object to trigger the listener.\n        realm.beginTransaction();\n        allTypesPrimaryKey.setColumnFloat(42f);\n        realm.commitTransaction();\n    }\n\n    // step 1: findFirstAsync\n    // step 2: async query returns, change the object in the listener\n    // step 3: listener gets called again\n    @Test\n    @RunTestInLooperThread\n    public void addChangeListener_listenerShouldBeCalledIfObjectChangesAfterAsyncReturn() {\n        final AtomicInteger listenerCounter = new AtomicInteger(0);\n        final Realm realm = looperThread.getRealm();\n        realm.beginTransaction();\n        realm.createObject(AllTypesPrimaryKey.class, 1);\n        realm.commitTransaction();\n\n        // Step 1\n        final AllTypesPrimaryKey allTypesPrimaryKey = realm.where(AllTypesPrimaryKey.class).findFirstAsync();\n        looperThread.keepStrongReference(allTypesPrimaryKey);\n        allTypesPrimaryKey.addChangeListener(new RealmChangeListener<AllTypesPrimaryKey>() {\n            @Override\n            public void onChange(AllTypesPrimaryKey element) {\n                int count = listenerCounter.getAndAdd(1);\n                if (count == 0) {\n                    // Step 2\n                    realm.executeTransactionAsync(new Realm.Transaction() {\n                        @Override\n                        public void execute(Realm realm) {\n                            realm.where(AllTypesPrimaryKey.class).findFirst().setColumnFloat(42f);\n                        }\n                    });\n                } else if (count == 1) {\n                    // Step 3\n                    assertEquals(allTypesPrimaryKey.getColumnFloat(), 42f, 0);\n                    looperThread.testComplete();\n                } else {\n                    fail();\n                }\n            }\n        });\n    }\n\n    @Test\n    public void getRealm_managedRealmObject() {\n        realm.beginTransaction();\n        AllTypes object = realm.createObject(AllTypes.class);\n        realm.commitTransaction();\n\n        assertSame(realm, object.getRealm());\n        assertSame(realm, RealmObject.getRealm(object));\n    }\n\n    @Test\n    public void getRealm_managedRealmModel() {\n        realm.beginTransaction();\n        AllTypesRealmModel object = realm.createObject(AllTypesRealmModel.class, 1L);\n        realm.commitTransaction();\n\n        assertSame(realm, RealmObject.getRealm(object));\n    }\n\n    @Test\n    public void getRealm_DynamicRealmObject() {\n        final DynamicRealm dynamicRealm = DynamicRealm.getInstance(realmConfig);\n        //noinspection TryFinallyCanBeTryWithResources\n        try {\n            dynamicRealm.beginTransaction();\n            DynamicRealmObject object = dynamicRealm.createObject(\"AllTypesRealmModel\", 1L);\n            dynamicRealm.commitTransaction();\n\n            try {\n                object.getRealm();\n                fail();\n            } catch (IllegalStateException expected) {\n                assertEquals(RealmObject.MSG_DYNAMIC_OBJECT, expected.getMessage());\n            }\n            try {\n                RealmObject.getRealm(object);\n                fail();\n            } catch (IllegalStateException expected) {\n                assertEquals(RealmObject.MSG_DYNAMIC_OBJECT, expected.getMessage());\n            }\n        } finally {\n            dynamicRealm.close();\n        }\n    }\n\n    @Test\n    public void getRealm_unmanagedRealmObjectReturnsNull() {\n        assertNull(new AllTypes().getRealm());\n        assertNull(RealmObject.getRealm(new AllTypes()));\n    }\n\n    @Test\n    public void getRealm_unmanagedRealmModelReturnsNull() {\n        assertNull(RealmObject.getRealm(new AllTypesRealmModel()));\n    }\n\n    @Test\n    public void getRealm_null() {\n        try {\n            RealmObject.getRealm(null);\n            fail();\n        } catch (IllegalArgumentException expected) {\n            assertEquals(RealmObject.MSG_NULL_OBJECT, expected.getMessage());\n        }\n    }\n\n    @Test\n    public void getRealm_closedObjectThrows() {\n        realm.beginTransaction();\n        AllTypes object = realm.createObject(AllTypes.class);\n        realm.commitTransaction();\n\n        realm.close();\n        realm = null;\n\n        try {\n            object.getRealm();\n            fail();\n        } catch (IllegalStateException e) {\n            assertEquals(BaseRealm.CLOSED_REALM_MESSAGE, e.getMessage());\n        }\n        try {\n            RealmObject.getRealm(object);\n            fail();\n        } catch (IllegalStateException e) {\n            assertEquals(BaseRealm.CLOSED_REALM_MESSAGE, e.getMessage());\n        }\n    }\n\n    @Test\n    public void getRealmConfiguration_deletedObjectThrows() {\n        realm.beginTransaction();\n        AllTypes object = realm.createObject(AllTypes.class);\n        object.deleteFromRealm();\n        realm.commitTransaction();\n\n        try {\n            object.getRealm();\n            fail();\n        } catch (IllegalStateException e) {\n            assertEquals(RealmObject.MSG_DELETED_OBJECT, e.getMessage());\n        }\n        try {\n            RealmObject.getRealm(object);\n            fail();\n        } catch (IllegalStateException e) {\n            assertEquals(RealmObject.MSG_DELETED_OBJECT, e.getMessage());\n        }\n    }\n\n    @Test\n    public void getRealm_illegalThreadThrows() throws Throwable {\n        realm.beginTransaction();\n        final AllTypes object = realm.createObject(AllTypes.class);\n        realm.commitTransaction();\n\n        final CountDownLatch threadFinished = new CountDownLatch(1);\n        final Thread thread = new Thread(new Runnable() {\n            @Override\n            public void run() {\n                try {\n                    object.getRealm();\n                    fail();\n                } catch (IllegalStateException e) {\n                    assertEquals(BaseRealm.INCORRECT_THREAD_MESSAGE, e.getMessage());\n                }\n                try {\n                    RealmObject.getRealm(object);\n                    fail();\n                } catch (IllegalStateException e) {\n                    assertEquals(BaseRealm.INCORRECT_THREAD_MESSAGE, e.getMessage());\n                } finally {\n                    threadFinished.countDown();\n                }\n            }\n        });\n        thread.start();\n        TestHelper.awaitOrFail(threadFinished);\n    }\n\n    @Test\n    public void setter_binary_long_values() {\n        byte[] longBinary = new byte[Table.MAX_BINARY_SIZE];\n        byte[] tooLongBinary = new byte[Table.MAX_BINARY_SIZE + 1];\n\n        realm.beginTransaction();\n        AllTypes allTypes = realm.createObject(AllTypes.class);\n        allTypes.setColumnBinary(longBinary);\n        realm.commitTransaction();\n        assertEquals(longBinary.length, allTypes.getColumnBinary().length);\n\n        realm.beginTransaction();\n        try {\n            allTypes.setColumnBinary(tooLongBinary);\n            fail();\n        } catch (IllegalArgumentException expected) {\n            assertThat(expected.getMessage(), CoreMatchers.containsString(\"which exceeds the max binary size\"));\n        }\n    }\n\n    @Test\n    public void setter_string_long_values() {\n        byte[] tooLongBinary = new byte[Table.MAX_STRING_SIZE + 1];\n        Arrays.fill(tooLongBinary, (byte) 'a');\n        String longString = new String(tooLongBinary, 0, Table.MAX_STRING_SIZE, Charset.forName(\"US-ASCII\"));\n        String tooLongString = new String(tooLongBinary, 0, Table.MAX_STRING_SIZE + 1, Charset.forName(\"US-ASCII\"));\n\n        realm.beginTransaction();\n        AllTypes allTypes = realm.createObject(AllTypes.class);\n        allTypes.setColumnString(longString);\n        realm.commitTransaction();\n        assertEquals(longString.length(), allTypes.getColumnString().length());\n\n        realm.beginTransaction();\n        try {\n            allTypes.setColumnString(tooLongString);\n            fail();\n        } catch (IllegalArgumentException expected) {\n            assertThat(expected.getMessage(), CoreMatchers.containsString(\"which exceeds the max string length\"));\n        }\n    }\n\n    @Test\n    public void setter_nonLatinFieldName() {\n        // Reproduces https://github.com/realm/realm-java/pull/5346\n        realm.beginTransaction();\n        NonLatinFieldNames obj = realm.createObject(NonLatinFieldNames.class);\n        obj.setΔέλτα(42);\n        realm.commitTransaction();\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/RealmPrimaryKeyTests.java",
    "content": "/*\n * Copyright 2016 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\npackage io.realm;\n\nimport org.junit.After;\nimport org.junit.Before;\nimport org.junit.Rule;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.junit.runners.Parameterized;\n\nimport java.lang.reflect.InvocationTargetException;\nimport java.util.Arrays;\n\nimport io.realm.entities.PrimaryKeyRequiredAsBoxedByte;\nimport io.realm.entities.PrimaryKeyRequiredAsBoxedInteger;\nimport io.realm.entities.PrimaryKeyRequiredAsBoxedLong;\nimport io.realm.entities.PrimaryKeyRequiredAsBoxedShort;\nimport io.realm.entities.PrimaryKeyRequiredAsString;\nimport io.realm.objectid.NullPrimaryKey;\n\nimport static org.junit.Assert.assertEquals;\nimport static org.junit.Assert.assertTrue;\nimport static org.junit.Assert.fail;\n\n@RunWith(Parameterized.class)\npublic class RealmPrimaryKeyTests {\n    @Rule\n    public final TestRealmConfigurationFactory configFactory = new TestRealmConfigurationFactory();\n\n    protected Realm realm;\n\n    @Before\n    public void setUp() {\n        RealmConfiguration realmConfig = configFactory.createConfiguration();\n        realm = Realm.getInstance(realmConfig);\n    }\n\n    @After\n    public void tearDown() {\n        if (realm != null) {\n            realm.close();\n        }\n    }\n\n    /**\n     * Base parameters for testing null/not-null primary key value. The parameters are aligned in an\n     * order of 1) a test target class, 2) a primary key field class, 3) a primary Key value, 4) a\n     * secondary field class, and 5) a secondary field value, accommodating {@interface NullPrimaryKey}\n     * to condense unit tests.\n     */\n    @Parameterized.Parameters\n    public static Iterable<Object[]> data() {\n        return Arrays.asList(new Object[][]{\n            // 1) Test target class                  2) PK Class    3) PK value            4) 2nd Class  5) 2nd field value\n            {PrimaryKeyRequiredAsString.class,       String.class,  \"424123\",              String.class, \"SomeSecondaryValue\"},\n            {PrimaryKeyRequiredAsBoxedByte.class,    Byte.class,    Byte.valueOf(\"67\"),    String.class, \"This-Is-Second-One\"},\n            {PrimaryKeyRequiredAsBoxedShort.class,   Short.class,   Short.valueOf(\"1729\"), String.class, \"AnyValueIsAccepted\"},\n            {PrimaryKeyRequiredAsBoxedInteger.class, Integer.class, Integer.valueOf(\"19\"), String.class, \"PlayWithSeondFied!\"},\n            {PrimaryKeyRequiredAsBoxedLong.class,    Long.class,    Long.valueOf(\"62914\"), String.class, \"Let's name a value\"}\n        });\n    }\n\n    final private Class<? extends RealmObject> testClazz;\n    final private Class primaryKeyFieldType;\n    final private Object primaryKeyFieldValue;\n    final private Class secondaryFieldType;\n    final private Object secondaryFieldValue;\n\n    public RealmPrimaryKeyTests(Class<? extends RealmObject> testClazz, Class primaryKeyFieldType, Object primaryKeyFieldValue, Class secondaryFieldType, Object secondaryFieldValue) {\n        this.testClazz = testClazz;\n        this.primaryKeyFieldType = primaryKeyFieldType;\n        this.primaryKeyFieldValue = primaryKeyFieldValue;\n        this.secondaryFieldType = secondaryFieldType;\n        this.secondaryFieldValue = secondaryFieldValue;\n    }\n\n    // @PrimaryKey + @Required annotation accept not-null value properly as a primary key value for Realm version 0.89.1+.\n    @Test\n    public void copyToRealmOrUpdate_requiredPrimaryKey() throws NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException {\n        RealmObject obj = (RealmObject)testClazz.getConstructor(primaryKeyFieldType, secondaryFieldType).newInstance(primaryKeyFieldValue, secondaryFieldValue);\n        realm.beginTransaction();\n        realm.copyToRealmOrUpdate(obj);\n        realm.commitTransaction();\n\n        RealmResults results = realm.where(testClazz).findAll();\n        assertEquals(1, results.size());\n        assertEquals(primaryKeyFieldValue, ((NullPrimaryKey)results.first()).getId());\n        assertEquals(secondaryFieldValue, ((NullPrimaryKey)results.first()).getName());\n    }\n\n    // @PrimaryKey + @Required annotation does accept null as a primary key value for Realm version 0.89.1+.\n    @Test\n    public void copyToRealmOrUpdate_requiredPrimaryKeyThrows() throws NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException {\n        RealmObject obj = (RealmObject)testClazz.getConstructor(primaryKeyFieldType, secondaryFieldType).newInstance(null, null);\n\n        realm.beginTransaction();\n        try {\n            realm.copyToRealmOrUpdate(obj);\n            fail(\"@PrimaryKey + @Required field cannot be null\");\n        } catch (RuntimeException expected) {\n            if (testClazz.equals(PrimaryKeyRequiredAsString.class)) {\n                assertTrue(expected instanceof IllegalArgumentException);\n            } else {\n                assertTrue(expected instanceof NullPointerException);\n            }\n\n        } finally {\n            realm.cancelTransaction();\n        }\n    }\n\n    // @PrimaryKey + @Required annotation does not accept null as a primary key value for Realm version 0.89.1+.\n    @Test\n    public void createObject_nullPrimaryKeyValueThrows() throws NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException {\n        realm.beginTransaction();\n        try {\n            realm.createObject(testClazz, null);\n            fail(\"@PrimaryKey + @Required field cannot be null\");\n        } catch (RuntimeException expected) {\n            assertTrue(expected instanceof IllegalArgumentException);\n        } finally {\n            realm.cancelTransaction();\n        }\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/RealmProxyMediatorTests.java",
    "content": "/*\n * Copyright 2016 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 */\npackage io.realm;\n\nimport androidx.test.ext.junit.runners.AndroidJUnit4;\n\nimport org.junit.After;\nimport org.junit.Before;\nimport org.junit.Rule;\nimport org.junit.Test;\nimport org.junit.rules.ExpectedException;\nimport org.junit.runner.RunWith;\n\nimport java.lang.reflect.Field;\nimport java.lang.reflect.Modifier;\nimport java.util.HashSet;\nimport java.util.Set;\n\nimport io.realm.entities.Cat;\nimport io.realm.internal.RealmProxyMediator;\n\nimport static org.junit.Assert.assertEquals;\n\n@RunWith(AndroidJUnit4.class)\npublic class RealmProxyMediatorTests {\n    @Rule\n    public final TestRealmConfigurationFactory configFactory = new TestRealmConfigurationFactory();\n    @Rule\n    public final ExpectedException thrown = ExpectedException.none();\n\n    private Realm realm;\n\n    @Before\n    public void setUp() {\n        RealmConfiguration config = configFactory.createConfiguration();\n        realm = Realm.getInstance(config);\n    }\n\n    @After\n    public void tearDown() {\n        if (realm != null) {\n            realm.close();\n        }\n    }\n\n    @Test\n    public void createColumnInfo_noDuplicateIndexInIndexFields() {\n        RealmProxyMediator mediator = realm.getConfiguration().getSchemaMediator();\n        io_realm_entities_CatRealmProxy.CatColumnInfo columnInfo = (io_realm_entities_CatRealmProxy.CatColumnInfo) mediator.createColumnInfo(Cat.class, realm.sharedRealm.getSchemaInfo());\n\n        final Set<Long> indexSet = new HashSet<Long>();\n        int indexCount = 0;\n\n        indexSet.add(columnInfo.nameColKey);\n        indexCount++;\n        indexSet.add(columnInfo.ageColKey);\n        indexCount++;\n        indexSet.add(columnInfo.heightColKey);\n        indexCount++;\n        indexSet.add(columnInfo.weightColKey);\n        indexCount++;\n        indexSet.add(columnInfo.hasTailColKey);\n        indexCount++;\n        indexSet.add(columnInfo.birthdayColKey);\n        indexCount++;\n        indexSet.add(columnInfo.ownerColKey);\n        indexCount++;\n        indexSet.add(columnInfo.scaredOfDogColKey);\n        indexCount++;\n\n        assertEquals(indexCount, indexSet.size());\n    }\n\n    @Test\n    public void createColumnInfo_noDuplicateIndexInIndicesMap() {\n        RealmProxyMediator mediator = realm.getConfiguration().getSchemaMediator();\n        io_realm_entities_CatRealmProxy.CatColumnInfo columnInfo;\n        columnInfo = (io_realm_entities_CatRealmProxy.CatColumnInfo) mediator.createColumnInfo(Cat.class, realm.sharedRealm.getSchemaInfo());\n\n        final Set<Long> columnKeySet = new HashSet<Long>();\n        int indexCount = 0;\n\n        // Gets index for each field and then put into set.\n        for (Field field : Cat.class.getDeclaredFields()) {\n            if (Modifier.isStatic(field.getModifiers())) {\n                continue;\n            }\n            columnKeySet.add(columnInfo.getColumnKey(field.getName()));\n            indexCount++;\n        }\n\n        assertEquals(\"if no duplicates, size of set equals to field count.\",\n                indexCount, columnKeySet.size());\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/RealmQueryTests.java",
    "content": "/*\n * Copyright 2015 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\npackage io.realm;\n\nimport android.util.Log;\n\nimport org.bson.types.Decimal128;\nimport org.bson.types.ObjectId;\nimport org.jetbrains.annotations.NotNull;\nimport org.junit.Ignore;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.mockito.internal.util.collections.Sets;\n\nimport java.io.IOException;\nimport java.lang.reflect.Field;\nimport java.math.BigDecimal;\nimport java.util.AbstractMap;\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.Date;\nimport java.util.HashSet;\nimport java.util.List;\nimport java.util.Objects;\nimport java.util.Set;\nimport java.util.UUID;\nimport java.util.concurrent.CountDownLatch;\nimport java.util.concurrent.atomic.AtomicInteger;\n\nimport androidx.test.annotation.UiThreadTest;\nimport androidx.test.ext.junit.runners.AndroidJUnit4;\nimport io.realm.entities.AllJavaTypesUnsupportedTypes;\nimport io.realm.entities.AllTypes;\nimport io.realm.entities.AnnotationIndexTypes;\nimport io.realm.entities.Cat;\nimport io.realm.entities.CatOwner;\nimport io.realm.entities.DictionaryAllTypes;\nimport io.realm.entities.Dog;\nimport io.realm.entities.IndexedFields;\nimport io.realm.entities.KeywordFieldNames;\nimport io.realm.entities.NoPrimaryKeyNullTypes;\nimport io.realm.entities.NonLatinFieldNames;\nimport io.realm.entities.NullTypes;\nimport io.realm.entities.Owner;\nimport io.realm.entities.PrimaryKeyAsBoxedByte;\nimport io.realm.entities.PrimaryKeyAsBoxedInteger;\nimport io.realm.entities.PrimaryKeyAsBoxedLong;\nimport io.realm.entities.PrimaryKeyAsBoxedShort;\nimport io.realm.entities.PrimaryKeyAsString;\nimport io.realm.entities.StringOnly;\nimport io.realm.entities.embedded.EmbeddedSimpleChild;\nimport io.realm.entities.embedded.EmbeddedSimpleParent;\nimport io.realm.entities.realmname.ClassWithValueDefinedNames;\nimport io.realm.exceptions.RealmException;\nimport io.realm.log.RealmLog;\nimport io.realm.rule.RunTestInLooperThread;\n\nimport static org.junit.Assert.assertEquals;\nimport static org.junit.Assert.assertFalse;\nimport static org.junit.Assert.assertNotEquals;\nimport static org.junit.Assert.assertNotNull;\nimport static org.junit.Assert.assertNull;\nimport static org.junit.Assert.assertTrue;\nimport static org.junit.Assert.fail;\n\n\n@RunWith(AndroidJUnit4.class)\npublic class RealmQueryTests extends QueryTests {\n    private void populateTestRealm(Realm testRealm, int dataSize) {\n        testRealm.beginTransaction();\n        testRealm.deleteAll();\n        for (int i = 0; i < dataSize; ++i) {\n            AllTypes allTypes = testRealm.createObject(AllTypes.class);\n            allTypes.setColumnBoolean((i % 3) == 0);\n            allTypes.setColumnBinary(new byte[] {1, 2, 3});\n            allTypes.setColumnDate(new Date(DECADE_MILLIS * (i - (dataSize / 2))));\n            allTypes.setColumnDouble(Math.PI);\n            allTypes.setColumnFloat(1.2345f + i);\n            allTypes.setColumnString(\"test data \" + i);\n            allTypes.setColumnLong(i);\n            allTypes.setColumnObjectId(new ObjectId(TestHelper.generateObjectIdHexString(i)));\n            allTypes.setColumnDecimal128(new Decimal128(new BigDecimal(i + \".23456789\")));\n            allTypes.setColumnUUID(UUID.fromString(TestHelper.generateUUIDString(i)));\n            allTypes.setColumnRealmAny(RealmAny.valueOf(i));\n\n            NonLatinFieldNames nonLatinFieldNames = testRealm.createObject(NonLatinFieldNames.class);\n            nonLatinFieldNames.set델타(i);\n            nonLatinFieldNames.setΔέλτα(i);\n            nonLatinFieldNames.set베타(1.2345f + i);\n            nonLatinFieldNames.setΒήτα(1.2345f + i);\n\n            Dog dog = testRealm.createObject(Dog.class);\n            dog.setAge(i);\n            dog.setName(\"test data \" + i);\n            allTypes.setColumnRealmObject(dog);\n        }\n        testRealm.commitTransaction();\n    }\n\n    private void populateTestRealm() {\n        populateTestRealm(realm, TEST_DATA_SIZE);\n    }\n\n    private void populateNoPrimaryKeyNullTypesRows(Realm testRealm, int dataSize) {\n        testRealm.beginTransaction();\n        testRealm.deleteAll();\n        for (int i = 0; i < dataSize; ++i) {\n            NoPrimaryKeyNullTypes noPrimaryKeyNullTypes = testRealm.createObject(NoPrimaryKeyNullTypes.class);\n            noPrimaryKeyNullTypes.setFieldStringNull((i % 3) == 0 ? null : \"test data \" + i);\n            noPrimaryKeyNullTypes.setFieldStringNotNull(\"test data \" + i);\n            noPrimaryKeyNullTypes.setFieldBooleanNull((i % 3) == 0 ? null : (i % 3) == 1);\n            noPrimaryKeyNullTypes.setFieldBooleanNotNull((i % 3) == 0);\n            noPrimaryKeyNullTypes.setFieldByteNull((i % 3) == 0 ? null : (byte) i);\n            noPrimaryKeyNullTypes.setFieldByteNotNull((byte) i);\n            noPrimaryKeyNullTypes.setFieldShortNull((i % 3) == 0 ? null : (short) i);\n            noPrimaryKeyNullTypes.setFieldShortNotNull((short) i);\n            noPrimaryKeyNullTypes.setFieldIntegerNull((i % 3) == 0 ? null : i);\n            noPrimaryKeyNullTypes.setFieldIntegerNotNull(i);\n            noPrimaryKeyNullTypes.setFieldLongNull((i % 3) == 0 ? null : (long) i);\n            noPrimaryKeyNullTypes.setFieldLongNotNull((long) i);\n            noPrimaryKeyNullTypes.setFieldFloatNull((i % 3) == 0 ? null : 1.2345f + i);\n            noPrimaryKeyNullTypes.setFieldFloatNotNull(1.2345f + i);\n            noPrimaryKeyNullTypes.setFieldDoubleNull((i % 3) == 0 ? null : Math.PI + i);\n            noPrimaryKeyNullTypes.setFieldDoubleNotNull(Math.PI + i);\n            noPrimaryKeyNullTypes.setFieldDateNull((i % 3) == 0 ? null : new Date(DECADE_MILLIS * (i - (dataSize / 2))));\n            noPrimaryKeyNullTypes.setFieldDateNotNull(new Date(DECADE_MILLIS * (i - (dataSize / 2))));\n        }\n        testRealm.commitTransaction();\n    }\n\n    private void populateNoPrimaryKeyNullTypesRows() {\n        populateNoPrimaryKeyNullTypesRows(realm, TEST_NO_PRIMARY_KEY_NULL_TYPES_SIZE);\n    }\n\n    private enum ThreadConfinedMethods {\n        EQUAL_TO_STRING,\n        EQUAL_TO_STRING_WITH_CASE,\n        EQUAL_TO_BYTE,\n        EQUAL_TO_BYTE_ARRAY,\n        EQUAL_TO_SHORT,\n        EQUAL_TO_INTEGER,\n        EQUAL_TO_LONG,\n        EQUAL_TO_DOUBLE,\n        EQUAL_TO_FLOAT,\n        EQUAL_TO_BOOLEAN,\n        EQUAL_TO_DATE,\n\n        IN_STRING,\n        IN_STRING_WITH_CASE,\n        IN_BYTE,\n        IN_SHORT,\n        IN_INTEGER,\n        IN_LONG,\n        IN_DOUBLE,\n        IN_FLOAT,\n        IN_BOOLEAN,\n        IN_DATE,\n\n        NOT_EQUAL_TO_STRING,\n        NOT_EQUAL_TO_STRING_WITH_CASE,\n        NOT_EQUAL_TO_BYTE,\n        NOT_EQUAL_TO_BYTE_ARRAY,\n        NOT_EQUAL_TO_SHORT,\n        NOT_EQUAL_TO_INTEGER,\n        NOT_EQUAL_TO_LONG,\n        NOT_EQUAL_TO_DOUBLE,\n        NOT_EQUAL_TO_FLOAT,\n        NOT_EQUAL_TO_BOOLEAN,\n        NOT_EQUAL_TO_DATE,\n\n        GREATER_THAN_INTEGER,\n        GREATER_THAN_LONG,\n        GREATER_THAN_DOUBLE,\n        GREATER_THAN_FLOAT,\n        GREATER_THAN_DATE,\n\n        GREATER_THAN_OR_EQUAL_TO_INTEGER,\n        GREATER_THAN_OR_EQUAL_TO_LONG,\n        GREATER_THAN_OR_EQUAL_TO_DOUBLE,\n        GREATER_THAN_OR_EQUAL_TO_FLOAT,\n        GREATER_THAN_OR_EQUAL_TO_DATE,\n\n        LESS_THAN_INTEGER,\n        LESS_THAN_LONG,\n        LESS_THAN_DOUBLE,\n        LESS_THAN_FLOAT,\n        LESS_THAN_DATE,\n\n        LESS_THAN_OR_EQUAL_TO_INTEGER,\n        LESS_THAN_OR_EQUAL_TO_LONG,\n        LESS_THAN_OR_EQUAL_TO_DOUBLE,\n        LESS_THAN_OR_EQUAL_TO_FLOAT,\n        LESS_THAN_OR_EQUAL_TO_DATE,\n\n        BETWEEN_INTEGER,\n        BETWEEN_LONG,\n        BETWEEN_DOUBLE,\n        BETWEEN_FLOAT,\n        BETWEEN_DATE,\n\n        CONTAINS_STRING,\n        CONTAINS_STRING_WITH_CASE,\n\n        BEGINS_WITH_STRING,\n        BEGINS_WITH_STRING_WITH_CASE,\n\n        ENDS_WITH_STRING,\n        ENDS_WITH_STRING_WITH_CASE,\n\n        LIKE_STRING,\n        LIKE_STRING_WITH_CASE,\n\n        BEGIN_GROUP,\n        END_GROUP,\n        OR,\n        AND,\n        NOT,\n        IS_NULL,\n        IS_NOT_NULL,\n        IS_EMPTY,\n        IS_NOT_EMPTY,\n\n        IS_VALID,\n        DISTINCT,\n        DISTINCT_BY_MULTIPLE_FIELDS,\n\n        SUM,\n        AVERAGE,\n        MIN,\n        MINIMUM_DATE,\n        MAX,\n        MAXIMUM_DATE,\n        COUNT,\n\n        FIND_ALL,\n        FIND_ALL_ASYNC,\n        SORT,\n        SORT_WITH_ORDER,\n        SORT_WITH_MANY_ORDERS,\n\n        FIND_FIRST,\n        FIND_FIRST_ASYNC,\n\n        CONTAINS_KEY,\n        CONTAINS_VALUE,\n        CONTAINS_ENTRY,\n    }\n\n    private static void callThreadConfinedMethod(RealmQuery<?> query, ThreadConfinedMethods method) {\n        switch (method) {\n            case EQUAL_TO_STRING: query.equalTo(           AllJavaTypesUnsupportedTypes.FIELD_STRING,  \"dummy value\"); break;\n            case EQUAL_TO_STRING_WITH_CASE: query.equalTo( AllJavaTypesUnsupportedTypes.FIELD_STRING,  \"dummy value\", Case.INSENSITIVE); break;\n            case EQUAL_TO_BYTE: query.equalTo(             AllJavaTypesUnsupportedTypes.FIELD_BYTE,    (byte) 1); break;\n            case EQUAL_TO_BYTE_ARRAY: query.equalTo(       AllJavaTypesUnsupportedTypes.FIELD_BINARY,  new byte[] {0, 1, 2}); break;\n            case EQUAL_TO_SHORT: query.equalTo(            AllJavaTypesUnsupportedTypes.FIELD_SHORT,   (short) 1); break;\n            case EQUAL_TO_INTEGER: query.equalTo(          AllJavaTypesUnsupportedTypes.FIELD_INT,     1); break;\n            case EQUAL_TO_LONG: query.equalTo(             AllJavaTypesUnsupportedTypes.FIELD_LONG,    1L); break;\n            case EQUAL_TO_DOUBLE: query.equalTo(           AllJavaTypesUnsupportedTypes.FIELD_DOUBLE,  1D); break;\n            case EQUAL_TO_FLOAT: query.equalTo(            AllJavaTypesUnsupportedTypes.FIELD_FLOAT,   1F); break;\n            case EQUAL_TO_BOOLEAN: query.equalTo(          AllJavaTypesUnsupportedTypes.FIELD_BOOLEAN, true); break;\n            case EQUAL_TO_DATE: query.equalTo(             AllJavaTypesUnsupportedTypes.FIELD_DATE,    new Date(0L)); break;\n\n            case IN_STRING: query.in(           AllJavaTypesUnsupportedTypes.FIELD_STRING,  new String[] {\"dummy value1\", \"dummy value2\"}); break;\n            case IN_STRING_WITH_CASE: query.in( AllJavaTypesUnsupportedTypes.FIELD_STRING,  new String[] {\"dummy value1\", \"dummy value2\"}, Case.INSENSITIVE); break;\n            case IN_BYTE: query.in(             AllJavaTypesUnsupportedTypes.FIELD_BYTE,    new Byte[] {1, 2, 3}); break;\n            case IN_SHORT: query.in(            AllJavaTypesUnsupportedTypes.FIELD_SHORT,   new Short[] {1, 2, 3}); break;\n            case IN_INTEGER: query.in(          AllJavaTypesUnsupportedTypes.FIELD_INT,     new Integer[] {1, 2, 3}); break;\n            case IN_LONG: query.in(             AllJavaTypesUnsupportedTypes.FIELD_LONG,    new Long[] {1L, 2L, 3L}); break;\n            case IN_DOUBLE: query.in(           AllJavaTypesUnsupportedTypes.FIELD_DOUBLE,  new Double[] {1D, 2D, 3D}); break;\n            case IN_FLOAT: query.in(            AllJavaTypesUnsupportedTypes.FIELD_FLOAT,   new Float[] {1F, 2F, 3F}); break;\n            case IN_BOOLEAN: query.in(          AllJavaTypesUnsupportedTypes.FIELD_BOOLEAN, new Boolean[] {true, false}); break;\n            case IN_DATE: query.in(             AllJavaTypesUnsupportedTypes.FIELD_DATE,    new Date[] {new Date(0L)}); break;\n\n            case NOT_EQUAL_TO_STRING: query.notEqualTo(           AllJavaTypesUnsupportedTypes.FIELD_STRING,  \"dummy value\"); break;\n            case NOT_EQUAL_TO_STRING_WITH_CASE: query.notEqualTo( AllJavaTypesUnsupportedTypes.FIELD_STRING,  \"dummy value\", Case.INSENSITIVE); break;\n            case NOT_EQUAL_TO_BYTE: query.notEqualTo(             AllJavaTypesUnsupportedTypes.FIELD_BYTE,    (byte) 1); break;\n            case NOT_EQUAL_TO_BYTE_ARRAY: query.notEqualTo(       AllJavaTypesUnsupportedTypes.FIELD_BINARY,  new byte[] {1,2,3}); break;\n            case NOT_EQUAL_TO_SHORT: query.notEqualTo(            AllJavaTypesUnsupportedTypes.FIELD_SHORT,   (short) 1); break;\n            case NOT_EQUAL_TO_INTEGER: query.notEqualTo(          AllJavaTypesUnsupportedTypes.FIELD_INT,     1); break;\n            case NOT_EQUAL_TO_LONG: query.notEqualTo(             AllJavaTypesUnsupportedTypes.FIELD_LONG,    1L); break;\n            case NOT_EQUAL_TO_DOUBLE: query.notEqualTo(           AllJavaTypesUnsupportedTypes.FIELD_DOUBLE,  1D); break;\n            case NOT_EQUAL_TO_FLOAT: query.notEqualTo(            AllJavaTypesUnsupportedTypes.FIELD_FLOAT,   1F); break;\n            case NOT_EQUAL_TO_BOOLEAN: query.notEqualTo(          AllJavaTypesUnsupportedTypes.FIELD_BOOLEAN, true); break;\n            case NOT_EQUAL_TO_DATE: query.notEqualTo(             AllJavaTypesUnsupportedTypes.FIELD_DATE,    new Date(0L)); break;\n\n            case GREATER_THAN_INTEGER: query.greaterThan( AllJavaTypesUnsupportedTypes.FIELD_INT,    1); break;\n            case GREATER_THAN_LONG: query.greaterThan(    AllJavaTypesUnsupportedTypes.FIELD_LONG,   1L); break;\n            case GREATER_THAN_DOUBLE: query.greaterThan(  AllJavaTypesUnsupportedTypes.FIELD_DOUBLE, 1D); break;\n            case GREATER_THAN_FLOAT: query.greaterThan(   AllJavaTypesUnsupportedTypes.FIELD_FLOAT,  1F); break;\n            case GREATER_THAN_DATE: query.greaterThan(    AllJavaTypesUnsupportedTypes.FIELD_DATE,   new Date(0L)); break;\n\n            case GREATER_THAN_OR_EQUAL_TO_INTEGER: query.greaterThanOrEqualTo( AllJavaTypesUnsupportedTypes.FIELD_INT,    1); break;\n            case GREATER_THAN_OR_EQUAL_TO_LONG: query.greaterThanOrEqualTo(    AllJavaTypesUnsupportedTypes.FIELD_LONG,   1L); break;\n            case GREATER_THAN_OR_EQUAL_TO_DOUBLE: query.greaterThanOrEqualTo(  AllJavaTypesUnsupportedTypes.FIELD_DOUBLE, 1D); break;\n            case GREATER_THAN_OR_EQUAL_TO_FLOAT: query.greaterThanOrEqualTo(   AllJavaTypesUnsupportedTypes.FIELD_FLOAT,  1F); break;\n            case GREATER_THAN_OR_EQUAL_TO_DATE: query.greaterThanOrEqualTo(    AllJavaTypesUnsupportedTypes.FIELD_DATE,   new Date(0L)); break;\n\n            case LESS_THAN_INTEGER: query.lessThan( AllJavaTypesUnsupportedTypes.FIELD_INT,    1); break;\n            case LESS_THAN_LONG: query.lessThan(    AllJavaTypesUnsupportedTypes.FIELD_LONG,   1L); break;\n            case LESS_THAN_DOUBLE: query.lessThan(  AllJavaTypesUnsupportedTypes.FIELD_DOUBLE, 1D); break;\n            case LESS_THAN_FLOAT: query.lessThan(   AllJavaTypesUnsupportedTypes.FIELD_FLOAT,  1F); break;\n            case LESS_THAN_DATE: query.lessThan(    AllJavaTypesUnsupportedTypes.FIELD_DATE,   new Date(0L)); break;\n\n            case LESS_THAN_OR_EQUAL_TO_INTEGER: query.lessThanOrEqualTo( AllJavaTypesUnsupportedTypes.FIELD_INT,    1); break;\n            case LESS_THAN_OR_EQUAL_TO_LONG: query.lessThanOrEqualTo(    AllJavaTypesUnsupportedTypes.FIELD_LONG,   1L); break;\n            case LESS_THAN_OR_EQUAL_TO_DOUBLE: query.lessThanOrEqualTo(  AllJavaTypesUnsupportedTypes.FIELD_DOUBLE, 1D); break;\n            case LESS_THAN_OR_EQUAL_TO_FLOAT: query.lessThanOrEqualTo(   AllJavaTypesUnsupportedTypes.FIELD_FLOAT,  1F); break;\n            case LESS_THAN_OR_EQUAL_TO_DATE: query.lessThanOrEqualTo(    AllJavaTypesUnsupportedTypes.FIELD_DATE,   new Date(0L)); break;\n\n            case BETWEEN_INTEGER: query.between( AllJavaTypesUnsupportedTypes.FIELD_INT,    1, 100); break;\n            case BETWEEN_LONG: query.between(    AllJavaTypesUnsupportedTypes.FIELD_LONG,   1L, 100L); break;\n            case BETWEEN_DOUBLE: query.between(  AllJavaTypesUnsupportedTypes.FIELD_DOUBLE, 1D, 100D); break;\n            case BETWEEN_FLOAT: query.between(   AllJavaTypesUnsupportedTypes.FIELD_FLOAT,  1F, 100F); break;\n            case BETWEEN_DATE: query.between(    AllJavaTypesUnsupportedTypes.FIELD_DATE,   new Date(0L), new Date(10000L)); break;\n\n            case CONTAINS_STRING: query.contains(           AllJavaTypesUnsupportedTypes.FIELD_STRING, \"dummy value\"); break;\n            case CONTAINS_STRING_WITH_CASE: query.contains( AllJavaTypesUnsupportedTypes.FIELD_STRING, \"dummy value\", Case.INSENSITIVE); break;\n\n            case BEGINS_WITH_STRING: query.beginsWith(           AllJavaTypesUnsupportedTypes.FIELD_STRING, \"dummy value\"); break;\n            case BEGINS_WITH_STRING_WITH_CASE: query.beginsWith( AllJavaTypesUnsupportedTypes.FIELD_STRING, \"dummy value\", Case.INSENSITIVE); break;\n\n            case ENDS_WITH_STRING: query.endsWith(           AllJavaTypesUnsupportedTypes.FIELD_STRING, \"dummy value\"); break;\n            case ENDS_WITH_STRING_WITH_CASE: query.endsWith( AllJavaTypesUnsupportedTypes.FIELD_STRING, \"dummy value\", Case.INSENSITIVE); break;\n\n            case LIKE_STRING: query.like(           AllJavaTypesUnsupportedTypes.FIELD_STRING, \"dummy value\"); break;\n            case LIKE_STRING_WITH_CASE: query.like( AllJavaTypesUnsupportedTypes.FIELD_STRING, \"dummy value\", Case.INSENSITIVE); break;\n\n            case BEGIN_GROUP: query.beginGroup(); break;\n            case END_GROUP: query.endGroup(); break;\n            case OR: query.or(); break;\n            case AND: query.and(); break;\n            case NOT: query.not(); break;\n            case IS_NULL: query.isNull(          AllJavaTypesUnsupportedTypes.FIELD_DATE); break;\n            case IS_NOT_NULL: query.isNotNull(   AllJavaTypesUnsupportedTypes.FIELD_DATE); break;\n            case IS_EMPTY: query.isEmpty(        AllJavaTypesUnsupportedTypes.FIELD_STRING); break;\n            case IS_NOT_EMPTY: query.isNotEmpty( AllJavaTypesUnsupportedTypes.FIELD_STRING); break;\n\n            case IS_VALID: query.isValid(); break;\n            case DISTINCT: query.distinct(                    AllJavaTypesUnsupportedTypes.FIELD_STRING); break;\n            case DISTINCT_BY_MULTIPLE_FIELDS: query.distinct( AllJavaTypesUnsupportedTypes.FIELD_STRING, AllJavaTypesUnsupportedTypes.FIELD_ID); break;\n\n            case SUM: query.sum(                  AllJavaTypesUnsupportedTypes.FIELD_INT); break;\n            case AVERAGE: query.average(          AllJavaTypesUnsupportedTypes.FIELD_INT); break;\n            case MIN: query.min(                  AllJavaTypesUnsupportedTypes.FIELD_INT); break;\n            case MINIMUM_DATE: query.minimumDate( AllJavaTypesUnsupportedTypes.FIELD_INT); break;\n            case MAX: query.max(                  AllJavaTypesUnsupportedTypes.FIELD_INT); break;\n            case MAXIMUM_DATE: query.maximumDate( AllJavaTypesUnsupportedTypes.FIELD_INT); break;\n            case COUNT: query.count(); break;\n\n            case FIND_ALL: query.findAll(); break;\n            case FIND_ALL_ASYNC: query.findAllAsync(); break;\n            case SORT: query.sort(AllJavaTypesUnsupportedTypes.FIELD_STRING); break;\n            case SORT_WITH_ORDER: query.sort(AllJavaTypesUnsupportedTypes.FIELD_STRING, Sort.ASCENDING); break;\n            case SORT_WITH_MANY_ORDERS: query.sort(new String[] {AllJavaTypesUnsupportedTypes.FIELD_STRING, AllJavaTypesUnsupportedTypes.FIELD_ID}, new Sort[] {Sort.DESCENDING, Sort.DESCENDING}); break;\n            case FIND_FIRST: query.findFirst(); break;\n            case FIND_FIRST_ASYNC: query.findFirstAsync(); break;\n\n            case CONTAINS_KEY: query.containsKey(AllJavaTypesUnsupportedTypes.FIELD_STRING, null); break;\n            case CONTAINS_VALUE: query.containsValue(AllJavaTypesUnsupportedTypes.FIELD_STRING, (String) null); break;\n            case CONTAINS_ENTRY: query.containsEntry(AllJavaTypesUnsupportedTypes.FIELD_STRING, new AbstractMap.SimpleImmutableEntry<>(null, null)); break;\n\n            default:\n                throw new AssertionError(\"missing case for \" + method);\n        }\n    }\n\n    // The purpose of this test case is to catch when insert supports objects containing dictionaries,\n    // to then we can use AllJavaTypes instead of AllJavaTypesUnsupportedTypes.\n    // See: https://github.com/realm/realm-java/issues/7435\n    @Test(expected = IllegalStateException.class)\n    public void catchInsertSupportsDictionaries(){\n        DictionaryAllTypes dictionaryAllTypes = new DictionaryAllTypes();\n        realm.insert(dictionaryAllTypes);\n    }\n\n    // The purpose of this test case is to catch when insert supports objects containing dictionaries,\n    // to then we can use AllJavaTypes instead of AllJavaTypesUnsupportedTypes.\n    // See: https://github.com/realm/realm-java/issues/7435\n    @Test(expected = IllegalStateException.class)\n    public void catchInsertOrUpdateSupportsDictionaries(){\n        DictionaryAllTypes dictionaryAllTypes = new DictionaryAllTypes();\n        realm.insertOrUpdate(dictionaryAllTypes);\n    }\n\n    @Test\n    public void callThreadConfinedMethodsFromWrongThread() throws Throwable {\n        final RealmQuery<AllJavaTypesUnsupportedTypes> query = realm.where(AllJavaTypesUnsupportedTypes.class);\n\n        final CountDownLatch testFinished = new CountDownLatch(1);\n\n        final String expectedMessage;\n        //noinspection TryWithIdenticalCatches\n        try {\n            final Field expectedMessageField = BaseRealm.class.getDeclaredField(\"INCORRECT_THREAD_MESSAGE\");\n            expectedMessageField.setAccessible(true);\n            expectedMessage = (String) expectedMessageField.get(null);\n        } catch (NoSuchFieldException e) {\n            throw new AssertionError(e);\n        } catch (IllegalAccessException e) {\n            throw new AssertionError(e);\n        }\n\n        final Thread thread = new Thread(\"callThreadConfinedMethodsFromWrongThread\") {\n            @Override\n            public void run() {\n                try {\n                    for (ThreadConfinedMethods method : ThreadConfinedMethods.values()) {\n                        try {\n                            callThreadConfinedMethod(query, method);\n                            fail(\"IllegalStateException must be thrown.\");\n                        } catch (IllegalStateException e) {\n                            assertEquals(expectedMessage, e.getMessage());\n                        }\n                    }\n                } finally {\n                    testFinished.countDown();\n                }\n            }\n        };\n        thread.start();\n\n        TestHelper.awaitOrFail(testFinished);\n    }\n\n    @Test\n    public void between() {\n        final int TEST_OBJECTS_COUNT = 200;\n        populateTestRealm(realm, TEST_OBJECTS_COUNT);\n\n        RealmResults<AllTypes> resultList = realm.where(AllTypes.class)\n                .between(AllTypes.FIELD_LONG, 0, 9).findAll();\n        assertEquals(10, resultList.size());\n\n        resultList = realm.where(AllTypes.class).beginsWith(AllTypes.FIELD_STRING, \"test data \").findAll();\n        assertEquals(TEST_OBJECTS_COUNT, resultList.size());\n\n        resultList = realm.where(AllTypes.class).beginsWith(AllTypes.FIELD_STRING, \"test data 1\")\n                .between(AllTypes.FIELD_LONG, 2, 20).findAll();\n        assertEquals(10, resultList.size());\n\n        resultList = realm.where(AllTypes.class).between(AllTypes.FIELD_LONG, 2, 20)\n                .beginsWith(AllTypes.FIELD_STRING, \"test data 1\").findAll();\n        assertEquals(10, resultList.size());\n\n        assertEquals(51, realm.where(AllTypes.class).between(AllTypes.FIELD_DATE,\n                new Date(0),\n                new Date(DECADE_MILLIS * 50)).count());\n    }\n\n    @Test\n    public void greaterThan() {\n        final int TEST_OBJECTS_COUNT = 200;\n        populateTestRealm(realm, TEST_OBJECTS_COUNT);\n\n        RealmResults<AllTypes> resultList = realm.where(AllTypes.class)\n                .greaterThan(AllTypes.FIELD_FLOAT, 10.2345f).findAll();\n        assertEquals(TEST_OBJECTS_COUNT - 10, resultList.size());\n\n        resultList = realm.where(AllTypes.class).beginsWith(AllTypes.FIELD_STRING, \"test data 1\")\n                .greaterThan(AllTypes.FIELD_FLOAT, 150.2345f).findAll();\n        assertEquals(TEST_OBJECTS_COUNT - 150, resultList.size());\n\n        RealmQuery<AllTypes> query = realm.where(AllTypes.class).greaterThan(AllTypes.FIELD_FLOAT, 11.2345f);\n        resultList = query.between(AllTypes.FIELD_LONG, 1, 20).findAll();\n        assertEquals(10, resultList.size());\n    }\n\n    @Test\n    public void greaterThan_date() {\n        final int TEST_OBJECTS_COUNT = 200;\n        populateTestRealm(realm, TEST_OBJECTS_COUNT);\n\n        RealmResults<AllTypes> resultList;\n        resultList = realm.where(AllTypes.class).greaterThan(AllTypes.FIELD_DATE, new Date(Long.MIN_VALUE)).findAll();\n        assertEquals(TEST_OBJECTS_COUNT, resultList.size());\n        resultList = realm.where(AllTypes.class).greaterThan(AllTypes.FIELD_DATE, new Date(DECADE_MILLIS * -80)).findAll();\n        assertEquals(179, resultList.size());\n        resultList = realm.where(AllTypes.class).greaterThan(AllTypes.FIELD_DATE, new Date(0)).findAll();\n        assertEquals(TEST_OBJECTS_COUNT / 2 - 1, resultList.size());\n        resultList = realm.where(AllTypes.class).greaterThan(AllTypes.FIELD_DATE, new Date(DECADE_MILLIS * 80)).findAll();\n        assertEquals(19, resultList.size());\n        resultList = realm.where(AllTypes.class).greaterThan(AllTypes.FIELD_DATE, new Date(Long.MAX_VALUE)).findAll();\n        assertEquals(0, resultList.size());\n    }\n\n\n    @Test\n    public void greaterThanOrEqualTo() {\n        final int TEST_OBJECTS_COUNT = 200;\n        populateTestRealm(realm, TEST_OBJECTS_COUNT);\n\n        RealmResults<AllTypes> resultList = realm.where(AllTypes.class)\n                .greaterThanOrEqualTo(AllTypes.FIELD_FLOAT, 10.2345f).findAll();\n        assertEquals(TEST_OBJECTS_COUNT - 9, resultList.size());\n\n        resultList = realm.where(AllTypes.class).beginsWith(AllTypes.FIELD_STRING, \"test data 1\")\n                .greaterThanOrEqualTo(AllTypes.FIELD_FLOAT, 50.2345f).findAll();\n        assertEquals(TEST_OBJECTS_COUNT - 100, resultList.size());\n\n        RealmQuery<AllTypes> query = realm.where(AllTypes.class)\n                .greaterThanOrEqualTo(AllTypes.FIELD_FLOAT, 11.2345f);\n        query = query.between(AllTypes.FIELD_LONG, 1, 20);\n\n        resultList = query.beginsWith(AllTypes.FIELD_STRING, \"test data 15\").findAll();\n        assertEquals(1, resultList.size());\n    }\n\n    @Test\n    public void greaterThanOrEqualTo_date() {\n        final int TEST_OBJECTS_COUNT = 200;\n        populateTestRealm(realm, TEST_OBJECTS_COUNT);\n\n        RealmResults<AllTypes> resultList;\n        resultList = realm.where(AllTypes.class).greaterThanOrEqualTo(AllTypes.FIELD_DATE, new Date(Long.MIN_VALUE)).findAll();\n        assertEquals(TEST_OBJECTS_COUNT, resultList.size());\n        resultList = realm.where(AllTypes.class).greaterThanOrEqualTo(AllTypes.FIELD_DATE, new Date(DECADE_MILLIS * -80)).findAll();\n        assertEquals(180, resultList.size());\n        resultList = realm.where(AllTypes.class).greaterThanOrEqualTo(AllTypes.FIELD_DATE, new Date(0)).findAll();\n        assertEquals(TEST_OBJECTS_COUNT / 2, resultList.size());\n        resultList = realm.where(AllTypes.class).greaterThanOrEqualTo(AllTypes.FIELD_DATE, new Date(DECADE_MILLIS * 80)).findAll();\n        assertEquals(20, resultList.size());\n        resultList = realm.where(AllTypes.class).greaterThanOrEqualTo(AllTypes.FIELD_DATE, new Date(Long.MAX_VALUE)).findAll();\n        assertEquals(0, resultList.size());\n    }\n\n    @Test\n    public void or() {\n        populateTestRealm(realm, 200);\n\n        RealmQuery<AllTypes> query = realm.where(AllTypes.class).equalTo(AllTypes.FIELD_FLOAT, 31.2345f);\n        RealmResults<AllTypes> resultList = query.or().between(AllTypes.FIELD_LONG, 1, 20).findAll();\n        assertEquals(21, resultList.size());\n\n        resultList = query.or().equalTo(AllTypes.FIELD_STRING, \"test data 15\").findAll();\n        assertEquals(21, resultList.size());\n\n        resultList = query.or().equalTo(AllTypes.FIELD_STRING, \"test data 117\").findAll();\n        assertEquals(22, resultList.size());\n    }\n\n    @Test(expected = UnsupportedOperationException.class)\n    public void or_missingFilters() {\n        realm.where(AllTypes.class).or().findAll();\n    }\n\n    @Test(expected = UnsupportedOperationException.class)\n    public void or_missingFilterBefore() {\n        realm.where(AllTypes.class).or().equalTo(AllTypes.FIELD_FLOAT, 31.2345f).findAll();\n    }\n\n    @Test(expected = UnsupportedOperationException.class)\n    public void or_missingFilterAfter() {\n        realm.where(AllTypes.class).equalTo(AllTypes.FIELD_FLOAT, 31.2345f).or().findAll();\n    }\n\n    @Test\n    public void not() {\n        populateTestRealm(); // create TEST_DATA_SIZE objects\n\n        // Only one object with value 5 -> TEST_DATA_SIZE-1 object with value \"not 5\".\n        RealmResults<AllTypes> list1 = realm.where(AllTypes.class).not().equalTo(AllTypes.FIELD_LONG, 5).findAll();\n        assertEquals(TEST_DATA_SIZE - 1, list1.size());\n\n        // not().greater() and lessThenOrEqual() must be the same.\n        RealmResults<AllTypes> list2 = realm.where(AllTypes.class).not().greaterThan(AllTypes.FIELD_LONG, 5).findAll();\n        RealmResults<AllTypes> list3 = realm.where(AllTypes.class).lessThanOrEqualTo(AllTypes.FIELD_LONG, 5).findAll();\n        assertEquals(list2.size(), list3.size());\n        for (int i = 0; i < list2.size(); i++) {\n            assertEquals(list2.get(i).getColumnLong(), list3.get(i).getColumnLong());\n        }\n\n        // excepted result: 0, 1, 2, 5\n        long expected[] = {0, 1, 2, 5};\n        RealmResults<AllTypes> list4 = realm.where(AllTypes.class)\n                .equalTo(AllTypes.FIELD_LONG, 5)\n                .or()\n                .not().beginGroup()\n                .greaterThan(AllTypes.FIELD_LONG, 2)\n                .endGroup()\n                .findAll();\n        assertEquals(4, list4.size());\n        for (int i = 0; i < list4.size(); i++) {\n            assertEquals(expected[i], list4.get(i).getColumnLong());\n        }\n    }\n\n    @Test(expected = UnsupportedOperationException.class)\n    public void not_aloneThrows() {\n        // a not() alone must fail\n        realm.where(AllTypes.class).not().findAll();\n    }\n\n    @Test\n    public void and_implicit() {\n        populateTestRealm(realm, 200);\n\n        RealmQuery<AllTypes> query = realm.where(AllTypes.class).equalTo(AllTypes.FIELD_FLOAT, 31.2345f);\n        RealmResults<AllTypes> resultList = query.between(AllTypes.FIELD_LONG, 1, 10).findAll();\n        assertEquals(0, resultList.size());\n\n        query = realm.where(AllTypes.class).equalTo(AllTypes.FIELD_FLOAT, 81.2345f);\n        resultList = query.between(AllTypes.FIELD_LONG, 1, 100).findAll();\n        assertEquals(1, resultList.size());\n    }\n\n    @Test\n    public void and_explicit() {\n        populateTestRealm(realm, 200);\n\n        RealmQuery<AllTypes> query = realm.where(AllTypes.class).equalTo(AllTypes.FIELD_FLOAT, 31.2345f);\n        RealmResults<AllTypes> resultList = query.and().between(AllTypes.FIELD_LONG, 1, 10).findAll();\n        assertEquals(0, resultList.size());\n\n        query = realm.where(AllTypes.class).equalTo(AllTypes.FIELD_FLOAT, 81.2345f);\n        resultList = query.and().between(AllTypes.FIELD_LONG, 1, 100).findAll();\n        assertEquals(1, resultList.size());\n    }\n\n    @Test\n    public void lessThan() {\n        final int TEST_OBJECTS_COUNT = 200;\n        populateTestRealm(realm, TEST_OBJECTS_COUNT);\n\n        RealmResults<AllTypes> resultList = realm.where(AllTypes.class).\n                lessThan(AllTypes.FIELD_FLOAT, 31.2345f).findAll();\n        assertEquals(30, resultList.size());\n        RealmQuery<AllTypes> query = realm.where(AllTypes.class).lessThan(AllTypes.FIELD_FLOAT, 31.2345f);\n        resultList = query.between(AllTypes.FIELD_LONG, 1, 10).findAll();\n        assertEquals(10, resultList.size());\n    }\n\n    @Test\n    public void lessThan_Date() {\n        final int TEST_OBJECTS_COUNT = 200;\n        populateTestRealm(realm, TEST_OBJECTS_COUNT);\n\n        RealmResults<AllTypes> resultList;\n        resultList = realm.where(AllTypes.class).lessThan(AllTypes.FIELD_DATE, new Date(Long.MIN_VALUE)).findAll();\n        assertEquals(0, resultList.size());\n        resultList = realm.where(AllTypes.class).lessThan(AllTypes.FIELD_DATE, new Date(DECADE_MILLIS * -80)).findAll();\n        assertEquals(20, resultList.size());\n        resultList = realm.where(AllTypes.class).lessThan(AllTypes.FIELD_DATE, new Date(0)).findAll();\n        assertEquals(TEST_OBJECTS_COUNT / 2, resultList.size());\n        resultList = realm.where(AllTypes.class).lessThan(AllTypes.FIELD_DATE, new Date(DECADE_MILLIS * 80)).findAll();\n        assertEquals(180, resultList.size());\n        resultList = realm.where(AllTypes.class).lessThan(AllTypes.FIELD_DATE, new Date(Long.MAX_VALUE)).findAll();\n        assertEquals(TEST_OBJECTS_COUNT, resultList.size());\n    }\n\n    @Test\n    public void lessThanOrEqualTo() {\n        final int TEST_OBJECTS_COUNT = 200;\n        populateTestRealm(realm, TEST_OBJECTS_COUNT);\n\n        RealmResults<AllTypes> resultList = realm.where(AllTypes.class)\n                .lessThanOrEqualTo(AllTypes.FIELD_FLOAT, 31.2345f).findAll();\n        assertEquals(31, resultList.size());\n        resultList = realm.where(AllTypes.class).lessThanOrEqualTo(AllTypes.FIELD_FLOAT, 31.2345f)\n                .between(AllTypes.FIELD_LONG, 11, 20).findAll();\n        assertEquals(10, resultList.size());\n    }\n\n    @Test\n    public void lessThanOrEqualTo_date() {\n        final int TEST_OBJECTS_COUNT = 200;\n        populateTestRealm(realm, TEST_OBJECTS_COUNT);\n\n        RealmResults<AllTypes> resultList;\n        resultList = realm.where(AllTypes.class).lessThanOrEqualTo(AllTypes.FIELD_DATE, new Date(Long.MIN_VALUE)).findAll();\n        assertEquals(0, resultList.size());\n        resultList = realm.where(AllTypes.class).lessThanOrEqualTo(AllTypes.FIELD_DATE, new Date(DECADE_MILLIS * -80)).findAll();\n        assertEquals(21, resultList.size());\n        resultList = realm.where(AllTypes.class).lessThanOrEqualTo(AllTypes.FIELD_DATE, new Date(0)).findAll();\n        assertEquals(TEST_OBJECTS_COUNT / 2 + 1, resultList.size());\n        resultList = realm.where(AllTypes.class).lessThanOrEqualTo(AllTypes.FIELD_DATE, new Date(DECADE_MILLIS * 80)).findAll();\n        assertEquals(181, resultList.size());\n        resultList = realm.where(AllTypes.class).lessThanOrEqualTo(AllTypes.FIELD_DATE, new Date(Long.MAX_VALUE)).findAll();\n        assertEquals(TEST_OBJECTS_COUNT, resultList.size());\n    }\n\n    @Test\n    public void equalTo() {\n        populateTestRealm(realm, 200);\n\n        RealmResults<AllTypes> resultList = realm.where(AllTypes.class)\n                .equalTo(AllTypes.FIELD_FLOAT, 31.2345f).findAll();\n        assertEquals(1, resultList.size());\n        resultList = realm.where(AllTypes.class).greaterThan(AllTypes.FIELD_FLOAT, 11.0f)\n                .equalTo(AllTypes.FIELD_LONG, 10).findAll();\n        assertEquals(1, resultList.size());\n        resultList = realm.where(AllTypes.class).greaterThan(AllTypes.FIELD_FLOAT, 11.0f)\n                .equalTo(AllTypes.FIELD_LONG, 1).findAll();\n        assertEquals(0, resultList.size());\n    }\n\n    @Test\n    public void equalTo_decimal128() {\n        populateTestRealm(realm, 10);\n\n        for (int i = 0; i < 10; i++) {\n            RealmResults<AllTypes> resultList = realm.where(AllTypes.class)\n                    .equalTo(AllTypes.FIELD_DECIMAL128, new Decimal128(new BigDecimal(i + \".23456789\")))\n                    .sort(AllTypes.FIELD_DECIMAL128, Sort.ASCENDING)\n                    .findAll();\n\n            assertEquals(1, resultList.size());\n            assertEquals(new Decimal128(new BigDecimal(i + \".23456789\")), resultList.get(0).getColumnDecimal128());\n        }\n    }\n\n    @Test\n    public void equalTo_objectId() {\n        populateTestRealm(realm, 10);\n\n        for (int i = 0; i < 10; i++) {\n            RealmResults<AllTypes> resultList = realm.where(AllTypes.class)\n                    .equalTo(AllTypes.FIELD_OBJECT_ID, new ObjectId(TestHelper.generateObjectIdHexString(i)))\n                    .sort(AllTypes.FIELD_OBJECT_ID, Sort.ASCENDING)\n                    .findAll();\n\n            assertEquals(1, resultList.size());\n            assertEquals(new ObjectId(TestHelper.generateObjectIdHexString(i)), resultList.get(0).getColumnObjectId());\n        }\n    }\n\n    @Test\n    public void equalTo_UUID() {\n        populateTestRealm(realm, 10);\n        for (int i = 0; i < 10; i++) {\n            RealmResults<AllTypes> resultList = realm\n                    .where(AllTypes.class)\n                    .equalTo(AllTypes.FIELD_UUID, UUID.fromString(TestHelper.generateUUIDString(i)))\n                    .sort(AllTypes.FIELD_UUID, Sort.ASCENDING)\n                    .findAll();\n\n            assertEquals(1, resultList.size());\n            assertEquals(UUID.fromString(TestHelper.generateUUIDString(i)), resultList.get(0).getColumnUUID());\n        }\n    }\n\n    @Test\n    public void notEqualTo_objectId() {\n        populateTestRealm(realm, 10);\n\n        RealmResults<AllTypes> resultList = realm\n                .where(AllTypes.class)\n                .notEqualTo(AllTypes.FIELD_OBJECT_ID, new ObjectId(TestHelper.generateObjectIdHexString(0)))\n                .sort(AllTypes.FIELD_OBJECT_ID, Sort.ASCENDING)\n                .findAll();\n\n        assertEquals(9, resultList.size());\n\n        for (int i = 1; i < 10; i++) {\n            assertNotEquals(new ObjectId(TestHelper.generateObjectIdHexString(0)), resultList.get(0).getColumnObjectId());\n        }\n    }\n\n    @Test\n    public void notEqualTo_decimal128() {\n        populateTestRealm(realm, 10);\n\n        RealmResults<AllTypes> resultList = realm\n                .where(AllTypes.class)\n                .notEqualTo(AllTypes.FIELD_DECIMAL128, new Decimal128(new BigDecimal(\"0.23456789\")))\n                .sort(AllTypes.FIELD_UUID, Sort.ASCENDING)\n                .findAll();\n\n        assertEquals(9, resultList.size());\n\n        for (int i = 1; i < 10; i++) {\n            assertNotEquals(new Decimal128(new BigDecimal(\"0.23456789\")), resultList.get(0).getColumnDecimal128());\n        }\n    }\n\n    @Test\n    public void notEqualTo_UUID() {\n        populateTestRealm(realm, 10);\n\n        RealmResults<AllTypes> resultList = realm\n                .where(AllTypes.class)\n                .notEqualTo(AllTypes.FIELD_UUID, UUID.fromString(\"007ba5ca-aa12-4afa-9219-e20cc3018599\"))\n                .sort(AllTypes.FIELD_UUID, Sort.ASCENDING)\n                .findAll();\n\n        assertEquals(10, resultList.size());\n\n        for (int i = 0; i < 10; i++) {\n            assertNotEquals(UUID.fromString(\"007ba5ca-aa12-4afa-9219-e20cc3018599\"), resultList.get(0).getColumnUUID());\n        }\n    }\n\n    @Test\n    public void equalTo_date() {\n        final int TEST_OBJECTS_COUNT = 200;\n        populateTestRealm(realm, TEST_OBJECTS_COUNT);\n\n        RealmResults<AllTypes> resultList;\n        resultList = realm.where(AllTypes.class).equalTo(AllTypes.FIELD_DATE, new Date(Long.MIN_VALUE)).findAll();\n        assertEquals(0, resultList.size());\n        resultList = realm.where(AllTypes.class).equalTo(AllTypes.FIELD_DATE, new Date(DECADE_MILLIS * -80)).findAll();\n        assertEquals(1, resultList.size());\n        resultList = realm.where(AllTypes.class).equalTo(AllTypes.FIELD_DATE, new Date(0)).findAll();\n        assertEquals(1, resultList.size());\n        resultList = realm.where(AllTypes.class).equalTo(AllTypes.FIELD_DATE, new Date(DECADE_MILLIS * 80)).findAll();\n        assertEquals(1, resultList.size());\n        resultList = realm.where(AllTypes.class).equalTo(AllTypes.FIELD_DATE, new Date(Long.MAX_VALUE)).findAll();\n        assertEquals(0, resultList.size());\n    }\n\n    @Test\n    public void equalTo_nonLatinCharacters() {\n        populateTestRealm(realm, 200);\n\n        RealmResults<NonLatinFieldNames> resultList = realm.where(NonLatinFieldNames.class)\n                .equalTo(NonLatinFieldNames.FIELD_LONG_KOREAN_CHAR, 13).findAll();\n        assertEquals(1, resultList.size());\n        resultList = realm.where(NonLatinFieldNames.class)\n                .greaterThan(NonLatinFieldNames.FIELD_FLOAT_KOREAN_CHAR, 11.0f)\n                .equalTo(NonLatinFieldNames.FIELD_LONG_KOREAN_CHAR, 10).findAll();\n        assertEquals(1, resultList.size());\n        resultList = realm.where(NonLatinFieldNames.class)\n                .greaterThan(NonLatinFieldNames.FIELD_FLOAT_KOREAN_CHAR, 11.0f)\n                .equalTo(NonLatinFieldNames.FIELD_LONG_KOREAN_CHAR, 1).findAll();\n        assertEquals(0, resultList.size());\n\n        resultList = realm.where(NonLatinFieldNames.class)\n                .equalTo(NonLatinFieldNames.FIELD_LONG_GREEK_CHAR, 13).findAll();\n        assertEquals(1, resultList.size());\n        resultList = realm.where(NonLatinFieldNames.class)\n                .greaterThan(NonLatinFieldNames.FIELD_FLOAT_GREEK_CHAR, 11.0f)\n                .equalTo(NonLatinFieldNames.FIELD_LONG_GREEK_CHAR, 10).findAll();\n        assertEquals(1, resultList.size());\n        resultList = realm.where(NonLatinFieldNames.class)\n                .greaterThan(NonLatinFieldNames.FIELD_FLOAT_GREEK_CHAR, 11.0f)\n                .equalTo(NonLatinFieldNames.FIELD_LONG_GREEK_CHAR, 1).findAll();\n        assertEquals(0, resultList.size());\n    }\n\n    private void doTestForInString(String targetField) {\n        populateNoPrimaryKeyNullTypesRows();\n        RealmResults<NoPrimaryKeyNullTypes> resultList = realm.where(NoPrimaryKeyNullTypes.class).in(targetField, new String[] {\"test data 14\"}).findAll();\n        assertEquals(1, resultList.size());\n        resultList = realm.where(NoPrimaryKeyNullTypes.class).in(targetField, new String[] {\"test data 14\", \"test data 118\", \"test data 31\", \"test data 199\"}).findAll();\n        assertEquals(4, resultList.size());\n        resultList = realm.where(NoPrimaryKeyNullTypes.class).in(targetField, new String[] {\"TEST data 14\", \"test data 118\", \"test data 31\", \"test DATA 199\"}, Case.INSENSITIVE).findAll();\n        assertEquals(4, resultList.size());\n        resultList = realm.where(NoPrimaryKeyNullTypes.class).not().in(targetField, new String[] {\"TEST data 14\", \"test data 118\", \"test data 31\", \"test DATA 199\"}, Case.INSENSITIVE).findAll();\n        assertEquals(196, resultList.size());\n        resultList = realm.where(NoPrimaryKeyNullTypes.class).not().in(targetField, new String[] {\"TEST data 14\", \"test data 118\", \"test data 31\", \"test DATA 199\"}, Case.INSENSITIVE).findAll();\n        assertEquals(196, resultList.size());\n\n        // Empty input always produces zero results\n        resultList = realm.where(NoPrimaryKeyNullTypes.class).in(targetField, (String[]) null).findAll();\n        assertTrue(resultList.isEmpty());\n        resultList = realm.where(NoPrimaryKeyNullTypes.class).in(targetField, new String[] {}).findAll();\n        assertTrue(resultList.isEmpty());\n    }\n\n    private void doTestForInBoolean(String targetField, int expected1, int expected2, int expected3, int expected4) {\n        populateNoPrimaryKeyNullTypesRows();\n        RealmResults<NoPrimaryKeyNullTypes> resultList = realm.where(NoPrimaryKeyNullTypes.class).in(targetField, new Boolean[] {false}).findAll();\n        assertEquals(expected1, resultList.size());\n        resultList = realm.where(NoPrimaryKeyNullTypes.class).in(targetField, new Boolean[] {true}).findAll();\n        assertEquals(expected2, resultList.size());\n        resultList = realm.where(NoPrimaryKeyNullTypes.class).in(targetField, new Boolean[] {true, false}).findAll();\n        assertEquals(expected3, resultList.size());\n        resultList = realm.where(NoPrimaryKeyNullTypes.class).not().in(targetField, new Boolean[] {true, false}).findAll();\n        assertEquals(expected4, resultList.size());\n\n        // Empty input always produces zero results\n        resultList = realm.where(NoPrimaryKeyNullTypes.class).in(targetField, (Boolean[]) null).findAll();\n        assertTrue(resultList.isEmpty());\n        resultList = realm.where(NoPrimaryKeyNullTypes.class).in(targetField, new Boolean[] {}).findAll();\n        assertTrue(resultList.isEmpty());\n    }\n\n    private void doTestForInDate(String targetField) {\n        populateNoPrimaryKeyNullTypesRows();\n        RealmResults<NoPrimaryKeyNullTypes> resultList = realm.where(NoPrimaryKeyNullTypes.class).in(targetField, new Date[] {new Date(DECADE_MILLIS * -80)}).findAll();\n        assertEquals(1, resultList.size());\n        resultList = realm.where(NoPrimaryKeyNullTypes.class).in(targetField, new Date[] {new Date(0)}).findAll();\n        assertEquals(1, resultList.size());\n        resultList = realm.where(NoPrimaryKeyNullTypes.class).in(targetField, new Date[] {new Date(DECADE_MILLIS * -80), new Date(0)}).findAll();\n        assertEquals(2, resultList.size());\n        resultList = realm.where(NoPrimaryKeyNullTypes.class).not().in(targetField, new Date[] {new Date(DECADE_MILLIS * -80), new Date(0)}).findAll();\n        assertEquals(198, resultList.size());\n\n        // Empty input always produces zero results\n        resultList = realm.where(NoPrimaryKeyNullTypes.class).in(targetField, (Date[]) null).findAll();\n        assertTrue(resultList.isEmpty());\n        resultList = realm.where(NoPrimaryKeyNullTypes.class).in(targetField, new Date[] {}).findAll();\n        assertTrue(resultList.isEmpty());\n    }\n\n    private void doTestForInDouble(String targetField) {\n        populateNoPrimaryKeyNullTypesRows();\n        RealmResults<NoPrimaryKeyNullTypes> resultList = realm.where(NoPrimaryKeyNullTypes.class).in(targetField, new Double[] {Math.PI + 1}).findAll();\n        assertEquals(1, resultList.size());\n        resultList = realm.where(NoPrimaryKeyNullTypes.class).in(targetField, new Double[] {Math.PI + 2}).findAll();\n        assertEquals(1, resultList.size());\n        resultList = realm.where(NoPrimaryKeyNullTypes.class).in(targetField, new Double[] {Math.PI + 1, Math.PI + 2}).findAll();\n        assertEquals(2, resultList.size());\n        resultList = realm.where(NoPrimaryKeyNullTypes.class).not().in(targetField, new Double[] {Math.PI + 1, Math.PI + 2}).findAll();\n        assertEquals(198, resultList.size());\n\n        // Empty input always produces zero results\n        resultList = realm.where(NoPrimaryKeyNullTypes.class).in(targetField, (Double[]) null).findAll();\n        assertTrue(resultList.isEmpty());\n        resultList = realm.where(NoPrimaryKeyNullTypes.class).in(targetField, new Double[] {}).findAll();\n        assertTrue(resultList.isEmpty());\n    }\n\n    private void doTestForInFloat(String targetField) {\n        populateNoPrimaryKeyNullTypesRows();\n        RealmResults<NoPrimaryKeyNullTypes> resultList = realm.where(NoPrimaryKeyNullTypes.class).in(targetField, new Float[] {1.2345f + 1}).findAll();\n        assertEquals(1, resultList.size());\n        resultList = realm.where(NoPrimaryKeyNullTypes.class).in(targetField, new Float[] {1.2345f + 2}).findAll();\n        assertEquals(1, resultList.size());\n        resultList = realm.where(NoPrimaryKeyNullTypes.class).in(targetField, new Float[] {1.2345f + 1, 1.2345f + 2}).findAll();\n        assertEquals(2, resultList.size());\n        resultList = realm.where(NoPrimaryKeyNullTypes.class).not().in(targetField, new Float[] {1.2345f + 1, 1.2345f + 2}).findAll();\n        assertEquals(198, resultList.size());\n\n        // Empty input always produces zero results\n        resultList = realm.where(NoPrimaryKeyNullTypes.class).in(targetField, (Float[]) null).findAll();\n        assertTrue(resultList.isEmpty());\n        resultList = realm.where(NoPrimaryKeyNullTypes.class).in(targetField, new Float[] {}).findAll();\n        assertTrue(resultList.isEmpty());\n    }\n\n    private void doTestForInByte(String targetField) {\n        populateNoPrimaryKeyNullTypesRows();\n        RealmResults<NoPrimaryKeyNullTypes> resultList = realm.where(NoPrimaryKeyNullTypes.class).in(targetField, new Byte[] {11}).findAll();\n        assertEquals(1, resultList.size());\n        resultList = realm.where(NoPrimaryKeyNullTypes.class).in(targetField, new Byte[] {13}).findAll();\n        assertEquals(1, resultList.size());\n        resultList = realm.where(NoPrimaryKeyNullTypes.class).in(targetField, new Byte[] {11, 13, 16, 98}).findAll();\n        assertEquals(4, resultList.size());\n        resultList = realm.where(NoPrimaryKeyNullTypes.class).not().in(targetField, new Byte[] {11, 13, 16, 98}).findAll();\n        assertEquals(196, resultList.size());\n\n        // Empty input always produces zero results\n        resultList = realm.where(NoPrimaryKeyNullTypes.class).in(targetField, (Byte[]) null).findAll();\n        assertTrue(resultList.isEmpty());\n        resultList = realm.where(NoPrimaryKeyNullTypes.class).in(targetField, new Byte[] {}).findAll();\n        assertTrue(resultList.isEmpty());\n    }\n\n    private void doTestForInShort(String targetField) {\n        populateNoPrimaryKeyNullTypesRows();\n        RealmResults<NoPrimaryKeyNullTypes> resultList = realm.where(NoPrimaryKeyNullTypes.class).in(targetField, new Short[] {11}).findAll();\n        assertEquals(1, resultList.size());\n        resultList = realm.where(NoPrimaryKeyNullTypes.class).in(targetField, new Short[] {4}).findAll();\n        assertEquals(1, resultList.size());\n        resultList = realm.where(NoPrimaryKeyNullTypes.class).in(targetField, new Short[] {2, 4, 5, 8}).findAll();\n        assertEquals(4, resultList.size());\n        resultList = realm.where(NoPrimaryKeyNullTypes.class).not().in(targetField, new Short[] {2, 4, 5, 8}).findAll();\n        assertEquals(196, resultList.size());\n\n        // Empty input always produces zero results\n        resultList = realm.where(NoPrimaryKeyNullTypes.class).in(targetField, (Float[]) null).findAll();\n        assertTrue(resultList.isEmpty());\n        resultList = realm.where(NoPrimaryKeyNullTypes.class).in(targetField, new Float[] {}).findAll();\n        assertTrue(resultList.isEmpty());\n    }\n\n    private void doTestForInInteger(String targetField) {\n        populateNoPrimaryKeyNullTypesRows();\n        RealmResults<NoPrimaryKeyNullTypes> resultList = realm.where(NoPrimaryKeyNullTypes.class).in(targetField, new Integer[] {11}).findAll();\n        assertEquals(1, resultList.size());\n        resultList = realm.where(NoPrimaryKeyNullTypes.class).in(targetField, new Integer[] {1}).findAll();\n        assertEquals(1, resultList.size());\n        resultList = realm.where(NoPrimaryKeyNullTypes.class).in(targetField, new Integer[] {1, 2, 4, 5}).findAll();\n        assertEquals(4, resultList.size());\n        resultList = realm.where(NoPrimaryKeyNullTypes.class).not().in(targetField, new Integer[] {1, 2, 4, 5}).findAll();\n        assertEquals(196, resultList.size());\n\n        // Empty input always produces zero results\n        resultList = realm.where(NoPrimaryKeyNullTypes.class).in(targetField, (Integer[]) null).findAll();\n        assertTrue(resultList.isEmpty());\n        resultList = realm.where(NoPrimaryKeyNullTypes.class).in(targetField, new Integer[] {}).findAll();\n        assertTrue(resultList.isEmpty());\n    }\n\n    private void doTestForInLong(String targetField) {\n        populateNoPrimaryKeyNullTypesRows();\n        RealmResults<NoPrimaryKeyNullTypes> resultList = realm.where(NoPrimaryKeyNullTypes.class).in(targetField, new Long[] {11l}).findAll();\n        assertEquals(1, resultList.size());\n        resultList = realm.where(NoPrimaryKeyNullTypes.class).in(targetField, new Long[] {13l}).findAll();\n        assertEquals(1, resultList.size());\n        resultList = realm.where(NoPrimaryKeyNullTypes.class).in(targetField, new Long[] {13l, 14l, 16l, 98l}).findAll();\n        assertEquals(4, resultList.size());\n        resultList = realm.where(NoPrimaryKeyNullTypes.class).not().in(targetField, new Long[] {13l, 14l, 16l, 98l}).findAll();\n        assertEquals(196, resultList.size());\n\n        // Empty input always produces zero results\n        resultList = realm.where(NoPrimaryKeyNullTypes.class).in(targetField, (Long[]) null).findAll();\n        assertTrue(resultList.isEmpty());\n        resultList = realm.where(NoPrimaryKeyNullTypes.class).in(targetField, new Long[] {}).findAll();\n        assertTrue(resultList.isEmpty());\n    }\n\n    @Test\n    public void in_stringNull() {\n        doTestForInString(NoPrimaryKeyNullTypes.FIELD_STRING_NULL);\n        RealmResults<NoPrimaryKeyNullTypes> resultList = realm.where(NoPrimaryKeyNullTypes.class).not().in(NoPrimaryKeyNullTypes.FIELD_STRING_NULL, new String[] {\"TEST data 14\", \"test data 118\", null, \"test DATA 199\"}, Case.INSENSITIVE).findAll();\n        assertEquals(130, resultList.size());\n    }\n\n    @Test\n    public void in_booleanNotNull() {\n        doTestForInBoolean(NoPrimaryKeyNullTypes.FIELD_BOOLEAN_NOT_NULL, 133, 67, 200, 0);\n        RealmResults<NoPrimaryKeyNullTypes> resultList = realm.where(NoPrimaryKeyNullTypes.class).not().in(NoPrimaryKeyNullTypes.FIELD_BOOLEAN_NOT_NULL, new Boolean[] {true, null, false}).findAll();\n        assertEquals(0, resultList.size());\n    }\n\n    @Test\n    public void in_booleanNull() {\n        doTestForInBoolean(NoPrimaryKeyNullTypes.FIELD_BOOLEAN_NULL, 66, 67, 133, 67);\n        RealmResults<NoPrimaryKeyNullTypes> resultList = realm.where(NoPrimaryKeyNullTypes.class).not().in(NoPrimaryKeyNullTypes.FIELD_BOOLEAN_NULL, new Boolean[] {true, null, false}).findAll();\n        assertEquals(0, resultList.size());\n    }\n\n    @Test\n    public void in_dateNotNull() {\n        doTestForInDate(NoPrimaryKeyNullTypes.FIELD_DATE_NOT_NULL);\n        RealmResults<NoPrimaryKeyNullTypes> resultList = realm.where(NoPrimaryKeyNullTypes.class).not().in(NoPrimaryKeyNullTypes.FIELD_DATE_NOT_NULL, new Date[] {new Date(DECADE_MILLIS * -80), null, new Date(0)}).findAll();\n        assertEquals(198, resultList.size());\n    }\n\n    @Test\n    public void in_dateNull() {\n        doTestForInDate(NoPrimaryKeyNullTypes.FIELD_DATE_NULL);\n        RealmResults<NoPrimaryKeyNullTypes> resultList = realm.where(NoPrimaryKeyNullTypes.class).not().in(NoPrimaryKeyNullTypes.FIELD_DATE_NULL, new Date[] {new Date(DECADE_MILLIS * -80), null, new Date(0)}).findAll();\n        assertEquals(131, resultList.size());\n    }\n\n    @Test\n    public void in_doubleNotNull() {\n        doTestForInDouble(NoPrimaryKeyNullTypes.FIELD_DOUBLE_NOT_NULL);\n        RealmResults<NoPrimaryKeyNullTypes> resultList = realm.where(NoPrimaryKeyNullTypes.class).not().in(NoPrimaryKeyNullTypes.FIELD_DOUBLE_NOT_NULL, new Double[] {Math.PI + 1, null, Math.PI + 2}).findAll();\n        assertEquals(198, resultList.size());\n    }\n\n    @Test\n    public void in_doubleNull() {\n        doTestForInDouble(NoPrimaryKeyNullTypes.FIELD_DOUBLE_NULL);\n        RealmResults<NoPrimaryKeyNullTypes> resultList = realm.where(NoPrimaryKeyNullTypes.class).not().in(NoPrimaryKeyNullTypes.FIELD_DOUBLE_NULL, new Double[] {Math.PI + 1, null, Math.PI + 2}).findAll();\n        assertEquals(131, resultList.size());\n    }\n\n    @Test\n    public void in_floatNotNull() {\n        doTestForInFloat(NoPrimaryKeyNullTypes.FIELD_FLOAT_NOT_NULL);\n        RealmResults<NoPrimaryKeyNullTypes> resultList = realm.where(NoPrimaryKeyNullTypes.class).not().in(NoPrimaryKeyNullTypes.FIELD_FLOAT_NOT_NULL, new Float[] {1.2345f + 1, null, 1.2345f + 2}).findAll();\n        assertEquals(198, resultList.size());\n    }\n\n    @Test\n    public void in_floatNull() {\n        doTestForInFloat(NoPrimaryKeyNullTypes.FIELD_FLOAT_NULL);\n        RealmResults<NoPrimaryKeyNullTypes> resultList = realm.where(NoPrimaryKeyNullTypes.class).not().in(NoPrimaryKeyNullTypes.FIELD_FLOAT_NULL, new Float[] {1.2345f + 1, null, 1.2345f + 2}).findAll();\n        assertEquals(131, resultList.size());\n    }\n\n    @Test\n    public void in_byteNotNull() {\n        doTestForInByte(NoPrimaryKeyNullTypes.FIELD_BYTE_NOT_NULL);\n        RealmResults<NoPrimaryKeyNullTypes> resultList = realm.where(NoPrimaryKeyNullTypes.class).not().in(NoPrimaryKeyNullTypes.FIELD_BYTE_NOT_NULL, new Byte[] {11, null, 13, 99}).findAll();\n        assertEquals(197, resultList.size());\n    }\n\n    @Test\n    public void in_byteNull() {\n        doTestForInByte(NoPrimaryKeyNullTypes.FIELD_BYTE_NULL);\n        RealmResults<NoPrimaryKeyNullTypes> resultList = realm.where(NoPrimaryKeyNullTypes.class).not().in(NoPrimaryKeyNullTypes.FIELD_BYTE_NULL, new Byte[] {11, null, 13, 99}).findAll();\n        assertEquals(131, resultList.size());\n    }\n\n    @Test\n    public void in_shortNotNull() {\n        doTestForInShort(NoPrimaryKeyNullTypes.FIELD_SHORT_NOT_NULL);\n        RealmResults<NoPrimaryKeyNullTypes> resultList = realm.where(NoPrimaryKeyNullTypes.class).not().in(NoPrimaryKeyNullTypes.FIELD_SHORT_NOT_NULL, new Short[] {2, null, 5, 8}).findAll();\n        assertEquals(197, resultList.size());\n    }\n\n    @Test\n    public void in_shortNull() {\n        doTestForInShort(NoPrimaryKeyNullTypes.FIELD_SHORT_NULL);\n        RealmResults<NoPrimaryKeyNullTypes> resultList = realm.where(NoPrimaryKeyNullTypes.class).not().in(NoPrimaryKeyNullTypes.FIELD_SHORT_NULL, new Short[] {2, null, 5, 8}).findAll();\n        assertEquals(130, resultList.size());\n    }\n\n    @Test\n    public void in_integerNotNull() {\n        doTestForInInteger(NoPrimaryKeyNullTypes.FIELD_INTEGER_NOT_NULL);\n        RealmResults<NoPrimaryKeyNullTypes> resultList = realm.where(NoPrimaryKeyNullTypes.class).not().in(NoPrimaryKeyNullTypes.FIELD_INTEGER_NOT_NULL, new Integer[] {1, null, 4, 5}).findAll();\n        assertEquals(197, resultList.size());\n    }\n\n    @Test\n    public void in_integerNull() {\n        doTestForInInteger(NoPrimaryKeyNullTypes.FIELD_INTEGER_NULL);\n        RealmResults<NoPrimaryKeyNullTypes> resultList = realm.where(NoPrimaryKeyNullTypes.class).not().in(NoPrimaryKeyNullTypes.FIELD_INTEGER_NULL, new Integer[] {1, null, 4, 5}).findAll();\n        assertEquals(130, resultList.size());\n    }\n\n    @Test\n    public void in_longNotNull() {\n        doTestForInLong(NoPrimaryKeyNullTypes.FIELD_LONG_NOT_NULL);\n        RealmResults<NoPrimaryKeyNullTypes> resultList = realm.where(NoPrimaryKeyNullTypes.class).not().in(NoPrimaryKeyNullTypes.FIELD_LONG_NOT_NULL, new Long[] {13l, null, 16l, 98l}).findAll();\n        assertEquals(197, resultList.size());\n    }\n\n    @Test\n    public void in_longNull() {\n        doTestForInLong(NoPrimaryKeyNullTypes.FIELD_LONG_NULL);\n        RealmResults<NoPrimaryKeyNullTypes> resultList = realm.where(NoPrimaryKeyNullTypes.class).not().in(NoPrimaryKeyNullTypes.FIELD_LONG_NULL, new Long[] {13l, null, 16l, 98l}).findAll();\n        assertEquals(130, resultList.size());\n    }\n\n    @Test\n    public void notEqualTo() {\n        final int TEST_OBJECTS_COUNT = 200;\n        populateTestRealm(realm, TEST_OBJECTS_COUNT);\n\n        RealmResults<AllTypes> resultList = realm.where(AllTypes.class)\n                .notEqualTo(AllTypes.FIELD_LONG, 31).findAll();\n        assertEquals(TEST_OBJECTS_COUNT - 1, resultList.size());\n\n        resultList = realm.where(AllTypes.class).notEqualTo(AllTypes.FIELD_FLOAT, 11.2345f)\n                .equalTo(AllTypes.FIELD_LONG, 10).findAll();\n        assertEquals(0, resultList.size());\n\n        resultList = realm.where(AllTypes.class).notEqualTo(AllTypes.FIELD_FLOAT, 11.2345f)\n                .equalTo(AllTypes.FIELD_LONG, 1).findAll();\n        assertEquals(1, resultList.size());\n    }\n\n    @Test\n    public void notEqualTo_date() {\n        final int TEST_OBJECTS_COUNT = 200;\n        populateTestRealm(realm, TEST_OBJECTS_COUNT);\n\n        RealmResults<AllTypes> resultList;\n        resultList = realm.where(AllTypes.class).notEqualTo(AllTypes.FIELD_DATE, new Date(Long.MIN_VALUE)).findAll();\n        assertEquals(TEST_OBJECTS_COUNT, resultList.size());\n        resultList = realm.where(AllTypes.class).notEqualTo(AllTypes.FIELD_DATE, new Date(DECADE_MILLIS * -80)).findAll();\n        assertEquals(TEST_OBJECTS_COUNT - 1, resultList.size());\n        resultList = realm.where(AllTypes.class).notEqualTo(AllTypes.FIELD_DATE, new Date(0)).findAll();\n        assertEquals(TEST_OBJECTS_COUNT - 1, resultList.size());\n        resultList = realm.where(AllTypes.class).notEqualTo(AllTypes.FIELD_DATE, new Date(DECADE_MILLIS * 80)).findAll();\n        assertEquals(TEST_OBJECTS_COUNT - 1, resultList.size());\n        resultList = realm.where(AllTypes.class).notEqualTo(AllTypes.FIELD_DATE, new Date(Long.MAX_VALUE)).findAll();\n        assertEquals(TEST_OBJECTS_COUNT, resultList.size());\n    }\n\n    @Test\n    public void contains_caseSensitive() {\n        final int TEST_OBJECTS_COUNT = 200;\n        populateTestRealm(realm, TEST_OBJECTS_COUNT);\n\n        RealmResults<AllTypes> resultList = realm.where(AllTypes.class)\n                .contains(\"columnString\", \"DaTa 0\", Case.INSENSITIVE)\n                .or().contains(\"columnString\", \"20\")\n                .findAll();\n        assertEquals(3, resultList.size());\n\n        resultList = realm.where(AllTypes.class).contains(\"columnString\", \"DATA\").findAll();\n        assertEquals(0, resultList.size());\n\n        resultList = realm.where(AllTypes.class)\n                .contains(\"columnString\", \"TEST\", Case.INSENSITIVE).findAll();\n        assertEquals(TEST_OBJECTS_COUNT, resultList.size());\n    }\n\n    @Test\n    public void contains_caseSensitiveWithNonLatinCharacters() {\n        populateTestRealm();\n\n        realm.beginTransaction();\n        realm.delete(AllTypes.class);\n        AllTypes at1 = realm.createObject(AllTypes.class);\n        at1.setColumnString(\"Αλφα\");\n        AllTypes at2 = realm.createObject(AllTypes.class);\n        at2.setColumnString(\"βήτα\");\n        AllTypes at3 = realm.createObject(AllTypes.class);\n        at3.setColumnString(\"δέλτα\");\n        realm.commitTransaction();\n\n        RealmResults<AllTypes> resultList = realm.where(AllTypes.class)\n                .contains(\"columnString\", \"Α\", Case.INSENSITIVE)\n                .or().contains(\"columnString\", \"δ\")\n                .findAll();\n        // Without case sensitive there is 3, Α = α\n        // assertEquals(3,resultList.size());\n        assertEquals(2, resultList.size());\n\n        resultList = realm.where(AllTypes.class).contains(\"columnString\", \"α\").findAll();\n        assertEquals(3, resultList.size());\n\n        resultList = realm.where(AllTypes.class).contains(\"columnString\", \"Δ\").findAll();\n        assertEquals(0, resultList.size());\n\n        resultList = realm.where(AllTypes.class).contains(\"columnString\", \"Δ\",\n                Case.INSENSITIVE).findAll();\n        // Without case sensitive there is 1, Δ = δ\n        // assertEquals(1,resultList.size());\n        assertEquals(0, resultList.size());\n    }\n\n    @Test\n    public void like_caseSensitive() {\n        final int TEST_OBJECTS_COUNT = 200;\n        populateTestRealm(realm, TEST_OBJECTS_COUNT);\n\n        RealmResults<AllTypes> resultList = realm.where(AllTypes.class).like(\"columnString\", \"*DaTa*\").findAll();\n        assertEquals(0, resultList.size());\n\n        resultList = realm.where(AllTypes.class).like(\"columnString\", \"*DaTa*\", Case.INSENSITIVE).findAll();\n        assertEquals(TEST_OBJECTS_COUNT, resultList.size());\n\n        resultList = realm.where(AllTypes.class).like(\"columnString\", \"*DaTa 2?\").findAll();\n        assertEquals(0, resultList.size());\n\n        resultList = realm.where(AllTypes.class).like(\"columnString\", \"*DaTa 2?\", Case.INSENSITIVE).findAll();\n        assertEquals(10, resultList.size());\n\n        resultList = realm.where(AllTypes.class).like(\"columnString\", \"TEST*0\").findAll();\n        assertEquals(0, resultList.size());\n\n        resultList = realm.where(AllTypes.class).like(\"columnString\", \"TEST*0\", Case.INSENSITIVE).findAll();\n        assertEquals(20, resultList.size());\n    }\n\n    @Test\n    public void like_caseSensitiveWithNonLatinCharacters() {\n        populateTestRealm();\n\n        String flagEmoji = new StringBuilder().append(Character.toChars(0x1F1E9)).toString();\n        String emojis = \"ABC\" + flagEmoji + \"DEF\";\n\n        realm.beginTransaction();\n        realm.delete(AllTypes.class);\n        AllTypes at1 = realm.createObject(AllTypes.class);\n        at1.setColumnString(\"Αλφα\");\n        AllTypes at2 = realm.createObject(AllTypes.class);\n        at2.setColumnString(\"βήτα\");\n        AllTypes at3 = realm.createObject(AllTypes.class);\n        at3.setColumnString(\"δέλτα\");\n        AllTypes at4 = realm.createObject(AllTypes.class);\n        at4.setColumnString(emojis);\n        realm.commitTransaction();\n\n        RealmResults<AllTypes> resultList = realm.where(AllTypes.class).like(\"columnString\", \"*Α*\").findAll();\n        assertEquals(1, resultList.size());\n\n        resultList = realm.where(AllTypes.class).like(\"columnString\", \"*λ*\").findAll();\n        assertEquals(2, resultList.size());\n\n        resultList = realm.where(AllTypes.class).like(\"columnString\", \"*Δ*\").findAll();\n        assertEquals(0, resultList.size());\n\n        resultList = realm.where(AllTypes.class).like(\"columnString\", \"*Α*\", Case.INSENSITIVE).findAll();\n        // without ASCII-only limitation A matches α\n        // assertEquals(3, resultList.size());\n        assertEquals(1, resultList.size());\n\n        resultList = realm.where(AllTypes.class).like(\"columnString\", \"*λ*\", Case.INSENSITIVE).findAll();\n        assertEquals(2, resultList.size());\n\n        resultList = realm.where(AllTypes.class).like(\"columnString\", \"*Δ*\", Case.INSENSITIVE).findAll();\n        // without ASCII-only limitation Δ matches δ\n        // assertEquals(1, resultList.size());\n        assertEquals(0, resultList.size());\n\n        resultList = realm.where(AllTypes.class).like(\"columnString\", \"?λ*\").findAll();\n        assertEquals(1, resultList.size());\n\n        resultList = realm.where(AllTypes.class).like(\"columnString\", \"??λ*\").findAll();\n        assertEquals(1, resultList.size());\n\n        resultList = realm.where(AllTypes.class).like(\"columnString\", \"?λ*\").findAll();\n        assertEquals(1, resultList.size());\n\n        resultList = realm.where(AllTypes.class).like(\"columnString\", \"??λ*\").findAll();\n        assertEquals(1, resultList.size());\n\n        resultList = realm.where(AllTypes.class).like(\"columnString\", \"ABC?DEF*\").findAll();\n        assertEquals(1, resultList.size());\n\n        resultList = realm.where(AllTypes.class).like(\"columnString\", \"*\" + flagEmoji + \"*\").findAll();\n        assertEquals(1, resultList.size());\n    }\n\n    @Test\n    public void equalTo_withNonExistingField() {\n        try {\n            realm.where(AllTypes.class).equalTo(\"NotAField\", 13).findAll();\n            fail(\"Should throw exception\");\n        } catch (IllegalArgumentException ignored) {\n        }\n    }\n\n    @Test\n    public void queryLink() {\n        realm.beginTransaction();\n        Owner owner = realm.createObject(Owner.class);\n        Dog dog1 = realm.createObject(Dog.class);\n        dog1.setName(\"Dog 1\");\n        dog1.setWeight(1);\n        Dog dog2 = realm.createObject(Dog.class);\n        dog2.setName(\"Dog 2\");\n        dog2.setWeight(2);\n        owner.getDogs().add(dog1);\n        owner.getDogs().add(dog2);\n        realm.commitTransaction();\n\n        // Dog.weight has index 4 which is more than the total number of columns in Owner\n        // This tests exposes a subtle error where the Owner table spec is used instead of Dog table spec.\n        RealmResults<Dog> dogs = realm.where(Owner.class).findFirst().getDogs().where()\n                .sort(\"name\", Sort.ASCENDING)\n                .findAll();\n        Dog dog = dogs.where().equalTo(\"weight\", 1d).findFirst();\n        assertEquals(dog1, dog);\n    }\n\n    @Test\n    public void sort_multiFailures() {\n        // Zero fields specified.\n        try {\n            realm.where(AllTypes.class).sort(new String[] {}, new Sort[] {}).findAll();\n            fail();\n        } catch (IllegalArgumentException ignored) {\n        }\n\n        // Number of fields and sorting orders don't match.\n        try {\n            realm.where(AllTypes.class)\n                    .sort(new String[] {AllTypes.FIELD_STRING}, new Sort[] {Sort.ASCENDING, Sort.ASCENDING})\n                    .findAll();\n            fail();\n        } catch (IllegalArgumentException ignored) {\n        }\n\n        // Null is not allowed.\n        try {\n            realm.where(AllTypes.class)\n                    .sort((String[]) null, null)\n                    .findAll();\n            fail();\n        } catch (IllegalArgumentException ignored) {\n        }\n        try {\n            realm.where(AllTypes.class)\n                    .sort(new String[] {AllTypes.FIELD_STRING}, null)\n                    .findAll();\n            fail();\n        } catch (IllegalArgumentException ignored) {\n        }\n\n        // Non-existing field name.\n        try {\n            realm.where(AllTypes.class)\n                    .sort(new String[] {AllTypes.FIELD_STRING, \"do-not-exist\"}, new Sort[] {Sort.ASCENDING, Sort.ASCENDING})\n                    .findAll();\n            fail();\n        } catch (IllegalArgumentException ignored) {\n        }\n    }\n\n    @Test\n    public void sort_singleField() {\n        realm.beginTransaction();\n        for (int i = 0; i < TEST_DATA_SIZE; i++) {\n            AllTypes allTypes = realm.createObject(AllTypes.class);\n            allTypes.setColumnLong(i);\n        }\n        realm.commitTransaction();\n\n        RealmResults<AllTypes> sortedList = realm.where(AllTypes.class)\n                .sort(new String[] {AllTypes.FIELD_LONG}, new Sort[] {Sort.DESCENDING})\n                .findAll();\n        assertEquals(TEST_DATA_SIZE, sortedList.size());\n        assertEquals(TEST_DATA_SIZE - 1, sortedList.first().getColumnLong());\n        assertEquals(0, sortedList.last().getColumnLong());\n    }\n\n    @Test\n    public void subQueryScope() {\n        populateTestRealm();\n        RealmResults<AllTypes> result = realm.where(AllTypes.class).lessThan(\"columnLong\", 5).findAll();\n        RealmResults<AllTypes> subQueryResult = result.where().greaterThan(\"columnLong\", 3).findAll();\n        assertEquals(1, subQueryResult.size());\n    }\n\n    @Test\n    public void findFirst() {\n        realm.beginTransaction();\n        Owner owner1 = realm.createObject(Owner.class);\n        owner1.setName(\"Owner 1\");\n        Dog dog1 = realm.createObject(Dog.class);\n        dog1.setName(\"Dog 1\");\n        dog1.setWeight(1);\n        Dog dog2 = realm.createObject(Dog.class);\n        dog2.setName(\"Dog 2\");\n        dog2.setWeight(2);\n        owner1.getDogs().add(dog1);\n        owner1.getDogs().add(dog2);\n\n        Owner owner2 = realm.createObject(Owner.class);\n        owner2.setName(\"Owner 2\");\n        Dog dog3 = realm.createObject(Dog.class);\n        dog3.setName(\"Dog 3\");\n        dog3.setWeight(1);\n        Dog dog4 = realm.createObject(Dog.class);\n        dog4.setName(\"Dog 4\");\n        dog4.setWeight(2);\n        owner2.getDogs().add(dog3);\n        owner2.getDogs().add(dog4);\n        realm.commitTransaction();\n\n        RealmList<Dog> dogs = realm.where(Owner.class).equalTo(\"name\", \"Owner 2\").findFirst().getDogs();\n        Dog dog = dogs.where().equalTo(\"name\", \"Dog 4\").findFirst();\n        assertEquals(dog4, dog);\n    }\n\n    @Test\n    public void findFirst_withSorting() {\n        realm.beginTransaction();\n        realm.insert(new Dog(\"Milo\"));\n        realm.insert(new Dog(\"Fido\"));\n        realm.insert(new Dog(\"Bella\"));\n        realm.commitTransaction();\n\n        Dog dog = realm.where(Dog.class).sort(\"name\").findFirst();\n        assertEquals(\"Bella\", dog.getName());\n    }\n\n    @Test\n    public void findFirst_withSortedConstrictingView() {\n        realm.beginTransaction();\n        realm.insert(new Dog(\"Milo\"));\n        realm.insert(new Dog(\"Fido\"));\n        realm.insert(new Dog(\"Bella\"));\n        realm.commitTransaction();\n\n        RealmResults<Dog> dogs = realm.where(Dog.class)\n                .in(\"name\", new String[] {\"Fido\", \"Bella\"})\n                .sort(\"name\", Sort.ASCENDING)\n                .findAll();\n        Dog dog = dogs.where().findFirst();\n        assertEquals(\"Bella\", dog.getName());\n    }\n\n    @Test\n    public void findFirst_subQuery_withSorting() {\n        realm.beginTransaction();\n        realm.insert(new Dog(\"Milo\"));\n        realm.insert(new Dog(\"Fido\"));\n        realm.insert(new Dog(\"Bella\"));\n        realm.commitTransaction();\n\n        RealmResults<Dog> dogs = realm.where(Dog.class).in(\"name\", new String[] {\"Fido\", \"Bella\"}).findAll();\n        Dog dog = dogs.where().sort(\"name\", Sort.ASCENDING).findFirst();\n        assertEquals(\"Bella\", dog.getName());\n    }\n\n    @Test\n    public void georgian() {\n        String words[] = {\"მონაცემთა ბაზა\", \"მიწისქვეშა გადასასვლელი\", \"რუსთაველის გამზირი\",\n                \"მთავარი ქუჩა\", \"სადგურის მოედანი\", \"ველოცირაპტორების ჯოგი\"};\n\n        String sorted[] = {\"ველოცირაპტორების ჯოგი\", \"მთავარი ქუჩა\", \"მიწისქვეშა გადასასვლელი\",\n                \"მონაცემთა ბაზა\", \"რუსთაველის გამზირი\", \"სადგურის მოედანი\"};\n\n        realm.beginTransaction();\n        realm.delete(StringOnly.class);\n        for (String word : words) {\n            StringOnly stringOnly = realm.createObject(StringOnly.class);\n            stringOnly.setChars(word);\n        }\n        realm.commitTransaction();\n\n        RealmResults<StringOnly> stringOnlies1 = realm.where(StringOnly.class).contains(\"chars\", \"მთავარი\").findAll();\n        assertEquals(1, stringOnlies1.size());\n\n        RealmResults<StringOnly> stringOnlies2 = realm.where(StringOnly.class).findAll();\n        stringOnlies2 = stringOnlies2.sort(\"chars\");\n        for (int i = 0; i < stringOnlies2.size(); i++) {\n            assertEquals(sorted[i], stringOnlies2.get(i).getChars());\n        }\n    }\n\n    // Queries nullable PrimaryKey.\n    @Test\n    public void equalTo_nullPrimaryKeys() {\n        final long SECONDARY_FIELD_NUMBER = 49992417L;\n        final String SECONDARY_FIELD_STRING = \"Realm is a mobile database hundreds of millions of people rely on.\";\n        // Fills up a Realm with one user PrimaryKey value and 9 numeric values, starting from -5.\n        TestHelper.populateTestRealmWithStringPrimaryKey(realm, (String) null, SECONDARY_FIELD_NUMBER, 10, -5);\n        TestHelper.populateTestRealmWithBytePrimaryKey(realm, (Byte) null, SECONDARY_FIELD_STRING, 10, -5);\n        TestHelper.populateTestRealmWithShortPrimaryKey(realm, (Short) null, SECONDARY_FIELD_STRING, 10, -5);\n        TestHelper.populateTestRealmWithIntegerPrimaryKey(realm, (Integer) null, SECONDARY_FIELD_STRING, 10, -5);\n        TestHelper.populateTestRealmWithLongPrimaryKey(realm, (Long) null, SECONDARY_FIELD_STRING, 10, -5);\n\n        // String\n        assertEquals(SECONDARY_FIELD_NUMBER, realm.where(PrimaryKeyAsString.class).equalTo(PrimaryKeyAsString.FIELD_PRIMARY_KEY, (String) null).findAll().first().getId());\n        // Boxed Byte\n        assertEquals(SECONDARY_FIELD_STRING, realm.where(PrimaryKeyAsBoxedByte.class).equalTo(PrimaryKeyAsBoxedByte.FIELD_PRIMARY_KEY, (Byte) null).findAll().first().getName());\n        // Boxed Short\n        assertEquals(SECONDARY_FIELD_STRING, realm.where(PrimaryKeyAsBoxedShort.class).equalTo(PrimaryKeyAsBoxedShort.FIELD_PRIMARY_KEY, (Short) null).findAll().first().getName());\n        // Boxed Integer\n        assertEquals(SECONDARY_FIELD_STRING, realm.where(PrimaryKeyAsBoxedInteger.class).equalTo(PrimaryKeyAsBoxedInteger.FIELD_PRIMARY_KEY, (Integer) null).findAll().first().getName());\n        // Boxed Long\n        assertEquals(SECONDARY_FIELD_STRING, realm.where(PrimaryKeyAsBoxedLong.class).equalTo(PrimaryKeyAsBoxedLong.FIELD_PRIMARY_KEY, (Long) null).findAll().first().getName());\n    }\n\n    @Test\n    public void isNull_nullPrimaryKeys() {\n        final long SECONDARY_FIELD_NUMBER = 49992417L;\n        final String SECONDARY_FIELD_STRING = \"Realm is a mobile database hundreds of millions of people rely on.\";\n        // Fills up a realm with one user PrimaryKey value and 9 numeric values, starting from -5.\n        TestHelper.populateTestRealmWithStringPrimaryKey(realm, (String) null, SECONDARY_FIELD_NUMBER, 10, -5);\n        TestHelper.populateTestRealmWithBytePrimaryKey(realm, (Byte) null, SECONDARY_FIELD_STRING, 10, -5);\n        TestHelper.populateTestRealmWithShortPrimaryKey(realm, (Short) null, SECONDARY_FIELD_STRING, 10, -5);\n        TestHelper.populateTestRealmWithIntegerPrimaryKey(realm, (Integer) null, SECONDARY_FIELD_STRING, 10, -5);\n        TestHelper.populateTestRealmWithLongPrimaryKey(realm, (Long) null, SECONDARY_FIELD_STRING, 10, -5);\n\n        // String\n        assertEquals(SECONDARY_FIELD_NUMBER, realm.where(PrimaryKeyAsString.class).isNull(PrimaryKeyAsString.FIELD_PRIMARY_KEY).findAll().first().getId());\n        // Boxed Byte\n        assertEquals(SECONDARY_FIELD_STRING, realm.where(PrimaryKeyAsBoxedByte.class).isNull(PrimaryKeyAsBoxedByte.FIELD_PRIMARY_KEY).findAll().first().getName());\n        // Boxed Short\n        assertEquals(SECONDARY_FIELD_STRING, realm.where(PrimaryKeyAsBoxedShort.class).isNull(PrimaryKeyAsBoxedShort.FIELD_PRIMARY_KEY).findAll().first().getName());\n        // Boxed Integer\n        assertEquals(SECONDARY_FIELD_STRING, realm.where(PrimaryKeyAsBoxedInteger.class).isNull(PrimaryKeyAsBoxedInteger.FIELD_PRIMARY_KEY).findAll().first().getName());\n        // Boxed Long\n        assertEquals(SECONDARY_FIELD_STRING, realm.where(PrimaryKeyAsBoxedLong.class).isNull(PrimaryKeyAsBoxedLong.FIELD_PRIMARY_KEY).findAll().first().getName());\n    }\n\n    @Test\n    public void notEqualTo_nullPrimaryKeys() {\n        final long SECONDARY_FIELD_NUMBER = 49992417L;\n        final String SECONDARY_FIELD_STRING = \"Realm is a mobile database hundreds of millions of people rely on.\";\n        // Fills up a realm with one user PrimaryKey value and one numeric values, starting from -1.\n        TestHelper.populateTestRealmWithStringPrimaryKey(realm, (String) null, SECONDARY_FIELD_NUMBER, 2, -1);\n        TestHelper.populateTestRealmWithBytePrimaryKey(realm, (Byte) null, SECONDARY_FIELD_STRING, 2, -1);\n        TestHelper.populateTestRealmWithShortPrimaryKey(realm, (Short) null, SECONDARY_FIELD_STRING, 2, -1);\n        TestHelper.populateTestRealmWithIntegerPrimaryKey(realm, (Integer) null, SECONDARY_FIELD_STRING, 2, -1);\n        TestHelper.populateTestRealmWithLongPrimaryKey(realm, (Long) null, SECONDARY_FIELD_STRING, 2, -1);\n\n        // String\n        assertEquals(SECONDARY_FIELD_NUMBER, realm.where(PrimaryKeyAsString.class).notEqualTo(PrimaryKeyAsString.FIELD_PRIMARY_KEY, \"-1\").findAll().first().getId());\n        // Boxed Byte\n        assertEquals(SECONDARY_FIELD_STRING, realm.where(PrimaryKeyAsBoxedByte.class).notEqualTo(PrimaryKeyAsBoxedByte.FIELD_PRIMARY_KEY, Byte.valueOf((byte) -1)).findAll().first().getName());\n        // Boxed Short\n        assertEquals(SECONDARY_FIELD_STRING, realm.where(PrimaryKeyAsBoxedShort.class).notEqualTo(PrimaryKeyAsBoxedShort.FIELD_PRIMARY_KEY, Short.valueOf((short) -1)).findAll().first().getName());\n        // Boxed Integer\n        assertEquals(SECONDARY_FIELD_STRING, realm.where(PrimaryKeyAsBoxedInteger.class).notEqualTo(PrimaryKeyAsBoxedInteger.FIELD_PRIMARY_KEY, Integer.valueOf(-1)).findAll().first().getName());\n        // Boxed Long\n        assertEquals(SECONDARY_FIELD_STRING, realm.where(PrimaryKeyAsBoxedLong.class).notEqualTo(PrimaryKeyAsBoxedLong.FIELD_PRIMARY_KEY, Long.valueOf((long) -1)).findAll().first().getName());\n    }\n\n    @Test\n    public void beginWith_nullStringPrimaryKey() {\n        final long SECONDARY_FIELD_NUMBER = 49992417L;\n        TestHelper.populateTestRealmWithStringPrimaryKey(realm, (String) null, SECONDARY_FIELD_NUMBER, 10, -5);\n\n        RealmQuery<PrimaryKeyAsString> query = realm.where(PrimaryKeyAsString.class);\n        try {\n            query.beginsWith(PrimaryKeyAsString.FIELD_PRIMARY_KEY, (String) null);\n            fail();\n        } catch (IllegalArgumentException ignore) {\n        }\n    }\n\n    @Test\n    public void contains_nullStringPrimaryKey() {\n        final long SECONDARY_FIELD_NUMBER = 49992417L;\n        TestHelper.populateTestRealmWithStringPrimaryKey(realm, (String) null, SECONDARY_FIELD_NUMBER, 10, -5);\n\n        RealmQuery<PrimaryKeyAsString> query = realm.where(PrimaryKeyAsString.class);\n        try {\n            query.contains(PrimaryKeyAsString.FIELD_PRIMARY_KEY, (String) null);\n            fail();\n        } catch (IllegalArgumentException ignore) {\n        }\n    }\n\n    @Test\n    public void endsWith_nullStringPrimaryKey() {\n        final long SECONDARY_FIELD_NUMBER = 49992417L;\n        TestHelper.populateTestRealmWithStringPrimaryKey(realm, (String) null, SECONDARY_FIELD_NUMBER, 10, -5);\n\n        RealmQuery<PrimaryKeyAsString> query = realm.where(PrimaryKeyAsString.class);\n        try {\n            query.endsWith(PrimaryKeyAsString.FIELD_PRIMARY_KEY, (String) null);\n            fail();\n        } catch (IllegalArgumentException ignore) {\n        }\n    }\n\n    @Test\n    public void like_nullStringPrimaryKey() {\n        final long SECONDARY_FIELD_NUMBER = 49992417L;\n        TestHelper.populateTestRealmWithStringPrimaryKey(realm, (String) null, SECONDARY_FIELD_NUMBER, 10, -5);\n\n        RealmQuery<PrimaryKeyAsString> query = realm.where(PrimaryKeyAsString.class);\n        try {\n            query.like(PrimaryKeyAsString.FIELD_PRIMARY_KEY, (String) null);\n            fail();\n        } catch (IllegalArgumentException ignore) {\n        }\n    }\n\n    @Test\n    public void between_nullPrimaryKeysIsNotZero() {\n        // Fills up a realm with one user PrimaryKey value and 9 numeric values, starting from -5.\n        TestHelper.populateTestRealmWithBytePrimaryKey(realm, (Byte) null, (String) null, 10, -5);\n        TestHelper.populateTestRealmWithShortPrimaryKey(realm, (Short) null, (String) null, 10, -5);\n        TestHelper.populateTestRealmWithIntegerPrimaryKey(realm, (Integer) null, (String) null, 10, -5);\n        TestHelper.populateTestRealmWithLongPrimaryKey(realm, (Long) null, (String) null, 10, -5);\n\n        // Boxed Byte\n        assertEquals(3, realm.where(PrimaryKeyAsBoxedByte.class).between(PrimaryKeyAsBoxedByte.FIELD_PRIMARY_KEY, -1, 1).count());\n        // Boxed Short\n        assertEquals(3, realm.where(PrimaryKeyAsBoxedShort.class).between(PrimaryKeyAsBoxedShort.FIELD_PRIMARY_KEY, -1, 1).count());\n        // Boxed Integer\n        assertEquals(3, realm.where(PrimaryKeyAsBoxedInteger.class).between(PrimaryKeyAsBoxedInteger.FIELD_PRIMARY_KEY, -1, 1).count());\n        // Boxed Long\n        assertEquals(3, realm.where(PrimaryKeyAsBoxedLong.class).between(PrimaryKeyAsBoxedLong.FIELD_PRIMARY_KEY, -1, 1).count());\n    }\n\n    @Test\n    public void greaterThan_nullPrimaryKeysIsNotZero() {\n        // Fills up a realm with one user PrimaryKey value and 9 numeric values, starting from -5.\n        TestHelper.populateTestRealmWithBytePrimaryKey(realm, (Byte) null, (String) null, 10, -5);\n        TestHelper.populateTestRealmWithShortPrimaryKey(realm, (Short) null, (String) null, 10, -5);\n        TestHelper.populateTestRealmWithIntegerPrimaryKey(realm, (Integer) null, (String) null, 10, -5);\n        TestHelper.populateTestRealmWithLongPrimaryKey(realm, (Long) null, (String) null, 10, -5);\n\n        // Boxed Byte\n        assertEquals(4, realm.where(PrimaryKeyAsBoxedByte.class).greaterThan(PrimaryKeyAsBoxedByte.FIELD_PRIMARY_KEY, -1).count());\n        // Boxed Short\n        assertEquals(4, realm.where(PrimaryKeyAsBoxedShort.class).greaterThan(PrimaryKeyAsBoxedShort.FIELD_PRIMARY_KEY, -1).count());\n        // Boxed Integer\n        assertEquals(4, realm.where(PrimaryKeyAsBoxedInteger.class).greaterThan(PrimaryKeyAsBoxedInteger.FIELD_PRIMARY_KEY, -1).count());\n        // Boxed Long\n        assertEquals(4, realm.where(PrimaryKeyAsBoxedLong.class).greaterThan(PrimaryKeyAsBoxedLong.FIELD_PRIMARY_KEY, -1).count());\n    }\n\n    @Test\n    public void greaterThanOrEqualTo_nullPrimaryKeysIsNotZero() {\n        // Fills up a realm with one user PrimaryKey value and 9 numeric values, starting from -5.\n        TestHelper.populateTestRealmWithBytePrimaryKey(realm, (Byte) null, (String) null, 10, -5);\n        TestHelper.populateTestRealmWithShortPrimaryKey(realm, (Short) null, (String) null, 10, -5);\n        TestHelper.populateTestRealmWithIntegerPrimaryKey(realm, (Integer) null, (String) null, 10, -5);\n        TestHelper.populateTestRealmWithLongPrimaryKey(realm, (Long) null, (String) null, 10, -5);\n\n        // Boxed Byte\n        assertEquals(5, realm.where(PrimaryKeyAsBoxedByte.class).greaterThanOrEqualTo(PrimaryKeyAsBoxedByte.FIELD_PRIMARY_KEY, -1).count());\n        // Boxed Short\n        assertEquals(5, realm.where(PrimaryKeyAsBoxedShort.class).greaterThanOrEqualTo(PrimaryKeyAsBoxedShort.FIELD_PRIMARY_KEY, -1).count());\n        // Boxed Integer\n        assertEquals(5, realm.where(PrimaryKeyAsBoxedInteger.class).greaterThanOrEqualTo(PrimaryKeyAsBoxedInteger.FIELD_PRIMARY_KEY, -1).count());\n        // Boxed Long\n        assertEquals(5, realm.where(PrimaryKeyAsBoxedLong.class).greaterThanOrEqualTo(PrimaryKeyAsBoxedLong.FIELD_PRIMARY_KEY, -1).count());\n    }\n\n    @Test\n    public void lessThan_nullPrimaryKeysIsNotZero() {\n        // Fills up a realm with one user PrimaryKey value and 9 numeric values, starting from -5.\n        TestHelper.populateTestRealmWithBytePrimaryKey(realm, (Byte) null, (String) null, 10, -5);\n        TestHelper.populateTestRealmWithShortPrimaryKey(realm, (Short) null, (String) null, 10, -5);\n        TestHelper.populateTestRealmWithIntegerPrimaryKey(realm, (Integer) null, (String) null, 10, -5);\n        TestHelper.populateTestRealmWithLongPrimaryKey(realm, (Long) null, (String) null, 10, -5);\n\n        // Boxed Byte\n        assertEquals(6, realm.where(PrimaryKeyAsBoxedByte.class).lessThan(PrimaryKeyAsBoxedByte.FIELD_PRIMARY_KEY, 1).count());\n        // Boxed Short\n        assertEquals(6, realm.where(PrimaryKeyAsBoxedShort.class).lessThan(PrimaryKeyAsBoxedShort.FIELD_PRIMARY_KEY, 1).count());\n        // Boxed Integer\n        assertEquals(6, realm.where(PrimaryKeyAsBoxedInteger.class).lessThan(PrimaryKeyAsBoxedInteger.FIELD_PRIMARY_KEY, 1).count());\n        // Boxed Long\n        assertEquals(6, realm.where(PrimaryKeyAsBoxedLong.class).lessThan(PrimaryKeyAsBoxedLong.FIELD_PRIMARY_KEY, 1).count());\n    }\n\n    @Test\n    public void lessThanOrEqualTo_nullPrimaryKeysIsNotZero() {\n        // Fills up a realm with one user PrimaryKey value and 9 numeric values, starting from -5.\n        TestHelper.populateTestRealmWithBytePrimaryKey(realm, (Byte) null, (String) null, 10, -5);\n        TestHelper.populateTestRealmWithShortPrimaryKey(realm, (Short) null, (String) null, 10, -5);\n        TestHelper.populateTestRealmWithIntegerPrimaryKey(realm, (Integer) null, (String) null, 10, -5);\n        TestHelper.populateTestRealmWithLongPrimaryKey(realm, (Long) null, (String) null, 10, -5);\n\n        // Boxed Byte\n        assertEquals(7, realm.where(PrimaryKeyAsBoxedByte.class).lessThanOrEqualTo(PrimaryKeyAsBoxedByte.FIELD_PRIMARY_KEY, 1).count());\n        // Boxed Short\n        assertEquals(7, realm.where(PrimaryKeyAsBoxedShort.class).lessThanOrEqualTo(PrimaryKeyAsBoxedShort.FIELD_PRIMARY_KEY, 1).count());\n        // Boxed Integer\n        assertEquals(7, realm.where(PrimaryKeyAsBoxedInteger.class).lessThanOrEqualTo(PrimaryKeyAsBoxedInteger.FIELD_PRIMARY_KEY, 1).count());\n        // Boxed Long\n        assertEquals(7, realm.where(PrimaryKeyAsBoxedLong.class).lessThanOrEqualTo(PrimaryKeyAsBoxedLong.FIELD_PRIMARY_KEY, 1).count());\n    }\n\n    // Queries nullable fields with equalTo null.\n    @Test\n    public void equalTo_nullableFields() {\n        TestHelper.populateTestRealmForNullTests(realm);\n\n        // 1 String\n        assertEquals(1, realm.where(NullTypes.class).equalTo(NullTypes.FIELD_STRING_NULL, \"Horse\").count());\n        assertEquals(1, realm.where(NullTypes.class).equalTo(NullTypes.FIELD_STRING_NULL, (String) null).count());\n        assertEquals(1, realm.where(NullTypes.class).equalTo(NullTypes.FIELD_STRING_NULL, \"Fish\").count());\n        assertEquals(0, realm.where(NullTypes.class).equalTo(NullTypes.FIELD_STRING_NULL, \"Goat\").count());\n        // 2 Bytes\n        assertEquals(1, realm.where(NullTypes.class).equalTo(NullTypes.FIELD_BYTES_NULL, new byte[] {0}).count());\n        assertEquals(1, realm.where(NullTypes.class).equalTo(NullTypes.FIELD_BYTES_NULL, (byte[]) null).count());\n        assertEquals(1, realm.where(NullTypes.class).equalTo(NullTypes.FIELD_BYTES_NULL, new byte[] {1, 2}).count());\n        assertEquals(0, realm.where(NullTypes.class).equalTo(NullTypes.FIELD_BYTES_NULL, new byte[] {1, 2, 3}).count());\n        // 3 Boolean\n        assertEquals(1, realm.where(NullTypes.class).equalTo(NullTypes.FIELD_BOOLEAN_NULL, true).count());\n        assertEquals(1, realm.where(NullTypes.class).equalTo(NullTypes.FIELD_BOOLEAN_NULL, (Boolean) null).count());\n        assertEquals(1, realm.where(NullTypes.class).equalTo(NullTypes.FIELD_BOOLEAN_NULL, false).count());\n        // 4 Byte\n        assertEquals(1, realm.where(NullTypes.class).equalTo(NullTypes.FIELD_BYTE_NULL, 1).count());\n        assertEquals(1, realm.where(NullTypes.class).equalTo(NullTypes.FIELD_BYTE_NULL, (byte) 1).count());\n        assertEquals(1, realm.where(NullTypes.class).equalTo(NullTypes.FIELD_BYTE_NULL, (Byte) null).count());\n        assertEquals(0, realm.where(NullTypes.class).equalTo(NullTypes.FIELD_BYTE_NULL, (byte) 42).count());\n        // 5 Short for other long based columns, only test null\n        assertEquals(1, realm.where(NullTypes.class).equalTo(NullTypes.FIELD_SHORT_NULL, 1).count());\n        assertEquals(1, realm.where(NullTypes.class).equalTo(NullTypes.FIELD_SHORT_NULL, (short) 1).count());\n        assertEquals(1, realm.where(NullTypes.class).equalTo(NullTypes.FIELD_SHORT_NULL, (Short) null).count());\n        assertEquals(0, realm.where(NullTypes.class).equalTo(NullTypes.FIELD_SHORT_NULL, (short) 42).count());\n        // 6 Integer\n        assertEquals(1, realm.where(NullTypes.class).equalTo(NullTypes.FIELD_INTEGER_NULL, 1).count());\n        assertEquals(1, realm.where(NullTypes.class).equalTo(NullTypes.FIELD_INTEGER_NULL, (Integer) null).count());\n        assertEquals(0, realm.where(NullTypes.class).equalTo(NullTypes.FIELD_INTEGER_NULL, 42).count());\n        // 7 Long\n        assertEquals(1, realm.where(NullTypes.class).equalTo(NullTypes.FIELD_LONG_NULL, 1).count());\n        assertEquals(1, realm.where(NullTypes.class).equalTo(NullTypes.FIELD_LONG_NULL, (long) 1).count());\n        assertEquals(1, realm.where(NullTypes.class).equalTo(NullTypes.FIELD_LONG_NULL, (Long) null).count());\n        assertEquals(0, realm.where(NullTypes.class).equalTo(NullTypes.FIELD_LONG_NULL, (long) 42).count());\n        // 8 Float\n        assertEquals(1, realm.where(NullTypes.class).equalTo(NullTypes.FIELD_FLOAT_NULL, 1F).count());\n        assertEquals(1, realm.where(NullTypes.class).equalTo(NullTypes.FIELD_FLOAT_NULL, (Float) null).count());\n        assertEquals(0, realm.where(NullTypes.class).equalTo(NullTypes.FIELD_FLOAT_NULL, 42F).count());\n        // 9 Double\n        assertEquals(1, realm.where(NullTypes.class).equalTo(NullTypes.FIELD_DOUBLE_NULL, 1D).count());\n        assertEquals(1, realm.where(NullTypes.class).equalTo(NullTypes.FIELD_DOUBLE_NULL, (Double) null).count());\n        assertEquals(0, realm.where(NullTypes.class).equalTo(NullTypes.FIELD_DOUBLE_NULL, 42D).count());\n        // 10 Date\n        assertEquals(1, realm.where(NullTypes.class).equalTo(NullTypes.FIELD_DATE_NULL, new Date(0)).count());\n        assertEquals(1, realm.where(NullTypes.class).equalTo(NullTypes.FIELD_DATE_NULL, (Date) null).count());\n        assertEquals(0, realm.where(NullTypes.class).equalTo(NullTypes.FIELD_DATE_NULL, new Date(424242)).count());\n        // 11 Object skipped, doesn't support equalTo query\n    }\n\n    // Queries nullable field for null.\n    @Test\n    public void isNull_nullableFields() {\n        TestHelper.populateTestRealmForNullTests(realm);\n\n        // 1 String\n        assertEquals(1, realm.where(NullTypes.class).isNull(NullTypes.FIELD_STRING_NULL).count());\n        // 2 Bytes\n        assertEquals(1, realm.where(NullTypes.class).isNull(NullTypes.FIELD_BYTES_NULL).count());\n        // 3 Boolean\n        assertEquals(1, realm.where(NullTypes.class).isNull(NullTypes.FIELD_BOOLEAN_NULL).count());\n        // 4 Byte\n        assertEquals(1, realm.where(NullTypes.class).isNull(NullTypes.FIELD_BYTE_NULL).count());\n        // 5 Short\n        assertEquals(1, realm.where(NullTypes.class).isNull(NullTypes.FIELD_SHORT_NULL).count());\n        // 6 Integer\n        assertEquals(1, realm.where(NullTypes.class).isNull(NullTypes.FIELD_INTEGER_NULL).count());\n        // 7 Long\n        assertEquals(1, realm.where(NullTypes.class).isNull(NullTypes.FIELD_LONG_NULL).count());\n        // 8 Float\n        assertEquals(1, realm.where(NullTypes.class).isNull(NullTypes.FIELD_FLOAT_NULL).count());\n        // 9 Double\n        assertEquals(1, realm.where(NullTypes.class).isNull(NullTypes.FIELD_DOUBLE_NULL).count());\n        // 10 Date\n        assertEquals(1, realm.where(NullTypes.class).isNull(NullTypes.FIELD_DATE_NULL).count());\n        // 11 Object\n        assertEquals(1, realm.where(NullTypes.class).isNull(NullTypes.FIELD_OBJECT_NULL).count());\n    }\n\n    // Queries nullable field for not null.\n    @Test\n    public void notEqualTo_nullableFields() {\n        TestHelper.populateTestRealmForNullTests(realm);\n        // 1 String\n        assertEquals(2, realm.where(NullTypes.class).notEqualTo(NullTypes.FIELD_STRING_NULL, \"Horse\").count());\n        assertEquals(2, realm.where(NullTypes.class).notEqualTo(NullTypes.FIELD_STRING_NULL, (String) null).count());\n        // 2 Bytes\n        assertEquals(2, realm.where(NullTypes.class).notEqualTo(NullTypes.FIELD_BYTES_NULL, new byte[] {1, 2}).count());\n        assertEquals(2, realm.where(NullTypes.class).notEqualTo(NullTypes.FIELD_BYTES_NULL, (byte[]) null).count());\n        // 3 Boolean\n        assertEquals(2, realm.where(NullTypes.class).notEqualTo(NullTypes.FIELD_BOOLEAN_NULL, false).count());\n        assertEquals(2, realm.where(NullTypes.class).notEqualTo(NullTypes.FIELD_BOOLEAN_NULL, (Boolean) null).count());\n        // 4 Byte\n        assertEquals(2, realm.where(NullTypes.class).notEqualTo(NullTypes.FIELD_BYTE_NULL, (byte) 1).count());\n        assertEquals(2, realm.where(NullTypes.class).notEqualTo(NullTypes.FIELD_BYTE_NULL, (Byte) null).count());\n        // 5 Short\n        assertEquals(2, realm.where(NullTypes.class).notEqualTo(NullTypes.FIELD_SHORT_NULL, (short) 1).count());\n        assertEquals(2, realm.where(NullTypes.class).notEqualTo(NullTypes.FIELD_SHORT_NULL, (Byte) null).count());\n        // 6 Integer\n        assertEquals(2, realm.where(NullTypes.class).notEqualTo(NullTypes.FIELD_INTEGER_NULL, 1).count());\n        assertEquals(2, realm.where(NullTypes.class).notEqualTo(NullTypes.FIELD_INTEGER_NULL, (Integer) null).count());\n        // 7 Long\n        assertEquals(2, realm.where(NullTypes.class).notEqualTo(NullTypes.FIELD_LONG_NULL, 1).count());\n        assertEquals(2, realm.where(NullTypes.class).notEqualTo(NullTypes.FIELD_LONG_NULL, (Integer) null).count());\n        // 8 Float\n        assertEquals(2, realm.where(NullTypes.class).notEqualTo(NullTypes.FIELD_FLOAT_NULL, 1F).count());\n        assertEquals(2, realm.where(NullTypes.class).notEqualTo(NullTypes.FIELD_FLOAT_NULL, (Float) null).count());\n        // 9 Double\n        assertEquals(2, realm.where(NullTypes.class).notEqualTo(NullTypes.FIELD_DOUBLE_NULL, 1D).count());\n        assertEquals(2, realm.where(NullTypes.class).notEqualTo(NullTypes.FIELD_DOUBLE_NULL, (Double) null).count());\n        // 10 Date\n        assertEquals(2, realm.where(NullTypes.class).notEqualTo(NullTypes.FIELD_DATE_NULL, new Date(0)).count());\n        assertEquals(2, realm.where(NullTypes.class).notEqualTo(NullTypes.FIELD_DATE_NULL, (Date) null).count());\n        // 11 Object skipped, doesn't support notEqualTo query\n    }\n\n    // Queries nullable field for not null.\n    @Test\n    public void isNotNull_nullableFields() {\n        TestHelper.populateTestRealmForNullTests(realm);\n\n        // 1 String\n        assertEquals(2, realm.where(NullTypes.class).isNotNull(NullTypes.FIELD_STRING_NULL).count());\n        // 2 Bytes\n        assertEquals(2, realm.where(NullTypes.class).isNotNull(NullTypes.FIELD_BYTES_NULL).count());\n        // 3 Boolean\n        assertEquals(2, realm.where(NullTypes.class).isNotNull(NullTypes.FIELD_BOOLEAN_NULL).count());\n        // 4 Byte\n        assertEquals(2, realm.where(NullTypes.class).isNotNull(NullTypes.FIELD_BYTE_NULL).count());\n        // 5 Short\n        assertEquals(2, realm.where(NullTypes.class).isNotNull(NullTypes.FIELD_SHORT_NULL).count());\n        // 6 Integer\n        assertEquals(2, realm.where(NullTypes.class).isNotNull(NullTypes.FIELD_INTEGER_NULL).count());\n        // 7 Long\n        assertEquals(2, realm.where(NullTypes.class).isNotNull(NullTypes.FIELD_LONG_NULL).count());\n        // 8 Float\n        assertEquals(2, realm.where(NullTypes.class).isNotNull(NullTypes.FIELD_FLOAT_NULL).count());\n        // 9 Double\n        assertEquals(2, realm.where(NullTypes.class).isNotNull(NullTypes.FIELD_DOUBLE_NULL).count());\n        // 10 Date\n        assertEquals(2, realm.where(NullTypes.class).isNotNull(NullTypes.FIELD_DATE_NULL).count());\n        // 11 Object\n        assertEquals(2, realm.where(NullTypes.class).isNotNull(NullTypes.FIELD_OBJECT_NULL).count());\n    }\n\n    @Test\n    public void isNull_differentThanEmpty() {\n        // Make sure that isNull doesn't match empty string \"\"\n        realm.executeTransaction(r -> {\n            r.delete(NullTypes.class);\n            NullTypes obj = new NullTypes();\n            obj.setId(1);\n            obj.setFieldStringNull(null);\n            r.insert(obj);\n            obj = new NullTypes();\n            obj.setId(2);\n            obj.setFieldStringNull(\"\");\n            r.insert(obj);\n            obj = new NullTypes();\n            obj.setId(3);\n            obj.setFieldStringNull(\"foo\");\n            r.insert(obj);\n        });\n\n        assertEquals(3, realm.where(NullTypes.class).findAll().size());\n\n        RealmResults<NullTypes> results = realm.where(NullTypes.class).isNull(NullTypes.FIELD_STRING_NULL).findAll();\n        assertEquals(1, results.size());\n        assertNull(results.first().getFieldStringNull());\n\n        results = realm.where(NullTypes.class).isEmpty(NullTypes.FIELD_STRING_NULL).findAll();\n        assertEquals(1, results.size());\n        assertEquals(\"\", results.first().getFieldStringNull());\n    }\n\n    // Queries nullable field with beginsWith - all strings begin with null.\n    @Test(expected = IllegalArgumentException.class)\n    public void beginWith_nullForNullableStrings() {\n        TestHelper.populateTestRealmForNullTests(realm);\n        assertEquals(\"Fish\", realm.where(NullTypes.class).beginsWith(NullTypes.FIELD_STRING_NULL,\n                (String) null).findFirst().getFieldStringNotNull());\n    }\n\n    // Queries nullable field with contains - all strings contain null.\n    @Test(expected = IllegalArgumentException.class)\n    public void contains_nullForNullableStrings() {\n        TestHelper.populateTestRealmForNullTests(realm);\n        assertEquals(\"Fish\", realm.where(NullTypes.class).contains(NullTypes.FIELD_STRING_NULL,\n                (String) null).findFirst().getFieldStringNotNull());\n    }\n\n    // Queries nullable field with endsWith - all strings end with null.\n    @Test(expected = IllegalArgumentException.class)\n    public void endsWith_nullForNullableStrings() {\n        TestHelper.populateTestRealmForNullTests(realm);\n        assertEquals(\"Fish\", realm.where(NullTypes.class).endsWith(NullTypes.FIELD_STRING_NULL,\n                (String) null).findFirst().getFieldStringNotNull());\n    }\n\n    // Queries nullable field with like - nulls do not match either '?' or '*'.\n    @Test\n    public void like_nullForNullableStrings() {\n        TestHelper.populateTestRealmForNullTests(realm);\n        RealmResults<NullTypes> resultList = realm.where(NullTypes.class).like(NullTypes.FIELD_STRING_NULL, \"*\")\n                .findAll();\n        assertEquals(2, resultList.size());\n\n        resultList = realm.where(NullTypes.class).like(NullTypes.FIELD_STRING_NULL, \"?\").findAll();\n        assertEquals(0, resultList.size());\n    }\n\n    // Queries with between and table has null values in row.\n    @Test\n    public void between_nullValuesInRow() {\n        TestHelper.populateTestRealmForNullTests(realm);\n\n        // 6 Integer\n        assertEquals(1, realm.where(NullTypes.class).between(NullTypes.FIELD_INTEGER_NULL, 2, 4).count());\n        // 7 Long\n        assertEquals(1, realm.where(NullTypes.class).between(NullTypes.FIELD_LONG_NULL, 2L, 4L).count());\n        // 8 Float\n        assertEquals(1, realm.where(NullTypes.class).between(NullTypes.FIELD_FLOAT_NULL, 2F, 4F).count());\n        // 9 Double\n        assertEquals(1, realm.where(NullTypes.class).between(NullTypes.FIELD_DOUBLE_NULL, 2D, 4D).count());\n        // 10 Date\n        assertEquals(1, realm.where(NullTypes.class).between(NullTypes.FIELD_DATE_NULL, new Date(10000),\n                new Date(20000)).count());\n    }\n\n    // Queries with greaterThan and table has null values in row.\n    @Test\n    public void greaterThan_nullValuesInRow() {\n        TestHelper.populateTestRealmForNullTests(realm);\n\n        // 6 Integer\n        assertEquals(1, realm.where(NullTypes.class).greaterThan(NullTypes.FIELD_INTEGER_NULL, 2).count());\n        // 7 Long\n        assertEquals(1, realm.where(NullTypes.class).greaterThan(NullTypes.FIELD_LONG_NULL, 2L).count());\n        // 8 Float\n        assertEquals(1, realm.where(NullTypes.class).greaterThan(NullTypes.FIELD_FLOAT_NULL, 2F).count());\n        // 9 Double\n        assertEquals(1, realm.where(NullTypes.class).greaterThan(NullTypes.FIELD_DOUBLE_NULL, 2D).count());\n        // 10 Date\n        assertEquals(1, realm.where(NullTypes.class).greaterThan(NullTypes.FIELD_DATE_NULL,\n                new Date(5000)).count());\n    }\n\n    // Queries with greaterThanOrEqualTo and table has null values in row.\n    @Test\n    public void greaterThanOrEqualTo_nullValuesInRow() {\n        TestHelper.populateTestRealmForNullTests(realm);\n\n        // 6 Integer\n        assertEquals(1, realm.where(NullTypes.class).greaterThanOrEqualTo(NullTypes.FIELD_INTEGER_NULL, 3).count());\n        // 7 Long\n        assertEquals(1, realm.where(NullTypes.class).greaterThanOrEqualTo(NullTypes.FIELD_LONG_NULL, 3L).count());\n        // 8 Float\n        assertEquals(1, realm.where(NullTypes.class).greaterThanOrEqualTo(NullTypes.FIELD_FLOAT_NULL, 3F).count());\n        // 9 Double\n        assertEquals(1, realm.where(NullTypes.class).greaterThanOrEqualTo(NullTypes.FIELD_DOUBLE_NULL, 3D).count());\n        // 10 Date\n        assertEquals(1, realm.where(NullTypes.class).greaterThanOrEqualTo(NullTypes.FIELD_DATE_NULL,\n                new Date(10000)).count());\n    }\n\n    // Queries with lessThan and table has null values in row.\n    @Test\n    public void lessThan_nullValuesInRow() {\n        TestHelper.populateTestRealmForNullTests(realm);\n\n        // 6 Integer\n        assertEquals(1, realm.where(NullTypes.class).lessThan(NullTypes.FIELD_INTEGER_NULL, 2).count());\n        // 7 Long\n        assertEquals(1, realm.where(NullTypes.class).lessThan(NullTypes.FIELD_LONG_NULL, 2L).count());\n        // 8 Float\n        assertEquals(1, realm.where(NullTypes.class).lessThan(NullTypes.FIELD_FLOAT_NULL, 2F).count());\n        // 9 Double\n        assertEquals(1, realm.where(NullTypes.class).lessThan(NullTypes.FIELD_DOUBLE_NULL, 2D).count());\n        // 10 Date\n        assertEquals(1, realm.where(NullTypes.class).lessThan(NullTypes.FIELD_DATE_NULL,\n                new Date(5000)).count());\n\n    }\n\n    // Queries with lessThanOrEqualTo and table has null values in row.\n    @Test\n    public void lessThanOrEqual_nullValuesInRow() {\n        TestHelper.populateTestRealmForNullTests(realm);\n\n        // 6 Integer\n        assertEquals(1, realm.where(NullTypes.class).lessThanOrEqualTo(NullTypes.FIELD_INTEGER_NULL, 1).count());\n        // 7 Long\n        assertEquals(1, realm.where(NullTypes.class).lessThanOrEqualTo(NullTypes.FIELD_LONG_NULL, 1L).count());\n        // 8 Float\n        assertEquals(1, realm.where(NullTypes.class).lessThanOrEqualTo(NullTypes.FIELD_FLOAT_NULL, 1F).count());\n        // 9 Double\n        assertEquals(1, realm.where(NullTypes.class).lessThanOrEqualTo(NullTypes.FIELD_DOUBLE_NULL, 1D).count());\n        // 10 Date\n        assertEquals(1, realm.where(NullTypes.class).lessThanOrEqualTo(NullTypes.FIELD_DATE_NULL,\n                new Date(9999)).count());\n    }\n\n    // If the RealmQuery is built on a TableView, it should not crash when used after GC.\n    // See issue #1161 for more details.\n    @Test\n    public void buildQueryFromResultsGC() {\n        // According to the testing, setting this to 10 can almost certainly trigger the GC.\n        // Uses 30 here can ensure GC happen. (Tested with 4.3 1G Ram and 5.0 3G Ram)\n        final int count = 30;\n        RealmResults<CatOwner> results = realm.where(CatOwner.class).findAll();\n\n        for (int i = 1; i <= count; i++) {\n            @SuppressWarnings({\"unused\"})\n            byte garbage[] = TestHelper.allocGarbage(0);\n            results = results.where().findAll();\n            System.gc(); // If a native resource has a reference count = 0, doing GC here might lead to a crash.\n        }\n    }\n\n    private static byte[][] binaries = {{1, 2, 3}, {1, 2}, {1, 2, 3}, {2, 3}, {2}, {4, 5, 6}};\n\n    private void createBinaryOnlyDataSet() {\n        realm.beginTransaction();\n        for (int i = 0; i < binaries.length; i++) {\n            AllJavaTypesUnsupportedTypes binaryOnly = new AllJavaTypesUnsupportedTypes((long) i);\n            binaryOnly.setFieldBinary(binaries[i]);\n            realm.copyToRealm(binaryOnly);\n        }\n        realm.commitTransaction();\n    }\n\n    @Test\n    public void equalTo_binary() {\n        createBinaryOnlyDataSet();\n\n        RealmResults<AllJavaTypesUnsupportedTypes> resultList;\n        resultList = realm.where(AllJavaTypesUnsupportedTypes.class).equalTo(AllJavaTypesUnsupportedTypes.FIELD_BINARY, binaries[0]).findAll();\n        assertEquals(2, resultList.size());\n        resultList = realm.where(AllJavaTypesUnsupportedTypes.class).equalTo(AllJavaTypesUnsupportedTypes.FIELD_BINARY, binaries[1]).findAll();\n        assertEquals(1, resultList.size());\n        resultList = realm.where(AllJavaTypesUnsupportedTypes.class).equalTo(AllJavaTypesUnsupportedTypes.FIELD_BINARY, new byte[] {1}).findAll();\n        assertEquals(0, resultList.size());\n    }\n\n    @Test\n    public void equalTo_binary_multiFailures() {\n        createBinaryOnlyDataSet();\n\n        // Non-binary field.\n        try {\n            RealmResults<AllJavaTypesUnsupportedTypes> resultList = realm.where(AllJavaTypesUnsupportedTypes.class)\n                    .equalTo(AllJavaTypesUnsupportedTypes.FIELD_INT, binaries[0]).findAll();\n            fail(\"Should throw exception.\");\n        } catch (IllegalArgumentException ignored) {\n        }\n\n        // Non-existent field.\n        try {\n            RealmResults<AllJavaTypesUnsupportedTypes> resultList = realm.where(AllJavaTypesUnsupportedTypes.class)\n                    .equalTo(\"NotAField\", binaries[0]).findAll();\n            fail(\"Should throw exception.\");\n        } catch (IllegalArgumentException ignored) {\n        }\n    }\n\n    @Test\n    public void notEqualTo_binary() {\n        createBinaryOnlyDataSet();\n\n        RealmResults<AllJavaTypesUnsupportedTypes> resultList;\n        resultList = realm.where(AllJavaTypesUnsupportedTypes.class).notEqualTo(AllJavaTypesUnsupportedTypes.FIELD_BINARY, binaries[0]).findAll();\n        assertEquals(4, resultList.size());\n        resultList = realm.where(AllJavaTypesUnsupportedTypes.class).notEqualTo(AllJavaTypesUnsupportedTypes.FIELD_BINARY, binaries[1]).findAll();\n        assertEquals(5, resultList.size());\n        resultList = realm.where(AllJavaTypesUnsupportedTypes.class).notEqualTo(AllJavaTypesUnsupportedTypes.FIELD_BINARY, new byte[] {1}).findAll();\n        assertEquals(6, resultList.size());\n    }\n\n    @Test\n    public void notEqualTo_binary_multiFailures() {\n        createBinaryOnlyDataSet();\n\n        // Non-binary field.\n        try {\n            RealmResults<AllJavaTypesUnsupportedTypes> resultList = realm.where(AllJavaTypesUnsupportedTypes.class)\n                    .notEqualTo(AllJavaTypesUnsupportedTypes.FIELD_INT, binaries[0]).findAll();\n            fail(\"Should throw exception.\");\n        } catch (IllegalArgumentException ignored) {\n        }\n\n        // Non-existent field.\n        try {\n            RealmResults<AllJavaTypesUnsupportedTypes> resultList = realm.where(AllJavaTypesUnsupportedTypes.class)\n                    .notEqualTo(\"NotAField\", binaries[0]).findAll();\n            fail(\"Should throw exception.\");\n        } catch (IllegalArgumentException ignored) {\n        }\n    }\n\n    // Tests min on empty columns.\n    @Test\n    public void min_emptyColumns() {\n        RealmQuery<NullTypes> query = realm.where(NullTypes.class);\n        assertNull(query.min(NullTypes.FIELD_INTEGER_NOT_NULL));\n        assertNull(query.min(NullTypes.FIELD_FLOAT_NOT_NULL));\n        assertNull(query.min(NullTypes.FIELD_DOUBLE_NOT_NULL));\n        assertNull(query.minimumDate(NullTypes.FIELD_DATE_NOT_NULL));\n    }\n\n    // Tests min on columns with all null rows.\n    @Test\n    public void min_allNullColumns() {\n        TestHelper.populateAllNullRowsForNumericTesting(realm);\n\n        RealmQuery<NullTypes> query = realm.where(NullTypes.class);\n        assertNull(query.min(NullTypes.FIELD_INTEGER_NULL));\n        assertNull(query.min(NullTypes.FIELD_FLOAT_NULL));\n        assertNull(query.min(NullTypes.FIELD_DOUBLE_NULL));\n        assertNull(query.minimumDate(NullTypes.FIELD_DATE_NULL));\n    }\n\n    // Tests min on columns with all non-null rows.\n    @Test\n    public void min_allNonNullRows() {\n        TestHelper.populateAllNonNullRowsForNumericTesting(realm);\n        RealmQuery<NullTypes> query = realm.where(NullTypes.class);\n\n        assertEquals(-1, query.min(NullTypes.FIELD_INTEGER_NULL).intValue());\n        assertEquals(-2f, query.min(NullTypes.FIELD_FLOAT_NULL).floatValue(), 0f);\n        assertEquals(-3d, query.min(NullTypes.FIELD_DOUBLE_NULL).doubleValue(), 0d);\n        assertEquals(-2000, query.minimumDate(NullTypes.FIELD_DATE_NULL).getTime());\n    }\n\n    // Tests min on columns with partial null rows.\n    @Test\n    public void min_partialNullRows() {\n        TestHelper.populatePartialNullRowsForNumericTesting(realm);\n        RealmQuery<NullTypes> query = realm.where(NullTypes.class);\n\n        assertEquals(3, query.min(NullTypes.FIELD_INTEGER_NULL).intValue());\n        assertEquals(4f, query.min(NullTypes.FIELD_FLOAT_NULL).floatValue(), 0f);\n        assertEquals(5d, query.min(NullTypes.FIELD_DOUBLE_NULL).doubleValue(), 0d);\n    }\n\n    // Test max on empty columns\n    @Test\n    public void max_emptyColumns() {\n        RealmQuery<NullTypes> query = realm.where(NullTypes.class);\n        assertNull(query.max(NullTypes.FIELD_INTEGER_NOT_NULL));\n        assertNull(query.max(NullTypes.FIELD_FLOAT_NOT_NULL));\n        assertNull(query.max(NullTypes.FIELD_DOUBLE_NOT_NULL));\n        assertNull(query.maximumDate(NullTypes.FIELD_DATE_NOT_NULL));\n    }\n\n    // Tests max on columns with all null rows.\n    @Test\n    public void max_allNullColumns() {\n        TestHelper.populateAllNullRowsForNumericTesting(realm);\n\n        RealmQuery<NullTypes> query = realm.where(NullTypes.class);\n        assertNull(query.max(NullTypes.FIELD_INTEGER_NULL));\n        assertNull(query.max(NullTypes.FIELD_FLOAT_NULL));\n        assertNull(query.max(NullTypes.FIELD_DOUBLE_NULL));\n        assertNull(query.maximumDate(NullTypes.FIELD_DATE_NULL));\n    }\n\n    // Tests max on columns with all non-null rows.\n    @Test\n    public void max_allNonNullRows() {\n        TestHelper.populateAllNonNullRowsForNumericTesting(realm);\n        RealmQuery<NullTypes> query = realm.where(NullTypes.class);\n\n        assertEquals(4, query.max(NullTypes.FIELD_INTEGER_NULL).intValue());\n        assertEquals(5f, query.max(NullTypes.FIELD_FLOAT_NULL).floatValue(), 0f);\n        assertEquals(6d, query.max(NullTypes.FIELD_DOUBLE_NULL).doubleValue(), 0d);\n        assertEquals(12345, query.maximumDate(NullTypes.FIELD_DATE_NULL).getTime());\n    }\n\n    // Tests max on columns with partial null rows.\n    @Test\n    public void max_partialNullRows() {\n        TestHelper.populatePartialNullRowsForNumericTesting(realm);\n        RealmQuery<NullTypes> query = realm.where(NullTypes.class);\n\n        assertEquals(4, query.max(NullTypes.FIELD_INTEGER_NULL).intValue());\n        assertEquals(5f, query.max(NullTypes.FIELD_FLOAT_NULL).floatValue(), 0f);\n        assertEquals(6d, query.max(NullTypes.FIELD_DOUBLE_NULL).doubleValue(), 0d);\n        assertEquals(12345, query.maximumDate(NullTypes.FIELD_DATE_NULL).getTime());\n    }\n\n    // Tests average on empty columns.\n    @Test\n    public void average_emptyColumns() {\n        RealmQuery<NullTypes> query = realm.where(NullTypes.class);\n        assertEquals(0d, query.average(NullTypes.FIELD_INTEGER_NULL), 0d);\n        assertEquals(0d, query.average(NullTypes.FIELD_FLOAT_NULL), 0d);\n        assertEquals(0d, query.average(NullTypes.FIELD_DOUBLE_NULL), 0d);\n    }\n\n    // Tests average on columns with all null rows.\n    @Test\n    public void average_allNullColumns() {\n        TestHelper.populateAllNullRowsForNumericTesting(realm);\n\n        RealmQuery<NullTypes> query = realm.where(NullTypes.class);\n        assertEquals(0d, query.average(NullTypes.FIELD_INTEGER_NULL), 0d);\n        assertEquals(0d, query.average(NullTypes.FIELD_FLOAT_NULL), 0d);\n        assertEquals(0d, query.average(NullTypes.FIELD_DOUBLE_NULL), 0d);\n    }\n\n    // Tests average on columns with all non-null rows.\n    @Test\n    public void average_allNonNullRows() {\n        TestHelper.populateAllNonNullRowsForNumericTesting(realm);\n        RealmQuery<NullTypes> query = realm.where(NullTypes.class);\n\n        assertEquals(2.0, query.average(NullTypes.FIELD_INTEGER_NULL), 0d);\n        assertEquals(7.0 / 3, query.average(NullTypes.FIELD_FLOAT_NULL), 0.001d);\n        assertEquals(8.0 / 3, query.average(NullTypes.FIELD_DOUBLE_NULL), 0.001d);\n    }\n\n    // Tests average on columns with partial null rows.\n    @Test\n    public void average_partialNullRows() {\n        TestHelper.populatePartialNullRowsForNumericTesting(realm);\n        RealmQuery<NullTypes> query = realm.where(NullTypes.class);\n\n        assertEquals(3.5, query.average(NullTypes.FIELD_INTEGER_NULL), 0d);\n        assertEquals(4.5, query.average(NullTypes.FIELD_FLOAT_NULL), 0d);\n        assertEquals(5.5, query.average(NullTypes.FIELD_DOUBLE_NULL), 0d);\n    }\n\n    // Tests sum on empty columns.\n    @Test\n    public void sum_emptyColumns() {\n        RealmQuery<NullTypes> query = realm.where(NullTypes.class);\n        assertEquals(0, query.sum(NullTypes.FIELD_INTEGER_NULL).intValue());\n        assertEquals(0f, query.sum(NullTypes.FIELD_FLOAT_NULL).floatValue(), 0f);\n        assertEquals(0d, query.sum(NullTypes.FIELD_DOUBLE_NULL).doubleValue(), 0d);\n    }\n\n    // Tests sum on columns with all null rows.\n    @Test\n    public void sum_allNullColumns() {\n        TestHelper.populateAllNullRowsForNumericTesting(realm);\n\n        RealmQuery<NullTypes> query = realm.where(NullTypes.class);\n        assertEquals(0, query.sum(NullTypes.FIELD_INTEGER_NULL).intValue());\n        assertEquals(0f, query.sum(NullTypes.FIELD_FLOAT_NULL).floatValue(), 0f);\n        assertEquals(0d, query.sum(NullTypes.FIELD_DOUBLE_NULL).doubleValue(), 0d);\n    }\n\n    // Tests sum on columns with all non-null rows.\n    @Test\n    public void sum_allNonNullRows() {\n        TestHelper.populateAllNonNullRowsForNumericTesting(realm);\n        RealmQuery<NullTypes> query = realm.where(NullTypes.class);\n\n        assertEquals(6, query.sum(NullTypes.FIELD_INTEGER_NULL).intValue());\n        assertEquals(7f, query.sum(NullTypes.FIELD_FLOAT_NULL).floatValue(), 0f);\n        assertEquals(8d, query.sum(NullTypes.FIELD_DOUBLE_NULL).doubleValue(), 0d);\n    }\n\n    // Tests sum on columns with partial null rows.\n    @Test\n    public void sum_partialNullRows() {\n        TestHelper.populatePartialNullRowsForNumericTesting(realm);\n        RealmQuery<NullTypes> query = realm.where(NullTypes.class);\n\n        assertEquals(7, query.sum(NullTypes.FIELD_INTEGER_NULL).intValue());\n        assertEquals(9f, query.sum(NullTypes.FIELD_FLOAT_NULL).floatValue(), 0f);\n        assertEquals(11d, query.sum(NullTypes.FIELD_DOUBLE_NULL).doubleValue(), 0d);\n    }\n\n    @Test\n    public void count() {\n        populateTestRealm(realm, TEST_DATA_SIZE);\n        assertEquals(TEST_DATA_SIZE, realm.where(AllTypes.class).count());\n    }\n\n    // Verify that count correctly when using distinct.\n    // See https://github.com/realm/realm-java/issues/5958\n    @Test\n    public void distinctCount() {\n        realm.executeTransaction(r -> {\n            for (int i = 0; i < 5; i++) {\n                AllTypes obj = new AllTypes();\n                obj.setColumnString(\"Foo\");\n                realm.copyToRealm(obj);\n            }\n        });\n        assertEquals(1, realm.where(AllTypes.class).distinct(AllTypes.FIELD_STRING).count());\n    }\n\n    // Tests isNull on link's nullable field.\n    @Test\n    public void isNull_linkField() {\n        TestHelper.populateTestRealmForNullTests(realm);\n\n        // For the link with null value, query isNull on its fields should return true.\n        // 1 String\n        assertEquals(2, realm.where(NullTypes.class).isNull(\n                NullTypes.FIELD_OBJECT_NULL + \".\" + NullTypes.FIELD_STRING_NULL).count());\n        // 2 Bytes\n        assertEquals(2, realm.where(NullTypes.class).isNull(\n                NullTypes.FIELD_OBJECT_NULL + \".\" + NullTypes.FIELD_BYTES_NULL).count());\n        // 3 Boolean\n        assertEquals(2, realm.where(NullTypes.class).isNull(\n                NullTypes.FIELD_OBJECT_NULL + \".\" + NullTypes.FIELD_BOOLEAN_NULL).count());\n        // 4 Byte\n        assertEquals(2, realm.where(NullTypes.class).isNull(\n                NullTypes.FIELD_OBJECT_NULL + \".\" + NullTypes.FIELD_BYTE_NULL).count());\n        // 5 Short\n        assertEquals(2, realm.where(NullTypes.class).isNull(\n                NullTypes.FIELD_OBJECT_NULL + \".\" + NullTypes.FIELD_SHORT_NULL).count());\n        // 6 Integer\n        assertEquals(2, realm.where(NullTypes.class).isNull(\n                NullTypes.FIELD_OBJECT_NULL + \".\" + NullTypes.FIELD_INTEGER_NULL).count());\n        // 7 Long\n        assertEquals(2, realm.where(NullTypes.class).isNull(\n                NullTypes.FIELD_OBJECT_NULL + \".\" + NullTypes.FIELD_LONG_NULL).count());\n        // 8 Float\n        assertEquals(2, realm.where(NullTypes.class).isNull(\n                NullTypes.FIELD_OBJECT_NULL + \".\" + NullTypes.FIELD_FLOAT_NULL).count());\n        // 9 Double\n        assertEquals(2, realm.where(NullTypes.class).isNull(\n                NullTypes.FIELD_OBJECT_NULL + \".\" + NullTypes.FIELD_DOUBLE_NULL).count());\n        // 10 Date\n        assertEquals(2, realm.where(NullTypes.class).isNull(\n                NullTypes.FIELD_OBJECT_NULL + \".\" + NullTypes.FIELD_DATE_NULL).count());\n        // 11 Object\n        assertEquals(2, realm.where(NullTypes.class).isNull(\n                NullTypes.FIELD_OBJECT_NULL + \".\" + NullTypes.FIELD_OBJECT_NULL).count());\n    }\n\n    // Tests isNotNull on link's nullable field.\n    @Test\n    public void isNotNull_linkField() {\n        TestHelper.populateTestRealmForNullTests(realm);\n\n        // 1 String\n        assertEquals(1, realm.where(NullTypes.class).isNotNull(\n                NullTypes.FIELD_OBJECT_NULL + \".\" + NullTypes.FIELD_STRING_NULL).count());\n        // 2 Bytes\n        assertEquals(1, realm.where(NullTypes.class).isNotNull(\n                NullTypes.FIELD_OBJECT_NULL + \".\" + NullTypes.FIELD_BYTES_NULL).count());\n        // 3 Boolean\n        assertEquals(1, realm.where(NullTypes.class).isNotNull(\n                NullTypes.FIELD_OBJECT_NULL + \".\" + NullTypes.FIELD_BOOLEAN_NULL).count());\n        // 4 Byte\n        assertEquals(1, realm.where(NullTypes.class).isNotNull(\n                NullTypes.FIELD_OBJECT_NULL + \".\" + NullTypes.FIELD_BYTE_NULL).count());\n        // 5 Short\n        assertEquals(1, realm.where(NullTypes.class).isNotNull(\n                NullTypes.FIELD_OBJECT_NULL + \".\" + NullTypes.FIELD_SHORT_NULL).count());\n        // 6 Integer\n        assertEquals(1, realm.where(NullTypes.class).isNotNull(\n                NullTypes.FIELD_OBJECT_NULL + \".\" + NullTypes.FIELD_INTEGER_NULL).count());\n        // 7 Long\n        assertEquals(1, realm.where(NullTypes.class).isNotNull(\n                NullTypes.FIELD_OBJECT_NULL + \".\" + NullTypes.FIELD_LONG_NULL).count());\n        // 8 Float\n        assertEquals(1, realm.where(NullTypes.class).isNotNull(\n                NullTypes.FIELD_OBJECT_NULL + \".\" + NullTypes.FIELD_FLOAT_NULL).count());\n        // 9 Double\n        assertEquals(1, realm.where(NullTypes.class).isNotNull(\n                NullTypes.FIELD_OBJECT_NULL + \".\" + NullTypes.FIELD_DOUBLE_NULL).count());\n        // 10 Date\n        assertEquals(1, realm.where(NullTypes.class).isNotNull(\n                NullTypes.FIELD_OBJECT_NULL + \".\" + NullTypes.FIELD_DATE_NULL).count());\n        // 11 Object\n        assertEquals(1, realm.where(NullTypes.class).isNotNull(\n                NullTypes.FIELD_OBJECT_NULL + \".\" + NullTypes.FIELD_OBJECT_NULL).count());\n\n        assertEquals(1, realm.where(NullTypes.class).isNotNull(\n                NullTypes.FIELD_OBJECT_NULL + \".\" + NullTypes.FIELD_DECIMAL128_NULL).count());\n\n        assertEquals(1, realm.where(NullTypes.class).isNotNull(\n                NullTypes.FIELD_OBJECT_NULL + \".\" + NullTypes.FIELD_OBJECT_ID_NULL).count());\n    }\n\n    // Calling isNull on fields with the RealmList type will trigger an exception.\n    @Test\n    public void isNull_listFieldThrows() {\n        try {\n            realm.where(Owner.class).isNull(\"dogs\");\n            fail();\n        } catch (IllegalArgumentException expected) {\n            assertTrue(expected.getMessage().contains(\"Illegal Argument: Cannot compare linklist ('dogs') with NULL\"));\n        }\n\n        try {\n            realm.where(Cat.class).isNull(\"owner.dogs\");\n            fail();\n        } catch (IllegalArgumentException expected) {\n            assertTrue(expected.getMessage().contains(\"Illegal Argument: Cannot compare linklist ('owner.dogs') with NULL\"));\n        }\n    }\n\n    // Calling isNotNull on fields with the RealmList type will trigger an exception.\n    @Test\n    public void isNotNull_listFieldThrows() {\n        try {\n            realm.where(Owner.class).isNotNull(\"dogs\");\n            fail();\n        } catch (IllegalArgumentException expected) {\n            assertTrue(expected.getMessage().contains(\"Illegal Argument: Cannot compare linklist ('dogs') with NULL\"));\n        }\n\n        try {\n            realm.where(Cat.class).isNotNull(\"owner.dogs\");\n            fail();\n        } catch (IllegalArgumentException expected) {\n            assertTrue(expected.getMessage().contains(\"Illegal Argument: Cannot compare linklist ('owner.dogs') with NULL\"));\n        }\n    }\n\n    @Test\n    public void isValid_tableQuery() {\n        final RealmQuery<AllTypes> query = realm.where(AllTypes.class);\n\n        assertTrue(query.isValid());\n        populateTestRealm(realm, 1);\n        // Still valid if result changed.\n        assertTrue(query.isValid());\n\n        realm.close();\n        assertFalse(query.isValid());\n    }\n\n    @Test\n    public void isValid_tableViewQuery() {\n        populateTestRealm();\n        final RealmQuery<AllTypes> query = realm.where(AllTypes.class).greaterThan(AllTypes.FIELD_FLOAT, 5f)\n                .findAll().where();\n        assertTrue(query.isValid());\n\n        populateTestRealm(realm, 1);\n        // Still valid if table view changed.\n        assertTrue(query.isValid());\n\n        realm.close();\n        assertFalse(query.isValid());\n    }\n\n    // Test for https://github.com/realm/realm-java/issues/1905\n    @Test\n    public void resultOfTableViewQuery() {\n        populateTestRealm();\n\n        final RealmResults<AllTypes> results = realm.where(AllTypes.class).equalTo(AllTypes.FIELD_LONG, 3L).findAll();\n        assertEquals(1, results.size());\n        assertEquals(\"test data 3\", results.first().getColumnString());\n\n        final RealmQuery<AllTypes> tableViewQuery = results.where();\n        assertEquals(\"test data 3\", tableViewQuery.findAll().first().getColumnString());\n        assertEquals(\"test data 3\", tableViewQuery.findFirst().getColumnString());\n    }\n\n    @Test\n    public void isValid_linkViewQuery() {\n        populateTestRealm(realm, 1);\n        final RealmList<Dog> list = realm.where(AllTypes.class).findFirst().getColumnRealmList();\n        final RealmQuery<Dog> query = list.where();\n        final long listLength = query.count();\n        assertTrue(query.isValid());\n\n        realm.beginTransaction();\n        final Dog dog = realm.createObject(Dog.class);\n        dog.setName(\"Dog\");\n        list.add(dog);\n        realm.commitTransaction();\n\n        // Still valid if base view changed.\n        assertEquals(listLength + 1, query.count());\n        assertTrue(query.isValid());\n\n        realm.close();\n        assertFalse(query.isValid());\n    }\n\n    @Test\n    public void isValid_removedParent() {\n        populateTestRealm(realm, 1);\n        final AllTypes obj = realm.where(AllTypes.class).findFirst();\n        final RealmQuery<Dog> query = obj.getColumnRealmList().where();\n        assertTrue(query.isValid());\n\n        realm.beginTransaction();\n        obj.deleteFromRealm();\n        realm.commitTransaction();\n\n        // Invalid if parent has been removed.\n        assertFalse(query.isValid());\n    }\n\n    @Test\n    public void isEmpty() throws IOException {\n        createIsEmptyDataSet(realm);\n        for (RealmFieldType type : SUPPORTED_IS_EMPTY_TYPES) {\n            switch (type) {\n                case STRING:\n                    assertEquals(2, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_STRING).count());\n                    break;\n                case BINARY:\n                    assertEquals(2, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_BINARY).count());\n                    break;\n                case LIST:\n                    assertEquals(1, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_LIST).count());\n                    break;\n                case OBJECT:\n                    assertEquals(1, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_OBJECT).count());\n                    break;\n                case INTEGER_LIST:\n                    assertEquals(3, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_INTEGER_LIST).count());\n                    break;\n                case BOOLEAN_LIST:\n                    assertEquals(3, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_BOOLEAN_LIST).count());\n                    break;\n                case STRING_LIST:\n                    assertEquals(3, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_STRING_LIST).count());\n                    break;\n                case BINARY_LIST:\n                    assertEquals(3, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_BINARY_LIST).count());\n                    break;\n                case DATE_LIST:\n                    assertEquals(3, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_DATE_LIST).count());\n                    break;\n                case FLOAT_LIST:\n                    assertEquals(3, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_FLOAT_LIST).count());\n                    break;\n                case DOUBLE_LIST:\n                    assertEquals(3, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_DOUBLE_LIST).count());\n                    break;\n                case DECIMAL128_LIST:\n                    assertEquals(3, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_DECIMAL128_LIST).count());\n                    break;\n                case OBJECT_ID_LIST:\n                    assertEquals(3, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_OBJECT_ID_LIST).count());\n                    break;\n                case UUID_LIST:\n                    assertEquals(3, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_UUID_LIST).count());\n                    break;\n                case MIXED_LIST:\n                    assertEquals(3, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_REALM_ANY_LIST).count());\n                    break;\n                case LINKING_OBJECTS:\n                    // Row 2 does not have a backlink\n                    assertEquals(1, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_OBJECT).count());\n                    assertEquals(1, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_LIST).count());\n                    break;\n                case STRING_TO_MIXED_MAP:\n                    assertEquals(3, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_REALM_ANY_DICTIONARY).count());\n                    break;\n                case STRING_TO_BOOLEAN_MAP:\n                    assertEquals(3, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_BOOLEAN_DICTIONARY).count());\n                    break;\n                case STRING_TO_STRING_MAP:\n                    assertEquals(3, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_STRING_DICTIONARY).count());\n                    break;\n                case STRING_TO_INTEGER_MAP:\n                    assertEquals(3, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_INTEGER_DICTIONARY).count());\n                    break;\n                case STRING_TO_FLOAT_MAP:\n                    assertEquals(3, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_FLOAT_DICTIONARY).count());\n                    break;\n                case STRING_TO_DOUBLE_MAP:\n                    assertEquals(3, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_DOUBLE_DICTIONARY).count());\n                    break;\n                case STRING_TO_BINARY_MAP:\n                    assertEquals(3, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_BINARY_DICTIONARY).count());\n                    break;\n                case STRING_TO_DATE_MAP:\n                    assertEquals(3, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_DATE_DICTIONARY).count());\n                    break;\n                case STRING_TO_OBJECT_ID_MAP:\n                    assertEquals(3, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_OBJECT_ID_DICTIONARY).count());\n                    break;\n                case STRING_TO_UUID_MAP:\n                    assertEquals(3, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_UUID_DICTIONARY).count());\n                    break;\n                case STRING_TO_DECIMAL128_MAP:\n                    assertEquals(3, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_DECIMAL128_DICTIONARY).count());\n                    break;\n                case STRING_TO_LINK_MAP:\n                    assertEquals(3, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_LINK_DICTIONARY).count());\n                    break;\n                case MIXED_SET:\n                    assertEquals(3, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_REALM_ANY_SET).count());\n                    break;\n                case BOOLEAN_SET:\n                    assertEquals(3, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_BOOLEAN_SET).count());\n                    break;\n                case STRING_SET:\n                    assertEquals(3, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_STRING_SET).count());\n                    break;\n                case INTEGER_SET:\n                    assertEquals(3, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_INTEGER_SET).count());\n                    break;\n                case FLOAT_SET:\n                    assertEquals(3, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_FLOAT_SET).count());\n                    break;\n                case DOUBLE_SET:\n                    assertEquals(3, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_DOUBLE_SET).count());\n                    break;\n                case BINARY_SET:\n                    assertEquals(3, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_BINARY_SET).count());\n                    break;\n                case DATE_SET:\n                    assertEquals(3, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_DATE_SET).count());\n                    break;\n                case OBJECT_ID_SET:\n                    assertEquals(3, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_OBJECT_ID_SET).count());\n                    break;\n                case UUID_SET:\n                    assertEquals(3, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_UUID_SET).count());\n                    break;\n                case DECIMAL128_SET:\n                    assertEquals(3, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_DECIMAL128_SET).count());\n                    break;\n                case LINK_SET:\n                    assertEquals(3, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_LINK_SET).count());\n                    break;\n                default:\n                    fail(\"Unknown type: \" + type);\n            }\n        }\n    }\n\n    @Test\n    public void isEmpty_acrossLink() {\n        createIsEmptyDataSet(realm);\n        for (RealmFieldType type : SUPPORTED_IS_EMPTY_TYPES) {\n            switch (type) {\n                case STRING:\n                    assertEquals(1, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_OBJECT + \".\" + AllJavaTypesUnsupportedTypes.FIELD_STRING).count());\n                    break;\n                case BINARY:\n                    assertEquals(1, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_OBJECT + \".\" + AllJavaTypesUnsupportedTypes.FIELD_BINARY).count());\n                    break;\n                case LIST:\n                    // Row 0: Backlink list to row 1, list to row 0; included\n                    // Row 1: Backlink list to row 2, list to row 1; included\n                    // Row 2: No backlink list; not included\n                    assertEquals(1, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_OBJECT + \".\" + AllJavaTypesUnsupportedTypes.FIELD_LIST).count());\n                    break;\n                case LINKING_OBJECTS:\n                    assertEquals(0, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_OBJECT + \".\" + AllJavaTypesUnsupportedTypes.FIELD_LO_LIST).count());\n\n                    // Row 0: Link to row 0, backlink to row 0; not included\n                    // Row 1: Link to row 1m backlink to row 1; not included\n                    // Row 2: Empty link; not included\n                    assertEquals(0, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_OBJECT + \".\" + AllJavaTypesUnsupportedTypes.FIELD_LO_OBJECT).count());\n                    break;\n                case OBJECT:\n                    assertEquals(0, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_OBJECT + \".\" + AllJavaTypesUnsupportedTypes.FIELD_OBJECT).count());\n                    break;\n                case INTEGER_LIST:\n                    assertEquals(3, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_OBJECT + \".\" + AllJavaTypesUnsupportedTypes.FIELD_INTEGER_LIST).count());\n                    break;\n                case BOOLEAN_LIST:\n                    assertEquals(3, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_OBJECT + \".\" + AllJavaTypesUnsupportedTypes.FIELD_BOOLEAN_LIST).count());\n                    break;\n                case STRING_LIST:\n                    assertEquals(3, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_OBJECT + \".\" + AllJavaTypesUnsupportedTypes.FIELD_STRING_LIST).count());\n                    break;\n                case BINARY_LIST:\n                    assertEquals(3, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_OBJECT + \".\" + AllJavaTypesUnsupportedTypes.FIELD_BINARY_LIST).count());\n                    break;\n                case DATE_LIST:\n                    assertEquals(3, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_OBJECT + \".\" + AllJavaTypesUnsupportedTypes.FIELD_DATE_LIST).count());\n                    break;\n                case FLOAT_LIST:\n                    assertEquals(3, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_OBJECT + \".\" + AllJavaTypesUnsupportedTypes.FIELD_FLOAT_LIST).count());\n                    break;\n                case DOUBLE_LIST:\n                    assertEquals(3, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_OBJECT + \".\" + AllJavaTypesUnsupportedTypes.FIELD_DOUBLE_LIST).count());\n                    break;\n                case DECIMAL128_LIST:\n                    assertEquals(3, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_OBJECT + \".\" + AllJavaTypesUnsupportedTypes.FIELD_DECIMAL128_LIST).count());\n                    break;\n                case OBJECT_ID_LIST:\n                    assertEquals(3, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_OBJECT + \".\" + AllJavaTypesUnsupportedTypes.FIELD_OBJECT_ID_LIST).count());\n                    break;\n                case UUID_LIST:\n                    assertEquals(3, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_OBJECT + \".\" + AllJavaTypesUnsupportedTypes.FIELD_UUID_LIST).count());\n                    break;\n                case MIXED_LIST:\n                    assertEquals(3, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_OBJECT + \".\" + AllJavaTypesUnsupportedTypes.FIELD_REALM_ANY_LIST).count());\n                    break;\n                case STRING_TO_MIXED_MAP:\n                    assertEquals(3, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_OBJECT + \".\" + AllJavaTypesUnsupportedTypes.FIELD_REALM_ANY_DICTIONARY).count());\n                    break;\n                case STRING_TO_BOOLEAN_MAP:\n                    assertEquals(3, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_OBJECT + \".\" + AllJavaTypesUnsupportedTypes.FIELD_BOOLEAN_DICTIONARY).count());\n                    break;\n                case STRING_TO_STRING_MAP:\n                    assertEquals(3, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_OBJECT + \".\" + AllJavaTypesUnsupportedTypes.FIELD_STRING_DICTIONARY).count());\n                    break;\n                case STRING_TO_INTEGER_MAP:\n                    assertEquals(3, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_OBJECT + \".\" + AllJavaTypesUnsupportedTypes.FIELD_INTEGER_DICTIONARY).count());\n                    break;\n                case STRING_TO_FLOAT_MAP:\n                    assertEquals(3, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_OBJECT + \".\" + AllJavaTypesUnsupportedTypes.FIELD_FLOAT_DICTIONARY).count());\n                    break;\n                case STRING_TO_DOUBLE_MAP:\n                    assertEquals(3, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_OBJECT + \".\" + AllJavaTypesUnsupportedTypes.FIELD_DOUBLE_DICTIONARY).count());\n                    break;\n                case STRING_TO_BINARY_MAP:\n                    assertEquals(3, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_OBJECT + \".\" + AllJavaTypesUnsupportedTypes.FIELD_BINARY_DICTIONARY).count());\n                    break;\n                case STRING_TO_DATE_MAP:\n                    assertEquals(3, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_OBJECT + \".\" + AllJavaTypesUnsupportedTypes.FIELD_DATE_DICTIONARY).count());\n                    break;\n                case STRING_TO_OBJECT_ID_MAP:\n                    assertEquals(3, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_OBJECT + \".\" + AllJavaTypesUnsupportedTypes.FIELD_OBJECT_ID_DICTIONARY).count());\n                    break;\n                case STRING_TO_UUID_MAP:\n                    assertEquals(3, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_OBJECT + \".\" + AllJavaTypesUnsupportedTypes.FIELD_UUID_DICTIONARY).count());\n                    break;\n                case STRING_TO_DECIMAL128_MAP:\n                    assertEquals(3, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_OBJECT + \".\" + AllJavaTypesUnsupportedTypes.FIELD_DECIMAL128_DICTIONARY).count());\n                    break;\n                case STRING_TO_LINK_MAP:\n                    assertEquals(2, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_OBJECT + \".\" + AllJavaTypesUnsupportedTypes.FIELD_LINK_DICTIONARY).count());\n                    break;\n                case MIXED_SET:\n                    assertEquals(3, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_OBJECT + \".\" + AllJavaTypesUnsupportedTypes.FIELD_REALM_ANY_SET).count());\n                    break;\n                case BOOLEAN_SET:\n                    assertEquals(3, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_OBJECT + \".\" + AllJavaTypesUnsupportedTypes.FIELD_BOOLEAN_SET).count());\n                    break;\n                case STRING_SET:\n                    assertEquals(3, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_OBJECT + \".\" + AllJavaTypesUnsupportedTypes.FIELD_STRING_SET).count());\n                    break;\n                case INTEGER_SET:\n                    assertEquals(3, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_OBJECT + \".\" + AllJavaTypesUnsupportedTypes.FIELD_INTEGER_SET).count());\n                    break;\n                case FLOAT_SET:\n                    assertEquals(3, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_OBJECT + \".\" + AllJavaTypesUnsupportedTypes.FIELD_FLOAT_SET).count());\n                    break;\n                case DOUBLE_SET:\n                    assertEquals(3, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_OBJECT + \".\" + AllJavaTypesUnsupportedTypes.FIELD_DOUBLE_SET).count());\n                    break;\n                case BINARY_SET:\n                    assertEquals(3, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_OBJECT + \".\" + AllJavaTypesUnsupportedTypes.FIELD_BINARY_SET).count());\n                    break;\n                case DATE_SET:\n                    assertEquals(3, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_OBJECT + \".\" + AllJavaTypesUnsupportedTypes.FIELD_DATE_SET).count());\n                    break;\n                case OBJECT_ID_SET:\n                    assertEquals(3, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_OBJECT + \".\" + AllJavaTypesUnsupportedTypes.FIELD_OBJECT_ID_SET).count());\n                    break;\n                case UUID_SET:\n                    assertEquals(3, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_OBJECT + \".\" + AllJavaTypesUnsupportedTypes.FIELD_UUID_SET).count());\n                    break;\n                case DECIMAL128_SET:\n                    assertEquals(3, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_OBJECT + \".\" + AllJavaTypesUnsupportedTypes.FIELD_DECIMAL128_SET).count());\n                    break;\n                case LINK_SET:\n                    assertEquals(2, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_OBJECT + \".\" + AllJavaTypesUnsupportedTypes.FIELD_LINK_SET).count());\n                    break;\n                default:\n                    fail(\"Unknown type: \" + type);\n            }\n        }\n    }\n\n    @Test\n    public void isEmpty_illegalFieldTypeThrows() {\n        for (RealmFieldType type : NOT_SUPPORTED_IS_EMPTY_TYPES) {\n            try {\n                switch (type) {\n                    case INTEGER:\n                        realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_LONG).findAll();\n                        break;\n                    case FLOAT:\n                        realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_FLOAT).findAll();\n                        break;\n                    case DOUBLE:\n                        realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_DOUBLE).findAll();\n                        break;\n                    case BOOLEAN:\n                        realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_BOOLEAN).findAll();\n                        break;\n                    case DATE:\n                        realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_DATE).findAll();\n                        break;\n                    case DECIMAL128:\n                        realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_DECIMAL128).findAll();\n                        break;\n                    case OBJECT_ID:\n                        realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_OBJECT_ID).findAll();\n                        break;\n                    case UUID:\n                        realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_UUID).findAll();\n                        break;\n                    case MIXED:\n                        realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_REALM_ANY).findAll();\n                        break;\n                    default:\n                        fail(\"Unknown type: \" + type);\n                }\n                fail(type + \" should throw an exception\");\n            } catch (IllegalArgumentException ignored) {\n            }\n        }\n    }\n\n    @Test\n    public void isEmpty_invalidFieldNameThrows() {\n        String[] fieldNames = new String[] {null, \"\", \"foo\", AllJavaTypesUnsupportedTypes.FIELD_OBJECT + \".foo\"};\n\n        for (String fieldName : fieldNames) {\n            try {\n                realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(fieldName);\n                fail();\n            } catch (IllegalArgumentException ignored) {\n            }\n        }\n    }\n\n    @Test\n    public void isEmpty_acrossLink_wrongTypeThrows() {\n        for (RealmFieldType type : RealmFieldType.values()) {\n            if (SUPPORTED_IS_EMPTY_TYPES.contains(type)) {\n                continue;\n            }\n\n            RealmQuery<Owner> query = realm.where(Owner.class);\n            try {\n                query.isEmpty(Owner.FIELD_CAT + \".\" + Cat.FIELD_AGE);\n                fail();\n            } catch (IllegalArgumentException expected) {\n                assertTrue(expected.getMessage().contains(\"Illegal Argument: Operation '@count' is not supported on property of type\"));\n            }\n        }\n    }\n\n    @Test\n    public void isNotEmpty() {\n        createIsNotEmptyDataSet(realm);\n        for (RealmFieldType type : SUPPORTED_IS_NOT_EMPTY_TYPES) {\n            switch (type) {\n                case STRING:\n                    assertEquals(1, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_STRING).count());\n                    break;\n                case BINARY:\n                    assertEquals(1, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_BINARY).count());\n                    break;\n                case LIST:\n                    assertEquals(1, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_LIST).count());\n                    break;\n                case LINKING_OBJECTS:\n                    assertEquals(2, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_OBJECT).count());\n                    assertEquals(1, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_LO_LIST).count());\n                    break;\n                case OBJECT:\n                    assertEquals(2, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_OBJECT).count());\n                    break;\n                case INTEGER_LIST:\n                    assertEquals(1, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_INTEGER_LIST).count());\n                    break;\n                case BOOLEAN_LIST:\n                    assertEquals(1, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_BOOLEAN_LIST).count());\n                    break;\n                case STRING_LIST:\n                    assertEquals(1, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_STRING_LIST).count());\n                    break;\n                case BINARY_LIST:\n                    assertEquals(1, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_BINARY_LIST).count());\n                    break;\n                case DATE_LIST:\n                    assertEquals(1, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_DATE_LIST).count());\n                    break;\n                case FLOAT_LIST:\n                    assertEquals(1, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_FLOAT_LIST).count());\n                    break;\n                case DOUBLE_LIST:\n                    assertEquals(1, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_DOUBLE_LIST).count());\n                    break;\n                case DECIMAL128_LIST:\n                    assertEquals(1, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_DECIMAL128_LIST).count());\n                    break;\n                case OBJECT_ID_LIST:\n                    assertEquals(1, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_OBJECT_ID_LIST).count());\n                    break;\n                case UUID_LIST:\n                    assertEquals(1, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_UUID_LIST).count());\n                    break;\n                case MIXED_LIST:\n                    assertEquals(1, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_REALM_ANY_LIST).count());\n                    break;\n                case STRING_TO_MIXED_MAP:\n                    assertEquals(1, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_REALM_ANY_DICTIONARY).count());\n                    break;\n                case STRING_TO_BOOLEAN_MAP:\n                    assertEquals(1, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_BOOLEAN_DICTIONARY).count());\n                    break;\n                case STRING_TO_STRING_MAP:\n                    assertEquals(1, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_STRING_DICTIONARY).count());\n                    break;\n                case STRING_TO_INTEGER_MAP:\n                    assertEquals(1, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_INTEGER_DICTIONARY).count());\n                    break;\n                case STRING_TO_FLOAT_MAP:\n                    assertEquals(1, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_FLOAT_DICTIONARY).count());\n                    break;\n                case STRING_TO_DOUBLE_MAP:\n                    assertEquals(1, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_DOUBLE_DICTIONARY).count());\n                    break;\n                case STRING_TO_BINARY_MAP:\n                    assertEquals(1, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_BINARY_DICTIONARY).count());\n                    break;\n                case STRING_TO_DATE_MAP:\n                    assertEquals(1, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_DATE_DICTIONARY).count());\n                    break;\n                case STRING_TO_OBJECT_ID_MAP:\n                    assertEquals(1, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_OBJECT_ID_DICTIONARY).count());\n                    break;\n                case STRING_TO_UUID_MAP:\n                    assertEquals(1, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_UUID_DICTIONARY).count());\n                    break;\n                case STRING_TO_DECIMAL128_MAP:\n                    assertEquals(1, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_DECIMAL128_DICTIONARY).count());\n                    break;\n                case STRING_TO_LINK_MAP:\n                    assertEquals(1, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_LINK_DICTIONARY).count());\n                    break;\n                case MIXED_SET:\n                    assertEquals(1, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_REALM_ANY_SET).count());\n                    break;\n                case BOOLEAN_SET:\n                    assertEquals(1, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_BOOLEAN_SET).count());\n                    break;\n                case STRING_SET:\n                    assertEquals(1, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_STRING_SET).count());\n                    break;\n                case INTEGER_SET:\n                    assertEquals(1, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_INTEGER_SET).count());\n                    break;\n                case FLOAT_SET:\n                    assertEquals(1, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_FLOAT_SET).count());\n                    break;\n                case DOUBLE_SET:\n                    assertEquals(1, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_DOUBLE_SET).count());\n                    break;\n                case BINARY_SET:\n                    assertEquals(1, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_BINARY_SET).count());\n                    break;\n                case DATE_SET:\n                    assertEquals(1, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_DATE_SET).count());\n                    break;\n                case OBJECT_ID_SET:\n                    assertEquals(1, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_OBJECT_ID_SET).count());\n                    break;\n                case UUID_SET:\n                    assertEquals(1, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_UUID_SET).count());\n                    break;\n                case DECIMAL128_SET:\n                    assertEquals(1, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_DECIMAL128_SET).count());\n                    break;\n                case LINK_SET:\n                    assertEquals(1, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_LINK_SET).count());\n                    break;\n                default:\n                    fail(\"Unknown type: \" + type);\n            }\n        }\n    }\n\n    @Test\n    public void isNotEmpty_acrossLink() {\n        createIsNotEmptyDataSet(realm);\n        for (RealmFieldType type : SUPPORTED_IS_NOT_EMPTY_TYPES) {\n            switch (type) {\n                case STRING:\n                    assertEquals(1, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_OBJECT + \".\" + AllJavaTypesUnsupportedTypes.FIELD_STRING).count());\n                    break;\n                case BINARY:\n                    assertEquals(1, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_OBJECT + \".\" + AllJavaTypesUnsupportedTypes.FIELD_BINARY).count());\n                    break;\n                case LIST:\n                    assertEquals(1, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_OBJECT + \".\" + AllJavaTypesUnsupportedTypes.FIELD_LIST).count());\n                    break;\n                case LINKING_OBJECTS:\n                    assertEquals(1, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_OBJECT + \".\" + AllJavaTypesUnsupportedTypes.FIELD_LO_LIST).count());\n                    assertEquals(2, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_OBJECT + \".\" + AllJavaTypesUnsupportedTypes.FIELD_LO_OBJECT).count());\n                    break;\n                case OBJECT:\n                    assertEquals(0, realm.where(AllJavaTypesUnsupportedTypes.class).isEmpty(AllJavaTypesUnsupportedTypes.FIELD_OBJECT).count());\n                    break;\n                case INTEGER_LIST:\n                    assertEquals(1, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_INTEGER_LIST).count());\n                    break;\n                case BOOLEAN_LIST:\n                    assertEquals(1, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_BOOLEAN_LIST).count());\n                    break;\n                case STRING_LIST:\n                    assertEquals(1, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_STRING_LIST).count());\n                    break;\n                case BINARY_LIST:\n                    assertEquals(1, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_BINARY_LIST).count());\n                    break;\n                case DATE_LIST:\n                    assertEquals(1, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_DATE_LIST).count());\n                    break;\n                case FLOAT_LIST:\n                    assertEquals(1, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_FLOAT_LIST).count());\n                    break;\n                case DOUBLE_LIST:\n                    assertEquals(1, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_DOUBLE_LIST).count());\n                    break;\n                case DECIMAL128_LIST:\n                    assertEquals(1, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_DECIMAL128_LIST).count());\n                    break;\n                case OBJECT_ID_LIST:\n                    assertEquals(1, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_OBJECT_ID_LIST).count());\n                    break;\n                case UUID_LIST:\n                    assertEquals(1, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_UUID_LIST).count());\n                    break;\n                case MIXED_LIST:\n                    assertEquals(1, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_REALM_ANY_LIST).count());\n                    break;\n                case STRING_TO_MIXED_MAP:\n                    assertEquals(1, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_REALM_ANY_DICTIONARY).count());\n                    break;\n                case STRING_TO_BOOLEAN_MAP:\n                    assertEquals(1, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_BOOLEAN_DICTIONARY).count());\n                    break;\n                case STRING_TO_STRING_MAP:\n                    assertEquals(1, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_STRING_DICTIONARY).count());\n                    break;\n                case STRING_TO_INTEGER_MAP:\n                    assertEquals(1, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_INTEGER_DICTIONARY).count());\n                    break;\n                case STRING_TO_FLOAT_MAP:\n                    assertEquals(1, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_FLOAT_DICTIONARY).count());\n                    break;\n                case STRING_TO_DOUBLE_MAP:\n                    assertEquals(1, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_DOUBLE_DICTIONARY).count());\n                    break;\n                case STRING_TO_BINARY_MAP:\n                    assertEquals(1, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_BINARY_DICTIONARY).count());\n                    break;\n                case STRING_TO_DATE_MAP:\n                    assertEquals(1, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_DATE_DICTIONARY).count());\n                    break;\n                case STRING_TO_OBJECT_ID_MAP:\n                    assertEquals(1, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_OBJECT_ID_DICTIONARY).count());\n                    break;\n                case STRING_TO_UUID_MAP:\n                    assertEquals(1, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_UUID_DICTIONARY).count());\n                    break;\n                case STRING_TO_DECIMAL128_MAP:\n                    assertEquals(1, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_DECIMAL128_DICTIONARY).count());\n                    break;\n                case STRING_TO_LINK_MAP:\n                    assertEquals(1, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_LINK_DICTIONARY).count());\n                    break;\n                case MIXED_SET:\n                    assertEquals(1, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_REALM_ANY_SET).count());\n                    break;\n                case BOOLEAN_SET:\n                    assertEquals(1, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_BOOLEAN_SET).count());\n                    break;\n                case STRING_SET:\n                    assertEquals(1, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_STRING_SET).count());\n                    break;\n                case INTEGER_SET:\n                    assertEquals(1, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_INTEGER_SET).count());\n                    break;\n                case FLOAT_SET:\n                    assertEquals(1, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_FLOAT_SET).count());\n                    break;\n                case DOUBLE_SET:\n                    assertEquals(1, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_DOUBLE_SET).count());\n                    break;\n                case BINARY_SET:\n                    assertEquals(1, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_BINARY_SET).count());\n                    break;\n                case DATE_SET:\n                    assertEquals(1, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_DATE_SET).count());\n                    break;\n                case OBJECT_ID_SET:\n                    assertEquals(1, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_OBJECT_ID_SET).count());\n                    break;\n                case UUID_SET:\n                    assertEquals(1, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_UUID_SET).count());\n                    break;\n                case DECIMAL128_SET:\n                    assertEquals(1, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_DECIMAL128_SET).count());\n                    break;\n                case LINK_SET:\n                    assertEquals(1, realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_LINK_SET).count());\n                    break;\n                default:\n                    fail(\"Unknown type: \" + type);\n            }\n        }\n    }\n\n    @Test\n    public void isNotEmpty_illegalFieldTypeThrows() {\n        for (RealmFieldType type : NOT_SUPPORTED_IS_NOT_EMPTY_TYPES) {\n            try {\n                switch (type) {\n                    case INTEGER:\n                        realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_LONG).findAll();\n                        break;\n                    case FLOAT:\n                        realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_FLOAT).findAll();\n                        break;\n                    case DOUBLE:\n                        realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_DOUBLE).findAll();\n                        break;\n                    case BOOLEAN:\n                        realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_BOOLEAN).findAll();\n                        break;\n                    case DATE:\n                        realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_DATE).findAll();\n                        break;\n                    case DECIMAL128:\n                        realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_DECIMAL128).findAll();\n                        break;\n                    case OBJECT_ID:\n                        realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_OBJECT_ID).findAll();\n                        break;\n                    case UUID:\n                        realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_UUID).findAll();\n                        break;\n                    case MIXED:\n                        realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(AllJavaTypesUnsupportedTypes.FIELD_REALM_ANY).findAll();\n                        break;\n                    default:\n                        fail(\"Unknown type: \" + type);\n                }\n                fail(type + \" should throw an exception\");\n            } catch (IllegalArgumentException ignored) {\n            }\n        }\n    }\n\n    @Test\n    public void isNotEmpty_invalidFieldNameThrows() {\n        String[] fieldNames = new String[] {null, \"\", \"foo\", AllJavaTypesUnsupportedTypes.FIELD_OBJECT + \".foo\"};\n\n        for (String fieldName : fieldNames) {\n            try {\n                realm.where(AllJavaTypesUnsupportedTypes.class).isNotEmpty(fieldName).findAll();\n                fail();\n            } catch (IllegalArgumentException ignored) {\n            }\n        }\n    }\n\n    // Tests that deep queries work on a lot of data.\n    @Test\n    public void deepLinkListQuery() {\n        realm.executeTransaction(new Realm.Transaction() {\n            @Override\n            public void execute(Realm realm) {\n\n                // Crashes with i == 1000, 500, 100, 89, 85, 84.\n                // Doesn't crash for i == 10, 50, 75, 82, 83.\n                for (int i = 0; i < 84; i++) {\n                    AllJavaTypesUnsupportedTypes obj = realm.createObject(AllJavaTypesUnsupportedTypes.class, i + 1);\n                    obj.setFieldBoolean(i % 2 == 0);\n                    obj.setFieldObject(obj);\n\n                    RealmResults<AllJavaTypesUnsupportedTypes> items = realm.where(AllJavaTypesUnsupportedTypes.class).findAll();\n                    RealmList<AllJavaTypesUnsupportedTypes> fieldList = obj.getFieldList();\n                    for (int j = 0; j < items.size(); j++) {\n                        fieldList.add(items.get(j));\n                    }\n                }\n            }\n        });\n\n        for (int i = 0; i < 4; i++) {\n            realm.where(AllJavaTypesUnsupportedTypes.class).equalTo(\n                    AllJavaTypesUnsupportedTypes.FIELD_LIST + \".\" + AllJavaTypesUnsupportedTypes.FIELD_OBJECT + \".\" + AllJavaTypesUnsupportedTypes.FIELD_BOOLEAN, true)\n                    .findAll();\n        }\n    }\n\n    @Test\n    public void sort_onSubObjectField() {\n        populateTestRealm(realm, TEST_DATA_SIZE);\n        RealmResults<AllTypes> results = realm.where(AllTypes.class)\n                .sort(AllTypes.FIELD_REALMOBJECT + \".\" + Dog.FIELD_AGE)\n                .findAll();\n        assertEquals(0, results.get(0).getColumnRealmObject().getAge());\n        assertEquals(TEST_DATA_SIZE - 1, results.get(TEST_DATA_SIZE - 1).getColumnRealmObject().getAge());\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void sort_async_onSubObjectField() {\n        Realm realm = looperThread.getRealm();\n        populateTestRealm(realm, TEST_DATA_SIZE);\n        RealmResults<AllTypes> results = realm.where(AllTypes.class)\n                .sort(AllTypes.FIELD_REALMOBJECT + \".\" + Dog.FIELD_AGE)\n                .findAllAsync();\n        looperThread.keepStrongReference(results);\n        results.addChangeListener(new RealmChangeListener<RealmResults<AllTypes>>() {\n            @Override\n            public void onChange(RealmResults<AllTypes> results) {\n                assertEquals(0, results.get(0).getColumnRealmObject().getAge());\n                assertEquals(TEST_DATA_SIZE - 1, results.get(TEST_DATA_SIZE - 1).getColumnRealmObject().getAge());\n                looperThread.testComplete();\n            }\n        });\n    }\n\n    @Test\n    public void findAll_indexedCaseInsensitiveFields() {\n        // Catches https://github.com/realm/realm-java/issues/4788\n        realm.beginTransaction();\n        realm.createObject(IndexedFields.class, new ObjectId()).indexedString = \"ROVER\";\n        realm.createObject(IndexedFields.class, new ObjectId()).indexedString = \"Rover\";\n        realm.commitTransaction();\n\n        RealmResults<IndexedFields> results = realm.where(IndexedFields.class)\n                .equalTo(IndexedFields.FIELD_INDEXED_STRING, \"rover\", Case.INSENSITIVE)\n                .findAll();\n        assertEquals(2, results.size());\n    }\n\n    @Test\n    public void sort_listOnSubObjectField() {\n        String[] fieldNames = new String[2];\n        fieldNames[0] = AllTypes.FIELD_REALMOBJECT + \".\" + Dog.FIELD_AGE;\n        fieldNames[1] = AllTypes.FIELD_REALMOBJECT + \".\" + Dog.FIELD_AGE;\n\n        Sort[] sorts = new Sort[2];\n        sorts[0] = Sort.ASCENDING;\n        sorts[1] = Sort.ASCENDING;\n\n        populateTestRealm(realm, TEST_DATA_SIZE);\n        RealmResults<AllTypes> results = realm.where(AllTypes.class)\n                .sort(fieldNames, sorts)\n                .findAll();\n        assertEquals(0, results.get(0).getColumnRealmObject().getAge());\n        assertEquals(TEST_DATA_SIZE - 1, results.get(TEST_DATA_SIZE - 1).getColumnRealmObject().getAge());\n    }\n\n    private void populateForDistinct(Realm realm, long numberOfBlocks, long numberOfObjects, boolean withNull) {\n        realm.beginTransaction();\n        for (int i = 0; i < numberOfObjects * numberOfBlocks; i++) {\n            for (int j = 0; j < numberOfBlocks; j++) {\n                AnnotationIndexTypes obj = realm.createObject(AnnotationIndexTypes.class);\n                obj.setIndexBoolean(j % 2 == 0);\n                obj.setIndexLong(j);\n                obj.setIndexDate(withNull ? null : new Date(1000L * j));\n                obj.setIndexString(withNull ? null : \"Test \" + j);\n                obj.setNotIndexBoolean(j % 2 == 0);\n                obj.setNotIndexLong(j);\n                obj.setNotIndexDate(withNull ? null : new Date(1000L * j));\n                obj.setNotIndexString(withNull ? null : \"Test \" + j);\n                obj.setFieldObject(obj);\n            }\n        }\n        realm.commitTransaction();\n    }\n\n    private void populateForDistinctAllTypes(Realm realm, long numberOfBlocks, long numberOfObjects) {\n        realm.beginTransaction();\n        for (int i = 0; i < numberOfBlocks; i++) {\n            Dog dog = realm.createObject(Dog.class);\n            for (int j = 0; j < numberOfObjects; j++) {\n                AllTypes obj = realm.createObject(AllTypes.class);\n                obj.setColumnBinary(new byte[j]);\n                obj.setColumnString(\"Test \" + j);\n                obj.setColumnLong(j);\n                obj.setColumnFloat(j / 1000f);\n                obj.setColumnDouble(j / 1000d);\n                obj.setColumnBoolean(j % 2 == 0);\n                obj.setColumnDate(new Date(1000L * j));\n                obj.setColumnDecimal128(new Decimal128(j));\n                obj.setColumnObjectId(new ObjectId(j, j));\n                obj.setColumnUUID(UUID.fromString(TestHelper.generateUUIDString(j)));\n                obj.setColumnMutableRealmInteger(j);\n                obj.setColumnRealmLink(obj);\n                obj.setColumnRealmObject(dog);\n                obj.setColumnRealmAny(RealmAny.valueOf(i));\n            }\n        }\n        realm.commitTransaction();\n    }\n\n    private void populateForDistinctInvalidTypesLinked(Realm realm) {\n        realm.beginTransaction();\n        AllJavaTypesUnsupportedTypes notEmpty = new AllJavaTypesUnsupportedTypes();\n        notEmpty.setFieldBinary(new byte[] {1, 2, 3});\n        notEmpty.setFieldObject(notEmpty);\n        notEmpty.setFieldList(new RealmList<AllJavaTypesUnsupportedTypes>(notEmpty));\n        realm.copyToRealm(notEmpty);\n        realm.commitTransaction();\n    }\n\n    @Test\n    public void distinct() {\n        final long numberOfBlocks = 3;\n        final long numberOfObjects = 3; // Must be greater than 1\n        populateForDistinct(realm, numberOfBlocks, numberOfObjects, false);\n\n        RealmResults<AnnotationIndexTypes> distinctBool = realm.where(AnnotationIndexTypes.class).distinct(AnnotationIndexTypes.FIELD_INDEX_BOOL).findAll();\n        assertEquals(2, distinctBool.size());\n        for (String field : new String[] {AnnotationIndexTypes.FIELD_INDEX_LONG, AnnotationIndexTypes.FIELD_INDEX_DATE, AnnotationIndexTypes.FIELD_INDEX_STRING}) {\n            RealmResults<AnnotationIndexTypes> distinct = realm.where(AnnotationIndexTypes.class).distinct(field).findAll();\n            assertEquals(field, numberOfBlocks, distinct.size());\n        }\n    }\n\n    @Test\n    public void distinct_withNullValues() {\n        final long numberOfBlocks = 3;\n        final long numberOfObjects = 3;\n        populateForDistinct(realm, numberOfBlocks, numberOfObjects, true);\n\n        for (String field : new String[] {AnnotationIndexTypes.FIELD_INDEX_DATE, AnnotationIndexTypes.FIELD_INDEX_STRING}) {\n            RealmResults<AnnotationIndexTypes> distinct = realm.where(AnnotationIndexTypes.class).distinct(field).findAll();\n            assertEquals(field, 1, distinct.size());\n        }\n    }\n\n    // Helper method to verify distinct behavior an all fields of AllTypes, potentially following\n    // possible multiple indirection links as given by 'prefix'\n    private void distinctAllFields(Realm realm, String prefix) {\n        final long numberOfBlocks = 3;\n        final long numberOfObjects = 3;\n\n        populateForDistinctAllTypes(realm, numberOfBlocks, numberOfObjects);\n\n        // Dynamic realm for verifying distinct query result against naive manual implementation of\n        // distinct\n        DynamicRealm dynamicRealm = DynamicRealm.createInstance(realm.sharedRealm);\n        RealmResults<DynamicRealmObject> all = dynamicRealm.where(AllTypes.CLASS_NAME)\n                .findAll();\n\n        // Bookkeeping to ensure that we are actually testing all types\n        HashSet types = new HashSet(Arrays.asList(RealmFieldType.values()));\n        types.remove(RealmFieldType.TYPED_LINK);\n        types.remove(RealmFieldType.MIXED_LIST);\n        types.remove(RealmFieldType.STRING_TO_MIXED_MAP);\n        types.remove(RealmFieldType.STRING_TO_BOOLEAN_MAP);\n        types.remove(RealmFieldType.STRING_TO_STRING_MAP);\n        types.remove(RealmFieldType.STRING_TO_INTEGER_MAP);\n        types.remove(RealmFieldType.STRING_TO_FLOAT_MAP);\n        types.remove(RealmFieldType.STRING_TO_DOUBLE_MAP);\n        types.remove(RealmFieldType.STRING_TO_BINARY_MAP);\n        types.remove(RealmFieldType.STRING_TO_DATE_MAP);\n        types.remove(RealmFieldType.STRING_TO_OBJECT_ID_MAP);\n        types.remove(RealmFieldType.STRING_TO_UUID_MAP);\n        types.remove(RealmFieldType.STRING_TO_DECIMAL128_MAP);\n        types.remove(RealmFieldType.STRING_TO_LINK_MAP);\n        types.remove(RealmFieldType.BOOLEAN_SET);\n        types.remove(RealmFieldType.STRING_SET);\n        types.remove(RealmFieldType.INTEGER_SET);\n        types.remove(RealmFieldType.FLOAT_SET);\n        types.remove(RealmFieldType.DOUBLE_SET);\n        types.remove(RealmFieldType.BINARY_SET);\n        types.remove(RealmFieldType.DATE_SET);\n        types.remove(RealmFieldType.DECIMAL128_SET);\n        types.remove(RealmFieldType.OBJECT_ID_SET);\n        types.remove(RealmFieldType.UUID_SET);\n        types.remove(RealmFieldType.LINK_SET);\n        types.remove(RealmFieldType.MIXED_SET);\n\n\n        // Iterate all fields of AllTypes table and verify that distinct either:\n        // - Returns correct number of entries, or\n        // - Raises an error that distinct cannot be performed on the specific field types (lists)\n        RealmObjectSchema schema = realm.getSchema().getSchemaForClass(AllTypes.CLASS_NAME);\n        Set<String> fieldNames = schema.getFieldNames();\n        for (String fieldName : fieldNames) {\n            String field = prefix + fieldName;\n            RealmFieldType type = schema.getFieldType(fieldName);\n\n            if (supportDistinct(type)) {\n                // Actual query\n                RealmResults<AllTypes> distinct = realm.where(AllTypes.class)\n                        .distinct(field)\n                        .findAll();\n\n                // Assert query result\n                // Test against manual distinct implementation\n                Set<List<? super Object>> values = distinct(all, field);\n                assertEquals(field, values.size(), distinct.size());\n                // Test against expected numbers from setup\n                switch (type) {\n                    case BOOLEAN:\n                        assertEquals(field, 2, distinct.size());\n                        break;\n                    case OBJECT:\n                        if (fieldName.equals(\"columnRealmObject\")) {\n                            assertEquals(field, numberOfBlocks, distinct.size());\n                        } else if (fieldName.equals(\"columnRealmLink\")) {\n                            assertEquals(field, numberOfBlocks * numberOfObjects, distinct.size());\n                        } else {\n                            fail(\"Unknown object \" + fieldName);\n                        }\n                        break;\n                    default:\n                        assertEquals(field, numberOfObjects, distinct.size());\n                        break;\n                }\n            } else {\n                // Test that unsupported types throw exception as expected\n                try {\n                    realm.where(AllTypes.class)\n                            .distinct(field)\n                            .findAll();\n                } catch (IllegalStateException ignore) { // Not distinct not supported on lists\n                }\n            }\n            types.remove(type);\n        }\n\n        // Validate that backlinks are not supported by sort/distinct\n        assertEquals(types.toString(), Sets.newSet(RealmFieldType.LINKING_OBJECTS), types);\n        RealmQuery<AllTypes> query = realm.where(AllTypes.class);\n\n        try{\n            query.distinct(prefix + AllTypes.FIELD_REALMBACKLINK);\n            fail();\n        } catch (IllegalArgumentException ignore){\n        }\n    }\n\n    @Test\n    public void distinct_allFields() {\n        distinctAllFields(realm, \"\");\n    }\n\n    @Test\n    public void distinct_linkedAllFields() {\n        distinctAllFields(realm, AllTypes.FIELD_REALMLINK + \".\");\n    }\n\n    @Test\n    public void distinct_nestedLinkedAllFields() {\n        distinctAllFields(realm, AllTypes.FIELD_REALMLINK + \".\" + AllTypes.FIELD_REALMLINK + \".\");\n    }\n\n    @Test\n    public void distinct_doesNotExist() {\n        final long numberOfBlocks = 3;\n        final long numberOfObjects = 3; // Must be greater than 1\n        populateForDistinct(realm, numberOfBlocks, numberOfObjects, false);\n\n        try {\n            realm.where(AnnotationIndexTypes.class).distinct(\"doesNotExist\").findAll();\n            fail();\n        } catch (IllegalArgumentException ignored) {\n        }\n    }\n\n    // Smoke test of async distinct. Underlying mechanism is the same as for sync test\n    // (distinct_allFields), so just verifying async mechanism.\n    @Test\n    @RunTestInLooperThread\n    public void distinct_async() throws Throwable {\n        final AtomicInteger changeListenerCalled = new AtomicInteger(4);\n        final Realm realm = looperThread.getRealm();\n        final long numberOfBlocks = 3;\n        final long numberOfObjects = 3; // Must be greater than 1\n        populateForDistinct(realm, numberOfBlocks, numberOfObjects, false);\n\n        final RealmResults<AnnotationIndexTypes> distinctBool = realm.where(AnnotationIndexTypes.class).distinct(AnnotationIndexTypes.FIELD_INDEX_BOOL).findAllAsync();\n        final RealmResults<AnnotationIndexTypes> distinctLong = realm.where(AnnotationIndexTypes.class).distinct(AnnotationIndexTypes.FIELD_INDEX_LONG).findAllAsync();\n        final RealmResults<AnnotationIndexTypes> distinctDate = realm.where(AnnotationIndexTypes.class).distinct(AnnotationIndexTypes.FIELD_INDEX_DATE).findAllAsync();\n        final RealmResults<AnnotationIndexTypes> distinctString = realm.where(AnnotationIndexTypes.class).distinct(AnnotationIndexTypes.FIELD_INDEX_STRING).findAllAsync();\n\n        assertFalse(distinctBool.isLoaded());\n        assertTrue(distinctBool.isValid());\n        assertTrue(distinctBool.isEmpty());\n\n        assertFalse(distinctLong.isLoaded());\n        assertTrue(distinctLong.isValid());\n        assertTrue(distinctLong.isEmpty());\n\n        assertFalse(distinctDate.isLoaded());\n        assertTrue(distinctDate.isValid());\n        assertTrue(distinctDate.isEmpty());\n\n        assertFalse(distinctString.isLoaded());\n        assertTrue(distinctString.isValid());\n        assertTrue(distinctString.isEmpty());\n\n        final Runnable endTest = new Runnable() {\n            @Override\n            public void run() {\n                if (changeListenerCalled.decrementAndGet() == 0) {\n                    looperThread.testComplete();\n                }\n            }\n        };\n\n        looperThread.keepStrongReference(distinctBool);\n        looperThread.keepStrongReference(distinctLong);\n        looperThread.keepStrongReference(distinctDate);\n        looperThread.keepStrongReference(distinctString);\n        distinctBool.addChangeListener(new RealmChangeListener<RealmResults<AnnotationIndexTypes>>() {\n            @Override\n            public void onChange(RealmResults<AnnotationIndexTypes> object) {\n                assertEquals(2, distinctBool.size());\n                endTest.run();\n            }\n        });\n\n        distinctLong.addChangeListener(new RealmChangeListener<RealmResults<AnnotationIndexTypes>>() {\n            @Override\n            public void onChange(RealmResults<AnnotationIndexTypes> object) {\n                assertEquals(numberOfBlocks, distinctLong.size());\n                endTest.run();\n            }\n        });\n\n        distinctDate.addChangeListener(new RealmChangeListener<RealmResults<AnnotationIndexTypes>>() {\n            @Override\n            public void onChange(RealmResults<AnnotationIndexTypes> object) {\n                assertEquals(numberOfBlocks, distinctDate.size());\n                endTest.run();\n            }\n        });\n\n        distinctString.addChangeListener(new RealmChangeListener<RealmResults<AnnotationIndexTypes>>() {\n            @Override\n            public void onChange(RealmResults<AnnotationIndexTypes> object) {\n                assertEquals(numberOfBlocks, distinctString.size());\n                endTest.run();\n            }\n        });\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void distinct_async_withNullValues() throws Throwable {\n        final AtomicInteger changeListenerCalled = new AtomicInteger(2);\n        final Realm realm = looperThread.getRealm();\n        final long numberOfBlocks = 3;\n        final long numberOfObjects = 3; // must be greater than 1\n        populateForDistinct(realm, numberOfBlocks, numberOfObjects, true);\n\n        final RealmResults<AnnotationIndexTypes> distinctDate = realm.where(AnnotationIndexTypes.class)\n                .distinct(AnnotationIndexTypes.FIELD_INDEX_DATE)\n                .findAllAsync();\n        final RealmResults<AnnotationIndexTypes> distinctString = realm.where(AnnotationIndexTypes.class)\n                .distinct(AnnotationIndexTypes.FIELD_INDEX_STRING)\n                .findAllAsync();\n\n        final Runnable endTest = new Runnable() {\n            @Override\n            public void run() {\n                if (changeListenerCalled.decrementAndGet() == 0) {\n                    looperThread.testComplete();\n                }\n            }\n        };\n\n        looperThread.keepStrongReference(distinctDate);\n        looperThread.keepStrongReference(distinctString);\n\n        distinctDate.addChangeListener(new RealmChangeListener<RealmResults<AnnotationIndexTypes>>() {\n            @Override\n            public void onChange(RealmResults<AnnotationIndexTypes> object) {\n                assertEquals(1, distinctDate.size());\n                endTest.run();\n            }\n        });\n\n        distinctString.addChangeListener(new RealmChangeListener<RealmResults<AnnotationIndexTypes>>() {\n            @Override\n            public void onChange(RealmResults<AnnotationIndexTypes> object) {\n                assertEquals(1, distinctString.size());\n                endTest.run();\n            }\n        });\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void distinct_async_doesNotExist() {\n        final long numberOfBlocks = 3;\n        final long numberOfObjects = 3;\n        populateForDistinct(realm, numberOfBlocks, numberOfObjects, false);\n\n        try {\n            realm.where(AnnotationIndexTypes.class).distinct(\"doesNotExist\").findAllAsync();\n        } catch (IllegalArgumentException ignored) {\n        }\n        looperThread.testComplete();\n    }\n\n    // Smoke test of async distinct invalid types. Underlying mechanism is the same as for sync test\n    // (distinct_allFields), so just verifying async mechanism.\n    @Test\n    @RunTestInLooperThread\n    public void distinct_async_invalidTypes() {\n        populateTestRealm(realm, TEST_DATA_SIZE);\n\n        RealmObjectSchema schema = realm.getSchema().getSchemaForClass(AllTypes.CLASS_NAME);\n\n        Set<String> fieldNames = schema.getFieldNames();\n        for (String fieldName : fieldNames) {\n            String field = fieldName;\n            RealmFieldType type = schema.getFieldType(fieldName);\n            if (!supportDistinct(type)) {\n                try {\n                    realm.where(AllTypes.class).distinct(field).findAllAsync();\n                } catch (IllegalArgumentException ignored) {\n                }\n            }\n        }\n        looperThread.testComplete();\n    }\n\n    @Test\n    public void distinctMultiArgs() {\n        final long numberOfBlocks = 3;\n        final long numberOfObjects = 3; // Must be greater than 1\n        populateForDistinct(realm, numberOfBlocks, numberOfObjects, false);\n\n        RealmQuery<AnnotationIndexTypes> query = realm.where(AnnotationIndexTypes.class);\n        RealmResults<AnnotationIndexTypes> distinctMulti = query.distinct(AnnotationIndexTypes.FIELD_INDEX_BOOL, AnnotationIndexTypes.INDEX_FIELDS).findAll();\n        assertEquals(numberOfBlocks, distinctMulti.size());\n    }\n\n    @Test\n    public void distinctMultiArgs_switchedFieldsOrder() {\n        final long numberOfBlocks = 3;\n        TestHelper.populateForDistinctFieldsOrder(realm, numberOfBlocks);\n\n        // Regardless of the block size defined above, the output size is expected to be the same, 4 in this case, due to receiving unique combinations of tuples.\n        RealmResults<AnnotationIndexTypes> distinctStringLong = realm.where(AnnotationIndexTypes.class).distinct(AnnotationIndexTypes.FIELD_INDEX_STRING, AnnotationIndexTypes.FIELD_INDEX_LONG).findAll();\n        RealmResults<AnnotationIndexTypes> distinctLongString = realm.where(AnnotationIndexTypes.class).distinct(AnnotationIndexTypes.FIELD_INDEX_LONG, AnnotationIndexTypes.FIELD_INDEX_STRING).findAll();\n        assertEquals(4, distinctStringLong.size());\n        assertEquals(4, distinctLongString.size());\n        assertEquals(distinctStringLong.size(), distinctLongString.size());\n    }\n\n    @Test\n    public void distinctMultiArgs_emptyField() {\n        final long numberOfBlocks = 3;\n        final long numberOfObjects = 3;\n        populateForDistinct(realm, numberOfBlocks, numberOfObjects, false);\n\n        RealmQuery<AnnotationIndexTypes> query = realm.where(AnnotationIndexTypes.class);\n        // An empty string field in the middle.\n        try {\n            query.distinct(AnnotationIndexTypes.FIELD_INDEX_BOOL, \"\", AnnotationIndexTypes.FIELD_INDEX_INT).findAll();\n            fail();\n        } catch (IllegalArgumentException ignored) {\n        }\n\n        // A null string field in the middle.\n        try {\n            query.distinct(AnnotationIndexTypes.FIELD_INDEX_BOOL, (String) null, AnnotationIndexTypes.FIELD_INDEX_INT).findAll();\n            fail();\n        } catch (IllegalArgumentException ignored) {\n        }\n\n        // (String) Null makes varargs a null array.\n        try {\n            query.distinct(AnnotationIndexTypes.FIELD_INDEX_BOOL, (String) null).findAll();\n            fail();\n        } catch (IllegalArgumentException ignored) {\n        }\n        // Two (String) null for first and varargs fields.\n        try {\n            query.distinct((String) null, (String) null).findAll();\n            fail();\n        } catch (IllegalArgumentException ignored) {\n        }\n        // \"\" & (String) null combination.\n        try {\n            query.distinct(\"\", (String) null).findAll();\n            fail();\n        } catch (IllegalArgumentException ignored) {\n        }\n        // \"\" & (String) null combination.\n        try {\n            query.distinct((String) null, \"\").findAll();\n            fail();\n        } catch (IllegalArgumentException ignored) {\n        }\n        // Two empty fields tests.\n        try {\n            query.distinct(\"\", \"\").findAll();\n            fail();\n        } catch (IllegalArgumentException ignored) {\n        }\n    }\n\n    @Test\n    public void distinctMultiArgs_withNullValues() {\n        final long numberOfBlocks = 3;\n        final long numberOfObjects = 3;\n        populateForDistinct(realm, numberOfBlocks, numberOfObjects, true);\n\n        RealmQuery<AnnotationIndexTypes> query = realm.where(AnnotationIndexTypes.class);\n        RealmResults<AnnotationIndexTypes> distinctMulti = query.distinct(AnnotationIndexTypes.FIELD_INDEX_DATE, AnnotationIndexTypes.FIELD_INDEX_STRING).findAll();\n        assertEquals(1, distinctMulti.size());\n    }\n\n    @Test\n    public void distinctMultiArgs_LinkedFields() {\n        final long numberOfBlocks = 3;\n        final long numberOfObjects = 3;\n        populateForDistinct(realm, numberOfBlocks, numberOfObjects, true);\n\n        DynamicRealm dynamicRealm = DynamicRealm.createInstance(realm.sharedRealm);\n        RealmResults<DynamicRealmObject> all = dynamicRealm.where(AnnotationIndexTypes.CLASS_NAME)\n                .findAll();\n\n        RealmQuery<AnnotationIndexTypes> query = realm.where(AnnotationIndexTypes.class);\n        RealmResults<AnnotationIndexTypes> distinct = query.distinct(AnnotationIndexTypes.INDEX_LINKED_FIELD_STRING, AnnotationIndexTypes.INDEX_LINKED_FIELDS).findAll();\n\n        List<String> fields = new ArrayList();\n        fields.add(AnnotationIndexTypes.INDEX_LINKED_FIELD_STRING);\n        fields.addAll(Arrays.asList(AnnotationIndexTypes.INDEX_LINKED_FIELDS));\n        Set<List<? super Object>> values = distinct(all, fields.toArray());\n        assertEquals(values.size(), distinct.size());\n    }\n\n    @Test(expected = UnsupportedOperationException.class)\n    public void beginGroup_missingEndGroup() {\n        realm.where(AllTypes.class).beginGroup().findAll();\n    }\n\n    @Test(expected = UnsupportedOperationException.class)\n    public void multipleBeginGroup_missingEndGroup() {\n        realm.where(AllTypes.class).beginGroup().beginGroup().endGroup().findAll();\n    }\n\n    @Test(expected = UnsupportedOperationException.class)\n    public void endGroup_missingBeginGroup() {\n        realm.where(AllTypes.class).endGroup().findAll();\n    }\n\n    @Test(expected = UnsupportedOperationException.class)\n    public void multipleEndGroup_missingBeginGroup() {\n        realm.where(AllTypes.class).beginGroup().endGroup().endGroup().findAll();\n    }\n\n    @Test\n    public void alwaysTrue() {\n        populateTestRealm();\n        assertEquals(TEST_DATA_SIZE, realm.where(AllTypes.class).alwaysTrue().findAll().size());\n    }\n\n    @Test\n    public void alwaysTrue_inverted() {\n        populateTestRealm();\n        assertEquals(0, realm.where(AllTypes.class).not().alwaysTrue().findAll().size());\n    }\n\n    @Test\n    public void alwaysFalse() {\n        populateTestRealm();\n        assertEquals(0, realm.where(AllTypes.class).alwaysFalse().findAll().size());\n    }\n\n    @Test\n    public void alwaysFalse_inverted() {\n        populateTestRealm();\n        assertEquals(TEST_DATA_SIZE, realm.where(AllTypes.class).not().alwaysFalse().findAll().size());\n    }\n\n    @Test\n    public void getRealm() {\n        assertTrue(realm == realm.where(AllTypes.class).getRealm());\n    }\n\n    @Test\n    public void getRealm_throwsIfDynamicRealm() {\n        DynamicRealm dRealm = DynamicRealm.getInstance(realm.getConfiguration());\n        try {\n            dRealm.where(AllTypes.CLASS_NAME).getRealm();\n            fail();\n        } catch (IllegalStateException ignore) {\n        } finally {\n            dRealm.close();\n        }\n    }\n\n    @Test\n    public void getRealm_throwsIfRealmClosed() {\n        RealmQuery<AllTypes> query = realm.where(AllTypes.class);\n        realm.close();\n        try {\n            query.getRealm();\n            fail();\n        } catch (IllegalStateException ignore) {\n        }\n    }\n\n    @Test\n    public void rawPredicate() {\n        populateTestRealm();\n        RealmResults<AllTypes> result = realm.where(AllTypes.class).rawPredicate(\"columnString = 'test data 0'\").findAll();\n        assertEquals(1, result.size());\n    }\n\n    @Test\n    public void rawPredicate_invalidFieldNameThrows() {\n        try {\n            realm.where(AllTypes.class).rawPredicate(\"foo = 'test data 0'\");\n            fail();\n        } catch (IllegalArgumentException e) {\n            assertTrue(\"Real message: \" + e.getMessage(), e.getMessage().contains(\"'AllTypes' has no property 'foo'\"));\n        }\n    }\n\n    @Test\n    public void rawPredicate_invalidLinkedFieldNameThrows() {\n        try {\n            realm.where(AllTypes.class).rawPredicate(\"columnRealmObject.foo = 'test data 0'\");\n            fail();\n        } catch (IllegalArgumentException e) {\n            assertTrue(\"Real message: \" + e.getMessage(), e.getMessage().contains(\"'Dog' has no property 'foo'\"));\n        }\n\n        try {\n            realm.where(AllTypes.class).rawPredicate(\"unknownField.foo = 'test data 0'\");\n            fail();\n        } catch (IllegalArgumentException e) {\n            assertTrue(\"Real message: \" + e.getMessage(), e.getMessage().contains(\"'AllTypes' has no property 'unknownField'\"));\n        }\n    }\n\n    @Test\n    public void rawPredicate_illegalSyntaxThrows() {\n        try {\n            realm.where(AllTypes.class).rawPredicate(\"lol\");\n            fail();\n        } catch (IllegalArgumentException e) {\n            assertTrue(e.getMessage().contains(\"Invalid predicate: 'lol'\"));\n        }\n    }\n\n    @Test\n    public void rawPredicate_invalidTypeThrows() {\n        try {\n            realm.where(AllTypes.class).rawPredicate(\"columnString = 42.0\");\n            fail();\n        } catch (IllegalArgumentException ex) {\n            assertTrue(\"Error message was: \" + ex.getMessage(), ex.getMessage().contains(\"Unsupported comparison between type 'string' and type 'double'\"));\n        }\n    }\n\n    @Test\n    public void rawPredicate_realmAnyWithTypedPredicates() {\n        populateTestRealm();\n        RealmResults<AllTypes> result = realm.where(AllTypes.class)\n                .equalTo(\"columnString\", \"test data 0\")\n                .or()\n                .rawPredicate(\"columnString = 'test data 1'\")\n                .findAll();\n        assertEquals(2, result.size());\n    }\n\n    @Test\n    public void rawPredicate_rawDescriptors() {\n        realm.beginTransaction();\n        realm.insert(new Dog(\"Milo\"));\n        realm.insert(new Dog(\"Fido\"));\n        realm.insert(new Dog(\"Bella\"));\n        realm.insert(new Dog(\"Bella\"));\n        realm.commitTransaction();\n\n        RealmQuery<Dog> query = realm.where(Dog.class)\n                .rawPredicate(\"TRUEPREDICATE SORT(name ASC) DISTINCT(name) LIMIT(2)\");\n\n        assertEquals(\"TRUEPREDICATE SORT(name ASC) DISTINCT(name) LIMIT(2)\", query.getDescription());\n\n        // Descriptors should be applied in order provided\n        RealmResults<Dog> dogs = query.findAll();\n        assertEquals(2, dogs.size());\n        assertEquals(\"Bella\", dogs.get(0).getName());\n        assertEquals(\"Fido\", dogs.get(1).getName());\n    }\n\n    // Descriptors defined by raw predicates can be realmAny with typed ones and still be applied in order\n    @Test\n    public void rawPredicate_mixTypedAndRawDescriptors() {\n        realm.beginTransaction();\n        realm.insert(new Dog(\"Milo\", 1));\n        realm.insert(new Dog(\"Fido\", 2));\n        realm.insert(new Dog(\"Bella\", 3));\n        realm.insert(new Dog(\"Bella\", 3));\n        realm.insert(new Dog(\"Bella\", 4));\n        realm.commitTransaction();\n\n        RealmQuery<Dog> query = realm.where(Dog.class)\n                .sort(\"age\", Sort.ASCENDING)\n                .rawPredicate(\"TRUEPREDICATE SORT(name ASC) DISTINCT(name, age) LIMIT(2)\")\n                .distinct(\"age\")\n                .limit(1);\n\n        // Descriptors should be applied in order provided throughout the query\n        assertEquals(\"TRUEPREDICATE SORT(age ASC) SORT(name ASC) DISTINCT(name, age) LIMIT(2) DISTINCT(age) LIMIT(1)\", query.getDescription());\n\n        RealmResults<Dog> dogs = query.findAll();\n        assertEquals(1, dogs.size());\n        assertEquals(\"Bella\", dogs.get(0).getName());\n        assertEquals(3, dogs.get(0).getAge());\n    }\n\n    @Test\n    public void rawPredicate_dynamicRealmQueries() {\n        // DynamicRealm queries hit a slightly different codepath than typed Realms, so this\n        // is just a smoke test.\n        populateTestRealm();\n        DynamicRealm dynamicRealm = DynamicRealm.getInstance(realm.getConfiguration());\n        try {\n            RealmResults<DynamicRealmObject> results = dynamicRealm\n                    .where(AllTypes.CLASS_NAME)\n                    .rawPredicate(AllTypes.FIELD_LONG + \" >= 5\")\n                    .findAll();\n            assertEquals(5, results.size());\n        } finally {\n            dynamicRealm.close();\n        }\n    }\n\n    @Test\n    public void rawPredicate_useJavaNames() {\n\n        // Java Field names\n        RealmResults<ClassWithValueDefinedNames> results = realm.where(ClassWithValueDefinedNames.class)\n                .rawPredicate(\"field = 'Foo'\")\n                .findAll();\n        assertTrue(results.isEmpty());\n\n        // Internal field name\n        results = realm.where(ClassWithValueDefinedNames.class)\n                .rawPredicate(\"my-field-name = 'Foo'\")\n                .findAll();\n        assertTrue(results.isEmpty());\n\n        // Linking Objects using the computed field\n        results = realm.where(ClassWithValueDefinedNames.class)\n                .rawPredicate(\"parents.@count = 0\")\n                .findAll();\n        assertTrue(results.isEmpty());\n\n        // Linking Objects using dynamic query with internal name for both class and property\n        results = realm.where(ClassWithValueDefinedNames.class)\n                .rawPredicate(\"@links.my-class-name.object-link.@count = 0\")\n                .findAll();\n        assertTrue(results.isEmpty());\n\n        // Linking Objects using dynamic query with internal name for class and alias for property\n        results = realm.where(ClassWithValueDefinedNames.class)\n                .rawPredicate(\"@links.my-class-name.objectLink.@count = 0\")\n                .findAll();\n        assertTrue(results.isEmpty());\n\n        // Linking Objects using dynamic query with alias for class and internal name for property\n        results = realm.where(ClassWithValueDefinedNames.class)\n                .rawPredicate(\"@links.ClassWithValueDefinedNames.object-link.@count = 0\")\n                .findAll();\n        assertTrue(results.isEmpty());\n\n        // Linking Objects using dynamic query with alias both class and property\n        results = realm.where(ClassWithValueDefinedNames.class)\n                .rawPredicate(\"@links.ClassWithValueDefinedNames.objectLink.@count = 0\")\n                .findAll();\n        assertTrue(results.isEmpty());\n    }\n\n    @Test\n    public void rawPredicate_argumentSubstitution() {\n        populateTestRealm();\n        RealmQuery<AllTypes> query = realm.where(AllTypes.class);\n        query.rawPredicate(\"columnString = $0 \" +\n                \"AND columnBoolean = $1 \" +\n                \"AND columnFloat = $2 \" +\n                \"AND columnLong = $3\", \"test data 0\", true, 1.2345f, 0);\n        RealmResults<AllTypes> results = query.findAll();\n        assertEquals(1, results.size());\n    }\n\n    @Test\n    public void rawPredicate_realmObjectArgumentSubstitution() {\n        realm.beginTransaction();\n\n        Dog dog = realm.createObject(Dog.class);\n        dog.setName(\"doggy dog\");\n        dog.setAge(1999);\n\n        AllTypes allTypes = realm.createObject(AllTypes.class);\n        allTypes.setColumnRealmObject(dog);\n\n        realm.commitTransaction();\n\n        RealmQuery<AllTypes> query = realm.where(AllTypes.class);\n        query.rawPredicate(\"columnRealmObject = $0\", dog);\n        RealmResults<AllTypes> results = query.findAll();\n        assertEquals(1, results.size());\n    }\n\n    @Test\n    public void rawPredicate_embeddedObjectArgumentSubstitution() {\n        realm.beginTransaction();\n\n        EmbeddedSimpleParent parent = realm.createObject(EmbeddedSimpleParent.class, UUID.randomUUID().toString());\n        parent.setChild(new EmbeddedSimpleChild());\n\n        EmbeddedSimpleChild child = parent.getChild();\n\n        realm.commitTransaction();\n\n        RealmQuery<EmbeddedSimpleParent> query = realm.where(EmbeddedSimpleParent.class);\n        query.rawPredicate(\"child = $0\", child);\n        RealmResults<EmbeddedSimpleParent> results = query.findAll();\n        assertEquals(1, results.size());\n    }\n\n    @Test\n    public void rawPredicate_invalidRealmObjectThrows() {\n        realm.beginTransaction();\n        AllTypes allTypes = realm.createObject(AllTypes.class);\n        realm.commitTransaction();\n\n        realm.executeTransaction(r -> allTypes.deleteFromRealm());\n\n        try {\n            realm.where(AllTypes.class).rawPredicate(\"columnRealmObject = $0\", allTypes);\n            fail();\n        } catch (IllegalArgumentException e) {\n            assertTrue(\"Real message: \" + e.getMessage(), e.getMessage().contains(\"RealmObject is not a valid managed object.\"));\n        }\n\n        try {\n            realm.where(AllTypes.class).rawPredicate(\"columnRealmObject = $0\", new AllTypes());\n            fail();\n        } catch (IllegalArgumentException e) {\n            assertTrue(\"Real message: \" + e.getMessage(), e.getMessage().contains(\"RealmObject is not a valid managed object.\"));\n        }\n    }\n\n    @Test\n    public void rawPredicate_invalidFormatOptions() {\n        RealmQuery<AllTypes> query = realm.where(AllTypes.class);\n        try {\n            // Argument type not valid\n            query.rawPredicate(\"columnString = $0\", 42);\n            fail();\n        } catch (IllegalArgumentException ignore) {\n        }\n\n        try {\n            // Missing number of arguments\n            query.rawPredicate(\"columnString = $0 AND columnString  = $1\", \"foo\");\n            RealmLog.error(query.getDescription());\n            fail();\n        } catch (IllegalStateException ignore) {\n        }\n\n        try {\n            // Wrong syntax for argument substitution\n            query.rawPredicate(\"columnString = %0\", \"foo\");\n            fail();\n        } catch (IllegalArgumentException ignore) {\n        }\n    }\n\n    @Test\n    public void rawPredicate_reservedKeywords() {\n        realm.beginTransaction();\n        realm.insert(new KeywordFieldNames());\n        realm.commitTransaction();\n\n        realm.where(KeywordFieldNames.class).rawPredicate(\"desc = $0\", \"value\").findAll();\n        realm.where(KeywordFieldNames.class).rawPredicate(\"limit = $0\", \"value\").findAll();\n        realm.where(KeywordFieldNames.class).rawPredicate(\"sort = $0\", \"value\").findAll();\n        realm.where(KeywordFieldNames.class).rawPredicate(\"distinct = $0\", \"value\").findAll();\n    }\n\n    @Test\n    public void limit() {\n        populateTestRealm(realm, TEST_DATA_SIZE);\n        RealmResults<AllTypes> results = realm.where(AllTypes.class).sort(AllTypes.FIELD_LONG).limit(5).findAll();\n        assertEquals(5, results.size());\n        for (int i = 0; i < 5; i++) {\n            assertEquals(i, results.get(i).getColumnLong());\n        }\n    }\n\n    @Test\n    public void limit_withSortAndDistinct() {\n        // The order of operators matter when using limit()\n        // If applying sort/distinct without limit, any order will result in the same query result.\n\n        realm.beginTransaction();\n        RealmList<AllJavaTypesUnsupportedTypes> list = realm.createObject(AllJavaTypesUnsupportedTypes.class, -1).getFieldList(); // Root object;\n        for (int i = 0; i < 5; i++) {\n            AllJavaTypesUnsupportedTypes obj = realm.createObject(AllJavaTypesUnsupportedTypes.class, i);\n            obj.setFieldLong(i);\n            list.add(obj);\n        }\n        realm.commitTransaction();\n\n        RealmResults<AllJavaTypesUnsupportedTypes> results = list.where()\n                .sort(AllJavaTypesUnsupportedTypes.FIELD_LONG, Sort.DESCENDING) // [4, 4, 3, 3, 2, 2, 1, 1, 0, 0]\n                .distinct(AllJavaTypesUnsupportedTypes.FIELD_LONG) // [4, 3, 2, 1, 0]\n                .limit(2) // [4, 3]\n                .findAll();\n        assertEquals(2, results.size());\n        assertEquals(4, results.first().getFieldLong());\n        assertEquals(3, results.last().getFieldLong());\n\n        results = list.where()\n                .limit(2) // [0, 1]\n                .distinct(AllJavaTypesUnsupportedTypes.FIELD_LONG) // [ 0, 1]\n                .sort(AllJavaTypesUnsupportedTypes.FIELD_LONG, Sort.DESCENDING) // [1, 0]\n                .findAll();\n        assertEquals(2, results.size());\n        assertEquals(1, results.first().getFieldLong());\n        assertEquals(0, results.last().getFieldLong());\n\n        results = list.where()\n                .distinct(AllJavaTypesUnsupportedTypes.FIELD_LONG) // [ 0, 1, 2, 3, 4]\n                .limit(2) // [0, 1]\n                .sort(AllJavaTypesUnsupportedTypes.FIELD_LONG, Sort.DESCENDING) // [1, 0]\n                .findAll();\n        assertEquals(2, results.size());\n        assertEquals(1, results.first().getFieldLong());\n        assertEquals(0, results.last().getFieldLong());\n    }\n\n    // Checks that https://github.com/realm/realm-object-store/pull/679/files#diff-c0354faf99b53cc5d3c9e6a58ed9ae85R610\n    // Do not apply to Realm Java as we do not lazy-execute queries.\n    @Test\n    public void limit_asSubQuery() {\n        realm.executeTransaction(r -> {\n            for (int i = 0; i < 10; i++) {\n                r.createObject(AllTypes.class).setColumnLong(i % 5);\n            }\n        });\n\n        RealmResults<AllTypes> results = realm.where(AllTypes.class)\n                .sort(AllTypes.FIELD_LONG, Sort.DESCENDING)\n                .findAll() // [4, 4, 3, 3, 2, 2, 1, 1, 0, 0]\n                .where()\n                .distinct(AllTypes.FIELD_LONG)\n                .findAll() // [4, 3, 2, 1, 0]\n                .where()\n                .limit(2) // [4, 3]\n                .findAll();\n        assertEquals(2, results.size());\n        assertEquals(4, results.first().getColumnLong());\n        assertEquals(3, results.last().getColumnLong());\n    }\n\n    @Test\n    public void limit_invalidValuesThrows() {\n        RealmQuery<AllTypes> query = realm.where(AllTypes.class);\n\n        try {\n            query.limit(-1).findAll();\n            fail();\n        } catch (IllegalArgumentException ignored) {\n        }\n    }\n\n    @Test\n    @UiThreadTest\n    public void findAll_runOnMainThreadAllowed() {\n        RealmConfiguration configuration = configFactory.createConfigurationBuilder()\n                .allowQueriesOnUiThread(true)\n                .name(\"ui_realm\")\n                .build();\n\n        Realm uiRealm = Realm.getInstance(configuration);\n        uiRealm.where(Dog.class).findAll();\n        uiRealm.close();\n    }\n\n    @Test\n    @UiThreadTest\n    public void findFirst_runOnMainThreadAllowed() {\n        RealmConfiguration configuration = configFactory.createConfigurationBuilder()\n                .allowQueriesOnUiThread(true)\n                .name(\"ui_realm\")\n                .build();\n\n        Realm uiRealm = Realm.getInstance(configuration);\n        uiRealm.where(Dog.class).findFirst();\n        uiRealm.close();\n    }\n\n    @Test\n    @UiThreadTest\n    public void findAll_runOnMainThreadThrows() {\n        RealmConfiguration configuration = configFactory.createConfigurationBuilder()\n                .allowQueriesOnUiThread(false)\n                .name(\"ui_realm\")\n                .build();\n\n        // Try-with-resources\n        try (Realm uiRealm = Realm.getInstance(configuration)) {\n            uiRealm.where(Dog.class).findAll();\n            fail(\"In this test queries are not allowed to run on the UI thread, so something went awry.\");\n        } catch (RealmException e) {\n            assertTrue(Objects.requireNonNull(e.getMessage()).contains(\"allowQueriesOnUiThread\"));\n        }\n    }\n\n    @Test\n    @UiThreadTest\n    public void findFirst_runOnMainThreadThrows() {\n        RealmConfiguration configuration = configFactory.createConfigurationBuilder()\n                .allowQueriesOnUiThread(false)\n                .name(\"ui_realm\")\n                .build();\n\n        // Try-with-resources\n        try (Realm uiRealm = Realm.getInstance(configuration)) {\n            uiRealm.where(Dog.class).findFirst();\n            fail(\"In this test queries are not allowed to run on the UI thread, so something went awry.\");\n        } catch (RealmException e) {\n            assertTrue(Objects.requireNonNull(e.getMessage()).contains(\"allowQueriesOnUiThread\"));\n        }\n    }\n\n    @Test\n    @UiThreadTest\n    public void asyncQuery_throwsWhenCallingRefresh() {\n        RealmConfiguration configuration = configFactory.createConfigurationBuilder()\n                .allowQueriesOnUiThread(false)\n                .name(\"ui_realm\")\n                .build();\n\n        // Try-with-resources\n        try (Realm uiRealm = Realm.getInstance(configuration)) {\n            uiRealm.refresh();\n\n            fail(\"In this test queries are not allowed to run on the UI thread, so something went awry.\");\n        } catch (RealmException e) {\n            assertTrue(Objects.requireNonNull(e.getMessage()).contains(\"allowQueriesOnUiThread\"));\n        }\n    }\n\n    @Test\n    @UiThreadTest\n    public void count_runOnMainThreadThrows() {\n        RealmConfiguration configuration = configFactory.createConfigurationBuilder()\n                .allowQueriesOnUiThread(false)\n                .name(\"ui_realm\")\n                .build();\n\n        // Try-with-resources\n        try (Realm uiRealm = Realm.getInstance(configuration)) {\n            uiRealm.where(Dog.class).count();\n\n            fail(\"In this test queries are not allowed to run on the UI thread, so something went awry.\");\n        } catch (RealmException e) {\n            assertTrue(Objects.requireNonNull(e.getMessage()).contains(\"allowQueriesOnUiThread\"));\n        }\n    }\n\n    @Test\n    @UiThreadTest\n    public void max_runOnMainThreadThrows() {\n        RealmConfiguration configuration = configFactory.createConfigurationBuilder()\n                .allowQueriesOnUiThread(false)\n                .name(\"ui_realm\")\n                .build();\n\n        // Try-with-resources\n        try (Realm uiRealm = Realm.getInstance(configuration)) {\n            uiRealm.where(Dog.class).max(\"age\");\n\n            fail(\"In this test queries are not allowed to run on the UI thread, so something went awry.\");\n        } catch (RealmException e) {\n            assertTrue(Objects.requireNonNull(e.getMessage()).contains(\"allowQueriesOnUiThread\"));\n        }\n    }\n\n    @Test\n    @UiThreadTest\n    public void min_runOnMainThreadThrows() {\n        RealmConfiguration configuration = configFactory.createConfigurationBuilder()\n                .allowQueriesOnUiThread(false)\n                .name(\"ui_realm\")\n                .build();\n\n        // Try-with-resources\n        try (Realm uiRealm = Realm.getInstance(configuration)) {\n            uiRealm.where(Dog.class).min(\"age\");\n\n            fail(\"In this test queries are not allowed to run on the UI thread, so something went awry.\");\n        } catch (RealmException e) {\n            assertTrue(Objects.requireNonNull(e.getMessage()).contains(\"allowQueriesOnUiThread\"));\n        }\n    }\n\n    @Test\n    @UiThreadTest\n    public void average_runOnMainThreadThrows() {\n        RealmConfiguration configuration = configFactory.createConfigurationBuilder()\n                .allowQueriesOnUiThread(false)\n                .name(\"ui_realm\")\n                .build();\n\n        // Try-with-resources\n        try (Realm uiRealm = Realm.getInstance(configuration)) {\n            uiRealm.where(Dog.class).average(\"age\");\n\n            fail(\"In this test queries are not allowed to run on the UI thread, so something went awry.\");\n        } catch (RealmException e) {\n            assertTrue(Objects.requireNonNull(e.getMessage()).contains(\"allowQueriesOnUiThread\"));\n        }\n    }\n\n    @Test\n    @UiThreadTest\n    public void averageDecimal128_runOnMainThreadThrows() {\n        RealmConfiguration configuration = configFactory.createConfigurationBuilder()\n                .allowQueriesOnUiThread(false)\n                .name(\"ui_realm\")\n                .build();\n\n        // Try-with-resources\n        try (Realm uiRealm = Realm.getInstance(configuration)) {\n            uiRealm.where(AllTypes.class).averageDecimal128(AllTypes.FIELD_DECIMAL128);\n\n            fail(\"In this test queries are not allowed to run on the UI thread, so something went awry.\");\n        } catch (RealmException e) {\n            assertTrue(Objects.requireNonNull(e.getMessage()).contains(\"allowQueriesOnUiThread\"));\n        }\n    }\n\n    @Test\n    @UiThreadTest\n    public void maximumDate_runOnMainThreadThrows() {\n        RealmConfiguration configuration = configFactory.createConfigurationBuilder()\n                .allowQueriesOnUiThread(false)\n                .name(\"ui_realm\")\n                .build();\n\n        // Try-with-resources\n        try (Realm uiRealm = Realm.getInstance(configuration)) {\n            uiRealm.where(Dog.class).maximumDate(\"birthday\");\n\n            fail(\"In this test queries are not allowed to run on the UI thread, so something went awry.\");\n        } catch (RealmException e) {\n            assertTrue(Objects.requireNonNull(e.getMessage()).contains(\"allowQueriesOnUiThread\"));\n        }\n    }\n\n    @Test\n    @UiThreadTest\n    public void minimumDate_runOnMainThreadThrows() {\n        RealmConfiguration configuration = configFactory.createConfigurationBuilder()\n                .allowQueriesOnUiThread(false)\n                .name(\"ui_realm\")\n                .build();\n\n        // Try-with-resources\n        try (Realm uiRealm = Realm.getInstance(configuration)) {\n            uiRealm.where(Dog.class).minimumDate(\"birthday\");\n\n            fail(\"In this test queries are not allowed to run on the UI thread, so something went awry.\");\n        } catch (RealmException e) {\n            assertTrue(Objects.requireNonNull(e.getMessage()).contains(\"allowQueriesOnUiThread\"));\n        }\n    }\n\n    private void fillDictionaryTests(){\n        realm.executeTransaction(transactionRealm -> {\n            DictionaryAllTypes allTypes1 = realm.createObject(DictionaryAllTypes.class);\n            allTypes1.getColumnStringDictionary().put(\"hello world1\", \"Test1\");\n\n            DictionaryAllTypes allTypes2 = realm.createObject(DictionaryAllTypes.class);\n            allTypes2.getColumnStringDictionary().put(\"hello world1\", \"Test2\");\n\n            DictionaryAllTypes allTypes3 = realm.createObject(DictionaryAllTypes.class);\n            allTypes3.getColumnStringDictionary().put(\"hello world2\", \"Test2\");\n        });\n    }\n\n    @Test\n    public void dictionary_containsKey(){\n        fillDictionaryTests();\n        RealmResults<DictionaryAllTypes> results = realm.where(DictionaryAllTypes.class).containsKey(DictionaryAllTypes.FIELD_STRING_DICTIONARY, \"hello world1\").findAll();\n        assertEquals(2, results.size());\n\n        // We can't assert on values since we don't know the order in which the results are delivered, so better to assert that the keys are contained in the results\n        DictionaryAllTypes results0 = results.get(0);\n        assertNotNull(results0);\n        assertTrue(results0.getColumnStringDictionary().containsKey(\"hello world1\"));\n        DictionaryAllTypes results1 = results.get(1);\n        assertNotNull(results1);\n        assertTrue(results1.getColumnStringDictionary().containsKey(\"hello world1\"));\n    }\n\n    @Test\n    public void dictionary_doesntContainKey(){\n        fillDictionaryTests();\n        RealmResults<DictionaryAllTypes> results = realm.where(DictionaryAllTypes.class).containsKey(DictionaryAllTypes.FIELD_STRING_DICTIONARY, \"Do I exist?\").findAll();\n        assertEquals(0, results.size());\n    }\n\n    @Test\n    public void dictionary_containsKeyNonLatin(){\n        fillDictionaryTests();\n        RealmResults<DictionaryAllTypes> results = realm.where(DictionaryAllTypes.class).containsKey(DictionaryAllTypes.FIELD_STRING_DICTIONARY, \"델타\").findAll();\n        assertEquals(0, results.size());\n    }\n\n    @Test\n    public void dictionary_containsValue(){\n        fillDictionaryTests();\n        RealmResults<DictionaryAllTypes> results = realm.where(DictionaryAllTypes.class).containsValue(DictionaryAllTypes.FIELD_STRING_DICTIONARY, \"Test2\").findAll();\n        assertEquals(2, results.size());\n        assertEquals(\"Test2\", results.get(0).getColumnStringDictionary().get(\"hello world1\"));\n        assertEquals(\"Test2\", results.get(1).getColumnStringDictionary().get(\"hello world2\"));\n    }\n\n    @Test\n    public void dictionary_doesntContainsValue(){\n        fillDictionaryTests();\n        RealmResults<DictionaryAllTypes> results = realm.where(DictionaryAllTypes.class).containsValue(DictionaryAllTypes.FIELD_STRING_DICTIONARY, \"who am I\").findAll();\n        assertEquals(0, results.size());\n    }\n\n    @Test\n    public void dictionary_containsEntry(){\n        fillDictionaryTests();\n        RealmResults<DictionaryAllTypes> results = realm.where(DictionaryAllTypes.class).containsEntry(DictionaryAllTypes.FIELD_STRING_DICTIONARY, new AbstractMap.SimpleImmutableEntry<>(\"hello world1\", \"Test2\")).findAll();\n        assertEquals(1, results.size());\n        assertEquals(\"Test2\", results.first().getColumnStringDictionary().get(\"hello world1\"));\n    }\n\n    @Test\n    public void dictionary_doesntContainsEntry(){\n        fillDictionaryTests();\n        RealmResults<DictionaryAllTypes> results = realm.where(DictionaryAllTypes.class).containsEntry(DictionaryAllTypes.FIELD_STRING_DICTIONARY, new AbstractMap.SimpleImmutableEntry<>(\"is this\", \"real\")).findAll();\n        assertEquals(0, results.size());\n    }\n\n    @Test\n    public void dictionary_containsKeyNull(){\n        fillDictionaryTests();\n        RealmResults<DictionaryAllTypes> results = realm.where(DictionaryAllTypes.class).containsKey(DictionaryAllTypes.FIELD_STRING_DICTIONARY, null).findAll();\n        assertEquals(0, results.size());\n    }\n\n    @Test\n    public void dictionary_containsValueNull(){\n        fillDictionaryTests();\n        RealmResults<DictionaryAllTypes> results = realm.where(DictionaryAllTypes.class).containsValue(DictionaryAllTypes.FIELD_STRING_DICTIONARY, (Date) null).findAll();\n        assertEquals(0, results.size());\n    }\n\n    @Test(expected = IllegalArgumentException.class)\n    public void dictionary_dictionary_containsEntryNull(){\n        fillDictionaryTests();\n        realm.where(DictionaryAllTypes.class).containsEntry(DictionaryAllTypes.FIELD_STRING_DICTIONARY, null);\n    }\n\n    // Illegal Argument: Illegal Argument: Cannot sort on a collection property\n    @Test\n    public void dictionary_sortByDictionaryElement() {\n        realm.executeTransaction(transactionRealm -> {\n                    transactionRealm.createObject(DictionaryAllTypes.class).getColumnStringDictionary().put(\"key1\", \"value1\");\n                    transactionRealm.createObject(DictionaryAllTypes.class).getColumnStringDictionary().put(\"key1\", \"value2\");\n                    transactionRealm.createObject(DictionaryAllTypes.class).getColumnStringDictionary().put(\"key1\", \"value0\");\n                    transactionRealm.createObject(DictionaryAllTypes.class).getColumnStringDictionary().put(\"key2\", \"value1\");\n                }\n        );\n        RealmResults<DictionaryAllTypes> results = realm.where(DictionaryAllTypes.class)\n                .rawPredicate(\"TRUEPREDICATE SORT(columnStringDictionary['key1'] ASC)\")\n                .findAll();\n\n        // Missing keys will be sorted as 'null' values\n        assertEquals(4, results.size());\n\n        String prevValue = null;\n        for (DictionaryAllTypes result : results) {\n            String value = result.getColumnStringDictionary().get(\"key1\");\n            assertTrue(prevValue == null || value != null && prevValue.compareTo(value) <= 0);\n            prevValue = value;\n        }\n    }\n\n    // FIXME Maybe move to QueryDescriptor or maybe even to RealmFieldType?\n    private boolean supportDistinct(RealmFieldType type) {\n        switch (type) {\n            case INTEGER:\n            case BOOLEAN:\n            case STRING:\n            case BINARY:\n            case DATE:\n            case FLOAT:\n            case DOUBLE:\n            case OBJECT:\n            case DECIMAL128:\n            case OBJECT_ID:\n            case UUID:\n            case LINKING_OBJECTS:\n            case MIXED:\n                return true;\n            case LIST:\n            case INTEGER_LIST:\n            case BOOLEAN_LIST:\n            case STRING_LIST:\n            case BINARY_LIST:\n            case DATE_LIST:\n            case FLOAT_LIST:\n            case DOUBLE_LIST:\n            case DECIMAL128_LIST:\n            case OBJECT_ID_LIST:\n            case UUID_LIST:\n            case MIXED_LIST:\n            case STRING_TO_MIXED_MAP:\n            case STRING_TO_BOOLEAN_MAP:\n            case STRING_TO_STRING_MAP:\n            case STRING_TO_INTEGER_MAP:\n            case STRING_TO_FLOAT_MAP:\n            case STRING_TO_DOUBLE_MAP:\n            case STRING_TO_BINARY_MAP:\n            case STRING_TO_DATE_MAP:\n            case STRING_TO_OBJECT_ID_MAP:\n            case STRING_TO_UUID_MAP:\n            case STRING_TO_DECIMAL128_MAP:\n            case STRING_TO_LINK_MAP:\n            case BOOLEAN_SET:\n            case STRING_SET:\n            case INTEGER_SET:\n            case FLOAT_SET:\n            case DOUBLE_SET:\n            case BINARY_SET:\n            case DATE_SET:\n            case DECIMAL128_SET:\n            case OBJECT_ID_SET:\n            case UUID_SET:\n            case LINK_SET:\n            case MIXED_SET:\n                return false;\n            case TYPED_LINK:\n        }\n        // Should never reach here as the above switch is exhaustive\n        throw new UnsupportedOperationException(\"Unhandled realm field type \" + type);\n    }\n\n    // Manual distinct method for verification. Uses field value's equals.\n    @NotNull\n    private Set<List<? super Object>> distinct(RealmResults<DynamicRealmObject> all, Object... fields) {\n        Set<List<? super Object>> values = new HashSet();\n\n        // Parsed hierarchical field accessors\n        List<String[]> fieldAccessors = new ArrayList<>();\n        for (Object field : fields) {\n            fieldAccessors.add(((String) field).split(\"\\\\.\"));\n        }\n\n        for (DynamicRealmObject object : all) {\n            List<? super Object> elements = new ArrayList<>(fields.length);\n            for (String[] split : fieldAccessors) {\n                int i = 0;\n                while (i < split.length - 1) {\n                    object = object.get(split[i]);\n                    i++;\n                }\n                String fieldName = split[i];\n                if (!object.isNull(fieldName)) {\n                    Object e = object.get(fieldName);\n                    // Need to convert byte arrays to list to detect duplicates when inserting to values\n                    if (e instanceof byte[]) {\n                        elements.add(convertBytesToList((byte[]) e));\n                    } else {\n                        elements.add(e);\n                    }\n                } else {\n                    elements.add(null);\n                }\n            }\n            values.add(elements);\n        }\n        return values;\n    }\n\n    private static List<Byte> convertBytesToList(byte[] bytes) {\n        final List<Byte> list = new ArrayList<>();\n        for (byte b : bytes) {\n            list.add(b);\n        }\n        return list;\n    }\n\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/RealmResultsTests.java",
    "content": "/*\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\npackage io.realm;\n\nimport androidx.test.annotation.UiThreadTest;\nimport androidx.test.ext.junit.runners.AndroidJUnit4;\n\nimport org.bson.types.Decimal128;\nimport org.bson.types.ObjectId;\nimport org.json.JSONException;\nimport org.junit.After;\nimport org.junit.Before;\nimport org.junit.Rule;\nimport org.junit.Test;\nimport org.junit.rules.ExpectedException;\nimport org.junit.runner.RunWith;\nimport org.mockito.Mockito;\nimport org.skyscreamer.jsonassert.JSONAssert;\n\nimport java.math.BigDecimal;\nimport java.text.SimpleDateFormat;\nimport java.time.temporal.ChronoUnit;\nimport java.util.Arrays;\nimport java.util.Calendar;\nimport java.util.Collection;\nimport java.util.Collections;\nimport java.util.Date;\nimport java.util.List;\nimport java.util.Set;\nimport java.util.TimeZone;\nimport java.util.UUID;\nimport java.util.concurrent.TimeUnit;\nimport java.util.concurrent.atomic.AtomicInteger;\n\nimport io.realm.entities.AllJavaTypes;\nimport io.realm.entities.AllTypes;\nimport io.realm.entities.CyclicType;\nimport io.realm.entities.DefaultValueOfField;\nimport io.realm.entities.DictionaryAllTypes;\nimport io.realm.entities.Dog;\nimport io.realm.entities.MappedAllJavaTypes;\nimport io.realm.entities.NonLatinFieldNames;\nimport io.realm.entities.Owner;\nimport io.realm.entities.PrimaryKeyAsLong;\nimport io.realm.entities.PrimaryKeyAsString;\nimport io.realm.entities.RandomPrimaryKey;\nimport io.realm.entities.StringOnly;\nimport io.realm.internal.OsResults;\nimport io.realm.log.RealmLog;\nimport io.realm.rule.RunInLooperThread;\nimport io.realm.rule.RunTestInLooperThread;\n\nimport static org.junit.Assert.assertArrayEquals;\nimport static org.junit.Assert.assertEquals;\nimport static org.junit.Assert.assertFalse;\nimport static org.junit.Assert.assertNotNull;\nimport static org.junit.Assert.assertNull;\nimport static org.junit.Assert.assertTrue;\nimport static org.junit.Assert.fail;\n\n@RunWith(AndroidJUnit4.class)\npublic class RealmResultsTests extends CollectionTests {\n\n    private final static int TEST_DATA_SIZE = 100;\n    private final static long YEAR_MILLIS = TimeUnit.DAYS.toMillis(365);\n    private final static long DECADE_MILLIS = 10 * TimeUnit.DAYS.toMillis(365);\n\n    @Rule\n    public final TestRealmConfigurationFactory configFactory = new TestRealmConfigurationFactory();\n    @Rule\n    public final ExpectedException thrown = ExpectedException.none();\n    @Rule\n    public final RunInLooperThread looperThread = new RunInLooperThread();\n\n    private Realm realm;\n    private RealmResults<AllTypes> collection;\n\n    private static final String uuid1 = \"017ba5ca-aa12-4afa-9219-e20cc3018599\";\n    private static final String uuid2 = \"027ba5ca-aa12-4afa-9219-e20cc3018599\";\n\n    @Before\n    public void setUp() {\n        RealmConfiguration realmConfig = configFactory.createConfiguration();\n        realm = Realm.getInstance(realmConfig);\n        populateTestRealm();\n        collection = realm.where(AllTypes.class)\n                .sort(AllTypes.FIELD_LONG, Sort.ASCENDING)\n                .findAll();\n    }\n\n    @After\n    public void tearDown() {\n        if (realm != null) {\n            realm.close();\n        }\n    }\n\n    private void populateTestRealm() {\n        populateTestRealm(TEST_DATA_SIZE);\n    }\n\n    @Test\n    public void findFirst() {\n        AllTypes result = realm.where(AllTypes.class).findFirst();\n        assertEquals(0, result.getColumnLong());\n        assertEquals(\"test data 0\", result.getColumnString());\n\n        AllTypes none = realm.where(AllTypes.class).equalTo(AllTypes.FIELD_STRING, \"smurf\").findFirst();\n        assertNull(none);\n    }\n\n    @Test\n    public void size_returns_Integer_MAX_VALUE_for_huge_results() {\n        final OsResults osResults = Mockito.mock(OsResults.class);\n        final RealmResults<AllTypes> targetResult = TestHelper.newRealmResults(realm, osResults, AllTypes.class);\n\n        Mockito.when(osResults.isLoaded()).thenReturn(true);\n        Mockito.when(osResults.size()).thenReturn(((long) Integer.MAX_VALUE) - 1);\n        assertEquals(Integer.MAX_VALUE - 1, targetResult.size());\n        Mockito.when(osResults.size()).thenReturn(((long) Integer.MAX_VALUE));\n        assertEquals(Integer.MAX_VALUE, targetResult.size());\n        Mockito.when(osResults.size()).thenReturn(((long) Integer.MAX_VALUE) + 1);\n        assertEquals(Integer.MAX_VALUE, targetResult.size());\n    }\n\n    @Test\n    public void subList() {\n        RealmResults<AllTypes> list = realm.where(AllTypes.class).findAll();\n        list.sort(\"columnLong\");\n        List<AllTypes> sublist = list.subList(Math.max(list.size() - 20, 0), list.size());\n        assertEquals(TEST_DATA_SIZE - 1, sublist.get(sublist.size() - 1).getColumnLong());\n    }\n\n    @SuppressWarnings(\"deprecation\")\n    @Test\n    public void unsupportedMethods() {\n        for (CollectionMutatorMethod method : CollectionMutatorMethod.values()) {\n            try {\n                switch (method) {\n                    case ADD_OBJECT: collection.add(new AllTypes()); break;\n                    case ADD_ALL_OBJECTS: collection.addAll(Collections.singletonList(new AllTypes())); break;\n                    case CLEAR: collection.clear(); break;\n                    case REMOVE_OBJECT: collection.remove(new AllTypes()); break;\n                    case REMOVE_ALL: collection.removeAll(Collections.singletonList(new AllTypes())); break;\n                    case RETAIN_ALL: collection.retainAll(Collections.singletonList(new AllTypes())); break;\n\n                    // Supported methods.\n                    case DELETE_ALL:\n                        continue;\n                }\n                fail(\"Unknown method or failed to throw:\" + method);\n            } catch (UnsupportedOperationException ignored) {\n            }\n        }\n\n        for (OrderedCollectionMutatorMethod method : OrderedCollectionMutatorMethod.values()) {\n            try {\n                switch (method) {\n                    case ADD_INDEX: collection.add(0, new AllTypes()); break;\n                    case ADD_ALL_INDEX: collection.addAll(0, Collections.singletonList(new AllTypes())); break;\n                    case SET: collection.set(0, new AllTypes()); break;\n                    case REMOVE_INDEX: collection.remove(0); break;\n\n                    // Supported methods.\n                    case DELETE_INDEX:\n                    case DELETE_FIRST:\n                    case DELETE_LAST:\n                        continue;\n                }\n                fail(\"Unknown method or failed to throw:\" + method);\n            } catch (UnsupportedOperationException ignored) {\n            }\n        }\n    }\n\n    // Triggers an ARM bug.\n    @Test\n    public void verifyArmComparisons() {\n        realm.beginTransaction();\n        realm.delete(AllTypes.class);\n        long id = -1;\n        for (int i = 0; i < 10; i++) {\n            AllTypes allTypes = realm.createObject(AllTypes.class);\n            allTypes.setColumnLong(id--);\n        }\n        realm.commitTransaction();\n\n        assertEquals(10, realm.where(AllTypes.class).between(AllTypes.FIELD_LONG, -10, -1).findAll().size());\n        assertEquals(10, realm.where(AllTypes.class).greaterThan(AllTypes.FIELD_LONG, -11).findAll().size());\n        assertEquals(10, realm.where(AllTypes.class).greaterThanOrEqualTo(AllTypes.FIELD_LONG, -10).findAll().size());\n        assertEquals(10, realm.where(AllTypes.class).lessThan(AllTypes.FIELD_LONG, 128).findAll().size());\n        assertEquals(10, realm.where(AllTypes.class).lessThan(AllTypes.FIELD_LONG, 127).findAll().size());\n        assertEquals(10, realm.where(AllTypes.class).lessThanOrEqualTo(AllTypes.FIELD_LONG, -1).findAll().size());\n        assertEquals(10, realm.where(AllTypes.class).lessThan(AllTypes.FIELD_LONG, 0).findAll().size());\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void changeListener_syncIfNeeded_updatedFromOtherThread() {\n        final Realm realm = looperThread.getRealm();\n        populateTestRealm(realm, 10);\n\n        final RealmResults<AllTypes> results = realm.where(AllTypes.class).lessThan(AllTypes.FIELD_LONG, 10).findAll();\n        assertEquals(10, results.size());\n\n        // 1. Deletes first object from another thread.\n        realm.executeTransactionAsync(new Realm.Transaction() {\n            @Override\n            public void execute(Realm realm) {\n                realm.where(AllTypes.class).equalTo(AllTypes.FIELD_LONG, 0).findFirst().deleteFromRealm();\n            }\n        }, new Realm.Transaction.OnSuccess() {\n            @Override\n            public void onSuccess() {\n                // 2. RealmResults are refreshed before onSuccess is called.\n                assertEquals(9, results.size());\n                realm.close();\n                looperThread.testComplete();\n            }\n        });\n    }\n\n    // distinctAsync\n    private void populateTestRealm(int objects) {\n        realm.beginTransaction();\n        realm.deleteAll();\n        for (int i = 0; i < objects; ++i) {\n            AllTypes allTypes = realm.createObject(AllTypes.class);\n            allTypes.setColumnBoolean((i % 2) == 0);\n            allTypes.setColumnBinary(new byte[]{1, 2, 3});\n            allTypes.setColumnDate(new Date(YEAR_MILLIS * (i - objects / 2)));\n            allTypes.setColumnDouble(Math.PI + i);\n            allTypes.setColumnFloat(1.234567f + i);\n            allTypes.setColumnString(\"test data \" + i);\n            allTypes.setColumnLong(i);\n            Dog d = realm.createObject(Dog.class);\n            d.setName(\"Foo \" + i);\n            allTypes.setColumnRealmObject(d);\n            allTypes.getColumnRealmList().add(d);\n            NonLatinFieldNames nonLatinFieldNames = realm.createObject(NonLatinFieldNames.class);\n            nonLatinFieldNames.set델타(i);\n            nonLatinFieldNames.setΔέλτα(i);\n        }\n        realm.commitTransaction();\n    }\n\n\n    private void populateTestRealm(Realm testRealm, int objects) {\n        testRealm.beginTransaction();\n        testRealm.deleteAll();\n        for (int i = 0; i < objects; i++) {\n            AllTypes allTypes = testRealm.createObject(AllTypes.class);\n            allTypes.setColumnBoolean((i % 3) == 0);\n            allTypes.setColumnBinary(new byte[]{1, 2, 3});\n            allTypes.setColumnDate(new Date(DECADE_MILLIS * (i - (objects / 2))));\n            allTypes.setColumnDouble(Math.PI);\n            allTypes.setColumnFloat(1.234567f + i);\n            allTypes.setColumnString(\"test data \" + i);\n            allTypes.setColumnLong(i);\n            NonLatinFieldNames nonLatinFieldNames = testRealm.createObject(NonLatinFieldNames.class);\n            nonLatinFieldNames.set델타(i);\n            nonLatinFieldNames.setΔέλτα(i);\n            nonLatinFieldNames.set베타(1.234567f + i);\n            nonLatinFieldNames.setΒήτα(1.234567f + i);\n        }\n        testRealm.commitTransaction();\n    }\n\n\n    private RealmResults<Dog> populateRealmResultsOnLinkView(Realm realm) {\n        realm.beginTransaction();\n        Owner owner = realm.createObject(Owner.class);\n        for (int i = 0; i < 10; i++) {\n            Dog dog = new Dog();\n            dog.setName(\"name_\" + i);\n            dog.setOwner(owner);\n            dog.setAge(i);\n            dog.setBirthday(new Date(i));\n            owner.getDogs().add(dog);\n        }\n        realm.commitTransaction();\n\n\n        return owner.getDogs().where().lessThan(Dog.FIELD_AGE, 5).findAll();\n    }\n\n    // If a RealmResults is built on a link view, when the link view is deleted on the same thread, within the same\n    // event loop, the RealmResults stays without changes since it is detached until the next event loop. In the next\n    // event loop, the results will be empty because of the parent link view is deleted.\n    // 1. Create results from link view.\n    // 2. Delete the parent link view by a local transaction.\n    // 3. Within the same event loop, the results stays the same.\n    // 4. The results change listener called, the results becomes empty.\n    @Test\n    @RunTestInLooperThread\n    public void accessors_resultsBuiltOnDeletedLinkView_deletionAsALocalCommit() {\n        Realm realm = looperThread.getRealm();\n        // Step 1\n        RealmResults<Dog> dogs = populateRealmResultsOnLinkView(realm);\n        looperThread.keepStrongReference(dogs);\n        dogs.addChangeListener(new RealmChangeListener<RealmResults<Dog>>() {\n            @Override\n            public void onChange(RealmResults<Dog> dogs) {\n                // Step 4.\n                // The results is still valid, but empty.\n                assertEquals(true, dogs.isValid());\n                assertEquals(true, dogs.isEmpty());\n                assertEquals(0, dogs.size());\n                try {\n                    dogs.first();\n                    fail();\n                } catch (IndexOutOfBoundsException ignored) {\n                }\n\n                assertEquals(0, dogs.sum(Dog.FIELD_AGE).intValue());\n                assertEquals(0f, dogs.sum(Dog.FIELD_HEIGHT).floatValue(), 0f);\n                assertEquals(0d, dogs.sum(Dog.FIELD_WEIGHT).doubleValue(), 0d);\n                assertEquals(0d, dogs.average(Dog.FIELD_AGE), 0d);\n                assertEquals(0d, dogs.average(Dog.FIELD_HEIGHT), 0d);\n                assertEquals(0d, dogs.average(Dog.FIELD_WEIGHT), 0d);\n                assertEquals(null, dogs.min(Dog.FIELD_AGE));\n                assertEquals(null, dogs.max(Dog.FIELD_AGE));\n                assertEquals(null, dogs.minDate(Dog.FIELD_BIRTHDAY));\n                assertEquals(null, dogs.maxDate(Dog.FIELD_BIRTHDAY));\n\n                assertEquals(0, dogs.where().findAll().size());\n\n                looperThread.testComplete();\n            }\n        });\n\n        // Step 2\n        realm.executeTransaction(new Realm.Transaction() {\n            @Override\n            public void execute(Realm realm) {\n                realm.where(Owner.class).findAll().deleteAllFromRealm();\n            }\n        });\n\n        // Step 3\n        assertEquals(true, dogs.isValid());\n        assertEquals(0, dogs.size());\n        // The link view has been deleted.\n        assertEquals(0, dogs.where().findAll().size());\n    }\n\n    // If a RealmResults is built on a link view, when the link view is deleted on a remote thread, within the same\n    // event loop, the RealmResults stays without changes since the Realm version doesn't change. In the next\n    // event loop, the results will be empty because of the parent link view is deleted.\n    // 1. Create results from link view.\n    // 2. Delete the parent link view by a remote transaction.\n    // 3. Within the same event loop, the results stays the same.\n    // 4. The results change listener called, the results becomes empty.\n    @Test\n    @RunTestInLooperThread\n    public void accessors_resultsBuiltOnDeletedLinkView_deletionAsARemoteCommit() {\n        // Step 1\n        Realm realm = looperThread.getRealm();\n        RealmResults<Dog> dogs = populateRealmResultsOnLinkView(realm);\n        looperThread.keepStrongReference(dogs);\n        dogs.addChangeListener(new RealmChangeListener<RealmResults<Dog>>() {\n            @Override\n            public void onChange(RealmResults<Dog> dogs) {\n                // Step 4\n                // The results is still valid, but empty.\n                assertEquals(true, dogs.isValid());\n                assertEquals(true, dogs.isEmpty());\n                assertEquals(0, dogs.size());\n                try {\n                    dogs.first();\n                    fail();\n                } catch (IndexOutOfBoundsException ignored) {\n                }\n\n                assertEquals(0, dogs.sum(Dog.FIELD_AGE).intValue());\n                assertEquals(0f, dogs.sum(Dog.FIELD_HEIGHT).floatValue(), 0f);\n                assertEquals(0d, dogs.sum(Dog.FIELD_WEIGHT).doubleValue(), 0d);\n                assertEquals(0d, dogs.average(Dog.FIELD_AGE), 0d);\n                assertEquals(0d, dogs.average(Dog.FIELD_HEIGHT), 0d);\n                assertEquals(0d, dogs.average(Dog.FIELD_WEIGHT), 0d);\n                assertEquals(null, dogs.min(Dog.FIELD_AGE));\n                assertEquals(null, dogs.max(Dog.FIELD_AGE));\n                assertEquals(null, dogs.minDate(Dog.FIELD_BIRTHDAY));\n                assertEquals(null, dogs.maxDate(Dog.FIELD_BIRTHDAY));\n\n                assertEquals(0, dogs.where().findAll().size());\n\n                looperThread.testComplete();\n            }\n        });\n\n\n        // Step 2\n        realm.executeTransactionAsync(new Realm.Transaction() {\n            @Override\n            public void execute(Realm realm) {\n                realm.where(Owner.class).findAll().deleteAllFromRealm();\n            }\n        });\n\n        // Step 3\n        assertEquals(true, dogs.isValid());\n        assertEquals(5, dogs.size());\n        // The link view still exists\n        assertEquals(5, dogs.where().findAll().size());\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void addChangeListener() {\n        Realm realm = looperThread.getRealm();\n        RealmResults<AllTypes> collection = realm.where(AllTypes.class).findAll();\n\n        looperThread.keepStrongReference(collection);\n        collection.addChangeListener(new RealmChangeListener<RealmResults<AllTypes>>() {\n            @Override\n            public void onChange(RealmResults<AllTypes> object) {\n                looperThread.testComplete();\n            }\n        });\n\n        realm.beginTransaction();\n        realm.createObject(AllTypes.class);\n        realm.commitTransaction();\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void addChangeListener_twice() {\n        final AtomicInteger listenersTriggered = new AtomicInteger(0);\n        final Realm realm = looperThread.getRealm();\n        RealmResults<AllTypes> collection = realm.where(AllTypes.class).findAll();\n\n        RealmChangeListener<RealmResults<AllTypes>> listener = new RealmChangeListener<RealmResults<AllTypes>>() {\n            @Override\n            public void onChange(RealmResults<AllTypes> object) {\n                listenersTriggered.incrementAndGet();\n            }\n        };\n\n        realm.addChangeListener(new RealmChangeListener<Realm>() {\n            @Override\n            public void onChange(Realm object) {\n                listenersTriggered.incrementAndGet();\n                looperThread.postRunnable(new Runnable() {\n                    @Override\n                    public void run() {\n                        if (listenersTriggered.get() == 1) {\n                            looperThread.testComplete();\n                        } else {\n                            fail(\"Only global listener should be triggered\");\n                        }\n                    }\n                });\n            }\n        });\n\n        // Adding it twice will be ignored, so removing it will not cause the listener to be triggered.\n        looperThread.keepStrongReference(collection);\n        collection.addChangeListener(listener);\n        collection.addChangeListener(listener);\n        collection.removeChangeListener(listener);\n\n        realm.beginTransaction();\n        realm.createObject(AllTypes.class);\n        realm.commitTransaction();\n    }\n\n    @Test\n    @UiThreadTest\n    public void addChangeListener_null() {\n        try {\n            collection.addChangeListener((RealmChangeListener<RealmResults<AllTypes>>) null);\n            fail();\n        } catch (IllegalArgumentException ignored) {\n        }\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void removeChangeListener() {\n        final AtomicInteger listenersTriggered = new AtomicInteger(0);\n        final Realm realm = looperThread.getRealm();\n        RealmResults<AllTypes> collection = realm.where(AllTypes.class).findAll();\n\n        RealmChangeListener<RealmResults<AllTypes>> listener = new RealmChangeListener<RealmResults<AllTypes>>() {\n            @Override\n            public void onChange(RealmResults<AllTypes> object) {\n                listenersTriggered.incrementAndGet();\n            }\n        };\n\n        looperThread.keepStrongReference(collection);\n        collection.addChangeListener(listener);\n        collection.removeChangeListener(listener);\n\n        realm.beginTransaction();\n        realm.createObject(AllTypes.class);\n        realm.commitTransaction();\n\n        // The above commit should have put a REALM_CHANGED event on the Looper queue before this runnable.\n        looperThread.postRunnable(new Runnable() {\n            @Override\n            public void run() {\n                if (listenersTriggered.get() == 0) {\n                    looperThread.testComplete();\n                } else {\n                    fail(\"Listener wasn't removed\");\n                }\n            }\n        });\n    }\n\n    @Test\n    @UiThreadTest\n    public void removeChangeListener_null() {\n        try {\n            collection.removeChangeListener((RealmChangeListener) null);\n            fail();\n        } catch (IllegalArgumentException ignored) {\n        }\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void removeAllChangeListeners() {\n        final AtomicInteger listenersTriggered = new AtomicInteger(0);\n        final Realm realm = looperThread.getRealm();\n        RealmResults<AllTypes> collection = realm.where(AllTypes.class).findAll();\n\n        RealmChangeListener<RealmResults<AllTypes>> listenerA = new RealmChangeListener<RealmResults<AllTypes>>() {\n            @Override\n            public void onChange(RealmResults<AllTypes> object) {\n                listenersTriggered.incrementAndGet();\n            }\n        };\n        RealmChangeListener<RealmResults<AllTypes>> listenerB = new RealmChangeListener<RealmResults<AllTypes>>() {\n            @Override\n            public void onChange(RealmResults<AllTypes> object) {\n                listenersTriggered.incrementAndGet();\n            }\n        };\n\n        looperThread.keepStrongReference(collection);\n        collection.addChangeListener(listenerA);\n        collection.addChangeListener(listenerB);\n        collection.removeAllChangeListeners();\n\n        realm.beginTransaction();\n        realm.createObject(AllTypes.class);\n        realm.commitTransaction();\n\n        // The above commit should have put a REALM_CHANGED event on the Looper queue before this runnable.\n        looperThread.postRunnable(new Runnable() {\n            @Override\n            public void run() {\n                if (listenersTriggered.get() == 0) {\n                    looperThread.testComplete();\n                } else {\n                    fail(\"Listeners wasn't removed\");\n                }\n            }\n        });\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void removeAllChangeListeners_thenAdd() {\n        final Realm realm = looperThread.getRealm();\n        RealmResults<AllTypes> collection = realm.where(AllTypes.class).findAll();\n\n        collection.addChangeListener(new RealmChangeListener<RealmResults<AllTypes>>() {\n            @Override\n            public void onChange(RealmResults<AllTypes> element) {\n                fail();\n            }\n        });\n        collection.removeAllChangeListeners();\n\n        collection.addChangeListener(new RealmChangeListener<RealmResults<AllTypes>>() {\n            @Override\n            public void onChange(RealmResults<AllTypes> results) {\n                assertEquals(1, results.size());\n                looperThread.testComplete();\n            }\n        });\n\n        realm.beginTransaction();\n        realm.createObject(AllTypes.class);\n        realm.commitTransaction();\n    }\n\n    @Test\n    public void deleteAndDeleteAll() {\n        realm.beginTransaction();\n        for (int i = 0; i < 10; i++) {\n            StringOnly stringOnly = realm.createObject(StringOnly.class);\n            stringOnly.setChars(\"String \" + i);\n        }\n        realm.commitTransaction();\n\n        RealmResults<StringOnly> stringOnlies = realm.where(StringOnly.class).findAll();\n\n        realm.beginTransaction();\n        // Removes one object.\n        stringOnlies.get(0).deleteFromRealm();\n        realm.commitTransaction();\n\n        realm.beginTransaction();\n        // Removes the rest.\n        stringOnlies.deleteAllFromRealm();\n        realm.commitTransaction();\n\n        assertEquals(0, realm.where(StringOnly.class).findAll().size());\n    }\n\n    @Test\n    public void syncQuery_defaultValuesAreIgnored() {\n        final String fieldIgnoredValue = DefaultValueOfField.FIELD_IGNORED_DEFAULT_VALUE + \".modified\";\n        final String fieldStringValue = DefaultValueOfField.FIELD_STRING_DEFAULT_VALUE + \".modified\";\n        final String fieldRandomStringValue = \"non-random\";\n        final short fieldShortValue = (short) (DefaultValueOfField.FIELD_SHORT_DEFAULT_VALUE + 1);\n        final int fieldIntValue = DefaultValueOfField.FIELD_INT_DEFAULT_VALUE + 1;\n        final long fieldLongPrimaryKeyValue = DefaultValueOfField.FIELD_LONG_PRIMARY_KEY_DEFAULT_VALUE + 1;\n        final long fieldLongValue = DefaultValueOfField.FIELD_LONG_DEFAULT_VALUE + 1;\n        final byte fieldByteValue = (byte) (DefaultValueOfField.FIELD_BYTE_DEFAULT_VALUE + 1);\n        final float fieldFloatValue = DefaultValueOfField.FIELD_FLOAT_DEFAULT_VALUE + 1;\n        final double fieldDoubleValue = DefaultValueOfField.FIELD_DOUBLE_DEFAULT_VALUE + 1;\n        final boolean fieldBooleanValue = !DefaultValueOfField.FIELD_BOOLEAN_DEFAULT_VALUE;\n        final Date fieldDateValue = new Date(DefaultValueOfField.FIELD_DATE_DEFAULT_VALUE.getTime() + 1);\n        final byte[] fieldBinaryValue = {(byte) (DefaultValueOfField.FIELD_BINARY_DEFAULT_VALUE[0] - 1)};\n        final int fieldObjectIntValue = RandomPrimaryKey.FIELD_INT_DEFAULT_VALUE + 1;\n        final int fieldListIntValue = RandomPrimaryKey.FIELD_INT_DEFAULT_VALUE + 2;\n\n        realm.executeTransaction(new Realm.Transaction() {\n            @Override\n            public void execute(Realm realm) {\n                final DefaultValueOfField obj = new DefaultValueOfField();\n                obj.setFieldIgnored(fieldIgnoredValue);\n                obj.setFieldString(fieldStringValue);\n                obj.setFieldRandomString(fieldRandomStringValue);\n                obj.setFieldShort(fieldShortValue);\n                obj.setFieldInt(fieldIntValue);\n                obj.setFieldLongPrimaryKey(fieldLongPrimaryKeyValue);\n                obj.setFieldLong(fieldLongValue);\n                obj.setFieldByte(fieldByteValue);\n                obj.setFieldFloat(fieldFloatValue);\n                obj.setFieldDouble(fieldDoubleValue);\n                obj.setFieldBoolean(fieldBooleanValue);\n                obj.setFieldDate(fieldDateValue);\n                obj.setFieldBinary(fieldBinaryValue);\n\n                final RandomPrimaryKey fieldObjectValue = new RandomPrimaryKey();\n                fieldObjectValue.setFieldInt(fieldObjectIntValue);\n                obj.setFieldObject(fieldObjectValue);\n\n                final RealmList<RandomPrimaryKey> list = new RealmList<RandomPrimaryKey>();\n                final RandomPrimaryKey listItem = new RandomPrimaryKey();\n                listItem.setFieldInt(fieldListIntValue);\n                list.add(listItem);\n                obj.setFieldList(list);\n\n                realm.copyToRealm(obj);\n            }\n        });\n\n        final RealmResults<DefaultValueOfField> result = realm.where(DefaultValueOfField.class)\n                .equalTo(DefaultValueOfField.FIELD_LONG_PRIMARY_KEY,\n                        fieldLongPrimaryKeyValue).findAll();\n\n        final DefaultValueOfField obj = result.first();\n\n        assertEquals(DefaultValueOfField.FIELD_IGNORED_DEFAULT_VALUE/*not fieldIgnoredValue*/,\n                obj.getFieldIgnored());\n        assertEquals(fieldStringValue, obj.getFieldString());\n        assertEquals(fieldRandomStringValue, obj.getFieldRandomString());\n        assertEquals(fieldShortValue, obj.getFieldShort());\n        assertEquals(fieldIntValue, obj.getFieldInt());\n        assertEquals(fieldLongPrimaryKeyValue, obj.getFieldLongPrimaryKey());\n        assertEquals(fieldLongValue, obj.getFieldLong());\n        assertEquals(fieldByteValue, obj.getFieldByte());\n        assertEquals(fieldFloatValue, obj.getFieldFloat(), 0f);\n        assertEquals(fieldDoubleValue, obj.getFieldDouble(), 0d);\n        assertEquals(fieldBooleanValue, obj.isFieldBoolean());\n        assertEquals(fieldDateValue, obj.getFieldDate());\n        assertTrue(Arrays.equals(fieldBinaryValue, obj.getFieldBinary()));\n        assertEquals(fieldObjectIntValue, obj.getFieldObject().getFieldInt());\n        assertEquals(1, obj.getFieldList().size());\n        assertEquals(fieldListIntValue, obj.getFieldList().first().getFieldInt());\n    }\n\n    @Test\n    public void getRealm() {\n        RealmResults<AllTypes> collection = realm.where(AllTypes.class).findAll();\n        assertTrue(realm == collection.getRealm());\n    }\n\n    @Test\n    public void getRealm_throwsIfDynamicRealm() {\n        DynamicRealm dRealm = DynamicRealm.getInstance(realm.getConfiguration());\n        RealmResults<DynamicRealmObject> collection = dRealm.where(AllTypes.CLASS_NAME).findAll();\n\n        try {\n            collection.getRealm();\n            fail();\n        } catch (IllegalStateException ignore) {\n        } finally {\n            dRealm.close();\n        }\n    }\n\n    @Test\n    public void getRealm_throwsIfRealmClosed() {\n        RealmResults<AllTypes> collection = realm.where(AllTypes.class).findAll();\n        realm.close();\n        try {\n            collection.getRealm();\n            fail();\n        } catch (IllegalStateException ignore) {\n        }\n    }\n\n    private void populateMappedAllJavaTypes(int objects) {\n        realm.beginTransaction();\n        realm.deleteAll();\n        for (int i = 0; i < objects; ++i) {\n            MappedAllJavaTypes obj = realm.createObject(MappedAllJavaTypes.class, i);\n            obj.fieldBoolean =  ((i % 2) == 0);\n            obj.fieldBinary = (new byte[]{1, 2, 3});\n            obj.fieldDate = (new Date(YEAR_MILLIS * (i - objects / 2)));\n            obj.fieldDouble = (Math.PI + i);\n            obj.fieldFloat = (1.234567f + i);\n            obj.fieldString = (\"test data \" + i);\n            obj.fieldLong = i;\n            obj.fieldObject = obj;\n            obj.fieldDecimal128 = new Decimal128( i);\n            obj.fieldObjectId = new ObjectId(TestHelper.generateObjectIdHexString(i));\n            obj.fieldUUID = UUID.fromString(TestHelper.generateUUIDString(i));\n            obj.fieldList.add(obj);\n        }\n        realm.commitTransaction();\n    }\n\n    private void populateAllJavaTypes(int objects) {\n        realm.beginTransaction();\n        realm.deleteAll();\n        for (int i = 0; i < objects; ++i) {\n            AllJavaTypes obj = realm.createObject(AllJavaTypes.class, i);\n            obj.setFieldBoolean((i % 2) == 0);\n            obj.setFieldBinary(new byte[]{1, 2, 3});\n            obj.setFieldDate(new Date(YEAR_MILLIS * (i - objects / 2)));\n            obj.setFieldDouble(Math.PI + i);\n            obj.setFieldFloat(1.234567f + i);\n            obj.setFieldString(\"test data \" + i);\n            obj.setFieldLong(i);\n            obj.setFieldObject(obj);\n            obj.setFieldDecimal128(new Decimal128(new BigDecimal(i + \".23456789\")));\n            obj.setFieldObjectId(new ObjectId(TestHelper.generateObjectIdHexString(i)));\n            obj.setFieldUUID(UUID.fromString(TestHelper.generateUUIDString(i)));\n            obj.getFieldList().add(obj);\n        }\n        realm.commitTransaction();\n    }\n\n    enum BulkSetMethods {\n        STRING,\n        BOOLEAN,\n        BYTE,\n        SHORT,\n        INTEGER,\n        LONG,\n        FLOAT,\n        DOUBLE,\n        BINARY,\n        DATE,\n        DECIMAL128,\n        OBJECT_ID,\n        UUID,\n        OBJECT,\n        MODEL_LIST,\n        STRING_VALUE_LIST,\n        BOOLEAN_VALUE_LIST,\n        BYTE_VALUE_LIST,\n        SHORT_VALUE_LIST,\n        INTEGER_VALUE_LIST,\n        LONG_VALUE_LIST,\n        FLOAT_VALUE_LIST,\n        DOUBLE_VALUE_LIST,\n        BINARY_VALUE_LIST,\n        DATE_VALUE_LIST,\n        DECIMAL128_VALUE_LIST,\n        OBJECT_ID_VALUE_LIST,\n        UUID_VALUE_LIST\n    }\n\n    interface ElementValidator<T> {\n        void validate(T obj);\n    }\n\n    private <T extends RealmModel> void assertElements(RealmResults<T> collection, ElementValidator<T> validator) {\n        for (T obj : collection) {\n            validator.validate(obj);\n        }\n    }\n\n    @Test\n    public void setValue() {\n        populateAllJavaTypes(5);\n        RealmResults<AllJavaTypes> collection = realm.where(AllJavaTypes.class).findAll();\n        realm.beginTransaction();\n        for (BulkSetMethods type : BulkSetMethods.values()) {\n            switch(type) {\n                case STRING:\n                    collection.setValue(AllJavaTypes.FIELD_STRING, \"foo\");\n                    assertElements(collection, obj -> assertEquals(\"foo\", obj.getFieldString()));\n                    collection.setValue(AllJavaTypes.FIELD_STRING, null);\n                    assertElements(collection, obj -> assertEquals(null, obj.getFieldString()));\n                    break;\n                case BOOLEAN:\n                    collection.setValue(AllJavaTypes.FIELD_BOOLEAN, true);\n                    assertElements(collection, obj -> assertTrue(obj.isFieldBoolean()));\n                    break;\n                case BYTE:\n                    collection.setValue(AllJavaTypes.FIELD_BYTE, (byte) 1);\n                    assertElements(collection, obj -> assertEquals((byte)1, obj.getFieldByte()));\n                    break;\n                case SHORT:\n                    collection.setValue(AllJavaTypes.FIELD_SHORT, (short) 2);\n                    assertElements(collection, obj -> assertEquals((short)2, obj.getFieldShort()));\n                    break;\n                case INTEGER:\n                    collection.setValue(AllJavaTypes.FIELD_INT, 3);\n                    assertElements(collection, obj -> assertEquals(3, obj.getFieldInt()));\n                    break;\n                case LONG:\n                    collection.setValue(AllJavaTypes.FIELD_LONG, 4L);\n                    assertElements(collection, obj -> assertEquals(4L, obj.getFieldLong()));\n                    break;\n                case FLOAT:\n                    collection.setValue(AllJavaTypes.FIELD_FLOAT, 1.23F);\n                    assertElements(collection, obj -> assertEquals(1.23F, obj.getFieldFloat(), 0F));\n                    break;\n                case DOUBLE:\n                    collection.setValue(AllJavaTypes.FIELD_DOUBLE, 1.234);\n                    assertElements(collection, obj -> assertEquals(1.234, obj.getFieldDouble(), 0F));\n                    break;\n                case BINARY:\n                    collection.setValue(AllJavaTypes.FIELD_BINARY, new byte[]{1,2,3});\n                    assertElements(collection, obj -> assertArrayEquals(new byte[]{1,2,3}, obj.getFieldBinary()));\n                    collection.setValue(AllJavaTypes.FIELD_BINARY, null);\n                    assertElements(collection, obj -> assertNull(obj.getFieldBinary()));\n                    break;\n                case DATE:\n                    collection.setValue(AllJavaTypes.FIELD_DATE, new Date(1000));\n                    assertElements(collection, obj -> assertEquals(new Date(1000), obj.getFieldDate()));\n                    collection.setValue(AllJavaTypes.FIELD_DATE, null);\n                    assertElements(collection, obj -> assertNull(obj.getFieldDate()));\n                    break;\n                case DECIMAL128:\n                    collection.setValue(AllJavaTypes.FIELD_DECIMAL128, new Decimal128(1000));\n                    assertElements(collection, obj -> assertEquals(new Decimal128(1000), obj.getFieldDecimal128()));\n                    collection.setValue(AllJavaTypes.FIELD_DECIMAL128, null);\n                    assertElements(collection, obj -> assertNull(obj.getFieldDecimal128()));\n                    break;\n                case OBJECT_ID:\n                    String hex = TestHelper.randomObjectIdHexString();\n                    collection.setValue(AllJavaTypes.FIELD_OBJECT_ID, new ObjectId(hex));\n                    assertElements(collection, obj -> assertEquals(new ObjectId(hex), obj.getFieldObjectId()));\n                    collection.setValue(AllJavaTypes.FIELD_OBJECT_ID, null);\n                    assertElements(collection, obj -> assertNull(obj.getFieldObjectId()));\n                    break;\n                case UUID:\n                    String uuid = UUID.randomUUID().toString();\n                    collection.setValue(AllJavaTypes.FIELD_UUID, UUID.fromString(uuid));\n                    assertElements(collection, obj -> assertEquals(UUID.fromString(uuid), obj.getFieldUUID()));\n                    collection.setValue(AllJavaTypes.FIELD_UUID, null);\n                    assertElements(collection, obj -> assertNull(obj.getFieldUUID()));\n                    break;\n                case OBJECT: {\n                    AllJavaTypes childObj = realm.createObject(AllJavaTypes.class, 42);\n                    collection.setValue(AllJavaTypes.FIELD_OBJECT, childObj);\n                    assertElements(collection, obj -> assertEquals(childObj, obj.getFieldObject()));\n                    collection.setValue(AllJavaTypes.FIELD_OBJECT, null);\n                    assertElements(collection, obj -> assertNull(obj.getFieldObject()));\n                    break;\n                }\n                case MODEL_LIST: {\n                    AllJavaTypes childObj = realm.createObject(AllJavaTypes.class, 43);\n                    collection.setValue(AllJavaTypes.FIELD_LIST, new RealmList<>(childObj));\n                    assertElements(collection, obj -> {\n                        assertEquals(1, obj.getFieldList().size());\n                        assertEquals(childObj, obj.getFieldList().first());\n                    });\n                    break;\n                }\n                case STRING_VALUE_LIST: {\n                    RealmList<String> list = new RealmList<>(\"Foo\", \"Bar\");\n                    collection.setValue(AllJavaTypes.FIELD_STRING_LIST, list);\n                    assertElements(collection, obj -> {\n                        assertEquals(\"Foo\", obj.getFieldStringList().first());\n                        assertEquals(\"Bar\", obj.getFieldStringList().last());\n                    });\n                    break;\n                }\n                case BOOLEAN_VALUE_LIST: {\n                    RealmList<Boolean> list = new RealmList<>(true, false);\n                    collection.setValue(AllJavaTypes.FIELD_BOOLEAN_LIST, list);\n                    assertElements(collection, obj -> {\n                        assertTrue(obj.getFieldBooleanList().first());\n                        assertFalse(obj.getFieldBooleanList().last());\n                    });\n                    break;\n                }\n                case BYTE_VALUE_LIST: {\n                    RealmList<Byte> list = new RealmList<>((byte) 1, (byte) 2);\n                    collection.setValue(AllJavaTypes.FIELD_BYTE_LIST, list);\n                    assertElements(collection, obj -> {\n                        assertEquals(Byte.valueOf((byte) 1), obj.getFieldByteList().first());\n                        assertEquals(Byte.valueOf((byte) 2), obj.getFieldByteList().last());\n                    });\n                    break;\n                }\n                case SHORT_VALUE_LIST: {\n                    RealmList<Short> list = new RealmList<>((short) 1, (short) 2);\n                    collection.setValue(AllJavaTypes.FIELD_SHORT_LIST, list);\n                    assertElements(collection, obj -> {\n                        assertEquals(Short.valueOf((short) 1), obj.getFieldShortList().first());\n                        assertEquals(Short.valueOf((short) 2), obj.getFieldShortList().last());\n                    });\n                    break;\n                }\n                case INTEGER_VALUE_LIST: {\n                    RealmList<Integer> list = new RealmList<>(1, 2);\n                    collection.setValue(AllJavaTypes.FIELD_INTEGER_LIST, list);\n                    assertElements(collection, obj -> {\n                        assertEquals(Integer.valueOf(1), obj.getFieldIntegerList().first());\n                        assertEquals(Integer.valueOf(2), obj.getFieldIntegerList().last());\n                    });\n                    break;\n                }\n                case LONG_VALUE_LIST: {\n                    RealmList<Long> list = new RealmList<>(1L, 2L);\n                    collection.setValue(AllJavaTypes.FIELD_LONG_LIST, list);\n                    assertElements(collection, obj -> {\n                        assertEquals(Long.valueOf(1), obj.getFieldLongList().first());\n                        assertEquals(Long.valueOf(2), obj.getFieldLongList().last());\n                    });\n                    break;\n                }\n                case FLOAT_VALUE_LIST: {\n                    RealmList<Float> list = new RealmList<>(1.1F, 2.2F);\n                    collection.setValue(AllJavaTypes.FIELD_FLOAT_LIST, list);\n                    assertElements(collection, obj -> {\n                        assertEquals(1.1F, obj.getFieldFloatList().first(), 0F);\n                        assertEquals(2.2F, obj.getFieldFloatList().last(), 0F);\n                    });\n                    break;\n                }\n                case DOUBLE_VALUE_LIST: {\n                    RealmList<Double> list = new RealmList<>(1.1D, 2.2D);\n                    collection.setValue(AllJavaTypes.FIELD_DOUBLE_LIST, list);\n                    assertElements(collection, obj -> {\n                        assertEquals(1.1D, obj.getFieldDoubleList().first(), 0D);\n                        assertEquals(2.2D, obj.getFieldDoubleList().last(), 0D);\n                    });\n                    break;\n                }\n                case BINARY_VALUE_LIST: {\n                    RealmList<byte[]> list = new RealmList<>(new byte[] {1,2,3}, new byte[] {2,3,4});\n                    collection.setValue(AllJavaTypes.FIELD_BINARY_LIST, list);\n                    assertElements(collection, obj -> {\n                        assertArrayEquals(new byte[] {1,2,3}, obj.getFieldBinaryList().first());\n                        assertArrayEquals(new byte[] {2,3,4}, obj.getFieldBinaryList().last());\n                    });\n                    break;\n                }\n                case DATE_VALUE_LIST:  {\n                    RealmList<Date> list = new RealmList<>(new Date(1000), new Date(2000));\n                    collection.setValue(AllJavaTypes.FIELD_DATE_LIST, list);\n                    assertElements(collection, obj -> {\n                        assertEquals(new Date(1000), obj.getFieldDateList().first());\n                        assertEquals(new Date(2000), obj.getFieldDateList().last());\n                    });\n                    break;\n                }\n                case DECIMAL128_VALUE_LIST:  {\n                    RealmList<Decimal128> list = new RealmList<>(new Decimal128(1000), new Decimal128(2000));\n                    collection.setValue(AllJavaTypes.FIELD_DECIMAL128_LIST, list);\n                    assertElements(collection, obj -> {\n                        assertEquals(new Decimal128(1000), obj.getFieldDecimal128List().first());\n                        assertEquals(new Decimal128(2000), obj.getFieldDecimal128List().last());\n                    });\n                    break;\n                }\n                case OBJECT_ID_VALUE_LIST:  {\n                    String hex1 = TestHelper.randomObjectIdHexString();\n                    String hex2 = TestHelper.randomObjectIdHexString();\n                    RealmList<ObjectId> list = new RealmList<>(new ObjectId(hex1), new ObjectId(hex2));\n                    collection.setValue(AllJavaTypes.FIELD_OBJECT_ID_LIST, list);\n                    assertElements(collection, obj -> {\n                        assertEquals(new ObjectId(hex1), obj.getFieldObjectIdList().first());\n                        assertEquals(new ObjectId(hex2), obj.getFieldObjectIdList().last());\n                    });\n                    break;\n                }\n                case UUID_VALUE_LIST:  {\n                    String uuid1 = UUID.randomUUID().toString();\n                    String uuid2 = UUID.randomUUID().toString();\n                    RealmList<UUID> list = new RealmList<>(UUID.fromString(uuid1), UUID.fromString(uuid2));\n                    collection.setValue(AllJavaTypes.FIELD_UUID_LIST, list);\n                    assertElements(collection, obj -> {\n                        assertEquals(UUID.fromString(uuid1), obj.getFieldUUIDList().first());\n                        assertEquals(UUID.fromString(uuid2), obj.getFieldUUIDList().last());\n                    });\n                    break;\n                }\n                default:\n                    fail(\"Unknown type: \" + type);\n            }\n        }\n    }\n\n    @Test\n    public void setValue_implicitConversions() {\n        populateAllJavaTypes(5);\n        RealmResults<AllJavaTypes> collection = realm.where(AllJavaTypes.class).findAll();\n        realm.beginTransaction();\n        for (BulkSetMethods type : BulkSetMethods.values()) {\n            switch(type) {\n                case BOOLEAN:\n                    collection.setValue(AllJavaTypes.FIELD_BOOLEAN, \"true\");\n                    assertElements(collection, obj -> assertTrue(obj.isFieldBoolean()));\n                    collection.setValue(AllJavaTypes.FIELD_BOOLEAN, \"FALSE\");\n                    assertElements(collection, obj -> assertFalse(obj.isFieldBoolean()));\n                    collection.setValue(AllJavaTypes.FIELD_BOOLEAN, \"True\");\n                    assertElements(collection, obj -> assertTrue(obj.isFieldBoolean()));\n                    collection.setValue(AllJavaTypes.FIELD_BOOLEAN, \"false\");\n                    assertElements(collection, obj -> assertFalse(obj.isFieldBoolean()));\n                    collection.setValue(AllJavaTypes.FIELD_BOOLEAN, \"TRUE\");\n                    assertElements(collection, obj -> assertTrue(obj.isFieldBoolean()));\n                    break;\n                case BYTE:\n                    collection.setValue(AllJavaTypes.FIELD_BYTE, \"1\");\n                    assertElements(collection, obj -> assertEquals((byte)1, obj.getFieldByte()));\n                    break;\n                case SHORT:\n                    collection.setValue(AllJavaTypes.FIELD_SHORT, \"2\");\n                    assertElements(collection, obj -> assertEquals((short)2, obj.getFieldShort()));\n                    break;\n                case INTEGER:\n                    collection.setValue(AllJavaTypes.FIELD_INT, \"3\");\n                    assertElements(collection, obj -> assertEquals(3, obj.getFieldInt()));\n                    break;\n                case LONG:\n                    collection.setValue(AllJavaTypes.FIELD_LONG, Long.toString(Long.MAX_VALUE));\n                    assertElements(collection, obj -> assertEquals(Long.MAX_VALUE, obj.getFieldLong()));\n                    break;\n                case FLOAT:\n                    collection.setValue(AllJavaTypes.FIELD_FLOAT, \"1.23F\");\n                    assertElements(collection, obj -> assertEquals(1.23F, obj.getFieldFloat(), 0F));\n                    break;\n                case DOUBLE:\n                    collection.setValue(AllJavaTypes.FIELD_DOUBLE, \"1.234\");\n                    assertElements(collection, obj -> assertEquals(1.234, obj.getFieldDouble(), 0F));\n                    break;\n                case DATE:\n                    collection.setValue(AllJavaTypes.FIELD_DATE, \"1000\");\n                    assertElements(collection, obj -> assertEquals(new Date(1000), obj.getFieldDate()));\n                    collection.setValue(AllJavaTypes.FIELD_DATE, \"/Date(2000+0000)/\");\n                    assertElements(collection, obj -> assertEquals(new Date(2000), obj.getFieldDate()));\n                    break;\n                case DECIMAL128:\n                    collection.setValue(AllJavaTypes.FIELD_DECIMAL128, \"1.234\");\n                    assertElements(collection, obj -> assertEquals(Decimal128.parse(\"1.234\"), obj.getFieldDecimal128()));\n                    break;\n                case OBJECT_ID:\n                    String hex = TestHelper.randomObjectIdHexString();\n                    collection.setValue(AllJavaTypes.FIELD_OBJECT_ID, new ObjectId(hex));\n                    assertElements(collection, obj -> assertEquals(new ObjectId(hex), obj.getFieldObjectId()));\n                    break;\n                case UUID:\n                    String uuid = UUID.randomUUID().toString();\n                    collection.setValue(AllJavaTypes.FIELD_UUID, UUID.fromString(uuid));\n                    assertElements(collection, obj -> assertEquals(UUID.fromString(uuid), obj.getFieldUUID()));\n                    break;\n\n                // These types do not offer any implicit conversion\n                case STRING:\n                case BINARY:\n                case OBJECT:\n                case MODEL_LIST:\n                case STRING_VALUE_LIST:\n                case BOOLEAN_VALUE_LIST:\n                case BYTE_VALUE_LIST:\n                case SHORT_VALUE_LIST:\n                case INTEGER_VALUE_LIST:\n                case LONG_VALUE_LIST:\n                case FLOAT_VALUE_LIST:\n                case DOUBLE_VALUE_LIST:\n                case BINARY_VALUE_LIST:\n                case DATE_VALUE_LIST:\n                case DECIMAL128_VALUE_LIST:\n                case OBJECT_ID_VALUE_LIST:\n                case UUID_VALUE_LIST:\n                    continue;\n\n                default:\n                    fail(\"Unknown type: \" + type);\n            }\n        }\n    }\n\n    // Test for https://github.com/realm/realm-java/issues/6478\n    @Test\n    public void setDate_updateRemovesObjectFromQuery() {\n        realm.beginTransaction();\n        realm.deleteAll();\n        int objects = 10;\n        for (int i = 0; i < objects; ++i) {\n            AllJavaTypes obj = realm.createObject(AllJavaTypes.class, i);\n            obj.setFieldDate(i % 2 == 0 ? null : new Date(1000));\n        }\n        realm.commitTransaction();\n\n        realm.beginTransaction();\n        RealmResults<AllJavaTypes> collection = realm.where(AllJavaTypes.class)\n                .isNull(AllJavaTypes.FIELD_DATE)\n                .findAll();\n\n        collection.setDate(AllJavaTypes.FIELD_DATE, new Date(2000));\n        realm.commitTransaction();\n\n        assertTrue(collection.isEmpty());\n    }\n\n    @Test\n    public void setValue_specificType() {\n        populateAllJavaTypes(5);\n        RealmResults<AllJavaTypes> collection = realm.where(AllJavaTypes.class).findAll();\n        realm.beginTransaction();\n        for (BulkSetMethods type : BulkSetMethods.values()) {\n            switch(type) {\n                case STRING:\n                    collection.setString(AllJavaTypes.FIELD_STRING, \"foo\");\n                    assertElements(collection, obj -> assertEquals(\"foo\", obj.getFieldString()));\n                    collection.setString(AllJavaTypes.FIELD_STRING, null);\n                    assertElements(collection, obj -> assertEquals(null, obj.getFieldString()));\n                    break;\n                case BOOLEAN:\n                    collection.setBoolean(AllJavaTypes.FIELD_BOOLEAN, true);\n                    assertElements(collection, obj -> assertTrue(obj.isFieldBoolean()));\n                    break;\n                case BYTE:\n                    collection.setByte(AllJavaTypes.FIELD_BYTE, (byte) 1);\n                    assertElements(collection, obj -> assertEquals((byte)1, obj.getFieldByte()));\n                    break;\n                case SHORT:\n                    collection.setShort(AllJavaTypes.FIELD_SHORT, (short) 2);\n                    assertElements(collection, obj -> assertEquals((short)2, obj.getFieldShort()));\n                    break;\n                case INTEGER:\n                    collection.setInt(AllJavaTypes.FIELD_INT, 3);\n                    assertElements(collection, obj -> assertEquals(3, obj.getFieldInt()));\n                    break;\n                case LONG:\n                    collection.setLong(AllJavaTypes.FIELD_LONG, 4L);\n                    assertElements(collection, obj -> assertEquals(4L, obj.getFieldLong()));\n                    break;\n                case FLOAT:\n                    collection.setFloat(AllJavaTypes.FIELD_FLOAT, 1.23F);\n                    assertElements(collection, obj -> assertEquals(1.23F, obj.getFieldFloat(), 0F));\n                    break;\n                case DOUBLE:\n                    collection.setDouble(AllJavaTypes.FIELD_DOUBLE, 1.234);\n                    assertElements(collection, obj -> assertEquals(1.234, obj.getFieldDouble(), 0F));\n                    break;\n                case BINARY:\n                    collection.setBlob(AllJavaTypes.FIELD_BINARY, new byte[]{1,2,3});\n                    assertElements(collection, obj -> assertArrayEquals(new byte[]{1,2,3}, obj.getFieldBinary()));\n                    collection.setBlob(AllJavaTypes.FIELD_BINARY, null);\n                    assertElements(collection, obj -> assertNull(obj.getFieldBinary()));\n                    break;\n                case DATE:\n                    collection.setDate(AllJavaTypes.FIELD_DATE, new Date(1000));\n                    assertElements(collection, obj -> assertEquals(new Date(1000), obj.getFieldDate()));\n                    collection.setDate(AllJavaTypes.FIELD_DATE, null);\n                    assertElements(collection, obj -> assertNull(obj.getFieldDate()));\n                    break;\n                case DECIMAL128:\n                    collection.setDecimal128(AllJavaTypes.FIELD_DECIMAL128, new Decimal128(1000));\n                    assertElements(collection, obj -> assertEquals(new Decimal128(1000), obj.getFieldDecimal128()));\n                    collection.setDecimal128(AllJavaTypes.FIELD_DECIMAL128, null);\n                    assertElements(collection, obj -> assertNull(obj.getFieldDecimal128()));\n                    break;\n                case OBJECT_ID:\n                    collection.setObjectId(AllJavaTypes.FIELD_OBJECT_ID, new ObjectId(TestHelper.generateObjectIdHexString(1)));\n                    assertElements(collection, obj -> assertEquals(new ObjectId(TestHelper.generateObjectIdHexString(1)), obj.getFieldObjectId()));\n                    collection.setObjectId(AllJavaTypes.FIELD_OBJECT_ID, null);\n                    assertElements(collection, obj -> assertNull(obj.getFieldObjectId()));\n                    break;\n                case UUID:\n                    collection.setUUID(AllJavaTypes.FIELD_UUID, UUID.fromString(uuid1));\n                    assertElements(collection, obj -> assertEquals(UUID.fromString(uuid1), obj.getFieldUUID()));\n                    collection.setUUID(AllJavaTypes.FIELD_UUID, null);\n                    assertElements(collection, obj -> assertNull(obj.getFieldUUID()));\n                    break;\n                case OBJECT: {\n                    AllJavaTypes childObj = realm.createObject(AllJavaTypes.class, 42);\n                    collection.setObject(AllJavaTypes.FIELD_OBJECT, childObj);\n                    assertElements(collection, obj -> assertEquals(childObj, obj.getFieldObject()));\n                    collection.setObject(AllJavaTypes.FIELD_OBJECT, null);\n                    assertElements(collection, obj -> assertNull(obj.getFieldObject()));\n                    break;\n                }\n                case MODEL_LIST: {\n                    AllJavaTypes childObj = realm.createObject(AllJavaTypes.class, 43);\n                    collection.setList(AllJavaTypes.FIELD_LIST, new RealmList<>(childObj));\n                    assertElements(collection, obj -> {\n                        assertEquals(1, obj.getFieldList().size());\n                        assertEquals(childObj, obj.getFieldList().first());\n                    });\n                    break;\n                }\n                case STRING_VALUE_LIST: {\n                    RealmList<String> list = new RealmList<>(\"Foo\", \"Bar\");\n                    collection.setList(AllJavaTypes.FIELD_STRING_LIST, list);\n                    assertElements(collection, obj -> {\n                        assertEquals(\"Foo\", obj.getFieldStringList().first());\n                        assertEquals(\"Bar\", obj.getFieldStringList().last());\n                    });\n                    break;\n                }\n                case BOOLEAN_VALUE_LIST: {\n                    RealmList<Boolean> list = new RealmList<>(true, false);\n                    collection.setList(AllJavaTypes.FIELD_BOOLEAN_LIST, list);\n                    assertElements(collection, obj -> {\n                        assertTrue(obj.getFieldBooleanList().first());\n                        assertFalse(obj.getFieldBooleanList().last());\n                    });\n                    break;\n                }\n                case BYTE_VALUE_LIST: {\n                    RealmList<Byte> list = new RealmList<>((byte) 1, (byte) 2);\n                    collection.setList(AllJavaTypes.FIELD_BYTE_LIST, list);\n                    assertElements(collection, obj -> {\n                        assertEquals(Byte.valueOf((byte) 1), obj.getFieldByteList().first());\n                        assertEquals(Byte.valueOf((byte) 2), obj.getFieldByteList().last());\n                    });\n                    break;\n                }\n                case SHORT_VALUE_LIST: {\n                    RealmList<Short> list = new RealmList<>((short) 1, (short) 2);\n                    collection.setList(AllJavaTypes.FIELD_SHORT_LIST, list);\n                    assertElements(collection, obj -> {\n                        assertEquals(Short.valueOf((short) 1), obj.getFieldShortList().first());\n                        assertEquals(Short.valueOf((short) 2), obj.getFieldShortList().last());\n                    });\n                    break;\n                }\n                case INTEGER_VALUE_LIST: {\n                    RealmList<Integer> list = new RealmList<>(1, 2);\n                    collection.setList(AllJavaTypes.FIELD_INTEGER_LIST, list);\n                    assertElements(collection, obj -> {\n                        assertEquals(Integer.valueOf(1), obj.getFieldIntegerList().first());\n                        assertEquals(Integer.valueOf(2), obj.getFieldIntegerList().last());\n                    });\n                    break;\n                }\n                case LONG_VALUE_LIST: {\n                    RealmList<Long> list = new RealmList<>(1L, 2L);\n                    collection.setList(AllJavaTypes.FIELD_LONG_LIST, list);\n                    assertElements(collection, obj -> {\n                        assertEquals(Long.valueOf(1), obj.getFieldLongList().first());\n                        assertEquals(Long.valueOf(2), obj.getFieldLongList().last());\n                    });\n                    break;\n                }\n                case FLOAT_VALUE_LIST: {\n                    RealmList<Float> list = new RealmList<>(1.1F, 2.2F);\n                    collection.setList(AllJavaTypes.FIELD_FLOAT_LIST, list);\n                    assertElements(collection, obj -> {\n                        assertEquals(1.1F, obj.getFieldFloatList().first(), 0F);\n                        assertEquals(2.2F, obj.getFieldFloatList().last(), 0F);\n                    });\n                    break;\n                }\n                case DOUBLE_VALUE_LIST: {\n                    RealmList<Double> list = new RealmList<>(1.1D, 2.2D);\n                    collection.setList(AllJavaTypes.FIELD_DOUBLE_LIST, list);\n                    assertElements(collection, obj -> {\n                        assertEquals(1.1D, obj.getFieldDoubleList().first(), 0D);\n                        assertEquals(2.2D, obj.getFieldDoubleList().last(), 0D);\n                    });\n                    break;\n                }\n                case BINARY_VALUE_LIST: {\n                    RealmList<byte[]> list = new RealmList<>(new byte[] {1,2,3}, new byte[] {2,3,4});\n                    collection.setList(AllJavaTypes.FIELD_BINARY_LIST, list);\n                    assertElements(collection, obj -> {\n                        assertArrayEquals(new byte[] {1,2,3}, obj.getFieldBinaryList().first());\n                        assertArrayEquals(new byte[] {2,3,4}, obj.getFieldBinaryList().last());\n                    });\n                    break;\n                }\n                case DATE_VALUE_LIST:  {\n                    RealmList<Date> list = new RealmList<>(new Date(1000), new Date(2000));\n                    collection.setList(AllJavaTypes.FIELD_DATE_LIST, list);\n                    assertElements(collection, obj -> {\n                        assertEquals(new Date(1000), obj.getFieldDateList().first());\n                        assertEquals(new Date(2000), obj.getFieldDateList().last());\n                    });\n                    break;\n                }\n                case DECIMAL128_VALUE_LIST:  {\n                    RealmList<Decimal128> list = new RealmList<>(new Decimal128(1000), new Decimal128(2000));\n                    collection.setList(AllJavaTypes.FIELD_DECIMAL128_LIST, list);\n                    assertElements(collection, obj -> {\n                        assertEquals(new Decimal128(1000), obj.getFieldDecimal128List().first());\n                        assertEquals(new Decimal128(2000), obj.getFieldDecimal128List().last());\n                    });\n                    break;\n                }\n                case OBJECT_ID_VALUE_LIST:  {\n                    String hex1 = TestHelper.randomObjectIdHexString();\n                    String hex2 = TestHelper.randomObjectIdHexString();\n                    RealmList<ObjectId> list = new RealmList<>(new ObjectId(hex1), new ObjectId(hex2));\n                    collection.setList(AllJavaTypes.FIELD_OBJECT_ID_LIST, list);\n                    assertElements(collection, obj -> {\n                        assertEquals(new ObjectId(hex1), obj.getFieldObjectIdList().first());\n                        assertEquals(new ObjectId(hex2), obj.getFieldObjectIdList().last());\n                    });\n                    break;\n                }\n                case UUID_VALUE_LIST:  {\n                    String uuid1 = UUID.randomUUID().toString();\n                    String uuid2 = UUID.randomUUID().toString();\n                    RealmList<UUID> list = new RealmList<>(UUID.fromString(uuid1), UUID.fromString(uuid2));\n                    collection.setList(AllJavaTypes.FIELD_UUID_LIST, list);\n                    assertElements(collection, obj -> {\n                        assertEquals(UUID.fromString(uuid1), obj.getFieldUUIDList().first());\n                        assertEquals(UUID.fromString(uuid2), obj.getFieldUUIDList().last());\n                    });\n                    break;\n                }\n                default:\n                    fail(\"Unknown type: \" + type);\n            }\n        }\n    }\n\n    @Test\n    public void setObject_unmanagedObjectThrows() {\n        RealmResults<AllTypes> collection = realm.where(AllTypes.class).findAll();\n        realm.beginTransaction();\n        try {\n            collection.setObject(AllTypes.FIELD_REALMOBJECT, new Dog());\n            fail();\n        } catch (IllegalArgumentException e) {\n            assertTrue(\"Wrong error message: \" + e.getMessage(), e.getMessage().contains(\"is not a valid, managed Realm object.\"));\n        }\n    }\n\n    @Test\n    public void setObject_wrongObjectTypeThrows() {\n        RealmResults<AllTypes> collection = realm.where(AllTypes.class).findAll();\n        realm.beginTransaction();\n        try {\n            collection.setObject(AllTypes.FIELD_REALMOBJECT, realm.createObject(AllTypes.class));\n            fail();\n        } catch (IllegalArgumentException e) {\n            assertTrue(\"Wrong error message: \" + e.getMessage(), e.getMessage().equals(\"Type of object is wrong. Was 'AllTypes', expected 'Dog'\"));\n        } finally {\n            realm.cancelTransaction();\n        }\n\n        DynamicRealm dynamicRealm = DynamicRealm.getInstance(realm.getConfiguration());\n        RealmResults<DynamicRealmObject> dynamicCollection = dynamicRealm.where(\"AllTypes\").findAll();\n        dynamicRealm.beginTransaction();\n        try {\n            dynamicCollection.setObject(AllTypes.FIELD_REALMOBJECT, dynamicRealm.createObject(\"AllTypes\"));\n            fail();\n        } catch (IllegalArgumentException e) {\n            assertTrue(\"Wrong error message: \" + e.getMessage(), e.getMessage().equals(\"Type of object is wrong. Was 'AllTypes', expected 'Dog'\"));\n        } finally {\n            dynamicRealm.close();\n        }\n    }\n\n    @Test\n    public void setList_unmanagedObjectThrows() {\n        RealmResults<AllTypes> collection = realm.where(AllTypes.class).findAll();\n        realm.beginTransaction();\n        try {\n            collection.setList(AllTypes.FIELD_REALMLIST, new RealmList<>(new Dog()));\n            fail();\n        } catch (IllegalArgumentException e) {\n            assertTrue(\"Wrong error message: \" + e.getMessage(), e.getMessage().contains(\"is not a valid, managed Realm object.\"));\n        }\n    }\n\n    @Test\n    public void setList_wrongObjectTypeThrows() {\n        RealmResults<AllTypes> collection = realm.where(AllTypes.class).findAll();\n        realm.beginTransaction();\n        try {\n            collection.setList(AllTypes.FIELD_REALMLIST, new RealmList<>(realm.createObject(AllTypes.class)));\n            fail();\n        } catch (IllegalArgumentException e) {\n            assertTrue(\"Wrong error message: \" + e.getMessage(), e.getMessage().equals(\"Type of object is wrong. Was 'AllTypes', expected 'Dog'\"));\n        } finally {\n            realm.cancelTransaction();\n        }\n\n        DynamicRealm dynamicRealm = DynamicRealm.getInstance(realm.getConfiguration());\n        RealmResults<DynamicRealmObject> dynamicCollection = dynamicRealm.where(\"AllTypes\").findAll();\n        dynamicRealm.beginTransaction();\n        try {\n            dynamicCollection.setList(AllTypes.FIELD_REALMLIST, new RealmList<>(dynamicRealm.createObject(\"AllTypes\")));\n            fail();\n        } catch (IllegalArgumentException e) {\n            assertTrue(\"Wrong error message: \" + e.getMessage(), e.getMessage().equals(\"Type of object is wrong. Was 'AllTypes', expected 'Dog'\"));\n        } finally {\n            dynamicRealm.close();\n        }\n    }\n\n    @Test\n    public void setValue_specificType_wrongFieldNameThrows() {\n        populateAllJavaTypes(5);\n        RealmResults<AllTypes> collection = realm.where(AllTypes.class).findAll();\n        realm.beginTransaction();\n        for (BulkSetMethods type : BulkSetMethods.values()) {\n            try {\n                switch(type) {\n                    case STRING: collection.setString(\"foo\", \"bar\"); break;\n                    case BOOLEAN: collection.setBoolean(\"foo\", true); break;\n                    case BYTE: collection.setByte(\"foo\", (byte) 1); break;\n                    case SHORT: collection.setShort(\"foo\", (short) 2); break;\n                    case INTEGER: collection.setInt(\"foo\", 3); break;\n                    case LONG: collection.setLong(\"foo\", 4L); break;\n                    case FLOAT: collection.setFloat(\"foo\", 1.23F); break;\n                    case DOUBLE: collection.setDouble(\"foo\", 1.234); break;\n                    case BINARY: collection.setBlob(\"foo\", new byte[]{1,2,3}); break;\n                    case DATE: collection.setDate(\"foo\", new Date(1000)); break;\n                    case DECIMAL128: collection.setDecimal128(\"foo\", new Decimal128(1000)); break;\n                    case OBJECT_ID: collection.setObjectId(\"foo\", new ObjectId(TestHelper.randomObjectIdHexString())); break;\n                    case UUID: collection.setUUID(\"foo\", UUID.randomUUID()); break;\n                    case OBJECT: collection.setObject(\"foo\", realm.createObject(AllTypes.class)); break;\n                    case MODEL_LIST: collection.setList(\"foo\", new RealmList<>()); break;\n                    case STRING_VALUE_LIST: collection.setList(\"foo\", new RealmList<>(\"Foo\")); break;\n                    case BOOLEAN_VALUE_LIST: collection.setList(\"foo\", new RealmList<>(true)); break;\n                    case BYTE_VALUE_LIST: collection.setList(\"foo\", new RealmList<>((byte) 1)); break;\n                    case SHORT_VALUE_LIST: collection.setList(\"foo\", new RealmList<>((short) 1)); break;\n                    case INTEGER_VALUE_LIST: collection.setList(\"foo\", new RealmList<>(1)); break;\n                    case LONG_VALUE_LIST: collection.setList(\"foo\", new RealmList<>(1L)); break;\n                    case FLOAT_VALUE_LIST: collection.setList(\"foo\", new RealmList<>(1.1F)); break;\n                    case DOUBLE_VALUE_LIST: collection.setList(\"foo\", new RealmList<>(1.1D)); break;\n                    case BINARY_VALUE_LIST: collection.setList(\"foo\", new RealmList<>(new byte[] {})); break;\n                    case DATE_VALUE_LIST: collection.setList(\"foo\", new RealmList<>(new Date())); break;\n                    case DECIMAL128_VALUE_LIST: collection.setList(\"foo\", new RealmList<>(new Decimal128(1000))); break;\n                    case OBJECT_ID_VALUE_LIST: collection.setList(\"foo\", new RealmList<>(new ObjectId(TestHelper.randomObjectIdHexString()))); break;\n                    case UUID_VALUE_LIST: collection.setList(\"foo\", new RealmList<>(UUID.randomUUID())); break;\n                    default:\n                        fail(\"Unknown type: \" + type);\n                }\n                fail(type + \" should have thrown an exception\");\n            } catch (IllegalArgumentException e) {\n                assertTrue(e.getMessage().contains(\"does not exist\"));\n            }\n        }\n    }\n\n    @Test\n    public void setValue_specificType_wrongTypeThrows() {\n        populateAllJavaTypes(5);\n        RealmResults<AllJavaTypes> collection = realm.where(AllJavaTypes.class).findAll();\n        realm.beginTransaction();\n        for (BulkSetMethods type : BulkSetMethods.values()) {\n            try {\n                switch(type) {\n                    case STRING: collection.setString(AllJavaTypes.FIELD_BOOLEAN, \"foo\"); break;\n                    case BOOLEAN: collection.setBoolean(AllJavaTypes.FIELD_STRING, true); break;\n                    case BYTE: collection.setByte(AllJavaTypes.FIELD_STRING, (byte) 1); break;\n                    case SHORT: collection.setShort(AllJavaTypes.FIELD_STRING, (short) 2); break;\n                    case INTEGER: collection.setInt(AllJavaTypes.FIELD_STRING, 3); break;\n                    case LONG:collection.setLong(AllJavaTypes.FIELD_STRING, 4L); break;\n                    case FLOAT: collection.setFloat(AllJavaTypes.FIELD_STRING, 1.23F); break;\n                    case DOUBLE: collection.setDouble(AllJavaTypes.FIELD_STRING, 1.234); break;\n                    case BINARY: collection.setBlob(AllJavaTypes.FIELD_STRING, new byte[]{1,2,3}); break;\n                    case DATE: collection.setDate(AllJavaTypes.FIELD_STRING, new Date(1000)); break;\n                    case DECIMAL128: collection.setDecimal128(AllJavaTypes.FIELD_STRING, new Decimal128(1000)); break;\n                    case OBJECT_ID: collection.setObjectId(AllJavaTypes.FIELD_STRING, new ObjectId(TestHelper.randomObjectIdHexString())); break;\n                    case UUID: collection.setUUID(AllJavaTypes.FIELD_STRING, UUID.randomUUID()); break;\n                    case OBJECT: collection.setObject(AllJavaTypes.FIELD_STRING, realm.createObject(AllJavaTypes.class, 42)); break;\n                    case MODEL_LIST: collection.setList(AllJavaTypes.FIELD_STRING, new RealmList<>(realm.createObject(AllJavaTypes.class, 43))); break;\n                    case STRING_VALUE_LIST: collection.setList(AllJavaTypes.FIELD_STRING, new RealmList<>(\"Foo\")); break;\n                    case BOOLEAN_VALUE_LIST: collection.setList(AllJavaTypes.FIELD_STRING, new RealmList<>(true)); break;\n                    case BYTE_VALUE_LIST: collection.setList(AllJavaTypes.FIELD_STRING, new RealmList<>((byte)1)); break;\n                    case SHORT_VALUE_LIST: collection.setList(AllJavaTypes.FIELD_STRING, new RealmList<>((short)1)); break;\n                    case INTEGER_VALUE_LIST: collection.setList(AllJavaTypes.FIELD_STRING, new RealmList<>(1)); break;\n                    case LONG_VALUE_LIST: collection.setList(AllJavaTypes.FIELD_STRING, new RealmList<>(1L)); break;\n                    case FLOAT_VALUE_LIST: collection.setList(AllJavaTypes.FIELD_STRING, new RealmList<>(1.1F)); break;\n                    case DOUBLE_VALUE_LIST: collection.setList(AllJavaTypes.FIELD_STRING, new RealmList<>(2.2D)); break;\n                    case BINARY_VALUE_LIST: collection.setList(AllJavaTypes.FIELD_STRING, new RealmList<>(new byte[]{})); break;\n                    case DATE_VALUE_LIST: collection.setList(AllJavaTypes.FIELD_STRING, new RealmList<>(new Date())); break;\n                    case DECIMAL128_VALUE_LIST: collection.setList(AllJavaTypes.FIELD_STRING, new RealmList<>(new Decimal128(1000))); break;\n                    case OBJECT_ID_VALUE_LIST: collection.setList(AllJavaTypes.FIELD_STRING, new RealmList<>(new ObjectId(TestHelper.randomObjectIdHexString()))); break;\n                    case UUID_VALUE_LIST: collection.setList(AllJavaTypes.FIELD_STRING, new RealmList<>(UUID.randomUUID())); break;\n                    default:\n                        fail(\"Unknown type: \" + type);\n                }\n                fail(type + \" should have thrown an exception\");\n            } catch (IllegalArgumentException e) {\n                RealmLog.error(type + \" -> \" + e.getMessage());\n                assertTrue(type + \" failed\", e.getMessage().contains(\"is not of the expected type\")\n                        || e.getMessage().contains(\"List contained the wrong type of elements\")\n                        || e.getMessage().contains(\"is not a list\"));\n            }\n        }\n    }\n\n    @Test\n    public void setValue_specificType_primaryKeyFieldThrows() {\n        populateAllJavaTypes(5);\n        realm.beginTransaction();\n        try {\n            RealmResults<PrimaryKeyAsString> collection = realm.where(PrimaryKeyAsString.class).findAll();\n            collection.setString(PrimaryKeyAsString.FIELD_PRIMARY_KEY, \"foo\");\n            fail();\n        } catch (IllegalStateException ignore) {\n        }\n\n        try {\n            RealmResults<PrimaryKeyAsLong> collection = realm.where(PrimaryKeyAsLong.class).findAll();\n            collection.setLong(PrimaryKeyAsLong.FIELD_ID, 42);\n            fail();\n        } catch (IllegalStateException ignore) {\n        }\n\n        try {\n            RealmResults<ObjectIdPrimaryKeyRequired> collection = realm.where(ObjectIdPrimaryKeyRequired.class).findAll();\n            collection.setObjectId(\"id\", new ObjectId(TestHelper.randomObjectIdHexString()));\n            fail();\n        } catch (IllegalStateException ignore) {\n        }\n\n\n    }\n\n    @Test\n    public void setValue_specificType_modelClassNameOnTypedRealms() {\n        populateMappedAllJavaTypes(5);\n        RealmResults<MappedAllJavaTypes> collection = realm.where(MappedAllJavaTypes.class).findAll();\n        realm.beginTransaction();\n        for (BulkSetMethods type : BulkSetMethods.values()) {\n            switch(type) {\n                case STRING:\n                    collection.setString(\"fieldString\", \"foo\");\n                    assertElements(collection, obj -> assertEquals(\"foo\", obj.fieldString));\n                    break;\n                case BOOLEAN:\n                    collection.setBoolean(\"fieldBoolean\", true);\n                    assertElements(collection, obj -> assertTrue(obj.fieldBoolean));\n                    break;\n                case BYTE:\n                    collection.setByte(\"fieldByte\", (byte) 1);\n                    assertElements(collection, obj -> assertEquals((byte) 1, obj.fieldByte));\n                    break;\n                case SHORT:\n                    collection.setShort(\"fieldShort\", (short) 2);\n                    assertElements(collection, obj -> assertEquals((short) 2, obj.fieldShort));\n                    break;\n                case INTEGER:\n                    collection.setInt(\"fieldInt\", 3);\n                    assertElements(collection, obj -> assertEquals(3, obj.fieldInt));\n                    break;\n                case LONG:\n                    collection.setLong(\"fieldLong\", 4L);\n                    assertElements(collection, obj -> assertEquals(4L, obj.fieldLong));\n                    break;\n                case FLOAT:\n                    collection.setFloat(\"fieldFloat\", 1.23F);\n                    assertElements(collection, obj -> assertEquals(1.23F, obj.fieldFloat, 0F));\n                    break;\n                case DOUBLE:\n                    collection.setDouble(\"fieldDouble\", 1.234);\n                    assertElements(collection, obj -> assertEquals(1.234, obj.fieldDouble, 0F));\n                    break;\n                case BINARY:\n                    collection.setBlob(\"fieldBinary\", new byte[]{1,2,3});\n                    assertElements(collection, obj -> assertArrayEquals(new byte[]{1,2,3}, obj.fieldBinary));\n                    break;\n                case DATE:\n                    collection.setDate(\"fieldDate\", new Date(1000));\n                    assertElements(collection, obj -> assertEquals(new Date(1000), obj.fieldDate));\n                    break;\n                case DECIMAL128:\n                    collection.setDecimal128(\"fieldDecimal128\", new Decimal128(1000));\n                    assertElements(collection, obj -> assertEquals(new Decimal128(1000), obj.fieldDecimal128));\n                    break;\n                case OBJECT_ID:{\n                    String hex = TestHelper.randomObjectIdHexString();\n                    collection.setObjectId(\"fieldObjectId\", new ObjectId(hex));\n                    assertElements(collection, obj -> assertEquals(new ObjectId(hex), obj.fieldObjectId));\n                    break;\n                }\n                case UUID:{\n                    String uuid = UUID.randomUUID().toString();\n                    collection.setUUID(\"fieldUUID\", UUID.fromString(uuid));\n                    assertElements(collection, obj -> assertEquals(UUID.fromString(uuid), obj.fieldUUID));\n                    break;\n                }\n                case OBJECT: {\n                    MappedAllJavaTypes childObj = realm.createObject(MappedAllJavaTypes.class, 42);\n                    collection.setObject(\"fieldObject\", childObj);\n                    assertElements(collection, obj -> assertEquals(childObj, obj.fieldObject));\n                    break;\n                }\n                case MODEL_LIST: {\n                    MappedAllJavaTypes childObj = realm.createObject(MappedAllJavaTypes.class, 43);\n                    collection.setList(\"fieldList\", new RealmList<>(childObj));\n                    assertElements(collection, obj -> {\n                        assertEquals(1, obj.fieldList.size());\n                        assertEquals(childObj, obj.fieldList.first());\n                    });\n                    break;\n                }\n                case STRING_VALUE_LIST:\n                    collection.setList(\"fieldStringList\", new RealmList<>(\"Foo\"));\n                    assertElements(collection, obj -> {\n                        assertEquals(1, obj.fieldStringList.size());\n                        assertEquals(\"Foo\", obj.fieldStringList.first());\n                    });\n                    break;\n                case BOOLEAN_VALUE_LIST:\n                    collection.setList(\"fieldBooleanList\", new RealmList<>(true));\n                    assertElements(collection, obj -> {\n                        assertEquals(1, obj.fieldBooleanList.size());\n                        assertEquals(true, obj.fieldBooleanList.first());\n                    });\n                    break;\n                case BYTE_VALUE_LIST:\n                    collection.setList(\"fieldByteList\", new RealmList<>((byte)1));\n                    assertElements(collection, obj -> {\n                        assertEquals(1, obj.fieldByteList.size());\n                        assertEquals(Byte.valueOf((byte) 1), obj.fieldByteList.first());\n                    });\n                    break;\n                case SHORT_VALUE_LIST:\n                    collection.setList(\"fieldShortList\", new RealmList<>((short)1));\n                    assertElements(collection, obj -> {\n                        assertEquals(1, obj.fieldShortList.size());\n                        assertEquals(Short.valueOf((short) 1), obj.fieldShortList.first());\n                    });\n                    break;\n                case INTEGER_VALUE_LIST:\n                    collection.setList(\"fieldIntegerList\", new RealmList<>(1));\n                    assertElements(collection, obj -> {\n                        assertEquals(1, obj.fieldIntegerList.size());\n                        assertEquals(Integer.valueOf(1), obj.fieldIntegerList.first());\n                    });\n                    break;\n                case LONG_VALUE_LIST:\n                    collection.setList(\"fieldLongList\", new RealmList<>(1L));\n                    assertElements(collection, obj -> {\n                        assertEquals(1, obj.fieldLongList.size());\n                        assertEquals(Long.valueOf((byte) 1), obj.fieldLongList.first());\n                    });\n                    break;\n                case FLOAT_VALUE_LIST:\n                    collection.setList(\"fieldFloatList\", new RealmList<>(1.1F));\n                    assertElements(collection, obj -> {\n                        assertEquals(1, obj.fieldFloatList.size());\n                        assertEquals(1.1F, obj.fieldFloatList.first(), 0F);\n                    });\n                    break;\n                case DOUBLE_VALUE_LIST:\n                    collection.setList(\"fieldDoubleList\", new RealmList<>(1.1D));\n                    assertElements(collection, obj -> {\n                        assertEquals(1, obj.fieldDoubleList.size());\n                        assertEquals(1.1D, obj.fieldDoubleList.first(), 0F);\n                    });\n                    break;\n                case BINARY_VALUE_LIST:\n                    collection.setList(\"fieldBinaryList\", new RealmList<>(new byte[] {1,2,3}));\n                    assertElements(collection, obj -> {\n                        assertEquals(1, obj.fieldBinaryList.size());\n                        assertArrayEquals(new byte[] {1,2,3}, obj.fieldBinaryList.first());\n                    });\n                    break;\n                case DATE_VALUE_LIST:\n                    collection.setList(\"fieldDateList\", new RealmList<>(new Date(1000)));\n                    assertElements(collection, obj -> {\n                        assertEquals(1, obj.fieldDateList.size());\n                        assertEquals(new Date(1000), obj.fieldDateList.first());\n                    });\n                    break;\n                case DECIMAL128_VALUE_LIST:\n                    collection.setList(\"fieldDecimalList\", new RealmList<>(new Decimal128(1000)));\n                    assertElements(collection, obj -> {\n                        assertEquals(1, obj.fieldDecimalList.size());\n                        assertEquals(new Decimal128(1000), obj.fieldDecimalList.first());\n                    });\n                    break;\n                case OBJECT_ID_VALUE_LIST:{\n                    String hex = TestHelper.randomObjectIdHexString();\n                    collection.setList(\"fieldObjectIdList\", new RealmList<>(new ObjectId(hex)));\n                    assertElements(collection, obj -> {\n                        assertEquals(1, obj.fieldObjectIdList.size());\n                        assertEquals(new ObjectId(hex), obj.fieldObjectIdList.first());\n                    });\n                    break;\n                }\n                case UUID_VALUE_LIST:{\n                    String uuid = UUID.randomUUID().toString();\n                    collection.setList(\"fieldUUIDList\", new RealmList<>(UUID.fromString(uuid)));\n                    assertElements(collection, obj -> {\n                        assertEquals(1, obj.fieldUUIDList.size());\n                        assertEquals(UUID.fromString(uuid), obj.fieldUUIDList.first());\n                    });\n                    break;\n                }\n                default:\n                    fail(\"Unknown type: \" + type);\n            }\n        }\n    }\n\n    @Test\n    public void setValue_specificType_internalNameOnDynamicRealms() {\n        populateMappedAllJavaTypes(5);\n        DynamicRealm dynamicRealm = DynamicRealm.getInstance(realm.getConfiguration());\n        dynamicRealm.beginTransaction();\n        try {\n            RealmResults<DynamicRealmObject> collection = dynamicRealm.where(\"MappedAllJavaTypes\").findAll();\n            for (BulkSetMethods type : BulkSetMethods.values()) {\n                switch(type) {\n                    case STRING:\n                        collection.setString(\"field_string\", \"foo\");\n                        assertElements(collection, obj -> assertEquals(\"foo\", obj.getString(\"field_string\")));\n                        break;\n                    case BOOLEAN:\n                        collection.setBoolean(\"field_boolean\", true);\n                        assertElements(collection, obj -> assertTrue(obj.getBoolean(\"field_boolean\")));\n                        break;\n                    case BYTE:\n                        collection.setByte(\"field_byte\", (byte) 1);\n                        assertElements(collection, obj -> assertEquals((byte) 1, obj.getByte(\"field_byte\")));\n                        break;\n                    case SHORT:\n                        collection.setShort(\"field_short\", (short) 2);\n                        assertElements(collection, obj -> assertEquals((short) 2, obj.getShort(\"field_short\")));\n                        break;\n                    case INTEGER:\n                        collection.setInt(\"field_int\", 3);\n                        assertElements(collection, obj -> assertEquals(3, obj.getInt(\"field_int\")));\n                        break;\n                    case LONG:\n                        collection.setLong(\"field_long\", 4L);\n                        assertElements(collection, obj -> assertEquals(4L, obj.getLong(\"field_long\")));\n                        break;\n                    case FLOAT:\n                        collection.setFloat(\"field_float\", 1.23F);\n                        assertElements(collection, obj -> assertEquals(1.23F, obj.getFloat(\"field_float\"), 0F));\n                        break;\n                    case DOUBLE:\n                        collection.setDouble(\"field_double\", 1.234);\n                        assertElements(collection, obj -> assertEquals(1.234, obj.getDouble(\"field_double\"), 0F));\n                        break;\n                    case BINARY:\n                        collection.setBlob(\"field_binary\", new byte[]{1,2,3});\n                        assertElements(collection, obj -> assertArrayEquals(new byte[]{1,2,3}, obj.getBlob(\"field_binary\")));\n                        break;\n                    case DATE:\n                        collection.setDate(\"field_date\", new Date(1000));\n                        assertElements(collection, obj -> assertEquals(new Date(1000), obj.getDate(\"field_date\")));\n                        break;\n                    case DECIMAL128:\n                        collection.setDecimal128(\"field_decimal128\", new Decimal128(1000));\n                        assertElements(collection, obj -> assertEquals(new Decimal128(1000), obj.getDecimal128(\"field_decimal128\")));\n                        break;\n                    case OBJECT_ID:{\n                        String hex = TestHelper.randomObjectIdHexString();\n                        collection.setObjectId(\"field_object_id\", new ObjectId(hex));\n                        assertElements(collection, obj -> assertEquals(new ObjectId(hex), obj.getObjectId(\"field_object_id\")));\n                        break;\n                    }\n                    case UUID:{\n                        String uuid = UUID.randomUUID().toString();\n                        collection.setUUID(\"field_uuid\", UUID.fromString(uuid));\n                        assertElements(collection, obj -> assertEquals(UUID.fromString(uuid), obj.getUUID(\"field_uuid\")));\n                        break;\n                    }\n                    case OBJECT: {\n                        DynamicRealmObject childObj = dynamicRealm.createObject(\"MappedAllJavaTypes\", 42);\n                        collection.setObject(\"field_object\", childObj);\n                        assertElements(collection, obj -> assertEquals(childObj, obj.getObject(\"field_object\")));\n                        break;\n                    }\n                    case MODEL_LIST: {\n                        DynamicRealmObject childObj = dynamicRealm.createObject(\"MappedAllJavaTypes\", 43);\n                        collection.setList(\"field_list\", new RealmList<>(childObj));\n                        assertElements(collection, obj -> {\n                            RealmList<DynamicRealmObject> list = obj.getList(\"field_list\");\n                            assertEquals(1, list.size());\n                            assertEquals(childObj, list.first());\n                        });\n                        break;\n                    }\n                    case STRING_VALUE_LIST:\n                        collection.setList(\"field_string_list\", new RealmList<>(\"Foo\"));\n                        assertElements(collection, obj -> {\n                            RealmList<String> list = obj.getList(\"field_string_list\", String.class);\n                            assertEquals(1, list.size());\n                            assertEquals(\"Foo\", list.first());\n                        });\n                        break;\n                    case BOOLEAN_VALUE_LIST:\n                        collection.setList(\"field_boolean_list\", new RealmList<>(true));\n                        assertElements(collection, obj -> {\n                            RealmList<Boolean> list = obj.getList(\"field_boolean_list\", Boolean.class);\n                            assertEquals(1, list.size());\n                            assertEquals(true, list.first());\n                        });\n                        break;\n                    case BYTE_VALUE_LIST:\n                        collection.setList(\"field_byte_list\", new RealmList<>((byte)1));\n                        assertElements(collection, obj -> {\n                            RealmList<Byte> list = obj.getList(\"field_byte_list\", Byte.class);\n                            assertEquals(1, list.size());\n                            assertEquals(Byte.valueOf((byte) 1), list.first());\n                        });\n                        break;\n                    case SHORT_VALUE_LIST:\n                        collection.setList(\"field_short_list\", new RealmList<>((short)1));\n                        assertElements(collection, obj -> {\n                            RealmList<Short> list = obj.getList(\"field_short_list\", Short.class);\n                            assertEquals(1, list.size());\n                            assertEquals(Short.valueOf((short) 1), list.first());\n                        });\n                        break;\n                    case INTEGER_VALUE_LIST:\n                        collection.setList(\"field_integer_list\", new RealmList<>(1));\n                        assertElements(collection, obj -> {\n                            RealmList<Integer> list = obj.getList(\"field_integer_list\", Integer.class);\n                            assertEquals(1, list.size());\n                            assertEquals(Integer.valueOf(1), list.first());\n                        });\n                        break;\n                    case LONG_VALUE_LIST:\n                        collection.setList(\"field_long_list\", new RealmList<>(1L));\n                        assertElements(collection, obj -> {\n                            RealmList<Long> list = obj.getList(\"field_long_list\", Long.class);\n                            assertEquals(1, list.size());\n                            assertEquals(Long.valueOf((byte) 1), list.first());\n                        });\n                        break;\n                    case FLOAT_VALUE_LIST:\n                        collection.setList(\"field_float_list\", new RealmList<>(1.1F));\n                        assertElements(collection, obj -> {\n                            RealmList<Float> list = obj.getList(\"field_float_list\", Float.class);\n                            assertEquals(1, list.size());\n                            assertEquals(1.1F, list.first(), 0F);\n                        });\n                        break;\n                    case DOUBLE_VALUE_LIST:\n                        collection.setList(\"field_double_list\", new RealmList<>(1.1D));\n                        assertElements(collection, obj -> {\n                            RealmList<Double> list = obj.getList(\"field_double_list\", Double.class);\n                            assertEquals(1, list.size());\n                            assertEquals(1.1D, list.first(), 0F);\n                        });\n                        break;\n                    case BINARY_VALUE_LIST:\n                        collection.setList(\"field_binary_list\", new RealmList<>(new byte[] {1,2,3}));\n                        assertElements(collection, obj -> {\n                            RealmList<byte[]> list = obj.getList(\"field_binary_list\", byte[].class);\n                            assertEquals(1, list.size());\n                            assertArrayEquals(new byte[] {1,2,3}, list.first());\n                        });\n                        break;\n                    case DATE_VALUE_LIST:\n                        collection.setList(\"field_date_list\", new RealmList<>(new Date(1000)));\n                        assertElements(collection, obj -> {\n                            RealmList<Date> list = obj.getList(\"field_date_list\", Date.class);\n                            assertEquals(1, list.size());\n                            assertEquals(new Date(1000), list.first());\n                        });\n                        break;\n                    case DECIMAL128_VALUE_LIST:\n                        collection.setList(\"field_decimal_list\", new RealmList<>(new Decimal128(1000)));\n                        assertElements(collection, obj -> {\n                            RealmList<Decimal128> list = obj.getList(\"field_decimal_list\", Decimal128.class);\n                            assertEquals(1, list.size());\n                            assertEquals(new Decimal128(1000), list.first());\n                        });\n                        break;\n                    case OBJECT_ID_VALUE_LIST:{\n                        String hex = TestHelper.randomObjectIdHexString();\n                        collection.setList(\"field_object_id_list\", new RealmList<>(new ObjectId(hex)));\n                        assertElements(collection, obj -> {\n                            RealmList<ObjectId> list = obj.getList(\"field_object_id_list\", ObjectId.class);\n                            assertEquals(1, list.size());\n                            assertEquals(new ObjectId(hex), list.first());\n                        });\n                        break;\n                    }\n                    case UUID_VALUE_LIST:{\n                        String uuid = UUID.randomUUID().toString();\n                        collection.setList(\"field_uuid_list\", new RealmList<>(UUID.fromString(uuid)));\n                        assertElements(collection, obj -> {\n                            RealmList<UUID> list = obj.getList(\"field_uuid_list\", UUID.class);\n                            assertEquals(1, list.size());\n                            assertEquals(UUID.fromString(uuid), list.first());\n                        });\n                        break;\n                    }\n                    default:\n                        fail(\"Unknown type: \" + type);\n                }\n            }\n        } finally {\n            dynamicRealm.close();\n        }\n    }\n\n    @Test\n    public void asJSON() throws JSONException {\n        Date date = Date.from(Calendar.getInstance().getTime().toInstant().truncatedTo(ChronoUnit.SECONDS));\n        SimpleDateFormat sdf = new SimpleDateFormat(\"yyyy-MM-dd HH:mm:ss\");\n        sdf.setTimeZone(TimeZone.getTimeZone(\"GMT\")); // Core return dates in UTC time\n        String now = sdf.format(date);\n\n        realm.beginTransaction();\n\n        AllTypes allTypes = realm.createObject(AllTypes.class);\n        Dog dog1 = realm.createObject(Dog.class);\n        Dog dog2 = realm.createObject(Dog.class);\n        Dog dog3 = realm.createObject(Dog.class);\n\n        dog1.setName(\"dog1\");\n        dog1.setAge(1);\n        dog1.setBirthday(date);\n        dog1.setHasTail(true);\n        dog1.setHeight(1.1f);\n        dog1.setWeight(10.1f);\n\n        dog2.setName(\"dog2\");\n        dog2.setAge(2);\n        dog2.setBirthday(date);\n        dog2.setHasTail(false);\n        dog2.setHeight(2.1f);\n        dog2.setWeight(20.1f);\n\n        dog3.setName(\"dog3\");\n        dog3.setAge(3);\n        dog3.setBirthday(date);\n        dog3.setHasTail(true);\n        dog3.setHeight(3.1f);\n        dog3.setWeight(30.1f);\n\n        Owner owner = realm.createObject(Owner.class);\n        owner.setName(\"Dog owner 1\");\n        dog3.setOwner(owner);\n\n        allTypes.setColumnString(\"alltypes1\");\n        allTypes.setColumnLong(1337L);\n        allTypes.setColumnFloat(3.14f);\n        allTypes.setColumnDouble(0.89123);\n        allTypes.setColumnBoolean(false);\n        allTypes.setColumnDate(date);\n        allTypes.setColumnDecimal128(new Decimal128(new BigDecimal(\"0.123456789\")));\n        allTypes.setColumnObjectId(new ObjectId(TestHelper.generateObjectIdHexString(7)));\n        allTypes.setColumnUUID(UUID.fromString(uuid1));\n        allTypes.setColumnBinary(new byte[]{1, 2, 3});\n        allTypes.setColumnMutableRealmInteger(0);\n        allTypes.setColumnRealmObject(dog1);\n        allTypes.getColumnRealmList().add(dog2);\n        allTypes.getColumnRealmList().add(dog3);\n        allTypes.getColumnStringList().add(\"Foo\");\n        allTypes.getColumnStringList().add(\"Bar\");\n        allTypes.getColumnBooleanList().add(false);\n        allTypes.getColumnBooleanList().add(true);\n        allTypes.getColumnLongList().add(1000L);\n        allTypes.getColumnLongList().add(2000L);\n        allTypes.getColumnDoubleList().add(1.123);\n        allTypes.getColumnDoubleList().add(5.321);\n        allTypes.getColumnFloatList().add(0.12f);\n        allTypes.getColumnFloatList().add(0.13f);\n        allTypes.getColumnDateList().add(date);\n        allTypes.getColumnDateList().add(date);\n        allTypes.getColumnDecimal128List().add(new Decimal128(-42));\n        allTypes.getColumnDecimal128List().add(Decimal128.NaN);\n        allTypes.getColumnDecimal128List().add(Decimal128.NEGATIVE_ZERO);\n        allTypes.getColumnDecimal128List().add(Decimal128.POSITIVE_ZERO);\n        allTypes.getColumnDecimal128List().add(Decimal128.NEGATIVE_INFINITY);\n        allTypes.getColumnDecimal128List().add(Decimal128.POSITIVE_INFINITY);\n        allTypes.getColumnObjectIdList().add(new ObjectId(TestHelper.generateObjectIdHexString(1)));\n        allTypes.getColumnObjectIdList().add(new ObjectId(TestHelper.generateObjectIdHexString(2)));\n        allTypes.getColumnUUIDList().add(UUID.fromString(uuid1));\n        allTypes.getColumnUUIDList().add(UUID.fromString(uuid2));\n\n        AllTypes allTypes2 = realm.createObject(AllTypes.class);\n        allTypes2.setColumnString(\"alltypes2\");\n        realm.commitTransaction();\n\n        RealmResults<AllTypes> all = realm.where(AllTypes.class)\n                .equalTo(\"columnString\", \"alltypes1\").findAll();\n        assertEquals(1, all.size());\n        String json = all.asJSON();\n\n        final String expectedJSON = \"[\\n\" +\n                \"   {\\n\" +\n                \"      \\\"_key\\\":100,\\n\" +\n                \"      \\\"columnString\\\":\\\"alltypes1\\\",\\n\" +\n                \"      \\\"columnLong\\\":1337,\\n\" +\n                \"      \\\"columnFloat\\\":3.1400001e+00,\\n\" +\n                \"      \\\"columnDouble\\\":8.9122999999999997e-01,\\n\" +\n                \"      \\\"columnBoolean\\\":false,\\n\" +\n                \"      \\\"columnDate\\\": \\\"\" + now + \"\\\",\\n\" +\n                \"      \\\"columnBinary\\\":\\\"AQID\\\",\\n\" +\n                \"      \\\"columnDecimal128\\\":\\\"1.23456789E-1\\\",\\n\" +\n                \"      \\\"columnObjectId\\\":\\\"789abcdef0123456789abcde\\\",\\n\" +\n                \"      \\\"columnUUID\\\":\\\"\"+ uuid1 +\"\\\",\\n\" +\n                \"      \\\"columnMutableRealmInteger\\\":0,\\n\" +\n                \"      \\\"columnRealmObject\\\":{\\n\" +\n                \"         \\\"_key\\\":100,\\n\" +\n                \"         \\\"name\\\":\\\"dog1\\\",\\n\" +\n                \"         \\\"age\\\":1,\\n\" +\n                \"         \\\"height\\\":1.1000000e+00,\\n\" +\n                \"         \\\"weight\\\":1.0100000381469727e+01,\\n\" +\n                \"         \\\"hasTail\\\":true,\\n\" +\n                \"         \\\"birthday\\\": \\\"\" + now + \"\\\",\\n\" +\n                \"         \\\"owner\\\":null\\n\" +\n                \"      },\\n\" +\n                \"      \\\"columnRealmList\\\":[\\n\" +\n                \"         {\\n\" +\n                \"            \\\"_key\\\":101,\\n\" +\n                \"            \\\"name\\\":\\\"dog2\\\",\\n\" +\n                \"            \\\"age\\\":2,\\n\" +\n                \"            \\\"height\\\":2.0999999e+00,\\n\" +\n                \"            \\\"weight\\\":2.0100000381469727e+01,\\n\" +\n                \"            \\\"hasTail\\\":false,\\n\" +\n                \"            \\\"birthday\\\": \\\"\" + now + \"\\\",\\n\" +\n                \"            \\\"owner\\\":null\\n\" +\n                \"         },\\n\" +\n                \"         {\\n\" +\n                \"            \\\"_key\\\":102,\\n\" +\n                \"            \\\"name\\\":\\\"dog3\\\",\\n\" +\n                \"            \\\"age\\\":3,\\n\" +\n                \"            \\\"height\\\":3.0999999e+00,\\n\" +\n                \"            \\\"weight\\\":3.0100000381469727e+01,\\n\" +\n                \"            \\\"hasTail\\\":true,\\n\" +\n                \"            \\\"birthday\\\": \\\"\" + now + \"\\\",\\n\" +\n                \"            \\\"owner\\\":{\\n\" +\n                \"               \\\"_key\\\":0,\\n\" +\n                \"               \\\"name\\\":\\\"Dog owner 1\\\",\\n\" +\n                \"               \\\"dogs\\\":[\\n\" +\n                \"\\n\" +\n                \"               ],\\n\" +\n                \"               \\\"cat\\\":null\\n\" +\n                \"            }\\n\" +\n                \"         }\\n\" +\n                \"      ],\\n\" +\n                \"      \\\"columnStringList\\\":[\\n\" +\n                \"         \\\"Foo\\\",\\n\" +\n                \"         \\\"Bar\\\"\\n\" +\n                \"      ],\\n\" +\n                \"      \\\"columnBinaryList\\\":[\\n\" +\n                \"\\n\" +\n                \"      ],\\n\" +\n                \"      \\\"columnBooleanList\\\":[\\n\" +\n                \"         false,\\n\" +\n                \"         true\\n\" +\n                \"      ],\\n\" +\n                \"      \\\"columnLongList\\\":[\\n\" +\n                \"         1000,\\n\" +\n                \"         2000\\n\" +\n                \"      ],\\n\" +\n                \"      \\\"columnDoubleList\\\":[\\n\" +\n                \"         1.1230000000000000e+00,\\n\" +\n                \"         5.3209999999999997e+00\\n\" +\n                \"      ],\\n\" +\n                \"      \\\"columnFloatList\\\":[\\n\" +\n                \"         1.2000000e-01,\\n\" +\n                \"         1.3000000e-01\\n\" +\n                \"      ],\\n\" +\n                \"      \\\"columnDateList\\\":[\\n\" +\n                \"            \\\"\" + now + \"\\\",\\n\" +\n                \"            \\\"\" + now + \"\\\"\\n\" +\n                \"      ],\\n\" +\n                \"      \\\"columnDecimal128List\\\":[\\n\" +\n                \"         \\\"-42\\\",\\n\" +\n                \"         \\\"NaN\\\",\\n\" +\n                \"         \\\"-0\\\",\\n\" +\n                \"         \\\"0\\\",\\n\" +\n                \"         \\\"-Inf\\\",\\n\" +\n                \"         \\\"Inf\\\"\\n\" +\n                \"      ],\\n\" +\n                \"      \\\"columnObjectIdList\\\":[\\n\" +\n                \"         \\\"123456789abcdef012345678\\\",\\n\" +\n                \"         \\\"23456789abcdef0123456789\\\"\\n\" +\n                \"      ],\\n\" +\n                \"      \\\"columnUUIDList\\\":[\\n\" +\n                \"         \\\"\"+ uuid1 +\"\\\",\\n\" +\n                \"         \\\"\"+ uuid2 +\"\\\"\\n\" +\n                \"      ]\\n\" +\n                \"   }\\n\" +\n                \"]\";\n        JSONAssert.assertEquals(expectedJSON, json, false);\n    }\n\n    @Test\n    public void asJSON_withEscaping() throws JSONException {\n        realm.beginTransaction();\n        PrimaryKeyAsLong element = realm.createObject(PrimaryKeyAsLong.class, 1);\n        String value = \"\\\"something\\\"\";\n        element.setName(value);\n        realm.commitTransaction();\n\n        RealmResults<PrimaryKeyAsLong> all = realm.where(PrimaryKeyAsLong.class)\n                .equalTo(PrimaryKeyAsString.FIELD_ID, element.getId())\n                .findAll();\n\n        assertEquals(1, all.size());\n\n        String json = all.asJSON();\n        final String expectedJSON = \"[{\\\"_key\\\":0,\\\"id\\\":1,\\\"name\\\":\\\"\\\\\\\"something\\\\\\\"\\\"}]\";\n        JSONAssert.assertEquals(expectedJSON, json, false);\n    }\n\n    @Test\n    public void asJSON_cycles() throws JSONException {\n        Date date = Date.from(Calendar.getInstance().getTime().toInstant().truncatedTo(ChronoUnit.SECONDS));\n        SimpleDateFormat sdf = new SimpleDateFormat(\"yyyy-MM-dd HH:mm:ss\");\n        sdf.setTimeZone(TimeZone.getTimeZone(\"GMT\")); // Core return dates in UTC time\n        String now = sdf.format(date);\n\n        CyclicType oneCyclicType = new CyclicType();\n        oneCyclicType.setName(\"One\");\n        oneCyclicType.setDate(date);\n\n        CyclicType anotherCyclicType = new CyclicType();\n        anotherCyclicType.setName(\"Two\");\n        anotherCyclicType.setDate(date);\n\n        oneCyclicType.setObject(anotherCyclicType);\n        anotherCyclicType.setObject(oneCyclicType);\n\n        realm.beginTransaction();\n        realm.insert(Arrays.asList(oneCyclicType, anotherCyclicType));\n        realm.commitTransaction();\n\n        RealmResults<CyclicType> realmObjects = realm.where(CyclicType.class).sort(CyclicType.FIELD_NAME).findAll();\n        assertEquals(2, realmObjects.size());\n        String json = realmObjects.asJSON();\n        String expectedJSON = \"[\\n\" +\n                \"    {\\n\" +\n                \"        \\\"_key\\\": 0,\\n\" +\n                \"        \\\"id\\\": 0,\\n\" +\n                \"        \\\"name\\\": \\\"One\\\",\\n\" +\n                \"        \\\"date\\\": \\\"\" + now + \"\\\",\\n\" +\n                \"        \\\"object\\\": {\\n\" +\n                \"            \\\"_key\\\": 1,\\n\" +\n                \"            \\\"id\\\": 0,\\n\" +\n                \"            \\\"name\\\": \\\"Two\\\",\\n\" +\n                \"            \\\"date\\\": \\\"\" + now + \"\\\",\\n\" +\n                \"            \\\"object\\\": {\\n\" +\n                \"                \\\"table\\\": \\\"class_CyclicType\\\",\\n\" +\n                \"                \\\"key\\\": 0\\n\" +\n                \"            },\\n\" +\n                \"            \\\"otherObject\\\": null,\\n\" +\n                \"            \\\"objects\\\": []\\n\" +\n                \"        },\\n\" +\n                \"        \\\"otherObject\\\": null,\\n\" +\n                \"        \\\"objects\\\": []\\n\" +\n                \"    },\\n\" +\n                \"    {\\n\" +\n                \"        \\\"_key\\\": 1,\\n\" +\n                \"        \\\"id\\\": 0,\\n\" +\n                \"        \\\"name\\\": \\\"Two\\\",\\n\" +\n                \"        \\\"date\\\": \\\"\" + now + \"\\\",\\n\" +\n                \"        \\\"object\\\": {\\n\" +\n                \"            \\\"_key\\\": 0,\\n\" +\n                \"            \\\"id\\\": 0,\\n\" +\n                \"            \\\"name\\\": \\\"One\\\",\\n\" +\n                \"            \\\"date\\\": \\\"\" + now + \"\\\",\\n\" +\n                \"            \\\"object\\\": {\\n\" +\n                \"                \\\"table\\\": \\\"class_CyclicType\\\",\\n\" +\n                \"                \\\"key\\\": 1\\n\" +\n                \"            },\\n\" +\n                \"            \\\"otherObject\\\": null,\\n\" +\n                \"            \\\"objects\\\": []\\n\" +\n                \"        },\\n\" +\n                \"        \\\"otherObject\\\": null,\\n\" +\n                \"        \\\"objects\\\": []\\n\" +\n                \"    }\\n\" +\n                \"]\";\n        JSONAssert.assertEquals(expectedJSON, json, false);\n    }\n\n    /**\n     * Test we can also hold primitive values in RealmResults. This is a somewhat concealed feature\n     * since we do not allow queries on primitive types as per version 10.3.1. The only place in\n     * the SDK that returns primitive RealmResults is the {@link RealmDictionary#values()}.\n     */\n    @Test\n    public void canHoldPrimitiveTypes() {\n        String KEY_1 = \"KEY_1\";\n        String KEY_2 = \"KEY_2\";\n        String VALUE_1 = \"VALUE_1\";\n        String VALUE_2 = \"VALUE_2\";\n\n        RealmDictionary<String> stringDictionary = new RealmDictionary<>();\n        stringDictionary.put(KEY_1, VALUE_1);\n        stringDictionary.put(KEY_2, VALUE_2);\n\n        realm.beginTransaction();\n        DictionaryAllTypes object = new DictionaryAllTypes();\n        object.setColumnStringDictionary(stringDictionary);\n        DictionaryAllTypes objectFromRealm = realm.copyToRealm(object);\n        realm.commitTransaction();\n\n        RealmDictionary<String> stringDictionaryFromRealm = objectFromRealm.getColumnStringDictionary();\n        assertNotNull(stringDictionaryFromRealm);\n\n        Collection<String> values = stringDictionaryFromRealm.values();\n        assertNotNull(values);\n        assertTrue(values instanceof RealmResults);\n        assertTrue(values.contains(VALUE_1));\n        assertTrue(values.contains(VALUE_2));\n\n        // Not returning RealmResults per se, but rather wrapped in a HashSet\n        Set<String> keySet = stringDictionaryFromRealm.keySet();\n        assertNotNull(keySet);\n        assertTrue(keySet.contains(KEY_1));\n        assertTrue(keySet.contains(KEY_2));\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/RealmSchemaTests.java",
    "content": "/*\n * Copyright 2015 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\npackage io.realm;\n\n\nimport org.hamcrest.CoreMatchers;\nimport org.junit.After;\nimport org.junit.Before;\nimport org.junit.Rule;\nimport org.junit.Test;\nimport org.junit.rules.ExpectedException;\nimport org.junit.runner.RunWith;\nimport org.junit.runners.Parameterized;\n\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Set;\n\nimport io.realm.entities.AllJavaTypes;\nimport io.realm.entities.Cat;\nimport io.realm.entities.Dog;\nimport io.realm.entities.DogPrimaryKey;\nimport io.realm.entities.NullTypes;\nimport io.realm.entities.Owner;\nimport io.realm.entities.PrimaryKeyAsString;\nimport io.realm.internal.Table;\n\nimport static org.junit.Assert.assertEquals;\nimport static org.junit.Assert.assertFalse;\nimport static org.junit.Assert.assertNotNull;\nimport static org.junit.Assert.assertNotSame;\nimport static org.junit.Assert.assertNull;\nimport static org.junit.Assert.assertSame;\nimport static org.junit.Assert.assertThat;\nimport static org.junit.Assert.assertTrue;\nimport static org.junit.Assert.fail;\n\n@RunWith(Parameterized.class)\npublic class RealmSchemaTests {\n\n    private enum SchemaType {\n        MUTABLE(MutableRealmObjectSchema.class),\n        IMMUTABLE(ImmutableRealmObjectSchema.class);\n\n        final Class<? extends RealmObjectSchema> objectSchemaClass;\n\n        SchemaType(Class<? extends RealmObjectSchema> objectSchemaClass) {\n            this.objectSchemaClass = objectSchemaClass;\n        }\n    }\n\n    @Rule\n    public final TestRealmConfigurationFactory configFactory = new TestRealmConfigurationFactory();\n    @Rule\n    public final ExpectedException thrown = ExpectedException.none();\n\n    private BaseRealm realm;\n    private RealmSchema realmSchema;\n    private SchemaType type;\n\n    @Parameterized.Parameters(name = \"{0}\")\n    public static List<SchemaType> data() {\n        return Arrays.asList(SchemaType.values());\n    }\n\n    public RealmSchemaTests(SchemaType type) {\n        this.type = type;\n    }\n\n    @Before\n    public void setUp() {\n        RealmConfiguration realmConfig = configFactory.createConfigurationBuilder()\n                .schema(AllJavaTypes.class, Owner.class, PrimaryKeyAsString.class, Cat.class, Dog.class,\n                        DogPrimaryKey.class, NullTypes.class)\n                .build();\n        Realm.getInstance(realmConfig).close(); // create Schema\n        if (type == SchemaType.MUTABLE) {\n            realm = DynamicRealm.getInstance(realmConfig);\n        } else {\n            realm = Realm.getInstance(realmConfig);\n        }\n        realmSchema = this.realm.getSchema();\n        realm.beginTransaction();\n    }\n\n    @After\n    public void tearDown() {\n        realm.close();\n    }\n\n    @Test\n    public void getAll() {\n        Set<RealmObjectSchema> objectSchemas = realmSchema.getAll();\n        assertEquals(7, objectSchemas.size());\n\n        List<String> expectedTables = new ArrayList<>(Arrays.asList(\n                AllJavaTypes.CLASS_NAME, \"Owner\", \"Cat\", \"Dog\", \"DogPrimaryKey\", \"PrimaryKeyAsString\", NullTypes.CLASS_NAME));\n        for (RealmObjectSchema objectSchema : objectSchemas) {\n            assertThat(objectSchema, CoreMatchers.instanceOf(type.objectSchemaClass));\n            if (!expectedTables.remove(objectSchema.getClassName())) {\n                fail(objectSchema.getClassName() + \" is not expected\");\n            }\n        }\n        assertTrue(\"expected class is not contained in schema: \" + (expectedTables.isEmpty() ? \"\" : expectedTables.get(0)),\n                expectedTables.isEmpty());\n    }\n\n    @Test\n    public void create() {\n        final String[] validClassNames = {\n                TestHelper.getRandomString(1),\n                \"Darby\",\n                TestHelper.getRandomString(Table.CLASS_NAME_MAX_LENGTH)\n        };\n\n        if (type == SchemaType.IMMUTABLE) {\n            thrown.expect(UnsupportedOperationException.class);\n            realmSchema.create(validClassNames[0]);\n            return;\n        }\n\n        for (String validClassName : validClassNames) {\n            realmSchema.create(validClassName);\n            assertTrue(realmSchema.contains(validClassName));\n        }\n    }\n\n    @Test\n    public void create_invalidNameThrows() {\n        if (type == SchemaType.IMMUTABLE) {\n            return;\n        }\n\n        String[] names = { null, \"\", TestHelper.getRandomString(58) };\n\n        for (String name : names) {\n            try {\n                realmSchema.create(name);\n                fail();\n            } catch (IllegalArgumentException ignored) {\n            }\n            assertFalse(String.format(\"'%s' failed\", name), realmSchema.contains(name));\n        }\n    }\n\n    @Test\n    public void create_duplicatedNameThrows() {\n        if (type == SchemaType.IMMUTABLE) {\n            return;\n        }\n\n        realmSchema.create(\"Foo\");\n        thrown.expect(IllegalArgumentException.class);\n        realmSchema.create(\"Foo\");\n    }\n\n    @Test\n    public void createWithPrimaryKeyField_string() {\n        final String[] validClassNames = {\n                TestHelper.getRandomString(1),\n                \"Darby\",\n                TestHelper.getRandomString(Table.CLASS_NAME_MAX_LENGTH)\n        };\n\n        if (type == SchemaType.IMMUTABLE) {\n            thrown.expect(UnsupportedOperationException.class);\n            realmSchema.createWithPrimaryKeyField(validClassNames[0], \"pkField\", String.class);\n            return;\n        }\n\n        for (String validClassName : validClassNames) {\n            // Not nullable\n            RealmObjectSchema objectSchema = realmSchema.createWithPrimaryKeyField(validClassName,\n                    \"pkField\", String.class, FieldAttribute.REQUIRED);\n            assertEquals(\"pkField\", objectSchema.getPrimaryKey());\n            assertEquals(RealmFieldType.STRING, objectSchema.getFieldType(\"pkField\"));\n            assertFalse(objectSchema.isNullable(\"pkField\"));\n            assertTrue(objectSchema.hasIndex(\"pkField\"));\n\n            realmSchema.remove(validClassName);\n\n            // Nullable\n            objectSchema = realmSchema.createWithPrimaryKeyField(validClassName,\n                    \"pkField\", String.class);\n            assertEquals(\"pkField\", objectSchema.getPrimaryKey());\n            assertEquals(RealmFieldType.STRING, objectSchema.getFieldType(\"pkField\"));\n            assertTrue(objectSchema.isNullable(\"pkField\"));\n            assertTrue(objectSchema.hasIndex(\"pkField\"));\n        }\n    }\n\n    @Test\n    public void createWithPrimaryKeyField_boxedInteger() {\n        final String[] validClassNames = {\n                TestHelper.getRandomString(1),\n                \"Darby\",\n                TestHelper.getRandomString(Table.CLASS_NAME_MAX_LENGTH)\n        };\n\n        if (type == SchemaType.IMMUTABLE) {\n            thrown.expect(UnsupportedOperationException.class);\n            realmSchema.createWithPrimaryKeyField(validClassNames[0], \"pkField\", Integer.class);\n            return;\n        }\n\n        for (String validClassName : validClassNames) {\n            // Not nullable\n\n            RealmObjectSchema objectSchema = realmSchema.createWithPrimaryKeyField(validClassName,\n                    \"pkField\", Integer.class, FieldAttribute.REQUIRED);\n            assertEquals(\"pkField\", objectSchema.getPrimaryKey());\n            assertEquals(RealmFieldType.INTEGER, objectSchema.getFieldType(\"pkField\"));\n            assertFalse(objectSchema.isNullable(\"pkField\"));\n            assertTrue(objectSchema.hasIndex(\"pkField\"));\n\n            realmSchema.remove(validClassName);\n\n            // Nullable\n\n            objectSchema = realmSchema.createWithPrimaryKeyField(validClassName, \"pkField\", Integer.class);\n            assertEquals(\"pkField\", objectSchema.getPrimaryKey());\n            assertEquals(RealmFieldType.INTEGER, objectSchema.getFieldType(\"pkField\"));\n            assertTrue(objectSchema.isNullable(\"pkField\"));\n            assertTrue(objectSchema.hasIndex(\"pkField\"));\n        }\n    }\n\n    @Test\n    public void createWithPrimaryKeyField_int() {\n        final String[] validClassNames = {\n                TestHelper.getRandomString(1),\n                \"Darby\",\n                TestHelper.getRandomString(Table.CLASS_NAME_MAX_LENGTH)\n        };\n\n        if (type == SchemaType.IMMUTABLE) {\n            thrown.expect(UnsupportedOperationException.class);\n            realmSchema.createWithPrimaryKeyField(validClassNames[0], \"pkField\", int.class);\n            return;\n        }\n\n        for (String validClassName : validClassNames) {\n            // Not nullable\n\n            RealmObjectSchema objectSchema = realmSchema.createWithPrimaryKeyField(validClassName,\n                    \"pkField\", int.class, FieldAttribute.REQUIRED);\n            assertEquals(\"pkField\", objectSchema.getPrimaryKey());\n            assertEquals(RealmFieldType.INTEGER, objectSchema.getFieldType(\"pkField\"));\n            assertFalse(objectSchema.isNullable(\"pkField\"));\n            assertTrue(objectSchema.hasIndex(\"pkField\"));\n\n            realmSchema.remove(validClassName);\n\n            // Nullable\n\n            objectSchema = realmSchema.createWithPrimaryKeyField(validClassName, \"pkField\", int.class);\n            assertEquals(\"pkField\", objectSchema.getPrimaryKey());\n            assertEquals(RealmFieldType.INTEGER, objectSchema.getFieldType(\"pkField\"));\n            assertFalse(objectSchema.isNullable(\"pkField\"));\n            assertTrue(objectSchema.hasIndex(\"pkField\"));\n        }\n    }\n\n    @Test\n    public void createWithPrimaryKeyField_explicitIndexed() {\n        if (type == SchemaType.IMMUTABLE) {\n            return;\n        }\n        realmSchema.createWithPrimaryKeyField(\"Foo\", \"pkField\", int.class,\n                FieldAttribute.INDEXED);\n        RealmObjectSchema objectSchema = realmSchema.getSchemaForClass(\"Foo\");\n        assertEquals(\"pkField\", objectSchema.getPrimaryKey());\n        assertEquals(RealmFieldType.INTEGER, objectSchema.getFieldType(\"pkField\"));\n        assertFalse(objectSchema.isNullable(\"pkField\"));\n        assertTrue(objectSchema.hasIndex(\"pkField\"));\n    }\n\n    @Test\n    public void createWithPrimaryKeyField_explicitPrimaryKey() {\n        if (type == SchemaType.IMMUTABLE) {\n            return;\n        }\n        realmSchema.createWithPrimaryKeyField(\"Foo\", \"pkField\", int.class,\n                FieldAttribute.PRIMARY_KEY);\n        RealmObjectSchema objectSchema = realmSchema.getSchemaForClass(\"Foo\");\n        assertEquals(\"pkField\", objectSchema.getPrimaryKey());\n        assertEquals(RealmFieldType.INTEGER, objectSchema.getFieldType(\"pkField\"));\n        assertFalse(objectSchema.isNullable(\"pkField\"));\n        assertTrue(objectSchema.hasIndex(\"pkField\"));\n    }\n\n    @Test\n    public void createWithPrimaryKeyField_invalidClassNameThrows() {\n        if (type == SchemaType.IMMUTABLE) {\n            return;\n        }\n        String[] invalidNames = { null, \"\", TestHelper.getRandomString(Table.CLASS_NAME_MAX_LENGTH + 1) };\n\n        for (String name : invalidNames) {\n            try {\n                realmSchema.createWithPrimaryKeyField(name, \"pkField\", int.class);\n                fail();\n            } catch (IllegalArgumentException ignored) {\n            }\n            assertFalse(String.format(\"'%s' failed\", name), realmSchema.contains(name));\n        }\n    }\n\n    @Test\n    public void createWithPrimaryKeyField_invalidFieldNameThrows() {\n        if (type == SchemaType.IMMUTABLE) {\n            return;\n        }\n        String[] invalidFieldNames = new String[] { null, \"\", \"foo.bar\", TestHelper.getRandomString(65) };\n        for (String fieldName : invalidFieldNames) {\n            try {\n                realmSchema.createWithPrimaryKeyField(\"Foo\", fieldName, int.class);\n                fail();\n            } catch (IllegalArgumentException ignored) {\n            }\n        }\n    }\n\n    @Test\n    public void createWithPrimaryKeyField_invalidFieldTypeThrows() {\n        if (type == SchemaType.IMMUTABLE) {\n            return;\n        }\n        Class<?>[] fieldTypes = new Class<?>[] {float.class, Float.class, Double.class, double.class, RealmObject.class,\n                RealmList.class, Object.class};\n        for (Class<?> fieldType : fieldTypes) {\n            try {\n                realmSchema.createWithPrimaryKeyField(\"Foo\", \"pkField\", fieldType);\n                fail();\n            } catch (IllegalArgumentException ignored) {\n            }\n        }\n    }\n\n    @Test\n    public void createWithPrimaryKeyField_duplicatedNameThrows() {\n        if (type == SchemaType.IMMUTABLE) {\n            return;\n        }\n        realmSchema.createWithPrimaryKeyField(\"Foo\", \"pkField\", int.class);\n        thrown.expect(IllegalArgumentException.class);\n        realmSchema.createWithPrimaryKeyField(\"Foo\", \"pkField\", int.class);\n    }\n\n    @Test\n    public void get() {\n        RealmObjectSchema objectSchema = realmSchema.get(AllJavaTypes.CLASS_NAME);\n        assertNotNull(objectSchema);\n        assertEquals(AllJavaTypes.CLASS_NAME, objectSchema.getClassName());\n        assertThat(objectSchema, CoreMatchers.instanceOf(type.objectSchemaClass));\n    }\n\n    @Test\n    public void get_unknownClass() {\n        assertNull(realmSchema.get(\"Foo\"));\n    }\n\n    @Test\n    public void rename() {\n        if (type == SchemaType.MUTABLE) {\n            realmSchema.rename(\"Owner\", \"Owner2\");\n            assertFalse(realmSchema.contains(\"Owner\"));\n            assertTrue(realmSchema.contains(\"Owner2\"));\n        } else {\n            thrown.expect(UnsupportedOperationException.class);\n            realmSchema.rename(\"Owner\", \"Owner2\");\n        }\n    }\n\n    @Test\n    public void rename_invalidArgumentThrows() {\n        if (type == SchemaType.IMMUTABLE) {\n            return;\n        }\n\n        String[] illegalNames = new String[] { null, \"\" };\n\n        // Tests as first parameter.\n        for (String illegalName : illegalNames) {\n            try {\n                realmSchema.rename(illegalName, AllJavaTypes.CLASS_NAME);\n                fail(illegalName + \" should throw an exception\");\n            } catch (IllegalArgumentException ignored) {\n            }\n        }\n\n        // Tests as last parameters.\n        for (String illegalName : illegalNames) {\n            try {\n                realmSchema.rename(AllJavaTypes.CLASS_NAME, illegalName);\n                fail(illegalName + \" should throw an exception\");\n            } catch (IllegalArgumentException ignored) {\n            }\n        }\n    }\n\n    @Test\n    public void rename_shouldChangeInfoInPKTable() {\n        if (type == SchemaType.IMMUTABLE) {\n            return;\n        }\n\n        final String NEW_NAME = \"NewPrimaryKeyAsString\";\n        assertTrue(realmSchema.contains(PrimaryKeyAsString.CLASS_NAME));\n        realmSchema.rename(PrimaryKeyAsString.CLASS_NAME, NEW_NAME);\n        assertFalse(realmSchema.contains(PrimaryKeyAsString.CLASS_NAME));\n        assertTrue(realmSchema.contains(NEW_NAME));\n        RealmObjectSchema objectSchema = realmSchema.get(NEW_NAME);\n\n        assertEquals(PrimaryKeyAsString.FIELD_PRIMARY_KEY, objectSchema.getPrimaryKey());\n\n        // Creates an object with the old name, and the PK should not exist after created.\n        RealmObjectSchema oldObjectSchema = realmSchema.create(PrimaryKeyAsString.CLASS_NAME);\n        oldObjectSchema.addField(PrimaryKeyAsString.FIELD_PRIMARY_KEY, String.class);\n\n        try {\n            // It should not have primary key anymore at this point.\n            oldObjectSchema.getPrimaryKey();\n            fail();\n        } catch (IllegalStateException ignored) {\n        }\n\n        oldObjectSchema.addPrimaryKey(PrimaryKeyAsString.FIELD_PRIMARY_KEY);\n        assertEquals(PrimaryKeyAsString.FIELD_PRIMARY_KEY, oldObjectSchema.getPrimaryKey());\n    }\n\n    @Test\n    public void remove() {\n        if (type == SchemaType.IMMUTABLE) {\n            thrown.expect(UnsupportedOperationException.class);\n            realmSchema.remove(AllJavaTypes.CLASS_NAME);\n        } else {\n            realmSchema.remove(AllJavaTypes.CLASS_NAME);\n            assertFalse(realmSchema.contains(AllJavaTypes.CLASS_NAME));\n        }\n    }\n\n    @Test\n    public void remove_invalidArgumentThrows() {\n        if (type == SchemaType.IMMUTABLE) {\n            return;\n        }\n\n        try {\n            realmSchema.remove(\"Foo\");\n            fail();\n        } catch (IllegalArgumentException ignored) {\n        }\n\n        try {\n            realmSchema.remove(null);\n            fail();\n        } catch (IllegalArgumentException ignored) {\n        }\n    }\n\n    // Test that it if { A -> B  && B -> A } you should remove the individual fields first before removing the entire\n    // class. This also include transitive dependencies.\n    @Test\n    public void remove_classWithReferencesThrows() {\n        if (type == SchemaType.IMMUTABLE) {\n            return;\n        }\n\n        try {\n            realmSchema.remove(\"Cat\");\n            fail();\n        } catch (IllegalStateException ignored) {\n        }\n\n        RealmObjectSchema ownerSchema = realmSchema.get(\"Owner\");\n        RealmObjectSchema catSchema = realmSchema.get(\"Cat\");\n        ownerSchema.removeField(\"cat\");\n        catSchema.removeField(\"owner\");\n        realmSchema.remove(\"Cat\");\n        assertFalse(realmSchema.contains(\"Cat\"));\n    }\n\n    @Test\n    public void remove_shouldRemoveInfoFromPKTable() {\n        if (type == SchemaType.IMMUTABLE) {\n            return;\n        }\n\n        assertTrue(realmSchema.contains(PrimaryKeyAsString.CLASS_NAME));\n        realmSchema.remove(PrimaryKeyAsString.CLASS_NAME);\n        assertFalse(realmSchema.contains(PrimaryKeyAsString.CLASS_NAME));\n\n        RealmObjectSchema objectSchema = realmSchema.create(PrimaryKeyAsString.CLASS_NAME);\n        objectSchema.addField(PrimaryKeyAsString.FIELD_PRIMARY_KEY, String.class);\n\n        try {\n            // It should not have primary key anymore at this point.\n            objectSchema.getPrimaryKey();\n            fail();\n        } catch (IllegalStateException ignored) {\n        }\n\n        objectSchema.addPrimaryKey(PrimaryKeyAsString.FIELD_PRIMARY_KEY);\n        assertEquals(PrimaryKeyAsString.FIELD_PRIMARY_KEY, objectSchema.getPrimaryKey());\n    }\n\n    @Test\n    public void remove_shouldClearDynamicCache() {\n        if (type == SchemaType.IMMUTABLE) {\n            return;\n        }\n\n        realmSchema.create(\"foo\");\n        // getSchemaForClass is an internal method, but used from DynamicRealmObject and RealmQuery\n        final RealmObjectSchema previousFoo = realmSchema.getSchemaForClass(\"foo\");\n\n        realmSchema.remove(\"foo\");\n\n        realmSchema.create(\"foo\");\n        final RealmObjectSchema newFoo = realmSchema.getSchemaForClass(\"foo\");\n\n        assertNotSame(previousFoo, newFoo);\n\n        try {\n            assertEquals(\"foo\", previousFoo.getClassName());\n            fail();\n        } catch (IllegalStateException ignored) {\n        }\n\n        assertEquals(\"foo\", newFoo.getClassName());\n    }\n\n    @Test\n    public void rename_shouldUpdateDynamicCache() {\n        if (type == SchemaType.IMMUTABLE) {\n            return;\n        }\n\n        realmSchema.create(\"foo\");\n        // getSchemaForClass is an internal method, but used from DynamicRealmObject and RealmQuery\n        final RealmObjectSchema foo = realmSchema.getSchemaForClass(\"foo\");\n\n        realmSchema.rename(\"foo\", \"bar\");\n\n        final RealmObjectSchema bar = realmSchema.getSchemaForClass(\"bar\");\n\n        assertSame(foo, bar);\n        assertEquals(\"bar\", bar.getClassName());\n    }\n\n    @Test\n    public void schemaInformationOfPrimitiveLists() {\n        Map<String, RealmFieldType> fieldNameToType = new HashMap<>();\n        fieldNameToType.put(NullTypes.FIELD_STRING_LIST_NULL, RealmFieldType.STRING_LIST);\n        fieldNameToType.put(NullTypes.FIELD_STRING_LIST_NOT_NULL, RealmFieldType.STRING_LIST);\n        fieldNameToType.put(NullTypes.FIELD_BINARY_LIST_NULL, RealmFieldType.BINARY_LIST);\n        fieldNameToType.put(NullTypes.FIELD_BINARY_LIST_NOT_NULL, RealmFieldType.BINARY_LIST);\n        fieldNameToType.put(NullTypes.FIELD_BOOLEAN_LIST_NULL, RealmFieldType.BOOLEAN_LIST);\n        fieldNameToType.put(NullTypes.FIELD_BOOLEAN_LIST_NOT_NULL, RealmFieldType.BOOLEAN_LIST);\n        fieldNameToType.put(NullTypes.FIELD_DATE_LIST_NULL, RealmFieldType.DATE_LIST);\n        fieldNameToType.put(NullTypes.FIELD_DATE_LIST_NOT_NULL, RealmFieldType.DATE_LIST);\n        fieldNameToType.put(NullTypes.FIELD_DECIMAL128_LIST_NULL, RealmFieldType.DECIMAL128_LIST);\n        fieldNameToType.put(NullTypes.FIELD_DECIMAL128_LIST_NOT_NULL, RealmFieldType.DECIMAL128_LIST);\n        fieldNameToType.put(NullTypes.FIELD_OBJECT_ID_LIST_NULL, RealmFieldType.OBJECT_ID_LIST);\n        fieldNameToType.put(NullTypes.FIELD_OBJECT_ID_LIST_NOT_NULL, RealmFieldType.OBJECT_ID_LIST);\n        fieldNameToType.put(NullTypes.FIELD_DOUBLE_LIST_NULL, RealmFieldType.DOUBLE_LIST);\n        fieldNameToType.put(NullTypes.FIELD_DOUBLE_LIST_NOT_NULL, RealmFieldType.DOUBLE_LIST);\n        fieldNameToType.put(NullTypes.FIELD_FLOAT_LIST_NULL, RealmFieldType.FLOAT_LIST);\n        fieldNameToType.put(NullTypes.FIELD_FLOAT_LIST_NOT_NULL, RealmFieldType.FLOAT_LIST);\n        fieldNameToType.put(NullTypes.FIELD_LONG_LIST_NULL, RealmFieldType.INTEGER_LIST);\n        fieldNameToType.put(NullTypes.FIELD_LONG_LIST_NOT_NULL, RealmFieldType.INTEGER_LIST);\n        fieldNameToType.put(NullTypes.FIELD_INTEGER_LIST_NULL, RealmFieldType.INTEGER_LIST);\n        fieldNameToType.put(NullTypes.FIELD_INTEGER_LIST_NOT_NULL, RealmFieldType.INTEGER_LIST);\n        fieldNameToType.put(NullTypes.FIELD_SHORT_LIST_NULL, RealmFieldType.INTEGER_LIST);\n        fieldNameToType.put(NullTypes.FIELD_SHORT_LIST_NOT_NULL, RealmFieldType.INTEGER_LIST);\n        fieldNameToType.put(NullTypes.FIELD_BYTE_LIST_NULL, RealmFieldType.INTEGER_LIST);\n        fieldNameToType.put(NullTypes.FIELD_BYTE_LIST_NOT_NULL, RealmFieldType.INTEGER_LIST);\n\n        final RealmObjectSchema objectSchema = realmSchema.get(NullTypes.CLASS_NAME);\n        assertNotNull(objectSchema);\n\n        for (Map.Entry<String, RealmFieldType> entry : fieldNameToType.entrySet()) {\n            final String fieldName = entry.getKey();\n            final RealmFieldType expectedType = entry.getValue();\n\n            assertEquals(expectedType, objectSchema.getFieldType(fieldName));\n            assertEquals(\"isNullable('\" + fieldName + \"')\",\n                    !fieldName.endsWith(\"NotNull\"), objectSchema.isNullable(fieldName));\n            assertEquals(\"isRequired('\" + fieldName + \"')\",\n                    fieldName.endsWith(\"NotNull\"), objectSchema.isRequired(fieldName));\n            assertFalse(objectSchema.isPrimaryKey(fieldName));\n        }\n    }\n\n    @Test\n    public void rename_newNameExists() {\n        if (type == SchemaType.IMMUTABLE) {\n            return;\n        }\n        thrown.expect(IllegalArgumentException.class);\n        thrown.expectMessage(\n                CoreMatchers.containsString(\"Cat cannot be renamed because the new class already exists\"));\n        realmSchema.rename(\"Cat\", \"Dog\");\n    }\n\n    @Test\n    public void mutableMethodsCalled_notInTransaction() {\n        if (type == SchemaType.IMMUTABLE) {\n            return;\n        }\n\n        realm.cancelTransaction();\n\n        try {\n            realmSchema.create(\"Foo\");\n            fail();\n        } catch (IllegalStateException expected) {\n            assertThat(expected.getMessage(), CoreMatchers.containsString(\"transaction\"));\n        }\n\n        try {\n            realmSchema.createWithPrimaryKeyField(\"Foo\", \"PK\", String.class);\n            fail();\n        } catch (IllegalStateException expected) {\n            assertThat(expected.getMessage(), CoreMatchers.containsString(\"transaction\"));\n        }\n\n        try {\n            realmSchema.remove(\"Cat\");\n            fail();\n        } catch (IllegalStateException expected) {\n            assertThat(expected.getMessage(), CoreMatchers.containsString(\"transaction\"));\n        }\n\n        try {\n            realmSchema.rename(\"Cat\", \"Foo1\");\n            fail();\n        } catch (IllegalStateException expected) {\n            assertThat(expected.getMessage(), CoreMatchers.containsString(\"transaction\"));\n        }\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/RealmTests.java",
    "content": "/*\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\npackage io.realm;\n\nimport static org.junit.Assert.assertEquals;\nimport static org.junit.Assert.assertFalse;\nimport static org.junit.Assert.assertNotNull;\nimport static org.junit.Assert.assertNotSame;\nimport static org.junit.Assert.assertNull;\nimport static org.junit.Assert.assertSame;\nimport static org.junit.Assert.assertThat;\nimport static org.junit.Assert.assertTrue;\nimport static org.junit.Assert.fail;\nimport static org.mockito.Mockito.mock;\nimport static org.mockito.Mockito.when;\nimport static io.realm.TestHelper.testNoObjectFound;\nimport static io.realm.TestHelper.testOneObjectFound;\nimport static io.realm.internal.test.ExtraTests.assertArrayEquals;\n\nimport android.content.Context;\nimport android.os.Build;\nimport android.os.Looper;\nimport android.os.StrictMode;\nimport android.os.SystemClock;\n\nimport androidx.test.annotation.UiThreadTest;\nimport androidx.test.ext.junit.runners.AndroidJUnit4;\nimport androidx.test.platform.app.InstrumentationRegistry;\nimport androidx.test.rule.UiThreadTestRule;\n\nimport junit.framework.AssertionFailedError;\n\nimport org.bson.types.Decimal128;\nimport org.bson.types.ObjectId;\nimport org.hamcrest.CoreMatchers;\nimport org.json.JSONArray;\nimport org.json.JSONException;\nimport org.json.JSONObject;\nimport org.junit.After;\nimport org.junit.Assume;\nimport org.junit.Before;\nimport org.junit.Ignore;\nimport org.junit.Rule;\nimport org.junit.Test;\nimport org.junit.rules.ExpectedException;\nimport org.junit.rules.TemporaryFolder;\nimport org.junit.runner.RunWith;\nimport org.mockito.invocation.InvocationOnMock;\nimport org.mockito.stubbing.Answer;\n\nimport java.io.File;\nimport java.io.FilenameFilter;\nimport java.io.IOException;\nimport java.io.InputStream;\nimport java.lang.reflect.InvocationTargetException;\nimport java.math.BigDecimal;\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.Date;\nimport java.util.List;\nimport java.util.Objects;\nimport java.util.Random;\nimport java.util.Scanner;\nimport java.util.UUID;\nimport java.util.concurrent.Callable;\nimport java.util.concurrent.CountDownLatch;\nimport java.util.concurrent.ExecutionException;\nimport java.util.concurrent.ExecutorService;\nimport java.util.concurrent.Executors;\nimport java.util.concurrent.Future;\nimport java.util.concurrent.TimeUnit;\nimport java.util.concurrent.atomic.AtomicBoolean;\nimport java.util.concurrent.atomic.AtomicInteger;\nimport java.util.concurrent.atomic.AtomicLong;\nimport java.util.concurrent.atomic.AtomicReference;\n\nimport io.realm.entities.AllJavaTypes;\nimport io.realm.entities.AllTypes;\nimport io.realm.entities.AllTypesPrimaryKey;\nimport io.realm.entities.Cat;\nimport io.realm.entities.CyclicType;\nimport io.realm.entities.CyclicTypePrimaryKey;\nimport io.realm.entities.DefaultValueConstructor;\nimport io.realm.entities.DefaultValueFromOtherConstructor;\nimport io.realm.entities.DefaultValueOfField;\nimport io.realm.entities.DefaultValueOverwriteNullLink;\nimport io.realm.entities.DefaultValueSetter;\nimport io.realm.entities.Dog;\nimport io.realm.entities.DogPrimaryKey;\nimport io.realm.entities.NoPrimaryKeyNullTypes;\nimport io.realm.entities.NonLatinFieldNames;\nimport io.realm.entities.Object4957;\nimport io.realm.entities.Owner;\nimport io.realm.entities.OwnerPrimaryKey;\nimport io.realm.entities.PrimaryKeyAsBoxedByte;\nimport io.realm.entities.PrimaryKeyAsBoxedInteger;\nimport io.realm.entities.PrimaryKeyAsBoxedLong;\nimport io.realm.entities.PrimaryKeyAsBoxedShort;\nimport io.realm.entities.PrimaryKeyAsLong;\nimport io.realm.entities.PrimaryKeyAsString;\nimport io.realm.entities.PrimaryKeyMix;\nimport io.realm.entities.PrimaryKeyRequiredAsBoxedByte;\nimport io.realm.entities.PrimaryKeyRequiredAsBoxedInteger;\nimport io.realm.entities.PrimaryKeyRequiredAsBoxedLong;\nimport io.realm.entities.PrimaryKeyRequiredAsBoxedShort;\nimport io.realm.entities.PrimaryKeyRequiredAsString;\nimport io.realm.entities.RandomPrimaryKey;\nimport io.realm.entities.StringAndInt;\nimport io.realm.entities.StringOnly;\nimport io.realm.entities.StringOnlyReadOnly;\nimport io.realm.exceptions.RealmException;\nimport io.realm.exceptions.RealmFileException;\nimport io.realm.exceptions.RealmMigrationNeededException;\nimport io.realm.exceptions.RealmPrimaryKeyConstraintException;\nimport io.realm.internal.OsSharedRealm;\nimport io.realm.internal.util.Pair;\nimport io.realm.log.RealmLog;\nimport io.realm.objectid.NullPrimaryKey;\nimport io.realm.rule.BlockingLooperThread;\nimport io.realm.util.RealmThread;\n\n\n@RunWith(AndroidJUnit4.class)\npublic class RealmTests {\n    private final static int TEST_DATA_SIZE = 10;\n\n    @Rule\n    public final UiThreadTestRule uiThreadTestRule = new UiThreadTestRule();\n    @Rule\n    public final TestRealmConfigurationFactory configFactory = new TestRealmConfigurationFactory();\n    @Rule\n    public final TemporaryFolder tmpFolder = new TemporaryFolder();\n    @Rule\n    public final ExpectedException thrown = ExpectedException.none();\n\n    public final BlockingLooperThread looperThread = new BlockingLooperThread();\n    private Context context;\n    private Realm realm;\n    private List<String> columnData = new ArrayList<String>() {{\n        add(AllTypes.FIELD_DOUBLE);\n        add(AllTypes.FIELD_FLOAT);\n        add(AllTypes.FIELD_LONG);\n        add(AllTypes.FIELD_DECIMAL128);\n        add(AllTypes.FIELD_BOOLEAN);\n        add(AllTypes.FIELD_DATE);\n        add(AllTypes.FIELD_OBJECT_ID);\n        add(AllTypes.FIELD_STRING);\n        add(AllTypes.FIELD_BINARY);\n        add(AllTypes.FIELD_UUID);\n        add(AllTypes.FIELD_REALM_ANY);\n    }};\n    private RealmConfiguration realmConfig;\n\n    @Before\n    public void setUp() {\n        // Injecting the Instrumentation instance is required\n        // for your test to run with AndroidJUnitRunner.\n        context = InstrumentationRegistry.getInstrumentation().getContext();\n        realmConfig = configFactory.createConfiguration();\n        realm = Realm.getInstance(realmConfig);\n    }\n\n    @After\n    public void tearDown() {\n        if (realm != null) {\n            realm.close();\n        }\n    }\n\n    private void populateTestRealm(Realm realm, int objects) {\n        realm.beginTransaction();\n        realm.deleteAll();\n        for (int i = 0; i < objects; ++i) {\n            AllTypes allTypes = realm.createObject(AllTypes.class);\n            allTypes.setColumnBoolean((i % 3) == 0);\n            allTypes.setColumnBinary(new byte[] {1, 2, 3});\n            allTypes.setColumnDate(new Date());\n            allTypes.setColumnDouble(Math.PI);\n            allTypes.setColumnFloat(1.234567F + i);\n            allTypes.setColumnObjectId(new ObjectId(TestHelper.generateObjectIdHexString(i)));\n            allTypes.setColumnDecimal128(new Decimal128(new BigDecimal(i + \"12345\")));\n            allTypes.setColumnUUID(UUID.fromString(TestHelper.generateUUIDString(i)));\n            allTypes.setColumnRealmAny(RealmAny.valueOf(UUID.fromString(TestHelper.generateUUIDString(i))));\n\n            allTypes.setColumnString(\"test data \" + i);\n            allTypes.setColumnLong(i);\n            NonLatinFieldNames nonLatinFieldNames = realm.createObject(NonLatinFieldNames.class);\n            nonLatinFieldNames.set델타(i);\n            nonLatinFieldNames.setΔέλτα(i);\n            nonLatinFieldNames.set베타(1.234567F + i);\n            nonLatinFieldNames.setΒήτα(1.234567F + i);\n        }\n        realm.commitTransaction();\n    }\n\n    private void populateTestRealm() {\n        populateTestRealm(realm, TEST_DATA_SIZE);\n    }\n\n    @Test\n    public void getInstance_writeProtectedFile() throws IOException {\n        String REALM_FILE = \"readonly.realm\";\n        File folder = configFactory.getRoot();\n        File realmFile = new File(folder, REALM_FILE);\n        assertFalse(realmFile.exists());\n        assertTrue(realmFile.createNewFile());\n        assertTrue(realmFile.setWritable(false));\n\n        try {\n            Realm.getInstance(configFactory.createConfigurationBuilder()\n                    .directory(folder)\n                    .name(REALM_FILE)\n                    .build());\n            fail();\n        } catch (RealmFileException expected) {\n            assertEquals(RealmFileException.Kind.PERMISSION_DENIED, expected.getKind());\n        }\n    }\n\n    @Test\n    public void getInstance_writeProtectedFileWithContext() throws IOException {\n        String REALM_FILE = \"readonly.realm\";\n        File folder = configFactory.getRoot();\n        File realmFile = new File(folder, REALM_FILE);\n        assertFalse(realmFile.exists());\n        assertTrue(realmFile.createNewFile());\n        assertTrue(realmFile.setWritable(false));\n\n        try {\n            Realm.getInstance(configFactory.createConfigurationBuilder().directory(folder).name(REALM_FILE).build());\n            fail();\n        } catch (RealmFileException expected) {\n            assertEquals(RealmFileException.Kind.PERMISSION_DENIED, expected.getKind());\n        }\n    }\n\n    @Test\n    public void getInstance_twiceWhenRxJavaUnavailable() {\n        // Test for https://github.com/realm/realm-java/issues/2416\n\n        // Though it's not a recommended way to create multiple configuration instance with the same parameter, it's legal.\n        final RealmConfiguration configuration1 = configFactory.createConfiguration(\"no_RxJava.realm\");\n        TestHelper.emulateRxJavaUnavailable(configuration1);\n        final RealmConfiguration configuration2 = configFactory.createConfiguration(\"no_RxJava.realm\");\n        TestHelper.emulateRxJavaUnavailable(configuration2);\n\n        final Realm realm1 = Realm.getInstance(configuration1);\n        //noinspection TryFinallyCanBeTryWithResources\n        try {\n            final Realm realm2 = Realm.getInstance(configuration2);\n            realm2.close();\n        } finally {\n            realm1.close();\n        }\n    }\n\n    @Test\n    public void checkIfValid() {\n        // checkIfValid() must not throw any Exception against valid Realm instance.\n        realm.checkIfValid();\n\n        realm.close();\n        try {\n            realm.checkIfValid();\n            fail(\"closed Realm instance must throw IllegalStateException.\");\n        } catch (IllegalStateException ignored) {\n        }\n        realm = null;\n    }\n\n    @Test\n    public void getInstance() {\n        assertNotNull(\"Realm.getInstance unexpectedly returns null\", realm);\n        assertTrue(\"Realm.getInstance does not contain expected table\", realm.getSchema().contains(AllTypes.CLASS_NAME));\n    }\n\n    @Test\n    public void where() {\n        populateTestRealm();\n        RealmResults<AllTypes> resultList = realm.where(AllTypes.class).findAll();\n        assertEquals(TEST_DATA_SIZE, resultList.size());\n    }\n\n    @Test\n    public void where_throwsIfClassArgIsNotASubtype() {\n        try {\n            realm.where(RealmObject.class);\n            fail();\n        } catch (IllegalArgumentException ignore) {\n        }\n\n        try {\n            realm.where(RealmModel.class);\n            fail();\n        } catch (IllegalArgumentException ignore) {\n        }\n    }\n\n    // Note that this test is relying on the values set while initializing the test dataset\n    // TODO Move to RealmQueryTests?\n    @Test\n    public void where_queryResults() throws IOException {\n        populateTestRealm(realm, 159);\n        RealmResults<AllTypes> resultList = realm.where(AllTypes.class).equalTo(AllTypes.FIELD_LONG, 33).findAll();\n        assertEquals(1, resultList.size());\n\n        resultList = realm.where(AllTypes.class).equalTo(AllTypes.FIELD_LONG, 3333).findAll();\n        assertEquals(0, resultList.size());\n\n        resultList = realm.where(AllTypes.class).equalTo(AllTypes.FIELD_STRING, \"test data 0\").findAll();\n        assertEquals(1, resultList.size());\n\n        resultList = realm.where(AllTypes.class).equalTo(AllTypes.FIELD_STRING, \"test data 0\", Case.INSENSITIVE).findAll();\n        assertEquals(1, resultList.size());\n\n        resultList = realm.where(AllTypes.class).equalTo(AllTypes.FIELD_STRING, \"Test data 0\", Case.SENSITIVE).findAll();\n        assertEquals(0, resultList.size());\n    }\n\n    // TODO Move to RealmQueryTests?\n    @Test\n    public void where_equalTo_wrongFieldTypeAsInput() throws IOException {\n        populateTestRealm();\n\n        for (int i = 0; i < columnData.size(); i++) {\n            // Realm queries applies coercion on numerical values\n            boolean NON_NUMERICAL_COLUMN = (i > 4) && (i != 10);\n            // Realm queries applies coercion on objectid and date\n            boolean NON_OBJECT_OR_DATE = ((i <= 4) || (i > 6)) && (i != 10);\n            // Realm queries applies coercion on string and binary\n            boolean NON_STRING_OR_BINARY = ((i <= 6) || (i > 8)) && (i != 10);\n\n\n            try {\n                realm.where(AllTypes.class).equalTo(columnData.get(i), 13.37D).findAll();\n                if (NON_NUMERICAL_COLUMN) {\n                    fail(\"Realm.where should fail with illegal argument\");\n                }\n            } catch (IllegalArgumentException ignored) {\n            }\n\n            try {\n                realm.where(AllTypes.class).equalTo(columnData.get(i), 13.3711F).findAll();\n                if (NON_NUMERICAL_COLUMN) {\n                    fail(\"Realm.where should fail with illegal argument\");\n                }\n            } catch (IllegalArgumentException ignored) {\n            }\n\n            try {\n                realm.where(AllTypes.class).equalTo(columnData.get(i), 1337).findAll();\n                if (NON_NUMERICAL_COLUMN) {\n                    fail(\"Realm.where should fail with illegal argument\");\n                }\n            } catch (IllegalArgumentException ignored) {\n            }\n\n            try {\n                realm.where(AllTypes.class).equalTo(columnData.get(i), new Decimal128(new BigDecimal(i + \"12345\"))).findAll();\n                if (NON_NUMERICAL_COLUMN) {\n                    fail(\"Realm.where should fail with illegal argument\");\n                }\n            } catch (IllegalArgumentException ignored) {\n            }\n\n            try {\n                realm.where(AllTypes.class).equalTo(columnData.get(i), true).findAll();\n                if (NON_NUMERICAL_COLUMN) {\n                    fail(\"Realm.where should fail with illegal argument\");\n                }\n            } catch (IllegalArgumentException ignored) {\n            }\n\n            try {\n                realm.where(AllTypes.class).equalTo(columnData.get(i), new Date()).findAll();\n                if (NON_OBJECT_OR_DATE) {\n                    fail(\"Realm.where should fail with illegal argument\");\n                }\n            } catch (IllegalArgumentException ignored) {\n            }\n\n            try {\n                realm.where(AllTypes.class).equalTo(columnData.get(i), new ObjectId(TestHelper.generateObjectIdHexString(i))).findAll();\n                if (NON_OBJECT_OR_DATE) {\n                    fail(\"Realm.where should fail with illegal argument\");\n                }\n            } catch (IllegalArgumentException ignored) {\n            }\n\n            try {\n                realm.where(AllTypes.class).equalTo(columnData.get(i), \"test\").findAll();\n                if (NON_STRING_OR_BINARY) {\n                    fail(\"Realm.where should fail with illegal argument\");\n                }\n            } catch (IllegalArgumentException ignored) {\n            }\n\n            try {\n                realm.where(AllTypes.class).equalTo(columnData.get(i), new byte[] {1, 2, 3}).findAll();\n                if (NON_STRING_OR_BINARY) {\n                    fail(\"Realm.where should fail with illegal argument\");\n                }\n            } catch (IllegalArgumentException ignored) {\n            }\n\n            try {\n                realm.where(AllTypes.class).equalTo(columnData.get(i), UUID.fromString(TestHelper.generateUUIDString(i))).findAll();\n                if ((i != 9) && (i != 10)) {\n                    fail(\"Realm.where should fail with illegal argument\");\n                }\n            } catch (IllegalArgumentException ignored) {\n            }\n        }\n    }\n\n    // TODO Move to RealmQueryTests?\n    @Test\n    public void where_equalTo_invalidFieldName() throws IOException {\n        try {\n            realm.where(AllTypes.class).equalTo(\"invalidcolumnname\", 33).findAll();\n            fail(\"Invalid field name\");\n        } catch (Exception ignored) {\n        }\n\n        try {\n            realm.where(AllTypes.class).equalTo(\"invalidcolumnname\", \"test\").findAll();\n            fail(\"Invalid field name\");\n        } catch (Exception ignored) {\n        }\n\n        try {\n            realm.where(AllTypes.class).equalTo(\"invalidcolumnname\", true).findAll();\n            fail(\"Invalid field name\");\n        } catch (Exception ignored) {\n        }\n\n        try {\n            realm.where(AllTypes.class).equalTo(\"invalidcolumnname\", Math.PI).findAll();\n            fail(\"Invalid field name\");\n        } catch (Exception ignored) {\n        }\n\n        try {\n            realm.where(AllTypes.class).equalTo(\"invalidcolumnname\", Math.PI).findAll();\n            fail(\"Invalid field name\");\n        } catch (Exception ignored) {\n        }\n    }\n\n    @Test\n    public void beginTransaction() throws IOException {\n        populateTestRealm();\n\n        realm.beginTransaction();\n        AllTypes allTypes = realm.createObject(AllTypes.class);\n        allTypes.setColumnFloat(3.14F);\n        allTypes.setColumnString(\"a unique string\");\n        realm.commitTransaction();\n\n        RealmResults<AllTypes> resultList = realm.where(AllTypes.class).findAll();\n        assertEquals(TEST_DATA_SIZE + 1, resultList.size());\n\n        resultList = realm.where(AllTypes.class).equalTo(AllTypes.FIELD_STRING, \"a unique string\").findAll();\n        assertEquals(1, resultList.size());\n        resultList = realm.where(AllTypes.class).equalTo(AllTypes.FIELD_FLOAT, 3.14F).findAll();\n        assertEquals(1, resultList.size());\n    }\n\n    @Test\n    public void nestedTransaction() {\n        realm.beginTransaction();\n        try {\n            realm.beginTransaction();\n            fail();\n        } catch (IllegalStateException e) {\n            assertTrue(e.getMessage().startsWith(\"The Realm is already in a write transaction\"));\n        }\n        realm.commitTransaction();\n    }\n\n    private enum Method {\n        METHOD_BEGIN,\n        METHOD_COMMIT,\n        METHOD_CANCEL,\n        METHOD_EXECUTE_TRANSACTION,\n        METHOD_EXECUTE_TRANSACTION_ASYNC,\n        METHOD_DELETE_TYPE,\n        METHOD_DELETE_ALL,\n        METHOD_CREATE_OBJECT,\n        METHOD_CREATE_OBJECT_WITH_PRIMARY_KEY,\n        METHOD_COPY_TO_REALM,\n        METHOD_COPY_TO_REALM_OR_UPDATE,\n        METHOD_CREATE_ALL_FROM_JSON,\n        METHOD_CREATE_OR_UPDATE_ALL_FROM_JSON,\n        METHOD_CREATE_FROM_JSON,\n        METHOD_CREATE_OR_UPDATE_FROM_JSON,\n        METHOD_INSERT_COLLECTION,\n        METHOD_INSERT_OBJECT,\n        METHOD_INSERT_OR_UPDATE_COLLECTION,\n        METHOD_INSERT_OR_UPDATE_OBJECT\n    }\n\n    // Calling methods on a wrong thread will fail.\n    private boolean runMethodOnWrongThread(final Method method) throws InterruptedException, ExecutionException {\n        if (method != Method.METHOD_BEGIN) {\n            realm.beginTransaction();\n            realm.createObject(Dog.class);\n        }\n        ExecutorService executorService = Executors.newSingleThreadExecutor();\n        Future<Boolean> future = executorService.submit(new Callable<Boolean>() {\n            @Override\n            public Boolean call() throws Exception {\n                try {\n                    switch (method) {\n                        case METHOD_BEGIN:\n                            realm.beginTransaction();\n                            break;\n                        case METHOD_COMMIT:\n                            realm.commitTransaction();\n                            break;\n                        case METHOD_CANCEL:\n                            realm.cancelTransaction();\n                            break;\n                        case METHOD_EXECUTE_TRANSACTION:\n                            realm.executeTransaction(realm -> fail());\n                            break;\n                        case METHOD_EXECUTE_TRANSACTION_ASYNC:\n                            realm.executeTransactionAsync(realm -> fail());\n                            break;\n                        case METHOD_DELETE_TYPE:\n                            realm.delete(AllTypes.class);\n                            break;\n                        case METHOD_DELETE_ALL:\n                            realm.deleteAll();\n                            break;\n                        case METHOD_CREATE_OBJECT:\n                            realm.createObject(AllTypes.class);\n                            break;\n                        case METHOD_CREATE_OBJECT_WITH_PRIMARY_KEY:\n                            realm.createObject(AllJavaTypes.class, 1L);\n                            break;\n                        case METHOD_COPY_TO_REALM:\n                            realm.copyToRealm(new AllTypes());\n                            break;\n                        case METHOD_COPY_TO_REALM_OR_UPDATE:\n                            realm.copyToRealm(new AllTypesPrimaryKey());\n                            break;\n                        case METHOD_CREATE_ALL_FROM_JSON:\n                            realm.createAllFromJson(AllTypes.class, \"[{}]\");\n                            break;\n                        case METHOD_CREATE_OR_UPDATE_ALL_FROM_JSON:\n                            realm.createOrUpdateAllFromJson(AllTypesPrimaryKey.class, \"[{\\\"columnLong\\\":1,\" +\n                                    \" \\\"columnBoolean\\\": true}]\");\n                            break;\n                        case METHOD_CREATE_FROM_JSON:\n                            realm.createObjectFromJson(AllTypes.class, \"{}\");\n                            break;\n                        case METHOD_CREATE_OR_UPDATE_FROM_JSON:\n                            realm.createOrUpdateObjectFromJson(AllTypesPrimaryKey.class, \"{\\\"columnLong\\\":1,\" +\n                                    \" \\\"columnBoolean\\\": true}\");\n                            break;\n                        case METHOD_INSERT_COLLECTION:\n                            realm.insert(Arrays.asList(new AllTypes(), new AllTypes()));\n                            break;\n                        case METHOD_INSERT_OBJECT:\n                            realm.insert(new AllTypes());\n                            break;\n                        case METHOD_INSERT_OR_UPDATE_COLLECTION:\n                            realm.insert(Arrays.asList(new AllTypesPrimaryKey(), new AllTypesPrimaryKey()));\n                            break;\n                        case METHOD_INSERT_OR_UPDATE_OBJECT:\n                            realm.insertOrUpdate(new AllTypesPrimaryKey());\n                            break;\n                    }\n                    return false;\n                } catch (IllegalStateException ignored) {\n                    return true;\n                } catch (RealmException jsonFailure) {\n                    // TODO: Eew. Reconsider how our JSON methods reports failure. See https://github.com/realm/realm-java/issues/1594\n                    return (jsonFailure.getMessage().equals(\"Could not map Json\"));\n                }\n            }\n        });\n\n        boolean result = future.get();\n        if (method != Method.METHOD_BEGIN) {\n            realm.cancelTransaction();\n        }\n        return result;\n    }\n\n    @Test\n    public void methodCalledOnWrongThread() throws ExecutionException, InterruptedException {\n        for (Method method : Method.values()) {\n            assertTrue(method.toString(), runMethodOnWrongThread(method));\n        }\n    }\n\n    // Calling methods on a wrong thread will fail.\n    private boolean runMethodOnClosedRealm(final Method method) throws InterruptedException, ExecutionException {\n        try {\n            switch (method) {\n                case METHOD_BEGIN:\n                    realm.beginTransaction();\n                    break;\n                case METHOD_COMMIT:\n                    realm.commitTransaction();\n                    break;\n                case METHOD_CANCEL:\n                    realm.cancelTransaction();\n                    break;\n                case METHOD_EXECUTE_TRANSACTION:\n                    realm.executeTransaction(realm -> fail());\n                    break;\n                case METHOD_EXECUTE_TRANSACTION_ASYNC:\n                    realm.executeTransactionAsync(realm -> fail());\n                    break;\n                case METHOD_DELETE_TYPE:\n                    realm.delete(AllTypes.class);\n                    break;\n                case METHOD_DELETE_ALL:\n                    realm.deleteAll();\n                    break;\n                case METHOD_CREATE_OBJECT:\n                    realm.createObject(AllTypes.class);\n                    break;\n                case METHOD_CREATE_OBJECT_WITH_PRIMARY_KEY:\n                    realm.createObject(AllJavaTypes.class, 1L);\n                    break;\n                case METHOD_COPY_TO_REALM:\n                    realm.copyToRealm(new AllTypes());\n                    break;\n                case METHOD_COPY_TO_REALM_OR_UPDATE:\n                    realm.copyToRealm(new AllTypesPrimaryKey());\n                    break;\n                case METHOD_CREATE_ALL_FROM_JSON:\n                    realm.createAllFromJson(AllTypes.class, \"[{}]\");\n                    break;\n                case METHOD_CREATE_OR_UPDATE_ALL_FROM_JSON:\n                    realm.createOrUpdateAllFromJson(AllTypesPrimaryKey.class, \"[{\\\"columnLong\\\":1,\" +\n                            \" \\\"columnBoolean\\\": true}]\");\n                    break;\n                case METHOD_CREATE_FROM_JSON:\n                    realm.createObjectFromJson(AllTypes.class, \"{}\");\n                    break;\n                case METHOD_CREATE_OR_UPDATE_FROM_JSON:\n                    realm.createOrUpdateObjectFromJson(AllTypesPrimaryKey.class, \"{\\\"columnLong\\\":1,\" +\n                            \" \\\"columnBoolean\\\": true}\");\n                    break;\n                case METHOD_INSERT_COLLECTION:\n                    realm.insert(Arrays.asList(new AllTypes(), new AllTypes()));\n                    break;\n                case METHOD_INSERT_OBJECT:\n                    realm.insert(new AllTypes());\n                    break;\n                case METHOD_INSERT_OR_UPDATE_COLLECTION:\n                    realm.insert(Arrays.asList(new AllTypesPrimaryKey(), new AllTypesPrimaryKey()));\n                    break;\n                case METHOD_INSERT_OR_UPDATE_OBJECT:\n                    realm.insertOrUpdate(new AllTypesPrimaryKey());\n                    break;\n            }\n            return false;\n        } catch (IllegalStateException ignored) {\n            return true;\n        } catch (RealmException jsonFailure) {\n            // TODO: Eew. Reconsider how our JSON methods reports failure. See https://github.com/realm/realm-java/issues/1594\n            return (jsonFailure.getMessage().equals(\"Could not map Json\"));\n        }\n    }\n\n    @Test\n    public void methodCalledOnClosedRealm() throws ExecutionException, InterruptedException {\n        realm.close();\n        for (Method method : Method.values()) {\n            assertTrue(method.toString(), runMethodOnClosedRealm(method));\n        }\n    }\n\n    @Test\n    public void commitTransaction() {\n        populateTestRealm();\n\n        realm.beginTransaction();\n        AllTypes allTypes = realm.createObject(AllTypes.class);\n        allTypes.setColumnBoolean(true);\n        realm.commitTransaction();\n\n        RealmResults<AllTypes> resultList = realm.where(AllTypes.class).findAll();\n        assertEquals(TEST_DATA_SIZE + 1, resultList.size());\n    }\n\n    @Test(expected = IllegalStateException.class)\n    public void commitTransaction_afterCancelTransaction() {\n        realm.beginTransaction();\n        realm.cancelTransaction();\n        realm.commitTransaction();\n    }\n\n    @Test(expected = IllegalStateException.class)\n    public void commitTransaction_twice() {\n        realm.beginTransaction();\n        realm.commitTransaction();\n        realm.commitTransaction();\n    }\n\n    @Test\n    public void cancelTransaction() {\n        populateTestRealm();\n\n        realm.beginTransaction();\n        realm.createObject(AllTypes.class);\n        realm.cancelTransaction();\n        assertEquals(TEST_DATA_SIZE, realm.where(AllTypes.class).count());\n\n        try {\n            realm.cancelTransaction();\n            fail();\n        } catch (IllegalStateException ignored) {\n        }\n    }\n\n    @Test\n    public void executeTransaction_null() {\n        OsSharedRealm.VersionID oldVersion = realm.sharedRealm.getVersionID();\n        try {\n            realm.executeTransaction(null);\n            fail(\"null transaction should throw\");\n        } catch (IllegalArgumentException ignored) {\n        }\n        OsSharedRealm.VersionID newVersion = realm.sharedRealm.getVersionID();\n        assertEquals(oldVersion, newVersion);\n    }\n\n    @Test\n    public void executeTransaction_success() {\n        assertEquals(0, realm.where(Owner.class).count());\n        realm.executeTransaction(new Realm.Transaction() {\n            @Override\n            public void execute(Realm realm) {\n                Owner owner = realm.createObject(Owner.class);\n                owner.setName(\"Owner\");\n            }\n        });\n        assertEquals(1, realm.where(Owner.class).count());\n    }\n\n    @Test\n    public void executeTransaction_canceled() {\n        final AtomicReference<RuntimeException> thrownException = new AtomicReference<RuntimeException>(null);\n\n        assertEquals(0, realm.where(Owner.class).count());\n        try {\n            realm.executeTransaction(new Realm.Transaction() {\n                @Override\n                public void execute(Realm realm) {\n                    Owner owner = realm.createObject(Owner.class);\n                    owner.setName(\"Owner\");\n                    thrownException.set(new RuntimeException(\"Boom\"));\n                    throw thrownException.get();\n                }\n            });\n        } catch (RuntimeException e) {\n            //noinspection ThrowableResultOfMethodCallIgnored\n            assertTrue(e == thrownException.get());\n        }\n        assertEquals(0, realm.where(Owner.class).count());\n    }\n\n    @Test\n    public void executeTransaction_cancelInsideClosureThrowsException() {\n        assertEquals(0, realm.where(Owner.class).count());\n        TestHelper.TestLogger testLogger = new TestHelper.TestLogger();\n        try {\n            RealmLog.add(testLogger);\n            realm.executeTransaction(new Realm.Transaction() {\n                @Override\n                public void execute(Realm realm) {\n                    Owner owner = realm.createObject(Owner.class);\n                    owner.setName(\"Owner\");\n                    realm.cancelTransaction();\n                    throw new RuntimeException(\"Boom\");\n                }\n            });\n        } catch (RuntimeException ignored) {\n            // Ensures that we pass a valuable error message to the logger for developers.\n            assertEquals(\"Could not cancel transaction, not currently in a transaction.\", testLogger.message);\n        } finally {\n            RealmLog.remove(testLogger);\n        }\n        assertEquals(0, realm.where(Owner.class).count());\n    }\n\n    @Test\n    @UiThreadTest\n    public void executeTransaction_mainThreadWritesAllowed() {\n        RealmConfiguration configuration = configFactory.createConfigurationBuilder()\n                .allowWritesOnUiThread(true)\n                .name(\"ui_realm\")\n                .build();\n\n        Realm uiRealm = Realm.getInstance(configuration);\n        uiRealm.executeTransaction(new Realm.Transaction() {\n            @Override\n            public void execute(Realm realm) {\n                realm.insert(new Dog(\"Snuffles\"));\n            }\n        });\n\n        RealmResults<Dog> results = uiRealm.where(Dog.class).equalTo(\"name\", \"Snuffles\").findAll();\n        assertEquals(1, results.size());\n        assertNotNull(results.first());\n        assertEquals(\"Snuffles\", Objects.requireNonNull(results.first()).getName());\n\n        uiRealm.close();\n    }\n\n    @Test\n    @UiThreadTest\n    public void executeTransaction_mainThreadWritesNotAllowed() {\n        RealmConfiguration configuration = configFactory.createConfigurationBuilder()\n                .allowWritesOnUiThread(false)\n                .name(\"ui_realm\")\n                .build();\n\n        // Try-with-resources\n        try (Realm uiRealm = Realm.getInstance(configuration)) {\n            uiRealm.executeTransaction(new Realm.Transaction() {\n                @Override\n                public void execute(Realm realm) {\n                    // no-op\n                }\n            });\n            fail(\"the call to executeTransaction should have failed, this line should not be reached.\");\n        } catch (RealmException e) {\n            assertTrue(Objects.requireNonNull(e.getMessage()).contains(\"allowWritesOnUiThread\"));\n        }\n    }\n\n    @Test\n    public void executeTransaction_runsOnNonUiThread() {\n        RealmConfiguration configuration = configFactory.createConfigurationBuilder()\n                .allowWritesOnUiThread(false)\n                .name(\"ui_realm\")\n                .build();\n\n        Realm uiRealm = Realm.getInstance(configuration);\n        uiRealm.executeTransaction(new Realm.Transaction() {\n            @Override\n            public void execute(Realm realm) {\n                // no-op\n            }\n        });\n\n        uiRealm.close();\n    }\n\n    @Test\n    public void delete_type() {\n        // ** Deletes non existing table should succeed.\n        realm.beginTransaction();\n        realm.delete(AllTypes.class);\n        realm.commitTransaction();\n\n        // ** Deletes existing class, but leaves other classes classes.\n\n        // Adds two classes.\n        populateTestRealm();\n        realm.beginTransaction();\n        Dog dog = realm.createObject(Dog.class);\n        dog.setName(\"Castro\");\n        realm.commitTransaction();\n        // Clears.\n        realm.beginTransaction();\n        realm.delete(Dog.class);\n        realm.commitTransaction();\n        // Checks one class is cleared but other class is still there.\n        RealmResults<AllTypes> resultListTypes = realm.where(AllTypes.class).findAll();\n        assertEquals(TEST_DATA_SIZE, resultListTypes.size());\n        RealmResults<Dog> resultListDogs = realm.where(Dog.class).findAll();\n        assertEquals(0, resultListDogs.size());\n\n        // ** delete() must throw outside a transaction.\n        try {\n            realm.delete(AllTypes.class);\n            fail(\"Expected exception\");\n        } catch (IllegalStateException ignored) {\n        }\n    }\n\n    private void createAndTestFilename(String language, String fileName) {\n        RealmConfiguration realmConfig = configFactory.createConfiguration(fileName);\n        Realm realm1 = Realm.getInstance(realmConfig);\n        realm1.beginTransaction();\n        Dog dog1 = realm1.createObject(Dog.class);\n        dog1.setName(\"Rex\");\n        realm1.commitTransaction();\n        realm1.close();\n\n        File file = new File(realmConfig.getPath());\n        assertTrue(language, file.exists());\n\n        Realm realm2 = Realm.getInstance(realmConfig);\n        Dog dog2 = realm2.where(Dog.class).findFirst();\n        assertEquals(language, \"Rex\", dog2.getName());\n        realm2.close();\n    }\n\n    // TODO Move to RealmConfigurationTests?\n    @Test\n    public void realmConfiguration_fileName() {\n        createAndTestFilename(\"American\", \"Washington\");\n        createAndTestFilename(\"Danish\", \"København\");\n        createAndTestFilename(\"Russian\", \"Москва\");\n        createAndTestFilename(\"Greek\", \"Αθήνα\");\n        createAndTestFilename(\"Chinese\", \"北京市\");\n        createAndTestFilename(\"Korean\", \"서울시\");\n        createAndTestFilename(\"Arabic\", \"الرياض\");\n        createAndTestFilename(\"India\", \"नई दिल्ली\");\n        createAndTestFilename(\"Japanese\", \"東京都\");\n    }\n\n    @Test\n    public void utf8Tests() {\n        realm.beginTransaction();\n        realm.delete(AllTypes.class);\n        realm.commitTransaction();\n\n        String file = \"assets/unicode_codepoints.csv\";\n        Scanner scanner = new Scanner(getClass().getClassLoader().getResourceAsStream(file), \"UTF-8\");\n        int i = 0;\n        String currentUnicode = null;\n        try {\n            realm.beginTransaction();\n            while (scanner.hasNextLine()) {\n                currentUnicode = scanner.nextLine();\n                char[] chars = Character.toChars(Integer.parseInt(currentUnicode, 16));\n                String codePoint = new String(chars);\n                AllTypes o = realm.createObject(AllTypes.class);\n                o.setColumnLong(i);\n                o.setColumnString(codePoint);\n\n                if (i > 1) {\n                    assertEquals(\"Codepoint: \" + i + \" / \" + currentUnicode, codePoint,\n                            o.getColumnString()); // codepoint 0 is NULL, ignore for now.\n                }\n                i++;\n            }\n            realm.commitTransaction();\n        } catch (Exception e) {\n            fail(\"Failure, Codepoint: \" + i + \" / \" + currentUnicode + \" \" + e.getMessage());\n        }\n    }\n\n    private List<String> getCharacterArray() {\n        List<String> chars_array = new ArrayList<String>();\n        String file = \"assets/unicode_codepoints.csv\";\n        Scanner scanner = new Scanner(getClass().getClassLoader().getResourceAsStream(file), \"UTF-8\");\n        int i = 0;\n        String currentUnicode = null;\n        try {\n            while (scanner.hasNextLine()) {\n                currentUnicode = scanner.nextLine();\n                char[] chars = Character.toChars(Integer.parseInt(currentUnicode, 16));\n                String codePoint = new String(chars);\n                chars_array.add(codePoint);\n                i++;\n            }\n        } catch (Exception e) {\n            fail(\"Failure, Codepoint: \" + i + \" / \" + currentUnicode + \" \" + e.getMessage());\n        }\n        return chars_array;\n    }\n\n    // The test writes and reads random Strings.\n    @Test\n    public void unicodeStrings() {\n        List<String> charsArray = getCharacterArray();\n        // Change seed value for new random values.\n        long seed = 20;\n        Random random = new Random(seed);\n\n        StringBuilder testChar = new StringBuilder();\n        realm.beginTransaction();\n        for (int i = 0; i < 1000; i++) {\n            testChar.setLength(0);\n            int length = random.nextInt(25);\n\n            for (int j = 0; j < length; j++) {\n                testChar.append(charsArray.get(random.nextInt(27261)));\n            }\n            StringOnly stringOnly = realm.createObject(StringOnly.class);\n\n            // tests setter\n            stringOnly.setChars(testChar.toString());\n\n            // tests getter\n            realm.where(StringOnly.class).findFirst().getChars();\n\n            realm.delete(StringOnly.class);\n        }\n        realm.cancelTransaction();\n    }\n\n    @Test\n    public void getInstance_referenceCounting() {\n        // At this point reference count should be one because of the setUp method.\n        try {\n            realm.where(AllTypes.class).count();\n        } catch (IllegalStateException e) {\n            fail();\n        }\n\n        // Makes sure the reference counter is per realm file.\n        RealmConfiguration anotherConfig = configFactory.createConfiguration(\"anotherRealm.realm\");\n        Realm.deleteRealm(anotherConfig);\n        Realm otherRealm = Realm.getInstance(anotherConfig);\n\n        // Raises the reference.\n        Realm realm = null;\n        try {\n            realm = Realm.getInstance(configFactory.createConfiguration());\n        } finally {\n            if (realm != null) { realm.close(); }\n        }\n\n        try {\n            // This should not fail because the reference is now 1.\n            if (realm != null) {\n                realm.where(AllTypes.class).count();\n            }\n        } catch (IllegalStateException e) {\n            fail();\n        }\n\n        this.realm.close();\n        try {\n            this.realm.where(AllTypes.class).count();\n            fail();\n        } catch (IllegalStateException ignored) {\n        }\n\n        try {\n            otherRealm.where(AllTypes.class).count();\n        } catch (IllegalStateException e) {\n            fail();\n        } finally {\n            otherRealm.close();\n        }\n\n        try {\n            otherRealm.where(AllTypes.class).count();\n            fail();\n        } catch (IllegalStateException ignored) {\n        }\n    }\n\n    @Test\n    public void getInstance_referenceCounting_doubleClose() {\n        realm.close();\n        realm.close(); // Counts down once too many. Counter is now potentially negative.\n        realm = Realm.getInstance(configFactory.createConfiguration());\n        realm.beginTransaction();\n        AllTypes allTypes = realm.createObject(AllTypes.class);\n        RealmResults<AllTypes> queryResult = realm.where(AllTypes.class).findAll();\n        assertEquals(allTypes, queryResult.get(0));\n        realm.commitTransaction();\n        realm.close(); // This might not close the Realm if the reference count is wrong.\n\n        // This should now fail due to the Realm being fully closed.\n        thrown.expect(IllegalStateException.class);\n        allTypes.getColumnString();\n    }\n\n    @Test\n    public void writeCopyTo() throws IOException {\n        RealmConfiguration configA = configFactory.createConfiguration(\"file1.realm\");\n        RealmConfiguration configB = configFactory.createConfiguration(\"file2.realm\");\n        Realm.deleteRealm(configA);\n        Realm.deleteRealm(configB);\n\n        Realm realm1 = null;\n        try {\n            realm1 = Realm.getInstance(configA);\n            realm1.beginTransaction();\n            AllTypes allTypes = realm1.createObject(AllTypes.class);\n            allTypes.setColumnString(\"Hello World\");\n            realm1.commitTransaction();\n\n            realm1.writeCopyTo(new File(configB.getPath()));\n        } finally {\n            if (realm1 != null) {\n                realm1.close();\n            }\n        }\n\n        // Copy is compacted i.e. smaller than original.\n        File file1 = new File(configA.getPath());\n        File file2 = new File(configB.getPath());\n        assertTrue(file1.length() >= file2.length());\n\n        Realm realm2 = null;\n        try {\n            // Contents is copied too.\n            realm2 = Realm.getInstance(configB);\n            RealmResults<AllTypes> results = realm2.where(AllTypes.class).findAll();\n            assertEquals(1, results.size());\n            assertEquals(\"Hello World\", results.first().getColumnString());\n        } finally {\n            if (realm2 != null) {\n                realm2.close();\n            }\n        }\n    }\n\n    @Test\n    public void compactRealm() {\n        final RealmConfiguration configuration = realm.getConfiguration();\n        realm.close();\n        realm = null;\n        assertTrue(Realm.compactRealm(configuration));\n        realm = Realm.getInstance(configuration);\n    }\n\n    @Test\n    public void compactRealm_failsIfOpen() {\n        assertFalse(Realm.compactRealm(realm.getConfiguration()));\n    }\n\n    @Test\n    public void compactRealm_encryptedEmptyRealm() {\n        RealmConfiguration realmConfig = configFactory.createConfiguration(\"enc.realm\", TestHelper.getRandomKey());\n        Realm realm = Realm.getInstance(realmConfig);\n        realm.close();\n        assertTrue(Realm.compactRealm(realmConfig));\n        realm = Realm.getInstance(realmConfig);\n        assertFalse(realm.isClosed());\n        assertTrue(realm.isEmpty());\n        realm.close();\n    }\n\n    @Test\n    public void compactRealm_encryptedPopulatedRealm() {\n        final int DATA_SIZE = 100;\n        RealmConfiguration realmConfig = configFactory.createConfiguration(\"enc.realm\", TestHelper.getRandomKey());\n        Realm realm = Realm.getInstance(realmConfig);\n\n        populateTestRealm(realm, DATA_SIZE);\n        realm.close();\n        assertTrue(Realm.compactRealm(realmConfig));\n        realm = Realm.getInstance(realmConfig);\n        assertFalse(realm.isClosed());\n        assertEquals(DATA_SIZE, realm.where(AllTypes.class).count());\n        realm.close();\n    }\n\n    @Test\n    public void compactRealm_emptyRealm() throws IOException {\n        final String REALM_NAME = \"test.realm\";\n        RealmConfiguration realmConfig = configFactory.createConfiguration(REALM_NAME);\n        Realm realm = Realm.getInstance(realmConfig);\n        realm.close();\n        long before = new File(realmConfig.getPath()).length();\n        assertTrue(Realm.compactRealm(realmConfig));\n        long after = new File(realmConfig.getPath()).length();\n        assertTrue(before >= after);\n    }\n\n    @Test\n    public void compactRealm_populatedRealm() throws IOException {\n        final String REALM_NAME = \"test.realm\";\n        RealmConfiguration realmConfig = configFactory.createConfiguration(REALM_NAME);\n        Realm realm = Realm.getInstance(realmConfig);\n        populateTestRealm(realm, 100);\n        realm.close();\n        long before = new File(realmConfig.getPath()).length();\n        assertTrue(Realm.compactRealm(realmConfig));\n        long after = new File(realmConfig.getPath()).length();\n        assertTrue(before >= after);\n    }\n\n    // This is only supported on API level 30 and below\n    @Test\n    public void compactRealm_onExternalStorage() {\n        final File externalFilesDir = context.getExternalFilesDir(null);\n        final RealmConfiguration config = configFactory.createConfigurationBuilder()\n                .directory(externalFilesDir)\n                .name(\"external.realm\")\n                .build();\n        Realm.deleteRealm(config);\n        Realm realm = Realm.getInstance(config);\n        realm.close();\n        assertTrue(Realm.compactRealm(config));\n        realm = Realm.getInstance(config);\n        realm.close();\n        Realm.deleteRealm(config);\n    }\n\n    private void populateTestRealmForCompact(Realm realm, int sizeInMB) {\n        byte[] oneMBData = new byte[1024 * 1024];\n        realm.beginTransaction();\n        for (int i = 0; i < sizeInMB; i++) {\n            realm.createObject(AllTypes.class).setColumnBinary(oneMBData);\n        }\n        realm.commitTransaction();\n    }\n\n    private Pair<Long, Long> populateTestRealmAndCompactOnLaunch(CompactOnLaunchCallback compactOnLaunch) {\n        return populateTestRealmAndCompactOnLaunch(compactOnLaunch, 1);\n    }\n\n    private Pair<Long, Long> populateTestRealmAndCompactOnLaunch(CompactOnLaunchCallback compactOnLaunch, int sizeInMB) {\n        final String REALM_NAME = \"test.realm\";\n        RealmConfiguration realmConfig = configFactory.createConfiguration(REALM_NAME);\n        Realm realm = Realm.getInstance(realmConfig);\n        populateTestRealmForCompact(realm, sizeInMB);\n        realm.beginTransaction();\n        realm.deleteAll();\n        realm.commitTransaction();\n        realm.close();\n        long before = new File(realmConfig.getPath()).length();\n        if (compactOnLaunch != null) {\n            realmConfig = configFactory.createConfigurationBuilder()\n                    .name(REALM_NAME)\n                    .compactOnLaunch(compactOnLaunch)\n                    .build();\n        } else {\n            realmConfig = configFactory.createConfigurationBuilder()\n                    .name(REALM_NAME)\n                    .compactOnLaunch()\n                    .build();\n        }\n        realm = Realm.getInstance(realmConfig);\n        realm.close();\n        long after = new File(realmConfig.getPath()).length();\n        return new Pair(before, after);\n    }\n\n    @Test\n    public void compactOnLaunch_shouldCompact() throws IOException {\n        Pair<Long, Long> results = populateTestRealmAndCompactOnLaunch(new CompactOnLaunchCallback() {\n            @Override\n            public boolean shouldCompact(long totalBytes, long usedBytes) {\n                assertTrue(totalBytes > usedBytes);\n                return true;\n            }\n        });\n        assertTrue(results.first > results.second);\n    }\n\n    @Test\n    public void compactOnLaunch_shouldNotCompact() throws IOException {\n        Pair<Long, Long> results = populateTestRealmAndCompactOnLaunch(new CompactOnLaunchCallback() {\n            @Override\n            public boolean shouldCompact(long totalBytes, long usedBytes) {\n                assertTrue(totalBytes > usedBytes);\n                return false;\n            }\n        });\n        assertEquals(results.first, results.second);\n    }\n\n    @Test\n    public void compactOnLaunch_multipleThread() throws IOException {\n        final String REALM_NAME = \"test.realm\";\n        final AtomicInteger compactOnLaunchCount = new AtomicInteger(0);\n\n        final RealmConfiguration realmConfig = configFactory.createConfigurationBuilder()\n                .name(REALM_NAME)\n                .compactOnLaunch(new CompactOnLaunchCallback() {\n                    @Override\n                    public boolean shouldCompact(long totalBytes, long usedBytes) {\n                        compactOnLaunchCount.incrementAndGet();\n                        return true;\n                    }\n                })\n                .build();\n        Realm realm = Realm.getInstance(realmConfig);\n        realm.close();\n        // WARNING: We need to init the schema first and close the Realm to make sure the relevant logic works in Object\n        // Store. See https://github.com/realm/realm-object-store/blob/master/src/shared_realm.cpp#L58\n        // Called once.\n        assertEquals(1, compactOnLaunchCount.get());\n\n        realm = Realm.getInstance(realmConfig);\n\n        assertEquals(2, compactOnLaunchCount.get());\n\n        Thread thread = new Thread(new Runnable() {\n            @Override\n            public void run() {\n                Realm bgRealm = Realm.getInstance(realmConfig);\n                bgRealm.close();\n                // compactOnLaunch should not be called anymore!\n                assertEquals(2, compactOnLaunchCount.get());\n            }\n        });\n        thread.start();\n\n        try {\n            thread.join();\n        } catch (InterruptedException e) {\n            fail();\n        }\n\n        realm.close();\n\n        assertEquals(2, compactOnLaunchCount.get());\n    }\n\n    @Test\n    public void compactOnLaunch_insufficientAmount() throws IOException {\n        Pair<Long, Long> results = populateTestRealmAndCompactOnLaunch(new CompactOnLaunchCallback() {\n            @Override\n            public boolean shouldCompact(long totalBytes, long usedBytes) {\n                final long thresholdSize = 50 * 1024 * 1024;\n                return (totalBytes > thresholdSize) && (((double) usedBytes / (double) totalBytes) < 0.5);\n            }\n        }, 1);\n        final long thresholdSize = 50 * 1024 * 1024;\n        assertTrue(results.first < thresholdSize);\n        assertEquals(results.first, results.second);\n    }\n\n    @Test\n    public void compactOnLaunch_throwsInTheCallback() {\n        final RuntimeException exception = new RuntimeException();\n        final RealmConfiguration realmConfig = configFactory.createConfigurationBuilder()\n                .name(\"compactThrowsTest\")\n                .compactOnLaunch(new CompactOnLaunchCallback() {\n                    @Override\n                    public boolean shouldCompact(long totalBytes, long usedBytes) {\n                        throw exception;\n                    }\n                })\n                .build();\n        Realm realm = null;\n        try {\n            realm = Realm.getInstance(realmConfig);\n            fail();\n        } catch (RuntimeException expected) {\n            assertSame(exception, expected);\n        } finally {\n            if (realm != null) {\n                realm.close();\n            }\n        }\n    }\n\n    @Test\n    public void defaultCompactOnLaunch() throws IOException {\n        Pair<Long, Long> results = populateTestRealmAndCompactOnLaunch(null, 50);\n        final long thresholdSize = 50 * 1024 * 1024;\n        assertTrue(results.first > thresholdSize);\n        assertTrue(results.first > results.second);\n    }\n\n    @Test\n    public void defaultCompactOnLaunch_onlyCallback() {\n        DefaultCompactOnLaunchCallback callback = new DefaultCompactOnLaunchCallback();\n        final long thresholdSize = 50 * 1024 * 1024;\n        final long big = thresholdSize + 1024;\n        assertFalse(callback.shouldCompact(big, (long) (big * 0.6)));\n        assertTrue(callback.shouldCompact(big, (long) (big * 0.3)));\n        final long small = thresholdSize - 1024;\n        assertFalse(callback.shouldCompact(small, (long) (small * 0.6)));\n        assertFalse(callback.shouldCompact(small, (long) (small * 0.3)));\n    }\n\n    @Test\n    public void defaultCompactOnLaunch_insufficientAmount() throws IOException {\n        Pair<Long, Long> results = populateTestRealmAndCompactOnLaunch(null, 1);\n        final long thresholdSize = 50 * 1024 * 1024;\n        assertTrue(results.first < thresholdSize);\n        assertEquals(results.first, results.second);\n    }\n\n    @Test\n    public void copyToRealm_null() {\n        realm.beginTransaction();\n        try {\n            realm.copyToRealm((AllTypes) null);\n            fail(\"Copying null objects into Realm should not be allowed\");\n        } catch (IllegalArgumentException ignored) {\n        } finally {\n            realm.cancelTransaction();\n        }\n    }\n\n    @Test\n    public void copyToRealm_managedObject() {\n        realm.beginTransaction();\n        AllTypes allTypes = realm.createObject(AllTypes.class);\n        allTypes.setColumnString(\"Test\");\n        realm.commitTransaction();\n\n        realm.beginTransaction();\n        AllTypes copiedAllTypes = realm.copyToRealm(allTypes);\n        realm.commitTransaction();\n\n        assertTrue(allTypes == copiedAllTypes);\n    }\n\n    @Test\n    public void copyToRealm_fromOtherRealm() {\n        realm.beginTransaction();\n        AllTypes allTypes = realm.createObject(AllTypes.class);\n        allTypes.setColumnString(\"Test\");\n        allTypes.setColumnDecimal128(new Decimal128(new BigDecimal(\"12345\")));\n        allTypes.setColumnObjectId(new ObjectId(TestHelper.randomObjectIdHexString()));\n        allTypes.setColumnUUID(UUID.randomUUID());\n        allTypes.setColumnRealmAny(RealmAny.valueOf(UUID.randomUUID()));\n        realm.commitTransaction();\n\n        RealmConfiguration realmConfig = configFactory.createConfiguration(\"other-realm\");\n        Realm otherRealm = Realm.getInstance(realmConfig);\n        otherRealm.beginTransaction();\n        AllTypes copiedAllTypes = otherRealm.copyToRealm(allTypes);\n        otherRealm.commitTransaction();\n\n        assertNotSame(allTypes, copiedAllTypes); // Same object in different Realms is not the same.\n        assertEquals(allTypes.getColumnString(), copiedAllTypes.getColumnString()); // But data is still the same.\n        otherRealm.close();\n    }\n\n    @Test\n    public void copyToRealm() {\n        Date date = new Date();\n        Dog dog = new Dog();\n        dog.setName(\"Fido\");\n        RealmList<Dog> list = new RealmList<Dog>();\n        list.add(dog);\n\n        AllTypes allTypes = new AllTypes();\n        allTypes.setColumnString(\"String\");\n        allTypes.setColumnLong(1L);\n        allTypes.setColumnFloat(1F);\n        allTypes.setColumnDouble(1D);\n        allTypes.setColumnBoolean(true);\n        allTypes.setColumnDate(date);\n        allTypes.setColumnBinary(new byte[] {1, 2, 3});\n        allTypes.setColumnDecimal128(new Decimal128(new BigDecimal(\"12345\")));\n        allTypes.setColumnObjectId(new ObjectId(TestHelper.generateObjectIdHexString(7)));\n        allTypes.setColumnUUID(UUID.fromString(TestHelper.generateUUIDString(7)));\n        allTypes.setColumnRealmAny(RealmAny.valueOf(UUID.fromString(TestHelper.generateUUIDString(6))));\n        allTypes.setColumnRealmObject(dog);\n        allTypes.setColumnRealmList(list);\n\n        allTypes.setColumnStringList(new RealmList<String>(\"1\"));\n        allTypes.setColumnBinaryList(new RealmList<byte[]>(new byte[] {1}));\n        allTypes.setColumnBooleanList(new RealmList<Boolean>(true));\n        allTypes.setColumnLongList(new RealmList<Long>(1L));\n        allTypes.setColumnDoubleList(new RealmList<Double>(1D));\n        allTypes.setColumnFloatList(new RealmList<Float>(1F));\n        allTypes.setColumnDateList(new RealmList<Date>(new Date(1L)));\n        allTypes.setColumnDecimal128List(new RealmList<Decimal128>(new Decimal128(new BigDecimal(\"54321\"))));\n        allTypes.setColumnObjectIdList(new RealmList<ObjectId>(new ObjectId(TestHelper.generateObjectIdHexString(5))));\n        allTypes.setColumnUUIDList(new RealmList<>(UUID.fromString(TestHelper.generateUUIDString(5))));\n        allTypes.setColumnRealmAnyList(new RealmList<>(RealmAny.valueOf(UUID.fromString(TestHelper.generateUUIDString(7)))));\n\n        realm.beginTransaction();\n        AllTypes realmTypes = realm.copyToRealm(allTypes);\n        realm.commitTransaction();\n\n        assertNotSame(allTypes, realmTypes); // Objects should not be considered equal.\n        assertEquals(allTypes.getColumnString(), realmTypes.getColumnString()); // But they contain the same data.\n        assertEquals(allTypes.getColumnLong(), realmTypes.getColumnLong());\n        assertEquals(allTypes.getColumnFloat(), realmTypes.getColumnFloat(), 0);\n        assertEquals(allTypes.getColumnDouble(), realmTypes.getColumnDouble(), 0);\n        assertEquals(allTypes.isColumnBoolean(), realmTypes.isColumnBoolean());\n        assertEquals(allTypes.getColumnDate(), realmTypes.getColumnDate());\n        assertArrayEquals(allTypes.getColumnBinary(), realmTypes.getColumnBinary());\n        assertEquals(allTypes.getColumnDecimal128(), realmTypes.getColumnDecimal128());\n        assertEquals(allTypes.getColumnObjectId(), realmTypes.getColumnObjectId());\n        assertEquals(allTypes.getColumnUUID(), realmTypes.getColumnUUID());\n        assertEquals(allTypes.getColumnRealmAny(), realmTypes.getColumnRealmAny());\n        assertEquals(allTypes.getColumnRealmObject().getName(), dog.getName());\n        assertEquals(list.size(), realmTypes.getColumnRealmList().size());\n        //noinspection ConstantConditions\n        assertEquals(list.get(0).getName(), realmTypes.getColumnRealmList().get(0).getName());\n        assertEquals(1, realmTypes.getColumnStringList().size());\n        assertEquals(\"1\", realmTypes.getColumnStringList().get(0));\n        assertEquals(1, realmTypes.getColumnBooleanList().size());\n        assertEquals(true, realmTypes.getColumnBooleanList().get(0));\n        assertEquals(1, realmTypes.getColumnBinaryList().size());\n        assertArrayEquals(new byte[] {1}, realmTypes.getColumnBinaryList().get(0));\n        assertEquals(1, realmTypes.getColumnLongList().size());\n        assertEquals((Long) 1L, realmTypes.getColumnLongList().get(0));\n        assertEquals(1, realmTypes.getColumnDoubleList().size());\n        assertEquals((Double) 1D, realmTypes.getColumnDoubleList().get(0));\n        assertEquals(1, realmTypes.getColumnFloatList().size());\n        assertEquals((Float) 1F, realmTypes.getColumnFloatList().get(0));\n        assertEquals(1, realmTypes.getColumnDateList().size());\n        assertEquals(new Date(1), realmTypes.getColumnDateList().get(0));\n\n        assertEquals(1, realmTypes.getColumnDecimal128List().size());\n        assertEquals(new Decimal128(new BigDecimal(\"54321\")), realmTypes.getColumnDecimal128List().get(0));\n\n        assertEquals(1, realmTypes.getColumnObjectIdList().size());\n        assertEquals(new ObjectId(TestHelper.generateObjectIdHexString(5)), realmTypes.getColumnObjectIdList().get(0));\n\n        assertEquals(1, realmTypes.getColumnUUIDList().size());\n        assertEquals(UUID.fromString(TestHelper.generateUUIDString(5)), realmTypes.getColumnUUIDList().get(0));\n\n        assertEquals(1, realmTypes.getColumnRealmAnyList().size());\n        assertEquals(RealmAny.valueOf(UUID.fromString(TestHelper.generateUUIDString(7))), realmTypes.getColumnRealmAnyList().get(0));\n    }\n\n    @Test\n    public void copyToRealm_cyclicObjectReferences() {\n        CyclicType oneCyclicType = new CyclicType();\n        oneCyclicType.setName(\"One\");\n        CyclicType anotherCyclicType = new CyclicType();\n        anotherCyclicType.setName(\"Two\");\n        oneCyclicType.setObject(anotherCyclicType);\n        anotherCyclicType.setObject(oneCyclicType);\n\n        realm.beginTransaction();\n        CyclicType realmObject = realm.copyToRealm(oneCyclicType);\n        realm.commitTransaction();\n\n        assertEquals(\"One\", realmObject.getName());\n        assertEquals(\"Two\", realmObject.getObject().getName());\n        assertEquals(2, realm.where(CyclicType.class).count());\n\n        // Tests copyToRealm overload that uses the Iterator.\n        // Makes sure we reuse the same graph cache Map to avoid duplicates.\n        realm.beginTransaction();\n        realm.deleteAll();\n        realm.commitTransaction();\n\n        assertEquals(0, realm.where(CyclicType.class).count());\n\n        realm.beginTransaction();\n        List<CyclicType> cyclicTypes = realm.copyToRealm(Arrays.asList(oneCyclicType, anotherCyclicType));\n        realm.commitTransaction();\n        assertEquals(2, cyclicTypes.size());\n        assertEquals(\"One\", cyclicTypes.get(0).getName());\n        assertEquals(\"Two\", cyclicTypes.get(1).getName());\n        assertEquals(2, realm.where(CyclicType.class).count());\n    }\n\n    @Test\n    public void copyToRealm_cyclicObjectReferencesWithPK() {\n        CyclicTypePrimaryKey oneCyclicType = new CyclicTypePrimaryKey(1, \"One\");\n        CyclicTypePrimaryKey anotherCyclicType = new CyclicTypePrimaryKey(2, \"Two\");\n        oneCyclicType.setObject(anotherCyclicType);\n        anotherCyclicType.setObject(oneCyclicType);\n\n        realm.beginTransaction();\n        CyclicTypePrimaryKey realmObject = realm.copyToRealm(oneCyclicType);\n        realm.commitTransaction();\n\n        assertEquals(\"One\", realmObject.getName());\n        assertEquals(\"Two\", realmObject.getObject().getName());\n        assertEquals(2, realm.where(CyclicTypePrimaryKey.class).count());\n\n        // Tests copyToRealm overload that uses the Iterator.\n        // Makes sure we reuse the same graph cache Map to avoid duplicates.\n        realm.beginTransaction();\n        realm.deleteAll();\n        realm.commitTransaction();\n\n        assertEquals(0, realm.where(CyclicTypePrimaryKey.class).count());\n\n        realm.beginTransaction();\n        List<CyclicTypePrimaryKey> cyclicTypes = realm.copyToRealm(Arrays.asList(oneCyclicType, anotherCyclicType));\n        realm.commitTransaction();\n        assertEquals(2, cyclicTypes.size());\n        assertEquals(\"One\", cyclicTypes.get(0).getName());\n        assertEquals(\"Two\", cyclicTypes.get(1).getName());\n        assertEquals(2, realm.where(CyclicTypePrimaryKey.class).count());\n    }\n\n    @Test\n    public void copyToRealm_cyclicListReferences() {\n        CyclicType oneCyclicType = new CyclicType();\n        oneCyclicType.setName(\"One\");\n        CyclicType anotherCyclicType = new CyclicType();\n        anotherCyclicType.setName(\"Two\");\n        oneCyclicType.setObjects(new RealmList<>(anotherCyclicType));\n        anotherCyclicType.setObjects(new RealmList<>(oneCyclicType));\n\n        realm.beginTransaction();\n        CyclicType realmObject = realm.copyToRealm(oneCyclicType);\n        realm.commitTransaction();\n\n        assertEquals(\"One\", realmObject.getName());\n        assertEquals(2, realm.where(CyclicType.class).count());\n    }\n\n    // Checks that if a field has a null value, it gets converted to the default value for that type.\n    @Test\n    public void copyToRealm_convertsNullToDefaultValue() {\n        realm.beginTransaction();\n        AllTypes realmTypes = realm.copyToRealm(new AllTypes());\n        realm.commitTransaction();\n\n        assertEquals(\"\", realmTypes.getColumnString());\n        assertEquals(new Date(0), realmTypes.getColumnDate());\n        assertArrayEquals(new byte[0], realmTypes.getColumnBinary());\n\n        assertNotNull(realmTypes.getColumnRealmList());\n        assertNotNull(realmTypes.getColumnStringList());\n        assertNotNull(realmTypes.getColumnBinaryList());\n        assertNotNull(realmTypes.getColumnBooleanList());\n        assertNotNull(realmTypes.getColumnLongList());\n        assertNotNull(realmTypes.getColumnDoubleList());\n        assertNotNull(realmTypes.getColumnFloatList());\n        assertNotNull(realmTypes.getColumnDateList());\n    }\n\n    // Check that using copyToRealm will set the primary key directly instead of first setting\n    // it to the default value (which can fail).\n    @Test\n    public void copyToRealm_primaryKeyIsSetDirectly() {\n        realm.beginTransaction();\n        realm.createObject(OwnerPrimaryKey.class, 0);\n        realm.copyToRealm(new OwnerPrimaryKey(1, \"Foo\"));\n        realm.commitTransaction();\n        assertEquals(2, realm.where(OwnerPrimaryKey.class).count());\n    }\n\n    @Test\n    public void copyToRealm_stringPrimaryKeyIsNull() {\n        final long SECONDARY_FIELD_VALUE = 34992142L;\n        TestHelper.addStringPrimaryKeyObjectToTestRealm(realm, (String) null, SECONDARY_FIELD_VALUE);\n\n        RealmResults<PrimaryKeyAsString> results = realm.where(PrimaryKeyAsString.class).findAll();\n        assertEquals(1, results.size());\n        assertEquals(null, results.first().getName());\n        assertEquals(SECONDARY_FIELD_VALUE, results.first().getId());\n    }\n\n    @Test\n    public void copyToRealm_boxedNumberPrimaryKeyIsNull() {\n        final String SECONDARY_FIELD_VALUE = \"nullNumberPrimaryKeyObj\";\n        final Class[] CLASSES = {PrimaryKeyAsBoxedByte.class, PrimaryKeyAsBoxedShort.class, PrimaryKeyAsBoxedInteger.class, PrimaryKeyAsBoxedLong.class};\n\n        TestHelper.addBytePrimaryKeyObjectToTestRealm(realm, (Byte) null, SECONDARY_FIELD_VALUE);\n        TestHelper.addShortPrimaryKeyObjectToTestRealm(realm, (Short) null, SECONDARY_FIELD_VALUE);\n        TestHelper.addIntegerPrimaryKeyObjectToTestRealm(realm, (Integer) null, SECONDARY_FIELD_VALUE);\n        TestHelper.addLongPrimaryKeyObjectToTestRealm(realm, (Long) null, SECONDARY_FIELD_VALUE);\n\n        for (Class clazz : CLASSES) {\n            RealmResults results = realm.where(clazz).findAll();\n            assertEquals(1, results.size());\n            assertEquals(null, ((NullPrimaryKey) results.first()).getId());\n            assertEquals(SECONDARY_FIELD_VALUE, ((NullPrimaryKey) results.first()).getName());\n        }\n    }\n\n    @Test\n    public void copyToRealm_duplicatedPrimaryKeyThrows() {\n        final String[] PRIMARY_KEY_TYPES = { \"String\", \"BoxedLong\", \"long\" };\n        for (String className : PRIMARY_KEY_TYPES) {\n            String expectedKey = null;\n            try {\n                realm.beginTransaction();\n                switch (className) {\n                    case \"String\": {\n                        expectedKey = \"foo\";\n                        PrimaryKeyAsString obj = new PrimaryKeyAsString(\"foo\");\n                        realm.copyToRealm(obj);\n                        realm.copyToRealm(obj);\n                        break;\n                    }\n                    case \"BoxedLong\": {\n                        expectedKey = Long.toString(Long.MIN_VALUE);\n                        PrimaryKeyAsBoxedLong obj = new PrimaryKeyAsBoxedLong(Long.MIN_VALUE, \"boxedlong\");\n                        realm.copyToRealm(obj);\n                        realm.copyToRealm(obj);\n                        break;\n                    }\n                    case \"long\":\n                        expectedKey = Long.toString(Long.MAX_VALUE);\n                        PrimaryKeyAsLong obj = new PrimaryKeyAsLong(Long.MAX_VALUE);\n                        realm.copyToRealm(obj);\n                        realm.copyToRealm(obj);\n                        break;\n                    default:\n                }\n                fail(\"Null value as primary key already exists, but wasn't detected correctly\");\n            } catch (RealmPrimaryKeyConstraintException expected) {\n                assertTrue(\"Exception message is: \" + expected.getMessage(),\n                        expected.getMessage().contains(\"with an existing primary key value '\"+ expectedKey +\"'\"));\n            } finally {\n                realm.cancelTransaction();\n            }\n        }\n    }\n\n    @Test\n    public void copyToRealm_duplicatedNullPrimaryKeyThrows() {\n        final String[] PRIMARY_KEY_TYPES = {\"String\", \"BoxedByte\", \"BoxedShort\", \"BoxedInteger\", \"BoxedLong\"};\n\n        TestHelper.addStringPrimaryKeyObjectToTestRealm(realm, (String) null, 0);\n        TestHelper.addBytePrimaryKeyObjectToTestRealm(realm, (Byte) null, (String) null);\n        TestHelper.addShortPrimaryKeyObjectToTestRealm(realm, (Short) null, (String) null);\n        TestHelper.addIntegerPrimaryKeyObjectToTestRealm(realm, (Integer) null, (String) null);\n        TestHelper.addLongPrimaryKeyObjectToTestRealm(realm, (Long) null, (String) null);\n\n        for (String className : PRIMARY_KEY_TYPES) {\n            try {\n                realm.beginTransaction();\n                switch (className) {\n                    case \"String\":\n                        realm.copyToRealm(new PrimaryKeyAsString());\n                        break;\n                    case \"BoxedByte\":\n                        realm.copyToRealm(new PrimaryKeyAsBoxedByte());\n                        break;\n                    case \"BoxedShort\":\n                        realm.copyToRealm(new PrimaryKeyAsBoxedShort());\n                        break;\n                    case \"BoxedInteger\":\n                        realm.copyToRealm(new PrimaryKeyAsBoxedInteger());\n                        break;\n                    case \"BoxedLong\":\n                        realm.copyToRealm(new PrimaryKeyAsBoxedLong());\n                        break;\n                    default:\n                }\n                fail(\"Null value as primary key already exists, but wasn't detected correctly\");\n            } catch (RealmPrimaryKeyConstraintException expected) {\n                assertTrue(\"Exception message is: \" + expected.getMessage(),\n                        expected.getMessage().contains(\"with an existing primary key value 'null'\"));\n            } finally {\n                realm.cancelTransaction();\n            }\n        }\n    }\n\n    @Test\n    public void copyToRealm_doNotCopyReferencedObjectIfManaged() {\n        realm.beginTransaction();\n\n        // Child object is managed by Realm.\n        CyclicTypePrimaryKey childObj = realm.createObject(CyclicTypePrimaryKey.class, 1);\n        childObj.setName(\"Child\");\n\n        // Parent object is an unmanaged object.\n        CyclicTypePrimaryKey parentObj = new CyclicTypePrimaryKey(2);\n        parentObj.setObject(childObj);\n\n        realm.copyToRealm(parentObj);\n        realm.commitTransaction();\n\n        assertEquals(2, realm.where(CyclicTypePrimaryKey.class).count());\n    }\n\n    @Test\n    public void copyToRealm_list() {\n        Dog dog1 = new Dog();\n        dog1.setName(\"Dog 1\");\n        Dog dog2 = new Dog();\n        dog2.setName(\"Dog 2\");\n        RealmList<Dog> list = new RealmList<Dog>();\n        list.addAll(Arrays.asList(dog1, dog2));\n\n        realm.beginTransaction();\n        List<Dog> copiedList = new ArrayList<Dog>(realm.copyToRealm(list));\n        realm.commitTransaction();\n\n        assertEquals(2, copiedList.size());\n        assertEquals(dog1.getName(), copiedList.get(0).getName());\n        assertEquals(dog2.getName(), copiedList.get(1).getName());\n    }\n\n    @Test\n    public void copyToRealm_objectInOtherThreadThrows() {\n        final CountDownLatch bgThreadDoneLatch = new CountDownLatch(1);\n\n        realm.beginTransaction();\n        final Dog dog = realm.createObject(Dog.class);\n        realm.commitTransaction();\n\n        new Thread(new Runnable() {\n            @Override\n            public void run() {\n                final Realm bgRealm = Realm.getInstance(realm.getConfiguration());\n                bgRealm.beginTransaction();\n                try {\n                    bgRealm.copyToRealm(dog);\n                    fail();\n                } catch (IllegalArgumentException expected) {\n                    assertEquals(\"Objects which belong to Realm instances in other threads cannot be copied into this\" +\n                                    \" Realm instance.\",\n                            expected.getMessage());\n                }\n                bgRealm.cancelTransaction();\n                bgRealm.close();\n                bgThreadDoneLatch.countDown();\n            }\n        }).start();\n\n        TestHelper.awaitOrFail(bgThreadDoneLatch);\n    }\n\n    @Test\n    public void copyToRealmOrUpdate_null() {\n        realm.beginTransaction();\n        thrown.expect(IllegalArgumentException.class);\n        realm.copyToRealmOrUpdate((AllTypes) null);\n    }\n\n    @Test\n    public void copyToRealmOrUpdate_stringPrimaryKeyFieldIsNull() {\n        final long SECONDARY_FIELD_VALUE = 2192841L;\n        final long SECONDARY_FIELD_UPDATED = 44887612L;\n        PrimaryKeyAsString nullPrimaryKeyObj = TestHelper.addStringPrimaryKeyObjectToTestRealm(realm, (String) null, SECONDARY_FIELD_VALUE);\n\n        RealmResults<PrimaryKeyAsString> result = realm.where(PrimaryKeyAsString.class).findAll();\n        assertEquals(1, result.size());\n        assertEquals(null, result.first().getName());\n        assertEquals(SECONDARY_FIELD_VALUE, result.first().getId());\n\n        // Updates objects.\n        realm.beginTransaction();\n        nullPrimaryKeyObj.setId(SECONDARY_FIELD_UPDATED);\n        realm.copyToRealmOrUpdate(nullPrimaryKeyObj);\n        realm.commitTransaction();\n\n        assertEquals(SECONDARY_FIELD_UPDATED, realm.where(PrimaryKeyAsString.class).findFirst().getId());\n    }\n\n    @Test\n    public void copyToRealmOrUpdate_boxedBytePrimaryKeyFieldIsNull() {\n        final String SECONDARY_FIELD_VALUE = \"nullBytePrimaryKeyObj\";\n        final String SECONDARY_FIELD_UPDATED = \"nullBytePrimaryKeyObjUpdated\";\n        PrimaryKeyAsBoxedByte nullPrimaryKeyObj = TestHelper.addBytePrimaryKeyObjectToTestRealm(realm, (Byte) null, SECONDARY_FIELD_VALUE);\n\n        RealmResults<PrimaryKeyAsBoxedByte> result = realm.where(PrimaryKeyAsBoxedByte.class).findAll();\n        assertEquals(1, result.size());\n        assertEquals(SECONDARY_FIELD_VALUE, result.first().getName());\n        assertEquals(null, result.first().getId());\n\n        // Updates objects.\n        realm.beginTransaction();\n        nullPrimaryKeyObj.setName(SECONDARY_FIELD_UPDATED);\n        realm.copyToRealmOrUpdate(nullPrimaryKeyObj);\n        realm.commitTransaction();\n\n        assertEquals(SECONDARY_FIELD_UPDATED, realm.where(PrimaryKeyAsBoxedByte.class).findFirst().getName());\n    }\n\n    @Test\n    public void copyToRealmOrUpdate_boxedShortPrimaryKeyFieldIsNull() {\n        final String SECONDARY_FIELD_VALUE = \"nullShortPrimaryKeyObj\";\n        final String SECONDARY_FIELD_UPDATED = \"nullShortPrimaryKeyObjUpdated\";\n        PrimaryKeyAsBoxedShort nullPrimaryKeyObj = TestHelper.addShortPrimaryKeyObjectToTestRealm(realm, (Short) null, SECONDARY_FIELD_VALUE);\n\n        RealmResults<PrimaryKeyAsBoxedShort> result = realm.where(PrimaryKeyAsBoxedShort.class).findAll();\n        assertEquals(1, result.size());\n        assertEquals(SECONDARY_FIELD_VALUE, result.first().getName());\n        assertEquals(null, result.first().getId());\n\n        // Updates objects.\n        realm.beginTransaction();\n        nullPrimaryKeyObj.setName(SECONDARY_FIELD_UPDATED);\n        realm.copyToRealmOrUpdate(nullPrimaryKeyObj);\n        realm.commitTransaction();\n\n        assertEquals(SECONDARY_FIELD_UPDATED, realm.where(PrimaryKeyAsBoxedShort.class).findFirst().getName());\n    }\n\n    @Test\n    public void copyToRealmOrUpdate_boxedIntegerPrimaryKeyFieldIsNull() {\n        final String SECONDARY_FIELD_VALUE = \"nullIntegerPrimaryKeyObj\";\n        final String SECONDARY_FIELD_UPDATED = \"nullIntegerPrimaryKeyObjUpdated\";\n        PrimaryKeyAsBoxedInteger nullPrimaryKeyObj = TestHelper.addIntegerPrimaryKeyObjectToTestRealm(realm, (Integer) null, SECONDARY_FIELD_VALUE);\n\n        RealmResults<PrimaryKeyAsBoxedInteger> result = realm.where(PrimaryKeyAsBoxedInteger.class).findAll();\n        assertEquals(1, result.size());\n        assertEquals(SECONDARY_FIELD_VALUE, result.first().getName());\n        assertEquals(null, result.first().getId());\n\n        // Updates objects.\n        realm.beginTransaction();\n        nullPrimaryKeyObj.setName(SECONDARY_FIELD_UPDATED);\n        realm.copyToRealmOrUpdate(nullPrimaryKeyObj);\n        realm.commitTransaction();\n\n        assertEquals(SECONDARY_FIELD_UPDATED, realm.where(PrimaryKeyAsBoxedInteger.class).findFirst().getName());\n    }\n\n    @Test\n    public void copyToRealmOrUpdate_boxedLongPrimaryKeyFieldIsNull() {\n        final String SECONDARY_FIELD_VALUE = \"nullLongPrimaryKeyObj\";\n        final String SECONDARY_FIELD_UPDATED = \"nullLongPrimaryKeyObjUpdated\";\n        PrimaryKeyAsBoxedLong nullPrimaryKeyObj = TestHelper.addLongPrimaryKeyObjectToTestRealm(realm, (Long) null, SECONDARY_FIELD_VALUE);\n\n        RealmResults<PrimaryKeyAsBoxedLong> result = realm.where(PrimaryKeyAsBoxedLong.class).findAll();\n        assertEquals(1, result.size());\n        assertEquals(SECONDARY_FIELD_VALUE, result.first().getName());\n        assertEquals(null, result.first().getId());\n\n        // Updates objects.\n        realm.beginTransaction();\n        nullPrimaryKeyObj.setName(SECONDARY_FIELD_UPDATED);\n        realm.copyToRealmOrUpdate(nullPrimaryKeyObj);\n        realm.commitTransaction();\n\n        assertEquals(SECONDARY_FIELD_UPDATED, realm.where(PrimaryKeyAsBoxedLong.class).findFirst().getName());\n    }\n\n    @Test\n    public void copyToRealmOrUpdate_noPrimaryKeyField() {\n        realm.beginTransaction();\n        thrown.expect(IllegalArgumentException.class);\n        realm.copyToRealmOrUpdate(new AllTypes());\n    }\n\n    @Test\n    public void copyToRealmOrUpdate_addNewObjects() {\n        realm.executeTransaction(new Realm.Transaction() {\n            @Override\n            public void execute(Realm realm) {\n                PrimaryKeyAsLong obj = new PrimaryKeyAsLong();\n                obj.setId(1);\n                obj.setName(\"Foo\");\n                realm.copyToRealm(obj);\n\n                PrimaryKeyAsLong obj2 = new PrimaryKeyAsLong();\n                obj2.setId(2);\n                obj2.setName(\"Bar\");\n                realm.copyToRealmOrUpdate(obj2);\n            }\n        });\n\n        assertEquals(2, realm.where(PrimaryKeyAsLong.class).count());\n    }\n\n    @Test\n    public void copyToRealmOrUpdate_updateExistingObject() {\n        realm.executeTransaction(new Realm.Transaction() {\n            @Override\n            public void execute(Realm realm) {\n                AllTypesPrimaryKey obj = new AllTypesPrimaryKey();\n                obj.setColumnString(\"Foo\");\n                obj.setColumnLong(1);\n                obj.setColumnFloat(1.23F);\n                obj.setColumnDouble(1.234D);\n                obj.setColumnBoolean(false);\n                obj.setColumnBinary(new byte[] {1, 2, 3});\n                obj.setColumnDate(new Date(1000));\n                obj.setColumnRealmObject(new DogPrimaryKey(1, \"Dog1\"));\n                obj.setColumnRealmList(new RealmList<DogPrimaryKey>(new DogPrimaryKey(2, \"Dog2\")));\n                obj.setColumnBoxedBoolean(true);\n                obj.setColumnStringList(new RealmList<>(\"1\"));\n                obj.setColumnBooleanList(new RealmList<>(false));\n                obj.setColumnBinaryList(new RealmList<>(new byte[] {1}));\n                obj.setColumnLongList(new RealmList<>(1L));\n                obj.setColumnDoubleList(new RealmList<>(1D));\n                obj.setColumnFloatList(new RealmList<>(1F));\n                obj.setColumnDateList(new RealmList<>(new Date(1L)));\n                realm.copyToRealm(obj);\n\n                AllTypesPrimaryKey obj2 = new AllTypesPrimaryKey();\n                obj2.setColumnString(\"Bar\");\n                obj2.setColumnLong(1);\n                obj2.setColumnFloat(2.23F);\n                obj2.setColumnDouble(2.234D);\n                obj2.setColumnBoolean(true);\n                obj2.setColumnBinary(new byte[] {2, 3, 4});\n                obj2.setColumnDate(new Date(2000));\n                obj2.setColumnRealmObject(new DogPrimaryKey(3, \"Dog3\"));\n                obj2.setColumnRealmList(new RealmList<DogPrimaryKey>(new DogPrimaryKey(4, \"Dog4\")));\n                obj2.setColumnBoxedBoolean(false);\n                obj2.setColumnStringList(new RealmList<>(\"2\", \"3\"));\n                obj2.setColumnBooleanList(new RealmList<>(true, false));\n                obj2.setColumnBinaryList(new RealmList<>(new byte[] {2}, new byte[] {3}));\n                obj2.setColumnLongList(new RealmList<>(2L, 3L));\n                obj2.setColumnDoubleList(new RealmList<>(2D, 3D));\n                obj2.setColumnFloatList(new RealmList<>(2F, 3F));\n                obj2.setColumnDateList(new RealmList<>(new Date(2L), new Date(3L)));\n                realm.copyToRealmOrUpdate(obj2);\n            }\n        });\n\n        assertEquals(1, realm.where(AllTypesPrimaryKey.class).count());\n        AllTypesPrimaryKey obj = realm.where(AllTypesPrimaryKey.class).findFirst();\n\n        // Checks that the the only element has all its properties updated.\n        assertEquals(\"Bar\", obj.getColumnString());\n        assertEquals(1, obj.getColumnLong());\n        assertEquals(2.23F, obj.getColumnFloat(), 0);\n        assertEquals(2.234D, obj.getColumnDouble(), 0);\n        assertEquals(true, obj.isColumnBoolean());\n        assertArrayEquals(new byte[] {2, 3, 4}, obj.getColumnBinary());\n        assertEquals(new Date(2000), obj.getColumnDate());\n        assertEquals(\"Dog3\", obj.getColumnRealmObject().getName());\n        assertEquals(1, obj.getColumnRealmList().size());\n        assertEquals(\"Dog4\", obj.getColumnRealmList().get(0).getName());\n        assertFalse(obj.getColumnBoxedBoolean());\n        assertEquals(2, obj.getColumnStringList().size());\n        assertEquals(\"2\", obj.getColumnStringList().get(0));\n        assertEquals(\"3\", obj.getColumnStringList().get(1));\n        assertEquals(2, obj.getColumnBooleanList().size());\n        assertEquals(true, obj.getColumnBooleanList().get(0));\n        assertEquals(false, obj.getColumnBooleanList().get(1));\n        assertEquals(2, obj.getColumnBinaryList().size());\n        assertArrayEquals(new byte[] {2}, obj.getColumnBinaryList().get(0));\n        assertArrayEquals(new byte[] {3}, obj.getColumnBinaryList().get(1));\n        assertEquals(2, obj.getColumnLongList().size());\n        assertEquals((Long) 2L, obj.getColumnLongList().get(0));\n        assertEquals((Long) 3L, obj.getColumnLongList().get(1));\n        assertEquals(2, obj.getColumnDoubleList().size());\n        assertEquals((Double) 2D, obj.getColumnDoubleList().get(0));\n        assertEquals((Double) 3D, obj.getColumnDoubleList().get(1));\n        assertEquals(2, obj.getColumnFloatList().size());\n        assertEquals((Float) 2F, obj.getColumnFloatList().get(0));\n        assertEquals((Float) 3F, obj.getColumnFloatList().get(1));\n        assertEquals(2, obj.getColumnDateList().size());\n        assertEquals(new Date(2L), obj.getColumnDateList().get(0));\n        assertEquals(new Date(3L), obj.getColumnDateList().get(1));\n    }\n\n    @Test\n    public void copyToRealmOrUpdate_overrideOwnList() {\n        realm.beginTransaction();\n        AllJavaTypes managedObj = realm.createObject(AllJavaTypes.class, 1);\n        managedObj.getFieldList().add(managedObj);\n        AllJavaTypes unmanagedObj = realm.copyFromRealm(managedObj);\n        unmanagedObj.setFieldList(managedObj.getFieldList());\n\n        managedObj = realm.copyToRealmOrUpdate(unmanagedObj);\n        assertEquals(1, managedObj.getFieldList().size());\n        assertEquals(1, managedObj.getFieldList().first().getFieldId());\n    }\n\n    @Test\n    public void copyToRealmOrUpdate_cyclicObject() {\n        CyclicTypePrimaryKey oneCyclicType = new CyclicTypePrimaryKey(1);\n        oneCyclicType.setName(\"One\");\n        CyclicTypePrimaryKey anotherCyclicType = new CyclicTypePrimaryKey(2);\n        anotherCyclicType.setName(\"Two\");\n        oneCyclicType.setObject(anotherCyclicType);\n        anotherCyclicType.setObject(oneCyclicType);\n\n        realm.beginTransaction();\n        realm.copyToRealm(oneCyclicType);\n        realm.commitTransaction();\n\n        oneCyclicType.setName(\"Three\");\n        anotherCyclicType.setName(\"Four\");\n        realm.beginTransaction();\n        realm.copyToRealmOrUpdate(oneCyclicType);\n        realm.commitTransaction();\n\n        assertEquals(2, realm.where(CyclicTypePrimaryKey.class).count());\n        assertEquals(\"Three\", realm.where(CyclicTypePrimaryKey.class).equalTo(\"id\", 1).findFirst().getName());\n    }\n\n\n    // Checks that an unmanaged object with only default values can override data.\n    @Test\n    public void copyToRealmOrUpdate_defaultValuesOverrideExistingData() {\n        realm.executeTransaction(new Realm.Transaction() {\n            @Override\n            public void execute(Realm realm) {\n                AllTypesPrimaryKey obj = new AllTypesPrimaryKey();\n                obj.setColumnString(\"Foo\");\n                obj.setColumnLong(1);\n                obj.setColumnFloat(1.23F);\n                obj.setColumnDouble(1.234D);\n                obj.setColumnBoolean(false);\n                obj.setColumnBinary(new byte[] {1, 2, 3});\n                obj.setColumnDate(new Date(1000));\n                obj.setColumnRealmObject(new DogPrimaryKey(1, \"Dog1\"));\n                obj.setColumnRealmList(new RealmList<DogPrimaryKey>(new DogPrimaryKey(2, \"Dog2\")));\n                realm.copyToRealm(obj);\n\n                AllTypesPrimaryKey obj2 = new AllTypesPrimaryKey();\n                obj2.setColumnLong(1);\n                realm.copyToRealmOrUpdate(obj2);\n            }\n        });\n\n        assertEquals(1, realm.where(AllTypesPrimaryKey.class).count());\n\n        AllTypesPrimaryKey obj = realm.where(AllTypesPrimaryKey.class).findFirst();\n        assertNull(obj.getColumnString());\n        assertEquals(1, obj.getColumnLong());\n        assertEquals(0.0F, obj.getColumnFloat(), 0);\n        assertEquals(0.0D, obj.getColumnDouble(), 0);\n        assertEquals(false, obj.isColumnBoolean());\n        assertNull(obj.getColumnBinary());\n        assertNull(obj.getColumnDate());\n        assertNull(obj.getColumnRealmObject());\n        assertEquals(0, obj.getColumnRealmList().size());\n    }\n\n\n    // Tests that if references to objects are removed, the objects are still in the Realm.\n    @Test\n    public void copyToRealmOrUpdate_referencesNotDeleted() {\n        realm.executeTransaction(new Realm.Transaction() {\n            @Override\n            public void execute(Realm realm) {\n                AllTypesPrimaryKey obj = new AllTypesPrimaryKey();\n                obj.setColumnLong(1);\n                obj.setColumnRealmObject(new DogPrimaryKey(1, \"Dog1\"));\n                obj.setColumnRealmList(new RealmList<DogPrimaryKey>(new DogPrimaryKey(2, \"Dog2\")));\n                realm.copyToRealm(obj);\n\n                AllTypesPrimaryKey obj2 = new AllTypesPrimaryKey();\n                obj2.setColumnLong(1);\n                obj2.setColumnRealmObject(new DogPrimaryKey(3, \"Dog3\"));\n                obj2.setColumnRealmList(new RealmList<DogPrimaryKey>(new DogPrimaryKey(4, \"Dog4\")));\n                realm.copyToRealmOrUpdate(obj2);\n            }\n        });\n\n        assertEquals(1, realm.where(AllTypesPrimaryKey.class).count());\n        assertEquals(4, realm.where(DogPrimaryKey.class).count());\n    }\n\n    @Test\n    public void copyToRealmOrUpdate_primaryKeyMixInObjectGraph() {\n        // Crate Object graph where tier 2 consists of 1 object with primary key and one doesn't.\n        // Tier 3 both have objects with primary keys.\n        //\n        //        PK\n        //     /      \\\n        //    PK      nonPK\n        //    |        |\n        //    PK       PK\n        DogPrimaryKey dog = new DogPrimaryKey(1, \"Dog\");\n        OwnerPrimaryKey owner = new OwnerPrimaryKey(1, \"Owner\");\n        owner.setDog(dog);\n\n        Cat cat = new Cat();\n        cat.setScaredOfDog(dog);\n\n        PrimaryKeyMix mixObject = new PrimaryKeyMix(1);\n        mixObject.setDogOwner(owner);\n        mixObject.setCat(cat);\n\n        realm.beginTransaction();\n        PrimaryKeyMix realmObject = realm.copyToRealmOrUpdate(mixObject);\n        realm.commitTransaction();\n\n        assertEquals(\"Dog\", realmObject.getCat().getScaredOfDog().getName());\n        assertEquals(\"Dog\", realmObject.getDogOwner().getDog().getName());\n    }\n\n    @Test\n    public void copyToRealmOrUpdate_iterable() {\n        realm.executeTransaction(new Realm.Transaction() {\n            @Override\n            public void execute(Realm realm) {\n                PrimaryKeyAsLong obj = new PrimaryKeyAsLong();\n                obj.setId(1);\n                obj.setName(\"Foo\");\n                realm.copyToRealm(obj);\n\n                PrimaryKeyAsLong obj2 = new PrimaryKeyAsLong();\n                obj2.setId(1);\n                obj2.setName(\"Bar\");\n\n                PrimaryKeyAsLong obj3 = new PrimaryKeyAsLong();\n                obj3.setId(1);\n                obj3.setName(\"Baz\");\n\n                realm.copyToRealmOrUpdate(Arrays.asList(obj2, obj3));\n            }\n        });\n\n        assertEquals(1, realm.where(PrimaryKeyAsLong.class).count());\n        assertEquals(\"Baz\", realm.where(PrimaryKeyAsLong.class).findFirst().getName());\n    }\n\n    // Tests that a collection of objects with references all gets copied.\n    @Test\n    public void copyToRealmOrUpdate_iterableChildObjects() {\n        DogPrimaryKey dog = new DogPrimaryKey(1, \"Snoop\");\n\n        AllTypesPrimaryKey allTypes1 = new AllTypesPrimaryKey();\n        allTypes1.setColumnLong(1);\n        allTypes1.setColumnRealmObject(dog);\n\n        AllTypesPrimaryKey allTypes2 = new AllTypesPrimaryKey();\n        allTypes1.setColumnLong(2);\n        allTypes2.setColumnRealmObject(dog);\n\n        realm.beginTransaction();\n        realm.copyToRealmOrUpdate(Arrays.asList(allTypes1, allTypes2));\n        realm.commitTransaction();\n\n        assertEquals(2, realm.where(AllTypesPrimaryKey.class).count());\n        assertEquals(1, realm.where(DogPrimaryKey.class).count());\n    }\n\n    @Test\n    public void copyToRealmOrUpdate_objectInOtherThreadThrows() {\n        final CountDownLatch bgThreadDoneLatch = new CountDownLatch(1);\n\n        realm.beginTransaction();\n        final OwnerPrimaryKey ownerPrimaryKey = realm.createObject(OwnerPrimaryKey.class, 0);\n        realm.commitTransaction();\n\n        new Thread(new Runnable() {\n            @Override\n            public void run() {\n                final Realm bgRealm = Realm.getInstance(realm.getConfiguration());\n                bgRealm.beginTransaction();\n                try {\n                    bgRealm.copyToRealm(ownerPrimaryKey);\n                    fail();\n                } catch (IllegalArgumentException expected) {\n                    assertEquals(\"Objects which belong to Realm instances in other threads cannot be copied into this\" +\n                                    \" Realm instance.\",\n                            expected.getMessage());\n                }\n                bgRealm.cancelTransaction();\n                bgRealm.close();\n                bgThreadDoneLatch.countDown();\n            }\n        }).start();\n\n        TestHelper.awaitOrFail(bgThreadDoneLatch);\n    }\n\n    @Test\n    public void copyToRealmOrUpdate_listHasObjectInOtherThreadThrows() {\n        final CountDownLatch bgThreadDoneLatch = new CountDownLatch(1);\n        final OwnerPrimaryKey ownerPrimaryKey = new OwnerPrimaryKey();\n\n        realm.beginTransaction();\n        Dog dog = realm.createObject(Dog.class);\n        realm.commitTransaction();\n        ownerPrimaryKey.setDogs(new RealmList<Dog>(dog));\n\n        new Thread(new Runnable() {\n            @Override\n            public void run() {\n                final Realm bgRealm = Realm.getInstance(realm.getConfiguration());\n                bgRealm.beginTransaction();\n                try {\n                    bgRealm.copyToRealm(ownerPrimaryKey);\n                    fail();\n                } catch (IllegalArgumentException expected) {\n                    assertEquals(\"Objects which belong to Realm instances in other threads cannot be copied into this\" +\n                                    \" Realm instance.\",\n                            expected.getMessage());\n                }\n                bgRealm.cancelTransaction();\n                bgRealm.close();\n                bgThreadDoneLatch.countDown();\n            }\n        }).start();\n\n        TestHelper.awaitOrFail(bgThreadDoneLatch);\n    }\n\n    // Test to reproduce issue https://github.com/realm/realm-java/issues/4957\n    @Test\n    public void copyToRealmOrUpdate_bug4957() {\n        Object4957 listElement = new Object4957();\n        listElement.setId(1);\n\n        Object4957 parent = new Object4957();\n        parent.setId(0);\n        parent.getChildList().add(listElement);\n\n        // parentCopy has same fields as the parent does. But they are not the same object.\n        Object4957 parentCopy = new Object4957();\n        parentCopy.setId(0);\n        parentCopy.getChildList().add(listElement);\n\n        parent.setChild(parentCopy);\n        parentCopy.setChild(parentCopy);\n\n        realm.beginTransaction();\n        Object4957 managedParent = realm.copyToRealmOrUpdate(parent);\n        realm.commitTransaction();\n        // The original bug fails here. It resulted the listElement has been added to the list twice.\n        // Because of the parent and parentCopy are not the same object, proxy will miss the cache to know the object\n        // has been created before. But it does know they share the same PK value.\n        assertEquals(1, managedParent.getChildList().size());\n\n        // insertOrUpdate doesn't have the problem!\n        realm.beginTransaction();\n        realm.deleteAll();\n        realm.insertOrUpdate(parent);\n        realm.commitTransaction();\n        managedParent = realm.where(Object4957.class).findFirst();\n        assertEquals(1, managedParent.getChildList().size());\n    }\n\n    @Test\n    public void getInstance_differentEncryptionKeys() {\n        byte[] key1 = TestHelper.getRandomKey(42);\n        byte[] key2 = TestHelper.getRandomKey(42);\n\n        // Makes sure the key is the same, but in two different instances.\n        assertArrayEquals(key1, key2);\n        assertTrue(key1 != key2);\n\n        final String ENCRYPTED_REALM = \"differentKeys.realm\";\n        Realm realm1 = null;\n        Realm realm2 = null;\n        try {\n            realm1 = Realm.getInstance(configFactory.createConfiguration(ENCRYPTED_REALM, key1));\n            try {\n                realm2 = Realm.getInstance(configFactory.createConfiguration(ENCRYPTED_REALM, key2));\n            } catch (Exception e) {\n                fail(\"Unexpected exception: \" + e);\n            } finally {\n                if (realm2 != null) {\n                    realm2.close();\n                }\n            }\n        } finally {\n            if (realm1 != null) {\n                realm1.close();\n            }\n        }\n    }\n\n    @Test\n    public void writeEncryptedCopyTo() throws Exception {\n        populateTestRealm();\n        long before = realm.where(AllTypes.class).count();\n        assertEquals(TEST_DATA_SIZE, before);\n\n        // Configures test realms.\n        final String ENCRYPTED_REALM_FILE_NAME = \"encryptedTestRealm.realm\";\n        final String RE_ENCRYPTED_REALM_FILE_NAME = \"reEncryptedTestRealm.realm\";\n        final String DECRYPTED_REALM_FILE_NAME = \"decryptedTestRealm.realm\";\n\n        RealmConfiguration encryptedRealmConfig = configFactory.createConfiguration(ENCRYPTED_REALM_FILE_NAME,\n                TestHelper.getRandomKey());\n\n        RealmConfiguration reEncryptedRealmConfig = configFactory.createConfiguration(RE_ENCRYPTED_REALM_FILE_NAME,\n                TestHelper.getRandomKey());\n\n        RealmConfiguration decryptedRealmConfig = configFactory.createConfiguration(DECRYPTED_REALM_FILE_NAME);\n\n        // Writes encrypted copy from a unencrypted Realm.\n        File destination = new File(encryptedRealmConfig.getPath());\n        realm.writeEncryptedCopyTo(destination, encryptedRealmConfig.getEncryptionKey());\n\n        Realm encryptedRealm = null;\n        try {\n\n            // Verifies encrypted Realm and writes new encrypted copy with a new key.\n            encryptedRealm = Realm.getInstance(encryptedRealmConfig);\n            assertEquals(TEST_DATA_SIZE, encryptedRealm.where(AllTypes.class).count());\n\n            destination = new File(reEncryptedRealmConfig.getPath());\n            encryptedRealm.writeEncryptedCopyTo(destination, reEncryptedRealmConfig.getEncryptionKey());\n\n            // Verifies re-encrypted copy.\n            Realm reEncryptedRealm = null;\n            try {\n                reEncryptedRealm = Realm.getInstance(reEncryptedRealmConfig);\n                assertEquals(TEST_DATA_SIZE, reEncryptedRealm.where(AllTypes.class).count());\n            } finally {\n                if (reEncryptedRealm != null) {\n                    reEncryptedRealm.close();\n                    if (!Realm.deleteRealm(reEncryptedRealmConfig)) {\n                        fail();\n                    }\n                }\n            }\n\n            // Writes non-encrypted copy from the encrypted version.\n            destination = new File(decryptedRealmConfig.getPath());\n            encryptedRealm.writeEncryptedCopyTo(destination, null);\n\n            // Verifies decrypted Realm and cleans up.\n            Realm decryptedRealm = null;\n            try {\n                decryptedRealm = Realm.getInstance(decryptedRealmConfig);\n                assertEquals(TEST_DATA_SIZE, decryptedRealm.where(AllTypes.class).count());\n            } finally {\n                if (decryptedRealm != null) {\n                    decryptedRealm.close();\n                    if (!Realm.deleteRealm(decryptedRealmConfig)) {\n                        fail();\n                    }\n                }\n            }\n        } finally {\n            if (encryptedRealm != null) {\n                encryptedRealm.close();\n                if (!Realm.deleteRealm(encryptedRealmConfig)) {\n                    fail();\n                }\n            }\n        }\n    }\n\n    @Test\n    public void writeEncryptedCopyTo_wrongKeyLength() {\n        byte[] wrongLengthKey = new byte[42];\n        File destination = new File(configFactory.getRoot(), \"wrong_key.realm\");\n        thrown.expect(IllegalArgumentException.class);\n        realm.writeEncryptedCopyTo(destination, wrongLengthKey);\n    }\n\n    @Test\n    public void deleteRealm_failures() {\n        final String OTHER_REALM_NAME = \"yetAnotherRealm.realm\";\n\n        RealmConfiguration configA = configFactory.createConfiguration();\n        RealmConfiguration configB = configFactory.createConfiguration(OTHER_REALM_NAME);\n\n        // This instance is already cached because of the setUp() method so this deletion should throw.\n        try {\n            Realm.deleteRealm(configA);\n            fail();\n        } catch (IllegalStateException ignored) {\n        }\n\n        // Creates a new Realm file.\n        Realm yetAnotherRealm = Realm.getInstance(configB);\n\n        // Deleting it should fail.\n        try {\n            Realm.deleteRealm(configB);\n            fail();\n        } catch (IllegalStateException ignored) {\n        }\n\n        // But now that we close it deletion should work.\n        yetAnotherRealm.close();\n        try {\n            Realm.deleteRealm(configB);\n        } catch (Exception e) {\n            fail();\n        }\n    }\n\n    // TODO Does this test something meaningfull not tested elsewhere?\n    @Test\n    public void setter_updateField() throws Exception {\n        realm.beginTransaction();\n\n        // Creates an owner with two dogs.\n        OwnerPrimaryKey owner = realm.createObject(OwnerPrimaryKey.class, 1);\n        owner.setName(\"Jack\");\n        Dog rex = realm.createObject(Dog.class);\n        rex.setName(\"Rex\");\n        Dog fido = realm.createObject(Dog.class);\n        fido.setName(\"Fido\");\n        owner.getDogs().add(rex);\n        owner.getDogs().add(fido);\n        assertEquals(2, owner.getDogs().size());\n\n        // Changing the name of the owner should not affect the number of dogs.\n        owner.setName(\"Peter\");\n        assertEquals(2, owner.getDogs().size());\n\n        // Updating the user should not affect it either. This is actually a no-op since owner is a Realm backed object.\n        OwnerPrimaryKey owner2 = realm.copyToRealmOrUpdate(owner);\n        assertEquals(2, owner.getDogs().size());\n        assertEquals(2, owner2.getDogs().size());\n\n        realm.commitTransaction();\n    }\n\n    @Test\n    public void deleteRealm() throws InterruptedException {\n        File tempDir = new File(configFactory.getRoot(), \"delete_test_dir\");\n        File tempDirRenamed = new File(configFactory.getRoot(), \"delete_test_dir_2\");\n        assertTrue(tempDir.mkdir());\n\n        final RealmConfiguration configuration = configFactory.createConfigurationBuilder()\n                .directory(tempDir)\n                .build();\n\n        final CountDownLatch bgThreadReadyLatch = new CountDownLatch(1);\n        final CountDownLatch readyToCloseLatch = new CountDownLatch(1);\n        final CountDownLatch closedLatch = new CountDownLatch(1);\n\n        Realm realm = Realm.getInstance(configuration);\n        // Creates another Realm to ensure the log files are generated.\n        new Thread(new Runnable() {\n            @Override\n            public void run() {\n                Realm realm = Realm.getInstance(configuration);\n                bgThreadReadyLatch.countDown();\n                TestHelper.awaitOrFail(readyToCloseLatch);\n                realm.close();\n                closedLatch.countDown();\n            }\n        }).start();\n\n        realm.beginTransaction();\n        realm.createObject(AllTypes.class);\n        realm.commitTransaction();\n\n        // Waits for bg thread's opening the same Realm.\n        TestHelper.awaitOrFail(bgThreadReadyLatch);\n\n        // A core upgrade might change the location of the files\n        assertTrue(tempDir.renameTo(tempDirRenamed));\n        readyToCloseLatch.countDown();\n\n        realm.close();\n        TestHelper.awaitOrFail(closedLatch);\n        // Now we get log files back!\n        assertTrue(tempDirRenamed.renameTo(tempDir));\n\n        assertTrue(Realm.deleteRealm(configuration));\n\n        assertEquals(1, tempDir.listFiles().length);\n\n        // Lock file should never be deleted\n        File lockFile = new File(configuration.getPath() + \".lock\");\n        assertTrue(lockFile.exists());\n    }\n\n    // Tests that all methods that require a transaction. (ie. any function that mutates Realm data)\n    @Test\n    public void callMutableMethodOutsideTransaction() throws JSONException, IOException {\n\n        // Prepares unmanaged object data.\n        AllTypesPrimaryKey t = new AllTypesPrimaryKey();\n        List<AllTypesPrimaryKey> ts = Arrays.asList(t, t);\n\n        // Prepares JSON data.\n        String jsonObjStr = \"{ \\\"columnLong\\\" : 1 }\";\n        JSONObject jsonObj = new JSONObject(jsonObjStr);\n        InputStream jsonObjStream = TestHelper.stringToStream(jsonObjStr);\n        InputStream jsonObjStream2 = TestHelper.stringToStream(jsonObjStr);\n\n        String jsonArrStr = \" [{ \\\"columnLong\\\" : 1 }] \";\n        JSONArray jsonArr = new JSONArray(jsonArrStr);\n        InputStream jsonArrStream = TestHelper.stringToStream(jsonArrStr);\n        InputStream jsonArrStream2 = TestHelper.stringToStream(jsonArrStr);\n\n        // Tests all methods that should require a transaction.\n        try {\n            realm.createObject(AllTypes.class);\n            fail();\n        } catch (IllegalStateException expected) {}\n        try {\n            realm.copyToRealm(t);\n            fail();\n        } catch (IllegalStateException expected) {}\n        try {\n            realm.copyToRealm(ts);\n            fail();\n        } catch (IllegalStateException expected) {}\n        try {\n            realm.copyToRealmOrUpdate(t);\n            fail();\n        } catch (IllegalStateException expected) {}\n        try {\n            realm.copyToRealmOrUpdate(ts);\n            fail();\n        } catch (IllegalStateException expected) {}\n        try {\n            realm.delete(AllTypes.class);\n            fail();\n        } catch (IllegalStateException expected) {}\n        try {\n            realm.deleteAll();\n            fail();\n        } catch (IllegalStateException expected) {}\n\n        try {\n            realm.createObjectFromJson(AllTypesPrimaryKey.class, jsonObj);\n            fail();\n        } catch (IllegalStateException expected) {}\n        try {\n            realm.createObjectFromJson(AllTypesPrimaryKey.class, jsonObjStr);\n            fail();\n        } catch (IllegalStateException expected) {}\n        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {\n            try {\n                realm.createObjectFromJson(NoPrimaryKeyNullTypes.class, jsonObjStream);\n                fail();\n            } catch (IllegalStateException expected) {}\n        }\n        try {\n            realm.createOrUpdateObjectFromJson(AllTypesPrimaryKey.class, jsonObj);\n            fail();\n        } catch (IllegalStateException expected) {}\n        try {\n            realm.createOrUpdateObjectFromJson(AllTypesPrimaryKey.class, jsonObjStr);\n            fail();\n        } catch (IllegalStateException expected) {}\n        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {\n            try {\n                realm.createOrUpdateObjectFromJson(AllTypesPrimaryKey.class, jsonObjStream2);\n                fail();\n            } catch (IllegalStateException expected) {}\n        }\n\n        try {\n            realm.createAllFromJson(AllTypesPrimaryKey.class, jsonArr);\n            fail();\n        } catch (IllegalStateException expected) {}\n        try {\n            realm.createAllFromJson(AllTypesPrimaryKey.class, jsonArrStr);\n            fail();\n        } catch (IllegalStateException expected) {}\n        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {\n            try {\n                realm.createAllFromJson(NoPrimaryKeyNullTypes.class, jsonArrStream);\n                fail();\n            } catch (IllegalStateException expected) {}\n        }\n        try {\n            realm.createOrUpdateAllFromJson(AllTypesPrimaryKey.class, jsonArr);\n            fail();\n        } catch (IllegalStateException expected) {}\n        try {\n            realm.createOrUpdateAllFromJson(AllTypesPrimaryKey.class, jsonArrStr);\n            fail();\n        } catch (IllegalStateException expected) {}\n        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {\n            try {\n                realm.createOrUpdateAllFromJson(AllTypesPrimaryKey.class, jsonArrStream2);\n                fail();\n            } catch (IllegalStateException expected) {}\n        }\n    }\n\n    @Test\n    public void createObject_cannotCreateDynamicRealmObject() {\n        realm.beginTransaction();\n        try {\n            realm.createObject(DynamicRealmObject.class);\n            fail();\n        } catch (RealmException ignored) {\n        }\n    }\n\n    @Test(expected = RealmException.class)\n    public void createObject_absentPrimaryKeyThrows() {\n        realm.beginTransaction();\n        realm.createObject(DogPrimaryKey.class);\n    }\n\n    @Test\n    public void createObjectWithPrimaryKey() {\n        realm.beginTransaction();\n        AllJavaTypes obj = realm.createObject(AllJavaTypes.class, 42);\n        assertEquals(1, realm.where(AllJavaTypes.class).count());\n        assertEquals(42, obj.getFieldId());\n    }\n\n    @Test\n    public void createObjectWithPrimaryKey_noPrimaryKeyField() {\n        realm.beginTransaction();\n        try {\n            realm.createObject(AllTypes.class, 42);\n            fail();\n        } catch (IllegalStateException ignored) {\n        }\n    }\n\n    @Test\n    public void createObjectWithPrimaryKey_wrongValueType() {\n        realm.beginTransaction();\n        try {\n            realm.createObject(AllJavaTypes.class, \"fortyTwo\");\n            fail();\n        } catch (IllegalArgumentException ignored) {\n        }\n    }\n\n    @Test\n    public void createObjectWithPrimaryKey_valueAlreadyExists() {\n        realm.beginTransaction();\n        realm.createObject(AllJavaTypes.class, 42);\n        try {\n            realm.createObject(AllJavaTypes.class, 42);\n            fail();\n        } catch (RealmPrimaryKeyConstraintException ignored) {\n        }\n    }\n\n    @Test\n    public void createObjectWithPrimaryKey_null() {\n        // Byte\n        realm.beginTransaction();\n        PrimaryKeyAsBoxedByte primaryKeyAsBoxedByte = realm.createObject(PrimaryKeyAsBoxedByte.class, null);\n        realm.commitTransaction();\n        assertEquals(1, realm.where(PrimaryKeyAsBoxedByte.class).count());\n        assertNull(primaryKeyAsBoxedByte.getId());\n\n        // Short\n        realm.beginTransaction();\n        PrimaryKeyAsBoxedShort primaryKeyAsBoxedShort = realm.createObject(PrimaryKeyAsBoxedShort.class, null);\n        realm.commitTransaction();\n        assertEquals(1, realm.where(PrimaryKeyAsBoxedShort.class).count());\n        assertNull(primaryKeyAsBoxedShort.getId());\n\n        // Integer\n        realm.beginTransaction();\n        PrimaryKeyAsBoxedInteger primaryKeyAsBoxedInteger = realm.createObject(PrimaryKeyAsBoxedInteger.class, null);\n        realm.commitTransaction();\n        assertEquals(1, realm.where(PrimaryKeyAsBoxedInteger.class).count());\n        assertNull(primaryKeyAsBoxedInteger.getId());\n\n        // Long\n        realm.beginTransaction();\n        PrimaryKeyAsBoxedLong primaryKeyAsBoxedLong = realm.createObject(PrimaryKeyAsBoxedLong.class, null);\n        realm.commitTransaction();\n        assertEquals(1, realm.where(PrimaryKeyAsBoxedLong.class).count());\n        assertNull(primaryKeyAsBoxedLong.getId());\n\n        // String\n        realm.beginTransaction();\n        PrimaryKeyAsString primaryKeyAsString = realm.createObject(PrimaryKeyAsString.class, null);\n        realm.commitTransaction();\n        assertEquals(1, realm.where(PrimaryKeyAsString.class).count());\n        assertNull(primaryKeyAsString.getName());\n    }\n\n    @Test\n    public void createObjectWithPrimaryKey_nullOnRequired() {\n        realm.beginTransaction();\n\n        // Byte\n        try {\n            realm.createObject(PrimaryKeyRequiredAsBoxedByte.class, null);\n            fail();\n        } catch (IllegalArgumentException ignored) {\n        }\n\n        // Short\n        try {\n            realm.createObject(PrimaryKeyRequiredAsBoxedShort.class, null);\n            fail();\n        } catch (IllegalArgumentException ignored) {\n        }\n\n        // Integer\n        try {\n            realm.createObject(PrimaryKeyRequiredAsBoxedInteger.class, null);\n            fail();\n        } catch (IllegalArgumentException ignored) {\n        }\n\n        // Long\n        try {\n            realm.createObject(PrimaryKeyRequiredAsBoxedLong.class, null);\n            fail();\n        } catch (IllegalArgumentException ignored) {\n        }\n\n        // String\n        try {\n            realm.createObject(PrimaryKeyRequiredAsString.class, null);\n            fail();\n        } catch (IllegalArgumentException ignored) {\n        }\n\n        realm.cancelTransaction();\n    }\n\n    @Test\n    public void createObjectWithPrimaryKey_nullDuplicated() {\n        realm.beginTransaction();\n\n        // Byte\n        realm.createObject(PrimaryKeyAsBoxedByte.class, null);\n        try {\n            realm.createObject(PrimaryKeyAsBoxedByte.class, null);\n            fail();\n        } catch (RealmPrimaryKeyConstraintException ignored) {\n        }\n\n        // Short\n        realm.createObject(PrimaryKeyAsBoxedShort.class, null);\n        try {\n            realm.createObject(PrimaryKeyAsBoxedShort.class, null);\n            fail();\n        } catch (RealmPrimaryKeyConstraintException ignored) {\n        }\n\n        // Integer\n        realm.createObject(PrimaryKeyAsBoxedInteger.class, null);\n        try {\n            realm.createObject(PrimaryKeyAsBoxedInteger.class, null);\n            fail();\n        } catch (RealmPrimaryKeyConstraintException ignored) {\n        }\n\n        // Long\n        realm.createObject(PrimaryKeyAsBoxedLong.class, null);\n        try {\n            realm.createObject(PrimaryKeyAsBoxedLong.class, null);\n            fail();\n        } catch (RealmPrimaryKeyConstraintException ignored) {\n        }\n\n        // String\n        realm.createObject(PrimaryKeyAsString.class, null);\n        try {\n            realm.createObject(PrimaryKeyAsString.class, null);\n            fail();\n        } catch (RealmPrimaryKeyConstraintException ignored) {\n        }\n\n        realm.cancelTransaction();\n    }\n\n    @Test\n    public void createObject_defaultValueFromModelField() {\n        realm.executeTransaction(new Realm.Transaction() {\n            @Override\n            public void execute(Realm realm) {\n                // Creates a DefaultValueOfField with non-default primary key value.\n                realm.createObject(DefaultValueOfField.class,\n                        DefaultValueOfField.FIELD_LONG_PRIMARY_KEY_DEFAULT_VALUE * 3);\n            }\n        });\n        final String createdRandomString = DefaultValueOfField.lastRandomStringValue;\n\n        testOneObjectFound(realm, DefaultValueOfField.class,\n                DefaultValueOfField.FIELD_STRING,\n                DefaultValueOfField.FIELD_STRING_DEFAULT_VALUE);\n        testOneObjectFound(realm, DefaultValueOfField.class,\n                DefaultValueOfField.FIELD_RANDOM_STRING, createdRandomString);\n        testOneObjectFound(realm, DefaultValueOfField.class, DefaultValueOfField.FIELD_SHORT,\n                DefaultValueOfField.FIELD_SHORT_DEFAULT_VALUE);\n        testOneObjectFound(realm, DefaultValueOfField.class,\n                DefaultValueOfField.FIELD_INT,\n                DefaultValueOfField.FIELD_INT_DEFAULT_VALUE);\n        // Default value for pk must be ignored.\n        testNoObjectFound(realm, DefaultValueOfField.class,\n                DefaultValueOfField.FIELD_LONG_PRIMARY_KEY,\n                DefaultValueOfField.FIELD_LONG_PRIMARY_KEY_DEFAULT_VALUE);\n        testOneObjectFound(realm, DefaultValueOfField.class,\n                DefaultValueOfField.FIELD_LONG_PRIMARY_KEY,\n                DefaultValueOfField.FIELD_LONG_PRIMARY_KEY_DEFAULT_VALUE * 3);\n        testOneObjectFound(realm, DefaultValueOfField.class,\n                DefaultValueOfField.FIELD_LONG,\n                DefaultValueOfField.FIELD_LONG_DEFAULT_VALUE);\n        testOneObjectFound(realm, DefaultValueOfField.class,\n                DefaultValueOfField.FIELD_BYTE,\n                DefaultValueOfField.FIELD_BYTE_DEFAULT_VALUE);\n        testOneObjectFound(realm, DefaultValueOfField.class,\n                DefaultValueOfField.FIELD_FLOAT,\n                DefaultValueOfField.FIELD_FLOAT_DEFAULT_VALUE);\n        testOneObjectFound(realm, DefaultValueOfField.class,\n                DefaultValueOfField.FIELD_DOUBLE,\n                DefaultValueOfField.FIELD_DOUBLE_DEFAULT_VALUE);\n        testOneObjectFound(realm, DefaultValueOfField.class,\n                DefaultValueOfField.FIELD_BOOLEAN,\n                DefaultValueOfField.FIELD_BOOLEAN_DEFAULT_VALUE);\n        testOneObjectFound(realm, DefaultValueOfField.class,\n                DefaultValueOfField.FIELD_DATE,\n                DefaultValueOfField.FIELD_DATE_DEFAULT_VALUE);\n        testOneObjectFound(realm, DefaultValueOfField.class,\n                DefaultValueOfField.FIELD_BINARY,\n                DefaultValueOfField.FIELD_BINARY_DEFAULT_VALUE);\n        testOneObjectFound(realm, DefaultValueOfField.class,\n                DefaultValueOfField.FIELD_OBJECT + \".\" + RandomPrimaryKey.FIELD_INT,\n                RandomPrimaryKey.FIELD_INT_DEFAULT_VALUE);\n        testOneObjectFound(realm, DefaultValueOfField.class,\n                DefaultValueOfField.FIELD_LIST + \".\" + RandomPrimaryKey.FIELD_INT,\n                RandomPrimaryKey.FIELD_INT_DEFAULT_VALUE);\n    }\n\n    @Test\n    public void createObject_overwriteNullifiedLinkWithDefaultValue() {\n        final DefaultValueOverwriteNullLink created;\n        realm.beginTransaction();\n        created = realm.createObject(DefaultValueOverwriteNullLink.class);\n        realm.commitTransaction();\n\n        assertEquals(created.getExpectedKeyOfFieldObject(), created.getFieldObject().getFieldRandomPrimaryKey());\n    }\n\n    @Test\n    public void createObject_defaultValueFromModelConstructor() {\n        realm.executeTransaction(new Realm.Transaction() {\n            @Override\n            public void execute(Realm realm) {\n                // Creates a DefaultValueConstructor with non-default primary key value.\n                realm.createObject(DefaultValueConstructor.class,\n                        DefaultValueConstructor.FIELD_LONG_PRIMARY_KEY_DEFAULT_VALUE * 3);\n            }\n        });\n        final String createdRandomString = DefaultValueConstructor.lastRandomStringValue;\n\n        testOneObjectFound(realm, DefaultValueConstructor.class,\n                DefaultValueConstructor.FIELD_STRING,\n                DefaultValueConstructor.FIELD_STRING_DEFAULT_VALUE);\n        testOneObjectFound(realm, DefaultValueConstructor.class,\n                DefaultValueConstructor.FIELD_RANDOM_STRING,\n                createdRandomString);\n        testOneObjectFound(realm, DefaultValueConstructor.class,\n                DefaultValueConstructor.FIELD_SHORT,\n                DefaultValueConstructor.FIELD_SHORT_DEFAULT_VALUE);\n        testOneObjectFound(realm, DefaultValueConstructor.class,\n                DefaultValueConstructor.FIELD_INT,\n                DefaultValueConstructor.FIELD_INT_DEFAULT_VALUE);\n        // Default value for pk must be ignored.\n        testNoObjectFound(realm, DefaultValueConstructor.class,\n                DefaultValueConstructor.FIELD_LONG_PRIMARY_KEY,\n                DefaultValueConstructor.FIELD_LONG_PRIMARY_KEY_DEFAULT_VALUE);\n        testOneObjectFound(realm, DefaultValueConstructor.class,\n                DefaultValueConstructor.FIELD_LONG_PRIMARY_KEY,\n                DefaultValueConstructor.FIELD_LONG_PRIMARY_KEY_DEFAULT_VALUE * 3);\n        testOneObjectFound(realm, DefaultValueConstructor.class,\n                DefaultValueConstructor.FIELD_LONG,\n                DefaultValueConstructor.FIELD_LONG_DEFAULT_VALUE);\n        testOneObjectFound(realm, DefaultValueConstructor.class,\n                DefaultValueConstructor.FIELD_BYTE,\n                DefaultValueConstructor.FIELD_BYTE_DEFAULT_VALUE);\n        testOneObjectFound(realm, DefaultValueConstructor.class,\n                DefaultValueConstructor.FIELD_FLOAT,\n                DefaultValueConstructor.FIELD_FLOAT_DEFAULT_VALUE);\n        testOneObjectFound(realm, DefaultValueConstructor.class,\n                DefaultValueConstructor.FIELD_DOUBLE,\n                DefaultValueConstructor.FIELD_DOUBLE_DEFAULT_VALUE);\n        testOneObjectFound(realm, DefaultValueConstructor.class,\n                DefaultValueConstructor.FIELD_BOOLEAN,\n                DefaultValueConstructor.FIELD_BOOLEAN_DEFAULT_VALUE);\n        testOneObjectFound(realm, DefaultValueConstructor.class,\n                DefaultValueConstructor.FIELD_DATE, DefaultValueConstructor.FIELD_DATE_DEFAULT_VALUE);\n        testOneObjectFound(realm, DefaultValueConstructor.class,\n                DefaultValueConstructor.FIELD_BINARY,\n                DefaultValueConstructor.FIELD_BINARY_DEFAULT_VALUE);\n        testOneObjectFound(realm, DefaultValueConstructor.class,\n                DefaultValueConstructor.FIELD_OBJECT + \".\" + RandomPrimaryKey.FIELD_INT,\n                RandomPrimaryKey.FIELD_INT_DEFAULT_VALUE);\n        testOneObjectFound(realm, DefaultValueConstructor.class,\n                DefaultValueConstructor.FIELD_LIST + \".\" + RandomPrimaryKey.FIELD_INT,\n                RandomPrimaryKey.FIELD_INT_DEFAULT_VALUE);\n    }\n\n    @Test\n    public void createObject_defaultValueSetterInConstructor() {\n        realm.executeTransaction(new Realm.Transaction() {\n            @Override\n            public void execute(Realm realm) {\n                // Creates a DefaultValueSetter with non-default primary key value.\n                realm.createObject(DefaultValueSetter.class,\n                        DefaultValueSetter.FIELD_LONG_PRIMARY_KEY_DEFAULT_VALUE * 3);\n            }\n        });\n        final String createdRandomString = DefaultValueSetter.lastRandomStringValue;\n\n        testOneObjectFound(realm, DefaultValueSetter.class,\n                DefaultValueSetter.FIELD_STRING,\n                DefaultValueSetter.FIELD_STRING_DEFAULT_VALUE);\n        testOneObjectFound(realm, DefaultValueSetter.class,\n                DefaultValueSetter.FIELD_RANDOM_STRING,\n                createdRandomString);\n        testOneObjectFound(realm, DefaultValueSetter.class,\n                DefaultValueSetter.FIELD_SHORT,\n                DefaultValueSetter.FIELD_SHORT_DEFAULT_VALUE);\n        testOneObjectFound(realm, DefaultValueSetter.class,\n                DefaultValueSetter.FIELD_INT,\n                DefaultValueSetter.FIELD_INT_DEFAULT_VALUE);\n        // Default value for pk must be ignored.\n        testNoObjectFound(realm, DefaultValueSetter.class,\n                DefaultValueSetter.FIELD_LONG_PRIMARY_KEY,\n                DefaultValueSetter.FIELD_LONG_PRIMARY_KEY_DEFAULT_VALUE);\n        testOneObjectFound(realm, DefaultValueSetter.class,\n                DefaultValueSetter.FIELD_LONG_PRIMARY_KEY,\n                DefaultValueSetter.FIELD_LONG_PRIMARY_KEY_DEFAULT_VALUE * 3);\n        testOneObjectFound(realm, DefaultValueSetter.class,\n                DefaultValueSetter.FIELD_LONG,\n                DefaultValueSetter.FIELD_LONG_DEFAULT_VALUE);\n        testOneObjectFound(realm, DefaultValueSetter.class,\n                DefaultValueSetter.FIELD_BYTE,\n                DefaultValueSetter.FIELD_BYTE_DEFAULT_VALUE);\n        testOneObjectFound(realm, DefaultValueSetter.class,\n                DefaultValueSetter.FIELD_FLOAT,\n                DefaultValueSetter.FIELD_FLOAT_DEFAULT_VALUE);\n        testOneObjectFound(realm, DefaultValueSetter.class,\n                DefaultValueSetter.FIELD_DOUBLE,\n                DefaultValueSetter.FIELD_DOUBLE_DEFAULT_VALUE);\n        testOneObjectFound(realm, DefaultValueSetter.class,\n                DefaultValueSetter.FIELD_BOOLEAN,\n                DefaultValueSetter.FIELD_BOOLEAN_DEFAULT_VALUE);\n        testOneObjectFound(realm, DefaultValueSetter.class,\n                DefaultValueSetter.FIELD_DATE,\n                DefaultValueSetter.FIELD_DATE_DEFAULT_VALUE);\n        testOneObjectFound(realm, DefaultValueSetter.class,\n                DefaultValueSetter.FIELD_BINARY,\n                DefaultValueSetter.FIELD_BINARY_DEFAULT_VALUE);\n        testOneObjectFound(realm, DefaultValueSetter.class,\n                DefaultValueSetter.FIELD_OBJECT + \".\" + RandomPrimaryKey.FIELD_INT,\n                RandomPrimaryKey.FIELD_INT_DEFAULT_VALUE);\n        testOneObjectFound(realm, DefaultValueSetter.class,\n                DefaultValueSetter.FIELD_LIST + \".\" + RandomPrimaryKey.FIELD_INT,\n                RandomPrimaryKey.FIELD_INT_DEFAULT_VALUE);\n        testOneObjectFound(realm, DefaultValueSetter.class,\n                DefaultValueSetter.FIELD_LIST + \".\" + RandomPrimaryKey.FIELD_INT,\n                RandomPrimaryKey.FIELD_INT_DEFAULT_VALUE + 1);\n    }\n\n    @Test\n    public void createObject_defaultValueFromOtherConstructor() {\n        realm.beginTransaction();\n        DefaultValueFromOtherConstructor obj = realm.createObject(DefaultValueFromOtherConstructor.class);\n        realm.commitTransaction();\n\n        assertEquals(42, obj.getFieldLong());\n    }\n\n    @Test\n    public void copyToRealm_defaultValuesAreIgnored() {\n        final String fieldIgnoredValue = DefaultValueOfField.FIELD_IGNORED_DEFAULT_VALUE + \".modified\";\n        final String fieldStringValue = DefaultValueOfField.FIELD_STRING_DEFAULT_VALUE + \".modified\";\n        final String fieldRandomStringValue = \"non-random\";\n        final short fieldShortValue = (short) (DefaultValueOfField.FIELD_SHORT_DEFAULT_VALUE + 1);\n        final int fieldIntValue = DefaultValueOfField.FIELD_INT_DEFAULT_VALUE + 1;\n        final long fieldLongPrimaryKeyValue = DefaultValueOfField.FIELD_LONG_PRIMARY_KEY_DEFAULT_VALUE + 1;\n        final long fieldLongValue = DefaultValueOfField.FIELD_LONG_DEFAULT_VALUE + 1;\n        final byte fieldByteValue = (byte) (DefaultValueOfField.FIELD_BYTE_DEFAULT_VALUE + 1);\n        final float fieldFloatValue = DefaultValueOfField.FIELD_FLOAT_DEFAULT_VALUE + 1;\n        final double fieldDoubleValue = DefaultValueOfField.FIELD_DOUBLE_DEFAULT_VALUE + 1;\n        final boolean fieldBooleanValue = !DefaultValueOfField.FIELD_BOOLEAN_DEFAULT_VALUE;\n        final Date fieldDateValue = new Date(DefaultValueOfField.FIELD_DATE_DEFAULT_VALUE.getTime() + 1);\n        final byte[] fieldBinaryValue = {(byte) (DefaultValueOfField.FIELD_BINARY_DEFAULT_VALUE[0] - 1)};\n        final int fieldObjectIntValue = RandomPrimaryKey.FIELD_INT_DEFAULT_VALUE + 1;\n        final int fieldListIntValue = RandomPrimaryKey.FIELD_INT_DEFAULT_VALUE + 2;\n\n        final DefaultValueOfField managedObj;\n        realm.beginTransaction();\n        {\n            final DefaultValueOfField obj = new DefaultValueOfField();\n            obj.setFieldIgnored(fieldIgnoredValue);\n            obj.setFieldString(fieldStringValue);\n            obj.setFieldRandomString(fieldRandomStringValue);\n            obj.setFieldShort(fieldShortValue);\n            obj.setFieldInt(fieldIntValue);\n            obj.setFieldLongPrimaryKey(fieldLongPrimaryKeyValue);\n            obj.setFieldLong(fieldLongValue);\n            obj.setFieldByte(fieldByteValue);\n            obj.setFieldFloat(fieldFloatValue);\n            obj.setFieldDouble(fieldDoubleValue);\n            obj.setFieldBoolean(fieldBooleanValue);\n            obj.setFieldDate(fieldDateValue);\n            obj.setFieldBinary(fieldBinaryValue);\n\n            final RandomPrimaryKey fieldObjectValue = new RandomPrimaryKey();\n            fieldObjectValue.setFieldInt(fieldObjectIntValue);\n            obj.setFieldObject(fieldObjectValue);\n\n            final RealmList<RandomPrimaryKey> list = new RealmList<RandomPrimaryKey>();\n            final RandomPrimaryKey listItem = new RandomPrimaryKey();\n            listItem.setFieldInt(fieldListIntValue);\n            list.add(listItem);\n            obj.setFieldList(list);\n\n            obj.setFieldStringList(new RealmList<>(\"2\", \"3\"));\n            obj.setFieldBooleanList(new RealmList<>(true, false));\n            obj.setFieldBinaryList(new RealmList<>(new byte[] {2}, new byte[] {3}));\n            obj.setFieldLongList(new RealmList<>(2L, 3L));\n            obj.setFieldIntegerList(new RealmList<>(2, 3));\n            obj.setFieldShortList(new RealmList<>((short) 2, (short) 3));\n            obj.setFieldByteList(new RealmList<>((byte) 2, (byte) 3));\n            obj.setFieldDoubleList(new RealmList<>(2D, 3D));\n            obj.setFieldFloatList(new RealmList<>(2F, 3F));\n            obj.setFieldDateList(new RealmList<>(new Date(2L), new Date(3L)));\n\n            managedObj = realm.copyToRealm(obj);\n        }\n        realm.commitTransaction();\n\n        assertEquals(DefaultValueOfField.FIELD_IGNORED_DEFAULT_VALUE/*not fieldIgnoredValue*/,\n                managedObj.getFieldIgnored());\n        assertEquals(fieldStringValue, managedObj.getFieldString());\n        assertEquals(fieldRandomStringValue, managedObj.getFieldRandomString());\n        assertEquals(fieldShortValue, managedObj.getFieldShort());\n        assertEquals(fieldIntValue, managedObj.getFieldInt());\n        assertEquals(fieldLongPrimaryKeyValue, managedObj.getFieldLongPrimaryKey());\n        assertEquals(fieldLongValue, managedObj.getFieldLong());\n        assertEquals(fieldByteValue, managedObj.getFieldByte());\n        assertEquals(fieldFloatValue, managedObj.getFieldFloat(), 0F);\n        assertEquals(fieldDoubleValue, managedObj.getFieldDouble(), 0D);\n        assertEquals(fieldBooleanValue, managedObj.isFieldBoolean());\n        assertEquals(fieldDateValue, managedObj.getFieldDate());\n        assertArrayEquals(fieldBinaryValue, managedObj.getFieldBinary());\n        assertEquals(fieldObjectIntValue, managedObj.getFieldObject().getFieldInt());\n        assertEquals(1, managedObj.getFieldList().size());\n        assertEquals(fieldListIntValue, managedObj.getFieldList().first().getFieldInt());\n\n        assertEquals(2, managedObj.getFieldStringList().size());\n        assertEquals(\"2\", managedObj.getFieldStringList().get(0));\n        assertEquals(\"3\", managedObj.getFieldStringList().get(1));\n        assertEquals(2, managedObj.getFieldBooleanList().size());\n        assertEquals(true, managedObj.getFieldBooleanList().get(0));\n        assertEquals(false, managedObj.getFieldBooleanList().get(1));\n        assertEquals(2, managedObj.getFieldBinaryList().size());\n        assertArrayEquals(new byte[] {2}, managedObj.getFieldBinaryList().get(0));\n        assertArrayEquals(new byte[] {3}, managedObj.getFieldBinaryList().get(1));\n        assertEquals(2, managedObj.getFieldLongList().size());\n        assertEquals((Long) 2L, managedObj.getFieldLongList().get(0));\n        assertEquals((Long) 3L, managedObj.getFieldLongList().get(1));\n        assertEquals(2, managedObj.getFieldIntegerList().size());\n        assertEquals((Integer) 2, managedObj.getFieldIntegerList().get(0));\n        assertEquals((Integer) 3, managedObj.getFieldIntegerList().get(1));\n        assertEquals(2, managedObj.getFieldShortList().size());\n        assertEquals((Short) (short) 2, managedObj.getFieldShortList().get(0));\n        assertEquals((Short) (short) 3, managedObj.getFieldShortList().get(1));\n        assertEquals(2, managedObj.getFieldByteList().size());\n        assertEquals((Byte) (byte) 2, managedObj.getFieldByteList().get(0));\n        assertEquals((Byte) (byte) 3, managedObj.getFieldByteList().get(1));\n        assertEquals(2, managedObj.getFieldDoubleList().size());\n        assertEquals((Double) 2D, managedObj.getFieldDoubleList().get(0));\n        assertEquals((Double) 3D, managedObj.getFieldDoubleList().get(1));\n        assertEquals(2, managedObj.getFieldFloatList().size());\n        assertEquals((Float) 2F, managedObj.getFieldFloatList().get(0));\n        assertEquals((Float) 3F, managedObj.getFieldFloatList().get(1));\n        assertEquals(2, managedObj.getFieldDateList().size());\n        assertEquals(new Date(2L), managedObj.getFieldDateList().get(0));\n        assertEquals(new Date(3L), managedObj.getFieldDateList().get(1));\n\n        // Makes sure that excess object by default value is not created.\n        assertEquals(2, realm.where(RandomPrimaryKey.class).count());\n    }\n\n    @Test\n    public void copyFromRealm_defaultValuesAreIgnored() {\n        final DefaultValueOfField managedObj;\n        realm.beginTransaction();\n        {\n            final DefaultValueOfField obj = new DefaultValueOfField();\n            obj.setFieldIgnored(DefaultValueOfField.FIELD_IGNORED_DEFAULT_VALUE + \".modified\");\n            obj.setFieldString(DefaultValueOfField.FIELD_STRING_DEFAULT_VALUE + \".modified\");\n            obj.setFieldRandomString(\"non-random\");\n            obj.setFieldShort((short) (DefaultValueOfField.FIELD_SHORT_DEFAULT_VALUE + 1));\n            obj.setFieldInt(DefaultValueOfField.FIELD_INT_DEFAULT_VALUE + 1);\n            obj.setFieldLongPrimaryKey(DefaultValueOfField.FIELD_LONG_PRIMARY_KEY_DEFAULT_VALUE + 1);\n            obj.setFieldLong(DefaultValueOfField.FIELD_LONG_DEFAULT_VALUE + 1);\n            obj.setFieldByte((byte) (DefaultValueOfField.FIELD_BYTE_DEFAULT_VALUE + 1));\n            obj.setFieldFloat(DefaultValueOfField.FIELD_FLOAT_DEFAULT_VALUE + 1);\n            obj.setFieldDouble(DefaultValueOfField.FIELD_DOUBLE_DEFAULT_VALUE + 1);\n            obj.setFieldBoolean(!DefaultValueOfField.FIELD_BOOLEAN_DEFAULT_VALUE);\n            obj.setFieldDate(new Date(DefaultValueOfField.FIELD_DATE_DEFAULT_VALUE.getTime() + 1));\n            obj.setFieldBinary(new byte[] {(byte) (DefaultValueOfField.FIELD_BINARY_DEFAULT_VALUE[0] - 1)});\n\n            final RandomPrimaryKey fieldObjectValue = new RandomPrimaryKey();\n            fieldObjectValue.setFieldInt(RandomPrimaryKey.FIELD_INT_DEFAULT_VALUE + 1);\n            obj.setFieldObject(fieldObjectValue);\n\n            final RealmList<RandomPrimaryKey> list = new RealmList<RandomPrimaryKey>();\n            final RandomPrimaryKey listItem = new RandomPrimaryKey();\n            listItem.setFieldInt(RandomPrimaryKey.FIELD_INT_DEFAULT_VALUE + 2);\n            list.add(listItem);\n            obj.setFieldList(list);\n\n            obj.setFieldStringList(new RealmList<>(\"2\", \"3\"));\n            obj.setFieldBooleanList(new RealmList<>(true, false));\n            obj.setFieldBinaryList(new RealmList<>(new byte[] {2}, new byte[] {3}));\n            obj.setFieldLongList(new RealmList<>(2L, 3L));\n            obj.setFieldIntegerList(new RealmList<>(2, 3));\n            obj.setFieldShortList(new RealmList<>((short) 2, (short) 3));\n            obj.setFieldByteList(new RealmList<>((byte) 2, (byte) 3));\n            obj.setFieldDoubleList(new RealmList<>(2D, 3D));\n            obj.setFieldFloatList(new RealmList<>(2F, 3F));\n            obj.setFieldDateList(new RealmList<>(new Date(2L), new Date(3L)));\n\n            managedObj = realm.copyToRealm(obj);\n        }\n        realm.commitTransaction();\n\n        final DefaultValueOfField copy = realm.copyFromRealm(managedObj);\n\n        assertEquals(DefaultValueOfField.FIELD_IGNORED_DEFAULT_VALUE, copy.getFieldIgnored());\n        assertEquals(managedObj.getFieldString(), copy.getFieldString());\n        assertEquals(managedObj.getFieldRandomString(), copy.getFieldRandomString());\n        assertEquals(managedObj.getFieldShort(), copy.getFieldShort());\n        assertEquals(managedObj.getFieldInt(), copy.getFieldInt());\n        assertEquals(managedObj.getFieldLongPrimaryKey(), copy.getFieldLongPrimaryKey());\n        assertEquals(managedObj.getFieldLong(), copy.getFieldLong());\n        assertEquals(managedObj.getFieldByte(), copy.getFieldByte());\n        assertEquals(managedObj.getFieldFloat(), copy.getFieldFloat(), 0F);\n        assertEquals(managedObj.getFieldDouble(), copy.getFieldDouble(), 0D);\n        assertEquals(managedObj.isFieldBoolean(), copy.isFieldBoolean());\n        assertEquals(managedObj.getFieldDate(), copy.getFieldDate());\n        assertArrayEquals(managedObj.getFieldBinary(), copy.getFieldBinary());\n        assertEquals(managedObj.getFieldObject().getFieldInt(), copy.getFieldObject().getFieldInt());\n        assertEquals(1, copy.getFieldList().size());\n        //noinspection ConstantConditions\n        assertEquals(managedObj.getFieldList().first().getFieldInt(), copy.getFieldList().first().getFieldInt());\n\n        assertEquals(2, managedObj.getFieldStringList().size());\n        assertEquals(\"2\", managedObj.getFieldStringList().get(0));\n        assertEquals(\"3\", managedObj.getFieldStringList().get(1));\n        assertEquals(2, managedObj.getFieldBooleanList().size());\n        assertEquals(true, managedObj.getFieldBooleanList().get(0));\n        assertEquals(false, managedObj.getFieldBooleanList().get(1));\n        assertEquals(2, managedObj.getFieldBinaryList().size());\n        assertArrayEquals(new byte[] {2}, managedObj.getFieldBinaryList().get(0));\n        assertArrayEquals(new byte[] {3}, managedObj.getFieldBinaryList().get(1));\n        assertEquals(2, managedObj.getFieldLongList().size());\n        assertEquals((Long) 2L, managedObj.getFieldLongList().get(0));\n        assertEquals((Long) 3L, managedObj.getFieldLongList().get(1));\n        assertEquals(2, managedObj.getFieldIntegerList().size());\n        assertEquals((Integer) 2, managedObj.getFieldIntegerList().get(0));\n        assertEquals((Integer) 3, managedObj.getFieldIntegerList().get(1));\n        assertEquals(2, managedObj.getFieldShortList().size());\n        assertEquals((Short) (short) 2, managedObj.getFieldShortList().get(0));\n        assertEquals((Short) (short) 3, managedObj.getFieldShortList().get(1));\n        assertEquals(2, managedObj.getFieldByteList().size());\n        assertEquals((Byte) (byte) 2, managedObj.getFieldByteList().get(0));\n        assertEquals((Byte) (byte) 3, managedObj.getFieldByteList().get(1));\n        assertEquals(2, managedObj.getFieldDoubleList().size());\n        assertEquals((Double) 2D, managedObj.getFieldDoubleList().get(0));\n        assertEquals((Double) 3D, managedObj.getFieldDoubleList().get(1));\n        assertEquals(2, managedObj.getFieldFloatList().size());\n        assertEquals((Float) 2F, managedObj.getFieldFloatList().get(0));\n        assertEquals((Float) 3F, managedObj.getFieldFloatList().get(1));\n        assertEquals(2, managedObj.getFieldDateList().size());\n        assertEquals(new Date(2L), managedObj.getFieldDateList().get(0));\n        assertEquals(new Date(3L), managedObj.getFieldDateList().get(1));\n    }\n\n    // Tests close Realm in another thread different from where it is created.\n    @Test\n    public void close_differentThread() throws InterruptedException {\n        final CountDownLatch latch = new CountDownLatch(1);\n        final AssertionFailedError threadAssertionError[] = new AssertionFailedError[1];\n\n        final Thread thatThread = new Thread(new Runnable() {\n            @Override\n            public void run() {\n                try {\n                    realm.close();\n                    threadAssertionError[0] = new AssertionFailedError(\n                            \"Close realm in a different thread should throw IllegalStateException.\");\n                } catch (IllegalStateException ignored) {\n                }\n                latch.countDown();\n            }\n        });\n        thatThread.start();\n\n        // Timeout should never happen.\n        TestHelper.awaitOrFail(latch);\n        if (threadAssertionError[0] != null) {\n            throw threadAssertionError[0];\n        }\n        // After exception thrown in another thread, nothing should be changed to the realm in this thread.\n        realm.checkIfValid();\n        realm.close();\n        realm = null;\n    }\n\n    @Test\n    public void isClosed() {\n        assertFalse(realm.isClosed());\n        realm.close();\n        assertTrue(realm.isClosed());\n    }\n\n    // Tests Realm#isClosed() in another thread different from where it is created.\n    @Test\n    public void isClosed_differentThread() throws InterruptedException {\n        final CountDownLatch latch = new CountDownLatch(1);\n        final AssertionFailedError threadAssertionError[] = new AssertionFailedError[1];\n\n        final Thread thatThread = new Thread(new Runnable() {\n            @Override\n            public void run() {\n                try {\n                    realm.isClosed();\n                    threadAssertionError[0] = new AssertionFailedError(\n                            \"Call isClosed() of Realm instance in a different thread should throw IllegalStateException.\");\n                } catch (IllegalStateException ignored) {\n                }\n                latch.countDown();\n            }\n        });\n        thatThread.start();\n\n        // Timeout should never happen.\n        TestHelper.awaitOrFail(latch);\n        if (threadAssertionError[0] != null) {\n            throw threadAssertionError[0];\n        }\n        // After exception thrown in another thread, nothing should be changed to the realm in this thread.\n        realm.checkIfValid();\n        assertFalse(realm.isClosed());\n        realm.close();\n    }\n\n    // Realm validation & initialization is done once, still ColumnIndices\n    // should be populated for the subsequent Realm sharing the same configuration\n    // even if we skip initialization & validation.\n    @Test\n    public void columnIndicesIsPopulatedWhenSkippingInitialization() throws Throwable {\n        final RealmConfiguration realmConfiguration = configFactory.createConfiguration(\"columnIndices\");\n        final Exception threadError[] = new Exception[1];\n        final CountDownLatch bgRealmOpened = new CountDownLatch(1);\n        final CountDownLatch mainThreadRealmDone = new CountDownLatch(1);\n        final CountDownLatch bgRealmClosed = new CountDownLatch(1);\n\n        new Thread(new Runnable() {\n            @Override\n            public void run() {\n                Realm realm = Realm.getInstance(realmConfiguration); // This will populate columnIndices.\n                try {\n                    bgRealmOpened.countDown();\n                    TestHelper.awaitOrFail(mainThreadRealmDone);\n                    realm.close();\n                    bgRealmClosed.countDown();\n                } catch (Exception e) {\n                    threadError[0] = e;\n                } finally {\n                    if (!realm.isClosed()) {\n                        realm.close();\n                    }\n                }\n            }\n        }).start();\n\n        TestHelper.awaitOrFail(bgRealmOpened);\n        Realm realm = Realm.getInstance(realmConfiguration);\n        realm.where(AllTypes.class).equalTo(\"columnString\", \"Foo\").findAll(); // This would crash if columnIndices == null.\n        realm.close();\n        mainThreadRealmDone.countDown();\n        TestHelper.awaitOrFail(bgRealmClosed);\n        if (threadError[0] != null) {\n            throw threadError[0];\n        }\n    }\n\n    @Test\n    public void isInTransaction() {\n        assertFalse(realm.isInTransaction());\n        realm.beginTransaction();\n        assertTrue(realm.isInTransaction());\n        realm.commitTransaction();\n        assertFalse(realm.isInTransaction());\n        realm.beginTransaction();\n        assertTrue(realm.isInTransaction());\n        realm.cancelTransaction();\n        assertFalse(realm.isInTransaction());\n    }\n\n    // Test for https://github.com/realm/realm-java/issues/1646\n    @Test\n    public void closingRealmWhileOtherThreadIsOpeningRealm() throws Exception {\n        final CountDownLatch startLatch = new CountDownLatch(1);\n        final CountDownLatch endLatch = new CountDownLatch(1);\n\n        final List<Exception> exception = new ArrayList<Exception>();\n\n        new Thread() {\n            @Override\n            public void run() {\n                try {\n                    startLatch.await(TestHelper.STANDARD_WAIT_SECS, TimeUnit.SECONDS);\n                } catch (InterruptedException e) {\n                    exception.add(e);\n                    return;\n                }\n\n                final Realm realm = Realm.getInstance(realmConfig);\n                try {\n                    realm.where(AllTypes.class).equalTo(\"columnLong\", 0L).findFirst();\n                } catch (Exception e) {\n                    exception.add(e);\n                } finally {\n                    endLatch.countDown();\n                    realm.close();\n                }\n            }\n        }.start();\n\n        // Prevents for another thread to enter Realm.createAndValidate().\n        synchronized (BaseRealm.class) {\n            startLatch.countDown();\n\n            // Waits for another thread's entering Realm.createAndValidate().\n            SystemClock.sleep(100L);\n\n            realm.close();\n            realm = null;\n        }\n\n        TestHelper.awaitOrFail(endLatch);\n\n        if (!exception.isEmpty()) {\n            throw exception.get(0);\n        }\n    }\n\n    // Bug reported https://github.com/realm/realm-java/issues/1728.\n    // Root cause is validatedRealmFiles will be cleaned when any thread's Realm ref counter reach 0.\n    @Test\n    public void openRealmWhileTransactionInAnotherThread() throws Exception {\n        final CountDownLatch realmOpenedInBgLatch = new CountDownLatch(1);\n        final CountDownLatch realmClosedInFgLatch = new CountDownLatch(1);\n        final CountDownLatch transBeganInBgLatch = new CountDownLatch(1);\n        final CountDownLatch fgFinishedLatch = new CountDownLatch(1);\n        final CountDownLatch bgFinishedLatch = new CountDownLatch(1);\n        final List<Exception> exception = new ArrayList<Exception>();\n\n        // Step 1: testRealm is opened already.\n\n        Thread thread = new Thread(new Runnable() {\n            @Override\n            public void run() {\n                // Step 2: Opens realm in background thread.\n                Realm realm = Realm.getInstance(realmConfig);\n                realmOpenedInBgLatch.countDown();\n                try {\n                    realmClosedInFgLatch.await(TestHelper.STANDARD_WAIT_SECS, TimeUnit.SECONDS);\n                } catch (InterruptedException e) {\n                    exception.add(e);\n                    realm.close();\n                    return;\n                }\n\n                // Step 4: Starts transaction in background.\n                realm.beginTransaction();\n                transBeganInBgLatch.countDown();\n                try {\n                    fgFinishedLatch.await(TestHelper.STANDARD_WAIT_SECS, TimeUnit.SECONDS);\n                } catch (InterruptedException e) {\n                    exception.add(e);\n                }\n                // Step 6: Cancels Transaction and closes realm in background.\n                realm.cancelTransaction();\n                realm.close();\n                bgFinishedLatch.countDown();\n            }\n        });\n        thread.start();\n\n        TestHelper.awaitOrFail(realmOpenedInBgLatch);\n        // Step 3: Closes all realm instances in foreground thread.\n        realm.close();\n        realmClosedInFgLatch.countDown();\n        TestHelper.awaitOrFail(transBeganInBgLatch);\n\n        // Step 5: Gets a new Realm instance in foreground.\n        realm = Realm.getInstance(realmConfig);\n        fgFinishedLatch.countDown();\n        TestHelper.awaitOrFail(bgFinishedLatch);\n\n        if (!exception.isEmpty()) {\n            throw exception.get(0);\n        }\n    }\n\n    @Test\n    public void isEmpty() {\n        RealmConfiguration realmConfig = configFactory.createConfiguration(\"empty_test.realm\");\n        Realm emptyRealm = Realm.getInstance(realmConfig);\n\n        assertTrue(emptyRealm.isEmpty());\n\n        emptyRealm.beginTransaction();\n        PrimaryKeyAsLong obj = new PrimaryKeyAsLong();\n        obj.setId(1);\n        obj.setName(\"Foo\");\n        emptyRealm.copyToRealm(obj);\n        assertFalse(emptyRealm.isEmpty());\n        emptyRealm.cancelTransaction();\n\n        assertTrue(emptyRealm.isEmpty());\n\n        emptyRealm.beginTransaction();\n        obj = new PrimaryKeyAsLong();\n        obj.setId(1);\n        obj.setName(\"Foo\");\n        emptyRealm.copyToRealm(obj);\n        emptyRealm.commitTransaction();\n\n        assertFalse(emptyRealm.isEmpty());\n\n        emptyRealm.close();\n    }\n\n    @Test\n    public void copyFromRealm_invalidObjectThrows() {\n        realm.beginTransaction();\n        AllTypes obj = realm.createObject(AllTypes.class);\n        obj.deleteFromRealm();\n        realm.commitTransaction();\n\n        try {\n            realm.copyFromRealm(obj);\n            fail();\n        } catch (IllegalArgumentException ignored) {\n        }\n\n        try {\n            realm.copyFromRealm(new AllTypes());\n            fail();\n        } catch (IllegalArgumentException ignored) {\n        }\n    }\n\n    @Test\n    public void copyFromRealm_invalidDepthThrows() {\n        realm.beginTransaction();\n        AllTypes obj = realm.createObject(AllTypes.class);\n        realm.commitTransaction();\n        thrown.expect(IllegalArgumentException.class);\n        realm.copyFromRealm(obj, -1);\n    }\n\n    @Test\n    public void copyFromRealm() {\n        populateTestRealm();\n        AllTypes realmObject = realm.where(AllTypes.class).sort(\"columnLong\").findAll().first();\n        AllTypes unmanagedObject = realm.copyFromRealm(realmObject);\n        assertArrayEquals(realmObject.getColumnBinary(), unmanagedObject.getColumnBinary());\n        assertEquals(realmObject.getColumnString(), unmanagedObject.getColumnString());\n        assertEquals(realmObject.getColumnLong(), unmanagedObject.getColumnLong());\n        assertEquals(realmObject.getColumnFloat(), unmanagedObject.getColumnFloat(), 0.00000000001);\n        assertEquals(realmObject.getColumnDouble(), unmanagedObject.getColumnDouble(), 0.00000000001);\n        assertEquals(realmObject.isColumnBoolean(), unmanagedObject.isColumnBoolean());\n        assertEquals(realmObject.getColumnDate(), unmanagedObject.getColumnDate());\n        assertEquals(realmObject.getColumnObjectId(), unmanagedObject.getColumnObjectId());\n        assertEquals(realmObject.getColumnDecimal128(), unmanagedObject.getColumnDecimal128());\n        assertEquals(realmObject.getColumnUUID(), unmanagedObject.getColumnUUID());\n        assertEquals(realmObject.getColumnRealmAny(), unmanagedObject.getColumnRealmAny());\n    }\n\n    @Test\n    public void copyFromRealm_newCopyEachTime() {\n        populateTestRealm();\n        AllTypes realmObject = realm.where(AllTypes.class).sort(\"columnLong\").findAll().first();\n        AllTypes unmanagedObject1 = realm.copyFromRealm(realmObject);\n        AllTypes unmanagedObject2 = realm.copyFromRealm(realmObject);\n        assertFalse(unmanagedObject1 == unmanagedObject2);\n        assertNotSame(unmanagedObject1, unmanagedObject2);\n    }\n\n    // Tests that the object graph is copied as it is and no extra copies are made.\n    // 1) (A -> B/[B,C])\n    // 2) (C -> B/[B,A])\n    // A copy should result in only 3 distinct objects.\n    @Test\n    public void copyFromRealm_cyclicObjectGraph() {\n        realm.beginTransaction();\n        CyclicType objA = realm.createObject(CyclicType.class);\n        objA.setName(\"A\");\n        CyclicType objB = realm.createObject(CyclicType.class);\n        objB.setName(\"B\");\n        CyclicType objC = realm.createObject(CyclicType.class);\n        objC.setName(\"C\");\n        objA.setObject(objB);\n        objC.setObject(objB);\n        objA.getObjects().add(objB);\n        objA.getObjects().add(objC);\n        objC.getObjects().add(objB);\n        objC.getObjects().add(objA);\n        realm.commitTransaction();\n\n        CyclicType copyA = realm.copyFromRealm(objA);\n        CyclicType copyB = copyA.getObject();\n        CyclicType copyC = copyA.getObjects().get(1);\n\n        assertEquals(\"A\", copyA.getName());\n        assertEquals(\"B\", copyB.getName());\n        assertEquals(\"C\", copyC.getName());\n\n        // Asserts object equality on the object graph.\n        assertTrue(copyA.getObject() == copyC.getObject());\n        assertTrue(copyA.getObjects().get(0) == copyC.getObjects().get(0));\n        assertTrue(copyA == copyC.getObjects().get(1));\n        assertTrue(copyC == copyA.getObjects().get(1));\n    }\n\n    // Tests that for (A -> B -> C) for maxDepth = 1, result is (A -> B -> null).\n    @Test\n    public void copyFromRealm_checkMaxDepth() {\n        realm.beginTransaction();\n        CyclicType objA = realm.createObject(CyclicType.class);\n        objA.setName(\"A\");\n        CyclicType objB = realm.createObject(CyclicType.class);\n        objB.setName(\"B\");\n        CyclicType objC = realm.createObject(CyclicType.class);\n        objC.setName(\"C\");\n        objA.setObject(objB);\n        objC.setObject(objC);\n        objA.getObjects().add(objB);\n        objA.getObjects().add(objC);\n        realm.commitTransaction();\n\n        CyclicType copyA = realm.copyFromRealm(objA, 1);\n\n        assertNull(copyA.getObject().getObject());\n    }\n\n    // Tests that depth restriction is calculated from the top-most encountered object, i.e. it is possible for some\n    // objects to exceed the depth limit.\n    // A -> B -> C -> D -> E\n    // A -> D -> E\n    // D is both at depth 1 and 3. For maxDepth = 3, E should still be copied.\n    @Test\n    public void copyFromRealm_sameObjectDifferentDepths() {\n        realm.beginTransaction();\n        CyclicType objA = realm.createObject(CyclicType.class);\n        objA.setName(\"A\");\n        CyclicType objB = realm.createObject(CyclicType.class);\n        objB.setName(\"B\");\n        CyclicType objC = realm.createObject(CyclicType.class);\n        objC.setName(\"C\");\n        CyclicType objD = realm.createObject(CyclicType.class);\n        objD.setName(\"D\");\n        CyclicType objE = realm.createObject(CyclicType.class);\n        objE.setName(\"E\");\n        objA.setObject(objB);\n        objB.setObject(objC);\n        objC.setObject(objD);\n        objD.setObject(objE);\n        objA.setOtherObject(objD);\n        realm.commitTransaction();\n\n        // Object is filled before otherObject. (because of field order - WARNING: Not guaranteed)\n        // This means that the object will be encountered first time at max depth, so E will not be copied.\n        // If the object cache does not handle this, otherObject will be wrong.\n        CyclicType copyA = realm.copyFromRealm(objA, 3);\n        assertEquals(\"E\", copyA.getOtherObject().getObject().getName());\n    }\n\n    @Test\n    public void copyFromRealm_list_invalidListThrows() {\n        realm.beginTransaction();\n        AllTypes object = realm.createObject(AllTypes.class);\n        List<AllTypes> list = new RealmList<AllTypes>(object);\n        object.deleteFromRealm();\n        realm.commitTransaction();\n\n        thrown.expect(IllegalArgumentException.class);\n        realm.copyFromRealm(list);\n    }\n\n    @Test\n    public void copyFromRealm_emptyList() {\n        RealmResults<AllTypes> results = realm.where(AllTypes.class).alwaysFalse().findAll();\n        List<AllTypes> copy = realm.copyFromRealm(results);\n        assertEquals(0, copy.size());\n    }\n\n    @Test\n    public void copyFromRealm_list_invalidDepthThrows() {\n        RealmResults<AllTypes> results = realm.where(AllTypes.class).findAll();\n        thrown.expect(IllegalArgumentException.class);\n        realm.copyFromRealm(results, -1);\n    }\n\n    // Tests that the same Realm objects in a list result in the same Java in-memory copy.\n    // List: A -> [(B -> C), (B -> C)] should result in only 2 copied objects A and B and not A1, B1, A2, B2\n    @Test\n    public void copyFromRealm_list_sameElements() {\n        realm.beginTransaction();\n        CyclicType objA = realm.createObject(CyclicType.class);\n        objA.setName(\"A\");\n        CyclicType objB = realm.createObject(CyclicType.class);\n        objB.setName(\"B\");\n        CyclicType objC = realm.createObject(CyclicType.class);\n        objC.setName(\"C\");\n        objB.setObject(objC);\n        objA.getObjects().add(objB);\n        objA.getObjects().add(objB);\n        realm.commitTransaction();\n\n        List<CyclicType> results = realm.copyFromRealm(objA.getObjects());\n        assertEquals(2, results.size());\n        assertEquals(\"B\", results.get(0).getName());\n        assertTrue(results.get(0) == results.get(1));\n    }\n\n    @Test\n    public void copyFromRealm_dynamicRealmObjectThrows() {\n        realm.beginTransaction();\n        AllTypes obj = realm.createObject(AllTypes.class);\n        realm.commitTransaction();\n        DynamicRealmObject dObj = new DynamicRealmObject(obj);\n\n        try {\n            realm.copyFromRealm(dObj);\n            fail();\n        } catch (IllegalArgumentException ignored) {\n        }\n    }\n\n    @Test\n    public void copyFromRealm_dynamicRealmListThrows() {\n        DynamicRealm dynamicRealm = DynamicRealm.getInstance(realm.getConfiguration());\n        dynamicRealm.beginTransaction();\n        RealmList<DynamicRealmObject> dynamicList = dynamicRealm.createObject(AllTypes.CLASS_NAME).getList(AllTypes.FIELD_REALMLIST);\n        DynamicRealmObject dObj = dynamicRealm.createObject(Dog.CLASS_NAME);\n        dynamicList.add(dObj);\n        dynamicRealm.commitTransaction();\n        try {\n            realm.copyFromRealm(dynamicList);\n            fail();\n        } catch (IllegalArgumentException ignored) {\n        } finally {\n            dynamicRealm.close();\n        }\n    }\n\n    // Tests if close can be called from Realm change listener when there is no other listeners.\n    @Test\n    public void closeRealmInChangeListener() {\n        looperThread.runBlocking(() -> {\n            Realm realm = Realm.getInstance(realmConfig);\n            looperThread.closeAfterTest(realm);\n            final RealmChangeListener<Realm> listener = new RealmChangeListener<Realm>() {\n                @Override\n                public void onChange(Realm object) {\n                    if (realm.where(AllTypes.class).count() == 1) {\n                        realm.removeChangeListener(this);\n                        looperThread.testComplete();\n                    }\n                }\n            };\n            realm.addChangeListener(listener);\n            realm.executeTransactionAsync(new Realm.Transaction() {\n                @Override\n                public void execute(Realm realm) {\n                    realm.createObject(AllTypes.class);\n                }\n            });\n        });\n    }\n\n    // Tests if close can be called from Realm change listener when there is a listener on empty Realm Object.\n    @Test\n    public void closeRealmInChangeListenerWhenThereIsListenerOnEmptyObject() {\n        looperThread.runBlocking(() -> {\n            final Realm realm = Realm.getInstance((realmConfig));\n            looperThread.closeAfterTest(realm);\n            final RealmChangeListener<AllTypes> dummyListener = new RealmChangeListener<AllTypes>() {\n                @Override\n                public void onChange(AllTypes object) {\n                }\n            };\n\n            // Change listener on Realm\n            final RealmChangeListener<Realm> listener = new RealmChangeListener<Realm>() {\n                @Override\n                public void onChange(Realm object) {\n                    if (realm.where(AllTypes.class).count() == 1) {\n                        realm.removeChangeListener(this);\n                        looperThread.testComplete();\n                    }\n                }\n            };\n            realm.addChangeListener(listener);\n\n            // Change listener on Empty Object\n            final AllTypes allTypes = realm.where(AllTypes.class).findFirstAsync();\n            allTypes.addChangeListener(dummyListener);\n\n            realm.executeTransactionAsync(new Realm.Transaction() {\n                @Override\n                public void execute(Realm realm) {\n                    realm.createObject(AllTypes.class);\n                }\n            });\n        });\n    }\n\n    // Tests if close can be called from Realm change listener when there is an listener on non-empty Realm Object.\n    @Test\n    public void closeRealmInChangeListenerWhenThereIsListenerOnObject() {\n        looperThread.runBlocking(() -> {\n            final Realm realm = Realm.getInstance((realmConfig));\n            looperThread.closeAfterTest(realm);\n            final RealmChangeListener<AllTypes> dummyListener = new RealmChangeListener<AllTypes>() {\n                @Override\n                public void onChange(AllTypes object) {\n                }\n            };\n            final RealmChangeListener<Realm> listener = new RealmChangeListener<Realm>() {\n                @Override\n                public void onChange(Realm object) {\n                    if (realm.where(AllTypes.class).count() == 2) {\n                        realm.removeChangeListener(this);\n                        looperThread.testComplete();\n                    }\n                }\n            };\n\n            realm.addChangeListener(listener);\n\n            realm.beginTransaction();\n            realm.createObject(AllTypes.class);\n            realm.commitTransaction();\n\n            // Change listener on Realm Object.\n            final AllTypes allTypes = realm.where(AllTypes.class).findFirst();\n            allTypes.addChangeListener(dummyListener);\n            realm.executeTransactionAsync(new Realm.Transaction() {\n                @Override\n                public void execute(Realm realm) {\n                    realm.createObject(AllTypes.class);\n                }\n            });\n        });\n    }\n\n    // Tests if close can be called from Realm change listener when there is an listener on RealmResults.\n    @Test\n    public void closeRealmInChangeListenerWhenThereIsListenerOnResults() {\n        looperThread.runBlocking(() -> {\n            final Realm realm = Realm.getInstance((realmConfig));\n            looperThread.closeAfterTest(realm);\n            final RealmChangeListener<RealmResults<AllTypes>> dummyListener = new RealmChangeListener<RealmResults<AllTypes>>() {\n                @Override\n                public void onChange(RealmResults<AllTypes> object) {\n                }\n            };\n            final RealmChangeListener<Realm> listener = new RealmChangeListener<Realm>() {\n                @Override\n                public void onChange(Realm object) {\n                    if (realm.where(AllTypes.class).count() == 1) {\n                        realm.removeChangeListener(this);\n                        looperThread.testComplete();\n                    }\n                }\n            };\n\n            realm.addChangeListener(listener);\n\n            // Change listener on Realm results.\n            RealmResults<AllTypes> results = realm.where(AllTypes.class).findAll();\n            results.addChangeListener(dummyListener);\n\n            realm.executeTransactionAsync(new Realm.Transaction() {\n                @Override\n                public void execute(Realm realm) {\n                    realm.createObject(AllTypes.class);\n                }\n            });\n        });\n    }\n\n    @Test\n    public void addChangeListener_throwOnAddingNullListenerFromLooperThread() {\n        looperThread.runBlocking(() -> {\n            final Realm realm = Realm.getInstance((realmConfig));\n            looperThread.closeAfterTest(realm);\n            try {\n                realm.addChangeListener(null);\n                fail(\"adding null change listener must throw an exception.\");\n            } catch (IllegalArgumentException ignore) {\n            } finally {\n                looperThread.testComplete();\n            }\n        });\n    }\n\n    @Test\n    public void addChangeListener_throwOnAddingNullListenerFromNonLooperThread() throws Throwable {\n        TestHelper.executeOnNonLooperThread(new TestHelper.Task() {\n            @Override\n            public void run() throws Exception {\n                final Realm realm = Realm.getInstance(realmConfig);\n\n                //noinspection TryFinallyCanBeTryWithResources\n                try {\n                    realm.addChangeListener(null);\n                    fail(\"adding null change listener must throw an exception.\");\n                } catch (IllegalArgumentException ignore) {\n                } finally {\n                    realm.close();\n                }\n            }\n        });\n    }\n\n    @Test\n    public void removeChangeListener_throwOnRemovingNullListenerFromLooperThread() {\n        looperThread.runBlocking(() -> {\n            final Realm realm = Realm.getInstance((realmConfig));\n            looperThread.closeAfterTest(realm);\n            try {\n                realm.removeChangeListener(null);\n                fail(\"removing null change listener must throw an exception.\");\n            } catch (IllegalArgumentException ignore) {\n            } finally {\n                looperThread.testComplete();\n            }\n        });\n    }\n\n    @Test\n    public void removeChangeListener_throwOnRemovingNullListenerFromNonLooperThread() throws Throwable {\n        TestHelper.executeOnNonLooperThread(new TestHelper.Task() {\n            @Override\n            public void run() throws Exception {\n                final Realm realm = Realm.getInstance(realmConfig);\n\n                //noinspection TryFinallyCanBeTryWithResources\n                try {\n                    realm.removeChangeListener(null);\n                    fail(\"removing null change listener must throw an exception.\");\n                } catch (IllegalArgumentException ignore) {\n                } finally {\n                    realm.close();\n                }\n            }\n        });\n    }\n\n    @Test\n    public void removeChangeListenerThrowExceptionOnWrongThread() {\n        final CountDownLatch signalTestFinished = new CountDownLatch(1);\n        Realm realm = Realm.getInstance(realmConfig);\n        Thread thread = new Thread(() -> {\n            try {\n                realm.removeChangeListener(object -> {});\n                fail(\"Should not be able to invoke removeChangeListener\");\n            } catch (IllegalStateException ignored) {\n            } finally {\n                signalTestFinished.countDown();\n            }\n        });\n        thread.start();\n        try {\n            TestHelper.awaitOrFail(signalTestFinished);\n        } finally {\n            thread.interrupt();\n            realm.close();\n        }\n    }\n\n    @Test\n    public void removeAllChangeListenersThrowExceptionOnWrongThreadThread() {\n        final CountDownLatch signalTestFinished = new CountDownLatch(1);\n        Realm realm = Realm.getInstance(realmConfig);\n        Thread thread = new Thread(() -> {\n            try {\n                realm.removeAllChangeListeners();\n                fail(\"Should not be able to invoke removeChangeListener\");\n            } catch (IllegalStateException ignored) {\n            } finally {\n                signalTestFinished.countDown();\n            }\n        });\n        thread.start();\n\n        try {\n            TestHelper.awaitOrFail(signalTestFinished);\n        } finally {\n            thread.interrupt();\n            realm.close();\n        }\n    }\n\n    @Test\n    public void deleteAll() {\n        realm.beginTransaction();\n        realm.createObject(AllTypes.class);\n        realm.createObject(Owner.class).setCat(realm.createObject(Cat.class));\n        realm.commitTransaction();\n\n        assertEquals(1, realm.where(AllTypes.class).count());\n        assertEquals(1, realm.where(Owner.class).count());\n        assertEquals(1, realm.where(Cat.class).count());\n\n        realm.beginTransaction();\n        realm.deleteAll();\n        realm.commitTransaction();\n\n        assertEquals(0, realm.where(AllTypes.class).count());\n        assertEquals(0, realm.where(Owner.class).count());\n        assertEquals(0, realm.where(Cat.class).count());\n        assertTrue(realm.isEmpty());\n    }\n\n    // Test for https://github.com/realm/realm-java/issues/5745\n    @Test\n    public void deleteAll_realmWithMoreTables() {\n        realm.close();\n        RealmConfiguration config1 = configFactory.createConfigurationBuilder()\n                .name(\"deleteAllTest.realm\")\n                .schema(StringOnly.class, StringAndInt.class)\n                .build();\n        realm = Realm.getInstance(config1);\n        realm.executeTransaction(r -> {\n            r.createObject(StringOnly.class);\n            r.createObject(StringAndInt.class);\n        });\n        realm.close();\n\n        RealmConfiguration config2 = configFactory.createConfigurationBuilder()\n                .name(\"deleteAllTest.realm\")\n                .schema(StringOnly.class)\n                .build();\n\n        realm = Realm.getInstance(config2);\n        realm.beginTransaction();\n        realm.deleteAll();\n        realm.commitTransaction();\n        assertTrue(realm.isEmpty());\n        realm.close();\n\n        // deleteAll() will only delete tables part of the schema, so reopening with the old\n        // should reveal the old data\n        realm = Realm.getInstance(config1);\n        assertFalse(realm.isEmpty());\n        assertEquals(1, realm.where(StringAndInt.class).count());\n    }\n\n\n    @Test\n    public void waitForChange_emptyDataChange() throws InterruptedException {\n        final CountDownLatch bgRealmOpened = new CountDownLatch(1);\n        final CountDownLatch bgRealmClosed = new CountDownLatch(1);\n        final AtomicBoolean bgRealmChangeResult = new AtomicBoolean(false);\n        final AtomicLong bgRealmWaitForChangeResult = new AtomicLong(0);\n\n        // Waits in background.\n        final CountDownLatch signalTestFinished = new CountDownLatch(1);\n        Thread thread = new Thread(new Runnable() {\n            @Override\n            public void run() {\n                Realm realm = Realm.getInstance(realmConfig);\n                bgRealmOpened.countDown();\n                bgRealmChangeResult.set(realm.waitForChange());\n                bgRealmWaitForChangeResult.set(realm.where(AllTypes.class).count());\n                realm.close();\n                bgRealmClosed.countDown();\n            }\n        });\n        thread.start();\n\n        TestHelper.awaitOrFail(bgRealmOpened);\n        realm.beginTransaction();\n        realm.commitTransaction();\n        TestHelper.awaitOrFail(bgRealmClosed);\n        assertTrue(bgRealmChangeResult.get());\n        assertEquals(0, bgRealmWaitForChangeResult.get());\n    }\n\n    @Test\n    public void waitForChange_withDataChange() throws InterruptedException {\n        final CountDownLatch bgRealmOpened = new CountDownLatch(1);\n        final CountDownLatch bgRealmClosed = new CountDownLatch(1);\n        final AtomicBoolean bgRealmChangeResult = new AtomicBoolean(false);\n        final AtomicLong bgRealmWaitForChangeResult = new AtomicLong(0);\n\n        // Waits in background.\n        final CountDownLatch signalTestFinished = new CountDownLatch(1);\n        Thread thread = new Thread(new Runnable() {\n            @Override\n            public void run() {\n                Realm realm = Realm.getInstance(realmConfig);\n                bgRealmOpened.countDown();\n                bgRealmChangeResult.set(realm.waitForChange());\n                bgRealmWaitForChangeResult.set(realm.where(AllTypes.class).count());\n                realm.close();\n                bgRealmClosed.countDown();\n            }\n        });\n        thread.start();\n\n        TestHelper.awaitOrFail(bgRealmOpened);\n        populateTestRealm();\n        TestHelper.awaitOrFail(bgRealmClosed);\n        assertTrue(bgRealmChangeResult.get());\n        assertEquals(TEST_DATA_SIZE, bgRealmWaitForChangeResult.get());\n    }\n\n    @Test\n    public void waitForChange_syncBackgroundRealmResults() throws InterruptedException {\n        final CountDownLatch bgRealmOpened = new CountDownLatch(1);\n        final CountDownLatch bgRealmClosed = new CountDownLatch(1);\n        final AtomicBoolean bgRealmChangeResult = new AtomicBoolean(false);\n        final AtomicLong bgRealmResultSize = new AtomicLong(0);\n\n        // Wait in background\n        final CountDownLatch signalTestFinished = new CountDownLatch(1);\n        Thread thread = new Thread(new Runnable() {\n            @Override\n            public void run() {\n                Realm realm = Realm.getInstance(realmConfig);\n                RealmResults<AllTypes> results = realm.where(AllTypes.class).findAll();\n                // First makes sure the results is empty.\n                bgRealmResultSize.set(results.size());\n                bgRealmOpened.countDown();\n                bgRealmChangeResult.set(realm.waitForChange());\n                bgRealmResultSize.set(results.size());\n                realm.close();\n                bgRealmClosed.countDown();\n            }\n        });\n        thread.start();\n\n        TestHelper.awaitOrFail(bgRealmOpened);\n        // Background result should be empty.\n        assertEquals(0, bgRealmResultSize.get());\n        populateTestRealm();\n        TestHelper.awaitOrFail(bgRealmClosed);\n        assertTrue(bgRealmChangeResult.get());\n        // Once RealmResults are synchronized after waitForChange, the result size should be what we expect.\n        assertEquals(TEST_DATA_SIZE, bgRealmResultSize.get());\n    }\n\n    @Test\n    public void stopWaitForChange() throws InterruptedException {\n        final CountDownLatch bgRealmOpened = new CountDownLatch(1);\n        final CountDownLatch bgRealmClosed = new CountDownLatch(1);\n        final AtomicBoolean bgRealmChangeResult = new AtomicBoolean(true);\n        final AtomicReference<Realm> bgRealm = new AtomicReference<Realm>();\n\n        // Waits in background.\n        new Thread(new Runnable() {\n            @Override\n            public void run() {\n                Realm realm = Realm.getInstance(realmConfig);\n                bgRealm.set(realm);\n                bgRealmOpened.countDown();\n                bgRealmChangeResult.set(realm.waitForChange());\n                realm.close();\n                bgRealmClosed.countDown();\n            }\n        }).start();\n\n        TestHelper.awaitOrFail(bgRealmOpened);\n        Thread.sleep(200);\n        bgRealm.get().stopWaitForChange();\n        TestHelper.awaitOrFail(bgRealmClosed);\n        assertFalse(bgRealmChangeResult.get());\n    }\n\n    // Tests if waitForChange doesn't blocks once stopWaitForChange has been called before.\n    @Test\n    public void waitForChange_stopWaitForChangeDisablesWaiting() throws InterruptedException {\n        final CountDownLatch bgRealmOpened = new CountDownLatch(1);\n        final CountDownLatch bgRealmStopped = new CountDownLatch(1);\n        final CountDownLatch bgRealmClosed = new CountDownLatch(1);\n        final AtomicBoolean bgRealmFirstWaitResult = new AtomicBoolean(true);\n        final AtomicBoolean bgRealmSecondWaitResult = new AtomicBoolean(false);\n        final AtomicReference<Realm> bgRealm = new AtomicReference<Realm>();\n\n        // Waits in background.\n        new Thread(new Runnable() {\n            @Override\n            public void run() {\n                Realm realm = Realm.getInstance(realmConfig);\n                bgRealm.set(realm);\n                bgRealmOpened.countDown();\n                bgRealmFirstWaitResult.set(realm.waitForChange());\n                bgRealmStopped.countDown();\n                bgRealmSecondWaitResult.set(realm.waitForChange());\n                realm.close();\n                bgRealmClosed.countDown();\n            }\n        }).start();\n\n        TestHelper.awaitOrFail(bgRealmOpened);\n        bgRealm.get().stopWaitForChange();\n        TestHelper.awaitOrFail(bgRealmStopped);\n        assertFalse(bgRealmFirstWaitResult.get());\n        TestHelper.awaitOrFail(bgRealmClosed);\n        assertFalse(bgRealmSecondWaitResult.get());\n    }\n\n    @Test\n    public void waitForChange_stopWaitForChangeReleasesAllWaitingThreads() throws InterruptedException {\n        final CountDownLatch bgRealmsOpened = new CountDownLatch(2);\n        final CountDownLatch bgRealmsClosed = new CountDownLatch(2);\n        final AtomicBoolean bgRealmFirstWaitResult = new AtomicBoolean(true);\n        final AtomicBoolean bgRealmSecondWaitResult = new AtomicBoolean(false);\n        final AtomicLong bgRealmWaitForChangeResult = new AtomicLong(0);\n        final AtomicReference<Realm> bgRealm = new AtomicReference<Realm>();\n\n        // Waits in background.\n        Thread thread1 = new Thread(new Runnable() {\n            @Override\n            public void run() {\n                Realm realm = Realm.getInstance(realmConfig);\n                bgRealm.set(realm);\n                bgRealmsOpened.countDown();\n                bgRealmFirstWaitResult.set(realm.waitForChange());\n                realm.close();\n                bgRealmsClosed.countDown();\n            }\n        });\n\n        Thread thread2 = new Thread(new Runnable() {\n            @Override\n            public void run() {\n                Realm realm = Realm.getInstance(realmConfig);\n                bgRealmsOpened.countDown();\n                bgRealmSecondWaitResult.set(realm.waitForChange());//In Core 6 calling stopWaitForChange will release all waiting threads\n                // which causes query below to run before `populateTestRealm` happens\n                bgRealmWaitForChangeResult.set(realm.where(AllTypes.class).count());\n                realm.close();\n                bgRealmsClosed.countDown();\n            }\n        });\n        thread1.start();\n        thread2.start();\n\n        TestHelper.awaitOrFail(bgRealmsOpened);\n        bgRealm.get().stopWaitForChange();\n        // Waits for Thread 2 to wait.\n        Thread.sleep(500);\n        populateTestRealm();\n        TestHelper.awaitOrFail(bgRealmsClosed);\n        assertFalse(bgRealmFirstWaitResult.get());\n        assertFalse(bgRealmSecondWaitResult.get());\n        assertEquals(0, bgRealmWaitForChangeResult.get());\n    }\n\n    // Checks if waitForChange() does not respond to Thread.interrupt().\n    @Test\n    public void waitForChange_interruptingThread() throws InterruptedException {\n        final CountDownLatch bgRealmOpened = new CountDownLatch(1);\n        final CountDownLatch bgRealmClosed = new CountDownLatch(1);\n        final AtomicReference<Boolean> bgRealmWaitResult = new AtomicReference<Boolean>();\n        final AtomicReference<Realm> bgRealm = new AtomicReference<Realm>();\n\n        // Waits in background.\n        Thread thread = new Thread(new Runnable() {\n            @Override\n            public void run() {\n                Realm realm = Realm.getInstance(realmConfig);\n                bgRealm.set(realm);\n                bgRealmOpened.countDown();\n                bgRealmWaitResult.set(realm.waitForChange());\n                realm.close();\n                bgRealmClosed.countDown();\n            }\n        });\n        thread.start();\n\n        TestHelper.awaitOrFail(bgRealmOpened);\n        // Makes sure background thread goes to wait.\n        Thread.sleep(500);\n        // Interrupting a thread should neither cause any side effect nor terminate the Background Realm from waiting.\n        thread.interrupt();\n        assertTrue(thread.isInterrupted());\n        assertEquals(null, bgRealmWaitResult.get());\n\n        // Now we'll stop realm from waiting.\n        bgRealm.get().stopWaitForChange();\n        TestHelper.awaitOrFail(bgRealmClosed);\n        assertFalse(bgRealmWaitResult.get());\n    }\n\n    @Test\n    public void waitForChange_onLooperThread() throws Throwable {\n        final CountDownLatch bgRealmClosed = new CountDownLatch(1);\n\n        Thread thread = new Thread(new Runnable() {\n            @Override\n            public void run() {\n                Looper.prepare();\n                Realm realm = Realm.getInstance(realmConfig);\n                try {\n                    realm.waitForChange();\n                    fail();\n                } catch (IllegalStateException ignored) {\n                } finally {\n                    realm.close();\n                    bgRealmClosed.countDown();\n                }\n            }\n        });\n        thread.start();\n\n        TestHelper.awaitOrFail(bgRealmClosed);\n    }\n\n    // Cannot wait inside of a transaction.\n    @Test(expected = IllegalStateException.class)\n    public void waitForChange_illegalWaitInsideTransaction() {\n        realm.beginTransaction();\n        realm.waitForChange();\n    }\n\n    @Test\n    public void waitForChange_stopWaitingOnClosedRealmThrows() throws InterruptedException {\n        final CountDownLatch bgRealmClosed = new CountDownLatch(1);\n        final AtomicReference<Realm> bgRealm = new AtomicReference<Realm>();\n\n        Thread thread = new Thread(new Runnable() {\n            @Override\n            public void run() {\n                Realm realm = Realm.getInstance(realmConfig);\n                bgRealm.set(realm);\n                realm.close();\n                bgRealmClosed.countDown();\n            }\n        });\n        thread.start();\n\n        TestHelper.awaitOrFail(bgRealmClosed);\n        try {\n            bgRealm.get().stopWaitForChange();\n            fail(\"Cannot stop a closed Realm from waiting\");\n        } catch (IllegalStateException expected) {\n        }\n    }\n\n    // waitForChange & stopWaitForChange within a simple Thread wrapper.\n    @Test\n    public void waitForChange_runWithRealmThread() throws InterruptedException {\n        final CountDownLatch bgRealmStarted = new CountDownLatch(1);\n        final CountDownLatch bgRealmFished = new CountDownLatch(1);\n        final AtomicBoolean bgRealmChangeResult = new AtomicBoolean(false);\n        final AtomicLong bgRealmResultSize = new AtomicLong(0);\n\n        RealmThread thread = new RealmThread(realmConfig, new RealmThread.RealmRunnable() {\n            @Override\n            public void run(Realm realm) {\n                bgRealmStarted.countDown();\n                bgRealmChangeResult.set(realm.waitForChange());\n                bgRealmResultSize.set(realm.where(AllTypes.class).count());\n                realm.close();\n                bgRealmFished.countDown();\n            }\n        });\n        thread.start();\n\n        TestHelper.awaitOrFail(bgRealmStarted);\n        populateTestRealm();\n        TestHelper.awaitOrFail(bgRealmFished);\n        assertTrue(bgRealmChangeResult.get());\n        assertEquals(TEST_DATA_SIZE, bgRealmResultSize.get());\n    }\n\n    @Test\n    public void waitForChange_endRealmThread() throws InterruptedException {\n        final CountDownLatch bgRealmStarted = new CountDownLatch(1);\n        final CountDownLatch bgRealmFished = new CountDownLatch(1);\n        final AtomicBoolean bgRealmChangeResult = new AtomicBoolean(true);\n\n        RealmThread thread = new RealmThread(realmConfig, new RealmThread.RealmRunnable() {\n            @Override\n            public void run(Realm realm) {\n                bgRealmStarted.countDown();\n                bgRealmChangeResult.set(realm.waitForChange());\n                realm.close();\n                bgRealmFished.countDown();\n            }\n        });\n        thread.start();\n\n        TestHelper.awaitOrFail(bgRealmStarted);\n        thread.end();\n        TestHelper.awaitOrFail(bgRealmFished);\n        assertFalse(bgRealmChangeResult.get());\n    }\n\n    @Test\n    public void getGlobalInstanceCount() {\n        final CountDownLatch bgDone = new CountDownLatch(1);\n\n        final RealmConfiguration config = configFactory.createConfiguration(\"globalCountTest\");\n        assertEquals(0, Realm.getGlobalInstanceCount(config));\n\n        // Opens thread local Realm.\n        Realm realm = Realm.getInstance(config);\n        assertEquals(1, Realm.getGlobalInstanceCount(config));\n\n        Realm realm1 = Realm.getInstance(config);\n        assertEquals(1, Realm.getGlobalInstanceCount(config));\n\n        // Even though each Realm type points to the same Realm on disk, we report them as\n        // multiple global instances\n\n        // Opens thread local DynamicRealm.\n        DynamicRealm dynRealm = DynamicRealm.getInstance(config);\n        assertEquals(2, Realm.getGlobalInstanceCount(config));\n\n        // Create frozen Realms.\n        Realm frozenRealm = realm.freeze();\n        assertTrue(frozenRealm.isFrozen());\n        assertEquals(3, Realm.getGlobalInstanceCount(config));\n\n        DynamicRealm frozenDynamicRealm = dynRealm.freeze();\n        assertTrue(frozenDynamicRealm.isFrozen());\n        assertEquals(4, Realm.getGlobalInstanceCount(config));\n\n        // Opens Realm in another thread.\n        new Thread(new Runnable() {\n            @Override\n            public void run() {\n                Realm realm = Realm.getInstance(config);\n                assertEquals(5, Realm.getGlobalInstanceCount(config));\n                realm.close();\n                assertEquals(4, Realm.getGlobalInstanceCount(config));\n                bgDone.countDown();\n            }\n        }).start();\n\n        TestHelper.awaitOrFail(bgDone);\n        dynRealm.close();\n        assertEquals(3, Realm.getGlobalInstanceCount(config));\n        realm.close();\n        realm1.close(); // Fully closing the live Realm also closes all frozen Realms\n        assertEquals(0, Realm.getGlobalInstanceCount(config));\n        assertTrue(frozenRealm.isClosed());\n        assertTrue(frozenDynamicRealm.isClosed());\n    }\n\n    @Test\n    public void getLocalInstanceCount() {\n        final RealmConfiguration config = configFactory.createConfiguration(\"localInstanceCount\");\n        assertEquals(0, Realm.getLocalInstanceCount(config));\n\n        // Opens thread local Realm.\n        Realm realm = Realm.getInstance(config);\n        assertEquals(1, Realm.getLocalInstanceCount(config));\n\n        // Opens thread local DynamicRealm.\n        DynamicRealm dynRealm = DynamicRealm.getInstance(config);\n        assertEquals(2, Realm.getLocalInstanceCount(config));\n\n        dynRealm.close();\n        assertEquals(1, Realm.getLocalInstanceCount(config));\n        realm.close();\n        assertEquals(0, Realm.getLocalInstanceCount(config));\n    }\n\n    // This is only supported on API 30 and below\n    @Test\n    public void namedPipeDirForExternalStorage() {\n\n        // Test for https://github.com/realm/realm-java/issues/3140\n        realm.close();\n        realm = null;\n\n        final File namedPipeDir = OsSharedRealm.getTemporaryDirectory();\n        assertTrue(namedPipeDir.isDirectory());\n        TestHelper.deleteRecursively(namedPipeDir);\n        //noinspection ResultOfMethodCallIgnored\n        namedPipeDir.mkdirs();\n\n        final File externalFilesDir = context.getExternalFilesDir(null);\n        final RealmConfiguration config = configFactory.createConfigurationBuilder()\n                .directory(externalFilesDir)\n                .name(\"external.realm\")\n                .build();\n        Realm.deleteRealm(config);\n\n        // Test if it works when the namedPipeDir is empty.\n        Realm realmOnExternalStorage = Realm.getInstance(config);\n        realmOnExternalStorage.close();\n\n        assertTrue(namedPipeDir.isDirectory());\n\n        Assume.assumeTrue(\"SELinux is not enforced on this device.\", TestHelper.isSelinuxEnforcing());\n\n        // Only checks the fifo file created by call, since all Realm instances share the same fifo created by\n        // external_commit_helper which might not be created in the newly created dir if there are Realm instances\n        // are not deleted when TestHelper.deleteRecursively(namedPipeDir) called.\n        File[] files = namedPipeDir.listFiles(new FilenameFilter() {\n            @Override\n            public boolean accept(File dir, String name) {\n                return name.matches(\"realm_.*cv\");\n            }\n        });\n        assertEquals(2, files.length);\n\n        // Tests if it works when the namedPipeDir and the named pipe files already exist.\n        realmOnExternalStorage = Realm.getInstance(config);\n        realmOnExternalStorage.close();\n    }\n\n    @Test(expected = IllegalStateException.class)\n    public void getInstanceAsync_nonLooperThreadShouldThrow() {\n        Realm.getInstanceAsync(realmConfig, new Realm.Callback() {\n            @Override\n            public void onSuccess(Realm realm) {\n                fail();\n            }\n        });\n    }\n\n    @Test\n    public void getInstanceAsync_nullConfigShouldThrow() {\n        looperThread.runBlocking(() -> {\n            try {\n                Realm.getInstanceAsync(null, new Realm.Callback() {\n                    @Override\n                    public void onSuccess(Realm realm) {\n                        fail();\n                    }\n                });\n                fail();\n            } catch(IllegalArgumentException ignore) {\n            }\n            looperThread.testComplete();\n        });\n    }\n\n    // Verify that the logic for waiting for the users file dir to be come available isn't totally broken\n    // This is pretty hard to test, so forced to break encapsulation in this case.\n    @Test\n    public void init_waitForFilesDir() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException, IOException {\n        java.lang.reflect.Method m = Realm.class.getDeclaredMethod(\"checkFilesDirAvailable\", Context.class);\n        m.setAccessible(true);\n\n        // A) Check it fails if getFilesDir is never created\n        Context mockContext = mock(Context.class);\n        when(mockContext.getFilesDir()).thenReturn(null);\n\n        try {\n            m.invoke(null, mockContext);\n            fail();\n        } catch (InvocationTargetException e) {\n            assertEquals(IllegalStateException.class, e.getCause().getClass());\n        }\n\n        // B) Check we return if the filesDir becomes available after a while\n        mockContext = mock(Context.class);\n        when(mockContext.getFilesDir()).then(new Answer<File>() {\n            int calls = 0;\n            File userFolder = tmpFolder.newFolder();\n\n            @Override\n            public File answer(InvocationOnMock invocationOnMock) throws Throwable {\n                calls++;\n                return (calls > 5) ? userFolder : null; // Start returning the correct folder after 5 attempts\n            }\n        });\n\n        assertNull(m.invoke(null, mockContext));\n    }\n\n    @Test\n    public void refresh_triggerNotifications() {\n        looperThread.runBlocking(() -> {\n            final CountDownLatch bgThreadDone = new CountDownLatch(1);\n            final AtomicBoolean listenerCalled = new AtomicBoolean(false);\n            final Realm realm = Realm.getInstance((realmConfig));\n            looperThread.closeAfterTest(realm);\n            RealmResults<AllTypes> results = realm.where(AllTypes.class).findAll();\n            assertEquals(0, results.size());\n            results.addChangeListener(new RealmChangeListener<RealmResults<AllTypes>>() {\n                @Override\n                public void onChange(RealmResults<AllTypes> results) {\n                    assertEquals(1, results.size());\n                    listenerCalled.set(true);\n                }\n            });\n\n            // Advance the Realm on a background while blocking this thread. When we refresh, it should trigger\n            // the listener.\n            new Thread(() -> {\n                Realm realm1 = Realm.getInstance(realmConfig);\n                realm1.beginTransaction();\n                realm1.createObject(AllTypes.class);\n                realm1.commitTransaction();\n                realm1.close();\n                bgThreadDone.countDown();\n            }).start();\n            TestHelper.awaitOrFail(bgThreadDone);\n\n            realm.refresh();\n            assertTrue(listenerCalled.get());\n            looperThread.testComplete();\n        });\n    }\n\n    @Test\n    public void refresh_nonLooperThreadAdvances() {\n        final CountDownLatch bgThreadDone = new CountDownLatch(1);\n        RealmResults<AllTypes> results = realm.where(AllTypes.class).findAll();\n        assertEquals(0, results.size());\n\n        new Thread(new Runnable() {\n            @Override\n            public void run() {\n                Realm realm = Realm.getInstance(RealmTests.this.realm.getConfiguration());\n                realm.beginTransaction();\n                realm.createObject(AllTypes.class);\n                realm.commitTransaction();\n                realm.close();\n                bgThreadDone.countDown();\n            }\n        }).start();\n        TestHelper.awaitOrFail(bgThreadDone);\n\n        realm.refresh();\n        assertEquals(1, results.size());\n    }\n\n    @Test\n    public void refresh_forceSynchronousNotifications() {\n        looperThread.runBlocking(() -> {\n            final CountDownLatch bgThreadDone = new CountDownLatch(1);\n            final AtomicBoolean listenerCalled = new AtomicBoolean(false);\n            final Realm realm = Realm.getInstance((realmConfig));\n            looperThread.closeAfterTest(realm);\n            RealmResults<AllTypes> results = realm.where(AllTypes.class).findAllAsync();\n            results.addChangeListener(new RealmChangeListener<RealmResults<AllTypes>>() {\n                @Override\n                public void onChange(RealmResults<AllTypes> results) {\n                    // Will be forced synchronous\n                    assertEquals(1, results.size());\n                    listenerCalled.set(true);\n                }\n            });\n\n            new Thread(new Runnable() {\n                @Override\n                public void run() {\n                    Realm realm = Realm.getInstance(realmConfig);\n                    realm.beginTransaction();\n                    realm.createObject(AllTypes.class);\n                    realm.commitTransaction();\n                    realm.close();\n                    bgThreadDone.countDown();\n                }\n            }).start();\n            TestHelper.awaitOrFail(bgThreadDone);\n\n            realm.refresh();\n            assertTrue(listenerCalled.get());\n            looperThread.testComplete();\n        });\n    }\n\n    @Test\n    public void refresh_insideTransactionThrows() {\n        realm.beginTransaction();\n        try {\n            realm.refresh();\n            fail();\n        } catch (IllegalStateException ignored) {\n        }\n        realm.cancelTransaction();\n    }\n\n    @Test\n    public void beginTransaction_readOnlyThrows() {\n        RealmConfiguration config = configFactory.createConfigurationBuilder()\n                .name(\"readonly.realm\")\n                .schema(StringOnlyReadOnly.class)\n                .assetFile(\"readonly.realm\")\n                .readOnly()\n                .build();\n        Realm realm = Realm.getInstance(config);\n        try {\n            realm.beginTransaction();\n            fail();\n        } catch (IllegalStateException e) {\n            assertThat(e.getMessage(),\n                    CoreMatchers.containsString(\"Can't perform transactions on read-only Realms.\"));\n        } finally {\n            realm.close();\n        }\n    }\n\n    @Test\n    public void getInstance_wrongSchemaInReadonlyThrows() {\n        RealmConfiguration config = configFactory.createConfigurationBuilder()\n                .name(\"readonly.realm\")\n                .schema(StringOnlyReadOnly.class, AllJavaTypes.class)\n                .assetFile(\"readonly.realm\")\n                .readOnly()\n                .build();\n\n        // This will throw because the Realm doesn't have the correct schema, and a new file cannot be re-created\n        // because it is read only.\n        try {\n            realm = Realm.getInstance(config);\n            fail();\n        } catch (RealmMigrationNeededException ignored) {\n        }\n    }\n\n    // https://github.com/realm/realm-java/issues/5570\n    @Test\n    public void getInstance_migrationExceptionThrows_migrationBlockDefiend_realmInstancesShouldBeClosed() {\n        RealmConfiguration config = configFactory.createConfigurationBuilder()\n                .name(\"readonly.realm\")\n                .schema(StringOnlyReadOnly.class, AllJavaTypes.class)\n                .schemaVersion(2)\n                .assetFile(\"readonly.realm\")\n                .migration(new RealmMigration() {\n                    @Override\n                    public void migrate(DynamicRealm realm, long oldVersion, long newVersion) {\n                    }\n                })\n                .build();\n\n        try {\n            realm = Realm.getInstance(config);\n            fail();\n        } catch (RealmMigrationNeededException ignored) {\n            // No Realm instance should be opened at this time.\n            Realm.deleteRealm(config);\n        }\n    }\n\n    @Test\n    public void hittingMaxNumberOfVersionsThrows() {\n        RealmConfiguration config = configFactory.createConfigurationBuilder()\n                .name(\"versions-test.realm\")\n                .maxNumberOfActiveVersions(1)\n                .build();\n        Realm realm = Realm.getInstance(config);\n        try {\n            realm.beginTransaction();\n            fail();\n        } catch (IllegalStateException e) {\n            assertTrue(e.getMessage().contains(\"Number of active versions (2) in the Realm exceeded the limit of 1\"));\n        } finally {\n            realm.close();\n        }\n    }\n\n    // Test for https://github.com/realm/realm-java/issues/6977\n    @Test\n    public void numberOfVersionsDecreasedOnClose() {\n        realm.close();\n        looperThread.runBlocking(() -> {\n            int count = 50;\n            final CountDownLatch bgThreadDoneLatch = new CountDownLatch(count);\n\n            RealmConfiguration config = configFactory.createConfigurationBuilder()\n                    // The multiple embedded threads seems to cause trouble with factory's directory setting\n                    .directory(context.getFilesDir())\n                    .name(\"versions-test.realm\")\n                    .maxNumberOfActiveVersions(5)\n                    .build();\n            Realm.deleteRealm(config);\n\n            // Synchronizes between change listener and Background writes so they operate in lockstep.\n            AtomicReference<CountDownLatch> guard = new AtomicReference<>(new CountDownLatch(1));\n\n            Realm realm = Realm.getInstance(config);\n            looperThread.closeAfterTest(realm);\n            realm.addChangeListener(callbackRealm -> {\n                // This test catches a bug that caused ObjectStore to pin Realm versions\n                // if a TableView was created inside a change notification and no elements\n                // in the TableView was accessed.\n                RealmResults<AllJavaTypes> query = realm.where(AllJavaTypes.class).findAll();\n                guard.get().countDown();\n                bgThreadDoneLatch.countDown();\n                if (bgThreadDoneLatch.getCount() == 0) {\n                    looperThread.testComplete();\n                }\n            });\n\n            // Write a number of transactions in the background in a serial manner\n            // in order to create a number of different versions. Done in serial\n            // to allow the LooperThread to catch up.\n            new Thread(() -> {\n                for (int i = 0; i < count; i++) {\n                    Thread t = new Thread() {\n                        @Override\n                        public void run() {\n                            Realm realm = Realm.getInstance(config);\n                            realm.executeTransaction(bgRealm -> { });\n                            realm.close();\n                        }\n                    };\n                    t.start();\n                    try {\n                        t.join();\n                        TestHelper.awaitOrFail(guard.get());\n                        guard.set(new CountDownLatch(1));\n                    } catch (InterruptedException e) {\n                        throw new RuntimeException(e);\n                    }\n                }\n            }).start();\n        });\n    }\n\n    // Test for https://github.com/realm/realm-java/issues/6152\n    @Test\n    @Ignore(\"See https://github.com/realm/realm-java/issues/7628\")\n    public void encryption_stressTest() {\n        realm.close();\n        looperThread.runBlocking(() -> {\n            final int WRITER_TRANSACTIONS = 50;\n            final int TEST_OBJECTS = 100_000;\n            final int MAX_STRING_LENGTH = 1000;\n            final AtomicInteger id = new AtomicInteger(0);\n            long seed = System.nanoTime();\n            Random random = new Random(seed);\n\n            RealmConfiguration config = configFactory.createConfigurationBuilder()\n                    .name(\"encryption-stress-test.realm\")\n                    .encryptionKey(TestHelper.getRandomKey(seed))\n                    .build();\n            Realm.deleteRealm(config);\n\n            Thread t = new Thread(new Runnable() {\n                @Override\n                public void run() {\n                    Realm realm = Realm.getInstance(config);\n                    for (int i = 0; i < WRITER_TRANSACTIONS; i++) {\n                        realm.executeTransaction(r -> {\n                            for (int j = 0; j < (TEST_OBJECTS / WRITER_TRANSACTIONS); j++) {\n                                AllJavaTypes obj = new AllJavaTypes(id.incrementAndGet());\n                                obj.setFieldString(TestHelper.getRandomString(random.nextInt(MAX_STRING_LENGTH)));\n                                r.insert(obj);\n                            }\n                        });\n                    }\n                    realm.close();\n                }\n            });\n            t.start();\n\n            Realm realm = Realm.getInstance(config);\n            looperThread.closeAfterTest(realm);\n            RealmResults<AllJavaTypes> results = realm.where(AllJavaTypes.class).findAllAsync();\n            looperThread.keepStrongReference(results);\n            results.addChangeListener(new OrderedRealmCollectionChangeListener<RealmResults<AllJavaTypes>>() {\n                @Override\n                public void onChange(RealmResults<AllJavaTypes> results, OrderedCollectionChangeSet changeSet) {\n                    for (AllJavaTypes obj : results) {\n                        String s = obj.getFieldString();\n                    }\n\n                    if (results.size() == TEST_OBJECTS) {\n                        try {\n                            t.join(5000);\n                        } catch (InterruptedException e) {\n                            fail(\"workerthread failed to finish in time.\");\n                        }\n                        looperThread.testComplete();\n                    }\n                }\n            });\n        });\n    }\n\n    @Test\n    public void getNumberOfActiveVersions() throws InterruptedException {\n        CountDownLatch bgWritesCompleted = new CountDownLatch(1);\n        CountDownLatch closeBgRealm = new CountDownLatch(1);\n        assertEquals(2, realm.getNumberOfActiveVersions());\n        Thread t = new Thread(() -> {\n            Realm bgRealm = Realm.getInstance(realmConfig);\n            assertEquals(2, bgRealm.getNumberOfActiveVersions());\n            for (int i = 0; i < 5; i++) {\n                bgRealm.executeTransaction(r -> { /* empty */ });\n            }\n            assertEquals(3, bgRealm.getNumberOfActiveVersions());\n            bgWritesCompleted.countDown();\n            TestHelper.awaitOrFail(closeBgRealm);\n            bgRealm.close();\n        });\n        t.start();\n        TestHelper.awaitOrFail(bgWritesCompleted);\n        assertEquals(3, realm.getNumberOfActiveVersions());\n        closeBgRealm.countDown();\n        t.join();\n        realm.refresh(); // Release old versions for GC\n        realm.beginTransaction();\n        realm.commitTransaction(); // Actually release the versions\n        assertEquals(2, realm.getNumberOfActiveVersions());\n        realm.close();\n        try {\n            realm.getNumberOfActiveVersions();\n            fail();\n        } catch (IllegalStateException ignore) {\n        }\n    }\n\n    @Test\n    public void getCachedInstanceDoNotTriggerStrictMode() {\n        StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()\n            .detectAll()\n            .penaltyLog()\n            .penaltyDeath()\n            .build());\n        try {\n            Realm.getInstance(realmConfig).close();\n        } finally {\n            StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()\n                    .permitAll()\n                    .build());\n        }\n    }\n\n    @Test\n    public void getCachedInstanceFromOtherThreadDoNotTriggerStrictMode() throws InterruptedException {\n        StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()\n                .detectAll()\n                .penaltyLog()\n                .penaltyDeath()\n                .build());\n        try {\n            Thread t = new Thread(() -> Realm.getInstance(realmConfig).close());\n            t.start();\n            t.join();\n        } finally {\n            StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()\n                    .permitAll()\n                    .build());\n        }\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/RunTestInLooperThreadLifeCycleTest.java",
    "content": "/*\n * Copyright 2017 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\npackage io.realm;\n\nimport androidx.test.ext.junit.runners.AndroidJUnit4;\n\nimport org.junit.After;\nimport org.junit.Before;\nimport org.junit.Rule;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\n\nimport java.io.Closeable;\nimport java.io.IOException;\nimport java.util.concurrent.atomic.AtomicBoolean;\n\nimport io.realm.rule.RunInLooperThread;\nimport io.realm.rule.RunTestInLooperThread;\n\nimport static org.junit.Assert.assertFalse;\nimport static org.junit.Assert.assertTrue;\n\n\n/**\n * Meta test. Checking the lifecycle of @RunTestInLooperThreadTest does the right thing.\n *\n * Current order is:\n * - @RunTestInLooperThread(before = <classRef>)\n * - @Before()\n * - @RunTestInLooperThread/@Test\n * - @After : This is called when exiting the test method. Warning: Looper test is still running.\n * - looperThread.runAfterTest(Runnable) : This is called when `testComplete()` is called. This can\n *   be both before and after `@After` has run.\n */\n\n@RunWith(AndroidJUnit4.class)\npublic class RunTestInLooperThreadLifeCycleTest {\n\n    @Rule\n    public final RunInLooperThread looperThread = new RunInLooperThread();\n\n    private static AtomicBoolean beforeCalled = new AtomicBoolean(false);\n    private static AtomicBoolean afterCalled = new AtomicBoolean(false);\n    private static AtomicBoolean testExited = new AtomicBoolean(false);\n    private static AtomicBoolean beforeRunnableCalled = new AtomicBoolean(false);\n    private static AtomicBoolean afterRunnableCalled = new AtomicBoolean(false);\n    private static AtomicBoolean closableClosed = new AtomicBoolean(false);\n\n    @Before\n    public void before() {\n        assertTrue(beforeCalled.compareAndSet(false, true));\n        assertTrue(beforeRunnableCalled.get());\n\n        looperThread.closeAfterTest(new Closeable() {\n            @Override\n            public void close() throws IOException {\n                assertTrue(testExited.get());\n                assertFalse(afterRunnableCalled.get());\n                assertTrue(closableClosed.compareAndSet(false, true));\n            }\n        });\n        looperThread.runAfterTest(new Runnable() {\n            @Override\n            public void run() {\n                assertTrue(testExited.get());\n                assertTrue(afterRunnableCalled.compareAndSet(false, true));\n                assertTrue(looperThread.isTestComplete());\n            }\n        });\n;    }\n\n    @After\n    public void after() {\n        assertTrue(afterCalled.compareAndSet(false, true));\n        assertTrue(testExited.get());\n        assertFalse(looperThread.isTestComplete()); // Beware of this. Use `runAfterTest` for destroying resources used.\n    }\n\n    @Test\n    @RunTestInLooperThread(before = PrepareLooperTest.class)\n    public void looperTest() {\n        looperThread.postRunnable(new Runnable() {\n            @Override\n            public void run() {\n                assertTrue(afterCalled.get());\n                assertFalse(looperThread.isTestComplete());\n                looperThread.testComplete();\n            }\n        });\n        assertTrue(testExited.compareAndSet(false, true));\n    }\n\n    public static class PrepareLooperTest implements RunInLooperThread.RunnableBefore {\n        @Override\n        public void run(RealmConfiguration realmConfig) {\n            assertTrue(beforeRunnableCalled.compareAndSet(false, true));\n            assertFalse(beforeCalled.get());\n        }\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/RxJavaTests.java",
    "content": "/*\n * Copyright 2015 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\npackage io.realm;\n\nimport android.os.SystemClock;\nimport androidx.test.ext.junit.runners.AndroidJUnit4;\n\nimport org.junit.Before;\nimport org.junit.Rule;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\n\nimport java.util.concurrent.atomic.AtomicInteger;\nimport java.util.concurrent.atomic.AtomicLong;\n\nimport io.reactivex.Flowable;\nimport io.reactivex.disposables.Disposable;\nimport io.reactivex.functions.Consumer;\nimport io.reactivex.schedulers.Schedulers;\nimport io.realm.entities.AllJavaTypes;\nimport io.realm.entities.AllTypes;\nimport io.realm.entities.CyclicType;\nimport io.realm.entities.Dog;\nimport io.realm.internal.util.Pair;\nimport io.realm.log.RealmLog;\nimport io.realm.rule.RunInLooperThread;\nimport io.realm.rule.RunTestInLooperThread;\n\nimport static org.junit.Assert.assertEquals;\nimport static org.junit.Assert.assertFalse;\nimport static org.junit.Assert.assertNotEquals;\nimport static org.junit.Assert.assertNotNull;\nimport static org.junit.Assert.assertNull;\nimport static org.junit.Assert.assertTrue;\nimport static org.junit.Assert.fail;\n\n/**\n * This class contains tests for the RxJava integration.\n *\n * Note that all tests must be run using @RunTestInLooperThread due to how the Observables\n * are constructed.\n */\n@RunWith(AndroidJUnit4.class)\npublic class RxJavaTests {\n\n    @Rule\n    public final RunInLooperThread looperThread = new RunInLooperThread();\n\n    private Realm realm;\n    private Disposable subscription;\n\n    @Before\n    public void setUp() {\n        // For non-LooperThread tests.\n        realm = looperThread.getRealm();\n        looperThread.runAfterTest(() -> {\n            if (subscription != null && !subscription.isDisposed()) {\n                subscription.dispose();\n                realm.close();\n\n\n\n                // Wait for Realm Observables to fully close\n                while (Realm.getGlobalInstanceCount(realm.configuration) > 0) {\n                    RealmLog.error(\"Counter: \" + Realm.getGlobalInstanceCount(realm.configuration));\n                    SystemClock.sleep(10);\n                }\n            }\n        });\n    }\n\n    private void disposeSuccessfulTest(BaseRealm testRealm) {\n        looperThread.postRunnable(() -> {\n            if (subscription != null) {\n                subscription.dispose();\n            }\n            if (!testRealm.getConfiguration().equals(realm.getConfiguration())) {\n                throw new IllegalStateException(\"This method only works for Realms with the same configuration as the looper Realm\");\n            }\n            testRealm.close();\n            if (!realm.equals(testRealm)) {\n                realm.close();\n            }\n            looperThread.postRunnable(new Runnable() {\n                @Override\n                public void run() {\n                    // Wait for Subscription to dispose of external resources\n                    if (Realm.getGlobalInstanceCount(testRealm.getConfiguration()) == 0) {\n                        looperThread.testComplete();\n                    } else {\n                        RealmLog.error(\"\" + Realm.getGlobalInstanceCount(testRealm.getConfiguration()));\n                        looperThread.postRunnable(this);\n                    }\n                }\n            });\n        });\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void realmObject_emittedOnSubscribe() {\n        realm.beginTransaction();\n        final AllJavaTypes obj = realm.createObject(AllJavaTypes.class, 42);\n        realm.commitTransaction();\n\n        subscription = obj.<AllJavaTypes>asFlowable().subscribe(rxObject -> {\n            assertTrue(rxObject.isFrozen());\n            assertNotEquals(rxObject, obj); // Frozen objects are not equal to their live counter parts.\n            assertEquals(rxObject.getFieldId(), obj.getFieldId());\n            disposeSuccessfulTest(realm);\n        });\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void realmObject_emitChangesetOnSubscribe() {\n        realm.beginTransaction();\n        final AllJavaTypes obj = realm.createObject(AllJavaTypes.class, 42);\n        realm.commitTransaction();\n\n        subscription = obj.<AllJavaTypes>asChangesetObservable().subscribe(change -> {\n            assertTrue(change.getObject().isFrozen());\n            assertEquals(change.getObject().getFieldId(), obj.getFieldId());\n            assertNull(change.getChangeset());\n            disposeSuccessfulTest(realm);\n        });\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void dynamicRealmObject_emitChangesetOnSubscribe() {\n        DynamicRealm dynamicRealm = DynamicRealm.getInstance(looperThread.getConfiguration());\n        dynamicRealm.beginTransaction();\n        final DynamicRealmObject obj = dynamicRealm.createObject(AllJavaTypes.CLASS_NAME, 42);\n        dynamicRealm.commitTransaction();\n\n        subscription = obj.<DynamicRealmObject>asChangesetObservable()\n                .subscribe(change -> {\n            assertTrue(change.getObject().isFrozen());\n            assertEquals(change.getObject().getLong(AllJavaTypes.FIELD_ID), obj.getLong(AllJavaTypes.FIELD_ID));\n            assertNull(change.getChangeset());\n            disposeSuccessfulTest(dynamicRealm);\n        });\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void realmObject_emittedOnUpdate() {\n        realm.beginTransaction();\n        final AllTypes obj = realm.createObject(AllTypes.class);\n        realm.commitTransaction();\n\n        subscription = obj.<AllTypes>asFlowable().subscribe(rxObject -> {\n            assertTrue(rxObject.isFrozen());\n            if (rxObject.isLoaded() && rxObject.getColumnLong() == 0) {\n                realm.beginTransaction();\n                obj.setColumnLong(1);\n                realm.commitTransaction();\n            } else if (rxObject.getColumnLong() == 1) {\n                disposeSuccessfulTest(realm);\n            }\n        });\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void realmObject_emittedChangesetOnUpdate() {\n        realm.beginTransaction();\n        final AllTypes obj = realm.createObject(AllTypes.class);\n        realm.commitTransaction();\n\n        subscription = obj.<AllTypes>asChangesetObservable().subscribe(change -> {\n            AllTypes rxObject = change.getObject();\n            assertTrue(rxObject.isFrozen());\n            if (rxObject.getColumnLong() == 0) {\n                realm.beginTransaction();\n                obj.setColumnLong(1);\n                realm.commitTransaction();\n            } else if (rxObject.getColumnLong() == 1) {\n                assertNotNull(change.getChangeset());\n                assertTrue(change.getChangeset().isFieldChanged(AllTypes.FIELD_LONG));\n                disposeSuccessfulTest(realm);\n            }\n        });\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void dynamicRealmObject_emittedChangesetOnUpdate() {\n        DynamicRealm dynamicRealm = DynamicRealm.getInstance(looperThread.getConfiguration());\n\n        dynamicRealm.beginTransaction();\n        final DynamicRealmObject obj = dynamicRealm.createObject(AllTypes.CLASS_NAME);\n        dynamicRealm.commitTransaction();\n\n        subscription = obj.<DynamicRealmObject>asChangesetObservable().subscribe(change -> {\n            DynamicRealmObject rxObject = change.getObject();\n            assertTrue(rxObject.isFrozen());\n            if (rxObject.getLong(AllTypes.FIELD_LONG) == 0) {\n                dynamicRealm.beginTransaction();\n                obj.setLong(AllTypes.FIELD_LONG, 1);\n                dynamicRealm.commitTransaction();\n            } else if (rxObject.getLong(AllTypes.FIELD_LONG) == 1) {\n                assertNotNull(change.getChangeset());\n                assertTrue(change.getChangeset().isFieldChanged(AllTypes.FIELD_LONG));\n                disposeSuccessfulTest(dynamicRealm);\n            }\n        });\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void findFirst_emittedOnSubscribe() {\n        realm.beginTransaction();\n        realm.createObject(AllTypes.class).setColumnLong(42);\n        realm.commitTransaction();\n\n        subscription = realm.where(AllTypes.class).equalTo(AllTypes.FIELD_LONG, 42).findFirst().<AllTypes>asFlowable()\n                .subscribe(rxObject -> {\n                    assertTrue(rxObject.isFrozen());\n                    assertEquals(42, rxObject.getColumnLong());\n                    disposeSuccessfulTest(realm);\n                });\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void findFirstAsync_emittedOnSubscribe() {\n        realm.beginTransaction();\n        realm.createObject(AllTypes.class).setColumnLong(42);\n        realm.commitTransaction();\n\n        final AllTypes asyncObj = realm.where(AllTypes.class).findFirstAsync();\n        subscription = asyncObj.<AllTypes>asFlowable().subscribe(rxObject -> {\n            assertTrue(rxObject.isFrozen());\n            // Because the subscription is run asynchronously. There is a chance\n            // the query resolved before the subscription triggers.\n            // This means it is not deterministic what state is first emitted here.\n            // It can either be a fully loaded object or one that is still loading.\n            if (rxObject.isLoaded()) {\n                assertTrue(rxObject.isValid());\n                assertEquals(42, rxObject.getColumnLong());\n            } else {\n                assertFalse(rxObject.isValid());\n            }\n            disposeSuccessfulTest(realm);\n        });\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void findFirstAsync_emittedOnUpdate() {\n        realm.beginTransaction();\n        realm.createObject(AllTypes.class).setColumnLong(1);\n        realm.commitTransaction();\n\n        subscription = realm.where(AllTypes.class).findFirstAsync().<AllTypes>asFlowable().subscribe(rxObject -> {\n            assertTrue(rxObject.isFrozen());\n            if (!rxObject.isLoaded()) return;\n\n            if (rxObject.getColumnLong() == 1) {\n                realm.executeTransactionAsync(r -> r.where(AllTypes.class).findFirst().setColumnLong(42));\n            } else if (rxObject.getColumnLong() == 42) {\n                disposeSuccessfulTest(realm);\n            }\n        });\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void findFirstAsync_emittedOnDelete() {\n        realm.beginTransaction();\n        realm.createObject(AllTypes.class);\n        realm.commitTransaction();\n\n        subscription = realm.where(AllTypes.class).findFirstAsync().<AllTypes>asFlowable().subscribe(rxObject -> {\n            assertTrue(rxObject.isFrozen());\n            if (!rxObject.isLoaded()) {\n                //noinspection UnnecessaryReturnStatement\n                return;\n            } else if (rxObject.isValid()) {\n                realm.executeTransactionAsync(r -> r.delete(AllTypes.class));\n            } else if (!rxObject.isValid()) {\n                disposeSuccessfulTest(realm);\n            }\n        });\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void realmResults_emittedOnSubscribe() {\n        final RealmResults<AllTypes> results = realm.where(AllTypes.class).findAll();\n        subscription = results.asFlowable().subscribe(rxResults -> {\n            assertTrue(rxResults.isFrozen());\n            disposeSuccessfulTest(realm);\n        });\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void realmResults_emittedChangesetOnSubscribe() {\n        final RealmResults<AllTypes> results = realm.where(AllTypes.class).findAll();\n        subscription = results.asChangesetObservable().subscribe(change -> {\n            RealmResults<AllTypes> rxResults = change.getCollection();\n            assertTrue(rxResults.isFrozen());\n            assertEquals(results, rxResults);\n            disposeSuccessfulTest(realm);\n        });\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void realmList_emittedOnSubscribe() {\n        realm.beginTransaction();\n        final RealmList<Dog> list = realm.createObject(AllTypes.class).getColumnRealmList();\n        list.add(new Dog(\"dog\"));\n        realm.commitTransaction();\n\n        subscription = list.asFlowable().subscribe(rxList -> {\n            assertTrue(rxList.isFrozen());\n            assertEquals(1, rxList.size());\n            assertEquals(\"dog\", rxList.first().getName());\n            disposeSuccessfulTest(realm);\n        });\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void realmList_emittedChangesetOnSubscribe() {\n        realm.beginTransaction();\n        final RealmList<Dog> list = realm.createObject(AllTypes.class).getColumnRealmList();\n        list.add(new Dog(\"dog\"));\n        realm.commitTransaction();\n\n        subscription = list.asChangesetObservable().subscribe(change -> {\n            RealmList<Dog> rxList = change.getCollection();\n            assertTrue(rxList.isFrozen());\n            assertEquals(1, rxList.size());\n            assertEquals(\"dog\", rxList.first().getName());\n            assertNull(change.getChangeset());\n            disposeSuccessfulTest(realm);\n        });\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void dynamicRealmResults_emittedOnSubscribe() {\n        final DynamicRealm dynamicRealm = DynamicRealm.getInstance(looperThread.getConfiguration());\n        final RealmResults<DynamicRealmObject> results = dynamicRealm.where(AllTypes.CLASS_NAME).findAll();\n        subscription = results.asFlowable().subscribe(rxResults -> {\n            assertTrue(rxResults.isFrozen());\n            assertTrue(rxResults.equals(results));\n            disposeSuccessfulTest(dynamicRealm);\n        });\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void dynamicRealmResults_emittedChangesetOnSubscribe() {\n        final DynamicRealm dynamicRealm = DynamicRealm.getInstance(realm.getConfiguration());\n        final RealmResults<DynamicRealmObject> results = dynamicRealm.where(AllTypes.CLASS_NAME).findAll();\n        subscription = results.asChangesetObservable().subscribe(change -> {\n            assertTrue(change.getCollection().isFrozen());\n            assertEquals(results, change.getCollection());\n            assertNull(change.getChangeset());\n            disposeSuccessfulTest(dynamicRealm);\n        });\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void realmResults_emittedOnUpdate() {\n        RealmResults<AllTypes> results = realm.where(AllTypes.class).findAll();\n\n        subscription = results.asFlowable().subscribe(rxResults -> {\n            assertTrue(rxResults.isFrozen());\n            if (rxResults.size() == 1) {\n                disposeSuccessfulTest(realm);\n            }\n        });\n\n        realm.beginTransaction();\n        realm.createObject(AllTypes.class);\n        realm.commitTransaction();\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void realmResults_emittedChangesetOnUpdate() {\n        RealmResults<AllTypes> results = realm.where(AllTypes.class).findAll();\n\n        subscription = results.asChangesetObservable().subscribe(change -> {\n            RealmResults<AllTypes> rxResults = change.getCollection();\n            assertTrue(rxResults.isFrozen());\n            if (rxResults.isEmpty()) {\n                realm.executeTransaction(r -> r.createObject(AllTypes.class));\n            } else if (rxResults.size() == 1) {\n                assertEquals(1, change.getChangeset().getInsertions().length);\n                disposeSuccessfulTest(realm);\n            }\n        });\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void realmList_emittedOnUpdate() {\n        realm.beginTransaction();\n        final RealmList<Dog> list = realm.createObject(AllTypes.class).getColumnRealmList();\n        realm.commitTransaction();\n\n        subscription = list.asFlowable().subscribe(rxList -> {\n            assertTrue(rxList.isFrozen());\n            if (rxList.isEmpty()) {\n                realm.executeTransaction(r -> list.add(new Dog()));\n            } else {\n                assertEquals(1, list.size());\n                disposeSuccessfulTest(realm);\n            }\n        });\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void realmList_emittedChangesetOnUpdate() {\n        realm.beginTransaction();\n        final RealmList<Dog> list = realm.createObject(AllTypes.class).getColumnRealmList();\n        realm.commitTransaction();\n\n        subscription = list.asChangesetObservable().subscribe(change -> {\n            RealmList<Dog> rxList = change.getCollection();\n            assertTrue(rxList.isFrozen());\n            if (rxList.isLoaded() && rxList.size() == 0) {\n                realm.beginTransaction();\n                list.add(new Dog());\n                realm.commitTransaction();\n            } else if (rxList.size() == 1) {\n                assertEquals(1, change.getChangeset().getInsertions().length);\n                disposeSuccessfulTest(realm);\n            }\n        });\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void realmList_parentDeletionCompleteFlowable() {\n        realm.beginTransaction();\n        final AllTypes parent = realm.createObject(AllTypes.class);\n        final RealmList<Dog> list = parent.getColumnRealmList();\n        list.add(new Dog(\"Fido\"));\n        realm.commitTransaction();\n        looperThread.keepStrongReference(parent);\n\n        // We should only emit valid lists. If the parent of the list is invalidated\n        // it should close the stream gracefully resulting in onComplete being called.\n        subscription = list.asFlowable().subscribe(\n                change -> { assertTrue(change.isValid()); },\n                error -> { fail(error.toString()); },\n                () -> {\n                    // Deleting the parent will gracefully close the stream\n                    disposeSuccessfulTest(realm);\n                });\n\n        looperThread.postRunnable(() -> {\n            realm.beginTransaction();\n            parent.deleteFromRealm();\n            realm.commitTransaction();\n        });\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void realmList_parentDeletionCompleteObservable() {\n        realm.beginTransaction();\n        final AllTypes parent = realm.createObject(AllTypes.class);\n        final RealmList<Dog> list = parent.getColumnRealmList();\n        list.add(new Dog(\"Fido\"));\n        realm.commitTransaction();\n        looperThread.keepStrongReference(parent);\n\n        // We should only emit valid lists. If the parent of the list is invalidated\n        // it should close the stream gracefully resulting in onComplete being called.\n        subscription = list.asChangesetObservable().subscribe(\n                change -> { assertTrue(change.getCollection().isValid()); },\n                error -> { fail(error.toString()); },\n                () -> {\n                    // Deleting the parent will gracefully close the stream\n                    disposeSuccessfulTest(realm);\n                });\n\n        looperThread.postRunnable(() -> {\n            realm.beginTransaction();\n            parent.deleteFromRealm();\n            realm.commitTransaction();\n        });\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void dynamicRealmList_parentDeletionCompleteFlowable() {\n        DynamicRealm dynamicRealm = DynamicRealm.getInstance(looperThread.getConfiguration());\n\n        dynamicRealm.beginTransaction();\n        final DynamicRealmObject parent = dynamicRealm.createObject(AllTypes.CLASS_NAME);\n        final RealmList<DynamicRealmObject> list = parent.getList(AllTypes.FIELD_REALMLIST);\n        list.add(dynamicRealm.createObject(Dog.CLASS_NAME));\n        dynamicRealm.commitTransaction();\n        looperThread.keepStrongReference(parent);\n\n        // We should only emit valid lists. If the parent of the list is invalidated\n        // it should close the stream gracefully resulting in onComplete being called.\n        subscription = list.asFlowable().subscribe(\n                change -> { assertTrue(change.isValid()); },\n                error -> { fail(error.toString()); },\n                () -> {\n                    // Deleting the parent will gracefully close the stream\n                    disposeSuccessfulTest(dynamicRealm);\n                });\n\n        looperThread.postRunnable(() -> {\n            dynamicRealm.beginTransaction();\n            parent.deleteFromRealm();\n            dynamicRealm.commitTransaction();\n        });\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void dynamicRealmList_parentDeletionCompleteObservable() {\n        DynamicRealm dynamicRealm = DynamicRealm.getInstance(looperThread.getConfiguration());\n\n        dynamicRealm.beginTransaction();\n        final DynamicRealmObject parent = dynamicRealm.createObject(AllTypes.CLASS_NAME);\n        final RealmList<DynamicRealmObject> list = parent.getList(AllTypes.FIELD_REALMLIST);\n        list.add(dynamicRealm.createObject(Dog.CLASS_NAME));\n        dynamicRealm.commitTransaction();\n        looperThread.keepStrongReference(parent);\n\n        // We should only emit valid lists. If the parent of the list is invalidated\n        // it should close the stream gracefully resulting in onComplete being called.\n        subscription = list.asChangesetObservable().subscribe(\n                change -> { assertTrue(change.getCollection().isValid()); },\n                error -> { fail(error.toString()); },\n                () -> {\n                    // Deleting the parent will gracefully close the stream.\n                    disposeSuccessfulTest(dynamicRealm);\n                });\n\n        looperThread.postRunnable(() -> {\n            dynamicRealm.beginTransaction();\n            parent.deleteFromRealm();\n            dynamicRealm.commitTransaction();\n        });\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void dynamicRealmResults_emittedOnUpdate() {\n        final DynamicRealm dynamicRealm = DynamicRealm.getInstance(looperThread.getConfiguration());\n        RealmResults<DynamicRealmObject> results = dynamicRealm.where(AllTypes.CLASS_NAME).findAll();\n\n        subscription = results.asFlowable().subscribe(rxResults -> {\n            assertTrue(rxResults.isFrozen());\n            if (rxResults.isLoaded() && rxResults.size() == 1) {\n                disposeSuccessfulTest(dynamicRealm);\n            }\n        });\n\n        dynamicRealm.beginTransaction();\n        dynamicRealm.createObject(AllTypes.CLASS_NAME);\n        dynamicRealm.commitTransaction();\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void dynamicRealmResults_emittedChangesetOnUpdate() {\n        final DynamicRealm dynamicRealm = DynamicRealm.getInstance(looperThread.getConfiguration());\n        RealmResults<DynamicRealmObject> results = dynamicRealm.where(AllTypes.CLASS_NAME).findAll();\n\n        subscription = results.asChangesetObservable()\n            .subscribe(change -> {\n                RealmResults<DynamicRealmObject> collection = change.getCollection();\n                if (collection.isLoaded() && collection.isEmpty()) {\n                    looperThread.postRunnable(() -> {\n                        DynamicRealm dynRealm = DynamicRealm.getInstance(looperThread.getConfiguration());\n                        dynRealm.executeTransaction(dr -> {\n                            dr.createObject(AllTypes.CLASS_NAME);\n                        });\n                        dynRealm.close();\n                    });\n                }\n\n                if (collection.isLoaded() && collection.size() == 1) {\n                    assertEquals(1, change.getChangeset().getInsertions().length);\n                    disposeSuccessfulTest(dynamicRealm);\n                }\n            });\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void findAllAsync_emittedOnSubscribe() {\n        final RealmResults<AllTypes> results = realm.where(AllTypes.class).findAllAsync();\n        subscription = results.asFlowable().subscribe(rxResults -> {\n            assertTrue(rxResults.isFrozen());\n            disposeSuccessfulTest(realm);\n        });\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void findAllAsync_emittedOnUpdate() {\n        final AtomicInteger subscriberCalled = new AtomicInteger(0);\n        Realm realm = looperThread.getRealm();\n        subscription = realm.where(AllTypes.class).findAllAsync().asFlowable().subscribe(rxResults -> {\n            assertTrue(rxResults.isFrozen());\n            if (subscriberCalled.incrementAndGet() == 2) {\n                disposeSuccessfulTest(realm);\n            }\n        });\n\n        realm.beginTransaction();\n        realm.createObject(AllTypes.class);\n        realm.commitTransaction();\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void realm_emittedOnSubscribe() {\n        subscription = realm.asFlowable().subscribe(rxRealm -> {\n            assertTrue(rxRealm.isFrozen());\n            assertEquals(realm.getPath(), rxRealm.getPath());\n            disposeSuccessfulTest(realm);\n        });\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void realm_emittedOnUpdate() {\n        subscription = realm.asFlowable().subscribe(rxRealm -> {\n            assertTrue(rxRealm.isFrozen());\n            if (rxRealm.isEmpty()) {\n                realm.executeTransaction(r -> r.createObject(AllTypes.class));\n            } else {\n                assertEquals(1, realm.where(AllTypes.class).count());\n                disposeSuccessfulTest(realm);\n            }\n        });\n    }\n\n    @Test\n    @RunTestInLooperThread\n    @SuppressWarnings(\"ReferenceEquality\")\n    public void dynamicRealm_emittedOnSubscribe() {\n        final DynamicRealm dynamicRealm = DynamicRealm.getInstance(realm.getConfiguration());\n        subscription = dynamicRealm.asFlowable().subscribe(rxRealm -> {\n            assertTrue(rxRealm.isFrozen());\n            assertEquals(rxRealm.getPath(), dynamicRealm.getPath());\n            assertEquals(rxRealm.sharedRealm.getVersionID(), dynamicRealm.sharedRealm.getVersionID());\n            disposeSuccessfulTest(dynamicRealm);\n        });\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void dynamicRealm_emittedOnUpdate() {\n        final DynamicRealm dynamicRealm = DynamicRealm.getInstance(looperThread.getConfiguration());\n        subscription = dynamicRealm.asFlowable().subscribe(rxRealm -> {\n            assertTrue(rxRealm.isFrozen());\n            if (rxRealm.isEmpty()) {\n                dynamicRealm.executeTransaction(r -> r.createObject(\"AllTypes\"));\n            } else {\n                assertEquals(1, rxRealm.where(AllTypes.CLASS_NAME).count());\n                disposeSuccessfulTest(dynamicRealm);\n            }\n        });\n    }\n\n    @Test\n    @RunTestInLooperThread\n    @SuppressWarnings(\"ReferenceEquality\")\n    public void unsubscribe_sameThread() {\n        subscription = realm.asFlowable()\n                .doOnCancel(() -> {\n                    disposeSuccessfulTest(realm);\n                })\n                .subscribe(rxRealm -> {\n            assertTrue(rxRealm.isFrozen());\n            assertEquals(rxRealm.getPath(), realm.getPath());\n            assertEquals(rxRealm.sharedRealm.getVersionID(), realm.sharedRealm.getVersionID());\n        });\n        subscription.dispose();\n    }\n\n    @Test\n    @RunTestInLooperThread\n    @SuppressWarnings(\"ReferenceEquality\")\n    public void unsubscribe_fromOtherThread() {\n        subscription = realm.asFlowable()\n            .doFinally(() -> {\n                disposeSuccessfulTest(realm);\n            })\n            .subscribe(new Consumer<Realm>() {\n                @Override\n                public void accept(Realm rxRealm) {\n                    assertTrue(rxRealm.isFrozen());\n                    assertEquals(rxRealm.getPath(), realm.getPath());\n                    assertEquals(rxRealm.sharedRealm.getVersionID(), realm.sharedRealm.getVersionID());\n                    looperThread.postRunnable(() -> {\n                        Thread t = new Thread(() -> subscription.dispose());\n                        t.start();\n                        looperThread.keepStrongReference(t);\n                    });\n                }\n            });\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void wrongGenericClassThrows() {\n        realm.beginTransaction();\n        final AllTypes obj = realm.createObject(AllTypes.class);\n        realm.commitTransaction();\n\n        Flowable<CyclicType> obs = obj.asFlowable();\n        subscription = obs.subscribe(\n                cyclicType -> fail(),\n                ignoredError -> {\n                    disposeSuccessfulTest(realm);\n                }\n        );\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void realm_closeInDoOnUnsubscribe() {\n        Flowable<Realm> observable = realm.asFlowable()\n                .doOnCancel(() -> realm.close())\n                .doFinally(() -> {\n                    looperThread.postRunnable(() -> {\n                        assertTrue(realm.isClosed());\n                        disposeSuccessfulTest(realm);\n                    });\n                });\n\n        subscription = observable.subscribe(ignore -> {\n            assertEquals(3, Realm.getLocalInstanceCount(realm.getConfiguration()));\n            subscription.dispose();\n        });\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void dynamicRealm_closeInDoOnUnsubscribe() {\n        final DynamicRealm dynamicRealm = DynamicRealm.getInstance(realm.getConfiguration());\n\n        Flowable<DynamicRealm> observable = dynamicRealm.asFlowable()\n                .doOnCancel(() -> {\n                    dynamicRealm.close();\n                })\n                .doFinally(() -> {\n                    assertFalse(dynamicRealm.isClosed());\n                    looperThread.postRunnable(() -> {\n                        assertTrue(dynamicRealm.isClosed());\n                        disposeSuccessfulTest(dynamicRealm);\n                    });\n                });\n\n        subscription = observable.subscribe(ignored -> {\n            subscription.dispose();\n        });\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void realmResults_closeInDoOnUnsubscribe() {\n        Flowable<RealmResults<AllTypes>> observable = realm.where(AllTypes.class).findAll().asFlowable()\n                .doOnCancel(() -> realm.close());\n\n        subscription = observable.subscribe(ignored -> {});\n        subscription.dispose();\n        assertTrue(realm.isClosed());\n        disposeSuccessfulTest(realm);\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void realmList_closeInDoOnUnsubscribe() {\n        realm.beginTransaction();\n        RealmList<Dog> list = realm.createObject(AllTypes.class).getColumnRealmList();\n        realm.commitTransaction();\n\n        Flowable<RealmList<Dog>> observable = list.asFlowable()\n                .doOnCancel(() -> realm.close())\n                .doFinally(() -> {\n                    looperThread.postRunnable(() -> {\n                        assertTrue(realm.isClosed());\n                        disposeSuccessfulTest(realm);\n                    });\n                });\n\n        subscription = observable.subscribe(ignored -> {\n            subscription.dispose();\n        });\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void dynamicRealmResults_closeInDoOnUnsubscribe() {\n        final DynamicRealm dynamicRealm = DynamicRealm.getInstance(looperThread.getConfiguration());\n\n        Flowable<RealmResults<DynamicRealmObject>> flowable = dynamicRealm.where(AllTypes.CLASS_NAME).findAll().asFlowable()\n                .doOnCancel(() -> {\n                    dynamicRealm.close();\n                })\n                .doFinally(() -> {\n                    looperThread.postRunnable(() -> {\n                        assertTrue(dynamicRealm.isClosed());\n                        disposeSuccessfulTest(dynamicRealm);\n                    });\n                });\n\n        subscription = flowable.subscribe(ignored -> {\n            subscription.dispose();\n        });\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void realmObject_closeInDoOnUnsubscribe() {\n        realm.beginTransaction();\n        realm.createObject(AllTypes.class);\n        realm.commitTransaction();\n\n        Flowable<AllTypes> flowable = realm.where(AllTypes.class).findFirst().<AllTypes>asFlowable()\n                .doOnCancel(() -> realm.close())\n                .doFinally(() -> {\n                    looperThread.postRunnable(() -> {\n                        assertTrue(realm.isClosed());\n                        disposeSuccessfulTest(realm);\n                    });\n                });\n\n        subscription = flowable.subscribe(ignored -> {\n            subscription.dispose();\n        });\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void dynamicRealmObject_closeInDoOnUnsubscribe() {\n        realm.beginTransaction();\n        realm.createObject(AllTypes.class);\n        realm.commitTransaction();\n\n        final DynamicRealm dynamicRealm = DynamicRealm.getInstance(looperThread.getConfiguration());\n\n        subscription = dynamicRealm.where(AllTypes.CLASS_NAME).findFirst().<DynamicRealmObject>asFlowable()\n                .doOnCancel(() -> dynamicRealm.close())\n                .doFinally(() -> {\n                    looperThread.postRunnable(() -> {\n                        assertTrue(dynamicRealm.isClosed());\n                        disposeSuccessfulTest(dynamicRealm);\n                    });\n                }).subscribe(ignored -> subscription.dispose());\n    }\n\n    // Tests that Observables keep strong references to their parent, so they are not accidentally GC'ed while\n    // waiting for results from the async API's.\n    @Test\n    @RunTestInLooperThread\n    @SuppressWarnings(\"CheckReturnValue\")\n    public void realmResults_gcStressTest() {\n        final int TEST_SIZE = 50;\n        final AtomicLong innerCounter = new AtomicLong();\n        final Realm realm = looperThread.getRealm();\n\n        realm.beginTransaction();\n        for (int i = 0; i < TEST_SIZE; i++) {\n            realm.createObject(AllTypes.class).setColumnLong(i);\n        }\n        realm.commitTransaction();\n\n        for (int i = 0; i < TEST_SIZE; i++) {\n            realm.where(AllTypes.class).equalTo(AllTypes.FIELD_LONG, i).findAllAsync().asFlowable()\n                    .filter(results -> results.isLoaded())\n                    .take(1) // Unsubscribes from Realm.\n                    .subscribe(allTypes -> {\n                        // Not guaranteed, but can result in the GC of other RealmResults waiting for a result.\n                        Runtime.getRuntime().gc();\n                        if (innerCounter.incrementAndGet() == TEST_SIZE) {\n                            disposeSuccessfulTest(realm);\n                        }\n                    }, throwable -> fail(throwable.toString()));\n        }\n    }\n\n    // Tests that Observables keep strong references to their parent, so they are not accidentally GC'ed while\n    // waiting for results from the async API's.\n    @Test\n    @RunTestInLooperThread\n    @SuppressWarnings(\"CheckReturnValue\")\n    public void dynamicRealmResults_gcStressTest() {\n        final int TEST_SIZE = 50;\n        final AtomicLong innerCounter = new AtomicLong();\n        final DynamicRealm dynamicRealm = DynamicRealm.getInstance(looperThread.getConfiguration());\n\n        dynamicRealm.beginTransaction();\n        for (int i = 0; i < TEST_SIZE; i++) {\n            dynamicRealm.createObject(AllTypes.CLASS_NAME).set(AllTypes.FIELD_LONG, i);\n        }\n        dynamicRealm.commitTransaction();\n\n        for (int i = 0; i < TEST_SIZE; i++) {\n            // Doesn't keep a reference to the Observable.\n            dynamicRealm.where(AllTypes.CLASS_NAME).equalTo(AllTypes.FIELD_LONG, i).findAllAsync().asFlowable()\n                    .filter(results -> results.isLoaded())\n                    .take(1) // Unsubscribes from Realm.\n                    .subscribe(dynamicRealmObjects -> {\n                        // Not guaranteed, but can result in the GC of other RealmResults waiting for a result.\n                        Runtime.getRuntime().gc();\n                        if (innerCounter.incrementAndGet() == TEST_SIZE) {\n                            disposeSuccessfulTest(dynamicRealm);\n                        }\n                    }, throwable -> fail(throwable.toString()));\n        }\n    }\n\n    // Tests that Observables keep strong references to their parent, so they are not accidentally GC'ed while\n    // waiting for results from the async API's.\n    @Test\n    @RunTestInLooperThread\n    @SuppressWarnings(\"CheckReturnValue\")\n    public void realmObject_gcStressTest() {\n        final int TEST_SIZE = 50;\n        final AtomicLong innerCounter = new AtomicLong();\n\n        realm.beginTransaction();\n        for (int i = 0; i < TEST_SIZE; i++) {\n            realm.createObject(AllTypes.class).setColumnLong(i);\n        }\n        realm.commitTransaction();\n\n        for (int i = 0; i < TEST_SIZE; i++) {\n            // Doesn't keep a reference to the Observable.\n            realm.where(AllTypes.class).equalTo(AllTypes.FIELD_LONG, i).findFirstAsync().<AllTypes>asFlowable()\n                    .filter(obj -> obj.isLoaded())\n                    .take(1) // Unsubscribes from Realm.\n                    .subscribe(allTypes -> {\n                        // Not guaranteed, but can result in the GC of other RealmResults waiting for a result.\n                        Runtime.getRuntime().gc();\n                        if (innerCounter.incrementAndGet() == TEST_SIZE) {\n                            disposeSuccessfulTest(realm);\n                        }\n                    }, throwable -> fail(throwable.toString()));\n        }\n    }\n\n    // Tests that Observables keep strong references to their parent, so they are not accidentally GC'ed while\n    // waiting for results from the async API's.\n    @Test\n    @RunTestInLooperThread\n    @SuppressWarnings(\"CheckReturnValue\")\n    public void dynamicRealmObject_gcStressTest() {\n        final int TEST_SIZE = 50;\n        final AtomicLong innerCounter = new AtomicLong();\n        final DynamicRealm dynamicRealm = DynamicRealm.getInstance(looperThread.getConfiguration());\n\n        dynamicRealm.beginTransaction();\n        for (int i = 0; i < TEST_SIZE; i++) {\n            dynamicRealm.createObject(AllTypes.CLASS_NAME).set(AllTypes.FIELD_LONG, i);\n        }\n        dynamicRealm.commitTransaction();\n\n        for (int i = 0; i < TEST_SIZE; i++) {\n            // Doesn't keep a reference to the Observable.\n            dynamicRealm.where(AllTypes.CLASS_NAME).equalTo(AllTypes.FIELD_LONG, i).findFirstAsync().<DynamicRealmObject>asFlowable()\n                    .filter(obj -> obj.isLoaded())\n                    .take(1) // Unsubscribes from Realm.\n                    .subscribe(dynamicRealmObject -> {\n                        // Not guaranteed, but can result in the GC of other RealmResults waiting for a result.\n                        Runtime.getRuntime().gc();\n                        if (innerCounter.incrementAndGet() == TEST_SIZE) {\n                            disposeSuccessfulTest(dynamicRealm);\n                        }\n                    }, throwable -> fail(throwable.toString()));\n        }\n    }\n\n\n    @Test\n    @RunTestInLooperThread\n    public void asFlowable_frozenRealm() {\n        Realm frozenRealm = realm.freeze();\n        subscription = frozenRealm.asFlowable()\n                .subscribe(rxRealm -> {\n                    assertEquals(frozenRealm, rxRealm);\n                    disposeSuccessfulTest(realm);\n                });\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void asFlowable_frozenDynamicRealm() {\n        DynamicRealm dynamicRealm = DynamicRealm.getInstance(looperThread.getConfiguration());\n        DynamicRealm frozenDynamicRealm = dynamicRealm.freeze();\n        subscription = frozenDynamicRealm.asFlowable()\n                .subscribe(rxRealm -> {\n                    assertEquals(frozenDynamicRealm, rxRealm);\n                    dynamicRealm.close();\n                    disposeSuccessfulTest(dynamicRealm);\n                });\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void asFlowable_frozenRealmResults() {\n        final RealmResults<AllTypes> frozenResults = realm.where(AllTypes.class).findAll().freeze();\n        subscription = frozenResults.asFlowable().subscribe(rxResults -> {\n            assertTrue(rxResults.isFrozen());\n            assertEquals(frozenResults, rxResults);\n            disposeSuccessfulTest(realm);\n        });\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void asChangesetObservable_frozenRealmResults() {\n        final RealmResults<AllTypes> frozenResults = realm.where(AllTypes.class).findAll().freeze();\n        subscription = frozenResults.asChangesetObservable().subscribe(change -> {\n            RealmResults<AllTypes> rxResults = change.getCollection();\n            assertTrue(rxResults.isFrozen());\n            assertEquals(frozenResults, rxResults);\n            assertNull(change.getChangeset());\n            disposeSuccessfulTest(realm);\n        });\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void asFlowable_frozenDynamicRealmResults() {\n        DynamicRealm dynamicRealm = DynamicRealm.getInstance(looperThread.getConfiguration());\n        final RealmResults<DynamicRealmObject> frozenResults = dynamicRealm.where(AllTypes.CLASS_NAME).findAll().freeze();\n        subscription = frozenResults.asFlowable().subscribe(rxResults -> {\n            assertTrue(rxResults.isFrozen());\n            assertEquals(frozenResults, rxResults);\n            disposeSuccessfulTest(dynamicRealm);\n        });\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void asChangesetObservable_frozenDynamicRealmResults() {\n        DynamicRealm dynamicRealm = DynamicRealm.getInstance(looperThread.getConfiguration());\n        final RealmResults<DynamicRealmObject> frozenResults = dynamicRealm.where(AllTypes.CLASS_NAME).findAll().freeze();\n        subscription = frozenResults.asChangesetObservable().subscribe(change -> {\n            RealmResults<DynamicRealmObject> rxResults = change.getCollection();\n            assertTrue(rxResults.isFrozen());\n            assertEquals(frozenResults, rxResults);\n            assertNull(change.getChangeset());\n            disposeSuccessfulTest(dynamicRealm);\n        });\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void asFlowable_frozenRealmList() {\n        realm.beginTransaction();\n        final RealmList<Dog> list = realm.createObject(AllTypes.class).getColumnRealmList();\n        list.add(new Dog(\"dog\"));\n        realm.commitTransaction();\n\n        RealmList<Dog> frozenList = list.freeze();\n        subscription = frozenList.asFlowable().subscribe(rxList -> {\n            assertTrue(rxList.isFrozen());\n            assertEquals(frozenList, rxList);\n            disposeSuccessfulTest(realm);\n        });\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void asChangesetObservable_frozenRealmList() {\n        realm.beginTransaction();\n        final RealmList<Dog> list = realm.createObject(AllTypes.class).getColumnRealmList();\n        list.add(new Dog(\"dog\"));\n        realm.commitTransaction();\n\n        RealmList<Dog> frozenList = list.freeze();\n        subscription = frozenList.asChangesetObservable().subscribe(change -> {\n            RealmList<Dog> rxList = change.getCollection();\n            assertTrue(rxList.isFrozen());\n            assertEquals(frozenList, rxList);\n            assertNull(change.getChangeset());\n            disposeSuccessfulTest(realm);\n        });\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void asFlowable_frozenDynamicRealmList() {\n        realm.beginTransaction();\n        final RealmList<Dog> list = realm.createObject(AllTypes.class).getColumnRealmList();\n        list.add(new Dog(\"dog\"));\n        realm.commitTransaction();\n\n        DynamicRealm dynamicRealm = DynamicRealm.getInstance(looperThread.getConfiguration());\n        RealmList<DynamicRealmObject> frozenList = dynamicRealm.where(AllTypes.CLASS_NAME).findFirst().getList(AllTypes.FIELD_REALMLIST).freeze();\n\n        subscription = frozenList.asFlowable().subscribe(rxList -> {\n            assertTrue(rxList.isFrozen());\n            assertEquals(frozenList, rxList);\n            disposeSuccessfulTest(dynamicRealm);\n        });\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void asChangesetObservable_frozenDynamicRealmList() {\n        realm.beginTransaction();\n        final RealmList<Dog> list = realm.createObject(AllTypes.class).getColumnRealmList();\n        list.add(new Dog(\"dog\"));\n        realm.commitTransaction();\n\n        DynamicRealm dynamicRealm = DynamicRealm.getInstance(looperThread.getConfiguration());\n        RealmList<DynamicRealmObject> frozenList = dynamicRealm.where(AllTypes.CLASS_NAME).findFirst().getList(AllTypes.FIELD_REALMLIST).freeze();\n\n        subscription = frozenList.asChangesetObservable().subscribe(change -> {\n            RealmList<DynamicRealmObject> rxList = change.getCollection();\n            assertTrue(rxList.isFrozen());\n            assertEquals(frozenList, rxList);\n            assertNull(change.getChangeset());\n            disposeSuccessfulTest(dynamicRealm);\n        });\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void asFlowable_frozenRealmObject() {\n        realm.beginTransaction();\n        final AllJavaTypes obj = realm.createObject(AllJavaTypes.class, 42);\n        realm.commitTransaction();\n\n        subscription = obj.<AllJavaTypes>freeze().<AllJavaTypes>asFlowable().subscribe(rxObject -> {\n            assertTrue(rxObject.isFrozen());\n            assertNotEquals(rxObject, obj);\n            assertEquals(rxObject.getFieldId(), obj.getFieldId());\n            disposeSuccessfulTest(realm);\n        });\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void asChangesetObservable_frozenRealmObject() {\n        realm.beginTransaction();\n        final AllJavaTypes obj = realm.createObject(AllJavaTypes.class, 42);\n        realm.commitTransaction();\n\n        subscription = obj.<AllJavaTypes>freeze().<AllJavaTypes>asChangesetObservable().subscribe(change -> {\n            AllJavaTypes rxObject = change.getObject();\n            assertTrue(rxObject.isFrozen());\n            assertNotEquals(rxObject, obj);\n            assertEquals(rxObject.getFieldId(), obj.getFieldId());\n            disposeSuccessfulTest(realm);\n        });\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void asFlowable_frozenDynamicRealmObject() {\n        realm.beginTransaction();\n        realm.createObject(AllTypes.class);\n        realm.commitTransaction();\n\n        DynamicRealm dynamicRealm = DynamicRealm.getInstance(looperThread.getConfiguration());\n        DynamicRealmObject obj = dynamicRealm.where(AllTypes.CLASS_NAME).findFirst();\n\n        DynamicRealmObject frozenObject = obj.<DynamicRealmObject>freeze();\n        subscription = frozenObject.asFlowable().subscribe(rxObject -> {\n            assertTrue(rxObject.isFrozen());\n            assertEquals(rxObject, frozenObject);\n            disposeSuccessfulTest(dynamicRealm);\n        });\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void asChangesetObservable_frozenDynamicRealmObject() {\n        realm.beginTransaction();\n        realm.createObject(AllTypes.class);\n        realm.commitTransaction();\n\n        DynamicRealm dynamicRealm = DynamicRealm.getInstance(looperThread.getConfiguration());\n        DynamicRealmObject obj = dynamicRealm.where(AllTypes.CLASS_NAME).findFirst();\n\n        DynamicRealmObject frozenObject = obj.<DynamicRealmObject>freeze();\n        subscription = frozenObject.asChangesetObservable().subscribe(change -> {\n            RealmObject rxObject = change.getObject();\n            assertTrue(rxObject.isFrozen());\n            assertEquals(rxObject, frozenObject);\n            assertNull(change.getChangeset());\n            disposeSuccessfulTest(dynamicRealm);\n        });\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void realmResults_readableAcrossThreads() {\n        final long TEST_SIZE = 10;\n        Realm realm = looperThread.getRealm();\n\n        realm.beginTransaction();\n        for (int i = 0; i < TEST_SIZE; i++) {\n            realm.createObject(AllTypes.class).setColumnLong(1);\n        }\n        realm.commitTransaction();\n\n        AtomicLong startingThread = new AtomicLong(Thread.currentThread().getId());\n        AtomicLong subscriberThread = new AtomicLong();\n        subscription = realm.where(AllTypes.class).sort(AllTypes.FIELD_LONG).findAllAsync().asFlowable()\n                .doOnSubscribe((r) -> {\n                    subscriberThread.set(Thread.currentThread().getId());\n                })\n                // Note that Realm automatically subscribes on the thread with the live Realm\n                // so calling `subscribeOn()` has very little effect.\n                // In most cases you probably want to call `observeOn` directly after `asFlowable()`.\n                .subscribeOn(Schedulers.io())\n                .filter(results -> {\n                    assertNotEquals(startingThread.get(), subscriberThread.get());\n                    return results.isLoaded();\n                })\n                .map(results -> new Pair<>(results.size(), new Pair<>(results, results.first())))\n                .observeOn(Schedulers.computation())\n                .subscribe(\n                        pair -> {\n                            assertNotEquals(startingThread.get(), Thread.currentThread().getId());\n                            assertNotEquals(subscriberThread.get(), Thread.currentThread().getId());\n                            assertEquals(TEST_SIZE, pair.first.intValue());\n                            assertEquals(TEST_SIZE, pair.second.first.size());\n                            assertEquals(pair.second.second.getColumnLong(), pair.second.first.first().getColumnLong());\n                            disposeSuccessfulTest(realm);\n                        }\n                );\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/SortTest.java",
    "content": "/*\n * Copyright 2015 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\npackage io.realm;\n\nimport android.content.Context;\nimport androidx.test.platform.app.InstrumentationRegistry;\nimport androidx.test.ext.junit.runners.AndroidJUnit4;\n\nimport org.junit.After;\nimport org.junit.Before;\nimport org.junit.Rule;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\n\nimport java.util.Date;\nimport java.util.concurrent.atomic.AtomicInteger;\n\nimport io.realm.entities.AllTypes;\nimport io.realm.entities.AnnotationIndexTypes;\nimport io.realm.entities.Dog;\nimport io.realm.entities.StringOnly;\nimport io.realm.internal.Table;\nimport io.realm.internal.UncheckedRow;\nimport io.realm.rule.RunInLooperThread;\nimport io.realm.rule.RunTestInLooperThread;\n\nimport static org.junit.Assert.assertEquals;\nimport static org.junit.Assert.fail;\n\n@RunWith(AndroidJUnit4.class)\npublic class SortTest {\n    private Realm realm;\n\n    @Rule\n    public final TestRealmConfigurationFactory configFactory = new TestRealmConfigurationFactory();\n    @Rule\n    public final RunInLooperThread looperThread = new RunInLooperThread();\n\n    private Context context;\n    private RealmConfiguration realmConfig;\n\n    private final static String FIELD_STRING = \"columnString\";\n    private final static String FIELD_LONG = \"columnLong\";\n\n    private final static String[] ORDER_STRING_INT = {FIELD_STRING, FIELD_LONG};\n    private final static String[] ORDER_INT_STRING = {FIELD_LONG, FIELD_STRING};\n\n    private final static Sort[] ORDER_ASC_ASC = {Sort.ASCENDING, Sort.ASCENDING};\n    private final static Sort[] ORDER_ASC_DES = {Sort.ASCENDING, Sort.DESCENDING};\n\n    private static String chars;\n    private int numberOfPermutations;\n\n    private void populateRealm(Realm realm) {\n        realm.beginTransaction();\n\n        realm.delete(AllTypes.class);\n        AllTypes object1 = realm.createObject(AllTypes.class);\n        object1.setColumnLong(5);\n        object1.setColumnString(\"Adam\");\n        object1.setColumnRealmObject(realm.copyToRealm(new Dog(\"D\")));\n\n        AllTypes object2 = realm.createObject(AllTypes.class);\n        object2.setColumnLong(4);\n        object2.setColumnString(\"Brian\");\n        object2.setColumnRealmObject(realm.copyToRealm(new Dog(\"C\")));\n\n        AllTypes object3 = realm.createObject(AllTypes.class);\n        object3.setColumnLong(4);\n        object3.setColumnString(\"Adam\");\n        object3.setColumnRealmObject(realm.copyToRealm(new Dog(\"B\")));\n\n        AllTypes object4 = realm.createObject(AllTypes.class);\n        object4.setColumnLong(5);\n        object4.setColumnString(\"Adam\");\n        object4.setColumnRealmObject(realm.copyToRealm(new Dog(\"A\")));\n\n        realm.delete(AnnotationIndexTypes.class);\n        AnnotationIndexTypes obj1 = realm.createObject(AnnotationIndexTypes.class);\n        obj1.setIndexLong(1);\n        obj1.setIndexInt(1);\n        obj1.setIndexString(\"A\");\n\n        AnnotationIndexTypes obj2 = realm.createObject(AnnotationIndexTypes.class);\n        obj2.setIndexLong(2);\n        obj2.setIndexInt(1);\n        obj2.setIndexString(\"B\");\n\n        AnnotationIndexTypes obj3 = realm.createObject(AnnotationIndexTypes.class);\n        obj3.setIndexLong(3);\n        obj3.setIndexInt(1);\n        obj3.setIndexString(\"C\");\n\n        realm.commitTransaction();\n    }\n\n    private UncheckedRow getRowBySourceIndexFromAllTypesTable(long sourceRowIndex) {\n        Table table = realm.getTable(AllTypes.class);\n        return table.getUncheckedRow(sourceRowIndex);\n    }\n\n    @Before\n    public void setUp() {\n        // Creates a Realm with the following objects:\n        // 0: (5, \"Adam\", Dog(\"D\"))\n        // 1: (4, \"Brian\", Dog(\"C\"))\n        // 2: (4, \"Adam\", Dog(\"B\"))\n        // 3: (5, \"Adam\", Dog(\"A\"))\n\n        // Injecting the Instrumentation instance is required\n        // for your test to run with AndroidJUnitRunner.\n        context = InstrumentationRegistry.getInstrumentation().getContext();\n        realmConfig = configFactory.createConfiguration();\n        realm = Realm.getInstance(realmConfig);\n\n        populateRealm(realm);\n    }\n\n    @After\n    public void tearDown() {\n        if (realm != null) {\n            realm.close();\n        }\n    }\n\n    @Test\n    public void sortMultiFailures() {\n        RealmResults<AllTypes> allTypes = realm.where(AllTypes.class).findAll();\n\n        // Zero fields specified.\n        try {\n            allTypes.sort(new String[]{}, new Sort[]{});\n            fail();\n        } catch (IllegalArgumentException ignored) {\n        }\n\n        // Number of fields and sorting orders don't match.\n        try {\n            allTypes.sort(new String[]{FIELD_STRING}, ORDER_ASC_ASC);\n            fail();\n        } catch (IllegalArgumentException ignored) {\n        }\n\n        // Null is not allowed.\n        try {\n            allTypes.sort(null, (Sort[]) null);\n            fail();\n        } catch (IllegalArgumentException ignored) {\n        }\n        try {\n            allTypes.sort(new String[]{FIELD_STRING}, null);\n            fail();\n        } catch (IllegalArgumentException ignored) {\n        }\n\n        // Non-existing field name.\n        try {\n            allTypes.sort(new String[]{FIELD_STRING, \"dont-exist\"}, ORDER_ASC_ASC);\n            fail();\n        } catch (IllegalArgumentException ignored) {\n        }\n    }\n\n    private void checkSortTwoFieldsStringAscendingIntAscending(RealmResults<AllTypes> results) {\n        // Sorted String (ascending), Long (ascending).\n        // Expected output:\n        // (4, \"Adam\"), row index = 2\n        // (5, \"Adam\"), row index = 0 - stable sort!\n        // (5, \"Adam\"), row index = 3\n        // (4, \"Brian\"), row index = 1\n        assertEquals(4, results.size());\n\n        assertEquals(\"Adam\", results.get(0).getColumnString());\n        assertEquals(4, results.get(0).getColumnLong());\n        assertEquals(0, results.getOsResults().indexOf(getRowBySourceIndexFromAllTypesTable(2)));\n\n        assertEquals(\"Adam\", results.get(1).getColumnString());\n        assertEquals(5, results.get(1).getColumnLong());\n        assertEquals(1, results.getOsResults().indexOf(getRowBySourceIndexFromAllTypesTable(0)));\n\n        assertEquals(\"Adam\", results.get(2).getColumnString());\n        assertEquals(5, results.get(2).getColumnLong());\n        assertEquals(2, results.getOsResults().indexOf(getRowBySourceIndexFromAllTypesTable(3)));\n\n        assertEquals(\"Brian\", results.get(3).getColumnString());\n        assertEquals(4, results.get(3).getColumnLong());\n        assertEquals(3, results.getOsResults().indexOf(getRowBySourceIndexFromAllTypesTable(1)));\n    }\n\n    private void checkSortTwoFieldsIntString(RealmResults<AllTypes> results) {\n        // Sorted Long (ascending), String (descending).\n        // Expected output:\n        // (4, \"Adam\"), row index = 2\n        // (4, \"Brian\"), row index = 1\n        // (5, \"Adam\"), row index = 0 - stable sort!\n        // (5, \"Adam\"), row index = 3\n        assertEquals(4, results.size());\n\n        assertEquals(\"Adam\", results.get(0).getColumnString());\n        assertEquals(4, results.get(0).getColumnLong());\n        assertEquals(0, results.getOsResults().indexOf(getRowBySourceIndexFromAllTypesTable(2)));\n\n        assertEquals(\"Brian\", results.get(1).getColumnString());\n        assertEquals(4, results.get(1).getColumnLong());\n        assertEquals(1, results.getOsResults().indexOf(getRowBySourceIndexFromAllTypesTable(1)));\n\n        assertEquals(\"Adam\", results.get(2).getColumnString());\n        assertEquals(5, results.get(2).getColumnLong());\n        assertEquals(2, results.getOsResults().indexOf(getRowBySourceIndexFromAllTypesTable(0)));\n\n        assertEquals(\"Adam\", results.get(3).getColumnString());\n        assertEquals(5, results.get(3).getColumnLong());\n        assertEquals(3, results.getOsResults().indexOf(getRowBySourceIndexFromAllTypesTable(3)));\n    }\n\n    private void checkSortTwoFieldsIntAscendingStringDescending(RealmResults<AllTypes> results) {\n        // Sorted Long (ascending), String (descending).\n        // Expected output:\n        // (4, \"Brian\"), row index = 1\n        // (4, \"Adam\"), row index = 2\n        // (5, \"Adam\"), row index = 0 - stable sort!\n        // (5, \"Adam\"), row index = 3\n        assertEquals(4, results.size());\n\n        assertEquals(\"Brian\", results.get(0).getColumnString());\n        assertEquals(4, results.get(0).getColumnLong());\n        assertEquals(0, results.getOsResults().indexOf(getRowBySourceIndexFromAllTypesTable(1)));\n\n        assertEquals(\"Adam\", results.get(1).getColumnString());\n        assertEquals(4, results.get(1).getColumnLong());\n        assertEquals(1, results.getOsResults().indexOf(getRowBySourceIndexFromAllTypesTable(2)));\n\n        assertEquals(\"Adam\", results.get(2).getColumnString());\n        assertEquals(5, results.get(2).getColumnLong());\n        assertEquals(2, results.getOsResults().indexOf(getRowBySourceIndexFromAllTypesTable(0)));\n\n        assertEquals(\"Adam\", results.get(3).getColumnString());\n        assertEquals(5, results.get(3).getColumnLong());\n        assertEquals(3, results.getOsResults().indexOf(getRowBySourceIndexFromAllTypesTable(3)));\n    }\n\n    private void checkSortTwoFieldsStringAscendingIntDescending(RealmResults<AllTypes> results) {\n        // Sorted String (ascending), Long (descending).\n        // Expected output:\n        // (5, \"Adam\"), row index = 0 - stable sort!\n        // (5, \"Adam\"), row index = 3\n        // (4, \"Adam\"), row index = 2\n        // (5, \"Brian\"), row index = 1\n        assertEquals(4, results.size());\n\n        assertEquals(\"Adam\", results.get(0).getColumnString());\n        assertEquals(5, results.get(0).getColumnLong());\n        assertEquals(0, results.getOsResults().indexOf(getRowBySourceIndexFromAllTypesTable(0)));\n\n        assertEquals(\"Adam\", results.get(1).getColumnString());\n        assertEquals(5, results.get(1).getColumnLong());\n        assertEquals(1, results.getOsResults().indexOf(getRowBySourceIndexFromAllTypesTable(3)));\n\n        assertEquals(\"Adam\", results.get(2).getColumnString());\n        assertEquals(4, results.get(2).getColumnLong());\n        assertEquals(2, results.getOsResults().indexOf(getRowBySourceIndexFromAllTypesTable(2)));\n\n        assertEquals(\"Brian\", results.get(3).getColumnString());\n        assertEquals(4, results.get(3).getColumnLong());\n        assertEquals(3, results.getOsResults().indexOf(getRowBySourceIndexFromAllTypesTable(1)));\n    }\n\n    @Test\n    public void sortRealmResultsTwoFields() {\n        RealmResults<AllTypes> results1 = realm.where(AllTypes.class).findAll().sort(ORDER_STRING_INT, ORDER_ASC_ASC);\n        checkSortTwoFieldsStringAscendingIntAscending(results1);\n\n        RealmResults<AllTypes> results2 = realm.where(AllTypes.class).findAll().sort(ORDER_INT_STRING, ORDER_ASC_ASC);\n        checkSortTwoFieldsIntString(results2);\n\n        RealmResults<AllTypes> results3 = realm.where(AllTypes.class).findAll().sort(ORDER_STRING_INT, ORDER_ASC_DES);\n        checkSortTwoFieldsStringAscendingIntDescending(results3);\n\n        RealmResults<AllTypes> results4 = realm.where(AllTypes.class).findAll().sort(ORDER_INT_STRING, ORDER_ASC_DES);\n        checkSortTwoFieldsIntAscendingStringDescending(results4);\n    }\n\n    @Test\n    public void realmQuerySortTwoFields() {\n        RealmResults<AllTypes> results1 = realm.where(AllTypes.class)\n                .findAll().sort(ORDER_STRING_INT, ORDER_ASC_ASC);\n        checkSortTwoFieldsStringAscendingIntAscending(results1);\n\n        RealmResults<AllTypes> results2 = realm.where(AllTypes.class)\n                .findAll().sort(ORDER_INT_STRING, ORDER_ASC_ASC);\n        checkSortTwoFieldsIntString(results2);\n\n        RealmResults<AllTypes> results3 = realm.where(AllTypes.class)\n                .findAll().sort(ORDER_STRING_INT, ORDER_ASC_DES);\n        checkSortTwoFieldsStringAscendingIntDescending(results3);\n\n        RealmResults<AllTypes> results4 = realm.where(AllTypes.class)\n                .findAll().sort(ORDER_INT_STRING, ORDER_ASC_DES);\n        checkSortTwoFieldsIntAscendingStringDescending(results4);\n    }\n\n    @Test\n    public void realmSortTwoFields() {\n        RealmResults<AllTypes> results1 = realm.where(AllTypes.class).findAll().\n                sort(ORDER_STRING_INT, ORDER_ASC_ASC);\n        checkSortTwoFieldsStringAscendingIntAscending(results1);\n\n        RealmResults<AllTypes> results2 = realm.where(AllTypes.class).findAll().\n                sort(ORDER_INT_STRING, ORDER_ASC_ASC);\n        checkSortTwoFieldsIntString(results2);\n\n        RealmResults<AllTypes> results3 = realm.where(AllTypes.class).findAll().\n                sort(ORDER_STRING_INT, ORDER_ASC_DES);\n        checkSortTwoFieldsStringAscendingIntDescending(results3);\n\n        RealmResults<AllTypes> results4 = realm.where(AllTypes.class).findAll().\n                sort(ORDER_INT_STRING, ORDER_ASC_DES);\n        checkSortTwoFieldsIntAscendingStringDescending(results4);\n    }\n\n    @Test\n    public void realmSortMultiFailures() {\n        RealmResults<AllTypes> allTypes = realm.where(AllTypes.class).findAll();\n\n        // Zero fields specified.\n        try {\n            realm.where(AllTypes.class).findAll().sort(new String[]{}, new Sort[]{});\n            fail();\n        } catch (IllegalArgumentException ignored) {\n        }\n\n        // Number of fields and sorting orders don't match.\n        try {\n            realm.where(AllTypes.class).findAll().\n                    sort(new String[]{FIELD_STRING}, ORDER_ASC_ASC);\n            fail();\n        } catch (IllegalArgumentException ignored) {\n        }\n\n        // Null is not allowed.\n        try {\n            realm.where(AllTypes.class).findAll().sort(null, (Sort[]) null);\n            fail();\n        } catch (IllegalArgumentException ignored) {\n        }\n        try {\n            realm.where(AllTypes.class).findAll().sort(new String[]{FIELD_STRING}, null);\n            fail();\n        } catch (IllegalArgumentException ignored) {\n        }\n\n        // Non-existing field name.\n        try {\n            realm.where(AllTypes.class).findAll().\n                    sort(new String[]{FIELD_STRING, \"dont-exist\"}, ORDER_ASC_ASC);\n            fail();\n        } catch (IllegalArgumentException ignored) {\n        }\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void resorting() throws InterruptedException {\n        final AtomicInteger changeListenerCalled = new AtomicInteger(4);\n\n        final Realm realm = looperThread.getRealm();\n        realm.setAutoRefresh(true);\n\n        final Runnable endTest = new Runnable() {\n            @Override\n            public void run() {\n                if (changeListenerCalled.decrementAndGet() == 0) {\n                    realm.close();\n                    looperThread.testComplete();\n                }\n            }\n        };\n\n        // 0: (5, \"Adam\")\n        // 1: (4, \"Brian\")\n        // 2: (4, \"Adam\")\n        // 3: (5, \"Adam\")\n        populateRealm(realm);\n\n        // rr0: [0, 1, 2, 3]\n        final RealmResults<AllTypes> rr0 = realm.where(AllTypes.class).findAll();\n        looperThread.keepStrongReference(rr0);\n        rr0.addChangeListener(new RealmChangeListener<RealmResults<AllTypes>>() {\n            @Override\n            public void onChange(RealmResults<AllTypes> element) {\n                // After commit: [0, 1, 2, 3, 4] - most likely as order isn't guaranteed.\n                assertEquals(5, element.size());\n                endTest.run();\n            }\n        });\n\n        // rr1: [1, 2, 0, 3]\n        final RealmResults<AllTypes> rr1 = realm.where(AllTypes.class).findAll().sort(FIELD_LONG, Sort.ASCENDING);\n        looperThread.keepStrongReference(rr1);\n        rr1.addChangeListener(new RealmChangeListener<RealmResults<AllTypes>>() {\n            @Override\n            public void onChange(RealmResults<AllTypes> element) {\n                // After commit: [1, 2, 0, 3, 4]\n                assertEquals(4, element.first().getColumnLong());\n                assertEquals(6, element.last().getColumnLong());\n                assertEquals(5, element.size());\n                endTest.run();\n            }\n        });\n        assertEquals(4, rr1.first().getColumnLong());\n        assertEquals(5, rr1.last().getColumnLong());\n\n        // rr2: [0, 3, 1, 2]\n        final RealmResults<AllTypes> rr2 = realm.where(AllTypes.class).findAll().sort(FIELD_LONG, Sort.DESCENDING);\n        looperThread.keepStrongReference(rr2);\n        rr2.addChangeListener(new RealmChangeListener<RealmResults<AllTypes>>() {\n            @Override\n            public void onChange(RealmResults<AllTypes> element) {\n                // After commit: [4, 0, 3, 1, 2]\n                assertEquals(6, element.first().getColumnLong());\n                assertEquals(4, element.last().getColumnLong());\n                assertEquals(5, element.size());\n                endTest.run();\n            }\n        });\n        assertEquals(5, rr2.first().getColumnLong());\n        assertEquals(4, rr2.last().getColumnLong());\n\n        realm.addChangeListener(new RealmChangeListener<Realm>() {\n            @Override\n            public void onChange(Realm element) {\n                assertEquals(5, element.where(AllTypes.class).findAll().size());\n                endTest.run();\n            }\n        });\n\n        // After commit:\n        // 0: (5, \"Adam\")\n        // 1: (4, \"Brian\")\n        // 2: (4, \"Adam\")\n        // 3: (5, \"Adam\")\n        // 4: (6, \"\")\n        realm.beginTransaction();\n        AllTypes allTypes = realm.createObject(AllTypes.class);\n        allTypes.setColumnLong(6);\n        realm.commitTransaction();\n    }\n\n    private void populateDates(Realm realm, int n) {\n        realm.beginTransaction();\n        realm.delete(AllTypes.class);\n        for (int i = 0; i < n; i++) {\n            AllTypes allTypes = realm.createObject(AllTypes.class);\n            allTypes.setColumnDate(new Date(i));\n        }\n        realm.commitTransaction();\n    }\n\n    @Test\n    public void sortingDates() {\n        final int TEST_SIZE = 10;\n\n        populateDates(realm, TEST_SIZE);\n\n        RealmResults<AllTypes> objectsAscending = realm.where(AllTypes.class).sort(AllTypes.FIELD_DATE, Sort.ASCENDING).findAll();\n        assertEquals(TEST_SIZE, objectsAscending.size());\n        int i = 0;\n        for (AllTypes allTypes : objectsAscending) {\n            assertEquals(new Date(i), allTypes.getColumnDate());\n            i++;\n        }\n\n        RealmResults<AllTypes> objectsDescending = realm.where(AllTypes.class).sort(AllTypes.FIELD_DATE, Sort.DESCENDING).findAll();\n        assertEquals(TEST_SIZE, objectsDescending.size());\n        i = TEST_SIZE - 1;\n        for (AllTypes allTypes : objectsDescending) {\n            assertEquals(new Date(i), allTypes.getColumnDate());\n            i--;\n        }\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void resortingDates() {\n        final int TEST_SIZE = 10;\n        final AtomicInteger changeListenerCalled = new AtomicInteger(2);\n\n        final Realm realm = Realm.getInstance(looperThread.createConfiguration());\n        realm.setAutoRefresh(true);\n        populateDates(realm, TEST_SIZE);\n\n        final Runnable endTest = new Runnable() {\n            @Override\n            public void run() {\n                if (changeListenerCalled.decrementAndGet() == 0) {\n                    realm.close();\n                    looperThread.testComplete();\n                }\n            }\n        };\n\n        RealmResults<AllTypes> objectsAscending = realm.where(AllTypes.class).sort(AllTypes.FIELD_DATE, Sort.ASCENDING).findAll();\n        assertEquals(TEST_SIZE, objectsAscending.size());\n        looperThread.keepStrongReference(objectsAscending);\n        objectsAscending.addChangeListener(new RealmChangeListener<RealmResults<AllTypes>>() {\n            @Override\n            public void onChange(RealmResults<AllTypes> element) {\n                assertEquals(TEST_SIZE + 1, element.size());\n                long i = 0;\n                for (AllTypes allTypes : element) {\n                    assertEquals(new Date(i), allTypes.getColumnDate());\n                    i++;\n                }\n                endTest.run();\n            }\n        });\n\n        RealmResults<AllTypes> objectsDescending = realm.where(AllTypes.class).sort(AllTypes.FIELD_DATE, Sort.DESCENDING).findAll();\n        assertEquals(TEST_SIZE, objectsDescending.size());\n        looperThread.keepStrongReference(objectsDescending);\n        objectsDescending.addChangeListener(new RealmChangeListener<RealmResults<AllTypes>>() {\n            @Override\n            public void onChange(RealmResults<AllTypes> element) {\n                assertEquals(TEST_SIZE + 1, element.size());\n                long i = ((long) element.size()) - 1;\n                for (AllTypes allTypes : element) {\n                    assertEquals(new Date(i), allTypes.getColumnDate());\n                    i--;\n                }\n                endTest.run();\n            }\n        });\n\n        realm.beginTransaction();\n        AllTypes allTypes = realm.createObject(AllTypes.class);\n        allTypes.setColumnDate(new Date(TEST_SIZE));\n        realm.commitTransaction();\n    }\n\n    @Test\n    public void sortByLongDistinctByInt() {\n        // Before sorting:\n        // (FIELD_INDEX_LONG, FIELD_INDEX_INT, FIELD_INDEX_STRING)\n        // (1, 1, \"A\")\n        // (2, 1, \"B\")\n        // (3, 1, \"C\")\n        // After sorting\n        // (3, 1, \"C\")\n        // (2, 1, \"B\")\n        // (1, 1, \"A)\n        RealmResults<AnnotationIndexTypes> results1 = realm.where(AnnotationIndexTypes.class)\n                .sort(AnnotationIndexTypes.FIELD_INDEX_LONG, Sort.DESCENDING)\n                .findAll();\n        assertEquals(3, results1.size());\n        assertEquals(3, results1.get(0).getIndexLong());\n\n        // After distinct:\n        // (3, 1, \"C\")\n        RealmResults<AnnotationIndexTypes> results2 =  results1.where().distinct(AnnotationIndexTypes.FIELD_INDEX_INT).findAll();\n        assertEquals(1, results2.size());\n        assertEquals(\"C\", results2.get(0).getIndexString());\n        assertEquals(3, results2.get(0).getIndexLong());\n    }\n\n    @Test\n    public void sortAndDistinctRealmAny() {\n        // Dataset:\n        // (FIELD_INDEX_LONG, FIELD_INDEX_INT, FIELD_INDEX_STRING)\n        // (1, 1, \"A\")\n        // (2, 1, \"B\")\n        // (3, 1, \"C\")\n        // Depending on the sorting, distinct should pick the first element encountered.\n        // The order of sort/distinct in the query matters\n\n        // Case 1: Selecting highest numbers\n        RealmResults<AnnotationIndexTypes> results1a = realm.where(AnnotationIndexTypes.class)\n                .sort(AnnotationIndexTypes.FIELD_INDEX_LONG, Sort.DESCENDING)\n                .distinct(AnnotationIndexTypes.FIELD_INDEX_INT)\n                .findAll();\n        assertEquals(1, results1a.size());\n        assertEquals(3, results1a.get(0).getIndexLong());\n\n        RealmResults<AnnotationIndexTypes> results1b = realm.where(AnnotationIndexTypes.class)\n                .distinct(AnnotationIndexTypes.FIELD_INDEX_INT)\n                .sort(AnnotationIndexTypes.FIELD_INDEX_LONG, Sort.DESCENDING)\n                .findAll();\n        assertEquals(1, results1b.size());\n        assertEquals(1, results1b.get(0).getIndexLong());\n\n        // Case 1: Selecting lowest number numbers\n        RealmResults<AnnotationIndexTypes> results2a = realm.where(AnnotationIndexTypes.class)\n                .sort(AnnotationIndexTypes.FIELD_INDEX_LONG, Sort.ASCENDING)\n                .distinct(AnnotationIndexTypes.FIELD_INDEX_INT)\n                .findAll();\n        assertEquals(1, results2a.size());\n        assertEquals(1, results2a.get(0).getIndexLong());\n\n        RealmResults<AnnotationIndexTypes> results2b = realm.where(AnnotationIndexTypes.class)\n                .distinct(AnnotationIndexTypes.FIELD_INDEX_INT)\n                .sort(AnnotationIndexTypes.FIELD_INDEX_LONG, Sort.ASCENDING)\n                .findAll();\n        assertEquals(1, results2b.size());\n        assertEquals(1, results2b.get(0).getIndexLong());\n    }\n\n    @Test\n    public void sortByChildValue() {\n        RealmResults<AllTypes> result = realm.where(AllTypes.class)\n                .sort(AllTypes.FIELD_REALMOBJECT + \".\" + Dog.FIELD_NAME, Sort.ASCENDING)\n                .findAll();\n\n        assertEquals(\"A\", result.first().getColumnRealmObject().getName());\n        assertEquals(\"D\", result.last().getColumnRealmObject().getName());\n    }\n\n    private void createAndTest(String str) {\n        realm.beginTransaction();\n        realm.delete(StringOnly.class);\n        for (int i = 0; i < str.length(); i++) {\n            StringOnly stringOnly = realm.createObject(StringOnly.class);\n            stringOnly.setChars(str.substring(i, i + 1));\n        }\n        realm.commitTransaction();\n        RealmResults<StringOnly> stringOnlies = realm.where(StringOnly.class).sort(\"chars\").findAll();\n        for (int i = 0; i < chars.length(); i++) {\n            assertEquals(chars.substring(i, i + 1), stringOnlies.get(i).getChars());\n        }\n    }\n\n    // permute and swap: http://www.geeksforgeeks.org/write-a-c-program-to-print-all-permutations-of-a-given-string/\n    private void permute(String str, int l, int r) {\n        if (l == r) {\n            numberOfPermutations++;\n            createAndTest(str);\n        } else {\n            for (int i = l; i <= r; i++) {\n                str = swap(str,l,i);\n                permute(str, l+1, r);\n                str = swap(str,l,i);\n            }\n        }\n    }\n\n    private String swap(String a, int i, int j) {\n        char temp;\n        char[] charArray = a.toCharArray();\n        temp = charArray[i] ;\n        charArray[i] = charArray[j];\n        charArray[j] = temp;\n        return String.valueOf(charArray);\n    }\n\n    private int factorial(int n) {\n        int fac = 1;\n        for(int i = 1; i <= n; i++) {\n            fac *= i;\n        }\n        return fac;\n    }\n\n    @Test\n    public void sortCaseSensitive() {\n        chars = \"'- !\\\"#$%&()*,./:;?_+<=>123aAbBcCxXyYzZ\";\n        createAndTest(new StringBuilder(chars).reverse().toString());\n\n        // try all permutations - keep the list short\n        chars = \"12aAbB\";\n        numberOfPermutations = 0;\n        permute(chars, 0, chars.length()-1);\n        assertEquals(numberOfPermutations, factorial(chars.length()));\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/TypeBasedNotificationsTests.java",
    "content": "/*\n * Copyright 2015 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 */\npackage io.realm;\n\nimport android.content.Context;\nimport android.os.Build;\nimport androidx.test.platform.app.InstrumentationRegistry;\nimport androidx.test.ext.junit.runners.AndroidJUnit4;\nimport android.util.Base64;\n\nimport org.json.JSONException;\nimport org.json.JSONObject;\nimport org.junit.Before;\nimport org.junit.Rule;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\n\nimport java.io.IOException;\nimport java.io.InputStream;\nimport java.nio.charset.Charset;\nimport java.util.Date;\nimport java.util.concurrent.CountDownLatch;\nimport java.util.concurrent.atomic.AtomicInteger;\n\nimport io.realm.entities.AllTypes;\nimport io.realm.entities.AllTypesPrimaryKey;\nimport io.realm.entities.Dog;\nimport io.realm.entities.PrimaryKeyAsLong;\nimport io.realm.rule.RunInLooperThread;\nimport io.realm.rule.RunTestInLooperThread;\n\nimport static org.hamcrest.number.OrderingComparison.greaterThanOrEqualTo;\nimport static org.junit.Assert.assertArrayEquals;\nimport static org.junit.Assert.assertEquals;\nimport static org.junit.Assert.assertNull;\nimport static org.junit.Assert.assertTrue;\nimport static org.junit.Assert.fail;\nimport static org.junit.Assume.assumeThat;\n\n@RunWith(AndroidJUnit4.class)\npublic class TypeBasedNotificationsTests {\n\n    private static final Charset UTF_8 = Charset.forName(\"UTF-8\");\n\n    @Rule\n    public final RunInLooperThread looperThread = new RunInLooperThread();\n    @Rule\n    public final TestRealmConfigurationFactory configFactory = new TestRealmConfigurationFactory();\n\n    private AtomicInteger globalCommitInvocations;\n    private AtomicInteger typebasedCommitInvocations;\n    private Context context;\n\n    @Before\n    public void setUp() {\n        context = InstrumentationRegistry.getInstrumentation().getTargetContext();\n        globalCommitInvocations = new AtomicInteger(0);\n        typebasedCommitInvocations = new AtomicInteger(0);\n    }\n\n    // ****************************************************************************************** //\n    // UC 0.\n    // Callback should be notified if we create a RealmObject without the async mechanism.\n    // ex: using (createObject, copyOrUpdate, createObjectFromJson etc.)\n    // ***************************************************************************************** //\n\n    //UC 0 Uses Realm.createObject.\n    @Test\n    @RunTestInLooperThread\n    public void callback_should_trigger_for_createObject() {\n        final Realm realm = looperThread.getRealm();\n        realm.addChangeListener(new RealmChangeListener<Realm>() {\n            @Override\n            public void onChange(Realm object) {\n                if (globalCommitInvocations.incrementAndGet() == 1) {\n                    looperThread.postRunnable(new Runnable() {\n                        @Override\n                        public void run() {\n                            assertEquals(1, typebasedCommitInvocations.get());\n                            looperThread.testComplete();\n                        }\n                    });\n                }\n            }\n        });\n\n        realm.beginTransaction();\n        final Dog dog = realm.createObject(Dog.class);\n        realm.commitTransaction();\n\n        looperThread.keepStrongReference(dog);\n        dog.addChangeListener(new RealmChangeListener<Dog>() {\n            @Override\n            public void onChange(Dog object) {\n                assertEquals(\"Akamaru\", dog.getName());\n                typebasedCommitInvocations.incrementAndGet();\n            }\n        });\n\n        realm.beginTransaction();\n        dog.setName(\"Akamaru\");\n        realm.commitTransaction();\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void callback_should_trigger_for_createObject_dynamic_realm() {\n        final DynamicRealm realm = DynamicRealm.getInstance(looperThread.getConfiguration());\n        looperThread.keepStrongReference(realm);\n        realm.addChangeListener(new RealmChangeListener<DynamicRealm>() {\n            @Override\n            public void onChange(DynamicRealm object) {\n                if (globalCommitInvocations.incrementAndGet() == 1) {\n                    looperThread.postRunnable(new Runnable() {\n                        @Override\n                        public void run() {\n                            realm.close();\n                            assertEquals(1, typebasedCommitInvocations.get());\n                            looperThread.testComplete();\n                        }\n                    });\n                }\n            }\n        });\n\n        realm.beginTransaction();\n        final DynamicRealmObject dog = realm.createObject(\"Dog\");\n        realm.commitTransaction();\n\n        looperThread.keepStrongReference(dog);\n        dog.addChangeListener(new RealmChangeListener<DynamicRealmObject>() {\n            @Override\n            public void onChange(DynamicRealmObject object) {\n                assertEquals(\"Akamaru\", dog.getString(\"name\"));\n                typebasedCommitInvocations.incrementAndGet();\n            }\n        });\n\n        realm.beginTransaction();\n        dog.setString(\"name\", \"Akamaru\");\n        realm.commitTransaction();\n    }\n\n    //UC 0 Uses Realm.copyToRealm.\n    @Test\n    @RunTestInLooperThread\n    public void callback_should_trigger_for_copyToRealm() {\n        final Realm realm = looperThread.getRealm();\n        realm.addChangeListener(new RealmChangeListener<Realm>() {\n            @Override\n            public void onChange(Realm object) {\n                if (globalCommitInvocations.incrementAndGet() == 1) {\n                    looperThread.postRunnable(new Runnable() {\n                        @Override\n                        public void run() {\n                            assertEquals(1, typebasedCommitInvocations.get());\n                            looperThread.testComplete();\n                        }\n                    });\n                }\n            }\n        });\n\n        realm.beginTransaction();\n        Dog akamaru = new Dog();\n        akamaru.setName(\"Akamaru\");\n        final Dog dog = realm.copyToRealm(akamaru);\n        realm.commitTransaction();\n\n        looperThread.keepStrongReference(dog);\n        dog.addChangeListener(new RealmChangeListener<Dog>() {\n            @Override\n            public void onChange(Dog object) {\n                assertEquals(8, dog.getAge());\n                typebasedCommitInvocations.incrementAndGet();\n            }\n        });\n\n        realm.beginTransaction();\n        dog.setAge(8);\n        realm.commitTransaction();\n    }\n\n    //UC 0 Uses Realm.copyToRealmOrUpdate.\n    @Test\n    @RunTestInLooperThread\n    public void callback_should_trigger_for_copyToRealmOrUpdate() {\n        final Realm realm = looperThread.getRealm();\n        realm.addChangeListener(new RealmChangeListener<Realm>() {\n            @Override\n            public void onChange(Realm object) {\n                if (globalCommitInvocations.incrementAndGet() == 1) {\n                    looperThread.postRunnable(new Runnable() {\n                        @Override\n                        public void run() {\n                            assertEquals(1, typebasedCommitInvocations.get());\n                            looperThread.testComplete();\n                        }\n                    });\n                }\n            }\n        });\n\n        PrimaryKeyAsLong obj = new PrimaryKeyAsLong();\n        obj.setId(1);\n        obj.setName(\"Foo\");\n\n        realm.beginTransaction();\n        final PrimaryKeyAsLong primaryKeyAsLong = realm.copyToRealmOrUpdate(obj);\n        realm.commitTransaction();\n\n        looperThread.keepStrongReference(primaryKeyAsLong);\n        primaryKeyAsLong.addChangeListener(new RealmChangeListener<PrimaryKeyAsLong>() {\n            @Override\n            public void onChange(PrimaryKeyAsLong object) {\n                assertEquals(1, primaryKeyAsLong.getId());\n                assertEquals(\"Bar\", primaryKeyAsLong.getName());\n                assertEquals(1, realm.where(PrimaryKeyAsLong.class).count());\n                typebasedCommitInvocations.incrementAndGet();\n            }\n        });\n\n        PrimaryKeyAsLong obj2 = new PrimaryKeyAsLong();\n        obj2.setId(1);\n        obj2.setName(\"Bar\");\n        realm.beginTransaction();\n        PrimaryKeyAsLong primaryKeyAsLong2 = realm.copyToRealmOrUpdate(obj2);\n        realm.commitTransaction();\n\n        assertEquals(primaryKeyAsLong, primaryKeyAsLong2);\n    }\n\n    //UC 0 Uses Realm.copyToRealmOrUpdate.\n    @Test\n    @RunTestInLooperThread\n    public void callback_should_trigger_for_createObjectFromJson() {\n        assumeThat(Build.VERSION.SDK_INT, greaterThanOrEqualTo(Build.VERSION_CODES.HONEYCOMB));\n\n        final Realm realm = looperThread.getRealm();\n        try {\n            InputStream in = TestHelper.loadJsonFromAssets(InstrumentationRegistry.getInstrumentation().getTargetContext(), \"all_simple_types.json\");\n            realm.beginTransaction();\n            final AllTypes objectFromJson = realm.createObjectFromJson(AllTypes.class, in);\n            realm.commitTransaction();\n            in.close();\n\n            looperThread.keepStrongReference(objectFromJson);\n            objectFromJson.addChangeListener(new RealmChangeListener<AllTypes>() {\n                @Override\n                public void onChange(AllTypes object) {\n                    assertEquals(\"ObjectFromJson\", objectFromJson.getColumnString());\n                    assertEquals(1L, objectFromJson.getColumnLong());\n                    assertEquals(1.23F, objectFromJson.getColumnFloat(), 0F);\n                    assertEquals(1.23D, objectFromJson.getColumnDouble(), 0D);\n                    assertEquals(true, objectFromJson.isColumnBoolean());\n                    assertArrayEquals(new byte[]{1, 2, 3}, objectFromJson.getColumnBinary());\n                    looperThread.testComplete();\n                }\n            });\n\n            realm.beginTransaction();\n            objectFromJson.setColumnString(\"ObjectFromJson\");\n            realm.commitTransaction();\n\n        } catch (IOException e) {\n            fail(e.getMessage());\n        }\n    }\n\n    //UC 0 Uses Realm.copyToRealmOrUpdate.\n    @Test\n    @RunTestInLooperThread\n    public void callback_should_trigger_for_createObjectFromJson_from_JSONObject() {\n        final Realm realm = looperThread.getRealm();\n\n        try {\n            JSONObject json = new JSONObject();\n            json.put(\"columnString\", \"String\");\n            json.put(\"columnLong\", 1L);\n            json.put(\"columnFloat\", 1.23f);\n            json.put(\"columnDouble\", 1.23d);\n            json.put(\"columnBoolean\", true);\n            json.put(\"columnBinary\", new String(Base64.encode(new byte[]{1, 2, 3}, Base64.DEFAULT), UTF_8));\n\n            realm.beginTransaction();\n            final AllTypes objectFromJson = realm.createObjectFromJson(AllTypes.class, json);\n            realm.commitTransaction();\n\n            looperThread.keepStrongReference(objectFromJson);\n            objectFromJson.addChangeListener(new RealmChangeListener<AllTypes>() {\n                @Override\n                public void onChange(AllTypes object) {\n                    assertEquals(\"ObjectFromJson\", objectFromJson.getColumnString());\n                    assertEquals(1L, objectFromJson.getColumnLong());\n                    assertEquals(1.23F, objectFromJson.getColumnFloat(), 0F);\n                    assertEquals(1.23D, objectFromJson.getColumnDouble(), 0D);\n                    assertEquals(true, objectFromJson.isColumnBoolean());\n                    assertArrayEquals(new byte[]{1, 2, 3}, objectFromJson.getColumnBinary());\n                    looperThread.testComplete();\n                }\n            });\n\n            realm.beginTransaction();\n            objectFromJson.setColumnString(\"ObjectFromJson\");\n            realm.commitTransaction();\n\n        } catch (JSONException e) {\n            fail(e.getMessage());\n        }\n    }\n\n    //UC 0 Uses Realm.createOrUpdateObjectFromJson.\n    @Test\n    @RunTestInLooperThread\n    public void callback_should_trigger_for_createOrUpdateObjectFromJson() {\n        assumeThat(Build.VERSION.SDK_INT, greaterThanOrEqualTo(Build.VERSION_CODES.HONEYCOMB));\n\n        final Realm realm = looperThread.getRealm();\n        realm.addChangeListener(new RealmChangeListener<Realm>() {\n            @Override\n            public void onChange(Realm object) {\n                if (globalCommitInvocations.incrementAndGet() == 1) {\n                    looperThread.postRunnable(new Runnable() {\n                        @Override\n                        public void run() {\n                            assertEquals(1, typebasedCommitInvocations.get());\n                            looperThread.testComplete();\n                        }\n                    });\n                }\n            }\n        });\n\n        try {\n            AllTypesPrimaryKey obj = new AllTypesPrimaryKey();\n            Date date = new Date(0);\n            // ID\n            obj.setColumnLong(1);\n            obj.setColumnBinary(new byte[]{1});\n            obj.setColumnBoolean(true);\n            obj.setColumnDate(date);\n            obj.setColumnDouble(1);\n            obj.setColumnFloat(1);\n            obj.setColumnString(\"1\");\n            realm.beginTransaction();\n            realm.copyToRealm(obj);\n            realm.commitTransaction();\n\n            InputStream in = TestHelper.loadJsonFromAssets(context, \"all_types_primary_key_field_only.json\");\n            realm.beginTransaction();\n            final AllTypesPrimaryKey objectFromJson = realm.createOrUpdateObjectFromJson(AllTypesPrimaryKey.class, in);\n            realm.commitTransaction();\n            in.close();\n\n            looperThread.keepStrongReference(objectFromJson);\n            objectFromJson.addChangeListener(new RealmChangeListener<AllTypesPrimaryKey>() {\n                @Override\n                public void onChange(AllTypesPrimaryKey object) {\n                    assertEquals(\"ObjectFromJson\", objectFromJson.getColumnString());\n                    assertEquals(1L, objectFromJson.getColumnLong());\n                    assertEquals(1F, objectFromJson.getColumnFloat(), 0F);\n                    assertEquals(1D, objectFromJson.getColumnDouble(), 0D);\n                    assertEquals(true, objectFromJson.isColumnBoolean());\n                    assertArrayEquals(new byte[]{1}, objectFromJson.getColumnBinary());\n                    assertNull(objectFromJson.getColumnRealmObject());\n                    assertEquals(0, objectFromJson.getColumnRealmList().size());\n                    typebasedCommitInvocations.incrementAndGet();\n                }\n            });\n\n            realm.beginTransaction();\n            objectFromJson.setColumnString(\"ObjectFromJson\");\n            realm.commitTransaction();\n\n        } catch (IOException e) {\n            fail(e.getMessage());\n        }\n    }\n\n    //UC 0 Uses Realm.copyToRealmOrUpdate.\n    @Test\n    @RunTestInLooperThread\n    public void callback_should_trigger_for_createOrUpdateObjectFromJson_from_JSONObject() throws JSONException {\n        final Realm realm = looperThread.getRealm();\n        realm.addChangeListener(new RealmChangeListener<Realm>() {\n            @Override\n            public void onChange(Realm object) {\n                looperThread.postRunnable(new Runnable() {\n                    @Override\n                    public void run() {\n                        assertEquals(1, typebasedCommitInvocations.get());\n                        looperThread.testComplete();\n                    }\n                });\n            }\n        });\n\n        AllTypesPrimaryKey obj = new AllTypesPrimaryKey();\n        obj.setColumnLong(1);\n        obj.setColumnString(\"Foo\");\n\n        realm.beginTransaction();\n        realm.copyToRealm(obj);\n        realm.commitTransaction();\n\n\n        JSONObject json = new JSONObject();\n        json.put(\"columnLong\", 1);\n        json.put(\"columnString\", \"bar\");\n\n        realm.beginTransaction();\n        final AllTypesPrimaryKey newObj = realm.createOrUpdateObjectFromJson(AllTypesPrimaryKey.class, json);\n        realm.commitTransaction();\n\n        looperThread.keepStrongReference(newObj);\n        newObj.addChangeListener(new RealmChangeListener<AllTypesPrimaryKey>() {\n            @Override\n            public void onChange(AllTypesPrimaryKey object) {\n                assertEquals(1, realm.where(AllTypesPrimaryKey.class).count());\n                assertEquals(\"bar\", newObj.getColumnString());\n                assertTrue(newObj.getColumnBoxedBoolean());\n                typebasedCommitInvocations.incrementAndGet();\n            }\n        });\n\n        realm.beginTransaction();\n        newObj.setColumnBoxedBoolean(Boolean.TRUE);\n        realm.commitTransaction();\n    }\n\n    // ********************************************************************************* //\n    // UC 1.\n    // Callback should be invoked after a relevant commit. (one that should impact the\n    // query from which we obtained our RealmObject or RealmResults.)\n    // ********************************************************************************* //\n    // UC 1 for Sync RealmObject\n    @Test\n    @RunTestInLooperThread\n    public void callback_with_relevant_commit_realmobject_sync() {\n        final Realm realm = looperThread.getRealm();\n\n        // Step 1: Creates object\n        realm.beginTransaction();\n        final Dog akamaru = realm.createObject(Dog.class);\n        akamaru.setName(\"Akamaru\");\n        realm.commitTransaction();\n\n        final Dog dog = realm.where(Dog.class).findFirst();\n        looperThread.keepStrongReference(dog);\n        dog.addChangeListener(new RealmChangeListener<Dog>() {\n            @Override\n            public void onChange(Dog object) {\n                // Step 3: Responds to relevant change.\n                typebasedCommitInvocations.incrementAndGet();\n                assertEquals(\"Akamaru\", dog.getName());\n                assertEquals(17, dog.getAge());\n                looperThread.testComplete();\n            }\n        });\n\n        // Step 2: Trigger non-related commit\n        realm.executeTransactionAsync(new Realm.Transaction() {\n            @Override\n            public void execute(Realm realm) {\n            }\n        });\n\n        realm.executeTransactionAsync(new Realm.Transaction() {\n            @Override\n            public void execute(Realm realm) {\n                realm.where(Dog.class).findFirst().setAge(17);\n            }\n        });\n    }\n\n    // UC 1 Async RealmObject.\n    @Test\n    @RunTestInLooperThread\n    public void callback_with_relevant_commit_realmobject_async() {\n        final Realm realm = looperThread.getRealm();\n\n        // Step 1: Creates object.\n        realm.beginTransaction();\n        final Dog akamaru = realm.createObject(Dog.class);\n        akamaru.setName(\"Akamaru\");\n        realm.commitTransaction();\n\n        final Dog dog = realm.where(Dog.class).findFirstAsync();\n\n        looperThread.keepStrongReference(dog);\n        dog.addChangeListener(new RealmChangeListener<Dog>() {\n            @Override\n            public void onChange(Dog object) {\n                switch (typebasedCommitInvocations.incrementAndGet()) {\n                    case 1:\n                        // Async query returns.\n                        assertEquals(\"Akamaru\", dog.getName());\n                        assertEquals(0, dog.getAge());\n\n                        // Step 2: Triggers non-related commit.\n                        realm.executeTransactionAsync(new Realm.Transaction() {\n                            @Override\n                            public void execute(Realm realm) {\n                            }\n                        });\n\n                        // Step 3: Triggers related commit.\n                        realm.executeTransactionAsync(new Realm.Transaction() {\n                            @Override\n                            public void execute(Realm realm) {\n                                realm.where(Dog.class).findFirst().setAge(17);\n                            }\n                        });\n                        break;\n\n                    case 2:\n                        // Step 4: Responds to relevant change.\n                        assertEquals(17, dog.getAge());\n                        looperThread.testComplete();\n                        break;\n                    default:\n                        fail();\n                }\n            }\n        });\n    }\n\n    // UC 1 Sync RealmResults.\n    @Test\n    @RunTestInLooperThread\n    public void callback_with_relevant_commit_realmresults_sync() {\n        final Realm realm = looperThread.getRealm();\n\n        // Step 1: Creates object.\n        realm.beginTransaction();\n        final Dog akamaru = realm.createObject(Dog.class);\n        akamaru.setName(\"Akamaru\");\n        realm.commitTransaction();\n\n        final RealmResults<Dog> dogs = realm.where(Dog.class).findAll();\n        looperThread.keepStrongReference(dogs);\n        dogs.addChangeListener(new RealmChangeListener<RealmResults<Dog>>() {\n            @Override\n            public void onChange(RealmResults<Dog> object) {\n                // Step 4: Responds to relevant change.\n                typebasedCommitInvocations.incrementAndGet();\n                assertEquals(1, dogs.size());\n                assertEquals(\"Akamaru\", dogs.get(0).getName());\n                assertEquals(17, dogs.get(0).getAge());\n                looperThread.testComplete();\n            }\n        });\n\n        // Step 2: Trigger non-related commit. If this triggered the results listener, assertion will happen there.\n        realm.executeTransactionAsync(new Realm.Transaction() {\n            @Override\n            public void execute(Realm realm) {\n            }\n        });\n\n        // Step 3: Triggers related commit.\n        realm.executeTransactionAsync(new Realm.Transaction() {\n            @Override\n            public void execute(Realm realm) {\n                realm.where(Dog.class).findFirst().setAge(17);\n            }\n        });\n    }\n\n    // UC 1 Async RealmResults.\n    @Test\n    @RunTestInLooperThread\n    public void callback_with_relevant_commit_realmresults_async() {\n        final Realm realm = looperThread.getRealm();\n\n        // Step 1: Creates object.\n        realm.beginTransaction();\n        final Dog akamaru = realm.createObject(Dog.class);\n        akamaru.setName(\"Akamaru\");\n        realm.commitTransaction();\n\n        final RealmResults<Dog> dogs = realm.where(Dog.class).findAllAsync();\n        looperThread.keepStrongReference(dogs);\n        dogs.addChangeListener(new RealmChangeListener<RealmResults<Dog>>() {\n            @Override\n            public void onChange(RealmResults<Dog> object) {\n                // Step 4: Responds to relevant change.\n                int commits = typebasedCommitInvocations.incrementAndGet();\n                switch (commits) {\n                    case 1:\n                        // Async query returns.\n                        assertEquals(1, dogs.size());\n                        assertEquals(\"Akamaru\", dogs.get(0).getName());\n                        // Step 2: Trigger non-related commit. If this triggered the results listener,\n                        // assertion will happen there.\n                        realm.executeTransactionAsync(new Realm.Transaction() {\n                            @Override\n                            public void execute(Realm realm) {\n                            }\n                        });\n\n                        // Step 3: Triggers related commit.\n                        realm.executeTransactionAsync(new Realm.Transaction() {\n                            @Override\n                            public void execute(Realm realm) {\n                                realm.where(Dog.class).findFirst().setAge(17);\n                            }\n                        });\n                        break;\n                    case 2:\n                        assertEquals(17, dogs.get(0).getAge());\n                        looperThread.testComplete();\n                        break;\n                    default:\n                        fail();\n                }\n            }\n        });\n    }\n\n    // ********************************************************************************* //\n    // UC 2.\n    // Multiple callbacks should be invoked after a relevant commit.\n    // ********************************************************************************* //\n    // UC 2 for Sync RealmObject.\n    @Test\n    @RunTestInLooperThread\n    public void multiple_callbacks_should_be_invoked_realmobject_sync() {\n        final int NUMBER_OF_LISTENERS = 7;\n        final Realm realm = looperThread.getRealm();\n        realm.addChangeListener(new RealmChangeListener<Realm>() {\n            @Override\n            public void onChange(Realm object) {\n                looperThread.postRunnable(new Runnable() {\n                    @Override\n                    public void run() {\n                        assertEquals(NUMBER_OF_LISTENERS, typebasedCommitInvocations.get());\n                        looperThread.testComplete();\n                    }\n                });\n            }\n        });\n\n        realm.beginTransaction();\n        Dog akamaru = realm.createObject(Dog.class);\n        realm.commitTransaction();\n\n        Dog dog = realm.where(Dog.class).findFirst();\n        looperThread.keepStrongReference(dog);\n        for (int i = 0; i < NUMBER_OF_LISTENERS; i++) {\n            dog.addChangeListener(new RealmChangeListener<Dog>() {\n                @Override\n                public void onChange(Dog object) {\n                    typebasedCommitInvocations.incrementAndGet();\n                }\n            });\n        }\n\n        realm.beginTransaction();\n        akamaru.setAge(17);\n        realm.commitTransaction();\n    }\n\n    // UC 2 Async RealmObject.\n    @Test\n    @RunTestInLooperThread\n    public void multiple_callbacks_should_be_invoked_realmobject_async() {\n        final int NUMBER_OF_LISTENERS = 7;\n        final Realm realm = looperThread.getRealm();\n\n        realm.beginTransaction();\n        Dog akamaru = realm.createObject(Dog.class);\n        realm.commitTransaction();\n\n        Dog dog = realm.where(Dog.class).findFirstAsync();\n        assertTrue(dog.load());\n        looperThread.keepStrongReference(dog);\n        for (int i = 0; i < NUMBER_OF_LISTENERS; i++) {\n            dog.addChangeListener(new RealmChangeListener<Dog>() {\n                @Override\n                public void onChange(Dog object) {\n                    typebasedCommitInvocations.incrementAndGet();\n                    if (typebasedCommitInvocations.get() > NUMBER_OF_LISTENERS) {\n                        fail();\n                    } else if (typebasedCommitInvocations.get() == NUMBER_OF_LISTENERS) {\n                        // Delayed post in case the listener gets triggered more time than expected.\n                        looperThread.postRunnableDelayed(new Runnable() {\n                            @Override\n                            public void run() {\n                                looperThread.testComplete();\n                            }\n                        }, 500);\n                    }\n                }\n            });\n        }\n\n        realm.beginTransaction();\n        akamaru.setAge(17);\n        realm.commitTransaction();\n    }\n\n    // UC 2 Sync RealmResults.\n    @Test\n    @RunTestInLooperThread\n    public void multiple_callbacks_should_be_invoked_realmresults_sync() {\n        final int NUMBER_OF_LISTENERS = 7;\n        final Realm realm = looperThread.getRealm();\n\n        realm.beginTransaction();\n        Dog akamaru = realm.createObject(Dog.class);\n        realm.commitTransaction();\n\n        RealmResults<Dog> dogs = realm.where(Dog.class).findAll();\n        looperThread.keepStrongReference(dogs);\n        for (int i = 0; i < NUMBER_OF_LISTENERS; i++) {\n            dogs.addChangeListener(new RealmChangeListener<RealmResults<Dog>>() {\n                @Override\n                public void onChange(RealmResults<Dog> results) {\n                    assertEquals(17, results.first().getAge());\n                    if (typebasedCommitInvocations.incrementAndGet() == NUMBER_OF_LISTENERS) {\n                        looperThread.testComplete();\n                    }\n                    assertTrue(typebasedCommitInvocations.get() <= NUMBER_OF_LISTENERS);\n                }\n            });\n        }\n\n        realm.beginTransaction();\n        akamaru.setAge(17);\n        realm.commitTransaction();\n    }\n\n    // UC 2 Async RealmResults.\n    @Test\n    @RunTestInLooperThread\n    public void multiple_callbacks_should_be_invoked_realmresults_async() {\n        final int NUMBER_OF_LISTENERS = 7;\n        final Realm realm = looperThread.getRealm();\n\n        realm.beginTransaction();\n        Dog akamaru = realm.createObject(Dog.class);\n        realm.commitTransaction();\n\n        realm.addChangeListener(new RealmChangeListener<Realm>() {\n            @Override\n            public void onChange(Realm object) {\n                looperThread.postRunnableDelayed(new Runnable() {\n                    @Override\n                    public void run() {\n                        assertEquals(NUMBER_OF_LISTENERS, typebasedCommitInvocations.get());\n                        looperThread.testComplete();\n                    }\n                }, 100L /* wait for listeners in RealmResults. Next run loop is not enough. */);\n            }\n        });\n\n        RealmResults<Dog> dogs = realm.where(Dog.class).findAllAsync();\n        assertTrue(dogs.load());\n\n        looperThread.keepStrongReference(dogs);\n        for (int i = 0; i < NUMBER_OF_LISTENERS; i++) {\n            dogs.addChangeListener(new RealmChangeListener<RealmResults<Dog>>() {\n                @Override\n                public void onChange(RealmResults<Dog> object) {\n                    typebasedCommitInvocations.incrementAndGet();\n                }\n            });\n        }\n\n        realm.beginTransaction();\n        akamaru.setAge(17);\n        realm.commitTransaction();\n    }\n\n    // ********************************************************************************* //\n    // UC 3.\n    // Callback should be invoked when a non Looper thread commits.\n    // ********************************************************************************* //\n\n    // UC 3 for Sync RealmObject.\n    // 1. Adds listener to RealmObject which is queried synchronized.\n    // 2. Commits transaction in another non-looper thread.\n    // 3. Listener on the RealmObject gets triggered.\n    @Test\n    @RunTestInLooperThread\n    public void non_looper_thread_commit_realmobject_sync() {\n        final Realm realm = looperThread.getRealm();\n\n        realm.beginTransaction();\n        realm.createObject(Dog.class);\n        realm.commitTransaction();\n\n        Dog dog = realm.where(Dog.class).findFirst();\n        looperThread.keepStrongReference(dog);\n        dog.addChangeListener(new RealmChangeListener<Dog>() {\n            @Override\n            public void onChange(Dog object) {\n                assertEquals(17, object.getAge());\n                looperThread.testComplete();\n            }\n        });\n\n        realm.executeTransactionAsync(new Realm.Transaction() {\n            @Override\n            public void execute(Realm realm) {\n                realm.where(Dog.class).findFirst().setAge(17);\n            }\n        });\n    }\n\n    // UC 3 Async RealmObject.\n    // 1. Creates RealmObject async query.\n    // 2. Waits async returns then change the object.\n    // 3. Listener on the RealmObject gets triggered again.\n    @Test\n    @RunTestInLooperThread\n    public void non_looper_thread_commit_realmobject_async() {\n        final Realm realm = looperThread.getRealm();\n\n        realm.beginTransaction();\n        realm.createObject(Dog.class).setAge(1);\n        realm.commitTransaction();\n\n        Dog dog = realm.where(Dog.class).findFirstAsync();\n        looperThread.keepStrongReference(dog);\n        dog.addChangeListener(new RealmChangeListener<Dog>() {\n            @Override\n            public void onChange(Dog object) {\n                switch (typebasedCommitInvocations.incrementAndGet()) {\n                    case 1:\n                        assertEquals(1, object.getAge());\n                        realm.executeTransactionAsync(new Realm.Transaction() {\n                            @Override\n                            public void execute(Realm realm) {\n                                realm.where(Dog.class).findFirst().setAge(17);\n                            }\n                        });\n                        break;\n                    case 2:\n                        assertEquals(17, object.getAge());\n                        looperThread.testComplete();\n                        break;\n                    default:\n                        fail();\n                }\n            }\n        });\n    }\n\n    // UC 3 Sync RealmResults.\n    // 1. Adds listener to RealmResults which is queried synchronized.\n    // 2. Commits transaction in another non-looper thread.\n    // 3. Listener on the RealmResults gets triggered.\n    @Test\n    @RunTestInLooperThread\n    public void non_looper_thread_commit_realmresults_sync() {\n        final Realm realm = looperThread.getRealm();\n        realm.addChangeListener(new RealmChangeListener<Realm>() {\n            @Override\n            public void onChange(Realm object) {\n                if (realm.where(Dog.class).count() == 2) {\n                    looperThread.postRunnable(new Runnable() {\n                        @Override\n                        public void run() {\n                            assertEquals(1, typebasedCommitInvocations.get());\n                            looperThread.testComplete();\n                        }\n                    });\n                }\n            }\n        });\n\n        realm.beginTransaction();\n        realm.createObject(Dog.class);\n        realm.commitTransaction();\n\n        final RealmResults<Dog> dogs = realm.where(Dog.class).findAll();\n        looperThread.keepStrongReference(dogs);\n        dogs.addChangeListener(new RealmChangeListener<RealmResults<Dog>>() {\n            @Override\n            public void onChange(RealmResults<Dog> object) {\n                typebasedCommitInvocations.incrementAndGet();\n                assertEquals(2, dogs.size());\n            }\n        });\n\n        Thread thread = new Thread() {\n            @Override\n            public void run() {\n                Realm bgRealm = Realm.getInstance(realm.getConfiguration());\n                bgRealm.beginTransaction();\n                bgRealm.createObject(Dog.class);\n                bgRealm.commitTransaction();\n                bgRealm.close();\n            }\n        };\n        thread.start();\n        try {\n            thread.join();\n        } catch (InterruptedException e) {\n            fail(e.getMessage());\n        }\n    }\n\n    // UC 3 Async RealmResults.\n    // 1. Creates RealmResults async query.\n    // 2. Waits COMPLETED_ASYNC_REALM_RESULTS then commits transaction in another non-looper thread.\n    // 3. Listener on the RealmResults gets triggered again.\n    @Test\n    @RunTestInLooperThread\n    public void non_looper_thread_commit_realmresults_async() {\n        final Realm realm = looperThread.getRealm();\n        realm.addChangeListener(new RealmChangeListener<Realm>() {\n            @Override\n            public void onChange(Realm object) {\n                if (realm.where(Dog.class).count() == 2) {\n                    looperThread.postRunnable(new Runnable() {\n                        @Override\n                        public void run() {\n                            assertEquals(2, typebasedCommitInvocations.get());\n                            looperThread.testComplete();\n                        }\n                    });\n                }\n            }\n        });\n\n        realm.beginTransaction();\n        realm.createObject(Dog.class);\n        realm.commitTransaction();\n\n        final Thread thread = new Thread() {\n            @Override\n            public void run() {\n                Realm bgRealm = Realm.getInstance(realm.getConfiguration());\n                bgRealm.beginTransaction();\n                bgRealm.createObject(Dog.class);\n                bgRealm.commitTransaction();\n                bgRealm.close();\n            }\n        };\n\n        final RealmResults<Dog> dogs = realm.where(Dog.class).findAllAsync();\n        looperThread.keepStrongReference(dogs);\n        dogs.addChangeListener(new RealmChangeListener<RealmResults<Dog>>() {\n            @Override\n            public void onChange(RealmResults<Dog> object) {\n                typebasedCommitInvocations.incrementAndGet();\n                if (typebasedCommitInvocations.get() == 1) {\n                    // COMPLETED_ASYNC_REALM_RESULTS arrived.\n                    thread.start();\n                    try {\n                        thread.join();\n                    } catch (InterruptedException e) {\n                        fail(e.getMessage());\n                    }\n                }\n            }\n        });\n    }\n\n    // ****************************************************************************************** //\n    // UC 4.\n    // Callback should throw if registered on a non Looper thread.\n    // No tests for async RealmObject & RealmResults, since those already require a Looper thread.\n    // ***************************************************************************************** //\n\n    // UC 4 for Realm\n    @Test\n    public void should_throw_on_non_looper_thread_realm() {\n        final CountDownLatch signalTestFinished = new CountDownLatch(1);\n        new Thread() {\n            @Override\n            public void run() {\n                Realm bgRealm = Realm.getInstance(configFactory.createConfiguration());\n                try {\n                    bgRealm.beginTransaction();\n                    bgRealm.createObject(Dog.class);\n                    bgRealm.commitTransaction();\n\n                    bgRealm.addChangeListener(new RealmChangeListener<Realm>() {\n                        @Override\n                        public void onChange(Realm object) {\n                            fail(\"Callback should not be registered and invoked on a non-Looper thread\");\n                        }\n                    });\n                    fail(\"Callback should not be registered and invoked on a non-Looper thread\");\n                } catch (IllegalStateException ignored) {\n\n                } finally {\n                    bgRealm.close();\n                    signalTestFinished.countDown();\n                }\n            }\n        }.start();\n        TestHelper.awaitOrFail(signalTestFinished);\n    }\n\n    // UC 4 for RealmObject.\n    @Test\n    public void should_throw_on_non_looper_thread_realmobject() {\n        final CountDownLatch signalTestFinished = new CountDownLatch(1);\n        new Thread() {\n            @Override\n            public void run() {\n                Realm bgRealm = Realm.getInstance(configFactory.createConfiguration());\n                try {\n                    bgRealm.beginTransaction();\n                    bgRealm.createObject(Dog.class);\n                    bgRealm.commitTransaction();\n\n                    Dog dog = bgRealm.where(Dog.class).findFirst();\n                    dog.addChangeListener(new RealmChangeListener<Dog>() {\n                        @Override\n                        public void onChange(Dog object) {\n                            fail(\"Callback should not be registered and invoked on a non-Looper thread\");\n                        }\n                    });\n                    fail(\"Callback should not be registered and invoked on a non-Looper thread\");\n                } catch (IllegalStateException ignored) {\n\n                } finally {\n                    bgRealm.close();\n                    signalTestFinished.countDown();\n                }\n            }\n        }.start();\n        TestHelper.awaitOrFail(signalTestFinished);\n    }\n\n    // UC 4 RealmObject.\n    @Test\n    public void should_throw_on_non_looper_thread_realmresults() {\n        final CountDownLatch signalTestFinished = new CountDownLatch(1);\n        new Thread() {\n            @Override\n            public void run() {\n                Realm bgRealm = Realm.getInstance(configFactory.createConfiguration());\n                try {\n                    bgRealm.beginTransaction();\n                    bgRealm.createObject(Dog.class);\n                    bgRealm.commitTransaction();\n\n                    RealmResults<Dog> dogs = bgRealm.where(Dog.class).findAll();\n                    dogs.addChangeListener(new RealmChangeListener<RealmResults<Dog>>() {\n                        @Override\n                        public void onChange(RealmResults<Dog> object) {\n                            fail(\"Callback should not be registered and invoked on a non-Looper thread\");\n                        }\n                    });\n                    fail(\"Callback should not be registered and invoked on a non-Looper thread\");\n                } catch (IllegalStateException ignored) {\n\n                } finally {\n                    bgRealm.close();\n                    signalTestFinished.countDown();\n                }\n            }\n        }.start();\n        TestHelper.awaitOrFail(signalTestFinished);\n    }\n\n    // Builds a RealmResults from a RealmList, and delete the RealmList. Test the behavior of ChangeListener on the\n    // \"invalid\" RealmResults.\n    @Test\n    @RunTestInLooperThread\n    public void changeListener_onResultsBuiltOnDeletedLinkView() {\n        final Realm realm = looperThread.getRealm();\n        realm.beginTransaction();\n        AllTypes allTypes = realm.createObject(AllTypes.class);\n        for (int i = 0; i < 10; i++) {\n            Dog dog = new Dog();\n            dog.setName(\"name_\" + i);\n            allTypes.getColumnRealmList().add(dog);\n        }\n        realm.commitTransaction();\n\n        final RealmResults<Dog> dogs =\n                allTypes.getColumnRealmList().where().equalTo(Dog.FIELD_NAME, \"name_0\").findAll();\n        looperThread.keepStrongReference(dogs);\n        dogs.addChangeListener(new RealmChangeListener<RealmResults<Dog>>() {\n            @Override\n            public void onChange(RealmResults<Dog> object) {\n                if (typebasedCommitInvocations.getAndIncrement() == 0) {\n                    assertTrue(dogs.isValid());\n                    assertEquals(0, dogs.size());\n                } else {\n                    fail(\"This listener should only be called once.\");\n                }\n            }\n        });\n\n        // Triggers the listener at the first time.\n        realm.beginTransaction();\n        allTypes.deleteFromRealm();\n        realm.commitTransaction();\n\n        // Tries to trigger the listener second time.\n        realm.beginTransaction();\n        realm.commitTransaction();\n\n        // Closes the realm and finishes the test. This needs to follow the REALM_CHANGED in the queue.\n        looperThread.postRunnable(new Runnable() {\n            @Override\n            public void run() {\n                realm.close();\n                assertEquals(1, typebasedCommitInvocations.get());\n                looperThread.testComplete();\n            }\n        });\n    }\n\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/UTFStringsTests.java",
    "content": "/*\n * Copyright 2020 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 */\npackage io.realm;\n\nimport androidx.test.ext.junit.runners.AndroidJUnit4;\n\nimport org.junit.After;\nimport org.junit.Before;\nimport org.junit.Rule;\nimport org.junit.Test;\nimport org.junit.rules.ExpectedException;\nimport org.junit.runner.RunWith;\n\nimport io.realm.entities.StringOnly;\n\n@RunWith(AndroidJUnit4.class)\npublic class UTFStringsTests {\n    @Rule\n    public final TestRealmConfigurationFactory configFactory = new TestRealmConfigurationFactory();\n    @Rule\n    public final ExpectedException thrown = ExpectedException.none();\n\n    private Realm realm;\n\n    @Before\n    public void setUp() {\n        RealmConfiguration config = configFactory.createConfiguration();\n        realm = Realm.getInstance(config);\n    }\n\n    @After\n    public void tearDown() {\n        if (realm != null) {\n            realm.close();\n        }\n    }\n\n    @Test\n    public void valid_utf() {\n        realm.beginTransaction();\n\n        StringOnly validString = new StringOnly();\n        validString.setChars(\"\\uD800\\uDC00\");\n        realm.copyToRealm(validString);\n\n        realm.commitTransaction();\n    }\n\n    @Test\n    public void invalid_first_half() {\n        realm.beginTransaction();\n\n        // Test invalid first surrogate\n        StringOnly invalidFirstSurrogate = new StringOnly();\n        invalidFirstSurrogate.setChars(\"\\uDC00\\uD800\");\n\n        thrown.expect(IllegalArgumentException.class);\n        thrown.expectMessage(\"Illegal Argument: Failure when converting to UTF-8: Invalid first half of surrogate pair; error_code = 5;  0xdc00 0xd800\");\n\n        realm.copyToRealm(invalidFirstSurrogate);\n        realm.commitTransaction();\n    }\n\n    @Test\n    public void invalid_second_half() {\n        realm.beginTransaction();\n\n        // Test invalid second surrogate\n        StringOnly invalidSecondSurrogate = new StringOnly();\n        invalidSecondSurrogate.setChars(\"\\uD800\\uD800\");\n\n        thrown.expect(IllegalArgumentException.class);\n        thrown.expectMessage(\"Illegal Argument: Failure when converting to UTF-8: Invalid second half of surrogate pair; error_code = 7;  0xd800 0xd800\");\n\n        realm.copyToRealm(invalidSecondSurrogate);\n\n        realm.commitTransaction();\n    }\n\n    @Test\n    public void incomplete_surrogate() {\n        realm.beginTransaction();\n\n        // Test incomplete surrogate\n        StringOnly incompleteSurrogate = new StringOnly();\n        incompleteSurrogate.setChars(\"\\u0000\\uD800\");\n\n        thrown.expect(IllegalArgumentException.class);\n        thrown.expectMessage(\"Illegal Argument: Failure when converting to UTF-8: Incomplete surrogate pair; error_code = 6;  0x0000 0xd800\");\n\n        realm.copyToRealm(incompleteSurrogate);\n\n        realm.commitTransaction();\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/UnManagedOrderedRealmCollectionTests.java",
    "content": "/*\n * Copyright 2016 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\npackage io.realm;\n\nimport org.junit.After;\nimport org.junit.Before;\nimport org.junit.Rule;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.junit.runners.Parameterized;\n\nimport java.util.Arrays;\nimport java.util.List;\n\nimport io.realm.entities.AllJavaTypes;\n\nimport static org.junit.Assert.assertTrue;\nimport static org.junit.Assert.fail;\n\n/**\n * Test class for all methods part of the the {@link OrderedRealmCollection} interface, that have a different behavior\n * than managed RealmCollection classes.\n *\n * Methods tested in this class:\n *\n * # OrderedRealmCollection\n *\n * - E first()\n * - E last()\n * - void sort(String field)\n * - void sort(String field, Sort sortOrder)\n * - void sort(String field1, Sort sortOrder1, String field2, Sort sortOrder2)\n * - void sort(String[] fields, Sort[] sortOrders)\n * - void deleteFromRealm(int location)\n * - void deleteFirstFromRealm()\n * - void deleteLastFromRealm();\n *\n * # List\n *\n *  - void add(int location, E object);\n *  - boolean addAll(int location, Collection<? extends E> collection);\n *  - E get(int location);\n *  - int indexOf(Object object);\n *  - int lastIndexOf(Object object);\n *  - ListIterator<E> listIterator();\n *  - ListIterator<E> listIterator(int location);\n *  - E remove(int location);\n *  - E set(int location, E object);\n *  - List<E> subList(int start, int end);\n *\n * # RealmCollection\n *\n * - RealmQuery<E> where();\n * - Number min(String fieldName);\n * - Number max(String fieldName);\n * - Number sum(String fieldName);\n * - double average(String fieldName);\n * - Date maxDate(String fieldName);\n * - Date minDate(String fieldName);\n * - void deleteAllFromRealm();\n * + boolean isLoaded();\n * + boolean load();\n * + boolean isValid();\n * + BaseRealm getRealm();\n *\n * # Collection\n *\n * - public boolean add(E object);\n * - public boolean addAll(Collection<? extends E> collection);\n * - public void deleteAll();\n * - public boolean contains(Object object);\n * - public boolean containsAll(Collection<?> collection);\n * - public boolean equals(Object object);\n * - public int hashCode();\n * - public boolean isEmpty();\n * - public Iterator<E> iterator();\n * - public boolean remove(Object object);\n * - public boolean removeAll(Collection<?> collection);\n * - public boolean retainAll(Collection<?> collection);\n * - public int size();\n * - public Object[] toArray();\n * - public <T> T[] toArray(T[] array);\n **\n * See {@link ManagedOrderedRealmCollectionTests} for similar tests for the managed behavior.\n */\n@RunWith(Parameterized.class)\npublic class UnManagedOrderedRealmCollectionTests extends CollectionTests {\n\n    private static final int TEST_SIZE = 10;\n\n    @Rule\n    public final TestRealmConfigurationFactory configFactory = new TestRealmConfigurationFactory();\n\n    private final UnManagedCollection collectionClass;\n    private Realm realm;\n    private OrderedRealmCollection<AllJavaTypes> collection;\n\n    @Parameterized.Parameters(name = \"{0}\")\n    public static List<UnManagedCollection> data() {\n        return Arrays.asList(UnManagedCollection.values());\n    }\n\n    public UnManagedOrderedRealmCollectionTests(UnManagedCollection collectionType) {\n        this.collectionClass = collectionType;\n    }\n\n    @Before\n    public void setup() {\n        realm = Realm.getInstance(configFactory.createConfiguration());\n        collection = createCollection(collectionClass);\n    }\n\n    private OrderedRealmCollection<AllJavaTypes> createCollection(UnManagedCollection collectionClass) {\n        switch (collectionClass) {\n            case UNMANAGED_REALMLIST:\n                return populateInMemoryList(TEST_SIZE);\n\n            default:\n                throw new AssertionError(\"Unsupported class: \" + collectionClass);\n        }\n    }\n\n    @After\n    public void tearDown() {\n        realm.close();\n    }\n\n    @Test\n    public void unsupportedMethods_unManagedCollections() {\n        // RealmCollection methods.\n        for (OrderedRealmCollectionMethod method : OrderedRealmCollectionMethod.values()) {\n            try {\n                switch (method) {\n                    case DELETE_INDEX: collection.deleteFromRealm(0); break;\n                    case DELETE_FIRST: collection.deleteFirstFromRealm(); break;\n                    case DELETE_LAST: collection.deleteLastFromRealm(); break;\n                    case SORT: collection.sort(AllJavaTypes.FIELD_STRING); break;\n                    case SORT_FIELD: collection.sort(AllJavaTypes.FIELD_STRING, Sort.ASCENDING); break;\n                    case SORT_2FIELDS: collection.sort(AllJavaTypes.FIELD_STRING, Sort.ASCENDING, AllJavaTypes.FIELD_LONG, Sort.DESCENDING); break;\n                    case SORT_MULTI: collection.sort(new String[] { AllJavaTypes.FIELD_STRING, AllJavaTypes.FIELD_LONG }, new Sort[] { Sort.ASCENDING, Sort.DESCENDING }); break;\n                    case CREATE_SNAPSHOT: collection.createSnapshot();\n                }\n                fail(method + \" should have thrown an exception.\");\n            } catch (UnsupportedOperationException ignored) {\n            }\n        }\n    }\n\n    @Test\n    public void isLoaded() {\n        assertTrue(collection.isLoaded());\n    }\n\n    @Test\n    public void load() {\n        assertTrue(collection.load());\n    }\n\n    @Test\n    public void isValid() {\n        assertTrue(collection.isValid());\n    }\n\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/UnManagedRealmCollectionTests.java",
    "content": "/*\n * Copyright 2016 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\npackage io.realm;\n\nimport org.junit.After;\nimport org.junit.Before;\nimport org.junit.Rule;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.junit.runners.Parameterized;\n\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.List;\n\nimport io.realm.entities.AllJavaTypes;\n\nimport static org.junit.Assert.assertFalse;\nimport static org.junit.Assert.assertTrue;\nimport static org.junit.Assert.fail;\n\n/**\n * Test class for all methods part of the the {@link RealmCollection} interface, that have a different behavior\n * than managed RealmCollection classes.\n *\n * See {@link ManagedRealmCollectionTests} for similar tests for the managed behavior.\n */\n@RunWith(Parameterized.class)\npublic class UnManagedRealmCollectionTests extends CollectionTests {\n\n    private static final int TEST_SIZE = 10;\n\n    @Rule\n    public final TestRealmConfigurationFactory configFactory = new TestRealmConfigurationFactory();\n\n    private final UnManagedCollection collectionClass;\n    private Realm realm;\n    private RealmCollection<AllJavaTypes> collection;\n\n    @Parameterized.Parameters(name = \"{0}\")\n    public static List<UnManagedCollection> data() {\n        return Arrays.asList(UnManagedCollection.values());\n    }\n\n    public UnManagedRealmCollectionTests(UnManagedCollection collectionType) {\n        this.collectionClass = collectionType;\n    }\n\n    @Before\n    public void setup() {\n        realm = Realm.getInstance(configFactory.createConfiguration());\n        collection = createCollection(collectionClass);\n    }\n\n    private RealmCollection<AllJavaTypes> createCollection(UnManagedCollection collectionClass) {\n        switch (collectionClass) {\n            case UNMANAGED_REALMLIST:\n                return populateInMemoryList(TEST_SIZE);\n\n            default:\n                throw new AssertionError(\"Unsupported class: \" + collectionClass);\n        }\n    }\n\n    @After\n    public void tearDown() {\n        realm.close();\n    }\n\n    @Test\n    public void unsupportedMethods_unManagedCollections() {\n        // RealmCollection methods.\n        for (RealmCollectionMethod method : RealmCollectionMethod.values()) {\n            try {\n                switch (method) {\n                    // Unsupported methods.\n                    case WHERE: collection.where(); break;\n                    case MIN: collection.min(AllJavaTypes.FIELD_LONG); break;\n                    case MAX: collection.max(AllJavaTypes.FIELD_LONG); break;\n                    case SUM: collection.sum(AllJavaTypes.FIELD_LONG); break;\n                    case AVERAGE: collection.average(AllJavaTypes.FIELD_LONG); break;\n                    case MIN_DATE: collection.minDate(AllJavaTypes.FIELD_DATE); break;\n                    case MAX_DATE: collection.maxDate(AllJavaTypes.FIELD_DATE); break;\n                    case DELETE_ALL_FROM_REALM: collection.deleteAllFromRealm(); break;\n                    case FREEZE: collection.freeze(); break;\n\n                    // Supported methods.\n                    case IS_VALID: assertTrue(collection.isValid()); continue;\n                    case IS_MANAGED: assertFalse(collection.isManaged()); continue;\n                    case IS_FROZEN: assertFalse(collection.isFrozen()); continue;\n                }\n                fail(method + \" should have thrown an exception.\");\n            } catch (UnsupportedOperationException ignored) {\n            }\n        }\n    }\n\n    @Test\n    public void isLoaded() {\n        assertTrue(collection.isLoaded());\n    }\n\n    @Test\n    public void load() {\n        assertTrue(collection.load());\n    }\n\n    @Test\n    public void isValid() {\n        assertTrue(collection.isValid());\n    }\n\n    @Test\n    public void isManaged() {\n        assertFalse(collection.isManaged());\n    }\n\n    @Test\n    public void contains() {\n        AllJavaTypes obj = collection.iterator().next();\n        assertTrue(collection.contains(obj));\n    }\n\n    @Test\n    public void equals_sameRealmObjectsDifferentCollection() {\n        List<AllJavaTypes> list = new ArrayList<AllJavaTypes>();\n        list.addAll(collection);\n        assertTrue(collection.equals(list));\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/entities/AllJavaTypes.java",
    "content": "/*\n * Copyright 2015 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\npackage io.realm.entities;\n\nimport org.bson.types.Decimal128;\nimport org.bson.types.ObjectId;\n\nimport java.util.Date;\nimport java.util.UUID;\n\nimport io.realm.RealmAny;\nimport io.realm.RealmList;\nimport io.realm.RealmObject;\nimport io.realm.RealmResults;\nimport io.realm.annotations.Ignore;\nimport io.realm.annotations.Index;\nimport io.realm.annotations.LinkingObjects;\nimport io.realm.annotations.PrimaryKey;\n\n\npublic class AllJavaTypes extends RealmObject {\n\n    public static final String CLASS_NAME = \"AllJavaTypes\";\n\n    public static final String FIELD_IGNORED = \"fieldIgnored\";\n    public static final String FIELD_STRING = \"fieldString\";\n    public static final String FIELD_SHORT = \"fieldShort\";\n    public static final String FIELD_INT = \"fieldInt\";\n    public static final String FIELD_LONG = \"fieldLong\";\n    public static final String FIELD_ID = \"fieldId\";\n    public static final String FIELD_BYTE = \"fieldByte\";\n    public static final String FIELD_FLOAT = \"fieldFloat\";\n    public static final String FIELD_DOUBLE = \"fieldDouble\";\n    public static final String FIELD_BOOLEAN = \"fieldBoolean\";\n    public static final String FIELD_DATE = \"fieldDate\";\n    public static final String FIELD_BINARY = \"fieldBinary\";\n    public static final String FIELD_DECIMAL128 = \"fieldDecimal128\";\n    public static final String FIELD_OBJECT_ID = \"fieldObjectId\";\n    public static final String FIELD_UUID = \"fieldUUID\";\n    public static final String FIELD_REALM_ANY = \"fieldRealmAny\";\n    public static final String FIELD_OBJECT = \"fieldObject\";\n    public static final String FIELD_LIST = \"fieldList\";\n\n    public static final String FIELD_STRING_LIST = \"fieldStringList\";\n    public static final String FIELD_BINARY_LIST = \"fieldBinaryList\";\n    public static final String FIELD_BOOLEAN_LIST = \"fieldBooleanList\";\n    public static final String FIELD_LONG_LIST = \"fieldLongList\";\n    public static final String FIELD_INTEGER_LIST = \"fieldIntegerList\";\n    public static final String FIELD_SHORT_LIST = \"fieldShortList\";\n    public static final String FIELD_BYTE_LIST = \"fieldByteList\";\n    public static final String FIELD_DOUBLE_LIST = \"fieldDoubleList\";\n    public static final String FIELD_FLOAT_LIST = \"fieldFloatList\";\n    public static final String FIELD_DATE_LIST = \"fieldDateList\";\n    public static final String FIELD_DECIMAL128_LIST = \"fieldDecimal128List\";\n    public static final String FIELD_OBJECT_ID_LIST = \"fieldObjectIdList\";\n    public static final String FIELD_UUID_LIST = \"fieldUUIDList\";\n    public static final String FIELD_REALM_ANY_LIST = \"fieldRealmAnyList\";\n\n    public static final String FIELD_LO_OBJECT = \"objectParents\";\n    public static final String FIELD_LO_LIST = \"listParents\";\n\n    public static final String[] INVALID_FIELD_TYPES_FOR_DISTINCT = new String[] {\n            FIELD_OBJECT + \".\" + FIELD_LIST,\n            FIELD_OBJECT + \".\" + FIELD_STRING_LIST,\n            FIELD_OBJECT + \".\" + FIELD_BINARY_LIST,\n            FIELD_OBJECT + \".\" + FIELD_BOOLEAN_LIST,\n            FIELD_OBJECT + \".\" + FIELD_LONG_LIST,\n            FIELD_OBJECT + \".\" + FIELD_INTEGER_LIST,\n            FIELD_OBJECT + \".\" + FIELD_SHORT_LIST,\n            FIELD_OBJECT + \".\" + FIELD_BYTE_LIST,\n            FIELD_OBJECT + \".\" + FIELD_DOUBLE_LIST,\n            FIELD_OBJECT + \".\" + FIELD_FLOAT_LIST,\n            FIELD_OBJECT + \".\" + FIELD_DATE_LIST,\n            FIELD_OBJECT + \".\" + FIELD_DECIMAL128_LIST,\n            FIELD_OBJECT + \".\" + FIELD_OBJECT_ID_LIST,\n            FIELD_OBJECT + \".\" + FIELD_UUID_LIST,\n    };\n\n    @Ignore\n    private String fieldIgnored;\n    @Index\n    private String fieldString;\n    @PrimaryKey\n    private long fieldId;\n    private long fieldLong;\n    private short fieldShort;\n    private int fieldInt;\n    private byte fieldByte;\n    private float fieldFloat;\n    private double fieldDouble;\n    private boolean fieldBoolean;\n    private Date fieldDate;\n    private byte[] fieldBinary;\n    private Decimal128 fieldDecimal128;\n    private ObjectId fieldObjectId;\n    private UUID fieldUUID;\n    private RealmAny fieldRealmAny;\n    private AllJavaTypes fieldObject;\n    private RealmList<AllJavaTypes> fieldList;\n\n    private RealmList<String> fieldStringList;\n    private RealmList<byte[]> fieldBinaryList;\n    private RealmList<Boolean> fieldBooleanList;\n    private RealmList<Long> fieldLongList;\n    private RealmList<Integer> fieldIntegerList;\n    private RealmList<Short> fieldShortList;\n    private RealmList<Byte> fieldByteList;\n    private RealmList<Double> fieldDoubleList;\n    private RealmList<Float> fieldFloatList;\n    private RealmList<Date> fieldDateList;\n    private RealmList<Decimal128> fieldDecimal128List;\n    private RealmList<ObjectId> fieldObjectIdList;\n    private RealmList<UUID> fieldUUIDList;\n    private RealmList<RealmAny> fieldRealmAnyList;\n\n    @LinkingObjects(FIELD_OBJECT)\n    private final RealmResults<AllJavaTypes> objectParents = null;\n\n    @LinkingObjects(FIELD_LIST)\n    private final RealmResults<AllJavaTypes> listParents = null;\n\n    public AllJavaTypes() {\n    }\n\n    public AllJavaTypes(long fieldLong) {\n        this.fieldId = fieldLong;\n        this.fieldLong = fieldLong;\n    }\n\n    public String getFieldIgnored() {\n        return fieldIgnored;\n    }\n\n    public void setFieldIgnored(String fieldIgnored) {\n        this.fieldIgnored = fieldIgnored;\n    }\n\n    public String getFieldString() {\n        return fieldString;\n    }\n\n    public void setFieldString(String fieldString) {\n        this.fieldString = fieldString;\n    }\n\n    public short getFieldShort() {\n        return fieldShort;\n    }\n\n    public void setFieldShort(short fieldShort) {\n        this.fieldShort = fieldShort;\n    }\n\n    public long getFieldLong() {\n        return fieldLong;\n    }\n\n    public void setFieldLong(long fieldLong) {\n        this.fieldLong = fieldLong;\n    }\n\n    public int getFieldInt() {\n        return fieldInt;\n    }\n\n    public void setFieldInt(int fieldInt) {\n        this.fieldInt = fieldInt;\n    }\n\n    public long getFieldId() {\n        return fieldId;\n    }\n\n    public void setFieldId(long fieldId) {\n        this.fieldId = fieldId;\n    }\n\n    public byte getFieldByte() {\n        return fieldByte;\n    }\n\n    public void setFieldByte(byte fieldByte) {\n        this.fieldByte = fieldByte;\n    }\n\n    public float getFieldFloat() {\n        return fieldFloat;\n    }\n\n    public void setFieldFloat(float fieldFloat) {\n        this.fieldFloat = fieldFloat;\n    }\n\n    public double getFieldDouble() {\n        return fieldDouble;\n    }\n\n    public void setFieldDouble(double fieldDouble) {\n        this.fieldDouble = fieldDouble;\n    }\n\n    public boolean isFieldBoolean() {\n        return fieldBoolean;\n    }\n\n    public void setFieldBoolean(boolean fieldBoolean) {\n        this.fieldBoolean = fieldBoolean;\n    }\n\n    public Date getFieldDate() {\n        return fieldDate;\n    }\n\n    public void setFieldDate(Date fieldDate) {\n        this.fieldDate = fieldDate;\n    }\n\n    public byte[] getFieldBinary() {\n        return fieldBinary;\n    }\n\n    public void setFieldBinary(byte[] fieldBinary) {\n        this.fieldBinary = fieldBinary;\n    }\n\n    public AllJavaTypes getFieldObject() {\n        return fieldObject;\n    }\n\n    public void setFieldObject(AllJavaTypes columnRealmObject) {\n        this.fieldObject = columnRealmObject;\n    }\n\n    public RealmList<AllJavaTypes> getFieldList() {\n        return fieldList;\n    }\n\n    public void setFieldList(RealmList<AllJavaTypes> columnRealmList) {\n        this.fieldList = columnRealmList;\n    }\n\n    public RealmList<String> getFieldStringList() {\n        return fieldStringList;\n    }\n\n    public void setFieldStringList(RealmList<String> fieldStringList) {\n        this.fieldStringList = fieldStringList;\n    }\n\n    public RealmList<byte[]> getFieldBinaryList() {\n        return fieldBinaryList;\n    }\n\n    public void setFieldBinaryList(RealmList<byte[]> fieldBinaryList) {\n        this.fieldBinaryList = fieldBinaryList;\n    }\n\n    public RealmList<Boolean> getFieldBooleanList() {\n        return fieldBooleanList;\n    }\n\n    public void setFieldBooleanList(RealmList<Boolean> fieldBooleanList) {\n        this.fieldBooleanList = fieldBooleanList;\n    }\n\n    public RealmList<Long> getFieldLongList() {\n        return fieldLongList;\n    }\n\n    public void setFieldLongList(RealmList<Long> fieldLongList) {\n        this.fieldLongList = fieldLongList;\n    }\n\n    public RealmList<Integer> getFieldIntegerList() {\n        return fieldIntegerList;\n    }\n\n    public void setFieldIntegerList(RealmList<Integer> fieldIntegerList) {\n        this.fieldIntegerList = fieldIntegerList;\n    }\n\n    public RealmList<Short> getFieldShortList() {\n        return fieldShortList;\n    }\n\n    public void setFieldShortList(RealmList<Short> fieldShortList) {\n        this.fieldShortList = fieldShortList;\n    }\n\n    public RealmList<Byte> getFieldByteList() {\n        return fieldByteList;\n    }\n\n    public void setFieldByteList(RealmList<Byte> fieldByteList) {\n        this.fieldByteList = fieldByteList;\n    }\n\n    public RealmList<Double> getFieldDoubleList() {\n        return fieldDoubleList;\n    }\n\n    public void setFieldDoubleList(RealmList<Double> fieldDoubleList) {\n        this.fieldDoubleList = fieldDoubleList;\n    }\n\n    public RealmList<Float> getFieldFloatList() {\n        return fieldFloatList;\n    }\n\n    public void setFieldFloatList(RealmList<Float> fieldFloatList) {\n        this.fieldFloatList = fieldFloatList;\n    }\n\n    public RealmList<Date> getFieldDateList() {\n        return fieldDateList;\n    }\n\n    public void setFieldDateList(RealmList<Date> fieldDateList) {\n        this.fieldDateList = fieldDateList;\n    }\n\n    public Decimal128 getFieldDecimal128() {\n        return fieldDecimal128;\n    }\n\n    public void setFieldDecimal128(Decimal128 fieldDecimal128) {\n        this.fieldDecimal128 = fieldDecimal128;\n    }\n\n    public ObjectId getFieldObjectId() {\n        return fieldObjectId;\n    }\n\n    public void setFieldObjectId(ObjectId fieldObjectId) {\n        this.fieldObjectId = fieldObjectId;\n    }\n\n    public UUID getFieldUUID() {\n        return fieldUUID;\n    }\n\n    public void setFieldUUID(UUID fieldUUID) {\n        this.fieldUUID = fieldUUID;\n    }\n\n    public RealmAny getFieldRealmAny() {\n        return fieldRealmAny;\n    }\n\n    public void setFieldRealmAny(RealmAny fieldRealmAny) {\n        this.fieldRealmAny = fieldRealmAny;\n    }\n\n    public RealmList<Decimal128> getFieldDecimal128List() {\n        return fieldDecimal128List;\n    }\n\n    public void setFieldDecimal128List(RealmList<Decimal128> fieldDecimal128List) {\n        this.fieldDecimal128List = fieldDecimal128List;\n    }\n\n    public RealmList<ObjectId> getFieldObjectIdList() {\n        return fieldObjectIdList;\n    }\n\n    public void setFieldObjectIdList(RealmList<ObjectId> fieldObjectIdList) {\n        this.fieldObjectIdList = fieldObjectIdList;\n    }\n\n    public RealmList<UUID> getFieldUUIDList() {\n        return fieldUUIDList;\n    }\n\n    public void setFieldUUIDList(RealmList<UUID> fieldUUIDList) {\n        this.fieldUUIDList = fieldUUIDList;\n    }\n\n    public RealmList<RealmAny> getFieldRealmAnyList() {\n        return fieldRealmAnyList;\n    }\n\n    public void setFieldRealmAnyList(RealmList<RealmAny> fieldRealmAnyList) {\n        this.fieldRealmAnyList = fieldRealmAnyList;\n    }\n\n    public RealmResults<AllJavaTypes> getObjectParents() {\n        return objectParents;\n    }\n\n    public RealmResults<AllJavaTypes> getListParents() {\n        return listParents;\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/entities/AllJavaTypesUnsupportedTypes.java",
    "content": "/*\n * Copyright 2015 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\npackage io.realm.entities;\n\nimport org.bson.types.Decimal128;\nimport org.bson.types.ObjectId;\n\nimport java.util.Date;\nimport java.util.UUID;\n\nimport io.realm.RealmAny;\nimport io.realm.RealmDictionary;\nimport io.realm.RealmList;\nimport io.realm.RealmObject;\nimport io.realm.RealmResults;\nimport io.realm.RealmSet;\nimport io.realm.annotations.Ignore;\nimport io.realm.annotations.Index;\nimport io.realm.annotations.LinkingObjects;\nimport io.realm.annotations.PrimaryKey;\n\n\npublic class AllJavaTypesUnsupportedTypes extends RealmObject {\n\n    public static final String CLASS_NAME = \"AllJavaTypes\";\n\n    public static final String FIELD_IGNORED = \"fieldIgnored\";\n    public static final String FIELD_STRING = \"fieldString\";\n    public static final String FIELD_SHORT = \"fieldShort\";\n    public static final String FIELD_INT = \"fieldInt\";\n    public static final String FIELD_LONG = \"fieldLong\";\n    public static final String FIELD_ID = \"fieldId\";\n    public static final String FIELD_BYTE = \"fieldByte\";\n    public static final String FIELD_FLOAT = \"fieldFloat\";\n    public static final String FIELD_DOUBLE = \"fieldDouble\";\n    public static final String FIELD_BOOLEAN = \"fieldBoolean\";\n    public static final String FIELD_DATE = \"fieldDate\";\n    public static final String FIELD_BINARY = \"fieldBinary\";\n    public static final String FIELD_DECIMAL128 = \"fieldDecimal128\";\n    public static final String FIELD_OBJECT_ID = \"fieldObjectId\";\n    public static final String FIELD_UUID = \"fieldUUID\";\n    public static final String FIELD_REALM_ANY = \"fieldRealmAny\";\n    public static final String FIELD_OBJECT = \"fieldObject\";\n    public static final String FIELD_LIST = \"fieldList\";\n\n    public static final String FIELD_STRING_LIST = \"fieldStringList\";\n    public static final String FIELD_BINARY_LIST = \"fieldBinaryList\";\n    public static final String FIELD_BOOLEAN_LIST = \"fieldBooleanList\";\n    public static final String FIELD_LONG_LIST = \"fieldLongList\";\n    public static final String FIELD_INTEGER_LIST = \"fieldIntegerList\";\n    public static final String FIELD_SHORT_LIST = \"fieldShortList\";\n    public static final String FIELD_BYTE_LIST = \"fieldByteList\";\n    public static final String FIELD_DOUBLE_LIST = \"fieldDoubleList\";\n    public static final String FIELD_FLOAT_LIST = \"fieldFloatList\";\n    public static final String FIELD_DATE_LIST = \"fieldDateList\";\n    public static final String FIELD_DECIMAL128_LIST = \"fieldDecimal128List\";\n    public static final String FIELD_OBJECT_ID_LIST = \"fieldObjectIdList\";\n    public static final String FIELD_UUID_LIST = \"fieldUUIDList\";\n    public static final String FIELD_REALM_ANY_LIST = \"fieldRealmAnyList\";\n\n    public static final String FIELD_LINK_DICTIONARY = \"columnRealmDictionary\";\n    public static final String FIELD_BOOLEAN_DICTIONARY = \"columnBooleanDictionary\";\n    public static final String FIELD_STRING_DICTIONARY = \"columnStringDictionary\";\n    public static final String FIELD_INTEGER_DICTIONARY = \"columnIntegerDictionary\";\n    public static final String FIELD_FLOAT_DICTIONARY = \"columnFloatDictionary\";\n    public static final String FIELD_LONG_DICTIONARY = \"columnLongDictionary\";\n    public static final String FIELD_SHORT_DICTIONARY = \"columnShortDictionary\";\n    public static final String FIELD_DOUBLE_DICTIONARY = \"columnDoubleDictionary\";\n    public static final String FIELD_BYTE_DICTIONARY = \"columnByteDictionary\";\n    public static final String FIELD_BINARY_DICTIONARY = \"columnBinaryDictionary\";\n    public static final String FIELD_DATE_DICTIONARY = \"columnDateDictionary\";\n    public static final String FIELD_OBJECT_ID_DICTIONARY = \"columnObjectIdDictionary\";\n    public static final String FIELD_UUID_DICTIONARY = \"columnUUIDDictionary\";\n    public static final String FIELD_DECIMAL128_DICTIONARY = \"columnDecimal128Dictionary\";\n    public static final String FIELD_REALM_ANY_DICTIONARY = \"columnRealmAnyDictionary\";\n\n    public static final String FIELD_LINK_SET = \"columnRealmSet\";\n    public static final String FIELD_BOOLEAN_SET = \"columnBooleanSet\";\n    public static final String FIELD_STRING_SET = \"columnStringSet\";\n    public static final String FIELD_INTEGER_SET = \"columnIntegerSet\";\n    public static final String FIELD_FLOAT_SET = \"columnFloatSet\";\n    public static final String FIELD_LONG_SET = \"columnLongSet\";\n    public static final String FIELD_SHORT_SET = \"columnShortSet\";\n    public static final String FIELD_DOUBLE_SET = \"columnDoubleSet\";\n    public static final String FIELD_BYTE_SET = \"columnByteSet\";\n    public static final String FIELD_BINARY_SET = \"columnBinarySet\";\n    public static final String FIELD_DATE_SET = \"columnDateSet\";\n    public static final String FIELD_OBJECT_ID_SET = \"columnObjectIdSet\";\n    public static final String FIELD_UUID_SET = \"columnUUIDSet\";\n    public static final String FIELD_DECIMAL128_SET = \"columnDecimal128Set\";\n    public static final String FIELD_REALM_ANY_SET = \"columnRealmAnySet\";\n\n    public static final String FIELD_LO_OBJECT = \"objectParents\";\n    public static final String FIELD_LO_LIST = \"listParents\";\n\n    public static final String[] INVALID_FIELD_TYPES_FOR_DISTINCT = new String[] {\n            FIELD_OBJECT + \".\" + FIELD_LIST,\n            FIELD_OBJECT + \".\" + FIELD_STRING_LIST,\n            FIELD_OBJECT + \".\" + FIELD_BINARY_LIST,\n            FIELD_OBJECT + \".\" + FIELD_BOOLEAN_LIST,\n            FIELD_OBJECT + \".\" + FIELD_LONG_LIST,\n            FIELD_OBJECT + \".\" + FIELD_INTEGER_LIST,\n            FIELD_OBJECT + \".\" + FIELD_SHORT_LIST,\n            FIELD_OBJECT + \".\" + FIELD_BYTE_LIST,\n            FIELD_OBJECT + \".\" + FIELD_DOUBLE_LIST,\n            FIELD_OBJECT + \".\" + FIELD_FLOAT_LIST,\n            FIELD_OBJECT + \".\" + FIELD_DATE_LIST,\n            FIELD_OBJECT + \".\" + FIELD_DECIMAL128_LIST,\n            FIELD_OBJECT + \".\" + FIELD_OBJECT_ID_LIST,\n            FIELD_OBJECT + \".\" + FIELD_UUID_LIST,\n    };\n\n    @Ignore\n    private String fieldIgnored;\n    @Index\n    private String fieldString;\n    @PrimaryKey\n    private long fieldId;\n    private long fieldLong;\n    private short fieldShort;\n    private int fieldInt;\n    private byte fieldByte;\n    private float fieldFloat;\n    private double fieldDouble;\n    private boolean fieldBoolean;\n    private Date fieldDate;\n    private byte[] fieldBinary;\n    private Decimal128 fieldDecimal128;\n    private ObjectId fieldObjectId;\n    private UUID fieldUUID;\n    private RealmAny fieldRealmAny;\n    private AllJavaTypesUnsupportedTypes fieldObject;\n    private RealmList<AllJavaTypesUnsupportedTypes> fieldList;\n\n    private RealmList<String> fieldStringList;\n    private RealmList<byte[]> fieldBinaryList;\n    private RealmList<Boolean> fieldBooleanList;\n    private RealmList<Long> fieldLongList;\n    private RealmList<Integer> fieldIntegerList;\n    private RealmList<Short> fieldShortList;\n    private RealmList<Byte> fieldByteList;\n    private RealmList<Double> fieldDoubleList;\n    private RealmList<Float> fieldFloatList;\n    private RealmList<Date> fieldDateList;\n    private RealmList<Decimal128> fieldDecimal128List;\n    private RealmList<ObjectId> fieldObjectIdList;\n    private RealmList<UUID> fieldUUIDList;\n    private RealmList<RealmAny> fieldRealmAnyList;\n\n    private RealmDictionary<AllJavaTypesUnsupportedTypes> columnRealmDictionary;\n    private RealmDictionary<Boolean> columnBooleanDictionary;\n    private RealmDictionary<String> columnStringDictionary;\n    private RealmDictionary<Integer> columnIntegerDictionary;\n    private RealmDictionary<Float> columnFloatDictionary;\n    private RealmDictionary<Long> columnLongDictionary;\n    private RealmDictionary<Short> columnShortDictionary;\n    private RealmDictionary<Double> columnDoubleDictionary;\n    private RealmDictionary<Byte> columnByteDictionary;\n    private RealmDictionary<byte[]> columnBinaryDictionary;\n    private RealmDictionary<Date> columnDateDictionary;\n    private RealmDictionary<ObjectId> columnObjectIdDictionary;\n    private RealmDictionary<UUID> columnUUIDDictionary;\n    private RealmDictionary<Decimal128> columnDecimal128Dictionary;\n    private RealmDictionary<RealmAny> columnRealmAnyDictionary;\n\n    private RealmSet<AllJavaTypesUnsupportedTypes> columnRealmSet;\n    private RealmSet<Boolean> columnBooleanSet;\n    private RealmSet<String> columnStringSet;\n    private RealmSet<Integer> columnIntegerSet;\n    private RealmSet<Float> columnFloatSet;\n    private RealmSet<Long> columnLongSet;\n    private RealmSet<Short> columnShortSet;\n    private RealmSet<Double> columnDoubleSet;\n    private RealmSet<Byte> columnByteSet;\n    private RealmSet<byte[]> columnBinarySet;\n    private RealmSet<Date> columnDateSet;\n    private RealmSet<ObjectId> columnObjectIdSet;\n    private RealmSet<UUID> columnUUIDSet;\n    private RealmSet<Decimal128> columnDecimal128Set;\n    private RealmSet<RealmAny> columnRealmAnySet;\n\n    @LinkingObjects(FIELD_OBJECT)\n    private final RealmResults<AllJavaTypesUnsupportedTypes> objectParents = null;\n\n    @LinkingObjects(FIELD_LIST)\n    private final RealmResults<AllJavaTypesUnsupportedTypes> listParents = null;\n\n    public AllJavaTypesUnsupportedTypes() {\n    }\n\n    public AllJavaTypesUnsupportedTypes(long fieldLong) {\n        this.fieldId = fieldLong;\n        this.fieldLong = fieldLong;\n    }\n\n    public String getFieldIgnored() {\n        return fieldIgnored;\n    }\n\n    public void setFieldIgnored(String fieldIgnored) {\n        this.fieldIgnored = fieldIgnored;\n    }\n\n    public String getFieldString() {\n        return fieldString;\n    }\n\n    public void setFieldString(String fieldString) {\n        this.fieldString = fieldString;\n    }\n\n    public short getFieldShort() {\n        return fieldShort;\n    }\n\n    public void setFieldShort(short fieldShort) {\n        this.fieldShort = fieldShort;\n    }\n\n    public long getFieldLong() {\n        return fieldLong;\n    }\n\n    public void setFieldLong(long fieldLong) {\n        this.fieldLong = fieldLong;\n    }\n\n    public int getFieldInt() {\n        return fieldInt;\n    }\n\n    public void setFieldInt(int fieldInt) {\n        this.fieldInt = fieldInt;\n    }\n\n    public long getFieldId() {\n        return fieldId;\n    }\n\n    public void setFieldId(long fieldId) {\n        this.fieldId = fieldId;\n    }\n\n    public byte getFieldByte() {\n        return fieldByte;\n    }\n\n    public void setFieldByte(byte fieldByte) {\n        this.fieldByte = fieldByte;\n    }\n\n    public float getFieldFloat() {\n        return fieldFloat;\n    }\n\n    public void setFieldFloat(float fieldFloat) {\n        this.fieldFloat = fieldFloat;\n    }\n\n    public double getFieldDouble() {\n        return fieldDouble;\n    }\n\n    public void setFieldDouble(double fieldDouble) {\n        this.fieldDouble = fieldDouble;\n    }\n\n    public boolean isFieldBoolean() {\n        return fieldBoolean;\n    }\n\n    public void setFieldBoolean(boolean fieldBoolean) {\n        this.fieldBoolean = fieldBoolean;\n    }\n\n    public Date getFieldDate() {\n        return fieldDate;\n    }\n\n    public void setFieldDate(Date fieldDate) {\n        this.fieldDate = fieldDate;\n    }\n\n    public byte[] getFieldBinary() {\n        return fieldBinary;\n    }\n\n    public void setFieldBinary(byte[] fieldBinary) {\n        this.fieldBinary = fieldBinary;\n    }\n\n    public AllJavaTypesUnsupportedTypes getFieldObject() {\n        return fieldObject;\n    }\n\n    public void setFieldObject(AllJavaTypesUnsupportedTypes columnRealmObject) {\n        this.fieldObject = columnRealmObject;\n    }\n\n    public RealmList<AllJavaTypesUnsupportedTypes> getFieldList() {\n        return fieldList;\n    }\n\n    public void setFieldList(RealmList<AllJavaTypesUnsupportedTypes> columnRealmList) {\n        this.fieldList = columnRealmList;\n    }\n\n    public RealmList<String> getFieldStringList() {\n        return fieldStringList;\n    }\n\n    public void setFieldStringList(RealmList<String> fieldStringList) {\n        this.fieldStringList = fieldStringList;\n    }\n\n    public RealmList<byte[]> getFieldBinaryList() {\n        return fieldBinaryList;\n    }\n\n    public void setFieldBinaryList(RealmList<byte[]> fieldBinaryList) {\n        this.fieldBinaryList = fieldBinaryList;\n    }\n\n    public RealmList<Boolean> getFieldBooleanList() {\n        return fieldBooleanList;\n    }\n\n    public void setFieldBooleanList(RealmList<Boolean> fieldBooleanList) {\n        this.fieldBooleanList = fieldBooleanList;\n    }\n\n    public RealmList<Long> getFieldLongList() {\n        return fieldLongList;\n    }\n\n    public void setFieldLongList(RealmList<Long> fieldLongList) {\n        this.fieldLongList = fieldLongList;\n    }\n\n    public RealmList<Integer> getFieldIntegerList() {\n        return fieldIntegerList;\n    }\n\n    public void setFieldIntegerList(RealmList<Integer> fieldIntegerList) {\n        this.fieldIntegerList = fieldIntegerList;\n    }\n\n    public RealmList<Short> getFieldShortList() {\n        return fieldShortList;\n    }\n\n    public void setFieldShortList(RealmList<Short> fieldShortList) {\n        this.fieldShortList = fieldShortList;\n    }\n\n    public RealmList<Byte> getFieldByteList() {\n        return fieldByteList;\n    }\n\n    public void setFieldByteList(RealmList<Byte> fieldByteList) {\n        this.fieldByteList = fieldByteList;\n    }\n\n    public RealmList<Double> getFieldDoubleList() {\n        return fieldDoubleList;\n    }\n\n    public void setFieldDoubleList(RealmList<Double> fieldDoubleList) {\n        this.fieldDoubleList = fieldDoubleList;\n    }\n\n    public RealmList<Float> getFieldFloatList() {\n        return fieldFloatList;\n    }\n\n    public void setFieldFloatList(RealmList<Float> fieldFloatList) {\n        this.fieldFloatList = fieldFloatList;\n    }\n\n    public RealmList<Date> getFieldDateList() {\n        return fieldDateList;\n    }\n\n    public void setFieldDateList(RealmList<Date> fieldDateList) {\n        this.fieldDateList = fieldDateList;\n    }\n\n    public Decimal128 getFieldDecimal128() {\n        return fieldDecimal128;\n    }\n\n    public void setFieldDecimal128(Decimal128 fieldDecimal128) {\n        this.fieldDecimal128 = fieldDecimal128;\n    }\n\n    public ObjectId getFieldObjectId() {\n        return fieldObjectId;\n    }\n\n    public void setFieldObjectId(ObjectId fieldObjectId) {\n        this.fieldObjectId = fieldObjectId;\n    }\n\n    public UUID getFieldUUID() {\n        return fieldUUID;\n    }\n\n    public void setFieldUUID(UUID fieldUUID) {\n        this.fieldUUID = fieldUUID;\n    }\n\n    public RealmAny getFieldRealmAny() {\n        return fieldRealmAny;\n    }\n\n    public void setFieldRealmAny(RealmAny fieldRealmAny) {\n        this.fieldRealmAny = fieldRealmAny;\n    }\n\n    public RealmList<Decimal128> getFieldDecimal128List() {\n        return fieldDecimal128List;\n    }\n\n    public void setFieldDecimal128List(RealmList<Decimal128> fieldDecimal128List) {\n        this.fieldDecimal128List = fieldDecimal128List;\n    }\n\n    public RealmList<ObjectId> getFieldObjectIdList() {\n        return fieldObjectIdList;\n    }\n\n    public void setFieldObjectIdList(RealmList<ObjectId> fieldObjectIdList) {\n        this.fieldObjectIdList = fieldObjectIdList;\n    }\n\n    public RealmList<UUID> getFieldUUIDList() {\n        return fieldUUIDList;\n    }\n\n    public void setFieldUUIDList(RealmList<UUID> fieldUUIDList) {\n        this.fieldUUIDList = fieldUUIDList;\n    }\n\n    public RealmList<RealmAny> getFieldRealmAnyList() {\n        return fieldRealmAnyList;\n    }\n\n    public void setFieldRealmAnyList(RealmList<RealmAny> fieldRealmAnyList) {\n        this.fieldRealmAnyList = fieldRealmAnyList;\n    }\n\n    public RealmResults<AllJavaTypesUnsupportedTypes> getObjectParents() {\n        return objectParents;\n    }\n\n    public RealmResults<AllJavaTypesUnsupportedTypes> getListParents() {\n        return listParents;\n    }\n\n    public RealmDictionary<AllJavaTypesUnsupportedTypes> getColumnRealmDictionary() {\n        return columnRealmDictionary;\n    }\n\n    public void setColumnRealmDictionary(RealmDictionary<AllJavaTypesUnsupportedTypes> columnRealmDictionary) {\n        this.columnRealmDictionary = columnRealmDictionary;\n    }\n\n    public RealmDictionary<Boolean> getColumnBooleanDictionary() {\n        return columnBooleanDictionary;\n    }\n\n    public void setColumnBooleanDictionary(RealmDictionary<Boolean> columnBooleanDictionary) {\n        this.columnBooleanDictionary = columnBooleanDictionary;\n    }\n\n    public RealmDictionary<String> getColumnStringDictionary() {\n        return columnStringDictionary;\n    }\n\n    public void setColumnStringDictionary(RealmDictionary<String> columnStringDictionary) {\n        this.columnStringDictionary = columnStringDictionary;\n    }\n\n    public RealmDictionary<Integer> getColumnIntegerDictionary() {\n        return columnIntegerDictionary;\n    }\n\n    public void setColumnIntegerDictionary(RealmDictionary<Integer> columnIntegerDictionary) {\n        this.columnIntegerDictionary = columnIntegerDictionary;\n    }\n\n    public RealmDictionary<Float> getColumnFloatDictionary() {\n        return columnFloatDictionary;\n    }\n\n    public void setColumnFloatDictionary(RealmDictionary<Float> columnFloatDictionary) {\n        this.columnFloatDictionary = columnFloatDictionary;\n    }\n\n    public RealmDictionary<Long> getColumnLongDictionary() {\n        return columnLongDictionary;\n    }\n\n    public void setColumnLongDictionary(RealmDictionary<Long> columnLongDictionary) {\n        this.columnLongDictionary = columnLongDictionary;\n    }\n\n    public RealmDictionary<Short> getColumnShortDictionary() {\n        return columnShortDictionary;\n    }\n\n    public void setColumnShortDictionary(RealmDictionary<Short> columnShortDictionary) {\n        this.columnShortDictionary = columnShortDictionary;\n    }\n\n    public RealmDictionary<Double> getColumnDoubleDictionary() {\n        return columnDoubleDictionary;\n    }\n\n    public void setColumnDoubleDictionary(RealmDictionary<Double> columnDoubleDictionary) {\n        this.columnDoubleDictionary = columnDoubleDictionary;\n    }\n\n    public RealmDictionary<Byte> getColumnByteDictionary() {\n        return columnByteDictionary;\n    }\n\n    public void setColumnByteDictionary(RealmDictionary<Byte> columnByteDictionary) {\n        this.columnByteDictionary = columnByteDictionary;\n    }\n\n    public RealmDictionary<byte[]> getColumnBinaryDictionary() {\n        return columnBinaryDictionary;\n    }\n\n    public void setColumnBinaryDictionary(RealmDictionary<byte[]> columnBinaryDictionary) {\n        this.columnBinaryDictionary = columnBinaryDictionary;\n    }\n\n    public RealmDictionary<Date> getColumnDateDictionary() {\n        return columnDateDictionary;\n    }\n\n    public void setColumnDateDictionary(RealmDictionary<Date> columnDateDictionary) {\n        this.columnDateDictionary = columnDateDictionary;\n    }\n\n    public RealmDictionary<ObjectId> getColumnObjectIdDictionary() {\n        return columnObjectIdDictionary;\n    }\n\n    public void setColumnObjectIdDictionary(RealmDictionary<ObjectId> columnObjectIdDictionary) {\n        this.columnObjectIdDictionary = columnObjectIdDictionary;\n    }\n\n    public RealmDictionary<UUID> getColumnUUIDDictionary() {\n        return columnUUIDDictionary;\n    }\n\n    public void setColumnUUIDDictionary(RealmDictionary<UUID> columnUUIDDictionary) {\n        this.columnUUIDDictionary = columnUUIDDictionary;\n    }\n\n    public RealmDictionary<Decimal128> getColumnDecimal128Dictionary() {\n        return columnDecimal128Dictionary;\n    }\n\n    public void setColumnDecimal128Dictionary(RealmDictionary<Decimal128> columnDecimal128Dictionary) {\n        this.columnDecimal128Dictionary = columnDecimal128Dictionary;\n    }\n\n    public RealmDictionary<RealmAny> getColumnRealmAnyDictionary() {\n        return columnRealmAnyDictionary;\n    }\n\n    public void setColumnRealmAnyDictionary(RealmDictionary<RealmAny> columnRealmAnyDictionary) {\n        this.columnRealmAnyDictionary = columnRealmAnyDictionary;\n    }\n\n    public RealmSet<AllJavaTypesUnsupportedTypes> getColumnRealmSet() {\n        return columnRealmSet;\n    }\n\n    public void setColumnRealmSet(RealmSet<AllJavaTypesUnsupportedTypes> columnRealmSet) {\n        this.columnRealmSet = columnRealmSet;\n    }\n\n    public RealmSet<Boolean> getColumnBooleanSet() {\n        return columnBooleanSet;\n    }\n\n    public void setColumnBooleanSet(RealmSet<Boolean> columnBooleanSet) {\n        this.columnBooleanSet = columnBooleanSet;\n    }\n\n    public RealmSet<String> getColumnStringSet() {\n        return columnStringSet;\n    }\n\n    public void setColumnStringSet(RealmSet<String> columnStringSet) {\n        this.columnStringSet = columnStringSet;\n    }\n\n    public RealmSet<Integer> getColumnIntegerSet() {\n        return columnIntegerSet;\n    }\n\n    public void setColumnIntegerSet(RealmSet<Integer> columnIntegerSet) {\n        this.columnIntegerSet = columnIntegerSet;\n    }\n\n    public RealmSet<Float> getColumnFloatSet() {\n        return columnFloatSet;\n    }\n\n    public void setColumnFloatSet(RealmSet<Float> columnFloatSet) {\n        this.columnFloatSet = columnFloatSet;\n    }\n\n    public RealmSet<Long> getColumnLongSet() {\n        return columnLongSet;\n    }\n\n    public void setColumnLongSet(RealmSet<Long> columnLongSet) {\n        this.columnLongSet = columnLongSet;\n    }\n\n    public RealmSet<Short> getColumnShortSet() {\n        return columnShortSet;\n    }\n\n    public void setColumnShortSet(RealmSet<Short> columnShortSet) {\n        this.columnShortSet = columnShortSet;\n    }\n\n    public RealmSet<Double> getColumnDoubleSet() {\n        return columnDoubleSet;\n    }\n\n    public void setColumnDoubleSet(RealmSet<Double> columnDoubleSet) {\n        this.columnDoubleSet = columnDoubleSet;\n    }\n\n    public RealmSet<Byte> getColumnByteSet() {\n        return columnByteSet;\n    }\n\n    public void setColumnByteSet(RealmSet<Byte> columnByteSet) {\n        this.columnByteSet = columnByteSet;\n    }\n\n    public RealmSet<byte[]> getColumnBinarySet() {\n        return columnBinarySet;\n    }\n\n    public void setColumnBinarySet(RealmSet<byte[]> columnBinarySet) {\n        this.columnBinarySet = columnBinarySet;\n    }\n\n    public RealmSet<Date> getColumnDateSet() {\n        return columnDateSet;\n    }\n\n    public void setColumnDateSet(RealmSet<Date> columnDateSet) {\n        this.columnDateSet = columnDateSet;\n    }\n\n    public RealmSet<ObjectId> getColumnObjectIdSet() {\n        return columnObjectIdSet;\n    }\n\n    public void setColumnObjectIdSet(RealmSet<ObjectId> columnObjectIdSet) {\n        this.columnObjectIdSet = columnObjectIdSet;\n    }\n\n    public RealmSet<UUID> getColumnUUIDSet() {\n        return columnUUIDSet;\n    }\n\n    public void setColumnUUIDSet(RealmSet<UUID> columnUUISet) {\n        this.columnUUIDSet = columnUUISet;\n    }\n\n    public RealmSet<Decimal128> getColumnDecimal128Set() {\n        return columnDecimal128Set;\n    }\n\n    public void setColumnDecimal128Set(RealmSet<Decimal128> columnDecimal12Set) {\n        this.columnDecimal128Set = columnDecimal12Set;\n    }\n\n    public RealmSet<RealmAny> getColumnRealmAnySet() {\n        return columnRealmAnySet;\n    }\n\n    public void setColumnRealmAnySet(RealmSet<RealmAny> columnRealmAnySet) {\n        this.columnRealmAnySet = columnRealmAnySet;\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/entities/AnimalModule.java",
    "content": "/*\n * Copyright 2015 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\npackage io.realm.entities;\n\nimport io.realm.annotations.RealmModule;\n\n@RealmModule(classes = {Dog.class, Cat.class, DogPrimaryKey.class})\npublic class AnimalModule {\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/entities/AnnotationNameConventions.java",
    "content": "/*\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\npackage io.realm.entities;\n\n\nimport io.realm.RealmObject;\n\npublic class AnnotationNameConventions extends RealmObject {\n    private long id_object;\n    private long object_id;\n    private boolean isObject;\n    private boolean hasObject;\n    private long mObject;\n\n    public long getId_object() {\n        return id_object;\n    }\n\n    public void setId_object(long id_object) {\n        this.id_object = id_object;\n    }\n\n    public long getObject_id() {\n        return object_id;\n    }\n\n    public void setObject_id(long object_id) {\n        this.object_id = object_id;\n    }\n\n    public boolean isObject() {\n        return isObject;\n    }\n\n    public void setObject(boolean isObject) {\n        this.isObject = isObject;\n    }\n\n    public boolean isHasObject() {\n        return hasObject;\n    }\n\n    public void setHasObject(boolean hasObject) {\n        this.hasObject = hasObject;\n    }\n\n    public long getmObject() {\n        return mObject;\n    }\n\n    public void setmObject(long mObject) {\n        this.mObject = mObject;\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/entities/AnnotationTypes.java",
    "content": "/*\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\npackage io.realm.entities;\n\nimport io.realm.RealmObject;\nimport io.realm.annotations.Ignore;\nimport io.realm.annotations.Index;\nimport io.realm.annotations.PrimaryKey;\n\npublic class AnnotationTypes extends RealmObject {\n\n    public static final String FIELD_INDEX_STRING = \"indexString\";\n    public static final String FIELD_NOT_INDEX_STRING = \"notIndexString\";\n    public static final String FIELD_IGNORE_STRING= \"ignoreString\";\n    public static final String FIELD_TRANSIENT_STRING = \"transientString\";\n\n    @PrimaryKey\n    private long id;\n\n    @Index\n    private String indexString;\n    private String notIndexString;\n\n    @Ignore\n    private String ignoreString;\n\n    private transient String transientString;\n\n    public long getId() {\n        return id;\n    }\n\n    public void setId(long id) {\n        this.id = id;\n    }\n\n    public String getIndexString() {\n        return indexString;\n    }\n\n    public void setIndexString(String indexString) {\n        this.indexString = indexString;\n    }\n\n    public String getNotIndexString() {\n        return notIndexString;\n    }\n\n    public void setNotIndexString(String notIndexString) {\n        this.notIndexString = notIndexString;\n    }\n\n    public String getIgnoreString() {\n        return ignoreString;\n    }\n\n    public void setIgnoreString(String ignoreString) {\n        this.ignoreString = ignoreString;\n    }\n\n    public String getTransientString() {\n        return transientString;\n    }\n\n    public void setTransientString(String transientString) {\n        this.transientString = transientString;\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/entities/AssetFileModule.java",
    "content": "/*\n * Copyright 2016 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\npackage io.realm.entities;\n\nimport io.realm.annotations.RealmModule;\n\n/**\n * module definition for \"asset_file.realm\"\n */\n@RealmModule(classes = {Owner.class, Cat.class, Dog.class, DogPrimaryKey.class})\npublic class AssetFileModule {\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/entities/CatOwner.java",
    "content": "/*\n * Copyright 2015 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 */\npackage io.realm.entities;\n\n\nimport io.realm.RealmList;\nimport io.realm.RealmObject;\nimport io.realm.annotations.Required;\n\npublic class CatOwner extends RealmObject {\n    public static final String CLASS_NAME = \"CatOwner\";\n    public static final String FIELD_NAME = \"name\";\n    public static final String FIELD_CATS = \"cats\";\n\n    @Required\n    private String name;\n    private RealmList<Cat> cats;\n\n\n    public String getName() {\n        return name;\n    }\n\n    public void setName(String name) {\n        this.name = name;\n    }\n\n    public RealmList<Cat> getCats() {\n        return cats;\n    }\n\n    public void setCats(RealmList<Cat> cats) {\n        this.cats = cats;\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/entities/ConflictingFieldName.java",
    "content": "/*\n * Copyright 2016 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\npackage io.realm.entities;\n\nimport io.realm.RealmObject;\n\npublic class ConflictingFieldName extends RealmObject {\n    private String realm;\n    private String row;\n    private String listeners;\n    private String pendingQuery;\n    private String isCompleted;\n    private String currentTableVersion;\n\n    public String getRealmString() {\n        return realm;\n    }\n\n    public void setRealmString(String realm) {\n        this.realm = realm;\n    }\n\n    public String getRow() {\n        return row;\n    }\n\n    public void setRow(String row) {\n        this.row = row;\n    }\n\n    public String getListeners() {\n        return listeners;\n    }\n\n    public void setListeners(String listeners) {\n        this.listeners = listeners;\n    }\n\n    public String getPendingQuery() {\n        return pendingQuery;\n    }\n\n    public void setPendingQuery(String pendingQuery) {\n        this.pendingQuery = pendingQuery;\n    }\n\n    public String getIsCompleted() {\n        return isCompleted;\n    }\n\n    public void setIsCompleted(String isCompleted) {\n        this.isCompleted = isCompleted;\n    }\n\n    public String getCurrentTableVersion() {\n        return currentTableVersion;\n    }\n\n    public void setCurrentTableVersion(String currentTableVersion) {\n        this.currentTableVersion = currentTableVersion;\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/entities/CustomMethods.java",
    "content": "/*\n * Copyright 2016 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\npackage io.realm.entities;\n\nimport io.realm.RealmList;\nimport io.realm.RealmObject;\nimport io.realm.annotations.Ignore;\n\npublic class CustomMethods extends RealmObject {\n    public static final String CUSTOM_TO_STRING = \"custom toString\";\n    public static final int HASHCODE = 1;\n\n    private String name;\n    private RealmList<CustomMethods> methods;\n\n    public CustomMethods() {\n    }\n\n    public CustomMethods(String name) {\n        this.name = name;\n    }\n\n    public String getName() {\n        return name;\n    }\n\n    public void setName(String name) {\n        this.name = name;\n    }\n\n    public RealmList<CustomMethods> getMethods() {\n        return methods;\n    }\n\n    @Override\n    public boolean equals(Object o) {\n        if (this == o) return true;\n        if (o == null || !(o instanceof CustomMethods)) return false;\n\n        CustomMethods that = (CustomMethods) o;\n\n        // Only compare name. Managed and unmanaged objects will be equal as long as they have the same value\n        return name != null ? name.equals(that.name) : that.name == null;\n    }\n\n    @Override\n    public String toString() {\n        return CUSTOM_TO_STRING;\n    }\n\n    @Override\n    public int hashCode() {\n        return HASHCODE;\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/entities/CyclicType.java",
    "content": "/*\n * Copyright 2015 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\npackage io.realm.entities;\n\nimport java.util.Date;\n\nimport io.realm.RealmList;\nimport io.realm.RealmObject;\n\npublic class CyclicType extends RealmObject {\n\n    public static final String FIELD_NAME = \"name\";\n    public static final String FIELD_ID = \"id\";\n    public static final String FIELD_DATE = \"date\";\n    public static final String FIELD_OBJECT = \"object\";\n\n    private long id;\n    private String name;\n    private Date date;\n    private CyclicType object;\n    private CyclicType otherObject;\n    private RealmList<CyclicType> objects;\n\n    public CyclicType() {\n    }\n\n    public CyclicType(String name) {\n        this.name = name;\n    }\n\n\n    public long getId() {\n        return id;\n    }\n\n    public void setId(long id) {\n        this.id = id;\n    }\n\n    public String getName() {\n        return name;\n    }\n\n    public void setName(String name) {\n        this.name = name;\n    }\n\n    public CyclicType getObject() {\n        return object;\n    }\n\n    public void setObject(CyclicType object) {\n        this.object = object;\n    }\n\n    public RealmList<CyclicType> getObjects() {\n        return objects;\n    }\n\n    public void setObjects(RealmList<CyclicType> objects) {\n        this.objects = objects;\n    }\n\n    public CyclicType getOtherObject() {\n        return otherObject;\n    }\n\n    public void setOtherObject(CyclicType otherObject) {\n        this.otherObject = otherObject;\n    }\n\n    public Date getDate() {\n        return date;\n    }\n\n    public void setDate(Date date) {\n        this.date = date;\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/entities/CyclicTypePrimaryKey.java",
    "content": "/*\n * Copyright 2015 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\npackage io.realm.entities;\n\nimport io.realm.RealmList;\nimport io.realm.RealmObject;\nimport io.realm.annotations.PrimaryKey;\n\npublic class CyclicTypePrimaryKey extends RealmObject {\n\n    @PrimaryKey\n    private long id;\n    private String name;\n    private CyclicTypePrimaryKey object;\n    private RealmList<CyclicTypePrimaryKey> objects;\n\n    public CyclicTypePrimaryKey() {\n    }\n\n    public CyclicTypePrimaryKey(long id) {\n        this.id = id;\n    }\n\n    public CyclicTypePrimaryKey(long id, String name) {\n        this.id = id;\n        this.name = name;\n    }\n\n    public long getId() {\n        return id;\n    }\n\n    public void setId(long id) {\n        this.id = id;\n    }\n\n    public String getName() {\n        return name;\n    }\n\n    public void setName(String name) {\n        this.name = name;\n    }\n\n    public CyclicTypePrimaryKey getObject() {\n        return object;\n    }\n\n    public void setObject(CyclicTypePrimaryKey object) {\n        this.object = object;\n    }\n\n    public RealmList<CyclicTypePrimaryKey> getObjects() {\n        return objects;\n    }\n\n    public void setObjects(RealmList<CyclicTypePrimaryKey> objects) {\n        this.objects = objects;\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/entities/DefaultValueConstructor.java",
    "content": "/*\n * Copyright 2016 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\npackage io.realm.entities;\n\nimport java.util.Date;\nimport java.util.UUID;\n\nimport io.realm.RealmList;\nimport io.realm.RealmObject;\nimport io.realm.annotations.Ignore;\nimport io.realm.annotations.PrimaryKey;\n\npublic class DefaultValueConstructor extends RealmObject {\n\n    public static final String CLASS_NAME = \"DefaultValueOfField\";\n    public static String FIELD_IGNORED = \"fieldIgnored\";\n    public static String FIELD_RANDOM_STRING = \"fieldRandomString\";\n    public static String FIELD_STRING = \"fieldString\";\n    public static String FIELD_SHORT = \"fieldShort\";\n    public static String FIELD_INT = \"fieldInt\";\n    public static String FIELD_LONG_PRIMARY_KEY = \"fieldLongPrimaryKey\";\n    public static String FIELD_LONG = \"fieldLong\";\n    public static String FIELD_BYTE = \"fieldByte\";\n    public static String FIELD_FLOAT = \"fieldFloat\";\n    public static String FIELD_DOUBLE = \"fieldDouble\";\n    public static String FIELD_BOOLEAN = \"fieldBoolean\";\n    public static String FIELD_DATE = \"fieldDate\";\n    public static String FIELD_BINARY = \"fieldBinary\";\n    public static String FIELD_OBJECT = \"fieldObject\";\n    public static String FIELD_LIST = \"fieldList\";\n\n\n    public static String FIELD_IGNORED_DEFAULT_VALUE = \"ignored\";\n    public static String FIELD_STRING_DEFAULT_VALUE = \"defaultString\";\n    public static short FIELD_SHORT_DEFAULT_VALUE = 1234;\n    public static int FIELD_INT_DEFAULT_VALUE = 123456;\n    public static long FIELD_LONG_PRIMARY_KEY_DEFAULT_VALUE = 2L * Integer.MAX_VALUE;\n    public static long FIELD_LONG_DEFAULT_VALUE = 3L * Integer.MAX_VALUE;\n    public static byte FIELD_BYTE_DEFAULT_VALUE = 100;\n    public static float FIELD_FLOAT_DEFAULT_VALUE = 0.5f;\n    public static double FIELD_DOUBLE_DEFAULT_VALUE = 0.25;\n    public static boolean FIELD_BOOLEAN_DEFAULT_VALUE = true;\n    public static Date FIELD_DATE_DEFAULT_VALUE = new Date(1473691826000L /*2016/9/12 23:56:26 JST*/);\n    public static byte[] FIELD_BINARY_DEFAULT_VALUE = new byte[] {123, -100, 0, 2};\n    public static RandomPrimaryKey FIELD_OBJECT_DEFAULT_VALUE;\n    public static RealmList<RandomPrimaryKey> FIELD_LIST_DEFAULT_VALUE;\n\n    static {\n        FIELD_OBJECT_DEFAULT_VALUE = new RandomPrimaryKey();\n        FIELD_LIST_DEFAULT_VALUE = new RealmList<RandomPrimaryKey>();\n        FIELD_LIST_DEFAULT_VALUE.add(new RandomPrimaryKey());\n    }\n\n    public static String lastRandomStringValue;\n\n    @Ignore private String fieldIgnored;\n    private String fieldString;\n    private String fieldRandomString;\n    private short fieldShort;\n    private int fieldInt;\n    @PrimaryKey private long fieldLongPrimaryKey;\n    private long fieldLong;\n    private byte fieldByte;\n    private float fieldFloat;\n    private double fieldDouble;\n    private boolean fieldBoolean;\n    private Date fieldDate;\n    private byte[] fieldBinary;\n    private RandomPrimaryKey fieldObject;\n    private RealmList<RandomPrimaryKey> fieldList;\n\n    public DefaultValueConstructor() {\n        fieldIgnored = FIELD_IGNORED_DEFAULT_VALUE;\n        fieldString = FIELD_STRING_DEFAULT_VALUE;\n        fieldRandomString = lastRandomStringValue = UUID.randomUUID().toString();\n        fieldShort = FIELD_SHORT_DEFAULT_VALUE;\n        fieldInt = FIELD_INT_DEFAULT_VALUE;\n        fieldLongPrimaryKey = FIELD_LONG_PRIMARY_KEY_DEFAULT_VALUE;\n        fieldLong = FIELD_LONG_DEFAULT_VALUE;\n        fieldByte = FIELD_BYTE_DEFAULT_VALUE;\n        fieldFloat = FIELD_FLOAT_DEFAULT_VALUE;\n        fieldDouble = FIELD_DOUBLE_DEFAULT_VALUE;\n        fieldBoolean = FIELD_BOOLEAN_DEFAULT_VALUE;\n        fieldDate = FIELD_DATE_DEFAULT_VALUE;\n        fieldBinary = FIELD_BINARY_DEFAULT_VALUE;\n        fieldObject = FIELD_OBJECT_DEFAULT_VALUE;\n        fieldList = FIELD_LIST_DEFAULT_VALUE;\n    }\n\n    public DefaultValueConstructor(long fieldLong) {\n        this.fieldLong = fieldLong;\n    }\n\n    public String getFieldIgnored() {\n        return fieldIgnored;\n    }\n\n    public void setFieldIgnored(String fieldIgnored) {\n        this.fieldIgnored = fieldIgnored;\n    }\n\n    public String getFieldString() {\n        return fieldString;\n    }\n\n    public void setFieldString(String fieldString) {\n        this.fieldString = fieldString;\n    }\n\n    public String getFieldRandomString() {\n        return fieldRandomString;\n    }\n\n    public void setFieldRandomString(String fieldRandomString) {\n        this.fieldRandomString = fieldRandomString;\n    }\n\n    public short getFieldShort() {\n        return fieldShort;\n    }\n\n    public void setFieldShort(short fieldShort) {\n        this.fieldShort = fieldShort;\n    }\n\n    public int getFieldInt() {\n        return fieldInt;\n    }\n\n    public void setFieldInt(int fieldInt) {\n        this.fieldInt = fieldInt;\n    }\n\n    public long getFieldLongPrimaryKey() {\n        return fieldLongPrimaryKey;\n    }\n\n    public void setFieldLongPrimaryKey(long fieldLongPrimaryKey) {\n        this.fieldLongPrimaryKey = fieldLongPrimaryKey;\n    }\n\n    public long getFieldLong() {\n        return fieldLong;\n    }\n\n    public void setFieldLong(long fieldLong) {\n        this.fieldLong = fieldLong;\n    }\n\n    public byte getFieldByte() {\n        return fieldByte;\n    }\n\n    public void setFieldByte(byte fieldByte) {\n        this.fieldByte = fieldByte;\n    }\n\n    public float getFieldFloat() {\n        return fieldFloat;\n    }\n\n    public void setFieldFloat(float fieldFloat) {\n        this.fieldFloat = fieldFloat;\n    }\n\n    public double getFieldDouble() {\n        return fieldDouble;\n    }\n\n    public void setFieldDouble(double fieldDouble) {\n        this.fieldDouble = fieldDouble;\n    }\n\n    public boolean isFieldBoolean() {\n        return fieldBoolean;\n    }\n\n    public void setFieldBoolean(boolean fieldBoolean) {\n        this.fieldBoolean = fieldBoolean;\n    }\n\n    public Date getFieldDate() {\n        return fieldDate;\n    }\n\n    public void setFieldDate(Date fieldDate) {\n        this.fieldDate = fieldDate;\n    }\n\n    public byte[] getFieldBinary() {\n        return fieldBinary;\n    }\n\n    public void setFieldBinary(byte[] fieldBinary) {\n        this.fieldBinary = fieldBinary;\n    }\n\n    public RandomPrimaryKey getFieldObject() {\n        return fieldObject;\n    }\n\n    public void setFieldObject(RandomPrimaryKey fieldObject) {\n        this.fieldObject = fieldObject;\n    }\n\n    public RealmList<RandomPrimaryKey> getFieldList() {\n        return fieldList;\n    }\n\n    public void setFieldList(RealmList<RandomPrimaryKey> fieldList) {\n        this.fieldList = fieldList;\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/entities/DefaultValueFromOtherConstructor.java",
    "content": "/*\n * Copyright 2017 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\npackage io.realm.entities;\n\nimport io.realm.RealmObject;\n\npublic class DefaultValueFromOtherConstructor extends RealmObject {\n\n    public static final String CLASS_NAME = \"DefaultValueOfField\";\n    public static String FIELD_LONG = \"fieldLong\";\n\n    private long fieldLong;\n\n    public DefaultValueFromOtherConstructor() {\n        this(42);\n    }\n\n    public DefaultValueFromOtherConstructor(long fieldLong) {\n        this.fieldLong = fieldLong;\n    }\n\n    public long getFieldLong() {\n        return fieldLong;\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/entities/DefaultValueOfField.java",
    "content": "/*\n * Copyright 2016 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\npackage io.realm.entities;\n\nimport org.bson.types.Decimal128;\nimport org.bson.types.ObjectId;\n\nimport java.util.Date;\nimport java.util.UUID;\n\nimport io.realm.RealmAny;\nimport io.realm.RealmList;\nimport io.realm.RealmObject;\nimport io.realm.annotations.Ignore;\nimport io.realm.annotations.PrimaryKey;\n\npublic class DefaultValueOfField extends RealmObject {\n\n    public static final String CLASS_NAME = \"DefaultValueOfField\";\n    public static final String FIELD_IGNORED = \"fieldIgnored\";\n    public static final String FIELD_RANDOM_STRING = \"fieldRandomString\";\n    public static final String FIELD_STRING = \"fieldString\";\n    public static final String FIELD_SHORT = \"fieldShort\";\n    public static final String FIELD_INT = \"fieldInt\";\n    public static final String FIELD_LONG_PRIMARY_KEY = \"fieldLongPrimaryKey\";\n    public static final String FIELD_LONG = \"fieldLong\";\n    public static final String FIELD_BYTE = \"fieldByte\";\n    public static final String FIELD_FLOAT = \"fieldFloat\";\n    public static final String FIELD_DOUBLE = \"fieldDouble\";\n    public static final String FIELD_BOOLEAN = \"fieldBoolean\";\n    public static final String FIELD_DATE = \"fieldDate\";\n    public static final String FIELD_OBJECT_ID = \"fieldObjectId\";\n    public static final String FIELD_DECIMAL128 = \"fieldDecimal128\";\n    public static final String FIELD_UUID = \"fieldUUID\";\n    public static final String FIELD_REALM_ANY = \"fieldRealmAny\";\n    public static final String FIELD_BINARY = \"fieldBinary\";\n    public static final String FIELD_OBJECT = \"fieldObject\";\n    public static final String FIELD_LIST = \"fieldList\";\n\n\n    public static final String FIELD_IGNORED_DEFAULT_VALUE = \"ignored\";\n    public static final String FIELD_STRING_DEFAULT_VALUE = \"defaultString\";\n    public static final short FIELD_SHORT_DEFAULT_VALUE = 1234;\n    public static final int FIELD_INT_DEFAULT_VALUE = 123456;\n    public static final long FIELD_LONG_PRIMARY_KEY_DEFAULT_VALUE = 2L * Integer.MAX_VALUE;\n    public static final long FIELD_LONG_DEFAULT_VALUE = 3L * Integer.MAX_VALUE;\n    public static final byte FIELD_BYTE_DEFAULT_VALUE = 100;\n    public static final float FIELD_FLOAT_DEFAULT_VALUE = 0.5f;\n    public static final double FIELD_DOUBLE_DEFAULT_VALUE = 0.25;\n    public static final boolean FIELD_BOOLEAN_DEFAULT_VALUE = true;\n    public static final Date FIELD_DATE_DEFAULT_VALUE = new Date(1473691826000L /*2016/9/12 23:56:26 JST*/);\n    public static final byte[] FIELD_BINARY_DEFAULT_VALUE = new byte[]{123, -100, 0, 2};\n    public static final ObjectId FIELD_OBJECT_ID_DEFAULT_VALUE = new ObjectId(new Date(10));\n    public static final Decimal128 FIELD_DECIMAL128_DEFAULT_VALUE = new Decimal128(10);\n    public static final UUID FIELD_UUID_DEFAULT_VALUE = UUID.randomUUID();\n    public static final RealmAny FIELD_REALM_ANY_DEFAULT_VALUE = RealmAny.valueOf((float) 10);\n    public static final RandomPrimaryKey FIELD_OBJECT_DEFAULT_VALUE;\n    public static final RealmList<RandomPrimaryKey> FIELD_LIST_DEFAULT_VALUE;\n    public static final RealmList<String> FIELD_STRING_LIST_DEFAULT_VALUE;\n    public static final RealmList<Boolean> FIELD_BOOLEAN_LIST_DEFAULT_VALUE;\n    public static final RealmList<byte[]> FIELD_BINARY_LIST_DEFAULT_VALUE;\n    public static final RealmList<Long> FIELD_LONG_LIST_DEFAULT_VALUE;\n    public static final RealmList<Integer> FIELD_INTEGER_LIST_DEFAULT_VALUE;\n    public static final RealmList<Short> FIELD_SHORT_LIST_DEFAULT_VALUE;\n    public static final RealmList<Byte> FIELD_BYTE_LIST_DEFAULT_VALUE;\n    public static final RealmList<Double> FIELD_DOUBLE_LIST_DEFAULT_VALUE;\n    public static final RealmList<Float> FIELD_FLOAT_LIST_DEFAULT_VALUE;\n    public static final RealmList<Date> FIELD_DATE_LIST_DEFAULT_VALUE;\n    public static final RealmList<ObjectId> FIELD_OBJECT_ID_LIST_DEFAULT_VALUE;\n    public static final RealmList<Decimal128> FIELD_DECIMAL128_LIST_DEFAULT_VALUE;\n    public static final RealmList<UUID> FIELD_UUID_LIST_DEFAULT_VALUE;\n    public static final RealmList<RealmAny> FIELD_REALM_ANY_LIST_DEFAULT_VALUE;\n\n    static {\n        FIELD_OBJECT_DEFAULT_VALUE = new RandomPrimaryKey();\n        FIELD_LIST_DEFAULT_VALUE = new RealmList<RandomPrimaryKey>();\n        FIELD_LIST_DEFAULT_VALUE.add(new RandomPrimaryKey());\n\n        FIELD_STRING_LIST_DEFAULT_VALUE = new RealmList<>(\"1\");\n        FIELD_BOOLEAN_LIST_DEFAULT_VALUE = new RealmList<>(true);\n        FIELD_BINARY_LIST_DEFAULT_VALUE = new RealmList<>(new byte[]{1});\n        FIELD_LONG_LIST_DEFAULT_VALUE = new RealmList<>(1L);\n        FIELD_INTEGER_LIST_DEFAULT_VALUE = new RealmList<>(1);\n        FIELD_SHORT_LIST_DEFAULT_VALUE = new RealmList<>((short) 1);\n        FIELD_BYTE_LIST_DEFAULT_VALUE = new RealmList<>((byte) 1);\n        FIELD_DOUBLE_LIST_DEFAULT_VALUE = new RealmList<>(1D);\n        FIELD_FLOAT_LIST_DEFAULT_VALUE = new RealmList<>(1F);\n        FIELD_DATE_LIST_DEFAULT_VALUE = new RealmList<>(new Date(1));\n        FIELD_OBJECT_ID_LIST_DEFAULT_VALUE = new RealmList<>(new ObjectId(new Date(10)));\n        FIELD_DECIMAL128_LIST_DEFAULT_VALUE = new RealmList<>(new Decimal128(10));\n        FIELD_UUID_LIST_DEFAULT_VALUE = new RealmList<>(UUID.randomUUID());\n        FIELD_REALM_ANY_LIST_DEFAULT_VALUE = new RealmList<>(RealmAny.valueOf((float) 10));\n    }\n\n    public static String lastRandomStringValue;\n\n    @Ignore private String fieldIgnored = FIELD_IGNORED_DEFAULT_VALUE;\n    private String fieldString = FIELD_STRING_DEFAULT_VALUE;\n    private String fieldRandomString = lastRandomStringValue = UUID.randomUUID().toString();\n    private short fieldShort = FIELD_SHORT_DEFAULT_VALUE;\n    private int fieldInt = FIELD_INT_DEFAULT_VALUE;\n    @PrimaryKey private long fieldLongPrimaryKey = FIELD_LONG_PRIMARY_KEY_DEFAULT_VALUE;\n    private long fieldLong = FIELD_LONG_DEFAULT_VALUE;\n    private byte fieldByte = FIELD_BYTE_DEFAULT_VALUE;\n    private float fieldFloat = FIELD_FLOAT_DEFAULT_VALUE;\n    private double fieldDouble = FIELD_DOUBLE_DEFAULT_VALUE;\n    private boolean fieldBoolean = FIELD_BOOLEAN_DEFAULT_VALUE;\n    private Date fieldDate = FIELD_DATE_DEFAULT_VALUE;\n    private byte[] fieldBinary = FIELD_BINARY_DEFAULT_VALUE;\n    private RandomPrimaryKey fieldObject = FIELD_OBJECT_DEFAULT_VALUE;\n    private ObjectId fieldObjectId = FIELD_OBJECT_ID_DEFAULT_VALUE;\n    private Decimal128 fieldDecimal128 = FIELD_DECIMAL128_DEFAULT_VALUE;\n    private UUID fieldUUID = FIELD_UUID_DEFAULT_VALUE;\n    private RealmAny fieldRealmAny = FIELD_REALM_ANY_DEFAULT_VALUE;\n\n    private RealmList<RandomPrimaryKey> fieldList = FIELD_LIST_DEFAULT_VALUE;\n    private RealmList<String> fieldStringList = FIELD_STRING_LIST_DEFAULT_VALUE;\n    private RealmList<byte[]> fieldBinaryList = FIELD_BINARY_LIST_DEFAULT_VALUE;\n    private RealmList<Boolean> fieldBooleanList = FIELD_BOOLEAN_LIST_DEFAULT_VALUE;\n    private RealmList<Long> fieldLongList = FIELD_LONG_LIST_DEFAULT_VALUE;\n    private RealmList<Integer> fieldIntegerList = FIELD_INTEGER_LIST_DEFAULT_VALUE;\n    private RealmList<Short> fieldShortList = FIELD_SHORT_LIST_DEFAULT_VALUE;\n    private RealmList<Byte> fieldByteList = FIELD_BYTE_LIST_DEFAULT_VALUE;\n    private RealmList<Double> fieldDoubleList = FIELD_DOUBLE_LIST_DEFAULT_VALUE;\n    private RealmList<Float> fieldFloatList = FIELD_FLOAT_LIST_DEFAULT_VALUE;\n    private RealmList<Date> fieldDateList = FIELD_DATE_LIST_DEFAULT_VALUE;\n    private RealmList<ObjectId> fieldObjectIdList = FIELD_OBJECT_ID_LIST_DEFAULT_VALUE;\n    private RealmList<Decimal128> fieldDecimal128List = FIELD_DECIMAL128_LIST_DEFAULT_VALUE;\n    private RealmList<UUID> fieldUUIDList = FIELD_UUID_LIST_DEFAULT_VALUE;\n    private RealmList<RealmAny> fieldRealmAnyList = FIELD_REALM_ANY_LIST_DEFAULT_VALUE;\n\n    public DefaultValueOfField() {\n    }\n\n    public DefaultValueOfField(long fieldLong) {\n        this.fieldLong = fieldLong;\n    }\n\n    public String getFieldIgnored() {\n        return fieldIgnored;\n    }\n\n    public void setFieldIgnored(String fieldIgnored) {\n        this.fieldIgnored = fieldIgnored;\n    }\n\n    public String getFieldString() {\n        return fieldString;\n    }\n\n    public void setFieldString(String fieldString) {\n        this.fieldString = fieldString;\n    }\n\n    public String getFieldRandomString() {\n        return fieldRandomString;\n    }\n\n    public void setFieldRandomString(String fieldRandomString) {\n        this.fieldRandomString = fieldRandomString;\n    }\n\n    public short getFieldShort() {\n        return fieldShort;\n    }\n\n    public void setFieldShort(short fieldShort) {\n        this.fieldShort = fieldShort;\n    }\n\n    public int getFieldInt() {\n        return fieldInt;\n    }\n\n    public void setFieldInt(int fieldInt) {\n        this.fieldInt = fieldInt;\n    }\n\n    public long getFieldLongPrimaryKey() {\n        return fieldLongPrimaryKey;\n    }\n\n    public void setFieldLongPrimaryKey(long fieldLongPrimaryKey) {\n        this.fieldLongPrimaryKey = fieldLongPrimaryKey;\n    }\n\n    public long getFieldLong() {\n        return fieldLong;\n    }\n\n    public void setFieldLong(long fieldLong) {\n        this.fieldLong = fieldLong;\n    }\n\n    public byte getFieldByte() {\n        return fieldByte;\n    }\n\n    public void setFieldByte(byte fieldByte) {\n        this.fieldByte = fieldByte;\n    }\n\n    public float getFieldFloat() {\n        return fieldFloat;\n    }\n\n    public void setFieldFloat(float fieldFloat) {\n        this.fieldFloat = fieldFloat;\n    }\n\n    public double getFieldDouble() {\n        return fieldDouble;\n    }\n\n    public void setFieldDouble(double fieldDouble) {\n        this.fieldDouble = fieldDouble;\n    }\n\n    public boolean isFieldBoolean() {\n        return fieldBoolean;\n    }\n\n    public void setFieldBoolean(boolean fieldBoolean) {\n        this.fieldBoolean = fieldBoolean;\n    }\n\n    public Date getFieldDate() {\n        return fieldDate;\n    }\n\n    public void setFieldDate(Date fieldDate) {\n        this.fieldDate = fieldDate;\n    }\n\n    public byte[] getFieldBinary() {\n        return fieldBinary;\n    }\n\n    public void setFieldBinary(byte[] fieldBinary) {\n        this.fieldBinary = fieldBinary;\n    }\n\n    public RandomPrimaryKey getFieldObject() {\n        return fieldObject;\n    }\n\n    public void setFieldObject(RandomPrimaryKey fieldObject) {\n        this.fieldObject = fieldObject;\n    }\n\n    public ObjectId getFieldObjectId() {\n        return fieldObjectId;\n    }\n\n    public void setFieldObjectId(ObjectId fieldObjectId) {\n        this.fieldObjectId = fieldObjectId;\n    }\n\n    public Decimal128 getFieldDecimal128() {\n        return fieldDecimal128;\n    }\n\n    public void setFieldDecimal128(Decimal128 fieldDecimal128) {\n        this.fieldDecimal128 = fieldDecimal128;\n    }\n\n    public UUID getFieldUUID() {\n        return fieldUUID;\n    }\n\n    public void setFieldUUID(UUID fieldUUID) {\n        this.fieldUUID = fieldUUID;\n    }\n\n    public RealmAny getFieldRealmAny() {\n        return fieldRealmAny;\n    }\n\n    public void setFieldRealmAny(RealmAny fieldRealmAny) {\n        this.fieldRealmAny = fieldRealmAny;\n    }\n\n    public RealmList<RandomPrimaryKey> getFieldList() {\n        return fieldList;\n    }\n\n    public void setFieldList(RealmList<RandomPrimaryKey> fieldList) {\n        this.fieldList = fieldList;\n    }\n\n    public RealmList<String> getFieldStringList() {\n        return fieldStringList;\n    }\n\n    public void setFieldStringList(RealmList<String> fieldStringList) {\n        this.fieldStringList = fieldStringList;\n    }\n\n    public RealmList<byte[]> getFieldBinaryList() {\n        return fieldBinaryList;\n    }\n\n    public void setFieldBinaryList(RealmList<byte[]> fieldBinaryList) {\n        this.fieldBinaryList = fieldBinaryList;\n    }\n\n    public RealmList<Boolean> getFieldBooleanList() {\n        return fieldBooleanList;\n    }\n\n    public void setFieldBooleanList(RealmList<Boolean> fieldBooleanList) {\n        this.fieldBooleanList = fieldBooleanList;\n    }\n\n    public RealmList<Long> getFieldLongList() {\n        return fieldLongList;\n    }\n\n    public void setFieldLongList(RealmList<Long> fieldLongList) {\n        this.fieldLongList = fieldLongList;\n    }\n\n    public RealmList<Integer> getFieldIntegerList() {\n        return fieldIntegerList;\n    }\n\n    public void setFieldIntegerList(RealmList<Integer> fieldIntegerList) {\n        this.fieldIntegerList = fieldIntegerList;\n    }\n\n    public RealmList<Short> getFieldShortList() {\n        return fieldShortList;\n    }\n\n    public void setFieldShortList(RealmList<Short> fieldShortList) {\n        this.fieldShortList = fieldShortList;\n    }\n\n    public RealmList<Byte> getFieldByteList() {\n        return fieldByteList;\n    }\n\n    public void setFieldByteList(RealmList<Byte> fieldByteList) {\n        this.fieldByteList = fieldByteList;\n    }\n\n    public RealmList<Double> getFieldDoubleList() {\n        return fieldDoubleList;\n    }\n\n    public void setFieldDoubleList(RealmList<Double> fieldDoubleList) {\n        this.fieldDoubleList = fieldDoubleList;\n    }\n\n    public RealmList<Float> getFieldFloatList() {\n        return fieldFloatList;\n    }\n\n    public void setFieldFloatList(RealmList<Float> fieldFloatList) {\n        this.fieldFloatList = fieldFloatList;\n    }\n\n    public RealmList<Date> getFieldDateList() {\n        return fieldDateList;\n    }\n\n    public void setFieldDateList(RealmList<Date> fieldDateList) {\n        this.fieldDateList = fieldDateList;\n    }\n\n    public RealmList<ObjectId> getFieldObjectIdList() {\n        return fieldObjectIdList;\n    }\n\n    public void setFieldObjectIdList(RealmList<ObjectId> fieldObjectIdList) {\n        this.fieldObjectIdList = fieldObjectIdList;\n    }\n\n    public RealmList<Decimal128> getFieldDecimal128List() {\n        return fieldDecimal128List;\n    }\n\n    public void setFieldDecimal128List(RealmList<Decimal128> fieldDecimal128List) {\n        this.fieldDecimal128List = fieldDecimal128List;\n    }\n\n    public RealmList<UUID> getFieldUUIDList() {\n        return fieldUUIDList;\n    }\n\n    public void setFieldUUIDList(RealmList<UUID> fieldUUIDList) {\n        this.fieldUUIDList = fieldUUIDList;\n    }\n\n    public RealmList<RealmAny> getFieldRealmAnyList() {\n        return fieldRealmAnyList;\n    }\n\n    public void setFieldRealmAnyList(RealmList<RealmAny> fieldRealmAnyList) {\n        this.fieldRealmAnyList = fieldRealmAnyList;\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/entities/DefaultValueOverwriteNullLink.java",
    "content": "/*\n * Copyright 2016 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\npackage io.realm.entities;\n\nimport java.util.Date;\nimport java.util.UUID;\n\nimport io.realm.RealmList;\nimport io.realm.RealmObject;\nimport io.realm.annotations.Ignore;\nimport io.realm.annotations.PrimaryKey;\n\npublic class DefaultValueOverwriteNullLink extends RealmObject {\n\n    public static final String CLASS_NAME = \"DefaultValueOverwriteNullLink\";\n    public static String FIELD_OBJECT = \"fieldObject\";\n    public static String EXPECTED_KEY_OF_FIELD_OBJECT = \"expectedKeyOfFieldObject\";\n\n    private RandomPrimaryKey fieldObject;\n    private String expectedKeyOfFieldObject;\n\n    public DefaultValueOverwriteNullLink() {\n        final RandomPrimaryKey firstDefaultValue = new RandomPrimaryKey();\n        final RandomPrimaryKey secondDefaultValue = new RandomPrimaryKey();\n\n        expectedKeyOfFieldObject = secondDefaultValue.getFieldRandomPrimaryKey();\n\n        fieldObject = firstDefaultValue;\n        fieldObject = null;\n        fieldObject = secondDefaultValue;\n    }\n\n    public RandomPrimaryKey getFieldObject() {\n        return fieldObject;\n    }\n\n    public void setFieldObject(RandomPrimaryKey fieldObject) {\n        this.fieldObject = fieldObject;\n    }\n\n    public String getExpectedKeyOfFieldObject() {\n        return expectedKeyOfFieldObject;\n    }\n\n    public void setExpectedKeyOfFieldObject(String expectedKeyOfFieldObject) {\n        this.expectedKeyOfFieldObject = expectedKeyOfFieldObject;\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/entities/DefaultValueSetter.java",
    "content": "/*\n * Copyright 2016 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\npackage io.realm.entities;\n\nimport java.util.Date;\nimport java.util.UUID;\n\nimport io.realm.RealmList;\nimport io.realm.RealmObject;\nimport io.realm.annotations.Ignore;\nimport io.realm.annotations.PrimaryKey;\n\npublic class DefaultValueSetter extends RealmObject {\n\n    public static final String CLASS_NAME = \"DefaultValueOfField\";\n    public static String FIELD_IGNORED = \"fieldIgnored\";\n    public static String FIELD_RANDOM_STRING = \"fieldRandomString\";\n    public static String FIELD_STRING = \"fieldString\";\n    public static String FIELD_SHORT = \"fieldShort\";\n    public static String FIELD_INT = \"fieldInt\";\n    public static String FIELD_LONG_PRIMARY_KEY = \"fieldLongPrimaryKey\";\n    public static String FIELD_LONG = \"fieldLong\";\n    public static String FIELD_BYTE = \"fieldByte\";\n    public static String FIELD_FLOAT = \"fieldFloat\";\n    public static String FIELD_DOUBLE = \"fieldDouble\";\n    public static String FIELD_BOOLEAN = \"fieldBoolean\";\n    public static String FIELD_DATE = \"fieldDate\";\n    public static String FIELD_BINARY = \"fieldBinary\";\n    public static String FIELD_OBJECT = \"fieldObject\";\n    public static String FIELD_LIST = \"fieldList\";\n\n\n    public static String FIELD_IGNORED_DEFAULT_VALUE = \"ignored\";\n    public static String FIELD_STRING_DEFAULT_VALUE = \"defaultString\";\n    public static short FIELD_SHORT_DEFAULT_VALUE = 1234;\n    public static int FIELD_INT_DEFAULT_VALUE = 123456;\n    public static long FIELD_LONG_PRIMARY_KEY_DEFAULT_VALUE = 2L * Integer.MAX_VALUE;\n    public static long FIELD_LONG_DEFAULT_VALUE = 3L * Integer.MAX_VALUE;\n    public static byte FIELD_BYTE_DEFAULT_VALUE = 100;\n    public static float FIELD_FLOAT_DEFAULT_VALUE = 0.5f;\n    public static double FIELD_DOUBLE_DEFAULT_VALUE = 0.25;\n    public static boolean FIELD_BOOLEAN_DEFAULT_VALUE = true;\n    public static Date FIELD_DATE_DEFAULT_VALUE = new Date(1473691826000L /*2016/9/12 23:56:26 JST*/);\n    public static byte[] FIELD_BINARY_DEFAULT_VALUE = new byte[] {123, -100, 0, 2};\n    public static RandomPrimaryKey FIELD_OBJECT_DEFAULT_VALUE;\n    public static RealmList<RandomPrimaryKey> FIELD_LIST_DEFAULT_VALUE;\n\n    static {\n        FIELD_OBJECT_DEFAULT_VALUE = new RandomPrimaryKey();\n        FIELD_LIST_DEFAULT_VALUE = new RealmList<RandomPrimaryKey>();\n        FIELD_LIST_DEFAULT_VALUE.add(new RandomPrimaryKey());\n    }\n\n    public static String lastRandomStringValue;\n\n    @Ignore private String fieldIgnored;\n    private String fieldString;\n    private String fieldRandomString;\n    private short fieldShort;\n    private int fieldInt;\n    @PrimaryKey private long fieldLongPrimaryKey;\n    private long fieldLong;\n    private byte fieldByte;\n    private float fieldFloat;\n    private double fieldDouble;\n    private boolean fieldBoolean;\n    private Date fieldDate;\n    private byte[] fieldBinary;\n    private RandomPrimaryKey fieldObject;\n    private RealmList<RandomPrimaryKey> fieldList;\n\n    public DefaultValueSetter() {\n        setFieldIgnored(FIELD_IGNORED_DEFAULT_VALUE);\n        setFieldString(FIELD_STRING_DEFAULT_VALUE);\n        setFieldRandomString(lastRandomStringValue = UUID.randomUUID().toString());\n        setFieldShort(FIELD_SHORT_DEFAULT_VALUE);\n        setFieldInt(FIELD_INT_DEFAULT_VALUE);\n        setFieldLongPrimaryKey(FIELD_LONG_PRIMARY_KEY_DEFAULT_VALUE);\n        setFieldLong(FIELD_LONG_DEFAULT_VALUE);\n        setFieldByte(FIELD_BYTE_DEFAULT_VALUE);\n        setFieldFloat(FIELD_FLOAT_DEFAULT_VALUE);\n        setFieldDouble(FIELD_DOUBLE_DEFAULT_VALUE);\n        setFieldBoolean(FIELD_BOOLEAN_DEFAULT_VALUE);\n        setFieldDate(FIELD_DATE_DEFAULT_VALUE);\n        setFieldBinary(FIELD_BINARY_DEFAULT_VALUE);\n        setFieldObject(FIELD_OBJECT_DEFAULT_VALUE);\n        setFieldList(FIELD_LIST_DEFAULT_VALUE);\n\n        final RandomPrimaryKey listItem2 = new RandomPrimaryKey();\n        listItem2.setFieldInt(listItem2.getFieldInt() + 1);\n        getFieldList().add(listItem2);\n    }\n\n    public DefaultValueSetter(long fieldLong) {\n        this.fieldLong = fieldLong;\n    }\n\n    public String getFieldIgnored() {\n        return fieldIgnored;\n    }\n\n    public void setFieldIgnored(String fieldIgnored) {\n        this.fieldIgnored = fieldIgnored;\n    }\n\n    public String getFieldString() {\n        return fieldString;\n    }\n\n    public void setFieldString(String fieldString) {\n        this.fieldString = fieldString;\n    }\n\n    public String getFieldRandomString() {\n        return fieldRandomString;\n    }\n\n    public void setFieldRandomString(String fieldRandomString) {\n        this.fieldRandomString = fieldRandomString;\n    }\n\n    public short getFieldShort() {\n        return fieldShort;\n    }\n\n    public void setFieldShort(short fieldShort) {\n        this.fieldShort = fieldShort;\n    }\n\n    public int getFieldInt() {\n        return fieldInt;\n    }\n\n    public void setFieldInt(int fieldInt) {\n        this.fieldInt = fieldInt;\n    }\n\n    public long getFieldLongPrimaryKey() {\n        return fieldLongPrimaryKey;\n    }\n\n    public void setFieldLongPrimaryKey(long fieldLongPrimaryKey) {\n        this.fieldLongPrimaryKey = fieldLongPrimaryKey;\n    }\n\n    public long getFieldLong() {\n        return fieldLong;\n    }\n\n    public void setFieldLong(long fieldLong) {\n        this.fieldLong = fieldLong;\n    }\n\n    public byte getFieldByte() {\n        return fieldByte;\n    }\n\n    public void setFieldByte(byte fieldByte) {\n        this.fieldByte = fieldByte;\n    }\n\n    public float getFieldFloat() {\n        return fieldFloat;\n    }\n\n    public void setFieldFloat(float fieldFloat) {\n        this.fieldFloat = fieldFloat;\n    }\n\n    public double getFieldDouble() {\n        return fieldDouble;\n    }\n\n    public void setFieldDouble(double fieldDouble) {\n        this.fieldDouble = fieldDouble;\n    }\n\n    public boolean isFieldBoolean() {\n        return fieldBoolean;\n    }\n\n    public void setFieldBoolean(boolean fieldBoolean) {\n        this.fieldBoolean = fieldBoolean;\n    }\n\n    public Date getFieldDate() {\n        return fieldDate;\n    }\n\n    public void setFieldDate(Date fieldDate) {\n        this.fieldDate = fieldDate;\n    }\n\n    public byte[] getFieldBinary() {\n        return fieldBinary;\n    }\n\n    public void setFieldBinary(byte[] fieldBinary) {\n        this.fieldBinary = fieldBinary;\n    }\n\n    public RandomPrimaryKey getFieldObject() {\n        return fieldObject;\n    }\n\n    public void setFieldObject(RandomPrimaryKey fieldObject) {\n        this.fieldObject = fieldObject;\n    }\n\n    public RealmList<RandomPrimaryKey> getFieldList() {\n        return fieldList;\n    }\n\n    public void setFieldList(RealmList<RandomPrimaryKey> fieldList) {\n        this.fieldList = fieldList;\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/entities/FieldOrder.java",
    "content": "/*\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\npackage io.realm.entities;\n\nimport io.realm.RealmObject;\n\npublic class FieldOrder extends RealmObject {\n\n    private boolean field1;\n    private int field2;\n\n    public boolean isField1() {\n        return field1;\n    }\n\n    public void setField1(boolean field1) {\n        this.field1 = field1;\n    }\n\n    public int getField2() {\n        return field2;\n    }\n\n    public void setField2(int field2) {\n        this.field2 = field2;\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/entities/HumanModule.java",
    "content": "/*\n * Copyright 2015 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\npackage io.realm.entities;\n\nimport io.realm.annotations.RealmModule;\n\n@RealmModule(classes = {CatOwner.class, Owner.class})\npublic class HumanModule {\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/entities/IOSAllTypes.java",
    "content": "/*\n * Copyright 2015 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\npackage io.realm.entities;\n\nimport java.util.Date;\n\nimport io.realm.RealmList;\nimport io.realm.RealmObject;\nimport io.realm.annotations.PrimaryKey;\n\npublic class IOSAllTypes extends RealmObject {\n\n    public final static String CLASS_NAME = \"IOSAllTypes\";\n\n    @PrimaryKey\n    private long id;\n\n    private boolean boolCol;\n    private short shortCol;\n    private int intCol;\n    private long longCol;\n    private long longLongCol;\n    private float floatCol;\n    private double doubleCol;\n    private byte[] byteCol = new byte[0];\n    private String stringCol = \"\";\n    private Date dateCol = new Date(0);\n    private IOSChild child;\n    private RealmList<IOSChild> children;\n\n    public long getId() {\n        return id;\n    }\n\n    public void setId(long id) {\n        this.id = id;\n    }\n\n    public boolean isBoolCol() {\n        return boolCol;\n    }\n\n    public void setBoolCol(boolean boolCol) {\n        this.boolCol = boolCol;\n    }\n\n    public short getShortCol() {\n        return shortCol;\n    }\n\n    public void setShortCol(short shortCol) {\n        this.shortCol = shortCol;\n    }\n\n    public int getIntCol() {\n        return intCol;\n    }\n\n    public void setIntCol(int intCol) {\n        this.intCol = intCol;\n    }\n\n    public long getLongCol() {\n        return longCol;\n    }\n\n    public void setLongCol(long longCol) {\n        this.longCol = longCol;\n    }\n\n    public long getLongLongCol() {\n        return longLongCol;\n    }\n\n    public void setLongLongCol(long longLongCol) {\n        this.longLongCol = longCol;\n    }\n\n    public float getFloatCol() {\n        return floatCol;\n    }\n\n    public void setFloatCol(float floatCol) {\n        this.floatCol = floatCol;\n    }\n\n    public double getDoubleCol() {\n        return doubleCol;\n    }\n\n    public void setDoubleCol(double doubleCol) {\n        this.doubleCol = doubleCol;\n    }\n\n    public byte[] getByteCol() {\n        return byteCol;\n    }\n\n    public void setByteCol(byte[] byteCol) {\n        this.byteCol = byteCol;\n    }\n\n    public String getStringCol() {\n        return stringCol;\n    }\n\n    public void setStringCol(String stringCol) {\n        this.stringCol = stringCol;\n    }\n\n    public Date getDateCol() {\n        return dateCol;\n    }\n\n    public void setDateCol(Date dateCol) {\n        this.dateCol = dateCol;\n    }\n\n    public IOSChild getChild() {\n        return child;\n    }\n\n    public void setChild(IOSChild child) {\n        this.child = child;\n    }\n\n    public RealmList<IOSChild> getChildren() {\n        return children;\n    }\n\n    public void setChildren(RealmList<IOSChild> children) {\n        this.children = children;\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/entities/IOSChild.java",
    "content": "/*\n * Copyright 2015 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\npackage io.realm.entities;\n\nimport io.realm.RealmObject;\n\npublic class IOSChild extends RealmObject {\n\n    private String name;\n\n    public String getName() {\n        return name;\n    }\n\n    public void setName(String name) {\n        this.name = name;\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/entities/IndexedFields.java",
    "content": "/*\n * Copyright 2017 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\npackage io.realm.entities;\n\nimport org.bson.types.ObjectId;\n\nimport io.realm.RealmObject;\nimport io.realm.annotations.Index;\nimport io.realm.annotations.PrimaryKey;\n\n\npublic class IndexedFields extends RealmObject {\n    public static final String CLASS_NAME = IndexedFields.class.getSimpleName();\n    public static final String FIELD_PRIMARY_STRING = \"_id\";\n    public static final String FIELD_INDEXED_STRING = \"indexedString\";\n    public static final String FIELD_NON_INDEXED_STRING = \"nonIndexedString\";\n\n    @PrimaryKey\n    public ObjectId _id = new ObjectId();\n\n    @Index\n    public String indexedString;\n    public String nonIndexedString;\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/entities/MappedAllJavaTypes.java",
    "content": "/*\n * Copyright 2018 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\npackage io.realm.entities;\n\nimport org.bson.types.Decimal128;\nimport org.bson.types.ObjectId;\n\nimport java.util.Date;\nimport java.util.UUID;\n\nimport io.realm.RealmList;\nimport io.realm.RealmObject;\nimport io.realm.annotations.Ignore;\nimport io.realm.annotations.Index;\nimport io.realm.annotations.PrimaryKey;\nimport io.realm.annotations.RealmClass;\nimport io.realm.annotations.RealmNamingPolicy;\n\n\n@RealmClass(fieldNamingPolicy = RealmNamingPolicy.LOWER_CASE_WITH_UNDERSCORES)\npublic class MappedAllJavaTypes extends RealmObject {\n\n    public static final String CLASS_NAME = \"MappedAllJavaTypes\";\n\n    @Ignore\n    public String fieldIgnored;\n    @Index\n    public String fieldString;\n    @PrimaryKey\n    public long fieldId;\n    public long fieldLong;\n    public short fieldShort;\n    public int fieldInt;\n    public byte fieldByte;\n    public float fieldFloat;\n    public double fieldDouble;\n    public boolean fieldBoolean;\n    public Date fieldDate;\n    public byte[] fieldBinary;\n    public Decimal128 fieldDecimal128;\n    public ObjectId fieldObjectId;\n    public UUID fieldUUID;\n    public MappedAllJavaTypes fieldObject;\n    public RealmList<MappedAllJavaTypes> fieldList;\n\n    public RealmList<String> fieldStringList;\n    public RealmList<byte[]> fieldBinaryList;\n    public RealmList<Boolean> fieldBooleanList;\n    public RealmList<Long> fieldLongList;\n    public RealmList<Integer> fieldIntegerList;\n    public RealmList<Short> fieldShortList;\n    public RealmList<Byte> fieldByteList;\n    public RealmList<Double> fieldDoubleList;\n    public RealmList<Float> fieldFloatList;\n    public RealmList<Date> fieldDateList;\n    public RealmList<Decimal128> fieldDecimalList; // FIXME using fieldDecimal128List causes issues investigate\n    public RealmList<ObjectId> fieldObjectIdList;\n    public RealmList<UUID> fieldUUIDList;\n\n    public MappedAllJavaTypes() {\n    }\n\n    public MappedAllJavaTypes(long fieldLong) {\n        this.fieldId = fieldLong;\n        this.fieldLong = fieldLong;\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/entities/MutableRealmIntegerTypes.java",
    "content": "package io.realm.entities;\n/*\n * Copyright 2017 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\nimport io.realm.MutableRealmInteger;\nimport io.realm.RealmObject;\nimport io.realm.annotations.Index;\nimport io.realm.annotations.Required;\n\n\npublic class MutableRealmIntegerTypes extends RealmObject {\n    public static final String CLASS_NAME = \"MutableRealmIntegerTypes\";\n    public static final String FIELD_NULLABLE_MUTABLEEALMINTEGER = \"columnNullableMutableRealmInteger\";\n    public static final String FIELD_NONNULLABLE_MUTABLEREALMINTEGER = \"columnNonNullableMutableRealmInteger\";\n    public static final String FIELD_INDEXED_MUTABLEREALMINTEGER = \"columnIndexedMutableRealmInteger\";\n\n    public final MutableRealmInteger columnNullableMutableRealmInteger = MutableRealmInteger.ofNull();\n\n    @Required\n    public final MutableRealmInteger columnNonNullableMutableRealmInteger = MutableRealmInteger.valueOf(0L);\n\n    @Index\n    public final MutableRealmInteger columnIndexedMutableRealmInteger = MutableRealmInteger.ofNull();\n\n    public MutableRealmInteger getColumnNullableMutableRealmInteger() {\n        return columnNullableMutableRealmInteger;\n    }\n\n    public MutableRealmInteger getColumnNonNullableMutableRealmInteger() {\n        return columnNonNullableMutableRealmInteger;\n    }\n\n    public MutableRealmInteger getColumnIndexedMutableRealmInteger() {\n        return columnIndexedMutableRealmInteger;\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/entities/NoPrimaryKeyNullTypes.java",
    "content": "/*\n * Copyright 2015 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\npackage io.realm.entities;\n\nimport org.bson.types.Decimal128;\nimport org.bson.types.ObjectId;\n\nimport java.util.Date;\nimport java.util.UUID;\n\nimport io.realm.RealmObject;\nimport io.realm.annotations.Required;\n\n// Always follow below order and put comments like below to make NullTypes Related cases\n// 1 String\n// 2 Bytes\n// 3 Boolean\n// 4 Byte\n// 5 Short\n// 6 Integer\n// 7 Long\n// 8 Float\n// 9 Double\n// 10 Date\n// 11 Object\npublic class NoPrimaryKeyNullTypes extends RealmObject {\n\n    public static String FIELD_STRING_NOT_NULL = \"fieldStringNotNull\";\n    public static String FIELD_STRING_NULL = \"fieldStringNull\";\n    public static String FIELD_BOOLEAN_NOT_NULL = \"fieldBooleanNotNull\";\n    public static String FIELD_BOOLEAN_NULL = \"fieldBooleanNull\";\n    public static String FIELD_BYTE_NOT_NULL = \"fieldByteNotNull\";\n    public static String FIELD_BYTE_NULL = \"fieldByteNull\";\n    public static String FIELD_SHORT_NOT_NULL = \"fieldShortNotNull\";\n    public static String FIELD_SHORT_NULL = \"fieldShortNull\";\n    public static String FIELD_INTEGER_NOT_NULL = \"fieldIntegerNotNull\";\n    public static String FIELD_INTEGER_NULL = \"fieldIntegerNull\";\n    public static String FIELD_LONG_NOT_NULL = \"fieldLongNotNull\";\n    public static String FIELD_LONG_NULL = \"fieldLongNull\";\n    public static String FIELD_FLOAT_NOT_NULL = \"fieldFloatNotNull\";\n    public static String FIELD_FLOAT_NULL = \"fieldFloatNull\";\n    public static String FIELD_DOUBLE_NOT_NULL = \"fieldDoubleNotNull\";\n    public static String FIELD_DOUBLE_NULL = \"fieldDoubleNull\";\n    public static String FIELD_DATE_NOT_NULL = \"fieldDateNotNull\";\n    public static String FIELD_DATE_NULL = \"fieldDateNull\";\n\n    @Required\n    private String fieldStringNotNull = \"\";\n    private String fieldStringNull;\n\n    @Required\n    private byte[] fieldBytesNotNull = new byte[0];\n    private byte[] fieldBytesNull;\n\n    @Required\n    private Boolean fieldBooleanNotNull = false;\n    private Boolean fieldBooleanNull;\n\n    @Required\n    private Byte fieldByteNotNull = 0;\n    private Byte fieldByteNull;\n\n    @Required\n    private Short fieldShortNotNull = 0;\n    private Short fieldShortNull;\n\n    @Required\n    private Integer fieldIntegerNotNull = 0;\n    private Integer fieldIntegerNull;\n\n    @Required\n    private Long fieldLongNotNull = 0L;\n    private Long fieldLongNull;\n\n    @Required\n    private Float fieldFloatNotNull = 0F;\n    private Float fieldFloatNull;\n\n    @Required\n    private Double fieldDoubleNotNull = 0D;\n    private Double fieldDoubleNull;\n\n    @Required\n    private Date fieldDateNotNull = new Date(0);\n    private Date fieldDateNull;\n\n    @Required\n    private Decimal128 fieldDecimal128NotNull = new Decimal128(0);\n    private Decimal128 fieldDecimal128Null;\n\n    @Required\n    private ObjectId fieldObjectIdNotNull = new ObjectId();\n    private ObjectId fieldObjectIdNull;\n\n    @Required\n    private UUID fieldUUIDNotNull = UUID.randomUUID();\n    private UUID fieldUUIDNull;\n\n    private NoPrimaryKeyNullTypes fieldObjectNull;\n\n    public String getFieldStringNotNull() {\n        return fieldStringNotNull;\n    }\n\n    public void setFieldStringNotNull(String fieldStringNotNull) {\n        this.fieldStringNotNull = fieldStringNotNull;\n    }\n\n    public String getFieldStringNull() {\n        return fieldStringNull;\n    }\n\n    public void setFieldStringNull(String fieldStringNull) {\n        this.fieldStringNull = fieldStringNull;\n    }\n\n    public byte[] getFieldBytesNull() {\n        return fieldBytesNull;\n    }\n\n    public void setFieldBytesNull(byte[] fieldBytesNull) {\n        this.fieldBytesNull = fieldBytesNull;\n    }\n\n    public byte[] getFieldBytesNotNull() {\n        return fieldBytesNotNull;\n    }\n\n    public void setFieldBytesNotNull(byte[] fieldBytesNotNull) {\n        this.fieldBytesNotNull = fieldBytesNotNull;\n    }\n\n    public Boolean getFieldBooleanNotNull() {\n        return fieldBooleanNotNull;\n    }\n\n    public void setFieldBooleanNotNull(Boolean fieldBooleanNotNull) {\n        this.fieldBooleanNotNull = fieldBooleanNotNull;\n    }\n\n    public Boolean getFieldBooleanNull() {\n        return fieldBooleanNull;\n    }\n\n    public void setFieldBooleanNull(Boolean fieldBooleanNull) {\n        this.fieldBooleanNull = fieldBooleanNull;\n    }\n\n    public Byte getFieldByteNotNull() {\n        return fieldByteNotNull;\n    }\n\n    public void setFieldByteNotNull(Byte fieldByteNotNull) {\n        this.fieldByteNotNull = fieldByteNotNull;\n    }\n\n    public Byte getFieldByteNull() {\n        return fieldByteNull;\n    }\n\n    public void setFieldByteNull(Byte fieldByteNull) {\n        this.fieldByteNull = fieldByteNull;\n    }\n\n    public Short getFieldShortNotNull() {\n        return fieldShortNotNull;\n    }\n\n    public void setFieldShortNotNull(Short fieldShortNotNull) {\n        this.fieldShortNotNull = fieldShortNotNull;\n    }\n\n    public Short getFieldShortNull() {\n        return fieldShortNull;\n    }\n\n    public void setFieldShortNull(Short fieldShortNull) {\n        this.fieldShortNull = fieldShortNull;\n    }\n\n    public Integer getFieldIntegerNotNull() {\n        return fieldIntegerNotNull;\n    }\n\n    public void setFieldIntegerNotNull(Integer fieldIntegerNotNull) {\n        this.fieldIntegerNotNull = fieldIntegerNotNull;\n    }\n\n    public Integer getFieldIntegerNull() {\n        return fieldIntegerNull;\n    }\n\n    public void setFieldIntegerNull(Integer fieldIntegerNull) {\n        this.fieldIntegerNull = fieldIntegerNull;\n    }\n\n    public Long getFieldLongNotNull() {\n        return fieldLongNotNull;\n    }\n\n    public void setFieldLongNotNull(Long fieldLongNotNull) {\n        this.fieldLongNotNull = fieldLongNotNull;\n    }\n\n    public Long getFieldLongNull() {\n        return fieldLongNull;\n    }\n\n    public void setFieldLongNull(Long fieldLongNull) {\n        this.fieldLongNull = fieldLongNull;\n    }\n\n    public Float getFieldFloatNotNull() {\n        return fieldFloatNotNull;\n    }\n\n    public void setFieldFloatNotNull(Float fieldFloatNotNull) {\n        this.fieldFloatNotNull = fieldFloatNotNull;\n    }\n\n    public Float getFieldFloatNull() {\n        return fieldFloatNull;\n    }\n\n    public void setFieldFloatNull(Float fieldFloatNull) {\n        this.fieldFloatNull = fieldFloatNull;\n    }\n\n    public Double getFieldDoubleNotNull() {\n        return fieldDoubleNotNull;\n    }\n\n    public void setFieldDoubleNotNull(Double fieldDoubleNotNull) {\n        this.fieldDoubleNotNull = fieldDoubleNotNull;\n    }\n\n    public Double getFieldDoubleNull() {\n        return fieldDoubleNull;\n    }\n\n    public void setFieldDoubleNull(Double fieldDoubleNull) {\n        this.fieldDoubleNull = fieldDoubleNull;\n    }\n\n    public Date getFieldDateNotNull() {\n        return fieldDateNotNull;\n    }\n\n    public void setFieldDateNotNull(Date fieldDateNotNull) {\n        this.fieldDateNotNull = fieldDateNotNull;\n    }\n\n    public Date getFieldDateNull() {\n        return fieldDateNull;\n    }\n\n    public void setFieldDateNull(Date fieldDateNull) {\n        this.fieldDateNull = fieldDateNull;\n    }\n\n    public NoPrimaryKeyNullTypes getFieldObjectNull() {\n        return fieldObjectNull;\n    }\n\n    public void setFieldObjectNull(NoPrimaryKeyNullTypes fieldObjectNull) {\n        this.fieldObjectNull = fieldObjectNull;\n    }\n\n    public Decimal128 getFieldDecimal128NotNull() {\n        return fieldDecimal128NotNull;\n    }\n\n    public void setFieldDecimal128NotNull(Decimal128 fieldDecimal128NotNull) {\n        this.fieldDecimal128NotNull = fieldDecimal128NotNull;\n    }\n\n    public Decimal128 getFieldDecimal128Null() {\n        return fieldDecimal128Null;\n    }\n\n    public void setFieldDecimal128Null(Decimal128 fieldDecimal128Null) {\n        this.fieldDecimal128Null = fieldDecimal128Null;\n    }\n\n    public ObjectId getFieldObjectIdNotNull() {\n        return fieldObjectIdNotNull;\n    }\n\n    public void setFieldObjectIdNotNull(ObjectId fieldObjectIdNotNull) {\n        this.fieldObjectIdNotNull = fieldObjectIdNotNull;\n    }\n\n    public ObjectId getFieldObjectIdNull() {\n        return fieldObjectIdNull;\n    }\n\n    public void setFieldObjectIdNull(ObjectId fieldObjectIdNull) {\n        this.fieldObjectIdNull = fieldObjectIdNull;\n    }\n\n    public UUID getFieldUUIDNotNull() {\n        return fieldUUIDNotNull;\n    }\n\n    public void setFieldUUIDNotNull(UUID fieldUUIDNotNull) {\n        this.fieldUUIDNotNull = fieldUUIDNotNull;\n    }\n\n    public UUID getFieldUUIDNull() {\n        return fieldUUIDNull;\n    }\n\n    public void setFieldUUIDNull(UUID fieldUUIDNull) {\n        this.fieldUUIDNull = fieldUUIDNull;\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/entities/NoPrimaryKeyWithPrimaryKeyObjectRelation.java",
    "content": "/*\n * Copyright 2016 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\npackage io.realm.entities;\n\nimport io.realm.RealmObject;\n\npublic class NoPrimaryKeyWithPrimaryKeyObjectRelation extends RealmObject {\n    private String columnString;\n\n    private AllTypesPrimaryKey columnRealmObjectPK;\n\n    private int columnInt = 8;\n\n    public String getColumnString() {\n        return columnString;\n    }\n\n    public void setColumnString(String columnString) {\n        this.columnString = columnString;\n    }\n\n    public AllTypesPrimaryKey getColumnRealmObjectPK() {\n        return columnRealmObjectPK;\n    }\n\n    public void setColumnRealmObjectPK(AllTypesPrimaryKey columnRealmObjectPK) {\n        this.columnRealmObjectPK = columnRealmObjectPK;\n    }\n\n    public int getColumnInt() {\n        return columnInt;\n    }\n\n    public void setColumnInt(int columnInt) {\n        this.columnInt = columnInt;\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/entities/NonLatinFieldNames.java",
    "content": "/*\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\npackage io.realm.entities;\n\nimport io.realm.RealmList;\nimport io.realm.RealmObject;\n\npublic class NonLatinFieldNames extends RealmObject {\n\n    public final static String FIELD_LONG_KOREAN_CHAR = \"델타\";\n    public final static String FIELD_LONG_GREEK_CHAR = \"Δέλτα\";\n    public final static String FIELD_FLOAT_KOREAN_CHAR = \"베타\";\n    public final static String FIELD_FLOAT_GREEK_CHAR = \"βήτα\";\n    public final static String FIELD_CHILDREN = \"children\";\n\n    private long 델타;\n    private long Δέλτα;\n\n    private float 베타;\n    private float βήτα;\n\n    private RealmList<NonLatinFieldNames> children;\n\n    public float get베타() { return 베타; }\n\n    public void set베타(float 베타) { this.베타 = 베타; }\n\n    public float getΒήτα() { return βήτα; }\n\n    public void setΒήτα(float βήτα) { this.βήτα = βήτα; }\n\n    public long get델타() { return 델타; }\n\n    public void set델타(long 델타) { this.델타 = 델타; }\n\n    public long getΔέλτα() { return Δέλτα; }\n\n    public void setΔέλτα(long δέλτα) { this.Δέλτα = δέλτα; }\n\n    public RealmList<NonLatinFieldNames> getChildren() {\n        return children;\n    }\n\n    public void setChildren(RealmList<NonLatinFieldNames> children) {\n        this.children = children;\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/entities/NullablePrimitiveFields.java",
    "content": "/*\n * Copyright 2020 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\npackage io.realm.entities;\n\nimport org.bson.types.Decimal128;\nimport org.bson.types.ObjectId;\n\nimport java.util.Date;\nimport java.util.UUID;\n\nimport io.realm.RealmAny;\nimport io.realm.RealmObject;\n\npublic class NullablePrimitiveFields extends RealmObject {\n\n    public static final String CLASS_NAME = \"NullablePrimitiveFields\";\n\n    public static final String FIELD_STRING = \"fieldString\";\n    public static final String FIELD_INT = \"fieldInt\";\n    public static final String FIELD_FLOAT = \"fieldFloat\";\n    public static final String FIELD_DOUBLE = \"fieldDouble\";\n    public static final String FIELD_BOOLEAN = \"fieldBoolean\";\n    public static final String FIELD_DATE = \"fieldDate\";\n    public static final String FIELD_BINARY = \"fieldBinary\";\n    public static final String FIELD_OBJECT_ID = \"fieldObjectId\";\n    public static final String FIELD_DECIMAL128 = \"fieldDecimal128\";\n    public static final String FIELD_UUID = \"fieldUUID\";\n    public static final String FIELD_REALM_ANY = \"fieldRealmAny\";\n\n    private Boolean fieldBoolean;\n    private Integer fieldInt;\n    private Float fieldFloat;\n    private Double fieldDouble;\n    private String fieldString;\n    private Byte fieldBinary;\n    private Date fieldDate;\n    private ObjectId fieldObjectId;\n    private Decimal128 fieldDecimal128;\n    private UUID fieldUUID;\n    private RealmAny fieldRealmAny;\n\n    public Integer getFieldInt() {\n        return fieldInt;\n    }\n\n    public void setFieldInt(Integer fieldInt) {\n        this.fieldInt = fieldInt;\n    }\n\n    public Float getFieldFloat() {\n        return fieldFloat;\n    }\n\n    public void setFieldFloat(Float fieldFloat) {\n        this.fieldFloat = fieldFloat;\n    }\n\n    public Double getFieldDouble() {\n        return fieldDouble;\n    }\n\n    public void setFieldDouble(Double fieldDouble) {\n        this.fieldDouble = fieldDouble;\n    }\n\n    public Boolean getFieldBoolean() {\n        return fieldBoolean;\n    }\n\n    public void setFieldBoolean(Boolean fieldBoolean) {\n        this.fieldBoolean = fieldBoolean;\n    }\n\n    public String getFieldString() {\n        return fieldString;\n    }\n\n    public void setFieldString(String fieldString) {\n        this.fieldString = fieldString;\n    }\n\n    public Date getFieldDate() {\n        return fieldDate;\n    }\n\n    public void setFieldDate(Date fieldDate) {\n        this.fieldDate = fieldDate;\n    }\n\n    public Byte getFieldBinary() {\n        return fieldBinary;\n    }\n\n    public void setFieldBinary(Byte fieldBinary) {\n        this.fieldBinary = fieldBinary;\n    }\n\n    public ObjectId getFieldObjectId() {\n        return fieldObjectId;\n    }\n\n    public void setFieldObjectId(ObjectId fieldObjectId) {\n        this.fieldObjectId = fieldObjectId;\n    }\n\n    public Decimal128 getFieldDecimal128() {\n        return fieldDecimal128;\n    }\n\n    public void setFieldDecimal128(Decimal128 fieldDecimal128) {\n        this.fieldDecimal128 = fieldDecimal128;\n    }\n\n    public UUID getFieldUUID() {\n        return fieldUUID;\n    }\n\n    public void setFieldUUID(UUID fieldUUID) {\n        this.fieldUUID = fieldUUID;\n    }\n\n    public RealmAny getFieldRealmAny() {\n        return fieldRealmAny;\n    }\n\n    public void setFieldRealmAny(RealmAny fieldRealmAny) {\n        this.fieldRealmAny = fieldRealmAny;\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/entities/Object4957.java",
    "content": "/*\n * Copyright 2017 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\npackage io.realm.entities;\n\nimport io.realm.RealmList;\nimport io.realm.RealmObject;\nimport io.realm.annotations.PrimaryKey;\n\n// Object to reproduce issue https://github.com/realm/realm-java/issues/4957 .\npublic class Object4957 extends RealmObject {\n    @PrimaryKey\n    private int id;\n    // Don't change the order of the field declaration! The order is the key to reproduce the original bug.\n    private Object4957 child;\n    private RealmList<Object4957> childList = new RealmList<Object4957>();\n\n    public void setId(int id) {\n        this.id = id;\n    }\n\n    public int getId() {\n        return id;\n    }\n\n    public void setChild(Object4957 child) {\n        this.child = child;\n    }\n\n    public RealmList<Object4957> getChildList() {\n        return childList;\n    }\n\n    public Object4957 getChild() {\n        return child;\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/entities/ObjectIdPrimaryKey.java",
    "content": "/*\n * Copyright 2020 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\npackage io.realm.entities;\n\nimport org.bson.types.ObjectId;\n\nimport io.realm.RealmObject;\nimport io.realm.annotations.PrimaryKey;\n\npublic class ObjectIdPrimaryKey extends RealmObject {\n\n    public static final String CLASS_NAME = \"ObjectIdPrimaryKey\";\n    public static final String PROPERTY_OBJECT_ID = \"objectId\";\n\n    @PrimaryKey\n    private ObjectId objectId;\n\n    public ObjectId getObjectId() {\n        return objectId;\n    }\n\n    public void setObjectId(ObjectId objectId) {\n        this.objectId = objectId;\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/entities/OwnerPrimaryKey.java",
    "content": "/*\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\npackage io.realm.entities;\n\nimport io.realm.RealmList;\nimport io.realm.RealmObject;\nimport io.realm.annotations.PrimaryKey;\n\npublic class OwnerPrimaryKey extends RealmObject {\n\n    @PrimaryKey\n    private long id;\n\n    private String name;\n    private DogPrimaryKey dog;\n    private RealmList<Dog> dogs;\n\n    public OwnerPrimaryKey() {\n    }\n\n    public OwnerPrimaryKey(long id, String name) {\n        this.id = id;\n        this.name = name;\n    }\n\n    public long getId() {\n        return id;\n    }\n\n    public void setId(long id) {\n        this.id = id;\n    }\n\n    public String getName() {\n        return name;\n    }\n\n    public void setName(String name) {\n        this.name = name;\n    }\n\n    public DogPrimaryKey getDog() {\n        return dog;\n    }\n\n    public void setDog(DogPrimaryKey dog) {\n        this.dog = dog;\n    }\n\n    public RealmList<Dog> getDogs() {\n        return dogs;\n    }\n\n    public void setDogs(RealmList<Dog> dogs) {\n        this.dogs = dogs;\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/entities/PrimaryKeyAsObjectId.java",
    "content": "/*\n * Copyright 2020 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\npackage io.realm.entities;\n\nimport org.bson.types.ObjectId;\n\nimport io.realm.RealmObject;\nimport io.realm.annotations.PrimaryKey;\nimport io.realm.annotations.Required;\nimport io.realm.objectid.NullPrimaryKey;\n\npublic class PrimaryKeyAsObjectId extends RealmObject implements NullPrimaryKey<ObjectId, String> {\n\n    public static final String CLASS_NAME = \"PrimaryKeyAsObjectId\";\n    public static final String FIELD_PRIMARY_KEY = \"name\";\n    public static final String FIELD_ID = \"id\";\n\n    @PrimaryKey\n    private ObjectId id;\n    private String name;\n\n    public PrimaryKeyAsObjectId() {\n    }\n\n    public PrimaryKeyAsObjectId(ObjectId id, String name) {\n        this.id = id;\n        this.name = name;\n    }\n\n    @Override\n    public ObjectId getId() {\n        return id;\n    }\n\n    @Override\n    public void setId(ObjectId id) {\n        this.id = id;\n    }\n\n    @Override\n    public String getName() {\n        return name;\n    }\n\n    @Override\n    public void setName(String name) {\n        this.name = name;\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/entities/PrimaryKeyMix.java",
    "content": "/*\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\npackage io.realm.entities;\n\nimport io.realm.RealmObject;\nimport io.realm.annotations.PrimaryKey;\n\npublic class PrimaryKeyMix extends RealmObject {\n\n    @PrimaryKey\n    private long id;\n\n    private OwnerPrimaryKey dogOwner;\n    private Cat cat;\n\n    public PrimaryKeyMix() {\n\n    }\n\n    public PrimaryKeyMix(long id) {\n        this.id = id;\n    }\n\n    public long getId() {\n        return id;\n    }\n\n    public void setId(long id) {\n        this.id = id;\n    }\n\n    public OwnerPrimaryKey getDogOwner() {\n        return dogOwner;\n    }\n\n    public void setDogOwner(OwnerPrimaryKey dogOwner) {\n        this.dogOwner = dogOwner;\n    }\n\n    public Cat getCat() {\n        return cat;\n    }\n\n    public void setCat(Cat cat) {\n        this.cat = cat;\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/entities/PrimaryKeyRequiredAsString.java",
    "content": "/*\n * Copyright 2016 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\npackage io.realm.entities;\n\nimport io.realm.RealmObject;\nimport io.realm.annotations.PrimaryKey;\nimport io.realm.annotations.Required;\nimport io.realm.objectid.NullPrimaryKey;\n\npublic class PrimaryKeyRequiredAsString extends RealmObject implements NullPrimaryKey<String, String> {\n\n    @PrimaryKey\n    @Required\n    private String id;\n\n    private String name;\n\n    public PrimaryKeyRequiredAsString(){}\n    public PrimaryKeyRequiredAsString(String id, String name) {\n        this.id = id;\n        this.name = name;\n    }\n\n    @Override\n    public String getId() {\n        return id;\n    }\n\n    @Override\n    public void setId(String id) {\n        this.id = id;\n    }\n\n    @Override\n    public String getName() {\n        return name;\n    }\n\n    @Override\n    public void setName(String name) {\n        this.name = name;\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/entities/PrimaryKeyWithNoPrimaryKeyObjectRelation.java",
    "content": "/*\n * Copyright 2016 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\npackage io.realm.entities;\n\nimport io.realm.RealmObject;\nimport io.realm.annotations.PrimaryKey;\n\npublic class PrimaryKeyWithNoPrimaryKeyObjectRelation extends RealmObject {\n    public static final String CLASS_NAME = \"PrimaryKeyWithNoPrimaryKeyObjectRelation\";\n    public static final String FIELD_COLUMN_STRING = \"columnString\";\n    public static final String FIELD_COLUMN_REALM_OBJECT_NO_PK = \"columnRealmObjectNoPK\";\n    public static final String FIELD_COLUMN_INT = \"columnInt\";\n\n    public static final int FIELD_COLUMN_INT_DEFAULT_VALUE = 8;\n\n    @PrimaryKey\n    private String columnString;\n\n    private AllTypes columnRealmObjectNoPK;\n\n    private int columnInt = FIELD_COLUMN_INT_DEFAULT_VALUE;\n\n    public String getColumnString() {\n        return columnString;\n    }\n\n    public void setColumnString(String columnString) {\n        this.columnString = columnString;\n    }\n\n    public AllTypes getColumnRealmObjectNoPK() {\n        return columnRealmObjectNoPK;\n    }\n\n    public void setColumnRealmObjectNoPK(AllTypes columnRealmObjectNoPK) {\n        this.columnRealmObjectNoPK = columnRealmObjectNoPK;\n    }\n\n    public int getColumnInt() {\n        return columnInt;\n    }\n\n    public void setColumnInt(int columnInt) {\n        this.columnInt = columnInt;\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/entities/PrimitiveListTypes.java",
    "content": "/*\n * Copyright 2017 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\npackage io.realm.entities;\n\nimport org.bson.types.Decimal128;\nimport org.bson.types.ObjectId;\n\nimport java.util.Date;\nimport java.util.UUID;\n\nimport io.realm.RealmAny;\nimport io.realm.RealmList;\nimport io.realm.RealmObject;\nimport io.realm.annotations.Required;\n\n\npublic class PrimitiveListTypes extends RealmObject {\n    public static final String FIELD_STRING_LIST = \"stringList\";\n    public static final String FIELD_BINARY_LIST = \"binaryList\";\n    public static final String FIELD_BOOLEAN_LIST = \"booleanList\";\n    public static final String FIELD_DOUBLE_LIST = \"doubleList\";\n    public static final String FIELD_FLOAT_LIST = \"floatList\";\n    public static final String FIELD_DATE_LIST = \"dateList\";\n    public static final String FIELD_BYTE_LIST = \"byteList\";\n    public static final String FIELD_SHORT_LIST = \"shortList\";\n    public static final String FIELD_INT_LIST = \"intList\";\n    public static final String FIELD_LONG_LIST = \"longList\";\n    public static final String FIELD_DECIMAL128_LIST = \"decimal128List\";\n    public static final String FIELD_OBJECT_ID_LIST = \"objectIdList\";\n    public static final String FIELD_UUID_LIST = \"uuidList\";\n    public static final String FIELD_REALM_ANY_LIST = \"realmAnyList\";\n    public static final String FIELD_REQUIRED_STRING_LIST = \"requiredStringList\";\n    public static final String FIELD_REQUIRED_BINARY_LIST = \"requiredBinaryList\";\n    public static final String FIELD_REQUIRED_BOOLEAN_LIST = \"requiredBooleanList\";\n    public static final String FIELD_REQUIRED_DOUBLE_LIST = \"requiredDoubleList\";\n    public static final String FIELD_REQUIRED_FLOAT_LIST = \"requiredFloatList\";\n    public static final String FIELD_REQUIRED_DATE_LIST = \"requiredDateList\";\n    public static final String FIELD_REQUIRED_BYTE_LIST = \"requiredByteList\";\n    public static final String FIELD_REQUIRED_SHORT_LIST = \"requiredShortList\";\n    public static final String FIELD_REQUIRED_INT_LIST = \"requiredIntList\";\n    public static final String FIELD_REQUIRED_LONG_LIST = \"requiredLongList\";\n    public static final String FIELD_REQUIRED_DECIMAL128_LIST = \"requiredDecimal128List\";\n    public static final String FIELD_REQUIRED_OBJECT_ID_LIST = \"requiredObjectIdList\";\n    public static final String FIELD_REQUIRED_UUID_LIST = \"requiredUUIDList\";\n\n    @SuppressWarnings(\"unused\")\n    private RealmList<String> stringList;\n    @SuppressWarnings(\"unused\")\n    private RealmList<byte[]> binaryList;\n    @SuppressWarnings(\"unused\")\n    private RealmList<Boolean> booleanList;\n    @SuppressWarnings(\"unused\")\n    private RealmList<Double> doubleList;\n    @SuppressWarnings(\"unused\")\n    private RealmList<Float> floatList;\n    @SuppressWarnings(\"unused\")\n    private RealmList<Date> dateList;\n    @SuppressWarnings(\"unused\")\n    private RealmList<Byte> byteList;\n    @SuppressWarnings(\"unused\")\n    private RealmList<Short> shortList;\n    @SuppressWarnings(\"unused\")\n    private RealmList<Integer> intList;\n    @SuppressWarnings(\"unused\")\n    private RealmList<Long> longList;\n    @SuppressWarnings(\"unused\")\n    private RealmList<Decimal128> decimal128List;\n    @SuppressWarnings(\"unused\")\n    private RealmList<ObjectId> objectIdList;\n    @SuppressWarnings(\"unused\")\n    private RealmList<UUID> uuidList;\n    @SuppressWarnings(\"unused\")\n    private RealmList<RealmAny> realmAnyList;\n\n    @SuppressWarnings(\"unused\")\n    @Required\n    private RealmList<String> requiredStringList;\n    @SuppressWarnings(\"unused\")\n    @Required\n    private RealmList<byte[]> requiredBinaryList;\n    @SuppressWarnings(\"unused\")\n    @Required\n    private RealmList<Boolean> requiredBooleanList;\n    @SuppressWarnings(\"unused\")\n    @Required\n    private RealmList<Double> requiredDoubleList;\n    @SuppressWarnings(\"unused\")\n    @Required\n    private RealmList<Float> requiredFloatList;\n    @SuppressWarnings(\"unused\")\n    @Required\n    private RealmList<Date> requiredDateList;\n    @SuppressWarnings(\"unused\")\n    @Required\n    private RealmList<Byte> requiredByteList;\n    @SuppressWarnings(\"unused\")\n    @Required\n    private RealmList<Short> requiredShortList;\n    @SuppressWarnings(\"unused\")\n    @Required\n    private RealmList<Integer> requiredIntList;\n    @SuppressWarnings(\"unused\")\n    @Required\n    private RealmList<Long> requiredLongList;\n    @SuppressWarnings(\"unused\")\n    @Required\n    private RealmList<Decimal128> requiredDecimal128List;\n    @SuppressWarnings(\"unused\")\n    @Required\n    public RealmList<ObjectId> requiredObjectIdList;\n    @SuppressWarnings(\"unused\")\n    @Required\n    private RealmList<UUID> requiredUUIDList;\n\n    public RealmList getList(String fieldName) {\n        switch (fieldName) {\n            case FIELD_STRING_LIST:\n                return stringList;\n            case FIELD_BINARY_LIST:\n                return binaryList;\n            case FIELD_BOOLEAN_LIST:\n                return booleanList;\n            case FIELD_DOUBLE_LIST:\n                return doubleList;\n            case FIELD_FLOAT_LIST:\n                return floatList;\n            case FIELD_DATE_LIST:\n                return dateList;\n            case FIELD_BYTE_LIST:\n                return byteList;\n            case FIELD_SHORT_LIST:\n                return shortList;\n            case FIELD_INT_LIST:\n                return intList;\n            case FIELD_LONG_LIST:\n                return longList;\n            case FIELD_DECIMAL128_LIST:\n                return decimal128List;\n            case FIELD_OBJECT_ID_LIST:\n                return objectIdList;\n            case FIELD_UUID_LIST:\n                return uuidList;\n            case FIELD_REALM_ANY_LIST:\n                return realmAnyList;\n            case FIELD_REQUIRED_STRING_LIST:\n                return requiredStringList;\n            case FIELD_REQUIRED_BINARY_LIST:\n                return requiredBinaryList;\n            case FIELD_REQUIRED_BOOLEAN_LIST:\n                return requiredBooleanList;\n            case FIELD_REQUIRED_DOUBLE_LIST:\n                return requiredDoubleList;\n            case FIELD_REQUIRED_FLOAT_LIST:\n                return requiredFloatList;\n            case FIELD_REQUIRED_DATE_LIST:\n                return requiredDateList;\n            case FIELD_REQUIRED_BYTE_LIST:\n                return requiredByteList;\n            case FIELD_REQUIRED_SHORT_LIST:\n                return requiredShortList;\n            case FIELD_REQUIRED_INT_LIST:\n                return requiredIntList;\n            case FIELD_REQUIRED_LONG_LIST:\n                return requiredLongList;\n            case FIELD_REQUIRED_DECIMAL128_LIST:\n                return requiredDecimal128List;\n            case FIELD_REQUIRED_OBJECT_ID_LIST:\n                return requiredObjectIdList;\n            case FIELD_REQUIRED_UUID_LIST:\n                return requiredUUIDList;\n            default:\n                throw new IllegalArgumentException(\"Unknown field name: '\" + fieldName + \"'.\");\n        }\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/entities/RandomPrimaryKey.java",
    "content": "/*\n * Copyright 2016 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\npackage io.realm.entities;\n\nimport java.util.UUID;\n\nimport io.realm.RealmObject;\nimport io.realm.annotations.PrimaryKey;\n\npublic class RandomPrimaryKey extends RealmObject {\n\n    public static final String CLASS_NAME = \"RandomPrimaryKey\";\n    public static String FIELD_RANDOM_PRIMARY_KEY = \"fieldRandomPrimaryKey\";\n    public static String FIELD_INT = \"fieldInt\";\n\n\n    public static int FIELD_INT_DEFAULT_VALUE = 1357924;\n\n    @PrimaryKey private String fieldRandomPrimaryKey = UUID.randomUUID().toString();\n    private int fieldInt = FIELD_INT_DEFAULT_VALUE;\n\n    public RandomPrimaryKey() {\n    }\n\n    public String getFieldRandomPrimaryKey() {\n        return fieldRandomPrimaryKey;\n    }\n\n    public void setFieldRandomPrimaryKey(String fieldRandomPrimaryKey) {\n        this.fieldRandomPrimaryKey = fieldRandomPrimaryKey;\n    }\n\n    public int getFieldInt() {\n        return fieldInt;\n    }\n\n    public void setFieldInt(int fieldInt) {\n        this.fieldInt = fieldInt;\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/entities/StringAndInt.java",
    "content": "/*\n * Copyright 2015 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\npackage io.realm.entities;\n\nimport io.realm.RealmObject;\n\npublic class StringAndInt extends RealmObject {\n    private String str;\n    private int number;\n\n    public String getStr() {\n        return str;\n    }\n\n    public void setStr(String str) {\n        this.str = str;\n    }\n\n    public int getNumber() {\n        return number;\n    }\n\n    public void setNumber(int number) {\n        this.number = number;\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/entities/StringOnly.java",
    "content": "/*\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\npackage io.realm.entities;\n\nimport io.realm.RealmObject;\n\npublic class StringOnly extends RealmObject {\n\n    public static final String CLASS_NAME = \"StringOnly\";\n    public static final String FIELD_CHARS = \"chars\";\n\n    private String chars;\n\n    public String getChars() {\n        return chars;\n    }\n\n    public void setChars(String chars) {\n        this.chars = chars;\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/entities/StringOnlyModule.java",
    "content": "package io.realm.entities;\n\nimport io.realm.annotations.RealmModule;\nimport io.realm.entities.StringOnly;\n\n@RealmModule(classes = { StringOnly.class})\npublic class StringOnlyModule {\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/entities/StringOnlyReadOnly.java",
    "content": "/*\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\npackage io.realm.entities;\n\nimport io.realm.RealmObject;\n\n\n/**\n * WARNING: This class is used by some `readOnly()` tests. Modifying this class will cause these to fail.\n * If this class is modified then `/assets/readonly.realm` must be re-created as well.\n */\npublic class StringOnlyReadOnly extends RealmObject {\n    private String chars;\n\n    public String getChars() {\n        return chars;\n    }\n\n    public void setChars(String chars) {\n        this.chars = chars;\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/entities/StringOnlyRequired.java",
    "content": "/*\n * Copyright 2017 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\npackage io.realm.entities;\n\nimport io.realm.RealmObject;\nimport io.realm.annotations.Required;\n\n// This class is used for the pre-null testing. Before 0.83.0, without nullable support, String is required by default.\n// To use the Realm file created before 0.83.0 without migration, @Required has to be added to the String field.\npublic class StringOnlyRequired extends RealmObject {\n    @Required\n    private String chars;\n\n    public String getChars() {\n        return chars;\n    }\n\n    public void setChars(String chars) {\n        this.chars = chars;\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/entities/Thread.java",
    "content": "/*\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\npackage io.realm.entities;\n\nimport io.realm.RealmObject;\n\n@SuppressWarnings(\"JavaLangClash\")\npublic class Thread extends RealmObject {\n    private String name;\n\n    public String getName() {\n        return name;\n    }\n\n    public void setName(String name) {\n        this.name = name;\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/entities/conflict/AllJavaTypes.java",
    "content": "/*\n * Copyright 2018 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 */\npackage io.realm.entities.conflict;\n\nimport io.realm.RealmObject;\nimport io.realm.annotations.RealmClass;\n\n// Potential conflict with `io.realm.entities.AllJavaTypes` but proxy classes should be generated\n// using the internal name (Which do not conflict)\n@RealmClass(name = \"!AllJavaTypes\")\npublic class AllJavaTypes extends RealmObject {\n    public String name;\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/entities/conflict/List.java",
    "content": "/*\n * Copyright 2016 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\npackage io.realm.entities.conflict;\n\nimport io.realm.RealmList;\nimport io.realm.RealmObject;\n\npublic class List extends RealmObject {\n    public RealmList<Map> mapList;\n    public Map map;\n\n    public java.lang.String str;\n    public String strObj;\n    public RealmList<String> strList;\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/entities/conflict/Map.java",
    "content": "/*\n * Copyright 2016 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\npackage io.realm.entities.conflict;\n\nimport io.realm.RealmList;\nimport io.realm.RealmModel;\nimport io.realm.annotations.RealmClass;\n\n@RealmClass\npublic class Map implements RealmModel {\n\n    public Map Map;\n    public RealmList<Map> mapList;\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/entities/conflict/String.java",
    "content": "/*\n * Copyright 2016 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\npackage io.realm.entities.conflict;\n\nimport io.realm.RealmList;\nimport io.realm.RealmObject;\n\n@SuppressWarnings(\"JavaLangClash\")\npublic class String extends RealmObject {\n    public String str;\n    public RealmList<String> strList;\n\n    public Map map;\n    public RealmList<Map> mapList;\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/entities/conflict/package-info.java",
    "content": "/*\n * Copyright 2016 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/**\n * The classes in this package have conflicting name with classes used in Realm proxy classes.\n *\n * Those model classes test https://github.com/realm/realm-java/issues/3077\n */\npackage io.realm.entities.conflict;\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/entities/migration/HandleBackLinksChild1.java",
    "content": "package io.realm.entities.migration;\n\nimport io.realm.RealmObject;\n\n// Original child as a regular object\npublic class HandleBackLinksChild1 extends RealmObject {\n\n    public String name;\n\n    public HandleBackLinksChild1() {}\n\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/entities/migration/HandleBackLinksChild2.java",
    "content": "package io.realm.entities.migration;\n\nimport io.realm.RealmObject;\nimport io.realm.annotations.RealmClass;\n\n// Child, now as an embedded object, respecting table names\n@RealmClass(embedded = true)\npublic class HandleBackLinksChild2 extends RealmObject {\n\n    public String name;\n\n    public HandleBackLinksChild2() {}\n\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/entities/migration/HandleBackLinksParent1.java",
    "content": "package io.realm.entities.migration;\n\nimport io.realm.RealmObject;\nimport io.realm.annotations.PrimaryKey;\n\n// Original parent with a regular object as a child\npublic class HandleBackLinksParent1 extends RealmObject {\n    @PrimaryKey\n    public long id;\n\n    public HandleBackLinksChild1 child;\n\n    public HandleBackLinksParent1() {}\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/entities/migration/HandleBackLinksParent2.java",
    "content": "package io.realm.entities.migration;\n\nimport io.realm.RealmObject;\nimport io.realm.annotations.PrimaryKey;\n\n// Parent, now having an embedded object as a child, respecting table names\npublic class HandleBackLinksParent2 extends RealmObject {\n    @PrimaryKey\n    public long id;\n\n    public HandleBackLinksChild2 child;\n\n    public HandleBackLinksParent2() {}\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/entities/migration/MigrationClassRenamed.java",
    "content": "/*\n * Copyright 2016 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\npackage io.realm.entities.migration;\n\nimport io.realm.RealmObject;\nimport io.realm.annotations.PrimaryKey;\nimport io.realm.migration.MigrationPrimaryKey;\n\n// Class used to test what happens if you modify a class name in a migration.\npublic class MigrationClassRenamed extends RealmObject implements MigrationPrimaryKey {\n    public static String CLASS_NAME = \"MigrationClassRenamed\";\n\n    public static long DEFAULT_FIELDS_COUNT = 5;\n    public static long DEFAULT_PRIMARY_INDEX = 2;\n\n    private Byte fieldFirst;\n    private Short fieldSecond;\n\n    // PK is placed in the middle to check if prior/posterior fields' removal is properly reflected\n    // during migration step.\n    @PrimaryKey\n    private String fieldPrimary;\n    private Integer fieldFourth;\n    private Long fieldFifth;\n\n    public void setFieldFirst(Byte fieldFirst) {\n        this.fieldFirst = fieldFirst;\n    }\n\n    public Byte getFieldFirst() {\n        return this.fieldFirst;\n    }\n\n    public void setFieldSecond(Short fieldSecond) {\n        this.fieldSecond = fieldSecond;\n    }\n\n    public Short getFieldSecond() {\n        return this.fieldSecond;\n    }\n\n    public void setFieldPrimary(String fieldPrimary) {\n        this.fieldPrimary = fieldPrimary;\n    }\n\n    public String getFieldPrimary() {\n        return this.fieldPrimary;\n    }\n\n    public void setFieldFourth(Integer fieldFourth) {\n        this.fieldFourth = fieldFourth;\n    }\n\n    public Integer getFieldFourth() {\n        return this.fieldFourth;\n    }\n\n    public void setFieldFifth(Long fieldFifth) {\n        this.fieldFifth = fieldFifth;\n    }\n\n    public Long getFieldFifth() {\n        return this.fieldFifth;\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/entities/migration/MigrationCore6PKStringIndexedByDefault.java",
    "content": "/*\n * Copyright 2019 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\npackage io.realm.entities.migration;\n\nimport io.realm.RealmObject;\nimport io.realm.annotations.PrimaryKey;\n\npublic class MigrationCore6PKStringIndexedByDefault extends RealmObject {\n    @PrimaryKey\n    public String name;\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/entities/migration/MigrationFieldRenameAndAdd.java",
    "content": "/*\n * Copyright 2017 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\npackage io.realm.entities.migration;\n\nimport io.realm.RealmObject;\n\n\npublic class MigrationFieldRenameAndAdd extends RealmObject {\n    private String string1; // to be renamed\n    private String string2;\n\n    public String getString1() {\n        return string1;\n    }\n\n    public void setString1(String string1) {\n        this.string1 = string1;\n    }\n\n    public String getString2() {\n        return string2;\n    }\n\n    public void setString2(String string2) {\n        this.string2 = string2;\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/entities/migration/MigrationFieldRenamed.java",
    "content": "/*\n * Copyright 2016 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\npackage io.realm.entities.migration;\n\nimport io.realm.RealmObject;\nimport io.realm.annotations.PrimaryKey;\nimport io.realm.migration.MigrationPrimaryKey;\n\n// Class used to test what happens if you rename a primary field in a migration.\npublic class MigrationFieldRenamed extends RealmObject implements MigrationPrimaryKey {\n    public static String CLASS_NAME = \"MigrationFieldRenamed\";\n\n    public static long DEFAULT_FIELDS_COUNT = 5;\n    public static long DEFAULT_PRIMARY_INDEX = 2;\n\n    public static String FIELD_PRIMARY = \"fieldRenamedPrimary\";\n\n    private Byte fieldFirst;\n    private Short fieldSecond;\n\n    // PK is placed in the middle to check if prior/posterior fields' removal is properly reflected\n    // during migration step. The MigrationPrimaryKey interface' PK field name is `fieldPrimary`.\n    @PrimaryKey\n    private String fieldRenamedPrimary;\n    private Integer fieldFourth;\n    private Long fieldFifth;\n\n    public void setFieldFirst(Byte fieldFirst) {\n        this.fieldFirst = fieldFirst;\n    }\n\n    public Byte getFieldFirst() {\n        return this.fieldFirst;\n    }\n\n    public void setFieldSecond(Short fieldSecond) {\n        this.fieldSecond = fieldSecond;\n    }\n\n    public Short getFieldSecond() {\n        return this.fieldSecond;\n    }\n\n    public void setFieldRenamedPrimary(String fieldRenamedPrimary) {\n        this.fieldRenamedPrimary = fieldRenamedPrimary;\n    }\n\n    public String getFieldRenamedPrimary() {\n        return this.fieldRenamedPrimary;\n    }\n\n    public void setFieldFourth(Integer fieldFourth) {\n        this.fieldFourth = fieldFourth;\n    }\n\n    public Integer getFieldFourth() {\n        return this.fieldFourth;\n    }\n\n    public void setFieldFifth(Long fieldFifth) {\n        this.fieldFifth = fieldFifth;\n    }\n\n    public Long getFieldFifth() {\n        return this.fieldFifth;\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/entities/migration/MigrationFieldTypeToInt.java",
    "content": "/*\n * Copyright 2016 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\npackage io.realm.entities.migration;\n\nimport io.realm.RealmObject;\nimport io.realm.annotations.PrimaryKey;\nimport io.realm.migration.MigrationPrimaryKey;\n\n// Class used to test what happens if you modify a String type primary key field to int type in a migration.\npublic class MigrationFieldTypeToInt extends RealmObject implements MigrationPrimaryKey {\n    public static String CLASS_NAME = \"MigrationFieldTypeToInt\";\n\n    public static long DEFAULT_FIELDS_COUNT = 5;\n    public static long DEFAULT_PRIMARY_INDEX = 4;\n\n    public static String FIELD_PRIMARY = \"fieldIntPrimary\";\n\n    public Byte fieldFirst;\n    public Short fieldSecond;\n    @PrimaryKey\n    public int fieldIntPrimary;\n    public Integer fieldFourth;\n    public Long fieldFifth;\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/entities/migration/MigrationFieldTypeToInteger.java",
    "content": "/*\n * Copyright 2016 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\npackage io.realm.entities.migration;\n\nimport io.realm.RealmObject;\nimport io.realm.annotations.PrimaryKey;\nimport io.realm.migration.MigrationPrimaryKey;\n\n// Class used to test what happens if you modify a String type primary key field to nullable Integer type in a migration.\npublic class MigrationFieldTypeToInteger extends RealmObject implements MigrationPrimaryKey {\n    public static String CLASS_NAME = \"MigrationFieldTypeToInteger\";\n\n    public static long DEFAULT_FIELDS_COUNT = 5;\n    public static long DEFAULT_PRIMARY_INDEX = 4;\n\n    public static String FIELD_PRIMARY = \"fieldIntegerPrimary\";\n\n    public Byte fieldFirst;\n    public Short fieldSecond;\n    @PrimaryKey\n    public Integer fieldIntegerPrimary;\n    public Integer fieldFourth;\n    public Long fieldFifth;\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/entities/migration/MigrationIndexedFieldRenamed.java",
    "content": "/*\n * Copyright 2017 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\npackage io.realm.entities.migration;\n\nimport io.realm.RealmObject;\nimport io.realm.annotations.Index;\nimport io.realm.annotations.PrimaryKey;\n\npublic class MigrationIndexedFieldRenamed extends RealmObject {\n    @PrimaryKey\n    public long id;\n    @Index\n    public int oldTestField;\n    public Long testField;\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/entities/migration/MigrationPosteriorIndexOnly.java",
    "content": "/*\n * Copyright 2016 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\npackage io.realm.entities.migration;\n\nimport io.realm.RealmObject;\nimport io.realm.annotations.PrimaryKey;\nimport io.realm.migration.MigrationPrimaryKey;\n\n// Class used for testing what happens if you modify fields defined after the primary key field\npublic class MigrationPosteriorIndexOnly extends RealmObject implements MigrationPrimaryKey {\n    public static String CLASS_NAME = \"MigrationPosteriorIndexOnly\";\n\n    public static long DEFAULT_FIELDS_COUNT = 3;\n    public static long DEFAULT_PRIMARY_INDEX = 0;\n\n    @PrimaryKey\n    private String fieldPrimary;\n    private Integer fieldFourth;\n    private Long fieldFifth;\n\n    public void setFieldPrimary(String fieldPrimary) {\n        this.fieldPrimary = fieldPrimary;\n    }\n\n    public String getFieldPrimary() {\n        return this.fieldPrimary;\n    }\n\n    public void setFieldFourth(Integer fieldFourth) {\n        this.fieldFourth = fieldFourth;\n    }\n\n    public Integer getFieldFourth() {\n        return this.fieldFourth;\n    }\n\n    public void setFieldFifth(Long fieldFifth) {\n        this.fieldFifth = fieldFifth;\n    }\n\n    public Long getFieldFifth() {\n        return this.fieldFifth;\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/entities/migration/MigrationPriorIndexOnly.java",
    "content": "/*\n * Copyright 2016 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\npackage io.realm.entities.migration;\n\nimport io.realm.RealmObject;\nimport io.realm.annotations.PrimaryKey;\nimport io.realm.migration.MigrationPrimaryKey;\n\n// Class used for testing what happens if you modify fields defined before the primary key field\npublic class MigrationPriorIndexOnly extends RealmObject implements MigrationPrimaryKey {\n    public static String CLASS_NAME = \"MigrationPriorIndexOnly\";\n\n    public static long DEFAULT_FIELDS_COUNT = 3;\n    public static long DEFAULT_PRIMARY_INDEX = 2;\n\n    private Byte fieldFirst;\n    private Short fieldSecond;\n    @PrimaryKey\n    private String fieldPrimary;\n\n    public void setFieldFirst(Byte fieldFirst) {\n        this.fieldFirst = fieldFirst;\n    }\n\n    public Byte getFieldFirst() {\n        return this.fieldFirst;\n    }\n\n    public void setFieldSecond(Short fieldSecond) {\n        this.fieldSecond = fieldSecond;\n    }\n\n    public Short getFieldSecond() {\n        return this.fieldSecond;\n    }\n\n    public void setFieldPrimary(String fieldPrimary) {\n        this.fieldPrimary = fieldPrimary;\n    }\n\n    public String getFieldPrimary() {\n        return this.fieldPrimary;\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/entities/pojo/AllTypesRealmModel.java",
    "content": "/*\n * Copyright 2016 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\npackage io.realm.entities.pojo;\n\nimport org.bson.types.Decimal128;\nimport org.bson.types.ObjectId;\n\nimport java.util.Date;\nimport java.util.UUID;\n\nimport io.realm.RealmAny;\nimport io.realm.RealmList;\nimport io.realm.RealmModel;\nimport io.realm.annotations.Index;\nimport io.realm.annotations.PrimaryKey;\nimport io.realm.annotations.RealmClass;\nimport io.realm.entities.Dog;\n\n@RealmClass\npublic class AllTypesRealmModel implements RealmModel {\n    public static final String CLASS_NAME = \"AllTypesRealmModel\";\n    public static final String FIELD_LONG = \"columnLong\";\n    public static final String FIELD_BYTE = \"columnByte\";\n    public static final String FIELD_DOUBLE = \"columnDouble\";\n    public static final String FIELD_STRING = \"columnString\";\n    public static final String FIELD_BINARY = \"columnBinary\";\n    public static final String FIELD_BOOLEAN = \"columnBoolean\";\n    public static final String FIELD_REALM_ANY = \"columnRealmAny\";\n    public static final String FIELD_REALM_ANY_LIST = \"columnRealmAnyRealmList\";\n\n    @Index\n    public String columnString;\n    @PrimaryKey\n    public long columnLong;\n    public byte columnByte;\n    public float columnFloat;\n    public double columnDouble;\n    public boolean columnBoolean;\n    public Date columnDate;\n    public byte[] columnBinary;\n    public Dog columnRealmObject;\n    public RealmList<Dog> columnRealmList;\n    public Decimal128 columnDecimal128;\n    public ObjectId columnObjectId;\n    public UUID columnUUID;\n    public RealmAny columnRealmAny;\n    public RealmList<RealmAny> columnRealmAnyRealmList;\n\n\n    @Override\n    public int hashCode() {\n        return 42;\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/entities/pojo/InvalidRealmModel.java",
    "content": "/*\n * Copyright 2016 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\npackage io.realm.entities.pojo;\n\nimport io.realm.RealmModel;\n\npublic class InvalidRealmModel implements RealmModel {\n    public String id;\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/entities/pojo/PojoWithRealmListOfRealmObject.java",
    "content": "/*\n * Copyright 2016 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\npackage io.realm.entities.pojo;\n\nimport io.realm.RealmList;\nimport io.realm.RealmModel;\nimport io.realm.annotations.RealmClass;\nimport io.realm.entities.AllTypes;\n\n@RealmClass\npublic class PojoWithRealmListOfRealmObject implements RealmModel {\n    private RealmList<AllTypes> columnRealmList;\n\n    public RealmList<AllTypes> getColumnRealmList() {\n        return columnRealmList;\n    }\n\n    public void setColumnRealmList(RealmList<AllTypes> columnRealmList) {\n        this.columnRealmList = columnRealmList;\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/entities/pojo/RealmModelWithRealmListOfRealmModel.java",
    "content": "/*\n * Copyright 2016 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\npackage io.realm.entities.pojo;\n\nimport io.realm.RealmList;\nimport io.realm.RealmModel;\nimport io.realm.annotations.RealmClass;\n\n@RealmClass\npublic class RealmModelWithRealmListOfRealmModel implements RealmModel {\n    private RealmList<AllTypesRealmModel> columnRealmList;\n\n    public RealmList<AllTypesRealmModel> getColumnRealmList() {\n        return columnRealmList;\n    }\n\n    public void setColumnRealmList(RealmList<AllTypesRealmModel> columnRealmList) {\n        this.columnRealmList = columnRealmList;\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/entities/pojo/RealmModelWithRealmModelField.java",
    "content": "/*\n * Copyright 2016 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\npackage io.realm.entities.pojo;\n\nimport io.realm.RealmModel;\nimport io.realm.annotations.RealmClass;\n\n@RealmClass\npublic class RealmModelWithRealmModelField implements RealmModel {\n    private AllTypesRealmModel allTypesRealmModel;\n\n    public AllTypesRealmModel getAllTypesRealmModel() {\n        return allTypesRealmModel;\n    }\n\n    public void setAllTypesRealmModel(AllTypesRealmModel allTypesRealmModel) {\n        this.allTypesRealmModel = allTypesRealmModel;\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/entities/pojo/RealmObjectWithRealmListOfRealmModel.java",
    "content": "/*\n * Copyright 2016 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\npackage io.realm.entities.pojo;\n\nimport io.realm.RealmList;\nimport io.realm.RealmObject;\n\npublic class RealmObjectWithRealmListOfRealmModel extends RealmObject {\n    private RealmList<AllTypesRealmModel> columnRealmList;\n\n    public RealmList<AllTypesRealmModel> getColumnRealmList() {\n        return columnRealmList;\n    }\n\n    public void setColumnRealmList(RealmList<AllTypesRealmModel> columnRealmList) {\n        this.columnRealmList = columnRealmList;\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/entities/pojo/RealmObjectWithRealmModelField.java",
    "content": "/*\n * Copyright 2016 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\npackage io.realm.entities.pojo;\n\nimport io.realm.RealmObject;\n\npublic class RealmObjectWithRealmModelField extends RealmObject {\n    private AllTypesRealmModel allTypesRealmModel;\n\n    public AllTypesRealmModel getAllTypesRealmModel() {\n        return allTypesRealmModel;\n    }\n\n    public void setAllTypesRealmModel(AllTypesRealmModel allTypesRealmModel) {\n        this.allTypesRealmModel = allTypesRealmModel;\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/entities/realmname/ClassNameOverrideModulePolicy.java",
    "content": "/*\n * Copyright 2017 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 */\npackage io.realm.entities.realmname;\n\nimport java.util.Arrays;\nimport java.util.List;\n\nimport io.realm.RealmList;\nimport io.realm.RealmObject;\nimport io.realm.annotations.RealmClass;\nimport io.realm.annotations.RealmField;\nimport io.realm.annotations.RealmNamingPolicy;\n\n// Class will inherit RealmNamingPolicy.LOWER_CASE_WITH_UNDERSCORES from the module `CustomRealmNamesModule`\n@RealmClass(name = \"class-name-override\", fieldNamingPolicy = RealmNamingPolicy.LOWER_CASE_WITH_UNDERSCORES)\npublic class ClassNameOverrideModulePolicy extends RealmObject {\n\n    // Expected internal names\n    public static final String CLASS_NAME = \"class-name-override\";\n    public static final String FIELD_CAMEL_CASE = \"camel_case\";\n    public static final String FIELD_PASCAL_CASE = \"pascal_case\";\n    public static final String FIELD_M_HUNGARIAN = \"hungarian\";\n    public static final String FIELD_ALLCAPS = \"allcaps\";\n    public static final String FIELD_ALLLOWER = \"alllower\";\n    public static final String FIELD_WITH_UNDERSCORES = \"with_underscores\";\n    public static final String FIELD_WITH_SPECIAL_CHARS = \"internal_var\";\n    public static final String FIELD_CUSTOM_NAME = \"a different name\";\n    public static final List<String> ALL_FIELDS = Arrays.asList(\n            FIELD_CAMEL_CASE,\n            FIELD_PASCAL_CASE,\n            FIELD_M_HUNGARIAN,\n            FIELD_ALLCAPS,\n            FIELD_ALLLOWER,\n            FIELD_WITH_UNDERSCORES,\n            FIELD_WITH_SPECIAL_CHARS,\n            FIELD_CUSTOM_NAME\n    );\n\n    public String camelCase;\n    public int PascalCase;\n    public boolean mHungarian;\n    public boolean ALLCAPS;\n    public boolean alllower;\n    public boolean with_underscores;\n    public RealmList<ClassWithPolicy> $_internalVar;\n    @RealmField(name = \"a different name\") // This will override the class policy\n    public String customName;\n}\n\n\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/entities/realmname/ClassWithPolicy.java",
    "content": "/*\n * Copyright 2017 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 */\npackage io.realm.entities.realmname;\n\nimport java.util.Arrays;\nimport java.util.Date;\nimport java.util.List;\n\nimport io.realm.RealmList;\nimport io.realm.RealmObject;\nimport io.realm.RealmResults;\nimport io.realm.annotations.LinkingObjects;\nimport io.realm.annotations.RealmClass;\nimport io.realm.annotations.RealmField;\nimport io.realm.annotations.RealmNamingPolicy;\n\n@RealmClass(fieldNamingPolicy = RealmNamingPolicy.LOWER_CASE_WITH_UNDERSCORES)\npublic class ClassWithPolicy extends RealmObject {\n\n    public static final String CLASS_NAME = \"class_with_policy\";\n    public static final String FIELD_CAMEL_CASE = \"camel_case\";\n    public static final String FIELD_PASCAL_CASE = \"pascal_case\";\n    public static final String FIELD_M_HUNGARIAN = \"hungarian\";\n    public static final String FIELD_ALLCAPS = \"allcaps\";\n    public static final String FIELD_ALLLOWER = \"alllower\";\n    public static final String FIELD_FIRST_CAPS = \"first_caps\";\n    public static final String FIELD_WITH_UNDERSCORES = \"with_underscores\";\n    public static final String FIELD_WITH_SPECIAL_CHARS = \"internal_var\";\n    public static final String FIELD_CUSTOM_NAME = \"a different name\";\n    public static final List<String> ALL_FIELDS = Arrays.asList(\n            FIELD_CAMEL_CASE,\n            FIELD_PASCAL_CASE,\n            FIELD_M_HUNGARIAN,\n            FIELD_ALLCAPS,\n            FIELD_ALLLOWER,\n            FIELD_FIRST_CAPS,\n            FIELD_WITH_UNDERSCORES,\n            FIELD_WITH_SPECIAL_CHARS,\n            FIELD_CUSTOM_NAME\n    );\n\n    public String camelCase;\n    public int PascalCase;\n    public boolean mHungarian;\n    public byte[] ALLCAPS;\n    public Date alllower;\n    public long FIRSTCaps;\n    public ClassWithPolicy with_underscores;\n    public RealmList<ClassWithPolicy> $_internalVar;\n    @RealmField(name = \"a different name\")\n    public String customName;\n\n    @LinkingObjects(\"with_underscores\")\n    public final RealmResults<ClassWithPolicy> parents = null;\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/entities/realmname/ClassWithValueDefinedNames.java",
    "content": "/*\n * Copyright 2018 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 */\npackage io.realm.entities.realmname;\n\nimport io.realm.RealmObject;\nimport io.realm.RealmResults;\nimport io.realm.annotations.LinkingObjects;\nimport io.realm.annotations.RealmClass;\nimport io.realm.annotations.RealmField;\n\n@RealmClass(\"my-class-name\")\npublic class ClassWithValueDefinedNames extends RealmObject {\n\n    public static final String JAVA_CLASS_NAME = \"ClassWithValueDefinedNames\";\n    public static final String REALM_CLASS_NAME = \"my-class-name\";\n\n    public static final String JAVA_FIELD_NAME = \"field\";\n    public static final String REALM_FIELD_NAME = \"my-field-name\";\n\n    @RealmField(\"my-field-name\")\n    public String field;\n\n    @RealmField(\"object-link\")\n    public ClassWithValueDefinedNames objectLink;\n\n    // Must use the Java defined name\n    // Using `@LinkingObjects(\"object-link\")` is not supported\n    @LinkingObjects(\"objectLink\")\n    public final RealmResults<ClassWithValueDefinedNames> parents = null;\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/entities/realmname/CustomRealmNamesModule.java",
    "content": "/*\n * Copyright 2018 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 */\npackage io.realm.entities.realmname;\n\nimport io.realm.annotations.RealmModule;\nimport io.realm.annotations.RealmNamingPolicy;\n\n@RealmModule(classes =\n        {\n            ClassNameOverrideModulePolicy.class,\n            ClassWithPolicy.class,\n            ClassWithValueDefinedNames.class,\n            DefaultPolicyFromModule.class,\n            FieldNameOverrideClassPolicy.class\n        },\n        classNamingPolicy = RealmNamingPolicy.LOWER_CASE_WITH_UNDERSCORES,\n        fieldNamingPolicy = RealmNamingPolicy.LOWER_CASE_WITH_UNDERSCORES\n)\npublic class CustomRealmNamesModule {\n\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/entities/realmname/DefaultPolicyFromModule.java",
    "content": "/*\n * Copyright 2018 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 */\npackage io.realm.entities.realmname;\n\nimport io.realm.RealmObject;\n\npublic class DefaultPolicyFromModule extends RealmObject {\n    public String camelCase; // case formatter should be inherited from CustomRealmNamesModule\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/entities/realmname/FieldNameOverrideClassPolicy.java",
    "content": "/*\n * Copyright 2017 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 */\npackage io.realm.entities.realmname;\n\nimport io.realm.RealmObject;\nimport io.realm.annotations.RealmClass;\nimport io.realm.annotations.RealmField;\nimport io.realm.annotations.RealmNamingPolicy;\n\n@RealmClass(fieldNamingPolicy = RealmNamingPolicy.PASCAL_CASE)\npublic class FieldNameOverrideClassPolicy extends RealmObject {\n\n    public static final String CLASS_NAME = \"field_name_override_class_policy\";\n    public static final String FIELD_CAMEL_CASE = \"camel_case\";\n\n    @RealmField(name = FIELD_CAMEL_CASE)\n    public String camelCase;\n\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/instrumentation/ActivityLifecycle.java",
    "content": "/*\n * Copyright 2015 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\npackage io.realm.instrumentation;\n\nimport io.realm.Realm;\nimport io.realm.RealmChangeListener;\nimport io.realm.RealmConfiguration;\nimport io.realm.RealmResults;\nimport io.realm.entities.AllTypes;\n\npublic class ActivityLifecycle implements Lifecycle, RealmChangeListener<RealmResults<AllTypes>> {\n    private final RealmConfiguration realmConfiguration;\n    private Realm realm;\n    private RealmResults<AllTypes> mAllTypes;\n\n    public ActivityLifecycle (RealmConfiguration realmConfiguration) {\n        this.realmConfiguration = realmConfiguration;\n    }\n\n    @Override\n    public void onStart() {\n        realm = Realm.getInstance(realmConfiguration);\n        mAllTypes = realm.where(AllTypes.class).findAllAsync();\n        mAllTypes.addChangeListener(this);\n    }\n\n    @Override\n    public void onStop() {\n        mAllTypes.removeChangeListener(this);\n        realm.close();\n    }\n\n    @Override\n    public void onChange(RealmResults<AllTypes> object) {\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/instrumentation/Lifecycle.java",
    "content": "/*\n * Copyright 2015 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\npackage io.realm.instrumentation;\n\npublic interface Lifecycle {\n    void onStart ();\n    void onStop ();\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/instrumentation/LifecycleComponentFactory.java",
    "content": "/*\n * Copyright 2015 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\npackage io.realm.instrumentation;\n\nimport io.realm.RealmConfiguration;\n\npublic class LifecycleComponentFactory {\n    public static Lifecycle newInstance(RealmConfiguration realmConfiguration) {\n        return new ActivityLifecycle(realmConfiguration);\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/instrumentation/package-info.java",
    "content": "/*\n * Copyright 2017 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@javax.annotation.ParametersAreNonnullByDefault\npackage io.realm.instrumentation;\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/internal/AndroidCapabilitiesTest.java",
    "content": "/*\n * Copyright 2017 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 */\npackage io.realm.internal;\n\nimport androidx.test.ext.junit.runners.AndroidJUnit4;\n\nimport org.junit.Rule;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\n\nimport io.realm.internal.android.AndroidCapabilities;\nimport io.realm.rule.RunInLooperThread;\nimport io.realm.rule.RunTestInLooperThread;\n\nimport static org.junit.Assert.assertFalse;\nimport static org.junit.Assert.assertTrue;\n\n@RunWith(AndroidJUnit4.class)\npublic class AndroidCapabilitiesTest {\n\n    @Rule\n    public final RunInLooperThread looperThread = new RunInLooperThread();\n\n    @Test\n    @RunTestInLooperThread()\n    public void emulateMainThread_false() {\n        assertFalse(new AndroidCapabilities().isMainThread());\n        looperThread.testComplete();\n    }\n\n    @Test\n    @RunTestInLooperThread(emulateMainThread = true)\n    public void emulateMainThread_true() {\n        assertTrue(new AndroidCapabilities().isMainThread());\n        looperThread.testComplete();\n    }\n\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/internal/JNIColumnInfoTest.java",
    "content": "/*\n * Copyright 2015 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\npackage io.realm.internal;\n\nimport androidx.test.platform.app.InstrumentationRegistry;\nimport androidx.test.ext.junit.runners.AndroidJUnit4;\n\nimport org.junit.After;\nimport org.junit.Before;\nimport org.junit.Rule;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\n\nimport io.realm.Realm;\nimport io.realm.RealmConfiguration;\nimport io.realm.RealmFieldType;\nimport io.realm.TestHelper;\nimport io.realm.TestRealmConfigurationFactory;\n\nimport static junit.framework.Assert.assertNotSame;\nimport static junit.framework.TestCase.assertEquals;\n\n\n@RunWith(AndroidJUnit4.class)\npublic class JNIColumnInfoTest {\n\n    @Rule\n    public final TestRealmConfigurationFactory configFactory = new TestRealmConfigurationFactory();\n\n    private OsSharedRealm sharedRealm;\n    private Table table;\n\n    @Before\n    public void setUp() {\n        Realm.init(InstrumentationRegistry.getInstrumentation().getContext());\n        RealmConfiguration config = configFactory.createConfiguration();\n        sharedRealm = OsSharedRealm.getInstance(config, OsSharedRealm.VersionID.LIVE);\n\n        table = TestHelper.createTable(sharedRealm, \"temp\", new TestHelper.AdditionalTableSetup() {\n            @Override\n            public void execute(Table table) {\n                table.addColumn(RealmFieldType.STRING, \"firstName\");\n                table.addColumn(RealmFieldType.STRING, \"lastName\");\n            }\n        });\n    }\n\n    @After\n    public void tearDown() {\n        if (sharedRealm != null) {\n            sharedRealm.close();\n        }\n    }\n\n    @Test\n    public void shouldGetColumnInformation() {\n        assertEquals(2, table.getColumnCount());\n\n        long columnKey = table.getColumnKey(\"lastName\");\n        assertNotSame(Table.NO_MATCH, columnKey);\n\n        assertEquals(RealmFieldType.STRING, table.getColumnType(columnKey));\n    }\n\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/internal/JNINativeTest.java",
    "content": "/*\n * Copyright 2015 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\npackage io.realm.internal;\n\nimport androidx.test.ext.junit.runners.AndroidJUnit4;\n\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\n\nimport static junit.framework.Assert.assertEquals;\n\n@RunWith(AndroidJUnit4.class)\npublic class JNINativeTest {\n\n    @Test\n    public void nativeExceptions() {\n        long maxExceptionNumber = TestUtil.getMaxExceptionNumber();\n        for (long i = 0; i < maxExceptionNumber; i++) {\n            String expect = TestUtil.getExpectedMessage(i);\n            try {\n                TestUtil.testThrowExceptions(i);\n            } catch (Throwable throwable) {\n                assertEquals(\"Exception kind: \" + i, expect, throwable.toString());\n            }\n        }\n    }\n\n    @Test\n    public void clampMaxTimestamps() {\n        assertEquals(Long.MAX_VALUE, TestUtil.getDateFromTimestamp(Long.MAX_VALUE, 999999999));\n        assertEquals(Long.MAX_VALUE, TestUtil.getDateFromTimestamp((Long.MAX_VALUE / 1000) + 1, 0)); // 1 second above MAX in milliseconds\n    }\n\n    @Test\n    public void clampMinTimestamps() {\n        assertEquals(Long.MIN_VALUE, TestUtil.getDateFromTimestamp(Long.MIN_VALUE, -999999999));\n        assertEquals(Long.MIN_VALUE, TestUtil.getDateFromTimestamp((Long.MIN_VALUE / 1000) - 1, 0)); // 1 second below MIN in milliseconds\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/internal/JNIQueryTest.java",
    "content": "/*\n * Copyright 2015 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\npackage io.realm.internal;\n\nimport org.bson.types.Decimal128;\nimport org.bson.types.ObjectId;\nimport org.junit.After;\nimport org.junit.Before;\nimport org.junit.Rule;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\n\nimport java.util.Date;\nimport java.util.concurrent.TimeUnit;\nimport java.util.concurrent.atomic.AtomicLong;\n\nimport androidx.test.ext.junit.runners.AndroidJUnit4;\nimport androidx.test.platform.app.InstrumentationRegistry;\nimport io.realm.RealmAny;\nimport io.realm.Realm;\nimport io.realm.RealmConfiguration;\nimport io.realm.RealmFieldType;\nimport io.realm.TestHelper;\nimport io.realm.TestRealmConfigurationFactory;\n\nimport static junit.framework.TestCase.assertEquals;\nimport static org.junit.Assert.fail;\n\n@RunWith(AndroidJUnit4.class)\npublic class JNIQueryTest {\n\n    @Rule\n    public final TestRealmConfigurationFactory configFactory = new TestRealmConfigurationFactory();\n\n    @SuppressWarnings(\"FieldCanBeLocal\")\n    private RealmConfiguration config;\n    private OsSharedRealm sharedRealm;\n    private Table table;\n\n    @Before\n    public void setUp() throws Exception {\n        Realm.init(InstrumentationRegistry.getInstrumentation().getContext());\n        config = configFactory.createConfiguration();\n        sharedRealm = OsSharedRealm.getInstance(config, OsSharedRealm.VersionID.LIVE);\n    }\n\n    @After\n    public void tearDown() {\n        if (sharedRealm != null && !sharedRealm.isClosed()) {\n            sharedRealm.close();\n        }\n    }\n\n    private void init() {\n        table = TestHelper.createTable(sharedRealm, \"temp\", new TestHelper.AdditionalTableSetup() {\n            @Override\n            public void execute(Table table) {\n                long colKey1 = table.addColumn(RealmFieldType.INTEGER, \"number\");\n                long colKey2 = table.addColumn(RealmFieldType.STRING, \"name\");\n\n                TestHelper.addRowWithValues(table, new long[]{colKey1, colKey2}, new Object[]{10, \"A\"});\n                TestHelper.addRowWithValues(table, new long[]{colKey1, colKey2}, new Object[]{11, \"B\"});\n                TestHelper.addRowWithValues(table, new long[]{colKey1, colKey2}, new Object[]{12, \"C\"});\n                TestHelper.addRowWithValues(table, new long[]{colKey1, colKey2}, new Object[]{13, \"B\"});\n                TestHelper.addRowWithValues(table, new long[]{colKey1, colKey2}, new Object[]{14, \"D\"});\n                TestHelper.addRowWithValues(table, new long[]{colKey1, colKey2}, new Object[]{16, \"D\"});\n            }\n        });\n\n        assertEquals(6, table.size());\n    }\n\n    @Test\n    public void shouldQuery() {\n        init();\n        TableQuery query = table.where();\n\n        long colKey1 = table.getColumnKey(\"number\");\n\n        long cnt = query.equalTo(null,\"name\", RealmAny.valueOf(\"D\")).count();\n        assertEquals(2, cnt);\n\n        cnt = query.minimumInt(colKey1);\n        assertEquals(14, cnt);\n\n        cnt = query.maximumInt(colKey1);\n        assertEquals(16, cnt);\n\n        cnt = query.sumInt(colKey1);\n        assertEquals(14+16, cnt);\n\n        double avg = query.averageInt(colKey1);\n        assertEquals(15.0, avg, Double.MIN_NORMAL);\n\n        // TODO: Add tests with all parameters\n    }\n\n\n    @Test\n    public void nonCompleteQuery() {\n        init();\n\n        // All the following queries are not valid, e.g contain a group but not a closing group, an or() but not a second filter etc\n        try { table.where().equalTo(null, \"\", RealmAny.valueOf(1)).or().validateQuery();       fail(\"missing a second filter\"); }      catch (IllegalArgumentException ignore) {}\n        try { table.where().beginGroup().equalTo(null,\"\", RealmAny.valueOf(1)).validateQuery();    fail(\"missing a closing group\"); }      catch (IllegalArgumentException ignore) {}\n\n        try { table.where().beginGroup().count();                                fail(); }                               catch (UnsupportedOperationException ignore) {}\n        try { table.where().beginGroup().validateQuery();                              fail(); }                               catch (UnsupportedOperationException ignore) {}\n        try { table.where().beginGroup().find();                                 fail(); }                               catch (UnsupportedOperationException ignore) {}\n        try { table.where().beginGroup().minimumInt(0);                          fail(); }                               catch (UnsupportedOperationException ignore) {}\n        try { table.where().beginGroup().maximumInt(0);                          fail(); }                               catch (UnsupportedOperationException ignore) {}\n        try { table.where().beginGroup().sumInt(0);                              fail(); }                               catch (UnsupportedOperationException ignore) {}\n        try { table.where().beginGroup().averageInt(0);                          fail(); }                               catch (UnsupportedOperationException ignore) {}\n\n        try { table.where().endGroup().equalTo(null,\"\", RealmAny.valueOf(1)).validateQuery(); fail(\"ends group, no start\"); }         catch (IllegalArgumentException ignore) {}\n        try { table.where().equalTo(null,\"\", RealmAny.valueOf(1)).endGroup().validateQuery(); fail(\"ends group, no start\"); }         catch (IllegalArgumentException ignore) {}\n\n        try { table.where().equalTo(null,\"\", RealmAny.valueOf(1)).endGroup().find();    fail(\"ends group, no start\"); }         catch (IllegalArgumentException ignore) {}\n    }\n\n    @Test\n    public void shouldFind() {\n        // Creates a table.\n        Table table = TestHelper.createTable(sharedRealm, \"temp\", new TestHelper.AdditionalTableSetup() {\n            @Override\n            public void execute(Table table) {\n                long colKey1 = table.addColumn(RealmFieldType.STRING, \"username\");\n                long colKey2 = table.addColumn(RealmFieldType.INTEGER, \"score\");\n                long colKey3 = table.addColumn(RealmFieldType.BOOLEAN, \"completed\");\n\n                // Inserts some values.\n                TestHelper.addRowWithValues(table, new long[]{colKey1, colKey2, colKey3}, new Object[]{\"Arnold\", 420, false});    // 0\n                TestHelper.addRowWithValues(table, new long[]{colKey1, colKey2, colKey3}, new Object[]{\"Jane\", 770, false});      // 1 *\n                TestHelper.addRowWithValues(table, new long[]{colKey1, colKey2, colKey3}, new Object[]{\"Erik\", 600, false});      // 2\n                TestHelper.addRowWithValues(table, new long[]{colKey1, colKey2, colKey3}, new Object[]{\"Henry\", 601, false});     // 3 *\n                TestHelper.addRowWithValues(table, new long[]{colKey1, colKey2, colKey3}, new Object[]{\"Bill\", 564, true});       // 4\n                TestHelper.addRowWithValues(table, new long[]{colKey1, colKey2, colKey3}, new Object[]{\"Janet\", 875, false});     // 5 *\n            }\n        });\n\n        TableQuery query = table.where().greaterThan(null,\"score\", RealmAny.valueOf(600));\n\n        // Finds first match.\n        assertEquals(1, query.find());\n    }\n\n    @Test\n    public void queryTestForNoMatches() {\n        Table t = TestHelper.createTableWithAllColumnTypes(sharedRealm);\n\n        long columnKey1 = t.getColumnKey(\"binary\");\n        long columnKey2 = t.getColumnKey(\"boolean\");\n        long columnKey3 = t.getColumnKey(\"date\");\n        long columnKey4 = t.getColumnKey(\"double\");\n        long columnKey5 = t.getColumnKey(\"float\");\n        long columnKey6 = t.getColumnKey(\"long\");\n        long columnKey7 = t.getColumnKey(\"string\");\n        long columnKey8 = t.getColumnKey(\"decimal128\");\n        long columnKey9 = t.getColumnKey(\"object_id\");\n\n\n        sharedRealm.beginTransaction();\n        TestHelper.addRowWithValues(t, new long[]{columnKey1, columnKey2, columnKey3, columnKey4, columnKey5, columnKey6, columnKey7, columnKey8, columnKey9},\n                new Object[]{new byte[]{1,2,3}, true, new Date(1384423149761L), 4.5d, 5.7f, 100, \"string\", new Decimal128(0), new ObjectId()});\n        sharedRealm.commitTransaction();\n\n        TableQuery q = t.where().greaterThan(null,\"long\", RealmAny.valueOf(1000)); // No matches\n\n        assertEquals(-1, q.find());\n    }\n\n    @Test\n    public void queryWithWrongDataType() {\n\n        Table table = TestHelper.createTableWithAllColumnTypes(sharedRealm);\n\n        String[] columnKeys = new String[]{\"binary\", \"boolean\", \"date\", \"double\", \"float\", \"long\", \"string\"};\n\n        // Queries the table.\n        TableQuery query = table.where();\n\n        RealmAny L123 = RealmAny.valueOf(123);\n        RealmAny L321 = RealmAny.valueOf(321);\n        RealmAny F123 = RealmAny.valueOf(123.5F);\n        RealmAny F321 = RealmAny.valueOf(321.5F);\n        RealmAny D123 = RealmAny.valueOf(123.5D);\n        RealmAny D321 = RealmAny.valueOf(321.5D);\n        RealmAny date = RealmAny.valueOf(new Date());\n\n        // Compares integer in non integer columns.\n        for (int i = 0; i <= 6; i++) {\n            if ((i != 5) && (i != 1) && (i != 3) && (i != 4)) {\n                try { query.equalTo(null, columnKeys[i], L123).find();            fail(); } catch(IllegalArgumentException ignore) {}\n                try { query.notEqualTo(null, columnKeys[i], L123).find();         fail(); } catch(IllegalArgumentException ignore) {}\n                try { query.lessThan(null, columnKeys[i], L123).find();           fail(); } catch(IllegalArgumentException ignore) {}\n                try { query.lessThanOrEqual(null, columnKeys[i], L123).find();    fail(); } catch(IllegalArgumentException ignore) {}\n                try { query.greaterThan(null, columnKeys[i], L123).find();        fail(); } catch(IllegalArgumentException ignore) {}\n                try { query.greaterThanOrEqual(null, columnKeys[i], L123).find(); fail(); } catch(IllegalArgumentException ignore) {}\n                try { query.between(null, columnKeys[i], L123, L321).find();                     fail(); } catch(IllegalArgumentException ignore) {}\n            }\n        }\n\n        // Compares float in non float columns.\n        for (int i = 0; i <= 6; i++) {\n            if ((i != 5) && (i != 1) && (i != 3) && (i != 4)) {\n                try { query.equalTo(null, columnKeys[i], F123).find();            fail(); } catch(IllegalArgumentException ignore) {}\n                try { query.notEqualTo(null, columnKeys[i], F123).find();         fail(); } catch(IllegalArgumentException ignore) {}\n                try { query.lessThan(null, columnKeys[i], F123).find();           fail(); } catch(IllegalArgumentException ignore) {}\n                try { query.lessThanOrEqual(null, columnKeys[i], F123).find();    fail(); } catch(IllegalArgumentException ignore) {}\n                try { query.greaterThan(null, columnKeys[i], F123).find();        fail(); } catch(IllegalArgumentException ignore) {}\n                try { query.greaterThanOrEqual(null, columnKeys[i], F123).find(); fail(); } catch(IllegalArgumentException ignore) {}\n                try { query.between(null, columnKeys[i], F123, F321).find();                    fail(); } catch(IllegalArgumentException ignore) {}\n            }\n        }\n\n        // Compares double in non double columns.\n        for (int i = 0; i <= 6; i++) {\n            if ((i != 5) && (i != 1) && (i != 3) && (i != 4)) {\n                try { query.equalTo(null, columnKeys[i], D123).find();                     fail(); } catch(IllegalArgumentException ignore) {}\n                try { query.notEqualTo(null, columnKeys[i], D123).find();                  fail(); } catch(IllegalArgumentException ignore) {}\n                try { query.lessThan(null, columnKeys[i], D123).find();                    fail(); } catch(IllegalArgumentException ignore) {}\n                try { query.lessThanOrEqual(null, columnKeys[i], D123).find();             fail(); } catch(IllegalArgumentException ignore) {}\n                try { query.greaterThan(null, columnKeys[i], D123).find();                 fail(); } catch(IllegalArgumentException ignore) {}\n                try { query.greaterThanOrEqual(null, columnKeys[i], D123).find();          fail(); } catch(IllegalArgumentException ignore) {}\n                try { query.between(null, columnKeys[i], D123, D321).find();                             fail(); } catch(IllegalArgumentException ignore) {}\n            }\n        }\n\n        // Compares boolean in non boolean columns.\n        for (int i = 0; i <= 6; i++) {\n            if ((i != 5) && (i != 1) && (i != 3) && (i != 4)) {\n              try { query.equalTo(null, columnKeys[i], RealmAny.valueOf(true)).find();                       fail(); } catch(IllegalArgumentException ignore) {}\n            }\n        }\n\n        // Compares date.\n        for (int i = 0; i <= 6; i++) {\n            if (i != 2) {\n                try { query.equalTo(null, columnKeys[i], date).find();                   fail(); } catch(IllegalArgumentException ignore) {}\n                try { query.lessThan(null, columnKeys[i], date).find();                fail(); } catch(IllegalArgumentException ignore) {}\n                try { query.lessThanOrEqual(null, columnKeys[i], date).find();         fail(); } catch(IllegalArgumentException ignore) {}\n                try { query.greaterThan(null, columnKeys[i], date).find();             fail(); } catch(IllegalArgumentException ignore) {}\n                try { query.greaterThanOrEqual(null, columnKeys[i], date).find();      fail(); } catch(IllegalArgumentException ignore) {}\n                try { query.between(null, columnKeys[i], date, date).find();                     fail(); } catch(IllegalArgumentException ignore) {}\n            }\n        }\n    }\n\n    @Test\n    public void maximumDate() {\n        final AtomicLong columnKey = new AtomicLong(-1);\n        Table table = TestHelper.createTable(sharedRealm, \"temp\", new TestHelper.AdditionalTableSetup() {\n            @Override\n            public void execute(Table table) {\n                columnKey.set(table.addColumn(RealmFieldType.DATE, \"date\"));\n\n                TestHelper.addRowWithValues(table, new long[]{columnKey.get()}, new Object[]{new Date(0)});\n                TestHelper.addRowWithValues(table, new long[]{columnKey.get()}, new Object[]{new Date(10000)});\n                TestHelper.addRowWithValues(table, new long[]{columnKey.get()}, new Object[]{new Date(1000)});\n            }\n        });\n\n        assertEquals(new Date(10000), table.where().maximumDate(columnKey.get()));\n    }\n\n    @Test\n    public void minimumDate() {\n        final AtomicLong columnKey = new AtomicLong(-1);\n        Table table = TestHelper.createTable(sharedRealm, \"temp\", new TestHelper.AdditionalTableSetup() {\n            @Override\n            public void execute(Table table) {\n                columnKey.set(table.addColumn(RealmFieldType.DATE, \"date\"));\n\n                TestHelper.addRowWithValues(table, new long[]{columnKey.get()}, new Object[]{new Date(10000)});\n                TestHelper.addRowWithValues(table, new long[]{columnKey.get()}, new Object[]{new Date(0)});\n                TestHelper.addRowWithValues(table, new long[]{columnKey.get()}, new Object[]{new Date(1000)});\n            }\n        });\n\n        assertEquals(new Date(0), table.where().minimumDate(columnKey.get()));\n    }\n\n    @Test\n    public void dateQuery() throws Exception {\n\n        final RealmAny past = RealmAny.valueOf(new Date(TimeUnit.SECONDS.toMillis(Integer.MIN_VALUE - 100L)));\n        final RealmAny future = RealmAny.valueOf(new Date(TimeUnit.SECONDS.toMillis(Integer.MAX_VALUE + 1L)));\n        final RealmAny distantPast = RealmAny.valueOf(new Date(Long.MIN_VALUE));\n        final RealmAny distantFuture = RealmAny.valueOf(new Date(Long.MAX_VALUE));\n        final RealmAny date0 = RealmAny.valueOf(new Date(0));\n        final RealmAny date10000 = RealmAny.valueOf(new Date(10000));\n\n        final AtomicLong columnKey = new AtomicLong(-1);\n\n        Table table = TestHelper.createTable(sharedRealm, \"temp\", new TestHelper.AdditionalTableSetup() {\n            @Override\n            public void execute(Table table) {\n                columnKey.set(table.addColumn(RealmFieldType.DATE, \"date\"));\n\n                TestHelper.addRowWithValues(table, new long[]{columnKey.get()}, new Object[]{new Date(10000)});\n                TestHelper.addRowWithValues(table, new long[]{columnKey.get()}, new Object[]{new Date(0)});\n                TestHelper.addRowWithValues(table, new long[]{columnKey.get()}, new Object[]{new Date(1000)});\n                TestHelper.addRowWithValues(table, new long[]{columnKey.get()}, new Object[]{future.asDate()});\n                TestHelper.addRowWithValues(table, new long[]{columnKey.get()}, new Object[]{distantFuture.asDate()});\n                TestHelper.addRowWithValues(table, new long[]{columnKey.get()}, new Object[]{past.asDate()});\n                TestHelper.addRowWithValues(table, new long[]{columnKey.get()}, new Object[]{distantPast.asDate()});\n            }\n        });\n\n        assertEquals(1L, table.where().equalTo(null, \"date\", distantPast).count());\n        assertEquals(6L, table.where().notEqualTo(null, \"date\", distantPast).count());\n        assertEquals(0L, table.where().lessThan(null, \"date\", distantPast).count());\n        assertEquals(1L, table.where().lessThanOrEqual(null, \"date\", distantPast).count());\n        assertEquals(6L, table.where().greaterThan(null, \"date\", distantPast).count());\n        assertEquals(7L, table.where().greaterThanOrEqual(null, \"date\", distantPast).count());\n\n        assertEquals(1L, table.where().equalTo(null, \"date\", past).count());\n        assertEquals(6L, table.where().notEqualTo(null, \"date\", past).count());\n        assertEquals(1L, table.where().lessThan(null, \"date\", past).count());\n        assertEquals(2L, table.where().lessThanOrEqual(null, \"date\", past).count());\n        assertEquals(5L, table.where().greaterThan(null, \"date\", past).count());\n        assertEquals(6L, table.where().greaterThanOrEqual(null, \"date\", past).count());\n\n        assertEquals(1L, table.where().equalTo(null, \"date\", date0).count());\n        assertEquals(6L, table.where().notEqualTo(null, \"date\", date0).count());\n        assertEquals(2L, table.where().lessThan(null, \"date\", date0).count());\n        assertEquals(3L, table.where().lessThanOrEqual(null, \"date\", date0).count());\n        assertEquals(4L, table.where().greaterThan(null, \"date\", date0).count());\n        assertEquals(5L, table.where().greaterThanOrEqual(null, \"date\", date0).count());\n\n        assertEquals(1L, table.where().equalTo(null, \"date\", future).count());\n        assertEquals(6L, table.where().notEqualTo(null, \"date\", future).count());\n        assertEquals(5L, table.where().lessThan(null, \"date\", future).count());\n        assertEquals(6L, table.where().lessThanOrEqual(null, \"date\", future).count());\n        assertEquals(1L, table.where().greaterThan(null, \"date\", future).count());\n        assertEquals(2L, table.where().greaterThanOrEqual(null, \"date\", future).count());\n\n        assertEquals(1L, table.where().equalTo(null, \"date\", distantFuture).count());\n        assertEquals(6L, table.where().notEqualTo(null, \"date\", distantFuture).count());\n        assertEquals(6L, table.where().lessThan(null, \"date\", distantFuture).count());\n        assertEquals(7L, table.where().lessThanOrEqual(null, \"date\", distantFuture).count());\n        assertEquals(0L, table.where().greaterThan(null, \"date\", distantFuture).count());\n        assertEquals(1L, table.where().greaterThanOrEqual(null, \"date\", distantFuture).count());\n\n        // between\n\n        assertEquals(1L, table.where().between(null, \"date\", distantPast, distantPast).count());\n        assertEquals(2L, table.where().between(null, \"date\", distantPast, past).count());\n        assertEquals(3L, table.where().between(null, \"date\", distantPast, date0).count());\n        assertEquals(5L, table.where().between(null, \"date\", distantPast, date10000).count());\n        assertEquals(6L, table.where().between(null, \"date\", distantPast, future).count());\n        assertEquals(7L, table.where().between(null, \"date\", distantPast, distantFuture).count());\n\n        assertEquals(0L, table.where().between(null, \"date\", past, distantPast).count());\n        assertEquals(1L, table.where().between(null, \"date\", past, past).count());\n        assertEquals(2L, table.where().between(null, \"date\", past, date0).count());\n        assertEquals(4L, table.where().between(null, \"date\", past, date10000).count());\n        assertEquals(5L, table.where().between(null, \"date\", past, future).count());\n        assertEquals(6L, table.where().between(null, \"date\", past, distantFuture).count());\n\n        assertEquals(0L, table.where().between(null, \"date\", date0, distantPast).count());\n        assertEquals(0L, table.where().between(null, \"date\", date0, past).count());\n        assertEquals(1L, table.where().between(null, \"date\", date0, date0).count());\n        assertEquals(3L, table.where().between(null, \"date\", date0, date10000).count());\n        assertEquals(4L, table.where().between(null, \"date\", date0, future).count());\n        assertEquals(5L, table.where().between(null, \"date\", date0, distantFuture).count());\n\n        assertEquals(0L, table.where().between(null, \"date\", date10000, distantPast).count());\n        assertEquals(0L, table.where().between(null, \"date\", date10000, past).count());\n        assertEquals(0L, table.where().between(null, \"date\", date10000, date0).count());\n        assertEquals(1L, table.where().between(null, \"date\", date10000, date10000).count());\n        assertEquals(2L, table.where().between(null, \"date\", date10000, future).count());\n        assertEquals(3L, table.where().between(null, \"date\", date10000, distantFuture).count());\n\n        assertEquals(0L, table.where().between(null, \"date\", future, distantPast).count());\n        assertEquals(0L, table.where().between(null, \"date\", future, past).count());\n        assertEquals(0L, table.where().between(null, \"date\", future, date0).count());\n        assertEquals(0L, table.where().between(null, \"date\", future, date10000).count());\n        assertEquals(1L, table.where().between(null, \"date\", future, future).count());\n        assertEquals(2L, table.where().between(null, \"date\", future, distantFuture).count());\n\n        assertEquals(0L, table.where().between(null, \"date\", distantFuture, distantPast).count());\n        assertEquals(0L, table.where().between(null, \"date\", distantFuture, past).count());\n        assertEquals(0L, table.where().between(null, \"date\", distantFuture, date0).count());\n        assertEquals(0L, table.where().between(null, \"date\", distantFuture, date10000).count());\n        assertEquals(0L, table.where().between(null, \"date\", distantFuture, future).count());\n        assertEquals(1L, table.where().between(null, \"date\", distantFuture, distantFuture).count());\n    }\n\n    @Test\n    public void byteArrayQuery() throws Exception {\n\n        final RealmAny binary1 = RealmAny.valueOf(new byte[] {0x01, 0x02, 0x03, 0x04});\n        final RealmAny binary2 = RealmAny.valueOf(new byte[] {0x05, 0x02, 0x03, 0x08});\n        final RealmAny binary3 = RealmAny.valueOf(new byte[] {0x09, 0x0a, 0x0b, 0x04});\n        final RealmAny binary4 = RealmAny.valueOf(new byte[] {0x05, 0x0a, 0x0b, 0x10});\n\n        final AtomicLong columnKey = new AtomicLong(-1);\n\n        Table table = TestHelper.createTable(sharedRealm, \"temp\", new TestHelper.AdditionalTableSetup() {\n            @Override\n            public void execute(Table table) {\n                columnKey.set(table.addColumn(RealmFieldType.BINARY, \"binary\"));\n\n                TestHelper.addRowWithValues(table, new long[]{columnKey.get()}, new Object[]{(Object) binary1.asBinary()});\n                TestHelper.addRowWithValues(table, new long[]{columnKey.get()}, new Object[]{(Object) binary2.asBinary()});\n                TestHelper.addRowWithValues(table, new long[]{columnKey.get()}, new Object[]{(Object) binary3.asBinary()});\n                TestHelper.addRowWithValues(table, new long[]{columnKey.get()}, new Object[]{(Object) binary4.asBinary()});\n            }\n        });\n\n        // Equal to\n\n        assertEquals(1L, table.where().equalTo(null, \"binary\", binary1).count());\n        assertEquals(1L, table.where().equalTo(null, \"binary\", binary3).count());\n\n        // Not equal to\n\n        assertEquals(3L, table.where().notEqualTo(null, \"binary\", binary2).count());\n        assertEquals(3L, table.where().notEqualTo(null, \"binary\", binary4).count());\n    }\n\n    @Test\n    public void decimal128Query() throws Exception {\n        final RealmAny one = RealmAny.valueOf(new Decimal128(1));\n        final RealmAny two = RealmAny.valueOf(new Decimal128(2));\n        final RealmAny three = RealmAny.valueOf(new Decimal128(3));\n\n        final AtomicLong columnKey = new AtomicLong(-1);\n\n        Table table = TestHelper.createTable(sharedRealm, \"temp\", new TestHelper.AdditionalTableSetup() {\n            @Override\n            public void execute(Table table) {\n                columnKey.set(table.addColumn(RealmFieldType.DECIMAL128, \"decimal128\"));\n\n                TestHelper.addRowWithValues(table, new long[]{columnKey.get()}, new Object[]{one.asDecimal128()});\n                TestHelper.addRowWithValues(table, new long[]{columnKey.get()}, new Object[]{two.asDecimal128()});\n                TestHelper.addRowWithValues(table, new long[]{columnKey.get()}, new Object[]{three.asDecimal128()});\n            }\n        });\n\n        assertEquals(1L, table.where().equalTo(null, \"decimal128\", one).count());\n        assertEquals(2L, table.where().notEqualTo(null, \"decimal128\", one).count());\n        assertEquals(0L, table.where().lessThan(null, \"decimal128\", one).count());\n        assertEquals(1L, table.where().lessThanOrEqual(null, \"decimal128\", one).count());\n        assertEquals(2L, table.where().greaterThan(null, \"decimal128\", one).count());\n        assertEquals(3L, table.where().greaterThanOrEqual(null, \"decimal128\", one).count());\n\n        assertEquals(1L, table.where().equalTo(null, \"decimal128\", two).count());\n        assertEquals(2L, table.where().notEqualTo(null, \"decimal128\", two).count());\n        assertEquals(1L, table.where().lessThan(null, \"decimal128\", two).count());\n        assertEquals(2L, table.where().lessThanOrEqual(null, \"decimal128\", two).count());\n        assertEquals(1L, table.where().greaterThan(null, \"decimal128\", two).count());\n        assertEquals(2L, table.where().greaterThanOrEqual(null, \"decimal128\", two).count());\n\n        assertEquals(1L, table.where().equalTo(null, \"decimal128\", three).count());\n        assertEquals(2L, table.where().notEqualTo(null, \"decimal128\", three).count());\n        assertEquals(2L, table.where().lessThan(null, \"decimal128\", three).count());\n        assertEquals(3L, table.where().lessThanOrEqual(null, \"decimal128\", three).count());\n        assertEquals(0L, table.where().greaterThan(null, \"decimal128\", three).count());\n        assertEquals(1L, table.where().greaterThanOrEqual(null, \"decimal128\", three).count());\n    }\n\n    @Test\n    public void objectIdQuery() throws Exception {\n        final RealmAny one = RealmAny.valueOf(new ObjectId(new Date(10)));\n        final RealmAny two = RealmAny.valueOf(new ObjectId(new Date(20)));\n        final RealmAny three = RealmAny.valueOf(new ObjectId(new Date(30)));\n\n        final AtomicLong columnKey = new AtomicLong(-1);\n\n        Table table = TestHelper.createTable(sharedRealm, \"temp\", new TestHelper.AdditionalTableSetup() {\n            @Override\n            public void execute(Table table) {\n                columnKey.set(table.addColumn(RealmFieldType.OBJECT_ID, \"objectid\"));\n\n                TestHelper.addRowWithValues(table, new long[]{columnKey.get()}, new Object[]{one.asObjectId()});\n                TestHelper.addRowWithValues(table, new long[]{columnKey.get()}, new Object[]{two.asObjectId()});\n                TestHelper.addRowWithValues(table, new long[]{columnKey.get()}, new Object[]{three.asObjectId()});\n            }\n        });\n\n        assertEquals(1L, table.where().equalTo(null, \"objectid\", one).count());\n        assertEquals(2L, table.where().notEqualTo(null, \"objectid\", one).count());\n        assertEquals(0L, table.where().lessThan(null, \"objectid\", one).count());\n        assertEquals(1L, table.where().lessThanOrEqual(null, \"objectid\", one).count());\n        assertEquals(2L, table.where().greaterThan(null, \"objectid\", one).count());\n        assertEquals(3L, table.where().greaterThanOrEqual(null, \"objectid\", one).count());\n\n        assertEquals(1L, table.where().equalTo(null, \"objectid\", two).count());\n        assertEquals(2L, table.where().notEqualTo(null, \"objectid\", two).count());\n        assertEquals(1L, table.where().lessThan(null, \"objectid\", two).count());\n        assertEquals(2L, table.where().lessThanOrEqual(null, \"objectid\", two).count());\n        assertEquals(1L, table.where().greaterThan(null, \"objectid\", two).count());\n        assertEquals(2L, table.where().greaterThanOrEqual(null, \"objectid\", two).count());\n\n        assertEquals(1L, table.where().equalTo(null, \"objectid\", three).count());\n        assertEquals(2L, table.where().notEqualTo(null, \"objectid\", three).count());\n        assertEquals(2L, table.where().lessThan(null, \"objectid\", three).count());\n        assertEquals(3L, table.where().lessThanOrEqual(null, \"objectid\", three).count());\n        assertEquals(0L, table.where().greaterThan(null, \"objectid\", three).count());\n        assertEquals(1L, table.where().greaterThanOrEqual(null, \"objectid\", three).count());\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/internal/JNIRowTest.java",
    "content": "/*\n * Copyright 2015 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\npackage io.realm.internal;\n\nimport androidx.test.platform.app.InstrumentationRegistry;\nimport androidx.test.ext.junit.runners.AndroidJUnit4;\n\nimport org.bson.types.Decimal128;\nimport org.bson.types.ObjectId;\nimport org.junit.After;\nimport org.junit.Before;\nimport org.junit.Rule;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\n\nimport java.util.Date;\nimport java.util.concurrent.atomic.AtomicLong;\n\nimport io.realm.Realm;\nimport io.realm.RealmConfiguration;\nimport io.realm.RealmFieldType;\nimport io.realm.TestHelper;\nimport io.realm.TestRealmConfigurationFactory;\n\nimport static junit.framework.Assert.assertFalse;\nimport static junit.framework.Assert.assertNull;\nimport static junit.framework.Assert.assertTrue;\nimport static org.junit.Assert.assertArrayEquals;\nimport static org.junit.Assert.assertEquals;\n\n@RunWith(AndroidJUnit4.class)\npublic class JNIRowTest {\n\n    @Rule\n    public final TestRealmConfigurationFactory configFactory = new TestRealmConfigurationFactory();\n\n    @SuppressWarnings(\"FieldCanBeLocal\")\n    private RealmConfiguration config;\n    private OsSharedRealm sharedRealm;\n\n    @Before\n    public void setUp() throws Exception {\n        Realm.init(InstrumentationRegistry.getInstrumentation().getContext());\n        config = configFactory.createConfiguration();\n        sharedRealm = OsSharedRealm.getInstance(config, OsSharedRealm.VersionID.LIVE);\n\n        sharedRealm.beginTransaction();\n    }\n\n    @After\n    public void tearDown() {\n        if (sharedRealm != null && sharedRealm.isInTransaction()) {\n            sharedRealm.cancelTransaction();\n        }\n\n        if (sharedRealm != null && !sharedRealm.isClosed()) {\n            sharedRealm.close();\n        }\n    }\n\n    @Test\n    public void nonNullValues() {\n        final byte[] data = new byte[2];\n\n        final AtomicLong colKey1 = new AtomicLong(-1);\n        final AtomicLong colKey2 = new AtomicLong(-1);\n        final AtomicLong colKey3 = new AtomicLong(-1);\n        final AtomicLong colKey4 = new AtomicLong(-1);\n        final AtomicLong colKey5 = new AtomicLong(-1);\n        final AtomicLong colKey6 = new AtomicLong(-1);\n        final AtomicLong colKey7 = new AtomicLong(-1);\n        final AtomicLong colKey8 = new AtomicLong(-1);\n        final AtomicLong colKey9 = new AtomicLong(-1);\n\n        Table table = TestHelper.createTable(sharedRealm, \"temp\", new TestHelper.AdditionalTableSetup() {\n            @Override\n            public void execute(Table table) {\n                colKey1.set(table.addColumn(RealmFieldType.STRING, \"string\"));\n                colKey2.set(table.addColumn(RealmFieldType.INTEGER, \"integer\"));\n                colKey3.set(table.addColumn(RealmFieldType.FLOAT, \"float\"));\n                colKey4.set(table.addColumn(RealmFieldType.DOUBLE, \"double\"));\n                colKey5.set(table.addColumn(RealmFieldType.BOOLEAN, \"boolean\"));\n                colKey6.set(table.addColumn(RealmFieldType.DATE, \"date\"));\n                colKey7.set(table.addColumn(RealmFieldType.BINARY, \"binary\"));\n                colKey8.set(table.addColumn(RealmFieldType.DECIMAL128, \"decimal128\"));\n                colKey9.set(table.addColumn(RealmFieldType.OBJECT_ID, \"object_id\"));\n\n                TestHelper.addRowWithValues(table,\n                        new long[]{colKey1.get(), colKey2.get(), colKey3.get(), colKey4.get(), colKey5.get(), colKey6.get(), colKey7.get(), colKey8.get(), colKey9.get()},\n                        new Object[]{\"abc\", 3, (float) 1.2, 1.3, true, new Date(0), data, new Decimal128(1), new ObjectId(TestHelper.generateObjectIdHexString(1))}\n                );\n            }\n        });\n\n        UncheckedRow row = table.getUncheckedRow(0);\n\n        assertEquals(\"abc\", row.getString(colKey1.get()));\n        assertEquals(3, row.getLong(colKey2.get()));\n        assertEquals(1.2F, row.getFloat(colKey3.get()), Float.MIN_NORMAL);\n        assertEquals(1.3, row.getDouble(colKey4.get()), Double.MIN_NORMAL);\n        assertEquals(true, row.getBoolean(colKey5.get()));\n        assertEquals(new Date(0), row.getDate(colKey6.get()));\n        assertArrayEquals(data, row.getBinaryByteArray(colKey7.get()));\n        assertEquals(new Decimal128(1), row.getDecimal128(colKey8.get()));\n        assertEquals(new ObjectId(TestHelper.generateObjectIdHexString(1)), row.getObjectId(colKey9.get()));\n\n        row.setString(colKey1.get(), \"a\");\n        row.setLong(colKey2.get(), 1);\n        row.setFloat(colKey3.get(), (float) 8.8);\n        row.setDouble(colKey4.get(), 9.9);\n        row.setBoolean(colKey5.get(), false);\n        row.setDate(colKey6.get(), new Date(10000));\n        row.setDecimal128(colKey8.get(), new Decimal128(2));\n        row.setObjectId(colKey9.get(), new ObjectId(TestHelper.generateObjectIdHexString(2)));\n\n        byte[] newData = new byte[3];\n        row.setBinaryByteArray(colKey7.get(), newData);\n\n        assertEquals(\"a\", row.getString(colKey1.get()));\n        assertEquals(1, row.getLong(colKey2.get()));\n        assertEquals(8.8F, row.getFloat(colKey3.get()), Float.MIN_NORMAL);\n        assertEquals(9.9, row.getDouble(colKey4.get()), Double.MIN_NORMAL);\n        assertEquals(false, row.getBoolean(colKey5.get()));\n        assertEquals(new Date(10000), row.getDate(colKey6.get()));\n        assertArrayEquals(newData, row.getBinaryByteArray(colKey7.get()));\n        assertEquals(new Decimal128(2), row.getDecimal128(colKey8.get()));\n        assertEquals(new ObjectId(TestHelper.generateObjectIdHexString(2)), row.getObjectId(colKey9.get()));\n    }\n\n    @Test\n    public void nullValues() {\n        Table table = TestHelper.createTable(sharedRealm, \"temp\");\n        long colStringIndex = table.addColumn(RealmFieldType.STRING, \"string\", true);\n        long colIntIndex = table.addColumn(RealmFieldType.INTEGER, \"integer\", true);\n        table.addColumn(RealmFieldType.FLOAT, \"float\");\n        table.addColumn(RealmFieldType.DOUBLE, \"double\");\n        long colBoolIndex = table.addColumn(RealmFieldType.BOOLEAN, \"boolean\", true);\n        table.addColumn(RealmFieldType.DATE, \"date\");\n        table.addColumn(RealmFieldType.BINARY, \"binary\");\n        long colDecimalIndex = table.addColumn(RealmFieldType.DECIMAL128, \"decimal128\", true);\n        long colObjectIdIndex = table.addColumn(RealmFieldType.OBJECT_ID, \"object_id\", true);\n\n        long rowIndex = OsObject.createRow(table);\n\n        UncheckedRow row = table.getUncheckedRow(rowIndex);\n\n        row.setString(colStringIndex, \"test\");\n        assertEquals(\"test\", row.getString(colStringIndex));\n        row.setNull(colStringIndex);\n        assertNull(row.getString(colStringIndex));\n\n        row.setLong(colIntIndex, 1);\n        assertFalse(row.isNull(colIntIndex));\n        row.setNull(colIntIndex);\n        assertTrue(row.isNull(colIntIndex));\n\n        row.setBoolean(colBoolIndex, true);\n        assertFalse(row.isNull(colBoolIndex));\n        row.setNull(colBoolIndex);\n        assertTrue(row.isNull(colBoolIndex));\n\n        row.setDecimal128(colDecimalIndex, new Decimal128(0));\n        assertFalse(row.isNull(colDecimalIndex));\n        row.setNull(colDecimalIndex);\n        assertTrue(row.isNull(colDecimalIndex));\n\n        row.setObjectId(colObjectIdIndex, new ObjectId());\n        assertFalse(row.isNull(colObjectIdIndex));\n        row.setNull(colObjectIdIndex);\n        assertTrue(row.isNull(colObjectIdIndex));\n    }\n\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/internal/JNITableInsertTest.java",
    "content": "/*\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\npackage io.realm.internal;\n\nimport androidx.test.platform.app.InstrumentationRegistry;\n\nimport org.bson.types.Decimal128;\nimport org.bson.types.ObjectId;\nimport org.junit.After;\nimport org.junit.Before;\nimport org.junit.Rule;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.junit.runners.Parameterized;\n\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.Collection;\nimport java.util.Date;\nimport java.util.List;\n\nimport io.realm.Realm;\nimport io.realm.RealmConfiguration;\nimport io.realm.TestHelper;\nimport io.realm.TestRealmConfigurationFactory;\n\nimport static org.junit.Assert.assertTrue;\nimport static org.junit.Assert.fail;\n\n\n@RunWith(Parameterized.class)\npublic class JNITableInsertTest {\n\n    @Rule\n    public final TestRealmConfigurationFactory configFactory = new TestRealmConfigurationFactory();\n\n    @SuppressWarnings(\"FieldCanBeLocal\")\n    private RealmConfiguration config;\n    private OsSharedRealm sharedRealm;\n\n    private List<Object> value = new ArrayList<>();\n\n    @Before\n    public void setUp() throws Exception {\n        Realm.init(InstrumentationRegistry.getInstrumentation().getContext());\n        config = configFactory.createConfiguration();\n        sharedRealm = OsSharedRealm.getInstance(config, OsSharedRealm.VersionID.LIVE);\n    }\n\n    @After\n    public void tearDown() {\n        if (sharedRealm != null && !sharedRealm.isClosed()) {\n            sharedRealm.close();\n        }\n    }\n\n    @Parameterized.Parameters\n    public static Collection<Object[]> parameters() {\n        List<Object> value = new ArrayList<>();\n        value.add(0, true);\n        value.add(1, \"abc\");\n        value.add(2, 123L);\n        value.add(3, 987.123f);\n        value.add(4, 1234567.898d);\n        value.add(5, new Date(645342));\n        value.add(6, new byte[]{1, 2, 3, 4, 5});\n        value.add(7, new Decimal128(1));\n        value.add(8, new ObjectId());\n        return Arrays.asList(\n                new Object[]{value},\n                new Object[]{value}\n        );\n    }\n\n    public JNITableInsertTest(List<Object> value) {\n        this.value = value;\n    }\n\n    @Test\n    public void testGenericAddOnTable() {\n        for (int i = 0; i < value.size(); i++) {\n            for (int j = 0; j < value.size(); j++) {\n                final Object valueI = value.get(i);\n                final Object valueJ = value.get(j);\n\n                TestHelper.createTable(sharedRealm, \"temp\" + i + \"_\" + j, new TestHelper.AdditionalTableSetup() {\n                    @Override\n                    public void execute(Table t) {\n                        // If the objects matches no exception will be thrown.\n                        if (valueI.getClass().equals(valueJ.getClass())) {\n                            assertTrue(true);\n                        } else {\n                            // Adds column.\n                            long colKey = t.addColumn(TestHelper.getColumnType(valueJ), valueJ.getClass().getSimpleName());\n                            // Adds value.\n                            try {\n                                TestHelper.addRowWithValues(t, new long[]{colKey}, new Object[]{valueI});\n                                fail(\"No matching type\");\n                            } catch (IllegalArgumentException ignored) {\n                            }\n                        }\n                    }\n                });\n            }\n        }\n    }\n\n}\n\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/internal/JNITableTest.java",
    "content": "/*\n * Copyright 2015 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\npackage io.realm.internal;\n\nimport androidx.test.ext.junit.runners.AndroidJUnit4;\n\nimport org.bson.types.Decimal128;\nimport org.bson.types.ObjectId;\nimport org.junit.After;\nimport org.junit.Before;\nimport org.junit.Rule;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\n\nimport java.util.Arrays;\nimport java.util.Date;\nimport java.util.Locale;\nimport java.util.concurrent.atomic.AtomicLong;\n\nimport io.realm.RealmConfiguration;\nimport io.realm.RealmFieldType;\nimport io.realm.TestHelper;\nimport io.realm.TestRealmConfigurationFactory;\n\nimport static junit.framework.Assert.assertEquals;\nimport static junit.framework.Assert.assertFalse;\nimport static junit.framework.Assert.assertTrue;\nimport static junit.framework.Assert.fail;\n\n\n@RunWith(AndroidJUnit4.class)\npublic class JNITableTest {\n    @Rule\n    public final TestRealmConfigurationFactory configFactory = new TestRealmConfigurationFactory();\n\n    @SuppressWarnings(\"FieldCanBeLocal\")\n    private RealmConfiguration config;\n    private OsSharedRealm sharedRealm;\n\n    @Before\n    public void setUp() {\n        config = configFactory.createConfiguration();\n        sharedRealm = OsSharedRealm.getInstance(config, OsSharedRealm.VersionID.LIVE);\n    }\n\n    @After\n    public void tearDown() {\n        if (sharedRealm != null)  {\n            sharedRealm.close();\n        }\n    }\n\n    @Test\n    public void tableToString() {\n        Table t = TestHelper.createTable(sharedRealm, \"temp\", new TestHelper.AdditionalTableSetup() {\n            @Override\n            public void execute(Table t) {\n                long colKey1 = t.addColumn(RealmFieldType.STRING, \"stringCol\");\n                long colKey2 = t.addColumn(RealmFieldType.INTEGER, \"intCol\");\n                long colKey3 = t.addColumn(RealmFieldType.BOOLEAN, \"boolCol\");\n\n                TestHelper.addRowWithValues(t, new long[]{colKey1, colKey2, colKey3}, new Object[]{\"s1\", 1, true});\n                TestHelper.addRowWithValues(t, new long[]{colKey1, colKey2, colKey3}, new Object[]{\"s2\", 2, false});\n            }\n        });\n\n        String expected = \"The Table temp contains 3 columns: stringCol, intCol, boolCol. And 2 rows.\";\n        assertEquals(expected, t.toString());\n    }\n\n    @Test\n    public void findFirstNonExisting() {\n        Table t = TestHelper.createTableWithAllColumnTypes(sharedRealm);\n        long colKey1 = t.getColumnKey(\"binary\");\n        long colKey2 = t.getColumnKey(\"boolean\");\n        long colKey3 = t.getColumnKey(\"date\");\n        long colKey4 = t.getColumnKey(\"double\");\n        long colKey5 = t.getColumnKey(\"float\");\n        long colKey6 = t.getColumnKey(\"long\");\n        long colKey7 = t.getColumnKey(\"string\");\n        long colKey8 = t.getColumnKey(\"decimal128\");\n        long colKey9 = t.getColumnKey(\"object_id\");\n\n        sharedRealm.beginTransaction();\n        TestHelper.addRowWithValues(t,\n                new long[]{colKey1, colKey2, colKey3, colKey4, colKey5, colKey6, colKey7, colKey8, colKey9},\n                new Object[] {new byte[] {1, 2, 3}, true, new Date(1384423149761L), 4.5D, 5.7F, 100, \"string\", new Decimal128(0), new ObjectId(TestHelper.generateObjectIdHexString(0))});\n        sharedRealm.commitTransaction();\n\n        assertEquals(-1, t.findFirstBoolean(colKey2, false));\n        assertEquals(-1, t.findFirstDate(colKey3, new Date(138442314986L)));\n        assertEquals(-1, t.findFirstDouble(colKey4, 1.0D));\n        assertEquals(-1, t.findFirstFloat(colKey5, 1.0F));\n        assertEquals(-1, t.findFirstLong(colKey6, 50));\n        assertEquals(-1, t.findFirstString(colKey7, \"anotherstring\"));\n        assertEquals(-1, t.findFirstDecimal128(colKey8, new Decimal128(1)));\n        assertEquals(-1, t.findFirstObjectId(colKey9, new ObjectId(TestHelper.generateObjectIdHexString(1))));\n    }\n\n    @Test\n    public void findFirst() {\n        final int TEST_SIZE = 10;\n        Table t = TestHelper.createTableWithAllColumnTypes(sharedRealm);\n        long colKey1 = t.getColumnKey(\"binary\");\n        long colKey2 = t.getColumnKey(\"boolean\");\n        long colKey3 = t.getColumnKey(\"date\");\n        long colKey4 = t.getColumnKey(\"double\");\n        long colKey5 = t.getColumnKey(\"float\");\n        long colKey6 = t.getColumnKey(\"long\");\n        long colKey7 = t.getColumnKey(\"string\");\n        long colKey8 = t.getColumnKey(\"decimal128\");\n        long colKey9 = t.getColumnKey(\"object_id\");\n\n        sharedRealm.beginTransaction();\n        for (int i = 0; i < TEST_SIZE; i++) {\n            TestHelper.addRowWithValues(t,\n                    new long[]{colKey1, colKey2, colKey3, colKey4, colKey5, colKey6, colKey7, colKey8, colKey9},\n                    new Object[] {new byte[] {1, 2, 3}, true, new Date(i), (double) i, (float) i, i, \"string \" + i, new Decimal128(i), new ObjectId(TestHelper.generateObjectIdHexString(i))});\n        }\n        TestHelper.addRowWithValues(t,\n                new long[]{colKey1, colKey2, colKey3, colKey4, colKey5, colKey6, colKey7, colKey8, colKey9},\n                new Object[] {new byte[] {1, 2, 3}, true, new Date(TEST_SIZE), (double) TEST_SIZE, (float) TEST_SIZE, TEST_SIZE, \"\", new Decimal128(TEST_SIZE), new ObjectId(TestHelper.generateObjectIdHexString(TEST_SIZE))});\n\n        sharedRealm.commitTransaction();\n\n        assertEquals(0, t.findFirstBoolean(colKey2, true));\n        for (int i = 0; i < TEST_SIZE; i++) {\n            assertEquals(i, t.findFirstDate(colKey3, new Date(i)));\n            assertEquals(i, t.findFirstDouble(colKey4, (double) i));\n            assertEquals(i, t.findFirstFloat(colKey5, (float) i));\n            assertEquals(i, t.findFirstLong(colKey6, i));\n            assertEquals(i, t.findFirstDecimal128(colKey8, new Decimal128(i)));\n            assertEquals(i, t.findFirstObjectId(colKey9, new ObjectId(TestHelper.generateObjectIdHexString(i))));\n        }\n\n        try {\n            t.findFirstString(colKey7, null);\n            fail();\n        } catch (IllegalArgumentException ignored) {}\n\n        try {\n            t.findFirstDate(colKey3, null);\n            fail();\n        } catch (IllegalArgumentException ignored) {}\n    }\n\n\n    @Test\n    public void getNonExistingColumn() {\n        Table t = TestHelper.createTable(sharedRealm, \"temp\", new TestHelper.AdditionalTableSetup() {\n            @Override\n            public void execute(Table t) {\n                t.addColumn(RealmFieldType.INTEGER, \"int\");\n            }\n        });\n\n        assertEquals(-1, t.getColumnKey(\"non-existing column\"));\n        try {\n            t.getColumnKey(null);\n            fail(\"column name null\");\n        } catch (IllegalArgumentException ignored) { }\n    }\n\n    @Test\n    public void setNulls() {\n        final AtomicLong colKey1 = new AtomicLong(-1);\n        final AtomicLong colKey2 = new AtomicLong(-1);\n        final AtomicLong colKey3 = new AtomicLong(-1);\n        final AtomicLong rowKey = new AtomicLong(-1);\n        Table t = TestHelper.createTable(sharedRealm, \"temp\", new TestHelper.AdditionalTableSetup() {\n            @Override\n            public void execute(Table t) {\n                colKey1.set(t.addColumn(RealmFieldType.STRING, \"col1\"));\n                colKey2.set(t.addColumn(RealmFieldType.DATE, \"col2\"));\n                colKey3.set(t.addColumn(RealmFieldType.BINARY, \"col3\"));\n                rowKey.set(TestHelper.addRowWithValues(t, new long[]{colKey1.get(), colKey2.get(), colKey3.get()},\n                        new Object[]{\"String val\", new Date(), new byte[] {1, 2, 3}}));\n            }\n        });\n\n        sharedRealm.beginTransaction();\n        try {\n            t.setString(colKey1.get(), rowKey.get(), null, false);\n            fail(\"null string not allowed\");\n        } catch (IllegalArgumentException ignored) { }\n        try {\n            t.setDate(colKey2.get(), rowKey.get(), null, false);\n            fail(\"null Date not allowed\");\n        } catch (IllegalArgumentException ignored) { }\n        sharedRealm.commitTransaction();\n    }\n\n    @Test\n    public void getName() {\n        String TABLE_NAME = \"tableName\";\n        //noinspection TryFinallyCanBeTryWithResources\n        try {\n\n            // Writes transaction must be run so we are sure a db exists with the correct table.\n            sharedRealm.beginTransaction();\n            sharedRealm.createTable(TABLE_NAME);\n            sharedRealm.commitTransaction();\n\n            Table table = sharedRealm.getTable(TABLE_NAME);\n            assertEquals(TABLE_NAME, table.getName());\n        } finally {\n            sharedRealm.close();\n        }\n    }\n\n    @Test\n    public void shouldThrowWhenSetIndexOnWrongRealmFieldType() {\n        Table t = TestHelper.createTableWithAllColumnTypes(sharedRealm);\n\n        long columnKey1 = t.getColumnKey(\"binary\");\n        long columnKey2 = t.getColumnKey(\"boolean\");\n        long columnKey3 = t.getColumnKey(\"date\");\n        long columnKey4 = t.getColumnKey(\"double\");\n        long columnKey5 = t.getColumnKey(\"float\");\n        long columnKey6 = t.getColumnKey(\"long\");\n        long columnKey7 = t.getColumnKey(\"string\");\n\n        long[] columnsKeys = new long[]{columnKey1, columnKey2, columnKey3, columnKey4, columnKey5, columnKey6, columnKey7};\n\n        for (int i = 0; i < columnsKeys.length; i++) {\n\n            // All types supported addSearchIndex and removeSearchIndex.\n            boolean exceptionExpected = (\n                    t.getColumnType(columnsKeys[i]) != RealmFieldType.STRING &&\n                            t.getColumnType(columnsKeys[i]) != RealmFieldType.INTEGER &&\n                            t.getColumnType(columnsKeys[i]) != RealmFieldType.BOOLEAN &&\n                            t.getColumnType(columnsKeys[i]) != RealmFieldType.DATE);\n\n            // Tries to addSearchIndex().\n            sharedRealm.beginTransaction();\n            try {\n                t.addSearchIndex(columnsKeys[i]);\n                if (exceptionExpected) {\n                    fail(\"Expected exception for colIndex \" + columnsKeys[i]);\n                }\n            } catch (IllegalArgumentException ignored) {\n            }\n            sharedRealm.commitTransaction();\n\n            // Tries to removeSearchIndex().\n            sharedRealm.beginTransaction();\n            try {\n                // Currently core will do nothing if the column doesn't have a search index.\n                t.removeSearchIndex(columnsKeys[i]);\n                if (exceptionExpected) {\n                    fail(\"Expected exception for colIndex \" + columnsKeys[i]);\n                }\n            } catch (IllegalArgumentException ignored) {\n            }\n            sharedRealm.commitTransaction();\n\n            // Tries to hasSearchIndex() for all columnTypes.\n            t.hasSearchIndex(columnsKeys[i]);\n        }\n    }\n\n    @Test\n    public void columnName() {\n        TestHelper.createTable(sharedRealm, \"temp\", new TestHelper.AdditionalTableSetup() {\n            @Override\n            public void execute(Table t) {\n                try {\n                    t.addColumn(RealmFieldType.STRING, \"I am 64 characters..............................................\");\n                    fail(\"Only 63 characters supported\");\n                } catch (IllegalArgumentException ignored) { }\n                t.addColumn(RealmFieldType.STRING, \"I am 63 characters.............................................\");\n            }\n        });\n    }\n\n    @Test\n    public void tableNumbers() {\n        final AtomicLong colKey1 = new AtomicLong(-1);\n        final AtomicLong colKey2 = new AtomicLong(-1);\n        final AtomicLong colKey3 = new AtomicLong(-1);\n        final AtomicLong colKey4 = new AtomicLong(-1);\n\n        final AtomicLong rowKey0 = new AtomicLong(-1);\n        final AtomicLong rowKey1 = new AtomicLong(-1);\n        final AtomicLong rowKey2 = new AtomicLong(-1);\n        final AtomicLong rowKey3 = new AtomicLong(-1);\n        final AtomicLong rowKey4 = new AtomicLong(-1);\n        final AtomicLong rowKey5 = new AtomicLong(-1);\n        final AtomicLong rowKey6 = new AtomicLong(-1);\n        Table t = TestHelper.createTable(sharedRealm, \"temp\", new TestHelper.AdditionalTableSetup() {\n            @Override\n            public void execute(Table t) {\n                colKey1.set(t.addColumn(RealmFieldType.INTEGER, \"intCol\"));\n                colKey2.set(t.addColumn(RealmFieldType.DOUBLE, \"doubleCol\"));\n                colKey3.set(t.addColumn(RealmFieldType.FLOAT, \"floatCol\"));\n                colKey4.set(t.addColumn(RealmFieldType.STRING, \"StringCol\"));\n\n                // Adds 3 rows of data with same values in each column.\n                rowKey0.set(TestHelper.addRowWithValues(t, new long[]{colKey1.get(), colKey2.get(), colKey3.get(), colKey4.get()}, new Object[]{1, 2.0D, 3.0F, \"s1\"}));\n                rowKey1.set(TestHelper.addRowWithValues(t, new long[]{colKey1.get(), colKey2.get(), colKey3.get(), colKey4.get()}, new Object[]{1, 2.0D, 3.0F, \"s1\"}));\n                rowKey2.set(TestHelper.addRowWithValues(t, new long[]{colKey1.get(), colKey2.get(), colKey3.get(), colKey4.get()}, new Object[]{1, 2.0D, 3.0F, \"s1\"}));\n\n                // Adds other values.\n                rowKey3.set(TestHelper.addRowWithValues(t, new long[]{colKey1.get(), colKey2.get(), colKey3.get(), colKey4.get()}, new Object[]{10, 20.0D, 30.0F, \"s10\"}));\n                rowKey4.set(TestHelper.addRowWithValues(t, new long[]{colKey1.get(), colKey2.get(), colKey3.get(), colKey4.get()}, new Object[]{100, 200.0D, 300.0F, \"s100\"}));\n                rowKey5.set(TestHelper.addRowWithValues(t, new long[]{colKey1.get(), colKey2.get(), colKey3.get(), colKey4.get()}, new Object[]{1000, 2000.0D, 3000.0F, \"s1000\"}));\n            }\n        });\n\n        // Counts instances of values added in the first 3 rows.\n        assertEquals(3, t.count(colKey1.get(), 1));\n        assertEquals(3, t.count(colKey2.get(), 2.0D));\n        assertEquals(3, t.count(colKey3.get(), 3.0F));\n        assertEquals(3, t.count(colKey4.get(), \"s1\"));\n\n\n        assertEquals(3, t.findFirstDouble(colKey2.get(), 20.0D)); // Find rows index for first double value of 20.0 in column 1.\n        assertEquals(4, t.findFirstFloat(colKey3.get(), 300.0F)); // Find rows index for first float value of 300.0 in column 2.\n\n        // Sets double and float.\n        sharedRealm.beginTransaction();\n        t.setDouble(colKey2.get(), rowKey2.get(), -2.0D, false);\n        t.setFloat(colKey3.get(), rowKey2.get(), -3.0F, false);\n        sharedRealm.commitTransaction();\n\n        // Gets double tests.\n        assertEquals(-2.0D, t.getDouble(colKey2.get(), rowKey2.get()));\n        assertEquals(20.0D, t.getDouble(colKey2.get(), rowKey3.get()));\n        assertEquals(200.0D, t.getDouble(colKey2.get(), rowKey4.get()));\n        assertEquals(2000.0D, t.getDouble(colKey2.get(), rowKey5.get()));\n\n        // Gets float test.\n        assertEquals(-3.0F, t.getFloat(colKey3.get(), rowKey2.get()));\n        assertEquals(30.0F, t.getFloat(colKey3.get(), rowKey3.get()));\n        assertEquals(300.0F, t.getFloat(colKey3.get(), rowKey4.get()));\n        assertEquals(3000.0F, t.getFloat(colKey3.get(), rowKey5.get()));\n    }\n\n    // Adds column and read back if it is nullable or not.\n    @Test\n    public void isNullable() {\n        final AtomicLong columnKey0 = new AtomicLong(-1);\n        final AtomicLong columnKey1 = new AtomicLong(-1);\n        Table table = TestHelper.createTable(sharedRealm, \"temp\", new TestHelper.AdditionalTableSetup() {\n            @Override\n            public void execute(Table table) {\n                columnKey0.set(table.addColumn(RealmFieldType.STRING, \"string1\", Table.NOT_NULLABLE));\n                columnKey1.set(table.addColumn(RealmFieldType.STRING, \"string2\", Table.NULLABLE));\n            }\n        });\n\n        assertFalse(table.isColumnNullable(columnKey0.get()));\n        assertTrue(table.isColumnNullable(columnKey1.get()));\n    }\n\n    @Test\n    public void defaultValue_setAndGet() {\n        final OsSharedRealm sharedRealm = OsSharedRealm.getInstance(configFactory.createConfiguration(), OsSharedRealm.VersionID.LIVE);\n        //noinspection TryFinallyCanBeTryWithResources\n        try {\n            sharedRealm.beginTransaction();\n            final Table table = sharedRealm.createTable(Table.getTableNameForClass(\"DefaultValueTest\"));\n            long colKey1 = table.addColumn(RealmFieldType.STRING, RealmFieldType.STRING.name().toLowerCase(Locale.ENGLISH) + \"Col\");\n            long colKey2 = table.addColumn(RealmFieldType.INTEGER, RealmFieldType.INTEGER.name().toLowerCase(Locale.ENGLISH) + \"Col\");\n            long colKey3 = table.addColumn(RealmFieldType.BOOLEAN, RealmFieldType.BOOLEAN.name().toLowerCase(Locale.ENGLISH) + \"Col\");\n            long colKey4 = table.addColumn(RealmFieldType.BINARY, RealmFieldType.BINARY.name().toLowerCase(Locale.ENGLISH) + \"Col\");\n            long colKey5 = table.addColumn(RealmFieldType.DATE, RealmFieldType.DATE.name().toLowerCase(Locale.ENGLISH) + \"Col\");\n            long colKey6 = table.addColumn(RealmFieldType.FLOAT, RealmFieldType.FLOAT.name().toLowerCase(Locale.ENGLISH) + \"Col\");\n            long colKey7 = table.addColumn(RealmFieldType.DOUBLE, RealmFieldType.DOUBLE.name().toLowerCase(Locale.ENGLISH) + \"Col\");\n            long colKey8 = table.addColumnLink(RealmFieldType.OBJECT, RealmFieldType.OBJECT.name().toLowerCase(Locale.ENGLISH) + \"Col\", table);\n\n            long[] columnKeys = new long[]{colKey1, colKey2, colKey3, colKey4, colKey5, colKey6, colKey7, colKey8};\n            Object[] datas = new Object[]{\"string value\",\n                    100L,\n                    true,\n                    new byte[]{123},\n                    new Date(123456),\n                    1.234F,\n                    Math.PI,\n                    0L};\n\n            RealmFieldType[] types = new RealmFieldType[]{\n                    RealmFieldType.STRING,\n                    RealmFieldType.INTEGER,\n                    RealmFieldType.BOOLEAN,\n                    RealmFieldType.BINARY,\n                    RealmFieldType.DATE,\n                    RealmFieldType.FLOAT,\n                    RealmFieldType.DOUBLE,\n                    RealmFieldType.OBJECT\n            };\n\n            long rowKey = OsObject.createRow(table);\n\n            for (int i = 0; i < columnKeys.length; i++) {\n                final RealmFieldType type = types[i];\n                final Object value = datas[i];\n\n                switch (type) {\n                    case STRING:\n                        table.setString(columnKeys[i], rowKey, (String) value, true);\n                        assertEquals(value, table.getString(columnKeys[i], rowKey));\n                        break;\n                    case INTEGER:\n                        table.setLong(columnKeys[i], rowKey, (long) value, true);\n                        assertEquals(value, table.getLong(columnKeys[i], rowKey));\n                        break;\n                    case BOOLEAN:\n                        table.setBoolean(columnKeys[i], rowKey, (boolean) value, true);\n                        assertEquals(value, table.getBoolean(columnKeys[i], rowKey));\n                        break;\n                    case BINARY:\n                        table.setBinaryByteArray(columnKeys[i], rowKey, (byte[]) value, true);\n                        assertTrue(Arrays.equals((byte[]) value, table.getBinaryByteArray(columnKeys[i], rowKey)));\n                        break;\n                    case DATE:\n                        table.setDate(columnKeys[i], rowKey, (Date) value, true);\n                        assertEquals(value, table.getDate(columnKeys[i], rowKey));\n                        break;\n                    case FLOAT:\n                        table.setFloat(columnKeys[i], rowKey, (float) value, true);\n                        assertEquals(value, table.getFloat(columnKeys[i], rowKey));\n                        break;\n                    case DOUBLE:\n                        table.setDouble(columnKeys[i], rowKey, (double) value, true);\n                        assertEquals(value, table.getDouble(columnKeys[i], rowKey));\n                        break;\n                    case OBJECT:\n                        table.setLink(columnKeys[i], rowKey, (long) value, true);\n                        assertEquals(value, table.getLink(columnKeys[i], rowKey));\n                        break;\n                    default:\n                        throw new RuntimeException(\"unexpected field type: \" + type);\n                }\n            }\n            sharedRealm.commitTransaction();\n\n            // Checks if the value can be read after committing transaction.\n            for (int i = 0; i < columnKeys.length; i++) {\n                final RealmFieldType type = types[i];\n                final Object value = datas[i];\n\n                switch (type) {\n                    case STRING:\n                        assertEquals(value, table.getString(columnKeys[i], rowKey));\n                        break;\n                    case INTEGER:\n                        assertEquals(value, table.getLong(columnKeys[i], rowKey));\n                        break;\n                    case BOOLEAN:\n                        assertEquals(value, table.getBoolean(columnKeys[i], rowKey));\n                        break;\n                    case BINARY:\n                        assertTrue(Arrays.equals((byte[]) value, table.getBinaryByteArray(columnKeys[i], rowKey)));\n                        break;\n                    case DATE:\n                        assertEquals(value, table.getDate(columnKeys[i], rowKey));\n                        break;\n                    case FLOAT:\n                        assertEquals(value, table.getFloat(columnKeys[i], rowKey));\n                        break;\n                    case DOUBLE:\n                        assertEquals(value, table.getDouble(columnKeys[i], rowKey));\n                        break;\n                    case OBJECT:\n                        assertEquals(value, table.getLink(columnKeys[i], rowKey));\n                        break;\n                    default:\n                        throw new RuntimeException(\"unexpected field type: \" + type);\n                }\n            }\n\n        } finally {\n            sharedRealm.close();\n        }\n    }\n\n    @Test\n    public void defaultValue_setMultipleTimes() {\n        final OsSharedRealm sharedRealm = OsSharedRealm.getInstance(configFactory.createConfiguration(), OsSharedRealm.VersionID.LIVE);\n        //noinspection TryFinallyCanBeTryWithResources\n        try {\n            sharedRealm.beginTransaction();\n            final Table table = sharedRealm.createTable(Table.getTableNameForClass(\"DefaultValueTest\"));\n            long colKey1 = table.addColumn(RealmFieldType.STRING, RealmFieldType.STRING.name().toLowerCase(Locale.ENGLISH) + \"Col\");\n            long colKey2 = table.addColumn(RealmFieldType.INTEGER, RealmFieldType.INTEGER.name().toLowerCase(Locale.ENGLISH) + \"Col\");\n            long colKey3 = table.addColumn(RealmFieldType.BOOLEAN, RealmFieldType.BOOLEAN.name().toLowerCase(Locale.ENGLISH) + \"Col\");\n            long colKey4 = table.addColumn(RealmFieldType.BINARY, RealmFieldType.BINARY.name().toLowerCase(Locale.ENGLISH) + \"Col\");\n            long colKey5 = table.addColumn(RealmFieldType.DATE, RealmFieldType.DATE.name().toLowerCase(Locale.ENGLISH) + \"Col\");\n            long colKey6 = table.addColumn(RealmFieldType.FLOAT, RealmFieldType.FLOAT.name().toLowerCase(Locale.ENGLISH) + \"Col\");\n            long colKey7 = table.addColumn(RealmFieldType.DOUBLE, RealmFieldType.DOUBLE.name().toLowerCase(Locale.ENGLISH) + \"Col\");\n            long colKey8 = table.addColumnLink(RealmFieldType.OBJECT, RealmFieldType.OBJECT.name().toLowerCase(Locale.ENGLISH) + \"Col\", table);\n\n\n            long[] columnKeys = new long[]{colKey1, colKey2, colKey3, colKey4, colKey5, colKey6, colKey7, colKey8};\n            Object[] datas = new Object[]{new String[] {\"string value1\", \"string value2\"},\n                    new Long[] {100L, 102L},\n                    new Boolean[] {false, true},\n                    new byte[][] {new byte[] {123}, new byte[] {-123}},\n                    new Date[] {new Date(123456), new Date(13579)},\n                    new Float[] {1.234F, 100F},\n                    new Double[] {Math.PI, Math.E},\n                    new Long[] {0L, 1L}\n\n            };\n            RealmFieldType[] types = new RealmFieldType[]{RealmFieldType.STRING,\n                    RealmFieldType.INTEGER,\n                    RealmFieldType.BOOLEAN,\n                    RealmFieldType.BINARY,\n                    RealmFieldType.DATE,\n                    RealmFieldType.FLOAT,\n                    RealmFieldType.DOUBLE,\n                    RealmFieldType.OBJECT};\n\n            long rowKey = OsObject.createRow(table);\n            OsObject.createRow(table); // For link field update.\n\n            for (int i = 0; i < columnKeys.length; i++) {\n                final RealmFieldType type = types[i];\n                final Object value1 = ((Object[]) datas[i])[0];\n                final Object value2 = ((Object[]) datas[i])[1];\n\n                switch (type) {\n                    case STRING:\n                        table.setString(columnKeys[i], rowKey, (String) value1, true);\n                        table.setString(columnKeys[i], rowKey, (String) value2, true);\n                        assertEquals(value2, table.getString(columnKeys[i], rowKey));\n                        break;\n                    case INTEGER:\n                        table.setLong(columnKeys[i], rowKey, (long) value1, true);\n                        table.setLong(columnKeys[i], rowKey, (long) value2, true);\n                        assertEquals(value2, table.getLong(columnKeys[i], rowKey));\n                        break;\n                    case BOOLEAN:\n                        table.setBoolean(columnKeys[i], rowKey, (boolean) value1, true);\n                        table.setBoolean(columnKeys[i], rowKey, (boolean) value2, true);\n                        assertEquals(value2, table.getBoolean(columnKeys[i], rowKey));\n                        break;\n                    case BINARY:\n                        table.setBinaryByteArray(columnKeys[i], rowKey, (byte[]) value1, true);\n                        table.setBinaryByteArray(columnKeys[i], rowKey, (byte[]) value2, true);\n                        assertTrue(Arrays.equals((byte[]) value2, table.getBinaryByteArray(columnKeys[i], rowKey)));\n                        break;\n                    case DATE:\n                        table.setDate(columnKeys[i], rowKey, (Date) value1, true);\n                        table.setDate(columnKeys[i], rowKey, (Date) value2, true);\n                        assertEquals(value2, table.getDate(columnKeys[i], rowKey));\n                        break;\n                    case FLOAT:\n                        table.setFloat(columnKeys[i], rowKey, (float) value1, true);\n                        table.setFloat(columnKeys[i], rowKey, (float) value2, true);\n                        assertEquals(value2, table.getFloat(columnKeys[i], rowKey));\n                        break;\n                    case DOUBLE:\n                        table.setDouble(columnKeys[i], rowKey, (double) value1, true);\n                        table.setDouble(columnKeys[i], rowKey, (double) value2, true);\n                        assertEquals(value2, table.getDouble(columnKeys[i], rowKey));\n                        break;\n                    case OBJECT:\n                        table.setLink(columnKeys[i], rowKey, (long) value1, true);\n                        table.setLink(columnKeys[i], rowKey, (long) value2, true);\n                        assertEquals(value2, table.getLink(columnKeys[i], rowKey));\n                        break;\n                    default:\n                        throw new RuntimeException(\"unexpected field type: \" + type);\n                }\n            }\n            sharedRealm.commitTransaction();\n\n            // Checks if the value can be read after committing transaction.\n            for (int i = 0; i < columnKeys.length; i++) {\n                final RealmFieldType type = types[i];\n                final Object value2 = ((Object[]) datas[i])[1];\n\n                switch (type) {\n                    case STRING:\n                        assertEquals(value2, table.getString(columnKeys[i], rowKey));\n                        break;\n                    case INTEGER:\n                        assertEquals(value2, table.getLong(columnKeys[i], rowKey));\n                        break;\n                    case BOOLEAN:\n                        assertEquals(value2, table.getBoolean(columnKeys[i], rowKey));\n                        break;\n                    case BINARY:\n                        assertTrue(Arrays.equals((byte[]) value2, table.getBinaryByteArray(columnKeys[i], rowKey)));\n                        break;\n                    case DATE:\n                        assertEquals(value2, table.getDate(columnKeys[i], rowKey));\n                        break;\n                    case FLOAT:\n                        assertEquals(value2, table.getFloat(columnKeys[i], rowKey));\n                        break;\n                    case DOUBLE:\n                        assertEquals(value2, table.getDouble(columnKeys[i], rowKey));\n                        break;\n                    case OBJECT:\n                        assertEquals(value2, table.getLink(columnKeys[i], rowKey));\n                        break;\n                    default:\n                        throw new RuntimeException(\"unexpected field type: \" + type);\n                }\n            }\n        } finally {\n            sharedRealm.close();\n        }\n    }\n\n    @Test\n    public void defaultValue_overwrittenByNonDefault() {\n        final OsSharedRealm sharedRealm = OsSharedRealm.getInstance(configFactory.createConfiguration(), OsSharedRealm.VersionID.LIVE);\n        //noinspection TryFinallyCanBeTryWithResources\n        try {\n            sharedRealm.beginTransaction();\n            final Table table = sharedRealm.createTable(Table.getTableNameForClass(\"DefaultValueTest\"));\n            long colKey1 = table.addColumn(RealmFieldType.STRING, RealmFieldType.STRING.name().toLowerCase(Locale.ENGLISH) + \"Col\");\n            long colKey2 = table.addColumn(RealmFieldType.INTEGER, RealmFieldType.INTEGER.name().toLowerCase(Locale.ENGLISH) + \"Col\");\n            long colKey3 = table.addColumn(RealmFieldType.BOOLEAN, RealmFieldType.BOOLEAN.name().toLowerCase(Locale.ENGLISH) + \"Col\");\n            long colKey4 = table.addColumn(RealmFieldType.BINARY, RealmFieldType.BINARY.name().toLowerCase(Locale.ENGLISH) + \"Col\");\n            long colKey5 = table.addColumn(RealmFieldType.DATE, RealmFieldType.DATE.name().toLowerCase(Locale.ENGLISH) + \"Col\");\n            long colKey6 = table.addColumn(RealmFieldType.FLOAT, RealmFieldType.FLOAT.name().toLowerCase(Locale.ENGLISH) + \"Col\");\n            long colKey7 = table.addColumn(RealmFieldType.DOUBLE, RealmFieldType.DOUBLE.name().toLowerCase(Locale.ENGLISH) + \"Col\");\n            long colKey8 = table.addColumnLink(RealmFieldType.OBJECT, RealmFieldType.OBJECT.name().toLowerCase(Locale.ENGLISH) + \"Col\", table);\n\n            long[] columnKeys = new long[]{colKey1, colKey2, colKey3, colKey4, colKey5, colKey6, colKey7, colKey8};\n            Object[] datas = new Object[]{new String[] {\"string value1\", \"string value2\"},\n                    new Long[] {100L, 102L},\n                    new Boolean[] {false, true},\n                    new byte[][] {new byte[] {123}, new byte[] {-123}},\n                    new Date[] {new Date(123456), new Date(13579)},\n                    new Float[] {1.234F, 100F},\n                    new Double[] {Math.PI, Math.E},\n                    new Long[] {0L, 1L}\n\n            };\n            RealmFieldType[] types = new RealmFieldType[]{RealmFieldType.STRING,\n                    RealmFieldType.INTEGER,\n                    RealmFieldType.BOOLEAN,\n                    RealmFieldType.BINARY,\n                    RealmFieldType.DATE,\n                    RealmFieldType.FLOAT,\n                    RealmFieldType.DOUBLE,\n                    RealmFieldType.OBJECT};\n            long rowKey = OsObject.createRow(table);\n            OsObject.createRow(table); // For link field update.\n\n            // Sets as default.\n            for (int i = 0; i< columnKeys.length; i++) {\n                final RealmFieldType type = types[i];\n                final Object value1 = ((Object[]) datas[i])[0];\n\n                switch (type) {\n                    case STRING:\n                        table.setString(columnKeys[i], rowKey, (String) value1, true);\n                        break;\n                    case INTEGER:\n                        table.setLong(columnKeys[i], rowKey, (long) value1, true);\n                        break;\n                    case BOOLEAN:\n                        table.setBoolean(columnKeys[i], rowKey, (boolean) value1, true);\n                        break;\n                    case BINARY:\n                        table.setBinaryByteArray(columnKeys[i], rowKey, (byte[]) value1, true);\n                        break;\n                    case DATE:\n                        table.setDate(columnKeys[i], rowKey, (Date) value1, true);\n                        break;\n                    case FLOAT:\n                        table.setFloat(columnKeys[i], rowKey, (float) value1, true);\n                        break;\n                    case DOUBLE:\n                        table.setDouble(columnKeys[i], rowKey, (double) value1, true);\n                        break;\n                    case OBJECT:\n                        table.setLink(columnKeys[i], rowKey, (long) value1, true);\n                        break;\n                    default:\n                        throw new RuntimeException(\"unexpected field type: \" + type);\n                }\n            }\n            sharedRealm.commitTransaction();\n\n            // Updates as non default.\n            sharedRealm.beginTransaction();\n            for (int i = 0; i< columnKeys.length; i++) {\n                final RealmFieldType type = types[i];\n                final Object value2 = ((Object[]) datas[i])[1];\n\n                switch (type) {\n                    case STRING:\n                        table.setString(columnKeys[i], rowKey, (String) value2, false);\n                        assertEquals(value2, table.getString(columnKeys[i], rowKey));\n                        break;\n                    case INTEGER:\n                        table.setLong(columnKeys[i], rowKey, (long) value2, false);\n                        assertEquals(value2, table.getLong(columnKeys[i], rowKey));\n                        break;\n                    case BOOLEAN:\n                        table.setBoolean(columnKeys[i], rowKey, (boolean) value2, false);\n                        assertEquals(value2, table.getBoolean(columnKeys[i], rowKey));\n                        break;\n                    case BINARY:\n                        table.setBinaryByteArray(columnKeys[i], rowKey, (byte[]) value2, false);\n                        assertTrue(Arrays.equals((byte[]) value2, table.getBinaryByteArray(columnKeys[i], rowKey)));\n                        break;\n                    case DATE:\n                        table.setDate(columnKeys[i], rowKey, (Date) value2, false);\n                        assertEquals(value2, table.getDate(columnKeys[i], rowKey));\n                        break;\n                    case FLOAT:\n                        table.setFloat(columnKeys[i], rowKey, (float) value2, false);\n                        assertEquals(value2, table.getFloat(columnKeys[i], rowKey));\n                        break;\n                    case DOUBLE:\n                        table.setDouble(columnKeys[i], rowKey, (double) value2, false);\n                        assertEquals(value2, table.getDouble(columnKeys[i], rowKey));\n                        break;\n                    case OBJECT:\n                        table.setLink(columnKeys[i], 0, (long) value2, false);\n                        assertEquals(value2, table.getLink(columnKeys[i], rowKey));\n                        break;\n                    default:\n                        throw new RuntimeException(\"unexpected field type: \" + type);\n                }\n            }\n            sharedRealm.commitTransaction();\n\n            // Checks if the value was overwritten.\n            for (int i = 0; i < columnKeys.length; i++) {\n                final RealmFieldType type = types[i];\n                final Object value2 = ((Object[]) datas[i])[1];\n\n                switch (type) {\n                    case STRING:\n                        assertEquals(value2, table.getString(columnKeys[i], rowKey));\n                        break;\n                    case INTEGER:\n                        assertEquals(value2, table.getLong(columnKeys[i], rowKey));\n                        break;\n                    case BOOLEAN:\n                        assertEquals(value2, table.getBoolean(columnKeys[i], rowKey));\n                        break;\n                    case BINARY:\n                        assertTrue(Arrays.equals((byte[]) value2, table.getBinaryByteArray(columnKeys[i], rowKey)));\n                        break;\n                    case DATE:\n                        assertEquals(value2, table.getDate(columnKeys[i], rowKey));\n                        break;\n                    case FLOAT:\n                        assertEquals(value2, table.getFloat(columnKeys[i], rowKey));\n                        break;\n                    case DOUBLE:\n                        assertEquals(value2, table.getDouble(columnKeys[i], rowKey));\n                        break;\n                    case OBJECT:\n                        assertEquals(value2, table.getLink(columnKeys[i], rowKey));\n                        break;\n                    default:\n                        throw new RuntimeException(\"unexpected field type: \" + type);\n                }\n            }\n        } finally {\n            sharedRealm.close();\n        }\n    }\n}\n\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/internal/ObserverPairListTests.java",
    "content": "/*\n * Copyright 2017 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\npackage io.realm.internal;\n\nimport android.annotation.SuppressLint;\nimport androidx.test.ext.junit.runners.AndroidJUnit4;\n\nimport org.junit.After;\nimport org.junit.Before;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\n\nimport java.util.concurrent.atomic.AtomicBoolean;\nimport java.util.concurrent.atomic.AtomicInteger;\n\nimport static junit.framework.Assert.assertEquals;\nimport static junit.framework.Assert.assertFalse;\nimport static junit.framework.Assert.assertTrue;\nimport static junit.framework.Assert.fail;\n\n/**\n * We are testing characteristic of the {@link ObserverPairList} here, such as:\n * Ownership of the listeners, equality of the pair and all public APIs for the class.\n */\n@RunWith(AndroidJUnit4.class)\npublic class ObserverPairListTests {\n\n    private static class TestListener<T> {\n        void onChange(T integer) {\n        }\n    }\n\n    private static class TestObserverPair extends ObserverPairList.ObserverPair<Integer, TestListener>  {\n        TestObserverPair(Integer observer, TestListener listener) {\n            super(observer, listener);\n        }\n    }\n\n    private ObserverPairList<TestObserverPair> observerPairs;\n    private TestListener testListener = new TestListener<Integer>();\n\n    private static final Integer ONE = 1;\n    private static final Integer TWO = 2;\n    private static final Integer THREE = 3;\n\n    @Before\n    public void setUp() {\n        observerPairs = new ObserverPairList<TestObserverPair>();\n    }\n\n    @After\n    public void tearDown() {\n        observerPairs = null;\n    }\n\n    @Test\n    public void add() {\n        TestObserverPair pair = new TestObserverPair(ONE, testListener);\n        observerPairs.add(pair);\n        assertEquals(1, observerPairs.size());\n\n        // Same observer object, different listener.\n        pair = new TestObserverPair(ONE, new TestListener<Integer>());\n        observerPairs.add(pair);\n        assertEquals(2, observerPairs.size());\n\n        // Different observer object, different listener.\n        pair = new TestObserverPair(TWO, new TestListener<Integer>());\n        observerPairs.add(pair);\n        assertEquals(3, observerPairs.size());\n\n        // Different observer object, same listener.\n        pair = new TestObserverPair(TWO, testListener);\n        observerPairs.add(pair);\n        assertEquals(4, observerPairs.size());\n    }\n\n    @Test\n    // The Observer pair is treated as the same when the observer is the same object and the listener is the same too.\n    public void add_noDuplicate() {\n        TestObserverPair pair = new TestObserverPair(ONE, testListener);\n        observerPairs.add(pair);\n        assertEquals(1, observerPairs.size());\n\n        pair = new TestObserverPair(ONE, testListener);\n        observerPairs.add(pair);\n        assertEquals(1, observerPairs.size());\n    }\n\n    // 1. add 2. clear 3. add 4. Check if the last listener can still be called.\n    @Test\n    public void add_worksAfterClears() {\n        final AtomicBoolean foreachCalled = new AtomicBoolean(false);\n        TestObserverPair pair = new TestObserverPair(ONE, testListener);\n        observerPairs.add(pair);\n        assertEquals(1, observerPairs.size());\n\n        observerPairs.clear();\n\n        observerPairs.add(pair);\n        assertEquals(1, observerPairs.size());\n        observerPairs.foreach(new ObserverPairList.Callback<TestObserverPair>() {\n            @Override\n            public void onCalled(TestObserverPair pair, Object observer) {\n                assertEquals(ONE, observer);\n                foreachCalled.set(true);\n            }\n        });\n        assertTrue(foreachCalled.get());\n    }\n\n    @SuppressLint({\"UseValueOf\", \"BoxedPrimitiveConstructor\"})\n    @Test\n    public void remove() {\n        TestObserverPair pair = new TestObserverPair(ONE, testListener);\n        observerPairs.add(pair);\n        assertEquals(1, observerPairs.size());\n\n        // Create a new Integer 1 to see if the equality is checked by the same object.\n        //noinspection UnnecessaryBoxing\n        observerPairs.remove(new Integer(1), testListener);\n        assertEquals(1, observerPairs.size());\n\n        // Different listener\n        observerPairs.remove(ONE, new TestListener());\n        assertEquals(1, observerPairs.size());\n\n        // Should remove now\n        observerPairs.remove(ONE, testListener);\n        assertEquals(0, observerPairs.size());\n    }\n\n    @Test\n    public void removeByObserver() {\n        TestObserverPair pair = new TestObserverPair(ONE, testListener);\n        observerPairs.add(pair);\n        pair = new TestObserverPair(ONE, new TestListener());\n        observerPairs.add(pair);\n        assertEquals(2, observerPairs.size());\n\n        // An different observer\n        //noinspection UnnecessaryBoxing\n        pair = new TestObserverPair(TWO, testListener);\n        observerPairs.add(pair);\n        assertEquals(3, observerPairs.size());\n\n        observerPairs.removeByObserver(ONE);\n        assertEquals(1, observerPairs.size());\n\n        observerPairs.removeByObserver(TWO);\n        assertEquals(0, observerPairs.size());\n    }\n\n    @Test\n    public void clear() {\n        TestObserverPair pair = new TestObserverPair(ONE, new TestListener());\n        observerPairs.add(pair);\n        assertEquals(1, observerPairs.size());\n        observerPairs.clear();\n        assertEquals(0, observerPairs.size());\n    }\n\n    @Test\n    public void isEmpty() {\n        assertTrue(observerPairs.isEmpty());\n        TestObserverPair pair = new TestObserverPair(ONE, new TestListener());\n        observerPairs.add(pair);\n        assertFalse(observerPairs.isEmpty());\n        observerPairs.clear();\n        assertTrue(observerPairs.isEmpty());\n    }\n\n    @Test\n    public void foreach() {\n        final boolean[] onChangesCalled = {false, false};\n        TestListener<Integer> listener = new TestListener<Integer>() {\n            @Override\n            void onChange(Integer i) {\n                onChangesCalled[i-1] = true;\n            }\n        };\n\n        TestObserverPair pair = new TestObserverPair(ONE, listener);\n        observerPairs.add(pair);\n        pair = new TestObserverPair(TWO, listener);\n        observerPairs.add(pair);\n        observerPairs.foreach(new ObserverPairList.Callback<TestObserverPair>() {\n            @Override\n            public void onCalled(TestObserverPair pair, Object observer) {\n                //noinspection unchecked\n                pair.listener.onChange(observer);\n            }\n        });\n        assertTrue(onChangesCalled[0] && onChangesCalled[1]);\n    }\n\n    // Test if the observer is GCed, the relevant listener should be removed when foreach called.\n    @Test\n    public void foreach_shouldRemoveWeakRefs() {\n        TestObserverPair pair = new TestObserverPair(ONE, new TestListener());\n        observerPairs.add(pair);\n        assertEquals(1, observerPairs.size());\n        observerPairs.foreach(new ObserverPairList.Callback<TestObserverPair>() {\n            @Override\n            public void onCalled(TestObserverPair pair, Object observer) {\n                // There is no guaranteed way to release the WeakReference,\n                // just clear it.\n                pair.observerRef.clear();\n            }\n        });\n        assertEquals(1, observerPairs.size());\n\n        observerPairs.foreach(new ObserverPairList.Callback<TestObserverPair>() {\n            @Override\n            public void onCalled(TestObserverPair pair, Object observer) {\n                fail();\n            }\n        });\n        assertEquals(0, observerPairs.size());\n    }\n\n    @Test\n    public void foreach_canRemove() {\n        final AtomicInteger count = new AtomicInteger(0);\n        final TestObserverPair pair1 = new TestObserverPair(ONE, new TestListener());\n        final TestListener listener2 = new TestListener();\n        final TestObserverPair pair2 = new TestObserverPair(TWO, listener2);\n        final TestObserverPair pair3 = new TestObserverPair(THREE, new TestListener());\n        observerPairs.add(pair1);\n        observerPairs.add(pair2);\n        observerPairs.add(pair3);\n        assertEquals(3, observerPairs.size());\n        observerPairs.foreach(new ObserverPairList.Callback<TestObserverPair>() {\n            @Override\n            public void onCalled(TestObserverPair pair, Object observer) {\n                assertFalse(((Integer) observer) == 2);\n                observerPairs.remove(TWO, listener2);\n                count.getAndIncrement();\n            }\n        });\n        assertEquals(2, observerPairs.size());\n        assertEquals(2, count.get());\n    }\n\n    @Test\n    public void foreach_canClear() {\n        final AtomicInteger count = new AtomicInteger(0);\n        final TestObserverPair pair1 = new TestObserverPair(ONE, new TestListener());\n        final TestObserverPair pair2 = new TestObserverPair(TWO, new TestListener());\n        final TestObserverPair pair3 = new TestObserverPair(THREE, new TestListener());\n        observerPairs.add(pair1);\n        observerPairs.add(pair2);\n        observerPairs.add(pair3);\n        assertEquals(3, observerPairs.size());\n        observerPairs.foreach(new ObserverPairList.Callback<TestObserverPair>() {\n            @Override\n            public void onCalled(TestObserverPair pair, Object observer) {\n                assertFalse(((Integer) observer) == 2);\n                assertFalse(((Integer) observer) == 3);\n                observerPairs.clear();\n                count.getAndIncrement();\n            }\n        });\n        assertEquals(0, observerPairs.size());\n        assertEquals(1, count.get());\n\n        observerPairs.add(pair1);\n        assertEquals(1, observerPairs.size());\n        observerPairs.foreach(new ObserverPairList.Callback<TestObserverPair>() {\n            @Override\n            public void onCalled(TestObserverPair pair, Object observer) {\n                assertTrue(((Integer) observer) == 1);\n            }\n        });\n    }\n\n    @Test\n    public void foreach_canAdd() {\n        final AtomicInteger count = new AtomicInteger(0);\n        final TestObserverPair pair1 = new TestObserverPair(ONE, new TestListener());\n        final TestObserverPair pair2 = new TestObserverPair(TWO, new TestListener());\n        observerPairs.add(pair1);\n        assertEquals(1, observerPairs.size());\n        observerPairs.foreach(new ObserverPairList.Callback<TestObserverPair>() {\n            @Override\n            public void onCalled(TestObserverPair pair, Object observer) {\n                observerPairs.add(pair2);\n                count.getAndIncrement();\n            }\n        });\n        assertEquals(2, observerPairs.size());\n        assertEquals(1, count.get());\n\n        count.set(0);\n        assertEquals(2, observerPairs.size());\n        observerPairs.foreach(new ObserverPairList.Callback<TestObserverPair>() {\n            @Override\n            public void onCalled(TestObserverPair pair, Object observer) {\n                count.getAndIncrement();\n            }\n        });\n        assertEquals(2, count.get());\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/internal/OsListTests.java",
    "content": "/*\n * Copyright 2017 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\npackage io.realm.internal;\n\nimport androidx.test.ext.junit.runners.AndroidJUnit4;\n\nimport org.junit.After;\nimport org.junit.Before;\nimport org.junit.Rule;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\n\nimport java.util.ArrayList;\nimport java.util.Date;\nimport java.util.List;\n\nimport io.realm.RealmConfiguration;\nimport io.realm.RealmFieldType;\nimport io.realm.TestRealmConfigurationFactory;\n\nimport static junit.framework.Assert.assertEquals;\nimport static junit.framework.Assert.assertNotNull;\nimport static junit.framework.Assert.fail;\nimport static org.junit.Assert.assertArrayEquals;\nimport static org.junit.Assert.assertFalse;\nimport static org.junit.Assert.assertNull;\nimport static org.junit.Assert.assertTrue;\n\n@RunWith(AndroidJUnit4.class)\npublic class OsListTests {\n    @Rule\n    public final TestRealmConfigurationFactory configFactory = new TestRealmConfigurationFactory();\n\n    private OsSharedRealm sharedRealm;\n    private UncheckedRow row;\n    private OsObjectSchemaInfo testObjectSchemaInfo;\n\n    @Before\n    public void setUp() {\n        OsObjectSchemaInfo objectSchemaInfo = new OsObjectSchemaInfo.Builder(\"TestModel\", false,14, 0)\n                .addPersistedValueListProperty(\"\", \"longList\", RealmFieldType.INTEGER_LIST, !Property.REQUIRED)\n                .addPersistedValueListProperty(\"\", \"doubleList\", RealmFieldType.DOUBLE_LIST,  !Property.REQUIRED)\n                .addPersistedValueListProperty(\"\", \"floatList\", RealmFieldType.FLOAT_LIST, !Property.REQUIRED)\n                .addPersistedValueListProperty(\"\", \"booleanList\", RealmFieldType.BOOLEAN_LIST, !Property.REQUIRED)\n                .addPersistedValueListProperty(\"\", \"binaryList\", RealmFieldType.BINARY_LIST, !Property.REQUIRED)\n                .addPersistedValueListProperty(\"\", \"dateList\", RealmFieldType.DATE_LIST, !Property.REQUIRED)\n                .addPersistedValueListProperty(\"\", \"stringList\", RealmFieldType.STRING_LIST, !Property.REQUIRED)\n\n                .addPersistedValueListProperty(\"\", \"requiredLongList\", RealmFieldType.INTEGER_LIST, Property.REQUIRED)\n                .addPersistedValueListProperty(\"\", \"requiredDoubleList\", RealmFieldType.DOUBLE_LIST, Property.REQUIRED)\n                .addPersistedValueListProperty(\"\", \"requiredFloatList\", RealmFieldType.FLOAT_LIST, Property.REQUIRED)\n                .addPersistedValueListProperty(\"\", \"requiredBooleanList\", RealmFieldType.BOOLEAN_LIST, Property.REQUIRED)\n                .addPersistedValueListProperty(\"\", \"requiredBinaryList\", RealmFieldType.BINARY_LIST, Property.REQUIRED)\n                .addPersistedValueListProperty(\"\", \"requiredDateList\", RealmFieldType.DATE_LIST, Property.REQUIRED)\n                .addPersistedValueListProperty(\"\", \"requiredStringList\", RealmFieldType.STRING_LIST, Property.REQUIRED)\n\n                .build();\n        List<OsObjectSchemaInfo> objectSchemaInfoList = new ArrayList<OsObjectSchemaInfo>();\n        objectSchemaInfoList.add(objectSchemaInfo);\n\n        OsSchemaInfo schemaInfo = new OsSchemaInfo(objectSchemaInfoList);\n\n        RealmConfiguration config = configFactory.createConfiguration();\n        OsRealmConfig.Builder configBuilder = new OsRealmConfig.Builder(config)\n                .autoUpdateNotification(true)\n                .schemaInfo(schemaInfo);\n        sharedRealm = OsSharedRealm.getInstance(configBuilder, OsSharedRealm.VersionID.LIVE);\n        sharedRealm.beginTransaction();\n        Table table = sharedRealm.getTable(Table.getTableNameForClass(\"TestModel\"));\n        row = table.getUncheckedRow(OsObject.createRow(table));\n        sharedRealm.commitTransaction();\n\n        schemaInfo = sharedRealm.getSchemaInfo();\n        testObjectSchemaInfo = schemaInfo.getObjectSchemaInfo(\"TestModel\");\n\n        sharedRealm.beginTransaction();\n    }\n\n    @After\n    public void tearDown() {\n        sharedRealm.cancelTransaction();\n        sharedRealm.close();\n    }\n\n    private void addNull_insertNull_setNull_nullableList(OsList osList) {\n        assertNotNull(osList.getValue(1));\n        osList.insertNull(1);\n        assertNull(osList.getValue(1));\n\n        osList.addNull();\n        assertNull(osList.getValue(osList.size() - 1));\n\n        assertNotNull(osList.getValue(2));\n        osList.setNull(2);\n        assertNull(osList.getValue(2));\n    }\n\n    private void addNull_insertNull_setNull_requiredList(OsList osList) {\n        long initialSize = osList.size();\n        try {\n            osList.insertNull(0);\n            fail();\n        } catch (IllegalArgumentException ignored) {\n            assertEquals(initialSize, osList.size());\n        }\n\n        initialSize = osList.size();\n        try {\n            osList.addNull();\n            fail();\n        } catch (IllegalArgumentException ignored) {\n            assertEquals(initialSize, osList.size());\n        }\n\n        initialSize = osList.size();\n        try {\n            osList.setNull(0);\n            fail();\n        } catch (IllegalArgumentException ignored) {\n            assertEquals(initialSize, osList.size());\n        }\n    }\n\n    private void add_insert_set_values_long(OsList osList) {\n        osList.addLong(42);\n        Long value = (Long) osList.getValue(0);\n        assertNotNull(value);\n        assertEquals(42, value.longValue());\n\n        osList.insertLong(0, 24);\n        value = (Long) osList.getValue(0);\n        assertNotNull(value);\n        assertEquals(24, value.longValue());\n\n        osList.setLong(0, 42);\n        value = (Long) osList.getValue(0);\n        assertNotNull(value);\n        assertEquals(42, value.longValue());\n    }\n\n    @Test\n    public void add_insert_set_get_Long() {\n        long columnKey = testObjectSchemaInfo.getProperty(\"longList\").getColumnKey();\n        OsList osList = new OsList(row, columnKey);\n\n        add_insert_set_values_long(osList);\n        addNull_insertNull_setNull_nullableList(osList);\n    }\n\n    @Test\n    public void add_insert_get_set_required_Long() {\n        long columnKey = testObjectSchemaInfo.getProperty(\"requiredLongList\").getColumnKey();\n        OsList osList = new OsList(row, columnKey);\n\n        add_insert_set_values_long(osList);\n        addNull_insertNull_setNull_requiredList(osList);\n    }\n\n    private void add_insert_set_values_double(OsList osList) {\n        osList.addDouble(42d);\n        Double value = (Double) osList.getValue(0);\n        assertNotNull(value);\n        assertEquals(42d, value.doubleValue(), 0d);\n\n        osList.insertDouble(0, 24);\n        value = (Double) osList.getValue(0);\n        assertNotNull(value);\n        assertEquals(24d, value.longValue(), 0d);\n\n        osList.setDouble(0, 42);\n        value = (Double) osList.getValue(0);\n        assertNotNull(value);\n        assertEquals(42d, value.longValue(), 0d);\n    }\n\n    @Test\n    public void add_insert_set_get_Double() {\n        long columnKey = testObjectSchemaInfo.getProperty(\"doubleList\").getColumnKey();\n        OsList osList = new OsList(row, columnKey);\n\n        add_insert_set_values_double(osList);\n        addNull_insertNull_setNull_nullableList(osList);\n    }\n\n    @Test\n    public void add_insert_set_get_required_Double() {\n        long columnKey = testObjectSchemaInfo.getProperty(\"requiredDoubleList\").getColumnKey();\n        OsList osList = new OsList(row, columnKey);\n\n        add_insert_set_values_double(osList);\n        addNull_insertNull_setNull_requiredList(osList);\n    }\n\n    private void add_insert_set_values_float(OsList osList) {\n        osList.addFloat(42f);\n        Float value = (Float) osList.getValue(0);\n        assertNotNull(value);\n        assertEquals(42f, value.doubleValue(), 0f);\n\n        osList.insertFloat(0, 24f);\n        value = (Float) osList.getValue(0);\n        assertNotNull(value);\n        assertEquals(24f, value.longValue(), 0f);\n\n        osList.setFloat(0, 42f);\n        value = (Float) osList.getValue(0);\n        assertNotNull(value);\n        assertEquals(42f, value.longValue(), 0f);\n    }\n\n    @Test\n    public void add_insert_get_Float() {\n        long columnKey = testObjectSchemaInfo.getProperty(\"floatList\").getColumnKey();\n        OsList osList = new OsList(row, columnKey);\n\n        add_insert_set_values_float(osList);\n        addNull_insertNull_setNull_nullableList(osList);\n    }\n\n    @Test\n    public void add_insert_get_required_Float() {\n        long columnKey = testObjectSchemaInfo.getProperty(\"requiredFloatList\").getColumnKey();\n        OsList osList = new OsList(row, columnKey);\n\n        add_insert_set_values_float(osList);\n        addNull_insertNull_setNull_requiredList(osList);\n    }\n\n    private void add_insert_set_values_boolean(OsList osList) {\n        osList.addBoolean(true);\n        Boolean value = (Boolean) osList.getValue(0);\n        assertNotNull(value);\n        assertTrue(value);\n\n        osList.insertBoolean(0, false);\n        value = (Boolean) osList.getValue(0);\n        assertNotNull(value);\n        assertFalse(value);\n\n        osList.setBoolean(0, true);\n        value = (Boolean) osList.getValue(0);\n        assertNotNull(value);\n        assertTrue(value);\n    }\n\n    @Test\n    public void add_insert_set_get_Boolean() {\n        long columnKey = testObjectSchemaInfo.getProperty(\"booleanList\").getColumnKey();\n        OsList osList = new OsList(row, columnKey);\n\n        add_insert_set_values_boolean(osList);\n        addNull_insertNull_setNull_nullableList(osList);\n    }\n\n    @Test\n    public void add_insert_set_get_required_Boolean() {\n        long columnKey = testObjectSchemaInfo.getProperty(\"requiredBooleanList\").getColumnKey();\n        OsList osList = new OsList(row, columnKey);\n\n        add_insert_set_values_boolean(osList);\n        addNull_insertNull_setNull_requiredList(osList);\n    }\n\n    @Test\n    public void add_insert_set_get_Date() {\n        long columnKey = testObjectSchemaInfo.getProperty(\"dateList\").getColumnKey();\n        OsList osList = new OsList(row, columnKey);\n\n        Date date42 = new Date(42);\n        Date date24 = new Date(24);\n\n        osList.addDate(null);\n        Date value = (Date) osList.getValue(0);\n        assertNull(value);\n\n        osList.addDate(date42);\n        value = (Date) osList.getValue(1);\n        assertNotNull(value);\n        assertEquals(date42, value);\n\n        osList.insertDate(0, null);\n        value = (Date) osList.getValue(0);\n        assertNull(value);\n\n        osList.insertDate(0, date24);\n        value = (Date) osList.getValue(0);\n        assertNotNull(value);\n        assertEquals(date24, value);\n\n        osList.insertNull(0);\n        value = (Date) osList.getValue(0);\n        assertNull(value);\n\n        osList.addNull();\n        assertNull(osList.getValue(5));\n\n        osList.setDate(5, date42);\n        value = (Date) osList.getValue(5);\n        assertNotNull(value);\n        assertEquals(date42, value);\n\n        osList.setDate(5, null);\n        value = (Date) osList.getValue(5);\n        assertNull(value);\n    }\n\n    @Test\n    public void add_insert_set_null_required_Date() {\n        long columnKey = testObjectSchemaInfo.getProperty(\"requiredDateList\").getColumnKey();\n        OsList osList = new OsList(row, columnKey);\n\n        addNull_insertNull_setNull_requiredList(osList);\n\n        try {\n            osList.insertDate(0, null);\n            fail();\n        } catch (IllegalArgumentException ignored) {\n        }\n\n        try {\n            osList.addDate(null);\n            fail();\n        } catch (IllegalArgumentException ignored) {\n        }\n\n        try {\n            osList.setDate(0, null);\n            fail();\n        } catch (IllegalArgumentException ignored) {\n        }\n    }\n\n    @Test\n    public void add_insert_get_String() {\n        long columnKey = testObjectSchemaInfo.getProperty(\"stringList\").getColumnKey();\n        OsList osList = new OsList(row, columnKey);\n\n        osList.addString(null);\n        String value = (String) osList.getValue(0);\n        assertNull(value);\n\n        osList.addString(\"42\");\n        value = (String) osList.getValue(1);\n        assertNotNull(value);\n        assertEquals(\"42\", value);\n\n        osList.insertString(0, null);\n        value = (String) osList.getValue(0);\n        assertNull(value);\n\n        osList.insertString(0, \"24\");\n        value = (String) osList.getValue(0);\n        assertNotNull(value);\n        assertEquals(\"24\", value);\n\n        osList.insertNull(0);\n        value = (String) osList.getValue(0);\n        assertNull(value);\n\n        osList.addNull();\n        assertNull(osList.getValue(5));\n\n        osList.setString(5, \"24\");\n        value = (String) osList.getValue(5);\n        assertNotNull(value);\n        assertEquals(\"24\", value);\n\n        osList.setString(5, null);\n        value = (String) osList.getValue(5);\n        assertNull(value);\n    }\n\n    @Test\n    public void add_insert_set_null_required_String() {\n        long columnKey = testObjectSchemaInfo.getProperty(\"requiredStringList\").getColumnKey();\n        OsList osList = new OsList(row, columnKey);\n\n        addNull_insertNull_setNull_requiredList(osList);\n\n        try {\n            osList.insertString(0, null);\n            fail();\n        } catch (IllegalArgumentException ignored) {\n        }\n\n        try {\n            osList.addString(null);\n            fail();\n        } catch (IllegalArgumentException ignored) {\n        }\n\n        try {\n            osList.setString(0, null);\n            fail();\n        } catch (IllegalArgumentException ignored) {\n        }\n    }\n\n    @Test\n    public void add_insert_get_Binary() {\n        long columnKey = testObjectSchemaInfo.getProperty(\"binaryList\").getColumnKey();\n        OsList osList = new OsList(row, columnKey);\n\n        byte[] bytes42 = new byte[1];\n        bytes42[0] = 42;\n        byte[] bytes24 = new byte[2];\n        bytes24[0] = 24;\n        bytes24[1] = 24;\n\n        osList.addBinary(null);\n        byte[] value = (byte[]) osList.getValue(0);\n        assertNull(value);\n\n        osList.addBinary(bytes42);\n        value = (byte[]) osList.getValue(1);\n        assertNotNull(value);\n        assertArrayEquals(bytes42, value);\n\n        osList.insertBinary(0, null);\n        value = (byte[]) osList.getValue(0);\n        assertNull(value);\n\n        osList.insertBinary(0, bytes24);\n        value = (byte[]) osList.getValue(0);\n        assertNotNull(value);\n        assertArrayEquals(bytes24, value);\n\n        osList.insertNull(0);\n        value = (byte[]) osList.getValue(0);\n        assertNull(value);\n\n        osList.addNull();\n        assertNull(osList.getValue(5));\n\n        osList.setBinary(5, bytes24);\n        value = (byte[]) osList.getValue(5);\n        assertNotNull(value);\n        assertArrayEquals(bytes24, value);\n\n        osList.setBinary(5, null);\n        value = (byte[]) osList.getValue(5);\n        assertNull(value);\n    }\n\n    @Test\n    public void add_insert_set_null_required_Binary() {\n        long columnKey = testObjectSchemaInfo.getProperty(\"requiredBinaryList\").getColumnKey();\n        OsList osList = new OsList(row, columnKey);\n\n        addNull_insertNull_setNull_requiredList(osList);\n\n        try {\n            osList.insertBinary(0, null);\n            fail();\n        } catch (IllegalArgumentException ignored) {\n        }\n\n        try {\n            osList.addBinary(null);\n            fail();\n        } catch (IllegalArgumentException ignored) {\n        }\n\n        try {\n            osList.setBinary(0, null);\n            fail();\n        } catch (IllegalArgumentException ignored) {\n        }\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/internal/OsObjectStoreTests.java",
    "content": "/*\n * Copyright 2017 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 */\npackage io.realm.internal;\n\nimport androidx.test.ext.junit.runners.AndroidJUnit4;\n\nimport org.junit.After;\nimport org.junit.Before;\nimport org.junit.Rule;\nimport org.junit.Test;\nimport org.junit.rules.ExpectedException;\nimport org.junit.runner.RunWith;\n\nimport java.util.concurrent.atomic.AtomicBoolean;\n\nimport io.realm.RealmConfiguration;\nimport io.realm.log.LogLevel;\nimport io.realm.log.RealmLog;\nimport io.realm.TestRealmConfigurationFactory;\n\nimport static junit.framework.Assert.assertEquals;\nimport static junit.framework.Assert.assertFalse;\nimport static junit.framework.Assert.assertTrue;\nimport static junit.framework.Assert.fail;\n\n// Tests for OsObjectStore\n@RunWith(AndroidJUnit4.class)\npublic class OsObjectStoreTests {\n    @Rule\n    public final TestRealmConfigurationFactory configFactory = new TestRealmConfigurationFactory();\n    @Rule\n    public final ExpectedException thrown = ExpectedException.none();\n\n    @Before\n    public void setUp() {\n        RealmLog.setLevel(LogLevel.ERROR);\n    }\n\n    @After\n    public void tearDown() {\n        RealmLog.setLevel(LogLevel.WARN);\n    }\n\n    @Test\n    public void callWithLock() {\n        RealmConfiguration config = configFactory.createConfiguration();\n\n        // Return false if there are opened OsSharedRealm instance\n        OsSharedRealm sharedRealm = OsSharedRealm.getInstance(config, OsSharedRealm.VersionID.LIVE);\n        assertFalse(OsObjectStore.callWithLock(config, new Runnable() {\n            @Override\n            public void run() {\n                fail();\n            }\n        }));\n        sharedRealm.close();\n\n        final AtomicBoolean callbackCalled = new AtomicBoolean(false);\n        assertTrue(OsObjectStore.callWithLock(config, new Runnable() {\n            @Override\n            public void run() {\n                callbackCalled.set(true);\n            }\n        }));\n        assertTrue(callbackCalled.get());\n    }\n\n    // Test if a java exception can be thrown from the callback.\n    @Test\n    public void callWithLock_throwInCallback() {\n        RealmConfiguration config = configFactory.createConfiguration();\n        final RuntimeException exception = new RuntimeException();\n\n        try {\n            OsObjectStore.callWithLock(config, new Runnable() {\n                @Override\n                public void run() {\n                    throw exception;\n                }\n            });\n            fail();\n        } catch (RuntimeException e) {\n            assertEquals(exception, e);\n        }\n\n        // The lock should be released after exception thrown\n        final AtomicBoolean callbackCalled = new AtomicBoolean(false);\n        assertTrue(OsObjectStore.callWithLock(config, new Runnable() {\n            @Override\n            public void run() {\n                callbackCalled.set(true);\n            }\n        }));\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/internal/OsResultsTests.java",
    "content": "/*\n * Copyright 2017 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\npackage io.realm.internal;\n\n\nimport org.junit.After;\nimport org.junit.Before;\nimport org.junit.Rule;\nimport org.junit.Test;\nimport org.junit.rules.ExpectedException;\nimport org.junit.runner.RunWith;\n\nimport java.lang.ref.WeakReference;\nimport java.util.ConcurrentModificationException;\nimport java.util.concurrent.CountDownLatch;\nimport java.util.concurrent.atomic.AtomicBoolean;\nimport java.util.concurrent.atomic.AtomicInteger;\n\nimport androidx.test.ext.junit.runners.AndroidJUnit4;\nimport io.realm.RealmAny;\nimport io.realm.RealmChangeListener;\nimport io.realm.RealmConfiguration;\nimport io.realm.RealmFieldType;\nimport io.realm.Sort;\nimport io.realm.TestHelper;\nimport io.realm.TestRealmConfigurationFactory;\nimport io.realm.rule.RunInLooperThread;\nimport io.realm.rule.RunTestInLooperThread;\n\nimport static junit.framework.Assert.assertEquals;\nimport static junit.framework.Assert.assertFalse;\nimport static junit.framework.Assert.assertTrue;\nimport static junit.framework.Assert.fail;\n\n\n@RunWith(AndroidJUnit4.class)\npublic class OsResultsTests {\n    @Rule\n    public final TestRealmConfigurationFactory configFactory = new TestRealmConfigurationFactory();\n    @Rule\n    public final ExpectedException thrown = ExpectedException.none();\n    @Rule\n    public final RunInLooperThread looperThread = new RunInLooperThread();\n\n    private final long[] oneNullTable = new long[] {NativeObject.NULLPTR};\n\n    private OsSharedRealm sharedRealm;\n    private Table table;\n\n    private long colKey0 = -1;\n    private long colKey1 = -1;\n    private long colKey2 = -1;\n    private long rowKey0 = -1;\n    private long rowKey1 = -1;\n    private long rowKey2 = -1;\n    private long rowKey3 = -1;\n\n    @Before\n    public void setUp() {\n        sharedRealm = getSharedRealm();\n        populateData(sharedRealm);\n    }\n\n    @After\n    public void tearDown() {\n        sharedRealm.close();\n    }\n\n    private OsSharedRealm getSharedRealm() {\n        RealmConfiguration config = configFactory.createConfiguration();\n        return getSharedRealm(config);\n    }\n\n    private OsSharedRealm getSharedRealmForLooper() {\n        RealmConfiguration config = looperThread.createConfiguration();\n        return getSharedRealm(config);\n    }\n\n    private OsSharedRealm getSharedRealm(RealmConfiguration config) {\n        OsRealmConfig.Builder configBuilder = new OsRealmConfig.Builder(config)\n                .autoUpdateNotification(true);\n        OsSharedRealm sharedRealm = OsSharedRealm.getInstance(configBuilder, OsSharedRealm.VersionID.LIVE);\n        sharedRealm.beginTransaction();\n        OsObjectStore.setSchemaVersion(sharedRealm, OsObjectStore.SCHEMA_NOT_VERSIONED);\n        sharedRealm.commitTransaction();\n        return sharedRealm;\n    }\n\n    private Table getTable(OsSharedRealm sharedRealm) {\n        return sharedRealm.getTable(Table.getTableNameForClass(\"test_table\"));\n    }\n\n    private void populateData(OsSharedRealm sharedRealm) {\n        sharedRealm.beginTransaction();\n        table = sharedRealm.createTable(Table.getTableNameForClass(\"test_table\"));\n        // Specify the column types and names\n        colKey0 = table.addColumn(RealmFieldType.STRING, \"firstName\");\n        table.addSearchIndex(colKey0);\n        colKey1 = table.addColumn(RealmFieldType.STRING, \"lastName\");\n        colKey2 = table.addColumn(RealmFieldType.INTEGER, \"age\");\n\n        // Add data to the table\n        rowKey0 = OsObject.createRow(table);\n        table.setString(colKey0, rowKey0, \"John\", false);\n        table.setString(colKey1, rowKey0, \"Lee\", false);\n        table.setLong(colKey2, rowKey0, 4, false);\n\n        rowKey1 = OsObject.createRow(table);\n        table.setString(colKey0, rowKey1, \"John\", false);\n        table.setString(colKey1, rowKey1, \"Anderson\", false);\n        table.setLong(colKey2, rowKey1, 3, false);\n\n        rowKey2 = OsObject.createRow(table);\n        table.setString(colKey0, rowKey2, \"Erik\", false);\n        table.setString(colKey1, rowKey2, \"Lee\", false);\n        table.setLong(colKey2, rowKey2, 1, false);\n\n        rowKey3 = OsObject.createRow(table);\n        table.setString(colKey0, rowKey3, \"Henry\", false);\n        table.setString(colKey1, rowKey3, \"Anderson\", false);\n        table.setLong(colKey2, rowKey3, 1, false);\n        sharedRealm.commitTransaction();\n    }\n\n    private void addRowAsync(final OsSharedRealm sharedRealm) {\n        final CountDownLatch latch = new CountDownLatch(1);\n        final RealmConfiguration configuration = sharedRealm.getConfiguration();\n        new Thread(new Runnable() {\n            @Override\n            public void run() {\n                OsSharedRealm sharedRealm = getSharedRealm(configuration);\n                addRow(sharedRealm);\n                sharedRealm.close();\n                latch.countDown();\n            }\n        }).start();\n        TestHelper.awaitOrFail(latch);\n    }\n\n    private void addRow(OsSharedRealm sharedRealm) {\n        sharedRealm.beginTransaction();\n        Table table = getTable(sharedRealm);\n        OsObject.createRow(table);\n        sharedRealm.commitTransaction();\n    }\n\n    @Test\n    public void constructor_withDistinct() {\n        OsResults osResults = OsResults.createFromQuery(sharedRealm, table.where().distinct(null, new String[]{\"firstName\"}));\n\n        assertEquals(3, osResults.size());\n        assertEquals(\"John\", osResults.getUncheckedRow(0).getString(colKey0));\n        assertEquals(\"Erik\", osResults.getUncheckedRow(1).getString(colKey0));\n        assertEquals(\"Henry\", osResults.getUncheckedRow(2).getString(colKey0));\n    }\n\n    @Test\n    public void constructor_queryOnDeletedTable() {\n        TableQuery query = table.where();\n\n        sharedRealm.beginTransaction();\n        assertTrue(OsObjectStore.deleteTableForObject(sharedRealm, table.getClassName()));\n        sharedRealm.commitTransaction();\n        // Query should be checked before creating OS Results.\n        thrown.expect(IllegalStateException.class);\n        OsResults.createFromQuery(sharedRealm, query);\n    }\n\n    @Test\n    public void size() {\n        OsResults osResults = OsResults.createFromQuery(sharedRealm, table.where());\n        assertEquals(4, osResults.size());\n    }\n\n    @Test\n    public void where() {\n        OsResults osResults = OsResults.createFromQuery(sharedRealm, table.where());\n        OsResults osResults2 = OsResults.createFromQuery(sharedRealm, osResults.where().equalTo(null,\"firstName\", RealmAny.valueOf(\"John\")));\n        OsResults osResults3 = OsResults.createFromQuery(sharedRealm, osResults2.where().equalTo(null, \"lastName\",  RealmAny.valueOf(\"Anderson\")));\n\n        // A new native Results should be created.\n        assertTrue(osResults.getNativePtr() != osResults2.getNativePtr());\n        assertTrue(osResults2.getNativePtr() != osResults3.getNativePtr());\n\n        assertEquals(4, osResults.size());\n        assertEquals(2, osResults2.size());\n        assertEquals(1, osResults3.size());\n    }\n\n    @Test\n    public void sort() {\n        OsResults osResults = OsResults.createFromQuery(sharedRealm, table.where().greaterThan(null,\"age\", RealmAny.valueOf(1)));\n\n        OsResults osResults2 = osResults.sort(null,\"age\", Sort.ASCENDING);\n\n        // A new native Results should be created.\n        assertTrue(osResults.getNativePtr() != osResults2.getNativePtr());\n        assertEquals(2, osResults.size());\n        assertEquals(2, osResults2.size());\n\n        assertEquals(3, osResults2.getUncheckedRow(0).getLong(colKey2));\n        assertEquals(4, osResults2.getUncheckedRow(1).getLong(colKey2));\n    }\n\n    @Test\n    public void clear() {\n        assertEquals(4, table.size());\n        OsResults osResults = OsResults.createFromQuery(sharedRealm, table.where());\n        sharedRealm.beginTransaction();\n        osResults.clear();\n        sharedRealm.commitTransaction();\n        assertEquals(0, table.size());\n    }\n\n    @Test\n    public void contains() {\n        OsResults osResults = OsResults.createFromQuery(sharedRealm, table.where());\n        UncheckedRow row = table.getUncheckedRow(0);\n        assertTrue(osResults.contains(row));\n    }\n\n    @Test\n    public void indexOf() {\n        OsResults osResults = OsResults.createFromQuery(sharedRealm, table.where().sort(null,new String[] {\"age\"}, new Sort[] {Sort.ASCENDING}));\n        UncheckedRow row = table.getUncheckedRow(rowKey0);\n        assertEquals(3, osResults.indexOf(row));\n    }\n\n    @Test\n    public void distinct() {\n        OsResults osResults = OsResults.createFromQuery(sharedRealm, table.where().lessThan(null,\"age\", RealmAny.valueOf(4)));\n\n        OsResults osResults2 = osResults.distinct(null, new String[]{\"age\"});\n\n        // A new native Results should be created.\n        assertTrue(osResults.getNativePtr() != osResults2.getNativePtr());\n        assertEquals(3, osResults.size());\n        assertEquals(2, osResults2.size());\n\n        assertEquals(3, osResults2.getUncheckedRow(0).getLong(colKey2));\n        assertEquals(1, osResults2.getUncheckedRow(1).getLong(colKey2));\n    }\n\n    // 1. Create a results and add listener.\n    // 2. Query results should be returned in the next loop.\n    @Test\n    @RunTestInLooperThread\n    public void addListener_shouldBeCalledToReturnTheQueryResults() {\n        final OsSharedRealm sharedRealm = getSharedRealmForLooper();\n        populateData(sharedRealm);\n        Table table = getTable(sharedRealm);\n\n        final OsResults osResults = OsResults.createFromQuery(sharedRealm, table.where());\n        looperThread.keepStrongReference(osResults);\n        osResults.addListener(osResults, new RealmChangeListener<OsResults>() {\n            @Override\n            public void onChange(OsResults osResults1) {\n                assertEquals(osResults, osResults1);\n                assertEquals(4, osResults1.size());\n                sharedRealm.close();\n                looperThread.testComplete();\n            }\n        });\n    }\n\n    // 1. Create a results and add listener on a non-looper thread.\n    // 2. Query results should be returned when refresh() called.\n    @Test\n    public void addListener_shouldBeCalledWhenRefreshToReturnTheQueryResults() {\n        final AtomicBoolean onChangeCalled = new AtomicBoolean(false);\n        final OsSharedRealm sharedRealm = getSharedRealm();\n        Table table = getTable(sharedRealm);\n\n        final OsResults osResults = OsResults.createFromQuery(sharedRealm, table.where());\n        osResults.addListener(osResults, new RealmChangeListener<OsResults>() {\n            @Override\n            public void onChange(OsResults osResults1) {\n                assertEquals(osResults, osResults1);\n                assertEquals(4, osResults1.size());\n                sharedRealm.close();\n                onChangeCalled.set(true);\n            }\n        });\n        sharedRealm.refresh();\n        assertTrue(onChangeCalled.get());\n    }\n\n    @Test\n    public void addListener_shouldBeCalledWhenRefreshAfterLocalCommit() {\n        final CountDownLatch latch = new CountDownLatch(2);\n        final OsResults osResults = OsResults.createFromQuery(sharedRealm, table.where());\n        assertEquals(4, osResults.size()); // See `populateData()`\n        osResults.addListener(osResults, new RealmChangeListener<OsResults>() {\n            @Override\n            public void onChange(OsResults element) {\n                if (latch.getCount() == 2) {\n                    // triggered by beginTransaction\n                    assertEquals(4, osResults.size());\n                } else if (latch.getCount() == 1) {\n                    // triggered by refresh\n                    assertEquals(5, osResults.size());\n                } else {\n                    fail();\n                }\n                latch.countDown();\n            }\n        });\n        sharedRealm.beginTransaction();\n        OsObject.createRow(table);\n        sharedRealm.commitTransaction();\n        sharedRealm.refresh();\n        TestHelper.awaitOrFail(latch);\n    }\n\n    // Local commit will trigger the listener first when beginTransaction gets called then again when call refresh.\n    @Test\n    public void addListener_triggeredByRefresh() {\n        final CountDownLatch latch = new CountDownLatch(1);\n        OsResults osResults = OsResults.createFromQuery(sharedRealm, table.where());\n        osResults.size();\n        osResults.addListener(osResults, new RealmChangeListener<OsResults>() {\n            @Override\n            public void onChange(OsResults element) {\n                assertEquals(1, latch.getCount());\n                latch.countDown();\n            }\n        });\n\n        addRowAsync(sharedRealm);\n\n        sharedRealm.refresh();\n        TestHelper.awaitOrFail(latch);\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void addListener_queryNotReturned() {\n        final OsSharedRealm sharedRealm = getSharedRealmForLooper();\n        populateData(sharedRealm);\n        Table table = getTable(sharedRealm);\n\n        final OsResults osResults = OsResults.createFromQuery(sharedRealm, table.where());\n        looperThread.keepStrongReference(osResults);\n        osResults.addListener(osResults, new RealmChangeListener<OsResults>() {\n            @Override\n            public void onChange(OsResults osResults1) {\n                assertEquals(osResults, osResults1);\n                assertEquals(5, osResults1.size());\n                sharedRealm.close();\n                looperThread.testComplete();\n            }\n        });\n\n        addRowAsync(sharedRealm);\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void addListener_queryReturned() {\n        final OsSharedRealm sharedRealm = getSharedRealmForLooper();\n        populateData(sharedRealm);\n        Table table = getTable(sharedRealm);\n\n        final OsResults osResults = OsResults.createFromQuery(sharedRealm, table.where());\n        looperThread.keepStrongReference(osResults);\n        assertEquals(4, osResults.size()); // Trigger the query to run.\n        osResults.addListener(osResults, new RealmChangeListener<OsResults>() {\n            @Override\n            public void onChange(OsResults osResults1) {\n                assertEquals(osResults, osResults1);\n                assertEquals(5, osResults1.size());\n                sharedRealm.close();\n                looperThread.testComplete();\n            }\n        });\n\n        addRowAsync(sharedRealm);\n    }\n\n    // Local commit will trigger the listener first when beginTransaction gets called then again when transaction\n    // committed.\n    @Test\n    @RunTestInLooperThread\n    public void addListener_triggeredByLocalCommit() {\n        final OsSharedRealm sharedRealm = getSharedRealmForLooper();\n        populateData(sharedRealm);\n        Table table = getTable(sharedRealm);\n        final AtomicInteger listenerCounter = new AtomicInteger(0);\n\n        final OsResults osResults = OsResults.createFromQuery(sharedRealm, table.where());\n        looperThread.keepStrongReference(osResults);\n        osResults.addListener(osResults, new RealmChangeListener<OsResults>() {\n            @Override\n            public void onChange(OsResults osResults1) {\n                switch (listenerCounter.getAndIncrement()) {\n                    case 0:\n                        assertEquals(4, osResults1.size());\n                        break;\n                    case 1:\n                        assertEquals(5, osResults1.size());\n                        sharedRealm.close();\n                        break;\n                    default:\n                        fail();\n                        break;\n                }\n            }\n        });\n        addRow(sharedRealm);\n        assertEquals(2, listenerCounter.get());\n        looperThread.testComplete();\n    }\n\n    private static class TestIterator extends OsResults.Iterator<Integer> {\n        TestIterator(OsResults osResults) {\n            super(osResults);\n        }\n\n        @Override\n        protected Integer convertRowToObject(UncheckedRow row) {\n            return null;\n        }\n\n        @Override\n        protected Integer getInternal(int pos, OsResults iteratorOsResults) {\n            return null;\n        }\n\n        boolean isDetached(OsSharedRealm sharedRealm) {\n            for (WeakReference<OsResults.Iterator> iteratorRef : sharedRealm.iterators) {\n                OsResults.Iterator iterator = iteratorRef.get();\n                if (iterator == this) {\n                    return false;\n                }\n            }\n            return true;\n        }\n    }\n\n    @Test\n    public void collectionIterator_detach_byBeginTransaction() {\n        final OsResults osResults = OsResults.createFromQuery(sharedRealm, table.where());\n        TestIterator iterator = new TestIterator(osResults);\n        assertFalse(iterator.isDetached(sharedRealm));\n        sharedRealm.beginTransaction();\n        assertTrue(iterator.isDetached(sharedRealm));\n        sharedRealm.commitTransaction();\n        assertTrue(iterator.isDetached(sharedRealm));\n    }\n\n    @Test\n    public void collectionIterator_detach_createdInTransaction() {\n        sharedRealm.beginTransaction();\n        final OsResults osResults = OsResults.createFromQuery(sharedRealm, table.where());\n        TestIterator iterator = new TestIterator(osResults);\n        assertTrue(iterator.isDetached(sharedRealm));\n    }\n\n    @Test\n    public void collectionIterator_invalid_nonLooperThread_byRefresh() {\n        final OsResults osResults = OsResults.createFromQuery(sharedRealm, table.where());\n        TestIterator iterator = new TestIterator(osResults);\n        assertFalse(iterator.isDetached(sharedRealm));\n        sharedRealm.refresh();\n        thrown.expect(ConcurrentModificationException.class);\n        iterator.checkValid();\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void collectionIterator_invalid_looperThread_byRemoteTransaction() {\n        final OsSharedRealm sharedRealm = getSharedRealmForLooper();\n        populateData(sharedRealm);\n        Table table = getTable(sharedRealm);\n        final OsResults osResults = OsResults.createFromQuery(sharedRealm, table.where());\n        final TestIterator iterator = new TestIterator(osResults);\n        looperThread.keepStrongReference(osResults);\n        assertFalse(iterator.isDetached(sharedRealm));\n        osResults.addListener(osResults, new RealmChangeListener<OsResults>() {\n            @Override\n            public void onChange(OsResults element) {\n                try {\n                    iterator.checkValid();\n                    fail();\n                } catch (ConcurrentModificationException ignored) {\n                }\n                sharedRealm.close();\n                looperThread.testComplete();\n            }\n        });\n\n        addRowAsync(sharedRealm);\n    }\n\n    @Test\n    public void collectionIterator_newInstance_throwsWhenSharedRealmIsClosed() {\n        final OsResults osResults = OsResults.createFromQuery(sharedRealm, table.where());\n        sharedRealm.close();\n        thrown.expect(IllegalStateException.class);\n        new TestIterator(osResults);\n    }\n\n    @Test\n    public void getMode() {\n        OsResults osResults = OsResults.createFromQuery(sharedRealm, table.where());\n        assertTrue(OsResults.Mode.QUERY == osResults.getMode());\n        osResults.firstUncheckedRow(); // Run the query\n        assertTrue(OsResults.Mode.TABLEVIEW == osResults.getMode());\n    }\n\n    @Test\n    public void createSnapshot() {\n        OsResults osResults = OsResults.createFromQuery(sharedRealm, table.where());\n        OsResults snapshot = osResults.createSnapshot();\n        assertTrue(OsResults.Mode.TABLEVIEW == snapshot.getMode());\n        thrown.expect(IllegalStateException.class);\n        snapshot.addListener(snapshot, new RealmChangeListener<OsResults>() {\n            @Override\n            public void onChange(OsResults element) {\n            }\n        });\n    }\n\n    @Test\n    @RunTestInLooperThread\n    public void load() {\n        final OsSharedRealm sharedRealm = getSharedRealmForLooper();\n        looperThread.closeAfterTest(sharedRealm);\n        populateData(sharedRealm);\n        final OsResults osResults = OsResults.createFromQuery(sharedRealm, table.where());\n        osResults.addListener(osResults, new RealmChangeListener<OsResults>() {\n            @Override\n            public void onChange(OsResults element) {\n                assertTrue(osResults.isLoaded());\n                looperThread.testComplete();\n            }\n        });\n        assertFalse(osResults.isLoaded());\n        osResults.load();\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/internal/OsSharedRealmTests.java",
    "content": "/*\n * Copyright 2016 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 */\npackage io.realm.internal;\n\nimport androidx.test.ext.junit.runners.AndroidJUnit4;\n\nimport org.junit.After;\nimport org.junit.Before;\nimport org.junit.Rule;\nimport org.junit.Test;\nimport org.junit.rules.ExpectedException;\nimport org.junit.runner.RunWith;\n\nimport java.util.concurrent.atomic.AtomicBoolean;\n\nimport io.realm.RealmConfiguration;\nimport io.realm.exceptions.RealmError;\nimport io.realm.TestRealmConfigurationFactory;\n\nimport static junit.framework.Assert.assertFalse;\nimport static junit.framework.Assert.assertTrue;\n\n@RunWith(AndroidJUnit4.class)\npublic class OsSharedRealmTests {\n    @Rule\n    public final TestRealmConfigurationFactory configFactory = new TestRealmConfigurationFactory();\n    @Rule\n    public final ExpectedException thrown = ExpectedException.none();\n\n    private RealmConfiguration config;\n    private OsSharedRealm sharedRealm;\n\n    @Before\n    public void setUp() {\n        config = configFactory.createConfiguration();\n        sharedRealm = OsSharedRealm.getInstance(config, OsSharedRealm.VersionID.LIVE);\n    }\n\n    @After\n    public void tearDown() {\n        if (sharedRealm != null) {\n            sharedRealm.close();\n        }\n    }\n\n    @Test\n    public void hasTable() {\n        assertFalse(sharedRealm.hasTable(\"MyTable\"));\n        sharedRealm.beginTransaction();\n        sharedRealm.createTable(\"MyTable\");\n        sharedRealm.commitTransaction();\n        assertTrue(sharedRealm.hasTable(\"MyTable\"));\n    }\n\n    @Test\n    public void getTable() {\n        assertFalse(sharedRealm.hasTable(\"MyTable\"));\n        sharedRealm.beginTransaction();\n        sharedRealm.createTable(\"MyTable\");\n        sharedRealm.commitTransaction();\n        assertTrue(sharedRealm.hasTable(\"MyTable\"));\n\n        // Table is existing, no need transaction to create it\n        assertTrue(sharedRealm.getTable(\"MyTable\").isValid());\n    }\n\n    @Test(expected = IllegalArgumentException.class)\n    public void getTable_throwsIfTableNotExist() {\n        sharedRealm.getTable(\"NON_EXISTING\");\n    }\n\n    @Test\n    public void isInTransaction() {\n        assertFalse(sharedRealm.isInTransaction());\n        sharedRealm.beginTransaction();\n        assertTrue(sharedRealm.isInTransaction());\n        sharedRealm.cancelTransaction();\n        assertFalse(sharedRealm.isInTransaction());\n    }\n\n    @Test\n    public void isInTransaction_returnFalseWhenRealmClosed() {\n        sharedRealm.close();\n        assertFalse(sharedRealm.isInTransaction());\n        sharedRealm = null;\n    }\n\n    @Test\n    public void renameTable() {\n        sharedRealm.beginTransaction();\n        sharedRealm.createTable(\"OldTable\");\n        assertTrue(sharedRealm.hasTable(\"OldTable\"));\n        sharedRealm.renameTable(\"OldTable\", \"NewTable\");\n        assertFalse(sharedRealm.hasTable(\"OldTable\"));\n        assertTrue(sharedRealm.hasTable(\"NewTable\"));\n        sharedRealm.commitTransaction();\n    }\n\n    @Test\n    public void renameTable_notInTransactionThrows() {\n        sharedRealm.beginTransaction();\n        sharedRealm.createTable(\"OldTable\");\n        sharedRealm.commitTransaction();\n        thrown.expect(IllegalStateException.class);\n        sharedRealm.renameTable(\"OldTable\", \"NewTable\");\n    }\n\n    @Test\n    public void renameTable_tableNotExist() {\n        sharedRealm.beginTransaction();\n        assertFalse(sharedRealm.hasTable(\"TableToRemove\"));\n        thrown.expect(RealmError.class);\n        sharedRealm.renameTable(\"TableToRemove\", \"newName\");\n        sharedRealm.cancelTransaction();\n    }\n\n\n    private void changeSchemaByAnotherRealm() {\n        OsSharedRealm sharedRealm = OsSharedRealm.getInstance(config, OsSharedRealm.VersionID.LIVE);\n        sharedRealm.beginTransaction();\n        sharedRealm.createTable(\"class_NewTable\");\n        sharedRealm.commitTransaction();\n        sharedRealm.close();\n    }\n\n    @Test\n    public void registerSchemaChangedCallback_beginTransaction() {\n        final AtomicBoolean listenerCalled = new AtomicBoolean(false);\n\n        assertFalse(sharedRealm.hasTable(\"class_NewTable\"));\n\n        sharedRealm.registerSchemaChangedCallback(new OsSharedRealm.SchemaChangedCallback() {\n            @Override\n            public void onSchemaChanged() {\n                assertTrue(sharedRealm.hasTable(\"class_NewTable\"));\n                listenerCalled.set(true);\n            }\n        });\n        changeSchemaByAnotherRealm();\n        sharedRealm.beginTransaction();\n        assertTrue(listenerCalled.get());\n    }\n\n    @Test\n    public void registerSchemaChangedCallback_refresh() {\n        final AtomicBoolean listenerCalled = new AtomicBoolean(false);\n\n        assertFalse(sharedRealm.hasTable(\"class_NewTable\"));\n\n        sharedRealm.registerSchemaChangedCallback(new OsSharedRealm.SchemaChangedCallback() {\n            @Override\n            public void onSchemaChanged() {\n                assertTrue(sharedRealm.hasTable(\"class_NewTable\"));\n                listenerCalled.set(true);\n            }\n        });\n        changeSchemaByAnotherRealm();\n        sharedRealm.refresh();\n        assertTrue(listenerCalled.get());\n    }\n\n    // Test for https://github.com/realm/realm-core/issues/3707\n    @Test\n    public void emitTableInstructionsForCustomClasses() {\n        final AtomicBoolean listenerCalled = new AtomicBoolean(false);\n        assertFalse(sharedRealm.hasTable(\"NewTable\"));\n        sharedRealm.registerSchemaChangedCallback(new OsSharedRealm.SchemaChangedCallback() {\n            @Override\n            public void onSchemaChanged() {\n                assertTrue(sharedRealm.hasTable(\"NewTable\"));\n                listenerCalled.set(true);\n            }\n        });\n\n        // Change schema using another Realm\n        // Classes not starting with class_ were treated differently by Sync\n        OsSharedRealm bgRealm = OsSharedRealm.getInstance(config, OsSharedRealm.VersionID.LIVE);\n        bgRealm.beginTransaction();\n        bgRealm.createTable(\"NewTable\");\n        bgRealm.commitTransaction();\n        bgRealm.close();\n\n        // Refresh existing instance\n        sharedRealm.refresh();\n        assertTrue(sharedRealm.hasTable(\"NewTable\"));\n        assertTrue(listenerCalled.get());\n    }\n\n    @Test\n    public void isClosed() {\n        sharedRealm.close();\n        assertTrue(sharedRealm.isClosed());\n        sharedRealm = null;\n    }\n\n    @Test\n    public void close_twice() {\n        sharedRealm.close();\n        sharedRealm.close();\n        assertTrue(sharedRealm.isClosed());\n        sharedRealm = null;\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/internal/PrimaryKeyTests.java",
    "content": "/*\n * Copyright 2016 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\npackage io.realm.internal;\n\nimport androidx.test.ext.junit.runners.AndroidJUnit4;\n\nimport org.bson.types.ObjectId;\nimport org.junit.After;\nimport org.junit.Before;\nimport org.junit.Rule;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\n\nimport java.util.Date;\n\nimport io.realm.DynamicRealm;\nimport io.realm.DynamicRealmObject;\nimport io.realm.FieldAttribute;\nimport io.realm.RealmConfiguration;\nimport io.realm.RealmFieldType;\nimport io.realm.RealmObjectSchema;\nimport io.realm.RealmSchema;\nimport io.realm.TestRealmConfigurationFactory;\n\nimport static org.junit.Assert.assertEquals;\nimport static org.junit.Assert.assertNull;\nimport static org.junit.Assert.assertTrue;\nimport static org.junit.Assert.fail;\n\n@RunWith(AndroidJUnit4.class)\npublic class PrimaryKeyTests {\n\n    @Rule\n    public final TestRealmConfigurationFactory configFactory = new TestRealmConfigurationFactory();\n\n    private RealmConfiguration config;\n    private OsSharedRealm sharedRealm;\n\n    @Before\n    public void setUp() {\n        config = configFactory.createConfiguration();\n    }\n\n    @After\n    public void tearDown() {\n        if (sharedRealm != null && !sharedRealm.isClosed()) {\n            sharedRealm.close();\n        }\n    }\n\n    private Table getTableWithStringPrimaryKey() {\n        sharedRealm = OsSharedRealm.getInstance(config, OsSharedRealm.VersionID.LIVE);\n        sharedRealm.beginTransaction();\n        OsObjectStore.setSchemaVersion(sharedRealm,0); // Create meta table\n        Table t = sharedRealm.createTable(Table.getTableNameForClass(\"TestTable\"));\n        long column = t.addColumn(RealmFieldType.STRING, \"colName\", true);\n        t.addSearchIndex(column);\n        OsObjectStore.setPrimaryKeyForObject(sharedRealm, \"TestTable\", \"colName\");\n        return t;\n    }\n\n    private Table getTableWithIntegerPrimaryKey() {\n        sharedRealm = OsSharedRealm.getInstance(config, OsSharedRealm.VersionID.LIVE);\n        sharedRealm.beginTransaction();\n        OsObjectStore.setSchemaVersion(sharedRealm,0); // Create meta table\n        Table t = sharedRealm.createTable(Table.getTableNameForClass(\"TestTable\"));\n        long column = t.addColumn(RealmFieldType.INTEGER, \"colName\");\n        t.addSearchIndex(column);\n        OsObjectStore.setPrimaryKeyForObject(sharedRealm, \"TestTable\", \"colName\");\n        return t;\n    }\n\n    private Table getTableWithPrimaryKey(RealmFieldType fieldType, boolean isNullable) {\n        OsObjectStore.setSchemaVersion(sharedRealm,0); // Create meta table\n        return sharedRealm.createTableWithPrimaryKey(Table.getTableNameForClass(\"TestTable\"), \"colName\", fieldType, isNullable);\n    }\n\n    /**\n     * This test surfaces a bunch of problems, most of them seem to be around caching of the schema\n     * during a transaction\n     *\n     * 1) Removing the primary key do not invalidate the cache in RealmSchema and those cached\n     *    are ImmutableRealmObjectSchema so do not change when the primary key is removed.\n     *\n     * 2) Addding `schema.refresh()` to RealmObjectSchema.removePrimaryKey()` causes\n     *    RealmPrimaryKeyConstraintException anyway. Unclear why.\n     */\n    @Test\n    public void removingPrimaryKeyRemovesConstraint_typeSetters() {\n        RealmConfiguration config = configFactory.createConfigurationBuilder()\n                .name(\"removeConstraints\").build();\n\n        DynamicRealm realm = DynamicRealm.getInstance(config);\n        RealmSchema realmSchema = realm.getSchema();\n        realm.beginTransaction();\n        RealmObjectSchema tableSchema = realmSchema.create(\"Employee\")\n                .addField(\"name\", String.class, FieldAttribute.PRIMARY_KEY);\n\n        realm.createObject(\"Employee\", \"Foo\");\n        DynamicRealmObject obj = realm.createObject(\"Employee\", \"Foo2\");\n\n        try {\n            // Tries to create 2nd entry with name Foo.\n            obj.setString(\"name\", \"Foo\");\n        } catch (IllegalArgumentException e) {\n            tableSchema.removePrimaryKey();\n            obj.setString(\"name\", \"Foo\");\n        } finally {\n            realm.close();\n        }\n    }\n\n    @Test\n    public void addEmptyRowWithPrimaryKeyWrongTypeStringThrows() {\n        Table t = getTableWithStringPrimaryKey();\n        try {\n            OsObject.createWithPrimaryKey(t, 42);\n            fail();\n        } catch (IllegalArgumentException ignored) {\n        }\n        sharedRealm.cancelTransaction();\n    }\n\n    @Test\n    public void addEmptyRowWithPrimaryKeyNullString() {\n        Table t = getTableWithStringPrimaryKey();\n        OsObject.createWithPrimaryKey(t, null);\n        assertEquals(1, t.size());\n        sharedRealm.cancelTransaction();\n    }\n\n    @Test\n    public void addEmptyRowWithPrimaryKeyWrongTypeIntegerThrows() {\n        Table t = getTableWithIntegerPrimaryKey();\n        try {\n            OsObject.createWithPrimaryKey(t, \"Foo\");\n            fail();\n        } catch (IllegalArgumentException ignored) {\n        }\n        sharedRealm.cancelTransaction();\n    }\n\n    @Test\n    public void addEmptyRowWithPrimaryKeyString() {\n        Table t = getTableWithStringPrimaryKey();\n        UncheckedRow row = OsObject.createWithPrimaryKey(t, \"Foo\");\n        assertEquals(1, t.size());\n        assertEquals(\"Foo\", row.getString(row.getColumnKey(\"colName\")));\n        sharedRealm.cancelTransaction();\n    }\n\n    @Test\n    public void addEmptyRowWithPrimaryKeyLong() {\n        Table t = getTableWithIntegerPrimaryKey();\n        UncheckedRow row = OsObject.createWithPrimaryKey(t, 42);\n        assertEquals(1, t.size());\n        assertEquals(42L, row.getLong(row.getColumnKey(\"colName\")));\n        sharedRealm.cancelTransaction();\n    }\n\n    @Test\n    public void createTableWithIntegerPrimaryKeyNullable(){\n        sharedRealm = OsSharedRealm.getInstance(config, OsSharedRealm.VersionID.LIVE);\n        sharedRealm.beginTransaction();\n\n        Table t = getTableWithPrimaryKey(RealmFieldType.INTEGER, true);\n\n        UncheckedRow row = OsObject.createWithPrimaryKey(t, 42);\n        assertEquals(1, t.size());\n        assertEquals(42, row.getLong(row.getColumnKey(\"colName\")));\n\n\n        row = OsObject.createWithPrimaryKey(t, null);\n        assertEquals(2, t.size());\n        assertTrue(row.isNull(row.getColumnKey(\"colName\")));\n\n        sharedRealm.cancelTransaction();\n    }\n\n    @Test\n    public void createTableWithStringPrimaryKeyNullable(){\n        sharedRealm = OsSharedRealm.getInstance(config, OsSharedRealm.VersionID.LIVE);\n        sharedRealm.beginTransaction();\n\n        Table t = getTableWithPrimaryKey(RealmFieldType.STRING, true);\n\n        UncheckedRow row = OsObject.createWithPrimaryKey(t, \"Foo\");\n        assertEquals(1, t.size());\n        assertEquals(\"Foo\", row.getString(row.getColumnKey(\"colName\")));\n\n        row = OsObject.createWithPrimaryKey(t, null);\n        assertEquals(2, t.size());\n        assertTrue(row.isNull(row.getColumnKey(\"colName\")));\n\n        sharedRealm.cancelTransaction();\n    }\n\n    @Test\n    public void createTableWithObjectIdPrimaryKeyNullable(){\n        sharedRealm = OsSharedRealm.getInstance(config, OsSharedRealm.VersionID.LIVE);\n        sharedRealm.beginTransaction();\n\n        Table t = getTableWithPrimaryKey(RealmFieldType.OBJECT_ID, true);\n\n        Date date = new Date();\n\n        UncheckedRow row = OsObject.createWithPrimaryKey(t, new ObjectId(date, 0));\n        assertEquals(1, t.size());\n        assertEquals(new ObjectId(date, 0), row.getObjectId(row.getColumnKey(\"colName\")));\n\n        row = OsObject.createWithPrimaryKey(t, null);\n        assertEquals(2, t.size());\n        assertTrue(row.isNull(row.getColumnKey(\"colName\")));\n\n        sharedRealm.cancelTransaction();\n    }\n\n    @Test\n    public void createTableWithIntegerPrimaryKey(){\n        sharedRealm = OsSharedRealm.getInstance(config, OsSharedRealm.VersionID.LIVE);\n        sharedRealm.beginTransaction();\n\n        Table t = getTableWithPrimaryKey(RealmFieldType.INTEGER, false);\n\n        UncheckedRow row = OsObject.createWithPrimaryKey(t, 42);\n        assertEquals(1, t.size());\n        assertEquals(42, row.getLong(row.getColumnKey(\"colName\")));\n\n        try {\n            OsObject.createWithPrimaryKey(t, null);\n            fail(\"Non-nullable primary key created with a null value.\");\n        } catch (IllegalArgumentException e){\n            assertEquals(\"Illegal Argument: This field(colName) is not nullable.\", e.getMessage());\n        }\n\n        sharedRealm.cancelTransaction();\n    }\n\n    @Test\n    public void createTableWithStringPrimaryKey(){\n        sharedRealm = OsSharedRealm.getInstance(config, OsSharedRealm.VersionID.LIVE);\n        sharedRealm.beginTransaction();\n\n        Table t = getTableWithPrimaryKey(RealmFieldType.STRING, false);\n\n        UncheckedRow row = OsObject.createWithPrimaryKey(t, \"Foo\");\n        assertEquals(1, t.size());\n        assertEquals(\"Foo\", row.getString(row.getColumnKey(\"colName\")));\n\n        try {\n            OsObject.createWithPrimaryKey(t, null);\n            fail(\"Non-nullable primary key created with a null value.\");\n        } catch (IllegalArgumentException e){\n            assertEquals(\"Illegal Argument: This field(colName) is not nullable.\", e.getMessage());\n        }\n\n        sharedRealm.cancelTransaction();\n    }\n\n    @Test\n    public void createTableWithObjectIdPrimaryKey(){\n        sharedRealm = OsSharedRealm.getInstance(config, OsSharedRealm.VersionID.LIVE);\n        sharedRealm.beginTransaction();\n\n        Table t = getTableWithPrimaryKey(RealmFieldType.OBJECT_ID, false);\n\n        Date date = new Date();\n\n        UncheckedRow row = OsObject.createWithPrimaryKey(t, new ObjectId(date, 0));\n        assertEquals(1, t.size());\n        assertEquals(new ObjectId(date, 0), row.getObjectId(row.getColumnKey(\"colName\")));\n\n        try {\n            OsObject.createWithPrimaryKey(t, null);\n            fail(\"Non-nullable primary key created with a null value.\");\n        } catch (IllegalArgumentException e){\n            assertEquals(\"Illegal Argument: This field(colName) is not nullable.\", e.getMessage());\n        }\n\n        sharedRealm.cancelTransaction();\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/internal/RealmNotifierTests.java",
    "content": "/*\n * Copyright 2017 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 */\npackage io.realm.internal;\n\n\nimport static junit.framework.Assert.assertEquals;\nimport static junit.framework.Assert.assertFalse;\nimport static junit.framework.Assert.fail;\nimport static org.junit.Assert.assertTrue;\n\nimport androidx.test.ext.junit.runners.AndroidJUnit4;\n\nimport org.junit.After;\nimport org.junit.Before;\nimport org.junit.Rule;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\n\nimport java.util.UUID;\nimport java.util.concurrent.atomic.AtomicBoolean;\nimport java.util.concurrent.atomic.AtomicInteger;\n\nimport javax.annotation.Nullable;\n\nimport io.realm.RealmChangeListener;\nimport io.realm.RealmConfiguration;\nimport io.realm.TestRealmConfigurationFactory;\nimport io.realm.internal.android.AndroidRealmNotifier;\nimport io.realm.rule.BlockingLooperThread;\n\n@RunWith(AndroidJUnit4.class)\npublic class RealmNotifierTests {\n    @Rule\n    public final TestRealmConfigurationFactory configFactory = new TestRealmConfigurationFactory();\n\n    private final BlockingLooperThread looperThread = new BlockingLooperThread();\n\n    private RealmConfiguration realmConfig;\n\n    private Capabilities capabilitiesCanDeliver = new Capabilities() {\n        @Override\n        public boolean canDeliverNotification() {\n            return true;\n        }\n\n        @Override\n        public void checkCanDeliverNotification(@Nullable String exceptionMessage) {\n        }\n\n        @Override\n        public boolean isMainThread() {\n            return false;\n        }\n    };\n\n    @Before\n    public void setUp() throws Exception {\n        realmConfig = configFactory.createConfiguration(UUID.randomUUID().toString());\n    }\n\n    @After\n    public void tearDown() {\n    }\n\n    private OsSharedRealm getSharedRealm(RealmConfiguration config) {\n        OsRealmConfig.Builder configBuilder = new OsRealmConfig.Builder(config)\n                .autoUpdateNotification(true);\n        return OsSharedRealm.getInstance(configBuilder, OsSharedRealm.VersionID.LIVE);\n    }\n\n    @Test\n    public void post() {\n        looperThread.runBlocking(() -> {\n            RealmNotifier notifier = new AndroidRealmNotifier(null, capabilitiesCanDeliver);\n            notifier.post(new Runnable() {\n                @Override\n                public void run() {\n                    looperThread.testComplete();\n                }\n            });\n        });\n    }\n\n    // Callback is immediately called when commitTransaction for local changes.\n    @Test\n    public void addChangeListener_byLocalChanges() {\n        looperThread.runBlocking(() -> {\n            final AtomicBoolean commitReturns = new AtomicBoolean(false);\n            OsSharedRealm sharedRealm = getSharedRealm(realmConfig);\n            sharedRealm.realmNotifier.addChangeListener(sharedRealm, new RealmChangeListener<OsSharedRealm>() {\n                @Override\n                public void onChange(OsSharedRealm sharedRealm) {\n                    // Transaction has been committed in core, but commitTransaction hasn't returned in java.\n                    assertFalse(commitReturns.get());\n                    sharedRealm.close();\n                    looperThread.testComplete();\n                }\n            });\n            sharedRealm.beginTransaction();\n            sharedRealm.commitTransaction();\n            commitReturns.set(true);\n        });\n    }\n\n    private void makeRemoteChanges(final RealmConfiguration config) {\n        // We don't use cache from RealmCoordinator\n        OsSharedRealm sharedRealm = getSharedRealm(config);\n        sharedRealm.beginTransaction();\n        sharedRealm.commitTransaction();\n        sharedRealm.close();\n    }\n\n    @Test\n    public void addChangeListener_byRemoteChanges() {\n        looperThread.runBlocking(() -> {\n            // To catch https://github.com/realm/realm-java/pull/4037 CI failure.\n            // In this case, object store should not send more than 100 notifications.\n            final int TIMES = 100;\n            final AtomicInteger commitCounter = new AtomicInteger(0);\n            final AtomicInteger listenerCounter = new AtomicInteger(0);\n\n            OsSharedRealm sharedRealm = getSharedRealm(realmConfig);\n            looperThread.keepStrongReference(sharedRealm);\n            sharedRealm.realmNotifier.addChangeListener(sharedRealm, new RealmChangeListener<OsSharedRealm>() {\n                @Override\n                public void onChange(OsSharedRealm sharedRealm) {\n                    int commits = commitCounter.get();\n                    int listenerCount = listenerCounter.addAndGet(1);\n                    assertEquals(commits, listenerCount);\n                    if (commits == TIMES) {\n                        sharedRealm.close();\n                        looperThread.testComplete();\n                    } else {\n                        makeRemoteChanges(realmConfig);\n                        commitCounter.getAndIncrement();\n                    }\n                }\n            });\n            makeRemoteChanges(realmConfig);\n            commitCounter.getAndIncrement();\n        });\n    }\n\n    // Ensure that exceptions in changelisteners do not cause native crashes, but instead\n    // propagate correctly to end users\n    @Test\n    public void addChangeListener_exceptionsPropagateCorrectly() {\n        try {\n            looperThread.runBlocking(() -> {\n                OsSharedRealm sharedRealm = getSharedRealm(realmConfig);\n                looperThread.closeAfterTest(sharedRealm);\n                sharedRealm.realmNotifier.addChangeListener(sharedRealm, new RealmChangeListener<OsSharedRealm>() {\n                    @Override\n                    public void onChange(OsSharedRealm sharedRealm) {\n                        throw new RuntimeException(\"BOOM\");\n                    }\n                });\n                makeRemoteChanges(realmConfig);\n            });\n            fail();\n        } catch (RuntimeException ex) {\n            assertTrue(ex.getMessage().contains(\"BOOM\"));\n        }\n    }\n\n    @Test\n    public void removeChangeListeners() {\n        looperThread.runBlocking(() -> {\n            OsSharedRealm sharedRealm = getSharedRealm(realmConfig);\n            Integer dummyObserver = 1;\n            looperThread.keepStrongReference(dummyObserver);\n            looperThread.keepStrongReference(sharedRealm);\n            sharedRealm.realmNotifier.addChangeListener(dummyObserver, new RealmChangeListener<Integer>() {\n                @Override\n                public void onChange(Integer dummy) {\n                    fail();\n                }\n            });\n            sharedRealm.realmNotifier.addChangeListener(sharedRealm, new RealmChangeListener<OsSharedRealm>() {\n                @Override\n                public void onChange(OsSharedRealm sharedRealm) {\n                    sharedRealm.close();\n                    looperThread.testComplete();\n                }\n            });\n\n            // This should only remove the listeners related with dummyObserver\n            sharedRealm.realmNotifier.removeChangeListeners(dummyObserver);\n\n            makeRemoteChanges(realmConfig);\n        });\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/internal/TableIndexAndDistinctTest.java",
    "content": "/*\n * Copyright 2015 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\npackage io.realm.internal;\n\nimport androidx.test.platform.app.InstrumentationRegistry;\nimport androidx.test.ext.junit.runners.AndroidJUnit4;\n\nimport org.junit.After;\nimport org.junit.Before;\nimport org.junit.Rule;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\n\nimport io.realm.Realm;\nimport io.realm.RealmConfiguration;\nimport io.realm.RealmFieldType;\nimport io.realm.TestHelper;\nimport io.realm.TestRealmConfigurationFactory;\n\nimport static org.junit.Assert.assertEquals;\n\n\n@RunWith(AndroidJUnit4.class)\npublic class TableIndexAndDistinctTest {\n\n    @Rule\n    public final TestRealmConfigurationFactory configFactory = new TestRealmConfigurationFactory();\n\n    @SuppressWarnings(\"FieldCanBeLocal\")\n    private RealmConfiguration config;\n    private OsSharedRealm sharedRealm;\n    private Table table;\n\n    private long colKey1;\n    private long colKey2;\n\n    @Before\n    public void setUp() throws Exception {\n        Realm.init(InstrumentationRegistry.getInstrumentation().getContext());\n        config = configFactory.createConfiguration();\n        sharedRealm = OsSharedRealm.getInstance(config, OsSharedRealm.VersionID.LIVE);\n\n        sharedRealm.beginTransaction();\n    }\n\n    @After\n    public void tearDown() {\n        if (sharedRealm != null && sharedRealm.isInTransaction()) {\n            sharedRealm.cancelTransaction();\n        }\n\n        if (sharedRealm != null && !sharedRealm.isClosed()) {\n            sharedRealm.close();\n        }\n    }\n\n    private void init() {\n        table = TestHelper.createTable(sharedRealm, \"temp\", new TestHelper.AdditionalTableSetup() {\n            @Override\n            public void execute(Table table) {\n                colKey1 = table.addColumn(RealmFieldType.INTEGER, \"number\");\n                colKey2 = table.addColumn(RealmFieldType.STRING, \"name\");\n\n                TestHelper.addRowWithValues(table, new long[]{colKey1, colKey2}, new Object[]{0, \"A\"});\n                TestHelper.addRowWithValues(table, new long[]{colKey1, colKey2}, new Object[]{1, \"B\"});\n                TestHelper.addRowWithValues(table, new long[]{colKey1, colKey2}, new Object[]{2, \"C\"});\n                TestHelper.addRowWithValues(table, new long[]{colKey1, colKey2}, new Object[]{3, \"B\"});\n                TestHelper.addRowWithValues(table, new long[]{colKey1, colKey2}, new Object[]{4, \"D\"});\n                TestHelper.addRowWithValues(table, new long[]{colKey1, colKey2}, new Object[]{5, \"D\"});\n                TestHelper.addRowWithValues(table, new long[]{colKey1, colKey2}, new Object[]{6, \"D\"});\n            }\n        });\n\n        assertEquals(7, table.size());\n    }\n\n    /**\n     * Checks that Index can be set on multiple columns, with the String.\n     * @param\n     */\n    @Test\n    public void shouldTestSettingIndexOnMultipleColumns() {\n        long[] columnsKey = new long[5];\n        // Creates a table only with String type columns\n        Table t = TestHelper.createTable(sharedRealm, \"temp\", new TestHelper.AdditionalTableSetup() {\n            @Override\n            public void execute(Table t) {\n                columnsKey[0] = t.addColumn(RealmFieldType.STRING, \"col1\");\n                columnsKey[1] = t.addColumn(RealmFieldType.STRING, \"col2\");\n                columnsKey[2] = t.addColumn(RealmFieldType.STRING, \"col3\");\n                columnsKey[3] = t.addColumn(RealmFieldType.STRING, \"col4\");\n                columnsKey[4] = t.addColumn(RealmFieldType.STRING, \"col5\");\n\n                TestHelper.addRowWithValues(t, columnsKey, new Object[]{\"row1\", \"row2\", \"row3\", \"row4\", \"row5\"});\n                TestHelper.addRowWithValues(t, columnsKey, new Object[]{\"row1\", \"row2\", \"row3\", \"row4\", \"row5\"});\n                TestHelper.addRowWithValues(t, columnsKey, new Object[]{\"row1\", \"row2\", \"row3\", \"row4\", \"row5\"});\n                TestHelper.addRowWithValues(t, columnsKey, new Object[]{\"row1\", \"row2\", \"row3\", \"row4\", \"row5\"});\n                TestHelper.addRowWithValues(t, columnsKey, new Object[]{\"row1\", \"row2\", \"row3\", \"row4\", \"row5\"});\n            }\n        });\n\n        for (int i = 0; i < columnsKey.length; i++) {\n            t.addSearchIndex(columnsKey[i]);\n            assertEquals(true, t.hasSearchIndex(columnsKey[i]));\n        }\n\n    }\n\n\n// TODO: parametric test\n/*    *//**\n     * Checks that all other column types than String throws exception.\n     *//*\n\n    @Test(expectedExceptions = IllegalArgumentException.class, dataProvider = \"columnIndex\")\n    public void shouldTestIndexOnWrongColumnType(Long index) {\n\n        // Gets a table with all available column types.\n        Table t = TestHelper.createTableWithAllColumnTypes(sharedRealm);\n\n        // If column type is String, then throw the excepted exception.\n        if (t.getColumnType(index).equals(RealmFieldType.STRING)){\n            throw new IllegalArgumentException();\n        }\n\n        t.addSearchIndex(index);\n    }*/\n\n    @Test\n    public void shouldCheckIndexIsOkOnColumn() {\n        init();\n        table.addSearchIndex(colKey1);\n    }\n\n    @Test\n    public void removeSearchIndex() {\n        init();\n        table.addSearchIndex(colKey1);\n        assertEquals(true, table.hasSearchIndex(colKey1));\n\n        table.removeSearchIndex(colKey1);\n        assertEquals(false, table.hasSearchIndex(colKey1));\n    }\n\n    @Test\n    public void removeSearchIndexNoOp() {\n        init();\n        assertEquals(false, table.hasSearchIndex(colKey1));\n\n        // Removes index from non-indexed column is a no-op.\n        table.removeSearchIndex(colKey1);\n        assertEquals(false, table.hasSearchIndex(colKey1));\n    }\n}\n\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/internal/android/ISO8601UtilsTest.java",
    "content": "/*\n * Copyright 2015 FasterXML\n * Copyright 2015 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 */\npackage io.realm.internal.android;\n\nimport androidx.test.ext.junit.runners.AndroidJUnit4;\n\nimport org.junit.Before;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\n\nimport java.text.ParseException;\nimport java.text.ParsePosition;\nimport java.util.Calendar;\nimport java.util.Date;\nimport java.util.GregorianCalendar;\nimport java.util.TimeZone;\nimport java.util.concurrent.TimeUnit;\n\nimport static org.junit.Assert.assertEquals;\nimport static org.junit.Assert.fail;\n\n/**\n * @see ISO8601Utils\n * @see <a href=\"https://github.com/FasterXML/jackson-databind/blob/master/src/test/java/com/fasterxml/jackson/databind/util/ISO8601UtilsTest.java\">Original Source</a>\n */\n@RunWith(AndroidJUnit4.class)\npublic class ISO8601UtilsTest {\n    private Date date;\n    private Date dateWithoutTime;\n    private Date dateZeroMillis;\n    private Date dateZeroSecondAndMillis;\n\n    @Before\n    public void setUp() {\n        Calendar cal = new GregorianCalendar(2007, 8 - 1, 13, 19, 51, 23);\n        cal.setTimeZone(TimeZone.getTimeZone(\"GMT\"));\n        cal.set(Calendar.MILLISECOND, 789);\n        date = cal.getTime();\n        cal.set(Calendar.MILLISECOND, 0);\n        dateZeroMillis = cal.getTime();\n        cal.set(Calendar.SECOND, 0);\n        dateZeroSecondAndMillis = cal.getTime();\n\n        cal = new GregorianCalendar(2007, 8 - 1, 13, 0, 0, 0);\n        cal.set(Calendar.MILLISECOND, 0);\n        cal.setTimeZone(TimeZone.getTimeZone(\"GMT\"));\n        dateWithoutTime = cal.getTime();\n\n    }\n\n    @Test\n    public void parse() throws java.text.ParseException {\n        Date d = ISO8601Utils.parse(\"2007-08-13T19:51:23.789Z\", new ParsePosition(0));\n        assertEquals(date, d);\n\n        d = ISO8601Utils.parse(\"2007-08-13T19:51:23Z\", new ParsePosition(0));\n        assertEquals(dateZeroMillis, d);\n\n        d = ISO8601Utils.parse(\"2007-08-13T21:51:23.789+02:00\", new ParsePosition(0));\n        assertEquals(date, d);\n    }\n\n    @Test\n    public void parseShortDate() throws java.text.ParseException {\n        Date d = ISO8601Utils.parse(\"20070813T19:51:23.789Z\", new ParsePosition(0));\n        assertEquals(date, d);\n\n        d = ISO8601Utils.parse(\"20070813T19:51:23Z\", new ParsePosition(0));\n        assertEquals(dateZeroMillis, d);\n\n        d = ISO8601Utils.parse(\"20070813T21:51:23.789+02:00\", new ParsePosition(0));\n        assertEquals(date, d);\n    }\n\n    @Test\n    public void parseShortTime() throws java.text.ParseException {\n        Date d = ISO8601Utils.parse(\"2007-08-13T195123.789Z\", new ParsePosition(0));\n        assertEquals(date, d);\n\n        d = ISO8601Utils.parse(\"2007-08-13T195123Z\", new ParsePosition(0));\n        assertEquals(dateZeroMillis, d);\n\n        d = ISO8601Utils.parse(\"2007-08-13T215123.789+02:00\", new ParsePosition(0));\n        assertEquals(date, d);\n    }\n\n    @Test\n    public void parseShortDateTime() throws java.text.ParseException {\n        Date d = ISO8601Utils.parse(\"20070813T195123.789Z\", new ParsePosition(0));\n        assertEquals(date, d);\n\n        d = ISO8601Utils.parse(\"20070813T195123Z\", new ParsePosition(0));\n        assertEquals(dateZeroMillis, d);\n\n        d = ISO8601Utils.parse(\"20070813T215123.789+02:00\", new ParsePosition(0));\n        assertEquals(date, d);\n    }\n\n    @Test\n    public void parseWithoutTime() throws ParseException {\n        Date d = ISO8601Utils.parse(\"2007-08-13Z\", new ParsePosition(0));\n        assertEquals(dateWithoutTime, d);\n\n        d = ISO8601Utils.parse(\"20070813Z\", new ParsePosition(0));\n        assertEquals(dateWithoutTime, d);\n\n        d = ISO8601Utils.parse(\"2007-08-13+00:00\", new ParsePosition(0));\n        assertEquals(dateWithoutTime, d);\n\n        d = ISO8601Utils.parse(\"20070813+00:00\", new ParsePosition(0));\n        assertEquals(dateWithoutTime, d);\n    }\n\n    @Test\n    public void parseOptional() throws java.text.ParseException {\n        Date d = ISO8601Utils.parse(\"2007-08-13T19:51Z\", new ParsePosition(0));\n        assertEquals(dateZeroSecondAndMillis, d);\n\n        d = ISO8601Utils.parse(\"2007-08-13T1951Z\", new ParsePosition(0));\n        assertEquals(dateZeroSecondAndMillis, d);\n\n        d = ISO8601Utils.parse(\"2007-08-13T21:51+02:00\", new ParsePosition(0));\n        assertEquals(dateZeroSecondAndMillis, d);\n    }\n\n    @Test\n    public void timeZoneDesignator() throws java.text.ParseException {\n        Date d = ISO8601Utils.parse(\"2007-08-13T21:51+02:00\", new ParsePosition(0));\n        assertEquals(dateZeroSecondAndMillis, d);\n\n        d = ISO8601Utils.parse(\"2007-08-13T21:51+0200\", new ParsePosition(0));\n        assertEquals(dateZeroSecondAndMillis, d);\n\n        d = ISO8601Utils.parse(\"2007-08-13T21:51+02\", new ParsePosition(0));\n        assertEquals(dateZeroSecondAndMillis, d);\n    }\n\n    @Test\n    public void parseRfc3339Examples() throws java.text.ParseException {\n        // Two digit milliseconds.\n        Date d = ISO8601Utils.parse(\"1985-04-12T23:20:50.52Z\", new ParsePosition(0));\n        assertEquals(newDate(1985, 4, 12, 23, 20, 50, 520, 0), d);\n\n        d = ISO8601Utils.parse(\"1996-12-19T16:39:57-08:00\", new ParsePosition(0));\n        assertEquals(newDate(1996, 12, 19, 16, 39, 57, 0, -8 * 60), d);\n\n        // Truncated leap second.\n        d = ISO8601Utils.parse(\"1990-12-31T23:59:60Z\", new ParsePosition(0));\n        assertEquals(newDate(1990, 12, 31, 23, 59, 59, 0, 0), d);\n\n        // Truncated leap second.\n        d = ISO8601Utils.parse(\"1990-12-31T15:59:60-08:00\", new ParsePosition(0));\n        assertEquals(newDate(1990, 12, 31, 15, 59, 59, 0, -8 * 60), d);\n\n        // Two digit milliseconds.\n        d = ISO8601Utils.parse(\"1937-01-01T12:00:27.87+00:20\", new ParsePosition(0));\n        assertEquals(newDate(1937, 1, 1, 12, 0, 27, 870, 20), d);\n    }\n\n    @Test\n    public void fractionalSeconds() throws java.text.ParseException {\n        Date d = ISO8601Utils.parse(\"1970-01-01T00:00:00.9Z\", new ParsePosition(0));\n        assertEquals(newDate(1970, 1, 1, 0, 0, 0, 900, 0), d);\n\n        d = ISO8601Utils.parse(\"1970-01-01T00:00:00.09Z\", new ParsePosition(0));\n        assertEquals(newDate(1970, 1, 1, 0, 0, 0, 90, 0), d);\n\n        d = ISO8601Utils.parse(\"1970-01-01T00:00:00.009Z\", new ParsePosition(0));\n        assertEquals(newDate(1970, 1, 1, 0, 0, 0, 9, 0), d);\n\n        d = ISO8601Utils.parse(\"1970-01-01T00:00:00.0009Z\", new ParsePosition(0));\n        assertEquals(newDate(1970, 1, 1, 0, 0, 0, 0, 0), d);\n\n        d = ISO8601Utils.parse(\"1970-01-01T00:00:00.2147483647Z\", new ParsePosition(0));\n        assertEquals(newDate(1970, 1, 1, 0, 0, 0, 214, 0), d);\n\n        d = ISO8601Utils.parse(\"1970-01-01T00:00:00.2147483648Z\", new ParsePosition(0));\n        assertEquals(newDate(1970, 1, 1, 0, 0, 0, 214, 0), d);\n\n        d = ISO8601Utils.parse(\"1970-01-01T00:00:00.9+02:00\", new ParsePosition(0));\n        assertEquals(newDate(1970, 1, 1, 0, 0, 0, 900, 2 * 60), d);\n\n        d = ISO8601Utils.parse(\"1970-01-01T00:00:00.09+02:00\", new ParsePosition(0));\n        assertEquals(newDate(1970, 1, 1, 0, 0, 0, 90, 2 * 60), d);\n\n        d = ISO8601Utils.parse(\"1970-01-01T00:00:00.009+02:00\", new ParsePosition(0));\n        assertEquals(newDate(1970, 1, 1, 0, 0, 0, 9, 2 * 60), d);\n\n        d = ISO8601Utils.parse(\"1970-01-01T00:00:00.0009+02:00\", new ParsePosition(0));\n        assertEquals(newDate(1970, 1, 1, 0, 0, 0, 0, 2 * 60), d);\n\n        d = ISO8601Utils.parse(\"1970-01-01T00:00:00.2147483648+02:00\", new ParsePosition(0));\n        assertEquals(newDate(1970, 1, 1, 0, 0, 0, 214, 2 * 60), d);\n    }\n\n    @Test\n    public void decimalWithoutDecimalPointButNoFractionalSeconds() throws java.text.ParseException {\n        try {\n            ISO8601Utils.parse(\"1970-01-01T00:00:00.Z\", new ParsePosition(0));\n            fail();\n        } catch (ParseException expected) {\n        }\n    }\n\n    private Date newDate(int year, int month, int day, int hour,\n                         int minute, int second, int millis, int timezoneOffsetMinutes) {\n        Calendar calendar = new GregorianCalendar(TimeZone.getTimeZone(\"GMT\"));\n        calendar.set(year, month - 1, day, hour, minute, second);\n        calendar.set(Calendar.MILLISECOND, millis);\n        return new Date(calendar.getTimeInMillis() - TimeUnit.MINUTES.toMillis(timezoneOffsetMinutes));\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/internal/android/JsonUtilsTest.java",
    "content": "/*\n * Copyright 2015 FasterXML\n * Copyright 2015 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 */\npackage io.realm.internal.android;\n\nimport androidx.test.ext.junit.runners.AndroidJUnit4;\n\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\n\nimport java.text.ParseException;\nimport java.util.Calendar;\nimport java.util.Date;\nimport java.util.GregorianCalendar;\nimport java.util.TimeZone;\n\nimport io.realm.exceptions.RealmException;\n\nimport static org.junit.Assert.assertEquals;\nimport static org.junit.Assert.assertNotNull;\nimport static org.junit.Assert.assertNull;\nimport static org.junit.Assert.assertTrue;\nimport static org.junit.Assert.fail;\n\n@RunWith(AndroidJUnit4.class)\npublic class JsonUtilsTest {\n\n    @Test\n    public void parseNullAndEmptyDateIsNull() {\n        Date output = JsonUtils.stringToDate(null);\n        assertNull(\"Null input should output a null date object\", output);\n\n        output = JsonUtils.stringToDate(\"\");\n        assertNull(\"Empty string input should output a null date object\", output);\n    }\n\n    @Test\n    public void parseMillisToDate() {\n        Date originalDate = Calendar.getInstance().getTime();\n        long dateTimeInMillis = originalDate.getTime();\n        Date output = JsonUtils.stringToDate(String.valueOf(dateTimeInMillis));\n\n        assertTrue(\"Dates should match\", output.equals(originalDate));\n    }\n\n    @Test\n    public void parseJsonDateToDate() {\n        String jsonDate = \"/Date(1198908717056)/\"; // 2007-12-27T23:11:57.056\n        Date output = JsonUtils.stringToDate(jsonDate);\n\n        assertEquals(1198908717056L, output.getTime());\n    }\n\n    @Test\n    public void negativeLongDate() {\n        long timeInMillis = -631152000L; // Jan 1, 1950\n        Date output = JsonUtils.stringToDate(String.valueOf(timeInMillis));\n\n        assertEquals(\"Should be Jan 1, 1950 in millis\", timeInMillis, output.getTime());\n    }\n\n    @Test\n    public void parseInvalidDateShouldThrowRealmException() {\n        String invalidLongDate = \"123abc\";\n        try {\n            Date d = JsonUtils.stringToDate(invalidLongDate);\n            fail(\"Should fail with a RealmException.\");\n        } catch (RealmException e) {\n            assertNotNull(e);\n            assertTrue(e.getCause() instanceof ParseException);\n        }\n    }\n\n    @Test\n    public void parseInvalidNumericDateShouldThrowRealmException() {\n        String invalidLongDate = \"2342347289374398342759873495743\"; // not a date.\n        try {\n            Date d = JsonUtils.stringToDate(invalidLongDate);\n            fail(\"Should fail with a RealmException.\");\n        } catch (RealmException e) {\n            assertNotNull(e);\n            assertTrue(e.getCause() instanceof NumberFormatException);\n        }\n    }\n\n    @Test\n    public void parseISO8601Dates() throws ParseException {\n        Calendar cal = new GregorianCalendar(2007, 8 - 1, 13, 19, 51, 23);\n        cal.setTimeZone(TimeZone.getTimeZone(\"GMT\"));\n        cal.set(Calendar.MILLISECOND, 789);\n        Date date = cal.getTime();\n        cal.set(Calendar.MILLISECOND, 0);\n        Date dateZeroMillis = cal.getTime();\n        cal.set(Calendar.SECOND, 0);\n\n        // Parses date with short time and decimal second.\n        Date d = JsonUtils.stringToDate(\"2007-08-13T195123.789Z\");\n        assertEquals(date, d);\n\n        // Short time without decimal second.\n        d = JsonUtils.stringToDate(\"2007-08-13T195123Z\");\n        assertEquals(dateZeroMillis, d);\n\n        // GMT+2 with decimal second.\n        d = JsonUtils.stringToDate(\"2007-08-13T215123.789+02:00\");\n        assertEquals(date, d);\n\n        // Tests without time.\n        cal = new GregorianCalendar(2007, 8 - 1, 13, 0, 0, 0);\n        cal.set(Calendar.MILLISECOND, 0);\n        cal.setTimeZone(TimeZone.getTimeZone(\"GMT\"));\n        Date dateWithoutTime = cal.getTime();\n\n        // Date only with hyphens.\n        d = JsonUtils.stringToDate(\"2007-08-13Z\");\n        assertEquals(dateWithoutTime, d);\n\n        // Date, no hyphens.\n        d = JsonUtils.stringToDate(\"20070813Z\");\n        assertEquals(dateWithoutTime, d);\n\n        // Hyphenated Date with empty time.\n        d = JsonUtils.stringToDate(\"2007-08-13+00:00\");\n        assertEquals(dateWithoutTime, d);\n\n        // Non-hyphenated date with empty time.\n        d = JsonUtils.stringToDate(\"20070813+00:00\");\n        assertEquals(dateWithoutTime, d);\n\n        // Please see the ISO8601UtilsTest.java file for a full suite of ISO8601 tests.\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/internal/test/ExtraTests.java",
    "content": "/*\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\npackage io.realm.internal.test;\n\nimport java.lang.reflect.Array;\nimport java.util.ArrayList;\nimport java.util.Date;\nimport java.util.List;\n\nimport static junit.framework.Assert.assertEquals;\nimport static junit.framework.Assert.fail;\n\npublic class ExtraTests {\n\n    public static void assertArrayEquals(Object[] expecteds, Object[] actuals) {\n        new ExactComparisonCriteria().arrayEquals(null, expecteds, actuals);\n    }\n\n    public static void assertArrayEquals(byte[] expecteds, byte[] actuals) {\n        new ExactComparisonCriteria().arrayEquals(null, expecteds, actuals);\n    }\n\n    public static void assertDateArrayEquals(Object[] expecteds, Date[] actuals)\n    {\n        int i=0;\n        for (Date date : actuals) {\n            Date expect = (Date)expecteds[i];\n            assertEquals(expect.getTime()/1000, date.getTime()/1000);\n            i++;\n        }\n    }\n\n    private static class ExactComparisonCriteria extends ComparisonCriteria {\n        @Override\n        protected void assertElementsEqual(Object expected, Object actual)\n        {\n            assertEquals(expected, actual);\n        }\n    }\n\n    private static abstract class ComparisonCriteria {\n        public void arrayEquals(String message, Object expecteds, Object actuals) throws ArrayComparisonFailure\n        {\n            if (expecteds == actuals) return;\n            String header= message == null ? \"\" : message + \": \";\n\n            int expectedsLength= assertArraysAreSameLength(expecteds, actuals, header);\n\n            for (int i= 0; i < expectedsLength; ++i) {\n                Object expected= Array.get(expecteds, i);\n                Object actual= Array.get(actuals, i);\n\n                if (isArray(expected) && isArray(actual)) {\n                    try {\n                        arrayEquals(message, expected, actual);\n                    }\n                    catch (ArrayComparisonFailure e) {\n                        e.addDimension(i);\n                        throw e;\n                    }\n                }\n                else\n                    try {\n                        assertElementsEqual(expected, actual);\n                    }\n                    catch (AssertionError e) {\n                        throw new ArrayComparisonFailure(header, e, i);\n                    }\n            }\n        }\n\n        private boolean isArray(Object expected)\n        {\n            return expected != null && expected.getClass().isArray();\n        }\n\n        private int assertArraysAreSameLength(Object expecteds, Object actuals, String header)\n        {\n            if (expecteds == null)\n                fail(header + \"expected array was null\");\n            if (actuals == null)\n                fail(header + \"actual array was null\");\n            int actualsLength= Array.getLength(actuals);\n            int expectedsLength= Array.getLength(expecteds);\n            if (actualsLength != expectedsLength)\n                fail(header + \"array lengths differed, expected.length=\"\n                                 + expectedsLength + \" actual.length=\" + actualsLength);\n            return expectedsLength;\n        }\n\n        protected abstract void assertElementsEqual(Object expected, Object actual);\n    }\n\n    private static class ArrayComparisonFailure extends AssertionError {\n\n        private static final long serialVersionUID= 1L;\n\n        private List<Integer> fIndices= new ArrayList<Integer>();\n        private final String fMessage;\n        private final AssertionError fCause;\n\n        public ArrayComparisonFailure(String message, AssertionError cause, int index) {\n            fMessage= message;\n            fCause= cause;\n            addDimension(index);\n        }\n\n        public void addDimension(int index) {\n            fIndices.add(0, index);\n        }\n\n        @Override\n        public String getMessage() {\n            StringBuilder builder= new StringBuilder();\n            if (fMessage != null)\n                builder.append(fMessage);\n            builder.append(\"arrays first differed at element \");\n            for (int each : fIndices) {\n                builder.append(\"[\");\n                builder.append(each);\n                builder.append(\"]\");\n            }\n            builder.append(\"; \");\n            builder.append(fCause.getMessage());\n            return builder.toString();\n        }\n\n        @Override public String toString() {\n            return getMessage();\n        }\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/log/RealmLogTests.java",
    "content": "package io.realm.log;\n\nimport androidx.test.platform.app.InstrumentationRegistry;\nimport androidx.test.ext.junit.runners.AndroidJUnit4;\n\nimport org.junit.Before;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\n\nimport io.realm.Realm;\nimport io.realm.TestHelper;\n\nimport static junit.framework.Assert.assertEquals;\nimport static junit.framework.Assert.assertFalse;\nimport static junit.framework.Assert.assertNull;\nimport static junit.framework.Assert.assertTrue;\n\n@RunWith(AndroidJUnit4.class)\npublic class RealmLogTests {\n\n    @Before\n    public void setUp() {\n        Realm.init(InstrumentationRegistry.getInstrumentation().getTargetContext());\n    }\n\n    @Test\n    public void add_remove() {\n        TestHelper.TestLogger testLogger = new TestHelper.TestLogger();\n        RealmLog.add(testLogger);\n        RealmLog.fatal(\"TEST\");\n        RealmLog.remove(testLogger);\n        RealmLog.fatal(\"TEST_AGAIN\");\n    }\n\n    @Test\n    public void set_get_logLevel() {\n        TestHelper.TestLogger testLogger = new TestHelper.TestLogger();\n        RealmLog.add(testLogger);\n\n        RealmLog.setLevel(LogLevel.FATAL);\n        assertEquals(LogLevel.FATAL, RealmLog.getLevel());\n        RealmLog.debug(\"TEST_DEBUG\");\n        assertNull(testLogger.message);\n\n        RealmLog.setLevel(LogLevel.DEBUG);\n        RealmLog.debug(\"TEST_DEBUG\");\n        assertEquals(\"TEST_DEBUG\", testLogger.message);\n        RealmLog.fatal(\"TEST_FATAL\");\n        assertEquals(\"TEST_FATAL\", testLogger.message);\n\n        RealmLog.remove(testLogger);\n    }\n\n    @Test\n    public void clear() {\n        TestHelper.TestLogger testLogger1 = new TestHelper.TestLogger();\n        TestHelper.TestLogger testLogger2 = new TestHelper.TestLogger();\n        RealmLog.add(testLogger1);\n        RealmLog.add(testLogger2);\n        RealmLog.fatal(\"TEST\");\n\n        assertEquals(\"TEST\", testLogger1.message);\n        assertEquals(\"TEST\", testLogger2.message);\n\n        RealmLog.clear();\n\n        RealmLog.fatal(\"TEST_AGAIN\");\n        assertEquals(\"TEST\", testLogger1.message);\n        assertEquals(\"TEST\", testLogger2.message);\n\n        RealmLog.registerDefaultLogger();\n    }\n\n    @Test\n    public void throwable_passedToTheJavaLogger() {\n        TestHelper.TestLogger testLogger = new TestHelper.TestLogger();\n        RealmLog.add(testLogger);\n        Throwable throwable;\n\n        try {\n            throw new RuntimeException(\"Test exception.\");\n        } catch (RuntimeException e) {\n            throwable = e;\n            RealmLog.fatal(e);\n        }\n\n        // Throwable has been passed.\n        assertEquals(throwable, testLogger.throwable);\n        // Message is the stacktrace.\n        assertTrue(testLogger.message.contains(\"RealmLogTests.java\"));\n        RealmLog.remove(testLogger);\n    }\n\n    @Test\n    public void coreLoggerBridge() {\n        TestHelper.TestLogger testLogger = new TestHelper.TestLogger();\n        RealmLog.setLevel(LogLevel.INFO);\n        RealmLog.add(testLogger);\n\n        long ptr = RealmLog.nativeCreateCoreLoggerBridge(\"TEST\");\n        RealmLog.nativeLogToCoreLoggerBridge(ptr, LogLevel.INFO, \"42\");\n        assertTrue(testLogger.message.equals(\"42\"));\n\n        RealmLog.setLevel(LogLevel.FATAL);\n        RealmLog.nativeLogToCoreLoggerBridge(ptr, LogLevel.INFO, \"44\");\n        assertTrue(testLogger.message.equals(\"42\"));\n        assertFalse(testLogger.message.equals(\"44\"));\n        RealmLog.nativeLogToCoreLoggerBridge(ptr, LogLevel.FATAL, \"45\");\n        assertTrue(testLogger.message.equals(\"45\"));\n        RealmLog.nativeCloseCoreLoggerBridge(ptr);\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/migration/MigrationPrimaryKey.java",
    "content": "/*\n * Copyright 2016 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\npackage io.realm.migration;\n\n/**\n * This interface should be used as a stub for dynamically creating the first version of schema.\n * As this is an interface and does not inherit RealmObject, a schema for {@link MigrationPrimaryKey}\n * there does not exist.\n */\npublic interface MigrationPrimaryKey {\n    String CLASS_NAME    = \"MigrationPrimaryKey\";\n\n    String FIELD_FIRST   = \"fieldFirst\";\n    String FIELD_SECOND  = \"fieldSecond\";\n\n    // this is original primary key field name.\n    String FIELD_PRIMARY = \"fieldPrimary\";\n    String FIELD_FOURTH  = \"fieldFourth\";\n    String FIELD_FIFTH   = \"fieldFifth\";\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/util/ExceptionHolder.java",
    "content": "/*\n * Copyright 2016 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\npackage io.realm.util;\n\nimport junit.framework.AssertionFailedError;\n\nimport java.io.PrintWriter;\nimport java.io.StringWriter;\n\nimport static junit.framework.Assert.fail;\n\n/**\n * Utility class for wrapping exceptions from background threads in unit tests.\n * It makes patterns like this possible:\n *\n * {@code\n *   final CountDownLatch taskDone = new CountDownLatch(1);\n *   final ExceptionHolder bgError = new ExceptionHolder();\n *   new Thread(new Runnable() {\n *      @Override\n *      public void run() {\n *          try {\n *              // Error prone code ...\n *          } catch (Exception e) {\n *              bgError.setException(e);\n *          } finall {\n *              taskDone.countDown();\n *          }\n *      }\n *   }).start()\n *   taskDone.await();\n *   bgError.checkFailure();\n * }\n */\npublic class ExceptionHolder {\n\n    private Throwable exception;\n\n    /**\n     * Sets the exception held by this container. This is an one-shot operation.\n     *\n     * @param throwable error to save.\n     * @throws IllegalStateException if an exception have already been put into this holder.\n     */\n    public void setException(Throwable throwable) {\n        if (exception != null) {\n            throw new IllegalStateException(\"An exception has already been set.\");\n        }\n        this.exception = throwable;\n    }\n\n    /**\n     * Sets a custom error message that can be used instead of setting an exception.\n     * This will still trigger {@link #checkFailure()}.\n     *\n     * @param message error message\n     */\n    public void setError(String message) {\n        setException(new AssertionFailedError(message));\n    }\n\n    /**\n     * Returns any saved exception.\n     *\n     * @return {@link Throwable} held by this container\n     */\n    public Throwable getException() {\n        return exception;\n    }\n\n    /**\n     * Checks if an exception has been set and fails the unit test if that is the case.\n     */\n    public void checkFailure() {\n        if (exception != null) {\n            StringWriter stacktrace = new StringWriter();\n            exception.printStackTrace(new PrintWriter(stacktrace));\n            fail(stacktrace.toString());\n        }\n    }\n}\n\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/util/LooperSpy.java",
    "content": "/*\n * Copyright 2016 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\npackage io.realm.util;\n\nimport android.os.Looper;\nimport android.os.Message;\nimport android.os.MessageQueue;\nimport android.util.Log;\n\nimport java.lang.reflect.Field;\n\n/**\n * Debug util for dumping the content of a Looper message queue.\n * Inspired by: https://corner.squareup.com/2013/12/android-main-thread-2.html\n */\npublic class LooperSpy {\n\n    private final Field messagesField;\n    private final Field nextField;\n    private final MessageQueue mainMessageQueue;\n\n    /**\n     * Creates a LooperSpy for the Looper on the main thread.\n     */\n    public static LooperSpy mainLooper() {\n        return new LooperSpy(Looper.getMainLooper());\n    }\n\n    /**\n     * Creates a LooperSpy for a specified Looper.\n     */\n    public static LooperSpy create(Looper looper) {\n        return new LooperSpy(looper);\n    }\n\n    private LooperSpy(Looper looper) {\n        try {\n            Field queueField = Looper.class.getDeclaredField(\"mQueue\");\n            queueField.setAccessible(true);\n            messagesField = MessageQueue.class.getDeclaredField(\"mMessages\");\n            messagesField.setAccessible(true);\n            nextField = Message.class.getDeclaredField(\"next\");\n            nextField.setAccessible(true);\n            mainMessageQueue = (MessageQueue) queueField.get(looper);\n        } catch (Exception e) {\n            throw new RuntimeException(e);\n        }\n    }\n\n    /**\n     * Outputs the Looper's entire MessageQueue to LogCat.\n     */\n    public void dumpQueue() {\n        try {\n            Message nextMessage = (Message) messagesField.get(mainMessageQueue);\n            Log.d(\"MainLooperSpy\", \"Begin dumping queue\");\n            dumpMessages(nextMessage);\n            Log.d(\"MainLooperSpy\", \"End dumping queue\");\n        } catch (IllegalAccessException e) {\n            throw new RuntimeException(e);\n        }\n    }\n\n    private void dumpMessages(Message message) throws IllegalAccessException {\n        if (message != null) {\n            Log.d(\"MainLooperSpy\", message.toString());\n            Message next = (Message) nextField.get(message);\n            dumpMessages(next);\n        }\n    }\n}\n\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/util/RealmBackgroundTask.java",
    "content": "/*\n * Copyright 2016 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\npackage io.realm.util;\n\nimport java.util.concurrent.CountDownLatch;\nimport java.util.concurrent.TimeUnit;\n\nimport io.realm.Realm;\nimport io.realm.RealmConfiguration;\nimport io.realm.TestHelper;\n\n\n/**\n * Utility class for running a task on a non-looper background thread.\n *\n * This class ensures that the background Realm is automatically closed no matter the outcome of\n * the test.\n *\n * Failures can be asserted using {@code task.checkFailure()}\n */\npublic abstract class RealmBackgroundTask {\n\n    private final RealmConfiguration configuration;\n    private final ExceptionHolder exceptionHolder = new ExceptionHolder();\n\n    public RealmBackgroundTask(RealmConfiguration configuration) {\n        this.configuration = configuration;\n    }\n\n    /**\n     * Runs the task on a background thread. It will either return when it completes successfully or throw an\n     * {@link junit.framework.AssertionFailedError} if it failed or timed out. The background task is limited to\n     * 10 seconds after which it will time out.\n     */\n    public void awaitOrFail() {\n        final CountDownLatch jobDone = new CountDownLatch(1);\n        new Thread(new Runnable() {\n            @Override\n            public void run() {\n                Realm realm = Realm.getInstance(configuration);\n                try {\n                    doInBackground(realm);\n                } catch (Throwable throwable) {\n                    exceptionHolder.setException(throwable);\n                } finally {\n                    realm.close();\n                    jobDone.countDown();\n                }\n            }\n        }, \"RealmBackgroundTask\").start();\n\n        try {\n            if (!jobDone.await(TestHelper.STANDARD_WAIT_SECS, TimeUnit.SECONDS)) {\n                exceptionHolder.setError(\"Job timed out!\");\n            }\n        } catch (InterruptedException e) {\n            exceptionHolder.setException(e);\n        }\n\n        exceptionHolder.checkFailure();\n    }\n\n    /**\n     * Executes the task. This method is called on a background thread.\n     *\n     * @param realm Realm instance created by the provided configuration.\n     */\n    protected abstract void doInBackground(Realm realm);\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/java/io/realm/util/RealmThread.java",
    "content": "/*\n * Copyright 2016 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\npackage io.realm.util;\n\nimport io.realm.Realm;\nimport io.realm.RealmConfiguration;\n\n// this is a simple example of how Realm can be encapsulated within a Thread wrapper.\npublic final class RealmThread extends Thread {\n\n    public interface RealmRunnable {\n        void run(final Realm realm);\n    }\n\n    private final RealmConfiguration realmConfig;\n    private final RealmRunnable task;\n    private Realm realm;\n\n    public RealmThread(RealmConfiguration realmConfig, RealmRunnable task) {\n        super();\n        this.realmConfig = realmConfig;\n        this.task = task;\n    }\n\n    public RealmThread(RealmConfiguration realmConfig, RealmRunnable task, String threadName) {\n        super(threadName);\n        this.realmConfig = realmConfig;\n        this.task = task;\n    }\n\n    @Override\n    public void run() {\n        realm = Realm.getInstance(this.realmConfig);\n        if (task != null) {\n            task.run(realm);\n        }\n        if (!realm.isClosed()) {\n            realm.close();\n        }\n        realm = null;\n    }\n\n    public void end() {\n        if (!this.isAlive()) {\n            return;\n        }\n        if (realm == null) {\n            return;\n        }\n        realm.stopWaitForChange();\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/kotlin/io/realm/Decimal128Tests.kt",
    "content": "/*\n * Copyright 2020 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 */\npackage io.realm\n\nimport androidx.test.ext.junit.runners.AndroidJUnit4\nimport androidx.test.platform.app.InstrumentationRegistry\nimport io.realm.annotations.PrimaryKey\nimport io.realm.annotations.Required\nimport io.realm.kotlin.createObject\nimport io.realm.kotlin.where\nimport org.bson.types.Decimal128\nimport org.junit.*\nimport org.junit.Assert.*\nimport org.junit.runner.RunWith\nimport java.math.BigDecimal\nimport kotlin.test.assertFailsWith\n\nopen class Decimal128Required : RealmObject() {\n    @PrimaryKey\n    var id: Long = 0\n\n    @Required\n    var decimal: Decimal128? = null\n    var name: String = \"\"\n}\n\nopen class Decimal128NotRequired : RealmObject() {\n    @PrimaryKey\n    var id: Long = 0\n    var decimal: Decimal128? = null\n    var name: String = \"\"\n}\n\nopen class Decimal128RequiredRealmList : RealmObject() {\n    var id: Long = 0\n\n    @Required\n    var decimals: RealmList<Decimal128> = RealmList()\n    var name: String = \"\"\n}\n\nopen class Decimal128OptionalRealmList : RealmObject() {\n    var id: Long = 0\n    var decimals: RealmList<Decimal128> = RealmList()\n    var name: String = \"\"\n}\n\nopen class LinkedDecimal128 : RealmObject() {\n    var linkedDecimal128: Decimal128NotRequired? = null\n}\n\n@RunWith(AndroidJUnit4::class)\nclass Decimal128Tests {\n    private lateinit var realmConfiguration: RealmConfiguration\n    private lateinit var realm: Realm\n\n    @Rule\n    @JvmField\n    val configFactory = TestRealmConfigurationFactory()\n\n    init {\n        Realm.init(InstrumentationRegistry.getInstrumentation().targetContext)\n    }\n\n    @Before\n    fun setUp() {\n        realmConfiguration = configFactory\n                .createConfigurationBuilder()\n                .schema(Decimal128Required::class.java,\n                        Decimal128NotRequired::class.java,\n                        Decimal128RequiredRealmList::class.java,\n                        Decimal128OptionalRealmList::class.java,\n                        LinkedDecimal128::class.java)\n                .build()\n        realm = Realm.getInstance(realmConfiguration)\n    }\n\n    @After\n    fun tearDown() {\n        realm.close()\n    }\n\n    @Test\n    fun copyToRealm() {\n        val value = Decimal128NotRequired()\n        value.decimal = Decimal128(BigDecimal.TEN)\n        value.id = 42\n        value.name = \"Foo\"\n\n        realm.beginTransaction()\n        val obj = realm.copyToRealm(value)\n        realm.commitTransaction()\n\n        assertEquals(Decimal128(BigDecimal.TEN), obj.decimal)\n        assertEquals(42L, obj.id)\n        assertEquals(\"Foo\", obj.name)\n    }\n\n    @Test\n    fun copyFromRealm() {\n        realm.beginTransaction()\n        val value = realm.createObject<Decimal128NotRequired>(42)\n        value.decimal = Decimal128(BigDecimal.TEN)\n        value.name = \"Foo\"\n        realm.commitTransaction()\n\n        val copy = realm.copyFromRealm(value)\n\n        assertEquals(Decimal128(BigDecimal.TEN), copy.decimal)\n        assertEquals(42L, copy.id)\n        assertEquals(\"Foo\", copy.name)\n    }\n\n    @Test\n    fun copyToRealmOrUpdate() {\n        realm.executeTransaction { realm ->\n            val value = realm.createObject<Decimal128NotRequired>(42)\n            value.decimal = Decimal128(BigDecimal.TEN)\n            value.name = \"Foo\"\n        }\n\n        val value = Decimal128NotRequired()\n        value.id = 42\n        value.decimal = Decimal128(BigDecimal.ONE)\n        value.name = \"Bar\"\n\n        realm.beginTransaction()\n        val obj = realm.copyToRealmOrUpdate(value)\n        realm.commitTransaction()\n\n        assertEquals(42L, obj.id)\n        assertEquals(Decimal128(BigDecimal.ONE), obj.decimal)\n        assertEquals(\"Bar\", obj.name)\n    }\n\n    @Test\n    fun insert() {\n        realm.executeTransaction { realm ->\n            val value = Decimal128Required()\n            value.id = 7\n            value.name = \"Foo\"\n            value.decimal = Decimal128(10)\n\n            realm.insert(value)\n        }\n\n        val obj = realm.where<Decimal128Required>().findFirst()\n\n        assertNotNull(obj)\n        assertEquals(7, obj!!.id)\n        assertEquals(Decimal128(10), obj.decimal)\n        assertEquals(\"Foo\", obj.name)\n    }\n\n    @Test\n    fun insertOrUpdate() {\n        realm.executeTransaction { realm ->\n            val value = realm.createObject<Decimal128Required>(7)\n            value.name = \"Foo\"\n            value.decimal = Decimal128(10)\n        }\n\n        realm.executeTransaction { realm ->\n            val value = Decimal128Required()\n            value.id = 7\n            value.name = \"Bar\"\n            value.decimal = Decimal128(20)\n\n            realm.insertOrUpdate(value)\n        }\n\n        val all = realm.where<Decimal128Required>().findAll()\n\n        assertEquals(1, all.size)\n        assertEquals(7, all[0]!!.id)\n        assertEquals(Decimal128(20), all[0]!!.decimal)\n        assertEquals(\"Bar\", all[0]!!.name)\n    }\n\n    @Test\n    fun frozen() {\n        realm.beginTransaction()\n        val obj = realm.createObject<Decimal128Required>(42)\n        obj.name = \"foo\"\n        obj.decimal = (Decimal128(BigDecimal.TEN))\n        realm.commitTransaction()\n\n        val frozen = obj.freeze<Decimal128Required>()\n\n        assertEquals(Decimal128(BigDecimal.TEN), frozen.decimal)\n        assertEquals(\"foo\", frozen.name)\n        assertEquals(42L, frozen.id)\n    }\n\n    @Test\n    fun requiredField() {\n        realm.beginTransaction()\n        val obj = realm.createObject<Decimal128Required>(42)\n        obj.name = \"foo\"\n        obj.decimal = (Decimal128(BigDecimal.TEN))\n        realm.commitTransaction()\n\n        val result = realm.where<Decimal128Required>().equalTo(\"decimal\", Decimal128(BigDecimal.TEN)).findFirst()\n        assertNotNull(result)\n        assertEquals(42L, result!!.id)\n        assertEquals(\"foo\", result.name)\n\n        realm.beginTransaction()\n\n        assertFailsWith<IllegalArgumentException>(\"It should not be possible to set null value for the required decimal field\") {\n            result.decimal = null\n        }\n\n        realm.commitTransaction()\n    }\n\n    @Test\n    fun nullableFiled() {\n        realm.beginTransaction()\n        val obj = realm.createObject<Decimal128NotRequired>(42)\n        obj.name = \"foo\"\n        obj.decimal = null\n        realm.commitTransaction()\n\n        val result = realm.where<Decimal128NotRequired>().isNull(\"decimal\").findFirst()\n        assertNotNull(result)\n        assertEquals(42L, result!!.id)\n        assertEquals(\"foo\", result.name)\n\n        realm.beginTransaction()\n        result.decimal = Decimal128(BigDecimal.TEN)\n        realm.commitTransaction()\n\n        val result2 = realm.where<Decimal128NotRequired>().equalTo(\"decimal\", Decimal128(BigDecimal.TEN)).findFirst()\n        assertEquals(42L, result2!!.id)\n        assertEquals(\"foo\", result2.name)\n    }\n\n    @Test\n    fun requiredRealmList() {\n        realm.beginTransaction()\n        val obj = realm.createObject<Decimal128RequiredRealmList>()\n        assertFailsWith<IllegalArgumentException>(\"It should not be possible to add nullable elements to a required RealmList<Decimal128>\") {\n            obj.decimals.add(null)\n        }\n    }\n\n    @Test\n    fun optionalRealmList() {\n        realm.beginTransaction()\n        val obj = realm.createObject<Decimal128OptionalRealmList>()\n        obj.decimals.add(null)\n        obj.decimals.add(Decimal128(BigDecimal.ZERO))\n        realm.commitTransaction()\n\n        assertEquals(2, realm.where<Decimal128OptionalRealmList>().findFirst()?.decimals?.size)\n    }\n\n    @Test\n    fun linkQueryNotSupported() {\n        realm.beginTransaction()\n        val obj = realm.createObject<Decimal128RequiredRealmList>()\n        realm.cancelTransaction()\n\n        assertFailsWith<UnsupportedOperationException> {\n            obj.decimals.where().equalTo(\"decimals\", Decimal128(BigDecimal.ZERO)).findAll()\n        }\n    }\n\n    @Test\n    fun NaN() {\n        realm.beginTransaction()\n        realm.createObject<Decimal128Required>(1).decimal = Decimal128(BigDecimal(Float.NaN.toLong()))\n        realm.createObject<Decimal128Required>(2).decimal = Decimal128(Float.NaN.toLong())\n        realm.createObject<Decimal128Required>(3).decimal = Decimal128(Double.NaN.toLong())\n        realm.commitTransaction()\n\n        val all = realm.where<Decimal128Required>().equalTo(\"decimal\", Decimal128(Float.NaN.toLong())).findAll()\n\n        assertEquals(3, all.size)\n    }\n\n    @Test\n    fun minValue() {\n        realm.beginTransaction()\n        realm.createObject<Decimal128Required>(1).decimal = Decimal128(BigDecimal(Float.MIN_VALUE.toLong()))\n        realm.createObject<Decimal128Required>(2).decimal = Decimal128(Float.MIN_VALUE.toLong())\n        realm.createObject<Decimal128Required>(3).decimal = Decimal128(Double.MIN_VALUE.toLong())\n        realm.createObject<Decimal128Required>(4).decimal = Decimal128.NEGATIVE_INFINITY\n        realm.createObject<Decimal128Required>(5).decimal = Decimal128.NEGATIVE_NaN\n        realm.createObject<Decimal128Required>(6).decimal = Decimal128.NEGATIVE_ZERO\n        realm.commitTransaction()\n\n        var all = realm.where<Decimal128Required>().equalTo(\"decimal\", Decimal128(Float.MIN_VALUE.toLong())).findAll()\n\n        assertEquals(4, all.size)\n        assertEquals(Decimal128(BigDecimal(Float.MIN_VALUE.toLong())), all[0]!!.decimal)\n        assertEquals(Decimal128(Float.MIN_VALUE.toLong()), all[1]!!.decimal)\n        assertEquals(Decimal128(Double.MIN_VALUE.toLong()), all[2]!!.decimal)\n        assertEquals(Decimal128.NEGATIVE_ZERO, all[3]!!.decimal)\n\n        all = realm.where<Decimal128Required>().notEqualTo(\"decimal\", Decimal128(Float.MIN_VALUE.toLong())).findAll()\n\n        assertEquals(2, all.size)\n        assertEquals(Decimal128.NEGATIVE_INFINITY, all[0]!!.decimal)\n        assertEquals(Decimal128.NEGATIVE_NaN, all[1]!!.decimal)\n    }\n\n    @Test\n    fun minQuery() {\n        realm.beginTransaction()\n        realm.createObject<Decimal128Required>(1).decimal = Decimal128(BigDecimal.TEN)\n        realm.createObject<Decimal128Required>(2).decimal = Decimal128(BigDecimal.ONE)\n        realm.createObject<Decimal128Required>(3).decimal = Decimal128(BigDecimal.ZERO)\n        realm.commitTransaction()\n\n        val min: Number? = realm.where<Decimal128Required>().min(\"decimal\")\n\n        assertNotNull(min)\n        assertTrue(min is Decimal128)\n        assertEquals(Decimal128(BigDecimal.ZERO), min)\n    }\n\n\n    @Test\n    fun maxValue() {\n        realm.beginTransaction()\n        realm.createObject<Decimal128Required>(1).decimal = Decimal128(BigDecimal(Float.MAX_VALUE.toLong()))\n        realm.createObject<Decimal128Required>(2).decimal = Decimal128(Float.MAX_VALUE.toLong())\n        realm.createObject<Decimal128Required>(3).decimal = Decimal128(Double.MAX_VALUE.toLong())\n        realm.createObject<Decimal128Required>(4).decimal = Decimal128.POSITIVE_INFINITY\n        realm.createObject<Decimal128Required>(5).decimal = Decimal128.NaN\n        realm.createObject<Decimal128Required>(6).decimal = Decimal128.POSITIVE_ZERO\n        realm.commitTransaction()\n\n        var all = realm.where<Decimal128Required>().equalTo(\"decimal\", Decimal128(Float.MAX_VALUE.toLong())).findAll()\n        assertEquals(3, all.size)\n        assertEquals(Decimal128(BigDecimal(Float.MAX_VALUE.toLong())), all[0]!!.decimal)\n        assertEquals(Decimal128(Float.MAX_VALUE.toLong()), all[1]!!.decimal)\n        assertEquals(Decimal128(Double.MAX_VALUE.toLong()), all[2]!!.decimal)\n\n        all = realm.where<Decimal128Required>().notEqualTo(\"decimal\", Decimal128(Float.MAX_VALUE.toLong())).findAll()\n\n        assertEquals(3, all.size)\n        assertEquals(Decimal128.POSITIVE_INFINITY, all[0]!!.decimal)\n        assertEquals(Decimal128.NaN, all[1]!!.decimal)\n        assertEquals(Decimal128.POSITIVE_ZERO, all[2]!!.decimal)\n    }\n\n    @Test\n    fun maxQuery() {\n        realm.beginTransaction()\n        realm.createObject<Decimal128Required>(1).decimal = Decimal128(BigDecimal.TEN)\n        realm.createObject<Decimal128Required>(2).decimal = Decimal128(BigDecimal.ONE)\n        realm.createObject<Decimal128Required>(3).decimal = Decimal128(BigDecimal.ZERO)\n        realm.commitTransaction()\n\n        val max: Number? = realm.where<Decimal128Required>().max(\"decimal\")\n\n        assertNotNull(max)\n        assertTrue(max is Decimal128)\n        assertEquals(Decimal128(BigDecimal.TEN), max)\n    }\n\n    @Test\n    fun betweenQuery() {\n        realm.beginTransaction()\n        realm.createObject<Decimal128Required>(1).decimal = Decimal128(BigDecimal.TEN)\n        realm.createObject<Decimal128Required>(2).decimal = Decimal128(BigDecimal.ONE)\n        realm.createObject<Decimal128Required>(3).decimal = Decimal128(BigDecimal.ZERO)\n        realm.commitTransaction()\n\n        val between = realm.where<Decimal128Required>().between(\"decimal\", Decimal128(-1L), Decimal128(11L)).findAll()\n\n        assertEquals(3, between.size)\n        assertEquals(Decimal128(BigDecimal.TEN), between[0]!!.decimal)\n        assertEquals(Decimal128(BigDecimal.ONE), between[1]!!.decimal)\n        assertEquals(Decimal128(BigDecimal.ZERO), between[2]!!.decimal)\n    }\n\n    @Test\n    fun averageQuery() {\n        var average = realm.where<Decimal128Required>().averageDecimal128(\"decimal\")\n        assertEquals(Decimal128(0), average)\n\n        realm.beginTransaction()\n        realm.createObject<Decimal128Required>(1).decimal = Decimal128(3)\n        realm.createObject<Decimal128Required>(2).decimal = Decimal128(7)\n        realm.createObject<Decimal128Required>(3).decimal = Decimal128(5)\n        realm.commitTransaction()\n\n        average = realm.where<Decimal128Required>().averageDecimal128(\"decimal\")\n        assertEquals(Decimal128(5), average)\n    }\n\n    @Test\n    fun sort() {\n        realm.beginTransaction()\n        realm.createObject<Decimal128Required>(1).decimal = Decimal128(BigDecimal.ONE)\n        realm.createObject<Decimal128Required>(2).decimal = Decimal128(BigDecimal.ZERO)\n        realm.createObject<Decimal128Required>(3).decimal = Decimal128(BigDecimal.TEN)\n        realm.commitTransaction()\n\n        var all = realm.where<Decimal128Required>().sort(\"decimal\", Sort.ASCENDING).findAll()\n        assertEquals(3, all.size)\n        assertEquals(Decimal128(BigDecimal.ZERO), all[0]!!.decimal)\n        assertEquals(Decimal128(BigDecimal.ONE), all[1]!!.decimal)\n        assertEquals(Decimal128(BigDecimal.TEN), all[2]!!.decimal)\n\n        all = realm.where<Decimal128Required>().sort(\"decimal\", Sort.DESCENDING).findAll()\n\n        assertEquals(3, all.size)\n        assertEquals(Decimal128(BigDecimal.TEN), all[0]!!.decimal)\n        assertEquals(Decimal128(BigDecimal.ONE), all[1]!!.decimal)\n        assertEquals(Decimal128(BigDecimal.ZERO), all[2]!!.decimal)\n    }\n\n    @Test\n    fun distinct() {\n        realm.beginTransaction()\n        realm.createObject<Decimal128NotRequired>(1).decimal = Decimal128(BigDecimal.ONE)\n        realm.createObject<Decimal128NotRequired>(2).decimal = Decimal128(BigDecimal.ONE)\n        realm.createObject<Decimal128NotRequired>(3).decimal = null\n        realm.createObject<Decimal128NotRequired>(4).decimal = Decimal128(BigDecimal.ZERO)\n        realm.createObject<Decimal128NotRequired>(5).decimal = Decimal128(BigDecimal.ZERO)\n        realm.createObject<Decimal128NotRequired>(6).decimal = null\n        realm.createObject<Decimal128NotRequired>(7).decimal = Decimal128(BigDecimal.TEN)\n        realm.createObject<Decimal128NotRequired>(8).decimal = Decimal128(BigDecimal.TEN)\n        realm.createObject<Decimal128NotRequired>(9).decimal = null\n        realm.commitTransaction()\n\n        val all = realm.where<Decimal128NotRequired>().distinct(\"decimal\").sort(\"decimal\", Sort.ASCENDING).findAll()\n\n        assertEquals(4, all.size)\n        assertNull(all[0]!!.decimal)\n        assertEquals(Decimal128(BigDecimal.ZERO), all[1]!!.decimal)\n        assertEquals(Decimal128(BigDecimal.ONE), all[2]!!.decimal)\n        assertEquals(Decimal128(BigDecimal.TEN), all[3]!!.decimal)\n\n    }\n\n    @Test\n    fun queriesCount() {\n        realm.beginTransaction()\n        realm.createObject<Decimal128NotRequired>(1).decimal = Decimal128(BigDecimal.ONE)\n        realm.createObject<Decimal128NotRequired>(2).decimal = null\n        realm.createObject<Decimal128NotRequired>(3).decimal = Decimal128(BigDecimal.TEN)\n        realm.createObject<Decimal128NotRequired>(4).decimal = Decimal128(BigDecimal.ZERO)\n        realm.commitTransaction()\n\n        assertEquals(4, realm.where<Decimal128NotRequired>().count())\n    }\n\n    @Test\n    fun queriesNotEqualTo() {\n        realm.beginTransaction()\n        realm.createObject<Decimal128NotRequired>(1).decimal = Decimal128(BigDecimal.ONE)\n        realm.createObject<Decimal128NotRequired>(2).decimal = null\n        realm.createObject<Decimal128NotRequired>(3).decimal = Decimal128(BigDecimal.TEN)\n        realm.createObject<Decimal128NotRequired>(4).decimal = Decimal128(BigDecimal.ZERO)\n        realm.commitTransaction()\n\n        val all = realm.where<Decimal128NotRequired>()\n                .notEqualTo(\"decimal\", Decimal128(BigDecimal.ONE))\n                .sort(\"decimal\", Sort.ASCENDING)\n                .findAll()\n\n        assertEquals(3, all.size)\n        assertNull(all[0]!!.decimal)\n        assertEquals(Decimal128(BigDecimal.ZERO), all[1]!!.decimal)\n        assertEquals(Decimal128(BigDecimal.TEN), all[2]!!.decimal)\n    }\n\n    @Test\n    fun queriesGreaterThanOrEqualTo() {\n        realm.beginTransaction()\n        realm.createObject<Decimal128NotRequired>(1).decimal = Decimal128(BigDecimal.ONE)\n        realm.createObject<Decimal128NotRequired>(2).decimal = null\n        realm.createObject<Decimal128NotRequired>(3).decimal = Decimal128(BigDecimal.TEN)\n        realm.createObject<Decimal128NotRequired>(4).decimal = Decimal128(BigDecimal.ZERO)\n        realm.commitTransaction()\n\n        val all = realm.where<Decimal128NotRequired>()\n                .greaterThanOrEqualTo(\"decimal\", Decimal128(BigDecimal.ONE))\n                .sort(\"decimal\", Sort.ASCENDING)\n                .findAll()\n\n        assertEquals(2, all.size)\n        assertEquals(Decimal128(BigDecimal.ONE), all[0]!!.decimal)\n        assertEquals(Decimal128(BigDecimal.TEN), all[1]!!.decimal)\n    }\n\n    @Test\n    fun queriesGreaterThan() {\n        realm.beginTransaction()\n        realm.createObject<Decimal128NotRequired>(1).decimal = Decimal128(BigDecimal.ONE)\n        realm.createObject<Decimal128NotRequired>(2).decimal = null\n        realm.createObject<Decimal128NotRequired>(3).decimal = Decimal128(BigDecimal.TEN)\n        realm.createObject<Decimal128NotRequired>(4).decimal = Decimal128(BigDecimal.ZERO)\n        realm.commitTransaction()\n\n        val all = realm.where<Decimal128NotRequired>()\n                .greaterThan(\"decimal\", Decimal128(BigDecimal.ONE))\n                .sort(\"decimal\", Sort.ASCENDING)\n                .findAll()\n\n        assertEquals(1, all.size)\n        assertEquals(Decimal128(BigDecimal.TEN), all[0]!!.decimal)\n    }\n\n    @Test\n    fun queriesLessThanOrEqualTo() {\n        realm.beginTransaction()\n        realm.createObject<Decimal128NotRequired>(1).decimal = Decimal128(BigDecimal.ONE)\n        realm.createObject<Decimal128NotRequired>(2).decimal = null\n        realm.createObject<Decimal128NotRequired>(3).decimal = Decimal128(BigDecimal.TEN)\n        realm.createObject<Decimal128NotRequired>(4).decimal = Decimal128(BigDecimal.ZERO)\n        realm.commitTransaction()\n\n        val all = realm.where<Decimal128NotRequired>()\n                .lessThanOrEqualTo(\"decimal\", Decimal128(BigDecimal.ONE))\n                .sort(\"decimal\", Sort.ASCENDING)\n                .findAll()\n\n        assertEquals(2, all.size)\n        assertEquals(Decimal128(BigDecimal.ZERO), all[0]!!.decimal)\n        assertEquals(Decimal128(BigDecimal.ONE), all[1]!!.decimal)\n    }\n\n    @Test\n    fun queriesLessThan() {\n        realm.beginTransaction()\n        realm.createObject<Decimal128NotRequired>(1).decimal = Decimal128(BigDecimal.ONE)\n        realm.createObject<Decimal128NotRequired>(2).decimal = null\n        realm.createObject<Decimal128NotRequired>(3).decimal = Decimal128(BigDecimal.TEN)\n        realm.createObject<Decimal128NotRequired>(4).decimal = Decimal128(BigDecimal.ZERO)\n        realm.commitTransaction()\n\n        val all = realm.where<Decimal128NotRequired>()\n                .lessThan(\"decimal\", Decimal128(BigDecimal.ONE))\n                .sort(\"decimal\", Sort.ASCENDING)\n                .findAll()\n\n        assertEquals(1, all.size)\n        assertEquals(Decimal128(BigDecimal.ZERO), all[0]!!.decimal)\n    }\n\n    @Test\n    fun queriesIsNull() {\n        realm.beginTransaction()\n        realm.createObject<Decimal128NotRequired>(1).decimal = Decimal128(BigDecimal.ONE)\n        realm.createObject<Decimal128NotRequired>(2).decimal = null\n        realm.createObject<Decimal128NotRequired>(3).decimal = Decimal128(BigDecimal.TEN)\n        realm.createObject<Decimal128NotRequired>(4).decimal = Decimal128(BigDecimal.ZERO)\n        realm.commitTransaction()\n\n        val all = realm.where<Decimal128NotRequired>()\n                .isNull(\"decimal\")\n                .findAll()\n\n        assertEquals(1, all.size)\n        assertNull(all[0]!!.decimal)\n        assertEquals(2L, all[0]!!.id)\n    }\n\n    @Test\n    fun queriesIsNotNull() {\n        realm.beginTransaction()\n        realm.createObject<Decimal128NotRequired>(1).decimal = Decimal128(BigDecimal.ONE)\n        realm.createObject<Decimal128NotRequired>(2).decimal = null\n        realm.createObject<Decimal128NotRequired>(3).decimal = Decimal128(BigDecimal.TEN)\n        realm.createObject<Decimal128NotRequired>(4).decimal = Decimal128(BigDecimal.ZERO)\n        realm.commitTransaction()\n\n        val all = realm.where<Decimal128NotRequired>()\n                .isNotNull(\"decimal\")\n                .sort(\"decimal\", Sort.ASCENDING)\n                .findAll()\n\n        assertEquals(3, all.size)\n        assertEquals(Decimal128(BigDecimal.ZERO), all[0]!!.decimal)\n        assertEquals(Decimal128(BigDecimal.ONE), all[1]!!.decimal)\n        assertEquals(Decimal128(BigDecimal.TEN), all[2]!!.decimal)\n    }\n\n    @Test\n    fun queriesAverage() {\n        realm.beginTransaction()\n        realm.createObject<Decimal128NotRequired>(1).decimal = Decimal128(BigDecimal.ONE)\n        realm.createObject<Decimal128NotRequired>(2).decimal = null\n        realm.createObject<Decimal128NotRequired>(3).decimal = Decimal128(BigDecimal.TEN)\n        realm.createObject<Decimal128NotRequired>(4).decimal = Decimal128(BigDecimal.ZERO)\n        realm.commitTransaction()\n\n        assertFailsWith<IllegalArgumentException>(\"Average is not supported for Decimal128\") {\n            realm.where<Decimal128NotRequired>().average(\"decimal\") // FIXME should we support avergae queries in Core?\n        }\n    }\n\n    @Test\n    fun queriesIsEmpty() {\n        realm.beginTransaction()\n        realm.createObject<Decimal128NotRequired>(1).decimal = Decimal128(BigDecimal.ONE)\n        realm.createObject<Decimal128NotRequired>(2).decimal = null\n        realm.createObject<Decimal128NotRequired>(3).decimal = Decimal128(BigDecimal.TEN)\n        realm.createObject<Decimal128NotRequired>(4).decimal = Decimal128(BigDecimal.ZERO)\n        realm.commitTransaction()\n\n        assertFailsWith<IllegalArgumentException>(\"isEmpty is not supported for Decimal128\") {\n            realm.where<Decimal128NotRequired>().isEmpty(\"decimal\").count()\n        }\n    }\n\n    @Test\n    fun linkedQuery() {\n        val decimal128Array = arrayOf(null, Decimal128.parse(\"0\"), Decimal128.parse(\"1\"), Decimal128.parse(\"2\"))\n\n        realm.executeTransaction { realm ->\n            decimal128Array.forEachIndexed { i, decimal128 ->\n                val decimalObj = realm.createObject<Decimal128NotRequired>(i)\n                decimalObj.decimal = decimal128\n\n                realm.createObject<LinkedDecimal128>().linkedDecimal128 = decimalObj\n            }\n        }\n\n        for (decimal in decimal128Array) {\n            val results = realm.where<LinkedDecimal128>().equalTo(\"linkedDecimal128.decimal\", decimal).findAll()\n            assertEquals(1, results.size)\n            assertEquals(decimal, results.first()?.linkedDecimal128?.decimal)\n        }\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/kotlin/io/realm/DictionaryMiscTests.kt",
    "content": "/*\n * Copyright 2021 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\npackage io.realm\n\nimport androidx.test.ext.junit.runners.AndroidJUnit4\nimport androidx.test.platform.app.InstrumentationRegistry\nimport io.realm.entities.DictionaryContainerClass\nimport io.realm.entities.EmbeddedObjectDictionaryContainerClass\nimport io.realm.entities.PrimaryKeyDictionaryContainer\nimport io.realm.entities.StringOnly\nimport io.realm.entities.embedded.EmbeddedSimpleChild\nimport io.realm.entities.embedded.EmbeddedSimpleParent\nimport io.realm.kotlin.createObject\nimport io.realm.kotlin.where\nimport org.bson.types.Decimal128\nimport org.bson.types.ObjectId\nimport org.json.JSONArray\nimport org.json.JSONObject\nimport org.junit.After\nimport org.junit.Before\nimport org.junit.Rule\nimport org.junit.Test\nimport org.junit.runner.RunWith\nimport java.util.*\nimport kotlin.test.*\n\n@RunWith(AndroidJUnit4::class)\nclass DictionaryMiscTests {\n\n    @Rule\n    @JvmField\n    val configFactory = TestRealmConfigurationFactory()\n\n    private val dictionaryFields = listOf(\n            // The \"java.lang\" prefix in primitive types is needed or else Kotlin will map it to raw primitives\n            Triple(DictionaryContainerClass::myBooleanDictionary, java.lang.Boolean::class.java, RealmFieldType.STRING_TO_BOOLEAN_MAP),\n            Triple(DictionaryContainerClass::myIntDictionary, java.lang.Integer::class.java, RealmFieldType.STRING_TO_INTEGER_MAP),\n            Triple(DictionaryContainerClass::myFloatDictionary, java.lang.Float::class.java, RealmFieldType.STRING_TO_FLOAT_MAP),\n            Triple(DictionaryContainerClass::myLongDictionary, java.lang.Long::class.java, RealmFieldType.STRING_TO_INTEGER_MAP),\n            Triple(DictionaryContainerClass::myShortDictionary, java.lang.Short::class.java, RealmFieldType.STRING_TO_INTEGER_MAP),\n            Triple(DictionaryContainerClass::myByteDictionary, java.lang.Byte::class.java, RealmFieldType.STRING_TO_INTEGER_MAP),\n            Triple(DictionaryContainerClass::myDoubleDictionary, java.lang.Double::class.java, RealmFieldType.STRING_TO_DOUBLE_MAP),\n            Triple(DictionaryContainerClass::myStringDictionary, String::class.java, RealmFieldType.STRING_TO_STRING_MAP),\n            Triple(DictionaryContainerClass::myBinaryDictionary, ByteArray::class.java, RealmFieldType.STRING_TO_BINARY_MAP),\n            Triple(DictionaryContainerClass::myDateDictionary, Date::class.java, RealmFieldType.STRING_TO_DATE_MAP),\n            Triple(DictionaryContainerClass::myObjectIdDictionary, ObjectId::class.java, RealmFieldType.STRING_TO_OBJECT_ID_MAP),\n            Triple(DictionaryContainerClass::myUUIDDictionary, UUID::class.java, RealmFieldType.STRING_TO_UUID_MAP),\n            Triple(DictionaryContainerClass::myDecimal128Dictionary, Decimal128::class.java, RealmFieldType.STRING_TO_DECIMAL128_MAP),\n            Triple(DictionaryContainerClass::myRealmAnyDictionary, RealmAny::class.java, RealmFieldType.STRING_TO_MIXED_MAP),\n            Triple(DictionaryContainerClass::myRealmModelDictionary, StringOnly::class.java, RealmFieldType.STRING_TO_LINK_MAP)\n    )\n\n    private lateinit var realm: Realm\n\n    @Before\n    fun setUp() {\n        Realm.init(InstrumentationRegistry.getInstrumentation().context)\n    }\n\n    @After\n    fun tearDown() {\n        realm.close()\n    }\n\n    @Test\n    fun migrate_realmDictionary() {\n        // Creates v0 of the Realm.\n        val originalConfig = configFactory.createConfigurationBuilder()\n                .schema(StringOnly::class.java)\n                .build()\n        Realm.getInstance(originalConfig).close()\n\n        // Creates v1 of the Realm.\n        val realmConfig = configFactory\n                .createConfigurationBuilder()\n                .schemaVersion(1)\n                .schema(StringOnly::class.java, DictionaryContainerClass::class.java)\n                .migration { realm, _, _ ->\n                    val schema = realm.schema.create(DictionaryContainerClass.CLASS_NAME)\n\n                    dictionaryFields.forEach {\n                        if (it.third == RealmFieldType.STRING_TO_LINK_MAP) {\n                            val realmModelSchema = realm.schema.get(it.second.simpleName)\n                            assertNotNull(realmModelSchema)\n                            schema.addRealmDictionaryField(it.first.name, realmModelSchema)\n                        } else {\n                            schema.addRealmDictionaryField(it.first.name, it.second)\n                        }\n                    }\n                }.build()\n\n        realm = Realm.getInstance(realmConfig)\n\n        val objectSchema = realm.schema.get(DictionaryContainerClass.CLASS_NAME)\n        assertNotNull(objectSchema)\n        dictionaryFields.forEach {\n            assertTrue(objectSchema.hasField(it.first.name))\n            assertEquals(it.third, objectSchema.getFieldType(it.first.name))\n        }\n\n        realm.executeTransaction { transactionRealm ->\n            val container = transactionRealm.createObject<DictionaryContainerClass>()\n            dictionaryFields.forEach {\n                val dictionary = it.first.get(container)\n                assertNotNull(dictionary)\n                assertTrue(dictionary.isEmpty())\n            }\n        }\n\n        realm.close()\n    }\n\n    @Test\n    fun put_embeddedObject() {\n        realm = Realm.getInstance(configFactory.createConfiguration())\n        realm.executeTransaction {\n            val parent = EmbeddedSimpleParent(\"parent\")\n            parent.child = EmbeddedSimpleChild(\"child\")\n\n            val managedParent: EmbeddedSimpleParent = it.copyToRealm(parent)\n            assertEquals(1, realm.where<EmbeddedSimpleChild>().count())\n            val managedChild: EmbeddedSimpleChild = managedParent.child!!\n\n            // Dictionary\n            val container = it.createObject<EmbeddedObjectDictionaryContainerClass>()\n            val dictionary = container.myEmbeddedObjectDictionary\n            dictionary[\"HELLO\"] = managedChild\n\n            assertEquals(1, dictionary.size)\n            val valueFromDictionary = dictionary[\"HELLO\"]\n            assertNotNull(valueFromDictionary)\n            assertNotEquals(managedChild, valueFromDictionary)     // should be NOT equals, they contain different objKeys\n\n            managedParent.deleteFromRealm()\n            assertFalse(managedParent.isValid)\n            assertEquals(1, dictionary.size)\n            assertFalse(managedChild.isValid)\n            assertTrue(valueFromDictionary.isValid)\n        }\n    }\n\n    @Test\n    fun copyToRealm_unmanagedEmbeddedObject() {\n        realm = Realm.getInstance(configFactory.createConfiguration())\n        realm.executeTransaction {\n            val unmanagedChild = EmbeddedSimpleChild(\"child\")\n\n            val unmanagedContainer = EmbeddedObjectDictionaryContainerClass().apply {\n                myEmbeddedObjectDictionary[\"KEY_EMBEDDED\"] = unmanagedChild\n            }\n\n            val managedContainer = it.copyToRealm(unmanagedContainer)\n            assertNotNull(managedContainer)\n            val managedDictionary = managedContainer.myEmbeddedObjectDictionary\n            assertNotNull(managedDictionary)\n            assertEquals(1, managedDictionary.size)\n\n            val managedChild = managedDictionary[\"KEY_EMBEDDED\"]\n            assertNotNull(managedChild)\n            assertTrue(managedChild.isValid)\n            assertEquals(unmanagedChild.childId, managedChild.childId)\n\n            assertEquals(1, it.where<EmbeddedSimpleChild>().count())\n            managedDictionary.clear()\n            assertTrue(managedDictionary.isEmpty())\n            assertEquals(0, it.where<EmbeddedSimpleChild>().count())\n            assertFalse(managedChild.isValid)\n        }\n    }\n\n    @Test\n    fun createAllFromJson_unsupportedOperation() {\n        realm = Realm.getInstance(configFactory.createConfiguration())\n        realm.executeTransaction {\n            val jsonArray = \"[{ \\\"columnLong\\\" : 1 }]\"\n\n            // createAllFromJson\n            assertFailsWith<UnsupportedOperationException> {\n                realm.createAllFromJson(DictionaryContainerClass::class.java, jsonArray)\n            }\n            assertFailsWith<UnsupportedOperationException> {\n                realm.createAllFromJson(DictionaryContainerClass::class.java, JSONArray(jsonArray))\n            }\n            assertFailsWith<UnsupportedOperationException> {\n                realm.createAllFromJson(DictionaryContainerClass::class.java, TestHelper.stringToStream(jsonArray))\n            }\n        }\n    }\n\n    @Test\n    fun createObjectFromJson_unsupportedOperation() {\n        realm = Realm.getInstance(configFactory.createConfiguration())\n        realm.executeTransaction {\n            val jsonObject = \"{ \\\"columnLong\\\" : 1 }\"\n\n            // createObjectFromJson\n            assertFailsWith<UnsupportedOperationException> {\n                realm.createObjectFromJson(DictionaryContainerClass::class.java, jsonObject)\n            }\n            assertFailsWith<UnsupportedOperationException> {\n                realm.createObjectFromJson(DictionaryContainerClass::class.java, JSONObject(jsonObject))\n            }\n            assertFailsWith<UnsupportedOperationException> {\n                realm.createObjectFromJson(DictionaryContainerClass::class.java, TestHelper.stringToStream(jsonObject))\n            }\n        }\n    }\n\n    @Test\n    fun createOrUpdateAllFromJson_unsupportedOperation() {\n        realm = Realm.getInstance(configFactory.createConfiguration())\n        realm.executeTransaction {\n            val jsonArray = \"[{ \\\"columnLong\\\" : 1 }]\"\n\n            // createOrUpdateAllFromJson\n            assertFailsWith<UnsupportedOperationException> {\n                realm.createOrUpdateAllFromJson(PrimaryKeyDictionaryContainer::class.java, jsonArray)\n            }\n            assertFailsWith<UnsupportedOperationException> {\n                realm.createOrUpdateAllFromJson(PrimaryKeyDictionaryContainer::class.java, JSONArray(jsonArray))\n            }\n            assertFailsWith<UnsupportedOperationException> {\n                realm.createOrUpdateAllFromJson(PrimaryKeyDictionaryContainer::class.java, TestHelper.stringToStream(jsonArray))\n            }\n        }\n    }\n\n    @Test\n    fun createOrUpdateObjectFromJson_unsupportedOperation() {\n        realm = Realm.getInstance(configFactory.createConfiguration())\n        realm.executeTransaction {\n            val jsonObject = \"{ \\\"columnLong\\\" : 1 }\"\n\n            // createOrUpdateObjectFromJson\n            assertFailsWith<UnsupportedOperationException> {\n                realm.createOrUpdateObjectFromJson(PrimaryKeyDictionaryContainer::class.java, jsonObject)\n            }\n            assertFailsWith<UnsupportedOperationException> {\n                realm.createOrUpdateObjectFromJson(PrimaryKeyDictionaryContainer::class.java, JSONObject(jsonObject))\n            }\n            assertFailsWith<UnsupportedOperationException> {\n                realm.createOrUpdateObjectFromJson(PrimaryKeyDictionaryContainer::class.java, TestHelper.stringToStream(jsonObject))\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/kotlin/io/realm/DictionaryTester.kt",
    "content": "/*\n * Copyright 2020 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\npackage io.realm\n\n/**\n * Contains all the methods to test in RealmDictionary plus some other convenience ones.\n */\ninterface DictionaryTester : GenericTester {\n    override fun setUp(configFactory: TestRealmConfigurationFactory) = Unit     // Not needed here\n    fun constructorWithAnotherMap()\n    fun isManaged()\n    fun isValid()\n    fun isFrozen()\n    fun size()\n    fun isEmpty()\n    fun containsKey()\n    fun containsValue()\n    fun get()\n    fun put()\n    fun putRequired()\n    fun remove()\n    fun putAll()\n    fun clear()\n    fun keySet()\n    fun values()\n    fun entrySet()\n    fun freeze()\n    fun dynamic()\n    fun insert()\n    fun insertList()\n    fun insertOrUpdate()\n    fun insertOrUpdateList()\n    fun copyToRealm()\n    fun copyToRealmOrUpdate()\n    fun copyFromRealm()\n    fun fieldAccessors(otherConfig: RealmConfiguration? = null)\n    fun addMapChangeListener()\n    fun addRealmChangeListener()\n    fun hasListeners()\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/kotlin/io/realm/EmbeddedObjectsTest.kt",
    "content": "/*\n * Copyright 2020 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 */\npackage io.realm\n\nimport androidx.test.ext.junit.runners.AndroidJUnit4\nimport androidx.test.platform.app.InstrumentationRegistry\nimport io.realm.entities.*\nimport io.realm.entities.embedded.*\nimport io.realm.exceptions.RealmPrimaryKeyConstraintException\nimport io.realm.kotlin.createEmbeddedObject\nimport io.realm.kotlin.createObject\nimport io.realm.kotlin.where\nimport io.realm.rule.BlockingLooperThread\nimport org.json.JSONObject\nimport org.junit.*\nimport org.junit.Assert.*\nimport org.junit.runner.RunWith\nimport java.io.ByteArrayInputStream\nimport java.nio.charset.Charset\nimport java.util.*\nimport kotlin.test.assertFailsWith\n\n/**\n * Class testing the Embedded Objects feature.\n */\n// FIXME: Move all of these tests out from here. We try to tests by Class, not Feature.\n\nprivate val UTF_8 = Charset.forName(\"UTF-8\");\n\nprivate const val parentId = \"uuid\"\nprivate const val childId = \"childId\"\nprivate const val embeddedChildId = \"embeddedChildId\"\nprivate const val childId1 = \"childId1\"\nprivate const val childId2 = \"childId2\"\nprivate const val childId3 = \"childId3\"\n\nprivate val simpleListParentData = mapOf(\n        \"_id\" to parentId,\n        \"children\" to listOf(\n                mapOf(\"childId\" to childId1),\n                mapOf(\"childId\" to childId2),\n                mapOf(\"childId\" to childId3)\n        )\n)\n\n@RunWith(AndroidJUnit4::class)\nclass EmbeddedObjectsTest {\n\n    @get:Rule\n    val configFactory = TestRealmConfigurationFactory()\n\n    private val looperThread = BlockingLooperThread()\n\n    private lateinit var realmConfig: RealmConfiguration\n    private lateinit var realm: Realm\n\n    @Before\n    fun setUp() {\n        Realm.init(InstrumentationRegistry.getInstrumentation().targetContext)\n        realmConfig = configFactory.createConfiguration()\n        realm = Realm.getInstance(realmConfig)\n    }\n\n    @After\n    fun tearDown() {\n        if (this::realm.isInitialized) {\n            realm.close()\n        }\n    }\n\n    @Test\n    fun createObject_throwsForEmbeddedClasses() = realm.executeTransaction { realm ->\n        assertFailsWith<IllegalArgumentException> { realm.createObject<EmbeddedSimpleChild>() }\n    }\n\n    @Test\n    fun createObjectWithPrimaryKey_throwsForEmbeddedClasses() = realm.executeTransaction { realm ->\n        assertFailsWith<IllegalArgumentException> { realm.createObject<EmbeddedSimpleChild>(\"foo\") }\n    }\n\n    @Test\n    fun createEmbeddedObject_nullArgsThrows() = realm.executeTransaction { realm ->\n        assertFailsWith<IllegalArgumentException> { realm.createEmbeddedObject(EmbeddedSimpleChild::class.java, TestHelper.getNull(), \"foo\") }\n        val parent = realm.createObject<EmbeddedSimpleParent>(\"parent\")\n        assertFailsWith<IllegalArgumentException> { realm.createEmbeddedObject(EmbeddedSimpleChild::class.java, parent, TestHelper.getNull()) }\n    }\n\n    @Test\n    fun createEmbeddedObject_nonExistingParentPropertyNameThrows() = realm.executeTransaction { realm ->\n        val parent = realm.createObject<EmbeddedSimpleParent>(\"parent\")\n        assertFailsWith<IllegalArgumentException> { realm.createEmbeddedObject<EmbeddedSimpleChild>(parent, \"foo\") }\n    }\n\n    @Test\n    fun createEmbeddedObject_wrongParentPropertyTypeThrows() = realm.executeTransaction { realm ->\n        val parent = realm.createObject<EmbeddedSimpleParent>(\"parent\")\n\n        // TODO: Smoke-test for wrong type. Figure out how to test all unsupported types.\n        assertFailsWith<IllegalArgumentException> { realm.createEmbeddedObject<EmbeddedSimpleChild>(parent, \"childId\") }\n    }\n\n    @Test\n    fun createEmbeddedObject_wrongParentPropertyObjectTypeThrows() = realm.executeTransaction { realm ->\n        val parent = realm.createObject<EmbeddedSimpleParent>(\"parent\")\n\n        assertFailsWith<IllegalArgumentException> {\n            // Embedded object is not of the type the parent object links to.\n            realm.createEmbeddedObject<EmbeddedTreeLeaf>(parent, \"child\")\n        }\n    }\n\n    @Test\n    fun createEmbeddedObject_wrongParentPropertyListTypeThrows() = realm.executeTransaction { realm ->\n        val parent = realm.createObject<EmbeddedSimpleListParent>(\"parent\")\n\n        assertFailsWith<IllegalArgumentException> {\n            // Embedded object is not of the type the parent object links to.\n            realm.createEmbeddedObject<EmbeddedTreeLeaf>(parent, \"children\")\n        }\n    }\n\n    @Test\n    fun createEmbeddedObject_simpleSingleChild() = realm.executeTransaction { realm ->\n        val parent = realm.createObject<EmbeddedSimpleParent>(\"parent\")\n        val child = realm.createEmbeddedObject<EmbeddedSimpleChild>(parent, \"child\")\n        assertEquals(child.parent, parent)\n    }\n\n    @Test\n    fun createEmbeddedObject_simpleChildList() = realm.executeTransaction { realm ->\n        // Using createEmbeddedObject() with a parent list, will append the object to the end\n        // of the list\n        val parent = realm.createObject<EmbeddedSimpleListParent>(UUID.randomUUID().toString())\n        val child1 = realm.createEmbeddedObject<EmbeddedSimpleChild>(parent, \"children\")\n        val child2 = realm.createEmbeddedObject<EmbeddedSimpleChild>(parent, \"children\")\n        assertEquals(2, parent.children.size.toLong())\n        assertEquals(child1, parent.children.first()!!)\n        assertEquals(child2, parent.children.last()!!)\n    }\n\n    @Test\n    fun dynamicRealm_createEmbeddedObject() =\n            DynamicRealm.getInstance(realm.configuration).use { realm ->\n                realm.executeTransaction {\n                    val parent = realm.createObject(\"EmbeddedSimpleParent\", \"PK_VALUE\")\n                    val child = realm.createEmbeddedObject(\"EmbeddedSimpleChild\", parent, \"child\")\n\n                    val idValue = \"ID_VALUE\"\n                    child.setString(\"childId\", idValue)\n\n                    val childInParent = parent.getObject(\"child\")\n                    assertNotNull(childInParent)\n                    assertEquals(childInParent!!.getString(\"childId\"), idValue)\n                    assertEquals(child, childInParent)\n\n                    val linkingParent = child.linkingObjects(\"EmbeddedSimpleParent\", \"child\").first()\n                    assertNotNull(linkingParent)\n                    assertEquals(parent.getString(\"_id\"), linkingParent!!.getString(\"_id\"))\n                    assertEquals(parent.getObject(\"child\"), linkingParent.getObject(\"child\"))\n                }\n            }\n\n    @Test\n    fun dynamicRealm_createEmbeddedObject_simpleChildList() =\n            DynamicRealm.getInstance(realm.configuration).use { realm ->\n                realm.executeTransaction {\n                    val parent = realm.createObject(\"EmbeddedSimpleListParent\", UUID.randomUUID().toString())\n                    val child1 = realm.createEmbeddedObject(\"EmbeddedSimpleChild\", parent, \"children\")\n                    val child2 = realm.createEmbeddedObject(\"EmbeddedSimpleChild\", parent, \"children\")\n                    assertEquals(2, parent.getList(\"children\").size.toLong())\n                    assertEquals(child1, parent.getList(\"children\").first()!!)\n                    assertEquals(child2, parent.getList(\"children\").last()!!)\n                }\n            }\n\n    @Test\n    fun dynamicRealm_createEmbeddedObject_wrongParentPropertyTypeThrows() {\n        DynamicRealm.getInstance(realm.configuration).use { realm ->\n            realm.executeTransaction {\n                val parent = realm.createObject(\"EmbeddedSimpleParent\", \"parent\")\n                assertFailsWith<IllegalArgumentException> { realm.createEmbeddedObject(\"EmbeddedSimpleChild\", parent, \"_id\") }\n            }\n        }\n    }\n\n    @Test\n    fun dynamicRealm_createEmbeddedObject_wrongParentPropertyObjectTypeThrows() =\n            DynamicRealm.getInstance(realm.configuration).use { realm ->\n                realm.executeTransaction {\n                    val parent = realm.createObject(\"EmbeddedSimpleParent\", \"parent\")\n\n                    assertFailsWith<IllegalArgumentException> {\n                        // Embedded object is not of the type the parent object links to.\n                        realm.createEmbeddedObject(\"EmbeddedTreeLeaf\", parent, \"child\")\n                    }\n                }\n            }\n\n    @Test\n    fun dynamicRealm_createEmbeddedObject_wrongParentPropertyListTypeThrows() =\n            DynamicRealm.getInstance(realm.configuration).use { realm ->\n                realm.executeTransaction {\n                    val parent = realm.createObject(\"EmbeddedSimpleListParent\", \"parent\")\n\n                    assertFailsWith<IllegalArgumentException> {\n                        // Embedded object is not of the type the parent object links to.\n                        realm.createEmbeddedObject(\"EmbeddedTreeLeaf\", parent, \"children\")\n                    }\n                }\n            }\n\n    @Test\n    fun settingParentFieldDeletesChild() = realm.executeTransaction { realm ->\n        val parent = EmbeddedSimpleParent(\"parent\")\n        parent.child = EmbeddedSimpleChild(\"child\")\n\n        val managedParent: EmbeddedSimpleParent = realm.copyToRealm(parent)\n        val managedChild: EmbeddedSimpleChild = managedParent.child!!\n        managedParent.child = null // Will delete the embedded object\n        assertFalse(managedChild.isValid)\n        assertEquals(0, realm.where<EmbeddedSimpleChild>().count())\n    }\n\n    @Test\n    fun dynamicRealm_settingParentFieldDeletesChild() =\n            DynamicRealm.getInstance(realm.configuration).use { realm ->\n                realm.executeTransaction {\n                    val parent = realm.createObject(\"EmbeddedSimpleParent\", \"parent\")\n                    val child = realm.createEmbeddedObject(\"EmbeddedSimpleChild\", parent, \"child\")\n\n                    assertEquals(1, realm.where(\"EmbeddedSimpleChild\").count())\n                    parent.setObject(\"child\", null)\n                    assertFalse(child.isValid)\n                    assertEquals(0, realm.where(\"EmbeddedSimpleChild\").count())\n                }\n            }\n\n    @Test\n    fun objectAccessor_willAutomaticallyCopyUnmanaged() = realm.executeTransaction { realm ->\n        // Checks that adding an unmanaged embedded object to a property will automatically copy it.\n        val parent = EmbeddedSimpleParent(\"parent\")\n        val managedParent: EmbeddedSimpleParent = realm.copyToRealm(parent)\n\n        assertEquals(0, realm.where<EmbeddedSimpleChild>().count())\n        managedParent.child = EmbeddedSimpleChild(\"child\") // Will copy the object to Realm\n        assertEquals(1, realm.where<EmbeddedSimpleChild>().count())\n        assertTrue(managedParent.child!!.isValid)\n    }\n\n    @Test\n    fun objectAccessor_willAutomaticallyCopyManaged() = realm.executeTransaction { realm ->\n        // Checks that setting a link to a managed embedded object will automatically copy it unlike\n        // normal objects that allow multiple parents. Note: This behavior is a bit controversial\n        // and was subject to a lot of discussion during API design. The problem is that making\n        // the behavior explicit will result in an extremely annoying API. We need to carefully\n        // monitor if people understand how this behaves.\n        val managedParent1: EmbeddedSimpleParent = realm.copyToRealm(EmbeddedSimpleParent(\"parent1\"))\n        val managedParent2: EmbeddedSimpleParent = realm.copyToRealm(EmbeddedSimpleParent(\"parent2\"))\n\n        assertEquals(0, realm.where<EmbeddedSimpleChild>().count())\n        managedParent1.child = EmbeddedSimpleChild(\"child\")\n        assertEquals(1, realm.where<EmbeddedSimpleChild>().count())\n        managedParent2.child = managedParent1.child // Will copy the embedded object\n        assertEquals(2, realm.where<EmbeddedSimpleChild>().count())\n        assertNotEquals(managedParent1.child, managedParent2.child)\n    }\n\n    @Test\n    fun objectAccessor_willCopyUnderConstruction() = realm.executeTransaction { realm ->\n        val unmanagedObj = EmbeddedWithConstructorArgs()\n        val managedObj = realm.copyToRealm(unmanagedObj)\n        assertEquals(EmbeddedWithConstructorArgs.INNER_CHILD_ID, managedObj.child!!.childId)\n    }\n\n    @Test\n    fun realmList_add_willAutomaticallyCopy() = realm.executeTransaction { realm ->\n        val parent = realm.copyToRealm(EmbeddedSimpleListParent(\"parent\"))\n        assertTrue(parent.children.add(EmbeddedSimpleChild(\"child\")))\n        val child = parent.children.first()!!\n        assertTrue(child.isValid)\n        assertEquals(\"child\", child.childId)\n\n        // FIXME: How to handle DynamicRealmObject :(\n    }\n\n    @Test\n    fun realmList_addIndex_willAutomaticallyCopy() = realm.executeTransaction { realm ->\n        val parent = realm.copyToRealm(EmbeddedSimpleListParent(\"parent\"))\n        parent.children.add(EmbeddedSimpleChild(\"secondChild\"))\n        parent.children.add(0, EmbeddedSimpleChild(\"firstChild\"))\n        val child = parent.children.first()!!\n        assertTrue(child.isValid)\n        assertEquals(\"firstChild\", child.childId)\n\n        // FIXME: How to handle DynamicRealmObject :(\n    }\n\n    @Test\n    fun realmList_set_willAutomaticallyCopy() = realm.executeTransaction { realm ->\n        // Checks that adding an unmanaged embedded object to a list will automatically make\n        // it managed\n        val parent = realm.copyToRealm(EmbeddedSimpleListParent(\"parent\"))\n        assertTrue(parent.children.add(EmbeddedSimpleChild(\"child\")))\n        assertEquals(1, realm.where<EmbeddedSimpleChild>().count())\n        parent.children[0] = EmbeddedSimpleChild(\"OtherChild\")\n        assertEquals(\"OtherChild\", parent.children.first()!!.childId)\n        assertEquals(1, realm.where<EmbeddedSimpleChild>().count())\n\n        // FIXME: How to handle DynamicRealmObject :(\n    }\n\n    @Test\n    fun copyToRealm_noParentThrows() = realm.executeTransaction {\n        assertFailsWith<IllegalArgumentException> {\n            realm.copyToRealm(EmbeddedSimpleChild(\"child\"))\n        }\n    }\n\n    @Test\n    fun copyToRealmOrUpdate_NoParentThrows() = realm.executeTransaction {\n        assertFailsWith<IllegalArgumentException> {\n            realm.copyToRealmOrUpdate(EmbeddedSimpleChild(\"child\"))\n        }\n    }\n\n    @Test\n    fun copyToRealm_simpleSingleChild() {\n        realm.executeTransaction {\n            val parent = EmbeddedSimpleParent(\"parent1\")\n            parent.child = EmbeddedSimpleChild(\"child1\")\n            it.copyToRealm(parent)\n        }\n\n        assertEquals(1, realm.where<EmbeddedSimpleParent>().count())\n        assertEquals(1, realm.where<EmbeddedSimpleChild>().count())\n    }\n\n    @Test\n    fun copyToRealm_simpleChildList() {\n        realm.executeTransaction {\n            val parent = EmbeddedSimpleListParent(\"parent1\")\n            parent.children = RealmList(EmbeddedSimpleChild(\"child1\"))\n            it.copyToRealm(parent)\n        }\n\n        assertEquals(1, realm.where<EmbeddedSimpleListParent>().count())\n        assertEquals(1, realm.where<EmbeddedSimpleChild>().count())\n    }\n\n    @Test\n    fun copyToRealm_treeSchema() {\n        realm.executeTransaction {\n            val parent = EmbeddedTreeParent(\"parent1\")\n\n            val node1 = EmbeddedTreeNode(\"node1\")\n            node1.leafNode = EmbeddedTreeLeaf(\"leaf1\")\n            parent.middleNode = node1\n            val node2 = EmbeddedTreeNode(\"node2\")\n            node2.leafNodeList.add(EmbeddedTreeLeaf(\"leaf2\"))\n            node2.leafNodeList.add(EmbeddedTreeLeaf(\"leaf3\"))\n            parent.middleNodeList.add(node2)\n\n            it.copyToRealm(parent)\n        }\n\n        assertEquals(1, realm.where<EmbeddedTreeParent>().count())\n        assertEquals(\"parent1\", realm.where<EmbeddedTreeParent>().findFirst()!!._id)\n\n        assertEquals(2, realm.where<EmbeddedTreeNode>().count())\n        val nodeResults = realm.where<EmbeddedTreeNode>().findAll()\n        assertTrue(nodeResults.any { it.treeNodeId == \"node1\" })\n        assertTrue(nodeResults.any { it.treeNodeId == \"node2\" })\n\n        assertEquals(3, realm.where<EmbeddedTreeLeaf>().count())\n        val leafResults = realm.where<EmbeddedTreeLeaf>().findAll()\n        assertTrue(leafResults.any { it.treeLeafId == \"leaf1\" })\n        assertTrue(leafResults.any { it.treeLeafId == \"leaf2\" })\n        assertTrue(leafResults.any { it.treeLeafId == \"leaf3\" })\n    }\n\n    @Test\n    fun copyToRealm_throwsIfMultipleRefsToListObjectsExists() {\n        realm.executeTransaction { r ->\n            val parent = EmbeddedSimpleListParent(\"parent\")\n            val child = EmbeddedSimpleChild(\"child\")\n            parent.children = RealmList(child, child)\n            assertFailsWith<IllegalArgumentException> { r.copyToRealm(parent) }\n        }\n    }\n\n    @Test\n    @Ignore(\"FIXME\")\n    fun copyToRealmOrUpdate_deleteReplacedObjects() {\n        TODO()\n    }\n\n    @Test\n    fun insert_noParentThrows() {\n        realm.executeTransaction { realm ->\n            val child = EmbeddedSimpleChild(\"child\")\n            assertFailsWith<IllegalArgumentException> { realm.insert(child) }\n        }\n    }\n\n    @Test\n    @Ignore(\"Add in another PR\")\n    fun insertOrUpdate_throws() {\n        TODO()\n    }\n\n    @Test\n    fun insert_simpleSingleChild() {\n        realm.executeTransaction {\n            val parent = EmbeddedSimpleParent(\"parent1\")\n            parent.child = EmbeddedSimpleChild(\"child1\")\n            it.insert(parent)\n        }\n\n        assertEquals(1, realm.where<EmbeddedSimpleParent>().count())\n        assertEquals(1, realm.where<EmbeddedSimpleChild>().count())\n    }\n\n    @Test\n    fun insert_simpleChildList() {\n        realm.executeTransaction {\n            val parent = EmbeddedSimpleListParent(\"parent1\")\n            parent.children = RealmList(EmbeddedSimpleChild(\"child1\"))\n            it.insert(parent)\n        }\n\n        assertEquals(1, realm.where<EmbeddedSimpleListParent>().count())\n        assertEquals(1, realm.where<EmbeddedSimpleChild>().count())\n    }\n\n    @Test\n    fun insert_treeSchema() {\n        realm.executeTransaction {\n            val parent = EmbeddedTreeParent(\"parent1\")\n\n            val node1 = EmbeddedTreeNode(\"node1\")\n            node1.leafNode = EmbeddedTreeLeaf(\"leaf1\")\n            parent.middleNode = node1\n            val node2 = EmbeddedTreeNode(\"node2\")\n            node2.leafNodeList.add(EmbeddedTreeLeaf(\"leaf2\"))\n            node2.leafNodeList.add(EmbeddedTreeLeaf(\"leaf3\"))\n            parent.middleNodeList.add(node2)\n\n            it.insert(parent)\n        }\n\n        assertEquals(1, realm.where<EmbeddedTreeParent>().count())\n        assertEquals(\"parent1\", realm.where<EmbeddedTreeParent>().findFirst()!!._id)\n\n        assertEquals(2, realm.where<EmbeddedTreeNode>().count())\n        val nodeResults = realm.where<EmbeddedTreeNode>().findAll()\n        assertTrue(nodeResults.any { it.treeNodeId == \"node1\" })\n        assertTrue(nodeResults.any { it.treeNodeId == \"node2\" })\n\n        assertEquals(3, realm.where<EmbeddedTreeLeaf>().count())\n        val leafResults = realm.where<EmbeddedTreeLeaf>().findAll()\n        assertTrue(leafResults.any { it.treeLeafId == \"leaf1\" })\n        assertTrue(leafResults.any { it.treeLeafId == \"leaf2\" })\n        assertTrue(leafResults.any { it.treeLeafId == \"leaf3\" })\n    }\n\n    @Test\n    fun insertOrUpdate_deletesOldEmbeddedObject() {\n        realm.executeTransaction { realm ->\n            val parent = EmbeddedSimpleParent(\"parent\")\n            val originalChild = EmbeddedSimpleChild(\"originalChild\")\n            parent.child = originalChild\n            realm.insert(parent)\n\n            assertEquals(1, realm.where<EmbeddedSimpleChild>().count())\n            val managedChild = realm.where<EmbeddedSimpleChild>()\n                    .equalTo(\"childId\", \"originalChild\")\n                    .findFirst()\n            assertTrue(managedChild!!.isValid)\n\n            val newChild = EmbeddedSimpleChild(\"newChild\")\n            parent.child = newChild\n            realm.insertOrUpdate(parent)\n            assertTrue(!managedChild.isValid)\n\n            assertEquals(1, realm.where<EmbeddedSimpleChild>().count())\n            val managedNewChild = realm.where<EmbeddedSimpleChild>()\n                    .equalTo(\"childId\", \"newChild\")\n                    .findFirst()\n            assertEquals(managedNewChild!!.childId, \"newChild\")\n            assertEquals(\n                    0,\n                    realm.where<EmbeddedSimpleChild>()\n                            .equalTo(\"childId\", \"originalChild\")\n                            .findAll()\n                            .size\n            )\n        }\n    }\n\n    @Test\n    fun insert_listWithEmbeddedObjects() {\n        realm.executeTransaction { realm ->\n            val list = listOf<EmbeddedSimpleParent>(\n                    EmbeddedSimpleParent(\"parent1\").apply { child = EmbeddedSimpleChild(\"child1\") },\n                    EmbeddedSimpleParent(\"parent2\").apply { child = EmbeddedSimpleChild(\"child2\") },\n                    EmbeddedSimpleParent(\"parent3\").apply { child = EmbeddedSimpleChild(\"child3\") }\n            )\n            realm.insert(list)\n\n            realm.where<EmbeddedSimpleParent>()\n                    .findAll()\n                    .sort(\"_id\")\n                    .also { results ->\n                        assertEquals(3, results.count())\n                        assertEquals(list[0]._id, results[0]!!._id)\n                        assertEquals(list[1]._id, results[1]!!._id)\n                        assertEquals(list[2]._id, results[2]!!._id)\n                        assertEquals(list[0].child!!.childId, results[0]!!.child!!.childId)\n                        assertEquals(list[1].child!!.childId, results[1]!!.child!!.childId)\n                        assertEquals(list[2].child!!.childId, results[2]!!.child!!.childId)\n                    }\n\n            realm.where<EmbeddedSimpleChild>()\n                    .findAll()\n                    .sort(\"childId\")\n                    .also { results ->\n                        assertEquals(3, results.count())\n                        assertEquals(list[0].child!!.childId, results[0]!!.childId)\n                        assertEquals(list[1].child!!.childId, results[1]!!.childId)\n                        assertEquals(list[2].child!!.childId, results[2]!!.childId)\n                        assertEquals(list[0]._id, results[0]!!.parent._id)\n                        assertEquals(list[1]._id, results[1]!!.parent._id)\n                        assertEquals(list[2]._id, results[2]!!.parent._id)\n                    }\n        }\n    }\n\n    @Test\n    fun insert_listWithEmbeddedObjects_duplicatePrimaryKeyThrows() {\n        realm.executeTransaction { realm ->\n            val list = listOf<EmbeddedSimpleParent>(\n                    EmbeddedSimpleParent(\"parent1\").apply { child = EmbeddedSimpleChild(\"child1\") },\n                    EmbeddedSimpleParent(\"parent2\").apply { child = EmbeddedSimpleChild(\"child2\") },\n                    EmbeddedSimpleParent(\"parent3\").apply { child = EmbeddedSimpleChild(\"child3\") }\n            )\n            realm.insert(list)\n\n            assertFailsWith<RealmPrimaryKeyConstraintException> {\n                realm.insert(list)\n            }\n        }\n    }\n\n    @Test\n    fun insert_listWithEmbeddedObjects_insertingChildrenDirectlyThrows() {\n        val list = listOf<EmbeddedSimpleChild>(\n                EmbeddedSimpleChild(\"child1\"),\n                EmbeddedSimpleChild(\"child2\"),\n                EmbeddedSimpleChild(\"child3\")\n        )\n\n        realm.executeTransaction { realm ->\n            assertFailsWith<IllegalArgumentException> {\n                realm.insert(list);\n            }\n        }\n    }\n\n    @Test\n    fun insertOrUpdate_listWithEmbeddedObjects() {\n        realm.executeTransaction { realm ->\n            val list = listOf<EmbeddedSimpleParent>(\n                    EmbeddedSimpleParent(\"parent1\").apply { child = EmbeddedSimpleChild(\"child1\") },\n                    EmbeddedSimpleParent(\"parent2\").apply { child = EmbeddedSimpleChild(\"child2\") },\n                    EmbeddedSimpleParent(\"parent3\").apply { child = EmbeddedSimpleChild(\"child3\") }\n            )\n            realm.insert(list)\n\n            val newList = listOf<EmbeddedSimpleParent>(\n                    EmbeddedSimpleParent(\"parent1\").apply { child = EmbeddedSimpleChild(\"newChild1\") },\n                    EmbeddedSimpleParent(\"parent2\").apply { child = EmbeddedSimpleChild(\"newChild2\") },\n                    EmbeddedSimpleParent(\"parent3\").apply { child = EmbeddedSimpleChild(\"newChild3\") }\n            )\n            realm.insertOrUpdate(newList)\n\n            assertNull(realm.where<EmbeddedSimpleChild>().equalTo(\"childId\", list[0].child!!.childId).findFirst())\n            assertNull(realm.where<EmbeddedSimpleChild>().equalTo(\"childId\", list[1].child!!.childId).findFirst())\n            assertNull(realm.where<EmbeddedSimpleChild>().equalTo(\"childId\", list[2].child!!.childId).findFirst())\n            assertNotNull(realm.where<EmbeddedSimpleChild>().equalTo(\"childId\", newList[0].child!!.childId).findFirst())\n            assertNotNull(realm.where<EmbeddedSimpleChild>().equalTo(\"childId\", newList[1].child!!.childId).findFirst())\n            assertNotNull(realm.where<EmbeddedSimpleChild>().equalTo(\"childId\", newList[2].child!!.childId).findFirst())\n\n            val query = realm.where<EmbeddedSimpleParent>()\n            assertEquals(3, query.count())\n            query.findAll()\n                    .sort(\"_id\")\n                    .also { results ->\n                        assertEquals(newList[0]._id, results[0]!!._id)\n                        assertEquals(newList[1]._id, results[1]!!._id)\n                        assertEquals(newList[2]._id, results[2]!!._id)\n                        assertEquals(newList[0].child!!.childId, results[0]!!.child!!.childId)\n                        assertEquals(newList[1].child!!.childId, results[1]!!.child!!.childId)\n                        assertEquals(newList[2].child!!.childId, results[2]!!.child!!.childId)\n                    }\n\n            realm.where<EmbeddedSimpleParent>()\n                    .also { assertEquals(3, it.count()) }\n                    .findAll()\n                    .sort(\"_id\")\n                    .also { results ->\n                        assertEquals(newList[0]._id, results[0]!!._id)\n                        assertEquals(newList[1]._id, results[1]!!._id)\n                        assertEquals(newList[2]._id, results[2]!!._id)\n                        assertEquals(newList[0].child!!.childId, results[0]!!.child!!.childId)\n                        assertEquals(newList[1].child!!.childId, results[1]!!.child!!.childId)\n                        assertEquals(newList[2].child!!.childId, results[2]!!.child!!.childId)\n                    }\n        }\n    }\n\n    // TODO Move all json import tests to RealmJsonTests when RealmJsonTests have been\n    //  converted to Kotlin\n    // Sanity check of string based variants. Implementation dispatches to json variant covered\n    // below, so not covering all cases for the string-variants.\n    @Test\n    fun createObjectFromJson_json_embeddedObjectList() {\n        realm.executeTransaction { realm ->\n            realm.createObjectFromJson(EmbeddedSimpleListParent::class.java, json(simpleListParentData))\n        }\n        val parent = realm.where(EmbeddedSimpleListParent::class.java).findFirst()!!\n        assertEquals(3, parent.children.count())\n        assertEquals(childId1, parent.children[0]!!.childId)\n        assertEquals(childId2, parent.children[1]!!.childId)\n        assertEquals(childId3, parent.children[2]!!.childId)\n    }\n\n    @Test\n    fun createObjectFromJson_stream_embeddedObjectList() {\n        val clz = EmbeddedSimpleListParent::class.java\n        realm.executeTransaction { realm ->\n            assertTrue(realm.schema.getSchemaForClass(clz).hasPrimaryKey())\n            realm.createObjectFromJson(clz, stream(simpleListParentData))\n        }\n        val all = realm.where(EmbeddedSimpleListParent::class.java).findAll()\n        assertEquals(1, all.count())\n        val parent = all.first()!!\n        assertEquals(3, parent.children.count())\n        assertEquals(childId1, parent.children[0]!!.childId)\n        assertEquals(childId2, parent.children[1]!!.childId)\n        assertEquals(childId3, parent.children[2]!!.childId)\n    }\n\n    // Stream based import implementation is differentiated depending on whether the class has a primary key\n    @Test\n    fun createObjectFromJson_stream_embeddedObjectListWithNoPrimaryKeyParent() {\n        val clz = EmbeddedSimpleListParentWithoutPrimaryKey::class.java\n        realm.executeTransaction { realm ->\n            assertFalse(realm.schema.getSchemaForClass(clz).hasPrimaryKey())\n            realm.createObjectFromJson(clz, stream(simpleListParentData))\n        }\n        val all = realm.where(EmbeddedSimpleListParentWithoutPrimaryKey::class.java).findAll()\n        assertEquals(1, all.count())\n        val parent = all.first()!!\n        assertEquals(parentId, parent._id)\n        assertEquals(3, parent.children.count())\n        assertEquals(childId1, parent.children[0]!!.childId)\n        assertEquals(childId2, parent.children[1]!!.childId)\n        assertEquals(childId3, parent.children[2]!!.childId)\n    }\n\n    @Test\n    fun createObjectFromJson_orphanedEmbeddedObjectThrows() {\n        throws { realm.createObjectFromJson(EmbeddedSimpleChild::class.java, json(simpleListParentData)) }\n        throws { realm.createObjectFromJson(EmbeddedSimpleChild::class.java, string(simpleListParentData)) }\n        throws { realm.createObjectFromJson(EmbeddedSimpleChild::class.java, stream(simpleListParentData)) }\n    }\n\n    private fun throws(block: () -> Unit) {\n        assertFailsWith<IllegalArgumentException> {\n            realm.executeTransaction { realm ->\n                block()\n            }\n        }\n    }\n\n\n    @Test\n    fun realmObjectSchema_setEmbedded() {\n        DynamicRealm.getInstance(realm.configuration).use { realm ->\n            realm.executeTransaction {\n                val objSchema: RealmObjectSchema = realm.schema[EmbeddedSimpleChild.NAME]!!\n                assertTrue(objSchema.isEmbedded)\n                objSchema.isEmbedded = false\n                assertFalse(objSchema.isEmbedded)\n                objSchema.isEmbedded = true\n                assertTrue(objSchema.isEmbedded)\n            }\n        }\n    }\n\n    @Test\n    fun realmObjectSchema_setEmbedded_throwsWithPrimaryKey() {\n        DynamicRealm.getInstance(realm.configuration).use { realm ->\n            realm.executeTransaction {\n                val objSchema: RealmObjectSchema = realm.schema[AllJavaTypes.CLASS_NAME]!!\n                assertFailsWith<IllegalStateException> { objSchema.isEmbedded = true }\n            }\n        }\n    }\n\n    @Test\n    fun realmObjectSchema_setEmbedded_throwsIfBreaksParentInvariants() {\n        // Classes can only be converted to be embedded if all objects have exactly one other\n        // object pointing to it.\n        DynamicRealm.getInstance(realm.configuration).use { realm ->\n            realm.executeTransaction {\n\n                // Create object with no parents\n                realm.createObject(Dog.CLASS_NAME)\n                val dogSchema = realm.schema[Dog.CLASS_NAME]!!\n                 assertFailsWith<IllegalStateException> {\n                    dogSchema.isEmbedded = true\n                 }\n\n                // Create object with two parents\n                val cat: DynamicRealmObject = realm.createObject(Cat.CLASS_NAME)\n                val owner1: DynamicRealmObject = realm.createObject(Owner.CLASS_NAME)\n                owner1.setObject(Owner.FIELD_CAT, cat)\n                val owner2: DynamicRealmObject = realm.createObject(Owner.CLASS_NAME)\n                owner2.setObject(Owner.FIELD_CAT, cat)\n                val catSchema = realm.schema[Cat.CLASS_NAME]!!\n                assertFailsWith<IllegalStateException> {\n                    catSchema.isEmbedded = true\n                }\n            }\n        }\n    }\n\n    @Test\n    fun realmObjectSchema_isEmbedded() {\n        assertTrue(realm.schema[EmbeddedSimpleChild.NAME]!!.isEmbedded)\n        assertFalse(realm.schema[AllTypes.CLASS_NAME]!!.isEmbedded)\n    }\n\n    @Test\n    fun dynamicRealm_realmObjectSchema_isEmbedded() {\n        DynamicRealm.getInstance(realm.configuration).use { realm ->\n            assertTrue(realm.schema[EmbeddedSimpleChild.NAME]!!.isEmbedded)\n            assertFalse(realm.schema[AllTypes.CLASS_NAME]!!.isEmbedded)\n        }\n    }\n\n    // Check that deleting a non-embedded parent deletes all embedded children\n    @Test\n    fun deleteParentObject_deletesEmbeddedChildren() = realm.executeTransaction {\n        val parent = EmbeddedSimpleParent(\"parent\")\n        parent.child = EmbeddedSimpleChild(\"child\")\n\n        val managedParent: EmbeddedSimpleParent = it.copyToRealm(parent)\n        assertEquals(1, realm.where<EmbeddedSimpleChild>().count())\n        val managedChild: EmbeddedSimpleChild = managedParent.child!!\n\n        managedParent.deleteFromRealm()\n        assertFalse(managedChild.isValid)\n        assertEquals(0, realm.where<EmbeddedSimpleParent>().count())\n        assertEquals(0, realm.where<EmbeddedSimpleChild>().count())\n    }\n\n    @Test\n    fun dynamicRealm_deleteParentObject_deletesEmbeddedChildren() =\n            DynamicRealm.getInstance(realm.configuration).use { realm ->\n                realm.executeTransaction {\n                    val parent = realm.createObject(\"EmbeddedSimpleParent\", \"parent\")\n                    assertEquals(0, realm.where(\"EmbeddedSimpleChild\").count())\n\n                    val child = realm.createEmbeddedObject(\"EmbeddedSimpleChild\", parent, \"child\")\n                    assertEquals(1, realm.where(\"EmbeddedSimpleChild\").count())\n\n                    parent.deleteFromRealm()\n                    assertFalse(child.isValid)\n                    assertEquals(0, realm.where(\"EmbeddedSimpleParent\").count())\n                    assertEquals(0, realm.where(\"EmbeddedSimpleChild\").count())\n                }\n            }\n\n    // Check that deleting a embedded parent deletes all embedded children\n    @Test\n    fun deleteParentEmbeddedObject_deletesEmbeddedChildren() = realm.executeTransaction {\n        val parent = EmbeddedTreeParent(\"parent1\")\n        val middleNode = EmbeddedTreeNode(\"node1\")\n        middleNode.leafNode = EmbeddedTreeLeaf(\"leaf1\")\n        middleNode.leafNodeList.add(EmbeddedTreeLeaf(\"leaf2\"))\n        middleNode.leafNodeList.add(EmbeddedTreeLeaf(\"leaf3\"))\n        parent.middleNode = middleNode\n\n        val managedParent: EmbeddedTreeParent = it.copyToRealm(parent)\n        assertEquals(1, realm.where<EmbeddedTreeNode>().count())\n        assertEquals(3, realm.where<EmbeddedTreeLeaf>().count())\n        managedParent.deleteFromRealm()\n        assertEquals(0, realm.where<EmbeddedTreeNode>().count())\n        assertEquals(0, realm.where<EmbeddedSimpleChild>().count())\n    }\n\n    @Test\n    fun dynamic_deleteParentEmbeddedObject_deletesEmbeddedChildren() =\n            DynamicRealm.getInstance(realm.configuration).use { realm ->\n                realm.executeTransaction {\n                    val parent = realm.createObject(\"EmbeddedTreeParent\", \"parent1\")\n                    val middleNode = realm.createEmbeddedObject(\"EmbeddedTreeNode\", parent, \"middleNode\")\n                    middleNode.setString(\"treeNodeId\", \"node1\")\n                    val leaf1 = realm.createEmbeddedObject(\"EmbeddedTreeLeaf\", middleNode, \"leafNode\")\n                    val leaf2 = realm.createEmbeddedObject(\"EmbeddedTreeLeaf\", middleNode, \"leafNodeList\")\n                    val leaf3 = realm.createEmbeddedObject(\"EmbeddedTreeLeaf\", middleNode, \"leafNodeList\")\n\n                    assertEquals(1, realm.where(\"EmbeddedTreeNode\").count())\n                    assertEquals(3, realm.where(\"EmbeddedTreeLeaf\").count())\n                    parent.deleteFromRealm()\n                    assertEquals(0, realm.where(\"EmbeddedTreeNode\").count())\n                    assertEquals(0, realm.where(\"EmbeddedSimpleChild\").count())\n                    assertFalse(parent.isValid)\n                    assertFalse(middleNode.isValid)\n                    assertFalse(leaf1.isValid)\n                    assertFalse(leaf2.isValid)\n                    assertFalse(leaf3.isValid)\n                }\n            }\n\n    // Cascade deleting an embedded object will trigger its object listener.\n    @Test\n    fun deleteParent_triggerChildObjectNotifications() = looperThread.runBlocking {\n        val realm = Realm.getInstance(realm.configuration)\n        looperThread.closeAfterTest(realm)\n\n        realm.executeTransaction {\n            val parent = EmbeddedSimpleParent(\"parent\")\n            val child = EmbeddedSimpleChild(\"child\")\n            parent.child = child\n            it.copyToRealm(parent)\n        }\n\n        val child = realm.where<EmbeddedSimpleParent>().findFirst()!!.child!!\n        child.addChangeListener(RealmChangeListener<EmbeddedSimpleChild> {\n            if (!it.isValid) {\n                looperThread.testComplete()\n            }\n        })\n\n        realm.executeTransaction {\n            child.parent.deleteFromRealm()\n        }\n    }\n\n    @Test\n    fun dynamicRealm_deleteParent_triggerChildObjectNotifications() = looperThread.runBlocking {\n        val realm = DynamicRealm.getInstance(realm.configuration)\n        looperThread.closeAfterTest(realm)\n\n        realm.executeTransaction {\n            val parent = realm.createObject(\"EmbeddedSimpleParent\", \"parent\")\n            realm.createEmbeddedObject(\"EmbeddedSimpleChild\", parent, \"child\")\n        }\n\n        val queriedChild = realm.where(\"EmbeddedSimpleParent\")\n                .findFirst()!!\n                .getObject(\"child\")!!\n                .apply {\n                    addChangeListener(RealmChangeListener<DynamicRealmObject> {\n                        if (!it.isValid) {\n                            looperThread.testComplete()\n                        }\n                    })\n                }\n\n        realm.executeTransaction {\n            queriedChild.linkingObjects(\"EmbeddedSimpleParent\", \"child\")\n                    .first()!!\n                    .deleteFromRealm()\n        }\n    }\n\n    // Cascade deleting a parent will trigger the listener on any lists in child embedded\n    // objects\n    @Test\n    fun deleteParent_triggerChildListObjectNotifications() = looperThread.runBlocking {\n        val realm = Realm.getInstance(realm.configuration)\n        looperThread.closeAfterTest(realm)\n\n        realm.executeTransaction {\n            val parent = EmbeddedSimpleListParent(\"parent\")\n            val child1 = EmbeddedSimpleChild(\"child1\")\n            val child2 = EmbeddedSimpleChild(\"child2\")\n            parent.children.add(child1)\n            parent.children.add(child2)\n            it.copyToRealm(parent)\n        }\n\n        val children: RealmList<EmbeddedSimpleChild> = realm.where<EmbeddedSimpleListParent>()\n                .findFirst()!!\n                .children\n\n        children.addChangeListener { list ->\n            if (!list.isValid) {\n                looperThread.testComplete()\n            }\n        }\n\n        realm.executeTransaction {\n            realm.where<EmbeddedSimpleListParent>().findFirst()!!.deleteFromRealm()\n        }\n    }\n\n    @Test\n    fun dynamicRealm_deleteParent_triggerChildListObjectNotifications() = looperThread.runBlocking {\n        val realm = DynamicRealm.getInstance(realm.configuration)\n        looperThread.closeAfterTest(realm)\n\n        realm.executeTransaction {\n            val parent = realm.createObject(\"EmbeddedSimpleListParent\", \"parent\")\n            realm.createEmbeddedObject(\"EmbeddedSimpleChild\", parent, \"children\")\n            realm.createEmbeddedObject(\"EmbeddedSimpleChild\", parent, \"children\")\n        }\n\n        realm.where(\"EmbeddedSimpleListParent\")\n                .findFirst()!!\n                .getList(\"children\")\n                .apply {\n                    addChangeListener { list ->\n                        if (!list.isValid) {\n                            looperThread.testComplete()\n                        }\n                    }\n                }\n\n        realm.executeTransaction {\n            realm.where(\"EmbeddedSimpleListParent\")\n                    .findFirst()!!\n                    .deleteFromRealm()\n        }\n    }\n\n    @Test\n    fun copyToRealmOrUpdate_replacesEmbededdList() {\n        realm.beginTransaction()\n        val parent = EmbeddedTreeParent()\n        parent.middleNodeList = RealmList(EmbeddedTreeNode(\"1\"), EmbeddedTreeNode(\"2\"))\n        parent._id = \"1\"\n        realm.copyToRealm(parent)\n        realm.commitTransaction()\n\n        realm.beginTransaction()\n        parent.middleNodeList.add(EmbeddedTreeNode(\"3\"))\n        val managedParent = realm.copyToRealmOrUpdate(parent)\n        assertEquals(3, managedParent.middleNodeList.size)\n        realm.commitTransaction()\n    }\n\n    @Test\n    fun insertOrUpdate_replacesEmbededdList() {\n        realm.beginTransaction()\n        val parent = EmbeddedTreeParent()\n        parent.middleNodeList = RealmList(EmbeddedTreeNode(\"1\"), EmbeddedTreeNode(\"2\"))\n        parent._id = \"1\"\n        val managedParent = realm.copyToRealm(parent)\n        realm.commitTransaction()\n\n        realm.beginTransaction()\n\n        // insertOrUpdate has different code paths for lists of equal size vs. lists of different sizes\n        parent.middleNodeList = RealmList(EmbeddedTreeNode(\"3\"), EmbeddedTreeNode(\"4\"))\n        realm.insertOrUpdate(parent)\n        assertEquals(2, managedParent.middleNodeList.size)\n        assertEquals(\"3\", managedParent.middleNodeList[0]!!.treeNodeId)\n        assertEquals(\"4\", managedParent.middleNodeList[1]!!.treeNodeId)\n\n        parent.middleNodeList.add(EmbeddedTreeNode(\"5\"))\n        realm.insertOrUpdate(parent)\n        assertEquals(3, managedParent.middleNodeList.size)\n        realm.commitTransaction()\n    }\n\n    @Test\n    @Ignore(\"Add in another PR\")\n    fun results_bulkUpdate() {\n        // What happens if you bulk update a RealmResults. Should it be allowed to use embeded\n        // objects here?\n        TODO()\n    }\n\n    // Convenience methods to create json in various forms from a map\n    private fun json(data: Map<String, Any>) = JSONObject(data)\n    private fun string(data: Map<String, Any>) = json(data).toString()\n    private fun stream(data: Map<String, Any>) =\n            ByteArrayInputStream(JSONObject(data).toString().toByteArray(UTF_8))\n\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/kotlin/io/realm/GenericTester.kt",
    "content": "/*\n * Copyright 2021 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\npackage io.realm\n\nimport io.realm.entities.AllTypes\nimport io.realm.entities.DictionaryAllTypes\nimport io.realm.entities.SetAllTypes\nimport io.realm.kotlin.createObject\nimport io.realm.kotlin.where\nimport io.realm.rule.BlockingLooperThread\nimport kotlin.test.assertEquals\nimport kotlin.test.assertNotNull\n\n/**\n * Generic tester for parameterized tests. Includes two types of `setUp` functions.\n */\ninterface GenericTester {\n    fun setUp(config: RealmConfiguration, looperThread: BlockingLooperThread)\n    fun setUp(configFactory: TestRealmConfigurationFactory)\n    fun tearDown()\n}\n\n/**\n * TODO: rename SetContainerClass to \"CollectionContainer\" and add all possible RealmList, RealmSet\n *  and RealmDictionary fields in that class and use it for Dictionary and Set tests. Use this new\n *  container instead of \"DictionaryAllTypes\".\n */\nfun createCollectionAllTypesManagedContainerAndAssert(\n    realm: Realm,\n    id: String? = null\n): DictionaryAllTypes {\n    var dictionaryAllTypesObject: DictionaryAllTypes? = null\n    realm.executeTransaction { transactionRealm ->\n        dictionaryAllTypesObject = transactionRealm.createObject()\n        assertNotNull(dictionaryAllTypesObject)\n\n        // Assign id if we have one\n        if (id != null) {\n            dictionaryAllTypesObject!!.columnString = id\n        }\n    }\n    val allTypesObjectFromRealm = if (id == null) {\n        realm.where<DictionaryAllTypes>().equalTo(\"columnString\", \"\").findFirst()\n    } else {\n        realm.where<DictionaryAllTypes>().equalTo(\"columnString\", id).findFirst()\n    }\n    assertEquals(dictionaryAllTypesObject, allTypesObjectFromRealm)\n    return dictionaryAllTypesObject!!\n}\n\n/**\n * TODO: migrate set fields from AllTypes to a \"CollectionContainer\" class and remove this\n *  method once sets are done.\n */\nfun createAllTypesManagedContainerAndAssert(\n    realm: Realm,\n    id: String? = null,\n    inTransaction: Boolean = false\n): SetAllTypes {\n    if (!inTransaction) {\n        realm.beginTransaction()\n    }\n\n    val allTypesObject: SetAllTypes = realm.createObject()\n    assertNotNull(allTypesObject)\n\n    // Assign id if we have one\n    if (id != null) {\n        allTypesObject.columnString = id\n    }\n\n    if (!inTransaction) {\n        realm.commitTransaction()\n    }\n\n    val allTypesObjectFromRealm = if (id == null) {\n        realm.where<SetAllTypes>().equalTo(AllTypes.FIELD_STRING, \"\").findFirst()\n    } else {\n        realm.where<SetAllTypes>().equalTo(AllTypes.FIELD_STRING, id).findFirst()\n    }\n    assertEquals(allTypesObject, allTypesObjectFromRealm)\n    return allTypesObject\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/kotlin/io/realm/KotlinSchemaTests.kt",
    "content": "/*\n * Copyright 2017 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 */\npackage io.realm\n\nimport androidx.test.ext.junit.runners.AndroidJUnit4\nimport io.realm.entities.AllKotlinTypes\nimport org.junit.After\nimport org.junit.Assert.assertFalse\nimport org.junit.Assert.assertTrue\nimport org.junit.Before\nimport org.junit.Rule\nimport org.junit.Test\nimport org.junit.runner.RunWith\n\n/**\n * This class tests how Kotlin classes are interpreted by Realm and exposed in the RealmSchema\n */\n@RunWith(AndroidJUnit4::class)\nclass KotlinSchemaTests {\n\n    @get:Rule\n    val configFactory = TestRealmConfigurationFactory()\n\n    private lateinit var realm: Realm\n\n    @Before\n    fun setUp() {\n        realm = Realm.getInstance(configFactory.createConfiguration())\n    }\n\n    @After\n    fun tearDown() {\n        realm.close()\n    }\n\n    @Test\n    fun kotlinTypeNonNull() {\n        val objSchema = realm.schema.get(AllKotlinTypes::class.simpleName!!)!!\n\n        assertFalse(objSchema.isNullable(AllKotlinTypes::nonNullBinary.name));\n        assertFalse(objSchema.isNullable(AllKotlinTypes::nonNullBoolean.name));\n        assertFalse(objSchema.isNullable(AllKotlinTypes::nonNullString.name));\n        assertFalse(objSchema.isNullable(AllKotlinTypes::nonNullLong.name));\n        assertFalse(objSchema.isNullable(AllKotlinTypes::nonNullInt.name));\n        assertFalse(objSchema.isNullable(AllKotlinTypes::nonNullShort.name));\n        assertFalse(objSchema.isNullable(AllKotlinTypes::nonNullByte.name));\n        assertFalse(objSchema.isNullable(AllKotlinTypes::nonNullDate.name));\n        assertFalse(objSchema.isNullable(AllKotlinTypes::nonNullDouble.name));\n        assertFalse(objSchema.isNullable(AllKotlinTypes::nonNullFloat.name));\n        assertFalse(objSchema.isNullable(AllKotlinTypes::nonNullList.name));\n        // We cannot enforce this constraint inside the schema right now.\n        // If people maintain the variant themselves they need a custom getter\n        // assertTrue(objSchema.isNullable(AllKotlinTypes::nonNullObject.name));\n    }\n\n    @Test\n    fun kotlinTypeNull() {\n        val objSchema = realm.schema.get(AllKotlinTypes::class.simpleName!!)!!\n        assertTrue(objSchema.isNullable(AllKotlinTypes::nullBinary.name));\n        assertTrue(objSchema.isNullable(AllKotlinTypes::nullBoolean.name));\n        assertTrue(objSchema.isNullable(AllKotlinTypes::nullString.name));\n        assertTrue(objSchema.isNullable(AllKotlinTypes::nullLong.name));\n        assertTrue(objSchema.isNullable(AllKotlinTypes::nullInt.name));\n        assertTrue(objSchema.isNullable(AllKotlinTypes::nullShort.name));\n        assertTrue(objSchema.isNullable(AllKotlinTypes::nullByte.name));\n        assertTrue(objSchema.isNullable(AllKotlinTypes::nullDate.name));\n        assertTrue(objSchema.isNullable(AllKotlinTypes::nullDouble.name));\n        assertTrue(objSchema.isNullable(AllKotlinTypes::nullFloat.name));\n        assertFalse(objSchema.isNullable(AllKotlinTypes::nullList.name)); // Managed realm objects do not allow null lists\n        assertTrue(objSchema.isNullable(AllKotlinTypes::nullObject.name));\n    }\n\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/kotlin/io/realm/ManagedDictionaryTesters.kt",
    "content": "/*\n * Copyright 2020 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\npackage io.realm\n\nimport io.realm.entities.DictionaryAllTypes\nimport io.realm.entities.DogPrimaryKey\nimport io.realm.entities.PopulatedDictionaryClass\nimport io.realm.entities.PrimaryKeyDictionaryContainer\nimport io.realm.kotlin.createObject\nimport io.realm.kotlin.where\nimport io.realm.rule.BlockingLooperThread\nimport org.bson.types.Decimal128\nimport org.bson.types.ObjectId\nimport java.lang.reflect.InvocationTargetException\nimport java.util.*\nimport kotlin.reflect.KFunction1\nimport kotlin.reflect.KFunction2\nimport kotlin.reflect.KProperty1\nimport kotlin.test.*\n\n/**\n * Generic tester for all types of managed dictionaries.\n *\n * It uses `KFunction1` and `KFunction2` to streamline the access to [RealmDictionary] fields in\n * [DictionaryAllTypes]. This way we only need one tester for all supported types.\n */\nclass ManagedDictionaryTester<T : Any>(\n        private val testerClass: String,\n        private val realmAnyType: RealmAny.Type? = null,\n        private val dictionaryFieldName: String,\n        private val dictionaryFieldClass: Class<T>,\n        private val dictionaryGetter: KFunction1<DictionaryAllTypes, RealmDictionary<T>>,\n        private val dictionarySetter: KFunction2<DictionaryAllTypes, RealmDictionary<T>, Unit>,\n        private val requiredDictionaryGetter: KFunction1<DictionaryAllTypes, RealmDictionary<T>>? = null,\n        private val initializedDictionary: RealmDictionary<T>,\n        private val alternativeDictionary: RealmDictionary<T>,\n        private val notPresentValue: T,\n        private val populatedGetter: KProperty1<PopulatedDictionaryClass, RealmDictionary<T>>,\n        private val typeAsserter: TypeAsserter<T> = TypeAsserter(),\n        private val primaryKeyDictionaryProperty: KProperty1<PrimaryKeyDictionaryContainer, RealmDictionary<T>>\n) : DictionaryTester {\n\n    private lateinit var config: RealmConfiguration\n    private lateinit var looperThread: BlockingLooperThread\n    private lateinit var realm: Realm\n\n    override fun toString(): String = when (realmAnyType) {\n        null -> \"ManagedDictionary-$testerClass\"\n        else -> \"ManagedDictionary-$testerClass\" + realmAnyType.name.let { \"-$it\" }\n    }\n\n    override fun setUp(config: RealmConfiguration, looperThread: BlockingLooperThread) {\n        this.config = config\n        this.looperThread = looperThread\n        this.realm = Realm.getInstance(config)\n    }\n\n    override fun tearDown() = realm.close()\n\n    override fun constructorWithAnotherMap() = Unit             // Not applicable in managed mode\n\n    override fun isManaged() = assertTrue(initAndAssert().isManaged)\n\n    override fun isValid() = assertTrue(initAndAssert().isValid)\n\n    override fun isFrozen() {\n        val dictionary = initAndAssert()\n        assertFalse(dictionary.isFrozen)\n        val frozenDictionary = dictionary.freeze()\n        assertTrue(frozenDictionary.isFrozen)\n    }\n\n    override fun size() {\n        val dictionary = initAndAssert()\n        assertEquals(0, dictionary.size)\n        realm.executeTransaction {\n            initializedDictionary.forEach { key, value ->\n                dictionary[key] = value\n            }\n        }\n        assertEquals(initializedDictionary.size, dictionary.size)\n    }\n\n    override fun isEmpty() {\n        val dictionary = initAndAssert()\n        assertTrue(dictionary.isEmpty())\n        realm.executeTransaction {\n            initializedDictionary.forEach { key, value ->\n                dictionary[key] = value\n            }\n        }\n        assertFalse(dictionary.isEmpty())\n    }\n\n    override fun containsKey() {\n        val dictionary = initAndAssert()\n\n        initializedDictionary.forEach { key, _ ->\n            assertFalse(dictionary.containsKey(key))\n        }\n\n        realm.executeTransaction {\n            initializedDictionary.forEach { key, value ->\n                dictionary[key] = value\n            }\n        }\n\n        initializedDictionary.forEach { key, _ ->\n            assertTrue(dictionary.containsKey(key))\n        }\n\n        assertFailsWith<NullPointerException> {\n            dictionary.containsKey(null)\n        }\n\n        val somethingEntirelyDifferent = initializedDictionary.map { (key, _) ->\n            Pair(key, key)\n        }\n        assertFailsWith<ClassCastException> {\n            dictionary.containsKey(somethingEntirelyDifferent as Any)\n        }\n    }\n\n    override fun containsValue() {\n        val dictionary = initAndAssert()\n\n        initializedDictionary.values.forEachIndexed { index, value ->\n            typeAsserter.assertContainsValueNotThere(realm, dictionary, index, value)\n        }\n\n        realm.executeTransaction {\n            initializedDictionary.forEach { key, value ->\n                dictionary[key] = value\n            }\n        }\n\n        dictionary.forEach { key, value ->\n            typeAsserter.assertContainsValueHelper(realm, key, value, initializedDictionary, dictionary)\n        }\n\n        val somethingEntirelyDifferent = initializedDictionary.map { (key, _) ->\n            Pair(key, key)\n        }\n        assertFailsWith<ClassCastException> {\n            dictionary.containsValue(somethingEntirelyDifferent as Any)\n        }\n    }\n\n    override fun get() {\n        val dictionary = initAndAssert()\n        initializedDictionary.forEach { key, _ ->\n            assertNull(dictionary[key])\n        }\n        realm.executeTransaction {\n            initializedDictionary.forEach { key, value ->\n                dictionary[key] = value\n            }\n        }\n        initializedDictionary.forEach { key, value ->\n            typeAsserter.assertEqualsHelper(realm, value, dictionary[key])\n        }\n\n        assertFailsWith<NullPointerException> {\n            dictionary.get(TestHelper.getNull())\n        }\n\n        val somethingEntirelyDifferent = initializedDictionary.map { (key, _) ->\n            Pair(key, key)\n        }\n        assertFailsWith<ClassCastException> {\n            dictionary.get(somethingEntirelyDifferent as Any)\n        }\n    }\n\n    override fun put() = putInternal(initializedDictionary, alternativeDictionary)\n\n    override fun putRequired() {\n        // RealmModel and RealmAny dictionaries are ignored since they cannot be marked with \"@Required\"\n        if (requiredDictionaryGetter != null) {\n            val allTypesObject = createCollectionAllTypesManagedContainerAndAssert(realm)\n            assertNotNull(allTypesObject)\n            val dictionary = requiredDictionaryGetter.call(allTypesObject)\n\n            // Check we can't insert null on a RealmDictionary marked as \"@Required\"\n            realm.executeTransaction {\n                assertFailsWith<NullPointerException> {\n                    dictionary[\"requiredKey\"] = null\n                }\n            }\n\n            // Now check it works normally for the same field but without inserting null values\n            val initializedNoNull = initializedDictionary.apply { assertNull(remove(KEY_NULL)) }\n            val alternativeNoNull = alternativeDictionary.apply { assertNull(remove(KEY_NULL)) }\n            putInternal(initializedNoNull, alternativeNoNull)\n        }\n    }\n\n    override fun remove() {\n        val dictionary = initAndAssert()\n        realm.executeTransaction {\n            initializedDictionary.forEach { key, value ->\n                dictionary[key] = value\n            }\n        }\n\n        // Remove, assert value and check size\n        realm.executeTransaction {\n            initializedDictionary.map {\n                Pair(it.key, it.value)\n            }.also { pairs ->\n                for (index in pairs.size - 1 downTo 0) {\n                    val key = pairs[index].first\n                    val value = pairs[index].second\n                    typeAsserter.assertEqualsHelper(realm, value, dictionary.remove(key))\n                    assertEquals(index, dictionary.size)\n\n                    // Special case for RealmModels: remove the actual object from the Realm and\n                    // check how that affects the dictionary\n                    typeAsserter.assertRemoveRealmModelFromRealm(dictionary, index, key, value)\n                }\n            }\n\n            assertFailsWith<NullPointerException> {\n                dictionary.remove(TestHelper.getNull())\n            }\n\n            val somethingEntirelyDifferent = initializedDictionary.map { (key, _) ->\n                Pair(key, key)\n            }\n            assertFailsWith<ClassCastException> {\n                dictionary.remove(somethingEntirelyDifferent as Any)\n            }\n        }\n    }\n\n    override fun putAll() {\n        val dictionary = initAndAssert()\n        val anotherDictionary = initAndAssert(id = \"anotherDictionary\")\n\n        assertTrue(dictionary.isEmpty())\n        assertTrue(anotherDictionary.isEmpty())\n\n        realm.executeTransaction {\n            dictionary.putAll(initializedDictionary)\n\n            // Check initialized dictionary got inserted\n            initializedDictionary.forEach { key, value ->\n                typeAsserter.assertEqualsHelper(realm, value, dictionary[key])\n            }\n\n            // Put a managed dictionary (itself)\n            dictionary.putAll(dictionary)\n            assertEquals(dictionary.size, initializedDictionary.size)\n\n            // Put a managed dictionary containing something else\n            anotherDictionary[KEY_NOT_PRESENT] = notPresentValue\n            dictionary.putAll(anotherDictionary)\n            assertEquals(dictionary.size, initializedDictionary.size + anotherDictionary.size)\n\n            // TODO: It is not possible to test that putting a map containing null keys throws\n            //  a NullPointerException from Kotlin, even when using TestHelper.getNull() due to\n            //  some bytecode generation that doesn't match.\n        }\n    }\n\n    override fun clear() {\n        val dictionary = initAndAssert()\n\n        // Insert entries, assert not empty, clear and assert empty\n        realm.executeTransaction {\n            dictionary.putAll(initializedDictionary)\n            assertFalse(dictionary.isEmpty())\n            dictionary.clear()\n            assertTrue(dictionary.isEmpty())\n        }\n    }\n\n    override fun keySet() {\n        val dictionary = initAndAssert()\n\n        realm.executeTransaction {\n            dictionary.putAll(initializedDictionary)\n        }\n\n        val keySet = dictionary.keys\n        initializedDictionary.forEach { key, _ ->\n            assertTrue(keySet.contains(key))\n        }\n    }\n\n    override fun values() {\n        val dictionary = initAndAssert()\n\n        realm.executeTransaction {\n            dictionary.putAll(initializedDictionary)\n        }\n\n        val values = dictionary.values\n        values.forEach { value ->\n            typeAsserter.assertValues(dictionary, value)\n        }\n    }\n\n    override fun entrySet() {\n        val allTypesObject = createCollectionAllTypesManagedContainerAndAssert(realm)\n        assertNotNull(allTypesObject)\n        val dictionary = dictionaryGetter.call(allTypesObject)\n\n        realm.executeTransaction {\n            dictionary.putAll(initializedDictionary)\n            val entrySet = dictionary.entries\n            assertNotNull(entrySet)\n\n            // Test size\n            assertEquals(initializedDictionary.size, entrySet.size)\n\n            // Test contains\n            dictionary.keys.forEach { dictionaryKey ->\n                val dictionaryValue = dictionary[dictionaryKey]\n                val otherEntry = AbstractMap.SimpleImmutableEntry(dictionaryKey, dictionaryValue)\n                assertTrue(entrySet.contains(otherEntry))\n            }\n\n            // Test iterator\n            val iterator = entrySet.iterator()\n            assertNotNull(iterator)\n            var iteratorSize = 0\n            while (iterator.hasNext()) {\n                iteratorSize++\n                iterator.next()\n            }\n            assertEquals(entrySet.size, iteratorSize)\n\n            // Test toArray\n            assertTrue(entrySet is RealmMapEntrySet<String, T?>)\n            val entrySetObjectArray = entrySet.toArray()\n            for (entry in entrySetObjectArray) {\n                assertTrue(entry is Map.Entry<*, *>)\n                assertTrue(entrySet.contains(entry))\n            }\n\n            // Internal helper function\n            fun testToArray(\n                    entrySetArray: Array<Map.Entry<String, T?>?>,\n                    biggerSize: Boolean = false\n            ) {\n                when {\n                    biggerSize -> assertTrue(entrySetArray.size > entrySet.size)\n                    else -> assertEquals(entrySet.size, entrySetArray.size)\n                }\n                for ((index, entry) in entrySetArray.withIndex()) {\n                    if (index >= entrySet.size) {\n                        assertNull(entry)\n                    } else {\n                        assertTrue(entry is Map.Entry<*, *>)\n                        assertTrue(entrySet.contains(entry))\n                    }\n                }\n            }\n\n            // Test toArray: smaller size, return a new instance\n            val testArraySmallerSize = arrayOfNulls<Map.Entry<String, T?>>(1)\n            val entrySetSmallerSizeArray = entrySet.toArray(testArraySmallerSize)\n            testToArray(entrySetSmallerSizeArray)\n\n            // Test toArray: same size, return a new instance\n            val testArraySameSize = arrayOfNulls<Map.Entry<String, T?>>(entrySet.size)\n            val entrySetSameSizeArray = entrySet.toArray(testArraySameSize)\n            testToArray(entrySetSameSizeArray)\n\n            // Test toArray: bigger size, add null as the last entry\n            val testArrayBiggerSize = arrayOfNulls<Map.Entry<String, T?>>(10)\n            val entrySetBiggerSizeArray = entrySet.toArray(testArrayBiggerSize)\n            testToArray(entrySetBiggerSizeArray, true)\n\n            // Test containsAll\n            val otherEntryCollection = dictionary.keys.map { dictionaryKey ->\n                val dictionaryValue = dictionary[dictionaryKey]\n                AbstractMap.SimpleImmutableEntry(dictionaryKey, dictionaryValue)\n            }\n            assertTrue(entrySet.containsAll(otherEntryCollection))\n\n            val differentCollection = alternativeDictionary.map { entry ->\n                AbstractMap.SimpleImmutableEntry(entry.key, entry.value)\n            }.toSet()\n\n            assertFalse(entrySet.containsAll(differentCollection))\n        }\n    }\n\n    override fun dynamic() {\n        // The methods for Realm object and primitive types are different\n        if (notPresentValue is DogPrimaryKey) {\n            doObjectDynamicTest()\n        } else {\n            doPrimitiveDynamicTest()\n        }\n    }\n\n    private fun doPrimitiveDynamicTest() {\n        // Create a dictionary from a immutable schema context\n        val dictionary = initAndAssert()\n        realm.executeTransaction {\n            dictionary.putAll(initializedDictionary)\n        }\n\n        val dynamicRealm = DynamicRealm.getInstance(realm.configuration)\n        val dynamicObject: DynamicRealmObject = dynamicRealm.where(DictionaryAllTypes.NAME).equalTo(\"columnString\", \"\").findFirst()!!\n        val dynamicDictionary = dynamicObject.getDictionary(dictionaryFieldName, dictionaryFieldClass)\n\n        // Access the previous dictionary from a mutable context\n        dictionary.values.forEach { value ->\n            typeAsserter.assertValues(dynamicDictionary, value)\n        }\n\n        // Update the dictionary with a new value\n        dynamicRealm.executeTransaction {\n            dynamicDictionary[KEY_NOT_PRESENT] = notPresentValue\n        }\n\n        dictionary.values.plus(notPresentValue).forEach { value ->\n            typeAsserter.assertValues(dynamicDictionary, value)\n        }\n\n        dictionary.keys.plus(KEY_NOT_PRESENT).forEach { key ->\n            typeAsserter.assertKeys(dynamicDictionary, key)\n        }\n\n        // Try to replace the whole dictionary by a new one\n        dynamicRealm.executeTransaction {\n            dynamicObject.setDictionary(dictionaryFieldName, RealmDictionary<T>().apply {\n                this[KEY_NOT_PRESENT] = notPresentValue\n            })\n        }\n\n        assertEquals(1, dynamicObject.get<RealmDictionary<T>>(dictionaryFieldName).size)\n\n        // Validate that dict is properly represented as a String\n        validateToString(dynamicObject, dynamicDictionary)\n\n        dynamicRealm.close()\n    }\n\n    private fun validateToString(dynamicObject: DynamicRealmObject, dynamicDictionary: RealmDictionary<*>) {\n        val type = when (dictionaryFieldClass.simpleName) {\n            \"Byte\", \"Short\", \"Integer\" -> \"Long\"\n            else -> dictionaryFieldClass.simpleName\n        }\n\n        val expectedDictionaryString = \"${dictionaryFieldName}:RealmDictionary<$type>[${dynamicDictionary.size}]\"\n        assertTrue(\n            dynamicObject.toString().contains(expectedDictionaryString),\n            \"DynamicRealmObject does not contain expected RealmDictionary string: $expectedDictionaryString\"\n        )\n    }\n\n    private fun doObjectDynamicTest() {\n        // Create a dictionary from a immutable schema context\n        val dictionary = initAndAssert()\n        realm.executeTransaction {\n            dictionary.putAll(initializedDictionary)\n            realm.insert(notPresentValue as DogPrimaryKey)\n        }\n\n        val dynamicRealm = DynamicRealm.getInstance(realm.configuration)\n        val dynamicObject: DynamicRealmObject =\n            dynamicRealm.where(DictionaryAllTypes.NAME).equalTo(\"columnString\", \"\").findFirst()!!\n        val dynamicDictionary = dynamicObject.getDictionary(dictionaryFieldName)\n\n        // Access the previous dictionary from a mutable context\n        dictionary.values.forEach { value ->\n            if (RealmObject.isValid(value as DogPrimaryKey)) {\n                val managedObject =\n                    dynamicRealm.where(DogPrimaryKey.CLASS_NAME).equalTo(DogPrimaryKey.ID, (value as DogPrimaryKey).id)\n                        .findFirst()!!\n                typeAsserter.assertDynamicValues(dynamicDictionary, managedObject)\n            }\n        }\n\n        // Update the dictionary with a new value\n        dynamicRealm.executeTransaction {\n            val notPresentManaged = dynamicRealm.where(DogPrimaryKey.CLASS_NAME)\n                .equalTo(DogPrimaryKey.ID, (notPresentValue as DogPrimaryKey).id).findFirst()!!\n            dynamicDictionary[KEY_NOT_PRESENT] = notPresentManaged\n        }\n\n        dictionary.values.plus(notPresentValue).forEach { value ->\n            if (RealmObject.isValid(value as DogPrimaryKey)) {\n                val managedObject =\n                    dynamicRealm.where(DogPrimaryKey.CLASS_NAME).equalTo(DogPrimaryKey.ID, (value as DogPrimaryKey).id)\n                        .findFirst()!!\n                typeAsserter.assertDynamicValues(dynamicDictionary, managedObject)\n            }\n        }\n\n        dictionary.keys.plus(KEY_NOT_PRESENT).forEach { key ->\n            typeAsserter.assertKeys(dynamicDictionary, key)\n        }\n\n        // Try to replace the whole dictionary by a new one\n        dynamicRealm.executeTransaction {\n            val notPresentManaged = dynamicRealm.where(DogPrimaryKey.CLASS_NAME)\n                .equalTo(DogPrimaryKey.ID, (notPresentValue as DogPrimaryKey).id).findFirst()!!\n            dynamicObject.setDictionary(dictionaryFieldName, RealmDictionary<DynamicRealmObject>().apply {\n                this[KEY_NOT_PRESENT] = notPresentManaged\n            })\n        }\n\n        assertEquals(1, dynamicObject.get<RealmDictionary<T>>(dictionaryFieldName).size)\n\n        // Validate that dict is properly represented as a String\n        validateToString(dynamicObject, dynamicDictionary)\n\n        dynamicRealm.close()\n    }\n\n    override fun freeze() = Unit                    // This has already been tested in \"isFrozen\"\n\n    override fun copyToRealm() {\n        // Instantiate container and set dictionary on container\n        val manualInstance = DictionaryAllTypes().apply {\n            dictionarySetter.call(this, initializedDictionary)\n        }\n\n        // Copy to Realm\n        realm.executeTransaction {\n            val allTypesObject = realm.copyToRealm(manualInstance)\n            assertNotNull(allTypesObject)\n        }\n\n        // Get dictionary from container from Realm\n        val allTypesObject = realm.where<DictionaryAllTypes>().findFirst()\n        assertNotNull(allTypesObject)\n        val dictionary = dictionaryGetter.call(allTypesObject)\n        assertFalse(dictionary.isEmpty())\n        initializedDictionary.forEach { key, value ->\n            typeAsserter.assertEqualsHelper(realm, value, dictionary[key])\n        }\n    }\n\n    override fun copyToRealmOrUpdate() {\n        // Instantiate container and set dictionary on container\n        val manualInstance = PrimaryKeyDictionaryContainer().apply {\n            primaryKeyDictionaryProperty.get(this).putAll(initializedDictionary)\n        }\n\n        // Copy to Realm\n        realm.executeTransaction {\n            val allTypesObject = realm.copyToRealmOrUpdate(manualInstance)\n            assertNotNull(allTypesObject)\n        }\n\n        // Get dictionary from container from Realm\n        val primaryKeyDictionaryContainer = realm.where<PrimaryKeyDictionaryContainer>().findFirst()\n        assertNotNull(primaryKeyDictionaryContainer)\n        val dictionary = primaryKeyDictionaryProperty.get(primaryKeyDictionaryContainer)\n        assertFalse(dictionary.isEmpty())\n        initializedDictionary.forEach { key, value ->\n            typeAsserter.assertEqualsHelper(realm, value, dictionary[key])\n        }\n\n        if (testerClass == \"String-NonLatin\" || testerClass == \"RealmAny-NonLatin\") {\n            primaryKeyDictionaryProperty.get(manualInstance)[NEW_KEY_NON_LATIN] = alternativeDictionary[KEY_BYE_NON_LATIN]\n        } else {\n            primaryKeyDictionaryProperty.get(manualInstance)[NEW_KEY] = alternativeDictionary[KEY_BYE]\n        }\n\n        // Copy to Realm with non managed updated model\n        realm.executeTransaction {\n            val allTypesObject = realm.copyToRealmOrUpdate(manualInstance)\n            assertNotNull(allTypesObject)\n        }\n\n        val updatedContainer = realm.where<PrimaryKeyDictionaryContainer>().findFirst()\n        assertNotNull(updatedContainer)\n        val updatedDictinary = primaryKeyDictionaryProperty.get(primaryKeyDictionaryContainer)\n        assertEquals(initializedDictionary.size + 1, updatedDictinary.size)\n        if (testerClass == \"String-NonLatin\" || testerClass == \"RealmAny-NonLatin\") {\n            typeAsserter.assertEqualsHelper(realm, alternativeDictionary[KEY_BYE_NON_LATIN], updatedDictinary[NEW_KEY_NON_LATIN])\n        } else {\n            typeAsserter.assertEqualsHelper(realm, alternativeDictionary[KEY_BYE], updatedDictinary[NEW_KEY])\n        }\n    }\n\n    override fun insert() {\n        // Instantiate container and set dictionary on container\n        val manualInstance = DictionaryAllTypes().apply {\n            dictionarySetter.call(this, initializedDictionary)\n        }\n\n        // Insert into Realm\n        realm.executeTransaction {\n            realm.insert(manualInstance)\n        }\n\n        // Get dictionary from container from Realm\n        val allTypesObject = realm.where<DictionaryAllTypes>().findFirst()\n        assertNotNull(allTypesObject)\n        val dictionary = dictionaryGetter.call(allTypesObject)\n        assertFalse(dictionary.isEmpty())\n        initializedDictionary.forEach { key, value ->\n            typeAsserter.assertEqualsHelper(realm, value, dictionary[key])\n        }\n    }\n\n    override fun insertList() {\n        // Instantiate container and set dictionary on container\n        val manualInstance = DictionaryAllTypes().apply {\n            dictionarySetter.call(this, initializedDictionary)\n        }\n        val emptyInstance = DictionaryAllTypes()\n\n        // Insert into Realm\n        realm.executeTransaction {\n            realm.insert(listOf(emptyInstance, manualInstance))\n        }\n\n        // Get dictionary from container from Realm\n        val allTypesObject = realm.where<DictionaryAllTypes>().findAll()[1]\n        assertNotNull(allTypesObject)\n        val dictionary = dictionaryGetter.call(allTypesObject)\n        assertFalse(dictionary.isEmpty())\n        initializedDictionary.forEach { key, value ->\n            typeAsserter.assertEqualsHelper(realm, value, dictionary[key])\n        }\n    }\n\n    override fun insertOrUpdate() {\n        // Instantiate container and set dictionary on container\n        val manualInstance = PrimaryKeyDictionaryContainer().apply {\n            primaryKeyDictionaryProperty.get(this).putAll(initializedDictionary)\n        }\n\n        // insert into Realm\n        realm.executeTransaction {\n            realm.insertOrUpdate(manualInstance)\n        }\n\n        // Get dictionary from container from Realm\n        val primaryKeyDictionaryContainer = realm.where<PrimaryKeyDictionaryContainer>().findFirst()\n        assertNotNull(primaryKeyDictionaryContainer)\n        val dictionary = primaryKeyDictionaryProperty.get(primaryKeyDictionaryContainer)\n        assertFalse(dictionary.isEmpty())\n        initializedDictionary.forEach { key, value ->\n            typeAsserter.assertEqualsHelper(realm, value, dictionary[key])\n        }\n\n        if (testerClass == \"String-NonLatin\" || testerClass == \"RealmAny-NonLatin\") {\n            primaryKeyDictionaryProperty.get(manualInstance)[NEW_KEY_NON_LATIN] = alternativeDictionary[KEY_BYE_NON_LATIN]\n        } else {\n            primaryKeyDictionaryProperty.get(manualInstance)[NEW_KEY] = alternativeDictionary[KEY_BYE]\n        }\n\n        // Insert to Realm with non managed updated model\n        realm.executeTransaction {\n            realm.insertOrUpdate(manualInstance)\n        }\n\n        val updatedContainer = realm.where<PrimaryKeyDictionaryContainer>().findFirst()\n        assertNotNull(updatedContainer)\n        val updatedDictinary = primaryKeyDictionaryProperty.get(primaryKeyDictionaryContainer)\n        assertEquals(initializedDictionary.size + 1, updatedDictinary.size)\n        if (testerClass == \"String-NonLatin\" || testerClass == \"RealmAny-NonLatin\") {\n            typeAsserter.assertEqualsHelper(realm, alternativeDictionary[KEY_BYE_NON_LATIN], updatedDictinary[NEW_KEY_NON_LATIN])\n        } else {\n            typeAsserter.assertEqualsHelper(realm, alternativeDictionary[KEY_BYE], updatedDictinary[NEW_KEY])\n        }\n    }\n\n    override fun insertOrUpdateList() {\n        // Instantiate container and set dictionary on container\n        val manualInstance = PrimaryKeyDictionaryContainer().apply {\n            name = \"manual\"\n            primaryKeyDictionaryProperty.get(this).putAll(initializedDictionary)\n        }\n        val emptyInstance = PrimaryKeyDictionaryContainer().apply {\n            name = \"empty\"\n        }\n\n        // insert into Realm\n        realm.executeTransaction {\n            realm.insertOrUpdate(listOf(emptyInstance, manualInstance))\n        }\n\n        // Get dictionary from container from Realm\n        val primaryKeyDictionaryContainer = realm.where<PrimaryKeyDictionaryContainer>()\n            .equalTo(\"name\", \"manual\")\n            .findFirst()\n        assertNotNull(primaryKeyDictionaryContainer)\n        val dictionary = primaryKeyDictionaryProperty.get(primaryKeyDictionaryContainer)\n        assertFalse(dictionary.isEmpty())\n        initializedDictionary.forEach { key, value ->\n            typeAsserter.assertEqualsHelper(realm, value, dictionary[key])\n        }\n\n        if (testerClass == \"String-NonLatin\" || testerClass == \"RealmAny-NonLatin\") {\n            primaryKeyDictionaryProperty.get(manualInstance)[NEW_KEY_NON_LATIN] = alternativeDictionary[KEY_BYE_NON_LATIN]\n        } else {\n            primaryKeyDictionaryProperty.get(manualInstance)[NEW_KEY] = alternativeDictionary[KEY_BYE]\n        }\n\n        // Insert to Realm with non managed updated model\n        realm.executeTransaction {\n            realm.insertOrUpdate(listOf(emptyInstance, manualInstance))\n        }\n\n        val updatedContainer = realm.where<PrimaryKeyDictionaryContainer>()\n            .equalTo(\"name\", \"manual\")\n            .findFirst()\n        assertNotNull(updatedContainer)\n        val updatedDictinary = primaryKeyDictionaryProperty.get(primaryKeyDictionaryContainer)\n        assertEquals(initializedDictionary.size + 1, updatedDictinary.size)\n        if (testerClass == \"String-NonLatin\" || testerClass == \"RealmAny-NonLatin\") {\n            typeAsserter.assertEqualsHelper(realm, alternativeDictionary[KEY_BYE_NON_LATIN], updatedDictinary[NEW_KEY_NON_LATIN])\n        } else {\n            typeAsserter.assertEqualsHelper(realm, alternativeDictionary[KEY_BYE], updatedDictinary[NEW_KEY])\n        }\n    }\n\n    override fun copyFromRealm() {\n        val allTypesObject = createCollectionAllTypesManagedContainerAndAssert(realm)\n        assertNotNull(allTypesObject)\n        val dictionary = dictionaryGetter.call(allTypesObject)\n\n        realm.executeTransaction {\n            dictionary.putAll(initializedDictionary)\n        }\n\n        val detachedAllTypes = realm.copyFromRealm(allTypesObject)\n        val detachedDictionary = dictionaryGetter.call(detachedAllTypes)\n        assertEquals(dictionary.size, detachedDictionary.size)\n\n        // Compare elements to the original values\n        detachedDictionary.forEach { key, value ->\n            typeAsserter.assertEqualsHelper(realm, value, dictionary[key])\n        }\n    }\n\n    override fun fieldAccessors(otherConfig: RealmConfiguration?) {\n        realm.executeTransaction { transactionRealm ->\n            val container = transactionRealm.createObject<PopulatedDictionaryClass>()\n            val dictionary = populatedGetter.get(container)\n            assertNotNull(dictionary)\n            assertTrue(dictionary.isManaged)\n            assertFalse(dictionary.isEmpty())\n        }\n\n        assertNotNull(otherConfig)\n        typeAsserter.assertAccessorSetter(\n            realm,\n            dictionaryGetter,\n            dictionarySetter,\n            initializedDictionary,\n            otherConfig\n        )\n    }\n\n    override fun addMapChangeListener() {\n        looperThread.runBlocking {\n            val looperThreadRealm = Realm.getInstance(config)\n            looperThread.closeAfterTest(looperThreadRealm)\n\n            // Get dictionary\n            val dictionary = initAndAssert(looperThreadRealm)\n\n            // Define operation we perform on the dictionary\n            var operation = ChangeListenerOperation.UNDEFINED\n\n            dictionary.addChangeListener { map, changes ->\n                typeAsserter.assertChangeListenerUpdates(\n                        testerClass,\n                        operation,\n                        looperThread,\n                        looperThreadRealm,\n                        dictionary,\n                        initializedDictionary,\n                        map,\n                        changes\n                )\n            }\n\n            // Insert objects in dictionary\n            looperThreadRealm.executeTransaction {\n                operation = ChangeListenerOperation.INSERT\n                dictionary.putAll(initializedDictionary)\n            }\n\n            // Update object\n            looperThreadRealm.executeTransaction {\n                operation = ChangeListenerOperation.UPDATE\n\n                // Use 'dictionary' instead of 'alternativeDictionary' as the semantics for\n                // inserting unmanaged objects might lead to having one extra update in the\n                // change set - calling 'put' with an unmanaged object with PK that already is\n                // in the database will trigger two changes: one for the actual modification and\n                // two for insertion itself since we use 'copyToRealmOrUpdate'.\n                if (testerClass == \"String-NonLatin\" || testerClass == \"RealmAny-NonLatin\") {\n                    dictionary[KEY_HELLO_NON_LATIN] = dictionary[KEY_BYE_NON_LATIN]\n                } else {\n                    dictionary[KEY_HELLO] = dictionary[KEY_BYE]\n                }\n            }\n\n            // Clear dictionary\n            looperThreadRealm.executeTransaction {\n                operation = ChangeListenerOperation.DELETE\n                dictionary.clear()\n            }\n        }\n    }\n\n    override fun addRealmChangeListener() {\n        looperThread.runBlocking {\n            val looperThreadRealm = Realm.getInstance(config)\n            looperThread.closeAfterTest(looperThreadRealm)\n\n            // Get dictionary\n            val dictionary = initAndAssert(looperThreadRealm)\n\n            // Define operation we perform on the dictionary\n            var operation = ChangeListenerOperation.UNDEFINED\n\n            dictionary.addChangeListener { map ->\n                typeAsserter.assertChangeListenerUpdates(\n                        testerClass,\n                        operation,\n                        looperThread,\n                        looperThreadRealm,\n                        dictionary,\n                        initializedDictionary,\n                        map\n                )\n            }\n\n            // Insert objects in dictionary\n            looperThreadRealm.executeTransaction {\n                operation = ChangeListenerOperation.INSERT\n                dictionary.putAll(initializedDictionary)\n            }\n\n            // Update object\n            looperThreadRealm.executeTransaction {\n                operation = ChangeListenerOperation.UPDATE\n\n                // Use 'dictionary' instead of 'alternativeDictionary' as the semantics for\n                // inserting unmanaged objects might lead to having one extra update in the\n                // change set - calling 'put' with an unmanaged object with PK that already is\n                // in the database will trigger two changes: one for the actual modification and\n                // two for insertion itself since we use 'copyToRealmOrUpdate'.\n                if (testerClass == \"String-NonLatin\" || testerClass == \"RealmAny-NonLatin\") {\n                    dictionary[KEY_HELLO_NON_LATIN] = dictionary[KEY_BYE_NON_LATIN]\n                } else {\n                    dictionary[KEY_HELLO] = dictionary[KEY_BYE]\n                }\n            }\n\n            // Clear dictionary\n            looperThreadRealm.executeTransaction {\n                operation = ChangeListenerOperation.DELETE\n                dictionary.clear()\n            }\n        }\n    }\n\n    override fun hasListeners() {\n        val looperThread = BlockingLooperThread()\n        looperThread.runBlocking {\n            val looperThreadRealm = Realm.getInstance(config)\n            looperThread.closeAfterTest(looperThreadRealm)\n\n            // Check for RealmChangeListener\n            val dictionary = initAndAssert(looperThreadRealm)\n            assertFalse(dictionary.hasListeners())\n\n            dictionary.addChangeListener { _ -> /* no-op */ }\n\n            assertTrue(dictionary.hasListeners())\n\n            // Check for MapChangeListener\n            val anotherDictionary = initAndAssert(looperThreadRealm, \"anotherDictionary\")\n            assertFalse(anotherDictionary.hasListeners())\n\n            anotherDictionary.addChangeListener { _, _ -> /* no-op */ }\n\n            assertTrue(anotherDictionary.hasListeners())\n\n            // Housekeeping and bye-bye\n            dictionary.removeAllChangeListeners()\n            anotherDictionary.removeAllChangeListeners()\n            looperThread.testComplete()\n        }\n    }\n\n    //----------------------------------\n    // Private stuff\n    //----------------------------------\n\n    private fun initAndAssert(\n            realm: Realm = this.realm,\n            id: String? = null\n    ): RealmDictionary<T> {\n        val allTypesObject = createCollectionAllTypesManagedContainerAndAssert(realm, id)\n        assertNotNull(allTypesObject)\n        return dictionaryGetter.call(allTypesObject)\n    }\n\n    private fun putInternal(\n            initialized: RealmDictionary<T>,\n            alternative: RealmDictionary<T>\n    ) {\n        val dictionary = initAndAssert(id = \"internal\")\n\n        realm.executeTransaction {\n            // Check we get null since previous values are not present\n            initialized.forEach { key, value ->\n                assertNull(dictionary.put(key, value))\n            }\n        }\n        initialized.forEach { key, value ->\n            typeAsserter.assertEqualsHelper(realm, value, dictionary[key])\n        }\n\n        // Now check we get the previous value after insertion\n        realm.executeTransaction {\n            alternative.forEach { key, value ->\n                typeAsserter.assertEqualsHelper(realm, initialized[key], dictionary.put(key, value))\n            }\n\n            // Check null key fails\n            assertFailsWith<NullPointerException> {\n                dictionary[TestHelper.getNull()] = initializedDictionary[KEY_HELLO]\n            }\n        }\n\n        // Finally check that the alternative values are there\n        dictionary.forEach { key, value ->\n            assertTrue(alternative.containsKey(key))\n            typeAsserter.assertContainsValueHelper(realm, key, value, alternative, dictionary)\n        }\n    }\n}\n\nenum class ChangeListenerOperation {\n    UNDEFINED, INSERT, UPDATE, DELETE\n}\n\n/**\n * Creates testers for all [DictionarySupportedType]s and initializes them for testing. There are as\n * many RealmAny testers as [RealmAny.Type]s.\n *\n * The `KFunction1` and `KFunction2` parameters for `dictionaryGetter` and `dictionarySetter`\n * respectively enables agnostic field processing, making it possible to cover all supported types\n * with just one tester class.\n */\nfun managedDictionaryFactory(): List<DictionaryTester> {\n    val primitiveTesters = listOf<DictionaryTester>(\n            ManagedDictionaryTester(\n                    testerClass = \"Long\",\n                    dictionaryFieldClass = Long::class.javaObjectType,\n                    dictionaryFieldName = \"columnLongDictionary\",\n                    dictionaryGetter = DictionaryAllTypes::getColumnLongDictionary,\n                    dictionarySetter = DictionaryAllTypes::setColumnLongDictionary,\n                    requiredDictionaryGetter = DictionaryAllTypes::getColumnRequiredLongDictionary,\n                    initializedDictionary = RealmDictionary<Long>().init(listOf(KEY_HELLO to VALUE_NUMERIC_HELLO.toLong(), KEY_BYE to VALUE_NUMERIC_BYE.toLong(), KEY_NULL to null)),\n                    alternativeDictionary = RealmDictionary<Long>().init(listOf(KEY_HELLO to VALUE_NUMERIC_BYE.toLong(), KEY_BYE to VALUE_NUMERIC_HELLO.toLong(), KEY_NULL to null)),\n                    notPresentValue = VALUE_NUMERIC_NOT_PRESENT.toLong(),\n                    populatedGetter = PopulatedDictionaryClass::populatedLongDictionary,\n                    primaryKeyDictionaryProperty = PrimaryKeyDictionaryContainer::myLongDictionary\n            ),\n            ManagedDictionaryTester(\n                    testerClass = \"Int\",\n                    dictionaryFieldClass = Int::class.javaObjectType,\n                    dictionaryFieldName = \"columnIntegerDictionary\",\n                    dictionaryGetter = DictionaryAllTypes::getColumnIntegerDictionary,\n                    dictionarySetter = DictionaryAllTypes::setColumnIntegerDictionary,\n                    requiredDictionaryGetter = DictionaryAllTypes::getColumnRequiredIntegerDictionary,\n                    initializedDictionary = RealmDictionary<Int>().init(listOf(KEY_HELLO to VALUE_NUMERIC_HELLO, KEY_BYE to VALUE_NUMERIC_BYE, KEY_NULL to null)),\n                    alternativeDictionary = RealmDictionary<Int>().init(listOf(KEY_HELLO to VALUE_NUMERIC_BYE, KEY_BYE to VALUE_NUMERIC_HELLO, KEY_NULL to null)),\n                    notPresentValue = VALUE_NUMERIC_NOT_PRESENT,\n                    populatedGetter = PopulatedDictionaryClass::populatedIntDictionary,\n                    primaryKeyDictionaryProperty = PrimaryKeyDictionaryContainer::myIntDictionary\n            ),\n            ManagedDictionaryTester(\n                    testerClass = \"Short\",\n                    dictionaryFieldClass = Short::class.javaObjectType,\n                    dictionaryFieldName = \"columnShortDictionary\",\n                    dictionaryGetter = DictionaryAllTypes::getColumnShortDictionary,\n                    dictionarySetter = DictionaryAllTypes::setColumnShortDictionary,\n                    requiredDictionaryGetter = DictionaryAllTypes::getColumnRequiredShortDictionary,\n                    initializedDictionary = RealmDictionary<Short>().init(listOf(KEY_HELLO to VALUE_NUMERIC_HELLO.toShort(), KEY_BYE to VALUE_NUMERIC_BYE.toShort(), KEY_NULL to null)),\n                    alternativeDictionary = RealmDictionary<Short>().init(listOf(KEY_HELLO to VALUE_NUMERIC_BYE.toShort(), KEY_BYE to VALUE_NUMERIC_HELLO.toShort(), KEY_NULL to null)),\n                    notPresentValue = VALUE_NUMERIC_NOT_PRESENT.toShort(),\n                    populatedGetter = PopulatedDictionaryClass::populatedShortDictionary,\n                    primaryKeyDictionaryProperty = PrimaryKeyDictionaryContainer::myShortDictionary\n            ),\n            ManagedDictionaryTester(\n                    testerClass = \"Byte\",\n                    dictionaryFieldClass = Byte::class.javaObjectType,\n                    dictionaryFieldName = \"columnByteDictionary\",\n                    dictionaryGetter = DictionaryAllTypes::getColumnByteDictionary,\n                    dictionarySetter = DictionaryAllTypes::setColumnByteDictionary,\n                    requiredDictionaryGetter = DictionaryAllTypes::getColumnRequiredByteDictionary,\n                    initializedDictionary = RealmDictionary<Byte>().init(listOf(KEY_HELLO to VALUE_NUMERIC_HELLO.toByte(), KEY_BYE to VALUE_NUMERIC_BYE.toByte(), KEY_NULL to null)),\n                    alternativeDictionary = RealmDictionary<Byte>().init(listOf(KEY_HELLO to VALUE_NUMERIC_BYE.toByte(), KEY_BYE to VALUE_NUMERIC_HELLO.toByte(), KEY_NULL to null)),\n                    notPresentValue = VALUE_NUMERIC_NOT_PRESENT.toByte(),\n                    populatedGetter = PopulatedDictionaryClass::populatedByteDictionary,\n                    primaryKeyDictionaryProperty = PrimaryKeyDictionaryContainer::myByteDictionary\n            ),\n            ManagedDictionaryTester(\n                    testerClass = \"Float\",\n                    dictionaryFieldClass = Float::class.javaObjectType,\n                    dictionaryFieldName = \"columnFloatDictionary\",\n                    dictionaryGetter = DictionaryAllTypes::getColumnFloatDictionary,\n                    dictionarySetter = DictionaryAllTypes::setColumnFloatDictionary,\n                    requiredDictionaryGetter = DictionaryAllTypes::getColumnRequiredFloatDictionary,\n                    initializedDictionary = RealmDictionary<Float>().init(listOf(KEY_HELLO to VALUE_NUMERIC_HELLO.toFloat(), KEY_BYE to VALUE_NUMERIC_BYE.toFloat(), KEY_NULL to null)),\n                    alternativeDictionary = RealmDictionary<Float>().init(listOf(KEY_HELLO to VALUE_NUMERIC_BYE.toFloat(), KEY_BYE to VALUE_NUMERIC_HELLO.toFloat(), KEY_NULL to null)),\n                    notPresentValue = VALUE_NUMERIC_NOT_PRESENT.toFloat(),\n                    populatedGetter = PopulatedDictionaryClass::populatedFloatDictionary,\n                    primaryKeyDictionaryProperty = PrimaryKeyDictionaryContainer::myFloatDictionary\n            ),\n            ManagedDictionaryTester(\n                    testerClass = \"Double\",\n                    dictionaryFieldClass = Double::class.javaObjectType,\n                    dictionaryFieldName = \"columnDoubleDictionary\",\n                    dictionaryGetter = DictionaryAllTypes::getColumnDoubleDictionary,\n                    dictionarySetter = DictionaryAllTypes::setColumnDoubleDictionary,\n                    requiredDictionaryGetter = DictionaryAllTypes::getColumnRequiredDoubleDictionary,\n                    initializedDictionary = RealmDictionary<Double>().init(listOf(KEY_HELLO to VALUE_NUMERIC_HELLO.toDouble(), KEY_BYE to VALUE_NUMERIC_BYE.toDouble(), KEY_NULL to null)),\n                    alternativeDictionary = RealmDictionary<Double>().init(listOf(KEY_HELLO to VALUE_NUMERIC_BYE.toDouble(), KEY_BYE to VALUE_NUMERIC_HELLO.toDouble(), KEY_NULL to null)),\n                    notPresentValue = VALUE_NUMERIC_NOT_PRESENT.toDouble(),\n                    populatedGetter = PopulatedDictionaryClass::populatedDoubleDictionary,\n                    primaryKeyDictionaryProperty = PrimaryKeyDictionaryContainer::myDoubleDictionary\n            ),\n            ManagedDictionaryTester(\n                    testerClass = \"String\",\n                    dictionaryFieldClass = String::class.java,\n                    dictionaryFieldName = \"columnStringDictionary\",\n                    dictionaryGetter = DictionaryAllTypes::getColumnStringDictionary,\n                    dictionarySetter = DictionaryAllTypes::setColumnStringDictionary,\n                    requiredDictionaryGetter = DictionaryAllTypes::getColumnRequiredStringDictionary,\n                    initializedDictionary = RealmDictionary<String>().init(listOf(KEY_HELLO to VALUE_STRING_HELLO, KEY_BYE to VALUE_STRING_BYE, KEY_NULL to null)),\n                    alternativeDictionary = RealmDictionary<String>().init(listOf(KEY_HELLO to VALUE_STRING_BYE, KEY_BYE to VALUE_STRING_HELLO, KEY_NULL to null)),\n                    notPresentValue = VALUE_STRING_NOT_PRESENT,\n                    populatedGetter = PopulatedDictionaryClass::populatedStringDictionary,\n                    primaryKeyDictionaryProperty = PrimaryKeyDictionaryContainer::myStringDictionary\n            ),\n            ManagedDictionaryTester(\n                    testerClass = \"String-NonLatin\",\n                    dictionaryFieldClass = String::class.java,\n                    dictionaryFieldName = \"columnStringDictionary\",\n                    dictionaryGetter = DictionaryAllTypes::getColumnStringDictionary,\n                    dictionarySetter = DictionaryAllTypes::setColumnStringDictionary,\n                    requiredDictionaryGetter = DictionaryAllTypes::getColumnRequiredStringDictionary,\n                    initializedDictionary = RealmDictionary<String>().init(listOf(KEY_HELLO_NON_LATIN to VALUE_STRING_NON_LATIN_HELLO, KEY_BYE_NON_LATIN to VALUE_STRING_NON_LATIN_BYE, KEY_NULL_NON_LATIN to null)),\n                    alternativeDictionary = RealmDictionary<String>().init(listOf(KEY_HELLO_NON_LATIN to VALUE_STRING_NON_LATIN_BYE, KEY_BYE_NON_LATIN to VALUE_STRING_NON_LATIN_HELLO, KEY_NULL_NON_LATIN to null)),\n                    notPresentValue = VALUE_STRING_NON_LATIN_NOT_PRESENT,\n                    populatedGetter = PopulatedDictionaryClass::populatedStringDictionary,\n                    primaryKeyDictionaryProperty = PrimaryKeyDictionaryContainer::myStringDictionary\n            ),\n            ManagedDictionaryTester(\n                    testerClass = \"Boolean\",\n                    dictionaryFieldClass = Boolean::class.javaObjectType,\n                    dictionaryFieldName = \"columnBooleanDictionary\",\n                    dictionaryGetter = DictionaryAllTypes::getColumnBooleanDictionary,\n                    dictionarySetter = DictionaryAllTypes::setColumnBooleanDictionary,\n                    requiredDictionaryGetter = DictionaryAllTypes::getColumnRequiredBooleanDictionary,\n                    initializedDictionary = RealmDictionary<Boolean>().init(listOf(KEY_HELLO to VALUE_BOOLEAN_HELLO, KEY_BYE to VALUE_BOOLEAN_BYE, KEY_NULL to null)),\n                    alternativeDictionary = RealmDictionary<Boolean>().init(listOf(KEY_HELLO to VALUE_BOOLEAN_BYE, KEY_BYE to VALUE_BOOLEAN_HELLO, KEY_NULL to null)),\n                    notPresentValue = VALUE_BOOLEAN_NOT_PRESENT,\n                    populatedGetter = PopulatedDictionaryClass::populatedBooleanDictionary,\n                    primaryKeyDictionaryProperty = PrimaryKeyDictionaryContainer::myBooleanDictionary\n            ),\n            ManagedDictionaryTester(\n                    testerClass = \"Date\",\n                    dictionaryFieldClass = Date::class.java,\n                    dictionaryFieldName = \"columnDateDictionary\",\n                    dictionaryGetter = DictionaryAllTypes::getColumnDateDictionary,\n                    dictionarySetter = DictionaryAllTypes::setColumnDateDictionary,\n                    requiredDictionaryGetter = DictionaryAllTypes::getColumnRequiredDateDictionary,\n                    initializedDictionary = RealmDictionary<Date>().init(listOf(KEY_HELLO to VALUE_DATE_HELLO, KEY_BYE to VALUE_DATE_BYE, KEY_NULL to null)),\n                    alternativeDictionary = RealmDictionary<Date>().init(listOf(KEY_HELLO to VALUE_DATE_BYE, KEY_BYE to VALUE_DATE_HELLO, KEY_NULL to null)),\n                    notPresentValue = VALUE_DATE_NOT_PRESENT,\n                    populatedGetter = PopulatedDictionaryClass::populatedDateDictionary,\n                    primaryKeyDictionaryProperty = PrimaryKeyDictionaryContainer::myDateDictionary\n            ),\n            ManagedDictionaryTester(\n                    testerClass = \"Decimal128\",\n                    dictionaryFieldClass = Decimal128::class.java,\n                    dictionaryFieldName = \"columnDecimal128Dictionary\",\n                    dictionaryGetter = DictionaryAllTypes::getColumnDecimal128Dictionary,\n                    dictionarySetter = DictionaryAllTypes::setColumnDecimal128Dictionary,\n                    requiredDictionaryGetter = DictionaryAllTypes::getColumnRequiredDecimal128Dictionary,\n                    initializedDictionary = RealmDictionary<Decimal128>().init(listOf(KEY_HELLO to VALUE_DECIMAL128_HELLO, KEY_BYE to VALUE_DECIMAL128_BYE, KEY_NULL to null)),\n                    alternativeDictionary = RealmDictionary<Decimal128>().init(listOf(KEY_HELLO to VALUE_DECIMAL128_BYE, KEY_BYE to VALUE_DECIMAL128_HELLO, KEY_NULL to null)),\n                    notPresentValue = VALUE_DECIMAL128_NOT_PRESENT,\n                    populatedGetter = PopulatedDictionaryClass::populatedDecimal128Dictionary,\n                    primaryKeyDictionaryProperty = PrimaryKeyDictionaryContainer::myDecimal128Dictionary\n            ),\n            ManagedDictionaryTester(\n                    testerClass = \"ByteArray\",\n                    dictionaryFieldClass = ByteArray::class.java,\n                    dictionaryFieldName = \"columnBinaryDictionary\",\n                    dictionaryGetter = DictionaryAllTypes::getColumnBinaryDictionary,\n                    dictionarySetter = DictionaryAllTypes::setColumnBinaryDictionary,\n                    requiredDictionaryGetter = DictionaryAllTypes::getColumnRequiredBinaryDictionary,\n                    initializedDictionary = RealmDictionary<ByteArray>().init(listOf(KEY_HELLO to VALUE_BINARY_HELLO, KEY_BYE to VALUE_BINARY_BYE, KEY_NULL to null)),\n                    alternativeDictionary = RealmDictionary<ByteArray>().init(listOf(KEY_HELLO to VALUE_BINARY_BYE, KEY_BYE to VALUE_BINARY_HELLO, KEY_NULL to null)),\n                    notPresentValue = VALUE_BINARY_NOT_PRESENT,\n                    populatedGetter = PopulatedDictionaryClass::populatedBinaryDictionary,\n                    primaryKeyDictionaryProperty = PrimaryKeyDictionaryContainer::myBinaryDictionary,\n                    typeAsserter = BinaryAsserter()\n            ),\n            ManagedDictionaryTester(\n                    testerClass = \"ObjectId\",\n                    dictionaryFieldClass = ObjectId::class.java,\n                    dictionaryFieldName = \"columnObjectIdDictionary\",\n                    dictionaryGetter = DictionaryAllTypes::getColumnObjectIdDictionary,\n                    dictionarySetter = DictionaryAllTypes::setColumnObjectIdDictionary,\n                    requiredDictionaryGetter = DictionaryAllTypes::getColumnRequiredObjectIdDictionary,\n                    initializedDictionary = RealmDictionary<ObjectId>().init(listOf(KEY_HELLO to VALUE_OBJECT_ID_HELLO, KEY_BYE to VALUE_OBJECT_ID_BYE, KEY_NULL to null)),\n                    alternativeDictionary = RealmDictionary<ObjectId>().init(listOf(KEY_HELLO to VALUE_OBJECT_ID_BYE, KEY_BYE to VALUE_OBJECT_ID_HELLO, KEY_NULL to null)),\n                    notPresentValue = VALUE_OBJECT_ID_NOT_PRESENT,\n                    populatedGetter = PopulatedDictionaryClass::populatedObjectIdDictionary,\n                    primaryKeyDictionaryProperty = PrimaryKeyDictionaryContainer::myObjectIdDictionary\n            ),\n            ManagedDictionaryTester(\n                    testerClass = \"UUID\",\n                    dictionaryFieldClass = UUID::class.java,\n                    dictionaryFieldName = \"columnUUIDDictionary\",\n                    dictionaryGetter = DictionaryAllTypes::getColumnUUIDDictionary,\n                    dictionarySetter = DictionaryAllTypes::setColumnUUIDDictionary,\n                    requiredDictionaryGetter = DictionaryAllTypes::getColumnRequiredUUIDDictionary,\n                    initializedDictionary = RealmDictionary<UUID>().init(listOf(KEY_HELLO to VALUE_UUID_HELLO, KEY_BYE to VALUE_UUID_BYE, KEY_NULL to null)),\n                    alternativeDictionary = RealmDictionary<UUID>().init(listOf(KEY_HELLO to VALUE_UUID_BYE, KEY_BYE to VALUE_UUID_HELLO, KEY_NULL to null)),\n                    notPresentValue = VALUE_UUID_NOT_PRESENT,\n                    populatedGetter = PopulatedDictionaryClass::populatedUUIDDictionary,\n                    primaryKeyDictionaryProperty = PrimaryKeyDictionaryContainer::myUUIDDictionary\n            ),\n            ManagedDictionaryTester(\n                    testerClass = \"DogPrimaryKey\",\n                    dictionaryFieldClass = DogPrimaryKey::class.java,\n                    dictionaryFieldName = \"columnRealmDictionary\",\n                    dictionaryGetter = DictionaryAllTypes::getColumnRealmDictionary,\n                    dictionarySetter = DictionaryAllTypes::setColumnRealmDictionary,\n                    initializedDictionary = RealmDictionary<DogPrimaryKey>().init(listOf(KEY_HELLO to VALUE_LINK_HELLO, KEY_BYE to VALUE_LINK_BYE, KEY_NULL to null)),\n                    alternativeDictionary = RealmDictionary<DogPrimaryKey>().init(listOf(KEY_HELLO to VALUE_LINK_BYE, KEY_BYE to VALUE_LINK_HELLO, KEY_NULL to null)),\n                    notPresentValue = VALUE_LINK_NOT_PRESENT,\n                    populatedGetter = PopulatedDictionaryClass::populatedRealmModelDictionary,\n                    primaryKeyDictionaryProperty = PrimaryKeyDictionaryContainer::myRealmModelDictionary,\n                    typeAsserter = RealmModelAsserter()\n            )\n    )\n\n    // Create RealmAny testers now\n    val realmAnyTesters = RealmAny.Type.values().map { realmAnyType ->\n        ManagedDictionaryTester(\n                testerClass = \"RealmAny\",\n                realmAnyType = realmAnyType,\n                dictionaryFieldClass = RealmAny::class.java,\n                dictionaryFieldName = \"columnRealmAnyDictionary\",\n                dictionaryGetter = DictionaryAllTypes::getColumnRealmAnyDictionary,\n                dictionarySetter = DictionaryAllTypes::setColumnRealmAnyDictionary,\n                initializedDictionary = RealmDictionary<RealmAny>().init(getRealmAnyKeyValuePairs(realmAnyType)),\n                alternativeDictionary = RealmDictionary<RealmAny>().init(getRealmAnyKeyValuePairs(realmAnyType, true)),\n                notPresentValue = VALUE_MIXED_NOT_PRESENT,\n                populatedGetter = PopulatedDictionaryClass::populatedRealmAnyDictionary,\n                primaryKeyDictionaryProperty = PrimaryKeyDictionaryContainer::myRealmAnyDictionary,\n                typeAsserter = RealmAnyAsserter()\n        )\n    }.plus(\n            ManagedDictionaryTester(\n                    testerClass = \"RealmAny-NonLatin\",\n                    realmAnyType = RealmAny.Type.STRING,\n                    dictionaryFieldClass = RealmAny::class.java,\n                    dictionaryFieldName = \"columnRealmAnyDictionary\",\n                    dictionaryGetter = DictionaryAllTypes::getColumnRealmAnyDictionary,\n                    dictionarySetter = DictionaryAllTypes::setColumnRealmAnyDictionary,\n                    initializedDictionary = RealmDictionary<RealmAny>().init(listOf(KEY_HELLO_NON_LATIN to VALUE_MIXED_STRING_NON_LATIN_BYE, KEY_BYE_NON_LATIN to VALUE_MIXED_STRING_NON_LATIN_HELLO, KEY_NULL_NON_LATIN to null)),\n                    alternativeDictionary = RealmDictionary<RealmAny>().init(listOf(KEY_HELLO_NON_LATIN to VALUE_MIXED_STRING_NON_LATIN_HELLO, KEY_BYE_NON_LATIN to VALUE_MIXED_STRING_NON_LATIN_BYE, KEY_NULL_NON_LATIN to null)),\n                    notPresentValue = VALUE_MIXED_NOT_PRESENT,\n                    populatedGetter = PopulatedDictionaryClass::populatedRealmAnyDictionary,\n                    primaryKeyDictionaryProperty = PrimaryKeyDictionaryContainer::myRealmAnyDictionary,\n                    typeAsserter = RealmAnyAsserter()\n            )\n    )\n\n    return primitiveTesters.plus(realmAnyTesters)\n}\n\n/**\n * Helper to harmonize testing across different types.\n */\nopen class TypeAsserter<T> {\n\n    // RealmModel and RealmAny require different testing here\n    open fun assertContainsValueNotThere(\n            realm: Realm,\n            dictionary: RealmDictionary<T>,\n            index: Int,\n            value: T?\n    ) {\n        assertFalse(dictionary.containsValue(value))\n    }\n\n    // RealmModel and RealmAny require different testing here\n    open fun assertRemoveRealmModelFromRealm(\n            dictionary: RealmDictionary<T>,\n            index: Int,\n            key: String,\n            value: T?\n    ) = Unit    // Do nothing if we aren't testing a RealmModel or a RealmAny wrapping a RealmModel\n\n    // RealmModel requires different testing here\n    open fun assertValues(dictionary: RealmDictionary<T>, value: T?) =\n            assertTrue(dictionary.containsValue(value))\n\n    open fun assertKeys(dictionary: RealmDictionary<*>, value: String?) =\n        assertTrue(dictionary.containsKey(value))\n\n    fun assertDynamicValues(dictionary: RealmDictionary<DynamicRealmObject>, value: DynamicRealmObject?) {\n        // null entries become \"invalid object\" when calling dictionary.values()\n        assertNotNull(value)\n        if (value.isValid) {\n            assertTrue(dictionary.containsValue(value))\n        } else {\n            assertTrue(dictionary.containsValue(null))\n        }\n    }\n\n    // RealmModel and RealmAny require different testing here\n    open fun assertContainsValueHelper(\n            realm: Realm,\n            key: String,\n            value: T?,\n            unmanagedDictionary: RealmDictionary<T>,\n            managedDictionary: RealmDictionary<T>\n    ) {\n        assertTrue(managedDictionary.containsValue(unmanagedDictionary[key]))\n    }\n\n    // ByteArray, RealmModel and RealmAny require different testing here\n    open fun assertEqualsHelper(realm: Realm, value: T?, valueFromRealm: T?) =\n            assertEquals(value, valueFromRealm)\n\n    // RealmModel requires different testing here\n    open fun assertAccessorSetter(\n        realm: Realm,\n        dictionaryGetter: KFunction1<DictionaryAllTypes, RealmDictionary<T>>,\n        dictionarySetter: KFunction2<DictionaryAllTypes, RealmDictionary<T>, Unit>,\n        initializedDictionary: RealmDictionary<T>,\n        otherConfig: RealmConfiguration\n    ) {\n        realm.executeTransaction { transactionRealm ->\n            val anotherContainer = transactionRealm.createObject<DictionaryAllTypes>()\n            dictionarySetter.call(anotherContainer, initializedDictionary)\n            val dictionary = dictionaryGetter.call(anotherContainer)\n            assertNotNull(dictionary)\n            assertTrue(dictionary.isManaged)\n            assertEquals(initializedDictionary.size, dictionary.size)\n        }\n    }\n\n    fun assertChangeListenerUpdates(\n            testerClass: String,\n            operation: ChangeListenerOperation,\n            looperThread: BlockingLooperThread,\n            looperThreadRealm: Realm,\n            managedDictionary: RealmDictionary<T>,\n            initializedDictionary: RealmDictionary<T>,\n            mapFromChangeListener: RealmMap<String, T>,\n            changes: MapChangeSet<String>? = null\n    ) {\n        when (operation) {\n            ChangeListenerOperation.INSERT -> {\n                // Check dictionary\n                initializedDictionary.forEach { key, _ ->\n                    assertContainsValueHelper(\n                            looperThreadRealm,\n                            key,\n                            mapFromChangeListener[key],\n                            initializedDictionary,\n                            mapFromChangeListener as RealmDictionary<T>\n                    )\n                    assertTrue(mapFromChangeListener.containsKey(key))\n\n                    if (changes != null) {\n                        assertTrue(changes.insertions.contains(key), \"Key missing: $key\")\n                    }\n                }\n            }\n            ChangeListenerOperation.UPDATE -> {\n                if (testerClass == \"String-NonLatin\" || testerClass == \"RealmAny-NonLatin\") {\n                    assertEqualsHelper(\n                            looperThreadRealm,\n                            initializedDictionary[KEY_BYE_NON_LATIN],\n                            mapFromChangeListener[KEY_HELLO_NON_LATIN]\n                    )\n                } else {\n                    assertEqualsHelper(\n                            looperThreadRealm,\n                            initializedDictionary[KEY_BYE],\n                            mapFromChangeListener[KEY_HELLO]\n                    )\n                }\n\n                if (changes != null) {\n                    assertEquals(1, changes.changes.size)\n                }\n            }\n            ChangeListenerOperation.DELETE -> {\n                // Dictionary has been cleared\n                assertTrue(mapFromChangeListener.isEmpty(), \"Wrong size: ${mapFromChangeListener.size}\")\n                assertEquals(0, mapFromChangeListener.size)\n\n                if (changes != null) {\n                    // Check deletions changeset size matches deleted elements\n                    assertEquals(initializedDictionary.size, changes.deletions.size)\n                }\n\n                // Housekeeping and bye-bye\n                managedDictionary.removeAllChangeListeners()\n                looperThreadRealm.close()\n                looperThread.testComplete()\n            }\n            ChangeListenerOperation.UNDEFINED ->\n                throw IllegalArgumentException(\"Operation cannot be default\")\n        }\n    }\n}\n\nclass BinaryAsserter : TypeAsserter<ByteArray>() {\n\n    override fun assertEqualsHelper(realm: Realm, value: ByteArray?, valueFromRealm: ByteArray?) {\n        if (value == null && valueFromRealm == null) {\n            return\n        }\n\n        assertNotNull(value)\n        assertNotNull(valueFromRealm)\n\n        // ByteArrays need to be compared with Arrays.equals\n        assertTrue(value.contentEquals(valueFromRealm))\n    }\n}\n\nclass RealmModelAsserter : TypeAsserter<DogPrimaryKey>() {\n\n    override fun assertContainsValueNotThere(\n            realm: Realm,\n            dictionary: RealmDictionary<DogPrimaryKey>,\n            index: Int,\n            value: DogPrimaryKey?\n    ) {\n        // Given that only managed objects can be contained in a managed RealmModel dictionary, we\n        // need to test containsValue with a dummy model\n        realm.executeTransaction { transactionRealm ->\n            val dummyRealmModel = transactionRealm.copyToRealm(DogPrimaryKey(666 + index.toLong(), \"DUMMY\"))\n            assertFalse(dictionary.containsValue(dummyRealmModel as DogPrimaryKey))\n        }\n    }\n\n    override fun assertRemoveRealmModelFromRealm(\n            dictionary: RealmDictionary<DogPrimaryKey>,\n            index: Int,\n            key: String,\n            value: DogPrimaryKey?\n    ) {\n        if (value != null) {\n            // Removal of actual RealmModel to check whether it vanished from the dictionary\n            // Insert again - \"value\" is unmanaged\n            dictionary[key] = value\n\n            // Delete from realm and check we get null if we get it from the dictionary\n            val modelFromRealm = dictionary[key] as DogPrimaryKey\n            assertTrue(modelFromRealm.isValid)\n\n            modelFromRealm.deleteFromRealm()\n            assertFalse(modelFromRealm.isValid)\n\n            assertNull(dictionary[key])\n\n            // Check size again (despite object removal, size should remain unchanged)\n            assertEquals(index + 1, dictionary.size)\n\n            // Delete it again so that the forEach size check works\n            dictionary.remove(key)\n            assertEquals(index, dictionary.size)\n        }\n    }\n\n    override fun assertValues(dictionary: RealmDictionary<DogPrimaryKey>, value: DogPrimaryKey?) {\n        // null entries become \"invalid object\" when calling dictionary.values()\n        assertNotNull(value)\n        if (value.isValid) {\n            assertTrue(dictionary.containsValue(value))\n        } else {\n            assertTrue(dictionary.containsValue(null))\n        }\n    }\n\n    override fun assertContainsValueHelper(\n            realm: Realm,\n            key: String,\n            value: DogPrimaryKey?,\n            unmanagedDictionary: RealmDictionary<DogPrimaryKey>,\n            managedDictionary: RealmDictionary<DogPrimaryKey>\n    ) {\n        if (value == null) {\n            assertTrue(managedDictionary.containsValue(null))\n        } else {\n            // Use managed model for containsValue: managed dictionaries can only contain managed models\n            val managedRealmModel = realm.where<DogPrimaryKey>()\n                    .equalTo(\"name\", value.name)\n                    .findFirst()\n            assertTrue(managedDictionary.containsValue(managedRealmModel))\n        }\n    }\n\n    override fun assertEqualsHelper(\n            realm: Realm,\n            value: DogPrimaryKey?,\n            valueFromRealm: DogPrimaryKey?\n    ) {\n        val modelFromRealm = realm.where<DogPrimaryKey>()\n                .equalTo(\"name\", value?.name)\n                .findFirst()\n        if (value == null && valueFromRealm == null) {\n            assertEquals(modelFromRealm, valueFromRealm)\n            return\n        }\n\n        assertNotNull(modelFromRealm)\n        assertEquals(modelFromRealm, valueFromRealm)\n    }\n\n    override fun assertAccessorSetter(\n        realm: Realm,\n        dictionaryGetter: KFunction1<DictionaryAllTypes, RealmDictionary<DogPrimaryKey>>,\n        dictionarySetter: KFunction2<DictionaryAllTypes, RealmDictionary<DogPrimaryKey>, Unit>,\n        initializedDictionary: RealmDictionary<DogPrimaryKey>,\n        otherConfig: RealmConfiguration\n    ) {\n        realm.executeTransaction { transactionRealm ->\n            // Setter fails when calling with a dictionary that contains unmanaged objects\n            // The throwable is an IllegalArgumentException wrapped inside an InvocationTargetException\n            // due to calling 'call' on the KFunction2\n            val anotherContainer = transactionRealm.createObject<DictionaryAllTypes>()\n            assertFailsWith<InvocationTargetException> {\n                dictionarySetter.call(anotherContainer, initializedDictionary)\n            }.let { e ->\n                assertTrue {\n                    e.targetException is IllegalArgumentException\n                }\n            }\n        }\n\n        // Setter fails when calling with a dictionary containing managed objects from another Realm\n        var otherRealmDictionary: RealmDictionary<DogPrimaryKey>? = null\n        val otherRealm = Realm.getInstance(otherConfig)\n        otherRealm.executeTransaction { transactionRealm ->\n            val otherRealmContainer = transactionRealm.createObject<DictionaryAllTypes>()\n            otherRealmDictionary = dictionaryGetter.call(otherRealmContainer)\n                .apply { this.putAll(initializedDictionary) }\n        }\n\n        realm.executeTransaction { transactionRealm ->\n            val anotherContainer = transactionRealm.createObject<DictionaryAllTypes>()\n\n            // The throwable is an IllegalArgumentException wrapped inside an InvocationTargetException\n            // due to calling 'call' on the KFunction2\n            assertFailsWith<InvocationTargetException> {\n                dictionarySetter.call(anotherContainer, otherRealmDictionary)\n            }.let { e ->\n                assertTrue {\n                    e.targetException is IllegalArgumentException\n                }\n            }\n        }\n\n        // Remember to close the other Realm!\n        otherRealm.close()\n    }\n}\n\nclass RealmAnyAsserter : TypeAsserter<RealmAny>() {\n\n    override fun assertContainsValueNotThere(\n            realm: Realm,\n            dictionary: RealmDictionary<RealmAny>,\n            index: Int,\n            value: RealmAny?\n    ) {\n        if (value?.valueClass == DogPrimaryKey::class.java) {\n            // Similar to RealmModelAsserter\n            realm.executeTransaction { transactionRealm ->\n                val dummyRealmModel = transactionRealm.copyToRealm(DogPrimaryKey(666 + index.toLong(), \"DUMMY\"))\n                val realmAnyWithManagedModel = RealmAny.valueOf(dummyRealmModel)\n                assertFalse(dictionary.containsValue(realmAnyWithManagedModel as RealmAny))\n            }\n        } else {\n            assertFalse(dictionary.containsValue(value))\n        }\n    }\n\n    override fun assertRemoveRealmModelFromRealm(\n            dictionary: RealmDictionary<RealmAny>,\n            index: Int,\n            key: String,\n            value: RealmAny?\n    ) {\n        // No need to check anything for other types than RealmModel\n        if (value is RealmAny && value.valueClass == DogPrimaryKey::class.java) {\n            // Removal of actual RealmModel to check whether it vanished from the dictionary\n            // Insert again - \"value\" is unmanaged\n            dictionary[key] = value\n\n            // Delete from realm and check we get null if we get it from the dictionary\n            val realmAnyValue = dictionary[key] as RealmAny\n            val modelFromRealm = realmAnyValue.asRealmModel(DogPrimaryKey::class.java)\n            assertTrue(modelFromRealm.isValid)\n\n            modelFromRealm.deleteFromRealm()\n            assertFalse(modelFromRealm.isValid)\n\n            assertTrue((dictionary[key] as RealmAny).isNull)\n\n            // Check size again (despite object removal, size should remain unchanged)\n            assertEquals(index + 1, dictionary.size)\n\n            // Delete it again so that the forEach size check works\n            dictionary.remove(key)\n            assertEquals(index, dictionary.size)\n        }\n    }\n\n    override fun assertContainsValueHelper(\n            realm: Realm,\n            key: String,\n            value: RealmAny?,\n            unmanagedDictionary: RealmDictionary<RealmAny>,\n            managedDictionary: RealmDictionary<RealmAny>\n    ) {\n        // We can never get null RealmAny values from a managed dictionary\n        assertNotNull(value)\n\n        if (value.isNull) {\n            // If null, check we have \"RealmAny.nullValue()\"\n            assertTrue(managedDictionary.containsValue(RealmAny.nullValue()))\n        } else if (value.valueClass == DogPrimaryKey::class.java) {\n            // If RealmModel, check dictionary contains a RealmAny containing the managed model\n            val managedRealmDog = realm.where<DogPrimaryKey>()\n                    .equalTo(\"name\", value.asRealmModel(DogPrimaryKey::class.java).name)\n                    .findFirst()\n            val realmAnyWithManagedDog = RealmAny.valueOf(managedRealmDog)\n            assertTrue(managedDictionary.containsValue(realmAnyWithManagedDog))\n        } else {\n            assertTrue(managedDictionary.containsValue(managedDictionary[key]))\n        }\n    }\n\n    override fun assertEqualsHelper(realm: Realm, value: RealmAny?, valueFromRealm: RealmAny?) {\n        // If null, check we have \"RealmAny.nullValue()\"\n        if (null == value) {\n            assertNotNull(valueFromRealm)\n            assertTrue(valueFromRealm.isNull)\n        } else if (value.valueClass == DogPrimaryKey::class.java) {\n            // If RealmModel, check provided the RealmAny equals a RealmAny containing the managed model\n            val managedRealmModel = realm.where<DogPrimaryKey>()\n                    .equalTo(\"name\", (value as RealmAny).asRealmModel(DogPrimaryKey::class.java).name)\n                    .findFirst()\n            val realmAnyWithManagedModel = RealmAny.valueOf(managedRealmModel)\n            assertEquals(valueFromRealm, realmAnyWithManagedModel)\n        } else {\n            assertEquals(value, valueFromRealm)\n        }\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/kotlin/io/realm/ManagedSetTester.kt",
    "content": "/*\n * Copyright 2021 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\npackage io.realm\n\nimport io.realm.entities.*\nimport io.realm.kotlin.createObject\nimport io.realm.kotlin.where\nimport io.realm.rule.BlockingLooperThread\nimport org.bson.types.Decimal128\nimport org.bson.types.ObjectId\nimport java.lang.UnsupportedOperationException\nimport java.util.*\nimport kotlin.reflect.KFunction1\nimport kotlin.reflect.KFunction2\nimport kotlin.reflect.KMutableProperty1\nimport kotlin.reflect.KProperty1\nimport kotlin.test.*\n\n/**\n * Generic tester for all types of unmanaged sets.\n */\nclass ManagedSetTester<T : Any>(\n        private val testerName: String,\n        private val setFieldName: String,\n        private val setFieldClass: Class<T>,\n        private val realmAnyType: RealmAny.Type? = null,\n        private val setGetter: KFunction1<SetAllTypes, RealmSet<T>>,\n        private val setSetter: KFunction2<SetAllTypes, RealmSet<T>, Unit>,\n        private val requiredSetGetter: KFunction1<SetAllTypes, RealmSet<T>>? = null,\n        private val managedSetGetter: KProperty1<SetContainerClass, RealmSet<T>>,\n        private val managedCollectionGetter: KProperty1<SetContainerClass, RealmList<T>>,\n        private val initializedSet: List<T?>,\n        private val notPresentValue: T,\n        private val toArrayManaged: ToArrayManaged<T>,\n        private val nullable: Boolean = true,\n        private val equalsTo: (expected: T?, value: T?) -> Boolean = { expected, value ->\n            // Used to assert that the contents of two collections are the same.\n           expected == value\n        },\n        private val primaryKeyAllTypesSetProperty: KMutableProperty1<SetAllTypesPrimaryKey, RealmSet<T>>\n) : SetTester {\n\n    private lateinit var config: RealmConfiguration\n    private lateinit var looperThread: BlockingLooperThread\n    private lateinit var realm: Realm\n\n    override fun toString(): String = \"ManagedSet-${testerName}\"\n\n    override fun setUp(config: RealmConfiguration, looperThread: BlockingLooperThread) {\n        this.config = config\n        this.looperThread = looperThread\n        this.realm = Realm.getInstance(config)\n    }\n\n    override fun tearDown() = realm.close()\n\n    override fun isManaged() = assertTrue(initAndAssertEmptySet(id = \"id\").isManaged)\n\n    override fun isValid() = assertTrue(initAndAssertEmptySet(id = \"id\").isValid)\n\n    override fun isFrozen() = Unit          // Tested in frozen\n\n    override fun size() {\n        val set = initAndAssertEmptySet(id = \"id\")\n\n        realm.executeTransaction {\n            initializedSet.forEach { value ->\n                set.add(value)\n            }\n        }\n        assertEquals(initializedSet.size, set.size)\n    }\n\n    override fun isEmpty() {\n        val set = initAndAssertEmptySet(id = \"id\")\n\n        realm.executeTransaction {\n            initializedSet.forEach { value ->\n                set.add(value)\n            }\n        }\n        assertFalse(set.isEmpty())\n    }\n\n    override fun contains() {\n        val set = initAndAssertEmptySet(id = \"id\")\n\n        initializedSet.forEach { value ->\n            assertFalse(set.contains(value))\n        }\n        realm.executeTransaction {\n            set.addAll(initializedSet)\n        }\n        initializedSet.forEach { value ->\n            assertTrue(set.contains(value))\n        }\n        assertFalse(set.contains(notPresentValue))\n\n        // Throws if we call contains with something entirely different\n        val somethingEntirelyDifferent = initializedSet.map {\n            Pair(it, it)\n        }\n        assertFailsWith<ClassCastException> {\n            set.contains<Any>(somethingEntirelyDifferent)\n        }\n    }\n\n    override fun iterator() {\n        val set = initAndAssertEmptySet(id = \"id\")\n\n        assertNotNull(set.iterator())\n        realm.executeTransaction {\n            set.addAll(initializedSet)\n        }\n\n        initializedSet.forEach { value ->\n            assertTrue(set.contains(value))\n        }\n    }\n\n    override fun toArray() {\n        val set = initAndAssertEmptySet(id = \"id\")\n\n        // Empty set\n        assertEquals(0, set.toArray().size)\n\n        // Set with some values\n        realm.executeTransaction {\n            // Empty set\n            assertEquals(0, set.toArray().size)\n\n            set.addAll(initializedSet)\n            val setToArray = set.toArray()\n            assertNotNull(setToArray)\n            assertEquals(initializedSet.size, setToArray.size)\n\n            val sameValuesUnmanagedSetToArray = RealmSet<T>().apply {\n                addAll(initializedSet)\n            }.toArray()\n\n            setToArray.contentEquals(sameValuesUnmanagedSetToArray)\n        }\n    }\n\n    override fun toArrayWithParameter() {\n        val set = initAndAssertEmptySet(id = \"id\")\n        toArrayManaged.assertToArrayWithParameter(realm, set, initializedSet)\n    }\n\n    override fun add() {\n        val set = initAndAssertEmptySet(id = \"id\")\n\n        realm.executeTransaction {\n            // Adding a value for the first time returns true\n            initializedSet.forEach { value ->\n                assertTrue(set.add(value))\n            }\n            // Adding an existing value returns false\n            initializedSet.forEach { value ->\n                assertFalse(set.add(value))\n            }\n        }\n\n        assertTrue(set.containsAll(initializedSet))\n    }\n\n    override fun remove() {\n        val set = initAndAssertEmptySet(id = \"id\")\n\n        realm.executeTransaction {\n            set.addAll(initializedSet)\n            initializedSet.forEach { value ->\n                assertTrue(set.remove(value))\n            }\n            assertTrue(set.isEmpty())\n\n            // Does not change if we remove something that is not there\n            assertFalse(set.remove(notPresentValue))\n\n            // Throws if we remove an object that is not the same type as the set\n            val somethingEntirelyDifferent = initializedSet.map {\n                Pair(it, it)\n            }\n            assertFailsWith<ClassCastException> {\n                set.remove<Any>(somethingEntirelyDifferent)\n            }\n\n            if (nullable) {\n                // Does not change if we remove null and null is not present\n                assertFalse(set.remove(null))\n            } else {\n                assertFailsWith<java.lang.NullPointerException>(\"Set does not support null values\") {\n                    set.remove(null)\n                }\n            }\n        }\n\n        assertEquals(0, set.size)\n    }\n\n    override fun containsAll() {\n        val set = initAndAssertEmptySet(id = \"id\")\n\n        realm.executeTransaction { transactionRealm ->\n            set.addAll(initializedSet)\n\n            // Contains an unmanaged collection\n            assertTrue(set.containsAll(initializedSet))\n\n            // Does not contain an unmanaged collection\n            assertFalse(set.containsAll(listOf(notPresentValue)))\n\n            // Contains a managed set (itself)\n            assertTrue(set.containsAll(set))\n\n            // Contains an empty collection - every set contains the empty set\n            assertTrue(set.containsAll(listOf()))\n\n            // Throws when passing a collection of a different type\n            val collectionOfDifferentType = initializedSet.map {\n                Pair(it, it)\n            }\n            assertFailsWith<java.lang.ClassCastException> {\n                set.containsAll(collectionOfDifferentType as Collection<*>)\n            }\n\n            // Contains a managed set containing the same values\n            val sameValuesManagedSet = managedSetGetter.get(transactionRealm.createObject())\n            sameValuesManagedSet.addAll(initializedSet)\n            assertEquals(initializedSet.size, sameValuesManagedSet.size)\n            assertTrue(set.containsAll(sameValuesManagedSet as Collection<*>))\n\n            // Does not contain a managed set with other values\n            val notPresentValueSet = managedSetGetter.get(transactionRealm.createObject())\n            notPresentValueSet.add(notPresentValue)\n            assertFalse(notPresentValueSet.isEmpty())\n            assertFalse(set.containsAll(notPresentValueSet as Collection<*>))\n\n            // Contains an empty RealmSet\n            val emptyManagedSet = managedSetGetter.get(transactionRealm.createObject())\n            assertTrue(emptyManagedSet.isEmpty())\n            assertTrue(set.containsAll(emptyManagedSet))\n\n            // Contains a managed list with the same elements\n            val sameValuesManagedList = managedCollectionGetter.call(transactionRealm.createObject<SetContainerClass>())\n            sameValuesManagedList.addAll(initializedSet)\n            assertTrue(set.containsAll(sameValuesManagedList))\n\n            // Does not contain a managed list with the other elements\n            val differentValuesManagedList =\n                managedCollectionGetter.call(transactionRealm.createObject<SetContainerClass>())\n            differentValuesManagedList.add(notPresentValue)\n            assertFalse(set.containsAll(differentValuesManagedList))\n\n            // Contains an empty managed list\n            val emptyValuesManagedList =\n                managedCollectionGetter.call(transactionRealm.createObject<SetContainerClass>())\n            assertTrue(set.containsAll(emptyValuesManagedList))\n\n            // TODO: it's not possible to test passing a null value from Kotlin, even if using\n            //  TestHelper.getNull(). It seems that Kotlin generates different bytecode when the\n            //  parameter to the function is a generics collection with an upper bound.\n            //  The only way to test this is by writing a Java test instead.\n        }\n    }\n\n    override fun addAll() {\n        val set = initAndAssertEmptySet(id = \"id\")\n\n        realm.executeTransaction { transactionRealm ->\n            // Changes after adding collection\n            assertTrue(set.addAll(initializedSet))\n            assertEquals(initializedSet.size, set.size)\n\n            // Does not change if we add the same data\n            assertFalse(set.addAll(initializedSet))\n            assertEquals(initializedSet.size, set.size)\n\n            // Does not change if we add itself to it\n            assertFalse(set.addAll(set))\n            assertEquals(initializedSet.size, set.size)\n\n            // Does not change if we add an empty collection\n            assertFalse(set.addAll(listOf()))\n            assertEquals(initializedSet.size, set.size)\n\n            // Throws when adding a collection of a different type\n            val somethingEntirelyDifferent = initializedSet.map {\n                Pair(it, it)\n            }\n            assertFailsWith<ClassCastException> {\n                set.addAll(somethingEntirelyDifferent as Collection<T>)\n            }\n\n            // Does not change if we add the same data from a managed set\n            val sameValuesManagedSet = managedSetGetter.get(transactionRealm.createObject())\n            assertNotNull(sameValuesManagedSet)\n            assertTrue(sameValuesManagedSet.addAll(initializedSet))\n            assertFalse(set.addAll(sameValuesManagedSet as Collection<T>))\n            assertEquals(initializedSet.size, set.size)\n\n            // Does not change if we add an empty RealmSet\n            val emptyManagedSet = managedSetGetter.get(transactionRealm.createObject())\n            assertTrue(emptyManagedSet.isEmpty())\n            assertFalse(set.addAll(emptyManagedSet))\n            assertEquals(initializedSet.size, set.size)\n\n            // Changes after adding a managed set containing other values\n            val notPresentValueSet = managedSetGetter.get(transactionRealm.createObject())\n            assertNotNull(notPresentValueSet)\n            notPresentValueSet.add(notPresentValue)\n            assertTrue(set.addAll(notPresentValueSet as Collection<T>))\n            assertEquals(initializedSet.size + notPresentValueSet.size, set.size)\n\n            // Does not change after adding a managed list with the same elements\n            set.clear()\n            set.addAll(initializedSet)\n            val sameValuesManagedList = managedCollectionGetter.call(transactionRealm.createObject<SetContainerClass>())\n            sameValuesManagedList.addAll(initializedSet)\n            assertFalse(set.addAll(sameValuesManagedList))\n            assertTrue(set.containsAll(sameValuesManagedList))\n\n            // Changes after adding a managed list with other elements\n            val differentValuesManagedList =\n                managedCollectionGetter.call(transactionRealm.createObject<SetContainerClass>())\n            differentValuesManagedList.addAll(listOf(notPresentValue))\n            assertTrue(set.addAll(differentValuesManagedList))\n            assertTrue(set.containsAll(differentValuesManagedList))\n\n            // Does not change after adding an empty managed list\n            set.clear()\n            assertTrue(set.addAll(initializedSet))\n            val emptyValuesManagedList =\n                managedCollectionGetter.call(transactionRealm.createObject<SetContainerClass>())\n            assertFalse(set.addAll(emptyValuesManagedList))\n            assertEquals(initializedSet.size, set.size)\n\n            // Fails if passed null according to Java Set interface\n            assertFailsWith<NullPointerException> {\n                set.addAll(TestHelper.getNull())\n            }\n        }\n    }\n\n    override fun dynamic() {\n        // Create a set from a immutable schema context\n        val set = initAndAssertEmptySet(id = \"id\")\n        realm.executeTransaction {\n            set.addAll(initializedSet)\n        }\n\n        val dynamicRealm = DynamicRealm.getInstance(realm.configuration)\n        val dynamicObject: DynamicRealmObject = dynamicRealm.where(SetAllTypes.NAME).equalTo(AllTypes.FIELD_STRING, \"id\").findFirst()!!\n        val dynamicSet = dynamicObject.getRealmSet(setFieldName, setFieldClass)\n\n        // Access the previous set from a mutable context\n        assertSetContainsSet(initializedSet, dynamicSet)\n\n        // Update the set with a new value\n        dynamicRealm.executeTransaction {\n            dynamicSet.add(notPresentValue)\n        }\n\n        assertSetContainsSet(initializedSet.plus(notPresentValue), dynamicSet)\n\n        // Try to replace the whole set by a new one\n        dynamicRealm.executeTransaction {\n            dynamicObject.setRealmSet(setFieldName, RealmSet<T>().apply {\n                add(notPresentValue)\n            })\n        }\n\n        assertSetContainsSet(listOf(notPresentValue), dynamicSet)\n        assertEquals(1, dynamicObject.get<RealmSet<T>>(setFieldName).size)\n\n        // Validate that set is properly represented as a String\n        validateToString(dynamicObject, dynamicSet)\n\n        dynamicRealm.close()\n    }\n\n    fun validateToString(dynamicObject: DynamicRealmObject, dynamicSet: RealmSet<*>) {\n        val type = when (setFieldClass.simpleName) {\n            \"Byte\", \"Short\", \"Integer\" -> \"Long\"\n            else -> setFieldClass.simpleName\n        }\n\n        val expectedSetString = \"${setFieldName}:RealmSet<$type>[${dynamicSet.size}]\"\n        assertTrue(\n            dynamicObject.toString().contains(expectedSetString),\n            \"DynamicRealmObject does not contain expected RealmSet string: $expectedSetString\"\n        )\n    }\n\n    override fun insert() {\n        doInsertTest(initializedSet)\n    }\n\n    // Separate method to allow calls from RealmModelSetManagedTester with unmanaged realm objects\n    fun doInsertTest(expectedSet: List<T?>) {\n        // Instantiate container and set Set on container\n        val manualInstance = SetAllTypes().apply {\n            setSetter.call(this, RealmSet<T>().init(expectedSet))\n        }\n\n        // Insert into Realm\n        realm.executeTransaction {\n            realm.insert(manualInstance)\n        }\n\n        // Get set from container from Realm\n        val allTypesObject = realm.where<SetAllTypes>().findFirst()\n        assertNotNull(allTypesObject)\n        val set: RealmSet<T> = setGetter.call(allTypesObject)\n\n        assertFalse(set.isEmpty())\n        assertSetContainsSet(expectedSet, set)\n    }\n\n    override fun insertList() {\n        doInsertListTest(initializedSet)\n    }\n\n    // Separate method to allow calls from RealmModelSetManagedTester with unmanaged realm objects\n    fun doInsertListTest(expectedSet: List<T?>) {\n        // Instantiate container and set Set on container\n        val manualInstance = SetAllTypes().apply {\n            setSetter.call(this, RealmSet<T>().init(expectedSet))\n        }\n\n        val emptyInstace = SetAllTypes()\n\n        // Insert into Realm\n        realm.executeTransaction {\n            realm.insert(listOf(emptyInstace, manualInstance))\n        }\n\n        // Get set from container from Realm\n        val allTypesObject = realm.where<SetAllTypes>().findAll()[1]\n        assertNotNull(allTypesObject)\n        val set: RealmSet<T> = setGetter.call(allTypesObject)\n\n        assertFalse(set.isEmpty())\n        assertSetContainsSet(expectedSet, set)\n    }\n\n    override fun insertOrUpdate() {\n        // Instantiate container and set Set on container\n        val manualInstance = SetAllTypesPrimaryKey().apply {\n            primaryKeyAllTypesSetProperty.setter(this, RealmSet<T>().init(initializedSet))\n        }\n\n        // Insert to Realm\n        realm.executeTransaction {\n            realm.insertOrUpdate(manualInstance)\n        }\n\n        // Get Set from container from Realm\n        val allTypesPrimaryKey = realm.where<SetAllTypesPrimaryKey>().findFirst()!!\n        val set = primaryKeyAllTypesSetProperty.get(allTypesPrimaryKey)\n        assertFalse(set.isEmpty())\n\n        assertSetContainsSet(initializedSet, set)\n\n        primaryKeyAllTypesSetProperty.getter(manualInstance).add(notPresentValue)\n\n        // Insert to Realm with non managed updated model\n        realm.executeTransaction {\n            realm.insertOrUpdate(manualInstance)\n        }\n\n        val updatedContainer = realm.where<SetAllTypesPrimaryKey>().findFirst()!!\n        val updatedSet = primaryKeyAllTypesSetProperty.get(updatedContainer)\n        assertEquals(initializedSet.size + 1, updatedSet.size)\n\n        assertSetContainsSet(initializedSet.plus(notPresentValue), set)\n    }\n\n    override fun insertOrUpdateList() {\n        // Instantiate container and set Set on container\n        val manualInstance = SetAllTypesPrimaryKey().apply {\n            columnLong = 0\n            primaryKeyAllTypesSetProperty.setter(this, RealmSet<T>().init(initializedSet))\n        }\n\n        val emptyInstance = SetAllTypesPrimaryKey().apply {\n            columnLong = 1\n        }\n\n        // Insert to Realm\n        realm.executeTransaction {\n            realm.insertOrUpdate(listOf(emptyInstance, manualInstance))\n        }\n\n        // Get Set from container from Realm\n        val allTypesPrimaryKey = realm.where<SetAllTypesPrimaryKey>().equalTo(\"columnLong\", 0.toLong()).findFirst()!!\n        val set = primaryKeyAllTypesSetProperty.get(allTypesPrimaryKey)\n        assertFalse(set.isEmpty())\n\n        assertSetContainsSet(initializedSet, set)\n\n        primaryKeyAllTypesSetProperty.getter(manualInstance).add(notPresentValue)\n\n        // Insert to Realm with non managed updated model\n        realm.executeTransaction {\n            realm.insertOrUpdate(listOf(emptyInstance, manualInstance))\n        }\n\n        val updatedContainer = realm.where<SetAllTypesPrimaryKey>().equalTo(\"columnLong\", 0L).findFirst()!!\n        val updatedSet = primaryKeyAllTypesSetProperty.get(updatedContainer)\n        assertEquals(initializedSet.size + 1, updatedSet.size)\n\n        assertSetContainsSet(initializedSet.plus(notPresentValue), set)\n    }\n\n    override fun copyToRealm() {\n        doCopyToRealmTest(initializedSet)\n    }\n\n    // Separate method to allow calls from RealmModelSetManagedTester with unmanaged realm objects\n    fun doCopyToRealmTest(expectedSet: List<T?>) {\n        // Instantiate container and set Set on container\n        val manualInstance = SetAllTypes().apply {\n            setSetter.call(this, RealmSet<T>().init(expectedSet))\n        }\n\n        // Copy to Realm\n        realm.executeTransaction {\n            val allTypesObject = realm.copyToRealm(manualInstance)\n            assertNotNull(allTypesObject)\n        }\n\n        // Get set from container from Realm\n        val allTypesObject = realm.where<SetAllTypes>().findFirst()\n        assertNotNull(allTypesObject)\n        val set: RealmSet<T> = setGetter.call(allTypesObject)\n\n        assertFalse(set.isEmpty())\n        assertSetContainsSet(expectedSet, set)\n    }\n\n    private fun assertSetContainsSet(expectedSet: List<T?>, set: RealmSet<T>) {\n        set.forEach loop@{ value ->\n            expectedSet.forEach { expected ->\n                if (equalsTo(expected, value)) {\n                    return@loop\n                }\n            }\n            fail(\"Missing value\")\n        }\n    }\n\n    override fun copyToRealmOrUpdate() {\n        // Instantiate container and set Set on container\n        val manualInstance = SetAllTypesPrimaryKey().apply {\n            primaryKeyAllTypesSetProperty.setter(this, RealmSet<T>().init(initializedSet))\n        }\n\n        // Copy to Realm\n        realm.executeTransaction {\n            val allTypesObject = realm.copyToRealmOrUpdate(manualInstance)\n            assertNotNull(allTypesObject)\n        }\n\n        // Get Set from container from Realm\n        val allTypesPrimaryKey = realm.where<SetAllTypesPrimaryKey>().findFirst()!!\n        val set = primaryKeyAllTypesSetProperty.get(allTypesPrimaryKey)\n        assertFalse(set.isEmpty())\n\n        assertSetContainsSet(initializedSet, set)\n\n        primaryKeyAllTypesSetProperty.getter(manualInstance).add(notPresentValue)\n\n        // Copy to Realm with non managed updated model\n        realm.executeTransaction {\n            val allTypesObject = realm.copyToRealmOrUpdate(manualInstance)\n            assertNotNull(allTypesObject)\n        }\n\n        val updatedContainer = realm.where<SetAllTypesPrimaryKey>().findFirst()!!\n        val updatedSet = primaryKeyAllTypesSetProperty.get(updatedContainer)\n        assertEquals(initializedSet.size + 1, updatedSet.size)\n\n        assertSetContainsSet(initializedSet.plus(notPresentValue), set)\n    }\n\n    override fun requiredConstraints() {\n        // RealmModel and RealmAny setters are ignored since they cannot be marked with \"@Required\"\n        if (requiredSetGetter != null) {\n            val allTypesObject = createAllTypesManagedContainerAndAssert(realm, \"id\")\n            assertNotNull(allTypesObject)\n            val set: RealmSet<T> = requiredSetGetter.call(allTypesObject)\n            // Check we can't operate with nulls on a RealmSet marked as \"@Required\"\n            realm.executeTransaction {\n                // Validate we cannot use Null values on add\n                assertFailsWith<java.lang.NullPointerException> {\n                    set.add(null)\n                }\n\n                // Validate we cannot use Null values on remove\n                assertFailsWith<java.lang.NullPointerException> {\n                    set.remove(null)\n                }\n\n                // Validate we cannot use Null values on contains\n                assertFailsWith<java.lang.NullPointerException> {\n                    set.contains(null)\n                }\n\n                // Validate we cannot use Null values on addAll\n                assertFailsWith<java.lang.NullPointerException> {\n                    set.addAll(listOf(null))\n                }\n\n                // Validate we cannot use Null values on removeAll\n                assertFailsWith<java.lang.NullPointerException> {\n                    set.removeAll(listOf(null))\n                }\n\n                // Validate we cannot use Null values on containsAll\n                assertFailsWith<java.lang.NullPointerException> {\n                    set.containsAll(listOf(null))\n                }\n\n                // Validate we cannot use Null values on retainAll\n                assertFailsWith<java.lang.NullPointerException> {\n                    set.add(initializedSet[0])\n                    set.retainAll(listOf(null))\n                }\n            }\n\n            // Now check it works normally for the same field but without null values\n            realm.executeTransaction {\n                set.add(notPresentValue)\n                set.remove(notPresentValue)\n                set.contains(notPresentValue)\n\n                set.addAll(listOf(notPresentValue))\n                set.removeAll(listOf(notPresentValue))\n                set.containsAll(listOf(notPresentValue))\n                set.add(notPresentValue)\n                set.retainAll(listOf(notPresentValue))\n            }\n        }\n    }\n\n    override fun retainAll() {\n        val set = initAndAssertEmptySet(id = \"id\")\n\n        realm.executeTransaction { transactionRealm ->\n            // Does not change after empty set intersects with another collection\n            assertFalse(set.retainAll(initializedSet))\n            assertTrue(set.isEmpty())\n\n            // Does not change after empty set intersects with empty collection\n            assertFalse(set.retainAll(listOf()))\n            assertTrue(set.isEmpty())\n\n            // Does not change after adding data and intersecting it with same values\n            set.addAll(initializedSet)\n            assertEquals(initializedSet.size, set.size)\n            assertFalse(set.retainAll(initializedSet))\n            assertEquals(initializedSet.size, set.size)\n\n            // Changes after intersection with empty collection\n            assertTrue(set.retainAll(listOf()))\n            assertTrue(set.isEmpty())\n\n            // Throws after intersection with a collection of a different type\n            set.addAll(initializedSet)\n            val collectionOfDifferentType = initializedSet.map {\n                Pair(it, it)\n            }\n            assertFailsWith<ClassCastException> {\n                set.retainAll(collectionOfDifferentType as Collection<*>)\n            }\n\n            // Changes after adding data and intersecting it with other values\n            assertEquals(initializedSet.size, set.size)\n            assertTrue(set.retainAll(listOf(notPresentValue)))\n            assertTrue(set.isEmpty())\n\n            // Does not change after intersection with itself\n            set.clear()\n            set.addAll(initializedSet)\n            assertFalse(set.isEmpty())\n            assertFalse(set.retainAll(set))\n            assertEquals(initializedSet.size, set.size)\n\n            // Does not change after intersection with another set containing the same elements\n            set.clear()\n            set.addAll(initializedSet)\n            val sameValuesManagedSet = managedSetGetter.get(transactionRealm.createObject())\n            assertNotNull(sameValuesManagedSet)\n            sameValuesManagedSet.addAll(initializedSet)\n            assertFalse(set.retainAll(sameValuesManagedSet as Collection<T>))\n            assertEquals(initializedSet.size, set.size)\n\n            // Changes after intersection with a managed set not containing any elements from the original set\n            set.clear()\n            set.addAll(initializedSet)\n            assertEquals(initializedSet.size, set.size)\n            val notPresentValueSet = managedSetGetter.get(transactionRealm.createObject())\n            assertNotNull(notPresentValueSet)\n            notPresentValueSet.add(notPresentValue)\n            assertTrue(set.retainAll(notPresentValueSet as Collection<T>))\n            assertTrue(set.isEmpty())\n\n            // Changes after intersection with another empty, managed set\n            set.clear()\n            set.addAll(initializedSet)\n            val emptyManagedSet = managedSetGetter.get(transactionRealm.createObject())\n            assertNotNull(emptyManagedSet)\n            assertTrue(set.retainAll(emptyManagedSet as Collection<T>))\n            assertTrue(set.isEmpty())\n\n            // Does not change after intersection with a managed list with the same elements\n            set.clear()\n            set.addAll(initializedSet)\n            val sameValuesManagedList = managedCollectionGetter.call(transactionRealm.createObject<SetContainerClass>())\n            sameValuesManagedList.addAll(initializedSet)\n            assertFalse(set.retainAll(sameValuesManagedList))\n            assertTrue(set.containsAll(sameValuesManagedList))\n\n            // Changes after intersection with a managed list with other elements\n            val differentValuesManagedList =\n                managedCollectionGetter.call(transactionRealm.createObject<SetContainerClass>())\n            differentValuesManagedList.addAll(listOf(notPresentValue))\n            assertTrue(set.retainAll(differentValuesManagedList))\n            assertTrue(set.isEmpty())\n\n            // Changes after intersection with an empty managed list\n            set.clear()\n            set.addAll(initializedSet)\n            val emptyValuesManagedList =\n                managedCollectionGetter.call(transactionRealm.createObject<SetContainerClass>())\n            assertTrue(set.retainAll(emptyValuesManagedList))\n            assertTrue(set.isEmpty())\n\n            // TODO: it's not possible to test passing a null value from Kotlin, even if using\n            //  TestHelper.getNull(). It seems that Kotlin generates different bytecode when the\n            //  parameter to the function is a generics collection with an upper bound.\n            //  The only way to test this is by writing a Java test instead.\n        }\n    }\n\n    override fun removeAll() {\n        val set = initAndAssertEmptySet(id = \"id\")\n\n        realm.executeTransaction { transactionRealm ->\n            // Does not change after removing a some values from an empty set\n            assertTrue(set.isEmpty())\n            assertFalse(set.removeAll(initializedSet))\n            assertTrue(set.isEmpty())\n\n            // Changes after adding values and then remove all\n            set.addAll(initializedSet)\n            assertEquals(initializedSet.size, set.size)\n            assertTrue(set.removeAll(initializedSet))\n            assertTrue(set.isEmpty())\n\n            // Does not change after adding values again and remove empty collection\n            set.addAll(initializedSet)\n            assertFalse(set.removeAll(listOf()))\n            assertEquals(initializedSet.size, set.size)\n\n            // Throws when removing a list of a different type\n            val differentTypeCollection = initializedSet.map {\n                Pair(it, it)\n            }\n            assertFailsWith<ClassCastException> {\n                set.removeAll(differentTypeCollection as Collection<*>)\n            }\n\n            // Does not change after remove something else from empty set\n            assertFalse(set.removeAll(listOf(notPresentValue)))\n            assertEquals(initializedSet.size, set.size)\n\n            // Changes if we remove all items using itself\n            set.addAll(initializedSet)\n            assertEquals(initializedSet.size, set.size)\n            assertTrue(set.removeAll(set))\n            assertTrue(set.isEmpty())\n\n            // Changes if we add some values and remove all items afterwards using another set containing the same items\n            set.addAll(initializedSet)\n            val sameValuesManagedSet = managedSetGetter.get(transactionRealm.createObject())\n            assertNotNull(sameValuesManagedSet)\n            sameValuesManagedSet.addAll(initializedSet)\n            assertEquals(initializedSet.size, sameValuesManagedSet.size)\n            assertTrue(set.removeAll(sameValuesManagedSet as Collection<T>))\n            assertTrue(set.isEmpty())\n\n            // Does not change if we add some values and remove a value not contained in the set afterwards\n            set.addAll(initializedSet)\n            assertEquals(initializedSet.size, set.size)\n            val notPresentValueSet = managedSetGetter.get(transactionRealm.createObject())\n            assertNotNull(notPresentValueSet)\n            notPresentValueSet.add(notPresentValue)\n            assertFalse(set.removeAll(notPresentValueSet as Collection<T>))\n            assertEquals(initializedSet.size, set.size)\n\n            // Changes after removing a managed list with the same elements\n            set.clear()\n            set.addAll(initializedSet)\n            val sameValuesManagedList = managedCollectionGetter.call(transactionRealm.createObject<SetContainerClass>())\n            sameValuesManagedList.addAll(initializedSet)\n            assertTrue(set.removeAll(sameValuesManagedList))\n            assertTrue(set.isEmpty())\n\n            // Does not change after removing a managed list with other elements\n            set.clear()\n            set.addAll(initializedSet)\n            val differentValuesManagedList =\n                managedCollectionGetter.call(transactionRealm.createObject<SetContainerClass>())\n            differentValuesManagedList.addAll(listOf(notPresentValue))\n            assertFalse(set.removeAll(differentValuesManagedList))\n            assertEquals(initializedSet.size, set.size)\n\n            // Does not change after removing an empty managed list\n            set.clear()\n            set.addAll(initializedSet)\n            val emptyValuesManagedList =\n                managedCollectionGetter.call(transactionRealm.createObject<SetContainerClass>())\n            assertFalse(set.removeAll(emptyValuesManagedList))\n            assertEquals(initializedSet.size, set.size)\n\n            // TODO: it's not possible to test passing a null value from Kotlin, even if using\n            //  TestHelper.getNull(). It seems that Kotlin generates different bytecode when the\n            //  parameter to the function is a generics collection with an upper bound.\n            //  The only way to test this is by writing a Java test instead.\n        }\n    }\n\n    override fun clear() {\n        val set = initAndAssertEmptySet(id = \"id\")\n\n        realm.executeTransaction {\n            set.add(notPresentValue)\n            assertEquals(1, set.size)\n            set.clear()\n            assertEquals(0, set.size)\n        }\n    }\n\n    override fun freeze() {\n        val set = initAndAssertEmptySet(id = \"id\")\n\n        realm.executeTransaction {\n            set.addAll(initializedSet)\n        }\n\n        val frozenSet = set.freeze()\n        assertFalse(set.isFrozen)\n        assertTrue(frozenSet.isFrozen)\n        assertEquals(set.size, frozenSet.size)\n    }\n\n    override fun setters() {\n        val allFields = createAllTypesManagedContainerAndAssert(realm, \"id\")\n        val aSet = RealmSet<T>().init(initializedSet)\n\n        realm.executeTransaction {\n            setSetter(allFields, aSet)\n            assertEquals(aSet.size, setGetter(allFields).size)\n\n            // Validate it can assign the set to itself\n            val managedSet = setGetter(allFields)\n            setSetter(allFields, managedSet)\n            assertEquals(aSet.size, setGetter(allFields).size)\n        }\n    }\n\n    override fun addRealmChangeListener() {\n        looperThread.runBlocking {\n            val looperThreadRealm = Realm.getInstance(config)\n\n            // Get set\n            val set = initAndAssertEmptySet(looperThreadRealm, \"id\")\n\n            // Define operation we perform on the dictionary\n            var operation = ChangeListenerOperation.UNDEFINED\n\n            set.addChangeListener { newSet ->\n                when (operation) {\n                    ChangeListenerOperation.INSERT -> {\n                        assertEquals(initializedSet.size, newSet.size)\n                    }\n                    ChangeListenerOperation.DELETE -> {\n                        assertTrue(newSet.isEmpty())\n                        looperThreadRealm.close()\n                        looperThread.testComplete()\n                    }\n                    else -> Unit\n                }\n            }\n\n            // Insert objects in set\n            looperThreadRealm.executeTransaction {\n                operation = ChangeListenerOperation.INSERT\n                set.addAll(initializedSet)\n            }\n\n            // Clear set\n            looperThreadRealm.executeTransaction {\n                operation = ChangeListenerOperation.DELETE\n                set.clear()\n            }\n        }\n    }\n\n    override fun addSetChangeListener() {\n        looperThread.runBlocking {\n            val looperThreadRealm = Realm.getInstance(config)\n\n            // Get set\n            val set = initAndAssertEmptySet(looperThreadRealm, \"id\")\n\n            // Define operation we perform on the dictionary\n            var operation = ChangeListenerOperation.UNDEFINED\n\n            set.addChangeListener { newSet, changes ->\n                when (operation) {\n                    ChangeListenerOperation.INSERT -> {\n                        assertEquals(initializedSet.size, newSet.size)\n                        assertEquals(initializedSet.size, changes.numberOfInsertions)\n                    }\n                    ChangeListenerOperation.DELETE -> {\n                        assertTrue(newSet.isEmpty())\n                        assertEquals(initializedSet.size, changes.numberOfDeletions)\n                        looperThreadRealm.close()\n                        looperThread.testComplete()\n                    }\n                    else -> Unit\n                }\n            }\n\n            // Insert objects in set\n            looperThreadRealm.executeTransaction {\n                operation = ChangeListenerOperation.INSERT\n                set.addAll(initializedSet)\n            }\n\n            // Clear set\n            looperThreadRealm.executeTransaction {\n                operation = ChangeListenerOperation.DELETE\n                set.clear()\n            }\n        }\n    }\n\n    override fun removeRealmChangeListener() {\n        looperThread.runBlocking {\n            val looperThreadRealm = Realm.getInstance(config)\n\n            // Get set\n            val set = initAndAssertEmptySet(looperThreadRealm, \"id\")\n\n            val listener: (RealmSet<T>) -> Unit = { _ -> /* no-op */ }\n            set.addChangeListener(listener)\n\n            assertTrue(set.hasListeners())\n\n            set.removeChangeListener(listener)\n            assertFalse(set.hasListeners())\n        }\n    }\n\n    override fun removeSetChangeListener() {\n        looperThread.runBlocking {\n            val looperThreadRealm = Realm.getInstance(config)\n\n            // Get set\n            val set = initAndAssertEmptySet(looperThreadRealm, \"id\")\n\n            val listener: (RealmSet<T>, SetChangeSet) -> Unit = { _, _ -> /* no-op */ }\n            set.addChangeListener(listener)\n\n            assertTrue(set.hasListeners())\n\n            set.removeChangeListener(listener)\n            assertFalse(set.hasListeners())\n        }\n    }\n\n    override fun hasListeners() {\n        looperThread.runBlocking {\n            val looperThreadRealm = Realm.getInstance(config)\n\n            // Check for RealmChangeListener\n            val set = initAndAssertEmptySet(looperThreadRealm, \"id\")\n            assertFalse(set.hasListeners())\n\n            set.addChangeListener { _ -> /* no-op */ }\n\n            assertTrue(set.hasListeners())\n\n            // Check for SetChangeListener\n            val anotherSet = initAndAssertEmptySet(looperThreadRealm, \"anotherId\")\n            assertFalse(anotherSet.hasListeners())\n\n            anotherSet.addChangeListener { _ -> /* no-op */ }\n\n            assertTrue(anotherSet.hasListeners())\n\n            // Housekeeping and bye-bye\n            set.removeAllChangeListeners()\n            anotherSet.removeAllChangeListeners()\n            looperThreadRealm.close()\n            looperThread.testComplete()\n        }\n    }\n\n    override fun aggregations() {\n        val set = initAndAssertEmptySet(id = \"id\")\n\n        // Aggregation operations are not supported on primitive types.\n        assertFailsWith<UnsupportedOperationException> {\n            set.min(\"aFieldName\")\n        }\n\n        assertFailsWith<UnsupportedOperationException> {\n            set.max(\"aFieldName\")\n        }\n\n        assertFailsWith<UnsupportedOperationException> {\n            set.average(\"aFieldName\")\n        }\n\n        assertFailsWith<UnsupportedOperationException> {\n            set.sum(\"aFieldName\")\n        }\n\n        assertFailsWith<UnsupportedOperationException> {\n            set.minDate(\"aFieldName\")\n        }\n\n        assertFailsWith<UnsupportedOperationException> {\n            set.maxDate(\"aFieldName\")\n        }\n\n        // Delete all is supported and behaves as a clear\n        realm.executeTransaction {\n            set.addAll(initializedSet)\n            assertEquals(initializedSet.size, set.size)\n            set.deleteAllFromRealm()\n            assertTrue(set.isEmpty())\n        }\n    }\n\n    //----------------------------------\n    // Private stuff\n    //----------------------------------\n\n    private fun initAndAssertEmptySet(\n        realm: Realm = this.realm,\n        id: String? = null\n    ): RealmSet<T> {\n        val allTypesObject = createAllTypesManagedContainerAndAssert(realm, id)\n        assertNotNull(allTypesObject)\n        val set = setGetter.call(allTypesObject)\n        assertTrue(set.isEmpty())\n        return set\n    }\n}\n\nfun managedSetFactory(): List<SetTester> {\n    val primitiveTesters: List<SetTester> = SetSupportedType.values().mapNotNull { supportedType ->\n        when (supportedType) {\n            SetSupportedType.LONG ->\n                ManagedSetTester<Long>(\n                        testerName = \"Long\",\n                        setFieldClass = Long::class.javaObjectType,\n                        setFieldName = \"columnLongSet\",\n                        setGetter = SetAllTypes::getColumnLongSet,\n                        setSetter = SetAllTypes::setColumnLongSet,\n                        requiredSetGetter = SetAllTypes::getColumnRequiredLongSet,\n                        managedSetGetter = SetContainerClass::myLongSet,\n                        managedCollectionGetter = SetContainerClass::myLongList,\n                        initializedSet = listOf(VALUE_NUMERIC_HELLO.toLong(), VALUE_NUMERIC_BYE.toLong(), null),\n                        notPresentValue = VALUE_NUMERIC_NOT_PRESENT.toLong(),\n                        primaryKeyAllTypesSetProperty = SetAllTypesPrimaryKey::columnLongSet,\n                        toArrayManaged = ToArrayManaged.LongManaged()\n                )\n            SetSupportedType.INTEGER ->\n                ManagedSetTester<Int>(\n                        testerName = \"Integer\",\n                        setFieldClass = Int::class.javaObjectType,\n                        setFieldName = \"columnIntegerSet\",\n                        setGetter = SetAllTypes::getColumnIntegerSet,\n                        setSetter = SetAllTypes::setColumnIntegerSet,\n                        requiredSetGetter = SetAllTypes::getColumnRequiredIntegerSet,\n                        managedSetGetter = SetContainerClass::myIntSet,\n                        managedCollectionGetter = SetContainerClass::myIntList,\n                        initializedSet = listOf(VALUE_NUMERIC_HELLO, VALUE_NUMERIC_BYE, null),\n                        notPresentValue = VALUE_NUMERIC_NOT_PRESENT,\n                        primaryKeyAllTypesSetProperty = SetAllTypesPrimaryKey::columnIntegerSet,\n                        toArrayManaged = ToArrayManaged.IntManaged()\n                )\n            SetSupportedType.SHORT ->\n                ManagedSetTester<Short>(\n                        testerName = \"Short\",\n                        setFieldClass = Short::class.javaObjectType,\n                        setFieldName = \"columnShortSet\",\n                        setGetter = SetAllTypes::getColumnShortSet,\n                        setSetter = SetAllTypes::setColumnShortSet,\n                        requiredSetGetter = SetAllTypes::getColumnRequiredShortSet,\n                        managedSetGetter = SetContainerClass::myShortSet,\n                        managedCollectionGetter = SetContainerClass::myShortList,\n                        initializedSet = listOf(VALUE_NUMERIC_HELLO.toShort(), VALUE_NUMERIC_BYE.toShort(), null),\n                        notPresentValue = VALUE_NUMERIC_NOT_PRESENT.toShort(),\n                        primaryKeyAllTypesSetProperty = SetAllTypesPrimaryKey::columnShortSet,\n                        toArrayManaged = ToArrayManaged.ShortManaged()\n                )\n            SetSupportedType.BYTE ->\n                ManagedSetTester<Byte>(\n                        testerName = \"Byte\",\n                        setFieldClass = Byte::class.javaObjectType,\n                        setFieldName = \"columnByteSet\",\n                        setGetter = SetAllTypes::getColumnByteSet,\n                        setSetter = SetAllTypes::setColumnByteSet,\n                        requiredSetGetter = SetAllTypes::getColumnRequiredByteSet,\n                        managedSetGetter = SetContainerClass::myByteSet,\n                        managedCollectionGetter = SetContainerClass::myByteList,\n                        initializedSet = listOf(VALUE_NUMERIC_HELLO.toByte(), VALUE_NUMERIC_BYE.toByte(), null),\n                        notPresentValue = VALUE_NUMERIC_NOT_PRESENT.toByte(),\n                        primaryKeyAllTypesSetProperty = SetAllTypesPrimaryKey::columnByteSet,\n                        toArrayManaged = ToArrayManaged.ByteManaged()\n                )\n            SetSupportedType.FLOAT ->\n                ManagedSetTester<Float>(\n                        testerName = \"Float\",\n                        setFieldClass = Float::class.javaObjectType,\n                        setFieldName = \"columnFloatSet\",\n                        setGetter = SetAllTypes::getColumnFloatSet,\n                        setSetter = SetAllTypes::setColumnFloatSet,\n                        requiredSetGetter = SetAllTypes::getColumnRequiredFloatSet,\n                        managedSetGetter = SetContainerClass::myFloatSet,\n                        managedCollectionGetter = SetContainerClass::myFloatList,\n                        initializedSet = listOf(VALUE_NUMERIC_HELLO.toFloat(), VALUE_NUMERIC_BYE.toFloat(), null),\n                        notPresentValue = VALUE_NUMERIC_NOT_PRESENT.toFloat(),\n                        primaryKeyAllTypesSetProperty = SetAllTypesPrimaryKey::columnFloatSet,\n                        toArrayManaged = ToArrayManaged.FloatManaged()\n                )\n            SetSupportedType.DOUBLE ->\n                ManagedSetTester<Double>(\n                        testerName = \"Double\",\n                        setFieldClass = Double::class.javaObjectType,\n                        setFieldName = \"columnDoubleSet\",\n                        setGetter = SetAllTypes::getColumnDoubleSet,\n                        setSetter = SetAllTypes::setColumnDoubleSet,\n                        requiredSetGetter = SetAllTypes::getColumnRequiredDoubleSet,\n                        managedSetGetter = SetContainerClass::myDoubleSet,\n                        managedCollectionGetter = SetContainerClass::myDoubleList,\n                        initializedSet = listOf(VALUE_NUMERIC_HELLO.toDouble(), VALUE_NUMERIC_BYE.toDouble(), null),\n                        notPresentValue = VALUE_NUMERIC_NOT_PRESENT.toDouble(),\n                        primaryKeyAllTypesSetProperty = SetAllTypesPrimaryKey::columnDoubleSet,\n                        toArrayManaged = ToArrayManaged.DoubleManaged()\n                )\n            SetSupportedType.STRING ->\n                ManagedSetTester<String>(\n                        testerName = \"String\",\n                        setFieldClass = String::class.javaObjectType,\n                        setFieldName = \"columnStringSet\",\n                        setGetter = SetAllTypes::getColumnStringSet,\n                        setSetter = SetAllTypes::setColumnStringSet,\n                        requiredSetGetter = SetAllTypes::getColumnRequiredStringSet,\n                        managedSetGetter = SetContainerClass::myStringSet,\n                        managedCollectionGetter = SetContainerClass::myStringList,\n                        initializedSet = listOf(VALUE_STRING_HELLO, VALUE_STRING_BYE, null),\n                        notPresentValue = VALUE_STRING_NOT_PRESENT,\n                        primaryKeyAllTypesSetProperty = SetAllTypesPrimaryKey::columnStringSet,\n                        toArrayManaged = ToArrayManaged.StringManaged()\n                )\n            SetSupportedType.BOOLEAN ->\n                ManagedSetTester<Boolean>(\n                        testerName = \"Boolean\",\n                        setFieldClass = Boolean::class.javaObjectType,\n                        setFieldName = \"columnBooleanSet\",\n                        setGetter = SetAllTypes::getColumnBooleanSet,\n                        setSetter = SetAllTypes::setColumnBooleanSet,\n                        requiredSetGetter = SetAllTypes::getColumnRequiredBooleanSet,\n                        managedSetGetter = SetContainerClass::myBooleanSet,\n                        managedCollectionGetter = SetContainerClass::myBooleanList,\n                        initializedSet = listOf(VALUE_BOOLEAN_HELLO, null),\n                        notPresentValue = VALUE_BOOLEAN_NOT_PRESENT,\n                        primaryKeyAllTypesSetProperty = SetAllTypesPrimaryKey::columnBooleanSet,\n                        toArrayManaged = ToArrayManaged.BooleanManaged()\n                )\n            SetSupportedType.DATE ->\n                ManagedSetTester<Date>(\n                        testerName = \"Date\",\n                        setFieldClass = Date::class.javaObjectType,\n                        setFieldName = \"columnDateSet\",\n                        setGetter = SetAllTypes::getColumnDateSet,\n                        setSetter = SetAllTypes::setColumnDateSet,\n                        requiredSetGetter = SetAllTypes::getColumnRequiredDateSet,\n                        managedSetGetter = SetContainerClass::myDateSet,\n                        managedCollectionGetter = SetContainerClass::myDateList,\n                        initializedSet = listOf(VALUE_DATE_HELLO, VALUE_DATE_BYE, null),\n                        notPresentValue = VALUE_DATE_NOT_PRESENT,\n                        primaryKeyAllTypesSetProperty = SetAllTypesPrimaryKey::columnDateSet,\n                        toArrayManaged = ToArrayManaged.DateManaged()\n                )\n            SetSupportedType.DECIMAL128 ->\n                ManagedSetTester<Decimal128>(\n                        testerName = \"Decimal128\",\n                        setFieldClass = Decimal128::class.javaObjectType,\n                        setFieldName = \"columnDecimal128Set\",\n                        setGetter = SetAllTypes::getColumnDecimal128Set,\n                        setSetter = SetAllTypes::setColumnDecimal128Set,\n                        requiredSetGetter = SetAllTypes::getColumnRequiredDecimal128Set,\n                        managedSetGetter = SetContainerClass::myDecimal128Set,\n                        managedCollectionGetter = SetContainerClass::myDecimal128List,\n                        initializedSet = listOf(VALUE_DECIMAL128_HELLO, VALUE_DECIMAL128_BYE, null),\n                        notPresentValue = VALUE_DECIMAL128_NOT_PRESENT,\n                        primaryKeyAllTypesSetProperty = SetAllTypesPrimaryKey::columnDecimal128Set,\n                        toArrayManaged = ToArrayManaged.Decimal128Managed()\n                )\n            SetSupportedType.BINARY ->\n                ManagedSetTester<ByteArray>(\n                        testerName = \"Binary\",\n                        setFieldClass = ByteArray::class.javaObjectType,\n                        setFieldName = \"columnBinarySet\",\n                        setGetter = SetAllTypes::getColumnBinarySet,\n                        setSetter = SetAllTypes::setColumnBinarySet,\n                        requiredSetGetter = SetAllTypes::getColumnRequiredBinarySet,\n                        managedSetGetter = SetContainerClass::myBinarySet,\n                        managedCollectionGetter = SetContainerClass::myBinaryList,\n                        initializedSet = listOf(VALUE_BINARY_HELLO, VALUE_BINARY_BYE, null),\n                        notPresentValue = VALUE_BINARY_NOT_PRESENT,\n                        equalsTo = { expected, value ->\n                            Arrays.equals(expected, value)\n                        },\n                        primaryKeyAllTypesSetProperty = SetAllTypesPrimaryKey::columnBinarySet,\n                        toArrayManaged = ToArrayManaged.BinaryManaged()\n                )\n            SetSupportedType.OBJECT_ID ->\n                ManagedSetTester<ObjectId>(\n                        testerName = \"ObjectId\",\n                        setFieldClass = ObjectId::class.javaObjectType,\n                        setFieldName = \"columnObjectIdSet\",\n                        setGetter = SetAllTypes::getColumnObjectIdSet,\n                        setSetter = SetAllTypes::setColumnObjectIdSet,\n                        requiredSetGetter = SetAllTypes::getColumnRequiredObjectIdSet,\n                        managedSetGetter = SetContainerClass::myObjectIdSet,\n                        managedCollectionGetter = SetContainerClass::myObjectIdList,\n                        initializedSet = listOf(VALUE_OBJECT_ID_HELLO, VALUE_OBJECT_ID_BYE, null),\n                        notPresentValue = VALUE_OBJECT_ID_NOT_PRESENT,\n                        primaryKeyAllTypesSetProperty = SetAllTypesPrimaryKey::columnObjectIdSet,\n                        toArrayManaged = ToArrayManaged.ObjectIdManaged()\n                )\n\n            SetSupportedType.UUID ->\n                ManagedSetTester<UUID>(\n                        testerName = \"UUID\",\n                        setFieldClass = UUID::class.javaObjectType,\n                        setFieldName = \"columnUUIDSet\",\n                        setGetter = SetAllTypes::getColumnUUIDSet,\n                        setSetter = SetAllTypes::setColumnUUIDSet,\n                        requiredSetGetter = SetAllTypes::getColumnRequiredUUIDSet,\n                        managedSetGetter = SetContainerClass::myUUIDSet,\n                        managedCollectionGetter = SetContainerClass::myUUIDList,\n                        initializedSet = listOf(VALUE_UUID_HELLO, VALUE_UUID_BYE, null),\n                        notPresentValue = VALUE_UUID_NOT_PRESENT,\n                        primaryKeyAllTypesSetProperty = SetAllTypesPrimaryKey::columnUUIDSet,\n                        toArrayManaged = ToArrayManaged.UUIDManaged()\n                )\n\n            SetSupportedType.LINK ->\n                RealmModelManagedSetTester<DogPrimaryKey>(\n                        testerName = \"LINK\",\n                        setFieldClass = DogPrimaryKey::class.java,\n                        setFieldName = \"columnRealmModelSet\",\n                        setGetter = SetAllTypes::getColumnRealmModelSet,\n                        setSetter = SetAllTypes::setColumnRealmModelSet,\n                        managedSetGetter = SetContainerClass::myRealmModelSet,\n                        managedCollectionGetter = SetContainerClass::myRealmModelList,\n                        unmanagedInitializedSet = listOf(VALUE_LINK_HELLO, VALUE_LINK_BYE),\n                        unmanagedNotPresentValue = VALUE_LINK_NOT_PRESENT,\n                        primaryKeyAllTypesSetProperty = SetAllTypesPrimaryKey::columnRealmModelSet,\n                        toArrayManaged = ToArrayManaged.RealmModelManaged(),\n                        insertObjects = { realm, objects ->\n                            realm.copyToRealmOrUpdate(objects)\n                        },\n                        deleteObjects = { objects ->\n                            objects.forEach {\n                                it!!.deleteFromRealm()\n                            }\n                        },\n                        equalsTo = { expected: DogPrimaryKey?, value: DogPrimaryKey? ->\n                            (expected == null && value == null) || ((expected != null && value != null) && (expected.id == value.id))\n                        },\n                        nullable = false\n                )\n            // Ignore RealmAny in this switch\n            else -> null\n        }\n    }\n\n    // Add extra tests for RealmAny datatype and Realm Models without PK\n    return primitiveTesters\n            // We add an extra test for Realm models without a PK\n            .plus(NoPKRealmModelSetTester<Owner>(\n                    testerName = \"LINK_NO_PK\",\n                    setGetter = SetAllTypes::getColumnRealmModelNoPkSet,\n                    setSetter = SetAllTypes::setColumnRealmModelNoPkSet,\n                    managedSetGetter = SetContainerClass::myRealmModelNoPkSet,\n                    managedCollectionGetter = SetContainerClass::myRealmModelNoPkList,\n                    initializedSet = listOf(VALUE_LINK_NO_PK_HELLO, VALUE_LINK_NO_PK_BYE),\n                    notPresentValue = VALUE_LINK_NO_PK_NOT_PRESENT,\n                    toArrayManaged = ToArrayManaged.RealmModelNoPKManaged()\n            ))\n            // Then we add the tests for RealmAny types\n            .plus(RealmAny.Type.values().map { realmAnyType ->\n                when (realmAnyType) {\n                    RealmAny.Type.OBJECT -> RealmModelManagedSetTester<RealmAny>(\n                            testerName = \"MIXED-${realmAnyType.name}\",\n                            realmAnyType = realmAnyType,\n                            setFieldClass = RealmAny::class.java,\n                            setFieldName = \"columnRealmAnySet\",\n                            setGetter = SetAllTypes::getColumnRealmAnySet,\n                            setSetter = SetAllTypes::setColumnRealmAnySet,\n                            managedSetGetter = SetContainerClass::myRealmAnySet,\n                            managedCollectionGetter = SetContainerClass::myRealmAnyList,\n                            unmanagedInitializedSet = getRealmAnyKeyValuePairs(realmAnyType).map {\n                                it.second\n                            },\n                            unmanagedNotPresentValue = RealmAny.valueOf(VALUE_LINK_NOT_PRESENT),\n                            toArrayManaged = ToArrayManaged.RealmAnyManaged(),\n                            insertObjects = { realm, objects ->\n                                objects.map { realmAny ->\n                                    if (realmAny?.type == RealmAny.Type.OBJECT) {\n                                        val unmanagedObject = realmAny.asRealmModel(DogPrimaryKey::class.java)\n                                        val managedObject = realm.copyToRealmOrUpdate(unmanagedObject)\n                                        RealmAny.valueOf(managedObject)\n                                    } else {\n                                        realmAny\n                                    }\n                                }\n                            },\n                            deleteObjects = { objects: List<RealmAny?> ->\n                                objects.map { realmAny ->\n                                    if (realmAny?.type == RealmAny.Type.OBJECT) {\n                                        val managedObject = realmAny.asRealmModel(DogPrimaryKey::class.java)\n                                        managedObject.deleteFromRealm()\n                                    } else {\n                                        realmAny\n                                    }\n                                }\n                            },\n                            nullable = true,\n                            equalsTo = { expected, value ->\n                                if (expected == null && value == RealmAny.nullValue()) {\n                                    true\n                                } else if(expected != null && value != RealmAny.nullValue()) {\n                                    val expectedModel = expected.asRealmModel(DogPrimaryKey::class.java)\n                                    // Managed RealmAny values are cannot be null but RealmAny.nullValue()\n                                    val valueModel = value!!.asRealmModel(DogPrimaryKey::class.java)\n\n                                    expectedModel.id == valueModel.id\n                                } else {\n                                    false\n                                }\n                            },\n                            primaryKeyAllTypesSetProperty = SetAllTypesPrimaryKey::columnRealmAnySet\n                    )\n                    RealmAny.Type.NULL -> NullRealmAnySetTester(\n                            testerName = \"MIXED-${realmAnyType.name}\",\n                            setGetter = SetAllTypes::getColumnRealmAnySet\n                    )\n                    else -> ManagedSetTester<RealmAny>(\n                            testerName = \"MIXED-${realmAnyType.name}\",\n                            realmAnyType = realmAnyType,\n                            setFieldClass = RealmAny::class.java,\n                            setFieldName = \"columnRealmAnySet\",\n                            setGetter = SetAllTypes::getColumnRealmAnySet,\n                            setSetter = SetAllTypes::setColumnRealmAnySet,\n                            managedSetGetter = SetContainerClass::myRealmAnySet,\n                            managedCollectionGetter = SetContainerClass::myRealmAnyList,\n                            initializedSet = getRealmAnyKeyValuePairs(realmAnyType).map {\n                                it.second\n                            },\n                            notPresentValue = VALUE_MIXED_NOT_PRESENT,\n                            toArrayManaged = ToArrayManaged.RealmAnyManaged(),\n                            equalsTo = { expected, value ->\n                                (expected == null && value == RealmAny.nullValue()) || ((expected != null) && (expected == value))\n                            },\n                            primaryKeyAllTypesSetProperty = SetAllTypesPrimaryKey::columnRealmAnySet\n                    )\n                }\n            })\n}\n\n/**\n * TODO\n */\nabstract class ToArrayManaged<T> {\n\n    abstract fun assertToArrayWithParameter(realm: Realm, set: RealmSet<T>, values: List<T?>)\n\n    fun assertContains(array: Array<T>, set: RealmSet<T>) {\n        array.forEach { arrayValue ->\n            assertTrue(set.contains(arrayValue))\n        }\n    }\n\n    protected fun test(\n        realm: Realm,\n        set: RealmSet<T>,\n        values: List<T?>,\n        emptyArray: Array<T>,\n        fullArray: Array<T>\n    ) {\n        val emptyFromSet = set.toArray(emptyArray)\n        assertEquals(0, emptyFromSet.size)\n\n        realm.executeTransaction {\n            set.addAll(values as Collection<T>)\n        }\n        val fullFromSet = set.toArray(fullArray)\n        assertEquals(values.size, fullFromSet.size)\n    }\n\n    class LongManaged : ToArrayManaged<Long>() {\n        override fun assertToArrayWithParameter(realm: Realm, set: RealmSet<Long>, values: List<Long?>) =\n            test(realm, set, values, emptyArray(), arrayOf())\n    }\n\n    class IntManaged : ToArrayManaged<Int>() {\n        override fun assertToArrayWithParameter(realm: Realm, set: RealmSet<Int>, values: List<Int?>) =\n            test(realm, set, values, emptyArray(), arrayOf())\n    }\n\n    class ShortManaged : ToArrayManaged<Short>() {\n        override fun assertToArrayWithParameter(realm: Realm, set: RealmSet<Short>, values: List<Short?>) =\n            test(realm, set, values, emptyArray(), arrayOf())\n    }\n\n    class ByteManaged : ToArrayManaged<Byte>() {\n        override fun assertToArrayWithParameter(realm: Realm, set: RealmSet<Byte>, values: List<Byte?>) =\n            test(realm, set, values, emptyArray(), arrayOf())\n    }\n\n    class FloatManaged : ToArrayManaged<Float>() {\n        override fun assertToArrayWithParameter(realm: Realm, set: RealmSet<Float>, values: List<Float?>) =\n            test(realm, set, values, emptyArray(), arrayOf())\n    }\n\n    class DoubleManaged : ToArrayManaged<Double>() {\n        override fun assertToArrayWithParameter(realm: Realm, set: RealmSet<Double>, values: List<Double?>) =\n            test(realm, set, values, emptyArray(), arrayOf())\n    }\n\n    class StringManaged : ToArrayManaged<String>() {\n        override fun assertToArrayWithParameter(realm: Realm, set: RealmSet<String>, values: List<String?>) =\n            test(realm, set, values, emptyArray(), arrayOf())\n    }\n\n    class BooleanManaged : ToArrayManaged<Boolean>() {\n        override fun assertToArrayWithParameter(realm: Realm, set: RealmSet<Boolean>, values: List<Boolean?>) =\n            test(realm, set, values, emptyArray(), arrayOf())\n    }\n\n    class DateManaged : ToArrayManaged<Date>() {\n        override fun assertToArrayWithParameter(realm: Realm, set: RealmSet<Date>, values: List<Date?>) =\n            test(realm, set, values, emptyArray(), arrayOf())\n    }\n\n    class Decimal128Managed : ToArrayManaged<Decimal128>() {\n        override fun assertToArrayWithParameter(realm: Realm, set: RealmSet<Decimal128>, values: List<Decimal128?>) =\n            test(realm, set, values, emptyArray(), arrayOf())\n    }\n\n    class BinaryManaged : ToArrayManaged<ByteArray>() {\n        override fun assertToArrayWithParameter(realm: Realm, set: RealmSet<ByteArray>, values: List<ByteArray?>) =\n            test(realm, set, values, emptyArray(), arrayOf())\n    }\n\n    class ObjectIdManaged : ToArrayManaged<ObjectId>() {\n        override fun assertToArrayWithParameter(realm: Realm, set: RealmSet<ObjectId>, values: List<ObjectId?>) =\n            test(realm, set, values, emptyArray(), arrayOf())\n    }\n\n    class UUIDManaged : ToArrayManaged<UUID>() {\n        override fun assertToArrayWithParameter(realm: Realm, set: RealmSet<UUID>, values: List<UUID?>) =\n            test(realm, set, values, emptyArray(), arrayOf())\n    }\n\n    class RealmModelManaged : ToArrayManaged<DogPrimaryKey>() {\n        override fun assertToArrayWithParameter(\n            realm: Realm,\n            set: RealmSet<DogPrimaryKey>,\n            values: List<DogPrimaryKey?>\n        ) =\n            test(realm, set, values, emptyArray(), arrayOf())\n    }\n\n    class RealmModelNoPKManaged : ToArrayManaged<Owner>() {\n        override fun assertToArrayWithParameter(realm: Realm, set: RealmSet<Owner>, values: List<Owner?>) =\n            test(realm, set, values, emptyArray(), arrayOf())\n    }\n\n    class RealmAnyManaged : ToArrayManaged<RealmAny>() {\n        override fun assertToArrayWithParameter(realm: Realm, set: RealmSet<RealmAny>, values: List<RealmAny?>) =\n            test(realm, set, values, emptyArray(), arrayOf())\n    }\n}\n\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/kotlin/io/realm/ModelDefaultValuesTests.kt",
    "content": "/*\n * Copyright 2020 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 */\npackage io.realm\n\nimport androidx.test.ext.junit.runners.AndroidJUnit4\nimport androidx.test.platform.app.InstrumentationRegistry\nimport io.realm.annotations.PrimaryKey\nimport io.realm.kotlin.createObject\nimport io.realm.kotlin.where\nimport org.junit.After\nimport org.junit.Before\nimport org.junit.Rule\nimport org.junit.Test\nimport org.junit.rules.TemporaryFolder\nimport org.junit.runner.RunWith\nimport kotlin.test.assertEquals\n\nopen class ModelWithPk : RealmObject() {\n    @field:PrimaryKey\n    var id: Long = 0\n}\n\nopen class ModelWithoutPk : RealmObject() {\n    var id: Long = 0\n}\n\nopen class ContainerModel : RealmObject() {\n    var modelWithPk: ModelWithPk? = ModelWithPk()\n    var modelWithoutPk: ModelWithoutPk? = ModelWithoutPk()\n}\n\n@RunWith(AndroidJUnit4::class)\nclass ModelDefaultValuesTests {\n    private lateinit var realmConfiguration: RealmConfiguration\n    private lateinit var realm: Realm\n\n    @Rule\n    @JvmField\n    val folder = TemporaryFolder()\n\n    init {\n        Realm.init(InstrumentationRegistry.getInstrumentation().targetContext)\n    }\n\n    @Before\n    fun setUp() {\n        realmConfiguration = RealmConfiguration\n                .Builder(InstrumentationRegistry.getInstrumentation().targetContext)\n                .directory(folder.newFolder())\n                .schema(ModelWithPk::class.java,\n                        ModelWithoutPk::class.java,\n                        ContainerModel::class.java)\n                .build()\n        realm = Realm.getInstance(realmConfiguration)\n    }\n\n    @After\n    fun tearDown() {\n        realm.close()\n    }\n\n    @Test\n    fun defaults_withExistingObjects() {\n        realm.executeTransaction {\n            realm.createObject<ModelWithoutPk>()\n            realm.createObject<ModelWithPk>(0)\n        }\n\n        assertEquals(1, realm.where<ModelWithoutPk>().findAll().size)\n        assertEquals(1, realm.where<ModelWithPk>().findAll().size)\n\n        realm.executeTransaction {\n            realm.createObject<ContainerModel>()\n        }\n\n        assertEquals(2, realm.where<ModelWithoutPk>().findAll().size)\n        assertEquals(1, realm.where<ModelWithPk>().findAll().size)\n        assertEquals(1, realm.where<ContainerModel>().findAll().size)\n    }\n\n    @Test\n    fun defaults_withNewObjects() {\n        realm.executeTransaction {\n            realm.createObject<ContainerModel>()\n        }\n\n        assertEquals(1, realm.where<ModelWithoutPk>().findAll().size)\n        assertEquals(1, realm.where<ModelWithPk>().findAll().size)\n        assertEquals(1, realm.where<ContainerModel>().findAll().size)\n    }\n}"
  },
  {
    "path": "realm/realm-library/src/androidTest/kotlin/io/realm/NoPKRealmModelSetTester.kt",
    "content": "/*\n * Copyright 2021 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\npackage io.realm\n\nimport io.realm.entities.SetAllTypes\nimport io.realm.entities.SetContainerClass\nimport io.realm.rule.BlockingLooperThread\nimport java.util.*\nimport kotlin.reflect.KFunction1\nimport kotlin.reflect.KFunction2\nimport kotlin.reflect.KProperty1\nimport kotlin.test.*\n\n/**\n * Tester for realm models without PK. The motivation of these tests is to show that RealmSets distinguish between two\n * objects by their internal key, no matter if all fields match they will be treated as different objects. This conflicts\n * with the equalsTo implementation in Java.\n *\n * Also this would help to catch if there is any regression or change in the core implementation for Sets.\n */\nclass NoPKRealmModelSetTester<T : RealmModel>(\n        private val testerName: String,\n        private val setGetter: KFunction1<SetAllTypes, RealmSet<T>>,\n        private val setSetter: KFunction2<SetAllTypes, RealmSet<T>, Unit>,\n        private val managedSetGetter: KProperty1<SetContainerClass, RealmSet<T>>,\n        private val managedCollectionGetter: KProperty1<SetContainerClass, RealmList<T>>,\n        private val initializedSet: List<T?>,\n        private val notPresentValue: T,\n        private val toArrayManaged: ToArrayManaged<T>,\n        private val nullable: Boolean = false\n) : SetTester {\n\n    private lateinit var config: RealmConfiguration\n    private lateinit var looperThread: BlockingLooperThread\n    private lateinit var realm: Realm\n    private lateinit var managedInitializedSet: List<T?>\n    private lateinit var managedNotPresentValue: T\n\n    override fun toString(): String = \"NoPKRealmModelSetTester-${testerName}\"\n\n    override fun setUp(config: RealmConfiguration, looperThread: BlockingLooperThread) {\n        this.config = config\n        this.looperThread = looperThread\n        this.realm = Realm.getInstance(config)\n\n        this.realm.executeTransaction { transactionRealm ->\n            this.managedInitializedSet = transactionRealm.copyToRealm(initializedSet)\n            this.managedNotPresentValue = transactionRealm.copyToRealm(notPresentValue)\n        }\n\n    }\n\n    override fun tearDown() = realm.close()\n\n    override fun isManaged() = assertTrue(initAndAssertEmptySet(id = \"id\").isManaged)\n\n    override fun isValid() = assertTrue(initAndAssertEmptySet(id = \"id\").isValid)\n\n    override fun isFrozen() = Unit          // Tested in frozen\n\n    override fun size() {\n        val set = initAndAssertEmptySet(id = \"id\")\n\n        realm.executeTransaction {\n            initializedSet.forEach { value ->\n                set.add(value)\n            }\n        }\n        assertEquals(initializedSet.size, set.size)\n    }\n\n    override fun isEmpty() {\n        val set = initAndAssertEmptySet(id = \"id\")\n\n        realm.executeTransaction {\n            initializedSet.forEach { value ->\n                set.add(value)\n            }\n        }\n        assertFalse(set.isEmpty())\n    }\n\n    override fun requiredConstraints() = Unit // Not tested\n\n    override fun contains() {\n        val set = initAndAssertEmptySet(id = \"id\")\n\n        managedInitializedSet.forEach { value ->\n            assertFalse(set.contains(value))\n        }\n        realm.executeTransaction {\n            set.addAll(initializedSet)\n        }\n        // All objects without a PK are different\n        managedInitializedSet.forEach { value ->\n            assertFalse(set.contains(value))\n        }\n        assertFalse(set.contains(managedNotPresentValue))\n    }\n\n    override fun iterator() {\n        val set = initAndAssertEmptySet(id = \"id\")\n\n        assertNotNull(set.iterator())\n        realm.executeTransaction {\n            set.addAll(initializedSet)\n\n            // Objects without PK are different\n            managedInitializedSet.forEach { value ->\n                assertFalse(set.contains(value))\n            }\n        }\n    }\n\n    override fun insert() = Unit // Not tested\n\n    override fun insertList() = Unit // Not tested\n\n    override fun insertOrUpdate() = Unit // Not tested\n\n    override fun insertOrUpdateList() = Unit // Not tested\n\n    override fun copyToRealm() = Unit // Not tested\n\n    override fun copyToRealmOrUpdate() = Unit // Not tested\n\n    override fun toArray() {\n        val set = initAndAssertEmptySet(id = \"id\")\n\n        // Empty set\n        assertEquals(0, set.toArray().size)\n\n        // Set with some values\n        realm.executeTransaction {\n            // Empty set\n            assertEquals(0, set.toArray().size)\n\n            set.addAll(initializedSet)\n            val setToArray = set.toArray()\n            assertNotNull(setToArray)\n            assertEquals(initializedSet.size, setToArray.size)\n\n            val sameValuesUnmanagedSetToArray = RealmSet<T>().apply {\n                addAll(initializedSet)\n            }.toArray()\n\n            setToArray.contentEquals(sameValuesUnmanagedSetToArray)\n        }\n    }\n\n    override fun toArrayWithParameter() {\n        val set = initAndAssertEmptySet(id = \"id\")\n        toArrayManaged.assertToArrayWithParameter(realm, set, initializedSet)\n    }\n\n    override fun add() {\n        val set = initAndAssertEmptySet(id = \"id\")\n\n        realm.executeTransaction {\n            // Adding a value for the first time returns true\n            initializedSet.forEach { value ->\n                assertTrue(set.add(value))\n            }\n            // Adding an existing value returns false\n            initializedSet.forEach { value ->\n                assertTrue(set.add(value))\n            }\n\n            // Validate that for the Realm set all objects without PK are different\n            assertFalse(set.containsAll(managedInitializedSet))\n        }\n    }\n\n    override fun remove() {\n        val set = initAndAssertEmptySet(id = \"id\")\n\n        realm.executeTransaction {\n            set.addAll(initializedSet)\n\n            // Validate that all objects without pk are different\n            managedInitializedSet.forEach { value ->\n                assertFalse(set.remove(value))\n            }\n            assertEquals(initializedSet.size, set.size)\n\n            // Does not change if we remove something that is not there\n            assertFalse(set.remove(managedNotPresentValue))\n        }\n    }\n\n    override fun dynamic() = Unit // Not tested\n\n    override fun containsAll() {\n        val set = initAndAssertEmptySet(id = \"id\")\n\n        realm.executeTransaction { transactionRealm ->\n            set.addAll(initializedSet)\n\n            // Contains an unmanaged collection\n            assertFalse(set.containsAll(managedInitializedSet))\n\n            // Does not contain an unmanaged collection\n            assertFalse(set.containsAll(listOf(managedNotPresentValue)))\n\n            // Contains a managed set (itself)\n            assertTrue(set.containsAll(set))\n\n            // Contains an empty collection - every set contains the empty set\n            assertTrue(set.containsAll(listOf()))\n        }\n    }\n\n    override fun addAll() {\n        val set = initAndAssertEmptySet(id = \"id\")\n\n        realm.executeTransaction { _ ->\n            // Changes after adding collection\n            assertTrue(set.addAll(initializedSet))\n            assertEquals(initializedSet.size, set.size)\n\n            // Changes if we add the data again\n            assertTrue(set.addAll(initializedSet))\n            assertEquals(initializedSet.size * 2, set.size)\n\n            // Does not change if we add itself to it\n            assertFalse(set.addAll(set))\n            assertEquals(initializedSet.size * 2, set.size)\n\n            // Does not change if we add an empty collection\n            assertFalse(set.addAll(listOf()))\n            assertEquals(initializedSet.size * 2, set.size)\n        }\n    }\n\n    override fun retainAll() {\n        val set = initAndAssertEmptySet(id = \"id\")\n\n        realm.executeTransaction { transactionRealm ->\n            // Does not change after empty set intersects with another collection\n            assertFalse(set.retainAll(managedInitializedSet))\n            assertTrue(set.isEmpty())\n\n            // Does not change after empty set intersects with empty collection\n            assertFalse(set.retainAll(listOf()))\n            assertTrue(set.isEmpty())\n\n            // Does change after adding data and intersecting it with some values\n            set.addAll(initializedSet)\n            assertEquals(initializedSet.size, set.size)\n            assertTrue(set.retainAll(managedInitializedSet))\n            assertEquals(0, set.size)\n        }\n    }\n\n    override fun removeAll() {\n        val set = initAndAssertEmptySet(id = \"id\")\n\n        realm.executeTransaction { transactionRealm ->\n            // Does not change after removing a some values from an empty set\n            assertTrue(set.isEmpty())\n            assertFalse(set.removeAll(managedInitializedSet))\n            assertTrue(set.isEmpty())\n\n            // Does not change after adding values and then remove all\n            set.addAll(initializedSet)\n            assertEquals(initializedSet.size, set.size)\n            assertFalse(set.removeAll(managedInitializedSet))\n            assertTrue(!set.isEmpty())\n\n            // Does not change after removing empty collection\n            assertFalse(set.removeAll(listOf()))\n            assertEquals(initializedSet.size, set.size)\n        }\n    }\n\n    override fun clear() {\n        val set = initAndAssertEmptySet(id = \"id\")\n\n        realm.executeTransaction {\n            set.add(notPresentValue)\n            assertEquals(1, set.size)\n            set.clear()\n            assertEquals(0, set.size)\n        }\n    }\n\n    override fun freeze() {\n        val set = initAndAssertEmptySet(id = \"id\")\n\n        realm.executeTransaction {\n            set.addAll(initializedSet)\n        }\n\n        val frozenSet = set.freeze()\n        assertFalse(set.isFrozen)\n        assertTrue(frozenSet.isFrozen)\n        assertEquals(set.size, frozenSet.size)\n    }\n\n    override fun setters() = Unit // Not tested\n\n    override fun addRealmChangeListener() = Unit\n\n    override fun removeSetChangeListener() = Unit\n\n    override fun removeRealmChangeListener() = Unit\n\n    override fun addSetChangeListener() = Unit\n\n    override fun hasListeners() = Unit\n\n    override fun aggregations() = Unit\n\n    //----------------------------------\n    // Private stuff\n    //----------------------------------\n\n    private fun initAndAssertEmptySet(\n        realm: Realm = this.realm,\n        id: String? = null\n    ): RealmSet<T> {\n        val allTypesObject = createAllTypesManagedContainerAndAssert(realm, id)\n        assertNotNull(allTypesObject)\n        val set = setGetter.call(allTypesObject)\n        assertTrue(set.isEmpty())\n        return set\n    }\n}\n\n\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/kotlin/io/realm/NullMixedSetTester.kt",
    "content": "/*\n * Copyright 2021 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\npackage io.realm\n\nimport io.realm.entities.SetAllTypes\nimport io.realm.rule.BlockingLooperThread\nimport java.util.*\nimport kotlin.reflect.KFunction1\nimport kotlin.test.*\n\n/**\n * Tester for RealmAny containing null values. It evaluates that null is accepted as a value and that only a null instance\n * can exist in a RealmSet.\n */\nclass NullRealmAnySetTester(\n    private val testerName: String,\n    private val setGetter: KFunction1<SetAllTypes, RealmSet<RealmAny>>\n) : SetTester {\n    private lateinit var config: RealmConfiguration\n    private lateinit var looperThread: BlockingLooperThread\n    private lateinit var realm: Realm\n\n    override fun toString(): String = \"NullRealmAnySetTester-${testerName}\"\n\n    override fun setUp(config: RealmConfiguration, looperThread: BlockingLooperThread) {\n        this.config = config\n        this.looperThread = looperThread\n        this.realm = Realm.getInstance(config)\n    }\n\n    override fun tearDown() = realm.close()\n\n    override fun isManaged() = assertTrue(initAndAssertEmptySet(id = \"id\").isManaged)\n\n    override fun isValid() = assertTrue(initAndAssertEmptySet(id = \"id\").isValid)\n\n    override fun isFrozen() = Unit // Tested in frozen\n\n    override fun insert() = Unit // Not applicable\n\n    override fun insertList() = Unit // Not applicable\n\n    override fun insertOrUpdate() = Unit // Not applicable\n\n    override fun insertOrUpdateList() = Unit // Not applicable\n\n    override fun copyToRealm() = Unit // Not applicable\n\n    override fun copyToRealmOrUpdate() = Unit // Not applicable\n\n    override fun size() {\n        val set = initAndAssertEmptySet(id = \"id\")\n\n        realm.executeTransaction {\n            set.add(RealmAny.nullValue())\n            set.add(RealmAny.nullValue())\n        }\n\n        // Null values are all the same\n        assertEquals(1, set.size)\n    }\n\n    override fun isEmpty() {\n        val set = initAndAssertEmptySet(id = \"id\")\n\n        assertTrue(set.isEmpty())\n\n        realm.executeTransaction {\n            set.add(RealmAny.nullValue())\n        }\n\n        // Null value counts as an item\n        assertFalse(set.isEmpty())\n    }\n\n    override fun contains() {\n        val set = initAndAssertEmptySet(id = \"id\")\n\n        assertFalse(set.contains(RealmAny.nullValue()))\n        assertFalse(set.contains(RealmAny.nullValue()))\n    }\n\n    override fun requiredConstraints() = Unit // Not tested\n\n    override fun iterator() = Unit // Not tested\n\n    override fun toArray() = Unit // Not tested\n\n    override fun toArrayWithParameter() = Unit // Not tested\n\n    override fun add() {\n        val set = initAndAssertEmptySet(id = \"id\")\n\n        realm.executeTransaction {\n            assertTrue(set.add(RealmAny.nullValue()))\n            assertTrue(set.contains(RealmAny.nullValue()))\n\n            // Should no be possible to add the same value\n            assertFalse(set.add(RealmAny.nullValue()))\n        }\n    }\n\n    override fun remove() {\n        val set = initAndAssertEmptySet(id = \"id\")\n\n        realm.executeTransaction {\n            set.add(RealmAny.nullValue())\n            assertEquals(1, set.size)\n\n            // Does not change if we remove something that is not there\n            assertFalse(set.remove(RealmAny.valueOf(\"Hello world\")))\n            assertEquals(1, set.size)\n\n            // Changes if we remove something that is there\n            set.remove(RealmAny.nullValue())\n            assertEquals(0, set.size)\n        }\n    }\n\n    override fun containsAll() {\n        val set = initAndAssertEmptySet(id = \"id\")\n\n        realm.executeTransaction {\n            assertFalse(set.containsAll(listOf(RealmAny.nullValue(), RealmAny.nullValue())))\n\n            set.add(RealmAny.nullValue())\n\n            // Contains any null value\n            assertTrue(set.containsAll(listOf(RealmAny.nullValue(), RealmAny.nullValue())))\n\n            // Contains a managed set (itself)\n            assertTrue(set.containsAll(set))\n\n            // Contains an empty collection - every set contains the empty set\n            assertTrue(set.containsAll(listOf()))\n        }\n    }\n\n    override fun addAll() {\n        val set = initAndAssertEmptySet(id = \"id\")\n\n        realm.executeTransaction {\n            // Changes after adding collection\n            assertTrue(set.addAll(listOf(RealmAny.nullValue(), RealmAny.nullValue())))\n            assertEquals(1, set.size)\n\n            // Does not changes if we add the data again\n            assertFalse(set.addAll(listOf(RealmAny.nullValue(), RealmAny.nullValue())))\n            assertEquals(1, set.size)\n\n            // Does not change if we add itself to it\n            assertFalse(set.addAll(set))\n            assertEquals(1, set.size)\n\n            // Does not change if we add an empty collection\n            assertFalse(set.addAll(listOf()))\n            assertEquals(1, set.size)\n        }\n    }\n\n    override fun retainAll() {\n        val set = initAndAssertEmptySet(id = \"id\")\n\n        realm.executeTransaction {\n            // Does not change after empty set intersects with another collection\n            assertFalse(set.retainAll(listOf(RealmAny.nullValue(), RealmAny.nullValue())))\n            assertTrue(set.isEmpty())\n\n            // Does not change after empty set intersects with empty collection\n            assertFalse(set.retainAll(listOf()))\n            assertTrue(set.isEmpty())\n\n            // Does change after adding data and intersecting it with some values\n            set.addAll(listOf(RealmAny.nullValue(), RealmAny.nullValue()))\n            assertEquals(1, set.size)\n            assertTrue(set.retainAll(listOf(RealmAny.valueOf(\"Hello world\"))))\n            assertEquals(0, set.size)\n        }\n    }\n\n    override fun removeAll() {\n        val set = initAndAssertEmptySet(id = \"id\")\n\n        realm.executeTransaction {\n            // Does not change after removing a some values from an empty set\n            assertTrue(set.isEmpty())\n            assertFalse(set.removeAll(listOf(RealmAny.nullValue(), RealmAny.nullValue())))\n            assertTrue(set.isEmpty())\n\n            // Does change after adding values and then remove all\n            set.addAll(listOf(RealmAny.nullValue(), RealmAny.nullValue()))\n            assertEquals(1, set.size)\n            assertTrue(set.removeAll(listOf(RealmAny.nullValue(), RealmAny.nullValue())))\n            assertTrue(set.isEmpty())\n\n            // Does not change after removing empty collection\n            set.addAll(listOf(RealmAny.nullValue(), RealmAny.nullValue()))\n            assertFalse(set.removeAll(listOf()))\n            assertEquals(1, set.size)\n        }\n    }\n\n    override fun clear() {\n        val set = initAndAssertEmptySet(id = \"id\")\n\n        realm.executeTransaction {\n            set.add(RealmAny.nullValue())\n            assertEquals(1, set.size)\n            set.clear()\n            assertEquals(0, set.size)\n        }\n    }\n\n    override fun freeze() = Unit // Not tested\n\n    override fun setters() = Unit // Not tested\n\n    override fun dynamic() = Unit // Not tested\n\n    override fun addRealmChangeListener() = Unit\n\n    override fun removeSetChangeListener() = Unit\n\n    override fun removeRealmChangeListener() = Unit\n\n    override fun addSetChangeListener() = Unit\n\n    override fun hasListeners() = Unit\n\n    override fun aggregations() = Unit // Not tested\n\n    //----------------------------------\n    // Private stuff\n    //----------------------------------\n\n    private fun initAndAssertEmptySet(\n        realm: Realm = this.realm,\n        id: String? = null\n    ): RealmSet<RealmAny> {\n        val allTypesObject = createAllTypesManagedContainerAndAssert(realm, id)\n        assertNotNull(allTypesObject)\n        val set = setGetter.call(allTypesObject)\n        assertTrue(set.isEmpty())\n        return set\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/kotlin/io/realm/ObjectIdTests.kt",
    "content": "/*\n * Copyright 2020 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 */\npackage io.realm\n\nimport androidx.test.ext.junit.runners.AndroidJUnit4\nimport androidx.test.platform.app.InstrumentationRegistry\nimport io.realm.TestHelper.generateObjectIdHexString\nimport io.realm.annotations.PrimaryKey\nimport io.realm.annotations.Required\nimport io.realm.exceptions.RealmException\nimport io.realm.exceptions.RealmPrimaryKeyConstraintException\nimport io.realm.kotlin.createObject\nimport io.realm.kotlin.where\nimport org.bson.types.ObjectId\nimport org.junit.*\nimport org.junit.Assert.*\nimport org.junit.runner.RunWith\nimport kotlin.test.assertFailsWith\n\nopen class ObjectIdPrimaryKeyRequired\n    : RealmObject() {\n    @PrimaryKey\n    @Required\n    var id: ObjectId? = null\n    var name: String = \"\"\n    var anotherId: ObjectId? = null\n}\n\nopen class ObjectIdPrimaryKeyNotRequired\n    : RealmObject() {\n    @PrimaryKey\n    var id: ObjectId? = null\n    var name: String = \"\"\n}\n\nopen class ObjectIdAndString\n    : RealmObject() {\n    var id: ObjectId? = null\n    var name: String = \"\"\n}\n\nopen class ObjectIdRequiredRealmList\n    : RealmObject() {\n    var id: Long = 0\n\n    @Required\n    var ids: RealmList<ObjectId> = RealmList()\n    var name: String = \"\"\n}\n\nopen class ObjectIdOptionalRealmList\n    : RealmObject() {\n    var id: Long = 0\n\n    var ids: RealmList<ObjectId> = RealmList()\n    var name: String = \"\"\n}\n\nopen class LinkedObjectId : RealmObject() {\n    var linkedObjectId: ObjectIdPrimaryKeyNotRequired? = null\n}\n\n@RunWith(AndroidJUnit4::class)\nclass ObjectIdTests {\n    private lateinit var realmConfiguration: RealmConfiguration\n    private lateinit var realm: Realm\n\n    @Rule\n    @JvmField\n    val configFactory = TestRealmConfigurationFactory()\n\n    init {\n        Realm.init(InstrumentationRegistry.getInstrumentation().targetContext)\n    }\n\n    @Before\n    fun setUp() {\n        realmConfiguration = configFactory\n                .createConfigurationBuilder()\n                .schema(ObjectIdPrimaryKeyRequired::class.java,\n                        ObjectIdPrimaryKeyNotRequired::class.java,\n                        ObjectIdAndString::class.java,\n                        ObjectIdRequiredRealmList::class.java,\n                        ObjectIdOptionalRealmList::class.java,\n                        LinkedObjectId::class.java)\n                .build()\n        realm = Realm.getInstance(realmConfiguration)\n    }\n\n    @After\n    fun tearDown() {\n        realm.close()\n    }\n\n    @Test\n    fun copyToRealm() {\n        val objectIdHex1 = generateObjectIdHexString(1)\n        val objectIdHex2 = generateObjectIdHexString(2)\n\n        val value = ObjectIdPrimaryKeyRequired()\n        value.id = ObjectId(objectIdHex1)\n        value.anotherId = ObjectId(objectIdHex2)\n        value.name = \"Foo\"\n\n        realm.beginTransaction()\n        val obj = realm.copyToRealm(value)\n        realm.commitTransaction()\n\n        assertEquals(ObjectId(objectIdHex1), obj.id)\n        assertEquals(ObjectId(objectIdHex2), obj.anotherId)\n        assertEquals(\"Foo\", obj.name)\n    }\n\n    @Test\n    fun copyFromRealm() {\n        val objectIdHex1 = generateObjectIdHexString(1)\n        val objectIdHex2 = generateObjectIdHexString(2)\n\n        realm.beginTransaction()\n        val value = realm.createObject<ObjectIdPrimaryKeyRequired>(ObjectId(objectIdHex1))\n        value.anotherId = ObjectId(objectIdHex2)\n        value.name = \"Foo\"\n        realm.commitTransaction()\n\n        val copy = realm.copyFromRealm(value)\n\n        assertEquals(ObjectId(objectIdHex1), copy.id)\n        assertEquals(ObjectId(objectIdHex2), copy.anotherId)\n        assertEquals(\"Foo\", copy.name)\n    }\n\n    @Test\n    fun copyToRealmOrUpdate() {\n        val objectIdHex1 = generateObjectIdHexString(1)\n        val objectIdHex2 = generateObjectIdHexString(2)\n        val objectIdHex3 = generateObjectIdHexString(3)\n\n        realm.executeTransaction { realm ->\n            val obj = realm.createObject<ObjectIdPrimaryKeyRequired>(ObjectId(objectIdHex1))\n            obj.anotherId = ObjectId(objectIdHex2)\n            obj.name = \"Foo\"\n        }\n\n        val value = ObjectIdPrimaryKeyRequired()\n        value.id = ObjectId(objectIdHex1)\n        value.anotherId = ObjectId(objectIdHex3)\n        value.name = \"Bar\"\n\n        realm.beginTransaction()\n        val obj = realm.copyToRealmOrUpdate(value)\n        realm.commitTransaction()\n\n        assertEquals(ObjectId(objectIdHex1), obj.id)\n        assertEquals(ObjectId(objectIdHex3), obj.anotherId)\n        assertEquals(\"Bar\", obj.name)\n    }\n\n    @Test\n    fun insert() {\n        val objectIdHex1 = generateObjectIdHexString(0)\n        val objectIdHex2 = generateObjectIdHexString(7)\n\n        realm.executeTransaction { realm ->\n            val value = ObjectIdPrimaryKeyRequired()\n            value.id = ObjectId(objectIdHex1)\n            value.name = \"Foo\"\n            value.anotherId = ObjectId(generateObjectIdHexString(7))\n\n            realm.insert(value)\n        }\n\n        val obj = realm.where<ObjectIdPrimaryKeyRequired>().findFirst()\n\n        assertNotNull(obj)\n        assertEquals(ObjectId(objectIdHex1), obj!!.id)\n        assertEquals(ObjectId(objectIdHex2), obj.anotherId)\n        assertEquals(\"Foo\", obj.name)\n    }\n\n    @Test\n    fun insertOrUpdate() {\n        val value = ObjectIdPrimaryKeyRequired()\n        val objectIdHex1 = generateObjectIdHexString(0)\n        val objectIdHex2 = generateObjectIdHexString(6)\n        val objectIdHex3 = generateObjectIdHexString(7)\n\n        realm.executeTransaction { realm ->\n            realm.createObject<ObjectIdPrimaryKeyRequired>(ObjectId(objectIdHex1))\n            value.name = \"Foo\"\n            value.anotherId = ObjectId(objectIdHex2)\n        }\n\n        realm.executeTransaction { realm ->\n            val value = ObjectIdPrimaryKeyRequired()\n            value.id = ObjectId(objectIdHex1)\n            value.name = \"Bar\"\n            value.anotherId = ObjectId(objectIdHex3)\n\n            realm.insertOrUpdate(value)\n        }\n\n        val all = realm.where<ObjectIdPrimaryKeyRequired>().findAll()\n\n        assertEquals(1, all.size)\n        assertEquals(ObjectId(objectIdHex1), all[0]!!.id)\n        assertEquals(ObjectId(objectIdHex3), all[0]!!.anotherId)\n        assertEquals(\"Bar\", all[0]!!.name)\n    }\n\n    @Test\n    fun frozen() {\n        realm.beginTransaction()\n        val hex = generateObjectIdHexString(7)\n        val obj = realm.createObject<ObjectIdPrimaryKeyRequired>(ObjectId(hex))\n        obj.name = \"foo\"\n        realm.commitTransaction()\n\n        val frozen = obj.freeze<ObjectIdPrimaryKeyRequired>()\n\n        assertEquals(ObjectId(hex), frozen.id)\n        assertEquals(\"foo\", frozen.name)\n    }\n\n    @Test\n    fun requiredPK() {\n        realm.beginTransaction()\n\n        assertFailsWith<RealmException> {\n            realm.createObject<ObjectIdPrimaryKeyRequired>()\n        }\n\n        val obj = realm.createObject<ObjectIdPrimaryKeyRequired>(ObjectId(generateObjectIdHexString(42)))\n        obj.name = \"foo\"\n\n        realm.commitTransaction()\n\n        val result = realm.where<ObjectIdPrimaryKeyRequired>().equalTo(\"id\", ObjectId(generateObjectIdHexString(42))).findFirst()\n\n        assertNotNull(result)\n        assertEquals(\"foo\", result?.name)\n    }\n\n    @Test\n    fun nullablePK() {\n        assertFailsWith<RealmException> {\n            realm.createObject<ObjectIdPrimaryKeyNotRequired>()\n        }\n\n        realm.beginTransaction()\n        val obj = realm.createObject<ObjectIdPrimaryKeyNotRequired>(null)\n        obj.name = \"foo\"\n        realm.commitTransaction()\n\n        val result = realm.where<ObjectIdPrimaryKeyNotRequired>().equalTo(\"id\", null as ObjectId?).findFirst()\n        assertNotNull(result)\n        assertEquals(\"foo\", result!!.name)\n    }\n\n\n    @Test\n    fun requiredRealmList() {\n        realm.beginTransaction()\n        val obj = realm.createObject<ObjectIdRequiredRealmList>()\n\n        assertFailsWith<IllegalArgumentException>(\"It should not be possible to add nullable elements to a required RealmList<ObjectId>\") {\n            obj.ids.add(null)\n        }\n    }\n\n    @Test\n    fun optionalRealmList() {\n        realm.beginTransaction()\n        val obj = realm.createObject<ObjectIdOptionalRealmList>()\n        obj.ids.add(null)\n        obj.ids.add(ObjectId(generateObjectIdHexString(0)))\n        realm.commitTransaction()\n\n        assertEquals(2, realm.where<ObjectIdOptionalRealmList>().findFirst()?.ids?.size)\n    }\n\n    @Test\n    fun linkQueryNotSupported() {\n        realm.beginTransaction()\n        val obj = realm.createObject<ObjectIdRequiredRealmList>()\n        realm.cancelTransaction()\n\n        assertFailsWith<UnsupportedOperationException> {\n            obj.ids.where().equalTo(\"ids\", ObjectId(generateObjectIdHexString(0))).findAll()\n        }\n    }\n\n    @Test\n    fun duplicatePK() {\n        realm.beginTransaction()\n        realm.createObject<ObjectIdPrimaryKeyRequired>(ObjectId(generateObjectIdHexString(0)))\n\n        assertFailsWith<RealmPrimaryKeyConstraintException>(\"It should throw for duplicate PK usage\") {\n            realm.createObject<ObjectIdPrimaryKeyRequired>(ObjectId(generateObjectIdHexString(0)))\n        }\n\n        realm.cancelTransaction()\n    }\n\n    @Test\n    fun sort() {\n        realm.beginTransaction()\n        realm.createObject<ObjectIdAndString>().id = ObjectId(generateObjectIdHexString(10))\n        realm.createObject<ObjectIdAndString>().id = ObjectId(generateObjectIdHexString(0))\n        realm.createObject<ObjectIdAndString>().id = ObjectId(generateObjectIdHexString(1))\n        realm.commitTransaction()\n\n        var all = realm.where<ObjectIdAndString>().sort(\"id\", Sort.ASCENDING).findAll()\n        assertEquals(3, all.size)\n        assertEquals(ObjectId(generateObjectIdHexString(0)), all[0]!!.id)\n        assertEquals(ObjectId(generateObjectIdHexString(1)), all[1]!!.id)\n        assertEquals(ObjectId(generateObjectIdHexString(10)), all[2]!!.id)\n\n        all = realm.where<ObjectIdAndString>().sort(\"id\", Sort.DESCENDING).findAll()\n        assertEquals(3, all.size)\n        assertEquals(ObjectId(generateObjectIdHexString(10)), all[0]!!.id)\n        assertEquals(ObjectId(generateObjectIdHexString(1)), all[1]!!.id)\n        assertEquals(ObjectId(generateObjectIdHexString(0)), all[2]!!.id)\n    }\n\n    @Test\n    fun distinct() {\n        realm.beginTransaction()\n        realm.createObject<ObjectIdAndString>().id = ObjectId(generateObjectIdHexString(1))\n        realm.createObject<ObjectIdAndString>().id = ObjectId(generateObjectIdHexString(1))\n        realm.createObject<ObjectIdAndString>().id = null\n        realm.createObject<ObjectIdAndString>().id = ObjectId(generateObjectIdHexString(0))\n        realm.createObject<ObjectIdAndString>().id = ObjectId(generateObjectIdHexString(0))\n        realm.createObject<ObjectIdAndString>().id = null\n        realm.createObject<ObjectIdAndString>().id = ObjectId(generateObjectIdHexString(10))\n        realm.createObject<ObjectIdAndString>().id = ObjectId(generateObjectIdHexString(10))\n        realm.createObject<ObjectIdAndString>().id = null\n        realm.commitTransaction()\n\n        val all = realm.where<ObjectIdAndString>().distinct(\"id\").sort(\"id\", Sort.ASCENDING).findAll()\n        assertEquals(4, all.size)\n\n        assertNull(all[0]!!.id)\n        assertEquals(ObjectId(generateObjectIdHexString(0)), all[1]!!.id)\n        assertEquals(ObjectId(generateObjectIdHexString(1)), all[2]!!.id)\n        assertEquals(ObjectId(generateObjectIdHexString(10)), all[3]!!.id)\n\n    }\n\n    @Test\n    fun queriesCount() {\n        realm.beginTransaction()\n        realm.createObject<ObjectIdAndString>().id = ObjectId(generateObjectIdHexString(1))\n        realm.createObject<ObjectIdAndString>().id = null\n        realm.createObject<ObjectIdAndString>().id = ObjectId(generateObjectIdHexString(10))\n        realm.createObject<ObjectIdAndString>().id = ObjectId(generateObjectIdHexString(0))\n        realm.commitTransaction()\n\n        assertEquals(4, realm.where<ObjectIdAndString>().count())\n    }\n\n    @Test\n\n    fun queriesNotEqualTo() {\n        realm.beginTransaction()\n        realm.createObject<ObjectIdAndString>().id = ObjectId(generateObjectIdHexString(1))\n        realm.createObject<ObjectIdAndString>().id = null\n        realm.createObject<ObjectIdAndString>().id = ObjectId(generateObjectIdHexString(10))\n        realm.createObject<ObjectIdAndString>().id = ObjectId(generateObjectIdHexString(0))\n        realm.commitTransaction()\n\n        val all = realm.where<ObjectIdAndString>()\n                .notEqualTo(\"id\", ObjectId(generateObjectIdHexString(1)))\n                .sort(\"id\", Sort.ASCENDING)\n                .findAll()\n\n        assertEquals(3, all.size)\n        assertNull(all[0]!!.id)\n        assertEquals(ObjectId(generateObjectIdHexString(0)), all[1]!!.id)\n        assertEquals(ObjectId(generateObjectIdHexString(10)), all[2]!!.id)\n    }\n\n    @Test\n    fun queriesGreaterThanOrEqualTo() {\n        realm.beginTransaction()\n        realm.createObject<ObjectIdAndString>().id = ObjectId(generateObjectIdHexString(1))\n        realm.createObject<ObjectIdAndString>().id = null\n        realm.createObject<ObjectIdAndString>().id = ObjectId(generateObjectIdHexString(10))\n        realm.createObject<ObjectIdAndString>().id = ObjectId(generateObjectIdHexString(0))\n        realm.commitTransaction()\n\n        val all = realm.where<ObjectIdAndString>()\n                .greaterThanOrEqualTo(\"id\", ObjectId(generateObjectIdHexString(1)))\n                .sort(\"id\", Sort.ASCENDING)\n                .findAll()\n\n        assertEquals(2, all.size)\n        assertEquals(ObjectId(generateObjectIdHexString(1)), all[0]!!.id)\n        assertEquals(ObjectId(generateObjectIdHexString(10)), all[1]!!.id)\n    }\n\n    @Test\n    fun queriesGreaterThan() {\n        realm.beginTransaction()\n        realm.createObject<ObjectIdAndString>().id = ObjectId(generateObjectIdHexString(1))\n        realm.createObject<ObjectIdAndString>().id = null\n        realm.createObject<ObjectIdAndString>().id = ObjectId(generateObjectIdHexString(10))\n        realm.createObject<ObjectIdAndString>().id = ObjectId(generateObjectIdHexString(0))\n        realm.commitTransaction()\n\n        val all = realm.where<ObjectIdAndString>()\n                .greaterThan(\"id\", ObjectId(generateObjectIdHexString(1)))\n                .sort(\"id\", Sort.ASCENDING)\n                .findAll()\n\n        assertEquals(1, all.size)\n        assertEquals(ObjectId(generateObjectIdHexString(10)), all[0]!!.id)\n    }\n\n    @Test\n    fun queriesLessThanOrEqualTo() {\n        realm.beginTransaction()\n        realm.createObject<ObjectIdAndString>().id = ObjectId(generateObjectIdHexString(1))\n        realm.createObject<ObjectIdAndString>().id = null\n        realm.createObject<ObjectIdAndString>().id = ObjectId(generateObjectIdHexString(10))\n        realm.createObject<ObjectIdAndString>().id = ObjectId(generateObjectIdHexString(0))\n        realm.commitTransaction()\n\n        val all = realm.where<ObjectIdAndString>()\n                .lessThanOrEqualTo(\"id\", ObjectId(generateObjectIdHexString(1)))\n                .sort(\"id\", Sort.ASCENDING)\n                .findAll()\n\n        assertEquals(2, all.size)\n        assertEquals(ObjectId(generateObjectIdHexString(0)), all[0]!!.id)\n        assertEquals(ObjectId(generateObjectIdHexString(1)), all[1]!!.id)\n    }\n\n    @Test\n    fun queriesLessThan() {\n        realm.beginTransaction()\n        realm.createObject<ObjectIdAndString>().id = ObjectId(generateObjectIdHexString(1))\n        realm.createObject<ObjectIdAndString>().id = null\n        realm.createObject<ObjectIdAndString>().id = ObjectId(generateObjectIdHexString(10))\n        realm.createObject<ObjectIdAndString>().id = ObjectId(generateObjectIdHexString(0))\n        realm.commitTransaction()\n\n        val all = realm.where<ObjectIdAndString>()\n                .lessThan(\"id\", ObjectId(generateObjectIdHexString(1)))\n                .sort(\"id\", Sort.ASCENDING)\n                .findAll()\n\n        assertEquals(1, all.size)\n        assertEquals(ObjectId(generateObjectIdHexString(0)), all[0]!!.id)\n    }\n\n    @Test\n    fun queriesIsNull() {\n        realm.beginTransaction()\n        realm.createObject<ObjectIdAndString>().id = ObjectId(generateObjectIdHexString(1))\n        realm.createObject<ObjectIdAndString>().id = null\n        realm.createObject<ObjectIdAndString>().id = ObjectId(generateObjectIdHexString(10))\n        realm.createObject<ObjectIdAndString>().id = ObjectId(generateObjectIdHexString(0))\n        realm.commitTransaction()\n\n        val all = realm.where<ObjectIdAndString>()\n                .isNull(\"id\")\n                .findAll()\n\n        assertEquals(1, all.size)\n        assertNull(all[0]!!.id)\n    }\n\n    @Test\n    fun queriesIsNotNull() {\n        realm.beginTransaction()\n        realm.createObject<ObjectIdAndString>().id = ObjectId(generateObjectIdHexString(1))\n        realm.createObject<ObjectIdAndString>().id = null\n        realm.createObject<ObjectIdAndString>().id = ObjectId(generateObjectIdHexString(10))\n        realm.createObject<ObjectIdAndString>().id = ObjectId(generateObjectIdHexString(0))\n        realm.commitTransaction()\n\n        val all = realm.where<ObjectIdAndString>()\n                .isNotNull(\"id\")\n                .sort(\"id\", Sort.ASCENDING)\n                .findAll()\n\n        assertEquals(3, all.size)\n        assertEquals(ObjectId(generateObjectIdHexString(0)), all[0]!!.id)\n        assertEquals(ObjectId(generateObjectIdHexString(1)), all[1]!!.id)\n        assertEquals(ObjectId(generateObjectIdHexString(10)), all[2]!!.id)\n    }\n\n    @Test\n    fun queriesAverage() {\n        realm.beginTransaction()\n        realm.createObject<ObjectIdAndString>().id = ObjectId(generateObjectIdHexString(1))\n        realm.createObject<ObjectIdAndString>().id = null\n        realm.createObject<ObjectIdAndString>().id = ObjectId(generateObjectIdHexString(10))\n        realm.createObject<ObjectIdAndString>().id = ObjectId(generateObjectIdHexString(0))\n        realm.commitTransaction()\n\n        assertFailsWith<IllegalArgumentException>(\"Average is not supported for ObjectId\") {\n            realm.where<ObjectIdAndString>().average(\"id\")\n        }\n    }\n\n    @Test\n    fun queriesIsEmpty() {\n        realm.beginTransaction()\n        realm.createObject<ObjectIdAndString>().id = ObjectId(generateObjectIdHexString(1))\n        realm.createObject<ObjectIdAndString>().id = null\n        realm.createObject<ObjectIdAndString>().id = ObjectId(generateObjectIdHexString(10))\n        realm.createObject<ObjectIdAndString>().id = ObjectId(generateObjectIdHexString(0))\n        realm.commitTransaction()\n\n        assertFailsWith<IllegalArgumentException>(\"isEmpty is not supported for ObjectId\") {\n            realm.where<ObjectIdAndString>().isEmpty(\"id\").count()\n        }\n    }\n\n    @Test\n    fun linkedQuery() {\n        val objectIdArray = arrayOf(null, ObjectId(), ObjectId(), ObjectId())\n\n        realm.executeTransaction { realm ->\n            for (objectId in objectIdArray) {\n                val objectIdObj = realm.createObject<ObjectIdPrimaryKeyNotRequired>(objectId)\n                realm.createObject<LinkedObjectId>().linkedObjectId = objectIdObj\n            }\n        }\n\n        for (objectId in objectIdArray) {\n            val results = realm.where<LinkedObjectId>().equalTo(\"linkedObjectId.id\", objectId).findAll()\n            assertEquals(1, results.size)\n            assertEquals(objectId, results.first()?.linkedObjectId?.id)\n        }\n    }\n\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/kotlin/io/realm/ParameterizedDictionaryTests.kt",
    "content": "/*\n * Copyright 2020 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\npackage io.realm\n\nimport androidx.test.platform.app.InstrumentationRegistry\nimport io.realm.entities.DogPrimaryKey\nimport io.realm.entities.Owner\nimport io.realm.rule.BlockingLooperThread\nimport org.bson.types.Decimal128\nimport org.bson.types.ObjectId\nimport org.junit.After\nimport org.junit.Before\nimport org.junit.Rule\nimport org.junit.Test\nimport org.junit.runner.RunWith\nimport org.junit.runners.Parameterized\nimport java.util.*\n\n/**\n * [RealmDictionary] tests. It uses [Parameterized] tests for all possible combinations of\n * [RealmDictionary] types (i.e. all primitive Realm types (see [DictionarySupportedType]) plus\n * [RealmModel] and [RealmAny] (and in turn all possible types supported by RealmAny) in both `managed`\n * and `unmanaged` modes.\n *\n * In order to streamline the testing for managed dictionaries we use Kotlin's reflection API\n * `KFunction1` and `KFunction2`. These two methods provide access to the Java getters and setters\n * used to work with each dictionary field.\n */\n@RunWith(Parameterized::class)\nclass ParameterizedDictionaryTests(\n        private val tester: DictionaryTester\n) {\n\n    /**\n     * Initializer for parameterized tests.\n     */\n    companion object {\n\n        @JvmStatic\n        @Parameterized.Parameters(name = \"{0}\")\n        fun testTypes(): List<DictionaryTester> {\n            return DictionaryMode.values().map { type ->\n                when (type) {\n                    DictionaryMode.UNMANAGED -> unmanagedDictionaryFactory()\n                    DictionaryMode.MANAGED -> managedDictionaryFactory()\n                }\n            }.flatten()\n        }\n    }\n\n    @Rule\n    @JvmField\n    val configFactory = TestRealmConfigurationFactory()\n\n    private val looperThread = BlockingLooperThread()\n\n    @Before\n    fun setUp() {\n        Realm.init(InstrumentationRegistry.getInstrumentation().context)\n        tester.setUp(configFactory.createConfiguration(), looperThread)\n    }\n\n    @After\n    fun tearDown() {\n        tester.tearDown()\n    }\n\n    @Test\n    fun constructorWithAnotherMap() {\n        tester.constructorWithAnotherMap()\n    }\n\n    @Test\n    fun isManaged() {\n        tester.isManaged()\n    }\n\n    @Test\n    fun isValid() {\n        tester.isValid()\n    }\n\n    @Test\n    fun isFrozen() {\n        tester.isFrozen()\n    }\n\n    @Test\n    fun size() {\n        tester.size()\n    }\n\n    @Test\n    fun isEmpty() {\n        tester.isEmpty()\n    }\n\n    @Test\n    fun containsKey() {\n        tester.containsKey()\n    }\n\n    @Test\n    fun containsValue() {\n        tester.containsValue()\n    }\n\n    @Test\n    fun get() {\n        tester.get()\n    }\n\n    @Test\n    fun put() {\n        tester.put()\n    }\n\n    @Test\n    fun putRequired() {\n        tester.putRequired()\n    }\n\n    @Test\n    fun remove() {\n        tester.remove()\n    }\n\n    @Test\n    fun putAll() {\n        tester.putAll()\n    }\n\n    @Test\n    fun clear() {\n        tester.clear()\n    }\n\n    @Test\n    fun keySet() {\n        tester.keySet()\n    }\n\n    @Test\n    fun values() {\n        tester.values()\n    }\n\n    @Test\n    fun entrySet() {\n        tester.entrySet()\n    }\n\n    @Test\n    fun freeze() {\n        tester.freeze()\n    }\n\n    @Test\n    fun dynamic() {\n        tester.dynamic()\n    }\n\n    @Test\n    fun insert() {\n        tester.insert()\n    }\n\n    @Test\n    fun insertList() {\n        tester.insertList()\n    }\n\n    @Test\n    fun insertOrUpdate() {\n        tester.insertOrUpdate()\n    }\n\n    @Test\n    fun insertOrUpdatedList() {\n        tester.insertOrUpdateList()\n    }\n\n    @Test\n    fun copyToRealm() {\n        tester.copyToRealm()\n    }\n\n    @Test\n    fun copyToRealmOrUpdate() {\n        tester.copyToRealmOrUpdate()\n    }\n\n    @Test\n    fun copyFromRealm() {\n        tester.copyFromRealm()\n    }\n\n    @Test\n    fun fieldAccessors() {\n        tester.fieldAccessors(configFactory.createConfiguration(\"alternativeRealm\"))\n    }\n\n    @Test\n    fun addRealmChangeListener() {\n        tester.addRealmChangeListener()\n    }\n\n    @Test\n    fun addMapChangeListener() {\n        tester.addMapChangeListener()\n    }\n\n    @Test\n    fun hasListeners() {\n        tester.hasListeners()\n    }\n}\n\n/**\n * Modes for dictionaries.\n */\nenum class DictionaryMode {\n    UNMANAGED, MANAGED\n}\n\n/**\n * Supported types by dictionaries. Notice that RealmAny dictionaries can in turn support all these\n * types internally (except RealmAny itself).\n *\n * Add new types ad-hoc here.\n */\nenum class DictionarySupportedType {\n    LONG, INTEGER, SHORT, BYTE, FLOAT, DOUBLE, STRING, BOOLEAN, DATE, DECIMAL128, BINARY, OBJECT_ID,\n    UUID, LINK, MIXED\n}\n\n//-------------------------------------------\n// Test values\n//-------------------------------------------\n\ninternal const val KEY_HELLO = \"KeyHello\"\ninternal const val KEY_BYE = \"KeyBye\"\ninternal const val KEY_NULL = \"KeyNull\"\ninternal const val KEY_NOT_PRESENT = \"KeyNotPresent\"\n\ninternal const val KEY_HELLO_NON_LATIN = \"Keyこんにちは\"\ninternal const val KEY_BYE_NON_LATIN = \"Keyさようなら\"\ninternal const val KEY_NULL_NON_LATIN = \"Keyヌル\"\ninternal const val KEY_NOT_PRESENT_NON_LATIN = \"Key現在ではない\"\n\ninternal const val NEW_KEY = \"NEW KEY\"\ninternal const val NEW_KEY_NON_LATIN = \"NEW KEYさようなら\"\ninternal const val VALUE_BOOLEAN_HELLO = true\ninternal const val VALUE_BOOLEAN_BYE = false\ninternal const val VALUE_BOOLEAN_NOT_PRESENT = VALUE_BOOLEAN_BYE\n\ninternal const val VALUE_STRING_HELLO = \"HELLO\"\ninternal const val VALUE_STRING_BYE = \"BYE\"\ninternal const val VALUE_STRING_NOT_PRESENT = \"NOT PRESENT\"\n\ninternal const val VALUE_STRING_NON_LATIN_HELLO = \"こんにちは\"\ninternal const val VALUE_STRING_NON_LATIN_BYE = \"さようなら\"\ninternal const val VALUE_STRING_NON_LATIN_NOT_PRESENT = \"現在ではない\"\n\ninternal const val VALUE_NUMERIC_HELLO = 42\ninternal const val VALUE_NUMERIC_BYE = -42\ninternal const val VALUE_NUMERIC_NOT_PRESENT = 13\n\ninternal val VALUE_DATE_HELLO = Calendar.getInstance().apply {\n    set(Calendar.YEAR, 1969)\n    set(Calendar.MONTH, Calendar.JULY)\n    set(Calendar.DAY_OF_MONTH, 20)\n}.time\ninternal val VALUE_DATE_BYE = Calendar.getInstance().time\ninternal val VALUE_DATE_NOT_PRESENT = Calendar.getInstance().apply {\n    set(Calendar.YEAR, 2000)\n    set(Calendar.MONTH, Calendar.JANUARY)\n    set(Calendar.DAY_OF_MONTH, 1)\n}.time\n\ninternal val VALUE_DECIMAL128_HELLO = Decimal128(VALUE_NUMERIC_HELLO.toLong())\ninternal val VALUE_DECIMAL128_BYE = Decimal128(VALUE_NUMERIC_BYE.toLong())\ninternal val VALUE_DECIMAL128_NOT_PRESENT = Decimal128(VALUE_NUMERIC_NOT_PRESENT.toLong())\n\ninternal val VALUE_BOXED_BINARY_HELLO = Array<Byte>(2) { index ->\n    if (index == 0) Byte.MIN_VALUE\n    else if (index == 1) Byte.MAX_VALUE\n    else throw IllegalArgumentException(\"Incorrect array size\")\n}\ninternal val VALUE_BOXED_BINARY_BYE = Array<Byte>(2) { index ->\n    if (index == 0) Byte.MAX_VALUE\n    else if (index == 1) Byte.MIN_VALUE\n    else throw IllegalArgumentException(\"Incorrect array size\")\n}\ninternal val VALUE_BOXED_BINARY_NOT_PRESENT = Array<Byte>(2) { index ->\n    if (index == 0) VALUE_NUMERIC_NOT_PRESENT.toByte()\n    else if (index == 1) (VALUE_NUMERIC_NOT_PRESENT * -1).toByte()\n    else throw IllegalArgumentException(\"Incorrect array size\")\n}\n\ninternal val VALUE_BINARY_HELLO = ByteArray(2).apply {\n    set(0, Byte.MIN_VALUE)\n    set(1, Byte.MAX_VALUE)\n}\ninternal val VALUE_BINARY_BYE = ByteArray(2).apply {\n    set(0, Byte.MAX_VALUE)\n    set(1, Byte.MIN_VALUE)\n}\ninternal val VALUE_BINARY_NOT_PRESENT = ByteArray(2).apply {\n    set(0, VALUE_NUMERIC_NOT_PRESENT.toByte())\n    set(1, (VALUE_NUMERIC_NOT_PRESENT * -1).toByte())\n}\n\ninternal val VALUE_OBJECT_ID_HELLO = ObjectId(VALUE_DATE_HELLO)\ninternal val VALUE_OBJECT_ID_BYE = ObjectId(VALUE_DATE_BYE)\ninternal val VALUE_OBJECT_ID_NOT_PRESENT = ObjectId(VALUE_DATE_NOT_PRESENT)\n\ninternal val VALUE_UUID_HELLO = UUID.nameUUIDFromBytes(VALUE_BINARY_HELLO)\ninternal val VALUE_UUID_BYE = UUID.nameUUIDFromBytes(VALUE_BINARY_BYE)\ninternal val VALUE_UUID_NOT_PRESENT = UUID.nameUUIDFromBytes(VALUE_BINARY_NOT_PRESENT)\n\ninternal const val VALUE_AGE_HELLO = 10.toLong()\ninternal val VALUE_BIRTHDAY_HELLO = Date(0)\n\ninternal const val VALUE_AGE_BYE = 20.toLong()\ninternal val VALUE_BIRTHDAY_BYE = Date(10)\n\ninternal val VALUE_LINK_HELLO = DogPrimaryKey(42, VALUE_STRING_HELLO).apply {\n    age = VALUE_AGE_HELLO\n    birthday = VALUE_BIRTHDAY_HELLO\n}\ninternal val VALUE_LINK_BYE = DogPrimaryKey(43, VALUE_STRING_BYE).apply {\n    age = VALUE_AGE_BYE\n    birthday = VALUE_BIRTHDAY_BYE\n}\ninternal val VALUE_LINK_NOT_PRESENT = DogPrimaryKey(44, VALUE_STRING_NOT_PRESENT)\n\ninternal val VALUE_LINK_NO_PK_HELLO = Owner().apply { name = VALUE_STRING_HELLO }\ninternal val VALUE_LINK_NO_PK_BYE = Owner().apply { name = VALUE_STRING_BYE }\ninternal val VALUE_LINK_NO_PK_NOT_PRESENT = Owner().apply { name = VALUE_STRING_NOT_PRESENT }\n\ninternal val VALUE_MIXED_INTEGER_HELLO = RealmAny.valueOf(VALUE_NUMERIC_HELLO)\ninternal val VALUE_MIXED_INTEGER_BYE = RealmAny.valueOf(VALUE_NUMERIC_BYE)\ninternal val VALUE_MIXED_FLOAT_HELLO = RealmAny.valueOf(VALUE_NUMERIC_HELLO.toFloat())\ninternal val VALUE_MIXED_FLOAT_BYE = RealmAny.valueOf(VALUE_NUMERIC_BYE.toFloat())\ninternal val VALUE_MIXED_DOUBLE_HELLO = RealmAny.valueOf(VALUE_NUMERIC_HELLO.toDouble())\ninternal val VALUE_MIXED_DOUBLE_BYE = RealmAny.valueOf(VALUE_NUMERIC_BYE.toDouble())\ninternal val VALUE_MIXED_STRING_HELLO = RealmAny.valueOf(VALUE_STRING_HELLO)\ninternal val VALUE_MIXED_STRING_BYE = RealmAny.valueOf(VALUE_STRING_BYE)\ninternal val VALUE_MIXED_STRING_NON_LATIN_HELLO = RealmAny.valueOf(VALUE_STRING_NON_LATIN_HELLO)\ninternal val VALUE_MIXED_STRING_NON_LATIN_BYE = RealmAny.valueOf(VALUE_STRING_NON_LATIN_BYE)\ninternal val VALUE_MIXED_BOOLEAN_HELLO = RealmAny.valueOf(VALUE_BOOLEAN_HELLO)\ninternal val VALUE_MIXED_BOOLEAN_BYE = RealmAny.valueOf(VALUE_BOOLEAN_BYE)\ninternal val VALUE_MIXED_DATE_HELLO = RealmAny.valueOf(VALUE_DATE_HELLO)\ninternal val VALUE_MIXED_DATE_BYE = RealmAny.valueOf(VALUE_DATE_BYE)\ninternal val VALUE_MIXED_DECIMAL128_HELLO = RealmAny.valueOf(VALUE_DECIMAL128_HELLO)\ninternal val VALUE_MIXED_DECIMAL128_BYE = RealmAny.valueOf(VALUE_DECIMAL128_BYE)\ninternal val VALUE_MIXED_BINARY_HELLO = RealmAny.valueOf(VALUE_BINARY_HELLO)\ninternal val VALUE_MIXED_BINARY_BYE = RealmAny.valueOf(VALUE_BINARY_BYE)\ninternal val VALUE_MIXED_OBJECT_ID_HELLO = RealmAny.valueOf(VALUE_OBJECT_ID_HELLO)\ninternal val VALUE_MIXED_OBJECT_ID_BYE = RealmAny.valueOf(VALUE_OBJECT_ID_BYE)\ninternal val VALUE_MIXED_UUID_HELLO = RealmAny.valueOf(VALUE_UUID_HELLO)\ninternal val VALUE_MIXED_UUID_BYE = RealmAny.valueOf(VALUE_UUID_BYE)\ninternal val VALUE_MIXED_LINK_HELLO = RealmAny.valueOf(VALUE_LINK_HELLO)\ninternal val VALUE_MIXED_LINK_BYE = RealmAny.valueOf(VALUE_LINK_BYE)\ninternal val VALUE_MIXED_NOT_PRESENT = RealmAny.valueOf(VALUE_STRING_NOT_PRESENT)\n\nenum class DictionaryKey {\n    KEY_HELLO, KEY_BYE, KEY_NULL\n}\n\nfun getRealmAnyForType(realmAnyType: RealmAny.Type, dictionaryKey: DictionaryKey): RealmAny? {\n    return when (realmAnyType) {\n        RealmAny.Type.INTEGER -> when (dictionaryKey) {\n            DictionaryKey.KEY_HELLO -> VALUE_MIXED_INTEGER_HELLO\n            DictionaryKey.KEY_BYE -> VALUE_MIXED_INTEGER_BYE\n            DictionaryKey.KEY_NULL -> null\n        }\n        RealmAny.Type.BOOLEAN -> when (dictionaryKey) {\n            DictionaryKey.KEY_HELLO -> VALUE_MIXED_BOOLEAN_HELLO\n            DictionaryKey.KEY_BYE -> VALUE_MIXED_BOOLEAN_BYE\n            DictionaryKey.KEY_NULL -> null\n        }\n        RealmAny.Type.STRING -> when (dictionaryKey) {\n            DictionaryKey.KEY_HELLO -> VALUE_MIXED_STRING_HELLO\n            DictionaryKey.KEY_BYE -> VALUE_MIXED_STRING_BYE\n            DictionaryKey.KEY_NULL -> null\n        }\n        RealmAny.Type.BINARY -> when (dictionaryKey) {\n            DictionaryKey.KEY_HELLO -> VALUE_MIXED_BINARY_HELLO\n            DictionaryKey.KEY_BYE -> VALUE_MIXED_BINARY_BYE\n            DictionaryKey.KEY_NULL -> null\n        }\n        RealmAny.Type.DATE -> when (dictionaryKey) {\n            DictionaryKey.KEY_HELLO -> VALUE_MIXED_DATE_HELLO\n            DictionaryKey.KEY_BYE -> VALUE_MIXED_DATE_BYE\n            DictionaryKey.KEY_NULL -> null\n        }\n        RealmAny.Type.FLOAT -> when (dictionaryKey) {\n            DictionaryKey.KEY_HELLO -> VALUE_MIXED_FLOAT_HELLO\n            DictionaryKey.KEY_BYE -> VALUE_MIXED_FLOAT_BYE\n            DictionaryKey.KEY_NULL -> null\n        }\n        RealmAny.Type.DOUBLE -> when (dictionaryKey) {\n            DictionaryKey.KEY_HELLO -> VALUE_MIXED_DOUBLE_HELLO\n            DictionaryKey.KEY_BYE -> VALUE_MIXED_DOUBLE_BYE\n            DictionaryKey.KEY_NULL -> null\n        }\n        RealmAny.Type.DECIMAL128 -> when (dictionaryKey) {\n            DictionaryKey.KEY_HELLO -> VALUE_MIXED_DECIMAL128_HELLO\n            DictionaryKey.KEY_BYE -> VALUE_MIXED_DECIMAL128_BYE\n            DictionaryKey.KEY_NULL -> null\n        }\n        RealmAny.Type.OBJECT_ID -> when (dictionaryKey) {\n            DictionaryKey.KEY_HELLO -> VALUE_MIXED_OBJECT_ID_HELLO\n            DictionaryKey.KEY_BYE -> VALUE_MIXED_OBJECT_ID_BYE\n            DictionaryKey.KEY_NULL -> null\n        }\n        RealmAny.Type.OBJECT -> when (dictionaryKey) {\n            DictionaryKey.KEY_HELLO -> VALUE_MIXED_LINK_HELLO\n            DictionaryKey.KEY_BYE -> VALUE_MIXED_LINK_BYE\n            DictionaryKey.KEY_NULL -> null\n        }\n        RealmAny.Type.UUID -> when (dictionaryKey) {\n            DictionaryKey.KEY_HELLO -> VALUE_MIXED_UUID_HELLO\n            DictionaryKey.KEY_BYE -> VALUE_MIXED_UUID_BYE\n            DictionaryKey.KEY_NULL -> null\n        }\n        RealmAny.Type.NULL -> when (dictionaryKey) {\n            DictionaryKey.KEY_HELLO -> RealmAny.valueOf(\"Not null\")\n            DictionaryKey.KEY_BYE -> RealmAny.nullValue()\n            DictionaryKey.KEY_NULL -> null\n        }\n    }\n}\n\nfun getRealmAnyKeyValuePairs(\n        realmAnyType: RealmAny.Type,\n        shouldSwapValues: Boolean = false\n): List<Pair<String, RealmAny?>> {\n    return when (realmAnyType) {\n        RealmAny.Type.INTEGER ->\n            if (shouldSwapValues) {\n                listOf(KEY_HELLO to VALUE_MIXED_INTEGER_BYE, KEY_BYE to VALUE_MIXED_INTEGER_HELLO, KEY_NULL to null)\n            } else {\n                listOf(KEY_HELLO to VALUE_MIXED_INTEGER_HELLO, KEY_BYE to VALUE_MIXED_INTEGER_BYE, KEY_NULL to null)\n            }\n        RealmAny.Type.BOOLEAN ->\n            if (shouldSwapValues) {\n                listOf(KEY_HELLO to null, KEY_NULL to VALUE_MIXED_BOOLEAN_HELLO)\n            } else {\n                listOf(KEY_HELLO to VALUE_MIXED_BOOLEAN_HELLO, KEY_NULL to null)\n            }\n        RealmAny.Type.STRING ->\n            if (shouldSwapValues) {\n                listOf(KEY_HELLO to VALUE_MIXED_STRING_BYE, KEY_BYE to VALUE_MIXED_STRING_HELLO, KEY_NULL to null)\n            } else {\n                listOf(KEY_HELLO to VALUE_MIXED_STRING_HELLO, KEY_BYE to VALUE_MIXED_STRING_BYE, KEY_NULL to null)\n            }\n        RealmAny.Type.BINARY ->\n            if (shouldSwapValues) {\n                listOf(KEY_HELLO to VALUE_MIXED_BINARY_BYE, KEY_BYE to VALUE_MIXED_BINARY_HELLO, KEY_NULL to null)\n            } else {\n                listOf(KEY_HELLO to VALUE_MIXED_BINARY_HELLO, KEY_BYE to VALUE_MIXED_BINARY_BYE, KEY_NULL to null)\n            }\n        RealmAny.Type.DATE ->\n            if (shouldSwapValues) {\n                listOf(KEY_HELLO to VALUE_MIXED_DATE_BYE, KEY_BYE to VALUE_MIXED_DATE_HELLO, KEY_NULL to null)\n            } else {\n                listOf(KEY_HELLO to VALUE_MIXED_DATE_HELLO, KEY_BYE to VALUE_MIXED_DATE_BYE, KEY_NULL to null)\n            }\n        RealmAny.Type.FLOAT ->\n            if (shouldSwapValues) {\n                listOf(KEY_HELLO to VALUE_MIXED_FLOAT_BYE, KEY_BYE to VALUE_MIXED_FLOAT_HELLO, KEY_NULL to null)\n            } else {\n                listOf(KEY_HELLO to VALUE_MIXED_FLOAT_HELLO, KEY_BYE to VALUE_MIXED_FLOAT_BYE, KEY_NULL to null)\n            }\n        RealmAny.Type.DOUBLE ->\n            if (shouldSwapValues) {\n                listOf(KEY_HELLO to VALUE_MIXED_DOUBLE_BYE, KEY_BYE to VALUE_MIXED_DOUBLE_HELLO, KEY_NULL to null)\n            } else {\n                listOf(KEY_HELLO to VALUE_MIXED_DOUBLE_HELLO, KEY_BYE to VALUE_MIXED_DOUBLE_BYE, KEY_NULL to null)\n            }\n        RealmAny.Type.DECIMAL128 ->\n            if (shouldSwapValues) {\n                listOf(KEY_HELLO to VALUE_MIXED_DECIMAL128_BYE, KEY_BYE to VALUE_MIXED_DECIMAL128_HELLO, KEY_NULL to null)\n            } else {\n                listOf(KEY_HELLO to VALUE_MIXED_DECIMAL128_HELLO, KEY_BYE to VALUE_MIXED_DECIMAL128_BYE, KEY_NULL to null)\n            }\n        RealmAny.Type.OBJECT_ID ->\n            if (shouldSwapValues) {\n                listOf(KEY_HELLO to VALUE_MIXED_OBJECT_ID_BYE, KEY_BYE to VALUE_MIXED_OBJECT_ID_HELLO, KEY_NULL to null)\n            } else {\n                listOf(KEY_HELLO to VALUE_MIXED_OBJECT_ID_HELLO, KEY_BYE to VALUE_MIXED_OBJECT_ID_BYE, KEY_NULL to null)\n            }\n        RealmAny.Type.OBJECT ->\n            if (shouldSwapValues) {\n                listOf(KEY_HELLO to VALUE_MIXED_LINK_BYE, KEY_BYE to VALUE_MIXED_LINK_HELLO, KEY_NULL to null)\n            } else {\n                listOf(KEY_HELLO to VALUE_MIXED_LINK_HELLO, KEY_BYE to VALUE_MIXED_LINK_BYE, KEY_NULL to null)\n            }\n        RealmAny.Type.UUID ->\n            if (shouldSwapValues) {\n                listOf(KEY_HELLO to VALUE_MIXED_UUID_BYE, KEY_BYE to VALUE_MIXED_UUID_HELLO, KEY_NULL to null)\n            } else {\n                listOf(KEY_HELLO to VALUE_MIXED_UUID_HELLO, KEY_BYE to VALUE_MIXED_UUID_BYE, KEY_NULL to null)\n            }\n        RealmAny.Type.NULL ->\n            if (shouldSwapValues) {\n                listOf(KEY_HELLO to RealmAny.valueOf(\"Not null\"), KEY_BYE to RealmAny.nullValue(), KEY_NULL to null)\n            } else {\n                listOf(KEY_HELLO to RealmAny.nullValue(), KEY_BYE to RealmAny.valueOf(\"Not null\"), KEY_NULL to null)\n            }\n    }\n}\n\nfun <T : Any> RealmDictionary<T>.init(\n        keyValuePairs: List<Pair<String, T?>>\n): RealmDictionary<T> {\n    return this.apply {\n        for (keyValuePair in keyValuePairs) {\n            put(keyValuePair.first, keyValuePair.second)\n        }\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/kotlin/io/realm/ParameterizedSetTests.kt",
    "content": "package io.realm\n\nimport androidx.test.platform.app.InstrumentationRegistry\nimport io.realm.rule.BlockingLooperThread\nimport org.junit.After\nimport org.junit.Before\nimport org.junit.Rule\nimport org.junit.Test\nimport org.junit.runner.RunWith\nimport org.junit.runners.Parameterized\n\n/**\n * [RealmSet] tests. It uses [Parameterized] tests for all possible combinations of\n * [RealmSet] types (i.e. all primitive Realm types (see [SetSupportedType]) plus\n * [RealmModel] and [RealmAny] (and in turn all possible types supported by RealmAny) in both `managed`\n * and `unmanaged` modes.\n *\n * In order to streamline the testing for managed dictionaries we use Kotlin's reflection API\n * `KFunction1` and `KFunction2`. These two methods provide access to the Java getters and setters\n * used to work with each dictionary field.\n */\n@RunWith(Parameterized::class)\nclass ParameterizedSetTests(\n        private val tester: SetTester\n) {\n\n    /**\n     * Initializer for parameterized tests\n     */\n    companion object {\n\n        @JvmStatic\n        @Parameterized.Parameters(name = \"{0}\")\n        fun testType(): List<SetTester> {\n            return SetMode.values().map { type ->\n                when (type) {\n                    SetMode.UNMANAGED -> unmanagedSetFactory()\n                    SetMode.MANAGED -> managedSetFactory()\n                }\n            }.flatten()\n        }\n    }\n\n    @Rule\n    @JvmField\n    val configFactory = TestRealmConfigurationFactory()\n\n    private val looperThread = BlockingLooperThread()\n\n    @Before\n    fun setUp() {\n        Realm.init(InstrumentationRegistry.getInstrumentation().context)\n        tester.setUp(configFactory.createConfiguration(), looperThread)\n    }\n\n    @After\n    fun tearDown() {\n        tester.tearDown()\n    }\n\n    @Test\n    fun isManaged() {\n        tester.isManaged()\n    }\n\n    @Test\n    fun isValid() {\n        tester.isValid()\n    }\n\n    @Test\n    fun isFrozen() {\n        tester.isFrozen()\n    }\n\n    @Test\n    fun size() {\n        tester.size()\n    }\n\n    @Test\n    fun isEmpty() {\n        tester.isEmpty()\n    }\n\n    @Test\n    fun contains() {\n        tester.contains()\n    }\n\n    @Test\n    fun dynamic() {\n        tester.dynamic()\n    }\n\n    @Test\n    fun iterator() {\n        tester.iterator()\n    }\n\n    @Test\n    fun toArray() {\n        tester.toArray()\n    }\n\n    @Test\n    fun toArrayWithParameter() {\n        tester.toArrayWithParameter()\n    }\n\n    @Test\n    fun add() {\n        tester.add()\n    }\n\n    @Test\n    fun remove() {\n        tester.remove()\n    }\n\n    @Test\n    fun insert() {\n        tester.insert()\n    }\n\n    @Test\n    fun insertList() {\n        tester.insertList()\n    }\n\n    @Test\n    fun insertOrUpdate() {\n        tester.insertOrUpdate()\n    }\n\n    @Test\n    fun insertOrUpdateList() {\n        tester.insertOrUpdateList()\n    }\n\n    @Test\n    fun copyToRealm() {\n        tester.copyToRealm()\n    }\n\n    @Test\n    fun copyToRealmOrUpdate() {\n        tester.copyToRealmOrUpdate()\n    }\n\n    @Test\n    fun containsAll() {\n        tester.containsAll()\n    }\n\n    @Test\n    fun addAll() {\n        tester.addAll()\n    }\n\n    @Test\n    fun retainAll() {\n        tester.retainAll()\n    }\n\n    @Test\n    fun putRequired() {\n        tester.requiredConstraints()\n    }\n\n    @Test\n    fun removeAll() {\n        tester.removeAll()\n    }\n\n    @Test\n    fun clear() {\n        tester.clear()\n    }\n\n    @Test\n    fun freeze() {\n        tester.freeze()\n    }\n\n    @Test\n    fun setters() {\n        tester.setters()\n    }\n\n    @Test\n    fun addRealmChangeListener() {\n        tester.addRealmChangeListener()\n    }\n\n    @Test\n    fun addSetChangeListener() {\n        tester.addSetChangeListener()\n    }\n\n    @Test\n    fun hasListeners() {\n        tester.hasListeners()\n    }\n\n    @Test\n    fun aggregations(){\n        tester.aggregations()\n    }\n}\n\n/**\n * Modes for sets.\n */\nenum class SetMode {\n    UNMANAGED, MANAGED\n}\n\n/**\n * Supported types by sets. Notice that RealmAny sets can in turn support all these types internally\n * (except RealmAny itself).\n *\n * Add new types ad-hoc here.\n */\nenum class SetSupportedType {\n    LONG, INTEGER, SHORT, BYTE, FLOAT, DOUBLE, STRING, BOOLEAN, DATE, DECIMAL128, BINARY, OBJECT_ID,\n    UUID, LINK, MIXED\n}\n\n/**\n *\n */\ninterface SetTester : GenericTester {\n    override fun setUp(configFactory: TestRealmConfigurationFactory) = Unit     // Not needed here\n    fun isManaged()\n    fun isValid()\n    fun isFrozen()\n    fun size()\n    fun isEmpty()\n    fun contains()\n    fun iterator()\n    fun toArray()\n    fun toArrayWithParameter()\n    fun add()\n    fun remove()\n    fun containsAll()\n    fun dynamic()\n    fun insert()\n    fun insertList()\n    fun insertOrUpdate()\n    fun insertOrUpdateList()\n    fun copyToRealm()\n    fun copyToRealmOrUpdate()\n    fun addAll()\n    fun retainAll()\n    fun requiredConstraints()\n    fun removeAll()\n    fun clear()\n    fun freeze()\n    fun setters()\n    fun addSetChangeListener()\n    fun addRealmChangeListener()\n    fun removeSetChangeListener()\n    fun removeRealmChangeListener()\n    fun hasListeners()\n    fun aggregations()\n}\n\nfun <T : Any> RealmSet<T>.init(values: List<T?>): RealmSet<T> {\n    return this.apply {\n        for (value in values) {\n            this.add(value)\n        }\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/kotlin/io/realm/RealmAnyCollectionTests.kt",
    "content": "/*\n * Copyright 2021 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\npackage io.realm\n\nimport androidx.test.ext.junit.runners.AndroidJUnit4\nimport androidx.test.platform.app.InstrumentationRegistry\nimport io.realm.*\nimport io.realm.entities.*\nimport io.realm.internal.core.NativeRealmAnyCollection\nimport org.bson.types.Decimal128\nimport org.bson.types.ObjectId\nimport org.junit.After\nimport org.junit.Before\nimport org.junit.Rule\nimport org.junit.Test\nimport org.junit.runner.RunWith\nimport java.util.*\nimport kotlin.random.Random\nimport kotlin.test.assertEquals\nimport kotlin.test.assertTrue\n\n@RunWith(AndroidJUnit4::class)\nclass RealmAnyCollectionTests {\n    private lateinit var realmConfiguration: RealmConfiguration\n    private lateinit var realm: Realm\n\n    @get:Rule\n    val configFactory = TestRealmConfigurationFactory()\n\n    init {\n        Realm.init(InstrumentationRegistry.getInstrumentation().targetContext)\n    }\n\n    @Before\n    fun setUp() {\n        realmConfiguration = configFactory.createSchemaConfiguration(\n            false,\n            PrimaryKeyAsString::class.java,\n            WithRealmAnyTestEntity::class.java\n        )\n\n        realm = Realm.getInstance(realmConfiguration)\n    }\n\n    @After\n    fun tearDown() {\n        realm.close()\n    }\n\n    // Test for https://github.com/realm/realm-java/issues/7626. The issue was only happening\n    // on a 32 bit arm devices or with abiFilter 'armeabi-v7a', so need such or update abiFilter in\n    // build.gradle to verify it.\n    @Test\n    fun accessAnyElement() {\n        realm.executeTransaction {\n            realm.createObject(WithRealmAnyTestEntity::class.java, 1).apply {\n                items = RealmList<RealmAny>(RealmAny.valueOf(1L))\n            }\n        }\n        val results: RealmResults<WithRealmAnyTestEntity> = realm.where(WithRealmAnyTestEntity::class.java).findAll()\n        val entity = results[0]!!\n        val realmAny = entity.items[0]!!\n        assertEquals(RealmAny.Type.INTEGER, realmAny.type)\n        assertEquals(1, realmAny.asInteger())\n    }\n\n    @Test\n    fun validateBoolean() {\n        val collection = listOf(true, false, null, true)\n        val nativeRealmAnyCollection = NativeRealmAnyCollection.newBooleanCollection(collection)\n\n        assertEquals(collection.size, nativeRealmAnyCollection.size)\n        collection.forEachIndexed { index, expectedValue ->\n            val nativeRealmAny = nativeRealmAnyCollection.getItem(index)\n\n            if (expectedValue == null) {\n                assertEquals(RealmAny.Type.NULL, nativeRealmAny.type)\n            } else {\n                assertEquals(RealmAny.Type.BOOLEAN, nativeRealmAny.type)\n                assertEquals(expectedValue, nativeRealmAny.asBoolean())\n            }\n        }\n    }\n\n    @Test\n    fun validateByte() {\n        val collection = listOf(1.toByte(), 2.toByte(), null, 5.toByte())\n        val nativeRealmAnyCollection = NativeRealmAnyCollection.newIntegerCollection(collection)\n\n        assertEquals(collection.size, nativeRealmAnyCollection.size)\n        collection.forEachIndexed { index, expectedValue ->\n            val nativeRealmAny = nativeRealmAnyCollection.getItem(index)\n\n            if (expectedValue == null) {\n                assertEquals(RealmAny.Type.NULL, nativeRealmAny.type)\n            } else {\n                assertEquals(RealmAny.Type.INTEGER, nativeRealmAny.type)\n                assertEquals(expectedValue, nativeRealmAny.asLong().toByte())\n            }\n        }\n    }\n\n    @Test\n    fun validateShort() {\n        val collection = listOf(1.toShort(), 2.toShort(), null, 5.toShort())\n        val nativeRealmAnyCollection = NativeRealmAnyCollection.newIntegerCollection(collection)\n\n        assertEquals(collection.size, nativeRealmAnyCollection.size)\n        collection.forEachIndexed { index, expectedValue ->\n            val nativeRealmAny = nativeRealmAnyCollection.getItem(index)\n\n            if (expectedValue == null) {\n                assertEquals(RealmAny.Type.NULL, nativeRealmAny.type)\n            } else {\n                assertEquals(RealmAny.Type.INTEGER, nativeRealmAny.type)\n                assertEquals(expectedValue, nativeRealmAny.asLong().toShort())\n            }\n        }\n    }\n\n    @Test\n    fun validateInteger() {\n        val collection = listOf(2, 3, null, 5)\n        val nativeRealmAnyCollection = NativeRealmAnyCollection.newIntegerCollection(collection)\n\n        assertEquals(collection.size, nativeRealmAnyCollection.size)\n        collection.forEachIndexed { index, expectedValue ->\n            val nativeRealmAny = nativeRealmAnyCollection.getItem(index)\n\n            if (expectedValue == null) {\n                assertEquals(RealmAny.Type.NULL, nativeRealmAny.type)\n            } else {\n                assertEquals(RealmAny.Type.INTEGER, nativeRealmAny.type)\n                assertEquals(expectedValue, nativeRealmAny.asLong().toInt())\n            }\n        }\n    }\n\n    @Test\n    fun validateLong() {\n        val collection = listOf(2.toLong(), 3.toLong(), null, 5.toLong())\n        val nativeRealmAnyCollection = NativeRealmAnyCollection.newIntegerCollection(collection)\n\n        assertEquals(collection.size, nativeRealmAnyCollection.size)\n        collection.forEachIndexed { index, expectedValue ->\n            val nativeRealmAny = nativeRealmAnyCollection.getItem(index)\n\n            if (expectedValue == null) {\n                assertEquals(RealmAny.Type.NULL, nativeRealmAny.type)\n            } else {\n                assertEquals(RealmAny.Type.INTEGER, nativeRealmAny.type)\n                assertEquals(expectedValue, nativeRealmAny.asLong())\n            }\n        }\n    }\n\n    @Test\n    fun validateFloat() {\n        val collection = listOf(1.4.toFloat(), 2.1.toFloat(), null, 5.5.toFloat())\n        val nativeRealmAnyCollection = NativeRealmAnyCollection.newFloatCollection(collection)\n\n        assertEquals(collection.size, nativeRealmAnyCollection.size)\n        collection.forEachIndexed { index, expectedValue ->\n            val nativeRealmAny = nativeRealmAnyCollection.getItem(index)\n\n            if (expectedValue == null) {\n                assertEquals(RealmAny.Type.NULL, nativeRealmAny.type)\n            } else {\n                assertEquals(RealmAny.Type.FLOAT, nativeRealmAny.type)\n                assertEquals(expectedValue, nativeRealmAny.asFloat().toFloat())\n            }\n        }\n    }\n\n    @Test\n    fun validateDouble() {\n        val collection = listOf(1.4, 2.1, null, 5.5)\n        val nativeRealmAnyCollection = NativeRealmAnyCollection.newDoubleCollection(collection)\n\n        assertEquals(collection.size, nativeRealmAnyCollection.size)\n        collection.forEachIndexed { index, expectedValue ->\n            val nativeRealmAny = nativeRealmAnyCollection.getItem(index)\n\n            if (expectedValue == null) {\n                assertEquals(RealmAny.Type.NULL, nativeRealmAny.type)\n            } else {\n                assertEquals(RealmAny.Type.DOUBLE, nativeRealmAny.type)\n                assertEquals(expectedValue, nativeRealmAny.asDouble())\n            }\n        }\n    }\n\n    @Test\n    fun validateString() {\n        val collection = listOf(UUID.randomUUID().toString(), UUID.randomUUID().toString(), null, UUID.randomUUID().toString())\n        val nativeRealmAnyCollection = NativeRealmAnyCollection.newStringCollection(collection)\n\n        assertEquals(collection.size, nativeRealmAnyCollection.size)\n        collection.forEachIndexed { index, expectedValue ->\n            val nativeRealmAny = nativeRealmAnyCollection.getItem(index)\n\n            if (expectedValue == null) {\n                assertEquals(RealmAny.Type.NULL, nativeRealmAny.type)\n            } else {\n                assertEquals(RealmAny.Type.STRING, nativeRealmAny.type)\n                assertEquals(expectedValue, nativeRealmAny.asString())\n            }\n        }\n    }\n\n    @Test\n    fun validateBinary() {\n        val collection = listOf(\n                byteArrayOf(1, 1, 0),\n                byteArrayOf(0, 1, 0),\n                null,\n                byteArrayOf(0, 1, 1)\n        )\n        val nativeRealmAnyCollection = NativeRealmAnyCollection.newBinaryCollection(collection)\n\n        assertEquals(collection.size, nativeRealmAnyCollection.size)\n        collection.forEachIndexed { index, expectedValue ->\n            val nativeRealmAny = nativeRealmAnyCollection.getItem(index)\n\n            if (expectedValue == null) {\n                assertEquals(RealmAny.Type.NULL, nativeRealmAny.type)\n            } else {\n                assertEquals(RealmAny.Type.BINARY, nativeRealmAny.type)\n                assertTrue(Arrays.equals(expectedValue, nativeRealmAny.asBinary()))\n            }\n        }\n    }\n\n    @Test\n    fun validateDate() {\n        val collection = listOf(Date(1), Date(2), null, Date(5))\n        val nativeRealmAnyCollection = NativeRealmAnyCollection.newDateCollection(collection)\n\n        assertEquals(collection.size, nativeRealmAnyCollection.size)\n        collection.forEachIndexed { index, expectedValue ->\n            val nativeRealmAny = nativeRealmAnyCollection.getItem(index)\n\n            if (expectedValue == null) {\n                assertEquals(RealmAny.Type.NULL, nativeRealmAny.type)\n            } else {\n                assertEquals(RealmAny.Type.DATE, nativeRealmAny.type)\n                assertEquals(expectedValue, nativeRealmAny.asDate())\n            }\n        }\n    }\n\n    @Test\n    fun validateObjectId() {\n        val collection = listOf(ObjectId(Date(1)), ObjectId(Date(2)), null, ObjectId(Date(5)))\n        val nativeRealmAnyCollection = NativeRealmAnyCollection.newObjectIdCollection(collection)\n\n        assertEquals(collection.size, nativeRealmAnyCollection.size)\n        collection.forEachIndexed { index, expectedValue ->\n            val nativeRealmAny = nativeRealmAnyCollection.getItem(index)\n\n            if (expectedValue == null) {\n                assertEquals(RealmAny.Type.NULL, nativeRealmAny.type)\n            } else {\n                assertEquals(RealmAny.Type.OBJECT_ID, nativeRealmAny.type)\n                assertEquals(expectedValue, nativeRealmAny.asObjectId())\n            }\n        }\n    }\n\n    @Test\n    fun validateDecimal128() {\n        val collection = listOf(Decimal128(1), Decimal128(2), null, Decimal128(5))\n        val nativeRealmAnyCollection = NativeRealmAnyCollection.newDecimal128Collection(collection)\n\n        assertEquals(collection.size, nativeRealmAnyCollection.size)\n        collection.forEachIndexed { index, expectedValue ->\n            val nativeRealmAny = nativeRealmAnyCollection.getItem(index)\n\n            if (expectedValue == null) {\n                assertEquals(RealmAny.Type.NULL, nativeRealmAny.type)\n            } else {\n                assertEquals(RealmAny.Type.DECIMAL128, nativeRealmAny.type)\n                assertEquals(expectedValue, nativeRealmAny.asDecimal128())\n            }\n        }\n    }\n\n    @Test\n    fun validateUUID() {\n        val collection = listOf(UUID.randomUUID(), UUID.randomUUID(), null, UUID.randomUUID())\n        val nativeRealmAnyCollection = NativeRealmAnyCollection.newUUIDCollection(collection)\n\n        assertEquals(collection.size, nativeRealmAnyCollection.size)\n        collection.forEachIndexed { index, expectedValue ->\n            val nativeRealmAny = nativeRealmAnyCollection.getItem(index)\n\n            if (expectedValue == null) {\n                assertEquals(RealmAny.Type.NULL, nativeRealmAny.type)\n            } else {\n                assertEquals(RealmAny.Type.UUID, nativeRealmAny.type)\n                assertEquals(expectedValue, nativeRealmAny.asUUID())\n            }\n        }\n    }\n\n    @Test\n    fun validateEmpty() {\n        val collection = listOf<Double?>()\n        val nativeRealmAnyCollection = NativeRealmAnyCollection.newDoubleCollection(collection)\n        assertEquals(collection.size, nativeRealmAnyCollection.size)\n    }\n\n    @Test\n    fun validateRealmModel() {\n        val collection = mutableListOf<PrimaryKeyAsString?>()\n\n        realm.executeTransaction {\n            val managedObjects = it.copyToRealmOrUpdate(listOf(\n                    PrimaryKeyAsString(UUID.randomUUID().toString(), 0),\n                    PrimaryKeyAsString(UUID.randomUUID().toString(), 0),\n                    PrimaryKeyAsString(UUID.randomUUID().toString(), 0)\n            ))\n\n            collection.addAll(managedObjects)\n            collection.add(2, null)\n        }\n\n        val nativeRealmAnyCollection = NativeRealmAnyCollection.newRealmModelCollection(collection)\n\n        assertEquals(collection.size, nativeRealmAnyCollection.size)\n        collection.forEachIndexed { index, expectedValue ->\n            val nativeRealmAny = nativeRealmAnyCollection.getItem(index)\n\n            if (expectedValue == null) {\n                assertEquals(RealmAny.Type.NULL, nativeRealmAny.type)\n            } else {\n                val realmAny = RealmAny(RealmAnyOperator.fromNativeRealmAny(realm, nativeRealmAny))\n                assertEquals(RealmAny.Type.OBJECT, realmAny.type)\n                assertEquals(expectedValue.name, realmAny.asRealmModel(PrimaryKeyAsString::class.java).name)\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/kotlin/io/realm/RealmModelManagedSetTester.kt",
    "content": "/*\n * Copyright 2021 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\npackage io.realm\n\nimport io.realm.entities.*\nimport io.realm.kotlin.createObject\nimport io.realm.rule.BlockingLooperThread\nimport java.lang.IllegalArgumentException\nimport kotlin.reflect.KFunction1\nimport kotlin.reflect.KFunction2\nimport kotlin.reflect.KMutableProperty1\nimport kotlin.reflect.KProperty1\nimport kotlin.test.*\n\n/**\n * Generic tester for Realm models types of managed sets.\n *\n * It delegates the validation of managed realm models to the ManagedSetTester class, as it will validate all the paths,\n * whereas in this test we validate Realm models specific cases.\n */\nclass RealmModelManagedSetTester<T : Any>(\n    private val testerName: String,\n    private val setFieldName: String,\n    private val setFieldClass: Class<T>,\n    private val realmAnyType: RealmAny.Type? = null,\n    private val setGetter: KFunction1<SetAllTypes, RealmSet<T>>,\n    private val setSetter: KFunction2<SetAllTypes, RealmSet<T>, Unit>,\n    private val managedSetGetter: KProperty1<SetContainerClass, RealmSet<T>>,\n    private val managedCollectionGetter: KProperty1<SetContainerClass, RealmList<T>>,\n    private val unmanagedInitializedSet: List<T?>,\n    private val unmanagedNotPresentValue: T,\n    private val toArrayManaged: ToArrayManaged<T>,\n    private val insertObjects: (realm: Realm, objects: List<T?>) -> List<T?>,\n    private val deleteObjects: (objects: List<T?>) -> Unit,\n    private val nullable: Boolean,\n    private val equalsTo: (expected: T?, value: T?) -> Boolean,\n    private val primaryKeyAllTypesSetProperty: KMutableProperty1<SetAllTypesPrimaryKey, RealmSet<T>>\n) : SetTester {\n\n    private lateinit var managedTester: ManagedSetTester<T>\n    private lateinit var config: RealmConfiguration\n    private lateinit var looperThread: BlockingLooperThread\n    private lateinit var realm: Realm\n    private lateinit var managedInitializedSet: List<T?>\n    private lateinit var managedNotPresentValue: T\n\n    private fun initAndAssertEmptySet(realm: Realm = this.realm): RealmSet<T> {\n        val allTypesObject = createAllTypesManagedContainerAndAssert(realm, \"unmanaged\")\n        assertNotNull(allTypesObject)\n        val set = setGetter.call(allTypesObject)\n        assertTrue(set.isEmpty())\n        return set\n    }\n\n    override fun toString(): String = \"RealmModelManagedSet-${testerName}\"\n\n    override fun setUp(config: RealmConfiguration, looperThread: BlockingLooperThread) {\n        this.config = config\n        this.looperThread = looperThread\n        this.realm = Realm.getInstance(config)\n\n        realm.executeTransaction { transactionRealm ->\n            managedInitializedSet = insertObjects(transactionRealm, unmanagedInitializedSet)\n            managedNotPresentValue = insertObjects(transactionRealm, listOf<T?>(unmanagedNotPresentValue))[0]!!\n        }\n\n        this.managedTester = ManagedSetTester(\n            testerName = testerName,\n            setFieldClass = setFieldClass,\n            setFieldName = setFieldName,\n            realmAnyType = realmAnyType,\n            setGetter = setGetter,\n            setSetter = setSetter,\n            managedSetGetter = managedSetGetter,\n            managedCollectionGetter = managedCollectionGetter,\n            initializedSet = managedInitializedSet,\n            notPresentValue = managedNotPresentValue,\n            toArrayManaged = toArrayManaged,\n            nullable = nullable,\n            equalsTo = equalsTo,\n            primaryKeyAllTypesSetProperty = primaryKeyAllTypesSetProperty\n        )\n\n        this.managedTester.setUp(config, looperThread)\n    }\n\n    override fun tearDown() {\n        managedTester.tearDown()\n        this.realm.close()\n    }\n\n    override fun isManaged() = managedTester.isManaged()\n\n    override fun isValid() = managedTester.isValid()\n\n    override fun isFrozen() = managedTester.isFrozen()\n\n    override fun size() = managedTester.size()\n\n    override fun isEmpty() = managedTester.isEmpty()\n\n    override fun requiredConstraints() = Unit // Not tested\n\n    override fun contains() {\n        managedTester.contains()\n\n        // Test with unmanaged realm objects\n        val set = initAndAssertEmptySet()\n        realm.executeTransaction {\n            // Check throws exception when unmanaged values are passed\n            assertFailsWith<IllegalArgumentException>(\"Unmanaged objects not permitted\") {\n                set.contains(unmanagedNotPresentValue)\n            }\n\n            if (!nullable) {\n                assertFailsWith<java.lang.NullPointerException>(\"Set does not support null values\") {\n                    assertFalse(set.contains(null))\n                }\n            }\n        }\n\n        // Test with object from another realm\n        accessTransactionRealmInLooperThread { looperRealm ->\n            val value = insertObjects(looperRealm, listOf<T?>(unmanagedNotPresentValue))[0]\n\n            assertFailsWith<IllegalArgumentException>(\"Cannot pass values from another Realm\") {\n                set.contains(value)\n            }\n        }\n    }\n\n    override fun iterator() = managedTester.iterator()\n\n    override fun toArray() = managedTester.toArray()\n\n    override fun toArrayWithParameter() = managedTester.toArrayWithParameter()\n\n    override fun dynamic() {\n        if (realmAnyType != null) {\n            dynamicRealmAnyTest()\n        } else {\n            dynamicObjectTest()\n        }\n    }\n\n    private fun toDynamicRealmAny(realm: DynamicRealm, value: RealmAny): RealmAny {\n        val id = value.asRealmModel(DogPrimaryKey::class.java).id\n        return RealmAny.valueOf(realm.where(DogPrimaryKey.CLASS_NAME).equalTo(DogPrimaryKey.ID, id).findFirst()!!)\n    }\n\n    private fun dynamicRealmAnyTest() {\n        // Create a set from a immutable schema context\n        val set = initAndAssertEmptySet()\n        realm.executeTransaction {\n            set.addAll(unmanagedInitializedSet)\n        }\n\n        val dynamicRealm = DynamicRealm.getInstance(realm.configuration)\n        val dynamicObject: DynamicRealmObject = dynamicRealm.where(SetAllTypes.NAME)\n            .equalTo(AllTypes.FIELD_STRING, \"unmanaged\").findFirst()!!\n        val dynamicSet: RealmSet<RealmAny> = dynamicObject.getRealmSet(setFieldName, setFieldClass) as RealmSet<RealmAny>\n\n        // Access the previous set from a mutable context\n        assertEquals(3, dynamicSet.size)\n\n        // Update the set with a new value\n        dynamicRealm.executeTransaction {\n            dynamicSet.add(toDynamicRealmAny(dynamicRealm, unmanagedNotPresentValue as RealmAny))\n        }\n\n        assertEquals(4, dynamicSet.size)\n\n        // Try to replace the whole set by a new one\n        dynamicRealm.executeTransaction {\n            dynamicObject.setRealmSet(setFieldName, RealmSet<RealmAny>().apply {\n                add(toDynamicRealmAny(dynamicRealm, unmanagedNotPresentValue as RealmAny))\n            })\n        }\n\n        assertEquals(1, dynamicObject.getRealmSet(setFieldName, setFieldClass).size)\n\n        // Validate that set is properly represented as a String\n        managedTester.validateToString(dynamicObject, dynamicSet)\n\n        dynamicRealm.close()\n    }\n\n    private fun dynamicObjectTest() {\n        // Create a set from a immutable schema context\n        val set = initAndAssertEmptySet()\n        realm.executeTransaction {\n            set.addAll(unmanagedInitializedSet)\n        }\n\n        val dynamicRealm = DynamicRealm.getInstance(realm.configuration)\n        val dynamicObject: DynamicRealmObject =\n            dynamicRealm.where(SetAllTypes.NAME).equalTo(AllTypes.FIELD_STRING, \"unmanaged\").findFirst()!!\n        val dynamicSet = dynamicObject.getRealmSet(setFieldName)\n\n        // Access the previous set from a mutable context\n        set.forEach { value ->\n            if (RealmObject.isValid(value as DogPrimaryKey)) {\n                val managedObject =\n                    dynamicRealm.where(DogPrimaryKey.CLASS_NAME).equalTo(DogPrimaryKey.ID, (value as DogPrimaryKey).id)\n                        .findFirst()!!\n                assertTrue(dynamicSet.contains(managedObject))\n            }\n        }\n\n        // Update the set with a new value\n        dynamicRealm.executeTransaction {\n            val notPresentManaged = dynamicRealm.where(DogPrimaryKey.CLASS_NAME)\n                .equalTo(DogPrimaryKey.ID, (unmanagedNotPresentValue as DogPrimaryKey).id).findFirst()!!\n            dynamicSet.add(notPresentManaged)\n        }\n\n        set.plus(unmanagedNotPresentValue).forEach { value ->\n            if (RealmObject.isValid(value as DogPrimaryKey)) {\n                val managedObject =\n                    dynamicRealm.where(DogPrimaryKey.CLASS_NAME).equalTo(DogPrimaryKey.ID, (value as DogPrimaryKey).id)\n                        .findFirst()!!\n                assertTrue(dynamicSet.contains(managedObject))\n            }\n        }\n\n        // Try to replace the whole set by a new one\n        dynamicRealm.executeTransaction {\n            val notPresentManaged = dynamicRealm.where(DogPrimaryKey.CLASS_NAME)\n                .equalTo(DogPrimaryKey.ID, (unmanagedNotPresentValue as DogPrimaryKey).id).findFirst()!!\n            dynamicObject.setRealmSet(setFieldName, RealmSet<DynamicRealmObject>().apply {\n                add(notPresentManaged)\n            })\n        }\n\n        assertEquals(1, dynamicObject.get<RealmSet<T>>(setFieldName).size)\n\n        // Validate that set is properly represented as a String\n        managedTester.validateToString(dynamicObject, dynamicSet)\n\n        dynamicRealm.close()\n    }\n\n    override fun add() {\n        // Test with managed objects\n        managedTester.add()\n\n        // Test with unmanaged objects\n        val set = initAndAssertEmptySet()\n        realm.executeTransaction {\n            // Adding a value for the first time returns true\n            unmanagedInitializedSet.forEach { value ->\n                assertTrue(set.add(value))\n            }\n            // Adding an existing value returns false\n            unmanagedInitializedSet.forEach { value ->\n                assertFalse(set.add(value))\n            }\n        }\n\n        // Test with object from another realm\n        accessTransactionRealmInLooperThread { looperRealm ->\n            val value = insertObjects(looperRealm, listOf<T?>(unmanagedNotPresentValue))[0]\n\n            assertFailsWith<IllegalArgumentException>(\"Cannot pass values from another Realm\") {\n                set.add(value)\n            }\n        }\n\n        assertTrue(set.containsAll(managedInitializedSet))\n    }\n\n    override fun remove() {\n        managedTester.remove()\n\n        // Test with unmanaged realm objects\n        val set = initAndAssertEmptySet()\n        realm.executeTransaction {\n            // Check throws exception when unmanaged values are passed\n            assertFailsWith<IllegalArgumentException>(\"Unmanaged objects not permitted\") {\n                set.remove(unmanagedNotPresentValue)\n            }\n        }\n\n        // Test with object from another realm\n        accessTransactionRealmInLooperThread { looperRealm ->\n            val value = insertObjects(looperRealm, listOf<T?>(unmanagedNotPresentValue))[0]\n\n            assertFailsWith<IllegalArgumentException>(\"Cannot pass values from another Realm\") {\n                set.remove(value)\n            }\n        }\n    }\n\n    override fun insert() {\n        // This specific test case needs unmanaged objects on PK models\n        realm.executeTransaction {\n            deleteObjects(managedInitializedSet)\n        }\n\n        // Call with unmanaged objects\n        managedTester.doInsertTest(unmanagedInitializedSet)\n    }\n\n    override fun insertList() {\n        // This specific test case needs unmanaged objects on PK models\n        realm.executeTransaction {\n            deleteObjects(managedInitializedSet)\n        }\n\n        // Call with unmanaged objects\n        managedTester.doInsertListTest(unmanagedInitializedSet)\n    }\n\n    override fun insertOrUpdate() {\n        managedTester.insertOrUpdate()\n    }\n\n    override fun insertOrUpdateList() {\n        managedTester.insertOrUpdate()\n    }\n\n    override fun copyToRealm() {\n        // This specific test case needs unmanaged objects on PK models\n        realm.executeTransaction {\n            deleteObjects(managedInitializedSet)\n        }\n\n        // Call with unmanaged objects\n        managedTester.doCopyToRealmTest(unmanagedInitializedSet)\n    }\n\n    override fun copyToRealmOrUpdate() {\n        managedTester.copyToRealmOrUpdate()\n    }\n\n    override fun containsAll() {\n        // Test with managed realm objects\n        managedTester.containsAll()\n\n        // Test with unmanaged realm objects\n        val set = initAndAssertEmptySet()\n        realm.executeTransaction {\n            // Check throws exception when unmanaged values are passed\n            assertFailsWith<IllegalArgumentException>(\"Collection with unmanaged objects not permitted\") {\n                set.containsAll(unmanagedInitializedSet)\n            }\n\n            if (!nullable) {\n                // Checks it does not contain nulls\n                assertFailsWith<java.lang.NullPointerException>(\"Set does not support null values\") {\n                    assertFalse(set.containsAll(listOf(null)))\n                }\n            }\n        }\n\n        // Test with objects from another realm\n        accessTransactionRealmInLooperThread { looperRealm ->\n            val values = insertObjects(looperRealm, unmanagedInitializedSet)\n\n            assertFailsWith<IllegalArgumentException>(\"Cannot pass values from another Realm\") {\n                set.containsAll(values)\n            }\n        }\n    }\n\n    override fun addAll() {\n        // Test with managed objects\n        managedTester.addAll()\n\n        val set = initAndAssertEmptySet()\n        realm.executeTransaction { transactionRealm ->\n            // Changes after adding collection\n            if (!nullable) {\n                assertFailsWith<java.lang.NullPointerException>(\"Cannot add null values into this set\") {\n                    set.addAll(listOf(null))\n                }\n            }\n\n            assertTrue(set.addAll(unmanagedInitializedSet))\n            assertEquals(unmanagedInitializedSet.size, set.size)\n\n            // Does not change if we add the same data\n            assertFalse(set.addAll(unmanagedInitializedSet))\n            assertEquals(unmanagedInitializedSet.size, set.size)\n\n            // Does not change if we add itself to it\n            assertFalse(set.addAll(set))\n            assertEquals(unmanagedInitializedSet.size, set.size)\n\n            // Does not change if we add an empty collection\n            assertFalse(set.addAll(listOf()))\n            assertEquals(unmanagedInitializedSet.size, set.size)\n\n            // Throws when adding a collection of a different type\n            val somethingEntirelyDifferent = unmanagedInitializedSet.map {\n                Pair(it, it)\n            }\n            assertFailsWith<ClassCastException> {\n                set.addAll(somethingEntirelyDifferent as Collection<T>)\n            }\n\n            // Does not change if we add the same data from a managed set\n            val sameValuesManagedSet = managedSetGetter.get(transactionRealm.createObject())\n            assertNotNull(sameValuesManagedSet)\n            assertTrue(sameValuesManagedSet.addAll(unmanagedInitializedSet))\n            assertFalse(set.addAll(sameValuesManagedSet as Collection<T>))\n            assertEquals(unmanagedInitializedSet.size, set.size)\n\n            // Does not change if we add an empty RealmSet\n            val emptyManagedSet = managedSetGetter.get(transactionRealm.createObject())\n            assertTrue(emptyManagedSet.isEmpty())\n            assertFalse(set.addAll(emptyManagedSet))\n            assertEquals(unmanagedInitializedSet.size, set.size)\n\n            // Changes after adding a managed set containing other values\n            val notPresentValueSet = managedSetGetter.get(transactionRealm.createObject())\n            assertNotNull(notPresentValueSet)\n            notPresentValueSet.add(unmanagedNotPresentValue)\n            assertTrue(set.addAll(notPresentValueSet as Collection<T>))\n            assertEquals(unmanagedInitializedSet.size + notPresentValueSet.size, set.size)\n\n            // Does not change after adding a managed list with the same elements\n            set.clear()\n            set.addAll(unmanagedInitializedSet)\n            val sameValuesManagedList = managedCollectionGetter.call(transactionRealm.createObject<SetContainerClass>())\n            sameValuesManagedList.addAll(unmanagedInitializedSet)\n            assertFalse(set.addAll(sameValuesManagedList))\n            assertTrue(set.containsAll(sameValuesManagedList))\n\n            // Changes after adding a managed list with other elements\n            val differentValuesManagedList =\n                managedCollectionGetter.call(transactionRealm.createObject<SetContainerClass>())\n            differentValuesManagedList.addAll(listOf(unmanagedNotPresentValue))\n            assertTrue(set.addAll(differentValuesManagedList))\n            assertTrue(set.containsAll(differentValuesManagedList))\n\n            // Does not change after adding an empty managed list\n            set.clear()\n            assertTrue(set.addAll(unmanagedInitializedSet))\n            val emptyValuesManagedList =\n                managedCollectionGetter.call(transactionRealm.createObject<SetContainerClass>())\n            assertFalse(set.addAll(emptyValuesManagedList))\n            assertEquals(unmanagedInitializedSet.size, set.size)\n\n            // Fails if passed null according to Java Set interface\n            assertFailsWith<NullPointerException> {\n                set.addAll(TestHelper.getNull())\n            }\n        }\n\n        // Test with objects from another realm\n        accessTransactionRealmInLooperThread { looperRealm ->\n            val values = insertObjects(looperRealm, unmanagedInitializedSet)\n\n            assertFailsWith<IllegalArgumentException>(\"Cannot pass values from another Realm\") {\n                set.addAll(values)\n            }\n        }\n    }\n\n    override fun retainAll() {\n        // Test with managed realm objects\n        managedTester.retainAll()\n\n        // Test with unmanaged realm objects\n        val set = initAndAssertEmptySet()\n        realm.executeTransaction {\n            // Check throws exception when unmanaged values are passed\n            assertFailsWith<IllegalArgumentException>(\"Collection with unmanaged objects not permitted\") {\n                set.retainAll(unmanagedInitializedSet)\n            }\n\n            if (!nullable) {\n                // Check throws exception when null values are passed\n                assertFailsWith<java.lang.NullPointerException>(\"Collections with nulls are not permitted\") {\n                    set.retainAll(listOf(null))\n                }\n            }\n        }\n\n        // Test with objects from another realm\n        accessTransactionRealmInLooperThread { looperRealm ->\n            val values = insertObjects(looperRealm, unmanagedInitializedSet)\n\n            assertFailsWith<IllegalArgumentException>(\"Cannot pass values from another Realm\") {\n                set.retainAll(values)\n            }\n        }\n    }\n\n    override fun removeAll() {\n        // Test with managed realm objects\n        managedTester.removeAll()\n\n        // Test with unmanaged realm objects\n        val set = initAndAssertEmptySet()\n        realm.executeTransaction {\n            // Check throws exception when unmanaged values are passed\n            assertFailsWith<IllegalArgumentException>(\"Collection with unmanaged objects not permitted\") {\n                set.removeAll(unmanagedInitializedSet)\n            }\n            if (!nullable) {\n                // Check throws exception when null values are passed\n                assertFailsWith<java.lang.NullPointerException>(\"Collections with nulls are not permitted\") {\n                    set.removeAll(listOf(null))\n                }\n            }\n        }\n\n        // Test with objects from another realm\n        accessTransactionRealmInLooperThread { looperRealm ->\n            val values = insertObjects(looperRealm, unmanagedInitializedSet)\n\n            assertFailsWith<IllegalArgumentException>(\"Cannot pass values from another Realm\") {\n                set.removeAll(values)\n            }\n        }\n    }\n\n    override fun clear() = managedTester.clear()\n\n    override fun freeze() = managedTester.freeze()\n\n    override fun setters() {\n        managedTester.setters()\n\n        accessTransactionRealmInLooperThread { looperRealm ->\n            val alternativeObject = createAllTypesManagedContainerAndAssert(looperRealm, \"alternativeObject\", true)\n            val alternativeSet = RealmSet<T>().init(managedInitializedSet)\n\n            assertFailsWith<IllegalArgumentException>(\"Cannot pass values from another Realm\") {\n                setSetter(alternativeObject, alternativeSet)\n            }\n        }\n    }\n\n    override fun addRealmChangeListener() = Unit\n\n    override fun addSetChangeListener() = Unit\n\n    override fun removeSetChangeListener() = Unit\n\n    override fun removeRealmChangeListener() = Unit\n\n    override fun hasListeners() = Unit\n\n    override fun aggregations() {\n        if (realmAnyType == null) {\n            // Aggregations on RealmAny type are not supported\n            val set = initAndAssertEmptySet()\n\n            realm.executeTransaction {\n                set.addAll(managedInitializedSet)\n            }\n\n            assertEquals(VALUE_AGE_HELLO, set.min(DogPrimaryKey.AGE))\n            assertEquals(VALUE_AGE_BYE, set.max(DogPrimaryKey.AGE))\n            assertEquals((VALUE_AGE_HELLO + VALUE_AGE_BYE) / 2.toDouble(), set.average(DogPrimaryKey.AGE))\n            assertEquals(VALUE_AGE_HELLO + VALUE_AGE_BYE, set.sum(DogPrimaryKey.AGE))\n            assertEquals(VALUE_BIRTHDAY_HELLO, set.minDate(DogPrimaryKey.BIRTHDAY))\n            assertEquals(VALUE_BIRTHDAY_BYE, set.maxDate(DogPrimaryKey.BIRTHDAY))\n\n            // Delete all should clear the set and remove all objects from the set\n            realm.executeTransaction {\n                set.addAll(managedInitializedSet)\n                assertEquals(managedInitializedSet.size, set.size)\n                set.deleteAllFromRealm()\n                assertTrue(set.isEmpty())\n\n                for (element in managedInitializedSet) {\n                    assertFalse(RealmObject.isValid(element as RealmModel))\n                }\n            }\n        } else {\n            // Aggregations on RealmAny type are not supported\n            managedTester.aggregations()\n        }\n    }\n\n    private fun accessTransactionRealmInLooperThread(block: (looperRealm: Realm) -> Unit) {\n        // Test with objects from another realm\n        looperThread.runBlocking {\n            Realm.getInstance(realm.configuration).use { looperRealm ->\n                looperRealm.executeTransaction {\n                    block(looperRealm)\n                }\n            }\n            looperThread.testComplete()\n        }\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/kotlin/io/realm/SetMiscTests.kt",
    "content": "/*\n * Copyright 2021 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\npackage io.realm\n\nimport androidx.test.ext.junit.runners.AndroidJUnit4\nimport androidx.test.platform.app.InstrumentationRegistry\nimport io.realm.entities.*\nimport io.realm.kotlin.createObject\nimport org.bson.types.Decimal128\nimport org.bson.types.ObjectId\nimport org.json.JSONArray\nimport org.json.JSONObject\nimport org.junit.After\nimport org.junit.Before\nimport org.junit.Rule\nimport org.junit.Test\nimport org.junit.runner.RunWith\nimport java.util.*\nimport kotlin.test.*\n\n@RunWith(AndroidJUnit4::class)\nclass SetMiscTests {\n\n    @Rule\n    @JvmField\n    val configFactory = TestRealmConfigurationFactory()\n\n    private val setFields = listOf(\n        // The \"java.lang\" prefix in primitive types is needed or else Kotlin will map it to raw primitives\n        Triple(\n            SetContainerMigrationClass::myBooleanSet,\n            java.lang.Boolean::class.java,\n            RealmFieldType.BOOLEAN_SET\n        ),\n        Triple(\n            SetContainerMigrationClass::myIntSet,\n            java.lang.Integer::class.java,\n            RealmFieldType.INTEGER_SET\n        ),\n        Triple(\n            SetContainerMigrationClass::myFloatSet,\n            java.lang.Float::class.java,\n            RealmFieldType.FLOAT_SET\n        ),\n        Triple(\n            SetContainerMigrationClass::myLongSet,\n            java.lang.Long::class.java,\n            RealmFieldType.INTEGER_SET\n        ),\n        Triple(\n            SetContainerMigrationClass::myShortSet,\n            java.lang.Short::class.java,\n            RealmFieldType.INTEGER_SET\n        ),\n        Triple(\n            SetContainerMigrationClass::myByteSet,\n            java.lang.Byte::class.java,\n            RealmFieldType.INTEGER_SET\n        ),\n        Triple(\n            SetContainerMigrationClass::myDoubleSet,\n            java.lang.Double::class.java,\n            RealmFieldType.DOUBLE_SET\n        ),\n        Triple(\n            SetContainerMigrationClass::myStringSet,\n            String::class.java,\n            RealmFieldType.STRING_SET\n        ),\n        Triple(\n            SetContainerMigrationClass::myBinarySet,\n            ByteArray::class.java,\n            RealmFieldType.BINARY_SET\n        ),\n        Triple(\n            SetContainerMigrationClass::myDateSet,\n            Date::class.java,\n            RealmFieldType.DATE_SET\n        ),\n        Triple(\n            SetContainerMigrationClass::myObjectIdSet,\n            ObjectId::class.java,\n            RealmFieldType.OBJECT_ID_SET\n        ),\n        Triple(\n            SetContainerMigrationClass::myUUIDSet,\n            UUID::class.java,\n            RealmFieldType.UUID_SET\n        ),\n        Triple(\n            SetContainerMigrationClass::myDecimal128Set,\n            Decimal128::class.java,\n            RealmFieldType.DECIMAL128_SET\n        ),\n        Triple(\n            SetContainerMigrationClass::myRealmAnySet,\n            RealmAny::class.java,\n            RealmFieldType.MIXED_SET\n        ),\n        Triple(\n            SetContainerMigrationClass::myRealmModelSet,\n            StringOnly::class.java,\n            RealmFieldType.LINK_SET\n        )\n    )\n\n    private lateinit var realm: Realm\n\n    @Before\n    fun setUp() {\n        Realm.init(InstrumentationRegistry.getInstrumentation().context)\n    }\n\n    @After\n    fun tearDown() {\n        realm.close()\n    }\n\n    @Test\n    fun migrate_realmSet() {\n        // Creates v0 of the Realm.\n        val originalConfig = configFactory.createConfigurationBuilder()\n            .schema(StringOnly::class.java)\n            .build()\n        Realm.getInstance(originalConfig).close()\n\n        // Creates v1 of the Realm.\n        val realmConfig = configFactory.createConfigurationBuilder()\n            .schemaVersion(1)\n            .schema(StringOnly::class.java, SetContainerMigrationClass::class.java)\n            .migration { realm, _, _ ->\n                val schema = realm.schema.create(SetContainerMigrationClass.CLASS_NAME)\n                schema.addField(\"id\", String::class.java)\n                    .addPrimaryKey(\"id\")\n\n                setFields.forEach {\n                    val objectSchema = if (it.third == RealmFieldType.LINK_SET) {\n                        val realmModelSchema = realm.schema.get(it.second.simpleName)\n                        assertNotNull(realmModelSchema)\n                        schema.addRealmSetField(it.first.name, realmModelSchema)\n                    } else {\n                        schema.addRealmSetField(it.first.name, it.second)\n                    }\n                    assertNotNull(objectSchema)\n                    assertTrue(objectSchema.hasField(it.first.name))\n                }\n            }.build()\n\n        realm = Realm.getInstance(realmConfig)\n\n        val objectSchema = realm.schema.get(SetContainerMigrationClass.CLASS_NAME)\n        assertNotNull(objectSchema)\n        setFields.forEach {\n            assertTrue(objectSchema.hasField(it.first.name))\n            assertEquals(it.third, objectSchema.getFieldType(it.first.name))\n        }\n\n        realm.executeTransaction { transactionRealm ->\n            val container = transactionRealm.createObject<SetContainerMigrationClass>(\"\")\n            setFields.forEach {\n                val set = it.first.get(container)\n                assertNotNull(set)\n                assertTrue(set.isEmpty())\n            }\n        }\n\n        realm.close()\n    }\n\n    @Test\n    fun migrate_removeRealmSet() {\n        // Creates v0 of the Realm.\n        val originalConfig = configFactory.createConfigurationBuilder()\n            .schema(StringOnly::class.java, SetContainerAfterMigrationClass::class.java)\n            .build()\n\n        // Initialize the schema\n        Realm.getInstance(originalConfig).close()\n        val localRealm = DynamicRealm.getInstance(originalConfig)\n        localRealm.executeTransaction {\n            val schema = it.schema\n\n            // Remove the \"end-result\" class from schema as we need to recreate it \"from scratch\"\n            schema.remove(SetContainerAfterMigrationClass.CLASS_NAME)\n            val createdSchema = schema.create(SetContainerAfterMigrationClass.CLASS_NAME)\n            createdSchema.addField(\"id\", String::class.java)\n                .addPrimaryKey(\"id\")\n\n            setFields.forEach { setField ->\n                // Now add the fields that will be removed in the migration\n                if (setField.third == RealmFieldType.LINK_SET) {\n                    createdSchema.addRealmObjectField(setField.first.name, createdSchema)\n                } else {\n                    createdSchema.addField(setField.first.name, setField.second)\n                }\n            }\n            assertEquals(setFields.size + 1, createdSchema.fieldNames.size)\n        }\n        localRealm.close()\n\n        // Creates v1 of the Realm.\n        val realmConfig = configFactory.createConfigurationBuilder()\n            .schemaVersion(1)\n            .schema(StringOnly::class.java, SetContainerAfterMigrationClass::class.java)\n            .migration { realm, _, _ ->\n                val schema = realm.schema.get(SetContainerAfterMigrationClass.CLASS_NAME)\n                assertNotNull(schema)\n\n                setFields.forEach {\n                    assertTrue(schema.hasField(it.first.name))\n                    schema.removeField(it.first.name)\n                    assertFalse(schema.hasField(it.first.name))\n                }\n                assertEquals(1, schema.fieldNames.size)\n            }.build()\n\n        realm = Realm.getInstance(realmConfig)\n\n        val objectSchema = realm.schema.get(SetContainerAfterMigrationClass.CLASS_NAME)\n        assertNotNull(objectSchema)\n        setFields.forEach {\n            assertFalse(objectSchema.hasField(it.first.name))\n        }\n        assertEquals(1, objectSchema.fieldNames.size)\n\n        realm.close()\n    }\n    \n    @Test\n    fun createAllFromJson_unsupportedOperation() {\n        realm = Realm.getInstance(configFactory.createConfiguration())\n        realm.executeTransaction {\n            val jsonArray = \"[{ \\\"columnLong\\\" : 1 }]\"\n\n            // createAllFromJson\n            assertFailsWith<UnsupportedOperationException> {\n                realm.createAllFromJson(SetContainerClass::class.java, jsonArray)\n            }\n            assertFailsWith<UnsupportedOperationException> {\n                realm.createAllFromJson(SetContainerClass::class.java, JSONArray(jsonArray))\n            }\n            assertFailsWith<UnsupportedOperationException> {\n                realm.createAllFromJson(SetContainerClass::class.java, TestHelper.stringToStream(jsonArray))\n            }\n        }\n    }\n\n    @Test\n    fun createObjectFromJson_unsupportedOperation() {\n        realm = Realm.getInstance(configFactory.createConfiguration())\n        realm.executeTransaction {\n            val jsonObject = \"{ \\\"columnLong\\\" : 1 }\"\n\n            // createObjectFromJson\n            assertFailsWith<UnsupportedOperationException> {\n                realm.createObjectFromJson(SetContainerClass::class.java, jsonObject)\n            }\n            assertFailsWith<UnsupportedOperationException> {\n                realm.createObjectFromJson(SetContainerClass::class.java, JSONObject(jsonObject))\n            }\n            assertFailsWith<UnsupportedOperationException> {\n                realm.createObjectFromJson(SetContainerClass::class.java, TestHelper.stringToStream(jsonObject))\n            }\n        }\n    }\n\n    @Test\n    fun createOrUpdateAllFromJson_unsupportedOperation() {\n        realm = Realm.getInstance(configFactory.createConfiguration())\n        realm.executeTransaction {\n            val jsonArray = \"[{ \\\"columnLong\\\" : 1 }]\"\n\n            // createOrUpdateAllFromJson\n            assertFailsWith<UnsupportedOperationException> {\n                realm.createOrUpdateAllFromJson(SetContainerMigrationClass::class.java, jsonArray)\n            }\n            assertFailsWith<UnsupportedOperationException> {\n                realm.createOrUpdateAllFromJson(SetContainerMigrationClass::class.java, JSONArray(jsonArray))\n            }\n            assertFailsWith<UnsupportedOperationException> {\n                realm.createOrUpdateAllFromJson(SetContainerMigrationClass::class.java, TestHelper.stringToStream(jsonArray))\n            }\n        }\n    }\n\n    @Test\n    fun createOrUpdateObjectFromJson_unsupportedOperation() {\n        realm = Realm.getInstance(configFactory.createConfiguration())\n        realm.executeTransaction {\n            val jsonObject = \"{ \\\"columnLong\\\" : 1 }\"\n\n            // createOrUpdateObjectFromJson\n            assertFailsWith<UnsupportedOperationException> {\n                realm.createOrUpdateObjectFromJson(SetContainerMigrationClass::class.java, jsonObject)\n            }\n            assertFailsWith<UnsupportedOperationException> {\n                realm.createOrUpdateObjectFromJson(SetContainerMigrationClass::class.java, JSONObject(jsonObject))\n            }\n            assertFailsWith<UnsupportedOperationException> {\n                realm.createOrUpdateObjectFromJson(SetContainerMigrationClass::class.java, TestHelper.stringToStream(jsonObject))\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/kotlin/io/realm/UUIDTests.kt",
    "content": "/*\n * Copyright 2020 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 */\npackage io.realm\n\nimport androidx.test.ext.junit.runners.AndroidJUnit4\nimport androidx.test.platform.app.InstrumentationRegistry\nimport io.realm.annotations.PrimaryKey\nimport io.realm.annotations.Required\nimport io.realm.exceptions.RealmException\nimport io.realm.exceptions.RealmPrimaryKeyConstraintException\nimport io.realm.kotlin.createObject\nimport io.realm.kotlin.where\nimport org.junit.*\nimport org.junit.Assert.*\nimport org.junit.runner.RunWith\nimport java.util.*\nimport kotlin.test.assertFailsWith\n\nopen class UUIDPrimaryKeyRequired\n    : RealmObject() {\n    @PrimaryKey\n    @Required\n    var id: UUID? = null\n    var name: String = \"\"\n    var anotherId: UUID? = null\n}\n\nopen class UUIDPrimaryKeyNotRequired\n    : RealmObject() {\n    @PrimaryKey\n    var id: UUID? = null\n    var name: String = \"\"\n}\n\nopen class UUIDAndString\n    : RealmObject() {\n    var id: UUID? = null\n    var name: String = \"\"\n}\n\nopen class UUIDRequiredRealmList\n    : RealmObject() {\n    var id: Long = 0\n\n    @Required\n    var ids: RealmList<UUID> = RealmList()\n    var name: String = \"\"\n}\n\nopen class UUIDOptionalRealmList\n    : RealmObject() {\n    var id: Long = 0\n\n    var ids: RealmList<UUID> = RealmList()\n    var name: String = \"\"\n}\n\nopen class LinkedUUID : RealmObject() {\n    var linkedUUID: UUIDPrimaryKeyNotRequired? = null\n}\n\n@RunWith(AndroidJUnit4::class)\nclass UUIDTests {\n    private lateinit var realmConfiguration: RealmConfiguration\n    private lateinit var realm: Realm\n\n    @Rule\n    @JvmField\n    val configFactory = TestRealmConfigurationFactory()\n\n    init {\n        Realm.init(InstrumentationRegistry.getInstrumentation().targetContext)\n    }\n\n    @Before\n    fun setUp() {\n        realmConfiguration = configFactory\n                .createConfigurationBuilder()\n                .schema(UUIDPrimaryKeyRequired::class.java,\n                        UUIDPrimaryKeyNotRequired::class.java,\n                        UUIDAndString::class.java,\n                        UUIDRequiredRealmList::class.java,\n                        UUIDOptionalRealmList::class.java,\n                        LinkedUUID::class.java)\n                .build()\n\n        realm = Realm.getInstance(realmConfiguration)\n    }\n\n    @After\n    fun tearDown() {\n        realm.close()\n    }\n\n    @Test\n    fun copyToRealm() {\n        val uuid1 = UUID.randomUUID()\n        val uuid2 = UUID.randomUUID()\n\n        val value = UUIDPrimaryKeyRequired()\n        value.id = uuid1\n        value.anotherId = uuid2\n        value.name = \"Foo\"\n\n        realm.beginTransaction()\n        val obj = realm.copyToRealm(value)\n        realm.commitTransaction()\n\n        assertEquals(uuid1, obj.id)\n        assertEquals(uuid2, obj.anotherId)\n        assertEquals(\"Foo\", obj.name)\n    }\n\n    @Test\n    fun copyFromRealm() {\n        val uuid1 = UUID.randomUUID()\n        val uuid2 = UUID.randomUUID()\n\n        realm.beginTransaction()\n        val obj = realm.createObject<UUIDPrimaryKeyRequired>(uuid1)\n        obj.anotherId = uuid2\n        obj.name = \"Foo\"\n        realm.commitTransaction()\n\n        val copy = realm.copyFromRealm(obj)\n\n        assertEquals(uuid1, copy.id)\n        assertEquals(uuid2, copy.anotherId)\n        assertEquals(\"Foo\", copy.name)\n    }\n\n    @Test\n    fun copyToRealmOrUpdate() {\n        val uuid1 = UUID.randomUUID()\n        val uuid2 = UUID.randomUUID()\n        val uuid3 = UUID.randomUUID()\n\n        realm.executeTransaction { realm ->\n            val obj = realm.createObject<UUIDPrimaryKeyRequired>(uuid1)\n            obj.anotherId = uuid2\n            obj.name = \"Foo\"\n        }\n\n        val value = UUIDPrimaryKeyRequired()\n        value.id = uuid1\n        value.name = \"Bar\"\n        value.anotherId = uuid3\n\n        realm.beginTransaction()\n        val obj = realm.copyToRealmOrUpdate(value)\n        realm.commitTransaction()\n\n        assertEquals(uuid1, obj.id)\n        assertEquals(uuid3, obj.anotherId)\n        assertEquals(\"Bar\", obj.name)\n    }\n\n    @Test\n    fun insert() {\n        val uuid1 = UUID.randomUUID()\n        val uuid2 = UUID.randomUUID()\n\n        realm.executeTransaction { realm ->\n            val value = UUIDPrimaryKeyRequired()\n            value.id = uuid1\n            value.name = \"Foo\"\n            value.anotherId = uuid2\n\n            realm.insert(value)\n        }\n\n        val obj = realm.where<UUIDPrimaryKeyRequired>().findFirst()\n\n        assertNotNull(obj)\n        assertEquals(uuid1, obj!!.id)\n        assertEquals(uuid2, obj.anotherId)\n        assertEquals(\"Foo\", obj.name)\n    }\n\n    @Test\n    fun insertOrUpdate() {\n        val uuid1 = UUID.randomUUID()\n        val uuid2 = UUID.randomUUID()\n        val uuid3 = UUID.randomUUID()\n\n        realm.executeTransaction { realm ->\n            val value = realm.createObject<UUIDPrimaryKeyRequired>(uuid1)\n            value.name = \"Foo\"\n            value.anotherId = uuid2\n        }\n\n        realm.executeTransaction { realm ->\n            val obj = UUIDPrimaryKeyRequired()\n            obj.id = uuid1\n            obj.anotherId = uuid3\n            obj.name = \"Bar\"\n            realm.insertOrUpdate(obj)\n        }\n\n        val all = realm.where<UUIDPrimaryKeyRequired>().findAll()\n\n        assertEquals(1, all.size)\n        assertEquals(uuid1, all[0]!!.id)\n        assertEquals(uuid3, all[0]!!.anotherId)\n        assertEquals(\"Bar\", all[0]!!.name)\n    }\n\n    @Test\n    fun frozen() {\n        val uuid1 = UUID.randomUUID()\n\n        realm.beginTransaction()\n        val obj = realm.createObject<UUIDPrimaryKeyRequired>(uuid1)\n        obj.name = \"foo\"\n        realm.commitTransaction()\n\n        val frozen = obj.freeze<UUIDPrimaryKeyRequired>()\n        assertEquals(uuid1, frozen.id)\n        assertEquals(\"foo\", frozen.name)\n    }\n\n    @Test\n    fun requiredPK() {\n        val uuid1 = UUID.randomUUID()\n\n        realm.beginTransaction()\n\n        assertFailsWith<RealmException> {\n            realm.createObject<UUIDPrimaryKeyRequired>()\n        }\n\n        val obj = realm.createObject<UUIDPrimaryKeyRequired>(uuid1)\n        obj.name = \"foo\"\n\n        realm.commitTransaction()\n\n        val result = realm.where<UUIDPrimaryKeyRequired>().equalTo(\"id\", uuid1).findFirst()\n        assertNotNull(result)\n        assertEquals(\"foo\", result?.name)\n    }\n\n    @Test\n    fun nullablePK() {\n        assertFailsWith<RealmException> {\n            realm.createObject<UUIDPrimaryKeyNotRequired>()\n        }\n\n        realm.beginTransaction()\n        val obj = realm.createObject<UUIDPrimaryKeyNotRequired>(null)\n        obj.name = \"foo\"\n        realm.commitTransaction()\n\n        val result = realm.where<UUIDPrimaryKeyNotRequired>().equalTo(\"id\", null as UUID?).findFirst()\n        assertNotNull(result)\n        assertEquals(\"foo\", result!!.name)\n    }\n\n\n    @Test\n    fun requiredRealmList() {\n        realm.beginTransaction()\n        val obj = realm.createObject<UUIDRequiredRealmList>()\n\n        assertFailsWith<IllegalArgumentException>(\"It should not be possible to add nullable elements to a required RealmList<UUID>\") {\n            obj.ids.add(null)\n        }\n    }\n\n    @Test\n    fun optionalRealmList() {\n        val uuid1 = UUID.randomUUID()\n\n        realm.beginTransaction()\n        val obj = realm.createObject<UUIDOptionalRealmList>()\n        obj.ids.add(null)\n        obj.ids.add(uuid1)\n        realm.commitTransaction()\n\n        assertEquals(2, realm.where<UUIDOptionalRealmList>().findFirst()?.ids?.size)\n    }\n\n    @Test\n    fun linkQueryNotSupported() {\n        val uuid1 = UUID.randomUUID()\n\n        realm.beginTransaction()\n        val obj = realm.createObject<UUIDRequiredRealmList>()\n        realm.cancelTransaction()\n\n        assertFailsWith<UnsupportedOperationException>(\"It should not be possible to perform link query on UUID\") {\n            obj.ids.where().equalTo(\"ids\", uuid1).findAll()\n        }\n    }\n\n    @Test\n    fun duplicatePK() {\n        val uuid1 = UUID.randomUUID()\n\n        realm.beginTransaction()\n        realm.createObject<UUIDPrimaryKeyRequired>(uuid1)\n\n        assertFailsWith<RealmPrimaryKeyConstraintException>(\"It should throw for duplicate PK usage\") {\n            realm.createObject<UUIDPrimaryKeyRequired>(uuid1)\n        }\n\n        realm.cancelTransaction()\n    }\n\n    @Test\n    fun sort() {\n        val uuid1 = UUID.fromString(\"017ba5ca-aa12-4afa-9219-e20cc3018599\")\n        val uuid2 = UUID.fromString(\"027ba5ca-aa12-4afa-9219-e20cc3018599\")\n        val uuid3 = UUID.fromString(\"037ba5ca-aa12-4afa-9219-e20cc3018599\")\n\n        realm.beginTransaction()\n        realm.createObject<UUIDAndString>().id = uuid3\n        realm.createObject<UUIDAndString>().id = uuid1\n        realm.createObject<UUIDAndString>().id = uuid2\n        realm.commitTransaction()\n\n        var all = realm.where<UUIDAndString>().sort(\"id\", Sort.ASCENDING).findAll()\n\n        assertEquals(3, all.size)\n        assertEquals(uuid1, all[0]!!.id)\n        assertEquals(uuid2, all[1]!!.id)\n        assertEquals(uuid3, all[2]!!.id)\n\n        all = realm.where<UUIDAndString>().sort(\"id\", Sort.DESCENDING).findAll()\n\n        assertEquals(3, all.size)\n        assertEquals(uuid3, all[0]!!.id)\n        assertEquals(uuid2, all[1]!!.id)\n        assertEquals(uuid1, all[2]!!.id)\n    }\n\n    @Test\n    fun distinct() {\n        val uuid1 = UUID.fromString(\"017ba5ca-aa12-4afa-9219-e20cc3018599\")\n        val uuid2 = UUID.fromString(\"027ba5ca-aa12-4afa-9219-e20cc3018599\")\n        val uuid3 = UUID.fromString(\"037ba5ca-aa12-4afa-9219-e20cc3018599\")\n\n        realm.beginTransaction()\n        realm.createObject<UUIDAndString>().id = uuid2\n        realm.createObject<UUIDAndString>().id = uuid2\n        realm.createObject<UUIDAndString>().id = null\n        realm.createObject<UUIDAndString>().id = uuid1\n        realm.createObject<UUIDAndString>().id = uuid1\n        realm.createObject<UUIDAndString>().id = null\n        realm.createObject<UUIDAndString>().id = uuid3\n        realm.createObject<UUIDAndString>().id = uuid3\n        realm.createObject<UUIDAndString>().id = null\n        realm.commitTransaction()\n\n        val all = realm.where<UUIDAndString>().distinct(\"id\").sort(\"id\", Sort.ASCENDING).findAll()\n\n        assertEquals(4, all.size)\n        assertNull(all[0]!!.id)\n        assertEquals(uuid1, all[1]!!.id)\n        assertEquals(uuid2, all[2]!!.id)\n        assertEquals(uuid3, all[3]!!.id)\n\n    }\n\n    @Test\n    fun queries() {\n        val uuid1 = UUID.randomUUID()\n        val uuid2 = UUID.randomUUID()\n        val uuid3 = UUID.randomUUID()\n\n        realm.executeTransaction { realm ->\n            realm.createObject<UUIDAndString>().id = uuid2\n            realm.createObject<UUIDAndString>().id = null\n            realm.createObject<UUIDAndString>().id = uuid3\n            realm.createObject<UUIDAndString>().id = uuid1\n        }\n\n        assertEquals(4, realm.where<UUIDAndString>().count())\n    }\n\n    @Test\n    fun queriesNotEqualTo() {\n        val uuid1 = UUID.fromString(\"017ba5ca-aa12-4afa-9219-e20cc3018599\")\n        val uuid2 = UUID.fromString(\"027ba5ca-aa12-4afa-9219-e20cc3018599\")\n        val uuid3 = UUID.fromString(\"037ba5ca-aa12-4afa-9219-e20cc3018599\")\n\n        realm.executeTransaction { realm ->\n            realm.createObject<UUIDAndString>().id = uuid2\n            realm.createObject<UUIDAndString>().id = null\n            realm.createObject<UUIDAndString>().id = uuid3\n            realm.createObject<UUIDAndString>().id = uuid1\n        }\n\n        val all = realm.where<UUIDAndString>()\n                .notEqualTo(\"id\", uuid2)\n                .sort(\"id\", Sort.ASCENDING)\n                .findAll()\n\n        assertEquals(3, all.size)\n        assertNull(all[0]!!.id)\n        assertEquals(uuid1, all[1]!!.id)\n        assertEquals(uuid3, all[2]!!.id)\n    }\n\n    @Test\n    fun queriesGreaterThanOrEqualTo() {\n        val uuid1 = UUID.fromString(\"017ba5ca-aa12-4afa-9219-e20cc3018599\")\n        val uuid2 = UUID.fromString(\"027ba5ca-aa12-4afa-9219-e20cc3018599\")\n        val uuid3 = UUID.fromString(\"037ba5ca-aa12-4afa-9219-e20cc3018599\")\n\n        realm.executeTransaction { realm ->\n            realm.createObject<UUIDAndString>().id = uuid2\n            realm.createObject<UUIDAndString>().id = null\n            realm.createObject<UUIDAndString>().id = uuid3\n            realm.createObject<UUIDAndString>().id = uuid1\n        }\n\n        val all = realm.where<UUIDAndString>()\n                .greaterThanOrEqualTo(\"id\", uuid2)\n                .sort(\"id\", Sort.ASCENDING)\n                .findAll()\n\n        assertEquals(2, all.size)\n        assertEquals(uuid2, all[0]!!.id)\n        assertEquals(uuid3, all[1]!!.id)\n    }\n\n    @Test\n    fun queriesGreaterThan() {\n        val uuid1 = UUID.fromString(\"017ba5ca-aa12-4afa-9219-e20cc3018599\")\n        val uuid2 = UUID.fromString(\"027ba5ca-aa12-4afa-9219-e20cc3018599\")\n        val uuid3 = UUID.fromString(\"037ba5ca-aa12-4afa-9219-e20cc3018599\")\n\n        realm.executeTransaction { realm ->\n            realm.createObject<UUIDAndString>().id = uuid2\n            realm.createObject<UUIDAndString>().id = null\n            realm.createObject<UUIDAndString>().id = uuid3\n            realm.createObject<UUIDAndString>().id = uuid1\n        }\n\n        val all = realm.where<UUIDAndString>()\n                .greaterThan(\"id\", uuid2)\n                .sort(\"id\", Sort.ASCENDING)\n                .findAll()\n\n        assertEquals(1, all.size)\n        assertEquals(uuid3, all[0]!!.id)\n    }\n\n    @Test\n    fun queriesLessThanOrEqualTo() {\n        val uuid1 = UUID.fromString(\"017ba5ca-aa12-4afa-9219-e20cc3018599\")\n        val uuid2 = UUID.fromString(\"027ba5ca-aa12-4afa-9219-e20cc3018599\")\n        val uuid3 = UUID.fromString(\"037ba5ca-aa12-4afa-9219-e20cc3018599\")\n\n        realm.executeTransaction { realm ->\n            realm.createObject<UUIDAndString>().id = uuid2\n            realm.createObject<UUIDAndString>().id = null\n            realm.createObject<UUIDAndString>().id = uuid3\n            realm.createObject<UUIDAndString>().id = uuid1\n        }\n\n        val all = realm.where<UUIDAndString>()\n                .lessThanOrEqualTo(\"id\", uuid2)\n                .sort(\"id\", Sort.ASCENDING)\n                .findAll()\n\n        assertEquals(2, all.size)\n        assertEquals(uuid1, all[0]!!.id)\n        assertEquals(uuid2, all[1]!!.id)\n    }\n\n    @Test\n    fun queriesLessThan() {\n        val uuid1 = UUID.fromString(\"017ba5ca-aa12-4afa-9219-e20cc3018599\")\n        val uuid2 = UUID.fromString(\"027ba5ca-aa12-4afa-9219-e20cc3018599\")\n        val uuid3 = UUID.fromString(\"037ba5ca-aa12-4afa-9219-e20cc3018599\")\n\n        realm.executeTransaction { realm ->\n            realm.createObject<UUIDAndString>().id = uuid2\n            realm.createObject<UUIDAndString>().id = null\n            realm.createObject<UUIDAndString>().id = uuid3\n            realm.createObject<UUIDAndString>().id = uuid1\n        }\n\n        val all = realm.where<UUIDAndString>()\n                .lessThan(\"id\", uuid2)\n                .sort(\"id\", Sort.ASCENDING)\n                .findAll()\n\n        assertEquals(1, all.size)\n        assertEquals(uuid1, all[0]!!.id)\n    }\n\n    @Test\n    fun queriesIsNull() {\n        val uuid1 = UUID.randomUUID()\n        val uuid2 = UUID.randomUUID()\n        val uuid3 = UUID.randomUUID()\n\n        realm.executeTransaction { realm ->\n            realm.createObject<UUIDAndString>().id = uuid2\n            realm.createObject<UUIDAndString>().id = null\n            realm.createObject<UUIDAndString>().id = uuid3\n            realm.createObject<UUIDAndString>().id = uuid1\n        }\n\n        val all = realm.where<UUIDAndString>()\n                .isNull(\"id\")\n                .findAll()\n\n        assertEquals(1, all.size)\n        assertNull(all[0]!!.id)\n    }\n\n    @Test\n    fun queriesIsNotNull() {\n        val uuid1 = UUID.fromString(\"017ba5ca-aa12-4afa-9219-e20cc3018599\")\n        val uuid2 = UUID.fromString(\"027ba5ca-aa12-4afa-9219-e20cc3018599\")\n        val uuid3 = UUID.fromString(\"037ba5ca-aa12-4afa-9219-e20cc3018599\")\n\n        realm.executeTransaction { realm ->\n            realm.createObject<UUIDAndString>().id = uuid2\n            realm.createObject<UUIDAndString>().id = null\n            realm.createObject<UUIDAndString>().id = uuid3\n            realm.createObject<UUIDAndString>().id = uuid1\n        }\n\n        val all = realm.where<UUIDAndString>()\n                .isNotNull(\"id\")\n                .sort(\"id\", Sort.ASCENDING)\n                .findAll()\n\n        assertEquals(3, all.size)\n        assertEquals(uuid1, all[0]!!.id)\n        assertEquals(uuid2, all[1]!!.id)\n        assertEquals(uuid3, all[2]!!.id)\n    }\n\n    @Test\n    fun queriesAverage() {\n        val uuid1 = UUID.randomUUID()\n        val uuid2 = UUID.randomUUID()\n        val uuid3 = UUID.randomUUID()\n\n        realm.executeTransaction { realm ->\n            realm.createObject<UUIDAndString>().id = uuid2\n            realm.createObject<UUIDAndString>().id = null\n            realm.createObject<UUIDAndString>().id = uuid3\n            realm.createObject<UUIDAndString>().id = uuid1\n        }\n\n        assertFailsWith<IllegalArgumentException>(\"Average is not supported for UUID\") {\n            realm.where<UUIDAndString>().average(\"id\")\n        }\n    }\n\n    @Test\n    fun queriesIsEmpty() {\n        val uuid1 = UUID.randomUUID()\n        val uuid2 = UUID.randomUUID()\n        val uuid3 = UUID.randomUUID()\n\n        realm.executeTransaction { realm ->\n            realm.createObject<UUIDAndString>().id = uuid2\n            realm.createObject<UUIDAndString>().id = null\n            realm.createObject<UUIDAndString>().id = uuid3\n            realm.createObject<UUIDAndString>().id = uuid1\n        }\n\n        assertFailsWith<IllegalArgumentException>(\"isEmpty is not supported for UUID\") {\n            realm.where<UUIDAndString>().isEmpty(\"id\")\n        }\n    }\n\n    @Test\n    fun linkedQuery() {\n        val uuidArray = arrayOf(null, UUID.randomUUID(), UUID.randomUUID(), UUID.randomUUID())\n\n        realm.executeTransaction { realm ->\n            for (uuid in uuidArray) {\n                val uuidObj = realm.createObject<UUIDPrimaryKeyNotRequired>(uuid)\n                realm.createObject<LinkedUUID>().linkedUUID = uuidObj\n            }\n        }\n\n        for (uuid in uuidArray) {\n            val results = realm.where<LinkedUUID>().equalTo(\"linkedUUID.id\", uuid).findAll()\n            assertEquals(1, results.size)\n            assertEquals(uuid, results.first()?.linkedUUID?.id)\n        }\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/kotlin/io/realm/UnmanagedDictionaryTesters.kt",
    "content": "/*\n * Copyright 2020 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\npackage io.realm\n\nimport io.realm.rule.BlockingLooperThread\nimport org.bson.types.Decimal128\nimport org.bson.types.ObjectId\nimport java.util.*\nimport kotlin.test.assertEquals\nimport kotlin.test.assertFailsWith\nimport kotlin.test.assertFalse\nimport kotlin.test.assertTrue\n\n/**\n * Generic tester for all types of unmanaged dictionaries.\n */\nclass UnmanagedDictionaryTester<T : Any>(\n        private val testerName: String,\n        private val keyValuePairs: List<Pair<String, T?>>,\n        private val notPresentKey: String,\n        private val notPresentValue: T\n) : DictionaryTester {\n\n    override fun toString(): String = testerName\n\n    override fun setUp(config: RealmConfiguration, looperThread: BlockingLooperThread) = Unit       // Not applicable\n    override fun tearDown() = Unit                                                                  // Not applicable\n\n    override fun constructorWithAnotherMap() {\n        val otherDictionary = RealmDictionary<T?>().apply {\n            for (keyValuePair in keyValuePairs) {\n                this[keyValuePair.first] = keyValuePair.second\n            }\n        }\n        val realmDictionary = RealmDictionary<T>(otherDictionary)\n        assertEquals(keyValuePairs.size, realmDictionary.size)\n        for (keyValuePair in keyValuePairs) {\n            assertTrue(realmDictionary.containsKey(keyValuePair.first))\n            assertTrue(realmDictionary.containsValue(keyValuePair.second))\n        }\n    }\n\n    override fun isManaged() {\n        val realmDictionary = RealmDictionary<T>()\n        assertFalse(realmDictionary.isManaged)\n    }\n\n    override fun isValid() {\n        val realmDictionary = RealmDictionary<T>()\n        assertTrue(realmDictionary.isValid)\n    }\n\n    override fun isFrozen() {\n        val realmDictionary = RealmDictionary<T>()\n        assertFalse(realmDictionary.isFrozen)\n    }\n\n    override fun size() {\n        val realmDictionary = RealmDictionary<T>()\n        assertEquals(0, realmDictionary.size)\n        for (keyValuePair in keyValuePairs) {\n            realmDictionary[keyValuePair.first] = keyValuePair.second\n        }\n        assertEquals(keyValuePairs.size, realmDictionary.size)\n    }\n\n    override fun isEmpty() {\n        val realmDictionary = RealmDictionary<T>()\n        assertTrue(realmDictionary.isEmpty())\n        for (keyValuePair in keyValuePairs) {\n            realmDictionary[keyValuePair.first] = keyValuePair.second\n        }\n        assertFalse(realmDictionary.isEmpty())\n    }\n\n    override fun containsKey() {\n        val realmDictionary = RealmDictionary<T>()\n        for (keyValuePair in keyValuePairs) {\n            realmDictionary[keyValuePair.first] = keyValuePair.second\n            assertTrue(realmDictionary.containsKey(keyValuePair.first))\n        }\n        assertFalse(realmDictionary.containsKey(notPresentKey))\n    }\n\n    override fun containsValue() {\n        val realmDictionary = RealmDictionary<T>()\n        for (keyValuePair in keyValuePairs) {\n            realmDictionary[keyValuePair.first] = keyValuePair.second\n            assertTrue(realmDictionary.containsValue(keyValuePair.second))\n        }\n        assertFalse(realmDictionary.containsValue(notPresentValue))\n    }\n\n    override fun get() = Unit                       // This will be tested in \"put\"\n\n    override fun put() {\n        val realmDictionary = RealmDictionary<T?>()\n        assertEquals(0, realmDictionary.size)\n        for (i in keyValuePairs.indices) {\n            realmDictionary[keyValuePairs[i].first] = keyValuePairs[i].second\n            assertEquals(i + 1, realmDictionary.size)\n        }\n        for (i in keyValuePairs.indices) {\n            assertEquals(keyValuePairs[i].second, realmDictionary[keyValuePairs[i].first])\n        }\n\n        // Cannot add a null key\n        assertFailsWith<NullPointerException> {\n            realmDictionary[null] = keyValuePairs[0].second\n        }\n    }\n\n    override fun putRequired() = Unit               // Not applicable\n\n    override fun remove() {\n        val realmDictionary = RealmDictionary<T>()\n        for (keyValuePair in keyValuePairs) {\n            realmDictionary[keyValuePair.first] = keyValuePair.second\n        }\n        for (keyValuePair in keyValuePairs) {\n            val removedValue = realmDictionary.remove(keyValuePair.first)\n            assertEquals(keyValuePair.second, removedValue)\n        }\n\n        // Nothing happens when removing a null key\n        realmDictionary.remove(null)\n    }\n\n    override fun putAll() {\n        val otherMap = HashMap<String, T?>().apply {\n            for (keyValuePair in keyValuePairs) {\n                this[keyValuePair.first] = keyValuePair.second\n            }\n        }\n        val realmDictionary = RealmDictionary<T>()\n        realmDictionary.putAll(otherMap)\n        assertEquals(keyValuePairs.size, realmDictionary.size)\n        for (keyValuePair in keyValuePairs) {\n            assertTrue(realmDictionary.containsKey(keyValuePair.first))\n            assertTrue(realmDictionary.containsValue(keyValuePair.second))\n        }\n    }\n\n    override fun clear() {\n        val realmDictionary = RealmDictionary<T>()\n        assertTrue(realmDictionary.isEmpty())\n        for (keyValuePair in keyValuePairs) {\n            realmDictionary[keyValuePair.first] = keyValuePair.second\n        }\n        assertFalse(realmDictionary.isEmpty())\n        realmDictionary.clear()\n        assertTrue(realmDictionary.isEmpty())\n    }\n\n    override fun keySet() {\n        val otherDictionary = RealmDictionary<T>().apply {\n            for (keyValuePair in keyValuePairs) {\n                this[keyValuePair.first] = keyValuePair.second\n            }\n        }\n        val realmDictionary = RealmDictionary<T>(otherDictionary)\n        val keySet = keyValuePairs.map { pair -> pair.first }.toSet()\n        assertEquals(keySet, realmDictionary.keys)\n    }\n\n    override fun values() {\n        val otherDictionary = RealmDictionary<T>().apply {\n            for (keyValuePair in keyValuePairs) {\n                this[keyValuePair.first] = keyValuePair.second\n            }\n        }\n        val realmDictionary = RealmDictionary<T>(otherDictionary)\n        val dictionaryValues = realmDictionary.values\n\n        // Depending on the internal implementation of the chosen Map, the order might be altered\n        keyValuePairs.forEach { pair ->\n            assertTrue(dictionaryValues.contains(pair.second))\n        }\n    }\n\n    override fun entrySet() {\n        val otherDictionary = RealmDictionary<T>().apply {\n            for (keyValuePair in keyValuePairs) {\n                this[keyValuePair.first] = keyValuePair.second\n            }\n        }\n        val realmDictionary = RealmDictionary<T>(otherDictionary)\n        assertEquals(otherDictionary.entries, realmDictionary.entries)\n    }\n\n    override fun freeze() {\n        val dictionary = RealmDictionary<T>()\n        assertFailsWith<UnsupportedOperationException> {\n            dictionary.freeze()\n        }\n    }\n\n    override fun dynamic() = Unit                                           // Not applicable\n    override fun insert() = Unit                                            // Not applicable\n    override fun insertList() = Unit                                        // Not applicable\n    override fun insertOrUpdate() = Unit                                    // Not applicable\n    override fun insertOrUpdateList() = Unit                                // Not applicable\n    override fun copyToRealm() = Unit                                       // Not applicable\n    override fun copyToRealmOrUpdate() = Unit                               // Not applicable\n    override fun copyFromRealm() = Unit                                     // Not applicable\n    override fun fieldAccessors(otherConfig: RealmConfiguration?) = Unit    // Not applicable\n\n    override fun addMapChangeListener() {\n        val dictionary = RealmDictionary<T>()\n        assertFailsWith<UnsupportedOperationException> {\n            dictionary.addChangeListener { _, _ -> /* no-op */ }\n        }\n    }\n\n    override fun addRealmChangeListener() {\n        val dictionary = RealmDictionary<T>()\n        assertFailsWith<UnsupportedOperationException> {\n            dictionary.addChangeListener { _ -> /* no-op */ }\n        }\n    }\n\n    override fun hasListeners() {\n        val dictionary = RealmDictionary<T>()\n        assertFalse(dictionary.hasListeners())\n    }\n}\n\n/**\n * Creates testers for all [DictionarySupportedType]s and initializes them for testing. There are as\n * many RealmAny testers as [RealmAny.Type]s.\n */\nfun unmanagedDictionaryFactory(): List<DictionaryTester> {\n    // Create primitive testers first\n    val primitiveTesters: List<DictionaryTester> = DictionarySupportedType.values().mapNotNull { supportedType ->\n        when (supportedType) {\n            DictionarySupportedType.LONG ->\n                UnmanagedDictionaryTester<Long>(\n                        testerName = \"UnmanagedLong\",\n                        keyValuePairs = listOf(KEY_HELLO to VALUE_NUMERIC_HELLO.toLong(), KEY_BYE to VALUE_NUMERIC_BYE.toLong(), KEY_NULL to null),\n                        notPresentKey = KEY_NOT_PRESENT,\n                        notPresentValue = VALUE_NUMERIC_NOT_PRESENT.toLong()\n                )\n            DictionarySupportedType.INTEGER ->\n                UnmanagedDictionaryTester<Int>(\n                        testerName = \"UnmanagedInteger\",\n                        keyValuePairs = listOf(KEY_HELLO to VALUE_NUMERIC_HELLO, KEY_BYE to VALUE_NUMERIC_BYE, KEY_NULL to null),\n                        notPresentKey = KEY_NOT_PRESENT,\n                        notPresentValue = VALUE_NUMERIC_NOT_PRESENT\n                )\n            DictionarySupportedType.SHORT ->\n                UnmanagedDictionaryTester<Short>(\n                        testerName = \"UnmanagedShort\",\n                        keyValuePairs = listOf(KEY_HELLO to VALUE_NUMERIC_HELLO.toShort(), KEY_BYE to VALUE_NUMERIC_BYE.toShort(), KEY_NULL to null),\n                        notPresentKey = KEY_NOT_PRESENT,\n                        notPresentValue = VALUE_NUMERIC_NOT_PRESENT.toShort()\n                )\n            DictionarySupportedType.BYTE ->\n                UnmanagedDictionaryTester<Byte>(\n                        testerName = \"UnmanagedByte\",\n                        keyValuePairs = listOf(KEY_HELLO to VALUE_NUMERIC_HELLO.toByte(), KEY_BYE to VALUE_NUMERIC_BYE.toByte(), KEY_NULL to null),\n                        notPresentKey = KEY_NOT_PRESENT,\n                        notPresentValue = VALUE_NUMERIC_NOT_PRESENT.toByte()\n                )\n            DictionarySupportedType.FLOAT ->\n                UnmanagedDictionaryTester<Float>(\n                        testerName = \"UnmanagedFloat\",\n                        keyValuePairs = listOf(KEY_HELLO to VALUE_NUMERIC_HELLO.toFloat(), KEY_BYE to VALUE_NUMERIC_BYE.toFloat(), KEY_NULL to null),\n                        notPresentKey = KEY_NOT_PRESENT,\n                        notPresentValue = VALUE_NUMERIC_NOT_PRESENT.toFloat()\n                )\n            DictionarySupportedType.DOUBLE ->\n                UnmanagedDictionaryTester<Double>(\n                        testerName = \"UnmanagedDouble\",\n                        keyValuePairs = listOf(KEY_HELLO to VALUE_NUMERIC_HELLO.toDouble(), KEY_BYE to VALUE_NUMERIC_BYE.toDouble(), KEY_NULL to null),\n                        notPresentKey = KEY_NOT_PRESENT,\n                        notPresentValue = VALUE_NUMERIC_NOT_PRESENT.toDouble()\n                )\n            DictionarySupportedType.STRING ->\n                UnmanagedDictionaryTester<String>(\n                        testerName = \"UnmanagedString\",\n                        keyValuePairs = listOf(KEY_HELLO to VALUE_STRING_HELLO, KEY_BYE to VALUE_STRING_BYE, KEY_NULL to null),\n                        notPresentKey = KEY_NOT_PRESENT,\n                        notPresentValue = VALUE_STRING_NOT_PRESENT\n                )\n            DictionarySupportedType.BOOLEAN ->\n                UnmanagedDictionaryTester<Boolean>(\n                        testerName = \"UnmanagedBoolean\",\n                        keyValuePairs = listOf(KEY_HELLO to VALUE_BOOLEAN_HELLO, KEY_NULL to null),\n                        notPresentKey = KEY_NOT_PRESENT,\n                        notPresentValue = VALUE_BOOLEAN_NOT_PRESENT\n                )\n            DictionarySupportedType.DATE ->\n                UnmanagedDictionaryTester<Date>(\n                        testerName = \"UnmanagedDate\",\n                        keyValuePairs = listOf(KEY_HELLO to VALUE_DATE_HELLO, KEY_BYE to VALUE_DATE_BYE, KEY_NULL to null),\n                        notPresentKey = KEY_NOT_PRESENT,\n                        notPresentValue = VALUE_DATE_NOT_PRESENT\n                )\n            DictionarySupportedType.DECIMAL128 ->\n                UnmanagedDictionaryTester<Decimal128>(\n                        testerName = \"UnmanagedDecimal128\",\n                        keyValuePairs = listOf(KEY_HELLO to VALUE_DECIMAL128_HELLO, KEY_BYE to VALUE_DECIMAL128_BYE, KEY_NULL to null),\n                        notPresentKey = KEY_NOT_PRESENT,\n                        notPresentValue = VALUE_DECIMAL128_NOT_PRESENT\n                )\n            DictionarySupportedType.BINARY ->\n                UnmanagedDictionaryTester<ByteArray>(\n                        testerName = \"UnmanagedBinary\",\n                        keyValuePairs = listOf(KEY_HELLO to VALUE_BINARY_HELLO, KEY_BYE to VALUE_BINARY_BYE, KEY_NULL to null),\n                        notPresentKey = KEY_NOT_PRESENT,\n                        notPresentValue = VALUE_BINARY_NOT_PRESENT\n                )\n            DictionarySupportedType.OBJECT_ID ->\n                UnmanagedDictionaryTester<ObjectId>(\n                        testerName = \"UnmanagedObjectId\",\n                        keyValuePairs = listOf(KEY_HELLO to VALUE_OBJECT_ID_HELLO, KEY_BYE to VALUE_OBJECT_ID_BYE, KEY_NULL to null),\n                        notPresentKey = KEY_NOT_PRESENT,\n                        notPresentValue = VALUE_OBJECT_ID_NOT_PRESENT\n                )\n            DictionarySupportedType.UUID ->\n                UnmanagedDictionaryTester<UUID>(\n                        testerName = \"UnmanagedUUID\",\n                        keyValuePairs = listOf(KEY_HELLO to VALUE_UUID_HELLO, KEY_BYE to VALUE_UUID_BYE, KEY_NULL to null),\n                        notPresentKey = KEY_NOT_PRESENT,\n                        notPresentValue = VALUE_UUID_NOT_PRESENT\n                )\n            DictionarySupportedType.LINK ->\n                UnmanagedDictionaryTester<RealmModel>(\n                        testerName = \"UnmanagedRealmModel\",\n                        keyValuePairs = listOf(KEY_HELLO to VALUE_LINK_HELLO, KEY_BYE to VALUE_LINK_BYE, KEY_NULL to null),\n                        notPresentKey = KEY_NOT_PRESENT,\n                        notPresentValue = VALUE_LINK_NOT_PRESENT\n                )\n            DictionarySupportedType.MIXED -> null      // Ignore RealmAny in this switch\n            else -> throw IllegalArgumentException(\"Unknown data type for Dictionaries\")\n        }\n    }\n\n    // Create RealmAny testers now\n    val realmAnyTesters = RealmAny.Type.values().map { realmAnyType ->\n        UnmanagedDictionaryTester<RealmAny>(\n                \"UnmanagedDictionaryRealmAny-${realmAnyType.name}\",\n                getRealmAnyKeyValuePairs(realmAnyType),\n                KEY_NOT_PRESENT,\n                VALUE_MIXED_NOT_PRESENT\n        )\n    }\n\n    // Put them together\n    return primitiveTesters.plus(realmAnyTesters)\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/kotlin/io/realm/UnmanagedSetTester.kt",
    "content": "/*\n * Copyright 2021 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\npackage io.realm\n\nimport io.realm.rule.BlockingLooperThread\nimport org.bson.types.Decimal128\nimport org.bson.types.ObjectId\nimport java.util.*\nimport kotlin.test.*\n\n/**\n * Generic tester for all types of unmanaged sets.\n */\nclass UnmanagedSetTester<T : Any>(\n        private val testerClass: Class<T>,\n        private val values: List<T?>,\n        private val notPresentValue: T,\n        private val toArrayUnmanaged: ToArrayUnmanaged<T>,\n        private val realmAnyType: RealmAny.Type? = null\n) : SetTester {\n\n    override fun toString(): String = when (realmAnyType) {\n        null -> \"UnmanagedDictionary-$testerClass\"\n        else -> \"UnmanagedDictionary-$testerClass\" + realmAnyType.name.let { \"-$it\" }\n    }\n\n    override fun setUp(config: RealmConfiguration, looperThread: BlockingLooperThread) = Unit\n\n    override fun tearDown() = Unit\n\n    override fun isManaged() {\n        val realmSet = RealmSet<T>()\n        assertFalse(realmSet.isManaged)\n    }\n\n    override fun isValid() {\n        val realmSet = RealmSet<T>()\n        assertTrue(realmSet.isValid)\n    }\n\n    override fun isFrozen() {\n        val realmSet = RealmSet<T>()\n        assertFalse(realmSet.isFrozen)\n    }\n\n    override fun size() {\n        val realmSet = RealmSet<T>()\n        assertEquals(0, realmSet.size)\n        realmSet.addAll(values)\n        assertEquals(values.size, realmSet.size)\n    }\n\n    override fun isEmpty() {\n        val realmSet = RealmSet<T>()\n        assertTrue(realmSet.isEmpty())\n        realmSet.addAll(values)\n        assertFalse(realmSet.isEmpty())\n    }\n\n    override fun contains() {\n        val realmSet = RealmSet<T>()\n        realmSet.addAll(values)\n        values.forEach { value ->\n            assertTrue(realmSet.contains(value))\n        }\n    }\n\n    override fun iterator() {\n        val realmSet = RealmSet<T>()\n        assertNotNull(realmSet.iterator())\n    }\n\n    override fun toArray() {\n        val realmSet = RealmSet<T>()\n        val emptyArray = realmSet.toArray()\n        assertEquals(0, emptyArray.size)\n\n        realmSet.addAll(values)\n        val fullArray = realmSet.toArray()\n        assertEquals(values.size, fullArray.size)\n    }\n\n    override fun toArrayWithParameter() {\n        toArrayUnmanaged.toArrayWithParameter(values)\n    }\n\n    override fun add() {\n        val realmSet = RealmSet<T>()\n        assertTrue(realmSet.isEmpty())\n        values.forEach { value ->\n            realmSet.add(value)\n        }\n        assertFalse(realmSet.isEmpty())\n        assertEquals(values.size, realmSet.size)\n    }\n\n    override fun remove() {\n        val realmSet = RealmSet<T>()\n        realmSet.addAll(values)\n        assertEquals(values.size, realmSet.size)\n\n        assertTrue(realmSet.remove(values[0]))\n        assertEquals(values.size - 1, realmSet.size)\n        assertFalse(realmSet.remove(notPresentValue))\n    }\n\n    override fun requiredConstraints() = Unit // Not tested\n\n    override fun containsAll() {\n        val realmSet = RealmSet<T>()\n        realmSet.addAll(values)\n        assertTrue(realmSet.containsAll(values))\n    }\n\n    override fun addAll() = Unit        // Tested multiple times in the other functions\n\n    override fun retainAll() {\n        val realmSet = RealmSet<T>()\n        realmSet.addAll(values)\n\n        // Test intersection with present value\n        val presentValues = values.subList(0, 1)\n        assertTrue(realmSet.retainAll(presentValues))\n        assertEquals(presentValues.size, realmSet.size)\n\n        // Test intersection with non-present value\n        val differentRealmSet = RealmSet<T>()\n        differentRealmSet.addAll(values)\n        assertTrue(differentRealmSet.retainAll(listOf(notPresentValue)))\n        assertTrue(differentRealmSet.isEmpty())\n    }\n\n    override fun dynamic() = Unit  // Not applicable\n\n    override fun insert() = Unit  // Not applicable\n\n    override fun insertList() = Unit  // Not applicable\n\n    override fun insertOrUpdate() = Unit  // Not applicable\n\n    override fun insertOrUpdateList() = Unit  // Not applicable\n\n    override fun copyToRealm() = Unit  // Not applicable\n\n    override fun copyToRealmOrUpdate() = Unit  // Not applicable\n\n    override fun removeAll() {\n        val realmSet = RealmSet<T>()\n        realmSet.addAll(values)\n        assertFalse(realmSet.isEmpty())\n        realmSet.removeAll(values)\n        assertTrue(realmSet.isEmpty())\n\n        val differentRealmSet = RealmSet<T>()\n        differentRealmSet.addAll(values)\n        assertFalse(differentRealmSet.isEmpty())\n        differentRealmSet.removeAll(listOf(notPresentValue))\n        assertEquals(values.size, differentRealmSet.size)\n    }\n\n    override fun clear() {\n        val realmSet = RealmSet<T>()\n        realmSet.addAll(values)\n        assertFalse(realmSet.isEmpty())\n        realmSet.clear()\n        assertTrue(realmSet.isEmpty())\n    }\n\n    override fun freeze() {\n        assertFailsWith<UnsupportedOperationException> {\n            RealmSet<T>().freeze()\n        }\n    }\n\n    override fun setters() = Unit                       // Not a valid test on unmanaged sets\n\n    override fun addRealmChangeListener() = Unit        // Not a valid test on unmanaged sets\n\n    override fun addSetChangeListener() = Unit          // Not a valid test on unmanaged sets\n\n    override fun removeSetChangeListener() = Unit       // Not a valid test on unmanaged sets\n\n    override fun removeRealmChangeListener() = Unit     // Not a valid test on unmanaged sets\n\n    override fun hasListeners() {\n        assertFalse(RealmSet<T>().hasListeners())\n    }\n\n    override fun aggregations() {\n        val set = RealmSet<T>()\n\n        // Aggregation operations are not supported on primitive types.\n        assertFailsWith<java.lang.UnsupportedOperationException> {\n            set.min(\"aFieldName\")\n        }\n\n        assertFailsWith<java.lang.UnsupportedOperationException> {\n            set.max(\"aFieldName\")\n        }\n\n        assertFailsWith<java.lang.UnsupportedOperationException> {\n            set.average(\"aFieldName\")\n        }\n\n        assertFailsWith<java.lang.UnsupportedOperationException> {\n            set.sum(\"aFieldName\")\n        }\n\n        assertFailsWith<java.lang.UnsupportedOperationException> {\n            set.minDate(\"aFieldName\")\n        }\n\n        assertFailsWith<java.lang.UnsupportedOperationException> {\n            set.maxDate(\"aFieldName\")\n        }\n\n        // deleteAllFromRealm is only supported on managed sets.\n        assertFailsWith<java.lang.UnsupportedOperationException> {\n            set.deleteAllFromRealm()\n        }\n    }\n}\n\nfun unmanagedSetFactory(): List<SetTester> {\n    val primitiveTesters: List<SetTester> = SetSupportedType.values().mapNotNull { supportedType ->\n        when (supportedType) {\n            SetSupportedType.LONG ->\n                UnmanagedSetTester(\n                        testerClass = Long::class.java,\n                        values = listOf(VALUE_NUMERIC_HELLO.toLong(), VALUE_NUMERIC_BYE.toLong(), null),\n                        notPresentValue = VALUE_NUMERIC_NOT_PRESENT.toLong(),\n                        toArrayUnmanaged = ToArrayUnmanaged.LongUnmanaged()\n                )\n            SetSupportedType.INTEGER ->\n                UnmanagedSetTester(\n                        testerClass = Int::class.java,\n                        values = listOf(VALUE_NUMERIC_HELLO, VALUE_NUMERIC_BYE),\n                        notPresentValue = VALUE_NUMERIC_NOT_PRESENT,\n                        toArrayUnmanaged = ToArrayUnmanaged.IntUnmanaged()\n                )\n            SetSupportedType.SHORT ->\n                UnmanagedSetTester(\n                        testerClass = Short::class.java,\n                        values = listOf(VALUE_NUMERIC_HELLO.toShort(), VALUE_NUMERIC_BYE.toShort(), null),\n                        notPresentValue = VALUE_NUMERIC_NOT_PRESENT.toShort(),\n                        toArrayUnmanaged = ToArrayUnmanaged.ShortUnmanaged()\n                )\n            SetSupportedType.BYTE ->\n                UnmanagedSetTester(\n                        testerClass = Byte::class.java,\n                        values = listOf(VALUE_NUMERIC_HELLO.toByte(), VALUE_NUMERIC_BYE.toByte(), null),\n                        notPresentValue = VALUE_NUMERIC_NOT_PRESENT.toByte(),\n                        toArrayUnmanaged = ToArrayUnmanaged.ByteUnmanaged()\n                )\n            SetSupportedType.FLOAT ->\n                UnmanagedSetTester(\n                        testerClass = Float::class.java,\n                        values = listOf(VALUE_NUMERIC_HELLO.toFloat(), VALUE_NUMERIC_BYE.toFloat(), null),\n                        notPresentValue = VALUE_NUMERIC_NOT_PRESENT.toFloat(),\n                        toArrayUnmanaged = ToArrayUnmanaged.FloatUnmanaged()\n                )\n            SetSupportedType.DOUBLE ->\n                UnmanagedSetTester(\n                        testerClass = Double::class.java,\n                        values = listOf(VALUE_NUMERIC_HELLO.toDouble(), VALUE_NUMERIC_BYE.toDouble(), null),\n                        notPresentValue = VALUE_NUMERIC_NOT_PRESENT.toDouble(),\n                        toArrayUnmanaged = ToArrayUnmanaged.DoubleUnmanaged()\n                )\n            SetSupportedType.STRING ->\n                UnmanagedSetTester(\n                        testerClass = String::class.java,\n                        values = listOf(VALUE_STRING_HELLO, VALUE_STRING_BYE, null),\n                        notPresentValue = VALUE_STRING_NOT_PRESENT,\n                        toArrayUnmanaged = ToArrayUnmanaged.StringUnmanaged()\n                )\n            SetSupportedType.BOOLEAN ->\n                UnmanagedSetTester(\n                        testerClass = Boolean::class.java,\n                        values = listOf(VALUE_BOOLEAN_HELLO, null),\n                        notPresentValue = VALUE_BOOLEAN_NOT_PRESENT,\n                        toArrayUnmanaged = ToArrayUnmanaged.BooleanUnmanaged()\n                )\n            SetSupportedType.DATE ->\n                UnmanagedSetTester(\n                        testerClass = Date::class.java,\n                        values = listOf(VALUE_DATE_HELLO, VALUE_DATE_BYE, null),\n                        notPresentValue = VALUE_DATE_NOT_PRESENT,\n                        toArrayUnmanaged = ToArrayUnmanaged.DateUnmanaged()\n                )\n            SetSupportedType.DECIMAL128 ->\n                UnmanagedSetTester(\n                        testerClass = Decimal128::class.java,\n                        values = listOf(VALUE_DECIMAL128_HELLO, VALUE_DECIMAL128_BYE, null),\n                        notPresentValue = VALUE_DECIMAL128_NOT_PRESENT,\n                        toArrayUnmanaged = ToArrayUnmanaged.Decimal128Unmanaged()\n                )\n            SetSupportedType.BINARY ->\n                UnmanagedSetTester(\n                        testerClass = ByteArray::class.java,\n                        values = listOf(VALUE_BINARY_HELLO, VALUE_BINARY_BYE, null),\n                        notPresentValue = VALUE_BINARY_NOT_PRESENT,\n                        toArrayUnmanaged = ToArrayUnmanaged.BinaryUnmanaged()\n                )\n            SetSupportedType.OBJECT_ID ->\n                UnmanagedSetTester(\n                        testerClass = ObjectId::class.java,\n                        values = listOf(VALUE_OBJECT_ID_HELLO, VALUE_OBJECT_ID_BYE, null),\n                        notPresentValue = VALUE_OBJECT_ID_NOT_PRESENT,\n                        toArrayUnmanaged = ToArrayUnmanaged.ObjectIdUnmanaged()\n                )\n            SetSupportedType.UUID ->\n                UnmanagedSetTester(\n                        testerClass = UUID::class.java,\n                        values = listOf(VALUE_UUID_HELLO, VALUE_UUID_BYE, null),\n                        notPresentValue = VALUE_UUID_NOT_PRESENT,\n                        toArrayUnmanaged = ToArrayUnmanaged.UUIDUnmanaged()\n                )\n            SetSupportedType.LINK ->\n                UnmanagedSetTester(\n                        testerClass = RealmModel::class.java,\n                        values = listOf(VALUE_LINK_HELLO, VALUE_LINK_BYE, null),\n                        notPresentValue = VALUE_LINK_NOT_PRESENT,\n                        toArrayUnmanaged = ToArrayUnmanaged.RealmModelUnmanaged()\n                )\n            SetSupportedType.MIXED -> null      // Ignore RealmAny in this switch\n            else -> throw IllegalArgumentException(\"Unknown data type for Sets\")\n        }\n    }\n\n    // Create RealmAny testers now\n    val realmAnyTesters = RealmAny.Type.values().map { realmAnyType ->\n        UnmanagedSetTester(\n                RealmAny::class.java,\n                getRealmAnyValues(realmAnyType),\n                VALUE_MIXED_NOT_PRESENT,\n                ToArrayUnmanaged.RealmAnyUnmanaged(),\n                realmAnyType\n        )\n    }\n\n    // Put them together\n    return primitiveTesters.plus(realmAnyTesters)\n}\n\nfun getRealmAnyValues(realmAnyType: RealmAny.Type): List<RealmAny?> {\n    return when (realmAnyType) {\n        RealmAny.Type.INTEGER ->\n            listOf(VALUE_MIXED_INTEGER_HELLO, VALUE_MIXED_INTEGER_BYE, null)\n        RealmAny.Type.BOOLEAN ->\n            listOf(VALUE_MIXED_BOOLEAN_HELLO, null)\n        RealmAny.Type.STRING ->\n            listOf(VALUE_MIXED_STRING_HELLO, VALUE_MIXED_STRING_BYE, null)\n        RealmAny.Type.BINARY ->\n            listOf(VALUE_MIXED_BINARY_HELLO, VALUE_MIXED_BINARY_BYE, null)\n        RealmAny.Type.DATE ->\n            listOf(VALUE_MIXED_DATE_HELLO, VALUE_MIXED_DATE_BYE, null)\n        RealmAny.Type.FLOAT ->\n            listOf(VALUE_MIXED_FLOAT_HELLO, VALUE_MIXED_FLOAT_BYE, null)\n        RealmAny.Type.DOUBLE ->\n            listOf(VALUE_MIXED_DOUBLE_HELLO, VALUE_MIXED_DOUBLE_BYE, null)\n        RealmAny.Type.DECIMAL128 ->\n            listOf(VALUE_MIXED_DECIMAL128_HELLO, VALUE_MIXED_DECIMAL128_BYE, null)\n        RealmAny.Type.OBJECT_ID ->\n            listOf(VALUE_MIXED_OBJECT_ID_HELLO, VALUE_MIXED_OBJECT_ID_BYE, null)\n        RealmAny.Type.OBJECT ->\n            listOf(VALUE_MIXED_LINK_HELLO, VALUE_MIXED_LINK_BYE, null)\n        RealmAny.Type.UUID ->\n            listOf(VALUE_MIXED_UUID_HELLO, VALUE_MIXED_UUID_BYE, null)\n        RealmAny.Type.NULL ->\n            listOf(RealmAny.nullValue(), RealmAny.valueOf(\"Not null\"), null)\n    }\n}\n\n/**\n * TODO\n */\nabstract class ToArrayUnmanaged<T> {\n\n    abstract fun toArrayWithParameter(values: List<T?>)\n\n    protected fun test(values: List<T?>, emptyArray: Array<T>, fullArray: Array<T>) {\n        val realmSet = RealmSet<T>()\n        val emptyFromSet = realmSet.toArray(emptyArray)\n        assertEquals(0, emptyFromSet.size)\n\n        realmSet.addAll(values as Collection<T>)\n        val fullFromSet = realmSet.toArray(fullArray)\n        assertEquals(values.size, fullFromSet.size)\n    }\n\n    class LongUnmanaged : ToArrayUnmanaged<Long>() {\n        override fun toArrayWithParameter(values: List<Long?>) = test(values, emptyArray(), arrayOf())\n    }\n\n    class IntUnmanaged : ToArrayUnmanaged<Int>() {\n        override fun toArrayWithParameter(values: List<Int?>) = test(values, emptyArray(), arrayOf())\n    }\n\n    class ShortUnmanaged : ToArrayUnmanaged<Short>() {\n        override fun toArrayWithParameter(values: List<Short?>) = test(values, emptyArray(), arrayOf())\n    }\n\n    class ByteUnmanaged : ToArrayUnmanaged<Byte>() {\n        override fun toArrayWithParameter(values: List<Byte?>) = test(values, emptyArray(), arrayOf())\n    }\n\n    class FloatUnmanaged : ToArrayUnmanaged<Float>() {\n        override fun toArrayWithParameter(values: List<Float?>) = test(values, emptyArray(), arrayOf())\n    }\n\n    class DoubleUnmanaged : ToArrayUnmanaged<Double>() {\n        override fun toArrayWithParameter(values: List<Double?>) = test(values, emptyArray(), arrayOf())\n    }\n\n    class StringUnmanaged : ToArrayUnmanaged<String>() {\n        override fun toArrayWithParameter(values: List<String?>) = test(values, emptyArray(), arrayOf())\n    }\n\n    class BooleanUnmanaged : ToArrayUnmanaged<Boolean>() {\n        override fun toArrayWithParameter(values: List<Boolean?>) = test(values, emptyArray(), arrayOf())\n    }\n\n    class DateUnmanaged : ToArrayUnmanaged<Date>() {\n        override fun toArrayWithParameter(values: List<Date?>) = test(values, emptyArray(), arrayOf())\n    }\n\n    class Decimal128Unmanaged : ToArrayUnmanaged<Decimal128>() {\n        override fun toArrayWithParameter(values: List<Decimal128?>) = test(values, emptyArray(), arrayOf())\n    }\n\n    class BinaryUnmanaged : ToArrayUnmanaged<ByteArray>() {\n        override fun toArrayWithParameter(values: List<ByteArray?>) = test(values, emptyArray(), arrayOf())\n    }\n\n    class ObjectIdUnmanaged : ToArrayUnmanaged<ObjectId>() {\n        override fun toArrayWithParameter(values: List<ObjectId?>) = test(values, emptyArray(), arrayOf())\n    }\n\n    class UUIDUnmanaged : ToArrayUnmanaged<UUID>() {\n        override fun toArrayWithParameter(values: List<UUID?>) = test(values, emptyArray(), arrayOf())\n    }\n\n    class RealmModelUnmanaged : ToArrayUnmanaged<RealmModel>() {\n        override fun toArrayWithParameter(values: List<RealmModel?>) = test(values, emptyArray(), arrayOf())\n    }\n\n    class RealmAnyUnmanaged : ToArrayUnmanaged<RealmAny>() {\n        override fun toArrayWithParameter(values: List<RealmAny?>) = test(values, emptyArray(), arrayOf())\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/kotlin/io/realm/entities/DictionaryAllTypes.java",
    "content": "/*\n * Copyright 2021 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\npackage io.realm.entities;\n\nimport org.bson.types.Decimal128;\nimport org.bson.types.ObjectId;\n\nimport java.util.Date;\nimport java.util.UUID;\n\nimport io.realm.RealmAny;\nimport io.realm.RealmDictionary;\nimport io.realm.RealmObject;\nimport io.realm.annotations.PrimaryKey;\nimport io.realm.annotations.Required;\n\npublic class DictionaryAllTypes extends RealmObject {\n\n    public static final String NAME = \"DictionaryAllTypes\";\n    public static final String FIELD_STRING_DICTIONARY = \"columnStringDictionary\";\n\n    private RealmDictionary<DogPrimaryKey> columnRealmDictionary;\n    private RealmDictionary<Boolean> columnBooleanDictionary;\n    private RealmDictionary<String> columnStringDictionary;\n    private RealmDictionary<Integer> columnIntegerDictionary;\n    private RealmDictionary<Float> columnFloatDictionary;\n    private RealmDictionary<Long> columnLongDictionary;\n    private RealmDictionary<Short> columnShortDictionary;\n    private RealmDictionary<Double> columnDoubleDictionary;\n    private RealmDictionary<Byte> columnByteDictionary;\n    private RealmDictionary<byte[]> columnBinaryDictionary;\n    private RealmDictionary<Date> columnDateDictionary;\n    private RealmDictionary<ObjectId> columnObjectIdDictionary;\n    private RealmDictionary<UUID> columnUUIDDictionary;\n    private RealmDictionary<Decimal128> columnDecimal128Dictionary;\n    private RealmDictionary<RealmAny> columnRealmAnyDictionary;\n\n    @Required\n    private String columnString = \"\";\n\n    @Required\n    private RealmDictionary<Boolean> columnRequiredBooleanDictionary;\n    @Required\n    private RealmDictionary<String> columnRequiredStringDictionary;\n    @Required\n    private RealmDictionary<Integer> columnRequiredIntegerDictionary;\n    @Required\n    private RealmDictionary<Float> columnRequiredFloatDictionary;\n    @Required\n    private RealmDictionary<Long> columnRequiredLongDictionary;\n    @Required\n    private RealmDictionary<Short> columnRequiredShortDictionary;\n    @Required\n    private RealmDictionary<Double> columnRequiredDoubleDictionary;\n    @Required\n    private RealmDictionary<Byte> columnRequiredByteDictionary;\n    @Required\n    private RealmDictionary<byte[]> columnRequiredBinaryDictionary;\n    @Required\n    private RealmDictionary<Date> columnRequiredDateDictionary;\n    @Required\n    private RealmDictionary<ObjectId> columnRequiredObjectIdDictionary;\n    @Required\n    private RealmDictionary<UUID> columnRequiredUUIDDictionary;\n    @Required\n    private RealmDictionary<Decimal128> columnRequiredDecimal128Dictionary;\n\n    public String getColumnString() {\n        return columnString;\n    }\n\n    public void setColumnString(String columnString) {\n        this.columnString = columnString;\n    }\n\n    public RealmDictionary<DogPrimaryKey> getColumnRealmDictionary() {\n        return columnRealmDictionary;\n    }\n\n    public void setColumnRealmDictionary(RealmDictionary<DogPrimaryKey> columnRealmDictionary) {\n        this.columnRealmDictionary = columnRealmDictionary;\n    }\n\n    public RealmDictionary<Boolean> getColumnBooleanDictionary() {\n        return columnBooleanDictionary;\n    }\n\n    public void setColumnBooleanDictionary(RealmDictionary<Boolean> columnBooleanDictionary) {\n        this.columnBooleanDictionary = columnBooleanDictionary;\n    }\n\n    public RealmDictionary<String> getColumnStringDictionary() {\n        return columnStringDictionary;\n    }\n\n    public void setColumnStringDictionary(RealmDictionary<String> columnStringDictionary) {\n        this.columnStringDictionary = columnStringDictionary;\n    }\n\n    public RealmDictionary<Integer> getColumnIntegerDictionary() {\n        return columnIntegerDictionary;\n    }\n\n    public void setColumnIntegerDictionary(RealmDictionary<Integer> columnIntegerDictionary) {\n        this.columnIntegerDictionary = columnIntegerDictionary;\n    }\n\n    public RealmDictionary<Float> getColumnFloatDictionary() {\n        return columnFloatDictionary;\n    }\n\n    public void setColumnFloatDictionary(RealmDictionary<Float> columnFloatDictionary) {\n        this.columnFloatDictionary = columnFloatDictionary;\n    }\n\n    public RealmDictionary<Long> getColumnLongDictionary() {\n        return columnLongDictionary;\n    }\n\n    public void setColumnLongDictionary(RealmDictionary<Long> columnLongDictionary) {\n        this.columnLongDictionary = columnLongDictionary;\n    }\n\n    public RealmDictionary<Short> getColumnShortDictionary() {\n        return columnShortDictionary;\n    }\n\n    public void setColumnShortDictionary(RealmDictionary<Short> columnShortDictionary) {\n        this.columnShortDictionary = columnShortDictionary;\n    }\n\n    public RealmDictionary<Double> getColumnDoubleDictionary() {\n        return columnDoubleDictionary;\n    }\n\n    public void setColumnDoubleDictionary(RealmDictionary<Double> columnDoubleDictionary) {\n        this.columnDoubleDictionary = columnDoubleDictionary;\n    }\n\n    public RealmDictionary<Byte> getColumnByteDictionary() {\n        return columnByteDictionary;\n    }\n\n    public void setColumnByteDictionary(RealmDictionary<Byte> columnByteDictionary) {\n        this.columnByteDictionary = columnByteDictionary;\n    }\n\n    public RealmDictionary<byte[]> getColumnBinaryDictionary() {\n        return columnBinaryDictionary;\n    }\n\n    public void setColumnBinaryDictionary(RealmDictionary<byte[]> columnBinaryDictionary) {\n        this.columnBinaryDictionary = columnBinaryDictionary;\n    }\n\n    public RealmDictionary<Date> getColumnDateDictionary() {\n        return columnDateDictionary;\n    }\n\n    public void setColumnDateDictionary(RealmDictionary<Date> columnDateDictionary) {\n        this.columnDateDictionary = columnDateDictionary;\n    }\n\n    public RealmDictionary<ObjectId> getColumnObjectIdDictionary() {\n        return columnObjectIdDictionary;\n    }\n\n    public void setColumnObjectIdDictionary(RealmDictionary<ObjectId> columnObjectIdDictionary) {\n        this.columnObjectIdDictionary = columnObjectIdDictionary;\n    }\n\n    public RealmDictionary<UUID> getColumnUUIDDictionary() {\n        return columnUUIDDictionary;\n    }\n\n    public void setColumnUUIDDictionary(RealmDictionary<UUID> columnUUIDDictionary) {\n        this.columnUUIDDictionary = columnUUIDDictionary;\n    }\n\n    public RealmDictionary<Decimal128> getColumnDecimal128Dictionary() {\n        return columnDecimal128Dictionary;\n    }\n\n    public void setColumnDecimal128Dictionary(RealmDictionary<Decimal128> columnDecimal128Dictionary) {\n        this.columnDecimal128Dictionary = columnDecimal128Dictionary;\n    }\n\n    public RealmDictionary<RealmAny> getColumnRealmAnyDictionary() {\n        return columnRealmAnyDictionary;\n    }\n\n    public void setColumnRealmAnyDictionary(RealmDictionary<RealmAny> columnRealmAnyDictionary) {\n        this.columnRealmAnyDictionary = columnRealmAnyDictionary;\n    }\n\n    public RealmDictionary<Boolean> getColumnRequiredBooleanDictionary() {\n        return columnRequiredBooleanDictionary;\n    }\n\n    public void setColumnRequiredBooleanDictionary(RealmDictionary<Boolean> columnRequiredBooleanDictionary) {\n        this.columnRequiredBooleanDictionary = columnRequiredBooleanDictionary;\n    }\n\n    public RealmDictionary<String> getColumnRequiredStringDictionary() {\n        return columnRequiredStringDictionary;\n    }\n\n    public void setColumnRequiredStringDictionary(RealmDictionary<String> columnRequiredStringDictionary) {\n        this.columnRequiredStringDictionary = columnRequiredStringDictionary;\n    }\n\n    public RealmDictionary<Integer> getColumnRequiredIntegerDictionary() {\n        return columnRequiredIntegerDictionary;\n    }\n\n    public void setColumnRequiredIntegerDictionary(RealmDictionary<Integer> columnRequiredIntegerDictionary) {\n        this.columnRequiredIntegerDictionary = columnRequiredIntegerDictionary;\n    }\n\n    public RealmDictionary<Float> getColumnRequiredFloatDictionary() {\n        return columnRequiredFloatDictionary;\n    }\n\n    public void setColumnRequiredFloatDictionary(RealmDictionary<Float> columnRequiredFloatDictionary) {\n        this.columnRequiredFloatDictionary = columnRequiredFloatDictionary;\n    }\n\n    public RealmDictionary<Long> getColumnRequiredLongDictionary() {\n        return columnRequiredLongDictionary;\n    }\n\n    public void setColumnRequiredLongDictionary(RealmDictionary<Long> columnRequiredLongDictionary) {\n        this.columnRequiredLongDictionary = columnRequiredLongDictionary;\n    }\n\n    public RealmDictionary<Short> getColumnRequiredShortDictionary() {\n        return columnRequiredShortDictionary;\n    }\n\n    public void setColumnRequiredShortDictionary(RealmDictionary<Short> columnRequiredShortDictionary) {\n        this.columnRequiredShortDictionary = columnRequiredShortDictionary;\n    }\n\n    public RealmDictionary<Double> getColumnRequiredDoubleDictionary() {\n        return columnRequiredDoubleDictionary;\n    }\n\n    public void setColumnRequiredDoubleDictionary(RealmDictionary<Double> columnRequiredDoubleDictionary) {\n        this.columnRequiredDoubleDictionary = columnRequiredDoubleDictionary;\n    }\n\n    public RealmDictionary<Byte> getColumnRequiredByteDictionary() {\n        return columnRequiredByteDictionary;\n    }\n\n    public void setColumnRequiredByteDictionary(RealmDictionary<Byte> columnRequiredByteDictionary) {\n        this.columnRequiredByteDictionary = columnRequiredByteDictionary;\n    }\n\n    public RealmDictionary<byte[]> getColumnRequiredBinaryDictionary() {\n        return columnRequiredBinaryDictionary;\n    }\n\n    public void setColumnRequiredBinaryDictionary(RealmDictionary<byte[]> columnRequiredBinaryDictionary) {\n        this.columnRequiredBinaryDictionary = columnRequiredBinaryDictionary;\n    }\n\n\n    public RealmDictionary<Date> getColumnRequiredDateDictionary() {\n        return columnRequiredDateDictionary;\n    }\n\n    public void setColumnRequiredDateDictionary(RealmDictionary<Date> columnRequiredDateDictionary) {\n        this.columnRequiredDateDictionary = columnRequiredDateDictionary;\n    }\n\n    public RealmDictionary<ObjectId> getColumnRequiredObjectIdDictionary() {\n        return columnRequiredObjectIdDictionary;\n    }\n\n    public void setColumnRequiredObjectIdDictionary(RealmDictionary<ObjectId> columnRequiredObjectIdDictionary) {\n        this.columnRequiredObjectIdDictionary = columnRequiredObjectIdDictionary;\n    }\n\n    public RealmDictionary<UUID> getColumnRequiredUUIDDictionary() {\n        return columnRequiredUUIDDictionary;\n    }\n\n    public void setColumnRequiredUUIDDictionary(RealmDictionary<UUID> columnRequiredUUIDDictionary) {\n        this.columnRequiredUUIDDictionary = columnRequiredUUIDDictionary;\n    }\n\n    public RealmDictionary<Decimal128> getColumnRequiredDecimal128Dictionary() {\n        return columnRequiredDecimal128Dictionary;\n    }\n\n    public void setColumnRequiredDecimal128Dictionary(RealmDictionary<Decimal128> columnRequiredDecimal128Dictionary) {\n        this.columnRequiredDecimal128Dictionary = columnRequiredDecimal128Dictionary;\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/kotlin/io/realm/entities/DictionaryContainerClass.kt",
    "content": "/*\n * Copyright 2021 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\npackage io.realm.entities\n\nimport io.realm.RealmAny\nimport io.realm.RealmDictionary\nimport io.realm.RealmList\nimport io.realm.RealmObject\nimport io.realm.annotations.PrimaryKey\nimport io.realm.entities.embedded.EmbeddedSimpleChild\nimport org.bson.types.Decimal128\nimport org.bson.types.ObjectId\nimport java.util.*\n\nopen class DictionaryContainerClass : RealmObject() {\n\n    val myRealmModelDictionary = RealmDictionary<StringOnly>()\n    val myBooleanDictionary = RealmDictionary<Boolean>()\n    val myStringDictionary = RealmDictionary<String>()\n    val myIntDictionary = RealmDictionary<Int>()\n    val myFloatDictionary = RealmDictionary<Float>()\n    val myLongDictionary = RealmDictionary<Long>()\n    val myShortDictionary = RealmDictionary<Short>()\n    val myDoubleDictionary = RealmDictionary<Double>()\n    val myByteDictionary = RealmDictionary<Byte>()\n    val myBinaryDictionary = RealmDictionary<ByteArray>()\n    val myDateDictionary = RealmDictionary<Date>()\n    val myObjectIdDictionary = RealmDictionary<ObjectId>()\n    val myUUIDDictionary = RealmDictionary<UUID>()\n    val myDecimal128Dictionary = RealmDictionary<Decimal128>()\n    val myRealmAnyDictionary = RealmDictionary<RealmAny>()\n\n    companion object {\n        const val CLASS_NAME = \"DictionaryContainerClass\"\n    }\n}\n\nopen class EmbeddedObjectDictionaryContainerClass : RealmObject() {\n    val myEmbeddedObjectDictionary = RealmDictionary<EmbeddedSimpleChild>()\n}\n\nopen class PrimaryKeyDictionaryContainer : RealmObject() {\n    @PrimaryKey\n    var name = \"\"\n\n    val myRealmModelDictionary = RealmDictionary<DogPrimaryKey>()\n    val myBooleanDictionary = RealmDictionary<Boolean>()\n    val myStringDictionary = RealmDictionary<String>()\n    val myIntDictionary = RealmDictionary<Int>()\n    val myFloatDictionary = RealmDictionary<Float>()\n    val myLongDictionary = RealmDictionary<Long>()\n    val myShortDictionary = RealmDictionary<Short>()\n    val myDoubleDictionary = RealmDictionary<Double>()\n    val myByteDictionary = RealmDictionary<Byte>()\n    val myBinaryDictionary = RealmDictionary<ByteArray>()\n    val myDateDictionary = RealmDictionary<Date>()\n    val myObjectIdDictionary = RealmDictionary<ObjectId>()\n    val myUUIDDictionary = RealmDictionary<UUID>()\n    val myDecimal128Dictionary = RealmDictionary<Decimal128>()\n    val myRealmAnyDictionary = RealmDictionary<RealmAny>()\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/kotlin/io/realm/entities/PopulatedDictionaryClass.kt",
    "content": "/*\n * Copyright 2020 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\npackage io.realm.entities\n\nimport io.realm.*\nimport org.bson.types.Decimal128\nimport org.bson.types.ObjectId\nimport java.util.*\n\nopen class PopulatedDictionaryClass : RealmObject() {\n\n    val populatedBooleanDictionary: RealmDictionary<Boolean> =\n            RealmDictionary<Boolean>().init(listOf(KEY_HELLO to VALUE_BOOLEAN_HELLO, KEY_BYE to VALUE_BOOLEAN_BYE, KEY_NULL to null))\n    val populatedStringDictionary: RealmDictionary<String> =\n            RealmDictionary<String>().init(listOf(KEY_HELLO to VALUE_STRING_HELLO, KEY_BYE to VALUE_STRING_BYE, KEY_NULL to null))\n    val populatedIntDictionary: RealmDictionary<Int> =\n            RealmDictionary<Int>().init(listOf(KEY_HELLO to VALUE_NUMERIC_HELLO, KEY_BYE to VALUE_NUMERIC_BYE, KEY_NULL to null))\n    val populatedFloatDictionary: RealmDictionary<Float> =\n            RealmDictionary<Float>().init(listOf(KEY_HELLO to VALUE_NUMERIC_HELLO.toFloat(), KEY_BYE to VALUE_NUMERIC_BYE.toFloat(), KEY_NULL to null))\n    val populatedLongDictionary: RealmDictionary<Long> =\n            RealmDictionary<Long>().init(listOf(KEY_HELLO to VALUE_NUMERIC_HELLO.toLong(), KEY_BYE to VALUE_NUMERIC_BYE.toLong(), KEY_NULL to null))\n    val populatedShortDictionary: RealmDictionary<Short> =\n            RealmDictionary<Short>().init(listOf(KEY_HELLO to VALUE_NUMERIC_HELLO.toShort(), KEY_BYE to VALUE_NUMERIC_BYE.toShort(), KEY_NULL to null))\n    val populatedDoubleDictionary: RealmDictionary<Double> =\n            RealmDictionary<Double>().init(listOf(KEY_HELLO to VALUE_NUMERIC_HELLO.toDouble(), KEY_BYE to VALUE_NUMERIC_BYE.toDouble(), KEY_NULL to null))\n    val populatedByteDictionary: RealmDictionary<Byte> =\n            RealmDictionary<Byte>().init(listOf(KEY_HELLO to VALUE_NUMERIC_HELLO.toByte(), KEY_BYE to VALUE_NUMERIC_BYE.toByte(), KEY_NULL to null))\n    val populatedBinaryDictionary: RealmDictionary<ByteArray> =\n            RealmDictionary<ByteArray>().init(listOf(KEY_HELLO to VALUE_BINARY_HELLO, KEY_BYE to VALUE_BINARY_BYE, KEY_NULL to null))\n    val populatedDateDictionary: RealmDictionary<Date> =\n            RealmDictionary<Date>().init(listOf(KEY_HELLO to VALUE_DATE_HELLO, KEY_BYE to VALUE_DATE_BYE, KEY_NULL to null))\n    val populatedObjectIdDictionary: RealmDictionary<ObjectId> =\n            RealmDictionary<ObjectId>().init(listOf(KEY_HELLO to VALUE_OBJECT_ID_HELLO, KEY_BYE to VALUE_OBJECT_ID_BYE, KEY_NULL to null))\n    val populatedUUIDDictionary: RealmDictionary<UUID> =\n            RealmDictionary<UUID>().init(listOf(KEY_HELLO to VALUE_UUID_HELLO, KEY_BYE to VALUE_UUID_BYE, KEY_NULL to null))\n    val populatedDecimal128Dictionary: RealmDictionary<Decimal128> =\n            RealmDictionary<Decimal128>().init(listOf(KEY_HELLO to VALUE_DECIMAL128_HELLO, KEY_BYE to VALUE_DECIMAL128_BYE, KEY_NULL to null))\n    val populatedRealmModelDictionary: RealmDictionary<DogPrimaryKey> =\n            RealmDictionary<DogPrimaryKey>().init(listOf(KEY_HELLO to VALUE_LINK_HELLO, KEY_BYE to VALUE_LINK_BYE, KEY_NULL to null))\n    val populatedRealmAnyDictionary: RealmDictionary<RealmAny> =\n            RealmAny.Type.values()\n                    .map { realmAnyType ->\n                        DictionaryKey.values().map { key ->\n                            Pair(\"${key.name}_${realmAnyType.name}\", getRealmAnyForType(realmAnyType, key))\n                        }\n                    }\n                    .flatten()\n                    .let { keyValuePairs ->\n                        RealmDictionary<RealmAny>().init(keyValuePairs)\n                    }\n\n    companion object {\n        const val CLASS_NAME = \"PopulatedDictionaryClass\"\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/kotlin/io/realm/entities/RealmAnyDefaultNonPK.kt",
    "content": "/*\n * Copyright 2020 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\npackage io.realm.entities\n\nimport io.realm.RealmAny\nimport io.realm.RealmObject\n\nopen class RealmAnyDefaultNonPK : RealmObject() {\n    companion object {\n        const val FIELD_REALM_ANY = \"realmAny\"\n    }\n\n    var realmAny: RealmAny? = RealmAny.valueOf(RealmAnyNotIndexed())\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/kotlin/io/realm/entities/RealmAnyDefaultPK.kt",
    "content": "/*\n * Copyright 2020 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\npackage io.realm.entities\n\nimport io.realm.RealmAny\nimport io.realm.RealmObject\n\nopen class RealmAnyDefaultPK : RealmObject() {\n    companion object {\n        const val FIELD_REALM_ANY = \"realmAny\"\n        const val NAME = \"hello world\"\n    }\n\n    var realmAny: RealmAny? = RealmAny.valueOf(PrimaryKeyAsString(NAME))\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/kotlin/io/realm/entities/RealmAnyIndexed.kt",
    "content": "/*\n * Copyright 2020 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\npackage io.realm.entities\n\nimport io.realm.RealmAny\nimport io.realm.RealmObject\nimport io.realm.annotations.Index\n\nopen class RealmAnyIndexed : RealmObject() {\n    companion object {\n        const val FIELD_REALM_ANY = \"realmAny\"\n        const val CLASS_NAME = \"RealmAnyIndexed\"\n    }\n\n    @Index\n    var realmAny: RealmAny? = null\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/kotlin/io/realm/entities/RealmAnyNotIndexed.kt",
    "content": "/*\n * Copyright 2020 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\npackage io.realm.entities\n\nimport io.realm.RealmAny\nimport io.realm.RealmObject\n\nopen class RealmAnyNotIndexed(\n        var realmAny: RealmAny? = RealmAny.nullValue()\n) : RealmObject() {\n    companion object {\n        const val CLASS_NAME = \"RealmAnyNotIndexed\"\n        const val FIELD_REALM_ANY = \"realmAny\"\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/kotlin/io/realm/entities/RealmAnyNotIndexedWithPK.kt",
    "content": "/*\n * Copyright 2020 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\npackage io.realm.entities\n\nimport io.realm.RealmAny\nimport io.realm.RealmObject\nimport io.realm.annotations.PrimaryKey\n\nopen class RealmAnyNotIndexedWithPK(@PrimaryKey var pk: Long) : RealmObject() {\n    companion object {\n        const val FIELD_REALM_ANY = \"realmAny\"\n    }\n\n    constructor(): this(0)\n\n    var realmAny: RealmAny? = RealmAny.nullValue()\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/kotlin/io/realm/entities/RealmAnyRealmListWithPK.kt",
    "content": "/*\n * Copyright 2020 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\npackage io.realm.entities\n\nimport io.realm.RealmAny\nimport io.realm.RealmList\nimport io.realm.RealmObject\nimport io.realm.annotations.PrimaryKey\n\nopen class RealmAnyRealmListWithPK(@PrimaryKey var pk: Long) : RealmObject() {\n    companion object {\n        const val CLASS_NAME = \"RealmAnyRealmListWithPK\"\n        const val FIELD_REALM_ANY = \"realmAnyList\"\n        const val PK = \"pk\"\n    }\n\n    constructor(): this(0)\n\n    var realmAnyList: RealmList<RealmAny> = RealmList()\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/kotlin/io/realm/entities/SetAllTypes.java",
    "content": "/*\n * Copyright 2021 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\npackage io.realm.entities;\n\nimport org.bson.types.Decimal128;\nimport org.bson.types.ObjectId;\n\nimport java.util.Date;\nimport java.util.UUID;\n\nimport io.realm.RealmAny;\nimport io.realm.RealmObject;\nimport io.realm.RealmSet;\nimport io.realm.annotations.Required;\n\npublic class SetAllTypes extends RealmObject {\n    public static final String NAME = \"SetAllTypes\";\n\n    private RealmSet<Boolean> columnBooleanSet;\n    private RealmSet<String> columnStringSet;\n    private RealmSet<Integer> columnIntegerSet;\n    private RealmSet<Float> columnFloatSet;\n    private RealmSet<Long> columnLongSet;\n    private RealmSet<Short> columnShortSet;\n    private RealmSet<Double> columnDoubleSet;\n    private RealmSet<Byte> columnByteSet;\n    private RealmSet<byte[]> columnBinarySet;\n    private RealmSet<Date> columnDateSet;\n    private RealmSet<ObjectId> columnObjectIdSet;\n    private RealmSet<UUID> columnUUIDSet;\n    private RealmSet<Decimal128> columnDecimal128Set;\n    private RealmSet<DogPrimaryKey> columnRealmModelSet;\n    private RealmSet<Owner> columnRealmModelNoPkSet;\n    private RealmSet<RealmAny> columnRealmAnySet;\n\n\n    public String columnString;\n\n    @Required\n    private RealmSet<Boolean> columnRequiredBooleanSet;\n    @Required\n    private RealmSet<String> columnRequiredStringSet;\n    @Required\n    private RealmSet<Integer> columnRequiredIntegerSet;\n    @Required\n    private RealmSet<Float> columnRequiredFloatSet;\n    @Required\n    private RealmSet<Long> columnRequiredLongSet;\n    @Required\n    private RealmSet<Short> columnRequiredShortSet;\n    @Required\n    private RealmSet<Double> columnRequiredDoubleSet;\n    @Required\n    private RealmSet<Byte> columnRequiredByteSet;\n    @Required\n    private RealmSet<byte[]> columnRequiredBinarySet;\n    @Required\n    private RealmSet<Date> columnRequiredDateSet;\n    @Required\n    private RealmSet<ObjectId> columnRequiredObjectIdSet;\n    @Required\n    private RealmSet<UUID> columnRequiredUUIDSet;\n    @Required\n    private RealmSet<Decimal128> columnRequiredDecimal128Set;\n\n    public RealmSet<Boolean> getColumnBooleanSet() {\n        return columnBooleanSet;\n    }\n\n    public void setColumnBooleanSet(RealmSet<Boolean> columnBooleanSet) {\n        this.columnBooleanSet = columnBooleanSet;\n    }\n\n    public RealmSet<String> getColumnStringSet() {\n        return columnStringSet;\n    }\n\n    public void setColumnStringSet(RealmSet<String> columnStringSet) {\n        this.columnStringSet = columnStringSet;\n    }\n\n    public RealmSet<Integer> getColumnIntegerSet() {\n        return columnIntegerSet;\n    }\n\n    public void setColumnIntegerSet(RealmSet<Integer> columnIntegerSet) {\n        this.columnIntegerSet = columnIntegerSet;\n    }\n\n    public RealmSet<Float> getColumnFloatSet() {\n        return columnFloatSet;\n    }\n\n    public void setColumnFloatSet(RealmSet<Float> columnFloatSet) {\n        this.columnFloatSet = columnFloatSet;\n    }\n\n    public RealmSet<Long> getColumnLongSet() {\n        return columnLongSet;\n    }\n\n    public void setColumnLongSet(RealmSet<Long> columnLongSet) {\n        this.columnLongSet = columnLongSet;\n    }\n\n    public RealmSet<Short> getColumnShortSet() {\n        return columnShortSet;\n    }\n\n    public void setColumnShortSet(RealmSet<Short> columnShortSet) {\n        this.columnShortSet = columnShortSet;\n    }\n\n    public RealmSet<Double> getColumnDoubleSet() {\n        return columnDoubleSet;\n    }\n\n    public void setColumnDoubleSet(RealmSet<Double> columnDoubleSet) {\n        this.columnDoubleSet = columnDoubleSet;\n    }\n\n    public RealmSet<Byte> getColumnByteSet() {\n        return columnByteSet;\n    }\n\n    public void setColumnByteSet(RealmSet<Byte> columnByteSet) {\n        this.columnByteSet = columnByteSet;\n    }\n\n    public RealmSet<byte[]> getColumnBinarySet() {\n        return columnBinarySet;\n    }\n\n    public void setColumnBinarySet(RealmSet<byte[]> columnBinarySet) {\n        this.columnBinarySet = columnBinarySet;\n    }\n\n    public RealmSet<Date> getColumnDateSet() {\n        return columnDateSet;\n    }\n\n    public void setColumnDateSet(RealmSet<Date> columnDateSet) {\n        this.columnDateSet = columnDateSet;\n    }\n\n    public RealmSet<ObjectId> getColumnObjectIdSet() {\n        return columnObjectIdSet;\n    }\n\n    public void setColumnObjectIdSet(RealmSet<ObjectId> columnObjectIdSet) {\n        this.columnObjectIdSet = columnObjectIdSet;\n    }\n\n    public RealmSet<UUID> getColumnUUIDSet() {\n        return columnUUIDSet;\n    }\n\n    public void setColumnUUIDSet(RealmSet<UUID> columnUUIDSet) {\n        this.columnUUIDSet = columnUUIDSet;\n    }\n\n    public RealmSet<Decimal128> getColumnDecimal128Set() {\n        return columnDecimal128Set;\n    }\n\n    public void setColumnDecimal128Set(RealmSet<Decimal128> columnDecimal128Set) {\n        this.columnDecimal128Set = columnDecimal128Set;\n    }\n\n    public RealmSet<DogPrimaryKey> getColumnRealmModelSet() {\n        return columnRealmModelSet;\n    }\n\n    public void setColumnRealmModelSet(RealmSet<DogPrimaryKey> columnRealmModelSet) {\n        this.columnRealmModelSet = columnRealmModelSet;\n    }\n\n    public RealmSet<Owner> getColumnRealmModelNoPkSet() {\n        return columnRealmModelNoPkSet;\n    }\n\n    public void setColumnRealmModelNoPkSet(RealmSet<Owner> columnRealmModelNoPkSet) {\n        this.columnRealmModelNoPkSet = columnRealmModelNoPkSet;\n    }\n\n    public RealmSet<RealmAny> getColumnRealmAnySet() {\n        return columnRealmAnySet;\n    }\n\n    public void setColumnRealmAnySet(RealmSet<RealmAny> columnRealmAnySet) {\n        this.columnRealmAnySet = columnRealmAnySet;\n    }\n\n    public RealmSet<Boolean> getColumnRequiredBooleanSet() {\n        return columnRequiredBooleanSet;\n    }\n\n    public void setColumnRequiredBooleanSet(RealmSet<Boolean> columnRequiredBooleanSet) {\n        this.columnRequiredBooleanSet = columnRequiredBooleanSet;\n    }\n\n    public RealmSet<String> getColumnRequiredStringSet() {\n        return columnRequiredStringSet;\n    }\n\n    public void setColumnRequiredStringSet(RealmSet<String> columnRequiredStringSet) {\n        this.columnRequiredStringSet = columnRequiredStringSet;\n    }\n\n    public RealmSet<Integer> getColumnRequiredIntegerSet() {\n        return columnRequiredIntegerSet;\n    }\n\n    public void setColumnRequiredIntegerSet(RealmSet<Integer> columnRequiredIntegerSet) {\n        this.columnRequiredIntegerSet = columnRequiredIntegerSet;\n    }\n\n    public RealmSet<Float> getColumnRequiredFloatSet() {\n        return columnRequiredFloatSet;\n    }\n\n    public void setColumnRequiredFloatSet(RealmSet<Float> columnRequiredFloatSet) {\n        this.columnRequiredFloatSet = columnRequiredFloatSet;\n    }\n\n    public RealmSet<Long> getColumnRequiredLongSet() {\n        return columnRequiredLongSet;\n    }\n\n    public void setColumnRequiredLongSet(RealmSet<Long> columnRequiredLongSet) {\n        this.columnRequiredLongSet = columnRequiredLongSet;\n    }\n\n    public RealmSet<Short> getColumnRequiredShortSet() {\n        return columnRequiredShortSet;\n    }\n\n    public void setColumnRequiredShortSet(RealmSet<Short> columnRequiredShortSet) {\n        this.columnRequiredShortSet = columnRequiredShortSet;\n    }\n\n    public RealmSet<Double> getColumnRequiredDoubleSet() {\n        return columnRequiredDoubleSet;\n    }\n\n    public void setColumnRequiredDoubleSet(RealmSet<Double> columnRequiredDoubleSet) {\n        this.columnRequiredDoubleSet = columnRequiredDoubleSet;\n    }\n\n    public RealmSet<Byte> getColumnRequiredByteSet() {\n        return columnRequiredByteSet;\n    }\n\n    public void setColumnRequiredByteSet(RealmSet<Byte> columnRequiredByteSet) {\n        this.columnRequiredByteSet = columnRequiredByteSet;\n    }\n\n    public RealmSet<byte[]> getColumnRequiredBinarySet() {\n        return columnRequiredBinarySet;\n    }\n\n    public void setColumnRequiredBinarySet(RealmSet<byte[]> columnRequiredBinarySet) {\n        this.columnRequiredBinarySet = columnRequiredBinarySet;\n    }\n\n    public RealmSet<Date> getColumnRequiredDateSet() {\n        return columnRequiredDateSet;\n    }\n\n    public void setColumnRequiredDateSet(RealmSet<Date> columnRequiredDateSet) {\n        this.columnRequiredDateSet = columnRequiredDateSet;\n    }\n\n    public RealmSet<ObjectId> getColumnRequiredObjectIdSet() {\n        return columnRequiredObjectIdSet;\n    }\n\n    public void setColumnRequiredObjectIdSet(RealmSet<ObjectId> columnRequiredObjectIdSet) {\n        this.columnRequiredObjectIdSet = columnRequiredObjectIdSet;\n    }\n\n    public RealmSet<UUID> getColumnRequiredUUIDSet() {\n        return columnRequiredUUIDSet;\n    }\n\n    public void setColumnRequiredUUIDSet(RealmSet<UUID> columnRequiredUUIDSet) {\n        this.columnRequiredUUIDSet = columnRequiredUUIDSet;\n    }\n\n    public RealmSet<Decimal128> getColumnRequiredDecimal128Set() {\n        return columnRequiredDecimal128Set;\n    }\n\n    public void setColumnRequiredDecimal128Set(RealmSet<Decimal128> columnRequiredDecimal128Set) {\n        this.columnRequiredDecimal128Set = columnRequiredDecimal128Set;\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/kotlin/io/realm/entities/SetAllTypesPrimaryKey.java",
    "content": "/*\n * Copyright 2021 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\npackage io.realm.entities;\n\nimport org.bson.types.Decimal128;\nimport org.bson.types.ObjectId;\n\nimport java.util.Date;\nimport java.util.UUID;\n\nimport io.realm.RealmAny;\nimport io.realm.RealmObject;\nimport io.realm.RealmSet;\nimport io.realm.annotations.PrimaryKey;\n\npublic class SetAllTypesPrimaryKey extends RealmObject {\n\n    @PrimaryKey\n    private long columnLong;\n\n    public RealmSet<Boolean> columnBooleanSet;\n    public RealmSet<String> columnStringSet;\n    public RealmSet<Integer> columnIntegerSet;\n    public RealmSet<Float> columnFloatSet;\n    public RealmSet<Long> columnLongSet;\n    public RealmSet<Short> columnShortSet;\n    public RealmSet<Double> columnDoubleSet;\n    public RealmSet<Byte> columnByteSet;\n    public RealmSet<byte[]> columnBinarySet;\n    public RealmSet<Date> columnDateSet;\n    public RealmSet<ObjectId> columnObjectIdSet;\n    public RealmSet<UUID> columnUUIDSet;\n    public RealmSet<Decimal128> columnDecimal128Set;\n    public RealmSet<DogPrimaryKey> columnRealmModelSet;\n    public RealmSet<Owner> columnRealmModelNoPkSet;\n    public RealmSet<RealmAny> columnRealmAnySet;\n\n    public long getColumnLong() {\n        return columnLong;\n    }\n\n    public void setColumnLong(long columnLong) {\n        this.columnLong = columnLong;\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/kotlin/io/realm/entities/SetContainerClass.kt",
    "content": "/*\n * Copyright 2021 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\npackage io.realm.entities\n\nimport io.realm.RealmAny\nimport io.realm.RealmList\nimport io.realm.RealmObject\nimport io.realm.RealmSet\nimport io.realm.annotations.PrimaryKey\nimport org.bson.types.Decimal128\nimport org.bson.types.ObjectId\nimport java.util.*\n\nopen class SetContainerClass : RealmObject() {\n\n    val myRealmModelNoPkSet = RealmSet<Owner>()\n    val myRealmModelSet = RealmSet<DogPrimaryKey>()\n    val myBooleanSet = RealmSet<Boolean>()\n    val myStringSet = RealmSet<String>()\n    val myIntSet = RealmSet<Int>()\n    val myFloatSet = RealmSet<Float>()\n    val myLongSet = RealmSet<Long>()\n    val myShortSet = RealmSet<Short>()\n    val myDoubleSet = RealmSet<Double>()\n    val myByteSet = RealmSet<Byte>()\n    val myBinarySet = RealmSet<ByteArray>()\n    val myDateSet = RealmSet<Date>()\n    val myObjectIdSet = RealmSet<ObjectId>()\n    val myUUIDSet = RealmSet<UUID>()\n    val myDecimal128Set = RealmSet<Decimal128>()\n    val myRealmAnySet = RealmSet<RealmAny>()\n\n    val myRealmModelNoPkList = RealmList<Owner>()\n    val myRealmModelList = RealmList<DogPrimaryKey>()\n    val myBooleanList = RealmList<Boolean>()\n    val myStringList = RealmList<String>()\n    val myIntList = RealmList<Int>()\n    val myFloatList = RealmList<Float>()\n    val myLongList = RealmList<Long>()\n    val myShortList = RealmList<Short>()\n    val myDoubleList = RealmList<Double>()\n    val myByteList = RealmList<Byte>()\n    val myBinaryList = RealmList<ByteArray>()\n    val myDateList = RealmList<Date>()\n    val myObjectIdList = RealmList<ObjectId>()\n    val myUUIDList = RealmList<UUID>()\n    val myDecimal128List = RealmList<Decimal128>()\n    val myRealmAnyList = RealmList<RealmAny>()\n\n    companion object {\n        const val CLASS_NAME = \"SetContainerClass\"\n    }\n}\n\nopen class SetContainerMigrationClass : RealmObject() {\n\n    @PrimaryKey\n    var id: String? = \"\"\n\n    val myRealmModelSet = RealmSet<StringOnly>()\n    val myBooleanSet = RealmSet<Boolean>()\n    val myStringSet = RealmSet<String>()\n    val myIntSet = RealmSet<Int>()\n    val myFloatSet = RealmSet<Float>()\n    val myLongSet = RealmSet<Long>()\n    val myShortSet = RealmSet<Short>()\n    val myDoubleSet = RealmSet<Double>()\n    val myByteSet = RealmSet<Byte>()\n    val myBinarySet = RealmSet<ByteArray>()\n    val myDateSet = RealmSet<Date>()\n    val myObjectIdSet = RealmSet<ObjectId>()\n    val myUUIDSet = RealmSet<UUID>()\n    val myDecimal128Set = RealmSet<Decimal128>()\n    val myRealmAnySet = RealmSet<RealmAny>()\n\n    companion object {\n        const val CLASS_NAME = \"SetContainerMigrationClass\"\n    }\n}\n\nopen class SetContainerAfterMigrationClass : RealmObject() {\n\n    @PrimaryKey\n    var id: String? = \"\"\n\n    companion object {\n        const val CLASS_NAME = \"SetContainerAfterMigrationClass\"\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/kotlin/io/realm/entities/embedded/EmbeddedSimpleChild.kt",
    "content": "/*\n * Copyright 2020 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 */\npackage io.realm.entities.embedded\n\nimport io.realm.RealmObject\nimport io.realm.annotations.LinkingObjects\nimport io.realm.annotations.RealmClass\nimport java.util.*\n\n/**\n * The embedded object part of a simple object graph. This object can have two parents\n * [EmbeddedSimpleParent] and [EmbeddedSimpleListParent].\n */\n@RealmClass(embedded = true)\nopen class EmbeddedSimpleChild(var childId: String = UUID.randomUUID().toString()) : RealmObject() {\n\n    @LinkingObjects(\"child\")\n    val parent = EmbeddedSimpleParent()\n\n    companion object {\n        const val NAME = \"EmbeddedSimpleChild\"\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/kotlin/io/realm/entities/embedded/EmbeddedSimpleListParent.kt",
    "content": "/*\n * Copyright 2020 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 */\npackage io.realm.entities.embedded\n\nimport io.realm.RealmList\nimport io.realm.RealmObject\nimport io.realm.annotations.PrimaryKey\nimport java.util.*\n\n// Top-level object describing a simple embedded objects structure consisting of only a\n// list of embedded objects.\nopen class EmbeddedSimpleListParent(@PrimaryKey var _id: String = UUID.randomUUID().toString()) : RealmObject() {\n    var children: RealmList<EmbeddedSimpleChild> = RealmList()\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/kotlin/io/realm/entities/embedded/EmbeddedSimpleListParentWithoutPrimaryKey.kt",
    "content": "/*\n * Copyright 2020 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 */\npackage io.realm.entities.embedded\n\nimport io.realm.RealmList\nimport io.realm.RealmObject\nimport io.realm.annotations.PrimaryKey\nimport java.util.*\n\n// Top-level object describing a simple embedded objects structure consisting of only a\n// list of embedded objects.\nopen class EmbeddedSimpleListParentWithoutPrimaryKey(var _id: String = UUID.randomUUID().toString()) : RealmObject() {\n    var children: RealmList<EmbeddedSimpleChild> = RealmList()\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/kotlin/io/realm/entities/embedded/EmbeddedSimpleParent.kt",
    "content": "/*\n * Copyright 2020 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 */\npackage io.realm.entities.embedded\n\nimport io.realm.RealmObject\nimport io.realm.annotations.PrimaryKey\nimport java.util.*\n\n// Top-level object describing a simple embedded objects structure consisting of only an object reference.\nopen class EmbeddedSimpleParent(@PrimaryKey var _id: String = UUID.randomUUID().toString()) : RealmObject() {\n    companion object {\n        const val NAME = \"EmbeddedSimpleParent\"\n        const val CHILD = \"child\"\n    }\n\n    var child: EmbeddedSimpleChild? = null\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/kotlin/io/realm/entities/embedded/EmbeddedTreeLeaf.kt",
    "content": "/*\n * Copyright 2020 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 */\npackage io.realm.entities.embedded\n\nimport io.realm.RealmObject\nimport io.realm.annotations.LinkingObjects\nimport io.realm.annotations.PrimaryKey\nimport io.realm.annotations.RealmClass\nimport java.util.*\n\n// Middle-level node in a object-graph that is three-shaped, i.e. no circular references.\n// The tree depth can be described as:\n// - 1 TreeParent\n// - 1 or more TreeNode's. I.e. a TreeNode can be the child of another TreeNode.\n// - 1 or more TreeLeaf objects. TreeLeaf objects are always at the bottom of tree.\n@RealmClass(embedded = true)\nopen class EmbeddedTreeLeaf(var treeLeafId: String = UUID.randomUUID().toString()) : RealmObject() {\n\n    @LinkingObjects(\"leafNode\")\n    val parentRef: EmbeddedTreeNode? = null\n\n    @LinkingObjects(\"leafNodeList\")\n    val parentListRef: EmbeddedTreeNode? = null\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/kotlin/io/realm/entities/embedded/EmbeddedTreeNode.kt",
    "content": "/*\n * Copyright 2020 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 */\npackage io.realm.entities.embedded\n\nimport io.realm.RealmList\nimport io.realm.RealmObject\nimport io.realm.annotations.PrimaryKey\nimport io.realm.annotations.RealmClass\nimport java.util.*\n\n// Middle-level node in a object-graph that is three-shaped, i.e. no circular references.\n// The tree depth can be described as:\n// - 1 TreeParent\n// - 1 or more TreeLeaf objects. TreeLeaf objects are always at the bottom of tree.\n@RealmClass(embedded = true)\nopen class EmbeddedTreeNode(var treeNodeId: String = UUID.randomUUID().toString()) : RealmObject() {\n    var leafNode: EmbeddedTreeLeaf? = null\n    var leafNodeList: RealmList<EmbeddedTreeLeaf> = RealmList()\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/kotlin/io/realm/entities/embedded/EmbeddedTreeParent.kt",
    "content": "/*\n * Copyright 2020 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 */\npackage io.realm.entities.embedded\n\nimport io.realm.RealmList\nimport io.realm.RealmObject\nimport io.realm.annotations.PrimaryKey\nimport java.util.*\n\n// Top-level node in a object-graph that is three-shaped, i.e. no circular references.\n// The tree depth can be described as:\n// - 1 TreeParent\n// - 1 or more TreeNodes. I.e. a TreeNode can be the child of another TreeNode.\n// - 1 or more TreeLeaf objects. TreeLeaf objects are always at the bottom of tree.\nopen class EmbeddedTreeParent(@PrimaryKey var _id: String = UUID.randomUUID().toString()) : RealmObject() {\n    var middleNode: EmbeddedTreeNode? = null\n    var middleNodeList: RealmList<EmbeddedTreeNode> = RealmList()\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/kotlin/io/realm/entities/embedded/EmbeddedWithConstructorArgs.kt",
    "content": "/*\n * Copyright 2020 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 */\npackage io.realm.entities.embedded\n\nimport io.realm.RealmObject\nimport io.realm.annotations.Ignore\n\nopen class EmbeddedWithConstructorArgs : RealmObject() {\n    var child: EmbeddedSimpleChild? = null\n    init {\n        child = EmbeddedSimpleChild(INNER_CHILD_ID)\n    }\n\n    companion object {\n        const val INNER_CHILD_ID = \"innerChild\"\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/kotlin/io/realm/entities/embedded/SimpleEmbeddedObject.kt",
    "content": "package io.realm.entities.embedded\n\nimport io.realm.RealmObject\nimport io.realm.annotations.RealmClass\n\n@RealmClass(embedded = true)\nopen class SimpleEmbeddedObject() : RealmObject() {\n    var name: String = \"a simple attribute\"\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/kotlin/io/realm/realmany/DynamicRealmAnyTests.kt",
    "content": "/*\n * Copyright 2020 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\npackage io.realm.realmany\n\nimport androidx.test.ext.junit.runners.AndroidJUnit4\nimport androidx.test.platform.app.InstrumentationRegistry\nimport io.realm.*\nimport org.bson.types.Decimal128\nimport org.bson.types.ObjectId\nimport org.junit.After\nimport org.junit.Before\nimport org.junit.Rule\nimport org.junit.Test\nimport org.junit.rules.TemporaryFolder\nimport org.junit.runner.RunWith\nimport java.util.*\nimport kotlin.test.assertEquals\nimport kotlin.test.assertNotNull\nimport kotlin.test.assertTrue\n\n@RunWith(AndroidJUnit4::class)\nclass DynamicRealmAnyTests {\n    @get:Rule\n    val configFactory = TestRealmConfigurationFactory()\n\n    @Rule\n    @JvmField\n    val folder = TemporaryFolder()\n\n    private lateinit var realm: DynamicRealm\n\n    init {\n        Realm.init(InstrumentationRegistry.getInstrumentation().targetContext)\n    }\n\n    @Before\n    fun setUp() {\n        realm = DynamicRealm.getInstance(configFactory.createConfiguration(\"RealmAny\"))\n\n        realm.executeTransaction {\n            realm.schema\n                    .create(\"RealmAnyObject\")\n                    .addField(\"myRealmAny\", RealmAny::class.java)\n\n            realm.schema\n                    .create(\"RealmAnyListObject\")\n                    .addRealmListField(\"aList\", RealmAny::class.java)\n\n            realm.schema\n                    .create(\"ObjectString\")\n                    .addField(\"aString\", String::class.java, FieldAttribute.PRIMARY_KEY)\n        }\n    }\n\n    @After\n    fun tearDown() {\n        realm.close()\n    }\n\n    @Test\n    fun writeRead_primitive() {\n        realm.beginTransaction()\n\n        val anObject = realm.createObject(\"RealmAnyObject\")\n        anObject.setRealmAny(\"myRealmAny\", RealmAny.valueOf(Date(10)))\n\n        realm.commitTransaction()\n\n        val myRealmAny = anObject.getRealmAny(\"myRealmAny\")\n\n        assertEquals(Date(10), myRealmAny.asDate())\n        assertEquals(RealmAny.valueOf(Date(10)), myRealmAny)\n\n        realm.close()\n    }\n\n    @Test\n    fun defaultNullValue() {\n        realm.beginTransaction()\n\n        val anObject = realm.createObject(\"RealmAnyObject\")\n\n        realm.commitTransaction()\n\n        val myRealmAny = anObject.getRealmAny(\"myRealmAny\")\n\n        assertNotNull(myRealmAny)\n        assertTrue(myRealmAny.isNull)\n        assertEquals(RealmAny.nullValue(), myRealmAny)\n        assertEquals(RealmAny.Type.NULL, myRealmAny.type)\n    }\n\n    @Test\n    fun setNullValue() {\n        realm.beginTransaction()\n\n        val anObject = realm.createObject(\"RealmAnyObject\")\n        anObject.setRealmAny(\"myRealmAny\", RealmAny.nullValue())\n\n        realm.commitTransaction()\n\n        val myRealmAny = anObject.getRealmAny(\"myRealmAny\")\n\n        assertTrue(myRealmAny.isNull)\n        assertEquals(RealmAny.Type.NULL, myRealmAny.type)\n    }\n\n    @Test\n    fun writeRead_model() {\n        realm.beginTransaction()\n\n        val innerObject = realm.createObject(\"RealmAnyObject\")\n        innerObject.setRealmAny(\"myRealmAny\", RealmAny.valueOf(Date(10)))\n\n        val outerObject = realm.createObject(\"RealmAnyObject\")\n        outerObject.setRealmAny(\"myRealmAny\", RealmAny.valueOf(innerObject))\n\n        realm.commitTransaction()\n\n        val innerRealmAny = innerObject.getRealmAny(\"myRealmAny\")\n        val outerRealmAny = outerObject.getRealmAny(\"myRealmAny\")\n\n        assertEquals(Date(10), innerRealmAny.asDate())\n        assertEquals(DynamicRealmObject::class.java, outerRealmAny.valueClass)\n\n        val aRealmAny = outerRealmAny\n                .asRealmModel(DynamicRealmObject::class.java)\n                .getRealmAny(\"myRealmAny\")\n\n        assertEquals(innerRealmAny.asDate(), aRealmAny.asDate())\n    }\n\n    @Test\n    fun managed_listsAllTypes() {\n        val aString = \"a string\"\n        val byteArray = byteArrayOf(0, 1, 0)\n        val date = Date()\n        val objectId = ObjectId()\n        val decimal128 = Decimal128(1)\n        val uuid = UUID.randomUUID()\n\n        realm.executeTransaction {\n            val allJavaTypes = it.createObject(\"RealmAnyListObject\")\n            val realmAnyList = allJavaTypes.getList(\"aList\", RealmAny::class.java)\n\n            val dynamicRealmObject = it.createObject(\"ObjectString\", \"dynamic\")\n\n            realmAnyList.add(RealmAny.valueOf(true))\n            realmAnyList.add(RealmAny.valueOf(1.toByte()))\n            realmAnyList.add(RealmAny.valueOf(2.toShort()))\n            realmAnyList.add(RealmAny.valueOf(3.toInt()))\n            realmAnyList.add(RealmAny.valueOf(4.toLong()))\n            realmAnyList.add(RealmAny.valueOf(5.toFloat()))\n            realmAnyList.add(RealmAny.valueOf(6.toDouble()))\n            realmAnyList.add(RealmAny.valueOf(aString))\n            realmAnyList.add(RealmAny.valueOf(byteArray))\n            realmAnyList.add(RealmAny.valueOf(date))\n            realmAnyList.add(RealmAny.valueOf(objectId))\n            realmAnyList.add(RealmAny.valueOf(decimal128))\n            realmAnyList.add(RealmAny.valueOf(uuid))\n            realmAnyList.add(RealmAny.nullValue())\n            realmAnyList.add(null)\n            realmAnyList.add(RealmAny.valueOf(dynamicRealmObject))\n        }\n\n        val allJavaTypes = realm.where(\"RealmAnyListObject\").findFirst()\n        val realmAnyList = allJavaTypes!!.getList(\"aList\", RealmAny::class.java)\n\n        assertEquals(true, realmAnyList[0]!!.asBoolean())\n        assertEquals(1, realmAnyList[1]!!.asByte())\n        assertEquals(2, realmAnyList[2]!!.asShort())\n        assertEquals(3, realmAnyList[3]!!.asInteger())\n        assertEquals(4, realmAnyList[4]!!.asLong())\n        assertEquals(5.toFloat(), realmAnyList[5]!!.asFloat())\n        assertEquals(6.toDouble(), realmAnyList[6]!!.asDouble())\n        assertEquals(aString, realmAnyList[7]!!.asString())\n        assertTrue(Arrays.equals(byteArray, realmAnyList[8]!!.asBinary()))\n        assertEquals(date, realmAnyList[9]!!.asDate())\n        assertEquals(objectId, realmAnyList[10]!!.asObjectId())\n        assertEquals(decimal128, realmAnyList[11]!!.asDecimal128())\n        assertEquals(uuid, realmAnyList[12]!!.asUUID())\n        assertTrue(realmAnyList[13]!!.isNull)\n        assertTrue(realmAnyList[14]!!.isNull)\n\n        assertEquals(\"dynamic\", realmAnyList[15]!!.asRealmModel(DynamicRealmObject::class.java).getString(\"aString\"))\n    }\n\n\n    @Test\n    fun managed_listsInsertAllTypes() {\n        val aString = \"a string\"\n        val byteArray = byteArrayOf(0, 1, 0)\n        val date = Date()\n        val objectId = ObjectId()\n        val decimal128 = Decimal128(1)\n        val uuid = UUID.randomUUID()\n\n        realm.executeTransaction {\n            val allJavaTypes = it.createObject(\"RealmAnyListObject\")\n            val realmAnyList = allJavaTypes.getList(\"aList\", RealmAny::class.java)\n            val dynamicRealmObject = it.createObject(\"ObjectString\", \"dynamic\")\n\n            realmAnyList.add(0, RealmAny.valueOf(true))\n            realmAnyList.add(0, RealmAny.valueOf(1.toByte()))\n            realmAnyList.add(0, RealmAny.valueOf(2.toShort()))\n            realmAnyList.add(0, RealmAny.valueOf(3.toInt()))\n            realmAnyList.add(0, RealmAny.valueOf(4.toLong()))\n            realmAnyList.add(0, RealmAny.valueOf(5.toFloat()))\n            realmAnyList.add(0, RealmAny.valueOf(6.toDouble()))\n            realmAnyList.add(0, RealmAny.valueOf(aString))\n            realmAnyList.add(0, RealmAny.valueOf(byteArray))\n            realmAnyList.add(0, RealmAny.valueOf(date))\n            realmAnyList.add(0, RealmAny.valueOf(objectId))\n            realmAnyList.add(0, RealmAny.valueOf(decimal128))\n            realmAnyList.add(0, RealmAny.valueOf(uuid))\n            realmAnyList.add(0, RealmAny.nullValue())\n            realmAnyList.add(0, null)\n            realmAnyList.add(0, RealmAny.valueOf(dynamicRealmObject))\n        }\n\n        val allJavaTypes = realm.where(\"RealmAnyListObject\").findFirst()\n        val realmAnyList = allJavaTypes!!.getList(\"aList\", RealmAny::class.java)\n\n        assertEquals(true, realmAnyList[15]!!.asBoolean())\n        assertEquals(1, realmAnyList[14]!!.asByte())\n        assertEquals(2, realmAnyList[13]!!.asShort())\n        assertEquals(3, realmAnyList[12]!!.asInteger())\n        assertEquals(4, realmAnyList[11]!!.asLong())\n        assertEquals(5.toFloat(), realmAnyList[10]!!.asFloat())\n        assertEquals(6.toDouble(), realmAnyList[9]!!.asDouble())\n        assertEquals(aString, realmAnyList[8]!!.asString())\n        assertTrue(Arrays.equals(byteArray, realmAnyList[7]!!.asBinary()))\n        assertEquals(date, realmAnyList[6]!!.asDate())\n        assertEquals(objectId, realmAnyList[5]!!.asObjectId())\n        assertEquals(decimal128, realmAnyList[4]!!.asDecimal128())\n        assertEquals(uuid, realmAnyList[3]!!.asUUID())\n        assertTrue(realmAnyList[2]!!.isNull)\n        assertTrue(realmAnyList[1]!!.isNull)\n        assertEquals(\"dynamic\", realmAnyList[0]!!.asRealmModel(DynamicRealmObject::class.java).getString(\"aString\"))\n    }\n\n    @Test\n    fun managed_listsSetAllTypes() {\n        val aString = \"a string\"\n        val byteArray = byteArrayOf(0, 1, 0)\n        val date = Date()\n        val objectId = ObjectId()\n        val decimal128 = Decimal128(1)\n        val uuid = UUID.randomUUID()\n\n        realm.executeTransaction {\n            val allJavaTypes = it.createObject(\"RealmAnyListObject\")\n            val dynamicRealmObject = it.createObject(\"ObjectString\", \"dynamic\")\n\n            val initialList = RealmList<RealmAny>()\n            initialList.addAll(arrayOfNulls(16))\n            allJavaTypes.setList(\"aList\", initialList)\n\n            val realmAnyList = allJavaTypes.getList(\"aList\", RealmAny::class.java)\n\n            realmAnyList[0] = RealmAny.valueOf(true)\n            realmAnyList[1] = RealmAny.valueOf(1.toByte())\n            realmAnyList[2] = RealmAny.valueOf(2.toShort())\n            realmAnyList[3] = RealmAny.valueOf(3.toInt())\n            realmAnyList[4] = RealmAny.valueOf(4.toLong())\n            realmAnyList[5] = RealmAny.valueOf(5.toFloat())\n            realmAnyList[6] = RealmAny.valueOf(6.toDouble())\n            realmAnyList[7] = RealmAny.valueOf(aString)\n            realmAnyList[8] = RealmAny.valueOf(byteArray)\n            realmAnyList[9] = RealmAny.valueOf(date)\n            realmAnyList[10] = RealmAny.valueOf(objectId)\n            realmAnyList[11] = RealmAny.valueOf(decimal128)\n            realmAnyList[12] = RealmAny.valueOf(uuid)\n            realmAnyList[13] = RealmAny.nullValue()\n            realmAnyList[14] = null\n            realmAnyList[15] = RealmAny.valueOf(dynamicRealmObject)\n        }\n\n        val allJavaTypes = realm.where(\"RealmAnyListObject\").findFirst()\n        val realmAnyList = allJavaTypes!!.getList(\"aList\", RealmAny::class.java)\n\n        assertEquals(true, realmAnyList[0]!!.asBoolean())\n        assertEquals(1, realmAnyList[1]!!.asByte())\n        assertEquals(2, realmAnyList[2]!!.asShort())\n        assertEquals(3, realmAnyList[3]!!.asInteger())\n        assertEquals(4, realmAnyList[4]!!.asLong())\n        assertEquals(5.toFloat(), realmAnyList[5]!!.asFloat())\n        assertEquals(6.toDouble(), realmAnyList[6]!!.asDouble())\n        assertEquals(aString, realmAnyList[7]!!.asString())\n        assertTrue(Arrays.equals(byteArray, realmAnyList[8]!!.asBinary()))\n        assertEquals(date, realmAnyList[9]!!.asDate())\n        assertEquals(objectId, realmAnyList[10]!!.asObjectId())\n        assertEquals(decimal128, realmAnyList[11]!!.asDecimal128())\n        assertEquals(uuid, realmAnyList[12]!!.asUUID())\n        assertTrue(realmAnyList[13]!!.isNull)\n        assertTrue(realmAnyList[14]!!.isNull)\n        assertEquals(\"dynamic\", realmAnyList[15]!!.asRealmModel(DynamicRealmObject::class.java).getString(\"aString\"))\n    }\n\n    @Test\n    fun managed_listsRemoveAllTypes() {\n        val aString = \"a string\"\n        val byteArray = byteArrayOf(0, 1, 0)\n        val date = Date()\n        val objectId = ObjectId()\n        val decimal128 = Decimal128(1)\n        val uuid = UUID.randomUUID()\n\n        realm.executeTransaction {\n            val allJavaTypes = it.createObject(\"RealmAnyListObject\")\n            val dynamicRealmObject = it.createObject(\"ObjectString\", \"dynamic\")\n\n            val realmAnyList = allJavaTypes.getList(\"aList\", RealmAny::class.java)\n\n            realmAnyList.add(RealmAny.valueOf(true))\n            realmAnyList.add(RealmAny.valueOf(1.toByte()))\n            realmAnyList.add(RealmAny.valueOf(2.toShort()))\n            realmAnyList.add(RealmAny.valueOf(3.toInt()))\n            realmAnyList.add(RealmAny.valueOf(4.toLong()))\n            realmAnyList.add(RealmAny.valueOf(5.toFloat()))\n            realmAnyList.add(RealmAny.valueOf(6.toDouble()))\n            realmAnyList.add(RealmAny.valueOf(aString))\n            realmAnyList.add(RealmAny.valueOf(byteArray))\n            realmAnyList.add(RealmAny.valueOf(date))\n            realmAnyList.add(RealmAny.valueOf(objectId))\n            realmAnyList.add(RealmAny.valueOf(decimal128))\n            realmAnyList.add(RealmAny.valueOf(uuid))\n            realmAnyList.add(RealmAny.nullValue())\n            realmAnyList.add(null)\n            realmAnyList.add(RealmAny.valueOf(dynamicRealmObject))\n        }\n\n        realm.executeTransaction {\n            val allJavaTypes = realm.where(\"RealmAnyListObject\").findFirst()\n            val realmAnyList = allJavaTypes!!.getList(\"aList\", RealmAny::class.java)\n\n            for (i in 0..15)\n                realmAnyList.removeAt(0)\n\n            assertEquals(0, realmAnyList.size)\n        }\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/kotlin/io/realm/realmany/RealmAnyBulkInsertsTests.kt",
    "content": "/*\n * Copyright 2020 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\npackage io.realm.realmany\n\nimport androidx.test.ext.junit.runners.AndroidJUnit4\nimport androidx.test.platform.app.InstrumentationRegistry\nimport io.realm.*\nimport io.realm.entities.*\nimport io.realm.kotlin.createObject\nimport io.realm.kotlin.where\nimport org.bson.types.Decimal128\nimport org.bson.types.ObjectId\nimport org.junit.After\nimport org.junit.Before\nimport org.junit.Rule\nimport org.junit.Test\nimport org.junit.rules.TemporaryFolder\nimport org.junit.runner.RunWith\nimport java.util.*\nimport kotlin.test.*\n\n@RunWith(AndroidJUnit4::class)\nclass RealmAnyBulkInsertsTests {\n    private lateinit var realmConfiguration: RealmConfiguration\n    private lateinit var realm: Realm\n\n    companion object {\n        const val TEST_VALUE_1 = \"hello world 1\"\n        const val TEST_VALUE_2 = \"hello world 2\"\n        const val TEST_VALUE_3 = \"hello world 3\"\n        const val TEST_VALUE_4 = \"hello world 4\"\n    }\n\n    @get:Rule\n    val configFactory = TestRealmConfigurationFactory()\n\n    init {\n        Realm.init(InstrumentationRegistry.getInstrumentation().targetContext)\n    }\n\n    @Before\n    fun setUp() {\n        realmConfiguration = configFactory.createSchemaConfiguration(\n                false,\n                RealmAnyNotIndexed::class.java,\n                RealmAnyIndexed::class.java,\n                AllJavaTypes::class.java,\n                RealmAnyRealmListWithPK::class.java,\n                RealmAnyNotIndexedWithPK::class.java,\n                PrimaryKeyAsString::class.java)\n\n        realm = Realm.getInstance(realmConfiguration)\n    }\n\n    @After\n    fun tearDown() {\n        realm.close()\n    }\n\n    private val testList1 = arrayOf(\n            RealmAny.valueOf(10.toByte()),\n            RealmAny.valueOf(20.toShort()),\n            RealmAny.valueOf(30.toInt()),\n            RealmAny.valueOf(40.toLong()),\n            RealmAny.valueOf(true),\n            RealmAny.valueOf(TEST_VALUE_1),\n            RealmAny.valueOf(byteArrayOf(0, 1, 1)),\n            RealmAny.valueOf(Date(10)),\n            RealmAny.valueOf(50.toFloat()),\n            RealmAny.valueOf(60.toDouble()),\n            RealmAny.valueOf(Decimal128(10)),\n            RealmAny.valueOf(ObjectId(Date(100))),\n            RealmAny.valueOf(UUID.randomUUID())\n    )\n\n    private val testList2 = arrayOf(\n            RealmAny.valueOf(1.toByte()),\n            RealmAny.valueOf(2.toShort()),\n            RealmAny.valueOf(3.toInt()),\n            RealmAny.valueOf(4.toLong()),\n            RealmAny.valueOf(false),\n            RealmAny.valueOf(TEST_VALUE_2),\n            RealmAny.valueOf(byteArrayOf(0, 1, 0)),\n            RealmAny.valueOf(Date(0)),\n            RealmAny.valueOf(5.toFloat()),\n            RealmAny.valueOf(6.toDouble()),\n            RealmAny.valueOf(Decimal128(1)),\n            RealmAny.valueOf(ObjectId(Date(10))),\n            RealmAny.valueOf(UUID.randomUUID())\n    )\n\n    /**\n     * RealmAny tests for Realm objects\n     */\n\n    @Test\n    fun copyFromRealm_realmModel() {\n        realm.beginTransaction()\n        val value = realm.createObject<RealmAnyNotIndexedWithPK>(0)\n\n        val inner = RealmAnyNotIndexedWithPK(1)\n        val allTypes = AllJavaTypes(0)\n        allTypes.fieldString = TEST_VALUE_1\n        val innerAllJavaTypes = AllJavaTypes(1)\n        innerAllJavaTypes.fieldString = TEST_VALUE_2\n\n        allTypes.fieldObject = innerAllJavaTypes\n\n        inner.realmAny = RealmAny.valueOf(allTypes)\n        value.realmAny = RealmAny.valueOf(inner)\n\n        realm.commitTransaction()\n\n        val copy0 = realm.copyFromRealm(value, 0)\n        val copy1 = realm.copyFromRealm(value, 1)\n        val copy2 = realm.copyFromRealm(value, 2)\n        val copy3 = realm.copyFromRealm(value, 3)\n\n        assertFalse(copy0.isManaged)\n        assertFalse(copy1.isManaged)\n        assertFalse(copy2.isManaged)\n        assertFalse(copy3.isManaged)\n\n        assertEquals(RealmAny.nullValue(), copy0.realmAny)\n        assertEquals(RealmAny.nullValue(), copy1.realmAny!!.asRealmModel(RealmAnyNotIndexedWithPK::class.java).realmAny)\n        assertEquals(TEST_VALUE_1, copy2.realmAny!!.asRealmModel(RealmAnyNotIndexedWithPK::class.java).realmAny!!.asRealmModel(AllJavaTypes::class.java).fieldString)\n        assertNull(copy2.realmAny!!.asRealmModel(RealmAnyNotIndexedWithPK::class.java).realmAny!!.asRealmModel(AllJavaTypes::class.java).fieldObject)\n\n        assertEquals(TEST_VALUE_1, copy3.realmAny!!.asRealmModel(RealmAnyNotIndexedWithPK::class.java).realmAny!!.asRealmModel(AllJavaTypes::class.java).fieldString)\n        assertNotNull(copy3.realmAny!!.asRealmModel(RealmAnyNotIndexedWithPK::class.java).realmAny!!.asRealmModel(AllJavaTypes::class.java).fieldObject)\n        assertEquals(TEST_VALUE_2, copy3.realmAny!!.asRealmModel(RealmAnyNotIndexedWithPK::class.java).realmAny!!.asRealmModel(AllJavaTypes::class.java).fieldObject.fieldString)\n    }\n\n    @Test\n    fun copyToRealm_realmModel() {\n        val value = RealmAnyNotIndexedWithPK()\n        value.realmAny = RealmAny.valueOf(PrimaryKeyAsString(TEST_VALUE_1))\n\n        realm.beginTransaction()\n        val managedValue = realm.copyToRealm(value)\n        realm.commitTransaction()\n\n        val managedInnerObject = managedValue.realmAny!!.asRealmModel(PrimaryKeyAsString::class.java)!!\n\n        assertTrue(managedInnerObject.isManaged)\n        assertEquals(TEST_VALUE_1, managedInnerObject.name)\n    }\n\n    @Test\n    fun copyToRealmOrUpdate_realmModel() {\n        realm.executeTransaction { realm ->\n            val obj = realm.createObject<RealmAnyNotIndexedWithPK>(0)\n            obj.realmAny = RealmAny.valueOf(PrimaryKeyAsString(TEST_VALUE_1))\n        }\n\n        val value = RealmAnyNotIndexedWithPK()\n        value.realmAny = RealmAny.valueOf(PrimaryKeyAsString(TEST_VALUE_2))\n\n        realm.beginTransaction()\n        val managedValue = realm.copyToRealmOrUpdate(value)\n        realm.commitTransaction()\n\n        val managedInnerObject = managedValue.realmAny!!.asRealmModel(PrimaryKeyAsString::class.java)\n        assertTrue(managedInnerObject.isManaged)\n        assertEquals(TEST_VALUE_2, managedInnerObject.name)\n    }\n\n    @Test\n    fun insert_realmModel() {\n        realm.executeTransaction { realm ->\n            val value = RealmAnyNotIndexedWithPK()\n            value.realmAny = RealmAny.valueOf(PrimaryKeyAsString(TEST_VALUE_1))\n\n            realm.insert(value)\n        }\n\n        val managedValue = realm.where<RealmAnyNotIndexedWithPK>().findFirst()!!\n        val managedInnerObject = managedValue.realmAny!!.asRealmModel(PrimaryKeyAsString::class.java)\n\n        assertTrue(managedInnerObject.isManaged)\n        assertEquals(TEST_VALUE_1, managedInnerObject.name)\n    }\n\n    @Test\n    fun insertOrUpdate_realmModel() {\n        realm.executeTransaction { realm ->\n            val value = realm.createObject<RealmAnyNotIndexedWithPK>(0)\n            value.realmAny = RealmAny.valueOf(PrimaryKeyAsString(TEST_VALUE_1))\n        }\n\n        realm.executeTransaction { realm ->\n            val value = RealmAnyNotIndexedWithPK()\n            value.realmAny = RealmAny.valueOf(PrimaryKeyAsString(TEST_VALUE_2))\n\n            realm.insertOrUpdate(value)\n        }\n\n        val all = realm.where<RealmAnyNotIndexedWithPK>().findAll()\n\n        assertEquals(1, all.size)\n\n        val managedInnerObject = all.first()!!.realmAny!!.asRealmModel(PrimaryKeyAsString::class.java)\n\n        assertTrue(managedInnerObject.isManaged)\n        assertEquals(TEST_VALUE_2, managedInnerObject.name)\n    }\n\n    /**\n     * Tests for RealmAny RealmLists\n     */\n\n    @Test\n    fun copyFromRealm_list() {\n        val list = RealmList(*testList1)\n        val inner = RealmAnyNotIndexedWithPK(1)\n        inner.realmAny = RealmAny.valueOf(PrimaryKeyAsString(TEST_VALUE_1))\n\n        list.add(RealmAny.valueOf(inner))\n\n        realm.beginTransaction()\n        val value = realm.createObject<RealmAnyRealmListWithPK>(0)\n        value.realmAnyList = list\n        realm.commitTransaction()\n\n        val copy0 = realm.copyFromRealm(value, 0)\n        val copy1 = realm.copyFromRealm(value, 1)\n        val copy2 = realm.copyFromRealm(value, 2)\n\n        assertFalse(copy0.isManaged)\n        assertFalse(copy1.isManaged)\n        assertFalse(copy2.isManaged)\n\n        assertNull(copy0.realmAnyList)\n        assertTrue(copy1.realmAnyList.containsAll(testList1.asList()))\n        assertEquals(RealmAny.nullValue(), copy1.realmAnyList.last()!!.asRealmModel(RealmAnyNotIndexedWithPK::class.java).realmAny)\n        assertEquals(TEST_VALUE_1, copy2.realmAnyList.last()!!.asRealmModel(RealmAnyNotIndexedWithPK::class.java).realmAny!!.asRealmModel(PrimaryKeyAsString::class.java).name)\n    }\n\n    @Test\n    fun copyToRealmOrUpdate_list() {\n        realm.executeTransaction { realm ->\n            val value = realm.createObject<RealmAnyRealmListWithPK>(0)\n            value.realmAnyList = RealmList(*testList1)\n            value.realmAnyList.add(RealmAny.valueOf(PrimaryKeyAsString(TEST_VALUE_1)))\n        }\n\n        val update = RealmAnyRealmListWithPK(0)\n        update.realmAnyList = RealmList(*testList2)\n        update.realmAnyList.add(RealmAny.valueOf(PrimaryKeyAsString(TEST_VALUE_2)))\n\n        realm.beginTransaction()\n        val managedValue = realm.copyToRealmOrUpdate(update)\n        realm.commitTransaction()\n\n        assertTrue(managedValue.realmAnyList.containsAll(testList2.asList()))\n\n        val managedInnerObject = managedValue.realmAnyList.last()!!.asRealmModel(PrimaryKeyAsString::class.java)\n        assertTrue(managedInnerObject.isManaged)\n        assertEquals(TEST_VALUE_2, managedInnerObject.name)\n    }\n\n    @Test\n    fun insert_realmModelList() {\n        realm.executeTransaction { realm ->\n            val value = RealmAnyRealmListWithPK()\n            value.realmAnyList = RealmList(*testList1)\n            value.realmAnyList.add(RealmAny.valueOf(PrimaryKeyAsString(TEST_VALUE_1)))\n\n            realm.insert(value)\n        }\n\n        val managedValue = realm.where<RealmAnyRealmListWithPK>().findFirst()!!\n\n        val managedInnerObject = managedValue.realmAnyList.last()!!.asRealmModel(PrimaryKeyAsString::class.java)\n\n        assertTrue(managedInnerObject.isManaged)\n        assertTrue(managedValue.realmAnyList.containsAll(testList1.asList()))\n        assertEquals(TEST_VALUE_1, managedInnerObject.name)\n    }\n\n    @Test\n    fun insertOrUpdate_realmModelList() {\n        realm.executeTransaction { realm ->\n            val value = realm.createObject<RealmAnyRealmListWithPK>(0)\n            value.realmAnyList = RealmList(*testList1)\n            value.realmAnyList.add(RealmAny.valueOf(PrimaryKeyAsString(TEST_VALUE_1)))\n        }\n\n        realm.executeTransaction { realm ->\n            val value = RealmAnyRealmListWithPK(0)\n            value.realmAnyList = RealmList(*testList2)\n            value.realmAnyList.add(RealmAny.valueOf(PrimaryKeyAsString(TEST_VALUE_2)))\n\n            realm.insertOrUpdate(value)\n        }\n\n        val all = realm.where<RealmAnyRealmListWithPK>().findAll()\n        assertEquals(1, all.size)\n\n        assertTrue(all.first()!!.realmAnyList.containsAll(testList2.asList()))\n\n        val managedInnerObject = all.first()!!.realmAnyList.last()!!.asRealmModel(PrimaryKeyAsString::class.java)\n        assertTrue(managedInnerObject.isManaged)\n        assertEquals(TEST_VALUE_2, managedInnerObject.name)\n    }\n\n    @Test\n    fun bulk_copyToRealm_realmModel() {\n        val value1 = RealmAnyNotIndexedWithPK(0)\n        value1.realmAny = RealmAny.valueOf(PrimaryKeyAsString(TEST_VALUE_1))\n\n        val value2 = RealmAnyNotIndexedWithPK(1)\n        value2.realmAny = RealmAny.valueOf(PrimaryKeyAsString(TEST_VALUE_2))\n\n        realm.beginTransaction()\n        val objects = realm.copyToRealm(arrayListOf(value1, value2))\n        realm.commitTransaction()\n\n        val managedInnerObject1 = objects[0].realmAny!!.asRealmModel(PrimaryKeyAsString::class.java)\n        val managedInnerObject2 = objects[1].realmAny!!.asRealmModel(PrimaryKeyAsString::class.java)\n\n        assertTrue(managedInnerObject1.isManaged)\n        assertTrue(managedInnerObject2.isManaged)\n\n        assertEquals(TEST_VALUE_1, managedInnerObject1.name)\n        assertEquals(TEST_VALUE_2, managedInnerObject2.name)\n    }\n\n    @Test\n    fun bulk_copyToRealm_realmModelList() {\n        val value1 = RealmAnyRealmListWithPK(0)\n        value1.realmAnyList = RealmList(*testList1)\n        value1.realmAnyList.add(RealmAny.valueOf(PrimaryKeyAsString(TEST_VALUE_1)))\n\n        val value2 = RealmAnyRealmListWithPK(1)\n        value2.realmAnyList = RealmList(*testList2)\n        value2.realmAnyList.add(RealmAny.valueOf(PrimaryKeyAsString(TEST_VALUE_2)))\n\n        realm.beginTransaction()\n        val objects = realm.copyToRealm(arrayListOf(value1, value2))\n        realm.commitTransaction()\n\n        assertTrue(objects[0].realmAnyList.containsAll(testList1.asList()))\n        assertTrue(objects[1].realmAnyList.containsAll(testList2.asList()))\n\n        val managedInnerObject1 = objects[0].realmAnyList.last()!!.asRealmModel(PrimaryKeyAsString::class.java)\n        val managedInnerObject2 = objects[1].realmAnyList.last()!!.asRealmModel(PrimaryKeyAsString::class.java)\n\n        assertTrue(managedInnerObject1.isManaged)\n        assertEquals(TEST_VALUE_1, managedInnerObject1.name)\n\n        assertTrue(managedInnerObject2.isManaged)\n        assertEquals(TEST_VALUE_2, managedInnerObject2.name)\n    }\n\n    @Test\n    fun bulk_copyToRealmOrUpdate_realmModel() {\n        realm.executeTransaction { realm ->\n            val obj1 = realm.createObject<RealmAnyNotIndexedWithPK>(0)\n            obj1.realmAny = RealmAny.valueOf(PrimaryKeyAsString(TEST_VALUE_1))\n\n            val obj2 = realm.createObject<RealmAnyNotIndexedWithPK>(1)\n            obj2.realmAny = RealmAny.valueOf(PrimaryKeyAsString(TEST_VALUE_2))\n        }\n\n        val value1 = RealmAnyNotIndexedWithPK(0)\n        value1.realmAny = RealmAny.valueOf(PrimaryKeyAsString(TEST_VALUE_3))\n\n        val value2 = RealmAnyNotIndexedWithPK(1)\n        value2.realmAny = RealmAny.valueOf(PrimaryKeyAsString(TEST_VALUE_4))\n\n        realm.beginTransaction()\n        val objects = realm.copyToRealmOrUpdate(arrayListOf(value1, value2))\n        realm.commitTransaction()\n\n        val managedInnerObject1 = objects[0].realmAny!!.asRealmModel(PrimaryKeyAsString::class.java)\n        val managedInnerObject2 = objects[1].realmAny!!.asRealmModel(PrimaryKeyAsString::class.java)\n\n        assertTrue(managedInnerObject1.isManaged)\n        assertEquals(TEST_VALUE_3, managedInnerObject1.name)\n\n        assertTrue(managedInnerObject2.isManaged)\n        assertEquals(TEST_VALUE_4, managedInnerObject2.name)\n    }\n\n    @Test\n    fun bulk_copyToRealmOrUpdate_realmModelList() {\n        realm.executeTransaction { realm ->\n            val value1 = realm.createObject<RealmAnyRealmListWithPK>(0)\n            value1.realmAnyList = RealmList(*testList1)\n            value1.realmAnyList.add(RealmAny.valueOf(PrimaryKeyAsString(TEST_VALUE_1)))\n\n            val value2 = realm.createObject<RealmAnyRealmListWithPK>(1)\n            value2.realmAnyList = RealmList(*testList1)\n            value2.realmAnyList.add(RealmAny.valueOf(PrimaryKeyAsString(TEST_VALUE_1)))\n        }\n\n        val value1 = RealmAnyRealmListWithPK(0)\n        value1.realmAnyList = RealmList(*testList2)\n        value1.realmAnyList.add(RealmAny.valueOf(PrimaryKeyAsString(TEST_VALUE_3)))\n\n        val value2 = RealmAnyRealmListWithPK(1)\n        value2.realmAnyList = RealmList(*testList2)\n        value2.realmAnyList.add(RealmAny.valueOf(PrimaryKeyAsString(TEST_VALUE_4)))\n\n        realm.beginTransaction()\n        val objects = realm.copyToRealmOrUpdate(arrayListOf(value1, value2))\n        realm.commitTransaction()\n\n        assertTrue(objects[0].realmAnyList.containsAll(testList2.asList()))\n        assertTrue(objects[1].realmAnyList.containsAll(testList2.asList()))\n\n        val managedInnerObject1 = objects[0].realmAnyList.last()!!.asRealmModel(PrimaryKeyAsString::class.java)\n        val managedInnerObject2 = objects[1].realmAnyList.last()!!.asRealmModel(PrimaryKeyAsString::class.java)\n\n        assertTrue(managedInnerObject1.isManaged)\n        assertEquals(TEST_VALUE_3, managedInnerObject1.name)\n\n        assertTrue(managedInnerObject2.isManaged)\n        assertEquals(TEST_VALUE_4, managedInnerObject2.name)\n    }\n\n    @Test\n    fun bulk_insert_realmModel() {\n        realm.executeTransaction { realm ->\n            val value1 = RealmAnyNotIndexedWithPK(0)\n            value1.realmAny = RealmAny.valueOf(PrimaryKeyAsString(TEST_VALUE_1))\n\n            val value2 = RealmAnyNotIndexedWithPK(1)\n            value2.realmAny = RealmAny.valueOf(PrimaryKeyAsString(TEST_VALUE_2))\n\n            realm.insert(arrayListOf(value1, value2))\n        }\n\n        val objects = realm.where<RealmAnyNotIndexedWithPK>().findAll()\n\n        val managedInnerObject1 = objects[0]!!.realmAny!!.asRealmModel(PrimaryKeyAsString::class.java)\n        val managedInnerObject2 = objects[1]!!.realmAny!!.asRealmModel(PrimaryKeyAsString::class.java)\n\n        assertTrue(managedInnerObject1.isManaged)\n        assertEquals(TEST_VALUE_1, managedInnerObject1.name)\n\n        assertTrue(managedInnerObject2.isManaged)\n        assertEquals(TEST_VALUE_2, managedInnerObject2.name)\n    }\n\n    @Test\n    fun bulk_insert_realmModelList() {\n        realm.executeTransaction { realm ->\n            val value1 = RealmAnyRealmListWithPK(0)\n            value1.realmAnyList = RealmList(*testList1)\n            value1.realmAnyList.add(RealmAny.valueOf(PrimaryKeyAsString(TEST_VALUE_1)))\n\n            val value2 = RealmAnyRealmListWithPK(1)\n            value2.realmAnyList = RealmList(*testList1)\n            value2.realmAnyList.add(RealmAny.valueOf(PrimaryKeyAsString(TEST_VALUE_2)))\n\n            realm.insert(arrayListOf(value1, value2))\n        }\n\n        val objects = realm.where<RealmAnyRealmListWithPK>().findAll()\n\n        assertTrue(objects[0]!!.realmAnyList.containsAll(testList1.asList()))\n        assertTrue(objects[1]!!.realmAnyList.containsAll(testList1.asList()))\n\n        val managedInnerObject1 = objects[0]!!.realmAnyList.last()!!.asRealmModel(PrimaryKeyAsString::class.java)\n        val managedInnerObject2 = objects[1]!!.realmAnyList.last()!!.asRealmModel(PrimaryKeyAsString::class.java)\n\n        assertTrue(managedInnerObject1.isManaged)\n        assertEquals(TEST_VALUE_1, managedInnerObject1.name)\n\n        assertTrue(managedInnerObject2.isManaged)\n        assertEquals(TEST_VALUE_2, managedInnerObject2.name)\n    }\n\n    @Test\n    fun bulk_insertOrUpdate_realmModel() {\n        realm.executeTransaction { realm ->\n            val value1 = realm.createObject<RealmAnyNotIndexedWithPK>(0)\n            value1.realmAny = RealmAny.valueOf(PrimaryKeyAsString(TEST_VALUE_1))\n\n            val value2 = realm.createObject<RealmAnyNotIndexedWithPK>(1)\n            value2.realmAny = RealmAny.valueOf(PrimaryKeyAsString(TEST_VALUE_2))\n        }\n\n        realm.executeTransaction { realm ->\n            val value1 = RealmAnyNotIndexedWithPK(0)\n            value1.realmAny = RealmAny.valueOf(PrimaryKeyAsString(TEST_VALUE_3))\n\n            val value2 = RealmAnyNotIndexedWithPK(1)\n            value2.realmAny = RealmAny.valueOf(PrimaryKeyAsString(TEST_VALUE_4))\n\n            realm.insertOrUpdate(arrayListOf(value1, value2))\n        }\n\n        val all = realm.where<RealmAnyNotIndexedWithPK>().findAll()\n\n        assertEquals(2, all.size)\n\n        val managedInnerObject1 = all[0]!!.realmAny!!.asRealmModel(PrimaryKeyAsString::class.java)\n        val managedInnerObject2 = all[1]!!.realmAny!!.asRealmModel(PrimaryKeyAsString::class.java)\n\n        assertTrue(managedInnerObject1.isManaged)\n        assertEquals(TEST_VALUE_3, managedInnerObject1.name)\n\n        assertTrue(managedInnerObject2.isManaged)\n        assertEquals(TEST_VALUE_4, managedInnerObject2.name)\n    }\n\n    @Test\n    fun bulk_insertOrUpdate_realmModelList() {\n        realm.executeTransaction { realm ->\n            val value1 = realm.createObject<RealmAnyRealmListWithPK>(0)\n            value1.realmAnyList = RealmList(*testList1)\n            value1.realmAnyList.add(RealmAny.valueOf(PrimaryKeyAsString(\"hello world1\")))\n\n            val value2 = realm.createObject<RealmAnyRealmListWithPK>(1)\n            value2.realmAnyList = RealmList(*testList1)\n            value2.realmAnyList.add(RealmAny.valueOf(PrimaryKeyAsString(TEST_VALUE_2)))\n        }\n\n        realm.executeTransaction { realm ->\n            val value1 = RealmAnyRealmListWithPK(0)\n            value1.realmAnyList = RealmList(*testList2)\n            value1.realmAnyList.add(RealmAny.valueOf(PrimaryKeyAsString(TEST_VALUE_3)))\n\n            val value2 = RealmAnyRealmListWithPK(1)\n            value2.realmAnyList = RealmList(*testList2)\n            value2.realmAnyList.add(RealmAny.valueOf(PrimaryKeyAsString(TEST_VALUE_4)))\n\n            realm.insertOrUpdate(arrayListOf(value1, value2))\n        }\n\n        val all = realm.where<RealmAnyRealmListWithPK>().findAll()\n        assertEquals(2, all.size)\n\n        assertTrue(all[0]!!.realmAnyList.containsAll(testList2.asList()))\n        assertTrue(all[1]!!.realmAnyList.containsAll(testList2.asList()))\n\n        val managedInnerObject1 = all[0]!!.realmAnyList.last()!!.asRealmModel(PrimaryKeyAsString::class.java)\n        assertTrue(managedInnerObject1.isManaged)\n        assertEquals(TEST_VALUE_3, managedInnerObject1.name)\n\n        val managedInnerObject2 = all[1]!!.realmAnyList.last()!!.asRealmModel(PrimaryKeyAsString::class.java)\n        assertTrue(managedInnerObject2.isManaged)\n        assertEquals(TEST_VALUE_4, managedInnerObject2.name)\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/kotlin/io/realm/realmany/RealmAnyChangeListenerTests.kt",
    "content": "/*\n * Copyright 2021 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\npackage io.realm.realmany\n\nimport androidx.test.platform.app.InstrumentationRegistry\nimport io.realm.*\nimport io.realm.entities.*\nimport io.realm.rule.BlockingLooperThread\nimport org.bson.types.Decimal128\nimport org.bson.types.ObjectId\nimport org.junit.After\nimport org.junit.Before\nimport org.junit.Rule\nimport org.junit.Test\nimport org.junit.rules.TemporaryFolder\nimport org.junit.runner.RunWith\nimport org.junit.runners.Parameterized\nimport java.util.*\nimport kotlin.test.assertFalse\nimport kotlin.test.assertTrue\n\n\n@RunWith(Parameterized::class)\nclass RealmAnyChangeListenerTests(private val testingType: RealmAny.Type, private val first: Any, private val second: Any, private val third: Any) {\n    private lateinit var realmConfiguration: RealmConfiguration\n\n    @get:Rule\n    val configFactory = TestRealmConfigurationFactory()\n\n    private val looperThread = BlockingLooperThread()\n\n    @Rule\n    @JvmField\n    val folder = TemporaryFolder()\n\n    init {\n        Realm.init(InstrumentationRegistry.getInstrumentation().targetContext)\n    }\n\n    @Before\n    fun setUp() {\n        realmConfiguration = configFactory.createSchemaConfiguration(\n                false,\n                AllJavaTypes::class.java)\n    }\n\n    @After\n    fun tearDown() {\n    }\n\n    companion object {\n        @JvmStatic\n        @Parameterized.Parameters\n        fun data(): MutableList<Array<Any>> {\n            val list = mutableListOf<Array<Any>>()\n\n            for (type in RealmAny.Type.values()) {\n                when (type) {\n                    RealmAny.Type.INTEGER -> {\n                        list.add(arrayOf(RealmAny.Type.INTEGER,\n                                RealmAny.valueOf(1.toByte()),\n                                RealmAny.valueOf(10.toByte()),\n                                RealmAny.valueOf(true))\n                        )\n                        list.add(arrayOf(RealmAny.Type.INTEGER,\n                                RealmAny.valueOf(2.toShort()),\n                                RealmAny.valueOf(20.toShort()\n                                ),\n                                RealmAny.valueOf(true)))\n                        list.add(arrayOf(RealmAny.Type.INTEGER,\n                                RealmAny.valueOf(3.toInt()),\n                                RealmAny.valueOf(30.toInt()),\n                                RealmAny.valueOf(true))\n                        )\n                        list.add(arrayOf(RealmAny.Type.INTEGER,\n                                RealmAny.valueOf(4.toLong()),\n                                RealmAny.valueOf(40.toLong()),\n                                RealmAny.valueOf(true))\n                        )\n                    }\n                    RealmAny.Type.BOOLEAN -> list.add(arrayOf(\n                            RealmAny.Type.BOOLEAN,\n                            RealmAny.valueOf(false),\n                            RealmAny.valueOf(true),\n                            RealmAny.valueOf(0.toInt()))\n                    )\n                    RealmAny.Type.STRING -> list.add(arrayOf(\n                            RealmAny.Type.STRING,\n                            RealmAny.valueOf(\"hello world1\"),\n                            RealmAny.valueOf(\"hello world2\"),\n                            RealmAny.valueOf(10.toInt()))\n                    )\n                    RealmAny.Type.BINARY -> list.add(arrayOf(\n                            RealmAny.Type.BINARY,\n                            RealmAny.valueOf(byteArrayOf(0, 1, 0)),\n                            RealmAny.valueOf(byteArrayOf(0, 1, 1)),\n                            RealmAny.valueOf(\"hello world3\"))\n                    )\n                    RealmAny.Type.DATE -> list.add(arrayOf(\n                            RealmAny.Type.DATE,\n                            RealmAny.valueOf(Date(0)),\n                            RealmAny.valueOf(Date(10)),\n                            RealmAny.valueOf(ObjectId(Date(10))))\n                    )\n                    RealmAny.Type.FLOAT -> list.add(arrayOf(\n                            RealmAny.Type.FLOAT,\n                            RealmAny.valueOf(5.toFloat()),\n                            RealmAny.valueOf(50.toFloat()),\n                            RealmAny.valueOf(false))\n                    )\n                    RealmAny.Type.DOUBLE -> list.add(arrayOf(\n                            RealmAny.Type.DOUBLE,\n                            RealmAny.valueOf(6.toDouble()),\n                            RealmAny.valueOf(60.toDouble()),\n                            RealmAny.valueOf(false)))\n                    RealmAny.Type.DECIMAL128 -> list.add(arrayOf(\n                            RealmAny.Type.DECIMAL128,\n                            RealmAny.valueOf(Decimal128(1)),\n                            RealmAny.valueOf(Decimal128(10)),\n                            RealmAny.valueOf(10.5.toFloat()))\n                    )\n                    RealmAny.Type.OBJECT_ID -> list.add(arrayOf(\n                            RealmAny.Type.OBJECT_ID,\n                            RealmAny.valueOf(ObjectId(Date(10))),\n                            RealmAny.valueOf(ObjectId(Date(100))),\n                            RealmAny.valueOf(Date(100)))\n                    )\n                    RealmAny.Type.UUID -> list.add(arrayOf(\n                            RealmAny.Type.UUID,\n                            RealmAny.valueOf(UUID.randomUUID()),\n                            RealmAny.valueOf(UUID.randomUUID()),\n                            RealmAny.valueOf(\"hello world1\"))\n                    )\n                    RealmAny.Type.OBJECT -> {\n                        val first = AllJavaTypes(0)\n                        first.fieldString = \"FOO\"\n\n                        val second = AllJavaTypes(0)\n                        second.fieldString = \"FOO\"\n                        second.fieldRealmAny = RealmAny.valueOf(first)\n\n                        list.add(arrayOf(\n                                RealmAny.Type.OBJECT,\n                                first,\n                                second,\n                                \"hello world1\")\n                        )\n                    }\n                    RealmAny.Type.NULL -> { // Not tested directly\n                    }\n\n                    else -> throw AssertionError(\"Missing case for type: ${type.name}\")\n                }\n            }\n\n            return list\n        }\n    }\n\n    @Test\n    fun primitives_changeValueKeepType() {\n        // Do not test on object types\n        if (testingType == RealmAny.Type.OBJECT)\n            return\n\n        looperThread.runBlocking {\n            Realm.getInstance(realmConfiguration).use { realm ->\n                realm.beginTransaction()\n\n                val all = AllJavaTypes(0)\n                all.fieldString = \"FOO1\"\n                all.fieldRealmAny = first as RealmAny?\n                val managedAll = realm.copyToRealm(all)\n\n                realm.commitTransaction()\n\n                looperThread.keepStrongReference(managedAll)\n\n                managedAll.addChangeListener { _: AllJavaTypes, changeSet ->\n                    changeSet!!\n                    looperThread.postRunnable(Runnable {\n                        assertTrue(changeSet.isFieldChanged(AllJavaTypes.FIELD_STRING))\n                        assertTrue(changeSet.isFieldChanged(AllJavaTypes.FIELD_REALM_ANY))\n                        looperThread.testComplete()\n                    })\n                }\n\n                realm.beginTransaction()\n\n                managedAll.fieldString = \"FOO2\"\n                managedAll.fieldRealmAny = second as RealmAny?\n\n                realm.commitTransaction()\n            }\n        }\n    }\n\n    @Test\n    fun primitives_changeValueChangeType() {\n        // Do not test on object types\n        if (testingType == RealmAny.Type.OBJECT)\n            return\n\n        looperThread.runBlocking {\n            Realm.getInstance(realmConfiguration).use { realm ->\n                realm.beginTransaction()\n\n                val all = AllJavaTypes(0)\n                all.fieldString = \"FOO1\"\n                all.fieldRealmAny = first as RealmAny?\n                val managedAll = realm.copyToRealm(all)\n\n                realm.commitTransaction()\n\n                looperThread.keepStrongReference(managedAll)\n\n                managedAll.addChangeListener<RealmModel> { _, changeSet ->\n                    changeSet!!\n                    looperThread.postRunnable(Runnable {\n                        assertTrue(changeSet.isFieldChanged(AllJavaTypes.FIELD_STRING))\n                        assertTrue(changeSet.isFieldChanged(AllJavaTypes.FIELD_REALM_ANY))\n                        looperThread.testComplete()\n                    })\n                }\n\n                realm.beginTransaction()\n\n                managedAll.fieldString = \"FOO2\"\n                managedAll.fieldRealmAny = third as RealmAny?\n\n                realm.commitTransaction()\n            }\n        }\n    }\n\n    @Test\n    fun primitives_changeValueChangeType_checkSameValueFlag() {\n        // Do not test on object types\n        if (testingType == RealmAny.Type.OBJECT)\n            return\n\n        looperThread.runBlocking {\n            Realm.getInstance(realmConfiguration).use { realm ->\n                realm.beginTransaction()\n\n                val all = AllJavaTypes(0)\n                all.fieldString = \"FOO1\"\n                all.fieldRealmAny = first as RealmAny?\n                val managedAll = realm.copyToRealm(all)\n\n                realm.commitTransaction()\n\n                looperThread.keepStrongReference(managedAll)\n\n                managedAll.addChangeListener { _: AllJavaTypes, changeSet ->\n                    changeSet!!\n                    looperThread.postRunnable(Runnable {\n                        assertTrue(changeSet.isFieldChanged(AllJavaTypes.FIELD_STRING))\n                        assertTrue(changeSet.isFieldChanged(AllJavaTypes.FIELD_REALM_ANY))\n                        looperThread.testComplete()\n                    })\n                }\n\n                realm.beginTransaction()\n\n                val updatingModel = AllJavaTypes(0)\n                updatingModel.fieldString = \"FOO2\"\n                updatingModel.fieldRealmAny = third as RealmAny?\n\n                realm.copyToRealmOrUpdate(updatingModel, ImportFlag.CHECK_SAME_VALUES_BEFORE_SET)\n\n                realm.commitTransaction()\n            }\n        }\n    }\n\n    @Test\n    fun primitives_keepValues() {\n        // Do not test on object types\n        if (testingType == RealmAny.Type.OBJECT)\n            return\n\n        looperThread.runBlocking {\n            Realm.getInstance(realmConfiguration).use { realm ->\n                realm.beginTransaction()\n\n                val all = AllJavaTypes(0)\n                all.fieldString = \"FOO1\"\n                all.fieldRealmAny = first as RealmAny?\n                val managedAll = realm.copyToRealm(all)\n\n                realm.commitTransaction()\n\n                looperThread.keepStrongReference(managedAll)\n\n                managedAll.addChangeListener { _: AllJavaTypes, changeSet ->\n                    changeSet!!\n                    looperThread.postRunnable(Runnable {\n                        assertTrue(changeSet.isFieldChanged(AllJavaTypes.FIELD_STRING))\n                        assertTrue(changeSet.isFieldChanged(AllJavaTypes.FIELD_REALM_ANY))\n                        looperThread.testComplete()\n                    })\n                }\n\n                realm.beginTransaction()\n\n                managedAll.fieldString = \"FOO2\"\n                managedAll.fieldRealmAny = first\n\n                realm.commitTransaction()\n            }\n        }\n    }\n\n    @Test\n    fun primitives_keepValues_checkSameValuesFlag() {\n        // Do not test on object types\n        if (testingType == RealmAny.Type.OBJECT)\n            return\n\n        looperThread.runBlocking {\n            Realm.getInstance(realmConfiguration).use { realm ->\n                realm.beginTransaction()\n\n                val all = AllJavaTypes(0)\n                all.fieldString = \"FOO1\"\n                all.fieldRealmAny = first as RealmAny?\n                val managedAll = realm.copyToRealm(all)\n\n                realm.commitTransaction()\n\n                looperThread.keepStrongReference(managedAll)\n\n                managedAll.addChangeListener { _: AllJavaTypes, changeSet ->\n                    changeSet!!\n                    looperThread.postRunnable(Runnable {\n                        assertTrue(changeSet.isFieldChanged(AllJavaTypes.FIELD_STRING))\n                        assertFalse(changeSet.isFieldChanged(AllJavaTypes.FIELD_REALM_ANY))\n                        looperThread.testComplete()\n                    })\n                }\n\n                realm.beginTransaction()\n\n                val updatingModel = AllJavaTypes(0)\n                updatingModel.fieldString = \"FOO2\"\n                updatingModel.fieldRealmAny = first\n\n                realm.copyToRealmOrUpdate(updatingModel, ImportFlag.CHECK_SAME_VALUES_BEFORE_SET)\n\n                realm.commitTransaction()\n            }\n        }\n    }\n\n    @Test\n    fun primitives_fromNull() {\n        // Do not test on object types\n        if (testingType == RealmAny.Type.OBJECT)\n            return\n\n        looperThread.runBlocking {\n            Realm.getInstance(realmConfiguration).use { realm ->\n                realm.beginTransaction()\n\n                val all = AllJavaTypes(0)\n                all.fieldString = \"FOO1\"\n                val managedAll = realm.copyToRealm(all)\n\n                realm.commitTransaction()\n\n                looperThread.keepStrongReference(managedAll)\n\n                managedAll.addChangeListener { _: AllJavaTypes, changeSet ->\n                    changeSet!!\n                    looperThread.postRunnable(Runnable {\n                        assertTrue(changeSet.isFieldChanged(AllJavaTypes.FIELD_STRING))\n                        assertTrue(changeSet.isFieldChanged(AllJavaTypes.FIELD_REALM_ANY))\n                        looperThread.testComplete()\n                    })\n                }\n\n                realm.beginTransaction()\n\n                managedAll.fieldString = \"FOO2\"\n                managedAll.fieldRealmAny = first as RealmAny?\n\n                realm.commitTransaction()\n            }\n        }\n    }\n\n    @Test\n    fun primitives_toNull() {\n        // Do not test on object types\n        if (testingType == RealmAny.Type.OBJECT)\n            return\n\n        looperThread.runBlocking {\n            Realm.getInstance(realmConfiguration).use { realm ->\n                realm.beginTransaction()\n\n                val all = AllJavaTypes(0)\n                all.fieldString = \"FOO1\"\n                all.fieldRealmAny = first as RealmAny?\n                val managedAll = realm.copyToRealm(all)\n\n                realm.commitTransaction()\n\n                looperThread.keepStrongReference(managedAll)\n\n                managedAll.addChangeListener { _: AllJavaTypes, changeSet ->\n                    changeSet!!\n                    looperThread.postRunnable(Runnable {\n                        assertTrue(changeSet.isFieldChanged(AllJavaTypes.FIELD_STRING))\n                        assertTrue(changeSet.isFieldChanged(AllJavaTypes.FIELD_REALM_ANY))\n                        looperThread.testComplete()\n                    })\n                }\n\n                realm.beginTransaction()\n\n                managedAll.fieldString = \"FOO2\"\n                managedAll.fieldRealmAny = RealmAny.nullValue()\n\n                realm.commitTransaction()\n            }\n        }\n    }\n\n    @Test\n    fun realmModels_cyclicDependency() {\n        // Do not test on object types\n        if (testingType != RealmAny.Type.OBJECT)\n            return\n\n        looperThread.runBlocking {\n            Realm.getInstance(realmConfiguration).use { realm ->\n                realm.beginTransaction()\n\n                val managedAll = realm.copyToRealmOrUpdate(first as AllJavaTypes)\n\n                realm.commitTransaction()\n\n                looperThread.keepStrongReference(managedAll)\n\n                RealmObject.addChangeListener(managedAll) { _, changeSet ->\n                    changeSet!!\n                    looperThread.postRunnable(Runnable {\n                        assertFalse(changeSet.isFieldChanged(AllJavaTypes.FIELD_STRING))\n                        assertTrue(changeSet.isFieldChanged(AllJavaTypes.FIELD_REALM_ANY))\n                        looperThread.testComplete()\n                    })\n                }\n\n                realm.beginTransaction()\n\n                realm.copyToRealmOrUpdate(second as RealmModel, ImportFlag.CHECK_SAME_VALUES_BEFORE_SET)\n\n                realm.commitTransaction()\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/kotlin/io/realm/realmany/RealmAnyHelper.kt",
    "content": "/*\n * Copyright 2021 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\npackage io.realm.realmany\n\nimport io.realm.RealmAny\nimport io.realm.RealmAny.Type\nimport io.realm.TestHelper\nimport io.realm.entities.PrimaryKeyAsString\nimport org.bson.types.Decimal128\nimport org.bson.types.ObjectId\nimport java.util.*\n\nclass RealmAnyHelper {\n    companion object {\n        fun generateRealmAnyValues(): ArrayList<RealmAny> {\n            val realmAnyValues = arrayListOf<RealmAny>()\n\n            for (type in RealmAny.Type.values()) {\n                when (type) {\n                    RealmAny.Type.INTEGER -> {\n                        for (i in 0..9) {\n                            realmAnyValues.add(RealmAny.valueOf(i.toByte()))\n                            realmAnyValues.add(RealmAny.valueOf((i).toShort()))\n                            realmAnyValues.add(RealmAny.valueOf((i).toInt()))\n                            realmAnyValues.add(RealmAny.valueOf((i).toLong()))\n                        }\n                    }\n                    RealmAny.Type.BOOLEAN -> {\n                        realmAnyValues.add(RealmAny.valueOf(false))\n                        realmAnyValues.add(RealmAny.valueOf(true))\n                    }\n                    RealmAny.Type.STRING -> {\n                        for (i in 0..4) {\n                            realmAnyValues.add(RealmAny.valueOf(\"hello world $i\"))\n                        }\n                        for (i in 0..4) {\n                            realmAnyValues.add(RealmAny.valueOf(\"HELLO WORLD $i\"))\n                        }\n                    }\n                    RealmAny.Type.BINARY -> {\n                        realmAnyValues.add(RealmAny.valueOf(byteArrayOf(0, 0, 0)))\n                        realmAnyValues.add(RealmAny.valueOf(byteArrayOf(0, 1, 0)))\n                        realmAnyValues.add(RealmAny.valueOf(byteArrayOf(0, 1, 1)))\n                        realmAnyValues.add(RealmAny.valueOf(byteArrayOf(1, 1, 0)))\n                        realmAnyValues.add(RealmAny.valueOf(byteArrayOf(1, 1, 1)))\n                    }\n                    RealmAny.Type.DATE -> {\n                        for (i in 0..4) {\n                            realmAnyValues.add(RealmAny.valueOf(Date(i.toLong())))\n                        }\n                    }\n                    RealmAny.Type.FLOAT -> {\n                        for (i in 0..9) {\n                            realmAnyValues.add(RealmAny.valueOf((4 + i * 0.1).toFloat()))\n                        }\n                    }\n                    RealmAny.Type.DOUBLE -> {\n                        for (i in 0..9) {\n                            realmAnyValues.add(RealmAny.valueOf((4 + i * 0.1).toDouble()))\n                        }\n                    }\n                    RealmAny.Type.DECIMAL128 -> {\n                        for (i in 0..4) {\n                            realmAnyValues.add(RealmAny.valueOf(Decimal128(i.toLong())))\n                        }\n                    }\n                    RealmAny.Type.OBJECT_ID -> {\n                        for (i in 0..4) {\n                            realmAnyValues.add(RealmAny.valueOf(ObjectId(TestHelper.generateObjectIdHexString(i))))\n                        }\n                    }\n                    RealmAny.Type.UUID -> {\n                        for (i in 0..4) {\n                            realmAnyValues.add(RealmAny.valueOf(UUID.fromString(TestHelper.generateUUIDString(i))))\n                        }\n                    }\n                    RealmAny.Type.OBJECT -> {\n                        for (i in 0..5) {\n                            realmAnyValues.add(RealmAny.valueOf(PrimaryKeyAsString(\"item $i\")))\n                        }\n                    }\n                    RealmAny.Type.NULL -> {\n                        for (i in 1..9) {\n                            realmAnyValues.add(RealmAny.nullValue())\n                        }\n                    }\n\n                    else -> throw AssertionError(\"Missing case for type: ${type.name}\")\n                }\n            }\n\n            return realmAnyValues\n        }\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/kotlin/io/realm/realmany/RealmAnyParameterizedQueryTests.kt",
    "content": "/*\n * Copyright 2021 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\npackage io.realm.realmany\n\nimport androidx.test.platform.app.InstrumentationRegistry\nimport io.realm.*\nimport io.realm.entities.RealmAnyNotIndexed\nimport io.realm.entities.PrimaryKeyAsString\nimport io.realm.kotlin.where\nimport org.bson.types.Decimal128\nimport org.bson.types.ObjectId\nimport org.junit.After\nimport org.junit.Before\nimport org.junit.Rule\nimport org.junit.Test\nimport org.junit.runner.RunWith\nimport org.junit.runners.Parameterized\nimport java.lang.reflect.InvocationTargetException\nimport java.util.*\nimport kotlin.reflect.KFunction\nimport kotlin.reflect.jvm.javaMethod\nimport kotlin.test.assertEquals\nimport kotlin.test.assertFailsWith\nimport kotlin.test.assertFalse\nimport kotlin.test.assertTrue\n\nclass RealmAnyParameterizedQueryTest(\n        val filter: KFunction<*>,\n        val arguments: Array<Any?>,\n        val expectedResult: Array<Any?>,\n        val expectedSize: Int? = null,\n        val expandArguments: Boolean = true,\n        val testWithUnmanagedObjects: Boolean = false\n) {\n    @Suppress(\"UNCHECKED_CAST\")\n    private fun asRealmAny(array: Array<Any?>, realm: Realm, copyToRealm: Boolean = true): Array<RealmAny> {\n        val realmAnyArray = arrayOfNulls<RealmAny?>(array.size)\n\n        realm.executeTransaction{\n            array.forEachIndexed { index, value ->\n                if (value == null)\n                    realmAnyArray[index] = RealmAny.nullValue()\n                else\n                    when (value) {\n                        is Boolean -> realmAnyArray[index] = RealmAny.valueOf(value)\n                        is Byte -> realmAnyArray[index] = RealmAny.valueOf(value)\n                        is Short -> realmAnyArray[index] = RealmAny.valueOf(value)\n                        is Int -> realmAnyArray[index] = RealmAny.valueOf(value)\n                        is Long -> realmAnyArray[index] = RealmAny.valueOf(value)\n                        is Float -> realmAnyArray[index] = RealmAny.valueOf(value)\n                        is Double -> realmAnyArray[index] = RealmAny.valueOf(value)\n                        is String -> realmAnyArray[index] = RealmAny.valueOf(value)\n                        is ByteArray -> realmAnyArray[index] = RealmAny.valueOf(value)\n                        is Decimal128 -> realmAnyArray[index] = RealmAny.valueOf(value)\n                        is ObjectId -> realmAnyArray[index] = RealmAny.valueOf(value)\n                        is UUID -> realmAnyArray[index] = RealmAny.valueOf(value)\n                        is Date -> realmAnyArray[index] = RealmAny.valueOf(value)\n                        is RealmModel -> realmAnyArray[index] = RealmAny.valueOf(if (copyToRealm) realm.copyToRealmOrUpdate(value) else value)\n                        else -> throw IllegalStateException(\"EqualsTo test for type ${value::class.qualifiedName} not implemented\")\n                    }\n            }\n        }\n\n        return realmAnyArray as Array<RealmAny>\n    }\n\n    override fun toString(): String {\n        if (arguments.isEmpty()) {\n            return filter.javaMethod!!.name\n        }\n\n        val firstParameter = arguments[0]\n        if (firstParameter is Array<*>) {\n            return \"${filter.javaMethod!!.name}:${firstParameter::class.java.componentType}\"\n        }\n\n        return \"${filter.javaMethod!!.name}:${arguments[0]!!::class.simpleName}\"\n    }\n\n    fun execute(context: Any, realm: Realm) {\n        if (expandArguments) {\n            filter.call(context, asRealmAny(expectedResult, realm), expectedSize ?: expectedResult.size, *arguments)\n        } else {\n            filter.call(context, asRealmAny(expectedResult, realm), expectedSize ?: expectedResult.size, arguments)\n        }\n    }\n\n    fun executeRealmAny(context: Any, realm: Realm) {\n        if (expandArguments) {\n            filter.call(context, asRealmAny(expectedResult, realm), expectedSize ?: expectedResult.size, *asRealmAny(arguments, realm))\n        } else {\n            filter.call(context, asRealmAny(expectedResult, realm), expectedSize ?: expectedResult.size, asRealmAny(arguments, realm))\n        }\n    }\n\n    fun executeRealmAny_nonManagedRealmModel(context: Any, realm: Realm) {\n        if(!testWithUnmanagedObjects){\n            return\n        }\n\n        val exception = assertFailsWith<InvocationTargetException>(\"Unmanaged Realm objects are not valid query arguments\"){\n            if (expandArguments) {\n                filter.call(context, asRealmAny(expectedResult, realm, false),\n                        expectedSize ?: expectedResult.size, *asRealmAny(arguments, realm, false))\n            } else {\n                filter.call(context, asRealmAny(expectedResult, realm, false),\n                        expectedSize ?: expectedResult.size, asRealmAny(arguments, realm, false))\n            }\n        }\n\n        assertTrue(exception.cause is IllegalArgumentException)\n    }\n}\n\n@RunWith(Parameterized::class)\nclass RealmAnyParameterizedQueryTests(val test: RealmAnyParameterizedQueryTest) {\n    private lateinit var realmConfiguration: RealmConfiguration\n    private lateinit var realm: Realm\n\n    private fun initializeTestData() {\n        val realmAnyValues = RealmAnyHelper.generateRealmAnyValues()\n\n        realm.beginTransaction()\n\n        for (value in realmAnyValues) {\n            val realmAnyObject = RealmAnyNotIndexed(value)\n            realm.insert(realmAnyObject)\n        }\n\n        realm.commitTransaction()\n    }\n\n    @get:Rule\n    val configFactory = TestRealmConfigurationFactory()\n\n    companion object {\n        @JvmStatic\n        @Parameterized.Parameters(name = \"{index}:{0}\")\n        fun data(): List<RealmAnyParameterizedQueryTest> = listOf(\n                // EQUALS TEST DEFINITIONS\n                RealmAnyParameterizedQueryTest(\n                        filter = RealmAnyParameterizedQueryTests::equalTo,\n                        arguments = arrayOf(true),\n                        expectedResult = arrayOf(true)\n                ),\n                RealmAnyParameterizedQueryTest(\n                        filter = RealmAnyParameterizedQueryTests::equalTo,\n                        arguments = arrayOf(4.toByte()),\n                        expectedResult = arrayOf(4, 4, 4, 4, 4.0.toFloat(), 4.0, Decimal128(4))\n                ),\n                RealmAnyParameterizedQueryTest(\n                        filter = RealmAnyParameterizedQueryTests::equalTo,\n                        arguments = arrayOf(4.toShort()),\n                        expectedResult = arrayOf(4, 4, 4, 4, 4.0.toFloat(), 4.0, Decimal128(4))\n                ),\n                RealmAnyParameterizedQueryTest(\n                        filter = RealmAnyParameterizedQueryTests::equalTo,\n                        arguments = arrayOf(4.toInt()),\n                        expectedResult = arrayOf(4, 4, 4, 4, 4.0.toFloat(), 4.0, Decimal128(4))\n                ),\n                RealmAnyParameterizedQueryTest(\n                        filter = RealmAnyParameterizedQueryTests::equalTo,\n                        arguments = arrayOf(4.toLong()),\n                        expectedResult = arrayOf(4, 4, 4, 4, 4.0.toFloat(), 4.0, Decimal128(4))\n                ),\n                RealmAnyParameterizedQueryTest(\n                        filter = RealmAnyParameterizedQueryTests::equalTo,\n                        arguments = arrayOf(4.toFloat()),\n                        expectedResult = arrayOf(4, 4, 4, 4, 4.0.toFloat(), 4.0, Decimal128(4))\n                ),\n                RealmAnyParameterizedQueryTest(\n                        filter = RealmAnyParameterizedQueryTests::equalTo,\n                        arguments = arrayOf(4.toDouble()),\n                        expectedResult = arrayOf(4, 4, 4, 4, 4.0.toFloat(), 4.0, Decimal128(4))\n                ),\n                RealmAnyParameterizedQueryTest(\n                        filter = RealmAnyParameterizedQueryTests::equalTo,\n                        arguments = arrayOf(\"hello world 1\"),\n                        expectedResult = arrayOf(\"hello world 1\")\n                ),\n                RealmAnyParameterizedQueryTest(\n                        filter = RealmAnyParameterizedQueryTests::equalTo,\n                        arguments = arrayOf(byteArrayOf(0, 1, 0)),\n                        expectedResult = arrayOf(byteArrayOf(0, 1, 0))\n                ),\n                RealmAnyParameterizedQueryTest(\n                        filter = RealmAnyParameterizedQueryTests::equalTo,\n                        arguments = arrayOf(Date(4)),\n                        expectedResult = arrayOf(Date(4))\n                ),\n                RealmAnyParameterizedQueryTest(\n                        filter = RealmAnyParameterizedQueryTests::equalTo,\n                        arguments = arrayOf(Decimal128(4)),\n                        expectedResult = arrayOf(4, 4, 4, 4, 4.0.toFloat(), 4.0, Decimal128(4))\n                ),\n                RealmAnyParameterizedQueryTest(\n                        filter = RealmAnyParameterizedQueryTests::equalTo,\n                        arguments = arrayOf(ObjectId(TestHelper.generateObjectIdHexString(0))),\n                        expectedResult = arrayOf(ObjectId(TestHelper.generateObjectIdHexString(0)))\n                ),\n                RealmAnyParameterizedQueryTest(\n                        filter = RealmAnyParameterizedQueryTests::equalTo,\n                        arguments = arrayOf(UUID.fromString(TestHelper.generateUUIDString(0))),\n                        expectedResult = arrayOf(UUID.fromString(TestHelper.generateUUIDString(0)))\n                ),\n                RealmAnyParameterizedQueryTest(\n                        filter = RealmAnyParameterizedQueryTests::equalToInsensitive,\n                        arguments = arrayOf(\"hello world 2\"),\n                        expectedResult = arrayOf(\"hello world 2\", \"HELLO WORLD 2\")\n                ),\n                RealmAnyParameterizedQueryTest(\n                        filter = RealmAnyParameterizedQueryTests::equalTo,\n                        arguments = arrayOf(PrimaryKeyAsString(\"item 1\")),\n                        expectedResult = arrayOf(PrimaryKeyAsString(\"item 1\")),\n                        testWithUnmanagedObjects = true\n                ),\n                // NOT EQUALS TEST DEFINITIONS\n                RealmAnyParameterizedQueryTest(\n                        filter = RealmAnyParameterizedQueryTests::notEqualTo,\n                        arguments = arrayOf(true),\n                        expectedResult = arrayOf(false),\n                        expectedSize = 111\n                ),\n                RealmAnyParameterizedQueryTest(\n                        filter = RealmAnyParameterizedQueryTests::notEqualTo,\n                        arguments = arrayOf(4.toByte()),\n                        expectedResult = arrayOf(4.toByte()),\n                        expectedSize = 105\n                ),\n                RealmAnyParameterizedQueryTest(\n                        filter = RealmAnyParameterizedQueryTests::notEqualTo,\n                        arguments = arrayOf(4.toShort()),\n                        expectedResult = arrayOf(4.toShort()),\n                        expectedSize = 105\n                ),\n                RealmAnyParameterizedQueryTest(\n                        filter = RealmAnyParameterizedQueryTests::notEqualTo,\n                        arguments = arrayOf(4.toInt()),\n                        expectedResult = arrayOf(4.toInt()),\n                        expectedSize = 105\n                ),\n                RealmAnyParameterizedQueryTest(\n                        filter = RealmAnyParameterizedQueryTests::notEqualTo,\n                        arguments = arrayOf(4.toLong()),\n                        expectedResult = arrayOf(4.toLong()),\n                        expectedSize = 105\n                ),\n                RealmAnyParameterizedQueryTest(\n                        filter = RealmAnyParameterizedQueryTests::notEqualTo,\n                        arguments = arrayOf(4.4.toFloat()),\n                        expectedResult = arrayOf(4.4.toFloat()),\n                        expectedSize = 111\n                ),\n                RealmAnyParameterizedQueryTest(\n                        filter = RealmAnyParameterizedQueryTests::notEqualTo,\n                        arguments = arrayOf(4.3),\n                        expectedResult = arrayOf(4.3),\n                        expectedSize = 111\n                ),\n                RealmAnyParameterizedQueryTest(\n                        filter = RealmAnyParameterizedQueryTests::notEqualTo,\n                        arguments = arrayOf(\"hello world 2\"),\n                        expectedResult = arrayOf(\"hello world 2\"),\n                        expectedSize = 111\n                ),\n                RealmAnyParameterizedQueryTest(\n                        filter = RealmAnyParameterizedQueryTests::notEqualTo,\n                        arguments = arrayOf(byteArrayOf(0, 1, 0)),\n                        expectedResult = arrayOf(byteArrayOf(0, 1, 0)),\n                        expectedSize = 111\n                ),\n                RealmAnyParameterizedQueryTest(\n                        RealmAnyParameterizedQueryTests::notEqualTo,\n                        arguments = arrayOf(Date(4)),\n                        expectedResult = arrayOf(Date(4)),\n                        expectedSize = 111\n                ),\n                RealmAnyParameterizedQueryTest(\n                        filter = RealmAnyParameterizedQueryTests::notEqualTo,\n                        arguments = arrayOf(Decimal128(4)),\n                        expectedResult = arrayOf(Decimal128(4)),\n                        expectedSize = 105\n                ),\n                RealmAnyParameterizedQueryTest(\n                        filter = RealmAnyParameterizedQueryTests::notEqualTo,\n                        arguments = arrayOf(ObjectId(TestHelper.generateObjectIdHexString(4))),\n                        expectedResult = arrayOf(ObjectId(TestHelper.generateObjectIdHexString(4))),\n                        expectedSize = 111\n                ),\n                RealmAnyParameterizedQueryTest(\n                        filter = RealmAnyParameterizedQueryTests::notEqualTo,\n                        arguments = arrayOf(UUID.fromString(TestHelper.generateUUIDString(4))),\n                        expectedResult = arrayOf(UUID.fromString(TestHelper.generateUUIDString(4))),\n                        expectedSize = 111\n                ),\n                RealmAnyParameterizedQueryTest(\n                        filter = RealmAnyParameterizedQueryTests::notEqualToInsensitive,\n                        arguments = arrayOf(\"HELLO WORLD 2\"),\n                        expectedResult = arrayOf(\"HELLO WORLD 2\"),\n                        expectedSize = 110\n                ),\n                RealmAnyParameterizedQueryTest(\n                        filter = RealmAnyParameterizedQueryTests::notEqualTo,\n                        arguments = arrayOf(PrimaryKeyAsString(\"item 1\")),\n                        expectedResult = arrayOf(PrimaryKeyAsString(\"item 1\")),\n                        expectedSize = 111,\n                        testWithUnmanagedObjects = true\n                ),\n                // GREATER THAN TEST DEFINITIONS\n                RealmAnyParameterizedQueryTest(\n                        filter = RealmAnyParameterizedQueryTests::greaterThan,\n                        arguments = arrayOf(5.toByte()),\n                        expectedResult = arrayOf(6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 9, 9, 9, 9)\n                ),\n                RealmAnyParameterizedQueryTest(\n                        filter = RealmAnyParameterizedQueryTests::greaterThan,\n                        arguments = arrayOf(5.toShort()),\n                        expectedResult = arrayOf(6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 9, 9, 9, 9)\n                ),\n                RealmAnyParameterizedQueryTest(\n                        filter = RealmAnyParameterizedQueryTests::greaterThan,\n                        arguments = arrayOf(5.toInt()),\n                        expectedResult = arrayOf(6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 9, 9, 9, 9)\n                ),\n                RealmAnyParameterizedQueryTest(\n                        filter = RealmAnyParameterizedQueryTests::greaterThan,\n                        arguments = arrayOf(5.toLong()),\n                        expectedResult = arrayOf(6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 9, 9, 9, 9)\n                ),\n                RealmAnyParameterizedQueryTest(\n                        filter = RealmAnyParameterizedQueryTests::greaterThan,\n                        arguments = arrayOf(4.5.toFloat()),\n                        expectedResult = arrayOf(5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 9, 9, 9, 9, 4.6.toFloat(), 4.7.toFloat(), 4.8.toFloat(), 4.9.toFloat(), 4.6, 4.7, 4.8, 4.9)\n                ),\n                RealmAnyParameterizedQueryTest(\n                        filter = RealmAnyParameterizedQueryTests::greaterThan,\n                        arguments = arrayOf(4.425),\n                        expectedResult = arrayOf(5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 9, 9, 9, 9, 4.5.toFloat(), 4.6.toFloat(), 4.7.toFloat(), 4.8.toFloat(), 4.9.toFloat(), 4.5, 4.6, 4.7, 4.8, 4.9)\n                ),\n                RealmAnyParameterizedQueryTest(\n                        filter = RealmAnyParameterizedQueryTests::greaterThan,\n                        arguments = arrayOf(Date(2)),\n                        expectedResult = arrayOf(Date(3), Date(4))\n                ),\n                RealmAnyParameterizedQueryTest(\n                        filter = RealmAnyParameterizedQueryTests::greaterThan,\n                        arguments = arrayOf(Decimal128(3)),\n                        expectedResult = arrayOf(4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 9, 9, 9, 9, 4.0.toFloat(), 4.1.toFloat(), 4.2.toFloat(), 4.3.toFloat(), 4.4.toFloat(), 4.5.toFloat(), 4.6.toFloat(), 4.7.toFloat(), 4.8.toFloat(), 4.9.toFloat(), 4.0, 4.1, 4.2, 4.3, 4.4, 4.5, 4.6, 4.7, 4.8, 4.9, Decimal128(4))\n                ),\n                RealmAnyParameterizedQueryTest(\n                        filter = RealmAnyParameterizedQueryTests::greaterThan,\n                        arguments = arrayOf(ObjectId(TestHelper.generateObjectIdHexString(1))),\n                        expectedResult = arrayOf(ObjectId(TestHelper.generateObjectIdHexString(2)), ObjectId(TestHelper.generateObjectIdHexString(3)), ObjectId(TestHelper.generateObjectIdHexString(4)))\n                ),\n                RealmAnyParameterizedQueryTest(\n                        filter = RealmAnyParameterizedQueryTests::greaterThan,\n                        arguments = arrayOf(UUID.fromString(TestHelper.generateUUIDString(1))),\n                        expectedResult = arrayOf(UUID.fromString(TestHelper.generateUUIDString(2)), UUID.fromString(TestHelper.generateUUIDString(3)), UUID.fromString(TestHelper.generateUUIDString(4)))\n                ),\n                // GREATER THAN OR EQUALS TEST DEFINITIONS\n                RealmAnyParameterizedQueryTest(\n                        filter = RealmAnyParameterizedQueryTests::greaterThanOrEqualTo,\n                        arguments = arrayOf(5.toByte()),\n                        expectedResult = arrayOf(5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 9, 9, 9, 9)\n                ),\n                RealmAnyParameterizedQueryTest(\n                        filter = RealmAnyParameterizedQueryTests::greaterThanOrEqualTo,\n                        arguments = arrayOf(5.toShort()),\n                        expectedResult = arrayOf(5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 9, 9, 9, 9)\n                ),\n                RealmAnyParameterizedQueryTest(\n                        filter = RealmAnyParameterizedQueryTests::greaterThanOrEqualTo,\n                        arguments = arrayOf(5.toInt()),\n                        expectedResult = arrayOf(5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 9, 9, 9, 9)\n                ),\n                RealmAnyParameterizedQueryTest(\n                        filter = RealmAnyParameterizedQueryTests::greaterThanOrEqualTo,\n                        arguments = arrayOf(5.toLong()),\n                        expectedResult = arrayOf(5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 9, 9, 9, 9)\n                ),\n                RealmAnyParameterizedQueryTest(\n                        filter = RealmAnyParameterizedQueryTests::greaterThanOrEqualTo,\n                        arguments = arrayOf(4.5.toFloat()),\n                        expectedResult = arrayOf(5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 9, 9, 9, 9, 4.5.toFloat(), 4.6.toFloat(), 4.7.toFloat(), 4.8.toFloat(), 4.9.toFloat(), 4.5, 4.6, 4.7, 4.8, 4.9)\n                ),\n                RealmAnyParameterizedQueryTest(\n                        filter = RealmAnyParameterizedQueryTests::greaterThanOrEqualTo,\n                        arguments = arrayOf(4.4),\n                        expectedResult = arrayOf(5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 9, 9, 9, 9, 4.4.toFloat(), 4.5.toFloat(), 4.6.toFloat(), 4.7.toFloat(), 4.8.toFloat(), 4.9.toFloat(), 4.4, 4.5, 4.6, 4.7, 4.8, 4.9)\n                ),\n                RealmAnyParameterizedQueryTest(\n                        filter = RealmAnyParameterizedQueryTests::greaterThanOrEqualTo,\n                        arguments = arrayOf(Date(2)),\n                        expectedResult = arrayOf(Date(2), Date(3), Date(4))\n                ),\n                RealmAnyParameterizedQueryTest(\n                        filter = RealmAnyParameterizedQueryTests::greaterThanOrEqualTo,\n                        arguments = arrayOf(Decimal128(3)),\n                        expectedResult = arrayOf(3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 9, 9, 9, 9, 4.0.toFloat(), 4.1.toFloat(), 4.2.toFloat(), 4.3.toFloat(), 4.4.toFloat(), 4.5.toFloat(), 4.6.toFloat(), 4.7.toFloat(), 4.8.toFloat(), 4.9.toFloat(), 4.0, 4.1, 4.2, 4.3, 4.4, 4.5, 4.6, 4.7, 4.8, 4.9, Decimal128(3), Decimal128(4))\n                ),\n                RealmAnyParameterizedQueryTest(\n                        filter = RealmAnyParameterizedQueryTests::greaterThanOrEqualTo,\n                        arguments = arrayOf(ObjectId(TestHelper.generateObjectIdHexString(1))),\n                        expectedResult = arrayOf(ObjectId(TestHelper.generateObjectIdHexString(1)), ObjectId(TestHelper.generateObjectIdHexString(2)), ObjectId(TestHelper.generateObjectIdHexString(3)), ObjectId(TestHelper.generateObjectIdHexString(4)))\n                ),\n                RealmAnyParameterizedQueryTest(\n                        filter = RealmAnyParameterizedQueryTests::greaterThanOrEqualTo,\n                        arguments = arrayOf(UUID.fromString(TestHelper.generateUUIDString(1))),\n                        expectedResult = arrayOf(UUID.fromString(TestHelper.generateUUIDString(1)), UUID.fromString(TestHelper.generateUUIDString(2)), UUID.fromString(TestHelper.generateUUIDString(3)), UUID.fromString(TestHelper.generateUUIDString(4)))\n                ),\n                // LESS THAN TEST DEFINITIONS\n                RealmAnyParameterizedQueryTest(\n                        filter = RealmAnyParameterizedQueryTests::lessThan,\n                        arguments = arrayOf(4.toByte()),\n                        expectedResult = arrayOf(0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, Decimal128(0), Decimal128(1), Decimal128(2), Decimal128(3))\n                ),\n                RealmAnyParameterizedQueryTest(\n                        filter = RealmAnyParameterizedQueryTests::lessThan,\n                        arguments = arrayOf(4.toShort()),\n                        expectedResult = arrayOf(0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, Decimal128(0), Decimal128(1), Decimal128(2), Decimal128(3))\n                ),\n                RealmAnyParameterizedQueryTest(\n                        filter = RealmAnyParameterizedQueryTests::lessThan,\n                        arguments = arrayOf(4.toInt()),\n                        expectedResult = arrayOf(0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, Decimal128(0), Decimal128(1), Decimal128(2), Decimal128(3))\n                ),\n                RealmAnyParameterizedQueryTest(\n                        filter = RealmAnyParameterizedQueryTests::lessThan,\n                        arguments = arrayOf(4.toLong()),\n                        expectedResult = arrayOf(0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, Decimal128(0), Decimal128(1), Decimal128(2), Decimal128(3))\n                ),\n                RealmAnyParameterizedQueryTest(\n                        filter = RealmAnyParameterizedQueryTests::lessThan,\n                        arguments = arrayOf(4.5.toFloat()),\n                        expectedResult = arrayOf(0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4.0.toFloat(), 4.1.toFloat(), 4.2.toFloat(), 4.3.toFloat(), 4.4.toFloat(), 4.0, 4.1, 4.2, 4.3, 4.4, Decimal128(0), Decimal128(1), Decimal128(2), Decimal128(3), Decimal128(4))\n                ),\n                RealmAnyParameterizedQueryTest(\n                        filter = RealmAnyParameterizedQueryTests::lessThan,\n                        arguments = arrayOf(4.3),\n                        expectedResult = arrayOf(0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4.0.toFloat(), 4.1.toFloat(), 4.2.toFloat(), 4.0, 4.1, 4.2, Decimal128(0), Decimal128(1), Decimal128(2), Decimal128(3), Decimal128(4))\n                ),\n                RealmAnyParameterizedQueryTest(\n                        filter = RealmAnyParameterizedQueryTests::lessThan,\n                        arguments = arrayOf(Date(3)),\n                        expectedResult = arrayOf(Date(0), Date(1), Date(2))\n                ),\n                RealmAnyParameterizedQueryTest(\n                        filter = RealmAnyParameterizedQueryTests::lessThan,\n                        arguments = arrayOf(Decimal128(3)),\n                        expectedResult = arrayOf(0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, Decimal128(0), Decimal128(1), Decimal128(2))\n                ),\n                RealmAnyParameterizedQueryTest(\n                        filter = RealmAnyParameterizedQueryTests::lessThan,\n                        arguments = arrayOf(ObjectId(TestHelper.generateObjectIdHexString(3))),\n                        expectedResult = arrayOf(ObjectId(TestHelper.generateObjectIdHexString(0)), ObjectId(TestHelper.generateObjectIdHexString(1)), ObjectId(TestHelper.generateObjectIdHexString(2)))\n                ),\n                RealmAnyParameterizedQueryTest(\n                        filter = RealmAnyParameterizedQueryTests::lessThan,\n                        arguments = arrayOf(UUID.fromString(TestHelper.generateUUIDString(3))),\n                        expectedResult = arrayOf(UUID.fromString(TestHelper.generateUUIDString(0)), UUID.fromString(TestHelper.generateUUIDString(1)), UUID.fromString(TestHelper.generateUUIDString(2)))\n                ),\n                // LESS THAN OR EQUALS TEST DEFINITIONS\n                RealmAnyParameterizedQueryTest(\n                        filter = RealmAnyParameterizedQueryTests::lessThanOrEqualTo,\n                        arguments = arrayOf(4.toByte()),\n                        expectedResult = arrayOf(0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4.0.toFloat(), 4.0, Decimal128(0), Decimal128(1), Decimal128(2), Decimal128(3), Decimal128(4))\n                ),\n                RealmAnyParameterizedQueryTest(\n                        filter = RealmAnyParameterizedQueryTests::lessThanOrEqualTo,\n                        arguments = arrayOf(4.toShort()),\n                        expectedResult = arrayOf(0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4.0.toFloat(), 4.0, Decimal128(0), Decimal128(1), Decimal128(2), Decimal128(3), Decimal128(4))\n                ),\n                RealmAnyParameterizedQueryTest(\n                        filter = RealmAnyParameterizedQueryTests::lessThanOrEqualTo,\n                        arguments = arrayOf(4.toInt()),\n                        expectedResult = arrayOf(0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4.0.toFloat(), 4.0, Decimal128(0), Decimal128(1), Decimal128(2), Decimal128(3), Decimal128(4))\n                ),\n                RealmAnyParameterizedQueryTest(\n                        filter = RealmAnyParameterizedQueryTests::lessThanOrEqualTo,\n                        arguments = arrayOf(4.toLong()),\n                        expectedResult = arrayOf(0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4.0.toFloat(), 4.0, Decimal128(0), Decimal128(1), Decimal128(2), Decimal128(3), Decimal128(4))\n                ),\n                RealmAnyParameterizedQueryTest(\n                        filter = RealmAnyParameterizedQueryTests::lessThanOrEqualTo,\n                        arguments = arrayOf(4.5.toFloat()),\n                        expectedResult = arrayOf(0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4.0.toFloat(), 4.1.toFloat(), 4.2.toFloat(), 4.3.toFloat(), 4.4.toFloat(), 4.5.toFloat(), 4.0, 4.1, 4.2, 4.3, 4.4, 4.5, Decimal128(0), Decimal128(1), Decimal128(2), Decimal128(3), Decimal128(4))\n                ),\n                RealmAnyParameterizedQueryTest(\n                        filter = RealmAnyParameterizedQueryTests::lessThanOrEqualTo,\n                        arguments = arrayOf(4.325),\n                        expectedResult = arrayOf(0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4.0.toFloat(), 4.1.toFloat(), 4.2.toFloat(), 4.3.toFloat(), 4.0, 4.1, 4.2, 4.3, Decimal128(0), Decimal128(1), Decimal128(2), Decimal128(3), Decimal128(4))\n                ),\n                RealmAnyParameterizedQueryTest(\n                        filter = RealmAnyParameterizedQueryTests::lessThanOrEqualTo,\n                        arguments = arrayOf(Date(3)),\n                        expectedResult = arrayOf(Date(0), Date(1), Date(2), Date(3))\n                ),\n                RealmAnyParameterizedQueryTest(\n                        filter = RealmAnyParameterizedQueryTests::lessThanOrEqualTo,\n                        arguments = arrayOf(Decimal128(3)),\n                        expectedResult = arrayOf(0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, Decimal128(0), Decimal128(1), Decimal128(2), Decimal128(3))\n                ),\n                RealmAnyParameterizedQueryTest(\n                        filter = RealmAnyParameterizedQueryTests::lessThanOrEqualTo,\n                        arguments = arrayOf(ObjectId(TestHelper.generateObjectIdHexString(3))),\n                        expectedResult = arrayOf(ObjectId(TestHelper.generateObjectIdHexString(0)), ObjectId(TestHelper.generateObjectIdHexString(1)), ObjectId(TestHelper.generateObjectIdHexString(2)), ObjectId(TestHelper.generateObjectIdHexString(3)))\n                ),\n                RealmAnyParameterizedQueryTest(\n                        filter = RealmAnyParameterizedQueryTests::lessThanOrEqualTo,\n                        arguments = arrayOf(UUID.fromString(TestHelper.generateUUIDString(3))),\n                        expectedResult = arrayOf(UUID.fromString(TestHelper.generateUUIDString(0)), UUID.fromString(TestHelper.generateUUIDString(1)), UUID.fromString(TestHelper.generateUUIDString(2)), UUID.fromString(TestHelper.generateUUIDString(3)))\n                ),\n                // IN TEST DEFINITIONS\n                RealmAnyParameterizedQueryTest(\n                        filter = RealmAnyParameterizedQueryTests::`in`,\n                        arguments = arrayOf(true, null),\n                        expectedResult = arrayOf(true, *arrayOfNulls(9)),\n                        expandArguments = false\n                ),\n                RealmAnyParameterizedQueryTest(\n                        filter = RealmAnyParameterizedQueryTests::`in`,\n                        arguments = arrayOf(4.toByte(), 2.toByte(), 5.toByte(), 22.toByte(), null),\n                        expectedResult = arrayOf(2, 2, 2, 2, 4, 4, 4, 4, 5, 5, 5, 5, 4.0.toFloat(), 4.0, Decimal128(2), Decimal128(4), *arrayOfNulls(9)),\n                        expandArguments = false\n                ),\n                RealmAnyParameterizedQueryTest(\n                        filter = RealmAnyParameterizedQueryTests::`in`,\n                        arguments = arrayOf(4.toShort(), 2.toShort(), 5.toShort(), 22.toShort(), null),\n                        expectedResult = arrayOf(2, 2, 2, 2, 4, 4, 4, 4, 5, 5, 5, 5, 4.0.toFloat(), 4.0, Decimal128(2), Decimal128(4), *arrayOfNulls(9)),\n                        expandArguments = false\n                ),\n                RealmAnyParameterizedQueryTest(\n                        filter = RealmAnyParameterizedQueryTests::`in`,\n                        arguments = arrayOf(4.toInt(), 2.toInt(), 5.toInt(), 22.toInt(), null),\n                        expectedResult = arrayOf(2, 2, 2, 2, 4, 4, 4, 4, 5, 5, 5, 5, 4.0.toFloat(), 4.0, Decimal128(2), Decimal128(4), *arrayOfNulls(9)),\n                        expandArguments = false\n                ),\n                RealmAnyParameterizedQueryTest(\n                        filter = RealmAnyParameterizedQueryTests::`in`,\n                        arguments = arrayOf(4.toLong(), 2.toLong(), 5.toLong(), 22.toLong(), null),\n                        expectedResult = arrayOf(2, 2, 2, 2, 4, 4, 4, 4, 5, 5, 5, 5, 4.0.toFloat(), 4.0, Decimal128(2), Decimal128(4), *arrayOfNulls(9)),\n                        expandArguments = false\n                ),\n                RealmAnyParameterizedQueryTest(\n                        filter = RealmAnyParameterizedQueryTests::`in`,\n                        arguments = arrayOf(4.8.toFloat(), 8.1.toFloat(), 4.3.toFloat(), 4.0.toFloat(), 4.7.toFloat(), null),\n                        expectedResult = arrayOf(4, 4, 4, 4, 4.0.toFloat(), 4.3.toFloat(), 4.7.toFloat(), 4.8.toFloat(), 4.0, Decimal128(4), *arrayOfNulls(9)),\n                        expandArguments = false\n                ),\n                RealmAnyParameterizedQueryTest(\n                        filter = RealmAnyParameterizedQueryTests::`in`,\n                        arguments = arrayOf(4.8, 8.1, 4.3, 4.0, 4.7, null),\n                        expectedResult = arrayOf(4, 4, 4, 4, 4.0, 4.0, 4.3, 4.7, 4.8, Decimal128(4), *arrayOfNulls(9)),\n                        expandArguments = false\n                ),\n                RealmAnyParameterizedQueryTest(\n                        filter = RealmAnyParameterizedQueryTests::`in`,\n                        arguments = arrayOf(\"hello world 3\", \"hello world 0\", \"hello world 4\", \"realm rocks\", null),\n                        expectedResult = arrayOf(\"hello world 0\", \"hello world 3\", \"hello world 4\", *arrayOfNulls(9)),\n                        expandArguments = false\n                ),\n                RealmAnyParameterizedQueryTest(\n                        filter = RealmAnyParameterizedQueryTests::`in`,\n                        arguments = arrayOf(\n                                byteArrayOf(0, 0, 0),\n                                byteArrayOf(0, 1, 1),\n                                byteArrayOf(1, 1, 0, 0),\n                                byteArrayOf(1, 1, 1),\n                                null\n                        ),\n                        expectedResult = arrayOf(\n                                byteArrayOf(0, 0, 0),\n                                byteArrayOf(0, 1, 1),\n                                byteArrayOf(1, 1, 1),\n                                *arrayOfNulls(9)\n                        ),\n                        expandArguments = false\n                ),\n                RealmAnyParameterizedQueryTest(\n                        filter = RealmAnyParameterizedQueryTests::`in`,\n                        arguments = arrayOf(Date(100), Date(3), null, Date(1)),\n                        expectedResult = arrayOf(Date(1), Date(3), *arrayOfNulls(9)),\n                        expandArguments = false\n                ),\n                RealmAnyParameterizedQueryTest(\n                        filter = RealmAnyParameterizedQueryTests::`in`,\n                        arguments = arrayOf(Decimal128(100), null, Decimal128(3), Decimal128(2)),\n                        expectedResult = arrayOf(2, 2, 2, 2, 3, 3, 3, 3, Decimal128(2), Decimal128(3), *arrayOfNulls(9)),\n                        expandArguments = false\n                ),\n                RealmAnyParameterizedQueryTest(\n                        filter = RealmAnyParameterizedQueryTests::`in`,\n                        arguments = arrayOf(ObjectId(TestHelper.generateObjectIdHexString(3)), null, ObjectId(TestHelper.generateObjectIdHexString(9)), ObjectId(TestHelper.generateObjectIdHexString(1))),\n                        expectedResult = arrayOf(ObjectId(TestHelper.generateObjectIdHexString(1)), ObjectId(TestHelper.generateObjectIdHexString(3)), *arrayOfNulls(9)),\n                        expandArguments = false\n                ),\n                RealmAnyParameterizedQueryTest(\n                        filter = RealmAnyParameterizedQueryTests::`in`,\n                        arguments = arrayOf(UUID.fromString(TestHelper.generateUUIDString(3)), null, UUID.fromString(TestHelper.generateUUIDString(9)), UUID.fromString(TestHelper.generateUUIDString(1))),\n                        expectedResult = arrayOf(UUID.fromString(TestHelper.generateUUIDString(1)), UUID.fromString(TestHelper.generateUUIDString(3)), *arrayOfNulls(9)),\n                        expandArguments = false\n                ),\n                RealmAnyParameterizedQueryTest(\n                        filter = RealmAnyParameterizedQueryTests::`in`,\n                        arguments = arrayOf(PrimaryKeyAsString(\"item 1\"), PrimaryKeyAsString(\"item 3\")),\n                        expectedResult = arrayOf(PrimaryKeyAsString(\"item 1\"), PrimaryKeyAsString(\"item 3\")),\n                        expandArguments = false\n                ),\n                RealmAnyParameterizedQueryTest(\n                        filter = RealmAnyParameterizedQueryTests::`in`,\n                        arguments = arrayOf(PrimaryKeyAsString(\"item 1\"), PrimaryKeyAsString(\"item 3\")),\n                        expectedResult = arrayOf(PrimaryKeyAsString(\"item 1\"), PrimaryKeyAsString(\"item 3\")),\n                        expandArguments = false,\n                        testWithUnmanagedObjects = true\n                ),\n                // BETWEEN TEST DEFINITIONS\n                RealmAnyParameterizedQueryTest(\n                        filter = RealmAnyParameterizedQueryTests::between,\n                        arguments = arrayOf(6.toByte(), 8.toByte()),\n                        expectedResult = arrayOf(6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8)\n                ),\n                RealmAnyParameterizedQueryTest(\n                        filter = RealmAnyParameterizedQueryTests::between,\n                        arguments = arrayOf(6.toShort(), 8.toShort()),\n                        expectedResult = arrayOf(6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8)\n                ),\n                RealmAnyParameterizedQueryTest(\n                        filter = RealmAnyParameterizedQueryTests::between,\n                        arguments = arrayOf(6.toInt(), 8.toInt()),\n                        expectedResult = arrayOf(6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8)\n                ),\n                RealmAnyParameterizedQueryTest(\n                        filter = RealmAnyParameterizedQueryTests::between,\n                        arguments = arrayOf(6.toLong(), 8.toLong()),\n                        expectedResult = arrayOf(6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8)\n                ),\n                RealmAnyParameterizedQueryTest(\n                        filter = RealmAnyParameterizedQueryTests::between,\n                        arguments = arrayOf(4.51.toFloat(), 4.89.toFloat()),\n                        expectedResult = arrayOf(4.6.toFloat(), 4.7.toFloat(), 4.8.toFloat(), 4.6, 4.7, 4.8)\n                ),\n                RealmAnyParameterizedQueryTest(\n                        filter = RealmAnyParameterizedQueryTests::between,\n                        arguments = arrayOf(4.49, 4.89),\n                        expectedResult = arrayOf(4.5.toFloat(), 4.6.toFloat(), 4.7.toFloat(), 4.8.toFloat(), 4.5, 4.6, 4.7, 4.8)\n                ),\n                RealmAnyParameterizedQueryTest(\n                        filter = RealmAnyParameterizedQueryTests::between,\n                        arguments = arrayOf(Date(2), Date(4)),\n                        expectedResult = arrayOf(Date(2), Date(3), Date(4))\n                ),\n                RealmAnyParameterizedQueryTest(\n                        filter = RealmAnyParameterizedQueryTests::between,\n                        arguments = arrayOf(Decimal128(2), Decimal128(4)),\n                        expectedResult = arrayOf(2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4.0.toFloat(), 4.0, Decimal128(2), Decimal128(3), Decimal128(4))\n                ),\n                RealmAnyParameterizedQueryTest(\n                        filter = RealmAnyParameterizedQueryTests::between,\n                        arguments = arrayOf(ObjectId(TestHelper.generateObjectIdHexString(2)), ObjectId(TestHelper.generateObjectIdHexString(4))),\n                        expectedResult = arrayOf(ObjectId(TestHelper.generateObjectIdHexString(2)), ObjectId(TestHelper.generateObjectIdHexString(3)), ObjectId(TestHelper.generateObjectIdHexString(4)))\n                ),\n                RealmAnyParameterizedQueryTest(\n                        filter = RealmAnyParameterizedQueryTests::between,\n                        arguments = arrayOf(UUID.fromString(TestHelper.generateUUIDString(2)), UUID.fromString(TestHelper.generateUUIDString(4))),\n                        expectedResult = arrayOf(UUID.fromString(TestHelper.generateUUIDString(2)), UUID.fromString(TestHelper.generateUUIDString(3)), UUID.fromString(TestHelper.generateUUIDString(4)))\n                ),\n                RealmAnyParameterizedQueryTest(\n                        filter = RealmAnyParameterizedQueryTests::beginsWith,\n                        arguments = arrayOf(\"hello\"),\n                        expectedResult = arrayOf(\"hello world 0\", \"hello world 1\", \"hello world 2\", \"hello world 3\", \"hello world 4\")\n                ),\n                RealmAnyParameterizedQueryTest(\n                        filter = RealmAnyParameterizedQueryTests::beginsWithInsensitive,\n                        arguments = arrayOf(\"hELlo\"),\n                        expectedResult = arrayOf(\"hello world 0\", \"hello world 1\", \"hello world 2\", \"hello world 3\", \"hello world 4\",\n                                \"HELLO WORLD 0\", \"HELLO WORLD 1\", \"HELLO WORLD 2\", \"HELLO WORLD 3\", \"HELLO WORLD 4\")\n                ),\n                RealmAnyParameterizedQueryTest(\n                        filter = RealmAnyParameterizedQueryTests::endsWith,\n                        arguments = arrayOf(\"world 4\"),\n                        expectedResult = arrayOf(\"hello world 4\")\n                ),\n                RealmAnyParameterizedQueryTest(\n                        filter = RealmAnyParameterizedQueryTests::endsWithInsensitive,\n                        arguments = arrayOf(\"wOrld 4\"),\n                        expectedResult = arrayOf(\"hello world 4\",\n                                \"HELLO WORLD 4\")\n                ),\n                RealmAnyParameterizedQueryTest(\n                        filter = RealmAnyParameterizedQueryTests::contains,\n                        arguments = arrayOf(\"world\"),\n                        expectedResult = arrayOf(\"hello world 0\", \"hello world 1\", \"hello world 2\", \"hello world 3\", \"hello world 4\")\n                ),\n                RealmAnyParameterizedQueryTest(\n                        filter = RealmAnyParameterizedQueryTests::containsInsensitive,\n                        arguments = arrayOf(\"WorLD\"),\n                        expectedResult = arrayOf(\"hello world 0\", \"hello world 1\", \"hello world 2\", \"hello world 3\", \"hello world 4\",\n                                \"HELLO WORLD 0\", \"HELLO WORLD 1\", \"HELLO WORLD 2\", \"HELLO WORLD 3\", \"HELLO WORLD 4\")\n                ),\n                RealmAnyParameterizedQueryTest(\n                        filter = RealmAnyParameterizedQueryTests::like,\n                        arguments = arrayOf(\"*w?rld*\"),\n                        expectedResult = arrayOf(\"hello world 0\", \"hello world 1\", \"hello world 2\", \"hello world 3\", \"hello world 4\")\n                ),\n                RealmAnyParameterizedQueryTest(\n                        filter = RealmAnyParameterizedQueryTests::likeInsensitive,\n                        arguments = arrayOf(\"*W?RLD*\"),\n                        expectedResult = arrayOf(\"hello world 0\", \"hello world 1\", \"hello world 2\", \"hello world 3\", \"hello world 4\",\n                                \"HELLO WORLD 0\", \"HELLO WORLD 1\", \"HELLO WORLD 2\", \"HELLO WORLD 3\", \"HELLO WORLD 4\")\n                )\n        )\n    }\n\n    init {\n        Realm.init(InstrumentationRegistry.getInstrumentation().targetContext)\n    }\n\n    @Before\n    fun setUp() {\n        realmConfiguration = configFactory.createSchemaConfiguration(\n                false,\n                RealmAnyNotIndexed::class.java,\n                PrimaryKeyAsString::class.java)\n\n        realm = Realm.getInstance(realmConfiguration)\n\n        initializeTestData()\n    }\n\n    @After\n    fun tearDown() {\n        realm.close()\n    }\n\n    @Test\n    fun primitives() {\n        this.test.execute(this, realm)\n    }\n\n    @Test\n    fun realmAny() {\n        this.test.executeRealmAny(this, realm)\n    }\n\n    @Test\n    fun realmAny_nonManagedRealmModel() {\n        this.test.executeRealmAny_nonManagedRealmModel(this, realm)\n    }\n\n    private fun validate(expected: Array<RealmAny>, results: RealmResults<RealmAnyNotIndexed>, expectedSize: Int) {\n        assertEquals(expectedSize, results.size)\n\n        expected.forEachIndexed { index, item ->\n            val comparing = results[index]!!.realmAny!!\n            assertTrue(item.coercedEquals(comparing), \"Values are not equal $item [vs] $comparing\")\n        }\n    }\n\n    private fun validateNotEqual(expected: Array<RealmAny>, results: RealmResults<RealmAnyNotIndexed>, expectedSize: Int) {\n        assertEquals(expectedSize, results.size)\n\n        expected.forEachIndexed { index, item ->\n            val comparing = results[index]!!.realmAny!!\n            assertFalse(item.coercedEquals(comparing), \"Values are equal $item [vs] $comparing\")\n        }\n    }\n\n    fun equalTo(expected: Array<RealmAny>, expectedSize: Int, value: Any) {\n        val query: RealmQuery<RealmAnyNotIndexed> = realm.where()\n\n        when (value) {\n            is Boolean -> query.equalTo(RealmAnyNotIndexed.FIELD_REALM_ANY, value)\n            is Byte -> query.equalTo(RealmAnyNotIndexed.FIELD_REALM_ANY, value)\n            is Short -> query.equalTo(RealmAnyNotIndexed.FIELD_REALM_ANY, value)\n            is Int -> query.equalTo(RealmAnyNotIndexed.FIELD_REALM_ANY, value)\n            is Long -> query.equalTo(RealmAnyNotIndexed.FIELD_REALM_ANY, value)\n            is Float -> query.equalTo(RealmAnyNotIndexed.FIELD_REALM_ANY, value)\n            is Double -> query.equalTo(RealmAnyNotIndexed.FIELD_REALM_ANY, value)\n            is String -> query.equalTo(RealmAnyNotIndexed.FIELD_REALM_ANY, value)\n            is ByteArray -> query.equalTo(RealmAnyNotIndexed.FIELD_REALM_ANY, value)\n            is Decimal128 -> query.equalTo(RealmAnyNotIndexed.FIELD_REALM_ANY, value)\n            is ObjectId -> query.equalTo(RealmAnyNotIndexed.FIELD_REALM_ANY, value)\n            is UUID -> query.equalTo(RealmAnyNotIndexed.FIELD_REALM_ANY, value)\n            is Date -> query.equalTo(RealmAnyNotIndexed.FIELD_REALM_ANY, value)\n            is RealmAny -> query.equalTo(RealmAnyNotIndexed.FIELD_REALM_ANY, value)\n            is RealmModel -> return\n            else -> throw IllegalStateException(\"EqualTo for type ${value::class.qualifiedName} not implemented\")\n        }\n\n        validate(expected, query.findAll()!!, expectedSize)\n    }\n\n    fun notEqualTo(expected: Array<RealmAny>, expectedSize: Int, value: Any) {\n        val query: RealmQuery<RealmAnyNotIndexed> = realm.where()\n\n        when (value) {\n            is Boolean -> query.notEqualTo(RealmAnyNotIndexed.FIELD_REALM_ANY, value)\n            is Byte -> query.notEqualTo(RealmAnyNotIndexed.FIELD_REALM_ANY, value)\n            is Short -> query.notEqualTo(RealmAnyNotIndexed.FIELD_REALM_ANY, value)\n            is Int -> query.notEqualTo(RealmAnyNotIndexed.FIELD_REALM_ANY, value)\n            is Long -> query.notEqualTo(RealmAnyNotIndexed.FIELD_REALM_ANY, value)\n            is Float -> query.notEqualTo(RealmAnyNotIndexed.FIELD_REALM_ANY, value)\n            is Double -> query.notEqualTo(RealmAnyNotIndexed.FIELD_REALM_ANY, value)\n            is String -> query.notEqualTo(RealmAnyNotIndexed.FIELD_REALM_ANY, value)\n            is ByteArray -> query.notEqualTo(RealmAnyNotIndexed.FIELD_REALM_ANY, value)\n            is Decimal128 -> query.notEqualTo(RealmAnyNotIndexed.FIELD_REALM_ANY, value)\n            is ObjectId -> query.notEqualTo(RealmAnyNotIndexed.FIELD_REALM_ANY, value)\n            is UUID -> query.notEqualTo(RealmAnyNotIndexed.FIELD_REALM_ANY, value)\n            is Date -> query.notEqualTo(RealmAnyNotIndexed.FIELD_REALM_ANY, value)\n            is RealmAny -> query.notEqualTo(RealmAnyNotIndexed.FIELD_REALM_ANY, value)\n            is RealmModel -> return\n            else -> throw IllegalStateException(\"NotEqualTo for type ${value::class.qualifiedName} not implemented\")\n        }\n\n        validateNotEqual(expected, query.findAll()!!, expectedSize)\n    }\n\n    fun equalToInsensitive(expected: Array<RealmAny>, expectedSize: Int, value: Any) {\n        val query: RealmQuery<RealmAnyNotIndexed> = realm.where()\n\n        when (value) {\n            is String -> query.equalTo(RealmAnyNotIndexed.FIELD_REALM_ANY, value, Case.INSENSITIVE)\n            is RealmAny -> query.equalTo(RealmAnyNotIndexed.FIELD_REALM_ANY, value, Case.INSENSITIVE)\n            else -> throw IllegalStateException(\"EqualTo[c] for type ${value::class.qualifiedName} not implemented\")\n        }\n\n        validate(expected, query.findAll()!!, expectedSize)\n    }\n\n    fun notEqualToInsensitive(expected: Array<RealmAny>, expectedSize: Int, value: Any) {\n        val query: RealmQuery<RealmAnyNotIndexed> = realm.where()\n\n        when (value) {\n            is String -> query.notEqualTo(RealmAnyNotIndexed.FIELD_REALM_ANY, value, Case.INSENSITIVE)\n            is RealmAny -> query.notEqualTo(RealmAnyNotIndexed.FIELD_REALM_ANY, value, Case.INSENSITIVE)\n            else -> throw IllegalStateException(\"NotEqualTo[c] for type ${value::class.qualifiedName} not implemented\")\n        }\n\n        validateNotEqual(expected, query.findAll()!!, expectedSize)\n    }\n\n    fun greaterThanOrEqualTo(expected: Array<RealmAny>, expectedSize: Int, value: Any) {\n        val query: RealmQuery<RealmAnyNotIndexed> = realm.where()\n\n        when (value) {\n            is Int -> query.greaterThanOrEqualTo(RealmAnyNotIndexed.FIELD_REALM_ANY, value)\n            is Long -> query.greaterThanOrEqualTo(RealmAnyNotIndexed.FIELD_REALM_ANY, value)\n            is Float -> query.greaterThanOrEqualTo(RealmAnyNotIndexed.FIELD_REALM_ANY, value)\n            is Double -> query.greaterThanOrEqualTo(RealmAnyNotIndexed.FIELD_REALM_ANY, value)\n            is Decimal128 -> query.greaterThanOrEqualTo(RealmAnyNotIndexed.FIELD_REALM_ANY, value)\n            is ObjectId -> query.greaterThanOrEqualTo(RealmAnyNotIndexed.FIELD_REALM_ANY, value)\n            is UUID -> query.greaterThanOrEqualTo(RealmAnyNotIndexed.FIELD_REALM_ANY, value)\n            is Date -> query.greaterThanOrEqualTo(RealmAnyNotIndexed.FIELD_REALM_ANY, value)\n            is RealmAny -> query.greaterThanOrEqualTo(RealmAnyNotIndexed.FIELD_REALM_ANY, value)\n            is Byte -> return\n            is Short -> return\n            else -> throw IllegalStateException(\"GreaterThanOrEqualTo for type ${value::class.qualifiedName} not implemented\")\n        }\n\n        validate(expected, query.findAll()!!, expectedSize)\n    }\n\n    fun greaterThan(expected: Array<RealmAny>, expectedSize: Int, value: Any) {\n        val query: RealmQuery<RealmAnyNotIndexed> = realm.where()\n\n        when (value) {\n            is Int -> query.greaterThan(RealmAnyNotIndexed.FIELD_REALM_ANY, value)\n            is Long -> query.greaterThan(RealmAnyNotIndexed.FIELD_REALM_ANY, value)\n            is Float -> query.greaterThan(RealmAnyNotIndexed.FIELD_REALM_ANY, value)\n            is Double -> query.greaterThan(RealmAnyNotIndexed.FIELD_REALM_ANY, value)\n            is Decimal128 -> query.greaterThan(RealmAnyNotIndexed.FIELD_REALM_ANY, value)\n            is ObjectId -> query.greaterThan(RealmAnyNotIndexed.FIELD_REALM_ANY, value)\n            is UUID -> query.greaterThan(RealmAnyNotIndexed.FIELD_REALM_ANY, value)\n            is Date -> query.greaterThan(RealmAnyNotIndexed.FIELD_REALM_ANY, value)\n            is RealmAny -> query.greaterThan(RealmAnyNotIndexed.FIELD_REALM_ANY, value)\n            is Byte -> return\n            is Short -> return\n            else -> throw IllegalStateException(\"GreaterThan for type ${value::class.qualifiedName} not implemented\")\n        }\n\n        validate(expected, query.findAll()!!, expectedSize)\n    }\n\n    fun lessThanOrEqualTo(expected: Array<RealmAny>, expectedSize: Int, value: Any) {\n        val query: RealmQuery<RealmAnyNotIndexed> = realm.where()\n\n        when (value) {\n            is Int -> query.lessThanOrEqualTo(RealmAnyNotIndexed.FIELD_REALM_ANY, value)\n            is Long -> query.lessThanOrEqualTo(RealmAnyNotIndexed.FIELD_REALM_ANY, value)\n            is Float -> query.lessThanOrEqualTo(RealmAnyNotIndexed.FIELD_REALM_ANY, value)\n            is Double -> query.lessThanOrEqualTo(RealmAnyNotIndexed.FIELD_REALM_ANY, value)\n            is Decimal128 -> query.lessThanOrEqualTo(RealmAnyNotIndexed.FIELD_REALM_ANY, value)\n            is ObjectId -> query.lessThanOrEqualTo(RealmAnyNotIndexed.FIELD_REALM_ANY, value)\n            is UUID -> query.lessThanOrEqualTo(RealmAnyNotIndexed.FIELD_REALM_ANY, value)\n            is Date -> query.lessThanOrEqualTo(RealmAnyNotIndexed.FIELD_REALM_ANY, value)\n            is RealmAny -> query.lessThanOrEqualTo(RealmAnyNotIndexed.FIELD_REALM_ANY, value)\n            is Byte -> return\n            is Short -> return\n            else -> throw IllegalStateException(\"LessThanOrEqualTo for type ${value::class.qualifiedName} not implemented\")\n        }\n\n        validate(expected, query.findAll()!!, expectedSize)\n    }\n\n    fun lessThan(expected: Array<RealmAny>, expectedSize: Int, value: Any) {\n        val query: RealmQuery<RealmAnyNotIndexed> = realm.where()\n\n        when (value) {\n            is Int -> query.lessThan(RealmAnyNotIndexed.FIELD_REALM_ANY, value)\n            is Long -> query.lessThan(RealmAnyNotIndexed.FIELD_REALM_ANY, value)\n            is Float -> query.lessThan(RealmAnyNotIndexed.FIELD_REALM_ANY, value)\n            is Double -> query.lessThan(RealmAnyNotIndexed.FIELD_REALM_ANY, value)\n            is Decimal128 -> query.lessThan(RealmAnyNotIndexed.FIELD_REALM_ANY, value)\n            is ObjectId -> query.lessThan(RealmAnyNotIndexed.FIELD_REALM_ANY, value)\n            is UUID -> query.lessThan(RealmAnyNotIndexed.FIELD_REALM_ANY, value)\n            is Date -> query.lessThan(RealmAnyNotIndexed.FIELD_REALM_ANY, value)\n            is RealmAny -> query.lessThan(RealmAnyNotIndexed.FIELD_REALM_ANY, value)\n            is Byte -> return\n            is Short -> return\n            else -> throw IllegalStateException(\"LessThan for type ${value::class.qualifiedName} not implemented\")\n        }\n\n        validate(expected, query.findAll()!!, expectedSize)\n    }\n\n    private inline fun <reified T> convertToType(value: Array<Any?>): Array<T> {\n        return Array(value.size) { i ->\n            value[i] as T\n        }\n    }\n\n    @Suppress(\"UNCHECKED_CAST\")\n    fun `in`(expected: Array<RealmAny>, expectedSize: Int, value: Array<Any?>) {\n        val query: RealmQuery<RealmAnyNotIndexed> = realm.where()\n\n        if (value.isNotEmpty()) {\n            when (value[0]) {\n                is Boolean -> query.`in`(RealmAnyNotIndexed.FIELD_REALM_ANY, convertToType<Boolean?>(value))\n                is Byte -> query.`in`(RealmAnyNotIndexed.FIELD_REALM_ANY, convertToType<Byte?>(value))\n                is Short -> query.`in`(RealmAnyNotIndexed.FIELD_REALM_ANY, convertToType<Short?>(value))\n                is Int -> query.`in`(RealmAnyNotIndexed.FIELD_REALM_ANY, convertToType<Int?>(value))\n                is Long -> query.`in`(RealmAnyNotIndexed.FIELD_REALM_ANY, convertToType<Long?>(value))\n                is Float -> query.`in`(RealmAnyNotIndexed.FIELD_REALM_ANY, convertToType<Float?>(value))\n                is Double -> query.`in`(RealmAnyNotIndexed.FIELD_REALM_ANY, convertToType<Double?>(value))\n                is String -> query.`in`(RealmAnyNotIndexed.FIELD_REALM_ANY, convertToType<String?>(value))\n                is Date -> query.`in`(RealmAnyNotIndexed.FIELD_REALM_ANY, convertToType<Date?>(value))\n                is RealmAny -> query.`in`(RealmAnyNotIndexed.FIELD_REALM_ANY, convertToType<RealmAny?>(value))\n                is Decimal128 -> return\n                is ObjectId -> return\n                is UUID -> return\n                is ByteArray -> return\n                is RealmModel -> return\n                else -> throw IllegalStateException(\"In for type ${value::class.qualifiedName} not implemented\")\n            }\n        }\n\n        validate(expected, query.findAll()!!, expectedSize)\n    }\n\n    fun between(expected: Array<RealmAny>, expectedSize: Int, value1: Any, value2: Any) {\n        val query: RealmQuery<RealmAnyNotIndexed> = realm.where()\n\n        when (value1) {\n            is Int -> query.between(RealmAnyNotIndexed.FIELD_REALM_ANY, value1, value2 as Int)\n            is Long -> query.between(RealmAnyNotIndexed.FIELD_REALM_ANY, value1, value2 as Long)\n            is Float -> query.between(RealmAnyNotIndexed.FIELD_REALM_ANY, value1, value2 as Float)\n            is Double -> query.between(RealmAnyNotIndexed.FIELD_REALM_ANY, value1, value2 as Double)\n            is Decimal128 -> query.between(RealmAnyNotIndexed.FIELD_REALM_ANY, value1, value2 as Decimal128)\n            is Date -> query.between(RealmAnyNotIndexed.FIELD_REALM_ANY, value1, value2 as Date)\n            is RealmAny -> query.between(RealmAnyNotIndexed.FIELD_REALM_ANY, value1, value2 as RealmAny)\n            is Byte -> return\n            is Short -> return\n            is ObjectId -> return\n            is UUID -> return\n            else -> throw IllegalStateException(\"Between for type ${value1::class.qualifiedName} not implemented\")\n        }\n\n        validate(expected, query.findAll()!!, expectedSize)\n    }\n\n    fun beginsWith(expected: Array<RealmAny>, expectedSize: Int, value: Any) {\n        val query: RealmQuery<RealmAnyNotIndexed> = realm.where()\n\n        when (value) {\n            is String -> query.beginsWith(RealmAnyNotIndexed.FIELD_REALM_ANY, value)\n            is RealmAny -> query.beginsWith(RealmAnyNotIndexed.FIELD_REALM_ANY, value)\n            else -> throw IllegalStateException(\"BeginsWith for type ${value::class.qualifiedName} not implemented\")\n        }\n\n        validate(expected, query.findAll()!!, expectedSize)\n    }\n\n    fun beginsWithInsensitive(expected: Array<RealmAny>, expectedSize: Int, value: Any) {\n        val query: RealmQuery<RealmAnyNotIndexed> = realm.where()\n\n        when (value) {\n            is String -> query.beginsWith(RealmAnyNotIndexed.FIELD_REALM_ANY, value, Case.INSENSITIVE)\n            is RealmAny -> query.beginsWith(RealmAnyNotIndexed.FIELD_REALM_ANY, value, Case.INSENSITIVE)\n            else -> throw IllegalStateException(\"BeginsWith for type ${value::class.qualifiedName} not implemented\")\n        }\n\n        validate(expected, query.findAll()!!, expectedSize)\n    }\n\n    fun endsWith(expected: Array<RealmAny>, expectedSize: Int, value: Any) {\n        val query: RealmQuery<RealmAnyNotIndexed> = realm.where()\n\n        when (value) {\n            is String -> query.endsWith(RealmAnyNotIndexed.FIELD_REALM_ANY, value)\n            is RealmAny -> query.endsWith(RealmAnyNotIndexed.FIELD_REALM_ANY, value)\n            else -> throw IllegalStateException(\"EndsWith for type ${value::class.qualifiedName} not implemented\")\n        }\n\n        validate(expected, query.findAll()!!, expectedSize)\n    }\n\n    fun endsWithInsensitive(expected: Array<RealmAny>, expectedSize: Int, value: Any) {\n        val query: RealmQuery<RealmAnyNotIndexed> = realm.where()\n\n        when (value) {\n            is String -> query.endsWith(RealmAnyNotIndexed.FIELD_REALM_ANY, value, Case.INSENSITIVE)\n            is RealmAny -> query.endsWith(RealmAnyNotIndexed.FIELD_REALM_ANY, value, Case.INSENSITIVE)\n            else -> throw IllegalStateException(\"EndsWith for type ${value::class.qualifiedName} not implemented\")\n        }\n\n        validate(expected, query.findAll()!!, expectedSize)\n    }\n\n    fun contains(expected: Array<RealmAny>, expectedSize: Int, value: Any) {\n        val query: RealmQuery<RealmAnyNotIndexed> = realm.where()\n\n        when (value) {\n            is String -> query.contains(RealmAnyNotIndexed.FIELD_REALM_ANY, value)\n            is RealmAny -> query.contains(RealmAnyNotIndexed.FIELD_REALM_ANY, value)\n            else -> throw IllegalStateException(\"Contains for type ${value::class.qualifiedName} not implemented\")\n        }\n\n        validate(expected, query.findAll()!!, expectedSize)\n    }\n\n    fun containsInsensitive(expected: Array<RealmAny>, expectedSize: Int, value: Any) {\n        val query: RealmQuery<RealmAnyNotIndexed> = realm.where()\n\n        when (value) {\n            is String -> query.contains(RealmAnyNotIndexed.FIELD_REALM_ANY, value, Case.INSENSITIVE)\n            is RealmAny -> query.contains(RealmAnyNotIndexed.FIELD_REALM_ANY, value, Case.INSENSITIVE)\n            else -> throw IllegalStateException(\"Contains for type ${value::class.qualifiedName} not implemented\")\n        }\n\n        validate(expected, query.findAll()!!, expectedSize)\n    }\n\n    fun like(expected: Array<RealmAny>, expectedSize: Int, value: Any) {\n        val query: RealmQuery<RealmAnyNotIndexed> = realm.where()\n\n        when (value) {\n            is String -> query.like(RealmAnyNotIndexed.FIELD_REALM_ANY, value)\n            is RealmAny -> query.like(RealmAnyNotIndexed.FIELD_REALM_ANY, value)\n            else -> throw IllegalStateException(\"Like for type ${value::class.qualifiedName} not implemented\")\n        }\n\n        validate(expected, query.findAll()!!, expectedSize)\n    }\n\n    fun likeInsensitive(expected: Array<RealmAny>, expectedSize: Int, value: Any) {\n        val query: RealmQuery<RealmAnyNotIndexed> = realm.where()\n\n        when (value) {\n            is String -> query.like(RealmAnyNotIndexed.FIELD_REALM_ANY, value, Case.INSENSITIVE)\n            is RealmAny -> query.like(RealmAnyNotIndexed.FIELD_REALM_ANY, value, Case.INSENSITIVE)\n            else -> throw IllegalStateException(\"Like for type ${value::class.qualifiedName} not implemented\")\n        }\n\n        validate(expected, query.findAll()!!, expectedSize)\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/kotlin/io/realm/realmany/RealmAnyPrimitiveBulkInserts.kt",
    "content": "/*\n * Copyright 2020 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\npackage io.realm.realmany\n\nimport androidx.test.platform.app.InstrumentationRegistry\nimport io.realm.*\nimport io.realm.entities.*\nimport io.realm.kotlin.createObject\nimport io.realm.kotlin.where\nimport org.bson.types.Decimal128\nimport org.bson.types.ObjectId\nimport org.junit.After\nimport org.junit.Before\nimport org.junit.Rule\nimport org.junit.Test\nimport org.junit.rules.TemporaryFolder\nimport org.junit.runner.RunWith\nimport org.junit.runners.Parameterized\nimport java.util.*\nimport kotlin.test.assertEquals\nimport kotlin.test.assertTrue\n\n@RunWith(Parameterized::class)\nclass RealmAnyPrimitivesBulkInsertsTests(\n        private val testingType: RealmAny.Type,\n        private val first: RealmAny,\n        private val second: RealmAny\n) {\n    companion object {\n        @JvmStatic\n        @Parameterized.Parameters\n        fun data(): MutableList<Array<Any>> {\n            val list = mutableListOf<Array<Any>>()\n\n            for (type in RealmAny.Type.values()) {\n                when (type) {\n                    RealmAny.Type.INTEGER -> {\n                        list.add(arrayOf(RealmAny.Type.INTEGER,\n                                RealmAny.valueOf(1.toByte()),\n                                RealmAny.valueOf(10.toByte())\n                        ))\n                        list.add(arrayOf(RealmAny.Type.INTEGER,\n                                RealmAny.valueOf(2.toShort()),\n                                RealmAny.valueOf(20.toShort())\n                        ))\n                        list.add(arrayOf(RealmAny.Type.INTEGER,\n                                RealmAny.valueOf(3.toInt()),\n                                RealmAny.valueOf(30.toInt())\n                        ))\n                        list.add(arrayOf(RealmAny.Type.INTEGER,\n                                RealmAny.valueOf(4.toLong()),\n                                RealmAny.valueOf(40.toLong())\n                        ))\n                    }\n                    RealmAny.Type.BOOLEAN -> list.add(arrayOf(\n                            RealmAny.Type.BOOLEAN,\n                            RealmAny.valueOf(false),\n                            RealmAny.valueOf(true)\n                    ))\n                    RealmAny.Type.STRING -> list.add(arrayOf(\n                            RealmAny.Type.STRING,\n                            RealmAny.valueOf(\"hello world1\"),\n                            RealmAny.valueOf(\"hello world2\")\n                    ))\n                    RealmAny.Type.BINARY -> list.add(arrayOf(\n                            RealmAny.Type.BINARY,\n                            RealmAny.valueOf(byteArrayOf(0, 1, 0)),\n                            RealmAny.valueOf(byteArrayOf(0, 1, 1))\n                    ))\n                    RealmAny.Type.DATE -> list.add(arrayOf(\n                            RealmAny.Type.DATE,\n                            RealmAny.valueOf(Date(0)),\n                            RealmAny.valueOf(Date(10))\n                    ))\n                    RealmAny.Type.FLOAT -> list.add(arrayOf(\n                            RealmAny.Type.FLOAT,\n                            RealmAny.valueOf(5.toFloat()),\n                            RealmAny.valueOf(50.toFloat())\n                    ))\n                    RealmAny.Type.DOUBLE -> list.add(arrayOf(\n                            RealmAny.Type.DOUBLE,\n                            RealmAny.valueOf(6.toDouble()),\n                            RealmAny.valueOf(60.toDouble())\n                    ))\n                    RealmAny.Type.DECIMAL128 -> list.add(arrayOf(\n                            RealmAny.Type.DECIMAL128,\n                            RealmAny.valueOf(Decimal128(1)),\n                            RealmAny.valueOf(Decimal128(10))\n                    ))\n                    RealmAny.Type.OBJECT_ID -> list.add(arrayOf(\n                            RealmAny.Type.OBJECT_ID,\n                            RealmAny.valueOf(ObjectId(Date(10))),\n                            RealmAny.valueOf(ObjectId(Date(100)))\n                    ))\n                    RealmAny.Type.UUID -> list.add(arrayOf(\n                            RealmAny.Type.UUID,\n                            RealmAny.valueOf(UUID.randomUUID()),\n                            RealmAny.valueOf(UUID.randomUUID())\n                    ))\n                    RealmAny.Type.OBJECT,   // Not tested in this test suite\n                    RealmAny.Type.NULL\n                    -> { // Not tested directly\n                    }\n\n                    else -> throw AssertionError(\"Missing case for type: ${type.name}\")\n                }\n            }\n\n            return list\n        }\n    }\n\n    private lateinit var realmConfiguration: RealmConfiguration\n    private lateinit var realm: Realm\n\n    @get:Rule\n    val configFactory = TestRealmConfigurationFactory()\n\n    init {\n        Realm.init(InstrumentationRegistry.getInstrumentation().targetContext)\n    }\n\n    @Before\n    fun setUp() {\n        realmConfiguration = configFactory.createSchemaConfiguration(\n                false,\n                RealmAnyNotIndexed::class.java,\n                RealmAnyIndexed::class.java,\n                AllJavaTypes::class.java,\n                RealmAnyRealmListWithPK::class.java,\n                RealmAnyNotIndexedWithPK::class.java,\n                PrimaryKeyAsString::class.java)\n\n        realm = Realm.getInstance(realmConfiguration)\n    }\n\n    @After\n    fun tearDown() {\n        realm.close()\n    }\n\n    @Test\n    fun copyFromRealm() {\n        realm.beginTransaction()\n        val value = realm.createObject<RealmAnyNotIndexedWithPK>(0)\n        value.realmAny = first\n        realm.commitTransaction()\n\n        val copy = realm.copyFromRealm(value)\n\n        if (testingType == RealmAny.Type.BINARY) {\n            assertTrue(Arrays.equals(first.asBinary(), copy.realmAny!!.asBinary()))\n        } else {\n            assertEquals(first, copy.realmAny)\n        }\n    }\n\n    @Test\n    fun copyToRealm_primitive() {\n        val value = RealmAnyNotIndexedWithPK()\n        value.realmAny = first\n\n        realm.beginTransaction()\n        val managedValue = realm.copyToRealm(value)\n        realm.commitTransaction()\n\n        if (testingType == RealmAny.Type.BINARY) {\n            assertTrue(Arrays.equals(first.asBinary(), managedValue.realmAny!!.asBinary()))\n        } else {\n            assertEquals(first, managedValue.realmAny)\n        }\n    }\n\n\n    @Test\n    fun copyToRealmOrUpdate_primitive() {\n        realm.executeTransaction { realm ->\n            val obj = realm.createObject<RealmAnyNotIndexedWithPK>(0)\n            obj.realmAny = first\n        }\n\n        val value = RealmAnyNotIndexedWithPK()\n        value.realmAny = second\n\n        realm.beginTransaction()\n        val managedValue = realm.copyToRealmOrUpdate(value)\n        realm.commitTransaction()\n\n        if (testingType == RealmAny.Type.BINARY) {\n            assertTrue(Arrays.equals(second.asBinary(), managedValue.realmAny!!.asBinary()))\n        } else {\n            assertEquals(second, managedValue.realmAny!!)\n        }\n    }\n\n    @Test\n    fun insert_primitive() {\n        realm.executeTransaction { realm ->\n            val value = RealmAnyNotIndexedWithPK()\n            value.realmAny = first\n\n            realm.insert(value)\n        }\n\n        val managedValue = realm.where<RealmAnyNotIndexedWithPK>().findFirst()!!\n\n        if (testingType == RealmAny.Type.BINARY) {\n            assertTrue(Arrays.equals(first.asBinary(), managedValue.realmAny!!.asBinary()))\n        } else {\n            assertEquals(first, managedValue.realmAny)\n        }\n    }\n\n    @Test\n    fun insertOrUpdate_primitive() {\n        realm.executeTransaction { realm ->\n            val value = realm.createObject<RealmAnyNotIndexedWithPK>(0)\n            value.realmAny = first\n        }\n\n        realm.executeTransaction { realm ->\n            val value = RealmAnyNotIndexedWithPK()\n            value.realmAny = second\n\n            realm.insertOrUpdate(value)\n        }\n\n        val all = realm.where<RealmAnyNotIndexedWithPK>().findAll()\n\n        assertEquals(1, all.size)\n\n        if (testingType == RealmAny.Type.BINARY) {\n            assertTrue(Arrays.equals(second.asBinary(), all[0]!!.realmAny!!.asBinary()))\n        } else {\n            assertEquals(second, all[0]!!.realmAny)\n        }\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/kotlin/io/realm/realmany/RealmAnyQueryTests.kt",
    "content": "/*\n * Copyright 2021 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\npackage io.realm.realmany\n\nimport androidx.test.ext.junit.runners.AndroidJUnit4\nimport androidx.test.platform.app.InstrumentationRegistry\nimport io.realm.*\nimport io.realm.entities.PrimaryKeyAsString\nimport io.realm.entities.RealmAnyNotIndexed\nimport io.realm.kotlin.where\nimport org.bson.types.Decimal128\nimport org.junit.After\nimport org.junit.Before\nimport org.junit.Rule\nimport org.junit.Test\nimport org.junit.runner.RunWith\nimport java.util.*\nimport kotlin.collections.HashSet\nimport kotlin.test.assertEquals\nimport kotlin.test.assertFailsWith\nimport kotlin.test.assertFalse\nimport kotlin.test.assertTrue\n\n@RunWith(AndroidJUnit4::class)\nclass RealmAnyQueryTests {\n    private lateinit var realmConfiguration: RealmConfiguration\n    private lateinit var realm: Realm\n\n    private fun initializeTestData() {\n        val realmAnyValues = RealmAnyHelper.generateRealmAnyValues()\n\n        realm.beginTransaction()\n\n        for (value in realmAnyValues) {\n            val realmAnyObject = RealmAnyNotIndexed(value)\n            realm.insert(realmAnyObject)\n        }\n\n        realm.commitTransaction()\n    }\n    \n    @get:Rule\n    val configFactory = TestRealmConfigurationFactory()\n\n    init {\n        Realm.init(InstrumentationRegistry.getInstrumentation().targetContext)\n    }\n\n    @Before\n    fun setUp() {\n        realmConfiguration = configFactory.createSchemaConfiguration(\n                false,\n                RealmAnyNotIndexed::class.java,\n                PrimaryKeyAsString::class.java)\n\n        realm = Realm.getInstance(realmConfiguration)\n    }\n\n    @After\n    fun tearDown() {\n        realm.close()\n    }\n\n    @Test\n    fun isNull() {\n        initializeTestData()\n        val results = realm.where<RealmAnyNotIndexed>().isNull(RealmAnyNotIndexed.FIELD_REALM_ANY).findAll()\n        assertEquals(9, results.size)\n        for (result in results) {\n            assertTrue(result.realmAny!!.isNull)\n        }\n    }\n\n    @Test\n    fun isNotNull() {\n        initializeTestData()\n        val results = realm.where<RealmAnyNotIndexed>().isNotNull(RealmAnyNotIndexed.FIELD_REALM_ANY).findAll()\n        assertEquals(103, results.size)\n        for (result in results) {\n            assertFalse(result.realmAny!!.isNull)\n        }\n    }\n\n    @Test\n    fun isEmpty() {\n        initializeTestData()\n        val query: RealmQuery<RealmAnyNotIndexed> = realm.where()\n        assertFailsWith<IllegalArgumentException> {\n            query.isEmpty(RealmAnyNotIndexed.FIELD_REALM_ANY)\n        }\n    }\n\n    @Test\n    fun isNotEmpty() {\n        initializeTestData()\n        val query: RealmQuery<RealmAnyNotIndexed> = realm.where()\n        assertFailsWith<IllegalArgumentException> {\n            query.isEmpty(RealmAnyNotIndexed.FIELD_REALM_ANY)\n        }\n    }\n\n    @Test\n    fun count() {\n        initializeTestData()\n        val value = realm.where<RealmAnyNotIndexed>().count()\n        assertEquals(112, value)\n    }\n\n    @Test\n    fun average() {\n        initializeTestData()\n        val value = realm.where<RealmAnyNotIndexed>().averageRealmAny(RealmAnyNotIndexed.FIELD_REALM_ANY)\n        assertEquals(Decimal128.parse(\"4.292307692307692307692307692307692\"), value)\n    }\n\n    @Test\n    fun sum() {\n        initializeTestData()\n        val value = realm.where<RealmAnyNotIndexed>().sum(RealmAnyNotIndexed.FIELD_REALM_ANY)\n        assertEquals(Decimal128.parse(\"279.00000000000000\"), value)\n    }\n\n    @Test\n    fun min() {\n        initializeTestData()\n        val value = realm.where<RealmAnyNotIndexed>().minRealmAny(RealmAnyNotIndexed.FIELD_REALM_ANY)\n\n        assertFalse(value.isNull)\n        assertEquals(RealmAny.Type.BOOLEAN, value.type)\n        assertFalse(value.asBoolean())\n    }\n\n    @Test\n    fun max() {\n        initializeTestData()\n        val value = realm.where<RealmAnyNotIndexed>().maxRealmAny(RealmAnyNotIndexed.FIELD_REALM_ANY)!!\n        assertEquals(\"item 5\", value.asRealmModel(PrimaryKeyAsString::class.java).name)\n    }\n\n    @Test\n    fun sort() {\n        initializeTestData()\n        val results = realm.where<RealmAnyNotIndexed>().sort(RealmAnyNotIndexed.FIELD_REALM_ANY).findAll()\n        assertEquals(112, results.size)\n        assertTrue(results.first()!!.realmAny!!.isNull)\n        assertEquals(RealmAny.Type.OBJECT, results.last()!!.realmAny!!.type)\n    }\n\n    @Test\n    fun distinct() {\n        initializeTestData()\n        val results = realm.where<RealmAnyNotIndexed>().distinct(RealmAnyNotIndexed.FIELD_REALM_ANY).findAll()\n\n        val hashSet = HashSet<RealmAny>()\n        for (result in results) {\n            hashSet.add(result.realmAny!!)\n        }\n        assertEquals(66, results.size)\n        assertEquals(hashSet.size, results.size)\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/kotlin/io/realm/realmany/RealmAnyTests.kt",
    "content": "/*\n * Copyright 2020 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\npackage io.realm.realmany\n\nimport androidx.test.ext.junit.runners.AndroidJUnit4\nimport androidx.test.platform.app.InstrumentationRegistry\nimport io.realm.*\nimport io.realm.entities.*\nimport io.realm.entities.embedded.SimpleEmbeddedObject\nimport io.realm.kotlin.createObject\nimport io.realm.kotlin.where\nimport io.realm.rule.BlockingLooperThread\nimport org.bson.types.Decimal128\nimport org.bson.types.ObjectId\nimport org.junit.After\nimport org.junit.Before\nimport org.junit.Rule\nimport org.junit.Test\nimport org.junit.runner.RunWith\nimport java.util.*\nimport kotlin.test.*\n\n\n@RunWith(AndroidJUnit4::class)\nclass RealmAnyTests {\n    private lateinit var realmConfiguration: RealmConfiguration\n    private lateinit var realm: Realm\n\n    @get:Rule\n    val configFactory = TestRealmConfigurationFactory()\n\n    init {\n        Realm.init(InstrumentationRegistry.getInstrumentation().targetContext)\n    }\n\n    @Before\n    fun setUp() {\n        realmConfiguration = configFactory.createSchemaConfiguration(\n                false,\n                RealmAnyNotIndexed::class.java,\n                RealmAnyIndexed::class.java,\n                AllJavaTypes::class.java,\n                RealmAnyNotIndexedWithPK::class.java,\n                SimpleEmbeddedObject::class.java,\n                RealmAnyDefaultPK::class.java,\n                RealmAnyDefaultNonPK::class.java,\n                PrimaryKeyAsString::class.java)\n\n        realm = Realm.getInstance(realmConfiguration)\n    }\n\n    @After\n    fun tearDown() {\n        realm.close()\n    }\n\n    // Unmanaged\n    @Test\n    fun unmanaged_byteValue() {\n        val realmAny = RealmAny.valueOf(10.toByte())\n\n        assertEquals(10, realmAny.asByte())\n        assertEquals(RealmAny.valueOf(10.toByte()), realmAny)\n        assertEquals(RealmAny.Type.INTEGER, realmAny.type)\n        assertEquals(RealmAny.Type.INTEGER.typedClass, realmAny.valueClass)\n    }\n\n    @Test\n    fun unmanaged_shortValue() {\n        val realmAny = RealmAny.valueOf(10.toShort())\n\n        assertEquals(10, realmAny.asShort())\n        assertEquals(RealmAny.valueOf(10.toShort()), realmAny)\n        assertEquals(RealmAny.Type.INTEGER, realmAny.type)\n        assertEquals(RealmAny.Type.INTEGER.typedClass, realmAny.valueClass)\n    }\n\n    @Test\n    fun unmanaged_integerValue() {\n        val realmAny = RealmAny.valueOf(10.toInt())\n\n        assertEquals(10, realmAny.asInteger())\n        assertEquals(RealmAny.valueOf(10.toInt()), realmAny)\n        assertEquals(RealmAny.Type.INTEGER, realmAny.type)\n        assertEquals(RealmAny.Type.INTEGER.typedClass, realmAny.valueClass)\n    }\n\n    @Test\n    fun unmanaged_longValue() {\n        val realmAny = RealmAny.valueOf(10.toLong())\n\n        assertEquals(10, realmAny.asLong())\n        assertEquals(RealmAny.valueOf(10.toLong()), realmAny)\n        assertEquals(RealmAny.Type.INTEGER, realmAny.type)\n        assertEquals(RealmAny.Type.INTEGER.typedClass, realmAny.valueClass)\n    }\n\n    @Test\n    fun unmanaged_booleanValue() {\n        val realmAny = RealmAny.valueOf(true)\n\n        assertEquals(true, realmAny.asBoolean())\n        assertEquals(RealmAny.valueOf(true), realmAny)\n        assertEquals(RealmAny.Type.BOOLEAN, realmAny.type)\n        assertEquals(RealmAny.Type.BOOLEAN.typedClass, realmAny.valueClass)\n    }\n\n    @Test\n    fun unmanaged_stringValue() {\n        val realmAny = RealmAny.valueOf(\"hello world\")\n\n        assertEquals(\"hello world\", realmAny.asString())\n        assertEquals(RealmAny.valueOf(\"hello world\"), realmAny)\n        assertEquals(RealmAny.Type.STRING, realmAny.type)\n        assertEquals(RealmAny.Type.STRING.typedClass, realmAny.valueClass)\n    }\n\n    @Test\n    fun unmanaged_binaryValue() {\n        val realmAny = RealmAny.valueOf(byteArrayOf(0, 1, 0))\n\n        assertTrue(Arrays.equals(byteArrayOf(0, 1, 0), realmAny.asBinary()))\n        assertEquals(RealmAny.valueOf(byteArrayOf(0, 1, 0)), realmAny)\n        assertEquals(RealmAny.Type.BINARY, realmAny.type)\n        assertEquals(RealmAny.Type.BINARY.typedClass, realmAny.valueClass)\n    }\n\n    @Test\n    fun unmanaged_dateValue() {\n        val realmAny = RealmAny.valueOf(Date(10))\n\n        assertEquals(Date(10), realmAny.asDate())\n        assertEquals(RealmAny.valueOf(Date(10)), realmAny)\n        assertEquals(RealmAny.Type.DATE, realmAny.type)\n        assertEquals(RealmAny.Type.DATE.typedClass, realmAny.valueClass)\n    }\n\n    @Test\n    fun unmanaged_decimal128Value() {\n        val realmAny = RealmAny.valueOf(Decimal128.fromIEEE754BIDEncoding(10, 10))\n\n        assertEquals(Decimal128.fromIEEE754BIDEncoding(10, 10), realmAny.asDecimal128())\n        assertEquals(RealmAny.valueOf(Decimal128.fromIEEE754BIDEncoding(10, 10)), realmAny)\n        assertEquals(RealmAny.Type.DECIMAL128, realmAny.type)\n        assertEquals(RealmAny.Type.DECIMAL128.typedClass, realmAny.valueClass)\n    }\n\n    @Test\n    fun unmanaged_doubleValue() {\n        val realmAny = RealmAny.valueOf(10.0)\n\n        assertEquals(10.0, realmAny.asDouble())\n        assertEquals(RealmAny.valueOf(10.0), realmAny)\n        assertEquals(RealmAny.Type.DOUBLE, realmAny.type)\n        assertEquals(RealmAny.Type.DOUBLE.typedClass, realmAny.valueClass)\n    }\n\n    @Test\n    fun unmanaged_floatValue() {\n        val realmAny = RealmAny.valueOf(10.0f)\n\n        assertEquals(10.0f, realmAny.asFloat())\n        assertEquals(RealmAny.valueOf(10.0f), realmAny)\n        assertEquals(RealmAny.Type.FLOAT, realmAny.type)\n        assertEquals(RealmAny.Type.FLOAT.typedClass, realmAny.valueClass)\n    }\n\n    @Test\n    fun unmanaged_objectIdValue() {\n        val realmAny = RealmAny.valueOf(ObjectId(TestHelper.generateObjectIdHexString(0)))\n\n        assertEquals(ObjectId(TestHelper.generateObjectIdHexString(0)), realmAny.asObjectId())\n        assertEquals(RealmAny.valueOf(ObjectId(TestHelper.generateObjectIdHexString(0))), realmAny)\n        assertEquals(RealmAny.Type.OBJECT_ID, realmAny.type)\n        assertEquals(RealmAny.Type.OBJECT_ID.typedClass, realmAny.valueClass)\n    }\n\n    @Test\n    fun unmanaged_realmModel() {\n        val obj = RealmAnyNotIndexed()\n        val realmAny = RealmAny.valueOf(obj)\n\n        assertEquals(obj, realmAny.asRealmModel(RealmAnyNotIndexed::class.java))\n        assertEquals(RealmAny.valueOf(obj), realmAny)\n        assertEquals(RealmAny.Type.OBJECT, realmAny.type)\n        assertEquals(RealmAnyNotIndexed::class.simpleName, realmAny.valueClass?.simpleName)\n    }\n\n    @Test\n    fun unmanaged_UUIDValue() {\n        val realmAny = RealmAny.valueOf(UUID.fromString(TestHelper.generateUUIDString(0)))\n\n        assertEquals(UUID.fromString(TestHelper.generateUUIDString(0)), realmAny.asUUID())\n        assertEquals(RealmAny.valueOf(UUID.fromString(TestHelper.generateUUIDString(0))), realmAny)\n        assertEquals(RealmAny.Type.UUID, realmAny.type)\n    }\n\n    @Test\n    fun unmanaged_null() {\n        val aLong: Boolean? = null\n\n        val realmAny = RealmAny.valueOf(aLong)\n\n        assertTrue(realmAny.isNull)\n        assertNotNull(realmAny)\n        assertEquals(RealmAny.nullValue(), realmAny)\n        assertEquals(RealmAny.Type.NULL, realmAny.type)\n        assertEquals(null, realmAny.valueClass)\n    }\n\n\n    // Managed Tests\n    @Test\n    fun managed_byteValue() {\n        realm.executeTransaction {\n            val realmAnyObject = it.createObject<RealmAnyNotIndexed>()\n            realmAnyObject.realmAny = RealmAny.valueOf(10.toByte())\n        }\n\n        val realmAnyObject = realm.where<RealmAnyNotIndexed>().findFirst()!!\n\n        assertTrue(realmAnyObject.isManaged)\n        assertEquals(10, realmAnyObject.realmAny!!.asByte())\n        assertEquals(RealmAny.valueOf(10.toByte()), realmAnyObject.realmAny)\n        assertEquals(RealmAny.Type.INTEGER, realmAnyObject.realmAny!!.type)\n    }\n\n    @Test\n    fun managed_shortValue() {\n        realm.executeTransaction {\n            val realmAnyObject = it.createObject<RealmAnyNotIndexed>()\n            realmAnyObject.realmAny = RealmAny.valueOf(10.toShort())\n        }\n\n        val realmAnyObject = realm.where<RealmAnyNotIndexed>().findFirst()!!\n\n        assertTrue(realmAnyObject.isManaged)\n        assertEquals(10, realmAnyObject.realmAny!!.asShort())\n        assertEquals(RealmAny.valueOf(10.toShort()), realmAnyObject.realmAny)\n        assertEquals(RealmAny.Type.INTEGER, realmAnyObject.realmAny!!.type)\n    }\n\n    @Test\n    fun managed_integerValue() {\n        realm.executeTransaction {\n            val realmAnyObject = it.createObject<RealmAnyNotIndexed>()\n            realmAnyObject.realmAny = RealmAny.valueOf(10.toInt())\n        }\n\n        val realmAnyObject = realm.where<RealmAnyNotIndexed>().findFirst()!!\n\n        assertTrue(realmAnyObject.isManaged)\n        assertEquals(10, realmAnyObject.realmAny!!.asInteger())\n        assertEquals(RealmAny.valueOf(10.toInt()), realmAnyObject.realmAny)\n        assertEquals(RealmAny.Type.INTEGER, realmAnyObject.realmAny!!.type)\n    }\n\n    @Test\n    fun managed_longValue() {\n        realm.executeTransaction {\n            val realmAnyObject = it.createObject<RealmAnyNotIndexed>()\n            realmAnyObject.realmAny = RealmAny.valueOf(10.toLong())\n        }\n\n        val realmAnyObject = realm.where<RealmAnyNotIndexed>().findFirst()!!\n\n        assertTrue(realmAnyObject.isManaged)\n        assertEquals(10, realmAnyObject.realmAny!!.asLong())\n        assertEquals(RealmAny.valueOf(10.toLong()), realmAnyObject.realmAny)\n        assertEquals(RealmAny.Type.INTEGER, realmAnyObject.realmAny!!.type)\n        assertEquals(RealmAny.Type.INTEGER.typedClass, realmAnyObject.realmAny!!.valueClass)\n    }\n\n    @Test\n    fun managed_booleanValue() {\n        realm.executeTransaction {\n            val realmAnyObject = it.createObject<RealmAnyNotIndexed>()\n            realmAnyObject.realmAny = RealmAny.valueOf(true)\n        }\n\n        val realmAnyObject = realm.where<RealmAnyNotIndexed>().findFirst()!!\n\n        assertTrue(realmAnyObject.isManaged)\n        assertEquals(true, realmAnyObject.realmAny!!.asBoolean())\n        assertEquals(RealmAny.valueOf(true), realmAnyObject.realmAny)\n        assertEquals(RealmAny.Type.BOOLEAN, realmAnyObject.realmAny!!.type)\n        assertEquals(RealmAny.Type.BOOLEAN.typedClass, realmAnyObject.realmAny!!.valueClass)\n    }\n\n    @Test\n    fun managed_stringValue() {\n        realm.executeTransaction {\n            val realmAnyObject = it.createObject<RealmAnyNotIndexed>()\n            realmAnyObject.realmAny = RealmAny.valueOf(\"hello world\")\n        }\n\n        val realmAnyObject = realm.where<RealmAnyNotIndexed>().findFirst()!!\n\n        assertTrue(realmAnyObject.isManaged)\n        assertEquals(\"hello world\", realmAnyObject.realmAny!!.asString())\n        assertEquals(RealmAny.valueOf(\"hello world\"), realmAnyObject.realmAny)\n        assertEquals(RealmAny.Type.STRING, realmAnyObject.realmAny!!.type)\n        assertEquals(RealmAny.Type.STRING.typedClass, realmAnyObject.realmAny!!.valueClass)\n    }\n\n    @Test\n    fun managed_binaryValue() {\n        realm.executeTransaction {\n            val realmAnyObject = it.createObject<RealmAnyNotIndexed>()\n            realmAnyObject.realmAny = RealmAny.valueOf(byteArrayOf(0, 1, 0))\n        }\n\n        val realmAnyObject = realm.where<RealmAnyNotIndexed>().findFirst()!!\n\n        assertTrue(realmAnyObject.isManaged)\n        assertTrue(Arrays.equals(byteArrayOf(0, 1, 0), realmAnyObject.realmAny!!.asBinary()))\n        assertEquals(RealmAny.valueOf(byteArrayOf(0, 1, 0)), realmAnyObject.realmAny!!)\n        assertEquals(RealmAny.Type.BINARY, realmAnyObject.realmAny!!.type)\n        assertEquals(RealmAny.Type.BINARY.typedClass, realmAnyObject.realmAny!!.valueClass)\n    }\n\n    @Test\n    fun managed_dateValue() {\n        realm.executeTransaction {\n            val realmAnyObject = it.createObject<RealmAnyNotIndexed>()\n            realmAnyObject.realmAny = RealmAny.valueOf(Date(10))\n        }\n\n        val realmAnyObject = realm.where<RealmAnyNotIndexed>().findFirst()!!\n\n        assertTrue(realmAnyObject.isManaged)\n        assertEquals(Date(10), realmAnyObject.realmAny!!.asDate())\n        assertEquals(RealmAny.valueOf(Date(10)), realmAnyObject.realmAny)\n        assertEquals(RealmAny.Type.DATE, realmAnyObject.realmAny!!.type)\n        assertEquals(RealmAny.Type.DATE.typedClass, realmAnyObject.realmAny!!.valueClass)\n    }\n\n    @Test\n    fun managed_decimal128Value() {\n        realm.executeTransaction {\n            val realmAnyObject = it.createObject<RealmAnyNotIndexed>()\n            realmAnyObject.realmAny = RealmAny.valueOf(Decimal128(10))\n        }\n\n        val realmAnyObject = realm.where<RealmAnyNotIndexed>().findFirst()!!\n\n        assertTrue(realmAnyObject.isManaged)\n        assertEquals(Decimal128(10), realmAnyObject.realmAny!!.asDecimal128())\n        assertEquals(RealmAny.valueOf(Decimal128(10)), realmAnyObject.realmAny)\n        assertEquals(RealmAny.Type.DECIMAL128, realmAnyObject.realmAny!!.type)\n        assertEquals(RealmAny.Type.DECIMAL128.typedClass, realmAnyObject.realmAny!!.valueClass)\n    }\n\n    @Test\n    fun managed_doubleValue() {\n        realm.executeTransaction {\n            val realmAnyObject = it.createObject<RealmAnyNotIndexed>()\n            realmAnyObject.realmAny = RealmAny.valueOf(10.0)\n        }\n\n        val realmAnyObject = realm.where<RealmAnyNotIndexed>().findFirst()!!\n\n        assertTrue(realmAnyObject.isManaged)\n        assertEquals(10.0, realmAnyObject.realmAny!!.asDouble())\n        assertEquals(RealmAny.valueOf(10.0), realmAnyObject.realmAny)\n        assertEquals(RealmAny.Type.DOUBLE, realmAnyObject.realmAny!!.type)\n        assertEquals(RealmAny.Type.DOUBLE.typedClass, realmAnyObject.realmAny!!.valueClass)\n    }\n\n    @Test\n    fun managed_floatValue() {\n        realm.executeTransaction {\n            val realmAnyObject = it.createObject<RealmAnyNotIndexed>()\n            realmAnyObject.realmAny = RealmAny.valueOf(10f)\n        }\n\n        val realmAnyObject = realm.where<RealmAnyNotIndexed>().findFirst()!!\n\n        assertTrue(realmAnyObject.isManaged)\n        assertEquals(10f, realmAnyObject.realmAny!!.asFloat())\n        assertEquals(RealmAny.valueOf(10f), realmAnyObject.realmAny)\n        assertEquals(RealmAny.Type.FLOAT, realmAnyObject.realmAny!!.type)\n        assertEquals(RealmAny.Type.FLOAT.typedClass, realmAnyObject.realmAny!!.valueClass)\n    }\n\n    @Test\n    fun managed_objectIdValue() {\n        realm.executeTransaction {\n            val realmAnyObject = it.createObject<RealmAnyNotIndexed>()\n            realmAnyObject.realmAny = RealmAny.valueOf(ObjectId(TestHelper.generateObjectIdHexString(0)))\n        }\n\n        val realmAnyObject = realm.where<RealmAnyNotIndexed>().findFirst()!!\n\n        assertTrue(realmAnyObject.isManaged)\n        assertEquals(ObjectId(TestHelper.generateObjectIdHexString(0)), realmAnyObject.realmAny!!.asObjectId())\n        assertEquals(RealmAny.valueOf(ObjectId(TestHelper.generateObjectIdHexString(0))), realmAnyObject.realmAny)\n        assertEquals(RealmAny.Type.OBJECT_ID, realmAnyObject.realmAny!!.type)\n        assertEquals(RealmAny.Type.OBJECT_ID.typedClass, realmAnyObject.realmAny!!.valueClass)\n    }\n\n    @Test\n    fun managed_UUIDValue() {\n        realm.executeTransaction {\n            val realmAnyObject = it.createObject<RealmAnyNotIndexed>()\n            realmAnyObject.realmAny = RealmAny.valueOf(UUID.fromString(TestHelper.generateUUIDString(0)))\n        }\n\n        val realmAnyObject = realm.where<RealmAnyNotIndexed>().findFirst()!!\n\n        assertTrue(realmAnyObject.isManaged)\n        assertEquals(UUID.fromString(TestHelper.generateUUIDString(0)), realmAnyObject.realmAny!!.asUUID())\n        assertEquals(RealmAny.valueOf(UUID.fromString(TestHelper.generateUUIDString(0))), realmAnyObject.realmAny)\n        assertEquals(RealmAny.Type.UUID, realmAnyObject.realmAny!!.type)\n    }\n\n    @Test\n    fun managed_null() {\n        realm.executeTransaction {\n            val realmAnyObject = it.createObject<RealmAnyNotIndexed>()\n            realmAnyObject.realmAny = null\n        }\n\n        val realmAnyObject = realm.where<RealmAnyNotIndexed>().findFirst()!!\n\n        assertTrue(realmAnyObject.isManaged)\n        assertNotNull(realmAnyObject.realmAny!!)\n        assertTrue(realmAnyObject.realmAny!!.isNull)\n        assertEquals(RealmAny.nullValue(), realmAnyObject.realmAny)\n        assertEquals(RealmAny.Type.NULL, realmAnyObject.realmAny!!.type)\n        assertEquals(RealmAny.Type.NULL.typedClass, realmAnyObject.realmAny!!.valueClass)\n    }\n\n    @Test\n    fun managed_linkUnmanagedRealmModel() {\n        val key = UUID.randomUUID().toString()\n\n        realm.executeTransaction {\n            val realmAnyObject = realm.createObject<RealmAnyNotIndexed>()\n            val innerObject = PrimaryKeyAsString(key)\n\n            realmAnyObject.realmAny = RealmAny.valueOf(innerObject)\n        }\n\n        val realmAnyObject = realm.where<RealmAnyNotIndexed>().findFirst()!!\n        val realmAnyObject2 = realm.where<RealmAnyNotIndexed>().findFirst()!!\n\n        val innerObject = realm.where<PrimaryKeyAsString>().findFirst()!!\n\n        assertTrue(realmAnyObject.isManaged)\n\n        assertEquals(\n                realmAnyObject.realmAny!!.asRealmModel(PrimaryKeyAsString::class.java),\n                realmAnyObject2.realmAny!!.asRealmModel(PrimaryKeyAsString::class.java)\n        )\n\n        assertEquals(innerObject, realmAnyObject.realmAny!!.asRealmModel(PrimaryKeyAsString::class.java))\n        assertEquals(RealmAny.valueOf(innerObject), realmAnyObject.realmAny)\n        assertEquals(RealmAny.Type.OBJECT, realmAnyObject.realmAny!!.type)\n        assertEquals(PrimaryKeyAsString::class.simpleName, realmAnyObject.realmAny!!.valueClass!!.simpleName)\n    }\n\n    @Test\n    fun managed_linkManagedRealmModel() {\n        val key = UUID.randomUUID().toString()\n\n        realm.executeTransaction {\n            val realmAnyObject = realm.createObject<RealmAnyNotIndexed>()\n            val innerObject = realm.createObject<PrimaryKeyAsString>(key)\n\n            realmAnyObject.realmAny = RealmAny.valueOf(innerObject)\n        }\n\n        val realmAnyObject = realm.where<RealmAnyNotIndexed>().findFirst()!!\n        val realmAnyObject2 = realm.where<RealmAnyNotIndexed>().findFirst()!!\n\n        val innerObject = realm.where<PrimaryKeyAsString>().findFirst()!!\n\n        assertTrue(realmAnyObject.isManaged)\n\n        assertEquals(\n                realmAnyObject.realmAny!!.asRealmModel(PrimaryKeyAsString::class.java),\n                realmAnyObject2.realmAny!!.asRealmModel(PrimaryKeyAsString::class.java)\n        )\n\n        assertEquals(innerObject, realmAnyObject.realmAny!!.asRealmModel(PrimaryKeyAsString::class.java))\n        assertEquals(RealmAny.valueOf(innerObject), realmAnyObject.realmAny)\n        assertEquals(RealmAny.Type.OBJECT, realmAnyObject.realmAny!!.type)\n        assertEquals(PrimaryKeyAsString::class.simpleName, realmAnyObject.realmAny!!.valueClass!!.simpleName)\n    }\n\n    @Test\n    fun managed_realmModel() {\n        realm.executeTransaction {\n            val realmAnyObject = realm.createObject<RealmAnyNotIndexed>()\n            val realmAny = RealmAny.valueOf(realmAnyObject)\n\n            assertEquals(RealmAnyNotIndexed::class.java, realmAny.valueClass)\n        }\n    }\n\n    @Test\n    fun managed_nullRealmAny() {\n        realm.executeTransaction {\n            val realmAnyObject = it.createObject<RealmAnyNotIndexed>()\n            realmAnyObject.realmAny = RealmAny.nullValue()\n        }\n\n        val realmAnyObject = realm.where<RealmAnyNotIndexed>().findFirst()!!\n\n        assertTrue(realmAnyObject.isManaged)\n        assertTrue(realmAnyObject.realmAny!!.isNull)\n        assertNotNull(realmAnyObject.realmAny)\n        assertEquals(RealmAny.nullValue(), realmAnyObject.realmAny)\n        assertEquals(RealmAny.Type.NULL, realmAnyObject.realmAny!!.type)\n        assertEquals(RealmAny.Type.NULL.typedClass, realmAnyObject.realmAny!!.valueClass)\n    }\n\n    @Test\n    fun managed_validity() {\n        realm.executeTransaction {\n            val realmAnyObject = it.createObject<RealmAnyNotIndexed>()\n            realmAnyObject.realmAny = RealmAny.nullValue()\n        }\n\n        val realmAnyObject = realm.where<RealmAnyNotIndexed>().findFirst()!!\n\n        assertTrue(realmAnyObject!!.isValid)\n\n        realm.executeTransaction {\n            realmAnyObject.deleteFromRealm()\n        }\n\n        assertFalse(realmAnyObject.isValid)\n    }\n\n    @Test\n    fun managed_frozen() {\n        realm.executeTransaction {\n            val realmAnyObject = it.createObject<RealmAnyNotIndexed>()\n            realmAnyObject.realmAny = RealmAny.nullValue()\n        }\n\n        val realmAnyObject = realm.where<RealmAnyNotIndexed>().findFirst()!!\n\n        assertFalse(realmAnyObject!!.isFrozen)\n        assertTrue(realmAnyObject.isValid)\n        assertTrue(realmAnyObject.realmAny!!.isNull)\n        assertEquals(RealmAny.Type.NULL, realmAnyObject.realmAny!!.type)\n    }\n\n    @Test\n    fun managed_notFrozen() {\n        realm.executeTransaction {\n            val realmAnyObject = it.createObject<RealmAnyNotIndexed>()\n            realmAnyObject.realmAny = RealmAny.nullValue()\n        }\n\n        val realmAnyObjectFrozen = realm.freeze().where<RealmAnyNotIndexed>().findFirst()!!\n\n        assertTrue(realmAnyObjectFrozen!!.isFrozen)\n        assertTrue(realmAnyObjectFrozen.isValid)\n        assertTrue(realmAnyObjectFrozen.realmAny!!.isNull)\n        assertEquals(RealmAny.Type.NULL, realmAnyObjectFrozen.realmAny!!.type)\n    }\n\n    @Test\n    fun managed_listsAddAllTypes() {\n        val aString = \"a string\"\n        val byteArray = byteArrayOf(0, 1, 0)\n        val date = Date()\n        val objectId = ObjectId()\n        val decimal128 = Decimal128(1)\n        val uuid = UUID.randomUUID()\n\n        realm.executeTransaction {\n            val allJavaTypes = it.createObject<AllJavaTypes>(0)\n            val managedRealmModel = it.createObject<PrimaryKeyAsString>(\"managed\")\n\n            allJavaTypes.fieldRealmAnyList.add(RealmAny.valueOf(true))\n            allJavaTypes.fieldRealmAnyList.add(RealmAny.valueOf(1.toByte()))\n            allJavaTypes.fieldRealmAnyList.add(RealmAny.valueOf(2.toShort()))\n            allJavaTypes.fieldRealmAnyList.add(RealmAny.valueOf(3.toInt()))\n            allJavaTypes.fieldRealmAnyList.add(RealmAny.valueOf(4.toLong()))\n            allJavaTypes.fieldRealmAnyList.add(RealmAny.valueOf(5.toFloat()))\n            allJavaTypes.fieldRealmAnyList.add(RealmAny.valueOf(6.toDouble()))\n            allJavaTypes.fieldRealmAnyList.add(RealmAny.valueOf(aString))\n            allJavaTypes.fieldRealmAnyList.add(RealmAny.valueOf(byteArray))\n            allJavaTypes.fieldRealmAnyList.add(RealmAny.valueOf(date))\n            allJavaTypes.fieldRealmAnyList.add(RealmAny.valueOf(objectId))\n            allJavaTypes.fieldRealmAnyList.add(RealmAny.valueOf(decimal128))\n            allJavaTypes.fieldRealmAnyList.add(RealmAny.valueOf(uuid))\n            allJavaTypes.fieldRealmAnyList.add(RealmAny.nullValue())\n            allJavaTypes.fieldRealmAnyList.add(null)\n            allJavaTypes.fieldRealmAnyList.add(RealmAny.valueOf(PrimaryKeyAsString(\"unmanaged\")))\n            allJavaTypes.fieldRealmAnyList.add(RealmAny.valueOf(managedRealmModel))\n        }\n\n        val allJavaTypes = realm.where<AllJavaTypes>().findFirst()\n\n        assertEquals(true, allJavaTypes!!.fieldRealmAnyList[0]!!.asBoolean())\n        assertEquals(1, allJavaTypes.fieldRealmAnyList[1]!!.asByte())\n        assertEquals(2, allJavaTypes.fieldRealmAnyList[2]!!.asShort())\n        assertEquals(3, allJavaTypes.fieldRealmAnyList[3]!!.asInteger())\n        assertEquals(4, allJavaTypes.fieldRealmAnyList[4]!!.asLong())\n        assertEquals(5.toFloat(), allJavaTypes.fieldRealmAnyList[5]!!.asFloat())\n        assertEquals(6.toDouble(), allJavaTypes.fieldRealmAnyList[6]!!.asDouble())\n        assertEquals(aString, allJavaTypes.fieldRealmAnyList[7]!!.asString())\n        assertTrue(Arrays.equals(byteArray, allJavaTypes.fieldRealmAnyList[8]!!.asBinary()))\n        assertEquals(date, allJavaTypes.fieldRealmAnyList[9]!!.asDate())\n        assertEquals(objectId, allJavaTypes.fieldRealmAnyList[10]!!.asObjectId())\n        assertEquals(decimal128, allJavaTypes.fieldRealmAnyList[11]!!.asDecimal128())\n        assertEquals(uuid, allJavaTypes.fieldRealmAnyList[12]!!.asUUID())\n        assertTrue(allJavaTypes.fieldRealmAnyList[13]!!.isNull)\n        assertTrue(allJavaTypes.fieldRealmAnyList[14]!!.isNull)\n\n        assertEquals(\"unmanaged\", allJavaTypes.fieldRealmAnyList[15]!!.asRealmModel(PrimaryKeyAsString::class.java).name)\n        assertEquals(\"managed\", allJavaTypes.fieldRealmAnyList[16]!!.asRealmModel(PrimaryKeyAsString::class.java).name)\n    }\n\n    @Test\n    fun managed_listsInsertAllTypes() {\n        val aString = \"a string\"\n        val byteArray = byteArrayOf(0, 1, 0)\n        val date = Date()\n        val objectId = ObjectId()\n        val decimal128 = Decimal128(1)\n        val uuid = UUID.randomUUID()\n\n        realm.executeTransaction {\n            val allJavaTypes = it.createObject<AllJavaTypes>(0)\n            val managedRealmModel = it.createObject<PrimaryKeyAsString>(\"managed\")\n\n            allJavaTypes.fieldRealmAnyList.add(0, RealmAny.valueOf(true))\n            allJavaTypes.fieldRealmAnyList.add(0, RealmAny.valueOf(1.toByte()))\n            allJavaTypes.fieldRealmAnyList.add(0, RealmAny.valueOf(2.toShort()))\n            allJavaTypes.fieldRealmAnyList.add(0, RealmAny.valueOf(3.toInt()))\n            allJavaTypes.fieldRealmAnyList.add(0, RealmAny.valueOf(4.toLong()))\n            allJavaTypes.fieldRealmAnyList.add(0, RealmAny.valueOf(5.toFloat()))\n            allJavaTypes.fieldRealmAnyList.add(0, RealmAny.valueOf(6.toDouble()))\n            allJavaTypes.fieldRealmAnyList.add(0, RealmAny.valueOf(aString))\n            allJavaTypes.fieldRealmAnyList.add(0, RealmAny.valueOf(byteArray))\n            allJavaTypes.fieldRealmAnyList.add(0, RealmAny.valueOf(date))\n            allJavaTypes.fieldRealmAnyList.add(0, RealmAny.valueOf(objectId))\n            allJavaTypes.fieldRealmAnyList.add(0, RealmAny.valueOf(decimal128))\n            allJavaTypes.fieldRealmAnyList.add(0, RealmAny.valueOf(uuid))\n            allJavaTypes.fieldRealmAnyList.add(0, RealmAny.nullValue())\n            allJavaTypes.fieldRealmAnyList.add(0, null)\n            allJavaTypes.fieldRealmAnyList.add(0, RealmAny.valueOf(PrimaryKeyAsString(\"unmanaged\")))\n            allJavaTypes.fieldRealmAnyList.add(0, RealmAny.valueOf(managedRealmModel))\n        }\n\n        val allJavaTypes = realm.where<AllJavaTypes>().findFirst()\n\n        assertEquals(true, allJavaTypes!!.fieldRealmAnyList[16]!!.asBoolean())\n        assertEquals(1, allJavaTypes.fieldRealmAnyList[15]!!.asByte())\n        assertEquals(2, allJavaTypes.fieldRealmAnyList[14]!!.asShort())\n        assertEquals(3, allJavaTypes.fieldRealmAnyList[13]!!.asInteger())\n        assertEquals(4, allJavaTypes.fieldRealmAnyList[12]!!.asLong())\n        assertEquals(5.toFloat(), allJavaTypes.fieldRealmAnyList[11]!!.asFloat())\n        assertEquals(6.toDouble(), allJavaTypes.fieldRealmAnyList[10]!!.asDouble())\n        assertEquals(aString, allJavaTypes.fieldRealmAnyList[9]!!.asString())\n        assertTrue(Arrays.equals(byteArray, allJavaTypes.fieldRealmAnyList[8]!!.asBinary()))\n        assertEquals(date, allJavaTypes.fieldRealmAnyList[7]!!.asDate())\n        assertEquals(objectId, allJavaTypes.fieldRealmAnyList[6]!!.asObjectId())\n        assertEquals(decimal128, allJavaTypes.fieldRealmAnyList[5]!!.asDecimal128())\n        assertEquals(uuid, allJavaTypes.fieldRealmAnyList[4]!!.asUUID())\n        assertTrue(allJavaTypes.fieldRealmAnyList[3]!!.isNull)\n        assertTrue(allJavaTypes.fieldRealmAnyList[2]!!.isNull)\n\n        assertEquals(\"unmanaged\", allJavaTypes.fieldRealmAnyList[1]!!.asRealmModel(PrimaryKeyAsString::class.java).name)\n        assertEquals(\"managed\", allJavaTypes.fieldRealmAnyList[0]!!.asRealmModel(PrimaryKeyAsString::class.java).name)\n    }\n\n    @Test\n    fun managed_listsSetAllTypes() {\n        val aString = \"a string\"\n        val byteArray = byteArrayOf(0, 1, 0)\n        val date = Date()\n        val objectId = ObjectId()\n        val decimal128 = Decimal128(1)\n        val uuid = UUID.randomUUID()\n\n        realm.executeTransaction {\n            val allJavaTypes = it.createObject<AllJavaTypes>(0)\n            val managedRealmModel = it.createObject<PrimaryKeyAsString>(\"managed\")\n\n            val initialList = RealmList<RealmAny>()\n            initialList.addAll(arrayOfNulls(17))\n\n            allJavaTypes.fieldRealmAnyList = initialList\n\n            allJavaTypes.fieldRealmAnyList[0] = RealmAny.valueOf(true)\n            allJavaTypes.fieldRealmAnyList[1] = RealmAny.valueOf(1.toByte())\n            allJavaTypes.fieldRealmAnyList[2] = RealmAny.valueOf(2.toShort())\n            allJavaTypes.fieldRealmAnyList[3] = RealmAny.valueOf(3.toInt())\n            allJavaTypes.fieldRealmAnyList[4] = RealmAny.valueOf(4.toLong())\n            allJavaTypes.fieldRealmAnyList[5] = RealmAny.valueOf(5.toFloat())\n            allJavaTypes.fieldRealmAnyList[6] = RealmAny.valueOf(6.toDouble())\n            allJavaTypes.fieldRealmAnyList[7] = RealmAny.valueOf(aString)\n            allJavaTypes.fieldRealmAnyList[8] = RealmAny.valueOf(byteArray)\n            allJavaTypes.fieldRealmAnyList[9] = RealmAny.valueOf(date)\n            allJavaTypes.fieldRealmAnyList[10] = RealmAny.valueOf(objectId)\n            allJavaTypes.fieldRealmAnyList[11] = RealmAny.valueOf(decimal128)\n            allJavaTypes.fieldRealmAnyList[12] = RealmAny.valueOf(uuid)\n            allJavaTypes.fieldRealmAnyList[13] = RealmAny.nullValue()\n            allJavaTypes.fieldRealmAnyList[14] = null\n            allJavaTypes.fieldRealmAnyList[15] = RealmAny.valueOf(PrimaryKeyAsString(\"unmanaged\"))\n            allJavaTypes.fieldRealmAnyList[16] = RealmAny.valueOf(managedRealmModel)\n        }\n\n        val allJavaTypes = realm.where<AllJavaTypes>().findFirst()\n\n        assertEquals(true, allJavaTypes!!.fieldRealmAnyList[0]!!.asBoolean())\n        assertEquals(1, allJavaTypes.fieldRealmAnyList[1]!!.asByte())\n        assertEquals(2, allJavaTypes.fieldRealmAnyList[2]!!.asShort())\n        assertEquals(3, allJavaTypes.fieldRealmAnyList[3]!!.asInteger())\n        assertEquals(4, allJavaTypes.fieldRealmAnyList[4]!!.asLong())\n        assertEquals(5.toFloat(), allJavaTypes.fieldRealmAnyList[5]!!.asFloat())\n        assertEquals(6.toDouble(), allJavaTypes.fieldRealmAnyList[6]!!.asDouble())\n        assertEquals(aString, allJavaTypes.fieldRealmAnyList[7]!!.asString())\n        assertTrue(Arrays.equals(byteArray, allJavaTypes.fieldRealmAnyList[8]!!.asBinary()))\n        assertEquals(date, allJavaTypes.fieldRealmAnyList[9]!!.asDate())\n        assertEquals(objectId, allJavaTypes.fieldRealmAnyList[10]!!.asObjectId())\n        assertEquals(decimal128, allJavaTypes.fieldRealmAnyList[11]!!.asDecimal128())\n        assertEquals(uuid, allJavaTypes.fieldRealmAnyList[12]!!.asUUID())\n        assertTrue(allJavaTypes.fieldRealmAnyList[13]!!.isNull)\n        assertTrue(allJavaTypes.fieldRealmAnyList[14]!!.isNull)\n        assertEquals(\"unmanaged\", allJavaTypes.fieldRealmAnyList[15]!!.asRealmModel(PrimaryKeyAsString::class.java).name)\n        assertEquals(\"managed\", allJavaTypes.fieldRealmAnyList[16]!!.asRealmModel(PrimaryKeyAsString::class.java).name)\n    }\n\n    @Test\n    fun managed_listsRemoveAllTypes() {\n        val aString = \"a string\"\n        val byteArray = byteArrayOf(0, 1, 0)\n        val date = Date()\n        val objectId = ObjectId()\n        val decimal128 = Decimal128(1)\n        val uuid = UUID.randomUUID()\n\n        realm.executeTransaction {\n            val allJavaTypes = it.createObject<AllJavaTypes>(0)\n            val managedRealmModel = it.createObject<PrimaryKeyAsString>(\"managed\")\n\n            allJavaTypes.fieldRealmAnyList.add(RealmAny.valueOf(true))\n            allJavaTypes.fieldRealmAnyList.add(RealmAny.valueOf(1.toByte()))\n            allJavaTypes.fieldRealmAnyList.add(RealmAny.valueOf(2.toShort()))\n            allJavaTypes.fieldRealmAnyList.add(RealmAny.valueOf(3.toInt()))\n            allJavaTypes.fieldRealmAnyList.add(RealmAny.valueOf(4.toLong()))\n            allJavaTypes.fieldRealmAnyList.add(RealmAny.valueOf(5.toFloat()))\n            allJavaTypes.fieldRealmAnyList.add(RealmAny.valueOf(6.toDouble()))\n            allJavaTypes.fieldRealmAnyList.add(RealmAny.valueOf(aString))\n            allJavaTypes.fieldRealmAnyList.add(RealmAny.valueOf(byteArray))\n            allJavaTypes.fieldRealmAnyList.add(RealmAny.valueOf(date))\n            allJavaTypes.fieldRealmAnyList.add(RealmAny.valueOf(objectId))\n            allJavaTypes.fieldRealmAnyList.add(RealmAny.valueOf(decimal128))\n            allJavaTypes.fieldRealmAnyList.add(RealmAny.valueOf(uuid))\n            allJavaTypes.fieldRealmAnyList.add(RealmAny.nullValue())\n            allJavaTypes.fieldRealmAnyList.add(null)\n            allJavaTypes.fieldRealmAnyList.add(RealmAny.valueOf(PrimaryKeyAsString(\"unmanaged\")))\n            allJavaTypes.fieldRealmAnyList.add(RealmAny.valueOf(managedRealmModel))\n        }\n\n        realm.executeTransaction {\n            val allJavaTypes = realm.where<AllJavaTypes>().findFirst()\n\n            for (i in 0..16)\n                allJavaTypes!!.fieldRealmAnyList.removeAt(0)\n\n            assertEquals(0, allJavaTypes!!.fieldRealmAnyList.size)\n        }\n    }\n\n    private val looperThread = BlockingLooperThread()\n\n    @Test\n    fun managed_listThrowsOtherRealm() {\n        realm.beginTransaction()\n\n        val aDog = realm.createObject(PrimaryKeyAsString::class.java, \"a dog\")\n\n        realm.commitTransaction()\n\n\n        looperThread.runBlocking {\n            val anotherRealm = Realm.getInstance(realm.configuration)\n\n            anotherRealm.beginTransaction()\n\n            val allTypes = anotherRealm.createObject(AllJavaTypes::class.java, 0)\n\n            assertFailsWith<IllegalArgumentException>(\"Cannot copy an object from another Realm instance.\") {\n                allTypes.fieldRealmAnyList.add(RealmAny.valueOf(aDog))\n            }\n\n            anotherRealm.commitTransaction()\n            anotherRealm.close()\n\n            looperThread.testComplete()\n        }\n    }\n\n    @Test\n    fun managed_listThrowsEmbedded() {\n        looperThread.runBlocking {\n            val anotherRealm = Realm.getInstance(realm.configuration)\n\n            anotherRealm.beginTransaction()\n\n            val allTypes = anotherRealm.createObject(AllJavaTypes::class.java, 0)\n\n            assertFailsWith<IllegalArgumentException>(\"Embedded objects are not supported by RealmAny.\") {\n                allTypes.fieldRealmAnyList.add(RealmAny.valueOf(SimpleEmbeddedObject()))\n            }\n\n            anotherRealm.commitTransaction()\n            anotherRealm.close()\n\n            looperThread.testComplete()\n        }\n    }\n\n    @Test\n    fun dynamiclists_throwCopyBetweenInstances() {\n        realm.beginTransaction()\n\n        val aDog = realm.createObject(PrimaryKeyAsString::class.java, \"a dog\")\n\n        realm.commitTransaction()\n\n        val dynDog = DynamicRealmObject(aDog)\n        val dynamicRealm = DynamicRealm.getInstance(realm.getConfiguration())\n\n        dynamicRealm.beginTransaction()\n\n        assertFailsWith<IllegalArgumentException>(\"Cannot copy DynamicRealmObject between Realm instances.\") {\n            dynamicRealm.createObject(AllJavaTypes.CLASS_NAME, 0)\n                    .getList(AllJavaTypes.FIELD_REALM_ANY_LIST, RealmAny::class.java)\n                    .add(RealmAny.valueOf(dynDog))\n        }\n\n        dynamicRealm.commitTransaction()\n\n        dynamicRealm.close()\n    }\n\n    @Test\n    fun lists_throwCopyBetweenThreads() {\n        realm.executeTransaction {\n            it.createObject(PrimaryKeyAsString::class.java, \"a dog\")\n        }\n\n        val dynamicRealm = DynamicRealm.getInstance(realm.getConfiguration())\n        val dynDog = dynamicRealm.where(PrimaryKeyAsString.CLASS_NAME).findFirst()\n\n        looperThread.runBlocking {\n            val innerDynamicRealm = DynamicRealm.getInstance(realm.getConfiguration())\n            innerDynamicRealm.beginTransaction()\n\n            assertFailsWith<IllegalStateException>(\"Cannot copy an object to a Realm instance created in another thread.\") {\n                dynamicRealm.createObject(AllJavaTypes.CLASS_NAME, 0)\n                        .getList(AllJavaTypes.FIELD_REALM_ANY_LIST, RealmAny::class.java)\n                        .add(RealmAny.valueOf(dynDog))\n            }\n\n            innerDynamicRealm.close()\n\n            looperThread.testComplete()\n        }\n\n        dynamicRealm.close()\n    }\n\n\n    @Test\n    fun freeze() {\n        realm.beginTransaction()\n        val obj = realm.createObject<RealmAnyNotIndexedWithPK>(0)\n        obj.realmAny = RealmAny.valueOf(10.toInt())\n        realm.commitTransaction()\n\n        val frozen = obj.freeze<RealmAnyNotIndexedWithPK>()\n\n        assertEquals(RealmAny.valueOf(10.toInt()), frozen.realmAny)\n    }\n\n    @Test\n    fun initialize_default_pkRealmModel() {\n        realm.executeTransaction {\n            realm.createObject<PrimaryKeyAsString>(RealmAnyDefaultPK.NAME)\n        }\n\n        realm.executeTransaction {\n            realm.createObject<RealmAnyDefaultPK>()\n        }\n\n        val realmAnyObject = realm.where<RealmAnyDefaultPK>().findFirst()!!\n\n        assertTrue(realmAnyObject.isManaged)\n        assertEquals(RealmAnyDefaultPK.NAME, realmAnyObject.realmAny!!.asRealmModel(PrimaryKeyAsString::class.java).name)\n        assertEquals(RealmAny.Type.OBJECT, realmAnyObject.realmAny!!.type)\n        assertEquals(PrimaryKeyAsString::class.simpleName, realmAnyObject.realmAny!!.valueClass?.simpleName)\n    }\n\n    @Test\n    fun initialize_default_nonPkRealmModel() {\n        realm.executeTransaction {\n            realm.createObject<RealmAnyNotIndexed>()\n        }\n\n        realm.executeTransaction {\n            realm.createObject<RealmAnyDefaultNonPK>()\n        }\n\n        val realmAnyObject = realm.where<RealmAnyDefaultNonPK>().findFirst()!!\n\n        assertTrue(realmAnyObject.isManaged)\n        assertEquals(RealmAny.Type.OBJECT, realmAnyObject.realmAny!!.type)\n        assertEquals(RealmAnyNotIndexed::class.simpleName, realmAnyObject.realmAny!!.valueClass?.simpleName)\n    }\n\n    @Test\n    fun missing_schemaClass() {\n        realm.close()\n\n        val missingClassName = \"MissingClass\"\n        val fieldName = \"aString\"\n        val expectedValue = \"Hello world\"\n\n        DynamicRealm.getInstance(realmConfiguration).use { dynamicRealm ->\n            dynamicRealm.executeTransaction { transactionRealm ->\n                transactionRealm.schema\n                        .create(missingClassName)\n                        .addField(fieldName, String::class.java)\n\n                val missingClassObject = transactionRealm.createObject(missingClassName).apply {\n                    set(fieldName, expectedValue)\n                }\n                transactionRealm.createObject(RealmAnyNotIndexed.CLASS_NAME).apply {\n                    set(RealmAnyNotIndexed.FIELD_REALM_ANY, RealmAny.valueOf(missingClassObject))\n                }\n            }\n        }\n\n        realm = Realm.getInstance(realmConfiguration)\n\n        val realmAnyNotIndexed = realm.where(RealmAnyNotIndexed::class.java).findFirst()!!\n        assertEquals(RealmAny.Type.OBJECT, realmAnyNotIndexed.realmAny!!.type)\n        assertEquals(DynamicRealmObject::class.java, realmAnyNotIndexed.realmAny!!.valueClass)\n\n        val innerObject = realmAnyNotIndexed.realmAny!!.asRealmModel(DynamicRealmObject::class.java)\n        assertEquals(expectedValue, innerObject.getString(fieldName))\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTest/res/xml/network_security_config.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<network-security-config>\n    <base-config>\n        <trust-anchors>\n            <certificates src=\"system\" />\n        </trust-anchors>\n    </base-config>\n    <domain-config cleartextTrafficPermitted=\"true\">\n        <domain includeSubdomains=\"false\">localhost</domain>\n        <domain includeSubdomains=\"false\">127.0.0.1</domain>\n    </domain-config>\n</network-security-config>\n"
  },
  {
    "path": "realm/realm-library/src/androidTestObjectServer/kotlin/io/realm/ApiKeyAuthTests.kt",
    "content": "/*\n * Copyright 2020 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 */\npackage io.realm\n\nimport androidx.test.annotation.UiThreadTest\nimport androidx.test.ext.junit.runners.AndroidJUnit4\nimport androidx.test.platform.app.InstrumentationRegistry\nimport io.realm.admin.ServerAdmin\nimport io.realm.mongodb.*\nimport io.realm.mongodb.auth.ApiKeyAuth\nimport io.realm.mongodb.auth.ApiKey\nimport io.realm.rule.BlockingLooperThread\nimport org.bson.types.ObjectId\nimport org.junit.After\nimport org.junit.Assert.*\nimport org.junit.Before\nimport org.junit.Test\nimport org.junit.runner.RunWith\n\n@RunWith(AndroidJUnit4::class)\nclass ApiKeyAuthTests {\n    private val looperThread = BlockingLooperThread()\n    private lateinit var app: TestApp\n    private lateinit var admin: ServerAdmin\n    private lateinit var user: User\n    private lateinit var provider: ApiKeyAuth\n\n    // Callback use to verify that an Illegal Argument was thrown from async methods\n    private val checkNullInVoidCallback = App.Callback<Void> { result ->\n        if (result.isSuccess) {\n            fail()\n        } else {\n            assertEquals(ErrorCode.UNKNOWN, result.error.errorCode)\n            looperThread.testComplete()\n        }\n    }\n\n    private val checkNullInApiKeyCallback = App.Callback<ApiKey> { result ->\n        if (result.isSuccess) {\n            fail()\n        } else {\n            assertEquals(ErrorCode.UNKNOWN, result.error.errorCode)\n            looperThread.testComplete()\n        }\n    }\n\n    // Methods exposed by the EmailPasswordAuthProvider\n    enum class Method {\n        CREATE,\n        FETCH_SINGLE,\n        FETCH_ALL,\n        DELETE,\n        ENABLE,\n        DISABLE\n    }\n\n    @Before\n    fun setUp() {\n        Realm.init(InstrumentationRegistry.getInstrumentation().targetContext)\n        app = TestApp()\n        admin = ServerAdmin(app)\n        user = app.registerUserAndLogin(TestHelper.getRandomEmail(), \"123456\")\n        provider = user.apiKeys\n    }\n\n    @After\n    fun tearDown() {\n        if (this::app.isInitialized) {\n            app.close()\n        }\n        admin.deleteAllUsers()\n    }\n\n    inline fun testNullArg(method: () -> Unit) {\n        try {\n            method()\n            fail()\n        } catch (ignore: IllegalArgumentException) {\n        }\n    }\n\n    @Test\n    fun createApiKey() {\n        val key: ApiKey = provider.create(\"my-key\")\n        assertEquals(\"my-key\", key.name)\n        assertNotNull(\"my-key\", key.value)\n        assertNotNull(\"my-key\", key.id)\n        assertTrue(\"my-key\", key.isEnabled)\n    }\n\n    @Test\n    fun createApiKey_invalidServerArgsThrows() {\n        try {\n            provider.create(\"%s\")\n            fail()\n        } catch (e: AppException) {\n            assertEquals(ErrorCode.INVALID_PARAMETER, e.errorCode)\n        }\n    }\n\n    @Test\n    fun createApiKey_invalidArgumentThrows() {\n        testNullArg { provider.create(TestHelper.getNull()) }\n        testNullArg { provider.create(\"\") }\n        looperThread.runBlocking {\n            provider.createAsync(TestHelper.getNull(), checkNullInApiKeyCallback)\n        }\n        looperThread.runBlocking {\n            provider.createAsync(\"\", checkNullInApiKeyCallback)\n        }\n    }\n\n    @Test\n    fun createApiKeyAsync() = looperThread.runBlocking {\n        provider.createAsync(\"my-key\") { result ->\n            val key = result.orThrow\n            assertEquals(\"my-key\", key.name)\n            assertNotNull(\"my-key\", key.value)\n            assertNotNull(\"my-key\", key.id)\n            assertTrue(\"my-key\", key.isEnabled)\n            looperThread.testComplete()\n        }\n    }\n\n    @Test\n    fun createApiKeyAsync_invalidServerArgsThrows() = looperThread.runBlocking {\n        provider.createAsync(\"%s\") { result ->\n            if (result.isSuccess) {\n                fail()\n            } else {\n                assertEquals(ErrorCode.INVALID_PARAMETER, result.error.errorCode)\n                looperThread.testComplete()\n            }\n        }\n    }\n\n    @Test\n    fun fetchApiKey() {\n        val key1: ApiKey = provider.create(\"my-key\")\n        val key2: ApiKey = provider.fetch(key1.id)\n\n        assertEquals(key1.id, key2.id)\n        assertEquals(key1.name, key2.name)\n        assertNull(key2.value)\n        assertEquals(key1.isEnabled, key2.isEnabled)\n    }\n\n    @Test\n    fun fetchApiKey_nonExistingKey() {\n        try {\n            provider.fetch(ObjectId())\n            fail()\n        } catch (e: AppException) {\n            assertEquals(ErrorCode.API_KEY_NOT_FOUND, e.errorCode)\n        }\n    }\n\n    @Test\n    fun fetchApiKey_invalidArgumentThrows() {\n        testNullArg { provider.fetch(TestHelper.getNull()) }\n        looperThread.runBlocking {\n            provider.fetchAsync(TestHelper.getNull(), checkNullInApiKeyCallback)\n        }\n    }\n\n    @Test\n    fun fetchApiKeyAsync() {\n        val key1: ApiKey = provider.create(\"my-key\")\n        looperThread.runBlocking {\n            provider.fetchAsync(key1.id) { result ->\n                val key2 = result.orThrow\n                assertEquals(key1.id, key2.id)\n                assertEquals(key1.name, key2.name)\n                assertNull(key2.value)\n                assertEquals(key1.isEnabled, key2.isEnabled)\n                looperThread.testComplete()\n            }\n        }\n    }\n\n    @Test\n    fun fetchAllApiKeys() {\n        val key1: ApiKey = provider.create(\"my-key\")\n        val key2: ApiKey = provider.create(\"other-key\")\n        val allKeys: List<ApiKey> = provider.fetchAll()\n        assertEquals(2, allKeys.size)\n        assertTrue(allKeys.any { it.id == key1.id })\n        assertTrue(allKeys.any { it.id == key2.id })\n    }\n\n    @Test\n    fun fetchAllApiKeysAsync() {\n        val key1: ApiKey = provider.create(\"my-key\")\n        val key2: ApiKey = provider.create(\"other-key\")\n        looperThread.runBlocking {\n            provider.fetchAll() { result ->\n                val keys: List<ApiKey> = result.orThrow\n                assertEquals(2, keys.size)\n                assertTrue(keys.any { it.id == key1.id })\n                assertTrue(keys.any { it.id == key2.id })\n                looperThread.testComplete()\n            }\n        }\n    }\n\n    @Test\n    fun deleteApiKey() {\n        val key1: ApiKey = provider.create(\"my-key\")\n        assertNotNull(provider.fetch(key1.id))\n        provider.delete(key1.id)\n        try {\n            provider.fetch(key1.id)\n            fail()\n        } catch (e: AppException) {\n            assertEquals(ErrorCode.API_KEY_NOT_FOUND, e.errorCode)\n        }\n    }\n\n    @Test\n    fun deleteApiKey_invalidServerArgsThrows() {\n        try {\n            provider.delete(ObjectId())\n            fail()\n        } catch (e: AppException) {\n            assertEquals(ErrorCode.API_KEY_NOT_FOUND, e.errorCode)\n        }\n    }\n\n    @Test\n    fun deleteApiKey_invalidArgumentThrows() {\n        testNullArg { provider.delete(TestHelper.getNull()) }\n        looperThread.runBlocking {\n            provider.deleteAsync(TestHelper.getNull(), checkNullInVoidCallback)\n        }\n    }\n\n    @Test\n    fun deleteApiKeyAsync() {\n        val key: ApiKey = provider.create(\"my-key\")\n        assertNotNull(provider.fetch(key.id))\n        looperThread.runBlocking {\n            provider.deleteAsync(key.id) { result ->\n                if (result.isSuccess) {\n                    try {\n                        provider.fetch(key.id)\n                        fail()\n                    } catch (e: AppException) {\n                        assertEquals(ErrorCode.API_KEY_NOT_FOUND, e.errorCode)\n                    }\n                    looperThread.testComplete()\n                } else {\n                    fail(result.error.toString())\n                }\n            }\n        }\n    }\n\n    @Test\n    fun deleteApiKeyAsync_invalidServerArgsThrows() = looperThread.runBlocking {\n        provider.deleteAsync(ObjectId()) { result ->\n            if (result.isSuccess) {\n                fail()\n            } else {\n                assertEquals(ErrorCode.API_KEY_NOT_FOUND, result.error.errorCode)\n                looperThread.testComplete()\n            }\n        }\n    }\n\n    @Test\n    fun enableApiKey() {\n        val key: ApiKey = provider.create(\"my-key\")\n        provider.disable(key.id)\n        assertFalse(provider.fetch(key.id).isEnabled)\n        provider.enable(key.id)\n        assertTrue(provider.fetch(key.id).isEnabled)\n    }\n\n    @Test\n    fun enableApiKey_alreadyEnabled() {\n        val key: ApiKey = provider.create(\"my-key\")\n        provider.disable(key.id)\n        assertFalse(provider.fetch(key.id).isEnabled)\n        provider.enable(key.id)\n        assertTrue(provider.fetch(key.id).isEnabled)\n        provider.enable(key.id)\n        assertTrue(provider.fetch(key.id).isEnabled)\n    }\n\n    @Test\n    fun enableApiKey_invalidServerArgsThrows() {\n        try {\n            provider.enable(ObjectId())\n            fail()\n        } catch (e: AppException) {\n            assertEquals(ErrorCode.API_KEY_NOT_FOUND, e.errorCode)\n        }\n    }\n\n    @Test\n    fun enableApiKey_invalidArgumentThrows() {\n        testNullArg { provider.enable(TestHelper.getNull()) }\n        looperThread.runBlocking {\n            provider.enableAsync(TestHelper.getNull(), checkNullInVoidCallback)\n        }\n    }\n\n    @Test\n    fun enableApiKeyAsync() {\n        val key: ApiKey = provider.create(\"my-key\")\n        provider.disable(key.id)\n        assertFalse(provider.fetch(key.id).isEnabled)\n        looperThread.runBlocking {\n            provider.enableAsync(key.id) { result ->\n                if (result.isSuccess) {\n                    assertTrue(provider.fetch(key.id).isEnabled)\n                    looperThread.testComplete()\n                } else {\n                    fail(result.error.toString())\n                }\n            }\n        }\n    }\n\n    @Test\n    fun enableApiKeyAsync_invalidServerArgsThrows() = looperThread.runBlocking {\n        provider.disableAsync(ObjectId()) { result ->\n            if (result.isSuccess) {\n                fail()\n            } else {\n                assertEquals(ErrorCode.API_KEY_NOT_FOUND, result.error.errorCode)\n                looperThread.testComplete()\n            }\n        }\n    }\n\n    @Test\n    fun disableApiKey() {\n        val key: ApiKey = provider.create(\"my-key\")\n        provider.disable(key.id)\n        assertFalse(provider.fetch(key.id).isEnabled)\n    }\n\n    @Test\n    fun disableApiKey_alreadyDisabled() {\n        val key: ApiKey = provider.create(\"my-key\")\n        provider.disable(key.id)\n        assertFalse(provider.fetch(key.id).isEnabled)\n        provider.disable(key.id)\n        assertFalse(provider.fetch(key.id).isEnabled)\n    }\n\n    @Test\n    fun disableApiKey_invalidServerArgsThrows() {\n        try {\n            provider.disable(ObjectId())\n            fail()\n        } catch (e: AppException) {\n            assertEquals(ErrorCode.API_KEY_NOT_FOUND, e.errorCode)\n        }\n    }\n\n    @Test\n    fun disableApiKey_invalidArgumentThrows() {\n        testNullArg { provider.disable(TestHelper.getNull()) }\n        looperThread.runBlocking {\n            provider.disableAsync(TestHelper.getNull(), checkNullInVoidCallback)\n        }\n    }\n\n    @Test\n    fun disableApiKeyAsync() {\n        val key: ApiKey = provider.create(\"my-key\")\n        assertTrue(key.isEnabled)\n        looperThread.runBlocking {\n            provider.disableAsync(key.id) { result ->\n                if (result.isSuccess) {\n                    assertFalse(provider.fetch(key.id).isEnabled)\n                    looperThread.testComplete()\n                } else {\n                    fail(result.error.toString())\n                }\n            }\n        }\n    }\n\n    @Test\n    fun disableApiKeyAsync_invalidServerArgsThrows() = looperThread.runBlocking {\n        provider.disableAsync(ObjectId()) { result ->\n            if (result.isSuccess) {\n                fail()\n            } else {\n                assertEquals(ErrorCode.API_KEY_NOT_FOUND, result.error.errorCode)\n                looperThread.testComplete()\n            }\n        }\n    }\n\n    @Test\n    @UiThreadTest\n    fun callMethodsOnMainThreadThrows() {\n        for (method in Method.values()) {\n            try {\n                when(method) {\n                    Method.CREATE -> provider.create(\"name\")\n                    Method.FETCH_SINGLE -> provider.fetch(ObjectId())\n                    Method.FETCH_ALL -> provider.fetchAll()\n                    Method.DELETE -> provider.delete(ObjectId())\n                    Method.ENABLE -> provider.enable(ObjectId())\n                    Method.DISABLE -> provider.disable(ObjectId())\n                }\n                fail(\"$method should have thrown an exception\")\n            } catch (error: AppException) {\n                assertEquals(ErrorCode.NETWORK_UNKNOWN, error.errorCode)\n            }\n        }\n    }\n\n    @Test\n    fun callAsyncMethodsOnNonLooperThreadThrows() {\n        for (method in Method.values()) {\n            try {\n                when(method) {\n                    Method.CREATE -> provider.createAsync(\"key\") { fail() }\n                    Method.FETCH_SINGLE -> provider.fetchAsync(ObjectId()) { fail() }\n                    Method.FETCH_ALL -> provider.fetchAll { fail() }\n                    Method.DELETE -> provider.deleteAsync(ObjectId()) { fail() }\n                    Method.ENABLE -> provider.enableAsync(ObjectId()) { fail() }\n                    Method.DISABLE -> provider.disableAsync(ObjectId()) { fail() }\n                }\n                fail(\"$method should have thrown an exception\")\n            } catch (ignore: IllegalStateException) {\n            }\n        }\n    }\n\n    @Test\n    fun callMethodWithLoggedOutUser() {\n        user.logOut()\n        for (method in Method.values()) {\n            try {\n                when(method) {\n                    Method.CREATE -> provider.create(\"name\")\n                    Method.FETCH_SINGLE -> provider.fetch(ObjectId())\n                    Method.FETCH_ALL -> provider.fetchAll()\n                    Method.DELETE -> provider.delete(ObjectId())\n                    Method.ENABLE -> provider.enable(ObjectId())\n                    Method.DISABLE -> provider.disable(ObjectId())\n                }\n                fail(\"$method should have thrown an exception\")\n            } catch (error: AppException) {\n                assertEquals(ErrorCode.APP_UNKNOWN, error.errorCode)\n            }\n        }\n    }\n\n    @Test\n    fun getUser() {\n        assertEquals(app.currentUser(), provider.user)\n    }\n\n    @Test\n    fun getApp() {\n        assertEquals(app, provider.app)\n    }\n}\n\n"
  },
  {
    "path": "realm/realm-library/src/androidTestObjectServer/kotlin/io/realm/AppConfigurationTests.kt",
    "content": "/*\n * Copyright 2020 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 */\npackage io.realm\n\nimport androidx.test.ext.junit.runners.AndroidJUnit4\nimport androidx.test.platform.app.InstrumentationRegistry\nimport io.realm.internal.network.LoggingInterceptor.LOGIN_FEATURE\nimport io.realm.log.LogLevel\nimport io.realm.log.RealmLog\nimport io.realm.log.RealmLogger\nimport io.realm.mongodb.*\nimport io.realm.mongodb.log.obfuscator.HttpLogObfuscator\nimport io.realm.mongodb.sync.*\nimport io.realm.rule.BlockingLooperThread\nimport io.realm.util.assertFailsWithErrorCode\nimport org.bson.codecs.StringCodec\nimport org.bson.codecs.configuration.CodecRegistries\nimport org.junit.Assert.*\nimport org.junit.Before\nimport org.junit.Rule\nimport org.junit.Test\nimport org.junit.rules.TemporaryFolder\nimport org.junit.runner.RunWith\nimport java.io.File\nimport java.lang.ClassCastException\nimport java.net.URL\nimport java.util.*\nimport java.util.concurrent.TimeUnit\nimport java.util.concurrent.atomic.AtomicBoolean\nimport kotlin.collections.LinkedHashMap\nimport kotlin.test.assertFailsWith\nimport kotlin.test.assertNull\n\nprivate const val CUSTOM_HEADER_NAME = \"Foo\"\nprivate const val CUSTOM_HEADER_VALUE = \"bar\"\nprivate const val AUTH_HEADER_NAME = \"RealmAuth\"\n\n@RunWith(AndroidJUnit4::class)\nclass AppConfigurationTests {\n\n    val looperThread = BlockingLooperThread()\n\n    @get:Rule\n    val tempFolder = TemporaryFolder()\n\n    @Before\n    fun setUp() {\n        Realm.init(InstrumentationRegistry.getInstrumentation().targetContext)\n    }\n\n    @Test\n    fun authorizationHeaderName_illegalArgumentsThrows() {\n        val builder: AppConfiguration.Builder = AppConfiguration.Builder(\"app-id\")\n        assertFailsWith<IllegalArgumentException> { builder.authorizationHeaderName(TestHelper.getNull()) }\n        assertFailsWith<IllegalArgumentException> { builder.authorizationHeaderName(\"\") }\n    }\n\n    @Test\n    fun authorizationHeaderName() {\n        val config1 = AppConfiguration.Builder(\"app-id\").build()\n        assertEquals(\"Authorization\", config1.authorizationHeaderName)\n\n        val config2 = AppConfiguration.Builder(\"app-id\")\n                .authorizationHeaderName(\"CustomAuth\")\n                .build()\n        assertEquals(\"CustomAuth\", config2.authorizationHeaderName)\n    }\n\n    @Test\n    fun addCustomRequestHeader_illegalArgumentThrows() {\n        val builder: AppConfiguration.Builder = AppConfiguration.Builder(\"app-id\")\n        assertFailsWith<IllegalArgumentException> { builder.addCustomRequestHeader(\"\", \"val\") }\n        assertFailsWith<IllegalArgumentException> { builder.addCustomRequestHeader(TestHelper.getNull(), \"val\") }\n        assertFailsWith<IllegalArgumentException> { builder.addCustomRequestHeader(\"header\", TestHelper.getNull()) }\n    }\n\n    @Test\n    fun addCustomRequestHeader() {\n        val config = AppConfiguration.Builder(\"app-id\")\n                .addCustomRequestHeader(\"header1\", \"val1\")\n                .addCustomRequestHeader(\"header2\", \"val2\")\n                .build()\n        val headers: Map<String, String> = config.customRequestHeaders\n        assertEquals(2, headers.size.toLong())\n        assertTrue(headers.any { it.key == \"header1\" && it.value == \"val1\" })\n        assertTrue(headers.any { it.key == \"header2\" && it.value == \"val2\" })\n    }\n\n    @Test\n    fun addCustomRequestHeaders() {\n        val inputHeaders: MutableMap<String, String> = LinkedHashMap()\n        inputHeaders[\"header1\"] = \"value1\"\n        inputHeaders[\"header2\"] = \"value2\"\n        val config = AppConfiguration.Builder(\"app-id\")\n                .addCustomRequestHeaders(TestHelper.getNull())\n                .addCustomRequestHeaders(inputHeaders)\n                .build()\n        val outputHeaders: Map<String, String> = config.customRequestHeaders\n        assertEquals(2, outputHeaders.size.toLong())\n        assertTrue(outputHeaders.any { it.key == \"header1\" && it.value == \"value1\" })\n        assertTrue(outputHeaders.any { it.key == \"header2\" && it.value == \"value2\" })\n    }\n\n    @Test\n    fun addCustomHeader_combinesSingleAndMultiple() {\n        val config = AppConfiguration.Builder(\"app-id\")\n                .addCustomRequestHeader(\"header3\", \"val3\")\n                .addCustomRequestHeaders(mapOf(Pair(\"header1\", \"val1\")))\n                .build()\n        val headers: Map<String, String> = config.customRequestHeaders\n        assertEquals(2, headers.size)\n        assertTrue(headers.any { it.key == \"header3\" && it.value == \"val3\" })\n        assertTrue(headers.any { it.key == \"header1\" && it.value == \"val1\" })\n    }\n\n    @Test\n    fun syncRootDirectory_default() {\n        val config = AppConfiguration.Builder(\"app-id\").build()\n        val expectedDefaultRoot = InstrumentationRegistry.getInstrumentation().targetContext.filesDir\n        assertEquals(expectedDefaultRoot, config.syncRootDirectory)\n    }\n\n    @Test\n    fun syncRootDirectory() {\n        val builder: AppConfiguration.Builder = AppConfiguration.Builder(\"app-id\")\n        val expectedRoot = tempFolder.newFolder()\n        val config = builder\n                .syncRootDirectory(expectedRoot)\n                .build()\n        assertEquals(expectedRoot, config.syncRootDirectory)\n    }\n\n    @Test\n    fun syncRootDirectory_null() {\n        val builder: AppConfiguration.Builder = AppConfiguration.Builder(\"app-id\")\n        assertFailsWith<IllegalArgumentException> { builder.syncRootDirectory(TestHelper.getNull()) }\n    }\n\n    @Test\n    fun syncRootDirectory_writeProtectedDir() {\n        val builder: AppConfiguration.Builder = AppConfiguration.Builder(\"app-id\")\n        val dir = File(\"/\")\n        assertFailsWith<IllegalArgumentException> { builder.syncRootDirectory(dir) }\n    }\n\n    @Test\n    fun syncRootDirectory_dirIsAFile() {\n        val builder: AppConfiguration.Builder = AppConfiguration.Builder(\"app-id\")\n        val file = File(tempFolder.newFolder(), \"dummyfile\")\n        assertTrue(file.createNewFile())\n        assertFailsWith<IllegalArgumentException> { builder.syncRootDirectory(file) }\n    }\n\n    @Test\n    fun appName() {\n        val config = AppConfiguration.Builder(\"app-id\")\n                .appName(\"app-name\")\n                .build()\n        assertEquals(\"app-name\", config.appName)\n    }\n\n    @Test\n    fun appName_defaultValue() {\n        val config = AppConfiguration.Builder(\"app-id\").build()\n        assertEquals(null, config.appName)\n    }\n\n    @Test\n    fun appName_invalidValuesThrows() {\n        val builder = AppConfiguration.Builder(\"app-id\")\n\n        assertFailsWith<java.lang.IllegalArgumentException> { builder.appName(TestHelper.getNull()) }\n        assertFailsWith<java.lang.IllegalArgumentException> { builder.appName(\"\") }\n    }\n\n    @Test\n    fun appVersion() {\n        val config = AppConfiguration.Builder(\"app-id\")\n                .appVersion(\"app-version\")\n                .build()\n        assertEquals(\"app-version\", config.appVersion)\n    }\n\n    @Test\n    fun appVersion_defaultValue() {\n        val config = AppConfiguration.Builder(\"app-id\").build()\n        assertEquals(null, config.appVersion)\n    }\n\n    @Test\n    fun appVersion_invalidValuesThrows() {\n        val builder = AppConfiguration.Builder(\"app-id\")\n\n        assertFailsWith<java.lang.IllegalArgumentException> { builder.appVersion(TestHelper.getNull()) }\n        assertFailsWith<java.lang.IllegalArgumentException> { builder.appVersion(\"\") }\n    }\n\n    @Test\n    fun baseUrl() {\n        val url = \"http://myurl.com\"\n        val config = AppConfiguration.Builder(\"foo\").baseUrl(url).build()\n        assertEquals(URL(url), config.baseUrl)\n    }\n\n    @Test\n    fun baseUrl_defaultValue() {\n        val url = \"https://realm.mongodb.com\"\n        val config = AppConfiguration.Builder(\"foo\").build()\n        assertEquals(URL(url), config.baseUrl)\n    }\n\n    @Test\n    fun baseUrl_invalidValuesThrows() {\n        val configBuilder = AppConfiguration.Builder(\"foo\")\n        assertFailsWith<IllegalArgumentException> { configBuilder.baseUrl(\"\") }\n        assertFailsWith<IllegalArgumentException> { configBuilder.baseUrl(TestHelper.getNull()) }\n        assertFailsWith<IllegalArgumentException> { configBuilder.baseUrl(\"invalid-url\") }\n    }\n\n    @Test\n    fun defaultSyncErrorHandler() {\n        val errorHandler = SyncSession.ErrorHandler { _, _ -> }\n\n        val config = AppConfiguration.Builder(\"app-id\")\n                .defaultSyncErrorHandler(errorHandler)\n                .build()\n        assertEquals(config.defaultErrorHandler, errorHandler)\n    }\n\n    @Test\n    fun defaultSyncErrorHandler_invalidValuesThrows() {\n        assertFailsWith<IllegalArgumentException> {\n            AppConfiguration.Builder(\"app-id\")\n                    .defaultSyncErrorHandler(TestHelper.getNull())\n        }\n\n    }\n\n    @Test\n    @Deprecated(\"defaultClientResetHandler deprecated in favor of defaultSyncClientResetStrategy\")\n    fun defaultClientResetHandler_throws() {\n        val config = AppConfiguration.Builder(\"app-id\")\n                .build()\n\n        assertFailsWith<ClassCastException> {\n            config.defaultClientResetHandler\n        }\n    }\n\n    @Test\n    @Deprecated(\"defaultClientResetHandler deprecated in favor of defaultSyncClientResetStrategy\")\n    fun setDefaultClientResetHandler() {\n        val handler = SyncSession.ClientResetHandler { _, _ -> }\n        val config = AppConfiguration.Builder(\"app-id\")\n            .defaultClientResetHandler(handler)\n            .build()\n        assertEquals(config.defaultSyncClientResetStrategy, handler)\n    }\n\n    @Test\n    @Deprecated(\"defaultClientResetHandler deprecated in favor of defaultSyncClientResetStrategy\")\n    fun defaultClientResetHandler_invalidValuesThrows() {\n        val builder = AppConfiguration.Builder(\"app-id\")\n        assertFailsWith<IllegalArgumentException> {\n            builder.defaultClientResetHandler(TestHelper.getNull<SyncSession.ClientResetHandler>())\n        }\n    }\n\n    @Test\n    fun defaultSyncClientStrategy() {\n        val config = AppConfiguration.Builder(\"app-id\")\n            .build()\n\n        assertTrue(config.defaultSyncClientResetStrategy is RecoverOrDiscardUnsyncedChangesStrategy)\n    }\n\n    @Test\n    fun setDefaultSyncClientStrategy_manual() {\n        val strategy = ManuallyRecoverUnsyncedChangesStrategy { _, _ -> }\n\n        val config = AppConfiguration.Builder(\"app-id\")\n            .defaultSyncClientResetStrategy(strategy)\n            .build()\n        assertEquals(config.defaultSyncClientResetStrategy, strategy)\n    }\n\n    @Test\n    fun setDefaultSyncClientStrategy_automaticRecovery() {\n        val strategy = object: RecoverUnsyncedChangesStrategy {\n            override fun onBeforeReset(realm: Realm) {\n                fail(\"Callback should not be reachable\")\n            }\n\n            override fun onAfterReset(before: Realm, after: Realm) {\n                fail(\"Callback should not be reachable\")\n            }\n\n            override fun onManualResetFallback(session: SyncSession, error: ClientResetRequiredError) {\n                fail(\"Callback should not be reachable\")\n            }\n        }\n\n        val config = AppConfiguration.Builder(\"app-id\")\n            .defaultSyncClientResetStrategy(strategy)\n            .build()\n        assertEquals(config.defaultSyncClientResetStrategy, strategy)\n    }\n\n    @Test\n    fun setDefaultSyncClientStrategy_automaticRecoveryOrDiscard() {\n        val strategy = object: RecoverOrDiscardUnsyncedChangesStrategy {\n            override fun onBeforeReset(realm: Realm) {\n                fail(\"Callback should not be reachable\")\n            }\n\n            override fun onAfterRecovery(before: Realm, after: Realm) {\n                fail(\"Callback should not be reachable\")\n            }\n\n            override fun onAfterDiscard(before: Realm, after: Realm) {\n                fail(\"Callback should not be reachable\")\n            }\n\n            override fun onManualResetFallback(session: SyncSession, error: ClientResetRequiredError) {\n                fail(\"Callback should not be reachable\")\n            }\n        }\n\n        val config = AppConfiguration.Builder(\"app-id\")\n            .defaultSyncClientResetStrategy(strategy)\n            .build()\n        assertEquals(config.defaultSyncClientResetStrategy, strategy)\n    }\n\n    @Test\n    fun setDefaultSyncClientStrategy_invalidValuesThrows() {\n        val builder = AppConfiguration.Builder(\"app-id\")\n        assertFailsWith<IllegalArgumentException> {\n            builder.defaultSyncClientResetStrategy(TestHelper.getNull<ManuallyRecoverUnsyncedChangesStrategy>())\n        }\n    }\n\n    @Test\n    fun encryptionKey() {\n        val key = TestHelper.getRandomKey()\n\n        val config = AppConfiguration.Builder(\"app-id\")\n                .encryptionKey(key)\n                .build()\n\n        assertArrayEquals(key, config.encryptionKey)\n    }\n\n    @Test\n    fun encryptionKey_invalidValuesThrows() {\n        val builder = AppConfiguration.Builder(\"app-id\")\n\n        assertFailsWith<IllegalArgumentException> {\n            builder.encryptionKey(TestHelper.getNull())\n        }\n\n        assertFailsWith<IllegalArgumentException> {\n            builder.encryptionKey(byteArrayOf(0, 0, 0, 0))\n        }\n    }\n\n    @Test\n    fun requestTimeout() {\n        val config = AppConfiguration.Builder(\"app-id\")\n                .requestTimeout(1, TimeUnit.SECONDS)\n                .build()\n        assertEquals(1000L, config.requestTimeoutMs)\n    }\n\n    @Test\n    fun requestTimeout_invalidValuesThrows() {\n        val builder = AppConfiguration.Builder(\"app-id\")\n\n        assertFailsWith<IllegalArgumentException> { builder.requestTimeout(-1, TimeUnit.MILLISECONDS) }\n        assertFailsWith<IllegalArgumentException> { builder.requestTimeout(1, TestHelper.getNull()) }\n    }\n\n    @Test\n    fun codecRegistry_null() {\n        val builder: AppConfiguration.Builder = AppConfiguration.Builder(\"app-id\")\n        assertFailsWith<IllegalArgumentException> {\n            builder.codecRegistry(TestHelper.getNull())\n        }\n    }\n\n    @Test\n    fun defaultFunctionsCodecRegistry() {\n        val config: AppConfiguration = AppConfiguration.Builder(\"app-id\").build()\n        assertEquals(AppConfiguration.DEFAULT_BSON_CODEC_REGISTRY, config.defaultCodecRegistry)\n    }\n\n    @Test\n    fun customCodecRegistry() {\n        val configCodecRegistry = CodecRegistries.fromCodecs(StringCodec())\n        val config: AppConfiguration = AppConfiguration.Builder(\"app-id\")\n                .codecRegistry(configCodecRegistry)\n                .build()\n        assertEquals(configCodecRegistry, config.defaultCodecRegistry)\n    }\n\n    @Test\n    fun httpLogObfuscator_null() {\n        val config = AppConfiguration.Builder(\"app-id\")\n                .httpLogObfuscator(TestHelper.getNull())\n                .build()\n        assertNull(config.httpLogObfuscator)\n    }\n\n    @Test\n    fun defaultLoginInfoObfuscator() {\n        val config = AppConfiguration.Builder(\"app-id\").build()\n\n        val defaultHttpLogObfuscator = HttpLogObfuscator(LOGIN_FEATURE, AppConfiguration.loginObfuscators)\n        assertEquals(defaultHttpLogObfuscator, config.httpLogObfuscator)\n    }\n    // Check that custom headers and auth header renames are correctly used for HTTP requests\n    // performed from Java.\n    @Test\n    fun javaRequestCustomHeaders() {\n        var app: App? = null\n        try {\n            looperThread.runBlocking {\n                app = TestApp(builder = { builder ->\n                    builder.addCustomRequestHeader(CUSTOM_HEADER_NAME, CUSTOM_HEADER_VALUE)\n                    builder.authorizationHeaderName(AUTH_HEADER_NAME)\n                })\n                runJavaRequestCustomHeadersTest(app!!)\n            }\n        } finally {\n            app?.close()\n        }\n    }\n\n    private fun runJavaRequestCustomHeadersTest(app: App) {\n        val username = UUID.randomUUID().toString()\n        val password = \"password\"\n        val headerSet = AtomicBoolean(false)\n\n        // Setup logger to inspect that we get a log message with the custom headers\n        val level = RealmLog.getLevel()\n        RealmLog.setLevel(LogLevel.ALL)\n        val logger = RealmLogger { level: Int, tag: String?, throwable: Throwable?, message: String? ->\n            if (level > LogLevel.TRACE && message!!.contains(CUSTOM_HEADER_NAME) && message.contains(CUSTOM_HEADER_VALUE)\n                    && message.contains(\"RealmAuth: \")) {\n                headerSet.set(true)\n            }\n        }\n        RealmLog.add(logger)\n        assertFailsWithErrorCode(ErrorCode.APP_UNKNOWN) {\n            app.registerUserAndLogin(username, password)\n        }\n        RealmLog.remove(logger)\n        RealmLog.setLevel(level)\n\n        assertTrue(headerSet.get())\n        looperThread.testComplete()\n    }\n\n\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTestObjectServer/kotlin/io/realm/AppTests.kt",
    "content": "/*\n * Copyright 2020 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 */\npackage io.realm\n\nimport androidx.test.ext.junit.runners.AndroidJUnit4\nimport androidx.test.platform.app.InstrumentationRegistry\nimport io.realm.admin.ServerAdmin\nimport io.realm.entities.SyncStringOnly\nimport io.realm.exceptions.RealmFileException\nimport io.realm.mongodb.*\nimport io.realm.mongodb.sync.SyncConfiguration\nimport io.realm.mongodb.sync.testSchema\nimport io.realm.rule.BlockingLooperThread\nimport org.bson.codecs.StringCodec\nimport org.bson.codecs.configuration.CodecRegistries\nimport org.junit.*\nimport org.junit.Assert.*\nimport org.junit.runner.RunWith\nimport java.io.File\nimport java.util.concurrent.atomic.AtomicReference\nimport kotlin.test.assertFailsWith\n\n@RunWith(AndroidJUnit4::class)\nclass AppTests {\n    @get:Rule\n    val configFactory = TestSyncConfigurationFactory()\n\n    private val looperThread = BlockingLooperThread()\n    private lateinit var app: TestApp\n    private lateinit var admin: ServerAdmin\n\n    @Before\n    fun setUp() {\n        Realm.init(InstrumentationRegistry.getInstrumentation().targetContext)\n        app = TestApp()\n        admin = ServerAdmin(app)\n    }\n\n    @After\n    fun tearDown() {\n        if (this::app.isInitialized) {\n            app.close()\n        }\n    }\n\n    @Test\n    fun login() {\n        val creds = Credentials.anonymous()\n        var user = app.login(creds)\n        assertNotNull(user)\n    }\n\n    @Test\n    fun login_invalidUserThrows() {\n        val credentials = Credentials.emailPassword(\"foo\", \"bar\")\n        try {\n            app.login(credentials)\n            fail()\n        } catch(ex: AppException) {\n            assertEquals(ErrorCode.INVALID_EMAIL_PASSWORD, ex.errorCode)\n        }\n    }\n\n    @Test\n    fun login_invalidArgsThrows() {\n        assertFailsWith<IllegalArgumentException> { app.login(TestHelper.getNull()) }\n    }\n\n    @Test\n    fun loginAsync() = looperThread.runBlocking {\n        app.loginAsync(Credentials.anonymous()) { result ->\n            assertNotNull(result.orThrow)\n            looperThread.testComplete()\n        }\n    }\n\n    @Test\n    fun loginAsync_invalidUserThrows() = looperThread.runBlocking {\n        app.loginAsync(Credentials.emailPassword(\"foo\", \"bar\")) { result ->\n            assertFalse(result.isSuccess)\n            assertEquals(ErrorCode.INVALID_EMAIL_PASSWORD, result.error.errorCode)\n            looperThread.testComplete()\n        }\n    }\n\n    @Test\n    fun loginAsync_throwsOnNonLooperThread() {\n        try {\n            app.loginAsync(Credentials.anonymous()) { fail() }\n            fail()\n        } catch (ignore: IllegalStateException) {\n        }\n    }\n\n    @Test\n    fun currentUser() {\n        assertNull(app.currentUser())\n        val user: User = app.login(Credentials.anonymous())\n        assertEquals(user, app.currentUser())\n        user.logOut()\n        assertNull(app.currentUser())\n    }\n\n    @Test\n    fun allUsers() {\n        assertEquals(0, app.allUsers().size)\n        val user1 = app.login(Credentials.anonymous())\n        var allUsers = app.allUsers()\n        assertEquals(1, allUsers.size)\n        assertTrue(allUsers.containsKey(user1.id))\n        assertEquals(user1, allUsers[user1.id])\n\n        // Only 1 anonymous user exists, so logging in again just returns the old one\n        val user2 = app.login(Credentials.anonymous())\n        allUsers = app.allUsers()\n        assertEquals(1, allUsers.size)\n        assertTrue(allUsers.containsKey(user2.id))\n\n        val user3: User = app.registerUserAndLogin(TestHelper.getRandomEmail(), \"123456\")\n        allUsers = app.allUsers()\n        assertEquals(2, allUsers.size)\n        assertTrue(allUsers.containsKey(user3.id))\n\n        // Logging out users that registered with email/password will just put them in LOGGED_OUT state\n        user3.logOut();\n        allUsers = app.allUsers()\n        assertEquals(2, allUsers.size)\n        assertTrue(allUsers.containsKey(user3.id))\n        assertEquals(User.State.LOGGED_OUT, allUsers[user3.id]!!.state)\n\n        // Logging out anonymous users will remove them completely\n        user1.logOut()\n        allUsers = app.allUsers()\n        assertEquals(1, allUsers.size)\n        assertFalse(allUsers.containsKey(user1.id))\n    }\n\n    @Test\n    fun allUsers_retrieveRemovedUser() {\n        val user1: User = app.login(Credentials.anonymous())\n        val allUsers: Map<String, User> = app.allUsers()\n        assertEquals(1, allUsers.size)\n        user1.logOut()\n        assertEquals(1, allUsers.size)\n        val userCopy: User = allUsers[user1.id] ?: error(\"Could not find user\")\n        assertEquals(user1, userCopy)\n        assertEquals(User.State.REMOVED, userCopy.state)\n        assertTrue(app.allUsers().isEmpty())\n    }\n\n    @Test\n    fun switchUser() {\n        val user1: User = app.login(Credentials.anonymous())\n        assertEquals(user1, app.currentUser())\n        val user2: User = app.login(Credentials.anonymous())\n        assertEquals(user2, app.currentUser())\n\n        assertEquals(user1, app.switchUser(user1))\n        assertEquals(user1, app.currentUser())\n    }\n\n    @Test\n    fun switchUser_throwIfUserNotLoggedIn() {\n        val user1: User = app.login(Credentials.anonymous())\n        val user2: User = app.login(Credentials.anonymous())\n        assertEquals(user2, app.currentUser())\n\n        user1.logOut()\n        try {\n            app.switchUser(user1)\n            fail()\n        } catch (ignore: IllegalArgumentException) {\n        }\n    }\n\n    @Test\n    fun currentUser_FallbackToNextValidUser() {\n        val user1: User = app.registerUserAndLogin(TestHelper.getRandomEmail(), \"123456\")\n        val user2: User = app.registerUserAndLogin(TestHelper.getRandomEmail(), \"123456\")\n        assertEquals(user2, app.currentUser())\n        user2.logOut()\n        assertEquals(user1, app.currentUser())\n        user1.logOut()\n        assertNull(app.currentUser())\n    }\n\n    @Test\n    fun switchUser_nullThrows() {\n        try {\n            app.switchUser(TestHelper.getNull())\n            fail()\n        } catch (ignore: IllegalArgumentException) {\n        }\n    }\n\n    @Ignore(\"Add this test once we have support for both EmailPassword and ApiKey Auth Providers\")\n    @Test\n    fun switchUser_authProvidersLockUsers() {\n        TODO(\"FIXME\")\n    }\n\n    @Test\n    fun authListener() {\n        val userRef = AtomicReference<User>(null)\n        looperThread.runBlocking {\n            val authenticationListener = object : AuthenticationListener {\n                override fun loggedIn(user: User) {\n                    userRef.set(user)\n                    user.logOutAsync { /* Ignore */ }\n                }\n\n                override fun loggedOut(user: User) {\n                    assertEquals(userRef.get(), user)\n                    looperThread.testComplete()\n                }\n            }\n            app.addAuthenticationListener(authenticationListener)\n            app.login(Credentials.anonymous())\n        }\n    }\n\n    @Test\n    fun authListener_nullThrows() {\n        assertFailsWith<IllegalArgumentException> { app.addAuthenticationListener(TestHelper.getNull()) }\n    }\n\n    @Test\n    fun authListener_remove() = looperThread.runBlocking {\n        val failListener = object : AuthenticationListener {\n            override fun loggedIn(user: User) { fail() }\n            override fun loggedOut(user: User) { fail() }\n        }\n        val successListener = object : AuthenticationListener {\n            override fun loggedOut(user: User) { fail() }\n            override fun loggedIn(user: User) { looperThread.testComplete() }\n        }\n        // This test depends on listeners being executed in order which is an\n        // implementation detail, but there isn't a sure fire way to do this\n        // without depending on implementation details or assume a specific timing.\n        app.addAuthenticationListener(failListener)\n        app.addAuthenticationListener(successListener)\n        app.removeAuthenticationListener(failListener)\n        app.login(Credentials.anonymous())\n    }\n\n    @Test\n    fun functions_defaultCodecRegistry() {\n        var user = app.login(Credentials.anonymous())\n        assertEquals(app.configuration.defaultCodecRegistry, app.getFunctions(user).defaultCodecRegistry)\n    }\n\n    @Test\n    fun functions_customCodecRegistry() {\n        var user = app.login(Credentials.anonymous())\n        val registry = CodecRegistries.fromCodecs(StringCodec())\n        assertEquals(registry, app.getFunctions(user, registry).defaultCodecRegistry)\n    }\n\n    @Test()\n    fun encryption() {\n        val context = InstrumentationRegistry.getInstrumentation().targetContext\n\n        // Create new test app with a random encryption key\n        val testApp = TestApp(appName = TEST_APP_2, builder = {\n            it.encryptionKey(TestHelper.getRandomKey())\n        })\n\n        try {\n            // Create Realm in order to create the sync metadata Realm\n            var user = testApp.login(Credentials.anonymous())\n\n            val syncConfig = SyncConfiguration\n                    .Builder(user, \"foo\")\n                    .testSchema(SyncStringOnly::class.java)\n                    .build()\n\n            Realm.getInstance(syncConfig).close()\n\n            // Create a configuration pointing to the metadata Realm for that app\n            val metadataDir = File(context.filesDir, \"mongodb-realm/${testApp.configuration.appId}/server-utility/metadata/\")\n            val config = RealmConfiguration.Builder()\n                    .name(\"sync_metadata.realm\")\n                    .directory(metadataDir)\n                    .build()\n            assertTrue(File(config.path).exists())\n\n            // Open the metadata realm file without a valid encryption key\n            assertFailsWith<RealmFileException> {\n                DynamicRealm.getInstance(config)\n            }\n        } finally {\n            testApp.close()\n        }\n    }\n\n    // Check that it is possible to have two Java instances of an App class, but they will\n    // share the underlying App state.\n    @Test\n    fun multipleInstancesSameApp() {\n        // Create a second copy of the test app\n        val app2 = TestApp()\n        try {\n            // User handling are shared between each app\n            val user = app.login(Credentials.anonymous());\n            assertEquals(user, app2.currentUser())\n            assertEquals(user, app.allUsers().values.first())\n            assertEquals(user, app2.allUsers().values.first())\n\n            user.logOut();\n\n            assertNull(app.currentUser())\n            assertNull(app2.currentUser())\n        } finally {\n            app2.close()\n        }\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTestObjectServer/kotlin/io/realm/AppUserTests.java",
    "content": "/*\n * Copyright 2016 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;\n//\n//import androidx.test.ext.junit.runners.AndroidJUnit4;\n//import androidx.test.platform.app.InstrumentationRegistry;\n//import androidx.test.rule.UiThreadTestRule;\n//\n//import org.junit.After;\n//import org.junit.Before;\n//import org.junit.Ignore;\n//import org.junit.Rule;\n//import org.junit.Test;\n//import org.junit.rules.ExpectedException;\n//import org.junit.runner.RunWith;\n//import org.mockito.Mockito;\n//import org.mockito.invocation.InvocationOnMock;\n//import org.mockito.stubbing.Answer;\n//\n//import java.io.File;\n//import java.lang.reflect.Constructor;\n//import java.lang.reflect.InvocationTargetException;\n//import java.net.MalformedURLException;\n//import java.net.URL;\n//import java.util.Calendar;\n//import java.util.Iterator;\n//import java.util.List;\n//import java.util.Map;\n//import java.util.UUID;\n//\n//import io.realm.entities.AllTypesModelModule;\n//import io.realm.entities.StringOnly;\n//import io.realm.entities.StringOnlyModule;\n//import io.realm.internal.objectserver.Token;\n//import io.realm.log.RealmLog;\n//import io.realm.objectserver.utils.UserFactory;\n//import io.realm.rule.RunInLooperThread;\n//import io.realm.rule.RunTestInLooperThread;\n//\n//import static io.realm.mongodb.SyncTestUtils.createTestAdminUser;\n//import static io.realm.mongodb.SyncTestUtils.createTestUser;\n//import static junit.framework.Assert.assertEquals;\n//import static org.junit.Assert.assertFalse;\n//import static org.junit.Assert.assertNotEquals;\n//import static org.junit.Assert.assertNotNull;\n//import static org.junit.Assert.assertNull;\n//import static org.junit.Assert.assertTrue;\n//import static org.junit.Assert.fail;\n//import static org.mockito.Matchers.any;\n//import static org.mockito.Mockito.when;\n//\n//@RunWith(AndroidJUnit4.class)\n//public class AppUserTests {\n//\n//    private static final URL authUrl;\n//    private static final Constructor<SyncUser> SYNC_USER_CONSTRUCTOR;\n//    static {\n//        try {\n//            authUrl = new URL(\"http://localhost/auth\");\n//            SYNC_USER_CONSTRUCTOR = SyncUser.class.getDeclaredConstructor(Token.class, URL.class);\n//            SYNC_USER_CONSTRUCTOR.setAccessible(true);\n//        } catch (MalformedURLException e) {\n//            throw new ExceptionInInitializerError(e);\n//        } catch (NoSuchMethodException e) {\n//            throw new ExceptionInInitializerError(e);\n//        }\n//    }\n//\n//    @Rule\n//    public final RunInLooperThread looperThread = new RunInLooperThread();\n//\n//    @Rule\n//    public final ExpectedException thrown = ExpectedException.none();\n//\n//    @Rule\n//    public final UiThreadTestRule uiThreadTestRule = new UiThreadTestRule();\n//\n//    @Before\n//    public void setUp() {\n//        BaseRealm.applicationContext = null;\n//        Realm.init(InstrumentationRegistry.getInstrumentation().getTargetContext());\n//        UserStore userStore = SyncManager.getUserStore();\n//        for (SyncUser syncUser : userStore.allUsers()) {\n//            userStore.remove(syncUser.getIdentity(), syncUser.getAuthenticationUrl().toString());\n//        }\n//    }\n//\n//    @After\n//    public void after() {\n//        if (!looperThread.isRuleUsed() || looperThread.isTestComplete()) {\n//            UserFactory.logoutAllUsers();\n//        } else {\n//            looperThread.runAfterTest(new Runnable() {\n//                @Override\n//                public void run() {\n//                    UserFactory.logoutAllUsers();\n//                }\n//            });\n//        }\n//    }\n//\n//    private static SyncUser createFakeUser(String id) {\n//        final Token token = new Token(\"token_value\", id, \"path_value\", Long.MAX_VALUE, null);\n//        try {\n//            return SYNC_USER_CONSTRUCTOR.newInstance(token, authUrl);\n//        } catch (InstantiationException | IllegalAccessException | InvocationTargetException e) {\n//            fail(e.getMessage());\n//        }\n//        return null;\n//    }\n//\n//    @Test\n//    public void equals_validUser() {\n//        final SyncUser user1 = createFakeUser(\"id_value\");\n//        final SyncUser user2 = createFakeUser(\"id_value\");\n//        assertTrue(user1.equals(user2));\n//    }\n//\n//    @Test\n//    public void equals_loggedOutUser() {\n//        final SyncUser user1 = createFakeUser(\"id_value\");\n//        final SyncUser user2 = createFakeUser(\"id_value\");\n//        user1.logOut();\n//        user2.logOut();\n//        assertTrue(user1.equals(user2));\n//    }\n//\n//    @Test\n//    public void hashCode_validUser() {\n//        final SyncUser user = createFakeUser(\"id_value\");\n//        assertNotEquals(0, user.hashCode());\n//    }\n//\n//    @Test\n//    public void hashCode_loggedOutUser() {\n//        final SyncUser user = createFakeUser(\"id_value\");\n//        user.logOut();\n//        assertNotEquals(0, user.hashCode());\n//    }\n//\n//    @Test\n//    public void toAndFromJson() {\n//        SyncUser user1 = createTestUser();\n//        SyncUser user2 = SyncUser.fromJson(user1.toJson());\n//        assertEquals(user1, user2);\n//    }\n//\n//    // Tests that the UserStore does not return users that have expired\n//    @Test\n//    public void currentUser_returnsNullIfUserExpired() {\n//        // Add an expired user to the user store\n//        UserStore userStore = SyncManager.getUserStore();\n//        userStore.put(createTestUser(Long.MIN_VALUE));\n//\n//        // Invalid users should not be returned when asking the for the current user\n//        assertNull(SyncUser.current());\n//    }\n//\n//    @Test\n//    public void currentUser_throwsIfMultipleUsersLoggedIn() {\n//        RealmObjectServer originalAuthServer = SyncManager.getAuthServer();\n//        RealmObjectServer authServer = Mockito.mock(RealmObjectServer.class);\n//        SyncManager.setAuthServerImpl(authServer);\n//\n//        try {\n//            // 1. Login two random users\n//            when(authServer.loginUser(any(SyncCredentials.class), any(URL.class))).thenAnswer(new Answer<AuthenticateResponse>() {\n//                @Override\n//                public AuthenticateResponse answer(InvocationOnMock invocationOnMock) throws Throwable {\n//                    return getNewRandomUser();\n//                }\n//            });\n//            SyncUser.logIn(SyncCredentials.facebook(\"foo\"), \"http:/test.realm.io/auth\");\n//            SyncUser.logIn(SyncCredentials.facebook(\"foo\"), \"http:/test.realm.io/auth\");\n//\n//            // 2. Verify current() now throws\n//            try {\n//                SyncUser.current();\n//                fail();\n//            } catch (IllegalStateException ignore) {\n//            }\n//        } finally {\n//            SyncManager.setAuthServerImpl(originalAuthServer);\n//        }\n//\n//    }\n//\n//    private AuthenticateResponse getNewRandomUser() {\n//        String identity = UUID.randomUUID().toString();\n//        String userTokenValue = UUID.randomUUID().toString();\n//        return SyncTestUtils.createLoginResponse(userTokenValue, identity, Long.MAX_VALUE, false);\n//    }\n//\n//    // Test that current user is cleared if it is logged out\n//    @Test\n//    public void currentUser_clearedOnLogout() {\n//        // Add 1 valid user to the user store\n//        SyncUser user = createTestUser(Long.MAX_VALUE);\n//        UserStore userStore = SyncManager.getUserStore();\n//        userStore.put(user);\n//\n//        SyncUser savedUser = SyncUser.current();\n//        assertEquals(user, savedUser);\n//        assertNotNull(savedUser);\n//        savedUser.logOut();\n//        assertNull(SyncUser.current());\n//    }\n//\n//    // `all()` returns an empty list if no users are logged in\n//    @Test\n//    public void all_empty() {\n//        Map<String, SyncUser> users = SyncUser.all();\n//        assertTrue(users.isEmpty());\n//    }\n//\n//    // `all()` returns only valid users. Invalid users are filtered.\n//    @Test\n//    public void all_validUsers() {\n//        // Add 1 expired user and 1 valid user to the user store\n//        UserStore userStore = SyncManager.getUserStore();\n//        userStore.put(createTestUser(Long.MIN_VALUE));\n//        userStore.put(createTestUser(Long.MAX_VALUE));\n//\n//        Map<String, SyncUser> users = SyncUser.all();\n//        assertEquals(1, users.size());\n//        assertTrue(users.entrySet().iterator().next().getValue().isValid());\n//    }\n//\n//    @Test\n//    public void isAdmin() {\n//        SyncUser user1 = createTestUser();\n//        assertFalse(user1.isAdmin());\n//\n//        SyncUser user2 = createTestAdminUser();\n//        assertTrue(user2.isAdmin());\n//    }\n//\n//    @Test\n//    public void isAdmin_allUsers() {\n//        UserStore userStore = SyncManager.getUserStore();\n//        SyncUser user = createTestAdminUser();\n//        assertTrue(user.isAdmin());\n//        userStore.put(user);\n//\n//        Map <String, SyncUser> users = SyncUser.all();\n//        assertEquals(1, users.size());\n//        assertTrue(users.entrySet().iterator().next().getValue().isAdmin());\n//    }\n//\n//    // Tests that the user store returns the last user to login\n//    @Ignore(\"This test fails because of wrong JSON string.\")\n//    @Test\n//    public void currentUser_returnsUserAfterLogin() {\n//        RealmObjectServer authServer = Mockito.mock(RealmObjectServer.class);\n//        when(authServer.loginUser(any(SyncCredentials.class), any(URL.class))).thenReturn(SyncTestUtils.createLoginResponse(Long.MAX_VALUE));\n//\n//        SyncUser user = SyncUser.logIn(SyncCredentials.facebook(\"foo\"), \"http://bar.com/auth\");\n//        assertEquals(user, SyncUser.current());\n//    }\n//\n//    @Test\n//    public void toString_returnDescription() {\n//        SyncUser user = createTestUser(\"http://objectserver.realm.io/auth\");\n//        String str = user.toString();\n//        assertTrue(str != null && !str.isEmpty());\n//    }\n//\n//    // Test that a login with an access token logs the user in directly without touching the network\n//    @Test\n//    public void login_withAccessToken() {\n//        RealmObjectServer authServer = Mockito.mock(RealmObjectServer.class);\n//        when(authServer.loginUser(any(SyncCredentials.class), any(URL.class))).thenThrow(new AssertionError(\"Server contacted.\"));\n//        RealmObjectServer originalServer = SyncManager.getAuthServer();\n//        SyncManager.setAuthServerImpl(authServer);\n//        try {\n//            SyncCredentials credentials = SyncCredentials.accessToken(\"foo\", \"bar\");\n//            SyncUser user = SyncUser.logIn(credentials, \"http://ros.realm.io/auth\");\n//            assertTrue(user.isValid());\n//        } finally {\n//            SyncManager.setAuthServerImpl(originalServer);\n//        }\n//    }\n//\n//    // Checks that `/auth` is correctly added to any URL without a path\n//    @Test\n//    public void login_appendAuthSegment() {\n//        RealmObjectServer authServer = Mockito.mock(RealmObjectServer.class);\n//        RealmObjectServer originalServer = SyncManager.getAuthServer();\n//        SyncManager.setAuthServerImpl(authServer);\n//        String[][] urls = {\n//                {\"http://ros.realm.io\", \"http://ros.realm.io/auth\"},\n//                {\"http://ros.realm.io:8080\", \"http://ros.realm.io:8080/auth\"},\n//                {\"http://ros.realm.io/\", \"http://ros.realm.io/\"},\n//                {\"http://ros.realm.io/?foo=bar\", \"http://ros.realm.io/?foo=bar\"},\n//                {\"http://ros.realm.io/auth\", \"http://ros.realm.io/auth\"},\n//                {\"http://ros.realm.io/auth/\", \"http://ros.realm.io/auth/\"},\n//                {\"http://ros.realm.io/custom-path/\", \"http://ros.realm.io/custom-path/\"}\n//        };\n//\n//        try {\n//            for (String[] url : urls) {\n//                RealmLog.error(url[0]);\n//                String input = url[0];\n//                String normalizedInput = url[1];\n//                SyncCredentials credentials = SyncCredentials.accessToken(\"token\", UUID.randomUUID().toString());\n//                SyncUser user = SyncUser.logIn(credentials, input);\n//                assertEquals(normalizedInput, user.getAuthenticationUrl().toString());\n//                user.logOut();\n//            }\n//        } finally {\n//            SyncManager.setAuthServerImpl(originalServer);\n//        }\n//    }\n//\n//    @Test\n//    public void changePassword_nullThrows() {\n//        SyncUser user = createTestUser();\n//\n//        thrown.expect(IllegalArgumentException.class);\n//        //noinspection ConstantConditions\n//        user.changePassword(null);\n//    }\n//\n//    @Test\n//    public void changePassword_admin_nullThrows() {\n//        SyncUser user = createTestUser();\n//\n//        thrown.expect(IllegalArgumentException.class);\n//        //noinspection ConstantConditions\n//        user.changePassword(null, \"new-password\");\n//    }\n//\n//    @Test\n//    public void changePasswordAsync_nonLooperThreadThrows() {\n//        SyncUser user = createTestUser();\n//\n//        thrown.expect(IllegalStateException.class);\n//        user.changePasswordAsync(\"password\", new SyncUser.Callback<SyncUser>() {\n//            @Override\n//            public void onSuccess(SyncUser user) {\n//                fail();\n//            }\n//\n//            @Override\n//            public void onError(ObjectServerError error) {\n//                fail();\n//            }\n//        });\n//    }\n//\n//    @Test\n//    public void changePassword_admin_Async_nonLooperThreadThrows() {\n//        SyncUser user = createTestUser();\n//\n//        thrown.expect(IllegalStateException.class);\n//        user.changePasswordAsync(\"user-id\", \"new\", new SyncUser.Callback<SyncUser>() {\n//            @Override\n//            public void onSuccess(SyncUser user) {\n//                fail();\n//            }\n//\n//            @Override\n//            public void onError(ObjectServerError error) {\n//                fail();\n//            }\n//        });\n//    }\n//\n//    @Test\n//    @RunTestInLooperThread\n//    public void changePasswordAsync_nullCallbackThrows() {\n//        SyncUser user = createTestUser();\n//\n//        thrown.expect(IllegalArgumentException.class);\n//        //noinspection ConstantConditions\n//        user.changePasswordAsync(\"new-password\", null);\n//    }\n//\n//    @Test\n//    @RunTestInLooperThread\n//    public void changePassword_admin_Async_nullCallbackThrows() {\n//        SyncUser user = createTestUser();\n//\n//        thrown.expect(IllegalArgumentException.class);\n//        //noinspection ConstantConditions\n//        user.changePasswordAsync(\"user-id\", \"new-password\", null);\n//    }\n//\n//    @Test\n//    @RunTestInLooperThread\n//    public void changePassword_noneAdminThrows() {\n//        SyncUser user = createTestUser();\n//\n//        thrown.expect(IllegalStateException.class);\n//        user.changePassword(\"user-id\", \"new-password\");\n//    }\n//\n//    @Test\n//    public void allSessions() {\n//        String url1 = \"realm://objectserver.realm.io/default\";\n//        String url2 = \"realm://objectserver.realm.io/~/default\";\n//\n//        SyncUser user = createTestUser();\n//        assertEquals(0, user.allSessions().size());\n//\n//        SyncConfiguration configuration1 = user.createConfiguration(url1).modules(new AllTypesModelModule()).build();\n//        Realm realm1 = Realm.getInstance(configuration1);\n//        List<SyncSession> allSessions = user.allSessions();\n//        assertEquals(1, allSessions.size());\n//        Iterator<SyncSession> iter = allSessions.iterator();\n//        SyncSession session = iter.next();\n//        assertEquals(user, session.getUser());\n//        assertEquals(url1, session.getServerUrl().toString());\n//\n//        SyncConfiguration configuration2 = user.createConfiguration(url2).modules(new AllTypesModelModule()).build();\n//        Realm realm2 = Realm.getInstance(configuration2);\n//        allSessions = user.allSessions();\n//        assertEquals(2, allSessions.size());\n//        iter = allSessions.iterator();\n//        String individualUrl = url2.replace(\"~\", user.getIdentity());\n//        int foundCount = 0;\n//        while (iter.hasNext()) {\n//            session = iter.next();\n//            assertEquals(user, session.getUser());\n//            if (individualUrl.equals(session.getServerUrl().toString())) {\n//                foundCount++;\n//            }\n//        }\n//        assertEquals(1, foundCount);\n//        realm1.close();\n//\n//        allSessions = user.allSessions();\n//        assertEquals(1, allSessions.size());\n//        iter = allSessions.iterator();\n//        session = iter.next();\n//        assertEquals(user, session.getUser());\n//        assertEquals(individualUrl, session.getServerUrl().toString());\n//\n//        realm2.close();\n//        assertEquals(0, user.allSessions().size());\n//    }\n//\n//    // JSON format changed in 3.6.0 (removed unnecessary fields), this regression test\n//    // makes sure we can still deserialize a valid SyncUser from the old format.\n//    @Test\n//    public void fromJson_WorkWithRemovedObjectServerUser() {\n//        String oldSyncUserJSON = \"{\\\"authUrl\\\":\\\"http:\\\\/\\\\/192.168.1.151:9080\\\\/auth\\\",\\\"userToken\\\":{\\\"token\\\":\\\"eyJpZGVudGl0eSI6IjY4OWQ5MGMxNDIyYTIwMmZkNTljNDYwM2M0ZTRmNmNjIiwiZXhwaXJlcyI6MTgxNjM1ODE4NCwiYXBwX2lkIjoiaW8ucmVhbG0ucmVhbG10YXNrcyIsImFjY2VzcyI6WyJyZWZyZXNoIl0sImlzX2FkbWluIjpmYWxzZSwic2FsdCI6MC4yMTEwMjQyNDgwOTEyMzg1NH0=:lEDa83o1zu8rkwdZVpTyunLHh1wmjxPPSGmZQNxdEM7xDmpbiU7V+8dgDWGevJNHMFluNDAOmrcAOI9TLfhI4rMDl70NI1K9rv\\\\/Aeq5uIOzq\\\\/Gf7JTeTUKY5Z7yRoppd8NArlNBKesLFxzdLRlfm1hflF9wH23xQXA19yUZ67JIlkhDPL5e3bau8O3Pr\\\\/St0unW3KzPOiZUk1l9KRrs2iMCCiXCfq4rf6rp7B2M7rBUMQm68GnB1Ot7l1CblxEWcREcbpyhBKTWIOFRGMwg2TW\\\\/zRR3cRNglx+ZC4FOeO0mfkX+nf+slyFODAnQkOzPZcGO8xc3I1emafX58Wl\\\\/Guw==\\\",\\\"token_data\\\":{\\\"identity\\\":\\\"689d90c1422a202fd59c4603c4e4f6cc\\\",\\\"path\\\":\\\"\\\",\\\"expires\\\":1816358184,\\\"access\\\":[\\\"unknown\\\"],\\\"is_admin\\\":false}},\\\"realms\\\":[]}\";\n//        SyncUser syncUser = SyncUser.fromJson(oldSyncUserJSON);\n//\n//        // Note: we can't call isValid() and expect it to be true\n//        //       since the user is not persisted in the UserStore\n//        //       isValid() requires SyncManager.getUserStore().isActive(identity)\n//        //       to return true as well.\n//        Token refreshToken = syncUser.getRefreshToken();\n//        assertNotNull(refreshToken);\n//        // refresh token should expire in 10 years (July 23, 2027)\n//        Calendar calendar = Calendar.getInstance();\n//        calendar.setTimeInMillis(refreshToken.expiresMs());\n//        int day = calendar.get(Calendar.DAY_OF_MONTH);\n//        int month = calendar.get(Calendar.MONTH);\n//        int year = calendar.get(Calendar.YEAR);\n//\n//        assertEquals(23, day);\n//        assertEquals(Calendar.JULY, month);\n//        assertEquals(2027, year);\n//\n//        assertEquals(\"http://192.168.1.151:9080/auth\", syncUser.getAuthenticationUrl().toString());\n//    }\n//\n//    @Test\n//    @Ignore(\"until https://github.com/realm/realm-java/issues/5097 is fixed\")\n//    public void logoutUserShouldDeleteRealmAfterRestart() throws InterruptedException {\n//        SyncManager.reset();\n//        BaseRealm.applicationContext = null; // Required for Realm.init() to work\n//        Realm.init(InstrumentationRegistry.getInstrumentation().getTargetContext());\n//\n//        SyncUser user = createTestUser();\n//        SyncConfiguration syncConfiguration = user.createConfiguration(\"realm://127.0.0.1:9080/~/tests\")\n//                .modules(new StringOnlyModule())\n//                .build();\n//\n//        Realm realm = Realm.getInstance(syncConfiguration);\n//        realm.executeTransaction(new Realm.Transaction() {\n//            @Override\n//            public void execute(Realm realm) {\n//                realm.createObject(StringOnly.class).setChars(\"1\");\n//            }\n//        });\n//        user.logOut();\n//        realm.close();\n//\n//        final File realmPath = new File (syncConfiguration.getPath());\n//        assertTrue(realmPath.exists());\n//\n//        // simulate an app restart\n//        SyncManager.reset();\n//        BaseRealm.applicationContext = null;\n//        Realm.init(InstrumentationRegistry.getInstrumentation().getTargetContext());\n//\n//        //now the file should be deleted\n//        assertFalse(realmPath.exists());\n//    }\n//}\n"
  },
  {
    "path": "realm/realm-library/src/androidTestObjectServer/kotlin/io/realm/CredentialsTests.kt",
    "content": "/*\n * Copyright 2020 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 */\npackage io.realm\n\nimport androidx.test.ext.junit.runners.AndroidJUnit4\nimport androidx.test.platform.app.InstrumentationRegistry\nimport io.realm.admin.ServerAdmin\nimport io.realm.mongodb.*\nimport io.realm.mongodb.auth.ApiKey\nimport io.realm.mongodb.auth.GoogleAuthType\nimport org.bson.Document\nimport org.junit.After\nimport org.junit.Assert.*\nimport org.junit.BeforeClass\nimport org.junit.Ignore\nimport org.junit.Test\nimport org.junit.runner.RunWith\nimport kotlin.test.assertFailsWith\n\n\n@RunWith(AndroidJUnit4::class)\nclass CredentialsTests {\n\n    private lateinit var app: App\n    private lateinit var admin: ServerAdmin\n\n    companion object {\n\n        @BeforeClass\n        @JvmStatic\n        fun setUp() {\n            Realm.init(InstrumentationRegistry.getInstrumentation().targetContext)\n        }\n    }\n\n    @After\n    fun tearDown() {\n        if (this::app.isInitialized) {\n            app.close()\n        }\n    }\n\n    @Test\n    fun anonymous() {\n        val creds = Credentials.anonymous()\n        assertEquals(Credentials.Provider.ANONYMOUS, creds.identityProvider)\n        assertTrue(creds.asJson().contains(\"anon-user\")) // Treat the JSON as an opaque value.\n    }\n\n    @Test\n    fun apiKey() {\n        val creds = Credentials.apiKey(\"token\")\n        assertEquals(Credentials.Provider.API_KEY, creds.identityProvider)\n        assertTrue(creds.asJson().contains(\"token\")) // Treat the JSON as an opaque value.\n    }\n\n    @Test\n    fun apiKey_invalidInput() {\n        assertFailsWith<IllegalArgumentException> { Credentials.apiKey(\"\") }\n        assertFailsWith<IllegalArgumentException> { Credentials.apiKey(TestHelper.getNull()) }\n    }\n\n    @Test\n    fun apple() {\n        val creds = Credentials.apple(\"apple-token\")\n        assertEquals(Credentials.Provider.APPLE, creds.identityProvider)\n        assertTrue(creds.asJson().contains(\"apple-token\")) // Treat the JSON as a largely opaque value.\n    }\n\n    @Test\n    fun apple_invalidInput() {\n        assertFailsWith<IllegalArgumentException> { Credentials.apple(\"\") }\n        assertFailsWith<IllegalArgumentException> { Credentials.apple(TestHelper.getNull()) }\n    }\n\n    @Test\n    fun customFunction() {\n        val mail = TestHelper.getRandomEmail()\n        val id = 666 + TestHelper.getRandomId()\n        val creds = mapOf(\n                \"mail\" to mail,\n                \"id\" to id\n        ).let { Credentials.customFunction(Document(it)) }\n        assertEquals(Credentials.Provider.CUSTOM_FUNCTION, creds.identityProvider)\n        assertTrue(creds.asJson().contains(mail))\n        assertTrue(creds.asJson().contains(id.toString()))\n    }\n\n    @Test\n    fun customFunction_invalidInput() {\n        assertFailsWith<IllegalArgumentException> { Credentials.customFunction(null) }\n    }\n\n    @Test\n    fun emailPassword() {\n        val creds = Credentials.emailPassword(\"foo@bar.com\", \"secret\")\n        assertEquals(Credentials.Provider.EMAIL_PASSWORD, creds.identityProvider)\n        // Treat the JSON as a largely opaque value.\n        assertTrue(creds.asJson().contains(\"foo@bar.com\"))\n        assertTrue(creds.asJson().contains(\"secret\"))\n    }\n\n    @Test\n    fun emailPassword_invalidInput() {\n        assertFailsWith<IllegalArgumentException> { Credentials.emailPassword(\"\", \"password\") }\n        assertFailsWith<IllegalArgumentException> { Credentials.emailPassword(\"email\", \"\") }\n        assertFailsWith<IllegalArgumentException> { Credentials.emailPassword(TestHelper.getNull(), \"password\") }\n        assertFailsWith<IllegalArgumentException> { Credentials.emailPassword(\"email\", TestHelper.getNull()) }\n    }\n\n    @Test\n    fun facebook() {\n        val creds = Credentials.facebook(\"fb-token\")\n        assertEquals(Credentials.Provider.FACEBOOK, creds.identityProvider)\n        assertTrue(creds.asJson().contains(\"fb-token\"))\n    }\n\n    @Test\n    fun facebook_invalidInput() {\n        assertFailsWith<IllegalArgumentException> { Credentials.facebook(\"\") }\n        assertFailsWith<IllegalArgumentException> { Credentials.facebook(TestHelper.getNull()) }\n    }\n\n    @Test\n    fun google_authCode() {\n        val creds = Credentials.google(\"google-token\", GoogleAuthType.AUTH_CODE)\n        assertEquals(Credentials.Provider.GOOGLE, creds.identityProvider)\n        assertTrue(creds.asJson().contains(\"google-token\"))\n        assertTrue(creds.asJson().contains(\"authCode\"))\n    }\n\n    @Test\n    fun google_idToken() {\n        val creds = Credentials.google(\"google-token\", GoogleAuthType.ID_TOKEN)\n        assertEquals(Credentials.Provider.GOOGLE, creds.identityProvider)\n        assertTrue(creds.asJson().contains(\"google-token\"))\n        assertTrue(creds.asJson().contains(\"id_token\"))\n    }\n\n    @Test\n    fun google_invalidInput_authCode() {\n        assertFailsWith<IllegalArgumentException> { Credentials.google(\"\", GoogleAuthType.AUTH_CODE) }\n        assertFailsWith<IllegalArgumentException> { Credentials.google(TestHelper.getNull(), GoogleAuthType.AUTH_CODE) }\n    }\n\n    @Test\n    fun google_invalidInput_idToken() {\n        assertFailsWith<IllegalArgumentException> { Credentials.google(\"\", GoogleAuthType.ID_TOKEN) }\n        assertFailsWith<IllegalArgumentException> { Credentials.google(TestHelper.getNull(), GoogleAuthType.ID_TOKEN) }\n    }\n\n    @Ignore(\"FIXME: Awaiting ObjectStore support\")\n    @Test\n    fun jwt() {\n        val creds = Credentials.jwt(\"jwt-token\")\n        assertEquals(Credentials.Provider.JWT, creds.identityProvider)\n        assertTrue(creds.asJson().contains(\"jwt-token\"))\n    }\n\n    @Test\n    fun jwt_invalidInput() {\n        assertFailsWith<IllegalArgumentException> { Credentials.jwt(\"\") }\n        assertFailsWith<IllegalArgumentException> { Credentials.jwt(TestHelper.getNull()) }\n    }\n\n    @Test\n    fun loginUsingCredentials() {\n        app = TestApp()\n        admin = ServerAdmin(app)\n        Credentials.Provider.values().forEach { provider ->\n            when (provider) {\n                Credentials.Provider.ANONYMOUS -> {\n                    val user = app.login(Credentials.anonymous())\n                    assertNotNull(user)\n                }\n                Credentials.Provider.API_KEY -> {\n                    // Log in, create an API key, log out, log in with the key, compare users\n                    val user: User = app.registerUserAndLogin(TestHelper.getRandomEmail(), \"123456\")\n                    val key: ApiKey = user.apiKeys.create(\"my-key\");\n                    user.logOut()\n                    val apiKeyUser = app.login(Credentials.apiKey(key.value!!))\n                    assertEquals(user.id, apiKeyUser.id)\n                }\n                Credentials.Provider.CUSTOM_FUNCTION -> {\n                    val customFunction = mapOf(\n                            \"mail\" to TestHelper.getRandomEmail(),\n                            \"id\" to 666 + TestHelper.getRandomId()\n                    ).let {\n                        Credentials.customFunction(Document(it))\n                    }\n\n                    // We are not testing the authentication function itself, but rather that the\n                    // credentials work\n                    val functionUser = app.login(customFunction)\n                    assertNotNull(functionUser)\n                }\n                Credentials.Provider.EMAIL_PASSWORD -> {\n                    val email = TestHelper.getRandomEmail()\n                    val password = \"123456\"\n                    app.emailPassword.registerUser(email, password)\n                    val user = app.login(Credentials.emailPassword(email, password))\n                    assertNotNull(user)\n                }\n\n                // These providers are hard to test for real since they depend on a 3rd party\n                // login service. Instead we attempt to login and verify that a proper exception\n                // is thrown. At least that should verify that correctly formatted JSON is being\n                // sent across the wire.\n                Credentials.Provider.FACEBOOK -> {\n                    expectErrorCode(app, ErrorCode.INVALID_SESSION, Credentials.facebook(\"facebook-token\"))\n                }\n                Credentials.Provider.APPLE -> {\n                    expectErrorCode(app, ErrorCode.INVALID_SESSION, Credentials.apple(\"apple-token\"))\n                }\n                Credentials.Provider.GOOGLE -> {\n                    expectErrorCode(app, ErrorCode.INVALID_SESSION, Credentials.google(\"google-token\", GoogleAuthType.AUTH_CODE))\n                    expectErrorCode(app, ErrorCode.INVALID_SESSION, Credentials.google(\"google-token\", GoogleAuthType.ID_TOKEN))\n                }\n                Credentials.Provider.JWT -> {\n                    expectErrorCode(app, ErrorCode.INVALID_SESSION, Credentials.jwt(\"jwt-token\"))\n                }\n                Credentials.Provider.UNKNOWN -> {\n                    // Ignore\n                }\n            }\n        }\n    }\n\n    private fun expectErrorCode(app: App, expectedCode: ErrorCode, credentials: Credentials) {\n        try {\n            app.login(credentials)\n            fail()\n        } catch (error: AppException) {\n            assertEquals(expectedCode, error.errorCode)\n        }\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTestObjectServer/kotlin/io/realm/EmailPasswordAuthTests.kt",
    "content": "/*\n * Copyright 2020 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 */\npackage io.realm\n\nimport androidx.test.annotation.UiThreadTest\nimport androidx.test.ext.junit.runners.AndroidJUnit4\nimport androidx.test.platform.app.InstrumentationRegistry\nimport io.realm.admin.ServerAdmin\nimport io.realm.log.LogLevel\nimport io.realm.log.RealmLog\nimport io.realm.mongodb.*\nimport io.realm.mongodb.auth.EmailPasswordAuth\nimport io.realm.rule.BlockingLooperThread\nimport org.junit.After\nimport org.junit.Assert.assertEquals\nimport org.junit.Assert.fail\nimport org.junit.Before\nimport org.junit.Ignore\nimport org.junit.Test\nimport org.junit.runner.RunWith\nimport kotlin.test.assertFailsWith\nimport io.realm.TEST_APP_1\nimport io.realm.TEST_APP_2\nimport io.realm.TEST_APP_3\nimport kotlin.random.Random\nimport kotlin.test.assertContains\n\nabstract class EmailPasswordAuthTests {\n\n    protected val looperThread = BlockingLooperThread()\n    protected lateinit var app: TestApp\n    protected lateinit var admin: ServerAdmin\n\n    // Callback use to verify that an Illegal Argument was thrown from async methods\n    protected val checkNullArgCallback = App.Callback<Void> { result ->\n        if (result.isSuccess) {\n            fail()\n        } else {\n            assertEquals(ErrorCode.UNKNOWN, result.error.errorCode)\n            looperThread.testComplete()\n        }\n    }\n\n    // Methods exposed by the EmailPasswordAuthProvider\n    protected enum class Method {\n        REGISTER_USER,\n        CONFIRM_USER,\n        RESEND_CONFIRMATION_EMAIL,\n        SEND_RESET_PASSWORD_EMAIL,\n        CALL_RESET_PASSWORD_FUNCTION,\n        RETRY_CUSTOM_CONFIRMATION,\n        RESET_PASSWORD\n    }\n}\n\n@RunWith(AndroidJUnit4::class)\nclass EmailPasswordAuthWithAutoConfirm: EmailPasswordAuthTests() {\n\n    @Before\n    fun setUp() {\n        Realm.init(InstrumentationRegistry.getInstrumentation().targetContext)\n        app = TestApp(appName = TEST_APP_1)\n        RealmLog.setLevel(LogLevel.DEBUG)\n        admin = ServerAdmin(app)\n        admin.deleteAllUsers()\n    }\n\n    @After\n    fun tearDown() {\n        app.close()\n        RealmLog.setLevel(LogLevel.WARN)\n    }\n\n    @Test\n    fun registerUser() {\n        val email = TestHelper.getRandomEmail()\n        val password = \"password1234\"\n        app.emailPassword.registerUser(email, password)\n        val user = app.login(Credentials.emailPassword(email, password))\n        assertEquals(User.State.LOGGED_IN, user.state)\n    }\n\n    @Test\n    fun registerUserAsync() {\n        val email = TestHelper.getRandomEmail()\n        val password = \"password1234\"\n        looperThread.runBlocking {\n            app.emailPassword.registerUserAsync(email, password) { result ->\n                if (result.isSuccess) {\n                    val user2 = app.login(Credentials.emailPassword(email, password))\n                    assertEquals(User.State.LOGGED_IN, user2.state)\n                    looperThread.testComplete()\n                } else {\n                    fail(result.error.toString())\n                }\n            }\n        }\n    }\n\n    @Test\n    fun registerUser_invalidServerArgsThrows() {\n        val provider = app.emailPassword\n        try {\n            provider.registerUser(\"invalid-email\", \"1234\")\n            fail()\n        } catch (ex: AppException) {\n            assertEquals(ErrorCode.BAD_REQUEST, ex.errorCode)\n        }\n    }\n\n    @Test\n    fun registerUserAsync_invalidServerArgsThrows() {\n        val provider = app.emailPassword\n        looperThread.runBlocking {\n            provider.registerUserAsync(\"invalid-email\", \"1234\") { result ->\n                if (result.isSuccess) {\n                    fail()\n                } else {\n                    assertEquals(ErrorCode.BAD_REQUEST, result.error.errorCode)\n                    looperThread.testComplete()\n                }\n            }\n        }\n    }\n\n    @Test\n    fun registerUser_invalidArgumentsThrows() {\n        val provider: EmailPasswordAuth = app.emailPassword\n        assertFailsWith<IllegalArgumentException> { provider.registerUser(TestHelper.getNull(), \"123456\") }\n        assertFailsWith<IllegalArgumentException> { provider.registerUser(\"foo@bar.baz\", TestHelper.getNull()) }\n        looperThread.runBlocking {\n            provider.registerUserAsync(TestHelper.getNull(), \"123456\", checkNullArgCallback)\n        }\n        looperThread.runBlocking {\n            provider.registerUserAsync(\"foo@bar.baz\", TestHelper.getNull(), checkNullArgCallback)\n        }\n    }\n\n    @Ignore(\"Find a way to automate this\")\n    @Test\n    fun confirmUser() {\n        TODO(\"Figure out how to manually test this\")\n    }\n\n    @Ignore(\"Find a way to automate this\")\n    @Test\n    fun confirmUserAsync() {\n        TODO(\"Figure out how to manually test this\")\n    }\n\n    @Test\n    fun confirmUser_invalidServerArgsThrows() {\n        val provider = app.emailPassword\n        try {\n            provider.confirmUser(\"invalid-token\", \"invalid-token-id\")\n            fail()\n        } catch (ex: AppException) {\n            assertEquals(ErrorCode.BAD_REQUEST, ex.errorCode)\n        }\n    }\n\n    @Test\n    fun confirmUserAsync_invalidServerArgsThrows() {\n        val provider = app.emailPassword\n        looperThread.runBlocking {\n            provider.confirmUserAsync(\"invalid-email\", \"1234\") { result ->\n                if (result.isSuccess) {\n                    fail()\n                } else {\n                    assertEquals(ErrorCode.BAD_REQUEST, result.error.errorCode)\n                    looperThread.testComplete()\n                }\n            }\n        }\n    }\n\n    @Test\n    fun confirmUser_invalidArgumentsThrows() {\n        val provider: EmailPasswordAuth = app.emailPassword\n        assertFailsWith<IllegalArgumentException> { provider.confirmUser(TestHelper.getNull(), \"token-id\") }\n        assertFailsWith<IllegalArgumentException> { provider.confirmUser(\"token\", TestHelper.getNull()) }\n        looperThread.runBlocking {\n            provider.confirmUserAsync(TestHelper.getNull(), \"token-id\", checkNullArgCallback)\n        }\n        looperThread.runBlocking {\n            provider.confirmUserAsync(\"token\", TestHelper.getNull(), checkNullArgCallback)\n        }\n    }\n    @Test\n    fun sendResetPasswordEmail() {\n        val provider = app.emailPassword\n        val email: String = \"test@10gen.com\" // Must be a valid email, otherwise the server will fail\n        provider.registerUser(email, \"123456\")\n        provider.sendResetPasswordEmail(email)\n    }\n\n    @Test\n    fun sendResetPasswordEmailAsync() {\n        val provider = app.emailPassword\n        val email: String = \"test@10gen.com\" // Must be a valid email, otherwise the server will fail\n        provider.registerUser(email, \"123456\")\n        looperThread.runBlocking {\n            provider.sendResetPasswordEmailAsync(email) { result ->\n                when (result.isSuccess) {\n                    true -> looperThread.testComplete()\n                    false -> fail(result.error.toString())\n                }\n\n            }\n        }\n    }\n\n    @Test\n    fun sendResetPasswordEmail_invalidServerArgsThrows() {\n        val provider = app.emailPassword\n        try {\n            provider.sendResetPasswordEmail(\"unknown@10gen.com\")\n            fail()\n        } catch (error: AppException) {\n            assertEquals(ErrorCode.USER_NOT_FOUND, error.errorCode)\n        }\n    }\n\n    @Test\n    fun sendResetPasswordEmailAsync_invalidServerArgsThrows() {\n        val provider = app.emailPassword\n        looperThread.runBlocking {\n            provider.sendResetPasswordEmailAsync(\"unknown@10gen.com\") { result ->\n                if (result.isSuccess) {\n                    fail()\n                } else {\n                    assertEquals(ErrorCode.USER_NOT_FOUND, result.error.errorCode)\n                    looperThread.testComplete()\n                }\n            }\n        }\n    }\n\n    @Test\n    fun sendResetPasswordEmail_invalidArgumentsThrows() {\n        val provider = app.emailPassword\n        assertFailsWith<IllegalArgumentException> { provider.sendResetPasswordEmail(TestHelper.getNull()) }\n        looperThread.runBlocking {\n            provider.sendResetPasswordEmailAsync(TestHelper.getNull(), checkNullArgCallback)\n        }\n    }\n\n    @Test\n    fun callResetPasswordFunction() {\n        val provider = app.emailPassword\n        admin.setResetFunction(enabled = true)\n        val email = TestHelper.getRandomEmail()\n        provider.registerUser(email, \"123456\")\n        try {\n            provider.callResetPasswordFunction(email, \"new-password\", \"say-the-magic-word\", 42)\n            val user = app.login(Credentials.emailPassword(email, \"new-password\"))\n            user.logOut()\n        } finally {\n            admin.setResetFunction(enabled = false)\n        }\n    }\n\n    @Test\n    fun callResetPasswordFunctionAsync() {\n        val provider = app.emailPassword\n        admin.setResetFunction(enabled = true)\n        val email = TestHelper.getRandomEmail()\n        provider.registerUser(email, \"123456\")\n        try {\n            looperThread.runBlocking {\n                provider.callResetPasswordFunctionAsync(email,\n                    \"new-password\",\n                    arrayOf(\"say-the-magic-word\", 42)) { result ->\n                    if (result.isSuccess) {\n                        val user = app.login(Credentials.emailPassword(email, \"new-password\"))\n                        user.logOut()\n                        looperThread.testComplete()\n                    } else {\n                        fail(result.error.toString())\n                    }\n                }\n            }\n        } finally {\n            admin.setResetFunction(enabled = false)\n        }\n    }\n\n    @Test\n    fun callResetPasswordFunction_invalidServerArgsThrows() {\n        val provider = app.emailPassword\n        admin.setResetFunction(enabled = true)\n        val email = TestHelper.getRandomEmail()\n        provider.registerUser(email, \"123456\")\n        try {\n            provider.callResetPasswordFunction(email, \"new-password\", \"wrong-magic-word\")\n        } catch (error: AppException) {\n            assertEquals(ErrorCode.APP_UNKNOWN, error.errorCode)\n        } finally {\n            admin.setResetFunction(enabled = false)\n        }\n    }\n\n    @Test\n    fun callResetPasswordFunctionAsync_invalidServerArgsThrows() {\n        val provider = app.emailPassword\n        admin.setResetFunction(enabled = true)\n        val email = TestHelper.getRandomEmail()\n        provider.registerUser(email, \"123456\")\n        try {\n            looperThread.runBlocking {\n                provider.callResetPasswordFunctionAsync(\n                    email,\n                    \"new-password\",\n                    arrayOf(\"wrong-magic-word\")) { result ->\n                    if (result.isSuccess) {\n                        fail()\n                    } else {\n                        assertEquals(ErrorCode.APP_UNKNOWN, result.error.errorCode)\n                        looperThread.testComplete()\n                    }\n                }\n            }\n        } finally {\n            admin.setResetFunction(enabled = false)\n        }\n    }\n\n    @Test\n    fun callResetPasswordFunction_invalidArgumentsThrows() {\n        val provider = app.emailPassword\n        assertFailsWith<IllegalArgumentException> { provider.callResetPasswordFunction(TestHelper.getNull(), \"password\") }\n        assertFailsWith<IllegalArgumentException> { provider.callResetPasswordFunction(\"foo@bar.baz\", TestHelper.getNull()) }\n        looperThread.runBlocking {\n            provider.callResetPasswordFunctionAsync(TestHelper.getNull(), \"new-password\", arrayOf(), checkNullArgCallback)\n        }\n        looperThread.runBlocking {\n            provider.callResetPasswordFunctionAsync(\"foo@bar.baz\", TestHelper.getNull(), arrayOf(), checkNullArgCallback)\n        }\n    }\n\n    @Ignore(\"Find a way to automate this\")\n    @Test\n    fun resetPassword() {\n        TODO(\"How to test this manually?\")\n    }\n\n    @Ignore(\"Find a way to automate this\")\n    @Test\n    fun resetPasswordAsync() {\n        TODO(\"How to test this manually?\")\n    }\n\n    @Test\n    fun resetPassword_invalidServerArgsThrows() {\n        val provider = app.emailPassword\n        try {\n            provider.resetPassword(\"invalid-token\", \"invalid-token-id\", \"new-password\")\n        } catch (error: AppException) {\n            assertEquals(ErrorCode.BAD_REQUEST, error.errorCode)\n        }\n    }\n\n    @Test\n    fun resetPasswordASync_invalidServerArgsThrows() {\n        val provider = app.emailPassword\n        looperThread.runBlocking {\n            provider.resetPasswordAsync(\"invalid-token\", \"invalid-token-id\", \"new-password\") { result ->\n                if (result.isSuccess) {\n                    fail()\n                } else {\n                    assertEquals(ErrorCode.BAD_REQUEST, result.error.errorCode)\n                    looperThread.testComplete()\n                }\n            }\n        }\n    }\n\n    @Test\n    fun resetPassword_invalidArgumentsThrows() {\n        val provider = app.emailPassword\n        assertFailsWith<IllegalArgumentException> { provider.resetPassword(TestHelper.getNull(), \"token-id\", \"password\") }\n        assertFailsWith<IllegalArgumentException> { provider.resetPassword(\"token\", TestHelper.getNull(), \"password\") }\n        assertFailsWith<IllegalArgumentException> { provider.resetPassword(\"token\", \"token-id\", TestHelper.getNull()) }\n        looperThread.runBlocking {\n            provider.resetPasswordAsync(TestHelper.getNull(), \"token-id\", \"password\", checkNullArgCallback)\n        }\n        looperThread.runBlocking {\n            provider.resetPasswordAsync(\"token\", TestHelper.getNull(), \"password\", checkNullArgCallback)\n        }\n        looperThread.runBlocking {\n            provider.resetPasswordAsync(\"token\", \"token-id\", TestHelper.getNull(), checkNullArgCallback)\n        }\n    }\n\n    @Test\n    @UiThreadTest\n    fun callMethodsOnMainThreadThrows() {\n        val provider: EmailPasswordAuth = app.emailPassword\n        val email: String = TestHelper.getRandomEmail()\n        for (method in Method.values()) {\n            try {\n                when (method) {\n                    Method.REGISTER_USER -> provider.registerUser(email, \"123456\")\n                    Method.CONFIRM_USER -> provider.confirmUser(\"token\", \"tokenId\")\n                    Method.RESEND_CONFIRMATION_EMAIL -> provider.resendConfirmationEmail(email)\n                    Method.SEND_RESET_PASSWORD_EMAIL -> provider.sendResetPasswordEmail(email)\n                    Method.CALL_RESET_PASSWORD_FUNCTION -> provider.callResetPasswordFunction(email, \"123456\")\n                    Method.RETRY_CUSTOM_CONFIRMATION -> provider.retryCustomConfirmation(email)\n                    Method.RESET_PASSWORD -> provider.resetPassword(\"token\", \"token-id\", \"password\")\n                }\n                fail(\"$method should have thrown an exception\")\n            } catch (error: AppException) {\n                assertEquals(ErrorCode.NETWORK_UNKNOWN, error.errorCode)\n            }\n        }\n    }\n\n    @Test\n    fun callAsyncMethodsOnNonLooperThreadThrows() {\n        val provider: EmailPasswordAuth = app.emailPassword\n        val email: String = TestHelper.getRandomEmail()\n        val callback = App.Callback<Void> { fail() }\n        for (method in Method.values()) {\n            try {\n                when (method) {\n                    Method.REGISTER_USER -> provider.registerUserAsync(email, \"123456\", callback)\n                    Method.CONFIRM_USER -> provider.confirmUserAsync(\"token\", \"tokenId\", callback)\n                    Method.RESEND_CONFIRMATION_EMAIL -> provider.resendConfirmationEmailAsync(email, callback)\n                    Method.SEND_RESET_PASSWORD_EMAIL -> provider.sendResetPasswordEmailAsync(email, callback)\n                    Method.CALL_RESET_PASSWORD_FUNCTION -> provider.callResetPasswordFunctionAsync(email, \"123456\", arrayOf(), callback)\n                    Method.RETRY_CUSTOM_CONFIRMATION -> provider.retryCustomConfirmationAsync(email, callback)\n                    Method.RESET_PASSWORD -> provider.resetPasswordAsync(\"token\", \"token-id\", \"password\", callback)\n                }\n                fail(\"$method should have thrown an exception\")\n            } catch (ignore: IllegalStateException) {\n            }\n        }\n    }\n}\n\n@RunWith(AndroidJUnit4::class)\nclass EmailPasswordAuthWithEmailConfirmTests: EmailPasswordAuthTests() {\n    @Before\n    fun setUp() {\n        Realm.init(InstrumentationRegistry.getInstrumentation().targetContext)\n        app = TestApp(appName = TEST_APP_2)\n        RealmLog.setLevel(LogLevel.DEBUG)\n        admin = ServerAdmin(app)\n        admin.deleteAllUsers()\n    }\n\n    @After\n    fun tearDown() {\n        app.close()\n        RealmLog.setLevel(LogLevel.WARN)\n    }\n\n    @Test\n    fun resendConfirmationEmail() {\n        // We only test that the server successfully accepts the request. We have no way of knowing\n        // if the Email was actually sent.\n        // TODO: Figure out a way to check if this actually happened. Perhaps a custom SMTP server?\n        val email = \"test@10gen.com\"\n        val provider = app.emailPassword\n        provider.registerUser(email, \"123456\")\n        provider.resendConfirmationEmail(email)\n    }\n\n    @Test\n    fun resendConfirmationEmailAsync() {\n        // We only test that the server successfully accepts the request. We have no way of knowing\n        // if the Email was actually sent.\n        val email = \"test@10gen.com\"\n        looperThread.runBlocking {\n            val provider = app.emailPassword\n            provider.registerUser(email, \"123456\")\n            provider.resendConfirmationEmailAsync(email) { result ->\n                when (result.isSuccess) {\n                    true -> looperThread.testComplete()\n                    false -> fail(result.error.toString())\n                }\n            }\n        }\n    }\n\n    @Test\n    fun resendConfirmationEmail_invalidServerArgsThrows() {\n        val email = \"test@10gen.com\"\n        val provider = app.emailPassword\n        provider.registerUser(email, \"123456\")\n        try {\n            provider.resendConfirmationEmail(\"foo\")\n            fail()\n        } catch (error: AppException) {\n            assertEquals(ErrorCode.USER_NOT_FOUND, error.errorCode)\n        }\n    }\n\n    @Test\n    fun resendConfirmationEmailAsync_invalidServerArgsThrows() {\n        val email = \"test@10gen.com\"\n        val provider = app.emailPassword\n        provider.registerUser(email, \"123456\")\n        looperThread.runBlocking {\n            provider.resendConfirmationEmailAsync(\"foo\") { result ->\n                if (result.isSuccess) {\n                    fail()\n                } else {\n                    assertEquals(ErrorCode.USER_NOT_FOUND, result.error.errorCode)\n                    looperThread.testComplete()\n                }\n            }\n        }\n    }\n\n    @Test\n    fun resendConfirmationEmail_invalidArgumentsThrows() {\n        val provider: EmailPasswordAuth = app.emailPassword\n        assertFailsWith<IllegalArgumentException> { provider.resendConfirmationEmail(TestHelper.getNull()) }\n        looperThread.runBlocking {\n            provider.resendConfirmationEmailAsync(TestHelper.getNull(), checkNullArgCallback)\n        }\n    }\n}\n\n@RunWith(AndroidJUnit4::class)\nclass EmailPasswordAuthWithCustomFunctionConfirmTests: EmailPasswordAuthTests() {\n    @Before\n    fun setUp() {\n        Realm.init(InstrumentationRegistry.getInstrumentation().targetContext)\n        app = TestApp(appName = TEST_APP_3)\n        RealmLog.setLevel(LogLevel.DEBUG)\n        admin = ServerAdmin(app)\n        admin.deleteAllUsers()\n    }\n\n    @After\n    fun tearDown() {\n        app.close()\n        RealmLog.setLevel(LogLevel.WARN)\n    }\n\n    @Test\n    fun retryCustomConfirmation() {\n        val email = \"test_realm_pending_${Random.nextLong()}@10gen.com\"\n        val provider = app.emailPassword\n        provider.registerUser(email, \"123456\")\n        provider.retryCustomConfirmation(email)\n    }\n\n    @Test\n    fun retryCustomConfirmation_failConfirmation() {\n        // Only emails containing realm_tests_do_autoverify or @10gen.com will be confirmed\n        val email = \"test_only_realm_pending_${Random.nextLong()}@mongodb.com\"\n        val provider = app.emailPassword\n        provider.registerUser(email, \"123456\")\n        val exception = assertFailsWith<AppException> {\n            provider.retryCustomConfirmation(email)\n        }\n        assertContains(exception.errorMessage!!, \"failed to confirm user \\\"$email\\\"\")\n    }\n\n    @Test\n    fun retryCustomConfirmationAsync() {\n        // First call to register will move any email with `realm_pending` into `Pending`. Next\n        // call will register it.\n        val email = \"test_realm_pending_${Random.nextLong()}@10gen.com\"\n        looperThread.runBlocking {\n            val provider = app.emailPassword\n            provider.registerUser(email, \"123456\")\n            provider.retryCustomConfirmationAsync(email) { result ->\n                when (result.isSuccess) {\n                    true -> looperThread.testComplete()\n                    false -> fail(result.error.toString())\n                }\n            }\n        }\n    }\n\n    @Test\n    fun retryCustomConfirmation_invalidServerArgsThrows() {\n        val email = \"test_${Random.nextLong()}@10gen.com\"\n        val provider = app.emailPassword\n        provider.registerUser(email, \"123456\")\n        try {\n            provider.retryCustomConfirmation(\"foo\")\n            fail()\n        } catch (error: AppException) {\n            assertEquals(ErrorCode.USER_NOT_FOUND, error.errorCode)\n        }\n    }\n\n    @Test\n    fun retryCustomConfirmationAsync_invalidServerArgsThrows() {\n        val email = \"test_${Random.nextLong()}@10gen.com\"\n        val provider = app.emailPassword\n        provider.registerUser(email, \"123456\")\n        looperThread.runBlocking {\n            provider.retryCustomConfirmationAsync(\"foo\") { result ->\n                if (result.isSuccess) {\n                    fail()\n                } else {\n                    assertEquals(ErrorCode.USER_NOT_FOUND, result.error.errorCode)\n                    looperThread.testComplete()\n                }\n            }\n        }\n    }\n\n    @Test\n    fun retryCustomConfirmation_invalidArgumentsThrows() {\n        val provider: EmailPasswordAuth = app.emailPassword\n        assertFailsWith<IllegalArgumentException> { provider.retryCustomConfirmation(TestHelper.getNull()) }\n        looperThread.runBlocking {\n            provider.retryCustomConfirmationAsync(TestHelper.getNull(), checkNullArgCallback)\n        }\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTestObjectServer/kotlin/io/realm/FunctionsTests.kt",
    "content": "/*\n * Copyright 2020 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\npackage io.realm\n\nimport androidx.test.ext.junit.runners.AndroidJUnit4\nimport androidx.test.platform.app.InstrumentationRegistry\nimport io.realm.admin.ServerAdmin\nimport io.realm.mongodb.*\nimport io.realm.mongodb.functions.Functions\nimport io.realm.rule.BlockingLooperThread\nimport io.realm.util.assertFailsWithErrorCode\nimport org.bson.*\nimport org.bson.codecs.*\nimport org.bson.codecs.configuration.CodecConfigurationException\nimport org.bson.codecs.configuration.CodecProvider\nimport org.bson.codecs.configuration.CodecRegistries\nimport org.bson.codecs.configuration.CodecRegistry\nimport org.bson.codecs.pojo.PojoCodecProvider\nimport org.bson.types.Decimal128\nimport org.bson.types.ObjectId\nimport org.junit.After\nimport org.junit.Assert.fail\nimport org.junit.Before\nimport org.junit.Ignore\nimport org.junit.Test\nimport org.junit.runner.RunWith\nimport java.lang.RuntimeException\nimport java.util.*\nimport kotlin.test.assertEquals\nimport kotlin.test.assertFailsWith\nimport kotlin.test.assertNotNull\nimport kotlin.test.assertTrue\n\n@RunWith(AndroidJUnit4::class)\nclass FunctionsTests {\n\n    companion object {\n        const val FIRST_ARG_FUNCTION = \"firstArg\"\n    }\n\n    // Pojo class for testing custom encoder/decoder\n    private data class Dog(var name: String? = null)\n\n    private val looperThread = BlockingLooperThread()\n\n    private lateinit var app: TestApp\n    private lateinit var functions: Functions\n\n    private lateinit var anonUser: User\n    private lateinit var admin: ServerAdmin\n\n    // Custom registry with support for encoding/decoding Dogs\n    private val pojoRegistry by lazy {\n        CodecRegistries.fromRegistries(\n                app.configuration.defaultCodecRegistry,\n                CodecRegistries.fromProviders(\n                        PojoCodecProvider.builder()\n                                .register(Dog::class.java)\n                                .build()\n                )\n        )\n    }\n\n    // Custom string decoder returning hardcoded value\n    private class CustomStringDecoder(val value: String) : Decoder<String> {\n        override fun decode(reader: BsonReader, decoderContext: DecoderContext): String {\n            reader.readString()\n            return value\n        }\n    }\n\n    // Custom codec that throws an exception when encoding/decoding integers\n    private val faultyIntegerCodec = object : Codec<Integer> {\n        override fun decode(reader: BsonReader, decoderContext: DecoderContext): Integer {\n            throw RuntimeException(\"Simulated error\")\n        }\n\n        override fun getEncoderClass(): Class<Integer> {\n            return Integer::class.java\n        }\n\n        override fun encode(writer: BsonWriter?, value: Integer?, encoderContext: EncoderContext?) {\n            throw RuntimeException(\"Simulated error\")\n        }\n    }\n\n    // Custom registry that throws an exception when encoding/decoding integers\n    private val faultyIntegerRegistry = CodecRegistries.fromRegistries(\n            CodecRegistries.fromProviders(IterableCodecProvider()),\n            CodecRegistries.fromCodecs(StringCodec(), faultyIntegerCodec)\n    )\n\n    @Before\n    fun setup() {\n        Realm.init(InstrumentationRegistry.getInstrumentation().targetContext)\n        app = TestApp()\n        admin = ServerAdmin(app)\n        anonUser = app.login(Credentials.anonymous())\n        functions = anonUser.functions\n    }\n\n    @After\n    fun teardown() {\n        if (this::app.isInitialized) {\n            app.close()\n        }\n    }\n\n    // Tests\n    // - Default codec factory\n    @Test\n    fun jniRoundTripForDefaultCodecRegistry() {\n        val i32 = 42\n        val i64 = 42L\n\n        for (type in BsonType.values()) {\n            when (type) {\n                BsonType.DOUBLE -> {\n                    assertEquals(1.4f, functions.callFunction(FIRST_ARG_FUNCTION, listOf(1.4f), java.lang.Float::class.java).toFloat())\n                    assertEquals(1.4, functions.callFunction(FIRST_ARG_FUNCTION, listOf(1.4), java.lang.Double::class.java).toDouble())\n                    assertTypeOfFirstArgFunction(BsonDouble(1.4), BsonDouble::class.java)\n                }\n                BsonType.STRING -> {\n                    assertTypeOfFirstArgFunction(\"Realm\", String::class.java)\n                    assertTypeOfFirstArgFunction(BsonString(\"Realm\"), BsonString::class.java)\n                }\n                BsonType.ARRAY -> {\n                    val values1 = listOf<Any>(true, i32, i64)\n                    assertEquals(values1[0], functions.callFunction(FIRST_ARG_FUNCTION, values1, java.lang.Boolean::class.java))\n\n                    // Previously failing in C++ parsing\n                    val values2 = listOf(1, true, 3)\n                    assertEquals(values2, functions.callFunction(FIRST_ARG_FUNCTION, listOf(values2), List::class.java))\n                    val values3 = listOf(2, \"Realm\", 3)\n                    assertEquals(values3, functions.callFunction(FIRST_ARG_FUNCTION, listOf(values3), List::class.java))\n                }\n                BsonType.BINARY -> {\n                    val value = byteArrayOf(1, 2, 3)\n                    val actual = functions.callFunction(FIRST_ARG_FUNCTION, listOf(value), ByteArray::class.java)\n                    assertEquals(value.toList(), actual.toList())\n                    assertTypeOfFirstArgFunction(BsonBinary(byteArrayOf(1, 2, 3)), BsonBinary::class.java)\n                }\n                BsonType.OBJECT_ID -> {\n                    assertTypeOfFirstArgFunction(ObjectId(), ObjectId::class.java)\n                    assertTypeOfFirstArgFunction(BsonObjectId(ObjectId()), BsonObjectId::class.java)\n                }\n                BsonType.BOOLEAN -> {\n                    assertTrue(functions.callFunction(FIRST_ARG_FUNCTION, listOf(true), java.lang.Boolean::class.java).booleanValue())\n                    assertTypeOfFirstArgFunction(BsonBoolean(true), BsonBoolean::class.java)\n                }\n                BsonType.INT32 -> {\n                    assertEquals(32, functions.callFunction(FIRST_ARG_FUNCTION, listOf(32), Integer::class.java).toInt())\n                    assertEquals(32, functions.callFunction(FIRST_ARG_FUNCTION, listOf(32L), Integer::class.java).toInt())\n                    assertTypeOfFirstArgFunction(BsonInt32(32), BsonInt32::class.java)\n                }\n                BsonType.INT64 -> {\n                    assertEquals(32L, functions.callFunction(FIRST_ARG_FUNCTION, listOf(32L), java.lang.Long::class.java).toLong())\n                    assertEquals(32L, functions.callFunction(FIRST_ARG_FUNCTION, listOf(32), java.lang.Long::class.java).toLong())\n                    assertTypeOfFirstArgFunction(BsonInt64(32), BsonInt64::class.java)\n                }\n                BsonType.DECIMAL128 -> {\n                    assertTypeOfFirstArgFunction(Decimal128(32L), Decimal128::class.java)\n                    assertTypeOfFirstArgFunction(BsonDecimal128(Decimal128(32L)), BsonDecimal128::class.java)\n                }\n                BsonType.DOCUMENT -> {\n                    val map = mapOf(\"foo\" to 5)\n                    val document = Document(map)\n                    assertEquals(map, functions.callFunction(FIRST_ARG_FUNCTION, listOf(map), Map::class.java))\n                    assertEquals(map, functions.callFunction(FIRST_ARG_FUNCTION, listOf(document), Map::class.java))\n                    assertEquals(document, functions.callFunction(FIRST_ARG_FUNCTION, listOf(map), Document::class.java))\n                    assertEquals(document, functions.callFunction(FIRST_ARG_FUNCTION, listOf(document), Document::class.java))\n\n                    // Previously failing in C++ parser\n                    var documents = listOf(Document(), Document())\n                    assertEquals(documents[0], functions.callFunction(FIRST_ARG_FUNCTION, documents, Document::class.java))\n                    documents = listOf(Document(\"KEY\", \"VALUE\"), Document(\"KEY\", \"VALUE\"), Document(\"KEY\", \"VALUE\"))\n                    assertEquals(documents[0], functions.callFunction(FIRST_ARG_FUNCTION, documents, Document::class.java))\n                }\n                BsonType.DATE_TIME -> {\n                    val now = Date(System.currentTimeMillis())\n                    assertEquals(now, functions.callFunction(FIRST_ARG_FUNCTION, listOf(now), Date::class.java))\n                }\n                BsonType.UNDEFINED,\n                BsonType.NULL,\n                BsonType.REGULAR_EXPRESSION,\n                BsonType.SYMBOL,\n                BsonType.DB_POINTER,\n                BsonType.JAVASCRIPT,\n                BsonType.JAVASCRIPT_WITH_SCOPE,\n                BsonType.TIMESTAMP,\n                BsonType.END_OF_DOCUMENT,\n                BsonType.MIN_KEY,\n                BsonType.MAX_KEY -> {\n                    // Relying on org.bson codec providers for conversion, so skipping explicit\n                    // tests for these more exotic types\n                }\n                else -> {\n                    fail()\n                }\n            }\n        }\n    }\n\n    private fun <T : Any> assertTypeOfFirstArgFunction(value: T, returnClass: Class<T>): T {\n        val actual = functions.callFunction(FIRST_ARG_FUNCTION, listOf(value), returnClass)\n        assertEquals(value, actual)\n        return actual\n    }\n\n    @Test\n    fun asyncCallFunction() = looperThread.runBlocking {\n        functions.callFunctionAsync(FIRST_ARG_FUNCTION, listOf(32), Integer::class.java) { result ->\n            try {\n                assertEquals(32, result.orThrow.toInt())\n            } finally {\n                looperThread.testComplete()\n            }\n        }\n    }\n\n\n    @Test\n    fun codecArgumentFailure() {\n        assertFailsWithErrorCode(ErrorCode.BSON_CODEC_NOT_FOUND) {\n            functions.callFunction(FIRST_ARG_FUNCTION, listOf(Dog(\"PojoFido\")), Dog::class.java)\n        }\n    }\n\n    @Test\n    fun asyncCodecArgumentFailure() = looperThread.runBlocking {\n        functions.callFunctionAsync(FIRST_ARG_FUNCTION, listOf(Dog(\"PojoFido\")), Integer::class.java) { result ->\n            try {\n                assertEquals(ErrorCode.BSON_CODEC_NOT_FOUND, result.error.errorCode)\n                assertTrue(result.error.exception is CodecConfigurationException)\n            } finally {\n                looperThread.testComplete()\n            }\n        }\n    }\n\n    @Test\n    fun codecResponseFailure() {\n        assertFailsWithErrorCode(ErrorCode.BSON_CODEC_NOT_FOUND) {\n            functions.callFunction(FIRST_ARG_FUNCTION, listOf(32), Dog::class.java)\n        }\n    }\n\n    @Test\n    fun asyncCodecResponseFailure() = looperThread.runBlocking {\n        functions.callFunctionAsync(FIRST_ARG_FUNCTION, listOf(Dog(\"PojoFido\")), Integer::class.java) { result ->\n            try {\n                assertEquals(ErrorCode.BSON_CODEC_NOT_FOUND, result.error.errorCode)\n                assertTrue(result.error.exception is CodecConfigurationException)\n            } finally {\n                looperThread.testComplete()\n            }\n        }\n    }\n\n    @Test\n    fun codecBsonEncodingFailure() {\n        assertFailsWithErrorCode(ErrorCode.BSON_ENCODING) {\n            functions.callFunction(FIRST_ARG_FUNCTION, listOf(32), String::class.java, faultyIntegerRegistry)\n        }\n    }\n\n    @Test\n    fun asyncCodecBsonEncodingFailure() = looperThread.runBlocking {\n        functions.callFunctionAsync(FIRST_ARG_FUNCTION, listOf(32), String::class.java, faultyIntegerRegistry) { result ->\n            try {\n                assertEquals(ErrorCode.BSON_ENCODING, result.error.errorCode)\n            } finally {\n                looperThread.testComplete()\n            }\n        }\n    }\n\n    @Test\n    fun codecBsonDecodingFailure() {\n        assertFailsWithErrorCode(ErrorCode.BSON_DECODING) {\n            functions.callFunction(FIRST_ARG_FUNCTION, listOf(32), String::class.java)\n        }\n    }\n\n    @Test\n    fun asyncCodecBsonDecodingFailure() = looperThread.runBlocking {\n        functions.callFunctionAsync(FIRST_ARG_FUNCTION, listOf(32), String::class.java) { result ->\n            try {\n                assertEquals(ErrorCode.BSON_DECODING, result.error.errorCode)\n                assertTrue(result.error.exception is BSONException)\n            } finally {\n                looperThread.testComplete()\n            }\n        }\n    }\n\n    @Test\n    fun localCodecRegistry() {\n        val input = Dog(\"PojoFido\")\n        assertEquals(input, functions.callFunction(FIRST_ARG_FUNCTION, listOf(input), Dog::class.java, pojoRegistry))\n    }\n\n    @Test\n    fun asyncLocalCodecRegistry() = looperThread.runBlocking {\n        val input = Dog(\"PojoFido\")\n        functions.callFunctionAsync(FIRST_ARG_FUNCTION, listOf(input), Dog::class.java, pojoRegistry) { result ->\n            try {\n                assertEquals(input, result.orThrow)\n            } finally {\n                looperThread.testComplete()\n            }\n        }\n    }\n\n    @Test\n    fun instanceCodecRegistry() {\n        val input = Dog(\"PojoFido\")\n        val functionsWithCodecRegistry = anonUser.getFunctions(pojoRegistry)\n        assertEquals(input, functionsWithCodecRegistry.callFunction(FIRST_ARG_FUNCTION, listOf(input), Dog::class.java))\n    }\n\n    @Test\n    fun resultDecoder() {\n        val input = \"Realm\"\n        val output = \"Custom Realm\"\n        assertEquals(output, functions.callFunction(FIRST_ARG_FUNCTION, listOf(input), CustomStringDecoder(output)))\n    }\n\n    @Test\n    fun asyncResultDecoder() = looperThread.runBlocking {\n        val input = \"Realm\"\n        val output = \"Custom Realm\"\n        functions.callFunctionAsync(FIRST_ARG_FUNCTION, listOf(input), CustomStringDecoder(output), App.Callback<String> { result ->\n            try {\n                assertEquals(output, result.orThrow)\n            } finally {\n                looperThread.testComplete()\n            }\n        })\n    }\n\n    @Test\n    fun unknownFunction() {\n        assertFailsWithErrorCode(ErrorCode.FUNCTION_NOT_FOUND) {\n            functions.callFunction(\"unknown\", listOf(32), String::class.java)\n        }\n    }\n\n    @Test\n    fun asyncUnknownFunction() = looperThread.runBlocking {\n        val input = Dog(\"PojoFido\")\n        functions.callFunctionAsync(\"unknown\", listOf(input), Dog::class.java, pojoRegistry) { result ->\n            try {\n                assertEquals(ErrorCode.FUNCTION_NOT_FOUND, result.error.errorCode)\n            } finally {\n                looperThread.testComplete()\n            }\n        }\n    }\n\n    @Test\n    fun asyncNonLoopers() {\n        assertFailsWith<IllegalStateException> {\n            functions.callFunctionAsync(FIRST_ARG_FUNCTION, listOf(32), Integer::class.java, pojoRegistry) { result ->\n                fail()\n            }\n        }\n    }\n\n    @Test\n    fun callFunction_sum() {\n        val numbers = listOf(1, 2, 3, 4)\n        assertEquals(10, functions.callFunction(\"sum\", numbers, Integer::class.java).toInt())\n    }\n\n    @Test\n    fun callFunction_remoteError() {\n        assertFailsWithErrorCode(ErrorCode.FUNCTION_EXECUTION_ERROR) {\n            functions.callFunction(\"error\", emptyList<Any>(), String::class.java)\n        }\n    }\n\n    @Test\n    fun callFunction_null() {\n        assertTrue(functions.callFunction(\"null\", emptyList<Any>(), BsonNull::class.java).isNull)\n    }\n\n    @Test\n    fun callFunction_void() {\n        assertEquals(BsonType.UNDEFINED, functions.callFunction(\"void\", emptyList<Any>(), BsonUndefined::class.java).bsonType)\n    }\n\n    @Test\n    fun callFunction_afterLogout() {\n        anonUser.logOut()\n        assertFailsWithErrorCode(ErrorCode.APP_UNKNOWN) {\n            functions.callFunction(FIRST_ARG_FUNCTION, listOf(1, 2, 3), Integer::class.java)\n        }\n    }\n\n    // Tests that functions that should not execute based on \"canevalute\"-expression fails.\n    @Test\n    fun callFunction_authorizedOnly() {\n        // Not allow for anonymous user\n        assertFailsWithErrorCode(ErrorCode.FUNCTION_EXECUTION_ERROR) {\n            functions.callFunction(\"authorizedOnly\", listOf(1, 2, 3), Document::class.java)\n        }\n        // User email must match \"canevaluate\" section of servers \"functions/authorizedOnly/config.json\"\n        val authorizedUser = app.registerUserAndLogin(\"authorizeduser@example.org\", \"asdfasdf\")\n        assertNotNull(authorizedUser.functions.callFunction(\"authorizedOnly\", listOf(1, 2, 3), Document::class.java))\n    }\n\n    @Test\n    fun getApp() {\n        assertEquals(app, functions.app)\n    }\n\n    @Test\n    fun getUser() {\n        assertEquals(anonUser, functions.user)\n    }\n\n    @Test\n    fun defaultCodecRegistry() {\n        // TODO Maybe we should test that setting configuration specific would propagate all the way\n        //  to here, but we do not have infrastructure to easily override TestApp configuration,\n        //  and actual configuration is verified in AppConfigurationTests\n        assertEquals(app.configuration.defaultCodecRegistry, functions.defaultCodecRegistry)\n    }\n\n    @Test\n    fun customCodecRegistry() {\n        val configCodecRegistry = CodecRegistries.fromCodecs(StringCodec())\n        val customCodecRegistryFunctions = anonUser.getFunctions(configCodecRegistry)\n        assertEquals(configCodecRegistry, customCodecRegistryFunctions.defaultCodecRegistry)\n    }\n\n    @Test\n    fun illegalBsonArgument() {\n        // Coded that will generate non-BsonArray from list\n        val faultyListCodec = object : Codec<Iterable<*>> {\n            override fun getEncoderClass(): Class<Iterable<*>> {\n                return Iterable::class.java\n            }\n\n            override fun encode(writer: BsonWriter, value: Iterable<*>, encoderContext: EncoderContext) {\n                writer.writeString(\"Not an array\")\n            }\n\n            override fun decode(reader: BsonReader?, decoderContext: DecoderContext?): ArrayList<*> {\n                TODO(\"Not yet implemented\")\n            }\n        }\n        // Codec registry that will use the above faulty codec for lists\n        val faultyCodecRegistry = CodecRegistries.fromProviders(\n                object : CodecProvider {\n                    override fun <T : Any> get(clazz: Class<T>?, registry: CodecRegistry?): Codec<T> {\n                        @Suppress(\"UNCHECKED_CAST\")\n                        return faultyListCodec as Codec<T>\n                    }\n                }\n        )\n        assertFailsWith<IllegalArgumentException> {\n            functions.callFunction(FIRST_ARG_FUNCTION, listOf(\"Realm\"), String::class.java, faultyCodecRegistry)\n        }\n    }\n\n    // Test cases previously failing due to C++ parsing\n    @Test\n    fun roundtrip_arrayOfBinary() {\n        val value = byteArrayOf(1, 2, 3)\n        val listOf = listOf(value)\n        val actual = functions.callFunction(FIRST_ARG_FUNCTION, listOf, ByteArray::class.java)\n        assertEquals(value.toList(), actual.toList())\n    }\n\n    @Test\n    fun roundtrip_arrayOfDocuments() {\n        val map = mapOf(\"foo\" to 5, \"bar\" to 7)\n        assertEquals(map, functions.callFunction(FIRST_ARG_FUNCTION, listOf(map), Map::class.java))\n    }\n\n    @Test\n    @Ignore(\"C++ parser does not support binary subtypes yet\")\n    fun roundtrip_binaryUuid() {\n        // arg      = \"{\"value\": {\"$binary\": {\"base64\": \"JmS8oQitTny4IPS2tyjmdA==\", \"subType\": \"04\"}}}\"\n        // response = \"{\"value\":{\"$binary\":{\"base64\":\"JmS8oQitTny4IPS2tyjmdA==\",\"subType\":\"00\"}}}\"\n        assertTypeOfFirstArgFunction(BsonBinary(UUID.randomUUID()), BsonBinary::class.java)\n    }\n\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTestObjectServer/kotlin/io/realm/ProgressListenerTests.kt",
    "content": "/*\n * Copyright 2020 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 */\npackage io.realm\n\nimport androidx.test.ext.junit.runners.AndroidJUnit4\nimport androidx.test.platform.app.InstrumentationRegistry\nimport io.realm.entities.DefaultSyncSchema\nimport io.realm.entities.SyncDog\nimport io.realm.entities.SyncStringOnly\nimport io.realm.internal.OsRealmConfig\nimport io.realm.kotlin.syncSession\nimport io.realm.kotlin.where\nimport io.realm.log.LogLevel\nimport io.realm.log.RealmLog\nimport io.realm.mongodb.User\nimport io.realm.mongodb.close\nimport io.realm.mongodb.registerUserAndLogin\nimport io.realm.mongodb.sync.Progress\nimport io.realm.mongodb.sync.ProgressListener\nimport io.realm.mongodb.sync.ProgressMode\nimport io.realm.mongodb.sync.SyncConfiguration\nimport io.realm.mongodb.sync.SyncSession\nimport io.realm.mongodb.sync.testRealmExists\nimport io.realm.mongodb.sync.testSchema\nimport io.realm.mongodb.sync.testSessionStopPolicy\nimport io.realm.rule.BlockingLooperThread\nimport org.bson.types.ObjectId\nimport org.junit.After\nimport org.junit.Assert.assertEquals\nimport org.junit.Assert.assertFalse\nimport org.junit.Assert.assertTrue\nimport org.junit.Assert.fail\nimport org.junit.Before\nimport org.junit.Test\nimport org.junit.runner.RunWith\nimport java.util.*\nimport java.util.concurrent.CountDownLatch\nimport java.util.concurrent.TimeUnit\nimport java.util.concurrent.atomic.AtomicBoolean\nimport java.util.concurrent.atomic.AtomicInteger\nimport kotlin.test.assertFailsWith\n\n@RunWith(AndroidJUnit4::class)\nclass ProgressListenerTests {\n\n    companion object {\n        private const val TEST_SIZE: Long = 10\n    }\n\n    private val looperThread = BlockingLooperThread()\n    private val configurationFactory = TestSyncConfigurationFactory()\n\n    private lateinit var app: TestApp\n    private lateinit var partitionValue: String\n\n    @Before\n    fun setUp() {\n        Realm.init(InstrumentationRegistry.getInstrumentation().targetContext)\n        RealmLog.setLevel(LogLevel.TRACE)\n        partitionValue = UUID.randomUUID().toString()\n        app = TestApp()\n    }\n\n    @After\n    fun tearDown() {\n        if (this::app.isInitialized) {\n            app.close()\n        }\n        RealmLog.setLevel(LogLevel.WARN)\n    }\n\n    @Test\n    fun downloadProgressListener_changesOnly() {\n        val allChangesDownloaded = CountDownLatch(1)\n        val user1: User = app.registerUserAndLogin(TestHelper.getRandomEmail(), \"123456\")\n        val user1Config = createSyncConfig(user1)\n        createRemoteData(user1Config)\n        val user2: User = app.registerUserAndLogin(TestHelper.getRandomEmail(), \"123456\")\n        val user2Config = createSyncConfig(user2)\n        Realm.getInstance(user2Config).use { realm ->\n            realm.syncSession.addDownloadProgressListener(ProgressMode.CURRENT_CHANGES) { progress ->\n                if (progress.isTransferComplete) {\n                    assertTransferComplete(progress, true)\n                    assertEquals(TEST_SIZE, getStoreTestDataSize(user2Config))\n                    allChangesDownloaded.countDown()\n                }\n            }\n            TestHelper.awaitOrFail(allChangesDownloaded)\n        }\n    }\n\n    @Test\n    fun downloadProgressListener_indefinitely() {\n        val transferCompleted = AtomicInteger(0)\n        val allChangesDownloaded = CountDownLatch(1)\n        val startWorker = CountDownLatch(1)\n        val user1: User = app.registerUserAndLogin(TestHelper.getRandomEmail(), \"123456\") // login(Credentials.anonymous())\n        val user1Config: SyncConfiguration = createSyncConfig(user1)\n\n        // Create worker thread that puts data into another Realm.\n        // This is to avoid blocking one progress listener while waiting for another to complete.\n        val worker = Thread(Runnable {\n            TestHelper.awaitOrFail(startWorker)\n            createRemoteData(user1Config)\n        })\n        worker.start()\n        val user2: User = app.registerUserAndLogin(TestHelper.getRandomEmail(), \"123456\") // login(Credentials.anonymous())\n        val user2Config: SyncConfiguration = createSyncConfig(user2)\n        Realm.getInstance(user2Config).use { user2Realm ->\n            val session: SyncSession = user2Realm.syncSession\n            session.addDownloadProgressListener(ProgressMode.INDEFINITELY) { progress ->\n                val objectCounts = getStoreTestDataSize(user2Config)\n                // The downloading progress listener could be triggered at the db version where only contains the meta\n                // data. So we start checking from when the first 10 objects downloaded.\n                RealmLog.warn(String.format(\n                        Locale.ENGLISH, \"downloadProgressListener_indefinitely download %d/%d objects count:%d\",\n                        progress.transferredBytes, progress.transferableBytes, objectCounts))\n                if (objectCounts != 0L && progress.isTransferComplete) {\n                    when (transferCompleted.incrementAndGet()) {\n                        1 -> {\n                            assertEquals(TEST_SIZE, objectCounts)\n                            assertTransferComplete(progress, true)\n                            startWorker.countDown()\n                        }\n                        2 -> {\n                            assertTransferComplete(progress, true)\n                            assertEquals(TEST_SIZE * 2, objectCounts)\n                            allChangesDownloaded.countDown()\n                        }\n                        else -> fail(\"Transfer complete called too many times:\" + transferCompleted.get())\n                    }\n                }\n            }\n            writeSampleData(user2Realm) // Write first batch of sample data\n            TestHelper.awaitOrFail(allChangesDownloaded)\n        }\n        // worker thread will hang if logout happens before listener triggered.\n        worker.join()\n        user1.logOut()\n        user2.logOut()\n    }\n\n    // Make sure that a ProgressListener continues to report the correct thing, even if it crashed\n    @Test\n    fun uploadListener_worksEvenIfCrashed() {\n        val transferCompleted = AtomicInteger(0)\n        val testDone = CountDownLatch(1)\n        val config = createSyncConfig()\n        Realm.getInstance(config).use { realm ->\n            val session: SyncSession = realm.syncSession\n            session.addUploadProgressListener(ProgressMode.INDEFINITELY) { progress ->\n                if (progress.isTransferComplete) {\n                    when (transferCompleted.incrementAndGet()) {\n                        1 -> {\n                            Realm.getInstance(config).use { realm ->\n                            writeSampleData(realm)\n                            }\n                            throw RuntimeException(\"Crashing the changelistener\")\n                        }\n                        2 -> {\n                            assertTransferComplete(progress, true)\n                            testDone.countDown()\n                        }\n                        else -> fail(\"Unsupported number of transfers completed: \" + transferCompleted.get())\n                    }\n                }\n            }\n            writeSampleData(realm) // Write first batch of sample data\n            TestHelper.awaitOrFail(testDone)\n        }\n    }\n\n    @Test\n    fun uploadProgressListener_changesOnly() {\n        val allChangeUploaded = CountDownLatch(1)\n        val config = createSyncConfig()\n        Realm.getInstance(config).use { realm ->\n            val session: SyncSession = realm.syncSession\n            assertEquals(SyncSession.State.ACTIVE, session.state)\n            writeSampleData(realm)\n            session.addUploadProgressListener(ProgressMode.CURRENT_CHANGES) { progress ->\n                if (progress.isTransferComplete) {\n                    assertTransferComplete(progress, true)\n                    allChangeUploaded.countDown()\n                }\n            }\n            TestHelper.awaitOrFail(allChangeUploaded)\n        }\n    }\n\n    @Test\n    fun uploadProgressListener_indefinitely() {\n        val transferCompleted = AtomicInteger(0)\n        val testDone = CountDownLatch(1)\n        val config = createSyncConfig()\n        Realm.getInstance(config).use { realm ->\n            val session: SyncSession = realm.syncSession\n            session.addUploadProgressListener(ProgressMode.INDEFINITELY) { progress ->\n                if (progress.isTransferComplete) {\n                    when (transferCompleted.incrementAndGet()) {\n                        1 -> {\n                            Realm.getInstance(config).use { realm ->\n                                writeSampleData(realm)\n                            }\n                        }\n                        2 -> {\n                            assertTransferComplete(progress, true)\n                            testDone.countDown()\n                        }\n                        else -> fail(\"Unsupported number of transfers completed: \" + transferCompleted.get())\n                    }\n                }\n            }\n            writeSampleData(realm) // Write first batch of sample data\n            TestHelper.awaitOrFail(testDone)\n        }\n    }\n\n    @Test\n    fun addListenerInsideCallback() {\n        val allChangeUploaded = CountDownLatch(1)\n        val config = createSyncConfig()\n        Realm.getInstance(config).use { realm ->\n            val session: SyncSession = realm.syncSession\n            writeSampleData(realm)\n            session.addUploadProgressListener(ProgressMode.CURRENT_CHANGES) { progress ->\n                if (progress.isTransferComplete) {\n                    Realm.getInstance(config).use { realm ->\n                        writeSampleData(realm)\n                    }\n                    session.addUploadProgressListener(ProgressMode.CURRENT_CHANGES) { progress ->\n                        if (progress.isTransferComplete) {\n                            allChangeUploaded.countDown()\n                        }\n                    }\n                }\n            }\n            TestHelper.awaitOrFail(allChangeUploaded)\n        }\n    }\n\n    @Test\n    fun addListenerInsideCallback_mixProgressModes() {\n        val allChangeUploaded = CountDownLatch(3)\n        val progressCompletedReported = AtomicBoolean(false)\n        val config = createSyncConfig()\n        Realm.getInstance(config).use { realm ->\n            val session: SyncSession = realm.syncSession\n            session.addUploadProgressListener(ProgressMode.INDEFINITELY) { progress ->\n                if (progress.isTransferComplete) {\n                    allChangeUploaded.countDown()\n                    if (progressCompletedReported.compareAndSet(false, true)) {\n                        Realm.getInstance(config).use { realm ->\n                            writeSampleData(realm)\n                        }\n                        session.addUploadProgressListener(ProgressMode.CURRENT_CHANGES) { progress ->\n                            if (progress.isTransferComplete) {\n                                allChangeUploaded.countDown()\n                            }\n                        }\n                    }\n                }\n            }\n            writeSampleData(realm)\n            TestHelper.awaitOrFail(allChangeUploaded)\n        }\n    }\n\n    @Test\n    fun addProgressListener_triggerImmediatelyWhenRegistered() {\n        val config = createSyncConfig()\n        Realm.getInstance(config).use { realm ->\n            val session: SyncSession = realm.syncSession\n            checkDownloadListener(session, ProgressMode.INDEFINITELY)\n            checkUploadListener(session, ProgressMode.INDEFINITELY)\n            checkDownloadListener(session, ProgressMode.CURRENT_CHANGES)\n            checkUploadListener(session, ProgressMode.CURRENT_CHANGES)\n        }\n    }\n\n    @Test\n    fun addProgressListener_triggerImmediatelyWhenRegistered_waitForInitialRemoteData() {\n        val user = app.registerUserAndLogin(TestHelper.getRandomEmail(), \"123456\")\n        val config = SyncConfiguration.Builder(user, getTestPartitionValue())\n                .waitForInitialRemoteData()\n                .modules(DefaultSyncSchema())\n                .build()\n        Realm.getInstance(config).use { realm ->\n            val session: SyncSession = realm.syncSession\n            checkDownloadListener(session, ProgressMode.INDEFINITELY)\n            checkUploadListener(session, ProgressMode.INDEFINITELY)\n            checkDownloadListener(session, ProgressMode.CURRENT_CHANGES)\n            checkUploadListener(session, ProgressMode.CURRENT_CHANGES)\n        }\n    }\n\n    @Test\n    fun progressListenersWorkWhenUsingWaitForInitialRemoteData() = looperThread.runBlocking {\n        val username = UUID.randomUUID().toString()\n        val password = \"password\"\n        var user: User = app.registerUserAndLogin(username, password)\n\n        // 1. Copy a valid Realm to the server (and pray it does it within 10 seconds)\n        val configOld: SyncConfiguration = configurationFactory.createSyncConfigurationBuilder(user, user.id)\n                .testSchema(SyncStringOnly::class.java)\n                .testSessionStopPolicy(OsRealmConfig.SyncSessionStopPolicy.IMMEDIATELY)\n                .build()\n        Realm.getInstance(configOld).use { realm ->\n            realm.executeTransaction { realm ->\n                for (i in 0..9) {\n                    realm.createObject(SyncStringOnly::class.java, ObjectId()).chars = \"Foo$i\"\n                }\n            }\n            realm.syncSession.uploadAllLocalChanges()\n        }\n        user.logOut()\n\n        assertFailsWith<IllegalStateException> {\n            app.sync.getSession(configOld)\n        }\n\n        // 2. Local state should now be completely reset. Open the same sync Realm but different local name again with\n        // a new configuration which should download the uploaded changes (pray it managed to do so within the time frame).\n        // Use different user to trigger different path\n        val user2 = app.registerUserAndLogin(TestHelper.getRandomEmail(), password)\n        val config: SyncConfiguration = configurationFactory.createSyncConfigurationBuilder(user2, user.id)\n                .testSchema(SyncStringOnly::class.java)\n                .waitForInitialRemoteData()\n                .build()\n\n        assertFalse(config.testRealmExists())\n\n        val countDownLatch = CountDownLatch(2)\n\n        val indefiniteListenerComplete = AtomicBoolean(false)\n        val currentChangesListenerComplete = AtomicBoolean(false)\n        val task = Realm.getInstanceAsync(config, object : Realm.Callback() {\n            override fun onSuccess(realm: Realm) {\n                realm.syncSession.addDownloadProgressListener(ProgressMode.INDEFINITELY, object : ProgressListener {\n                    override fun onChange(progress: Progress) {\n                        if (progress.isTransferComplete()) {\n                            indefiniteListenerComplete.set(true)\n                            countDownLatch.countDown()\n                        }\n                    }\n                })\n                realm.syncSession.addDownloadProgressListener(ProgressMode.CURRENT_CHANGES, object : ProgressListener {\n                    override fun onChange(progress: Progress) {\n                        if (progress.isTransferComplete()) {\n                            currentChangesListenerComplete.set(true)\n                            countDownLatch.countDown()\n                        }\n                    }\n                })\n                countDownLatch.await(100, TimeUnit.SECONDS)\n                realm.close()\n                if (!indefiniteListenerComplete.get()) {\n                    fail(\"Indefinite progress listener did not report complete.\")\n                }\n                if (!currentChangesListenerComplete.get()) {\n                    fail(\"Current changes progress listener did not report complete.\")\n                }\n                looperThread.testComplete()\n            }\n\n            override fun onError(exception: Throwable) {\n                fail(exception.toString())\n            }\n        })\n        looperThread.keepStrongReference(task)\n    }\n\n    @Test\n    fun uploadListener_keepIncreasingInSize() {\n        val config = createSyncConfig()\n        Realm.getInstance(config).use { realm ->\n            val session: SyncSession = realm.syncSession\n            for (i in 0..9) {\n                val changesUploaded = CountDownLatch(1)\n                writeSampleData(realm)\n                session.addUploadProgressListener(ProgressMode.CURRENT_CHANGES) { progress ->\n                    if (progress.isTransferComplete) {\n                        assertTransferComplete(progress, true)\n                        changesUploaded.countDown()\n                    }\n                }\n                TestHelper.awaitOrFail(changesUploaded)\n            }\n        }\n    }\n\n    private fun checkDownloadListener(session: SyncSession, progressMode: ProgressMode) {\n        val listenerCalled = CountDownLatch(1)\n        session.addDownloadProgressListener(progressMode) { progress ->\n            listenerCalled.countDown()\n        }\n        TestHelper.awaitOrFail(listenerCalled, 30)\n    }\n    private fun checkUploadListener(session: SyncSession, progressMode: ProgressMode) {\n        val listenerCalled = CountDownLatch(1)\n        session.addUploadProgressListener(progressMode) { progress ->\n            listenerCalled.countDown()\n        }\n        TestHelper.awaitOrFail(listenerCalled, 30)\n    }\n\n\n    private fun writeSampleData(realm: Realm, partitionValue: String = getTestPartitionValue()) {\n        realm.executeTransaction {\n            for (i in 0 until TEST_SIZE) {\n                val obj = SyncDog()\n                obj.name = \"Object $i\"\n                realm.insert(obj)\n            }\n        }\n    }\n\n    private fun assertTransferComplete(progress: Progress, nonZeroChange: Boolean) {\n        assertTrue(progress.isTransferComplete)\n        assertEquals(1.0, progress.fractionTransferred, 0.0)\n        assertEquals(progress.transferableBytes, progress.transferredBytes)\n        if (nonZeroChange) {\n            assertTrue(progress.transferredBytes > 0)\n        }\n    }\n\n    // Create remote data for a given user.\n    private fun createRemoteData(config: SyncConfiguration) {\n        Realm.getInstance(config).use { realm ->\n            val changesUploaded = CountDownLatch(1)\n            val session: SyncSession = realm.syncSession\n            writeSampleData(realm)\n            session.addUploadProgressListener(ProgressMode.CURRENT_CHANGES, object : ProgressListener {\n                override fun onChange(progress: Progress) {\n                    if (progress.isTransferComplete) {\n                        session.removeProgressListener(this)\n                        changesUploaded.countDown()\n                    }\n                }\n            })\n            TestHelper.awaitOrFail(changesUploaded)\n        }\n    }\n\n    private fun getStoreTestDataSize(config: RealmConfiguration): Long {\n        Realm.getInstance(config).use { realm ->\n            return realm.where<SyncDog>().count()\n        }\n    }\n\n    private fun createSyncConfig(user: User = app.registerUserAndLogin(TestHelper.getRandomEmail(), \"123456\"), partitionValue: String = getTestPartitionValue()): SyncConfiguration {\n        return SyncConfiguration.Builder(user, partitionValue)\n                .modules(DefaultSyncSchema())\n                .build()\n    }\n\n    private fun getTestPartitionValue(): String {\n        if (!this::partitionValue.isInitialized) {\n            fail(\"Test not setup correctly. Partition value is missing\");\n        }\n        return partitionValue\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTestObjectServer/kotlin/io/realm/SchemaTests.kt",
    "content": "/*\n * Copyright 2016 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 */\npackage io.realm\n\nimport androidx.test.ext.junit.runners.AndroidJUnit4\nimport io.realm.entities.SyncStringOnly\nimport io.realm.mongodb.SyncTestUtils.Companion.createTestUser\nimport io.realm.mongodb.close\nimport io.realm.mongodb.registerUserAndLogin\nimport io.realm.mongodb.sync.SyncConfiguration\nimport io.realm.mongodb.sync.testSchema\nimport io.realm.util.assertFailsWith\nimport junit.framework.Assert.*\nimport junit.framework.TestCase\nimport org.bson.types.ObjectId\nimport org.junit.After\nimport org.junit.Before\nimport org.junit.Rule\nimport org.junit.Test\nimport org.junit.rules.ErrorCollector\nimport org.junit.runner.RunWith\nimport kotlin.test.assertTrue\n\n@RunWith(AndroidJUnit4::class)\nclass SchemaTests {\n    @get:Rule\n    val configFactory = TestSyncConfigurationFactory()\n\n    @get:Rule\n    val errorCollector = ErrorCollector()\n\n    private lateinit var config: SyncConfiguration\n    private lateinit var app: TestApp\n\n    @Before\n    fun setUp() {\n        app = TestApp()\n        val user =  app.registerUserAndLogin(TestHelper.getRandomEmail(), \"123456\")\n        config = configFactory\n                .createSyncConfigurationBuilder(user)\n                .testSchema(SyncStringOnly::class.java)\n                .build()\n    }\n\n    @After\n    fun tearDown() {\n        if (this::app.isInitialized) {\n            app.close()\n        }\n    }\n\n    @Test\n    fun instance() {\n        val realm = Realm.getInstance(config)\n        realm.use {\n            TestCase.assertFalse(realm.isClosed)\n        }\n        assertTrue(realm.isClosed)\n    }\n\n    @Test\n    fun createObject() {\n        Realm.getInstance(config).use { realm ->\n            realm.executeTransaction {\n                assertTrue(realm.schema.contains(SyncStringOnly.CLASS_NAME))\n                val stringOnly = realm.createObject(SyncStringOnly::class.java, ObjectId())\n            }\n            assertEquals(1, realm.where(SyncStringOnly::class.java).count())\n        }\n    }\n\n    @Test\n    fun allow_createClass() {\n        DynamicRealm.getInstance(config).use { realm ->\n            val className = \"Dogplace\"\n            realm.executeTransaction {\n                realm.schema.create(className)\n            }\n            assertTrue(realm.schema.contains(className))\n        }\n    }\n\n    @Test\n    fun allow_addField() {\n        // Init schema\n        Realm.getInstance(config).close()\n        DynamicRealm.getInstance(config).use { realm ->\n            val objectSchema = realm.schema[SyncStringOnly.CLASS_NAME]!!\n            assertNotNull(objectSchema)\n            realm.executeTransaction {\n                objectSchema.addField(\"foo\", String::class.java)\n                assertTrue(objectSchema.hasField(\"foo\"))\n            }\n            assertTrue(objectSchema.hasField(\"foo\"))\n        }\n    }\n\n    // Special column \"__OID\" should be hidden from users.\n    @Test\n    fun fieldNames_stableIdColumnShouldBeHidden() {\n        Realm.getInstance(config).use { realm ->\n            val objectSchema = realm.schema[SyncStringOnly.CLASS_NAME]!!\n            assertNotNull(objectSchema)\n            val names = objectSchema.fieldNames\n            assertEquals(2, names.size)\n\n            val iter = names.iterator()\n            assertEquals(SyncStringOnly.FIELD_ID, iter.next())\n            assertEquals(SyncStringOnly.FIELD_CHARS, iter.next())\n        }\n    }\n\n    enum class DestructiveSchemaOperation {\n        REMOVE_CLASS,\n        RENAME_CLASS,\n        SET_CLASS_NAME,\n        REMOVE_FIELD,\n        RENAME_FIELD,\n        REMOVE_INDEX,\n        REMOVE_PRIMARY_KEY,\n        ADD_PRIMARY_KEY,\n        ADD_FIELD_PRIMARY_KEY,\n    }\n\n    @Test\n    fun disallowDestructiveUpdateOfSyncedDynamicRealm() {\n        for (operation in DestructiveSchemaOperation.values()) {\n            // Init schema\n            Realm.getInstance(config).close()\n            val className = SyncStringOnly.CLASS_NAME\n            val newClassName = \"Dogplace\"\n            val fieldName = SyncStringOnly.FIELD_CHARS\n            val newFieldName = \"newchars\"\n\n            DynamicRealm.getInstance(config).use { realm ->\n                assertTrue(realm.schema.contains(className))\n                val objectSchema = realm.schema[className]!!\n                assertNotNull(objectSchema)\n                assertTrue(objectSchema.hasField(fieldName))\n\n                realm.beginTransaction()\n                errorCollector.assertFailsWith<UnsupportedOperationException> {\n                    when (operation) {\n                        DestructiveSchemaOperation.REMOVE_CLASS ->\n                            realm.schema.remove(className)\n                        DestructiveSchemaOperation.RENAME_CLASS ->\n                            realm.schema.rename(className, newClassName)\n                        DestructiveSchemaOperation.SET_CLASS_NAME ->\n                            objectSchema.setClassName(newClassName)\n                        DestructiveSchemaOperation.REMOVE_FIELD ->\n                            objectSchema.removeField(fieldName)\n                        DestructiveSchemaOperation.RENAME_FIELD ->\n                            objectSchema.renameField(fieldName, newFieldName)\n                        DestructiveSchemaOperation.REMOVE_INDEX ->\n                            objectSchema.removeIndex(fieldName)\n                        DestructiveSchemaOperation.REMOVE_PRIMARY_KEY ->\n                            objectSchema.removePrimaryKey()\n                        DestructiveSchemaOperation.ADD_PRIMARY_KEY ->\n                            objectSchema.addPrimaryKey(fieldName)\n                        DestructiveSchemaOperation.ADD_FIELD_PRIMARY_KEY -> {\n                            objectSchema.addField(newFieldName, String::class.java, FieldAttribute.PRIMARY_KEY)\n                        }\n                        else -> fail()\n                    }\n                }\n                // Verify that operation is actually not performed in the transaction\n                assertTrue(realm.schema.contains(className))\n                assertFalse(realm.schema.contains(newClassName))\n                assertTrue(objectSchema.hasField(fieldName))\n\n                realm.cancelTransaction()\n\n                // Verify that operation is actually not performed after cancelling\n                assertTrue(realm.schema.contains(className))\n                assertFalse(realm.schema.contains(newClassName))\n                assertTrue(objectSchema.hasField(fieldName))\n                assertFalse(objectSchema.hasField(newFieldName))\n                assertNotNull(objectSchema)\n            }\n        }\n    }\n\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTestObjectServer/kotlin/io/realm/SyncedRealmMigrationTests.kt",
    "content": "/*\n * Copyright 2020 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 */\npackage io.realm\n\nimport androidx.test.ext.junit.runners.AndroidJUnit4\nimport io.realm.entities.IndexedFields\nimport io.realm.entities.PrimaryKeyAsString\nimport io.realm.entities.StringOnly\nimport io.realm.entities.SyncStringOnly\nimport io.realm.internal.OsObjectSchemaInfo\nimport io.realm.internal.OsRealmConfig\nimport io.realm.internal.OsSchemaInfo\nimport io.realm.internal.OsSharedRealm\nimport io.realm.mongodb.close\nimport io.realm.mongodb.registerUserAndLogin\nimport io.realm.mongodb.sync.testSchema\nimport io.realm.util.assertFailsWithMessage\nimport org.bson.types.ObjectId\nimport org.hamcrest.CoreMatchers\nimport org.junit.After\nimport org.junit.Assert.*\nimport org.junit.Before\nimport org.junit.Rule\nimport org.junit.Test\nimport org.junit.runner.RunWith\nimport kotlin.test.assertFailsWith\n\n/**\n * Testing methods around migrations for Realms using a [SyncConfiguration].\n */\n@RunWith(AndroidJUnit4::class)\nclass SyncedRealmMigrationTests {\n\n    @get:Rule\n    val configFactory = TestSyncConfigurationFactory()\n\n    private lateinit var app: TestApp\n\n    @Before\n    fun setUp() {\n        app = TestApp()\n    }\n\n    @After\n    fun tearDown() {\n        if (this::app.isInitialized) {\n            app.close()\n        }\n    }\n\n    @Test\n    fun migrateRealm_syncConfigurationThrows() {\n        val config = configFactory.createSyncConfigurationBuilder(app.registerUserAndLogin()).build()\n        assertFailsWith<IllegalArgumentException> {\n            Realm.migrateRealm(config)\n        }\n    }\n\n    // Check that the Realm can still be opened even if the ondisk schema are missing fields. These will be added\n    // automatically.\n    @Test\n    fun addField_worksWithMigrationError() {\n        val config = configFactory.createSyncConfigurationBuilder(app.registerUserAndLogin())\n                .testSchema(SyncStringOnly::class.java)\n                .build()\n\n        // Setup initial Realm schema (with missing fields)\n        DynamicRealm.getInstance(config).use { dynamicRealm ->\n            val schema = dynamicRealm.schema\n            dynamicRealm.executeTransaction {\n                schema.createWithPrimaryKeyField(SyncStringOnly.CLASS_NAME, SyncStringOnly.FIELD_ID, ObjectId::class.java, FieldAttribute.REQUIRED) // Create empty class\n            }\n        }\n\n        // Open typed Realm, which will validate the schema\n        Realm.getInstance(config).use { realm ->\n            assertTrue(realm.schema[SyncStringOnly.CLASS_NAME]!!.hasField(StringOnly.FIELD_CHARS)) // Field has been added\n        }\n    }\n\n    // Check that the Realm can still be opened even if the ondisk schema has more fields than in the model class.\n    // The underlying field should not be deleted, just hidden.\n    @Test\n    fun missingFields_hiddenSilently() {\n        val config = configFactory.createSyncConfigurationBuilder(app.registerUserAndLogin())\n                .testSchema(SyncStringOnly::class.java)\n                .build()\n\n        // Setup initial Realm schema (with too many fields)\n        DynamicRealm.getInstance(config).use { dynamicRealm ->\n            val schema = dynamicRealm.schema\n            dynamicRealm.executeTransaction {\n                schema.createWithPrimaryKeyField(SyncStringOnly.CLASS_NAME, SyncStringOnly.FIELD_ID, ObjectId::class.java, FieldAttribute.REQUIRED)\n                        .addField(SyncStringOnly.FIELD_CHARS, String::class.java)\n                        .addField(\"newField\", String::class.java)\n                // A schema version has to be set otherwise Object Store will try to initialize the schema again and reach an\n                // error branch. That is not a real case.\n                dynamicRealm.version = 0\n            }\n        }\n\n        // Open typed Realm, which will validate the schema\n        Realm.getInstance(config).use { realm ->\n            val stringOnlySchema = realm.schema[SyncStringOnly.CLASS_NAME]!!\n            assertTrue(stringOnlySchema.hasField(SyncStringOnly.FIELD_CHARS))\n            assertTrue(stringOnlySchema.hasField(\"newField\"))\n            assertEquals(3, stringOnlySchema.fieldNames.size.toLong())\n        }\n    }\n\n    // Check that a Realm cannot be opened if it contain breaking schema changes, like changing a primary key\n    @Test\n    fun breakingSchemaChange_throws() {\n        val config = configFactory.createSyncConfigurationBuilder(app.registerUserAndLogin())\n                .testSchema(PrimaryKeyAsString::class.java)\n                .build()\n\n        // Setup initial Realm schema (with a different primary key)\n        val expectedObjectSchema = OsObjectSchemaInfo.Builder(PrimaryKeyAsString.CLASS_NAME, false, 2, 0)\n                .addPersistedProperty(\"\", PrimaryKeyAsString.FIELD_PRIMARY_KEY, RealmFieldType.STRING, false, true, false)\n                .addPersistedProperty(\"\", \"_id\", RealmFieldType.INTEGER, true, true, true)\n                .build()\n        val schemaInfo = OsSchemaInfo(listOf(expectedObjectSchema))\n        val configBuilder = OsRealmConfig.Builder(config).schemaInfo(schemaInfo)\n        OsSharedRealm.getInstance(configBuilder, OsSharedRealm.VersionID.LIVE).close()\n        assertFailsWithMessage<java.lang.IllegalStateException>(\n                CoreMatchers.containsString(\"Schema validation failed due to the following errors:\")\n        ) {\n            Realm.getInstance(config).close()\n        }\n    }\n\n    // Check that indexes are not being added if the schema version is the same\n    @Test\n    fun sameSchemaVersion_doNotRebuildIndexes() {\n        val config = configFactory.createSyncConfigurationBuilder(app.registerUserAndLogin())\n                .testSchema(IndexedFields::class.java)\n                .schemaVersion(42)\n                .build()\n\n        // Setup initial Realm schema (with no indexes)\n        DynamicRealm.getInstance(config).use { dynamicRealm ->\n            val schema = dynamicRealm.schema\n            dynamicRealm.executeTransaction {\n                schema.createWithPrimaryKeyField(IndexedFields.CLASS_NAME, IndexedFields.FIELD_PRIMARY_STRING, ObjectId::class.java)\n                        .addField(IndexedFields.FIELD_INDEXED_STRING, String::class.java) // No index\n                        .addField(IndexedFields.FIELD_NON_INDEXED_STRING, String::class.java)\n                dynamicRealm.version = 42\n            }\n        }\n\n        Realm.getInstance(config).use { realm ->\n            // Opening at same schema version (42) will not rebuild indexes\n            val indexedFieldsSchema = realm.schema[IndexedFields.CLASS_NAME]!!\n            assertFalse(indexedFieldsSchema.hasIndex(IndexedFields.FIELD_INDEXED_STRING))\n            assertFalse(indexedFieldsSchema.hasIndex(IndexedFields.FIELD_NON_INDEXED_STRING))\n        }\n    }\n\n    // Check that indexes are being added if the schema version is different\n    @Test\n    fun differentSchemaVersions_rebuildIndexes() {\n        val config = configFactory.createSyncConfigurationBuilder(app.registerUserAndLogin())\n                .testSchema(IndexedFields::class.java)\n                .schemaVersion(42)\n                .build()\n\n        // Setup initial Realm schema (with no indexes)\n        DynamicRealm.getInstance(config).use { dynamicRealm ->\n            val schema = dynamicRealm.schema\n            dynamicRealm.executeTransaction {\n                schema.createWithPrimaryKeyField(IndexedFields.CLASS_NAME, IndexedFields.FIELD_PRIMARY_STRING, ObjectId::class.java)\n                        .addField(IndexedFields.FIELD_INDEXED_STRING, String::class.java) // No index\n                        .addField(IndexedFields.FIELD_NON_INDEXED_STRING, String::class.java)\n                dynamicRealm.version = 43\n            }\n        }\n\n        Realm.getInstance(config).use { realm ->\n            // Opening at different schema version (42) should rebuild indexes\n            val indexedFieldsSchema = realm.schema[IndexedFields.CLASS_NAME]!!\n            assertNotNull(indexedFieldsSchema)\n            assertTrue(indexedFieldsSchema.hasIndex(IndexedFields.FIELD_INDEXED_STRING))\n            assertFalse(indexedFieldsSchema.hasIndex(IndexedFields.FIELD_NON_INDEXED_STRING))\n        }\n    }\n\n    // Check that indexes are being added if other fields are being added as well\n    @Test\n    fun addingFields_rebuildIndexes() {\n        val config = configFactory.createSyncConfigurationBuilder(app.registerUserAndLogin())\n                .testSchema(IndexedFields::class.java)\n                .schemaVersion(42)\n                .build()\n\n        // Setup initial Realm schema (with no indexes)\n        val className = IndexedFields::class.java.simpleName\n        DynamicRealm.getInstance(config).use { dynamicRealm ->\n            val schema = dynamicRealm.schema\n            dynamicRealm.executeTransaction {\n                schema.createWithPrimaryKeyField(className, IndexedFields.FIELD_PRIMARY_STRING, ObjectId::class.java)\n                        .addField(IndexedFields.FIELD_INDEXED_STRING, String::class.java) // No index\n                // .addField(IndexedFields.FIELD_NON_INDEXED_STRING, String.class); // Missing field\n                dynamicRealm.version = 41\n            }\n        }\n\n        // Opening at different schema version (42) should add field and rebuild indexes\n        Realm.getInstance(config).use { realm ->\n            val realmObjectSchema = realm.schema[className]!!\n            assertTrue(realmObjectSchema.hasField(IndexedFields.FIELD_NON_INDEXED_STRING))\n            assertTrue(realmObjectSchema.hasIndex(IndexedFields.FIELD_INDEXED_STRING))\n        }\n    }\n\n    @Test\n    fun schemaVersionUpgradedWhenMigrating() {\n        val config = configFactory.createSyncConfigurationBuilder(app.registerUserAndLogin())\n                .testSchema(SyncStringOnly::class.java)\n                .schemaVersion(42)\n                .build()\n\n        // Setup initial Realm schema (with missing fields)\n        DynamicRealm.getInstance(config).use { dynamicRealm ->\n            val schema = dynamicRealm.schema\n            dynamicRealm.executeTransaction {\n                schema.createWithPrimaryKeyField(SyncStringOnly.CLASS_NAME, SyncStringOnly.FIELD_ID, ObjectId::class.java, FieldAttribute.REQUIRED) // Create empty class\n                dynamicRealm.version = 1\n            }\n        }\n\n        // Open typed Realm, which will validate the schema\n        Realm.getInstance(config).use { realm ->\n            assertEquals(42, realm.version)\n        }\n    }\n\n    // The remote Realm containing more field than the local typed Realm defined is allowed.\n    @Test\n    fun moreFieldsThanExpectedIsAllowed() {\n        val config = configFactory\n                .createSyncConfigurationBuilder(app.registerUserAndLogin())\n                .testSchema(SyncStringOnly::class.java)\n                .build()\n\n        // Initialize schema\n        Realm.getInstance(config).close()\n        DynamicRealm.getInstance(config).use { dynamicRealm ->\n            dynamicRealm.executeTransaction {\n                val objectSchema = dynamicRealm.schema[SyncStringOnly.CLASS_NAME]!!\n                // Add one extra field which doesn't exist in the typed Realm.\n                objectSchema.addField(\"oneMoreField\", Integer::class.java)\n            }\n            // Column keys cache are cleared when closing\n        }\n\n        // Verify schema again.\n        Realm.getInstance(config).close()\n    }\n\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTestObjectServer/kotlin/io/realm/UserProfileInfoTests.kt",
    "content": "/*\n * Copyright 2020 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 */\npackage io.realm\n\nimport androidx.test.ext.junit.runners.AndroidJUnit4\nimport androidx.test.platform.app.InstrumentationRegistry\nimport io.realm.internal.network.OkHttpNetworkTransport\nimport io.realm.internal.objectstore.OsJavaNetworkTransport\nimport io.realm.mongodb.*\nimport org.junit.After\nimport org.junit.Assert.assertEquals\nimport org.junit.Assert.fail\nimport org.junit.Before\nimport org.junit.Test\nimport org.junit.runner.RunWith\nimport kotlin.test.assertNull\n\n@RunWith(AndroidJUnit4::class)\nclass UserProfileTests {\n    companion object {\n        const val ACCESS_TOKEN = \"\"\"eyJhbGciOiJSUzI1NiIsImtpZCI6IjVlNjk2M2RmYWZlYTYzMjU0NTgxYzAyNiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1ODM5NjcyMDgsImlhdCI6MTU4Mzk2NTQwOCwiaXNzIjoiNWU2OTY0ZTBhZmVhNjMyNTQ1ODFjMWEzIiwic3RpdGNoX2RldklkIjoiMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwIiwic3RpdGNoX2RvbWFpbklkIjoiNWU2OTYzZGVhZmVhNjMyNTQ1ODFjMDI1Iiwic3ViIjoiNWU2OTY0ZTBhZmVhNjMyNTQ1ODFjMWExIiwidHlwIjoiYWNjZXNzIn0.J4mp8LnlsxTQRV_7W2Er4qY0tptR76PJGG1k6HSMmUYqgfpJC2Fnbcf1VCoebzoNolH2-sr8AHDVBBCyjxRjqoY9OudFHmWZKmhDV1ysxPP4XmID0nUuN45qJSO8QEAqoOmP1crXjrUZWedFw8aaCZE-bxYfvcDHyjBcbNKZqzawwUw2PyTOlrNjgs01k2J4o5a5XzYkEsJuzr4_8UqKW6zXvYj24UtqnqoYatW5EzpX63m2qig8AcBwPK4ZHb5wEEUdf4QZxkRY5QmTgRHP8SSqVUB_mkHgKaizC_tSB3E0BekaDfLyWVC1taAstXJNfzgFtLI86AzuXS2dCiCfqQ\"\"\"\n        const val REFRESH_TOKEN = \"\"\"eyJhbGciOiJSUzI1NiIsImtpZCI6IjVlNjk2M2RmYWZlYTYzMjU0NTgxYzAyNiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1ODkxNDk0MDgsImlhdCI6MTU4Mzk2NTQwOCwic3RpdGNoX2RhdGEiOm51bGwsInN0aXRjaF9kZXZJZCI6IjAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMCIsInN0aXRjaF9kb21haW5JZCI6IjVlNjk2M2RlYWZlYTYzMjU0NTgxYzAyNSIsInN0aXRjaF9pZCI6IjVlNjk2NGUwYWZlYTYzMjU0NTgxYzFhMyIsInN0aXRjaF9pZGVudCI6eyJpZCI6IjVlNjk2NGUwYWZlYTYzMjU0NTgxYzFhMC1oaWF2b3ZkbmJxbGNsYXBwYnl1cmJpaW8iLCJwcm92aWRlcl90eXBlIjoiYW5vbi11c2VyIiwicHJvdmlkZXJfaWQiOiI1ZTY5NjNlMGFmZWE2MzI1NDU4MWMwNGEifSwic3ViIjoiNWU2OTY0ZTBhZmVhNjMyNTQ1ODFjMWExIiwidHlwIjoicmVmcmVzaCJ9.FhLdpmL48Mw0SyUKWuaplz3wfeS8TCO8S7I9pIJenQww9nPqQ7lIvykQxjCCtinGvsZIJKt_7R31xYCq4Jp53Nw81By79IwkXtO7VXHPsXXZG5_2xV-s0u44e85sYD5su_H-xnx03sU2piJbWJLSB8dKu3rMD4mO-S0HNXCCAty-JkYKSaM2-d_nS8MNb6k7Vfm7y69iz_uwHc-bb_1rPg7r827K6DEeEMF41Hy3Nx1kCdAUOM9-6nYv3pZSU1PFrGYi2uyTXPJ7R7HigY5IGHWd0hwONb_NUr4An2omqfvlkLEd77ut4V9m6mExFkoKzRz7shzn-IGkh3e4h7ECGA\"\"\"\n        const val USER_ID = \"5e6964e0afea63254581c1a1\"\n        const val DEVICE_ID = \"000000000000000000000000\"\n        const val NAME = \"NAME\"\n        const val EMAIL = \"unique_user@domain.com\"\n        const val PICTURE_URL = \"PICTURE_URL\"\n        const val FIRST_NAME = \"FIRST_NAME\"\n        const val LAST_NAME = \"LAST_NAME\"\n        const val GENDER = \"GENDER\"\n        const val BIRTHDAY = \"BIRTHDAY\"\n        const val MIN_AGE = 1L\n        const val MAX_AGE = 99L\n    }\n\n    private lateinit var app: App\n    lateinit var profileBody: String\n\n    private fun setDefaultProfile() {\n        profileBody = \"\"\"\n                            {\n                                \"name\": \"$NAME\",\n                                \"email\": \"$EMAIL\",\n                                \"picture_url\": \"$PICTURE_URL\",\n                                \"first_name\": \"$FIRST_NAME\",\n                                \"last_name\": \"$LAST_NAME\",\n                                \"gender\": \"$GENDER\",\n                                \"birthday\": \"$BIRTHDAY\",\n                                \"min_age\": \"$MIN_AGE\",\n                                \"max_age\": \"$MAX_AGE\"\n                            }\n        \"\"\".trimIndent()\n    }\n\n    private fun setNullProfile() {\n        profileBody = \"\"\"\n                            {\n\n                            }\n        \"\"\".trimIndent()\n    }\n\n    @Before\n    fun setUp() {\n        Realm.init(InstrumentationRegistry.getInstrumentation().targetContext)\n\n        setDefaultProfile();\n\n        app = TestApp(object : OsJavaNetworkTransport() {\n            override fun sendRequestAsync(method: String, url: String, timeoutMs: Long, headers: MutableMap<String, String>, body: String, completionBlockPtr: Long) {\n                val response = executeRequest(method, url, timeoutMs, headers, body)\n                handleResponse(response, completionBlockPtr)\n            }\n\n            override fun executeRequest(\n                method: String,\n                url: String,\n                timeoutMs: Long,\n                headers: MutableMap<String, String>,\n                body: String\n            ): Response {\n                var result = \"\"\n                when {\n                    url.endsWith(\"/providers/${Credentials.Provider.EMAIL_PASSWORD.id}/login\") -> {\n                        result = \"\"\"\n                                    {\n                                        \"access_token\": \"$ACCESS_TOKEN\",\n                                        \"refresh_token\": \"$REFRESH_TOKEN\",\n                                        \"user_id\": \"$USER_ID\",\n                                        \"device_id\": \"$DEVICE_ID\"\n                                    }            \n                                \"\"\".trimIndent()\n                    }\n                    url.endsWith(\"/auth/profile\") -> {\n                        result = \"\"\"\n                                    {\n                                        \"user_id\": \"5e6964e0afea63254581c1a1\",\n                                        \"domain_id\": \"000000000000000000000000\",\n                                        \"identities\": [\n                                            {\n                                                \"id\": \"5e68f51ade5ba998bb17500d\",\n                                                \"provider_type\": \"local-userpass\",\n                                                \"provider_id\": \"000000000000000000000003\",\n                                                \"provider_data\": {\n                                                    \"email\": \"unique_user@domain.com\"\n                                                }\n                                            }\n                                        ],\n                                        \"data\": $profileBody,\n                                        \"type\": \"normal\",\n                                        \"roles\": [\n                                            {\n                                                \"role_name\": \"GROUP_OWNER\",\n                                                \"group_id\": \"5e68f51e087b1b33a53f56d5\"\n                                            }\n                                        ]\n                                    }\n                                \"\"\".trimIndent()\n                    }\n                    url.endsWith(\"/location\") -> {\n                        result = \"\"\"\n                                    { \"deployment_model\" : \"GLOBAL\",\n                                      \"location\": \"US-VA\", \n                                      \"hostname\": \"http://localhost:9090\",\n                                      \"ws_hostname\": \"ws://localhost:9090\"\n                                    }\n                                    \"\"\".trimIndent()\n                    }\n                    url.endsWith(\"/providers/${Credentials.Provider.EMAIL_PASSWORD.id}/register\") -> {\n                        result = \"\"\n                    }\n                    else -> {\n                        fail(\"Unexpected request url: $url\")\n                    }\n                }\n                return OkHttpNetworkTransport.Response.httpResponse(200, mapOf(Pair(\"Content-Type\", \"application/json\")), result)\n            }\n\n            override fun sendStreamingRequest(request: Request): Response? {\n                return null\n            }\n        })\n    }\n\n    @After\n    fun tearDown() {\n        if (this::app.isInitialized) {\n            app.close()\n        }\n    }\n\n    @Test\n    fun getUserId() {\n        val user: User = app.registerUserAndLogin(TestHelper.getRandomEmail(), \"123456\")\n        assertEquals(USER_ID, user.id)\n    }\n\n    @Test\n    fun getDeviceId() {\n        val user: User = app.registerUserAndLogin(TestHelper.getRandomEmail(), \"123456\")\n        assertEquals(DEVICE_ID, user.deviceId)\n    }\n\n    @Test\n    fun accessToken() {\n        val user: User = app.registerUserAndLogin(TestHelper.getRandomEmail(), \"123456\")\n        assertEquals(ACCESS_TOKEN, user.accessToken)\n    }\n\n    @Test\n    fun refreshToken() {\n        val user: User = app.registerUserAndLogin(TestHelper.getRandomEmail(), \"123456\")\n        assertEquals(REFRESH_TOKEN, user.refreshToken)\n    }\n\n    @Test\n    fun getUser(){\n        val user: User = app.registerUserAndLogin(TestHelper.getRandomEmail(), \"123456\")\n        val profile = user.profile\n        assertEquals(user, profile.user)\n    }\n\n    @Test\n    fun getName() {\n        val user: User = app.registerUserAndLogin(TestHelper.getRandomEmail(), \"123456\")\n        val profile = user.profile\n        assertEquals(NAME, profile.name)\n    }\n\n    @Test\n    fun getEmail() {\n        val user: User = app.registerUserAndLogin(TestHelper.getRandomEmail(), \"123456\")\n        val profile = user.profile\n        assertEquals(EMAIL, profile.email)\n    }\n\n    @Test\n    fun getFirstName() {\n        val user: User = app.registerUserAndLogin(TestHelper.getRandomEmail(), \"123456\")\n        val profile = user.profile\n        assertEquals(FIRST_NAME, profile.firstName)\n    }\n\n    @Test\n    fun getLastName() {\n        val user: User = app.registerUserAndLogin(TestHelper.getRandomEmail(), \"123456\")\n        val profile = user.profile\n        assertEquals(LAST_NAME, profile.lastName)\n    }\n\n    @Test\n    fun getBirthday() {\n        val user: User = app.registerUserAndLogin(TestHelper.getRandomEmail(), \"123456\")\n        val profile = user.profile\n        assertEquals(BIRTHDAY, profile.birthday)\n    }\n\n    @Test\n    fun getGender() {\n        val user: User = app.registerUserAndLogin(TestHelper.getRandomEmail(), \"123456\")\n        val profile = user.profile\n        assertEquals(GENDER, profile.gender)\n    }\n\n    @Test\n    fun getMinAge() {\n        val user: User = app.registerUserAndLogin(TestHelper.getRandomEmail(), \"123456\")\n        val profile = user.profile\n        assertEquals(MIN_AGE, profile.minAge)\n    }\n\n    @Test\n    fun getMaxAge() {\n        val user: User = app.registerUserAndLogin(TestHelper.getRandomEmail(), \"123456\")\n        val profile = user.profile\n        assertEquals(MAX_AGE, profile.maxAge)\n    }\n\n    @Test\n    fun getPictureUrl() {\n        val user: User = app.registerUserAndLogin(TestHelper.getRandomEmail(), \"123456\")\n        val profile = user.profile\n        assertEquals(PICTURE_URL, profile.pictureUrl)\n    }\n\n    @Test\n    fun getNameNullable() {\n        setNullProfile()\n\n        val user: User = app.registerUserAndLogin(TestHelper.getRandomEmail(), \"123456\")\n        val profile = user.profile\n        assertNull(profile.name)\n    }\n\n    @Test\n    fun getEmailNullable() {\n        setNullProfile()\n\n        val user: User = app.registerUserAndLogin(TestHelper.getRandomEmail(), \"123456\")\n        val profile = user.profile\n        assertNull(profile.email)\n    }\n\n    @Test\n    fun getFirstNameNullable() {\n        setNullProfile()\n\n        val user: User = app.registerUserAndLogin(TestHelper.getRandomEmail(), \"123456\")\n        val profile = user.profile\n        assertNull(profile.firstName)\n    }\n\n    @Test\n    fun getLastNameNullable() {\n        setNullProfile()\n\n        val user: User = app.registerUserAndLogin(TestHelper.getRandomEmail(), \"123456\")\n        val profile = user.profile\n        assertNull(profile.lastName)\n    }\n\n    @Test\n    fun getBirthdayNullable() {\n        setNullProfile()\n\n        val user: User = app.registerUserAndLogin(TestHelper.getRandomEmail(), \"123456\")\n        val profile = user.profile\n        assertNull(profile.birthday)\n    }\n\n    @Test\n    fun getGenderNullable() {\n        setNullProfile()\n\n        val user: User = app.registerUserAndLogin(TestHelper.getRandomEmail(), \"123456\")\n        val profile = user.profile\n        assertNull(profile.gender)\n    }\n\n    @Test\n    fun getMinAgeNullable() {\n        setNullProfile()\n\n        val user: User = app.registerUserAndLogin(TestHelper.getRandomEmail(), \"123456\")\n        val profile = user.profile\n        assertNull(profile.minAge)\n    }\n\n    @Test\n    fun getMaxAgeNullable() {\n        setNullProfile()\n\n        val user: User = app.registerUserAndLogin(TestHelper.getRandomEmail(), \"123456\")\n        val profile = user.profile\n        assertNull(profile.maxAge)\n    }\n\n    @Test\n    fun getPictureUrlNullable() {\n        setNullProfile()\n\n        val user: User = app.registerUserAndLogin(TestHelper.getRandomEmail(), \"123456\")\n        val profile = user.profile\n        assertNull(profile.pictureUrl)\n    }\n\n    @Test\n    fun getProviderType() {\n        val user: User = app.registerUserAndLogin(TestHelper.getRandomEmail(), \"123456\")\n        assertEquals(Credentials.Provider.EMAIL_PASSWORD, user.providerType)\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTestObjectServer/kotlin/io/realm/admin/ServerAdmin.kt",
    "content": "package io.realm.admin\n\nimport io.realm.log.LogLevel\nimport io.realm.log.RealmLog\nimport io.realm.mongodb.App\nimport io.realm.mongodb.User\nimport io.realm.mongodb.sync.SyncSession\nimport io.realm.TestHelper\nimport okhttp3.*\nimport okio.Buffer\nimport org.json.JSONArray\nimport org.json.JSONObject\nimport java.nio.charset.Charset\nimport java.util.concurrent.CountDownLatch\nimport java.util.concurrent.TimeUnit\n/**\n * Wrapper around MongoDB Realm Server Admin functions needed for tests.\n */\nclass ServerAdmin(private val app: App) {\n\n    private lateinit var accessToken: String\n    private lateinit var groupId: String\n    private lateinit var appId: String\n\n    private val json = MediaType.parse(\"application/json; charset=utf-8\")\n    private val baseUrl = \"http://127.0.0.1:9090/api/admin/v3.0\"\n    private val client: OkHttpClient = OkHttpClient.Builder()\n            .callTimeout(30, TimeUnit.SECONDS)\n            .followRedirects(true)\n            .addInterceptor { chain ->\n                val request: Request = chain.request()\n                if (RealmLog.getLevel() <= LogLevel.DEBUG) {\n                    val sb = StringBuilder(request.method())\n                    sb.append(' ')\n                    sb.append(request.url())\n                    sb.append('\\n')\n                    sb.append(request.headers())\n                    if (request.body() != null) {\n                        // Stripped down version of https://github.com/square/okhttp/blob/master/okhttp-logging-interceptor/src/main/java/okhttp3/logging/HttpLoggingInterceptor.java\n                        // We only expect request context to be JSON.\n                        val buffer = Buffer()\n                        request.body()?.writeTo(buffer)\n                        sb.append(buffer.readString(Charset.forName(\"UTF-8\")))\n                    }\n                    RealmLog.debug(\"Admin HTTP Request = \\n%s\", sb)\n                }\n                chain.proceed(request)\n            }\n            .connectionPool(ConnectionPool(5, 5, TimeUnit.SECONDS))\n            .build()\n\n    init {\n        logIn()\n    }\n\n    private fun executeRequest(builder: Request.Builder, authenticate: Boolean = true): String {\n        if (authenticate) {\n            builder.header(\"Authorization\", \"Bearer $accessToken\")\n        }\n        val call = client.newCall(builder.build())\n        val response = call.execute()\n        val body: String = response.body()?.string() ?: \"\"\n        val code = response.code()\n        if (code < 200 || code > 299) {\n            throw IllegalArgumentException(\"HTTP error $code : $body\")\n        }\n\n        return body\n    }\n\n    // Logs the admin user so we can call other endpoints\n    private fun logIn() {\n        // Login\n        val body = mapOf(Pair(\"username\", \"unique_user@domain.com\"), Pair(\"password\", \"password\"))\n        var builder: Request.Builder = Request.Builder()\n                .url(\"$baseUrl/auth/providers/local-userpass/login\")\n                .post(RequestBody.create(json, JSONObject(body).toString()))\n        var result = JSONObject(executeRequest(builder, authenticate = false))\n        accessToken = result.getString(\"access_token\")\n\n        // Get GroupId\n        builder = Request.Builder().url(\"$baseUrl/auth/profile\").get()\n        result = JSONObject(executeRequest(builder))\n        groupId = (result.getJSONArray(\"roles\")[0] as JSONObject).getString(\"group_id\")\n\n        // Get Internal App Id of the requested app\n        val appId = this.app.configuration.appId\n        builder = Request.Builder().url(\"$baseUrl/groups/$groupId/apps\").get()\n        val response = JSONArray(executeRequest(builder))\n        for (i in 0 until response.length()) {\n            val appObject = response[i] as JSONObject\n            if (appObject.getString(\"client_app_id\") == appId) {\n                this.appId = appObject.getString(\"_id\")\n                return\n            }\n        }\n        throw IllegalArgumentException(\"Could not find app: $\")\n    }\n\n    fun enableFlexibleSync() {\n        var request = Request.Builder()\n            .url(\"$baseUrl/groups/$groupId/apps/$appId/services\")\n            .get()\n        var result = executeRequest(request, true)\n        val list = JSONArray(executeRequest(request))\n        for (i in 0 until list.length()) {\n            val obj: JSONObject = list.getJSONObject(i)\n            if (obj.getString(\"type\") == \"mongodb\") {\n                val serviceId = obj.getString(\"_id\")\n                val configUpdateJson = \"\"\"\n                        {\n                            \"flexible_sync\": {\n                                \"state\": \"enabled\", \n                                \"database_name\": \"test_data\",\n                                \"permissions\": {\n                                    \"rules\": {},\n                                    \"defaultRoles\": [\n                                        {\n                                            \"name\": \"all\",\n                                            \"applyWhen\": {},\n                                            \"read\": true,\n                                            \"write\": true\n                                        }\n                                    ]\n                                }, \n                                \"queryable_fields_names\": [\"owner\", \"name\", \"color\", \"section\"]\n                            }\n                        }\n                \"\"\".trimIndent()\n                obj.put(\"config\", JSONObject(configUpdateJson))\n                request = Request.Builder()\n                    .url(\"$baseUrl/groups/$groupId/apps/$appId/services/${serviceId}/config\")\n                    .patch(RequestBody.create(json, configUpdateJson))\n                executeRequest(request, true)\n                break;\n            }\n        }\n    }\n\n    fun disableUser(user: User) {\n        var request = Request.Builder()\n                .url(\"$baseUrl/groups/$groupId/apps/$appId/users/${user.id}/disable\")\n                .put(RequestBody.create(json, \"\"))\n        executeRequest(request, true)\n    }\n\n    /**\n     * Deletes all currently registered and pending users on MongoDB Realm.\n     */\n    fun deleteAllUsers() {\n        deleteAllRegisteredUsers()\n        deleteAllPendingUsers()\n    }\n\n    private fun deleteAllPendingUsers() {\n        var request = Request.Builder()\n                .url(\"$baseUrl/groups/$groupId/apps/$appId/user_registrations/pending_users\")\n                .get()\n        val pendingUsers = JSONArray(executeRequest(request))\n        for (i in 0 until pendingUsers.length()) {\n            val user = pendingUsers[i] as JSONObject\n            val loginTypes = user.getJSONArray(\"login_ids\")\n            for (j in 0 until loginTypes.length()) {\n                val login = loginTypes[j] as JSONObject\n                if (login.getString(\"id_type\") == \"email\") {\n                    deletePendingUser(login.getString(\"id\"))\n                }\n            }\n        }\n    }\n\n    private fun deleteAllRegisteredUsers() {\n        var request = Request.Builder()\n                .url(\"$baseUrl/groups/$groupId/apps/$appId/users\")\n                .get()\n        val list = JSONArray(executeRequest(request))\n        for (i in 0 until list.length()) {\n            val o = list[i] as JSONObject\n            request = Request.Builder()\n                    .url(\"$baseUrl/groups/$groupId/apps/$appId/users/${o.getString(\"_id\")}\")\n                    .delete()\n            executeRequest(request)\n        }\n    }\n\n    private fun deletePendingUser(email: String) {\n        val request = Request.Builder()\n                .url(\"$baseUrl/groups/$groupId/apps/$appId/user_registrations/by_email/$email\")\n                .delete()\n        executeRequest(request)\n    }\n\n    /**\n     * Determines whether or not the preconfigured reset password function is used instead\n     * of sending an email.\n     */\n    fun setResetFunction(enabled: Boolean) {\n        val providerId: String = getLocalUserPassProviderId()\n\n        // Read current config\n        var request = Request.Builder()\n                .url(\"$baseUrl/groups/$groupId/apps/$appId/auth_providers/$providerId\")\n                .get()\n        val authProviderConfig = JSONObject(executeRequest(request, true))\n        authProviderConfig.getJSONObject(\"config\").apply {\n            put(\"runResetFunction\", enabled)\n        }\n        // Change autoConfirm and update the provider\n        request = Request.Builder()\n                .url(\"$baseUrl/groups/$groupId/apps/$appId/auth_providers/$providerId\")\n                .patch(RequestBody.create(json, authProviderConfig.toString()))\n        executeRequest(request)\n    }\n\n    private fun getLocalUserPassProviderId(): String {\n        val request: Request.Builder = Request.Builder()\n            .url(\"$baseUrl/groups/$groupId/apps/$appId/auth_providers\")\n            .get()\n        val authProvidersListResult = JSONArray(executeRequest(request, true))\n        var providerId: String? = null\n        for (i in 0 until authProvidersListResult.length()) {\n            val o = authProvidersListResult[i] as JSONObject\n            if (o.getString(\"name\") == \"local-userpass\") {\n                providerId = o.getString(\"_id\")\n                break\n            }\n        }\n        return providerId!!\n    }\n\n    /**\n     * Creates an admin API key that can be used for testing purposes.\n     */\n    fun createServerApiKey(): String {\n        val body = mapOf(Pair(\"name\", \"SERVER_KEY\"))\n        val builder = Request.Builder()\n                .url(\"$baseUrl/groups/$groupId/apps/$appId/api_keys\")\n                .post(RequestBody.create(json, JSONObject(body).toString()))\n        val result = JSONObject(executeRequest(builder))\n        return result.getString(\"key\")\n    }\n\n    private fun getMongodbServiceId(): String {\n        var request = Request.Builder()\n            .url(\"$baseUrl/groups/$groupId/apps/$appId/services\")\n            .get()\n        val list = JSONArray(executeRequest(request))\n        for (i in 0 until list.length()) {\n            val obj: JSONObject = list.getJSONObject(i)\n            if (obj.getString(\"type\") == \"mongodb\") {\n                return obj.getString(\"_id\")\n            }\n        }\n\n        error(\"Mongodb service not found for ${this.app.configuration.appId}\")\n    }\n\n    private fun getConfig(): JSONObject {\n        val serviceId = getMongodbServiceId()\n\n        val request: Request.Builder = Request.Builder()\n            .url(\"$baseUrl/groups/$groupId/apps/$appId/services/$serviceId/config\")\n            .get()\n\n        return JSONObject(executeRequest(request, true))\n    }\n\n    private fun isRecoveryModeEnabled(): Boolean = !getConfig()\n        .let { config: JSONObject ->\n            if (config.has(\"sync\")) {\n                config.getJSONObject(\"sync\")\n            } else if(config.has(\"flexible_sync\")) {\n                config.getJSONObject(\"flexible_sync\")\n            } else {\n                throw Error(\"Sync mode not defined\")\n            }\n        }.optBoolean(\"is_recovery_mode_disabled\", false)\n\n    private fun setIsRecoveryModeEnabled(isRecoveryModeEnabled: Boolean) {\n        val serviceId = getMongodbServiceId()\n\n        val config = getConfig().apply {\n            this.let { config ->\n                if (config.has(\"sync\")) {\n                    config.getJSONObject(\"sync\")\n                } else if (config.has(\"flexible_sync\")) {\n                    config.getJSONObject(\"flexible_sync\")\n                } else {\n                    throw Error(\"Sync mode not defined\")\n                }\n            }.put(\"is_recovery_mode_disabled\", !isRecoveryModeEnabled)\n        }\n\n        val request = Request.Builder()\n            .url(\"$baseUrl/groups/$groupId/apps/$appId/services/${serviceId}/config\")\n            .patch(RequestBody.create(json, config.toString()))\n\n        executeRequest(request, true)\n    }\n\n    private fun callTriggerResetFunction(\n        appId: String,\n        userId: String\n    ) {\n\n        val functionCall = JSONObject(\"\"\"\n            {\n                \"name\": \"triggerClientReset\",\n                \"arguments\": [\"$appId\", \"$userId\"]\n            }\n        \"\"\".trimIndent())\n\n        val request = Request.Builder()\n            .url(\"$baseUrl/groups/$groupId/apps/$appId/debug/execute_function?run_as_system=true\")\n            .post(RequestBody.create(json, functionCall.toString()))\n\n        executeRequest(request, true)\n    }\n\n    // Will trigger a client reset with the recovery mode disabled if needed\n    // Disabling the recovery mode would force a `RecoverOrDiscardUnsyncedChangesStrategy` to\n    // discard the local changes even if they are recoverable.\n    fun triggerClientReset(\n        syncSession: SyncSession,\n        withRecoveryModeEnabled: Boolean = true,\n        latch: CountDownLatch? = null,\n        block: () -> Unit\n    )\n    {\n        // Later, we will restore the original status\n        val wasRecoveryModeEnabled = isRecoveryModeEnabled()\n\n        try {\n            syncSession.downloadAllServerChanges()\n            syncSession.stop()\n\n            block()\n\n            setIsRecoveryModeEnabled(withRecoveryModeEnabled)\n\n            callTriggerResetFunction(appId, syncSession.user.id)\n\n            syncSession.start()\n            syncSession.downloadAllServerChanges()\n        } finally {\n            latch?.let { TestHelper.awaitOrFail(it) }\n            setIsRecoveryModeEnabled(wasRecoveryModeEnabled)\n        }\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTestObjectServer/kotlin/io/realm/entities/DefaultSyncSchema.kt",
    "content": "/**\n * Copyright 2020 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 */\npackage io.realm.entities\n\nimport io.realm.annotations.RealmModule\nimport io.realm.entities.embedded.*\n\nconst val defaultPartitionValue = \"default\"\n\n/**\n * The set of classes initially supported by MongoDB Realm.\n */\n@RealmModule(classes = [\n    SyncDog::class,\n    SyncPerson::class,\n    SyncAllTypes::class,\n    EmbeddedSimpleParent::class,\n    EmbeddedSimpleChild::class,\n    EmbeddedSimpleListParent::class\n    // FIXME: add these to schema once https://jira.mongodb.org/projects/HELP/queues/issue/HELP-17759 is fixed\n//    EmbeddedTreeParent::class,\n//    EmbeddedTreeNode::class,\n//    EmbeddedTreeLeaf::class\n])\nclass DefaultSyncSchema\n\n@RealmModule(classes = [\n    SyncColor::class\n])\nclass ColorSyncSchema\n\n@RealmModule(classes = [\n    DummySyncObject::class,\n])\nclass ObjectSyncSchema\n"
  },
  {
    "path": "realm/realm-library/src/androidTestObjectServer/kotlin/io/realm/entities/DummySyncObject.kt",
    "content": "/**\n * Copyright 2022 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 */\npackage io.realm.entities\n\nimport io.realm.RealmObject\nimport io.realm.annotations.PrimaryKey\nimport org.bson.types.ObjectId\nimport java.util.*\n\nopen class DummySyncObject: RealmObject() {\n    @PrimaryKey\n    var _id: ObjectId? = ObjectId.get()\n    var string: String = UUID.randomUUID().toString()\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTestObjectServer/kotlin/io/realm/entities/FlexSyncColor.kt",
    "content": "/**\n * Copyright 2022 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 */\npackage io.realm.entities\n\nimport android.graphics.Color\nimport io.realm.RealmObject\nimport io.realm.annotations.PrimaryKey\nimport org.bson.types.ObjectId\n\n/**\n * Object used when testing Flexible Sync\n */\nopen class FlexSyncColor(): RealmObject() {\n    constructor(section: Int): this() {\n        this.section = section\n    }\n    @PrimaryKey\n    var _id: ObjectId? = ObjectId.get()\n    var section: Int = 0\n    var color: String = Color.RED.toString()\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTestObjectServer/kotlin/io/realm/entities/SyncAllTypes.kt",
    "content": "/*\n * Copyright 2020 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\npackage io.realm.entities\n\nimport io.realm.*\nimport io.realm.annotations.PrimaryKey\nimport io.realm.annotations.RealmField\nimport io.realm.annotations.Required\nimport org.bson.types.Decimal128\nimport org.bson.types.ObjectId\nimport java.math.BigDecimal\nimport java.util.*\n\nopen class SyncAllTypes : RealmObject() {\n\n    companion object {\n        const val CLASS_NAME = \"SyncAllTypes\"\n        const val FIELD_STRING = \"columnString\"\n        const val FIELD_LONG = \"columnLong\"\n        const val FIELD_FLOAT = \"columnFloat\"\n        const val FIELD_DOUBLE = \"columnDouble\"\n        const val FIELD_BOOLEAN = \"columnBoolean\"\n        const val FIELD_DATE = \"columnDate\"\n        const val FIELD_BINARY = \"columnBinary\"\n        const val FIELD_MUTABLEREALMINTEGER = \"columnMutableRealmInteger\"\n        const val FIELD_DECIMAL128 = \"columnDecimal128\"\n        const val FIELD_OBJECT_ID = \"columnObjectId\"\n        const val FIELD_REALMOBJECT = \"columnRealmObject\"\n        const val FIELD_REALMLIST = \"columnRealmList\"\n        const val FIELD_STRING_LIST = \"columnStringList\"\n        const val FIELD_BINARY_LIST = \"columnBinaryList\"\n        const val FIELD_BOOLEAN_LIST = \"columnBooleanList\"\n        const val FIELD_LONG_LIST = \"columnLongList\"\n        const val FIELD_DOUBLE_LIST = \"columnDoubleList\"\n        const val FIELD_FLOAT_LIST = \"columnFloatList\"\n        const val FIELD_DATE_LIST = \"columnDateList\"\n    }\n\n    @PrimaryKey\n    @RealmField(name = \"_id\")\n    var id = ObjectId()\n\n    @Required\n    var columnString = \"\"\n    var columnLong: Long = 0\n\n    var columnFloat = 0f\n\n    var columnDouble = 0.0\n    var isColumnBoolean = false\n\n    @Required\n    var columnDate = Date(0)\n\n    @Required\n    var columnBinary = ByteArray(0)\n\n    @Required\n    var columnDecimal128 = Decimal128(BigDecimal.ZERO)\n\n    @Required\n    var columnObjectId = ObjectId(TestHelper.randomObjectIdHexString())\n\n    @Required\n    var columnUUID: UUID = UUID.randomUUID()\n\n    var columnRealmAny: RealmAny? = RealmAny.nullValue()\n\n    val columnRealmInteger: MutableRealmInteger = MutableRealmInteger.ofNull()\n\n    var columnRealmObject: SyncDog? = null\n\n    var columnRealmList: RealmList<SyncDog> = RealmList()\n    @Required\n    var columnStringList: RealmList<String> = RealmList()\n    @Required\n    var columnBinaryList: RealmList<ByteArray> = RealmList()\n    @Required\n    var columnBooleanList: RealmList<Boolean> = RealmList()\n    @Required\n    var columnLongList: RealmList<Long> = RealmList()\n    @Required\n    var columnDoubleList: RealmList<Double> = RealmList()\n    @Required\n    var columnFloatList: RealmList<Float>? = null\n    @Required\n    var columnDateList: RealmList<Date> = RealmList()\n    @Required\n    var columnDecimal128List: RealmList<Decimal128> = RealmList()\n\n    @Required\n    var columnObjectIdList: RealmList<ObjectId> = RealmList()\n    \n    @Required\n    var columnUUIDList: RealmList<UUID> = RealmList()\n\n    var columnRealmAnyList: RealmList<RealmAny> = RealmList()\n\n    var columnRealmDictionary: RealmDictionary<SyncDog> = RealmDictionary()\n    @Required // Cloud only supports non-null values for this type\n    var columnBooleanDictionary: RealmDictionary<Boolean> = RealmDictionary()\n    @Required // Cloud only supports non-null values for this type\n    var columnStringDictionary: RealmDictionary<String> = RealmDictionary()\n    @Required // Cloud only supports non-null values for this type\n    var columnIntegerDictionary: RealmDictionary<Int> = RealmDictionary()\n    @Required // Cloud only supports non-null values for this type\n    var columnFloatDictionary: RealmDictionary<Float> = RealmDictionary()\n    @Required // Cloud only supports non-null values for this type\n    var columnLongDictionary: RealmDictionary<Long> = RealmDictionary()\n    @Required // Cloud only supports non-null values for this type\n    var columnShortDictionary: RealmDictionary<Short> = RealmDictionary()\n    @Required // Cloud only supports non-null values for this type\n    var columnDoubleDictionary: RealmDictionary<Double> = RealmDictionary()\n    @Required // Cloud only supports non-null values for this type\n    var columnByteDictionary: RealmDictionary<Byte> = RealmDictionary()\n    @Required // Cloud only supports non-null values for this type\n    var columnBinaryDictionary: RealmDictionary<ByteArray> = RealmDictionary()\n    @Required // Cloud only supports non-null values for this type\n    var columnDateDictionary: RealmDictionary<Date> = RealmDictionary()\n    @Required // Cloud only supports non-null values for this type\n    var columnObjectIdDictionary: RealmDictionary<ObjectId> = RealmDictionary()\n    @Required // Cloud only supports non-null values for this type\n    var columnUUIDDictionary: RealmDictionary<UUID> = RealmDictionary()\n    @Required // Cloud only supports non-null values for this type\n    var columnDecimal128Dictionary: RealmDictionary<Decimal128> = RealmDictionary()\n    var columnRealmAnyDictionary: RealmDictionary<RealmAny> = RealmDictionary()\n\n    var columnRealmSet: RealmSet<SyncDog> = RealmSet()\n    @Required // Cloud only supports non-null values for this type\n    var columnBooleanSet: RealmSet<Boolean> = RealmSet()\n    @Required // Cloud only supports non-null values for this type\n    var columnStringSet: RealmSet<String> = RealmSet()\n    @Required // Cloud only supports non-null values for this type\n    var columnIntegerSet: RealmSet<Int> = RealmSet()\n    @Required // Cloud only supports non-null values for this type\n    var columnFloatSet: RealmSet<Float> = RealmSet()\n    @Required // Cloud only supports non-null values for this type\n    var columnLongSet: RealmSet<Long> = RealmSet()\n    @Required // Cloud only supports non-null values for this type\n    var columnShortSet: RealmSet<Short> = RealmSet()\n    @Required // Cloud only supports non-null values for this type\n    var columnDoubleSet: RealmSet<Double> = RealmSet()\n    @Required // Cloud only supports non-null values for this type\n    var columnByteSet: RealmSet<Byte> = RealmSet()\n    @Required // Cloud only supports non-null values for this type\n    var columnBinarySet: RealmSet<ByteArray> = RealmSet()\n    @Required // Cloud only supports non-null values for this type\n    var columnDateSet: RealmSet<Date> = RealmSet()\n    @Required // Cloud only supports non-null values for this type\n    var columnObjectIdSet: RealmSet<ObjectId> = RealmSet()\n    @Required // Cloud only supports non-null values for this type\n    var columnUUIDSet: RealmSet<UUID> = RealmSet()\n    @Required // Cloud only supports non-null values for this type\n    var columnDecimal128Set: RealmSet<Decimal128> = RealmSet()\n    var columnRealmAnySet: RealmSet<RealmAny> = RealmSet()\n\n    fun setColumnMutableRealmInteger(value: Int) {\n        columnRealmInteger.set(value.toLong())\n    }\n\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTestObjectServer/kotlin/io/realm/entities/SyncAllTypesSchema.kt",
    "content": "/*\n * Copyright 2020 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/**\n * Copyright 2020 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 */\npackage io.realm.entities\n\nimport io.realm.annotations.RealmModule\n\n/**\n * The set of classes initially supported by MongoDB Realm.\n */\n@RealmModule(classes = [SyncDog::class, SyncPerson::class, SyncAllTypes::class])\nclass SyncAllTypesSchema {\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTestObjectServer/kotlin/io/realm/entities/SyncAllTypesWithFloat.kt",
    "content": "/*\n * Copyright 2020 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\npackage io.realm.entities\n\nimport io.realm.*\nimport io.realm.annotations.PrimaryKey\nimport io.realm.annotations.RealmField\nimport io.realm.annotations.Required\nimport org.bson.types.Decimal128\nimport org.bson.types.ObjectId\nimport java.math.BigDecimal\nimport java.util.*\n\n// TODO This class is only for tracking failure when uploading SyncAllTypes including float field.\n//  Once supported this class can be deleted and we can include the float field in SyncAllTypes\nopen class SyncAllTypesWithFloat : RealmObject() {\n\n    companion object {\n        const val CLASS_NAME = \"AllTypes\"\n        const val FIELD_STRING = \"columnString\"\n        const val FIELD_LONG = \"columnLong\"\n        const val FIELD_FLOAT = \"columnFloat\"\n        const val FIELD_DOUBLE = \"columnDouble\"\n        const val FIELD_BOOLEAN = \"columnBoolean\"\n        const val FIELD_DATE = \"columnDate\"\n        const val FIELD_BINARY = \"columnBinary\"\n        const val FIELD_MUTABLEREALMINTEGER = \"columnMutableRealmInteger\"\n        const val FIELD_DECIMAL128 = \"columnDecimal128\"\n        const val FIELD_OBJECT_ID = \"columnObjectId\"\n        const val FIELD_REALMOBJECT = \"columnRealmObject\"\n        const val FIELD_REALMLIST = \"columnRealmList\"\n        const val FIELD_STRING_LIST = \"columnStringList\"\n        const val FIELD_BINARY_LIST = \"columnBinaryList\"\n        const val FIELD_BOOLEAN_LIST = \"columnBooleanList\"\n        const val FIELD_LONG_LIST = \"columnLongList\"\n        const val FIELD_DOUBLE_LIST = \"columnDoubleList\"\n        const val FIELD_FLOAT_LIST = \"columnFloatList\"\n        const val FIELD_DATE_LIST = \"columnDateList\"\n    }\n\n    @PrimaryKey\n    @RealmField(name = \"_id\")\n    var id = ObjectId()\n\n    @Required\n    var columnString = \"\"\n    var columnLong: Long = 0\n\n    var columnFloat = 0f\n\n    var columnDouble = 0.0\n    var isColumnBoolean = false\n\n    @Required\n    var columnDate = Date(0)\n\n    @Required\n    var columnBinary = ByteArray(0)\n\n    @Required\n    var columnDecimal128 = Decimal128(BigDecimal.ZERO)\n\n    @Required\n    var columnObjectId = ObjectId(TestHelper.randomObjectIdHexString())\n    val columnRealmInteger = MutableRealmInteger.ofNull()\n    var columnRealmObject: SyncDog? = null\n\n    var columnRealmList: RealmList<SyncDog>? = null\n    @Required\n    var columnStringList: RealmList<String>? = null\n    @Required\n    var columnBinaryList: RealmList<ByteArray>? = null\n    @Required\n    var columnBooleanList: RealmList<Boolean>? = null\n    @Required\n    var columnLongList: RealmList<Long>? = null\n    @Required\n    var columnDoubleList: RealmList<Double>? = null\n\n    @Required\n    var columnFloatList: RealmList<Float>? = null\n\n    @Required\n    var columnDateList: RealmList<Date>? = null\n    @Required\n    var columnDecimal128List: RealmList<Decimal128>? = null\n\n    @Required\n    var columnObjectIdList: RealmList<ObjectId>? = null\n\n    var columnRealmDictionary: RealmDictionary<SyncDog> = RealmDictionary()\n    @Required // Cloud only supports non-null values for this type\n    var columnBooleanDictionary: RealmDictionary<Boolean> = RealmDictionary()\n    @Required // Cloud only supports non-null values for this type\n    var columnStringDictionary: RealmDictionary<String> = RealmDictionary()\n    @Required // Cloud only supports non-null values for this type\n    var columnIntegerDictionary: RealmDictionary<Int> = RealmDictionary()\n    @Required // Cloud only supports non-null values for this type\n    var columnFloatDictionary: RealmDictionary<Float> = RealmDictionary()\n    @Required // Cloud only supports non-null values for this type\n    var columnLongDictionary: RealmDictionary<Long> = RealmDictionary()\n    @Required // Cloud only supports non-null values for this type\n    var columnShortDictionary: RealmDictionary<Short> = RealmDictionary()\n    @Required // Cloud only supports non-null values for this type\n    var columnDoubleDictionary: RealmDictionary<Double> = RealmDictionary()\n    @Required // Cloud only supports non-null values for this type\n    var columnByteDictionary: RealmDictionary<Byte> = RealmDictionary()\n    @Required // Cloud only supports non-null values for this type\n    var columnBinaryDictionary: RealmDictionary<ByteArray> = RealmDictionary()\n    @Required // Cloud only supports non-null values for this type\n    var columnDateDictionary: RealmDictionary<Date> = RealmDictionary()\n    @Required // Cloud only supports non-null values for this type\n    var columnObjectIdDictionary: RealmDictionary<ObjectId> = RealmDictionary()\n    @Required // Cloud only supports non-null values for this type\n    var columnUUIDDictionary: RealmDictionary<UUID> = RealmDictionary()\n    @Required // Cloud only supports non-null values for this type\n    var columnDecimal128Dictionary: RealmDictionary<Decimal128> = RealmDictionary()\n    var columnRealmAnyDictionary: RealmDictionary<RealmAny> = RealmDictionary()\n\n    fun setColumnMutableRealmInteger(value: Int) {\n        columnRealmInteger.set(value.toLong())\n    }\n\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTestObjectServer/kotlin/io/realm/entities/SyncColor.kt",
    "content": "/**\n * Copyright 2020 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 */\npackage io.realm.entities\n\nimport android.graphics.Color\nimport io.realm.RealmObject\nimport io.realm.annotations.PrimaryKey\nimport io.realm.annotations.RealmField\nimport org.bson.types.ObjectId\n\n// FIXME: This class is just temporary as a smoke test for Sync. Should be removed once all Sync tests have been migrated.\nopen class SyncColor: RealmObject() {\n    @PrimaryKey\n    var _id: ObjectId? = ObjectId.get()\n    @RealmField(name = \"realm_id\")\n    var realmId: String? = null\n    var color: String = Color.RED.toString()\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTestObjectServer/kotlin/io/realm/entities/SyncDog.kt",
    "content": "/**\n * Copyright 2020 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 */\npackage io.realm.entities\n\nimport io.realm.RealmObject\nimport io.realm.RealmResults\nimport io.realm.annotations.LinkingObjects\nimport io.realm.annotations.PrimaryKey\nimport io.realm.annotations.RealmField\nimport org.bson.types.ObjectId\n\nopen class SyncDog: RealmObject() {\n    @PrimaryKey\n    @RealmField(name = \"_id\")\n    var id: ObjectId? = ObjectId()\n    // This field is not required by clients\n    // But if added, it must always have the\n    // same value as the partition value\n    // used to open the Realm\n    // @RealmField(name = \"realm_id\")\n    // var realmId: String? = null\n    var breed: String? = null\n    var name: String = \"\"\n\n    @LinkingObjects(\"columnRealmObject\")\n    val syncAllTypes: RealmResults<SyncAllTypes>? = null\n}\n\n"
  },
  {
    "path": "realm/realm-library/src/androidTestObjectServer/kotlin/io/realm/entities/SyncPerson.kt",
    "content": "/**\n * Copyright 2020 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 */\npackage io.realm.entities\n\nimport io.realm.RealmList\nimport io.realm.RealmObject\nimport io.realm.annotations.PrimaryKey\nimport io.realm.annotations.RealmClass\nimport io.realm.annotations.RealmField\nimport io.realm.annotations.Required\nimport org.bson.types.ObjectId\n\nopen class SyncPerson(\n        @PrimaryKey\n        @RealmField(name = \"_id\")\n        var id: ObjectId? = ObjectId(),\n        var age: Long = 0,\n        var dogs: RealmList<SyncDog> = RealmList(),\n        var firstName: String = \"\",\n        var lastName: String = \"\"\n        // This field is not required by clients\n        // But if added, it must always have the\n        // same value as the partition value\n        // used to open the Realm\n        // @RealmField(name = \"realm_id\")\n        // var realmId: String? = null\n): RealmObject()"
  },
  {
    "path": "realm/realm-library/src/androidTestObjectServer/kotlin/io/realm/entities/SyncSchemeMigration.kt",
    "content": "/*\n * Copyright 2020 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 */\npackage io.realm.entities\n\nimport io.realm.RealmObject\nimport io.realm.annotations.PrimaryKey\nimport io.realm.annotations.RealmField\nimport org.bson.types.ObjectId\n\nopen class SyncSchemeMigration : RealmObject() {\n\n    companion object {\n        const val CLASS_NAME = \"SyncSchemeMigration\"\n    }\n\n    @PrimaryKey\n    @RealmField(name = \"_id\")\n    var id = ObjectId()\n\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTestObjectServer/kotlin/io/realm/entities/SyncStringOnly.kt",
    "content": "/*\n * Copyright 2020 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 */\npackage io.realm.entities\n\nimport io.realm.RealmObject\nimport io.realm.annotations.PrimaryKey\nimport io.realm.annotations.RealmField\nimport org.bson.types.ObjectId\n\nopen class SyncStringOnly : RealmObject() {\n\n    companion object {\n        const val CLASS_NAME = \"SyncStringOnly\"\n        const val FIELD_ID = \"_id\"\n        const val FIELD_CHARS = \"chars\"\n    }\n\n    @PrimaryKey\n    @RealmField(name = \"_id\")\n    var id: ObjectId = ObjectId()\n\n    var chars: String? = null\n\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTestObjectServer/kotlin/io/realm/entities/SyncStringOnlyModule.kt",
    "content": "/*\n * Copyright 2020 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\npackage io.realm.entities\n\nimport io.realm.annotations.RealmModule\n\n@RealmModule(classes = [SyncStringOnly::class])\nclass SyncStringOnlyModule\n"
  },
  {
    "path": "realm/realm-library/src/androidTestObjectServer/kotlin/io/realm/internal/async/RealmResultTaskImplTest.kt",
    "content": "/*\n * Copyright 2020 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\npackage io.realm.internal.async\n\nimport androidx.test.ext.junit.runners.AndroidJUnit4\nimport io.realm.TestHelper\nimport io.realm.mongodb.App\nimport io.realm.mongodb.AppException\nimport io.realm.mongodb.RealmResultTask\nimport io.realm.rule.BlockingLooperThread\nimport org.junit.Test\nimport org.junit.runner.RunWith\nimport java.util.concurrent.ThreadPoolExecutor\nimport java.util.concurrent.atomic.AtomicReference\nimport kotlin.test.*\n\nprivate const val OUTPUT = 42\nprivate const val EXCEPTION_REASON = \"BOOM\"\n\n@RunWith(AndroidJUnit4::class)\nclass RealmResultTaskImplTest {\n\n    private val looperThread = BlockingLooperThread()\n    private val service: ThreadPoolExecutor = App.NETWORK_POOL_EXECUTOR\n\n    @Test\n    fun constructor_throwsOnNullArgs() {\n        assertFailsWith<IllegalArgumentException> {\n            RealmResultTaskImpl<String>(TestHelper.getNull(), object : RealmResultTaskImpl.Executor<String>() {\n                override fun run(): String {\n                    return \"something\"\n                }\n            })\n        }\n\n        assertFailsWith<IllegalArgumentException> {\n            RealmResultTaskImpl<String>(service, TestHelper.getNull())\n        }\n    }\n\n    @Test\n    fun get() = RealmResultTaskImpl(\n            service,\n            object : RealmResultTaskImpl.Executor<Int>() {\n                override fun run(): Int {\n                    return OUTPUT\n                }\n            }\n    ).let { task -> assertEquals(OUTPUT, task.get()) }\n\n    @Test\n    fun get_fails() {\n        val task: RealmResultTask<String> = RealmResultTaskImpl(\n                service,\n                object : RealmResultTaskImpl.Executor<String>() {\n                    override fun run(): String {\n                        throw RuntimeException(EXCEPTION_REASON)\n                    }\n                }\n        )\n        assertFailsWith<RuntimeException> {\n            task.get()\n        }.let {\n            assertTrue(it.message!!.contains(EXCEPTION_REASON))\n        }\n    }\n\n    @Test\n    fun getAsync_success() = looperThread.runBlocking {\n        val task: RealmResultTask<Int> = RealmResultTaskImpl(\n                service,\n                object : RealmResultTaskImpl.Executor<Int>() {\n                    override fun run(): Int {\n                        return OUTPUT\n                    }\n                }\n        )\n\n        task.getAsync { result ->\n            assertEquals(OUTPUT, result.get())\n            looperThread.testComplete()\n        }\n    }\n\n    @Test\n    fun getAsync_returnsError() = looperThread.runBlocking {\n        val task: RealmResultTask<String> = RealmResultTaskImpl(\n                service,\n                object : RealmResultTaskImpl.Executor<String>() {\n                    override fun run(): String {\n                        throw RuntimeException(EXCEPTION_REASON)\n                    }\n                }\n        )\n\n        task.getAsync { result ->\n            assertNull(result.get())\n            assertNotNull(result.error)\n            assertEquals(AppException::class.java, result.error::class.java)\n            result.error.exception!!.let { exception ->\n                assertEquals(exception::class.java, RuntimeException::class.java)\n                assertTrue(exception.message.equals(EXCEPTION_REASON))\n            }\n            looperThread.testComplete()\n        }\n    }\n\n    @Test\n    fun getAsync_throwsDueToNoLooper() {\n        val task: RealmResultTask<String> = RealmResultTaskImpl(\n                service,\n                object : RealmResultTaskImpl.Executor<String>() {\n                    override fun run(): String {\n                        fail(\"Should fail before returning anything\")\n                    }\n                }\n        )\n        assertFailsWith<IllegalStateException> {\n            task.getAsync {\n                fail(\"Should never reach this callback\")\n            }\n        }\n    }\n\n    @Test\n    fun cancel() {\n        val taskReference = AtomicReference<RealmResultTask<String>>()\n        val task: RealmResultTask<String> = RealmResultTaskImpl(\n                service,\n                object : RealmResultTaskImpl.Executor<String>() {\n                    override fun run(): String? {\n                        // Ensure we cancel before returning a result\n                        taskReference.get().let {\n                            assertNotNull(it)\n                            assertFalse(it.isCancelled)\n\n                            // Cancel task here\n                            it.cancel()\n\n                            // Makes no difference to complete here or from another thread\n                            looperThread.testComplete()\n                        }\n\n                        // It does not matter we return something here, it will not be delivered\n                        return null\n                    }\n                }\n        )\n        taskReference.set(task)\n\n        looperThread.runBlocking {\n            task.getAsync {\n                fail(\"Should never reach this callback\")\n            }\n        }\n\n        assertTrue(task.isCancelled)\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTestObjectServer/kotlin/io/realm/internal/async/RealmStreamTaskImplTest.kt",
    "content": "/*\n * Copyright 2020 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\npackage io.realm.internal.async\n\nimport androidx.test.ext.junit.runners.AndroidJUnit4\nimport io.realm.internal.objectserver.EventStream\nimport io.realm.mongodb.mongo.events.BaseChangeEvent\nimport io.realm.rule.BlockingLooperThread\nimport junit.framework.Assert.assertEquals\nimport org.junit.Test\nimport org.junit.runner.RunWith\nimport java.lang.IllegalStateException\nimport kotlin.test.assertFailsWith\n\n@RunWith(AndroidJUnit4::class)\nclass RealmStreamTaskImplTest {\n    private val looperThread = BlockingLooperThread()\n\n    @Test\n    fun asyncExclusiveAccess() {\n        // Validates that we cannot access synchronously if we are already\n        // accessing the stream asynchronously.\n\n        val task = RealmEventStreamAsyncTaskImpl(\"test\", object : RealmEventStreamAsyncTaskImpl.Executor<String>() {\n            override fun run(): EventStream<String> {\n                return object : EventStream<String> {\n                    var opened: Boolean = true\n\n                    override fun getNextEvent(): BaseChangeEvent<String>? {\n                        return null\n                    }\n\n                    override fun close() {\n                        opened = false\n                    }\n\n                    override fun isOpen(): Boolean {\n                        return opened\n                    }\n                }\n            }\n        })\n\n        task.get { }\n\n        assertFailsWith<IllegalStateException> {\n            task.get { }\n        }\n    }\n\n    @Test\n    fun openClose() {\n        val task = RealmEventStreamTaskImpl(\"test\", object : RealmEventStreamTaskImpl.Executor<String>() {\n            override fun run(): EventStream<String> {\n                return object : EventStream<String> {\n                    var opened: Boolean = false\n\n                    override fun getNextEvent(): BaseChangeEvent<String>? {\n                        opened = true\n                        return null\n                    }\n\n                    override fun close() {\n                        opened = false\n                    }\n\n                    override fun isOpen(): Boolean {\n                        return opened\n                    }\n                }\n            }\n        })\n\n        assertEquals(false, task.isOpen)\n        assertEquals(false, task.isCancelled)\n\n        task.next\n\n        assertEquals(true, task.isOpen)\n        assertEquals(false, task.isCancelled)\n\n        task.cancel()\n\n        assertEquals(false, task.isOpen)\n        assertEquals(true, task.isCancelled)\n    }\n\n    @Test\n    fun openCloseAsync() {\n        val task = RealmEventStreamAsyncTaskImpl(\"test\", object : RealmEventStreamAsyncTaskImpl.Executor<String>() {\n            override fun run(): EventStream<String> {\n                return object : EventStream<String> {\n                    var opened: Boolean = false\n\n                    override fun getNextEvent(): BaseChangeEvent<String>? {\n                        opened = true\n                        return null\n                    }\n\n                    override fun close() {\n                        opened = false\n                    }\n\n                    override fun isOpen(): Boolean {\n                        return opened\n                    }\n                }\n            }\n        })\n\n        assertEquals(false, task.isOpen)\n        assertEquals(false, task.isCancelled)\n\n        looperThread.runBlocking {\n            task.get {\n                looperThread.testComplete()\n            }\n        }\n\n        assertEquals(true, task.isOpen)\n        assertEquals(false, task.isCancelled)\n\n        task.cancel()\n\n        assertEquals(false, task.isOpen)\n        assertEquals(true, task.isCancelled)\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTestObjectServer/kotlin/io/realm/internal/network/LoggingInterceptorTest.kt",
    "content": "/*\n * Copyright 2020 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 */\npackage io.realm.internal.network\n\nimport androidx.test.platform.app.InstrumentationRegistry\nimport io.realm.Realm\nimport io.realm.TestApp\nimport io.realm.TestHelper\nimport io.realm.internal.network.LoggingInterceptor.LOGIN_FEATURE\nimport io.realm.log.LogLevel\nimport io.realm.log.RealmLog\nimport io.realm.mongodb.*\nimport io.realm.mongodb.auth.GoogleAuthType\nimport io.realm.mongodb.log.obfuscator.HttpLogObfuscator\nimport io.realm.util.assertFailsWithErrorCode\nimport org.bson.Document\nimport org.junit.After\nimport org.junit.Assert\nimport org.junit.Before\nimport org.junit.Test\nimport kotlin.test.assertTrue\n\nclass LoggingInterceptorTest {\n\n    private lateinit var app: App\n    private lateinit var testLogger: TestHelper.TestLogger\n\n    @Before\n    fun setUp() {\n        Realm.init(InstrumentationRegistry.getInstrumentation().targetContext)\n    }\n\n    @After\n    fun tearDown() {\n        if (this::app.isInitialized) {\n            app.close()\n        }\n        if (this::testLogger.isInitialized) {\n            RealmLog.setLevel(LogLevel.WARN)\n            RealmLog.remove(testLogger)\n        }\n    }\n\n    @Test\n    fun emailPasswordRegistrationAndLogin_noObfuscation() {\n        app = TestApp()\n        testLogger = getLogger()\n\n        val email = TestHelper.getRandomEmail()\n        val password = \"123456\"\n        app.emailPassword.registerUser(email, password)\n        assertMessageExists(\"\"\"\"email\":\"$email\"\"\"\", \"\"\"\"password\":\"$password\"\"\"\")\n\n        app.login(Credentials.emailPassword(email, password))\n        assertMessageExists(\"\"\"\"username\":\"$email\"\"\"\", \"\"\"\"password\":\"$password\"\"\"\")\n    }\n\n    @Test\n    fun emailPasswordRegistrationAndLogin_obfuscation() {\n        app = TestApp { builder ->\n            builder.httpLogObfuscator(HttpLogObfuscator(LOGIN_FEATURE, AppConfiguration.loginObfuscators))\n        }\n        testLogger = getLogger()\n\n        val email = TestHelper.getRandomEmail()\n        val password = \"123456\"\n        app.emailPassword.registerUser(email, password)\n        assertMessageExists(\"\"\"\"email\":\"***\"\"\"\", \"\"\"\"password\":\"***\"\"\"\")\n\n        app.login(Credentials.emailPassword(email, password))\n        assertMessageExists(\"\"\"\"username\":\"***\"\"\"\", \"\"\"\"password\":\"***\"\"\"\")\n    }\n\n    @Test\n    fun customFunctionLogin_noObfuscation() {\n        app = TestApp()\n        testLogger = getLogger()\n\n        val key1 = \"mail\"\n        val key2 = \"id\"\n        val value1 = TestHelper.getRandomEmail()\n        val value2 = 666 + TestHelper.getRandomId()\n        val customFunction = mapOf(\n                key1 to value1,\n                key2 to value2\n        ).let {\n            Credentials.customFunction(Document(it))\n        }\n\n        app.login(customFunction)\n        assertMessageExists(\"\"\"\"$key1\":\"$value1\"\"\"\")\n    }\n\n    @Test\n    fun customFunctionLogin_obfuscation() {\n        app = TestApp { builder ->\n            builder.httpLogObfuscator(HttpLogObfuscator(LOGIN_FEATURE, AppConfiguration.loginObfuscators))\n        }\n        testLogger = getLogger()\n\n        val key1 = \"mail\"\n        val key2 = \"id\"\n        val value1 = TestHelper.getRandomEmail()\n        val value2 = 666 + TestHelper.getRandomId()\n        val customFunction = mapOf(\n                key1 to value1,\n                key2 to value2\n        ).let { credsMap ->\n            Credentials.customFunction(Document(credsMap))\n        }\n\n        app.login(customFunction)\n        assertMessageExists(\"\"\"\"functionArgs\":\"***\"\"\"\")\n    }\n\n    @Test\n    fun facebookTokenLogin_noObfuscation() {\n        app = TestApp()\n        testLogger = getLogger()\n        val token = \"facebook-token\"\n\n        try {\n            app.login(Credentials.facebook(token))\n        } catch (error: AppException) {\n            // It will fail as long as oauth2 tokens aren't supported\n        } finally {\n            assertMessageExists(\"\"\"accessToken\":\"$token\"\"\"\")\n        }\n    }\n\n    @Test\n    fun facebookTokenLogin_obfuscation() {\n        app = TestApp { builder ->\n            builder.httpLogObfuscator(HttpLogObfuscator(LOGIN_FEATURE, AppConfiguration.loginObfuscators))\n        }\n        testLogger = getLogger()\n        val token = \"facebook-token\"\n\n        try {\n            app.login(Credentials.facebook(token))\n        } catch (error: AppException) {\n            Assert.assertEquals(ErrorCode.INVALID_SESSION, error.errorCode)\n        } finally {\n            assertMessageExists(\"\"\"\"accessToken\":\"***\"\"\"\")\n        }\n    }\n\n    @Test\n    fun appleTokenLogin_noObfuscation() {\n        app = TestApp()\n        testLogger = getLogger()\n        val token = \"apple-token\"\n\n        try {\n            app.login(Credentials.apple(token))\n        } catch (error: AppException) {\n            Assert.assertEquals(ErrorCode.INVALID_SESSION, error.errorCode)\n        } finally {\n            assertMessageExists(\"\"\"\"id_token\":\"$token\"\"\"\")\n        }\n    }\n\n    @Test\n    fun appleTokenLogin_obfuscation() {\n        app = TestApp { builder ->\n            builder.httpLogObfuscator(HttpLogObfuscator(LOGIN_FEATURE, AppConfiguration.loginObfuscators))\n        }\n        testLogger = getLogger()\n        val token = \"apple-token\"\n\n        try {\n            app.login(Credentials.apple(token))\n        } catch (error: AppException) {\n            Assert.assertEquals(ErrorCode.INVALID_SESSION, error.errorCode)\n        } finally {\n            assertMessageExists(\"\"\"\"id_token\":\"***\"\"\"\")\n        }\n    }\n\n    @Test\n    fun googleTokenLogin_authCode_noObfuscation() {\n        app = TestApp()\n        testLogger = getLogger()\n        val token = \"google-token\"\n\n        try {\n            app.login(Credentials.google(token, GoogleAuthType.AUTH_CODE))\n        } catch (error: AppException) {\n            Assert.assertEquals(ErrorCode.INVALID_SESSION, error.errorCode)\n        } finally {\n            assertMessageExists(\"\"\"\"authCode\":\"$token\"\"\"\")\n        }\n    }\n\n    @Test\n    fun googleTokenLogin_authCode_obfuscation() {\n        app = TestApp { builder ->\n            builder.httpLogObfuscator(HttpLogObfuscator(LOGIN_FEATURE, AppConfiguration.loginObfuscators))\n        }\n        testLogger = getLogger()\n        val token = \"google-token\"\n\n        try {\n            app.login(Credentials.google(token, GoogleAuthType.AUTH_CODE))\n        } catch (error: AppException) {\n            Assert.assertEquals(ErrorCode.INVALID_SESSION, error.errorCode)\n        } finally {\n            assertMessageExists(\"\"\"\"authCode\":\"***\"\"\"\")\n        }\n    }\n\n\n    @Test\n    fun googleTokenLogin_idToken_noObfuscation() {\n        app = TestApp()\n        testLogger = getLogger()\n        val token = \"google-token\"\n\n        assertFailsWithErrorCode(ErrorCode.INVALID_SESSION) {\n            app.login(Credentials.google(token, GoogleAuthType.ID_TOKEN))\n        }.also {\n            assertMessageExists(\"\"\"\"id_token\":\"$token\"\"\"\")\n        }\n    }\n\n    @Test\n    fun googleTokenLogin_idToken_obfuscation() {\n        app = TestApp { builder ->\n            builder.httpLogObfuscator(HttpLogObfuscator(LOGIN_FEATURE, AppConfiguration.loginObfuscators))\n        }\n        testLogger = getLogger()\n        val token = \"google-token\"\n\n        try {\n            app.login(Credentials.google(token, GoogleAuthType.ID_TOKEN))\n        } catch (error: AppException) {\n            Assert.assertEquals(ErrorCode.INVALID_SESSION, error.errorCode)\n        } finally {\n            assertMessageExists(\"\"\"\"id_token\":\"***\"\"\"\")\n        }\n    }\n\n    private fun getLogger(): TestHelper.TestLogger =\n            TestHelper.TestLogger().also {\n                RealmLog.add(it)\n                RealmLog.setLevel(LogLevel.ALL)\n            }\n\n    // Check whether the expected logcat entries are present in the test logger buffer\n    private fun assertMessageExists(vararg entries: String) {\n        var patternExists = false\n        for (entry in entries) {\n            val iterator = testLogger.messageBuffer.iterator()\n            while (iterator.hasNext()) {\n                val bufferEntry = iterator.next()\n                if (bufferEntry != null && bufferEntry.contains(entry)) {\n                    patternExists = true\n                    continue\n                }\n            }\n            // Skip to assertion if found\n            if (patternExists) continue\n        }\n        assertTrue(patternExists)\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTestObjectServer/kotlin/io/realm/internal/network/NetworkRequestTests.kt",
    "content": "package io.realm.internal.network\n\nimport androidx.test.platform.app.InstrumentationRegistry\nimport io.realm.Realm\nimport io.realm.mongodb.App\nimport io.realm.mongodb.AppException\nimport io.realm.mongodb.ErrorCode\nimport junit.framework.TestCase.assertEquals\nimport org.junit.Before\nimport org.junit.Test\nimport kotlin.test.assertFailsWith\n\nclass NetworkRequestTests {\n\n    private lateinit var app: App\n\n    @Before\n    fun setUp() {\n        Realm.init(InstrumentationRegistry.getInstrumentation().targetContext)\n    }\n\n    // Test for https://github.com/realm/realm-java/issues/7847\n    @Test\n    fun interruptedRequestReturnsError() {\n        val request = object: NetworkRequest<Unit>() {\n            override fun mapSuccess(result: Any?): Unit {\n                Unit\n            }\n\n            override fun execute(callback: NetworkRequest<Unit>) {\n                Thread.currentThread().interrupt()\n            }\n        }\n        assertFailsWith<AppException> {\n            request.resultOrThrow()\n        }.also {\n            assertEquals(it.errorCode, ErrorCode.NETWORK_INTERRUPTED)\n            assertEquals(it.errorMessage, \"Network request interrupted.\")\n        }\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTestObjectServer/kotlin/io/realm/mongodb/AppExt.kt",
    "content": "/*\n * Copyright 2020 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 */\npackage io.realm.mongodb\n\nimport io.realm.RealmExt\nimport io.realm.admin.ServerAdmin\nimport io.realm.mongodb.sync.testReset\nimport io.realm.testClearApplicationContext\nimport io.realm.TestHelper\n\n/**\n * Resets the Realm Application and delete all local state.\n *\n * Trying to access any Sync or Realm App API's after this has been called has undefined\n * behavior.\n */\nfun App.close() {\n    ServerAdmin(this).deleteAllUsers()\n    this.syncManager.testReset()\n    this.osApp.networkTransport.reset()\n    RealmExt.testClearApplicationContext()\n}\n\n/**\n * Helper function for quickly logging in test users.\n * This only works if users in the Realm Application are configured to be automatically confirmed.\n */\nfun App.registerUserAndLogin(email: String = TestHelper.getRandomEmail(), password: String = \"123456\"): User {\n    emailPassword.registerUser(email, password)\n    return login(Credentials.emailPassword(email, password))\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTestObjectServer/kotlin/io/realm/mongodb/MongoClientTest.kt",
    "content": "/*\n * Copyright 2020 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 */\npackage io.realm.mongodb\n\nimport androidx.test.ext.junit.runners.AndroidJUnit4\nimport androidx.test.platform.app.InstrumentationRegistry\nimport io.realm.*\nimport io.realm.mongodb.mongo.MongoClient\nimport io.realm.mongodb.mongo.MongoCollection\nimport io.realm.mongodb.mongo.MongoNamespace\nimport io.realm.mongodb.mongo.events.BaseChangeEvent.OperationType\nimport io.realm.mongodb.mongo.options.CountOptions\nimport io.realm.mongodb.mongo.options.FindOneAndModifyOptions\nimport io.realm.mongodb.mongo.options.FindOptions\nimport io.realm.mongodb.mongo.options.UpdateOptions\nimport io.realm.rule.BlockingLooperThread\nimport io.realm.util.assertFailsWithErrorCode\nimport io.realm.util.mongodb.CustomType\nimport org.bson.BsonDocument\nimport org.bson.BsonString\nimport org.bson.Document\nimport org.bson.codecs.configuration.CodecRegistries\nimport org.bson.types.ObjectId\nimport org.junit.After\nimport org.junit.Before\nimport org.junit.Ignore\nimport org.junit.Test\nimport org.junit.runner.RunWith\nimport java.io.IOException\nimport kotlin.test.*\n\nprivate const val COLLECTION_NAME = \"mongo_data\" // uses ObjectId as _id\nprivate const val COLLECTION_NAME_ALT = \"mongo_data_alt\" // uses Integer as _id\n\n@RunWith(AndroidJUnit4::class)\nclass MongoClientTest {\n    private lateinit var app: TestApp\n    private lateinit var user: User\n    private lateinit var client: MongoClient\n\n    private val looperThread = BlockingLooperThread()\n\n    @Before\n    fun setUp() {\n        Realm.init(InstrumentationRegistry.getInstrumentation().targetContext)\n        app = TestApp()\n        user = app.registerUserAndLogin(TestHelper.getRandomEmail(), \"123456\")\n        client = user.getMongoClient(SERVICE_NAME)\n    }\n\n    @After\n    fun tearDown() {\n        if (this::client.isInitialized) {\n            with(getCollectionInternal(COLLECTION_NAME)) {\n                deleteMany(Document()).get()\n            }\n            with(getCollectionInternal(COLLECTION_NAME_ALT)) {\n                deleteMany(Document()).get()\n            }\n        }\n        if (this::app.isInitialized) {\n            app.close()\n        }\n    }\n\n    @Test\n    fun serviceName() {\n        assertNotNull(client.serviceName)\n        assertEquals(SERVICE_NAME, client.serviceName)\n    }\n\n    @Test\n    fun count() {\n        with(getCollectionInternal()) {\n            assertEquals(0, count().get())\n\n            val rawDoc = Document(\"hello\", \"world\")\n            val doc1 = Document(rawDoc)\n            val doc2 = Document(rawDoc)\n            insertOne(doc1).get()\n            assertEquals(1, count().get())\n            insertOne(doc2).get()\n            assertEquals(2, count().get())\n\n            assertEquals(2, count(rawDoc).get())\n            assertEquals(0, count(Document(\"hello\", \"Friend\")).get())\n            assertEquals(1, count(rawDoc, CountOptions().limit(1)).get())\n\n            assertFailsWithErrorCode(ErrorCode.MONGODB_ERROR) {\n                count(Document(\"\\$who\", 1)).get()\n            }.also { e ->\n                assertTrue(e.errorMessage!!.contains(\"operator\", true))\n            }\n        }\n    }\n\n    @Test\n    fun count_fails() {\n        with(getCollectionInternal()) {\n            assertFailsWithErrorCode(ErrorCode.MONGODB_ERROR) {\n                count(Document(\"\\$who\", 1)).get()\n            }.also { e ->\n                assertTrue(e.errorMessage!!.contains(\"operator\", true))\n            }\n        }\n    }\n\n    @Test\n    fun findOne_nullResult() {\n        with(getCollectionInternal()) {\n            // Test findOne() on empty collection with no filter and no options\n            assertNull(findOne().get())\n\n            // Test findOne() with filter that does not match any documents and no options\n            assertNull(findOne(Document(\"hello\", \"worldDNE\")).get())\n\n            val doc1 = Document(\"hello\", \"world1\")\n            insertOne(doc1).get()\n            assertEquals(1, count().get())\n\n            // Test findOne() with filter that does not match any documents and no options\n            assertNull(findOne(Document(\"hello\", \"worldDNE\")).get())\n        }\n    }\n\n    @Test\n    fun findOne_singleDocument() {\n        with(getCollectionInternal()) {\n            val doc1 = Document(\"hello\", \"world1\")\n\n            // Insert one document\n            insertOne(doc1).get()\n            assertEquals(1, count().get())\n\n            // No filter and no options\n            assertEquals(doc1, findOne().get()!!.withoutId())\n\n            // Projection (remove \"_id\") options\n            val projection = Document(\"hello\", 1).apply { this[\"_id\"] = 0 }\n            var options = FindOptions()\n                    .limit(2)\n                    .projection(projection)\n            assertEquals(doc1, findOne(Document(), options).get()!!)\n\n            // Projection (remove \"_id\") and sort (by desc \"hello\") options\n            options = FindOptions()\n                    .limit(2)\n                    .projection(projection)\n                    .sort(Document(\"hello\", -1))\n            assertEquals(doc1, findOne(Document(), options).get()!!)\n        }\n    }\n\n    @Test\n    fun findOne_multipleDocuments() {\n        with(getCollectionInternal()) {\n            val doc1 = Document(\"hello\", \"world1\")\n            val doc2 = Document(\"hello\", \"world2\")\n            val doc3 = Document(\"hello\", \"world3\")\n\n            // Insert 3 documents\n            insertMany(listOf(doc1, doc2, doc3)).get()\n            assertEquals(3, count().get())\n\n            // Projection (remove \"_id\") and sort (by asc \"hello\") options\n            val projection = Document(\"hello\", 1).apply { this[\"_id\"] = 0 }\n            var options = FindOptions()\n                    .limit(2)\n                    .projection(projection)\n                    .sort(Document(\"hello\", 1))\n            assertEquals(doc1, findOne(Document(), options).get()!!)\n\n            // Projection (remove \"_id\") and sort (by desc \"hello\") options\n            options = FindOptions()\n                    .limit(2)\n                    .projection(projection)\n                    .sort(Document(\"hello\", -1))\n            assertEquals(doc3, findOne(Document(), options).get()!!)\n        }\n    }\n\n    @Test\n    fun findOne_fails() {\n        with(getCollectionInternal()) {\n            assertFailsWithErrorCode(ErrorCode.MONGODB_ERROR) {\n                findOne(Document(\"\\$who\", 1)).get()\n            }.also { e ->\n                assertTrue(e.errorMessage!!.contains(\"operator\", true))\n            }\n        }\n    }\n\n    @Test\n    fun find() {\n        with(getCollectionInternal()) {\n            // Find on an empty collection returns false on hasNext and null on first\n            var iter = find()\n            assertFalse(iter.iterator().get()!!.hasNext())\n            assertNull(iter.first().get())\n\n            val doc1 = Document(\"hello\", \"world\")\n            val doc2 = Document(\"hello\", \"friend\")\n            doc2[\"proj\"] = \"field\"\n            insertMany(listOf(doc1, doc2)).get()\n\n            // Iterate after inserting two documents\n            assertTrue(iter.iterator().get()!!.hasNext())\n            assertEquals(doc1, iter.first().get()!!.withoutId())\n\n            // Get next with sort by desc \"_id\" and limit to 1 document\n            assertEquals(doc2,\n                    iter.limit(1)\n                            .sort(Document(\"_id\", -1))\n                            .iterator().get()!!\n                            .next().withoutId())\n\n            // Find first document\n            iter = find(doc1)\n            assertTrue(iter.iterator().get()!!.hasNext())\n            assertEquals(doc1,\n                    iter.iterator().get()!!\n                            .next().withoutId())\n\n            // Find with filter for first document\n            iter = find().filter(doc1)\n            assertTrue(iter.iterator().get()!!.hasNext())\n            assertEquals(doc1,\n                    iter.iterator().get()!!\n                            .next().withoutId())\n\n            // Find with projection shows \"proj\" in result\n            val expected = Document(\"proj\", \"field\")\n            assertEquals(expected,\n                    find(doc2)\n                            .projection(Document(\"proj\", 1))\n                            .iterator().get()!!\n                            .next().withoutId())\n\n            // Getting a new iterator returns first element on tryNext\n            val asyncIter = iter.iterator().get()!!\n            assertEquals(doc1, asyncIter.tryNext().withoutId())\n        }\n    }\n\n    @Test\n    fun find_fails() {\n        with(getCollectionInternal()) {\n            assertFailsWithErrorCode(ErrorCode.MONGODB_ERROR) {\n                find(Document(\"\\$who\", 1)).first().get()\n            }.also { e ->\n                assertTrue(e.errorMessage!!.contains(\"operator\", true))\n            }\n        }\n    }\n\n    @Test\n    fun aggregate() {\n        with(getCollectionInternal()) {\n            // Aggregate on an empty collection returns false on hasNext and null on first\n            var iter = aggregate(listOf())\n            assertFalse(iter.iterator().get()!!.hasNext())\n            assertNull(iter.first().get())\n\n            // Iterate after inserting two documents\n            val doc1 = Document(\"hello\", \"world\")\n            val doc2 = Document(\"hello\", \"friend\")\n            insertMany(listOf(doc1, doc2)).get()\n            assertTrue(iter.iterator().get()!!.hasNext())\n            assertEquals(doc1.withoutId(), iter.first().get()!!.withoutId())\n\n            // Aggregate with pipeline, sort by desc \"_id\" and limit to 1 document\n            iter = aggregate(listOf(Document(\"\\$sort\", Document(\"_id\", -1)), Document(\"\\$limit\", 1)))\n            assertEquals(doc2.withoutId(),\n                    iter.iterator().get()!!\n                            .next().withoutId())\n\n            // Aggregate with pipeline, match first document\n            iter = aggregate(listOf(Document(\"\\$match\", doc1)))\n            assertTrue(iter.iterator().get()!!.hasNext())\n            assertEquals(doc1.withoutId(), iter.iterator().get()!!.next().withoutId())\n        }\n    }\n\n    @Test\n    fun aggregate_fails() {\n        with(getCollectionInternal()) {\n            assertFailsWithErrorCode(ErrorCode.MONGODB_ERROR) {\n                aggregate(listOf(Document(\"\\$who\", 1))).first().get()\n            }.also { e ->\n                assertTrue(e.errorMessage!!.contains(\"pipeline\", true))\n            }\n        }\n    }\n\n    @Test\n    fun insertOne() {\n        with(getCollectionInternal()) {\n            val doc1 = Document(\"hello\", \"world\").apply { this[\"_id\"] = ObjectId() }\n            assertEquals(doc1.getObjectId(\"_id\"), insertOne(doc1).get()!!.insertedId.asObjectId().value)\n            assertEquals(1, count().get())\n\n            val doc2 = Document(\"hello\", \"world\")\n            val insertOneResult = insertOne(doc2).get()!!\n            assertNotNull(insertOneResult.insertedId.asObjectId().value)\n            assertEquals(2, count().get())\n        }\n    }\n\n    @Test\n    fun insertOne_throwsWhenMixingIdTypes() {\n        with(getCollectionInternal()) {\n            // The default collection uses ObjectId for \"_id\"\n            val doc1 = Document(\"hello\", \"world\").apply { this[\"_id\"] = 666 }\n            assertFailsWith<AppException> {\n                insertOne(doc1).get()!!\n            }.let { e ->\n                assertContains(e.errorMessage!!, \"insert not permitted\")\n            }\n        }\n    }\n\n    @Test\n    fun insertOne_integerId() {\n        with(getCollectionInternal(COLLECTION_NAME_ALT)) {\n            val doc1 = Document(\"hello\", \"world\").apply { this[\"_id\"] = 666 }\n            val insertOneResult = insertOne(doc1).get()!!\n            assertEquals(doc1.getInteger(\"_id\"), insertOneResult.insertedId.asInt32().value)\n            assertEquals(1, count().get())\n        }\n    }\n\n    @Test\n    fun insertOne_fails() {\n        with(getCollectionInternal()) {\n            val doc1 = Document(\"hello\", \"world\").apply { this[\"_id\"] = ObjectId() }\n            insertOne(doc1).get()\n\n            assertFailsWithErrorCode(ErrorCode.MONGODB_ERROR) {\n                insertOne(doc1).get()\n            }.also { e ->\n                assertTrue(e.errorMessage!!.contains(\"duplicate\", true))\n            }\n        }\n    }\n\n    @Test\n    fun insertMany_singleDocument() {\n        with(getCollectionInternal()) {\n            val doc1 = Document(\"hello\", \"world\").apply { this[\"_id\"] = ObjectId() }\n\n            assertEquals(doc1.getObjectId(\"_id\"),\n                    insertMany(listOf(doc1)).get()!!.insertedIds[0]!!.asObjectId().value)\n            val doc2 = Document(\"hello\", \"world\")\n\n            assertNotEquals(doc1.getObjectId(\"_id\"), insertMany(listOf(doc2)).get()!!.insertedIds[0]!!.asObjectId().value)\n\n            val doc3 = Document(\"one\", \"two\")\n            val doc4 = Document(\"three\", 4)\n\n            insertMany(listOf(doc3, doc4)).get()\n        }\n    }\n\n    @Test\n    fun insertMany_singleDocument_fails() {\n        with(getCollectionInternal()) {\n            val doc1 = Document(\"hello\", \"world\").apply { this[\"_id\"] = ObjectId() }\n            insertMany(listOf(doc1)).get()\n\n            assertFailsWithErrorCode(ErrorCode.MONGODB_ERROR) {\n                insertMany(listOf(doc1)).get()\n            }.also { e ->\n                assertTrue(e.errorMessage!!.contains(\"duplicate\", true))\n            }\n        }\n    }\n\n    @Test\n    fun insertMany_multipleDocuments() {\n        with(getCollectionInternal()) {\n            val doc1 = Document(\"hello\", \"world\").apply { this[\"_id\"] = ObjectId() }\n            val doc2 = Document(\"hello\", \"world\").apply { this[\"_id\"] = ObjectId() }\n            val documents = listOf(doc1, doc2)\n\n            insertMany(documents).get()!!\n                    .insertedIds\n                    .forEach { entry ->\n                        assertEquals(documents[entry.key.toInt()][\"_id\"], entry.value.asObjectId().value)\n                    }\n\n            val doc3 = Document(\"one\", \"two\")\n            val doc4 = Document(\"three\", 4)\n\n            insertMany(listOf(doc3, doc4)).get()\n            assertEquals(4, count().get())\n        }\n    }\n\n    @Test\n    fun insertMany_multipleDocuments_IntegerId() {\n        with(getCollectionInternal(COLLECTION_NAME_ALT)) {\n            val doc1 = Document(\"hello\", \"world\").apply { this[\"_id\"] = 42 }\n            val doc2 = Document(\"hello\", \"world\").apply { this[\"_id\"] = 42 + 1 }\n            val documents = listOf(doc1, doc2)\n\n            insertMany(documents).get()!!\n                    .insertedIds\n                    .forEach { entry ->\n                        assertEquals(documents[entry.key.toInt()][\"_id\"], entry.value.asInt32().value)\n                    }\n\n            val doc3 = Document(\"one\", \"two\")\n            val doc4 = Document(\"three\", 4)\n\n            insertMany(listOf(doc3, doc4)).get()\n            assertEquals(4, count().get())\n        }\n    }\n\n    @Test\n    fun insertMany_throwsWhenMixingIdTypes() {\n        with(getCollectionInternal()) {\n            val doc1 = Document(\"hello\", \"world\").apply { this[\"_id\"] = 42 }\n            val doc2 = Document(\"hello\", \"world\").apply { this[\"_id\"] = 42 + 1 }\n            val documents = listOf(doc1, doc2)\n\n            assertFailsWith<AppException> {\n                insertMany(documents).get()!!\n            }.let { e ->\n                assertContains(e.errorMessage!!, \"insert not permitted\")\n            }\n        }\n    }\n\n    @Test\n    fun insertMany_multipleDocuments_fails() {\n        with(getCollectionInternal()) {\n            val doc1 = Document(\"hello\", \"world\").apply { this[\"_id\"] = ObjectId() }\n            val doc2 = Document(\"hello\", \"world\").apply { this[\"_id\"] = ObjectId() }\n            val documents = listOf(doc1, doc2)\n            insertMany(documents).get()\n\n            assertFailsWithErrorCode(ErrorCode.MONGODB_ERROR) {\n                insertMany(documents).get()\n            }.also { e ->\n                assertTrue(e.errorMessage!!.contains(\"duplicate\", true))\n            }\n        }\n    }\n\n    @Test\n    fun deleteOne_singleDocument() {\n        with(getCollectionInternal()) {\n            assertEquals(0, deleteOne(Document()).get()!!.deletedCount)\n            assertEquals(0, deleteOne(Document(\"hello\", \"world\")).get()!!.deletedCount)\n\n            val doc1 = Document(\"hello\", \"world\")\n\n            insertOne(doc1).get()\n            assertEquals(1, deleteOne(doc1).get()!!.deletedCount)\n            assertEquals(0, count().get())\n        }\n    }\n\n    @Test\n    fun deleteOne_fails() {\n        with(getCollectionInternal()) {\n            assertFailsWithErrorCode(ErrorCode.MONGODB_ERROR) {\n                deleteOne(Document(\"\\$who\", 1)).get()\n            }.also { e ->\n                assertTrue(e.errorMessage!!.contains(\"operator\", true))\n            }\n        }\n    }\n\n    @Test\n    fun deleteOne_multipleDocuments() {\n        with(getCollectionInternal()) {\n            assertEquals(0, count().get())\n\n            val rawDoc = Document(\"hello\", \"world\")\n            val doc1 = Document(rawDoc)\n            val doc1b = Document(rawDoc)\n            val doc2 = Document(\"foo\", \"bar\")\n            val doc3 = Document(\"42\", \"666\")\n            insertMany(listOf(doc1, doc1b, doc2, doc3)).get()\n            assertEquals(1, deleteOne(rawDoc).get()!!.deletedCount)\n            assertEquals(1, deleteOne(Document()).get()!!.deletedCount)\n            assertEquals(2, count().get())\n        }\n    }\n\n    @Test\n    fun deleteMany_singleDocument() {\n        with(getCollectionInternal()) {\n            assertEquals(0, count().get())\n\n            val rawDoc = Document(\"hello\", \"world\")\n            val doc1 = Document(rawDoc)\n\n            insertOne(doc1).get()\n            assertEquals(1, count().get())\n            assertEquals(1, deleteMany(doc1).get()!!.deletedCount)\n            assertEquals(0, count().get())\n        }\n    }\n\n    @Test\n    fun deleteMany_multipleDocuments() {\n        with(getCollectionInternal()) {\n            assertEquals(0, count().get())\n\n            val rawDoc = Document(\"hello\", \"world\")\n            val doc1 = Document(rawDoc)\n            val doc1b = Document(rawDoc)\n            val doc2 = Document(\"foo\", \"bar\")\n            val doc3 = Document(\"42\", \"666\")\n            insertMany(listOf(doc1, doc1b, doc2, doc3)).get()\n            assertEquals(2, deleteMany(rawDoc).get()!!.deletedCount)                 // two docs will be deleted\n            assertEquals(2, count().get())                                           // two docs still present\n            assertEquals(2, deleteMany(Document()).get()!!.deletedCount)             // delete all\n            assertEquals(0, count().get())\n\n            insertMany(listOf(doc1, doc1b, doc2, doc3)).get()\n            assertEquals(4, deleteMany(Document()).get()!!.deletedCount)             // delete all\n            assertEquals(0, count().get())\n        }\n    }\n\n    @Test\n    fun deleteMany_fails() {\n        with(getCollectionInternal()) {\n            assertFailsWithErrorCode(ErrorCode.MONGODB_ERROR) {\n                deleteMany(Document(\"\\$who\", 1)).get()\n            }.also { e ->\n                assertTrue(e.errorMessage!!.contains(\"operator\", true))\n            }\n        }\n    }\n\n    @Test\n    fun updateOne_emptyCollection() {\n        with(getCollectionInternal()) {\n            val doc1 = Document(\"hello\", \"world\")\n\n            // Update on an empty collection\n            updateOne(Document(), doc1)\n                    .get()!!\n                    .let {\n                        assertEquals(0, it.matchedCount)\n                        assertEquals(0, it.modifiedCount)\n                        assertNull(it.upsertedId)\n                    }\n\n            // Update on an empty collection adding some values\n            val doc2 = Document(\"\\$set\", Document(\"woof\", \"meow\"))\n            updateOne(Document(), doc2)\n                    .get()!!\n                    .let {\n                        assertEquals(0, it.matchedCount)\n                        assertEquals(0, it.modifiedCount)\n                        assertNull(it.upsertedId)\n                        assertEquals(0, count().get())\n                    }\n        }\n    }\n\n    @Test\n    fun updateOne_emptyCollectionWithUpsert() {\n        with(getCollectionInternal()) {\n            val doc1 = Document(\"hello\", \"world\")\n\n            // Update on empty collection with upsert\n            val options = UpdateOptions().upsert(true)\n            updateOne(Document(), doc1, options)\n                    .get()!!\n                    .let {\n                        assertEquals(0, it.matchedCount)\n                        assertEquals(0, it.modifiedCount)\n                        assertFalse(it.upsertedId!!.isNull)\n                    }\n            assertEquals(1, count().get())\n\n            assertEquals(doc1, find(Document()).first().get()!!.withoutId())\n        }\n    }\n\n    @Test\n    fun updateOne_fails() {\n        with(getCollectionInternal()) {\n            assertFailsWithErrorCode(ErrorCode.MONGODB_ERROR) {\n                updateOne(Document(\"\\$who\", 1), Document()).get()\n            }.also { e ->\n                assertTrue(e.errorMessage!!.contains(\"operator\", true))\n            }\n        }\n    }\n\n    @Test\n    fun updateMany_emptyCollection() {\n        with(getCollectionInternal()) {\n            val doc1 = Document(\"hello\", \"world\")\n\n            // Update on empty collection\n            updateMany(Document(), doc1)\n                    .get()!!\n                    .let {\n                        assertEquals(0, it.matchedCount)\n                        assertEquals(0, it.modifiedCount)\n                        assertNull(it.upsertedId)\n                    }\n            assertEquals(0, count().get())\n        }\n    }\n\n    @Test\n    fun updateMany_emptyCollectionWithUpsert() {\n        with(getCollectionInternal()) {\n            val doc1 = Document(\"hello\", \"world\")\n\n            // Update on empty collection with upsert\n            updateMany(Document(), doc1, UpdateOptions().upsert(true))\n                    .get()!!\n                    .let {\n                        assertEquals(0, it.matchedCount)\n                        assertEquals(0, it.modifiedCount)\n                        assertNotNull(it.upsertedId)\n                    }\n            assertEquals(1, count().get())\n\n            // Add new value using update\n            val update = Document(\"woof\", \"meow\")\n            updateMany(Document(), Document(\"\\$set\", update))\n                    .get()!!\n                    .let {\n                        assertEquals(1, it.matchedCount)\n                        assertEquals(1, it.modifiedCount)\n                        assertNull(it.upsertedId)\n                    }\n            assertEquals(1, count().get())\n            val expected = Document(doc1).apply { this[\"woof\"] = \"meow\" }\n            assertEquals(expected, find().first().get()!!.withoutId())\n\n            // Insert empty document, add [\"woof\", \"meow\"] to it and check it worked\n            insertOne(Document()).get()\n            updateMany(Document(), Document(\"\\$set\", update))\n                    .get()!!\n                    .let {\n                        assertEquals(2, it.matchedCount)\n                        assertEquals(2, it.modifiedCount)\n                    }\n            assertEquals(2, count().get())\n            find().iterator()\n                    .get()!!\n                    .let {\n                        assertEquals(expected, it.next().withoutId())\n                        assertEquals(update, it.next().withoutId())\n                        assertFalse(it.hasNext())\n                    }\n        }\n    }\n\n    @Test\n    fun updateMany_fails() {\n        with(getCollectionInternal()) {\n            assertFailsWithErrorCode(ErrorCode.MONGODB_ERROR) {\n                updateMany(Document(\"\\$who\", 1), Document()).get()\n            }.also { e ->\n                assertTrue(e.errorMessage!!.contains(\"operator\", true))\n            }\n        }\n    }\n\n    @Test\n    fun findOneAndUpdate_emptyCollection() {\n        with(getCollectionInternal()) {\n            // Test null return format\n            assertNull(findOneAndUpdate(Document(), Document()).get())\n        }\n    }\n\n    @Test\n    fun findOneAndUpdate_noUpdates() {\n        with(getCollectionInternal()) {\n            assertNull(findOneAndUpdate(Document(), Document()).get())\n            assertEquals(0, count().get())\n        }\n    }\n\n    @Test\n    fun findOneAndUpdate_noUpsert() {\n        with(getCollectionInternal()) {\n            val sampleDoc = Document(\"hello\", \"world1\")\n            sampleDoc[\"num\"] = 2\n\n            // Insert a sample Document\n            insertOne(sampleDoc).get()\n            assertEquals(1, count().get())\n\n            // Sample call to findOneAndUpdate() where we get the previous document back\n            val sampleUpdate = Document(\"\\$set\", Document(\"hello\", \"hellothere\")).apply {\n                this[\"\\$inc\"] = Document(\"num\", 1)\n            }\n            findOneAndUpdate(Document(\"hello\", \"world1\"), sampleUpdate)\n                    .get()!!\n                    .withoutId()\n                    .let {\n                        assertEquals(sampleDoc.withoutId(), it)\n                    }\n            assertEquals(1, count().get())\n\n            // Make sure the update took place\n            val expectedDoc = Document(\"hello\", \"hellothere\")\n            expectedDoc[\"num\"] = 3\n            assertEquals(expectedDoc.withoutId(), find().first().get()!!.withoutId())\n            assertEquals(1, count().get())\n\n            // Call findOneAndUpdate() again but get the new document\n            sampleUpdate.remove(\"\\$set\")\n            expectedDoc[\"num\"] = 4\n            val options = FindOneAndModifyOptions()\n                    .returnNewDocument(true)\n            findOneAndUpdate(Document(\"hello\", \"hellothere\"), sampleUpdate, options)\n                    .get()!!\n                    .withoutId()\n                    .let {\n                        assertEquals(expectedDoc.withoutId(), it)\n                    }\n            assertEquals(1, count().get())\n\n            // Test null behaviour again with a filter that should not match any documents\n            assertNull(findOneAndUpdate(Document(\"hello\", \"zzzzz\"), Document()).get())\n            assertEquals(1, count().get())\n        }\n    }\n\n    @Test\n    fun findOneAndUpdate_upsert() {\n        with(getCollectionInternal()) {\n            val doc1 = Document(\"hello\", \"world1\").apply { this[\"num\"] = 1 }\n            val doc2 = Document(\"hello\", \"world2\").apply { this[\"num\"] = 2 }\n            val doc3 = Document(\"hello\", \"world3\").apply { this[\"num\"] = 3 }\n\n            val filter = Document(\"hello\", \"hellothere\")\n\n            // Test the upsert option where it should not actually be invoked\n            var options = FindOneAndModifyOptions()\n                    .returnNewDocument(true)\n                    .upsert(true)\n            val update1 = Document(\"\\$set\", doc1)\n            assertEquals(doc1,\n                    findOneAndUpdate(filter, update1, options)\n                            .get()!!\n                            .withoutId())\n            assertEquals(1, count().get())\n            assertEquals(doc1.withoutId(),\n                    find().first()\n                            .get()!!\n                            .withoutId())\n\n            // Test the upsert option where the server should perform upsert and return new document\n            val update2 = Document(\"\\$set\", doc2)\n            assertEquals(doc2,\n                    findOneAndUpdate(filter, update2, options)\n                            .get()!!\n                            .withoutId())\n            assertEquals(2, count().get())\n\n            // Test the upsert option where the server should perform upsert and return old document\n            // The old document should be empty\n            options = FindOneAndModifyOptions()\n                    .upsert(true)\n            val update = Document(\"\\$set\", doc3)\n            assertNull(findOneAndUpdate(filter, update, options).get())\n            assertEquals(3, count().get())\n        }\n    }\n\n    @Test\n    fun findOneAndUpdate_withProjectionAndSort() {\n        with(getCollectionInternal()) {\n            insertMany(listOf(\n                    Document(mapOf(Pair(\"team\", \"Fearful Mallards\"), Pair(\"score\", 25000))),\n                    Document(mapOf(Pair(\"team\", \"Tactful Mooses\"), Pair(\"score\", 23500))),\n                    Document(mapOf(Pair(\"team\", \"Aquatic Ponies\"), Pair(\"score\", 19250))),\n                    Document(mapOf(Pair(\"team\", \"Cuddly Zebras\"), Pair(\"score\", 15235))),\n                    Document(mapOf(Pair(\"team\", \"Garrulous Bears\"), Pair(\"score\", 18000)))\n            )).get()\n\n            assertEquals(5, count().get())\n            assertNotNull(findOne(Document(\"team\", \"Cuddly Zebras\")))\n\n            // Project: team, hide _id; Sort: score ascending\n            val project = Document(mapOf(Pair(\"_id\", 0), Pair(\"team\", 1), Pair(\"score\", 1)))\n            val sort = Document(\"score\", 1)\n\n            // This results in the update of Cuddly Zebras\n            val updatedDocument = findOneAndUpdate(\n                    Document(\"score\", Document(\"\\$lt\", 22250)),\n                    Document(\"\\$inc\", Document(\"score\", 1)),\n                    FindOneAndModifyOptions()\n                            .projection(project)\n                            .sort(sort)\n            ).get()\n\n            assertEquals(5, count().get())\n            assertEquals(\n                    Document(mapOf(Pair(\"team\", \"Cuddly Zebras\"), Pair(\"score\", 15235))),\n                    updatedDocument\n            )\n            assertEquals(\n                    Document(mapOf(Pair(\"team\", \"Cuddly Zebras\"), Pair(\"score\", 15235 + 1))),\n                    findOne(Document(\"team\", \"Cuddly Zebras\")).get().withoutId()\n            )\n        }\n    }\n\n    @Test\n    fun findOneAndUpdate_fails() {\n        with(getCollectionInternal()) {\n            assertFailsWithErrorCode(ErrorCode.MONGODB_ERROR) {\n                findOneAndUpdate(Document(), Document(\"\\$who\", 1)).get()\n            }.also { e ->\n                assertTrue(e.errorMessage!!.contains(\"modifier\", true))\n            }\n\n            assertFailsWithErrorCode(ErrorCode.MONGODB_ERROR) {\n                findOneAndUpdate(Document(), Document(\"\\$who\", 1), FindOneAndModifyOptions().upsert(true)).get()\n            }.also { e ->\n                assertTrue(e.errorMessage!!.contains(\"modifier\", true))\n            }\n        }\n    }\n\n    @Test\n    fun findOneAndReplace_noUpdates() {\n        with(getCollectionInternal()) {\n            // Test null behaviour again with a filter that should not match any documents\n            assertNull(findOneAndReplace(Document(\"hello\", \"zzzzz\"), Document()).get())\n            assertEquals(0, count().get())\n            assertNull(findOneAndReplace(Document(), Document()).get())\n            assertEquals(0, count().get())\n        }\n    }\n\n    @Test\n    fun findOneAndReplace_noUpsert() {\n        with(getCollectionInternal()) {\n            val sampleDoc = Document(\"hello\", \"world1\").apply { this[\"num\"] = 2 }\n\n            // Insert a sample Document\n            insertOne(sampleDoc).get()\n            assertEquals(1, count().get())\n\n            // Sample call to findOneAndReplace() where we get the previous document back\n            var sampleUpdate = Document(\"hello\", \"world2\").apply { this[\"num\"] = 2 }\n            assertEquals(sampleDoc.withoutId(),\n                    findOneAndReplace(Document(\"hello\", \"world1\"), sampleUpdate).get()!!.withoutId())\n            assertEquals(1, count().get())\n\n            // Make sure the update took place\n            val expectedDoc = Document(\"hello\", \"world2\").apply { this[\"num\"] = 2 }\n            assertEquals(expectedDoc.withoutId(), find().first().get()!!.withoutId())\n            assertEquals(1, count().get())\n\n            // Call findOneAndReplace() again but get the new document\n            sampleUpdate = Document(\"hello\", \"world3\").apply { this[\"num\"] = 3 }\n            val options = FindOneAndModifyOptions().returnNewDocument(true)\n            assertEquals(sampleUpdate.withoutId(),\n                    findOneAndReplace(Document(), sampleUpdate, options).get()!!.withoutId())\n            assertEquals(1, count().get())\n\n            // Test null behaviour again with a filter that should not match any documents\n            assertNull(findOneAndReplace(Document(\"hello\", \"zzzzz\"), Document()).get())\n            assertEquals(1, count().get())\n        }\n    }\n\n    @Test\n    fun findOneAndReplace_upsert() {\n        with(getCollectionInternal()) {\n            val doc4 = Document(\"hello\", \"world4\").apply { this[\"num\"] = 4 }\n            val doc5 = Document(\"hello\", \"world5\").apply { this[\"num\"] = 5 }\n            val doc6 = Document(\"hello\", \"world6\").apply { this[\"num\"] = 6 }\n\n            // Test the upsert option where it should not actually be invoked\n            val sampleUpdate = Document(\"hello\", \"world4\").apply { this[\"num\"] = 4 }\n            var options = FindOneAndModifyOptions()\n                    .returnNewDocument(true)\n                    .upsert(true)\n            assertEquals(doc4.withoutId(),\n                    findOneAndReplace(Document(\"hello\", \"world3\"), doc4, options)\n                            .get()!!\n                            .withoutId())\n            assertEquals(1, count().get())\n            assertEquals(doc4.withoutId(), find().first().get()!!.withoutId())\n\n            // Test the upsert option where the server should perform upsert and return new document\n            options = FindOneAndModifyOptions().returnNewDocument(true).upsert(true)\n            assertEquals(doc5.withoutId(), findOneAndReplace(Document(\"hello\", \"hellothere\"), doc5, options).get()!!.withoutId())\n            assertEquals(2, count().get())\n\n            // Test the upsert option where the server should perform upsert and return old document\n            // The old document should be empty\n            options = FindOneAndModifyOptions().upsert(true)\n            assertNull(findOneAndReplace(Document(\"hello\", \"hellothere\"), doc6, options).get())\n            assertEquals(3, count().get())\n        }\n    }\n\n    @Test\n    fun findOneAndReplace_withProjectionAndSort() {\n        with(getCollectionInternal()) {\n            insertMany(listOf(\n                    Document(mapOf(Pair(\"team\", \"Fearful Mallards\"), Pair(\"score\", 25000))),\n                    Document(mapOf(Pair(\"team\", \"Tactful Mooses\"), Pair(\"score\", 23500))),\n                    Document(mapOf(Pair(\"team\", \"Aquatic Ponies\"), Pair(\"score\", 19250))),\n                    Document(mapOf(Pair(\"team\", \"Cuddly Zebras\"), Pair(\"score\", 15235))),\n                    Document(mapOf(Pair(\"team\", \"Garrulous Bears\"), Pair(\"score\", 18000)))\n            )).get()\n\n            assertEquals(5, count().get())\n            assertNotNull(findOne(Document(\"team\", \"Cuddly Zebras\")))\n\n            // Project: team, hide _id; Sort: score ascending\n            val project = Document(mapOf(Pair(\"_id\", 0), Pair(\"team\", 1)))\n            val sort = Document(\"score\", 1)\n\n            // This results in the replacement of Cuddly Zebras\n            val replacedDocument = findOneAndReplace(\n                    Document(\"score\", Document(\"\\$lt\", 22250)),\n                    Document(mapOf(Pair(\"team\", \"Therapeutic Hamsters\"), Pair(\"score\", 22250))),\n                    FindOneAndModifyOptions()\n                            .projection(project)\n                            .sort(sort)\n            ).get()\n\n            assertEquals(5, count().get())\n            assertEquals(Document(\"team\", \"Cuddly Zebras\"), replacedDocument)\n            assertNull(findOne(Document(\"team\", \"Cuddly Zebras\")).get())\n            assertNotNull(findOne(Document(\"team\", \"Therapeutic Hamsters\")).get())\n\n            // Check returnNewDocument\n            val newDocument = findOneAndReplace(\n                    Document(\"score\", 22250),\n                    Document(mapOf(Pair(\"team\", \"New Therapeutic Hamsters\"), Pair(\"score\", 30000))),\n                    FindOneAndModifyOptions().returnNewDocument(true)\n            ).get()\n\n            assertEquals(Document(mapOf(Pair(\"team\", \"New Therapeutic Hamsters\"), Pair(\"score\", 30000))), newDocument.withoutId())\n        }\n    }\n\n    @Test\n    fun findOneAndReplace_fails() {\n        with(getCollectionInternal()) {\n            assertFailsWithErrorCode(ErrorCode.INVALID_PARAMETER) {\n                findOneAndReplace(Document(), Document(\"\\$who\", 1)).get()\n            }\n\n            assertFailsWithErrorCode(ErrorCode.INVALID_PARAMETER) {\n                findOneAndReplace(Document(), Document(\"\\$who\", 1), FindOneAndModifyOptions().upsert(true)).get()\n            }\n        }\n    }\n\n    private fun assertDocumentEquals(expected: Document, actual: Document) {\n        // Accounts for the missing _id field in the expected document\n        assertTrue {\n            actual.remove(\"_id\") != null\n        }\n\n        assertEquals(expected.keys.size, actual.keys.size)\n\n        for (key in expected.keys) {\n            assertTrue(actual.keys.contains(key))\n            assertEquals(expected[key], actual[key])\n        }\n    }\n\n    @Test\n    fun watchStreamSynchronous() {\n        with(getCollectionInternal()) {\n            val insertedDocument = Document(\"watch\", \"1\")\n                    .apply {\n                        this[\"num\"] = 1\n                    }\n\n            val updatedDocument = Document(\"watch\", \"1\")\n                    .apply {\n                        this[\"num\"] = 2\n                    }\n\n\n            val watcher = this.watch()\n\n            val condition = looperThread.runDetached {\n                watcher.next.let { changeEvent ->\n                    assertEquals(OperationType.INSERT, changeEvent.operationType)\n                    assertDocumentEquals(insertedDocument, changeEvent.fullDocument!!)\n                }\n\n                watcher.next.let { changeEvent ->\n                    assertEquals(OperationType.REPLACE, changeEvent.operationType)\n                    assertDocumentEquals(updatedDocument, changeEvent.fullDocument!!)\n                }\n\n                watcher.next.let { changeEvent ->\n                    assertEquals(OperationType.DELETE, changeEvent.operationType)\n                    assertNull(changeEvent.fullDocument)\n                }\n\n                looperThread.testComplete()\n            }\n\n            // Busy wait till watcher is ready to receive updates.\n            // It syncs the event producer thread (current thread) with\n            // the event consumer thread.\n            while (!watcher.isOpen) {\n            }\n\n            this.insertOne(insertedDocument).get()\n\n            val filter = Document(\"watch\", \"1\")\n            this.updateOne(filter, updatedDocument).get()\n            this.deleteOne(filter).get()\n\n            condition.await()\n        }\n    }\n\n    @Test\n    fun watchStreamDocumentsFilterSynchronous() {\n        with(getCollectionInternal()) {\n            val type1 = Document(\"type\", \"1\")\n                    .apply {\n                        this[\"num\"] = 1\n                    }\n\n            val type2 = Document(\"type\", \"2\")\n                    .apply {\n                        this[\"num\"] = 1\n                    }\n\n            val filter = Document(\"fullDocument.type\", \"1\")\n            val watcher = this.watchWithFilter(filter)\n\n            val condition = looperThread.runDetached {\n                watcher.next.let { changeEvent ->\n                    assertEquals(OperationType.INSERT, changeEvent.operationType)\n                    assertEquals(\"1\", changeEvent.fullDocument!![\"type\"])\n                }\n\n                watcher.cancel()\n                looperThread.testComplete()\n            }\n\n            // Busy wait till watcher is ready to receive updates.\n            // It syncs the event producer thread (current thread) with\n            // the event consumer thread.\n            while (!watcher.isOpen) {\n            }\n\n            this.insertOne(type2).get()\n            this.insertOne(type1).get()\n\n            condition.await()\n        }\n    }\n\n    @Test\n    fun watchStreamBsonDocumentFilterSynchronous() {\n        with(getCollectionInternal()) {\n            val type1 = Document(\"type\", \"1\")\n                    .apply {\n                        this[\"num\"] = 1\n                    }\n\n            val type2 = Document(\"type\", \"2\")\n                    .apply {\n                        this[\"num\"] = 1\n                    }\n\n            val filter = BsonDocument(\"fullDocument.type\", BsonString(\"1\"))\n            val watcher = this.watchWithFilter(filter)\n\n            val condition = looperThread.runDetached {\n                watcher.next.let { changeEvent ->\n                    assertEquals(OperationType.INSERT, changeEvent.operationType)\n                    assertEquals(\"1\", changeEvent.fullDocument!![\"type\"])\n                }\n\n                watcher.cancel()\n                looperThread.testComplete()\n\n            }\n\n            // Busy wait till watcher is ready to receive updates.\n            // It syncs the event producer thread (current thread) with\n            // the event consumer thread.\n            while (!watcher.isOpen) {\n            }\n\n            this.insertOne(type2).get()\n            this.insertOne(type1).get()\n\n            condition.await()\n        }\n    }\n\n    @Test\n    fun watchStreamObjectIdsSynchronous() {\n        with(getCollectionInternal()) {\n            val doc1 = Document(\"document\", \"1\")\n                    .apply {\n                        this[\"num\"] = 1\n                    }\n\n            val doc2 = Document(\"document\", \"2\")\n                    .apply {\n                        this[\"num\"] = 1\n                    }\n\n            val doc1Id = this.insertOne(doc1).get()\n            val doc2Id = this.insertOne(doc2).get()\n\n            val watcherObjectId = this.watch(doc1Id.insertedId.asObjectId().value)\n\n            val condition = looperThread.runDetached {\n                watcherObjectId.next.let { changeEvent ->\n                    assertEquals(OperationType.REPLACE, changeEvent.operationType)\n                    assertEquals(\"1\", changeEvent.fullDocument!![\"document\"])\n                }\n                watcherObjectId.cancel()\n\n                looperThread.testComplete()\n            }\n\n            // Busy wait till watcher is ready to receive updates.\n            // It syncs the event producer thread (current thread) with\n            // the event consumer thread.\n            while (!watcherObjectId.isOpen) {\n            }\n\n            doc1.apply {\n                this[\"num\"] = 2\n            }\n\n            doc2.apply {\n                this[\"num\"] = 2\n            }\n\n            val filter1 = Document(\"_id\", doc1Id.insertedId)\n            val filter2 = Document(\"_id\", doc2Id.insertedId)\n\n            this.updateOne(filter2, doc2).get()\n            this.updateOne(filter1, doc1).get()\n\n            condition.await()\n        }\n    }\n\n    @Test\n    fun watchStreamIdsSynchronous() {\n        with(getCollectionInternal()) {\n            val doc1 = Document(\"document\", \"1\")\n                    .apply {\n                        this[\"num\"] = 1\n                    }\n\n            val doc2 = Document(\"document\", \"2\")\n                    .apply {\n                        this[\"num\"] = 1\n                    }\n\n            val doc1Id = this.insertOne(doc1).get()\n            val doc2Id = this.insertOne(doc2).get()\n\n            val watcherBsonValue = this.watch(doc1Id.insertedId)\n\n            val condition = looperThread.runDetached {\n                watcherBsonValue.next.let { changeEvent ->\n                    assertEquals(OperationType.REPLACE, changeEvent.operationType)\n                    assertEquals(\"1\", changeEvent.fullDocument!![\"document\"])\n                }\n\n                watcherBsonValue.cancel()\n                looperThread.testComplete()\n            }\n\n            // Busy wait till watcher is ready to receive updates.\n            // It syncs the event producer thread (current thread) with\n            // the event consumer thread.\n            while (!watcherBsonValue.isOpen) {\n            }\n\n            doc1.apply {\n                this[\"num\"] = 2\n            }\n\n            doc2.apply {\n                this[\"num\"] = 2\n            }\n\n            val filter1 = Document(\"_id\", doc1Id.insertedId)\n            val filter2 = Document(\"_id\", doc2Id.insertedId)\n\n            this.updateOne(filter2, doc2).get()\n            this.updateOne(filter1, doc1).get()\n\n            condition.await()\n        }\n\n    }\n\n    @Test\n    fun watchStreamAsynchronous() {\n        looperThread.runBlocking {\n            with(getCollectionInternal()) {\n                val insertedDocument = Document(\"watch\", \"1\")\n                        .apply {\n                            this[\"num\"] = 1\n                        }\n\n                val updatedDocument = Document(\"watch\", \"1\")\n                        .apply {\n                            this[\"num\"] = 2\n                        }\n\n\n                val watcher = this.watchAsync()\n\n                var eventCount = 0\n                watcher.get { it ->\n                    if (it.isSuccess) {\n                        it.get().let { changeEvent ->\n                            when (eventCount) {\n                                0 -> {\n                                    assertEquals(OperationType.INSERT, changeEvent.operationType)\n                                    assertDocumentEquals(insertedDocument, changeEvent.fullDocument!!)\n                                }\n                                1 -> {\n                                    assertEquals(OperationType.REPLACE, changeEvent.operationType)\n                                    assertDocumentEquals(updatedDocument, changeEvent.fullDocument!!)\n                                }\n                                2 -> {\n                                    assertEquals(OperationType.DELETE, changeEvent.operationType)\n                                    assertNull(changeEvent.fullDocument)\n\n                                    watcher.cancel()\n                                }\n                            }\n                        }\n\n                        eventCount++\n                    } else {\n                        when (it.error.errorCode) {\n                            ErrorCode.NETWORK_IO_EXCEPTION -> looperThread.testComplete()\n                            else -> fail()\n                        }\n                        looperThread.testComplete()\n                    }\n                }\n\n                // Busy wait till watcher is ready to receive updates.\n                // It syncs the event producer thread (current thread) with\n                // the event consumer thread.\n                while (!watcher.isOpen) {\n                }\n\n                this.insertOne(insertedDocument).get()\n\n                val filter = Document(\"watch\", \"1\")\n                this.updateOne(filter, updatedDocument).get()\n                this.deleteOne(filter).get()\n            }\n        }\n    }\n\n    @Test\n    fun watchStreamCancelSynchronous() {\n        with(getCollectionInternal()) {\n            val watcher = this.watch()\n\n            val condition = looperThread.runDetached {\n                assertFailsWith<IOException> {\n                    watcher.next\n                }\n\n                assertEquals(false, watcher.isOpen)\n                assertEquals(true, watcher.isCancelled)\n\n                looperThread.testComplete()\n            }\n\n            // Busy wait till watcher is ready to receive updates.\n            // It syncs the event producer thread (current thread) with\n            // the event consumer thread.\n            while (!watcher.isOpen) {\n            }\n\n            watcher.cancel()\n\n            condition.await()\n        }\n    }\n\n    @Test\n    fun watchStreamCancelAsynchronous() {\n        looperThread.runBlocking {\n            with(getCollectionInternal()) {\n                val watcher = this.watchAsync()\n\n                watcher.get {\n                    if (it.isSuccess) {\n                        fail()\n                    } else {\n                        assertEquals(ErrorCode.NETWORK_IO_EXCEPTION, it.error.errorCode)\n\n                        assertEquals(false, watcher.isOpen)\n                        assertEquals(true, watcher.isCancelled)\n\n                        looperThread.testComplete()\n                    }\n                }\n\n                // Busy wait till watcher is ready to receive updates.\n                // It syncs the event producer thread (current thread) with\n                // the event consumer thread.\n                while (!watcher.isOpen) {\n                }\n\n                watcher.cancel()\n            }\n        }\n    }\n\n    @Ignore(\"https://github.com/realm/realm-java/issues/7239\")\n    @Test\n    fun watchError() {\n        with(getCollectionInternal()) {\n            val watcher = this.watch()\n\n            // This should time out after 60 seconds with no events.\n            // This no longer seems to happen though as pr. https://github.com/realm/realm-java/issues/7239\n            // So we need to find another way to test this.\n            assertFailsWith<AppException> {\n                watcher.next\n            }\n\n            assertEquals(false, watcher.isOpen)\n            assertEquals(false, watcher.isCancelled)\n        }\n    }\n\n    @Test\n    fun findOneAndDelete() {\n        with(getCollectionInternal()) {\n            val sampleDoc = Document(\"hello\", \"world1\").apply { this[\"num\"] = 1 }\n\n            // Collection should start out empty\n            // This also tests the null return format\n            assertNull(findOneAndDelete(Document()).get())\n\n            // Insert a sample Document\n            insertOne(sampleDoc).get()\n            assertEquals(1, count().get())\n\n            // Sample call to findOneAndDelete() where we delete the only doc in the collection\n            assertEquals(sampleDoc.withoutId(),\n                    findOneAndDelete(Document()).get()!!.withoutId())\n\n            // There should be no documents in the collection now\n            assertEquals(0, count().get())\n\n            // Insert a sample Document\n            insertOne(sampleDoc).get()\n            assertEquals(1, count().get())\n\n            // Call findOneAndDelete() again but this time with a filter\n            assertEquals(sampleDoc.withoutId(),\n                    findOneAndDelete(Document(\"hello\", \"world1\")).get()!!.withoutId())\n\n            // There should be no documents in the collection now\n            assertEquals(0, count().get())\n\n            // Insert a sample Document\n            insertOne(sampleDoc).get()\n            assertEquals(1, count().get())\n\n            // Test null behaviour again with a filter that should not match any documents\n            assertNull(findOneAndDelete(Document(\"hello\", \"zzzzz\")).get())\n            assertEquals(1, count().get())\n\n            val doc2 = Document(\"hello\", \"world2\").apply { this[\"num\"] = 2 }\n            val doc3 = Document(\"hello\", \"world3\").apply { this[\"num\"] = 3 }\n\n            // Insert new documents\n            insertMany(listOf(doc2, doc3)).get()\n            assertEquals(3, count().get())\n        }\n    }\n\n    @Test\n    fun findOneAndDelete_withProjectionAndSort() {\n        with(getCollectionInternal()) {\n            insertMany(listOf(\n                    Document(mapOf(Pair(\"team\", \"Fearful Mallards\"), Pair(\"score\", 25000))),\n                    Document(mapOf(Pair(\"team\", \"Tactful Mooses\"), Pair(\"score\", 23500))),\n                    Document(mapOf(Pair(\"team\", \"Aquatic Ponies\"), Pair(\"score\", 19250))),\n                    Document(mapOf(Pair(\"team\", \"Cuddly Zebras\"), Pair(\"score\", 15235))),\n                    Document(mapOf(Pair(\"team\", \"Garrulous Bears\"), Pair(\"score\", 18000)))\n            )).get()\n\n            assertEquals(5, count().get())\n            assertNotNull(findOne(Document(\"team\", \"Cuddly Zebras\")))\n\n            // Project: team, hide _id; Sort: score ascending\n            val project = Document(mapOf(Pair(\"_id\", 0), Pair(\"team\", 1)))\n            val sort = Document(\"score\", 1)\n\n            // This results in the deletion of Cuddly Zebras\n            val deletedDocument = findOneAndDelete(\n                    Document(\"score\", Document(\"\\$lt\", 22250)),\n                    FindOneAndModifyOptions()\n                            .projection(project)\n                            .sort(sort)\n            ).get()\n\n            assertEquals(4, count().get())\n            assertEquals(Document(\"team\", \"Cuddly Zebras\"), deletedDocument.withoutId())\n            assertNull(findOne(Document(\"team\", \"Cuddly Zebras\")).get())\n        }\n    }\n\n    @Test\n    fun withDocument() {\n        // aAd default codecs as they too are needed for proper collection initialization\n        val expandedCodecRegistry = CodecRegistries\n                .fromRegistries(AppConfiguration.DEFAULT_BSON_CODEC_REGISTRY,\n                        CodecRegistries.fromCodecs(CustomType.Codec()))\n\n        val expected = CustomType(ObjectId(), 42)\n\n        // Get default collection\n        with(getCollectionInternal()) {\n            // Now specify custom class\n            var coll = withDocumentClass(CustomType::class.java)\n            assertEquals(CustomType::class.java, coll.documentClass)\n\n            assertFailsWith(AppException::class) {\n                coll.insertOne(expected).get()\n            }\n\n            val defaultCodecRegistry = AppConfiguration.DEFAULT_BSON_CODEC_REGISTRY\n            assertEquals(defaultCodecRegistry, coll.codecRegistry)\n\n            // Use expanded registry\n            coll = coll.withCodecRegistry(expandedCodecRegistry)\n            assertEquals(expected.id,\n                    coll.insertOne(expected).get()!!.insertedId.asObjectId().value)\n            assertEquals(expected, coll.find().first().get())\n        }\n\n        val expected2 = CustomType(null, 42)\n\n        // Now get new collection for CustomType\n        with(getCollectionInternal(CustomType::class.java)\n                .withCodecRegistry(expandedCodecRegistry)) {\n            insertOne(expected2).get()!!\n            val actual: CustomType = find().first().get()!!\n            assertEquals(expected2.intValue, actual.intValue)\n        }\n\n        with(getCollectionInternal(CustomType::class.java)\n                .withCodecRegistry(expandedCodecRegistry)) {\n            val actual: CustomType = find(Document(), CustomType::class.java)\n                    .first()\n                    .get()!!\n            assertEquals(expected2.intValue, actual.intValue)\n            assertNotNull(expected.id)\n\n            val iter = aggregate(listOf(Document(\"\\$match\", Document())), CustomType::class.java)\n            assertTrue(iter.iterator().get()!!.hasNext())\n            assertEquals(expected, iter.iterator().get()!!.next())\n        }\n    }\n\n    @Test\n    fun getMongoClientServiceName() {\n        assertNotNull(client.serviceName)\n        assertEquals(SERVICE_NAME, client.serviceName)\n    }\n\n    @Test\n    fun getCollectionName() {\n        with(getCollectionInternal()) {\n            assertNotNull(this)\n            assertEquals(COLLECTION_NAME, this.name)\n        }\n    }\n\n    private fun getCollectionInternal(\n            collectionName: String = COLLECTION_NAME\n    ): MongoCollection<Document> {\n        return client.getDatabase(DATABASE_NAME).let {\n            assertEquals(it.name, DATABASE_NAME)\n            it.getCollection(collectionName).also { collection ->\n                assertEquals(MongoNamespace(DATABASE_NAME, collectionName), collection.namespace)\n            }\n        }\n    }\n\n    private fun <ResultT> getCollectionInternal(\n            resultClass: Class<ResultT>,\n            collectionName: String = COLLECTION_NAME\n    ): MongoCollection<ResultT> {\n        return client.getDatabase(DATABASE_NAME).let {\n            assertEquals(it.name, DATABASE_NAME)\n            it.getCollection(collectionName, resultClass).also { collection ->\n                assertEquals(MongoNamespace(DATABASE_NAME, collectionName), collection.namespace)\n            }\n        }\n    }\n\n    private fun Document.withId(objectId: ObjectId? = null): Document {\n        return apply { this[\"_id\"] = objectId ?: ObjectId() }\n    }\n\n    private fun Document.withoutId(): Document {\n        return apply { remove(\"_id\") }\n    }\n\n    private fun List<Document>.withoutIds(): List<Document> {\n        return apply { map { it.withoutId() } }\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTestObjectServer/kotlin/io/realm/mongodb/UserTests.kt",
    "content": "/*\n * Copyright 2020 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 */\npackage io.realm.mongodb\n\nimport androidx.test.ext.junit.runners.AndroidJUnit4\nimport androidx.test.platform.app.InstrumentationRegistry\nimport io.realm.*\nimport io.realm.admin.ServerAdmin\nimport io.realm.mongodb.auth.ApiKey\nimport io.realm.mongodb.auth.ApiKeyAuth\nimport io.realm.rule.BlockingLooperThread\nimport org.bson.Document\nimport org.junit.After\nimport org.junit.Assert.*\nimport org.junit.Before\nimport org.junit.Ignore\nimport org.junit.Test\nimport org.junit.runner.RunWith\nimport kotlin.test.assertContains\nimport kotlin.test.assertFails\nimport kotlin.test.assertFailsWith\n\nval CUSTOM_USER_DATA_FIELD = \"custom_field\"\nval CUSTOM_USER_DATA_VALUE = \"custom_data\"\n\n@RunWith(AndroidJUnit4::class)\nclass UserTests {\n\n    val looperThread = BlockingLooperThread()\n\n    private lateinit var app: App\n    private lateinit var anonUser: User\n    private lateinit var admin: ServerAdmin\n\n    @Before\n    fun setUp() {\n        Realm.init(InstrumentationRegistry.getInstrumentation().targetContext)\n        app = TestApp()\n        admin = ServerAdmin(app)\n        anonUser = app.login(Credentials.anonymous())\n    }\n\n    @After\n    fun tearDown() {\n        if (this::app.isInitialized) {\n            app.close()\n        }\n    }\n\n    @Test\n    fun getApp() {\n        assertEquals(app, anonUser.app)\n    }\n\n    @Test\n    fun getState_anonymousUser() {\n        assertEquals(User.State.LOGGED_IN, anonUser.state)\n        anonUser.logOut()\n        assertEquals(User.State.REMOVED, anonUser.state)\n    }\n\n    @Test\n    fun getState_emailUser() {\n        val emailUser = app.registerUserAndLogin(TestHelper.getRandomEmail(), \"123456\")\n        assertEquals(User.State.LOGGED_IN, emailUser.state)\n        emailUser.logOut()\n        assertEquals(User.State.LOGGED_OUT, emailUser.state)\n        app.removeUser(emailUser)\n        assertEquals(User.State.REMOVED, emailUser.state)\n    }\n\n    @Test\n    fun logOut() {\n        // Anonymous users are removed upon log out\n        assertEquals(anonUser, app.currentUser())\n        anonUser.logOut()\n        assertEquals(User.State.REMOVED, anonUser.state)\n        assertNull(app.currentUser())\n\n        // Users registered with Email/Password will register as Logged Out\n        val user2: User = app.registerUserAndLogin(TestHelper.getRandomEmail(), \"123456\")\n        val current: User = app.currentUser()!!\n        assertEquals(user2, current)\n        user2.logOut()\n        assertEquals(User.State.LOGGED_OUT, user2.state)\n        // Same effect on all instances\n        assertEquals(User.State.LOGGED_OUT, current.state)\n        // And no current user anymore\n        assertNull(app.currentUser())\n    }\n\n    @Test\n    fun logOutAsync() = looperThread.runBlocking {\n        assertEquals(anonUser, app.currentUser())\n        anonUser.logOutAsync() { result ->\n            val callbackUser: User = result.orThrow\n            assertNull(app.currentUser())\n            assertEquals(anonUser, callbackUser)\n            assertEquals(User.State.REMOVED, anonUser.state)\n            assertEquals(User.State.REMOVED, callbackUser.state)\n            looperThread.testComplete()\n        }\n    }\n\n    @Test\n    fun logOutUserInstanceImpactsCurrentUser() {\n        val currentUser = app.currentUser()!!\n        assertEquals(User.State.LOGGED_IN, currentUser.state)\n        assertEquals(User.State.LOGGED_IN, anonUser.state)\n        assertEquals(currentUser, anonUser)\n\n        anonUser!!.logOut()\n\n        assertNotEquals(User.State.LOGGED_OUT, currentUser.state)\n        assertNotEquals(User.State.LOGGED_OUT, anonUser.state)\n        assertNull(app.currentUser())\n    }\n\n    @Test\n    fun logOutCurrentUserImpactsOtherInstances() {\n        val currentUser = app.currentUser()!!\n        assertEquals(User.State.LOGGED_IN, currentUser.state)\n        assertEquals(User.State.LOGGED_IN, anonUser.state)\n        assertEquals(currentUser, anonUser)\n\n        currentUser!!.logOut()\n\n        assertNotEquals(User.State.LOGGED_OUT, currentUser.state)\n        assertNotEquals(User.State.LOGGED_OUT, anonUser.state)\n        assertNull(app.currentUser())\n    }\n\n    @Test\n    fun repeatedLogInAndOut() {\n        val password = \"123456\"\n        val initialUser = app.registerUserAndLogin(TestHelper.getRandomEmail(), password)\n        assertEquals(User.State.LOGGED_IN, initialUser.state)\n        initialUser.logOut()\n        assertEquals(User.State.LOGGED_OUT, initialUser.state)\n\n        repeat(3) {\n            val user = app.login(Credentials.emailPassword(initialUser.profile.email, password))\n            assertEquals(User.State.LOGGED_IN, user.state)\n            user.logOut()\n            assertEquals(User.State.LOGGED_OUT, user.state)\n        }\n    }\n\n    @Test\n    fun logOutAsync_throwsOnNonLooperThread() {\n        try {\n            anonUser.logOutAsync { fail() }\n            fail()\n        } catch (ignore: IllegalStateException) {\n        }\n    }\n\n    @Test\n    fun linkUser_emailPassword() {\n        assertEquals(1, anonUser.identities.size)\n\n        val email = TestHelper.getRandomEmail()\n        val password = \"123456\"\n        app.emailPassword.registerUser(email, password) // TODO: Test what happens if auto-confirm is enabled\n        var linkedUser: User = anonUser.linkCredentials(Credentials.emailPassword(email, password))\n\n        assertTrue(anonUser === linkedUser)\n        assertEquals(2, linkedUser.identities.size)\n        assertEquals(Credentials.Provider.EMAIL_PASSWORD, linkedUser.identities[1].provider)\n\n        // Validate that we cannot link a second set of credentials\n        val otherEmail = TestHelper.getRandomEmail()\n        val otherPassword = \"123456\"\n        app.emailPassword.registerUser(otherEmail, otherPassword)\n\n        val credentials = Credentials.emailPassword(otherEmail, otherPassword)\n\n        assertFails {\n            linkedUser = anonUser.linkCredentials(credentials)\n        }\n    }\n\n    @Test\n    fun linkUser_userApiKey() {\n        // Generate API key\n        val user: User = app.registerUserAndLogin(TestHelper.getRandomEmail(), \"123456\")\n        val apiKey: ApiKey = user.apiKeys.create(\"my-key\");\n        user.logOut()\n\n        anonUser = app.login(Credentials.anonymous())\n\n        assertEquals(1, anonUser.identities.size)\n\n        // Linking with another user's API key is not allowed and must raise an AppException\n        val exception = assertFailsWith<AppException> {\n            anonUser.linkCredentials(Credentials.apiKey(apiKey.value))\n        }\n\n        assertContains(exception.errorMessage!!, \"invalid user link request\");\n        assertEquals(ErrorCode.Category.FATAL, exception.errorCode.category);\n        assertEquals(\"realm::app::ServiceError\", exception.errorCode.type);\n        assertEquals(ErrorCode.INVALID_PARAMETER, exception.errorCode);\n    }\n\n    @Test\n    fun linkUser_customFunction() {\n        assertEquals(1, anonUser.identities.size)\n\n        val document = Document(mapOf(\n                \"mail\" to TestHelper.getRandomEmail(),\n                \"id\" to TestHelper.getRandomId() + 666\n        ))\n\n        val credentials = Credentials.customFunction(document)\n\n        val linkedUser = anonUser.linkCredentials(credentials)\n\n        assertTrue(anonUser === linkedUser)\n        assertEquals(2, linkedUser.identities.size)\n        assertEquals(Credentials.Provider.CUSTOM_FUNCTION, linkedUser.identities[1].provider)\n    }\n\n    @Test\n    fun linkUser_existingCredentialsThrows() {\n        val email = TestHelper.getRandomEmail()\n        val password = \"123456\"\n        val emailUser: User = app.registerUserAndLogin(email, password)\n        try {\n            anonUser.linkCredentials(Credentials.emailPassword(email, password))\n            fail()\n        } catch (ex: AppException) {\n            assertEquals(ErrorCode.INVALID_SESSION, ex.errorCode)\n        }\n    }\n\n    @Test\n    fun linkUser_invalidArgsThrows() {\n        try {\n            anonUser.linkCredentials(TestHelper.getNull())\n            fail()\n        } catch (ignore: IllegalArgumentException) {\n        }\n    }\n\n    @Test\n    fun linkUserAsync() = looperThread.runBlocking {\n        assertEquals(1, anonUser.identities.size)\n        val email = TestHelper.getRandomEmail()\n        val password = \"123456\"\n        app.emailPassword.registerUser(email, password) // TODO: Test what happens if auto-confirm is enabled\n\n        anonUser.linkCredentialsAsync(Credentials.emailPassword(email, password)) { result ->\n            val linkedUser: User = result.orThrow\n            assertTrue(anonUser === linkedUser)\n            assertEquals(2, linkedUser.identities.size)\n            assertEquals(Credentials.Provider.EMAIL_PASSWORD, linkedUser.identities[1].provider)\n            looperThread.testComplete()\n        }\n    }\n\n    @Test\n    fun linkUserAsync_throwsOnNonLooperThread() {\n        try {\n            anonUser.linkCredentialsAsync(Credentials.emailPassword(TestHelper.getRandomEmail(), \"123456\")) { fail() }\n            fail()\n        } catch (ignore: java.lang.IllegalStateException) {\n        }\n    }\n\n    @Test\n    fun removeUser() {\n        anonUser.logOut() // Remove user used by other tests\n\n        // Removing logged in user\n        val user1 = app.registerUserAndLogin(TestHelper.getRandomEmail(), \"123456\")\n        assertEquals(user1, app.currentUser())\n        assertEquals(1, app.allUsers().size)\n        app.removeUser(user1)\n        assertEquals(User.State.REMOVED, user1.state)\n        assertNull(app.currentUser())\n        assertEquals(0, app.allUsers().size)\n\n        // Remove logged out user\n        val user2 = app.registerUserAndLogin(TestHelper.getRandomEmail(), \"123456\")\n        user2.logOut()\n        assertNull(app.currentUser())\n        assertEquals(1, app.allUsers().size)\n        app.removeUser(user2)\n        assertEquals(User.State.REMOVED, user2.state)\n        assertEquals(0, app.allUsers().size)\n    }\n\n    @Test\n    fun removeUserAsync() {\n        anonUser.logOut() // Remove user used by other tests\n\n        // Removing logged in user\n        looperThread.runBlocking {\n            val user = app.registerUserAndLogin(TestHelper.getRandomEmail(), \"123456\")\n            assertEquals(user, app.currentUser())\n            assertEquals(1, app.allUsers().size)\n            user.removeAsync { result ->\n                assertEquals(User.State.REMOVED, result.orThrow.state)\n                assertNull(app.currentUser())\n                assertEquals(0, app.allUsers().size)\n                looperThread.testComplete()\n            }\n        }\n\n        // Removing logged out user\n        looperThread.runBlocking {\n            val user = app.registerUserAndLogin(TestHelper.getRandomEmail(), \"123456\")\n            user.logOut()\n            assertNull(app.currentUser())\n            assertEquals(1, app.allUsers().size)\n            user.removeAsync { result ->\n                assertEquals(User.State.REMOVED, result.orThrow.state)\n                assertEquals(0, app.allUsers().size)\n                looperThread.testComplete()\n            }\n        }\n    }\n\n    @Test\n    fun removeUserAsync_nonLooperThreadThrows() {\n        val user: User = app.registerUserAndLogin(TestHelper.getRandomEmail(), \"1234567\")\n        try {\n            user.removeAsync { fail() }\n        } catch (ignore: IllegalStateException) {\n        }\n    }\n\n    @Test\n    fun getApiKeyAuthProvider() {\n        val user: User = app.registerUserAndLogin(TestHelper.getRandomEmail(), \"123456\")\n        val provider1: ApiKeyAuth = user.apiKeys\n        assertEquals(user, provider1.user)\n\n        user.logOut()\n\n        try {\n            user.apiKeys\n            fail()\n        } catch (ex: IllegalStateException) {\n        }\n    }\n\n    @Test\n    fun revokedRefreshTokenIsNotSameAfterLogin() = looperThread.runBlocking {\n        val password = \"password\"\n        val user = app.registerUserAndLogin(TestHelper.getRandomEmail(), password)\n        val refreshToken = user.refreshToken\n\n        app.addAuthenticationListener(object : AuthenticationListener {\n            override fun loggedIn(user: User) {}\n\n            override fun loggedOut(loggerOutUser: User) {\n                app.loginAsync(Credentials.emailPassword(loggerOutUser.profile.email, password)) {\n                    val loggedInUser = it.orThrow\n                    assertTrue(loggerOutUser !== loggedInUser)\n                    assertNotEquals(refreshToken, loggedInUser.refreshToken)\n                    looperThread.testComplete()\n                }\n            }\n        })\n        user.logOut()\n    }\n\n    fun isLoggedIn() {\n        var anonUser = app.login(Credentials.anonymous())\n        val user: User = app.registerUserAndLogin(TestHelper.getRandomEmail(), \"123456\")\n\n\n        assertTrue(anonUser.isLoggedIn)\n        assertTrue(user.isLoggedIn)\n\n        anonUser.logOut()\n        assertFalse(anonUser.isLoggedIn)\n        assertTrue(user.isLoggedIn)\n\n        user.logOut()\n        assertFalse(user.isLoggedIn)\n    }\n\n    @Test\n    fun equals() {\n        val user: User = app.registerUserAndLogin(TestHelper.getRandomEmail(), \"123456\")\n        assertEquals(user, user)\n        assertNotEquals(user, app)\n        user.logOut()\n\n        val sameUserNewLogin = app.login(Credentials.emailPassword(user.profile.email!!, \"123456\"))\n        // Verify that it is not same object but uses underlying OSSyncUser equality on identity\n        assertFalse(user === sameUserNewLogin)\n        assertEquals(user, sameUserNewLogin)\n\n        val differentUser: User = app.registerUserAndLogin(TestHelper.getRandomEmail(), \"123456\")\n        assertNotEquals(user, differentUser)\n    }\n\n    @Test\n    fun hashCode_user() {\n        val user: User = app.registerUserAndLogin(TestHelper.getRandomEmail(), \"123456\")\n        user.logOut()\n\n        val sameUserNewLogin = app.login(Credentials.emailPassword(user.profile.email!!, \"123456\"))\n        // Verify that two equal users also returns same hashCode\n        assertFalse(user === sameUserNewLogin)\n        assertEquals(user.hashCode(), sameUserNewLogin.hashCode())\n    }\n\n    @Test\n    fun customData_initiallyEmpty() {\n        val user = app.registerUserAndLogin(TestHelper.getRandomEmail(), \"123456\")\n        // Newly registered users do not have any custom data with current test server setup\n        assertEquals(Document(), user.customData)\n    }\n\n    @Test\n    fun customData_refresh() {\n        val user = app.registerUserAndLogin(TestHelper.getRandomEmail(), \"123456\")\n        // Newly registered users do not have any custom data with current test server setup\n        assertEquals(Document(), user.customData)\n\n        updateCustomData(user, Document(CUSTOM_USER_DATA_FIELD, CUSTOM_USER_DATA_VALUE))\n\n        val updatedCustomData = user.refreshCustomData()\n        assertEquals(CUSTOM_USER_DATA_VALUE, updatedCustomData[CUSTOM_USER_DATA_FIELD])\n        assertEquals(CUSTOM_USER_DATA_VALUE, user.customData[CUSTOM_USER_DATA_FIELD])\n    }\n\n    @Test\n    fun customData_refreshAsync() = looperThread.runBlocking {\n        val user = app.registerUserAndLogin(TestHelper.getRandomEmail(), \"123456\")\n        // Newly registered users do not have any custom data with current test server setup\n        assertEquals(Document(), user.customData)\n\n        updateCustomData(user, Document(CUSTOM_USER_DATA_FIELD, CUSTOM_USER_DATA_VALUE))\n\n        val updatedCustomData = user.refreshCustomData { result ->\n            val updatedCustomData = result.orThrow\n            assertEquals(CUSTOM_USER_DATA_VALUE, updatedCustomData[CUSTOM_USER_DATA_FIELD])\n            assertEquals(CUSTOM_USER_DATA_VALUE, user.customData[CUSTOM_USER_DATA_FIELD])\n            looperThread.testComplete()\n        }\n    }\n\n    @Test\n    fun customData_refreshByLogout() {\n        val password = \"123456\"\n        val user = app.registerUserAndLogin(TestHelper.getRandomEmail(), password)\n        // Newly registered users do not have any custom data with current test server setup\n        assertEquals(Document(), user.customData)\n\n        updateCustomData(user, Document(CUSTOM_USER_DATA_FIELD, CUSTOM_USER_DATA_VALUE))\n\n        // But will be updated when authorization token is refreshed\n        user.logOut()\n        app.login(Credentials.emailPassword(user.profile.email, password))\n        assertEquals(CUSTOM_USER_DATA_VALUE, user.customData.get(CUSTOM_USER_DATA_FIELD))\n    }\n\n    @Test\n    fun customData_refreshAsyncThrowsOnNonLooper() {\n        val password = \"123456\"\n        val user = app.registerUserAndLogin(TestHelper.getRandomEmail(), password)\n\n        assertFailsWith<java.lang.IllegalStateException> {\n            user.refreshCustomData { }\n        }\n    }\n\n    private fun updateCustomData(user: User, data: Document) {\n        // Name of collection and property used for storing custom user data. Must match server config.json\n        val COLLECTION_NAME = \"custom_user_data\"\n        val USER_ID_FIELD = \"userid\"\n\n        val client = user.getMongoClient(SERVICE_NAME)\n        client.getDatabase(DATABASE_NAME).let {\n            it.getCollection(COLLECTION_NAME).also { collection ->\n                collection.insertOne(data.append(USER_ID_FIELD, user.id)).get()\n            }\n        }\n    }\n\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTestObjectServer/kotlin/io/realm/mongodb/push/PushTest.kt",
    "content": "/*\n * Copyright 2020 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\npackage io.realm.mongodb.push\n\nimport androidx.test.ext.junit.runners.AndroidJUnit4\nimport androidx.test.platform.app.InstrumentationRegistry\nimport io.realm.Realm\nimport io.realm.TestApp\nimport io.realm.TestHelper\nimport io.realm.mongodb.ErrorCode\nimport io.realm.mongodb.User\nimport io.realm.mongodb.close\nimport io.realm.mongodb.registerUserAndLogin\nimport io.realm.rule.BlockingLooperThread\nimport io.realm.util.assertFailsWithErrorCode\nimport org.junit.After\nimport org.junit.Before\nimport org.junit.Test\nimport org.junit.runner.RunWith\nimport kotlin.test.assertEquals\nimport kotlin.test.assertFailsWith\n\nprivate const val SERVICE_NAME = \"gcm\"      // it comes from the test server's gcm/config.json\nprivate const val SAMPLE_TOKEN = \"fXXW6Qv0Tb2fgNf3pFOtqt:APA91bGs4YUXswCC2w8-X9tSdwo9-r6KwAeicP0FDJtBubyuFgorbAICNTftI4SbSSynvN0s-KVWXaGUo1eWuumkGJzFWngwuxQWWv5uolsfjidYz3kLEdiwWW0D_igtD5nRtYZu6gMW\"\n\n@RunWith(AndroidJUnit4::class)\nclass PushTest {\n\n    private lateinit var app: TestApp\n    private lateinit var user: User\n\n    private val looperThread = BlockingLooperThread()\n\n    @Before\n    fun setUp() {\n        Realm.init(InstrumentationRegistry.getInstrumentation().targetContext)\n\n        app = TestApp()\n        user = app.registerUserAndLogin(TestHelper.getRandomEmail(), \"123456\")\n    }\n\n    @After\n    fun tearDown() {\n        if (this::app.isInitialized) {\n            app.close()\n        }\n    }\n\n    @Test\n    fun registerDevice() {\n        user.getPush(SERVICE_NAME).registerDevice(SAMPLE_TOKEN)\n    }\n\n    @Test\n    fun registerDevice_twice() {\n        // the API allows registering/deregistering twice, just checking we don't get errors\n        user.getPush(SERVICE_NAME).registerDevice(SAMPLE_TOKEN)\n        user.getPush(SERVICE_NAME).registerDevice(SAMPLE_TOKEN)\n    }\n\n    @Test\n    fun registerDevice_throwsBecauseOfUnknownService() {\n        assertFailsWithErrorCode(ErrorCode.SERVICE_NOT_FOUND) {\n            user.getPush(\"asdf\").registerDevice(SAMPLE_TOKEN)\n        }\n    }\n\n    @Test\n    fun registerDevice_throwsBecauseOfLoggedOutUser() {\n        user.logOut()\n        assertFailsWithErrorCode(ErrorCode.APP_UNKNOWN) {\n            user.getPush(SERVICE_NAME).registerDevice(SAMPLE_TOKEN)\n        }\n    }\n\n    @Test\n    fun registerDeviceAsync() {\n        looperThread.runBlocking {\n            user.getPush(SERVICE_NAME).registerDeviceAsync(SAMPLE_TOKEN) {\n                looperThread.testComplete()\n            }\n        }\n    }\n\n    @Test\n    fun registerDeviceAsync_throwsBecauseOfWrongThread() {\n        assertFailsWith(IllegalStateException::class) {\n            user.getPush(SERVICE_NAME).registerDeviceAsync(SAMPLE_TOKEN) { /* do nothing */ }\n        }\n    }\n\n    @Test\n    fun registerDeviceAsync_throwsBecauseOfUnknownService() {\n        looperThread.runBlocking {\n            user.getPush(\"asdf\").registerDeviceAsync(SAMPLE_TOKEN) {\n                assertEquals(ErrorCode.SERVICE_NOT_FOUND, it.error.errorCode)\n                looperThread.testComplete()\n            }\n        }\n    }\n\n    @Test\n    fun deregisterDevice() {\n        user.getPush(SERVICE_NAME).deregisterDevice()\n    }\n\n    @Test\n    fun deregisterDevice_twice() {\n        // the API allows registering/deregistering twice, just checking we don't get errors\n        user.getPush(SERVICE_NAME).deregisterDevice()\n        user.getPush(SERVICE_NAME).deregisterDevice()\n    }\n\n    @Test\n    fun deregisterDevice_throwsBecauseOfUnknownService() {\n        assertFailsWithErrorCode(ErrorCode.SERVICE_NOT_FOUND) {\n            user.getPush(\"asdf\").deregisterDevice()\n        }\n    }\n\n    @Test\n    fun deregisterDevice_throwsBecauseOfLoggedOutUser() {\n        user.logOut()\n        assertFailsWithErrorCode(ErrorCode.APP_UNKNOWN) {\n            user.getPush(SERVICE_NAME).deregisterDevice()\n        }\n    }\n\n    @Test\n    fun deregisterDeviceAsync() {\n        looperThread.runBlocking {\n            user.getPush(SERVICE_NAME).deregisterDeviceAsync() {\n                looperThread.testComplete()\n            }\n        }\n    }\n\n    @Test\n    fun deregisterDeviceAsync_throwsBecauseOfWrongThread() {\n        assertFailsWith(IllegalStateException::class) {\n            user.getPush(SERVICE_NAME).deregisterDeviceAsync() { /* do nothing */ }\n        }\n    }\n\n    @Test\n    fun deregisterDeviceAsync_throwsBecauseOfUnknownService() {\n        looperThread.runBlocking {\n            user.getPush(\"asdf\").deregisterDeviceAsync() {\n                assertEquals(ErrorCode.SERVICE_NOT_FOUND, it.error.errorCode)\n                looperThread.testComplete()\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTestObjectServer/kotlin/io/realm/mongodb/sync/FlexibleSyncConfigurationTests.kt",
    "content": "/*\n * Copyright 2022 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 */\npackage io.realm.mongodb.sync\n\nimport androidx.test.ext.junit.runners.AndroidJUnit4\nimport androidx.test.platform.app.InstrumentationRegistry\nimport io.realm.Realm\nimport io.realm.TEST_APP_3\nimport io.realm.TestApp\nimport io.realm.TestHelper\nimport io.realm.TestSyncConfigurationFactory\nimport io.realm.mongodb.SyncTestUtils.Companion.createTestUser\nimport io.realm.mongodb.User\nimport io.realm.mongodb.close\nimport org.junit.*\nimport org.junit.Assert.assertEquals\nimport org.junit.Assert.assertFalse\nimport org.junit.Assert.assertNotEquals\nimport org.junit.Assert.assertTrue\nimport org.junit.runner.RunWith\nimport kotlin.test.assertFailsWith\n\n@RunWith(AndroidJUnit4::class)\nclass FlexibleSyncConfigurationTests {\n\n    @get:Rule\n    val configFactory = TestSyncConfigurationFactory()\n\n    private lateinit var app: TestApp\n\n    @Before\n    fun setUp() {\n        Realm.init(InstrumentationRegistry.getInstrumentation().targetContext)\n        app = TestApp(appName = TEST_APP_3)\n    }\n\n    @After\n    fun tearDown() {\n        if (this::app.isInitialized) {\n            app.close()\n        }\n    }\n\n    @Test\n    fun defaultConfig() {\n        val user: User = createTestUser(app)\n        val config = SyncConfiguration.defaultConfig(user)\n        assertTrue(config.isFlexibleSyncConfiguration)\n    }\n\n    @Test\n    fun equals() {\n        val user: User = createTestUser(app)\n        val config: SyncConfiguration = SyncConfiguration.defaultConfig(user)\n        assertTrue(config == config)\n    }\n\n    @Test\n    fun equals_same() {\n        val user: User = createTestUser(app)\n        val config1: SyncConfiguration = SyncConfiguration.Builder(user).build()\n        val config2: SyncConfiguration = SyncConfiguration.Builder(user).build()\n        assertTrue(config1 == config2)\n    }\n\n    @Test\n    fun equals_not() {\n        val user1: User = createTestUser(app)\n        val user2: User = createTestUser(app)\n        val config1: SyncConfiguration = SyncConfiguration.Builder(user1).build()\n        val config2: SyncConfiguration = SyncConfiguration.Builder(user2).build()\n        assertFalse(config1 == config2)\n    }\n\n    @Test\n    fun hashCode_equal() {\n        val user: User = createTestUser(app)\n        val config: SyncConfiguration = SyncConfiguration.defaultConfig(user)\n        assertEquals(config.hashCode(), config.hashCode())\n    }\n\n    @Test\n    fun hashCode_notEquals() {\n        val user1: User = createTestUser(app)\n        val user2: User = createTestUser(app)\n        val config1: SyncConfiguration = SyncConfiguration.defaultConfig(user1)\n        val config2: SyncConfiguration = SyncConfiguration.defaultConfig(user2)\n        assertNotEquals(config1.hashCode(), config2.hashCode())\n    }\n\n    @Test\n    fun get_syncSpecificValues() {\n        val user: User = createTestUser(app)\n        val config: SyncConfiguration = SyncConfiguration.defaultConfig(user)\n        assertTrue(user == config.user)\n        assertEquals(\"ws://127.0.0.1:9090/\", config.serverUrl.toString()) // FIXME: Figure out exactly what to return here\n        assertFalse(config.shouldDeleteRealmOnLogout())\n        assertTrue(config.isSyncConfiguration)\n        assertTrue(config.isFlexibleSyncConfiguration)\n    }\n\n    @Test\n    fun toString_nonEmpty() {\n        val user: User = createTestUser(app)\n        val config: SyncConfiguration = SyncConfiguration.defaultConfig(user)\n        assertTrue(config.isFlexibleSyncConfiguration)\n        assertFalse(config.isPartitionBasedSyncConfiguration)\n    }\n\n    @Test\n    fun getPartitionValueThrows() {\n        val user: User = createTestUser(app)\n        val config: SyncConfiguration = SyncConfiguration.defaultConfig(user)\n        assertFailsWith<IllegalStateException> { config.partitionValue }\n    }\n\n    @Test\n    fun defaultPath() {\n        val user: User = createTestUser(app)\n        val config: SyncConfiguration = SyncConfiguration.defaultConfig(user)\n        assertTrue(\"Path is: ${config.path}\", config.path.endsWith(\"/default.realm\"))\n    }\n\n    @Test\n    fun initialSubscriptions() {\n        val user: User = createTestUser(app)\n        val handler = SyncConfiguration.InitialFlexibleSyncSubscriptions { realm, subscriptions ->\n            // Do nothing\n        }\n        val config: SyncConfiguration = SyncConfiguration.Builder(user)\n            .initialSubscriptions(handler)\n            .build()\n\n        assertEquals(handler, config.initialSubscriptionsHandler)\n    }\n\n    @Test\n    fun defaultClientResetStrategy() {\n        val user: User = createTestUser(app)\n        val handler = SyncConfiguration.InitialFlexibleSyncSubscriptions { realm, subscriptions ->\n            // Do nothing\n        }\n        val config: SyncConfiguration = SyncConfiguration.defaultConfig(user)\n        assertTrue(config.syncClientResetStrategy is RecoverOrDiscardUnsyncedChangesStrategy)\n    }\n\n    @Test\n    fun manualClientResyncMode() {\n        val user: User = createTestUser(app)\n\n        val config = configFactory.createFlexibleSyncConfigurationBuilder(user)\n            .syncClientResetStrategy(object : ManuallyRecoverUnsyncedChangesStrategy {\n                override fun onClientReset(session: SyncSession, error: ClientResetRequiredError) {\n                    Assert.fail(\"Should not be called\")\n                }\n            })\n            .build()\n        assertTrue(config.syncClientResetStrategy is ManuallyRecoverUnsyncedChangesStrategy)\n    }\n\n    @Test\n    fun discardUnsyncedChangesStrategyMode() {\n        val user: User = createTestUser(app)\n\n        val config = configFactory.createFlexibleSyncConfigurationBuilder(user)\n            .syncClientResetStrategy(object : DiscardUnsyncedChangesStrategy {\n                override fun onBeforeReset(realm: Realm) {\n                    Assert.fail(\"Should not be called\")\n                }\n\n                override fun onAfterReset(before: Realm, after: Realm) {\n                    Assert.fail(\"Should not be called\")\n                }\n\n                override fun onError(session: SyncSession, error: ClientResetRequiredError) {\n                    Assert.fail(\"Should not be called\")\n                }\n\n                override fun onManualResetFallback(session: SyncSession, error: ClientResetRequiredError) {\n                    Assert.fail(\"Should not be called\")\n                }\n\n            })\n            .build()\n        assertTrue(config.syncClientResetStrategy is DiscardUnsyncedChangesStrategy)\n    }\n\n    @Test\n    fun recoverUnsyncedChangesStrategyMode() {\n        val user: User = createTestUser(app)\n\n        val config = configFactory.createFlexibleSyncConfigurationBuilder(user)\n            .syncClientResetStrategy(object : RecoverUnsyncedChangesStrategy {\n                override fun onBeforeReset(realm: Realm) {\n                    Assert.fail(\"Should not be called\")\n                }\n\n                override fun onAfterReset(before: Realm, after: Realm) {\n                    Assert.fail(\"Should not be called\")\n                }\n\n                override fun onManualResetFallback(session: SyncSession, error: ClientResetRequiredError) {\n                    Assert.fail(\"Should not be called\")\n                }\n            })\n            .build()\n        assertTrue(config.syncClientResetStrategy is RecoverUnsyncedChangesStrategy)\n    }\n\n    @Test\n    fun recoverOrDiscardUnsyncedChangesStrategyMode() {\n        val user: User = createTestUser(app)\n\n        val config = configFactory.createFlexibleSyncConfigurationBuilder(user)\n            .syncClientResetStrategy(object : RecoverOrDiscardUnsyncedChangesStrategy {\n                override fun onBeforeReset(realm: Realm) {\n                    Assert.fail(\"Should not be called\")\n                }\n\n                override fun onAfterRecovery(before: Realm, after: Realm) {\n                    Assert.fail(\"Should not be called\")\n                }\n\n                override fun onAfterDiscard(before: Realm, after: Realm) {\n                    Assert.fail(\"Should not be called\")\n                }\n\n                override fun onManualResetFallback(session: SyncSession, error: ClientResetRequiredError) {\n                    Assert.fail(\"Should not be called\")\n                }\n\n            })\n            .build()\n        assertTrue(config.syncClientResetStrategy is RecoverOrDiscardUnsyncedChangesStrategy)\n    }\n\n    @Test\n    fun clientResyncMode_throwsOnNull() {\n        val user: User = createTestUser(app)\n        val config = configFactory.createFlexibleSyncConfigurationBuilder(user)\n\n        assertFailsWith<IllegalArgumentException> {\n            config.syncClientResetStrategy(TestHelper.getNull<ManuallyRecoverUnsyncedChangesStrategy>())\n        }\n        assertFailsWith<IllegalArgumentException> {\n            config.syncClientResetStrategy(TestHelper.getNull<DiscardUnsyncedChangesStrategy>())\n        }\n    }\n\n    @Test\n    fun overrideDefaultPath() {\n        val user: User = createTestUser(app)\n        val config: SyncConfiguration = SyncConfiguration.Builder(user)\n            .name(\"custom.realm\")\n            .build()\n        assertTrue(\"Path is: ${config.path}\", config.path.endsWith(\"${app.configuration.appId}/${user.id}/custom.realm\"))\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTestObjectServer/kotlin/io/realm/mongodb/sync/FlexibleSyncIntegrationTests.kt",
    "content": "/*\n * Copyright 2022 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\npackage io.realm.mongodb.sync\n\nimport android.util.Log\nimport androidx.test.ext.junit.runners.AndroidJUnit4\nimport androidx.test.platform.app.InstrumentationRegistry\nimport io.realm.*\nimport io.realm.admin.ServerAdmin\nimport io.realm.entities.*\nimport io.realm.kotlin.syncSession\nimport io.realm.log.LogLevel\nimport io.realm.log.RealmLog\nimport io.realm.mongodb.User\nimport io.realm.mongodb.registerUserAndLogin\nimport io.realm.rule.BlockingLooperThread\nimport org.junit.runner.RunWith\nimport io.realm.kotlin.where\nimport io.realm.mongodb.close\nimport org.junit.*\nimport org.junit.Assert.*\nimport java.util.*\nimport java.util.concurrent.CountDownLatch\nimport java.util.concurrent.atomic.AtomicInteger\nimport kotlin.random.Random\nimport kotlin.test.assertFailsWith\n\n/**\n * Integration smoke tests for Flexible Sync. This is not intended to cover all cases, but just\n * test common scenarios.\n */\n@RunWith(AndroidJUnit4::class)\nclass FlexibleSyncIntegrationTests {\n\n    @get:Rule\n    val configFactory = TestSyncConfigurationFactory()\n    private val looperThread = BlockingLooperThread()\n\n    private lateinit var app: TestApp\n    private lateinit var serverAdmin: ServerAdmin\n    private lateinit var realmConfig: SyncConfiguration\n    private lateinit var realm: Realm\n    private lateinit var user: User\n    private var section: Int = 0\n\n    @Before\n    fun setUp() {\n        Realm.init(InstrumentationRegistry.getInstrumentation().targetContext)\n        RealmLog.setLevel(LogLevel.ALL)\n        app = TestApp(appName = TEST_APP_3)\n        user = app.registerUserAndLogin(TestHelper.getRandomEmail(), \"SECRET_PASSWORD\")\n        serverAdmin = ServerAdmin(app).apply {\n            enableFlexibleSync() // Currently required because importing doesn't work\n        }\n        section = Random.nextInt() // Generate random section to allow replays of unit tests\n    }\n\n    @After\n    fun tearDown() {\n        if (this::app.isInitialized) {\n            app.close()\n        }\n    }\n\n    @Test\n    fun downloadInitialData() {\n        // Upload data from user 1\n        val user1 = app.registerUserAndLogin(TestHelper.getRandomEmail(), \"123456\")\n        val config1 = configFactory.createFlexibleSyncConfigurationBuilder(user1)\n            .schema(FlexSyncColor::class.java)\n            .build()\n        val realm1 = Realm.getInstance(config1)\n        val subs = realm1.subscriptions.update {\n            it.add(Subscription.create(realm1.where<FlexSyncColor>().equalTo(\"section\", section)))\n        }\n        assertTrue(subs.waitForSynchronization())\n        realm1.executeTransaction {\n            it.insert(FlexSyncColor(section).apply { color = \"red\" })\n            it.insert(FlexSyncColor(section).apply { color = \"blue\" })\n        }\n        realm1.syncSession.uploadAllLocalChanges()\n        realm1.close()\n\n        // Download data from user 2\n        val user2 = app.registerUserAndLogin(TestHelper.getRandomEmail(), \"123456\")\n        val config2 = configFactory.createFlexibleSyncConfigurationBuilder(user2)\n            .schema(FlexSyncColor::class.java)\n            .initialSubscriptions { realm, subscriptions ->\n                subscriptions.add(\n                    Subscription.create(\n                        realm.where<FlexSyncColor>()\n                            .equalTo(\"section\", section)\n                            .equalTo(\"color\", \"blue\")\n                    )\n                )\n            }\n            .waitForInitialRemoteData()\n            .build()\n        val realm2 = Realm.getInstance(config2)\n        assertEquals(1, realm2.where<FlexSyncColor>().equalTo(\"color\", \"blue\").count())\n        realm2.close()\n    }\n\n    @Test\n    fun clientResetIfNoSubscriptionWhenWriting() = looperThread.runBlocking {\n        val user = app.registerUserAndLogin(TestHelper.getRandomEmail(), \"123456\")\n        val config = configFactory.createFlexibleSyncConfigurationBuilder(user)\n            .schema(FlexSyncColor::class.java)\n            .build()\n        val realm = Realm.getInstance(config)\n        looperThread.closeAfterTest(realm)\n        realm.executeTransaction {\n            assertFailsWith<RuntimeException> { it.insert(FlexSyncColor().apply { color = \"red\" }) }\n            looperThread.testComplete()\n        }\n    }\n\n    @Test\n    fun dataIsDeletedWhenSubscriptionIsRemoved() {\n        val user = app.registerUserAndLogin(TestHelper.getRandomEmail(), \"123456\")\n        val config = configFactory.createFlexibleSyncConfigurationBuilder(user)\n            .schema(FlexSyncColor::class.java)\n            .initialSubscriptions { realm, subscriptions ->\n                subscriptions.add(\n                    Subscription.create(\n                        \"sub\", realm.where<FlexSyncColor>()\n                            .equalTo(\"section\", section)\n                            .beginGroup()\n                            .equalTo(\"color\", \"red\")\n                            .or()\n                            .equalTo(\"color\", \"blue\")\n                            .endGroup()\n                    )\n                )\n            }\n            .build()\n        val realm = Realm.getInstance(config)\n        realm.executeTransaction {\n            it.insert(FlexSyncColor(section).apply { color = \"red\" })\n            it.insert(FlexSyncColor(section).apply { color = \"blue\" })\n        }\n        assertEquals(2, realm.where<FlexSyncColor>().count())\n        val subscriptions = realm.subscriptions\n        subscriptions.update {\n            it.addOrUpdate(\n                Subscription.create(\n                    \"sub\", realm.where<FlexSyncColor>()\n                        .equalTo(\"section\", section)\n                        .equalTo(\"color\", \"red\")\n                )\n            )\n        }\n        assertTrue(subscriptions.waitForSynchronization())\n        realm.refresh()\n        assertEquals(1, realm.where<FlexSyncColor>().count())\n        realm.close()\n    }\n\n    @Test\n    fun errorHandler_discardUnsyncedChangesStrategyReported() = looperThread.runBlocking {\n        val latch = CountDownLatch(2)\n\n        val config = configFactory.createFlexibleSyncConfigurationBuilder(user)\n            .schema(FlexSyncColor::class.java)\n            .initialSubscriptions { realm, subscriptions ->\n                subscriptions.add(\n                    Subscription.create(\n                        \"sub\",\n                        realm.where<FlexSyncColor>().equalTo(\"section\", section)\n                    )\n                )\n            }\n            .syncClientResetStrategy(object : DiscardUnsyncedChangesStrategy {\n                override fun onBeforeReset(realm: Realm) {\n                    assertTrue(realm.isFrozen)\n                    assertEquals(1, realm.where<FlexSyncColor>().count())\n                    latch.countDown()\n                }\n\n                override fun onAfterReset(before: Realm, after: Realm) {\n                    assertTrue(before.isFrozen)\n                    assertFalse(after.isFrozen)\n\n                    assertEquals(1, before.where<FlexSyncColor>().count())\n                    assertEquals(0, after.where<FlexSyncColor>().count())\n\n                    //Validate we can move data to the reset Realm.\n                    after.executeTransaction {\n                        it.insert(before.where<FlexSyncColor>().findFirst()!!)\n                    }\n                    assertEquals(1, after.where<FlexSyncColor>().count())\n                    latch.countDown()\n                }\n\n                @Deprecated(\"Deprecated in favor of onManualResetFallback\")\n                override fun onError(session: SyncSession, error: ClientResetRequiredError) {\n                    fail(\"This test case was not supposed to trigger DiscardUnsyncedChangesStrategy::onError()\")\n                }\n\n                override fun onManualResetFallback(\n                    session: SyncSession,\n                    error: ClientResetRequiredError\n                ) {\n                    fail(\"This test case was not supposed to trigger DiscardUnsyncedChangesStrategy::onManualResetFallback()\")\n                }\n\n            })\n            .modules(ColorSyncSchema())\n            .build()\n\n        val realm = Realm.getInstance(config)\n        looperThread.closeAfterTest(realm)\n\n        serverAdmin.triggerClientReset(realm.syncSession) {\n            realm.executeTransaction {\n                realm.copyToRealm(FlexSyncColor().apply {\n                    this.section = this@FlexibleSyncIntegrationTests.section\n                })\n            }\n\n            assertEquals(1, realm.where<FlexSyncColor>().count())\n        }\n\n        looperThread.testComplete(latch)\n    }\n\n    @Test\n    fun clientReset_discardUnsyncedChangesStrategy_fallback_userException_onBeforeReset() = looperThread.runBlocking {\n        val latch = CountDownLatch(2)\n\n        val config = configFactory.createFlexibleSyncConfigurationBuilder(user)\n            .schema(FlexSyncColor::class.java)\n            .initialSubscriptions { realm, subscriptions ->\n                subscriptions.add(\n                    Subscription.create(\n                        \"sub\",\n                        realm.where<FlexSyncColor>().equalTo(\"section\", section)\n                    )\n                )\n            }\n            .syncClientResetStrategy(object : DiscardUnsyncedChangesStrategy {\n                override fun onBeforeReset(realm: Realm) {\n\n                    throw RuntimeException()\n                }\n\n                override fun onAfterReset(before: Realm, after: Realm) {\n                    fail(\"This test case was not supposed to trigger DiscardUnsyncedChangesStrategy::onAfterReset()\")\n                }\n\n                @Deprecated(\"Deprecated in favor of onManualResetFallback\")\n                override fun onError(session: SyncSession, error: ClientResetRequiredError) {\n                    latch.countDown()\n                }\n\n                override fun onManualResetFallback(\n                    session: SyncSession,\n                    error: ClientResetRequiredError\n                ) {\n                    validateManualResetIsAvailable(session, error)\n\n                    latch.countDown()\n                }\n\n            })\n            .build()\n\n        val realm = Realm.getInstance(config)\n        looperThread.closeAfterTest(realm)\n\n        serverAdmin.triggerClientReset(realm.syncSession) {\n            realm.executeTransaction {\n                realm.copyToRealm(FlexSyncColor().apply {\n                    this.section = this@FlexibleSyncIntegrationTests.section\n                })\n            }\n\n            assertEquals(1, realm.where<FlexSyncColor>().count())\n        }\n\n        looperThread.testComplete(latch)\n    }\n\n    @Test\n    fun clientReset_discardUnsyncedChangesStrategy_fallback_userException_onAfterReset() = looperThread.runBlocking {\n        val latch = CountDownLatch(2)\n\n        val config = configFactory.createFlexibleSyncConfigurationBuilder(user)\n            .schema(FlexSyncColor::class.java)\n            .initialSubscriptions { realm, subscriptions ->\n                subscriptions.add(\n                    Subscription.create(\n                        \"sub\",\n                        realm.where<FlexSyncColor>().equalTo(\"section\", section)\n                    )\n                )\n            }\n            .syncClientResetStrategy(object : DiscardUnsyncedChangesStrategy {\n                override fun onBeforeReset(realm: Realm) {\n                    assertNotNull(realm)\n                }\n\n                override fun onAfterReset(before: Realm, after: Realm) {\n                    throw RuntimeException()\n                }\n\n                @Deprecated(\"Deprecated in favor of onManualResetFallback\")\n                override fun onError(session: SyncSession, error: ClientResetRequiredError) {\n                    latch.countDown()\n                }\n\n                override fun onManualResetFallback(\n                    session: SyncSession,\n                    error: ClientResetRequiredError\n                ) {\n                    validateManualResetIsAvailable(session, error)\n\n                    latch.countDown()\n                }\n\n            })\n            .build()\n\n        val realm = Realm.getInstance(config)\n        looperThread.closeAfterTest(realm)\n\n        serverAdmin.triggerClientReset(realm.syncSession) {\n            realm.executeTransaction {\n                realm.copyToRealm(FlexSyncColor().apply {\n                    this.section = this@FlexibleSyncIntegrationTests.section\n                })\n            }\n\n            assertEquals(1, realm.where<FlexSyncColor>().count())\n        }\n\n        looperThread.testComplete(latch)\n    }\n\n    @Test\n    fun errorHandler_automaticRecoveryStrategy() = looperThread.runBlocking {\n        val latch = CountDownLatch(2)\n\n        val config = configFactory.createFlexibleSyncConfigurationBuilder(user)\n            .schema(FlexSyncColor::class.java)\n            .initialSubscriptions { realm, subscriptions ->\n                subscriptions.add(\n                    Subscription.create(\n                        \"sub\",\n                        realm.where<FlexSyncColor>().equalTo(\"section\", section)\n                    )\n                )\n            }\n            .syncClientResetStrategy(object : RecoverUnsyncedChangesStrategy {\n                override fun onBeforeReset(realm: Realm) {\n                    assertTrue(realm.isFrozen)\n                    assertEquals(1, realm.where<FlexSyncColor>().count())\n                    latch.countDown()\n                }\n\n                override fun onAfterReset(before: Realm, after: Realm) {\n                    assertEquals(1, before.where<FlexSyncColor>().count())\n                    assertEquals(1, after.where<FlexSyncColor>().count())\n                    latch.countDown()\n                }\n\n                override fun onManualResetFallback(session: SyncSession, error: ClientResetRequiredError) {\n                    fail(\"This test case was not supposed to trigger AutomaticRecoveryStrategy::onManualResetFallback()\")\n                }\n            })\n            .modules(ColorSyncSchema())\n            .build()\n\n        val realm = Realm.getInstance(config)\n        looperThread.closeAfterTest(realm)\n\n        serverAdmin.triggerClientReset(realm.syncSession) {\n            realm.executeTransaction {\n                realm.copyToRealm(FlexSyncColor().apply {\n                    this.section = this@FlexibleSyncIntegrationTests.section\n                })\n            }\n\n            assertEquals(1, realm.where<FlexSyncColor>().count())\n        }\n\n        looperThread.testComplete(latch)\n    }\n\n    @Test\n    fun clientReset_recoverUnsyncedChangesStrategy_fallback_userException_onBeforeReset() = looperThread.runBlocking {\n        val config = configFactory.createFlexibleSyncConfigurationBuilder(user)\n            .schema(FlexSyncColor::class.java)\n            .initialSubscriptions { realm, subscriptions ->\n                subscriptions.add(\n                    Subscription.create(\n                        \"sub\",\n                        realm.where<FlexSyncColor>().equalTo(\"section\", section)\n                    )\n                )\n            }\n            .syncClientResetStrategy(object : RecoverUnsyncedChangesStrategy {\n                override fun onBeforeReset(realm: Realm) {\n                    throw RuntimeException()\n                }\n\n                override fun onAfterReset(before: Realm, after: Realm) {\n                    fail(\"This test case was not supposed to trigger RecoverUnsyncedChangesStrategy::onAfterReset()\")\n                }\n\n                override fun onManualResetFallback(\n                    session: SyncSession,\n                    error: ClientResetRequiredError\n                ) {\n                    validateManualResetIsAvailable(session, error)\n\n                    looperThread.testComplete()\n                }\n            })\n            .build()\n\n        val realm = Realm.getInstance(config)\n        looperThread.closeAfterTest(realm)\n\n        serverAdmin.triggerClientReset(realm.syncSession) {\n            realm.executeTransaction {\n                realm.copyToRealm(FlexSyncColor().apply {\n                    this.section = this@FlexibleSyncIntegrationTests.section\n                })\n            }\n\n            assertEquals(1, realm.where<FlexSyncColor>().count())\n        }\n    }\n\n    @Test\n    fun clientReset_recoverUnsyncedChangesStrategy_fallback_userException_onAfterReset() = looperThread.runBlocking {\n        val config = configFactory.createFlexibleSyncConfigurationBuilder(user)\n            .schema(FlexSyncColor::class.java)\n            .initialSubscriptions { realm, subscriptions ->\n                subscriptions.add(\n                    Subscription.create(\n                        \"sub\",\n                        realm.where<FlexSyncColor>().equalTo(\"section\", section)\n                    )\n                )\n            }\n            .syncClientResetStrategy(object : RecoverUnsyncedChangesStrategy {\n                override fun onBeforeReset(realm: Realm) {\n                    assertNotNull(realm)\n                }\n\n                override fun onAfterReset(before: Realm, after: Realm) {\n                    throw RuntimeException()\n                }\n\n                override fun onManualResetFallback(\n                    session: SyncSession,\n                    error: ClientResetRequiredError\n                ) {\n                    validateManualResetIsAvailable(session, error)\n\n                    looperThread.testComplete()\n                }\n            })\n            .build()\n\n        val realm = Realm.getInstance(config)\n        looperThread.closeAfterTest(realm)\n\n        serverAdmin.triggerClientReset(realm.syncSession) {\n            realm.executeTransaction {\n                realm.copyToRealm(FlexSyncColor().apply {\n                    this.section = this@FlexibleSyncIntegrationTests.section\n                })\n            }\n\n            assertEquals(1, realm.where<FlexSyncColor>().count())\n        }\n    }\n\n    @Test\n    fun errorHandler_automaticRecoveryOrDiscardStrategy() = looperThread.runBlocking {\n        val latch = CountDownLatch(2)\n\n        val config = configFactory.createFlexibleSyncConfigurationBuilder(user)\n            .schema(FlexSyncColor::class.java)\n            .initialSubscriptions { realm, subscriptions ->\n                subscriptions.add(\n                    Subscription.create(\n                        \"sub\",\n                        realm.where<FlexSyncColor>().equalTo(\"section\", section)\n                    )\n                )\n            }\n            .syncClientResetStrategy(object :\n                RecoverOrDiscardUnsyncedChangesStrategy {\n                override fun onBeforeReset(realm: Realm) {\n                    assertTrue(realm.isFrozen)\n                    assertEquals(1, realm.where<FlexSyncColor>().count())\n                    latch.countDown()\n                }\n\n                override fun onAfterRecovery(before: Realm, after: Realm) {\n                    assertEquals(1, before.where<FlexSyncColor>().count())\n                    assertEquals(1, after.where<FlexSyncColor>().count())\n                    latch.countDown()\n                }\n\n                override fun onAfterDiscard(before: Realm, after: Realm) {\n                    fail(\"This test case was not supposed to trigger AutomaticRecoveryOrDiscardUnsyncedChangesStrategy::onAfterDiscard()\")\n                }\n\n                override fun onManualResetFallback(session: SyncSession, error: ClientResetRequiredError) {\n                    fail(\"This test case was not supposed to trigger AutomaticRecoveryStrategy::onManualResetFallback()\")\n                }\n            })\n            .modules(ColorSyncSchema())\n            .build()\n\n        val realm = Realm.getInstance(config)\n        looperThread.closeAfterTest(realm)\n\n        serverAdmin.triggerClientReset(realm.syncSession) {\n            realm.executeTransaction {\n                realm.copyToRealm(FlexSyncColor().apply {\n                    this.section = this@FlexibleSyncIntegrationTests.section\n                })\n            }\n\n            assertEquals(1, realm.where<FlexSyncColor>().count())\n        }\n\n        looperThread.testComplete(latch)\n    }\n\n    @Test\n    fun errorHandler_automaticRecoveryOrDiscardStrategy_discardsLocal() = looperThread.runBlocking {\n        val latch = CountDownLatch(2)\n\n        val config = configFactory.createFlexibleSyncConfigurationBuilder(user)\n            .schema(FlexSyncColor::class.java)\n            .initialSubscriptions { realm, subscriptions ->\n                subscriptions.add(\n                    Subscription.create(\n                        \"sub\",\n                        realm.where<FlexSyncColor>().equalTo(\"section\", section)\n                    )\n                )\n            }\n            .syncClientResetStrategy(object :\n                RecoverOrDiscardUnsyncedChangesStrategy {\n                override fun onBeforeReset(realm: Realm) {\n                    assertTrue(realm.isFrozen)\n                    assertEquals(1, realm.where<FlexSyncColor>().count())\n                    latch.countDown()\n                }\n\n                override fun onAfterRecovery(before: Realm, after: Realm) {\n                    fail(\"This test case was not supposed to trigger AutomaticRecoveryOrDiscardUnsyncedChangesStrategy::onAfterRecovery()\")\n                }\n\n                override fun onAfterDiscard(before: Realm, after: Realm) {\n                    assertTrue(before.isFrozen)\n                    assertFalse(after.isFrozen)\n\n                    assertEquals(1, before.where<FlexSyncColor>().count())\n                    assertEquals(0, after.where<FlexSyncColor>().count())\n\n                    //Validate we can move data to the reset Realm.\n                    after.executeTransaction {\n                        it.insert(before.where<FlexSyncColor>().findFirst()!!)\n                    }\n                    assertEquals(1, after.where<FlexSyncColor>().count())\n                    latch.countDown()\n                }\n\n\n                override fun onManualResetFallback(session: SyncSession, error: ClientResetRequiredError) {\n                    fail(\"This test case was not supposed to trigger AutomaticRecoveryOrDiscardUnsyncedChangesStrategy::onManualResetFallback()\")\n                }\n            })\n            .modules(ColorSyncSchema())\n            .build()\n\n        val realm = Realm.getInstance(config)\n        looperThread.closeAfterTest(realm)\n\n        serverAdmin.triggerClientReset(realm.syncSession, withRecoveryModeEnabled = false, latch) {\n            realm.executeTransaction {\n                realm.copyToRealm(FlexSyncColor().apply {\n                    this.section = this@FlexibleSyncIntegrationTests.section\n                })\n            }\n\n            assertEquals(1, realm.where<FlexSyncColor>().count())\n        }\n\n        looperThread.testComplete(latch)\n    }\n\n\n    @Test\n    fun clientReset_recoverOrDiscardUnsyncedChangesStrategy_fallback_userException_onBeforeReset() = looperThread.runBlocking {\n        val config = configFactory.createFlexibleSyncConfigurationBuilder(user)\n            .schema(FlexSyncColor::class.java)\n            .initialSubscriptions { realm, subscriptions ->\n                subscriptions.add(\n                    Subscription.create(\n                        \"sub\",\n                        realm.where<FlexSyncColor>().equalTo(\"section\", section)\n                    )\n                )\n            }\n            .syncClientResetStrategy(object : RecoverOrDiscardUnsyncedChangesStrategy {\n                override fun onBeforeReset(realm: Realm) {\n                    throw RuntimeException()\n                }\n\n                override fun onAfterRecovery(before: Realm, after: Realm) {\n                    fail(\"This test case was not supposed to trigger RecoverOrDiscardUnsyncedChangesStrategy::onAfterRecovery()\")\n                }\n\n                override fun onAfterDiscard(before: Realm, after: Realm) {\n                    fail(\"This test case was not supposed to trigger RecoverOrDiscardUnsyncedChangesStrategy::onAfterDiscard()\")\n                }\n\n                override fun onManualResetFallback(\n                    session: SyncSession,\n                    error: ClientResetRequiredError\n                ) {\n                    validateManualResetIsAvailable(session, error)\n\n                    looperThread.testComplete()\n                }\n            })\n            .modules(ObjectSyncSchema())\n            .build()\n\n        val realm = Realm.getInstance(config)\n        looperThread.closeAfterTest(realm)\n\n        serverAdmin.triggerClientReset(realm.syncSession) {\n            realm.executeTransaction {\n                realm.copyToRealm(FlexSyncColor().apply {\n                    this.section = this@FlexibleSyncIntegrationTests.section\n                })\n            }\n\n            assertEquals(1, realm.where<FlexSyncColor>().count())\n        }\n    }\n\n    @Test\n    fun clientReset_recoverOrDiscardUnsyncedChangesStrategy_fallback_userException_onAfterRecovery() = looperThread.runBlocking {\n        val config = configFactory.createFlexibleSyncConfigurationBuilder(user)\n            .schema(FlexSyncColor::class.java)\n            .initialSubscriptions { realm, subscriptions ->\n                subscriptions.add(\n                    Subscription.create(\n                        \"sub\",\n                        realm.where<FlexSyncColor>().equalTo(\"section\", section)\n                    )\n                )\n            }\n            .syncClientResetStrategy(object : RecoverOrDiscardUnsyncedChangesStrategy {\n                override fun onBeforeReset(realm: Realm) {\n                    assertNotNull(realm)\n                }\n\n                override fun onAfterRecovery(before: Realm, after: Realm) {\n                    throw RuntimeException()\n                }\n\n                override fun onAfterDiscard(before: Realm, after: Realm) {\n                    fail(\"This test case was not supposed to trigger RecoverOrDiscardUnsyncedChangesStrategy::onAfterDiscard()\")\n                }\n\n                override fun onManualResetFallback(\n                    session: SyncSession,\n                    error: ClientResetRequiredError\n                ) {\n                    validateManualResetIsAvailable(session, error)\n\n                    looperThread.testComplete()\n                }\n            })\n            .modules(ObjectSyncSchema())\n            .build()\n\n        val realm = Realm.getInstance(config)\n        looperThread.closeAfterTest(realm)\n\n        serverAdmin.triggerClientReset(realm.syncSession) {\n            realm.executeTransaction {\n                realm.copyToRealm(FlexSyncColor().apply {\n                    this.section = this@FlexibleSyncIntegrationTests.section\n                })\n            }\n\n            assertEquals(1, realm.where<FlexSyncColor>().count())\n        }\n    }\n\n    @Test\n    fun clientReset_recoverOrDiscardUnsyncedChangesStrategy_fallback_userException_onAfterDiscard() = looperThread.runBlocking {\n        val config = configFactory.createFlexibleSyncConfigurationBuilder(user)\n            .schema(FlexSyncColor::class.java)\n            .initialSubscriptions { realm, subscriptions ->\n                subscriptions.add(\n                    Subscription.create(\n                        \"sub\",\n                        realm.where<FlexSyncColor>().equalTo(\"section\", section)\n                    )\n                )\n            }\n            .syncClientResetStrategy(object : RecoverOrDiscardUnsyncedChangesStrategy {\n                override fun onBeforeReset(realm: Realm) {\n                    assertNotNull(realm)\n                }\n\n                override fun onAfterRecovery(before: Realm, after: Realm) {\n                    fail(\"This test case was not supposed to trigger RecoverOrDiscardUnsyncedChangesStrategy::onAfterRecovery()\")\n                }\n\n                override fun onAfterDiscard(before: Realm, after: Realm) {\n                    throw RuntimeException()\n                }\n\n                override fun onManualResetFallback(\n                    session: SyncSession,\n                    error: ClientResetRequiredError\n                ) {\n                    validateManualResetIsAvailable(session, error)\n\n                    looperThread.testComplete()\n                }\n            })\n            .modules(ObjectSyncSchema())\n            .build()\n\n        val realm = Realm.getInstance(config)\n        looperThread.closeAfterTest(realm)\n\n        serverAdmin.triggerClientReset(realm.syncSession, withRecoveryModeEnabled = false) {\n            realm.executeTransaction {\n                realm.copyToRealm(FlexSyncColor().apply {\n                    this.section = this@FlexibleSyncIntegrationTests.section\n                })\n            }\n\n            assertEquals(1, realm.where<FlexSyncColor>().count())\n        }\n    }\n\n}"
  },
  {
    "path": "realm/realm-library/src/androidTestObjectServer/kotlin/io/realm/mongodb/sync/MutableSubscriptionSetTests.kt",
    "content": "/*\n * Copyright 2022 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 */\npackage io.realm.mongodb.sync\n\nimport androidx.test.ext.junit.runners.AndroidJUnit4\nimport androidx.test.platform.app.InstrumentationRegistry\nimport io.realm.Realm\nimport io.realm.TEST_APP_3\nimport io.realm.TestApp\nimport io.realm.TestHelper\nimport io.realm.TestSyncConfigurationFactory\nimport io.realm.admin.ServerAdmin\nimport io.realm.entities.FlexSyncColor\nimport io.realm.entities.SyncDog\nimport io.realm.kotlin.where\nimport io.realm.log.LogLevel\nimport io.realm.log.RealmLog\nimport io.realm.mongodb.close\nimport io.realm.mongodb.registerUserAndLogin\nimport io.realm.rule.BlockingLooperThread\nimport junit.framework.Assert.assertEquals\nimport junit.framework.Assert.assertFalse\nimport junit.framework.Assert.assertNull\nimport junit.framework.Assert.assertTrue\nimport org.junit.After\nimport org.junit.Assert.fail\nimport org.junit.Before\nimport org.junit.Rule\nimport org.junit.Test\nimport org.junit.runner.RunWith\nimport kotlin.test.assertFailsWith\n\n/**\n * Class wrapping tests for modifying a subscription set.\n */\n@RunWith(AndroidJUnit4::class)\nclass MutableSubscriptionSetTests {\n\n\n    @get:Rule\n    val configFactory = TestSyncConfigurationFactory()\n    private val looperThread = BlockingLooperThread()\n\n    private lateinit var app: TestApp\n    private lateinit var realm: Realm\n    private lateinit var config: SyncConfiguration\n\n    @Before\n    fun setUp() {\n        Realm.init(InstrumentationRegistry.getInstrumentation().targetContext)\n        RealmLog.setLevel(LogLevel.ALL)\n        app = TestApp(appName = TEST_APP_3)\n        ServerAdmin(app).enableFlexibleSync() // Currrently required because importing doesn't work\n        val user = app.registerUserAndLogin(TestHelper.getRandomEmail(), \"123456\")\n        config = configFactory.createFlexibleSyncConfigurationBuilder(user)\n            .schema(FlexSyncColor::class.java)\n            .build()\n        realm = Realm.getInstance(config)\n    }\n\n    @After\n    fun tearDown() {\n        realm.close()\n        if (this::app.isInitialized) {\n            app.close()\n        }\n    }\n\n    @Test\n    fun initialSubscriptions() {\n        realm.subscriptions.update { mutableSubs ->\n            assertEquals(0, mutableSubs.size())\n            assertEquals(SubscriptionSet.State.UNCOMMITTED, mutableSubs.state)\n        }\n    }\n\n    @Test\n    fun addNamedSubscription() {\n        val updatedSubs = realm.subscriptions.update { mutableSubs ->\n            mutableSubs.add(Subscription.create(\"test\", realm.where<FlexSyncColor>()))\n        }\n        assertEquals(1, updatedSubs.size())\n        assertEquals(SubscriptionSet.State.PENDING, updatedSubs.state)\n        val sub: Subscription = updatedSubs.first()\n        assertEquals(\"test\", sub.name)\n        assertEquals(\"TRUEPREDICATE \", sub.query)\n        assertEquals(\"FlexSyncColor\", sub.objectType)\n        assertTrue(sub.createdAt!!.time > 0)\n        assertTrue(sub.updatedAt == sub.createdAt)\n    }\n\n    @Test\n    fun addAnonymousSubscription() {\n        val updatedSubs = realm.subscriptions.update { mutableSubs ->\n            mutableSubs.add(Subscription.create(realm.where<FlexSyncColor>()))\n        }\n        assertEquals(1, updatedSubs.size())\n        assertEquals(SubscriptionSet.State.PENDING, updatedSubs.state)\n        val sub: Subscription = updatedSubs.first()\n        assertNull(sub.name)\n        assertEquals(sub.query, \"TRUEPREDICATE \")\n        assertEquals(sub.objectType, \"FlexSyncColor\")\n        assertTrue(sub.createdAt!!.time > 0)\n        assertTrue(sub.updatedAt == sub.createdAt)\n    }\n\n    @Test\n    fun add_multiple_anonymous() {\n        realm.subscriptions.update { mutableSubs ->\n            mutableSubs.add(Subscription.create(realm.where<FlexSyncColor>()))\n            mutableSubs.add(Subscription.create(realm.where<FlexSyncColor>().equalTo(\"section\", 10L)))\n            mutableSubs.add(Subscription.create(realm.where<FlexSyncColor>().equalTo(\"section\", 5L)))\n            mutableSubs.add(Subscription.create(realm.where<FlexSyncColor>().equalTo(\"section\", 1L)))\n        }.also { subscriptionSet ->\n            assertEquals(4, subscriptionSet.count())\n        }\n    }\n\n    @Test\n    fun addExistingAnonymous_throws() {\n        realm.subscriptions.update { mutableSubs ->\n            mutableSubs.add(Subscription.create(realm.where<FlexSyncColor>()))\n            assertFailsWith<IllegalArgumentException> {\n                mutableSubs.add(Subscription.create(realm.where<FlexSyncColor>()))\n            }\n        }\n    }\n\n    @Test\n    fun addExistingNamed_throws() {\n        realm.subscriptions.update { mutableSubs ->\n            mutableSubs.add(Subscription.create(\"sub1\", realm.where<FlexSyncColor>()))\n            assertFailsWith<IllegalArgumentException> {\n                mutableSubs.add(Subscription.create(\"sub1\", realm.where<FlexSyncColor>()))\n            }\n        }\n    }\n\n    @Test\n    fun addOrUpdate_managedThrows() {\n        realm.subscriptions.update {\n            val managedSub = it.add(Subscription.create(realm.where<FlexSyncColor>()))\n            assertFailsWith<java.lang.IllegalArgumentException> {  it.addOrUpdate(managedSub) }\n        }\n    }\n\n    @Test\n    fun update() {\n        val subs = realm.subscriptions\n        subs.update { mutableSubs ->\n            mutableSubs.add(Subscription.create(\"sub1\", realm.where<FlexSyncColor>()))\n        }\n        subs.update { mutableSubs ->\n            mutableSubs.addOrUpdate(Subscription.create(\"sub1\", realm.where<FlexSyncColor>().equalTo(\"color\", \"red\")))\n        }\n        val sub = subs.first()\n        assertEquals(\"sub1\", sub.name)\n        assertEquals(\"FlexSyncColor\", sub.objectType)\n        assertEquals(\"color == \\\"red\\\" \", sub.query)\n        assertTrue(sub.createdAt!! < sub.updatedAt!!)\n    }\n\n    @Test\n    fun updateAsync() = looperThread.runBlocking {\n        val realm = Realm.getInstance(config)\n        looperThread.closeAfterTest(realm)\n        val subs = realm.subscriptions\n        subs.update {\n            it.add(Subscription.create(\"sub1\", realm.where<FlexSyncColor>()))\n        }\n\n        subs.updateAsync(object: SubscriptionSet.UpdateAsyncCallback {\n            override fun update(subscriptions: MutableSubscriptionSet) {\n                Realm.getInstance(realm.configuration).use { bgRealm ->\n                    subscriptions.addOrUpdate(Subscription.create(\n                        \"sub1\",\n                        bgRealm.where<FlexSyncColor>()\n                            .equalTo(\"color\", \"red\"))\n                    )\n                }\n            }\n\n            override fun onSuccess(subscriptions: SubscriptionSet) {\n                val sub = subscriptions.first()\n                assertEquals(\"sub1\", sub.name)\n                assertEquals(\"FlexSyncColor\", sub.objectType)\n                assertEquals(\"color == \\\"red\\\" \", sub.query)\n                assertTrue(sub.createdAt!! < sub.updatedAt!!)\n                looperThread.testComplete()\n            }\n\n            override fun onError(exception: Throwable) {\n                fail(exception.toString())\n            }\n        })\n    }\n\n    @Test\n    fun updateAsync_throws() = looperThread.runBlocking {\n        val realm = Realm.getInstance(config)\n        looperThread.closeAfterTest(realm)\n        val subs = realm.subscriptions\n        subs.updateAsync(object: SubscriptionSet.UpdateAsyncCallback {\n            override fun update(subscriptions: MutableSubscriptionSet) {\n                throw RuntimeException(\"Boom\")\n            }\n\n            override fun onSuccess(subscriptions: SubscriptionSet) {\n                fail()\n            }\n\n            override fun onError(exception: Throwable) {\n                assertTrue(exception is RuntimeException)\n                assertEquals(\"Boom\", exception.message)\n                looperThread.testComplete()\n            }\n        })\n    }\n\n    @Test\n    fun removeNamed() {\n        var updatedSubs = realm.subscriptions.update { mutableSubs ->\n            mutableSubs.addOrUpdate(Subscription.create(\"test\", realm.where<FlexSyncColor>()))\n        }\n        assertEquals(1, updatedSubs.size())\n        updatedSubs = updatedSubs.update { mutableSubs ->\n            assertTrue(mutableSubs.remove(\"test\"))\n            assertEquals(0, mutableSubs.size());\n        }\n        assertEquals(0, updatedSubs.size());\n    }\n\n    @Test\n    fun removeNamed_fails() {\n        var updatedSubs = realm.subscriptions.update { mutableSubs ->\n            assertFalse(mutableSubs.remove(\"dont-exists\"))\n        }\n    }\n\n    @Test\n    fun removeSubscription() {\n        var updatedSubs = realm.subscriptions.update { mutableSubs ->\n            mutableSubs.addOrUpdate(Subscription.create(\"test\", realm.where<FlexSyncColor>()))\n        }\n        assertEquals(1, updatedSubs.size())\n        updatedSubs = updatedSubs.update { mutableSubs ->\n            assertTrue(mutableSubs.remove(mutableSubs.first()))\n            assertEquals(0, mutableSubs.size());\n        }\n        assertEquals(0, updatedSubs.size());\n    }\n\n    @Test\n    fun removeSubscription_fails() {\n        realm.subscriptions.update { mutableSubs ->\n            val managedSub = mutableSubs.add(Subscription.create(realm.where<FlexSyncColor>()))\n            assertTrue(mutableSubs.remove(managedSub))\n            assertFalse(mutableSubs.remove(managedSub))\n        }\n    }\n\n    @Test\n    fun removeSubscription_unManagedthrows() {\n        realm.subscriptions.update { mutableSubs ->\n            val managedSub = mutableSubs.add(Subscription.create(\"sub\", realm.where<FlexSyncColor>()))\n            assertFailsWith<IllegalArgumentException> {\n                mutableSubs.remove(Subscription.create(\"sub\", realm.where<FlexSyncColor>()))\n            }\n        }\n    }\n\n    @Test\n    fun removeAllStringTyped() {\n        var updatedSubs = realm.subscriptions.update { mutableSubs ->\n            mutableSubs.addOrUpdate(Subscription.create(realm.where<FlexSyncColor>()))\n        }\n        assertEquals(1, updatedSubs.size())\n        updatedSubs = updatedSubs.update { mutableSubs ->\n            assertTrue(mutableSubs.removeAll(\"FlexSyncColor\"))\n            assertEquals(0, mutableSubs.size());\n        }\n        assertEquals(0, updatedSubs.size());\n    }\n\n    @Test\n    fun removeAllStringTyped_fails() {\n        // Not part of schema\n        realm.subscriptions.update { mutableSubs ->\n            assertFalse(mutableSubs.removeAll(\"DontExists\"))\n        }\n\n        // part of schema\n        realm.subscriptions.update { mutableSubs ->\n            assertFalse(mutableSubs.removeAll(\"FlexSyncColor\"))\n        }\n    }\n\n    @Test\n    fun removeAllClassTyped() {\n        var updatedSubs = realm.subscriptions.update { mutableSubs ->\n            mutableSubs.addOrUpdate(Subscription.create(realm.where<FlexSyncColor>()))\n        }\n        assertEquals(1, updatedSubs.size())\n        updatedSubs = updatedSubs.update { mutableSubs ->\n            assertTrue(mutableSubs.removeAll(FlexSyncColor::class.java))\n            assertEquals(0, mutableSubs.size());\n        }\n        assertEquals(0, updatedSubs.size());\n    }\n\n    @Test\n    fun removeAllClassTyped_fails() {\n        // Not part of schema\n        realm.subscriptions.update { mutableSubs ->\n            assertFailsWith<IllegalArgumentException> {\n                mutableSubs.removeAll(SyncDog::class.java)\n            }\n        }\n\n        // part of schema\n        realm.subscriptions.update { mutableSubs ->\n            assertFalse(mutableSubs.removeAll(FlexSyncColor::class.java))\n        }\n    }\n\n    @Test\n    fun removeAll() {\n        var updatedSubs = realm.subscriptions.update { mutableSubs ->\n            mutableSubs.add(Subscription.create(\"test\", realm.where<FlexSyncColor>()))\n            mutableSubs.add(Subscription.create(\"test2\", realm.where<FlexSyncColor>()))\n        }\n        assertEquals(2, updatedSubs.size())\n        updatedSubs = updatedSubs.update { mutableSubs ->\n            assertTrue(mutableSubs.removeAll())\n            assertEquals(0, mutableSubs.size());\n        }\n        assertEquals(0, updatedSubs.size());\n    }\n\n    @Test\n    fun removeAll_fails() {\n        realm.subscriptions.update { mutableSubs ->\n            assertFalse(mutableSubs.removeAll())\n        }\n    }\n\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTestObjectServer/kotlin/io/realm/mongodb/sync/ProgressTests.kt",
    "content": "/*\n * Copyright 2020 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 */\npackage io.realm.mongodb.sync\n\nimport androidx.test.ext.junit.runners.AndroidJUnit4\nimport org.junit.Assert.assertEquals\nimport org.junit.Test\nimport org.junit.runner.RunWith\nimport java.util.*\n\n@RunWith(AndroidJUnit4::class)\nclass ProgressTests {\n\n    @Test\n    fun getFractionTransferred () {\n        val testData = arrayOf(\n                arrayOf<Any>(0L, 0L, 1.0),\n                arrayOf<Any>(0L, 1L, 0.0),\n                arrayOf<Any>(1L, 1L, 1.0),\n                arrayOf<Any>(1L, 2L, 0.5)\n        )\n        for (test in testData) {\n            val transferredBytes = test[0] as Long\n            val transferableBytes = test[1] as Long\n            val fraction = test[2] as Double\n            val progress = Progress(transferredBytes, transferableBytes)\n            val errorMessage = String.format(Locale.US, \"Failed with: (%d, %d)\", transferredBytes, transferableBytes)\n            assertEquals(errorMessage, fraction, progress.fractionTransferred, 0.0)\n        }\n    }\n\n    @Test\n    fun getTransferredBytes() {\n        val testData = longArrayOf(0, Long.MAX_VALUE)\n        for (transferredBytes in testData) {\n            val errorMessage = String.format(Locale.US, \"Failed with: %d\", transferredBytes)\n            val progress = Progress(transferredBytes, Long.MAX_VALUE)\n            assertEquals(errorMessage, transferredBytes, progress.transferredBytes)\n        }\n    }\n\n    @Test\n    fun getTransferableBytes() {\n        val testData = longArrayOf(0, Long.MAX_VALUE)\n        for (transferableBytes in testData) {\n            val errorMessage = String.format(Locale.US, \"Failed with: %d\", transferableBytes)\n            val progress = Progress(0, transferableBytes)\n            assertEquals(errorMessage, transferableBytes, progress.transferableBytes)\n        }\n    }\n\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTestObjectServer/kotlin/io/realm/mongodb/sync/SSLConfigurationTests.kt",
    "content": "/*\n * Copyright 2017 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 */\npackage io.realm.mongodb.sync\n\nimport android.os.SystemClock\nimport androidx.test.ext.junit.runners.AndroidJUnit4\nimport io.realm.Realm\nimport io.realm.TestApp\nimport io.realm.TestHelper\nimport io.realm.TestHelper.TestLogger\nimport io.realm.TestSyncConfigurationFactory\nimport io.realm.entities.DefaultSyncSchema\nimport io.realm.entities.SyncDog\nimport io.realm.exceptions.RealmFileException\nimport io.realm.kotlin.syncSession\nimport io.realm.log.LogLevel\nimport io.realm.log.RealmLog\nimport io.realm.mongodb.App\nimport io.realm.mongodb.AppException\nimport io.realm.mongodb.Credentials\nimport io.realm.mongodb.ErrorCode\nimport io.realm.mongodb.User\nimport io.realm.mongodb.close\nimport io.realm.mongodb.registerUserAndLogin\nimport io.realm.rule.BlockingLooperThread\nimport org.bson.types.ObjectId\nimport org.junit.After\nimport org.junit.Assert\nimport org.junit.Before\nimport org.junit.Ignore\nimport org.junit.Rule\nimport org.junit.Test\nimport org.junit.runner.RunWith\nimport java.util.*\nimport java.util.concurrent.TimeUnit\nimport kotlin.test.assertEquals\n\n/**\n * Remember: Any test against the local BAAS server will not use an SSL connection.\n */\n@RunWith(AndroidJUnit4::class)\n@Ignore(\"Should only be run manually\")\nclass SSLConfigurationTests {\n\n    @get:Rule\n    val configFactory = TestSyncConfigurationFactory()\n    private val looperThread = BlockingLooperThread()\n    private lateinit var app: App\n\n    @Before\n    fun setUp() {\n        app = App(\"application-0-nfiqi\")\n    }\n\n    @Test\n    fun disableSSLVerification() = looperThread.runBlocking {\n        val username = TestHelper.getRandomEmail()\n        val password = \"password\"\n        var user: User = app.registerUserAndLogin(username, password)\n        var partition = UUID.randomUUID().toString()\n\n        // 1. Copy a valid Realm to the server\n        val syncConfig: SyncConfiguration = configFactory.createSyncConfigurationBuilder(user, partition)\n                .modules(DefaultSyncSchema())\n                .build()\n        var realm = Realm.getInstance(syncConfig)\n        realm.beginTransaction()\n        realm.createObject(SyncDog::class.java, ObjectId()).name = \"Foo\"\n        realm.commitTransaction()\n\n        // make sure the changes gets to the server\n        app.sync.getSession(syncConfig).uploadAllLocalChanges()\n        realm.close()\n        user.logOut()\n\n        // 2. Local state should now be completely reset. Open the Realm again with a new configuration which should\n        // download the uploaded changes.\n        user = app.registerUserAndLogin(TestHelper.getRandomEmail(), \"password\")\n        val syncConfigSSL: SyncConfiguration = configFactory.createSyncConfigurationBuilder(user, partition)\n                .modules(DefaultSyncSchema())\n                .waitForInitialRemoteData()\n                .trustedRootCA(\"trusted_ca.pem\") // This is expired and should be ignored\n                .disableSSLVerification()\n                .build()\n        realm = Realm.getInstance(syncConfigSSL)\n        val all = realm.where(SyncDog::class.java).findAll()\n        try {\n            Assert.assertEquals(1, all.size.toLong())\n            Assert.assertEquals(\"Foo\", all[0]!!.name)\n        } finally {\n            realm.close()\n        }\n        looperThread.testComplete()\n    }\n\n    @Test\n    fun trustedRootCA_syncShouldFailWithoutTrustedCA() = looperThread.runBlocking {\n        val username = TestHelper.getRandomEmail()\n        val password = \"password\"\n        var user: User = app.registerUserAndLogin(username, password)\n\n        // 1. Copy a valid Realm to the server\n        val syncConfig: SyncConfiguration = configFactory.createSyncConfigurationBuilder(user)\n            .modules(DefaultSyncSchema())\n            .build()\n        var realm = Realm.getInstance(syncConfig)\n        realm.beginTransaction()\n        realm.createObject(SyncDog::class.java, ObjectId()).name = \"Foo\"\n        realm.commitTransaction()\n\n        // make sure the changes gets to the server\n        app.sync.getSession(syncConfig).uploadAllLocalChanges()\n        realm.close()\n        user.logOut()\n\n        // 2. Local state should now be completely reset. Open the Realm again with a new configuration which should\n        // download the uploaded changes.\n        user = app.login(Credentials.emailPassword(username, password))\n        val syncConfigSSL: SyncConfiguration = configFactory.createSyncConfigurationBuilder(user)\n                .name(\"useSsl\")\n                .modules(DefaultSyncSchema())\n                .trustedRootCA(\"untrusted_ca.pem\")\n                .build()\n        // waitForInitialRemoteData will throw an Internal error (125): Operation Canceled\n        SystemClock.sleep(TimeUnit.SECONDS.toMillis(2))\n        realm = Realm.getInstance(syncConfigSSL)\n        try {\n            realm.syncSession.downloadAllServerChanges()\n        } catch (ex: AppException) {\n            assertEquals(ErrorCode.CLIENT_SSL_SERVER_CERT_REJECTED, ex.errorCode)\n        } finally {\n            realm.close()\n        }\n        looperThread.testComplete()\n    }\n\n    @Test\n    fun combining_trustedRootCA_and_withoutSSLVerification_willWarn() = looperThread.runBlocking {\n        val username = TestHelper.getRandomEmail()\n        val password = \"password\"\n        val user: User = app.registerUserAndLogin(username, password)\n\n        val testLogger = TestLogger()\n        val originalLevel = RealmLog.getLevel()\n        RealmLog.add(testLogger)\n        RealmLog.setLevel(LogLevel.WARN)\n        configFactory.createSyncConfigurationBuilder(user)\n            .name(\"useSsl\")\n            .modules(DefaultSyncSchema())\n            .trustedRootCA(\"trusted_ca.pem\")\n            .disableSSLVerification()\n            .build()\n        assertEquals(\n            \"SSL Verification is disabled, the provided server certificate will not be used.\",\n            testLogger.message\n        )\n        RealmLog.remove(testLogger)\n        RealmLog.setLevel(originalLevel)\n        looperThread.testComplete()\n    }\n}"
  },
  {
    "path": "realm/realm-library/src/androidTestObjectServer/kotlin/io/realm/mongodb/sync/SessionTests.kt",
    "content": "/*\n * Copyright 2020 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 */\npackage io.realm.mongodb.sync\n\nimport androidx.test.annotation.UiThreadTest\nimport androidx.test.ext.junit.runners.AndroidJUnit4\nimport androidx.test.platform.app.InstrumentationRegistry\nimport io.realm.*\nimport io.realm.TestHelper.TestLogger\nimport io.realm.admin.ServerAdmin\nimport io.realm.entities.DefaultSyncSchema\nimport io.realm.entities.SyncStringOnly\nimport io.realm.entities.SyncStringOnlyModule\nimport io.realm.exceptions.RealmFileException\nimport io.realm.exceptions.RealmMigrationNeededException\nimport io.realm.internal.ErrorCategory\nimport io.realm.kotlin.syncSession\nimport io.realm.log.LogLevel\nimport io.realm.log.RealmLog\nimport io.realm.mongodb.*\nimport io.realm.rule.BlockingLooperThread\nimport io.realm.util.ResourceContainer\nimport io.realm.util.assertFailsWithMessage\nimport kotlinx.coroutines.runBlocking\nimport org.bson.types.ObjectId\nimport org.hamcrest.CoreMatchers\nimport org.junit.*\nimport org.junit.Test\nimport org.junit.runner.RunWith\nimport java.util.concurrent.TimeUnit\nimport java.util.concurrent.atomic.AtomicBoolean\nimport kotlin.test.*\n\n@RunWith(AndroidJUnit4::class)\nclass SessionTests {\n    private lateinit var configuration: SyncConfiguration\n    private lateinit var app: TestApp\n    private lateinit var admin: ServerAdmin\n    private lateinit var user: User\n\n    @get:Rule\n    val configFactory = TestSyncConfigurationFactory()\n\n    private val looperThread = BlockingLooperThread()\n\n    @Before\n    fun setUp() {\n        Realm.init(InstrumentationRegistry.getInstrumentation().targetContext)\n        app = TestApp()\n        admin = ServerAdmin(app)\n        // TODO We could potentially work without a fully functioning user to speed up tests, but\n        //  seems like the old  way of \"faking\" it, does now work for now, so using a real user.\n        // user = SyncTestUtils.createTestUser(app)\n        user = app.registerUserAndLogin(TestHelper.getRandomEmail(), \"123456\")\n        configuration = SyncConfiguration.Builder(user, \"default\")\n                .modules(DefaultSyncSchema())\n                .build()\n    }\n\n    @After\n    fun tearDown() {\n        if (this::app.isInitialized) {\n            app.close()\n        }\n    }\n\n    @Test\n    fun get_syncValues() {\n        Realm.getInstance(configuration).use { realm ->\n            val session = realm.syncSession\n            assertEquals(\"ws://127.0.0.1:9090/\", session.serverUrl.toString())\n            assertEquals(user, session.user)\n            assertEquals(configuration, session.configuration)\n        }\n    }\n\n    @Test\n    fun addDownloadProgressListener_nullThrows() {\n        Realm.getInstance(configuration).use { realm ->\n        val session = realm.syncSession\n            assertFailsWith<IllegalArgumentException> {\n                session.addDownloadProgressListener(ProgressMode.CURRENT_CHANGES, TestHelper.getNull())\n            }\n        }\n    }\n\n    @Test\n    fun addUploadProgressListener_nullThrows() {\n        Realm.getInstance(configuration).use { realm ->\n            val session = realm.syncSession\n            assertFailsWith<IllegalArgumentException> {\n                session.addUploadProgressListener(ProgressMode.CURRENT_CHANGES, TestHelper.getNull())\n            }\n        }\n    }\n\n    @Test\n    fun removeProgressListener() {\n        Realm.getInstance(configuration).use { realm ->\n            val session = realm.syncSession\n            val listeners = arrayOf(\n                    null,\n                    ProgressListener { progress: Progress? -> },\n                    ProgressListener { progress: Progress? -> }\n            )\n            session.addDownloadProgressListener(ProgressMode.CURRENT_CHANGES, TestHelper.allowNull(listeners[2]))\n            session.addDownloadProgressListener(ProgressMode.CURRENT_CHANGES, TestHelper.allowNull(listeners[2]))\n\n            // Check that remove works unconditionally for all input\n            for (listener in listeners) {\n                session.removeProgressListener(TestHelper.allowNull(listener))\n            }\n        }\n    }\n\n    // Check that a if Seamless loss Client Reset fails the error is correctly reported.\n    @Test\n    fun errorHandler_discardUnsyncedChangesStrategy_resetErrorHandled_deprecated() = looperThread.runBlocking {\n        val email = TestHelper.getRandomEmail()\n        val user: User = app.registerUserAndLogin(email, \"123456\")\n\n        val config = configFactory.createSyncConfigurationBuilder(user)\n            .testSchema(SyncStringOnly::class.java)\n            .syncClientResetStrategy(object : DiscardUnsyncedChangesStrategy {\n                override fun onBeforeReset(realm: Realm) {\n                    fail(\"This test case was not supposed to trigger DiscardUnsyncedChangesStrategy::onBeforeReset()\")\n                }\n\n                override fun onAfterReset(before: Realm, after: Realm) {\n                    fail(\"This test case was not supposed to trigger DiscardUnsyncedChangesStrategy::onAfterReset()\")\n                }\n\n                @Deprecated(\"Deprecated in favor of onManualResetFallback\")\n                override fun onError(session: SyncSession, error: ClientResetRequiredError) {\n                    val filePathFromError = error.originalFile.absolutePath\n                    val filePathFromConfig = session.configuration.path\n                    assertEquals(filePathFromError, filePathFromConfig)\n                    assertFalse(error.backupFile.exists())\n                    assertTrue(error.originalFile.exists())\n                    // Note, this error message is just the one created by ObjectStore for testing\n                    // The server will send a different message. This just ensures that we don't\n                    // accidentially modify or remove the message.\n                    assertEquals(\"Simulate Client Reset\", error.message)\n                    looperThread.testComplete()\n                }\n\n                override fun onManualResetFallback(\n                    session: SyncSession,\n                    error: ClientResetRequiredError\n                ) {\n                    // do nothing\n                }\n            })\n            .build()\n\n        val realm = Realm.getInstance(config)\n        looperThread.closeAfterTest(realm)\n        user.app.sync.simulateClientReset(realm.syncSession, ErrorCode.AUTOMATIC_CLIENT_RESET_FAILED)\n    }\n\n    // Check that a if Seamless loss Client Reset fails the error is correctly reported.\n    @Test\n    fun errorHandler_discardUnsyncedChangesStrategy_resetErrorHandled() = looperThread.runBlocking {\n        val email = TestHelper.getRandomEmail()\n        val user: User = app.registerUserAndLogin(email, \"123456\")\n\n        val config = configFactory.createSyncConfigurationBuilder(user)\n            .testSchema(SyncStringOnly::class.java)\n            .syncClientResetStrategy(object : DiscardUnsyncedChangesStrategy {\n                override fun onBeforeReset(realm: Realm) {\n                    fail(\"This test case was not supposed to trigger DiscardUnsyncedChangesStrategy::onBeforeReset()\")\n                }\n\n                override fun onAfterReset(before: Realm, after: Realm) {\n                    fail(\"This test case was not supposed to trigger DiscardUnsyncedChangesStrategy::onAfterReset()\")\n                }\n\n                @Deprecated(\"Deprecated in favor of onManualResetFallback\")\n                override fun onError(session: SyncSession, error: ClientResetRequiredError) {\n                    // do nothing\n                }\n\n                override fun onManualResetFallback(\n                    session: SyncSession,\n                    error: ClientResetRequiredError\n                ) {\n                    val filePathFromError = error.originalFile.absolutePath\n                    val filePathFromConfig = session.configuration.path\n                    assertEquals(filePathFromError, filePathFromConfig)\n                    assertFalse(error.backupFile.exists())\n                    assertTrue(error.originalFile.exists())\n                    // Note, this error message is just the one created by ObjectStore for testing\n                    // The server will send a different message. This just ensures that we don't\n                    // accidentially modify or remove the message.\n                    assertEquals(\"Simulate Client Reset\", error.message)\n                    looperThread.testComplete()\n                }\n            })\n            .build()\n\n        val realm = Realm.getInstance(config)\n        looperThread.closeAfterTest(realm)\n        user.app.sync.simulateClientReset(realm.syncSession, ErrorCode.AUTOMATIC_CLIENT_RESET_FAILED)\n    }\n\n    @Test\n    fun errorHandler_recoverOrDiscardUnsyncedChangesStrategy_resetErrorHandled() = looperThread.runBlocking {\n        val email = TestHelper.getRandomEmail()\n        val user: User = app.registerUserAndLogin(email, \"123456\")\n\n        val config = configFactory.createSyncConfigurationBuilder(user)\n            .testSchema(SyncStringOnly::class.java)\n            .syncClientResetStrategy(object: RecoverOrDiscardUnsyncedChangesStrategy {\n                override fun onBeforeReset(realm: Realm) {\n                    fail(\"This test case was not supposed to trigger RecoverOrDiscardUnsyncedChangesStrategy::onBeforeReset()\")\n                }\n\n                override fun onAfterRecovery(before: Realm, after: Realm) {\n                    fail(\"This test case was not supposed to trigger RecoverOrDiscardUnsyncedChangesStrategy::onAfterRecovery()\")\n                }\n\n                override fun onAfterDiscard(before: Realm, after: Realm) {\n                    fail(\"This test case was not supposed to trigger RecoverOrDiscardUnsyncedChangesStrategy::onAfterDiscard()\")\n                }\n\n                override fun onManualResetFallback(session: SyncSession, error: ClientResetRequiredError) {\n                    val filePathFromError = error.originalFile.absolutePath\n                    val filePathFromConfig = session.configuration.path\n                    assertEquals(filePathFromError, filePathFromConfig)\n                    assertFalse(error.backupFile.exists())\n                    assertTrue(error.originalFile.exists())\n                    // Note, this error message is just the one created by ObjectStore for testing\n                    // The server will send a different message. This just ensures that we don't\n                    // accidentially modify or remove the message.\n                    assertEquals(\"Simulate Client Reset\", error.message)\n                    looperThread.testComplete()\n                }\n            })\n            .build()\n\n        val realm = Realm.getInstance(config)\n        looperThread.closeAfterTest(realm)\n        user.app.sync.simulateClientReset(realm.syncSession, ErrorCode.AUTOMATIC_CLIENT_RESET_FAILED)\n    }\n\n    // Check that a Client Reset is correctly reported.\n    @Test\n    @Deprecated(\"clientResetHandler deprecated in favor of syncClientResetStrategy\")\n    fun errorHandler_manualClientResetReported() = looperThread.runBlocking {\n        val config = configFactory.createSyncConfigurationBuilder(user)\n                .testSchema(SyncStringOnly::class.java)\n                .clientResetHandler { session: SyncSession, error: ClientResetRequiredError ->\n                    val filePathFromError = error.originalFile.absolutePath\n                    val filePathFromConfig = session.configuration.path\n                    assertEquals(filePathFromError, filePathFromConfig)\n                    assertFalse(error.backupFile.exists())\n                    assertTrue(error.originalFile.exists())\n                    assertTrue(error.message!!.contains(\"Bad client file identifier\"), error.message)\n                    looperThread.testComplete()\n                }\n                .build()\n\n        val realm = Realm.getInstance(config)\n        looperThread.closeAfterTest(realm)\n\n        // Trigger error\n        admin.triggerClientReset(realm.syncSession) { /* Do nothing */ }\n    }\n\n    // Check that we can manually execute the Client Reset.\n    @Test\n    @Deprecated(\"clientResetHandler deprecated in favor of syncClientResetStrategy\")\n    fun errorHandler_manualExecuteClientReset() = looperThread.runBlocking {\n        val resources = ResourceContainer()\n\n        val config = configFactory.createSyncConfigurationBuilder(user)\n                .testSchema(SyncStringOnly::class.java)\n                .clientResetHandler { _: SyncSession, error: ClientResetRequiredError ->\n                    try {\n                        error.executeClientReset()\n                        fail(\"All Realms should be closed before executing Client Reset can be allowed\")\n                    } catch (ignored: IllegalStateException) {\n                    }\n\n                    // Execute Client Reset\n                    runBlocking(looperThread.asDispatcher()) {\n                        resources.close()\n                    }\n                    error.executeClientReset()\n\n                    // Validate that files have been moved\n                    assertFalse(error.originalFile.exists())\n                    assertTrue(error.backupFile.exists())\n                    looperThread.testComplete()\n                }\n                .build()\n        val realm = Realm.getInstance(config)\n        resources.add(realm)\n\n        // Trigger error\n        admin.triggerClientReset(realm.syncSession) { /* Do nothing */ }\n    }\n\n    // Check that we can use the backup SyncConfiguration to open the Realm.\n    @Test\n    @Deprecated(\"clientResetHandler deprecated in favor of syncClientResetStrategy\")\n    fun errorHandler_useBackupSyncConfigurationForClientReset() = looperThread.runBlocking {\n        val resources = ResourceContainer()\n        val config = configFactory.createSyncConfigurationBuilder(user)\n                .schema(SyncStringOnly::class.java)\n                .clientResetHandler { _: SyncSession?, error: ClientResetRequiredError ->\n                    // Execute Client Reset\n                    runBlocking(looperThread.asDispatcher()) {\n                        resources.close()\n                    }\n                    error.executeClientReset()\n\n                    // Validate that files have been moved\n                    assertFalse(error.originalFile.exists())\n                    assertTrue(error.backupFile.exists())\n                    val backupRealmConfiguration = error.backupRealmConfiguration\n                    assertNotNull(backupRealmConfiguration)\n                    assertFalse(backupRealmConfiguration is SyncConfiguration)\n                    assertTrue(backupRealmConfiguration.isRecoveryConfiguration)\n                    Realm.getInstance(backupRealmConfiguration).use { backupRealm ->\n                        assertFalse(backupRealm.isEmpty)\n                        assertEquals(1, backupRealm.where(SyncStringOnly::class.java).count())\n                        assertEquals(\"Foo\", backupRealm.where(SyncStringOnly::class.java).findAll().first()!!.chars)\n                    }\n\n                    // opening a Dynamic Realm should also work\n                    DynamicRealm.getInstance(backupRealmConfiguration).use { dynamicRealm ->\n                        assertNotNull(dynamicRealm.schema.get(SyncStringOnly.CLASS_NAME))\n                        val all = dynamicRealm.where(SyncStringOnly.CLASS_NAME).findAll()\n                        assertEquals(1, all.size.toLong())\n                        assertEquals(\"Foo\", all.first()!!.getString(SyncStringOnly.FIELD_CHARS))\n                    }\n                    looperThread.testComplete()\n                }\n                .build()\n        val realm = Realm.getInstance(config)\n        realm.executeTransaction {\n            realm.createObject(SyncStringOnly::class.java, ObjectId()).chars = \"Foo\"\n        }\n        resources.add(realm)\n\n        // Trigger error\n        admin.triggerClientReset(realm.syncSession) { /* Do nothing */ }\n    }\n\n    // Check that we can open the backup file without using the provided SyncConfiguration,\n    // this might be the case if the user decide to act upon the client reset later (providing s/he\n    // persisted the location of the file)\n    @Test\n    @Deprecated(\"clientResetHandler deprecated in favor of syncClientResetStrategy\")\n    fun errorHandler_useBackupSyncConfigurationAfterClientReset() = looperThread.runBlocking {\n        val resources = ResourceContainer()\n        val config = configFactory.createSyncConfigurationBuilder(user)\n                .modules(SyncStringOnlyModule())\n                .clientResetHandler { _: SyncSession, error: ClientResetRequiredError ->\n                    // Execute Client Reset\n                    runBlocking(looperThread.asDispatcher()) {\n                        resources.close()\n                    }\n                    error.executeClientReset()\n\n                    // Validate that files have been moved\n                    assertFalse(error.originalFile.exists())\n                    assertTrue(error.backupFile.exists())\n                    val backupFile = error.backupFile.absolutePath\n\n                    // this SyncConf doesn't specify any module, it will throw a migration required\n                    // exception since the backup Realm contain only StringOnly table\n                    var backupRealmConfiguration = SyncConfiguration.forRecovery(backupFile)\n                    assertFailsWith<RealmMigrationNeededException> {\n                        Realm.getInstance(backupRealmConfiguration)\n                    }\n\n                    // opening a DynamicRealm will work though\n                    DynamicRealm.getInstance(backupRealmConfiguration).use { dynamicRealm ->\n                        assertNotNull(dynamicRealm.schema.get(SyncStringOnly.CLASS_NAME))\n                        val all = dynamicRealm.where(SyncStringOnly.CLASS_NAME).findAll()\n                        assertEquals(1, all.size.toLong())\n                        assertEquals(\"Foo\", all.first()!!.getString(SyncStringOnly.FIELD_CHARS))\n                        // make sure we can't write to it (read-only Realm)\n                        assertFailsWith<java.lang.IllegalStateException> {\n                            dynamicRealm.beginTransaction()\n                        }\n                    }\n\n                    assertFailsWith<IllegalArgumentException> {\n                        SyncConfiguration.forRecovery(backupFile, null, SyncStringOnly::class.java)\n                    }\n\n                    // specifying the module will allow to open the typed Realm\n                    backupRealmConfiguration = SyncConfiguration.forRecovery(backupFile, null, SyncStringOnlyModule())\n                    Realm.getInstance(backupRealmConfiguration).use { backupRealm ->\n                        assertFalse(backupRealm.isEmpty)\n                        assertEquals(1, backupRealm.where(SyncStringOnly::class.java).count())\n                        val allSorted = backupRealm.where(SyncStringOnly::class.java).findAll()\n                        assertEquals(\"Foo\", allSorted[0]!!.chars)\n                    }\n                    looperThread.testComplete()\n                }\n                .build()\n\n        val realm = Realm.getInstance(config)\n        realm.executeTransaction {\n            it.createObject(SyncStringOnly::class.java, ObjectId()).chars = \"Foo\"\n        }\n        resources.add(realm)\n\n        // Trigger error\n        admin.triggerClientReset(realm.syncSession) { /* Do nothing */ }\n    }\n\n    // make sure the backup file Realm is encrypted with the same key as the original synced Realm.\n    @Test\n    @Deprecated(\"clientResetHandler deprecated in favor of syncClientResetStrategy\")\n    fun errorHandler_useClientResetEncrypted() = looperThread.runBlocking {\n        val resources = ResourceContainer()\n\n        val randomKey = TestHelper.getRandomKey()\n        val config = configFactory.createSyncConfigurationBuilder(user)\n                .encryptionKey(randomKey)\n                .modules(SyncStringOnlyModule())\n                .clientResetHandler { _: SyncSession, error: ClientResetRequiredError ->\n                    // Execute Client Reset\n                    runBlocking(looperThread.asDispatcher()) {\n                        resources.close()\n                    }\n                    error.executeClientReset()\n                    var backupRealmConfiguration = error.backupRealmConfiguration\n\n                    // can open encrypted backup Realm\n                    Realm.getInstance(backupRealmConfiguration).use { backupEncryptedRealm ->\n                        assertEquals(1, backupEncryptedRealm.where(SyncStringOnly::class.java).count())\n                        val allSorted = backupEncryptedRealm.where(SyncStringOnly::class.java).findAll()\n                        assertEquals(\"Foo\", allSorted[0]!!.chars)\n                    }\n                    val backupFile = error.backupFile.absolutePath\n\n                    // build a conf to open a DynamicRealm\n                    backupRealmConfiguration = SyncConfiguration.forRecovery(backupFile, randomKey, SyncStringOnlyModule())\n                    Realm.getInstance(backupRealmConfiguration).use { backupEncryptedRealm ->\n                        assertEquals(1, backupEncryptedRealm.where(SyncStringOnly::class.java).count())\n                        val allSorted = backupEncryptedRealm.where(SyncStringOnly::class.java).findAll()\n                        assertEquals(\"Foo\", allSorted[0]!!.chars)\n                    }\n\n                    // using wrong key throw\n                    assertFailsWith<RealmFileException> {\n                        Realm.getInstance(SyncConfiguration.forRecovery(backupFile, TestHelper.getRandomKey(), SyncStringOnlyModule()))\n                    }\n                    looperThread.testComplete()\n                }\n                .build()\n\n        val realm = Realm.getInstance(config)\n        realm.executeTransaction {\n            realm.createObject(SyncStringOnly::class.java, ObjectId()).chars = \"Foo\"\n        }\n        resources.add(realm)\n\n        // Trigger error\n        admin.triggerClientReset(realm.syncSession) { /* Do nothing */ }\n    }\n\n\n    // Check that a Client Reset is correctly reported.\n    @Test\n    fun errorHandler_manuallyRecoverUnsyncedChangesStrategy_errorHandled() = looperThread.runBlocking {\n        val config = configFactory.createSyncConfigurationBuilder(user)\n            .testSchema(SyncStringOnly::class.java)\n            .syncClientResetStrategy { session: SyncSession, error: ClientResetRequiredError ->\n                val filePathFromError = error.originalFile.absolutePath\n                val filePathFromConfig = session.configuration.path\n                assertEquals(filePathFromError, filePathFromConfig)\n                assertFalse(error.backupFile.exists())\n                assertTrue(error.originalFile.exists())\n                assertTrue(error.message!!.contains(\"Bad client file identifier\"), error.message)\n                looperThread.testComplete()\n            }\n            .build()\n\n        val realm = Realm.getInstance(config)\n        looperThread.closeAfterTest(realm)\n\n        // Trigger error\n        admin.triggerClientReset(realm.syncSession) { /* Do nothing */ }\n    }\n\n    // Check that we can manually execute the Client Reset.\n    @Test\n    fun errorHandler_manuallyRecoverUnsyncedChangesStrategy_executeClientReset() = looperThread.runBlocking {\n        val resources = ResourceContainer()\n\n        val config = configFactory.createSyncConfigurationBuilder(user)\n            .testSchema(SyncStringOnly::class.java)\n            .syncClientResetStrategy { _: SyncSession, error: ClientResetRequiredError ->\n                try {\n                    error.executeClientReset()\n                    fail(\"All Realms should be closed before executing Client Reset can be allowed\")\n                } catch (ignored: IllegalStateException) {\n                }\n\n                // Execute Client Reset\n                runBlocking(looperThread.asDispatcher()) {\n                    resources.close()\n                }\n                error.executeClientReset()\n\n                // Validate that files have been moved\n                assertFalse(error.originalFile.exists())\n                assertTrue(error.backupFile.exists())\n                looperThread.testComplete()\n            }\n            .build()\n        val realm = Realm.getInstance(config)\n        resources.add(realm)\n\n        // Trigger error\n        admin.triggerClientReset(realm.syncSession) { /* Do nothing */ }\n    }\n\n    // Check that we can use the backup SyncConfiguration to open the Realm.\n    @Test\n    fun errorHandler_manuallyRecoverUnsyncedChangesStrategy_attempRecoverData() = looperThread.runBlocking {\n        val resources = ResourceContainer()\n        val config = configFactory.createSyncConfigurationBuilder(user)\n            .schema(SyncStringOnly::class.java)\n            .syncClientResetStrategy { _: SyncSession, error: ClientResetRequiredError ->\n                // Execute Client Reset\n                runBlocking(looperThread.asDispatcher()) {\n                    resources.close()\n                }\n                error.executeClientReset()\n\n                // Validate that files have been moved\n                assertFalse(error.originalFile.exists())\n                assertTrue(error.backupFile.exists())\n                val backupRealmConfiguration = error.backupRealmConfiguration\n                assertNotNull(backupRealmConfiguration)\n                assertFalse(backupRealmConfiguration is SyncConfiguration)\n                assertTrue(backupRealmConfiguration.isRecoveryConfiguration)\n                Realm.getInstance(backupRealmConfiguration).use { backupRealm ->\n                    assertFalse(backupRealm.isEmpty)\n                    assertEquals(1, backupRealm.where(SyncStringOnly::class.java).count())\n                    assertEquals(\n                        \"Foo\",\n                        backupRealm.where(SyncStringOnly::class.java).findAll().first()!!.chars\n                    )\n                }\n\n                // opening a Dynamic Realm should also work\n                DynamicRealm.getInstance(backupRealmConfiguration).use { dynamicRealm ->\n                    assertNotNull(dynamicRealm.schema.get(SyncStringOnly.CLASS_NAME))\n                    val all = dynamicRealm.where(SyncStringOnly.CLASS_NAME).findAll()\n                    assertEquals(1, all.size.toLong())\n                    assertEquals(\"Foo\", all.first()!!.getString(SyncStringOnly.FIELD_CHARS))\n                }\n                looperThread.testComplete()\n            }\n            .build()\n        val realm = Realm.getInstance(config)\n        realm.executeTransaction {\n            realm.createObject(SyncStringOnly::class.java, ObjectId()).chars = \"Foo\"\n        }\n        resources.add(realm)\n\n        // Trigger error\n        admin.triggerClientReset(realm.syncSession) { /* Do nothing */ }\n    }\n\n    // Check that we can open the backup file without using the provided SyncConfiguration,\n    // this might be the case if the user decide to act upon the client reset later (providing s/he\n    // persisted the location of the file)\n    @Test\n    fun errorHandler_manuallyRecoverUnsyncedChangesStrategy_useBackupAfterClientReset() = looperThread.runBlocking {\n        val resources = ResourceContainer()\n        val config = configFactory.createSyncConfigurationBuilder(user)\n            .modules(SyncStringOnlyModule())\n            .syncClientResetStrategy { _: SyncSession, error: ClientResetRequiredError ->\n                // Execute Client Reset\n                runBlocking(looperThread.asDispatcher()) {\n                    resources.close()\n                }\n                error.executeClientReset()\n\n                // Validate that files have been moved\n                assertFalse(error.originalFile.exists())\n                assertTrue(error.backupFile.exists())\n                val backupFile = error.backupFile.absolutePath\n\n                // this SyncConf doesn't specify any module, it will throw a migration required\n                // exception since the backup Realm contain only StringOnly table\n                var backupRealmConfiguration = SyncConfiguration.forRecovery(backupFile)\n                assertFailsWith<RealmMigrationNeededException> {\n                    Realm.getInstance(backupRealmConfiguration)\n                }\n\n                // opening a DynamicRealm will work though\n                DynamicRealm.getInstance(backupRealmConfiguration).use { dynamicRealm ->\n                    assertNotNull(dynamicRealm.schema.get(SyncStringOnly.CLASS_NAME))\n                    val all = dynamicRealm.where(SyncStringOnly.CLASS_NAME).findAll()\n                    assertEquals(1, all.size.toLong())\n                    assertEquals(\"Foo\", all.first()!!.getString(SyncStringOnly.FIELD_CHARS))\n                    // make sure we can't write to it (read-only Realm)\n                    assertFailsWith<java.lang.IllegalStateException> {\n                        dynamicRealm.beginTransaction()\n                    }\n                }\n\n                assertFailsWith<IllegalArgumentException> {\n                    SyncConfiguration.forRecovery(backupFile, null, SyncStringOnly::class.java)\n                }\n\n                // specifying the module will allow to open the typed Realm\n                backupRealmConfiguration =\n                    SyncConfiguration.forRecovery(backupFile, null, SyncStringOnlyModule())\n                Realm.getInstance(backupRealmConfiguration).use { backupRealm ->\n                    assertFalse(backupRealm.isEmpty)\n                    assertEquals(1, backupRealm.where(SyncStringOnly::class.java).count())\n                    val allSorted = backupRealm.where(SyncStringOnly::class.java).findAll()\n                    assertEquals(\"Foo\", allSorted[0]!!.chars)\n                }\n                looperThread.testComplete()\n            }\n            .build()\n\n        val realm = Realm.getInstance(config)\n        realm.executeTransaction {\n            it.createObject(SyncStringOnly::class.java, ObjectId()).chars = \"Foo\"\n        }\n        resources.add(realm)\n\n        // Trigger error\n        admin.triggerClientReset(realm.syncSession) { /* Do nothing */ }\n    }\n\n    // make sure the backup file Realm is encrypted with the same key as the original synced Realm.\n    @Test\n    fun errorHandler_manuallyRecoverUnsyncedChangesStrategy_encrypted() = looperThread.runBlocking {\n        val resources = ResourceContainer()\n\n        val randomKey = TestHelper.getRandomKey()\n        val config = configFactory.createSyncConfigurationBuilder(user)\n            .encryptionKey(randomKey)\n            .modules(SyncStringOnlyModule())\n            .syncClientResetStrategy { _: SyncSession, error: ClientResetRequiredError ->\n                // Execute Client Reset\n                runBlocking(looperThread.asDispatcher()) {\n                    resources.close()\n                }\n                error.executeClientReset()\n                var backupRealmConfiguration = error.backupRealmConfiguration\n\n                // can open encrypted backup Realm\n                Realm.getInstance(backupRealmConfiguration).use { backupEncryptedRealm ->\n                    assertEquals(1, backupEncryptedRealm.where(SyncStringOnly::class.java).count())\n                    assertEquals(\n                        \"Foo\",\n                        backupEncryptedRealm.where(SyncStringOnly::class.java).findAll()\n                            .first()!!.chars\n                    )\n                }\n                val backupFile = error.backupFile.absolutePath\n\n                // build a conf to open a DynamicRealm\n                backupRealmConfiguration =\n                    SyncConfiguration.forRecovery(backupFile, randomKey, SyncStringOnlyModule())\n                Realm.getInstance(backupRealmConfiguration).use { backupEncryptedRealm ->\n                    assertEquals(1, backupEncryptedRealm.where(SyncStringOnly::class.java).count())\n                    val allSorted = backupEncryptedRealm.where(SyncStringOnly::class.java).findAll()\n                    assertEquals(\"Foo\", allSorted[0]!!.chars)\n                }\n\n                // using wrong key throw\n                assertFailsWith<RealmFileException> {\n                    Realm.getInstance(\n                        SyncConfiguration.forRecovery(\n                            backupFile,\n                            TestHelper.getRandomKey(),\n                            SyncStringOnlyModule()\n                        )\n                    )\n                }\n                looperThread.testComplete()\n            }\n            .build()\n\n        val realm = Realm.getInstance(config)\n        realm.executeTransaction {\n            realm.createObject(SyncStringOnly::class.java, ObjectId()).chars = \"Foo\"\n        }\n        resources.add(realm)\n\n        // Trigger error\n        admin.triggerClientReset(realm.syncSession) { /* Do nothing */ }\n    }\n\n    @Test\n    fun errorHandler_recoverUnsyncedChangesStrategy_resetErrorHandled() = looperThread.runBlocking {\n        val config = configFactory.createSyncConfigurationBuilder(user)\n            .testSchema(SyncStringOnly::class.java)\n            .syncClientResetStrategy(object: RecoverUnsyncedChangesStrategy {\n                override fun onBeforeReset(realm: Realm) {\n                    fail(\"This test case was not supposed to trigger RecoverUnsyncedChangesStrategy::onBeforeReset()\")\n                }\n\n                override fun onAfterReset(before: Realm, after: Realm) {\n                    fail(\"This test case was not supposed to trigger RecoverUnsyncedChangesStrategy::onAfterReset()\")\n                }\n\n                override fun onManualResetFallback(session: SyncSession, error: ClientResetRequiredError) {\n                    val filePathFromError = error.originalFile.absolutePath\n                    val filePathFromConfig = session.configuration.path\n                    assertEquals(filePathFromError, filePathFromConfig)\n                    assertFalse(error.backupFile.exists())\n                    assertTrue(error.originalFile.exists())\n                    // Note, this error message is just the one created by ObjectStore for testing\n                    // The server will send a different message. This just ensures that we don't\n                    // accidentially modify or remove the message.\n                    assertEquals(\"Simulate Client Reset\", error.message)\n                    looperThread.testComplete()\n                }\n            })\n            .build()\n\n        val realm = Realm.getInstance(config)\n        looperThread.closeAfterTest(realm)\n\n        // Trigger error\n        user.app.sync.simulateClientReset(realm.syncSession, ErrorCode.AUTOMATIC_CLIENT_RESET_FAILED)\n    }\n\n    @Test\n    @UiThreadTest\n    fun uploadAllLocalChanges_throwsOnUiThread() {\n        Realm.getInstance(configuration).use { realm ->\n            assertFailsWith<java.lang.IllegalStateException> {\n                realm.syncSession.uploadAllLocalChanges()\n            }\n        }\n    }\n\n    @Test\n    @UiThreadTest\n    fun uploadAllLocalChanges_withTimeout_throwsOnUiThread() {\n        Realm.getInstance(configuration).use { realm ->\n            assertFailsWith<IllegalStateException> {\n                realm.syncSession.uploadAllLocalChanges(30, TimeUnit.SECONDS)\n            }\n        }\n    }\n\n    @Test\n    fun uploadAllLocalChanges_withTimeout_invalidParametersThrows() {\n        Realm.getInstance(configuration). use { realm ->\n            val session = realm.syncSession\n            assertFailsWith<IllegalArgumentException> {\n                session.uploadAllLocalChanges(-1, TimeUnit.SECONDS)\n            }\n            assertFailsWith<IllegalArgumentException> {\n                session.uploadAllLocalChanges(1, TestHelper.getNull())\n            }\n        }\n    }\n\n    @Test\n    fun uploadAllLocalChanges_returnFalseWhenTimedOut() {\n        Realm.getInstance(configuration).use { realm ->\n            val session = realm.syncSession\n            // We never assume to be able to download changes with one 1ms\n            assertFalse(session.uploadAllLocalChanges(1, TimeUnit.MILLISECONDS))\n        }\n    }\n\n    @Test\n    @UiThreadTest\n    fun downloadAllServerChanges_throwsOnUiThread() {\n        Realm.getInstance(configuration).use { realm ->\n            assertFailsWith<IllegalStateException> {\n                realm.syncSession.downloadAllServerChanges()\n            }\n        }\n    }\n\n    @Test\n    @UiThreadTest\n    fun downloadAllServerChanges_withTimeout_throwsOnUiThread() {\n        Realm.getInstance(configuration).use { realm ->\n            assertFailsWith<IllegalStateException> {\n                realm.syncSession.downloadAllServerChanges(30, TimeUnit.SECONDS)\n            }\n        }\n    }\n\n    @Test\n    fun downloadAllServerChanges_withTimeout_invalidParametersThrows() {\n        Realm.getInstance(configuration).use { realm ->\n            val session = realm.syncSession\n            assertFailsWith<IllegalArgumentException> {\n                session.downloadAllServerChanges(-1, TimeUnit.SECONDS)\n            }\n            assertFailsWith<IllegalArgumentException> {\n                session.downloadAllServerChanges(1, TestHelper.getNull())\n            }\n        }\n    }\n\n    @Test\n    fun downloadAllServerChanges_returnFalseWhenTimedOut() {\n        Realm.getInstance(configuration).use { realm ->\n            val session = realm.syncSession\n            // We never assume to be able to download changes within one 1ms\n            assertFalse(session.downloadAllServerChanges(1, TimeUnit.MILLISECONDS))\n        }\n    }\n\n    @Test\n    @UiThreadTest\n    fun unrecognizedErrorCode_errorHandler() {\n        val errorHandlerCalled = AtomicBoolean(false)\n        configuration = configFactory.createSyncConfigurationBuilder(user)\n                .testSchema(SyncStringOnly::class.java)\n                .errorHandler { session: SyncSession?, error: AppException ->\n                    errorHandlerCalled.set(true)\n                    assertEquals(ErrorCode.UNKNOWN, error.errorCode)\n                    assertEquals(ErrorCode.Category.FATAL, error.category)\n                }\n                .build()\n\n        Realm.getInstance(configuration).use { realm ->\n            val session = realm.syncSession\n            // TODO This test requires errors to be reported, when running full test suite\n            //  some test running before leaves it at FATAL. Do we have conventions about it? For\n            //  now just lowering while triggering the actual test\n            val level = RealmLog.getLevel()\n            RealmLog.setLevel(LogLevel.WARN)\n            val testLogger = TestLogger()\n            RealmLog.add(testLogger)\n            session.notifySessionError(ErrorCategory.RLM_SYNC_ERROR_CATEGORY_UNKNOWN, 3, \"Unknown Error\", \"\")\n            RealmLog.remove(testLogger)\n            // TODO See comment above\n            RealmLog.setLevel(level)\n            assertTrue(errorHandlerCalled.get())\n            assertEquals(\"Unknown error code: 'unknown:3'\", testLogger.message)\n        }\n    }\n\n    // Closing the Realm should remove the session\n    @Test\n    fun getSessionThrowsOnNonExistingSession() {\n        Realm.getInstance(configuration).use { realm ->\n            val session = realm.syncSession\n            assertEquals(configuration, session.configuration)\n        // Exiting the scope closes the Realm and should remove the session\n        }\n        assertFailsWithMessage<IllegalStateException>(\n                CoreMatchers.containsString( \"No SyncSession found using the path : \")\n        ) {\n            app.sync.getSession(configuration)\n        }\n    }\n\n    @Test\n    fun stop_doesNotThrowIfCalledWhenRealmIsClosed() {\n        val realm = Realm.getInstance(configuration)\n        val session = realm.syncSession\n        realm.close()\n        session.stop()\n    }\n\n    // Smoke test of discouraged method of retrieving session\n    @Test\n    fun getOrCreateSession() {\n        assertNotNull(app.sync.getOrCreateSession(configuration))\n    }\n\n    @Test\n    fun getAllSessions(){\n        val realm = Realm.getInstance(configuration)\n        val sessions = app.sync.allSessions\n\n        assertNotNull(sessions)\n        assertEquals(1, sessions.size)\n\n        realm.close()\n    }\n    \n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTestObjectServer/kotlin/io/realm/mongodb/sync/SubscriptionSetTests.kt",
    "content": "/*\n * Copyright 2022 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 */\npackage io.realm.mongodb.sync\n\nimport androidx.test.ext.junit.runners.AndroidJUnit4\nimport androidx.test.platform.app.InstrumentationRegistry\nimport io.realm.Realm\nimport io.realm.TEST_APP_3\nimport io.realm.TestApp\nimport io.realm.TestHelper\nimport io.realm.TestSyncConfigurationFactory\nimport io.realm.admin.ServerAdmin\nimport io.realm.entities.FlexSyncColor\nimport io.realm.kotlin.where\nimport io.realm.log.LogLevel\nimport io.realm.log.RealmLog\nimport io.realm.mongodb.close\nimport io.realm.mongodb.registerUserAndLogin\nimport io.realm.rule.BlockingLooperThread\nimport org.junit.After\nimport org.junit.Assert.assertEquals\nimport org.junit.Assert.assertFalse\nimport org.junit.Assert.assertNotNull\nimport org.junit.Assert.assertNull\nimport org.junit.Assert.assertTrue\nimport org.junit.Assert.fail\nimport org.junit.Before\nimport org.junit.Ignore\nimport org.junit.Rule\nimport org.junit.Test\nimport org.junit.runner.RunWith\nimport java.lang.RuntimeException\nimport java.util.concurrent.TimeUnit\nimport kotlin.test.assertFailsWith\n\n/**\n * Class wrapping tests for SubscriptionSets\n */\n@RunWith(AndroidJUnit4::class)\nclass SubscriptionSetTests {\n\n    @get:Rule\n    val configFactory = TestSyncConfigurationFactory()\n    private val looperThread = BlockingLooperThread()\n\n    private lateinit var app: TestApp\n    private lateinit var realmConfig: SyncConfiguration\n    private lateinit var realm: Realm\n\n    @Before\n    fun setUp() {\n        Realm.init(InstrumentationRegistry.getInstrumentation().targetContext)\n        RealmLog.setLevel(LogLevel.ALL)\n        app = TestApp(appName = TEST_APP_3)\n        ServerAdmin(app).enableFlexibleSync() // Currrently required because importing doesn't work\n        val user = app.registerUserAndLogin(TestHelper.getRandomEmail(), \"123456\")\n        realmConfig = configFactory.createFlexibleSyncConfigurationBuilder(user)\n            .schema(FlexSyncColor::class.java)\n            .build()\n        realm = Realm.getInstance(realmConfig)\n    }\n\n    @After\n    fun tearDown() {\n        realm.close()\n        if (this::app.isInitialized) {\n            app.close()\n        }\n    }\n\n    @Test\n    fun initialSubscriptions() {\n        val subscriptions = realm.subscriptions\n        assertEquals(0, subscriptions.size())\n        assertEquals(SubscriptionSet.State.PENDING, subscriptions.state) // it cannot be UNCOMMITTED since it's not a mutable subscription set\n    }\n\n    @Test\n    fun find() {\n        val subscriptions = realm.subscriptions\n        assertNull(subscriptions.find(realm.where<FlexSyncColor>()))\n        subscriptions.update { mutableSubs ->\n            mutableSubs.addOrUpdate(Subscription.create(realm.where<FlexSyncColor>()))\n        }\n        val sub: Subscription? = subscriptions.find(realm.where<FlexSyncColor>())\n        assertNotNull(sub)\n        assertEquals(\"FlexSyncColor\", sub!!.objectType)\n    }\n\n    @Test\n    fun find_byName() {\n        val subscriptions = realm.subscriptions\n        assertNull(subscriptions.find(\"foo\"))\n        subscriptions.update { mutableSubs ->\n            mutableSubs.addOrUpdate(Subscription.create(\"foo\", realm.where<FlexSyncColor>()))\n        }\n\n        val sub: Subscription? = subscriptions.find(\"foo\")\n        assertNotNull(sub)\n        assertEquals(\"foo\", sub!!.name)\n    }\n\n    @Test\n    fun getState() {\n        val subscriptions = realm.subscriptions\n        assertEquals(SubscriptionSet.State.PENDING, subscriptions.state) // it cannot be UNCOMMITTED since it's not a mutable subscription set\n        subscriptions.update { mutableSubs ->\n            mutableSubs.addOrUpdate(Subscription.create(\"test\", realm.where<FlexSyncColor>()))\n        }\n        assertEquals(SubscriptionSet.State.PENDING, subscriptions.state)\n        subscriptions.waitForSynchronization()\n        assertEquals(SubscriptionSet.State.COMPLETE, subscriptions.state)\n        subscriptions.update { mutableSubs ->\n            mutableSubs.addOrUpdate(Subscription.create(\"test\", realm.where<FlexSyncColor>().limit(1)))\n        }\n        subscriptions.waitForSynchronization()\n        assertEquals(SubscriptionSet.State.ERROR, subscriptions.state)\n    }\n\n    @Test\n    fun size() {\n        val subscriptions = realm.subscriptions\n        assertEquals(0, subscriptions.size())\n        subscriptions.update { mutableSubs ->\n            mutableSubs.addOrUpdate(Subscription.create(realm.where<FlexSyncColor>()))\n        }\n        assertEquals(1, subscriptions.size())\n        subscriptions.update { mutableSubs ->\n            mutableSubs.removeAll()\n        }\n        assertEquals(0, subscriptions.size())\n    }\n\n    @Test\n    fun errorMessage() {\n        val subscriptions = realm.subscriptions\n        assertNull(subscriptions.errorMessage)\n        subscriptions.update { mutableSubs ->\n            mutableSubs.addOrUpdate(Subscription.create(realm.where<FlexSyncColor>().limit(1)))\n        }\n        subscriptions.waitForSynchronization()\n        assertTrue(subscriptions.errorMessage!!.contains(\"Client provided query with bad syntax\"))\n        subscriptions.update { mutableSubs ->\n            mutableSubs.removeAll() // TODO Removing all queries seems to provoke an error on the server\n            mutableSubs.addOrUpdate(\n                Subscription.create(realm.where<FlexSyncColor>())\n            )\n        }\n        subscriptions.waitForSynchronization()\n        assertNull(subscriptions.errorMessage)\n    }\n\n    @Test\n    fun iterator_zeroSize() {\n        val subscriptions = realm.subscriptions\n        val iterator: MutableIterator<Subscription> = subscriptions.iterator()\n        assertFalse(iterator.hasNext())\n        assertFailsWith<NoSuchElementException> { iterator.next() }\n        assertFailsWith<UnsupportedOperationException> { iterator.remove() }\n    }\n\n    @Test\n    fun iterator() {\n        val subscriptions = realm.subscriptions\n        subscriptions.update { mutableSub ->\n            mutableSub.addOrUpdate(Subscription.create(\"sub1\", realm.where<FlexSyncColor>()))\n        }\n        val iterator: MutableIterator<Subscription> = subscriptions.iterator()\n        assertTrue(iterator.hasNext())\n        assertEquals(\"sub1\", iterator.next().name)\n        assertFalse(iterator.hasNext())\n        assertFailsWith<NoSuchElementException> { iterator.next() }\n        assertFailsWith<UnsupportedOperationException> { iterator.remove() }\n    }\n\n    @Test\n    fun subscriptions_throwsOnClosedRealm() {\n        realm.close()\n        assertFailsWith<IllegalStateException> { realm.subscriptions }\n    }\n\n    @Test\n    @Ignore\n    fun subscriptions_accessAfterRealmClosed() {\n        val subscriptions = realm.subscriptions\n        realm.close()\n        // FIXME: Results in native crash. Must check if Realm is closed.\n        subscriptions.update { mutableSubs ->\n            mutableSubs.addOrUpdate(Subscription.create(realm.where<FlexSyncColor>()))\n        }\n        subscriptions.waitForSynchronization()\n        assertEquals(SubscriptionSet.State.COMPLETE, subscriptions.state)\n    }\n\n    @Test\n    fun waitForSynchronizationInitialSubscriptions() {\n        val subscriptions = realm.subscriptions\n         assertTrue(subscriptions.waitForSynchronization())\n         assertEquals(SubscriptionSet.State.COMPLETE, subscriptions.state)\n         assertEquals(0, subscriptions.size())\n    }\n\n    @Test\n    fun waitForSynchronizationInitialEmptySubscriptionSet() {\n        val subscriptions = realm.subscriptions\n        subscriptions.update { /* Do nothing */ }\n\n        assertTrue(subscriptions.waitForSynchronization())\n        assertEquals(SubscriptionSet.State.COMPLETE, subscriptions.state)\n        assertEquals(0, subscriptions.size())\n    }\n\n    @Test\n    fun waitForSynchronizationAfterInsert() {\n        var updatedSubs = realm.subscriptions.update { mutableSubs ->\n            mutableSubs.add(Subscription.create(\"test\", realm.where<FlexSyncColor>()))\n        }\n        assertFalse(updatedSubs.state == SubscriptionSet.State.COMPLETE)\n        assertTrue(updatedSubs.waitForSynchronization())\n        assertEquals(SubscriptionSet.State.COMPLETE, updatedSubs.state)\n    }\n\n    @Test\n    fun waitForSynchronizationError() {\n        var updatedSubs = realm.subscriptions.update { mutableSubs ->\n            mutableSubs.addOrUpdate(Subscription.create(\"test\", realm.where<FlexSyncColor>().limit(1)))\n        }\n        assertFalse(updatedSubs.waitForSynchronization())\n        assertEquals(SubscriptionSet.State.ERROR, updatedSubs.state)\n        assertTrue(updatedSubs.errorMessage!!.contains(\"Client provided query with bad syntax\"))\n    }\n\n    @Test\n    fun waitForSynchronization_timeOut() {\n        var updatedSubs = realm.subscriptions.update { mutableSubs ->\n            mutableSubs.add(Subscription.create(\"sub\", realm.where<FlexSyncColor>()))\n        }\n        assertTrue(updatedSubs.waitForSynchronization(1, TimeUnit.MINUTES))\n    }\n\n    @Test\n    fun waitForSynchronizationAsync() = looperThread.runBlocking {\n        val realm = Realm.getInstance(realmConfig)\n        looperThread.closeAfterTest(realm)\n        val subs = realm.subscriptions\n        subs.update {\n            it.add(Subscription.create(realm.where<FlexSyncColor>()))\n        }\n        subs.waitForSynchronizationAsync(object:\n            SubscriptionSet.StateChangeCallback {\n            override fun onStateChange(subscriptions: SubscriptionSet) {\n                assertEquals(1, subscriptions.size())\n                assertEquals(SubscriptionSet.State.COMPLETE, subscriptions.state)\n                looperThread.testComplete()\n            }\n            override fun onError(e: Throwable) {\n                fail(e.toString())\n            }\n        })\n    }\n\n    @Test\n    fun waitForSynchronizationAsync_error() = looperThread.runBlocking {\n        // Server errors are not reported as Exceptions but as state changes\n        val realm = Realm.getInstance(realmConfig)\n        looperThread.closeAfterTest(realm)\n        val subs = realm.subscriptions\n        subs.update { mutableSubs ->\n            mutableSubs.add(Subscription.create(\"test\", realm.where<FlexSyncColor>().limit(1)))\n        }\n        subs.waitForSynchronizationAsync(object:\n            SubscriptionSet.StateChangeCallback {\n            override fun onStateChange(subscriptions: SubscriptionSet) {\n                assertEquals(SubscriptionSet.State.ERROR, subscriptions.state)\n                assertTrue(subscriptions.errorMessage!!.contains(\"Client provided query with bad syntax\"))\n                looperThread.testComplete()\n            }\n            override fun onError(e: Throwable) {\n                fail(e.toString())\n            }\n        })\n    }\n\n    @Test\n    fun waitForSynchronizationAsync_timeOut() = looperThread.runBlocking {\n        val realm = Realm.getInstance(realmConfig)\n        looperThread.closeAfterTest(realm)\n        val subs = realm.subscriptions\n        subs.update {\n            it.add(Subscription.create(realm.where<FlexSyncColor>()))\n        }\n        subs.waitForSynchronizationAsync(1, TimeUnit.MINUTES, object:\n            SubscriptionSet.StateChangeCallback {\n            override fun onStateChange(subscriptions: SubscriptionSet) {\n                assertEquals(1, subscriptions.size())\n                assertEquals(SubscriptionSet.State.COMPLETE, subscriptions.state)\n                looperThread.testComplete()\n            }\n            override fun onError(e: Throwable) {\n                fail(e.toString())\n            }\n        })\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTestObjectServer/kotlin/io/realm/mongodb/sync/SubscriptionTests.kt",
    "content": "/*\n * Copyright 2022 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 */\npackage io.realm.mongodb.sync\n\nimport androidx.test.ext.junit.runners.AndroidJUnit4\nimport androidx.test.platform.app.InstrumentationRegistry\nimport io.realm.Realm\nimport io.realm.TEST_APP_3\nimport io.realm.TestApp\nimport io.realm.TestHelper\nimport io.realm.TestSyncConfigurationFactory\nimport io.realm.entities.FlexSyncColor\nimport io.realm.mongodb.close\nimport io.realm.mongodb.registerUserAndLogin\nimport org.junit.After\nimport org.junit.Before\nimport org.junit.Rule\nimport org.junit.Test\nimport org.junit.runner.RunWith\nimport io.realm.kotlin.where\nimport org.junit.Assert.assertEquals\nimport org.junit.Assert.assertNull\nimport java.lang.IllegalArgumentException\nimport kotlin.test.assertFailsWith\n\n/**\n * Class wrapping tests for SubscriptionSets\n */\n@RunWith(AndroidJUnit4::class)\nclass SubscriptionTests {\n\n    @get:Rule\n    val configFactory = TestSyncConfigurationFactory()\n\n    private lateinit var app: TestApp\n    private lateinit var realm: Realm\n\n    @Before\n    fun setUp() {\n        Realm.init(InstrumentationRegistry.getInstrumentation().targetContext)\n        app = TestApp(appName = TEST_APP_3)\n        val user = app.registerUserAndLogin(TestHelper.getRandomEmail(), \"123456\")\n        val config = configFactory.createFlexibleSyncConfigurationBuilder(user)\n            .schema(FlexSyncColor::class.java)\n            .build()\n        realm = Realm.getInstance(config)\n    }\n\n    @After\n    fun tearDown() {\n        realm.close()\n        if (this::app.isInitialized) {\n            app.close()\n        }\n    }\n\n    @Test\n    fun unmanagedSubscription() {\n        var sub = Subscription.create(\"sub\", realm.where<FlexSyncColor>())\n        assertEquals(\"sub\", sub.name)\n        assertEquals(\"FlexSyncColor\", sub.objectType)\n        assertEquals(\"TRUEPREDICATE \", sub.query)\n        assertNull(sub.createdAt)\n        assertNull(sub.updatedAt)\n\n        sub = Subscription.create(realm.where<FlexSyncColor>())\n        assertNull(sub.name)\n        assertEquals(\"FlexSyncColor\", sub.objectType)\n        assertEquals(\"TRUEPREDICATE \", sub.query)\n        assertNull(sub.createdAt)\n        assertNull(sub.updatedAt)\n    }\n\n    @Test\n    fun create_emptyNameThrows() {\n        val query = realm.where<FlexSyncColor>()\n        assertFailsWith<IllegalArgumentException> {\n            Subscription.create(\"\", query)\n        }\n    }\n\n}"
  },
  {
    "path": "realm/realm-library/src/androidTestObjectServer/kotlin/io/realm/mongodb/sync/SyncConfigurationTests.kt",
    "content": "/*\n * Copyright 2020 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 */\npackage io.realm.mongodb.sync\n\nimport androidx.test.ext.junit.runners.AndroidJUnit4\nimport androidx.test.platform.app.InstrumentationRegistry\nimport io.reactivex.Flowable\nimport io.reactivex.Observable\nimport io.reactivex.Single\nimport io.realm.*\nimport io.realm.coroutines.FlowFactory\nimport io.realm.entities.SyncStringOnly\nimport io.realm.entities.SyncStringOnlyModule\nimport io.realm.kotlin.createObject\nimport io.realm.kotlin.where\nimport io.realm.mongodb.AppException\nimport io.realm.mongodb.SyncTestUtils.Companion.createTestUser\nimport io.realm.mongodb.User\nimport io.realm.mongodb.close\nimport io.realm.mongodb.registerUserAndLogin\nimport io.realm.rx.CollectionChange\nimport io.realm.rx.ObjectChange\nimport io.realm.rx.RxObservableFactory\nimport kotlinx.coroutines.flow.Flow\nimport kotlinx.coroutines.flow.flowOf\nimport org.bson.BsonString\nimport org.bson.types.ObjectId\nimport org.junit.*\nimport org.junit.Assert.*\nimport org.junit.Test\nimport org.junit.runner.RunWith\nimport java.lang.ClassCastException\nimport kotlin.test.assertFailsWith\nimport java.lang.IllegalStateException\nimport java.util.UUID\n\n@RunWith(AndroidJUnit4::class)\nclass SyncConfigurationTests {\n\n    companion object {\n        private const val DEFAULT_PARTITION = \"default\"\n    }\n\n    @get:Rule\n    val configFactory = TestSyncConfigurationFactory()\n\n    private lateinit var app: TestApp\n\n    @Before\n    fun setUp() {\n        Realm.init(InstrumentationRegistry.getInstrumentation().targetContext)\n        app = TestApp()\n    }\n\n    @After\n    fun tearDown() {\n        if (this::app.isInitialized) {\n            app.close()\n        }\n    }\n\n    @Test\n    fun errorHandler() {\n        val builder: SyncConfiguration.Builder = SyncConfiguration.Builder(createTestUser(app), DEFAULT_PARTITION)\n        val errorHandler: SyncSession.ErrorHandler = object : SyncSession.ErrorHandler {\n            override fun onError(session: SyncSession, error: AppException) {}\n        }\n        val config = builder.errorHandler(errorHandler).build()\n        assertEquals(errorHandler, config.errorHandler)\n    }\n\n    @Test\n    fun errorHandler_fromAppConfiguration() {\n        val user: User = createTestUser(app)\n        val config: SyncConfiguration = SyncConfiguration.defaultConfig(user, DEFAULT_PARTITION)\n        assertEquals(app.configuration.defaultErrorHandler, config.errorHandler)\n    }\n\n    @Test\n    fun errorHandler_nullThrows() {\n        val user: User = createTestUser(app)\n        val builder = SyncConfiguration.Builder(user, DEFAULT_PARTITION)\n        assertFailsWith<IllegalArgumentException> { builder.errorHandler(TestHelper.getNull()) }\n    }\n\n    @Test\n    fun clientResetStrategy_manual() {\n        val builder: SyncConfiguration.Builder = SyncConfiguration.Builder(createTestUser(app), DEFAULT_PARTITION)\n        val strategy = ManuallyRecoverUnsyncedChangesStrategy { _, _ -> }\n        val config = builder.syncClientResetStrategy(strategy).build()\n        assertEquals(strategy, config.syncClientResetStrategy)\n    }\n\n    @Test\n    fun clientResetStrategy_automatic() {\n        val builder: SyncConfiguration.Builder = SyncConfiguration.Builder(createTestUser(app), DEFAULT_PARTITION)\n        val strategy = object: RecoverUnsyncedChangesStrategy {\n            override fun onBeforeReset(realm: Realm) {\n                fail(\"Callback should not be reachable\")\n            }\n\n            override fun onAfterReset(before: Realm, after: Realm) {\n                fail(\"Callback should not be reachable\")\n            }\n\n            override fun onManualResetFallback(session: SyncSession, error: ClientResetRequiredError) {\n                fail(\"Callback should not be reachable\")\n            }\n        }\n        val config = builder.syncClientResetStrategy(strategy).build()\n        assertEquals(strategy, config.syncClientResetStrategy)\n    }\n\n    @Test\n    fun clientResetStrategy_automaticOrDiscard() {\n        val builder: SyncConfiguration.Builder = SyncConfiguration.Builder(createTestUser(app), DEFAULT_PARTITION)\n        val strategy = object: RecoverOrDiscardUnsyncedChangesStrategy {\n            override fun onBeforeReset(realm: Realm) {\n                fail(\"Callback should not be reachable\")\n            }\n\n            override fun onAfterRecovery(before: Realm, after: Realm) {\n                fail(\"Callback should not be reachable\")\n            }\n\n            override fun onAfterDiscard(before: Realm, after: Realm) {\n                fail(\"Callback should not be reachable\")\n            }\n\n            override fun onManualResetFallback(session: SyncSession, error: ClientResetRequiredError) {\n                fail(\"Callback should not be reachable\")\n            }\n        }\n        val config = builder.syncClientResetStrategy(strategy).build()\n        assertEquals(strategy, config.syncClientResetStrategy)\n    }\n\n    @Test\n    fun clientResetHandler_fromAppConfiguration() {\n        val user: User = createTestUser(app)\n        val config: SyncConfiguration = SyncConfiguration.defaultConfig(user, DEFAULT_PARTITION)\n        assertEquals(app.configuration.defaultSyncClientResetStrategy, config.syncClientResetStrategy)\n    }\n\n    @Test\n    fun clientResetHandler_nullThrows() {\n        val user: User = createTestUser(app)\n        val builder = SyncConfiguration.Builder(user, DEFAULT_PARTITION)\n        assertFailsWith<IllegalArgumentException> { builder.syncClientResetStrategy(TestHelper.getNull<ManuallyRecoverUnsyncedChangesStrategy>()) }\n    }\n\n    @Test\n    fun clientResetHandler_deprecated() {\n        val builder: SyncConfiguration.Builder = SyncConfiguration.Builder(createTestUser(app), DEFAULT_PARTITION)\n        val handler = SyncSession.ClientResetHandler { _, _ -> }\n        val config = builder.syncClientResetStrategy(handler).build()\n        assertEquals(handler, config.syncClientResetStrategy)\n    }\n\n    @Test\n    fun clientResetHandler_deprecatedThrows() {\n        val builder: SyncConfiguration.Builder = SyncConfiguration.Builder(createTestUser(app), DEFAULT_PARTITION)\n        val handler = ManuallyRecoverUnsyncedChangesStrategy { _, _ -> }\n        val config = builder.syncClientResetStrategy(handler).build()\n        assertFailsWith<ClassCastException> {\n            config.clientResetHandler\n        }\n    }\n\n    @Test\n    fun equals() {\n        val user: User = createTestUser(app)\n        val config: SyncConfiguration = SyncConfiguration.defaultConfig(user, DEFAULT_PARTITION)\n        assertTrue(config == config)\n    }\n\n    @Test\n    fun equals_same() {\n        val user: User = createTestUser(app)\n        val config1: SyncConfiguration = SyncConfiguration.Builder(user, DEFAULT_PARTITION).build()\n        val config2: SyncConfiguration = SyncConfiguration.Builder(user, DEFAULT_PARTITION).build()\n        assertTrue(config1 == config2)\n    }\n\n    @Test\n    // FIXME Tests are not exhaustive\n    fun equals_not() {\n        val user1: User = createTestUser(app)\n        val user2: User = createTestUser(app)\n        val config1: SyncConfiguration = SyncConfiguration.Builder(user1, DEFAULT_PARTITION).build()\n        val config2: SyncConfiguration = SyncConfiguration.Builder(user2, DEFAULT_PARTITION).build()\n        assertFalse(config1 == config2)\n    }\n\n    @Test\n    fun hashCode_equal() {\n        val user: User = createTestUser(app)\n        val config: SyncConfiguration = SyncConfiguration.defaultConfig(user, DEFAULT_PARTITION)\n        assertEquals(config.hashCode(), config.hashCode())\n    }\n\n    @Test\n    fun hashCode_notEquals() {\n        val user1: User = createTestUser(app)\n        val user2: User = createTestUser(app)\n        val config1: SyncConfiguration = SyncConfiguration.defaultConfig(user1, DEFAULT_PARTITION)\n        val config2: SyncConfiguration = SyncConfiguration.defaultConfig(user2, DEFAULT_PARTITION)\n        assertNotEquals(config1.hashCode(), config2.hashCode())\n    }\n\n    @Test\n    fun get_syncSpecificValues() {\n        val user: User = createTestUser(app)\n        val config: SyncConfiguration = SyncConfiguration.defaultConfig(user, DEFAULT_PARTITION)\n        assertTrue(user == config.user)\n        assertEquals(\"ws://127.0.0.1:9090/\", config.serverUrl.toString()) // FIXME: Figure out exactly what to return here\n        assertFalse(config.shouldDeleteRealmOnLogout())\n        assertTrue(config.isSyncConfiguration)\n    }\n\n    @Test\n    fun name() {\n        val user: User = createTestUser(app)\n        val filename = \"my-file-name.realm\"\n        val config: SyncConfiguration = SyncConfiguration.Builder(user, DEFAULT_PARTITION)\n                .name(filename)\n                .build()\n        val suffix = \"/mongodb-realm/${user.app.configuration.appId}/${user.id}/$filename\"\n        assertTrue(config.path.endsWith(suffix))\n    }\n\n    @Test\n    fun name_illegalValuesThrows() {\n        val user: User = createTestUser(app)\n        val builder = SyncConfiguration.Builder(user, DEFAULT_PARTITION)\n\n        assertFailsWith<IllegalArgumentException> { builder.name(TestHelper.getNull()) }\n        assertFailsWith<IllegalArgumentException> { builder.name(\".realm\") }\n    }\n\n    @Test\n    fun encryption() {\n        val user: User = createTestUser(app)\n        val config: SyncConfiguration = SyncConfiguration.Builder(user, DEFAULT_PARTITION)\n                .encryptionKey(TestHelper.getRandomKey())\n                .build()\n        assertNotNull(config.encryptionKey)\n    }\n\n    @Test\n    fun encryption_invalid_null() {\n        val user: User = createTestUser(app)\n        val builder = SyncConfiguration.Builder(user, DEFAULT_PARTITION)\n        assertFailsWith<IllegalArgumentException> { builder.encryptionKey(TestHelper.getNull()) }\n    }\n\n    @Test\n    fun encryption_invalid_wrong_length() {\n        val user: User = createTestUser(app)\n        val builder = SyncConfiguration.Builder(user, DEFAULT_PARTITION)\n        assertFailsWith<IllegalArgumentException> { builder.encryptionKey(byteArrayOf(1, 2, 3)) }\n    }\n\n    @Test\n    fun initialData() {\n        val user: User = createTestUser(app)\n        val config = configFactory.createSyncConfigurationBuilder(user)\n                .schema(SyncStringOnly::class.java)\n                .initialData(object : Realm.Transaction {\n                    override fun execute(realm: Realm) {\n                        val stringOnly: SyncStringOnly = realm.createObject(ObjectId())\n                        stringOnly.chars = \"TEST 42\"\n                    }\n                })\n                .build()\n        assertNotNull(config.initialDataTransaction)\n\n        // open the first time - initialData must be triggered\n        Realm.getInstance(config).use { realm ->\n            val results: RealmResults<SyncStringOnly> = realm.where<SyncStringOnly>().findAll()\n            assertEquals(1, results.size)\n            assertEquals(\"TEST 42\", results.first()!!.chars)\n        }\n\n        // open the second time - initialData must not be triggered\n        Realm.getInstance(config).use { realm ->\n            assertEquals(1, realm.where<SyncStringOnly>().count())\n        }\n    }\n\n    @Test\n    fun defaultRxFactory() {\n        val user: User = createTestUser(app)\n        val config: SyncConfiguration = SyncConfiguration.defaultConfig(user, DEFAULT_PARTITION)\n        assertNotNull(config.rxFactory)\n    }\n\n    @Test\n    fun toString_nonEmpty() {\n        val user: User = createTestUser(app)\n        val config: SyncConfiguration = SyncConfiguration.defaultConfig(user, DEFAULT_PARTITION)\n        val configStr = config.toString()\n        assertTrue(configStr.isNotEmpty())\n    }\n\n    // Check that it is possible for multiple users to reference the same Realm URL while each user still use their\n    // own copy on the filesystem. This is e.g. what happens if a Realm is shared using a PermissionOffer.\n    @Test\n    fun multipleUsersReferenceSameRealm() {\n        val user1: User = app.registerUserAndLogin(TestHelper.getRandomEmail(), \"123456\")\n        val user2: User = app.registerUserAndLogin(TestHelper.getRandomEmail(), \"123456\")\n\n        val config1: SyncConfiguration = SyncConfiguration.Builder(user1, DEFAULT_PARTITION)\n                .modules(SyncStringOnlyModule())\n                .build()\n        val config2: SyncConfiguration = SyncConfiguration.Builder(user2, DEFAULT_PARTITION)\n                .modules(SyncStringOnlyModule())\n                .build()\n\n        // Verify that two different configurations can be used for the same URL\n        val realm1: Realm = Realm.getInstance(config1)\n        val realm2: Realm = Realm.getInstance(config2)\n        assertNotEquals(realm1, realm2)\n\n        realm1.close()\n        realm2.close()\n\n        // Verify that we actually save two different files\n        assertNotEquals(config1.path, config2.path)\n    }\n\n    @Test\n    fun defaultConfiguration_throwsIfNotLoggedIn() {\n        // TODO Maybe we could avoid registering a real user\n        val user = app.registerUserAndLogin(TestHelper.getRandomEmail(), \"123456\")\n        user.logOut()\n        assertFailsWith<IllegalArgumentException> { SyncConfiguration.defaultConfig(user, DEFAULT_PARTITION) }\n    }\n\n    @Test\n    @Ignore(\"Not implemented yet\")\n    fun shouldWaitForInitialRemoteData() {\n    }\n\n    @Test\n    @Ignore(\"Not implemented yet\")\n    fun getInitialRemoteDataTimeout() {\n    }\n\n    @Test\n    @Ignore(\"Not implemented yet\")\n    fun getSessionStopPolicy() {\n    }\n\n    @Test\n    @Ignore(\"Not implemented yet\")\n    fun getUrlPrefix() {\n    }\n\n    @Test\n    fun getPartitionValue() {\n        val user: User = createTestUser(app)\n        val config: SyncConfiguration = SyncConfiguration.defaultConfig(user, DEFAULT_PARTITION)\n        assertEquals(BsonString(DEFAULT_PARTITION), config.partitionValue)\n    }\n\n    @Test\n    fun defaultClientResyncMode() {\n        val user: User = createTestUser(app)\n\n        var config: SyncConfiguration = SyncConfiguration.defaultConfig(user, DEFAULT_PARTITION)\n        assertTrue(config.syncClientResetStrategy is RecoverOrDiscardUnsyncedChangesStrategy)\n    }\n\n    @Test\n    fun legacyClientResyncMode() {\n        val user: User = createTestUser(app)\n\n        val config = SyncConfiguration.Builder(user, DEFAULT_PARTITION)\n                .syncClientResetStrategy(object : SyncSession.ClientResetHandler {\n                    override fun onClientReset(session: SyncSession, error: ClientResetRequiredError) {\n                        fail(\"Should not be called\")\n                    }\n                })\n                .build()\n        assertTrue(config.syncClientResetStrategy is ManuallyRecoverUnsyncedChangesStrategy)\n    }\n\n    @Test\n    fun manualClientResyncMode() {\n        val user: User = createTestUser(app)\n\n        val config = SyncConfiguration.Builder(user, DEFAULT_PARTITION)\n                .syncClientResetStrategy(object : ManuallyRecoverUnsyncedChangesStrategy {\n                    override fun onClientReset(session: SyncSession, error: ClientResetRequiredError) {\n                        fail(\"Should not be called\")\n                    }\n                })\n                .build()\n        assertTrue(config.syncClientResetStrategy is ManuallyRecoverUnsyncedChangesStrategy)\n    }\n\n    @Test\n    fun discardUnsyncedChangesStrategyMode() {\n        val user: User = createTestUser(app)\n\n        val config = SyncConfiguration.Builder(user, DEFAULT_PARTITION)\n            .syncClientResetStrategy(object : DiscardUnsyncedChangesStrategy {\n                override fun onBeforeReset(realm: Realm) {\n                    fail(\"Should not be called\")\n                }\n\n                override fun onAfterReset(before: Realm, after: Realm) {\n                    fail(\"Should not be called\")\n                }\n\n                override fun onError(session: SyncSession, error: ClientResetRequiredError) {\n                    fail(\"Should not be called\")\n                }\n\n                override fun onManualResetFallback(\n                    session: SyncSession,\n                    error: ClientResetRequiredError\n                ) {\n                    fail(\"Should not be called\")\n                }\n            })\n            .build()\n        assertTrue(config.syncClientResetStrategy is DiscardUnsyncedChangesStrategy)\n    }\n\n    @Test\n    fun recoverUnsyncedChangesStrategyMode() {\n        val user: User = createTestUser(app)\n\n        val config = SyncConfiguration.Builder(user, DEFAULT_PARTITION)\n            .syncClientResetStrategy(object: RecoverUnsyncedChangesStrategy{\n                override fun onBeforeReset(realm: Realm) {\n                    fail(\"Should not be called\")\n                }\n\n                override fun onAfterReset(before: Realm, after: Realm) {\n                    fail(\"Should not be called\")\n                }\n\n                override fun onManualResetFallback(session: SyncSession, error: ClientResetRequiredError) {\n                    fail(\"Should not be called\")\n                }\n            })\n            .build()\n        assertTrue(config.syncClientResetStrategy is RecoverUnsyncedChangesStrategy)\n    }\n\n    @Test\n    fun recoverOrDiscardUnsyncedChangesStrategyMode() {\n        val user: User = createTestUser(app)\n\n        val config = SyncConfiguration.Builder(user, DEFAULT_PARTITION)\n            .syncClientResetStrategy(object : RecoverOrDiscardUnsyncedChangesStrategy {\n                override fun onBeforeReset(realm: Realm) {\n                    fail(\"Should not be called\")\n                }\n\n                override fun onAfterRecovery(before: Realm, after: Realm) {\n                    fail(\"Should not be called\")\n                }\n\n                override fun onAfterDiscard(before: Realm, after: Realm) {\n                    fail(\"Should not be called\")\n                }\n\n                override fun onManualResetFallback(session: SyncSession, error: ClientResetRequiredError) {\n                    fail(\"Should not be called\")\n                }\n\n            })\n            .build()\n        assertTrue(config.syncClientResetStrategy is RecoverOrDiscardUnsyncedChangesStrategy)\n    }\n\n    @Test\n    fun clientResyncMode_throwsOnNull() {\n        val user: User = createTestUser(app)\n        val config: SyncConfiguration.Builder = SyncConfiguration.Builder(user, DEFAULT_PARTITION)\n\n        assertFailsWith<IllegalArgumentException> {\n            config.syncClientResetStrategy(TestHelper.getNull<ManuallyRecoverUnsyncedChangesStrategy>())\n        }\n        assertFailsWith<IllegalArgumentException> {\n            config.syncClientResetStrategy(TestHelper.getNull<DiscardUnsyncedChangesStrategy>())\n        }\n    }\n\n    // If the same user create two configurations with different partition values they must\n    // resolve to different paths on disk.\n    @Test\n    fun differentPartitionValuesAreDifferentRealms() {\n        val user: User = createTestUser(app)\n        val config1 = SyncConfiguration.Builder(user, \"realm1\").modules(SyncStringOnlyModule()).build()\n        val config2 = SyncConfiguration.Builder(user, \"realm2\").modules(SyncStringOnlyModule()).build()\n        assertNotEquals(config1.path, config2.path)\n\n        assertTrue(config1.path.endsWith(\"${app.configuration.appId}/${user.id}/s_realm1.realm\"))\n        assertTrue(config2.path.endsWith(\"${app.configuration.appId}/${user.id}/s_realm2.realm\"))\n\n        // Check for https://github.com/realm/realm-java/issues/6882\n        val realm1 = Realm.getInstance(config1)\n        try {\n            val realm2 = Realm.getInstance(config2)\n            realm2.close()\n        } finally {\n            realm1.close()\n        }\n    }\n\n    @Test\n    fun nullPartitionValue() {\n        val user: User = createTestUser(app)\n\n        val configs = listOf<SyncConfiguration>(\n                SyncConfiguration.defaultConfig(user, null as String?),\n                SyncConfiguration.defaultConfig(user, null as Int?),\n                SyncConfiguration.defaultConfig(user, null as Long?),\n                SyncConfiguration.defaultConfig(user, null as ObjectId?),\n                SyncConfiguration.defaultConfig(user, null as UUID?),\n                SyncConfiguration.Builder(user, null as String?).build(),\n                SyncConfiguration.Builder(user, null as Int?).build(),\n                SyncConfiguration.Builder(user, null as Long?).build(),\n                SyncConfiguration.Builder(user, null as ObjectId?).build(),\n                SyncConfiguration.Builder(user, null as UUID?).build()\n        )\n\n        configs.forEach { config ->\n            assertTrue(config.path.endsWith(\"/null.realm\"))\n        }\n    }\n\n    @Test\n    fun loggedOutUsersThrows() {\n        val user: User = app.registerUserAndLogin(TestHelper.getRandomEmail(), \"123456\")\n        user.logOut()\n        assertFailsWith<java.lang.IllegalArgumentException> {\n            SyncConfiguration.defaultConfig(user, ObjectId())\n        }\n        assertFailsWith<java.lang.NullPointerException> {\n            SyncConfiguration.defaultConfig(app.currentUser()!!, ObjectId())\n        }\n    }\n\n    @Test\n    fun allowQueriesOnUiThread_defaultsToTrue() {\n        val builder: SyncConfiguration.Builder = SyncConfiguration.Builder(createTestUser(app), DEFAULT_PARTITION)\n        val configuration = builder.build()\n        assertTrue(configuration.isAllowQueriesOnUiThread)\n    }\n\n    @Test\n    fun allowQueriesOnUiThread_explicitFalse() {\n        val builder: SyncConfiguration.Builder = SyncConfiguration.Builder(createTestUser(app), DEFAULT_PARTITION)\n        val configuration = builder.allowQueriesOnUiThread(false)\n                .build()\n        assertFalse(configuration.isAllowQueriesOnUiThread)\n    }\n\n    @Test\n    fun allowQueriesOnUiThread_explicitTrue() {\n        val builder: SyncConfiguration.Builder = SyncConfiguration.Builder(createTestUser(app), DEFAULT_PARTITION)\n        val configuration = builder.allowQueriesOnUiThread(true)\n                .build()\n        assertTrue(configuration.isAllowQueriesOnUiThread)\n    }\n\n    @Test\n    fun allowWritesOnUiThread_defaultsToFalse() {\n        val builder: SyncConfiguration.Builder = SyncConfiguration.Builder(createTestUser(app), DEFAULT_PARTITION)\n        val configuration = builder.build()\n        assertFalse(configuration.isAllowWritesOnUiThread)\n    }\n\n    @Test\n    fun allowWritesOnUiThread_explicitFalse() {\n        val builder: SyncConfiguration.Builder = SyncConfiguration.Builder(createTestUser(app), DEFAULT_PARTITION)\n        val configuration = builder.allowWritesOnUiThread(false)\n                .build()\n        assertFalse(configuration.isAllowWritesOnUiThread)\n    }\n\n    @Test\n    fun allowWritesOnUiThread_explicitTrue() {\n        val builder: SyncConfiguration.Builder = SyncConfiguration.Builder(createTestUser(app), DEFAULT_PARTITION)\n        val configuration = builder.allowWritesOnUiThread(true)\n                .build()\n        assertTrue(configuration.isAllowWritesOnUiThread)\n    }\n\n    @Test\n    fun rxFactory_defaultNonNull() {\n        val configuration = SyncConfiguration.Builder(createTestUser(app), DEFAULT_PARTITION)\n                .build()\n        assertNotNull(configuration.rxFactory)\n    }\n\n    @Test\n    fun rxFactory_nullThrows() {\n        assertFailsWith<IllegalArgumentException> {\n            SyncConfiguration.Builder(createTestUser(app), DEFAULT_PARTITION)\n                    .rxFactory(TestHelper.getNull())\n        }.let {\n            assertTrue(it.message!!.contains(\"null\"))\n        }\n    }\n\n    @Test\n    fun rxFactory() {\n        val factory = object: RxObservableFactory {\n            override fun from(realm: Realm): Flowable<Realm> {\n                return Flowable.just(null)\n            }\n\n            override fun from(realm: DynamicRealm): Flowable<DynamicRealm> {\n                return Flowable.just(null)\n            }\n\n            override fun <E : Any?> from(realm: Realm, results: RealmResults<E>): Flowable<RealmResults<E>> {\n                return Flowable.just(null)\n            }\n\n            override fun <E : Any?> from(realm: DynamicRealm, results: RealmResults<E>): Flowable<RealmResults<E>> {\n                return Flowable.just(null)\n            }\n\n            override fun <E : Any?> from(realm: Realm, list: RealmList<E>): Flowable<RealmList<E>> {\n                return Flowable.just(null)\n            }\n\n            override fun <E : Any?> from(realm: DynamicRealm, list: RealmList<E>): Flowable<RealmList<E>> {\n                return Flowable.just(null)\n            }\n\n            override fun <E : RealmModel?> from(realm: Realm, `object`: E): Flowable<E> {\n                return Flowable.just(null)\n            }\n\n            override fun from(realm: DynamicRealm, `object`: DynamicRealmObject): Flowable<DynamicRealmObject> {\n                return Flowable.just(null)\n            }\n\n            override fun <E : Any?> from(realm: Realm, query: RealmQuery<E>): Single<RealmQuery<E>> {\n                return Single.just(null)\n            }\n\n            override fun <E : Any?> from(realm: DynamicRealm, query: RealmQuery<E>): Single<RealmQuery<E>> {\n                return Single.just(null)\n            }\n\n            override fun <E : Any?> changesetsFrom(realm: Realm, results: RealmResults<E>): Observable<CollectionChange<RealmResults<E>>> {\n                return Observable.just(null)\n            }\n\n            override fun <E : Any?> changesetsFrom(realm: DynamicRealm, results: RealmResults<E>): Observable<CollectionChange<RealmResults<E>>> {\n                return Observable.just(null)\n            }\n\n            override fun <E : Any?> changesetsFrom(realm: Realm, list: RealmList<E>): Observable<CollectionChange<RealmList<E>>> {\n                return Observable.just(null)\n            }\n\n            override fun <E : Any?> changesetsFrom(realm: DynamicRealm, list: RealmList<E>): Observable<CollectionChange<RealmList<E>>> {\n                return Observable.just(null)\n            }\n\n            override fun <E : RealmModel?> changesetsFrom(realm: Realm, `object`: E): Observable<ObjectChange<E>> {\n                return Observable.just(null)\n            }\n\n            override fun changesetsFrom(realm: DynamicRealm, `object`: DynamicRealmObject): Observable<ObjectChange<DynamicRealmObject>> {\n                return Observable.just(null)\n            }\n\n        }\n\n        val configuration1 = SyncConfiguration.Builder(createTestUser(app), DEFAULT_PARTITION)\n                .rxFactory(factory)\n                .build()\n        assertEquals(factory, configuration1.rxFactory)\n\n        val configuration2 = SyncConfiguration.Builder(createTestUser(app), DEFAULT_PARTITION)\n                .build()\n        assertNotEquals(factory, configuration2.rxFactory)\n    }\n\n    @Test\n    fun flowFactory_defaultNonNull() {\n        val configuration = SyncConfiguration.Builder(createTestUser(app), DEFAULT_PARTITION)\n                .build()\n        assertNotNull(configuration.flowFactory)\n    }\n\n    @Test\n    fun flowFactory_nullThrows() {\n        assertFailsWith<IllegalArgumentException> {\n            SyncConfiguration.Builder(createTestUser(app), DEFAULT_PARTITION)\n                    .flowFactory(TestHelper.getNull())\n        }.let {\n            assertTrue(it.message!!.contains(\"null\"))\n        }\n    }\n\n    @Test\n    fun flowFactory() {\n        val factory = object : FlowFactory {\n            override fun from(realm: Realm): Flow<Realm> {\n                return flowOf()\n            }\n\n            override fun from(dynamicRealm: DynamicRealm): Flow<DynamicRealm> {\n                return flowOf()\n            }\n\n            override fun <T : Any?> from(realm: Realm, results: RealmResults<T>): Flow<RealmResults<T>> {\n                return flowOf()\n            }\n\n            override fun <T : Any?> from(dynamicRealm: DynamicRealm, results: RealmResults<T>): Flow<RealmResults<T>> {\n                return flowOf()\n            }\n\n            override fun <T : Any?> from(realm: Realm, realmList: RealmList<T>): Flow<RealmList<T>> {\n                return flowOf()\n            }\n\n            override fun <T : Any?> from(dynamicRealm: DynamicRealm, realmList: RealmList<T>): Flow<RealmList<T>> {\n                return flowOf()\n            }\n\n            override fun <T : RealmModel?> from(realm: Realm, realmObject: T): Flow<T> {\n                return flowOf()\n            }\n\n            override fun from(dynamicRealm: DynamicRealm, dynamicRealmObject: DynamicRealmObject): Flow<DynamicRealmObject> {\n                return flowOf()\n            }\n\n            override fun <T : Any?> changesetFrom(realm: Realm, results: RealmResults<T>): Flow<CollectionChange<RealmResults<T>>> {\n                return flowOf()\n            }\n\n            override fun <T : Any?> changesetFrom(dynamicRealm: DynamicRealm, results: RealmResults<T>): Flow<CollectionChange<RealmResults<T>>> {\n                return flowOf()\n            }\n\n            override fun <T : Any?> changesetFrom(realm: Realm, list: RealmList<T>): Flow<CollectionChange<RealmList<T>>> {\n                return flowOf()\n            }\n\n            override fun <T : Any?> changesetFrom(dynamicRealm: DynamicRealm, list: RealmList<T>): Flow<CollectionChange<RealmList<T>>> {\n                return flowOf()\n            }\n\n            override fun <T : RealmModel?> changesetFrom(realm: Realm, realmObject: T): Flow<ObjectChange<T>> {\n                return flowOf()\n            }\n\n            override fun changesetFrom(dynamicRealm: DynamicRealm, dynamicRealmObject: DynamicRealmObject): Flow<ObjectChange<DynamicRealmObject>> {\n                return flowOf()\n            }\n        }\n\n        val configuration1 = SyncConfiguration.Builder(createTestUser(app), DEFAULT_PARTITION)\n                .flowFactory(factory)\n                .build()\n        assertEquals(factory, configuration1.flowFactory)\n\n        val configuration2 = SyncConfiguration.Builder(createTestUser(app), DEFAULT_PARTITION)\n                .build()\n        assertNotEquals(factory, configuration2.flowFactory)\n    }\n\n    @Test\n    fun assetFile() {\n        val builder: SyncConfiguration.Builder = SyncConfiguration.Builder(createTestUser(app), DEFAULT_PARTITION)\n        val configuration: SyncConfiguration = builder\n            .assetFile(\"data/synced-data.realm\")\n            .build()\n        assertEquals(\"data/synced-data.realm\", configuration.assetFilePath);\n    }\n\n    @Test\n    fun assetFile_nullThrows() {\n        val builder: SyncConfiguration.Builder = SyncConfiguration.Builder(createTestUser(app), DEFAULT_PARTITION)\n        assertFailsWith<IllegalArgumentException> { builder.assetFile(TestHelper.getNull()) }\n    }\n\n    @Test\n    fun assetFile_inMemoryThrows() {\n        val builder: SyncConfiguration.Builder = SyncConfiguration.Builder(createTestUser(app), DEFAULT_PARTITION)\n            .inMemory()\n        assertFailsWith<IllegalStateException> { builder.assetFile(\"foo.bar\") }\n    }\n\n    @Test\n    fun overrideDefaultPath() {\n        val user: User = createTestUser(app)\n        val config: SyncConfiguration = SyncConfiguration.Builder(user, DEFAULT_PARTITION)\n            .name(\"custom.realm\")\n            .build()\n        assertTrue(\"Path is: ${config.path}\", config.path.endsWith(\"${app.configuration.appId}/${user.id}/custom.realm\"))\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTestObjectServer/kotlin/io/realm/mongodb/sync/SyncExt.kt",
    "content": "/*\n * Copyright 2020 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\npackage io.realm.mongodb.sync\n\n// Helper to expose package protected methods for testing purpose\nfun Sync.testReset() {\n    this.reset()\n}\n\nfun Sync.simulateClientReset(session: SyncSession) {\n    this.simulateClientReset(session)\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTestObjectServer/kotlin/io/realm/mongodb/sync/SyncSessionExt.kt",
    "content": "/*\n * Copyright 2020 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\npackage io.realm.mongodb.sync\n\n// Helper to expose package protected methods for testing purpose\nfun SyncSession.testClose() {\n    this.close()\n}\n\nfun SyncSession.testShutdownAndWait() {\n    this.shutdownAndWait()\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTestObjectServer/kotlin/io/realm/mongodb/sync/SyncedRealmTests.kt",
    "content": "/*\n * Copyright 2020 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 */\npackage io.realm.mongodb.sync\n\nimport androidx.annotation.UiThread\nimport androidx.test.ext.junit.runners.AndroidJUnit4\nimport androidx.test.platform.app.InstrumentationRegistry\nimport io.realm.*\nimport io.realm.entities.*\nimport io.realm.entities.embedded.*\nimport io.realm.exceptions.RealmFileException\nimport io.realm.kotlin.createEmbeddedObject\nimport io.realm.kotlin.createObject\nimport io.realm.kotlin.syncSession\nimport io.realm.kotlin.where\nimport io.realm.log.LogLevel\nimport io.realm.log.RealmLog\nimport io.realm.mongodb.*\nimport io.realm.mongodb.SyncTestUtils.Companion.createTestUser\nimport io.realm.rule.BlockingLooperThread\nimport org.bson.BsonNull\nimport org.bson.BsonString\nimport org.bson.types.Decimal128\nimport org.bson.types.ObjectId\nimport org.junit.*\nimport org.junit.Assert.*\nimport org.junit.runner.RunWith\nimport java.io.File\nimport java.lang.IllegalStateException\nimport java.util.*\nimport java.util.concurrent.TimeUnit\nimport kotlin.test.assertFailsWith\n\n/**\n * Testing sync specific methods on [Realm].\n */\n@RunWith(AndroidJUnit4::class)\nclass SyncedRealmTests {\n\n    @get:Rule\n    val configFactory = TestSyncConfigurationFactory()\n\n    private val looperThread = BlockingLooperThread()\n    private lateinit var app: App\n    private lateinit var partitionValue: String\n\n    @Before\n    fun setUp() {\n        Realm.init(InstrumentationRegistry.getInstrumentation().targetContext)\n        app = TestApp()\n        partitionValue = UUID.randomUUID().toString()\n    }\n\n    @After\n    fun tearDown() {\n        if (this::app.isInitialized) {\n            app.close()\n        }\n        RealmLog.setLevel(LogLevel.WARN)\n    }\n\n    // Smoke test for Sync. Waiting for working Sync support.\n    @Test\n    fun connectWithInitialSchema() {\n        val user: User = createNewUser()\n        val config = createDefaultConfig(user)\n        Realm.getInstance(config).use { realm ->\n            with(realm.syncSession) {\n                uploadAllLocalChanges()\n                downloadAllServerChanges()\n            }\n            assertTrue(realm.isEmpty)\n        }\n    }\n\n    // Smoke test for Sync\n    @Test\n    fun roundTripObjectsNotInServerSchemaObject() {\n        // User 1 creates an object an uploads it to MongoDB Realm\n        val user1: User = createNewUser()\n        val config1: SyncConfiguration = createCustomConfig(user1, partitionValue)\n        Realm.getInstance(config1).use { realm ->\n            realm.executeTransaction {\n                for (i in 1..10) {\n                    it.insert(SyncColor())\n                }\n            }\n            realm.syncSession.uploadAllLocalChanges()\n            assertEquals(10, realm.where<SyncColor>().count())\n        }\n\n        // User 2 logs and using the same partition key should see the object\n        val user2: User = createNewUser()\n        val config2 = createCustomConfig(user2, partitionValue)\n        Realm.getInstance(config2).use { realm ->\n            realm.syncSession.downloadAllServerChanges()\n            realm.refresh()\n            assertEquals(10, realm.where<SyncColor>().count())\n        }\n    }\n\n    // Smoke test for sync\n    // Insert different types with no links between them\n    @Test\n    fun roundTripSimpleObjectsInServerSchema() {\n        // User 1 creates an object an uploads it to MongoDB Realm\n        val user1: User = createNewUser()\n        val config1: SyncConfiguration = createDefaultConfig(user1, partitionValue)\n        Realm.getInstance(config1).use { realm ->\n            realm.executeTransaction {\n                val person = SyncPerson()\n                person.firstName = \"Jane\"\n                person.lastName = \"Doe\"\n                person.age = 42\n                realm.insert(person);\n                for (i in 0..9) {\n                    val dog = SyncDog()\n                    dog.name = \"Fido $i\"\n                    it.insert(dog)\n                }\n            }\n            realm.syncSession.uploadAllLocalChanges()\n            assertEquals(10, realm.where<SyncDog>().count())\n            assertEquals(1, realm.where<SyncPerson>().count())\n        }\n\n        // User 2 logs and using the same partition key should see the object\n        val user2: User = createNewUser()\n        val config2 = createDefaultConfig(user2, partitionValue)\n        Realm.getInstance(config2).use { realm ->\n            realm.syncSession.downloadAllServerChanges()\n            realm.refresh()\n            assertEquals(10, realm.where<SyncDog>().count())\n            assertEquals(1, realm.where<SyncPerson>().count())\n        }\n    }\n\n    // Smoke test for sync\n    // Insert objects with links between them\n    @Test\n    fun roundTripObjectsWithLists() {\n        // User 1 creates an object an uploads it to MongoDB Realm\n        val user1: User = createNewUser()\n        val config1: SyncConfiguration = createDefaultConfig(user1, partitionValue)\n        Realm.deleteRealm(config1)\n        Realm.getInstance(config1).use { realm ->\n            realm.executeTransaction {\n                val person = SyncPerson()\n                person.firstName = \"Jane\"\n                person.lastName = \"Doe\"\n                person.age = 42\n                for (i in 0..9) {\n                    val dog = SyncDog()\n                    dog.name = \"Fido $i\"\n                    person.dogs.add(dog)\n                }\n                realm.insert(person)\n            }\n            realm.syncSession.uploadAllLocalChanges()\n            assertEquals(10, realm.where<SyncDog>().count())\n            assertEquals(1, realm.where<SyncPerson>().count())\n        }\n\n        // User 2 logs and using the same partition key should see the object\n        val user2: User = createNewUser()\n        val config2 = createDefaultConfig(user2, partitionValue)\n        Realm.deleteRealm(config2)\n        Realm.getInstance(config2).use { realm ->\n            realm.syncSession.downloadAllServerChanges()\n            realm.refresh()\n            assertEquals(10, realm.where<SyncDog>().count())\n            assertEquals(1, realm.where<SyncPerson>().count())\n        }\n    }\n\n    @Test\n    fun session() {\n        val user: User = app.login(Credentials.anonymous())\n        Realm.getInstance(createDefaultConfig(user)).use { realm ->\n            assertNotNull(realm.syncSession)\n            assertEquals(SyncSession.State.ACTIVE, realm.syncSession.state)\n            assertEquals(user, realm.syncSession.user)\n        }\n    }\n\n    @Test\n    fun nullPartition() {\n        val config = configFactory.createSyncConfigurationBuilder(createNewUser(), BsonNull())\n                .modules(DefaultSyncSchema())\n                .build()\n        assertTrue(config.path.endsWith(\"null.realm\"))\n        Realm.getInstance(config).use { realm ->\n            realm.syncSession.uploadAllLocalChanges() // Ensures that we can actually connect\n        }\n    }\n\n    @Test\n    @Ignore(\"FIXME Flaky, seems like Realm.compactRealm(config) sometimes returns false\")\n    fun compactRealm_populatedRealm() {\n        val config = configFactory.createSyncConfigurationBuilder(createNewUser()).build()\n        Realm.getInstance(config).use { realm ->\n            realm.executeTransaction { r: Realm ->\n                for (i in 0..9) {\n                    r.insert(AllJavaTypes(i.toLong()))\n                }\n            }\n        }\n        assertTrue(Realm.compactRealm(config))\n\n        Realm.getInstance(config).use { realm ->\n            assertEquals(10, realm.where(AllJavaTypes::class.java).count())\n        }\n    }\n\n    @Test\n    fun compactOnLaunch_shouldCompact() {\n        var user = createTestUser(app)\n\n        // Fill Realm with data and record size\n        val config1 = configFactory.createSyncConfigurationBuilder(user)\n                .testSchema(SyncByteArray::class.java)\n                .build()\n\n        var originalSize: Long? = null\n        Realm.getInstance(config1).use { realm ->\n            val oneMBData = ByteArray(1024 * 1024)\n            realm.executeTransaction {\n                for (i in 0..9) {\n                    realm.createObject(SyncByteArray::class.java, ObjectId()).columnBinary = oneMBData\n                }\n            }\n            originalSize = File(realm.path).length()\n        }\n\n        // Recreate mock user as it is automatically logged out\n        user = createTestUser(app)\n        // Open Realm with CompactOnLaunch\n        val config2 = configFactory.createSyncConfigurationBuilder(user)\n                .compactOnLaunch { totalBytes, usedBytes -> true }\n                .testSchema(SyncByteArray::class.java)\n                .build()\n        Realm.getInstance(config2).use { realm ->\n            val compactedSize = File(realm.path).length()\n            assertTrue(originalSize!! > compactedSize)\n        }\n    }\n\n    @Test\n    fun embeddedObject_roundTrip() {\n        val user1: User = createNewUser()\n        val config1: SyncConfiguration = createDefaultConfig(user1, partitionValue)\n        val primaryKeyValue = UUID.randomUUID().toString()\n        Realm.getInstance(config1).use { realm ->\n            assertTrue(realm.isEmpty)\n\n            realm.executeTransaction {\n                realm.createObject<EmbeddedSimpleParent>(primaryKeyValue).let { parent ->\n                    realm.createEmbeddedObject<EmbeddedSimpleChild>(parent, \"child\")\n                }\n            }\n            realm.syncSession.uploadAllLocalChanges()\n\n            assertEquals(1, realm.where<EmbeddedSimpleParent>().count())\n            assertEquals(1, realm.where<EmbeddedSimpleChild>().count())\n        }\n\n        val user2: User = createNewUser()\n        val config2: SyncConfiguration = createDefaultConfig(user2, partitionValue)\n        Realm.getInstance(config2).use { realm ->\n            realm.syncSession.downloadAllServerChanges(5, TimeUnit.SECONDS).let {\n                if (!it) fail()\n            }\n            realm.refresh()\n\n            val childResults = realm.where<EmbeddedSimpleChild>()\n            assertEquals(1, childResults.count())\n            val parentResults = realm.where<EmbeddedSimpleParent>()\n            assertEquals(1, parentResults.count())\n            val parent = parentResults.findFirst()!!\n            assertEquals(primaryKeyValue, parent._id)\n            assertEquals(parent._id, parent.child!!.parent._id)\n        }\n    }\n\n    @Test\n    fun embeddedObject_copyUnmanaged_roundTrip() {\n        val user1: User = createNewUser()\n        val config1: SyncConfiguration = createDefaultConfig(user1, partitionValue)\n        val primaryKeyValue = UUID.randomUUID().toString()\n\n        Realm.getInstance(config1).use { realm ->\n            assertTrue(realm.isEmpty)\n\n            realm.executeTransaction {\n                val parent = EmbeddedSimpleParent(primaryKeyValue)\n\n//                parent.child = EmbeddedSimpleChild()\n                val managedParent = it.copyToRealmOrUpdate(parent)\n                // FIXME: instantiating the child in managedParent yields this from sync:\n                //  \"MongoDB error: Updating the path 'child.childID' would create a conflict at 'child'\"\n                managedParent.child = EmbeddedSimpleChild() // Will copy the object to Realm\n            }\n            realm.syncSession.uploadAllLocalChanges()\n\n            assertEquals(1, realm.where<EmbeddedSimpleParent>().count())\n            assertEquals(1, realm.where<EmbeddedSimpleChild>().count())\n        }\n\n        val user2: User = createNewUser()\n        val config2: SyncConfiguration = createDefaultConfig(user2, partitionValue)\n        Realm.getInstance(config2).use { realm ->\n            realm.syncSession.downloadAllServerChanges(5, TimeUnit.SECONDS).let {\n                if (!it) fail()\n            }\n            realm.refresh()\n\n            val childResults = realm.where<EmbeddedSimpleChild>()\n            assertEquals(1, childResults.count())\n            val parentResults = realm.where<EmbeddedSimpleParent>()\n            assertEquals(1, parentResults.count())\n            val parent = parentResults.findFirst()!!\n            assertEquals(primaryKeyValue, parent._id)\n            assertEquals(parent._id, parent.child!!.parent._id)\n        }\n    }\n\n    @Test\n    fun embeddedObject_realmList_roundTrip() {\n        val user1: User = createNewUser()\n        val config1: SyncConfiguration = createDefaultConfig(user1, partitionValue)\n        val primaryKeyValue = UUID.randomUUID().toString()\n        Realm.getInstance(config1).use { realm ->\n            realm.executeTransaction {\n                realm.createObject(EmbeddedSimpleListParent::class.java, primaryKeyValue).let { parent ->\n                    realm.createEmbeddedObject(EmbeddedSimpleChild::class.java, parent, \"children\")\n                    realm.createEmbeddedObject(EmbeddedSimpleChild::class.java, parent, \"children\")\n                }\n            }\n            realm.syncSession.uploadAllLocalChanges()\n\n            assertEquals(1, realm.where<EmbeddedSimpleListParent>().count())\n            assertEquals(2, realm.where<EmbeddedSimpleChild>().count())\n        }\n\n        val user2: User = createNewUser()\n        val config2: SyncConfiguration = createDefaultConfig(user2, partitionValue)\n        Realm.getInstance(config2).use { realm ->\n            assertEquals(0, realm.where<EmbeddedSimpleListParent>().count())\n            assertEquals(0, realm.where<EmbeddedSimpleChild>().count())\n\n            realm.syncSession.downloadAllServerChanges(5, TimeUnit.SECONDS).let {\n                if (!it) fail()\n            }\n            realm.refresh()\n\n            val childResults = realm.where<EmbeddedSimpleChild>()\n            assertEquals(2, childResults.count())\n            val parentResults = realm.where<EmbeddedSimpleListParent>()\n            assertEquals(1, parentResults.count())\n            val parentFromResults = parentResults.findFirst()!!\n            assertEquals(primaryKeyValue, parentFromResults._id)\n\n            parentFromResults.children.also { childrenInParent ->\n                val childrenFromResults = childResults.findAll()\n                childrenInParent.forEach { childInParent ->\n                    assertTrue(childrenFromResults.contains(childInParent))\n                }\n            }\n        }\n    }\n\n    @Test\n    fun embeddedObject_realmList_copyUnmanaged_roundTrip() {\n        val user1: User = createNewUser()\n        val config1: SyncConfiguration = createDefaultConfig(user1, partitionValue)\n        val primaryKeyValue = UUID.randomUUID().toString()\n        Realm.getInstance(config1).use { realm ->\n            realm.executeTransaction {\n                val parent = EmbeddedSimpleListParent(primaryKeyValue)\n                parent.children = RealmList(EmbeddedSimpleChild(\"child1\"), EmbeddedSimpleChild(\"child2\"))\n                realm.insert(parent)\n            }\n            realm.syncSession.uploadAllLocalChanges()\n\n            assertEquals(1, realm.where<EmbeddedSimpleListParent>().count())\n            assertEquals(2, realm.where<EmbeddedSimpleChild>().count())\n        }\n\n        val user2: User = createNewUser()\n        val config2: SyncConfiguration = createDefaultConfig(user2, partitionValue)\n        Realm.getInstance(config2).use { realm ->\n            assertEquals(0, realm.where<EmbeddedSimpleListParent>().count())\n            assertEquals(0, realm.where<EmbeddedSimpleChild>().count())\n\n            realm.syncSession.downloadAllServerChanges(1, TimeUnit.SECONDS).let {\n                if (!it) fail()\n            }\n            realm.refresh()\n\n            val childResults = realm.where<EmbeddedSimpleChild>()\n            assertEquals(2, childResults.count())\n            val parentResults = realm.where<EmbeddedSimpleListParent>()\n            assertEquals(1, parentResults.count())\n            val parentFromResults = parentResults.findFirst()!!\n            assertEquals(primaryKeyValue, parentFromResults._id)\n            assertEquals(\"child1\", childResults.findAll()[0]!!.childId)\n            assertEquals(\"child2\", childResults.findAll()[1]!!.childId)\n        }\n    }\n\n    // FIXME: remember to add tree structure classes to DefaultSyncSchema.kt\n    @Test\n    @Ignore(\"Enable when https://jira.mongodb.org/projects/HELP/queues/issue/HELP-17759 is fixed\")\n    fun copyToRealm_treeSchema() {\n        val user1: User = createNewUser()\n        val config1: SyncConfiguration = createDefaultConfig(user1, partitionValue)\n        val primaryKeyValue = UUID.randomUUID().toString()\n\n        Realm.getInstance(config1).use { realm ->\n            realm.executeTransaction {\n                val parent = EmbeddedTreeParent(\"parent1\")\n\n                val node1 = EmbeddedTreeNode(\"node1\")\n                node1.leafNode = EmbeddedTreeLeaf(\"leaf1\")\n                parent.middleNode = node1\n                val node2 = EmbeddedTreeNode(\"node2\")\n                node2.leafNodeList.add(EmbeddedTreeLeaf(\"leaf2\"))\n                node2.leafNodeList.add(EmbeddedTreeLeaf(\"leaf3\"))\n                parent.middleNodeList.add(node2)\n\n                it.copyToRealm(parent)\n            }\n            realm.syncSession.uploadAllLocalChanges()\n        }\n\n        val user2: User = createNewUser()\n        val config2: SyncConfiguration = createDefaultConfig(user2, partitionValue)\n        Realm.getInstance(config2).use { realm ->\n            assertEquals(0, realm.where<EmbeddedSimpleListParent>().count())\n            assertEquals(0, realm.where<EmbeddedSimpleChild>().count())\n\n            realm.syncSession.downloadAllServerChanges(1, TimeUnit.SECONDS).let {\n                if (!it) fail()\n            }\n            realm.refresh()\n\n            Assert.assertEquals(1, realm.where<EmbeddedTreeParent>().count())\n            Assert.assertEquals(\"parent1\", realm.where<EmbeddedTreeParent>().findFirst()!!._id)\n\n            Assert.assertEquals(2, realm.where<EmbeddedTreeNode>().count())\n            val nodeResults = realm.where<EmbeddedTreeNode>().findAll()\n            assertTrue(nodeResults.any { it.treeNodeId == \"node1\" })\n            assertTrue(nodeResults.any { it.treeNodeId == \"node2\" })\n\n            Assert.assertEquals(3, realm.where<EmbeddedTreeLeaf>().count())\n            val leafResults = realm.where<EmbeddedTreeLeaf>().findAll()\n            assertTrue(leafResults.any { it.treeLeafId == \"leaf1\" })\n            assertTrue(leafResults.any { it.treeLeafId == \"leaf2\" })\n            assertTrue(leafResults.any { it.treeLeafId == \"leaf3\" })\n        }\n    }\n\n    // Check that we can create multiple apps that synchronize with each other\n    @Test\n    fun multipleAppsCanSync() {\n        val app2 = TestApp(appName = TEST_APP_2)\n        var realm1: Realm? = null\n        var realm2: Realm? = null\n        try {\n            // Login users on both Realms\n            val app1User = app.login(Credentials.anonymous())\n            val app2User = app2.login(Credentials.anonymous())\n            assertNotEquals(app1User, app2User)\n\n            // Create one Realm against each app\n            val config1 = configFactory.createSyncConfigurationBuilder(app1User, BsonString(\"foo\"))\n                    .modules(DefaultSyncSchema())\n                    .build()\n            val config2 = configFactory.createSyncConfigurationBuilder(app2User, BsonString(\"foo\"))\n                    .modules(DefaultSyncSchema())\n                    .build()\n\n            // Make sure we can synchronize changes\n            realm1 = Realm.getInstance(config1)\n            realm2 = Realm.getInstance(config2)\n            realm1.syncSession.downloadAllServerChanges(1, TimeUnit.MINUTES)\n            realm2.syncSession.downloadAllServerChanges(1, TimeUnit.MINUTES)\n            assertTrue(realm1.isEmpty)\n            assertTrue(realm2.isEmpty)\n        } finally {\n            realm1?.close()\n            realm2?.close()\n            app2.close()\n        }\n    }\n\n    @Test\n    fun allTypes_roundTrip() {\n        val expectedRealmAnyValues = arrayListOf(\n                RealmAny.valueOf(1.toLong()),\n                RealmAny.valueOf(false),\n                RealmAny.valueOf(10.5.toFloat()),\n                RealmAny.valueOf(10.5.toDouble()),\n                RealmAny.valueOf(\"hello world 2\"),\n                RealmAny.valueOf(Date(105)),\n                RealmAny.valueOf(Decimal128(102)),\n                RealmAny.valueOf(ObjectId()),\n                RealmAny.valueOf(UUID.randomUUID())\n        )\n\n        val primaryKeyValue = ObjectId()\n        val expectedRealmInteger = 100.toLong()\n        val expectedString = \"hello world\"\n        val expectedLong = 10.toLong()\n        val expectedDouble = 10.0\n        val expectedFloat = 10.0.toFloat()\n        val expectedBoolean = true\n        val expectedDate = Date()\n        val expectedBinary = byteArrayOf(0, 1, 0)\n        val expectedDecimal128 = Decimal128(10)\n        val expectedObjectId = ObjectId()\n        val expectedUUID = UUID.randomUUID()\n        var expectedRealmObject = SyncDog().apply {\n            id = expectedObjectId\n        }\n        val expectedRealmList = RealmList<SyncDog>()\n        val expectedStringList = RealmList<String>(\"hello world 1\", \"hello world 2\")\n        val expectedBinaryList = RealmList<ByteArray>(expectedBinary)\n        val expectedBooleanList = RealmList<Boolean>(true, false, false, true)\n        val expectedLongList = RealmList<Long>(0, 1, 2, 5, 7)\n        val expectedDoubleList = RealmList<Double>(0.0, 2.toDouble(), 10.5)\n        val expectedFloatList = RealmList<Float>(0.0.toFloat(), 2.toFloat(), 10.5.toFloat())\n        val expectedDateList = RealmList<Date>(Date(100), Date(10), Date(200))\n        val expectedDecimal128List = RealmList<Decimal128>(Decimal128(10), Decimal128(100), Decimal128(20))\n        val expectedObjectIdList = RealmList<ObjectId>(ObjectId(Date(1000)), ObjectId(Date(100)), ObjectId(Date(2000)))\n        val expectedUUIDList = RealmList<UUID>(UUID.randomUUID())\n        val expectedRealmAnyList = RealmList<RealmAny>()\n        expectedRealmAnyList.addAll(expectedRealmAnyValues)\n\n        val expectedRealmDict = RealmDictionary<SyncDog>()\n        val expectedStringDict = RealmDictionary<String>().init(listOf(\"key\" to expectedString))\n        val expectedBinaryDict = RealmDictionary<ByteArray>().init(listOf(\"key\" to expectedBinary))\n        val expectedBooleanDict = RealmDictionary<Boolean>().init(listOf(\"key\" to expectedBoolean))\n        val expectedLongDict = RealmDictionary<Long>().init(listOf(\"key\" to expectedLong))\n        val expectedDoubleDict = RealmDictionary<Double>().init(listOf(\"key\" to expectedDouble))\n        val expectedFloatDict = RealmDictionary<Float>().init(listOf(\"key\" to expectedFloat))\n        val expectedDateDict = RealmDictionary<Date>().init(listOf(\"key\" to expectedDate))\n        val expectedDecimal128Dict = RealmDictionary<Decimal128>().init(listOf(\"key\" to expectedDecimal128))\n        val expectedObjectIdDict = RealmDictionary<ObjectId>().init(listOf(\"key\" to expectedObjectId))\n        val expectedUUIDDict = RealmDictionary<UUID>().init(listOf(\"key\" to expectedUUID))\n        val expectedRealmAnyDict = RealmDictionary<RealmAny>()\n\n        val expectedRealmSet = RealmSet<SyncDog>()\n        val expectedStringSet = RealmSet<String>().init(listOf(expectedString))\n        val expectedBinarySet = RealmSet<ByteArray>().init(listOf(expectedBinary))\n        val expectedBooleanSet = RealmSet<Boolean>().init(listOf(expectedBoolean))\n        val expectedLongSet = RealmSet<Long>().init(listOf(expectedLong))\n        val expectedDoubleSet = RealmSet<Double>().init(listOf(expectedDouble))\n        val expectedFloatSet = RealmSet<Float>().init(listOf(expectedFloat))\n        val expectedDateSet = RealmSet<Date>().init(listOf(expectedDate))\n        val expectedDecimal128Set = RealmSet<Decimal128>().init(listOf(expectedDecimal128))\n        val expectedObjectIdSet = RealmSet<ObjectId>().init(listOf(expectedObjectId))\n        val expectedUUIDSet = RealmSet<UUID>().init(listOf(expectedUUID))\n        val expectedRealmAnySet = RealmSet<RealmAny>()\n\n        val user1: User = createNewUser()\n        val config1: SyncConfiguration = createDefaultConfig(user1, partitionValue)\n\n        val user2: User = createNewUser()\n        val config2: SyncConfiguration = createDefaultConfig(user2, partitionValue)\n\n        Realm.getInstance(config1).use { realm1 ->\n            Realm.getInstance(config2).use { realm2 ->\n                for (expectedRealmAny in expectedRealmAnyValues) {\n                    realm1.executeTransaction {\n                        expectedRealmObject = realm1.copyToRealmOrUpdate(expectedRealmObject)\n                        expectedRealmList.add(expectedRealmObject)\n                        expectedRealmDict[\"key\"] = expectedRealmObject\n\n                        // Populate object to round-trip\n                        val syncObject = SyncAllTypes().apply {\n                            id = primaryKeyValue\n\n                            RealmFieldType.values().map { realmFieldType ->\n                                when (realmFieldType) {\n                                    RealmFieldType.INTEGER -> {\n                                        columnLong = expectedLong\n                                        // MutableRealmInteger\n                                        columnRealmInteger.set(expectedRealmInteger)\n                                    }\n                                    RealmFieldType.BOOLEAN -> isColumnBoolean = expectedBoolean\n                                    RealmFieldType.STRING -> columnString = expectedString\n                                    RealmFieldType.BINARY -> columnBinary = expectedBinary\n                                    RealmFieldType.DATE -> columnDate = expectedDate\n                                    RealmFieldType.DOUBLE -> columnDouble = expectedDouble\n                                    RealmFieldType.FLOAT -> columnFloat = expectedFloat\n                                    RealmFieldType.OBJECT -> columnRealmObject = expectedRealmObject\n                                    RealmFieldType.DECIMAL128 -> columnDecimal128 = expectedDecimal128\n                                    RealmFieldType.OBJECT_ID -> columnObjectId = expectedObjectId\n                                    RealmFieldType.UUID -> columnUUID = expectedUUID\n                                    RealmFieldType.MIXED -> columnRealmAny = expectedRealmAny\n                                    RealmFieldType.LIST -> columnRealmList = expectedRealmList\n                                    RealmFieldType.INTEGER_LIST -> columnLongList = expectedLongList\n                                    RealmFieldType.BOOLEAN_LIST -> columnBooleanList = expectedBooleanList\n                                    RealmFieldType.STRING_LIST -> columnStringList = expectedStringList\n                                    RealmFieldType.BINARY_LIST -> columnBinaryList = expectedBinaryList\n                                    RealmFieldType.DATE_LIST -> columnDateList = expectedDateList\n                                    RealmFieldType.DOUBLE_LIST -> columnDoubleList = expectedDoubleList\n                                    RealmFieldType.FLOAT_LIST -> columnFloatList = expectedFloatList\n                                    RealmFieldType.DECIMAL128_LIST -> columnDecimal128List = expectedDecimal128List\n                                    RealmFieldType.OBJECT_ID_LIST -> columnObjectIdList = expectedObjectIdList\n                                    RealmFieldType.UUID_LIST -> columnUUIDList = expectedUUIDList\n                                    RealmFieldType.MIXED_LIST -> columnRealmAnyList = expectedRealmAnyList\n                                    RealmFieldType.STRING_TO_INTEGER_MAP -> columnLongDictionary = expectedLongDict\n                                    RealmFieldType.STRING_TO_BOOLEAN_MAP -> columnBooleanDictionary = expectedBooleanDict\n                                    RealmFieldType.STRING_TO_STRING_MAP -> columnStringDictionary = expectedStringDict\n                                    RealmFieldType.STRING_TO_BINARY_MAP -> columnBinaryDictionary = expectedBinaryDict\n                                    RealmFieldType.STRING_TO_DATE_MAP -> columnDateDictionary = expectedDateDict\n                                    RealmFieldType.STRING_TO_DOUBLE_MAP -> columnDoubleDictionary = expectedDoubleDict\n                                    RealmFieldType.STRING_TO_FLOAT_MAP -> columnFloatDictionary = expectedFloatDict\n                                    RealmFieldType.STRING_TO_DECIMAL128_MAP -> columnDecimal128Dictionary = expectedDecimal128Dict\n                                    RealmFieldType.STRING_TO_OBJECT_ID_MAP -> columnObjectIdDictionary = expectedObjectIdDict\n                                    RealmFieldType.STRING_TO_UUID_MAP -> columnUUIDDictionary = expectedUUIDDict\n                                    RealmFieldType.STRING_TO_MIXED_MAP -> {\n                                        expectedRealmAnyDict[\"key\"] = expectedRealmAny\n                                        columnRealmAnyDictionary = expectedRealmAnyDict\n                                    }\n                                    RealmFieldType.STRING_TO_LINK_MAP -> columnRealmDictionary = expectedRealmDict\n                                    RealmFieldType.LINK_SET -> columnRealmSet = expectedRealmSet\n                                    RealmFieldType.INTEGER_SET -> columnLongSet = expectedLongSet\n                                    RealmFieldType.BOOLEAN_SET -> columnBooleanSet = expectedBooleanSet\n                                    RealmFieldType.STRING_SET -> columnStringSet = expectedStringSet\n                                    RealmFieldType.BINARY_SET -> columnBinarySet = expectedBinarySet\n                                    RealmFieldType.DATE_SET -> columnDateSet = expectedDateSet\n                                    RealmFieldType.DOUBLE_SET -> columnDoubleSet = expectedDoubleSet\n                                    RealmFieldType.FLOAT_SET -> columnFloatSet = expectedFloatSet\n                                    RealmFieldType.DECIMAL128_SET -> columnDecimal128Set = expectedDecimal128Set\n                                    RealmFieldType.OBJECT_ID_SET -> columnObjectIdSet = expectedObjectIdSet\n                                    RealmFieldType.UUID_SET -> columnUUIDSet = expectedUUIDSet\n                                    RealmFieldType.MIXED_SET -> columnRealmAnySet = expectedRealmAnySet\n                                    RealmFieldType.LINKING_OBJECTS,     // Nothing to set\n                                    RealmFieldType.TYPED_LINK          // Not an actual exposed type, it is used internally by RealmAny\n                                    -> {}\n                                }\n                            }\n                        }\n\n                        realm1.copyToRealmOrUpdate(syncObject)\n                    }\n                    realm1.syncSession.uploadAllLocalChanges()\n\n                    assertEquals(1, realm1.where<SyncAllTypes>().count())\n\n                    realm2.syncSession.downloadAllServerChanges(TestHelper.STANDARD_WAIT_SECS.toLong(), TimeUnit.SECONDS).let {\n                        if (!it) fail()\n                    }\n                    realm2.refresh()\n\n                    assertEquals(1, realm2.where<SyncAllTypes>().count())\n\n                    // Validate that after a round-trip the values are the initial ones, the expected values\n                    realm2.where<SyncAllTypes>().findFirst()!!.let { syncAllTypes ->\n                        assertEquals(primaryKeyValue, syncAllTypes.id)\n\n                        RealmFieldType.values().map { realmFieldType ->\n                            when (realmFieldType) {\n                                RealmFieldType.INTEGER -> {\n                                    assertEquals(expectedLong, syncAllTypes.columnLong)\n                                    // MutableRealmInteger\n                                    assertEquals(expectedRealmInteger, syncAllTypes.columnRealmInteger.get())\n                                }\n                                RealmFieldType.BOOLEAN -> assertEquals(expectedBoolean, syncAllTypes.isColumnBoolean)\n                                RealmFieldType.STRING -> assertEquals(expectedString, syncAllTypes.columnString)\n                                RealmFieldType.BINARY -> assertTrue(expectedBinary.contentEquals(syncAllTypes.columnBinary))\n                                RealmFieldType.DATE -> assertEquals(expectedDate, syncAllTypes.columnDate)\n                                RealmFieldType.DOUBLE -> assertEquals(expectedDouble, syncAllTypes.columnDouble, 0.0)\n                                RealmFieldType.OBJECT -> assertEquals(expectedObjectId, syncAllTypes.columnRealmObject!!.id)\n                                RealmFieldType.DECIMAL128 -> assertEquals(expectedDecimal128, syncAllTypes.columnDecimal128)\n                                RealmFieldType.OBJECT_ID -> assertEquals(expectedObjectId, syncAllTypes.columnObjectId)\n                                RealmFieldType.UUID -> assertEquals(expectedUUID, syncAllTypes.columnUUID)\n                                RealmFieldType.MIXED -> assertEquals(expectedRealmAny, syncAllTypes.columnRealmAny)\n                                RealmFieldType.LIST -> assertEquals(expectedObjectId, syncAllTypes.columnRealmList.first()!!.id)\n                                RealmFieldType.INTEGER_LIST -> assertEquals(expectedLongList, syncAllTypes.columnLongList)\n                                RealmFieldType.BOOLEAN_LIST -> assertEquals(expectedBooleanList, syncAllTypes.columnBooleanList)\n                                RealmFieldType.STRING_LIST -> assertEquals(expectedStringList, syncAllTypes.columnStringList)\n                                RealmFieldType.BINARY_LIST -> {\n                                    expectedBinaryList.forEachIndexed { index, bytes ->\n                                        Arrays.equals(bytes, syncAllTypes.columnBinaryList[index])\n                                    }\n                                }\n                                RealmFieldType.DATE_LIST -> assertEquals(expectedDateList, syncAllTypes.columnDateList)\n                                RealmFieldType.DOUBLE_LIST -> assertEquals(expectedDoubleList, syncAllTypes.columnDoubleList)\n                                RealmFieldType.DECIMAL128_LIST -> assertEquals(expectedDecimal128List, syncAllTypes.columnDecimal128List)\n                                RealmFieldType.OBJECT_ID_LIST -> assertEquals(expectedObjectIdList, syncAllTypes.columnObjectIdList)\n                                RealmFieldType.UUID_LIST -> assertEquals(expectedUUIDList, syncAllTypes.columnUUIDList)\n                                RealmFieldType.MIXED_LIST -> assertEquals(expectedRealmAnyList, syncAllTypes.columnRealmAnyList)\n                                RealmFieldType.STRING_TO_INTEGER_MAP -> assertEquals(expectedLong, syncAllTypes.columnLongDictionary[\"key\"])\n                                RealmFieldType.STRING_TO_BOOLEAN_MAP -> assertEquals(expectedBoolean, syncAllTypes.columnBooleanDictionary[\"key\"])\n                                RealmFieldType.STRING_TO_STRING_MAP -> assertEquals(expectedString, syncAllTypes.columnStringDictionary[\"key\"])\n                                RealmFieldType.STRING_TO_BINARY_MAP -> assertTrue(Arrays.equals(expectedBinary, syncAllTypes.columnBinaryDictionary[\"key\"]))\n                                RealmFieldType.STRING_TO_DATE_MAP -> assertEquals(expectedDate, syncAllTypes.columnDateDictionary[\"key\"])\n                                RealmFieldType.STRING_TO_DOUBLE_MAP -> assertEquals(expectedDouble, syncAllTypes.columnDoubleDictionary[\"key\"])\n                                RealmFieldType.STRING_TO_DECIMAL128_MAP -> assertEquals(expectedDecimal128, syncAllTypes.columnDecimal128Dictionary[\"key\"])\n                                RealmFieldType.STRING_TO_OBJECT_ID_MAP -> assertEquals(expectedObjectId, syncAllTypes.columnObjectIdDictionary[\"key\"])\n                                RealmFieldType.STRING_TO_UUID_MAP -> assertEquals(expectedUUID, syncAllTypes.columnUUIDDictionary[\"key\"])\n                                RealmFieldType.STRING_TO_MIXED_MAP -> assertEquals(expectedRealmAny, syncAllTypes.columnRealmAnyDictionary[\"key\"])\n                                RealmFieldType.STRING_TO_LINK_MAP -> assertEquals(expectedObjectId, syncAllTypes.columnRealmDictionary[\"key\"]!!.id)\n                                RealmFieldType.INTEGER_SET -> {\n                                    assertEquals(expectedLongSet.size, syncAllTypes.columnLongSet.size)\n                                    expectedLongSet.forEach { value ->\n                                        assertTrue(syncAllTypes.columnLongSet.contains(value))\n                                    }\n                                }\n                                RealmFieldType.BOOLEAN_SET -> {\n                                    assertEquals(expectedBooleanSet.size, syncAllTypes.columnBooleanSet.size)\n                                    expectedBooleanSet.forEach { value ->\n                                        assertTrue(syncAllTypes.columnBooleanSet.contains(value))\n                                    }\n                                }\n                                RealmFieldType.STRING_SET -> {\n                                    assertEquals(expectedStringSet.size, syncAllTypes.columnStringSet.size)\n                                    expectedStringSet.forEach { value ->\n                                        assertTrue(syncAllTypes.columnStringSet.contains(value))\n                                    }\n                                }\n                                RealmFieldType.BINARY_SET -> {\n                                    assertEquals(expectedBinarySet.size, syncAllTypes.columnBinarySet.size)\n                                    expectedBinarySet.forEach { value ->\n                                        assertTrue(syncAllTypes.columnBinarySet.contains(value))\n                                    }\n                                }\n                                RealmFieldType.DATE_SET -> {\n                                    assertEquals(expectedDateSet.size, syncAllTypes.columnDateSet.size)\n                                    expectedDateSet.forEach { value ->\n                                        assertTrue(syncAllTypes.columnDateSet.contains(value))\n                                    }\n                                }\n                                RealmFieldType.DOUBLE_SET -> {\n                                    assertEquals(expectedDoubleSet.size, syncAllTypes.columnDoubleSet.size)\n                                    expectedDoubleSet.forEach { value ->\n                                        assertTrue(syncAllTypes.columnDoubleSet.contains(value))\n                                    }\n                                }\n                                RealmFieldType.DECIMAL128_SET -> {\n                                    assertEquals(expectedDecimal128Set.size, syncAllTypes.columnDecimal128Set.size)\n                                    expectedDecimal128Set.forEach { value ->\n                                        assertTrue(syncAllTypes.columnDecimal128Set.contains(value))\n                                    }\n                                }\n                                RealmFieldType.OBJECT_ID_SET -> {\n                                    assertEquals(expectedObjectIdSet.size, syncAllTypes.columnObjectIdSet.size)\n                                    expectedObjectIdSet.forEach { value ->\n                                        assertTrue(syncAllTypes.columnObjectIdSet.contains(value))\n                                    }\n                                }\n                                RealmFieldType.UUID_SET -> {\n                                    assertEquals(expectedUUIDSet.size, syncAllTypes.columnUUIDSet.size)\n                                    expectedUUIDSet.forEach { value ->\n                                        assertTrue(syncAllTypes.columnUUIDSet.contains(value))\n                                    }\n                                }\n                                RealmFieldType.MIXED_SET -> {\n                                    assertEquals(expectedRealmAnySet.size, syncAllTypes.columnRealmAnySet.size)\n                                    expectedRealmAnySet.forEach { value ->\n                                        assertTrue(syncAllTypes.columnRealmAnySet.contains(value))\n                                    }\n                                }\n                                RealmFieldType.LINK_SET -> {\n                                    assertEquals(expectedRealmSet.size, syncAllTypes.columnRealmSet.size)\n                                    expectedRealmSet.forEach { value ->\n                                        assertTrue(syncAllTypes.columnRealmSet.contains(value))\n                                    }\n                                }\n                                RealmFieldType.LINKING_OBJECTS -> assertEquals(primaryKeyValue, syncAllTypes.columnRealmObject!!.syncAllTypes!!.first()!!.id)\n                                RealmFieldType.TYPED_LINK,          // Not an actual exposed type, it is used internally by RealmAny\n                                RealmFieldType.FLOAT,               // Float is not cloud compatible yet\n                                RealmFieldType.FLOAT_LIST,          // Float is not cloud compatible yet\n                                RealmFieldType.STRING_TO_FLOAT_MAP  // Float is not cloud compatible yet\n                                -> {}\n                            }\n                        }\n                    }\n                }\n            }\n        }\n    }\n\n    @Test\n    // FIXME Missing test, maybe fitting better in SyncSessionTest.kt...when migrated\n    @Ignore(\"Not implemented yet\")\n    fun refreshConnections() = Unit\n\n\n    @Test\n    @UiThread\n    fun writeCopyTo_syncedRealmThrowsOnMainThread() {\n        lateinit var user: User\n        val t = Thread { user = createNewUser() }\n        t.start()\n        t.join()\n        val config: SyncConfiguration = createCustomConfig(user, \"foo\")\n        val realm = Realm.getInstance(config)\n        realm.use { r: Realm ->\n            assertFailsWith<IllegalStateException> { r.writeCopyTo(File(File(config.path).parent, \"dummy.realm\")) }\n        }\n    }\n\n    @Test\n    fun writeCopyTo_syncedRealmThrowsIfLocalChangesNotUploaded() {\n        val user = createNewUser()\n        val config: SyncConfiguration = createCustomConfig(user, \"foo\")\n        val realm = Realm.getInstance(config)\n        realm.syncSession.stop()\n        realm.executeTransaction {\n            it.insert(SyncColor())\n        }\n        realm.use { r: Realm ->\n            assertFailsWith<IllegalStateException> {\n                r.writeCopyTo(File(File(config.path).parent, \"dummy.realm\"))\n            }\n        }\n    }\n\n    @Test\n    fun writeCopyTo() {\n        val user = createNewUser()\n        val partitionValue = UUID.randomUUID().toString()\n        val config: SyncConfiguration = createCustomConfig(user, partitionValue)\n        val copy = File(Realm.getApplicationContext()!!.filesDir,\"copy.realm\")\n        Realm.getInstance(config).use { realm: Realm ->\n            realm.executeTransaction {\n                it.insert(SyncColor())\n            }\n\n            // Create copy of file\n            if (copy.exists()) {\n                copy.delete()\n            }\n            realm.syncSession.uploadAllLocalChanges()\n            realm.syncSession.downloadAllServerChanges() // Work around for https://github.com/realm/realm-core/issues/4865\n            realm.writeCopyTo(copy)\n        }\n\n        // Manually move the file into the place of another user.\n        // and verify that the user can sync with the Realm.\n        // We cannot use the \"assetFile\" API that users do, as terminating\n        // Sync renders the file invalid, so we cannot package a test file\n        // for later use.\n        val user2 = createNewUser()\n        val config2: SyncConfiguration = createCustomConfig(user2, partitionValue)\n        val destination = File(config2.path)\n        destination.delete()\n        assertTrue(copy.renameTo(destination))\n\n        Realm.getInstance(config2).use { realm: Realm ->\n            // Check that the copy contains data\n            assertEquals(1, realm.where<SyncColor>().count())\n            realm.executeTransaction {\n                realm.createObject(SyncColor::class.java, ObjectId())\n            }\n            // Check that we can synchronize with the server\n            realm.syncSession.downloadAllServerChanges()\n            realm.syncSession.uploadAllLocalChanges()\n        }\n    }\n\n    @Test\n    fun writeCopyEncryptedTo() {\n        val key = TestHelper.getRandomKey()\n\n        val user = createNewUser()\n        val partitionValue = UUID.randomUUID().toString()\n        val config: SyncConfiguration = createCustomConfig(user, partitionValue)\n        val copy = File(Realm.getApplicationContext()!!.filesDir,\"copy.realm\")\n        Realm.getInstance(config).use { realm: Realm ->\n            realm.executeTransaction {\n                it.insert(SyncColor())\n            }\n\n            // Create copy of file\n            if (copy.exists()) {\n                copy.delete()\n            }\n            realm.syncSession.uploadAllLocalChanges()\n            realm.syncSession.downloadAllServerChanges() // Work around for https://github.com/realm/realm-core/issues/4865\n            realm.writeEncryptedCopyTo(copy, key)\n        }\n\n        // Manually move the file into the place of another user.\n        // and verify that the user can sync with the Realm.\n        // We cannot use the \"assetFile\" API that users do, as terminating\n        // Sync renders the file invalid, so we cannot package a test file\n        // for later use.\n        val user2 = createNewUser()\n        val config2: SyncConfiguration = SyncConfiguration.Builder(user2, partitionValue)\n                .schema(SyncColor::class.java)\n                .encryptionKey(key)\n                .build()\n        val destination = File(config2.path)\n        destination.delete()\n        assertTrue(copy.renameTo(destination))\n\n        Realm.getInstance(config2).use { realm: Realm ->\n            // Check that the copy contains data\n            assertEquals(1, realm.where<SyncColor>().count())\n            realm.executeTransaction {\n                realm.createObject(SyncColor::class.java, ObjectId())\n            }\n\n            // Check that we can synchronize with the server\n            realm.syncSession.downloadAllServerChanges()\n            realm.syncSession.uploadAllLocalChanges()\n        }\n    }\n\n    @Test\n    @Ignore(\"See https://github.com/realm/realm-java/issues/7700\")\n    fun assetFile() {\n        val user = createNewUser()\n        val config = SyncConfiguration.Builder(user, \"e873fb25-11ef-498f-9782-3c8e1cd2a12c\")\n            .assetFile(\"synced_realm_e873fb25-11ef-498f-9782-3c8e1cd2a12c_no_client_id.realm\")\n            .syncClientResetStrategy(ManuallyRecoverUnsyncedChangesStrategy {\n                    session, error -> fail(\"Client reset should not have been invoked\")\n            })\n            .schema(SyncColor::class.java)\n            .build()\n\n        Realm.getInstance(config).use { realm: Realm ->\n            realm.syncSession.downloadAllServerChanges()\n            assertEquals(1, realm.where<SyncColor>().count())\n        }\n    }\n\n    @Test\n    @Ignore(\"See https://github.com/realm/realm-java/issues/7700\")\n    fun assetFile_wrongPartitionValue() = looperThread.runBlocking {\n        val user = createNewUser()\n        val config = SyncConfiguration.Builder(user, \"foo\")\n                .clientResetHandler { _, error ->\n                    // Client reset expected when connecting with wrong partition value\n                    assertEquals(ErrorCode.CLIENT_RESET, error.errorCode)\n                    looperThread.testComplete()\n                }\n                .assetFile(\"synced_realm_e873fb25-11ef-498f-9782-3c8e1cd2a12c_no_client_id.realm\")\n                .schema(SyncColor::class.java)\n                .build()\n\n        val realm = Realm.getInstance(config)\n        looperThread.keepStrongReference(realm)\n        looperThread.closeAfterTest(realm)\n        assertEquals(1, realm.where<SyncColor>().count())\n    }\n\n    @Test\n    fun assetFile_wrongFileType() {\n        val user = createNewUser()\n        val config = SyncConfiguration.Builder(user, \"foo\")\n                .assetFile(\"versionTest.realm\")\n                .schema(SyncColor::class.java)\n                .build()\n\n        assertFailsWith<RealmFileException> {\n            Realm.getInstance(config)\n        }\n    }\n\n    @Test\n    fun customSyncRoot() {\n        app.close()\n        Realm.init(InstrumentationRegistry.getInstrumentation().targetContext)\n        val defaultRoot = File(Realm.getApplicationContext()!!.filesDir, \"mongodb-realm\")\n        val root = File(Realm.getApplicationContext()!!.filesDir, \"my-custom-dir\")\n        if (defaultRoot.exists()) { assertTrue(defaultRoot.deleteRecursively()) }\n        if (root.exists()) { assertTrue(root.deleteRecursively()) }\n\n        app = TestApp(builder = { it.syncRootDirectory(root) })\n        assertTrue(\"Root folder wasn't created\", root.exists())\n        assertFalse(\"Default folder was created\", defaultRoot.exists())\n\n        try {\n            val user: User = createNewUser()\n            val config = createDefaultConfig(user)\n            assertTrue(\"Wrong path: ${config.path}\", config.path.contains(\"/my-custom-dir/mongodb-realm/\"))\n            Realm.getInstance(config).close()\n            assertTrue(File(config.path).exists())\n            assertFalse(\"Default folder was created\", defaultRoot.exists())\n        } finally {\n            assertTrue(root.deleteRecursively())\n        }\n    }\n\n    private fun createDefaultConfig(user: User, partitionValue: String = defaultPartitionValue): SyncConfiguration {\n        return SyncConfiguration.Builder(user, partitionValue)\n                .modules(DefaultSyncSchema())\n                .build()\n    }\n\n    private fun createCustomConfig(user: User, partitionValue: String = defaultPartitionValue): SyncConfiguration {\n        return SyncConfiguration.Builder(user, partitionValue)\n            .schema(SyncColor::class.java)\n            .build()\n    }\n\n    private fun createNewUser(): User {\n        val email = TestHelper.getRandomEmail()\n        val password = \"123456\"\n        app.emailPassword.registerUser(email, password)\n        return app.login(Credentials.emailPassword(email, password))\n    }\n\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTestObjectServer/kotlin/io/realm/mongodb/sync/TrustManagerCertificateValidationTests.java",
    "content": "package io.realm.mongodb.sync;\n\nimport static org.junit.Assert.assertFalse;\nimport static org.junit.Assert.assertTrue;\n\nimport androidx.test.core.app.ApplicationProvider;\nimport androidx.test.ext.junit.runners.AndroidJUnit4;\n\nimport org.junit.BeforeClass;\nimport org.junit.Ignore;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport io.realm.Realm;\n\n@RunWith(AndroidJUnit4.class)\npublic class TrustManagerCertificateValidationTests {\n\n    @BeforeClass\n    public static void setUp() {\n        // mainly to setup logging otherwise\n        // java.lang.UnsatisfiedLinkError: No implementation found for void io.realm.log.RealmLog.nativeSetLogLevel(int) (tried Java_io_realm_log_RealmLog_nativeSetLogLevel and Java_io_realm_log_RealmLog_nativeSetLogLevel__I)\n        // will be thrown\n        Realm.init(ApplicationProvider.getApplicationContext());\n    }\n\n    // IMPORTANT: Following test assume the root certificate is installed on the test device\n    //            certificate is located in <realm-java>/tools/sync_test_server/keys/android_test_certificate.crt\n    //            adb push <realm-java>/tools/sync_test_server/keys/android_test_certificate.crt /sdcard/\n    //            then import the certificate from the device (Settings/Security/Install from storage)\n    @Test\n    @Ignore(\"FIXME: https://github.com/realm/realm-java/issues/6472\")\n    public void sslVerifyCallback_certificateChainWithRootCAInstalledShouldValidate() {\n        // simulating the following certificate chain\n        // ---\n        // Certificate chain\n        // 0 s:/DC=127.0.0.1/O=Realm/OU=Realm/CN=127.0.0.1\n        // i:/DC=io/DC=realm/O=Realm/OU=Realm Test Signing CA/CN=Realm Test Signing CA\n        // 1 s:/DC=io/DC=realm/O=Realm/OU=Realm Test Signing CA/CN=Realm Test Signing CA\n        // i:/DC=io/DC=realm/O=Realm/OU=Realm Test Root CA/CN=Realm Test Root CA\n        // ---\n\n        // s:/DC=127.0.0.1/O=Realm/OU=Realm/CN=127.0.0.1\n        String pem_depth0 = \"-----BEGIN CERTIFICATE-----\\n\" +\n                \"MIIE1DCCArygAwIBAgIBBzANBgkqhkiG9w0BAQUFADB7MRIwEAYKCZImiZPyLGQB\\n\" +\n                \"GRYCaW8xFTATBgoJkiaJk/IsZAEZFgVyZWFsbTEOMAwGA1UECgwFUmVhbG0xHjAc\\n\" +\n                \"BgNVBAsMFVJlYWxtIFRlc3QgU2lnbmluZyBDQTEeMBwGA1UEAwwVUmVhbG0gVGVz\\n\" +\n                \"dCBTaWduaW5nIENBMB4XDTE3MDUxNzIzMjg0OFoXDTE5MDUxNzIzMjg0OFowTzEZ\\n\" +\n                \"MBcGCgmSJomT8ixkARkWCTEyNy4wLjAuMTEOMAwGA1UECgwFUmVhbG0xDjAMBgNV\\n\" +\n                \"BAsMBVJlYWxtMRIwEAYDVQQDDAkxMjcuMC4wLjEwggEiMA0GCSqGSIb3DQEBAQUA\\n\" +\n                \"A4IBDwAwggEKAoIBAQC3jJl7a1spgJyZt/64HgZsTVi9OLbME2r//fYmoHHSipTq\\n\" +\n                \"Br7huFsDXpaOYRkPgF+4UUOXADhnRw4JuKuA0ZyBuIHbC7TF3no89ZzLvysS/rGd\\n\" +\n                \"TqBKq67EERlUxRftWMNy8OVG3CFBTGMdMYXzuvataT7Yhp3EVjtSR10k3UCv+foD\\n\" +\n                \"TE4tW9I03PCkGRMU9mx8HEe9fXmiCWGtP41OWcWupys5AOk0aGxv2GCiqSQzHJ+A\\n\" +\n                \"tMaOujeYcT3dgmbY4MKBzEvRXVgmz4UKrP0IpUBQ//lz6CcYe3B1cyojx9cVvsrO\\n\" +\n                \"V8nuu2202P3HIkcomwBeS6+CY8PXanROYBeUavuDAgMBAAGjgY4wgYswDgYDVR0P\\n\" +\n                \"AQH/BAQDAgWgMAkGA1UdEwQCMAAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUF\\n\" +\n                \"BwMCMB0GA1UdDgQWBBTGvfRJ9S52UkTx4s4ubPlZsVYUrTAfBgNVHSMEGDAWgBQn\\n\" +\n                \"eeHa8RXQ6eWGMIfnH1/PJzpwtDAPBgNVHREECDAGhwR/AAABMA0GCSqGSIb3DQEB\\n\" +\n                \"BQUAA4ICAQCbP3T0aXJrW3WItxBf4HOygr7ccRuj1qRurqZfUXhcgGQgISATFgjQ\\n\" +\n                \"rhX2UiTZI1wk7WI7DuZfAEu/oZQ0KvsqRl9U5jt/voFb3+h4ph7O4oe5i+TYBB8Y\\n\" +\n                \"xCmAeiGpVsUp7k4oM/qNkkaiMTHF+TEZ7R32x3WCZbYarbw0SvMYBaCj1JpQ8u+7\\n\" +\n                \"xC+JEJVoF2qFds6IjBnP16pww9BZm5rA0KjQ08318I5eGauhrlTcB6xtbtjw7mVH\\n\" +\n                \"3ikedhsdDmL13R32bq0nLo2+xKhBC7FEIj0ps1d0PjtBKBmNSO1lBVuOF6erRSTZ\\n\" +\n                \"lQDkBOds2GtrKoleH/u08hwgVer1QJlYot7Dg+UBcPhT6Y2Vugsg0JnmtDEFVQCc\\n\" +\n                \"9/OWfHRbfcdqruyQ+A/y8FjsgAx5BLDzac3lQfL1/ES62U8/Mv5p824fMpRieBd2\\n\" +\n                \"3NUMGaaLl3DpGTmo+rEAphhvSy04Lx2WC4eYhsEsdUQ8DuHr9MROAsef98wwinIj\\n\" +\n                \"v0R8fD/3fLGx16pL5B7dyv1ajS6q/0mvpWNviDEmfbOk401NRdZEexKobga7gcCA\\n\" +\n                \"pF+VO9SlSgEdAA57XSApl9DWiHPxicEBVIWbnO9Bbfm2g8xlrDTKv4j8NE9/YjDi\\n\" +\n                \"2QLrx1iGkG/kfl8gRfLEoH6tklqFjwiQPehlvlR54mI8XY5XNioXuw==\\n\" +\n                \"-----END CERTIFICATE-----\";\n\n        // s:/DC=io/DC=realm/O=Realm/OU=Realm Test Signing CA/CN=Realm Test Signing CA\n        String pem_depth1 = \"-----BEGIN CERTIFICATE-----\\n\" +\n                \"MIIF0TCCA7mgAwIBAgIBAjANBgkqhkiG9w0BAQUFADB1MRIwEAYKCZImiZPyLGQB\\n\" +\n                \"GRYCaW8xFTATBgoJkiaJk/IsZAEZFgVyZWFsbTEOMAwGA1UECgwFUmVhbG0xGzAZ\\n\" +\n                \"BgNVBAsMElJlYWxtIFRlc3QgUm9vdCBDQTEbMBkGA1UEAwwSUmVhbG0gVGVzdCBS\\n\" +\n                \"b290IENBMB4XDTE2MDkwNzEwMTcyOFoXDTI2MDkwNzEwMTcyOFowezESMBAGCgmS\\n\" +\n                \"JomT8ixkARkWAmlvMRUwEwYKCZImiZPyLGQBGRYFcmVhbG0xDjAMBgNVBAoMBVJl\\n\" +\n                \"YWxtMR4wHAYDVQQLDBVSZWFsbSBUZXN0IFNpZ25pbmcgQ0ExHjAcBgNVBAMMFVJl\\n\" +\n                \"YWxtIFRlc3QgU2lnbmluZyBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoC\\n\" +\n                \"ggIBAL9bWpLeU69zgOE/IlV1OH2eO2VJqtOnrAS+TaXCfQMwydhB0gAKzd+jaKUT\\n\" +\n                \"kgpxIsUJ1HWXc6b6N2SnYVWEiMG+65LgphsABMQx/UrpFFbIrQtcc8hVHOZgsTrj\\n\" +\n                \"wh1BGm1XEt/awv5A59GlcSlxyw0S1ca+6KtinBFwtd7xILa8Ba96P+TfdDPWu6Mz\\n\" +\n                \"WfM6oK8t6ucWyI8l8fsnc4BG40RbuPVMuo5hbV8swI/o0r066A36Ft4yGYTIbK0R\\n\" +\n                \"FFzORL5GvvB7gych8Un1uuW8WQewwvtPflZ268sU8VDWs4MQK7HTgGiYRWdwnhvv\\n\" +\n                \"/yjQ7xo4KGQWhFrRnwV/FVBqzqwIJeQ/1t8J2VmyBdm345Su9sYEaS7VR3lUkvty\\n\" +\n                \"8kwJK2Q6PtEwdgwzZQoIVTREgwXpHlHCWHBEMGzvCuCw4hAr4VUpJANoYbtEWOqt\\n\" +\n                \"A7OpDxNE/+ok03u9JXhXeXvkS568MjNj1fclOffFMY2f8naja7tbpN3MlkS0RJ1Q\\n\" +\n                \"7y5kKQKjx1L3NpLF+vt13SVnPkY3453c3vblagqVfumQPsmx+HQHuf/yJMmE8J88\\n\" +\n                \"p87KZL53HnyTKW/Ijo1006gd4dubi8Mn2A0D/H4+JRlquKWX0HrDEzO8OozHJen5\\n\" +\n                \"z0rFwyZjQu9Y10IGMIogyM1qQIv6iOBU7WAJaSYSQ7Xyk2xbAgMBAAGjZjBkMA4G\\n\" +\n                \"A1UdDwEB/wQEAwIBBjASBgNVHRMBAf8ECDAGAQH/AgEAMB0GA1UdDgQWBBQneeHa\\n\" +\n                \"8RXQ6eWGMIfnH1/PJzpwtDAfBgNVHSMEGDAWgBSEcHEsBDvQkoO1+3x/sGEMYhZx\\n\" +\n                \"dDANBgkqhkiG9w0BAQUFAAOCAgEANgWEjIghCKfivUGoJ3+3wpqG1yH+7UxR0Snf\\n\" +\n                \"NUoO6qC1bMwoL169n5dovqoq/1SRnu8EXQ3s55g1EHhQth8XlqlemmD7aOkGfVOM\\n\" +\n                \"WLeaR+CfyNFDGnRBP6sDITWIjjQ6JbeYZySL1BSIVxyZ3wgMvVefU9s6R6TlTCk4\\n\" +\n                \"4oI5RepiyhvYlcsK42UQl8cQ14st2/oWxsQMgSbmb/Ha+3nAEidYmiuVoL1ziK31\\n\" +\n                \"rZvNST2tLAKE+Ii+PL/XoijoCR58DbBWrebjpxFWWGaD3YAxVqYVReHjUkny+Ew8\\n\" +\n                \"YP3WG0Vh7FLB2bnasF1cO3/vNN1IJhlaZq21p4drc+jq013N0T+sd+RZjU2VOC/o\\n\" +\n                \"F/+PZ8j4XY6Gt3hQJWI1uQcV9utlmICWC9IUy1QadQyr2cKZGyDa46R3aO91zER/\\n\" +\n                \"ZvRHjHoDIbZsxwCyUBWEXIcq+wM61y3fUpaAtsA9oEtlZ17zvUH+9GI63g8wjUe/\\n\" +\n                \"igv4Dth7hJNg5nOpYBHzWhYsKljA3HiPZsgQkNXaAzXppyKKBBTP4fvJRl/MKe/H\\n\" +\n                \"Ir1lpIpH4NUQDRJMo3IR5l+eW4c460h03YYmq0VhY0VSIak1ZYQwSYVokLYjDPAQ\\n\" +\n                \"ft7h6D2Ubf9EoC6GHEy77HKFO9BtSWlHqWEfxTnL1noG6UFS3wAAwAg/Ib1EUsR4\\n\" +\n                \"pf7lM/4=\\n\" +\n                \"-----END CERTIFICATE-----\\n\";\n\n        String serverAddress = \"127.0.0.1\";\n\n        assertTrue(Sync.sslVerifyCallback(serverAddress, pem_depth1, 1));\n        assertTrue(Sync.sslVerifyCallback(serverAddress, pem_depth0, 0));\n    }\n\n    @Test\n    public void sslVerifyCallback_shouldFailOnExpiredCert() {\n        // simulating the following certificate chain (one of the\n        // ---\n        // Certificate chain\n        // 0 s:/CN=*.ie1.realmlab.net\n        // i:/C=US/O=Amazon/OU=Server CA 1B/CN=Amazon\n        // 1 s:/C=US/O=Amazon/OU=Server CA 1B/CN=Amazon\n        // i:/C=US/O=Amazon/CN=Amazon Root CA 1\n        // 2 s:/C=US/O=Amazon/CN=Amazon Root CA 1\n        // i:/C=US/ST=Arizona/L=Scottsdale/O=Starfield Technologies, Inc./CN=Starfield Services Root Certificate Authority - G2\n        // 3 s:/C=US/ST=Arizona/L=Scottsdale/O=Starfield Technologies, Inc./CN=Starfield Services Root Certificate Authority - G2\n        // i:/C=US/O=Starfield Technologies, Inc./OU=Starfield Class 2 Certification Authority\n        // ---\n\n        // ie1.realmlab.net (!!!! EXPIRED on May 3, 2018)\n        String pem_depth0 = \"-----BEGIN CERTIFICATE-----\\n\" +\n                \"MIIEWDCCA0CgAwIBAgIQBE6+74j1z/Z88OEsSc3VIzANBgkqhkiG9w0BAQsFADBG\\n\" +\n                \"MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRUwEwYDVQQLEwxTZXJ2ZXIg\\n\" +\n                \"Q0EgMUIxDzANBgNVBAMTBkFtYXpvbjAeFw0xNzA0MDMwMDAwMDBaFw0xODA1MDMx\\n\" +\n                \"MjAwMDBaMB0xGzAZBgNVBAMMEiouaWUxLnJlYWxtbGFiLm5ldDCCASIwDQYJKoZI\\n\" +\n                \"hvcNAQEBBQADggEPADCCAQoCggEBAKfV/38WJ47qvr4Onopu+XKYlTyTsvouX2VQ\\n\" +\n                \"jRopM0gdXehp9BfwnFme8KUVZLSYh0vdmY7Wm5A7oxcL4ZuUpDSs9+xuERNg1YMD\\n\" +\n                \"gI46ehj08+KUSfuqsVuw3gpNM6VPtpKY2I4//fJFmJKTWXA/fl35By0Xbuv4I180\\n\" +\n                \"FFWu7CV0N4b/QQsjT0+CVvAjHRMMTpw0qtcZGQ4lWNNiqcqUql+Eklm/90S+lyBD\\n\" +\n                \"q8YQUwcxhMgxKt6M5zwJpWuIbjov9kygDzlw/YU8P5wqvgocfnnXaKw+rr7EdiTS\\n\" +\n                \"U2ZT99JO0F0CPzPZnphNrRtjkJ4Chtp0FVRqAdthpGH4i1VIKP0CAwEAAaOCAWkw\\n\" +\n                \"ggFlMB8GA1UdIwQYMBaAFFmkZgZSoHuVkjyjlAcnlnRb+T3QMB0GA1UdDgQWBBRP\\n\" +\n                \"5MQbQpMCFJgjiFgEtZUIiKdNeDAdBgNVHREEFjAUghIqLmllMS5yZWFsbWxhYi5u\\n\" +\n                \"ZXQwDgYDVR0PAQH/BAQDAgWgMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcD\\n\" +\n                \"AjA7BgNVHR8ENDAyMDCgLqAshipodHRwOi8vY3JsLnNjYTFiLmFtYXpvbnRydXN0\\n\" +\n                \"LmNvbS9zY2ExYi5jcmwwEwYDVR0gBAwwCjAIBgZngQwBAgEwdQYIKwYBBQUHAQEE\\n\" +\n                \"aTBnMC0GCCsGAQUFBzABhiFodHRwOi8vb2NzcC5zY2ExYi5hbWF6b250cnVzdC5j\\n\" +\n                \"b20wNgYIKwYBBQUHMAKGKmh0dHA6Ly9jcnQuc2NhMWIuYW1hem9udHJ1c3QuY29t\\n\" +\n                \"L3NjYTFiLmNydDAMBgNVHRMBAf8EAjAAMA0GCSqGSIb3DQEBCwUAA4IBAQAObbVL\\n\" +\n                \"zDqqFO4iDjR4VRTYQbb3gSDxySqFqMm4iBJBmqgNRDsNDb75EmlbB0udbZ6+LHDK\\n\" +\n                \"pmPh81ocdJECHZctidDh1zCkVf3uOYyPJqxNpt0ZCurGMTi4i5kaIbAwR50lZU2V\\n\" +\n                \"eSkR5rYFoBIVcUNbXzzOMLTcJrRqbVYz7z9zCN71l12dKNMXdu9tLcec+WCGi0R+\\n\" +\n                \"MNBOQ/XVlAzymsmQM6nWb0DEQ86ya9AAAMVQBVgyeEPZNPidxc82kU8pML9mO0Yl\\n\" +\n                \"MtbgZWXH1kTppsi+/WbOwy+kalpiMJ7TXIvHmQat81FWiJNTnKwfVEsz79Op8EAW\\n\" +\n                \"p9RkpzfSQpZQ30/u\\n\" +\n                \"-----END CERTIFICATE-----\\n\";\n\n        // OU=Server CA 1B/CN=Amazon\n        String pem_depth1 = \"-----BEGIN CERTIFICATE-----\\n\" +\n                \"MIIESTCCAzGgAwIBAgITBn+UV4WH6Kx33rJTMlu8mYtWDTANBgkqhkiG9w0BAQsF\\n\" +\n                \"ADA5MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6\\n\" +\n                \"b24gUm9vdCBDQSAxMB4XDTE1MTAyMjAwMDAwMFoXDTI1MTAxOTAwMDAwMFowRjEL\\n\" +\n                \"MAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEVMBMGA1UECxMMU2VydmVyIENB\\n\" +\n                \"IDFCMQ8wDQYDVQQDEwZBbWF6b24wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK\\n\" +\n                \"AoIBAQDCThZn3c68asg3Wuw6MLAd5tES6BIoSMzoKcG5blPVo+sDORrMd4f2AbnZ\\n\" +\n                \"cMzPa43j4wNxhplty6aUKk4T1qe9BOwKFjwK6zmxxLVYo7bHViXsPlJ6qOMpFge5\\n\" +\n                \"blDP+18x+B26A0piiQOuPkfyDyeR4xQghfj66Yo19V+emU3nazfvpFA+ROz6WoVm\\n\" +\n                \"B5x+F2pV8xeKNR7u6azDdU5YVX1TawprmxRC1+WsAYmz6qP+z8ArDITC2FMVy2fw\\n\" +\n                \"0IjKOtEXc/VfmtTFch5+AfGYMGMqqvJ6LcXiAhqG5TI+Dr0RtM88k+8XUBCeQ8IG\\n\" +\n                \"KuANaL7TiItKZYxK1MMuTJtV9IblAgMBAAGjggE7MIIBNzASBgNVHRMBAf8ECDAG\\n\" +\n                \"AQH/AgEAMA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUWaRmBlKge5WSPKOUByeW\\n\" +\n                \"dFv5PdAwHwYDVR0jBBgwFoAUhBjMhTTsvAyUlC4IWZzHshBOCggwewYIKwYBBQUH\\n\" +\n                \"AQEEbzBtMC8GCCsGAQUFBzABhiNodHRwOi8vb2NzcC5yb290Y2ExLmFtYXpvbnRy\\n\" +\n                \"dXN0LmNvbTA6BggrBgEFBQcwAoYuaHR0cDovL2NydC5yb290Y2ExLmFtYXpvbnRy\\n\" +\n                \"dXN0LmNvbS9yb290Y2ExLmNlcjA/BgNVHR8EODA2MDSgMqAwhi5odHRwOi8vY3Js\\n\" +\n                \"LnJvb3RjYTEuYW1hem9udHJ1c3QuY29tL3Jvb3RjYTEuY3JsMBMGA1UdIAQMMAow\\n\" +\n                \"CAYGZ4EMAQIBMA0GCSqGSIb3DQEBCwUAA4IBAQCFkr41u3nPo4FCHOTjY3NTOVI1\\n\" +\n                \"59Gt/a6ZiqyJEi+752+a1U5y6iAwYfmXss2lJwJFqMp2PphKg5625kXg8kP2CN5t\\n\" +\n                \"6G7bMQcT8C8xDZNtYTd7WPD8UZiRKAJPBXa30/AbwuZe0GaFEQ8ugcYQgSn+IGBI\\n\" +\n                \"8/LwhBNTZTUVEWuCUUBVV18YtbAiPq3yXqMB48Oz+ctBWuZSkbvkNodPLamkB2g1\\n\" +\n                \"upRyzQ7qDn1X8nn8N8V7YJ6y68AtkHcNSRAnpTitxBKjtKPISLMVCx7i4hncxHZS\\n\" +\n                \"yLyKQXhw2W2Xs0qLeC1etA+jTGDK4UfLeC0SF7FSi8o5LL21L8IzApar2pR/\\n\" +\n                \"-----END CERTIFICATE-----\\n\";\n        // Amazon Root CA 1\n        String pem_depth2 = \"-----BEGIN CERTIFICATE-----\\n\" +\n                \"MIIEkjCCA3qgAwIBAgITBn+USionzfP6wq4rAfkI7rnExjANBgkqhkiG9w0BAQsF\\n\" +\n                \"ADCBmDELMAkGA1UEBhMCVVMxEDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNj\\n\" +\n                \"b3R0c2RhbGUxJTAjBgNVBAoTHFN0YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4x\\n\" +\n                \"OzA5BgNVBAMTMlN0YXJmaWVsZCBTZXJ2aWNlcyBSb290IENlcnRpZmljYXRlIEF1\\n\" +\n                \"dGhvcml0eSAtIEcyMB4XDTE1MDUyNTEyMDAwMFoXDTM3MTIzMTAxMDAwMFowOTEL\\n\" +\n                \"MAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJv\\n\" +\n                \"b3QgQ0EgMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALJ4gHHKeNXj\\n\" +\n                \"ca9HgFB0fW7Y14h29Jlo91ghYPl0hAEvrAIthtOgQ3pOsqTQNroBvo3bSMgHFzZM\\n\" +\n                \"9O6II8c+6zf1tRn4SWiw3te5djgdYZ6k/oI2peVKVuRF4fn9tBb6dNqcmzU5L/qw\\n\" +\n                \"IFAGbHrQgLKm+a/sRxmPUDgH3KKHOVj4utWp+UhnMJbulHheb4mjUcAwhmahRWa6\\n\" +\n                \"VOujw5H5SNz/0egwLX0tdHA114gk957EWW67c4cX8jJGKLhD+rcdqsq08p8kDi1L\\n\" +\n                \"93FcXmn/6pUCyziKrlA4b9v7LWIbxcceVOF34GfID5yHI9Y/QCB/IIDEgEw+OyQm\\n\" +\n                \"jgSubJrIqg0CAwEAAaOCATEwggEtMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/\\n\" +\n                \"BAQDAgGGMB0GA1UdDgQWBBSEGMyFNOy8DJSULghZnMeyEE4KCDAfBgNVHSMEGDAW\\n\" +\n                \"gBScXwDfqgHXMCs4iKK4bUqc8hGRgzB4BggrBgEFBQcBAQRsMGowLgYIKwYBBQUH\\n\" +\n                \"MAGGImh0dHA6Ly9vY3NwLnJvb3RnMi5hbWF6b250cnVzdC5jb20wOAYIKwYBBQUH\\n\" +\n                \"MAKGLGh0dHA6Ly9jcnQucm9vdGcyLmFtYXpvbnRydXN0LmNvbS9yb290ZzIuY2Vy\\n\" +\n                \"MD0GA1UdHwQ2MDQwMqAwoC6GLGh0dHA6Ly9jcmwucm9vdGcyLmFtYXpvbnRydXN0\\n\" +\n                \"LmNvbS9yb290ZzIuY3JsMBEGA1UdIAQKMAgwBgYEVR0gADANBgkqhkiG9w0BAQsF\\n\" +\n                \"AAOCAQEAYjdCXLwQtT6LLOkMm2xF4gcAevnFWAu5CIw+7bMlPLVvUOTNNWqnkzSW\\n\" +\n                \"MiGpSESrnO09tKpzbeR/FoCJbM8oAxiDR3mjEH4wW6w7sGDgd9QIpuEdfF7Au/ma\\n\" +\n                \"eyKdpwAJfqxGF4PcnCZXmTA5YpaP7dreqsXMGz7KQ2hsVxa81Q4gLv7/wmpdLqBK\\n\" +\n                \"bRRYh5TmOTFffHPLkIhqhBGWJ6bt2YFGpn6jcgAKUj6DiAdjd4lpFw85hdKrCEVN\\n\" +\n                \"0FE6/V1dN2RMfjCyVSRCnTawXZwXgWHxyvkQAiSr6w10kY17RSlQOYiypok1JR4U\\n\" +\n                \"akcjMS9cmvqtmg5iUaQqqcT5NJ0hGA==\\n\" +\n                \"-----END CERTIFICATE-----\\n\";\n\n        // O=Starfield Technologies, Inc./CN=Starfield Services Root Certificate Authority - G2\n        String pem_depth3 = \"-----BEGIN CERTIFICATE-----\\n\" +\n                \"MIIEdTCCA12gAwIBAgIJAKcOSkw0grd/MA0GCSqGSIb3DQEBCwUAMGgxCzAJBgNV\\n\" +\n                \"BAYTAlVTMSUwIwYDVQQKExxTdGFyZmllbGQgVGVjaG5vbG9naWVzLCBJbmMuMTIw\\n\" +\n                \"MAYDVQQLEylTdGFyZmllbGQgQ2xhc3MgMiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0\\n\" +\n                \"eTAeFw0wOTA5MDIwMDAwMDBaFw0zNDA2MjgxNzM5MTZaMIGYMQswCQYDVQQGEwJV\\n\" +\n                \"UzEQMA4GA1UECBMHQXJpem9uYTETMBEGA1UEBxMKU2NvdHRzZGFsZTElMCMGA1UE\\n\" +\n                \"ChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjE7MDkGA1UEAxMyU3RhcmZp\\n\" +\n                \"ZWxkIFNlcnZpY2VzIFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IC0gRzIwggEi\\n\" +\n                \"MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDVDDrEKvlO4vW+GZdfjohTsR8/\\n\" +\n                \"y8+fIBNtKTrID30892t2OGPZNmCom15cAICyL1l/9of5JUOG52kbUpqQ4XHj2C0N\\n\" +\n                \"Tm/2yEnZtvMaVq4rtnQU68/7JuMauh2WLmo7WJSJR1b/JaCTcFOD2oR0FMNnngRo\\n\" +\n                \"Ot+OQFodSk7PQ5E751bWAHDLUu57fa4657wx+UX2wmDPE1kCK4DMNEffud6QZW0C\\n\" +\n                \"zyyRpqbn3oUYSXxmTqM6bam17jQuug0DuDPfR+uxa40l2ZvOgdFFRjKWcIfeAg5J\\n\" +\n                \"Q4W2bHO7ZOphQazJ1FTfhy/HIrImzJ9ZVGif/L4qL8RVHHVAYBeFAlU5i38FAgMB\\n\" +\n                \"AAGjgfAwge0wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0O\\n\" +\n                \"BBYEFJxfAN+qAdcwKziIorhtSpzyEZGDMB8GA1UdIwQYMBaAFL9ft9HO3R+G9FtV\\n\" +\n                \"rNzXEMIOqYjnME8GCCsGAQUFBwEBBEMwQTAcBggrBgEFBQcwAYYQaHR0cDovL28u\\n\" +\n                \"c3MyLnVzLzAhBggrBgEFBQcwAoYVaHR0cDovL3guc3MyLnVzL3guY2VyMCYGA1Ud\\n\" +\n                \"HwQfMB0wG6AZoBeGFWh0dHA6Ly9zLnNzMi51cy9yLmNybDARBgNVHSAECjAIMAYG\\n\" +\n                \"BFUdIAAwDQYJKoZIhvcNAQELBQADggEBACMd44pXyn3pF3lM8R5V/cxTbj5HD9/G\\n\" +\n                \"VfKyBDbtgB9TxF00KGu+x1X8Z+rLP3+QsjPNG1gQggL4+C/1E2DUBc7xgQjB3ad1\\n\" +\n                \"l08YuW3e95ORCLp+QCztweq7dp4zBncdDQh/U90bZKuCJ/Fp1U1ervShw3WnWEQt\\n\" +\n                \"8jxwmKy6abaVd38PMV4s/KCHOkdp8Hlf9BRUpJVeEXgSYCfOn8J3/yNTd126/+pZ\\n\" +\n                \"59vPr5KW7ySaNRB6nJHGDn2Z9j8Z3/VyVOEVqQdZe4O/Ui5GjLIAZHYcSNPYeehu\\n\" +\n                \"VsyuLAOQ1xk4meTKCRlb/weWsKh/NEnfVqn3sF/tM+2MR7cwA130A4w=\\n\" +\n                \"-----END CERTIFICATE-----\\n\";\n\n        String serverAddress = \"nabil-test.ie1.realmlab.net\";\n\n        assertTrue(Sync.sslVerifyCallback(serverAddress, pem_depth3, 3));\n        assertTrue(Sync.sslVerifyCallback(serverAddress, pem_depth2, 2));\n        assertTrue(Sync.sslVerifyCallback(serverAddress, pem_depth1, 1));\n        assertFalse(Sync.sslVerifyCallback(serverAddress, pem_depth0, 0));\n    }\n\n    @Ignore(\"FIXME: Certificate expired\")\n    @Test\n    public void sslVerifyCallback_shouldVerifyHostname() {\n        // simulating the following certificate chain\n\n        // 0 s:/CN=us1a.cloud.realm.io\n        //   i:/C=US/O=Amazon/OU=Server CA 1B/CN=Amazon\n        String pem_depth0 = \"-----BEGIN CERTIFICATE-----\\n\" +\n                \"MIIEfjCCA2agAwIBAgIQAuZyKHDOzYP160MtNtRBEjANBgkqhkiG9w0BAQsFADBG\\n\" +\n                \"MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRUwEwYDVQQLEwxTZXJ2ZXIg\\n\" +\n                \"Q0EgMUIxDzANBgNVBAMTBkFtYXpvbjAeFw0xODAyMTkwMDAwMDBaFw0xOTAzMTkx\\n\" +\n                \"MjAwMDBaMB4xHDAaBgNVBAMTE3VzMWEuY2xvdWQucmVhbG0uaW8wggEiMA0GCSqG\\n\" +\n                \"SIb3DQEBAQUAA4IBDwAwggEKAoIBAQC6XER+3bFiK4TCc5lQv/O3xTc9oC/bcPVr\\n\" +\n                \"zs52mzcGW/wNH6dxW3i3T3gz3Pit8TDkDf0tzoZNdfr7PYs+BPtinM3ZbKSSnF6G\\n\" +\n                \"5F8HNpe/1p1blko22wJDa9OyZD4tZ3f6hBlUU+8tHFC2B7BGEzuVKf3Aacap0wdh\\n\" +\n                \"KsAAaF/mbtLQaelRFtHcIOz2B28e7Fub/iwJGCW79Keq+lDRLG+xayEsBqO3+FJ3\\n\" +\n                \"h4FxbhsKW/O5tb/5B4dZfgJopWZfcmTUZ89ZX2IYaukfwkrV+/09ZAr87jMi9E7+\\n\" +\n                \"zU37qHtrWVWQV48BxdWiMmmvJb0ytYM0rxal2YuXi6NOBTP0sbxVAgMBAAGjggGO\\n\" +\n                \"MIIBijAfBgNVHSMEGDAWgBRZpGYGUqB7lZI8o5QHJ5Z0W/k90DAdBgNVHQ4EFgQU\\n\" +\n                \"ZNEE3UPcZg2ZOJd4eMZryxUTvKswNQYDVR0RBC4wLIITdXMxYS5jbG91ZC5yZWFs\\n\" +\n                \"bS5pb4IVKi51czFhLmNsb3VkLnJlYWxtLmlvMA4GA1UdDwEB/wQEAwIFoDAdBgNV\\n\" +\n                \"HSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwOwYDVR0fBDQwMjAwoC6gLIYqaHR0\\n\" +\n                \"cDovL2NybC5zY2ExYi5hbWF6b250cnVzdC5jb20vc2NhMWIuY3JsMCAGA1UdIAQZ\\n\" +\n                \"MBcwCwYJYIZIAYb9bAECMAgGBmeBDAECATB1BggrBgEFBQcBAQRpMGcwLQYIKwYB\\n\" +\n                \"BQUHMAGGIWh0dHA6Ly9vY3NwLnNjYTFiLmFtYXpvbnRydXN0LmNvbTA2BggrBgEF\\n\" +\n                \"BQcwAoYqaHR0cDovL2NydC5zY2ExYi5hbWF6b250cnVzdC5jb20vc2NhMWIuY3J0\\n\" +\n                \"MAwGA1UdEwEB/wQCMAAwDQYJKoZIhvcNAQELBQADggEBAAserhwXWohdFjImCcCh\\n\" +\n                \"0XGW7s47vygasV4kE7vg59dz5RQrVuu+U0HFKTuPw6d4xSaQrUq1wo76RJtZalpG\\n\" +\n                \"ek9vOvS0GWxjSsts2D0oWZXq772bhlXRfj21NsgwzfWMXIrUaV32l5qDhin1wx7x\\n\" +\n                \"oZL7mNQ75qFB56jv5zzsX2woFv1GN0a03nFgy9Jk6aWCM5Q3oujrxJJWsgXIMloj\\n\" +\n                \"uqg+I4MfhTEC1ZnGOEoO4Rq3i1rSLa59mv4lhcO/+yrEENKESgx8/8DnIjQoEuRp\\n\" +\n                \"QtbxCVxPYfnjBuRuvyTfSo1GMK6SuhvkqVbDhBbRDDCh2T8Nmea3BcFi1kcpImOr\\n\" +\n                \"MI4=\\n\" +\n                \"-----END CERTIFICATE-----\";\n\n        //  1 s:/C=US/O=Amazon/OU=Server CA 1B/CN=Amazon\n        //  i:/C=US/O=Amazon/CN=Amazon Root CA 1\n        String pem_depth1 = \"-----BEGIN CERTIFICATE-----\\n\" +\n                \"MIIESTCCAzGgAwIBAgITBn+UV4WH6Kx33rJTMlu8mYtWDTANBgkqhkiG9w0BAQsF\\n\" +\n                \"ADA5MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6\\n\" +\n                \"b24gUm9vdCBDQSAxMB4XDTE1MTAyMjAwMDAwMFoXDTI1MTAxOTAwMDAwMFowRjEL\\n\" +\n                \"MAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEVMBMGA1UECxMMU2VydmVyIENB\\n\" +\n                \"IDFCMQ8wDQYDVQQDEwZBbWF6b24wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK\\n\" +\n                \"AoIBAQDCThZn3c68asg3Wuw6MLAd5tES6BIoSMzoKcG5blPVo+sDORrMd4f2AbnZ\\n\" +\n                \"cMzPa43j4wNxhplty6aUKk4T1qe9BOwKFjwK6zmxxLVYo7bHViXsPlJ6qOMpFge5\\n\" +\n                \"blDP+18x+B26A0piiQOuPkfyDyeR4xQghfj66Yo19V+emU3nazfvpFA+ROz6WoVm\\n\" +\n                \"B5x+F2pV8xeKNR7u6azDdU5YVX1TawprmxRC1+WsAYmz6qP+z8ArDITC2FMVy2fw\\n\" +\n                \"0IjKOtEXc/VfmtTFch5+AfGYMGMqqvJ6LcXiAhqG5TI+Dr0RtM88k+8XUBCeQ8IG\\n\" +\n                \"KuANaL7TiItKZYxK1MMuTJtV9IblAgMBAAGjggE7MIIBNzASBgNVHRMBAf8ECDAG\\n\" +\n                \"AQH/AgEAMA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUWaRmBlKge5WSPKOUByeW\\n\" +\n                \"dFv5PdAwHwYDVR0jBBgwFoAUhBjMhTTsvAyUlC4IWZzHshBOCggwewYIKwYBBQUH\\n\" +\n                \"AQEEbzBtMC8GCCsGAQUFBzABhiNodHRwOi8vb2NzcC5yb290Y2ExLmFtYXpvbnRy\\n\" +\n                \"dXN0LmNvbTA6BggrBgEFBQcwAoYuaHR0cDovL2NydC5yb290Y2ExLmFtYXpvbnRy\\n\" +\n                \"dXN0LmNvbS9yb290Y2ExLmNlcjA/BgNVHR8EODA2MDSgMqAwhi5odHRwOi8vY3Js\\n\" +\n                \"LnJvb3RjYTEuYW1hem9udHJ1c3QuY29tL3Jvb3RjYTEuY3JsMBMGA1UdIAQMMAow\\n\" +\n                \"CAYGZ4EMAQIBMA0GCSqGSIb3DQEBCwUAA4IBAQCFkr41u3nPo4FCHOTjY3NTOVI1\\n\" +\n                \"59Gt/a6ZiqyJEi+752+a1U5y6iAwYfmXss2lJwJFqMp2PphKg5625kXg8kP2CN5t\\n\" +\n                \"6G7bMQcT8C8xDZNtYTd7WPD8UZiRKAJPBXa30/AbwuZe0GaFEQ8ugcYQgSn+IGBI\\n\" +\n                \"8/LwhBNTZTUVEWuCUUBVV18YtbAiPq3yXqMB48Oz+ctBWuZSkbvkNodPLamkB2g1\\n\" +\n                \"upRyzQ7qDn1X8nn8N8V7YJ6y68AtkHcNSRAnpTitxBKjtKPISLMVCx7i4hncxHZS\\n\" +\n                \"yLyKQXhw2W2Xs0qLeC1etA+jTGDK4UfLeC0SF7FSi8o5LL21L8IzApar2pR/\\n\" +\n                \"-----END CERTIFICATE-----\";\n\n        //  2 s:/C=US/O=Amazon/CN=Amazon Root CA 1\n        //   i:/C=US/ST=Arizona/L=Scottsdale/O=Starfield Technologies, Inc./CN=Starfield Services Root Certificate Authority - G2\n        String pem_depth2 = \"-----BEGIN CERTIFICATE-----\\n\" +\n                \"MIIEkjCCA3qgAwIBAgITBn+USionzfP6wq4rAfkI7rnExjANBgkqhkiG9w0BAQsF\\n\" +\n                \"ADCBmDELMAkGA1UEBhMCVVMxEDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNj\\n\" +\n                \"b3R0c2RhbGUxJTAjBgNVBAoTHFN0YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4x\\n\" +\n                \"OzA5BgNVBAMTMlN0YXJmaWVsZCBTZXJ2aWNlcyBSb290IENlcnRpZmljYXRlIEF1\\n\" +\n                \"dGhvcml0eSAtIEcyMB4XDTE1MDUyNTEyMDAwMFoXDTM3MTIzMTAxMDAwMFowOTEL\\n\" +\n                \"MAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJv\\n\" +\n                \"b3QgQ0EgMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALJ4gHHKeNXj\\n\" +\n                \"ca9HgFB0fW7Y14h29Jlo91ghYPl0hAEvrAIthtOgQ3pOsqTQNroBvo3bSMgHFzZM\\n\" +\n                \"9O6II8c+6zf1tRn4SWiw3te5djgdYZ6k/oI2peVKVuRF4fn9tBb6dNqcmzU5L/qw\\n\" +\n                \"IFAGbHrQgLKm+a/sRxmPUDgH3KKHOVj4utWp+UhnMJbulHheb4mjUcAwhmahRWa6\\n\" +\n                \"VOujw5H5SNz/0egwLX0tdHA114gk957EWW67c4cX8jJGKLhD+rcdqsq08p8kDi1L\\n\" +\n                \"93FcXmn/6pUCyziKrlA4b9v7LWIbxcceVOF34GfID5yHI9Y/QCB/IIDEgEw+OyQm\\n\" +\n                \"jgSubJrIqg0CAwEAAaOCATEwggEtMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/\\n\" +\n                \"BAQDAgGGMB0GA1UdDgQWBBSEGMyFNOy8DJSULghZnMeyEE4KCDAfBgNVHSMEGDAW\\n\" +\n                \"gBScXwDfqgHXMCs4iKK4bUqc8hGRgzB4BggrBgEFBQcBAQRsMGowLgYIKwYBBQUH\\n\" +\n                \"MAGGImh0dHA6Ly9vY3NwLnJvb3RnMi5hbWF6b250cnVzdC5jb20wOAYIKwYBBQUH\\n\" +\n                \"MAKGLGh0dHA6Ly9jcnQucm9vdGcyLmFtYXpvbnRydXN0LmNvbS9yb290ZzIuY2Vy\\n\" +\n                \"MD0GA1UdHwQ2MDQwMqAwoC6GLGh0dHA6Ly9jcmwucm9vdGcyLmFtYXpvbnRydXN0\\n\" +\n                \"LmNvbS9yb290ZzIuY3JsMBEGA1UdIAQKMAgwBgYEVR0gADANBgkqhkiG9w0BAQsF\\n\" +\n                \"AAOCAQEAYjdCXLwQtT6LLOkMm2xF4gcAevnFWAu5CIw+7bMlPLVvUOTNNWqnkzSW\\n\" +\n                \"MiGpSESrnO09tKpzbeR/FoCJbM8oAxiDR3mjEH4wW6w7sGDgd9QIpuEdfF7Au/ma\\n\" +\n                \"eyKdpwAJfqxGF4PcnCZXmTA5YpaP7dreqsXMGz7KQ2hsVxa81Q4gLv7/wmpdLqBK\\n\" +\n                \"bRRYh5TmOTFffHPLkIhqhBGWJ6bt2YFGpn6jcgAKUj6DiAdjd4lpFw85hdKrCEVN\\n\" +\n                \"0FE6/V1dN2RMfjCyVSRCnTawXZwXgWHxyvkQAiSr6w10kY17RSlQOYiypok1JR4U\\n\" +\n                \"akcjMS9cmvqtmg5iUaQqqcT5NJ0hGA==\\n\" +\n                \"-----END CERTIFICATE-----\";\n\n        //  3 s:/C=US/ST=Arizona/L=Scottsdale/O=Starfield Technologies, Inc./CN=Starfield Services Root Certificate Authority - G2\n        //   i:/C=US/O=Starfield Technologies, Inc./OU=Starfield Class 2 Certification Authority\n        String pem_depth3 = \"-----BEGIN CERTIFICATE-----\\n\" +\n                \"MIIEdTCCA12gAwIBAgIJAKcOSkw0grd/MA0GCSqGSIb3DQEBCwUAMGgxCzAJBgNV\\n\" +\n                \"BAYTAlVTMSUwIwYDVQQKExxTdGFyZmllbGQgVGVjaG5vbG9naWVzLCBJbmMuMTIw\\n\" +\n                \"MAYDVQQLEylTdGFyZmllbGQgQ2xhc3MgMiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0\\n\" +\n                \"eTAeFw0wOTA5MDIwMDAwMDBaFw0zNDA2MjgxNzM5MTZaMIGYMQswCQYDVQQGEwJV\\n\" +\n                \"UzEQMA4GA1UECBMHQXJpem9uYTETMBEGA1UEBxMKU2NvdHRzZGFsZTElMCMGA1UE\\n\" +\n                \"ChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjE7MDkGA1UEAxMyU3RhcmZp\\n\" +\n                \"ZWxkIFNlcnZpY2VzIFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IC0gRzIwggEi\\n\" +\n                \"MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDVDDrEKvlO4vW+GZdfjohTsR8/\\n\" +\n                \"y8+fIBNtKTrID30892t2OGPZNmCom15cAICyL1l/9of5JUOG52kbUpqQ4XHj2C0N\\n\" +\n                \"Tm/2yEnZtvMaVq4rtnQU68/7JuMauh2WLmo7WJSJR1b/JaCTcFOD2oR0FMNnngRo\\n\" +\n                \"Ot+OQFodSk7PQ5E751bWAHDLUu57fa4657wx+UX2wmDPE1kCK4DMNEffud6QZW0C\\n\" +\n                \"zyyRpqbn3oUYSXxmTqM6bam17jQuug0DuDPfR+uxa40l2ZvOgdFFRjKWcIfeAg5J\\n\" +\n                \"Q4W2bHO7ZOphQazJ1FTfhy/HIrImzJ9ZVGif/L4qL8RVHHVAYBeFAlU5i38FAgMB\\n\" +\n                \"AAGjgfAwge0wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0O\\n\" +\n                \"BBYEFJxfAN+qAdcwKziIorhtSpzyEZGDMB8GA1UdIwQYMBaAFL9ft9HO3R+G9FtV\\n\" +\n                \"rNzXEMIOqYjnME8GCCsGAQUFBwEBBEMwQTAcBggrBgEFBQcwAYYQaHR0cDovL28u\\n\" +\n                \"c3MyLnVzLzAhBggrBgEFBQcwAoYVaHR0cDovL3guc3MyLnVzL3guY2VyMCYGA1Ud\\n\" +\n                \"HwQfMB0wG6AZoBeGFWh0dHA6Ly9zLnNzMi51cy9yLmNybDARBgNVHSAECjAIMAYG\\n\" +\n                \"BFUdIAAwDQYJKoZIhvcNAQELBQADggEBACMd44pXyn3pF3lM8R5V/cxTbj5HD9/G\\n\" +\n                \"VfKyBDbtgB9TxF00KGu+x1X8Z+rLP3+QsjPNG1gQggL4+C/1E2DUBc7xgQjB3ad1\\n\" +\n                \"l08YuW3e95ORCLp+QCztweq7dp4zBncdDQh/U90bZKuCJ/Fp1U1ervShw3WnWEQt\\n\" +\n                \"8jxwmKy6abaVd38PMV4s/KCHOkdp8Hlf9BRUpJVeEXgSYCfOn8J3/yNTd126/+pZ\\n\" +\n                \"59vPr5KW7ySaNRB6nJHGDn2Z9j8Z3/VyVOEVqQdZe4O/Ui5GjLIAZHYcSNPYeehu\\n\" +\n                \"VsyuLAOQ1xk4meTKCRlb/weWsKh/NEnfVqn3sF/tM+2MR7cwA130A4w=\\n\" +\n                \"-----END CERTIFICATE-----\";\n\n        String serverAddress = \"foo.us1a.cloud.realm.io\";\n\n        assertTrue(Sync.sslVerifyCallback(serverAddress, pem_depth3, 3));\n        assertTrue(Sync.sslVerifyCallback(serverAddress, pem_depth2, 2));\n        assertTrue(Sync.sslVerifyCallback(serverAddress, pem_depth1, 1));\n        assertTrue(Sync.sslVerifyCallback(serverAddress, pem_depth0, 0));\n\n        // reaching depth0 will validate (or not) the entire chain, then removing the PEMs from memory\n        // make sure the hostname verify works\n\n        String wrongServerAddress = \"hax0r-us1a.cloud2.realm.io\";\n        assertTrue(Sync.sslVerifyCallback(wrongServerAddress, pem_depth3, 3));\n        assertTrue(Sync.sslVerifyCallback(wrongServerAddress, pem_depth2, 2));\n        assertTrue(Sync.sslVerifyCallback(wrongServerAddress, pem_depth1, 1));\n        // the method fails because of the hostname verification\n        assertFalse(Sync.sslVerifyCallback(wrongServerAddress, pem_depth0, 0));\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTestObjectServer/kotlin/io/realm/transport/HttpNetworkTransportInterceptor.kt",
    "content": "/*\n * Copyright 2021 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 */\npackage io.realm.transport\n\nimport io.realm.internal.network.OkHttpNetworkTransport\nimport io.realm.internal.objectstore.OsJavaNetworkTransport\nimport io.realm.mongodb.log.obfuscator.HttpLogObfuscator\n\n/**\n * This class intercepts the response of an HTTP request instead of passing it on to ObjectStore.\n * This enables us to query it later.\n */\n\ntypealias Observer = (response: OsJavaNetworkTransport.Response) -> Unit\n\nclass HttpNetworkTransportInterceptor(private val passOnToObjectStore: Boolean = false,\n                                      obfuscator: HttpLogObfuscator?) : OkHttpNetworkTransport(obfuscator) {\n\n    private var observer: Observer? = null\n    var preExecuteAction : (() -> Unit)? = null\n\n    override fun handleResponse(\n        response: OsJavaNetworkTransport.Response,\n        completionBlockPtr: Long\n    ) {\n        observer?.let {\n            it(response)\n        }\n        if (passOnToObjectStore) {\n            super.handleResponse(response, completionBlockPtr)\n        }\n    }\n\n    override fun executeRequest(\n        method: String,\n        url: String,\n        timeoutMs: Long,\n        headers: MutableMap<String, String>,\n        body: String\n    ): OsJavaNetworkTransport.Response {\n        preExecuteAction?.let { it() }\n        return super.executeRequest(method, url, timeoutMs, headers, body)\n    }\n    \n    fun observeResponses(callback: (response: OsJavaNetworkTransport.Response) -> Unit) {\n        observer = callback\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTestObjectServer/kotlin/io/realm/transport/OkHttpNetworkTransportTests.kt",
    "content": "/*\n * Copyright 2020 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 */\npackage io.realm.transport\n\nimport androidx.test.ext.junit.runners.AndroidJUnit4\nimport androidx.test.platform.app.InstrumentationRegistry\nimport io.realm.Realm\nimport io.realm.TestHelper\nimport io.realm.internal.objectstore.OsJavaNetworkTransport\nimport org.junit.Assert.assertEquals\nimport org.junit.Assert.assertTrue\nimport org.junit.Before\nimport org.junit.Ignore\nimport org.junit.Test\nimport org.junit.runner.RunWith\nimport java.util.concurrent.CountDownLatch\n\n/**\n * This class is responsible for testing the OkHttp implementation of the network layer.\n * Any behavior happening after the network request has executed are not covered by this class,\n * but instead in [OsJavaNetworkTransportTests].\n *\n * This class uses a simple custom webserver written in Node that must be running when\n * executing these tests.\n */\n@RunWith(AndroidJUnit4::class)\nclass OkHttpNetworkTransportTests {\n\n    private lateinit var transport: HttpNetworkTransportInterceptor\n    private val baseUrl = \"http://127.0.0.1:8888\" // URL to command server\n\n    enum class HTTPMethod(val nativeKey: String) {\n        GET(\"get\"), POST(\"post\"), PATCH(\"patch\"), PUT(\"put\"), DELETE(\"delete\");\n    }\n\n    @Before\n    fun setUp() {\n        Realm.init(InstrumentationRegistry.getInstrumentation().targetContext)\n        transport = HttpNetworkTransportInterceptor(false, null)\n    }\n\n    @Test\n    fun requestSuccessful() {\n        val url = \"$baseUrl/okhttp?success=true\"\n        for (method in HTTPMethod.values()) {\n            val body = if (method == HTTPMethod.GET) \"\" else \"{ \\\"body\\\" : \\\"some content\\\" }\"\n            val headers = mapOf(\n                    Pair(\"Content-Type\", \"application/json;charset=utf-8\"),\n                    Pair(\"Accept\", \"application/json\")\n            )\n            val fakeCompletionPtr = 0L\n\n            val latch = CountDownLatch(1)\n            transport.observeResponses { response: OsJavaNetworkTransport.Response ->\n                assertEquals(200, response.httpResponseCode)\n                assertEquals(0, response.customResponseCode)\n                assertEquals(\"${method.name}-success\", response.body)\n                latch.countDown()\n            }\n\n            transport.sendRequestAsync(method.nativeKey,\n                    url,\n                    5000,\n                    headers,\n                    body,\n                    fakeCompletionPtr\n            )\n            TestHelper.awaitOrFail(latch)\n        }\n    }\n\n    @Test\n    fun requestFailedOnServer() {\n        val url = \"$baseUrl/okhttp?success=false\"\n        for (method in HTTPMethod.values()) {\n            val body = if (method == HTTPMethod.GET) \"\" else \"{ \\\"body\\\" : \\\"some content\\\" }\"\n            val headers = mapOf(\n                    Pair(\"Content-Type\", \"application/json;charset=utf-8\"),\n                    Pair(\"Accept\", \"application/json\")\n            )\n            val fakeCompletionPtr = 0L\n\n            val latch = CountDownLatch(1)\n            transport.observeResponses { response: OsJavaNetworkTransport.Response ->\n                assertEquals(500, response.httpResponseCode)\n                assertEquals(0, response.customResponseCode)\n                assertEquals(\"${method.name}-failure\", response.body)\n                latch.countDown()\n            }\n\n            transport.sendRequestAsync(method.nativeKey,\n                    url,\n                    5000,\n                    headers,\n                    body,\n                    fakeCompletionPtr)\n            TestHelper.awaitOrFail(latch)\n        }\n    }\n\n    // Make sure that the client doesn't crash if attempting to send invalid JSON\n    // This is mostly a guard against Java crashing if ObjectStore serializes the wrong\n    // way by accident.\n    @Test\n    fun requestSendsIllegalJson() {\n        val url = \"$baseUrl/okhttp?success=true\"\n        for (method in HTTPMethod.values()) {\n            val body = if (method == HTTPMethod.GET) \"\" else \"Boom!\"\n            val headers = mapOf(\n                    Pair(\"Content-Type\", \"application/json;charset=utf-8\"),\n                    Pair(\"Accept\", \"application/json\")\n            )\n            val fakeCompletionPtr = 0L\n\n            val latch = CountDownLatch(1)\n            transport.observeResponses { response: OsJavaNetworkTransport.Response ->\n                assertEquals(200, response.httpResponseCode)\n                assertEquals(0, response.customResponseCode)\n                assertEquals(\"${method.name}-success\", response.body)\n                latch.countDown()\n            }\n\n            transport.sendRequestAsync(method.nativeKey,\n                    url,\n                    5000,\n                    headers,\n                    body,\n                    fakeCompletionPtr)\n            TestHelper.awaitOrFail(latch)\n        }\n    }\n\n\n    // Validate that we can access a text/event-stream streamed response\n    @Test\n    fun streamRequest() {\n        val url = \"$baseUrl/watcher\"\n\n        val headers = mapOf(\n                Pair(\"Accept\", \"text/event-stream\")\n        )\n\n        val request = OsJavaNetworkTransport.Request(\"get\", url, headers, \"\")\n        val response = transport.sendStreamingRequest(request)\n\n        assertEquals(200, response.httpResponseCode)\n        assertEquals(0, response.customResponseCode)\n        assertEquals(\"hello world 1\", response.readBodyLine())\n        assertEquals(\"hello world 2\", response.readBodyLine())\n\n        response.close()\n    }\n\n\n    @Test\n    fun requestInterrupted() {\n        val url = \"$baseUrl/okhttp?success=true\"\n        for (method in HTTPMethod.values()) {\n            val body = if (method == HTTPMethod.GET) \"\" else \"{ \\\"body\\\" : \\\"some content\\\" }\"\n            val headers = mapOf(\n                    Pair(\"Content-Type\", \"application/json;charset=utf-8\"),\n                    Pair(\"Accept\", \"application/json\")\n            )\n            val fakeCompletionPtr = 0L\n\n            val latch = CountDownLatch(1)\n\n            transport.observeResponses { response ->\n                assertEquals(0, response.httpResponseCode)\n                assertEquals(OsJavaNetworkTransport.ERROR_IO, response.customResponseCode)\n                assertTrue(response.body.contains(\"interrupted\"))\n                latch.countDown()\n            }\n\n            transport.preExecuteAction = {\n                Thread.currentThread().interrupt()\n            }\n\n            transport.sendRequestAsync(method.nativeKey,\n                    url,\n                    5000,\n                    headers,\n                    body,\n                    fakeCompletionPtr)\n\n            TestHelper.awaitOrFail(latch)\n        }\n    }\n\n    @Ignore(\"Add test for this\")\n    @Test\n    fun customAuthorizationHeader() {\n        TODO(\"FIXME\")\n    }\n\n    @Ignore(\"Add test for this\")\n    @Test\n    fun customHeaders() {\n        TODO(\"FIXME\")\n    }\n    \n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTestObjectServer/kotlin/io/realm/transport/OsJavaNetworkTransportTests.kt",
    "content": "/*\n * Copyright 2020 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 */\npackage io.realm.transport\n\nimport androidx.test.ext.junit.runners.AndroidJUnit4\nimport androidx.test.platform.app.InstrumentationRegistry\nimport io.realm.*\nimport io.realm.internal.network.OkHttpNetworkTransport\nimport io.realm.internal.objectstore.OsJavaNetworkTransport\nimport io.realm.log.RealmLog\nimport io.realm.mongodb.*\nimport org.junit.After\nimport org.junit.Assert.*\nimport org.junit.Before\nimport org.junit.Test\nimport org.junit.runner.RunWith\n\n/**\n * This class is responsible for testing the general network transport layer, i.e. that\n * requests can round trip correctly through all layers and that exceptions/errors are reported\n * correctly.\n *\n * This class should _NOT_ test any real network logic. See [OkHttpNetworkTransportTests] for\n * tests using the actual network implementation.\n */\n@RunWith(AndroidJUnit4::class)\nclass OsJavaNetworkTransportTests {\n\n    private lateinit var app: App\n    private val successHeaders: Map<String, String> = mapOf(Pair(\"Content-Type\", \"application/json\"))\n\n    @Before\n    fun setUp() {\n        Realm.init(InstrumentationRegistry.getInstrumentation().targetContext)\n    }\n\n    @After\n    fun tearDown() {\n        if (this::app.isInitialized) {\n            app.close()\n        }\n    }\n\n    // Test that the round trip works in case of a successful HTTP request.\n    @Test\n    fun requestSuccess() {\n        app = TestApp(object: OsJavaNetworkTransport() {\n            override fun sendRequestAsync(method: String,\n                                     url: String,\n                                     timeoutMs: Long,\n                                     headers: MutableMap<String, String>,\n                                     body: String,\n                                     completionPtr: Long) {\n                val response = executeRequest(method, url, timeoutMs, headers, body)\n                handleResponse(response, completionPtr)\n            }\n\n            override fun executeRequest(\n                method: String,\n                url: String,\n                timeoutMs: Long,\n                headers: MutableMap<String, String>,\n                body: String\n            ): Response {\n                var result = \"\"\n                when {\n                    url.endsWith(\"/providers/${Credentials.Provider.ANONYMOUS.id}/login\") -> {\n                        result = \"\"\"\n                                    {\n                                        \"access_token\": \"eyJhbGciOiJSUzI1NiIsImtpZCI6IjVlNjk2M2RmYWZlYTYzMjU0NTgxYzAyNiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1ODM5NjcyMDgsImlhdCI6MTU4Mzk2NTQwOCwiaXNzIjoiNWU2OTY0ZTBhZmVhNjMyNTQ1ODFjMWEzIiwic3RpdGNoX2RldklkIjoiMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwIiwic3RpdGNoX2RvbWFpbklkIjoiNWU2OTYzZGVhZmVhNjMyNTQ1ODFjMDI1Iiwic3ViIjoiNWU2OTY0ZTBhZmVhNjMyNTQ1ODFjMWExIiwidHlwIjoiYWNjZXNzIn0.J4mp8LnlsxTQRV_7W2Er4qY0tptR76PJGG1k6HSMmUYqgfpJC2Fnbcf1VCoebzoNolH2-sr8AHDVBBCyjxRjqoY9OudFHmWZKmhDV1ysxPP4XmID0nUuN45qJSO8QEAqoOmP1crXjrUZWedFw8aaCZE-bxYfvcDHyjBcbNKZqzawwUw2PyTOlrNjgs01k2J4o5a5XzYkEsJuzr4_8UqKW6zXvYj24UtqnqoYatW5EzpX63m2qig8AcBwPK4ZHb5wEEUdf4QZxkRY5QmTgRHP8SSqVUB_mkHgKaizC_tSB3E0BekaDfLyWVC1taAstXJNfzgFtLI86AzuXS2dCiCfqQ\",\n                                        \"refresh_token\": \"eyJhbGciOiJSUzI1NiIsImtpZCI6IjVlNjk2M2RmYWZlYTYzMjU0NTgxYzAyNiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1ODkxNDk0MDgsImlhdCI6MTU4Mzk2NTQwOCwic3RpdGNoX2RhdGEiOm51bGwsInN0aXRjaF9kZXZJZCI6IjAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMCIsInN0aXRjaF9kb21haW5JZCI6IjVlNjk2M2RlYWZlYTYzMjU0NTgxYzAyNSIsInN0aXRjaF9pZCI6IjVlNjk2NGUwYWZlYTYzMjU0NTgxYzFhMyIsInN0aXRjaF9pZGVudCI6eyJpZCI6IjVlNjk2NGUwYWZlYTYzMjU0NTgxYzFhMC1oaWF2b3ZkbmJxbGNsYXBwYnl1cmJpaW8iLCJwcm92aWRlcl90eXBlIjoiYW5vbi11c2VyIiwicHJvdmlkZXJfaWQiOiI1ZTY5NjNlMGFmZWE2MzI1NDU4MWMwNGEifSwic3ViIjoiNWU2OTY0ZTBhZmVhNjMyNTQ1ODFjMWExIiwidHlwIjoicmVmcmVzaCJ9.FhLdpmL48Mw0SyUKWuaplz3wfeS8TCO8S7I9pIJenQww9nPqQ7lIvykQxjCCtinGvsZIJKt_7R31xYCq4Jp53Nw81By79IwkXtO7VXHPsXXZG5_2xV-s0u44e85sYD5su_H-xnx03sU2piJbWJLSB8dKu3rMD4mO-S0HNXCCAty-JkYKSaM2-d_nS8MNb6k7Vfm7y69iz_uwHc-bb_1rPg7r827K6DEeEMF41Hy3Nx1kCdAUOM9-6nYv3pZSU1PFrGYi2uyTXPJ7R7HigY5IGHWd0hwONb_NUr4An2omqfvlkLEd77ut4V9m6mExFkoKzRz7shzn-IGkh3e4h7ECGA\",\n                                        \"user_id\": \"5e6964e0afea63254581c1a1\",\n                                        \"device_id\": \"000000000000000000000000\"\n                                    }                    \n                                \"\"\".trimIndent()\n                    }\n                    url.endsWith(\"/auth/profile\") -> {\n                        result = \"\"\"\n                                    {\n                                        \"user_id\": \"5e6964e0afea63254581c1a1\",\n                                        \"domain_id\": \"000000000000000000000000\",\n                                        \"identities\": [\n                                            {\n                                                \"id\": \"5e68f51ade5ba998bb17500d\",\n                                                \"provider_type\": \"local-userpass\",\n                                                \"provider_id\": \"000000000000000000000003\",\n                                                \"provider_data\": {\n                                                    \"email\": \"unique_user@domain.com\"\n                                                }\n                                            }\n                                        ],\n                                        \"data\": {\n                                            \"email\": \"unique_user@domain.com\"\n                                        },\n                                        \"type\": \"normal\",\n                                        \"roles\": [\n                                            {\n                                                \"role_name\": \"GROUP_OWNER\",\n                                                \"group_id\": \"5e68f51e087b1b33a53f56d5\"\n                                            }\n                                        ]\n                                    }\n                                \"\"\".trimIndent()\n                    }\n                    url.endsWith(\"/location\") -> {\n                        result = \"\"\"\n                                    { \"deployment_model\" : \"GLOBAL\",\n                                      \"location\": \"US-VA\", \n                                      \"hostname\": \"http://localhost:9090\",\n                                      \"ws_hostname\": \"ws://localhost:9090\"\n                                    }\n                                    \"\"\".trimIndent()\n                    }\n                    else -> {\n                        fail(\"Unexpected request url: $url\")\n                    }\n                }\n                return OkHttpNetworkTransport.Response.httpResponse(200, successHeaders, result)\n            }\n\n            override fun sendStreamingRequest(request: Request): Response {\n                throw IllegalAccessError()\n            }\n        })\n\n        val creds = Credentials.anonymous()\n        val user: User = app.login(creds)\n        assertNotNull(user)\n    }\n\n    // Test that the server accepting the result but returns an error is succesfully reported back\n    // to the user as an exception.\n    @Test\n    fun requestFailWithServerError() {\n        app = TestApp(object: OsJavaNetworkTransport() {\n            override fun sendRequestAsync(method: String,\n                                     url: String,\n                                     timeoutMs: Long,\n                                     headers: MutableMap<String, String>,\n                                     body: String,\n                                     completionPtr: Long) {\n                val response = executeRequest(method, url, timeoutMs, headers, body)\n                handleResponse(response, completionPtr)\n            }\n\n            override fun executeRequest(\n                method: String,\n                url: String,\n                timeoutMs: Long,\n                headers: MutableMap<String, String>,\n                body: String\n            ): Response {\n                val result = \"\"\"\n                    {\n                        \"error\": \"invalid username/password\",\n                        \"error_code\": \"AuthError\",\n                        \"link\": \"http://localhost:9090/some_link\"\n                    }                \n                    \"\"\".trimIndent()\n                return OkHttpNetworkTransport.Response.httpResponse(200, successHeaders, result)\n            }\n\n            override fun sendStreamingRequest(request: Request): Response {\n                throw IllegalAccessError()\n            }\n        })\n\n        val creds = Credentials.emailPassword(\"foo\", \"bar\")\n        try {\n            app.login(creds)\n            fail()\n        } catch (ex: AppException) {\n            assertEquals(ErrorCode.AUTH_ERROR, ex.errorCode)\n            assertEquals(ErrorCode.Type.SERVICE, ex.errorType)\n        }\n    }\n\n    // Test that the server failing to respond with a non-200 status code returns a proper exception\n    // to the user.\n    @Test\n    fun requestFailWithHttpError() {\n        app = TestApp(object: OsJavaNetworkTransport() {\n            override fun sendRequestAsync(method: String,\n                                     url: String,\n                                     timeoutMs: Long,\n                                     headers: MutableMap<String, String>,\n                                     body: String,\n                                     completionPtr: Long) {\n                val response = executeRequest(method, url, timeoutMs, headers, body)\n                handleResponse(response, completionPtr)\n            }\n\n            override fun executeRequest(\n                method: String,\n                url: String,\n                timeoutMs: Long,\n                headers: MutableMap<String, String>,\n                body: String\n            ): Response {\n                return OkHttpNetworkTransport.Response.httpResponse(500, mapOf(), \"Boom!\")\n            }\n\n            override fun sendStreamingRequest(request: Request): Response {\n                throw IllegalAccessError()\n            }\n        })\n\n        val creds = Credentials.anonymous()\n        try {\n            app.login(creds)\n            fail()\n        } catch (ex: AppException) {\n            assertEquals(ErrorCode.INTERNAL_SERVER_ERROR, ex.errorCode)\n            assertEquals(ErrorCode.Type.HTTP, ex.errorType)\n        }\n    }\n\n    // Test that custom error codes thrown from the Java transport are correctly reported back to the user.\n    @Test\n    fun requestFailWithCustomError() {\n        app = TestApp(object: OsJavaNetworkTransport() {\n            override fun sendRequestAsync(method: String,\n                                     url: String,\n                                     timeoutMs: Long,\n                                     headers: MutableMap<String, String>,\n                                     body: String,\n                                     completionBlockPtr: Long) {\n                val response = executeRequest(method, url, timeoutMs, headers, body)\n                handleResponse(response, completionBlockPtr)\n            }\n\n            override fun executeRequest(\n                method: String,\n                url: String,\n                timeoutMs: Long,\n                headers: MutableMap<String, String>,\n                body: String\n            ): Response {\n                return OkHttpNetworkTransport.Response.ioError(\"Boom!\")\n            }\n\n            override fun sendStreamingRequest(request: Request): Response {\n                throw IllegalAccessError()\n            }\n        })\n\n        val creds = Credentials.anonymous()\n        try {\n            app.login(creds)\n            fail()\n        } catch (ex: AppException) {\n            assertEquals(ErrorCode.NETWORK_IO_EXCEPTION, ex.errorCode)\n            assertEquals(ErrorCode.Type.JAVA, ex.errorType)\n        }\n    }\n\n\n    // Test that if the Java transport throws an uncaught exception it is correctly returned\n    // to the user.\n    @Test\n    fun requestFailWithTransportException() {\n        app = TestApp(object: OsJavaNetworkTransport() {\n            override fun sendRequestAsync(method: String,\n                                     url: String,\n                                     timeoutMs: Long,\n                                     headers: MutableMap<String, String>,\n                                     body: String,\n                                     completionBlockPtr: Long) {\n                throw IllegalStateException(\"Boom!\")\n            }\n\n            override fun executeRequest(\n                method: String,\n                url: String,\n                timeoutMs: Long,\n                headers: MutableMap<String, String>,\n                body: String\n            ): Response {\n                throw NotImplementedError(\"Should not be called\")\n            }\n\n            override fun sendStreamingRequest(request: Request): Response {\n                throw IllegalAccessError()\n            }\n        })\n\n        val creds = Credentials.anonymous()\n        try {\n            app.login(creds)\n            fail()\n        } catch (ex: IllegalStateException) {\n            assertEquals(\"Boom!\", ex.message)\n        }\n    }\n\n    // Test that if the Java transport throws a fatal error it is correctly returned to the user.\n    @Test\n    fun requestFailWithTransportError() {\n        app = TestApp(object: OsJavaNetworkTransport() {\n            override fun sendRequestAsync(method: String,\n                                     url: String,\n                                     timeoutMs: Long,\n                                     headers: MutableMap<String, String>,\n                                     body: String,\n                                     completionBlockPtr: Long) {\n                throw Error(\"Boom!\")\n            }\n\n            override fun executeRequest(\n                method: String,\n                url: String,\n                timeoutMs: Long,\n                headers: MutableMap<String, String>,\n                body: String\n            ): Response {\n                throw NotImplementedError(\"Should not be called\")\n            }\n\n            override fun sendStreamingRequest(request: Request): Response {\n                throw IllegalAccessError()\n            }\n        })\n\n        val creds = Credentials.anonymous()\n        try {\n            app.login(creds)\n            fail()\n        } catch (ex: Error) {\n            assertEquals(\"Boom!\", ex.message)\n        }\n    }\n}\n\n"
  },
  {
    "path": "realm/realm-library/src/androidTestObjectServer/kotlin/io/realm/util/KotlinTestUtils.kt",
    "content": "package io.realm.util\n\nimport android.util.ArraySet\nimport io.realm.mongodb.ErrorCode\nimport io.realm.mongodb.AppException\nimport org.hamcrest.Matcher\nimport org.hamcrest.MatcherAssert.assertThat\nimport org.junit.rules.ErrorCollector\nimport java.io.Closeable\nimport kotlin.test.assertEquals\nimport kotlin.test.assertFailsWith\nimport kotlin.test.assertNotNull\nimport kotlin.test.fail\n\n// Helper methods for improving Kotlin unit tests.\n\n/**\n * Verify that an [AppException] exception is thrown with a specific [ErrorCode]\n */\ninline fun assertFailsWithErrorCode(\n        expectedCode: ErrorCode,\n        method: () -> Unit\n): AppException {\n    return assertFailsWith(AppException::class) {\n        method()\n        fail()\n    }.also { e: AppException ->\n        assertEquals(expectedCode, e.errorCode, \"Unexpected error code\")\n        assertNotNull(e.errorMessage)\n    }\n}\n\ninline fun <reified T> ErrorCollector.assertFailsWith(block: () -> Unit) {\n    try {\n        block()\n    } catch (e: Exception) {\n        if (e !is T) {\n            addError(e)\n        }\n    }\n}\n\ninline fun <reified T> assertFailsWithMessage(matcher: Matcher<in String?>, block: () -> Unit) {\n    try {\n        block()\n        fail(\"assertFailsWithMessage completed without expected exception\")\n    } catch (e: Exception) {\n        if (e !is T) {\n            throw AssertionError(\"assertFailsWithMessage did not throw expected exception: \" + T::class.java.name)\n        }\n        assertThat(e.message, matcher)\n    }\n}\n\n/**\n * A **resource container** to keep references for objects that should later be closed.\n */\nclass ResourceContainer : Closeable {\n    val resources = ArraySet<Closeable>()\n\n    @Synchronized\n    override fun close() {\n        resources.map { it.close() }\n        resources.clear()\n    }\n\n    @Synchronized\n    fun add(resource: Closeable) {\n        resources.add(resource)\n    }\n}\n\n"
  },
  {
    "path": "realm/realm-library/src/androidTestObjectServer/kotlin/io/realm/util/KotlinTestUtilsTests.kt",
    "content": "/*\n * Copyright 2020 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\npackage io.realm.util\n\nimport androidx.test.ext.junit.runners.AndroidJUnit4\nimport org.hamcrest.CoreMatchers\nimport org.junit.Test\nimport org.junit.runner.RunWith\nimport java.lang.RuntimeException\n\n@RunWith(AndroidJUnit4::class)\nclass KotlinTestUtilsTests {\n\n    @Test\n    fun assertFailsWithMessage_noException() {\n        kotlin.test.assertFailsWith<AssertionError> {\n            assertFailsWithMessage<IllegalArgumentException>(CoreMatchers.anything()) { }\n        }\n    }\n\n    @Test\n    fun assertFailsWithMessage_wrongException() {\n        kotlin.test.assertFailsWith<AssertionError> {\n            assertFailsWithMessage<IllegalArgumentException>(CoreMatchers.anything()) {\n                throw RuntimeException()\n            }\n        }\n    }\n\n    @Test\n    fun assertFailsWithMessage_nonMatchingMessage() {\n        val message= \"Exception error messages\"\n        kotlin.test.assertFailsWith<AssertionError> {\n            assertFailsWithMessage<RuntimeException>(CoreMatchers.equalTo(\"\")) {\n                RuntimeException(\"Exception error messages\")\n            }\n        }\n    }\n\n    @Test\n    fun assertFailsWithMessage_matchingMessage() {\n        val message= \"Exception error messages\"\n        assertFailsWithMessage<RuntimeException>(CoreMatchers.equalTo(message)) {\n            throw RuntimeException(message)\n        }\n    }\n\n}\n"
  },
  {
    "path": "realm/realm-library/src/androidTestObjectServer/kotlin/io/realm/util/mongodb/CustomType.java",
    "content": "/*\n * Copyright 2020 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\npackage io.realm.util.mongodb;\n\nimport org.bson.BsonReader;\nimport org.bson.BsonString;\nimport org.bson.BsonValue;\nimport org.bson.BsonWriter;\nimport org.bson.Document;\nimport org.bson.codecs.CollectibleCodec;\nimport org.bson.codecs.DecoderContext;\nimport org.bson.codecs.DocumentCodec;\nimport org.bson.codecs.EncoderContext;\nimport org.bson.types.ObjectId;\n\nimport java.util.Objects;\n\npublic class CustomType {\n\n    private ObjectId id;\n    private final int intValue;\n\n    public CustomType(final ObjectId id, final int intValue) {\n        this.id = id;\n        this.intValue = intValue;\n    }\n\n    public ObjectId getId() {\n        return id;\n    }\n\n    void setId(final ObjectId id) {\n        this.id = id;\n    }\n\n    CustomType withNewObjectId() {\n        setId(new ObjectId());\n        return this;\n    }\n\n    public int getIntValue() {\n        return intValue;\n    }\n\n    @Override\n    public boolean equals(final Object object) {\n        if (this == object) {\n            return true;\n        }\n        if (!(object instanceof CustomType)) {\n            return false;\n        }\n        final CustomType other = (CustomType) object;\n        return id.equals(other.id) && intValue == other.intValue;\n    }\n\n    @Override\n    public int hashCode() {\n        return Objects.hash(id, intValue);\n    }\n\n    public static class Codec implements CollectibleCodec<CustomType> {\n\n        @Override\n        public CustomType generateIdIfAbsentFromDocument(final CustomType document) {\n            return documentHasId(document) ? document.withNewObjectId() : document;\n        }\n\n        @Override\n        public boolean documentHasId(final CustomType document) {\n            return document.getId() == null;\n        }\n\n        @Override\n        public BsonValue getDocumentId(final CustomType document) {\n            return new BsonString(document.getId().toHexString());\n        }\n\n        @Override\n        public CustomType decode(final BsonReader reader, final DecoderContext decoderContext) {\n            final Document document = (new DocumentCodec()).decode(reader, decoderContext);\n            return new CustomType(document.getObjectId(\"_id\"), document.getInteger(\"intValue\"));\n        }\n\n        @Override\n        public void encode(\n                final BsonWriter writer,\n                final CustomType value,\n                final EncoderContext encoderContext\n        ) {\n            final Document document = new Document();\n            if (value.getId() != null) {\n                document.put(\"_id\", value.getId());\n            }\n            document.put(\"intValue\", value.getIntValue());\n            (new DocumentCodec()).encode(writer, document, encoderContext);\n        }\n\n        @Override\n        public Class<CustomType> getEncoderClass() {\n            return CustomType.class;\n        }\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/AndroidManifest.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<manifest package=\"io.realm\" />\n"
  },
  {
    "path": "realm/realm-library/src/main/cpp/.clang-format",
    "content": "---\nLanguage:        Cpp\nAccessModifierOffset: -4\nAlignAfterOpenBracket: Align\nAlignConsecutiveAssignments: false\nAlignConsecutiveDeclarations: false\nAlignEscapedNewlinesLeft: false\nAlignOperands:   true\nAlignTrailingComments: true\nAllowAllParametersOfDeclarationOnNextLine: true\nAllowShortBlocksOnASingleLine: false\nAllowShortCaseLabelsOnASingleLine: false\nAllowShortFunctionsOnASingleLine: Empty\nAllowShortIfStatementsOnASingleLine: false\nAllowShortLoopsOnASingleLine: false\nAlwaysBreakAfterDefinitionReturnType: None\nAlwaysBreakAfterReturnType: None\nAlwaysBreakBeforeMultilineStrings: false\nAlwaysBreakTemplateDeclarations: true\nBinPackArguments: true\nBinPackParameters: true\nBraceWrapping:   \n  AfterClass:      false\n  AfterControlStatement: false\n  AfterEnum:       false\n  AfterFunction:   true\n  AfterNamespace:  false\n  AfterObjCDeclaration: false\n  AfterStruct:     false\n  AfterUnion:      false\n  BeforeCatch:     true\n  BeforeElse:      true\n  IndentBraces:    false\nBreakBeforeBinaryOperators: None\nBreakBeforeBraces: Custom\nBreakBeforeTernaryOperators: true\nBreakConstructorInitializersBeforeComma: true\nColumnLimit:     118\nCommentPragmas:  '^ IWYU pragma:'\nConstructorInitializerAllOnOneLineOrOnePerLine: false\nConstructorInitializerIndentWidth: 4\nContinuationIndentWidth: 4\nCpp11BracedListStyle: true\nDerivePointerAlignment: false\nDisableFormat:   false\nExperimentalAutoDetectBinPacking: false\nForEachMacros:   [ foreach, Q_FOREACH, BOOST_FOREACH ]\nIncludeCategories: \n  - Regex:           '^\"(llvm|llvm-c|clang|clang-c)/'\n    Priority:        2\n  - Regex:           '^(<|\"(gtest|isl|json)/)'\n    Priority:        3\n  - Regex:           '.*'\n    Priority:        1\nIndentCaseLabels: true\nIndentWidth:     4\nIndentWrappedFunctionNames: false\nKeepEmptyLinesAtTheStartOfBlocks: true\nMacroBlockBegin: ''\nMacroBlockEnd:   ''\nMaxEmptyLinesToKeep: 2\nNamespaceIndentation: None\nObjCBlockIndentWidth: 2\nObjCSpaceAfterProperty: false\nObjCSpaceBeforeProtocolList: true\nPenaltyBreakBeforeFirstCallParameter: 19\nPenaltyBreakComment: 300\nPenaltyBreakFirstLessLess: 120\nPenaltyBreakString: 1000\nPenaltyExcessCharacter: 1000000\nPenaltyReturnTypeOnItsOwnLine: 60\nPointerAlignment: Left\nReflowComments:  true\nSortIncludes:    false\nSpaceAfterCStyleCast: false\nSpaceBeforeAssignmentOperators: true\nSpaceBeforeParens: ControlStatements\nSpaceInEmptyParentheses: false\nSpacesBeforeTrailingComments: 1\nSpacesInAngles:  false\nSpacesInContainerLiterals: true\nSpacesInCStyleCastParentheses: false\nSpacesInParentheses: false\nSpacesInSquareBrackets: false\nStandard:        Cpp11\nTabWidth:        4\nUseTab:          Never\n...\n\n"
  },
  {
    "path": "realm/realm-library/src/main/cpp/CMakeLists.txt",
    "content": "###########################################################################\n#\n# Copyright 2017 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###########################################################################\ncmake_minimum_required(VERSION 3.27.7)\nproject(RealmJava)\n\n# For debugging: Enable this to output all variables defined for the project\n#get_cmake_property(_variableNames VARIABLES)\n#foreach (_variableName ${_variableNames})\n#    message(STATUS \"${_variableName}=${${_variableName}}\")\n#endforeach()\n\n# loading dependencies properties\nfile(STRINGS \"${CMAKE_SOURCE_DIR}/../../../../../dependencies.list\" DEPENDENCIES)\nforeach(LINE IN LISTS DEPENDENCIES)\n\n    string(REGEX MATCHALL \"([^=]+)\" KEY_VALUE \"${LINE}\")\n    list(LENGTH KEY_VALUE matches_count)\n    if(matches_count STREQUAL 2)\n        list(GET KEY_VALUE 0 KEY)\n        list(GET KEY_VALUE 1 VALUE)\n        set(DEP_${KEY} ${VALUE})\n    endif()\nendforeach()\n\nFUNCTION(capitalizeFirstLetter var value)\n    string(SUBSTRING ${value} 0 1 firstLetter)\n    string(TOUPPER ${firstLetter} firstLetter)\n    string(REGEX REPLACE \"^.(.*)\" \"${firstLetter}\\\\1\" value \"${value}\")\n    set(${var} \"${value}\" PARENT_SCOPE)\nENDFUNCTION(capitalizeFirstLetter)\n\n# find javah\nfind_package(Java COMPONENTS Development)\nif (NOT Java_Development_FOUND)\n    if (DEFINED ENV{JAVA_HOME} AND EXISTS \"$ENV{JAVA_HOME}/bin/javah\")\n        set(Java_JAVAH_EXECUTABLE \"$ENV{JAVA_HOME}/bin/javah\")\n    elseif (EXISTS \"/usr/bin/javah\")\n        set(Java_JAVAH_EXECUTABLE \"/usr/bin/javah\")\n    else()\n        message(FATAL_ERROR \"Cannot find javah\")\n    endif()\nendif()\ninclude (UseJava)\n\nset(CMAKE_VERBOSE_MAKEFILE ON)\n# Generate compile_commands.json\nset(CMAKE_EXPORT_COMPILE_COMMANDS ON)\n\n# Initialize common compile & link flags.\nset(REALM_LINKER_FLAGS \"\")\nset(REALM_COMMON_CXX_FLAGS \"-DREALM_PLATFORM_JAVA=1\")\n\n# Setup lcache\nif(NDK_LCACHE)\n    set(CMAKE_CXX_CREATE_SHARED_LIBRARY \"${NDK_LCACHE} ${CMAKE_CXX_CREATE_SHARED_LIBRARY}\")\nendif()\n\n# Set option flags for Core.\n# See https://github.com/realm/realm-core/blob/master/CMakeLists.txt#L174 for the full list.\nif (REALM_FLAVOR STREQUAL base)\n    set(REALM_ENABLE_SYNC OFF)\nelse()\n    set(REALM_ENABLE_SYNC ON)\nendif()\n\n# Format strings used to represent build parameters: Variant and Type\nstring(TOLOWER ${CMAKE_BUILD_TYPE} build_type_FOLDER)\nset(realmFlavorCap \"\")\nset(buildTypeCap \"\")\ncapitalizeFirstLetter(realmFlavorCap \"${REALM_FLAVOR}\")\ncapitalizeFirstLetter(buildTypeCap \"${CMAKE_BUILD_TYPE}\")\nmessage(\"Build type: ${CMAKE_BUILD_TYPE}\")\nif(CMAKE_BUILD_TYPE STREQUAL RelWithDebInfo)\n    # From NDK 23, Android uses CMake \"RelWithDebInfo\" instead of \"Release\", but we create the JNI\n    # headers from Gradle using the `debug`/`release` variant names, so rename\n    set(buildTypeCap \"Release\")\nendif()\n\n# The JNI header files are generated by the Java compile task.\nmessage(\"JNI Header directory: ${CMAKE_SOURCE_DIR}/../../../build/intermediates/javac/${REALM_FLAVOR}${buildTypeCap}/jni_include\")\nset(jni_headers_PATH ${CMAKE_SOURCE_DIR}/../../../build/intermediates/javac/${REALM_FLAVOR}${buildTypeCap}/jni_include)\n\n# Check if user defined download location\nif(NOT DEFINED ENV{REALM_CORE_DOWNLOAD_DIR})\n    set(REALM_CORE_DOWNLOAD_DIR ${CMAKE_BINARY_DIR})\nelse()\n    set(REALM_CORE_DOWNLOAD_DIR $ENV{REALM_CORE_DOWNLOAD_DIR})\nendif()\n\nif(REALM_JAVA_BUILD_CORE_FROM_SOURCE OR NOT REALM_ENABLE_SYNC)\n    message(STATUS \"Building Realm Core from source...\")\n\n    set(REALM_BUILD_LIB_ONLY ON)\n    add_subdirectory(realm-core EXCLUDE_FROM_ALL)\nelse()\n    message(STATUS \"Using prebuilt Realm Core.\")\n\n    # CMAKE_INTERPROCEDURAL_OPTIMIZATION is not compatible with binary artifacts.\n    set(CMAKE_INTERPROCEDURAL_OPTIMIZATION OFF)\n\n    execute_process(COMMAND \"${CMAKE_COMMAND}\" \"-E\" \"environment\")\n    set(core_filename \"realm-${CMAKE_BUILD_TYPE}-v${DEP_REALM_CORE}-Android-${CMAKE_ANDROID_ARCH_ABI}-devel\")\n\n    # Use cached resources if possible\n    if(NOT EXISTS \"${REALM_CORE_DOWNLOAD_DIR}/${core_filename}.tar.gz\")\n        message(STATUS \"Downloading ${core_filename}...\")\n        file(DOWNLOAD \"https://static.realm.io/downloads/core/${core_filename}.tar.gz\" \"${REALM_CORE_DOWNLOAD_DIR}/${core_filename}.tar.gz\")\n    else()\n        file(TIMESTAMP \"${REALM_CORE_DOWNLOAD_DIR}/${core_filename}.tar.gz\" CORE_FILE_TIMESTAMP \"%b %d %H:%M\")\n        message(STATUS \"Using cached filename: ${core_filename}.tar.gz : ${CORE_FILE_TIMESTAMP}\")\n    endif()\n\n    message(STATUS \"Uncompressing realm-core...\")\n    file(MAKE_DIRECTORY \"${CMAKE_BINARY_DIR}/${core_filename}\")\n\n    execute_process(COMMAND ${CMAKE_COMMAND} -E tar xfz \"${REALM_CORE_DOWNLOAD_DIR}/${core_filename}.tar.gz\"\n            WORKING_DIRECTORY \"${CMAKE_BINARY_DIR}/${core_filename}\")\n\n    include(${CMAKE_BINARY_DIR}/${core_filename}/lib/cmake/Realm/RealmConfig.cmake)\nendif()\n\n# build application's shared lib\ninclude_directories(\n    ${CMAKE_SOURCE_DIR}\n    ${jni_headers_PATH}\n)\n\n# Hack the memmove bug on Samsung device.\nif (ARMEABI OR ARMEABI_V7A)\n    set(REALM_LINKER_FLAGS \"${REALM_LINKER_FLAGS} -Wl,--wrap,memmove -Wl,--wrap,memcpy\")\n    set(REALM_COMMON_CXX_FLAGS \"${REALM_COMMON_CXX_FLAGS} -DREALM_WRAP_MEMMOVE=1\")\nelse()\n    set(REALM_COMMON_CXX_FLAGS \"${REALM_COMMON_CXX_FLAGS} -DREALM_WRAP_MEMMOVE=0\")\nendif()\n\n#FIXME uninitialized is reported by query_expression.hpp:1070\n#      d.init(ValueBase::m_from_link_list, ValueBase::m_values, D{});\n#FIXME maybe-uninitialized is reported by table_view.cpp:272:15:\n#     'best.m_nanoseconds' was declared here\n#     -Wno-missing-field-initializers disable in object store as well.\n# FIXME See https://github.com/realm/realm-core/issues/4732\nset(WARNING_CXX_FLAGS \"-Werror -Wall -Wextra -pedantic -Wmissing-declarations \\\n    -Wempty-body -Wparentheses -Wunknown-pragmas -Wunreachable-code \\\n    -Wno-missing-field-initializers -Wno-unevaluated-expression -Wno-unreachable-code \\\n    -Wno-c99-extensions\")\nset(REALM_COMMON_CXX_FLAGS \"${REALM_COMMON_CXX_FLAGS} -DREALM_ANDROID -DREALM_HAVE_CONFIG -DPIC -fdata-sections -pthread -frtti -fvisibility=hidden -fsigned-char -fno-stack-protector -std=c++17\")\nif (REALM_ENABLE_SYNC)\n    set(REALM_COMMON_CXX_FLAGS \"${REALM_COMMON_CXX_FLAGS} -DREALM_ENABLE_SYNC=1\")\nendif()\nset(CMAKE_CXX_FLAGS_RELEASE \"-DNDEBUG -O2\")\n# -ggdb doesn't play well with -flto\nset(CMAKE_CXX_FLAGS_DEBUG \"${CMAKE_CXX_FLAGS_DEBUG} -glldb -g\")\nset(CMAKE_CXX_FLAGS \"${CMAKE_CXX_FLAGS} ${REALM_COMMON_CXX_FLAGS} ${WARNING_CXX_FLAGS} ${ABI_CXX_FLAGS}\")\n\n# Set Linker flags flags\nif (CMAKE_BUILD_TYPE STREQUAL \"Release\")\n    set(REALM_LINKER_FLAGS \"${REALM_LINKER_FLAGS} -Wl,-gc-sections -Wl,--exclude-libs,ALL\")\nendif()\nif (REALM_ENABLE_SYNC)\n    set(REALM_LINKER_FLAGS \"${REALM_LINKER_FLAGS} -lz\")\nendif()\nset(CMAKE_SHARED_LINKER_FLAGS \"${CMAKE_SHARED_LINKER_FLAGS} ${REALM_LINKER_FLAGS}\")\n\n# JNI source files\nfile(GLOB jni_SRC\n    \"*.cpp\"\n    \"jni_util/*.cpp\"\n    \"jni_impl/android_logger.cpp\"\n)\n# Those source file are only needed for sync.\nif (NOT REALM_ENABLE_SYNC)\n    list(REMOVE_ITEM jni_SRC\n        ${CMAKE_CURRENT_SOURCE_DIR}/io_realm_mongodb_User.cpp\n        ${CMAKE_CURRENT_SOURCE_DIR}/io_realm_mongodb_FunctionsImpl.cpp\n        ${CMAKE_CURRENT_SOURCE_DIR}/io_realm_mongodb_EmailPasswordAuthImpl.cpp\n        ${CMAKE_CURRENT_SOURCE_DIR}/io_realm_mongodb_ApiKeyAuthImpl.cpp\n        ${CMAKE_CURRENT_SOURCE_DIR}/io_realm_mongodb_sync_ClientResetRequiredError.cpp\n        ${CMAKE_CURRENT_SOURCE_DIR}/io_realm_mongodb_sync_Sync.cpp\n        ${CMAKE_CURRENT_SOURCE_DIR}/io_realm_mongodb_sync_SyncSession.cpp\n        ${CMAKE_CURRENT_SOURCE_DIR}/io_realm_internal_objectstore_OsApp.cpp\n        ${CMAKE_CURRENT_SOURCE_DIR}/io_realm_internal_objectstore_OsAsyncOpenTask.cpp\n        ${CMAKE_CURRENT_SOURCE_DIR}/io_realm_internal_objectstore_OsAppCredentials.cpp\n        ${CMAKE_CURRENT_SOURCE_DIR}/io_realm_internal_objectstore_OsJavaNetworkTransport.cpp\n        ${CMAKE_CURRENT_SOURCE_DIR}/io_realm_internal_objectstore_OsMongoClient.cpp\n        ${CMAKE_CURRENT_SOURCE_DIR}/io_realm_internal_objectstore_OsMongoCollection.cpp\n        ${CMAKE_CURRENT_SOURCE_DIR}/io_realm_internal_objectstore_OsWatchStream.cpp\n        ${CMAKE_CURRENT_SOURCE_DIR}/io_realm_internal_objectstore_OsMongoDatabase.cpp\n        ${CMAKE_CURRENT_SOURCE_DIR}/io_realm_internal_objectstore_OsMutableSubscriptionSet.cpp\n        ${CMAKE_CURRENT_SOURCE_DIR}/io_realm_internal_objectstore_OsSubscription.cpp\n        ${CMAKE_CURRENT_SOURCE_DIR}/io_realm_internal_objectstore_OsSubscriptionSet.cpp\n        ${CMAKE_CURRENT_SOURCE_DIR}/io_realm_internal_objectstore_OsPush.cpp\n        ${CMAKE_CURRENT_SOURCE_DIR}/io_realm_internal_objectstore_OsSyncUser.cpp\n        ${CMAKE_CURRENT_SOURCE_DIR}/io_realm_mongodb_mongo_iterable_AggregateIterable.cpp\n        ${CMAKE_CURRENT_SOURCE_DIR}/io_realm_mongodb_mongo_iterable_FindIterable.cpp\n        ${CMAKE_CURRENT_SOURCE_DIR}/jni_util/bson_util.cpp\n    )\nendif()\n\nadd_library(realm-jni SHARED ${jni_SRC})\ntarget_link_libraries(realm-jni log android Realm::ObjectStore)\n\n# Use 16 KB ELF alignment to support devices with page size greater than 4 KB\ntarget_link_options(realm-jni PRIVATE \"-Wl,-z,max-page-size=16384\")\n\n# Strip the release so files and backup the unstripped versions\nif (buildTypeCap STREQUAL \"Release\")\n    set(unstripped_SO_DIR\n        \"${CMAKE_SOURCE_DIR}/../../../build/outputs/jniLibs-unstripped/${REALM_FLAVOR}/${ANDROID_ABI}\")\n    add_custom_command(TARGET realm-jni\n        POST_BUILD\n        COMMAND ${CMAKE_COMMAND} -E make_directory ${unstripped_SO_DIR}\n        COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_FILE:realm-jni> ${unstripped_SO_DIR}\n        COMMAND ${CMAKE_STRIP} $<TARGET_FILE:realm-jni>)\nendif()\n"
  },
  {
    "path": "realm/realm-library/src/main/cpp/io_realm_RealmQuery.cpp",
    "content": "/*\n * Copyright 2018 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#include \"io_realm_RealmQuery.h\"\n\n#include <realm/object-store/results.hpp>\n#include <realm/object-store/shared_realm.hpp>\n\n#include \"util.hpp\"\n\n\nusing namespace realm;\n\nJNIEXPORT jstring JNICALL Java_io_realm_RealmQuery_nativeSerializeQuery(JNIEnv* env, jclass, jlong table_query_ptr)\n{\n    try {\n        auto query = reinterpret_cast<Query*>(table_query_ptr);\n        std::string serialized_query = query->get_description();\n\n        return to_jstring(env, serialized_query);\n    }\n    CATCH_STD()\n    return to_jstring(env, \"\");\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/cpp/io_realm_internal_CheckedRow.cpp",
    "content": "/*\n * Copyright 2015 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#include \"io_realm_internal_CheckedRow.h\"\n#include \"io_realm_internal_UncheckedRow.h\"\n\n#include \"util.hpp\"\n\nusing namespace realm;\n\nJNIEXPORT jlong JNICALL Java_io_realm_internal_CheckedRow_nativeGetColumnCount(JNIEnv* env, jobject obj,\n                                                                               jlong nativeRowPtr)\n{\n    if (!OBJ(nativeRowPtr)->is_valid()) {\n        return 0;\n    }\n\n    return Java_io_realm_internal_UncheckedRow_nativeGetColumnCount(env, obj, nativeRowPtr);\n}\n\nJNIEXPORT jlong JNICALL Java_io_realm_internal_CheckedRow_nativeGetColumnKey(JNIEnv* env, jobject obj,\n                                                                               jlong nativeRowPtr, jstring columnName)\n{\n    if (!OBJ(nativeRowPtr)->is_valid()) {\n        ThrowException(env, IllegalArgument, \"Object passed is not valid\");\n    }\n\n    ColKey col_key (Java_io_realm_internal_UncheckedRow_nativeGetColumnKey(env, obj, nativeRowPtr, columnName));\n    if (!bool(col_key)) {\n        JStringAccessor column_name(env, columnName);\n        ThrowException(env, IllegalArgument, concat_stringdata(\"Field not found: \", column_name));\n    }\n    return col_key.value;\n}\n\nJNIEXPORT jint JNICALL Java_io_realm_internal_CheckedRow_nativeGetColumnType(JNIEnv* env, jobject obj,\n                                                                             jlong nativeRowPtr, jlong columnKey)\n{\n    return Java_io_realm_internal_UncheckedRow_nativeGetColumnType(env, obj, nativeRowPtr, columnKey);\n}\n\nJNIEXPORT jlong JNICALL Java_io_realm_internal_CheckedRow_nativeGetLong(JNIEnv* env, jobject obj, jlong nativeRowPtr,\n                                                                        jlong columnKey)\n{\n    if (!TYPE_VALID(env, OBJ(nativeRowPtr)->get_table(), columnKey, col_type_Int)) {\n        return 0;\n    }\n\n    return Java_io_realm_internal_UncheckedRow_nativeGetLong(env, obj, nativeRowPtr, columnKey);\n}\n\nJNIEXPORT jboolean JNICALL Java_io_realm_internal_CheckedRow_nativeGetBoolean(JNIEnv* env, jobject obj,\n                                                                              jlong nativeRowPtr, jlong columnKey)\n{\n    if (!TYPE_VALID(env, OBJ(nativeRowPtr)->get_table(), columnKey, col_type_Bool)) {\n        return JNI_FALSE;\n    }\n\n    return Java_io_realm_internal_UncheckedRow_nativeGetBoolean(env, obj, nativeRowPtr, columnKey);\n}\n\nJNIEXPORT jfloat JNICALL Java_io_realm_internal_CheckedRow_nativeGetFloat(JNIEnv* env, jobject obj,\n                                                                          jlong nativeRowPtr, jlong columnKey)\n{\n    if (!TYPE_VALID(env, OBJ(nativeRowPtr)->get_table(), columnKey, col_type_Float)) {\n        return 0;\n    }\n\n    return Java_io_realm_internal_UncheckedRow_nativeGetFloat(env, obj, nativeRowPtr, columnKey);\n}\n\nJNIEXPORT jdouble JNICALL Java_io_realm_internal_CheckedRow_nativeGetDouble(JNIEnv* env, jobject obj,\n                                                                            jlong nativeRowPtr, jlong columnKey)\n{\n    if (!TYPE_VALID(env, OBJ(nativeRowPtr)->get_table(), columnKey, col_type_Double)) {\n        return 0;\n    }\n\n    return Java_io_realm_internal_UncheckedRow_nativeGetDouble(env, obj, nativeRowPtr, columnKey);\n}\n\nJNIEXPORT jlong JNICALL Java_io_realm_internal_CheckedRow_nativeGetTimestamp(JNIEnv* env, jobject obj,\n                                                                             jlong nativeRowPtr, jlong columnKey)\n{\n    if (!TYPE_VALID(env, OBJ(nativeRowPtr)->get_table(), columnKey, col_type_Timestamp)) {\n        return 0;\n    }\n\n    return Java_io_realm_internal_UncheckedRow_nativeGetTimestamp(env, obj, nativeRowPtr, columnKey);\n}\n\nJNIEXPORT jstring JNICALL Java_io_realm_internal_CheckedRow_nativeGetString(JNIEnv* env, jobject obj,\n                                                                            jlong nativeRowPtr, jlong columnKey)\n{\n    if (!TYPE_VALID(env, OBJ(nativeRowPtr)->get_table(), columnKey, col_type_String)) {\n        return nullptr;\n    }\n\n    return Java_io_realm_internal_UncheckedRow_nativeGetString(env, obj, nativeRowPtr, columnKey);\n}\n\nJNIEXPORT jbyteArray JNICALL Java_io_realm_internal_CheckedRow_nativeGetByteArray(JNIEnv* env, jobject obj,\n                                                                                  jlong nativeRowPtr,\n                                                                                  jlong columnKey)\n{\n    if (!TYPE_VALID(env, OBJ(nativeRowPtr)->get_table(), columnKey, col_type_Binary)) {\n        return nullptr;\n    }\n\n    return Java_io_realm_internal_UncheckedRow_nativeGetByteArray(env, obj, nativeRowPtr, columnKey);\n}\n\nJNIEXPORT jlong JNICALL Java_io_realm_internal_CheckedRow_nativeGetLink(JNIEnv* env, jobject obj, jlong nativeRowPtr,\n                                                                        jlong columnKey)\n{\n    if (!TYPE_VALID(env, OBJ(nativeRowPtr)->get_table(), columnKey, col_type_Link)) {\n        return 0;\n    }\n\n    return Java_io_realm_internal_UncheckedRow_nativeGetLink(env, obj, nativeRowPtr, columnKey);\n}\n\nJNIEXPORT jboolean JNICALL Java_io_realm_internal_CheckedRow_nativeIsNullLink(JNIEnv* env, jobject obj,\n                                                                              jlong nativeRowPtr, jlong columnKey)\n{\n    if (!TYPE_VALID(env, OBJ(nativeRowPtr)->get_table(), columnKey, col_type_Link)) {\n        return JNI_FALSE;\n    }\n\n    return Java_io_realm_internal_UncheckedRow_nativeIsNullLink(env, obj, nativeRowPtr, columnKey);\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_CheckedRow_nativeSetLong(JNIEnv* env, jobject obj, jlong nativeRowPtr,\n                                                                       jlong columnKey, jlong value)\n{\n    if (!TYPE_VALID(env, OBJ(nativeRowPtr)->get_table(), columnKey, col_type_Int)) {\n        return;\n    }\n\n    Java_io_realm_internal_UncheckedRow_nativeSetLong(env, obj, nativeRowPtr, columnKey, value);\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_CheckedRow_nativeSetBoolean(JNIEnv* env, jobject obj,\n                                                                          jlong nativeRowPtr, jlong columnKey,\n                                                                          jboolean value)\n{\n    if (!TYPE_VALID(env, OBJ(nativeRowPtr)->get_table(), columnKey, col_type_Bool)) {\n        return;\n    }\n\n    Java_io_realm_internal_UncheckedRow_nativeSetBoolean(env, obj, nativeRowPtr, columnKey, value);\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_CheckedRow_nativeSetFloat(JNIEnv* env, jobject obj, jlong nativeRowPtr,\n                                                                        jlong columnKey, jfloat value)\n{\n    if (!TYPE_VALID(env, OBJ(nativeRowPtr)->get_table(), columnKey, col_type_Float)) {\n        return;\n    }\n\n    Java_io_realm_internal_UncheckedRow_nativeSetFloat(env, obj, nativeRowPtr, columnKey, value);\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_CheckedRow_nativeSetDouble(JNIEnv* env, jobject obj, jlong nativeRowPtr,\n                                                                         jlong columnKey, jdouble value)\n{\n    if (!TYPE_VALID(env, OBJ(nativeRowPtr)->get_table(), columnKey, col_type_Double)) {\n        return;\n    }\n\n    Java_io_realm_internal_UncheckedRow_nativeSetDouble(env, obj, nativeRowPtr, columnKey, value);\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_CheckedRow_nativeSetTimestamp(JNIEnv* env, jobject obj,\n                                                                            jlong nativeRowPtr, jlong columnKey,\n                                                                            jlong value)\n{\n    if (!TYPE_VALID(env, OBJ(nativeRowPtr)->get_table(), columnKey, col_type_Timestamp)) {\n        return;\n    }\n\n    Java_io_realm_internal_UncheckedRow_nativeSetTimestamp(env, obj, nativeRowPtr, columnKey, value);\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_CheckedRow_nativeSetString(JNIEnv* env, jobject obj, jlong nativeRowPtr,\n                                                                         jlong columnKey, jstring value)\n{\n    if (!TYPE_VALID(env, OBJ(nativeRowPtr)->get_table(), columnKey, col_type_String)) {\n        return;\n    }\n\n    Java_io_realm_internal_UncheckedRow_nativeSetString(env, obj, nativeRowPtr, columnKey, value);\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_CheckedRow_nativeSetByteArray(JNIEnv* env, jobject obj,\n                                                                            jlong nativeRowPtr, jlong columnKey,\n                                                                            jbyteArray value)\n{\n    if (!TYPE_VALID(env, OBJ(nativeRowPtr)->get_table(), columnKey, col_type_Binary)) {\n        return;\n    }\n\n    Java_io_realm_internal_UncheckedRow_nativeSetByteArray(env, obj, nativeRowPtr, columnKey, value);\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_CheckedRow_nativeSetLink(JNIEnv* env, jobject obj, jlong nativeRowPtr,\n                                                                       jlong columnKey, jlong value)\n{\n    if (!TYPE_VALID(env, OBJ(nativeRowPtr)->get_table(), columnKey, col_type_Link)) {\n        return;\n    }\n\n    Java_io_realm_internal_UncheckedRow_nativeSetLink(env, obj, nativeRowPtr, columnKey, value);\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_CheckedRow_nativeNullifyLink(JNIEnv* env, jobject obj,\n                                                                           jlong nativeRowPtr, jlong columnKey)\n{\n    if (!TYPE_VALID(env, OBJ(nativeRowPtr)->get_table(), columnKey, col_type_Link)) {\n        return;\n    }\n\n    Java_io_realm_internal_UncheckedRow_nativeNullifyLink(env, obj, nativeRowPtr, columnKey);\n}\n\n\nJNIEXPORT jlongArray JNICALL Java_io_realm_internal_CheckedRow_nativeGetDecimal128(JNIEnv* env, jobject obj, jlong nativeRowPtr, jlong columnKey)\n{\n    if (!TYPE_VALID(env, OBJ(nativeRowPtr)->get_table(), columnKey, col_type_Decimal)) {\n        return nullptr;\n    }\n\n    return Java_io_realm_internal_UncheckedRow_nativeGetDecimal128(env, obj, nativeRowPtr, columnKey);\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_CheckedRow_nativeSetDecimal128(JNIEnv* env, jobject obj, jlong nativeRowPtr, jlong columnKey, jlong low, jlong high)\n{\n    if (!TYPE_VALID(env, OBJ(nativeRowPtr)->get_table(), columnKey, col_type_Decimal)) {\n        return;\n    }\n\n    Java_io_realm_internal_UncheckedRow_nativeSetDecimal128(env, obj, nativeRowPtr, columnKey, low, high);\n}\n\nJNIEXPORT jstring JNICALL Java_io_realm_internal_CheckedRow_nativeGetObjectId(JNIEnv* env, jobject obj,\n                                                                                    jlong nativeRowPtr,\n                                                                                    jlong columnKey)\n{\n    if (!TYPE_VALID(env, OBJ(nativeRowPtr)->get_table(), columnKey, col_type_ObjectId)) {\n        return nullptr;\n    }\n\n    return Java_io_realm_internal_UncheckedRow_nativeGetObjectId(env, obj, nativeRowPtr, columnKey);\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_CheckedRow_nativeSetObjectId(JNIEnv* env, jobject obj,\n                                                                              jlong nativeRowPtr, jlong columnKey,\n                                                                              jstring j_value)\n{\n    if (!TYPE_VALID(env, OBJ(nativeRowPtr)->get_table(), columnKey, col_type_ObjectId)) {\n        return;\n    }\n\n    Java_io_realm_internal_UncheckedRow_nativeSetObjectId(env, obj, nativeRowPtr, columnKey, j_value);\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/cpp/io_realm_internal_NativeObjectReference.cpp",
    "content": "/*\n * Copyright 2016 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#include \"io_realm_internal_NativeObjectReference.h\"\n\ntypedef void (*FinalizeFunc)(jlong);\n\nJNIEXPORT void JNICALL Java_io_realm_internal_NativeObjectReference_nativeCleanUp(JNIEnv*, jclass,\n                                                                                  jlong finalizer_ptr,\n                                                                                  jlong native_ptr)\n{\n    FinalizeFunc finalize_func = reinterpret_cast<FinalizeFunc>(finalizer_ptr);\n    finalize_func(native_ptr);\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/cpp/io_realm_internal_OsCollectionChangeSet.cpp",
    "content": "/*\n * Copyright 2017 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#include \"io_realm_internal_OsCollectionChangeSet.h\"\n\n#include <realm/object-store/collection_notifications.hpp>\n\n#include \"util.hpp\"\n\nusing namespace realm;\n\nstatic void finalize_changeset(jlong ptr);\nstatic jintArray index_set_to_jint_array(JNIEnv* env, const IndexSet& index_set);\nstatic jintArray index_set_to_indices_array(JNIEnv* env, const IndexSet& index_set);\n\nstatic void finalize_changeset(jlong ptr)\n{\n    delete reinterpret_cast<CollectionChangeSet*>(ptr);\n}\n\nstatic jintArray index_set_to_jint_array(JNIEnv* env, const IndexSet& index_set)\n{\n    if (index_set.empty()) {\n        return env->NewIntArray(0);\n    }\n\n    std::vector<jint> ranges_vector;\n    for (auto& changes : index_set) {\n        ranges_vector.push_back(changes.first);\n        ranges_vector.push_back(changes.second - changes.first);\n    }\n\n    if (ranges_vector.size() > io_realm_internal_OsCollectionChangeSet_MAX_ARRAY_LENGTH) {\n        std::ostringstream error_msg;\n        error_msg << \"There are too many ranges changed in this change set. They cannot fit into an array.\"\n                  << \" ranges_vector's size: \" << ranges_vector.size()\n                  << \" Java array's max size: \" << io_realm_internal_OsCollectionChangeSet_MAX_ARRAY_LENGTH << \".\";\n        ThrowException(env, IllegalState, error_msg.str());\n        return nullptr;\n    }\n    jintArray jint_array = env->NewIntArray(static_cast<jsize>(ranges_vector.size()));\n    env->SetIntArrayRegion(jint_array, 0, ranges_vector.size(), ranges_vector.data());\n    return jint_array;\n}\n\nstatic jintArray index_set_to_indices_array(JNIEnv* env, const IndexSet& index_set)\n{\n    if (index_set.empty()) {\n        return env->NewIntArray(0);\n    }\n\n    std::vector<jint> indices_vector;\n    for (auto index : index_set.as_indexes()) {\n        indices_vector.push_back(index);\n    }\n    if (indices_vector.size() > io_realm_internal_OsCollectionChangeSet_MAX_ARRAY_LENGTH) {\n        std::ostringstream error_msg;\n        error_msg << \"There are too many indices in this change set. They cannot fit into an array.\"\n                  << \" indices_vector's size: \" << indices_vector.size()\n                  << \" Java array's max size: \" << io_realm_internal_OsCollectionChangeSet_MAX_ARRAY_LENGTH << \".\";\n        ThrowException(env, IllegalState, error_msg.str());\n        return nullptr;\n    }\n    jintArray jint_array = env->NewIntArray(static_cast<jsize>(indices_vector.size()));\n    env->SetIntArrayRegion(jint_array, 0, indices_vector.size(), indices_vector.data());\n    return jint_array;\n}\n\nJNIEXPORT jlong JNICALL Java_io_realm_internal_OsCollectionChangeSet_nativeGetFinalizerPtr(JNIEnv*, jclass)\n{\n    return reinterpret_cast<jlong>(&finalize_changeset);\n}\n\nJNIEXPORT jintArray JNICALL Java_io_realm_internal_OsCollectionChangeSet_nativeGetRanges(JNIEnv* env, jclass,\n                                                                                         jlong native_ptr, jint type)\n{\n    // no throws\n    auto& change_set = *reinterpret_cast<CollectionChangeSet*>(native_ptr);\n    switch (type) {\n        case io_realm_internal_OsCollectionChangeSet_TYPE_DELETION:\n            return index_set_to_jint_array(env, change_set.deletions);\n        case io_realm_internal_OsCollectionChangeSet_TYPE_INSERTION:\n            return index_set_to_jint_array(env, change_set.insertions);\n        case io_realm_internal_OsCollectionChangeSet_TYPE_MODIFICATION:\n            return index_set_to_jint_array(env, change_set.modifications_new);\n        default:\n            REALM_UNREACHABLE();\n    }\n}\n\nJNIEXPORT jintArray JNICALL Java_io_realm_internal_OsCollectionChangeSet_nativeGetIndices(JNIEnv* env, jclass,\n                                                                                          jlong native_ptr, jint type)\n{\n    // no throws\n    auto& change_set = *reinterpret_cast<CollectionChangeSet*>(native_ptr);\n    switch (type) {\n        case io_realm_internal_OsCollectionChangeSet_TYPE_DELETION:\n            return index_set_to_indices_array(env, change_set.deletions);\n        case io_realm_internal_OsCollectionChangeSet_TYPE_INSERTION:\n            return index_set_to_indices_array(env, change_set.insertions);\n        case io_realm_internal_OsCollectionChangeSet_TYPE_MODIFICATION:\n            return index_set_to_indices_array(env, change_set.modifications_new);\n        default:\n            REALM_UNREACHABLE();\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/cpp/io_realm_internal_OsList.cpp",
    "content": "/*\n * Copyright 2017 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#include \"io_realm_internal_OsList.h\"\n\n#include <realm/object-store/list.hpp>\n#include <realm/object-store/results.hpp>\n#include <realm/object-store/shared_realm.hpp>\n\n#include \"observable_collection_wrapper.hpp\"\n#include \"java_accessor.hpp\"\n#include \"java_object_accessor.hpp\"\n#include \"java_exception_def.hpp\"\n#include \"jni_util/java_exception_thrower.hpp\"\n#include \"util.hpp\"\n\nusing namespace realm;\nusing namespace realm::util;\nusing namespace realm::_impl;\n\ntypedef ObservableCollectionWrapper<List> ListWrapper;\n\nnamespace {\nvoid finalize_list(jlong ptr)\n{\n    delete reinterpret_cast<ListWrapper*>(ptr);\n}\n\ninline void add_value(JNIEnv* env, jlong list_ptr, Any&& value)\n{\n    auto& wrapper = *reinterpret_cast<ListWrapper*>(list_ptr);\n\n    JavaAccessorContext context(env);\n    wrapper.collection().add(context, value);\n}\n\ninline void insert_value(JNIEnv* env, jlong list_ptr, jlong pos, Any&& value)\n{\n    auto& wrapper = *reinterpret_cast<ListWrapper*>(list_ptr);\n\n    JavaAccessorContext context(env);\n    wrapper.collection().insert(context, pos, value);\n}\n\ninline void set_value(JNIEnv* env, jlong list_ptr, jlong pos, Any&& value)\n{\n    auto& wrapper = *reinterpret_cast<ListWrapper*>(list_ptr);\n\n    JavaAccessorContext context(env);\n    wrapper.collection().set(context, pos, value);\n}\n\n// Check nullable earlier https://github.com/realm/realm-object-store/issues/544\ninline void check_nullable(JNIEnv* env, jlong list_ptr, jobject jobject_ptr = nullptr)\n{\n    auto& wrapper = *reinterpret_cast<ListWrapper*>(list_ptr);\n    if (!jobject_ptr && !is_nullable(wrapper.collection().get_type())) {\n        THROW_JAVA_EXCEPTION(env, JavaExceptionDef::IllegalArgument,\n                             \"This 'RealmList' is not nullable. A non-null value is expected.\");\n    }\n}\n} // anonymous namespace\n\nJNIEXPORT jlong JNICALL Java_io_realm_internal_OsList_nativeGetFinalizerPtr(JNIEnv*, jclass)\n{\n    return reinterpret_cast<jlong>(&finalize_list);\n}\n\nJNIEXPORT jlongArray JNICALL Java_io_realm_internal_OsList_nativeCreate(JNIEnv* env, jclass, jlong shared_realm_ptr,\n                                                                        jlong obj_ptr, jlong column_key)\n{\n    try {\n        auto& obj = *reinterpret_cast<realm::Obj*>(obj_ptr);\n\n        auto& shared_realm = *reinterpret_cast<SharedRealm*>(shared_realm_ptr);\n        jlong ret[2];\n\n        List list(shared_realm, obj, ColKey(column_key));\n        ListWrapper* wrapper_ptr = new ListWrapper(list);\n        ret[0] = reinterpret_cast<jlong>(wrapper_ptr);\n\n        if (wrapper_ptr->collection().get_type() == PropertyType::Object) {\n            auto link_view_ref = obj.get_linklist(ColKey(column_key));\n\n            TableRef* target_table_ptr = new TableRef(link_view_ref.get_target_table());\n            ret[1] = reinterpret_cast<jlong>(target_table_ptr);\n        }\n        else {\n            ret[1] = reinterpret_cast<jlong>(nullptr);\n        }\n\n        jlongArray ret_array = env->NewLongArray(2);\n        if (!ret_array) {\n            ThrowException(env, OutOfMemory, \"Could not allocate memory to create OsList.\");\n            return nullptr;\n        }\n        env->SetLongArrayRegion(ret_array, 0, 2, ret);\n        return ret_array;\n    }\n    CATCH_STD()\n    return nullptr;\n}\n\nJNIEXPORT jlong JNICALL Java_io_realm_internal_OsList_nativeGetRow(JNIEnv* env, jclass, jlong list_ptr,\n                                                                   jlong column_index)\n{\n    try {\n        auto& wrapper = *reinterpret_cast<ListWrapper*>(list_ptr);\n        auto obj = wrapper.collection().get(column_index);\n        return reinterpret_cast<jlong>(new Obj(std::move(obj)));\n    }\n    CATCH_STD()\n    return reinterpret_cast<jlong>(nullptr);\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_OsList_nativeAddRow(JNIEnv* env, jclass, jlong list_ptr,\n                                                                  jlong target_obj_key)\n{\n\n    try {\n        auto& wrapper = *reinterpret_cast<ListWrapper*>(list_ptr);\n        wrapper.collection().add(ObjKey(target_obj_key));\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_OsList_nativeInsertRow(JNIEnv* env, jclass, jlong list_ptr, jlong pos,\n                                                                     jlong target_obj_key)\n{\n    try {\n        auto& wrapper = *reinterpret_cast<ListWrapper*>(list_ptr);\n        wrapper.collection().insert(static_cast<size_t>(pos), ObjKey(target_obj_key));\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_OsList_nativeSetRow(JNIEnv* env, jclass, jlong list_ptr, jlong pos,\n                                                                  jlong target_obj_key)\n{\n    try {\n        auto& wrapper = *reinterpret_cast<ListWrapper*>(list_ptr);\n        wrapper.collection().set(static_cast<size_t>(pos), ObjKey(target_obj_key));\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_OsList_nativeMove(JNIEnv* env, jclass, jlong list_ptr,\n                                                                jlong source_index, jlong target_index)\n{\n    try {\n        auto& wrapper = *reinterpret_cast<ListWrapper*>(list_ptr);\n        wrapper.collection().move(source_index, target_index);\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_OsList_nativeRemove(JNIEnv* env, jclass, jlong list_ptr, jlong index)\n{\n    try {\n        auto& wrapper = *reinterpret_cast<ListWrapper*>(list_ptr);\n        wrapper.collection().remove(index);\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_OsList_nativeRemoveAll(JNIEnv* env, jclass, jlong list_ptr)\n{\n    try {\n        auto& wrapper = *reinterpret_cast<ListWrapper*>(list_ptr);\n        wrapper.collection().remove_all();\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT jlong JNICALL Java_io_realm_internal_OsList_nativeSize(JNIEnv* env, jclass, jlong list_ptr)\n{\n    try {\n        auto& wrapper = *reinterpret_cast<ListWrapper*>(list_ptr);\n        return wrapper.collection().size();\n    }\n    CATCH_STD()\n    return 0;\n}\n\nJNIEXPORT jlong JNICALL Java_io_realm_internal_OsList_nativeGetQuery(JNIEnv* env, jclass, jlong list_ptr)\n{\n    try {\n        auto& wrapper = *reinterpret_cast<ListWrapper*>(list_ptr);\n        auto query = wrapper.collection().get_query();\n        query.set_ordering(std::make_unique<DescriptorOrdering>());\n        return reinterpret_cast<jlong>(new Query(std::move(query)));\n    }\n    CATCH_STD()\n    return reinterpret_cast<jlong>(nullptr);\n}\n\nJNIEXPORT jboolean JNICALL Java_io_realm_internal_OsList_nativeIsValid(JNIEnv* env, jclass, jlong list_ptr)\n{\n    try {\n        auto& wrapper = *reinterpret_cast<ListWrapper*>(list_ptr);\n        return wrapper.collection().is_valid();\n    }\n    CATCH_STD()\n    return JNI_FALSE;\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_OsList_nativeDelete(JNIEnv* env, jclass, jlong list_ptr, jlong index)\n{\n    try {\n        auto& wrapper = *reinterpret_cast<ListWrapper*>(list_ptr);\n        wrapper.collection().delete_at(S(index));\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_OsList_nativeDeleteAll(JNIEnv* env, jclass, jlong list_ptr)\n{\n    try {\n        auto& wrapper = *reinterpret_cast<ListWrapper*>(list_ptr);\n        wrapper.collection().delete_all();\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_OsList_nativeStartListening(JNIEnv* env, jobject instance,\n                                                                              jlong native_ptr)\n{\n    try {\n        auto wrapper = reinterpret_cast<ListWrapper*>(native_ptr);\n        wrapper->start_listening(env, instance);\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_OsList_nativeStopListening(JNIEnv* env, jobject, jlong native_ptr)\n{\n    try {\n        auto wrapper = reinterpret_cast<ListWrapper*>(native_ptr);\n        wrapper->stop_listening();\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_OsList_nativeAddNull(JNIEnv* env, jclass, jlong list_ptr)\n{\n    try {\n        check_nullable(env, list_ptr);\n        add_value(env, list_ptr, Any());\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_OsList_nativeInsertNull(JNIEnv* env, jclass, jlong list_ptr, jlong pos)\n{\n    try {\n        check_nullable(env, list_ptr);\n        insert_value(env, list_ptr, pos, Any());\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_OsList_nativeSetNull(JNIEnv* env, jclass, jlong list_ptr, jlong pos)\n{\n    try {\n        check_nullable(env, list_ptr);\n        set_value(env, list_ptr, pos, Any());\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_OsList_nativeAddLong(JNIEnv* env, jclass, jlong list_ptr, jlong value)\n{\n    try {\n        add_value(env, list_ptr, Any(value));\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_OsList_nativeInsertLong(JNIEnv* env, jclass, jlong list_ptr, jlong pos,\n                                                                      jlong value)\n{\n    try {\n        insert_value(env, list_ptr, pos, Any(value));\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_OsList_nativeSetLong(JNIEnv* env, jclass, jlong list_ptr, jlong pos,\n                                                                   jlong value)\n{\n    try {\n        set_value(env, list_ptr, pos, Any(value));\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_OsList_nativeAddDouble(JNIEnv* env, jclass, jlong list_ptr,\n                                                                     jdouble value)\n{\n    try {\n        add_value(env, list_ptr, Any(value));\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_OsList_nativeInsertDouble(JNIEnv* env, jclass, jlong list_ptr,\n                                                                        jlong pos, jdouble value)\n{\n    try {\n        insert_value(env, list_ptr, pos, Any(value));\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_OsList_nativeSetDouble(JNIEnv* env, jclass, jlong list_ptr, jlong pos,\n                                                                     jdouble value)\n{\n    try {\n        set_value(env, list_ptr, pos, Any(value));\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_OsList_nativeAddFloat(JNIEnv* env, jclass, jlong list_ptr, jfloat value)\n{\n    try {\n        add_value(env, list_ptr, Any(value));\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_OsList_nativeInsertFloat(JNIEnv* env, jclass, jlong list_ptr, jlong pos,\n                                                                       jfloat value)\n{\n    try {\n        insert_value(env, list_ptr, pos, Any(value));\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_OsList_nativeSetFloat(JNIEnv* env, jclass, jlong list_ptr, jlong pos,\n                                                                    jfloat value)\n{\n    try {\n        set_value(env, list_ptr, pos, Any(value));\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_OsList_nativeAddBoolean(JNIEnv* env, jclass, jlong list_ptr,\n                                                                      jboolean value)\n{\n    try {\n        add_value(env, list_ptr, Any(value));\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_OsList_nativeInsertBoolean(JNIEnv* env, jclass, jlong list_ptr,\n                                                                         jlong pos, jboolean value)\n{\n    try {\n        insert_value(env, list_ptr, pos, Any(value));\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_OsList_nativeSetBoolean(JNIEnv* env, jclass, jlong list_ptr, jlong pos,\n                                                                      jboolean value)\n{\n    try {\n        set_value(env, list_ptr, pos, Any(value));\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_OsList_nativeAddBinary(JNIEnv* env, jclass, jlong list_ptr,\n                                                                     jbyteArray value)\n{\n    try {\n        check_nullable(env, list_ptr, value);\n        JByteArrayAccessor accessor(env, value);\n        add_value(env, list_ptr, Any(accessor));\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_OsList_nativeInsertBinary(JNIEnv* env, jclass, jlong list_ptr,\n                                                                        jlong pos, jbyteArray value)\n{\n    try {\n        check_nullable(env, list_ptr, value);\n        JByteArrayAccessor accessor(env, value);\n        insert_value(env, list_ptr, pos, Any(accessor));\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_OsList_nativeSetBinary(JNIEnv* env, jclass, jlong list_ptr, jlong pos,\n                                                                     jbyteArray value)\n{\n    try {\n        check_nullable(env, list_ptr, value);\n        JByteArrayAccessor accessor(env, value);\n        set_value(env, list_ptr, pos, Any(accessor));\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_OsList_nativeAddDate(JNIEnv* env, jclass, jlong list_ptr, jlong value)\n{\n    try {\n        add_value(env, list_ptr, Any(value));\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_OsList_nativeInsertDate(JNIEnv* env, jclass, jlong list_ptr, jlong pos,\n                                                                      jlong value)\n{\n    try {\n        insert_value(env, list_ptr, pos, Any(value));\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_OsList_nativeSetDate(JNIEnv* env, jclass, jlong list_ptr, jlong pos,\n                                                                   jlong value)\n{\n    try {\n        set_value(env, list_ptr, pos, Any(value));\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_OsList_nativeAddString(JNIEnv* env, jclass, jlong list_ptr,\n                                                                     jstring value)\n{\n    try {\n        check_nullable(env, list_ptr, value);\n        JStringAccessor accessor(env, value);\n        add_value(env, list_ptr, Any(accessor));\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_OsList_nativeInsertString(JNIEnv* env, jclass, jlong list_ptr,\n                                                                        jlong pos, jstring value)\n{\n    try {\n        check_nullable(env, list_ptr, value);\n        JStringAccessor accessor(env, value);\n        insert_value(env, list_ptr, pos, Any(accessor));\n    }\n    CATCH_STD();\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_OsList_nativeSetString(JNIEnv* env, jclass, jlong list_ptr, jlong pos,\n                                                                     jstring value)\n{\n    try {\n        check_nullable(env, list_ptr, value);\n        JStringAccessor accessor(env, value);\n        set_value(env, list_ptr, pos, Any(accessor));\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_OsList_nativeAddDecimal128(JNIEnv* env, jclass, jlong list_ptr,\n                                                                         jlong j_low_value, jlong j_high_value)\n{\n    try {\n          Decimal128::Bid128 raw {static_cast<uint64_t>(j_low_value), static_cast<uint64_t>(j_high_value)};\n          add_value(env, list_ptr, Any(Decimal128(raw)));\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_OsList_nativeInsertDecimal128(JNIEnv* env, jclass, jlong list_ptr,\n                                                                            jlong pos, jlong j_low_value, jlong j_high_value)\n{\n    try {\n        Decimal128::Bid128 raw {static_cast<uint64_t>(j_low_value), static_cast<uint64_t>(j_high_value)};\n        insert_value(env, list_ptr, pos, Any(Decimal128(raw)));\n    }\n    CATCH_STD();\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_OsList_nativeSetDecimal128(JNIEnv* env, jclass, jlong list_ptr, jlong pos,\n                                                                         jlong j_high_value, jlong j_low_value)\n{\n    try {\n        Decimal128::Bid128 raw {static_cast<uint64_t>(j_low_value), static_cast<uint64_t>(j_high_value)};\n        set_value(env, list_ptr, pos, Any(Decimal128(raw)));\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_OsList_nativeAddObjectId(JNIEnv* env, jclass, jlong list_ptr,\n                                                                       jstring j_value)\n{\n\n    try {\n        JStringAccessor value(env, j_value);\n        add_value(env, list_ptr, Any(ObjectId(StringData(value).data())));\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_OsList_nativeInsertObjectId(JNIEnv* env, jclass, jlong list_ptr,\n                                                                          jlong pos, jstring j_value)\n{\n    try {\n        JStringAccessor value(env, j_value);\n        insert_value(env, list_ptr, pos, Any(ObjectId(StringData(value).data())));\n    }\n    CATCH_STD();\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_OsList_nativeSetObjectId(JNIEnv* env, jclass, jlong list_ptr, jlong pos,\n                                                                       jstring j_value)\n{\n    try {\n        JStringAccessor value(env, j_value);\n        set_value(env, list_ptr, pos, Any(ObjectId(StringData(value).data())));\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_OsList_nativeAddUUID(JNIEnv* env, jclass, jlong list_ptr,\n                                                                       jstring j_value)\n{\n    try {\n        JStringAccessor value(env, j_value);\n        add_value(env, list_ptr, Any(UUID(StringData(value).data())));\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_OsList_nativeInsertUUID(JNIEnv* env, jclass, jlong list_ptr,\n                                                                          jlong pos, jstring j_value)\n{\n    try {\n        JStringAccessor value(env, j_value);\n        insert_value(env, list_ptr, pos, Any(UUID(StringData(value).data())));\n    }\n    CATCH_STD();\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_OsList_nativeSetUUID(JNIEnv* env, jclass, jlong list_ptr, jlong pos,\n                                                                       jstring j_value)\n{\n    try {\n        JStringAccessor value(env, j_value);\n        set_value(env, list_ptr, pos, Any(UUID(StringData(value).data())));\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_OsList_nativeAddRealmAny(JNIEnv* env, jclass, jlong list_ptr,\n                                                                   jlong mixed_ptr)\n{\n    try {\n        auto java_value = *reinterpret_cast<JavaValue*>(mixed_ptr);\n        add_value(env, list_ptr, Any(java_value.to_mixed()));\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_OsList_nativeInsertRealmAny(JNIEnv* env, jclass, jlong list_ptr,\n                                                                      jlong pos, jlong mixed_ptr)\n{\n    try {\n        auto java_value = *reinterpret_cast<JavaValue*>(mixed_ptr);\n        insert_value(env, list_ptr, pos, Any(java_value.to_mixed()));\n    }\n    CATCH_STD();\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_OsList_nativeSetRealmAny(JNIEnv* env, jclass, jlong list_ptr, jlong pos,\n                                                                   jlong mixed_ptr)\n{\n    try {\n        auto java_value = *reinterpret_cast<JavaValue*>(mixed_ptr);\n        set_value(env, list_ptr, pos, Any(java_value.to_mixed()));\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT jobject JNICALL Java_io_realm_internal_OsList_nativeGetValue(JNIEnv* env, jclass, jlong list_ptr, jlong pos)\n{\n    try {\n        auto& wrapper = *reinterpret_cast<ListWrapper*>(list_ptr);\n        JavaAccessorContext context(env);\n        return util::any_cast<jobject>(wrapper.collection().get(context, pos));\n    }\n    CATCH_STD()\n\n    return nullptr;\n}\n\nJNIEXPORT jlong JNICALL Java_io_realm_internal_OsList_nativeCreateAndAddEmbeddedObject(JNIEnv* env, jclass, jlong native_list_ptr, jlong j_index)\n{\n    try {\n        List& list = reinterpret_cast<ListWrapper*>(native_list_ptr)->collection();\n        auto& realm = list.get_realm();\n        auto& object_schema = list.get_object_schema();\n        JavaContext ctx(env, realm, object_schema);\n        // Create dummy object. Properties must be added later.\n        // TODO CreatePolicy::Skip is a hack right after the object is inserted and before Schemas\n        //  are validated. Figure out a better approach.\n        auto array_index = static_cast<size_t>(j_index);\n        list.insert(ctx, array_index, JavaValue(std::map<ColKey, JavaValue>()), CreatePolicy::Skip);\n        return reinterpret_cast<jlong>(list.get(array_index).get_key().value);\n    }\n    CATCH_STD()\n    return reinterpret_cast<jlong>(nullptr);\n}\n\n\nJNIEXPORT jlong JNICALL Java_io_realm_internal_OsList_nativeCreateAndSetEmbeddedObject(JNIEnv* env, jclass, jlong native_list_ptr, jlong j_index)\n{\n    try {\n        List& list = reinterpret_cast<ListWrapper*>(native_list_ptr)->collection();\n        auto& realm = list.get_realm();\n        auto& object_schema = list.get_object_schema();\n        JavaContext ctx(env, realm, object_schema);\n        size_t array_index = static_cast<size_t>(j_index);\n        // Create dummy object. Properties must be added later.\n        // TODO CreatePolicy::Skip is a hack right after the object is inserted and before Schemas\n        //  are validated. Figure out a better approach.\n        list.set(ctx, array_index, JavaValue(std::map<ColKey, JavaValue>()), CreatePolicy::Skip);\n        return reinterpret_cast<jlong>(list.get(list.size() - 1).get_key().value);\n    }\n    CATCH_STD()\n    return reinterpret_cast<jlong>(nullptr);\n}\n\nJNIEXPORT jlong JNICALL Java_io_realm_internal_OsList_nativeFreeze(JNIEnv* env, jclass, jlong native_list_ptr, jlong frozen_realm_native_ptr)\n{\n    try {\n        auto& wrapper = *reinterpret_cast<ListWrapper*>(native_list_ptr);\n        auto frozen_realm = *(reinterpret_cast<SharedRealm*>(frozen_realm_native_ptr));\n        List list = wrapper.collection().freeze(frozen_realm);\n        return reinterpret_cast<jlong>(new ListWrapper(list));\n    }\n    CATCH_STD()\n    return reinterpret_cast<jlong>(nullptr);\n}\n\n"
  },
  {
    "path": "realm/realm-library/src/main/cpp/io_realm_internal_OsMap.cpp",
    "content": "/*\n * Copyright 2020 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#include \"io_realm_internal_OsMap.h\"\n\n#include <realm/object-store/dictionary.hpp>\n#include <realm/object-store/shared_realm.hpp>\n\n#include \"java_accessor.hpp\"\n#include \"java_object_accessor.hpp\"\n#include \"java_exception_def.hpp\"\n#include \"jni_util/java_exception_thrower.hpp\"\n#include \"util.hpp\"\n#include \"observable_collection_wrapper.hpp\"\n#include \"observable_dictionary_wrapper.hpp\"\n\nusing namespace realm;\nusing namespace realm::util;\nusing namespace realm::object_store;\nusing namespace realm::_impl;\n\nvoid finalize_map(jlong ptr) {\n    delete reinterpret_cast<ObservableDictionaryWrapper*>(ptr);\n}\n\nJNIEXPORT jlong JNICALL Java_io_realm_internal_OsMap_nativeGetFinalizerPtr(JNIEnv*, jclass) {\n    return reinterpret_cast<jlong>(&finalize_map);\n}\n\nJNIEXPORT jlongArray JNICALL\nJava_io_realm_internal_OsMap_nativeCreate(JNIEnv* env, jclass, jlong shared_realm_ptr,\n                                          jlong obj_ptr, jlong column_key) {\n    try {\n        auto obj = *reinterpret_cast<realm::Obj*>(obj_ptr);\n        auto shared_realm = *reinterpret_cast<SharedRealm*>(shared_realm_ptr);\n\n        // Return an array of pointers: first to the wrapper, second to the table (if applicable)\n        jlong ret[2];\n\n        // Get dictionary, put it in the wrapper and save pointer to be returned\n        object_store::Dictionary dictionary(shared_realm, obj, ColKey(column_key));\n        auto wrapper_ptr = new ObservableDictionaryWrapper(dictionary);\n        ret[0] = reinterpret_cast<jlong>(wrapper_ptr);\n\n        // Special case for objects: return the table. Ignore for other types\n        if (wrapper_ptr->collection().get_type() == PropertyType::Object) {\n            const DictionaryPtr& ptr = obj.get_dictionary_ptr(ColKey(column_key));\n            auto target_table_ptr = new TableRef(ptr->get_target_table());\n            ret[1] = reinterpret_cast<jlong>(target_table_ptr);\n        } else {\n            ret[1] = reinterpret_cast<jlong>(nullptr);\n        }\n\n        jlongArray ret_array = env->NewLongArray(2);\n        if (!ret_array) {\n            ThrowException(env, OutOfMemory, \"Could not allocate memory to create OsMap.\");\n            return nullptr;\n        }\n\n        env->SetLongArrayRegion(ret_array, 0, 2, ret);\n        return ret_array;\n    }\n    CATCH_STD()\n    return nullptr;\n}\n\nJNIEXPORT jobject JNICALL\nJava_io_realm_internal_OsMap_nativeGetValue(JNIEnv* env, jclass, jlong wrapper_ptr,\n                                            jstring j_key) {\n    try {\n        auto& wrapper = *reinterpret_cast<ObservableDictionaryWrapper*>(wrapper_ptr);\n        auto& dictionary = wrapper.collection();\n        JStringAccessor key(env, j_key);\n        const Optional<Mixed>& optional_result = dictionary.try_get_any(StringData(key));\n        if (optional_result) {\n            const Mixed& value = optional_result.value();\n            if (value.is_null()) {\n                return nullptr;\n            } else {\n                const DataType& type = value.get_type();\n                switch (type) {\n                    case DataType::Type::Int:\n                        return JavaClassGlobalDef::new_long(env, value.get_int());\n                    case DataType::Type::Double:\n                        return JavaClassGlobalDef::new_double(env, value.get_double());\n                    case DataType::Type::Bool:\n                        return JavaClassGlobalDef::new_boolean(env, value.get_bool());\n                    case DataType::Type::String:\n                        return to_jstring(env, value.get_string());\n                    case DataType::Type::Binary:\n                        return JavaClassGlobalDef::new_byte_array(env, value.get_binary());\n                    case DataType::Type::Float:\n                        return JavaClassGlobalDef::new_float(env, value.get_float());\n                    case DataType::Type::UUID:\n                        return JavaClassGlobalDef::new_uuid(env, value.get_uuid());\n                    case DataType::Type::ObjectId:\n                        return JavaClassGlobalDef::new_object_id(env, value.get_object_id());\n                    case DataType::Type::Timestamp:\n                        return JavaClassGlobalDef::new_date(env, value.get_timestamp());\n                    case DataType::Type::Decimal:\n                        return JavaClassGlobalDef::new_decimal128(env, value.get_decimal());\n                    default:\n                        throw std::logic_error(\"'getValue' method only suitable for int, float, double, boolean, String, byte[], float, UUID, Decimal128 and ObjectId.\");\n                }\n            }\n        }\n    }\n    CATCH_STD()\n\n    return nullptr;\n}\n\nJNIEXPORT jlong JNICALL\nJava_io_realm_internal_OsMap_nativeGetRealmAnyPtr(JNIEnv *env, jclass, jlong wrapper_ptr,\n                                               jstring j_key) {\n    try {\n        auto& wrapper = *reinterpret_cast<ObservableDictionaryWrapper*>(wrapper_ptr);\n        auto& dictionary = wrapper.collection();\n        JStringAccessor key(env, j_key);\n        const Optional<Mixed>& optional_result = dictionary.try_get_any(StringData(key));\n        if (optional_result) {\n            return reinterpret_cast<jlong>(new JavaValue(from_mixed(optional_result.value())));\n        }\n    }\n    CATCH_STD();\n    return io_realm_internal_OsMap_NOT_FOUND;\n}\n\nJNIEXPORT jlong JNICALL\nJava_io_realm_internal_OsMap_nativeGetRow(JNIEnv* env, jclass, jlong wrapper_ptr,\n                                          jstring j_key) {\n    try {\n        auto& wrapper = *reinterpret_cast<ObservableDictionaryWrapper*>(wrapper_ptr);\n        auto& dictionary = wrapper.collection();\n        JStringAccessor key(env, j_key);\n        const Optional<Mixed>& optional_result = dictionary.try_get_any(StringData(key));\n        if (optional_result) {\n            const Mixed& value = optional_result.value();\n            if (!value.is_null()) {\n                return optional_result.value().get<ObjKey>().value;\n            }\n        }\n    }\n    CATCH_STD()\n    return io_realm_internal_OsMap_NOT_FOUND;\n}\n\nJNIEXPORT void JNICALL\nJava_io_realm_internal_OsMap_nativePutRealmAny(JNIEnv* env, jclass, jlong wrapper_ptr, jstring j_key,\n                                            jlong mixed_ptr) {\n    try {\n        auto& wrapper = *reinterpret_cast<ObservableDictionaryWrapper*>(wrapper_ptr);\n        auto& dictionary = wrapper.collection();\n        auto mixed_java_value = *reinterpret_cast<JavaValue*>(mixed_ptr);\n        const Mixed& mixed = mixed_java_value.to_mixed();\n        JStringAccessor key(env, j_key);\n        dictionary.insert(StringData(key), mixed);\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL\nJava_io_realm_internal_OsMap_nativePutNull(JNIEnv* env, jclass, jlong wrapper_ptr,\n                                           jstring j_key) {\n    try {\n        auto& wrapper = *reinterpret_cast<ObservableDictionaryWrapper*>(wrapper_ptr);\n        auto& dictionary = wrapper.collection();\n        JStringAccessor key(env, j_key);\n        dictionary.insert(StringData(key).data(), Mixed());\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL\nJava_io_realm_internal_OsMap_nativePutLong(JNIEnv* env, jclass, jlong wrapper_ptr,\n                                           jstring j_key, jlong j_value) {\n    try {\n        auto& wrapper = *reinterpret_cast<ObservableDictionaryWrapper*>(wrapper_ptr);\n        auto& dictionary = wrapper.collection();\n        JStringAccessor key(env, j_key);\n        JavaAccessorContext context(env);\n        dictionary.insert(context, StringData(key).data(), Any(j_value));\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL\nJava_io_realm_internal_OsMap_nativePutFloat(JNIEnv* env, jclass, jlong wrapper_ptr,\n                                            jstring j_key, jfloat j_value) {\n    try {\n        auto& wrapper = *reinterpret_cast<ObservableDictionaryWrapper*>(wrapper_ptr);\n        auto& dictionary = wrapper.collection();\n        JStringAccessor key(env, j_key);\n        JavaAccessorContext context(env);\n        dictionary.insert(context, StringData(key).data(), Any(j_value));\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL\nJava_io_realm_internal_OsMap_nativePutDouble(JNIEnv* env, jclass, jlong wrapper_ptr,\n                                             jstring j_key, jdouble j_value) {\n    try {\n        auto& wrapper = *reinterpret_cast<ObservableDictionaryWrapper*>(wrapper_ptr);\n        auto& dictionary = wrapper.collection();\n        JStringAccessor key(env, j_key);\n        JavaAccessorContext context(env);\n        dictionary.insert(context, StringData(key).data(), Any(j_value));\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL\nJava_io_realm_internal_OsMap_nativePutString(JNIEnv* env, jclass, jlong wrapper_ptr,\n                                             jstring j_key, jstring j_value) {\n    try {\n        auto& wrapper = *reinterpret_cast<ObservableDictionaryWrapper*>(wrapper_ptr);\n        auto& dictionary = wrapper.collection();\n        JStringAccessor key(env, j_key);\n        JStringAccessor value(env, j_value);\n        JavaAccessorContext context(env);\n        dictionary.insert(context, StringData(key).data(), Any(value));\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL\nJava_io_realm_internal_OsMap_nativePutBoolean(JNIEnv* env, jclass, jlong wrapper_ptr,\n                                              jstring j_key, jboolean j_value) {\n    try {\n        auto& wrapper = *reinterpret_cast<ObservableDictionaryWrapper*>(wrapper_ptr);\n        auto& dictionary = wrapper.collection();\n        JStringAccessor key(env, j_key);\n        JavaAccessorContext context(env);\n        dictionary.insert(context, StringData(key).data(), Any(j_value));\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL\nJava_io_realm_internal_OsMap_nativePutDate(JNIEnv* env, jclass, jlong wrapper_ptr,\n                                           jstring j_key, jlong j_value) {\n    try {\n        auto& wrapper = *reinterpret_cast<ObservableDictionaryWrapper*>(wrapper_ptr);\n        auto& dictionary = wrapper.collection();\n        JStringAccessor key(env, j_key);\n        JavaAccessorContext context(env);\n        dictionary.insert(context, StringData(key).data(), Any(j_value));\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL\nJava_io_realm_internal_OsMap_nativePutDecimal128(JNIEnv* env, jclass, jlong wrapper_ptr,\n                                                 jstring j_key, jlong j_high_value,\n                                                 jlong j_low_value) {\n    try {\n        auto& wrapper = *reinterpret_cast<ObservableDictionaryWrapper*>(wrapper_ptr);\n        auto& dictionary = wrapper.collection();\n        JStringAccessor key(env, j_key);\n        Decimal128::Bid128 raw {static_cast<uint64_t>(j_low_value), static_cast<uint64_t>(j_high_value)};\n        auto decimal128 = Decimal128(raw);\n        JavaAccessorContext context(env);\n        dictionary.insert(context, StringData(key).data(), Any(decimal128));\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL\nJava_io_realm_internal_OsMap_nativePutBinary(JNIEnv* env, jclass, jlong wrapper_ptr,\n                                             jstring j_key, jbyteArray j_value) {\n    try {\n        auto& wrapper = *reinterpret_cast<ObservableDictionaryWrapper*>(wrapper_ptr);\n        auto& dictionary = wrapper.collection();\n        JStringAccessor key(env, j_key);\n        JByteArrayAccessor data(env, j_value);\n        JavaAccessorContext context(env);\n        dictionary.insert(context, StringData(key).data(), Any(data));\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL\nJava_io_realm_internal_OsMap_nativePutObjectId(JNIEnv* env, jclass, jlong wrapper_ptr, jstring j_key,\n                                               jstring j_value) {\n    try {\n        auto& wrapper = *reinterpret_cast<ObservableDictionaryWrapper*>(wrapper_ptr);\n        auto& dictionary = wrapper.collection();\n        JStringAccessor key(env, j_key);\n        JStringAccessor data(env, j_value);\n\n        const ObjectId object_id = ObjectId(StringData(data).data());\n\n        JavaAccessorContext context(env);\n        dictionary.insert(context, StringData(key).data(), Any(object_id));\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL\nJava_io_realm_internal_OsMap_nativePutUUID(JNIEnv* env, jclass, jlong wrapper_ptr, jstring j_key,\n                                           jstring j_value) {\n    try {\n        auto& wrapper = *reinterpret_cast<ObservableDictionaryWrapper*>(wrapper_ptr);\n        auto& dictionary = wrapper.collection();\n        JStringAccessor key(env, j_key);\n        JStringAccessor value(env, j_value);\n        JavaAccessorContext context(env);\n        dictionary.insert(context, StringData(key).data(), Any(UUID(StringData(value).data())));\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL\nJava_io_realm_internal_OsMap_nativePutRow(JNIEnv* env, jclass, jlong wrapper_ptr, jstring j_key,\n                                          jlong j_obj_key) {\n    try {\n        auto& wrapper = *reinterpret_cast<ObservableDictionaryWrapper*>(wrapper_ptr);\n        auto& dictionary = wrapper.collection();\n        JStringAccessor key(env, j_key);\n        dictionary.insert(StringData(key).data(), ObjKey(j_obj_key));\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL\nJava_io_realm_internal_OsMap_nativeClear(JNIEnv* env, jclass, jlong wrapper_ptr) {\n    try {\n        auto& wrapper = *reinterpret_cast<ObservableDictionaryWrapper*>(wrapper_ptr);\n        auto& dictionary = wrapper.collection();\n        dictionary.remove_all();\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT jlong JNICALL\nJava_io_realm_internal_OsMap_nativeSize(JNIEnv* env, jclass, jlong wrapper_ptr) {\n    try {\n        auto& wrapper = *reinterpret_cast<ObservableDictionaryWrapper*>(wrapper_ptr);\n        auto& dictionary = wrapper.collection();\n        return dictionary.size();\n    }\n    CATCH_STD()\n    return reinterpret_cast<jlong>(nullptr);\n}\n\nJNIEXPORT jboolean JNICALL\nJava_io_realm_internal_OsMap_nativeContainsKey(JNIEnv* env, jclass, jlong wrapper_ptr,\n                                               jstring j_key) {\n    try {\n        auto& wrapper = *reinterpret_cast<ObservableDictionaryWrapper*>(wrapper_ptr);\n        auto& dictionary = wrapper.collection();\n        JStringAccessor key(env, j_key);\n        return dictionary.contains(StringData(key).data());\n    }\n    CATCH_STD()\n    return false;\n}\n\nJNIEXPORT jboolean JNICALL\nJava_io_realm_internal_OsMap_nativeIsValid(JNIEnv* env, jclass, jlong wrapper_ptr) {\n    try {\n        auto& wrapper = *reinterpret_cast<ObservableDictionaryWrapper*>(wrapper_ptr);\n        auto& dictionary = wrapper.collection();\n        return dictionary.is_valid();\n    }\n    CATCH_STD()\n    return false;\n}\n\nJNIEXPORT void JNICALL\nJava_io_realm_internal_OsMap_nativeRemove(JNIEnv* env, jclass, jlong wrapper_ptr,\n                                          jstring j_key) {\n    try {\n        auto& wrapper = *reinterpret_cast<ObservableDictionaryWrapper*>(wrapper_ptr);\n        auto& dictionary = wrapper.collection();\n        JStringAccessor key(env, j_key);\n        dictionary.erase(StringData(key));\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT jlong JNICALL\nJava_io_realm_internal_OsMap_nativeKeys(JNIEnv* env, jclass, jlong wrapper_ptr) {\n    try {\n        auto& wrapper = *reinterpret_cast<ObservableDictionaryWrapper*>(wrapper_ptr);\n        auto& dictionary = wrapper.collection();\n        const Results& key_results = dictionary.get_keys();\n\n        // Return an ObservableCollectionWrapper as these are results!\n        auto results_wrapper = new ObservableCollectionWrapper(key_results);\n        return reinterpret_cast<jlong>(results_wrapper);\n    }\n    CATCH_STD()\n    return reinterpret_cast<jlong>(nullptr);\n}\n\nJNIEXPORT jlong JNICALL\nJava_io_realm_internal_OsMap_nativeValues(JNIEnv* env, jclass, jlong wrapper_ptr) {\n    try {\n        auto& wrapper = *reinterpret_cast<ObservableDictionaryWrapper*>(wrapper_ptr);\n        auto& dictionary = wrapper.collection();\n        const Results& value_results = dictionary.get_values();\n\n        // Return an ObservableCollectionWrapper as these are results!\n        auto results_wrapper = new ObservableCollectionWrapper(value_results);\n        return reinterpret_cast<jlong>(results_wrapper);\n    }\n    CATCH_STD()\n    return reinterpret_cast<jlong>(nullptr);\n}\n\nJNIEXPORT jlong JNICALL\nJava_io_realm_internal_OsMap_nativeFreeze(JNIEnv* env, jclass, jlong wrapper_ptr,\n                                          jlong realm_ptr) {\n    try {\n        auto& wrapper = *reinterpret_cast<ObservableDictionaryWrapper*>(wrapper_ptr);\n        auto& dictionary = wrapper.collection();\n        std::shared_ptr<Realm>& shared_realm_ptr = *reinterpret_cast<std::shared_ptr<Realm>*>(realm_ptr);\n        object_store::Dictionary frozen_dictionary = dictionary.freeze(shared_realm_ptr);\n        return reinterpret_cast<jlong>(new ObservableDictionaryWrapper(frozen_dictionary));\n    }\n    CATCH_STD()\n    return reinterpret_cast<jlong>(nullptr);\n}\n\nJNIEXPORT jlong JNICALL\nJava_io_realm_internal_OsMap_nativeCreateAndPutEmbeddedObject(JNIEnv* env, jclass,\n                                                              jlong wrapper_ptr,\n                                                              jstring j_key) {\n    try {\n        auto& wrapper = *reinterpret_cast<ObservableDictionaryWrapper*>(wrapper_ptr);\n        auto& dictionary = wrapper.collection();\n        auto& realm = dictionary.get_realm();\n        auto& object_schema = dictionary.get_object_schema();\n\n        JStringAccessor key(env, j_key);\n        JavaContext context(env, realm, object_schema);\n\n        dictionary.insert(context, StringData(key), JavaValue(std::map<ColKey, JavaValue>()), CreatePolicy::Skip);\n        const Mixed& mixed = dictionary.get_any(StringData(key));\n        return reinterpret_cast<jlong>(mixed.get<ObjKey>().value);\n    }\n    CATCH_STD()\n    return reinterpret_cast<jlong>(nullptr);\n}\n\nJNIEXPORT jobjectArray JNICALL\nJava_io_realm_internal_OsMap_nativeGetEntryForModel(JNIEnv* env, jclass, jlong wrapper_ptr, jint j_pos) {\n    try {\n        auto& wrapper = *reinterpret_cast<ObservableDictionaryWrapper*>(wrapper_ptr);\n        auto& dictionary = wrapper.collection();\n        const std::pair<StringData, Mixed>& pair = dictionary.get_pair(j_pos);\n        const StringData& key = pair.first;\n        const Mixed& mixed = pair.second;\n\n        jobjectArray pair_array = env->NewObjectArray(2, JavaClassGlobalDef::java_lang_object(), NULL);\n        env->SetObjectArrayElement(pair_array, 0, to_jstring(env, key));\n        if (mixed.is_null()) {\n            env->SetObjectArrayElement(pair_array, 1, JavaClassGlobalDef::new_long(env, io_realm_internal_OsMap_NOT_FOUND));\n        } else {\n            env->SetObjectArrayElement(pair_array, 1, JavaClassGlobalDef::new_long(env, mixed.get<ObjKey>().value));\n        }\n        return pair_array;\n    }\n    CATCH_STD()\n    return nullptr;\n}\n\nJNIEXPORT jobjectArray JNICALL\nJava_io_realm_internal_OsMap_nativeGetEntryForRealmAny(JNIEnv* env, jclass, jlong wrapper_ptr, jint j_pos) {\n    try {\n        auto& wrapper = *reinterpret_cast<ObservableDictionaryWrapper*>(wrapper_ptr);\n        auto& dictionary = wrapper.collection();\n        const std::pair<StringData, Mixed>& pair = dictionary.get_pair(j_pos);\n        const StringData& key = pair.first;\n        const Mixed& mixed = pair.second;\n\n        jlong mixed_ptr = reinterpret_cast<jlong>(new JavaValue(from_mixed(mixed)));\n        jobjectArray pair_array = env->NewObjectArray(2, JavaClassGlobalDef::java_lang_object(), NULL);\n        env->SetObjectArrayElement(pair_array, 0, to_jstring(env, key));\n        env->SetObjectArrayElement(pair_array, 1, JavaClassGlobalDef::new_long(env, mixed_ptr));\n        return pair_array;\n    }\n    CATCH_STD()\n    return nullptr;\n}\n\nJNIEXPORT jobjectArray JNICALL\nJava_io_realm_internal_OsMap_nativeGetEntryForPrimitive(JNIEnv* env, jclass, jlong wrapper_ptr,\n                                                        jint j_pos) {\n    try {\n        auto& wrapper = *reinterpret_cast<ObservableDictionaryWrapper*>(wrapper_ptr);\n        auto& dictionary = wrapper.collection();\n        const std::pair<StringData, Mixed>& pair = dictionary.get_pair(j_pos);\n        const StringData& key = pair.first;\n        const Mixed& mixed = pair.second;\n\n        jobjectArray pair_array = env->NewObjectArray(2, JavaClassGlobalDef::java_lang_object(), NULL);\n        env->SetObjectArrayElement(pair_array, 0, to_jstring(env, key));\n\n        if (mixed.is_null()) {\n            env->SetObjectArrayElement(pair_array, 1, NULL);\n        } else {\n            const DataType& type = mixed.get_type();\n            switch (type) {\n                case DataType::Type::Int:\n                    env->SetObjectArrayElement(pair_array, 1, JavaClassGlobalDef::new_long(env, mixed.get_int()));\n                    break;\n                case DataType::Type::Double:\n                    env->SetObjectArrayElement(pair_array, 1, JavaClassGlobalDef::new_double(env, mixed.get_double()));\n                    break;\n                case DataType::Type::Bool:\n                    env->SetObjectArrayElement(pair_array, 1, JavaClassGlobalDef::new_boolean(env, mixed.get_bool()));\n                    break;\n                case DataType::Type::String:\n                    env->SetObjectArrayElement(pair_array, 1, to_jstring(env, mixed.get_string()));\n                    break;\n                case DataType::Type::Binary:\n                    env->SetObjectArrayElement(pair_array, 1, JavaClassGlobalDef::new_byte_array(env, mixed.get_binary()));\n                    break;\n                case DataType::Type::Float:\n                    env->SetObjectArrayElement(pair_array, 1, JavaClassGlobalDef::new_float(env, mixed.get_float()));\n                    break;\n                case DataType::Type::UUID:\n                    env->SetObjectArrayElement(pair_array, 1, JavaClassGlobalDef::new_uuid(env, mixed.get_uuid()));\n                    break;\n                case DataType::Type::ObjectId:\n                    env->SetObjectArrayElement(pair_array, 1, JavaClassGlobalDef::new_object_id(env, mixed.get_object_id()));\n                    break;\n                case DataType::Type::Timestamp:\n                    env->SetObjectArrayElement(pair_array, 1, JavaClassGlobalDef::new_date(env, mixed.get_timestamp()));\n                    break;\n                case DataType::Type::Decimal:\n                    env->SetObjectArrayElement(pair_array, 1, JavaClassGlobalDef::new_decimal128(env, mixed.get_decimal()));\n                    break;\n                default:\n                    throw std::logic_error(\"'getEntryForPrimitive' method only suitable for int, double, boolean, String, byte[], float, UUID, Decimal128 and ObjectId.\");\n            }\n        }\n        return pair_array;\n    }\n    CATCH_STD()\n    return nullptr;\n}\n\nJNIEXPORT jboolean JNICALL\nJava_io_realm_internal_OsMap_nativeContainsNull(JNIEnv* env, jclass, jlong wrapper_ptr) {\n    try {\n        auto& wrapper = *reinterpret_cast<ObservableDictionaryWrapper*>(wrapper_ptr);\n        auto& dictionary = wrapper.collection();\n        size_t find_result = dictionary.find_any(Mixed());\n        if (find_result != realm::not_found) {\n            return true;\n        }\n    }\n    CATCH_STD()\n    return false;\n}\n\nJNIEXPORT jboolean JNICALL\nJava_io_realm_internal_OsMap_nativeContainsLong(JNIEnv* env, jclass, jlong wrapper_ptr,\n                                                jlong j_value) {\n    try {\n        auto& wrapper = *reinterpret_cast<ObservableDictionaryWrapper*>(wrapper_ptr);\n        auto& dictionary = wrapper.collection();\n        size_t find_result = dictionary.find_any(Mixed(j_value));\n        if (find_result != realm::not_found) {\n            return true;\n        }\n    }\n    CATCH_STD()\n    return false;\n}\n\nJNIEXPORT jboolean JNICALL\nJava_io_realm_internal_OsMap_nativeContainsDouble(JNIEnv* env, jclass, jlong wrapper_ptr,\n                                                  jdouble j_value) {\n    try {\n        auto& wrapper = *reinterpret_cast<ObservableDictionaryWrapper*>(wrapper_ptr);\n        auto& dictionary = wrapper.collection();\n        size_t find_result = dictionary.find_any(Mixed(j_value));\n        if (find_result != realm::not_found) {\n            return true;\n        }\n    }\n    CATCH_STD()\n    return false;\n}\n\nJNIEXPORT jboolean JNICALL\nJava_io_realm_internal_OsMap_nativeContainsBoolean(JNIEnv* env, jclass, jlong wrapper_ptr,\n                                                   jboolean j_value) {\n    try {\n        auto& wrapper = *reinterpret_cast<ObservableDictionaryWrapper*>(wrapper_ptr);\n        auto& dictionary = wrapper.collection();\n        size_t find_result = dictionary.find_any(Mixed(bool(j_value)));\n        if (find_result != realm::not_found) {\n            return true;\n        }\n    }\n    CATCH_STD()\n    return false;\n}\n\nJNIEXPORT jboolean JNICALL\nJava_io_realm_internal_OsMap_nativeContainsString(JNIEnv* env, jclass, jlong wrapper_ptr,\n                                                  jstring j_value) {\n    try {\n        auto& wrapper = *reinterpret_cast<ObservableDictionaryWrapper*>(wrapper_ptr);\n        auto& dictionary = wrapper.collection();\n        JStringAccessor key(env, j_value);\n        size_t find_result = dictionary.find_any(Mixed(StringData(key)));\n        if (find_result != realm::not_found) {\n            return true;\n        }\n    }\n    CATCH_STD()\n    return false;\n}\n\nJNIEXPORT jboolean JNICALL\nJava_io_realm_internal_OsMap_nativeContainsBinary(JNIEnv* env, jclass, jlong wrapper_ptr,\n                                                  jbyteArray j_value) {\n    try {\n        auto& wrapper = *reinterpret_cast<ObservableDictionaryWrapper*>(wrapper_ptr);\n        auto& dictionary = wrapper.collection();\n        const OwnedBinaryData& data = OwnedBinaryData(JByteArrayAccessor(env, j_value).transform<BinaryData>());\n        size_t find_result = dictionary.find_any(Mixed(data.get()));\n        if (find_result != realm::not_found) {\n            return true;\n        }\n    }\n    CATCH_STD()\n    return false;\n}\n\nJNIEXPORT jboolean JNICALL\nJava_io_realm_internal_OsMap_nativeContainsFloat(JNIEnv* env, jclass, jlong wrapper_ptr,\n                                                 jfloat j_value) {\n    try {\n        auto& wrapper = *reinterpret_cast<ObservableDictionaryWrapper*>(wrapper_ptr);\n        auto& dictionary = wrapper.collection();\n        size_t find_result = dictionary.find_any(Mixed(j_value));\n        if (find_result != realm::not_found) {\n            return true;\n        }\n    }\n    CATCH_STD()\n    return false;\n}\n\nJNIEXPORT jboolean JNICALL\nJava_io_realm_internal_OsMap_nativeContainsObjectId(JNIEnv* env, jclass, jlong wrapper_ptr,\n                                                    jstring j_value) {\n    try {\n        auto& wrapper = *reinterpret_cast<ObservableDictionaryWrapper*>(wrapper_ptr);\n        auto& dictionary = wrapper.collection();\n        JStringAccessor data(env, j_value);\n        const ObjectId object_id = ObjectId(StringData(data).data());\n        size_t find_result = dictionary.find_any(Mixed(object_id));\n        if (find_result != realm::not_found) {\n            return true;\n        }\n    }\n    CATCH_STD()\n    return false;\n}\n\nJNIEXPORT jboolean JNICALL\nJava_io_realm_internal_OsMap_nativeContainsUUID(JNIEnv* env, jclass, jlong wrapper_ptr,\n                                                jstring j_value) {\n    try {\n        auto& wrapper = *reinterpret_cast<ObservableDictionaryWrapper*>(wrapper_ptr);\n        auto& dictionary = wrapper.collection();\n        JStringAccessor value(env, j_value);\n        const UUID& uuid = UUID(StringData(value).data());\n        size_t find_result = dictionary.find_any(Mixed(uuid));\n        if (find_result != realm::not_found) {\n            return true;\n        }\n    }\n    CATCH_STD()\n    return false;\n}\n\nJNIEXPORT jboolean JNICALL\nJava_io_realm_internal_OsMap_nativeContainsDate(JNIEnv* env, jclass, jlong wrapper_ptr,\n                                                jlong j_value) {\n    try {\n        auto& wrapper = *reinterpret_cast<ObservableDictionaryWrapper*>(wrapper_ptr);\n        auto& dictionary = wrapper.collection();\n        realm::Timestamp timestamp = from_milliseconds(j_value);\n        size_t find_result = dictionary.find_any(Mixed(timestamp));\n        if (find_result != realm::not_found) {\n            return true;\n        }\n    }\n    CATCH_STD()\n    return false;\n}\n\nJNIEXPORT jboolean JNICALL\nJava_io_realm_internal_OsMap_nativeContainsDecimal128(JNIEnv* env, jclass, jlong wrapper_ptr,\n                                                      jlong j_high_value, jlong j_low_value) {\n    try {\n        auto& wrapper = *reinterpret_cast<ObservableDictionaryWrapper*>(wrapper_ptr);\n        auto& dictionary = wrapper.collection();\n        Decimal128::Bid128 raw {static_cast<uint64_t>(j_low_value), static_cast<uint64_t>(j_high_value)};\n        auto decimal128 = Decimal128(raw);\n        size_t find_result = dictionary.find_any(Mixed(decimal128));\n        if (find_result != realm::not_found) {\n            return true;\n        }\n    }\n    CATCH_STD()\n    return false;\n}\n\nJNIEXPORT jboolean JNICALL\nJava_io_realm_internal_OsMap_nativeContainsRealmAny(JNIEnv* env, jclass, jlong wrapper_ptr,\n                                                 jlong mixed_ptr) {\n    try {\n        auto& wrapper = *reinterpret_cast<ObservableDictionaryWrapper*>(wrapper_ptr);\n        auto& dictionary = wrapper.collection();\n        auto mixed_java_value = *reinterpret_cast<JavaValue*>(mixed_ptr);\n        const Mixed& mixed = mixed_java_value.to_mixed();\n        size_t find_result = dictionary.find_any(mixed);\n        if (find_result != realm::not_found) {\n            return true;\n        }\n    }\n    CATCH_STD();\n    return false;\n}\n\nJNIEXPORT jboolean JNICALL\nJava_io_realm_internal_OsMap_nativeContainsRealmModel(JNIEnv* env, jclass, jlong wrapper_ptr,\n                                                      jlong j_obj_key, jlong j_table_ptr) {\n    try {\n        auto& wrapper = *reinterpret_cast<ObservableDictionaryWrapper*>(wrapper_ptr);\n        auto& dictionary = wrapper.collection();\n\n        TableRef target_table = TBL_REF(j_table_ptr);\n        ObjKey object_key(j_obj_key);\n        ObjLink object_link(target_table->get_key(), object_key);\n\n        const Mixed& mixed = Mixed(object_link);\n        size_t find_result = dictionary.find_any(mixed);\n        if (find_result != realm::not_found) {\n            return true;\n        }\n    }\n    CATCH_STD();\n    return false;\n}\n\nJNIEXPORT void JNICALL\nJava_io_realm_internal_OsMap_nativeStartListening(JNIEnv* env, jclass, jlong wrapper_ptr,\n                                                  jobject j_observable_map) {\n    try {\n        auto wrapper = reinterpret_cast<ObservableDictionaryWrapper*>(wrapper_ptr);\n        wrapper->start_listening(env, j_observable_map);\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL\nJava_io_realm_internal_OsMap_nativeStopListening(JNIEnv* env, jclass, jlong wrapper_ptr) {\n    try {\n        auto wrapper = reinterpret_cast<ObservableDictionaryWrapper*>(wrapper_ptr);\n        wrapper->stop_listening();\n    }\n    CATCH_STD()\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/cpp/io_realm_internal_OsMapChangeSet.cpp",
    "content": "/*\n * Copyright 2021 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#include \"io_realm_internal_OsMapChangeSet.h\"\n\n#include <realm/object-store/dictionary.hpp>\n\n#include \"util.hpp\"\n#include \"java_class_global_def.hpp\"\n\nusing namespace realm;\nusing namespace realm::_impl;\n\ninline jobjectArray generate_change_set(JNIEnv* env, const std::vector<Mixed>& change_set) {\n    unsigned long insertions_size = change_set.size();\n    jobjectArray ret_array = env->NewObjectArray(insertions_size, JavaClassGlobalDef::java_lang_string(), NULL);\n    for (unsigned long i = 0; i < insertions_size; i++) {\n        Mixed mixed_key = change_set[i];\n        const StringData& key = mixed_key.get_string();\n        env->SetObjectArrayElement(ret_array, i, to_jstring(env, key));\n    }\n\n    return ret_array;\n}\n\nvoid finalize_changeset(jlong ptr) {\n    delete reinterpret_cast<DictionaryChangeSet*>(ptr);\n}\n\nJNIEXPORT jlong JNICALL\nJava_io_realm_internal_OsMapChangeSet_nativeGetFinalizerPtr(JNIEnv*, jclass) {\n    return reinterpret_cast<jlong>(&finalize_changeset);\n}\n\nJNIEXPORT jobjectArray JNICALL\nJava_io_realm_internal_OsMapChangeSet_nativeGetStringKeyDeletions(JNIEnv* env, jclass,\n                                                             jlong native_ptr) {\n    DictionaryChangeSet& change_set = *reinterpret_cast<DictionaryChangeSet*>(native_ptr);\n    return generate_change_set(env, change_set.deletions);\n}\n\nJNIEXPORT jobjectArray JNICALL\nJava_io_realm_internal_OsMapChangeSet_nativeGetStringKeyInsertions(JNIEnv* env, jclass,\n                                                                   jlong native_ptr) {\n    DictionaryChangeSet& change_set = *reinterpret_cast<DictionaryChangeSet*>(native_ptr);\n    return generate_change_set(env, change_set.insertions);\n}\n\nJNIEXPORT jobjectArray JNICALL\nJava_io_realm_internal_OsMapChangeSet_nativeGetStringKeyModifications(JNIEnv* env, jclass,\n                                                                      jlong native_ptr) {\n    DictionaryChangeSet& change_set = *reinterpret_cast<DictionaryChangeSet*>(native_ptr);\n    return generate_change_set(env, change_set.modifications);\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/cpp/io_realm_internal_OsObject.cpp",
    "content": "/*\n * Copyright 2017 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#include \"io_realm_internal_OsObject.h\"\n\n#include <realm/object-store/object_schema.hpp>\n#include <realm/object-store/object.hpp>\n#include <realm/object-store/shared_realm.hpp>\n\n#include \"util.hpp\"\n#include \"java_class_global_def.hpp\"\n\n#include \"jni_util/java_global_weak_ref.hpp\"\n#include \"jni_util/java_method.hpp\"\n#include \"jni_util/java_class.hpp\"\n#include \"jni_util/java_exception_thrower.hpp\"\n\nusing namespace realm;\nusing namespace realm::jni_util;\nusing namespace realm::_impl;\n\nstatic const char* PK_CONSTRAINT_EXCEPTION_CLASS = \"io/realm/exceptions/RealmPrimaryKeyConstraintException\";\nstatic const char* PK_EXCEPTION_MSG_FORMAT = \"Primary key value already exists: %1 .\";\n\n// We need to control the life cycle of Object, weak ref of Java OsObject and the NotificationToken.\n// Wrap all three together, so when the Java object gets GCed, all three of them will be invalidated.\nstruct ObjectWrapper {\n    JavaGlobalWeakRef m_row_object_weak_ref;\n    NotificationToken m_notification_token;\n    realm::Object m_object;\n\n    ObjectWrapper(realm::Object& object)\n        : m_row_object_weak_ref()\n        , m_notification_token()\n        , m_object(std::move(object))\n    {\n    }\n\n    ObjectWrapper(ObjectWrapper&&) = delete;\n    ObjectWrapper& operator=(ObjectWrapper&&) = delete;\n\n    ObjectWrapper(ObjectWrapper const&) = delete;\n    ObjectWrapper& operator=(ObjectWrapper const&) = delete;\n\n    ~ObjectWrapper()\n    {\n    }\n};\n\nstruct ChangeCallback {\n    ChangeCallback(ObjectWrapper* wrapper, JavaMethod notify_change_listeners)\n        : m_wrapper(wrapper),\n        m_notify_change_listeners_method(notify_change_listeners)\n    {\n    }\n\n    void parse_fields(JNIEnv* env, CollectionChangeSet const& change_set)\n    {\n        if (m_field_names_array) {\n            return;\n        }\n\n        if (!change_set.deletions.empty()) {\n            m_deleted = true;\n            return;\n        }\n\n        // The local ref of jstring needs to be released to avoid reach the local ref table size limitation.\n        std::vector<JavaGlobalRefByMove> field_names;\n        auto table = m_wrapper->m_object.get_obj().get_table();\n        for (const auto& col: change_set.columns) {\n            if (col.second.empty()) {\n                continue;\n            }\n            // FIXME: After full integration of the OS schema, parse the column name from\n            // wrapper->m_object.get_object_schema() will be faster.\n            field_names.push_back(JavaGlobalRefByMove(env, to_jstring(env, table->get_column_name(ColKey(col.first))), true));\n        }\n        m_field_names_array = env->NewObjectArray(field_names.size(), JavaClassGlobalDef::java_lang_string(), 0);\n        for (size_t i = 0; i < field_names.size(); ++i) {\n            env->SetObjectArrayElement(m_field_names_array, i, field_names[i].get());\n        }\n    }\n\n    JNIEnv* check_env()\n    {\n        JNIEnv* env = JniUtils::get_env(false);\n        if (!env || env->ExceptionCheck()) {\n            // JVM detached or java exception has been thrown before.\n            return nullptr;\n        }\n        return env;\n    }\n\n    void before(CollectionChangeSet const& change_set)\n    {\n        JNIEnv* env = check_env();\n        if (!env) {\n            return;\n        }\n\n        parse_fields(env, change_set);\n    }\n\n    void after(CollectionChangeSet const& change_set)\n    {\n        JNIEnv* env = check_env();\n        if (!env) {\n            return;\n        }\n        if (change_set.empty()) {\n            return;\n        }\n\n        parse_fields(env, change_set);\n        m_wrapper->m_row_object_weak_ref.call_with_local_ref(env, [&](JNIEnv*, jobject row_obj) {\n            env->CallVoidMethod(row_obj, m_notify_change_listeners_method, m_deleted ? nullptr : m_field_names_array);\n        });\n        m_field_names_array = nullptr;\n        m_deleted = false;\n    }\n\n    void error(std::exception_ptr err)\n    {\n        if (err) {\n            try {\n                std::rethrow_exception(err);\n            }\n            catch (const std::exception& e) {\n                Log::e(\"Caught exception in object change callback %1\", e.what());\n            }\n        }\n    }\n\nprivate:\n    ObjectWrapper* m_wrapper;\n    bool m_deleted = false;\n    jobjectArray m_field_names_array = nullptr;\n    JavaMethod m_notify_change_listeners_method;\n};\n\nstatic void finalize_object(jlong ptr)\n{\n    delete reinterpret_cast<ObjectWrapper*>(ptr);\n}\n\nstatic inline Obj do_create_row_with_primary_key(JNIEnv* env, jlong shared_realm_ptr, jlong table_ref_ptr,\n                                                    jlong pk_column_key, jlong pk_value, jboolean is_pk_null)\n{\n    auto& shared_realm = *(reinterpret_cast<SharedRealm*>(shared_realm_ptr));\n    TableRef table = TBL_REF(table_ref_ptr);\n    ColKey col_key(pk_column_key);\n    shared_realm->verify_in_write(); // throws\n    if (is_pk_null && !COL_NULLABLE(env, table, pk_column_key)) { // throws\n        return Obj();\n    }\n\n    if (is_pk_null) {\n\n        if (bool(table->find_first_null(col_key))) {\n            THROW_JAVA_EXCEPTION(env, PK_CONSTRAINT_EXCEPTION_CLASS, util::format(PK_EXCEPTION_MSG_FORMAT, \"'null'\"));\n        }\n    }\n    else {\n        if (bool(table->find_first_int(col_key, pk_value))) {\n            THROW_JAVA_EXCEPTION(env, PK_CONSTRAINT_EXCEPTION_CLASS, util::format(PK_EXCEPTION_MSG_FORMAT, pk_value));\n        }\n    }\n\n    Mixed pk_val = is_pk_null ? Mixed() : Mixed(util::Optional<int64_t>(pk_value));\n    return table->create_object_with_primary_key(pk_val);\n}\n\nstatic inline Obj do_create_row_with_primary_key(JNIEnv* env, jlong shared_realm_ptr, jlong table_ref_ptr,\n                                                    jlong pk_column_key, jstring pk_value)\n{\n    auto& shared_realm = *(reinterpret_cast<SharedRealm*>(shared_realm_ptr));\n    TableRef table = TBL_REF(table_ref_ptr);\n    ColKey col_key(pk_column_key);\n    shared_realm->verify_in_write(); // throws\n    JStringAccessor str_accessor(env, pk_value); // throws\n    if (!pk_value && !COL_NULLABLE(env, table, pk_column_key)) { // throws\n        return Obj();\n    }\n\n    if (pk_value) {\n        if (bool(table->find_first_string(col_key, str_accessor))) {\n            THROW_JAVA_EXCEPTION(env, PK_CONSTRAINT_EXCEPTION_CLASS,\n                                 util::format(PK_EXCEPTION_MSG_FORMAT, str_accessor.operator std::string()));\n        }\n    }\n    else {\n        if (bool(table->find_first_null(col_key))) {\n            THROW_JAVA_EXCEPTION(env, PK_CONSTRAINT_EXCEPTION_CLASS, util::format(PK_EXCEPTION_MSG_FORMAT, \"'null'\"));\n        }\n    }\n    return table->create_object_with_primary_key(StringData(str_accessor));\n}\n\nstatic inline Obj do_create_row_with_object_id_primary_key(JNIEnv* env, jlong shared_realm_ptr, jlong table_ref_ptr,\n                                                            jlong pk_column_key, jstring pk_value)\n{\n    auto& shared_realm = *(reinterpret_cast<SharedRealm*>(shared_realm_ptr));\n    TableRef table = TBL_REF(table_ref_ptr);\n    ColKey col_key(pk_column_key);\n    shared_realm->verify_in_write(); // throws\n    JStringAccessor str_accessor(env, pk_value); // throws\n    if (!pk_value && !COL_NULLABLE(env, table, pk_column_key)) { // throws\n        return Obj();\n    }\n\n    if (pk_value) {\n        auto objectId = ObjectId(StringData(str_accessor).data());\n        if (bool(table->find_first_object_id(col_key, objectId))) {\n            THROW_JAVA_EXCEPTION(env, PK_CONSTRAINT_EXCEPTION_CLASS,\n                                 util::format(PK_EXCEPTION_MSG_FORMAT, str_accessor.operator std::string()));\n        }\n\n        return table->create_object_with_primary_key(objectId);\n    }\n    else {\n        if (bool(table->find_first_null(col_key))) {\n            THROW_JAVA_EXCEPTION(env, PK_CONSTRAINT_EXCEPTION_CLASS, util::format(PK_EXCEPTION_MSG_FORMAT, \"'null'\"));\n        }\n        return table->create_object_with_primary_key(realm::util::Optional<realm::ObjectId>());\n    }\n}\n\nstatic inline Obj do_create_row_with_uuid_primary_key(JNIEnv* env, jlong shared_realm_ptr, jlong table_ref_ptr,\n                                                           jlong pk_column_key, jstring pk_value)\n{\n    auto& shared_realm = *(reinterpret_cast<SharedRealm*>(shared_realm_ptr));\n    TableRef table = TBL_REF(table_ref_ptr);\n    ColKey col_key(pk_column_key);\n    shared_realm->verify_in_write(); // throws\n    JStringAccessor str_accessor(env, pk_value); // throws\n    if (!pk_value && !COL_NULLABLE(env, table, pk_column_key)) { //throws\n        return Obj();\n    }\n\n    if (pk_value) {\n        auto uuid = UUID(StringData(str_accessor).data());\n        if (bool(table->find_first_uuid(col_key, uuid))) {\n            THROW_JAVA_EXCEPTION(env, PK_CONSTRAINT_EXCEPTION_CLASS,\n                                 util::format(PK_EXCEPTION_MSG_FORMAT, str_accessor.operator std::string()));\n        }\n\n        return table->create_object_with_primary_key(uuid);\n    }\n    else {\n        if (bool(table->find_first_null(col_key))) {\n            THROW_JAVA_EXCEPTION(env, PK_CONSTRAINT_EXCEPTION_CLASS, util::format(PK_EXCEPTION_MSG_FORMAT, \"'null'\"));\n        }\n        return table->create_object_with_primary_key(realm::util::Optional<realm::UUID>());\n    }\n}\n\n\nJNIEXPORT jlong JNICALL Java_io_realm_internal_OsObject_nativeGetFinalizerPtr(JNIEnv*, jclass)\n{\n    return reinterpret_cast<jlong>(&finalize_object);\n}\n\nJNIEXPORT jlong JNICALL Java_io_realm_internal_OsObject_nativeCreate(JNIEnv*, jclass, jlong shared_realm_ptr,\n                                                                     jlong obj_ptr)\n{\n    // FIXME: Currently OsObject is only used for object notifications. Since the Object Store's schema has not been\n    // fully integrated with realm-java, we pass a dummy ObjectSchema to create Object.\n    static const ObjectSchema dummy_object_schema;\n    auto& shared_realm = *(reinterpret_cast<SharedRealm*>(shared_realm_ptr));\n    auto& obj = *(reinterpret_cast<Obj*>(obj_ptr));\n    Object object(shared_realm, dummy_object_schema, obj); // no throw\n    auto wrapper = new ObjectWrapper(object);              // no throw\n    return reinterpret_cast<jlong>(wrapper);\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_OsObject_nativeStartListening(JNIEnv* env, jobject instance,\n                                                                            jlong native_ptr)\n{\n    try {\n        auto wrapper = reinterpret_cast<ObjectWrapper*>(native_ptr);\n        if (!wrapper->m_row_object_weak_ref) {\n            wrapper->m_row_object_weak_ref = JavaGlobalWeakRef(env, instance);\n        }\n\n        static JavaClass os_object_class(env, \"io/realm/internal/OsObject\");\n        static JavaMethod notify_change_listeners(env, os_object_class, \"notifyChangeListeners\",\n                                                  \"([Ljava/lang/String;)V\");\n        // The wrapper pointer will be used in the callback. But it should never become an invalid pointer when the\n        // notification block gets called. This should be guaranteed by the Object Store that after the notification\n        // token is destroyed, the block shouldn't be called.\n        wrapper->m_notification_token = wrapper->m_object.add_notification_callback(ChangeCallback(wrapper, notify_change_listeners));\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_OsObject_nativeStopListening(JNIEnv* env, jobject, jlong native_ptr)\n{\n    try {\n        auto wrapper = reinterpret_cast<ObjectWrapper*>(native_ptr);\n        wrapper->m_notification_token = {};\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT jlong JNICALL Java_io_realm_internal_OsObject_nativeCreateRow(JNIEnv* env, jclass, jlong table_ref_ptr)\n{\n    try {\n        TableRef table = TBL_REF(table_ref_ptr);\n        Obj obj = table->create_object();\n        return (jlong)(obj.get_key().value);\n    }\n    CATCH_STD()\n    return -1;\n}\n\nJNIEXPORT jlong JNICALL Java_io_realm_internal_OsObject_nativeCreateNewObject(JNIEnv* env, jclass, jlong table_ref_ptr)\n{\n    try {\n        TableRef table = TBL_REF(table_ref_ptr);\n        Obj* obj = new Obj(table->create_object());\n        return reinterpret_cast<jlong>(obj);\n    }\n    CATCH_STD()\n    return 0;\n}\n\nJNIEXPORT jlong JNICALL Java_io_realm_internal_OsObject_nativeCreateNewObjectWithLongPrimaryKey(\n    JNIEnv* env, jclass, jlong shared_realm_ptr, jlong table_ref_ptr, jlong pk_column_ndx, jlong pk_value,\n    jboolean is_pk_null)\n{\n    try {\n        Obj obj =\n            do_create_row_with_primary_key(env, shared_realm_ptr, table_ref_ptr, pk_column_ndx, pk_value, is_pk_null);\n        if (bool(obj)) {\n            return reinterpret_cast<jlong>(new Obj(obj));\n        }\n    }\n    CATCH_STD()\n    return 0;\n}\n\nJNIEXPORT jlong JNICALL Java_io_realm_internal_OsObject_nativeCreateRowWithLongPrimaryKey(\n    JNIEnv* env, jclass, jlong shared_realm_ptr, jlong table_ref_ptr, jlong pk_column_ndx, jlong pk_value,\n    jboolean is_pk_null)\n{\n    try {\n        Obj obj = do_create_row_with_primary_key(env, shared_realm_ptr, table_ref_ptr, pk_column_ndx, pk_value, is_pk_null);\n        return (jlong)(obj.get_key().value);\n    }\n    CATCH_STD()\n    return realm::npos;\n}\n\nJNIEXPORT jlong JNICALL Java_io_realm_internal_OsObject_nativeCreateNewObjectWithStringPrimaryKey(\n    JNIEnv* env, jclass, jlong shared_realm_ptr, jlong table_ref_ptr, jlong pk_column_ndx, jstring pk_value)\n{\n    try {\n        Obj obj = do_create_row_with_primary_key(env, shared_realm_ptr, table_ref_ptr, pk_column_ndx, pk_value);\n        if (bool(obj)) {\n            return reinterpret_cast<jlong>(new Obj(obj));\n        }\n    }\n    CATCH_STD()\n    return 0;\n}\n\nJNIEXPORT jlong JNICALL Java_io_realm_internal_OsObject_nativeCreateRowWithStringPrimaryKey(\n    JNIEnv* env, jclass, jlong shared_realm_ptr, jlong table_ref_ptr, jlong pk_column_ndx, jstring pk_value)\n{\n    try {\n        Obj obj = do_create_row_with_primary_key(env, shared_realm_ptr, table_ref_ptr, pk_column_ndx, pk_value);\n        return (jlong)(obj.get_key().value);\n    }\n    CATCH_STD()\n    return realm::npos;\n}\n\nJNIEXPORT jlong JNICALL Java_io_realm_internal_OsObject_nativeCreateRowWithObjectIdPrimaryKey(\n        JNIEnv* env, jclass, jlong shared_realm_ptr, jlong table_ref_ptr, jlong pk_column_ndx, jstring pk_value)\n{\n    try {\n        Obj obj = do_create_row_with_object_id_primary_key(env, shared_realm_ptr, table_ref_ptr, pk_column_ndx, pk_value);\n        return (jlong)(obj.get_key().value);\n    }\n    CATCH_STD()\n    return realm::npos;\n}\n\nJNIEXPORT jlong JNICALL Java_io_realm_internal_OsObject_nativeCreateNewObjectWithObjectIdPrimaryKey(\n        JNIEnv* env, jclass, jlong shared_realm_ptr, jlong table_ref_ptr, jlong pk_column_ndx, jstring pk_value)\n{\n    try {\n        Obj obj = do_create_row_with_object_id_primary_key(env, shared_realm_ptr, table_ref_ptr, pk_column_ndx, pk_value);\n        if (bool(obj)) {\n            return reinterpret_cast<jlong>(new Obj(obj));\n        }\n    }\n    CATCH_STD()\n    return 0;\n}\n\nJNIEXPORT jlong JNICALL Java_io_realm_internal_OsObject_nativeCreateRowWithUUIDPrimaryKey(\n        JNIEnv* env, jclass, jlong shared_realm_ptr, jlong table_ref_ptr, jlong pk_column_ndx, jstring pk_value)\n{\n    try {\n        Obj obj = do_create_row_with_uuid_primary_key(env, shared_realm_ptr, table_ref_ptr, pk_column_ndx, pk_value);\n        return (jlong)(obj.get_key().value);\n    }\n    CATCH_STD()\n    return realm::npos;\n}\n\nJNIEXPORT jlong JNICALL Java_io_realm_internal_OsObject_nativeCreateNewObjectWithUUIDPrimaryKey(\n        JNIEnv* env, jclass, jlong shared_realm_ptr, jlong table_ref_ptr, jlong pk_column_ndx, jstring pk_value)\n{\n    try {\n        Obj obj = do_create_row_with_uuid_primary_key(env, shared_realm_ptr, table_ref_ptr, pk_column_ndx, pk_value);\n        if (bool(obj)) {\n            return reinterpret_cast<jlong>(new Obj(obj));\n        } else {\n            THROW_JAVA_EXCEPTION(env, PK_CONSTRAINT_EXCEPTION_CLASS, \"Invalid Object returned from 'do_create_row_with_uuid_primary_key'\");\n        }\n    }\n    CATCH_STD()\n    return 0;\n}\n\nJNIEXPORT jlong JNICALL Java_io_realm_internal_OsObject_nativeCreateEmbeddedObject(\n    JNIEnv* env, jclass, jlong j_parent_table_ptr, jlong j_parent_object_key, jlong j_parent_column_key)\n{\n    try {\n        TableRef table = TBL_REF(j_parent_table_ptr);\n        ObjKey obj_key(static_cast<int64_t>(j_parent_object_key));\n        Obj parent_obj = table->get_object(obj_key);\n        ColKey col_key(static_cast<int64_t>(j_parent_column_key));\n        Obj child_obj;\n        if (table->get_column_type(col_key) == type_Link) {\n            child_obj = parent_obj.create_and_set_linked_object(col_key);\n        } else {\n            LnkLstPtr list = parent_obj.get_linklist_ptr(col_key);\n            child_obj = list->create_and_insert_linked_object(list->size());\n        }\n        return to_jlong_or_not_found(child_obj.get_key());\n    }\n    CATCH_STD()\n    return 0;\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/cpp/io_realm_internal_OsObjectSchemaInfo.cpp",
    "content": "/*\n * Copyright 2016 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#include \"io_realm_internal_OsObjectSchemaInfo.h\"\n\n#include <realm/util/assert.hpp>\n\n#include <realm/object-store/object_schema.hpp>\n#include <realm/object-store/property.hpp>\n\n#include \"java_accessor.hpp\"\n#include \"java_exception_def.hpp\"\n#include \"jni_util/java_exception_thrower.hpp\"\n#include \"util.hpp\"\n\nusing namespace realm;\nusing namespace realm::jni_util;\nusing namespace realm::_impl;\n\nstatic void finalize_object_schema(jlong ptr)\n{\n    delete reinterpret_cast<ObjectSchema*>(ptr);\n}\n\nJNIEXPORT jlong JNICALL Java_io_realm_internal_OsObjectSchemaInfo_nativeCreateRealmObjectSchema(JNIEnv* env, jclass,\n                                                                                                jstring j_public_class_name,\n                                                                                                jstring j_internal_class_name,\n                                                                                                jboolean j_embedded)\n{\n    try {\n        JStringAccessor public_name(env, j_public_class_name);\n        JStringAccessor internal_name(env, j_internal_class_name);\n        ObjectSchema* object_schema = new ObjectSchema();\n        object_schema->name = internal_name;\n        object_schema->alias = public_name;\n        object_schema->table_type = to_bool(j_embedded) ? ObjectSchema::ObjectType::Embedded : ObjectSchema::ObjectType::TopLevel;\n        return reinterpret_cast<jlong>(object_schema);\n    }\n    CATCH_STD()\n    return 0;\n}\n\nJNIEXPORT jlong JNICALL Java_io_realm_internal_OsObjectSchemaInfo_nativeGetFinalizerPtr(JNIEnv*, jclass)\n{\n    return reinterpret_cast<jlong>(&finalize_object_schema);\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_OsObjectSchemaInfo_nativeAddProperties(JNIEnv* env, jclass,\n                                                                                     jlong native_ptr,\n                                                                                     jlongArray j_persisted_properties,\n                                                                                     jlongArray j_computed_properties)\n{\n    try {\n        ObjectSchema& object_schema = *reinterpret_cast<ObjectSchema*>(native_ptr);\n        JLongArrayAccessor persisted_properties(env, j_persisted_properties);\n        for (jsize i = 0; i < persisted_properties.size(); ++i)\n        {\n            Property* prop = reinterpret_cast<Property*>(persisted_properties[i]);\n            REALM_ASSERT_DEBUG(prop != nullptr);\n            if (prop->is_primary) {\n                object_schema.primary_key = prop->name;\n            }\n            object_schema.persisted_properties.emplace_back(std::move(*prop));\n            delete prop;\n        }\n\n        JLongArrayAccessor computed_properties(env, j_computed_properties);\n        for (jsize i = 0; i < computed_properties.size(); ++i)\n        {\n            Property* prop = reinterpret_cast<Property*>(computed_properties[i]);\n            REALM_ASSERT_DEBUG(prop != nullptr);\n            object_schema.computed_properties.emplace_back(std::move(*prop));\n            delete prop;\n        }\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT jstring JNICALL Java_io_realm_internal_OsObjectSchemaInfo_nativeGetClassName(JNIEnv* env, jclass,\n                                                                                       jlong nativePtr)\n{\n    try {\n        ObjectSchema* object_schema = reinterpret_cast<ObjectSchema*>(nativePtr);\n        auto name = object_schema->name;\n        return to_jstring(env, name);\n    }\n    CATCH_STD()\n\n    return nullptr;\n}\n\nJNIEXPORT jlong JNICALL Java_io_realm_internal_OsObjectSchemaInfo_nativeGetProperty(JNIEnv* env, jclass,\n                                                                                    jlong native_ptr,\n                                                                                    jstring j_property_name)\n{\n    try {\n        auto& object_schema = *reinterpret_cast<ObjectSchema*>(native_ptr);\n        JStringAccessor property_name_accessor(env, j_property_name);\n        StringData property_name(property_name_accessor);\n        auto* property = object_schema.property_for_name(property_name);\n        if (property) {\n            return reinterpret_cast<jlong>(new Property(*property));\n        }\n        THROW_JAVA_EXCEPTION(env, JavaExceptionDef::IllegalState,\n                             util::format(\"Property '%1' cannot be found.\", property_name.data()));\n    }\n    CATCH_STD()\n    return reinterpret_cast<jlong>(nullptr);\n}\n\nJNIEXPORT jlong JNICALL Java_io_realm_internal_OsObjectSchemaInfo_nativeGetPrimaryKeyProperty(JNIEnv* env, jclass,\n                                                                                              jlong native_ptr)\n{\n    try {\n        auto& object_schema = *reinterpret_cast<ObjectSchema*>(native_ptr);\n        auto* property = object_schema.primary_key_property();\n        if (property) {\n            return reinterpret_cast<jlong>(new Property(*property));\n        }\n    }\n    CATCH_STD()\n    return reinterpret_cast<jlong>(nullptr);\n}\n\nJNIEXPORT jboolean JNICALL Java_io_realm_internal_OsObjectSchemaInfo_nativeIsEmbedded(JNIEnv* env, jclass, jlong native_ptr)\n{\n    try {\n        auto& object_schema = *reinterpret_cast<ObjectSchema*>(native_ptr);\n        return to_jbool(object_schema.table_type == ObjectSchema::ObjectType::Embedded);\n    }\n    CATCH_STD()\n    return to_jbool(false);\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/cpp/io_realm_internal_OsObjectStore.cpp",
    "content": "/*\n * Copyright 2017 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#include \"io_realm_internal_OsObjectStore.h\"\n\n#include <realm/object-store/object_store.hpp>\n#include <realm/object-store/shared_realm.hpp>\n\n#include \"util.hpp\"\n#include \"jni_util/java_method.hpp\"\n#include \"jni_util/java_exception_thrower.hpp\"\n#include \"jni_util/java_exception_thrower.hpp\"\n\nusing namespace realm;\nusing namespace realm::jni_util;\nusing namespace realm::util;\nusing namespace realm::_impl;\n\nstatic_assert(io_realm_internal_OsObjectStore_SCHEMA_NOT_VERSIONED == static_cast<jlong>(ObjectStore::NotVersioned),\n              \"\");\n\ninline static bool is_allowed_to_primary_key(JNIEnv* env, DataType column_type)\n{\n    if (column_type == type_String\n        || column_type == type_Int\n        || column_type == type_Bool\n        || column_type == type_Timestamp\n        || column_type == type_OldDateTime\n        || column_type == type_ObjectId\n        || column_type == type_UUID) {\n        return true;\n    }\n\n    ThrowException(env, IllegalArgument, \"This field cannot be a primary key - \"\n                                         \"Only String/byte/short/int/long/boolean/Date/ObjectId/UUID fields are supported.\");\n    return false;\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_OsObjectStore_nativeSetPrimaryKeyForObject(JNIEnv* env, jclass,\n                                                                                          jlong shared_realm_ptr,\n                                                                                          jstring j_class_name,\n                                                                                          jstring j_pk_field_name)\n{\n    try {\n        auto& shared_realm = *(reinterpret_cast<SharedRealm*>(shared_realm_ptr));\n        JStringAccessor class_name(env, j_class_name);\n        JStringAccessor primary_key_field_name(env, j_pk_field_name);\n\n        auto& group = shared_realm->read_group();\n        if (!group.has_table(class_name)) {\n            std::string name_str = class_name;\n            if (name_str.find(TABLE_PREFIX) == 0) {\n                name_str = name_str.substr(TABLE_PREFIX.length());\n            }\n            THROW_JAVA_EXCEPTION(env, JavaExceptionDef::IllegalArgument,\n                                 util::format(\"The class '%1' doesn't exist in this Realm.\", name_str));\n        }\n        TableRef table = group.get_table(class_name);\n        auto column_key = table->get_column_key(primary_key_field_name);\n        if (j_pk_field_name && !is_allowed_to_primary_key(env, table->get_column_type(column_key))) {\n            return;\n        }\n        shared_realm->verify_in_write();\n        table->set_primary_key_column(column_key);\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT jstring JNICALL Java_io_realm_internal_OsObjectStore_nativeGetPrimaryKeyForObject(JNIEnv* env, jclass,\n                                                                                             jlong shared_realm_ptr,\n                                                                                             jstring j_class_name)\n{\n    try {\n        auto& shared_realm = *(reinterpret_cast<SharedRealm*>(shared_realm_ptr));\n        JStringAccessor class_name(env, j_class_name);\n        TableRef table = shared_realm->read_group().get_table(class_name);\n        auto col = table->get_primary_key_column();\n        std::string primary_key_field_name = (col) ? table->get_column_name(col) : \"\";\n        return primary_key_field_name.size() == 0 ? nullptr : to_jstring(env, primary_key_field_name);\n    }\n    CATCH_STD()\n    return nullptr;\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_OsObjectStore_nativeSetSchemaVersion(JNIEnv* env, jclass,\n                                                                                   jlong shared_realm_ptr,\n                                                                                   jlong schema_version)\n{\n    try {\n        auto& shared_realm = *(reinterpret_cast<SharedRealm*>(shared_realm_ptr));\n        shared_realm->verify_in_write();\n        ObjectStore::set_schema_version(shared_realm->read_group(), schema_version);\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT jlong JNICALL Java_io_realm_internal_OsObjectStore_nativeGetSchemaVersion(JNIEnv* env, jclass,\n                                                                                    jlong shared_realm_ptr)\n{\n    try {\n        auto& shared_realm = *(reinterpret_cast<SharedRealm*>(shared_realm_ptr));\n        return ObjectStore::get_schema_version(shared_realm->read_group());\n    }\n    CATCH_STD()\n    return ObjectStore::NotVersioned;\n}\n\nJNIEXPORT jboolean JNICALL Java_io_realm_internal_OsObjectStore_nativeDeleteTableForObject(JNIEnv* env, jclass,\n                                                                                        jlong shared_realm_ptr,\n                                                                                        jstring j_class_name)\n{\n    try {\n        auto& shared_realm = *(reinterpret_cast<SharedRealm*>(shared_realm_ptr));\n        JStringAccessor class_name_accessor(env, j_class_name);\n        shared_realm->verify_in_write();\n        if (!ObjectStore::table_for_object_type(shared_realm->read_group(), class_name_accessor)) {\n            return JNI_FALSE;\n        }\n        ObjectStore::delete_data_for_object(shared_realm->read_group(), class_name_accessor);\n        return JNI_TRUE;\n    }\n    CATCH_STD()\n    return JNI_FALSE;\n}\n\nJNIEXPORT jboolean JNICALL Java_io_realm_internal_OsObjectStore_nativeCallWithLock(JNIEnv* env, jclass,\n                                                                                   jstring j_realm_path,\n                                                                                   jobject j_runnable)\n{\n    try {\n        JStringAccessor path_accessor(env, j_realm_path);\n        std::string realm_path(path_accessor);\n        static JavaClass runnable_class(env, \"java/lang/Runnable\");\n        static JavaMethod run_method(env, runnable_class, \"run\", \"()V\");\n        bool result = DB::call_with_lock(realm_path, [&](std::string path) {\n            REALM_ASSERT_RELEASE_EX(realm_path.compare(path) == 0, realm_path.c_str(), path.c_str());\n            env->CallVoidMethod(j_runnable, run_method);\n            TERMINATE_JNI_IF_JAVA_EXCEPTION_OCCURRED(env, nullptr);\n        });\n        return result;\n    }\n    CATCH_STD()\n    return false;\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/cpp/io_realm_internal_OsRealmConfig.cpp",
    "content": "/*\n * Copyright 2017 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#include \"io_realm_internal_OsRealmConfig.h\"\n\n#include <realm/object-store/shared_realm.hpp>\n#if REALM_ENABLE_SYNC\n#include <realm/sync/config.hpp>\n#include <realm/object-store/sync/app.hpp>\n#include <realm/object-store/sync/sync_manager.hpp>\n#include <realm/object-store/sync/sync_session.hpp>\n#include <realm/util/misc_ext_errors.hpp>\n#endif\n\n#include <linux/errno.h>\n#include <jni_util/bson_util.hpp>\n#include <realm/sync/client.hpp>\n#include <realm/object-store/thread_safe_reference.hpp>\n\n#include \"java_accessor.hpp\"\n#include \"util.hpp\"\n#include \"jni_util/java_method.hpp\"\n#include \"jni_util/java_class.hpp\"\n#include \"jni_util/java_global_weak_ref.hpp\"\n#include \"jni_util/jni_utils.hpp\"\n#include \"jni_util/java_exception_thrower.hpp\"\n#include <realm/util/basic_system_errors.hpp>\n\nusing namespace realm;\nusing namespace realm::jni_util;\nusing namespace realm::_impl;\n\n\nstatic_assert(SchemaMode::Automatic ==\n                  static_cast<SchemaMode>(io_realm_internal_OsRealmConfig_SCHEMA_MODE_VALUE_AUTOMATIC),\n              \"\");\nstatic_assert(SchemaMode::Immutable==\n                  static_cast<SchemaMode>(io_realm_internal_OsRealmConfig_SCHEMA_MODE_VALUE_IMMUTABLE),\n              \"\");\nstatic_assert(SchemaMode::ReadOnly ==\n                  static_cast<SchemaMode>(io_realm_internal_OsRealmConfig_SCHEMA_MODE_VALUE_READONLY),\n              \"\");\nstatic_assert(SchemaMode::SoftResetFile ==\n                  static_cast<SchemaMode>(io_realm_internal_OsRealmConfig_SCHEMA_MODE_VALUE_SOFT_RESET_FILE),\n              \"\");\nstatic_assert(SchemaMode::AdditiveDiscovered ==\n                  static_cast<SchemaMode>(io_realm_internal_OsRealmConfig_SCHEMA_MODE_VALUE_ADDITIVE_DISCOVERED),\n              \"\");\nstatic_assert(SchemaMode::Manual == static_cast<SchemaMode>(io_realm_internal_OsRealmConfig_SCHEMA_MODE_VALUE_MANUAL),\n              \"\");\n\nstatic void finalize_realm_config(jlong ptr)\n{\n    delete reinterpret_cast<Realm::Config*>(ptr);\n}\n\nstatic JavaClass& get_shared_realm_class(JNIEnv* env)\n{\n    static JavaClass shared_realm_class(env, \"io/realm/internal/OsSharedRealm\");\n    return shared_realm_class;\n}\n\nJNIEXPORT jlong JNICALL Java_io_realm_internal_OsRealmConfig_nativeGetFinalizerPtr(JNIEnv*, jclass)\n{\n    return reinterpret_cast<jlong>(&finalize_realm_config);\n}\n\nJNIEXPORT jlong JNICALL Java_io_realm_internal_OsRealmConfig_nativeCreate(JNIEnv* env, jclass, jstring j_realm_path,\n                                                                          jstring j_fifo_fallback_dir,\n                                                                          jboolean enable_format_upgrade,\n                                                                          jlong j_max_number_of_active_versions)\n{\n    try {\n        JStringAccessor realm_path(env, j_realm_path);\n        JStringAccessor fifo_fallback_dir(env, j_fifo_fallback_dir);\n        auto* config_ptr = new Realm::Config();\n        config_ptr->path = realm_path;\n        config_ptr->disable_format_upgrade = !enable_format_upgrade;\n        config_ptr->fifo_files_fallback_path = fifo_fallback_dir;\n        config_ptr->max_number_of_active_versions = j_max_number_of_active_versions;\n        return reinterpret_cast<jlong>(config_ptr);\n    }\n    CATCH_STD()\n    return reinterpret_cast<jlong>(nullptr);\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_OsRealmConfig_nativeSetEncryptionKey(JNIEnv* env, jclass,\n                                                                                   jlong native_ptr,\n                                                                                   jbyteArray j_key_array)\n{\n    try {\n        JByteArrayAccessor jarray_accessor(env, j_key_array);\n        auto& config = *reinterpret_cast<Realm::Config*>(native_ptr);\n        // Encryption key should be set before creating sync_config.\n        REALM_ASSERT(!config.sync_config);\n        config.encryption_key = jarray_accessor.transform<std::vector<char>>();\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_OsRealmConfig_nativeSetInMemory(JNIEnv*, jclass, jlong native_ptr,\n                                                                              jboolean in_mem)\n{\n    auto& config = *reinterpret_cast<Realm::Config*>(native_ptr);\n    config.in_memory = in_mem; // no throw\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_OsRealmConfig_nativeSetSchemaConfig(JNIEnv* env, jobject j_config,\n                                                                                  jlong native_ptr, jbyte schema_mode,\n                                                                                  jlong schema_version,\n                                                                                  jlong schema_info_ptr,\n                                                                                  jobject j_migration_callback)\n{\n    try {\n        auto& config = *reinterpret_cast<Realm::Config*>(native_ptr);\n        config.schema_mode = static_cast<SchemaMode>(schema_mode);\n        config.schema_version = schema_version;\n        if (schema_info_ptr) {\n            auto& schema = *reinterpret_cast<Schema*>(schema_info_ptr);\n            config.schema = schema;\n        }\n        else {\n            config.schema = none;\n        }\n\n        if (j_migration_callback) {\n            static JavaMethod run_migration_callback_method(\n                env, get_shared_realm_class(env), \"runMigrationCallback\",\n                \"(JLio/realm/internal/OsRealmConfig;Lio/realm/internal/OsSharedRealm$MigrationCallback;J)V\", true);\n            // weak ref to avoid leaks caused by circular refs.\n            JavaGlobalWeakRef j_config_weak(env, j_config);\n            JavaGlobalWeakRef j_migration_cb_weak(env, j_migration_callback);\n            // TODO: It would be great if we can use move constructor in the lambda capture which was introduced in\n            // c++14. But sadly it seems to be a bug with gcc 4.9 to support it.\n            config.migration_function = [j_migration_cb_weak, j_config_weak](SharedRealm old_realm,\n                                                                                 SharedRealm realm, Schema&) {\n                JNIEnv* env = JniUtils::get_env(false);\n                // Java needs a new pointer for the OsSharedRealm life control.\n                SharedRealm* new_shared_realm_ptr = new SharedRealm(realm);\n                JavaGlobalRefByMove config_global = j_config_weak.global_ref(env);\n                if (!config_global) {\n                    return;\n                }\n\n                j_migration_cb_weak.call_with_local_ref(env, [&](JNIEnv* env, jobject obj) {\n                    env->CallStaticVoidMethod(get_shared_realm_class(env), run_migration_callback_method,\n                                              reinterpret_cast<jlong>(new_shared_realm_ptr), config_global.get(), obj,\n                                              old_realm->schema_version());\n                });\n                TERMINATE_JNI_IF_JAVA_EXCEPTION_OCCURRED(env, nullptr);\n            };\n        }\n        else {\n            config.migration_function = nullptr;\n        }\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_OsRealmConfig_nativeSetCompactOnLaunchCallback(\n    JNIEnv* env, jclass, jlong native_ptr, jobject j_compact_on_launch)\n{\n    try {\n        auto& config = *reinterpret_cast<Realm::Config*>(native_ptr);\n        if (j_compact_on_launch) {\n            static JavaClass compact_on_launch_class(env, \"io/realm/CompactOnLaunchCallback\");\n            static JavaMethod should_compact(env, compact_on_launch_class, \"shouldCompact\", \"(JJ)Z\");\n            // weak ref to avoid leaks caused by circular refs.\n            JavaGlobalWeakRef java_compact_on_launch_weak(env, j_compact_on_launch);\n\n            config.should_compact_on_launch_function = [java_compact_on_launch_weak](uint64_t totalBytes,\n                                                                                    uint64_t usedBytes) {\n                JNIEnv* env = JniUtils::get_env(false);\n                bool result = false;\n                java_compact_on_launch_weak.call_with_local_ref(env, [&](JNIEnv* env, jobject obj) {\n                    result = env->CallBooleanMethod(obj, should_compact, static_cast<jlong>(totalBytes),\n                                                    static_cast<jlong>(usedBytes));\n                });\n                TERMINATE_JNI_IF_JAVA_EXCEPTION_OCCURRED(env, nullptr);\n                return result;\n            };\n        }\n        else {\n            config.should_compact_on_launch_function = nullptr;\n        }\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_OsRealmConfig_nativeSetInitializationCallback(JNIEnv* env,\n                                                                                            jobject j_config,\n                                                                                            jlong native_ptr,\n                                                                                            jobject j_init_callback)\n{\n    try {\n        auto& config = *reinterpret_cast<Realm::Config*>(native_ptr);\n\n        if (j_init_callback) {\n            static JavaMethod run_initialization_callback_method(\n                env, get_shared_realm_class(env), \"runInitializationCallback\",\n                \"(JLio/realm/internal/OsRealmConfig;Lio/realm/internal/OsSharedRealm$InitializationCallback;)V\", true);\n            // weak ref to avoid leaks caused by circular refs.\n            JavaGlobalWeakRef j_init_cb_weak(env, j_init_callback);\n            JavaGlobalWeakRef j_config_weak(env, j_config);\n            config.initialization_function = [j_init_cb_weak, j_config_weak](SharedRealm realm) {\n                JNIEnv* env = JniUtils::get_env(false);\n                // Java needs a new pointer for the OsSharedRealm life control.\n                SharedRealm* new_shared_realm_ptr = new SharedRealm(realm);\n                JavaGlobalRefByMove config_global_ref = j_config_weak.global_ref(env);\n                if (!config_global_ref) {\n                    return;\n                }\n                j_init_cb_weak.call_with_local_ref(env, [&](JNIEnv* env, jobject obj) {\n                    env->CallStaticVoidMethod(get_shared_realm_class(env), run_initialization_callback_method,\n                                              reinterpret_cast<jlong>(new_shared_realm_ptr), config_global_ref.get(),\n                                              obj);\n                });\n                TERMINATE_JNI_IF_JAVA_EXCEPTION_OCCURRED(env, nullptr);\n            };\n        }\n        else {\n            config.initialization_function = nullptr;\n        }\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_OsRealmConfig_nativeEnableChangeNotification(\n    JNIEnv*, jclass, jlong native_ptr, jboolean enable_auto_change_notification)\n{\n    // No throws\n    auto& config = *reinterpret_cast<Realm::Config*>(native_ptr);\n    config.automatic_change_notifications = enable_auto_change_notification;\n}\n\n#if REALM_ENABLE_SYNC\nJNIEXPORT jstring JNICALL Java_io_realm_internal_OsRealmConfig_nativeCreateAndSetSyncConfig(\n    JNIEnv* env, jobject j_config, jlong j_app_ptr, jlong j_config_ptr, jstring j_sync_realm_url, jstring j_user_id, jstring j_user_provider,\n    jstring j_refresh_token, jstring j_access_token, jstring j_device_id, jbyte j_session_stop_policy, jstring j_url_prefix,\n    jstring j_custom_auth_header_name, jobjectArray j_custom_headers_array, jbyte j_client_reset_mode,\n    jobject j_on_before_client_reset_handler,\n    jobject j_on_after_client_reset_handler,\n    jstring j_partion_key_value, jobject j_java_sync_service)\n{\n    auto app = *reinterpret_cast<std::shared_ptr<app::App>*>(j_app_ptr);\n    auto& config = *reinterpret_cast<Realm::Config*>(j_config_ptr);\n    // sync_config should only be initialized once!\n    REALM_ASSERT(!config.sync_config);\n\n    try {\n        static JavaClass sync_manager_class(env, \"io/realm/mongodb/sync/Sync\");\n        // Doing the methods lookup from the thread that loaded the lib, to avoid\n        // https://developer.android.com/training/articles/perf-jni.html#faq_FindClass\n        static JavaMethod java_error_callback_method(env, sync_manager_class, \"notifyErrorHandler\",\n                                                     \"(BILjava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V\");\n\n        // error handler will be called form the sync client thread\n        auto error_handler = [sync_service_object = JavaGlobalRefByCopy(env, j_java_sync_service)](std::shared_ptr<SyncSession> session, SyncError error) {\n            JNIEnv* env = realm::jni_util::JniUtils::get_env(true);\n            ErrorCodes::Error error_code = error.status.code();\n            auto error_code_value = static_cast<int32_t>(error_code);\n            jbyte error_category = categoryAsJByte(error.status);\n\n            // System/Connection errors are defined by constants in\n            // https://android.googlesource.com/kernel/lk/+/upstream-master/include/errno.h\n            // However the integer values are not guaranteed to be stable according to POSIX.\n            //\n            // For this reason we manually map the constants to the error integer values defined in Java.\n            // For simplicity Java re-use the values currently defined in errno.h.\n            if (ErrorCodes::error_categories(error.status.code()).test(realm::ErrorCategory::system_error)) {\n                switch(error_code_value) {\n                    case ECONNRESET: error_code_value = 104; break;\n                    case ESHUTDOWN: error_code_value = 110; break;\n                    case ECONNREFUSED: error_code_value = 111; break;\n                    case EADDRINUSE: error_code_value = 112; break;\n                    case ECONNABORTED: error_code_value = 113; break;\n                    default:\n                        /* Do nothing */\n                        (void)0;\n                }\n            }\n\n            std::string client_reset_path_info;\n\n            // All client reset errors will be in the protocol category. Re-assign the error code\n            // to a value not used by https://github.com/realm/realm-sync/blob/develop/src/realm/sync/protocol.hpp#L232\n            // This way we only have one error in Java representing Client Reset.\n            if (error.is_client_reset_requested()) {\n                client_reset_path_info = error.user_info[SyncError::c_recovery_file_path_key];\n                error_code_value = 7; // See ErrorCode.java\n                error_category = io_realm_internal_ErrorCategory_RLM_SYNC_ERROR_CATEGORY_CUSTOM;\n            }\n            jstring jerror_message = to_jstring(env, error.simple_message);\n            jstring jerror_message_log_url = to_jstring(env, error.logURL);\n            jstring jclient_reset_path_info = to_jstring(env, client_reset_path_info);\n            jstring jsession_path = to_jstring(env, session->path());\n            env->CallVoidMethod(sync_service_object.get(),\n                                java_error_callback_method,\n                                error_category,\n                                error_code_value,\n                                jerror_message,\n                                jerror_message_log_url,\n                                jclient_reset_path_info,\n                                jsession_path);\n            env->DeleteLocalRef(jerror_message);\n            env->DeleteLocalRef(jerror_message_log_url);\n            env->DeleteLocalRef(jsession_path);\n            if (env->ExceptionCheck()) {\n                env->ExceptionDescribe();\n                env->ExceptionClear();\n                throw std::runtime_error(\"User-provided callback failed\");\n            }\n        };\n\n        // Get logged in user\n        JStringAccessor user_id(env, j_user_id);\n        JStringAccessor user_provider(env, j_user_provider);\n        std::shared_ptr<SyncUser> user = app->sync_manager()->get_existing_logged_in_user(user_id);\n\n        // FIXME: Investigate we shall be get the user https://github.com/realm/realm-java/issues/7591\n        if (!user) {\n            JStringAccessor refresh_token(env, j_refresh_token);\n            JStringAccessor access_token(env, j_access_token);\n            JStringAccessor device_id(env, j_device_id);\n            user = app->sync_manager()->get_user(user_id, refresh_token, access_token, device_id);\n        }\n\n        SyncSessionStopPolicy session_stop_policy = static_cast<SyncSessionStopPolicy>(j_session_stop_policy);\n\n        JStringAccessor realm_url(env, j_sync_realm_url);\n        // TODO Simplify. Java serialization only allows writing full documents, so the partition\n        //  key is embedded in a document with key 'value'. To get is as string were we parse it\n        //  and reformat with C++ bson serialization as it supports serializing single values.\n        if (j_partion_key_value) {\n            Bson bson(JniBsonProtocol::jstring_to_bson(env, j_partion_key_value));\n            std::stringstream buffer;\n            buffer << bson;\n            config.sync_config = std::make_shared<SyncConfig>(SyncConfig{user, buffer.str()});\n        } else {\n            config.sync_config = std::make_shared<SyncConfig>(SyncConfig{user, SyncConfig::FLXSyncEnabled{}});\n        }\n\n        config.sync_config->stop_policy = session_stop_policy;\n        config.sync_config->error_handler = std::move(error_handler);\n        switch (j_client_reset_mode) {\n            case io_realm_internal_OsRealmConfig_CLIENT_RESYNC_MODE_MANUAL: config.sync_config->client_resync_mode = realm::ClientResyncMode::Manual; break;\n            case io_realm_internal_OsRealmConfig_CLIENT_RESYNC_MODE_DISCARD_LOCAL: config.sync_config->client_resync_mode = realm::ClientResyncMode::DiscardLocal; break;\n            case io_realm_internal_OsRealmConfig_CLIENT_RESYNC_MODE_RECOVER: config.sync_config->client_resync_mode = realm::ClientResyncMode::Recover; break;\n            case io_realm_internal_OsRealmConfig_CLIENT_RESYNC_MODE_RECOVER_OR_DISCARD: config.sync_config->client_resync_mode = realm::ClientResyncMode::RecoverOrDiscard; break;\n            default: throw std::logic_error(util::format(\"Unsupported value for ClientResetMode: %1\", j_client_reset_mode));\n        }\n\n        // setup before and after client reset callbacks\n        if (j_client_reset_mode != io_realm_internal_OsRealmConfig_CLIENT_RESYNC_MODE_MANUAL) {\n            static JavaClass before_client_reset_handler_class(env, \"io/realm/internal/SyncObjectServerFacade$BeforeClientResetHandler\");\n            static JavaClass after_client_reset_handler_class(env, \"io/realm/internal/SyncObjectServerFacade$AfterClientResetHandler\");\n            static JavaMethod on_before_client_reset_method(env, before_client_reset_handler_class, \"onBeforeReset\",\"(JLio/realm/internal/OsRealmConfig;)V\", false);\n            static JavaMethod on_after_client_reset_method(env, after_client_reset_handler_class, \"onAfterReset\",\"(JJLio/realm/internal/OsRealmConfig;Z)V\", false);\n\n            JavaGlobalWeakRef j_config_weak(env, j_config);\n            JavaGlobalWeakRef j_on_before_client_reset_handler_weak(env, j_on_before_client_reset_handler);\n            JavaGlobalWeakRef j_on_after_client_reset_handler_weak(env, j_on_after_client_reset_handler);\n            config.sync_config->notify_before_client_reset = [j_on_before_client_reset_handler_weak, j_config_weak](SharedRealm before_frozen) {\n                JNIEnv* env = JniUtils::get_env(false);\n                JavaGlobalRefByMove config_global = j_config_weak.global_ref(env);\n                if (!config_global) {\n                    return;\n                }\n\n                // The local and remote Realm lifecycles are handled in Java via a\n                // ManualReleaseNativeContext.\n                auto* before_frozen_ptr = new SharedRealm(std::move(before_frozen));\n                j_on_before_client_reset_handler_weak.call_with_local_ref(env, [&](JNIEnv* env, jobject obj) {\n                    env->CallVoidMethod(obj, on_before_client_reset_method, reinterpret_cast<jlong>(before_frozen_ptr), config_global.get());\n                });\n\n                // Propagate the exception back to core that would handle the fallback to manual mode\n                if (env->ExceptionCheck()) {\n                    env->ExceptionDescribe();\n                    env->ExceptionClear();\n                    throw std::runtime_error(\"User-provided callback failed\");\n                }\n            };\n\n            config.sync_config->notify_after_client_reset = [j_on_after_client_reset_handler_weak, j_config_weak](SharedRealm before_frozen, ThreadSafeReference after, bool did_recover) {\n                JNIEnv* env = JniUtils::get_env(false);\n                JavaGlobalRefByMove config_global = j_config_weak.global_ref(env);\n                if (!config_global) {\n                    return;\n                }\n\n                // The local Realm lifecycle is handled in Java via a\n                // ManualReleaseNativeContext.\n                auto* before_frozen_ptr = new SharedRealm(std::move(before_frozen));\n\n                // Resolve ThreadSafeReference\n                auto* after_ptr = new SharedRealm(after.resolve<std::shared_ptr<Realm>>(nullptr));\n\n                j_on_after_client_reset_handler_weak.call_with_local_ref(env, [&](JNIEnv* env, jobject obj) {\n                    env->CallVoidMethod(obj, on_after_client_reset_method, reinterpret_cast<jlong>(before_frozen_ptr), reinterpret_cast<jlong>(after_ptr), config_global.get(), did_recover);\n                });\n\n                // Propagate the exception back to core that would handle the fallback to manual mode\n                if (env->ExceptionCheck()) {\n                    env->ExceptionDescribe();\n                    env->ExceptionClear();\n                    throw std::runtime_error(\"User-provided callback failed\");\n                }\n            };\n        }\n\n        if (j_url_prefix) {\n            JStringAccessor url_prefix(env, j_url_prefix);\n            (void) url_prefix;\n            // config.sync_config->url_prefix = realm::util::Optional<std::string>(url_prefix);\n        }\n\n        if (j_custom_auth_header_name) {\n            JStringAccessor custom_auth_header_name(env, j_custom_auth_header_name);\n            config.sync_config->authorization_header_name = realm::util::Optional<std::string>(custom_auth_header_name);\n        }\n\n        if (j_custom_headers_array) {\n            jsize count = env->GetArrayLength(j_custom_headers_array);\n            for (int i = 0; i < count; i = i + 2) {\n                JStringAccessor key(env, (jstring) env->GetObjectArrayElement(j_custom_headers_array, i));\n                JStringAccessor value(env, (jstring) env->GetObjectArrayElement(j_custom_headers_array, i + 1));\n                config.sync_config->custom_http_headers[std::string(key)] = std::string(value);\n            }\n        }\n\n        // return to_jstring(env, config.sync_config->realm_url.c_str());\n        // FIXME: We must return the realm url here for proxy support to work\n        return to_jstring(env, \"\");\n    }\n    CATCH_STD()\n    return nullptr;\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_OsRealmConfig_nativeSetSyncConfigSslSettings(\n    JNIEnv* env, jclass, jlong native_ptr, jboolean sync_client_validate_ssl,\n    jstring j_sync_ssl_trust_certificate_path)\n{\n    auto& config = *reinterpret_cast<Realm::Config*>(native_ptr);\n    // To ensure the sync_config has been created and this function won't be called multiple time on the same config.\n    REALM_ASSERT(config.sync_config);\n    REALM_ASSERT(config.sync_config->client_validate_ssl);\n    REALM_ASSERT(!config.sync_config->ssl_trust_certificate_path);\n\n    try {\n        config.sync_config->client_validate_ssl = sync_client_validate_ssl;\n        if (j_sync_ssl_trust_certificate_path) {\n            JStringAccessor cert_path(env, j_sync_ssl_trust_certificate_path);\n            config.sync_config->ssl_trust_certificate_path = realm::util::Optional<std::string>(cert_path);\n        }\n        else if (config.sync_config->client_validate_ssl) {\n            // set default callback to allow Android to check the certificate\n            static JavaClass sync_manager_class(env, \"io/realm/mongodb/sync/Sync\");\n            static JavaMethod java_ssl_verify_callback(env, sync_manager_class, \"sslVerifyCallback\",\n                                                       \"(Ljava/lang/String;Ljava/lang/String;I)Z\", true);\n\n            std::function<sync::Session::SSLVerifyCallback> ssl_verify_callback =\n                [](const std::string server_address, REALM_UNUSED realm::sync::Session::port_type server_port,\n                   const char* pem_data, size_t pem_size, REALM_UNUSED int preverify_ok, int depth) {\n\n                    Log::d(\"Callback to Java requesting certificate validation for host %1\",\n                                            server_address.c_str());\n\n                    JNIEnv* env = realm::jni_util::JniUtils::get_env(true);\n\n                    jstring jserver_address = to_jstring(env, server_address.c_str());\n                    // deep copy the pem_data into a string so DeleteLocalRef delete the local reference not the original const char\n                    std::string pem(pem_data, pem_size);\n                    jstring jpem = to_jstring(env, pem.c_str());\n                    bool isValid = env->CallStaticBooleanMethod(sync_manager_class, java_ssl_verify_callback,\n                                                                jserver_address,\n                                                                jpem, depth) == JNI_TRUE;\n                    env->DeleteLocalRef(jserver_address);\n                    env->DeleteLocalRef(jpem);\n                    return isValid;\n                };\n            config.sync_config->ssl_verify_callback = std::move(ssl_verify_callback);\n        }\n    }\n    CATCH_STD()\n}\n\nstatic_assert(SyncConfig::ProxyConfig::Type::HTTP == static_cast<SyncConfig::ProxyConfig::Type>(io_realm_internal_OsRealmConfig_PROXYCONFIG_TYPE_VALUE_HTTP),\n              \"\");\n\nJNIEXPORT void JNICALL Java_io_realm_internal_OsRealmConfig_nativeSetSyncConfigProxySettings(\n    JNIEnv* env, jclass, jlong native_ptr, jbyte proxy_type,\n    jstring j_proxy_address, jint proxy_port)\n{\n    auto& config = *reinterpret_cast<Realm::Config*>(native_ptr);\n    // To ensure the sync_config has been created and this function won't be called multiple time on the same config.\n    REALM_ASSERT(config.sync_config);\n    REALM_ASSERT(!config.sync_config->proxy_config);\n\n    try {\n        SyncConfig::ProxyConfig proxy_config;\n        proxy_config.type = static_cast<SyncConfig::ProxyConfig::Type>(proxy_type);\n        proxy_config.address = JStringAccessor(env, j_proxy_address);\n        proxy_config.port = proxy_port;\n\n        config.sync_config->proxy_config.emplace(std::move(proxy_config));\n    }\n    CATCH_STD()\n}\n#endif\n"
  },
  {
    "path": "realm/realm-library/src/main/cpp/io_realm_internal_OsResults.cpp",
    "content": "/*\n * Copyright 2016 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#include \"io_realm_internal_OsResults.h\"\n\n#include <realm/object-store/shared_realm.hpp>\n#include <realm/object-store/results.hpp>\n#include <realm/object-store/list.hpp>\n#include <realm/parser/keypath_mapping.hpp>\n#include <realm/util/optional.hpp>\n\n#include \"java_class_global_def.hpp\"\n#include \"java_object_accessor.hpp\"\n#include \"java_query_descriptor.hpp\"\n#include \"observable_collection_wrapper.hpp\"\n#include \"util.hpp\"\n\nusing namespace realm;\nusing namespace realm::jni_util;\nusing namespace realm::util;\nusing namespace realm::_impl;\n\ntypedef ObservableCollectionWrapper<Results> ResultsWrapper;\n\nstatic void finalize_results(jlong ptr);\n\nstatic void finalize_results(jlong ptr)\n{\n    delete reinterpret_cast<ResultsWrapper*>(ptr);\n}\n\nJNIEXPORT jlong JNICALL Java_io_realm_internal_OsResults_nativeCreateResults(JNIEnv* env, jclass,\n                                                                             jlong shared_realm_ptr,\n                                                                             jlong query_ptr)\n{\n    try {\n        auto& query = *reinterpret_cast<Query*>(query_ptr);\n        if (!TABLE_VALID(env, query.get_table())) {\n            return reinterpret_cast<jlong>(nullptr);\n        }\n\n        auto ordering = query.get_ordering();\n\n        auto shared_realm = *(reinterpret_cast<SharedRealm*>(shared_realm_ptr));\n        Results results(shared_realm, query, *ordering);\n\n        query.set_ordering(std::make_unique<DescriptorOrdering>(*ordering));\n\n        auto wrapper = new ResultsWrapper(results);\n\n        return reinterpret_cast<jlong>(wrapper);\n    }\n    CATCH_STD()\n    return reinterpret_cast<jlong>(nullptr);\n}\n\nJNIEXPORT jlong JNICALL Java_io_realm_internal_OsResults_nativeCreateSnapshot(JNIEnv* env, jclass, jlong native_ptr)\n{\n    try {\n        auto wrapper = reinterpret_cast<ResultsWrapper*>(native_ptr);\n        auto snapshot_results = wrapper->collection().snapshot();\n        auto snapshot_wrapper = new ResultsWrapper(snapshot_results);\n        return reinterpret_cast<jlong>(snapshot_wrapper);\n    }\n    CATCH_STD();\n    return reinterpret_cast<jlong>(nullptr);\n}\n\nJNIEXPORT jboolean JNICALL Java_io_realm_internal_OsResults_nativeContains(JNIEnv* env, jclass, jlong native_ptr,\n                                                                            jlong native_obj_ptr)\n{\n    try {\n        auto wrapper = reinterpret_cast<ResultsWrapper*>(native_ptr);\n        const Obj* obj = reinterpret_cast<Obj*>(native_obj_ptr);\n        size_t index = wrapper->collection().index_of(*obj);\n        return to_jbool(index != not_found);\n    }\n    CATCH_STD();\n    return JNI_FALSE;\n}\n\nJNIEXPORT jlong JNICALL Java_io_realm_internal_OsResults_nativeGetRow(JNIEnv* env, jclass, jlong native_ptr,\n                                                                       jint index)\n{\n    try {\n        auto wrapper = reinterpret_cast<ResultsWrapper*>(native_ptr);\n        auto obj = wrapper->collection().get(static_cast<size_t>(index));\n        return reinterpret_cast<jlong>(new Obj(std::move(obj)));\n    }\n    CATCH_STD()\n    return reinterpret_cast<jlong>(nullptr);\n}\n\nJNIEXPORT jlong JNICALL Java_io_realm_internal_OsResults_nativeFirstRow(JNIEnv* env, jclass, jlong native_ptr)\n{\n    try {\n        auto wrapper = reinterpret_cast<ResultsWrapper*>(native_ptr);\n        auto optional_obj = wrapper->collection().first();\n        if (optional_obj) {\n            return reinterpret_cast<jlong>(new Obj(std::move(optional_obj.value())));\n        }\n    }\n    CATCH_STD()\n    return reinterpret_cast<jlong>(nullptr);\n}\n\n\nJNIEXPORT jlong JNICALL Java_io_realm_internal_OsResults_nativeLastRow(JNIEnv* env, jclass, jlong native_ptr)\n{\n    try {\n        auto wrapper = reinterpret_cast<ResultsWrapper*>(native_ptr);\n        auto optional_obj = wrapper->collection().last();\n        if (optional_obj) {\n            return reinterpret_cast<jlong>(new Obj(optional_obj.value()));\n        }\n    }\n    CATCH_STD()\n    return reinterpret_cast<jlong>(nullptr);\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_OsResults_nativeClear(JNIEnv* env, jclass, jlong native_ptr)\n{\n    try {\n        auto wrapper = reinterpret_cast<ResultsWrapper*>(native_ptr);\n        wrapper->collection().clear();\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT jlong JNICALL Java_io_realm_internal_OsResults_nativeSize(JNIEnv* env, jclass, jlong native_ptr)\n{\n    try {\n        auto wrapper = reinterpret_cast<ResultsWrapper*>(native_ptr);\n        return static_cast<jlong>(wrapper->collection().size());\n    }\n    CATCH_STD()\n    return 0;\n}\n\nJNIEXPORT jobject JNICALL Java_io_realm_internal_OsResults_nativeAggregate(JNIEnv* env, jclass, jlong native_ptr,\n                                                                            jlong column_key, jbyte agg_func)\n{\n    try {\n        auto wrapper = reinterpret_cast<ResultsWrapper*>(native_ptr);\n\n        ColKey col_key(column_key);\n        util::Optional<Mixed> value;\n        switch (agg_func) {\n            case io_realm_internal_OsResults_AGGREGATE_FUNCTION_MINIMUM:\n                value = wrapper->collection().min(col_key);\n                break;\n            case io_realm_internal_OsResults_AGGREGATE_FUNCTION_MAXIMUM:\n                value = wrapper->collection().max(col_key);\n                break;\n            case io_realm_internal_OsResults_AGGREGATE_FUNCTION_AVERAGE: {\n                util::Optional<Mixed> value_count(wrapper->collection().average(col_key));\n                if (value_count) {\n                    value = value_count;\n                }\n                else {\n                    value = util::Optional<Mixed>(0.0);\n                }\n                break;\n            }\n            case io_realm_internal_OsResults_AGGREGATE_FUNCTION_SUM:\n                value = wrapper->collection().sum(col_key);\n                break;\n            default:\n                REALM_UNREACHABLE();\n        }\n\n        if (!value) {\n            return static_cast<jobject>(nullptr);\n        }\n\n        Mixed m = *value;\n        switch (m.get_type()) {\n            case type_Int:\n                return JavaClassGlobalDef::new_long(env, m.get_int());\n            case type_Float:\n                return JavaClassGlobalDef::new_float(env, m.get_float());\n            case type_Double:\n                return JavaClassGlobalDef::new_double(env, m.get_double());\n            case type_Timestamp:\n                return JavaClassGlobalDef::new_date(env, m.get_timestamp());\n            default:\n                throw std::invalid_argument(\"Excepted numeric type\");\n        }\n    }\n    CATCH_STD()\n    return static_cast<jobject>(nullptr);\n}\n\nJNIEXPORT jlong JNICALL Java_io_realm_internal_OsResults_nativeStringDescriptor(JNIEnv* env,\n                                                                                jclass,\n                                                                                jlong native_ptr,\n                                                                                jstring j_descriptor,\n                                                                                jlong j_mapping_ptr)\n{\n    try {\n        auto wrapper = reinterpret_cast<ResultsWrapper*>(native_ptr);\n        JStringAccessor descriptor(env, j_descriptor); // throws\n        std::vector<Mixed> args;\n\n        query_parser::KeyPathMapping mapping;\n        if (j_mapping_ptr) {\n            mapping = *reinterpret_cast<query_parser::KeyPathMapping *>(j_mapping_ptr);\n        }\n\n        Query predicate = wrapper->collection().get_table()->query(\"TRUEPREDICATE \" + std::string(descriptor), args, mapping);\n\n        if (auto parsed_ordering = predicate.get_ordering()) {\n            auto distinct_result = wrapper->collection().apply_ordering(std::move(*parsed_ordering));\n            return reinterpret_cast<jlong>(new ResultsWrapper(distinct_result));\n        }\n\n        return native_ptr;\n    }\n    CATCH_STD()\n    return reinterpret_cast<jlong>(nullptr);\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_OsResults_nativeStartListening(JNIEnv* env, jobject instance,\n                                                                              jlong native_ptr)\n{\n    try {\n        auto wrapper = reinterpret_cast<ResultsWrapper*>(native_ptr);\n        wrapper->start_listening(env, instance);\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_OsResults_nativeStopListening(JNIEnv* env, jobject, jlong native_ptr)\n{\n    try {\n        auto wrapper = reinterpret_cast<ResultsWrapper*>(native_ptr);\n        wrapper->stop_listening();\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT jlong JNICALL Java_io_realm_internal_OsResults_nativeGetFinalizerPtr(JNIEnv*, jclass)\n{\n    return reinterpret_cast<jlong>(&finalize_results);\n}\n\nJNIEXPORT jlong JNICALL Java_io_realm_internal_OsResults_nativeGetTable(JNIEnv *env, jclass,\n                                                                        jlong native_ptr) {\n    try {\n        auto wrapper = reinterpret_cast<ResultsWrapper*>(native_ptr);\n        auto* table_ref = new ConstTableRef(wrapper->collection().get_table());\n        return reinterpret_cast<jlong>(table_ref);\n    }\n    CATCH_STD()\n    return 0;\n}\n\nJNIEXPORT jlong JNICALL Java_io_realm_internal_OsResults_nativeWhere(JNIEnv* env, jclass, jlong native_ptr)\n{\n    try {\n        auto wrapper = reinterpret_cast<ResultsWrapper*>(native_ptr);\n        TableView table_view = wrapper->collection().get_tableview();\n        Query* query = new Query(table_view.get_parent(), std::unique_ptr<TableView>(new TableView(std::move(table_view))));\n        query->set_ordering(std::make_unique<DescriptorOrdering>());\n        return reinterpret_cast<jlong>(query);\n    }\n    CATCH_STD()\n    return 0;\n}\n\nJNIEXPORT jstring JNICALL Java_io_realm_internal_OsResults_toJSON(JNIEnv* env, jclass, jlong native_ptr, jint maxDepth)\n{\n    try {\n        auto wrapper = reinterpret_cast<ResultsWrapper*>(native_ptr);\n\n        auto table_view = wrapper->collection().get_tableview();\n        std::stringstream ss;\n        table_view.to_json(ss, maxDepth);\n        return to_jstring(env, ss.str().c_str());\n    }\n    CATCH_STD()\n    return nullptr;\n}\n\nJNIEXPORT jlong JNICALL Java_io_realm_internal_OsResults_nativeIndexOf(JNIEnv* env, jclass, jlong native_ptr,\n                                                                        jlong obj_native_ptr)\n{\n    try {\n        auto wrapper = reinterpret_cast<ResultsWrapper*>(native_ptr);\n        Obj* obj = reinterpret_cast<Obj*>(obj_native_ptr);\n\n        return static_cast<jlong>(wrapper->collection().index_of(*obj));\n    }\n    CATCH_STD()\n    return npos;\n}\n\nJNIEXPORT jboolean JNICALL Java_io_realm_internal_OsResults_nativeDeleteLast(JNIEnv* env, jclass, jlong native_ptr)\n{\n    try {\n        auto wrapper = reinterpret_cast<ResultsWrapper*>(native_ptr);\n        auto obj = wrapper->collection().last();\n        if (obj && obj->is_valid()) {\n            obj->remove();\n            return JNI_TRUE;\n        }\n    }\n    CATCH_STD()\n    return JNI_FALSE;\n}\n\nJNIEXPORT jboolean JNICALL Java_io_realm_internal_OsResults_nativeDeleteFirst(JNIEnv* env, jclass, jlong native_ptr)\n{\n    try {\n        auto wrapper = reinterpret_cast<ResultsWrapper*>(native_ptr);\n        auto obj = wrapper->collection().first();\n        if (obj && obj->is_valid()) {\n            obj->remove();\n            return JNI_TRUE;\n        }\n    }\n    CATCH_STD()\n    return JNI_FALSE;\n}\n\nstatic inline void update_objects(JNIEnv* env, jlong results_ptr, jstring& j_field_name, JavaValue& value) {\n    try {\n        auto wrapper = reinterpret_cast<ResultsWrapper*>(results_ptr);\n        JavaContext ctx(env, wrapper->collection().get_realm(), wrapper->collection().get_object_schema());\n        JStringAccessor prop_name(env, j_field_name);\n        wrapper->collection().set_property_value(ctx, prop_name, value);\n    }\n    CATCH_STD()\n}\n\n\nJNIEXPORT void JNICALL Java_io_realm_internal_OsResults_nativeSetNull(JNIEnv* env, jclass, jlong native_ptr, jstring j_field_name)\n{\n    auto value = JavaValue();\n    update_objects(env, native_ptr, j_field_name, value);\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_OsResults_nativeSetBoolean(JNIEnv* env, jclass, jlong native_ptr, jstring j_field_name, jboolean j_value)\n{\n    JavaValue value(j_value);\n    update_objects(env, native_ptr, j_field_name, value);\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_OsResults_nativeSetInt(JNIEnv* env, jclass, jlong native_ptr, jstring j_field_name, jlong j_value)\n{\n    JavaValue value(j_value);\n    update_objects(env, native_ptr, j_field_name, value);\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_OsResults_nativeSetFloat(JNIEnv* env, jclass, jlong native_ptr, jstring j_field_name, jfloat j_value)\n{\n    JavaValue value(j_value);\n    update_objects(env, native_ptr, j_field_name, value);\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_OsResults_nativeSetDouble(JNIEnv* env, jclass, jlong native_ptr, jstring j_field_name, jdouble j_value)\n{\n    JavaValue value(j_value);\n    update_objects(env, native_ptr, j_field_name, value);\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_OsResults_nativeSetString(JNIEnv* env, jclass, jlong native_ptr, jstring j_field_name, jstring j_value)\n{\n    JStringAccessor str(env, j_value);\n    JavaValue value = str.is_null() ? JavaValue() : JavaValue(std::string(str));\n    update_objects(env, native_ptr, j_field_name, value);\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_OsResults_nativeSetBinary(JNIEnv* env, jclass, jlong native_ptr, jstring j_field_name, jbyteArray j_value)\n{\n    auto data = OwnedBinaryData(JByteArrayAccessor(env, j_value).transform<BinaryData>());\n    JavaValue value(data);\n    update_objects(env, native_ptr, j_field_name, value);\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_OsResults_nativeSetTimestamp(JNIEnv* env, jclass, jlong native_ptr, jstring j_field_name, jlong j_value)\n{\n    JavaValue value(from_milliseconds(j_value));\n    update_objects(env, native_ptr, j_field_name, value);\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_OsResults_nativeSetDecimal128(JNIEnv* env, jclass, jlong native_ptr, jstring j_field_name, jlong low, jlong high)\n{\n\n    Decimal128::Bid128 raw = {static_cast<uint64_t>(low), static_cast<uint64_t>(high)};\n    Decimal128 decimal128 = Decimal128(raw);\n    JavaValue value(decimal128);\n    update_objects(env, native_ptr, j_field_name, value);\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_OsResults_nativeSetObjectId(JNIEnv* env, jclass, jlong native_ptr, jstring j_field_name, jstring j_value)\n{\n    JStringAccessor data(env, j_value);\n    ObjectId objectId = ObjectId(StringData(data).data());\n    JavaValue value(objectId);\n    update_objects(env, native_ptr, j_field_name, value);\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_OsResults_nativeSetUUID(JNIEnv* env, jclass, jlong native_ptr, jstring j_field_name, jstring j_value)\n{\n    JStringAccessor data(env, j_value);\n    UUID uuid = UUID(StringData(data).data());\n    JavaValue value(uuid);\n    update_objects(env, native_ptr, j_field_name, value);\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_OsResults_nativeSetObject(JNIEnv* env, jclass, jlong native_ptr, jstring j_field_name, jlong row_ptr)\n{\n    JavaValue value(reinterpret_cast<Obj*>(row_ptr));\n    update_objects(env, native_ptr, j_field_name, value);\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_OsResults_nativeSetList(JNIEnv* env, jclass, jlong native_ptr, jstring j_field_name, jlong builder_ptr)\n{\n    // OsObjectBuilder has been used to build up the list we want to insert. This means the\n    // fake object described by the OsObjectBuilder only contains one property, namely the list we\n    // want to insert and this list is assumed to be at index = 0.\n    std::map<ColKey, JavaValue> builder = *reinterpret_cast<std::map<ColKey, JavaValue>*>(builder_ptr);\n    REALM_ASSERT_DEBUG(builder.size() == 1);\n    update_objects(env, native_ptr, j_field_name, builder.begin()->second);\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_OsResults_nativeDelete(JNIEnv* env, jclass, jlong native_ptr,\n                                                                      jlong index)\n{\n    try {\n        auto wrapper = reinterpret_cast<ResultsWrapper*>(native_ptr);\n        auto obj = wrapper->collection().get(index);\n        if (obj.is_valid()) {\n            obj.remove();\n        }\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT jboolean JNICALL Java_io_realm_internal_OsResults_nativeIsValid(JNIEnv* env, jclass, jlong native_ptr)\n{\n    try {\n        auto wrapper = reinterpret_cast<ResultsWrapper*>(native_ptr);\n        return wrapper->collection().is_valid();\n    }\n    CATCH_STD()\n    return JNI_FALSE;\n}\n\nJNIEXPORT jbyte JNICALL Java_io_realm_internal_OsResults_nativeGetMode(JNIEnv* env, jclass, jlong native_ptr)\n{\n    try {\n        auto wrapper = reinterpret_cast<ResultsWrapper*>(native_ptr);\n        switch (wrapper->collection().get_mode()) {\n            case Results::Mode::Empty:\n                return io_realm_internal_OsResults_MODE_EMPTY;\n            case Results::Mode::Table:\n                return io_realm_internal_OsResults_MODE_TABLE;\n            case Results::Mode::Collection:\n                return io_realm_internal_OsResults_MODE_LIST;\n            case Results::Mode::Query:\n                return io_realm_internal_OsResults_MODE_QUERY;\n            case Results::Mode::TableView:\n                return io_realm_internal_OsResults_MODE_TABLEVIEW;\n            default:\n                throw std::logic_error(util::format(\"Unexpected state: %1\", static_cast<uint8_t>(wrapper->collection().get_mode())));\n        }\n    }\n    CATCH_STD()\n    return -1;\n}\n\nJNIEXPORT jlong JNICALL Java_io_realm_internal_OsResults_nativeCreateResultsFromBacklinks(JNIEnv *env, jclass,\n                                                                                           jlong shared_realm_ptr,\n                                                                                           jlong obj_ptr,\n                                                                                           jlong src_table_ref_ptr,\n                                                                                           jlong src_col_key)\n{\n    Obj* obj = OBJ(obj_ptr);\n    if (!ROW_VALID(env, obj)) {\n        return reinterpret_cast<jlong>(nullptr);\n    }\n    try {\n        TableRef src_table = TBL_REF(src_table_ref_ptr);\n        TableView backlink_view = obj->get_backlink_view(src_table, ColKey(src_col_key));\n        auto shared_realm = *(reinterpret_cast<SharedRealm*>(shared_realm_ptr));\n        Results results(shared_realm, std::move(backlink_view));\n        auto wrapper = new ResultsWrapper(results);\n        return reinterpret_cast<jlong>(wrapper);\n    }\n    CATCH_STD()\n    return reinterpret_cast<jlong>(nullptr);\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_OsResults_nativeEvaluateQueryIfNeeded(JNIEnv* env, jclass,\n                                                                                    jlong native_ptr,\n                                                                                    jboolean wants_notifications)\n{\n    try {\n        auto wrapper = reinterpret_cast<ResultsWrapper*>(native_ptr);\n        wrapper->collection().evaluate_query_if_needed(wants_notifications);\n    }\n    CATCH_STD()\n}\n\n\nJNIEXPORT jlong JNICALL Java_io_realm_internal_OsResults_nativeFreeze(JNIEnv* env, jclass, jlong native_ptr, jlong frozen_realm_native_ptr)\n{\n    try {\n        auto wrapper = reinterpret_cast<ResultsWrapper*>(native_ptr);\n        auto frozen_realm = *(reinterpret_cast<SharedRealm*>(frozen_realm_native_ptr));\n        Results results = wrapper->collection().freeze(frozen_realm);\n        return reinterpret_cast<jlong>(new ResultsWrapper(results));\n    }\n    CATCH_STD()\n    return reinterpret_cast<jlong>(nullptr);\n}\n\nJNIEXPORT jobject JNICALL\nJava_io_realm_internal_OsResults_nativeGetValue(JNIEnv* env, jclass, jlong native_ptr,\n                                                jint pos) {\n    try {\n        auto& wrapper = *reinterpret_cast<ResultsWrapper*>(native_ptr);\n        JavaAccessorContext context(env);\n        return util::any_cast<jobject>(wrapper.collection().get(context, pos));\n    }\n    CATCH_STD()\n\n    return nullptr;\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/cpp/io_realm_internal_OsSchemaInfo.cpp",
    "content": "/*\n * Copyright 2016 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#include \"io_realm_internal_OsSchemaInfo.h\"\n\n#include <realm/object-store/schema.hpp>\n#include <realm/object-store/object_schema.hpp>\n#include <realm/object-store/property.hpp>\n#include \"java_accessor.hpp\"\n#include \"java_exception_def.hpp\"\n#include \"util.hpp\"\n#include \"jni_util/java_exception_thrower.hpp\"\n\nusing namespace realm;\nusing namespace realm::jni_util;\nusing namespace realm::util;\nusing namespace realm::_impl;\n\nstatic void finalize_schema(jlong ptr)\n{\n    delete reinterpret_cast<Schema*>(ptr);\n}\n\nJNIEXPORT jlong JNICALL Java_io_realm_internal_OsSchemaInfo_nativeCreateFromList(JNIEnv* env, jclass,\n                                                                                 jlongArray objectSchemaPtrs_)\n{\n    try {\n        std::vector<ObjectSchema> object_schemas;\n        JLongArrayAccessor array(env, objectSchemaPtrs_);\n        for (jsize i = 0; i < array.size(); ++i) {\n            object_schemas.push_back(*reinterpret_cast<ObjectSchema*>(array[i]));\n        }\n        auto* schema = new Schema(std::move(object_schemas));\n        return reinterpret_cast<jlong>(schema);\n    }\n    CATCH_STD()\n    return 0;\n}\n\nJNIEXPORT jlong JNICALL Java_io_realm_internal_OsSchemaInfo_nativeGetFinalizerPtr(JNIEnv*, jclass)\n{\n    return reinterpret_cast<jlong>(&finalize_schema);\n}\n\nJNIEXPORT jlong JNICALL Java_io_realm_internal_OsSchemaInfo_nativeGetObjectSchemaInfo(JNIEnv* env, jclass,\n                                                                                      jlong native_ptr,\n                                                                                      jstring j_class_name)\n{\n    try {\n        JStringAccessor class_name_accessor(env, j_class_name);\n        StringData class_name(class_name_accessor);\n        auto& schema = *reinterpret_cast<Schema*>(native_ptr);\n        auto it = schema.find(class_name);\n        if (it == schema.end()) {\n            THROW_JAVA_EXCEPTION(env, JavaExceptionDef::IllegalState,\n                                 format(\"Class '%1' cannot be found in the schema.\", class_name.data()));\n        } else {\n            return reinterpret_cast<jlong>(new ObjectSchema(*it));\n        }\n    }\n    CATCH_STD()\n\n    return reinterpret_cast<jlong>(nullptr);\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/cpp/io_realm_internal_OsSet.cpp",
    "content": "/*\n * Copyright 2020 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#include \"io_realm_internal_OsSet.h\"\n\n#include <algorithm>    // std::set_intersection, std::sort\n#include <vector>       // std::vector\n#include <set>          // std::set\n#include <realm/object-store/set.hpp>\n#include <realm/object-store/shared_realm.hpp>\n\n#include \"java_accessor.hpp\"\n#include \"java_object_accessor.hpp\"\n#include \"java_exception_def.hpp\"\n#include \"jni_util/java_exception_thrower.hpp\"\n#include \"observable_collection_wrapper.hpp\"\n#include \"util.hpp\"\n\nusing namespace realm;\nusing namespace realm::util;\nusing namespace realm::object_store;\nusing namespace realm::_impl;\n\ntypedef ObservableCollectionWrapper<object_store::Set> SetWrapper;\n\nvoid finalize_set(jlong ptr) {\n    delete reinterpret_cast<SetWrapper*>(ptr);\n}\n\ninline bool isSetNullable(JNIEnv *env, realm::object_store::Set &set) {\n    if (is_nullable(set.get_type())) {\n        return true;\n    }\n\n    THROW_JAVA_EXCEPTION(env, JavaExceptionDef::NullPointerException,\n                         \"This 'RealmSet' is not nullable. A non-null value is expected.\");\n}\n\nJNIEXPORT jlong JNICALL Java_io_realm_internal_OsSet_nativeGetFinalizerPtr(JNIEnv*, jclass) {\n    return reinterpret_cast<jlong>(&finalize_set);\n}\n\nJNIEXPORT jlongArray JNICALL\nJava_io_realm_internal_OsSet_nativeCreate(JNIEnv* env, jclass, jlong shared_realm_ptr,\n                                          jlong obj_ptr, jlong column_key) {\n    try {\n        auto obj = *reinterpret_cast<realm::Obj*>(obj_ptr);\n        auto shared_realm = *reinterpret_cast<SharedRealm*>(shared_realm_ptr);\n\n        // Return an array of pointers: first to the wrapper, second to the table (if applicable)\n        jlong ret[2];\n\n        // Get set, put it in the wrapper and save pointer to be returned\n        object_store::Set set(shared_realm, obj, ColKey(column_key));\n        auto wrapper_ptr = new SetWrapper(set, \"io/realm/internal/ObservableSet\");\n        ret[0] = reinterpret_cast<jlong>(wrapper_ptr);\n\n        // Special case for objects: return the table. Ignore for other types\n        if (wrapper_ptr->collection().get_type() == PropertyType::Object) {\n            auto set_view_ref = obj.get_linkset(ColKey(column_key));\n\n            auto target_table_ptr = new TableRef(set_view_ref.get_target_table());\n            ret[1] = reinterpret_cast<jlong>(target_table_ptr);\n        } else {\n            ret[1] = reinterpret_cast<jlong>(nullptr);\n        }\n\n        jlongArray ret_array = env->NewLongArray(2);\n        if (!ret_array) {\n            ThrowException(env, OutOfMemory, \"Could not allocate memory to create OsSet.\");\n            return nullptr;\n        }\n\n        env->SetLongArrayRegion(ret_array, 0, 2, ret);\n        return ret_array;\n    }\n    CATCH_STD()\n    return nullptr;\n}\n\nJNIEXPORT jboolean JNICALL\nJava_io_realm_internal_OsSet_nativeIsValid(JNIEnv* env, jclass, jlong wrapper_ptr) {\n    try {\n        auto& wrapper = *reinterpret_cast<SetWrapper*>(wrapper_ptr);\n        object_store::Set& set = wrapper.collection();\n        return set.is_valid();\n    }\n    CATCH_STD()\n    return false;\n}\n\nJNIEXPORT void JNICALL\nJava_io_realm_internal_OsSet_nativeDeleteAll(JNIEnv* env, jclass, jlong wrapper_ptr) {\n    try {\n        auto& wrapper = *reinterpret_cast<SetWrapper*>(wrapper_ptr);\n        wrapper.collection().delete_all();\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT jlong JNICALL Java_io_realm_internal_OsSet_nativeGetQuery(JNIEnv* env, jclass, jlong wrapper_ptr)\n{\n    try {\n        auto& wrapper = *reinterpret_cast<SetWrapper*>(wrapper_ptr);\n        auto query = wrapper.collection().get_query();\n        query.set_ordering(std::make_unique<DescriptorOrdering>());\n        return reinterpret_cast<jlong>(new Query(std::move(query)));\n    }\n    CATCH_STD()\n    return reinterpret_cast<jlong>(nullptr);\n}\n\nJNIEXPORT jobject JNICALL\nJava_io_realm_internal_OsSet_nativeGetValueAtIndex(JNIEnv* env, jclass, jlong wrapper_ptr, jint position) {\n    try {\n        auto& wrapper = *reinterpret_cast<SetWrapper*>(wrapper_ptr);\n        object_store::Set& set = wrapper.collection();\n        const Mixed& value = set.get_any(position);\n        if (value.is_null()) {\n            return nullptr;\n        } else {\n            const DataType& type = value.get_type();\n            switch (type) {\n                case DataType::Type::Int:\n                    return JavaClassGlobalDef::new_long(env, value.get_int());\n                case DataType::Type::Double:\n                    return JavaClassGlobalDef::new_double(env, value.get_double());\n                case DataType::Type::Bool:\n                    return JavaClassGlobalDef::new_boolean(env, value.get_bool());\n                case DataType::Type::String:\n                    return to_jstring(env, value.get_string());\n                case DataType::Type::Binary:\n                    return JavaClassGlobalDef::new_byte_array(env, value.get_binary());\n                case DataType::Type::Float:\n                    return JavaClassGlobalDef::new_float(env, value.get_float());\n                case DataType::Type::UUID:\n                    return JavaClassGlobalDef::new_uuid(env, value.get_uuid());\n                case DataType::Type::ObjectId:\n                    return JavaClassGlobalDef::new_object_id(env, value.get_object_id());\n                case DataType::Type::Timestamp:\n                    return JavaClassGlobalDef::new_date(env, value.get_timestamp());\n                case DataType::Type::Decimal:\n                    return JavaClassGlobalDef::new_decimal128(env, value.get_decimal());\n                default:\n                    throw std::logic_error(\"'getValue' method only suitable for int, double, boolean, String, byte[], float, UUID, Decimal128 and ObjectId.\");\n            }\n        }\n    }\n    CATCH_STD()\n    return nullptr;\n}\n\nJNIEXPORT jlong JNICALL\nJava_io_realm_internal_OsSet_nativeSize(JNIEnv* env, jclass, jlong wrapper_ptr) {\n    try {\n        auto& wrapper = *reinterpret_cast<SetWrapper*>(wrapper_ptr);\n        object_store::Set& set = wrapper.collection();\n        return set.size();\n    }\n    CATCH_STD()\n    return 0;\n}\n\nJNIEXPORT jboolean JNICALL\nJava_io_realm_internal_OsSet_nativeContainsNull(JNIEnv *env, jclass, jlong wrapper_ptr) {\n    try {\n        auto& wrapper = *reinterpret_cast<SetWrapper*>(wrapper_ptr);\n        object_store::Set& set = wrapper.collection();\n\n        if (isSetNullable(env, set)) {\n            size_t found = set.find_any(Mixed());\n            return found != npos;       // npos represents \"not found\"\n        }\n    }\n    CATCH_STD()\n    return reinterpret_cast<jlong>(nullptr);\n}\n\nJNIEXPORT jboolean JNICALL\nJava_io_realm_internal_OsSet_nativeContainsBoolean(JNIEnv* env, jclass, jlong wrapper_ptr,\n                                                   jboolean j_value) {\n    try {\n        auto& wrapper = *reinterpret_cast<SetWrapper*>(wrapper_ptr);\n        object_store::Set& set = wrapper.collection();\n        size_t found = set.find_any(Mixed(bool(j_value)));\n        return found != npos;       // npos represents \"not found\"\n    }\n    CATCH_STD()\n    return reinterpret_cast<jlong>(nullptr);\n}\n\nJNIEXPORT jboolean JNICALL\nJava_io_realm_internal_OsSet_nativeContainsString(JNIEnv* env, jclass, jlong wrapper_ptr,\n                                                  jstring j_value) {\n    try {\n        auto& wrapper = *reinterpret_cast<SetWrapper*>(wrapper_ptr);\n        object_store::Set& set = wrapper.collection();\n        JStringAccessor value(env, j_value);\n        size_t found = set.find_any(Mixed(StringData(value)));\n        return found != npos;       // npos represents \"not found\"\n    }\n    CATCH_STD()\n    return reinterpret_cast<jlong>(nullptr);\n}\n\nJNIEXPORT jboolean JNICALL\nJava_io_realm_internal_OsSet_nativeContainsLong(JNIEnv* env, jclass, jlong wrapper_ptr,\n                                                jlong j_value) {\n    try {\n        auto& wrapper = *reinterpret_cast<SetWrapper*>(wrapper_ptr);\n        object_store::Set& set = wrapper.collection();\n        size_t found = set.find_any(Mixed(j_value));\n        return found != npos;       // npos represents \"not found\"\n    }\n    CATCH_STD()\n    return reinterpret_cast<jlong>(nullptr);\n}\n\nJNIEXPORT jboolean JNICALL\nJava_io_realm_internal_OsSet_nativeContainsFloat(JNIEnv* env, jclass, jlong wrapper_ptr,\n                                                 jfloat j_value) {\n    try {\n        auto& wrapper = *reinterpret_cast<SetWrapper*>(wrapper_ptr);\n        object_store::Set& set = wrapper.collection();\n        size_t found = set.find_any(Mixed(j_value));\n        return found != npos;       // npos represents \"not found\"\n    }\n    CATCH_STD()\n    return reinterpret_cast<jlong>(nullptr);\n}\n\nJNIEXPORT jboolean JNICALL\nJava_io_realm_internal_OsSet_nativeContainsDouble(JNIEnv* env, jclass, jlong wrapper_ptr,\n                                                  jdouble j_value) {\n    try {\n        auto& wrapper = *reinterpret_cast<SetWrapper*>(wrapper_ptr);\n        object_store::Set& set = wrapper.collection();\n        size_t found = set.find_any(Mixed(j_value));\n        return found != npos;       // npos represents \"not found\"\n    }\n    CATCH_STD()\n    return reinterpret_cast<jlong>(nullptr);\n}\n\nJNIEXPORT jboolean JNICALL\nJava_io_realm_internal_OsSet_nativeContainsBinary(JNIEnv* env, jclass, jlong wrapper_ptr,\n                                                  jbyteArray j_value) {\n    try {\n        auto& wrapper = *reinterpret_cast<SetWrapper*>(wrapper_ptr);\n        object_store::Set& set = wrapper.collection();\n        const OwnedBinaryData& data = OwnedBinaryData(JByteArrayAccessor(env, j_value).transform<BinaryData>());\n        size_t found = set.find_any(Mixed(data.get()));\n        return found != npos;       // npos represents \"not found\"\n    }\n    CATCH_STD()\n    return reinterpret_cast<jlong>(nullptr);\n}\n\nJNIEXPORT jboolean JNICALL\nJava_io_realm_internal_OsSet_nativeContainsDate(JNIEnv* env, jclass, jlong wrapper_ptr,\n                                                jlong j_value) {\n    try {\n        auto& wrapper = *reinterpret_cast<SetWrapper*>(wrapper_ptr);\n        object_store::Set& set = wrapper.collection();\n        realm::Timestamp timestamp = from_milliseconds(j_value);\n        size_t found = set.find_any(Mixed(timestamp));\n        return found != npos;       // npos represents \"not found\"\n    }\n    CATCH_STD()\n    return reinterpret_cast<jlong>(nullptr);\n}\n\nJNIEXPORT jboolean JNICALL\nJava_io_realm_internal_OsSet_nativeContainsDecimal128(JNIEnv* env, jclass, jlong wrapper_ptr,\n                                                      jlong j_low_value, jlong j_high_value) {\n    try {\n        auto& wrapper = *reinterpret_cast<SetWrapper*>(wrapper_ptr);\n        object_store::Set& set = wrapper.collection();\n        Decimal128::Bid128 raw {static_cast<uint64_t>(j_low_value), static_cast<uint64_t>(j_high_value)};\n        Decimal128 decimal128 = Decimal128(raw);\n        size_t found = set.find_any(Mixed(decimal128));\n        return found != npos;       // npos represents \"not found\"\n    }\n    CATCH_STD()\n    return reinterpret_cast<jlong>(nullptr);\n}\n\nJNIEXPORT jboolean JNICALL\nJava_io_realm_internal_OsSet_nativeContainsObjectId(JNIEnv* env, jclass, jlong wrapper_ptr,\n                                                    jstring j_value) {\n    try {\n        auto& wrapper = *reinterpret_cast<SetWrapper*>(wrapper_ptr);\n        object_store::Set& set = wrapper.collection();\n        JStringAccessor data(env, j_value);\n        const ObjectId object_id = ObjectId(StringData(data).data());\n        size_t found = set.find_any(Mixed(object_id));\n        return found != npos;       // npos represents \"not found\"\n    }\n    CATCH_STD()\n    return reinterpret_cast<jlong>(nullptr);\n}\n\nJNIEXPORT jboolean JNICALL\nJava_io_realm_internal_OsSet_nativeContainsUUID(JNIEnv* env, jclass, jlong wrapper_ptr,\n                                                jstring j_value) {\n    try {\n        auto& wrapper = *reinterpret_cast<SetWrapper*>(wrapper_ptr);\n        object_store::Set& set = wrapper.collection();\n        JStringAccessor value(env, j_value);\n        const UUID& uuid = UUID(StringData(value).data());\n        size_t found = set.find_any(Mixed(uuid));\n        return found != npos;       // npos represents \"not found\"\n    }\n    CATCH_STD()\n    return reinterpret_cast<jlong>(nullptr);\n}\n\nJNIEXPORT jboolean JNICALL\nJava_io_realm_internal_OsSet_nativeContainsRow(JNIEnv* env, jclass, jlong wrapper_ptr,\n                                               jlong j_obj_key) {\n    try {\n        auto& wrapper = *reinterpret_cast<SetWrapper*>(wrapper_ptr);\n        object_store::Set& set = wrapper.collection();\n        ObjKey object_key(j_obj_key);\n        size_t found = set.find_any(object_key);\n        return found != npos;       // npos represents \"not found\"\n    }\n    CATCH_STD()\n    return reinterpret_cast<jlong>(nullptr);\n}\n\nJNIEXPORT jboolean JNICALL\nJava_io_realm_internal_OsSet_nativeContainsRealmAny(JNIEnv* env, jclass, jlong wrapper_ptr,\n                                                 jlong mixed_ptr) {\n    try {\n        auto& wrapper = *reinterpret_cast<SetWrapper*>(wrapper_ptr);\n        object_store::Set& set = wrapper.collection();\n        auto& java_value = *reinterpret_cast<JavaValue*>(mixed_ptr);\n        size_t found = set.find_any(java_value.to_mixed());\n        return found != npos;       // npos represents \"not found\"\n    }\n    CATCH_STD()\n    return reinterpret_cast<jlong>(nullptr);\n}\n\nJNIEXPORT jlongArray JNICALL\nJava_io_realm_internal_OsSet_nativeAddNull(JNIEnv* env, jclass, jlong wrapper_ptr) {\n    try {\n        auto& wrapper = *reinterpret_cast<SetWrapper*>(wrapper_ptr);\n        object_store::Set& set = wrapper.collection();\n        JavaAccessorContext context(env);\n\n        if (isSetNullable(env, set)) {\n            const std::pair<size_t, bool> &add_pair = set.insert(context, Any());\n            jlong ret[2];\n            ret[0] = add_pair.first;    // index\n            ret[1] = add_pair.second;   // found (or not)\n            jlongArray ret_array = env->NewLongArray(2);\n            env->SetLongArrayRegion(ret_array, 0, 2, ret);\n            return ret_array;\n        }\n    }\n    CATCH_STD()\n    return nullptr;\n}\n\nJNIEXPORT jlongArray JNICALL\nJava_io_realm_internal_OsSet_nativeAddBoolean(JNIEnv* env, jclass, jlong wrapper_ptr,\n                                              jboolean j_value) {\n    try {\n        auto& wrapper = *reinterpret_cast<SetWrapper*>(wrapper_ptr);\n        object_store::Set& set = wrapper.collection();\n        JavaAccessorContext context(env);\n\n        // TODO: abstract this call so that the rest is the same for all types\n        const std::pair<size_t, bool>& add_pair = set.insert(context, Any(j_value));\n\n        jlong ret[2];\n        ret[0] = add_pair.first;    // index\n        ret[1] = add_pair.second;   // found (or not)\n        jlongArray ret_array = env->NewLongArray(2);\n        env->SetLongArrayRegion(ret_array, 0, 2, ret);\n        return ret_array;\n    }\n    CATCH_STD()\n    return nullptr;\n}\n\nJNIEXPORT jlongArray JNICALL\nJava_io_realm_internal_OsSet_nativeAddString(JNIEnv* env, jclass, jlong wrapper_ptr, jstring j_value) {\n    try {\n        auto& wrapper = *reinterpret_cast<SetWrapper*>(wrapper_ptr);\n        object_store::Set& set = wrapper.collection();\n        JStringAccessor value(env, j_value);\n        JavaAccessorContext context(env);\n\n        // TODO: abstract this call so that the rest is the same for all types\n        const std::pair<size_t, bool>& add_pair = set.insert(context, Any(value));\n\n        jlong ret[2];\n        ret[0] = add_pair.first;    // index\n        ret[1] = add_pair.second;   // found (or not)\n        jlongArray ret_array = env->NewLongArray(2);\n        env->SetLongArrayRegion(ret_array, 0, 2, ret);\n        return ret_array;\n    }\n    CATCH_STD()\n    return nullptr;\n}\n\nJNIEXPORT jlongArray JNICALL\nJava_io_realm_internal_OsSet_nativeAddLong(JNIEnv* env, jclass, jlong wrapper_ptr, jlong j_value) {\n    try {\n        auto& wrapper = *reinterpret_cast<SetWrapper*>(wrapper_ptr);\n        object_store::Set& set = wrapper.collection();\n        JavaAccessorContext context(env);\n\n        // TODO: abstract this call so that the rest is the same for all types\n        const std::pair<size_t, bool>& add_pair = set.insert(context, Any(j_value));\n\n        jlong ret[2];\n        ret[0] = add_pair.first;    // index\n        ret[1] = add_pair.second;   // found (or not)\n        jlongArray ret_array = env->NewLongArray(2);\n        env->SetLongArrayRegion(ret_array, 0, 2, ret);\n        return ret_array;\n    }\n    CATCH_STD()\n    return nullptr;\n}\n\nJNIEXPORT jlongArray JNICALL\nJava_io_realm_internal_OsSet_nativeAddFloat(JNIEnv* env, jclass, jlong wrapper_ptr, jfloat j_value) {\n    try {\n        auto& wrapper = *reinterpret_cast<SetWrapper*>(wrapper_ptr);\n        object_store::Set& set = wrapper.collection();\n        JavaAccessorContext context(env);\n\n        // TODO: abstract this call so that the rest is the same for all types\n        const std::pair<size_t, bool>& add_pair = set.insert(context, Any(j_value));\n\n        jlong ret[2];\n        ret[0] = add_pair.first;    // index\n        ret[1] = add_pair.second;   // found (or not)\n        jlongArray ret_array = env->NewLongArray(2);\n        env->SetLongArrayRegion(ret_array, 0, 2, ret);\n        return ret_array;\n    }\n    CATCH_STD()\n    return nullptr;\n}\n\nJNIEXPORT jlongArray JNICALL\nJava_io_realm_internal_OsSet_nativeAddDouble(JNIEnv* env, jclass, jlong wrapper_ptr,\n                                             jdouble j_value) {\n    try {\n        auto& wrapper = *reinterpret_cast<SetWrapper*>(wrapper_ptr);\n        object_store::Set& set = wrapper.collection();\n        JavaAccessorContext context(env);\n\n        // TODO: abstract this call so that the rest is the same for all types\n        const std::pair<size_t, bool>& add_pair = set.insert(context, Any(j_value));\n\n        jlong ret[2];\n        ret[0] = add_pair.first;    // index\n        ret[1] = add_pair.second;   // found (or not)\n        jlongArray ret_array = env->NewLongArray(2);\n        env->SetLongArrayRegion(ret_array, 0, 2, ret);\n        return ret_array;\n    }\n    CATCH_STD()\n    return nullptr;\n}\n\nJNIEXPORT jlongArray JNICALL\nJava_io_realm_internal_OsSet_nativeAddBinary(JNIEnv* env, jclass, jlong wrapper_ptr,\n                                             jbyteArray j_value) {\n    try {\n        auto& wrapper = *reinterpret_cast<SetWrapper*>(wrapper_ptr);\n        object_store::Set& set = wrapper.collection();\n        JavaAccessorContext context(env);\n        JByteArrayAccessor data(env, j_value);\n\n        // TODO: abstract this call so that the rest is the same for all types\n        const std::pair<size_t, bool>& add_pair = set.insert(context, Any(data));\n\n        jlong ret[2];\n        ret[0] = add_pair.first;    // index\n        ret[1] = add_pair.second;   // found (or not)\n        jlongArray ret_array = env->NewLongArray(2);\n        env->SetLongArrayRegion(ret_array, 0, 2, ret);\n        return ret_array;\n    }\n    CATCH_STD()\n    return nullptr;\n}\n\nJNIEXPORT jlongArray JNICALL\nJava_io_realm_internal_OsSet_nativeAddDate(JNIEnv* env, jclass, jlong wrapper_ptr,\n                                           jlong j_value) {\n    try {\n        auto& wrapper = *reinterpret_cast<SetWrapper*>(wrapper_ptr);\n        object_store::Set& set = wrapper.collection();\n        JavaAccessorContext context(env);\n\n        // TODO: abstract this call so that the rest is the same for all types\n        const std::pair<size_t, bool>& add_pair = set.insert(context, Any(j_value));\n\n        jlong ret[2];\n        ret[0] = add_pair.first;    // index\n        ret[1] = add_pair.second;   // found (or not)\n        jlongArray ret_array = env->NewLongArray(2);\n        env->SetLongArrayRegion(ret_array, 0, 2, ret);\n        return ret_array;\n    }\n    CATCH_STD()\n    return nullptr;\n}\n\nJNIEXPORT jlongArray JNICALL\nJava_io_realm_internal_OsSet_nativeAddDecimal128(JNIEnv* env, jclass, jlong wrapper_ptr,\n                                                 jlong j_low_value, jlong j_high_value) {\n    try {\n        auto& wrapper = *reinterpret_cast<SetWrapper*>(wrapper_ptr);\n        object_store::Set& set = wrapper.collection();\n        JavaAccessorContext context(env);\n        Decimal128::Bid128 raw {static_cast<uint64_t>(j_low_value), static_cast<uint64_t>(j_high_value)};\n        Decimal128 decimal128 = Decimal128(raw);\n\n        // TODO: abstract this call so that the rest is the same for all types\n        const std::pair<size_t, bool>& add_pair = set.insert(context, Any(decimal128));\n\n        jlong ret[2];\n        ret[0] = add_pair.first;    // index\n        ret[1] = add_pair.second;   // found (or not)\n        jlongArray ret_array = env->NewLongArray(2);\n        env->SetLongArrayRegion(ret_array, 0, 2, ret);\n        return ret_array;\n    }\n    CATCH_STD()\n    return nullptr;\n}\n\nJNIEXPORT jlongArray JNICALL\nJava_io_realm_internal_OsSet_nativeAddObjectId(JNIEnv* env, jclass, jlong wrapper_ptr,\n                                               jstring j_value) {\n    try {\n        auto& wrapper = *reinterpret_cast<SetWrapper*>(wrapper_ptr);\n        object_store::Set& set = wrapper.collection();\n        JavaAccessorContext context(env);\n        JStringAccessor data(env, j_value);\n        const ObjectId object_id = ObjectId(StringData(data).data());\n\n        // TODO: abstract this call so that the rest is the same for all types\n        const std::pair<size_t, bool>& add_pair = set.insert(context, Any(object_id));\n\n        jlong ret[2];\n        ret[0] = add_pair.first;    // index\n        ret[1] = add_pair.second;   // found (or not)\n        jlongArray ret_array = env->NewLongArray(2);\n        env->SetLongArrayRegion(ret_array, 0, 2, ret);\n        return ret_array;\n    }\n    CATCH_STD()\n    return nullptr;\n}\n\nJNIEXPORT jlongArray JNICALL\nJava_io_realm_internal_OsSet_nativeAddUUID(JNIEnv* env, jclass, jlong wrapper_ptr,\n                                           jstring j_value) {\n    try {\n        auto& wrapper = *reinterpret_cast<SetWrapper*>(wrapper_ptr);\n        object_store::Set& set = wrapper.collection();\n        JavaAccessorContext context(env);\n        JStringAccessor value(env, j_value);\n        const UUID& uuid = UUID(StringData(value).data());\n\n        // TODO: abstract this call so that the rest is the same for all types\n        const std::pair<size_t, bool>& add_pair = set.insert(context, Any(uuid));\n\n        jlong ret[2];\n        ret[0] = add_pair.first;    // index\n        ret[1] = add_pair.second;   // found (or not)\n        jlongArray ret_array = env->NewLongArray(2);\n        env->SetLongArrayRegion(ret_array, 0, 2, ret);\n        return ret_array;\n    }\n    CATCH_STD()\n    return nullptr;\n}\n\nJNIEXPORT jlongArray JNICALL\nJava_io_realm_internal_OsSet_nativeAddRow(JNIEnv* env, jclass, jlong wrapper_ptr,\n                                          jlong j_obj_key) {\n    try {\n        auto& wrapper = *reinterpret_cast<SetWrapper*>(wrapper_ptr);\n        object_store::Set& set = wrapper.collection();\n        ObjKey object_key(j_obj_key);\n\n        // TODO: abstract this call so that the rest is the same for all types\n        const std::pair<size_t, bool>& add_pair = set.insert(object_key);\n\n        jlong ret[2];\n        ret[0] = add_pair.first;    // index\n        ret[1] = add_pair.second;   // found (or not)\n        jlongArray ret_array = env->NewLongArray(2);\n        env->SetLongArrayRegion(ret_array, 0, 2, ret);\n        return ret_array;\n    }\n    CATCH_STD()\n    return nullptr;\n}\n\n\n\nJNIEXPORT jlongArray JNICALL\nJava_io_realm_internal_OsSet_nativeAddRealmAny(JNIEnv* env, jclass, jlong wrapper_ptr,\n                                            jlong mixed_ptr) {\n    try {\n        auto& wrapper = *reinterpret_cast<SetWrapper*>(wrapper_ptr);\n        object_store::Set& set = wrapper.collection();\n        auto& java_value = *reinterpret_cast<JavaValue*>(mixed_ptr);\n\n        // TODO: abstract this call so that the rest is the same for all types\n        const std::pair<size_t, bool>& add_pair = set.insert(java_value.to_mixed());\n\n        jlong ret[2];\n        ret[0] = add_pair.first;    // index\n        ret[1] = add_pair.second;   // found (or not)\n        jlongArray ret_array = env->NewLongArray(2);\n        env->SetLongArrayRegion(ret_array, 0, 2, ret);\n        return ret_array;\n    }\n    CATCH_STD()\n    return nullptr;\n}\n\nJNIEXPORT jlongArray JNICALL\nJava_io_realm_internal_OsSet_nativeRemoveNull(JNIEnv* env, jclass, jlong wrapper_ptr) {\n    try {\n        auto& wrapper = *reinterpret_cast<SetWrapper*>(wrapper_ptr);\n        object_store::Set& set = wrapper.collection();\n\n        if (isSetNullable(env, set)) {\n            const std::pair<size_t, bool> &remove_pair = set.remove_any(Mixed());\n            jlong ret[2];\n            ret[0] = remove_pair.first;     // index\n            ret[1] = remove_pair.second;    // found (or not)\n            jlongArray ret_array = env->NewLongArray(2);\n            env->SetLongArrayRegion(ret_array, 0, 2, ret);\n            return ret_array;\n        }\n    }\n    CATCH_STD()\n    return nullptr;\n}\n\nJNIEXPORT jlongArray JNICALL\nJava_io_realm_internal_OsSet_nativeRemoveBoolean(JNIEnv* env, jclass, jlong wrapper_ptr,\n                                                 jboolean j_value) {\n    try {\n        auto& wrapper = *reinterpret_cast<SetWrapper*>(wrapper_ptr);\n        object_store::Set& set = wrapper.collection();\n\n        // TODO: abstract this call so that the rest is the same for all types\n        const std::pair<size_t, bool>& remove_pair = set.remove_any(Mixed(bool(j_value)));\n\n        jlong ret[2];\n        ret[0] = remove_pair.first;     // index\n        ret[1] = remove_pair.second;    // found (or not)\n        jlongArray ret_array = env->NewLongArray(2);\n        env->SetLongArrayRegion(ret_array, 0, 2, ret);\n        return ret_array;\n    }\n    CATCH_STD()\n    return nullptr;\n}\n\nJNIEXPORT jlongArray JNICALL\nJava_io_realm_internal_OsSet_nativeRemoveString(JNIEnv* env, jclass, jlong wrapper_ptr, jstring j_value) {\n    try {\n        auto& wrapper = *reinterpret_cast<SetWrapper*>(wrapper_ptr);\n        object_store::Set& set = wrapper.collection();\n        JStringAccessor value(env, j_value);\n\n        // TODO: abstract this call so that the rest is the same for all types\n        const std::pair<size_t, bool>& remove_pair = set.remove_any(Mixed(StringData(value)));\n\n        jlong ret[2];\n        ret[0] = remove_pair.first;     // index\n        ret[1] = remove_pair.second;    // found (or not)\n        jlongArray ret_array = env->NewLongArray(2);\n        env->SetLongArrayRegion(ret_array, 0, 2, ret);\n        return ret_array;\n    }\n    CATCH_STD()\n    return nullptr;\n}\n\nJNIEXPORT jlongArray JNICALL\nJava_io_realm_internal_OsSet_nativeRemoveLong(JNIEnv* env, jclass, jlong wrapper_ptr,\n                                              jlong j_value) {\n    try {\n        auto& wrapper = *reinterpret_cast<SetWrapper*>(wrapper_ptr);\n        object_store::Set& set = wrapper.collection();\n\n        // TODO: abstract this call so that the rest is the same for all types\n        const std::pair<size_t, bool>& remove_pair = set.remove_any(Mixed(j_value));\n\n        jlong ret[2];\n        ret[0] = remove_pair.first;     // index\n        ret[1] = remove_pair.second;    // found (or not)\n        jlongArray ret_array = env->NewLongArray(2);\n        env->SetLongArrayRegion(ret_array, 0, 2, ret);\n        return ret_array;\n    }\n    CATCH_STD()\n    return nullptr;\n}\n\nJNIEXPORT jlongArray JNICALL\nJava_io_realm_internal_OsSet_nativeRemoveFloat(JNIEnv* env, jclass, jlong wrapper_ptr,\n                                               jfloat j_value) {\n    try {\n        auto& wrapper = *reinterpret_cast<SetWrapper*>(wrapper_ptr);\n        object_store::Set& set = wrapper.collection();\n\n        // TODO: abstract this call so that the rest is the same for all types\n        const std::pair<size_t, bool>& remove_pair = set.remove_any(Mixed(j_value));\n\n        jlong ret[2];\n        ret[0] = remove_pair.first;     // index\n        ret[1] = remove_pair.second;    // found (or not)\n        jlongArray ret_array = env->NewLongArray(2);\n        env->SetLongArrayRegion(ret_array, 0, 2, ret);\n        return ret_array;\n    }\n    CATCH_STD()\n    return nullptr;\n}\n\nJNIEXPORT jlongArray JNICALL\nJava_io_realm_internal_OsSet_nativeRemoveDouble(JNIEnv* env, jclass, jlong wrapper_ptr,\n                                                jdouble j_value) {\n    try {\n        auto& wrapper = *reinterpret_cast<SetWrapper*>(wrapper_ptr);\n        object_store::Set& set = wrapper.collection();\n\n        // TODO: abstract this call so that the rest is the same for all types\n        const std::pair<size_t, bool>& remove_pair = set.remove_any(Mixed(j_value));\n\n        jlong ret[2];\n        ret[0] = remove_pair.first;     // index\n        ret[1] = remove_pair.second;    // found (or not)\n        jlongArray ret_array = env->NewLongArray(2);\n        env->SetLongArrayRegion(ret_array, 0, 2, ret);\n        return ret_array;\n    }\n    CATCH_STD()\n    return nullptr;\n}\n\nJNIEXPORT jlongArray JNICALL\nJava_io_realm_internal_OsSet_nativeRemoveBinary(JNIEnv* env, jclass, jlong wrapper_ptr,\n                                                jbyteArray j_value) {\n    try {\n        auto& wrapper = *reinterpret_cast<SetWrapper*>(wrapper_ptr);\n        object_store::Set& set = wrapper.collection();\n        const OwnedBinaryData& data = OwnedBinaryData(JByteArrayAccessor(env, j_value).transform<BinaryData>());\n\n        // TODO: abstract this call so that the rest is the same for all types\n        const std::pair<size_t, bool>& remove_pair = set.remove_any(Mixed(data.get()));\n\n        jlong ret[2];\n        ret[0] = remove_pair.first;     // index\n        ret[1] = remove_pair.second;    // found (or not)\n        jlongArray ret_array = env->NewLongArray(2);\n        env->SetLongArrayRegion(ret_array, 0, 2, ret);\n        return ret_array;\n    }\n    CATCH_STD()\n    return nullptr;\n}\n\nJNIEXPORT jlongArray JNICALL\nJava_io_realm_internal_OsSet_nativeRemoveDate(JNIEnv* env, jclass, jlong wrapper_ptr,\n                                              jlong j_value) {\n    try {\n        auto& wrapper = *reinterpret_cast<SetWrapper*>(wrapper_ptr);\n        object_store::Set& set = wrapper.collection();\n        realm::Timestamp timestamp = from_milliseconds(j_value);\n\n        // TODO: abstract this call so that the rest is the same for all types\n        const std::pair<size_t, bool>& remove_pair = set.remove_any(Mixed(timestamp));\n\n        jlong ret[2];\n        ret[0] = remove_pair.first;     // index\n        ret[1] = remove_pair.second;    // found (or not)\n        jlongArray ret_array = env->NewLongArray(2);\n        env->SetLongArrayRegion(ret_array, 0, 2, ret);\n        return ret_array;\n    }\n    CATCH_STD()\n    return nullptr;\n}\n\nJNIEXPORT jlongArray JNICALL\nJava_io_realm_internal_OsSet_nativeRemoveDecimal128(JNIEnv* env, jclass, jlong wrapper_ptr,\n                                                    jlong j_low_value, jlong j_high_value) {\n    try {\n        auto& wrapper = *reinterpret_cast<SetWrapper*>(wrapper_ptr);\n        object_store::Set& set = wrapper.collection();\n        Decimal128::Bid128 raw {static_cast<uint64_t>(j_low_value), static_cast<uint64_t>(j_high_value)};\n        Decimal128 decimal128 = Decimal128(raw);\n\n        // TODO: abstract this call so that the rest is the same for all types\n        const std::pair<size_t, bool>& remove_pair = set.remove_any(Mixed(decimal128));\n\n        jlong ret[2];\n        ret[0] = remove_pair.first;     // index\n        ret[1] = remove_pair.second;    // found (or not)\n        jlongArray ret_array = env->NewLongArray(2);\n        env->SetLongArrayRegion(ret_array, 0, 2, ret);\n        return ret_array;\n    }\n    CATCH_STD()\n    return nullptr;\n}\n\nJNIEXPORT jlongArray JNICALL\nJava_io_realm_internal_OsSet_nativeRemoveObjectId(JNIEnv* env, jclass, jlong wrapper_ptr,\n                                                  jstring j_value) {\n    try {\n        auto& wrapper = *reinterpret_cast<SetWrapper*>(wrapper_ptr);\n        object_store::Set& set = wrapper.collection();\n        JStringAccessor data(env, j_value);\n        const ObjectId object_id = ObjectId(StringData(data).data());\n\n        // TODO: abstract this call so that the rest is the same for all types\n        const std::pair<size_t, bool>& remove_pair = set.remove_any(Mixed(object_id));\n\n\n        jlong ret[2];\n        ret[0] = remove_pair.first;     // index\n        ret[1] = remove_pair.second;    // found (or not)\n        jlongArray ret_array = env->NewLongArray(2);\n        env->SetLongArrayRegion(ret_array, 0, 2, ret);\n        return ret_array;\n    }\n    CATCH_STD()\n    return nullptr;\n}\n\nJNIEXPORT jlongArray JNICALL\nJava_io_realm_internal_OsSet_nativeRemoveUUID(JNIEnv* env, jclass, jlong wrapper_ptr,\n                                              jstring j_value) {\n    try {\n        auto& wrapper = *reinterpret_cast<SetWrapper*>(wrapper_ptr);\n        object_store::Set& set = wrapper.collection();\n        JStringAccessor value(env, j_value);\n        const UUID& uuid = UUID(StringData(value).data());\n\n        // TODO: abstract this call so that the rest is the same for all types\n        const std::pair<size_t, bool>& remove_pair = set.remove_any(Mixed(uuid));\n\n        jlong ret[2];\n        ret[0] = remove_pair.first;     // index\n        ret[1] = remove_pair.second;    // found (or not)\n        jlongArray ret_array = env->NewLongArray(2);\n        env->SetLongArrayRegion(ret_array, 0, 2, ret);\n        return ret_array;\n    }\n    CATCH_STD()\n    return nullptr;\n}\n\nJNIEXPORT jlongArray JNICALL\nJava_io_realm_internal_OsSet_nativeRemoveRow(JNIEnv* env, jclass, jlong wrapper_ptr,\n                                             jlong j_obj_key) {\n    try {\n        auto& wrapper = *reinterpret_cast<SetWrapper*>(wrapper_ptr);\n        object_store::Set& set = wrapper.collection();\n        ObjKey object_key(j_obj_key);\n\n        // TODO: abstract this call so that the rest is the same for all types\n        const std::pair<size_t, bool>& remove_pair = set.remove(object_key);\n\n        jlong ret[2];\n        ret[0] = remove_pair.first;     // index\n        ret[1] = remove_pair.second;    // found (or not)\n        jlongArray ret_array = env->NewLongArray(2);\n        env->SetLongArrayRegion(ret_array, 0, 2, ret);\n        return ret_array;\n    }\n    CATCH_STD()\n    return nullptr;\n}\n\nJNIEXPORT jlongArray JNICALL\nJava_io_realm_internal_OsSet_nativeRemoveRealmAny(JNIEnv* env, jclass, jlong wrapper_ptr,\n                                               jlong mixed_ptr) {\n    try {\n        auto& wrapper = *reinterpret_cast<SetWrapper*>(wrapper_ptr);\n        object_store::Set& set = wrapper.collection();\n        auto& java_value = *reinterpret_cast<JavaValue*>(mixed_ptr);\n\n        // TODO: abstract this call so that the rest is the same for all types\n        const std::pair<size_t, bool>& remove_pair = set.remove(java_value.to_mixed());\n\n        jlong ret[2];\n        ret[0] = remove_pair.first;     // index\n        ret[1] = remove_pair.second;    // found (or not)\n        jlongArray ret_array = env->NewLongArray(2);\n        env->SetLongArrayRegion(ret_array, 0, 2, ret);\n        return ret_array;\n    }\n    CATCH_STD()\n    return nullptr;\n}\n\nJNIEXPORT jlong JNICALL\nJava_io_realm_internal_OsSet_nativeGetRow(JNIEnv* env, jclass, jlong wrapper_ptr,\n                                          jint j_index) {\n    try {\n        auto& wrapper = *reinterpret_cast<SetWrapper*>(wrapper_ptr);\n        object_store::Set& set = wrapper.collection();\n        const Obj &obj = set.get(j_index);\n        return obj.get_key().value;\n    }\n    CATCH_STD()\n    return -1;\n}\n\nJNIEXPORT jlong JNICALL\nJava_io_realm_internal_OsSet_nativeGetRealmAny(JNIEnv* env, jclass, jlong wrapper_ptr,\n                                            jint j_index) {\n    try {\n        auto& wrapper = *reinterpret_cast<SetWrapper*>(wrapper_ptr);\n        object_store::Set& set = wrapper.collection();\n        const Mixed& mixed = set.get_any(j_index);\n        return reinterpret_cast<jlong>(new JavaValue(from_mixed(mixed)));\n    }\n    CATCH_STD()\n    return -1;\n}\n\nJNIEXPORT jboolean JNICALL\nJava_io_realm_internal_OsSet_nativeContainsAll(JNIEnv*, jclass, jlong wrapper_ptr, jlong other_wrapper_ptr) {\n    auto& wrapper = *reinterpret_cast<SetWrapper*>(wrapper_ptr);\n    object_store::Set& set = wrapper.collection();\n    auto& other_wrapper = *reinterpret_cast<SetWrapper*>(other_wrapper_ptr);\n    object_store::Set& other_set = other_wrapper.collection();\n\n    // If other set is a subset of set then set contains other set\n    bool is_contained = other_set.is_subset_of(set);\n    return is_contained;\n}\n\nJNIEXPORT jboolean JNICALL\nJava_io_realm_internal_OsSet_nativeUnion(JNIEnv*, jclass, jlong wrapper_ptr, jlong other_wrapper_ptr) {\n    auto& wrapper = *reinterpret_cast<SetWrapper*>(wrapper_ptr);\n    object_store::Set& set = wrapper.collection();\n    auto& other_wrapper = *reinterpret_cast<SetWrapper*>(other_wrapper_ptr);\n    object_store::Set& other_set = other_wrapper.collection();\n\n    // If other set is a subset of set it means set will not change after the union\n    bool has_changed = !other_set.is_subset_of(set);\n    set.assign_union(other_set);\n    return has_changed;\n}\n\nJNIEXPORT jboolean JNICALL\nJava_io_realm_internal_OsSet_nativeAsymmetricDifference(JNIEnv*,\n                                                        jclass,\n                                                        jlong wrapper_ptr,\n                                                        jlong other_wrapper_ptr) {\n    auto& wrapper = *reinterpret_cast<SetWrapper*>(wrapper_ptr);\n    object_store::Set& set = wrapper.collection();\n    auto& other_wrapper = *reinterpret_cast<SetWrapper*>(other_wrapper_ptr);\n    object_store::Set& other_set = other_wrapper.collection();\n\n    // If other set is a subset of set it means set will change after the difference\n    bool has_changed = other_set.is_subset_of(set);\n    set.assign_difference(other_set);\n    return has_changed;\n}\n\nJNIEXPORT jboolean JNICALL\nJava_io_realm_internal_OsSet_nativeIntersect(JNIEnv*,\n                                             jclass,\n                                             jlong wrapper_ptr,\n                                             jlong other_wrapper_ptr) {\n    auto& wrapper = *reinterpret_cast<SetWrapper*>(wrapper_ptr);\n    object_store::Set& set = wrapper.collection();\n    auto& other_wrapper = *reinterpret_cast<SetWrapper*>(other_wrapper_ptr);\n    object_store::Set& other_set = other_wrapper.collection();\n\n    // If other set intersects set it means set will not change after the intersection\n    bool has_changed = !set.intersects(other_set);\n    set.assign_intersection(other_set);\n    return has_changed;\n}\n\nJNIEXPORT void JNICALL\nJava_io_realm_internal_OsSet_nativeClear(JNIEnv* env, jclass, jlong wrapper_ptr) {\n    try {\n        auto& wrapper = *reinterpret_cast<SetWrapper*>(wrapper_ptr);\n        object_store::Set& set = wrapper.collection();\n        set.remove_all();\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT jlong JNICALL\nJava_io_realm_internal_OsSet_nativeFreeze(JNIEnv* env, jclass, jlong wrapper_ptr,\n                                          jlong frozen_realm_ptr) {\n    try {\n        auto& wrapper = *reinterpret_cast<SetWrapper*>(wrapper_ptr);\n        object_store::Set& set = wrapper.collection();\n        auto& shared_realm_ptr = *reinterpret_cast<std::shared_ptr<Realm>*>(frozen_realm_ptr);\n        object_store::Set frozen_set = set.freeze(shared_realm_ptr);\n        return reinterpret_cast<jlong>(new SetWrapper(frozen_set, \"io/realm/internal/ObservableSet\"));\n    }\n    CATCH_STD()\n    return reinterpret_cast<jlong>(nullptr);\n}\n\nJNIEXPORT jboolean JNICALL\nJava_io_realm_internal_OsSet_nativeContainsAllRealmAnyCollection(JNIEnv* env, jclass, jlong wrapper_ptr,\n                                                              jlong mixed_collection_ptr) {\n    try {\n        auto& wrapper = *reinterpret_cast<SetWrapper*>(wrapper_ptr);\n        object_store::Set& set = wrapper.collection();\n        auto &collection = *reinterpret_cast<std::vector<JavaValue> *>(mixed_collection_ptr);\n        const std::vector<Mixed>& mixed_collection = to_mixed_vector(collection);\n\n        for (const Mixed& mixed : mixed_collection) {\n            if (!mixed.is_null() || isSetNullable(env, set)) {\n                size_t found;\n                found = set.find_any(mixed);\n\n                if (found == npos) {    // npos represents \"not found\"\n                    return false;\n                }\n            }\n        }\n        return true;\n    }\n    CATCH_STD()\n    return false;\n}\n\nJNIEXPORT jboolean JNICALL\nJava_io_realm_internal_OsSet_nativeAddAllRealmAnyCollection(JNIEnv* env, jclass, jlong wrapper_ptr,\n                                                         jlong mixed_collection_ptr) {\n    try {\n        auto& wrapper = *reinterpret_cast<SetWrapper*>(wrapper_ptr);\n        object_store::Set& set = wrapper.collection();\n        auto& collection = *reinterpret_cast<std::vector<JavaValue> *>(mixed_collection_ptr);\n        const std::vector<Mixed>& mixed_collection = to_mixed_vector(collection);\n        bool set_has_changed = false;\n\n        for (const Mixed &mixed : mixed_collection) {\n            if (!mixed.is_null() || isSetNullable(env, set)) {\n                const std::pair<size_t, bool> &insert_pair = set.insert_any(mixed);\n\n                // If we get true it means the element was not there and therefore it has changed\n                if (insert_pair.second) {\n                    set_has_changed = true;\n                }\n            }\n        }\n        return set_has_changed;\n    }\n    CATCH_STD()\n    return false;\n}\n\nJNIEXPORT jboolean JNICALL\nJava_io_realm_internal_OsSet_nativeRemoveAllRealmAnyCollection(JNIEnv* env, jclass, jlong wrapper_ptr,\n                                                            jlong mixed_collection_ptr) {\n    try {\n        auto& wrapper = *reinterpret_cast<SetWrapper*>(wrapper_ptr);\n        object_store::Set& set = wrapper.collection();\n        auto& collection = *reinterpret_cast<std::vector<JavaValue> *>(mixed_collection_ptr);\n        const std::vector<Mixed>& mixed_collection = to_mixed_vector(collection);\n        bool set_has_changed = false;\n\n        for (const Mixed &mixed : mixed_collection) {\n            if (!mixed.is_null() || isSetNullable(env, set)) {\n                const std::pair<size_t, bool> &remove_pair = set.remove_any(mixed);\n\n                // If we get true it means the element was not there and therefore it has changed\n                if (remove_pair.second) {\n                    set_has_changed = true;\n                }\n            }\n        }\n        return set_has_changed;\n    }\n    CATCH_STD()\n    return false;\n}\n\nJNIEXPORT jboolean JNICALL\nJava_io_realm_internal_OsSet_nativeRetainAllRealmAnyCollection(JNIEnv* env, jclass, jlong wrapper_ptr,\n                                                            jlong mixed_collection_ptr) {\n    try {\n        auto& wrapper = *reinterpret_cast<SetWrapper*>(wrapper_ptr);\n        object_store::Set& set = wrapper.collection();\n        auto &collection = *reinterpret_cast<std::vector<JavaValue> *>(mixed_collection_ptr);\n        const std::vector<Mixed> &mixed_collection = to_mixed_vector(collection);\n\n        std::vector<Mixed> common_elements;\n        bool set_has_changed = false;\n\n        for (const Mixed &mixed : mixed_collection) {\n            if (!mixed.is_null() || isSetNullable(env, set)) {\n                // Check for present values\n                if (set.find_any(mixed) != realm::npos) {\n                    // Put shared elements and store them in an auxiliary structure to use later\n                    common_elements.push_back(mixed);\n                } else {\n                    // If an element is not found that means the set will change\n                    set_has_changed = true;\n                }\n            }\n        }\n\n        // Insert shared elements now\n        set.remove_all();\n        for (auto& shared_element : common_elements) {\n            set.insert_any(shared_element);\n        }\n\n        return set_has_changed;\n    }\n    CATCH_STD()\n    return false;\n}\n\nJNIEXPORT void JNICALL\nJava_io_realm_internal_OsSet_nativeStartListening(JNIEnv* env, jclass, jlong wrapper_ptr,\n                                                  jobject j_observable_map) {\n    try {\n        auto wrapper = reinterpret_cast<SetWrapper*>(wrapper_ptr);\n        wrapper->start_listening(env, j_observable_map);\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL\nJava_io_realm_internal_OsSet_nativeStopListening(JNIEnv* env, jclass, jlong wrapper_ptr) {\n    try {\n        auto wrapper = reinterpret_cast<SetWrapper*>(wrapper_ptr);\n        wrapper->stop_listening();\n    }\n    CATCH_STD()\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/cpp/io_realm_internal_OsSharedRealm.cpp",
    "content": "/*\n * Copyright 2016 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#include \"io_realm_internal_OsSharedRealm.h\"\n#if REALM_ENABLE_SYNC\n#include <realm/sync/config.hpp>\n#include <realm/object-store/sync/sync_manager.hpp>\n#include <realm/object-store/sync/sync_session.hpp>\n#include <realm/object-store/results.hpp>\n#include <realm/sync/subscriptions.hpp>\n\n#include \"observable_collection_wrapper.hpp\"\n#endif\n\n#include <realm/util/assert.hpp>\n\n#include <realm/object-store/shared_realm.hpp>\n\n#include \"java_accessor.hpp\"\n#include \"java_binding_context.hpp\"\n#include \"java_exception_def.hpp\"\n#include <realm/object-store/object_store.hpp>\n#include \"util.hpp\"\n#include \"jni_util/java_method.hpp\"\n#include \"jni_util/java_class.hpp\"\n#include \"jni_util/java_exception_thrower.hpp\"\n\n\nusing namespace realm;\nusing namespace realm::_impl;\nusing namespace realm::jni_util;\n\nstatic const char* c_table_name_exists_exception_msg = \"Class already exists: '%1'.\";\n\n#if REALM_ENABLE_SYNC // used only for partial sync now\ntypedef ObservableCollectionWrapper<Results> ResultsWrapper;\n#endif\n\nJNIEXPORT void JNICALL Java_io_realm_internal_OsSharedRealm_nativeInit(JNIEnv* env, jclass,\n                                                                     jstring temporary_directory_path)\n{\n    try {\n        JStringAccessor path(env, temporary_directory_path);    // throws\n        DBOptions::set_sys_tmp_dir(std::string(path)); // throws\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT jlong JNICALL Java_io_realm_internal_OsSharedRealm_nativeGetSharedRealm(JNIEnv* env, jclass, jlong config_ptr,\n                                                                                jlong j_version_no, jlong j_version_index,\n                                                                                jobject realm_notifier)\n{\n    auto& config = *reinterpret_cast<Realm::Config*>(config_ptr);\n    try {\n        SharedRealm shared_realm;\n        if (j_version_no == -1 && j_version_index == -1) {\n            shared_realm = Realm::get_shared_realm(config);\n            shared_realm->read_group(); // Required to start the ObjectStore Scheduler.\n        }\n        else {\n            VersionID version(static_cast<uint_fast64_t>(j_version_no), static_cast<uint_fast32_t>(j_version_index));\n            shared_realm = Realm::get_frozen_realm(config, version);\n        }\n\n        // The migration callback & initialization callback could throw.\n        if (env->ExceptionCheck()) {\n            return reinterpret_cast<jlong>(nullptr);\n        }\n        shared_realm->m_binding_context = JavaBindingContext::create(env, realm_notifier);\n        return reinterpret_cast<jlong>(new SharedRealm(std::move(shared_realm)));\n    }\n    catch (SchemaMismatchException& e) {\n        // An exception has been thrown in the migration block.\n        if (env->ExceptionCheck()) {\n            return reinterpret_cast<jlong>(nullptr);\n        }\n        static JavaClass migration_needed_class(env, JavaExceptionDef::RealmMigrationNeeded);\n        static JavaMethod constructor(env, migration_needed_class, \"<init>\",\n                                      \"(Ljava/lang/String;Ljava/lang/String;)V\");\n\n        jstring message = to_jstring(env, e.what());\n        jstring path = to_jstring(env, config.path);\n        jobject migration_needed_exception = env->NewObject(migration_needed_class, constructor, path, message);\n        env->Throw(reinterpret_cast<jthrowable>(migration_needed_exception));\n    }\n    catch (InvalidSchemaVersionException& e) {\n        // An exception has been thrown in the migration block.\n        if (env->ExceptionCheck()) {\n            return reinterpret_cast<jlong>(nullptr);\n        }\n        // To match the old behaviour. Otherwise it will be converted to ISE in the CATCH_STD.\n        ThrowException(env, IllegalArgument, e.what());\n    }\n    CATCH_STD()\n    return reinterpret_cast<jlong>(nullptr);\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_OsSharedRealm_nativeCloseSharedRealm(JNIEnv*, jclass,\n                                                                                 jlong shared_realm_ptr)\n{\n    auto& shared_realm = *(reinterpret_cast<SharedRealm*>(shared_realm_ptr));\n    // Close the SharedRealm only. Let the finalizer daemon thread free the SharedRealm\n    if (!shared_realm->is_closed()) {\n        shared_realm->close();\n    }\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_OsSharedRealm_nativeBeginTransaction(JNIEnv* env, jclass,\n                                                                                 jlong shared_realm_ptr)\n{\n    auto& shared_realm = *(reinterpret_cast<SharedRealm*>(shared_realm_ptr));\n    try {\n        shared_realm->begin_transaction();\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_OsSharedRealm_nativeCommitTransaction(JNIEnv* env, jclass,\n                                                                                  jlong shared_realm_ptr)\n{\n    auto& shared_realm = *(reinterpret_cast<SharedRealm*>(shared_realm_ptr));\n    try {\n        shared_realm->commit_transaction();\n        // Realm could be closed in the RealmNotifier.didChange().\n        if (!shared_realm->is_closed()) {\n            // To trigger async queries, so the UI can be refreshed immediately to avoid inconsistency.\n            // See more discussion on https://github.com/realm/realm-java/issues/4245\n            shared_realm->refresh();\n        }\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_OsSharedRealm_nativeCancelTransaction(JNIEnv* env, jclass,\n                                                                                  jlong shared_realm_ptr)\n{\n    auto& shared_realm = *(reinterpret_cast<SharedRealm*>(shared_realm_ptr));\n    try {\n        shared_realm->cancel_transaction();\n    }\n    CATCH_STD()\n}\n\n\nJNIEXPORT jboolean JNICALL Java_io_realm_internal_OsSharedRealm_nativeIsInTransaction(JNIEnv*, jclass,\n                                                                                    jlong shared_realm_ptr)\n{\n    auto& shared_realm = *(reinterpret_cast<SharedRealm*>(shared_realm_ptr));\n    return static_cast<jboolean>(shared_realm->is_in_transaction());\n}\n\nJNIEXPORT jboolean JNICALL Java_io_realm_internal_OsSharedRealm_nativeIsEmpty(JNIEnv* env, jclass,\n                                                                            jlong shared_realm_ptr)\n{\n    auto& shared_realm = *(reinterpret_cast<SharedRealm*>(shared_realm_ptr));\n    try {\n        return static_cast<jboolean>(ObjectStore::is_empty(shared_realm->read_group()));\n    }\n    CATCH_STD()\n    return JNI_FALSE;\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_OsSharedRealm_nativeRefresh(JNIEnv* env, jclass, jlong shared_realm_ptr)\n{\n    auto& shared_realm = *(reinterpret_cast<SharedRealm*>(shared_realm_ptr));\n    try {\n        shared_realm->refresh();\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT jlongArray JNICALL Java_io_realm_internal_OsSharedRealm_nativeGetVersionID(JNIEnv* env, jclass,\n                                                                                   jlong shared_realm_ptr)\n{\n    auto& shared_realm = *(reinterpret_cast<SharedRealm*>(shared_realm_ptr));\n    try {\n        util::Optional<DB::VersionID> opt_version_id = shared_realm->current_transaction_version();\n        if (!opt_version_id) {\n            return NULL;\n        }\n\n        DB::VersionID version_id = opt_version_id.value();\n        jlong version_array[2];\n        version_array[0] = static_cast<jlong>(version_id.version);\n        version_array[1] = static_cast<jlong>(version_id.index);\n\n        jlongArray version_data = env->NewLongArray(2);\n        if (version_data == NULL) {\n            ThrowException(env, OutOfMemory, \"Could not allocate memory to return versionID.\");\n            return NULL;\n        }\n        env->SetLongArrayRegion(version_data, 0, 2, version_array);\n\n        return version_data;\n    }\n    CATCH_STD()\n\n    return NULL;\n}\n\nJNIEXPORT jboolean JNICALL Java_io_realm_internal_OsSharedRealm_nativeIsClosed(JNIEnv*, jclass, jlong shared_realm_ptr)\n{\n    auto& shared_realm = *(reinterpret_cast<SharedRealm*>(shared_realm_ptr));\n    return static_cast<jboolean>(shared_realm->is_closed());\n}\n\n\nJNIEXPORT jlong JNICALL Java_io_realm_internal_OsSharedRealm_nativeGetTableRef(JNIEnv* env, jclass, jlong shared_realm_ptr,\n                                                                          jstring table_name)\n{\n    try {\n        JStringAccessor name(env, table_name); // throws\n        auto& shared_realm = *(reinterpret_cast<SharedRealm*>(shared_realm_ptr));\n        auto& group = shared_realm->read_group();\n        if (!group.has_table(name)) {\n            std::string name_str = name;\n            if (name_str.find(TABLE_PREFIX) == 0) {\n                name_str = name_str.substr(TABLE_PREFIX.length());\n            }\n            THROW_JAVA_EXCEPTION(env, JavaExceptionDef::IllegalArgument,\n                                 util::format(\"The class '%1' doesn't exist in this Realm.\", name_str));\n        }\n\n        TableRef* tableRef = new TableRef(group.get_table(name));\n        return reinterpret_cast<jlong>(tableRef);\n    }\n    CATCH_STD()\n\n    return reinterpret_cast<jlong>(nullptr);\n}\n\nJNIEXPORT jlong JNICALL Java_io_realm_internal_OsSharedRealm_nativeCreateTable(JNIEnv* env, jclass,\n                                                                             jlong shared_realm_ptr,\n                                                                             jstring j_table_name)\n{\n    std::string table_name;\n    try {\n        table_name = JStringAccessor(env, j_table_name); // throws\n        auto& shared_realm = *(reinterpret_cast<SharedRealm*>(shared_realm_ptr));\n        shared_realm->verify_in_write(); // throws\n        TableRef table;\n        auto& group = shared_realm->read_group();\n#if REALM_ENABLE_SYNC\n        // Sync doesn't throw when table exists.\n        if (group.has_table(table_name)) {\n            THROW_JAVA_EXCEPTION(env, JavaExceptionDef::IllegalArgument,\n                                 util::format(c_table_name_exists_exception_msg, table_name.substr(TABLE_PREFIX.length())));\n        }\n        table = static_cast<Transaction&>(group).add_table(table_name); // throws\n#else\n        table = group.add_table(table_name); // throws\n#endif\n        return reinterpret_cast<jlong>(new TableRef(table));\n    }\n    catch (TableNameInUse& e) {\n        // We need to print the table name, so catch the exception here.\n        std::string class_name_str(table_name.substr(TABLE_PREFIX.length()));\n        ThrowException(env, IllegalArgument, util::format(c_table_name_exists_exception_msg, class_name_str));\n    }\n    CATCH_STD()\n\n    return reinterpret_cast<jlong>(nullptr);\n}\n\nJNIEXPORT jlong JNICALL Java_io_realm_internal_OsSharedRealm_nativeCreateTableWithPrimaryKeyField(\n    JNIEnv* env, jclass, jlong shared_realm_ptr, jstring j_table_name, jstring j_field_name, jint j_field_type,\n    jboolean is_nullable)\n{\n    std::string class_name_str;\n    try {\n        std::string table_name(JStringAccessor(env, j_table_name));\n        class_name_str = std::string(table_name.substr(TABLE_PREFIX.length()));\n        JStringAccessor field_name(env, j_field_name); // throws\n        auto& shared_realm = *(reinterpret_cast<SharedRealm*>(shared_realm_ptr));\n        shared_realm->verify_in_write(); // throws\n\n        DataType pkType = static_cast<DataType>(j_field_type);\n        TableRef table;\n        auto& group = shared_realm->read_group();\n#if REALM_ENABLE_SYNC\n        // Sync doesn't throw when table exists.\n        if (group.has_table(table_name)) {\n            THROW_JAVA_EXCEPTION(env, JavaExceptionDef::IllegalArgument,\n                                 util::format(c_table_name_exists_exception_msg, class_name_str));\n        }\n        table = static_cast<Transaction&>(group).add_table_with_primary_key(table_name, pkType, field_name, is_nullable);\n#else\n        table = group.add_table_with_primary_key(table_name, pkType, field_name,\n                                                         is_nullable);\n#endif\n        return reinterpret_cast<jlong>(new TableRef(table));\n    }\n    catch (TableNameInUse& e) {\n        // We need to print the table name, so catch the exception here.\n        ThrowException(env, IllegalArgument, util::format(c_table_name_exists_exception_msg, class_name_str));\n    }\n    CATCH_STD()\n\n    return reinterpret_cast<jlong>(nullptr);\n}\n\nJNIEXPORT jobjectArray JNICALL Java_io_realm_internal_OsSharedRealm_nativeGetTablesName(JNIEnv* env, jclass,\n                                                                                        jlong shared_realm_ptr)\n{\n    auto& shared_realm = *(reinterpret_cast<SharedRealm*>(shared_realm_ptr));\n\n    auto& group = shared_realm->read_group();\n\n    auto keys = group.get_table_keys();\n    if (!keys.empty()) {\n        size_t len = keys.size();\n        jobjectArray table_names = env->NewObjectArray(len, JavaClassGlobalDef::java_lang_string(), 0);\n\n        if (table_names == nullptr) {\n            ThrowException(env, OutOfMemory, \"Could not allocate memory to return tables names\");\n            return nullptr;\n        }\n\n        for (size_t i = 0; i < len; ++i) {\n            StringData name = group.get_table_name(keys[i]);\n            env->SetObjectArrayElement(table_names, i, to_jstring(env, name.data()));\n        }\n\n        return table_names;\n    }\n    return nullptr;\n}\n\nJNIEXPORT jboolean JNICALL Java_io_realm_internal_OsSharedRealm_nativeHasTable(JNIEnv* env, jclass,\n                                                                             jlong shared_realm_ptr,\n                                                                             jstring table_name)\n{\n    auto& shared_realm = *(reinterpret_cast<SharedRealm*>(shared_realm_ptr));\n    try {\n        JStringAccessor name(env, table_name);\n        return static_cast<jboolean>(shared_realm->read_group().has_table(name));\n    }\n    CATCH_STD()\n    return JNI_FALSE;\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_OsSharedRealm_nativeRenameTable(JNIEnv* env, jclass,\n                                                                            jlong shared_realm_ptr,\n                                                                            jstring old_table_name,\n                                                                            jstring new_table_name)\n{\n    auto& shared_realm = *(reinterpret_cast<SharedRealm*>(shared_realm_ptr));\n    try {\n        JStringAccessor old_name(env, old_table_name);\n        if (!shared_realm->is_in_transaction()) {\n            std::ostringstream ss;\n            ss << \"Class \" << old_name << \" cannot be removed when the realm is not in transaction.\";\n            ThrowException(env, IllegalState, ss.str());\n            return;\n        }\n        JStringAccessor new_name(env, new_table_name);\n        shared_realm->read_group().rename_table(old_name, new_name);\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT jlong JNICALL Java_io_realm_internal_OsSharedRealm_nativeSize(JNIEnv* env, jclass, jlong shared_realm_ptr)\n{\n    auto& shared_realm = *(reinterpret_cast<SharedRealm*>(shared_realm_ptr));\n    try {\n        return static_cast<jlong>(shared_realm->read_group().size());\n    }\n    CATCH_STD()\n\n    return 0;\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_OsSharedRealm_nativeWriteCopy(JNIEnv* env, jclass, jlong shared_realm_ptr,\n                                                                          jstring path, jbyteArray key)\n{\n    auto& shared_realm = *(reinterpret_cast<SharedRealm*>(shared_realm_ptr));\n    try {\n        JStringAccessor path_str(env, path);\n        JByteArrayAccessor jarray_accessor(env, key);\n\n        RealmConfig write_copy_config;\n        write_copy_config.path = std::string(path_str);\n        // Force sync history on sync configurations\n        write_copy_config.force_sync_history = shared_realm->config().sync_config != nullptr;\n\n        if(!jarray_accessor.is_null())\n            write_copy_config.encryption_key = jarray_accessor.transform<std::vector<char>>();\n\n        shared_realm->convert(write_copy_config);\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT jboolean JNICALL Java_io_realm_internal_OsSharedRealm_nativeWaitForChange(JNIEnv* env, jclass,\n                                                                                  jlong shared_realm_ptr)\n{\n    auto& shared_realm = *(reinterpret_cast<SharedRealm*>(shared_realm_ptr));\n    try {\n        return static_cast<jboolean>(shared_realm->wait_for_change());\n    }\n    CATCH_STD()\n\n    return JNI_FALSE;\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_OsSharedRealm_nativeStopWaitForChange(JNIEnv* env, jclass,\n                                                                                  jlong shared_realm_ptr)\n{\n    auto& shared_realm = *(reinterpret_cast<SharedRealm*>(shared_realm_ptr));\n    try {\n        shared_realm->wait_for_change_release();\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT jboolean JNICALL Java_io_realm_internal_OsSharedRealm_nativeCompact(JNIEnv* env, jclass,\n                                                                            jlong shared_realm_ptr)\n{\n    auto& shared_realm = *(reinterpret_cast<SharedRealm*>(shared_realm_ptr));\n    try {\n        return static_cast<jboolean>(shared_realm->compact());\n    }\n    CATCH_STD()\n\n    return JNI_FALSE;\n}\n\nstatic void finalize_shared_realm(jlong ptr)\n{\n    delete reinterpret_cast<SharedRealm*>(ptr);\n}\n\nJNIEXPORT jlong JNICALL Java_io_realm_internal_OsSharedRealm_nativeGetFinalizerPtr(JNIEnv*, jclass)\n{\n    return reinterpret_cast<jlong>(&finalize_shared_realm);\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_OsSharedRealm_nativeSetAutoRefresh(JNIEnv* env, jclass,\n                                                                               jlong shared_realm_ptr,\n                                                                               jboolean enabled)\n{\n    try {\n        auto& shared_realm = *(reinterpret_cast<SharedRealm*>(shared_realm_ptr));\n        shared_realm->set_auto_refresh(to_bool(enabled));\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT jboolean JNICALL Java_io_realm_internal_OsSharedRealm_nativeIsAutoRefresh(JNIEnv* env, jclass,\n                                                                                  jlong shared_realm_ptr)\n{\n    try {\n        auto& shared_realm = *(reinterpret_cast<SharedRealm*>(shared_realm_ptr));\n        return to_jbool(shared_realm->auto_refresh());\n    }\n    CATCH_STD()\n    return JNI_FALSE;\n}\n\nJNIEXPORT jlong JNICALL Java_io_realm_internal_OsSharedRealm_nativeGetSchemaInfo(JNIEnv*, jclass,\n                                                                               jlong shared_realm_ptr)\n{\n    // No throws\n    auto& shared_realm = *(reinterpret_cast<SharedRealm*>(shared_realm_ptr));\n    return reinterpret_cast<jlong>(&shared_realm->schema());\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_OsSharedRealm_nativeRegisterSchemaChangedCallback(\n    JNIEnv* env, jclass, jlong shared_realm_ptr, jobject j_schema_changed_callback)\n{\n    // No throws\n    auto& shared_realm = *(reinterpret_cast<SharedRealm*>(shared_realm_ptr));\n    JavaGlobalWeakRef callback_weak_ref(env, j_schema_changed_callback);\n    if (shared_realm->m_binding_context) {\n        JavaBindingContext& java_binding_context =\n            *(static_cast<JavaBindingContext*>(shared_realm->m_binding_context.get()));\n        java_binding_context.set_schema_changed_callback(env, j_schema_changed_callback);\n    }\n}\n\nJNIEXPORT jboolean JNICALL Java_io_realm_internal_OsSharedRealm_nativeIsPartial(JNIEnv*, jclass, jlong /*shared_realm_ptr*/)\n{\n    // No throws\n    // auto& shared_realm = *(reinterpret_cast<SharedRealm*>(shared_realm_ptr));\n    return to_jbool(false);\n}\n\nJNIEXPORT jboolean JNICALL Java_io_realm_internal_OsSharedRealm_nativeIsFrozen(JNIEnv* env, jclass, jlong shared_realm_ptr)\n{\n    try {\n        auto& shared_realm = *(reinterpret_cast<SharedRealm*>(shared_realm_ptr));\n        return to_jbool(shared_realm->is_frozen());\n    }\n    CATCH_STD()\n    return false;\n}\n\nJNIEXPORT jlong JNICALL Java_io_realm_internal_OsSharedRealm_nativeFreeze(JNIEnv* env, jclass, jlong shared_realm_ptr)\n{\n    try {\n        auto& shared_realm = *(reinterpret_cast<SharedRealm*>(shared_realm_ptr));\n        return reinterpret_cast<jlong>(new SharedRealm(shared_realm->freeze()));\n    }\n    CATCH_STD()\n    return reinterpret_cast<jlong>(nullptr);\n}\n\nJNIEXPORT jlong JNICALL Java_io_realm_internal_OsSharedRealm_nativeNumberOfVersions(JNIEnv* env, jclass, jlong shared_realm_ptr)\n{\n    try {\n        auto& shared_realm = *(reinterpret_cast<SharedRealm*>(shared_realm_ptr));\n        return to_jlong_or_not_found(shared_realm->get_number_of_versions());\n    }\n    CATCH_STD()\n    return 0;\n}\n\n#if REALM_ENABLE_SYNC\nJNIEXPORT jlong JNICALL Java_io_realm_internal_OsSharedRealm_nativeGetActiveSubscriptionSet(JNIEnv* env, jclass, jlong j_native_ptr)\n{\n    try {\n        auto realm = *reinterpret_cast<SharedRealm*>(j_native_ptr);\n        const sync::SubscriptionSet subs = realm->get_latest_subscription_set();\n        return reinterpret_cast<jlong>(new sync::SubscriptionSet(std::move(subs)));\n    }\n    CATCH_STD();\n    return 0;\n}\n#endif\n\n#if REALM_ENABLE_SYNC\nJNIEXPORT jlong JNICALL Java_io_realm_internal_OsSharedRealm_nativeGetLatestSubscriptionSet(JNIEnv* env, jclass, jlong j_native_ptr)\n{\n    try {\n        auto realm = *reinterpret_cast<SharedRealm*>(j_native_ptr);\n        const sync::SubscriptionSet subs = realm->get_active_subscription_set();\n        return reinterpret_cast<jlong>(new sync::SubscriptionSet(std::move(subs)));\n    }\n    CATCH_STD();\n    return 0;\n}\n#endif\n"
  },
  {
    "path": "realm/realm-library/src/main/cpp/io_realm_internal_Property.cpp",
    "content": "/*\n * Copyright 2016 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#include \"io_realm_internal_Property.h\"\n\n#include <realm/object-store/property.hpp>\n#include <realm/object-store/object_store.hpp>\n\n#include \"util.hpp\"\n\nusing namespace realm;\n\nstatic_assert(io_realm_internal_Property_TYPE_INT == static_cast<jint>(PropertyType::Int), \"\");\nstatic_assert(io_realm_internal_Property_TYPE_BOOL == static_cast<jint>(PropertyType::Bool), \"\");\nstatic_assert(io_realm_internal_Property_TYPE_STRING == static_cast<jint>(PropertyType::String), \"\");\nstatic_assert(io_realm_internal_Property_TYPE_DATA == static_cast<jint>(PropertyType::Data), \"\");\nstatic_assert(io_realm_internal_Property_TYPE_DATE == static_cast<jint>(PropertyType::Date), \"\");\nstatic_assert(io_realm_internal_Property_TYPE_FLOAT == static_cast<jint>(PropertyType::Float), \"\");\nstatic_assert(io_realm_internal_Property_TYPE_DOUBLE == static_cast<jint>(PropertyType::Double), \"\");\nstatic_assert(io_realm_internal_Property_TYPE_OBJECT == static_cast<jint>(PropertyType::Object), \"\");\nstatic_assert(io_realm_internal_Property_TYPE_LINKING_OBJECTS == static_cast<jint>(PropertyType::LinkingObjects), \"\");\nstatic_assert(io_realm_internal_Property_TYPE_REQUIRED == static_cast<jint>(PropertyType::Required), \"\");\nstatic_assert(io_realm_internal_Property_TYPE_NULLABLE == static_cast<jint>(PropertyType::Nullable), \"\");\nstatic_assert(io_realm_internal_Property_TYPE_ARRAY == static_cast<jint>(PropertyType::Array), \"\");\n\nstatic void finalize_property(jlong ptr)\n{\n    delete reinterpret_cast<Property*>(ptr);\n}\n\nJNIEXPORT jlong JNICALL Java_io_realm_internal_Property_nativeCreatePersistedProperty(JNIEnv* env, jclass,\n                                                                                      jstring j_internal_name,\n                                                                                      jstring j_public_name,\n                                                                                      jint type,\n                                                                                      jboolean is_primary,\n                                                                                      jboolean is_indexed)\n{\n    try {\n        JStringAccessor public_name(env, j_public_name);\n        JStringAccessor internal_name(env, j_internal_name);\n        PropertyType p_type = static_cast<PropertyType>(static_cast<int>(type));\n        std::unique_ptr<Property> property(\n            new Property(internal_name, p_type, to_bool(is_primary), to_bool(is_indexed), public_name));\n        if (to_bool(is_indexed) && !property->type_is_indexable()) {\n            throw std::invalid_argument(\n                \"This field cannot be indexed - Only String/byte/short/int/long/boolean/Date fields are supported.\");\n        }\n        if (to_bool(is_primary) && p_type != PropertyType::Int && p_type != PropertyType::String && p_type != PropertyType::ObjectId && p_type != PropertyType::UUID) {\n            std::string typ = property->type_string();\n            throw std::invalid_argument(\"Invalid primary key type: \" + typ);\n        }\n        return reinterpret_cast<jlong>(property.release());\n    }\n    CATCH_STD()\n    return 0;\n}\n\nJNIEXPORT jlong JNICALL Java_io_realm_internal_Property_nativeCreatePersistedLinkProperty(JNIEnv* env, jclass,\n                                                                                          jstring j_internal_name,\n                                                                                          jstring j_public_name,\n                                                                                          jint type,\n                                                                                          jstring j_target_class_name)\n{\n    try {\n        JStringAccessor public_name(env, j_public_name);\n        JStringAccessor internal_name(env, j_internal_name);\n        JStringAccessor link_class_name(env, j_target_class_name);\n        PropertyType p_type = static_cast<PropertyType>(static_cast<int>(type));\n        return reinterpret_cast<jlong>(new Property(internal_name, p_type, link_class_name, \"\", public_name));\n    }\n    CATCH_STD()\n    return 0;\n}\n\nJNIEXPORT jlong JNICALL Java_io_realm_internal_Property_nativeCreateComputedLinkProperty(JNIEnv* env, jclass,\n                                                                                         jstring j_name_str,\n                                                                                         jstring j_source_class_name,\n                                                                                         jstring j_source_field_name)\n{\n    try {\n        JStringAccessor name(env, j_name_str);\n        JStringAccessor target_class_name(env, j_source_class_name);\n        JStringAccessor target_field_name(env, j_source_field_name);\n\n        PropertyType p_type = PropertyType::LinkingObjects | PropertyType::Array;\n        return reinterpret_cast<jlong>(new Property(name, p_type, target_class_name, target_field_name));\n    }\n    CATCH_STD()\n    return 0;\n}\n\nJNIEXPORT jlong JNICALL Java_io_realm_internal_Property_nativeGetFinalizerPtr(JNIEnv*, jclass)\n{\n    return reinterpret_cast<jlong>(&finalize_property);\n}\n\nJNIEXPORT jint JNICALL Java_io_realm_internal_Property_nativeGetType(JNIEnv*, jclass, jlong native_ptr)\n{\n    auto& property = *reinterpret_cast<Property*>(native_ptr);\n    return static_cast<jint>(property.type);\n}\n\nJNIEXPORT jlong JNICALL Java_io_realm_internal_Property_nativeGetColumnKey(JNIEnv*, jclass, jlong native_ptr)\n{\n    auto& property = *reinterpret_cast<Property*>(native_ptr);\n    return static_cast<jlong>(property.column_key.value);\n}\n\nJNIEXPORT jstring JNICALL Java_io_realm_internal_Property_nativeGetLinkedObjectName(JNIEnv* env, jclass,\n                                                                                    jlong native_ptr)\n{\n    try {\n        auto& property = *reinterpret_cast<Property*>(native_ptr);\n        std::string name = property.object_type;\n        if (!name.empty()) {\n            return to_jstring(env, name);\n        }\n    }\n    CATCH_STD()\n    return nullptr;\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/cpp/io_realm_internal_Table.cpp",
    "content": "/*\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#include <sstream>\n\n#include \"util.hpp\"\n#include \"io_realm_internal_Property.h\"\n#include \"io_realm_internal_Table.h\"\n\n#include \"java_accessor.hpp\"\n#include \"java_object_accessor.hpp\"\n#include \"java_exception_def.hpp\"\n#include <realm/object-store/shared_realm.hpp>\n#include \"jni_util/java_exception_thrower.hpp\"\n\n#include <realm/util/to_string.hpp>\n\nusing namespace std;\nusing namespace realm;\nusing namespace realm::_impl;\nusing namespace realm::jni_util;\nusing namespace realm::util;\n\nstatic_assert(io_realm_internal_Table_MAX_STRING_SIZE == Table::max_string_size, \"\");\nstatic_assert(io_realm_internal_Table_MAX_BINARY_SIZE == Table::max_binary_size, \"\");\n\nstatic void finalize_table(jlong ptr);\n\ninline static bool is_allowed_to_index(JNIEnv* env, DataType column_type)\n{\n    if (column_type == type_String\n           || column_type == type_Int\n           || column_type == type_Bool\n           || column_type == type_Timestamp\n           || column_type == type_OldDateTime\n           || column_type == type_ObjectId\n           || column_type == type_UUID\n           || column_type == type_Mixed) {\n        return true;\n    }\n\n    ThrowException(env, IllegalArgument, \"This field cannot be indexed - \"\n                                         \"Only String/byte/short/int/long/boolean/Date/ObjectId/UUID/Mixed fields are supported.\");\n    return false;\n}\n\n// Note: Don't modify spec on a table which has a shared_spec.\n// A spec is shared on subtables that are not in Mixed columns.\n//\n\nJNIEXPORT jlong JNICALL Java_io_realm_internal_Table_nativeAddColumn(JNIEnv* env, jobject, jlong nativeTableRefPtr,\n                                                                     jint colType, jstring name, jboolean isNullable)\n{\n    try {\n        JStringAccessor name2(env, name); // throws\n        bool is_column_nullable = to_bool(isNullable);\n        DataType dataType = DataType(colType);\n        if (is_column_nullable && dataType == type_LinkList) {\n            ThrowException(env, IllegalArgument, \"List fields cannot be nullable.\");\n        }\n        TableRef table = TBL_REF(nativeTableRefPtr);\n        ColKey col_key = table->add_column(dataType, name2, is_column_nullable);\n        return (jlong)(col_key.value);\n    }\n    CATCH_STD()\n    return 0;\n}\n\nJNIEXPORT jlong JNICALL Java_io_realm_internal_Table_nativeAddPrimitiveListColumn(JNIEnv* env, jobject,\n                                                                                  jlong native_table_ptr, jint j_col_type,\n                                                                                  jstring j_name, jboolean j_is_nullable)\n{\n    try {\n        JStringAccessor name(env, j_name); // throws\n        bool is_column_nullable = to_bool(j_is_nullable);\n        DataType data_type = DataType(j_col_type);\n        TableRef table = TBL_REF(native_table_ptr);\n        return (jlong)(table->add_column_list(data_type, name, is_column_nullable).value);\n    }\n    CATCH_STD()\n    return reinterpret_cast<jlong>(nullptr);\n}\n\nJNIEXPORT jlong JNICALL Java_io_realm_internal_Table_nativeAddPrimitiveDictionaryColumn(JNIEnv* env,\n                                                                                        jobject,\n                                                                                        jlong native_table_ptr,\n                                                                                        jint j_col_type,\n                                                                                        jstring j_name,\n                                                                                        jboolean j_is_nullable)\n{\n    try {\n        JStringAccessor name(env, j_name); // throws\n        bool is_column_nullable = to_bool(j_is_nullable);\n        DataType data_type = DataType(j_col_type);\n        TableRef table = TBL_REF(native_table_ptr);\n        return (jlong)(table->add_column_dictionary(data_type, name, is_column_nullable).value);\n    }\n    CATCH_STD()\n    return reinterpret_cast<jlong>(nullptr);\n}\n\nJNIEXPORT jlong JNICALL Java_io_realm_internal_Table_nativeAddPrimitiveSetColumn(JNIEnv* env,\n                                                                                 jobject,\n                                                                                 jlong native_table_ptr,\n                                                                                 jint j_col_type,\n                                                                                 jstring j_name,\n                                                                                 jboolean j_is_nullable)\n{\n    try {\n        JStringAccessor name(env, j_name); // throws\n        bool is_column_nullable = to_bool(j_is_nullable);\n        DataType data_type = DataType(j_col_type);\n        TableRef table = TBL_REF(native_table_ptr);\n        return (jlong)(table->add_column_set(data_type, name, is_column_nullable).value);\n    }\n    CATCH_STD()\n    return reinterpret_cast<jlong>(nullptr);\n}\n\nJNIEXPORT jlong JNICALL Java_io_realm_internal_Table_nativeAddColumnLink(JNIEnv* env, jobject, jlong nativeTableRefPtr,\n                                                                         jint colType, jstring name,\n                                                                         jlong targetTableRefPtr)\n{\n    TableRef targetTableRef = TBL_REF(targetTableRefPtr);\n    if (!targetTableRef->is_group_level()) {\n        ThrowException(env, UnsupportedOperation, \"Links can only be made to toplevel tables.\");\n        return 0;\n    }\n    try {\n        JStringAccessor name_accessor(env, name); // throws\n        TableRef table = TBL_REF(nativeTableRefPtr);\n\n        if (colType == int(DataType::Type::Link)) {\n            return static_cast<jlong>(table->add_column(*targetTableRef, name_accessor).value);\n        } else if (colType == int(DataType::Type::LinkList)) {\n            return static_cast<jlong>(table->add_column_list(*targetTableRef, name_accessor).value);\n        } else {\n            throw PropertyTypeMismatch(table->get_name(), StringData(name_accessor));\n        }\n    }\n    CATCH_STD()\n    return 0;\n}\n\nJNIEXPORT jlong JNICALL Java_io_realm_internal_Table_nativeAddColumnDictionaryLink(JNIEnv* env,\n                                                                                   jobject,\n                                                                                   jlong nativeTableRefPtr,\n                                                                                   jint colType,\n                                                                                   jstring name,\n                                                                                   jlong targetTableRefPtr)\n{\n    TableRef targetTableRef = TBL_REF(targetTableRefPtr);\n    if (!targetTableRef->is_group_level()) {\n        ThrowException(env, UnsupportedOperation, \"Links can only be made to toplevel tables.\");\n        return 0;\n    }\n    try {\n        JStringAccessor name_accessor(env, name); // throws\n        TableRef table = TBL_REF(nativeTableRefPtr);\n\n        // There is no entry in DataType::Type to identify Link Dictionaries, so use PropertyType instead\n        if (colType == (int(PropertyType::Dictionary) + int(DataType::Type::Link))) {\n            return static_cast<jlong>(table->add_column_dictionary(*targetTableRef, name_accessor).value);\n        } else {\n            throw PropertyTypeMismatch(table->get_name(), StringData(name_accessor));\n        }\n    }\n    CATCH_STD()\n    return 0;\n}\n\nJNIEXPORT jlong JNICALL Java_io_realm_internal_Table_nativeAddColumnSetLink(JNIEnv* env,\n                                                                            jobject,\n                                                                            jlong nativeTableRefPtr,\n                                                                            jint colType,\n                                                                            jstring name,\n                                                                            jlong targetTableRefPtr)\n{\n    TableRef targetTableRef = TBL_REF(targetTableRefPtr);\n    if (!targetTableRef->is_group_level()) {\n        ThrowException(env, UnsupportedOperation, \"Links can only be made to toplevel tables.\");\n        return 0;\n    }\n    try {\n        JStringAccessor name_accessor(env, name); // throws\n        TableRef table = TBL_REF(nativeTableRefPtr);\n\n        // There is no entry in DataType::Type to identify Link Set, so use PropertyType instead\n        if (colType == (int(PropertyType::Set) + int(DataType::Type::Link))) {\n            return static_cast<jlong>(table->add_column_set(*targetTableRef, name_accessor).value);\n        } else {\n            throw PropertyTypeMismatch(table->get_name(), StringData(name_accessor));\n        }\n    }\n    CATCH_STD()\n    return 0;\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_Table_nativeRemoveColumn(JNIEnv* env, jobject, jlong nativeTableRefPtr,\n                                                                       jlong columnKey)\n{\n    try {\n        TableRef table = TBL_REF(nativeTableRefPtr);\n        table->remove_column(ColKey(columnKey));\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_Table_nativeRenameColumn(JNIEnv* env, jobject, jlong nativeTableRefPtr,\n                                                                       jlong columnKey, jstring name)\n{\n    try {\n        JStringAccessor name2(env, name); // throws\n        TableRef table = TBL_REF(nativeTableRefPtr);\n        table->rename_column(ColKey(columnKey), name2);\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT jboolean JNICALL Java_io_realm_internal_Table_nativeIsColumnNullable(JNIEnv*, jobject,\n                                                                               jlong nativeTableRefPtr,\n                                                                               jlong columnKey)\n{\n    TableRef table = TBL_REF(nativeTableRefPtr);\n    return to_jbool(table->is_nullable(ColKey(columnKey))); // noexcept\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_Table_nativeConvertColumnToNullable(JNIEnv* env, jobject,\n                                                                                  jlong native_table_ref_ptr,\n                                                                                  jlong j_column_key,\n                                                                                  jboolean is_primary_key)\n{\n    try {\n        TableRef table = TBL_REF(native_table_ref_ptr);\n        ColKey col_key(j_column_key);\n        bool nullable = true;\n        bool throw_on_value_conversion = false;\n        ColKey newCol = table->set_nullability(col_key, nullable, throw_on_value_conversion);\n        if (to_bool(is_primary_key)) {\n            table->set_primary_key_column(newCol);\n        }\n\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_Table_nativeConvertColumnToNotNullable(JNIEnv* env, jobject,\n                                                                                     jlong native_table_ref_ptr,\n                                                                                     jlong j_column_key,\n                                                                                     jboolean is_primary_key)\n{\n    try {\n        TableRef table = TBL_REF(native_table_ref_ptr);\n        ColKey col_key(j_column_key);\n        bool nullable = false;\n        bool throw_on_value_conversion = is_primary_key;\n        ColKey newCol = table->set_nullability(col_key, nullable, throw_on_value_conversion);\n        if (to_bool(is_primary_key)) {\n            table->set_primary_key_column(newCol);\n        }\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT jlong JNICALL Java_io_realm_internal_Table_nativeSize(JNIEnv*, jobject, jlong nativeTableRefPtr)\n{\n    TableRef table = TBL_REF(nativeTableRefPtr);\n    return static_cast<jlong>(table->size()); // noexcept\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_Table_nativeClear(JNIEnv* env, jobject, jlong nativeTableRefPtr)\n{\n    try {\n        TableRef table = TBL_REF(nativeTableRefPtr);\n        table->clear();\n    }\n    CATCH_STD()\n}\n\n\n// -------------- Column information\n\n\nJNIEXPORT jlong JNICALL Java_io_realm_internal_Table_nativeGetColumnCount(JNIEnv*, jobject, jlong nativeTableRefPtr)\n{\n    TableRef table = TBL_REF(nativeTableRefPtr);\n    return static_cast<jlong>(table->get_column_count()); // noexcept\n}\n\nJNIEXPORT jstring JNICALL Java_io_realm_internal_Table_nativeGetColumnName(JNIEnv* env, jobject, jlong nativeTableRefPtr,\n                                                                           jlong columnKey)\n{\n    try {\n        TableRef table = TBL_REF(nativeTableRefPtr);\n        ColKey col_key(columnKey);\n        StringData stringData = table->get_column_name(col_key);\n        return to_jstring(env, stringData);\n    }\n    CATCH_STD();\n    return nullptr;\n}\n\nJNIEXPORT jobjectArray JNICALL Java_io_realm_internal_Table_nativeGetColumnNames(JNIEnv* env, jobject, jlong nativeTableRefPtr)\n{\n    try {\n        TableRef table = TBL_REF(nativeTableRefPtr);\n        ColKeys col_keys = table->get_column_keys();\n        size_t size = col_keys.size();\n        jobjectArray col_keys_array = env->NewObjectArray(size, JavaClassGlobalDef::java_lang_string(), 0);\n        if (col_keys_array == NULL) {\n            ThrowException(env, OutOfMemory, \"Could not allocate memory to return column names.\");\n            return NULL;\n        }\n        for (size_t i = 0; i < size; ++i) {\n            env->SetObjectArrayElement(col_keys_array, i, to_jstring(env,  table->get_column_name(col_keys[i])));\n        }\n\n        return col_keys_array;\n    }\n    CATCH_STD();\n    return NULL;\n}\n\nJNIEXPORT jlong JNICALL Java_io_realm_internal_Table_nativeGetColumnKey(JNIEnv* env, jobject, jlong nativeTableRefPtr,\n                                                                          jstring columnName)\n{\n    try {\n        JStringAccessor columnName2(env, columnName);                                     // throws\n        TableRef table = TBL_REF(nativeTableRefPtr);\n        ColKey col_key = table->get_column_key(columnName2);\n        if (table->valid_column(col_key)) {\n            return col_key.value;\n        }\n        return -1;\n    }\n    CATCH_STD()\n    return -1;\n}\n\nJNIEXPORT jint JNICALL Java_io_realm_internal_Table_nativeGetColumnType(JNIEnv*, jobject, jlong nativeTableRefPtr,\n                                                                        jlong columnKey)\n{\n    ColKey column_key (columnKey);\n    TableRef table = TBL_REF(nativeTableRefPtr);\n    DataType column_type = table->get_column_type(column_key);\n    if (column_type != type_LinkList &&  table->is_list(column_key)) {\n        // add the offset so it can be mapped correctly in Java (RealmFieldType#fromNativeValue)\n        return int(column_type) + int(PropertyType::Array);\n    } else if (column_key.is_set()) {\n        return int(column_type) + int(PropertyType::Set);\n    } else if (column_key.is_dictionary()) {\n        return int(column_type) + int(PropertyType::Dictionary);\n    }\n\n    return int(column_type);\n    // For primitive list\n    // FIXME: Add test in https://github.com/realm/realm-java/pull/5221 before merging to master\n    // FIXME: Add method in Object Store to return a PropertyType.\n}\n\n\n// ---------------- Row handling\n\nJNIEXPORT void JNICALL Java_io_realm_internal_Table_nativeMoveLastOver(JNIEnv* env, jobject, jlong nativeTableRefPtr,\n                                                                       jlong rowKey)\n{\n    try {\n        TableRef table = TBL_REF(nativeTableRefPtr);\n        table->remove_object(ObjKey(rowKey));\n    }\n    CATCH_STD()\n}\n\n// ----------------- Get cell\n\nJNIEXPORT jlong JNICALL Java_io_realm_internal_Table_nativeGetLong(JNIEnv* env, jobject, jlong nativeTableRefPtr,\n                                                                   jlong columnKey, jlong rowKey)\n{\n    TableRef table = TBL_REF(nativeTableRefPtr);\n    if (!TYPE_VALID(env, table, columnKey, col_type_Int)) {\n        return 0;\n    }\n    return table->get_object(ObjKey(rowKey)).get<Int>(ColKey(columnKey)); // noexcept\n}\n\nJNIEXPORT jboolean JNICALL Java_io_realm_internal_Table_nativeGetBoolean(JNIEnv* env, jobject, jlong nativeTableRefPtr,\n                                                                         jlong columnKey, jlong rowKey)\n{\n    TableRef table = TBL_REF(nativeTableRefPtr);\n    if (!TYPE_VALID(env, table, columnKey, col_type_Bool)) {\n        return JNI_FALSE;\n    }\n\n    return to_jbool(table->get_object(ObjKey(rowKey)).get<bool>(ColKey(columnKey)));\n}\n\nJNIEXPORT jfloat JNICALL Java_io_realm_internal_Table_nativeGetFloat(JNIEnv* env, jobject, jlong nativeTableRefPtr,\n                                                                     jlong columnKey, jlong rowKey)\n{\n    TableRef table = TBL_REF(nativeTableRefPtr);\n    if (!TYPE_VALID(env, table, columnKey, col_type_Float)) {\n        return 0;\n    }\n\n    return table->get_object(ObjKey(rowKey)).get<float>(ColKey(columnKey));\n}\n\nJNIEXPORT jdouble JNICALL Java_io_realm_internal_Table_nativeGetDouble(JNIEnv* env, jobject, jlong nativeTableRefPtr,\n                                                                       jlong columnKey, jlong rowKey)\n{\n    TableRef table = TBL_REF(nativeTableRefPtr);\n    if (!TYPE_VALID(env, table, columnKey, col_type_Double)) {\n        return 0;\n    }\n\n    return table->get_object(ObjKey(rowKey)).get<double>(ColKey(columnKey));\n}\n\nJNIEXPORT jlong JNICALL Java_io_realm_internal_Table_nativeGetTimestamp(JNIEnv* env, jobject, jlong nativeTableRefPtr,\n                                                                        jlong columnKey, jlong rowKey)\n{\n    TableRef table = TBL_REF(nativeTableRefPtr);\n    if (!TYPE_VALID(env, table, columnKey, col_type_Timestamp)) {\n        return 0;\n    }\n    try {\n        return to_milliseconds(table->get_object(ObjKey(rowKey)).get<Timestamp>(ColKey(columnKey)));\n    }\n    CATCH_STD()\n    return 0;\n}\n\nJNIEXPORT jstring JNICALL Java_io_realm_internal_Table_nativeGetString(JNIEnv* env, jobject, jlong nativeTableRefPtr,\n                                                                       jlong columnKey, jlong rowKey)\n{\n    TableRef table = TBL_REF(nativeTableRefPtr);\n    if (!TYPE_VALID(env, table, columnKey, col_type_String)) {\n        return nullptr;\n    }\n    try {\n        return to_jstring(env, table->get_object(ObjKey(rowKey)).get<StringData>(ColKey(columnKey)));\n    }\n    CATCH_STD()\n    return nullptr;\n}\n\nJNIEXPORT jlongArray JNICALL Java_io_realm_internal_Table_nativeGetDecimal128(JNIEnv* env, jobject, jlong nativeTableRefPtr,\n                                                                       jlong columnKey, jlong rowKey)\n{\n    TableRef table = TBL_REF(nativeTableRefPtr);\n    if (!TYPE_VALID(env, table, columnKey, col_type_Decimal)) {\n        return nullptr;\n    }\n    try {\n        Decimal128 decimal128 = table->get_object(ObjKey(rowKey)).get<Decimal128>(ColKey(columnKey));\n        RETURN_DECIMAL128_AS_JLONG_ARRAY__OR_NULL(decimal128)\n    }\n    CATCH_STD()\n    return nullptr;\n}\n\nJNIEXPORT jstring JNICALL Java_io_realm_internal_Table_nativeGetObjectId(JNIEnv* env, jobject, jlong nativeTableRefPtr,\n                                                                       jlong columnKey, jlong rowKey)\n{\n    TableRef table = TBL_REF(nativeTableRefPtr);\n    if (!TYPE_VALID(env, table, columnKey, col_type_ObjectId)) {\n        return nullptr;\n    }\n    try {\n        return to_jstring(env, table->get_object(ObjKey(rowKey)).get<ObjectId>(ColKey(columnKey)).to_string().data());\n    }\n    CATCH_STD()\n    return nullptr;\n}\n\nJNIEXPORT jbyteArray JNICALL Java_io_realm_internal_Table_nativeGetByteArray(JNIEnv* env, jobject,\n                                                                             jlong nativeTableRefPtr, jlong columnKey,\n                                                                             jlong rowKey)\n{\n    TableRef table = TBL_REF(nativeTableRefPtr);\n    if (!TYPE_VALID(env, table, columnKey, col_type_Binary)) {\n        return nullptr;\n    }\n    try {\n        realm::BinaryData bin = table->get_object(ObjKey(rowKey)).get<BinaryData>(ColKey(columnKey));\n        return JavaClassGlobalDef::new_byte_array(env, bin);\n    }\n    CATCH_STD()\n\n    return nullptr;\n}\nJNIEXPORT jlong JNICALL Java_io_realm_internal_Table_nativeGetLink(JNIEnv* env, jobject, jlong nativeTableRefPtr,\n                                                                   jlong columnKey, jlong rowKey)\n{\n    TableRef table = TBL_REF(nativeTableRefPtr);\n    if (!TYPE_VALID(env, table, columnKey, col_type_Link)) {\n        return 0;\n    }\n    return static_cast<jlong>(table->get_object(ObjKey(rowKey)).get<ObjKey>(ColKey(columnKey)).value); // noexcept\n}\n\nJNIEXPORT jlong JNICALL Java_io_realm_internal_Table_nativeGetLinkTarget(JNIEnv* env, jobject, jlong nativeTableRefPtr,\n                                                                         jlong columnKey)\n{\n    try {\n        TableRef table_ref = TBL_REF(nativeTableRefPtr);\n        return reinterpret_cast<jlong>(new TableRef(table_ref->get_link_target(ColKey(columnKey))));\n    }\n    CATCH_STD()\n    return 0;\n}\n\nJNIEXPORT jboolean JNICALL Java_io_realm_internal_Table_nativeIsNull(JNIEnv*, jobject, jlong nativeTableRefPtr,\n                                                                     jlong columnKey, jlong rowKey)\n{\n    TableRef table = TBL_REF(nativeTableRefPtr);\n    return to_jbool(table->get_object(ObjKey(rowKey)).is_null(ColKey(columnKey))); // noexcept\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_Table_nativeSetRealmAny(JNIEnv* env, jclass, jlong nativeTableRefPtr,\n                                                                  jlong columnKey, jlong rowKey, jlong nativePtr,\n                                                                  jboolean isDefault)\n{\n    TableRef table = TBL_REF(nativeTableRefPtr);\n    if (!TYPE_VALID(env, table, columnKey, col_type_Mixed)) {\n        return;\n    }\n    try {\n        auto java_value = *reinterpret_cast<JavaValue *>(nativePtr);\n        table->get_object(ObjKey(rowKey)).set<Mixed>(ColKey(columnKey), java_value.to_mixed(), B(isDefault));\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_Table_nativeSetLink(JNIEnv* env, jclass, jlong nativeTableRefPtr,\n                                                                  jlong columnKey, jlong rowKey,\n                                                                  jlong targetRowKey, jboolean isDefault)\n{\n    TableRef table = TBL_REF(nativeTableRefPtr);\n    if (!TYPE_VALID(env, table, columnKey, col_type_Link)) {\n        return;\n    }\n    try {\n        table->get_object(ObjKey(rowKey)).set(ColKey(columnKey), ObjKey(targetRowKey), B(isDefault));\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_Table_nativeSetLong(JNIEnv* env, jclass, jlong nativeTableRefPtr,\n                                                                  jlong columnKey, jlong rowKey, jlong value,\n                                                                  jboolean isDefault)\n{\n    TableRef table = TBL_REF(nativeTableRefPtr);\n    if (!TYPE_VALID(env, table, columnKey, col_type_Int)) {\n        return;\n    }\n    try {\n        table->get_object(ObjKey(rowKey)).set<int64_t>(ColKey(columnKey), value, B(isDefault));\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_Table_nativeIncrementLong(JNIEnv* env, jclass, jlong nativeTableRefPtr,\n                                                                  jlong columnKey, jlong rowKey, jlong value)\n{\n\n    TableRef table = TBL_REF(nativeTableRefPtr);\n    if (!TYPE_VALID(env, table, columnKey, col_type_Int)) {\n        return;\n    }\n\n    try {\n        auto obj = table->get_object(ObjKey(rowKey));\n        if (obj.is_null(ColKey(columnKey))) {\n            THROW_JAVA_EXCEPTION(env, JavaExceptionDef::IllegalState,\n                                 \"Cannot increment a MutableRealmInteger whose value is null. Set its value first.\");\n        }\n\n        obj.add_int(ColKey(columnKey), value);\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_Table_nativeSetBoolean(JNIEnv* env, jclass, jlong nativeTableRefPtr,\n                                                                     jlong columnKey, jlong rowKey,\n                                                                     jboolean value, jboolean isDefault)\n{\n    TableRef table = TBL_REF(nativeTableRefPtr);\n    if (!TYPE_VALID(env, table, columnKey, col_type_Bool)) {\n        return;\n    }\n    try {\n        table->get_object(ObjKey(rowKey)).set(ColKey(columnKey), B(value), B(isDefault));\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_Table_nativeSetFloat(JNIEnv* env, jclass, jlong nativeTableRefPtr,\n                                                                   jlong columnKey, jlong rowKey, jfloat value,\n                                                                   jboolean isDefault)\n{\n    TableRef table = TBL_REF(nativeTableRefPtr);\n    if (!TYPE_VALID(env, table, columnKey, col_type_Float)) {\n        return;\n    }\n    try {\n        table->get_object(ObjKey(rowKey)).set(ColKey(columnKey), value, B(isDefault));\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_Table_nativeSetDouble(JNIEnv* env, jclass, jlong nativeTableRefPtr,\n                                                                    jlong columnKey, jlong rowKey, jdouble value,\n                                                                    jboolean isDefault)\n{\n    TableRef table = TBL_REF(nativeTableRefPtr);\n    if (!TYPE_VALID(env, table, columnKey, col_type_Double)) {\n        return;\n    }\n    try {\n        table->get_object(ObjKey(rowKey)).set(ColKey(columnKey), value, B(isDefault));\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_Table_nativeSetString(JNIEnv* env, jclass, jlong nativeTableRefPtr,\n                                                                    jlong columnKey, jlong rowKey, jstring value,\n                                                                    jboolean isDefault)\n{\n    TableRef table = TBL_REF(nativeTableRefPtr);\n    if (!TYPE_VALID(env, table, columnKey, col_type_String)) {\n        return;\n    }\n    try {\n        if (value == nullptr) {\n            if (!COL_NULLABLE(env, table, columnKey)) {\n                return;\n            }\n        }\n        JStringAccessor value2(env, value); // throws\n        table->get_object(ObjKey(rowKey)).set(ColKey(columnKey), StringData(value2), B(isDefault));\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_Table_nativeSetTimestamp(JNIEnv* env, jclass, jlong nativeTableRefPtr,\n                                                                       jlong columnKey, jlong rowKey,\n                                                                       jlong timestampValue, jboolean isDefault)\n{\n    TableRef table = TBL_REF(nativeTableRefPtr);\n    if (!TYPE_VALID(env, table, columnKey, col_type_Timestamp)) {\n        return;\n    }\n    try {\n        table->get_object(ObjKey(rowKey)).set(ColKey(columnKey), from_milliseconds(timestampValue), B(isDefault));\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_Table_nativeSetByteArray(JNIEnv* env, jclass, jlong nativeTableRefPtr,\n                                                                       jlong columnKey, jlong rowKey,\n                                                                       jbyteArray dataArray, jboolean isDefault)\n{\n    TableRef table = TBL_REF(nativeTableRefPtr);\n    if (!TYPE_VALID(env, table, columnKey, col_type_Binary)) {\n        return;\n    }\n    try {\n        if (dataArray == nullptr && !COL_NULLABLE(env, table, columnKey)) {\n            return;\n        }\n\n        JByteArrayAccessor jarray_accessor(env, dataArray);\n        table->get_object(ObjKey(rowKey)).set(ColKey(columnKey), jarray_accessor.transform<BinaryData>(), B(isDefault));\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_Table_nativeSetDecimal128(JNIEnv* env, jclass, jlong nativeTableRefPtr,\n                                                                        jlong columnKey, jlong rowKey, jlong low,\n                                                                        jlong high, jboolean isDefault)\n{\n    TableRef table = TBL_REF(nativeTableRefPtr);\n    if (!TYPE_VALID(env, table, columnKey, col_type_Decimal)) {\n        return;\n    }\n    try {\n        Decimal128::Bid128 raw {static_cast<uint64_t>(low), static_cast<uint64_t>(high)};\n        table->get_object(ObjKey(rowKey)).set(ColKey(columnKey), Decimal128(raw), B(isDefault));\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_Table_nativeSetObjectId(JNIEnv* env, jclass, jlong nativeTableRefPtr,\n                                                                      jlong columnKey, jlong rowKey, jstring j_value,\n                                                                      jboolean isDefault)\n{\n    TableRef table = TBL_REF(nativeTableRefPtr);\n    if (!TYPE_VALID(env, table, columnKey, col_type_ObjectId)) {\n        return;\n    }\n    try {\n        JStringAccessor value(env, j_value);\n        table->get_object(ObjKey(rowKey)).set(ColKey(columnKey), ObjectId(StringData(value).data()), B(isDefault));\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_Table_nativeSetUUID(JNIEnv* env, jclass, jlong nativeTableRefPtr,\n                                                                      jlong columnKey, jlong rowKey, jstring j_value,\n                                                                      jboolean isDefault)\n{\n    TableRef table = TBL_REF(nativeTableRefPtr);\n    if (!TYPE_VALID(env, table, columnKey, col_type_UUID)) {\n        return;\n    }\n    try {\n        JStringAccessor value(env, j_value);\n        table->get_object(ObjKey(rowKey)).set(ColKey(columnKey), UUID(StringData(value).data()), B(isDefault));\n    }\n    CATCH_STD()\n}\n\n\nJNIEXPORT void JNICALL Java_io_realm_internal_Table_nativeSetNull(JNIEnv* env, jclass, jlong nativeTableRefPtr,\n                                                                  jlong columnKey, jlong rowKey,\n                                                                  jboolean isDefault)\n{\n    TableRef table = TBL_REF(nativeTableRefPtr);\n    if (!COL_NULLABLE(env, table, columnKey)) {\n        return;\n    }\n\n    try {\n        table->get_object(ObjKey(rowKey)).set_null(ColKey(columnKey), B(isDefault));\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT jlong JNICALL Java_io_realm_internal_Table_nativeGetRowPtr(JNIEnv* env, jobject, jlong nativeTableRefPtr,\n                                                                     jlong key)\n{\n    try {\n        TableRef table = TBL_REF(nativeTableRefPtr);\n        Obj* obj = new Obj(table->get_object(ObjKey(key)));\n        return reinterpret_cast<jlong>(obj);\n    }\n    CATCH_STD()\n    return reinterpret_cast<jlong>(nullptr);\n}\n\n//--------------------- Indexing methods:\n\nJNIEXPORT void JNICALL Java_io_realm_internal_Table_nativeAddSearchIndex(JNIEnv* env, jobject, jlong nativeTableRefPtr,\n                                                                         jlong columnKey)\n{\n    TableRef table = TBL_REF(nativeTableRefPtr);\n    ColKey colKey(columnKey);\n    DataType column_type = table->get_column_type(colKey);\n    if (!is_allowed_to_index(env, column_type)) {\n        return;\n    }\n\n    try {\n        table->add_search_index(colKey);\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_Table_nativeRemoveSearchIndex(JNIEnv* env, jobject,\n                                                                            jlong nativeTableRefPtr, jlong columnKey)\n{\n    TableRef table = TBL_REF(nativeTableRefPtr);\n    DataType column_type = table->get_column_type(ColKey(columnKey));\n    if (!is_allowed_to_index(env, column_type)) {\n        return;\n    }\n    try {\n        table->remove_search_index(ColKey(columnKey));\n    }\n    CATCH_STD()\n}\n\n\nJNIEXPORT jboolean JNICALL Java_io_realm_internal_Table_nativeHasSearchIndex(JNIEnv* env, jobject,\n                                                                             jlong nativeTableRefPtr, jlong columnKey)\n{\n    try {\n        TableRef table = TBL_REF(nativeTableRefPtr);\n        return to_jbool(table->has_search_index(ColKey(columnKey)));\n    }\n    CATCH_STD()\n    return JNI_FALSE;\n}\n\nJNIEXPORT jboolean JNICALL Java_io_realm_internal_Table_nativeIsNullLink(JNIEnv* env, jobject, jlong nativeTableRefPtr,\n                                                                         jlong columnKey, jlong rowKey)\n{\n    TableRef table = TBL_REF(nativeTableRefPtr);\n    if (!TYPE_VALID(env, table, columnKey, col_type_Link)) {\n        return JNI_FALSE;\n    }\n\n    return to_jbool(table->get_object(ObjKey(rowKey)).is_null(ColKey(columnKey)));\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_Table_nativeNullifyLink(JNIEnv* env, jclass, jlong nativeTableRefPtr,\n                                                                      jlong columnKey, jlong rowKey)\n{\n    TableRef table = TBL_REF(nativeTableRefPtr);\n    if (!TYPE_VALID(env, table, columnKey, col_type_Link)) {\n        return;\n    }\n    try {\n        table->get_object(ObjKey(rowKey)).set_null(ColKey(columnKey));\n    }\n    CATCH_STD()\n}\n\n//---------------------- Count\n\nJNIEXPORT jlong JNICALL Java_io_realm_internal_Table_nativeCountLong(JNIEnv* env, jobject, jlong nativeTableRefPtr,\n                                                                     jlong columnKey, jlong value)\n{\n    TableRef table = TBL_REF(nativeTableRefPtr);\n    if (!TYPE_VALID(env, table, columnKey, col_type_Int)) {\n        return 0;\n    }\n    try {\n        return static_cast<jlong>(table->count_int(ColKey(columnKey), value));\n    }\n    CATCH_STD()\n    return 0;\n}\n\nJNIEXPORT jlong JNICALL Java_io_realm_internal_Table_nativeCountFloat(JNIEnv* env, jobject, jlong nativeTableRefPtr,\n                                                                      jlong columnKey, jfloat value)\n{\n    TableRef table = TBL_REF(nativeTableRefPtr);\n    if (!TYPE_VALID(env, table, columnKey, col_type_Float)) {\n        return 0;\n    }\n    try {\n        return static_cast<jlong>(table->count_float(ColKey(columnKey), value));\n    }\n    CATCH_STD()\n    return 0;\n}\n\nJNIEXPORT jlong JNICALL Java_io_realm_internal_Table_nativeCountDouble(JNIEnv* env, jobject, jlong nativeTableRefPtr,\n                                                                       jlong columnKey, jdouble value)\n{\n    TableRef table = TBL_REF(nativeTableRefPtr);\n    if (!TYPE_VALID(env, table, columnKey, col_type_Double)) {\n        return 0;\n    }\n    try {\n        return static_cast<jlong>(table->count_double(ColKey(columnKey), value));\n    }\n    CATCH_STD()\n    return 0;\n}\n\nJNIEXPORT jlong JNICALL Java_io_realm_internal_Table_nativeCountString(JNIEnv* env, jobject, jlong nativeTableRefPtr,\n                                                                       jlong columnKey, jstring value)\n{\n    TableRef table = TBL_REF(nativeTableRefPtr);\n    if (!TYPE_VALID(env, table, columnKey, col_type_String)) {\n        return 0;\n    }\n    try {\n        JStringAccessor value2(env, value); // throws\n        return static_cast<jlong>(table->count_string(ColKey(columnKey), value2));\n    }\n    CATCH_STD()\n    return 0;\n}\n\n\nJNIEXPORT jlong JNICALL Java_io_realm_internal_Table_nativeWhere(JNIEnv* env, jobject, jlong nativeTableRefPtr)\n{\n    try {\n        TableRef table = TBL_REF(nativeTableRefPtr);\n        Query* queryPtr = new Query(table->where());\n        queryPtr->set_ordering(std::make_unique<DescriptorOrdering>());\n        return reinterpret_cast<jlong>(queryPtr);\n    }\n    CATCH_STD()\n    return reinterpret_cast<jlong>(nullptr);\n}\n\n//----------------------- FindFirst\n\nJNIEXPORT jlong JNICALL Java_io_realm_internal_Table_nativeFindFirstInt(JNIEnv* env, jclass, jlong nativeTableRefPtr,\n                                                                        jlong columnKey, jlong value)\n{\n    TableRef table = TBL_REF(nativeTableRefPtr);\n    if (!TYPE_VALID(env, table, columnKey, col_type_Int)) {\n        return -1;\n    }\n    try {\n        return to_jlong_or_not_found(table->find_first_int(ColKey(columnKey), value));\n    }\n    CATCH_STD()\n    return -1;\n}\n\nJNIEXPORT jlong JNICALL Java_io_realm_internal_Table_nativeFindFirstBool(JNIEnv* env, jobject, jlong nativeTableRefPtr,\n                                                                         jlong columnKey, jboolean value)\n{\n    TableRef table = TBL_REF(nativeTableRefPtr);\n    if (!TYPE_VALID(env, table, columnKey, col_type_Bool)) {\n        return -1;\n    }\n    try {\n        return to_jlong_or_not_found(table->find_first_bool(ColKey(columnKey), to_bool(value)));\n    }\n    CATCH_STD()\n    return -1;\n}\n\nJNIEXPORT jlong JNICALL Java_io_realm_internal_Table_nativeFindFirstFloat(JNIEnv* env, jobject, jlong nativeTableRefPtr,\n                                                                          jlong columnKey, jfloat value)\n{\n    TableRef table = TBL_REF(nativeTableRefPtr);\n    if (!TYPE_VALID(env, table, columnKey, col_type_Float)) {\n        return -1;\n    }\n    try {\n        return to_jlong_or_not_found(table->find_first_float(ColKey(columnKey), value));\n    }\n    CATCH_STD()\n    return -1;\n}\n\nJNIEXPORT jlong JNICALL Java_io_realm_internal_Table_nativeFindFirstDouble(JNIEnv* env, jobject, jlong nativeTableRefPtr,\n                                                                           jlong columnKey, jdouble value)\n{\n    TableRef table = TBL_REF(nativeTableRefPtr);\n    if (!TYPE_VALID(env, table, columnKey, col_type_Double)) {\n        return -1;\n    }\n    try {\n        return to_jlong_or_not_found(table->find_first_double(ColKey(columnKey), value));\n    }\n    CATCH_STD()\n    return -1;\n}\n\nJNIEXPORT jlong JNICALL Java_io_realm_internal_Table_nativeFindFirstTimestamp(JNIEnv* env, jobject,\n                                                                              jlong nativeTableRefPtr, jlong columnKey,\n                                                                              jlong dateTimeValue)\n{\n    TableRef table = TBL_REF(nativeTableRefPtr);\n    if (!TYPE_VALID(env, table, columnKey, col_type_Timestamp)) {\n        return -1;\n    }\n    try {\n        return to_jlong_or_not_found(table->find_first_timestamp(ColKey(columnKey), from_milliseconds(dateTimeValue)));\n    }\n    CATCH_STD()\n    return -1;\n}\n\nJNIEXPORT jlong JNICALL Java_io_realm_internal_Table_nativeFindFirstString(JNIEnv* env, jclass, jlong nativeTableRefPtr,\n                                                                           jlong columnKey, jstring value)\n{\n    TableRef table = TBL_REF(nativeTableRefPtr);\n    if (!TYPE_VALID(env, table, columnKey, col_type_String)) {\n        return -1;\n    }\n\n    try {\n        JStringAccessor value2(env, value); // throws\n        return to_jlong_or_not_found(table->find_first_string(ColKey(columnKey), value2));\n    }\n    CATCH_STD()\n    return -1;\n}\n\nJNIEXPORT jlong JNICALL Java_io_realm_internal_Table_nativeFindFirstDecimal128(JNIEnv* env, jclass, jlong nativeTableRefPtr,\n                                                                             jlong columnKey, jlong low, jlong high)\n{\n    TableRef table = TBL_REF(nativeTableRefPtr);\n    if (!TYPE_VALID(env, table, columnKey, col_type_Decimal)) {\n        return -1;\n    }\n\n    try {\n        Decimal128::Bid128 raw {static_cast<uint64_t>(low), static_cast<uint64_t>(high)};\n        return to_jlong_or_not_found(table->find_first_decimal(ColKey(columnKey), Decimal128(raw)));\n    }\n    CATCH_STD()\n    return -1;\n}\n\nJNIEXPORT jlong JNICALL Java_io_realm_internal_Table_nativeFindFirstObjectId(JNIEnv* env, jclass, jlong nativeTableRefPtr,\n                                                                             jlong columnKey, jstring j_value)\n{\n    TableRef table = TBL_REF(nativeTableRefPtr);\n    if (!TYPE_VALID(env, table, columnKey, col_type_ObjectId)) {\n        return -1;\n    }\n\n    try {\n        JStringAccessor value(env, j_value); // throws\n        ObjectId id = ObjectId(StringData(value).data());\n        return to_jlong_or_not_found(table->find_first_object_id(ColKey(columnKey), id));\n    }\n    CATCH_STD()\n    return -1;\n}\n\nJNIEXPORT jlong JNICALL Java_io_realm_internal_Table_nativeFindFirstUUID(JNIEnv* env, jclass, jlong nativeTableRefPtr,\n                                                                             jlong columnKey, jstring j_value)\n{\n    TableRef table = TBL_REF(nativeTableRefPtr);\n    if (!TYPE_VALID(env, table, columnKey, col_type_UUID)) {\n        return -1;\n    }\n\n    try {\n        JStringAccessor value(env, j_value); // throws\n        UUID uuid = UUID(StringData(value).data());\n        return to_jlong_or_not_found(table->find_first_uuid(ColKey(columnKey), uuid));\n    }\n    CATCH_STD()\n    return -1;\n}\n\n\nJNIEXPORT jlong JNICALL Java_io_realm_internal_Table_nativeFindFirstNull(JNIEnv* env, jclass, jlong nativeTableRefPtr,\n                                                                         jlong columnKey)\n{\n    TableRef table = TBL_REF(nativeTableRefPtr);\n    if (!COL_NULLABLE(env, table, columnKey)) {\n        return static_cast<jlong>(realm::not_found);\n    }\n    try {\n        return to_jlong_or_not_found(table->find_first_null(ColKey(columnKey)));\n    }\n    CATCH_STD()\n    return static_cast<jlong>(realm::not_found);\n}\n\n// FindAll\n\n//\n\nJNIEXPORT jstring JNICALL Java_io_realm_internal_Table_nativeGetName(JNIEnv* env, jobject, jlong nativeTableRefPtr)\n{\n    try {\n        TableRef table = TBL_REF(nativeTableRefPtr);\n        // Mirror API in Java for now. Before Core 6 this would return null for tables not attached to the group.\n        if (table) {\n            return to_jstring(env, table->get_name());\n        } else {\n            return nullptr;\n        }\n    }\n    CATCH_STD()\n    return nullptr;\n}\n\nJNIEXPORT jboolean JNICALL Java_io_realm_internal_Table_nativeIsValid(JNIEnv*, jobject, jlong nativeTableRefPtr)\n{\n    if(TBL_REF(nativeTableRefPtr)) {\n        return JNI_TRUE;\n    } else {\n        return JNI_FALSE;\n    }\n}\n\nJNIEXPORT jboolean JNICALL Java_io_realm_internal_Table_nativeHasSameSchema(JNIEnv*, jobject, jlong thisTableRefPtr,\n                                                                            jlong otherTableRefPtr)\n{\n    TableRef this_table = TBL_REF(thisTableRefPtr);\n    TableRef other_table = TBL_REF(otherTableRefPtr);\n    return to_jbool(this_table->get_key() == other_table->get_key());\n}\n\nstatic void finalize_table(jlong ptr)\n{\n    delete reinterpret_cast<realm::TableRef*>(ptr);\n}\n\nJNIEXPORT jlong JNICALL Java_io_realm_internal_Table_nativeGetFinalizerPtr(JNIEnv*, jclass)\n{\n    return reinterpret_cast<jlong>(&finalize_table);\n}\n\nJNIEXPORT jlong JNICALL Java_io_realm_internal_Table_nativeFreeze(JNIEnv*, jclass, jlong j_frozen_shared_realm_ptr, jlong j_table_ptr)\n{\n    auto& shared_realm = *(reinterpret_cast<SharedRealm*>(j_frozen_shared_realm_ptr));\n    TableRef table = TableRef(TBL_REF(j_table_ptr));\n    TableRef* frozen_table = new TableRef(shared_realm->import_copy_of(table));\n    return reinterpret_cast<jlong>(frozen_table);\n}\n\nJNIEXPORT jboolean JNICALL Java_io_realm_internal_Table_nativeIsEmbedded(JNIEnv* env, jclass, jlong j_table_ptr)\n{\n    try {\n        TableRef table = TableRef(TBL_REF(j_table_ptr));\n        return to_jbool(table->is_embedded());\n    }\n    CATCH_STD()\n    return false;\n}\n\nJNIEXPORT jboolean JNICALL Java_io_realm_internal_Table_nativeSetEmbedded(JNIEnv* env, jclass, jlong j_table_ptr, jboolean j_embedded, jboolean j_handle_backlinks)\n{\n    try {\n        TableRef table = TableRef(TBL_REF(j_table_ptr));\n        table->set_table_type(to_bool(j_embedded) ? Table::Type::Embedded : Table::Type::TopLevel, to_bool(j_handle_backlinks));\n        return true;\n    }\n    CATCH_STD()\n    return false;\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/cpp/io_realm_internal_TableQuery.cpp",
    "content": "/*\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#include \"io_realm_internal_TableQuery.h\"\n\n#include <realm.hpp>\n#include <realm/query_expression.hpp>\n#include <realm/table.hpp>\n#include <realm/parser/keypath_mapping.hpp>\n#include <realm/parser/query_parser.hpp>\n\n#include <realm/object-store/shared_realm.hpp>\n#include <realm/object-store/object_store.hpp>\n#include <realm/object-store/results.hpp>\n\n#include \"java_accessor.hpp\"\n#include \"java_object_accessor.hpp\"\n#include \"java_class_global_def.hpp\"\n#include \"util.hpp\"\n\nusing namespace realm;\nusing namespace realm::jni_util;\nusing namespace realm::_impl;\n\nstatic void finalize_table_query(jlong ptr);\n\n// Find --------------------------------------\n\nJNIEXPORT jlong JNICALL Java_io_realm_internal_TableQuery_nativeFind(JNIEnv *env, jobject, jlong nativeQueryPtr) {\n    Query *pQuery = Q(nativeQueryPtr);\n    try {\n        auto ordering = pQuery->get_ordering();\n        ObjKey objKey;\n\n        if (ordering) {\n            auto all = pQuery->find_all(*ordering);\n            objKey = all.size() > 0 ? all.get_key(0) : ObjKey();\n        } else {\n            objKey = pQuery->find();\n        }\n\n        pQuery->set_ordering(std::make_unique<DescriptorOrdering>(*ordering));\n\n        return to_jlong_or_not_found(objKey);\n    }\n    CATCH_STD()\n    return -1;\n}\n\n// Integer Aggregates\n\nJNIEXPORT jlong JNICALL Java_io_realm_internal_TableQuery_nativeSumInt(JNIEnv *env, jobject, jlong nativeQueryPtr,\n                                                                       jlong columnKey) {\n    Query *pQuery = Q(nativeQueryPtr);\n    ConstTableRef pTable = pQuery->get_table();\n    if (!TYPE_VALID(env, pTable, columnKey, col_type_Int)) {\n        return 0;\n    }\n    try {\n        auto result = pQuery->sum(ColKey(columnKey));\n        if (result && !result->is_null()) {\n            return result->get_int();\n        }\n    }\n    CATCH_STD()\n    return 0;\n}\n\nJNIEXPORT jobject JNICALL Java_io_realm_internal_TableQuery_nativeMaximumInt(JNIEnv *env, jobject,\n                                                                             jlong nativeQueryPtr, jlong columnKey) {\n    Query *pQuery = Q(nativeQueryPtr);\n    ConstTableRef pTable = pQuery->get_table();\n    if (!TYPE_VALID(env, pTable, columnKey, col_type_Int)) {\n        return nullptr;\n    }\n    try {\n        auto result = pQuery->max(ColKey(columnKey));\n        if (result && !result->is_null()) {\n            return JavaClassGlobalDef::new_long(env, result->get_int());\n        }\n    }\n    CATCH_STD()\n    return nullptr;\n}\n\nJNIEXPORT jobject JNICALL Java_io_realm_internal_TableQuery_nativeMinimumInt(JNIEnv *env, jobject,\n                                                                             jlong nativeQueryPtr, jlong columnKey) {\n    Query *pQuery = Q(nativeQueryPtr);\n    ConstTableRef pTable = pQuery->get_table();\n    if (!TYPE_VALID(env, pTable, columnKey, col_type_Int)) {\n        return nullptr;\n    }\n    try {\n        auto result = pQuery->min(ColKey(columnKey));\n        if (result && !result->is_null()) {\n            return JavaClassGlobalDef::new_long(env, result->get_int());\n        }\n    }\n    CATCH_STD()\n    return nullptr;\n}\n\nJNIEXPORT jdouble JNICALL Java_io_realm_internal_TableQuery_nativeAverageInt(JNIEnv *env, jobject,\n                                                                             jlong nativeQueryPtr, jlong columnKey) {\n    Query *pQuery = Q(nativeQueryPtr);\n    ConstTableRef pTable = pQuery->get_table();\n    if (!TYPE_VALID(env, pTable, columnKey, col_type_Int)) {\n        return 0;\n    }\n    try {\n        auto result = pQuery->avg(ColKey(columnKey));\n        if (result && !result->is_null()) {\n            return result->get_double();\n        }\n    }\n    CATCH_STD()\n    return 0;\n}\n\n\n// float Aggregates\n\nJNIEXPORT jdouble JNICALL Java_io_realm_internal_TableQuery_nativeSumFloat(JNIEnv *env, jobject, jlong nativeQueryPtr,\n                                                                           jlong columnKey) {\n    Query *pQuery = Q(nativeQueryPtr);\n    ConstTableRef pTable = pQuery->get_table();\n    if (!TYPE_VALID(env, pTable, columnKey, col_type_Float)) {\n        return 0;\n    }\n    try {\n        auto result = pQuery->sum(ColKey(columnKey));\n        if (result && !result->is_null()) {\n            return result->get_double();\n        }\n    }\n    CATCH_STD()\n    return 0;\n}\n\nJNIEXPORT jobject JNICALL Java_io_realm_internal_TableQuery_nativeMaximumFloat(JNIEnv *env, jobject,\n                                                                               jlong nativeQueryPtr,\n                                                                               jlong columnKey) {\n    Query *pQuery = Q(nativeQueryPtr);\n    ConstTableRef pTable = pQuery->get_table();\n    if (!TYPE_VALID(env, pTable, columnKey, col_type_Float)) {\n        return nullptr;\n    }\n    try {\n        auto result = pQuery->max(ColKey(columnKey));\n        if (result && !result->is_null()) {\n            return JavaClassGlobalDef::new_float(env, result->get_float());\n        }\n    }\n    CATCH_STD()\n    return nullptr;\n}\n\nJNIEXPORT jobject JNICALL Java_io_realm_internal_TableQuery_nativeMinimumFloat(JNIEnv *env, jobject,\n                                                                               jlong nativeQueryPtr,\n                                                                               jlong columnKey) {\n    Query *pQuery = Q(nativeQueryPtr);\n    ConstTableRef pTable = pQuery->get_table();\n    if (!TYPE_VALID(env, pTable, columnKey, col_type_Float)) {\n        return nullptr;\n    }\n    try {\n        auto result = pQuery->min(ColKey(columnKey));\n        if (result && !result->is_null()) {\n            return JavaClassGlobalDef::new_float(env, result->get_float());\n        }\n    }\n    CATCH_STD()\n    return nullptr;\n}\n\nJNIEXPORT jdouble JNICALL Java_io_realm_internal_TableQuery_nativeAverageFloat(JNIEnv *env, jobject,\n                                                                               jlong nativeQueryPtr,\n                                                                               jlong columnKey) {\n    Query *pQuery = Q(nativeQueryPtr);\n    ConstTableRef pTable = pQuery->get_table();\n    if (!TYPE_VALID(env, pTable, columnKey, col_type_Float)) {\n        return 0;\n    }\n    try {\n        auto result = pQuery->avg(ColKey(columnKey));\n        if (result && !result->is_null()) {\n            return result->get_double();\n        }\n    }\n    CATCH_STD()\n    return 0;\n}\n\n// double Aggregates\nJNIEXPORT jlongArray JNICALL Java_io_realm_internal_TableQuery_nativeSumRealmAny(JNIEnv *env, jobject,\n                                                                              jlong nativeQueryPtr, jlong columnKey) {\n    Query *pQuery = Q(nativeQueryPtr);\n    ConstTableRef pTable = pQuery->get_table();\n    if (!TYPE_VALID(env, pTable, columnKey, col_type_Mixed)) {\n        return nullptr;\n    }\n    try {\n        auto result = pQuery->sum(ColKey(columnKey));\n        if (result && !result->is_null()) {\n            Decimal128 decimal128 = result->get_decimal();\n            RETURN_DECIMAL128_AS_JLONG_ARRAY__OR_NULL(decimal128)\n        }\n    }\n    CATCH_STD()\n    return nullptr;\n}\n\nJNIEXPORT jdouble JNICALL Java_io_realm_internal_TableQuery_nativeSumDouble(JNIEnv *env, jobject,\n                                                                            jlong nativeQueryPtr, jlong columnKey) {\n    Query *pQuery = Q(nativeQueryPtr);\n    ConstTableRef pTable = pQuery->get_table();\n    if (!TYPE_VALID(env, pTable, columnKey, col_type_Double)) {\n        return 0;\n    }\n    try {\n        auto result = pQuery->sum(ColKey(columnKey));\n        if (result && !result->is_null()) {\n            return result->get_double();\n        }\n    }\n    CATCH_STD()\n    return 0;\n}\n\nJNIEXPORT jobject JNICALL Java_io_realm_internal_TableQuery_nativeMaximumDouble(JNIEnv *env, jobject,\n                                                                                jlong nativeQueryPtr,\n                                                                                jlong columnKey) {\n    Query *pQuery = Q(nativeQueryPtr);\n    ConstTableRef pTable = pQuery->get_table();\n    if (!TYPE_VALID(env, pTable, columnKey, col_type_Double)) {\n        return nullptr;\n    }\n    try {\n        auto result = pQuery->max(ColKey(columnKey));\n        if (result && !result->is_null()) {\n            return JavaClassGlobalDef::new_double(env, result->get_double());\n        }\n    }\n    CATCH_STD()\n    return nullptr;\n}\n\nJNIEXPORT jobject JNICALL Java_io_realm_internal_TableQuery_nativeMaximumRealmAny(JNIEnv *env, jobject,\n                                                                               jlong nativeQueryPtr,\n                                                                               jlong columnKey) {\n    Query *pQuery = Q(nativeQueryPtr);\n    ConstTableRef pTable = pQuery->get_table();\n    if (!TYPE_VALID(env, pTable, columnKey, col_type_Mixed)) {\n        return nullptr;\n    }\n    try {\n        auto result = pQuery->max(ColKey(columnKey));\n        if (result && !result->is_null()) {\n            return JavaClassGlobalDef::new_mixed(env, *result);\n        }\n    }\n    CATCH_STD()\n    return nullptr;\n}\n\nJNIEXPORT jlongArray JNICALL Java_io_realm_internal_TableQuery_nativeMaximumDecimal128(JNIEnv *env, jobject,\n                                                                                       jlong nativeQueryPtr,\n                                                                                       jlong columnKey) {\n    Query *pQuery = Q(nativeQueryPtr);\n    ConstTableRef pTable = pQuery->get_table();\n    if (!TYPE_VALID(env, pTable, columnKey, col_type_Decimal)) {\n        return nullptr;\n    }\n    try {\n        auto result = pQuery->max(ColKey(columnKey));\n        if (result && !result->is_null()) {\n            RETURN_DECIMAL128_AS_JLONG_ARRAY__OR_NULL(result->get<Decimal128>())\n        }\n    }\n    CATCH_STD()\n    return nullptr;\n}\n\nJNIEXPORT jlongArray JNICALL Java_io_realm_internal_TableQuery_nativeSumDecimal128(JNIEnv *env, jobject,\n                                                                                   jlong nativeQueryPtr,\n                                                                                   jlong columnKey) {\n    Query *pQuery = Q(nativeQueryPtr);\n    ConstTableRef pTable = pQuery->get_table();\n    if (!TYPE_VALID(env, pTable, columnKey, col_type_Decimal)) {\n        return 0;\n    }\n    try {\n        auto result = pQuery->sum(ColKey(columnKey));\n        if (result && !result->is_null()) {\n            RETURN_DECIMAL128_AS_JLONG_ARRAY__OR_NULL(result->get_decimal())\n        }\n    }\n    CATCH_STD()\n    return 0;\n}\n\nJNIEXPORT jobject JNICALL Java_io_realm_internal_TableQuery_nativeMinimumDouble(JNIEnv *env, jobject,\n                                                                                jlong nativeQueryPtr,\n                                                                                jlong columnKey) {\n    Query *pQuery = Q(nativeQueryPtr);\n    ConstTableRef pTable = pQuery->get_table();\n    if (!TYPE_VALID(env, pTable, columnKey, col_type_Double)) {\n        return nullptr;\n    }\n    try {\n        auto result = pQuery->min(ColKey(columnKey));\n        if (result && !result->is_null()) {\n            return JavaClassGlobalDef::new_double(env, result->get<double>());\n        }\n    }\n    CATCH_STD()\n    return nullptr;\n}\n\nJNIEXPORT jobject JNICALL Java_io_realm_internal_TableQuery_nativeMinimumRealmAny(JNIEnv *env, jobject,\n                                                                               jlong nativeQueryPtr,\n                                                                               jlong columnKey) {\n    Query *pQuery = Q(nativeQueryPtr);\n    ConstTableRef pTable = pQuery->get_table();\n    if (!TYPE_VALID(env, pTable, columnKey, col_type_Mixed)) {\n        return nullptr;\n    }\n    try {\n        auto result = pQuery->min(ColKey(columnKey));\n        if (result && !result->is_null()) {\n            return JavaClassGlobalDef::new_mixed(env, *result);\n        }\n    }\n    CATCH_STD()\n    return nullptr;\n}\n\nJNIEXPORT jlongArray JNICALL Java_io_realm_internal_TableQuery_nativeMinimumDecimal128(JNIEnv *env, jobject,\n                                                                                       jlong nativeQueryPtr,\n                                                                                       jlong columnKey) {\n    Query *pQuery = Q(nativeQueryPtr);\n    ConstTableRef pTable = pQuery->get_table();\n    if (!TYPE_VALID(env, pTable, columnKey, col_type_Decimal)) {\n        return nullptr;\n    }\n    try {\n        auto result = pQuery->min(ColKey(columnKey));\n        if (result && !result->is_null()) {\n            RETURN_DECIMAL128_AS_JLONG_ARRAY__OR_NULL(result->get<Decimal128>())\n        }\n    }\n    CATCH_STD()\n    return nullptr;\n}\n\nJNIEXPORT jdouble JNICALL Java_io_realm_internal_TableQuery_nativeAverageDouble(JNIEnv *env, jobject,\n                                                                                jlong nativeQueryPtr,\n                                                                                jlong columnKey) {\n    Query *pQuery = Q(nativeQueryPtr);\n    ConstTableRef pTable = pQuery->get_table();\n    if (!TYPE_VALID(env, pTable, columnKey, col_type_Double)) {\n        return 0;\n    }\n    try {\n        auto result = pQuery->avg(ColKey(columnKey));\n        if (result && !result->is_null()) {\n            return result->get_double();\n        }\n    }\n    CATCH_STD()\n    return 0;\n}\n\nJNIEXPORT jlongArray JNICALL Java_io_realm_internal_TableQuery_nativeAverageRealmAny(JNIEnv *env, jobject,\n                                                                                  jlong nativeQueryPtr,\n                                                                                  jlong columnKey) {\n    Query *pQuery = Q(nativeQueryPtr);\n    ConstTableRef pTable = pQuery->get_table();\n    if (!TYPE_VALID(env, pTable, columnKey, col_type_Mixed)) {\n        return nullptr;\n    }\n    try {\n        auto result = pQuery->avg(ColKey(columnKey));\n        if (result && !result->is_null()) {\n            RETURN_DECIMAL128_AS_JLONG_ARRAY__OR_NULL(result->get<Decimal128>())\n        }\n    }\n    CATCH_STD()\n    return nullptr;\n}\n\nJNIEXPORT jlongArray JNICALL Java_io_realm_internal_TableQuery_nativeAverageDecimal128(JNIEnv *env, jobject,\n                                                                                       jlong nativeQueryPtr,\n                                                                                       jlong columnKey) {\n    Query *pQuery = Q(nativeQueryPtr);\n    ConstTableRef pTable = pQuery->get_table();\n    if (!TYPE_VALID(env, pTable, columnKey, col_type_Decimal)) {\n        return nullptr;\n    }\n    try {\n        auto result = pQuery->avg(ColKey(columnKey));\n        if (result && !result->is_null()) {\n            RETURN_DECIMAL128_AS_JLONG_ARRAY__OR_NULL(result->get<Decimal128>())\n        }\n    }\n    CATCH_STD()\n    return nullptr;\n}\n\n// date aggregates\nJNIEXPORT jobject JNICALL Java_io_realm_internal_TableQuery_nativeMaximumTimestamp(JNIEnv *env, jobject,\n                                                                                   jlong nativeQueryPtr,\n                                                                                   jlong columnKey) {\n    Query *pQuery = Q(nativeQueryPtr);\n    ConstTableRef pTable = pQuery->get_table();\n    if (!TYPE_VALID(env, pTable, columnKey, col_type_Timestamp)) {\n        return nullptr;\n    }\n    try {\n        auto result = pQuery->max(ColKey(columnKey));\n        if (result && !result->is_null()) {\n            return JavaClassGlobalDef::new_long(env, to_milliseconds(result->get_timestamp()));\n        }\n    }\n    CATCH_STD()\n    return nullptr;\n}\n\nJNIEXPORT jobject JNICALL Java_io_realm_internal_TableQuery_nativeMinimumTimestamp(JNIEnv *env, jobject,\n                                                                                   jlong nativeQueryPtr,\n                                                                                   jlong columnKey) {\n    Query *pQuery = Q(nativeQueryPtr);\n    ConstTableRef pTable = pQuery->get_table();\n    if (!TYPE_VALID(env, pTable, columnKey, col_type_Timestamp)) {\n        return nullptr;\n    }\n    try {\n        auto result = pQuery->min(ColKey(columnKey));\n        if (result && !result->is_null()) {\n            return JavaClassGlobalDef::new_long(env, to_milliseconds(result->get_timestamp()));\n        }\n    }\n    CATCH_STD()\n    return nullptr;\n}\n\n// Count, Remove\n\nJNIEXPORT jlong JNICALL Java_io_realm_internal_TableQuery_nativeCount(JNIEnv *env, jobject, jlong nativeQueryPtr) {\n    Query *pQuery = Q(nativeQueryPtr);\n    try {\n        return static_cast<jlong>(pQuery->count());\n    }\n    CATCH_STD()\n    return 0;\n}\n\nJNIEXPORT jlong JNICALL Java_io_realm_internal_TableQuery_nativeRemove(JNIEnv *env, jobject, jlong nativeQueryPtr) {\n    Query *pQuery = Q(nativeQueryPtr);\n    try {\n        return static_cast<jlong>(pQuery->remove());\n    }\n    CATCH_STD()\n    return 0;\n}\n\nstatic void finalize_table_query(jlong ptr) {\n    delete Q(ptr);\n}\n\nJNIEXPORT jlong JNICALL Java_io_realm_internal_TableQuery_nativeGetFinalizerPtr(JNIEnv *, jclass) {\n    return reinterpret_cast<jlong>(&finalize_table_query);\n}\n\nvoid rawQuery(jlong j_query_ptr,\n              const std::string filter,\n              const std::vector<Mixed> &args,\n              jlong j_mapping_ptr,\n              bool onlyOrder = false) {\n    auto &query = *reinterpret_cast<Query *>(j_query_ptr);\n\n    query_parser::KeyPathMapping mapping;\n    if (j_mapping_ptr) {\n        mapping = *reinterpret_cast<query_parser::KeyPathMapping *>(j_mapping_ptr);\n    }\n\n    Query predicate = query.get_table()->query(filter, args, mapping);\n\n    if (!onlyOrder) {\n        query.and_query(predicate);\n    }\n\n    if (auto parsed_ordering = predicate.get_ordering()) {\n        auto ordering = query.get_ordering();\n        ordering->append(*parsed_ordering);\n\n        query.set_ordering(std::make_unique<DescriptorOrdering>(*ordering));\n    }\n}\n\nJNIEXPORT void JNICALL\nJava_io_realm_internal_TableQuery_nativeRawPredicate(JNIEnv *env,\n                                                     jobject,\n                                                     jlong j_query_ptr,\n                                                     jstring j_filter,\n                                                     jlongArray j_args,\n                                                     jlong j_mapping_ptr) {\n    try {\n        JStringAccessor filter(env, j_filter); // throws\n\n        JLongArrayAccessor arguments(env, j_args);\n        std::vector<Mixed> args;\n\n        for (jsize i = 0; i < arguments.size(); ++i) {\n            auto &value = *reinterpret_cast<JavaValue *>(arguments[i]);\n            args.push_back(value.to_mixed());\n        }\n\n        rawQuery(j_query_ptr, std::string(filter), args, j_mapping_ptr);\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL\nJava_io_realm_internal_TableQuery_nativeRawDescriptor(JNIEnv *env,\n                                                      jobject,\n                                                      jlong j_query_ptr,\n                                                      jstring j_descriptor,\n                                                      jlong j_mapping_ptr) {\n    try {\n        JStringAccessor filter(env, j_descriptor); // throws\n        std::vector<Mixed> args(0);\n\n        rawQuery(j_query_ptr, \"TRUEPREDICATE \" + std::string(filter), args, j_mapping_ptr, true);\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL\nJava_io_realm_internal_TableQuery_nativeBeginGroup(JNIEnv *env,\n                                                   jobject,\n                                                   jlong j_query_ptr) {\n    try {\n        auto query = reinterpret_cast<Query *>(j_query_ptr);\n        query->group();\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL\nJava_io_realm_internal_TableQuery_nativeEndGroup(JNIEnv *env,\n                                                 jobject,\n                                                 jlong j_query_ptr) {\n    try {\n        auto query = reinterpret_cast<Query *>(j_query_ptr);\n        query->end_group();\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL\nJava_io_realm_internal_TableQuery_nativeOr(JNIEnv *env,\n                                           jobject,\n                                           jlong j_query_ptr) {\n    try {\n        auto query = reinterpret_cast<Query *>(j_query_ptr);\n        query->Or();\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL\nJava_io_realm_internal_TableQuery_nativeNot(JNIEnv *env,\n                                            jobject,\n                                            jlong j_query_ptr) {\n    try {\n        auto query = reinterpret_cast<Query *>(j_query_ptr);\n        query->Not();\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT jstring JNICALL\nJava_io_realm_internal_TableQuery_nativeValidateQuery(JNIEnv *env, jobject,\n                                                      jlong nativeQueryPtr) {\n    try {\n        const std::string str = Q(nativeQueryPtr)->validate();\n        StringData sd(str);\n        return to_jstring(env, sd);\n    }\n    CATCH_STD()\n    return nullptr;\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/cpp/io_realm_internal_TestUtil.cpp",
    "content": "#define __STDC_LIMIT_MACROS // See https://stackoverflow.com/a/3233069/1389357\n#include <cstdint>\n\n#include \"io_realm_internal_TestUtil.h\"\n#include \"util.hpp\"\n\n#include <realm/timestamp.hpp>\n\nstatic jstring throwOrGetExpectedMessage(JNIEnv* env, jlong testcase, bool should_throw);\n\nJNIEXPORT jlong JNICALL Java_io_realm_internal_TestUtil_getMaxExceptionNumber(JNIEnv*, jclass)\n{\n    return ExceptionKindMax;\n}\n\nJNIEXPORT jstring JNICALL Java_io_realm_internal_TestUtil_getExpectedMessage(JNIEnv* env, jclass,\n                                                                             jlong exception_kind)\n{\n    return throwOrGetExpectedMessage(env, exception_kind, false);\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_TestUtil_testThrowExceptions(JNIEnv* env, jclass, jlong exception_kind)\n{\n    throwOrGetExpectedMessage(env, exception_kind, true);\n}\n\nJNIEXPORT jlong JNICALL Java_io_realm_internal_TestUtil_getDateFromTimestamp(JNIEnv*, jclass, jlong seconds, jint nanoseconds)\n{\n    return to_milliseconds(realm::Timestamp(static_cast<int64_t>(seconds), static_cast<int32_t>(nanoseconds)));\n}\n\nstatic jstring throwOrGetExpectedMessage(JNIEnv* env, jlong testcase, bool should_throw)\n{\n    std::string expect;\n\n    switch (ExceptionKind(testcase)) {\n        case ClassNotFound:\n            expect = \"java.lang.ClassNotFoundException: Class 'parm1' could not be located.\";\n            if (should_throw)\n                ThrowException(env, ClassNotFound, \"parm1\", \"parm2\");\n            break;\n        case IllegalArgument:\n            expect = \"java.lang.IllegalArgumentException: Illegal Argument: parm1\";\n            if (should_throw)\n                ThrowException(env, IllegalArgument, \"parm1\", \"parm2\");\n            break;\n        case IndexOutOfBounds:\n            expect = \"java.lang.ArrayIndexOutOfBoundsException: parm1\";\n            if (should_throw)\n                ThrowException(env, IndexOutOfBounds, \"parm1\", \"parm2\");\n            break;\n        case UnsupportedOperation:\n            expect = \"java.lang.UnsupportedOperationException: parm1\";\n            if (should_throw)\n                ThrowException(env, UnsupportedOperation, \"parm1\", \"parm2\");\n            break;\n        case OutOfMemory:\n            expect = \"java.lang.OutOfMemoryError: parm1 parm2\";\n            if (should_throw)\n                ThrowException(env, OutOfMemory, \"parm1\", \"parm2\");\n            break;\n        case FatalError:\n            expect = \"io.realm.exceptions.RealmError: Unrecoverable error. parm1\";\n            if (should_throw)\n                ThrowException(env, FatalError, \"parm1\", \"parm2\");\n            break;\n        case RuntimeError:\n            expect = \"java.lang.RuntimeException: parm1\";\n            if (should_throw)\n                ThrowException(env, RuntimeError, \"parm1\", \"parm2\");\n            break;\n        case BadVersion:\n            expect = \"io.realm.internal.async.BadVersionException: parm1\";\n            if (should_throw)\n                ThrowException(env, BadVersion, \"parm1\", \"parm2\");\n            break;\n        case IllegalState:\n            expect = \"java.lang.IllegalStateException: parm1\";\n            if (should_throw)\n                ThrowException(env, IllegalState, \"parm1\");\n            break;\n        // FIXME: This is difficult to test right now. Need to refactor the test.\n        // See https://github.com/realm/realm-java/issues/3348\n        // case RealmFileError:\n        default:\n            break;\n    }\n    if (should_throw) {\n        return nullptr;\n    }\n    return to_jstring(env, expect);\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/cpp/io_realm_internal_UncheckedRow.cpp",
    "content": "/*\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#include \"io_realm_internal_UncheckedRow.h\"\n#include \"io_realm_internal_Property.h\"\n\n#include \"java_accessor.hpp\"\n#include \"java_object_accessor.hpp\"\n#include \"util.hpp\"\n\nusing namespace realm;\nusing namespace realm::_impl;\n\nstatic void finalize_unchecked_row(jlong ptr);\n\nJNIEXPORT jlong JNICALL Java_io_realm_internal_UncheckedRow_nativeGetColumnCount(JNIEnv*, jobject, jlong nativeRowPtr)\n{\n    if (!OBJ(nativeRowPtr)->is_valid()) {\n        return 0;\n    }\n\n    return static_cast<jlong>(OBJ(nativeRowPtr)->get_table()->get_column_count()); // noexcept\n}\n\nJNIEXPORT jlong JNICALL Java_io_realm_internal_UncheckedRow_nativeGetColumnKey(JNIEnv* env, jobject,\n                                                                                 jlong nativeRowPtr,\n                                                                                 jstring columnName)\n{\n    if (!OBJ(nativeRowPtr)->is_valid()) {\n        ThrowException(env, IllegalArgument, \"Object passed is not valid\");\n    }\n\n    try {\n        JStringAccessor columnName2(env, columnName);                                   // throws\n        ColKey col_key = OBJ(nativeRowPtr)->get_table()->get_column_key(columnName2);\n        if (bool(col_key)) {\n            return col_key.value;\n        }\n    }\n    CATCH_STD()\n    return ColKey().value;\n}\n\nJNIEXPORT jobjectArray JNICALL Java_io_realm_internal_UncheckedRow_nativeGetColumnNames(JNIEnv* env, jobject,\n                                                                               jlong nativeRowPtr)\n{\n    if (!OBJ(nativeRowPtr)->is_valid()) {\n        ThrowException(env, IllegalArgument, \"Object passed is not valid\");\n    }\n\n    try {\n        ColKeys col_keys = OBJ(nativeRowPtr)->get_table()->get_column_keys();\n\n        size_t size = col_keys.size();\n        jobjectArray col_keys_array = env->NewObjectArray(size, JavaClassGlobalDef::java_lang_string(), 0);\n        if (col_keys_array == NULL) {\n            ThrowException(env, OutOfMemory, \"Could not allocate memory to return column keys.\");\n            return NULL;\n        }\n        for (size_t i = 0; i < size; ++i) {\n            env->SetObjectArrayElement(col_keys_array, i, to_jstring(env,  OBJ(nativeRowPtr)->get_table()->get_column_name(col_keys[i])));\n        }\n\n        return col_keys_array;\n\n    }\n    CATCH_STD()\n    return NULL;\n}\n\n\nJNIEXPORT jint JNICALL Java_io_realm_internal_UncheckedRow_nativeGetColumnType(JNIEnv*, jobject, jlong nativeRowPtr,\n                                                                               jlong columnKey)\n{\n    ColKey column_key (columnKey);\n    auto table = OBJ(nativeRowPtr)->get_table();\n    DataType column_type = table->get_column_type(column_key);\n    if (column_type != type_LinkList && table->is_list(column_key)/* && column_type < type_LinkList because type_ObjectId is = 15*/) {\n        // add the offset so it can be mapped correctly in Java (RealmFieldType#fromNativeValue)\n        return int(column_type) + int(PropertyType::Array);\n    } else if (column_key.is_dictionary()) {\n        return int(column_type) + int(PropertyType::Dictionary);\n    } else if (column_key.is_set()) {\n        return int(column_type) + int(PropertyType::Set);\n    }\n\n    return int(column_type);\n}\n\nJNIEXPORT jlong JNICALL Java_io_realm_internal_UncheckedRow_nativeGetObjectKey(JNIEnv* env, jobject, jlong nativeRowPtr)\n{\n    if (!ROW_VALID(env, OBJ(nativeRowPtr))) {\n        return 0;\n    }\n\n    return static_cast<jlong>(OBJ(nativeRowPtr)->get_key().value);\n}\n\nJNIEXPORT jlong JNICALL Java_io_realm_internal_UncheckedRow_nativeGetLong(JNIEnv* env, jobject, jlong nativeRowPtr,\n                                                                          jlong columnKey)\n{\n    if (!ROW_VALID(env, OBJ(nativeRowPtr))) {\n        return 0;\n    }\n    ColKey col_key(columnKey);\n    if (col_key.get_attrs().test(col_attr_Nullable)) {\n        auto val = OBJ(nativeRowPtr)->get<util::Optional<int64_t>>(col_key);\n        return val.value();\n    } else {\n        return  OBJ(nativeRowPtr)->get<int64_t>(col_key);\n    }\n}\n\nJNIEXPORT jboolean JNICALL Java_io_realm_internal_UncheckedRow_nativeGetBoolean(JNIEnv* env, jobject,\n                                                                                jlong nativeRowPtr, jlong columnKey)\n{\n    if (!ROW_VALID(env, OBJ(nativeRowPtr))) {\n        return 0;\n    }\n\n    return to_jbool(OBJ(nativeRowPtr)->get<bool>(ColKey(columnKey)));\n}\n\nJNIEXPORT jfloat JNICALL Java_io_realm_internal_UncheckedRow_nativeGetFloat(JNIEnv* env, jobject, jlong nativeRowPtr,\n                                                                            jlong columnKey)\n{\n    if (!ROW_VALID(env, OBJ(nativeRowPtr))) {\n        return 0;\n    }\n\n    return OBJ(nativeRowPtr)->get<float>(ColKey(columnKey));\n}\n\nJNIEXPORT jdouble JNICALL Java_io_realm_internal_UncheckedRow_nativeGetDouble(JNIEnv* env, jobject,\n                                                                              jlong nativeRowPtr, jlong columnKey)\n{\n    if (!ROW_VALID(env, OBJ(nativeRowPtr))) {\n        return 0;\n    }\n\n    return OBJ(nativeRowPtr)->get<double>(ColKey(columnKey));\n}\n\nJNIEXPORT jlong JNICALL Java_io_realm_internal_UncheckedRow_nativeGetTimestamp(JNIEnv* env, jobject,\n                                                                               jlong nativeRowPtr, jlong columnKey)\n{\n    if (!ROW_VALID(env, OBJ(nativeRowPtr))) {\n        return 0;\n    }\n\n    return to_milliseconds(OBJ(nativeRowPtr)->get<Timestamp>(ColKey(columnKey)));\n}\n\nJNIEXPORT jstring JNICALL Java_io_realm_internal_UncheckedRow_nativeGetString(JNIEnv* env, jobject,\n                                                                              jlong nativeRowPtr, jlong columnKey)\n{\n    if (!ROW_VALID(env, OBJ(nativeRowPtr))) {\n        return nullptr;\n    }\n\n    try {\n        StringData value = OBJ(nativeRowPtr)->get<StringData>(ColKey(columnKey));\n        return to_jstring(env, value);\n    }\n    CATCH_STD()\n    return nullptr;\n}\n\nJNIEXPORT jbyteArray JNICALL Java_io_realm_internal_UncheckedRow_nativeGetByteArray(JNIEnv* env, jobject,\n                                                                                    jlong nativeRowPtr,\n                                                                                    jlong columnKey)\n{\n    if (!ROW_VALID(env, OBJ(nativeRowPtr))) {\n        return nullptr;\n    }\n\n    try {\n        BinaryData bin = OBJ(nativeRowPtr)->get<BinaryData>(ColKey(columnKey));\n        return JavaClassGlobalDef::new_byte_array(env, bin);\n    }\n    CATCH_STD()\n    return nullptr;\n}\n\nJNIEXPORT jlong JNICALL Java_io_realm_internal_UncheckedRow_nativeGetLink(JNIEnv* env, jobject, jlong nativeRowPtr,\n                                                                          jlong columnKey)\n{\n    if (!ROW_VALID(env, OBJ(nativeRowPtr))) {\n        return 0;\n    }\n\n    ColKey col_key(columnKey);\n    if (OBJ(nativeRowPtr)->is_null(col_key)) {\n        return jlong(-1);\n    }\n\n    return static_cast<jlong>(OBJ(nativeRowPtr)->get<ObjKey>(col_key).value);\n}\n\nJNIEXPORT jboolean JNICALL Java_io_realm_internal_UncheckedRow_nativeIsNullLink(JNIEnv* env, jobject,\n                                                                                jlong nativeRowPtr, jlong columnKey)\n{\n    if (!ROW_VALID(env, OBJ(nativeRowPtr))) {\n        return 0;\n    }\n\n    return to_jbool(OBJ(nativeRowPtr)->is_null(ColKey(columnKey)));\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_UncheckedRow_nativeSetLong(JNIEnv* env, jobject, jlong nativeRowPtr,\n                                                                         jlong columnKey, jlong value)\n{\n    if (!ROW_VALID(env, OBJ(nativeRowPtr))) {\n        return;\n    }\n\n    try {\n        OBJ(nativeRowPtr)->set<int64_t>(ColKey(columnKey), value);\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_UncheckedRow_nativeSetRealmAny(JNIEnv* env, jobject, jlong nativeRowPtr,\n                                                                              jlong columnKey, jlong nativePtr)\n{\n    if (!ROW_VALID(env, OBJ(nativeRowPtr))) {\n        return;\n    }\n\n    try {\n        auto java_value = *reinterpret_cast<JavaValue *>(nativePtr);\n        auto mixed = java_value.to_mixed();\n        OBJ(nativeRowPtr)->set<Mixed>(ColKey(columnKey), mixed);\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_UncheckedRow_nativeSetBoolean(JNIEnv* env, jobject, jlong nativeRowPtr,\n                                                                            jlong columnKey, jboolean value)\n{\n    if (!ROW_VALID(env, OBJ(nativeRowPtr))) {\n        return;\n    }\n\n    try {\n        OBJ(nativeRowPtr)->set(ColKey(columnKey), (value == JNI_TRUE));\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_UncheckedRow_nativeSetFloat(JNIEnv* env, jobject, jlong nativeRowPtr,\n                                                                          jlong columnKey, jfloat value)\n{\n    if (!ROW_VALID(env, OBJ(nativeRowPtr))) {\n        return;\n    }\n\n    try {\n        OBJ(nativeRowPtr)->set(ColKey(columnKey), value);\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_UncheckedRow_nativeSetDouble(JNIEnv* env, jobject, jlong nativeRowPtr,\n                                                                           jlong columnKey, jdouble value)\n{\n    if (!ROW_VALID(env, OBJ(nativeRowPtr))) {\n        return;\n    }\n\n    try {\n        OBJ(nativeRowPtr)->set(ColKey(columnKey), value);\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_UncheckedRow_nativeSetTimestamp(JNIEnv* env, jobject,\n                                                                              jlong nativeRowPtr, jlong columnKey,\n                                                                              jlong value)\n{\n    if (!ROW_VALID(env, OBJ(nativeRowPtr))) {\n        return;\n    }\n\n    try {\n        OBJ(nativeRowPtr)->set(ColKey(columnKey), from_milliseconds(value));\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_UncheckedRow_nativeSetString(JNIEnv* env, jobject, jlong nativeRowPtr,\n                                                                           jlong columnKey, jstring value)\n{\n    if (!ROW_VALID(env, OBJ(nativeRowPtr))) {\n        return;\n    }\n\n    try {\n        ColKey col_key(columnKey);\n        if ((value == nullptr) && !col_key.get_attrs().test(col_attr_Nullable)) {\n            ThrowNullValueException(env, OBJ(nativeRowPtr)->get_table(), ColKey(columnKey));\n            return;\n        }\n        JStringAccessor value2(env, value); // throws\n        OBJ(nativeRowPtr)->set(col_key, StringData(value2));\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_UncheckedRow_nativeSetByteArray(JNIEnv* env, jobject,\n                                                                              jlong nativeRowPtr, jlong columnKey,\n                                                                              jbyteArray value)\n{\n    if (!ROW_VALID(env, OBJ(nativeRowPtr))) {\n        return;\n    }\n\n    try {\n        auto& obj = *reinterpret_cast<realm::Obj*>(nativeRowPtr);\n        ColKey col_key(columnKey);\n        if ((value == nullptr) && !col_key.get_attrs().test(col_attr_Nullable)) {\n            ThrowNullValueException(env, OBJ(nativeRowPtr)->get_table(), ColKey(columnKey));\n            return;\n        }\n\n        JByteArrayAccessor jarray_accessor(env, value);\n        obj.set(col_key, jarray_accessor.transform<BinaryData>());\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_UncheckedRow_nativeSetLink(JNIEnv* env, jobject, jlong nativeRowPtr,\n                                                                         jlong columnKey, jlong valueObjKey)\n{\n    if (!ROW_VALID(env, OBJ(nativeRowPtr))) {\n        return;\n    }\n\n    try {\n        OBJ(nativeRowPtr)->set(ColKey(columnKey), ObjKey(valueObjKey));\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_UncheckedRow_nativeNullifyLink(JNIEnv* env, jobject, jlong nativeRowPtr,\n                                                                             jlong columnKey)\n{\n    if (!ROW_VALID(env, OBJ(nativeRowPtr))) {\n        return;\n    }\n\n    try {\n        OBJ(nativeRowPtr)->set_null(ColKey(columnKey));\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT jboolean JNICALL Java_io_realm_internal_UncheckedRow_nativeIsValid(JNIEnv*, jobject, jlong nativeRowPtr)\n{\n    return to_jbool(OBJ(nativeRowPtr)->is_valid());\n}\n\nJNIEXPORT jboolean JNICALL Java_io_realm_internal_UncheckedRow_nativeHasColumn(JNIEnv* env, jobject obj,\n                                                                               jlong nativeRowPtr, jstring columnName)\n{\n    ColKey col_key (Java_io_realm_internal_UncheckedRow_nativeGetColumnKey(env, obj, nativeRowPtr, columnName));\n    return to_jbool(bool(col_key));\n}\n\nJNIEXPORT jboolean JNICALL Java_io_realm_internal_UncheckedRow_nativeIsNull(JNIEnv* env, jobject, jlong nativeRowPtr,\n                                                                            jlong columnKey)\n{\n    if (!ROW_VALID(env, OBJ(nativeRowPtr))) {\n        return JNI_FALSE;\n    }\n\n    try {\n        bool is_bool = to_jbool(OBJ(nativeRowPtr)->is_null(ColKey(columnKey)));\n        return is_bool;\n    }\n    CATCH_STD()\n    return JNI_FALSE;\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_UncheckedRow_nativeSetNull(JNIEnv* env, jobject, jlong nativeRowPtr,\n                                                                         jlong columnKey)\n{\n    if (!ROW_VALID(env, OBJ(nativeRowPtr))) {\n        return;\n    }\n    if (!COL_NULLABLE(env, OBJ(nativeRowPtr)->get_table(), columnKey)) {\n        return;\n    }\n    try {\n        OBJ(nativeRowPtr)->set_null(ColKey(columnKey));\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT jlong JNICALL Java_io_realm_internal_UncheckedRow_nativeFreeze(JNIEnv* env, jobject, jlong j_native_row_ptr,\n                                                                         jlong j_frozen_realm_native_ptr)\n{\n    try {\n        Obj* obj = reinterpret_cast<Obj*>(j_native_row_ptr);\n        auto frozen_realm = *(reinterpret_cast<SharedRealm*>(j_frozen_realm_native_ptr));\n        auto frozen_obj = new Obj(frozen_realm->import_copy_of(*obj));\n        return reinterpret_cast<jlong>(frozen_obj);\n    }\n    CATCH_STD()\n    return reinterpret_cast<jlong>(nullptr);\n}\n\n\nstatic void finalize_unchecked_row(jlong ptr)\n{\n    delete OBJ(ptr);\n}\n\nJNIEXPORT jlong JNICALL Java_io_realm_internal_UncheckedRow_nativeGetFinalizerPtr(JNIEnv*, jclass)\n{\n    return reinterpret_cast<jlong>(&finalize_unchecked_row);\n}\n\nJNIEXPORT jlongArray JNICALL Java_io_realm_internal_UncheckedRow_nativeGetDecimal128(JNIEnv* env, jobject,\n                                                                                    jlong nativeRowPtr,\n                                                                                    jlong columnKey)\n{\n    if (!ROW_VALID(env, OBJ(nativeRowPtr))) {\n        return nullptr;\n    }\n\n    try {\n        Decimal128 decimal128 = OBJ(nativeRowPtr)->get<Decimal128>(ColKey(columnKey));\n        RETURN_DECIMAL128_AS_JLONG_ARRAY__OR_NULL(decimal128)\n    }\n    CATCH_STD()\n    return nullptr;\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_UncheckedRow_nativeSetDecimal128(JNIEnv* env, jobject,\n                                                                              jlong nativeRowPtr, jlong columnKey,\n                                                                              jlong low, jlong high)\n{\n    if (!ROW_VALID(env, OBJ(nativeRowPtr))) {\n        return;\n    }\n\n    try {\n        ColKey col_key(columnKey);\n        Decimal128::Bid128 raw {static_cast<uint64_t>(low), static_cast<uint64_t>(high)};\n        OBJ(nativeRowPtr)->set(col_key, Decimal128(raw));\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT jstring JNICALL Java_io_realm_internal_UncheckedRow_nativeGetObjectId(JNIEnv* env, jobject,\n                                                                                jlong nativeRowPtr,\n                                                                                jlong columnKey)\n{\n    if (!ROW_VALID(env, OBJ(nativeRowPtr))) {\n        return nullptr;\n    }\n\n    try {\n        ObjectId objectId = OBJ(nativeRowPtr)->get<ObjectId>(ColKey(columnKey));\n        return to_jstring(env, objectId.to_string().data());\n    }\n    CATCH_STD()\n    return nullptr;\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_UncheckedRow_nativeSetObjectId(JNIEnv* env, jobject,\n                                                                              jlong nativeRowPtr, jlong columnKey,\n                                                                              jstring j_value)\n{\n    if (!ROW_VALID(env, OBJ(nativeRowPtr))) {\n        return;\n    }\n\n    try {\n        JStringAccessor value(env, j_value);\n        OBJ(nativeRowPtr)->set(ColKey(columnKey), ObjectId(StringData(value).data()));\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT jstring JNICALL Java_io_realm_internal_UncheckedRow_nativeGetUUID(JNIEnv* env, jobject,\n                                                                            jlong nativeRowPtr,\n                                                                            jlong columnKey)\n{\n    if (!ROW_VALID(env, OBJ(nativeRowPtr))) {\n        return nullptr;\n    }\n\n    try {\n        UUID uuid = OBJ(nativeRowPtr)->get<UUID>(ColKey(columnKey));\n        return to_jstring(env, uuid.to_string().data());\n    }\n    CATCH_STD()\n    return nullptr;\n}\n\nJNIEXPORT jlong JNICALL Java_io_realm_internal_UncheckedRow_nativeGetRealmAny(JNIEnv* env, jobject,\n                                                                            jlong nativeRowPtr,\n                                                                            jlong columnKey)\n{\n    if (!ROW_VALID(env, OBJ(nativeRowPtr))) {\n        return reinterpret_cast<jlong>(nullptr);\n    }\n\n    try {\n        auto mixed = OBJ(nativeRowPtr)->get<Mixed>(ColKey(columnKey));\n        return reinterpret_cast<jlong>(new JavaValue(from_mixed(mixed)));\n    }\n    CATCH_STD()\n    return reinterpret_cast<jlong>(nullptr);\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_UncheckedRow_nativeSetUUID(JNIEnv* env, jobject,\n                                                                             jlong nativeRowPtr, jlong columnKey,\n                                                                             jstring j_value)\n{\n    if (!ROW_VALID(env, OBJ(nativeRowPtr))) {\n        return;\n    }\n\n    try {\n        JStringAccessor value(env, j_value);\n        OBJ(nativeRowPtr)->set(ColKey(columnKey), UUID(StringData(value).data()));\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT jlong JNICALL Java_io_realm_internal_UncheckedRow_nativeCreateEmbeddedObject(JNIEnv* env, jobject,\n                                                                                       jlong j_obj_ptr,\n                                                                                       jlong j_column_key)\n{\n    if (!ROW_VALID(env, OBJ(j_obj_ptr))) {\n        return -1;\n    }\n    try {\n        Obj embedded_object = OBJ(j_obj_ptr)->create_and_set_linked_object(ColKey(j_column_key));\n        return reinterpret_cast<jlong>(embedded_object.get_key().value);\n    }\n    CATCH_STD()\n    return -1;\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/cpp/io_realm_internal_Util.cpp",
    "content": "/*\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#include <jni.h>\n\n#include \"jni_util/jni_utils.hpp\"\n#include \"jni_util/hack.hpp\"\n#include \"java_class_global_def.hpp\"\n\n#include <realm/string_data.hpp>\n#include <realm/unicode.hpp>\n\n#include \"util.hpp\"\n\nusing std::string;\nusing namespace realm::jni_util;\nusing namespace realm::_impl;\n\n//#define USE_VLD\n#if defined(_MSC_VER) && defined(_DEBUG) && defined(USE_VLD)\n#include \"C:\\\\Program Files (x86)\\\\Visual Leak Detector\\\\include\\\\vld.h\"\n#endif\n\nconst string TABLE_PREFIX(\"class_\");\n\n\nJNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void*)\n{\n    // Workaround for some known bugs in system calls on specific devices.\n    hack_init();\n\n    JNIEnv* env;\n    if (vm->GetEnv((void**)&env, JNI_VERSION_1_6) != JNI_OK) {\n        return JNI_ERR;\n    }\n    else {\n        JniUtils::initialize(vm, JNI_VERSION_1_6);\n        JavaClassGlobalDef::initialize(env);\n    }\n\n    return JNI_VERSION_1_6;\n}\n\nJNIEXPORT void JNI_OnUnload(JavaVM* vm, void*)\n{\n    JNIEnv* env;\n    if (vm->GetEnv((void**)&env, JNI_VERSION_1_6) != JNI_OK) {\n        return;\n    }\n    else {\n        JavaClassGlobalDef::release();\n        JniUtils::release();\n    }\n}\n\nJNIEXPORT jstring JNICALL Java_io_realm_internal_Util_nativeGetTablePrefix(JNIEnv* env, jclass)\n{\n    realm::StringData sd(TABLE_PREFIX);\n    return to_jstring(env, sd);\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/cpp/io_realm_internal_core_NativeRealmAny.cpp",
    "content": "/*\n * Copyright 2020 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#include \"io_realm_internal_core_NativeRealmAny.h\"\n\n#include \"java_accessor.hpp\"\n#include \"java_object_accessor.hpp\"\n\nusing namespace std;\nusing namespace realm;\nusing namespace realm::_impl;\n\nstatic void finalize_mixed(jlong ptr) {\n    delete reinterpret_cast<JavaValue *>(ptr);\n}\n\nJNIEXPORT jlong JNICALL\nJava_io_realm_internal_core_NativeRealmAny_nativeGetFinalizerPtr(JNIEnv *, jclass) {\n    return reinterpret_cast<jlong>(&finalize_mixed);\n}\n\nJNIEXPORT jlong JNICALL\nJava_io_realm_internal_core_NativeRealmAny_nativeCreateNull(JNIEnv *env, jclass) {\n    try {\n        return reinterpret_cast<jlong>(new JavaValue());\n    } CATCH_STD()\n\n    return reinterpret_cast<jlong>(nullptr);\n}\n\nJNIEXPORT jlong JNICALL\nJava_io_realm_internal_core_NativeRealmAny_nativeCreateBoolean(JNIEnv *env, jclass, jboolean j_value) {\n    try {\n        return reinterpret_cast<jlong>(new JavaValue(j_value));\n    } CATCH_STD()\n\n    return reinterpret_cast<jlong>(nullptr);\n}\n\nJNIEXPORT jboolean JNICALL\nJava_io_realm_internal_core_NativeRealmAny_nativeAsBoolean(JNIEnv *env, jclass, jlong native_ptr) {\n    try {\n        auto java_value = *reinterpret_cast<JavaValue *>(native_ptr);\n        return java_value.get_boolean();\n    } CATCH_STD()\n\n    return 0;\n}\n\nJNIEXPORT jlong JNICALL\nJava_io_realm_internal_core_NativeRealmAny_nativeCreateLong(JNIEnv *env, jclass, jlong j_value) {\n    try {\n        return reinterpret_cast<jlong>(new JavaValue(j_value));\n    } CATCH_STD()\n\n    return reinterpret_cast<jlong>(nullptr);\n}\n\nJNIEXPORT jlong JNICALL\nJava_io_realm_internal_core_NativeRealmAny_nativeAsLong(JNIEnv *env, jclass, jlong native_ptr) {\n    try {\n        auto java_value = *reinterpret_cast<JavaValue *>(native_ptr);\n        return java_value.get_int();\n    } CATCH_STD()\n\n    return 0;\n}\n\nJNIEXPORT jlong JNICALL\nJava_io_realm_internal_core_NativeRealmAny_nativeCreateFloat(JNIEnv *env, jclass, jfloat j_value) {\n    try {\n        return reinterpret_cast<jlong>(new JavaValue(j_value));\n    } CATCH_STD()\n\n    return reinterpret_cast<jlong>(nullptr);\n}\n\nJNIEXPORT jfloat JNICALL\nJava_io_realm_internal_core_NativeRealmAny_nativeAsFloat(JNIEnv *env, jclass, jlong native_ptr) {\n    try {\n        auto java_value = *reinterpret_cast<JavaValue *>(native_ptr);\n        return java_value.get_float();\n    } CATCH_STD()\n\n    return 0;\n}\n\nJNIEXPORT jlong JNICALL\nJava_io_realm_internal_core_NativeRealmAny_nativeCreateDouble(JNIEnv *env, jclass, jdouble j_value) {\n    try {\n        return reinterpret_cast<jlong>(new JavaValue(j_value));\n    } CATCH_STD()\n\n    return reinterpret_cast<jlong>(nullptr);\n}\n\nJNIEXPORT jdouble JNICALL\nJava_io_realm_internal_core_NativeRealmAny_nativeAsDouble(JNIEnv *env, jclass, jlong native_ptr) {\n    try {\n        auto java_value = *reinterpret_cast<JavaValue *>(native_ptr);\n        return java_value.get_double();\n    } CATCH_STD()\n\n    return 0;\n}\n\nJNIEXPORT jlong JNICALL\nJava_io_realm_internal_core_NativeRealmAny_nativeCreateString(JNIEnv *env, jclass, jstring j_value) {\n    try {\n        JStringAccessor string_accessor(env, j_value); // throws\n        return reinterpret_cast<jlong>(new JavaValue(std::string(string_accessor)));\n    } CATCH_STD()\n\n    return reinterpret_cast<jlong>(nullptr);\n}\n\nJNIEXPORT jstring JNICALL\nJava_io_realm_internal_core_NativeRealmAny_nativeAsString(JNIEnv *env, jclass, jlong native_ptr) {\n    try {\n        auto java_value = *reinterpret_cast<JavaValue *>(native_ptr);\n        return to_jstring(env, java_value.get_string());\n    } CATCH_STD()\n\n    return nullptr;\n}\n\nJNIEXPORT jlong JNICALL\nJava_io_realm_internal_core_NativeRealmAny_nativeCreateBinary(JNIEnv *env, jclass, jbyteArray j_value) {\n    try {\n        JByteArrayAccessor array_accessor(env, j_value); // throws\n        auto data = OwnedBinaryData(JByteArrayAccessor(env, j_value).transform<BinaryData>());\n        return reinterpret_cast<jlong>(new JavaValue(data));\n    } CATCH_STD()\n\n    return reinterpret_cast<jlong>(nullptr);\n}\n\nJNIEXPORT jbyteArray JNICALL\nJava_io_realm_internal_core_NativeRealmAny_nativeAsBinary(JNIEnv *env, jclass, jlong native_ptr) {\n    try {\n        auto java_value = *reinterpret_cast<JavaValue *>(native_ptr);\n        return JavaClassGlobalDef::new_byte_array(env, java_value.get_binary().get());\n    } CATCH_STD()\n\n    return nullptr;\n}\n\nJNIEXPORT jlong JNICALL\nJava_io_realm_internal_core_NativeRealmAny_nativeCreateDate(JNIEnv *env, jclass, jlong j_value) {\n    try {\n        return reinterpret_cast<jlong>(new JavaValue(from_milliseconds(j_value)));\n    } CATCH_STD()\n\n    return reinterpret_cast<jlong>(nullptr);\n}\n\nJNIEXPORT jlong JNICALL\nJava_io_realm_internal_core_NativeRealmAny_nativeAsDate(JNIEnv *env, jclass, jlong native_ptr) {\n    try {\n        auto java_value = *reinterpret_cast<JavaValue *>(native_ptr);\n        return to_milliseconds(java_value.get_date());\n    } CATCH_STD()\n\n    return 0;\n}\n\nJNIEXPORT jlong JNICALL\nJava_io_realm_internal_core_NativeRealmAny_nativeCreateObjectId(JNIEnv *env, jclass, jstring j_value) {\n    try {\n        JStringAccessor string_accessor(env, j_value); // throws\n        return reinterpret_cast<jlong>(new JavaValue(ObjectId(StringData(string_accessor).data())));\n    } CATCH_STD()\n\n    return reinterpret_cast<jlong>(nullptr);\n}\n\nJNIEXPORT jstring JNICALL\nJava_io_realm_internal_core_NativeRealmAny_nativeAsObjectId(JNIEnv *env, jclass, jlong native_ptr) {\n    try {\n        auto java_value = *reinterpret_cast<JavaValue *>(native_ptr);\n        return to_jstring(env, java_value.get_object_id().to_string().data());\n    } CATCH_STD()\n\n    return nullptr;\n}\n\nJNIEXPORT jlong JNICALL\nJava_io_realm_internal_core_NativeRealmAny_nativeCreateDecimal128(JNIEnv *env, jclass, jlong j_low, jlong j_high) {\n    try {\n        Decimal128::Bid128 raw{static_cast<uint64_t>(j_low), static_cast<uint64_t>(j_high)};\n        return reinterpret_cast<jlong>(new JavaValue(Decimal128(raw)));\n    } CATCH_STD()\n\n    return reinterpret_cast<jlong>(nullptr);\n}\n\nJNIEXPORT jlongArray JNICALL\nJava_io_realm_internal_core_NativeRealmAny_nativeAsDecimal128(JNIEnv *env, jclass, jlong native_ptr) {\n    try {\n        auto java_value = *reinterpret_cast<JavaValue *>(native_ptr);\n        Decimal128 decimal128 = java_value.get_decimal128();\n        RETURN_DECIMAL128_AS_JLONG_ARRAY__OR_NULL(decimal128)\n    } CATCH_STD()\n\n    return nullptr;\n}\n\nJNIEXPORT jlong JNICALL\nJava_io_realm_internal_core_NativeRealmAny_nativeCreateUUID(JNIEnv *env, jclass, jstring j_value) {\n    try {\n        JStringAccessor string_accessor(env, j_value); // throws\n        return reinterpret_cast<jlong>(new JavaValue(UUID(StringData(string_accessor).data())));\n    } CATCH_STD()\n\n    return reinterpret_cast<jlong>(nullptr);\n}\n\nJNIEXPORT jstring JNICALL\nJava_io_realm_internal_core_NativeRealmAny_nativeAsUUID(JNIEnv *env, jclass, jlong native_ptr) {\n    try {\n        auto java_value = *reinterpret_cast<JavaValue *>(native_ptr);\n        return to_jstring(env, java_value.get_uuid().to_string().data());\n    } CATCH_STD()\n\n    return nullptr;\n}\n\nJNIEXPORT jlong JNICALL\nJava_io_realm_internal_core_NativeRealmAny_nativeCreateLink(JNIEnv *env, jclass, jlong target_table_ref,\n                                                              jlong target_object_key) {\n    try {\n        TableRef target_table = TBL_REF(target_table_ref);\n        ObjKey object_key(target_object_key);\n        ObjLink object_link(target_table->get_key(), object_key);\n\n        return reinterpret_cast<jlong>(new JavaValue(object_link));\n    } CATCH_STD()\n\n    return reinterpret_cast<jlong>(nullptr);\n}\n\nJNIEXPORT jint JNICALL\nJava_io_realm_internal_core_NativeRealmAny_nativeGetType(JNIEnv *env, jclass, jlong native_ptr) {\n    try {\n        auto java_value = *reinterpret_cast<JavaValue *>(native_ptr);\n        auto mixed = java_value.to_mixed();\n\n        return mixed.is_null() ? -1 : int(mixed.get_type());\n    } CATCH_STD()\n\n    return -1;\n}\n\nJNIEXPORT jstring JNICALL\nJava_io_realm_internal_core_NativeRealmAny_nativeGetRealmModelTableName(JNIEnv *env, jclass, jlong native_ptr,\n                                                                     jlong shared_realm_ptr) {\n    try {\n        auto java_value = *reinterpret_cast<JavaValue *>(native_ptr);\n        auto &shared_realm = *(reinterpret_cast<SharedRealm *>(shared_realm_ptr));\n\n        if (java_value.get_type() == JavaValueType::ObjectLink) {\n            auto &obj_link = java_value.get_object_link();\n            return to_jstring(env, shared_realm->read_group().get_table(obj_link.get_table_key())->get_name());\n        } else {\n            auto &obj = java_value.get_object();\n            return to_jstring(env, obj->get_table()->get_name());\n        }\n    } CATCH_STD()\n\n    return nullptr;\n}\n\nJNIEXPORT jlong JNICALL\nJava_io_realm_internal_core_NativeRealmAny_nativeGetRealmModelRowKey(JNIEnv *env, jclass, jlong native_ptr) {\n    try {\n        auto java_value = *reinterpret_cast<JavaValue *>(native_ptr);\n\n        if (java_value.get_type() == JavaValueType::ObjectLink) {\n            auto obj_link = java_value.get_object_link();\n            return obj_link.get_obj_key().value;\n        } else {\n            auto &obj = java_value.get_object();\n            return obj->get_key().value;\n        }\n\n    } CATCH_STD()\n\n    return 0;\n}\n\nJNIEXPORT jboolean JNICALL\nJava_io_realm_internal_core_NativeRealmAny_nativeEquals(JNIEnv *env, jclass, jlong native_ptr, jlong native_other_ptr) {\n    try {\n        auto java_value = *reinterpret_cast<JavaValue *>(native_ptr);\n        auto other_java_value = *reinterpret_cast<JavaValue *>(native_other_ptr);\n\n        auto mixed = java_value.to_mixed();\n        auto other_mixed = other_java_value.to_mixed();\n\n        return mixed.compare(other_mixed) == 0;\n    } CATCH_STD()\n\n    return false;\n}\n\n"
  },
  {
    "path": "realm/realm-library/src/main/cpp/io_realm_internal_core_NativeRealmAnyCollection.cpp",
    "content": "/*\n * Copyright 2021 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#include \"io_realm_internal_core_NativeRealmAnyCollection.h\"\n\n#include \"java_accessor.hpp\"\n#include \"java_object_accessor.hpp\"\n#include \"util.hpp\"\n\nusing namespace std;\nusing namespace realm;\nusing namespace realm::_impl;\n\nstatic void finalize_collection(jlong ptr) {\n    delete reinterpret_cast<std::vector<JavaValue> *>(ptr);\n}\n\nJNIEXPORT jlong JNICALL\nJava_io_realm_internal_core_NativeRealmAnyCollection_nativeGetFinalizerPtr(JNIEnv *, jclass) {\n    return reinterpret_cast<jlong>(&finalize_collection);\n}\n\nJNIEXPORT jlong JNICALL\nJava_io_realm_internal_core_NativeRealmAnyCollection_nativeCreateBooleanCollection(JNIEnv *env, jclass,\n                                                                                jbooleanArray j_boolean_array,\n                                                                                jbooleanArray j_not_null) {\n    try {\n        // TODO: could be worth templating this logic here and in the methods below\n        //  https://github.com/realm/realm-java/issues/7384\n        JBooleanArrayAccessor values(env, j_boolean_array);\n        JBooleanArrayAccessor not_null(env, j_not_null);\n        auto collection = new std::vector<JavaValue>();\n        for (int i = 0; i < values.size(); i++) {\n            if (not_null[i]) {\n                collection->push_back(JavaValue(values[i]));\n            } else {\n                collection->push_back(JavaValue());\n            }\n        }\n        return reinterpret_cast<jlong>(collection);\n    } CATCH_STD()\n\n    return reinterpret_cast<jlong>(nullptr);\n}\n\nJNIEXPORT jlong JNICALL\nJava_io_realm_internal_core_NativeRealmAnyCollection_nativeCreateIntegerCollection(JNIEnv *env, jclass,\n                                                                                jlongArray j_long_array,\n                                                                                jbooleanArray j_not_null) {\n    try {\n        JLongArrayAccessor values(env, j_long_array);\n        JBooleanArrayAccessor not_null(env, j_not_null);\n        auto collection = new std::vector<JavaValue>();\n        for (int i = 0; i < values.size(); i++) {\n            if (not_null[i]) {\n                collection->push_back(JavaValue(values[i]));\n            } else {\n                collection->push_back(JavaValue());\n            }\n        }\n        return reinterpret_cast<jlong>(collection);\n    } CATCH_STD()\n\n    return reinterpret_cast<jlong>(nullptr);\n}\n\nJNIEXPORT jlong JNICALL\nJava_io_realm_internal_core_NativeRealmAnyCollection_nativeCreateFloatCollection(JNIEnv *env, jclass,\n                                                                              jfloatArray j_float_array,\n                                                                              jbooleanArray j_not_null) {\n    try {\n        JFloatArrayAccessor values(env, j_float_array);\n        JBooleanArrayAccessor not_null(env, j_not_null);\n        auto collection = new std::vector<JavaValue>();\n        for (int i = 0; i < values.size(); i++) {\n            if (not_null[i]) {\n                collection->push_back(JavaValue(values[i]));\n            } else {\n                collection->push_back(JavaValue());\n            }\n        }\n        return reinterpret_cast<jlong>(collection);\n    } CATCH_STD()\n\n    return reinterpret_cast<jlong>(nullptr);\n}\n\nJNIEXPORT jlong JNICALL\nJava_io_realm_internal_core_NativeRealmAnyCollection_nativeCreateDoubleCollection(JNIEnv *env, jclass,\n                                                                               jdoubleArray j_double_arrray,\n                                                                               jbooleanArray j_not_null) {\n    try {\n        JDoubleArrayAccessor values(env, j_double_arrray);\n        JBooleanArrayAccessor not_null(env, j_not_null);\n        auto collection = new std::vector<JavaValue>();\n        for (int i = 0; i < values.size(); i++) {\n            if (not_null[i]) {\n                collection->push_back(JavaValue(values[i]));\n            } else {\n                collection->push_back(JavaValue());\n            }\n        }\n        return reinterpret_cast<jlong>(collection);\n    } CATCH_STD()\n\n    return reinterpret_cast<jlong>(nullptr);\n}\n\nJNIEXPORT jlong JNICALL\nJava_io_realm_internal_core_NativeRealmAnyCollection_nativeCreateStringCollection(JNIEnv *env, jclass,\n                                                                               jobjectArray j_string_array,\n                                                                               jbooleanArray j_not_null) {\n    try {\n        JObjectArrayAccessor<JStringAccessor, jstring> values(env, j_string_array);\n        JBooleanArrayAccessor not_null(env, j_not_null);\n        auto collection = new std::vector<JavaValue>();\n        for (int i = 0; i < values.size(); i++) {\n            if (not_null[i]) {\n                collection->push_back(JavaValue(StringData(values[i])));\n            } else {\n                collection->push_back(JavaValue());\n            }\n        }\n        return reinterpret_cast<jlong>(collection);\n    } CATCH_STD()\n\n    return reinterpret_cast<jlong>(nullptr);\n}\n\nJNIEXPORT jlong JNICALL\nJava_io_realm_internal_core_NativeRealmAnyCollection_nativeCreateBinaryCollection(JNIEnv *env, jclass,\n                                                                               jobjectArray j_binary_array,\n                                                                               jbooleanArray j_not_null) {\n    try {\n        JObjectArrayAccessor<JByteArrayAccessor, jbyteArray> values(env, j_binary_array);\n        JBooleanArrayAccessor not_null(env, j_not_null);\n        auto collection = new std::vector<JavaValue>();\n        for (int i = 0; i < values.size(); i++) {\n            if (not_null[i]) {\n                collection->push_back(JavaValue(OwnedBinaryData(values[i].transform<BinaryData>())));\n            } else {\n                collection->push_back(JavaValue());\n            }\n        }\n        return reinterpret_cast<jlong>(collection);\n    } CATCH_STD()\n\n    return reinterpret_cast<jlong>(nullptr);\n}\n\nJNIEXPORT jlong JNICALL\nJava_io_realm_internal_core_NativeRealmAnyCollection_nativeCreateDateCollection(JNIEnv *env, jclass,\n                                                                             jlongArray j_date_array,\n                                                                             jbooleanArray j_not_null) {\n    try {\n        JLongArrayAccessor values(env, j_date_array);\n        JBooleanArrayAccessor not_null(env, j_not_null);\n        auto collection = new std::vector<JavaValue>();\n        for (int i = 0; i < values.size(); i++) {\n            if (not_null[i]) {\n                collection->push_back(JavaValue(from_milliseconds(values[i])));\n            } else {\n                collection->push_back(JavaValue());\n            }\n        }\n        return reinterpret_cast<jlong>(collection);\n    } CATCH_STD()\n\n    return reinterpret_cast<jlong>(nullptr);\n}\n\nJNIEXPORT jlong JNICALL\nJava_io_realm_internal_core_NativeRealmAnyCollection_nativeCreateObjectIdCollection(JNIEnv *env, jclass,\n                                                                                 jobjectArray j_object_id_array,\n                                                                                 jbooleanArray j_not_null) {\n    try {\n        JObjectArrayAccessor<JStringAccessor, jstring> values(env, j_object_id_array);\n        JBooleanArrayAccessor not_null(env, j_not_null);\n        auto collection = new std::vector<JavaValue>();\n        for (int i = 0; i < values.size(); i++) {\n            if (not_null[i]) {\n                collection->push_back(JavaValue(ObjectId(StringData(values[i]).data())));\n            } else {\n                collection->push_back(JavaValue());\n            }\n        }\n        return reinterpret_cast<jlong>(collection);\n    } CATCH_STD()\n\n    return reinterpret_cast<jlong>(nullptr);\n}\n\nJNIEXPORT jlong JNICALL\nJava_io_realm_internal_core_NativeRealmAnyCollection_nativeCreateDecimal128Collection(JNIEnv *env, jclass,\n                                                                                   jlongArray j_low_array,\n                                                                                   jlongArray j_high_array,\n                                                                                   jbooleanArray j_not_null) {\n    try {\n        JLongArrayAccessor low_values(env, j_low_array);\n        JLongArrayAccessor high_values(env, j_high_array);\n        JBooleanArrayAccessor not_null(env, j_not_null);\n\n        auto collection = new std::vector<JavaValue>();\n        for (int i = 0; i < low_values.size(); i++) {\n            if (not_null[i]) {\n                Decimal128::Bid128 raw{static_cast<uint64_t>(low_values[i]), static_cast<uint64_t>(high_values[i])};\n                collection->push_back(JavaValue(Decimal128(raw)));\n            } else {\n                collection->push_back(JavaValue());\n            }\n        }\n        return reinterpret_cast<jlong>(collection);\n    } CATCH_STD()\n\n    return reinterpret_cast<jlong>(nullptr);\n}\n\nJNIEXPORT jlong JNICALL\nJava_io_realm_internal_core_NativeRealmAnyCollection_nativeCreateUUIDCollection(JNIEnv *env, jclass,\n                                                                             jobjectArray j_uuid_array,\n                                                                             jbooleanArray j_not_null) {\n    try {\n        JObjectArrayAccessor<JStringAccessor, jstring> values(env, j_uuid_array);\n        JBooleanArrayAccessor not_null(env, j_not_null);\n        auto collection = new std::vector<JavaValue>();\n        for (int i = 0; i < values.size(); i++) {\n            if (not_null[i]) {\n                collection->push_back(JavaValue(UUID(StringData(values[i]).data())));\n            } else {\n                collection->push_back(JavaValue());\n            }\n        }\n        return reinterpret_cast<jlong>(collection);\n    } CATCH_STD()\n\n    return reinterpret_cast<jlong>(nullptr);\n}\n\nJNIEXPORT jlong JNICALL\nJava_io_realm_internal_core_NativeRealmAnyCollection_nativeCreateObjectCollection(JNIEnv *env, jclass,\n                                                                               jlongArray j_object_array,\n                                                                               jbooleanArray j_not_null) {\n    try {\n        JLongArrayAccessor values(env, j_object_array);\n        JBooleanArrayAccessor not_null(env, j_not_null);\n        auto collection = new std::vector<JavaValue>();\n        for (int i = 0; i < values.size(); i++) {\n            collection->push_back(not_null[i] ?\n                                  JavaValue(reinterpret_cast<Obj *>(values[i])) : from_mixed(Mixed()));\n        }\n        return reinterpret_cast<jlong>(collection);\n    } CATCH_STD()\n\n    return reinterpret_cast<jlong>(nullptr);\n}\n\nJNIEXPORT jlong JNICALL\nJava_io_realm_internal_core_NativeRealmAnyCollection_nativeCreateRealmAnyCollection(JNIEnv *env, jclass,\n                                                                               jlongArray j_mixed_ptrs,\n                                                                               jbooleanArray j_not_null) {\n    try {\n        JLongArrayAccessor values(env, j_mixed_ptrs);\n        JBooleanArrayAccessor not_null(env, j_not_null);\n        auto collection = new std::vector<JavaValue>();\n        for (int i = 0; i < values.size(); i++) {\n            collection->push_back(not_null[i] ?\n                                  JavaValue(reinterpret_cast<JavaValue *>(values[i])) : from_mixed(Mixed()));\n        }\n        return reinterpret_cast<jlong>(collection);\n    } CATCH_STD()\n\n    return reinterpret_cast<jlong>(nullptr);\n}\n\nJNIEXPORT jint JNICALL\nJava_io_realm_internal_core_NativeRealmAnyCollection_nativeGetCollectionSize(JNIEnv *env, jclass,\n                                                                          jlong j_native_ptr) {\n    try {\n        auto &collection = *reinterpret_cast<std::vector<JavaValue> *>(j_native_ptr);\n        return collection.size();\n    } CATCH_STD()\n\n    return 0;\n}\n\nJNIEXPORT jlong JNICALL\nJava_io_realm_internal_core_NativeRealmAnyCollection_nativeGetCollectionItem(JNIEnv *env, jclass,\n                                                                          jlong j_native_ptr,\n                                                                          jint j_index) {\n    try {\n        auto &collection = *reinterpret_cast<std::vector<JavaValue> *>(j_native_ptr);\n        return reinterpret_cast<jlong>(new JavaValue(collection[j_index]));\n    } CATCH_STD()\n\n    return reinterpret_cast<jlong>(nullptr);\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/cpp/io_realm_internal_objectstore_OsApp.cpp",
    "content": "/*\n * Copyright 2020 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#include \"io_realm_internal_objectstore_OsApp.h\"\n\n#include \"java_network_transport.hpp\"\n#include \"util.hpp\"\n#include \"jni_util/java_method.hpp\"\n#include \"jni_util/jni_utils.hpp\"\n\n#include <realm/sync/binding_callback_thread_observer.hpp>\n#include <realm/object-store/sync/app.hpp>\n#include <realm/object-store/sync/sync_manager.hpp>\n\n#include <jni_util/bson_util.hpp>\n\nusing namespace realm;\nusing namespace realm::app;\nusing namespace realm::jni_util;\nusing namespace realm::_impl;\n\nstruct AndroidClientListener : public realm::BindingCallbackThreadObserver {\n    AndroidClientListener(JNIEnv* env)\n            : m_realm_exception_class(env, \"io/realm/exceptions/RealmError\")\n    {\n    }\n\n    void did_create_thread() override\n    {\n        Log::d(\"SyncClient thread created\");\n        // Attach the sync client thread to the JVM so errors can be returned properly\n        JniUtils::get_env(true);\n    }\n\n    void will_destroy_thread() override\n    {\n        // avoid allocating any NewString if we have a pending exception\n        // otherwise a \"JNI called with pending exception\" will be called\n        if (JniUtils::get_env(true)->ExceptionCheck() == JNI_FALSE) {\n            Log::d(\"SyncClient thread destroyed\");\n        }\n\n        // Failing to detach the JVM before closing the thread will crash on ART\n        JniUtils::detach_current_thread();\n    }\n\n    bool handle_error(std::exception const& e) override\n    {\n        JNIEnv* env = JniUtils::get_env(true);\n        std::string msg = util::format(\"An exception has been thrown on the sync client thread:\\n%1\", e.what());\n        Log::f(msg.c_str());\n        // Since user has no way to handle exceptions thrown on the sync client thread, we just convert it to a Java\n        // exception to get more debug information for ourself.\n        // FIXME: We really need to find a universal and clever way to get the native backtrace when exception thrown\n        env->ThrowNew(m_realm_exception_class, msg.c_str());\n\n        return true;\n    }\n\nprivate:\n    // FindClass() doesn't work in the native thread even when the JVM is attached before, due to it\n    // using another ClassLoader. So we get the RealmError class on a normal JVM thread and throw it\n    // later on the sync client thread.\n    JavaClass m_realm_exception_class;\n};\n\nstatic void finalize_client(jlong ptr) {\n    delete reinterpret_cast<App*>(ptr);\n}\n\nJNIEXPORT jlong JNICALL\nJava_io_realm_internal_objectstore_OsApp_nativeGetFinalizerMethodPtr(JNIEnv*, jclass) {\n    return reinterpret_cast<jlong>(&finalize_client);\n}\n\nJNIEXPORT jlong JNICALL Java_io_realm_internal_objectstore_OsApp_nativeCreate(JNIEnv* env, jobject obj,\n                                                               jstring j_app_id,\n                                                               jstring j_base_url,\n                                                               jstring j_app_name,\n                                                               jstring j_app_version,\n                                                               jlong j_request_timeout_ms,\n                                                               jbyteArray j_encryption_key,\n                                                               jstring j_sync_base_dir,\n                                                               jstring j_user_agent_binding_info,\n                                                               jstring j_user_agent_application_info,\n                                                               jstring j_platform,\n                                                               jstring j_platform_version,\n                                                               jstring j_sdk_version,\n                                                               jstring j_cpu_arch,\n                                                               jstring j_device_name,\n                                                               jstring j_device_version,\n                                                               jstring j_framework_name,\n                                                               jstring j_framework_version\n                                                               )\n{\n    try {\n\n        JStringAccessor app_id(env, j_app_id);\n\n        // Check if we already have a cached instance, if yes, return that instead. The Java GC\n        // will only cleanup the shared pointer, but leave the cached instance alone. This also\n        // means that no App is never fully closed. This should be safe as App doesn't implement\n        // Closable in Java, so it doesn't have a a visible lifecycle.\n        auto cached_app = App::get_cached_app(app_id);\n        if (cached_app) {\n            return reinterpret_cast<jlong>(new std::shared_ptr<App>(cached_app));\n        }\n\n        // App Config\n        JStringAccessor base_url(env, j_base_url);\n        JStringAccessor app_name(env, j_app_name);\n        JStringAccessor app_version(env, j_app_version);\n        JStringAccessor platform(env, j_platform);\n        JStringAccessor platform_version(env, j_platform_version);\n        JStringAccessor sdk_version(env, j_sdk_version);\n        JByteArrayAccessor encryption_key(env, j_encryption_key);\n        JStringAccessor cpu_arch(env, j_cpu_arch);\n        JStringAccessor device_name(env, j_device_name);\n        JStringAccessor device_version(env, j_device_version);\n        JStringAccessor framework_name(env, j_framework_name);\n        JStringAccessor framework_version(env, j_framework_version);\n\n        // Create Network Transport\n        static JavaMethod get_network_transport_method(env, obj, \"getNetworkTransport\", \"()Lio/realm/internal/objectstore/OsJavaNetworkTransport;\");\n        jobject network_transport_impl = env->CallObjectMethod(obj, get_network_transport_method);\n        auto network_transport = std::make_shared<JavaNetworkTransport>(network_transport_impl);\n\n        auto app_config = App::Config{\n                app_id,\n                network_transport,\n                util::Optional<std::string>(base_url),\n                util::Optional<std::uint64_t>(j_request_timeout_ms),\n                {\n                        platform_version,\n                        sdk_version,\n                        \"Java\",\n                        device_name,\n                        device_version,\n                        framework_name,\n                        framework_version,\n                        // TODO bundle_id should be match metric submitted value and be injected at compiler time.\n                        \"\"\n                }\n        };\n\n        // Sync Config\n        JStringAccessor base_file_path(env, j_sync_base_dir); // throws\n        JStringAccessor user_agent_binding_info(env, j_user_agent_binding_info); // throws\n        JStringAccessor user_agent_application_info(env, j_user_agent_application_info); // throws\n\n        SyncClientConfig client_config;\n        client_config.base_file_path = base_file_path;\n        client_config.user_agent_binding_info = user_agent_binding_info;\n        client_config.user_agent_application_info = user_agent_application_info;\n        // Disable multiplexing. See https://github.com/realm/realm-core/issues/6656\n        client_config.multiplex_sessions = false;\n\n        if(j_encryption_key == nullptr){\n            client_config.metadata_mode = SyncManager::MetadataMode::NoEncryption;\n        } else {\n            client_config.metadata_mode = SyncManager::MetadataMode::Encryption;\n            client_config.custom_encryption_key = encryption_key.transform<std::vector<char>>();\n        }\n        // Register Sync Client thread start/stop callback. Must be called after .configure()\n        static AndroidClientListener client_thread_listener(env);\n        client_config.default_socket_provider_thread_observer = std::make_shared<BindingCallbackThreadObserver>(client_thread_listener);\n\n        SharedApp app = App::get_app(app::App::CacheMode::Enabled, app_config, client_config);\n        // Init logger. Must be called after .configure()\n        app->sync_manager()->set_logger_factory(javaLoggerFactory);\n\n        return reinterpret_cast<jlong>(new std::shared_ptr<App>(app));\n    }\n    CATCH_STD()\n    return 0;\n}\n\n\nJNIEXPORT void JNICALL Java_io_realm_internal_objectstore_OsApp_nativeLogin(JNIEnv* env, jclass, jlong j_app_ptr, jlong j_credentials_ptr, jobject j_callback)\n{\n    try {\n        auto app = *reinterpret_cast<std::shared_ptr<App>*>(j_app_ptr);\n        auto credentials = reinterpret_cast<AppCredentials *>(j_credentials_ptr);\n        std::function<jobject(JNIEnv*, std::shared_ptr<SyncUser>)> mapper = [](JNIEnv* env, std::shared_ptr<SyncUser> user) {\n            auto* java_user = new std::shared_ptr<SyncUser>(std::move(user));\n            return JavaClassGlobalDef::new_long(env, reinterpret_cast<int64_t>(java_user));\n        };\n        auto callback = JavaNetworkTransport::create_result_callback(env, j_callback, mapper);\n        app->log_in_with_credentials(*credentials, std::move(callback));\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_objectstore_OsApp_nativeLogOut(JNIEnv* env, jclass, jlong j_app_ptr, jlong j_user_ptr, jobject j_callback)\n{\n    try {\n        auto app = *reinterpret_cast<std::shared_ptr<App>*>(j_app_ptr);\n        auto user = *reinterpret_cast<std::shared_ptr<SyncUser>*>(j_user_ptr);\n        app->log_out(user, JavaNetworkTransport::create_void_callback(env, j_callback));\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT jobject JNICALL Java_io_realm_internal_objectstore_OsApp_nativeCurrentUser(JNIEnv* env, jclass, jlong j_app_ptr)\n{\n    try {\n        auto app = *reinterpret_cast<std::shared_ptr<App>*>(j_app_ptr);\n        std::shared_ptr<SyncUser> user = app->current_user();\n        if (user) {\n            auto* java_user = new std::shared_ptr<SyncUser>(std::move(user));\n            return JavaClassGlobalDef::new_long(env, reinterpret_cast<int64_t>(java_user));\n        }\n        else {\n            return NULL;\n        }\n    }\n    CATCH_STD()\n    return NULL;\n}\n\nJNIEXPORT jlongArray JNICALL Java_io_realm_internal_objectstore_OsApp_nativeGetAllUsers(JNIEnv* env, jclass, jlong j_app_ptr)\n{\n    try {\n        auto app = *reinterpret_cast<std::shared_ptr<App>*>(j_app_ptr);\n        std::vector<std::shared_ptr<SyncUser>> users = app->all_users();\n        auto size = users.size();\n\n        jlongArray java_users = env->NewLongArray(size);\n        if (!java_users) {\n            ThrowException(env, OutOfMemory, \"Could not allocate memory to create array of users.\");\n            return nullptr;\n        }\n\n        jlong* user_ptrs = new jlong[size];\n        for(size_t i = 0; i < size; ++i) {\n            auto *java_user = new std::shared_ptr<SyncUser>(std::move(users[i]));\n            user_ptrs[i] = reinterpret_cast<int64_t>(java_user);\n        }\n\n        env->SetLongArrayRegion(java_users, 0, size, user_ptrs);\n        delete[] user_ptrs;\n        return java_users;\n    }\n    CATCH_STD()\n    return nullptr;\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_objectstore_OsApp_nativeSwitchUser(JNIEnv* env,\n                                                                  jclass,\n                                                                  jlong j_app_ptr,\n                                                                  jlong j_user_ptr)\n{\n    try {\n        auto app = *reinterpret_cast<std::shared_ptr<App>*>(j_app_ptr);\n        auto user = *reinterpret_cast<std::shared_ptr<SyncUser>*>(j_user_ptr);\n        app->switch_user(user);\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT jobject JNICALL Java_io_realm_internal_objectstore_OsApp_nativeMakeStreamingRequest(JNIEnv* env,\n                                                                               jclass,\n                                                                               jlong j_app_ptr,\n                                                                               jlong j_user_ptr,\n                                                                               jstring j_function_name,\n                                                                               jstring j_bson_args,\n                                                                               jstring j_service_name)\n{\n    try {\n        auto app = *reinterpret_cast<std::shared_ptr<App>*>(j_app_ptr);\n        auto user = *reinterpret_cast<std::shared_ptr<SyncUser>*>(j_user_ptr);\n\n        JStringAccessor function_name(env, j_function_name);\n        JStringAccessor service_name(env, j_service_name);\n\n        bson::BsonArray filter(JniBsonProtocol::parse_checked(env, j_bson_args, Bson::Type::Array, \"BSON filter must be an Array\"));\n\n        const Request &request = app->make_streaming_request(user, function_name, filter,\n                                                             std::string(service_name));\n\n        jstring j_method;\n\n        switch (request.method){\n            case HttpMethod::get:\n                j_method = env->NewStringUTF(\"get\");\n                break;\n            case HttpMethod::post:\n                j_method = env->NewStringUTF(\"post\");\n                break;\n            case HttpMethod::patch:\n                j_method = env->NewStringUTF(\"patch\");\n                break;\n            case HttpMethod::put:\n                j_method = env->NewStringUTF(\"put\");\n                break;\n            case HttpMethod::del:\n                j_method = env->NewStringUTF(\"del\");\n                break;\n        }\n\n        jstring j_url = env->NewStringUTF(request.url.c_str());\n        jobject j_headers = JniUtils::to_hash_map(env, request.headers);\n        jstring j_body = env->NewStringUTF(request.body.c_str());\n\n        static JavaClass request_class(env, \"io/realm/internal/objectstore/OsJavaNetworkTransport$Request\");\n        static JavaMethod request_constructor(env, request_class, \"<init>\",\"(Ljava/lang/String;Ljava/lang/String;Ljava/util/Map;Ljava/lang/String;)V\");\n        jobject j_request = env->NewObject(request_class, request_constructor, j_method, j_url, j_headers, j_body);\n\n        return j_request;\n    }\n    CATCH_STD()\n\n    return nullptr;\n}\n\n"
  },
  {
    "path": "realm/realm-library/src/main/cpp/io_realm_internal_objectstore_OsAppCredentials.cpp",
    "content": "/*\n * Copyright 2020 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#include \"io_realm_internal_objectstore_OsAppCredentials.h\"\n\n#include \"util.hpp\"\n\n#include <jni_util/bson_util.hpp>\n#include <realm/object-store/sync/app_credentials.hpp>\n\nusing namespace realm;\nusing namespace realm::app;\nusing namespace realm::bson;\nusing namespace realm::jni_util;\n\nstatic void finalize_credentials(jlong ptr)\n{\n    delete reinterpret_cast<AppCredentials*>(ptr);\n}\n\nJNIEXPORT jlong JNICALL Java_io_realm_internal_objectstore_OsAppCredentials_nativeGetFinalizerMethodPtr(JNIEnv*, jclass)\n{\n    return reinterpret_cast<jlong>(&finalize_credentials);\n}\n\nJNIEXPORT jlong JNICALL Java_io_realm_internal_objectstore_OsAppCredentials_nativeCreate(JNIEnv* env,\n                                                                                         jclass,\n                                                                                         jint j_type,\n                                                                                         jobjectArray j_args)\n{\n    try {\n        AppCredentials creds = AppCredentials::anonymous(); // Is there a way to avoid setting this to a specific value?\n        switch(j_type) {\n            case io_realm_internal_objectstore_OsAppCredentials_TYPE_ANONYMOUS:\n                /* Default, do nothing */;\n                break;\n            case io_realm_internal_objectstore_OsAppCredentials_TYPE_FACEBOOK: {\n                JStringAccessor access_token(env, (jstring) env->GetObjectArrayElement(j_args, 0));\n                creds = AppCredentials::facebook(access_token);\n                break;\n            }\n            case io_realm_internal_objectstore_OsAppCredentials_TYPE_EMAIL_PASSWORD: {\n                JStringAccessor email(env, (jstring) env->GetObjectArrayElement(j_args, 0));\n                JStringAccessor password(env, (jstring) env->GetObjectArrayElement(j_args, 1));\n                creds = AppCredentials::username_password(email, password);\n                break;\n            }\n            case io_realm_internal_objectstore_OsAppCredentials_TYPE_APPLE: {\n                JStringAccessor id_token(env, (jstring) env->GetObjectArrayElement(j_args, 0));\n                creds = AppCredentials::apple(id_token);\n                break;\n            }\n            case io_realm_internal_objectstore_OsAppCredentials_TYPE_GOOGLE_AUTH_CODE: {\n                JStringAccessor id_token(env, (jstring) env->GetObjectArrayElement(j_args, 0));\n                creds = AppCredentials::google(AuthCode(StringData(id_token).data()));\n                break;\n            }\n            case io_realm_internal_objectstore_OsAppCredentials_TYPE_GOOGLE_ID_TOKEN: {\n                JStringAccessor id_token(env, (jstring) env->GetObjectArrayElement(j_args, 0));\n                creds = AppCredentials::google(IdToken(StringData(id_token).data()));\n                break;\n            }\n            case io_realm_internal_objectstore_OsAppCredentials_TYPE_JWT: {\n                JStringAccessor token(env, (jstring) env->GetObjectArrayElement(j_args, 0));\n                creds = AppCredentials::custom(token);\n                break;\n            }\n            case io_realm_internal_objectstore_OsAppCredentials_TYPE_API_KEY: {\n                JStringAccessor token(env, (jstring) env->GetObjectArrayElement(j_args, 0));\n                creds = AppCredentials::api_key(token);\n                break;\n            }\n            case io_realm_internal_objectstore_OsAppCredentials_TYPE_CUSTOM_FUNCTION: {\n                jstring j_payload = (jstring) env->GetObjectArrayElement(j_args, 0);\n                bson::BsonDocument payload(JniBsonProtocol::parse_checked(env, j_payload, Bson::Type::Document, \"Payload must be a Document\"));\n                creds = AppCredentials::function(payload);\n                break;\n            }\n            default:\n                throw std::runtime_error(util::format(\"Unknown credentials type: %1\", j_type));\n        }\n        return reinterpret_cast<jlong>(new AppCredentials(std::move(creds)));\n    }\n    CATCH_STD()\n    return 0;\n}\n\nJNIEXPORT jstring JNICALL Java_io_realm_internal_objectstore_OsAppCredentials_nativeGetProvider(JNIEnv* env, jclass, jlong j_native_ptr)\n{\n    try {\n        auto credentials = reinterpret_cast<AppCredentials*>(j_native_ptr);\n        std::string provider = credentials->provider_as_string();\n        return to_jstring(env, provider);\n    }\n    CATCH_STD()\n    return nullptr;\n}\n\nJNIEXPORT jstring JNICALL Java_io_realm_internal_objectstore_OsAppCredentials_nativeAsJson(JNIEnv* env, jclass, jlong j_native_ptr)\n{\n    try {\n        auto credentials = reinterpret_cast<AppCredentials*>(j_native_ptr);\n        std::string json = credentials->serialize_as_json();\n        return to_jstring(env, json);\n    }\n    CATCH_STD()\n    return 0;\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/cpp/io_realm_internal_objectstore_OsAsyncOpenTask.cpp",
    "content": "/*\n * Copyright 2019 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#include \"io_realm_internal_objectstore_OsAsyncOpenTask.h\"\n\n#include \"util.hpp\"\n#include <realm/object-store/thread_safe_reference.hpp>\n#include \"jni_util/java_method.hpp\"\n#include \"jni_util/java_class.hpp\"\n#include \"jni_util/jni_utils.hpp\"\n#include <realm/object-store/sync/async_open_task.hpp>\n#include <realm/sync/config.hpp>\n\n#include <realm/object-store/shared_realm.hpp>\n#include <memory>\n\nusing namespace realm;\nusing namespace realm::jni_util;\nusing namespace realm::_impl;\n\nJNIEXPORT jlong JNICALL Java_io_realm_internal_objectstore_OsAsyncOpenTask_start(JNIEnv* env, jobject obj, jlong config_ptr)\n{\n    try {\n\n        static JavaClass java_async_open_task_class(env, \"io/realm/internal/objectstore/OsAsyncOpenTask\");\n        static JavaMethod java_notify_realm_ready(env, java_async_open_task_class, \"notifyRealmReady\", \"()V\", false);\n        static JavaMethod java_notify_error(env, java_async_open_task_class, \"notifyError\", \"(BILjava/lang/String;)V\", false);\n\n        auto global_obj = env->NewGlobalRef(obj);\n        auto& config = *reinterpret_cast<Realm::Config*>(config_ptr);\n\n        std::shared_ptr<realm::AsyncOpenTask> task = Realm::get_synchronized_realm(config);\n\n        auto deleter = [](jobject obj) {\n            jni_util::JniUtils::get_env(true)->DeleteGlobalRef(obj);\n        };\n        std::shared_ptr<_jobject> task_obj(env->NewGlobalRef(global_obj), deleter);\n        task->start([task=std::move(task_obj)](realm::ThreadSafeReference realm_ref, std::exception_ptr error) {\n            JNIEnv* local_env = jni_util::JniUtils::get_env(true);\n            if (error) {\n                try {\n                    std::rethrow_exception(error);\n                }\n                catch(const realm::Exception& e) {\n                    const realm::Status& status = e.to_status();\n                    auto error_code = static_cast<int32_t>(status.code());\n                    jbyte category = categoryAsJByte(e.to_status());\n                    jstring j_error_msg = to_jstring(local_env, e.what());\n                    local_env->CallVoidMethod(task.get(), java_notify_error, category, error_code, j_error_msg);\n                    local_env->DeleteLocalRef(j_error_msg);\n                }\n                catch (const std::exception& e) {\n                    jint error_code = -1;\n                    jbyte category = io_realm_internal_ErrorCategory_RLM_SYNC_ERROR_CATEGORY_UNKNOWN;\n                    jstring j_error_msg = to_jstring(local_env, e.what());\n                    local_env->CallVoidMethod(task.get(), java_notify_error, category, error_code, j_error_msg);\n                    local_env->DeleteLocalRef(j_error_msg);\n                }\n            }\n            else {\n                auto realm = Realm::get_shared_realm(std::move(realm_ref));\n                realm->close();\n                local_env->CallVoidMethod(task.get(), java_notify_realm_ready);\n            }\n            const_cast<std::shared_ptr<_jobject>&>(task).reset();\n        });\n        return reinterpret_cast<jlong>(&(*task));\n    }\n    CATCH_STD()\n    return 0;\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_objectstore_OsAsyncOpenTask_cancel(JNIEnv*, jobject, jlong task_ptr)\n{\n    AsyncOpenTask* task = reinterpret_cast<AsyncOpenTask*>(task_ptr);\n    task->cancel();\n}"
  },
  {
    "path": "realm/realm-library/src/main/cpp/io_realm_internal_objectstore_OsJavaNetworkTransport.cpp",
    "content": "/*\n * Copyright 2020 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#include \"io_realm_internal_objectstore_OsJavaNetworkTransport.h\"\n\n#include \"java_network_transport.hpp\"\n#include \"util.hpp\"\n#include \"jni_util/java_method.hpp\"\n#include \"jni_util/jni_utils.hpp\"\n\n#include <realm/object-store/sync/app.hpp>\n\nusing namespace realm;\nusing namespace realm::app;\nusing namespace realm::jni_util;\nusing namespace realm::_impl;\n\nJNIEXPORT void JNICALL Java_io_realm_internal_objectstore_OsJavaNetworkTransport_nativeHandleResponse(JNIEnv* env,\n                                                                                                      jclass,\n                                                                                                      jobject j_response_obj,\n                                                                                                      jlong j_completion_block_ptr)\n{\n    try {\n        std::unique_ptr<ResponseFunction> completion_block(reinterpret_cast<ResponseFunction*>(j_completion_block_ptr));\n\n        // Read response\n        static const JavaClass& response_class(JavaClassGlobalDef::network_transport_response_class());\n        static JavaMethod get_http_code_method(env, response_class, \"getHttpResponseCode\", \"()I\");\n        static JavaMethod get_custom_code_method(env, response_class, \"getCustomResponseCode\", \"()I\");\n        static JavaMethod get_headers_method(env, response_class, \"getJNIFriendlyHeaders\", \"()[Ljava/lang/String;\");\n        static JavaMethod get_body_method(env, response_class, \"getBody\", \"()Ljava/lang/String;\");\n\n        jint http_code = env->CallIntMethod(j_response_obj, get_http_code_method);\n        jint custom_code = env->CallIntMethod(j_response_obj, get_custom_code_method);\n        JStringAccessor java_body(env, (jstring) env->CallObjectMethod(j_response_obj, get_body_method), true);\n        JObjectArrayAccessor<JStringAccessor, jstring> java_headers(env, static_cast<jobjectArray>(env->CallObjectMethod(j_response_obj, get_headers_method)));\n        auto response_headers = std::map<std::string, std::string>();\n        for (int i = 0; i < java_headers.size(); i = i + 2) {\n            JStringAccessor key = java_headers[i];\n            JStringAccessor value = java_headers[i+1];\n            response_headers.insert(std::pair<std::string,std::string>(key,value));\n        }\n        std::string body = java_body;\n\n        // Trigger callback into ObjectStore and cleanup\n        (*completion_block)({(int) http_code, (int) custom_code, response_headers, body});\n    }\n    CATCH_STD()\n}\n\n"
  },
  {
    "path": "realm/realm-library/src/main/cpp/io_realm_internal_objectstore_OsKeyPathMapping.cpp",
    "content": "/*\n * Copyright 2021 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#include \"io_realm_internal_objectstore_OsKeyPathMapping.h\"\n\n#include <realm/sort_descriptor.hpp>\n#include <realm/object-store/keypath_helpers.hpp>\n#include <realm/object-store/shared_realm.hpp>\n#include <realm/parser/keypath_mapping.hpp>\n\n#include \"util.hpp\"\n\nusing namespace realm;\nusing namespace realm::jni_util;\nusing namespace realm::_impl;\n\nstatic void finalize_client(jlong ptr) {\n    delete reinterpret_cast<query_parser::KeyPathMapping*>(ptr);\n}\n\nJNIEXPORT jlong JNICALL\nJava_io_realm_internal_objectstore_OsKeyPathMapping_nativeGetFinalizerMethodPtr(JNIEnv*, jclass) {\n    return reinterpret_cast<jlong>(&finalize_client);\n}\n\nJNIEXPORT jlong JNICALL Java_io_realm_internal_objectstore_OsKeyPathMapping_nativeCreateMapping(JNIEnv* env, jclass, jlong j_shared_realm_ptr) {\n    try {\n        auto shared_realm = *(reinterpret_cast<SharedRealm*>(j_shared_realm_ptr));\n        auto mapping = new query_parser::KeyPathMapping;\n        realm::populate_keypath_mapping(*mapping, *shared_realm);\n        return reinterpret_cast<jlong>(mapping);\n    }\n    CATCH_STD()\n    return 0;\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/cpp/io_realm_internal_objectstore_OsMongoClient.cpp",
    "content": "/*\n * Copyright 2020 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#include \"io_realm_internal_objectstore_OsMongoClient.h\"\n\n#include \"java_class_global_def.hpp\"\n#include \"java_network_transport.hpp\"\n#include \"util.hpp\"\n#include \"jni_util/java_method.hpp\"\n#include \"jni_util/jni_utils.hpp\"\n\n#include <realm/util/optional.hpp>\n#include <realm/object-store/sync/app.hpp>\n#include <realm/object-store/sync/sync_user.hpp>\n#include <realm/object-store/sync/mongo_client.hpp>\n#include <realm/object-store/sync/mongo_database.hpp>\n\nusing namespace realm;\nusing namespace realm::app;\nusing namespace realm::jni_util;\nusing namespace realm::_impl;\n\nstatic void finalize_client(jlong ptr) {\n    delete reinterpret_cast<MongoClient*>(ptr);\n}\n\nJNIEXPORT jlong JNICALL\nJava_io_realm_internal_objectstore_OsMongoClient_nativeGetFinalizerMethodPtr(JNIEnv*, jclass) {\n    return reinterpret_cast<jlong>(&finalize_client);\n}\n\nJNIEXPORT jlong JNICALL\nJava_io_realm_internal_objectstore_OsMongoClient_nativeCreate(JNIEnv* env,\n                                                              jclass,\n                                                              jlong j_user_ptr,\n                                                              jstring j_service_name) {\n    try {\n        std::shared_ptr<SyncUser>& user = *reinterpret_cast<std::shared_ptr<SyncUser>*>(j_user_ptr);\n        JStringAccessor name(env, j_service_name);\n        MongoClient client(user->mongo_client(name));\n        return reinterpret_cast<jlong>(new MongoClient(std::move(client)));\n    }\n    CATCH_STD()\n    return reinterpret_cast<jlong>(nullptr);\n}\n\nJNIEXPORT jlong JNICALL\nJava_io_realm_internal_objectstore_OsMongoClient_nativeCreateDatabase(JNIEnv* env,\n                                                                      jclass,\n                                                                      jlong j_client_ptr,\n                                                                      jstring j_database_name) {\n    try {\n        auto client = reinterpret_cast<MongoClient*>(j_client_ptr);\n        JStringAccessor name(env, j_database_name);\n        MongoDatabase database(client->db(name));\n        return reinterpret_cast<jlong>(new MongoDatabase(std::move(database)));\n    }\n    CATCH_STD()\n    return reinterpret_cast<jlong>(nullptr);\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/cpp/io_realm_internal_objectstore_OsMongoCollection.cpp",
    "content": "/*\n * Copyright 2020 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#include \"io_realm_internal_objectstore_OsMongoCollection.h\"\n\n#include \"java_class_global_def.hpp\"\n#include \"java_network_transport.hpp\"\n#include \"util.hpp\"\n#include \"jni_util/java_method.hpp\"\n#include \"jni_util/jni_utils.hpp\"\n#include \"jni_util/bson_util.hpp\"\n#include <realm/util/bson/bson.hpp>\n\n#include <realm/util/optional.hpp>\n#include <realm/object-store/sync/app.hpp>\n#include <realm/object-store/sync/mongo_database.hpp>\n#include <realm/object-store/sync/mongo_collection.hpp>\n#include <jni_util/bson_util.hpp>\n\nusing namespace realm;\nusing namespace realm::app;\nusing namespace realm::bson;\nusing namespace realm::jni_util;\nusing namespace realm::_impl;\n\n// This mapper works for both count and delete operations\nstatic std::function<jobject(JNIEnv*, uint64_t)> collection_mapper_count = [](JNIEnv* env, uint64_t result) {\n    return JavaClassGlobalDef::new_long(env, result);\n};\n\n// This mapper works for both findOne and findOneAndUpdate/Replace functions\nstatic std::function<jobject(JNIEnv*, util::Optional<bson::BsonDocument>)> collection_mapper_find_one = [](JNIEnv* env, util::Optional<bson::BsonDocument> document) {\n    return document ? JniBsonProtocol::bson_to_jstring(env, *document) : nullptr;\n};\n\nstatic std::function<jobject(JNIEnv*, util::Optional<Bson>)> collection_mapper_insert_one = [](JNIEnv* env, util::Optional<Bson> bson_id) {\n    if (bson_id) {\n        return JniBsonProtocol::bson_to_jstring(env, bson_id.value());\n    }\n    throw std::logic_error(\"Error in 'insert_one', parameter 'bson_id' has no value.\");\n};\n\nstatic std::function<jobject(JNIEnv*, std::vector<Bson>)> collection_mapper_insert_many = [](JNIEnv* env, std::vector<Bson> bson_ids) {\n    if (bson_ids.empty()) {\n        throw std::logic_error(\"Error in 'insert_many', parameter 'object_ids' is empty.\");\n    }\n    auto arr = (jobjectArray)env->NewObjectArray(static_cast<jsize>(bson_ids.size()), JavaClassGlobalDef::java_lang_object(), nullptr);\n    if (arr == nullptr) {\n        ThrowException(env, OutOfMemory, \"Could not allocate memory to return list of ObjectIds of inserted documents.\");\n        return arr;\n    }\n    for (size_t i = 0; i < bson_ids.size(); ++i) {\n        env->SetObjectArrayElement(arr, i, JniBsonProtocol::bson_to_jstring(env, bson_ids[i]));\n    }\n    return arr;\n};\n\nstatic std::function<jobject(JNIEnv*, MongoCollection::UpdateResult)> collection_mapper_update = [](JNIEnv* env, MongoCollection::UpdateResult result) {\n    Bson matched_count(result.matched_count);\n    Bson modified_count(result.modified_count);\n    Bson upserted_value;\n    if (result.upserted_id) {\n        upserted_value = Bson(result.upserted_id.value());\n    }\n    std::vector<Bson> bson_vector = { matched_count, modified_count, upserted_value };\n    Bson output(bson_vector);\n    return JniBsonProtocol::bson_to_jstring(env, output);\n};\n\nstatic void finalize_collection(jlong ptr) {\n    delete reinterpret_cast<MongoCollection*>(ptr);\n}\n\nJNIEXPORT jlong JNICALL\nJava_io_realm_internal_objectstore_OsMongoCollection_nativeGetFinalizerMethodPtr(JNIEnv*, jclass) {\n    return reinterpret_cast<jlong>(&finalize_collection);\n}\n\nJNIEXPORT void JNICALL\nJava_io_realm_internal_objectstore_OsMongoCollection_nativeCount(JNIEnv* env,\n                                                                 jclass,\n                                                                 jlong j_collection_ptr,\n                                                                 jstring j_filter,\n                                                                 jlong j_limit,\n                                                                 jobject j_callback) {\n    try {\n        auto collection = reinterpret_cast<MongoCollection*>(j_collection_ptr);\n\n        bson::BsonDocument filter(JniBsonProtocol::parse_checked(env, j_filter, Bson::Type::Document, \"BSON filter must be a Document\"));\n        uint64_t limit = std::uint64_t(j_limit);\n        collection->count(filter, limit, JavaNetworkTransport::create_result_callback(env, j_callback, collection_mapper_count));\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL\nJava_io_realm_internal_objectstore_OsMongoCollection_nativeFindOne(JNIEnv* env,\n                                                                   jclass,\n                                                                   jint j_find_one_type,\n                                                                   jlong j_collection_ptr,\n                                                                   jstring j_filter,\n                                                                   jstring j_projection,\n                                                                   jstring j_sort,\n                                                                   jlong j_limit,\n                                                                   jobject j_callback) {\n    try {\n        auto collection = reinterpret_cast<MongoCollection*>(j_collection_ptr);\n\n        bson::BsonDocument filter(JniBsonProtocol::parse_checked(env, j_filter, Bson::Type::Document, \"BSON filter must be a Document\"));\n\n        switch (j_find_one_type) {\n            case io_realm_internal_objectstore_OsMongoCollection_FIND_ONE:\n                collection->find_one(filter, JavaNetworkTransport::create_result_callback(env, j_callback, collection_mapper_find_one));\n                break;\n            case io_realm_internal_objectstore_OsMongoCollection_FIND_ONE_WITH_OPTIONS: {\n                uint64_t limit = std::uint64_t(j_limit);\n\n                bson::BsonDocument projection(JniBsonProtocol::parse_checked(env, j_projection, Bson::Type::Document, \"BSON projection must be a Document\"));\n                bson::BsonDocument sort(JniBsonProtocol::parse_checked(env, j_sort, Bson::Type::Document, \"BSON sort must be a Document\"));\n                MongoCollection::FindOptions options = {\n                        limit,\n                        projection,\n                        sort\n                };\n\n                collection->find_one(filter, options, JavaNetworkTransport::create_result_callback(env, j_callback, collection_mapper_find_one));\n                break;\n            }\n            default:\n                throw std::logic_error(util::format(\"Unknown find_one type: %1\", j_find_one_type));\n        }\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL\nJava_io_realm_internal_objectstore_OsMongoCollection_nativeInsertOne(JNIEnv* env,\n                                                                     jclass,\n                                                                     jlong j_collection_ptr,\n                                                                     jstring j_document,\n                                                                     jobject j_callback) {\n    try {\n        auto collection = reinterpret_cast<MongoCollection*>(j_collection_ptr);\n\n        bson::BsonDocument filter(JniBsonProtocol::parse_checked(env, j_document, Bson::Type::Document, \"BSON document must be a Document\"));\n        collection->insert_one(filter, JavaNetworkTransport::create_result_callback(env, j_callback, collection_mapper_insert_one));\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL\nJava_io_realm_internal_objectstore_OsMongoCollection_nativeInsertMany(JNIEnv* env,\n                                                                      jclass,\n                                                                      jlong j_collection_ptr,\n                                                                      jstring j_documents,\n                                                                      jobject j_callback) {\n    try {\n        auto collection = reinterpret_cast<MongoCollection*>(j_collection_ptr);\n\n        BsonArray bson_array(JniBsonProtocol::parse_checked(env, j_documents, Bson::Type::Array, \"BSON documents must be a BsonArray\"));\n        collection->insert_many(bson_array, JavaNetworkTransport::create_result_callback(env, j_callback, collection_mapper_insert_many));\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL\nJava_io_realm_internal_objectstore_OsMongoCollection_nativeDelete(JNIEnv* env,\n                                                                  jclass,\n                                                                  jint j_delete_type,\n                                                                  jlong j_collection_ptr,\n                                                                  jstring j_document,\n                                                                  jobject j_callback) {\n    try {\n        auto collection = reinterpret_cast<MongoCollection*>(j_collection_ptr);\n        bson::BsonDocument filter(JniBsonProtocol::parse_checked(env, j_document, Bson::Type::Document, \"BSON document must be a Document\"));\n\n        switch (j_delete_type) {\n            case io_realm_internal_objectstore_OsMongoCollection_DELETE_ONE:\n                collection->delete_one(filter, JavaNetworkTransport::create_result_callback(env, j_callback, collection_mapper_count));\n                break;\n            case io_realm_internal_objectstore_OsMongoCollection_DELETE_MANY:\n                collection->delete_many(filter, JavaNetworkTransport::create_result_callback(env, j_callback, collection_mapper_count));\n                break;\n            default:\n                throw std::logic_error(util::format(\"Unknown delete type: %1\", j_delete_type));\n        }\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL\nJava_io_realm_internal_objectstore_OsMongoCollection_nativeUpdate(JNIEnv *env,\n                                                                  jclass,\n                                                                  jint j_update_type,\n                                                                  jlong j_collection_ptr,\n                                                                  jstring j_filter,\n                                                                  jstring j_update,\n                                                                  jboolean j_upsert,\n                                                                  jobject j_callback) {\n    try {\n        auto collection = reinterpret_cast<MongoCollection*>(j_collection_ptr);\n\n        bson::BsonDocument filter(JniBsonProtocol::parse_checked(env, j_filter, Bson::Type::Document, \"BSON filter must be a Document\"));\n        bson::BsonDocument update(JniBsonProtocol::parse_checked(env, j_update, Bson::Type::Document, \"BSON update must be a Document\"));\n\n        switch (j_update_type) {\n            case io_realm_internal_objectstore_OsMongoCollection_UPDATE_ONE:\n                collection->update_one(filter, update, JavaNetworkTransport::create_result_callback(env, j_callback, collection_mapper_update));\n                break;\n            case io_realm_internal_objectstore_OsMongoCollection_UPDATE_ONE_WITH_OPTIONS:\n                collection->update_one(filter, update, to_bool(j_upsert), JavaNetworkTransport::create_result_callback(env, j_callback, collection_mapper_update));\n                break;\n            case io_realm_internal_objectstore_OsMongoCollection_UPDATE_MANY:\n                collection->update_many(filter, update, JavaNetworkTransport::create_result_callback(env, j_callback, collection_mapper_update));\n                break;\n            case io_realm_internal_objectstore_OsMongoCollection_UPDATE_MANY_WITH_OPTIONS:\n                collection->update_many(filter, update, to_bool(j_upsert), JavaNetworkTransport::create_result_callback(env, j_callback, collection_mapper_update));\n                break;\n            default:\n                throw std::logic_error(util::format(\"Unknown update type: %1\", j_update_type));\n        }\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL\nJava_io_realm_internal_objectstore_OsMongoCollection_nativeFindOneAndUpdate(JNIEnv *env,\n                                                                            jclass,\n                                                                            jint j_find_one_and_update_type,\n                                                                            jlong j_collection_ptr,\n                                                                            jstring j_filter,\n                                                                            jstring j_update,\n                                                                            jstring j_projection,\n                                                                            jstring j_sort,\n                                                                            jboolean j_upsert,\n                                                                            jboolean j_return_new_document,\n                                                                            jobject j_callback) {\n    try {\n        auto collection = reinterpret_cast<MongoCollection*>(j_collection_ptr);\n\n        bson::BsonDocument filter(JniBsonProtocol::parse_checked(env, j_filter, Bson::Type::Document, \"BSON filter must be a Document\"));\n        bson::BsonDocument update(JniBsonProtocol::parse_checked(env, j_update, Bson::Type::Document, \"BSON update must be a Document\"));\n\n        switch (j_find_one_and_update_type) {\n            case io_realm_internal_objectstore_OsMongoCollection_FIND_ONE_AND_UPDATE:\n                collection->find_one_and_update(filter, update, JavaNetworkTransport::create_result_callback(env, j_callback, collection_mapper_find_one));\n                break;\n            case io_realm_internal_objectstore_OsMongoCollection_FIND_ONE_AND_UPDATE_WITH_OPTIONS: {\n                bson::BsonDocument projection(JniBsonProtocol::parse_checked(env, j_projection, Bson::Type::Document, \"BSON projection must be a Document\"));\n                bson::BsonDocument sort(JniBsonProtocol::parse_checked(env, j_sort, Bson::Type::Document, \"BSON sort must be a Document\"));\n                MongoCollection::FindOneAndModifyOptions options = {\n                        projection,\n                        sort,\n                        to_bool(j_upsert),\n                        to_bool(j_return_new_document)\n                };\n                collection->find_one_and_update(filter, update, options, JavaNetworkTransport::create_result_callback(env, j_callback, collection_mapper_find_one));\n                break;\n            }\n            default:\n                throw std::logic_error(util::format(\"Unknown find_one_and_update type: %1\", j_find_one_and_update_type));\n        }\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL\nJava_io_realm_internal_objectstore_OsMongoCollection_nativeFindOneAndReplace(JNIEnv *env,\n                                                                             jclass,\n                                                                             jint j_find_one_and_replace_type,\n                                                                             jlong j_collection_ptr,\n                                                                             jstring j_filter,\n                                                                             jstring j_update,\n                                                                             jstring j_projection,\n                                                                             jstring j_sort,\n                                                                             jboolean j_upsert,\n                                                                             jboolean j_return_new_document,\n                                                                             jobject j_callback) {\n    try {\n        auto collection = reinterpret_cast<MongoCollection*>(j_collection_ptr);\n\n        bson::BsonDocument filter(JniBsonProtocol::parse_checked(env, j_filter, Bson::Type::Document, \"BSON filter must be a Document\"));\n        bson::BsonDocument update(JniBsonProtocol::parse_checked(env, j_update, Bson::Type::Document, \"BSON update must be a Document\"));\n\n        switch (j_find_one_and_replace_type) {\n            case io_realm_internal_objectstore_OsMongoCollection_FIND_ONE_AND_REPLACE:\n                collection->find_one_and_replace(filter, update, JavaNetworkTransport::create_result_callback(env, j_callback, collection_mapper_find_one));\n                break;\n            case io_realm_internal_objectstore_OsMongoCollection_FIND_ONE_AND_REPLACE_WITH_OPTIONS: {\n                bson::BsonDocument projection(JniBsonProtocol::parse_checked(env, j_projection, Bson::Type::Document, \"BSON projection must be a Document\"));\n                bson::BsonDocument sort(JniBsonProtocol::parse_checked(env, j_sort, Bson::Type::Document, \"BSON sort must be a Document\"));\n                MongoCollection::FindOneAndModifyOptions options = {\n                        projection,\n                        sort,\n                        to_bool(j_upsert),\n                        to_bool(j_return_new_document)\n                };\n                collection->find_one_and_replace(filter, update, options, JavaNetworkTransport::create_result_callback(env, j_callback, collection_mapper_find_one));\n                break;\n            }\n            default:\n                throw std::logic_error(util::format(\"Unknown find_one_and_replace type: %1\", j_find_one_and_replace_type));\n        }\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL\nJava_io_realm_internal_objectstore_OsMongoCollection_nativeFindOneAndDelete(JNIEnv *env,\n                                                                            jclass,\n                                                                            jint j_find_one_and_delete_type,\n                                                                            jlong j_collection_ptr,\n                                                                            jstring j_filter,\n                                                                            jstring j_projection,\n                                                                            jstring j_sort,\n                                                                            jboolean j_upsert,\n                                                                            jboolean j_return_new_document,\n                                                                            jobject j_callback) {\n    try {\n        auto collection = reinterpret_cast<MongoCollection*>(j_collection_ptr);\n\n        bson::BsonDocument filter(JniBsonProtocol::parse_checked(env, j_filter, Bson::Type::Document, \"BSON filter must be a Document\"));\n\n        switch (j_find_one_and_delete_type) {\n            case io_realm_internal_objectstore_OsMongoCollection_FIND_ONE_AND_DELETE:\n                collection->find_one_and_delete(filter, JavaNetworkTransport::create_result_callback(env, j_callback, collection_mapper_find_one));\n                break;\n            case io_realm_internal_objectstore_OsMongoCollection_FIND_ONE_AND_DELETE_WITH_OPTIONS: {\n                bson::BsonDocument projection(JniBsonProtocol::parse_checked(env, j_projection, Bson::Type::Document, \"BSON projection must be a Document\"));\n                bson::BsonDocument sort(JniBsonProtocol::parse_checked(env, j_sort, Bson::Type::Document, \"BSON sort must be a Document\"));\n                MongoCollection::FindOneAndModifyOptions options = {\n                        projection,\n                        sort,\n                        to_bool(j_upsert),\n                        to_bool(j_return_new_document)\n                };\n                collection->find_one_and_delete(filter, options, JavaNetworkTransport::create_result_callback(env, j_callback, collection_mapper_find_one));\n                break;\n            }\n            default:\n                throw std::logic_error(util::format(\"Unknown find_one_and_delete type: %1\", j_find_one_and_delete_type));\n        }\n    }\n    CATCH_STD()\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/cpp/io_realm_internal_objectstore_OsMongoDatabase.cpp",
    "content": "/*\n * Copyright 2020 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#include \"io_realm_internal_objectstore_OsMongoDatabase.h\"\n\n#include \"java_class_global_def.hpp\"\n#include \"java_network_transport.hpp\"\n#include \"util.hpp\"\n#include \"jni_util/java_method.hpp\"\n#include \"jni_util/jni_utils.hpp\"\n\n#include <realm/util/optional.hpp>\n#include <realm/object-store/sync/app.hpp>\n#include <realm/object-store/sync/sync_user.hpp>\n#include <realm/object-store/sync/mongo_database.hpp>\n#include <realm/object-store/sync/mongo_collection.hpp>\n\nusing namespace realm;\nusing namespace realm::app;\nusing namespace realm::jni_util;\nusing namespace realm::_impl;\n\nstatic void finalize_database(jlong ptr) {\n    delete reinterpret_cast<MongoDatabase*>(ptr);\n}\n\nJNIEXPORT jlong JNICALL\nJava_io_realm_internal_objectstore_OsMongoDatabase_nativeGetFinalizerMethodPtr(JNIEnv*, jclass) {\n    return reinterpret_cast<jlong>(&finalize_database);\n}\n\nJNIEXPORT jlong JNICALL\nJava_io_realm_internal_objectstore_OsMongoDatabase_nativeGetCollection(JNIEnv* env,\n                                                                       jclass,\n                                                                       jlong j_database_ptr,\n                                                                       jstring j_collection_name) {\n    try {\n        auto database = reinterpret_cast<MongoDatabase*>(j_database_ptr);\n        JStringAccessor name(env, j_collection_name);\n        MongoCollection collection(database->collection(name));\n        return reinterpret_cast<jlong>(new MongoCollection(std::move(collection)));\n    }\n    CATCH_STD()\n    return reinterpret_cast<jlong>(nullptr);\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/cpp/io_realm_internal_objectstore_OsMutableSubscriptionSet.cpp",
    "content": "/*\n * Copyright 2022 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#include \"io_realm_internal_objectstore_OsMutableSubscriptionSet.h\"\n\n#include \"java_network_transport.hpp\"\n#include \"util.hpp\"\n#include \"jni_util/java_method.hpp\"\n#include \"jni_util/jni_utils.hpp\"\n\n#include <realm/object-store/shared_realm.hpp>\n#include <realm/sync/binding_callback_thread_observer.hpp>\n#include <realm/object-store/sync/app.hpp>\n#include <realm/object-store/sync/sync_manager.hpp>\n#include <realm/sync/subscriptions.hpp>\n\n#include <jni_util/bson_util.hpp>\n\nusing namespace realm;\nusing namespace realm::app;\nusing namespace realm::jni_util;\nusing namespace realm::_impl;\n\nJNIEXPORT jlong JNICALL Java_io_realm_internal_objectstore_OsMutableSubscriptionSet_nativeInsertOrAssign(JNIEnv* env,\n                                                                                              jclass,\n                                                                                              jlong j_subscription_set_ptr,\n                                                                                              jstring j_name,\n                                                                                              jlong j_query,\n                                                                                              jboolean j_throw_on_update)\n{\n    try {\n        auto subscriptions = reinterpret_cast<sync::MutableSubscriptionSet*>(j_subscription_set_ptr);\n        JStringAccessor name(env, j_name);\n        auto query = reinterpret_cast<Query*>(j_query);\n        std::pair<sync::SubscriptionSet::iterator, bool> result = name.is_null() ? subscriptions->insert_or_assign(*query) : subscriptions->insert_or_assign(name, *query);\n\n        if (j_throw_on_update && !result.second) {\n            ThrowException(env, ExceptionKind::IllegalArgument, \"Subscription could not be added because it already existed\");\n            return -1;\n        } else {\n            return reinterpret_cast<jlong>(new sync::Subscription(*result.first));\n        }\n    }\n    CATCH_STD()\n    return 0;\n}\n\nJNIEXPORT jlong JNICALL Java_io_realm_internal_objectstore_OsMutableSubscriptionSet_nativeCommit(JNIEnv* env,\n                                                                                                         jclass,\n                                                                                                         jlong j_subscription_set_ptr)\n{\n    try {\n        auto subscriptions = reinterpret_cast<sync::MutableSubscriptionSet*>(j_subscription_set_ptr);\n        sync::SubscriptionSet sub_set = std::move(*subscriptions).commit();\n        return reinterpret_cast<jlong>(new sync::SubscriptionSet(sub_set));\n    }\n    CATCH_STD()\n    return 0;\n}\n\nJNIEXPORT jboolean JNICALL Java_io_realm_internal_objectstore_OsMutableSubscriptionSet_nativeRemoveNamed(JNIEnv *env,\n                                                                                                    jclass,\n                                                                                                    jlong j_subscriptions_set_ptr,\n                                                                                                    jstring j_name)\n{\n    try {\n        auto subscriptions = reinterpret_cast<sync::MutableSubscriptionSet*>(j_subscriptions_set_ptr);\n        JStringAccessor name(env, j_name);\n        for (auto it = subscriptions->begin(); it != subscriptions->end(); ++it) {\n            if (it->name == name) {\n                subscriptions->erase(it);\n                return true;\n            }\n        }\n    }\n    CATCH_STD()\n    return false;\n}\n\nJNIEXPORT jboolean JNICALL Java_io_realm_internal_objectstore_OsMutableSubscriptionSet_nativeRemove(JNIEnv *env,\n                                                                             jclass,\n                                                                             jlong j_subscriptions_set_ptr,\n                                                                             jlong j_subscription_ptr)\n{\n    try {\n        auto subscriptions = reinterpret_cast<sync::MutableSubscriptionSet*>(j_subscriptions_set_ptr);\n        auto sub = reinterpret_cast<sync::Subscription*>(j_subscription_ptr);\n        for (auto it = subscriptions->begin(); it != subscriptions->end(); ++it) {\n            if (it->id == sub->id) {\n                subscriptions->erase(it);\n                return true;\n            }\n        }\n    }\n    CATCH_STD()\n    return false;\n}\n\nJNIEXPORT jboolean JNICALL Java_io_realm_internal_objectstore_OsMutableSubscriptionSet_nativeRemoveAll(JNIEnv *env,\n                                                                               jclass,\n                                                                               jlong j_subscriptions_set_ptr)\n{\n    try {\n        auto subscriptions = reinterpret_cast<sync::MutableSubscriptionSet*>(j_subscriptions_set_ptr);\n        bool remove = subscriptions->size() > 0;\n        subscriptions->clear();\n        return remove;\n    }\n    CATCH_STD()\n    return false;\n}\n\nJNIEXPORT jboolean JNICALL Java_io_realm_internal_objectstore_OsMutableSubscriptionSet_nativeRemoveAllForType(JNIEnv *env,\n                                                                                                       jclass,\n                                                                                                       jlong j_subscriptions_set_ptr,\n                                                                                                       jstring j_clazz_type)\n{\n    try {\n        auto subscriptions = reinterpret_cast<sync::MutableSubscriptionSet*>(j_subscriptions_set_ptr);\n        JStringAccessor type(env, j_clazz_type);\n        bool remove = false;\n        for (auto it = subscriptions->begin(); it != subscriptions->end(); ++it) {\n            if (it->object_class_name == type) {\n                it = subscriptions->erase(it);\n                remove = true;\n                if (it == subscriptions->end()) {\n                    return remove;\n                }\n            }\n        }\n        return remove;\n    }\n    CATCH_STD()\n    return false;\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/cpp/io_realm_internal_objectstore_OsObjectBuilder.cpp",
    "content": "/*\n * Copyright 2018 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#include \"io_realm_internal_objectstore_OsObjectBuilder.h\"\n\n#include \"java_object_accessor.hpp\"\n#include \"util.hpp\"\n\n#include <realm/util/any.hpp>\n\nusing namespace realm;\nusing namespace realm::jni_util;\nusing namespace realm::_impl;\n\ntypedef std::map<ColKey, JavaValue> OsObjectData;\n\nJNIEXPORT void JNICALL Java_io_realm_internal_objectstore_OsObjectBuilder_nativeDestroyBuilder(JNIEnv*, jclass, jlong data_ptr)\n{\n    delete reinterpret_cast<OsObjectData*>(data_ptr);\n}\n\nJNIEXPORT jlong JNICALL Java_io_realm_internal_objectstore_OsObjectBuilder_nativeCreateBuilder(JNIEnv* env, jclass)\n{\n    try {\n        auto map = new std::map<ColKey, JavaValue>();\n        return reinterpret_cast<jlong>(map);\n    }\n    CATCH_STD()\n    return -1;\n}\n\nstatic inline void add_property(jlong data_ptr, jlong column_key, JavaValue const& value)\n{\n    OsObjectData* data = reinterpret_cast<OsObjectData*>(data_ptr);\n    (*data)[ColKey(column_key)] = std::move(value);\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_objectstore_OsObjectBuilder_nativeAddNull\n        (JNIEnv* env, jclass, jlong data_ptr, jlong column_key)\n{\n    try {\n        const JavaValue value = JavaValue();\n        add_property(data_ptr, column_key, value);\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_objectstore_OsObjectBuilder_nativeAddString\n    (JNIEnv* env, jclass, jlong data_ptr, jlong column_key, jstring j_value)\n{\n    try {\n        JStringAccessor value(env, j_value);\n        std::string string_value(value);\n        const JavaValue wrapped_value(string_value);\n        add_property(data_ptr, column_key, wrapped_value);\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_objectstore_OsObjectBuilder_nativeAddInteger\n        (JNIEnv* env, jclass, jlong data_ptr, jlong column_key, jlong j_value)\n{\n    try {\n        const JavaValue value(j_value);\n        add_property(data_ptr, column_key, value);\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_objectstore_OsObjectBuilder_nativeAddFloat\n        (JNIEnv* env, jclass, jlong data_ptr, jlong column_key, jfloat j_value)\n{\n    try {\n        const JavaValue value(j_value);\n        add_property(data_ptr, column_key, value);\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_objectstore_OsObjectBuilder_nativeAddDouble\n        (JNIEnv* env, jclass, jlong data_ptr, jlong column_key, jdouble j_value)\n{\n    try {\n        const JavaValue value(j_value);\n        add_property(data_ptr, column_key, value);\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_objectstore_OsObjectBuilder_nativeAddBoolean\n        (JNIEnv* env, jclass, jlong data_ptr, jlong column_key, jboolean j_value)\n{\n    try {\n        const JavaValue value(j_value);\n        add_property(data_ptr, column_key, value);\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_objectstore_OsObjectBuilder_nativeAddByteArray\n        (JNIEnv* env, jclass, jlong data_ptr, jlong column_key, jbyteArray j_value)\n{\n    try {\n        auto data = OwnedBinaryData(JByteArrayAccessor(env, j_value).transform<BinaryData>());\n        const JavaValue value(data);\n        add_property(data_ptr, column_key, value);\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_objectstore_OsObjectBuilder_nativeAddDate\n        (JNIEnv* env, jclass, jlong data_ptr, jlong column_key, jlong j_value)\n{\n    try {\n        const JavaValue value(from_milliseconds(j_value));\n        add_property(data_ptr, column_key, value);\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_objectstore_OsObjectBuilder_nativeAddDecimal128\n        (JNIEnv* env, jclass, jlong data_ptr, jlong column_key, jlong j_low_value, jlong j_high_value)\n{\n    try {\n        Decimal128::Bid128 raw {static_cast<uint64_t>(j_low_value), static_cast<uint64_t>(j_high_value)};\n        Decimal128 decimal128 = Decimal128(raw);\n        const JavaValue value(decimal128);\n        add_property(data_ptr, column_key, value);\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_objectstore_OsObjectBuilder_nativeAddObjectId\n        (JNIEnv* env, jclass, jlong data_ptr, jlong column_key, jstring j_data)\n{\n    try {\n        JStringAccessor data(env, j_data);\n        ObjectId objectId = ObjectId(StringData(data).data());\n        const JavaValue value(objectId);\n        add_property(data_ptr, column_key, value);\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_objectstore_OsObjectBuilder_nativeAddUUID\n        (JNIEnv* env, jclass, jlong data_ptr, jlong column_key, jstring j_data)\n{\n    try {\n        JStringAccessor data(env, j_data);\n        UUID uuid = UUID(StringData(data).data());\n        const JavaValue value(uuid);\n        add_property(data_ptr, column_key, value);\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_objectstore_OsObjectBuilder_nativeAddRealmAny\n        (JNIEnv* env, jclass, jlong data_ptr, jlong column_key, jlong native_ptr)\n{\n    try {\n        auto java_value = reinterpret_cast<JavaValue*>(native_ptr);\n        const JavaValue value(java_value);\n        add_property(data_ptr, column_key, value);\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_objectstore_OsObjectBuilder_nativeAddObject\n        (JNIEnv* env, jclass, jlong data_ptr, jlong column_key, jlong row_ptr)\n{\n    try {\n        const JavaValue value(reinterpret_cast<Obj*>(row_ptr));\n        add_property(data_ptr, column_key, value);\n    }\n    CATCH_STD()\n}\n\nstatic inline const ObjectSchema& get_schema(const Schema& schema, TableRef table)\n{\n    std::string table_name(table->get_name());\n    std::string class_name = std::string(table_name.substr(TABLE_PREFIX.length()));\n    auto it = schema.find(class_name);\n    if (it == schema.end()) {\n        throw std::runtime_error(util::format(\"Class '%1' cannot be found in the schema.\", class_name.data()));\n    }\n    return *it;\n}\n\nJNIEXPORT jlong JNICALL Java_io_realm_internal_objectstore_OsObjectBuilder_nativeCreateOrUpdateTopLevelObject(JNIEnv* env,\n                                                                                                              jclass,\n                                                                                                              jlong shared_realm_ptr,\n                                                                                                              jlong table_ref_ptr,\n                                                                                                              jlong builder_ptr,\n                                                                                                              jboolean update_existing,\n                                                                                                              jboolean ignore_same_values)\n{\n    try {\n        SharedRealm shared_realm = *(reinterpret_cast<SharedRealm*>(shared_realm_ptr));\n\n        CreatePolicy policy = CreatePolicy::ForceCreate;\n        if (update_existing && ignore_same_values) {\n            policy = CreatePolicy::UpdateModified;\n        } else if (update_existing) {\n            policy = CreatePolicy::UpdateAll;\n        }\n\n        TableRef table = TBL_REF(table_ref_ptr);\n        const auto& schema = shared_realm->schema();\n        const ObjectSchema& object_schema = get_schema(schema, table);\n        JavaContext ctx(env, shared_realm, object_schema);\n        auto list = *reinterpret_cast<OsObjectData*>(builder_ptr);\n        JavaValue values = JavaValue(list);\n        Object obj = Object::create(ctx, shared_realm, object_schema, values, policy);\n        return reinterpret_cast<jlong>(new Obj(obj.get_obj()));\n    }\n    CATCH_STD()\n    return realm::npos;\n}\n\nJNIEXPORT jlong JNICALL Java_io_realm_internal_objectstore_OsObjectBuilder_nativeUpdateEmbeddedObject(JNIEnv* env,\n                                                                                                      jclass,\n                                                                                                      jlong shared_realm_ptr,\n                                                                                                      jlong table_ref_ptr,\n                                                                                                      jlong builder_ptr,\n                                                                                                      jlong j_obj_key,\n                                                                                                      jboolean ignore_same_values)\n{\n    try {\n        SharedRealm shared_realm = *(reinterpret_cast<SharedRealm*>(shared_realm_ptr));\n        CreatePolicy policy = (ignore_same_values) ? CreatePolicy::UpdateModified : CreatePolicy::UpdateAll;\n        TableRef table = TBL_REF(table_ref_ptr);\n        ObjKey embedded_object_key(j_obj_key);\n        const auto& schema = shared_realm->schema();\n        const ObjectSchema& object_schema = get_schema(schema, table);\n        JavaContext ctx(env, shared_realm, object_schema);\n        auto list = *reinterpret_cast<OsObjectData*>(builder_ptr);\n        JavaValue values = JavaValue(list);\n        Object obj = Object::create(ctx, shared_realm, object_schema, values, policy, embedded_object_key);\n        return reinterpret_cast<jlong>(new Obj(obj.get_obj()));\n    }\n    CATCH_STD()\n    return realm::npos;\n}\n\nJNIEXPORT jlong JNICALL Java_io_realm_internal_objectstore_OsObjectBuilder_nativeStartList\n        (JNIEnv* env, jclass, jlong list_size)\n{\n    try {\n        auto list = new std::vector<JavaValue>();\n        list->reserve(list_size);\n        return reinterpret_cast<jlong>(list);\n    }\n    CATCH_STD()\n    return realm::npos;\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_objectstore_OsObjectBuilder_nativeStopList\n        (JNIEnv* env, jclass, jlong data_ptr, jlong column_key, jlong list_ptr)\n{\n    try {\n        auto list = reinterpret_cast<std::vector<JavaValue>*>(list_ptr);\n        const JavaValue value((*list));\n        add_property(data_ptr, column_key, value);\n        delete list;\n    }\n    CATCH_STD()\n}\n\n\nJNIEXPORT void JNICALL Java_io_realm_internal_objectstore_OsObjectBuilder_nativeAddObjectList\n        (JNIEnv* env, jclass, jlong data_ptr, jlong column_key, jlongArray row_ptrs)\n{\n    try {\n        auto rows = JLongArrayAccessor(env, row_ptrs);\n        auto list = std::vector<JavaValue>();\n        list.reserve(rows.size());\n        for (jsize i = 0; i < rows.size(); ++i) {\n            auto item = JavaValue(reinterpret_cast<Obj*>(rows[i]));\n            list.push_back(item);\n        }\n        JavaValue value(list);\n        add_property(data_ptr, column_key, value);\n    }\n    CATCH_STD()\n}\n\nstatic inline void add_list_element(jlong list_ptr, JavaValue const& value)\n{\n    auto list = reinterpret_cast<std::vector<JavaValue>*>(list_ptr);\n    list->push_back(std::move(value));\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_objectstore_OsObjectBuilder_nativeAddNullListItem\n        (JNIEnv* env, jclass, jlong list_ptr)\n{\n    try {\n        const JavaValue value = JavaValue();\n        add_list_element(list_ptr, value);\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_objectstore_OsObjectBuilder_nativeAddIntegerListItem\n        (JNIEnv* env, jclass, jlong list_ptr, jlong j_value)\n{\n    try {\n        const JavaValue value(j_value);\n        add_list_element(list_ptr, value);\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_objectstore_OsObjectBuilder_nativeAddStringListItem\n    (JNIEnv* env, jclass, jlong list_ptr, jstring j_value)\n{\n    try {\n        JStringAccessor value(env, j_value);\n        std::string string_value(value);\n        const JavaValue wrapped_value(string_value);\n        add_list_element(list_ptr, wrapped_value);\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_objectstore_OsObjectBuilder_nativeAddFloatListItem\n        (JNIEnv* env, jclass, jlong list_ptr, jfloat j_value)\n{\n    try {\n        const JavaValue value(j_value);\n        add_list_element(list_ptr, value);\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_objectstore_OsObjectBuilder_nativeAddDoubleListItem\n        (JNIEnv* env, jclass, jlong list_ptr, jdouble j_value)\n{\n    try {\n        const JavaValue value(j_value);\n        add_list_element(list_ptr, value);\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_objectstore_OsObjectBuilder_nativeAddBooleanListItem\n        (JNIEnv* env, jclass, jlong list_ptr, jboolean j_value)\n{\n    try {\n        const JavaValue value(j_value);\n        add_list_element(list_ptr, value);\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_objectstore_OsObjectBuilder_nativeAddByteArrayListItem\n        (JNIEnv* env, jclass, jlong list_ptr, jbyteArray j_value)\n{\n    try {\n        auto data = OwnedBinaryData(JByteArrayAccessor(env, j_value).transform<BinaryData>());\n        const JavaValue value(data);\n        add_list_element(list_ptr, value);\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_objectstore_OsObjectBuilder_nativeAddDateListItem\n        (JNIEnv* env, jclass, jlong list_ptr, jlong j_value)\n{\n    try {\n        const JavaValue value(from_milliseconds(j_value));\n        add_list_element(list_ptr, value);\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_objectstore_OsObjectBuilder_nativeAddObjectListItem\n        (JNIEnv* env, jclass, jlong list_ptr, jlong row_ptr)\n{\n    try {\n        const JavaValue value(reinterpret_cast<Obj*>(row_ptr));\n        add_list_element(list_ptr, value);\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_objectstore_OsObjectBuilder_nativeAddDecimal128ListItem\n        (JNIEnv* env, jclass, jlong list_ptr, jlong j_low_value, jlong j_high_value)\n{\n    try {\n        Decimal128::Bid128 raw {static_cast<uint64_t>(j_low_value), static_cast<uint64_t>(j_high_value)};\n        Decimal128 decimal128 = Decimal128(raw);\n        const JavaValue value(decimal128);\n        add_list_element(list_ptr, value);\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_objectstore_OsObjectBuilder_nativeAddObjectIdListItem\n        (JNIEnv* env, jclass, jlong list_ptr, jstring j_data)\n{\n    try {\n        JStringAccessor data(env, j_data);\n        ObjectId objectId = ObjectId(StringData(data).data());\n        const JavaValue value(objectId);\n        add_list_element(list_ptr, value);\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_objectstore_OsObjectBuilder_nativeAddUUIDListItem\n        (JNIEnv* env, jclass, jlong list_ptr, jstring j_data)\n{\n    try {\n        JStringAccessor data(env, j_data);\n        UUID uuid = UUID(StringData(data).data());\n        const JavaValue value(uuid);\n        add_list_element(list_ptr, value);\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_objectstore_OsObjectBuilder_nativeAddRealmAnyListItem\n        (JNIEnv* env, jclass, jlong list_ptr, jlong mixed_ptr)\n{\n    try {\n        auto java_value = *reinterpret_cast<JavaValue *>(mixed_ptr);\n        add_list_element(list_ptr, java_value);\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT jlong JNICALL\nJava_io_realm_internal_objectstore_OsObjectBuilder_nativeStartDictionary(JNIEnv* env,\n                                                                         jclass) {\n    try {\n        auto dictionary = new std::map<std::string, JavaValue>();\n        return reinterpret_cast<jlong>(dictionary);\n    }\n    CATCH_STD()\n    return realm::npos;\n}\n\nJNIEXPORT void JNICALL\nJava_io_realm_internal_objectstore_OsObjectBuilder_nativeStopDictionary(JNIEnv* env, jclass,\n                                                                        jlong data_ptr,\n                                                                        jlong column_key,\n                                                                        jlong dictionary_ptr) {\n    try {\n        auto dictionary = reinterpret_cast<std::map<std::string, JavaValue>*>(dictionary_ptr);\n        const JavaValue value((*dictionary));\n        add_property(data_ptr, column_key, value);\n        delete dictionary;\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL\nJava_io_realm_internal_objectstore_OsObjectBuilder_nativeAddNullDictionaryEntry(JNIEnv *env,\n                                                                                jclass,\n                                                                                jlong dictionary_ptr,\n                                                                                jstring j_key) {\n    try {\n        auto dictionary = reinterpret_cast<std::map<std::string, JavaValue>*>(dictionary_ptr);\n        JStringAccessor key(env, j_key);\n        const JavaValue value = JavaValue();\n        dictionary->insert(std::make_pair(key, value));\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL\nJava_io_realm_internal_objectstore_OsObjectBuilder_nativeAddBooleanDictionaryEntry(JNIEnv* env,\n                                                                                   jclass,\n                                                                                   jlong dictionary_ptr,\n                                                                                   jstring j_key,\n                                                                                   jboolean j_value) {\n    try {\n        auto dictionary = reinterpret_cast<std::map<std::string, JavaValue>*>(dictionary_ptr);\n        JStringAccessor key(env, j_key);\n        const JavaValue value(j_value);\n        dictionary->insert(std::make_pair(key, value));\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL\nJava_io_realm_internal_objectstore_OsObjectBuilder_nativeAddStringDictionaryEntry(JNIEnv* env,\n                                                                                  jclass,\n                                                                                  jlong dictionary_ptr,\n                                                                                  jstring j_key,\n                                                                                  jstring j_value) {\n    try {\n        auto dictionary = reinterpret_cast<std::map<std::string, JavaValue>*>(dictionary_ptr);\n        JStringAccessor key(env, j_key);\n        JStringAccessor value(env, j_value);\n        JavaValue java_value(value);\n        dictionary->insert(std::make_pair(key, value));\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL\nJava_io_realm_internal_objectstore_OsObjectBuilder_nativeAddIntegerDictionaryEntry(JNIEnv* env,\n                                                                                   jclass,\n                                                                                   jlong dictionary_ptr,\n                                                                                   jstring j_key,\n                                                                                   jlong j_value) {\n    try {\n        auto dictionary = reinterpret_cast<std::map<std::string, JavaValue>*>(dictionary_ptr);\n        JStringAccessor key(env, j_key);\n        const JavaValue value(j_value);\n        dictionary->insert(std::make_pair(key, value));\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL\nJava_io_realm_internal_objectstore_OsObjectBuilder_nativeAddDoubleDictionaryEntry(JNIEnv* env,\n                                                                                  jclass,\n                                                                                  jlong dictionary_ptr,\n                                                                                  jstring j_key,\n                                                                                  jdouble j_value) {\n    try {\n        auto dictionary = reinterpret_cast<std::map<std::string, JavaValue>*>(dictionary_ptr);\n        JStringAccessor key(env, j_key);\n        const JavaValue value(j_value);\n        dictionary->insert(std::make_pair(key, value));\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL\nJava_io_realm_internal_objectstore_OsObjectBuilder_nativeAddFloatDictionaryEntry(JNIEnv* env,\n                                                                                 jclass,\n                                                                                 jlong dictionary_ptr,\n                                                                                 jstring j_key,\n                                                                                 jfloat j_value) {\n    try {\n        auto dictionary = reinterpret_cast<std::map<std::string, JavaValue>*>(dictionary_ptr);\n        JStringAccessor key(env, j_key);\n        const JavaValue value(j_value);\n        dictionary->insert(std::make_pair(key, value));\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL\nJava_io_realm_internal_objectstore_OsObjectBuilder_nativeAddBinaryDictionaryEntry(JNIEnv* env,\n                                                                                  jclass,\n                                                                                  jlong dictionary_ptr,\n                                                                                  jstring j_key,\n                                                                                  jbyteArray j_value) {\n    try {\n        auto dictionary = reinterpret_cast<std::map<std::string, JavaValue>*>(dictionary_ptr);\n        JStringAccessor key(env, j_key);\n        auto data = OwnedBinaryData(JByteArrayAccessor(env, j_value).transform<BinaryData>());\n        const JavaValue value(data);\n        dictionary->insert(std::make_pair(key, value));\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL\nJava_io_realm_internal_objectstore_OsObjectBuilder_nativeAddDateDictionaryEntry(JNIEnv* env,\n                                                                                jclass,\n                                                                                jlong dictionary_ptr,\n                                                                                jstring j_key,\n                                                                                jlong j_value) {\n    try {\n        auto dictionary = reinterpret_cast<std::map<std::string, JavaValue>*>(dictionary_ptr);\n        JStringAccessor key(env, j_key);\n        const JavaValue value(from_milliseconds(j_value));\n        dictionary->insert(std::make_pair(key, value));\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL\nJava_io_realm_internal_objectstore_OsObjectBuilder_nativeAddDecimal128DictionaryEntry(JNIEnv* env,\n                                                                                      jclass,\n                                                                                      jlong dictionary_ptr,\n                                                                                      jstring j_key,\n                                                                                      jlong j_high_value,\n                                                                                      jlong j_low_value) {\n    try {\n        auto dictionary = reinterpret_cast<std::map<std::string, JavaValue>*>(dictionary_ptr);\n\n        JStringAccessor key(env, j_key);\n\n        Decimal128::Bid128 raw {static_cast<uint64_t>(j_low_value), static_cast<uint64_t>(j_high_value)};\n        auto decimal128 = Decimal128(raw);\n        const JavaValue value(decimal128);\n\n        dictionary->insert(std::make_pair(key, value));\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL\nJava_io_realm_internal_objectstore_OsObjectBuilder_nativeAddObjectIdDictionaryEntry(JNIEnv* env,\n                                                                                    jclass,\n                                                                                    jlong dictionary_ptr,\n                                                                                    jstring j_key,\n                                                                                    jstring j_value) {\n    try {\n        auto dictionary = reinterpret_cast<std::map<std::string, JavaValue>*>(dictionary_ptr);\n\n        JStringAccessor key(env, j_key);\n        JStringAccessor data(env, j_value);\n\n        const ObjectId object_id = ObjectId(StringData(data).data());\n        const JavaValue object_id_value(object_id);\n\n        dictionary->insert(std::make_pair(key, object_id_value));\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL\nJava_io_realm_internal_objectstore_OsObjectBuilder_nativeAddUUIDDictionaryEntry(JNIEnv* env,\n                                                                                jclass,\n                                                                                jlong dictionary_ptr,\n                                                                                jstring j_key,\n                                                                                jstring j_value) {\n    try {\n        auto dictionary = reinterpret_cast<std::map<std::string, JavaValue>*>(dictionary_ptr);\n\n        JStringAccessor key(env, j_key);\n        JStringAccessor data(env, j_value);\n\n        const UUID uuid = UUID(StringData(data).data());\n        const JavaValue uuid_value(uuid);\n\n        dictionary->insert(std::make_pair(key, uuid_value));\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL\nJava_io_realm_internal_objectstore_OsObjectBuilder_nativeAddObjectDictionaryEntry(JNIEnv* env,\n                                                                                jclass,\n                                                                                jlong dictionary_ptr,\n                                                                                jstring j_key,\n                                                                                jlong j_value) {\n    try {\n        auto dictionary = reinterpret_cast<std::map<std::string, JavaValue>*>(dictionary_ptr);\n        JStringAccessor key(env, j_key);\n        dictionary->insert(std::make_pair(key, JavaValue(reinterpret_cast<Obj*>(j_value))));\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL\nJava_io_realm_internal_objectstore_OsObjectBuilder_nativeAddRealmAnyDictionaryEntry(JNIEnv* env,\n                                                                                 jclass,\n                                                                                 jlong dictionary_ptr,\n                                                                                 jstring j_key,\n                                                                                 jlong mixed_ptr) {\n    try {\n        auto dictionary = reinterpret_cast<std::map<std::string, JavaValue>*>(dictionary_ptr);\n        auto mixed_java_value = *reinterpret_cast<JavaValue *>(mixed_ptr);\n\n        JStringAccessor key(env, j_key);\n\n        dictionary->insert(std::make_pair(key, std::move(mixed_java_value)));\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT jlong JNICALL\nJava_io_realm_internal_objectstore_OsObjectBuilder_nativeStartSet(JNIEnv* env,\n                                                                  jclass,\n                                                                  jlong j_size) {\n    try {\n        auto set_as_list = new std::vector<JavaValue>();\n        set_as_list->reserve(j_size);\n        return reinterpret_cast<jlong>(set_as_list);\n    }\n    CATCH_STD()\n    return realm::npos;\n}\n\nJNIEXPORT void JNICALL\nJava_io_realm_internal_objectstore_OsObjectBuilder_nativeStopSet(JNIEnv* env,\n                                                                 jclass,\n                                                                 jlong data_ptr,\n                                                                 jlong column_key,\n                                                                 jlong set_ptr) {\n    try {\n        auto set_as_list = reinterpret_cast<std::vector<JavaValue>*>(set_ptr);\n        const JavaValue value((*set_as_list));\n        add_property(data_ptr, column_key, value);\n        delete set_as_list;\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL\nJava_io_realm_internal_objectstore_OsObjectBuilder_nativeAddNullSetItem(JNIEnv* env,\n                                                                        jclass,\n                                                                        jlong set_ptr) {\n    try {\n        const JavaValue value = JavaValue();\n        add_list_element(set_ptr, value);\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL\nJava_io_realm_internal_objectstore_OsObjectBuilder_nativeAddStringSetItem(JNIEnv* env,\n                                                                          jclass,\n                                                                          jlong set_ptr,\n                                                                          jstring j_value) {\n    try {\n        JStringAccessor value(env, j_value);\n        std::string string_value(value);\n        const JavaValue wrapped_value(string_value);\n        add_list_element(set_ptr, wrapped_value);\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL\nJava_io_realm_internal_objectstore_OsObjectBuilder_nativeAddBooleanSetItem(JNIEnv* env,\n                                                                           jclass,\n                                                                           jlong set_ptr,\n                                                                           jboolean j_value) {\n    try {\n        const JavaValue wrapped_value(j_value);\n        add_list_element(set_ptr, wrapped_value);\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL\nJava_io_realm_internal_objectstore_OsObjectBuilder_nativeAddIntegerSetItem(JNIEnv* env,\n                                                                           jclass,\n                                                                           jlong set_ptr,\n                                                                           jlong j_value) {\n    try {\n        const JavaValue value(j_value);\n        add_list_element(set_ptr, value);\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL\nJava_io_realm_internal_objectstore_OsObjectBuilder_nativeAddFloatSetItem(JNIEnv* env,\n                                                                         jclass,\n                                                                         jlong set_ptr,\n                                                                         jfloat j_value) {\n    try {\n        const JavaValue value(j_value);\n        add_list_element(set_ptr, value);\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL\nJava_io_realm_internal_objectstore_OsObjectBuilder_nativeAddDoubleSetItem(JNIEnv* env,\n                                                                          jclass,\n                                                                          jlong set_ptr,\n                                                                          jdouble j_value) {\n    try {\n        const JavaValue value(j_value);\n        add_list_element(set_ptr, value);\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL\nJava_io_realm_internal_objectstore_OsObjectBuilder_nativeAddByteArraySetItem(JNIEnv* env,\n                                                                             jclass,\n                                                                             jlong set_ptr,\n                                                                             jbyteArray j_value) {\n    try {\n        auto data = OwnedBinaryData(JByteArrayAccessor(env, j_value).transform<BinaryData>());\n        const JavaValue value(data);\n        add_list_element(set_ptr, value);\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL\nJava_io_realm_internal_objectstore_OsObjectBuilder_nativeAddDateSetItem(JNIEnv* env,\n                                                                        jclass,\n                                                                        jlong set_ptr,\n                                                                        jlong j_value) {\n    try {\n        const JavaValue value(from_milliseconds(j_value));\n        add_list_element(set_ptr, value);\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL\nJava_io_realm_internal_objectstore_OsObjectBuilder_nativeAddDecimal128SetItem(JNIEnv* env,\n                                                                              jclass,\n                                                                              jlong set_ptr,\n                                                                              jlong j_low_value,\n                                                                              jlong j_high_value) {\n    try {\n        Decimal128::Bid128 raw {static_cast<uint64_t>(j_low_value), static_cast<uint64_t>(j_high_value)};\n        Decimal128 decimal128 = Decimal128(raw);\n        const JavaValue value(decimal128);\n        add_list_element(set_ptr, value);\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL\nJava_io_realm_internal_objectstore_OsObjectBuilder_nativeAddObjectIdSetItem(JNIEnv* env,\n                                                                            jclass,\n                                                                            jlong set_ptr,\n                                                                            jstring j_value) {\n    try {\n        JStringAccessor data(env, j_value);\n        ObjectId objectId = ObjectId(StringData(data).data());\n        const JavaValue value(objectId);\n        add_list_element(set_ptr, value);\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL\nJava_io_realm_internal_objectstore_OsObjectBuilder_nativeAddUUIDSetItem(JNIEnv* env,\n                                                                        jclass,\n                                                                        jlong set_ptr,\n                                                                        jstring j_value) {\n    try {\n        JStringAccessor data(env, j_value);\n        UUID uuid = UUID(StringData(data).data());\n        const JavaValue value(uuid);\n        add_list_element(set_ptr, value);\n    }\n    CATCH_STD()\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/cpp/io_realm_internal_objectstore_OsPush.cpp",
    "content": "/*\n * Copyright 2020 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#include \"io_realm_internal_objectstore_OsPush.h\"\n\n#include \"java_class_global_def.hpp\"\n#include \"java_network_transport.hpp\"\n#include \"util.hpp\"\n#include \"jni_util/java_method.hpp\"\n#include \"jni_util/jni_utils.hpp\"\n\n#include <realm/util/optional.hpp>\n#include <realm/object-store/sync/app.hpp>\n#include <jni.h>\n\nusing namespace realm;\nusing namespace realm::app;\nusing namespace realm::bson;\nusing namespace realm::jni_util;\nusing namespace realm::_impl;\n\nstatic void finalize_push_client(jlong ptr) {\n    delete reinterpret_cast<PushClient*>(ptr);\n}\n\nJNIEXPORT jlong JNICALL\nJava_io_realm_internal_objectstore_OsPush_nativeGetFinalizerMethodPtr(JNIEnv*, jclass) {\n    return reinterpret_cast<jlong>(&finalize_push_client);\n}\n\nJNIEXPORT jlong JNICALL\nJava_io_realm_internal_objectstore_OsPush_nativeCreate(JNIEnv* env,\n                                                       jclass,\n                                                       jlong j_app_ptr,\n                                                       jstring j_service_name) {\n    try {\n        std::shared_ptr<App> &app = *reinterpret_cast<std::shared_ptr<App> *>(j_app_ptr);\n        JStringAccessor service_name(env, j_service_name);\n        PushClient client(app->push_notification_client(service_name));\n        return reinterpret_cast<jlong>(new PushClient(std::move(client)));\n    }\n    CATCH_STD()\n    return reinterpret_cast<jlong>(nullptr);\n}\n\nJNIEXPORT void JNICALL\nJava_io_realm_internal_objectstore_OsPush_nativeRegisterDevice(JNIEnv *env,\n                                                               jclass,\n                                                               jlong j_push_client_ptr,\n                                                               jlong j_user_ptr,\n                                                               jstring j_service_name,\n                                                               jstring j_registration_token,\n                                                               jobject j_callback) {\n    try {\n        auto push_client = reinterpret_cast<PushClient*>(j_push_client_ptr);\n        auto user = *reinterpret_cast<std::shared_ptr<SyncUser>*>(j_user_ptr);\n\n        JStringAccessor service_name(env, j_service_name);\n        JStringAccessor registration_token(env, j_registration_token);\n\n        push_client->register_device(registration_token,\n                                     user,\n                                     JavaNetworkTransport::create_void_callback(env, j_callback));\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL\nJava_io_realm_internal_objectstore_OsPush_nativeDeregisterDevice(JNIEnv *env,\n                                                               jclass,\n                                                               jlong j_push_client_ptr,\n                                                               jlong j_user_ptr,\n                                                               jstring j_service_name,\n                                                               jobject j_callback) {\n    try {\n        auto push_client = reinterpret_cast<PushClient*>(j_push_client_ptr);\n        auto user = *reinterpret_cast<std::shared_ptr<SyncUser>*>(j_user_ptr);\n\n        JStringAccessor service_name(env, j_service_name);\n\n        push_client->deregister_device(user,\n                                       JavaNetworkTransport::create_void_callback(env, j_callback));\n    }\n    CATCH_STD()\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/cpp/io_realm_internal_objectstore_OsSubscription.cpp",
    "content": "/*\n * Copyright 2022 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#include \"io_realm_internal_objectstore_OsSubscription.h\"\n\n#include \"java_network_transport.hpp\"\n#include \"util.hpp\"\n#include \"jni_util/java_method.hpp\"\n#include \"jni_util/jni_utils.hpp\"\n\n#include <realm/object-store/shared_realm.hpp>\n#include <realm/sync/binding_callback_thread_observer.hpp>\n#include <realm/object-store/sync/app.hpp>\n#include <realm/object-store/sync/sync_manager.hpp>\n#include <realm/sync/subscriptions.hpp>\n\n#include <jni_util/bson_util.hpp>\n\nusing namespace realm;\nusing namespace realm::app;\nusing namespace realm::jni_util;\nusing namespace realm::_impl;\n\nstatic void finalize_subscription(jlong ptr) {\n    delete reinterpret_cast<sync::Subscription*>(ptr);\n}\n\nJNIEXPORT jlong JNICALL\nJava_io_realm_internal_objectstore_OsSubscription_nativeGetFinalizerMethodPtr(JNIEnv*, jclass) {\n    return reinterpret_cast<jlong>(&finalize_subscription);\n}\n\nJNIEXPORT jstring JNICALL Java_io_realm_internal_objectstore_OsSubscription_nativeName(JNIEnv* env,\n                                                                                              jclass,\n                                                                                              jlong j_subscription_ptr)\n{\n    try {\n        auto sub = reinterpret_cast<sync::Subscription*>(j_subscription_ptr);\n        return to_jstring(env, sub->name);\n    }\n    CATCH_STD()\n    return nullptr;\n}\n\nJNIEXPORT jstring JNICALL Java_io_realm_internal_objectstore_OsSubscription_nativeObjectClassName(JNIEnv* env,\n                                                                                       jclass,\n                                                                                       jlong j_subscription_ptr)\n{\n    try {\n        auto sub = reinterpret_cast<sync::Subscription*>(j_subscription_ptr);\n        return to_jstring(env, sub->object_class_name);\n    }\n    CATCH_STD()\n    return nullptr;\n}\n\nJNIEXPORT jstring JNICALL Java_io_realm_internal_objectstore_OsSubscription_nativeQueryString(JNIEnv* env,\n                                                                                                  jclass,\n                                                                                                  jlong j_subscription_ptr)\n{\n    try {\n        auto sub = reinterpret_cast<sync::Subscription*>(j_subscription_ptr);\n        return to_jstring(env, sub->query_string);\n    }\n    CATCH_STD()\n    return nullptr;\n}\n\nJNIEXPORT jlong JNICALL Java_io_realm_internal_objectstore_OsSubscription_nativeCreatedAt(JNIEnv* env,\n                                                                                              jclass,\n                                                                                              jlong j_subscription_ptr)\n{\n    try {\n        auto sub = reinterpret_cast<sync::Subscription*>(j_subscription_ptr);\n        return to_milliseconds(sub->created_at);\n    }\n    CATCH_STD()\n    return 0;\n}\n\nJNIEXPORT jlong JNICALL Java_io_realm_internal_objectstore_OsSubscription_nativeUpdatedAt(JNIEnv* env,\n                                                                                            jclass,\n                                                                                            jlong j_subscription_ptr)\n{\n    try {\n        auto sub = reinterpret_cast<sync::Subscription*>(j_subscription_ptr);\n        return to_milliseconds(sub->updated_at);\n    }\n    CATCH_STD()\n    return 0;\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/cpp/io_realm_internal_objectstore_OsSubscriptionSet.cpp",
    "content": "/*\n * Copyright 2022 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#include \"io_realm_internal_objectstore_OsSubscriptionSet.h\"\n\n#include \"java_network_transport.hpp\"\n#include \"util.hpp\"\n#include \"jni_util/java_global_weak_ref.hpp\"\n#include \"jni_util/java_method.hpp\"\n#include \"jni_util/jni_utils.hpp\"\n\n#include <realm/object-store/shared_realm.hpp>\n#include <realm/sync/binding_callback_thread_observer.hpp>\n#include <realm/object-store/sync/app.hpp>\n#include <realm/object-store/sync/sync_manager.hpp>\n#include <realm/sync/subscriptions.hpp>\n\n#include <jni_util/bson_util.hpp>\n\nusing namespace realm;\nusing namespace realm::app;\nusing namespace realm::jni_util;\nusing namespace realm::_impl;\n\nstatic void finalize_subscription_set(jlong ptr) {\n    delete reinterpret_cast<sync::SubscriptionSet*>(ptr);\n}\n\nJNIEXPORT jlong JNICALL\nJava_io_realm_internal_objectstore_OsSubscriptionSet_nativeGetFinalizerMethodPtr(JNIEnv*, jclass) {\n    return reinterpret_cast<jlong>(&finalize_subscription_set);\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_objectstore_OsSubscriptionSet_nativeRelease(JNIEnv*, jclass, jlong j_subscription_set_ptr) {\n    delete reinterpret_cast<sync::SubscriptionSet*>(j_subscription_set_ptr);\n}\n\nJNIEXPORT jlong JNICALL Java_io_realm_internal_objectstore_OsSubscriptionSet_nativeSize(JNIEnv* env, jclass, jlong j_subscription_set_ptr)\n{\n    try {\n        auto subscriptions = reinterpret_cast<sync::SubscriptionSet*>(j_subscription_set_ptr);\n        return subscriptions->size();\n    }\n    CATCH_STD()\n    return 0;\n}\n\nJNIEXPORT jbyte JNICALL Java_io_realm_internal_objectstore_OsSubscriptionSet_nativeState(JNIEnv* env, jclass, jlong j_subscription_set_ptr)\n{\n    try {\n        auto subscriptions = reinterpret_cast<sync::SubscriptionSet*>(j_subscription_set_ptr);\n        sync::SubscriptionSet::State state = subscriptions->state();\n        switch(state) {\n            case sync::SubscriptionSet::State::Uncommitted:\n                return io_realm_internal_objectstore_OsSubscriptionSet_STATE_VALUE_UNCOMMITTED;\n            case sync::SubscriptionSet::State::Pending:\n                return io_realm_internal_objectstore_OsSubscriptionSet_STATE_VALUE_PENDING;\n            case sync::SubscriptionSet::State::Bootstrapping:\n                return io_realm_internal_objectstore_OsSubscriptionSet_STATE_VALUE_BOOTSTRAPPING;\n            case sync::SubscriptionSet::State::Complete:\n                return io_realm_internal_objectstore_OsSubscriptionSet_STATE_VALUE_COMPLETE;\n            case sync::SubscriptionSet::State::Error:\n                return io_realm_internal_objectstore_OsSubscriptionSet_STATE_VALUE_ERROR;\n            case sync::SubscriptionSet::State::Superseded:\n                return io_realm_internal_objectstore_OsSubscriptionSet_STATE_VALUE_SUPERSEDED;\n            case sync::SubscriptionSet::State::AwaitingMark:\n                return io_realm_internal_objectstore_OsSubscriptionSet_STATE_VALUE_AWAITING_MARK;\n        }\n    }\n    CATCH_STD()\n    return 0;\n}\n\nJNIEXPORT jlong JNICALL Java_io_realm_internal_objectstore_OsSubscriptionSet_nativeCreateMutableSubscriptionSet(JNIEnv* env, jclass, jlong j_subscription_set_ptr)\n{\n    try {\n        auto subscriptions = reinterpret_cast<sync::SubscriptionSet*>(j_subscription_set_ptr);\n        return reinterpret_cast<jlong>(new sync::MutableSubscriptionSet(subscriptions->make_mutable_copy()));\n    }\n    CATCH_STD()\n    return 0;\n}\n\nJNIEXPORT jlong JNICALL Java_io_realm_internal_objectstore_OsSubscriptionSet_nativeSubscriptionAt(JNIEnv *env, jclass,\n                                                                          jlong j_subscription_set_ptr,\n                                                                          jint j_index)\n{\n    try {\n        auto subscriptions = reinterpret_cast<sync::SubscriptionSet*>(j_subscription_set_ptr);\n        return reinterpret_cast<jlong>(new sync::Subscription(subscriptions->at(j_index)));\n    }\n    CATCH_STD()\n    return 0;\n}\n\nJNIEXPORT void JNICALL Java_io_realm_internal_objectstore_OsSubscriptionSet_nativeWaitForSynchronization(JNIEnv *env,\n                                                                                  jclass,\n                                                                                  jlong j_subscription_set_ptr,\n                                                                                  jobject j_callback)\n{\n    try {\n        auto subscriptions = reinterpret_cast<sync::SubscriptionSet *>(j_subscription_set_ptr);\n        util::Future<sync::SubscriptionSet::State> result = subscriptions->get_state_change_notification(\n                sync::SubscriptionSet::State::Complete);\n\n        static JavaClass callback_class(env, \"io/realm/internal/objectstore/OsSubscriptionSet$StateChangeCallback\");\n        static JavaMethod onchange_method(env, callback_class, \"onChange\", \"(B)V\", false);\n        JavaGlobalWeakRef j_callback_weak(env, j_callback);\n        std::move(result).get_async([j_callback_weak](StatusOrStatusWith<sync::SubscriptionSet::State> status) noexcept {\n            JNIEnv* env = JniUtils::get_env(true);\n            j_callback_weak.call_with_local_ref(env, [&](JNIEnv* env, jobject obj) {\n                if (status.is_ok()) {\n                    env->CallVoidMethod(obj, onchange_method, static_cast<jbyte>(status.get_value()));\n                } else {\n                    env->CallVoidMethod(obj, onchange_method, static_cast<jbyte>(sync::SubscriptionSet::State::Error));\n                }\n            });\n        });\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT jlong JNICALL\nJava_io_realm_internal_objectstore_OsSubscriptionSet_nativeFindByName(JNIEnv *env, jclass,\n                                                                      jlong j_subscription_set_ptr,\n                                                                      jstring j_name)\n{\n    try {\n        auto subscriptions = reinterpret_cast<sync::SubscriptionSet*>(j_subscription_set_ptr);\n        JStringAccessor name(env, j_name);\n        const sync::Subscription* subscription = subscriptions->find(name);\n        if (subscription != nullptr) {\n            return reinterpret_cast<jlong>(new sync::Subscription(std::move(*subscription)));\n        } else {\n            return -1;\n        }\n    }\n    CATCH_STD()\n    return 0;\n}\n\nJNIEXPORT jlong JNICALL Java_io_realm_internal_objectstore_OsSubscriptionSet_nativeFindByQuery(JNIEnv *env, jclass,\n                                                                       jlong j_subscription_set_ptr,\n                                                                       jlong j_query_ptr)\n{\n    try {\n        auto subscriptions = reinterpret_cast<sync::SubscriptionSet*>(j_subscription_set_ptr);\n        auto query = reinterpret_cast<Query*>(j_query_ptr);\n        const sync::Subscription* subscription = subscriptions->find(*query);\n        if (subscription != nullptr) {\n            return reinterpret_cast<jlong>(new sync::Subscription(std::move(*subscription)));\n        } else {\n            return -1;\n        }\n    }\n    CATCH_STD()\n    return 0;\n}\n\nJNIEXPORT jstring JNICALL Java_io_realm_internal_objectstore_OsSubscriptionSet_nativeErrorMessage(JNIEnv *env, jclass,\n                                                                        jlong j_subscription_set_ptr)\n{\n    try {\n        auto subscriptions = reinterpret_cast<sync::SubscriptionSet*>(j_subscription_set_ptr);\n        return to_jstring(env, subscriptions->error_str());\n    }\n    CATCH_STD()\n    return nullptr;\n}\n\nJNIEXPORT void JNICALL\nJava_io_realm_internal_objectstore_OsSubscriptionSet_nativeRefresh(JNIEnv *env, jclass, jlong j_subscription_set_ptr) {\n    try {\n        auto subscriptions = reinterpret_cast<sync::SubscriptionSet *>(j_subscription_set_ptr);\n        subscriptions->refresh();\n    }\n    CATCH_STD()\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/cpp/io_realm_internal_objectstore_OsSyncUser.cpp",
    "content": "/*\n * Copyright 2020 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#include \"io_realm_internal_objectstore_OsSyncUser.h\"\n\n#include \"java_class_global_def.hpp\"\n#include \"util.hpp\"\n#include \"jni_util/java_class.hpp\"\n#include \"java_network_transport.hpp\"\n\n#include <realm/object-store/sync/sync_user.hpp>\n#include <realm/util/bson/bson.hpp>\n#include <jni_util/bson_util.hpp>\n\nusing namespace realm;\nusing namespace realm::_impl;\nusing namespace realm::jni_util;\nusing namespace realm::util;\n\nstatic void finalize_user(jlong ptr)\n{\n    delete reinterpret_cast<std::shared_ptr<SyncUser>*>(ptr);\n}\n\nJNIEXPORT jlong JNICALL Java_io_realm_internal_objectstore_OsSyncUser_nativeGetFinalizerMethodPtr(JNIEnv*, jclass)\n{\n    return reinterpret_cast<jlong>(&finalize_user);\n}\n\nJNIEXPORT jstring JNICALL Java_io_realm_internal_objectstore_OsSyncUser_nativeGetName(JNIEnv* env, jclass, jlong j_native_ptr)\n{\n    try {\n        auto user = *reinterpret_cast<std::shared_ptr<SyncUser>*>(j_native_ptr);\n        return to_jstring(env, user->user_profile().name());\n    }\n    CATCH_STD();\n    return nullptr;\n}\n\nJNIEXPORT jstring JNICALL Java_io_realm_internal_objectstore_OsSyncUser_nativeGetEmail(JNIEnv* env, jclass, jlong j_native_ptr)\n{\n    try {\n        auto user = *reinterpret_cast<std::shared_ptr<SyncUser>*>(j_native_ptr);\n        return to_jstring(env, user->user_profile().email());\n    }\n    CATCH_STD();\n    return nullptr;\n}\n\nJNIEXPORT jstring JNICALL Java_io_realm_internal_objectstore_OsSyncUser_nativeGetPictureUrl(JNIEnv* env, jclass, jlong j_native_ptr)\n{\n    try {\n        auto user = *reinterpret_cast<std::shared_ptr<SyncUser>*>(j_native_ptr);\n        return to_jstring(env, user->user_profile().picture_url());\n    }\n    CATCH_STD();\n    return nullptr;\n}\n\nJNIEXPORT jstring JNICALL Java_io_realm_internal_objectstore_OsSyncUser_nativeGetFirstName(JNIEnv* env, jclass, jlong j_native_ptr)\n{\n    try {\n        auto user = *reinterpret_cast<std::shared_ptr<SyncUser>*>(j_native_ptr);\n        return to_jstring(env, user->user_profile().first_name());\n    }\n    CATCH_STD();\n    return nullptr;\n}\n\nJNIEXPORT jstring JNICALL Java_io_realm_internal_objectstore_OsSyncUser_nativeGetLastName(JNIEnv* env, jclass, jlong j_native_ptr)\n{\n    try {\n        auto user = *reinterpret_cast<std::shared_ptr<SyncUser>*>(j_native_ptr);\n        return to_jstring(env, user->user_profile().last_name());\n    }\n    CATCH_STD();\n    return nullptr;\n}\n\nJNIEXPORT jstring JNICALL Java_io_realm_internal_objectstore_OsSyncUser_nativeGetGender(JNIEnv* env, jclass, jlong j_native_ptr)\n{\n    try {\n        auto user = *reinterpret_cast<std::shared_ptr<SyncUser>*>(j_native_ptr);\n        return to_jstring(env, user->user_profile().gender());\n    }\n    CATCH_STD();\n    return nullptr;\n}\n\nJNIEXPORT jstring JNICALL Java_io_realm_internal_objectstore_OsSyncUser_nativeGetBirthday(JNIEnv* env, jclass, jlong j_native_ptr)\n{\n    try {\n        auto user = *reinterpret_cast<std::shared_ptr<SyncUser>*>(j_native_ptr);\n        return to_jstring(env, user->user_profile().birthday());\n    }\n    CATCH_STD();\n    return nullptr;\n}\n\nJNIEXPORT jstring JNICALL Java_io_realm_internal_objectstore_OsSyncUser_nativeGetMinAge(JNIEnv* env, jclass, jlong j_native_ptr)\n{\n    try {\n        auto user = *reinterpret_cast<std::shared_ptr<SyncUser>*>(j_native_ptr);\n        return to_jstring(env, user->user_profile().min_age());\n    }\n    CATCH_STD();\n    return nullptr;\n}\n\nJNIEXPORT jstring JNICALL Java_io_realm_internal_objectstore_OsSyncUser_nativeGetMaxAge(JNIEnv* env, jclass, jlong j_native_ptr)\n{\n    try {\n        auto user = *reinterpret_cast<std::shared_ptr<SyncUser>*>(j_native_ptr);\n        return to_jstring(env, user->user_profile().max_age());\n    }\n    CATCH_STD();\n    return nullptr;\n}\n\nJNIEXPORT jstring JNICALL Java_io_realm_internal_objectstore_OsSyncUser_nativeGetAccessToken(JNIEnv* env, jclass, jlong j_native_ptr)\n{\n    try {\n        auto user = *reinterpret_cast<std::shared_ptr<SyncUser>*>(j_native_ptr);\n        std::string token = user->access_token();\n        return to_jstring(env, token);\n    }\n    CATCH_STD();\n    return nullptr;\n}\n\nJNIEXPORT jstring JNICALL Java_io_realm_internal_objectstore_OsSyncUser_nativeGetRefreshToken(JNIEnv* env, jclass, jlong j_native_ptr)\n{\n    try {\n        auto user = *reinterpret_cast<std::shared_ptr<SyncUser>*>(j_native_ptr);\n        std::string token = user->refresh_token();\n        return to_jstring(env, token);\n    }\n    CATCH_STD();\n    return nullptr;\n}\n\nJNIEXPORT jobjectArray JNICALL Java_io_realm_internal_objectstore_OsSyncUser_nativeGetIdentities(JNIEnv* env, jclass, jlong j_native_ptr)\n{\n    try {\n        auto user = *reinterpret_cast<std::shared_ptr<SyncUser>*>(j_native_ptr);\n        std::vector<SyncUserIdentity> ids = user->identities();\n        jobjectArray arr = env->NewObjectArray(ids.size()*2, JavaClassGlobalDef::java_lang_string(), 0);\n        if (arr == NULL) {\n            ThrowException(env, OutOfMemory, \"Could not allocate memory to return identites\");\n            return NULL;\n        }\n        int j = 0;\n        for(size_t i = 0; i < ids.size(); ++i) {\n            SyncUserIdentity id = ids[i];\n            env->SetObjectArrayElement( arr, j, to_jstring(env, id.id));\n            env->SetObjectArrayElement( arr, j+1, to_jstring(env, id.provider_type));\n            j = j+2;\n        }\n        return arr;\n    }\n    CATCH_STD();\n    return nullptr;\n}\n\nJNIEXPORT jstring JNICALL Java_io_realm_internal_objectstore_OsSyncUser_nativeGetIdentity(JNIEnv* env, jclass, jlong j_native_ptr)\n{\n    try {\n        auto user = *reinterpret_cast<std::shared_ptr<SyncUser>*>(j_native_ptr);\n        return to_jstring(env, user->identity());\n    }\n    CATCH_STD();\n    return nullptr;\n}\n\nJNIEXPORT jbyte JNICALL Java_io_realm_internal_objectstore_OsSyncUser_nativeGetState(JNIEnv* env, jclass, jlong j_native_ptr)\n{\n    try {\n        auto user = *reinterpret_cast<std::shared_ptr<SyncUser>*>(j_native_ptr);\n        switch(user->state()) {\n            case SyncUser::State::LoggedOut: return static_cast<jbyte>(io_realm_internal_objectstore_OsSyncUser_STATE_LOGGED_OUT);\n            case SyncUser::State::LoggedIn:  return static_cast<jbyte>(io_realm_internal_objectstore_OsSyncUser_STATE_LOGGED_IN);\n            case SyncUser::State::Removed: return static_cast<jbyte>(io_realm_internal_objectstore_OsSyncUser_STATE_REMOVED);\n            default:\n                throw std::logic_error(util::format(\"Unknown state: %1\", static_cast<size_t>(user->state())));\n        }\n    }\n    CATCH_STD();\n    return static_cast<jbyte>(-1);\n}\n\nJNIEXPORT jstring JNICALL Java_io_realm_internal_objectstore_OsSyncUser_nativeGetProviderType(JNIEnv* env, jclass, jlong j_native_ptr)\n{\n    try {\n        auto user = *reinterpret_cast<std::shared_ptr<SyncUser>*>(j_native_ptr);\n        return to_jstring(env, user->identities().begin()->provider_type);\n    }\n    CATCH_STD();\n    return nullptr;\n}\n\nJNIEXPORT jstring JNICALL Java_io_realm_internal_objectstore_OsSyncUser_nativeGetDeviceId(JNIEnv* env, jclass, jlong j_native_ptr)\n{\n    try {\n        auto user = *reinterpret_cast<std::shared_ptr<SyncUser>*>(j_native_ptr);\n        std::string device_id = user->device_id();\n        return to_jstring(env, device_id);\n    }\n    CATCH_STD();\n    return nullptr;\n}\n\nJNIEXPORT jstring JNICALL Java_io_realm_internal_objectstore_OsSyncUser_nativeCustomData(JNIEnv* env, jclass, jlong j_native_ptr) {\n    try {\n        auto user = *reinterpret_cast<std::shared_ptr<SyncUser>*>(j_native_ptr);\n        const util::Optional<bson::BsonDocument> custom_data(user->custom_data());\n        if (custom_data) {\n            return JniBsonProtocol::bson_to_jstring(env, *custom_data);\n        } else {\n            return JniBsonProtocol::bson_to_jstring(env, BsonDocument());\n        }\n    }\n    CATCH_STD()\n    return JniBsonProtocol::bson_to_jstring(env, BsonDocument());\n}\n\n\nJNIEXPORT void JNICALL Java_io_realm_internal_objectstore_OsSyncUser_nativeRefreshCustomData\n        (JNIEnv* env, jclass, jlong j_native_ptr, jobject j_callback) {\n    try {\n        auto user = *reinterpret_cast<std::shared_ptr<SyncUser>*>(j_native_ptr);\n        auto callback = JavaNetworkTransport::create_void_callback(env, j_callback);\n        user->refresh_custom_data(std::move(callback));\n    }\n    CATCH_STD()\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/cpp/io_realm_internal_objectstore_OsWatchStream.cpp",
    "content": "/*\n * Copyright 2020 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#include \"io_realm_internal_objectstore_OsWatchStream.h\"\n\n#include \"java_class_global_def.hpp\"\n#include \"jni_util/bson_util.hpp\"\n#include \"util.hpp\"\n\n#include <realm/object-store/sync/generic_network_transport.hpp>\n#include <realm/object-store/sync/mongo_collection.hpp>\n\nusing namespace realm;\nusing namespace realm::app;\nusing namespace realm::bson;\nusing namespace realm::jni_util;\nusing namespace realm::_impl;\n\nstatic void finalize_watchstream(jlong ptr) {\n    delete reinterpret_cast<WatchStream *>(ptr);\n}\n\nJNIEXPORT jlong JNICALL\nJava_io_realm_internal_objectstore_OsWatchStream_nativeGetFinalizerMethodPtr(JNIEnv *, jclass) {\n    return reinterpret_cast<jlong>(&finalize_watchstream);\n}\n\nJNIEXPORT jlong JNICALL\nJava_io_realm_internal_objectstore_OsWatchStream_nativeCreateWatchStream(JNIEnv *env, jclass) {\n    try {\n        return (jlong) new WatchStream();\n    }\n    CATCH_STD()\n\n    return 0;\n}\n\nJNIEXPORT void JNICALL\nJava_io_realm_internal_objectstore_OsWatchStream_nativeFeedLine(JNIEnv *env, jclass,\n                                                                jlong j_watch_stream_ptr,\n                                                                jstring j_line) {\n    try {\n        WatchStream *watch_stream = reinterpret_cast<WatchStream *>(j_watch_stream_ptr);\n        JStringAccessor line(env, j_line);\n\n        watch_stream->feed_line(std::string(line));\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT jstring JNICALL\nJava_io_realm_internal_objectstore_OsWatchStream_nativeGetState(JNIEnv *env, jclass,\n                                                                jlong j_watch_stream_ptr) {\n    try {\n        WatchStream *watch_stream = reinterpret_cast<WatchStream *>(j_watch_stream_ptr);\n\n        switch (watch_stream->state()) {\n            case WatchStream::NEED_DATA:\n                return env->NewStringUTF(\"NEED_DATA\");\n            case WatchStream::HAVE_EVENT:\n                return env->NewStringUTF(\"HAVE_EVENT\");\n            case WatchStream::HAVE_ERROR:\n                return env->NewStringUTF(\"HAVE_ERROR\");\n        }\n    }\n    CATCH_STD()\n\n    return nullptr;\n}\n\nJNIEXPORT jstring JNICALL\nJava_io_realm_internal_objectstore_OsWatchStream_nativeGetNextEvent(JNIEnv *env, jclass,\n                                                                    jlong j_watch_stream_ptr) {\n    try {\n        WatchStream *watch_stream = reinterpret_cast<WatchStream *>(j_watch_stream_ptr);\n        return JniBsonProtocol::bson_to_jstring(env, watch_stream->next_event());\n    }\n    CATCH_STD()\n\n    return nullptr;\n}\n\n\nJNIEXPORT jthrowable JNICALL\nJava_io_realm_internal_objectstore_OsWatchStream_nativeGetError(JNIEnv *env, jclass,\n                                                                jlong j_watch_stream_ptr) {\n    try {\n        WatchStream *watch_stream = reinterpret_cast<WatchStream *>(j_watch_stream_ptr);\n\n        auto app_error = watch_stream->error();\n        jbyte category = categoryAsJByte(app_error.to_status());\n\n        jstring error_code_message = env->NewStringUTF(app_error.code_string().data());\n        jstring app_error_message = env->NewStringUTF(app_error.what());\n\n        static JavaClass app_exception_class(env, \"io/realm/mongodb/AppException\");\n        static JavaMethod app_exception_constructor(env, app_exception_class, \"<init>\",\n                                                    \"(Lio/realm/mongodb/ErrorCode;Ljava/lang/String;)V\");\n\n        static JavaClass error_code_class(env, \"io/realm/mongodb/ErrorCode\");\n        static JavaMethod error_code_constructor(env, error_code_class, \"fromNativeError\",\n                                                 \"(Ljava/lang/String;I)Lio/realm/mongodb/ErrorCode;\",\n                                                 true);\n\n        jobject j_error_code = env->CallStaticObjectMethod(error_code_class, error_code_constructor,\n                                                           category, error_code_message);\n        jobject j_app_error = env->NewObject(app_exception_class, app_exception_constructor,\n                                             j_error_code, app_error_message);\n\n        return static_cast<jthrowable>(j_app_error);\n    }\n    CATCH_STD()\n\n    return nullptr;\n}\n\n"
  },
  {
    "path": "realm/realm-library/src/main/cpp/io_realm_log_RealmLog.cpp",
    "content": "/*\n * Copyright 2016 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#include \"io_realm_log_RealmLog.h\"\n#include \"jni_util/log.hpp\"\n#include \"util.hpp\"\n\nusing namespace realm::util;\nusing namespace realm::jni_util;\n\nJNIEXPORT void JNICALL Java_io_realm_log_RealmLog_nativeAddLogger(JNIEnv* env, jclass, jobject java_logger)\n{\n    try {\n        Log::shared().add_java_logger(env, java_logger);\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL Java_io_realm_log_RealmLog_nativeRemoveLogger(JNIEnv* env, jclass, jobject java_logger)\n{\n    try {\n        Log::shared().remove_java_logger(env, java_logger);\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL Java_io_realm_log_RealmLog_nativeClearLoggers(JNIEnv* env, jclass)\n{\n    try {\n        Log::shared().clear_loggers();\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL Java_io_realm_log_RealmLog_nativeRegisterDefaultLogger(JNIEnv* env, jclass)\n{\n    try {\n        Log::shared().register_default_logger();\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL Java_io_realm_log_RealmLog_nativeLog(JNIEnv* env, jclass, jint level, jstring tag,\n                                                            jthrowable throwable, jstring message)\n{\n    try {\n        JStringAccessor tag_accessor(env, tag);\n        JStringAccessor message_accessor(env, message);\n        Log::shared().log(static_cast<Log::Level>(level), std::string(tag_accessor).c_str(), throwable,\n                          std::string(message_accessor).c_str());\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL Java_io_realm_log_RealmLog_nativeSetLogLevel(JNIEnv* env, jclass, jint level)\n{\n    try {\n        Log::shared().set_level(static_cast<Log::Level>(level));\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT jint JNICALL Java_io_realm_log_RealmLog_nativeGetLogLevel(JNIEnv* env, jclass)\n{\n    try {\n        return static_cast<jint>(Log::shared().get_level());\n    }\n    CATCH_STD()\n\n    return static_cast<jint>(Log::Level::all);\n}\n\n// Methods for testing only.\nJNIEXPORT jlong JNICALL Java_io_realm_log_RealmLog_nativeCreateCoreLoggerBridge(JNIEnv* env, jclass, jstring tag)\n{\n    return reinterpret_cast<jlong>(new CoreLoggerBridge(JStringAccessor(env, tag)));\n}\n\nJNIEXPORT void JNICALL Java_io_realm_log_RealmLog_nativeCloseCoreLoggerBridge(JNIEnv*, jclass, jlong native_ptr)\n{\n    delete reinterpret_cast<CoreLoggerBridge*>(native_ptr);\n}\n\nJNIEXPORT void JNICALL Java_io_realm_log_RealmLog_nativeLogToCoreLoggerBridge(JNIEnv* env, jclass, jlong native_ptr,\n                                                                              jint level, jstring msg)\n{\n    CoreLoggerBridge* bridge = reinterpret_cast<CoreLoggerBridge*>(native_ptr);\n    std::string message = JStringAccessor(env, msg);\n    bridge->log(Log::convert_to_core_log_level(static_cast<Log::Level>(level)), message.c_str());\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/cpp/io_realm_mongodb_ApiKeyAuthImpl.cpp",
    "content": "/*\n * Copyright 2020 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#include \"io_realm_mongodb_ApiKeyAuthImpl.h\"\n\n#include \"java_class_global_def.hpp\"\n#include \"java_network_transport.hpp\"\n#include \"util.hpp\"\n#include \"jni_util/java_method.hpp\"\n#include \"jni_util/jni_utils.hpp\"\n\n#include <realm/util/optional.hpp>\n#include <realm/object-store/sync/app.hpp>\n\nusing namespace realm;\nusing namespace realm::app;\nusing namespace realm::jni_util;\nusing namespace realm::_impl;\n\nstatic jobjectArray map_key(JNIEnv* env, App::UserAPIKey& key)\n{\n    jobjectArray arr = (jobjectArray)env->NewObjectArray(4, JavaClassGlobalDef::java_lang_object(), NULL);\n    if (arr == NULL) {\n        ThrowException(env, OutOfMemory, \"Could not allocate memory to return API key.\");\n        return NULL;\n    }\n    std::string api_key_id = key.id.to_string();\n    env->SetObjectArrayElement(arr, 0, to_jstring(env, api_key_id));\n    env->SetObjectArrayElement(arr, 1, (key.key) ? to_jstring(env, key.key) : NULL);\n    env->SetObjectArrayElement(arr, 2, to_jstring(env, key.name));\n    env->SetObjectArrayElement(arr, 3, JavaClassGlobalDef::new_boolean(env, key.disabled));\n    return arr;\n}\n\n// Shared mapper function for mapping UserApiKey to Java Object[]\nstatic std::function<jobject(JNIEnv*, App::UserAPIKey)> single_key_mapper = [](JNIEnv* env, App::UserAPIKey key) {\n    return map_key(env, key);\n};\n\n// Shared mapper function for mapping Vector<UserApiKey> to Java Object[][]\nstatic std::function<jobject(JNIEnv*, std::vector<App::UserAPIKey>)> multi_key_mapper = [](JNIEnv* env, std::vector<App::UserAPIKey> keys) {\n    jobjectArray arr = (jobjectArray)env->NewObjectArray(static_cast<jsize>(keys.size()), JavaClassGlobalDef::java_lang_object(), NULL);\n    if (arr == NULL) {\n        ThrowException(env, OutOfMemory, \"Could not allocate memory to return list of API keys.\");\n        return arr;\n    }\n    for (size_t i = 0; i < keys.size(); ++i) {\n        env->SetObjectArrayElement(arr, i, map_key(env, keys[i]));\n    }\n    return arr;\n};\n\nJNIEXPORT void JNICALL Java_io_realm_mongodb_ApiKeyAuthImpl_nativeCallFunction(JNIEnv* env,\n                                                                   jclass,\n                                                                   jint j_function_type,\n                                                                   jlong j_app_ptr,\n                                                                   jlong j_user_ptr,\n                                                                   jstring j_arg,\n                                                                   jobject j_callback)\n{\n    try {\n        auto app = *reinterpret_cast<std::shared_ptr<App>*>(j_app_ptr);\n        auto user = *reinterpret_cast<std::shared_ptr<SyncUser>*>(j_user_ptr);\n        auto client = app->provider_client<App::UserAPIKeyProviderClient>();\n        switch(j_function_type) {\n            case io_realm_mongodb_ApiKeyAuthImpl_TYPE_CREATE: {\n                JStringAccessor name(env, j_arg);\n                auto callback = JavaNetworkTransport::create_result_callback(env, j_callback, single_key_mapper);\n                client.create_api_key(name, user, std::move(callback));\n                break;\n            }\n            case io_realm_mongodb_ApiKeyAuthImpl_TYPE_FETCH_SINGLE: {\n                auto callback = JavaNetworkTransport::create_result_callback(env, j_callback, single_key_mapper);\n                std::string str_id = JStringAccessor(env, static_cast<jstring>(j_arg));\n                client.fetch_api_key(ObjectId(str_id.c_str()), user, std::move(callback));\n                break;\n            }\n            case io_realm_mongodb_ApiKeyAuthImpl_TYPE_FETCH_ALL: {\n                auto callback = JavaNetworkTransport::create_result_callback(env, j_callback, multi_key_mapper);\n                client.fetch_api_keys(user, std::move(callback));\n                break;\n            }\n            case io_realm_mongodb_ApiKeyAuthImpl_TYPE_DELETE: {\n                auto callback = JavaNetworkTransport::create_void_callback(env, j_callback);\n                std::string str_id = JStringAccessor(env, static_cast<jstring>(j_arg));\n                client.delete_api_key(ObjectId(str_id.c_str()), user, std::move(callback));\n                break;\n            }\n            case io_realm_mongodb_ApiKeyAuthImpl_TYPE_ENABLE: {\n                auto callback = JavaNetworkTransport::create_void_callback(env, j_callback);\n                std::string str_id = JStringAccessor(env, static_cast<jstring>(j_arg));\n                client.enable_api_key(ObjectId(str_id.c_str()), user, std::move(callback));\n                break;\n            }\n            case io_realm_mongodb_ApiKeyAuthImpl_TYPE_DISABLE: {\n                auto callback = JavaNetworkTransport::create_void_callback(env, j_callback);\n                std::string str_id = JStringAccessor(env, static_cast<jstring>(j_arg));\n                client.disable_api_key(ObjectId(str_id.c_str()), user, std::move(callback));\n                break;\n            }\n            default:\n                throw std::logic_error(util::format(\"Unknown function: %1\", j_function_type));\n        }\n    }\n    CATCH_STD()\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/cpp/io_realm_mongodb_EmailPasswordAuthImpl.cpp",
    "content": "/*\n * Copyright 2020 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#include \"io_realm_mongodb_EmailPasswordAuthImpl.h\"\n\n#include \"java_network_transport.hpp\"\n#include \"util.hpp\"\n#include \"jni_util/java_method.hpp\"\n#include \"jni_util/jni_utils.hpp\"\n#include \"jni_util/bson_util.hpp\"\n\n#include <realm/object-store/sync/app.hpp>\n\nusing namespace realm;\nusing namespace realm::app;\nusing namespace realm::jni_util;\nusing namespace realm::_impl;\n\nJNIEXPORT void JNICALL Java_io_realm_mongodb_EmailPasswordAuthImpl_nativeCallFunction(JNIEnv* env,\n                                                                          jclass,\n                                                                          jint j_function_type,\n                                                                          jlong j_app_ptr,\n                                                                          jobject j_callback,\n                                                                          jobjectArray j_args)\n{\n    try {\n        auto app = *reinterpret_cast<std::shared_ptr<App>*>(j_app_ptr);\n        JObjectArrayAccessor<JStringAccessor, jstring> args(env, j_args);\n        auto client = app->provider_client<App::UsernamePasswordProviderClient>();\n        switch(j_function_type) {\n            case io_realm_mongodb_EmailPasswordAuthImpl_TYPE_REGISTER_USER:\n                client.register_email(args[0], args[1], JavaNetworkTransport::create_void_callback(env, j_callback));\n                break;\n            case io_realm_mongodb_EmailPasswordAuthImpl_TYPE_CONFIRM_USER:\n                client.confirm_user(args[0], args[1], JavaNetworkTransport::create_void_callback(env, j_callback));\n                break;\n            case io_realm_mongodb_EmailPasswordAuthImpl_TYPE_RESEND_CONFIRMATION_EMAIL:\n                client.resend_confirmation_email(args[0], JavaNetworkTransport::create_void_callback(env, j_callback));\n                break;\n            case io_realm_mongodb_EmailPasswordAuthImpl_TYPE_SEND_RESET_PASSWORD_EMAIL:\n                client.send_reset_password_email(args[0], JavaNetworkTransport::create_void_callback(env, j_callback));\n                break;\n            case io_realm_mongodb_EmailPasswordAuthImpl_TYPE_CALL_RESET_PASSWORD_FUNCTION: {\n                bson::BsonArray reset_arg(JniBsonProtocol::string_to_bson(args[2]));\n                client.call_reset_password_function(args[0], args[1], reset_arg, JavaNetworkTransport::create_void_callback(env, j_callback));\n                break;\n            }\n            case io_realm_mongodb_EmailPasswordAuthImpl_TYPE_RESET_PASSWORD:\n                client.reset_password(args[0], args[1], args[2], JavaNetworkTransport::create_void_callback(env, j_callback));\n                break;\n            case io_realm_mongodb_EmailPasswordAuthImpl_TYPE_RETRY_CUSTOM_CONFIRMATION:\n                client.retry_custom_confirmation(args[0], JavaNetworkTransport::create_void_callback(env, j_callback));\n                break;\n            default:\n                throw std::logic_error(util::format(\"Unknown function: %1\", j_function_type));\n        }\n    }\n    CATCH_STD()\n}\n\n"
  },
  {
    "path": "realm/realm-library/src/main/cpp/io_realm_mongodb_FunctionsImpl.cpp",
    "content": "/*\n * Copyright 2020 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#include \"io_realm_mongodb_FunctionsImpl.h\"\n\n#include \"util.hpp\"\n#include \"jni_util/bson_util.hpp\"\n#include \"java_network_transport.hpp\"\n#include <realm/object-store/sync/app.hpp>\n\n\nusing namespace realm;\nusing namespace realm::app;\nusing namespace realm::bson;\nusing namespace realm::jni_util;\n\nstatic std::function<jobject(JNIEnv*, util::Optional<Bson> )> success_mapper = [](JNIEnv* env, util::Optional<Bson> response) {\n    if (response) {\n        return JniBsonProtocol::bson_to_jstring(env, *response);\n    } else {\n        // We should never reach here, as this is the success mapper and we would not end up here\n        // if we did not received a parsable BSON response\n        throw std::logic_error(\"Function did not return a result\");\n    }\n};\n\nJNIEXPORT void JNICALL\nJava_io_realm_mongodb_FunctionsImpl_nativeCallFunction(JNIEnv* env, jclass , jlong j_app_ptr, jlong j_user_ptr, jstring j_name,\n                                               jstring j_args_json , jobject j_callback) {\n    try {\n        auto app = *reinterpret_cast<std::shared_ptr<App>*>(j_app_ptr);\n        auto user = *reinterpret_cast<std::shared_ptr<SyncUser>*>(j_user_ptr);\n\n        auto callback = JavaNetworkTransport::create_result_callback(env, j_callback, success_mapper);\n\n        JStringAccessor name(env, j_name);\n        BsonArray args(JniBsonProtocol::parse_checked(env, j_args_json, Bson::Type::Array, \"BSON argument must be an BsonArray\"));\n        app->call_function(user, name, args, std::move(callback));\n    }\n    CATCH_STD()\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/cpp/io_realm_mongodb_User.cpp",
    "content": "/*\n * Copyright 2020 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#include \"io_realm_mongodb_User.h\"\n\n#include \"java_network_transport.hpp\"\n#include \"util.hpp\"\n#include \"jni_util/java_method.hpp\"\n#include \"jni_util/jni_utils.hpp\"\n\n#include <realm/object-store/sync/app.hpp>\n#include <jni_util/bson_util.hpp>\n\nusing namespace realm;\nusing namespace realm::app;\nusing namespace realm::jni_util;\nusing namespace realm::_impl;\n\nJNIEXPORT void JNICALL Java_io_realm_mongodb_User_nativeLinkUser(JNIEnv* env,\n                                                             jclass,\n                                                             jlong j_app_ptr,\n                                                             jlong j_user_ptr,\n                                                             jlong j_credentials_ptr,\n                                                             jobject j_callback)\n{\n    try {\n        auto app = *reinterpret_cast<std::shared_ptr<App>*>(j_app_ptr);\n        auto user = *reinterpret_cast<std::shared_ptr<SyncUser>*>(j_user_ptr);\n        auto credentials = reinterpret_cast<AppCredentials*>(j_credentials_ptr);\n        std::function<jobject(JNIEnv*, std::shared_ptr<SyncUser>)> mapper = [](JNIEnv* env, std::shared_ptr<SyncUser> user) {\n            auto* java_user = new std::shared_ptr<SyncUser>(std::move(user));\n            return JavaClassGlobalDef::new_long(env, reinterpret_cast<int64_t>(java_user));\n        };\n        auto callback = JavaNetworkTransport::create_result_callback(env, j_callback, mapper);\n        app->link_user(user, *credentials, std::move(callback));\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL Java_io_realm_mongodb_User_nativeRemoveUser(JNIEnv* env,\n                                                               jclass,\n                                                               jlong j_app_ptr,\n                                                               jlong j_user_ptr,\n                                                               jobject j_callback)\n{\n    try {\n        auto app = *reinterpret_cast<std::shared_ptr<App>*>(j_app_ptr);\n        auto user = *reinterpret_cast<std::shared_ptr<SyncUser>*>(j_user_ptr);\n        app->remove_user(user, JavaNetworkTransport::create_void_callback(env, j_callback));\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL Java_io_realm_mongodb_User_nativeLogOut(JNIEnv* env, jclass, jlong j_app_ptr, jlong j_user_ptr, jobject j_callback)\n{\n    try {\n        auto app = *reinterpret_cast<std::shared_ptr<App>*>(j_app_ptr);\n        auto user = *reinterpret_cast<std::shared_ptr<SyncUser>*>(j_user_ptr);\n        app->log_out(user, JavaNetworkTransport::create_void_callback(env, j_callback));\n    }\n    CATCH_STD()\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/cpp/io_realm_mongodb_mongo_iterable_AggregateIterable.cpp",
    "content": "/*\n * Copyright 2020 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#include \"io_realm_mongodb_mongo_iterable_AggregateIterable.h\"\n\n#include \"java_class_global_def.hpp\"\n#include \"java_network_transport.hpp\"\n#include \"util.hpp\"\n#include \"jni_util/java_method.hpp\"\n#include \"jni_util/jni_utils.hpp\"\n#include \"jni_util/bson_util.hpp\"\n\n#include <realm/util/optional.hpp>\n#include <realm/util/bson/bson.hpp>\n#include <realm/object-store/sync/mongo_collection.hpp>\n#include <jni_util/bson_util.hpp>\n#include <jni.h>\n\nusing namespace realm;\nusing namespace realm::bson;\nusing namespace realm::jni_util;\nusing namespace realm::_impl;\n\nstatic std::function<jobject(JNIEnv*, util::Optional<bson::BsonArray>)> collection_mapper_aggregate = [](JNIEnv* env, util::Optional<bson::BsonArray> array) {\n    return array ? JniBsonProtocol::bson_to_jstring(env, *array) : NULL;\n};\n\nJNIEXPORT void JNICALL\nJava_io_realm_mongodb_mongo_iterable_AggregateIterable_nativeAggregate(JNIEnv* env,\n                                                                       jclass,\n                                                                       jlong j_collection_ptr,\n                                                                       jstring j_pipeline,\n                                                                       jobject j_callback) {\n    try {\n        auto collection = reinterpret_cast<MongoCollection *>(j_collection_ptr);\n\n        BsonArray bson_array(JniBsonProtocol::parse_checked(env, j_pipeline, Bson::Type::Array, \"BSON pipeline must be a BsonArray\"));\n\n        collection->aggregate(bson_array, JavaNetworkTransport::create_result_callback(env, j_callback, collection_mapper_aggregate));\n    }\n    CATCH_STD()\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/cpp/io_realm_mongodb_mongo_iterable_FindIterable.cpp",
    "content": "/*\n * Copyright 2020 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#include \"io_realm_mongodb_mongo_iterable_FindIterable.h\"\n\n#include \"java_class_global_def.hpp\"\n#include \"java_network_transport.hpp\"\n#include \"util.hpp\"\n#include \"jni_util/java_method.hpp\"\n#include \"jni_util/jni_utils.hpp\"\n#include \"jni_util/bson_util.hpp\"\n\n#include <realm/util/optional.hpp>\n#include <realm/util/bson/bson.hpp>\n#include <realm/object-store/sync/mongo_collection.hpp>\n#include <jni_util/bson_util.hpp>\n\nusing namespace realm;\nusing namespace realm::bson;\nusing namespace realm::jni_util;\nusing namespace realm::_impl;\n\nstatic std::function<jobject(JNIEnv*, util::Optional<bson::BsonArray>)> collection_mapper_find = [](JNIEnv* env, util::Optional<bson::BsonArray> array) {\n    return array ? JniBsonProtocol::bson_to_jstring(env, *array) : NULL;\n};\n\nJNIEXPORT void JNICALL\nJava_io_realm_mongodb_mongo_iterable_FindIterable_nativeFind(JNIEnv *env,\n                                                             jclass,\n                                                             jint j_find_type,\n                                                             jlong j_collection_ptr,\n                                                             jstring j_filter,\n                                                             jstring j_projection,\n                                                             jstring j_sort,\n                                                             jlong j_limit,\n                                                             jobject j_callback) {\n    try {\n        auto collection = reinterpret_cast<MongoCollection*>(j_collection_ptr);\n\n        bson::BsonDocument filter(JniBsonProtocol::parse_checked(env, j_filter, Bson::Type::Document, \"BSON filter must be a Document\"));\n\n        switch (j_find_type) {\n            case io_realm_mongodb_mongo_iterable_FindIterable_FIND:\n                collection->find(filter, JavaNetworkTransport::create_result_callback(env, j_callback, collection_mapper_find));\n                break;\n            case io_realm_mongodb_mongo_iterable_FindIterable_FIND_WITH_OPTIONS:\n                uint64_t limit = std::uint64_t(j_limit);\n                bson::BsonDocument projection(JniBsonProtocol::parse_checked(env, j_projection, Bson::Type::Document, \"BSON projection must be a Document\"));\n                bson::BsonDocument sort(JniBsonProtocol::parse_checked(env, j_sort, Bson::Type::Document, \"BSON sort must be a Document\"));\n                MongoCollection::FindOptions options = {\n                        limit,\n                        projection,\n                        sort\n                };\n                collection->find(filter, options, JavaNetworkTransport::create_result_callback(env, j_callback, collection_mapper_find));\n                break;\n        }\n    }\n    CATCH_STD()\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/cpp/io_realm_mongodb_sync_ClientResetRequiredError.cpp",
    "content": "/*\n * Copyright 2017 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#include <jni.h>\n\n#include <realm/object-store/sync/app.hpp>\n#include <realm/object-store/sync/sync_manager.hpp>\n\n#include \"util.hpp\"\n#include \"io_realm_mongodb_sync_ClientResetRequiredError.h\"\n\nusing namespace realm;\n\nJNIEXPORT void JNICALL Java_io_realm_mongodb_sync_ClientResetRequiredError_nativeExecuteClientReset(JNIEnv* env, jobject,\n                                                                                                    jlong j_app_ptr,\n                                                                                                    jstring localRealmPath)\n{\n    try {\n        auto app = *reinterpret_cast<std::shared_ptr<app::App>*>(j_app_ptr);\n        JStringAccessor local_realm_path(env, localRealmPath);\n        if (!app->sync_manager()->immediately_run_file_actions(std::string(local_realm_path))) {\n            ThrowException(\n                env, IllegalState,\n                concat_stringdata(\"Realm was not configured correctly. Client Reset could not be run for Realm at: \",\n                                  local_realm_path));\n            return;\n        }\n    }\n    CATCH_STD()\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/cpp/io_realm_mongodb_sync_Sync.cpp",
    "content": "/*\n * Copyright 2016 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#include \"io_realm_mongodb_sync_Sync.h\"\n\n#include <realm/object-store/impl/realm_coordinator.hpp>\n#include <realm/object-store/sync/app.hpp>\n#include <realm/object-store/sync/sync_manager.hpp>\n#include <realm/object-store/sync/sync_session.hpp>\n#include <realm/sync/protocol.hpp>\n#include <realm/sync/binding_callback_thread_observer.hpp>\n\n#include \"util.hpp\"\n#include <jni_util/bson_util.hpp>\n#include <realm-core/src/realm/sync/client_base.hpp>\n#include \"jni_util/java_class.hpp\"\n#include \"jni_util/java_method.hpp\"\n#include \"jni_util/jni_utils.hpp\"\n\nusing namespace realm;\nusing namespace realm::jni_util;\nusing namespace realm::util;\n\nJNIEXPORT void JNICALL Java_io_realm_mongodb_sync_Sync_nativeReset(JNIEnv* env, jclass, jlong j_app_ptr)\n{\n    try {\n        auto app = *reinterpret_cast<std::shared_ptr<app::App>*>(j_app_ptr);\n        app->sync_manager()->close_all_sessions();\n        app->sync_manager()->wait_for_sessions_to_terminate();\n        app->sync_manager()->reset_for_testing();\n        app->sync_manager()->set_logger_factory(javaLoggerFactory);\n        app::App::clear_cached_apps();\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL Java_io_realm_mongodb_sync_Sync_nativeSimulateSyncError(JNIEnv* env, jclass, jlong j_app_ptr, jstring local_realm_path,\n                                                                       jint err_code, jstring j_type, jstring err_message,\n                                                                       jboolean is_fatal)\n{\n    try {\n        auto app = *reinterpret_cast<std::shared_ptr<app::App>*>(j_app_ptr);\n        JStringAccessor path(env, local_realm_path);\n        JStringAccessor message(env, err_message);\n        JStringAccessor type(env, j_type);\n\n        auto session = app->sync_manager()->get_existing_active_session(path);\n        if (!session) {\n            ThrowException(env, IllegalArgument, concat_stringdata(\"Session not found: \", path));\n            return;\n        }\n\n        auto code = static_cast<ErrorCodes::Error>(err_code);\n        auto status = Status(code, message);\n        auto sync_error = sync::SessionErrorInfo{status, sync::IsFatal{static_cast<bool>(is_fatal)}};\n        SyncSession::OnlyForTesting::handle_error(*session, std::move(sync_error));\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL Java_io_realm_mongodb_sync_Sync_nativeReconnect(JNIEnv* env, jclass, jlong j_app_ptr)\n{\n    try {\n        auto app = *reinterpret_cast<std::shared_ptr<app::App>*>(j_app_ptr);\n        app->sync_manager()->reconnect();\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT jstring JNICALL Java_io_realm_mongodb_sync_Sync_nativeGetPathForRealm(JNIEnv* env,\n                                                                                jclass,\n                                                                                jlong j_app_ptr,\n                                                                                jstring j_user_id,\n                                                                                jstring j_encoded_partition_value,\n                                                                                jstring j_override_filename)\n{\n    try {\n        // This is a little bit of a hack. Normally Realm Java doesn't generate the C++ SyncConfig\n        // until the Realm is opened, but the Sync API for creating the Realm path require that\n        // it is created up front. So we cheat and create a SyncConfig with the minimal values\n        // needed for the path to be calculated.\n        auto app = *reinterpret_cast<std::shared_ptr<app::App>*>(j_app_ptr);\n        JStringAccessor user_id(env, j_user_id);\n        std::shared_ptr<SyncUser> user = app->sync_manager()->get_existing_logged_in_user(user_id);\n        if (!user) {\n            throw std::logic_error(\"User is not logged in\");\n        }\n        Bson bson(JniBsonProtocol::jstring_to_bson(env, j_encoded_partition_value));\n        std::stringstream buffer;\n        buffer << bson;\n        SyncConfig config{user, buffer.str()};\n        util::Optional<std::string> file_name = util::none;\n        if (j_override_filename != nullptr) {\n            JStringAccessor override_file_name(env, j_override_filename);\n            file_name = std::string(override_file_name);\n        }\n        return to_jstring(env, app->sync_manager()->path_for_realm(config, file_name));\n    }\n    CATCH_STD()\n    return nullptr;\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/cpp/io_realm_mongodb_sync_SyncSession.cpp",
    "content": "/*\n * Copyright 2017 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#include <jni.h>\n#include <string>\n\n#include \"io_realm_mongodb_sync_SyncSession.h\"\n\n#include <realm/object-store/sync/app.hpp>\n#include <realm/object-store/sync/sync_manager.hpp>\n#include <realm/object-store/sync/sync_session.hpp>\n\n#include \"util.hpp\"\n#include \"java_class_global_def.hpp\"\n#include \"jni_util/java_global_ref_by_move.hpp\"\n#include \"jni_util/java_global_ref_by_copy.hpp\"\n#include \"jni_util/java_local_ref.hpp\"\n#include \"jni_util/java_method.hpp\"\n#include \"jni_util/java_class.hpp\"\n#include \"jni_util/jni_utils.hpp\"\n\nusing namespace realm;\nusing namespace realm::jni_util;\nusing namespace realm::sync;\nusing namespace realm::_impl;\n\nstatic_assert(SyncSession::State::Active ==\n                  static_cast<SyncSession::State>(io_realm_mongodb_sync_SyncSession_STATE_VALUE_ACTIVE),\n              \"\");\nstatic_assert(SyncSession::State::Dying ==\n                  static_cast<SyncSession::State>(io_realm_mongodb_sync_SyncSession_STATE_VALUE_DYING),\n              \"\");\nstatic_assert(SyncSession::State::Inactive ==\n                  static_cast<SyncSession::State>(io_realm_mongodb_sync_SyncSession_STATE_VALUE_INACTIVE),\n              \"\");\n\nstatic_assert(SyncSession::ConnectionState::Disconnected ==\n              static_cast<SyncSession::ConnectionState >(io_realm_mongodb_sync_SyncSession_CONNECTION_VALUE_DISCONNECTED),\n              \"\");\nstatic_assert(SyncSession::ConnectionState::Connecting ==\n              static_cast<SyncSession::ConnectionState>(io_realm_mongodb_sync_SyncSession_CONNECTION_VALUE_CONNECTING),\n              \"\");\nstatic_assert(SyncSession::ConnectionState::Connected ==\n              static_cast<SyncSession::ConnectionState>(io_realm_mongodb_sync_SyncSession_CONNECTION_VALUE_CONNECTED),\n              \"\");\n\n\n\nvoid handleCompletion(jint callback_id, JavaMethod &java_notify_result_method,\n                      const JavaGlobalRefByCopy &session_ref, const Status &status) {\n    JNIEnv* env = JniUtils::get_env(true);\n    JavaLocalRef<jobject> java_error_category;\n    JavaLocalRef<jobject> java_error_code;\n    JavaLocalRef<jstring> java_error_message;\n\n    if (!status.is_ok()) {\n        jbyte category = categoryAsJByte(status);\n        java_error_category = JavaLocalRef<jobject>(env, JavaClassGlobalDef::new_long(env,category));\n        java_error_code = JavaLocalRef<jobject>(env, JavaClassGlobalDef::new_long(env, static_cast<int32_t>(status.code())));\n        java_error_message = JavaLocalRef<jstring>(env, env->NewStringUTF( status.reason().c_str()));\n    }\n\n    env->CallVoidMethod(session_ref.get(), java_notify_result_method,\n                        callback_id, java_error_category.get(), java_error_code.get(),\n                        java_error_message.get());\n}\n\nJNIEXPORT jlong JNICALL Java_io_realm_mongodb_sync_SyncSession_nativeAddProgressListener(JNIEnv* env, jobject j_session_object,\n                                                                                         jlong j_app_ptr,\n                                                                                         jstring j_local_realm_path,\n                                                                                         jlong listener_id, jint direction,\n                                                                                         jboolean is_streaming)\n{\n    try {\n        auto app = *reinterpret_cast<std::shared_ptr<app::App>*>(j_app_ptr);\n        // JNIEnv is thread confined, so we need a deep copy in order to capture the string in the lambda\n        std::string local_realm_path(JStringAccessor(env, j_local_realm_path));\n        std::shared_ptr<SyncSession> session = app->sync_manager()->get_existing_session(local_realm_path);\n        if (!session) {\n            // FIXME: We should lift this restriction\n            ThrowException(env, IllegalState,\n                           \"Cannot register a progress listener before a session is \"\n                           \"created. A session will be created after the first call to Realm.getInstance().\");\n            return 0;\n        }\n\n        SyncSession::ProgressDirection type = (direction == 1) ? SyncSession::ProgressDirection::download : SyncSession::ProgressDirection::upload;\n\n        static JavaClass java_syncsession_class(env, \"io/realm/mongodb/sync/SyncSession\");\n        static JavaMethod java_notify_progress_listener(env, java_syncsession_class, \"notifyProgressListener\", \"(JJJ)V\");\n\n        auto callback = [session_ref = JavaGlobalRefByCopy(env, j_session_object), local_realm_path, listener_id](uint64_t transferred, uint64_t transferrable) {\n            JNIEnv* local_env = jni_util::JniUtils::get_env(true);\n\n            JavaLocalRef<jstring> path(local_env, to_jstring(local_env, local_realm_path));\n            local_env->CallVoidMethod(session_ref.get(),\n                    java_notify_progress_listener,\n                    listener_id,\n                    static_cast<jlong>(transferred),\n                    static_cast<jlong>(transferrable));\n\n            // All exceptions will be caught on the Java side of handlers, but Errors will still end\n            // up here, so we need to do something sensible with them.\n            // Throwing a C++ exception will terminate the sync thread and cause the pending Java\n            // exception to become visible. For some (unknown) reason Logcat will not see the C++\n            // exception, only the Java one.\n            if (local_env->ExceptionCheck()) {\n                local_env->ExceptionDescribe();\n                throw std::runtime_error(\"An unexpected Error was thrown from Java. See LogCat\");\n            }\n        };\n        uint64_t token = session->register_progress_notifier(callback, type, to_bool(is_streaming));\n        return static_cast<jlong>(token);\n    }\n    CATCH_STD()\n    return 0;\n}\n\nJNIEXPORT void JNICALL Java_io_realm_mongodb_sync_SyncSession_nativeRemoveProgressListener(JNIEnv* env, jclass,\n                                                                              jlong j_app_ptr,\n                                                                              jstring j_local_realm_path,\n                                                                              jlong listener_token)\n{\n    try {\n        auto app = *reinterpret_cast<std::shared_ptr<app::App>*>(j_app_ptr);\n        JStringAccessor local_realm_path(env, j_local_realm_path);\n        std::shared_ptr<SyncSession> session = app->sync_manager()->get_existing_session(local_realm_path);\n        if (session) {\n            session->unregister_progress_notifier(static_cast<uint64_t>(listener_token));\n        }\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT jboolean JNICALL Java_io_realm_mongodb_sync_SyncSession_nativeWaitForDownloadCompletion(JNIEnv* env,\n                                                                                        jobject session_object,\n                                                                                        jlong j_app_ptr,\n                                                                                        jint callback_id,\n                                                                                        jstring j_local_realm_path)\n{\n    try {\n        auto app = *reinterpret_cast<std::shared_ptr<app::App>*>(j_app_ptr);\n        JStringAccessor local_realm_path(env, j_local_realm_path);\n        auto session = app->sync_manager()->get_existing_session(local_realm_path);\n\n        if (session) {\n            static JavaClass java_sync_session_class(env, \"io/realm/mongodb/sync/SyncSession\");\n            static JavaMethod java_notify_result_method(env, java_sync_session_class, \"notifyAllChangesSent\",\n                                                        \"(ILjava/lang/Long;Ljava/lang/Long;Ljava/lang/String;)V\");\n\n            session->wait_for_download_completion([session_ref = JavaGlobalRefByCopy(env, session_object), callback_id](const Status& status) {\n                handleCompletion(callback_id, java_notify_result_method, session_ref, status);\n            });\n            return to_jbool(JNI_TRUE);\n        }\n    }\n    CATCH_STD()\n    return JNI_FALSE;\n}\n\nJNIEXPORT jboolean JNICALL Java_io_realm_mongodb_sync_SyncSession_nativeWaitForUploadCompletion(JNIEnv* env,\n                                                                                   jobject session_object,\n                                                                                   jlong j_app_ptr,\n                                                                                   jint callback_id,\n                                                                                   jstring j_local_realm_path)\n{\n    try {\n        auto app = *reinterpret_cast<std::shared_ptr<app::App>*>(j_app_ptr);\n        JStringAccessor local_realm_path(env, j_local_realm_path);\n        auto session = app->sync_manager()->get_existing_session(local_realm_path);\n\n        if (session) {\n            static JavaClass java_sync_session_class(env, \"io/realm/mongodb/sync/SyncSession\");\n            static JavaMethod java_notify_result_method(env, java_sync_session_class, \"notifyAllChangesSent\",\n                                                        \"(ILjava/lang/Long;Ljava/lang/Long;Ljava/lang/String;)V\");\n\n            session->wait_for_upload_completion([session_ref = JavaGlobalRefByCopy(env, session_object), callback_id] (const Status& status) {\n                handleCompletion(callback_id, java_notify_result_method, session_ref, status);\n            });\n            return JNI_TRUE;\n        }\n    }\n    CATCH_STD()\n    return JNI_FALSE;\n}\n\n\nJNIEXPORT jbyte JNICALL Java_io_realm_mongodb_sync_SyncSession_nativeGetState(JNIEnv* env, jclass, jlong j_app_ptr, jstring j_local_realm_path)\n{\n    try {\n        auto app = *reinterpret_cast<std::shared_ptr<app::App>*>(j_app_ptr);\n        JStringAccessor local_realm_path(env, j_local_realm_path);\n        auto session = app->sync_manager()->get_existing_session(local_realm_path);\n\n        if (session) {\n            switch (session->state()) {\n                case SyncSession::State::Active:\n                    return io_realm_mongodb_sync_SyncSession_STATE_VALUE_ACTIVE;\n                case SyncSession::State::Dying:\n                    return io_realm_mongodb_sync_SyncSession_STATE_VALUE_DYING;\n                case SyncSession::State::Inactive:\n                    return io_realm_mongodb_sync_SyncSession_STATE_VALUE_INACTIVE;\n                case SyncSession::State::Paused:\n                    return io_realm_mongodb_sync_SyncSession_STATE_VALUE_PAUSED;\n                case SyncSession::State::WaitingForAccessToken:\n                    return io_realm_mongodb_sync_SyncSession_STATE_VALUE_WAITING_FOR_ACCESS_TOKEN;\n            }\n        }\n    }\n    CATCH_STD()\n    return -1;\n}\n\nJNIEXPORT jbyte JNICALL Java_io_realm_mongodb_sync_SyncSession_nativeGetConnectionState(JNIEnv* env, jclass, jlong j_app_ptr, jstring j_local_realm_path)\n{\n    try {\n        auto app = *reinterpret_cast<std::shared_ptr<app::App>*>(j_app_ptr);\n        JStringAccessor local_realm_path(env, j_local_realm_path);\n        auto session = app->sync_manager()->get_existing_session(local_realm_path);\n\n        if (session) {\n            switch (session->connection_state()) {\n                case SyncSession::ConnectionState::Disconnected:\n                    return io_realm_mongodb_sync_SyncSession_CONNECTION_VALUE_DISCONNECTED;\n                case SyncSession::ConnectionState::Connecting:\n                    return io_realm_mongodb_sync_SyncSession_CONNECTION_VALUE_CONNECTING;\n                case SyncSession::ConnectionState::Connected:\n                    return io_realm_mongodb_sync_SyncSession_CONNECTION_VALUE_CONNECTED;\n            }\n        }\n    }\n    CATCH_STD()\n    return -1;\n}\n\nstatic jlong get_connection_value(SyncSession::ConnectionState state) {\n    switch (state) {\n        case SyncSession::ConnectionState::Disconnected: return static_cast<jlong>(io_realm_mongodb_sync_SyncSession_CONNECTION_VALUE_DISCONNECTED);\n        case SyncSession::ConnectionState::Connecting: return static_cast<jlong>(io_realm_mongodb_sync_SyncSession_CONNECTION_VALUE_CONNECTING);\n        case SyncSession::ConnectionState::Connected: return static_cast<jlong>(io_realm_mongodb_sync_SyncSession_CONNECTION_VALUE_CONNECTED);\n    }\n    return static_cast<jlong>(-1);\n}\n\nJNIEXPORT jlong JNICALL Java_io_realm_mongodb_sync_SyncSession_nativeAddConnectionListener(JNIEnv* env, jobject j_session_object, jlong j_app_ptr, jstring j_local_realm_path)\n{\n    try {\n        auto app = *reinterpret_cast<std::shared_ptr<app::App>*>(j_app_ptr);\n        // JNIEnv is thread confined, so we need a deep copy in order to capture the string in the lambda\n        std::string local_realm_path(JStringAccessor(env, j_local_realm_path));\n        std::shared_ptr<SyncSession> session = app->sync_manager()->get_existing_session(local_realm_path);\n        if (!session) {\n            // FIXME: We should lift this restriction\n            ThrowException(env, IllegalState,\n            \"Cannot register a connection listener before a session is \"\n            \"created. A session will be created after the first call to Realm.getInstance().\");\n            return 0;\n        }\n\n        static JavaClass java_syncmanager_class(env, \"io/realm/mongodb/sync/SyncSession\");\n        static JavaMethod java_notify_connection_listener(env, java_syncmanager_class, \"notifyConnectionListeners\", \"(JJ)V\");\n\n        auto callback = [session_ref = JavaGlobalRefByCopy(env, j_session_object)](SyncSession::ConnectionState old_state, SyncSession::ConnectionState new_state) {\n            JNIEnv* local_env = jni_util::JniUtils::get_env(true);\n\n            jlong old_connection_value = get_connection_value(old_state);\n            jlong new_connection_value = get_connection_value(new_state);\n\n            local_env->CallVoidMethod(session_ref.get(), java_notify_connection_listener,\n                                        old_connection_value, new_connection_value);\n\n            // All exceptions will be caught on the Java side of handlers, but Errors will still end\n            // up here, so we need to do something sensible with them.\n            // Throwing a C++ exception will terminate the sync thread and cause the pending Java\n            // exception to become visible. For some (unknown) reason Logcat will not see the C++\n            // exception, only the Java one.\n            if (local_env->ExceptionCheck()) {\n                local_env->ExceptionDescribe();\n                throw std::runtime_error(\"An unexpected Error was thrown from Java. See LogCat\");\n            }\n        };\n        uint64_t token = session->register_connection_change_callback(std::move(callback));\n        return static_cast<jlong>(token);\n    }\n    CATCH_STD()\n    return 0;\n}\n\nJNIEXPORT void JNICALL Java_io_realm_mongodb_sync_SyncSession_nativeRemoveConnectionListener(JNIEnv* env, jclass, jlong j_app_ptr, jlong listener_id, jstring j_local_realm_path)\n{\n    try {\n        auto app = *reinterpret_cast<std::shared_ptr<app::App>*>(j_app_ptr);\n        // JNIEnv is thread confined, so we need a deep copy in order to capture the string in the lambda\n        std::string local_realm_path(JStringAccessor(env, j_local_realm_path));\n        std::shared_ptr<SyncSession> session = app->sync_manager()->get_existing_session(local_realm_path);\n        if (session) {\n            session->unregister_connection_change_callback(static_cast<uint64_t>(listener_id));\n        }\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL Java_io_realm_mongodb_sync_SyncSession_nativeStart(JNIEnv* env, jclass, jlong j_app_ptr, jstring j_local_realm_path)\n{\n    try {\n        auto app = *reinterpret_cast<std::shared_ptr<app::App>*>(j_app_ptr);\n        JStringAccessor local_realm_path(env, j_local_realm_path);\n        auto session = app->sync_manager()->get_existing_session(local_realm_path);\n        if (!session) {\n            // FIXME: We should lift this restriction\n            ThrowException(env, IllegalState,\n            \"Cannot call start() before a session is \"\n            \"created. A session will be created after the first call to Realm.getInstance().\");\n            return;\n        }\n        session->revive_if_needed();\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL Java_io_realm_mongodb_sync_SyncSession_nativeStop(JNIEnv* env, jclass, jlong j_app_ptr, jstring j_local_realm_path)\n{\n    try {\n        auto app = *reinterpret_cast<std::shared_ptr<app::App>*>(j_app_ptr);\n        JStringAccessor local_realm_path(env, j_local_realm_path);\n        auto session = app->sync_manager()->get_existing_session(local_realm_path);\n        if (session) {\n            session->force_close();\n        }\n    }\n    CATCH_STD()\n}\n\nJNIEXPORT void JNICALL Java_io_realm_mongodb_sync_SyncSession_nativeShutdownAndWait (JNIEnv* env, jclass, jlong j_app_ptr, jstring j_local_realm_path) {\n    try {\n        auto app = *reinterpret_cast<std::shared_ptr<app::App>*>(j_app_ptr);\n        JStringAccessor local_realm_path(env, j_local_realm_path);\n        auto session = app->sync_manager()->get_existing_session(local_realm_path);\n        if (session) {\n            session->shutdown_and_wait();\n        }\n    }\n    CATCH_STD()\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/cpp/java_accessor.hpp",
    "content": "\n/*\n * Copyright 2017 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#ifndef REALM_JNI_IMPL_JAVA_ACCESSOR_HPP\n#define REALM_JNI_IMPL_JAVA_ACCESSOR_HPP\n\n#include <jni.h>\n\n#include <vector>\n#include <memory>\n\n#include <realm/binary_data.hpp>\n#include <realm/table.hpp>\n#include <realm/util/any.hpp>\n#include <realm/util/to_string.hpp>\n\n#include <realm/object-store/object_accessor.hpp>\n\n#include \"java_class_global_def.hpp\"\n#include \"java_exception_def.hpp\"\n#include \"jni_util/java_exception_thrower.hpp\"\n\n// Utility classes for accessing Java objects from JNI\nnamespace realm {\nnamespace _impl {\n\ntemplate <typename, typename>\nclass JPrimitiveArrayAccessor;\ntypedef JPrimitiveArrayAccessor<jbyteArray, jbyte> JByteArrayAccessor;\ntypedef JPrimitiveArrayAccessor<jbooleanArray, jboolean> JBooleanArrayAccessor;\ntypedef JPrimitiveArrayAccessor<jlongArray, jlong> JLongArrayAccessor;\ntypedef JPrimitiveArrayAccessor<jfloatArray, jfloat> JFloatArrayAccessor;\ntypedef JPrimitiveArrayAccessor<jdoubleArray, jdouble> JDoubleArrayAccessor;\n\n// JPrimitiveArrayAccessor and JObjectArrayAccessor are not supposed to be used across JNI borders. They won't acquire\n// references of the original Java object. Thus, you have to ensure the original java object is available during the\n// life cycle of those accessors. Moreover, some returned object like BinaryData and StringData, they don't own the\n// memory they use. So the accessor has to be available during the life cycle of those returned objects.\n\n// Accessor for Java primitive arrays\ntemplate <typename ArrayType, typename ElementType>\nclass JPrimitiveArrayAccessor {\npublic:\n    JPrimitiveArrayAccessor(JNIEnv* env, ArrayType jarray)\n        : m_size(jarray ? env->GetArrayLength(jarray) : 0)\n        , m_elements_holder(std::make_shared<ElementsHolder>(env, jarray))\n    {\n        check_init(env);\n    }\n    ~JPrimitiveArrayAccessor() = default;\n\n    JPrimitiveArrayAccessor(JPrimitiveArrayAccessor&&) = default;\n    JPrimitiveArrayAccessor& operator=(JPrimitiveArrayAccessor&&) = default;\n    JPrimitiveArrayAccessor(const JPrimitiveArrayAccessor&) = default;\n    JPrimitiveArrayAccessor& operator=(const JPrimitiveArrayAccessor&) = default;\n\n    inline bool is_null()\n    {\n        return !m_elements_holder->m_jarray;\n    }\n\n    inline jsize size() const noexcept\n    {\n        return m_size;\n    }\n\n    inline ElementType* data() const noexcept\n    {\n        return m_elements_holder->m_data_ptr;\n    }\n\n    inline const ElementType& operator[](const int index) const noexcept\n    {\n        return m_elements_holder->m_data_ptr[index];\n    }\n\n    // Converts the Java array into an instance of T. The returned value's life cycle may still rely on this accessor.\n    // (e.g.: BinaryData/StringData)\n    template <typename T>\n    T transform();\n\nprivate:\n    // Holding the data returned by GetXxxArrayElements call.\n    struct ElementsHolder {\n        ElementsHolder(JNIEnv*, ArrayType);\n        ~ElementsHolder();\n\n        JNIEnv* m_env;\n        const ArrayType m_jarray;\n        ElementType* m_data_ptr;\n        const jint m_release_mode = JNI_ABORT;\n    };\n\n    jsize m_size;\n    // For enabling copy/move constructors. ReleaseXxxArrayElements should only be called once.\n    std::shared_ptr<ElementsHolder> m_elements_holder;\n\n    inline void check_init(JNIEnv* env)\n    {\n        if (m_elements_holder->m_jarray != nullptr && m_elements_holder->m_data_ptr == nullptr) {\n            THROW_JAVA_EXCEPTION(env, JavaExceptionDef::IllegalArgument,\n                                 util::format(\"GetXxxArrayElements failed on %1.\",\n                                              reinterpret_cast<int64_t>(m_elements_holder->m_jarray)));\n        }\n    }\n};\n\n// Accessor for Java object arrays\ntemplate <typename AccessorType, typename ObjectType>\nclass JObjectArrayAccessor {\npublic:\n    JObjectArrayAccessor(JNIEnv* env, jobjectArray jobject_array)\n        : m_env(env)\n        , m_jobject_array(jobject_array)\n        , m_size(jobject_array ? env->GetArrayLength(jobject_array) : 0)\n    {\n    }\n    ~JObjectArrayAccessor()\n    {\n    }\n\n    // Not implemented\n    JObjectArrayAccessor(JObjectArrayAccessor&&) = delete;\n    JObjectArrayAccessor& operator=(JObjectArrayAccessor&&) = delete;\n    JObjectArrayAccessor(const JObjectArrayAccessor&) = delete;\n    JObjectArrayAccessor& operator=(const JObjectArrayAccessor&) = delete;\n\n    inline jsize size() const noexcept\n    {\n        return m_size;\n    }\n\n    inline AccessorType operator[](const int index) const noexcept\n    {\n        return AccessorType(m_env, static_cast<ObjectType>(m_env->GetObjectArrayElement(m_jobject_array, index)));\n    }\n\nprivate:\n    JNIEnv* m_env;\n    jobjectArray m_jobject_array;\n    jsize m_size;\n};\n\ntemplate<>\ninline JStringAccessor JObjectArrayAccessor<JStringAccessor,jstring>::operator[](const int index) const noexcept {\n    return JStringAccessor(m_env, static_cast<jstring>(m_env->GetObjectArrayElement(m_jobject_array, index)), true);\n}\n\n// An object accessor context which can be used to create and access objects\n// using util::Any as the type-erased value type. In addition, this serves as\n// the reference implementation of an accessor context that must be implemented\n// by each binding.\nclass JavaAccessorContext {\npublic:\n    JavaAccessorContext(JNIEnv* env)\n        : m_env(env){}\n\n    // Convert from core types to the boxed type\n    util::Any box(BinaryData v) const\n    {\n        return reinterpret_cast<jobject>(JavaClassGlobalDef::new_byte_array(m_env, v));\n    }\n    util::Any box(List /*v*/) const\n    {\n        REALM_TERMINATE(\"not supported\");\n    }\n    util::Any box(Object /*v*/) const\n    {\n        REALM_TERMINATE(\"not supported\");\n    }\n    util::Any box(Results /*v*/) const\n    {\n        REALM_TERMINATE(\"not supported\");\n    }\n    util::Any box(StringData v) const\n    {\n        return reinterpret_cast<jobject>(to_jstring(m_env, v));\n    }\n    util::Any box(Timestamp v) const\n    {\n        return JavaClassGlobalDef::new_date(m_env, v);\n    }\n    util::Any box(Decimal v) const\n    {\n        return JavaClassGlobalDef::new_decimal128(m_env, v);\n    }\n    util::Any box(ObjectId v) const\n    {\n        return JavaClassGlobalDef::new_object_id(m_env, v);\n    }\n    util::Any box(UUID v) const\n    {\n        return JavaClassGlobalDef::new_uuid(m_env, v);\n    }\n    util::Any box(Mixed v) const\n    {\n        return JavaClassGlobalDef::new_mixed(m_env, v);\n    }\n    util::Any box(bool v) const\n    {\n        return _impl::JavaClassGlobalDef::new_boolean(m_env, v);\n    }\n    util::Any box(double v) const\n    {\n        return _impl::JavaClassGlobalDef::new_double(m_env, v);\n    }\n    util::Any box(float v) const\n    {\n        return _impl::JavaClassGlobalDef::new_float(m_env, v);\n    }\n    util::Any box(int64_t v) const\n    {\n        return _impl::JavaClassGlobalDef::new_long(m_env, v);\n    }\n    util::Any box(util::Optional<bool> v) const\n    {\n        return v ? _impl::JavaClassGlobalDef::new_boolean(m_env, v.value()) : nullptr;\n    }\n    util::Any box(util::Optional<double> v) const\n    {\n        return v ? _impl::JavaClassGlobalDef::new_double(m_env, v.value()) : nullptr;\n    }\n    util::Any box(util::Optional<float> v) const\n    {\n        return v ? _impl::JavaClassGlobalDef::new_float(m_env, v.value()) : nullptr;\n    }\n    util::Any box(util::Optional<int64_t> v) const\n    {\n        return v ? _impl::JavaClassGlobalDef::new_long(m_env, v.value()) : nullptr;\n    }\n    util::Any box(util::Optional<Decimal> v) const\n    {\n        return v ? _impl::JavaClassGlobalDef::new_decimal128(m_env, v.value()) : nullptr;\n    }\n    util::Any box(util::Optional<ObjectId> v) const\n    {\n        return v ? _impl::JavaClassGlobalDef::new_object_id(m_env, v.value()) : nullptr;\n    }\n    util::Any box(util::Optional<UUID> v) const\n    {\n        return v ? _impl::JavaClassGlobalDef::new_uuid(m_env, v.value()) : nullptr;\n    }\n    util::Any box(Obj) const\n    {\n        REALM_TERMINATE(\"not supported\");\n    }\n\n    bool is_null(util::Any value) {\n        return !value.has_value();\n    }\n\n    // Convert from the boxed type to core types. This needs to be implemented\n    // for all of the types which `box()` can take, plus `RowExpr` and optional\n    // versions of the numeric types, minus `List` and `Results`.\n    //\n    // `create` and `update` are only applicable to `unbox<RowExpr>`. If\n    // `create` is false then when given something which is not a managed Realm\n    // object `unbox()` should simply return a detached row expr, while if it's\n    // true then `unbox()` should create a new object in the context's Realm\n    // using the provided value. If `update` is true then upsert semantics\n    // should be used for this.\n    template <typename T>\n    T unbox(util::Any& v, CreatePolicy = CreatePolicy::Skip, ObjKey /*current_row*/ = ObjKey()) const\n    {\n        return util::any_cast<T>(v);\n    }\n\nprivate:\n    JNIEnv* m_env;\n\n    inline void check_value_not_null(util::Any& v, const char* expected_type) const\n    {\n        if (!v.has_value()) {\n            THROW_JAVA_EXCEPTION(\n                m_env, JavaExceptionDef::IllegalArgument,\n                util::format(\"This field is required. A non-null '%1' type value is expected.\", expected_type));\n        }\n    }\n};\n\n// Accessor for jbyteArray\ntemplate <>\ninline JPrimitiveArrayAccessor<jbyteArray, jbyte>::ElementsHolder::ElementsHolder(JNIEnv* env, jbyteArray jarray)\n    : m_env(env)\n    , m_jarray(jarray)\n    , m_data_ptr(jarray ? env->GetByteArrayElements(jarray, nullptr) : nullptr)\n{\n}\n\ntemplate <>\ninline JPrimitiveArrayAccessor<jbyteArray, jbyte>::ElementsHolder::~ElementsHolder()\n{\n    if (m_jarray) {\n        m_env->ReleaseByteArrayElements(m_jarray, m_data_ptr, m_release_mode);\n    }\n}\n\ntemplate <>\ntemplate <>\ninline BinaryData JPrimitiveArrayAccessor<jbyteArray, jbyte>::transform<BinaryData>()\n{\n    // To solve the link issue by directly using Table::max_binary_size\n    static constexpr size_t max_binary_size = Table::max_binary_size;\n\n    if (static_cast<size_t>(m_size) > max_binary_size) {\n        THROW_JAVA_EXCEPTION(m_elements_holder->m_env, JavaExceptionDef::IllegalArgument,\n                             util::format(\"The length of 'byte[]' value is %1 which exceeds the max binary size %2.\",\n                                 m_size, max_binary_size));\n    }\n    return is_null() ? realm::BinaryData()\n                     : realm::BinaryData(reinterpret_cast<const char*>(m_elements_holder->m_data_ptr), m_size);\n}\n\ntemplate <>\ntemplate <>\ninline std::vector<char> JPrimitiveArrayAccessor<jbyteArray, jbyte>::transform<std::vector<char>>()\n{\n    if (is_null()) {\n        return {};\n    }\n\n    std::vector<char> v(m_size);\n    std::copy_n(m_elements_holder->m_data_ptr, v.size(), v.begin());\n    return v;\n}\n\n// Accessor for jbooleanArray\ntemplate <>\ninline JPrimitiveArrayAccessor<jbooleanArray, jboolean>::ElementsHolder::ElementsHolder(JNIEnv* env,\n                                                                                        jbooleanArray jarray)\n    : m_env(env)\n    , m_jarray(jarray)\n    , m_data_ptr(jarray ? env->GetBooleanArrayElements(jarray, nullptr) : nullptr)\n{\n}\n\ntemplate <>\ninline JPrimitiveArrayAccessor<jbooleanArray, jboolean>::ElementsHolder::~ElementsHolder()\n{\n    if (m_jarray) {\n        m_env->ReleaseBooleanArrayElements(m_jarray, m_data_ptr, m_release_mode);\n    }\n}\n\n// Accessor for jlongArray\ntemplate <>\ninline JPrimitiveArrayAccessor<jlongArray, jlong>::ElementsHolder::ElementsHolder(JNIEnv* env, jlongArray jarray)\n    : m_env(env)\n    , m_jarray(jarray)\n    , m_data_ptr(jarray ? env->GetLongArrayElements(jarray, nullptr) : nullptr)\n{\n}\n\ntemplate <>\ninline JPrimitiveArrayAccessor<jlongArray, jlong>::ElementsHolder::~ElementsHolder()\n{\n    if (m_jarray) {\n        m_env->ReleaseLongArrayElements(m_jarray, m_data_ptr, m_release_mode);\n    }\n}\n\n// Accessor for jfloatArray\ntemplate <>\ninline JPrimitiveArrayAccessor<jfloatArray, jfloat>::ElementsHolder::ElementsHolder(JNIEnv* env, jfloatArray jarray)\n    : m_env(env)\n    , m_jarray(jarray)\n    , m_data_ptr(jarray ? env->GetFloatArrayElements(jarray, nullptr) : nullptr)\n{\n}\n\ntemplate <>\ninline JPrimitiveArrayAccessor<jfloatArray, jfloat>::ElementsHolder::~ElementsHolder()\n{\n    if (m_jarray) {\n        m_env->ReleaseFloatArrayElements(m_jarray, m_data_ptr, m_release_mode);\n    }\n}\n\n// Accessor for jdoubleArray\ntemplate <>\ninline JPrimitiveArrayAccessor<jdoubleArray , jdouble>::ElementsHolder::ElementsHolder(JNIEnv* env, jdoubleArray jarray)\n    : m_env(env)\n    , m_jarray(jarray)\n    , m_data_ptr(jarray ? env->GetDoubleArrayElements(jarray, nullptr) : nullptr)\n{\n}\n\ntemplate <>\ninline JPrimitiveArrayAccessor<jdoubleArray, jdouble>::ElementsHolder::~ElementsHolder()\n{\n    if (m_jarray) {\n        m_env->ReleaseDoubleArrayElements(m_jarray, m_data_ptr, m_release_mode);\n    }\n}\n\ntemplate <>\ninline bool JavaAccessorContext::unbox(util::Any& v, CreatePolicy, ObjKey) const\n{\n    check_value_not_null(v, \"Boolean\");\n    return util::any_cast<jboolean>(v) == JNI_TRUE;\n}\n\ntemplate <>\ninline int64_t JavaAccessorContext::unbox(util::Any& v, CreatePolicy, ObjKey) const\n{\n    check_value_not_null(v, \"Long\");\n    return static_cast<int64_t>(util::any_cast<jlong>(v));\n}\n\ntemplate <>\ninline double JavaAccessorContext::unbox(util::Any& v, CreatePolicy, ObjKey) const\n{\n    check_value_not_null(v, \"Double\");\n    return static_cast<double>(util::any_cast<jdouble>(v));\n}\n\ntemplate <>\ninline float JavaAccessorContext::unbox(util::Any& v, CreatePolicy, ObjKey) const\n{\n    check_value_not_null(v, \"Float\");\n    return static_cast<float>(util::any_cast<jfloat>(v));\n}\n\ntemplate <>\ninline StringData JavaAccessorContext::unbox(util::Any& v, CreatePolicy, ObjKey) const\n{\n    if (!v.has_value()) {\n        return StringData();\n    }\n    auto& value = util::any_cast<JStringAccessor&>(v);\n    return value;\n}\n\ntemplate <>\ninline BinaryData JavaAccessorContext::unbox(util::Any& v, CreatePolicy, ObjKey) const\n{\n    if (!v.has_value())\n        return BinaryData();\n    auto& value = util::any_cast<JByteArrayAccessor&>(v);\n    return value.transform<BinaryData>();\n}\n\ntemplate <>\ninline Timestamp JavaAccessorContext::unbox(util::Any& v, CreatePolicy, ObjKey) const\n{\n    return v.has_value() ? from_milliseconds(util::any_cast<jlong>(v)) : Timestamp();\n}\n\ntemplate <>\ninline Decimal128 JavaAccessorContext::unbox(util::Any& v, CreatePolicy, ObjKey) const\n{\n    return v.has_value() ?  util::any_cast<Decimal128&>(v) : Decimal128(realm::null());\n}\n\ntemplate <>\ninline util::Optional<ObjectId> JavaAccessorContext::unbox(util::Any& v, CreatePolicy, ObjKey) const\n{\n    return v.has_value() ?  util::make_optional(util::any_cast<ObjectId&>(v)) : util::none;\n}\n\ntemplate <>\ninline util::Optional<UUID> JavaAccessorContext::unbox(util::Any& v, CreatePolicy, ObjKey) const\n{\n    return v.has_value() ?  util::make_optional(util::any_cast<UUID&>(v)) : util::none;\n}\n\ntemplate <>\ninline Obj JavaAccessorContext::unbox(util::Any&, CreatePolicy, ObjKey) const\n{\n    REALM_TERMINATE(\"not supported\");\n}\n\ntemplate <>\ninline util::Optional<bool> JavaAccessorContext::unbox(util::Any& v, CreatePolicy, ObjKey) const\n{\n    return v.has_value() ? util::make_optional(util::any_cast<jboolean>(v) == JNI_TRUE) : util::none;\n}\n\ntemplate <>\ninline util::Optional<int64_t> JavaAccessorContext::unbox(util::Any& v, CreatePolicy, ObjKey) const\n{\n    return v.has_value() ? util::make_optional(static_cast<int64_t>(util::any_cast<jlong>(v))) : util::none;\n}\n\ntemplate <>\ninline util::Optional<double> JavaAccessorContext::unbox(util::Any& v, CreatePolicy, ObjKey) const\n{\n    return v.has_value() ? util::make_optional(util::any_cast<jdouble>(v)) : util::none;\n}\n\ntemplate <>\ninline util::Optional<float> JavaAccessorContext::unbox(util::Any& v, CreatePolicy, ObjKey) const\n{\n    return v.has_value() ? util::make_optional(util::any_cast<jfloat>(v)) : util::none;\n}\n\ntemplate <>\ninline Mixed JavaAccessorContext::unbox(util::Any& v, CreatePolicy, ObjKey) const\n{\n    return v.has_value() ?  util::any_cast<Mixed&>(v) : Mixed();\n}\n\n} // namespace realm\n} // namespace _impl\n\n#endif // REALM_JNI_IMPL_JAVA_ACCESSOR_HPP\n"
  },
  {
    "path": "realm/realm-library/src/main/cpp/java_binding_context.cpp",
    "content": "/*\n * Copyright 2016 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#include \"java_binding_context.hpp\"\n#include \"java_class_global_def.hpp\"\n#include \"jni_util/java_method.hpp\"\n\n#include \"util.hpp\"\n\nusing namespace realm;\nusing namespace realm::_impl;\nusing namespace realm::jni_util;\n\nvoid JavaBindingContext::before_notify()\n{\n    if (JniUtils::get_env()->ExceptionCheck()) {\n        return;\n    }\n    if (m_java_notifier) {\n        m_java_notifier.call_with_local_ref([&](JNIEnv* env, jobject notifier_obj) {\n            // Method IDs from RealmNotifier implementation. Cache them as member vars.\n            static JavaMethod notify_by_other_method(env, JavaClassGlobalDef::realm_notifier(), \"beforeNotify\",\n                                                     \"()V\");\n            env->CallVoidMethod(notifier_obj, notify_by_other_method);\n        });\n    }\n}\n\nvoid JavaBindingContext::did_change(std::vector<BindingContext::ObserverState> const&, std::vector<void*> const&,\n                                    bool version_changed)\n{\n    auto env = JniUtils::get_env();\n    if (env->ExceptionCheck()) {\n        return;\n    }\n    if (version_changed) {\n        m_java_notifier.call_with_local_ref(env, [&](JNIEnv*, jobject notifier_obj) {\n            static JavaMethod realm_notifier_did_change_method(env, JavaClassGlobalDef::realm_notifier(), \"didChange\",\n                                                               \"()V\");\n            env->CallVoidMethod(notifier_obj, realm_notifier_did_change_method);\n        });\n    }\n}\n\nvoid JavaBindingContext::schema_did_change(Schema const&)\n{\n    if (!m_schema_changed_callback) {\n        return;\n    }\n    auto env = JniUtils::get_env(false);\n    if (env->ExceptionCheck()) {\n        return;\n    }\n    static JavaMethod on_schema_changed_method(env, JavaClassGlobalDef::shared_realm_schema_change_callback(),\n                                               \"onSchemaChanged\", \"()V\");\n    m_schema_changed_callback.call_with_local_ref(\n        env, [](JNIEnv* env, jobject callback_obj) { env->CallVoidMethod(callback_obj, on_schema_changed_method); });\n}\n\nvoid JavaBindingContext::set_schema_changed_callback(JNIEnv* env, jobject schema_changed_callback)\n{\n    m_schema_changed_callback = JavaGlobalWeakRef(env, schema_changed_callback);\n}\n\nvoid JavaBindingContext::will_send_notifications() {\n    auto env = JniUtils::get_env();\n    if (env->ExceptionCheck()) {\n        return;\n    }\n    m_java_notifier.call_with_local_ref(env, [&](JNIEnv*, jobject notifier_obj) {\n        static JavaMethod realm_notifier_will_send_notifications(env, JavaClassGlobalDef::realm_notifier(),\n                                                           \"willSendNotifications\", \"()V\");\n        env->CallVoidMethod(notifier_obj, realm_notifier_will_send_notifications);\n    });\n}\n\nvoid JavaBindingContext::did_send_notifications() {\n    auto env = JniUtils::get_env();\n    if (env->ExceptionCheck()) {\n        return;\n    }\n    m_java_notifier.call_with_local_ref(env, [&](JNIEnv*, jobject notifier_obj) {\n        static JavaMethod realm_notifier_did_send_notifications(env, JavaClassGlobalDef::realm_notifier(),\n                                                                 \"didSendNotifications\", \"()V\");\n        env->CallVoidMethod(notifier_obj, realm_notifier_did_send_notifications);\n    });\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/cpp/java_binding_context.hpp",
    "content": "/*\n * Copyright 2016 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#ifndef JAVA_BINDING_CONTEXT_HPP\n#define JAVA_BINDING_CONTEXT_HPP\n\n#include <jni.h>\n#include <memory>\n\n#include <realm/object-store/binding_context.hpp>\n\n#include \"jni_util/java_global_weak_ref.hpp\"\n\nnamespace realm {\n\nnamespace _impl {\n// Binding context which will be called from OS.\nclass JavaBindingContext final : public BindingContext {\nprivate:\n    struct ConcreteJavaBindContext {\n        JNIEnv* jni_env;\n        jobject java_notifier;\n    };\n\n    // Weak global refs to the needed Java objects.\n    // Java should hold a strong ref to them as long as the SharedRealm lives\n    jni_util::JavaGlobalWeakRef m_java_notifier;\n    jni_util::JavaGlobalWeakRef m_schema_changed_callback;\n\npublic:\n    virtual ~JavaBindingContext(){};\n    void before_notify() override;\n    void did_change(std::vector<ObserverState> const& observers, std::vector<void*> const& invalidated,\n                    bool version_changed = true) override;\n    void schema_did_change(Schema const&) override;\n    void will_send_notifications() override;\n    void did_send_notifications() override;\n    explicit JavaBindingContext(const ConcreteJavaBindContext& concrete_context)\n        : m_java_notifier(concrete_context.jni_env, concrete_context.java_notifier)\n        , m_schema_changed_callback()\n    {\n    }\n    JavaBindingContext(const JavaBindingContext&) = delete;\n    JavaBindingContext& operator=(const JavaBindingContext&) = delete;\n    JavaBindingContext(JavaBindingContext&&) = delete;\n    JavaBindingContext& operator=(JavaBindingContext&&) = delete;\n\n    void set_schema_changed_callback(JNIEnv* env, jobject schema_changed_callback);\n\n    static inline std::unique_ptr<JavaBindingContext> create(JNIEnv* env, jobject notifier)\n    {\n        return std::make_unique<JavaBindingContext>(ConcreteJavaBindContext{env, notifier});\n    };\n};\n\n} // namespace _impl\n\n} // namespace realm\n\n#endif\n"
  },
  {
    "path": "realm/realm-library/src/main/cpp/java_class_global_def.cpp",
    "content": "/*\n * Copyright 2017 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#include \"realm/array_blob.hpp\"\n\n#include \"java_object_accessor.hpp\"\n#include \"java_class_global_def.hpp\"\n#include \"java_exception_def.hpp\"\n#include \"jni_util/java_exception_thrower.hpp\"\n\nusing namespace realm;\nusing namespace realm::_impl;\n\njbyteArray JavaClassGlobalDef::new_byte_array(JNIEnv* env, const BinaryData& binary_data)\n{\n    static_assert(MAX_JSIZE >= ArrayBlob::max_binary_size, \"ArrayBlob's max size is too big.\");\n\n    if (binary_data.is_null()) {\n        return nullptr;\n    }\n\n    auto size = static_cast<jsize>(binary_data.size());\n    jbyteArray ret = env->NewByteArray(size);\n    if (!ret) {\n        THROW_JAVA_EXCEPTION(env, JavaExceptionDef::OutOfMemory,\n                             util::format(\"'NewByteArray' failed with size %1.\", size));\n    }\n\n    env->SetByteArrayRegion(ret, 0, size, reinterpret_cast<const jbyte*>(binary_data.data()));\n    return ret;\n}\n\n\njobject JavaClassGlobalDef::new_decimal128(JNIEnv* env, const Decimal128& decimal128)\n{\n    if (decimal128.is_null()) {\n        return nullptr;\n    }\n    static jni_util::JavaMethod fromIEEE754BIDEncoding(env, instance()->m_bson_decimal128, \"fromIEEE754BIDEncoding\", \"(JJ)Lorg/bson/types/Decimal128;\", true);\n    const Decimal128::Bid128* raw = decimal128.raw();\n    return env->CallStaticObjectMethod(instance()->m_bson_decimal128, fromIEEE754BIDEncoding, static_cast<jlong>(raw->w[1]), static_cast<jlong>(raw->w[0]));\n}\n\njobject JavaClassGlobalDef::new_object_id(JNIEnv* env, const ObjectId& objectId)\n{\n    static jni_util::JavaMethod init(env, instance()->m_bson_object_id, \"<init>\", \"(Ljava/lang/String;)V\");\n    return env->NewObject(instance()->m_bson_object_id, init, to_jstring(env, objectId.to_string().data()));\n}\n\njobject JavaClassGlobalDef::new_uuid(JNIEnv* env, const UUID& uuid)\n{\n    static jni_util::JavaMethod from_string(env, instance()->m_java_util_uuid, \"fromString\", \"(Ljava/lang/String;)Ljava/util/UUID;\", true);\n    return env->CallStaticObjectMethod(instance()->m_java_util_uuid, from_string, to_jstring(env, uuid.to_string().data()));\n}\n\njobject JavaClassGlobalDef::new_mixed(JNIEnv* env, const Mixed& mixed)\n{\n    static jni_util::JavaMethod init(env, instance()->m_io_realm_internal_core_native_mixed, \"<init>\", \"(J)V\");\n    JavaValue *pValue = new JavaValue(from_mixed(mixed));\n    // ARM 32 doesn't convert the pointer correct, so do explicit cast\n    jlong nativePtr = reinterpret_cast<jlong>(pValue);\n    return env->NewObject(instance()->m_io_realm_internal_core_native_mixed, init, nativePtr);\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/cpp/java_class_global_def.hpp",
    "content": "/*\n * Copyright 2017 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#ifndef REALM_JNI_IMPL_CLASS_GLOBAL_DEF_HPP\n#define REALM_JNI_IMPL_CLASS_GLOBAL_DEF_HPP\n\n#include \"util.hpp\"\n#include \"jni_util/java_class.hpp\"\n#include \"jni_util/java_method.hpp\"\n\n#include <memory>\n\n#include <realm/util/assert.hpp>\n\nnamespace realm {\n\nclass BinaryData;\n\nnamespace _impl {\n\n// Manage a global static jclass pool which will be initialized when JNI_OnLoad() called.\n// FindClass is a relatively slow operation, loading all the needed classes when start is not good since usually user\n// will call Realm.init() when the app starts.\n// Instead, we only load necessary classes including:\n// 1. Common types which might be used everywhere. (Boxed types, String, etc.)\n// 2. Classes which might be initialized in the native thread.\n//\n// FindClass will fail if it is called from a native thread (e.g.: the sync client thread.). But usually it is not a\n// problem if the FindClass is called from an JNI method. So keeping a static JavaClass var locally is still preferred\n// if it is possible.\nclass JavaClassGlobalDef {\nprivate:\n    JavaClassGlobalDef(JNIEnv* env)\n        : m_java_lang_long(env, \"java/lang/Long\", false)\n        , m_java_lang_float(env, \"java/lang/Float\", false)\n        , m_java_lang_double(env, \"java/lang/Double\", false)\n        , m_java_util_date(env, \"java/util/Date\", false)\n        , m_java_lang_string(env, \"java/lang/String\", false)\n        , m_java_lang_boolean(env, \"java/lang/Boolean\", false)\n        , m_java_lang_object(env, \"java/lang/Object\", false)\n        , m_shared_realm_schema_change_callback(env, \"io/realm/internal/OsSharedRealm$SchemaChangedCallback\", false)\n        , m_realm_notifier(env, \"io/realm/internal/RealmNotifier\", false)\n        , m_bson_decimal128(env, \"org/bson/types/Decimal128\", false)\n        , m_bson_object_id(env, \"org/bson/types/ObjectId\", false)\n        , m_java_util_uuid(env, \"java/util/UUID\", false)\n        , m_io_realm_internal_core_native_mixed(env, \"io/realm/internal/core/NativeRealmAny\", false)\n#if REALM_ENABLE_SYNC\n        , m_network_transport_response(env, \"io/realm/internal/objectstore/OsJavaNetworkTransport$Response\", false)\n#endif\n    {\n    }\n\n    jni_util::JavaClass m_java_lang_long;\n    jni_util::JavaClass m_java_lang_float;\n    jni_util::JavaClass m_java_lang_double;\n    jni_util::JavaClass m_java_util_date;\n    jni_util::JavaClass m_java_lang_string;\n    jni_util::JavaClass m_java_lang_boolean;\n    jni_util::JavaClass m_java_lang_object;\n\n    jni_util::JavaClass m_shared_realm_schema_change_callback;\n    jni_util::JavaClass m_realm_notifier;\n    jni_util::JavaClass m_bson_decimal128;\n    jni_util::JavaClass m_bson_object_id;\n    jni_util::JavaClass m_java_util_uuid;\n    jni_util::JavaClass m_io_realm_internal_core_native_mixed;\n\n#if REALM_ENABLE_SYNC\n    jni_util::JavaClass m_network_transport_response;\n#endif\n\n    inline static std::unique_ptr<JavaClassGlobalDef>& instance()\n    {\n        static std::unique_ptr<JavaClassGlobalDef> instance;\n        return instance;\n    };\n\npublic:\n    // Called in JNI_OnLoad\n    static void initialize(JNIEnv* env)\n    {\n        REALM_ASSERT(!instance());\n        instance().reset(new JavaClassGlobalDef(env));\n    }\n    // Called in JNI_OnUnload\n    static void release()\n    {\n        REALM_ASSERT(instance());\n        instance().release();\n    }\n\n    // java.lang.Long\n    inline static jobject new_long(JNIEnv* env, int64_t value)\n    {\n        static jni_util::JavaMethod init(env, instance()->m_java_lang_long, \"<init>\", \"(J)V\");\n        return env->NewObject(instance()->m_java_lang_long, init, value);\n    }\n    inline static const jni_util::JavaClass& java_lang_long()\n    {\n        return instance()->m_java_lang_long;\n    }\n\n    // java.lang.Float\n    inline static jobject new_float(JNIEnv* env, float value)\n    {\n        static jni_util::JavaMethod init(env, instance()->m_java_lang_float, \"<init>\", \"(F)V\");\n        return env->NewObject(instance()->m_java_lang_float, init, value);\n    }\n    inline static const jni_util::JavaClass& java_lang_float()\n    {\n        return instance()->m_java_lang_float;\n    }\n\n    // java.lang.Double\n    inline static jobject new_double(JNIEnv* env, double value)\n    {\n        static jni_util::JavaMethod init(env, instance()->m_java_lang_double, \"<init>\", \"(D)V\");\n        return env->NewObject(instance()->m_java_lang_double, init, value);\n    }\n    inline static const jni_util::JavaClass& java_lang_double()\n    {\n        return instance()->m_java_lang_double;\n    }\n\n    // java.lang.Boolean\n    inline static jobject new_boolean(JNIEnv* env, bool value)\n    {\n        static jni_util::JavaMethod init(env, instance()->m_java_lang_boolean, \"<init>\", \"(Z)V\");\n        return env->NewObject(instance()->m_java_lang_boolean, init, value ? JNI_TRUE : JNI_FALSE);\n    }\n    inline static const jni_util::JavaClass& java_lang_boolean()\n    {\n        return instance()->m_java_lang_boolean;\n    }\n\n    // java.util.Date\n    // return nullptr if ts is null\n    inline static jobject new_date(JNIEnv* env, const realm::Timestamp& ts)\n    {\n        if (ts.is_null()) {\n            return nullptr;\n        }\n        static jni_util::JavaMethod init(env, instance()->m_java_util_date, \"<init>\", \"(J)V\");\n        return env->NewObject(instance()->m_java_util_date, init, to_milliseconds(ts));\n    }\n    inline static const jni_util::JavaClass& java_util_date()\n    {\n        return instance()->m_java_util_date;\n    }\n\n    // java.util.String\n    inline static const jni_util::JavaClass& java_lang_string()\n    {\n        return instance()->m_java_lang_string;\n    }\n\n    // byte[]\n    // return nullptr if binary_data is null\n    static jbyteArray new_byte_array(JNIEnv* env, const BinaryData& binary_data);\n\n    static jobject new_decimal128(JNIEnv* env, const Decimal128& decimal128);\n\n    static jobject new_object_id(JNIEnv* env, const ObjectId& objectId);\n\n    static jobject new_uuid(JNIEnv* env, const UUID& uuid);\n\n    static jobject new_mixed(JNIEnv* env, const Mixed& mixed);\n\n    // io.realm.internal.OsSharedRealm.SchemaChangedCallback\n    inline static const jni_util::JavaClass& shared_realm_schema_change_callback()\n    {\n        return instance()->m_shared_realm_schema_change_callback;\n    }\n\n    // io.realm.internal.RealmNotifier\n    inline static const jni_util::JavaClass& realm_notifier()\n    {\n        return instance()->m_realm_notifier;\n    }\n\n    // java.lang.Object\n    inline static const jni_util::JavaClass& java_lang_object()\n    {\n        return instance()->m_java_lang_object;\n    }\n\n#if REALM_ENABLE_SYNC\n    inline static const jni_util::JavaClass& network_transport_response_class()\n    {\n        return instance()->m_network_transport_response;\n    }\n#endif\n};\n\n} // namespace realm\n} // namespace jni_impl\n\n\n#endif // REALM_JNI_IMPL_CLASS_GLOBAL_DEF_HPP\n"
  },
  {
    "path": "realm/realm-library/src/main/cpp/java_exception_def.cpp",
    "content": "/*\n * Copyright 2017 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#include \"java_exception_def.hpp\"\n\nusing namespace realm::_impl;\n\nconst char* JavaExceptionDef::IllegalState = \"java/lang/IllegalStateException\";\nconst char* JavaExceptionDef::IllegalArgument = \"java/lang/IllegalArgumentException\";\nconst char* JavaExceptionDef::OutOfMemory = \"java/lang/OutOfMemoryError\";\nconst char* JavaExceptionDef::RealmMigrationNeeded = \"io/realm/exceptions/RealmMigrationNeededException\";\nconst char* JavaExceptionDef::NullPointerException = \"java/lang/NullPointerException\";\n"
  },
  {
    "path": "realm/realm-library/src/main/cpp/java_exception_def.hpp",
    "content": "/*\n * Copyright 2017 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#ifndef REALM_JNI_IMPL_EXCEPTION_DEF_HPP\n#define REALM_JNI_IMPL_EXCEPTION_DEF_HPP\n\nnamespace realm {\nnamespace _impl {\n\n// Definitions of Java exceptions which are used in JNI.\nclass JavaExceptionDef {\npublic:\n    // Class names\n    static const char* IllegalState;\n    static const char* IllegalArgument;\n    static const char* OutOfMemory;\n    static const char* RealmMigrationNeeded;\n    static const char* NullPointerException;\n};\n\n} // namespace realm\n} // namespace jni_impl\n\n#endif\n"
  },
  {
    "path": "realm/realm-library/src/main/cpp/java_network_transport.hpp",
    "content": "/*\n * Copyright 2020 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#ifndef REALM_JAVA_NETWORK_TRANSPORT\n#define REALM_JAVA_NETWORK_TRANSPORT\n\n#include \"java_accessor.hpp\"\n#include \"util.hpp\"\n#include <realm/object-store/sync/generic_network_transport.hpp>\n#include \"jni_util/java_class.hpp\"\n#include \"jni_util/java_method.hpp\"\n#include \"jni_util/jni_utils.hpp\"\n\nusing namespace realm::app;\nusing namespace realm::jni_util;\nusing namespace realm::_impl;\n\nnamespace realm {\n\nusing ResponseFunction = util::UniqueFunction<void(const app::Response&)>;\n\nstruct JavaNetworkTransport : public app::GenericNetworkTransport {\n\n    JavaNetworkTransport(jobject java_network_transport_impl) {\n        JNIEnv* env = JniUtils::get_env(true);\n        m_java_network_transport_impl = env->NewGlobalRef(java_network_transport_impl);\n        jclass cls = env->GetObjectClass(m_java_network_transport_impl);\n        auto method_name = \"sendRequestAsync\";\n        auto signature = \"(Ljava/lang/String;Ljava/lang/String;JLjava/util/Map;Ljava/lang/String;J)V\";\n        m_send_request_method = env->GetMethodID(cls, method_name, signature);\n        REALM_ASSERT_RELEASE_EX(m_send_request_method != nullptr, method_name, signature);\n    }\n\n    void send_request_to_server(const Request& request, ResponseFunction&& completion)  {\n        JNIEnv* env = JniUtils::get_env(true);\n\n        // Setup method\n        std::string method;\n        switch(request.method) {\n            case app::HttpMethod::get: method = \"get\"; break;\n            case app::HttpMethod::post: method = \"post\"; break;\n            case app::HttpMethod::patch: method = \"patch\"; break;\n            case app::HttpMethod::put: method = \"put\"; break;\n            case app::HttpMethod::del: method = \"delete\"; break;\n        }\n\n        // Create headers\n        static JavaClass mapClass(env, \"java/util/HashMap\");\n        static JavaMethod init(env, mapClass, \"<init>\", \"(I)V\");\n        static JavaMethod put_method(env, mapClass, \"put\", \"(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;\");\n        size_t map_size = request.headers.size();\n        jobject request_headers = env->NewObject(mapClass, init, (jsize) map_size);\n        for (auto header : request.headers) {\n            jstring key = to_jstring(env, header.first);\n            jstring value = to_jstring(env, header.second);\n            env->CallObjectMethod(request_headers, put_method, key, value);\n            env->DeleteLocalRef(key);\n            env->DeleteLocalRef(value);\n        }\n\n        // Execute network request on the Java side\n        jstring jmethod = to_jstring(env, method);\n        jstring jurl = to_jstring(env, request.url);\n        jstring jbody = to_jstring(env, request.body);\n        env->CallVoidMethod(\n                m_java_network_transport_impl,\n                m_send_request_method,\n                jmethod,\n                jurl,\n                static_cast<jlong>(request.timeout_ms),\n                request_headers,\n                jbody,\n                new ResponseFunction(std::move(completion))\n        );\n        env->DeleteLocalRef(jmethod);\n        env->DeleteLocalRef(jurl);\n        env->DeleteLocalRef(jbody);\n        env->DeleteLocalRef(request_headers);\n    }\n\n    static void handleError(const JavaGlobalRefByCopy &callback, util::Optional<AppError> &error, JNIEnv *env,\n                            const JavaClass &java_callback_class) {\n        static JavaMethod java_notify_onerror(env, java_callback_class, \"onError\", \"(BILjava/lang/String;Ljava/lang/String;)V\");\n        auto err = error.value();\n        jbyte category = categoryAsJByte(err.to_status());\n        int error_code = err.is_custom_error() || err.is_http_error() ? err.additional_status_code.value() : err.code();\n        env->CallVoidMethod(callback.get(),\n                            java_notify_onerror,\n                            category,\n                            error_code,\n                            to_jstring(env, err.what()),\n                            to_jstring(env, err.link_to_server_logs));\n    }\n\n    // Helper method for constructing callbacks for REST calls that must return an actual result to Java\n    template<typename T>\n    static util::UniqueFunction<void(T, util::Optional<app::AppError>&&)> create_result_callback(JNIEnv* env, jobject j_callback, const std::function<jobject (JNIEnv*, T)>& success_mapper) {\n        return [callback = JavaGlobalRefByCopy(env, j_callback), success_mapper](T result, util::Optional<app::AppError>&& error) {\n            JNIEnv* env = JniUtils::get_env(true);\n            static JavaClass java_callback_class(env, \"io/realm/internal/network/NetworkRequest\");\n\n            if (error) {\n                handleError(callback, error, env, java_callback_class);\n            } else {\n                static JavaMethod java_notify_onsuccess(env, java_callback_class, \"onSuccess\", \"(Ljava/lang/Object;)V\");\n                jobject success_obj = success_mapper(env, result);\n                env->CallVoidMethod(callback.get(), java_notify_onsuccess, success_obj);\n            }\n        };\n    }\n\n    // Helper method for constructing callbacks for REST calls that doesn't return any results to Java.\n    static util::UniqueFunction<void(util::Optional<app::AppError>)> create_void_callback(JNIEnv* env, jobject j_callback) {\n        return [callback = JavaGlobalRefByCopy(env, j_callback)](util::Optional<app::AppError> error) {\n            JNIEnv* env = JniUtils::get_env(true);\n\n            static JavaClass java_callback_class(env, \"io/realm/internal/network/NetworkRequest\");\n\n            if (error) {\n                handleError(callback, error, env, java_callback_class);\n            } else {\n                static JavaMethod java_notify_onsuccess(env, java_callback_class, \"onSuccess\", \"(Ljava/lang/Object;)V\");\n                env->CallVoidMethod(callback.get(), java_notify_onsuccess, NULL);\n            }\n        };\n    }\n\n    ~JavaNetworkTransport() {\n        JniUtils::get_env(true)->DeleteGlobalRef(m_java_network_transport_impl);\n    }\n\nprivate:\n    jobject m_java_network_transport_impl;     // Global ref of Java implementation of the network transport.\n    jmethodID m_send_request_method;\n};\n\n} // realm namespace\n\n#endif\n\n"
  },
  {
    "path": "realm/realm-library/src/main/cpp/java_object_accessor.hpp",
    "content": "////////////////////////////////////////////////////////////////////////////\n//\n// Copyright 2018 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\n#ifndef REALM_JAVA_OBJECT_ACCESSOR\n#define REALM_JAVA_OBJECT_ACCESSOR\n\n#include \"util.hpp\"\n#include <algorithm>\n#include <cstddef>\n#include <type_traits>\n\n#include \"java_accessor.hpp\"\n#include \"java_class_global_def.hpp\"\n#include <realm/object-store/object_accessor.hpp>\n#include <realm/object-store/property.hpp>\n\n#include <realm/decimal128.hpp>\n#include <realm/object_id.hpp>\n#include <realm/util/any.hpp>\n\nusing namespace realm::_impl;\n\n#define REALM_FOR_EACH_JAVA_VALUE_TYPE(X) \\\n    X(Integer) \\\n    X(String) \\\n    X(Boolean) \\\n    X(Float) \\\n    X(Double) \\\n    X(Date) \\\n    X(ObjectId) \\\n    X(UUID) \\\n    X(ObjectLink) \\\n    X(Mixed) \\\n    X(Decimal) \\\n    X(Binary) \\\n    X(Object) \\\n    X(List) \\\n    X(PropertyList) \\\n    X(Dictionary) \\\n\nnamespace realm {\n\nstruct JavaValue;\n\nenum class JavaValueType {\n    Empty,\n#define REALM_DEFINE_JAVA_VALUE_TYPE(x) x,\n    REALM_FOR_EACH_JAVA_VALUE_TYPE(REALM_DEFINE_JAVA_VALUE_TYPE)\n#undef REALM_DEFINE_JAVA_VALUE_TYPE\n    NumValueTypes\n};\n\n// Ugly work-around for initializer lists having problems on GCC 4.9\ntemplate <class T> constexpr T realm_max(T a) {\n    return a;\n}\n\ntemplate <class T, class... Rest> constexpr T realm_max(T a, T b, Rest... rest) {\n    return a > realm_max(b, rest...) ? a : realm_max(b, rest...);\n}\n\ntemplate <JavaValueType> struct JavaValueTypeRepr;\ntemplate <> struct JavaValueTypeRepr<JavaValueType::Integer>       { using Type = jlong; };\ntemplate <> struct JavaValueTypeRepr<JavaValueType::String>        { using Type = std::string; };\ntemplate <> struct JavaValueTypeRepr<JavaValueType::Boolean>       { using Type = jboolean; };\ntemplate <> struct JavaValueTypeRepr<JavaValueType::Float>         { using Type = jfloat; };\ntemplate <> struct JavaValueTypeRepr<JavaValueType::Double>        { using Type = jdouble; };\ntemplate <> struct JavaValueTypeRepr<JavaValueType::Date>          { using Type = Timestamp; };\ntemplate <> struct JavaValueTypeRepr<JavaValueType::ObjectId>      { using Type = ObjectId; };\ntemplate <> struct JavaValueTypeRepr<JavaValueType::Decimal>       { using Type = Decimal128; };\ntemplate <> struct JavaValueTypeRepr<JavaValueType::UUID>          { using Type = UUID; };\ntemplate <> struct JavaValueTypeRepr<JavaValueType::ObjectLink>    { using Type = ObjLink; };\ntemplate <> struct JavaValueTypeRepr<JavaValueType::Mixed>         { using Type = JavaValue*; };\ntemplate <> struct JavaValueTypeRepr<JavaValueType::Binary>        { using Type = OwnedBinaryData; };\ntemplate <> struct JavaValueTypeRepr<JavaValueType::Object>        { using Type = Obj*; };\ntemplate <> struct JavaValueTypeRepr<JavaValueType::List>          { using Type = std::vector<JavaValue>; };\ntemplate <> struct JavaValueTypeRepr<JavaValueType::PropertyList>  { using Type = std::map<ColKey, JavaValue>; };\ntemplate <> struct JavaValueTypeRepr<JavaValueType::Dictionary>    { using Type = std::map<std::string, JavaValue>; };\n\n// Tagged union class representing all the values Java can send to Object Store\nstruct JavaValue {\n    using Storage = std::aligned_storage_t<realm_max(\n#define REALM_GET_SIZE_OF_JAVA_VALUE_TYPE_REPR(x) \\\n        sizeof(JavaValueTypeRepr<JavaValueType::x>::Type),\n        REALM_FOR_EACH_JAVA_VALUE_TYPE(REALM_GET_SIZE_OF_JAVA_VALUE_TYPE_REPR)\n        size_t(0)\n#undef REALM_GET_SIZE_OF_JAVA_VALUE_TYPE_REPR\n        ), realm_max(\n#define REALM_GET_ALIGN_OF_JAVA_VALUE_TYPE_REPR(x) \\\n        alignof(JavaValueTypeRepr<JavaValueType::x>::Type),\n        REALM_FOR_EACH_JAVA_VALUE_TYPE(REALM_GET_ALIGN_OF_JAVA_VALUE_TYPE_REPR)\n        size_t(0)\n#undef REALM_GET_ALIGN_OF_JAVA_VALUE_TYPE_REPR\n        )>;\n\n    Storage m_storage;\n    JavaValueType m_type;\n\n    // Initializer constructors\n    JavaValue() : m_type(JavaValueType::Empty) {}\n\n#define REALM_DEFINE_JAVA_VALUE_TYPE_CONSTRUCTOR(x) \\\n    explicit JavaValue(JavaValueTypeRepr<JavaValueType::x>::Type value) : m_type(JavaValueType::x) \\\n    { \\\n        new(&m_storage) JavaValueTypeRepr<JavaValueType::x>::Type{std::move(value)}; \\\n    }\n    REALM_FOR_EACH_JAVA_VALUE_TYPE(REALM_DEFINE_JAVA_VALUE_TYPE_CONSTRUCTOR)\n#undef REALM_DEFINE_JAVA_VALUE_TYPE_CONSTRUCTOR\n\n    // Copy constructors\n    JavaValue(const JavaValue& jvt) : m_type(JavaValueType::Empty) {\n        *this = jvt;\n    }\n\n    // Move constructor\n    JavaValue(JavaValue&& jvt) : m_type(JavaValueType::Empty) {\n        *this = std::move(jvt);\n    }\n\n    ~JavaValue()\n    {\n        clear();\n    }\n\n    JavaValue& operator=(const JavaValue& rhs)\n    {\n       clear();\n       switch (rhs.m_type) {\n#define REALM_DEFINE_JAVA_VALUE_COPY_ASSIGNMENT(x) \\\n           case JavaValueType::x: { \\\n               using T = JavaValueTypeRepr<JavaValueType::x>::Type; \\\n               new(&m_storage) T{*reinterpret_cast<const T*>(&rhs.m_storage)}; \\\n               break; \\\n           }\n        REALM_FOR_EACH_JAVA_VALUE_TYPE(REALM_DEFINE_JAVA_VALUE_COPY_ASSIGNMENT)\n#undef REALM_DEFINE_JAVA_VALUE_COPY_ASSIGNMENT\n           default: REALM_ASSERT(rhs.m_type == JavaValueType::Empty);\n        }\n        m_type = rhs.m_type;\n        return *this;\n    }\n\n    JavaValue& operator=(JavaValue&& rhs)\n    {\n       clear();\n       switch (rhs.m_type) {\n           case JavaValueType::Empty: break; // Do nothing\n#define REALM_DEFINE_JAVA_VALUE_COPY_ASSIGNMENT(x) \\\n           case JavaValueType::x: { \\\n               using T = JavaValueTypeRepr<JavaValueType::x>::Type; \\\n               new(&m_storage) T{std::move(*reinterpret_cast<T*>(&rhs.m_storage))}; \\\n               break; \\\n           }\n        REALM_FOR_EACH_JAVA_VALUE_TYPE(REALM_DEFINE_JAVA_VALUE_COPY_ASSIGNMENT)\n#undef REALM_DEFINE_JAVA_VALUE_COPY_ASSIGNMENT\n           default: REALM_TERMINATE(\"Invalid type\");\n        }\n        m_type = rhs.m_type;\n        return *this;\n    }\n\n    bool has_value() const noexcept\n    {\n        return m_type != JavaValueType::Empty;\n    }\n\n    JavaValueType get_type() const noexcept\n    {\n        return m_type;\n    }\n\n    template <JavaValueType type>\n    const typename JavaValueTypeRepr<type>::Type& get_as() const noexcept\n    {\n        REALM_ASSERT(m_type == type);\n        return *reinterpret_cast<const typename JavaValueTypeRepr<type>::Type*>(&m_storage);\n    }\n\n    auto& get_int() const noexcept\n    {\n        return get_as<JavaValueType::Integer>();\n    }\n\n    auto& get_boolean() const noexcept\n    {\n        return get_as<JavaValueType::Boolean>();\n    }\n\n    auto& get_string() const noexcept\n    {\n        return get_as<JavaValueType::String>();\n    }\n\n    auto& get_float() const noexcept\n    {\n        return get_as<JavaValueType::Float>();\n    }\n\n    auto& get_double() const noexcept\n    {\n        return get_as<JavaValueType::Double>();\n    }\n\n    auto& get_list() const noexcept\n    {\n        return get_as<JavaValueType::List>();\n    }\n\n    auto& get_dictionary() const noexcept\n    {\n        return get_as<JavaValueType::Dictionary>();\n    }\n\n    auto& get_property_list() const noexcept\n    {\n        return get_as<JavaValueType::PropertyList>();\n    }\n\n\n    auto& get_date() const noexcept\n    {\n        return get_as<JavaValueType::Date>();\n    }\n\n    auto& get_object_id() const noexcept\n    {\n        return get_as<JavaValueType::ObjectId>();\n    }\n\n    auto& get_uuid() const noexcept\n    {\n        return get_as<JavaValueType::UUID>();\n    }\n\n    auto& get_mixed() const noexcept\n    {\n        return get_as<JavaValueType::Mixed>();\n    }\n\n    auto& get_object_link() const noexcept\n    {\n        return get_as<JavaValueType::ObjectLink>();\n    }\n\n    auto& get_decimal128() const noexcept\n    {\n        return get_as<JavaValueType::Decimal>();\n    }\n\n    auto& get_binary() const noexcept\n    {\n        return get_as<JavaValueType::Binary>();\n    }\n\n    auto& get_object() const noexcept\n    {\n        return get_as<JavaValueType::Object>();\n    }\n\n    void clear() noexcept\n    {\n        switch (m_type) {\n            case JavaValueType::Empty: break; // Do nothing\n#define REALM_DEFINE_JAVA_VALUE_DESTROY(x) \\\n            case JavaValueType::x: { \\\n                using T = JavaValueTypeRepr<JavaValueType::x>::Type; \\\n                reinterpret_cast<T*>(&m_storage)->~T(); \\\n                break; \\\n            }\n            REALM_FOR_EACH_JAVA_VALUE_TYPE(REALM_DEFINE_JAVA_VALUE_DESTROY)\n#undef REALM_DEFINE_JAVA_VALUE_DESTROY\n            default: REALM_TERMINATE(\"Invalid type.\");\n        }\n        m_type = JavaValueType::Empty;\n    }\n\n    // Returns a string representation of the value contained in this object.\n    std::string to_string() const {\n        std::ostringstream ss;\n        switch(m_type) {\n            case JavaValueType::Empty:\n                return \"null\";\n            case JavaValueType::Integer:\n                ss << static_cast<int64_t>(get_int());\n                return std::string(ss.str());\n            case JavaValueType::String:\n                return get_string();\n            case JavaValueType::Boolean:\n                return (get_boolean() == JNI_TRUE) ? \"true\" : \"false\";\n            case JavaValueType::Float:\n                ss << static_cast<float>(get_float());\n                return std::string(ss.str());\n            case JavaValueType::Double:\n                ss << static_cast<double>(get_double());\n                return std::string(ss.str());\n            case JavaValueType::Date:\n                ss << get_date();\n                return std::string(ss.str());\n            case JavaValueType::ObjectId:\n                return get_object_id().to_string();\n            case JavaValueType::UUID:\n                return get_uuid().to_string();\n            case JavaValueType::Decimal:\n                return get_decimal128().to_string();\n            case JavaValueType::Binary:\n                ss << \"Blob[\";\n                ss << get_binary().size();\n                ss << \"]\";\n                return std::string(ss.str());\n            case JavaValueType::Object:\n                ss << \"Object[Type: \";\n                ss << get_object()->get_table()->get_name();\n                ss << \", colKey: \";\n                ss << get_object()->get_key().value;\n                ss << \"]\";\n                return std::string(ss.str());\n            case JavaValueType::ObjectLink:\n                ss << \"ObjectLink[tableKey: \";\n                ss << get_object_link().get_table_key().value;\n                ss << \", colKey: \";\n                ss << get_object_link().get_obj_key().value;\n                ss << \"]\";\n                return std::string(ss.str());\n            case JavaValueType::List:\n                ss << \"List[size: \";\n                ss << get_list().size();\n                ss << \"]\";\n            case JavaValueType::PropertyList:\n                ss << \"PropertyList \";\n                return std::string(ss.str());\n            default: REALM_TERMINATE(\"Invalid type.\");\n        }\n    }\n\n    realm::Mixed to_mixed() const {\n        switch (this->get_type()) {\n            case JavaValueType::Integer:\n                return Mixed(this->get_int());\n            case JavaValueType::String:\n                return Mixed(StringData(this->get_string()));\n            case JavaValueType::Boolean:\n                return Mixed(B(this->get_boolean()));\n            case JavaValueType::Float:\n                return Mixed(this->get_float());\n            case JavaValueType::Double:\n                return Mixed(this->get_double());\n            case JavaValueType::Date:\n                return Mixed(this->get_date());\n            case JavaValueType::ObjectId:\n                return Mixed(this->get_object_id());\n            case JavaValueType::UUID:\n                return Mixed(this->get_uuid());\n            case JavaValueType::Decimal:\n                return Mixed(this->get_decimal128());\n            case JavaValueType::Binary:\n                return Mixed(this->get_binary().get());\n            case JavaValueType::ObjectLink:\n                return Mixed(this->get_object_link());\n            case JavaValueType::Mixed:\n                return reinterpret_cast<JavaValue*>(this->get_mixed())->to_mixed();\n            case JavaValueType::Object:\n                return Mixed(this->get_object()->get_key());\n            case JavaValueType::List:\n            case JavaValueType::PropertyList:\n            case JavaValueType::Dictionary:\n            case JavaValueType::NumValueTypes:\n            case JavaValueType::Empty:\n                return Mixed();\n            default:\n                throw std::runtime_error(util::format(\"Cannot convert type %d to Mixed\", int(this->get_type())));\n        }\n    }\n};\n\n\nstruct RequiredFieldValueNotProvidedException : public std::logic_error {\n    const std::string object_type;\n    RequiredFieldValueNotProvidedException(const std::string& object_type)\n            : std::logic_error(\"This field is required. A non-null '\" + object_type + \"' type value is expected.\")\n    {\n    }\n};\n\n// This is the Java implementation of the `CppContext` class found in `object_accessor_impl.hpp`\n// It is an object accessor context which can be used to create and access objects.\n// It will map between JNI types and Cores data types.\nclass JavaContext {\npublic:\n    JavaContext(JNIEnv* env, std::shared_ptr<Realm> realm, const ObjectSchema& os)\n    : m_env(env),\n      realm(std::move(realm)),\n      object_schema(&os) { }\n\n    // This constructor is the only one used by the object accessor code, and is\n    // used when recurring into a link or array property during object creation\n    // (i.e. prop.type will always be Object or Array).\n    JavaContext(JavaContext& c, Obj parent, Property const& prop)\n            : m_env(c.m_env)\n            , realm(c.realm)\n            , m_parent(std::move(parent))\n            , m_property(&prop)\n            , object_schema(prop.type == PropertyType::Object ? &*realm->schema().find(prop.object_type) : c.object_schema)\n    { }\n\n    // The use of util::Optional for the following two functions is not a hard\n    // requirement; only that it be some type which can be evaluated in a\n    // boolean context to determine if it contains a value, and if it does\n    // contain a value it must be dereferencable to obtain that value.\n\n    // Get the value for a property in an input object, or `util::none` if no\n    // value present. The property is identified both by the name of the\n    // property and its index within the ObjectScehma's persisted_properties\n    // array.\n    util::Optional<JavaValue> value_for_property(JavaValue& dict,\n                                                 Property const& prop,\n                                                 size_t /*property_index*/) const\n    {\n        const std::map<ColKey, JavaValue>& map = dict.get_property_list();\n        auto it = map.find(prop.column_key);\n        return it == map.end() ? util::none : util::make_optional(it->second);\n    }\n\n    // Get the default value for the given property in the given object schema,\n    // or `util::none` if there is none (which is distinct from the default\n    // being `null`).\n    //\n    // This implementation does not support default values; see the default\n    // value tests for an example of one which does.\n    util::Optional<JavaValue>\n    default_value_for_property(ObjectSchema const&, Property const&) const\n    {\n        return util::none;\n    }\n\n    // Convert from core types to the boxed type. These are currently not used as Proxy objects read\n    // directly from the Row objects. This implementation is thus only here as a reminder of which\n    // method signatures to add if needed.\n    // JavaValueType box(BinaryData v) const { return reinterpret_cast<jobject>(JavaClassGlobalDef::new_byte_array(m_env, v)); }\n    // JavaValueType box(List /*v*/) const { REALM_TERMINATE(\"'List' not implemented\"); }\n    // JavaValueType box(Object /*v*/) const { REALM_TERMINATE(\"'Object' not implemented\"); }\n    // JavaValueType box(Results /*v*/) const { REALM_TERMINATE(\"'Results' not implemented\"); }\n    // JavaValueType box(StringData v) const { return reinterpret_cast<jobject>(to_jstring(m_env, v)); }\n    // JavaValueType box(Timestamp v) const { return JavaClassGlobalDef::new_date(m_env, v); }\n    // JavaValueType box(bool v) const { return _impl::JavaClassGlobalDef::new_boolean(m_env, v); }\n    // JavaValueType box(double v) const { return _impl::JavaClassGlobalDef::new_double(m_env, v); }\n    // JavaValueType box(float v) const { return _impl::JavaClassGlobalDef::new_float(m_env, v); }\n    // JavaValueType box(int64_t v) const { return _impl::JavaClassGlobalDef::new_long(m_env, v); }\n    // JavaValueType box(util::Optional<bool> v) const { return v ? _impl::JavaClassGlobalDef::new_boolean(m_env, v.value()) : nullptr; }\n    // JavaValueType box(util::Optional<double> v) const { return v ? _impl::JavaClassGlobalDef::new_double(m_env, v.value()) : nullptr; }\n    // JavaValueType box(util::Optional<float> v) const { return v ? _impl::JavaClassGlobalDef::new_float(m_env, v.value()) : nullptr; }\n    // JavaValueType box(util::Optional<int64_t> v) const { return v ? _impl::JavaClassGlobalDef::new_long(m_env, v.value()) : nullptr; }\n    // JavaValueType box(RowExpr) const { REALM_TERMINATE(\"'RowExpr' not implemented\"); }\n\n    // Mixed type is only supported by the Cocoa binding to enable reading\n    // old Realm files that may have used them. All other bindings can ignore it.\n//    JavaValueType box(Mixed) const { REALM_TERMINATE(\"'Mixed' not supported\"); }\n\n    // Convert from the boxed type to core types. This needs to be implemented\n    // for all of the types which `box()` can take, plus `RowExpr` and optional\n    // versions of the numeric types, minus `List` and `Results`.\n    //\n    // `create` and `update` are only applicable to `unbox<RowExpr>`. If\n    // `create` is false then when given something which is not a managed Realm\n    // object `unbox()` should simply return a detached row expr, while if it's\n    // true then `unbox()` should create a new object in the context's Realm\n    // using the provided value. If `update` is true then upsert semantics\n    // should be used for this.\n    template<typename T>\n    T unbox(JavaValue const& /*v*/, CreatePolicy = CreatePolicy::Skip, ObjKey /*current_row*/ = ObjKey()) const\n    {\n        throw std::logic_error(\"Missing template specialization\"); // All types should have specialized templates\n    }\n\n    Obj unbox_embedded(JavaValue const& v, CreatePolicy policy, Obj& parent, ColKey col, size_t ndx) const;\n\n    bool is_null(JavaValue const& v) const noexcept { return !v.has_value(); }\n    JavaValue null_value() const noexcept { return {}; }\n    util::Optional<JavaValue> no_value() const noexcept { return {}; }\n\n    // Hooks which will be called before and after modifying a property from\n    // within Object::create(). These are not currently used.\n    void will_change(Object const&, Property const&) {}\n    void did_change() {}\n\n    // Get a string representation of the given value for use in error messages.\n    // This method is currently only used when printing warnings about primary keys\n    // which means the output only need to be valid for the primary key types:\n    // StringData, int64_t and Optional<int64_t>\n    std::string print(JavaValue const& val) const {\n        return val.to_string();\n    }\n\n    // Cocoa allows supplying fewer values than there are properties when\n    // creating objects using an array of values. Other bindings should not\n    // mimick this behavior so just return false here.\n    bool allow_missing(JavaValue const&) const { return false; }\n\n    Obj create_embedded_object();\n\n    // Determine if `value` boxes the same List as `list`\n    bool is_same_list(List const& /*list*/, JavaValue const& /*value*/)\n    {\n        // Lists from Java are currently never the same as the ones found in Object Store.\n        return false;\n    }\n\n    bool is_same_dictionary(const object_store::Dictionary&, JavaValue const& /*value*/){\n        //TODO: Implement with sets\n        return false;\n    }\n\n    bool is_same_set(object_store::Set const&, JavaValue const& /*value*/){\n        //TODO: Implement with sets\n        return false;\n    }\n\n    template<typename Func>\n    void enumerate_collection(JavaValue& value, Func&& fn) {\n        if (value.get_type() == JavaValueType::List) {\n            for (const auto& v : value.get_list()) {\n                fn(v);\n            }\n        } else {\n            throw std::logic_error(\"Type is not a list\");\n        }\n    }\n\n    template<typename Func>\n    void enumerate_dictionary(JavaValue& value, Func&& fn) {\n        if (value.get_type() == JavaValueType::Dictionary) {\n            for (const auto& v : value.get_dictionary()) {\n                fn(v.first, v.second);\n            }\n        } else {\n            throw std::logic_error(\"Type is not a dictionary\");\n        }\n    }\n\n    private:\n    JNIEnv* m_env;\n    std::shared_ptr<Realm> realm;\n    Obj m_parent;\n    const Property* m_property = nullptr;\n    const ObjectSchema* object_schema = nullptr;\n\n    inline void check_value_not_null(JavaValue const& v, const char* expected_type) const\n    {\n        if (!v.has_value()) {\n            throw RequiredFieldValueNotProvidedException(std::string(expected_type));\n        }\n    }\n};\n\ntemplate <>\ninline bool JavaContext::unbox(JavaValue const& v, CreatePolicy, ObjKey) const\n{\n    check_value_not_null(v, \"Boolean\");\n    return v.get_boolean() == JNI_TRUE;\n}\n\ntemplate <>\ninline int64_t JavaContext::unbox(JavaValue const& v, CreatePolicy, ObjKey) const\n{\n    check_value_not_null(v, \"Long\");\n    return static_cast<int64_t>(v.get_int());\n}\n\ntemplate <>\ninline double JavaContext::unbox(JavaValue const& v, CreatePolicy, ObjKey) const\n{\n    check_value_not_null(v, \"Double\");\n    return static_cast<double>(v.get_double());\n}\n\ntemplate <>\ninline float JavaContext::unbox(JavaValue const& v, CreatePolicy, ObjKey) const\n{\n    check_value_not_null(v, \"Float\");\n    return static_cast<float>(v.get_float());\n}\n\ntemplate <>\ninline StringData JavaContext::unbox(JavaValue const& v, CreatePolicy, ObjKey) const\n{\n    if (!v.has_value()) {\n        return StringData();\n    }\n    return StringData(v.get_string());\n}\n\ntemplate <>\ninline BinaryData JavaContext::unbox(JavaValue const& v, CreatePolicy, ObjKey) const\n{\n    if (!v.has_value()) {\n        return BinaryData();\n    } else {\n        return v.get_binary().get();\n    }\n}\n\ntemplate <>\ninline Timestamp JavaContext::unbox(JavaValue const& v, CreatePolicy, ObjKey) const\n{\n    return v.has_value() ? v.get_date() : Timestamp();\n}\n\ntemplate <>\ninline Decimal128 JavaContext::unbox(JavaValue const& v, CreatePolicy, ObjKey) const\n{\n    return v.has_value() ? v.get_decimal128() : Decimal128(realm::null());\n}\n\ntemplate <>\ninline ObjectId JavaContext::unbox(JavaValue const& v, CreatePolicy, ObjKey) const\n{\n    check_value_not_null(v, \"ObjectId\");\n    return v.get_object_id();\n}\n\ntemplate <>\ninline UUID JavaContext::unbox(JavaValue const& v, CreatePolicy, ObjKey) const\n{\n    check_value_not_null(v, \"UUID\");\n    return v.get_uuid();\n}\n\ntemplate <>\ninline Mixed JavaContext::unbox(JavaValue const& v, CreatePolicy, ObjKey) const\n{\n    return v.has_value() ? v.to_mixed() : Mixed();\n}\n\ntemplate <>\ninline Obj JavaContext::unbox(JavaValue const& v, CreatePolicy policy, ObjKey current_row) const\n{\n    if (v.get_type() == JavaValueType::Object) {\n        return *v.get_object();\n    } else if (!policy.create) {\n        return Obj();\n    }\n    REALM_ASSERT(object_schema);\n    return Object::create(const_cast<JavaContext&>(*this), realm, *object_schema, v, policy, current_row).get_obj();\n}\n\ntemplate <>\ninline util::Optional<bool> JavaContext::unbox(JavaValue const& v, CreatePolicy, ObjKey) const\n{\n    return v.has_value() ? util::make_optional(v.get_boolean() == JNI_TRUE) : util::none;\n}\n\ntemplate <>\ninline util::Optional<int64_t> JavaContext::unbox(JavaValue const& v, CreatePolicy, ObjKey) const\n{\n    return v.has_value() ? util::make_optional(static_cast<int64_t>(v.get_int())) : util::none;\n}\n\ntemplate <>\ninline util::Optional<double> JavaContext::unbox(JavaValue const& v, CreatePolicy, ObjKey) const\n{\n    return v.has_value() ? util::make_optional(v.get_double()) : util::none;\n}\n\ntemplate <>\ninline util::Optional<float> JavaContext::unbox(JavaValue const& v, CreatePolicy, ObjKey) const\n{\n    return v.has_value() ? util::make_optional(v.get_float()) : util::none;\n}\n\ntemplate <>\ninline util::Optional<ObjectId> JavaContext::unbox(JavaValue const& v, CreatePolicy, ObjKey) const\n{\n    return v.has_value() ? util::make_optional(v.get_object_id()) : util::none;\n}\n\ntemplate <>\ninline util::Optional<UUID> JavaContext::unbox(JavaValue const& v, CreatePolicy, ObjKey) const\n{\n    return v.has_value() ? util::make_optional(v.get_uuid()) : util::none;\n}\n\ntemplate <>\ninline util::Optional<Decimal> JavaContext::unbox(JavaValue const& v, CreatePolicy, ObjKey) const\n{\n    return v.has_value() ? util::make_optional(v.get_decimal128()) : util::none;\n}\n\ninline Obj JavaContext::create_embedded_object() {\n    return m_parent.create_and_set_linked_object(m_property->column_key);\n}\n\ninline JavaValue from_mixed(realm::Mixed mixed_value){\n    if (mixed_value.is_null()) {\n        return JavaValue();\n    } else {\n        switch (mixed_value.get_type()) {\n            case type_Int:\n                return JavaValue(mixed_value.get<int64_t>());\n            case type_Bool:\n                return JavaValue(static_cast<jboolean>(mixed_value.get<bool>()));\n            case type_String:\n                return JavaValue(std::string(mixed_value.get<StringData>()));\n            case type_Binary:\n                return JavaValue(OwnedBinaryData(mixed_value.get<BinaryData>()));\n            case type_Timestamp:\n                return JavaValue(mixed_value.get<Timestamp>());\n            case type_Float:\n                return JavaValue(mixed_value.get<float>());\n            case type_Double:\n                return JavaValue(mixed_value.get<double>());\n            case type_Decimal:\n                return JavaValue(mixed_value.get<Decimal128>());\n            case type_ObjectId:\n                return JavaValue(mixed_value.get<ObjectId>());\n            case type_UUID:\n                return JavaValue(mixed_value.get<UUID>());\n            case type_TypedLink:\n                return JavaValue(mixed_value.get<ObjLink>());\n            case type_Mixed:\n            case type_Link:\n            case type_LinkList:\n                return JavaValue();\n        }\n    }\n}\n\ninline std::vector<Mixed> to_mixed_vector(const std::vector<JavaValue>& java_value_vector) {\n    std::vector<Mixed> mixed_vector = std::vector<Mixed>();\n\n    for (auto &java_value: java_value_vector) {\n        mixed_vector.push_back(java_value.to_mixed());\n    }\n\n    return mixed_vector;\n}\n\n}\n\n#endif // REALM_JAVA_OBJECT_ACCESSOR_HPP\n"
  },
  {
    "path": "realm/realm-library/src/main/cpp/java_query_descriptor.cpp",
    "content": "/*\n * Copyright 2016 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\n#include \"java_accessor.hpp\"\n#include \"java_query_descriptor.hpp\"\n#include \"util.hpp\"\n#include \"jni_util/java_class.hpp\"\n#include \"jni_util/java_method.hpp\"\n\nusing namespace realm;\nusing namespace realm::_impl;\nusing namespace realm::jni_util;\n\nSortDescriptor JavaQueryDescriptor::sort_descriptor() const noexcept\n{\n    if (m_sort_desc_obj == nullptr) {\n        return SortDescriptor();\n    }\n\n    return SortDescriptor(get_column_keys(), get_ascendings());\n}\n\nDistinctDescriptor JavaQueryDescriptor::distinct_descriptor() const noexcept\n{\n    if (m_sort_desc_obj == nullptr) {\n        return DistinctDescriptor();\n    }\n    return DistinctDescriptor(get_column_keys());\n}\n\nstd::vector<std::vector<ExtendedColumnKey>> JavaQueryDescriptor::get_column_keys() const noexcept\n{\n    static JavaMethod get_column_keys_method(m_env, get_sort_desc_class(), \"getColumnKeys\", \"()[[J\");\n    jobjectArray column_indices =\n            static_cast<jobjectArray>(m_env->CallObjectMethod(m_sort_desc_obj, get_column_keys_method));\n    JObjectArrayAccessor<JLongArrayAccessor, jlongArray> arrays(m_env, column_indices);\n    jsize arr_len = arrays.size();\n    std::vector<std::vector<ExtendedColumnKey>> keys;\n\n    for (int i = 0; i < arr_len; ++i) {\n        auto jni_long_array = arrays[i];\n        std::vector<ExtendedColumnKey> col_keys;\n        for (int j = 0; j < jni_long_array.size(); ++j) {\n            col_keys.push_back(ColKey(jni_long_array[j]));\n        }\n        keys.push_back(std::move(col_keys));\n    }\n    return keys;\n}\n\nstd::vector<bool> JavaQueryDescriptor::get_ascendings() const noexcept\n{\n    static JavaMethod get_ascendings_method(m_env, get_sort_desc_class(), \"getAscendings\", \"()[Z\");\n\n    jbooleanArray ascendings =\n        static_cast<jbooleanArray>(m_env->CallObjectMethod(m_sort_desc_obj, get_ascendings_method));\n\n    if (!ascendings) {\n        return {};\n    }\n\n    JBooleanArrayAccessor ascending_array(m_env, ascendings);\n    std::vector<bool> ascending_list;\n    jsize arr_len = ascending_array.size();\n\n    for (int i = 0; i < arr_len; i++) {\n        ascending_list.push_back(static_cast<bool>(ascending_array[i]));\n    }\n    return ascending_list;\n}\n\nJavaClass const& JavaQueryDescriptor::get_sort_desc_class() const noexcept\n{\n    static JavaClass sort_desc_class(m_env, \"io/realm/internal/core/QueryDescriptor\");\n    return sort_desc_class;\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/cpp/java_query_descriptor.hpp",
    "content": "/*\n * Copyright 2016 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#ifndef JAVA_QUERY_DESCRIPTOR_HPP\n#define JAVA_QUERY_DESCRIPTOR_HPP\n\n#include <jni.h>\n\n#include \"java_accessor.hpp\"\n\nnamespace realm {\n\nnamespace jni_util {\nclass JavaClass;\n}\n\nnamespace _impl {\n\n// For converting a Java QueryDescriptor object to realm::SortDescriptor or realm::DistinctDescriptor.\n//\n// This class is not designed to be used across JNI calls. So it doesn't acquire a reference to the given Java object.\n// We don't hold a pointer to the native Sort/DistinctDescriptor in the Java object like normally we do, because the\n// ObjectStore always consumes the descriptor by calling the move constructor. Holding an empty descriptor at Java level\n// thus doesn't make much sense and causes problems with memory management.\nclass JavaQueryDescriptor {\npublic:\n    JavaQueryDescriptor(JNIEnv* env, jobject sort_desc_obj)\n        : m_env(env)\n        , m_sort_desc_obj(sort_desc_obj)\n    {\n    }\n\n    JavaQueryDescriptor(const JavaQueryDescriptor&) = delete;\n    JavaQueryDescriptor& operator=(const JavaQueryDescriptor&) = delete;\n    JavaQueryDescriptor(JavaQueryDescriptor&&) = delete;\n    JavaQueryDescriptor& operator=(JavaQueryDescriptor&&) = delete;\n\n    // Prevent heap allocation\n    static void *operator new     (size_t) = delete;\n    static void *operator new[]   (size_t) = delete;\n    static void  operator delete  (void*)  = delete;\n    static void  operator delete[](void*)  = delete;\n\n    realm::SortDescriptor sort_descriptor() const noexcept;\n    realm::DistinctDescriptor distinct_descriptor() const noexcept;\n\nprivate:\n    JNIEnv* m_env;\n    jobject m_sort_desc_obj;\n\n    std::vector<std::vector<ExtendedColumnKey>> get_column_keys() const noexcept;\n    std::vector<bool> get_ascendings() const noexcept;\n\n    jni_util::JavaClass const& get_sort_desc_class() const noexcept;\n};\n\n} // namespace _impl\n} // namespace realm\n#endif // JAVA_QUERY_DESCRIPTOR_HPP\n"
  },
  {
    "path": "realm/realm-library/src/main/cpp/jni_impl/android_logger.cpp",
    "content": "/*\n * Copyright 2016 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#include <cstring>\n\n#include \"android_logger.hpp\"\n\nusing namespace realm;\nusing namespace realm::jni_util;\nusing namespace realm::jni_impl;\nusing namespace realm::util;\n\nstd::shared_ptr<AndroidLogger> AndroidLogger::shared()\n{\n    // Private constructor, make_shared is not available.\n    static std::shared_ptr<AndroidLogger> android_logger(new AndroidLogger());\n    return android_logger;\n}\n\nvoid AndroidLogger::log(Log::Level level, const char* tag, jthrowable, const char* message)\n{\n    android_LogPriority android_log_priority;\n    switch (level) {\n        case Log::Level::trace:\n            android_log_priority = ANDROID_LOG_VERBOSE;\n            break;\n        case Log::Level::debug:\n            android_log_priority = ANDROID_LOG_DEBUG;\n            break;\n        case Log::Level::info:\n            android_log_priority = ANDROID_LOG_INFO;\n            break;\n        case Log::Level::warn:\n            android_log_priority = ANDROID_LOG_WARN;\n            break;\n        case Log::Level::error:\n            android_log_priority = ANDROID_LOG_ERROR;\n            break;\n        case Log::Level::fatal:\n            android_log_priority = ANDROID_LOG_FATAL;\n            break;\n        default: // Cannot get here.\n            throw std::invalid_argument(format(\"Invalid log level: %1.\", level));\n    }\n    if (message) {\n        print(android_log_priority, tag, message);\n    }\n}\n\nvoid AndroidLogger::print(android_LogPriority priority, const char* tag, const char* log_string)\n{\n    size_t log_size = strlen(log_string);\n\n    if (log_size > LOG_ENTRY_MAX_LENGTH) {\n        size_t start = 0;\n\n        while (start < log_size) {\n            size_t count = log_size - start > LOG_ENTRY_MAX_LENGTH ? LOG_ENTRY_MAX_LENGTH : log_size - start;\n            std::string tmp_str(log_string, start, count);\n            __android_log_write(priority, tag, tmp_str.c_str());\n            start += count;\n        }\n    }\n    else {\n        __android_log_write(priority, tag, log_string);\n    }\n}\n\nnamespace realm {\nnamespace jni_util {\n\nstd::shared_ptr<JniLogger> get_default_logger()\n{\n    return std::static_pointer_cast<JniLogger>(AndroidLogger::shared());\n}\n}\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/cpp/jni_impl/android_logger.hpp",
    "content": "/*\n * Copyright 2016 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#ifndef REALM_JNI_IMPL_ANDROID_LOGGER_HPP\n#define REALM_JNI_IMPL_ANDROID_LOGGER_HPP\n\n#include <android/log.h>\n#include \"jni_util/log.hpp\"\n\nnamespace realm {\nnamespace jni_impl {\n\n// Default logger implementation for Android.\nclass AndroidLogger final: public realm::jni_util::JniLogger {\npublic:\n    static std::shared_ptr<AndroidLogger> shared();\n\nprotected:\n    void log(realm::jni_util::Log::Level level, const char* tag, jthrowable throwable, const char* message) override;\n\nprivate:\n    AndroidLogger(){};\n    static void print(android_LogPriority priority, const char* tag, const char* log_string);\n    static const size_t LOG_ENTRY_MAX_LENGTH = 4000;\n};\n}\n}\n\n#endif // REALM_JNI_IMPL_ANDROID_LOGGER_HPP\n"
  },
  {
    "path": "realm/realm-library/src/main/cpp/jni_util/bson_util.cpp",
    "content": "/*\n * Copyright 2020 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#include <string>\n#include \"util.hpp\"\n#include \"bson_util.hpp\"\n\n// Must match JniBsonProtocol.VALUE from Java\nstatic const std::string VALUE(\"value\");\n\nusing namespace realm::bson;\nusing namespace realm::jni_util;\n\nBson JniBsonProtocol::string_to_bson(const std::string arg) {\n    BsonDocument document(parse(arg));\n    return document[VALUE];\n}\n\nBson JniBsonProtocol::jstring_to_bson(JNIEnv* env, const jstring arg) {\n    return string_to_bson(JStringAccessor(env, arg));\n}\n\nconst Bson& JniBsonProtocol::check(const realm::bson::Bson& bson, const realm::bson::Bson::Type type, const std::string message) {\n    if (bson.type() != type) {\n        throw realm::InvalidArgument(message);\n    }\n    return bson;\n}\n\nBson JniBsonProtocol::parse_checked(JNIEnv* env, const jstring arg, const Bson::Type type, const std::string message) {\n    return JniBsonProtocol::check(JniBsonProtocol::jstring_to_bson(env, arg), type, message);\n}\n\nstd::string JniBsonProtocol::bson_to_string(const Bson& bson) {\n    BsonDocument document{{VALUE, bson}};\n    std::stringstream buffer;\n    buffer << document;\n    return buffer.str();\n}\n\njstring JniBsonProtocol::bson_to_jstring(JNIEnv* env, const Bson& bson) {\n    std::string r = bson_to_string(bson);\n    return to_jstring(env, r);\n};\n"
  },
  {
    "path": "realm/realm-library/src/main/cpp/jni_util/bson_util.hpp",
    "content": "/*\n * Copyright 2020 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#ifndef REALM_BSON_UTIL_HPP\n#define REALM_BSON_UTIL_HPP\n\n#include <jni.h>\n#include <realm/util/bson/bson.hpp>\n\nnamespace realm {\nnamespace jni_util {\n\nusing namespace realm::bson;\n\n// Serializes and wraps bson values passed between java and JNI according to JniBsonProtocol.java\nclass JniBsonProtocol {\npublic:\n    static Bson string_to_bson(const std::string arg);\n    static Bson jstring_to_bson(JNIEnv* env, const jstring arg);\n    static const Bson& check(const Bson& bson, const Bson::Type type, const std::string message);\n    static Bson parse_checked(JNIEnv* env, const jstring arg, const Bson::Type type, const std::string message);\n    static std::string bson_to_string(const Bson& bson);\n    static jstring bson_to_jstring(JNIEnv* env, const Bson& bson);\n};\n\n} // jni_util\n} // realm\n\n#endif //REALM_BSON_UTIL_HPP\n"
  },
  {
    "path": "realm/realm-library/src/main/cpp/jni_util/hack.cpp",
    "content": "/*\n * Copyright 2017 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#include \"hack.hpp\"\n#include \"log.hpp\"\n\n#include <string.h>\n\n#include <realm/util/assert.hpp>\n\n#ifndef REALM_WRAP_MEMMOVE\n#error \"REALM_WRAP_MEMMOVE is not defined!\"\n#endif\n\n#if REALM_WRAP_MEMMOVE\nextern \"C\" {\nvoid* __wrap_memmove(void *dest, const void *src, size_t n);\nvoid* __real_memmove(void *dest, const void *src, size_t n);\n\nvoid* __wrap_memcpy(void *dest, const void *src, size_t n);\nvoid* __real_memcpy(void *dest, const void *src, size_t n);\n}\n\nusing namespace realm::jni_util;\n\ntypedef void* (*MemMoveFunc)(void *dest, const void *src, size_t n);\nstatic MemMoveFunc s_wrap_memmove_ptr = &__real_memmove;\nstatic MemMoveFunc s_wrap_memcpy_ptr = &__real_memcpy;\n\nstatic void* hacked_memmove(void* s1, const void* s2, size_t n)\n{\n    // adapted from https://github.com/dryc/libc11/blob/master/src/string/memmove.c\n    char* dest = (char*)s1;\n    const char* src = (const char*)s2;\n    if (dest <= src) {\n        while (n--) {\n            *dest++ = *src++;\n        }\n    }\n    else {\n        src += n;\n        dest += n;\n        while (n--) {\n            *--dest = *--src;\n        }\n    }\n    return static_cast<void*>(s1);\n}\n\nstatic void* hacked_memcpy(void* s1, const void* s2, size_t n)\n{\n    // adapted from https://github.com/dryc/libc11/blob/master/src/string/memcpy.c\n    char* dest = (char*)s1;\n    const char* src = (const char*)s2;\n    while (n--) {\n        *dest++ = *src++;\n    }\n    return static_cast<void*>(s1);\n}\n\nvoid* __wrap_memmove(void *dest, const void *src, size_t n)\n{\n    return (*s_wrap_memmove_ptr)(dest, src, n);\n}\n\nvoid* __wrap_memcpy(void *dest, const void *src, size_t n)\n{\n    return (*s_wrap_memcpy_ptr)(dest, src, n);\n}\n\n\n// See https://github.com/realm/realm-java/issues/3651#issuecomment-290290228\n// There is a bug in memmove for some Samsung devices which will return \"dest-n\" instead of dest.\n// The bug was originally found by QT, see https://bugreports.qt.io/browse/QTBUG-34984 .\n// To work around it, we use linker's wrap feature to use a pure C implementation of memmove if the device has the\n// problem.\nstatic void check_memmove()\n{\n    char* array = strdup(\"Foobar\");\n    size_t len = strlen(array);\n    void* ptr = __real_memmove(array + 1, array, len - 1);\n    if (ptr != array + 1 || strncmp(array, \"FFooba\", len) != 0) {\n        Log::e(\"memmove is broken on this device. Switching to the builtin implementation.\");\n        s_wrap_memmove_ptr = &hacked_memmove;\n        s_wrap_memcpy_ptr  = &hacked_memcpy;\n    }\n    free(array);\n}\n#endif\n\nnamespace realm {\nnamespace jni_util {\n\nvoid hack_init()\n{\n#if REALM_WRAP_MEMMOVE\n    check_memmove();\n#endif\n}\n\n}\n}\n\n"
  },
  {
    "path": "realm/realm-library/src/main/cpp/jni_util/hack.hpp",
    "content": "/*\n * Copyright 2017 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#ifndef REALM_JNI_UTIL_HACK_HPP\n#define REALM_JNI_UTIL_HACK_HPP\n\nnamespace realm {\nnamespace jni_util {\n\n// Workaround bugs on some devices.\nvoid hack_init();\n\n}\n}\n#endif // REALM_JNI_UTIL_HACK_HPP\n"
  },
  {
    "path": "realm/realm-library/src/main/cpp/jni_util/java_class.cpp",
    "content": "/*\n * Copyright 2017 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#include \"java_class.hpp\"\n#include \"jni_utils.hpp\"\n\n#include <realm/util/assert.hpp>\n\nusing namespace realm::jni_util;\n\nJavaClass::JavaClass()\n    : m_ref_owner()\n    , m_class(nullptr)\n{\n}\n\nJavaClass::JavaClass(JNIEnv* env, const char* class_name, bool free_on_unload)\n    : m_ref_owner(get_jclass(env, class_name))\n    , m_class(reinterpret_cast<jclass>(m_ref_owner.get()))\n{\n    if (free_on_unload) {\n        // Move the ownership of global ref to JNIUtils which will be released when JNI_OnUnload.\n        JniUtils::keep_global_ref(m_ref_owner);\n    }\n}\n\nJavaClass::JavaClass(JavaClass&& rhs)\n    : m_ref_owner(std::move(rhs.m_ref_owner))\n    , m_class(rhs.m_class)\n{\n    rhs.m_class = nullptr;\n}\n\nJavaGlobalRefByMove JavaClass::get_jclass(JNIEnv* env, const char* class_name)\n{\n    jclass cls = env->FindClass(class_name);\n    REALM_ASSERT_RELEASE_EX(cls, class_name);\n\n    JavaGlobalRefByMove cls_ref(env, cls, true);\n    return cls_ref;\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/cpp/jni_util/java_class.hpp",
    "content": "/*\n * Copyright 2017 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#ifndef REALM_JNI_UTIL_JAVA_CLASS_HPP\n#define REALM_JNI_UTIL_JAVA_CLASS_HPP\n\n#include <jni.h>\n\n#include \"java_global_ref_by_move.hpp\"\n\nnamespace realm {\nnamespace jni_util {\n\n// To find the jclass and manage the lifecycle for the jclass's global ref.\nclass JavaClass {\npublic:\n    JavaClass();\n    // when free_on_unload is true, the jclass's global ref will be released when JNI_OnUnload called. This is useful\n    // when the JavaClass instance is static. Otherwise the jclass's global ref will be released when this object is\n    // deleted.\n    JavaClass(JNIEnv* env, const char* class_name, bool free_on_unload = true);\n    ~JavaClass()\n    {\n    }\n\n    JavaClass(JavaClass&&);\n\n    inline jclass get() noexcept\n    {\n        return m_class;\n    }\n\n    inline operator jclass() const noexcept\n    {\n        return m_class;\n    }\n\n    inline operator bool() const noexcept\n    {\n        return m_class != nullptr;\n    }\n\n    // Not implemented for now.\n    JavaClass(JavaClass&) = delete;\n    JavaClass& operator=(JavaClass&&) = delete;\n\nprivate:\n    JavaGlobalRefByMove m_ref_owner;\n    jclass m_class;\n    static JavaGlobalRefByMove get_jclass(JNIEnv* env, const char* class_name);\n};\n\n} // jni_util\n} // realm\n\n#endif\n"
  },
  {
    "path": "realm/realm-library/src/main/cpp/jni_util/java_exception_thrower.cpp",
    "content": "/*\n * Copyright 2017 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#include \"java_exception_thrower.hpp\"\n#include \"log.hpp\"\n\nusing namespace realm::util;\nusing namespace realm::jni_util;\n\nJavaExceptionThrower::JavaExceptionThrower(const char* file_path, int line_num)\n    : std::runtime_error(\"Java exception has been occurred. Terminate JNI by throwing a c++ exception.\")\n    , m_exception_class()\n    , m_file_path(file_path)\n    , m_line_num(line_num)\n{\n}\n\nJavaExceptionThrower::JavaExceptionThrower(JNIEnv* env, const char* class_name, std::string message,\n                                           const char* file_path, int line_num)\n    : std::runtime_error(std::move(message))\n    , m_exception_class(env, class_name, false)\n    , m_file_path(file_path)\n    , m_line_num(line_num)\n{\n}\n\nvoid JavaExceptionThrower::throw_java_exception(JNIEnv* env)\n{\n    std::string message = format(\"%1\\n(%2:%3)\", what(), m_file_path, m_line_num);\n    Log::w(message.c_str());\n\n    // There is a pending Java exception, just return.\n    if (env->ExceptionCheck()) {\n        Log::w(\"There is a pending Java exception.\");\n        return;\n    }\n    env->ThrowNew(m_exception_class, message.c_str());\n}\n\nvoid JavaExceptionThrower::terminate_jni_if_java_exception_occurred(JNIEnv* env, CleanUpFunction clean_up_func,\n                                                                    const char* file_path, int line_num)\n{\n    if (!env->ExceptionCheck()) {\n        return;\n    }\n    if (clean_up_func) {\n        clean_up_func();\n    }\n    throw JavaExceptionThrower(file_path, line_num);\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/cpp/jni_util/java_exception_thrower.hpp",
    "content": "/*\n * Copyright 2017 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#ifndef REALM_JNI_UTIL_JAVA_EXCEPTION_THROWER_HPP\n#define REALM_JNI_UTIL_JAVA_EXCEPTION_THROWER_HPP\n\n#include <jni.h>\n\n#include <functional>\n#include <stdexcept>\n\n#include \"java_class.hpp\"\n\nnamespace realm {\nnamespace jni_util {\n\n#define THROW_JAVA_EXCEPTION(env, class_name, message)                                                               \\\n    throw realm::jni_util::JavaExceptionThrower(env, class_name, message, __FILE__, __LINE__)\n\n#define TERMINATE_JNI_IF_JAVA_EXCEPTION_OCCURRED(env, clean_up_func)                                                 \\\n    JavaExceptionThrower::terminate_jni_if_java_exception_occurred(env, clean_up_func, __FILE__, __LINE__);\n\n// Class to help throw a Java exception from JNI code.\n// This exception will be called from CATCH_STD and throw a Java exception there.\nclass JavaExceptionThrower : public std::runtime_error {\npublic:\n    using CleanUpFunction = std::function<void()>;\n\n    JavaExceptionThrower(const char* file_path, int line_num);\n    JavaExceptionThrower(JNIEnv* env, const char* class_name, std::string message, const char* file_path,\n                         int line_num);\n\n    void throw_java_exception(JNIEnv* env);\n\n    // This method will throw a JavaExceptionThrower to terminate JNI then return to java if there is an Java\n    // exception has been thrown before.\n    // clean_up_fucn will be called before throwing the c++ exception if there is a pending java exception.\n    static void terminate_jni_if_java_exception_occurred(JNIEnv* env, CleanUpFunction clean_up_func,\n                                                         const char* file_path, int line_num);\n\nprivate:\n    JavaClass m_exception_class;\n    const char* m_file_path;\n    int m_line_num;\n};\n\n} // namespace realm\n} // namesapce jni_util\n\n#endif // REALM_JNI_UTIL_JAVA_EXCEPTION_THROWER_HPP\n"
  },
  {
    "path": "realm/realm-library/src/main/cpp/jni_util/java_global_ref_by_copy.cpp",
    "content": "/*\n * Copyright 2020 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#include \"java_global_ref_by_copy.hpp\"\n#include \"jni_utils.hpp\"\n\n#include <memory>\n\nusing namespace realm::jni_util;\n\nJavaGlobalRefByCopy::JavaGlobalRefByCopy() : m_ref(nullptr) {\n\n}\n\nJavaGlobalRefByCopy::JavaGlobalRefByCopy(JNIEnv *env, jobject obj)\n        : m_ref(obj ? env->NewGlobalRef(obj) : nullptr) {\n}\n\nJavaGlobalRefByCopy::JavaGlobalRefByCopy(const JavaGlobalRefByCopy &rhs)\n        : m_ref(rhs.m_ref ? jni_util::JniUtils::get_env(true)->NewGlobalRef(rhs.m_ref) : nullptr) {\n}\n\nJavaGlobalRefByCopy::~JavaGlobalRefByCopy() {\n    if (m_ref) {\n        JniUtils::get_env()->DeleteGlobalRef(m_ref);\n    }\n}\n\njobject JavaGlobalRefByCopy::get() const noexcept {\n    return m_ref;\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/cpp/jni_util/java_global_ref_by_copy.hpp",
    "content": "/*\n * Copyright 2020 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#ifndef REALM_JNI_UTIL_JAVA_GLOBAL_REF_COPY_HPP\n#define REALM_JNI_UTIL_JAVA_GLOBAL_REF_COPY_HPP\n\n#include <jni.h>\n\nnamespace realm {\n    namespace jni_util {\n\n        // Manages the lifecycle of jobject's global ref via copy constructors\n        //\n        // It prevents leaking global references by automatically referencing and unreferencing Java objects\n        // any time the instance is copied or destroyed. Its principal use is on data structures that don't support\n        // moving operations such as in std::function lambdas.\n        //\n        // Note that there is another flavor available: JavaGlobalRefByMove.\n        //\n        // JavaGlobalRefByCopy: multiple references will exist to the Java object, one on each instance.\n        // JavaGlobalRefByMove: only one reference will only be available at last moved instance.\n\n        class JavaGlobalRefByCopy {\n        public:\n            JavaGlobalRefByCopy();\n\n            JavaGlobalRefByCopy(JNIEnv *env, jobject obj);\n\n            JavaGlobalRefByCopy(const JavaGlobalRefByCopy &rhs);\n\n            JavaGlobalRefByCopy(JavaGlobalRefByCopy&& rhs) = delete;\n\n            ~JavaGlobalRefByCopy();\n\n            jobject get() const noexcept;\n\n        private:\n            jobject m_ref;\n        };\n    }\n}\n\n#endif // REALM_JNI_UTIL_JAVA_GLOBAL_REF_COPY_HPP\n"
  },
  {
    "path": "realm/realm-library/src/main/cpp/jni_util/java_global_ref_by_move.cpp",
    "content": "/*\n * Copyright 2017 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#include \"java_global_ref_by_move.hpp\"\n#include \"jni_utils.hpp\"\n\n#include <memory>\n\nusing namespace realm::jni_util;\n\nJavaGlobalRefByMove::~JavaGlobalRefByMove()\n{\n    if (m_ref) {\n        JniUtils::get_env()->DeleteGlobalRef(m_ref);\n    }\n}\n\nJavaGlobalRefByMove& JavaGlobalRefByMove::operator=(JavaGlobalRefByMove&& rhs)\n{\n    this->~JavaGlobalRefByMove();\n    new (this) JavaGlobalRefByMove(std::move(rhs));\n    return *this;\n}\n\nJavaGlobalRefByMove::JavaGlobalRefByMove(JavaGlobalRefByMove& rhs)\n        : m_ref(rhs.m_ref ? jni_util::JniUtils::get_env(true)->NewGlobalRef(rhs.m_ref) : nullptr)\n{\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/cpp/jni_util/java_global_ref_by_move.hpp",
    "content": "/*\n * Copyright 2017 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#ifndef REALM_JNI_UTIL_JAVA_GLOBAL_REF_HPP\n#define REALM_JNI_UTIL_JAVA_GLOBAL_REF_HPP\n\n#include <jni.h>\n\nnamespace realm {\nnamespace jni_util {\n\n// Manages the lifecycle of jobject's global ref via move constructors\n//\n// It prevents leaking global references by automatically referencing and unreferencing Java objects\n// any time the instance is moved or destroyed. Its principal use is on data structures that support move\n// operations, such as std::vector.\n//\n// Note that there is another flavor available: JavaGlobalRefByCopy.\n//\n// JavaGlobalRefByCopy: multiple references will exist to the Java object, one on each instance.\n// JavaGlobalRefByMove: only one reference will only be available at last moved instance.\n\nclass JavaGlobalRefByMove {\npublic:\n    JavaGlobalRefByMove()\n        : m_ref(nullptr)\n    {\n    }\n    // Acquire a global ref on the given jobject. The local ref will be released if given release_local_ref is true.\n    JavaGlobalRefByMove(JNIEnv* env, jobject obj, bool release_local_ref = false)\n        : m_ref(obj ? env->NewGlobalRef(obj) : nullptr)\n    {\n        if (release_local_ref) {\n            env->DeleteLocalRef(obj);\n        }\n    }\n    JavaGlobalRefByMove(JavaGlobalRefByMove&& rhs)\n        : m_ref(rhs.m_ref)\n    {\n        rhs.m_ref = nullptr;\n    }\n    ~JavaGlobalRefByMove();\n\n    JavaGlobalRefByMove& operator=(JavaGlobalRefByMove&& rhs);\n    JavaGlobalRefByMove& operator=(JavaGlobalRefByMove& rhs) = delete;\n    JavaGlobalRefByMove(JavaGlobalRefByMove&);\n\n    inline operator bool() const noexcept\n    {\n        return m_ref != nullptr;\n    }\n\n    inline jobject get() const noexcept\n    {\n        return m_ref;\n    }\n\nprivate:\n    jobject m_ref;\n};\n}\n}\n\n#endif // REALM_JNI_UTIL_JAVA_GLOBAL_REF_HPP\n"
  },
  {
    "path": "realm/realm-library/src/main/cpp/jni_util/java_global_weak_ref.cpp",
    "content": "/*\n * Copyright 2017 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#include \"java_global_weak_ref.hpp\"\n#include \"java_local_ref.hpp\"\n\nusing namespace realm::jni_util;\n\nJavaGlobalWeakRef::JavaGlobalWeakRef()\n    : m_weak(nullptr)\n{\n}\n\nJavaGlobalWeakRef::JavaGlobalWeakRef(JNIEnv* env, jobject obj)\n    : m_weak(obj ? env->NewWeakGlobalRef(obj) : nullptr)\n{\n}\n\nJavaGlobalWeakRef::~JavaGlobalWeakRef()\n{\n    if (m_weak) {\n        JniUtils::get_env()->DeleteWeakGlobalRef(m_weak);\n    }\n}\n\nJavaGlobalWeakRef::JavaGlobalWeakRef(JavaGlobalWeakRef&& rhs)\n    : m_weak(rhs.m_weak)\n{\n    rhs.m_weak = nullptr;\n}\n\nJavaGlobalWeakRef& JavaGlobalWeakRef::operator=(JavaGlobalWeakRef&& rhs)\n{\n    this->~JavaGlobalWeakRef();\n    new (this) JavaGlobalWeakRef(std::move(rhs));\n    return *this;\n}\n\nJavaGlobalWeakRef::JavaGlobalWeakRef(const JavaGlobalWeakRef& rhs)\n    : m_weak(JniUtils::get_env(true)->NewWeakGlobalRef(rhs.m_weak))\n{\n}\n\nJavaGlobalWeakRef& JavaGlobalWeakRef::operator=(const JavaGlobalWeakRef& rhs)\n{\n    new (this) JavaGlobalWeakRef(rhs);\n    return *this;\n}\n\nJavaGlobalRefByMove JavaGlobalWeakRef::global_ref(JNIEnv* env) const\n{\n    if (!env) {\n        env = JniUtils::get_env(true);\n    }\n    return JavaGlobalRefByMove(env, m_weak);\n}\n\nbool JavaGlobalWeakRef::call_with_local_ref(JNIEnv* env, std::function<Callback> callback) const\n{\n    if (!m_weak) {\n        return false;\n    }\n\n    JavaLocalRef<jobject> obj(env, m_weak, need_to_create_local_ref);\n\n    if (!obj) {\n        return false;\n    }\n    callback(env, obj);\n    return true;\n}\n\nbool JavaGlobalWeakRef::call_with_local_ref(std::function<Callback> callback) const\n{\n    return call_with_local_ref(JniUtils::get_env(), callback);\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/cpp/jni_util/java_global_weak_ref.hpp",
    "content": "/*\n * Copyright 2017 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#ifndef REALM_JNI_UTIL_JAVA_GLOBAL_WEAK_REF_HPP\n#define REALM_JNI_UTIL_JAVA_GLOBAL_WEAK_REF_HPP\n\n#include <jni.h>\n#include <functional>\n\n#include \"jni_utils.hpp\"\n\nnamespace realm {\nnamespace jni_util {\n\n// RAII wrapper for weak global ref.\nclass JavaGlobalWeakRef {\npublic:\n    JavaGlobalWeakRef();\n    JavaGlobalWeakRef(JNIEnv*, jobject);\n    ~JavaGlobalWeakRef();\n\n    JavaGlobalWeakRef(JavaGlobalWeakRef&&);\n    JavaGlobalWeakRef& operator=(JavaGlobalWeakRef&&);\n\n    JavaGlobalWeakRef(const JavaGlobalWeakRef&);\n    JavaGlobalWeakRef& operator=(const JavaGlobalWeakRef&);\n\n    inline operator bool() const noexcept\n    {\n        return m_weak != nullptr;\n    }\n\n    JavaGlobalRefByMove global_ref(JNIEnv* env = nullptr) const;\n\n    using Callback = void(JNIEnv* env, jobject obj);\n\n    // Acquire a local ref and run the callback with it if the weak ref is valid. The local ref will be deleted after\n    // callback finished. Return false if the weak ref is not valid anymore.\n    bool call_with_local_ref(JNIEnv* env, std::function<Callback> callback) const ;\n    // Try to get an JNIEnv for current thread then run the callback.\n    bool call_with_local_ref(std::function<Callback> callback) const;\n\nprivate:\n    jweak m_weak;\n};\n\n} // namespace jni_util\n} // namespace realm\n\n#endif // REALM_JNI_UTIL_JAVA_GLOBAL_WEAK_REF_HPP\n"
  },
  {
    "path": "realm/realm-library/src/main/cpp/jni_util/java_local_ref.hpp",
    "content": "/*\n * Copyright 2017 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#ifndef REALM_JNI_UTIL_JAVA_LOCAL_REF_HPP\n#define REALM_JNI_UTIL_JAVA_LOCAL_REF_HPP\n\n#include <jni.h>\n\nnamespace realm {\nnamespace jni_util {\n\nstruct NeedToCreateLocalRef {\n};\nstatic constexpr NeedToCreateLocalRef need_to_create_local_ref{};\n\n// Wraps jobject and automatically calls DeleteLocalRef when this object is destroyed.\n// DeleteLocalRef is not necessary to be called in most cases since all local references will be cleaned up when the\n// program returns to Java from native. But if the local ref is created in a loop, consider to use this class to wrap\n// it because the size of local reference table is relative small (512 bytes on Android).\ntemplate <typename T>\nclass JavaLocalRef {\npublic:\n    inline JavaLocalRef() noexcept\n        : m_jobject(nullptr)\n        , m_env(nullptr){};\n    inline JavaLocalRef(JNIEnv* env, T obj) noexcept\n        : m_jobject(obj)\n        , m_env(env){};\n    // need_to_create is useful when acquire a local ref from a global weak ref.\n    inline JavaLocalRef(JNIEnv* env, T obj, NeedToCreateLocalRef) noexcept\n        : m_jobject(env->NewLocalRef(obj))\n        , m_env(env){};\n\n    inline ~JavaLocalRef()\n    {\n        if (m_jobject) {\n            m_env->DeleteLocalRef(m_jobject);\n        }\n    }\n\n    JavaLocalRef& operator=(JavaLocalRef&& rhs)\n    {\n        this->~JavaLocalRef();\n        new (this) JavaLocalRef(std::move(rhs));\n        return *this;\n    }\n\n    inline JavaLocalRef(JavaLocalRef&& rhs)\n        : m_jobject(rhs.m_jobject)\n        , m_env(rhs.m_env)\n    {\n        rhs.m_jobject = nullptr;\n        rhs.m_env = nullptr;\n    }\n\n    inline operator bool() const noexcept\n    {\n        return m_jobject != nullptr;\n    };\n    inline operator T() const noexcept\n    {\n        return m_jobject;\n    }\n    inline T get() const noexcept\n    {\n        return m_jobject;\n    };\n\n    JavaLocalRef(const JavaLocalRef&) = delete;\n    JavaLocalRef& operator=(const JavaLocalRef&) = delete;\n\nprivate:\n    T m_jobject;\n    JNIEnv* m_env;\n};\n\n} // namespace realm\n} // namespace jni_util\n#endif // REALM_JNI_UTIL_JAVA_LOCAL_REF_HPP\n"
  },
  {
    "path": "realm/realm-library/src/main/cpp/jni_util/java_method.cpp",
    "content": "/*\n * Copyright 2017 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#include \"java_method.hpp\"\n#include \"java_class.hpp\"\n\n#include <realm/util/assert.hpp>\n\nusing namespace realm::jni_util;\n\nJavaMethod::JavaMethod(JNIEnv* env, JavaClass const& cls, const char* method_name, const char* signature, bool static_method)\n{\n    if (static_method) {\n        m_method_id = env->GetStaticMethodID(cls, method_name, signature);\n    }\n    else {\n        m_method_id = env->GetMethodID(cls, method_name, signature);\n    }\n\n    REALM_ASSERT_RELEASE_EX(m_method_id != nullptr, method_name, signature);\n}\n\nJavaMethod::JavaMethod(JNIEnv* env, jobject const& obj, const char* method_name, const char* signature)\n{\n    jclass cls = env->GetObjectClass(obj);\n    m_method_id = env->GetMethodID(cls, method_name, signature);\n    REALM_ASSERT_RELEASE_EX(m_method_id != nullptr, method_name, signature);\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/cpp/jni_util/java_method.hpp",
    "content": "/*\n * Copyright 2017 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#ifndef REALM_JNI_UTIL_JAVA_METHOD_HPP\n#define REALM_JNI_UTIL_JAVA_METHOD_HPP\n\n#include <jni.h>\n\nnamespace realm {\nnamespace jni_util {\n\nclass JavaClass;\n// RAII wrapper for java method ID. Since normally method ID stays unchanged for the whole JVM life cycle, it would be\n// safe to have a static JavaMethod object to avoid calling GetMethodID multiple times.\nclass JavaMethod {\npublic:\n    JavaMethod()\n        : m_method_id(nullptr)\n    {\n    }\n    // Lookup a method on a named class\n    JavaMethod(JNIEnv* env, JavaClass const& cls, const char* method_name, const char* signature,\n               bool static_method = false);\n\n    // Lookup a method on a object from Java\n    JavaMethod(JNIEnv* env, jobject const& cls, const char* method_name, const char* signature);\n\n    // From https://developer.android.com/training/articles/perf-jni.html\n    // The class references, field IDs, and method IDs are guaranteed valid until the class is unloaded. Classes are\n    // only unloaded if all classes associated with a ClassLoader can be garbage collected, which is rare but will not\n    // be impossible in Android. Note however that the jclass is a class reference and must be protected with a call\n    // to NewGlobalRef (see the next section).\n    //\n    // BUT THERE ARE BUGS. See below:\n    //\n    // WARNING!! For anyone wants to implement this method, please DON'T. There might be a bug in JVM implementation\n    // that the jmethodID retrieved from jobject's jclass would be invalid under some certain conditions.\n    // See https://github.com/realm/realm-java/issues/4964 for how to reproduce it.\n    // JavaMethod(JNIEnv* env, jobject obj, const char* method_name, const char* signature);\n\n    // For this constructor, there is no evidence that jmethodID will be invalidated when there is no ref to the jclass.\n    // Just in case, though we force the caller to keep a global ref by JavaClass to make sure we won't encounter another\n    // JVM bug.\n    // JavaMethod(JNIEnv* env, const char* class_name, const char* method_name, const char* signature,\n    //           bool static_method = false);\n\n    JavaMethod(const JavaMethod&) = default;\n    JavaMethod& operator=(const JavaMethod&) = default;\n    JavaMethod(JavaMethod&& rhs) = delete;\n    JavaMethod& operator=(JavaMethod&& rhs) = delete;\n\n    ~JavaMethod()\n    {\n    }\n\n    inline operator bool() const noexcept\n    {\n        return m_method_id != nullptr;\n    }\n    inline operator const jmethodID&() const noexcept\n    {\n        return m_method_id;\n    }\n\nprivate:\n    jmethodID m_method_id;\n};\n\n} // namespace realm\n} // namespace jni_util\n\n#endif // REALM_JNI_UTIL_JAVA_METHOD_HPP\n"
  },
  {
    "path": "realm/realm-library/src/main/cpp/jni_util/jni_utils.cpp",
    "content": "/*\n * Copyright 2017 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#include \"jni_utils.hpp\"\n#include \"java_class.hpp\"\n#include \"java_method.hpp\"\n\n#include <realm/util/assert.hpp>\n\n#include <memory>\n\nusing namespace realm::jni_util;\nusing namespace std;\n\nstatic std::unique_ptr<JniUtils> s_instance;\n\nvoid JniUtils::initialize(JavaVM* vm, jint vm_version) noexcept\n{\n    REALM_ASSERT_DEBUG(!s_instance);\n\n    s_instance = std::unique_ptr<JniUtils>(new JniUtils(vm, vm_version));\n}\n\nvoid JniUtils::release()\n{\n    REALM_ASSERT_DEBUG(s_instance);\n    s_instance.release();\n}\n\nJNIEnv* JniUtils::get_env(bool attach_if_needed)\n{\n    REALM_ASSERT_DEBUG(s_instance);\n\n    JNIEnv* env;\n    if (s_instance->m_vm->GetEnv(reinterpret_cast<void**>(&env), s_instance->m_vm_version) != JNI_OK) {\n        if (attach_if_needed) {\n            jint ret = s_instance->m_vm->AttachCurrentThread(&env, nullptr);\n            REALM_ASSERT_RELEASE(ret == JNI_OK);\n        }\n        else {\n            REALM_ASSERT_RELEASE(false);\n        }\n    }\n\n    return env;\n}\n\nvoid JniUtils::detach_current_thread()\n{\n    s_instance->m_vm->DetachCurrentThread();\n}\n\nvoid JniUtils::keep_global_ref(JavaGlobalRefByMove& ref)\n{\n    s_instance->m_global_refs.push_back(std::move(ref));\n}\n\njobject JniUtils::to_hash_map(JNIEnv* env, std::map<std::string, std::string> map)\n{\n    static JavaClass hash_map_class(env, \"java/util/HashMap\");\n    static JavaMethod hash_map_constructor(env, hash_map_class, \"<init>\", \"(I)V\");\n    static JavaMethod hash_map_put(env, hash_map_class, \"put\", \"(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;\");\n\n    jobject hash_map = env->NewObject(hash_map_class, hash_map_constructor, (jint) map.size());\n\n    for (const auto& it : map)\n    {\n        jstring key = env->NewStringUTF(it.first.c_str());\n        jstring value = env->NewStringUTF(it.second.c_str());\n\n        env->CallObjectMethod(hash_map, hash_map_put,\n                              key,\n                              value);\n\n        env->DeleteLocalRef(key);\n        env->DeleteLocalRef(value);\n    }\n\n    return hash_map;\n}\n\n"
  },
  {
    "path": "realm/realm-library/src/main/cpp/jni_util/jni_utils.hpp",
    "content": "/*\n * Copyright 2017 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#ifndef REALM_JNI_UTIL_JNI_UTILS_HPP\n#define REALM_JNI_UTIL_JNI_UTILS_HPP\n\n#include <jni.h>\n\n#include <vector>\n#include <map>\n\n#include \"java_global_ref_by_move.hpp\"\n#include \"java_global_ref_by_copy.hpp\"\n\nnamespace realm {\nnamespace jni_util {\n\n// Util functions for JNI.\nclass JniUtils {\npublic:\n    ~JniUtils()\n    {\n    }\n\n    // Call this only once in JNI_OnLoad.\n    static void initialize(JavaVM* vm, jint vm_version) noexcept;\n    // Call this in JNI_OnUnload.\n    static void release();\n    // When attach_if_needed is false, returns the JNIEnv if there is one attached to this thread. Assert if there is\n    // none. When attach_if_needed is true, try to attach and return a JNIEnv if necessary.\n    static JNIEnv* get_env(bool attach_if_needed = false);\n    // Detach the current thread from the JVM. Only required for C++ threads that where attached in the first place.\n    // Failing to do so is a resource leak.\n    static void detach_current_thread();\n    // Keep the given global reference until JNI_OnUnload is called.\n    static void keep_global_ref(JavaGlobalRefByMove& ref);\n    // Transforms a string map into a Java String HashMap\n    static jobject to_hash_map(JNIEnv* env, std::map<std::string, std::string> map);\n\nprivate:\n    JniUtils(JavaVM* vm, jint vm_version) noexcept\n        : m_vm(vm)\n        , m_vm_version(vm_version)\n    {\n    }\n\n    JavaVM* m_vm;\n    jint m_vm_version;\n    std::vector<JavaGlobalRefByMove> m_global_refs;\n};\n\n} // namespace realm\n} // namespace jni_util\n\n#endif // REALM_JNI_UTIL_JNI_UTILS_HPP\n"
  },
  {
    "path": "realm/realm-library/src/main/cpp/jni_util/log.cpp",
    "content": "/*\n * Copyright 2016 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#include <algorithm>\n\n#include <realm/util/assert.hpp>\n\n#include \"jni_util/log.hpp\"\n#include \"jni_util/java_local_ref.hpp\"\n\nusing namespace realm;\nusing namespace realm::jni_util;\nusing namespace realm::util;\n\nconst char* Log::REALM_JNI_TAG = \"REALM_JNI\";\nLog::Level Log::s_level = Log::Level::warn;\nstd::vector<CoreLoggerBridge*> CoreLoggerBridge::s_bridges;\nstd::mutex CoreLoggerBridge::s_mutex;\n\n// Native wrapper for Java RealmLogger class\nclass JavaLogger : public JniLogger {\npublic:\n    JavaLogger(JNIEnv* env, jobject java_logger);\n    ~JavaLogger();\n\n    bool is_same_object(JNIEnv* env, jobject java_logger);\n\nprotected:\n    void log(Log::Level level, const char* tag, jthrowable throwable, const char* message) override;\n\nprivate:\n    JavaVM* m_jvm;\n    // Global ref of the logger object.\n    jobject m_java_logger;\n    jmethodID m_log_method;\n\n    inline JNIEnv* get_current_env() noexcept\n    {\n        JNIEnv* env;\n        if (m_jvm->GetEnv((void**)&env, JNI_VERSION_1_6) != JNI_OK) {\n            m_jvm->AttachCurrentThread(&env, nullptr); // Should never fail\n        }\n        return env;\n    }\n};\n\nJniLogger::JniLogger()\n    : m_is_java_logger(false)\n{\n}\n\nJniLogger::~JniLogger()\n{\n}\n\nJniLogger::JniLogger(bool is_java_logger)\n    : m_is_java_logger(is_java_logger)\n{\n}\n\nJavaLogger::JavaLogger(JNIEnv* env, jobject java_logger)\n    : JniLogger(true)\n{\n    jint ret = env->GetJavaVM(&m_jvm);\n    if (ret != 0) {\n        throw std::runtime_error(util::format(\"Failed to get Java vm. Error: %d\", ret));\n    }\n    m_java_logger = env->NewGlobalRef(java_logger);\n    jclass cls = env->GetObjectClass(m_java_logger);\n    m_log_method = env->GetMethodID(cls, \"log\", \"(ILjava/lang/String;Ljava/lang/Throwable;Ljava/lang/String;)V\");\n}\n\nJavaLogger::~JavaLogger()\n{\n    get_current_env()->DeleteGlobalRef(m_java_logger);\n}\n\nvoid JavaLogger::log(Log::Level level, const char* tag, jthrowable throwable, const char* message)\n{\n    JNIEnv* env = get_current_env();\n\n    // NOTE: If a Java exception has been thrown in native code, the below call will trigger an JNI exception\n    // \"JNI called with pending exception\". This is something that should be avoided when printing log in JNI --\n    // Always\n    // print log before calling env->ThrowNew. Doing env->ExceptionCheck() here creates overhead for normal cases.\n    JavaLocalRef<jstring> java_tag(env, env->NewStringUTF(tag));\n    JavaLocalRef<jstring> java_error_message(env, env->NewStringUTF(message));\n    env->CallVoidMethod(m_java_logger, m_log_method, level, java_tag.get(), throwable, java_error_message.get());\n}\n\nbool JavaLogger::is_same_object(JNIEnv* env, jobject java_logger)\n{\n    return env->IsSameObject(m_java_logger, java_logger);\n}\n\nLog::Log()\n    : m_loggers()\n{\n    add_logger(get_default_logger());\n}\n\nLog& Log::shared()\n{\n    static Log log;\n    return log;\n}\n\nvoid Log::add_java_logger(JNIEnv* env, const jobject java_logger)\n{\n    std::shared_ptr<JniLogger> logger = std::make_shared<JavaLogger>(env, java_logger);\n    add_logger(logger);\n}\n\nvoid Log::remove_java_logger(JNIEnv* env, const jobject java_logger)\n{\n    std::lock_guard<std::mutex> lock(m_mutex);\n    m_loggers.erase(std::remove_if(m_loggers.begin(), m_loggers.end(),\n                                   [&](const auto& obj) {\n                                       return obj->m_is_java_logger &&\n                                              std::static_pointer_cast<JavaLogger>(obj)->is_same_object(env,\n                                                                                                        java_logger);\n                                   }),\n                    m_loggers.end());\n}\n\nvoid Log::add_logger(std::shared_ptr<JniLogger> logger)\n{\n    std::lock_guard<std::mutex> lock(m_mutex);\n    if (std::find(m_loggers.begin(), m_loggers.end(), logger) == m_loggers.end()) {\n        m_loggers.push_back(logger);\n    }\n}\n\nvoid Log::remove_logger(std::shared_ptr<JniLogger> logger)\n{\n    std::lock_guard<std::mutex> lock(m_mutex);\n\n    m_loggers.erase(\n        std::remove_if(m_loggers.begin(), m_loggers.end(), [&](const auto& obj) { return obj == logger; }),\n        m_loggers.end());\n}\n\nvoid Log::register_default_logger()\n{\n    add_logger(get_default_logger());\n}\n\nvoid Log::clear_loggers()\n{\n    std::lock_guard<std::mutex> lock(m_mutex);\n    m_loggers.clear();\n}\n\nvoid Log::set_level(Level level)\n{\n    s_level = level;\n    CoreLoggerBridge::set_levels(level);\n}\n\nvoid Log::log(Level level, const char* tag, jthrowable throwable, const char* message)\n{\n    if (s_level <= level) {\n        std::lock_guard<std::mutex> lock(m_mutex);\n        for (auto& logger : m_loggers) {\n            logger->log(level, tag, throwable, message);\n        }\n    }\n}\n\nrealm::util::Logger::Level Log::convert_to_core_log_level(Level level)\n{\n        switch (level) {\n            case Log::trace:\n                return Logger::Level::trace;\n            case Log::debug:\n                return Logger::Level::debug;\n            case Log::info:\n                return Logger::Level::info;\n            case Log::warn:\n                return Logger::Level::warn;\n            case Log::error:\n                return Logger::Level::error;\n            case Log::fatal:\n                return Logger::Level::fatal;\n            case Log::all:\n                return Logger::Level::all;\n            case Log::off:\n                return Logger::Level::off;\n            default:\n                break;\n        }\n        REALM_UNREACHABLE();\n}\n\nCoreLoggerBridge::CoreLoggerBridge(std::string tag)\n    : m_tag(std::move(tag))\n{\n    std::lock_guard<std::mutex> lock(s_mutex);\n    s_bridges.push_back(this);\n    set_level_threshold(Log::convert_to_core_log_level(Log::shared().get_level()));\n}\n\nCoreLoggerBridge::~CoreLoggerBridge()\n{\n    std::lock_guard<std::mutex> lock(s_mutex);\n    s_bridges.erase(std::remove(s_bridges.begin(), s_bridges.end(), this), s_bridges.end());\n}\n\nvoid CoreLoggerBridge::set_levels(Log::Level level)\n{\n    std::lock_guard<std::mutex> lock(s_mutex);\n    for (auto bridge : s_bridges) {\n        bridge->set_level_threshold(Log::convert_to_core_log_level(level));\n    }\n}\n\nvoid CoreLoggerBridge::do_log(realm::util::Logger::Level level, const std::string& msg)\n{\n    // Ignore the level threshold from the root logger.\n    Log::Level jni_level = Log::all; // Initial value to suppress the false positive compile warning.\n    switch (level) {\n        case Level::trace:\n            jni_level = Log::trace;\n            break;\n        case Level::debug: // Fall through. Map to same level debug.\n        case Level::detail:\n            jni_level = Log::debug;\n            break;\n        case Level::info:\n            jni_level = Log::info;\n            break;\n        case Level::warn:\n            jni_level = Log::warn;\n            break;\n        case Level::error:\n            jni_level = Log::error;\n            break;\n        case Level::fatal:\n            jni_level = Log::fatal;\n            break;\n        case Level::all: // Fall through.\n        case Level::off: // Fall through.\n            throw std::invalid_argument(format(\"Invalid log level.\"));\n    }\n    Log::shared().log(jni_level, m_tag.c_str(), msg.c_str());\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/cpp/jni_util/log.hpp",
    "content": "/*\n * Copyright 2016 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#ifndef REALM_JNI_UTIL_LOG_HPP\n#define REALM_JNI_UTIL_LOG_HPP\n\n#include <jni.h>\n\n#include <memory>\n#include <mutex>\n#include <string>\n#include <vector>\n\n#include \"io_realm_log_LogLevel.h\"\n\n#include <realm/util/logger.hpp>\n\nnamespace realm {\n\nnamespace jni_util {\n\nclass JniLogger;\n\n// This is built for Realm logging, bother for Java and native side.\n// Multiple loggers can be registered. All registered loggers will receive the same log events.\nclass Log {\npublic:\n    enum Level {\n        all = io_realm_log_LogLevel_ALL,\n        trace = io_realm_log_LogLevel_TRACE,\n        debug = io_realm_log_LogLevel_DEBUG,\n        info = io_realm_log_LogLevel_INFO,\n        warn = io_realm_log_LogLevel_WARN,\n        error = io_realm_log_LogLevel_ERROR,\n        fatal = io_realm_log_LogLevel_FATAL,\n        off = io_realm_log_LogLevel_OFF\n    };\n\n    // Add & Remove a Java RealmLogger. A Java logger needs to be implemented from io.realm.log.RealmLogger interface.\n    void add_java_logger(JNIEnv* env, const jobject java_logger);\n    void remove_java_logger(JNIEnv* env, const jobject java_logger);\n\n    void add_logger(std::shared_ptr<JniLogger> logger);\n    void remove_logger(std::shared_ptr<JniLogger> logger);\n\n    // Remove all custom loggers, but keep the default logger.\n    void clear_loggers();\n\n    // Add the default logger if it has been removed before.\n    void register_default_logger();\n\n    void set_level(Level level);\n    inline Level get_level()\n    {\n        return s_level;\n    };\n\n    void log(Level level, const char* tag, jthrowable throwable, const char* message);\n\n    inline void log(Level level, const char* tag, const char* message)\n    {\n        log(level, tag, nullptr, message);\n    }\n\n    // Helper functions for logging with REALM_JNI tag.\n    inline static void t(const char* message)\n    {\n        shared().log(trace, REALM_JNI_TAG, nullptr, message);\n    }\n    inline static void d(const char* message)\n    {\n        shared().log(debug, REALM_JNI_TAG, nullptr, message);\n    }\n    inline static void i(const char* message)\n    {\n        shared().log(info, REALM_JNI_TAG, nullptr, message);\n    }\n    inline static void w(const char* message)\n    {\n        shared().log(warn, REALM_JNI_TAG, nullptr, message);\n    }\n    inline static void e(const char* message)\n    {\n        shared().log(error, REALM_JNI_TAG, nullptr, message);\n    }\n    inline static void f(const char* message)\n    {\n        shared().log(fatal, REALM_JNI_TAG, nullptr, message);\n    }\n\n    template <typename... Args>\n    inline static void t(const char* fmt, Args&&... args)\n    {\n        shared().log(trace, REALM_JNI_TAG, nullptr, util::format(fmt, {util::Printable(args)...}).c_str());\n    }\n    template <typename... Args>\n    inline static void d(const char* fmt, Args&&... args)\n    {\n        shared().log(debug, REALM_JNI_TAG, nullptr, util::format(fmt, {util::Printable(args)...}).c_str());\n    }\n    template <typename... Args>\n    inline static void i(const char* fmt, Args&&... args)\n    {\n        shared().log(info, REALM_JNI_TAG, nullptr, util::format(fmt, {util::Printable(args)...}).c_str());\n    }\n    template <typename... Args>\n    inline static void w(const char* fmt, Args&&... args)\n    {\n        shared().log(warn, REALM_JNI_TAG, nullptr, util::format(fmt, {util::Printable(args)...}).c_str());\n    }\n    template <typename... Args>\n    inline static void e(const char* fmt, Args&&... args)\n    {\n        shared().log(error, REALM_JNI_TAG, nullptr, util::format(fmt, {util::Printable(args)...}).c_str());\n    }\n    template <typename... Args>\n    inline static void f(const char* fmt, Args&&... args)\n    {\n        shared().log(fatal, REALM_JNI_TAG, nullptr, util::format(fmt, {util::Printable(args)...}).c_str());\n    }\n\n    static realm::util::Logger::Level convert_to_core_log_level(Level level);\n\n    // Get the shared Log instance.\n    static Log& shared();\n\n    // public & static for reading faster. For TR_ENTER check.\n    // Accessing to this var won't be thread safe and it is not necessary to be. Changing log level concurrently\n    // won't be a critical issue for commons cases.\n    static Level s_level;\n\nprivate:\n    Log();\n\n    std::vector<std::shared_ptr<JniLogger>> m_loggers;\n    std::mutex m_mutex;\n    // Log tag for generic Realm JNI.\n    static const char* REALM_JNI_TAG;\n};\n\n// Base Logger class.\nclass JniLogger {\nprotected:\n    JniLogger();\n    virtual ~JniLogger();\n    // Used by JavaLogger.\n    JniLogger(bool is_java_logger);\n    // Indicate if this is a wrapper for Java RealmLogger class. See JavaLogger\n    bool m_is_java_logger;\n\nprotected:\n    // Overwrite this method to handle the log event.\n    // throwable is the Throwable passed from Java which could be null.\n    virtual void log(Log::Level level, const char* tag, jthrowable throwable, const char* message) = 0;\n    friend class Log;\n};\n\n// Implement this function to return the default logger which will be registered during initialization.\nextern std::shared_ptr<JniLogger> get_default_logger();\n\n// Do NOT call set_level_threshold on the bridge to set the log level. Instead, call the Log::set_level which will\n// set all logger levels.\nclass CoreLoggerBridge : public realm::util::Logger {\npublic:\n    CoreLoggerBridge(std::string tag);\n    ~CoreLoggerBridge();\n    CoreLoggerBridge(CoreLoggerBridge&&) = delete;\n    CoreLoggerBridge(CoreLoggerBridge&) = delete;\n    CoreLoggerBridge operator=(CoreLoggerBridge&&) = delete;\n    CoreLoggerBridge operator=(CoreLoggerBridge&) = delete;\n    void do_log(Logger::Level, const std::string& msg) override;\n\nprivate:\n    // Set log level for all logger bridges.\n    static void set_levels(Log::Level level);\n    friend class Log;\n\n    const std::string m_tag;\n    static std::vector<CoreLoggerBridge*> s_bridges;\n    static std::mutex s_mutex;\n};\n\n} // namespace jni_util\n} // namespace realm\n\n#endif // REALM_JNI_UTIL_LOG_HPP\n"
  },
  {
    "path": "realm/realm-library/src/main/cpp/observable_collection_wrapper.hpp",
    "content": "/*\n * Copyright 2017 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#ifndef REALM_JNI_IMPL_OBSERVABLE_COLLECTION_WRAPPER_HPP\n#define REALM_JNI_IMPL_OBSERVABLE_COLLECTION_WRAPPER_HPP\n\n#include \"jni_util/java_class.hpp\"\n#include \"jni_util/java_global_weak_ref.hpp\"\n#include \"jni_util/java_method.hpp\"\n#include \"jni_util/log.hpp\"\n\n#include <realm/object-store/results.hpp>\n#include <realm/util/optional.hpp>\n\nnamespace realm {\nnamespace _impl {\n\n// Wrapper of Object Store List & Results.\n// We need to control the life cycle of Results/List, weak ref of Java OsResults/OsList object and the NotificationToken.\n// Wrap all three together, so when the Java OsResults/OsList object gets GCed, all three of them will be invalidated.\ntemplate <typename T>\nclass ObservableCollectionWrapper {\npublic:\n\n    // Default to the listener class we already use\n    ObservableCollectionWrapper(T& collection)\n        : m_collection_weak_ref()\n        , m_notification_token()\n        , m_collection(std::move(collection))\n        , listener_class_name(\"io/realm/internal/ObservableCollection\")\n    {\n    }\n\n    // Give the option of specifying a different listener class (e.g. for sets)\n    ObservableCollectionWrapper(T& collection, const char* listener_class_name)\n            : m_collection_weak_ref()\n            , m_notification_token()\n            , m_collection(std::move(collection))\n            , listener_class_name(listener_class_name)\n    {\n    }\n\n    ~ObservableCollectionWrapper() = default;\n\n    ObservableCollectionWrapper(ObservableCollectionWrapper&&) = delete;\n    ObservableCollectionWrapper& operator=(ObservableCollectionWrapper&&) = delete;\n    ObservableCollectionWrapper(ObservableCollectionWrapper const&) = delete;\n    ObservableCollectionWrapper& operator=(ObservableCollectionWrapper const&) = delete;\n\n    T& collection()\n    {\n        return m_collection;\n    };\n    void start_listening(JNIEnv* env, jobject j_collection_object);\n    void stop_listening();\n\nprivate:\n    jni_util::JavaGlobalWeakRef m_collection_weak_ref;\n    NotificationToken m_notification_token;\n    T m_collection;\n\npublic:\n    const char* listener_class_name;\n};\n\ntemplate <typename T>\nvoid ObservableCollectionWrapper<T>::start_listening(JNIEnv* env, jobject j_collection_object)\n{\n    static jni_util::JavaClass os_results_class(env, listener_class_name);\n    static jni_util::JavaMethod notify_change_listeners(env, os_results_class, \"notifyChangeListeners\", \"(J)V\");\n\n    if (!m_collection_weak_ref) {\n        m_collection_weak_ref = jni_util::JavaGlobalWeakRef(env, j_collection_object);\n    }\n\n    auto cb = [=](CollectionChangeSet const& changes) {\n        // OS will call all notifiers' callback in one run, so check the Java exception first!!\n        if (env->ExceptionCheck())\n            return;\n\n        m_collection_weak_ref.call_with_local_ref(env, [&](JNIEnv* local_env, jobject collection_obj) {\n            local_env->CallVoidMethod(\n                collection_obj, notify_change_listeners,\n                reinterpret_cast<jlong>(changes.empty() ? 0 : new CollectionChangeSet(changes)));\n        });\n    };\n\n    m_notification_token = m_collection.add_notification_callback(cb);\n}\n\ntemplate <typename T>\nvoid ObservableCollectionWrapper<T>::stop_listening()\n{\n    m_notification_token = {};\n}\n\n} // namespace realm\n} // namespace _impl\n\n#endif // REALM_JNI_IMPL_OBSERVABLE_COLLECTION_WRAPPER_HPP\n"
  },
  {
    "path": "realm/realm-library/src/main/cpp/observable_dictionary_wrapper.hpp",
    "content": "/*\n * Copyright 2021 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#ifndef REALM_JNI_IMPL_OBSERVABLE_DICTIONARY_WRAPPER_HPP\n#define REALM_JNI_IMPL_OBSERVABLE_DICTIONARY_WRAPPER_HPP\n\n#include \"jni_util/java_class.hpp\"\n#include \"jni_util/java_global_weak_ref.hpp\"\n#include \"jni_util/java_method.hpp\"\n#include \"jni_util/log.hpp\"\n\n#include <realm/object-store/results.hpp>\n#include <realm/util/optional.hpp>\n#include <io_realm_internal_OsMapChangeSet.h>\n\nnamespace realm {\nnamespace _impl {\n\n// Wrapper of Object Store Dictionary.\n// We need to control the life cycle of Dictionary, weak ref of Java ObservableMap object and the NotificationToken.\n// Wrap all three together, so when the Java ObservableMap object gets GCed, all three of them will be invalidated.\nclass ObservableDictionaryWrapper {\npublic:\n    ObservableDictionaryWrapper(object_store::Dictionary& collection)\n            : m_collection_weak_ref()\n            , m_notification_token()\n            , m_collection(std::move(collection))\n    {\n    }\n\n    ~ObservableDictionaryWrapper() = default;\n\n    ObservableDictionaryWrapper(ObservableDictionaryWrapper&&) = delete;\n    ObservableDictionaryWrapper& operator=(ObservableDictionaryWrapper&&) = delete;\n    ObservableDictionaryWrapper(ObservableDictionaryWrapper const&) = delete;\n    ObservableDictionaryWrapper& operator=(ObservableDictionaryWrapper const&) = delete;\n\n    object_store::Dictionary& collection()\n    {\n        return m_collection;\n    };\n    void start_listening(JNIEnv* env, jobject j_collection_object);\n    void stop_listening();\n\nprivate:\n    jni_util::JavaGlobalWeakRef m_collection_weak_ref;\n    NotificationToken m_notification_token;\n    object_store::Dictionary m_collection;\n};\n\nvoid ObservableDictionaryWrapper::start_listening(JNIEnv* env, jobject j_observable_map)\n{\n    static jni_util::JavaClass os_map_class(env, \"io/realm/internal/ObservableMap\");\n    static jni_util::JavaMethod notify_change_listeners(env, os_map_class, \"notifyChangeListeners\", \"(J)V\");\n\n    if (!m_collection_weak_ref) {\n        m_collection_weak_ref = jni_util::JavaGlobalWeakRef(env, j_observable_map);\n    }\n\n    auto cb = [=](DictionaryChangeSet changes) {\n        // OS will call all notifiers' callback in one run, so check the Java exception first!!\n        if (env->ExceptionCheck())\n            return;\n\n        m_collection_weak_ref.call_with_local_ref(env, [&](JNIEnv* local_env, jobject collection_obj) {\n            bool changes_empty = changes.deletions.empty() &&\n                                 changes.insertions.empty() &&\n                                 changes.modifications.empty();\n\n            local_env->CallVoidMethod(\n                    collection_obj,\n                    notify_change_listeners,\n                    reinterpret_cast<jlong>(changes_empty ? io_realm_internal_OsMapChangeSet_EMPTY_CHANGESET : new DictionaryChangeSet(changes)));\n        });\n    };\n    m_notification_token = m_collection.add_key_based_notification_callback(cb);\n}\n\nvoid ObservableDictionaryWrapper::stop_listening()\n{\n    m_notification_token = {};\n}\n\n} // namespace realm\n} // namespace _impl\n\n#endif // REALM_JNI_IMPL_OBSERVABLE_DICTIONARY_WRAPPER_HPP\n"
  },
  {
    "path": "realm/realm-library/src/main/cpp/subscription_wrapper.hpp",
    "content": "/*\n * Copyright 2018 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#ifndef REALM_JNI_IMPL_SUBSCRIPTION_WRAPPER_HPP\n#define REALM_JNI_IMPL_SUBSCRIPTION_WRAPPER_HPP\n\n\n#include \"jni_util/java_class.hpp\"\n#include \"jni_util/java_global_weak_ref.hpp\"\n#include \"jni_util/java_method.hpp\"\n\n#include <realm/util/optional.hpp>\n\nnamespace realm {\nnamespace _impl {\n\n// Wrapper of Object Store Subscription\n// We need to control the life cycle of Results/List, weak ref of Java OsResults/OsList object and the NotificationToken.\n// Wrap all three together, so when the Java OsResults/OsList object gets GCed, all three of them will be invalidated.\nclass SubscriptionWrapper {\npublic:\n    SubscriptionWrapper(partial_sync::Subscription subscription)\n        : m_subscription_weak_ref(),\n          m_notification_token(),\n          m_subscription(std::move(subscription))\n    {\n    }\n\n    ~SubscriptionWrapper() = default;\n\n    SubscriptionWrapper(SubscriptionWrapper &&) = delete;\n    SubscriptionWrapper &operator=(SubscriptionWrapper &&) = delete;\n    SubscriptionWrapper(SubscriptionWrapper const &) = delete;\n    SubscriptionWrapper &operator=(SubscriptionWrapper const &) = delete;\n\n    partial_sync::Subscription& subscription() {\n        return m_subscription;\n    };\n\n    void start_listening(JNIEnv* env, jobject j_subscription_object);\n    void stop_listening();\n\nprivate:\n    jni_util::JavaGlobalWeakRef m_subscription_weak_ref;\n    partial_sync::SubscriptionNotificationToken m_notification_token;\n    partial_sync::Subscription m_subscription;\n};\n\nvoid SubscriptionWrapper::start_listening(JNIEnv *env, jobject j_subscription_object)\n{\n    static jni_util::JavaClass os_results_class(env, \"io/realm/internal/sync/OsSubscription\");\n    static jni_util::JavaMethod notify_change_listeners(env, os_results_class, \"notifyChangeListeners\", \"()V\");\n\n    if (!m_subscription_weak_ref) {\n        m_subscription_weak_ref = jni_util::JavaGlobalWeakRef(env, j_subscription_object);\n    }\n\n    auto cb = [=]() {\n        // OS will call all notifiers' callback in one run, so check the Java exception first!!\n        if (env->ExceptionCheck())\n            return;\n\n        m_subscription_weak_ref.call_with_local_ref(env, [&](JNIEnv *local_env, jobject subscription_obj) {\n            local_env->CallVoidMethod(subscription_obj, notify_change_listeners);\n        });\n    };\n\n    m_notification_token = m_subscription.add_notification_callback(cb);\n}\n\nvoid SubscriptionWrapper::stop_listening()\n{\n    m_notification_token = {};\n}\n\n} // namespace _impl\n} // namespace realm\n\n#endif // REALM_JNI_IMPL_SUBSCRIPTION_WRAPPER_HPP\n"
  },
  {
    "path": "realm/realm-library/src/main/cpp/utf8.hpp",
    "content": "/*\n * Copyright 2011 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#ifndef REALM_UTIL_UTF8_HPP\n#define REALM_UTIL_UTF8_HPP\n\n#include <stdint.h>\n#include <string>\n\n#include <realm/util/safe_int_ops.hpp>\n#include <realm/string_data.hpp>\n#include <realm/util/features.h>\n#include <realm/utilities.hpp>\n\nnamespace realm {\nnamespace util {\n\n\n/// Transcode between UTF-8 and UTF-16.\n///\n/// \\tparam Char16 Must be an integral type with at least 16 bits.\n///\n/// \\tparam Traits16 Must define to_int_type() and to_char_type() for\n/// \\a Char16.\ntemplate <class Char16, class Traits16 = std::char_traits<Char16>>\nstruct Utf8x16 {\n    /// Transcode as much as possible of the specified UTF-8 input, to\n    /// UTF-16. Returns true if all input characters were transcoded, or\n    /// transcoding stopped because the next character did not fit into the\n    /// output buffer. Returns false if transcoding stopped due to invalid\n    /// input. It is not specified whether this function returns true or false\n    /// if invalid input occurs at the same time as the output buffer runs\n    /// full. In any case, upon return, \\a in_begin and \\a out_begin are\n    /// advanced to the position where transcoding stopped.\n    ///\n    /// Throws only if Traits16::to_char_type() throws.\n    static size_t to_utf16(const char*& in_begin, const char* in_end, Char16*& out_begin, Char16* out_end);\n\n    /// Same as to_utf16(), but in reverse.\n    ///\n    /// Throws only if Traits16::to_int_type() throws.\n    static size_t to_utf8(const Char16*& in_begin, const Char16* in_end, char*& out_begin, char* out_end,\n                          size_t& error_code);\n\n    /// Summarize the number of UTF-16 elements needed to hold the result of\n    /// transcoding the specified UTF-8 string. Upon return, if \\a in_begin !=\n    /// \\a in_end, then the summation stopped due to invalid UTF-8 input. The\n    /// returned size then reflects the number of UTF-16 elements needed to hold\n    /// the result of transcoding the part of the input that was examined. This\n    /// function will only detect a few UTF-8 validity issues, and can therefore\n    /// not be used for general UTF-8 validation.\n    static std::size_t find_utf16_buf_size(const char*& in_begin, const char* in_end, size_t& error_code);\n\n    /// Summarize the number of UTF-8 bytes needed to hold the result of\n    /// transcoding the specified UTF-16 string. Upon return, if \\a in_begin !=\n    /// \\a in_end, then the summation stopped due to invalid UTF-16 input, or to\n    /// prevent the returned \\c size_t value from overflowing. The returned size\n    /// then reflects the number of UTF-8 bytes needed to hold the result of\n    /// transcoding the part of the input that was examined. This function will\n    /// only detect a few UTF-16 validity issues, and can therefore not be used\n    /// for general UTF-16 validation.\n    static std::size_t find_utf8_buf_size(const Char16*& in_begin, const Char16* in_end, size_t& error_code);\n};\n\n\n// Implementation:\n\n// Adapted from reference implementation.\n// http://www.unicode.org/resources/utf8.html\n// http://www.bsdua.org/files/unicode.tar.gz\ntemplate <class Char16, class Traits16>\ninline size_t Utf8x16<Char16, Traits16>::to_utf16(const char*& in_begin, const char* in_end, Char16*& out_begin,\n                                                  Char16* out_end)\n{\n    using namespace std;\n    typedef char_traits<char> traits8;\n    size_t invalid = 0;\n    const char* in = in_begin;\n    Char16* out = out_begin;\n    while (in != in_end) {\n        if (REALM_UNLIKELY(out == out_end)) {\n            break; // Need space in output buffer\n        }\n        uint_fast16_t v1 = uint_fast16_t(traits8::to_int_type(in[0]));\n        if (REALM_LIKELY(v1 < 0x80)) { // One byte\n            // UTF-8 layout: 0xxxxxxx\n            *out++ = Traits16::to_char_type(v1);\n            in += 1;\n            continue;\n        }\n        if (REALM_UNLIKELY(v1 < 0xC0)) {\n            invalid = true;\n            break; // Invalid first byte of UTF-8 sequence\n        }\n        if (REALM_LIKELY(v1 < 0xE0)) { // Two bytes\n            if (REALM_UNLIKELY(in_end - in < 2)) {\n                invalid = 1;\n                break; // Incomplete UTF-8 sequence\n            }\n            uint_fast16_t v2 = uint_fast16_t(traits8::to_int_type(in[1]));\n            // UTF-8 layout: 110xxxxx 10xxxxxx\n            if (REALM_UNLIKELY((v2 & 0xC0) != 0x80)) {\n                invalid = 2;\n                break; // Invalid continuation byte\n            }\n            uint_fast16_t v = uint_fast16_t(((v1 & 0x1F) << 6) | ((v2 & 0x3F) << 0));\n            if (REALM_UNLIKELY(v < 0x80)) {\n                invalid = 3;\n                break; // Overlong encoding is invalid\n            }\n            *out++ = Traits16::to_char_type(v);\n            in += 2;\n            continue;\n        }\n        if (REALM_LIKELY(v1 < 0xF0)) { // Three bytes\n            if (REALM_UNLIKELY(in_end - in < 3)) {\n                invalid = 4;\n                break; // Incomplete UTF-8 sequence\n            }\n            uint_fast16_t v2 = uint_fast16_t(traits8::to_int_type(in[1]));\n            uint_fast16_t v3 = uint_fast16_t(traits8::to_int_type(in[2]));\n            // UTF-8 layout: 1110xxxx 10xxxxxx 10xxxxxx\n            if (REALM_UNLIKELY((v2 & 0xC0) != 0x80 || (v3 & 0xC0) != 0x80)) {\n                invalid = true;\n                break; // Invalid continuation byte\n            }\n            uint_fast16_t v = uint_fast16_t(((v1 & 0x0F) << 12) | ((v2 & 0x3F) << 6) | ((v3 & 0x3F) << 0));\n            if (REALM_UNLIKELY(v < 0x800)) {\n                invalid = 5;\n                break; // Overlong encoding is invalid\n            }\n            if (REALM_UNLIKELY(0xD800 <= v && v < 0xE000)) {\n                invalid = 6;\n                break; // Illegal code point range (reserved for UTF-16 surrogate pairs)\n            }\n            *out++ = Traits16::to_char_type(v);\n            in += 3;\n            continue;\n        }\n        if (REALM_UNLIKELY(out + 1 == out_end)) {\n            break; // Need space in output buffer for surrogate pair\n        }\n        if (REALM_LIKELY(v1 < 0xF8)) { // Four bytes\n            if (REALM_UNLIKELY(in_end - in < 4)) {\n                invalid = 7;\n                break; // Incomplete UTF-8 sequence\n            }\n            uint_fast32_t w1 = uint_fast32_t(v1);                          // 16 bit -> 32 bit\n            uint_fast32_t v2 = uint_fast32_t(traits8::to_int_type(in[1])); // 32 bit intended\n            uint_fast16_t v3 = uint_fast16_t(traits8::to_int_type(in[2])); // 16 bit intended\n            uint_fast16_t v4 = uint_fast16_t(traits8::to_int_type(in[3])); // 16 bit intended\n            // UTF-8 layout: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx\n            if (REALM_UNLIKELY((v2 & 0xC0) != 0x80 || (v3 & 0xC0) != 0x80 || (v4 & 0xC0) != 0x80)) {\n                invalid = 8;\n                break; // Invalid continuation byte\n            }\n            uint_fast32_t v = uint_fast32_t(((w1 & 0x07) << 18) | // Parenthesis is 32 bit partial result\n                                            ((v2 & 0x3F) << 12) | // Parenthesis is 32 bit partial result\n                                            ((v3 & 0x3F) << 6) |  // Parenthesis is 16 bit partial result\n                                            ((v4 & 0x3F) << 0));  // Parenthesis is 16 bit partial result\n            if (REALM_UNLIKELY(v < 0x10000)) {\n                invalid = 9;\n                break; // Overlong encoding is invalid\n            }\n            if (REALM_UNLIKELY(0x110000 <= v)) {\n                invalid = 19;\n                break; // Code point too big for UTF-16\n            }\n            v -= 0x10000l;\n            *out++ = Traits16::to_char_type(0xD800 + (v / 0x400));\n            *out++ = Traits16::to_char_type(0xDC00 + (v % 0x400));\n            in += 4;\n            continue;\n        }\n        // Invalid first byte of UTF-8 sequence, or code point too big for UTF-16\n        invalid = 11;\n        break;\n    }\n\n    in_begin = in;\n    out_begin = out;\n    return invalid;\n}\n\n\ntemplate <class Char16, class Traits16>\ninline std::size_t Utf8x16<Char16, Traits16>::find_utf16_buf_size(const char*& in_begin, const char* in_end,\n                                                                  size_t& error_code)\n{\n    using namespace std;\n    typedef char_traits<char> traits8;\n    size_t num_out = 0;\n    error_code = 0;\n    const char* in = in_begin;\n    while (in != in_end) {\n        uint_fast16_t v1 = uint_fast16_t(traits8::to_int_type(in[0]));\n        if (REALM_LIKELY(v1 < 0x80)) { // One byte\n            num_out += 1;\n            in += 1;\n            continue;\n        }\n        if (REALM_UNLIKELY(v1 < 0xC0)) {\n            error_code = 1;\n            break; // Invalid first byte of UTF-8 sequence\n        }\n        if (REALM_LIKELY(v1 < 0xE0)) { // Two bytes\n            if (REALM_UNLIKELY(in_end - in < 2)) {\n                error_code = 2;\n                break; // Incomplete UTF-8 sequence\n            }\n            num_out += 1;\n            in += 2;\n            continue;\n        }\n        if (REALM_LIKELY(v1 < 0xF0)) { // Three bytes\n            if (REALM_UNLIKELY(in_end - in < 3)) {\n                error_code = 3;\n                break; // Incomplete UTF-8 sequence\n            }\n            num_out += 1;\n            in += 3;\n            continue;\n        }\n        if (REALM_LIKELY(v1 < 0xF8)) { // Four bytes\n            if (REALM_UNLIKELY(in_end - in < 4)) {\n                error_code = 4;\n                break; // Incomplete UTF-8 sequence\n            }\n            num_out += 2; // Surrogate pair\n            in += 4;\n            continue;\n        }\n        // Invalid first byte of UTF-8 sequence, or code point too big for UTF-16\n        error_code = 5;\n        break;\n    }\n\n    in_begin = in;\n    return num_out;\n}\n\n\n// Adapted from reference implementation.\n// http://www.unicode.org/resources/utf8.html\n// http://www.bsdua.org/files/unicode.tar.gz\ntemplate <class Char16, class Traits16>\ninline size_t Utf8x16<Char16, Traits16>::to_utf8(const Char16*& in_begin, const Char16* in_end, char*& out_begin,\n                                                 char* out_end, size_t& error_code)\n{\n    using namespace std;\n    typedef char_traits<char> traits8;\n    typedef typename traits8::int_type traits8_int_type;\n    bool invalid = false;\n    error_code = 0;\n    const Char16* in = in_begin;\n    char* out = out_begin;\n    while (in != in_end) {\n        uint_fast16_t v1 = uint_fast16_t(Traits16::to_int_type(in[0]));\n        if (REALM_LIKELY(v1 < 0x80)) {\n            if (REALM_UNLIKELY(out == out_end)) {\n                error_code = 1;\n                break; // Not enough output buffer space\n            }\n            // UTF-8 layout: 0xxxxxxx\n            *out++ = traits8::to_char_type(traits8_int_type(v1));\n            in += 1;\n            continue;\n        }\n        if (REALM_LIKELY(v1 < 0x800)) {\n            if (REALM_UNLIKELY(out_end - out < 2)) {\n                error_code = 2;\n                break; // Not enough output buffer space\n            }\n            // UTF-8 layout: 110xxxxx 10xxxxxx\n            *out++ = traits8::to_char_type(traits8_int_type(0xC0 + v1 / 0x40));\n            *out++ = traits8::to_char_type(traits8_int_type(0x80 + v1 % 0x40));\n            in += 1;\n            continue;\n        }\n        if (REALM_LIKELY(v1 < 0xD800 || 0xE000 <= v1)) {\n            if (REALM_UNLIKELY(out_end - out < 3)) {\n                error_code = 3;\n                break; // Not enough output buffer space\n            }\n            // UTF-8 layout: 1110xxxx 10xxxxxx 10xxxxxx\n            *out++ = traits8::to_char_type(traits8_int_type(0xE0 + v1 / 0x1000));\n            *out++ = traits8::to_char_type(traits8_int_type(0x80 + v1 / 0x40 % 0x40));\n            *out++ = traits8::to_char_type(traits8_int_type(0x80 + v1 % 0x40));\n            in += 1;\n            continue;\n        }\n\n        // Surrogate pair\n        if (REALM_UNLIKELY(out_end - out < 4)) {\n            error_code = 4;\n            break; // Not enough output buffer space\n        }\n        if (REALM_UNLIKELY(0xDC00 <= v1)) {\n            error_code = 5;\n            invalid = true;\n            break; // Invalid first half of surrogate pair\n        }\n        if (REALM_UNLIKELY(in + 1 == in_end)) {\n            error_code = 6;\n            invalid = true;\n            break; // Incomplete surrogate pair\n        }\n        uint_fast16_t v2 = uint_fast16_t(Traits16::to_int_type(in[1]));\n        if (REALM_UNLIKELY(v2 < 0xDC00 || 0xE000 <= v2)) {\n            error_code = 7;\n            invalid = true;\n            break; // Invalid second half of surrogate pair\n        }\n        uint_fast32_t v = 0x10000l + (uint_fast32_t(v1 - 0xD800) * 0x400 + (v2 - 0xDC00));\n        // UTF-8 layout: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx\n        *out++ = traits8::to_char_type(traits8_int_type(0xF0 + v / 0x40000));\n        *out++ = traits8::to_char_type(traits8_int_type(0x80 + v / 0x1000 % 0x40));\n        *out++ = traits8::to_char_type(traits8_int_type(0x80 + v / 0x40 % 0x40));\n        *out++ = traits8::to_char_type(traits8_int_type(0x80 + v % 0x40));\n        in += 2;\n    }\n\n    in_begin = in;\n    out_begin = out;\n    return !invalid;\n}\n\n\ntemplate <class Char16, class Traits16>\ninline std::size_t Utf8x16<Char16, Traits16>::find_utf8_buf_size(const Char16*& in_begin, const Char16* in_end,\n                                                                 size_t& error_code)\n{\n    using namespace std;\n    size_t num_out = 0;\n    error_code = 0;\n    const Char16* in = in_begin;\n    while (in != in_end) {\n        uint_fast16_t v = uint_fast16_t(Traits16::to_int_type(in[0]));\n        if (REALM_LIKELY(v < 0x80)) {\n            if (REALM_UNLIKELY(int_add_with_overflow_detect(num_out, 1))) {\n                error_code = 1;\n                break; // Avoid overflow\n            }\n            in += 1;\n        }\n        else if (REALM_LIKELY(v < 0x800)) {\n            if (REALM_UNLIKELY(int_add_with_overflow_detect(num_out, 2))) {\n                error_code = 2;\n                break; // Avoid overflow\n            }\n            in += 1;\n        }\n        else if (REALM_LIKELY(v < 0xD800 || 0xE000 <= v)) {\n            if (REALM_UNLIKELY(int_add_with_overflow_detect(num_out, 3))) {\n                error_code = 3;\n                break; // Avoid overflow\n            }\n            in += 1;\n        }\n        else {\n            if (REALM_UNLIKELY(in + 1 == in_end)) {\n                error_code = 4;\n                break; // Incomplete surrogate pair\n            }\n            if (REALM_UNLIKELY(int_add_with_overflow_detect(num_out, 4))) {\n                error_code = 5;\n                break; // Avoid overflow\n            }\n            in += 2;\n        }\n    }\n\n    in_begin = in;\n    return num_out;\n}\n} // namespace util\n} // namespace realm\n\n#endif // REALM_UTIL_UTF8_HPP\n"
  },
  {
    "path": "realm/realm-library/src/main/cpp/util.cpp",
    "content": "/*\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#include <algorithm>\n#include <iomanip>\n#include <stdexcept>\n\n#include <realm/util/assert.hpp>\n#include <realm/util/file.hpp>\n#include <realm/unicode.hpp>\n#include <jni_util/java_method.hpp>\n#include \"utf8.hpp\"\n\n#include \"util.hpp\"\n#include \"io_realm_internal_Util.h\"\n#include \"io_realm_internal_OsSharedRealm.h\"\n#include <realm/object-store/shared_realm.hpp>\n#include <realm/object-store/results.hpp>\n#include <realm/object-store/list.hpp>\n#include <realm/object-store/object.hpp>\n#include <realm/parser/query_parser.hpp>\n#if REALM_ENABLE_SYNC\n#include <realm/object-store/sync/app.hpp>\n#endif\n\n#include \"java_exception_def.hpp\"\n#include \"java_object_accessor.hpp\"\n#include \"jni_util/java_exception_thrower.hpp\"\n\nusing namespace realm;\nusing namespace realm::util;\nusing namespace realm::jni_util;\nusing namespace realm::_impl;\n\n\n#if REALM_ENABLE_SYNC\nrealm::SyncClientConfig::LoggerFactory javaLoggerFactory = [](realm::util::Logger::Level) {\n    // The level param is ignored. Use the global RealmLog.setLevel() to control all log levels.\n    return std::make_unique<realm::jni_util::CoreLoggerBridge>(std::string(\"REALM_SYNC\"));\n};\n#endif\n\nvoid ThrowRealmFileException(JNIEnv* env, const std::string& message, ErrorCodes::Error code, const std::string_view& path = \"\");\n\nvoid ConvertException(JNIEnv* env, const char* file, int line)\n{\n    std::ostringstream ss;\n    try {\n        throw;\n    }\n    catch (JavaExceptionThrower& e) {\n        e.throw_java_exception(env);\n    }\n    catch (std::bad_alloc& e) {\n        ss << e.what() << \" in \" << file << \" line \" << line;\n        ThrowException(env, OutOfMemory, ss.str());\n    }\n    catch (CrossTableLinkTarget& e) {\n        ss << e.what() << \" in \" << file << \" line \" << line;\n        ThrowException(env, IllegalState, ss.str());\n    }\n    catch (DB::BadVersion& e) {\n        ss << e.what() << \" in \" << file << \" line \" << line;\n        ThrowException(env, BadVersion, ss.str());\n    }\n    catch (OutOfBounds& e) {\n        ss << \"Out of range  in \" << file << \" line \" << line << \"(requested: \" << e.index\n           << \" valid: \" << e.size << \")\";\n        ThrowException(env, IndexOutOfBounds, ss.str());\n    }\n    catch (InvalidArgument& e) {\n        ss << e.what() << \" in \" << file << \" line \" << line;\n        ThrowException(env, IllegalArgument, ss.str());\n    }\n    catch (const InvalidDatabase& e) {\n        ss << e.what() << \" (\" << e.get_path() << \") in \" << file << \" line \" << line;\n        ThrowRealmFileException(env, ss.str(), e.code(), e.get_path());\n    }\n    catch (FileAccessError& e) {\n        ss << e.what() << \" (\" << e.get_path() << \") in \" << file << \" line \" << line;\n        ThrowRealmFileException(env, ss.str(), e.code(), e.get_path());\n    }\n    catch(realm::MissingPropertyValueException& e) {\n        ThrowException(env, IllegalArgument, e.what());\n    }\n    catch(realm::RequiredFieldValueNotProvidedException& e) {\n        ThrowException(env, IllegalArgument, e.what());\n    }\n#if REALM_ENABLE_SYNC\n    catch (realm::app::AppError& e) {\n        // TODO Figure out exactly what kind of mapping is needed here\n        if (e.is_custom_error()) {\n            ThrowException(env, IllegalArgument, e.what());\n        }\n        else if (e.code() == ErrorCodes::ClientUserNotLoggedIn) {\n            ThrowException(env, IllegalArgument, e.what());\n        }\n        else {\n            ThrowException(env, IllegalState, e.what());\n        }\n    }\n#endif\n    catch (LogicError& e) {\n        ThrowException(env, IllegalState, e.what());\n    }\n    catch (realm::RuntimeError& e) {\n        ss << e.what() << \" in \" << file << \" line \" << line;\n        ThrowException(env, ExceptionKind::RuntimeError, ss.str());\n    }\n    catch (realm::Exception& e) {\n        ss << e.what() << \" in \" << file << \" line \" << line;\n\n        if(e.code() == realm::ErrorCodes::IllegalOperation) {\n            ThrowException(env, IllegalState, ss.str());\n        } else {\n            ThrowException(env, FatalError, ss.str());\n        }\n    }\n    /* catch (...) is not needed if we only throw exceptions derived from std::exception */\n}\n\nvoid ThrowException(JNIEnv* env, ExceptionKind exception, const char* classStr)\n{\n    ThrowException(env, exception, classStr, \"\");\n}\n\nvoid ThrowException(JNIEnv* env, ExceptionKind exception, const std::string& classStr, const std::string& itemStr)\n{\n    std::string message;\n    jclass jExceptionClass = NULL;\n\n    Log::e(\"jni: ThrowingException %1, %2, %3.\", exception, classStr.c_str(), itemStr.c_str());\n\n    switch (exception) {\n        case ClassNotFound:\n            jExceptionClass = env->FindClass(\"java/lang/ClassNotFoundException\");\n            message = \"Class '\" + classStr + \"' could not be located.\";\n            break;\n\n        case IllegalArgument:\n            jExceptionClass = env->FindClass(\"java/lang/IllegalArgumentException\");\n            message = \"Illegal Argument: \" + classStr;\n            break;\n\n        case IndexOutOfBounds:\n            jExceptionClass = env->FindClass(\"java/lang/ArrayIndexOutOfBoundsException\");\n            message = classStr;\n            break;\n\n        case UnsupportedOperation:\n            jExceptionClass = env->FindClass(\"java/lang/UnsupportedOperationException\");\n            message = classStr;\n            break;\n\n        case OutOfMemory:\n            jExceptionClass = env->FindClass(JavaExceptionDef::OutOfMemory);\n            message = classStr + \" \" + itemStr;\n            break;\n\n        case FatalError:\n            jExceptionClass = env->FindClass(\"io/realm/exceptions/RealmError\");\n            message = \"Unrecoverable error. \" + classStr;\n            break;\n        case ExceptionKind::RuntimeError:\n            jExceptionClass = env->FindClass(\"java/lang/RuntimeException\");\n            message = classStr;\n            break;\n\n        case BadVersion:\n            jExceptionClass = env->FindClass(\"io/realm/internal/async/BadVersionException\");\n            message = classStr;\n            break;\n\n        case IllegalState:\n            jExceptionClass = env->FindClass(\"java/lang/IllegalStateException\");\n            message = classStr;\n            break;\n        case IllegalFormatException:\n            jExceptionClass = env->FindClass(\"java/util/IllegalFormatException\");\n            message = classStr;\n            break;\n        // Should never get here.\n        case ExceptionKindMax:\n        default:\n            break;\n    }\n    if (jExceptionClass != NULL) {\n        Log::e(\"Exception has been thrown: %1\", message.c_str());\n        env->ThrowNew(jExceptionClass, message.c_str());\n    }\n    else {\n        Log::e(\"ERROR: Couldn't throw exception.\");\n    }\n\n    env->DeleteLocalRef(jExceptionClass);\n}\n\nvoid ThrowRealmFileException(JNIEnv* env, const std::string& message, ErrorCodes::Error code, const std::string_view& path)\n{\n    static JavaClass  jrealm_file_exception_cls(env, \"io/realm/exceptions/RealmFileException\");\n    static JavaMethod constructor(env, jrealm_file_exception_cls, \"<init>\", \"(BLjava/lang/String;)V\");\n\n    // Initial value to suppress gcc warning.\n    jbyte kind_code; // To suppress compile warning.\n    switch (code) {\n        case ErrorCodes::Error::InvalidDatabase:\n            kind_code = io_realm_internal_OsSharedRealm_FILE_EXCEPTION_KIND_ACCESS_ERROR;\n            break;\n        case ErrorCodes::Error::IncompatibleHistories:\n            kind_code = io_realm_internal_OsSharedRealm_FILE_EXCEPTION_KIND_BAD_HISTORY;\n            break;\n        case ErrorCodes::Error::PermissionDenied:\n            kind_code = io_realm_internal_OsSharedRealm_FILE_EXCEPTION_KIND_PERMISSION_DENIED;\n            break;\n        case ErrorCodes::Error::FileAlreadyExists:\n            kind_code = io_realm_internal_OsSharedRealm_FILE_EXCEPTION_KIND_EXISTS;\n            break;\n        case ErrorCodes::Error::FileNotFound:\n            kind_code = io_realm_internal_OsSharedRealm_FILE_EXCEPTION_KIND_NOT_FOUND;\n            break;\n        case ErrorCodes::Error::IncompatibleLockFile:\n            kind_code = io_realm_internal_OsSharedRealm_FILE_EXCEPTION_KIND_INCOMPATIBLE_LOCK_FILE;\n            break;\n        case ErrorCodes::Error::FileFormatUpgradeRequired:\n            kind_code = io_realm_internal_OsSharedRealm_FILE_EXCEPTION_KIND_FORMAT_UPGRADE_REQUIRED;\n            break;\n        default:\n            kind_code = -1;\n    }\n    if (kind_code == -1) {\n        // No matching error code, throwing a fatal error one\n        ThrowException(env, FatalError, message);\n    } else {\n        jstring jmessage = to_jstring(env, message);\n        jstring jpath = to_jstring(env, path);\n        jobject exception = env->NewObject(jrealm_file_exception_cls, constructor, kind_code, jmessage, jpath);\n        env->Throw(reinterpret_cast<jthrowable>(exception));\n        env->DeleteLocalRef(exception);\n    }\n}\n\nvoid ThrowNullValueException(JNIEnv* env, const TableRef table, ColKey col_key)\n{\n    std::ostringstream ss;\n    ss << \"Trying to set a non-nullable field '\" << table->get_column_name(col_key) << \"' in '\" << table->get_name()\n       << \"' to null.\";\n    ThrowException(env, IllegalArgument, ss.str());\n}\n//*********************************************************************\n// String handling\n//*********************************************************************\n\nnamespace {\n\n// This assumes that 'jchar' is an integral type with at least 16\n// non-sign value bits, that is, an unsigned 16-bit integer, or any\n// signed or unsigned integer with more than 16 bits.\nstruct JcharTraits {\n    static jchar to_int_type(jchar c) noexcept\n    {\n        return c;\n    }\n    static jchar to_char_type(jchar i) noexcept\n    {\n        return i;\n    }\n};\n\nstruct JStringCharsAccessor {\n    JStringCharsAccessor(JNIEnv* e, jstring s, bool delete_jstring_ref_on_delete)\n        : m_env(e)\n        , m_string(s)\n        , m_data(e->GetStringChars(s, 0))\n        , m_size(get_size(e, s))\n        , m_delete_jstring_ref_on_delete(delete_jstring_ref_on_delete)\n    {\n    }\n    ~JStringCharsAccessor()\n    {\n        m_env->ReleaseStringChars(m_string, m_data);\n        // TODO Left as opt-in to avoid inspecting all usages as part of the fix for\n        //  https://github.com/realm/realm-java/pull/7232. We should consider making this the\n        //  default and try to handle local refs uniformly through JavaLocalRefs or similar\n        //  mechanisms.\n        if (m_delete_jstring_ref_on_delete) {\n            m_env->DeleteLocalRef(m_string);\n        }\n    }\n    const jchar* data() const noexcept\n    {\n        return m_data;\n    }\n    size_t size() const noexcept\n    {\n        return m_size;\n    }\n\nprivate:\n    JNIEnv* const m_env;\n    const jstring m_string;\n    const jchar* const m_data;\n    const size_t m_size;\n    const bool m_delete_jstring_ref_on_delete;\n\n    static size_t get_size(JNIEnv* e, jstring s)\n    {\n        size_t size;\n        if (int_cast_with_overflow_detect(e->GetStringLength(s), size))\n            throw realm::RuntimeError(ErrorCodes::RuntimeError, \"String size overflow\");\n        return size;\n    }\n};\n\n} // anonymous namespace\n\nstatic std::string string_to_hex(const std::string& message, StringData& str, const char* in_begin, const char* in_end,\n                            jchar* out_curr, jchar* out_end, size_t retcode, size_t error_code)\n{\n    std::ostringstream ret;\n\n    const char* s = str.data();\n    ret << message << \" \";\n    ret << \"error_code = \" << error_code << \"; \";\n    ret << \"retcode = \" << retcode << \"; \";\n    ret << \"StringData.size = \" << str.size() << \"; \";\n    ret << \"StringData.data = \" << str << \"; \";\n    ret << \"StringData as hex = \";\n    for (std::string::size_type i = 0; i < str.size(); ++i)\n        ret << \" 0x\" << std::hex << std::setfill('0') << std::setw(2) << (int)s[i];\n    ret << \"; \";\n    ret << \"in_begin = \" << in_begin << \"; \";\n    ret << \"in_end = \" << in_end << \"; \";\n    ret << \"out_curr = \" << out_curr << \"; \";\n    ret << \"out_end = \" << out_end << \";\";\n    return ret.str();\n}\n\nstatic std::string str_to_hex_error_code_to_message(size_t error_code){\n    switch (error_code){\n        case 1:\n        case 2:\n        case 3:\n        case 4:\n            return \"Not enough output buffer space\";\n        case 5:\n            return \"Invalid first half of surrogate pair\";\n        case 6:\n            return \"Incomplete surrogate pair\";\n        case 7:\n            return \"Invalid second half of surrogate pair\";\n        default:\n            return \"Unknown\";\n    }\n}\n\nstatic std::string string_to_hex(const std::string& message, const jchar* str, size_t size, size_t error_code)\n{\n    std::ostringstream ret;\n\n    ret << message << \": \" << str_to_hex_error_code_to_message(error_code) << \"; \";\n    ret << \"error_code = \" << error_code << \"; \";\n    for (size_t i = 0; i < size; ++i) {\n        ret << \" 0x\" << std::hex << std::setfill('0') << std::setw(4) << (int) str[i];\n    }\n    return ret.str();\n}\n\nstd::string concat_stringdata(const char* message, StringData strData)\n{\n    if (strData.is_null()) {\n        return std::string(message);\n    }\n    return std::string(message) + std::string(strData.data(), strData.size());\n}\n\njstring to_jstring(JNIEnv* env, StringData str)\n{\n    if (str.is_null()) {\n        return NULL;\n    }\n\n    // For efficiency, if the incoming UTF-8 string is sufficiently\n    // small, we will attempt to store the UTF-16 output into a stack\n    // allocated buffer of static size. Otherwise we will have to\n    // dynamically allocate the output buffer after calculating its\n    // size.\n\n    const size_t stack_buf_size = 48;\n    jchar stack_buf[stack_buf_size];\n    std::unique_ptr<jchar[]> dyn_buf;\n\n    const char* in_begin = str.data();\n    const char* in_end = str.data() + str.size();\n    jchar* out_begin = stack_buf;\n    jchar* out_curr = stack_buf;\n    jchar* out_end = stack_buf + stack_buf_size;\n\n    typedef Utf8x16<jchar, JcharTraits> Xcode;\n\n    if (str.size() <= stack_buf_size) {\n        size_t retcode = Xcode::to_utf16(in_begin, in_end, out_curr, out_end);\n        if (retcode != 0) {\n            throw realm::RuntimeError(ErrorCodes::RuntimeError,string_to_hex(\"Failure when converting short string to UTF-16\", str, in_begin, in_end,\n                                              out_curr, out_end, size_t(0), retcode));\n        }\n        if (in_begin == in_end) {\n            goto transcode_complete;\n        }\n    }\n\n    {\n        const char* in_begin2 = in_begin;\n        size_t error_code;\n        size_t size = Xcode::find_utf16_buf_size(in_begin2, in_end, error_code);\n        if (in_begin2 != in_end) {\n            throw realm::RuntimeError(ErrorCodes::RuntimeError,string_to_hex(\"Failure when computing UTF-16 size\", str, in_begin, in_end, out_curr,\n                                              out_end, size, error_code));\n        }\n        if (int_add_with_overflow_detect(size, stack_buf_size)) {\n            throw realm::RuntimeError(ErrorCodes::RuntimeError,\"String size overflow\");\n        }\n        dyn_buf.reset(new jchar[size]);\n        out_curr = std::copy(out_begin, out_curr, dyn_buf.get());\n        out_begin = dyn_buf.get();\n        out_end = dyn_buf.get() + size;\n        size_t retcode = Xcode::to_utf16(in_begin, in_end, out_curr, out_end);\n        if (retcode != 0) {\n            throw realm::RuntimeError(ErrorCodes::RuntimeError,string_to_hex(\"Failure when converting long string to UTF-16\", str, in_begin, in_end,\n                                              out_curr, out_end, size_t(0), retcode));\n        }\n        REALM_ASSERT(in_begin == in_end);\n    }\n\ntranscode_complete : {\n    jsize out_size;\n    if (int_cast_with_overflow_detect(out_curr - out_begin, out_size)) {\n        throw realm::RuntimeError(ErrorCodes::RuntimeError,\"String size overflow\");\n    }\n\n    return env->NewString(out_begin, out_size);\n}\n}\n\n\nJStringAccessor::JStringAccessor(JNIEnv* env, jstring str, bool delete_jstring_ref)\n    : m_env(env)\n{\n    // For efficiency, if the incoming UTF-16 string is sufficiently\n    // small, we will choose an UTF-8 output buffer whose size (in\n    // bytes) is simply 4 times the number of 16-bit elements in the\n    // input. This is guaranteed to be enough. However, to avoid\n    // excessive over allocation, this is not done for larger input\n    // strings.\n\n    if (str == NULL) {\n        m_is_null = true;\n        return;\n    }\n    m_is_null = false;\n\n    JStringCharsAccessor chars(env, str, delete_jstring_ref);\n\n    typedef Utf8x16<jchar, JcharTraits> Xcode;\n    size_t max_project_size = 48;\n    REALM_ASSERT(max_project_size <= std::numeric_limits<size_t>::max() / 4);\n    size_t buf_size;\n    if (chars.size() <= max_project_size) {\n        buf_size = chars.size() * 4;\n    }\n    else {\n        const jchar* begin = chars.data();\n        const jchar* end = begin + chars.size();\n        size_t error_code;\n        buf_size = Xcode::find_utf8_buf_size(begin, end, error_code);\n    }\n    char* tmp_char_array = new char[buf_size]; // throws\n    m_data.reset(tmp_char_array, std::default_delete<char[]>());\n    {\n        const jchar* in_begin = chars.data();\n        const jchar* in_end = in_begin + chars.size();\n        char* out_begin = m_data.get();\n        char* out_end = m_data.get() + buf_size;\n        size_t error_code;\n        if (!Xcode::to_utf8(in_begin, in_end, out_begin, out_end, error_code)) {\n            throw realm::InvalidArgument(\n                string_to_hex(\"Failure when converting to UTF-8\", chars.data(), chars.size(), error_code));\n        }\n        if (in_begin != in_end) {\n            throw realm::InvalidArgument(\n                string_to_hex(\"in_begin != in_end when converting to UTF-8\", chars.data(), chars.size(), error_code));\n        }\n        m_size = out_begin - m_data.get();\n        // FIXME: Does this help on string issues? Or does it only help lldb?\n        std::memset(tmp_char_array + m_size, 0, buf_size - m_size);\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/cpp/util.hpp",
    "content": "/*\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#ifndef REALM_JAVA_UTIL_HPP\n#define REALM_JAVA_UTIL_HPP\n\n#include <string>\n#include <string_view>\n#include <sstream>\n#include <memory>\n\n#include <jni.h>\n\n// Used by logging\n#include <inttypes.h>\n\n#include <realm.hpp>\n#include <realm/error_codes.hpp>\n#include <realm/timestamp.hpp>\n#include <realm/table.hpp>\n#include <realm/util/basic_system_errors.hpp>\n#include <realm/util/safe_int_ops.hpp>\n#include \"io_realm_internal_Util.h\"\n\n#include \"java_exception_def.hpp\"\n#include \"jni_util/log.hpp\"\n#include \"jni_util/java_exception_thrower.hpp\"\n\n#if REALM_ENABLE_SYNC\n#include <realm/sync/client_base.hpp>\n#endif\n\n#define CHECK_PARAMETERS 1 // Check all parameters in API and throw exceptions in java if invalid\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nJNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* reserved);\n\n#ifdef __cplusplus\n}\n#endif\n\n// Exception handling\n#define CATCH_STD()                                                                                                  \\\n    catch (...)                                                                                                      \\\n    {                                                                                                                \\\n        ConvertException(env, __FILE__, __LINE__);                                                                   \\\n    }\n\n// Return a Decimal128 value as a jlongArray two value (low, high) or nullptrif the Decimal128 is null\n#define RETURN_DECIMAL128_AS_JLONG_ARRAY__OR_NULL(decimal128)                                          \\\n    if (!decimal128.is_null()) {                                                                       \\\n        uint64_t* raw = decimal128.raw()->w;                                                           \\\n        jlongArray ret_array = env->NewLongArray(2);                                                   \\\n        if (!ret_array) {                                                                              \\\n            ThrowException(env, OutOfMemory, \"Could not allocate memory to return decimal128 value.\"); \\\n            return nullptr;                                                                            \\\n        }                                                                                              \\\n        jlong ret[2] = { jlong(raw[0])/*low*/, jlong(raw[1]) /*high*/};                                \\\n        env->SetLongArrayRegion(ret_array, 0, 2, ret);                                                 \\\n        return ret_array;                                                                              \\\n    } else {                                                                                           \\\n        return nullptr;                                                                                \\\n    }\n\n#define MAX_JINT 0x7FFFFFFFL\n#define MAX_JSIZE MAX_JINT\n#define MAX_JLONG 0x7fffffffffffffffLL\n#define MIN_JLONG (-MAX_JLONG-1)\n\n// TODO: Clean up those marcos. Casting with marcos reduces the readability, and it is actually breaking the C++ type\n// conversion. e.g.: You cannot cast a pointer with S64 below.\n// Helper macros for better readability\n#define S(x) static_cast<size_t>(x)\n#define B(x) static_cast<bool>(x)\n#define Q(x) reinterpret_cast<realm::Query*>(x)\n#define OBJ(x) reinterpret_cast<realm::Obj*>(x)\n#define TBL_REF(x) *reinterpret_cast<realm::TableRef*>(x)\n\n// Exception handling\nenum ExceptionKind {\n    // FIXME: This is not something should be exposed to java, ClassNotFound is something we should\n    // crash hard in native code and fix it.\n    ClassNotFound = 0,\n    IllegalArgument,\n    IllegalFormatException,\n    IndexOutOfBounds,\n    UnsupportedOperation,\n    OutOfMemory,\n    FatalError,\n    RuntimeError,\n    BadVersion,\n    IllegalState,\n    RealmFileError,\n    // NOTE!!!!: Please also add test cases to io_realm_internal_TestUtil when introducing a\n    // new exception kind.\n    ExceptionKindMax // Always keep this as the last one!\n};\n\nvoid ConvertException(JNIEnv* env, const char* file, int line);\nvoid ThrowException(JNIEnv* env, ExceptionKind exception, const std::string& classStr,\n                    const std::string& itemStr = \"\");\nvoid ThrowException(JNIEnv* env, ExceptionKind exception, const char* classStr);\nvoid ThrowNullValueException(JNIEnv* env, const realm::TableRef table, realm::ColKey col_key);\n\n// Check parameters\n\n#define TABLE_VALID(env, ptr) TableIsValid(env, ptr)\n#define ROW_VALID(env, ptr) RowIsValid(env, ptr)\n\n#if CHECK_PARAMETERS\n\n#define TYPE_VALID(env, ptr, col, type) TypeValid(env, ptr, col, type)\n#define COL_NULLABLE(env, table_ref, columnKey) ColIsNullable(env, table_ref, columnKey)\n\n#else\n\n#define TYPE_VALID(env, ptr, col, type) (true)\n#define COL_NULLABLE(env, ptr, col) (true)\n\n#endif\n\n\n#if REALM_ENABLE_SYNC\n#include \"io_realm_internal_ErrorCategory.h\"\n#include <realm/object-store/sync/sync_manager.hpp>\n\ninline jbyte categoryAsJByte(const realm::Status &status) {\n    // See error code mapping to categories here:\n    // https://github.com/realm/realm-core/blob/master/src/realm/error_codes.cpp#L29\n    //\n    // In most cases, only 1 category is assigned, but some errors have multiple. However we only\n    // want to assign one category to each error (in order to preserve backwards compatibility)\n    //\n    // So we attempt to find the most \"important\" category to assign the error to. This is tricky,\n    // but generally we consider vague categories like\n    // `io_realm_internal_ErrorCategory_RLM_SYNC_ERROR_CATEGORY_RUNTIME` is\n    // less important than more specific ones like `io_realm_internal_ErrorCategory_RLM_APP_ERROR_CATEGORY_JSON`\n    //\n    // In the current implementation, categories between index 0 and 7 are considered equal\n    // and the order is somewhat arbitrary. No error codes has multiple of these categories\n    // associated either.\n    realm::ErrorCategory categories = realm::ErrorCodes::error_categories(status.code());\n    jbyte category = io_realm_internal_ErrorCategory_RLM_SYNC_ERROR_CATEGORY_UNKNOWN;\n    if (categories.test(realm::ErrorCategory::custom_error)) {\n        category = io_realm_internal_ErrorCategory_RLM_SYNC_ERROR_CATEGORY_CUSTOM;\n    } else if (categories.test(realm::ErrorCategory::websocket_error)) {\n        category = io_realm_internal_ErrorCategory_RLM_SYNC_ERROR_CATEGORY_WEBSOCKET;\n    } else if (categories.test(realm::ErrorCategory::sync_error)) {\n        category = io_realm_internal_ErrorCategory_RLM_SYNC_ERROR_CATEGORY_SYNC;\n    } else if (categories.test(realm::ErrorCategory::service_error)) {\n        category = io_realm_internal_ErrorCategory_RLM_SYNC_ERROR_CATEGORY_SERVICE;\n    } else if (categories.test(realm::ErrorCategory::json_error)) {\n        category = io_realm_internal_ErrorCategory_RLM_SYNC_ERROR_CATEGORY_JSON;\n    } else if (categories.test(realm::ErrorCategory::client_error)) {\n        category = io_realm_internal_ErrorCategory_RLM_SYNC_ERROR_CATEGORY_CLIENT;\n    } else if (categories.test(realm::ErrorCategory::system_error)) {\n        category = io_realm_internal_ErrorCategory_RLM_APP_ERROR_CATEGORY_SYSTEM;\n    } else if (categories.test(realm::ErrorCategory::file_access)) {\n        category = io_realm_internal_ErrorCategory_RLM_APP_ERROR_CATEGORY_FILE_ACCESS;\n    } else if (categories.test(realm::ErrorCategory::http_error)) {\n        category = io_realm_internal_ErrorCategory_RLM_SYNC_ERROR_CATEGORY_HTTP;\n    } else if (categories.test(realm::ErrorCategory::invalid_argument)) {\n        category = io_realm_internal_ErrorCategory_RLM_APP_ERROR_CATEGORY_INVALID_ARGUMENT;\n    } else if (categories.test(realm::ErrorCategory::app_error)) {\n        category = io_realm_internal_ErrorCategory_RLM_SYNC_ERROR_CATEGORY_APP;\n    } else if (categories.test(realm::ErrorCategory::logic_error)) {\n        category = io_realm_internal_ErrorCategory_RLM_APP_ERROR_CATEGORY_LOGIC;\n    } else if (categories.test(realm::ErrorCategory::runtime_error)) {\n        category = io_realm_internal_ErrorCategory_RLM_APP_ERROR_CATEGORY_RUNTIME;\n    }\n    return category;\n}\n\nextern realm::SyncClientConfig::LoggerFactory javaLoggerFactory;\n#endif\n\ninline jlong to_jlong_or_not_found(size_t res)\n{\n    return (res == realm::not_found) ? jlong(-1) : jlong(res);\n}\n\ninline jlong to_jlong_or_not_found(realm::ColKey key)\n{\n    return bool(key) ? jlong(key.value) : jlong(-1);\n}\n\ninline jlong to_jlong_or_not_found(realm::ObjKey key)\n{\n    return bool(key) ? jlong(key.value) : jlong(-1);\n}\n\ninline bool TableIsValid(JNIEnv* env, const realm::ConstTableRef table)\n{\n    if (!table) {\n        ThrowException(env, IllegalState, \"Table is no longer valid to operate on.\");\n    }\n    return true;\n}\n\ninline bool RowIsValid(JNIEnv* env, realm::Obj* rowPtr)\n{\n    bool valid = (rowPtr != NULL && rowPtr->is_valid());\n    if (!valid) {\n        ThrowException(env, IllegalState,\n                       \"Object is no longer valid to operate on. Was it deleted by another thread?\");\n    }\n    return valid;\n}\n\ntemplate <class T>\ninline bool TypeValid(JNIEnv* env, T* pTable, jlong columnKey, realm::ColumnType expectColType)\n{\n    realm::ColKey col_key(columnKey);\n    auto colType = col_key.get_type();\n    if (colType != expectColType) {\n        ThrowException(env, IllegalArgument, \"ColumnType of '\" + std::string(pTable->get_column_name(col_key)) + \"' is invalid.\");\n        return false;\n    }\n    return true;\n}\n\ninline bool TypeValid(JNIEnv* env, realm::ConstTableRef table, jlong columnKey, realm::ColumnType expectColType)\n{\n    realm::ColKey col_key(columnKey);\n    auto colType = col_key.get_type();\n    if (colType != expectColType) {\n        ThrowException(env, IllegalArgument, \"ColumnType of '\" + std::string(table->get_column_name(col_key)) + \"' is invalid.\");\n        return false;\n    }\n    return true;\n}\n\ntemplate <class T>\ninline bool ColIsNullable(JNIEnv* env, T table_ref, jlong columnKey)\n{\n    realm::ColKey col = realm::ColKey(columnKey);\n    realm::DataType colType = table_ref->get_column_type(col);\n    if (colType == realm::type_Link) {\n        return true;\n    }\n\n    if (colType == realm::type_LinkList) {\n        ThrowException(env, IllegalArgument, \"RealmList(\" + std::string(table_ref->get_column_name(col)) + \") is not nullable.\");\n        return false;\n    }\n\n    // checking for primitive list\n    if (table_ref->is_list(col)) {\n        ThrowException(env, IllegalArgument, \"RealmList(\" + std::string(table_ref->get_column_name(col)) + \") is not nullable.\");\n        return false;\n    }\n\n    if (table_ref->is_nullable(col)) {\n        return true;\n    }\n\n    ThrowException(env, IllegalArgument, \"This field(\" + std::string(table_ref->get_column_name(col)) + \") is not nullable.\");\n    return false;\n}\n\n// Utility function for appending StringData, which is returned\n// by a lot of core functions, and might potentially be NULL.\nstd::string concat_stringdata(const char* message, realm::StringData data);\n\n// Note: JNI offers methods to convert between modified UTF-8 and\n// UTF-16. Unfortunately these methods are not appropriate in this\n// context. The reason is that they use a modified version of\n// UTF-8 where U+0000 is stored as 0xC0 0x80 instead of 0x00 and\n// where a character in the range U+10000 to U+10FFFF is stored as\n// two consecutive UTF-8 encodings of the corresponding UTF-16\n// surrogate pair. Because Realm uses proper UTF-8, we need to\n// do the transcoding ourselves.\n//\n// See also http://en.wikipedia.org/wiki/UTF-8#Modified_UTF-8\n\njstring to_jstring(JNIEnv*, realm::StringData);\n\nclass JStringAccessor {\npublic:\n    JStringAccessor(JNIEnv* env, jstring s) : JStringAccessor(env, s, false) {}; // throws\n    JStringAccessor(JNIEnv*, jstring, bool); // throws\n\n    bool is_null_or_empty() {\n        return m_is_null || m_size == 0;\n    }\n\n    bool is_null() {\n        return m_is_null;\n    }\n\n    operator realm::StringData() const\n    {\n        // To solve the link issue by directly using Table::max_string_size\n        static constexpr size_t max_string_size = realm::Table::max_string_size;\n\n        if (m_is_null) {\n            return realm::StringData();\n        }\n        else if (m_size > max_string_size) {\n            THROW_JAVA_EXCEPTION(\n                m_env, realm::_impl::JavaExceptionDef::IllegalArgument,\n                realm::util::format(\n                    \"The length of 'String' value in UTF8 encoding is %1 which exceeds the max string length %2.\",\n                    m_size, max_string_size));\n        }\n        else {\n            return realm::StringData(m_data.get(), m_size);\n        }\n    }\n\n    operator std::string() const noexcept\n    {\n        if (m_is_null) {\n            return std::string();\n        }\n        return std::string(m_data.get(), m_size);\n    }\n\n    operator std::string_view() const noexcept\n    {\n        if (m_is_null) {\n            return std::string_view();\n        }\n        return std::string_view(m_data.get(), m_size);\n    }\n\n\nprivate:\n    JNIEnv* m_env;\n    bool m_is_null;\n    std::shared_ptr<char> m_data;\n    std::size_t m_size;\n};\n\ninline jlong to_milliseconds(const realm::Timestamp& ts)\n{\n    const int64_t seconds = ts.get_seconds();\n    const int32_t nanoseconds = ts.get_nanoseconds();\n    int64_t result_ms = seconds;\n\n    // Convert seconds to milliseconds.\n    // Clamp to MAX/MIN in case of overflow/underflow.\n    int64_t sec_min_limit = MIN_JLONG/1000LL;\n    int64_t sec_max_limit = MAX_JLONG/1000LL;\n    if (seconds < 0 && sec_min_limit > seconds) {\n        return static_cast<jlong>(MIN_JLONG);\n    } else if (seconds > 0 && sec_max_limit < seconds) {\n        return static_cast<jlong>(MAX_JLONG);\n    } else {\n        result_ms = seconds * 1000; // Here it is safe to convert to milliseconds\n    }\n\n    // Convert nanoseconds to milliseconds and add to final result.\n    // Clamp to MAX/MIN in case of the result overflowing/underflowing.\n    if (realm::util::int_add_with_overflow_detect(result_ms, nanoseconds / 1000000)) {\n        // The nanoseconds part is at max 1 sec. which means that if overflow/underflow\n        // is detected we can infer the direction from `result_ms` since we must be close\n        // to the limit boundary.\n        return static_cast<jlong>((result_ms < 0) ? MIN_JLONG : MAX_JLONG);\n    }\n\n    return static_cast<jlong>(result_ms);\n}\n\ninline realm::Timestamp from_milliseconds(jlong milliseconds)\n{\n    // From core's reference implementation aka unit test\n    int64_t seconds = milliseconds / 1000;\n    int32_t nanoseconds = (milliseconds % 1000) * 1000000;\n    return realm::Timestamp(seconds, nanoseconds);\n}\n\nextern const std::string TABLE_PREFIX;\n\nstatic inline bool to_bool(jboolean b)\n{\n    return b == JNI_TRUE;\n}\n\nstatic inline jboolean to_jbool(bool b)\n{\n    return b ? JNI_TRUE : JNI_FALSE;\n}\n\n#endif // REALM_JAVA_UTIL_HPP\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/BaseRealm.java",
    "content": "/*\n * Copyright 2015 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\npackage io.realm;\n\nimport android.content.Context;\nimport android.os.Looper;\n\nimport java.io.Closeable;\nimport java.io.File;\nimport java.io.FileNotFoundException;\nimport java.util.Collections;\nimport java.util.List;\nimport java.util.concurrent.atomic.AtomicBoolean;\n\nimport javax.annotation.Nullable;\n\nimport io.reactivex.Flowable;\nimport io.realm.exceptions.RealmException;\nimport io.realm.exceptions.RealmFileException;\nimport io.realm.exceptions.RealmMigrationNeededException;\nimport io.realm.internal.CheckedRow;\nimport io.realm.internal.ColumnInfo;\nimport io.realm.internal.InvalidRow;\nimport io.realm.internal.OsObjectStore;\nimport io.realm.internal.OsRealmConfig;\nimport io.realm.internal.OsSchemaInfo;\nimport io.realm.internal.OsSharedRealm;\nimport io.realm.internal.RealmObjectProxy;\nimport io.realm.internal.RealmProxyMediator;\nimport io.realm.internal.Row;\nimport io.realm.internal.Table;\nimport io.realm.internal.UncheckedRow;\nimport io.realm.internal.Util;\nimport io.realm.internal.annotations.ObjectServer;\nimport io.realm.internal.async.RealmThreadPoolExecutor;\nimport io.realm.log.RealmLog;\n\n/**\n * Base class for all Realm instances.\n *\n * @see io.realm.Realm\n * @see io.realm.DynamicRealm\n */\n@SuppressWarnings(\"WeakerAccess\")\nabstract class BaseRealm implements Closeable {\n    private static final String INCORRECT_THREAD_CLOSE_MESSAGE =\n            \"Realm access from incorrect thread. Realm instance can only be closed on the thread it was created.\";\n    static final String INCORRECT_THREAD_MESSAGE =\n            \"Realm access from incorrect thread. Realm objects can only be accessed on the thread they were created.\";\n    static final String CLOSED_REALM_MESSAGE =\n            \"This Realm instance has already been closed, making it unusable.\";\n    private static final String NOT_IN_TRANSACTION_MESSAGE =\n            \"Changing Realm data can only be done from inside a transaction.\";\n    static final String LISTENER_NOT_ALLOWED_MESSAGE =\n            \"Listeners cannot be used on current thread.\";\n    static final String DELETE_NOT_SUPPORTED_UNDER_PARTIAL_SYNC =\n            \"This API is not supported by partially \" +\n            \"synchronized Realms. Either unsubscribe using 'Realm.unsubscribeAsync()' or \" +\n            \"delete the objects using a query and 'RealmResults.deleteAllFromRealm()'\";\n\n    static volatile Context applicationContext;\n\n    // Thread pool for all async operations (Query & transaction)\n    static final RealmThreadPoolExecutor asyncTaskExecutor = RealmThreadPoolExecutor.newDefaultExecutor();\n\n    /**\n     * Thread pool executor used for write operations - only one thread is needed as writes cannot\n     * be parallelized.\n     */\n    public static final RealmThreadPoolExecutor WRITE_EXECUTOR = RealmThreadPoolExecutor.newSingleThreadExecutor();\n\n    final boolean frozen; // Cache the value in Java, since it is accessed frequently and doesn't change.\n    final long threadId;\n    protected final RealmConfiguration configuration;\n    // Which RealmCache is this Realm associated to. It is null if the Realm instance is opened without being put into a\n    // cache. It is also null if the Realm is closed.\n    private RealmCache realmCache;\n    public OsSharedRealm sharedRealm;\n    private boolean shouldCloseSharedRealm;\n    private OsSharedRealm.SchemaChangedCallback schemaChangedCallback = new OsSharedRealm.SchemaChangedCallback() {\n        @Override\n        public void onSchemaChanged() {\n            RealmSchema schema = getSchema();\n            if (schema != null) {\n                schema.refresh();\n            }\n            if (BaseRealm.this instanceof Realm) {\n                schema.createKeyPathMapping();\n            }\n        }\n    };\n\n    // Create a realm instance and associate it to a RealmCache.\n    BaseRealm(RealmCache cache, @Nullable OsSchemaInfo schemaInfo, OsSharedRealm.VersionID version) {\n        this(cache.getConfiguration(), schemaInfo, version);\n        this.realmCache = cache;\n    }\n\n    // Create a realm instance without associating it to any RealmCache.\n    BaseRealm(final RealmConfiguration configuration, @Nullable OsSchemaInfo schemaInfo, OsSharedRealm.VersionID version) {\n        this.threadId = Thread.currentThread().getId();\n        this.configuration = configuration;\n        this.realmCache = null;\n\n        OsSharedRealm.MigrationCallback migrationCallback = null;\n        if (schemaInfo != null && configuration.getMigration() != null) {\n            migrationCallback = createMigrationCallback(configuration.getMigration());\n        }\n\n        OsSharedRealm.InitializationCallback initializationCallback = null;\n        final Realm.Transaction initialDataTransaction = configuration.getInitialDataTransaction();\n        if (initialDataTransaction != null) {\n            initializationCallback = new OsSharedRealm.InitializationCallback() {\n                @Override\n                public void onInit(OsSharedRealm sharedRealm) {\n                    Realm instance = Realm.createInstance(sharedRealm);\n                    initialDataTransaction.execute(instance);\n                }\n            };\n        }\n\n        OsRealmConfig.Builder configBuilder = new OsRealmConfig.Builder(configuration)\n                .fifoFallbackDir(new File(BaseRealm.applicationContext.getFilesDir(), \".realm.temp\"))\n                .autoUpdateNotification(true)\n                .migrationCallback(migrationCallback)\n                .schemaInfo(schemaInfo)\n                .initializationCallback(initializationCallback);\n        this.sharedRealm = OsSharedRealm.getInstance(configBuilder, version);\n        this.frozen = sharedRealm.isFrozen();\n        this.shouldCloseSharedRealm = true;\n        sharedRealm.registerSchemaChangedCallback(schemaChangedCallback);\n    }\n\n    // Create a realm instance directly from a OsSharedRealm instance. This instance doesn't have the ownership of the\n    // given OsSharedRealm instance. The OsSharedRealm instance should not be closed when close() called.\n    BaseRealm(OsSharedRealm sharedRealm) {\n        this.threadId = Thread.currentThread().getId();\n        this.configuration = sharedRealm.getConfiguration();\n        this.realmCache = null;\n\n        this.sharedRealm = sharedRealm;\n        this.frozen = sharedRealm.isFrozen();\n        this.shouldCloseSharedRealm = false;\n    }\n\n   /**\n     * Sets the auto-refresh status of the Realm instance.\n     * <p>\n     * Auto-refresh is a feature that enables automatic update of the current Realm instance and all its derived objects\n     * (RealmResults and RealmObject instances) when a commit is performed on a Realm acting on the same file in\n     * another thread. This feature is only available if the Realm instance lives on an {@link android.os.Looper}\n     * enabled thread.\n     *\n     * @param autoRefresh {@code true} will turn auto-refresh on, {@code false} will turn it off.\n     * @throws IllegalStateException if called from a non-Looper thread.\n     */\n    public void setAutoRefresh(boolean autoRefresh) {\n        checkIfValid();\n        sharedRealm.setAutoRefresh(autoRefresh);\n    }\n\n    /**\n     * Retrieves the auto-refresh status of the Realm instance.\n     *\n     * @return the auto-refresh status.\n     */\n    public boolean isAutoRefresh() {\n        return sharedRealm.isAutoRefresh();\n    }\n\n    /**\n     * Refreshes the Realm instance and all the RealmResults and RealmObjects instances coming from it.\n     * It also calls any listeners associated with the Realm if needed.\n     * <p>\n     * WARNING: Calling this on a thread with async queries will turn those queries into synchronous queries.\n     * This means this method will throw a {@link RealmException} if\n     * {@link RealmConfiguration.Builder#allowQueriesOnUiThread(boolean)} was used with {@code true} to\n     * obtain a Realm instance. In most cases it is better to use {@link RealmChangeListener}s to be notified\n     * about changes to the Realm on a given thread than it is to use this method.\n     *\n     * @throws IllegalStateException if attempting to refresh from within a transaction.\n     * @throws RealmException if called from the UI thread after opting out via {@link RealmConfiguration.Builder#allowQueriesOnUiThread(boolean)}.\n     */\n    public void refresh() {\n        checkIfValid();\n        checkAllowQueriesOnUiThread();\n\n        if (isInTransaction()) {\n            throw new IllegalStateException(\"Cannot refresh a Realm instance inside a transaction.\");\n        }\n        sharedRealm.refresh();\n    }\n\n    /**\n     * Checks if the Realm is currently in a transaction.\n     *\n     * @return {@code true} if inside a transaction, {@code false} otherwise.\n     */\n    public boolean isInTransaction() {\n        checkIfValid();\n        return sharedRealm.isInTransaction();\n    }\n\n    protected <T extends BaseRealm> void addListener(RealmChangeListener<T> listener) {\n        //noinspection ConstantConditions\n        if (listener == null) {\n            throw new IllegalArgumentException(\"Listener should not be null\");\n        }\n        checkIfValid();\n        sharedRealm.capabilities.checkCanDeliverNotification(LISTENER_NOT_ALLOWED_MESSAGE);\n        if (frozen) {\n            throw new IllegalStateException(\"It is not possible to add a change listener to a frozen Realm since it never changes.\");\n        }\n        //noinspection unchecked\n        sharedRealm.realmNotifier.addChangeListener((T) this, listener);\n    }\n\n    /**\n     * Removes the specified change listener.\n     *\n     * @param listener the change listener to be removed.\n     * @throws IllegalArgumentException if the change listener is {@code null}.\n     * @throws IllegalStateException if you try to remove a listener from a non-Looper Thread.\n     * @see io.realm.RealmChangeListener\n     */\n    protected <T extends BaseRealm> void removeListener(RealmChangeListener<T> listener) {\n        //noinspection ConstantConditions\n        if (listener == null) {\n            throw new IllegalArgumentException(\"Listener should not be null\");\n        }\n        if (isClosed()) {\n            RealmLog.warn(\"Calling removeChangeListener on a closed Realm %s, \" +\n                    \"make sure to close all listeners before closing the Realm.\", configuration.getPath());\n        }\n        //noinspection unchecked\n        sharedRealm.realmNotifier.removeChangeListener((T) this, listener);\n    }\n\n    /**\n     * Returns an RxJava Flowable that monitors changes to this Realm. It will emit the current state\n     * when subscribed to. Items will continually be emitted as the Realm is updated -\n     * {@code onComplete} will never be called.\n     * <p>\n     * Items emitted from Realm Flowables are frozen (See {@link #freeze()}. This means that they\n     * are immutable and can be read on any thread.\n     * <p>\n     * Realm Flowables always emit items from the thread holding the live Realm. This means that if\n     * you need to do further processing, it is recommend to observe the values on a computation\n     * scheduler:\n     * <p>\n     * {@code\n     * realm.asFlowable()\n     *   .observeOn(Schedulers.computation())\n     *   .map(rxRealm -> doExpensiveWork(rxRealm))\n     *   .observeOn(AndroidSchedulers.mainThread())\n     *   .subscribe( ... );\n     * }\n     * <p>\n     * If you would like the {@code asFlowable()} to stop emitting items, you can instruct RxJava to\n     * only emit only the first item by using the {@code first()} operator:\n     * <p>\n     * <pre>\n     * {@code\n     * realm.asFlowable().first().subscribe( ... ); // You only get the results once\n     * }\n     * </pre>\n     *\n     * @return RxJava Observable that only calls {@code onNext}. It will never call {@code onComplete} or {@code OnError}.\n     * @throws UnsupportedOperationException if the required RxJava framework is not on the classpath.\n     * @throws IllegalStateException if the Realm wasn't opened on a Looper thread.\n     * @see <a href=\"https://github.com/realm/realm-java/tree/master/examples/rxJavaExample\">RxJava and Realm</a>\n     */\n    public abstract Flowable asFlowable();\n\n    /**\n     * Removes all user-defined change listeners.\n     *\n     * @throws IllegalStateException if you try to remove listeners from a non-Looper Thread.\n     * @see io.realm.RealmChangeListener\n     */\n    protected void removeAllListeners() {\n        if (isClosed()) {\n            RealmLog.warn(\"Calling removeChangeListener on a closed Realm %s, \" +\n                    \"make sure to close all listeners before closing the Realm.\", configuration.getPath());\n        }\n        sharedRealm.realmNotifier.removeChangeListeners(this);\n    }\n\n    /**\n     * Writes a compacted copy of the Realm to the given destination File. The resulting file can be\n     * used as initial dataset to bootstrap a local or synced Realm in other devices.\n     * <p>\n     * The destination file cannot already exist.\n     * <p>\n     * Note that if this is called from within a transaction it writes the current data, and not the data as it was when\n     * the last transaction was committed.\n     *\n     * @param destination file to save the Realm to.\n     * @throws IllegalArgumentException if destination argument is null.\n     * @throws RealmFileException if an error happened when accessing the underlying Realm file or writing to the\n     * destination file.\n     * @throws IllegalStateException if called from the UI thread.\n     * @throws IllegalStateException if not all client changes are integrated in server.\n     */\n    public void writeCopyTo(File destination) {\n        //noinspection ConstantConditions\n        if (destination == null) {\n            throw new IllegalArgumentException(\"The destination argument cannot be null\");\n        }\n        checkIfValid();\n        sharedRealm.writeCopy(destination, null);\n    }\n\n    /**\n     * Writes a compacted and encrypted copy of the Realm to the given destination File. The\n     * resulting file can be used as initial dataset to bootstrap a local or synced Realm in other\n     * devices.\n     * <p>\n     * The destination file cannot already exist.\n     * <p>\n     * Note that if this is called from within a transaction it writes the current data, and not the data as it was when\n     * the last transaction was committed.\n     * <p>\n     *\n     * @param destination file to save the Realm to.\n     * @param key a 64-byte encryption key.\n     * @throws IllegalArgumentException if destination argument is null.\n     * @throws RealmFileException if an error happened when accessing the underlying Realm file or writing to the\n     * destination file.\n     * @throws IllegalStateException if called from the UI thread.\n     * @throws IllegalStateException if not all client changes are integrated in server.\n     */\n    public void writeEncryptedCopyTo(File destination, byte[] key) {\n        //noinspection ConstantConditions\n        if (destination == null) {\n            throw new IllegalArgumentException(\"The destination argument cannot be null\");\n        }\n        checkIfValid();\n        sharedRealm.writeCopy(destination, key);\n    }\n\n    /**\n     * Blocks the current thread until new changes to the Realm are available or {@link #stopWaitForChange()}\n     * is called from another thread. Once stopWaitForChange is called, all future calls to this method will\n     * return false immediately.\n     *\n     * @return {@code true} if the Realm was updated to the latest version, {@code false} if it was\n     * cancelled by calling stopWaitForChange.\n     * @throws IllegalStateException if calling this from within a transaction or from a Looper thread.\n     * @throws RealmMigrationNeededException on typed {@link Realm} if the latest version contains\n     * incompatible schema changes.\n     * @deprecated this method will be removed on the next-major release.\n     */\n    @Deprecated\n    public boolean waitForChange() {\n        checkIfValid();\n        if (isInTransaction()) {\n            throw new IllegalStateException(\"Cannot wait for changes inside of a transaction.\");\n        }\n        if (Looper.myLooper() != null) {\n            throw new IllegalStateException(\"Cannot wait for changes inside a Looper thread. Use RealmChangeListeners instead.\");\n        }\n        boolean hasChanged = sharedRealm.waitForChange();\n        if (hasChanged) {\n            // Since this Realm instance has been waiting for change, advance realm & refresh realm.\n            sharedRealm.refresh();\n        }\n        return hasChanged;\n    }\n\n    /**\n     * Makes any current {@link #waitForChange()} return {@code false} immediately. Once this is called,\n     * all future calls to waitForChange will immediately return {@code false}.\n     * <p>\n     * This method is thread-safe and should _only_ be called from another thread than the one that\n     * called waitForChange.\n     *\n     * @throws IllegalStateException if the {@link io.realm.Realm} instance has already been closed.\n     * @deprecated this method will be removed in the next-major release\n     */\n    @Deprecated\n    public void stopWaitForChange() {\n        if (realmCache != null) {\n            realmCache.invokeWithLock(new RealmCache.Callback0() {\n                @Override\n                public void onCall() {\n                    // Checks if the Realm instance has been closed.\n                    if (sharedRealm == null || sharedRealm.isClosed()) {\n                        throw new IllegalStateException(BaseRealm.CLOSED_REALM_MESSAGE);\n                    }\n                    sharedRealm.stopWaitForChange();\n                }\n            });\n        } else {\n            throw new IllegalStateException(BaseRealm.CLOSED_REALM_MESSAGE);\n        }\n    }\n\n    /**\n     * Starts a transaction which must be closed by {@link io.realm.Realm#commitTransaction()} or aborted by\n     * {@link io.realm.Realm#cancelTransaction()}. Transactions are used to atomically create, update and delete objects\n     * within a Realm.\n     * <p>\n     * Before beginning a transaction, the Realm instance is updated to the latest version in order to include all\n     * changes from other threads. This update does not trigger any registered {@link RealmChangeListener}.\n     * <p>\n     * It is therefore recommended to query for the items that should be modified from inside the transaction. Otherwise\n     * there is a risk that some of the results have been deleted or modified when the transaction begins.\n     * <p>\n     * <pre>\n     * {@code\n     * // Don't do this\n     * RealmResults<Person> persons = realm.where(Person.class).findAll();\n     * realm.beginTransaction();\n     * persons.first().setName(\"John\");\n     * realm.commitTransaction();\n     *\n     * // Do this instead\n     * realm.beginTransaction();\n     * RealmResults<Person> persons = realm.where(Person.class).findAll();\n     * persons.first().setName(\"John\");\n     * realm.commitTransaction();\n     * }\n     * </pre>\n     * <p>\n     * Notice: it is not possible to nest transactions. If you start a transaction within a transaction an exception is\n     * thrown.\n     *\n     * @throws RealmMigrationNeededException on typed {@link Realm} if the latest version contains\n     * incompatible schema changes.\n     */\n    public void beginTransaction() {\n        checkIfValid();\n        sharedRealm.beginTransaction();\n    }\n\n    /**\n     * All changes since {@link io.realm.Realm#beginTransaction()} are persisted to disk and the Realm reverts back to\n     * being read-only. An event is sent to notify all other Realm instances that a change has occurred. When the event\n     * is received, the other Realms will update their objects and {@link io.realm.RealmResults} to reflect the\n     * changes from this commit.\n     */\n    public void commitTransaction() {\n        checkIfValid();\n        sharedRealm.commitTransaction();\n    }\n\n    /**\n     * Reverts all writes (created, updated, or deleted objects) made in the current write transaction and end the\n     * transaction.\n     * <p>\n     * The Realm reverts back to read-only.\n     * <p>\n     * Calling this when not in a transaction will throw an exception.\n     */\n    public void cancelTransaction() {\n        checkIfValid();\n        sharedRealm.cancelTransaction();\n    }\n\n    /**\n     * Returns a frozen snapshot of the current Realm. This Realm can be read and queried from any thread without throwing\n     * an {@link IllegalStateException}. A frozen Realm has its own lifecycle and can be closed by calling {@link #close()},\n     * but fully closing the Realm that spawned the frozen copy will also close the frozen Realm.\n     * <p>\n     * Frozen data can be queried as normal, but trying to mutate it in any way or attempting to register any listener will\n     * throw an {@link IllegalStateException}.\n     * <p>\n     * Note: Keeping a large number of Realms with different versions alive can have a negative impact on the filesize\n     * of the Realm. In order to avoid such a situation, it is possible to set {@link RealmConfiguration.Builder#maxNumberOfActiveVersions(long)}.\n     *\n     * @return a frozen copy of this Realm.\n     * @throws IllegalStateException if this method is called from inside a write transaction.\n     */\n    public abstract BaseRealm freeze();\n\n    /**\n     * Returns whether or not this Realm is frozen.\n     *\n     * @return {@code true} if the Realm is frozen, {@code false} if it is not.\n     * @see #freeze()\n     */\n    public boolean isFrozen() {\n        // This method needs to be threadsafe even for live Realms, so don't call {@link #checkIfValid}\n        if (sharedRealm == null || sharedRealm.isClosed()) {\n            throw new IllegalStateException(BaseRealm.CLOSED_REALM_MESSAGE);\n        }\n        return frozen;\n    }\n\n    /**\n     * Returns the current number of active versions currently being held by this Realm.\n     * <p>\n     * Having a large number of active versions have a negative impact on the size of the\n     * Realm file. See <a href=\"https://docs.mongodb.com/realm/sdk/android/fundamentals/realms/#realm-file-size\">the FAQ</a>\n     * for more information.\n     *\n     * @return number of active versions currently being held by the Realm.\n     * @see RealmConfiguration.Builder#maxNumberOfActiveVersions(long)\n     */\n    public long getNumberOfActiveVersions() {\n        checkIfValid();\n        return getSharedRealm().getNumberOfVersions();\n    }\n\n    /**\n     * Checks if a Realm's underlying resources are still available or not getting accessed from the wrong thread.\n     */\n    protected void checkIfValid() {\n        if (sharedRealm == null || sharedRealm.isClosed()) {\n            throw new IllegalStateException(BaseRealm.CLOSED_REALM_MESSAGE);\n        }\n\n        // Checks if we are in the right thread.\n        if (!frozen && threadId != Thread.currentThread().getId()) {\n            throw new IllegalStateException(BaseRealm.INCORRECT_THREAD_MESSAGE);\n        }\n    }\n\n    /**\n     * Checks whether queries are allowed from the UI thread in the current RealmConfiguration.\n     */\n    protected void checkAllowQueriesOnUiThread() {\n        // Warn on query being executed on UI thread if isAllowQueriesOnUiThread is set to true, throw otherwise\n        if (getSharedRealm().capabilities.isMainThread()) {\n            if (!getConfiguration().isAllowQueriesOnUiThread()) {\n                throw new RealmException(\"Queries on the UI thread have been disabled. They can be enabled by setting 'RealmConfiguration.Builder.allowQueriesOnUiThread(true)'.\");\n            }\n        }\n    }\n\n    /**\n     * Checks whether writes are allowed from the UI thread in the current RealmConfiguration.\n     */\n    protected void checkAllowWritesOnUiThread() {\n        // Warn on transaction being executed on UI thread if allowWritesOnUiThread is set to true, throw otherwise\n        if (getSharedRealm().capabilities.isMainThread()) {\n            if (!getConfiguration().isAllowWritesOnUiThread()) {\n                throw new RealmException(\"Running transactions on the UI thread has been disabled. It can be enabled by setting 'RealmConfiguration.Builder.allowWritesOnUiThread(true)'.\");\n            }\n        }\n    }\n\n    protected void checkIfInTransaction() {\n        if (!sharedRealm.isInTransaction()) {\n            throw new IllegalStateException(\"Changing Realm data can only be done from inside a transaction.\");\n        }\n    }\n\n    /**\n     * Checks if the Realm is valid and in a transaction.\n     */\n    protected void checkIfValidAndInTransaction() {\n        if (!isInTransaction()) {\n            throw new IllegalStateException(NOT_IN_TRANSACTION_MESSAGE);\n        }\n    }\n\n    /**\n     * Creates a row representing an embedded object - for internal use only.\n     *\n     * @param className the class name of the object to create.\n     * @param parentProxy The parent object which should hold a reference to the embedded object.\n     * @param parentProperty the property in the parent class which holds the reference.\n     * @param schema the Realm schema from which to obtain table information.\n     * @param parentObjectSchema the parent object schema from which to obtain property information.\n     * @return the row representing the newly created embedded object.\n     * @throws IllegalArgumentException if any embedded object invariants are broken.\n     */\n    Row getEmbeddedObjectRow(final String className,\n                             final RealmObjectProxy parentProxy,\n                             final String parentProperty,\n                             final RealmSchema schema,\n                             final RealmObjectSchema parentObjectSchema) {\n        final long parentPropertyColKey = parentObjectSchema.getColumnKey(parentProperty);\n        final RealmFieldType parentPropertyType = parentObjectSchema.getFieldType(parentProperty);\n        final Row row = parentProxy.realmGet$proxyState().getRow$realm();\n        final RealmFieldType fieldType = parentObjectSchema.getFieldType(parentProperty);\n        boolean propertyAcceptable = parentObjectSchema.isPropertyAcceptableForEmbeddedObject(fieldType);\n        if (!propertyAcceptable) {\n            throw new IllegalArgumentException(String.format(\"Field '%s' does not contain a valid link\", parentProperty));\n        }\n        final String linkedType = parentObjectSchema.getPropertyClassName(parentProperty);\n\n        // By now linkedType can only be either OBJECT or LIST, so no exhaustive check needed\n        Row embeddedObject;\n        if (linkedType.equals(className)) {\n            long objKey = row.createEmbeddedObject(parentPropertyColKey, parentPropertyType);\n            embeddedObject = schema.getTable(className).getCheckedRow(objKey);\n        } else {\n            throw new IllegalArgumentException(String.format(\"Parent type %s expects that property '%s' be of type %s but was %s.\", parentObjectSchema.getClassName(), parentProperty, linkedType, className));\n        }\n\n        return embeddedObject;\n    }\n\n    /**\n     * Checks if the Realm is not built with a SyncRealmConfiguration.\n     */\n    void checkNotInSync() {\n        if (configuration.isSyncConfiguration()) {\n            throw new UnsupportedOperationException(\"You cannot perform destructive changes to a schema of a synced Realm\");\n        }\n    }\n\n    /**\n     * Returns the canonical path to where this Realm is persisted on disk.\n     *\n     * @return the canonical path to the Realm file.\n     * @see File#getCanonicalPath()\n     */\n    public String getPath() {\n        return configuration.getPath();\n    }\n\n    /**\n     * Returns the {@link RealmConfiguration} for this Realm.\n     *\n     * @return the {@link RealmConfiguration} for this Realm.\n     */\n    public RealmConfiguration getConfiguration() {\n        return configuration;\n    }\n\n    /**\n     * Returns the schema version for this Realm.\n     *\n     * @return the schema version for the Realm file backing this Realm.\n     */\n    public long getVersion() {\n        return OsObjectStore.getSchemaVersion(sharedRealm);\n    }\n\n    /**\n     * Closes the Realm instance and all its resources.\n     * <p>\n     * It's important to always remember to close Realm instances when you're done with it in order not to leak memory,\n     * file descriptors or grow the size of Realm file out of measure.\n     *\n     * @throws IllegalStateException if attempting to close from another thread.\n     */\n    @Override\n    public void close() {\n        if (!frozen && this.threadId != Thread.currentThread().getId()) {\n            throw new IllegalStateException(INCORRECT_THREAD_CLOSE_MESSAGE);\n        }\n\n        if (realmCache != null) {\n            realmCache.release(this);\n        } else {\n            doClose();\n        }\n    }\n\n    /**\n     * Closes the Realm instances and all its resources without checking the {@link RealmCache}.\n     */\n    void doClose() {\n        realmCache = null;\n        if (sharedRealm != null && shouldCloseSharedRealm) {\n            sharedRealm.close();\n            sharedRealm = null;\n        }\n    }\n\n    /**\n     * Checks if the {@link io.realm.Realm} instance has already been closed.\n     *\n     * @return {@code true} if closed, {@code false} otherwise.\n     * @throws IllegalStateException if attempting to close from another thread.\n     */\n    public boolean isClosed() {\n        if (!frozen && this.threadId != Thread.currentThread().getId()) {\n            throw new IllegalStateException(INCORRECT_THREAD_MESSAGE);\n        }\n\n        return sharedRealm == null || sharedRealm.isClosed();\n    }\n\n    /**\n     * Checks if this {@link io.realm.Realm} contains any objects.\n     *\n     * @return {@code true} if empty, @{code false} otherwise.\n     */\n    public abstract boolean isEmpty();\n\n    /**\n     * Returns the schema for this Realm.\n     *\n     * @return The {@link RealmSchema} for this Realm.\n     */\n    public abstract RealmSchema getSchema();\n\n    /**\n     * Returns the subscription set associated with this Realm. The subscription set defines\n     * a set of queries that define which data is synchronized between this realm and the server.\n     * <p>\n     * This method is only applicable to synchronized realms using flexible sync.\n     *\n     * @return the subscription set associated with this realm.\n     * @throws IllegalStateException if this realm is either a local realm or a partion-based\n     * synchronized realm.\n     */\n    @ObjectServer\n    public io.realm.mongodb.sync.SubscriptionSet getSubscriptions() {\n        checkIfValid();\n        return sharedRealm.getSubscriptions(configuration.getSchemaMediator(), asyncTaskExecutor, WRITE_EXECUTOR);\n    }\n\n    // Used by RealmList/RealmResults, to create RealmObject from a OsResults.\n    // Invariant: if dynamicClassName != null -> clazz == DynamicRealmObject\n    <E extends RealmModel> E get(@Nullable Class<E> clazz, @Nullable String dynamicClassName, UncheckedRow row) {\n        final boolean isDynamicRealmObject = dynamicClassName != null;\n\n        E result;\n        if (isDynamicRealmObject) {\n            //noinspection unchecked\n            result = (E) new DynamicRealmObject(this, CheckedRow.getFromRow(row));\n        } else {\n            // 'clazz' is non-null when 'dynamicClassName' is null.\n            //noinspection ConstantConditions\n            result = configuration.getSchemaMediator().newInstance(clazz, this, row, getSchema().getColumnInfo(clazz),\n                    false, Collections.<String>emptyList());\n        }\n        return result;\n    }\n\n    <E extends RealmModel> E get(Class<E> clazz, long rowKey, boolean acceptDefaultValue, List<String> excludeFields) {\n        Table table = getSchema().getTable(clazz);\n        UncheckedRow row = table.getUncheckedRow(rowKey);\n        return configuration.getSchemaMediator().newInstance(clazz, this, row, getSchema().getColumnInfo(clazz),\n                acceptDefaultValue, excludeFields);\n    }\n\n    // Used by RealmList/RealmResults\n    // Invariant: if dynamicClassName != null -> clazz == DynamicRealmObject\n    // TODO: Remove this after RealmList is backed by OS Results.\n    <E extends RealmModel> E get(@Nullable Class<E> clazz, @Nullable String dynamicClassName, long rowIndex) {\n        final boolean isDynamicRealmObject = dynamicClassName != null;\n        // 'clazz' is non-null when 'dynamicClassName' is null.\n        //noinspection ConstantConditions\n        final Table table = isDynamicRealmObject ? getSchema().getTable(dynamicClassName) : getSchema().getTable(clazz);\n\n        E result;\n        if (isDynamicRealmObject) {\n            @SuppressWarnings(\"unchecked\")\n            E dynamicObj = (E) new DynamicRealmObject(this,\n                    (rowIndex != Table.NO_MATCH) ? table.getCheckedRow(rowIndex) : InvalidRow.INSTANCE);\n            result = dynamicObj;\n        } else {\n            result = configuration.getSchemaMediator().newInstance(clazz, this,\n                    (rowIndex != Table.NO_MATCH) ? table.getUncheckedRow(rowIndex) : InvalidRow.INSTANCE,\n                    getSchema().getColumnInfo(clazz), false, Collections.<String>emptyList());\n        }\n\n        return result;\n    }\n\n    /**\n     * Deletes all objects from this Realm.\n     *\n     * @throws IllegalStateException if the Realm is closed or called from an incorrect thread.\n     */\n    public void deleteAll() {\n        checkIfValid();\n        for (RealmObjectSchema objectSchema : getSchema().getAll()) {\n            getSchema().getTable(objectSchema.getClassName()).clear();\n        }\n    }\n\n    /**\n     * Deletes the Realm file defined by the given configuration.\n     */\n    static boolean deleteRealm(final RealmConfiguration configuration) {\n        final AtomicBoolean realmDeleted = new AtomicBoolean(true);\n        boolean callbackExecuted = OsObjectStore.callWithLock(configuration, new Runnable() {\n            @Override\n            public void run() {\n                String canonicalPath = configuration.getPath();\n                File realmFolder = configuration.getRealmDirectory();\n                String realmFileName = configuration.getRealmFileName();\n                realmDeleted.set(Util.deleteRealm(canonicalPath, realmFolder, realmFileName));\n            }\n        });\n        if (!callbackExecuted) {\n            throw new IllegalStateException(\"It's not allowed to delete the file associated with an open Realm. \" +\n                    \"Remember to close() all the instances of the Realm before deleting its file: \"\n                    + configuration.getPath());\n        }\n        return realmDeleted.get();\n    }\n\n    /**\n     * Compacts the Realm file defined by the given configuration.\n     *\n     * @param configuration configuration for the Realm to compact.\n     * @return {@code true} if compaction succeeded, {@code false} otherwise.\n     */\n    static boolean compactRealm(final RealmConfiguration configuration) {\n        OsSharedRealm sharedRealm = OsSharedRealm.getInstance(configuration, OsSharedRealm.VersionID.LIVE);\n        Boolean result = sharedRealm.compact();\n        sharedRealm.close();\n        return result;\n    }\n\n    /**\n     * Migrates the Realm file defined by the given configuration using the provided migration block.\n     *\n     * @param configuration configuration for the Realm that should be migrated. If this is a SyncConfiguration this\n     * method does nothing.\n     * @param migration if set, this migration block will override what is set in {@link RealmConfiguration}.\n     * @throws FileNotFoundException if the Realm file doesn't exist.\n     * @throws IllegalArgumentException if the provided configuration is a {@code SyncConfiguration}.\n     */\n    protected static void migrateRealm(final RealmConfiguration configuration, @Nullable final RealmMigration migration)\n            throws FileNotFoundException {\n\n        //noinspection ConstantConditions\n        if (configuration == null) {\n            throw new IllegalArgumentException(\"RealmConfiguration must be provided\");\n        }\n        if (configuration.isSyncConfiguration()) {\n            throw new IllegalArgumentException(\"Manual migrations are not supported for synced Realms\");\n        }\n        if (migration == null && configuration.getMigration() == null) {\n            throw new RealmMigrationNeededException(configuration.getPath(), \"RealmMigration must be provided.\");\n        }\n\n        final AtomicBoolean fileNotFound = new AtomicBoolean(false);\n\n        RealmCache.invokeWithGlobalRefCount(configuration, new RealmCache.Callback() {\n            @Override\n            public void onResult(int count) {\n                if (count != 0) {\n                    throw new IllegalStateException(\"Cannot migrate a Realm file that is already open: \"\n                            + configuration.getPath());\n                }\n\n                File realmFile = new File(configuration.getPath());\n                if (!realmFile.exists()) {\n                    fileNotFound.set(true);\n                    return;\n                }\n\n                RealmProxyMediator mediator = configuration.getSchemaMediator();\n                OsSchemaInfo schemaInfo = new OsSchemaInfo(mediator.getExpectedObjectSchemaInfoMap().values());\n                OsSharedRealm.MigrationCallback migrationCallback = null;\n                final RealmMigration migrationToBeApplied = migration != null ? migration : configuration.getMigration();\n                if (migrationToBeApplied != null) {\n                    migrationCallback = createMigrationCallback(migrationToBeApplied);\n                }\n                OsRealmConfig.Builder configBuilder = new OsRealmConfig.Builder(configuration)\n                        .autoUpdateNotification(false)\n                        .schemaInfo(schemaInfo)\n                        .migrationCallback(migrationCallback);\n                OsSharedRealm sharedRealm = null;\n                try {\n                    sharedRealm =\n                            OsSharedRealm.getInstance(configBuilder, OsSharedRealm.VersionID.LIVE);\n                } finally {\n                    if (sharedRealm != null) {\n                        sharedRealm.close();\n                    }\n                }\n            }\n        });\n\n        if (fileNotFound.get()) {\n            throw new FileNotFoundException(\"Cannot migrate a Realm file which doesn't exist: \"\n                    + configuration.getPath());\n        }\n    }\n\n    private static OsSharedRealm.MigrationCallback createMigrationCallback(final RealmMigration migration) {\n        return new OsSharedRealm.MigrationCallback() {\n            @Override\n            public void onMigrationNeeded(OsSharedRealm sharedRealm, long oldVersion, long newVersion) {\n                migration.migrate(DynamicRealm.createInstance(sharedRealm), oldVersion, newVersion);\n            }\n        };\n    }\n\n    @Override\n    protected void finalize() throws Throwable {\n        if (shouldCloseSharedRealm && sharedRealm != null && !sharedRealm.isClosed()) {\n            RealmLog.warn(\"Remember to call close() on all Realm instances. \" +\n                    \"Realm %s is being finalized without being closed, \" +\n                    \"this can lead to running out of native memory.\", configuration.getPath()\n            );\n            if (realmCache != null) {\n                realmCache.leak();\n            }\n        }\n        super.finalize();\n    }\n\n    OsSharedRealm getSharedRealm() {\n        return sharedRealm;\n    }\n\n    public static final class RealmObjectContext {\n        private BaseRealm realm;\n        private Row row;\n        private ColumnInfo columnInfo;\n        private boolean acceptDefaultValue;\n        private List<String> excludeFields;\n\n        public void set(BaseRealm realm, Row row, ColumnInfo columnInfo,\n                boolean acceptDefaultValue, List<String> excludeFields) {\n            this.realm = realm;\n            this.row = row;\n            this.columnInfo = columnInfo;\n            this.acceptDefaultValue = acceptDefaultValue;\n            this.excludeFields = excludeFields;\n        }\n\n        BaseRealm getRealm() {\n            return realm;\n        }\n\n        public Row getRow() {\n            return row;\n        }\n\n        public ColumnInfo getColumnInfo() {\n            return columnInfo;\n        }\n\n        public boolean getAcceptDefaultValue() {\n            return acceptDefaultValue;\n        }\n\n        public List<String> getExcludeFields() {\n            return excludeFields;\n        }\n\n        public void clear() {\n            realm = null;\n            row = null;\n            columnInfo = null;\n            acceptDefaultValue = false;\n            excludeFields = null;\n        }\n    }\n\n    /**\n     * CM: This is used when creating new proxy classes directly from the generated proxy code.\n     * It is a bit unclear exactly how it works, but it seems to be some work-around for some\n     * constructor shenanigans, i.e. values are set in this object just before the Proxy object\n     * is created (see `RealmDefaultModuleMediator.newInstance)`).\n     */\n    static final class ThreadLocalRealmObjectContext extends ThreadLocal<RealmObjectContext> {\n        @Override\n        protected RealmObjectContext initialValue() {\n            return new RealmObjectContext();\n        }\n    }\n\n    public static final ThreadLocalRealmObjectContext objectContext = new ThreadLocalRealmObjectContext();\n\n    /**\n     * The Callback used when reporting back the result of loading a Realm asynchronously using either\n     * {@link Realm#getInstanceAsync(RealmConfiguration, Realm.Callback)} or\n     * {@link DynamicRealm#getInstanceAsync(RealmConfiguration, DynamicRealm.Callback)}.\n     * <p>\n     * Before creating the first Realm instance in a process, there are some initialization work that need to be done\n     * such as creating or validating schemas, running migration if needed,\n     * copy asset file if {@link RealmConfiguration.Builder#assetFile(String)} is supplied and execute the\n     * {@link RealmConfiguration.Builder#initialData(Realm.Transaction)} if necessary. This work may take time\n     * and block the caller thread for a while. To avoid the {@code getInstance()} call blocking the main thread, the\n     * {@code getInstanceAsync()} can be used instead to do the initialization work in the background thread and\n     * deliver a Realm instance to the caller thread.\n     * <p>\n     * In general, this method is mostly useful on the UI thread since that should be blocked as little as possible. On\n     * any other Looper threads or other threads that don't support callbacks, using the standard {@code getInstance()}\n     * should be fine.\n     * <p>\n     * Here is an example of using {@code getInstanceAsync()} when the app starts the first activity:\n     * <pre>\n     * public class MainActivity extends Activity {\n     *\n     *   private Realm realm = null;\n     *   private RealmAsyncTask realmAsyncTask;\n     *   private static RealmConfiguration config = new RealmConfiguration.Builder()\n     *     .schema(42)\n     *     .migration(new MyMigration()) // Potentially lengthy migration\n     *     .build();\n     *\n     *   \\@Override\n     *   protected void onCreate(Bundle savedInstanceState) {\n     *     super.onCreate(savedInstanceState);\n     *     setContentView(R.layout.layout_main);\n     *     realmAsyncTask = Realm.getInstanceAsync(config, new Callback() {\n     *         \\@Override\n     *         public void onSuccess(Realm realm) {\n     *             if (isDestroyed()) {\n     *                 // If the activity is destroyed, the Realm instance should be closed immediately to avoid leaks.\n     *                 // Or you can call realmAsyncTask.cancel() in onDestroy() to stop callback delivery.\n     *                 realm.close();\n     *             } else {\n     *                 MainActivity.this.realm = realm;\n     *                 // Remove the spinner and start the real UI.\n     *             }\n     *         }\n     *     });\n     *\n     *     // Show a spinner before Realm instance returned by the callback.\n     *   }\n     *\n     *   \\@Override\n     *   protected void onDestroy() {\n     *     super.onDestroy();\n     *     if (realm != null) {\n     *         realm.close();\n     *         realm = null;\n     *     } else {\n     *         // Calling cancel() on the thread where getInstanceAsync was called on to stop the callback delivery.\n     *         // Otherwise you need to check if the activity is destroyed to close in the onSuccess() properly.\n     *         realmAsyncTask.cancel();\n     *     }\n     *   }\n     * }\n     * </pre>\n     *\n     * @param <T> {@link Realm} or {@link DynamicRealm}.\n     */\n    public abstract static class InstanceCallback<T extends BaseRealm> {\n\n        /**\n         * Deliver a Realm instance to the caller thread.\n         *\n         * @param realm the Realm instance for the caller thread.\n         */\n        public abstract void onSuccess(T realm);\n\n        /**\n         * Deliver an error happens when creating the Realm instance to the caller thread. The default implementation\n         * will throw an exception on the caller thread.\n         *\n         * @param exception happened while initializing Realm on a background thread.\n         */\n        public void onError(Throwable exception) {\n            throw new RealmException(\"Exception happens when initializing Realm in the background thread.\", exception);\n        }\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/Case.java",
    "content": "/*\n * Copyright 2015 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\npackage io.realm;\n\n/**\n * This class describes the Case settings used in Realm queries.\n *\n * @see io.realm.RealmQuery#equalTo(String, String, Case)\n * @see io.realm.RealmQuery#contains(String, String, Case)\n * @see io.realm.RealmQuery#beginsWith(String, String, Case)\n * @see io.realm.RealmQuery#endsWith(String, String, Case)\n */\npublic enum Case {\n    SENSITIVE(true),\n    INSENSITIVE(false);\n\n    private final boolean value;\n\n    Case(boolean value) {\n        this.value = value;\n    }\n\n    /**\n     * Returns the value for this setting that is used by the underlying query engine.\n     *\n     * @return The value used by the underlying query engine to indicate this value.\n     */\n    public boolean getValue() {\n        return value;\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/CollectionUtils.java",
    "content": "/*\n * Copyright 2020 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\npackage io.realm;\n\nimport java.util.Collections;\nimport java.util.HashMap;\nimport java.util.Locale;\n\nimport javax.annotation.Nullable;\n\nimport io.realm.internal.OsObjectStore;\nimport io.realm.internal.RealmObjectProxy;\nimport io.realm.internal.RealmProxyMediator;\nimport io.realm.internal.Table;\nimport io.realm.internal.Util;\n\n\npublic class CollectionUtils {\n    public static final String LIST_TYPE = \"list\";\n    public static final String DICTIONARY_TYPE = \"dictionary\";\n    public static final String SET_TYPE = \"set\";\n\n    static boolean isClassForRealmModel(Class<?> clazz) {\n        return RealmModel.class.isAssignableFrom(clazz);\n    }\n\n    /**\n     * Called by both list operators to determine whether a RealmModel is an embedded object\n     *\n     * @param realm  the Realm instance to check against.\n     * @param object the object to check.\n     * @return true if the object can be copied, false otherwise\n     */\n    static boolean isEmbedded(BaseRealm realm, RealmModel object) {\n        if (realm instanceof Realm) {\n            return realm.getSchema().getSchemaForClass(object.getClass()).isEmbedded();\n        } else {\n            String objectType = ((DynamicRealmObject) object).getType();\n            return realm.getSchema().getSchemaForClass(objectType).isEmbedded();\n        }\n    }\n\n    /**\n     * Called by both list and dictionary operators to determine whether a RealmModel can be copied\n     * to a Realm.\n     *\n     * @param realm          the Realm instance to check against.\n     * @param object         the object to copy.\n     * @param className      the object class.\n     * @param collectionType the type of the calling collection.\n     * @return true if the object can be copied, false otherwise\n     */\n    static boolean checkCanObjectBeCopied(BaseRealm realm, RealmModel object, String className, String collectionType) {\n        if (object instanceof RealmObjectProxy) {\n            RealmObjectProxy proxy = (RealmObjectProxy) object;\n\n            if (proxy instanceof DynamicRealmObject) {\n                if (proxy.realmGet$proxyState().getRealm$realm() == realm) {\n                    String objectClassName = ((DynamicRealmObject) object).getType();\n                    if (className.equals(RealmAny.class.getCanonicalName()) || className.equals(objectClassName)) {\n                        // Same Realm instance and same target table\n                        return false;\n                    } else {\n                        // Different target table\n                        throw new IllegalArgumentException(String.format(Locale.US,\n                                \"The object has a different type from %s's.\" +\n                                        \" Type of the %s is '%s', type of object is '%s'.\", collectionType, collectionType, className, objectClassName));\n                    }\n                } else if (realm.threadId == proxy.realmGet$proxyState().getRealm$realm().threadId) {\n                    // We don't support moving DynamicRealmObjects across Realms automatically. The overhead is too big as\n                    // you have to run a full schema validation for each object.\n                    // And copying from another Realm instance pointed to the same Realm file is not supported as well.\n                    throw new IllegalArgumentException(\"Cannot pass DynamicRealmObject between Realm instances.\");\n                } else {\n                    throw new IllegalStateException(\"Cannot pass an object to a Realm instance created in another thread.\");\n                }\n            } else {\n                // Object is already in this realm\n                if (proxy.realmGet$proxyState().getRow$realm() != null && proxy.realmGet$proxyState().getRealm$realm().getPath().equals(realm.getPath())) {\n                    if (realm != proxy.realmGet$proxyState().getRealm$realm()) {\n                        throw new IllegalArgumentException(\"Cannot pass an object from another Realm instance.\");\n                    }\n                    return false;\n                }\n            }\n        }\n        return true;\n    }\n\n    /**\n     * Called by both list and dictionary operators to determine whether a RealmAny instance contains\n     * a RealmModel in it and, if so, copy it to the provided Realm or not. This method acts as a\n     * pass-through in case the RealmAny instance contains a Realm primitive.\n     *\n     * @param realm the Realm instance to check against and to which the object inside the RealmAny\n     *              instance will be copied if needed.\n     * @param realmAny the RealmAny instance containing the RealmModel to copy to Realm, if needed.\n     * @return the RealmAny instance that may or may not be copied\n     */\n    @SuppressWarnings(\"unchecked\")\n    static RealmAny copyToRealmIfNeeded(BaseRealm realm, RealmAny realmAny) {\n        if (realmAny.getType() == RealmAny.Type.OBJECT) {\n            Class<? extends RealmModel> objectClass = (Class<? extends RealmModel>) realmAny.getValueClass();\n            RealmModel object = realmAny.asRealmModel(objectClass);\n\n            if (object instanceof RealmObjectProxy) {\n                RealmObjectProxy proxy = (RealmObjectProxy) object;\n                if (proxy instanceof DynamicRealmObject) {\n                    if (proxy.realmGet$proxyState().getRealm$realm() == realm) {\n                        return realmAny;\n                    } else if (realm.threadId == proxy.realmGet$proxyState().getRealm$realm().threadId) {\n                        // We don't support moving DynamicRealmObjects across Realms automatically. The overhead is too big as\n                        // you have to run a full schema validation for each object.\n                        // And copying from another Realm instance pointed to the same Realm file is not supported as well.\n                        throw new IllegalArgumentException(\"Cannot copy DynamicRealmObject between Realm instances.\");\n                    } else {\n                        throw new IllegalStateException(\"Cannot copy an object to a Realm instance created in another thread.\");\n                    }\n                } else {\n                    if (realm.getSchema().getSchemaForClass(objectClass).isEmbedded()) {\n                        throw new IllegalArgumentException(\"Embedded objects are not supported by RealmAny.\");\n                    }\n\n                    // Object is already in this realm\n                    if ((proxy.realmGet$proxyState().getRow$realm() != null) && proxy.realmGet$proxyState().getRealm$realm().getPath().equals(realm.getPath())) {\n                        if (realm != proxy.realmGet$proxyState().getRealm$realm()) {\n                            throw new IllegalArgumentException(\"Cannot copy an object from another Realm instance.\");\n                        }\n                        return realmAny;\n                    }\n                }\n            }\n\n            return RealmAny.valueOf(copyToRealm(realm, object));\n        }\n\n        return realmAny;\n    }\n\n    /**\n     * Called by both list and dictionary operators to copy a RealmModel to Realm in case it has\n     * been deemed necessary.\n     *\n     * @param baseRealm The Realm instance to copy the object to.\n     * @param object    The object to copy.\n     * @param <E>       The RealmModel type.\n     * @return the copied object\n     */\n    public static <E extends RealmModel> E copyToRealm(BaseRealm baseRealm, E object) {\n        // At this point the object can only be a typed object, so the backing Realm cannot be a DynamicRealm.\n        Realm realm = (Realm) baseRealm;\n        String simpleClassName = realm.getConfiguration().getSchemaMediator().getSimpleClassName(object.getClass());\n        if (OsObjectStore.getPrimaryKeyForObject(realm.getSharedRealm(), simpleClassName) != null) {\n            return realm.copyToRealmOrUpdate(object);\n        } else {\n            return realm.copyToRealm(object);\n        }\n    }\n\n    /**\n     * Checks whether it is possible to add or remove a provided listener.\n     *\n     * @param listener      The listener to be checked.\n     * @param checkListener whether the check should be performed.\n     */\n    public static void checkForAddRemoveListener(BaseRealm baseRealm, @Nullable Object listener, boolean checkListener) {\n        if (checkListener && listener == null) {\n            throw new IllegalArgumentException(\"Listener should not be null\");\n        }\n        baseRealm.checkIfValid();\n        baseRealm.sharedRealm.capabilities.checkCanDeliverNotification(BaseRealm.LISTENER_NOT_ALLOWED_MESSAGE);\n    }\n\n    /**\n     * Used to update an embedded object internally after its row has been created.\n     *\n     * @param realm      The Realm instance used to create the object.\n     * @param realmModel the model that will be used to update the object.\n     * @param objKey     the object key.\n     */\n    static void updateEmbeddedObject(Realm realm, RealmModel realmModel, long objKey) {\n        RealmProxyMediator schemaMediator = realm.getConfiguration().getSchemaMediator();\n        Class<? extends RealmModel> modelClass = Util.getOriginalModelClass(realmModel.getClass());\n        Table table = realm.getTable(modelClass);\n        RealmModel managedObject = schemaMediator.newInstance(modelClass, realm, table.getUncheckedRow(objKey), realm.getSchema().getColumnInfo(modelClass), true, Collections.EMPTY_LIST);\n        schemaMediator.updateEmbeddedObject(realm, realmModel, managedObject, new HashMap<>(), Collections.EMPTY_SET);\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/CompactOnLaunchCallback.java",
    "content": "/*\n * Copyright 2017 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\npackage io.realm;\n\nimport io.realm.internal.Keep;\n\n/**\n * This interface is used to determine if a Realm file should be compacted the first time the file is opened and before\n * the instance is returned.\n * <p>\n * Note that compacting a file can take a while, so compacting should generally only be done on a background thread or\n * when used in combination with {@link Realm#getInstanceAsync(RealmConfiguration, io.realm.Realm.Callback)}.\n */\n@Keep\npublic interface CompactOnLaunchCallback {\n\n    /**\n     * This method determines if the Realm file should be compacted before opened and returned to the user. It is passed\n     * the total file size (data + free space) and the bytes used by data in the file.\n     *\n     * @param totalBytes the total file size (data + free space).\n     * @param usedBytes the total bytes used by data in the file.\n     * @return {code true} to indicate an attempt to compact the file should be made. Otherwise, the compaction will be\n     * skipped.\n     */\n    boolean shouldCompact(long totalBytes, long usedBytes);\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/DefaultCompactOnLaunchCallback.java",
    "content": "/*\n * Copyright 2017 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\npackage io.realm;\n\n/**\n * The default implementation for determining if a file should be compacted or not. This implementation will only\n * trigger if the file is above 50 MB and more than 50% can be reclaimed.\n */\npublic class DefaultCompactOnLaunchCallback implements CompactOnLaunchCallback {\n    @Override\n    public boolean shouldCompact(long totalBytes, long usedBytes) {\n        final long thresholdSize = 50 * 1024 * 1024;\n        return (totalBytes > thresholdSize) && (((double) usedBytes / (double) totalBytes) < 0.5);\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/DynamicRealm.java",
    "content": "/*\n * Copyright 2015 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\npackage io.realm;\n\nimport java.util.Locale;\nimport java.util.concurrent.Future;\n\nimport javax.annotation.Nullable;\n\nimport io.reactivex.Flowable;\nimport io.realm.annotations.RealmClass;\nimport io.realm.exceptions.RealmException;\nimport io.realm.exceptions.RealmFileException;\nimport io.realm.internal.CheckedRow;\nimport io.realm.internal.OsObject;\nimport io.realm.internal.OsObjectStore;\nimport io.realm.internal.OsSharedRealm;\nimport io.realm.internal.RealmNotifier;\nimport io.realm.internal.RealmObjectProxy;\nimport io.realm.internal.Row;\nimport io.realm.internal.Table;\nimport io.realm.internal.Util;\nimport io.realm.internal.async.RealmAsyncTaskImpl;\nimport io.realm.log.RealmLog;\n\n/**\n * DynamicRealm is a dynamic variant of {@link io.realm.Realm}. This means that all access to data and/or queries are\n * done using string based class names instead of class type references.\n * <p>\n * This is useful during migrations or when working with string-based data like CSV or XML files.\n * <p>\n * The same {@link io.realm.RealmConfiguration} can be used to open a Realm file in both dynamic and typed mode, but\n * modifying the schema while having both a typed and dynamic version open is highly discouraged and will most likely\n * crash the typed Realm. During migrations only a DynamicRealm will be open.\n * <p>\n * Dynamic Realms do not enforce schemas or schema versions and {@link RealmMigration} code is not used even if it has\n * been defined in the {@link RealmConfiguration}.\n * <p>\n * This means that the schema is not created or validated until a Realm has been opened in typed mode. If a Realm\n * file is opened in dynamic mode first it will not contain any information about classes and fields, and any queries\n * for classes defined by the schema will fail.\n *\n * @see Realm\n * @see RealmSchema\n */\npublic class DynamicRealm extends BaseRealm {\n\n    private final RealmSchema schema;\n\n    private DynamicRealm(final RealmCache cache, OsSharedRealm.VersionID version) {\n        super(cache, null, version);\n        RealmCache.invokeWithGlobalRefCount(cache.getConfiguration(), new RealmCache.Callback() {\n            @Override\n            public void onResult(int count) {\n                if (count > 0)  {\n                    return;\n                }\n                if (cache.getConfiguration().isReadOnly()) {\n                    return;\n                }\n                if (OsObjectStore.getSchemaVersion(sharedRealm) != OsObjectStore.SCHEMA_NOT_VERSIONED) {\n                    return;\n                }\n                sharedRealm.beginTransaction();\n                if (OsObjectStore.getSchemaVersion(sharedRealm) == OsObjectStore.SCHEMA_NOT_VERSIONED) {\n                    // To initialize the meta table.\n                    OsObjectStore.setSchemaVersion(sharedRealm, OsObjectStore.SCHEMA_NOT_VERSIONED);\n                }\n                sharedRealm.commitTransaction();\n            }\n        });\n        this.schema = new MutableRealmSchema(this);\n    }\n\n    private DynamicRealm(OsSharedRealm sharedRealm) {\n        super(sharedRealm);\n        this.schema = new MutableRealmSchema(this);\n    }\n\n    /**\n     * Realm static constructor that returns a dynamic variant of the Realm instance defined by provided\n     * {@link io.realm.RealmConfiguration}. Dynamic Realms do not care about schemaVersion and schemas, so opening a\n     * DynamicRealm will never trigger a migration.\n     *\n     * @return the DynamicRealm defined by the configuration.\n     * @throws RealmFileException if an error happened when accessing the underlying Realm file.\n     * @throws IllegalArgumentException if {@code configuration} argument is {@code null}.\n     * @see RealmConfiguration for details on how to configure a Realm.\n     */\n    public static DynamicRealm getInstance(RealmConfiguration configuration) {\n        //noinspection ConstantConditions\n        if (configuration == null) {\n            throw new IllegalArgumentException(\"A non-null RealmConfiguration must be provided\");\n        }\n        return RealmCache.createRealmOrGetFromCache(configuration, DynamicRealm.class);\n    }\n\n    /**\n     * The creation of the first Realm instance per {@link RealmConfiguration} in a process can take some time as all\n     * initialization code need to run at that point (Setting up the Realm, validating schemas and creating initial\n     * data). This method places the initialization work in a background thread and deliver the Realm instance\n     * to the caller thread asynchronously after the initialization is finished.\n     *\n     * @param configuration {@link RealmConfiguration} used to open the Realm.\n     * @param callback invoked to return the results.\n     * @throws IllegalArgumentException if a null {@link RealmConfiguration} or a null {@link Callback} is provided.\n     * @throws IllegalStateException if it is called from a non-Looper or {@link android.app.IntentService} thread.\n     * @return a {@link RealmAsyncTask} representing a cancellable task.\n     * @see Callback for more details.\n     */\n    public static RealmAsyncTask getInstanceAsync(RealmConfiguration configuration,\n                                                  Callback callback) {\n        //noinspection ConstantConditions\n        if (configuration == null) {\n            throw new IllegalArgumentException(\"A non-null RealmConfiguration must be provided\");\n        }\n        return RealmCache.createRealmOrGetFromCacheAsync(configuration, callback, DynamicRealm.class);\n    }\n\n    /**\n     * Instantiates and adds a new object to the Realm.\n     *\n     * @param className the class name of the object to create.\n     * @return the new object.\n     * @throws RealmException if the object could not be created.\n     */\n    public DynamicRealmObject createObject(String className) {\n        checkIfValid();\n        Table table = schema.getTable(className);\n        String pkField = OsObjectStore.getPrimaryKeyForObject(sharedRealm, className);\n        // Check and throw the exception earlier for a better exception message.\n        if (pkField != null) {\n            throw new RealmException(String.format(Locale.US,\n                    \"'%s' has a primary key field '%s', use  'createObject(String, Object)' instead.\",\n                    className, pkField));\n        }\n\n        return new DynamicRealmObject(this, CheckedRow.getFromRow(OsObject.create(table)));\n    }\n\n    /**\n     * Creates an object with a given primary key. Classes without a primary key defined must use\n     * {@link #createObject(String)}} instead.\n     *\n     * @return the new object. All fields will have default values for their type, except for the\n     * primary key field which will have the provided value.\n     * @throws RealmException if object could not be created due to the primary key being invalid.\n     * @throws IllegalStateException if the model clazz does not have a primary key defined.\n     * @throws IllegalArgumentException if the {@code primaryKeyValue} doesn't have a value that can be converted to the\n     * expected value.\n     */\n    public DynamicRealmObject createObject(String className, Object primaryKeyValue) {\n        Table table = schema.getTable(className);\n        return new DynamicRealmObject(this,\n                CheckedRow.getFromRow(OsObject.createWithPrimaryKey(table, primaryKeyValue)));\n    }\n\n    /**\n     * Instantiates and adds a new embedded object to the Realm.\n     * <p>\n     * This method should only be used to create objects of types marked as embedded.\n     *\n     * @param className the class name of the object to create.\n     * @param parentObject The parent object which should hold a reference to the embedded object.\n     *                     If the parent property is a list the embedded object will be added to the\n     *                     end of that list.\n     * @param parentProperty the property in the parent class which holds the reference.\n     * @return the newly created embedded object.\n     * @throws IllegalArgumentException if {@code clazz} is not an embedded class or if the property\n     * in the parent class cannot hold objects of the appropriate type.\n     * @see RealmClass#embedded()\n     */\n    public DynamicRealmObject createEmbeddedObject(String className,\n                                                   DynamicRealmObject parentObject,\n                                                   String parentProperty) {\n        checkIfValid();\n        Util.checkNull(parentObject, \"parentObject\");\n        Util.checkEmpty(parentProperty, \"parentProperty\");\n        if (!RealmObject.isManaged(parentObject) || !RealmObject.isValid(parentObject)) {\n            throw new IllegalArgumentException(\"Only valid, managed objects can be a parent to an embedded object.\");\n        }\n\n        String pkField = OsObjectStore.getPrimaryKeyForObject(sharedRealm, className);\n        // Check and throw the exception earlier for a better exception message.\n        if (pkField != null) {\n            throw new RealmException(String.format(Locale.US,\n                    \"'%s' has a primary key field '%s', embedded objects cannot have primary keys.\",\n                    className, pkField));\n        }\n\n        String parentClassName = parentObject.getType();\n        RealmObjectSchema parentObjectSchema = schema.get(parentClassName);\n\n        if (parentObjectSchema == null) {\n            throw new IllegalStateException(String.format(\"No schema found for '%s'.\", parentClassName));\n        }\n\n        Row embeddedObject = getEmbeddedObjectRow(className, parentObject, parentProperty, schema, parentObjectSchema);\n\n        return new DynamicRealmObject(this, embeddedObject);\n    }\n\n    /**\n     * Returns a RealmQuery, which can be used to query the provided class.\n     *\n     * @param className the class of the object which is to be queried.\n     * @return a RealmQuery, which can be used to query for specific objects of provided type.\n     * @throws IllegalArgumentException if the class doesn't exist.\n     * @see io.realm.RealmQuery\n     */\n    public RealmQuery<DynamicRealmObject> where(String className) {\n        checkIfValid();\n        if (!sharedRealm.hasTable(Table.getTableNameForClass(className))) {\n            throw new IllegalArgumentException(\"Class does not exist in the Realm and cannot be queried: \" + className);\n        }\n        return RealmQuery.createDynamicQuery(this, className);\n    }\n\n\n    /**\n     * Adds a change listener to the Realm.\n     * <p>\n     * The listeners will be executed when changes are committed by this or another thread.\n     * <p>\n     * Realm instances are cached per thread. For that reason it is important to\n     * remember to remove listeners again either using {@link #removeChangeListener(RealmChangeListener)}\n     * or {@link #removeAllChangeListeners()}. Not doing so can cause memory leaks.\n     *\n     * @param listener the change listener.\n     * @throws IllegalArgumentException if the change listener is {@code null}.\n     * @see io.realm.RealmChangeListener\n     * @see #removeChangeListener(RealmChangeListener)\n     * @see #removeAllChangeListeners()\n     * @see #refresh()\n     */\n    public void addChangeListener(RealmChangeListener<DynamicRealm> listener) {\n        addListener(listener);\n    }\n\n    /**\n     * Removes the specified change listener.\n     *\n     * @param listener the change listener to be removed.\n     * @throws IllegalArgumentException if the change listener is {@code null}.\n     * @throws IllegalStateException if you try to remove a listener from a non-Looper Thread.\n     * @see io.realm.RealmChangeListener\n     */\n    public void removeChangeListener(RealmChangeListener<DynamicRealm> listener) {\n        removeListener(listener);\n    }\n\n    /**\n     * Removes all user-defined change listeners.\n     *\n     * @throws IllegalStateException if you try to remove listeners from a non-Looper Thread.\n     * @see io.realm.RealmChangeListener\n     */\n    public void removeAllChangeListeners() {\n        removeAllListeners();\n    }\n\n    /**\n     * Deletes all objects of the specified class from the Realm.\n     *\n     * @param className the class for which all objects should be removed.\n     * @throws IllegalStateException if the Realm is closed or called from an incorrect thread.\n     */\n    public void delete(String className) {\n        checkIfValid();\n        checkIfInTransaction();\n        schema.getTable(className).clear();\n    }\n\n    /**\n     * Executes a given transaction on the DynamicRealm. {@link #beginTransaction()} and\n     * {@link #commitTransaction()} will be called automatically. If any exception is thrown\n     * during the transaction {@link #cancelTransaction()} will be called instead of {@link #commitTransaction()}.\n     * <p>\n     * Calling this method from the UI thread will throw a {@link RealmException}. Doing so may result in a drop of frames\n     * or even ANRs. We recommend calling this method from a non-UI thread or using\n     * {@link #executeTransactionAsync(Transaction)} instead.\n     *\n     * @param transaction {@link Transaction} to execute.\n     * @throws IllegalArgumentException if the {@code transaction} is {@code null}.\n     * @throws RealmException if called from the UI thread, unless an explicit opt-in has been declared in {@link RealmConfiguration.Builder#allowWritesOnUiThread(boolean)}.\n     */\n    public void executeTransaction(Transaction transaction) {\n        //noinspection ConstantConditions\n        if (transaction == null) {\n            throw new IllegalArgumentException(\"Transaction should not be null\");\n        }\n\n        checkAllowWritesOnUiThread();\n\n        beginTransaction();\n        try {\n            transaction.execute(this);\n            commitTransaction();\n        } catch (RuntimeException e) {\n            if (isInTransaction()) {\n                cancelTransaction();\n            } else {\n                RealmLog.warn(\"Could not cancel transaction, not currently in a transaction.\");\n            }\n            throw e;\n        }\n    }\n\n    /**\n     * Similar to {@link #executeTransaction(Transaction)} but runs asynchronously on a worker thread.\n     *\n     * @param transaction {@link Transaction} to execute.\n     * @return a {@link RealmAsyncTask} representing a cancellable task.\n     * @throws IllegalArgumentException if the {@code transaction} is {@code null}, or if the Realm is opened from\n     * another thread.\n     */\n    public RealmAsyncTask executeTransactionAsync(final Transaction transaction) {\n        return executeTransactionAsync(transaction, null, null);\n    }\n\n    /**\n     * Similar to {@link #executeTransactionAsync(Transaction)}, but also accepts an OnSuccess callback.\n     *\n     * @param transaction {@link Transaction} to execute.\n     * @param onSuccess callback invoked when the transaction succeeds.\n     * @return a {@link RealmAsyncTask} representing a cancellable task.\n     * @throws IllegalArgumentException if the {@code transaction} is {@code null}, or if the realm is opened from\n     * another thread.\n     */\n    public RealmAsyncTask executeTransactionAsync(final Transaction transaction, final Transaction.OnSuccess onSuccess) {\n        //noinspection ConstantConditions\n        if (onSuccess == null) {\n            throw new IllegalArgumentException(\"onSuccess callback can't be null\");\n        }\n\n        return executeTransactionAsync(transaction, onSuccess, null);\n    }\n\n    /**\n     * Similar to {@link #executeTransactionAsync(Transaction)}, but also accepts an OnError callback.\n     *\n     * @param transaction {@link Transaction} to execute.\n     * @param onError callback invoked when the transaction fails.\n     * @return a {@link RealmAsyncTask} representing a cancellable task.\n     * @throws IllegalArgumentException if the {@code transaction} is {@code null}, or if the realm is opened from\n     * another thread.\n     */\n    public RealmAsyncTask executeTransactionAsync(final Transaction transaction, final Transaction.OnError onError) {\n        //noinspection ConstantConditions\n        if (onError == null) {\n            throw new IllegalArgumentException(\"onError callback can't be null\");\n        }\n\n        return executeTransactionAsync(transaction, null, onError);\n    }\n\n    /**\n     * Similar to {@link #executeTransactionAsync(Transaction)}, but also accepts an OnSuccess and OnError callbacks.\n     *\n     * @param transaction {@link Transaction} to execute.\n     * @param onSuccess callback invoked when the transaction succeeds.\n     * @param onError callback invoked when the transaction fails.\n     * @return a {@link RealmAsyncTask} representing a cancellable task.\n     * @throws IllegalArgumentException if the {@code transaction} is {@code null}, or if the realm is opened from\n     * another thread.\n     */\n    public RealmAsyncTask executeTransactionAsync(final Transaction transaction,\n                                                  @Nullable final Transaction.OnSuccess onSuccess,\n                                                  @Nullable final Transaction.OnError onError) {\n        checkIfValid();\n\n        //noinspection ConstantConditions\n        if (transaction == null) {\n            throw new IllegalArgumentException(\"Transaction should not be null\");\n        }\n\n        if (isFrozen()) {\n            throw new IllegalStateException(\"Write transactions on a frozen Realm is not allowed.\");\n        }\n\n        // Avoid to call canDeliverNotification() in bg thread.\n        final boolean canDeliverNotification = sharedRealm.capabilities.canDeliverNotification();\n\n        // If the user provided a Callback then we have to make sure the current Realm has an events looper to deliver\n        // the results.\n        if ((onSuccess != null || onError != null)) {\n            sharedRealm.capabilities.checkCanDeliverNotification(\"Callback cannot be delivered on current thread.\");\n        }\n\n        // We need to use the same configuration to open a background OsSharedRealm (i.e Realm)\n        // to perform the transaction\n        final RealmConfiguration realmConfiguration = getConfiguration();\n        // We need to deliver the callback even if the Realm is closed. So acquire a reference to the notifier here.\n        final RealmNotifier realmNotifier = sharedRealm.realmNotifier;\n\n        final Future<?> pendingTransaction = asyncTaskExecutor.submitTransaction(new Runnable() {\n            @Override\n            public void run() {\n                if (Thread.currentThread().isInterrupted()) {\n                    return;\n                }\n\n                OsSharedRealm.VersionID versionID = null;\n                Throwable exception = null;\n\n                final DynamicRealm bgRealm = DynamicRealm.getInstance(realmConfiguration);\n                bgRealm.beginTransaction();\n                try {\n                    transaction.execute(bgRealm);\n\n                    if (Thread.currentThread().isInterrupted()) {\n                        return;\n                    }\n\n                    bgRealm.commitTransaction();\n                    // The bgRealm needs to be closed before post event to caller's handler to avoid concurrency\n                    // problem. This is currently guaranteed by posting callbacks later below.\n                    versionID = bgRealm.sharedRealm.getVersionID();\n                } catch (final Throwable e) {\n                    exception = e;\n                } finally {\n                    try {\n                        if (bgRealm.isInTransaction()) {\n                            bgRealm.cancelTransaction();\n                        }\n                    } finally {\n                        bgRealm.close();\n                    }\n                }\n\n                final Throwable backgroundException = exception;\n                final OsSharedRealm.VersionID backgroundVersionID = versionID;\n                // Cannot be interrupted anymore.\n                if (canDeliverNotification) {\n                    if (backgroundVersionID != null && onSuccess != null) {\n                        realmNotifier.post(new Runnable() {\n                            @Override\n                            public void run() {\n                                if (isClosed()) {\n                                    // The caller Realm is closed. Just call the onSuccess. Since the new created Realm\n                                    // cannot be behind the background one.\n                                    onSuccess.onSuccess();\n                                    return;\n                                }\n\n                                if (sharedRealm.getVersionID().compareTo(backgroundVersionID) < 0) {\n                                    sharedRealm.realmNotifier.addTransactionCallback(new Runnable() {\n                                        @Override\n                                        public void run() {\n                                            onSuccess.onSuccess();\n                                        }\n                                    });\n                                } else {\n                                    onSuccess.onSuccess();\n                                }\n                            }\n                        });\n                    } else if (backgroundException != null) {\n                        realmNotifier.post(new Runnable() {\n                            @Override\n                            public void run() {\n                                if (onError != null) {\n                                    onError.onError(backgroundException);\n                                } else {\n                                    throw new RealmException(\"Async transaction failed\", backgroundException);\n                                }\n                            }\n                        });\n                    }\n                } else {\n                    if (backgroundException != null) {\n                        // FIXME: ThreadPoolExecutor will never throw the exception in the background.\n                        // We need a redesign of the async transaction API.\n                        // Throw in the worker thread since the caller thread cannot get notifications.\n                        throw new RealmException(\"Async transaction failed\", backgroundException);\n                    }\n                }\n\n            }\n        });\n\n        return new RealmAsyncTaskImpl(pendingTransaction, asyncTaskExecutor);\n    }\n\n    /**\n     * Creates a {@link DynamicRealm} instance without checking the existence in the {@link RealmCache}.\n     *\n     * @return a {@link DynamicRealm} instance.\n     */\n    static DynamicRealm createInstance(RealmCache cache, OsSharedRealm.VersionID version) {\n        return new DynamicRealm(cache, version);\n    }\n\n    /**\n     * Creates a {@link DynamicRealm} instance with a given {@link OsSharedRealm} instance without owning it.\n     * This is designed to be used in the migration block when opening a typed Realm instance.\n     *\n     * @param sharedRealm the existing {@link OsSharedRealm} instance.\n     * @return a {@link DynamicRealm} instance.\n     */\n    static DynamicRealm createInstance(OsSharedRealm sharedRealm) {\n        return new DynamicRealm(sharedRealm);\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    @Override\n    public Flowable<DynamicRealm> asFlowable() {\n        return configuration.getRxFactory().from(this);\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    @Override\n    public boolean isEmpty() {\n        checkIfValid();\n        return sharedRealm.isEmpty();\n    }\n\n    /**\n     * Returns the mutable schema for this Realm.\n     *\n     * @return The {@link RealmSchema} for this Realm.\n     */\n    @Override\n    public RealmSchema getSchema() {\n        return schema;\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    @Override\n    public DynamicRealm freeze() {\n        // In some cases a Read transaction has not begun for the Realm, which means\n        // we cannot read the current version. In that case, do some work that will create the\n        // read transaction.\n        OsSharedRealm.VersionID version;\n        try {\n            version = sharedRealm.getVersionID();\n        } catch (IllegalStateException e) {\n            getVersion();\n            version = sharedRealm.getVersionID();\n        }\n        return RealmCache.createRealmOrGetFromCache(configuration, DynamicRealm.class, version);\n    }\n\n    /**\n     * Set the schema version of this dynamic realm to the given version number. If the meta table doesn't exist, this\n     * will create the meta table first.\n     * <p>\n     * NOTE: This API is for internal testing only. Except testing, the schema version should always be set by the\n     * Object Store during schema initialization or migration.\n     *\n     * @param version the schema version to be set.\n     */\n    void setVersion(long version) {\n        OsObjectStore.setSchemaVersion(sharedRealm, version);\n    }\n\n    /**\n     * Encapsulates a Realm transaction.\n     * <p>\n     * Using this class will automatically handle {@link io.realm.DynamicRealm#beginTransaction()} and {@link io.realm.DynamicRealm#commitTransaction()}\n     * If any exception is thrown during the transaction {@link io.realm.DynamicRealm#cancelTransaction()} will be called\n     * instead of {@link io.realm.DynamicRealm#commitTransaction()}.\n     */\n    public interface Transaction {\n        void execute(DynamicRealm realm);\n\n        /**\n         * Callback invoked to notify the caller thread.\n         */\n        class Callback {\n            public void onSuccess() {}\n\n            public void onError(Exception ignore) {}\n        }\n\n        /**\n         * Callback invoked to notify the caller thread about the success of the transaction.\n         */\n        interface OnSuccess {\n            void onSuccess();\n        }\n\n        /**\n         * Callback invoked to notify the caller thread about error during the transaction.\n         * The transaction will be rolled back and the background Realm will be closed before\n         * invoking {@link #onError(Throwable)}.\n         */\n        interface OnError {\n            void onError(Throwable error);\n        }\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    public abstract static class Callback extends InstanceCallback<DynamicRealm> {\n        /**\n         * {@inheritDoc}\n         */\n        @Override\n        public abstract void onSuccess(DynamicRealm realm);\n\n        /**\n         * {@inheritDoc}\n         */\n        @Override\n        public void onError(Throwable exception) {\n            super.onError(exception);\n        }\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/DynamicRealmObject.java",
    "content": "/*\n * Copyright 2015 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 */\npackage io.realm;\n\nimport org.bson.types.Decimal128;\nimport org.bson.types.ObjectId;\n\nimport java.util.Arrays;\nimport java.util.Date;\nimport java.util.Iterator;\nimport java.util.Locale;\nimport java.util.Map;\nimport java.util.UUID;\n\nimport javax.annotation.Nonnull;\nimport javax.annotation.Nullable;\n\nimport io.realm.exceptions.RealmException;\nimport io.realm.internal.CheckedRow;\nimport io.realm.internal.OsList;\nimport io.realm.internal.OsMap;\nimport io.realm.internal.OsSet;\nimport io.realm.internal.RealmObjectProxy;\nimport io.realm.internal.Row;\nimport io.realm.internal.Table;\nimport io.realm.internal.UncheckedRow;\nimport io.realm.internal.android.JsonUtils;\nimport io.realm.internal.core.NativeRealmAny;\n\nimport static io.realm.RealmFieldTypeConstants.DICTIONARY_OFFSET;\nimport static io.realm.RealmFieldTypeConstants.LIST_OFFSET;\nimport static io.realm.RealmFieldTypeConstants.SET_OFFSET;\n\n\n/**\n * Class that wraps a normal RealmObject in order to allow dynamic access instead of a typed interface.\n * Using a DynamicRealmObject is slower than using the regular RealmObject class.\n */\n@SuppressWarnings(\"WeakerAccess\")\npublic class DynamicRealmObject extends RealmObject implements RealmObjectProxy {\n    static final String MSG_LINK_QUERY_NOT_SUPPORTED = \"Queries across relationships are not supported\";\n\n    private final ProxyState<DynamicRealmObject> proxyState = new ProxyState<>(this);\n\n    /**\n     * Creates a dynamic Realm object based on an existing object.\n     *\n     * @param obj the Realm object to convert to a dynamic object. Only objects managed by {@link Realm} can be used.\n     * @throws IllegalArgumentException if object isn't managed by Realm or is a {@link DynamicRealmObject} already.\n     */\n    public DynamicRealmObject(RealmModel obj) {\n        //noinspection ConstantConditions\n        if (obj == null) {\n            throw new IllegalArgumentException(\"A non-null object must be provided.\");\n        }\n        if (obj instanceof DynamicRealmObject) {\n            throw new IllegalArgumentException(\"The object is already a DynamicRealmObject: \" + obj);\n        }\n\n        if (!RealmObject.isManaged(obj)) {\n            throw new IllegalArgumentException(\"An object managed by Realm must be provided. This \" +\n                    \"is an unmanaged object.\");\n        }\n\n        if (!RealmObject.isValid(obj)) {\n            throw new IllegalArgumentException(\"A valid object managed by Realm must be provided. \" +\n                    \"This object was deleted.\");\n        }\n\n        RealmObjectProxy proxy = (RealmObjectProxy) obj;\n        Row row = proxy.realmGet$proxyState().getRow$realm();\n        proxyState.setRealm$realm(proxy.realmGet$proxyState().getRealm$realm());\n        proxyState.setRow$realm(((UncheckedRow) row).convertToChecked());\n        proxyState.setConstructionFinished();\n    }\n\n    // row must be an instance of CheckedRow or InvalidRow\n    DynamicRealmObject(BaseRealm realm, Row row) {\n        proxyState.setRealm$realm(realm);\n        proxyState.setRow$realm(row);\n        proxyState.setConstructionFinished();\n    }\n\n    /**\n     * Returns the value for the given field.\n     *\n     * @param fieldName name of the field.\n     * @return the field value.\n     * @throws ClassCastException if the field doesn't contain a field of the defined return type.\n     */\n    @SuppressWarnings({\"unchecked\", \"TypeParameterUnusedInFormals\"})\n    public <E> E get(String fieldName) {\n        proxyState.getRealm$realm().checkIfValid();\n\n        long columnKey = proxyState.getRow$realm().getColumnKey(fieldName);\n        if (proxyState.getRow$realm().isNull(columnKey)) {\n            return null;\n        }\n        RealmFieldType type = proxyState.getRow$realm().getColumnType(columnKey);\n        switch (type) {\n            case BOOLEAN:\n                return (E) Boolean.valueOf(proxyState.getRow$realm().getBoolean(columnKey));\n            case INTEGER:\n                return (E) Long.valueOf(proxyState.getRow$realm().getLong(columnKey));\n            case FLOAT:\n                return (E) Float.valueOf(proxyState.getRow$realm().getFloat(columnKey));\n            case DOUBLE:\n                return (E) Double.valueOf(proxyState.getRow$realm().getDouble(columnKey));\n            case STRING:\n                return (E) proxyState.getRow$realm().getString(columnKey);\n            case BINARY:\n                return (E) proxyState.getRow$realm().getBinaryByteArray(columnKey);\n            case DATE:\n                return (E) proxyState.getRow$realm().getDate(columnKey);\n            case DECIMAL128:\n                return (E) proxyState.getRow$realm().getDecimal128(columnKey);\n            case OBJECT_ID:\n                return (E) proxyState.getRow$realm().getObjectId(columnKey);\n            case MIXED:\n                return (E) getRealmAny(columnKey);\n            case UUID:\n                return (E) proxyState.getRow$realm().getUUID(columnKey);\n            case OBJECT:\n                return (E) getObject(fieldName);\n            case LIST:\n                return (E) getList(fieldName);\n            case STRING_TO_INTEGER_MAP:\n                return (E) getDictionary(fieldName, Integer.class);\n            case STRING_TO_BOOLEAN_MAP:\n                return (E) getDictionary(fieldName, Boolean.class);\n            case STRING_TO_STRING_MAP:\n                return (E) getDictionary(fieldName, String.class);\n            case STRING_TO_BINARY_MAP:\n                return (E) getDictionary(fieldName, byte[].class);\n            case STRING_TO_DATE_MAP:\n                return (E) getDictionary(fieldName, Date.class);\n            case STRING_TO_FLOAT_MAP:\n                return (E) getDictionary(fieldName, Float.class);\n            case STRING_TO_DOUBLE_MAP:\n                return (E) getDictionary(fieldName, Double.class);\n            case STRING_TO_DECIMAL128_MAP:\n                return (E) getDictionary(fieldName, Decimal128.class);\n            case STRING_TO_OBJECT_ID_MAP:\n                return (E) getDictionary(fieldName, ObjectId.class);\n            case STRING_TO_UUID_MAP:\n                return (E) getDictionary(fieldName, UUID.class);\n            case STRING_TO_MIXED_MAP:\n                return (E) getDictionary(fieldName, RealmAny.class);\n            case STRING_TO_LINK_MAP:\n                return (E) getDictionary(fieldName);\n            case INTEGER_SET:\n                return (E) getRealmSet(fieldName, Integer.class);\n            case BOOLEAN_SET:\n                return (E) getRealmSet(fieldName, Boolean.class);\n            case STRING_SET:\n                return (E) getRealmSet(fieldName, String.class);\n            case BINARY_SET:\n                return (E) getRealmSet(fieldName, byte[].class);\n            case DATE_SET:\n                return (E) getRealmSet(fieldName, Date.class);\n            case FLOAT_SET:\n                return (E) getRealmSet(fieldName, Float.class);\n            case DOUBLE_SET:\n                return (E) getRealmSet(fieldName, Double.class);\n            case DECIMAL128_SET:\n                return (E) getRealmSet(fieldName, Decimal128.class);\n            case OBJECT_ID_SET:\n                return (E) getRealmSet(fieldName, ObjectId.class);\n            case UUID_SET:\n                return (E) getRealmSet(fieldName, UUID.class);\n            case LINK_SET:\n                return (E) getRealmSet(fieldName);\n            case MIXED_SET:\n                return (E) getRealmSet(fieldName, RealmAny.class);\n            default:\n                throw new IllegalStateException(\"Field type not supported: \" + type);\n        }\n    }\n\n    /**\n     * Returns the {@code boolean} value for a given field.\n     * <p>\n     * If the field is nullable, use {@link #isNull(String)} to check for {@code null} instead of using\n     * this method.\n     *\n     * @param fieldName the name of the field.\n     * @return the boolean value.\n     * @throws IllegalArgumentException           if field name doesn't exist or it doesn't contain booleans.\n     * @throws io.realm.exceptions.RealmException if the return value would be {@code null}.\n     */\n    public boolean getBoolean(String fieldName) {\n        proxyState.getRealm$realm().checkIfValid();\n\n        long columnKey = proxyState.getRow$realm().getColumnKey(fieldName);\n        try {\n            return proxyState.getRow$realm().getBoolean(columnKey);\n        } catch (IllegalArgumentException e) {\n            checkFieldType(fieldName, columnKey, RealmFieldType.BOOLEAN);\n            throw e;\n        }\n    }\n\n    /**\n     * Returns the {@code int} value for a given field.\n     * <p>\n     * If the field is nullable, use {@link #isNull(String)} to check for {@code null} instead of using\n     * this method.\n     *\n     * @param fieldName the name of the field.\n     * @return the int value. Integer values exceeding {@code Integer.MAX_VALUE} will wrap.\n     * @throws IllegalArgumentException           if field name doesn't exist or it doesn't contain integers.\n     * @throws io.realm.exceptions.RealmException if the return value would be {@code null}.\n     */\n    public int getInt(String fieldName) {\n        return (int) getLong(fieldName);\n    }\n\n    /**\n     * Returns the {@code short} value for a given field.\n     * <p>\n     * If the field is nullable, use {@link #isNull(String)} to check for {@code null} instead of using\n     * this method.\n     *\n     * @param fieldName the name of the field.\n     * @return the short value. Integer values exceeding {@code Short.MAX_VALUE} will wrap.\n     * @throws IllegalArgumentException           if field name doesn't exist or it doesn't contain integers.\n     * @throws io.realm.exceptions.RealmException if the return value would be {@code null}.\n     */\n    public short getShort(String fieldName) {\n        return (short) getLong(fieldName);\n    }\n\n    /**\n     * Returns the {@code long} value for a given field.\n     * <p>\n     * If the field is nullable, use {@link #isNull(String)} to check for {@code null} instead of using\n     * this method.\n     *\n     * @param fieldName the name of the field.\n     * @return the long value. Integer values exceeding {@code Long.MAX_VALUE} will wrap.\n     * @throws IllegalArgumentException           if field name doesn't exist or it doesn't contain integers.\n     * @throws io.realm.exceptions.RealmException if the return value would be {@code null}.\n     */\n    public long getLong(String fieldName) {\n        proxyState.getRealm$realm().checkIfValid();\n\n        long columnKey = proxyState.getRow$realm().getColumnKey(fieldName);\n        try {\n            return proxyState.getRow$realm().getLong(columnKey);\n        } catch (IllegalArgumentException e) {\n            checkFieldType(fieldName, columnKey, RealmFieldType.INTEGER);\n            throw e;\n        }\n    }\n\n    /**\n     * Returns the {@code byte} value for a given field.\n     * <p>\n     * If the field is nullable, use {@link #isNull(String)} to check for {@code null} instead of using\n     * this method.\n     *\n     * @param fieldName the name of the field.\n     * @return the byte value.\n     * @throws IllegalArgumentException           if field name doesn't exist or it doesn't contain integers.\n     * @throws io.realm.exceptions.RealmException if the return value would be {@code null}.\n     */\n    public byte getByte(String fieldName) {\n        return (byte) getLong(fieldName);\n    }\n\n    /**\n     * Returns the {@code float} value for a given field.\n     * <p>\n     * If the field is nullable, use {@link #isNull(String)} to check for {@code null} instead of using\n     * this method.\n     *\n     * @param fieldName the name of the field.\n     * @return the float value.\n     * @throws IllegalArgumentException           if field name doesn't exist or it doesn't contain floats.\n     * @throws io.realm.exceptions.RealmException if the return value would be {@code null}.\n     */\n    public float getFloat(String fieldName) {\n        proxyState.getRealm$realm().checkIfValid();\n\n        long columnKey = proxyState.getRow$realm().getColumnKey(fieldName);\n        try {\n            return proxyState.getRow$realm().getFloat(columnKey);\n        } catch (IllegalArgumentException e) {\n            checkFieldType(fieldName, columnKey, RealmFieldType.FLOAT);\n            throw e;\n        }\n    }\n\n    /**\n     * Returns the {@code double} value for a given field.\n     * <p>\n     * If the field is nullable, use {@link #isNull(String)} to check for {@code null} instead of using\n     * this method.\n     *\n     * @param fieldName the name of the field.\n     * @return the double value.\n     * @throws IllegalArgumentException           if field name doesn't exist or it doesn't contain doubles.\n     * @throws io.realm.exceptions.RealmException if the return value would be {@code null}.\n     */\n    public double getDouble(String fieldName) {\n        proxyState.getRealm$realm().checkIfValid();\n\n        long columnKey = proxyState.getRow$realm().getColumnKey(fieldName);\n        try {\n            return proxyState.getRow$realm().getDouble(columnKey);\n        } catch (IllegalArgumentException e) {\n            checkFieldType(fieldName, columnKey, RealmFieldType.DOUBLE);\n            throw e;\n        }\n    }\n\n    /**\n     * Returns the {@code byte[]} value for a given field.\n     *\n     * @param fieldName the name of the field.\n     * @return the byte[] value.\n     * @throws IllegalArgumentException if field name doesn't exist or it doesn't contain binary data.\n     */\n    public byte[] getBlob(String fieldName) {\n        proxyState.getRealm$realm().checkIfValid();\n\n        long columnKey = proxyState.getRow$realm().getColumnKey(fieldName);\n        try {\n            return proxyState.getRow$realm().getBinaryByteArray(columnKey);\n        } catch (IllegalArgumentException e) {\n            checkFieldType(fieldName, columnKey, RealmFieldType.BINARY);\n            throw e;\n        }\n    }\n\n    /**\n     * Returns the {@code String} value for a given field.\n     *\n     * @param fieldName the name of the field.\n     * @return the String value.\n     * @throws IllegalArgumentException if field name doesn't exist or it doesn't contain Strings.\n     */\n    public String getString(String fieldName) {\n        proxyState.getRealm$realm().checkIfValid();\n\n        long columnKey = proxyState.getRow$realm().getColumnKey(fieldName);\n        try {\n            return proxyState.getRow$realm().getString(columnKey);\n        } catch (IllegalArgumentException e) {\n            checkFieldType(fieldName, columnKey, RealmFieldType.STRING);\n            throw e;\n        }\n    }\n\n    /**\n     * Returns the {@code Date} value for a given field.\n     *\n     * @param fieldName the name of the field.\n     * @return the Date value.\n     * @throws IllegalArgumentException if field name doesn't exist or it doesn't contain Dates.\n     */\n    public Date getDate(String fieldName) {\n        proxyState.getRealm$realm().checkIfValid();\n\n        long columnKey = proxyState.getRow$realm().getColumnKey(fieldName);\n        checkFieldType(fieldName, columnKey, RealmFieldType.DATE);\n        if (proxyState.getRow$realm().isNull(columnKey)) {\n            return null;\n        } else {\n            return proxyState.getRow$realm().getDate(columnKey);\n        }\n    }\n\n    /**\n     * Returns the {@code Decimal128} value for a given field.\n     *\n     * @param fieldName the name of the field.\n     * @return the Decimal128 value.\n     * @throws IllegalArgumentException if field name doesn't exist or it doesn't contain Decimal128.\n     */\n    public Decimal128 getDecimal128(String fieldName) {\n        proxyState.getRealm$realm().checkIfValid();\n\n        long columnKey = proxyState.getRow$realm().getColumnKey(fieldName);\n        checkFieldType(fieldName, columnKey, RealmFieldType.DECIMAL128);\n        if (proxyState.getRow$realm().isNull(columnKey)) {\n            return null;\n        } else {\n            return proxyState.getRow$realm().getDecimal128(columnKey);\n        }\n    }\n\n    /**\n     * Returns the {@code ObjectId} value for a given field.\n     *\n     * @param fieldName the name of the field.\n     * @return the ObjectId value.\n     * @throws IllegalArgumentException if field name doesn't exist or it doesn't contain ObjectId.\n     */\n    public ObjectId getObjectId(String fieldName) {\n        proxyState.getRealm$realm().checkIfValid();\n\n        long columnKey = proxyState.getRow$realm().getColumnKey(fieldName);\n        checkFieldType(fieldName, columnKey, RealmFieldType.OBJECT_ID);\n        if (proxyState.getRow$realm().isNull(columnKey)) {\n            return null;\n        } else {\n            return proxyState.getRow$realm().getObjectId(columnKey);\n        }\n    }\n\n    /**\n     * Returns the {@code RealmAny} value for a given field.\n     *\n     * @param fieldName the name of the field.\n     * @return the RealmAny value.\n     * @throws IllegalArgumentException if field name doesn't exist or it doesn't contain RealmAny.\n     */\n    public RealmAny getRealmAny(String fieldName) {\n        proxyState.getRealm$realm().checkIfValid();\n\n        long columnKey = proxyState.getRow$realm().getColumnKey(fieldName);\n        checkFieldType(fieldName, columnKey, RealmFieldType.MIXED);\n\n        return getRealmAny(columnKey);\n    }\n\n    /**\n     * Returns the {@code UUID} value for a given field.\n     *\n     * @param fieldName the name of the field.\n     * @return the UUID value.\n     * @throws IllegalArgumentException if field name doesn't exist or it doesn't contain UUID.\n     */\n    public UUID getUUID(String fieldName) {\n        proxyState.getRealm$realm().checkIfValid();\n\n        long columnKey = proxyState.getRow$realm().getColumnKey(fieldName);\n        checkFieldType(fieldName, columnKey, RealmFieldType.UUID);\n        if (proxyState.getRow$realm().isNull(columnKey)) {\n            return null;\n        } else {\n            return proxyState.getRow$realm().getUUID(columnKey);\n        }\n    }\n\n    /**\n     * Returns the object being linked to from this field.\n     *\n     * @param fieldName the name of the field.\n     * @return the {@link DynamicRealmObject} representation of the linked object or {@code null} if no object is linked.\n     * @throws IllegalArgumentException if field name doesn't exist or it doesn't contain links to other objects.\n     */\n    @Nullable\n    public DynamicRealmObject getObject(String fieldName) {\n        proxyState.getRealm$realm().checkIfValid();\n\n        long columnKey = proxyState.getRow$realm().getColumnKey(fieldName);\n        checkFieldType(fieldName, columnKey, RealmFieldType.OBJECT);\n        if (proxyState.getRow$realm().isNullLink(columnKey)) {\n            return null;\n        } else {\n            long linkObjectKey = proxyState.getRow$realm().getLink(columnKey);\n            CheckedRow linkRow = proxyState.getRow$realm().getTable().getLinkTarget(columnKey).getCheckedRow(linkObjectKey);\n            return new DynamicRealmObject(proxyState.getRealm$realm(), linkRow);\n        }\n    }\n\n    /**\n     * Returns the {@link RealmList} of {@link DynamicRealmObject}s being linked from the given field.\n     * <p>\n     * If the list contains primitive types, use {@link #getList(String, Class)} instead.\n     *\n     * @param fieldName the name of the field.\n     * @return the {@link RealmList} data for this field.\n     * @throws IllegalArgumentException if field name doesn't exist or it doesn't contain a list of objects.\n     */\n    public RealmList<DynamicRealmObject> getList(String fieldName) {\n        proxyState.getRealm$realm().checkIfValid();\n\n        long columnKey = proxyState.getRow$realm().getColumnKey(fieldName);\n        try {\n            OsList osList = proxyState.getRow$realm().getModelList(columnKey);\n            //noinspection ConstantConditions\n            @Nonnull\n            String className = osList.getTargetTable().getClassName();\n            return new RealmList<>(className, osList, proxyState.getRealm$realm());\n        } catch (IllegalArgumentException e) {\n            checkFieldType(fieldName, columnKey, RealmFieldType.LIST);\n            throw e;\n        }\n    }\n\n    /**\n     * Returns the {@link RealmList} containing only primitive values.\n     *\n     * <p>\n     * If the list contains references to other Realm objects, use {@link #getList(String)} instead.\n     *\n     * @param fieldName     the name of the field.\n     * @param primitiveType the type of elements in the list. Only primitive types are supported.\n     * @return the {@link RealmList} data for this field.\n     * @throws IllegalArgumentException if field name doesn't exist or it doesn't contain a list of primitive objects.\n     */\n    public <E> RealmList<E> getList(String fieldName, Class<E> primitiveType) {\n        proxyState.getRealm$realm().checkIfValid();\n\n        if (primitiveType == null) {\n            throw new IllegalArgumentException(\"Non-null 'primitiveType' required.\");\n        }\n        long columnKey = proxyState.getRow$realm().getColumnKey(fieldName);\n        RealmFieldType realmType = primitiveTypeToRealmFieldType(CollectionType.LIST, primitiveType);\n        try {\n            OsList osList = proxyState.getRow$realm().getValueList(columnKey, realmType);\n            return new RealmList<>(primitiveType, osList, proxyState.getRealm$realm());\n        } catch (IllegalArgumentException e) {\n            checkFieldType(fieldName, columnKey, realmType);\n            throw e;\n        }\n    }\n\n    /**\n     * Returns the {@link RealmDictionary} of {@link DynamicRealmObject}s being linked from the given field.\n     * <p>\n     * If the dictionary contains primitive types, use {@link #getDictionary(String, Class)} instead.\n     *\n     * @param fieldName the name of the field.\n     * @return the {@link RealmDictionary} data for this field.\n     * @throws IllegalArgumentException if field name doesn't exist or it doesn't contain a dictionary of objects.\n     */\n    public RealmDictionary<DynamicRealmObject> getDictionary(String fieldName) {\n        proxyState.getRealm$realm().checkIfValid();\n\n        long columnKey = proxyState.getRow$realm().getColumnKey(fieldName);\n        try {\n            OsMap osMap = proxyState.getRow$realm().getModelMap(columnKey);\n            //noinspection ConstantConditions\n            @Nonnull\n            String className = osMap.getTargetTable().getClassName();\n            return new RealmDictionary<>(proxyState.getRealm$realm(), osMap, className);\n        } catch (IllegalArgumentException e) {\n            checkFieldType(fieldName, columnKey, RealmFieldType.STRING_TO_LINK_MAP);\n            throw e;\n        }\n    }\n\n    /**\n     * Returns the {@link RealmDictionary} containing only primitive values.\n     *\n     * <p>\n     * If the dictionary contains references to other Realm objects, use {@link #getDictionary(String)} instead.\n     *\n     * @param fieldName     the name of the field.\n     * @param primitiveType the type of elements in the dictionary. Only primitive types are supported.\n     * @return the {@link RealmDictionary} data for this field.\n     * @throws IllegalArgumentException if field name doesn't exist or it doesn't contain a dictionary of primitive objects.\n     */\n    public <E> RealmDictionary<E> getDictionary(String fieldName, Class<E> primitiveType) {\n        proxyState.getRealm$realm().checkIfValid();\n\n        if (primitiveType == null) {\n            throw new IllegalArgumentException(\"Non-null 'primitiveType' required.\");\n        }\n        long columnKey = proxyState.getRow$realm().getColumnKey(fieldName);\n        RealmFieldType realmType = primitiveTypeToRealmFieldType(CollectionType.DICTIONARY, primitiveType);\n        try {\n            OsMap osMap = proxyState.getRow$realm().getValueMap(columnKey, realmType);\n            return new RealmDictionary<>(proxyState.getRealm$realm(), osMap, primitiveType);\n        } catch (IllegalArgumentException e) {\n            checkFieldType(fieldName, columnKey, realmType);\n            throw e;\n        }\n    }\n\n    /**\n     * Returns the {@link RealmSet} of {@link DynamicRealmObject}s being linked from the given field.\n     * <p>\n     * If the set contains primitive types, use {@link #getRealmSet(String, Class)} instead.\n     *\n     * @param fieldName the name of the field.\n     * @return the {@link RealmSet} data for this field.\n     * @throws IllegalArgumentException if field name doesn't exist or it doesn't contain a set of objects.\n     */\n    public RealmSet<DynamicRealmObject> getRealmSet(String fieldName) {\n        proxyState.getRealm$realm().checkIfValid();\n\n        long columnKey = proxyState.getRow$realm().getColumnKey(fieldName);\n        try {\n            OsSet osSet = proxyState.getRow$realm().getModelSet(columnKey);\n            //noinspection ConstantConditions\n            @Nonnull\n            String className = osSet.getTargetTable().getClassName();\n            return new RealmSet<>(proxyState.getRealm$realm(), osSet, className);\n        } catch (IllegalArgumentException e) {\n            checkFieldType(fieldName, columnKey, RealmFieldType.LINK_SET);\n            throw e;\n        }\n    }\n\n    /**\n     * Returns the {@link RealmSet} containing only primitive values.\n     *\n     * <p>\n     * If the set contains references to other Realm objects, use {@link #getRealmSet(String)} instead.\n     *\n     * @param fieldName     the name of the field.\n     * @param primitiveType the type of elements in the set. Only primitive types are supported.\n     * @return the {@link RealmSet} data for this field.\n     * @throws IllegalArgumentException if field name doesn't exist or it doesn't contain a set of primitive objects.\n     */\n    public <E> RealmSet<E> getRealmSet(String fieldName, Class<E> primitiveType) {\n        proxyState.getRealm$realm().checkIfValid();\n\n        if (primitiveType == null) {\n            throw new IllegalArgumentException(\"Non-null 'primitiveType' required.\");\n        }\n        long columnKey = proxyState.getRow$realm().getColumnKey(fieldName);\n        RealmFieldType realmType = primitiveTypeToRealmFieldType(CollectionType.SET, primitiveType);\n        try {\n            OsSet osSet = proxyState.getRow$realm().getValueSet(columnKey, realmType);\n            return new RealmSet<>(proxyState.getRealm$realm(), osSet, primitiveType);\n        } catch (IllegalArgumentException e) {\n            checkFieldType(fieldName, columnKey, realmType);\n            throw e;\n        }\n    }\n\n    private enum CollectionType {\n        LIST,\n        DICTIONARY,\n        SET\n    }\n\n    private <E> RealmFieldType primitiveTypeToRealmFieldType(CollectionType collectionType, Class<E> primitiveType) {\n        int nativeValue = primitiveTypeToCoreType(primitiveType);\n\n        switch (collectionType) {\n            case SET:\n                nativeValue += SET_OFFSET;\n                break;\n            case DICTIONARY:\n                nativeValue += DICTIONARY_OFFSET;\n                break;\n            case LIST:\n                nativeValue += LIST_OFFSET;\n                break;\n            default:\n                throw new IllegalArgumentException(\"Type not supported: \" + collectionType);\n        }\n\n        return RealmFieldType.fromNativeValue(nativeValue);\n    }\n\n    private <E> int primitiveTypeToCoreType(Class<E> primitiveType) {\n        if (primitiveType.equals(Integer.class)\n                || primitiveType.equals(Long.class)\n                || primitiveType.equals(Short.class)\n                || primitiveType.equals(Byte.class)) {\n            return RealmFieldTypeConstants.CORE_TYPE_VALUE_INTEGER;\n        } else if (primitiveType.equals(Boolean.class)) {\n            return RealmFieldTypeConstants.CORE_TYPE_VALUE_BOOLEAN;\n        } else if (primitiveType.equals(String.class)) {\n            return RealmFieldTypeConstants.CORE_TYPE_VALUE_STRING;\n        } else if (primitiveType.equals(byte[].class)) {\n            return RealmFieldTypeConstants.CORE_TYPE_VALUE_BINARY;\n        } else if (primitiveType.equals(Date.class)) {\n            return RealmFieldTypeConstants.CORE_TYPE_VALUE_DATE;\n        } else if (primitiveType.equals(Float.class)) {\n            return RealmFieldTypeConstants.CORE_TYPE_VALUE_FLOAT;\n        } else if (primitiveType.equals(Double.class)) {\n            return RealmFieldTypeConstants.CORE_TYPE_VALUE_DOUBLE;\n        } else if (primitiveType.equals(Decimal128.class)) {\n            return RealmFieldTypeConstants.CORE_TYPE_VALUE_DECIMAL128;\n        } else if (primitiveType.equals(ObjectId.class)) {\n            return RealmFieldTypeConstants.CORE_TYPE_VALUE_OBJECTID;\n        } else if (primitiveType.equals(UUID.class)) {\n            return RealmFieldTypeConstants.CORE_TYPE_VALUE_UUID;\n        } else if (primitiveType.equals(RealmAny.class)) {\n            return RealmFieldTypeConstants.CORE_TYPE_VALUE_MIXED;\n        } else {\n            throw new IllegalArgumentException(\"Unsupported element type. Only primitive types supported. Yours was: \" + primitiveType);\n        }\n    }\n\n    /**\n     * Checks if the value of a given field is {@code null}.\n     *\n     * @param fieldName the name of the field.\n     * @return {@code true} if field value is null, {@code false} otherwise.\n     * @throws IllegalArgumentException if field name doesn't exist.\n     */\n    public boolean isNull(String fieldName) {\n        proxyState.getRealm$realm().checkIfValid();\n\n        long columnKey = proxyState.getRow$realm().getColumnKey(fieldName);\n        RealmFieldType type = proxyState.getRow$realm().getColumnType(columnKey);\n        switch (type) {\n            case OBJECT:\n                return proxyState.getRow$realm().isNullLink(columnKey);\n            case BOOLEAN:\n            case INTEGER:\n            case FLOAT:\n            case DOUBLE:\n            case STRING:\n            case BINARY:\n            case DATE:\n            case DECIMAL128:\n            case OBJECT_ID:\n            case MIXED:\n            case UUID:\n                return proxyState.getRow$realm().isNull(columnKey);\n            case LIST:\n            case LINKING_OBJECTS:\n            case INTEGER_LIST:\n            case BOOLEAN_LIST:\n            case STRING_LIST:\n            case BINARY_LIST:\n            case DATE_LIST:\n            case FLOAT_LIST:\n            case DOUBLE_LIST:\n            case DECIMAL128_LIST:\n            case OBJECT_ID_LIST:\n            case UUID_LIST:\n            case MIXED_LIST:\n                // fall through\n            default:\n                return false;\n        }\n    }\n\n    /**\n     * Checks whether an object has the given field or not.\n     *\n     * @param fieldName field name to check.\n     * @return {@code true} if the object has a field with the given name, {@code false} otherwise.\n     */\n    public boolean hasField(String fieldName) {\n        proxyState.getRealm$realm().checkIfValid();\n\n        //noinspection SimplifiableIfStatement,ConstantConditions\n        if (fieldName == null || fieldName.isEmpty()) {\n            return false;\n        }\n        return proxyState.getRow$realm().hasColumn(fieldName);\n    }\n\n    /**\n     * Returns the list of field names on this object.\n     *\n     * @return list of field names on this objects or the empty list if the object doesn't have any fields.\n     */\n    public String[] getFieldNames() {\n        proxyState.getRealm$realm().checkIfValid();\n        return proxyState.getRow$realm().getColumnNames();\n    }\n\n    /**\n     * Sets the value for the given field. This method will automatically try to convert numbers and\n     * booleans that are given as {@code String} to their appropriate type. For example {@code \"10\"}\n     * will be converted to {@code 10} if the field type is {@code int}.\n     * <p>\n     * Using the typed setters will be faster than using this method.\n     *\n     * @throws IllegalArgumentException if field name doesn't exist or if the input value cannot be converted\n     *                                  to the appropriate input type.\n     * @throws NumberFormatException    if a String based number cannot be converted properly.\n     * @throws RealmException           if the field is a {@link io.realm.annotations.PrimaryKey} field.\n     */\n    @SuppressWarnings(\"unchecked\")\n    public void set(String fieldName, Object value) {\n        proxyState.getRealm$realm().checkIfValid();\n\n        boolean isString = (value instanceof String);\n        String strValue = isString ? (String) value : null;\n\n        // Does implicit conversion if needed.\n        long columnKey = proxyState.getRow$realm().getColumnKey(fieldName);\n        RealmFieldType type = proxyState.getRow$realm().getColumnType(columnKey);\n        if (isString && type != RealmFieldType.STRING) {\n            switch (type) {\n                case BOOLEAN:\n                    value = Boolean.parseBoolean(strValue);\n                    break;\n                case INTEGER:\n                    value = Long.parseLong(strValue);\n                    break;\n                case FLOAT:\n                    value = Float.parseFloat(strValue);\n                    break;\n                case DOUBLE:\n                    value = Double.parseDouble(strValue);\n                    break;\n                case DATE:\n                    value = JsonUtils.stringToDate(strValue);\n                    break;\n                case DECIMAL128:\n                    value = Decimal128.parse(strValue);\n                    break;\n                case OBJECT_ID:\n                    value = new ObjectId(strValue);\n                    break;\n                case UUID:\n                    value = UUID.fromString(strValue);\n                    break;\n                case MIXED:\n                    value = RealmAny.valueOf(strValue);\n                    break;\n                default:\n                    throw new IllegalArgumentException(String.format(Locale.US,\n                            \"Field %s is not a String field, \" +\n                                    \"and the provide value could not be automatically converted: %s. Use a typed\" +\n                                    \"setter instead\", fieldName, value));\n            }\n        }\n\n        if (value == null) {\n            setNull(fieldName);\n        } else {\n            setValue(fieldName, value);\n        }\n    }\n\n    // Automatically finds the appropriate setter based on the objects type.\n    private void setValue(String fieldName, Object value) {\n        Class<?> valueClass = value.getClass();\n        if (valueClass == Boolean.class) {\n            setBoolean(fieldName, (Boolean) value);\n        } else if (valueClass == Short.class) {\n            setShort(fieldName, (Short) value);\n        } else if (valueClass == Integer.class) {\n            setInt(fieldName, (Integer) value);\n        } else if (valueClass == Long.class) {\n            setLong(fieldName, (Long) value);\n        } else if (valueClass == Byte.class) {\n            setByte(fieldName, (Byte) value);\n        } else if (valueClass == Float.class) {\n            setFloat(fieldName, (Float) value);\n        } else if (valueClass == Double.class) {\n            setDouble(fieldName, (Double) value);\n        } else if (valueClass == String.class) {\n            setString(fieldName, (String) value);\n        } else if (value instanceof Date) {\n            setDate(fieldName, (Date) value);\n        } else if (value instanceof byte[]) {\n            setBlob(fieldName, (byte[]) value);\n        } else if (valueClass == DynamicRealmObject.class) {\n            setObject(fieldName, (DynamicRealmObject) value);\n        } else if (valueClass == RealmList.class) {\n            RealmList<?> list = (RealmList<?>) value;\n            setList(fieldName, list);\n        } else if (valueClass == Decimal128.class) {\n            setDecimal128(fieldName, (Decimal128) value);\n        } else if (valueClass == ObjectId.class) {\n            setObjectId(fieldName, (ObjectId) value);\n        } else if (valueClass == UUID.class) {\n            setUUID(fieldName, (UUID) value);\n        } else if (valueClass == RealmAny.class) {\n            setRealmAny(fieldName, (RealmAny) value);\n        } else {\n            throw new IllegalArgumentException(\"Value is of an type not supported: \" + value.getClass());\n        }\n    }\n\n    /**\n     * Sets the {@code boolean} value of the given field.\n     *\n     * @param fieldName field name to update.\n     * @param value     value to insert.\n     * @throws IllegalArgumentException if field name doesn't exist or field isn't a boolean field.\n     */\n    public void setBoolean(String fieldName, boolean value) {\n        proxyState.getRealm$realm().checkIfValid();\n\n        long columnKey = proxyState.getRow$realm().getColumnKey(fieldName);\n        proxyState.getRow$realm().setBoolean(columnKey, value);\n    }\n\n    /**\n     * Sets the {@code short} value of the given field.\n     *\n     * @param fieldName field name.\n     * @param value     value to insert.\n     * @throws IllegalArgumentException if field name doesn't exist or field isn't an integer field.\n     * @throws RealmException           if the field is a {@link io.realm.annotations.PrimaryKey} field.\n     */\n    public void setShort(String fieldName, short value) {\n        proxyState.getRealm$realm().checkIfValid();\n\n        checkIsPrimaryKey(fieldName);\n        long columnKey = proxyState.getRow$realm().getColumnKey(fieldName);\n        proxyState.getRow$realm().setLong(columnKey, value);\n    }\n\n    /**\n     * Sets the {@code int} value of the given field.\n     *\n     * @param fieldName field name to update.\n     * @param value     value to insert.\n     * @throws IllegalArgumentException if field name doesn't exist or field isn't an integer field.\n     * @throws RealmException           if the field is a {@link io.realm.annotations.PrimaryKey} field.\n     */\n    public void setInt(String fieldName, int value) {\n        proxyState.getRealm$realm().checkIfValid();\n\n        checkIsPrimaryKey(fieldName);\n        long columnKey = proxyState.getRow$realm().getColumnKey(fieldName);\n        proxyState.getRow$realm().setLong(columnKey, value);\n    }\n\n    /**\n     * Sets the {@code long} value of the given field.\n     *\n     * @param fieldName field name.\n     * @param value     value to insert.\n     * @throws IllegalArgumentException if field name doesn't exist or field isn't an integer field.\n     * @throws RealmException           if the field is a {@link io.realm.annotations.PrimaryKey} field.\n     */\n    public void setLong(String fieldName, long value) {\n        proxyState.getRealm$realm().checkIfValid();\n\n        checkIsPrimaryKey(fieldName);\n        long columnKey = proxyState.getRow$realm().getColumnKey(fieldName);\n        proxyState.getRow$realm().setLong(columnKey, value);\n    }\n\n    /**\n     * Sets the {@code byte} value of the given field.\n     *\n     * @param fieldName field name.\n     * @param value     value to insert.\n     * @throws IllegalArgumentException if field name doesn't exist or field isn't an integer field.\n     * @throws RealmException           if the field is a {@link io.realm.annotations.PrimaryKey} field.\n     */\n    public void setByte(String fieldName, byte value) {\n        proxyState.getRealm$realm().checkIfValid();\n\n        checkIsPrimaryKey(fieldName);\n        long columnKey = proxyState.getRow$realm().getColumnKey(fieldName);\n        proxyState.getRow$realm().setLong(columnKey, value);\n    }\n\n    /**\n     * Sets the {@code float} value of the given field.\n     *\n     * @param fieldName field name.\n     * @param value     value to insert.\n     * @throws IllegalArgumentException if field name doesn't exist or field isn't a float field.\n     */\n    public void setFloat(String fieldName, float value) {\n        proxyState.getRealm$realm().checkIfValid();\n\n        long columnKey = proxyState.getRow$realm().getColumnKey(fieldName);\n        proxyState.getRow$realm().setFloat(columnKey, value);\n    }\n\n    /**\n     * Sets the {@code double} value of the given field.\n     *\n     * @param fieldName field name.\n     * @param value     value to insert.\n     * @throws IllegalArgumentException if field name doesn't exist or field isn't a double field.\n     */\n    public void setDouble(String fieldName, double value) {\n        proxyState.getRealm$realm().checkIfValid();\n\n        long columnKey = proxyState.getRow$realm().getColumnKey(fieldName);\n        proxyState.getRow$realm().setDouble(columnKey, value);\n    }\n\n    /**\n     * Sets the {@code String} value of the given field.\n     *\n     * @param fieldName field name.\n     * @param value     value to insert.\n     * @throws IllegalArgumentException if field name doesn't exist or field isn't a String field.\n     * @throws RealmException           if the field is a {@link io.realm.annotations.PrimaryKey} field.\n     */\n    public void setString(String fieldName, @Nullable String value) {\n        proxyState.getRealm$realm().checkIfValid();\n\n        checkIsPrimaryKey(fieldName);\n        long columnKey = proxyState.getRow$realm().getColumnKey(fieldName);\n        proxyState.getRow$realm().setString(columnKey, value);\n    }\n\n    /**\n     * Sets the binary value of the given field.\n     *\n     * @param fieldName field name.\n     * @param value     value to insert.\n     * @throws IllegalArgumentException if field name doesn't exist or field isn't a binary field.\n     */\n    public void setBlob(String fieldName, @Nullable byte[] value) {\n        proxyState.getRealm$realm().checkIfValid();\n\n        long columnKey = proxyState.getRow$realm().getColumnKey(fieldName);\n        proxyState.getRow$realm().setBinaryByteArray(columnKey, value);\n    }\n\n    /**\n     * Sets the {@code Date} value of the given field.\n     *\n     * @param fieldName field name.\n     * @param value     value to insert.\n     * @throws IllegalArgumentException if field name doesn't exist or field isn't a Date field.\n     */\n    public void setDate(String fieldName, @Nullable Date value) {\n        proxyState.getRealm$realm().checkIfValid();\n\n        long columnKey = proxyState.getRow$realm().getColumnKey(fieldName);\n        if (value == null) {\n            proxyState.getRow$realm().setNull(columnKey);\n        } else {\n            proxyState.getRow$realm().setDate(columnKey, value);\n        }\n    }\n\n    /**\n     * Sets the {@code Decimal128} value of the given field.\n     *\n     * @param fieldName field name.\n     * @param value     value to insert.\n     * @throws IllegalArgumentException if field name doesn't exist or field isn't a Decimal128 field.\n     */\n    public void setDecimal128(String fieldName, @Nullable Decimal128 value) {\n        proxyState.getRealm$realm().checkIfValid();\n\n        long columnKey = proxyState.getRow$realm().getColumnKey(fieldName);\n        if (value == null) {\n            proxyState.getRow$realm().setNull(columnKey);\n        } else {\n            proxyState.getRow$realm().setDecimal128(columnKey, value);\n        }\n    }\n\n    /**\n     * Sets the {@code ObjectId} value of the given field.\n     *\n     * @param fieldName field name.\n     * @param value     value to insert.\n     * @throws IllegalArgumentException if field name doesn't exist or field isn't a ObjectId field.\n     */\n    public void setObjectId(String fieldName, @Nullable ObjectId value) {\n        proxyState.getRealm$realm().checkIfValid();\n\n        long columnKey = proxyState.getRow$realm().getColumnKey(fieldName);\n        if (value == null) {\n            proxyState.getRow$realm().setNull(columnKey);\n        } else {\n            proxyState.getRow$realm().setObjectId(columnKey, value);\n        }\n    }\n\n    /**\n     * Sets the {@code RealmAny} value of the given field.\n     *\n     * @param fieldName field name.\n     * @param value     value to insert.\n     * @throws IllegalArgumentException if field name doesn't exist or field isn't a RealmAny field.\n     */\n    public void setRealmAny(String fieldName, @Nullable RealmAny value) {\n        proxyState.getRealm$realm().checkIfValid();\n\n        long columnKey = proxyState.getRow$realm().getColumnKey(fieldName);\n        if (value == null) {\n            proxyState.getRow$realm().setNull(columnKey);\n        } else {\n            proxyState.getRow$realm().setRealmAny(columnKey, value.getNativePtr());\n        }\n    }\n\n    /**\n     * Sets the {@code UUID} value of the given field.\n     *\n     * @param fieldName field name.\n     * @param value     value to insert.\n     * @throws IllegalArgumentException if field name doesn't exist or field isn't a UUID field.\n     */\n    public void setUUID(String fieldName, @Nullable UUID value) {\n        proxyState.getRealm$realm().checkIfValid();\n\n        long columnKey = proxyState.getRow$realm().getColumnKey(fieldName);\n        if (value == null) {\n            proxyState.getRow$realm().setNull(columnKey);\n        } else {\n            proxyState.getRow$realm().setUUID(columnKey, value);\n        }\n    }\n\n    /**\n     * Sets a reference to another object on the given field.\n     *\n     * @param fieldName field name.\n     * @param value     object to link to.\n     * @throws IllegalArgumentException if field name doesn't exist, it doesn't link to other Realm objects, the type\n     *                                  of DynamicRealmObject doesn't match or it belongs to a different Realm.\n     */\n    public void setObject(String fieldName, @Nullable DynamicRealmObject value) {\n        proxyState.getRealm$realm().checkIfValid();\n\n        long columnKey = proxyState.getRow$realm().getColumnKey(fieldName);\n        if (value == null) {\n            proxyState.getRow$realm().nullifyLink(columnKey);\n        } else {\n            if (value.proxyState.getRealm$realm() == null || value.proxyState.getRow$realm() == null) {\n                throw new IllegalArgumentException(\"Cannot link to objects that are not part of the Realm.\");\n            }\n            if (proxyState.getRealm$realm() != value.proxyState.getRealm$realm()) {\n                throw new IllegalArgumentException(\"Cannot add an object from another Realm instance.\");\n            }\n            Table table = proxyState.getRow$realm().getTable().getLinkTarget(columnKey);\n            Table inputTable = value.proxyState.getRow$realm().getTable();\n            if (!table.hasSameSchema(inputTable)) {\n                throw new IllegalArgumentException(String.format(Locale.US,\n                        \"Type of object is wrong. Was %s, expected %s\",\n                        inputTable.getName(), table.getName()));\n            }\n            proxyState.getRow$realm().setLink(columnKey, value.proxyState.getRow$realm().getObjectKey());\n        }\n    }\n\n    /**\n     * Sets the reference to a {@link RealmList} on the given field.\n     * <p>\n     * This will copy all the elements in the list into Realm, but any further changes to the list\n     * will not be reflected in the Realm. Use {@link #getList(String)} in order to get a reference to\n     * the managed list.\n     *\n     * @param fieldName field name.\n     * @param list      list of objects. Must either be primitive types or {@link DynamicRealmObject}s.\n     * @throws IllegalArgumentException if field name doesn't exist, it is not a list field, the objects in the\n     *                                  list doesn't match the expected type or any Realm object in the list belongs to a different Realm.\n     */\n    public <E> void setList(String fieldName, RealmList<E> list) {\n        proxyState.getRealm$realm().checkIfValid();\n\n        //noinspection ConstantConditions\n        if (list == null) {\n            throw new IllegalArgumentException(\"Non-null 'list' required\");\n        }\n\n        // Find type of list in Realm\n        long columnKey = proxyState.getRow$realm().getColumnKey(fieldName);\n        final RealmFieldType columnType = proxyState.getRow$realm().getColumnType(columnKey);\n\n        switch (columnType) {\n            case LIST:\n                // Due to type erasure it is not possible to check the generic parameter,\n                // instead we try to see if the first element is of the wrong type in order\n                // to throw a better error message.\n                // Primitive types are checked inside `setModelList`\n                if (!list.isEmpty()) {\n                    E element = list.first();\n                    if (!(element instanceof DynamicRealmObject) && RealmModel.class.isAssignableFrom(element.getClass())) {\n                        throw new IllegalArgumentException(\"RealmList must contain `DynamicRealmObject's, not Java model classes.\");\n                    }\n                }\n                //noinspection unchecked\n                setModelList(fieldName, (RealmList<DynamicRealmObject>) list);\n                break;\n            case INTEGER_LIST:\n            case BOOLEAN_LIST:\n            case STRING_LIST:\n            case BINARY_LIST:\n            case DATE_LIST:\n            case FLOAT_LIST:\n            case DOUBLE_LIST:\n            case DECIMAL128_LIST:\n            case OBJECT_ID_LIST:\n            case UUID_LIST:\n            case MIXED_LIST:\n                setValueList(fieldName, list, columnType);\n                break;\n            default:\n                throw new IllegalArgumentException(String.format(\"Field '%s' is not a list but a %s\", fieldName, columnType));\n        }\n    }\n\n    private void setModelList(String fieldName, RealmList<DynamicRealmObject> list) {\n        long columnKey = proxyState.getRow$realm().getColumnKey(fieldName);\n        OsList osList = proxyState.getRow$realm().getModelList(columnKey);\n        Table linkTargetTable = osList.getTargetTable();\n        //noinspection ConstantConditions\n        @Nonnull final String linkTargetTableName = linkTargetTable.getClassName();\n\n        boolean typeValidated;\n        if (list.className == null && list.clazz == null) {\n            // Unmanaged lists don't know anything about the types they contain. They might even hold objects of\n            // multiple types :(, so we have to check each item in the list.\n            typeValidated = false;\n        } else {\n            String listType = list.className != null ? list.className\n                    : proxyState.getRealm$realm().getSchema().getTable(list.clazz).getClassName();\n            if (!linkTargetTableName.equals(listType)) {\n                throw new IllegalArgumentException(String.format(Locale.US,\n                        \"The elements in the list are not the proper type. \" +\n                                \"Was %s expected %s.\", listType, linkTargetTableName));\n            }\n            typeValidated = true;\n        }\n\n        final int listLength = list.size();\n        final long[] indices = new long[listLength];\n\n        for (int i = 0; i < listLength; i++) {\n            RealmObjectProxy obj = list.get(i);\n            if (obj.realmGet$proxyState().getRealm$realm() != proxyState.getRealm$realm()) {\n                throw new IllegalArgumentException(\"Each element in 'list' must belong to the same Realm instance.\");\n            }\n            if (!typeValidated && !linkTargetTable.hasSameSchema(obj.realmGet$proxyState().getRow$realm().getTable())) {\n                throw new IllegalArgumentException(String.format(Locale.US,\n                        \"Element at index %d is not the proper type. \" +\n                                \"Was '%s' expected '%s'.\",\n                        i,\n                        obj.realmGet$proxyState().getRow$realm().getTable().getClassName(),\n                        linkTargetTableName));\n            }\n            indices[i] = obj.realmGet$proxyState().getRow$realm().getObjectKey();\n        }\n\n        osList.removeAll();\n        for (int i = 0; i < listLength; i++) {\n            osList.addRow(indices[i]);\n        }\n    }\n\n    @SuppressWarnings(\"unchecked\")\n    private <E> void setValueList(String fieldName, RealmList<E> list, RealmFieldType primitiveType) {\n        long columnKey = proxyState.getRow$realm().getColumnKey(fieldName);\n        OsList osList = proxyState.getRow$realm().getValueList(columnKey, primitiveType);\n\n        Class<E> elementClass;\n        switch(primitiveType) {\n            case INTEGER_LIST: elementClass = (Class<E>) Long.class; break;\n            case BOOLEAN_LIST: elementClass = (Class<E>) Boolean.class; break;\n            case STRING_LIST: elementClass = (Class<E>) String.class; break;\n            case BINARY_LIST: elementClass = (Class<E>) byte[].class; break;\n            case DATE_LIST: elementClass = (Class<E>) Date.class; break;\n            case FLOAT_LIST: elementClass = (Class<E>) Float.class; break;\n            case DOUBLE_LIST: elementClass = (Class<E>) Double.class; break;\n            case DECIMAL128_LIST: elementClass = (Class<E>) Decimal128.class; break;\n            case OBJECT_ID_LIST: elementClass = (Class<E>) ObjectId.class; break;\n            case UUID_LIST: elementClass = (Class<E>) UUID.class; break;\n            case MIXED_LIST: elementClass = (Class<E>) RealmAny.class; break;\n            default:\n                throw new IllegalArgumentException(\"Unsupported type: \" + primitiveType);\n        }\n        final ManagedListOperator<?> operator = getOperator(proxyState.getRealm$realm(), osList, primitiveType, elementClass);\n\n        if (list.isManaged() && osList.size() == list.size()) {\n            // There is a chance that the source list and the target list are the same list in the same object.\n            // In this case, we can't use removeAll().\n            final int size = list.size();\n            final Iterator<?> iterator = list.iterator();\n            for (int i = 0; i < size; i++) {\n                @Nullable final Object value = iterator.next();\n                operator.set(i, value);\n            }\n        } else {\n            osList.removeAll();\n            for (Object value : list) {\n                operator.append(value);\n            }\n        }\n    }\n\n    private <E> ManagedListOperator<E> getOperator(BaseRealm realm, OsList osList, RealmFieldType valueListType, Class<E> valueClass) {\n        if (valueListType == RealmFieldType.STRING_LIST) {\n            //noinspection unchecked\n            return (ManagedListOperator<E>) new StringListOperator(realm, osList, (Class<String>) valueClass);\n        }\n        if (valueListType == RealmFieldType.INTEGER_LIST) {\n            return new LongListOperator<>(realm, osList, valueClass);\n        }\n        if (valueListType == RealmFieldType.BOOLEAN_LIST) {\n            //noinspection unchecked\n            return (ManagedListOperator<E>) new BooleanListOperator(realm, osList, (Class<Boolean>) valueClass);\n        }\n        if (valueListType == RealmFieldType.BINARY_LIST) {\n            //noinspection unchecked\n            return (ManagedListOperator<E>) new BinaryListOperator(realm, osList, (Class<byte[]>) valueClass);\n        }\n        if (valueListType == RealmFieldType.DOUBLE_LIST) {\n            //noinspection unchecked\n            return (ManagedListOperator<E>) new DoubleListOperator(realm, osList, (Class<Double>) valueClass);\n        }\n        if (valueListType == RealmFieldType.FLOAT_LIST) {\n            //noinspection unchecked\n            return (ManagedListOperator<E>) new FloatListOperator(realm, osList, (Class<Float>) valueClass);\n        }\n        if (valueListType == RealmFieldType.DATE_LIST) {\n            //noinspection unchecked\n            return (ManagedListOperator<E>) new DateListOperator(realm, osList, (Class<Date>) valueClass);\n        }\n        if (valueListType == RealmFieldType.DECIMAL128_LIST) {\n            //noinspection unchecked\n            return (ManagedListOperator<E>) new Decimal128ListOperator(realm, osList, (Class<Decimal128>) valueClass);\n        }\n        if (valueListType == RealmFieldType.OBJECT_ID_LIST) {\n            //noinspection unchecked\n            return (ManagedListOperator<E>) new ObjectIdListOperator(realm, osList, (Class<ObjectId>) valueClass);\n        }\n        if (valueListType == RealmFieldType.UUID_LIST) {\n            //noinspection unchecked\n            return (ManagedListOperator<E>) new UUIDListOperator(realm, osList, (Class<UUID>) valueClass);\n        }\n        if (valueListType == RealmFieldType.MIXED_LIST) {\n            //noinspection unchecked\n            return (ManagedListOperator<E>) new RealmAnyListOperator(realm, osList, (Class<RealmAny>) valueClass);\n        }\n        throw new IllegalArgumentException(\"Unexpected list type: \" + valueListType.name());\n    }\n\n    /**\n     * Sets the reference to a {@link RealmDictionary} on the given field.\n     * <p>\n     * This will copy all the elements in the dictionary into Realm, but any further changes to the dictionary\n     * will not be reflected in the Realm. Use {@link #getDictionary(String)} in order to get a reference to\n     * the managed dictionary.\n     *\n     * @param fieldName  field name.\n     * @param dictionary dictionary of objects. Must either be primitive types or {@link DynamicRealmObject}s.\n     * @throws IllegalArgumentException if field name doesn't exist, it is not a dictionary field, the objects in the\n     *                                  dictionary doesn't match the expected type or any Realm object in the dictionary\n     *                                  belongs to a different Realm.\n     */\n    public <E> void setDictionary(String fieldName, RealmDictionary<E> dictionary) {\n        proxyState.getRealm$realm().checkIfValid();\n\n        //noinspection ConstantConditions\n        if (dictionary == null) {\n            throw new IllegalArgumentException(\"Non-null 'dictionary' required\");\n        }\n\n        // Find type of list in Realm\n        long columnKey = proxyState.getRow$realm().getColumnKey(fieldName);\n        final RealmFieldType columnType = proxyState.getRow$realm().getColumnType(columnKey);\n\n        switch (columnType) {\n            case STRING_TO_INTEGER_MAP:\n            case STRING_TO_BOOLEAN_MAP:\n            case STRING_TO_STRING_MAP:\n            case STRING_TO_BINARY_MAP:\n            case STRING_TO_DATE_MAP:\n            case STRING_TO_FLOAT_MAP:\n            case STRING_TO_DOUBLE_MAP:\n            case STRING_TO_DECIMAL128_MAP:\n            case STRING_TO_OBJECT_ID_MAP:\n            case STRING_TO_UUID_MAP:\n            case STRING_TO_MIXED_MAP:\n                setValueDictionary(fieldName, dictionary, columnType);\n                break;\n            case STRING_TO_LINK_MAP:\n                //noinspection unchecked\n                setModelDictionary(fieldName, (RealmDictionary<DynamicRealmObject>) dictionary);\n                break;\n            default:\n                throw new IllegalArgumentException(String.format(\"Field '%s' is not a dictionary but a %s\", fieldName, columnType));\n        }\n    }\n\n    private void setModelDictionary(String fieldName, RealmDictionary<DynamicRealmObject> sourceDictionary) {\n        long columnKey = proxyState.getRow$realm().getColumnKey(fieldName);\n        OsMap osMap = proxyState.getRow$realm().getModelMap(columnKey);\n        Table linkTargetTable = osMap.getTargetTable();\n        //noinspection ConstantConditions\n        @Nonnull final String linkTargetTableName = linkTargetTable.getClassName();\n\n        boolean typeValidated;\n        if (!sourceDictionary.isManaged()) {\n            typeValidated = false;\n        } else {\n            String dictType = (sourceDictionary.getValueClassName() != null) ? sourceDictionary.getValueClassName()\n                    : proxyState.getRealm$realm().getSchema().getTable(sourceDictionary.getValueClass()).getClassName();\n            if (!linkTargetTableName.equals(dictType)) {\n                throw new IllegalArgumentException(String.format(Locale.US,\n                        \"The elements in the dictionary are not the proper type. \" +\n                                \"Was %s expected %s.\", dictType, linkTargetTableName));\n            }\n            typeValidated = true;\n        }\n\n        // This dictionary holds all the validated row pointers\n        RealmDictionary<Long> auxiliaryDictionary = new RealmDictionary<>();\n\n        // Now we must validate that the dictionary contains valid objects\n        for (Map.Entry<String, DynamicRealmObject> entry : sourceDictionary.entrySet()) {\n            RealmObjectProxy obj = entry.getValue();\n            if (obj.realmGet$proxyState().getRealm$realm() != proxyState.getRealm$realm()) {\n                throw new IllegalArgumentException(\"Each element in 'dictionary' must belong to the same Realm instance.\");\n            }\n            if (!typeValidated && !linkTargetTable.hasSameSchema(obj.realmGet$proxyState().getRow$realm().getTable())) {\n                throw new IllegalArgumentException(String.format(Locale.US,\n                        \"Element with key %s is not the proper type. \" +\n                                \"Was '%s' expected '%s'.\",\n                        entry.getKey(),\n                        obj.realmGet$proxyState().getRow$realm().getTable().getClassName(),\n                        linkTargetTableName));\n            }\n            long row = obj.realmGet$proxyState().getRow$realm().getObjectKey();\n            auxiliaryDictionary.put(entry.getKey(), row);\n        }\n\n        // We have validated the source dictionary and we can safely clear the target dictionary\n        osMap.clear();\n        for (Map.Entry<String, Long> entry : auxiliaryDictionary.entrySet()) {\n            osMap.putRow(entry.getKey(), entry.getValue());\n        }\n    }\n\n    @SuppressWarnings(\"unchecked\")\n    private <E> void setValueDictionary(String fieldName, RealmDictionary<E> sourceDictionary, RealmFieldType primitiveType) {\n        long columnKey = proxyState.getRow$realm().getColumnKey(fieldName);\n        OsMap osMap = proxyState.getRow$realm().getValueMap(columnKey, primitiveType);\n\n        Class<E> elementClass;\n        switch(primitiveType) {\n            case STRING_TO_INTEGER_MAP: elementClass = (Class<E>) Long.class; break;\n            case STRING_TO_BOOLEAN_MAP: elementClass = (Class<E>) Boolean.class; break;\n            case STRING_TO_STRING_MAP: elementClass = (Class<E>) String.class; break;\n            case STRING_TO_BINARY_MAP: elementClass = (Class<E>) byte[].class; break;\n            case STRING_TO_DATE_MAP: elementClass = (Class<E>) Date.class; break;\n            case STRING_TO_FLOAT_MAP: elementClass = (Class<E>) Float.class; break;\n            case STRING_TO_DOUBLE_MAP: elementClass = (Class<E>) Double.class; break;\n            case STRING_TO_DECIMAL128_MAP: elementClass = (Class<E>) Decimal128.class; break;\n            case STRING_TO_OBJECT_ID_MAP: elementClass = (Class<E>) ObjectId.class; break;\n            case STRING_TO_UUID_MAP: elementClass = (Class<E>) UUID.class; break;\n            case STRING_TO_MIXED_MAP: elementClass = (Class<E>) RealmAny.class; break;\n            default:\n                throw new IllegalArgumentException(\"Unsupported type: \" + primitiveType);\n        }\n\n        // Dictionary in the RealmObject\n        RealmDictionary<E> targetDictionary = new RealmDictionary<>(proxyState.getRealm$realm(), osMap, elementClass);\n\n        // We move the data in a auxiliary dictionary to prevent removing the values when the input and out dicts are\n        // the same.\n        RealmDictionary<E> auxiliaryDictionary = new RealmDictionary<>();\n        for (Map.Entry<String, E> entry : sourceDictionary.entrySet()) {\n            auxiliaryDictionary.put(entry.getKey(), entry.getValue());\n        }\n\n        // Now we can safely clear the target dictionary\n        osMap.clear();\n\n        // And now we move the data back in\n        for (Map.Entry<String, E> entry : auxiliaryDictionary.entrySet()) {\n            targetDictionary.put(entry.getKey(), entry.getValue());\n        }\n    }\n\n    /**\n     * Sets the reference to a {@link RealmSet} on the given field.\n     * <p>\n     * This will copy all the elements in the set into Realm, but any further changes to the set\n     * will not be reflected in the Realm. Use {@link #getRealmSet(String)} in order to get a reference to\n     * the managed set.\n     *\n     * @param fieldName field name.\n     * @param set       set of objects. Must either be primitive types or {@link DynamicRealmObject}s.\n     * @throws IllegalArgumentException if field name doesn't exist, it is not a set field, the objects in the\n     *                                  set doesn't match the expected type or any Realm object in the set\n     *                                  belongs to a different Realm.\n     */\n    public <E> void setRealmSet(String fieldName, RealmSet<E> set) {\n        proxyState.getRealm$realm().checkIfValid();\n\n        //noinspection ConstantConditions\n        if (set == null) {\n            throw new IllegalArgumentException(\"Non-null 'set' required\");\n        }\n\n        // Find type of list in Realm\n        long columnKey = proxyState.getRow$realm().getColumnKey(fieldName);\n        final RealmFieldType columnType = proxyState.getRow$realm().getColumnType(columnKey);\n\n        switch (columnType) {\n            case INTEGER_SET:\n            case BOOLEAN_SET:\n            case STRING_SET:\n            case BINARY_SET:\n            case DATE_SET:\n            case FLOAT_SET:\n            case DOUBLE_SET:\n            case DECIMAL128_SET:\n            case OBJECT_ID_SET:\n            case UUID_SET:\n            case MIXED_SET:\n                setValueSet(fieldName, set, columnType);\n                break;\n            case LINK_SET:\n                //noinspection unchecked\n                setModelSet(fieldName, (RealmSet<DynamicRealmObject>) set);\n                break;\n            default:\n                throw new IllegalArgumentException(String.format(\"Field '%s' is not a set but a %s\", fieldName, columnType));\n        }\n    }\n\n    private void setModelSet(String fieldName, RealmSet<DynamicRealmObject> sourceSet) {\n        long columnKey = proxyState.getRow$realm().getColumnKey(fieldName);\n        OsSet osSet = proxyState.getRow$realm().getModelSet(columnKey);\n        Table linkTargetTable = osSet.getTargetTable();\n        //noinspection ConstantConditions\n        @Nonnull final String linkTargetTableName = linkTargetTable.getClassName();\n\n        boolean typeValidated;\n        if (!sourceSet.isManaged()) {\n            typeValidated = false;\n        } else {\n            String setType = (sourceSet.getValueClassName() != null) ? sourceSet.getValueClassName()\n                    : proxyState.getRealm$realm().getSchema().getTable(sourceSet.getValueClass()).getClassName();\n            if (!linkTargetTableName.equals(setType)) {\n                throw new IllegalArgumentException(String.format(Locale.US,\n                        \"The elements in the set are not the proper type. \" +\n                                \"Was %s expected %s.\", setType, linkTargetTableName));\n            }\n            typeValidated = true;\n        }\n\n        // This set holds all the validated row pointers\n        RealmSet<Long> auxiliarySet = new RealmSet<>();\n\n        // Now we must validate that the set contains valid objects\n        for (DynamicRealmObject obj : sourceSet) {\n            if (obj.realmGet$proxyState().getRealm$realm() != proxyState.getRealm$realm()) {\n                throw new IllegalArgumentException(\"Each element in 'set' must belong to the same Realm instance.\");\n            }\n            if (!typeValidated && !linkTargetTable.hasSameSchema(obj.realmGet$proxyState().getRow$realm().getTable())) {\n                throw new IllegalArgumentException(String.format(Locale.US,\n                        \"Set contains an element with not the proper type. \" +\n                                \"Was '%s' expected '%s'.\",\n                        obj.realmGet$proxyState().getRow$realm().getTable().getClassName(),\n                        linkTargetTableName));\n            }\n            long row = obj.realmGet$proxyState().getRow$realm().getObjectKey();\n            auxiliarySet.add(row);\n        }\n\n        // We have validated the source set and we can safely clear the target set\n        osSet.clear();\n        for (Long row : auxiliarySet) {\n            osSet.addRow(row);\n        }\n    }\n\n    @SuppressWarnings(\"unchecked\")\n    private <E> void setValueSet(String fieldName, RealmSet<E> sourceSet, RealmFieldType primitiveType) {\n        long columnKey = proxyState.getRow$realm().getColumnKey(fieldName);\n        OsSet osSet = proxyState.getRow$realm().getValueSet(columnKey, primitiveType);\n\n        Class<E> elementClass;\n        switch(primitiveType) {\n            case INTEGER_SET: elementClass = (Class<E>) Number.class; break;\n            case BOOLEAN_SET: elementClass = (Class<E>) Boolean.class; break;\n            case STRING_SET: elementClass = (Class<E>) String.class; break;\n            case BINARY_SET: elementClass = (Class<E>) byte[].class; break;\n            case DATE_SET: elementClass = (Class<E>) Date.class; break;\n            case FLOAT_SET: elementClass = (Class<E>) Float.class; break;\n            case DOUBLE_SET: elementClass = (Class<E>) Double.class; break;\n            case DECIMAL128_SET: elementClass = (Class<E>) Decimal128.class; break;\n            case OBJECT_ID_SET: elementClass = (Class<E>) ObjectId.class; break;\n            case UUID_SET: elementClass = (Class<E>) UUID.class; break;\n            case MIXED_SET: elementClass = (Class<E>) RealmAny.class; break;\n            default:\n                throw new IllegalArgumentException(\"Unsupported type: \" + primitiveType);\n        }\n\n        // Set in the RealmObject\n        RealmSet<E> targetSet = new RealmSet<>(proxyState.getRealm$realm(), osSet, elementClass);\n\n        // We move the data in a auxiliary set to prevent removing the values when the input and out sets are\n        // the same.\n        RealmSet<E> auxiliarySet = new RealmSet<>();\n        auxiliarySet.addAll(sourceSet);\n\n        // Now we can safely clear the target set\n        osSet.clear();\n\n        // And now we move the data back in\n        targetSet.addAll(auxiliarySet);\n    }\n\n    /**\n     * Sets the value to {@code null} for the given field.\n     *\n     * @param fieldName field name.\n     * @throws IllegalArgumentException if field name doesn't exist, or the field isn't nullable.\n     * @throws RealmException           if the field is a {@link io.realm.annotations.PrimaryKey} field.\n     */\n    public void setNull(String fieldName) {\n        proxyState.getRealm$realm().checkIfValid();\n\n        long columnKey = proxyState.getRow$realm().getColumnKey(fieldName);\n        RealmFieldType type = proxyState.getRow$realm().getColumnType(columnKey);\n        if (type == RealmFieldType.OBJECT) {\n            proxyState.getRow$realm().nullifyLink(columnKey);\n        } else {\n            checkIsPrimaryKey(fieldName);\n            proxyState.getRow$realm().setNull(columnKey);\n        }\n    }\n\n    /**\n     * Returns the type of object. This will normally correspond to the name of a class that is extending\n     * {@link RealmObject}.\n     *\n     * @return this objects type.\n     */\n    public String getType() {\n        proxyState.getRealm$realm().checkIfValid();\n\n        return proxyState.getRow$realm().getTable().getClassName();\n    }\n\n    /**\n     * Returns the type used by the underlying storage engine to represent this field.\n     *\n     * @return the underlying type used by Realm to represent this field.\n     */\n    public RealmFieldType getFieldType(String fieldName) {\n        proxyState.getRealm$realm().checkIfValid();\n\n        long columnKey = proxyState.getRow$realm().getColumnKey(fieldName);\n        return proxyState.getRow$realm().getColumnType(columnKey);\n    }\n\n    private void checkFieldType(String fieldName, long columnIndex, RealmFieldType expectedType) {\n        RealmFieldType columnType = proxyState.getRow$realm().getColumnType(columnIndex);\n        if (columnType != expectedType) {\n            String expectedIndefiniteVowel = \"\";\n            if (expectedType == RealmFieldType.INTEGER || expectedType == RealmFieldType.OBJECT) {\n                expectedIndefiniteVowel = \"n\";\n            }\n            String columnTypeIndefiniteVowel = \"\";\n            if (columnType == RealmFieldType.INTEGER || columnType == RealmFieldType.OBJECT) {\n                columnTypeIndefiniteVowel = \"n\";\n            }\n            throw new IllegalArgumentException(String.format(Locale.US,\n                    \"'%s' is not a%s '%s', but a%s '%s'.\",\n                    fieldName, expectedIndefiniteVowel, expectedType, columnTypeIndefiniteVowel, columnType));\n        }\n    }\n\n    /**\n     * Returns a hash code value for the {@link DynamicRealmObject} object.\n     * <p>\n     * By the general contract of {@link Object#hashCode()}, any two objects for which {@link #equals}\n     * returns {@code true} must return the same hash code value.\n     * <p>\n     * Note that a {@link RealmObject} is a live object, and it might be updated by changes from\n     * other threads. This means that a hash code value of the object is not stable, and the value\n     * should be neither used as a key in HashMap nor saved in HashSet.\n     *\n     * @return a hash code value for the object.\n     * @see #equals\n     */\n    @Override\n    public int hashCode() {\n        proxyState.getRealm$realm().checkIfValid();\n\n        String realmName = proxyState.getRealm$realm().getPath();\n        String tableName = proxyState.getRow$realm().getTable().getName();\n        long rowIndex = proxyState.getRow$realm().getObjectKey();\n\n        int result = 17;\n        result = 31 * result + ((realmName != null) ? realmName.hashCode() : 0);\n        result = 31 * result + ((tableName != null) ? tableName.hashCode() : 0);\n        result = 31 * result + (int) (rowIndex ^ (rowIndex >>> 32));\n        return result;\n    }\n\n    @Override\n    public boolean equals(Object o) {\n        proxyState.getRealm$realm().checkIfValid();\n\n        if (this == o) {\n            return true;\n        }\n        if (o == null || getClass() != o.getClass()) {\n            return false;\n        }\n\n        DynamicRealmObject other = (DynamicRealmObject) o;\n\n        String path = proxyState.getRealm$realm().getPath();\n        String otherPath = other.proxyState.getRealm$realm().getPath();\n        if (path != null ? !path.equals(otherPath) : otherPath != null) {\n            return false;\n        }\n\n        String tableName = proxyState.getRow$realm().getTable().getName();\n        String otherTableName = other.proxyState.getRow$realm().getTable().getName();\n        //noinspection SimplifiableIfStatement\n        if (tableName != null ? !tableName.equals(otherTableName) : otherTableName != null) {\n            return false;\n        }\n\n        return proxyState.getRow$realm().getObjectKey() == other.proxyState.getRow$realm().getObjectKey();\n    }\n\n    @Override\n    public String toString() {\n        proxyState.getRealm$realm().checkIfValid();\n\n        if (!proxyState.getRow$realm().isValid()) {\n            return \"Invalid object\";\n        }\n\n        final String className = proxyState.getRow$realm().getTable().getClassName();\n        StringBuilder sb = new StringBuilder(className + \" = dynamic[\");\n        String[] fields = getFieldNames();\n        for (String field : fields) {\n            long columnKey = proxyState.getRow$realm().getColumnKey(field);\n            RealmFieldType type = proxyState.getRow$realm().getColumnType(columnKey);\n            sb.append(\"{\");\n            sb.append(field).append(\":\");\n            switch (type) {\n                case BOOLEAN:\n                    sb.append(proxyState.getRow$realm().isNull(columnKey) ? \"null\" : proxyState.getRow$realm().getBoolean(columnKey));\n                    break;\n                case INTEGER:\n                    sb.append(proxyState.getRow$realm().isNull(columnKey) ? \"null\" : proxyState.getRow$realm().getLong(columnKey));\n                    break;\n                case FLOAT:\n                    sb.append(proxyState.getRow$realm().isNull(columnKey) ? \"null\" : proxyState.getRow$realm().getFloat(columnKey));\n                    break;\n                case DOUBLE:\n                    sb.append(proxyState.getRow$realm().isNull(columnKey) ? \"null\" : proxyState.getRow$realm().getDouble(columnKey));\n                    break;\n                case STRING:\n                    sb.append(proxyState.getRow$realm().getString(columnKey));\n                    break;\n                case BINARY:\n                    sb.append(Arrays.toString(proxyState.getRow$realm().getBinaryByteArray(columnKey)));\n                    break;\n                case DATE:\n                    sb.append(proxyState.getRow$realm().isNull(columnKey) ? \"null\" : proxyState.getRow$realm().getDate(columnKey));\n                    break;\n                case DECIMAL128:\n                    sb.append(proxyState.getRow$realm().isNull(columnKey) ? \"null\" : proxyState.getRow$realm().getDecimal128(columnKey));\n                    break;\n                case OBJECT_ID:\n                    sb.append(proxyState.getRow$realm().isNull(columnKey) ? \"null\" : proxyState.getRow$realm().getObjectId(columnKey));\n                    break;\n                case UUID:\n                    sb.append(proxyState.getRow$realm().isNull(columnKey) ? \"null\" : proxyState.getRow$realm().getUUID(columnKey));\n                    break;\n                case MIXED:\n                    sb.append(proxyState.getRow$realm().isNull(columnKey) ? \"null\" : getRealmAny(columnKey));\n                    break;\n                case OBJECT:\n                    sb.append(proxyState.getRow$realm().isNullLink(columnKey)\n                            ? \"null\"\n                            : proxyState.getRow$realm().getTable().getLinkTarget(columnKey).getClassName());\n                    break;\n                case LIST: {\n                    String targetClassName = proxyState.getRow$realm().getTable().getLinkTarget(columnKey).getClassName();\n                    sb.append(String.format(Locale.US, \"RealmList<%s>[%s]\", targetClassName, proxyState.getRow$realm().getModelList(columnKey).size()));\n                    break;\n                }\n                case INTEGER_LIST:\n                    sb.append(String.format(Locale.US, \"RealmList<Long>[%s]\", proxyState.getRow$realm().getValueList(columnKey, type).size()));\n                    break;\n                case BOOLEAN_LIST:\n                    sb.append(String.format(Locale.US, \"RealmList<Boolean>[%s]\", proxyState.getRow$realm().getValueList(columnKey, type).size()));\n                    break;\n                case STRING_LIST:\n                    sb.append(String.format(Locale.US, \"RealmList<String>[%s]\", proxyState.getRow$realm().getValueList(columnKey, type).size()));\n                    break;\n                case BINARY_LIST:\n                    sb.append(String.format(Locale.US, \"RealmList<byte[]>[%s]\", proxyState.getRow$realm().getValueList(columnKey, type).size()));\n                    break;\n                case DATE_LIST:\n                    sb.append(String.format(Locale.US, \"RealmList<Date>[%s]\", proxyState.getRow$realm().getValueList(columnKey, type).size()));\n                    break;\n                case FLOAT_LIST:\n                    sb.append(String.format(Locale.US, \"RealmList<Float>[%s]\", proxyState.getRow$realm().getValueList(columnKey, type).size()));\n                    break;\n                case DOUBLE_LIST:\n                    sb.append(String.format(Locale.US, \"RealmList<Double>[%s]\", proxyState.getRow$realm().getValueList(columnKey, type).size()));\n                    break;\n                case DECIMAL128_LIST:\n                    sb.append(String.format(Locale.US, \"RealmList<Decimal128>[%s]\", proxyState.getRow$realm().getValueList(columnKey, type).size()));\n                    break;\n                case OBJECT_ID_LIST:\n                    sb.append(String.format(Locale.US, \"RealmList<ObjectId>[%s]\", proxyState.getRow$realm().getValueList(columnKey, type).size()));\n                    break;\n                case UUID_LIST:\n                    sb.append(String.format(Locale.US, \"RealmList<UUID>[%s]\", proxyState.getRow$realm().getValueList(columnKey, type).size()));\n                    break;\n                case MIXED_LIST:\n                    sb.append(String.format(Locale.US, \"RealmList<RealmAny>[%s]\", proxyState.getRow$realm().getValueList(columnKey, type).size()));\n                    break;\n                case STRING_TO_INTEGER_MAP:\n                    sb.append(String.format(Locale.US, \"RealmDictionary<Long>[%s]\", proxyState.getRow$realm().getValueMap(columnKey, type).size()));\n                    break;\n                case STRING_TO_BOOLEAN_MAP:\n                    sb.append(String.format(Locale.US, \"RealmDictionary<Boolean>[%s]\", proxyState.getRow$realm().getValueMap(columnKey, type).size()));\n                    break;\n                case STRING_TO_STRING_MAP:\n                    sb.append(String.format(Locale.US, \"RealmDictionary<String>[%s]\", proxyState.getRow$realm().getValueMap(columnKey, type).size()));\n                    break;\n                case STRING_TO_BINARY_MAP:\n                    sb.append(String.format(Locale.US, \"RealmDictionary<byte[]>[%s]\", proxyState.getRow$realm().getValueMap(columnKey, type).size()));\n                    break;\n                case STRING_TO_DATE_MAP:\n                    sb.append(String.format(Locale.US, \"RealmDictionary<Date>[%s]\", proxyState.getRow$realm().getValueMap(columnKey, type).size()));\n                    break;\n                case STRING_TO_FLOAT_MAP:\n                    sb.append(String.format(Locale.US, \"RealmDictionary<Float>[%s]\", proxyState.getRow$realm().getValueMap(columnKey, type).size()));\n                    break;\n                case STRING_TO_DOUBLE_MAP:\n                    sb.append(String.format(Locale.US, \"RealmDictionary<Double>[%s]\", proxyState.getRow$realm().getValueMap(columnKey, type).size()));\n                    break;\n                case STRING_TO_DECIMAL128_MAP:\n                    sb.append(String.format(Locale.US, \"RealmDictionary<Decimal128>[%s]\", proxyState.getRow$realm().getValueMap(columnKey, type).size()));\n                    break;\n                case STRING_TO_OBJECT_ID_MAP:\n                    sb.append(String.format(Locale.US, \"RealmDictionary<ObjectId>[%s]\", proxyState.getRow$realm().getValueMap(columnKey, type).size()));\n                    break;\n                case STRING_TO_UUID_MAP:\n                    sb.append(String.format(Locale.US, \"RealmDictionary<UUID>[%s]\", proxyState.getRow$realm().getValueMap(columnKey, type).size()));\n                    break;\n                case STRING_TO_MIXED_MAP:\n                    sb.append(String.format(Locale.US, \"RealmDictionary<RealmAny>[%s]\", proxyState.getRow$realm().getValueMap(columnKey, type).size()));\n                    break;\n                case STRING_TO_LINK_MAP: {\n                    String targetClassName = proxyState.getRow$realm().getTable().getLinkTarget(columnKey).getClassName();\n                    sb.append(String.format(Locale.US, \"RealmDictionary<%s>[%s]\", targetClassName, proxyState.getRow$realm().getModelMap(columnKey).size()));\n                    break;\n                }\n                case INTEGER_SET:\n                    sb.append(String.format(Locale.US, \"RealmSet<Long>[%s]\", proxyState.getRow$realm().getValueSet(columnKey, type).size()));\n                    break;\n                case BOOLEAN_SET:\n                    sb.append(String.format(Locale.US, \"RealmSet<Boolean>[%s]\", proxyState.getRow$realm().getValueSet(columnKey, type).size()));\n                    break;\n                case STRING_SET:\n                    sb.append(String.format(Locale.US, \"RealmSet<String>[%s]\", proxyState.getRow$realm().getValueSet(columnKey, type).size()));\n                    break;\n                case BINARY_SET:\n                    sb.append(String.format(Locale.US, \"RealmSet<byte[]>[%s]\", proxyState.getRow$realm().getValueSet(columnKey, type).size()));\n                    break;\n                case DATE_SET:\n                    sb.append(String.format(Locale.US, \"RealmSet<Date>[%s]\", proxyState.getRow$realm().getValueSet(columnKey, type).size()));\n                    break;\n                case FLOAT_SET:\n                    sb.append(String.format(Locale.US, \"RealmSet<Float>[%s]\", proxyState.getRow$realm().getValueSet(columnKey, type).size()));\n                    break;\n                case DOUBLE_SET:\n                    sb.append(String.format(Locale.US, \"RealmSet<Double>[%s]\", proxyState.getRow$realm().getValueSet(columnKey, type).size()));\n                    break;\n                case DECIMAL128_SET:\n                    sb.append(String.format(Locale.US, \"RealmSet<Decimal128>[%s]\", proxyState.getRow$realm().getValueSet(columnKey, type).size()));\n                    break;\n                case OBJECT_ID_SET:\n                    sb.append(String.format(Locale.US, \"RealmSet<ObjectId>[%s]\", proxyState.getRow$realm().getValueSet(columnKey, type).size()));\n                    break;\n                case UUID_SET:\n                    sb.append(String.format(Locale.US, \"RealmSet<UUID>[%s]\", proxyState.getRow$realm().getValueSet(columnKey, type).size()));\n                    break;\n                case MIXED_SET:\n                    sb.append(String.format(Locale.US, \"RealmSet<RealmAny>[%s]\", proxyState.getRow$realm().getValueSet(columnKey, type).size()));\n                    break;\n                case LINK_SET: {\n                    String targetClassName = proxyState.getRow$realm().getTable().getLinkTarget(columnKey).getClassName();\n                    sb.append(String.format(Locale.US, \"RealmSet<%s>[%s]\", targetClassName, proxyState.getRow$realm().getModelSet(columnKey).size()));\n                    break;\n                }\n                default:\n                    sb.append(\"?\");\n                    break;\n            }\n            sb.append(\"},\");\n        }\n        sb.replace(sb.length() - 1, sb.length(), \"\");\n        sb.append(\"]\");\n        return sb.toString();\n    }\n\n    private RealmAny getRealmAny(long columnKey) {\n        NativeRealmAny nativeRealmAny = proxyState.getRow$realm().getNativeRealmAny(columnKey);\n        return new RealmAny(RealmAnyOperator.fromNativeRealmAny(proxyState.getRealm$realm(), nativeRealmAny));\n    }\n\n    /**\n     * Returns {@link RealmResults} containing all {@code srcClassName} class objects that have a relationship\n     * to this object from {@code srcFieldName} field.\n     * <p>\n     * An entry is added for each reference, e.g. if the same reference is in a list multiple times,\n     * the src object will show up here multiple times.\n     *\n     * @param srcClassName name of the class returned objects belong to.\n     * @param srcFieldName name of the field in the source class that holds a reference to this object.\n     *                     Field type must be either {@code io.realm.RealmFieldType.OBJECT} or {@code io.realm.RealmFieldType.LIST}.\n     * @return the result.\n     * @throws IllegalArgumentException if the {@code srcClassName} is {@code null} or does not exist,\n     *                                  the {@code srcFieldName} is {@code null} or does not exist,\n     *                                  type of the source field is not supported.\n     */\n    public RealmResults<DynamicRealmObject> linkingObjects(String srcClassName, String srcFieldName) {\n        final DynamicRealm realm = (DynamicRealm) proxyState.getRealm$realm();\n        realm.checkIfValid();\n        proxyState.getRow$realm().checkIfAttached();\n\n        final RealmSchema schema = realm.getSchema();\n        final RealmObjectSchema realmObjectSchema = schema.get(srcClassName);\n        if (realmObjectSchema == null) {\n            throw new IllegalArgumentException(\"Class not found: \" + srcClassName);\n        }\n\n        //noinspection ConstantConditions\n        if (srcFieldName == null) {\n            throw new IllegalArgumentException(\"Non-null 'srcFieldName' required.\");\n        }\n        if (srcFieldName.contains(\".\")) {\n            throw new IllegalArgumentException(MSG_LINK_QUERY_NOT_SUPPORTED);\n        }\n\n        final RealmFieldType fieldType = realmObjectSchema.getFieldType(srcFieldName); // throws IAE if not found\n        if (fieldType != RealmFieldType.OBJECT && fieldType != RealmFieldType.LIST) {\n            throw new IllegalArgumentException(String.format(Locale.US,\n                    \"Unexpected field type: %1$s. Field type should be either %2$s.%3$s or %2$s.%4$s.\",\n                    fieldType.name(),\n                    RealmFieldType.class.getSimpleName(),\n                    RealmFieldType.OBJECT.name(), RealmFieldType.LIST.name()));\n        }\n\n        return RealmResults.createDynamicBacklinkResults(realm, (UncheckedRow) proxyState.getRow$realm(), realmObjectSchema.getTable(), srcFieldName);\n    }\n\n    /**\n     * Returns {@link DynamicRealm} instance where this {@link DynamicRealmObject} belongs.\n     * <p>\n     * You <b>must not</b> call {@link DynamicRealm#close()} against returned instance.\n     *\n     * @return {@link DynamicRealm} instance where this object belongs.\n     * @throws IllegalStateException if this object was deleted or the corresponding {@link DynamicRealm} was already closed.\n     */\n    public DynamicRealm getDynamicRealm() {\n        final BaseRealm realm = realmGet$proxyState().getRealm$realm();\n        realm.checkIfValid();\n        if (!isValid()) {\n            throw new IllegalStateException(MSG_DELETED_OBJECT);\n        }\n        return (DynamicRealm) realm;\n    }\n\n    @Override\n    public void realm$injectObjectContext() {\n        // nothing to do for DynamicRealmObject\n    }\n\n    @Override\n    public ProxyState realmGet$proxyState() {\n        return proxyState;\n    }\n\n    // Checks if the given field is primary key field. Throws if it is a PK field.\n    private void checkIsPrimaryKey(String fieldName) {\n        RealmObjectSchema objectSchema = proxyState.getRealm$realm().getSchema().getSchemaForClass(getType());\n        if (objectSchema.hasPrimaryKey() && objectSchema.getPrimaryKey().equals(fieldName)) {\n            throw new IllegalArgumentException(String.format(Locale.US,\n                    \"Primary key field '%s' cannot be changed after object was created.\", fieldName));\n        }\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/FieldAttribute.java",
    "content": "/*\n * Copyright 2015 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\npackage io.realm;\n\n/**\n * This class contains all Realm attributes for a Realm field.\n * These will usually match the annotations found in the {@code io.realm.annotation} package. See the relevant\n * annotation for further information on each modifier.\n */\npublic enum FieldAttribute {\n    /**\n     * Marks a field as indexed.\n     *\n     * @see io.realm.annotations.Index\n     */\n    INDEXED,\n\n    /**\n     * Marks a field as a primary key. This also implicitly mark it as {@link #INDEXED}.\n     *\n     * @see io.realm.annotations.PrimaryKey\n     */\n    PRIMARY_KEY,\n\n    /**\n     * Marks a field as explicitly not allowing null values. The default behavior for allowing {@code\n     * null} depends on the type of the field.\n     *\n     * @see io.realm.annotations.Required\n     * @see RealmObjectSchema#setRequired(String, boolean)\n     */\n    REQUIRED\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/FrozenPendingRow.java",
    "content": "/*\n * Copyright 2019 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 */\npackage io.realm;\n\nimport org.bson.types.Decimal128;\nimport org.bson.types.ObjectId;\n\nimport java.util.Date;\nimport java.util.UUID;\n\nimport io.realm.internal.InvalidRow;\nimport io.realm.internal.OsList;\nimport io.realm.internal.OsMap;\nimport io.realm.internal.OsSet;\nimport io.realm.internal.OsSharedRealm;\nimport io.realm.internal.Row;\nimport io.realm.internal.Table;\nimport io.realm.internal.core.NativeRealmAny;\n\n\n/**\n * A PendingRow that has been frozen. This behaves in many ways similar\n * to a deleted Row, but will report {@link #isLoaded()} as {@code as false}.\n */\npublic enum FrozenPendingRow implements Row {\n    INSTANCE;\n\n    private static final String QUERY_NOT_RETURNED_MESSAGE =\n            \"This object was frozen while a query for it was still running.\";\n\n    @Override\n    public long getColumnCount() {\n        throw new IllegalStateException(QUERY_NOT_RETURNED_MESSAGE);\n    }\n\n    @Override\n    public String[] getColumnNames() {\n        throw new  IllegalStateException(QUERY_NOT_RETURNED_MESSAGE);\n    }\n\n    @Override\n    public long getColumnKey(String columnName) {\n        throw new IllegalStateException(QUERY_NOT_RETURNED_MESSAGE);\n    }\n\n    @Override\n    public RealmFieldType getColumnType(long columnKey) {\n        throw new IllegalStateException(QUERY_NOT_RETURNED_MESSAGE);\n    }\n\n    @Override\n    public Table getTable() {\n        throw new IllegalStateException(QUERY_NOT_RETURNED_MESSAGE);\n    }\n\n    @Override\n    public long getObjectKey() {\n        throw new IllegalStateException(QUERY_NOT_RETURNED_MESSAGE);\n    }\n\n    @Override\n    public long getLong(long columnKey) {\n        throw new IllegalStateException(QUERY_NOT_RETURNED_MESSAGE);\n    }\n\n    @Override\n    public boolean getBoolean(long columnKey) {\n        throw new IllegalStateException(QUERY_NOT_RETURNED_MESSAGE);\n    }\n\n    @Override\n    public float getFloat(long columnKey) {\n        throw new IllegalStateException(QUERY_NOT_RETURNED_MESSAGE);\n    }\n\n    @Override\n    public double getDouble(long columnKey) {\n        throw new IllegalStateException(QUERY_NOT_RETURNED_MESSAGE);\n    }\n\n    @Override\n    public Date getDate(long columnKey) {\n        throw new IllegalStateException(QUERY_NOT_RETURNED_MESSAGE);\n    }\n\n    @Override\n    public String getString(long columnKey) {\n        throw new IllegalStateException(QUERY_NOT_RETURNED_MESSAGE);\n    }\n\n    @Override\n    public byte[] getBinaryByteArray(long columnKey) {\n        throw new IllegalStateException(QUERY_NOT_RETURNED_MESSAGE);\n    }\n\n    @Override\n    public Decimal128 getDecimal128(long columnKey) {\n        throw new IllegalStateException(QUERY_NOT_RETURNED_MESSAGE);\n    }\n\n    @Override\n    public ObjectId getObjectId(long columnKey) {\n        throw new IllegalStateException(QUERY_NOT_RETURNED_MESSAGE);\n    }\n\n    @Override\n    public UUID getUUID(long columnKey) {\n        throw new IllegalStateException(QUERY_NOT_RETURNED_MESSAGE);\n    }\n\n    @Override\n    public NativeRealmAny getNativeRealmAny(long columnKey) {\n        throw new IllegalStateException(QUERY_NOT_RETURNED_MESSAGE);\n    }\n\n    @Override\n    public long getLink(long columnKey) {\n        throw new IllegalStateException(QUERY_NOT_RETURNED_MESSAGE);\n    }\n\n    @Override\n    public boolean isNullLink(long columnKey) {\n        throw new IllegalStateException(QUERY_NOT_RETURNED_MESSAGE);\n    }\n\n    @Override\n    public OsList getModelList(long columnKey) {\n        throw new IllegalStateException(QUERY_NOT_RETURNED_MESSAGE);\n    }\n\n    @Override\n    public OsList getValueList(long columnKey, RealmFieldType fieldType) {\n        throw new IllegalStateException(QUERY_NOT_RETURNED_MESSAGE);\n    }\n\n    @Override\n    public OsMap getRealmAnyMap(long columnKey) {\n        throw new IllegalStateException(QUERY_NOT_RETURNED_MESSAGE);\n    }\n\n    @Override\n    public OsMap getModelMap(long columnKey) {\n        throw new IllegalStateException(QUERY_NOT_RETURNED_MESSAGE);\n    }\n\n    @Override\n    public OsMap getValueMap(long columnKey, RealmFieldType fieldType) {\n        throw new IllegalStateException(QUERY_NOT_RETURNED_MESSAGE);\n    }\n\n    @Override\n    public OsSet getRealmAnySet(long columnKey) {\n        throw new IllegalStateException(QUERY_NOT_RETURNED_MESSAGE);\n    }\n\n    @Override\n    public OsSet getModelSet(long columnKey) {\n        throw new IllegalStateException(QUERY_NOT_RETURNED_MESSAGE);\n    }\n\n    @Override\n    public OsSet getValueSet(long columnKey, RealmFieldType fieldType) {\n        throw new IllegalStateException(QUERY_NOT_RETURNED_MESSAGE);\n    }\n\n    @Override\n    public void setLong(long columnKey, long value) {\n        throw new IllegalStateException(QUERY_NOT_RETURNED_MESSAGE);\n    }\n\n    @Override\n    public void setBoolean(long columnKey, boolean value) {\n        throw new IllegalStateException(QUERY_NOT_RETURNED_MESSAGE);\n    }\n\n    @Override\n    public void setFloat(long columnKey, float value) {\n        throw new IllegalStateException(QUERY_NOT_RETURNED_MESSAGE);\n    }\n\n    @Override\n    public void setDouble(long columnKey, double value) {\n        throw new IllegalStateException(QUERY_NOT_RETURNED_MESSAGE);\n    }\n\n    @Override\n    public void setDate(long columnKey, Date date) {\n        throw new IllegalStateException(QUERY_NOT_RETURNED_MESSAGE);\n    }\n\n    @Override\n    public void setString(long columnKey, String value) {\n        throw new IllegalStateException(QUERY_NOT_RETURNED_MESSAGE);\n    }\n\n    @Override\n    public void setRealmAny(long columnKey, long value) {\n        throw new IllegalStateException(QUERY_NOT_RETURNED_MESSAGE);\n    }\n\n    @Override\n    public void setBinaryByteArray(long columnKey, byte[] data) {\n        throw new IllegalStateException(QUERY_NOT_RETURNED_MESSAGE);\n    }\n\n    @Override\n    public void setLink(long columnKey, long value) {\n        throw new IllegalStateException(QUERY_NOT_RETURNED_MESSAGE);\n    }\n\n    @Override\n    public void nullifyLink(long columnKey) {\n        throw new IllegalStateException(QUERY_NOT_RETURNED_MESSAGE);\n    }\n\n    @Override\n    public boolean isNull(long columnKey) {\n        throw new IllegalStateException(QUERY_NOT_RETURNED_MESSAGE);\n    }\n\n    @Override\n    public void setNull(long columnKey) {\n        throw new IllegalStateException(QUERY_NOT_RETURNED_MESSAGE);\n    }\n\n    @Override\n    public void setDecimal128(long columnKey, Decimal128 value) {\n        throw new IllegalStateException(QUERY_NOT_RETURNED_MESSAGE);\n    }\n\n    @Override\n    public void setObjectId(long columnKey, ObjectId value) {\n        throw new IllegalStateException(QUERY_NOT_RETURNED_MESSAGE);\n    }\n\n    @Override\n    public void setUUID(long columnKey, UUID value) {\n        throw new IllegalStateException(QUERY_NOT_RETURNED_MESSAGE);\n    }\n\n    @Override\n    public long createEmbeddedObject(long columnKey, RealmFieldType parentPropertyType) {\n        throw new IllegalStateException(QUERY_NOT_RETURNED_MESSAGE);\n    }\n\n    @Override\n    public boolean isValid() {\n        return false;\n    }\n\n    @Override\n    public void checkIfAttached() {\n        throw new IllegalStateException(QUERY_NOT_RETURNED_MESSAGE);\n    }\n\n    @Override\n    public boolean hasColumn(String fieldName) {\n        throw new IllegalStateException(QUERY_NOT_RETURNED_MESSAGE);\n    }\n\n    @Override\n    public Row freeze(OsSharedRealm frozenRealm) {\n        return InvalidRow.INSTANCE;\n    }\n\n    @Override\n    public boolean isLoaded() {\n        return false;\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/ImmutableRealmObjectSchema.java",
    "content": "/*\n * Copyright 2017 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\npackage io.realm;\n\nimport io.realm.internal.ColumnInfo;\nimport io.realm.internal.Table;\n\n/**\n * Immutable {@link RealmObjectSchema}.\n */\nclass ImmutableRealmObjectSchema extends RealmObjectSchema {\n\n    private static final String SCHEMA_IMMUTABLE_EXCEPTION_MSG = \"This 'RealmObjectSchema' is immutable.\" +\n            \" Please use 'DynamicRealm.getSchema() to get a mutable instance.\";\n\n    ImmutableRealmObjectSchema(BaseRealm realm, RealmSchema schema, Table table, ColumnInfo columnInfo) {\n        super(realm, schema, table, columnInfo);\n    }\n\n    ImmutableRealmObjectSchema(BaseRealm realm, RealmSchema schema, Table table) {\n        super(realm, schema, table, new DynamicColumnIndices(table));\n    }\n\n    @Override\n    public RealmObjectSchema setClassName(String className) {\n        throw new UnsupportedOperationException(SCHEMA_IMMUTABLE_EXCEPTION_MSG);\n    }\n\n    @Override\n    public RealmObjectSchema addField(String fieldName, Class<?> fieldType, FieldAttribute... attributes) {\n        throw new UnsupportedOperationException(SCHEMA_IMMUTABLE_EXCEPTION_MSG);\n    }\n\n    @Override\n    public RealmObjectSchema addRealmObjectField(String fieldName, RealmObjectSchema objectSchema) {\n        throw new UnsupportedOperationException(SCHEMA_IMMUTABLE_EXCEPTION_MSG);\n    }\n\n    @Override\n    public RealmObjectSchema addRealmListField(String fieldName, RealmObjectSchema objectSchema) {\n        throw new UnsupportedOperationException(SCHEMA_IMMUTABLE_EXCEPTION_MSG);\n    }\n\n    @Override\n    public RealmObjectSchema addRealmListField(String fieldName, Class<?> primitiveType) {\n        throw new UnsupportedOperationException(SCHEMA_IMMUTABLE_EXCEPTION_MSG);\n    }\n\n    @Override\n    public RealmObjectSchema addRealmDictionaryField(String fieldName, Class<?> primitiveType) {\n        throw new UnsupportedOperationException(SCHEMA_IMMUTABLE_EXCEPTION_MSG);\n    }\n\n    @Override\n    public RealmObjectSchema addRealmSetField(String fieldName, RealmObjectSchema objectSchema) {\n        throw new UnsupportedOperationException(SCHEMA_IMMUTABLE_EXCEPTION_MSG);\n    }\n\n    @Override\n    public RealmObjectSchema addRealmSetField(String fieldName, Class<?> primitiveType) {\n        throw new UnsupportedOperationException(SCHEMA_IMMUTABLE_EXCEPTION_MSG);\n    }\n\n    @Override\n    public RealmObjectSchema addRealmDictionaryField(String fieldName, RealmObjectSchema objectSchema) {\n        throw new UnsupportedOperationException(SCHEMA_IMMUTABLE_EXCEPTION_MSG);\n    }\n\n    @Override\n    public RealmObjectSchema removeField(String fieldName) {\n        throw new UnsupportedOperationException(SCHEMA_IMMUTABLE_EXCEPTION_MSG);\n    }\n\n    @Override\n    public RealmObjectSchema renameField(String currentFieldName, String newFieldName) {\n        throw new UnsupportedOperationException(SCHEMA_IMMUTABLE_EXCEPTION_MSG);\n    }\n\n    @Override\n    public RealmObjectSchema addIndex(String fieldName) {\n        throw new UnsupportedOperationException(SCHEMA_IMMUTABLE_EXCEPTION_MSG);\n    }\n\n    @Override\n    public RealmObjectSchema removeIndex(String fieldName) {\n        throw new UnsupportedOperationException(SCHEMA_IMMUTABLE_EXCEPTION_MSG);\n    }\n\n    @Override\n    public RealmObjectSchema addPrimaryKey(String fieldName) {\n        throw new UnsupportedOperationException(SCHEMA_IMMUTABLE_EXCEPTION_MSG);\n    }\n\n    @Override\n    public RealmObjectSchema removePrimaryKey() {\n        throw new UnsupportedOperationException(SCHEMA_IMMUTABLE_EXCEPTION_MSG);\n    }\n\n    @Override\n    public RealmObjectSchema setRequired(String fieldName, boolean required) {\n        throw new UnsupportedOperationException(SCHEMA_IMMUTABLE_EXCEPTION_MSG);\n    }\n\n    @Override\n    public RealmObjectSchema setNullable(String fieldName, boolean nullable) {\n        throw new UnsupportedOperationException(SCHEMA_IMMUTABLE_EXCEPTION_MSG);\n    }\n\n    @Override\n    public RealmObjectSchema transform(Function function) {\n        throw new UnsupportedOperationException(SCHEMA_IMMUTABLE_EXCEPTION_MSG);\n    }\n\n    @Override\n    String getPropertyClassName(String propertyName) {\n        ColumnInfo.ColumnDetails columnDetails = columnInfo.getColumnDetails(propertyName);\n        if (columnDetails == null) {\n            throw new IllegalArgumentException(String.format(\"Property '%s' not found.\", propertyName));\n        } else {\n            return columnDetails.linkedClassName;\n        }\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/ImmutableRealmSchema.java",
    "content": "/*\n * Copyright 2017 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\npackage io.realm;\n\nimport java.util.LinkedHashSet;\nimport java.util.Set;\n\nimport io.realm.internal.ColumnIndices;\nimport io.realm.internal.RealmProxyMediator;\nimport io.realm.internal.Table;\n\n/**\n * Immutable {@link RealmSchema} used by {@link Realm}.\n *\n * @see MutableRealmSchema for schema support for {@link DynamicRealm}.\n */\nclass ImmutableRealmSchema extends RealmSchema {\n\n    private static final String SCHEMA_IMMUTABLE_EXCEPTION_MSG = \"This 'RealmSchema' is immutable.\" +\n            \" Please use 'DynamicRealm.getSchema() to get a mutable instance.\";\n\n    ImmutableRealmSchema(BaseRealm realm, ColumnIndices columnIndices) {\n        super(realm, columnIndices);\n    }\n\n    @Override\n    public RealmObjectSchema get(String className) {\n        checkNotEmpty(className, EMPTY_STRING_MSG);\n\n        String internalClassName = Table.getTableNameForClass(className);\n        if (!realm.getSharedRealm().hasTable(internalClassName)) { return null; }\n        Table table = realm.getSharedRealm().getTable(internalClassName);\n        return new ImmutableRealmObjectSchema(realm, this, table, getColumnInfo(className));\n    }\n\n    @Override\n    public Set<RealmObjectSchema> getAll() {\n        // Only return schema objects for classes defined by the schema in the RealmConfiguration\n        RealmProxyMediator schemaMediator = realm.getConfiguration().getSchemaMediator();\n        Set<Class<? extends RealmModel>> classes = schemaMediator.getModelClasses();\n        Set<RealmObjectSchema> schemas = new LinkedHashSet<>(classes.size());\n        for (Class<? extends RealmModel> clazz : classes) {\n            String className = schemaMediator.getSimpleClassName(clazz);\n            RealmObjectSchema objectSchema = get(className);\n            schemas.add(objectSchema);\n        }\n        return schemas;\n    }\n\n    @Override\n    public RealmObjectSchema create(String className) {\n        throw new UnsupportedOperationException(SCHEMA_IMMUTABLE_EXCEPTION_MSG);\n    }\n\n    @Override\n    public RealmObjectSchema createWithPrimaryKeyField(String className, String primaryKeyFieldName, Class<?> fieldType, FieldAttribute... attributes) {\n        throw new UnsupportedOperationException(SCHEMA_IMMUTABLE_EXCEPTION_MSG);\n    }\n\n    @Override\n    public void remove(String className) {\n        throw new UnsupportedOperationException(SCHEMA_IMMUTABLE_EXCEPTION_MSG);\n    }\n\n    @Override\n    public RealmObjectSchema rename(String oldClassName, String newClassName) {\n        throw new UnsupportedOperationException(SCHEMA_IMMUTABLE_EXCEPTION_MSG);\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/ImportFlag.java",
    "content": "/*\n * Copyright 2018 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 */\npackage io.realm;\n\nimport io.realm.annotations.Beta;\n\n/**\n * This class describe how data is saved to Realm when saving whole objects.\n *\n * @see Realm#copyToRealm(RealmModel, ImportFlag...)\n */\n@Beta\npublic enum ImportFlag {\n\n    /**\n     * With this flag enabled, fields will not be written to the Realm file if they contain the same\n     * value as the value already present in the Realm.\n     * <p>\n     * For local Realms this only has an impact on change listeners which will not report changes to\n     * those fields that were not written.\n     * <p>\n     * For synchronized Realms this also impacts the server, which will see improved performance as\n     * there are fewer changes to upload and merge into the server Realm.\n     * <p>\n     * It also impacts how the server merges changes from different devices. Realm uses a\n     * last-write-wins approach when merging individual fields in an object, so if a field is not\n     * written it will be considered \"older\" than other fields modified.\n     * <p>\n     * E.g:\n     * <ol>\n     *     <li>\n     *         Server starts out with (Field A = 1, Field B = 1)\n     *     </li>\n     *     <li>\n     *         Device 1 writes (Field A = 2, Field B = 2).\n     *     </li>\n     *     <li>\n     *         Device 2 writes (Field A = 3, Field B = 1) but ignores (Field B = 1), because that is\n     *         the value in the Realm file at this point.\n     *     </li>\n     *     <li>\n     *         Device 1 uploads its changes to the server making the server (Field A = 2, Field B = 2).\n     *         Then Device 2 uploads its changes. Due to last-write-wins, the server version now\n     *         becomes (Field A = 3, Field B = 2).\n     *     </li>\n     * </ol>\n     * This is normally the desired behavior as the final object is the merged result of the latest\n     * changes from both devices, however if all the fields in an object are considered an atomic\n     * unit, then this flag should not be set as it will ensure that all fields are set and thus have\n     * the same \"age\" when data are sent to the server.\n     *\n     * @see <a href=\"https://docs.mongodb.com/realm/sync/conflict-resolution/\">Docs on conflict resolution</a>\n     */\n    CHECK_SAME_VALUES_BEFORE_SET,\n\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/ManagedListOperator.java",
    "content": "/*\n * Copyright 2020 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\npackage io.realm;\n\nimport org.bson.types.Decimal128;\nimport org.bson.types.ObjectId;\n\nimport java.util.Date;\nimport java.util.Locale;\nimport java.util.UUID;\n\nimport javax.annotation.Nullable;\n\nimport io.realm.internal.OsList;\nimport io.realm.internal.RealmObjectProxy;\n\nimport io.realm.internal.core.NativeRealmAny;\n\nimport static io.realm.CollectionUtils.LIST_TYPE;\n\n\n/**\n * This class provides facade for against {@link OsList}. {@link OsList} is used for both {@link RealmModel}s\n * and values, but there are some subtle differences in actual operation.\n * <p>\n * This class provides a common interface for them.\n * <p>\n * You need to use appropriate sub-class for underlying field type.\n *\n * @param <T> class of element which is returned on read operation.\n */\nabstract class ManagedListOperator<T> {\n    static final String NULL_OBJECTS_NOT_ALLOWED_MESSAGE = \"RealmList does not accept null values.\";\n    static final String INVALID_OBJECT_TYPE_MESSAGE = \"Unacceptable value type. Acceptable: %1$s, actual: %2$s .\";\n\n    final BaseRealm realm;\n    final OsList osList;\n    @Nullable\n    final Class<T> clazz;\n\n    ManagedListOperator(BaseRealm realm, OsList osList, @Nullable Class<T> clazz) {\n        this.realm = realm;\n        this.clazz = clazz;\n        this.osList = osList;\n    }\n\n    public abstract boolean forRealmModel();\n\n    public final OsList getOsList() {\n        return osList;\n    }\n\n    public final boolean isValid() {\n        return osList.isValid();\n    }\n\n    public final int size() {\n        final long actualSize = osList.size();\n        return actualSize < Integer.MAX_VALUE ? (int) actualSize : Integer.MAX_VALUE;\n    }\n\n    public final boolean isEmpty() {\n        return osList.isEmpty();\n    }\n\n    protected abstract void checkValidValue(@Nullable Object value);\n\n    protected void checkInsertIndex(int index) {\n        final int size = size();\n        if (index < 0 || size < index) {\n            throw new IndexOutOfBoundsException(\"Invalid index \" + index + \", size is \" + osList.size());\n        }\n    }\n\n    @Nullable\n    public abstract T get(int index);\n\n    public final void append(@Nullable Object value) {\n        checkValidValue(value);\n\n        if (value == null) {\n            appendNull();\n        } else {\n            appendValue(value);\n        }\n    }\n\n    private void appendNull() {\n        osList.addNull();\n    }\n\n    protected abstract void appendValue(Object value);\n\n    public final void insert(int index, @Nullable T value) {\n        checkValidValue(value);\n\n        if (value == null) {\n            insertNull(index);\n        } else {\n            insertValue(index, value);\n        }\n\n    }\n\n    protected void insertNull(int index) {\n        osList.insertNull(index);\n    }\n\n    protected abstract void insertValue(int index, Object value);\n\n    @Nullable\n    public final T set(int index, @Nullable Object value) {\n        checkValidValue(value);\n\n        //noinspection unchecked\n        final T oldObject = get(index);\n        if (value == null) {\n            setNull(index);\n        } else {\n            setValue(index, value);\n        }\n        return oldObject;\n    }\n\n    protected void setNull(int index) {\n        osList.setNull(index);\n    }\n\n    protected abstract void setValue(int index, Object value);\n\n    final void move(int oldPos, int newPos) {\n        osList.move(oldPos, newPos);\n    }\n\n    final void remove(int index) {\n        osList.remove(index);\n    }\n\n    final void removeAll() {\n        osList.removeAll();\n    }\n\n    final void delete(int index) {\n        osList.delete(index);\n    }\n\n    final void deleteLast() {\n        osList.delete(osList.size() - 1);\n    }\n\n    final void deleteAll() {\n        osList.deleteAll();\n    }\n\n}\n\n/**\n * A subclass of {@link ManagedListOperator} that deal with {@link RealmModel} list field.\n */\nfinal class RealmModelListOperator<T> extends ManagedListOperator<T> {\n\n    @Nullable\n    private final String className;\n\n    RealmModelListOperator(BaseRealm realm, OsList osList, @Nullable Class<T> clazz, @Nullable String className) {\n        super(realm, osList, clazz);\n        this.className = className;\n    }\n\n    @Override\n    public boolean forRealmModel() {\n        return true;\n    }\n\n    @Override\n    public T get(int index) {\n        //noinspection unchecked\n        return (T) realm.get((Class<? extends RealmModel>) clazz, className, osList.getUncheckedRow(index));\n    }\n\n    @Override\n    protected void checkValidValue(@Nullable Object value) {\n        if (value == null) {\n            throw new IllegalArgumentException(NULL_OBJECTS_NOT_ALLOWED_MESSAGE);\n        }\n        if (!(value instanceof RealmModel)) {\n            throw new IllegalArgumentException(\n                    String.format(Locale.ENGLISH, INVALID_OBJECT_TYPE_MESSAGE,\n                            \"java.lang.String\",\n                            value.getClass().getName()));\n        }\n    }\n\n    @Override\n    public void appendValue(Object value) {\n        RealmModel realmObject = (RealmModel) value;\n        boolean copyObject = CollectionUtils.checkCanObjectBeCopied(realm, realmObject, className, LIST_TYPE);\n        if (CollectionUtils.isEmbedded(realm, realmObject)) {\n            if (value instanceof DynamicRealmObject) {\n                throw new IllegalArgumentException(\"Embedded objects are not supported by RealmLists of DynamicRealmObjects yet.\");\n            }\n            long objKey = osList.createAndAddEmbeddedObject();\n            CollectionUtils.updateEmbeddedObject((Realm) realm, realmObject, objKey);\n        } else {\n            RealmObjectProxy proxy = (RealmObjectProxy) ((copyObject) ? CollectionUtils.copyToRealm(realm, (RealmModel) value) : realmObject);\n            osList.addRow(proxy.realmGet$proxyState().getRow$realm().getObjectKey());\n        }\n    }\n\n    @Override\n    protected void insertNull(int index) {\n        throw new RuntimeException(\"Should not reach here.\");\n    }\n\n    @Override\n    public void insertValue(int index, Object value) {\n        // need to check in advance to avoid unnecessary copy of unmanaged object into Realm.\n        checkInsertIndex(index);\n        RealmModel realmObject = (RealmModel) value;\n        boolean copyObject = CollectionUtils.checkCanObjectBeCopied(realm, realmObject, className, LIST_TYPE);\n        if (CollectionUtils.isEmbedded(realm, realmObject)) {\n            if (value instanceof DynamicRealmObject) {\n                throw new IllegalArgumentException(\"Embedded objects are not supported by RealmLists of DynamicRealmObjects yet.\");\n            }\n            long objKey = osList.createAndAddEmbeddedObject(index);\n            CollectionUtils.updateEmbeddedObject((Realm) realm, realmObject, objKey);\n        } else {\n            RealmObjectProxy proxy = (RealmObjectProxy) ((copyObject) ? CollectionUtils.copyToRealm(realm, (RealmModel) value) : realmObject);\n            osList.insertRow(index, proxy.realmGet$proxyState().getRow$realm().getObjectKey());\n        }\n    }\n\n    @Override\n    protected void setNull(int index) {\n        throw new RuntimeException(\"Should not reach here.\");\n    }\n\n    @Override\n    protected void setValue(int index, Object value) {\n        RealmModel realmObject = (RealmModel) value;\n        boolean copyObject = CollectionUtils.checkCanObjectBeCopied(realm, realmObject, className, LIST_TYPE);\n        if (CollectionUtils.isEmbedded(realm, realmObject)) {\n            if (value instanceof DynamicRealmObject) {\n                throw new IllegalArgumentException(\"Embedded objects are not supported by RealmLists of DynamicRealmObjects yet.\");\n            }\n            long objKey = osList.createAndSetEmbeddedObject(index);\n            CollectionUtils.updateEmbeddedObject((Realm) realm, realmObject, objKey);\n        } else {\n            RealmObjectProxy proxy = (RealmObjectProxy) ((copyObject) ? CollectionUtils.copyToRealm(realm, (RealmModel) value) : realmObject);\n            osList.setRow(index, proxy.realmGet$proxyState().getRow$realm().getObjectKey());\n        }\n    }\n}\n\n/**\n * A subclass of {@link ManagedListOperator} that deal with {@link String} list field.\n */\nfinal class StringListOperator extends ManagedListOperator<String> {\n\n    StringListOperator(BaseRealm realm, OsList osList, Class<String> clazz) {\n        super(realm, osList, clazz);\n    }\n\n    @Override\n    public boolean forRealmModel() {\n        return false;\n    }\n\n    @Nullable\n    @Override\n    public String get(int index) {\n        return (String) osList.getValue(index);\n    }\n\n    @Override\n    protected void checkValidValue(@Nullable Object value) {\n        if (value == null) {\n            // null is always valid (but schema may reject null on insertion).\n            return;\n        }\n        if (!(value instanceof String)) {\n            throw new IllegalArgumentException(\n                    String.format(Locale.ENGLISH, INVALID_OBJECT_TYPE_MESSAGE,\n                            \"java.lang.String\",\n                            value.getClass().getName()));\n        }\n    }\n\n    @Override\n    public void appendValue(Object value) {\n        osList.addString((String) value);\n    }\n\n    @Override\n    public void insertValue(int index, Object value) {\n        osList.insertString(index, (String) value);\n    }\n\n    @Override\n    protected void setValue(int index, Object value) {\n        osList.setString(index, (String) value);\n    }\n}\n\n/**\n * A subclass of {@link ManagedListOperator} that deal with {@code long} list field.\n */\nfinal class LongListOperator<T> extends ManagedListOperator<T> {\n\n    LongListOperator(BaseRealm realm, OsList osList, Class<T> clazz) {\n        super(realm, osList, clazz);\n    }\n\n    @Override\n    public boolean forRealmModel() {\n        return false;\n    }\n\n    @Nullable\n    @Override\n    public T get(int index) {\n        final Long value = (Long) osList.getValue(index);\n        if (value == null) {\n            return null;\n        }\n        if (clazz == Long.class) {\n            //noinspection unchecked\n            return (T) value;\n        }\n        if (clazz == Integer.class) {\n            //noinspection unchecked,UnnecessaryBoxing,ConstantConditions\n            return clazz.cast(Integer.valueOf(value.intValue()));\n        }\n        if (clazz == Short.class) {\n            //noinspection unchecked,UnnecessaryBoxing,ConstantConditions\n            return clazz.cast(Short.valueOf(value.shortValue()));\n        }\n        if (clazz == Byte.class) {\n            //noinspection unchecked,UnnecessaryBoxing,ConstantConditions\n            return clazz.cast(Byte.valueOf(value.byteValue()));\n        }\n        //noinspection ConstantConditions\n        throw new IllegalStateException(\"Unexpected element type: \" + clazz.getName());\n    }\n\n    @Override\n    protected void checkValidValue(@Nullable Object value) {\n        if (value == null) {\n            // null is always valid (but schema may reject null on insertion).\n            return;\n        }\n        if (!(value instanceof Number)) {\n            throw new IllegalArgumentException(\n                    String.format(Locale.ENGLISH, INVALID_OBJECT_TYPE_MESSAGE,\n                            \"java.lang.Long, java.lang.Integer, java.lang.Short, java.lang.Byte\",\n                            value.getClass().getName()));\n        }\n    }\n\n    @Override\n    public void appendValue(Object value) {\n        osList.addLong(((Number) value).longValue());\n    }\n\n    @Override\n    public void insertValue(int index, Object value) {\n        osList.insertLong(index, ((Number) value).longValue());\n    }\n\n    @Override\n    protected void setValue(int index, Object value) {\n        osList.setLong(index, ((Number) value).longValue());\n    }\n}\n\n/**\n * A subclass of {@link ManagedListOperator} that deal with {@code boolean} list field.\n */\nfinal class BooleanListOperator extends ManagedListOperator<Boolean> {\n\n    BooleanListOperator(BaseRealm realm, OsList osList, Class<Boolean> clazz) {\n        super(realm, osList, clazz);\n    }\n\n    @Override\n    public boolean forRealmModel() {\n        return false;\n    }\n\n    @Nullable\n    @Override\n    public Boolean get(int index) {\n        return (Boolean) osList.getValue(index);\n    }\n\n    @Override\n    protected void checkValidValue(@Nullable Object value) {\n        if (value == null) {\n            // null is always valid (but schema may reject null on insertion).\n            return;\n        }\n        if (!(value instanceof Boolean)) {\n            throw new IllegalArgumentException(\n                    String.format(Locale.ENGLISH, INVALID_OBJECT_TYPE_MESSAGE,\n                            \"java.lang.Boolean\",\n                            value.getClass().getName()));\n        }\n    }\n\n    @Override\n    public void appendValue(Object value) {\n        osList.addBoolean((Boolean) value);\n    }\n\n    @Override\n    public void insertValue(int index, Object value) {\n        osList.insertBoolean(index, (Boolean) value);\n    }\n\n    @Override\n    protected void setValue(int index, Object value) {\n        osList.setBoolean(index, (Boolean) value);\n    }\n}\n\n/**\n * A subclass of {@link ManagedListOperator} that deal with {@code byte[]} list field.\n */\nfinal class BinaryListOperator extends ManagedListOperator<byte[]> {\n\n    BinaryListOperator(BaseRealm realm, OsList osList, Class<byte[]> clazz) {\n        super(realm, osList, clazz);\n    }\n\n    @Override\n    public boolean forRealmModel() {\n        return false;\n    }\n\n    @Nullable\n    @Override\n    public byte[] get(int index) {\n        return (byte[]) osList.getValue(index);\n    }\n\n    @Override\n    protected void checkValidValue(@Nullable Object value) {\n        if (value == null) {\n            // null is always valid (but schema may reject null on insertion).\n            return;\n        }\n        if (!(value instanceof byte[])) {\n            throw new IllegalArgumentException(\n                    String.format(Locale.ENGLISH, INVALID_OBJECT_TYPE_MESSAGE,\n                            \"byte[]\",\n                            value.getClass().getName()));\n        }\n    }\n\n    @Override\n    public void appendValue(Object value) {\n        osList.addBinary((byte[]) value);\n    }\n\n    @Override\n    public void insertValue(int index, Object value) {\n        osList.insertBinary(index, (byte[]) value);\n    }\n\n    @Override\n    protected void setValue(int index, Object value) {\n        osList.setBinary(index, (byte[]) value);\n    }\n}\n\n/**\n * A subclass of {@link ManagedListOperator} that deal with {@code double} list field.\n */\nfinal class DoubleListOperator extends ManagedListOperator<Double> {\n\n    DoubleListOperator(BaseRealm realm, OsList osList, Class<Double> clazz) {\n        super(realm, osList, clazz);\n    }\n\n    @Override\n    public boolean forRealmModel() {\n        return false;\n    }\n\n    @Nullable\n    @Override\n    public Double get(int index) {\n        return (Double) osList.getValue(index);\n    }\n\n    @Override\n    protected void checkValidValue(@Nullable Object value) {\n        if (value == null) {\n            // null is always valid (but schema may reject null on insertion).\n            return;\n        }\n        if (!(value instanceof Number)) {\n            throw new IllegalArgumentException(\n                    String.format(Locale.ENGLISH, INVALID_OBJECT_TYPE_MESSAGE,\n                            \"java.lang.Number\",\n                            value.getClass().getName()));\n        }\n    }\n\n    @Override\n    public void appendValue(Object value) {\n        osList.addDouble(((Number) value).doubleValue());\n    }\n\n    @Override\n    public void insertValue(int index, Object value) {\n        osList.insertDouble(index, ((Number) value).doubleValue());\n    }\n\n    @Override\n    protected void setValue(int index, Object value) {\n        osList.setDouble(index, ((Number) value).doubleValue());\n    }\n}\n\n/**\n * A subclass of {@link ManagedListOperator} that deal with {@code float} list field.\n */\nfinal class FloatListOperator extends ManagedListOperator<Float> {\n\n    FloatListOperator(BaseRealm realm, OsList osList, Class<Float> clazz) {\n        super(realm, osList, clazz);\n    }\n\n    @Override\n    public boolean forRealmModel() {\n        return false;\n    }\n\n    @Nullable\n    @Override\n    public Float get(int index) {\n        return (Float) osList.getValue(index);\n    }\n\n    @Override\n    protected void checkValidValue(@Nullable Object value) {\n        if (value == null) {\n            // null is always valid (but schema may reject null on insertion).\n            return;\n        }\n        if (!(value instanceof Number)) {\n            throw new IllegalArgumentException(\n                    String.format(Locale.ENGLISH, INVALID_OBJECT_TYPE_MESSAGE,\n                            \"java.lang.Number\",\n                            value.getClass().getName()));\n        }\n    }\n\n    @Override\n    public void appendValue(Object value) {\n        osList.addFloat(((Number) value).floatValue());\n    }\n\n    @Override\n    public void insertValue(int index, Object value) {\n        osList.insertFloat(index, ((Number) value).floatValue());\n    }\n\n    @Override\n    protected void setValue(int index, Object value) {\n        osList.setFloat(index, ((Number) value).floatValue());\n    }\n}\n\n/**\n * A subclass of {@link ManagedListOperator} that deal with {@link Date} list field.\n */\nfinal class DateListOperator extends ManagedListOperator<Date> {\n\n    DateListOperator(BaseRealm realm, OsList osList, Class<Date> clazz) {\n        super(realm, osList, clazz);\n    }\n\n    @Override\n    public boolean forRealmModel() {\n        return false;\n    }\n\n    @Nullable\n    @Override\n    public Date get(int index) {\n        return (Date) osList.getValue(index);\n    }\n\n    @Override\n    protected void checkValidValue(@Nullable Object value) {\n        if (value == null) {\n            // null is always valid (but schema may reject null on insertion).\n            return;\n        }\n        if (!(value instanceof Date)) {\n            throw new IllegalArgumentException(\n                    String.format(Locale.ENGLISH, INVALID_OBJECT_TYPE_MESSAGE,\n                            \"java.util.Date\",\n                            value.getClass().getName()));\n        }\n    }\n\n    @Override\n    public void appendValue(Object value) {\n        osList.addDate((Date) value);\n    }\n\n    @Override\n    public void insertValue(int index, Object value) {\n        osList.insertDate(index, (Date) value);\n    }\n\n    @Override\n    protected void setValue(int index, Object value) {\n        osList.setDate(index, (Date) value);\n    }\n}\n\n/**\n * A subclass of {@link ManagedListOperator} that deal with {@link Decimal128} list field.\n */\nfinal class Decimal128ListOperator extends ManagedListOperator<Decimal128> {\n\n    Decimal128ListOperator(BaseRealm realm, OsList osList, Class<Decimal128> clazz) {\n        super(realm, osList, clazz);\n    }\n\n    @Override\n    public boolean forRealmModel() {\n        return false;\n    }\n\n    @Nullable\n    @Override\n    public Decimal128 get(int index) {\n        return (Decimal128) osList.getValue(index);\n    }\n\n    @Override\n    protected void checkValidValue(@Nullable Object value) {\n        if (value == null) {\n            // null is always valid (but schema may reject null on insertion).\n            return;\n        }\n        if (!(value instanceof Decimal128)) {\n            throw new IllegalArgumentException(\n                    String.format(Locale.ENGLISH, INVALID_OBJECT_TYPE_MESSAGE,\n                            \"org.bson.types.Decimal128\",\n                            value.getClass().getName()));\n        }\n    }\n\n    @Override\n    public void appendValue(Object value) {\n        osList.addDecimal128((Decimal128) value);\n    }\n\n    @Override\n    public void insertValue(int index, Object value) {\n        osList.insertDecimal128(index, (Decimal128) value);\n    }\n\n    @Override\n    protected void setValue(int index, Object value) {\n        osList.setDecimal128(index, (Decimal128) value);\n    }\n}\n\n/**\n * A subclass of {@link ManagedListOperator} that deal with {@link ObjectId} list field.\n */\nfinal class ObjectIdListOperator extends ManagedListOperator<ObjectId> {\n\n    ObjectIdListOperator(BaseRealm realm, OsList osList, Class<ObjectId> clazz) {\n        super(realm, osList, clazz);\n    }\n\n    @Override\n    public boolean forRealmModel() {\n        return false;\n    }\n\n    @Nullable\n    @Override\n    public ObjectId get(int index) {\n        return (ObjectId) osList.getValue(index);\n    }\n\n    @Override\n    protected void checkValidValue(@Nullable Object value) {\n        if (value == null) {\n            // null is always valid (but schema may reject null on insertion).\n            return;\n        }\n        if (!(value instanceof ObjectId)) {\n            throw new IllegalArgumentException(\n                    String.format(Locale.ENGLISH, INVALID_OBJECT_TYPE_MESSAGE,\n                            \"org.bson.types.ObjectId\",\n                            value.getClass().getName()));\n        }\n    }\n\n    @Override\n    public void appendValue(Object value) {\n        osList.addObjectId((ObjectId) value);\n    }\n\n    @Override\n    public void insertValue(int index, Object value) {\n        osList.insertObjectId(index, (ObjectId) value);\n    }\n\n    @Override\n    protected void setValue(int index, Object value) {\n        osList.setObjectId(index, (ObjectId) value);\n    }\n}\n\n/**\n * A subclass of {@link ManagedListOperator} that deal with {@link UUID} list field.\n */\nfinal class UUIDListOperator extends ManagedListOperator<UUID> {\n\n    UUIDListOperator(BaseRealm realm, OsList osList, Class<UUID> clazz) {\n        super(realm, osList, clazz);\n    }\n\n    @Override\n    public boolean forRealmModel() {\n        return false;\n    }\n\n    @Nullable\n    @Override\n    public UUID get(int index) {\n        return (UUID) osList.getValue(index);\n    }\n\n    @Override\n    protected void checkValidValue(@Nullable Object value) {\n        if (value == null) {\n            // null is always valid (but schema may reject null on insertion).\n            return;\n        }\n        if (!(value instanceof UUID)) {\n            throw new IllegalArgumentException(\n                    String.format(Locale.ENGLISH, INVALID_OBJECT_TYPE_MESSAGE,\n                            \"java.util.UUID\",\n                            value.getClass().getName()));\n        }\n    }\n\n    @Override\n    public void appendValue(Object value) {\n        osList.addUUID((UUID) value);\n    }\n\n    @Override\n    public void insertValue(int index, Object value) {\n        osList.insertUUID(index, (UUID) value);\n    }\n\n    @Override\n    protected void setValue(int index, Object value) {\n        osList.setUUID(index, (UUID) value);\n    }\n}\n\n/**\n * A subclass of {@link ManagedListOperator} that deal with {@link RealmAny} list field.\n */\nfinal class RealmAnyListOperator extends ManagedListOperator<RealmAny> {\n\n    RealmAnyListOperator(BaseRealm realm, OsList osList, Class<RealmAny> clazz) {\n        super(realm, osList, clazz);\n    }\n\n    @Override\n    public boolean forRealmModel() {\n        return false;\n    }\n\n    @Override\n    public RealmAny get(int index) {\n        NativeRealmAny nativeRealmAny = (NativeRealmAny) osList.getValue(index);\n        nativeRealmAny = (nativeRealmAny == null) ? new NativeRealmAny() : nativeRealmAny;\n        return new RealmAny(RealmAnyOperator.fromNativeRealmAny(realm, nativeRealmAny));\n    }\n\n    @Override\n    protected void checkValidValue(@Nullable Object value) {\n        if (value == null) {\n            // null is always valid (but schema may reject null on insertion).\n            return;\n        }\n        if (!(value instanceof RealmAny)) {\n            throw new IllegalArgumentException(\n                    String.format(Locale.ENGLISH, INVALID_OBJECT_TYPE_MESSAGE,\n                            \"java.util.RealmAny\",\n                            value.getClass().getName()));\n        }\n    }\n\n    @Override\n    public void appendValue(Object value) {\n        RealmAny realmAny = (RealmAny) value;\n        realmAny = CollectionUtils.copyToRealmIfNeeded(realm, realmAny);\n        osList.addRealmAny(realmAny.getNativePtr());\n    }\n\n    @Override\n    public void insertValue(int index, Object value) {\n        checkInsertIndex(index);\n\n        RealmAny realmAny = (RealmAny) value;\n        realmAny = CollectionUtils.copyToRealmIfNeeded(realm, realmAny);\n        osList.insertRealmAny(index, realmAny.getNativePtr());\n    }\n\n    @Override\n    protected void setValue(int index, Object value) {\n        RealmAny realmAny = (RealmAny) value;\n        realmAny = CollectionUtils.copyToRealmIfNeeded(realm, realmAny);\n        osList.setRealmAny(index, realmAny.getNativePtr());\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/ManagedMapManager.java",
    "content": "/*\n * Copyright 2020 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\npackage io.realm;\n\nimport java.util.Collection;\nimport java.util.Map;\nimport java.util.Objects;\nimport java.util.Set;\n\nimport javax.annotation.Nullable;\n\nimport io.realm.internal.Freezable;\nimport io.realm.internal.ManageableObject;\nimport io.realm.internal.ObservableMap;\nimport io.realm.internal.ObserverPairList;\nimport io.realm.internal.OsMap;\nimport io.realm.internal.RealmObjectProxy;\nimport io.realm.internal.Row;\nimport io.realm.internal.core.NativeRealmAny;\nimport io.realm.internal.util.Pair;\n\n/**\n * A {@code ManagedMapManager} abstracts the different types of keys and values a managed\n * {@link RealmMap} can contain.\n *\n * @param <K> the key type\n * @param <V> the value type\n */\nabstract class ManagedMapManager<K, V> implements Map<K, V>, ManageableObject, Freezable<RealmMap<K, V>>, ObservableMap {\n\n    protected final BaseRealm baseRealm;\n    protected final MapValueOperator<K, V> mapValueOperator;\n    protected final TypeSelectorForMap<K, V> typeSelectorForMap;\n    protected final ObserverPairList<MapObserverPair<K, V>> mapObserverPairs = new ObserverPairList<>();\n\n    ManagedMapManager(BaseRealm baseRealm,\n                      MapValueOperator<K, V> mapValueOperator,\n                      TypeSelectorForMap<K, V> typeSelectorForMap) {\n        this.baseRealm = baseRealm;\n        this.mapValueOperator = mapValueOperator;\n        this.typeSelectorForMap = typeSelectorForMap;\n    }\n\n    abstract boolean containsKeyInternal(@Nullable Object key);\n\n    abstract void validateMap(Map<? extends K, ? extends V> map);\n\n    abstract RealmMap<K, V> freezeInternal(Pair<BaseRealm, OsMap> frozenBaseRealmMap);\n\n    abstract MapChangeSet<K> changeSetFactory(long nativeChangeSetPtr);\n\n\n    @Override\n    public abstract V put(@Nullable K key, @Nullable V value);\n\n    @Override\n    public abstract Set<Entry<K, V>> entrySet();\n\n    @Override\n    public boolean isManaged() {\n        return true;\n    }\n\n    @Override\n    public boolean isValid() {\n        return mapValueOperator.isValid();\n    }\n\n    @Override\n    public boolean isFrozen() {\n        return mapValueOperator.isFrozen();\n    }\n\n    @Override\n    public V remove(Object key) {\n        if (key == null) {\n            throw new NullPointerException(\"Null keys are not allowed.\");\n        }\n\n        //noinspection unchecked\n        V removedValue = mapValueOperator.get((K) key);\n        mapValueOperator.remove(key);\n        return removedValue;\n    }\n\n    @Override\n    public int size() {\n        return mapValueOperator.size();\n    }\n\n    @Override\n    public boolean isEmpty() {\n        return mapValueOperator.isEmpty();\n    }\n\n    @Override\n    public boolean containsKey(@Nullable Object key) {\n        return containsKeyInternal(key);\n    }\n\n    @Override\n    public boolean containsValue(@Nullable Object value) {\n        return mapValueOperator.containsValue(value);\n    }\n\n    @Override\n    public void putAll(Map<? extends K, ? extends V> m) {\n        validateMap(m);\n        mapValueOperator.putAll(m);\n    }\n\n    @Override\n    public void clear() {\n        mapValueOperator.clear();\n    }\n\n    @Override\n    public Set<K> keySet() {\n        return mapValueOperator.keySet();\n    }\n\n    @Override\n    public Collection<V> values() {\n        return mapValueOperator.values();\n    }\n\n    @Override\n    public RealmMap<K, V> freeze() {\n        return freezeInternal(mapValueOperator.freeze());\n    }\n\n    @Override\n    public void notifyChangeListeners(long nativeChangeSetPtr) {\n        MapChangeSet<K> mapChangeSet = new MapChangeSetImpl<>(changeSetFactory(nativeChangeSetPtr));\n        if (mapChangeSet.isEmpty()) {\n            // First callback we get is right after subscription: do nothing\n            return;\n        }\n        mapObserverPairs.foreach(new Callback<>(mapChangeSet));\n    }\n\n    void addChangeListener(RealmMap<K, V> realmMap, MapChangeListener<K, V> listener) {\n            CollectionUtils.checkForAddRemoveListener(baseRealm, listener, true);\n        if (mapObserverPairs.isEmpty()) {\n            mapValueOperator.startListening(this);\n        }\n        ObservableMap.MapObserverPair<K, V> mapObserverPair = new MapObserverPair<>(realmMap, listener);\n        mapObserverPairs.add(mapObserverPair);\n    }\n\n    void addChangeListener(RealmMap<K, V> realmMap, RealmChangeListener<RealmMap<K, V>> listener) {\n        addChangeListener(realmMap, new RealmChangeListenerWrapper<>(listener));\n    }\n\n    void removeListener(RealmMap<K, V> realmMap, MapChangeListener<K, V> listener) {\n        mapObserverPairs.remove(realmMap, listener);\n        if (mapObserverPairs.isEmpty()) {\n            mapValueOperator.stopListening();\n        }\n    }\n\n    void removeListener(RealmMap<K, V> realmMap, RealmChangeListener<RealmMap<K, V>> listener) {\n        removeListener(realmMap, new RealmChangeListenerWrapper<>(listener));\n    }\n\n    void removeAllChangeListeners() {\n        CollectionUtils.checkForAddRemoveListener(baseRealm, null, false);\n        mapObserverPairs.clear();\n        mapValueOperator.stopListening();\n    }\n\n    boolean hasListeners() {\n        return !mapObserverPairs.isEmpty();\n    }\n\n    boolean isNotNullItemTypeValid(@Nullable Object item, Class<?> clazz) {\n        return item == null || item.getClass() == clazz;\n    }\n\n    OsMap getOsMap() {\n        return mapValueOperator.osMap;\n    }\n\n    String getClassName() {\n        return typeSelectorForMap.getValueClassName();\n    }\n\n    Class<V> getValueClass() {\n        return typeSelectorForMap.getValueClass();\n    }\n}\n\n/**\n * Specialization for {@link ManagedMapManager}s targeting {@link RealmDictionary}.\n * <p>\n * Dictionaries can in turn contain values of type {@link RealmAny} and Realm primitive types, i.e.\n * integer, boolean, string, byte array, date, float, double, decimal, object id, UUID and\n * {@link RealmModel}.\n * <p>\n * A {@link MapValueOperator} representing the {@code V}-value type has to be used when\n * instantiating this operator.\n *\n * @param <V> the value type\n */\nclass DictionaryManager<V> extends ManagedMapManager<String, V> {\n\n    DictionaryManager(BaseRealm baseRealm,\n                      MapValueOperator<String, V> mapValueOperator,\n                      TypeSelectorForMap<String, V> typeSelectorForMap) {\n        super(baseRealm, mapValueOperator, typeSelectorForMap);\n    }\n\n    @Override\n    boolean containsKeyInternal(Object key) {\n        if (key == null) {\n            throw new NullPointerException(\"Null keys are not allowed when calling 'containsKey'.\");\n        }\n        if (!isNotNullItemTypeValid(key, String.class)) {\n            throw new ClassCastException(\"Only String keys can be used with 'containsKey'.\");\n        }\n        return mapValueOperator.containsKey(key);\n    }\n\n    @Override\n    void validateMap(Map<? extends String, ? extends V> map) {\n        for (Map.Entry<? extends String, ? extends V> entry : map.entrySet()) {\n            String key = entry.getKey();\n            if (key == null) {\n                throw new NullPointerException(\"Null keys are not allowed.\");\n            }\n        }\n    }\n\n    @Override\n    RealmDictionary<V> freezeInternal(Pair<BaseRealm, OsMap> frozenBaseRealmMap) {\n        BaseRealm frozenBaseRealm = frozenBaseRealmMap.first;\n        return typeSelectorForMap.freeze(frozenBaseRealm);\n    }\n\n    @Override\n    public V get(Object key) {\n        if (key == null) {\n            throw new NullPointerException(\"Null keys are not allowed when calling 'get'.\");\n        }\n        if (!isNotNullItemTypeValid(key, String.class)) {\n            throw new ClassCastException(\"Only String keys can be used with 'containsKey'.\");\n        }\n\n        return mapValueOperator.get((String) key);\n    }\n\n    @Override\n    public V put(String key, @Nullable V value) {\n        if (key == null) {\n            throw new NullPointerException(\"Null keys are not allowed.\");\n        }\n        try {\n            return mapValueOperator.put(key, value);\n        } catch (IllegalStateException e) {\n            // If the exception caught here is caused by adding null to a dictionary marked as\n            // \"@Required\" we have to convert it to NullPointerException as per the Java Map\n            // interface\n            if (Objects.requireNonNull(e.getMessage()).contains(\"Data type mismatch\")) {\n                throw new NullPointerException(\"Cannot insert null values in a dictionary marked with '@Required'.\");\n            } else {\n                throw e;\n            }\n        }\n    }\n\n    @Override\n    public Set<Entry<String, V>> entrySet() {\n        return mapValueOperator.entrySet();\n    }\n\n    @Override\n    MapChangeSet<String> changeSetFactory(long nativeChangeSetPtr) {\n        return new StringMapChangeSet(nativeChangeSetPtr);\n    }\n}\n\n/**\n * Abstraction for different map value types. Here are defined as generics but specializations\n * should provide concrete types.\n *\n * @param <K> the key type\n * @param <V> the value type\n */\nabstract class MapValueOperator<K, V> {\n\n    protected final Class<V> valueClass;\n    protected final BaseRealm baseRealm;\n    protected final OsMap osMap;\n    protected final TypeSelectorForMap<K, V> typeSelectorForMap;\n    protected final RealmMapEntrySet.IteratorType iteratorType;\n\n    MapValueOperator(Class<V> valueClass,\n                     BaseRealm baseRealm,\n                     OsMap osMap,\n                     TypeSelectorForMap<K, V> typeSelectorForMap,\n                     RealmMapEntrySet.IteratorType iteratorType) {\n        this.valueClass = valueClass;\n        this.baseRealm = baseRealm;\n        this.osMap = osMap;\n        this.typeSelectorForMap = typeSelectorForMap;\n        this.iteratorType = iteratorType;\n    }\n\n    @Nullable\n    abstract V get(K key);\n\n    @Nullable\n    abstract V put(K key, @Nullable V value);\n\n    abstract Set<Map.Entry<K, V>> entrySet();\n\n    abstract boolean containsValueInternal(@Nullable Object value);\n\n    void remove(Object key) {\n        osMap.remove(key);\n    }\n\n    int size() {\n        return (int) osMap.size();\n    }\n\n    boolean isEmpty() {\n        return osMap.size() == 0;\n    }\n\n    boolean containsKey(Object key) {\n        return osMap.containsKey(key);\n    }\n\n    boolean containsValue(@Nullable Object value) {\n        if (value != null && value.getClass() != valueClass) {\n            throw new ClassCastException(\"Only '\" + valueClass.getSimpleName() +\n                    \"'  values can be used with 'containsValue'.\");\n        }\n        return containsValueInternal(value);\n    }\n\n    boolean isValid() {\n        if (baseRealm.isClosed()) {\n            return false;\n        }\n        return osMap.isValid();\n    }\n\n    boolean isFrozen() {\n        return baseRealm.isFrozen();\n    }\n\n    void clear() {\n        osMap.clear();\n    }\n\n    void putAll(Map<? extends K, ? extends V> map) {\n        // TODO: inefficient, pass array of keys and array of values to JNI instead,\n        //  which requires operators to implement it as it varies from type to type\n        for (Map.Entry<? extends K, ? extends V> entry : map.entrySet()) {\n            put(entry.getKey(), entry.getValue());\n        }\n    }\n\n    Set<K> keySet() {\n        return typeSelectorForMap.keySet();\n    }\n\n    Collection<V> values() {\n        return typeSelectorForMap.getValues();\n    }\n\n    Pair<BaseRealm, OsMap> freeze() {\n        BaseRealm frozenRealm = baseRealm.freeze();\n        return new Pair<>(frozenRealm, osMap.freeze(frozenRealm.sharedRealm));\n    }\n\n    void startListening(ObservableMap observableMap) {\n        osMap.startListening(observableMap);\n    }\n\n    void stopListening() {\n        osMap.stopListening();\n    }\n}\n\n/**\n * {@link MapValueOperator} targeting {@link RealmAny} values in {@link RealmMap}s.\n */\nclass RealmAnyValueOperator<K> extends MapValueOperator<K, RealmAny> {\n\n    RealmAnyValueOperator(BaseRealm baseRealm,\n                       OsMap osMap,\n                       TypeSelectorForMap<K, RealmAny> typeSelectorForMap) {\n        super(RealmAny.class, baseRealm, osMap, typeSelectorForMap, RealmMapEntrySet.IteratorType.MIXED);\n    }\n\n    @Nullable\n    @Override\n    RealmAny get(Object key) {\n        long realmAnyPtr = osMap.getRealmAnyPtr(key);\n        if (realmAnyPtr == OsMap.NOT_FOUND) {\n            return null;\n        }\n        NativeRealmAny nativeRealmAny = new NativeRealmAny(realmAnyPtr);\n        return new RealmAny(RealmAnyOperator.fromNativeRealmAny(baseRealm, nativeRealmAny));\n    }\n\n    @Nullable\n    @Override\n    RealmAny put(Object key, @Nullable RealmAny value) {\n        RealmAny original = get(key);\n\n        if (value == null) {\n            osMap.put(key, null);\n        } else {\n            osMap.putRealmAny(key, CollectionUtils.copyToRealmIfNeeded(baseRealm, value).getNativePtr());\n        }\n        return original;\n    }\n\n    @Override\n    Set<Map.Entry<K, RealmAny>> entrySet() {\n        return new RealmMapEntrySet<>(baseRealm, osMap, RealmMapEntrySet.IteratorType.MIXED, null);\n    }\n\n    @Override\n    boolean containsValueInternal(@Nullable Object value) {\n        // RealmAny dictionaries store null values as RealmAny.nullValue()\n        if (value == null) {\n            return false;\n        }\n        if (value instanceof RealmAny) {\n            return osMap.containsRealmAnyValue(((RealmAny) value).getNativePtr());\n        }\n        throw new IllegalArgumentException(\"This dictionary can only contain 'RealmAny' values.\");\n    }\n}\n\n/**\n * {@link MapValueOperator} targeting boxable values in {@link RealmMap}s.\n */\nclass GenericPrimitiveValueOperator<K, V> extends MapValueOperator<K, V> {\n\n    private final EqualsHelper<K, V> equalsHelper;\n\n    GenericPrimitiveValueOperator(Class<V> valueClass,\n                                  BaseRealm baseRealm,\n                                  OsMap osMap,\n                                  TypeSelectorForMap<K, V> typeSelectorForMap,\n                                  RealmMapEntrySet.IteratorType iteratorType) {\n        this(valueClass, baseRealm, osMap, typeSelectorForMap, iteratorType, new GenericEquals<>());\n    }\n\n    GenericPrimitiveValueOperator(Class<V> valueClass,\n                                  BaseRealm baseRealm,\n                                  OsMap osMap,\n                                  TypeSelectorForMap<K, V> typeSelectorForMap,\n                                  RealmMapEntrySet.IteratorType iteratorType,\n                                  EqualsHelper<K, V> equalsHelper) {\n        super(valueClass, baseRealm, osMap, typeSelectorForMap, iteratorType);\n        this.equalsHelper = equalsHelper;\n    }\n\n    @Nullable\n    @Override\n    V get(Object key) {\n        Object value = osMap.get(key);\n        if (value == null) {\n            return null;\n        }\n        return processValue(value);\n    }\n\n    @Nullable\n    @Override\n    V put(K key, @Nullable V value) {\n        V original = get(key);\n        osMap.put(key, value);\n        return original;\n    }\n\n    @Override\n    Set<Map.Entry<K, V>> entrySet() {\n        return new RealmMapEntrySet<>(baseRealm, osMap, iteratorType, equalsHelper, null);\n    }\n\n    @Override\n    boolean containsValueInternal(@Nullable Object value) {\n        return osMap.containsPrimitiveValue(value);\n    }\n\n    /**\n     * Normally it is enough with typecasting the value to {@code T}, but e.g. {@link Long} cannot\n     * be cast directly to {@link Integer} so a special operator has to override this method to do\n     * it.\n     *\n     * @param value the value of the dictionary entry as an {@link Object}.\n     * @return the value in its right form\n     */\n    @Nullable\n    V processValue(Object value) {\n        //noinspection unchecked\n        return (V) value;\n    }\n}\n\n/**\n * {@link MapValueOperator} targeting {@link Integer} values in {@link RealmMap}s. Use this one\n * instead of {@link GenericPrimitiveValueOperator} to avoid and typecast exception when converting the\n * {@link Long} result from JNI to {@link Integer}.\n */\nclass IntegerValueOperator<K> extends GenericPrimitiveValueOperator<K, Integer> {\n\n    IntegerValueOperator(BaseRealm baseRealm,\n                         OsMap osMap,\n                         TypeSelectorForMap<K, Integer> typeSelectorForMap) {\n        super(Integer.class, baseRealm, osMap, typeSelectorForMap, RealmMapEntrySet.IteratorType.INTEGER);\n    }\n\n    @Override\n    Integer processValue(Object value) {\n        return ((Long) value).intValue();\n    }\n}\n\n/**\n * {@link MapValueOperator} targeting {@link Short} values in {@link RealmMap}s. Use this one\n * instead of {@link GenericPrimitiveValueOperator} to avoid and typecast exception when converting the\n * {@link Long} result from JNI to {@link Short}.\n */\nclass ShortValueOperator<K> extends GenericPrimitiveValueOperator<K, Short> {\n\n    ShortValueOperator(BaseRealm baseRealm,\n                       OsMap osMap,\n                       TypeSelectorForMap<K, Short> typeSelectorForMap) {\n        super(Short.class, baseRealm, osMap, typeSelectorForMap, RealmMapEntrySet.IteratorType.SHORT);\n    }\n\n    @Override\n    Short processValue(Object value) {\n        return ((Long) value).shortValue();\n    }\n}\n\n/**\n * {@link MapValueOperator} targeting {@link Byte} values in {@link RealmMap}s. Use this one\n * instead of {@link GenericPrimitiveValueOperator} to avoid and typecast exception when converting the\n * {@link Long} result from JNI to {@link Byte}.\n */\nclass ByteValueOperator<K> extends GenericPrimitiveValueOperator<K, Byte> {\n\n    ByteValueOperator(BaseRealm baseRealm,\n                      OsMap osMap,\n                      TypeSelectorForMap<K, Byte> typeSelectorForMap) {\n        super(Byte.class, baseRealm, osMap, typeSelectorForMap, RealmMapEntrySet.IteratorType.BYTE);\n    }\n\n    @Override\n    Byte processValue(Object value) {\n        return ((Long) value).byteValue();\n    }\n}\n\n/**\n * {@link MapValueOperator} targeting {@link RealmModel}s values in {@link RealmMap}s.\n */\nclass RealmModelValueOperator<K, V> extends MapValueOperator<K, V> {\n\n    RealmModelValueOperator(BaseRealm baseRealm,\n                            OsMap osMap,\n                            TypeSelectorForMap<K, V> typeSelectorForMap) {\n        //noinspection unchecked\n        super((Class<V>) RealmModel.class, baseRealm, osMap, typeSelectorForMap, RealmMapEntrySet.IteratorType.OBJECT);\n    }\n\n    @Nullable\n    @Override\n    V get(Object key) {\n        long realmModelKey = osMap.getModelRowKey(key);\n        if (realmModelKey == OsMap.NOT_FOUND) {\n            return null;\n        }\n\n        return typeSelectorForMap.getRealmModel(baseRealm, realmModelKey);\n    }\n\n    @Nullable\n    @Override\n    V put(K key, @Nullable V value) {\n        return typeSelectorForMap.putRealmModel(baseRealm, osMap, key, value);\n    }\n\n    @Override\n    Set<Map.Entry<K, V>> entrySet() {\n        return new RealmMapEntrySet<>(baseRealm, osMap, RealmMapEntrySet.IteratorType.OBJECT, typeSelectorForMap);\n    }\n\n    @Override\n    boolean containsValueInternal(@Nullable Object value) {\n        if (value == null) {\n            return osMap.containsPrimitiveValue(null);\n        } else if (value instanceof RealmObjectProxy) {\n            Row row$realm = ((RealmObjectProxy) value).realmGet$proxyState().getRow$realm();\n            long tablePtr = row$realm.getTable().getNativePtr();\n            return osMap.containsRealmModel(row$realm.getObjectKey(), tablePtr);\n        }\n        throw new IllegalArgumentException(\"Only managed models can be contained in this dictionary.\");\n    }\n\n    @Override\n    boolean containsValue(@Nullable Object value) {\n        if (value != null && !RealmModel.class.isAssignableFrom(value.getClass())) {\n            throw new ClassCastException(\"Only RealmModel values can be used with 'containsValue'.\");\n        }\n        return containsValueInternal(value);\n    }\n}\n\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/MapChangeListener.java",
    "content": "/*\n * Copyright 2021 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\npackage io.realm;\n\n/**\n * {@link MapChangeListener} can be registered with a {@link RealmMap} to receive a notification\n * with a {@link MapChangeSet} to describe the details of what have been changed in the map since\n * last time.\n * <p>\n * Realm instances on a thread without an {@link android.os.Looper} cannot register a\n * {@link MapChangeListener}.\n * <p>\n *\n * @param <K> the type of the keys stored in the map\n * @param <V> the type of the values stored in the map\n * @see RealmMap#addChangeListener(MapChangeListener)\n */\npublic interface MapChangeListener<K, V> {\n\n    /**\n     * This will be called when the async query is finished the first time or the collection of objects has changed.\n     *\n     * @param map     the map this listener is registered to.\n     * @param changes object with information about the change.\n     */\n    void onChange(RealmMap<K, V> map, MapChangeSet<K> changes);\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/MapChangeSet.java",
    "content": "/*\n * Copyright 2021 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\npackage io.realm;\n\nimport io.realm.internal.OsMapChangeSet;\n\n/**\n * This interface describes the changes made to a map during the last update.\n * <p>\n * {@link MapChangeSet} is passed to the {@link MapChangeListener} which is registered\n * by {@link RealmMap#addChangeListener(MapChangeListener)}.\n */\npublic interface MapChangeSet<T> {\n\n    /**\n     * The number of entries that have been deleted in the previous version of the map.\n     *\n     * @return array with the keys that have been deleted.\n     */\n    T[] getDeletions();\n\n    /**\n     * Array containing the keys that have been inserted in the previous version of the map.\n     *\n     * @return array with the keys that have been inserted.\n     */\n    T[] getInsertions();\n\n    /**\n     * Array containing the keys that have been modified in the previous version of the map.\n     *\n     * @return array with the keys that have been modified.\n     */\n    T[] getChanges();\n\n    /**\n     * Whether the change set is empty or not. This is needed to detect whether a notification has\n     * been triggered right after subscription.\n     *\n     * @return whether the change set contains changes.\n     */\n    boolean isEmpty();\n}\n\n/**\n * Generic implementation of a {@link MapChangeSet}. This class forwards the fetching of the changes\n * to a delegate according to the key type. For now only {@code String} keys are allowed.\n *\n * @param <K> the type of the keys stored in the map\n */\nclass MapChangeSetImpl<K> implements MapChangeSet<K> {\n\n    private final MapChangeSet<K> delegate;\n\n    MapChangeSetImpl(MapChangeSet<K> delegate) {\n        this.delegate = delegate;\n    }\n\n    @Override\n    public K[] getDeletions() {\n        return delegate.getDeletions();\n    }\n\n    @Override\n    public K[] getInsertions() {\n        return delegate.getInsertions();\n    }\n\n    @Override\n    public K[] getChanges() {\n        return delegate.getChanges();\n    }\n\n    @Override\n    public boolean isEmpty() {\n        return delegate.isEmpty();\n    }\n}\n\n/**\n * Delegate for {@code String} keys. Used for changes in {@link RealmDictionary}.\n */\nclass StringMapChangeSet implements MapChangeSet<String> {\n\n    private final OsMapChangeSet osMapChangeSet;\n\n    StringMapChangeSet(long nativePtr) {\n        osMapChangeSet = new OsMapChangeSet(nativePtr);\n    }\n\n    @Override\n    public String[] getDeletions() {\n        return osMapChangeSet.getStringKeyDeletions();\n    }\n\n    @Override\n    public String[] getInsertions() {\n        return osMapChangeSet.getStringKeyInsertions();\n    }\n\n    @Override\n    public String[] getChanges() {\n        return osMapChangeSet.getStringKeyModifications();\n    }\n\n    @Override\n    public boolean isEmpty() {\n        return osMapChangeSet.isEmpty();\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/MutableRealmInteger.java",
    "content": "/*\n * Copyright 2017 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 */\npackage io.realm;\n\nimport javax.annotation.Nullable;\n\nimport io.realm.annotations.Beta;\nimport io.realm.internal.ManageableObject;\nimport io.realm.internal.Row;\nimport io.realm.internal.Table;\n\n\n/**\n * A {@code MutableRealmInteger} is a mutable, {@link Long}-like numeric quantity.\n * It behaves almost exactly as a reference to a {@link Long}. More specifically:\n * <ul>\n * <li>A {@code MutableRealmInteger} may have the value {@code null}.</li>\n * <li>The {@link #equals} operator compares the contained {@link Long} values. {@code null}-valued {@code MutableRealmInteger} are {@code .equals}</li>\n * <li>The {@link #compareTo} operator compares the contained {@link Long} values.  It considers {@code null} &lt; any non-{@code null} value.</li>\n * <li>The {@link #increment} and {@link #decrement} operators throw {@link IllegalStateException} when applied to a {@code null}-valued {@code MutableRealmInteger}.</li>\n * </ul>\n * <p>\n *\n * {@code MutableRealmInteger}s are most interesting as members of a managed {@link RealmModel} object.\n * When managed, the {@link #increment} and {@link #decrement} operators implement a\n * <a href=\"https://en.wikipedia.org/wiki/Conflict-free_replicated_data_type\">conflict free replicated data type</a>:\n * Simultaneous increments and decrements from multiple distributed clients will be aggregated correctly.\n * For instance, if the value of {@code counter} field for the object representing user \"Fred\" is currently 0,\n * then the following code, executed on two different devices, simultaneously, even if connected by only a slow,\n * unreliable network, will <b>always</b> cause the value of {@code counter} to converge, eventually on the value 2.\n * <pre>\n * <code> MutableRealmInteger counter = realm.where(Users.class)\n *     .equalTo(\"name\", Fred)\n *     .findFirst()\n *     .counter.increment(1);</code>\n * </pre>\n * Note that the {@link #set(Long)} operator must be used with extreme care. It will quash the effects of any prior calls\n * to {@link #increment(long)} or {@link #decrement(long)}. Although the value of a {@code MutableRealmInteger} will\n * always converge across devices, the specific value on which it converges will depend on the actual order in which\n * operations took place. Mixing {@link #set(Long)} with {@link #increment(long)} and {@link #decrement(long)} is,\n * therefore, not advised, unless fuzzy counting is acceptable.\n * <p>\n *\n * {@code MutableRealmInteger}s may not be primary keys. Their implementations are not thread safe.\n * Like all managed Realm objects, managed {@code MutableRealmInteger}s may not be moved across threads.\n * Unmanaged {@code MutableRealmInteger}s may be moved across threads but require safe publication.\n * <p>\n *\n * A {@code MutableRealmInteger}, in a model class, must always be declared {@code final}. For instance:\n * <pre>\n * {@code public final MutableRealmInteger counter = MutableRealmInteger.ofNull(); }\n * </pre>\n * Although initializing the {@code MutableRealmInteger} as {@code null} may work very limited circumstances,\n * developers are advised <b>not</b> to do it:\n * <pre>\n * {@code\n *  public final MutableRealmInteger counter = null; // DO NOT DO THIS! }\n * </pre>\n * Also note that when a {@code MutableRealmInteger} is {@code @Required}, it is better, though not required,\n * to initialize it with a non-null value.\n * <pre>\n * <code>\n * {@literal @}Required\n *  public final MutableRealmInteger counter = MutableRealmInteger.valueOf(0L);</code>\n * </pre>\n *\n *<p>\n * A reference to a managed {@code MutableRealmInteger} is subject to all of the constraints that apply\n * to the model object from which it was obtained: It can only be mutated within a transaction and\n * it becomes invalid if the Realm backing it is closed. Use the {@code isManaged()}\n * and {@code isValid()} operators to determine whether a {@code MutableRealmInteger} is\n * in a consistent state. Note, in particular, that a reference to a managed {@code MutableRealmInteger}\n * retains a reference to the model object to which it belongs. For example in this code:\n * <pre>\n * {@code MutableRealmInteger counter = realm.where(Users.class).findFirst().counter; }\n * </pre>\n * the {@code counter} holds a reference to the {@code User} model object from which it was obtained.\n * Neither can be GCed until all references to both are unreachable.\n */\n@Beta\npublic abstract class MutableRealmInteger implements Comparable<MutableRealmInteger>, ManageableObject {\n\n    /**\n     * Unmanaged Implementation.\n     */\n    private static final class Unmanaged extends MutableRealmInteger {\n        @Nullable\n        private Long value;\n\n        Unmanaged(@Nullable Long value) {\n            this.value = value;\n        }\n\n        @Override\n        public boolean isManaged() {\n            return false;\n        }\n\n        @Override\n        public boolean isValid() {\n            return true;\n        }\n\n        @Override\n        public boolean isFrozen() {\n            return false;\n        }\n\n        @Override\n        public void set(@Nullable Long newValue) {\n            value = newValue;\n        }\n\n        @Override\n        @Nullable\n        public Long get() {\n            return value;\n        }\n\n        @Override\n        public void increment(long inc) {\n            if (value == null) {\n                throw new IllegalStateException(\"Cannot increment a MutableRealmInteger whose value is null. Set its value first.\");\n            }\n            //noinspection UnnecessaryBoxing\n            value = Long.valueOf(value + inc);\n        }\n\n        @Override\n        public void decrement(long dec) {\n            increment(-dec);\n        }\n    }\n\n\n    /**\n     * Managed Implementation.\n     * Proxies create new subclasses for each {@code MutableRealmInteger} field.\n     */\n    @SuppressWarnings(\"unused\")\n    abstract static class Managed<T extends RealmModel> extends MutableRealmInteger {\n        protected abstract ProxyState<T> getProxyState();\n\n        protected abstract long getColumnIndex();\n\n        @Override\n        public final boolean isManaged() {\n            return true;\n        }\n\n        @Override\n        public final boolean isValid() {\n            return !getRealm().isClosed() && getRow().isValid();\n        }\n\n        @Override\n        public final Long get() {\n            Row row = getRow();\n            row.checkIfAttached();\n            long columnIndex = getColumnIndex();\n            return (row.isNull(columnIndex)) ? null : row .getLong(columnIndex);\n        }\n\n        @Override\n        public final void set(@Nullable Long value) {\n            ProxyState proxyState = getProxyState();\n            proxyState.getRealm$realm().checkIfValidAndInTransaction();\n\n            if (!proxyState.isUnderConstruction()) {\n                setValue(value, false);\n                return;\n            }\n\n            if (!proxyState.getAcceptDefaultValue$realm()) {\n                return;\n            }\n\n            setValue(value, true);\n        }\n\n        @Override\n        public final void increment(long inc) {\n            getRealm().checkIfValidAndInTransaction();\n            Row row = getRow();\n            row.getTable().incrementLong(getColumnIndex(), row.getObjectKey(), inc);\n        }\n\n        @Override\n        public final void decrement(long dec) {\n            increment(-dec);\n        }\n\n        @Override\n        public boolean isFrozen() {\n            return getRealm().isFrozen();\n        }\n\n        private BaseRealm getRealm() {\n            return getProxyState().getRealm$realm();\n       }\n\n        private Row getRow() {\n            return getProxyState().getRow$realm();\n        }\n\n        private void setValue(@Nullable Long value, boolean isDefault) {\n            Row row = getRow();\n            Table table = row.getTable();\n            long rowIndex = row.getObjectKey();\n            long columnIndex = getColumnIndex();\n            if (value == null) {\n                table.setNull(columnIndex, rowIndex, isDefault);\n            } else {\n                table.setLong(columnIndex, rowIndex, value, isDefault);\n            }\n        }\n    }\n\n    /**\n     * Creates a new, unmanaged {@code MutableRealmInteger} with the specified initial value.\n     *\n     * @param value initial value.\n     */\n    public static MutableRealmInteger valueOf(Long value) {\n        return new MutableRealmInteger.Unmanaged(value);\n    }\n\n    /**\n     * Creates a new, unmanaged {@code MutableRealmInteger} whose value is {@code null}.\n     */\n    public static MutableRealmInteger ofNull() {\n        return new MutableRealmInteger.Unmanaged(null);\n    }\n\n    /**\n     * Creates a new, unmanaged {@code MutableRealmInteger} with the specified initial value.\n     *\n     * @param value initial value.\n     */\n    public static MutableRealmInteger valueOf(long value) {\n        return valueOf(Long.valueOf(value));\n    }\n\n    /**\n     * Creates a new, unmanaged {@code MutableRealmInteger} with the specified initial value.\n     *\n     * @param value initial value: parsed by {@link Long#parseLong}.\n     */\n    public static MutableRealmInteger valueOf(String value) {\n        return valueOf(Long.parseLong(value));\n    }\n\n    /**\n     * Seal the class.\n     * In fact, this allows subclasses inside the package \"realm.io\".\n     * Because it eliminates the synthetic constructor, though, we can live with that.\n     * Don't make subclasses.\n     */\n    MutableRealmInteger() {}\n\n    /**\n     * Gets the {@code MutableRealmInteger} value.\n     * The value may be null.\n     *\n     * @return the value.\n     */\n    @Nullable\n    public abstract Long get();\n\n    /**\n     * Sets the {@code MutableRealmInteger} value.\n     * Calling {@code set} forcibly sets the {@code MutableRealmInteger} to the provided value.\n     * Doing this obliterates the effects of any calls to {@link #increment} and {@link #decrement} perceived\n     * before the call to {@code set}.\n     *\n     * @param newValue new value.\n     */\n    public abstract void set(@Nullable Long newValue);\n\n    /**\n     * Sets the {@code MutableRealmInteger} value.\n     * Calling {@link #set} forcibly sets the {@code MutableRealmInteger} to the provided value.\n     * Doing this obliterates the effects of any calls to {@link #increment} and {@link #decrement} perceived\n     * before the call to {@link #set}.\n     *\n     * @param newValue new value.\n     */\n    public final void set(long newValue) {\n        set(Long.valueOf(newValue));\n    }\n\n    /**\n     * Increments the {@code MutableRealmInteger}, adding the value of the argument.\n     * Increment/decrement from all devices are reflected in the new value, which is guaranteed to converge.\n     *\n     * @param inc quantity to be added to the {@code MutableRealmInteger}.\n     */\n    public abstract void increment(long inc);\n\n    /**\n     * Decrements the {@code MutableRealmInteger}, subtracting the value of the argument.\n     * Increment/decrement from all devices are reflected in the new value, which is guaranteed to converge.\n     *\n     * @param dec quantity to be subtracted from the {@code MutableRealmInteger}.\n     */\n    public abstract void decrement(long dec);\n\n    /**\n     * @return true if and only if {@link #get} will return {@code null}.\n     */\n    public final boolean isNull() {\n        return get() == null;\n    }\n\n    /**\n     * {@code MutableRealmInteger}s compare strictly by their values.\n     * Null is a legal value for a {@code MutableRealmInteger} and {@code null} &lt; any non-{@code null} value\n     *\n     * @param o the compare target\n     * @return -1, 0, or 1, depending on whether this object's value is &lt;, =, or &gt; the target's.\n     */\n    @Override\n    public final int compareTo(MutableRealmInteger o) {\n        Long thisValue = get();\n        Long otherValue = o.get();\n        return (thisValue == null)\n                ? ((otherValue == null) ? 0 : -1)\n                : ((otherValue == null) ? 1 : thisValue.compareTo (otherValue));\n    }\n\n    /**\n     * A {@code MutableRealmInteger}'s hash code is, exactly, the hash code of its value.\n     *\n     * @return true if the target has the same value.\n     */\n    @Override\n    public final int hashCode() {\n        Long thisValue = get();\n        return (thisValue == null) ? 0 : thisValue.hashCode();\n    }\n\n    /**\n     * Two {@code MutableRealmInteger}s are {@code .equals} if and only if their {@code longValues} are equal.\n     *\n     * @param o compare target\n     * @return true if the target has the same value.\n     */\n    @Override\n    public final boolean equals(Object o) {\n        if (o == this) { return true; }\n        if (!(o instanceof MutableRealmInteger)) { return false; }\n        Long thisValue = get();\n        Long otherValue = ((MutableRealmInteger) o).get();\n        return (thisValue == null) ? otherValue == null : thisValue.equals(otherValue);\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/MutableRealmObjectSchema.java",
    "content": "/*\n * Copyright 2017 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\npackage io.realm;\n\nimport java.util.Date;\nimport java.util.Locale;\n\nimport javax.annotation.Nonnull;\n\nimport io.realm.internal.CheckedRow;\nimport io.realm.internal.OsObjectStore;\nimport io.realm.internal.OsResults;\nimport io.realm.internal.Table;\nimport io.realm.internal.Util;\n\n/**\n * Mutable {@link RealmObjectSchema}.\n */\nclass MutableRealmObjectSchema extends RealmObjectSchema {\n\n    /**\n     * Creates a mutable schema object for a given Realm class.\n     *\n     * @param realm Realm holding the objects.\n     * @param table table representation of the Realm class\n     */\n    MutableRealmObjectSchema(BaseRealm realm, RealmSchema schema, Table table) {\n        super(realm, schema, table, new DynamicColumnIndices(table));\n    }\n\n    @Override\n    public RealmObjectSchema setClassName(String className) {\n        realm.checkNotInSync(); // renaming a table is not permitted\n        checkEmpty(className);\n        String internalTableName = Table.getTableNameForClass(className);\n        if (className.length() > Table.CLASS_NAME_MAX_LENGTH) {\n            throw new IllegalArgumentException(String.format(Locale.US,\n                    \"Class name is too long. Limit is %1$d characters: \\'%2$s\\' (%3$d)\",\n                    Table.CLASS_NAME_MAX_LENGTH, className, className.length()));\n        }\n        //noinspection ConstantConditions\n        if (realm.sharedRealm.hasTable(internalTableName)) {\n            throw new IllegalArgumentException(\"Class already exists: \" + className);\n        }\n        // in case this table has a primary key, we need to transfer it after renaming the table.\n        //noinspection ConstantConditions\n        @Nonnull String oldTableName = table.getName();\n        @Nonnull String oldClassName = table.getClassName();\n        String pkField = OsObjectStore.getPrimaryKeyForObject(realm.sharedRealm, oldClassName);\n        if (pkField != null) {\n            OsObjectStore.setPrimaryKeyForObject(realm.sharedRealm, oldClassName, null);\n        }\n        realm.sharedRealm.renameTable(oldTableName, internalTableName);\n        if (pkField != null) {\n            try {\n                OsObjectStore.setPrimaryKeyForObject(realm.sharedRealm, className, pkField);\n            } catch (Exception e) {\n                // revert the table name back when something goes wrong\n                //noinspection ConstantConditions\n                realm.sharedRealm.renameTable(table.getName(), oldTableName);\n                throw e;\n            }\n        }\n        return this;\n    }\n\n    private void checkEmpty(String str) {\n        //noinspection ConstantConditions\n        if (str == null || str.isEmpty()) {\n            throw new IllegalArgumentException(\"Null or empty class names are not allowed\");\n        }\n    }\n\n    @Override\n    public RealmObjectSchema addField(String fieldName, Class<?> fieldType, FieldAttribute... attributes) {\n        FieldMetaData metadata = SUPPORTED_LIST_SIMPLE_FIELDS.get(fieldType);\n        if (metadata == null) {\n            if (SUPPORTED_LINKED_FIELDS.containsKey(fieldType)) {\n                throw new IllegalArgumentException(\"Use addRealmObjectField() instead to add fields that link to other RealmObjects: \" + fieldName);\n            } else if (RealmModel.class.isAssignableFrom(fieldType)) {\n                throw new IllegalArgumentException(String.format(Locale.US,\n                        \"Use 'addRealmObjectField()' instead to add fields that link to other RealmObjects: %s(%s)\",\n                        fieldName, fieldType));\n            } else {\n                throw new IllegalArgumentException(String.format(Locale.US,\n                        \"Realm doesn't support this field type: %s(%s)\",\n                        fieldName, fieldType));\n            }\n        }\n\n        if (containsAttribute(attributes, FieldAttribute.PRIMARY_KEY)) {\n            checkAddPrimaryKeyForSync();\n            checkForObjectStoreInvalidPrimaryKeyTypes(fieldName, fieldType);\n        }\n\n        checkNewFieldName(fieldName);\n        boolean nullable = metadata.defaultNullable;\n        if (containsAttribute(attributes, FieldAttribute.REQUIRED)) {\n            nullable = false;\n        }\n\n        long columnKey = table.addColumn(metadata.fieldType, fieldName, nullable);\n        try {\n            addModifiers(fieldName, attributes);\n        } catch (Exception e) {\n            // Modifiers have been removed by the addModifiers method()\n            table.removeColumn(columnKey);\n            throw e;\n        }\n        return this;\n    }\n\n    @Override\n    public RealmObjectSchema addRealmObjectField(String fieldName, RealmObjectSchema objectSchema) {\n        checkLegalName(fieldName);\n        checkFieldNameIsAvailable(fieldName);\n        table.addColumnLink(RealmFieldType.OBJECT, fieldName,\n                realm.sharedRealm.getTable(Table.getTableNameForClass(objectSchema.getClassName())));\n        return this;\n    }\n\n    @Override\n    public RealmObjectSchema addRealmListField(String fieldName, RealmObjectSchema objectSchema) {\n        checkLegalName(fieldName);\n        checkFieldNameIsAvailable(fieldName);\n        table.addColumnLink(RealmFieldType.LIST, fieldName, realm.sharedRealm.getTable(Table.getTableNameForClass(objectSchema.getClassName())));\n        return this;\n    }\n\n    @Override\n    public RealmObjectSchema addRealmListField(String fieldName, Class<?> primitiveType) {\n        checkLegalName(fieldName);\n        checkFieldNameIsAvailable(fieldName);\n\n        FieldMetaData metadata = SUPPORTED_LIST_SIMPLE_FIELDS.get(primitiveType);\n        if (metadata == null) {\n            if (primitiveType.equals(RealmObjectSchema.class) || RealmModel.class.isAssignableFrom(primitiveType)) {\n                throw new IllegalArgumentException(\"Use 'addRealmListField(String name, RealmObjectSchema schema)' instead to add lists that link to other RealmObjects: \" + fieldName);\n            } else {\n                throw new IllegalArgumentException(String.format(Locale.US,\n                        \"RealmList does not support lists with this type: %s(%s)\",\n                        fieldName, primitiveType));\n            }\n        }\n        table.addColumn(metadata.collectionType, fieldName, metadata.defaultNullable);\n        return this;\n    }\n\n    @Override\n    public RealmObjectSchema addRealmDictionaryField(String fieldName, Class<?> primitiveType) {\n        checkLegalName(fieldName);\n        checkFieldNameIsAvailable(fieldName);\n\n        FieldMetaData metadata = SUPPORTED_DICTIONARY_SIMPLE_FIELDS.get(primitiveType);\n        if (metadata == null) {\n            if (primitiveType.equals(RealmObjectSchema.class) || RealmModel.class.isAssignableFrom(primitiveType)) {\n                throw new IllegalArgumentException(\"Use 'addRealmDictionaryField(String name, RealmObjectSchema schema)' instead to add dictionaries that link to other RealmObjects: \" + fieldName);\n            } else {\n                throw new IllegalArgumentException(String.format(Locale.US,\n                        \"RealmDictionary does not support dictionaries with this type: %s(%s)\",\n                        fieldName, primitiveType));\n            }\n        }\n        table.addColumn(metadata.collectionType, fieldName, metadata.defaultNullable);\n        return this;\n    }\n\n    @Override\n    public RealmObjectSchema addRealmDictionaryField(String fieldName, RealmObjectSchema objectSchema) {\n        checkLegalName(fieldName);\n        checkFieldNameIsAvailable(fieldName);\n        table.addColumnDictionaryLink(RealmFieldType.STRING_TO_LINK_MAP, fieldName, realm.sharedRealm.getTable(Table.getTableNameForClass(objectSchema.getClassName())));\n        return this;\n    }\n\n    @Override\n    public RealmObjectSchema addRealmSetField(String fieldName, RealmObjectSchema objectSchema) {\n        checkLegalName(fieldName);\n        checkFieldNameIsAvailable(fieldName);\n        table.addColumnSetLink(RealmFieldType.LINK_SET, fieldName, realm.sharedRealm.getTable(Table.getTableNameForClass(objectSchema.getClassName())));\n        return this;\n    }\n\n    @Override\n    public RealmObjectSchema addRealmSetField(String fieldName, Class<?> primitiveType) {\n        checkLegalName(fieldName);\n        checkFieldNameIsAvailable(fieldName);\n\n        FieldMetaData metadata = SUPPORTED_SET_SIMPLE_FIELDS.get(primitiveType);\n        if (metadata == null) {\n            if (primitiveType.equals(RealmObjectSchema.class) || RealmModel.class.isAssignableFrom(primitiveType)) {\n                throw new IllegalArgumentException(\"Use 'addRealmSetField(String name, RealmObjectSchema schema)' instead to add sets that link to other RealmObjects: \" + fieldName);\n            } else {\n                throw new IllegalArgumentException(String.format(Locale.US,\n                        \"RealmSet does not support sets with this type: %s(%s)\",\n                        fieldName, primitiveType));\n            }\n        }\n        table.addColumn(metadata.collectionType, fieldName, metadata.defaultNullable);\n        return this;\n    }\n\n    @Override\n    public RealmObjectSchema removeField(String fieldName) {\n        realm.checkNotInSync(); // destructive modification of a schema is not permitted\n        checkLegalName(fieldName);\n        if (!hasField(fieldName)) {\n            throw new IllegalStateException(fieldName + \" does not exist.\");\n        }\n        long columnKey = getColumnKey(fieldName);\n        String className = getClassName();\n        if (fieldName.equals(OsObjectStore.getPrimaryKeyForObject(realm.sharedRealm, className))) {\n            OsObjectStore.setPrimaryKeyForObject(realm.sharedRealm, className, fieldName);\n        }\n        table.removeColumn(columnKey);\n        return this;\n    }\n\n    @Override\n    public RealmObjectSchema renameField(String currentFieldName, String newFieldName) {\n        realm.checkNotInSync(); // destructive modification of a schema is not permitted\n        checkLegalName(currentFieldName);\n        checkFieldExists(currentFieldName);\n        checkLegalName(newFieldName);\n        checkFieldNameIsAvailable(newFieldName);\n        long columnKey = getColumnKey(currentFieldName);\n        table.renameColumn(columnKey, newFieldName);\n\n        // ATTENTION: We don't need to re-set the PK table here since the column key won't be changed when renaming.\n\n        return this;\n    }\n\n    @Override\n    public RealmObjectSchema addIndex(String fieldName) {\n        checkLegalName(fieldName);\n        checkFieldExists(fieldName);\n        long columnKey = getColumnKey(fieldName);\n        if (table.hasSearchIndex(columnKey)) {\n            throw new IllegalStateException(fieldName + \" already has an index.\");\n        }\n        table.addSearchIndex(columnKey);\n        return this;\n    }\n\n    @Override\n    public RealmObjectSchema removeIndex(String fieldName) {\n        realm.checkNotInSync(); // Destructive modifications are not permitted.\n        checkLegalName(fieldName);\n        checkFieldExists(fieldName);\n        long columnKey = getColumnKey(fieldName);\n        if (!table.hasSearchIndex(columnKey)) {\n            throw new IllegalStateException(\"Field is not indexed: \" + fieldName);\n        }\n        table.removeSearchIndex(columnKey);\n        return this;\n    }\n\n    @Override\n    public RealmObjectSchema addPrimaryKey(String fieldName) {\n        checkAddPrimaryKeyForSync();\n        checkLegalName(fieldName);\n        checkFieldExists(fieldName);\n        String currentPKField = OsObjectStore.getPrimaryKeyForObject(realm.sharedRealm, getClassName());\n        if (currentPKField != null) {\n            throw new IllegalStateException(\n                    String.format(Locale.ENGLISH, \"Field '%s' has been already defined as primary key.\",\n                            currentPKField));\n        }\n        long columnKey = getColumnKey(fieldName);\n        final RealmFieldType fieldType = getFieldType(fieldName);\n        checkForObjectStoreInvalidPrimaryKeyTypes(fieldName, fieldType);\n        if (fieldType != RealmFieldType.STRING && !table.hasSearchIndex(columnKey)) {\n            // No exception will be thrown since adding PrimaryKey implies the column has an index.\n            table.addSearchIndex(columnKey);\n        }\n        OsObjectStore.setPrimaryKeyForObject(realm.sharedRealm, getClassName(), fieldName);\n        return this;\n    }\n\n    @Override\n    public RealmObjectSchema removePrimaryKey() {\n        realm.checkNotInSync(); // Destructive modifications are not permitted.\n        String pkField = OsObjectStore.getPrimaryKeyForObject(realm.sharedRealm, getClassName());\n        if (pkField == null) {\n            throw new IllegalStateException(getClassName() + \" doesn't have a primary key.\");\n        }\n        long columnKey = table.getColumnKey(pkField);\n        if (table.hasSearchIndex(columnKey)) {\n            table.removeSearchIndex(columnKey);\n        }\n        OsObjectStore.setPrimaryKeyForObject(realm.sharedRealm, getClassName(), null);\n        return this;\n    }\n\n    @Override\n    public RealmObjectSchema setRequired(String fieldName, boolean required) {\n        long columnKey = table.getColumnKey(fieldName);\n        boolean currentColumnRequired = isRequired(fieldName);\n        RealmFieldType type = table.getColumnType(columnKey);\n\n        if (type == RealmFieldType.OBJECT) {\n            throw new IllegalArgumentException(\"Cannot modify the required state for RealmObject references: \" + fieldName);\n        }\n        if (type == RealmFieldType.LIST) {\n            throw new IllegalArgumentException(\"Cannot modify the required state for RealmList references: \" + fieldName);\n        }\n        if (required && currentColumnRequired) {\n            throw new IllegalStateException(\"Field is already required: \" + fieldName);\n        }\n        if (!required && !currentColumnRequired) {\n            throw new IllegalStateException(\"Field is already nullable: \" + fieldName);\n        }\n\n        if (required) {\n            try {\n                table.convertColumnToNotNullable(columnKey);\n            } catch (RuntimeException e) {\n                // Preserve old behaviour instead of throwing the rather non-descript Core error\n                if (e.getMessage().contains(\"has null value(s) in property\")) {\n                    throw new IllegalStateException(e.getMessage());\n                } else {\n                    throw e;\n                }\n            }\n        } else {\n            table.convertColumnToNullable(columnKey);\n        }\n        return this;\n    }\n\n    @Override\n    public RealmObjectSchema setNullable(String fieldName, boolean nullable) {\n        setRequired(fieldName, !nullable);\n        return this;\n    }\n\n    @Override\n    public RealmObjectSchema transform(Function function) {\n        //noinspection ConstantConditions\n        if (function != null) {\n            // Users might delete object being transformed or accidentally delete other objects\n            // in the same table. E.g. cascading deletes if it is referenced by an object being deleted.\n            OsResults result = OsResults.createFromQuery(realm.sharedRealm, table.where()).createSnapshot();\n            long original_size = result.size();\n            if (original_size > Integer.MAX_VALUE) {\n                throw new UnsupportedOperationException(\"Too many results to iterate: \" + original_size);\n            }\n            int size = (int) result.size();\n            for (int i = 0; i < size; i++) {\n                DynamicRealmObject obj = new DynamicRealmObject(realm, new CheckedRow(result.getUncheckedRow(i)));\n                if (obj.isValid()) {\n                    function.apply(obj);\n                }\n            }\n        }\n\n        return this;\n    }\n\n    @Override\n    String getPropertyClassName(String propertyName) {\n        String linkedClassName = table.getLinkTarget(getColumnKey(propertyName)).getClassName();\n        if (Util.isEmptyString(linkedClassName)) {\n            throw new IllegalArgumentException(String.format(\"Property '%s' not found.\", propertyName));\n        }\n\n        return linkedClassName;\n    }\n\n    // Invariant: Field was just added. This method is responsible for cleaning up attributes if it fails.\n    private void addModifiers(String fieldName, FieldAttribute[] attributes) {\n        boolean indexAdded = false;\n        try {\n            //noinspection ConstantConditions\n            if (attributes != null && attributes.length > 0) {\n                if (containsAttribute(attributes, FieldAttribute.INDEXED)) {\n                    addIndex(fieldName);\n                    indexAdded = true;\n                }\n\n                if (containsAttribute(attributes, FieldAttribute.PRIMARY_KEY)) {\n                    // Note : adding primary key implies application of FieldAttribute.INDEXED attribute.\n                    addPrimaryKey(fieldName);\n                    indexAdded = true;\n                }\n\n                // REQUIRED is being handled when adding the column using addField through the nullable parameter.\n            }\n        } catch (Exception e) {\n            // If something went wrong, revert all attributes.\n            long columnKey = getColumnKey(fieldName);\n            if (indexAdded) {\n                table.removeSearchIndex(columnKey);\n            }\n            throw (RuntimeException) e;\n        }\n    }\n\n    static boolean containsAttribute(FieldAttribute[] attributeList, FieldAttribute attribute) {\n        //noinspection ConstantConditions\n        if (attributeList == null || attributeList.length == 0) {\n            return false;\n        }\n        for (FieldAttribute anAttributeList : attributeList) {\n            if (anAttributeList == attribute) {\n                return true;\n            }\n        }\n        return false;\n    }\n\n    private void checkNewFieldName(String fieldName) {\n        checkLegalName(fieldName);\n        checkFieldNameIsAvailable(fieldName);\n    }\n\n    private void checkFieldNameIsAvailable(String fieldName) {\n        if (table.getColumnKey(fieldName) != Table.NO_MATCH) {\n            throw new IllegalArgumentException(\"Field already exists in '\" + getClassName() + \"': \" + fieldName);\n        }\n    }\n\n    private void checkAddPrimaryKeyForSync() {\n        if (realm.configuration.isSyncConfiguration()) {\n            throw new UnsupportedOperationException(\"'addPrimaryKey' is not supported by synced Realms.\");\n        }\n    }\n\n    // This method only does extra validation for primary keys that isn't done by Core.\n    // The reason being that ObjectStore currently has more restrictions on primary key types\n    // than what is offered by Core, e.g. Boolean being an allowed primary key in Core, but not\n    // ObjectStore. Since MutableRealmSchemas do not create an ObjectStore schema, we need to\n    // manually encode that difference here to avoid discrepency between allowed schemas for Realm\n    // and DynamicRealm\n    private void checkForObjectStoreInvalidPrimaryKeyTypes(String fieldName, Class<?> fieldType) {\n        if (fieldType == boolean.class || fieldType == Boolean.class) {\n            checkForObjectStoreInvalidPrimaryKeyTypes(fieldName, RealmFieldType.BOOLEAN);\n        }\n        if (fieldType == Date.class) {\n            checkForObjectStoreInvalidPrimaryKeyTypes(fieldName, RealmFieldType.DATE);\n        }\n    }\n    private void checkForObjectStoreInvalidPrimaryKeyTypes(String fieldName, RealmFieldType type) {\n        switch(type) {\n            case BOOLEAN:\n                throw new IllegalArgumentException(\"Boolean fields cannot be marked as primary keys: \" + fieldName);\n            case DATE:\n                throw new IllegalArgumentException(\"Date fields cannot be marked as primary keys: \" + fieldName);\n            default:\n                /* This is fine, or is checked by Core */\n        }\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/MutableRealmSchema.java",
    "content": "/*\n * Copyright 2017 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\npackage io.realm;\n\nimport java.util.LinkedHashSet;\nimport java.util.Locale;\nimport java.util.Set;\n\nimport io.realm.internal.OsObjectStore;\nimport io.realm.internal.Table;\n\n/**\n * Mutable {@link RealmSchema} used by {@link DynamicRealm}.\n *\n * @see ImmutableRealmSchema for schema support for {@link Realm}.\n */\nclass MutableRealmSchema extends RealmSchema {\n\n    MutableRealmSchema(BaseRealm realm) {\n        super(realm, null);\n    }\n\n    @Override\n    public RealmObjectSchema get(String className) {\n        checkNotEmpty(className, EMPTY_STRING_MSG);\n\n        String internalClassName = Table.getTableNameForClass(className);\n        if (!realm.getSharedRealm().hasTable(internalClassName)) { return null; }\n        Table table = realm.getSharedRealm().getTable(internalClassName);\n        return new MutableRealmObjectSchema(realm, this, table);\n    }\n\n    @Override\n    public Set<RealmObjectSchema> getAll() {\n        // Return all tables prefixed with class__ in the Realm file\n        String[] names = realm.getSharedRealm().getTablesNames();\n        int tableCount = names.length;\n        Set<RealmObjectSchema> schemas = new LinkedHashSet<>(tableCount);\n        for (int i = 0; i < tableCount; i++) {\n            RealmObjectSchema objectSchema = get(Table.getClassNameForTable(names[i]));\n            if (objectSchema != null) {\n                schemas.add(objectSchema);\n            }\n        }\n        return schemas;\n    }\n\n    @Override\n    public RealmObjectSchema create(String className) {\n        // Adding a class is always permitted.\n        checkNotEmpty(className, EMPTY_STRING_MSG);\n\n        String internalTableName = Table.getTableNameForClass(className);\n        if (className.length() > Table.CLASS_NAME_MAX_LENGTH) {\n            throw new IllegalArgumentException(\n                    String.format(Locale.US,\n                            \"Class name is too long. Limit is %1$d characters: %2$s\",\n                            Table.CLASS_NAME_MAX_LENGTH,\n                            className.length()));\n        }\n        return new MutableRealmObjectSchema(realm, this, realm.getSharedRealm().createTable(internalTableName));\n    }\n\n    @Override\n    public RealmObjectSchema createWithPrimaryKeyField(String className, String primaryKeyFieldName, Class<?> fieldType,\n                                                       FieldAttribute... attributes) {\n        checkNotEmpty(className, EMPTY_STRING_MSG);\n        RealmObjectSchema.checkLegalName(primaryKeyFieldName);\n        String internalTableName = checkAndGetTableNameFromClassName(className);\n\n        RealmObjectSchema.FieldMetaData metadata = RealmObjectSchema.SUPPORTED_LIST_SIMPLE_FIELDS.get(fieldType);\n        if ((metadata == null) || (\n                        (metadata.fieldType != RealmFieldType.STRING) &&\n                        (metadata.fieldType != RealmFieldType.INTEGER) &&\n                        (metadata.fieldType != RealmFieldType.OBJECT_ID)\n        )) {\n            throw new IllegalArgumentException(String.format(\"Realm doesn't support primary key field type '%s'.\",\n                    fieldType));\n        }\n\n        boolean nullable = metadata.defaultNullable;\n        if (MutableRealmObjectSchema.containsAttribute(attributes, FieldAttribute.REQUIRED)) {\n            nullable = false;\n        }\n\n        return new MutableRealmObjectSchema(realm, this,\n                realm.getSharedRealm().createTableWithPrimaryKey(internalTableName, primaryKeyFieldName,\n                        metadata.fieldType, nullable));\n    }\n\n    @Override\n    public void remove(String className) {\n        realm.checkNotInSync(); // Destructive modifications are not permitted.\n        checkNotEmpty(className, EMPTY_STRING_MSG);\n        String internalTableName = Table.getTableNameForClass(className);\n        if (!OsObjectStore.deleteTableForObject(realm.getSharedRealm(), className)) {\n            throw new IllegalArgumentException(\"Cannot remove class because it is not in this Realm: \" + className);\n        }\n        removeFromClassNameToSchemaMap(internalTableName);\n    }\n\n    @Override\n    public RealmObjectSchema rename(String oldClassName, String newClassName) {\n        realm.checkNotInSync(); // Destructive modifications are not permitted.\n        checkNotEmpty(oldClassName, \"Class names cannot be empty or null\");\n        checkNotEmpty(newClassName, \"Class names cannot be empty or null\");\n        String oldInternalName = Table.getTableNameForClass(oldClassName);\n        String newInternalName = Table.getTableNameForClass(newClassName);\n        checkHasTable(oldClassName, \"Cannot rename class because it doesn't exist in this Realm: \" + oldClassName);\n        if (realm.getSharedRealm().hasTable(newInternalName)) {\n            throw new IllegalArgumentException(oldClassName + \" cannot be renamed because the new class already exists: \" + newClassName);\n        }\n\n        realm.getSharedRealm().renameTable(oldInternalName, newInternalName);\n        Table table = realm.getSharedRealm().getTable(newInternalName);\n        RealmObjectSchema objectSchema = removeFromClassNameToSchemaMap(oldInternalName);\n        if (objectSchema == null || !objectSchema.getTable().isValid() || !objectSchema.getClassName().equals(newClassName)) {\n            objectSchema = new MutableRealmObjectSchema(realm, this, table);\n        }\n        putToClassNameToSchemaMap(newInternalName, objectSchema);\n\n        return objectSchema;\n    }\n\n    private String checkAndGetTableNameFromClassName(String className) {\n        if (className.length() > Table.CLASS_NAME_MAX_LENGTH) {\n            throw new IllegalArgumentException(\n                    String.format(Locale.US,\n                            \"Class name is too long. Limit is %1$d characters: %2$s\",\n                            Table.CLASS_NAME_MAX_LENGTH,\n                            className.length()));\n        }\n        return Table.getTableNameForClass(className);\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/ObjectChangeSet.java",
    "content": "/*\n * Copyright 2017 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\npackage io.realm;\n\n/**\n * Information about the changes made to an object.\n *\n * @see RealmObject#addChangeListener(RealmObjectChangeListener) .\n */\npublic interface ObjectChangeSet {\n\n    /**\n     * @return true if the object has been deleted from the Realm.\n     */\n    boolean isDeleted();\n\n    /**\n     * @return the names of changed fields if the object still exists and there are field changes. Returns an empty\n     * {@code String[]} if the object has been deleted.\n     */\n    String[] getChangedFields();\n\n    /**\n     * Checks if a given field has been changed.\n     *\n     * @param fieldName to be checked if its value has been changed.\n     * @return {@code true} if the field has been changed. It returns {@code false} if the object is deleted, the field\n     * cannot be found or the field hasn't been changed.\n     */\n    boolean isFieldChanged(String fieldName);\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/OrderedCollectionChangeSet.java",
    "content": "/*\n * Copyright 2017 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\npackage io.realm;\n\nimport java.util.Locale;\n\nimport javax.annotation.Nullable;\n\n/**\n * This interface describes the changes made to a collection during the last update.\n * <p>\n * {@link OrderedCollectionChangeSet} is passed to the {@link OrderedRealmCollectionChangeListener} which is registered\n * by {@link RealmResults#addChangeListener(OrderedRealmCollectionChangeListener)}.\n * <p>\n * The change information is available in two formats: a simple array of row indices in the collection for each type of\n * change, or an array of {@link Range}s.\n */\npublic interface OrderedCollectionChangeSet {\n\n    /**\n     * State describing the nature of the changeset.\n     */\n    enum State {\n        /**\n         * This state is used first time the callback is invoked. The query will have completed and\n         * data is ready for the UI.\n         */\n        INITIAL,\n        /**\n         * This state is used for every subsequent update after the first.\n         */\n        UPDATE,\n        /**\n         * This state is used if some error occurred on the background evaluating the query.\n         * <p>\n         * For local and fully synchronized Realms, this state should only be encountered if the\n         * Realm could not be succesfully opened in the background,.\n         */\n        ERROR\n    }\n\n    /**\n     * Returns the state represented by this change. See {@link State} for a description of the\n     * different states a changeset can be in.\n     *\n     * @return what kind of state is represented by this changeset.\n     * @see State\n     */\n    State getState();\n\n    /**\n     * The deleted indices in the previous version of the collection.\n     *\n     * @return the indices array. A zero-sized array will be returned if no objects were deleted.\n     */\n    int[] getDeletions();\n\n    /**\n     * The inserted indices in the new version of the collection.\n     *\n     * @return the indices array. A zero-sized array will be returned if no objects were inserted.\n     */\n    int[] getInsertions();\n\n    /**\n     * The modified indices in the new version of the collection.\n     * <p>\n     * For {@link RealmResults}, this means that one or more of the properties of the object at the given index were\n     * modified (or an object linked to by that object was modified).\n     *\n     * @return the indices array. A zero-sized array will be returned if objects were modified.\n     */\n    int[] getChanges();\n\n    /**\n     * The deleted ranges of objects in the previous version of the collection.\n     *\n     * @return the {@link Range} array. A zero-sized array will be returned if no objects were deleted.\n     */\n    Range[] getDeletionRanges();\n\n    /**\n     * The inserted ranges of objects in the new version of the collection.\n     *\n     * @return the {@link Range} array. A zero-sized array will be returned if no objects were inserted.\n     */\n    Range[] getInsertionRanges();\n\n    /**\n     * The modified ranges of objects in the new version of the collection.\n     *\n     * @return the {@link Range} array. A zero-sized array will be returned if no objects were modified.\n     */\n    Range[] getChangeRanges();\n\n    /**\n     * Returns any error that happened. If an error has happened, the state of the collection and other\n     * changeset information is undefined. It is possible for a collection to go into an error state\n     * after being created and starting to send updates.\n     *\n     * @return the error that happened.\n     */\n    @Nullable\n    Throwable getError();\n\n    /**\n     *\n     */\n    class Range {\n        /**\n         * The start index of this change range.\n         */\n        public final int startIndex;\n\n        /**\n         * How many elements are inside this range.\n         */\n        public final int length;\n\n        /**\n         * Creates a {@link Range} with given start index and length.\n         *\n         * @param startIndex the start index of this change range.\n         * @param length how many elements are inside this range.\n         */\n        public Range(int startIndex, int length) {\n            this.startIndex = startIndex;\n            this.length = length;\n        }\n\n        @Override\n        public String toString() {\n            return String.format(Locale.ENGLISH, \"startIndex: %d, length: %d\", startIndex, length);\n        }\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/OrderedRealmCollection.java",
    "content": "/*\n * Copyright 2016 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\npackage io.realm;\n\nimport java.util.List;\n\nimport javax.annotation.Nullable;\n\n\n/**\n * An {@code OrderedRealmCollection} is a collection which maintains an ordering for its elements. Every\n * element in the {@code OrderedRealmCollection} has an index. Each element can thus be accessed by its\n * index, with the first index being zero. Normally, {@code OrderedRealmCollection}s allow duplicate\n * elements, as compared to Sets, where elements have to be unique.\n * <p>\n * <p>\n * <p>\n * There are three types of {@link OrderedRealmCollection}. {@link RealmResults} and {@link RealmList} are live\n * collections. They are up-to-date all the time and they will never contain an invalid {@link RealmObject}.\n * {@link OrderedRealmCollectionSnapshot} is different. An {@link OrderedRealmCollectionSnapshot} can be created from\n * another {@link OrderedRealmCollection}. Its size and elements order stay the same as the original collection's when\n * it was created. {@link OrderedRealmCollectionSnapshot} may contain invalid {@link RealmObject}s if the objects get\n * deleted.\n * <p>\n * <p>\n * <p>\n * <div class=\"loops\"></div>\n * Using iterators to iterate on {@link OrderedRealmCollection} will always work. You can delete or modify the elements\n * without impacting the iterator. See below example:\n * <p>\n * <pre>\n * {@code\n * RealmResults<Dog> dogs = realm.where(Dog.class).findAll();\n * int s = dogs.size(); // 10\n * realm.beginTransaction();\n * for (Dog dog : dogs) {\n *     dog.deleteFromRealm();\n *     s = dogs.size(); // This will be decreased by 1 every time after a dog is removed.\n * }\n * realm.commitTransaction();\n * s = dogs.size(); // 0\n * }\n * </pre>\n * <p>\n * An iterator created from a live collection will create a stable view when the iterator is created, allowing you to\n * delete and modify elements while iterating without impacting the iterator. However, the {@code RealmResults} backing\n * the iterator will still be live updated meaning that size and order of elements can change when iterating.\n * {@link RealmList} has the same behaviour as {@link RealmResults} since they are both live collections.\n * <p>\n * <p>\n * <p>\n * A simple for-loop is different. See below example:\n * <p>\n * <pre>\n * {@code\n * RealmResults<Dog> dogs = realm.where(Dog.class).findAll();\n * realm.beginTransaction();\n * for (int i = 0; i < dogs.size(); i++) {\n *     dogs.get(i).deleteFromRealm();\n * }\n * realm.commitTransaction();\n * s = dogs.size(); // 5\n * }\n * </pre>\n * <p>\n * The above example only deletes half of elements in the {@link RealmResults}. This is because of {@code dogs.size()}\n * decreased by 1 for every loop. The deletion happens in the loop will immediately impact the size of\n * {@code RealmResults}. To solve this problem, you can create a {@link OrderedRealmCollectionSnapshot} from the\n * {@link RealmResults} or {@link RealmList} and do simple for-loop on that instead:\n * <p>\n * <pre>\n * {@code\n * RealmResults<Dog> dogs = realm.where(Dog.class).findAll();\n * OrderedRealmCollectionSnapshot snapshot = dogs.createSnapshot();\n * // dogs.size() == 10 && snapshot.size() == 10\n * realm.beginTransaction();\n * for (int i = 0; i < snapshot.size(); i++) {\n *     snapshot.get(0).deleteFromRealm();\n *     // snapshot.get(0).isValid() == false\n * }\n * realm.commitTransaction();\n * // dogs.size() == 0 && snapshot.size() == 10\n * }\n * </pre>\n * <p>\n * As you can see, after deletion, the size and elements order of snapshot stay the same as before. But the element at\n * the position becomes invalid.\n */\npublic interface OrderedRealmCollection<E> extends List<E>, RealmCollection<E> {\n\n    /**\n     * Gets the first object from the collection.\n     *\n     * @return the first object.\n     * @throws IndexOutOfBoundsException if the collection is empty.\n     */\n    @Nullable\n    E first();\n\n    /**\n     * Gets the first object from the collection. If the collection is empty, the provided default will be used instead.\n     *\n     * @return the first object or the provided default.\n     */\n    @Nullable\n    E first(@Nullable E defaultValue);\n\n    /**\n     * Gets the last object from the collection.\n     *\n     * @return the last object.\n     * @throws IndexOutOfBoundsException if the collection is empty.\n     */\n    @Nullable\n    E last();\n\n    /**\n     * Gets the last object from the collection. If the collection is empty, the provided default will be used instead.\n     *\n     * @return the last object or the provided default.\n     */\n    @Nullable\n    E last(@Nullable E defaultValue);\n\n    /**\n     * Sorts a collection based on the provided field in ascending order.\n     *\n     * @param fieldName the field name to sort by. Only fields of type boolean, short, int, long, float, double, Date,\n     * and String are supported.\n     * @return a new sorted {@link RealmResults} will be created and returned. The original collection stays unchanged.\n     * @throws java.lang.IllegalArgumentException if field name does not exist or it has an invalid type.\n     * @throws java.lang.IllegalStateException if the Realm is closed, called on the wrong thread or the collection is\n     * an unmanaged collection.\n     */\n    RealmResults<E> sort(String fieldName);\n\n    /**\n     * Sorts a collection based on the provided field and sort order.\n     *\n     * @param fieldName the field name to sort by. Only fields of type boolean, short, int, long, float, double, Date,\n     * and String are supported.\n     * @param sortOrder the direction to sort by.\n     * @return a new sorted {@link RealmResults} will be created and returned. The original collection stays unchanged.\n     * @throws java.lang.IllegalArgumentException if field name does not exist or has an invalid type.\n     * @throws java.lang.IllegalStateException if the Realm is closed, called on the wrong thread or the collection is\n     * an unmanaged collection.\n     */\n    RealmResults<E> sort(String fieldName, Sort sortOrder);\n\n    /**\n     * Sorts a collection based on the provided fields and sort orders.\n     *\n     * @param fieldName1 first field name. Only fields of type boolean, short, int, long, float,\n     * double, Date, and String are supported.\n     * @param sortOrder1 sort order for first field.\n     * @param fieldName2 second field name. Only fields of type boolean, short, int, long, float,\n     * double, Date, and String are supported.\n     * @param sortOrder2 sort order for second field.\n     * @return a new sorted {@link RealmResults} will be created and returned. The original collection stays unchanged.\n     * @throws java.lang.IllegalArgumentException if a field name does not exist or has an invalid type.\n     * @throws java.lang.IllegalStateException if the Realm is closed, called on the wrong thread or the collection is\n     * an unmanaged collection.\n     */\n    RealmResults<E> sort(String fieldName1, Sort sortOrder1, String fieldName2, Sort sortOrder2);\n\n    /**\n     * Sorts a collection based on the provided fields and sort orders.\n     *\n     * @param fieldNames an array of field names to sort by. Only fields of type boolean, short, int, long, float,\n     * double, Date, and String are supported.\n     * @param sortOrders the directions to sort by.\n     * @return a new sorted {@link RealmResults} will be created and returned. The original collection stays unchanged.\n     * @throws java.lang.IllegalArgumentException if a field name does not exist or has an invalid type.\n     * @throws java.lang.IllegalStateException if the Realm is closed, called on the wrong thread or the collection is\n     * an unmanaged collection.\n     */\n    RealmResults<E> sort(String[] fieldNames, Sort[] sortOrders);\n\n    /**\n     * Deletes the object at the given index from the Realm. This also removes it from the collection.\n     *\n     * @param location the array index identifying the object to be removed.\n     * @throws IndexOutOfBoundsException if {@code location < 0 || location >= size()}.\n     * @throws java.lang.IllegalStateException if the Realm is closed or the method is called from the wrong thread.\n     * @throws UnsupportedOperationException if the collection is unmanaged.\n     */\n    void deleteFromRealm(int location);\n\n    /**\n     * Deletes the first object from the Realm. This also removes it from this collection.\n     *\n     * @return {@code true} if an object was deleted, {@code false} otherwise.\n     * @throws java.lang.IllegalStateException if the Realm is closed or the method is called on the wrong thread.\n     * @throws UnsupportedOperationException if the collection is unmanaged.\n     */\n    boolean deleteFirstFromRealm();\n\n    /**\n     * Deletes the last object from the Realm. This also removes it from this collection.\n     *\n     * @return {@code true} if an object was deleted, {@code false} otherwise.\n     * @throws java.lang.IllegalStateException if the Realm is closed or the method is called from the wrong thread.\n     * @throws UnsupportedOperationException if the collection is unmanaged.\n     */\n    boolean deleteLastFromRealm();\n\n    /**\n     * Creates a snapshot from this {@link OrderedRealmCollection}.\n     *\n     * @return the snapshot of this collection.\n     * @throws java.lang.IllegalStateException if the Realm is closed or the method is called from the wrong thread.\n     * @throws UnsupportedOperationException if the collection is unmanaged.\n     * @see OrderedRealmCollectionSnapshot\n     */\n    OrderedRealmCollectionSnapshot<E> createSnapshot();\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/OrderedRealmCollectionChangeListener.java",
    "content": "/*\n * Copyright 2017 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\npackage io.realm;\n\n/**\n * {@link OrderedRealmCollectionChangeListener} can be registered with a {@link RealmResults} to receive a notification\n * with a {@link OrderedCollectionChangeSet} to describe the details of what have been changed in the collection since\n * last time.\n * <p>\n * Realm instances on a thread without an {@link android.os.Looper} cannot register a\n * {@link OrderedRealmCollectionChangeListener}.\n * <p>\n *\n * @see RealmResults#addChangeListener(OrderedRealmCollectionChangeListener)\n */\npublic interface OrderedRealmCollectionChangeListener<T> {\n\n    /**\n     * This will be called when the async query is finished the first time or the collection of objects has changed.\n     *\n     * @param t the collection this listener is registered to.\n     * @param changeSet object with information about the change.\n     */\n    void onChange(T t, OrderedCollectionChangeSet changeSet);\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/OrderedRealmCollectionImpl.java",
    "content": "package io.realm;\n\nimport java.util.AbstractList;\nimport java.util.Arrays;\nimport java.util.ConcurrentModificationException;\nimport java.util.Date;\nimport java.util.Iterator;\nimport java.util.ListIterator;\nimport java.util.Locale;\n\nimport javax.annotation.Nullable;\n\nimport io.realm.internal.InvalidRow;\nimport io.realm.internal.OsResults;\nimport io.realm.internal.RealmObjectProxy;\nimport io.realm.internal.Table;\nimport io.realm.internal.UncheckedRow;\nimport io.realm.internal.core.NativeRealmAny;\n\n/**\n * General implementation for {@link OrderedRealmCollection} which is based on the {@code Collection}.\n */\nabstract class OrderedRealmCollectionImpl<E> extends AbstractList<E> implements OrderedRealmCollection<E> {\n    private static final String NOT_SUPPORTED_MESSAGE = \"This method is not supported by 'RealmResults' or\" +\n            \" 'OrderedRealmCollectionSnapshot'.\";\n\n    /**\n     * The {@link BaseRealm} instance in which this collection resides.\n     * <p>\n     * Warning: This field is only exposed for internal usage, and should not be used.\n     */\n    public final BaseRealm baseRealm;\n\n    @Nullable\n    final Class<E> classSpec;   // Return type\n    @Nullable\n    final String className;     // Class name used by DynamicRealmObjects\n    final OsResults osResults;\n    final CollectionOperator<E> operator;\n\n    OrderedRealmCollectionImpl(BaseRealm baseRealm, OsResults osResults, Class<E> clazz) {\n        this(baseRealm, osResults, clazz, null, getCollectionOperator(false, baseRealm, osResults, clazz, null));\n    }\n\n    OrderedRealmCollectionImpl(BaseRealm baseRealm, OsResults osResults, Class<E> clazz, CollectionOperator<E> operator) {\n        this(baseRealm, osResults, clazz, null, operator);\n    }\n\n    OrderedRealmCollectionImpl(BaseRealm baseRealm, OsResults osResults, String className) {\n        this(baseRealm, osResults, null, className, getCollectionOperator(false, baseRealm, osResults, null, className));\n    }\n\n    OrderedRealmCollectionImpl(BaseRealm baseRealm, OsResults osResults, String className, CollectionOperator<E> operator) {\n        this(baseRealm, osResults, null, className, operator);\n    }\n\n    private OrderedRealmCollectionImpl(BaseRealm baseRealm, OsResults osResults, @Nullable Class<E> clazz, @Nullable String className, CollectionOperator<E> operator) {\n        this.baseRealm = baseRealm;\n        this.osResults = osResults;\n        this.classSpec = clazz;\n        this.className = className;\n        this.operator = operator;\n    }\n\n    Table getTable() {\n        return osResults.getTable();\n    }\n\n    OsResults getOsResults() {\n        return osResults;\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    @Override\n    public boolean isValid() {\n        return osResults.isValid();\n    }\n\n    /**\n     * A {@link RealmResults} or a {@link OrderedRealmCollectionSnapshot} is always a managed collection.\n     *\n     * @return {@code true}.\n     * @see RealmCollection#isManaged()\n     */\n    @Override\n    public boolean isManaged() {\n        return true;\n    }\n\n    /**\n     * Searches this {@link OrderedRealmCollection} for the specified object.\n     *\n     * @param object the object to search for.\n     * @return {@code true} if {@code object} is an element of this {@code OrderedRealmCollection},\n     * {@code false} otherwise.\n     */\n    @Override\n    public boolean contains(@Nullable Object object) {\n        if (isLoaded()) {\n            // Deleted objects can never be part of a RealmResults\n            if (object instanceof RealmObjectProxy) {\n                RealmObjectProxy proxy = (RealmObjectProxy) object;\n                if (proxy.realmGet$proxyState().getRow$realm() == InvalidRow.INSTANCE) {\n                    return false;\n                }\n            }\n\n            for (E e : this) {\n                if (e instanceof byte[] && object instanceof byte[]) {\n                    if (Arrays.equals((byte[]) e, (byte[]) object)) {\n                        return true;\n                    }\n                } else {\n                    if (e != null && e.equals(object)) {\n                        return true;\n                    } else if (e == null && object == null) {\n                        return true;\n                    }\n                }\n            }\n        }\n        return false;\n    }\n\n    /**\n     * Returns the element at the specified location in this list.\n     *\n     * @param location the index of the element to return.\n     * @return the element at the specified index.\n     * @throws IndexOutOfBoundsException if {@code location < 0 || location >= size()}.\n     */\n    @Override\n    @Nullable\n    public E get(int location) {\n        baseRealm.checkIfValid();\n        return operator.get(location);\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    @Override\n    @Nullable\n    public E first() {\n        return firstImpl(true, null);\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    @Override\n    @Nullable\n    public E first(@Nullable E defaultValue) {\n        return firstImpl(false, defaultValue);\n    }\n\n    @Nullable\n    private E firstImpl(boolean shouldThrow, @Nullable E defaultValue) {\n        return operator.firstImpl(shouldThrow, defaultValue);\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    @Override\n    @Nullable\n    public E last() {\n        return lastImpl(true, null);\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    @Override\n    @Nullable\n    public E last(@Nullable E defaultValue) {\n        return lastImpl(false, defaultValue);\n\n    }\n\n    @Nullable\n    private E lastImpl(boolean shouldThrow, @Nullable E defaultValue) {\n        return operator.lastImpl(shouldThrow, defaultValue);\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    @Override\n    public void deleteFromRealm(int location) {\n        // TODO: Implement the delete in OS level and do check there!\n        baseRealm.checkIfValidAndInTransaction();\n        osResults.delete(location);\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    @Override\n    public boolean deleteAllFromRealm() {\n        baseRealm.checkIfValid();\n        if (size() > 0) {\n            osResults.clear();\n            return true;\n        }\n        return false;\n    }\n\n    /**\n     * Returns an iterator for the results of a query. Any change to Realm while iterating will cause this iterator to\n     * throw a {@link ConcurrentModificationException} if accessed.\n     *\n     * @return an iterator on the elements of this list.\n     * @see Iterator\n     */\n    @SuppressWarnings(\"NullableProblems\")\n    @Override\n    public Iterator<E> iterator() {\n        return new RealmCollectionIterator();\n    }\n\n    /**\n     * Returns a list iterator for the results of a query. Any change to Realm while iterating will cause the iterator\n     * to throw a {@link ConcurrentModificationException} if accessed.\n     *\n     * @return a ListIterator on the elements of this list.\n     * @see ListIterator\n     */\n    @Override\n    public ListIterator<E> listIterator() {\n        return new RealmCollectionListIterator(0);\n    }\n\n    /**\n     * Returns a list iterator on the results of a query. Any change to Realm while iterating will cause the iterator to\n     * throw a {@link ConcurrentModificationException} if accessed.\n     *\n     * @param location the index at which to start the iteration.\n     * @return a ListIterator on the elements of this list.\n     * @throws IndexOutOfBoundsException if {@code location < 0 || location > size()}.\n     * @see ListIterator\n     */\n    @SuppressWarnings(\"NullableProblems\")\n    @Override\n    public ListIterator<E> listIterator(int location) {\n        return new RealmCollectionListIterator(location);\n    }\n\n    // Sorting\n\n    // aux. method used by sort methods\n    private long getColumnKeyForSort(String fieldName) {\n        //noinspection ConstantConditions\n        if (fieldName == null || fieldName.isEmpty()) {\n            throw new IllegalArgumentException(\"Non-empty field name required.\");\n        }\n        if (fieldName.contains(\".\")) {\n            throw new IllegalArgumentException(\"Aggregates on child object fields are not supported: \" + fieldName);\n        }\n        long columnKey = osResults.getTable().getColumnKey(fieldName);\n        if (columnKey < 0) {\n            throw new IllegalArgumentException(String.format(Locale.US, \"Field '%s' does not exist.\", fieldName));\n        }\n        return columnKey;\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    @Override\n    public RealmResults<E> sort(String fieldName) {\n        OsResults sortedOsResults = osResults.sort(baseRealm.getSchema().getKeyPathMapping(), fieldName, Sort.ASCENDING);\n        return createLoadedResults(sortedOsResults);\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    @Override\n    public RealmResults<E> sort(String fieldName, Sort sortOrder) {\n        OsResults sortedOsResults = osResults.sort(baseRealm.getSchema().getKeyPathMapping(), fieldName, sortOrder);\n        return createLoadedResults(sortedOsResults);\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    @Override\n    public RealmResults<E> sort(String[] fieldNames, Sort[] sortOrders) {\n        OsResults sortedOsResults = osResults.sort(baseRealm.getSchema().getKeyPathMapping(), fieldNames, sortOrders);\n        return createLoadedResults(sortedOsResults);\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    @Override\n    public RealmResults<E> sort(String fieldName1, Sort sortOrder1, String fieldName2, Sort sortOrder2) {\n        return sort(new String[]{fieldName1, fieldName2}, new Sort[]{sortOrder1, sortOrder2});\n    }\n\n    // Aggregates\n\n    /**\n     * Returns the number of elements in this query result.\n     *\n     * @return the number of elements in this query result.\n     */\n    @Override\n    public int size() {\n        if (isLoaded()) {\n            long size = osResults.size();\n            return (size > Integer.MAX_VALUE) ? Integer.MAX_VALUE : (int) size;\n        }\n        return 0;\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    @Override\n    public Number min(String fieldName) {\n        baseRealm.checkIfValid();\n        long columnKey = getColumnKeyForSort(fieldName);\n        return osResults.aggregateNumber(OsResults.Aggregate.MINIMUM, columnKey);\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    @Override\n    public Date minDate(String fieldName) {\n        baseRealm.checkIfValid();\n        long columnIndex = getColumnKeyForSort(fieldName);\n        return osResults.aggregateDate(OsResults.Aggregate.MINIMUM, columnIndex);\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    @Override\n    public Number max(String fieldName) {\n        baseRealm.checkIfValid();\n        long columnIndex = getColumnKeyForSort(fieldName);\n        return osResults.aggregateNumber(OsResults.Aggregate.MAXIMUM, columnIndex);\n    }\n\n    /**\n     * Finds the maximum date.\n     *\n     * @param fieldName the field to look for the maximum date. If fieldName is not of Date type, an exception is\n     *                  thrown.\n     * @return if no objects exist or they all have {@code null} as the value for the given date field, {@code null}\n     * will be returned. Otherwise the maximum date is returned. When determining the maximum date, objects with\n     * {@code null} values are ignored.\n     * @throws IllegalArgumentException if fieldName is not a Date field.\n     */\n    @Override\n    @Nullable\n    public Date maxDate(String fieldName) {\n        baseRealm.checkIfValid();\n        long columnIndex = getColumnKeyForSort(fieldName);\n        return osResults.aggregateDate(OsResults.Aggregate.MAXIMUM, columnIndex);\n    }\n\n\n    /**\n     * {@inheritDoc}\n     */\n    @Override\n    public Number sum(String fieldName) {\n        baseRealm.checkIfValid();\n        long columnIndex = getColumnKeyForSort(fieldName);\n        return osResults.aggregateNumber(OsResults.Aggregate.SUM, columnIndex);\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    @Override\n    public double average(String fieldName) {\n        baseRealm.checkIfValid();\n        long columnIndex = getColumnKeyForSort(fieldName);\n\n        Number avg = osResults.aggregateNumber(OsResults.Aggregate.AVERAGE, columnIndex);\n        return avg.doubleValue();\n    }\n\n    // Deleting\n\n    /**\n     * Not supported by {@link RealmResults} and {@link OrderedRealmCollectionSnapshot}.\n     *\n     * @throws UnsupportedOperationException\n     */\n    @Deprecated\n    @Override\n    public E remove(int index) {\n        throw new UnsupportedOperationException(NOT_SUPPORTED_MESSAGE);\n    }\n\n    /**\n     * Not supported by {@link RealmResults} and {@link OrderedRealmCollectionSnapshot}.\n     *\n     * @throws UnsupportedOperationException\n     */\n    @Deprecated\n    @Override\n    public boolean remove(Object object) {\n        throw new UnsupportedOperationException(NOT_SUPPORTED_MESSAGE);\n    }\n\n    /**\n     * Not supported by {@link RealmResults} and {@link OrderedRealmCollectionSnapshot}.\n     *\n     * @throws UnsupportedOperationException\n     */\n    @Deprecated\n    @Override\n    public boolean removeAll(@SuppressWarnings(\"NullableProblems\") java.util.Collection<?> collection) {\n        throw new UnsupportedOperationException(NOT_SUPPORTED_MESSAGE);\n    }\n\n    /**\n     * Not supported by {@link RealmResults} and {@link OrderedRealmCollectionSnapshot}.\n     *\n     * @throws UnsupportedOperationException\n     */\n    @Deprecated\n    @Override\n    public E set(int location, E object) {\n        throw new UnsupportedOperationException(NOT_SUPPORTED_MESSAGE);\n    }\n\n    /**\n     * Not supported by {@link RealmResults} and {@link OrderedRealmCollectionSnapshot}.\n     *\n     * @throws UnsupportedOperationException\n     */\n    @Deprecated\n    @Override\n    public boolean retainAll(@SuppressWarnings(\"NullableProblems\") java.util.Collection<?> collection) {\n        throw new UnsupportedOperationException(NOT_SUPPORTED_MESSAGE);\n    }\n\n    /**\n     * Removes the last object in the list. This also deletes the object from the underlying Realm.\n     *\n     * @throws IllegalStateException if the corresponding Realm is closed or in an incorrect thread.\n     */\n    @Override\n    public boolean deleteLastFromRealm() {\n        // TODO: Implement the deleteLast in OS level and do check there!\n        baseRealm.checkIfValidAndInTransaction();\n        return osResults.deleteLast();\n    }\n\n    /**\n     * Removes the first object in the list. This also deletes the object from the underlying Realm.\n     *\n     * @throws IllegalStateException if the corresponding Realm is closed or in an incorrect thread.\n     */\n    @Override\n    public boolean deleteFirstFromRealm() {\n        // TODO: Implement the deleteLast in OS level and do check there!\n        baseRealm.checkIfValidAndInTransaction();\n        return osResults.deleteFirst();\n    }\n\n    /**\n     * Not supported by {@link RealmResults} and {@link OrderedRealmCollectionSnapshot}.\n     *\n     * @throws UnsupportedOperationException always.\n     */\n    @Override\n    @Deprecated\n    public void clear() {\n        throw new UnsupportedOperationException(NOT_SUPPORTED_MESSAGE);\n    }\n\n    /**\n     * Not supported by {@link RealmResults} and {@link OrderedRealmCollectionSnapshot}.\n     *\n     * @throws UnsupportedOperationException always.\n     */\n    @Override\n    @Deprecated\n    public boolean add(E element) {\n        throw new UnsupportedOperationException(NOT_SUPPORTED_MESSAGE);\n    }\n\n    /**\n     * Not supported by {@link RealmResults} and {@link OrderedRealmCollectionSnapshot}.\n     *\n     * @throws UnsupportedOperationException always.\n     */\n    @Override\n    @Deprecated\n    public void add(int index, E element) {\n        throw new UnsupportedOperationException(NOT_SUPPORTED_MESSAGE);\n    }\n\n    /**\n     * Not supported by {@link RealmResults} and {@link OrderedRealmCollectionSnapshot}.\n     *\n     * @throws UnsupportedOperationException always.\n     */\n    @Override\n    @Deprecated\n    public boolean addAll(int location,\n                          @SuppressWarnings(\"NullableProblems\") java.util.Collection<? extends E> collection) {\n        throw new UnsupportedOperationException(NOT_SUPPORTED_MESSAGE);\n    }\n\n    /**\n     * Not supported by {@link RealmResults} and {@link OrderedRealmCollectionSnapshot}.\n     *\n     * @throws UnsupportedOperationException always.\n     */\n    @Deprecated\n    @Override\n    public boolean addAll(@SuppressWarnings(\"NullableProblems\") java.util.Collection<? extends E> collection) {\n        throw new UnsupportedOperationException(NOT_SUPPORTED_MESSAGE);\n    }\n\n    // Custom RealmResults iterator. It ensures that we only iterate on a Realm that hasn't changed.\n    private class RealmCollectionIterator extends OsResults.Iterator<E> {\n        RealmCollectionIterator() {\n            super(OrderedRealmCollectionImpl.this.osResults);\n        }\n\n        @Override\n        protected E convertRowToObject(UncheckedRow row) {\n            return operator.convertRowToObject(row);\n        }\n\n        @Override\n        protected E getInternal(int pos, OsResults iteratorOsResults) {\n            return operator.getFromResults(pos, iteratorOsResults);\n        }\n    }\n\n    @Override\n    public OrderedRealmCollectionSnapshot<E> createSnapshot() {\n        if (className != null) {\n            return new OrderedRealmCollectionSnapshot<E>(baseRealm, osResults, className);\n        } else {\n            // 'classSpec' is non-null when 'className' is null.\n            //noinspection ConstantConditions\n            return new OrderedRealmCollectionSnapshot<E>(baseRealm, osResults, classSpec);\n        }\n    }\n\n    /**\n     * Returns the {@link Realm} instance to which this collection belongs.\n     * <p>\n     * Calling {@link Realm#close()} on the returned instance is discouraged as it is the same as\n     * calling it on the original Realm instance which may cause the Realm to fully close invalidating the\n     * query result.\n     *\n     * @return {@link Realm} instance this collection belongs to.\n     * @throws IllegalStateException if the Realm is an instance of {@link DynamicRealm} or the\n     *                               {@link Realm} was already closed.\n     */\n    public Realm getRealm() {\n        baseRealm.checkIfValid();\n        if (!(baseRealm instanceof Realm)) {\n            throw new IllegalStateException(\"This method is only available for typed Realms\");\n        }\n        return (Realm) baseRealm;\n    }\n\n    // Custom RealmResults list iterator.\n    private class RealmCollectionListIterator extends OsResults.ListIterator<E> {\n        RealmCollectionListIterator(int start) {\n            super(OrderedRealmCollectionImpl.this.osResults, start);\n        }\n\n        @Override\n        protected E convertRowToObject(UncheckedRow row) {\n            return operator.convertRowToObject(row);\n        }\n\n        @Override\n        protected E getInternal(int pos, OsResults iteratorOsResults) {\n            return operator.getFromResults(pos, iteratorOsResults);\n        }\n    }\n\n    RealmResults<E> createLoadedResults(OsResults newOsResults) {\n        RealmResults<E> results;\n        if (className != null) {\n            results = new RealmResults<E>(baseRealm, newOsResults, className);\n        } else {\n            // 'classSpec' is non-null when 'className' is null.\n            //noinspection ConstantConditions\n            results = new RealmResults<E>(baseRealm, newOsResults, classSpec);\n        }\n        results.load();\n        return results;\n    }\n\n    protected static <T> CollectionOperator<T> getCollectionOperator(boolean forPrimitives,\n                                                                     BaseRealm baseRealm,\n                                                                     OsResults osResults,\n                                                                     @Nullable Class<T> clazz,\n                                                                     @Nullable String className) {\n        if (forPrimitives) {\n            if (clazz == Integer.class) {\n                //noinspection unchecked\n                return (CollectionOperator<T>) new IntegerValueOperator(baseRealm, osResults, Integer.class, className);\n            } else if (clazz == Short.class) {\n                //noinspection unchecked\n                return (CollectionOperator<T>) new ShortValueOperator(baseRealm, osResults, Short.class, className);\n            } else if (clazz == Byte.class) {\n                //noinspection unchecked\n                return (CollectionOperator<T>) new ByteValueOperator(baseRealm, osResults, Byte.class, className);\n            } else if (clazz == RealmAny.class) {\n                //noinspection unchecked\n                return (CollectionOperator<T>) new RealmAnyValueOperator(baseRealm, osResults, RealmAny.class, className);\n            } else {\n                return new PrimitiveValueOperator<>(baseRealm, osResults, clazz, className);\n            }\n        } else {\n            return new ModelCollectionOperator<>(baseRealm, osResults, clazz, className);\n        }\n    }\n\n    /**\n     * Used to abstract operations from the collection itself depending on whether it is a primitive\n     * value collection or a model collection.\n     *\n     * @param <T> the type of the collection.\n     */\n    abstract static class CollectionOperator<T> {\n\n        protected final BaseRealm baseRealm;\n        protected final OsResults osResults;\n        @Nullable\n        protected final Class<T> classSpec;\n        @Nullable\n        protected final String className;\n\n        CollectionOperator(BaseRealm baseRealm,\n                                  OsResults osResults,\n                                  @Nullable Class<T> classSpec,\n                                  @Nullable String className) {\n            this.baseRealm = baseRealm;\n            this.osResults = osResults;\n            this.classSpec = classSpec;\n            this.className = className;\n        }\n\n        public abstract T get(int location);\n\n        @Nullable\n        public abstract T firstImpl(boolean shouldThrow, @Nullable T defaultValue);\n\n        @Nullable\n        public abstract T lastImpl(boolean shouldThrow, @Nullable T defaultValue);\n\n        public abstract T convertRowToObject(UncheckedRow row);\n\n        public abstract T getFromResults(int pos, OsResults iteratorOsResults);\n\n        protected T convertToObject(@Nullable UncheckedRow row,\n                                    boolean shouldThrow,\n                                    @Nullable T defaultValue) {\n            if (row != null) {\n                //noinspection unchecked\n                return (T) baseRealm.get((Class<? extends RealmModel>) classSpec, className, row);\n            } else {\n                if (shouldThrow) {\n                    throw new IndexOutOfBoundsException(\"No results were found.\");\n                } else {\n                    return defaultValue;\n                }\n            }\n        }\n    }\n\n    /**\n     * Operator for models.\n     *\n     * @param <T> the type of the collection, must extend {@link RealmModel}.\n     */\n    static class ModelCollectionOperator<T> extends CollectionOperator<T> {\n\n        ModelCollectionOperator(BaseRealm baseRealm,\n                                       OsResults osResults,\n                                       @Nullable Class<T> clazz,\n                                       @Nullable String className) {\n            super(baseRealm, osResults, clazz, className);\n        }\n\n        @Override\n        public T get(int location) {\n            //noinspection unchecked\n            return (T) baseRealm.get((Class<? extends RealmModel>) classSpec, className, osResults.getUncheckedRow(location));\n        }\n\n        @Nullable\n        @Override\n        public T firstImpl(boolean shouldThrow, @Nullable T defaultValue) {\n            return convertToObject(osResults.firstUncheckedRow(), shouldThrow, defaultValue);\n        }\n\n        @Nullable\n        @Override\n        public T lastImpl(boolean shouldThrow, @Nullable T defaultValue) {\n            return convertToObject(osResults.lastUncheckedRow(), shouldThrow, defaultValue);\n        }\n\n        @Override\n        public T convertRowToObject(UncheckedRow row) {\n            //noinspection unchecked\n            return (T) baseRealm.get((Class<? extends RealmObject>) classSpec, className, row);\n        }\n\n        @Override\n        public T getFromResults(int pos, OsResults iteratorOsResults) {\n            return convertRowToObject(iteratorOsResults.getUncheckedRow(pos));\n        }\n    }\n\n    /**\n     * Operator for Realm primitive types.\n     *\n     * @param <T> the type of the collection.\n     */\n    static class PrimitiveValueOperator<T> extends CollectionOperator<T> {\n\n        PrimitiveValueOperator(BaseRealm baseRealm,\n                                      OsResults osResults,\n                                      @Nullable Class<T> classSpec,\n                                      @Nullable String className) {\n            super(baseRealm, osResults, classSpec, className);\n        }\n\n        @Override\n        public T get(int location) {\n            Object value = osResults.getValue(location);\n\n            //noinspection unchecked\n            return (T) value;\n        }\n\n        @Nullable\n        @Override\n        public T firstImpl(boolean shouldThrow, @Nullable T defaultValue) {\n            if (osResults.size() != 0) {\n                //noinspection unchecked\n                return (T) osResults.getValue(0);\n            }\n            return defaultValue;\n        }\n\n        @Nullable\n        @Override\n        public T lastImpl(boolean shouldThrow, @Nullable T defaultValue) {\n            int size = (int) osResults.size();\n            if (size != 0) {\n                //noinspection unchecked\n                return (T) osResults.getValue(size - 1);\n            }\n            return defaultValue;\n        }\n\n        @Override\n        public T convertRowToObject(UncheckedRow row) {\n            throw new UnsupportedOperationException(\"Method 'convertRowToObject' cannot be used on primitive Realm collections.\");\n        }\n\n        @Override\n        public T getFromResults(int pos, OsResults iteratorOsResults) {\n            //noinspection unchecked\n            return (T) iteratorOsResults.getValue(pos);\n        }\n    }\n\n    static class IntegerValueOperator extends PrimitiveValueOperator<Integer> {\n\n        IntegerValueOperator(BaseRealm baseRealm,\n                                    OsResults osResults,\n                                    @Nullable Class<Integer> classSpec,\n                                    @Nullable String className) {\n            super(baseRealm, osResults, classSpec, className);\n        }\n\n        @Override\n        public Integer get(int location) {\n            Object value = osResults.getValue(location);\n            Long longValue = (Long) value;\n            return longValue.intValue();\n        }\n\n        @Override\n        public Integer getFromResults(int pos, OsResults iteratorOsResults) {\n            Long longValue = (Long) iteratorOsResults.getValue(pos);\n            if (longValue == null) {\n                return null;\n            }\n            return longValue.intValue();\n        }\n    }\n\n    static class ShortValueOperator extends PrimitiveValueOperator<Short> {\n\n        ShortValueOperator(BaseRealm baseRealm,\n                                  OsResults osResults,\n                                  @Nullable Class<Short> classSpec,\n                                  @Nullable String className) {\n            super(baseRealm, osResults, classSpec, className);\n        }\n\n        @Override\n        public Short get(int location) {\n            Object value = osResults.getValue(location);\n            Long longValue = (Long) value;\n            return longValue.shortValue();\n        }\n\n        @Override\n        public Short getFromResults(int pos, OsResults iteratorOsResults) {\n            Long longValue = (Long) iteratorOsResults.getValue(pos);\n            if (longValue == null) {\n                return null;\n            }\n            return longValue.shortValue();\n        }\n    }\n\n    static class ByteValueOperator extends PrimitiveValueOperator<Byte> {\n\n        ByteValueOperator(BaseRealm baseRealm,\n                                 OsResults osResults,\n                                 @Nullable Class<Byte> classSpec,\n                                 @Nullable String className) {\n            super(baseRealm, osResults, classSpec, className);\n        }\n\n        @Override\n        public Byte get(int location) {\n            Object value = osResults.getValue(location);\n            Long longValue = (Long) value;\n            return longValue.byteValue();\n        }\n\n        @Override\n        public Byte getFromResults(int pos, OsResults iteratorOsResults) {\n            Long longValue = (Long) iteratorOsResults.getValue(pos);\n            if (longValue == null) {\n                return null;\n            }\n            return longValue.byteValue();\n        }\n    }\n\n    static class RealmAnyValueOperator extends PrimitiveValueOperator<RealmAny> {\n\n        RealmAnyValueOperator(BaseRealm baseRealm,\n                                  OsResults osResults,\n                                  @Nullable Class<RealmAny> classSpec,\n                                  @Nullable String className) {\n            super(baseRealm, osResults, classSpec, className);\n        }\n\n        @Override\n        public RealmAny get(int location) {\n            Object value = osResults.getValue(location);\n            NativeRealmAny nativeRealmAny = (NativeRealmAny) value;\n            return new RealmAny(RealmAnyOperator.fromNativeRealmAny(baseRealm, nativeRealmAny));\n        }\n\n        @Override\n        public RealmAny getFromResults(int pos, OsResults iteratorOsResults) {\n            NativeRealmAny nativeRealmAny = (NativeRealmAny) iteratorOsResults.getValue(pos);\n            return new RealmAny(RealmAnyOperator.fromNativeRealmAny(baseRealm, nativeRealmAny));\n        }\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/OrderedRealmCollectionSnapshot.java",
    "content": "/*\n * Copyright 2017 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\npackage io.realm;\n\nimport java.util.Locale;\n\nimport io.realm.internal.Freezable;\nimport io.realm.internal.OsResults;\nimport io.realm.internal.UncheckedRow;\n\n\n/**\n * An {@link OrderedRealmCollectionSnapshot} is a special type of {@link OrderedRealmCollection}. It can be created by\n * calling {@link OrderedRealmCollection#createSnapshot()}. Unlike {@link RealmResults} and {@link RealmList}, its\n * size and order of elements will never be changed after creation.\n * <p>\n * {@link OrderedRealmCollectionSnapshot} is useful when making changes which may impact the size or order of the\n * collection in simple loops. For example:\n * <pre>\n * {@code\n * final RealmResults<Dog>  dogs = realm.where(Dog.class).findAll();\n * final OrderedRealmCollectionSnapshot<Dog> snapshot = dogs.createSnapshot();\n * final int dogsCount = snapshot.size(); // dogs.size() == snapshot.size() == 10\n * realm.executeTransaction(new Realm.Transaction() {\n *     /@Override\n *     public void execute(Realm realm) {\n *         for (int i = 0; i < dogsCount; i++) {\n *         // This won't work since RealmResults is always up-to-date, its size gets decreased by 1 after every loop. An\n *         // IndexOutOfBoundsException will be thrown after 5 loops.\n *         // dogs.deleteFromRealm(i);\n *         snapshot.deleteFromRealm(i); // Deletion on OrderedRealmCollectionSnapshot won't change the size of it.\n *         }\n *     }\n * });\n * }\n * </pre>\n */\npublic class OrderedRealmCollectionSnapshot<E> extends OrderedRealmCollectionImpl<E> {\n\n    private int size = -1;\n\n    OrderedRealmCollectionSnapshot(BaseRealm realm, OsResults osResults, Class<E> clazz) {\n        super(realm, osResults.createSnapshot(), clazz);\n    }\n\n    OrderedRealmCollectionSnapshot(BaseRealm realm, OsResults osResults, String className) {\n        super(realm, osResults.createSnapshot(), className);\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    @Override\n    public int size() {\n        // Optimization for simple loops. The size of snapshot will never be changed.\n        if (size == -1) {\n            size = super.size();\n        }\n        return size;\n    }\n\n    /**\n     * Not supported by {@link OrderedRealmCollectionSnapshot}. Use 'sort()' on the original\n     * {@link OrderedRealmCollection} instead.\n     *\n     * @throws UnsupportedOperationException\n     */\n    @Override\n    public RealmResults<E> sort(String fieldName) {\n        throw getUnsupportedException(\"sort\");\n    }\n\n    /**\n     * Not supported by {@link OrderedRealmCollectionSnapshot}. Use 'sort()' on the original\n     * {@link OrderedRealmCollection} instead.\n     *\n     * @throws UnsupportedOperationException\n     */\n    @Override\n    public RealmResults<E> sort(String fieldName, Sort sortOrder) {\n        throw getUnsupportedException(\"sort\");\n    }\n\n    /**\n     * Not supported by {@link OrderedRealmCollectionSnapshot}. Use 'sort()' on the original\n     * {@link OrderedRealmCollection} instead.\n     *\n     * @throws UnsupportedOperationException\n     */\n    @Override\n    public RealmResults<E> sort(String fieldName1, Sort sortOrder1, String fieldName2, Sort sortOrder2) {\n        throw getUnsupportedException(\"sort\");\n    }\n\n    /**\n     * Not supported by {@link OrderedRealmCollectionSnapshot}. Use 'sort()' on the original\n     * {@link OrderedRealmCollection} instead.\n     *\n     * @throws UnsupportedOperationException\n     */\n    @Override\n    public RealmResults<E> sort(String[] fieldNames, Sort[] sortOrders) {\n        throw getUnsupportedException(\"sort\");\n    }\n\n    /**\n     * Not supported by {@link OrderedRealmCollectionSnapshot}. Use 'where()' on the original\n     * {@link OrderedRealmCollection} instead.\n     *\n     * @throws UnsupportedOperationException\n     */\n    @Deprecated\n    @Override\n    public RealmQuery<E> where() {\n        throw getUnsupportedException(\"where\");\n    }\n\n    private UnsupportedOperationException getUnsupportedException(String methodName) {\n        return new UnsupportedOperationException(\n                String.format(Locale.US, \"'%s()' is not supported by OrderedRealmCollectionSnapshot. \" +\n                        \"Call '%s()' on the original 'RealmCollection' instead.\", methodName, methodName));\n    }\n\n\n    /**\n     * {@inheritDoc}\n     */\n    @Override\n    public boolean isLoaded() {\n        return true;\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    @Override\n    public boolean load() {\n        return true;\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    @Override\n    public OrderedRealmCollectionSnapshot<E> createSnapshot() {\n        baseRealm.checkIfValid();\n        return this;\n    }\n\n    @Override\n    public OrderedRealmCollection<E> freeze() {\n        // Technically, nothing prevents us from supporting this, but there isn't any good use\n        // case for supporting it, since snapshots should only be used when modifying Results.\n        // So for now, this is disabled.\n        throw getUnsupportedException(\"freeze\");\n    }\n\n    /**\n     * Deletes the object at the given index from the Realm. The object at the given index will become invalid. Just\n     * returns if the object is invalid already.\n     *\n     * @param location the array index identifying the object to be removed.\n     * @throws IndexOutOfBoundsException if {@code location < 0 || location >= size()}.\n     * @throws java.lang.IllegalStateException if the Realm is closed or the method is called from the wrong thread.\n     */\n    @Override\n    public void deleteFromRealm(int location) {\n        baseRealm.checkIfValidAndInTransaction();\n        UncheckedRow row = osResults.getUncheckedRow(location);\n        if (row.isValid()) {\n            osResults.delete(location);\n        }\n    }\n\n    /**\n     * Deletes the first object from the Realm. The first object will become invalid.\n     *\n     * @return {@code true} if an object was deleted, {@code false} otherwise.\n     * @throws java.lang.IllegalStateException if the Realm is closed or the method is called on the wrong thread.\n     */\n    @Override\n    public boolean deleteFirstFromRealm() {\n        baseRealm.checkIfValidAndInTransaction();\n        UncheckedRow row = osResults.firstUncheckedRow();\n        return row != null && row.isValid() && osResults.deleteFirst();\n    }\n\n    /**\n     * Deletes the last object from the Realm. The last object will become invalid.\n     *\n     * @return {@code true} if an object was deleted, {@code false} otherwise.\n     * @throws java.lang.IllegalStateException if the Realm is closed or the method is called from the wrong thread.\n     */\n    @Override\n    public boolean deleteLastFromRealm() {\n        baseRealm.checkIfValidAndInTransaction();\n        UncheckedRow row = osResults.lastUncheckedRow();\n        return row != null && row.isValid() && osResults.deleteLast();\n    }\n\n    /**\n     * This deletes all objects in the collection from the underlying Realm. All objects in the collection snapshot\n     * will become invalid.\n     *\n     * @return {@code true} if objects was deleted, {@code false} otherwise.\n     * @throws IllegalStateException if the corresponding Realm is closed or in an incorrect thread.\n     * @throws java.lang.IllegalStateException if the Realm has been closed or called from an incorrect thread.\n     */\n    @Override\n    public boolean deleteAllFromRealm() {\n        return super.deleteAllFromRealm();\n    }\n\n    @Override\n    public boolean isFrozen() {\n        return false;\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/ProxyState.java",
    "content": "/*\n * Copyright 2016 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\npackage io.realm;\n\nimport java.util.List;\n\nimport javax.annotation.Nullable;\n\nimport io.realm.internal.ObserverPairList;\nimport io.realm.internal.PendingRow;\nimport io.realm.internal.RealmObjectProxy;\nimport io.realm.internal.Row;\nimport io.realm.internal.OsObject;\nimport io.realm.internal.UncheckedRow;\n\n\n/**\n * This implements {@code RealmObjectProxy} interface, to eliminate copying logic between\n * {@link RealmObject} and {@link DynamicRealmObject}.\n */\npublic final class ProxyState<E extends RealmModel> implements PendingRow.FrontEnd {\n\n    static class RealmChangeListenerWrapper<T extends RealmModel> implements RealmObjectChangeListener<T> {\n        private final RealmChangeListener<T> listener;\n\n        RealmChangeListenerWrapper(RealmChangeListener<T> listener) {\n            //noinspection ConstantConditions\n            if (listener == null) {\n                throw new IllegalArgumentException(\"Listener should not be null\");\n            }\n            this.listener = listener;\n        }\n\n        @Override\n        public void onChange(T object, @Nullable ObjectChangeSet changes) {\n            listener.onChange(object);\n        }\n\n        @Override\n        public boolean equals(Object obj) {\n            return obj instanceof RealmChangeListenerWrapper &&\n                    listener == ((RealmChangeListenerWrapper) obj).listener;\n        }\n\n        @Override\n        public int hashCode() {\n            return listener.hashCode();\n        }\n    }\n\n    private static class QueryCallback implements ObserverPairList.Callback<OsObject.ObjectObserverPair> {\n\n        @Override\n        public void onCalled(OsObject.ObjectObserverPair pair, Object observer) {\n            //noinspection unchecked\n            pair.onChange((RealmModel) observer, null);\n        }\n    }\n\n    private E model;\n\n    // true only while executing the constructor of the enclosing proxy object\n    private boolean underConstruction = true;\n\n    private Row row;\n    private OsObject osObject;\n    private BaseRealm realm;\n    private boolean acceptDefaultValue;\n    private List<String> excludeFields;\n\n    private ObserverPairList<OsObject.ObjectObserverPair> observerPairs =\n            new ObserverPairList<OsObject.ObjectObserverPair>();\n    private static QueryCallback queryCallback = new QueryCallback();\n\n    public ProxyState() {}\n\n    public ProxyState(E model) {\n        this.model = model;\n    }\n\n    public BaseRealm getRealm$realm() {\n        return realm;\n    }\n\n    public void setRealm$realm(BaseRealm realm) {\n        this.realm = realm;\n    }\n\n    public Row getRow$realm() {\n        return row;\n    }\n\n    public void setRow$realm(Row row) {\n        this.row = row;\n    }\n\n    public boolean getAcceptDefaultValue$realm() {\n        return acceptDefaultValue;\n    }\n\n    public void setAcceptDefaultValue$realm(boolean acceptDefaultValue) {\n        this.acceptDefaultValue = acceptDefaultValue;\n    }\n\n    @SuppressWarnings(\"unused\")\n    public List<String> getExcludeFields$realm() {\n        return excludeFields;\n    }\n\n    public void setExcludeFields$realm(List<String> excludeFields) {\n        this.excludeFields = excludeFields;\n    }\n\n    /**\n     * Notifies all registered listeners.\n     */\n    private void notifyQueryFinished() {\n        observerPairs.foreach(queryCallback);\n    }\n\n    public void addChangeListener(RealmObjectChangeListener<E> listener) {\n        if (row instanceof PendingRow) {\n            observerPairs.add(new OsObject.ObjectObserverPair<E>(model, listener));\n        } else if (row instanceof UncheckedRow) {\n            registerToObjectNotifier();\n            if (osObject != null) {\n                osObject.addListener(model, listener);\n            }\n        }\n    }\n\n    public void removeChangeListener(RealmObjectChangeListener<E> listener) {\n        if (osObject != null) {\n            osObject.removeListener(model, listener);\n        } else {\n            observerPairs.remove(model, listener);\n        }\n    }\n\n    public void removeAllChangeListeners() {\n        if (osObject != null) {\n            osObject.removeListener(model);\n        } else {\n            observerPairs.clear();\n        }\n    }\n\n    public boolean isUnderConstruction() {\n        return underConstruction;\n    }\n\n    public void setConstructionFinished() {\n        underConstruction = false;\n        // Only used while construction.\n        excludeFields = null;\n    }\n\n    private void registerToObjectNotifier() {\n        if (realm.sharedRealm == null || realm.sharedRealm.isClosed() || !row.isValid()) {\n            return;\n        }\n\n        if (osObject == null) {\n            osObject = new OsObject(realm.sharedRealm, (UncheckedRow) row);\n            osObject.setObserverPairs(observerPairs);\n            // We should never need observerPairs after pending row returns.\n            observerPairs = null;\n        }\n    }\n\n    public boolean isLoaded() {\n        return row.isLoaded();\n    }\n\n    public void load() {\n        if (row instanceof PendingRow) {\n            ((PendingRow) row).executeQuery();\n        }\n    }\n\n    @Override\n    public void onQueryFinished(Row row) {\n        this.row = row;\n        // getTable should return a non-null table since the row should always be valid here.\n        notifyQueryFinished();\n        if (row.isValid()) {\n            registerToObjectNotifier();\n        }\n    }\n\n    /**\n     * Check that object is a valid and managed object by this Realm.\n     * Used by proxy classes to verify input.\n     *\n     * @param value model object\n     */\n    public void checkValidObject(RealmModel value) {\n        if (!RealmObject.isValid(value) || !RealmObject.isManaged(value)) {\n            throw new IllegalArgumentException(\"'value' is not a valid managed object.\");\n        }\n        if (((RealmObjectProxy) value).realmGet$proxyState().getRealm$realm() != getRealm$realm()) {\n            throw new IllegalArgumentException(\"'value' belongs to a different Realm.\");\n        }\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/ProxyUtils.java",
    "content": "/*\n * Copyright 2017 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 */\npackage io.realm;\n\nimport android.annotation.TargetApi;\nimport android.os.Build;\nimport android.util.JsonReader;\nimport android.util.JsonToken;\n\nimport org.bson.types.Decimal128;\nimport org.bson.types.ObjectId;\nimport org.json.JSONArray;\nimport org.json.JSONException;\nimport org.json.JSONObject;\n\nimport java.io.IOException;\nimport java.util.Date;\nimport java.util.HashMap;\nimport java.util.HashSet;\nimport java.util.Locale;\nimport java.util.Map;\nimport java.util.Set;\nimport java.util.UUID;\n\nimport javax.annotation.Nonnull;\nimport javax.annotation.Nullable;\n\nimport io.realm.internal.OsList;\nimport io.realm.internal.RealmObjectProxy;\nimport io.realm.internal.android.JsonUtils;\n\n\nclass ProxyUtils {\n\n    /**\n     * Called by proxy to set the managed {@link RealmList} according to the given {@link JSONObject}.\n     *\n     * @param realmList  the managed {@link RealmList}.\n     * @param jsonObject the {@link JSONObject} which may contain the data of the list to be set.\n     * @param fieldName  the field name of the {@link RealmList}.\n     * @param <E>        type of the {@link RealmList}.\n     * @throws JSONException if it fails to parse JSON.\n     */\n    static <E> void setRealmListWithJsonObject(Realm realm,\n            RealmList<E> realmList, JSONObject jsonObject, String fieldName, boolean update) throws JSONException {\n        if (!jsonObject.has(fieldName)) {\n            return;\n        }\n\n        OsList osList = realmList.getOsList();\n        if (jsonObject.isNull(fieldName)) {\n            osList.removeAll();\n            return;\n        }\n\n        JSONArray jsonArray = jsonObject.getJSONArray(fieldName);\n        osList.removeAll();\n        int arraySize = jsonArray.length();\n\n        if (realmList.clazz == Boolean.class) {\n            for (int i = 0; i < arraySize; i++) {\n                if (jsonArray.isNull(i)) {\n                    osList.addNull();\n                } else {\n                    osList.addBoolean(jsonArray.getBoolean(i));\n                }\n            }\n        } else if (realmList.clazz == Float.class) {\n            for (int i = 0; i < arraySize; i++) {\n                if (jsonArray.isNull(i)) {\n                    osList.addNull();\n                } else {\n                    osList.addFloat((float) jsonArray.getDouble(i));\n                }\n            }\n        } else if (realmList.clazz == Double.class) {\n            for (int i = 0; i < arraySize; i++) {\n                if (jsonArray.isNull(i)) {\n                    osList.addNull();\n                } else {\n                    osList.addDouble(jsonArray.getDouble(i));\n                }\n            }\n        } else if (realmList.clazz == String.class) {\n            for (int i = 0; i < arraySize; i++) {\n                if (jsonArray.isNull(i)) {\n                    osList.addNull();\n                } else {\n                    osList.addString(jsonArray.getString(i));\n                }\n            }\n        } else if (realmList.clazz == byte[].class) {\n            for (int i = 0; i < arraySize; i++) {\n                if (jsonArray.isNull(i)) {\n                    osList.addNull();\n                } else {\n                    osList.addBinary(JsonUtils.stringToBytes(jsonArray.getString(i)));\n                }\n            }\n        } else if (realmList.clazz == Date.class) {\n            for (int i = 0; i < arraySize; i++) {\n                if (jsonArray.isNull(i)) {\n                    osList.addNull();\n                    continue;\n                }\n\n                Object timestamp = jsonArray.get(i);\n                if (timestamp instanceof String) {\n                    osList.addDate(JsonUtils.stringToDate((String) timestamp));\n                } else {\n                    osList.addDate(new Date(jsonArray.getLong(i)));\n                }\n            }\n        } else if (realmList.clazz == ObjectId.class) {\n            for (int i = 0; i < arraySize; i++) {\n                if (jsonArray.isNull(i)) {\n                    osList.addNull();\n                    continue;\n                }\n\n                Object id = jsonArray.get(i);\n                if (id instanceof String) {\n                    osList.addObjectId(new ObjectId((String) id));\n                } else {\n                    osList.addObjectId((ObjectId) id);\n                }\n            }\n        } else if (realmList.clazz == Decimal128.class) {\n            for (int i = 0; i < arraySize; i++) {\n                if (jsonArray.isNull(i)) {\n                    osList.addNull();\n                    continue;\n                }\n\n                Object decimal = jsonArray.get(i);\n\n                if (decimal instanceof org.bson.types.Decimal128) {\n                    osList.addDecimal128((org.bson.types.Decimal128) decimal);\n                } else if (decimal instanceof String) {\n                    osList.addDecimal128(org.bson.types.Decimal128.parse((String) decimal));\n                } else if (decimal instanceof Integer) {\n                    osList.addDecimal128(new org.bson.types.Decimal128((Integer) (decimal)));\n                } else if (decimal instanceof Long) {\n                    osList.addDecimal128(new org.bson.types.Decimal128((Long) (decimal)));\n                } else if (decimal instanceof Double) {\n                    osList.addDecimal128(new org.bson.types.Decimal128(new java.math.BigDecimal((Double) (decimal))));\n                } else {\n                    osList.addDecimal128((Decimal128) decimal);\n                }\n            }\n        } else if (realmList.clazz == UUID.class) {\n            for (int i = 0; i < arraySize; i++) {\n                if (jsonArray.isNull(i)) {\n                    osList.addNull();\n                    continue;\n                }\n\n                Object uuid = jsonArray.get(i);\n                if (uuid instanceof java.util.UUID) {\n                    osList.addUUID((java.util.UUID) uuid);\n                } else {\n                    osList.addUUID(java.util.UUID.fromString((String)uuid));\n                }\n            }\n        } else if (realmList.clazz == RealmAny.class) {\n            for (int i = 0; i < arraySize; i++) {\n                if (jsonArray.isNull(i)) {\n                    osList.addNull();\n                    continue;\n                }\n\n                Object value = jsonArray.get(i);\n                RealmAny realmAny;\n                if (value instanceof String) {\n                    realmAny = RealmAny.valueOf((String) value);\n                } else if (value instanceof Integer) {\n                    realmAny = RealmAny.valueOf((Integer) value);\n                } else if (value instanceof Long) {\n                    realmAny = RealmAny.valueOf((Long) value);\n                } else if (value instanceof Double) {\n                    realmAny = RealmAny.valueOf((Double) value);\n                } else if (value instanceof Boolean) {\n                    realmAny = RealmAny.valueOf((Boolean) value);\n                } else if (value instanceof RealmAny) {\n                    realmAny = (io.realm.RealmAny) value;\n                    realmAny = ProxyUtils.copyOrUpdate(realmAny, realm, update, new HashMap<>(), new HashSet<>());\n                } else {\n                    throw new IllegalArgumentException(String.format(\"Unsupported JSON type: %s\", value.getClass().getSimpleName()));\n                }\n                osList.addRealmAny(realmAny.getNativePtr());\n            }\n        } else if (realmList.clazz == Long.class || realmList.clazz == Integer.class ||\n                realmList.clazz == Short.class || realmList.clazz == Byte.class) {\n            for (int i = 0; i < arraySize; i++) {\n                if (jsonArray.isNull(i)) {\n                    osList.addNull();\n                } else {\n                    osList.addLong(jsonArray.getLong(i));\n                }\n            }\n        } else {\n            throwWrongElementType(realmList.clazz);\n        }\n    }\n\n    /**\n     * Called by proxy to create an unmanaged {@link RealmList} according to the given {@link JsonReader}.\n     *\n     * @param elementClass the type of the {@link RealmList}.\n     * @param jsonReader   the JSON stream to be parsed which may contain the data of the list to be set.\n     * @param <E>          type of the {@link RealmList}.\n     * @throws IOException if it fails to parse JSON stream.\n     */\n    @TargetApi(Build.VERSION_CODES.HONEYCOMB)\n    static <E> RealmList<E> createRealmListWithJsonStream(Class<E> elementClass, JsonReader jsonReader) throws IOException {\n\n        if (jsonReader.peek() == null) {\n            jsonReader.skipValue();\n            return null;\n        }\n\n        jsonReader.beginArray();\n        RealmList realmList = new RealmList<E>();\n\n        if (elementClass == Boolean.class) {\n            while (jsonReader.hasNext()) {\n                if (jsonReader.peek() == JsonToken.NULL) {\n                    jsonReader.skipValue();\n                    realmList.add(null);\n                } else {\n                    realmList.add(jsonReader.nextBoolean());\n                }\n            }\n        } else if (elementClass == Float.class) {\n            while (jsonReader.hasNext()) {\n                if (jsonReader.peek() == JsonToken.NULL) {\n                    jsonReader.skipValue();\n                    realmList.add(null);\n                } else {\n                    realmList.add((float) jsonReader.nextDouble());\n                }\n            }\n        } else if (elementClass == Double.class) {\n            while (jsonReader.hasNext()) {\n                if (jsonReader.peek() == JsonToken.NULL) {\n                    jsonReader.skipValue();\n                    realmList.add(null);\n                } else {\n                    realmList.add(jsonReader.nextDouble());\n                }\n            }\n        } else if (elementClass == String.class) {\n            while (jsonReader.hasNext()) {\n                if (jsonReader.peek() == JsonToken.NULL) {\n                    jsonReader.skipValue();\n                    realmList.add(null);\n                } else {\n                    realmList.add(jsonReader.nextString());\n                }\n            }\n        } else if (elementClass == byte[].class) {\n            while (jsonReader.hasNext()) {\n                if (jsonReader.peek() == JsonToken.NULL) {\n                    jsonReader.skipValue();\n                    realmList.add(null);\n                } else {\n                    realmList.add(JsonUtils.stringToBytes(jsonReader.nextString()));\n                }\n            }\n        } else if (elementClass == Date.class) {\n            while (jsonReader.hasNext()) {\n                JsonToken token = jsonReader.peek();\n                if (token == JsonToken.NULL) {\n                    jsonReader.skipValue();\n                    realmList.add(null);\n                } else if (token == JsonToken.NUMBER) {\n                    realmList.add(new Date(jsonReader.nextLong()));\n                } else {\n                    realmList.add(JsonUtils.stringToDate(jsonReader.nextString()));\n                }\n            }\n        } else if (elementClass == Long.class) {\n            while (jsonReader.hasNext()) {\n                if (jsonReader.peek() == JsonToken.NULL) {\n                    jsonReader.skipValue();\n                    realmList.add(null);\n                } else {\n                    realmList.add(jsonReader.nextLong());\n                }\n            }\n        } else if (elementClass == Integer.class) {\n            while (jsonReader.hasNext()) {\n                if (jsonReader.peek() == JsonToken.NULL) {\n                    jsonReader.skipValue();\n                    realmList.add(null);\n                } else {\n                    realmList.add((int) jsonReader.nextLong());\n                }\n            }\n        } else if (elementClass == Short.class) {\n            while (jsonReader.hasNext()) {\n                if (jsonReader.peek() == JsonToken.NULL) {\n                    jsonReader.skipValue();\n                    realmList.add(null);\n                } else {\n                    realmList.add((short) jsonReader.nextLong());\n                }\n            }\n        } else if (elementClass == Byte.class) {\n            while (jsonReader.hasNext()) {\n                if (jsonReader.peek() == JsonToken.NULL) {\n                    jsonReader.skipValue();\n                    realmList.add(null);\n                } else {\n                    realmList.add((byte) jsonReader.nextLong());\n                }\n            }\n        } else if (elementClass == ObjectId.class) {\n            while (jsonReader.hasNext()) {\n                if (jsonReader.peek() == JsonToken.NULL) {\n                    jsonReader.skipValue();\n                    realmList.add(null);\n                } else {\n                    realmList.add(new ObjectId(jsonReader.nextString()));\n                }\n            }\n        } else if (elementClass == Decimal128.class) {\n            while (jsonReader.hasNext()) {\n                if (jsonReader.peek() == JsonToken.NULL) {\n                    jsonReader.skipValue();\n                    realmList.add(null);\n                } else {\n                    realmList.add(org.bson.types.Decimal128.parse(jsonReader.nextString()));\n                }\n            }\n        } else if (elementClass == UUID.class) {\n            while (jsonReader.hasNext()) {\n                if (jsonReader.peek() == JsonToken.NULL) {\n                    jsonReader.skipValue();\n                    realmList.add(null);\n                } else {\n                    realmList.add(java.util.UUID.fromString(jsonReader.nextString()));\n                }\n            }\n        } else if (elementClass == RealmAny.class) {\n            while (jsonReader.hasNext()) {\n                if (jsonReader.peek() == JsonToken.NULL) {\n                    jsonReader.skipValue();\n                    realmList.add(RealmAny.nullValue());\n                } else if (jsonReader.peek() == JsonToken.STRING) {\n                    realmList.add(RealmAny.valueOf(jsonReader.nextString()));\n                } else if (jsonReader.peek() == JsonToken.NUMBER) {\n                    String value = jsonReader.nextString();\n                    if (value.contains(\".\")) {\n                        realmList.add(RealmAny.valueOf(Double.parseDouble(value)));\n                    } else {\n                        realmList.add(RealmAny.valueOf(Long.parseLong(value)));\n                    }\n                } else if (jsonReader.peek() == JsonToken.BOOLEAN) {\n                    realmList.add(RealmAny.valueOf(jsonReader.nextBoolean()));\n                }\n            }\n        } else if (elementClass == ObjectId.class) {\n            while (jsonReader.hasNext()) {\n                if (jsonReader.peek() == JsonToken.NULL) {\n                    jsonReader.skipValue();\n                    realmList.add(null);\n                } else {\n                    realmList.add(new ObjectId(jsonReader.nextString()));\n                }\n            }\n        } else if (elementClass == Decimal128.class) {\n            while (jsonReader.hasNext()) {\n                if (jsonReader.peek() == JsonToken.NULL) {\n                    jsonReader.skipValue();\n                    realmList.add(null);\n                } else {\n                    realmList.add(org.bson.types.Decimal128.parse(jsonReader.nextString()));\n                }\n            }\n        } else {\n            throwWrongElementType(elementClass);\n        }\n\n        jsonReader.endArray();\n\n        return realmList;\n    }\n\n    private static void throwWrongElementType(@Nullable Class clazz) {\n        throw new IllegalArgumentException(String.format(Locale.ENGLISH, \"Element type '%s' is not handled.\",\n                clazz));\n    }\n\n    @Nullable\n    static <T extends RealmModel> RealmAny copyToRealmIfNeeded(ProxyState<T> proxyState, @Nullable RealmAny value) {\n        final Realm realm = (Realm) proxyState.getRealm$realm();\n\n        if (value == null) {\n            return RealmAny.nullValue();\n        }\n\n        if (value.getType() == RealmAny.Type.OBJECT) {\n            RealmModel realmAnyRealmModel = value.asRealmModel(RealmModel.class);\n\n            if (realm.getSchema().getSchemaForClass(realmAnyRealmModel.getClass()).isEmbedded()) {\n                throw new IllegalArgumentException(\"Embedded objects are not supported by RealmAny.\");\n            }\n\n            if (!RealmObject.isManaged(realmAnyRealmModel)) {\n                if (realm.hasPrimaryKey(realmAnyRealmModel.getClass())) {\n                    value = RealmAny.valueOf(realm.copyToRealmOrUpdate(realmAnyRealmModel));\n                } else {\n                    value = RealmAny.valueOf(realm.copyToRealm(realmAnyRealmModel));\n                }\n            } else {\n                proxyState.checkValidObject(realmAnyRealmModel);\n            }\n        }\n\n        return value;\n    }\n\n    @SuppressWarnings(\"unchecked\")\n    static RealmAny copyOrUpdate(RealmAny realmAny, @Nonnull Realm realm, boolean update, @Nonnull Map<RealmModel, RealmObjectProxy> cache, @Nonnull Set<ImportFlag> flags) {\n        if (realmAny == null) {\n            return RealmAny.nullValue();\n        }\n\n        if (realmAny.getType() == RealmAny.Type.OBJECT) {\n            Class<? extends RealmModel> realmAnyValueClass = (Class<? extends RealmModel>) realmAny.getValueClass();\n            RealmModel realmAnyRealmObject = realmAny.asRealmModel(realmAnyValueClass);\n\n            RealmObjectProxy cacheRealmObject = cache.get(realmAnyRealmObject);\n            if (cacheRealmObject != null) {\n                realmAny = RealmAny.valueOf(cacheRealmObject);\n            } else {\n                RealmModel managedRealmAnyRealmObject = realm\n                        .getConfiguration()\n                        .getSchemaMediator()\n                        .copyOrUpdate(realm, realmAnyRealmObject, update, cache, flags);\n\n                realmAny = RealmAny.valueOf(managedRealmAnyRealmObject);\n            }\n        }\n\n        return realmAny;\n    }\n\n    @SuppressWarnings(\"unchecked\")\n    static RealmAny insert(RealmAny realmAny, @Nonnull Realm realm, @Nonnull Map<RealmModel, Long> cache) {\n        if (realmAny == null) {\n            return RealmAny.nullValue();\n        }\n\n        if (realmAny.getType() == RealmAny.Type.OBJECT) {\n            Class<? extends RealmModel> realmAnyValueClass = (Class<? extends RealmModel>) realmAny.getValueClass();\n            RealmModel realmAnyRealmObject = realmAny.asRealmModel(realmAnyValueClass);\n\n            Long cacheRealmObject = cache.get(realmAnyRealmObject);\n            if (cacheRealmObject != null) {\n                realmAny = RealmAny.valueOf(cacheRealmObject);\n            } else {\n                long index = realm.getConfiguration()\n                        .getSchemaMediator()\n                        .insert(realm, realmAnyRealmObject, cache);\n\n                RealmModel realmModel = realm.get(realmAnyValueClass, null, index);\n\n                realmAny = RealmAny.valueOf(realmModel);\n            }\n        }\n\n        return realmAny;\n    }\n\n    @SuppressWarnings(\"unchecked\")\n    static RealmAny insertOrUpdate(RealmAny realmAny, @Nonnull Realm realm, @Nonnull Map<RealmModel, Long> cache) {\n        if (realmAny == null) {\n            return RealmAny.nullValue();\n        }\n\n        if (realmAny.getType() == RealmAny.Type.OBJECT) {\n            Class<? extends RealmModel> realmAnyValueClass = (Class<? extends RealmModel>) realmAny.getValueClass();\n            RealmModel realmAnyRealmObject = realmAny.asRealmModel(realmAnyValueClass);\n\n            Long cacheRealmObject = cache.get(realmAnyRealmObject);\n            if (cacheRealmObject != null) {\n                realmAny = RealmAny.valueOf(cacheRealmObject);\n            } else {\n                long index = realm.getConfiguration()\n                        .getSchemaMediator()\n                        .insertOrUpdate(realm, realmAnyRealmObject, cache);\n\n                realmAny = RealmAny.valueOf(realm.get(realmAnyValueClass, null, index));\n            }\n        }\n\n        return realmAny;\n    }\n\n    @SuppressWarnings(\"unchecked\")\n    static RealmAny createDetachedCopy(RealmAny realmAny, @Nonnull Realm realm, int currentDepth, int maxDepth, Map<RealmModel, RealmObjectProxy.CacheData<RealmModel>> cache) {\n        if (currentDepth > maxDepth || realmAny == null) {\n            return RealmAny.nullValue();\n        }\n\n        if (realmAny.getType() == RealmAny.Type.OBJECT) {\n            Class<? extends RealmModel> realmAnyValueClass = (Class<? extends RealmModel>) realmAny.getValueClass();\n            RealmModel realmAnyRealmObject = realmAny.asRealmModel(realmAnyValueClass);\n\n            RealmModel detachedCopy = realm.getConfiguration()\n                    .getSchemaMediator()\n                    .createDetachedCopy(realmAnyRealmObject, maxDepth - 1, cache);\n\n            realmAny = RealmAny.valueOf(detachedCopy);\n        }\n\n        return realmAny;\n    }\n\n    @SuppressWarnings(\"unchecked\")\n    static RealmAny createOrUpdateUsingJsonObject(RealmAny realmAny, @Nonnull Realm realm, int currentDepth, int maxDepth, Map<RealmModel, RealmObjectProxy.CacheData<RealmModel>> cache) {\n        if (currentDepth > maxDepth || realmAny == null) {\n            return RealmAny.nullValue();\n        }\n\n        if (realmAny.getType() == RealmAny.Type.OBJECT) {\n            Class<? extends RealmModel> realmAnyValueClass = (Class<? extends RealmModel>) realmAny.getValueClass();\n            RealmModel realmAnyRealmObject = realmAny.asRealmModel(realmAnyValueClass);\n\n            RealmModel detachedCopy = realm.getConfiguration()\n                    .getSchemaMediator()\n                    .createDetachedCopy(realmAnyRealmObject, maxDepth - 1, cache);\n\n            realmAny = RealmAny.valueOf(detachedCopy);\n        }\n\n        return realmAny;\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/Realm.java",
    "content": "/*\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\npackage io.realm;\n\nimport android.app.IntentService;\nimport android.content.Context;\nimport android.os.Build;\nimport android.os.SystemClock;\nimport android.util.JsonReader;\n\nimport org.json.JSONArray;\nimport org.json.JSONException;\nimport org.json.JSONObject;\n\nimport java.io.File;\nimport java.io.FileNotFoundException;\nimport java.io.IOException;\nimport java.io.InputStream;\nimport java.io.InputStreamReader;\nimport java.lang.reflect.Constructor;\nimport java.lang.reflect.InvocationTargetException;\nimport java.lang.reflect.Method;\nimport java.util.ArrayList;\nimport java.util.Collection;\nimport java.util.Collections;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Locale;\nimport java.util.Map;\nimport java.util.Scanner;\nimport java.util.Set;\nimport java.util.concurrent.Future;\nimport java.util.concurrent.atomic.AtomicInteger;\n\nimport javax.annotation.Nullable;\n\nimport io.reactivex.Flowable;\nimport io.realm.annotations.RealmClass;\nimport io.realm.exceptions.RealmError;\nimport io.realm.exceptions.RealmException;\nimport io.realm.exceptions.RealmFileException;\nimport io.realm.exceptions.RealmMigrationNeededException;\nimport io.realm.exceptions.RealmPrimaryKeyConstraintException;\nimport io.realm.internal.ColumnIndices;\nimport io.realm.internal.ObjectServerFacade;\nimport io.realm.internal.OsObject;\nimport io.realm.internal.OsObjectStore;\nimport io.realm.internal.OsSchemaInfo;\nimport io.realm.internal.OsSharedRealm;\nimport io.realm.internal.RealmCore;\nimport io.realm.internal.RealmNotifier;\nimport io.realm.internal.RealmObjectProxy;\nimport io.realm.internal.RealmProxyMediator;\nimport io.realm.internal.Row;\nimport io.realm.internal.Table;\nimport io.realm.internal.Util;\nimport io.realm.internal.annotations.ObjectServer;\nimport io.realm.internal.async.RealmAsyncTaskImpl;\nimport io.realm.log.RealmLog;\n\n/**\n * The Realm class is the storage and transactional manager of your object persistent store. It is in charge of creating\n * instances of your RealmObjects. Objects within a Realm can be queried and read at any time. Creating, modifying, and\n * deleting objects must be done while inside a transaction. See {@link #executeTransaction(Transaction)}\n * <p>\n * The transactions ensure that multiple instances (on multiple threads) can access the same objects in a consistent\n * state with full ACID guarantees.\n * <p>\n * It is important to remember to call the {@link #close()} method when done with a Realm instance. Failing to do so can\n * lead to {@link java.lang.OutOfMemoryError} as the native resources cannot be freed.\n * <p>\n * Realm instances cannot be used across different threads. This means that you have to open an instance on each thread\n * you want to use Realm. Realm instances are cached automatically per thread using reference counting, so as long as\n * the reference count doesn't reach zero, calling {@link #getInstance(RealmConfiguration)} will just return the cached\n * Realm and should be considered a lightweight operation.\n * <p>\n * For the UI thread this means that opening and closing Realms should occur in either onCreate/onDestroy or\n * onStart/onStop.\n * <p>\n * Realm instances coordinate their state across threads using the {@link android.os.Handler} mechanism. This also means\n * that Realm instances on threads without an {@link android.os.Looper} cannot receive updates unless {@link #refresh()}\n * is manually called.\n * <p>\n * A standard pattern for working with Realm in Android activities can be seen below:\n * <p>\n * <pre>\n * public class RealmApplication extends Application {\n *\n *     \\@Override\n *     public void onCreate() {\n *         super.onCreate();\n *\n *         // The Realm file will be located in package's \"files\" directory.\n *         RealmConfiguration realmConfig = new RealmConfiguration.Builder(this).build();\n *         Realm.setDefaultConfiguration(realmConfig);\n *     }\n * }\n *\n * public class RealmActivity extends Activity {\n *\n *   private Realm realm;\n *\n *   \\@Override\n *   protected void onCreate(Bundle savedInstanceState) {\n *     super.onCreate(savedInstanceState);\n *     setContentView(R.layout.layout_main);\n *     realm = Realm.getDefaultInstance();\n *   }\n *\n *   \\@Override\n *   protected void onDestroy() {\n *     super.onDestroy();\n *     realm.close();\n *   }\n * }\n * </pre>\n * <p>\n * Realm supports String and byte fields containing up to 16 MB.\n * <p>\n *\n * @see <a href=\"http://en.wikipedia.org/wiki/ACID\">ACID</a>\n * @see <a href=\"https://github.com/realm/realm-java/tree/master/examples\">Examples using Realm</a>\n */\npublic class Realm extends BaseRealm {\n\n    private static final String NULL_CONFIG_MSG = \"A non-null RealmConfiguration must be provided\";\n\n    public static final String DEFAULT_REALM_NAME = RealmConfiguration.DEFAULT_REALM_NAME;\n\n    /**\n     * The required length for encryption keys used to encrypt Realm data.\n     */\n    public static final int ENCRYPTION_KEY_LENGTH = 64;\n\n    private static final Object defaultConfigurationLock = new Object();\n    // guarded by `defaultConfigurationLock`\n    private static RealmConfiguration defaultConfiguration;\n    private final RealmSchema schema;\n\n    /**\n     * The constructor is private to enforce the use of the static one.\n     *\n     * @param cache the {@link RealmCache} associated to this Realm instance.\n     * @throws IllegalArgumentException if trying to open an encrypted Realm with the wrong key.\n     */\n    private Realm(RealmCache cache, OsSharedRealm.VersionID version) {\n        super(cache, createExpectedSchemaInfo(cache.getConfiguration().getSchemaMediator()), version);\n        schema = new ImmutableRealmSchema(this,\n                new ColumnIndices(configuration.getSchemaMediator(), sharedRealm.getSchemaInfo()));\n        // FIXME: This is to work around the different behaviour between the read only Realms in the Object Store and\n        //  in current java implementation. Opening a read only Realm with some missing schemas is allowed by Object\n        //  Store and realm-cocoa. In that case, any query based on the missing schema should just return an empty\n        //  results. Fix this together with https://github.com/realm/realm-java/issues/2953\n        if (configuration.isReadOnly()) {\n            RealmProxyMediator mediator = configuration.getSchemaMediator();\n            Set<Class<? extends RealmModel>> classes = mediator.getModelClasses();\n            for (Class<? extends RealmModel> clazz  : classes) {\n                String tableName = Table.getTableNameForClass(mediator.getSimpleClassName(clazz));\n                if (!sharedRealm.hasTable(tableName)) {\n                    sharedRealm.close();\n                    throw new RealmMigrationNeededException(configuration.getPath(),\n                            String.format(Locale.US, \"Cannot open the read only Realm. '%s' is missing.\",\n                                    Table.getClassNameForTable(tableName)));\n                }\n            }\n        }\n    }\n\n    private Realm(OsSharedRealm sharedRealm) {\n        super(sharedRealm);\n        schema = new ImmutableRealmSchema(this,\n                new ColumnIndices(configuration.getSchemaMediator(), sharedRealm.getSchemaInfo()));\n    }\n\n    private static OsSchemaInfo createExpectedSchemaInfo(RealmProxyMediator mediator) {\n        return new OsSchemaInfo(mediator.getExpectedObjectSchemaInfoMap().values());\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    @Override\n    public Flowable<Realm> asFlowable() {\n        return configuration.getRxFactory().from(this);\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    @Override\n    public boolean isEmpty() {\n        checkIfValid();\n        for (RealmObjectSchema clazz : schema.getAll()) {\n            if (!clazz.getClassName().startsWith(\"__\") && clazz.getTable().size() > 0) {\n                return false;\n            }\n        }\n        return true;\n    }\n\n    /**\n     * Returns the schema for this Realm. The schema is immutable.\n     * Any attempt to modify it will result in an {@link UnsupportedOperationException}.\n     * <p>\n     * The schema can only be modified using {@link DynamicRealm#getSchema()} or through an migration.\n     *\n     * @return The {@link RealmSchema} for this Realm.\n     */\n    @Override\n    public RealmSchema getSchema() {\n        return schema;\n    }\n\n    /**\n     * Initializes the Realm library and creates a default configuration that is ready to use. It is required to call\n     * this method before interacting with any other of the Realm API's.\n     * <p>\n     * A good place is in an {@link android.app.Application} subclass:\n     * <pre>\n     * {@code\n     * public class MyApplication extends Application {\n     *   \\@Override\n     *   public void onCreate() {\n     *     super.onCreate();\n     *     Realm.init(this);\n     *   }\n     * }\n     * }\n     * </pre>\n     * <p>\n     * Remember to register it in the {@code AndroidManifest.xml} file:\n     * <pre>\n     * {@code\n     * <?xml version=\"1.0\" encoding=\"utf-8\"?>\n     * <manifest xmlns:android=\"http://schemas.android.com/apk/res/android\" package=\"io.realm.example\">\n     * <application android:name=\".MyApplication\">\n     *   // ...\n     * </application>\n     * </manifest>\n     * }\n     * </pre>\n     *\n     * @param context the Application Context.\n     * @throws IllegalArgumentException if a {@code null} context is provided.\n     * @throws IllegalStateException if {@link Context#getFilesDir()} could not be found.\n     * @see #getDefaultInstance()\n     */\n    public static synchronized void init(Context context) {\n        initializeRealm(context, \"\");\n    }\n\n\n    /**\n     * Initializes the Realm library and creates a default configuration that is ready to use. It is required to call\n     * this method before interacting with any other of the Realm API's.\n     * <p>\n     * A good place is in an {@link android.app.Application} subclass:\n     * <pre>\n     * {@code\n     * public class MyApplication extends Application {\n     *   \\@Override\n     *   public void onCreate() {\n     *     super.onCreate();\n     *     Realm.init(this, \"MyApp/\" + BuildConfig.VERSION_NAME);\n     *   }\n     * }\n     * }\n     * </pre>\n     * <p>\n     * Remember to register it in the {@code AndroidManifest.xml} file:\n     * <pre>\n     * {@code\n     * <?xml version=\"1.0\" encoding=\"utf-8\"?>\n     * <manifest xmlns:android=\"http://schemas.android.com/apk/res/android\" package=\"io.realm.example\">\n     * <application android:name=\".MyApplication\">\n     *   // ...\n     * </application>\n     * </manifest>\n     * }\n     * </pre>\n     *\n     * @param context the Application Context.\n     * @param userAgent optional user defined string that will be sent to the Realm Object Server\n     * as part of a {@code User-Agent} header when a session is established. This setting will not be\n     * used by non-synchronized Realms.\n     * @throws IllegalArgumentException if a {@code null} context or userAgent is provided.\n     * @throws IllegalStateException if {@link Context#getFilesDir()} could not be found.\n     * @see #getDefaultInstance()\n     */\n    @ObjectServer\n    public static synchronized void init(Context context, String userAgent) {\n        //noinspection ConstantConditions\n        if (userAgent == null) {\n            throw new IllegalArgumentException(\"Non-null 'userAgent' required.\");\n        }\n        initializeRealm(context, userAgent);\n    }\n\n    // Checks whether the app is an Instant App or not. It first it tries with the system\n    // `PackageManager.isInstantApp` available from SDK 26. If not available it tries to invoke,\n    // via reflection, `PackageManagerCompat.isInstantApp` as it has support back to SDK 21.\n    private static boolean isInstantApp(Context context) {\n        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {\n            return context.getPackageManager().isInstantApp();\n        } else {\n            try {\n                Class instantAppsClass = Class.forName(\"com.google.android.gms.instantapps.InstantApps\");\n                Method getPackageManagerCompatMethod = instantAppsClass.getMethod(\"getPackageManagerCompat\", Context.class);\n                Object packageManagerCompatInstance = getPackageManagerCompatMethod.invoke(null, context);\n\n                Class packageManagerClass = Class.forName(\"com.google.android.gms.instantapps.PackageManagerCompat\");\n                Method isInstantAppMethod = packageManagerClass.getMethod(\"isInstantApp\");\n                return (boolean) isInstantAppMethod.invoke(packageManagerCompatInstance);\n            } catch (Exception ignored) {\n                // PackageManagerCompat not found and could not determine if it is instant app\n                return false;\n            }\n        }\n    }\n\n    private static void initializeRealm(Context context, String userAgent) {\n        if (BaseRealm.applicationContext == null) {\n            //noinspection ConstantConditions\n            if (context == null) {\n                throw new IllegalArgumentException(\"Non-null context required.\");\n            }\n            checkFilesDirAvailable(context);\n\n            // https://github.com/realm/realm-java/issues/7640\n            if (isInstantApp(context)) {\n                throw new RealmError(\"Could not initialize Realm: Instant apps are not currently supported.\");\n            }\n\n            RealmCore.loadLibrary(context);\n            setDefaultConfiguration(new RealmConfiguration.Builder(context).build());\n\n            ObjectServerFacade.getSyncFacadeIfPossible().initialize(\n                    context,\n                    userAgent,\n                    (configuration, versionID) -> RealmCache.createRealmOrGetFromCache(\n                            configuration,\n                            Realm.class,\n                            versionID\n                    ),\n                    Realm::createInstance);\n\n            if (context.getApplicationContext() != null) {\n                BaseRealm.applicationContext = context.getApplicationContext();\n            } else {\n                BaseRealm.applicationContext = context;\n            }\n            OsSharedRealm.initialize(new File(context.getFilesDir(), \".realm.temp\"));\n        }\n    }\n\n    /**\n     * In some cases, Context.getFilesDir() is not available when the app launches the first time.\n     * This should never happen according to the official Android documentation, but the race condition wasn't fixed\n     * until Android 4.4.\n     * <p>\n     * This method attempts to fix that situation. If this doesn't work an {@link IllegalStateException} will be\n     * thrown.\n     * <p>\n     * See these links for further details:\n     * https://issuetracker.google.com/issues/36918154\n     * https://github.com/realm/realm-java/issues/4493#issuecomment-295349044\n     */\n    private static void checkFilesDirAvailable(Context context) {\n        File filesDir = context.getFilesDir();\n        if (filesDir != null) {\n            if (filesDir.exists()) {\n                return; // Everything is fine. Escape as soon as possible\n            } else {\n                try {\n                    // This was reported as working on some devices, which I really hope is just the race condition\n                    // kicking in, otherwise something is seriously wrong with the permission system on those devices.\n                    // We will try it anyway, since starting a loop will be slower by many magnitudes.\n                    filesDir.mkdirs();\n                } catch (SecurityException ignored) {\n                }\n            }\n        }\n        if (filesDir == null || !filesDir.exists()) {\n            // Wait a \"reasonable\" amount of time before quitting.\n            // In this case we define reasonable as 200 ms (~12 dropped frames) before giving up (which most likely\n            // will result in the app crashing). This lag would only be seen in worst case scenarios, and then, only\n            // when the app is started the first time.\n            long[] timeoutsMs = new long[]{1, 2, 5, 10, 16}; // Exponential waits, capped at 16 ms;\n            long maxTotalWaitMs = 200;\n            long currentTotalWaitMs = 0;\n            int waitIndex = -1;\n            while (context.getFilesDir() == null || !context.getFilesDir().exists()) {\n                long waitMs = timeoutsMs[Math.min(++waitIndex, timeoutsMs.length - 1)];\n                SystemClock.sleep(waitMs);\n                currentTotalWaitMs += waitMs;\n                if (currentTotalWaitMs > maxTotalWaitMs) {\n                    break;\n                }\n            }\n        }\n\n        // One final check before giving up\n        if (context.getFilesDir() == null || !context.getFilesDir().exists()) {\n            throw new IllegalStateException(\"Context.getFilesDir() returns \" + context.getFilesDir() + \" which is not an existing directory. See https://issuetracker.google.com/issues/36918154\");\n        }\n    }\n\n    /**\n     * Realm static constructor that returns the Realm instance defined by the {@link io.realm.RealmConfiguration} set\n     * by {@link #setDefaultConfiguration(RealmConfiguration)}\n     *\n     * @return an instance of the Realm class.\n     * @throws java.lang.NullPointerException if no default configuration has been defined.\n     * @throws RealmMigrationNeededException if no migration has been provided by the default configuration and the\n     * @throws RealmFileException if an error happened when accessing the underlying Realm file.\n     * was set and the thread opening the Realm was interrupted while the download was in progress.\n     */\n//     * @throws io.realm.exceptions.DownloadingRealmInterruptedException if {@link SyncConfiguration.Builder#waitForInitialRemoteData()}\n//     * RealmObject classes or version has has changed so a migration is required.\n    public static Realm getDefaultInstance() {\n        RealmConfiguration configuration = getDefaultConfiguration();\n        if (configuration == null) {\n            if (BaseRealm.applicationContext == null) {\n                throw new IllegalStateException(\"Call `Realm.init(Context)` before calling this method.\");\n            } else {\n                throw new IllegalStateException(\"Set default configuration by using `Realm.setDefaultConfiguration(RealmConfiguration)`.\");\n            }\n        }\n        return RealmCache.createRealmOrGetFromCache(configuration, Realm.class);\n    }\n\n    /**\n     * Realm static constructor that returns the Realm instance defined by provided {@link io.realm.RealmConfiguration}\n     *\n     * @param configuration {@link RealmConfiguration} used to open the Realm\n     * @return an instance of the Realm class\n     * @throws RealmMigrationNeededException if no migration has been provided by the configuration and the RealmObject\n     * classes or version has has changed so a migration is required.\n     * @throws RealmFileException if an error happened when accessing the underlying Realm file.\n     * @throws IllegalArgumentException if a null {@link RealmConfiguration} is provided.\n     * @see RealmConfiguration for details on how to configure a Realm.\n     */\n//     * @throws io.realm.exceptions.DownloadingRealmInterruptedException if {@link SyncConfiguration.Builder#waitForInitialRemoteData()}\n//     * was set and the thread opening the Realm was interrupted while the download was in progress.\n    public static Realm getInstance(RealmConfiguration configuration) {\n        //noinspection ConstantConditions\n        if (configuration == null) {\n            throw new IllegalArgumentException(NULL_CONFIG_MSG);\n        }\n        return RealmCache.createRealmOrGetFromCache(configuration, Realm.class);\n    }\n\n    /**\n     * The creation of the first Realm instance per {@link RealmConfiguration} in a process can take some time as all\n     * initialization code need to run at that point (setting up the Realm, validating schemas and creating initial\n     * data). This method places the initialization work in a background thread and deliver the Realm instance\n     * to the caller thread asynchronously after the initialization is finished.\n     *\n     * @param configuration {@link RealmConfiguration} used to open the Realm.\n     * @param callback invoked to return the results.\n     * @throws IllegalArgumentException if a null {@link RealmConfiguration} or a null {@link Callback} is provided.\n     * @throws IllegalStateException if it is called from a non-Looper or {@link IntentService} thread.\n     * @return a {@link RealmAsyncTask} representing a cancellable task.\n     * @see Callback for more details.\n     */\n    public static RealmAsyncTask getInstanceAsync(RealmConfiguration configuration,\n                                                  Callback callback) {\n        //noinspection ConstantConditions\n        if (configuration == null) {\n            throw new IllegalArgumentException(NULL_CONFIG_MSG);\n        }\n        return RealmCache.createRealmOrGetFromCacheAsync(configuration, callback, Realm.class);\n    }\n\n    /**\n     * Sets the {@link io.realm.RealmConfiguration} used when calling {@link #getDefaultInstance()}.\n     *\n     * @param configuration the {@link io.realm.RealmConfiguration} to use as the default configuration.\n     * @throws IllegalArgumentException if a null {@link RealmConfiguration} is provided.\n     * @see RealmConfiguration for details on how to configure a Realm.\n     */\n    public static void setDefaultConfiguration(RealmConfiguration configuration) {\n        //noinspection ConstantConditions\n        if (configuration == null) {\n            throw new IllegalArgumentException(\"A non-null RealmConfiguration must be provided\");\n        }\n        synchronized (defaultConfigurationLock) {\n            defaultConfiguration = configuration;\n        }\n    }\n\n    /**\n     * Returns the default configuration for {@link #getDefaultInstance()}.\n     *\n     * @return default configuration object or {@code null} if no default configuration is specified.\n     */\n    @Nullable\n    public static RealmConfiguration getDefaultConfiguration() {\n        synchronized (defaultConfigurationLock) {\n            return defaultConfiguration;\n        }\n    }\n\n    /**\n     * Removes the current default configuration (if any). Any further calls to {@link #getDefaultInstance()} will\n     * fail until a new default configuration has been set using {@link #setDefaultConfiguration(RealmConfiguration)}.\n     */\n    public static void removeDefaultConfiguration() {\n        synchronized (defaultConfigurationLock) {\n            defaultConfiguration = null;\n        }\n    }\n\n    /**\n     * Creates a {@link Realm} instance without checking the existence in the {@link RealmCache}.\n     *\n     * @param cache the {@link RealmCache} where to create the realm in.\n     * @return a {@link Realm} instance.\n     */\n    static Realm createInstance(RealmCache cache, OsSharedRealm.VersionID version) {\n        return new Realm(cache, version);\n    }\n\n    /**\n     * Creates a {@code Realm} instance directly from a {@link OsSharedRealm}. This {@code Realm} doesn't need to be\n     * closed.\n     */\n    static Realm createInstance(OsSharedRealm sharedRealm) {\n        return new Realm(sharedRealm);\n    }\n\n    /**\n     * Creates a Realm object for each object in a JSON array. This must be done within a transaction.\n     * <p>\n     * JSON properties with unknown properties will be ignored. If a {@link RealmObject} field is not present in the\n     * JSON object the {@link RealmObject} field will be set to the default value for that type.\n     *\n     * <p>\n     * This method currently does not support value list field.\n     *\n     * @param clazz type of Realm objects to create.\n     * @param json an array where each JSONObject must map to the specified class.\n     * @throws RealmException if mapping from JSON fails.\n     * @throws IllegalArgumentException if the JSON object doesn't have a primary key property but the corresponding\n     * {@link RealmObjectSchema} has a {@link io.realm.annotations.PrimaryKey} defined.\n     * @throws UnsupportedOperationException if the object to insert contains a {@link RealmDictionary} or\n     * a {@link RealmSet}.\n     * @see RealmSet\n     * @see RealmDictionary\n     * @see RealmMap\n     */\n    public <E extends RealmModel> void createAllFromJson(Class<E> clazz, JSONArray json) {\n        //noinspection ConstantConditions\n        if (clazz == null || json == null) {\n            return;\n        }\n        checkIfValid();\n\n        for (int i = 0; i < json.length(); i++) {\n            try {\n                configuration.getSchemaMediator().createOrUpdateUsingJsonObject(clazz, this, json.getJSONObject(i), false);\n            } catch (JSONException e) {\n                throw new RealmException(\"Could not map JSON\", e);\n            }\n        }\n    }\n\n    /**\n     * Tries to update a list of existing objects identified by their primary key with new JSON data. If an existing\n     * object could not be found in the Realm, a new object will be created. This must happen within a transaction.\n     * If updating a {@link RealmObject} and a field is not found in the JSON object, that field will not be updated. If\n     * a new {@link RealmObject} is created and a field is not found in the JSON object, that field will be assigned the\n     * default value for the field type.\n     *\n     * <p>\n     * This method currently does not support value list field.\n     *\n     * @param clazz type of {@link io.realm.RealmObject} to create or update. It must have a primary key defined.\n     * @param json array with object data.\n     * @throws IllegalArgumentException if trying to update a class without a {@link io.realm.annotations.PrimaryKey}.\n     * @throws IllegalArgumentException if the JSON object doesn't have a primary key property but the corresponding\n     * {@link RealmObjectSchema} has a {@link io.realm.annotations.PrimaryKey} defined.\n     * @throws RealmException if unable to map JSON.\n     * @throws UnsupportedOperationException if the object to insert contains a {@link RealmDictionary} or\n     * a {@link RealmSet}.\n     * @see #createAllFromJson(Class, org.json.JSONArray)\n     * @see RealmSet\n     * @see RealmDictionary\n     * @see RealmMap\n     */\n    public <E extends RealmModel> void createOrUpdateAllFromJson(Class<E> clazz, JSONArray json) {\n        //noinspection ConstantConditions\n        if (clazz == null || json == null) {\n            return;\n        }\n        checkIfValid();\n        checkHasPrimaryKey(clazz);\n        for (int i = 0; i < json.length(); i++) {\n            try {\n                configuration.getSchemaMediator().createOrUpdateUsingJsonObject(clazz, this, json.getJSONObject(i), true);\n            } catch (JSONException e) {\n                throw new RealmException(\"Could not map JSON\", e);\n            }\n        }\n    }\n\n    /**\n     * Creates a Realm object for each object in a JSON array. This must be done within a transaction.\n     * JSON properties with unknown properties will be ignored. If a {@link RealmObject} field is not present in the\n     * JSON object the {@link RealmObject} field will be set to the default value for that type.\n     *\n     * <p>\n     * This method currently does not support value list field.\n     *\n     * @param clazz type of Realm objects to create.\n     * @param json the JSON array as a String where each object can map to the specified class.\n     * @throws RealmException if mapping from JSON fails.\n     * @throws IllegalArgumentException if the JSON object doesn't have a primary key property but the corresponding\n     * {@link RealmObjectSchema} has a {@link io.realm.annotations.PrimaryKey} defined.\n     * @throws UnsupportedOperationException if the object to insert contains a {@link RealmDictionary} or\n     * a {@link RealmSet}.\n     * @see RealmSet\n     * @see RealmDictionary\n     * @see RealmMap\n     */\n    public <E extends RealmModel> void createAllFromJson(Class<E> clazz, String json) {\n        //noinspection ConstantConditions\n        if (clazz == null || json == null || json.length() == 0) {\n            return;\n        }\n\n        JSONArray arr;\n        try {\n            arr = new JSONArray(json);\n        } catch (JSONException e) {\n            throw new RealmException(\"Could not create JSON array from string\", e);\n        }\n\n        createAllFromJson(clazz, arr);\n    }\n\n    /**\n     * Tries to update a list of existing objects identified by their primary key with new JSON data. If an existing\n     * object could not be found in the Realm, a new object will be created. This must happen within a transaction.\n     * If updating a {@link RealmObject} and a field is not found in the JSON object, that field will not be updated.\n     * If a new {@link RealmObject} is created and a field is not found in the JSON object, that field will be assigned\n     * the default value for the field type.\n     *\n     * <p>\n     * This method currently does not support value list field.\n     *\n     * @param clazz type of {@link io.realm.RealmObject} to create or update. It must have a primary key defined.\n     * @param json string with an array of JSON objects.\n     * @throws IllegalArgumentException if trying to update a class without a {@link io.realm.annotations.PrimaryKey}.\n     * @throws RealmException if unable to create a JSON array from the json string.\n     * @throws IllegalArgumentException if the JSON object doesn't have a primary key property but the corresponding\n     * {@link RealmObjectSchema} has a {@link io.realm.annotations.PrimaryKey} defined.\n     * @throws UnsupportedOperationException if the object to insert contains a {@link RealmDictionary} or\n     * a {@link RealmSet}.\n     * @see #createAllFromJson(Class, String)\n     * @see RealmSet\n     * @see RealmDictionary\n     * @see RealmMap\n     */\n    public <E extends RealmModel> void createOrUpdateAllFromJson(Class<E> clazz, String json) {\n        //noinspection ConstantConditions\n        if (clazz == null || json == null || json.length() == 0) {\n            return;\n        }\n        checkIfValid();\n        checkHasPrimaryKey(clazz);\n\n        JSONArray arr;\n        try {\n            arr = new JSONArray(json);\n        } catch (JSONException e) {\n            throw new RealmException(\"Could not create JSON array from string\", e);\n        }\n\n        createOrUpdateAllFromJson(clazz, arr);\n    }\n\n    /**\n     * Creates a Realm object for each object in a JSON array. This must be done within a transaction.\n     * JSON properties with unknown properties will be ignored. If a {@link RealmObject} field is not present in the\n     * JSON object the {@link RealmObject} field will be set to the default value for that type.\n     * <p>\n     * This API is only available in API level 11 or later.\n     *\n     * <p>\n     * This method currently does not support value list field.\n     *\n     * @param clazz type of Realm objects created.\n     * @param inputStream the JSON array as a InputStream. All objects in the array must be of the specified class.\n     * @throws RealmException if mapping from JSON fails.\n     * @throws IllegalArgumentException if the JSON object doesn't have a primary key property but the corresponding\n     * {@link RealmObjectSchema} has a {@link io.realm.annotations.PrimaryKey} defined.\n     * @throws IOException if something was wrong with the input stream.\n     * @throws UnsupportedOperationException if the object to insert contains a {@link RealmDictionary} or\n     * a {@link RealmSet}.\n     * @see RealmSet\n     * @see RealmDictionary\n     * @see RealmMap\n     */\n    public <E extends RealmModel> void createAllFromJson(Class<E> clazz, InputStream inputStream) throws IOException {\n        //noinspection ConstantConditions\n        if (clazz == null || inputStream == null) {\n            return;\n        }\n        checkIfValid();\n\n        JsonReader reader = new JsonReader(new InputStreamReader(inputStream, \"UTF-8\"));\n        try {\n            reader.beginArray();\n            while (reader.hasNext()) {\n                configuration.getSchemaMediator().createUsingJsonStream(clazz, this, reader);\n            }\n            reader.endArray();\n        } finally {\n            reader.close();\n        }\n    }\n\n    /**\n     * Tries to update a list of existing objects identified by their primary key with new JSON data. If an existing\n     * object could not be found in the Realm, a new object will be created. This must happen within a transaction.\n     * If updating a {@link RealmObject} and a field is not found in the JSON object, that field will not be updated.\n     * If a new {@link RealmObject} is created and a field is not found in the JSON object, that field will be assigned\n     * the default value for the field type.\n     * <p>\n     * This API is only available in API level 11 or later.\n     *\n     * <p>\n     * This method currently does not support value list field.\n     *\n     * @param clazz type of {@link io.realm.RealmObject} to create or update. It must have a primary key defined.\n     * @param in the InputStream with a list of object data in JSON format.\n     * @throws IllegalArgumentException if trying to update a class without a {@link io.realm.annotations.PrimaryKey}.\n     * @throws IllegalArgumentException if the JSON object doesn't have a primary key property but the corresponding\n     * {@link RealmObjectSchema} has a {@link io.realm.annotations.PrimaryKey} defined.\n     * @throws RealmException if unable to read JSON.\n     * @throws UnsupportedOperationException if the object to insert contains a {@link RealmDictionary} or\n     * a {@link RealmSet}.\n     * @see #createOrUpdateAllFromJson(Class, java.io.InputStream)\n     * @see RealmSet\n     * @see RealmDictionary\n     * @see RealmMap\n     */\n    public <E extends RealmModel> void createOrUpdateAllFromJson(Class<E> clazz, InputStream in) {\n        //noinspection ConstantConditions\n        if (clazz == null || in == null) {\n            return;\n        }\n        checkIfValid();\n        checkHasPrimaryKey(clazz);\n\n        // As we need the primary key value we have to first parse the entire input stream as in the general\n        // case that value might be the last property. :(\n        Scanner scanner = null;\n        try {\n            scanner = getFullStringScanner(in);\n            JSONArray json = new JSONArray(scanner.next());\n            for (int i = 0; i < json.length(); i++) {\n                configuration.getSchemaMediator().createOrUpdateUsingJsonObject(clazz, this, json.getJSONObject(i), true);\n            }\n        } catch (JSONException e) {\n            throw new RealmException(\"Failed to read JSON\", e);\n        } finally {\n            if (scanner != null) {\n                scanner.close();\n            }\n        }\n    }\n\n    /**\n     * Creates a Realm object pre-filled with data from a JSON object. This must be done inside a transaction. JSON\n     * properties with unknown properties will be ignored. If a {@link RealmObject} field is not present in the JSON\n     * object the {@link RealmObject} field will be set to the default value for that type.\n     *\n     * <p>\n     * This method currently does not support value list field.\n     *\n     * @param clazz type of Realm object to create.\n     * @param json the JSONObject with object data.\n     * @return created object or {@code null} if no JSON data was provided.\n     * @throws RealmException if the mapping from JSON fails.\n     * @throws IllegalArgumentException if the JSON object doesn't have a primary key property but the corresponding\n     * {@link RealmObjectSchema} has a {@link io.realm.annotations.PrimaryKey} defined.\n     * @throws UnsupportedOperationException if the object to insert contains a {@link RealmDictionary} or\n     * a {@link RealmSet}.\n     * @see #createOrUpdateObjectFromJson(Class, org.json.JSONObject)\n     * @see RealmSet\n     * @see RealmDictionary\n     * @see RealmMap\n     */\n    @Nullable\n    public <E extends RealmModel> E createObjectFromJson(Class<E> clazz, JSONObject json) {\n        //noinspection ConstantConditions\n        if (clazz == null || json == null) {\n            return null;\n        }\n        checkIfValid();\n\n        try {\n            return configuration.getSchemaMediator().createOrUpdateUsingJsonObject(clazz, this, json, false);\n        } catch (JSONException e) {\n            throw new RealmException(\"Could not map JSON\", e);\n        }\n    }\n\n    /**\n     * Tries to update an existing object defined by its primary key with new JSON data. If no existing object could be\n     * found a new object will be saved in the Realm. This must happen within a transaction. If updating a {@link RealmObject}\n     * and a field is not found in the JSON object, that field will not be updated. If a new {@link RealmObject} is\n     * created and a field is not found in the JSON object, that field will be assigned the default value for the field type.\n     *\n     * <p>\n     * This method currently does not support value list field.\n     *\n     * @param clazz Type of {@link io.realm.RealmObject} to create or update. It must have a primary key defined.\n     * @param json {@link org.json.JSONObject} with object data.\n     * @return created or updated {@link io.realm.RealmObject}.\n     * @throws IllegalArgumentException if trying to update a class without a {@link io.realm.annotations.PrimaryKey}.\n     * @throws IllegalArgumentException if the JSON object doesn't have a primary key property but the corresponding\n     * {@link RealmObjectSchema} has a {@link io.realm.annotations.PrimaryKey} defined.\n     * @throws RealmException if JSON data cannot be mapped.\n     * @throws UnsupportedOperationException if the object to insert contains a {@link RealmDictionary} or\n     * a {@link RealmSet}.\n     * @see #createObjectFromJson(Class, org.json.JSONObject)\n     * @see RealmSet\n     * @see RealmDictionary\n     * @see RealmMap\n     */\n    public <E extends RealmModel> E createOrUpdateObjectFromJson(Class<E> clazz, JSONObject json) {\n        //noinspection ConstantConditions\n        if (clazz == null || json == null) {\n            return null;\n        }\n        checkIfValid();\n        checkHasPrimaryKey(clazz);\n        try {\n            return configuration.getSchemaMediator().createOrUpdateUsingJsonObject(clazz, this, json, true);\n        } catch (JSONException e) {\n            throw new RealmException(\"Could not map JSON\", e);\n        }\n    }\n\n    /**\n     * Creates a Realm object pre-filled with data from a JSON object. This must be done inside a transaction. JSON\n     * properties with unknown properties will be ignored. If a {@link RealmObject} field is not present in the JSON\n     * object the {@link RealmObject} field will be set to the default value for that type.\n     *\n     * <p>\n     * This method currently does not support value list field.\n     *\n     * @param clazz type of Realm object to create.\n     * @param json the JSON string with object data.\n     * @return created object or {@code null} if JSON string was empty or null.\n     * @throws RealmException if mapping to json failed.\n     * @throws IllegalArgumentException if the JSON object doesn't have a primary key property but the corresponding\n     * {@link RealmObjectSchema} has a {@link io.realm.annotations.PrimaryKey} defined.\n     * @throws UnsupportedOperationException if the object to insert contains a {@link RealmDictionary} or\n     * a {@link RealmSet}.\n     * @see RealmSet\n     * @see RealmDictionary\n     * @see RealmMap\n     */\n    @Nullable\n    public <E extends RealmModel> E createObjectFromJson(Class<E> clazz, String json) {\n        //noinspection ConstantConditions\n        if (clazz == null || json == null || json.length() == 0) {\n            return null;\n        }\n\n        JSONObject obj;\n        try {\n            obj = new JSONObject(json);\n        } catch (JSONException e) {\n            throw new RealmException(\"Could not create Json object from string\", e);\n        }\n\n        return createObjectFromJson(clazz, obj);\n    }\n\n    /**\n     * Tries to update an existing object defined by its primary key with new JSON data. If no existing object could be\n     * found a new object will be saved in the Realm. This must happen within a transaction. If updating a\n     * {@link RealmObject} and a field is not found in the JSON object, that field will not be updated. If a new\n     * {@link RealmObject} is created and a field is not found in the JSON object, that field will be assigned the\n     * default value for the field type.\n     *\n     * <p>\n     * This method currently does not support value list field.\n     *\n     * @param clazz type of {@link io.realm.RealmObject} to create or update. It must have a primary key defined.\n     * @param json string with object data in JSON format.\n     * @return created or updated {@link io.realm.RealmObject}.\n     * @throws IllegalArgumentException if trying to update a class without a {@link io.realm.annotations.PrimaryKey}.\n     * @throws IllegalArgumentException if the JSON object doesn't have a primary key property but the corresponding\n     * {@link RealmObjectSchema} has a {@link io.realm.annotations.PrimaryKey} defined.\n     * @throws RealmException if JSON object cannot be mapped from the string parameter.\n     * @throws UnsupportedOperationException if the object to insert contains a {@link RealmDictionary} or\n     * a {@link RealmSet}.\n     * @see #createObjectFromJson(Class, String)\n     * @see RealmSet\n     * @see RealmDictionary\n     * @see RealmMap\n     */\n    public <E extends RealmModel> E createOrUpdateObjectFromJson(Class<E> clazz, String json) {\n        //noinspection ConstantConditions\n        if (clazz == null || json == null || json.length() == 0) {\n            return null;\n        }\n        checkIfValid();\n        checkHasPrimaryKey(clazz);\n\n        JSONObject obj;\n        try {\n            obj = new JSONObject(json);\n        } catch (JSONException e) {\n            throw new RealmException(\"Could not create Json object from string\", e);\n        }\n\n        return createOrUpdateObjectFromJson(clazz, obj);\n    }\n\n    /**\n     * Creates a Realm object pre-filled with data from a JSON object. This must be done inside a transaction. JSON\n     * properties with unknown properties will be ignored. If a {@link RealmObject} field is not present in the JSON\n     * object the {@link RealmObject} field will be set to the default value for that type.\n     * <p>\n     * This API is only available in API level 11 or later.\n     *\n     * <p>\n     * This method currently does not support value list field.\n     *\n     * @param clazz type of Realm object to create.\n     * @param inputStream the JSON object data as a InputStream.\n     * @return created object or {@code null} if JSON string was empty or null.\n     * @throws RealmException if the mapping from JSON failed.\n     * @throws IllegalArgumentException if the JSON object doesn't have a primary key property but the corresponding\n     * {@link RealmObjectSchema} has a {@link io.realm.annotations.PrimaryKey} defined.\n     * @throws IOException if something went wrong with the input stream.\n     * @throws UnsupportedOperationException if the object to insert contains a {@link RealmDictionary} or\n     * a {@link RealmSet}.\n     * @see RealmSet\n     * @see RealmDictionary\n     * @see RealmMap\n     */\n    @Nullable\n    public <E extends RealmModel> E createObjectFromJson(Class<E> clazz, InputStream inputStream) throws IOException {\n        //noinspection ConstantConditions\n        if (clazz == null || inputStream == null) {\n            return null;\n        }\n        checkIfValid();\n        E realmObject;\n\n        if (OsObjectStore.getPrimaryKeyForObject(\n                sharedRealm, configuration.getSchemaMediator().getSimpleClassName(clazz)) != null) {\n            // As we need the primary key value we have to first parse the entire input stream as in the general\n            // case that value might be the last property. :(\n            Scanner scanner = null;\n            try {\n                scanner = getFullStringScanner(inputStream);\n                JSONObject json = new JSONObject(scanner.next());\n                realmObject = configuration.getSchemaMediator().createOrUpdateUsingJsonObject(clazz, this, json, false);\n\n            } catch (JSONException e) {\n                throw new RealmException(\"Failed to read JSON\", e);\n            } finally {\n                if (scanner != null) {\n                    scanner.close();\n                }\n            }\n        } else {\n            JsonReader reader = new JsonReader(new InputStreamReader(inputStream, \"UTF-8\"));\n            try {\n                realmObject = configuration.getSchemaMediator().createUsingJsonStream(clazz, this, reader);\n            } finally {\n                reader.close();\n            }\n        }\n        return realmObject;\n    }\n\n    /**\n     * Tries to update an existing object defined by its primary key with new JSON data. If no existing object could be\n     * found a new object will be saved in the Realm. This must happen within a transaction. If updating a\n     * {@link RealmObject} and a field is not found in the JSON object, that field will not be updated. If a new\n     * {@link RealmObject} is created and a field is not found in the JSON object, that field will be assigned the\n     * default value for the field type.\n     * <p>\n     * This API is only available in API level 11 or later.\n     *\n     * <p>\n     * This method currently does not support value list field.\n     *\n     * @param clazz type of {@link io.realm.RealmObject} to create or update. It must have a primary key defined.\n     * @param in the {@link InputStream} with object data in JSON format.\n     * @return created or updated {@link io.realm.RealmObject}.\n     * @throws IllegalArgumentException if trying to update a class without a {@link io.realm.annotations.PrimaryKey}.\n     * @throws IllegalArgumentException if the JSON object doesn't have a primary key property but the corresponding\n     * {@link RealmObjectSchema} has a {@link io.realm.annotations.PrimaryKey} defined.\n     * @throws RealmException if failure to read JSON.\n     * @throws UnsupportedOperationException if the object to insert contains a {@link RealmDictionary} or\n     * a {@link RealmSet}.\n     * @see #createObjectFromJson(Class, java.io.InputStream)\n     * @see RealmSet\n     * @see RealmDictionary\n     * @see RealmMap\n     */\n    public <E extends RealmModel> E createOrUpdateObjectFromJson(Class<E> clazz, InputStream in) {\n        //noinspection ConstantConditions\n        if (clazz == null || in == null) {\n            return null;\n        }\n        checkIfValid();\n        checkHasPrimaryKey(clazz);\n\n        // As we need the primary key value we have to first parse the entire input stream as in the general\n        // case that value might be the last property. :(\n        Scanner scanner = null;\n        try {\n            scanner = getFullStringScanner(in);\n            JSONObject json = new JSONObject(scanner.next());\n            return createOrUpdateObjectFromJson(clazz, json);\n        } catch (JSONException e) {\n            throw new RealmException(\"Failed to read JSON\", e);\n        } finally {\n            if (scanner != null) {\n                scanner.close();\n            }\n        }\n    }\n\n    private Scanner getFullStringScanner(InputStream in) {\n        return new Scanner(in, \"UTF-8\").useDelimiter(\"\\\\A\");\n    }\n\n    /**\n     * Instantiates and adds a new object to the Realm.\n     * <p>\n     * This method is only available for model classes with no @PrimaryKey annotation.\n     * If you like to create an object that has a primary key, use {@link #createObject(Class, Object)}\n     * or {@link #copyToRealm(RealmModel, ImportFlag...)} instead.\n     *\n     * @param clazz the Class of the object to create.\n     * @return the new object.\n     * @throws RealmException if the primary key is defined in the model class or an object cannot be created.\n     * @see #createObject(Class, Object)\n     */\n    public <E extends RealmModel> E createObject(Class<E> clazz) {\n        checkIfValid();\n        RealmProxyMediator mediator = configuration.getSchemaMediator();\n        if (mediator.isEmbedded(clazz)) {\n            throw new IllegalArgumentException(\"This class is marked embedded. Use `createEmbeddedObject(class, parent, property)` instead:  \" + mediator.getSimpleClassName(clazz));\n        }\n        return createObjectInternal(clazz, true, Collections.<String>emptyList());\n    }\n\n    /**\n     * Same as {@link #createObject(Class)} but this does not check the thread.\n     *\n     * @param clazz the Class of the object to create.\n     * @param acceptDefaultValue if {@code true}, default value of the object will be applied and\n     * if {@code false}, it will be ignored.\n     * @return the new object.\n     * @throws RealmException if the primary key is defined in the model class or an object cannot be created.\n     */\n    // Called from proxy classes.\n    <E extends RealmModel> E createObjectInternal(\n            Class<E> clazz,\n            boolean acceptDefaultValue,\n            List<String> excludeFields) {\n        Table table = schema.getTable(clazz);\n        // Checks and throws the exception earlier for a better exception message.\n        if (OsObjectStore.getPrimaryKeyForObject(\n                sharedRealm, configuration.getSchemaMediator().getSimpleClassName(clazz)) != null) {\n            throw new RealmException(String.format(Locale.US, \"'%s' has a primary key, use\" +\n                    \" 'createObject(Class<E>, Object)' instead.\", table.getClassName()));\n        }\n        return configuration.getSchemaMediator().newInstance(clazz, this,\n                OsObject.create(table),\n                schema.getColumnInfo(clazz),\n                acceptDefaultValue, excludeFields);\n    }\n\n    /**\n     * Instantiates and adds a new object to the Realm with the primary key value already set.\n     * <p>\n     * If the value violates the primary key constraint, no object will be added and a {@link RealmException} will be\n     * thrown.\n     * The default value for primary key provided by the model class will be ignored.\n     *\n     * @param clazz the Class of the object to create.\n     * @param primaryKeyValue value for the primary key field.\n     * @return the new object.\n     * @throws RealmException if object could not be created due to the primary key being invalid.\n     * @throws IllegalStateException if the model class does not have an primary key defined.\n     * @throws IllegalArgumentException if the {@code primaryKeyValue} doesn't have a value that can be converted to the\n     * expected value.\n     */\n    public <E extends RealmModel> E createObject(Class<E> clazz, @Nullable Object primaryKeyValue) {\n        checkIfValid();\n        RealmProxyMediator mediator = configuration.getSchemaMediator();\n        if (mediator.isEmbedded(clazz)) {\n            throw new IllegalArgumentException(\"This class is marked embedded. Use `createEmbeddedObject(class, parent, property)` instead:  \" + mediator.getSimpleClassName(clazz));\n        }\n        return createObjectInternal(clazz, primaryKeyValue, true, Collections.<String>emptyList());\n    }\n\n    /**\n     * Instantiates and adds a new embedded object to the Realm.\n     * <p>\n     * This method should only be used to create objects of types marked as embedded.\n     *\n     * @param clazz the Class of the object to create. It must be marked with {@code \\@RealmClass(embedded = true)}.\n     * @param parentObject The parent object which should hold a reference to the embedded object.\n     * @param parentProperty the property in the parent class which holds the reference. If the parent property is a list\n     * the embedded object will be added to the end of that list.\n     * @return the newly created embedded object.\n     * @throws IllegalArgumentException if {@code clazz} is not an embedded class or if the property\n     * in the parent class cannot hold objects of the appropriate type.\n     * @see RealmClass#embedded()\n     */\n    public <E extends RealmModel> E createEmbeddedObject(Class<E> clazz, RealmModel parentObject, String parentProperty) {\n        checkIfValid();\n        Util.checkNull(parentObject, \"parentObject\");\n        Util.checkEmpty(parentProperty, \"parentProperty\");\n        if (!RealmObject.isManaged(parentObject) || !RealmObject.isValid(parentObject)) {\n            throw new IllegalArgumentException(\"Only valid, managed objects can be a parent to an embedded object.\");\n        }\n\n        String className = schema.getSchemaForClass(clazz).getClassName();\n        Class<? extends RealmModel> parentClassName = parentObject.getClass();\n        RealmObjectSchema parentObjectSchema = schema.getSchemaForClass(parentClassName);\n\n        Row embeddedObject = getEmbeddedObjectRow(className, (RealmObjectProxy) parentObject, parentProperty, schema, parentObjectSchema);\n\n        //noinspection unchecked\n        return (E) configuration.getSchemaMediator().newInstance(clazz,\n                this,\n                embeddedObject,\n                schema.getColumnInfo(clazz),\n                true, Collections.EMPTY_LIST);\n    }\n\n    /**\n     * Same as {@link #createObject(Class, Object)} but this does not check the thread.\n     *\n     * @param clazz the Class of the object to create.\n     * @param primaryKeyValue value for the primary key field.\n     * @param acceptDefaultValue if {@code true}, default value of the object will be applied and\n     * if {@code false}, it will be ignored.\n     * @return the new object.\n     * @throws RealmException if object could not be created due to the primary key being invalid.\n     * @throws IllegalStateException if the model class does not have an primary key defined.\n     * @throws IllegalArgumentException if the {@code primaryKeyValue} doesn't have a value that can be converted to the\n     * expected value.\n     */\n    // Called from proxy classes.\n    <E extends RealmModel> E createObjectInternal(\n            Class<E> clazz,\n            @Nullable Object primaryKeyValue,\n            boolean acceptDefaultValue,\n            List<String> excludeFields) {\n        Table table = schema.getTable(clazz);\n\n        return configuration.getSchemaMediator().newInstance(clazz, this,\n                OsObject.createWithPrimaryKey(table, primaryKeyValue),\n                schema.getColumnInfo(clazz),\n                acceptDefaultValue, excludeFields);\n    }\n\n    /**\n     * Copies a RealmObject to the Realm instance and returns the copy. Any further changes to the original RealmObject\n     * will not be reflected in the Realm copy. This is a deep copy, so all referenced objects will be copied. Objects\n     * already in this Realm will be ignored.\n     * <p>\n     * Please note, copying an object will copy all field values. Any unset field in this and child objects will be\n     * set to their default value if not provided.\n     *\n     * @param object the {@link io.realm.RealmObject} to copy to the Realm.\n     * @param flags any flag that modifies the behaviour of inserting the data into the Realm.\n     * @return a managed RealmObject with its properties backed by the Realm.\n     * @throws java.lang.IllegalArgumentException if the object is {@code null} or it belongs to a Realm instance\n     * in a different thread.\n     */\n    public <E extends RealmModel> E copyToRealm(E object, ImportFlag... flags) {\n        checkNotNullObject(object);\n\n        return copyOrUpdate(object, false, new HashMap<>(), Util.toSet(flags));\n    }\n\n    /**\n     * Updates an existing RealmObject that is identified by the same {@link io.realm.annotations.PrimaryKey} or creates\n     * a new copy if no existing object could be found. This is a deep copy or update i.e., all referenced objects will be\n     * either copied or updated.\n     * <p>\n     * Please note, copying an object will copy all field values. Any unset field in the object and child objects will be\n     * set to their default value if not provided.\n     *\n     * @param object {@link io.realm.RealmObject} to copy or update.\n     * @param flags any flag that modifies the behaviour of inserting the data into the Realm.\n     * @return the new or updated RealmObject with all its properties backed by the Realm.\n     * @throws java.lang.IllegalArgumentException if the object is {@code null} or doesn't have a Primary key defined\n     * or it belongs to a Realm instance in a different thread.\n     * @see #copyToRealm(RealmModel, ImportFlag...)\n     */\n    public <E extends RealmModel> E copyToRealmOrUpdate(E object, ImportFlag... flags) {\n        checkNotNullObject(object);\n        checkHasPrimaryKey(object.getClass());\n        return copyOrUpdate(object, true, new HashMap<>(), Util.toSet(flags));\n    }\n\n    /**\n     * Copies a collection of RealmObjects to the Realm instance and returns their copy. Any further changes to the\n     * original RealmObjects will not be reflected in the Realm copies. This is a deep copy i.e., all referenced objects\n     * will be copied. Objects already in this Realm will be ignored.\n     * <p>\n     * Please note, copying an object will copy all field values. Any unset field in the objects and child objects will be\n     * set to their default value if not provided.\n     *\n     * @param objects the RealmObjects to copy to the Realm.\n     * @param flags any flag that modifies the behaviour of inserting the data into the Realm.\n     * @return a list of the the converted RealmObjects that all has their properties managed by the Realm.\n     * @throws io.realm.exceptions.RealmException if any of the objects has already been added to Realm.\n     * @throws java.lang.IllegalArgumentException if any of the elements in the input collection is {@code null}.\n     */\n    public <E extends RealmModel> List<E> copyToRealm(Iterable<E> objects, ImportFlag... flags) {\n        //noinspection ConstantConditions\n        if (objects == null) {\n            return new ArrayList<>();\n        }\n        ArrayList realmObjects;\n        if (objects instanceof Collection) {\n            realmObjects = new ArrayList<>(((Collection) objects).size());\n        } else {\n            realmObjects = new ArrayList<>();\n        }\n        Map<RealmModel, RealmObjectProxy> cache = new HashMap<>();\n        for (E object : objects) {\n            checkNotNullObject(object);\n            realmObjects.add(copyOrUpdate(object, false, cache, Util.toSet(flags)));\n        }\n\n        return realmObjects;\n    }\n\n    /**\n     * Inserts a list of an unmanaged RealmObjects. This is generally faster than {@link #copyToRealm(Iterable, ImportFlag...)} since it\n     * doesn't return the inserted elements, and performs minimum allocations and checks.\n     * After being inserted any changes to the original objects will not be persisted.\n     * <p>\n     * Please note:\n     * <ul>\n     * <li>\n     * We don't check if the provided objects are already managed or not, so inserting a managed object might duplicate it.\n     * Duplication will only happen if the object doesn't have a primary key. Objects with primary keys will never get duplicated.\n     * </li>\n     * <li>We don't create (nor return) a managed {@link RealmObject} for each element</li>\n     * <li>Copying an object will copy all field values. Any unset field in the object and child objects will be set to their default value if not provided</li>\n     * </ul>\n     * <p>\n     * If you want the managed {@link RealmObject} returned, use {@link #copyToRealm(Iterable, ImportFlag...)}, otherwise if\n     * you have a large number of object this method is generally faster.\n     *\n     * @param objects RealmObjects to insert.\n     * @throws IllegalStateException if the corresponding Realm is closed, called from an incorrect thread or not in a\n     * transaction.\n     */\n    public void insert(Collection<? extends RealmModel> objects) {\n        checkIfValidAndInTransaction();\n        //noinspection ConstantConditions\n        if (objects == null) {\n            throw new IllegalArgumentException(\"Null objects cannot be inserted into Realm.\");\n        }\n        if (objects.isEmpty()) {\n            return;\n        }\n        configuration.getSchemaMediator().insert(this, objects);\n    }\n\n    /**\n     * Inserts an unmanaged RealmObject. This is generally faster than {@link #copyToRealm(RealmModel, ImportFlag...)} since it\n     * doesn't return the inserted elements, and performs minimum allocations and checks.\n     * After being inserted any changes to the original object will not be persisted.\n     * <p>\n     * Please note:\n     * <ul>\n     * <li>\n     * We don't check if the provided objects are already managed or not, so inserting a managed object might duplicate it.\n     * Duplication will only happen if the object doesn't have a primary key. Objects with primary keys will never get duplicated.\n     * </li>\n     * <li>We don't create (nor return) a managed {@link RealmObject} for each element</li>\n     * <li>Copying an object will copy all field values. Any unset field in the object and child objects will be set to their default value if not provided</li>\n     * </ul>\n     * <p>\n     * If you want the managed {@link RealmObject} returned, use {@link #copyToRealm(RealmModel, ImportFlag...)}, otherwise if\n     * you have a large number of object this method is generally faster.\n     *\n     * @param object RealmObjects to insert.\n     * @throws IllegalStateException if the corresponding Realm is closed, called from an incorrect thread or not in a\n     * transaction.\n     * @throws io.realm.exceptions.RealmPrimaryKeyConstraintException if two objects with the same primary key is\n     * inserted or if a primary key value already exists in the Realm.\n     */\n    public void insert(RealmModel object) {\n        checkIfValidAndInTransaction();\n        //noinspection ConstantConditions\n        if (object == null) {\n            throw new IllegalArgumentException(\"Null object cannot be inserted into Realm.\");\n        }\n        Map<RealmModel, Long> cache = new HashMap<>();\n        configuration.getSchemaMediator().insert(this, object, cache);\n    }\n\n    /**\n     * Inserts or updates a list of unmanaged RealmObjects. This is generally faster than\n     * {@link #copyToRealmOrUpdate(Iterable, ImportFlag...)} since it doesn't return the inserted elements, and performs minimum\n     * allocations and checks.\n     * After being inserted any changes to the original objects will not be persisted.\n     * <p>\n     * Please note:\n     * <ul>\n     * <li>\n     * We don't check if the provided objects are already managed or not, so inserting a managed object might duplicate it.\n     * Duplication will only happen if the object doesn't have a primary key. Objects with primary keys will never get duplicated.\n     * </li>\n     * <li>We don't create (nor return) a managed {@link RealmObject} for each element</li>\n     * <li>Copying an object will copy all field values. Any unset field in the object and child objects will be set to their default value if not provided</li>\n     * </ul>\n     * <p>\n     * If you want the managed {@link RealmObject} returned, use {@link #copyToRealm(Iterable, ImportFlag...)}, otherwise if\n     * you have a large number of object this method is generally faster.\n     *\n     * @param objects RealmObjects to insert.\n     * @throws IllegalStateException if the corresponding Realm is closed, called from an incorrect thread or not in a\n     * transaction.\n     * @throws io.realm.exceptions.RealmPrimaryKeyConstraintException if two objects with the same primary key is\n     * inserted or if a primary key value already exists in the Realm.\n     */\n    public void insertOrUpdate(Collection<? extends RealmModel> objects) {\n        checkIfValidAndInTransaction();\n        //noinspection ConstantConditions\n        if (objects == null) {\n            throw new IllegalArgumentException(\"Null objects cannot be inserted into Realm.\");\n        }\n        if (objects.isEmpty()) {\n            return;\n        }\n        configuration.getSchemaMediator().insertOrUpdate(this, objects);\n    }\n\n    /**\n     * Inserts or updates an unmanaged RealmObject. This is generally faster than\n     * {@link #copyToRealmOrUpdate(RealmModel, ImportFlag...)} since it doesn't return the inserted elements, and performs minimum\n     * allocations and checks.\n     * After being inserted any changes to the original object will not be persisted.\n     * <p>\n     * Please note:\n     * <ul>\n     * <li>\n     * We don't check if the provided objects are already managed or not, so inserting a managed object might duplicate it.\n     * Duplication will only happen if the object doesn't have a primary key. Objects with primary keys will never get duplicated.\n     * </li>\n     * <li>We don't create (nor return) a managed {@link RealmObject} for each element</li>\n     * <li>Copying an object will copy all field values. Any unset field in the object and child objects will be set to their default value if not provided</li>\n     * </ul>\n     * <p>\n     * If you want the managed {@link RealmObject} returned, use {@link #copyToRealm(RealmModel, ImportFlag...)}, otherwise if\n     * you have a large number of object this method is generally faster.\n     *\n     * @param object RealmObjects to insert.\n     * @throws IllegalStateException if the corresponding Realm is closed, called from an incorrect thread or not in a\n     * transaction.\n     */\n    public void insertOrUpdate(RealmModel object) {\n        checkIfValidAndInTransaction();\n        //noinspection ConstantConditions\n        if (object == null) {\n            throw new IllegalArgumentException(\"Null object cannot be inserted into Realm.\");\n        }\n        Map<RealmModel, Long> cache = new HashMap<>();\n        configuration.getSchemaMediator().insertOrUpdate(this, object, cache);\n    }\n\n    /**\n     * Updates a list of existing RealmObjects that is identified by their {@link io.realm.annotations.PrimaryKey} or\n     * creates a new copy if no existing object could be found. This is a deep copy or update i.e., all referenced\n     * objects will be either copied or updated.\n     * <p>\n     * Please note, copying an object will copy all field values. Any unset field in the objects and child objects will be\n     * set to their default value if not provided.\n     *\n     * @param objects a list of objects to update or copy into Realm.\n     * @param flags any flag that modifies the behaviour of inserting the data into the Realm.\n     * @return a list of all the new or updated RealmObjects.\n     * @throws java.lang.IllegalArgumentException if RealmObject is {@code null} or doesn't have a Primary key defined.\n     * @see #copyToRealm(Iterable, ImportFlag...)\n     */\n    public <E extends RealmModel> List<E> copyToRealmOrUpdate(Iterable<E> objects, ImportFlag... flags) {\n        //noinspection ConstantConditions\n        if (objects == null) {\n            return new ArrayList<>(0);\n        }\n\n        ArrayList realmObjects;\n        if (objects instanceof Collection) {\n            realmObjects = new ArrayList<>(((Collection) objects).size());\n        } else {\n            realmObjects = new ArrayList<>();\n        }\n        Map<RealmModel, RealmObjectProxy> cache = new HashMap<>();\n        Set<ImportFlag> importFlags = Util.toSet(flags);\n        for (E object : objects) {\n            checkNotNullObject(object);\n            realmObjects.add(copyOrUpdate(object, true, cache, importFlags));\n        }\n\n        return realmObjects;\n    }\n\n    /**\n     * Makes an unmanaged in-memory copy of already persisted RealmObjects. This is a deep copy that will copy all\n     * referenced objects.\n     * <p>\n     * The copied objects are all detached from Realm and they will no longer be automatically updated. This means\n     * that the copied objects might contain data that are no longer consistent with other managed Realm objects.\n     * <p>\n     * *WARNING*: Any changes to copied objects can be merged back into Realm using\n     * {@link #copyToRealmOrUpdate(RealmModel, ImportFlag...)}, but all fields will be overridden, not just those that\n     * were changed. This includes references to other objects, and can potentially override changes made by other\n     * threads. This behaviour can be modified using {@link ImportFlag}s.\n     *\n     * @param realmObjects RealmObjects to copy.\n     * @param <E> type of object.\n     * @return an in-memory detached copy of managed RealmObjects.\n     * @throws IllegalArgumentException if the RealmObject is no longer accessible or it is a {@link DynamicRealmObject}.\n     * @see #copyToRealmOrUpdate(Iterable, ImportFlag...)\n     */\n    public <E extends RealmModel> List<E> copyFromRealm(Iterable<E> realmObjects) {\n        return copyFromRealm(realmObjects, Integer.MAX_VALUE);\n    }\n\n    /**\n     * Makes an unmanaged in-memory copy of already persisted RealmObjects. This is a deep copy that will copy all\n     * referenced objects up to the defined depth.\n     * <p>\n     * The copied objects are all detached from Realm and they will no longer be automatically updated. This means\n     * that the copied objects might contain data that are no longer consistent with other managed Realm objects.\n     * <p>\n     * *WARNING*: Any changes to copied objects can be merged back into Realm using\n     * {@link #copyToRealmOrUpdate(Iterable, ImportFlag...)}, but all fields will be overridden, not just those that were changed.\n     * This includes references to other objects even though they might be {@code null} due to {@code maxDepth} being\n     * reached. This can also potentially override changes made by other threads. This behaviour can be modified using\n     * {@link ImportFlag}s.\n     *\n     * @param realmObjects RealmObjects to copy.\n     * @param maxDepth limit of the deep copy. All references after this depth will be {@code null}. Starting depth is\n     * {@code 0}.\n     * @param <E> type of object.\n     * @return an in-memory detached copy of the RealmObjects.\n     * @throws IllegalArgumentException if {@code maxDepth < 0}, the RealmObject is no longer accessible or it is a\n     * {@link DynamicRealmObject}.\n     * @see #copyToRealmOrUpdate(Iterable, ImportFlag...)\n     */\n    public <E extends RealmModel> List<E> copyFromRealm(Iterable<E> realmObjects, int maxDepth) {\n        checkMaxDepth(maxDepth);\n        //noinspection ConstantConditions\n        if (realmObjects == null) {\n            return new ArrayList<>(0);\n        }\n\n        ArrayList unmanagedObjects;\n        if (realmObjects instanceof Collection) {\n            unmanagedObjects = new ArrayList<>(((Collection) realmObjects).size());\n        } else {\n            unmanagedObjects = new ArrayList<>();\n        }\n        Map<RealmModel, RealmObjectProxy.CacheData<RealmModel>> listCache = new HashMap<>();\n        for (E object : realmObjects) {\n            checkValidObjectForDetach(object);\n            unmanagedObjects.add(createDetachedCopy(object, maxDepth, listCache));\n        }\n\n        return unmanagedObjects;\n    }\n\n    /**\n     * Makes an unmanaged in-memory copy of an already persisted {@link RealmObject}. This is a deep copy that will copy\n     * all referenced objects.\n     * <p>\n     * The copied object(s) are all detached from Realm and they will no longer be automatically updated. This means\n     * that the copied objects might contain data that are no longer consistent with other managed Realm objects.\n     * <p>\n     * *WARNING*: Any changes to copied objects can be merged back into Realm using\n     * {@link #copyToRealmOrUpdate(RealmModel, ImportFlag...)}, but all fields will be overridden, not just those that were changed.\n     * This includes references to other objects, and can potentially override changes made by other threads.\n     * This behaviour can be modified using {@link ImportFlag}s.\n     *\n     * @param realmObject {@link RealmObject} to copy.\n     * @param <E> type of object.\n     * @return an in-memory detached copy of the managed {@link RealmObject}.\n     * @throws IllegalArgumentException if the RealmObject is no longer accessible or it is a {@link DynamicRealmObject}.\n     * @see #copyToRealmOrUpdate(RealmModel, ImportFlag...)\n     */\n    public <E extends RealmModel> E copyFromRealm(E realmObject) {\n        return copyFromRealm(realmObject, Integer.MAX_VALUE);\n    }\n\n    /**\n     * Makes an unmanaged in-memory copy of an already persisted {@link RealmObject}. This is a deep copy that will copy\n     * all referenced objects up to the defined depth.\n     * <p>\n     * The copied object(s) are all detached from Realm and they will no longer be automatically updated. This means\n     * that the copied objects might contain data that are no longer consistent with other managed Realm objects.\n     * <p>\n     * *WARNING*: Any changes to copied objects can be merged back into Realm using\n     * {@link #copyToRealmOrUpdate(RealmModel, ImportFlag...)}, but all fields will be overridden, not just those that were changed.\n     * This includes references to other objects even though they might be {@code null} due to {@code maxDepth} being\n     * reached. This can also potentially override changes made by other threads. This behaviour can be modified using\n     * {@link ImportFlag}s.\n     *\n     * @param realmObject {@link RealmObject} to copy.\n     * @param maxDepth limit of the deep copy. All references after this depth will be {@code null}. Starting depth is\n     * {@code 0}.\n     * @param <E> type of object.\n     * @return an in-memory detached copy of the managed {@link RealmObject}.\n     * @throws IllegalArgumentException if {@code maxDepth < 0}, the RealmObject is no longer accessible or it is a\n     * {@link DynamicRealmObject}.\n     * @see #copyToRealmOrUpdate(RealmModel, ImportFlag...)\n     */\n    public <E extends RealmModel> E copyFromRealm(E realmObject, int maxDepth) {\n        checkMaxDepth(maxDepth);\n        checkValidObjectForDetach(realmObject);\n        return createDetachedCopy(realmObject, maxDepth, new HashMap<RealmModel, RealmObjectProxy.CacheData<RealmModel>>());\n    }\n\n    /**\n     * Returns a typed RealmQuery, which can be used to query for specific objects of this type\n     *\n     * @param clazz the class of the object which is to be queried for.\n     * @return a typed RealmQuery, which can be used to query for specific objects of this type.\n     * @see io.realm.RealmQuery\n     */\n    public <E extends RealmModel> RealmQuery<E> where(Class<E> clazz) {\n        checkIfValid();\n        return RealmQuery.createQuery(this, clazz);\n    }\n\n    /**\n     * Adds a change listener to the Realm.\n     * <p>\n     * The listeners will be executed when changes are committed by this or another thread.\n     * <p>\n     * Realm instances are per thread singletons and cached, so listeners should be\n     * removed manually even if calling {@link #close()}. Otherwise there is a\n     * risk of memory leaks.\n     *\n     * @param listener the change listener.\n     * @throws IllegalArgumentException if the change listener is {@code null}.\n     * @throws IllegalStateException if you try to register a listener from a non-Looper or {@link IntentService} thread.\n     * @see io.realm.RealmChangeListener\n     * @see #removeChangeListener(RealmChangeListener)\n     * @see #removeAllChangeListeners()\n     */\n    public void addChangeListener(RealmChangeListener<Realm> listener) {\n        addListener(listener);\n    }\n\n    /**\n     * Removes the specified change listener.\n     *\n     * @param listener the change listener to be removed.\n     * @throws IllegalArgumentException if the change listener is {@code null}.\n     * @throws IllegalStateException if you try to remove a listener from a non-Looper Thread.\n     * @see io.realm.RealmChangeListener\n     */\n    public void removeChangeListener(RealmChangeListener<Realm> listener) {\n        removeListener(listener);\n    }\n\n    /**\n     * Removes all user-defined change listeners.\n     *\n     * @throws IllegalStateException if you try to remove listeners from a non-Looper Thread.\n     * @see io.realm.RealmChangeListener\n     */\n    public void removeAllChangeListeners() {\n        removeAllListeners();\n    }\n\n    /**\n     * Executes a given transaction on the Realm. {@link #beginTransaction()} and {@link #commitTransaction()} will be\n     * called automatically. If any exception is thrown during the transaction {@link #cancelTransaction()} will be\n     * called instead of {@link #commitTransaction()}.\n     * <p>\n     * Calling this method from the UI thread will throw a {@link RealmException}. Doing so may result in a drop of frames\n     * or even ANRs. We recommend calling this method from a non-UI thread or using\n     * {@link #executeTransactionAsync(Transaction)} instead.\n     *\n     * @param transaction the {@link io.realm.Realm.Transaction} to execute.\n     * @throws IllegalArgumentException if the {@code transaction} is {@code null}.\n     * @throws RealmMigrationNeededException if the latest version contains incompatible schema changes.\n     * @throws RealmException if called from the UI thread, unless an explicit opt-in has been declared in {@link RealmConfiguration.Builder#allowWritesOnUiThread(boolean)}.\n     */\n    public void executeTransaction(Transaction transaction) {\n        //noinspection ConstantConditions\n        if (transaction == null) {\n            throw new IllegalArgumentException(\"Transaction should not be null\");\n        }\n        checkIfValid();\n        checkAllowWritesOnUiThread();\n\n        beginTransaction();\n        try {\n            transaction.execute(this);\n            commitTransaction();\n        } catch (Throwable e) {\n            if (isInTransaction()) {\n                cancelTransaction();\n            } else {\n                RealmLog.warn(\"Could not cancel transaction, not currently in a transaction.\");\n            }\n            throw e;\n        }\n    }\n\n    /**\n     * Similar to {@link #executeTransaction(Transaction)} but runs asynchronously on a worker thread.\n     *\n     * @param transaction {@link io.realm.Realm.Transaction} to execute.\n     * @return a {@link RealmAsyncTask} representing a cancellable task.\n     * @throws IllegalArgumentException if the {@code transaction} is {@code null}, or if the Realm is opened from\n     * another thread.\n     */\n    public RealmAsyncTask executeTransactionAsync(final Transaction transaction) {\n        return executeTransactionAsync(transaction, null, null);\n    }\n\n    /**\n     * Similar to {@link #executeTransactionAsync(Transaction)}, but also accepts an OnSuccess callback.\n     *\n     * @param transaction {@link io.realm.Realm.Transaction} to execute.\n     * @param onSuccess callback invoked when the transaction succeeds.\n     * @return a {@link RealmAsyncTask} representing a cancellable task.\n     * @throws IllegalArgumentException if the {@code transaction} is {@code null}, or if the realm is opened from\n     * another thread.\n     */\n    public RealmAsyncTask executeTransactionAsync(final Transaction transaction, final Realm.Transaction.OnSuccess onSuccess) {\n        //noinspection ConstantConditions\n        if (onSuccess == null) {\n            throw new IllegalArgumentException(\"onSuccess callback can't be null\");\n        }\n\n        return executeTransactionAsync(transaction, onSuccess, null);\n    }\n\n    /**\n     * Similar to {@link #executeTransactionAsync(Transaction)}, but also accepts an OnError callback.\n     *\n     * @param transaction {@link io.realm.Realm.Transaction} to execute.\n     * @param onError callback invoked when the transaction fails.\n     * @return a {@link RealmAsyncTask} representing a cancellable task.\n     * @throws IllegalArgumentException if the {@code transaction} is {@code null}, or if the realm is opened from\n     * another thread.\n     */\n    public RealmAsyncTask executeTransactionAsync(final Transaction transaction, final Realm.Transaction.OnError onError) {\n        //noinspection ConstantConditions\n        if (onError == null) {\n            throw new IllegalArgumentException(\"onError callback can't be null\");\n        }\n\n        return executeTransactionAsync(transaction, null, onError);\n    }\n\n    /**\n     * Similar to {@link #executeTransactionAsync(Transaction)}, but also accepts an OnSuccess and OnError callbacks.\n     *\n     * @param transaction {@link io.realm.Realm.Transaction} to execute.\n     * @param onSuccess callback invoked when the transaction succeeds.\n     * @param onError callback invoked when the transaction fails.\n     * @return a {@link RealmAsyncTask} representing a cancellable task.\n     * @throws IllegalArgumentException if the {@code transaction} is {@code null}, or if the realm is opened from\n     * another thread.\n     */\n    public RealmAsyncTask executeTransactionAsync(final Transaction transaction,\n            @Nullable final Realm.Transaction.OnSuccess onSuccess,\n            @Nullable final Realm.Transaction.OnError onError) {\n        checkIfValid();\n\n        //noinspection ConstantConditions\n        if (transaction == null) {\n            throw new IllegalArgumentException(\"Transaction should not be null\");\n        }\n\n        if (isFrozen()) {\n            throw new IllegalStateException(\"Write transactions on a frozen Realm is not allowed.\");\n        }\n\n        // Avoid to call canDeliverNotification() in bg thread.\n        final boolean canDeliverNotification = sharedRealm.capabilities.canDeliverNotification();\n\n        // If the user provided a Callback then we have to make sure the current Realm has an events looper to deliver\n        // the results.\n        if ((onSuccess != null || onError != null)) {\n            sharedRealm.capabilities.checkCanDeliverNotification(\"Callback cannot be delivered on current thread.\");\n        }\n\n        // We need to use the same configuration to open a background OsSharedRealm (i.e Realm)\n        // to perform the transaction\n        final RealmConfiguration realmConfiguration = getConfiguration();\n        // We need to deliver the callback even if the Realm is closed. So acquire a reference to the notifier here.\n        final RealmNotifier realmNotifier = sharedRealm.realmNotifier;\n\n        final Future<?> pendingTransaction = asyncTaskExecutor.submitTransaction(new Runnable() {\n            @Override\n            public void run() {\n                if (Thread.currentThread().isInterrupted()) {\n                    return;\n                }\n\n                OsSharedRealm.VersionID versionID = null;\n                Throwable exception = null;\n\n                final Realm bgRealm = Realm.getInstance(realmConfiguration);\n                bgRealm.beginTransaction();\n                try {\n                    transaction.execute(bgRealm);\n\n                    if (Thread.currentThread().isInterrupted()) {\n                        return;\n                    }\n\n                    bgRealm.commitTransaction();\n                    // The bgRealm needs to be closed before post event to caller's handler to avoid concurrency\n                    // problem. This is currently guaranteed by posting callbacks later below.\n                    versionID = bgRealm.sharedRealm.getVersionID();\n                } catch (final Throwable e) {\n                    exception = e;\n                } finally {\n                    try {\n                        if (bgRealm.isInTransaction()) {\n                            bgRealm.cancelTransaction();\n                        }\n                    } finally {\n                        bgRealm.close();\n                    }\n                }\n\n                final Throwable backgroundException = exception;\n                final OsSharedRealm.VersionID backgroundVersionID = versionID;\n                // Cannot be interrupted anymore.\n                if (canDeliverNotification) {\n                    if (backgroundVersionID != null && onSuccess != null) {\n                        realmNotifier.post(new Runnable() {\n                            @Override\n                            public void run() {\n                                if (isClosed()) {\n                                    // The caller Realm is closed. Just call the onSuccess. Since the new created Realm\n                                    // cannot be behind the background one.\n                                    onSuccess.onSuccess();\n                                    return;\n                                }\n\n                                if (sharedRealm.getVersionID().compareTo(backgroundVersionID) < 0) {\n                                    sharedRealm.realmNotifier.addTransactionCallback(new Runnable() {\n                                        @Override\n                                        public void run() {\n                                            onSuccess.onSuccess();\n                                        }\n                                    });\n                                } else {\n                                    onSuccess.onSuccess();\n                                }\n                            }\n                        });\n                    } else if (backgroundException != null) {\n                        realmNotifier.post(new Runnable() {\n                            @Override\n                            public void run() {\n                                if (onError != null) {\n                                    onError.onError(backgroundException);\n                                } else {\n                                    throw new RealmException(\"Async transaction failed\", backgroundException);\n                                }\n                            }\n                        });\n                    }\n                } else {\n                    if (backgroundException != null) {\n                        // FIXME: ThreadPoolExecutor will never throw the exception in the background.\n                        // We need a redesign of the async transaction API.\n                        // Throw in the worker thread since the caller thread cannot get notifications.\n                        throw new RealmException(\"Async transaction failed\", backgroundException);\n                    }\n                }\n\n            }\n        });\n\n        return new RealmAsyncTaskImpl(pendingTransaction, asyncTaskExecutor);\n    }\n\n    /**\n     * Deletes all objects of the specified class from the Realm.\n     *\n     * @param clazz the class which objects should be removed.\n     * @throws IllegalStateException if the Realm is closed or called from an incorrect thread.\n     */\n    public void delete(Class<? extends RealmModel> clazz) {\n        checkIfValid();\n        schema.getTable(clazz).clear();\n    }\n\n\n    @SuppressWarnings(\"unchecked\")\n    private <E extends RealmModel> E copyOrUpdate(E object, boolean update, Map<RealmModel, RealmObjectProxy> cache, Set<ImportFlag> flags) {\n        checkIfValid();\n        if (!isInTransaction()) {\n            throw new IllegalStateException(\"`copyOrUpdate` can only be called inside a write transaction.\");\n\n        }\n        if (configuration.getSchemaMediator().isEmbedded(Util.getOriginalModelClass(object.getClass()))) {\n            throw new IllegalArgumentException(\"Embedded objects cannot be copied into Realm by themselves. They need to be attached to a parent object\");\n        }\n        try {\n            return configuration.getSchemaMediator().copyOrUpdate(this, object, update, cache, flags);\n            // Core throws a RuntimeException if there primary key already exists in realm. Here we\n            // convert it into a RealmPrimaryKeyConstraintException\n        } catch (RuntimeException e) {\n            // See https://github.com/realm/realm-java/issues/6262\n            // For now we convert the OS exception using pattern matching on the error message.\n            if (e.getMessage().startsWith(\"Attempting to create an object of type\")) {\n                throw new RealmPrimaryKeyConstraintException(e.getMessage());\n            } else {\n                throw e;\n            }\n        }\n    }\n\n    private <E extends RealmModel> E createDetachedCopy(E object, int maxDepth, Map<RealmModel, RealmObjectProxy.CacheData<RealmModel>> cache) {\n        checkIfValid();\n        return configuration.getSchemaMediator().createDetachedCopy(object, maxDepth, cache);\n    }\n\n    private <E extends RealmModel> void checkNotNullObject(E object) {\n        //noinspection ConstantConditions\n        if (object == null) {\n            throw new IllegalArgumentException(\"Null objects cannot be copied into Realm.\");\n        }\n    }\n\n    private void checkHasPrimaryKey(Class<? extends RealmModel> clazz) {\n        if (!hasPrimaryKey(clazz)) {\n            throw new IllegalArgumentException(\"A RealmObject with no @PrimaryKey cannot be updated: \" + clazz.toString());\n        }\n    }\n\n    // Called from proxy classes.\n    boolean hasPrimaryKey(Class<? extends RealmModel> clazz){\n        return configuration.getSchemaMediator().hasPrimaryKey(clazz);\n    }\n\n    private void checkMaxDepth(int maxDepth) {\n        if (maxDepth < 0) {\n            throw new IllegalArgumentException(\"maxDepth must be > 0. It was: \" + maxDepth);\n        }\n    }\n\n    private <E extends RealmModel> void checkValidObjectForDetach(E realmObject) {\n        //noinspection ConstantConditions\n        if (realmObject == null) {\n            throw new IllegalArgumentException(\"Null objects cannot be copied from Realm.\");\n        }\n        if (!(RealmObject.isManaged(realmObject) && RealmObject.isValid(realmObject))) {\n            throw new IllegalArgumentException(\"Only valid managed objects can be copied from Realm.\");\n        }\n        if (realmObject instanceof DynamicRealmObject) {\n            throw new IllegalArgumentException(\"DynamicRealmObject cannot be copied from Realm.\");\n        }\n    }\n\n    /**\n     * Manually triggers the migration associated with a given RealmConfiguration. If Realm is already at the latest\n     * version, nothing will happen.\n     *\n     * @param configuration {@link RealmConfiguration}\n     * @throws FileNotFoundException if the Realm file doesn't exist.\n     */\n    public static void migrateRealm(RealmConfiguration configuration) throws FileNotFoundException {\n        migrateRealm(configuration, null);\n    }\n\n    /**\n     * Manually triggers a migration on a RealmMigration.\n     *\n     * @param configuration the{@link RealmConfiguration}.\n     * @param migration the {@link RealmMigration} to run on the Realm. This will override any migration set on the\n     * configuration.\n     * @throws FileNotFoundException if the Realm file doesn't exist.\n     */\n    public static void migrateRealm(RealmConfiguration configuration, @Nullable RealmMigration migration)\n            throws FileNotFoundException {\n        BaseRealm.migrateRealm(configuration, migration);\n    }\n\n    /**\n     * Deletes the Realm file along with the related temporary files specified by the given {@link RealmConfiguration}\n     * from the filesystem. Temporary file with \".lock\" extension won't be deleted.\n     * <p>\n     * All Realm instances must be closed before calling this method.\n     * <p>\n     * WARNING: For synchronized Realm, there is a chance that an internal Realm instance on the background thread is\n     * not closed even all the user controlled Realm instances are closed. This will result an\n     * {@code IllegalStateException}. See issue https://github.com/realm/realm-java/issues/5416 .\n     *\n     * @param configuration a {@link RealmConfiguration}.\n     * @return {@code false} if the Realm file could not be deleted. Temporary files deletion failure won't impact\n     * the return value. All of the failing file deletions will be logged.\n     * @throws IllegalStateException if there are Realm instances opened on other threads or other processes.\n     */\n    public static boolean deleteRealm(RealmConfiguration configuration) {\n        return BaseRealm.deleteRealm(configuration);\n    }\n\n    /**\n     * Compacts a Realm file. A Realm file usually contain free/unused space.\n     * This method removes this free space and the file size is thereby reduced.\n     * Objects within the Realm files are untouched.\n     * <p>\n     * The file must be closed before this method is called, otherwise {@code false} will be returned.<br>\n     * The file system should have free space for at least a copy of the Realm file.<br>\n     * The Realm file is left untouched if any file operation fails.<br>\n     *\n     * @param configuration a {@link RealmConfiguration} pointing to a Realm file.\n     * @return {@code true} if successful, {@code false} if any file operation failed.\n     */\n    public static boolean compactRealm(RealmConfiguration configuration) {\n        return BaseRealm.compactRealm(configuration);\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    @Override\n    public Realm freeze() {\n        return RealmCache.createRealmOrGetFromCache(configuration, Realm.class, sharedRealm.getVersionID());\n    }\n\n    Table getTable(Class<? extends RealmModel> clazz) {\n        return schema.getTable(clazz);\n    }\n\n    /**\n     * Returns the default Realm module. This module contains all Realm classes in the current project, but not those\n     * from library or project dependencies. Realm classes in these should be exposed using their own module.\n     *\n     * @return the default Realm module or {@code null} if no default module exists.\n     * @throws RealmException if unable to create an instance of the module.\n     * @see io.realm.RealmConfiguration.Builder#modules(Object, Object...)\n     */\n    @Nullable\n    public static Object getDefaultModule() {\n        String moduleName = \"io.realm.DefaultRealmModule\";\n        Class<?> clazz;\n        //noinspection TryWithIdenticalCatches\n        try {\n            clazz = Class.forName(moduleName);\n            Constructor<?> constructor = clazz.getDeclaredConstructors()[0];\n            constructor.setAccessible(true);\n            return constructor.newInstance();\n        } catch (ClassNotFoundException e) {\n            return null;\n        } catch (InvocationTargetException e) {\n            throw new RealmException(\"Could not create an instance of \" + moduleName, e);\n        } catch (InstantiationException e) {\n            throw new RealmException(\"Could not create an instance of \" + moduleName, e);\n        } catch (IllegalAccessException e) {\n            throw new RealmException(\"Could not create an instance of \" + moduleName, e);\n        }\n    }\n\n    /**\n     * Returns the current number of open Realm instances across all threads in current process that are using this\n     * configuration. This includes both dynamic and normal Realms.\n     *\n     * @param configuration the {@link io.realm.RealmConfiguration} for the Realm.\n     * @return number of open Realm instances across all threads.\n     */\n    public static int getGlobalInstanceCount(RealmConfiguration configuration) {\n        final AtomicInteger globalCount = new AtomicInteger(0);\n        RealmCache.invokeWithGlobalRefCount(configuration, new RealmCache.Callback() {\n            @Override\n            public void onResult(int count) {\n                globalCount.set(count);\n            }\n        });\n        return globalCount.get();\n    }\n\n    /**\n     * Returns the current number of open Realm instances on the thread calling this method. This include both\n     * dynamic and normal Realms.\n     *\n     * @param configuration the {@link io.realm.RealmConfiguration} for the Realm.\n     * @return number of open Realm instances on the caller thread.\n     */\n    public static int getLocalInstanceCount(RealmConfiguration configuration) {\n        return RealmCache.getLocalThreadCount(configuration);\n    }\n\n    /**\n     * Get the application context used when initializing Realm with {@link Realm#init(Context)} or\n     * {@link Realm#init(Context, String)}.\n     *\n     * @return the application context used when initializing Realm with {@link Realm#init(Context)} or\n     * {@link Realm#init(Context, String)}, or null if Realm has not been initialized yet.\n     */\n    @Nullable\n    public static Context getApplicationContext() {\n        return applicationContext;\n    }\n\n    /**\n     * Encapsulates a Realm transaction.\n     * <p>\n     * Using this class will automatically handle {@link io.realm.Realm#beginTransaction()} and {@link io.realm.Realm#commitTransaction()}\n     * If any exception is thrown during the transaction {@link io.realm.Realm#cancelTransaction()} will be called instead of\n     * {@link io.realm.Realm#commitTransaction()}.\n     */\n    public interface Transaction {\n        void execute(Realm realm);\n\n        /**\n         * Callback invoked to notify the caller thread.\n         */\n        class Callback {\n            public void onSuccess() {}\n\n            public void onError(Exception ignore) {}\n        }\n\n        /**\n         * Callback invoked to notify the caller thread about the success of the transaction.\n         */\n        interface OnSuccess {\n            void onSuccess();\n        }\n\n        /**\n         * Callback invoked to notify the caller thread about error during the transaction.\n         * The transaction will be rolled back and the background Realm will be closed before\n         * invoking {@link #onError(Throwable)}.\n         */\n        interface OnError {\n            void onError(Throwable error);\n        }\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    public abstract static class Callback extends InstanceCallback<Realm> {\n        /**\n         * {@inheritDoc}\n         */\n        @Override\n        public abstract void onSuccess(Realm realm);\n\n        /**\n         * {@inheritDoc}\n         */\n        @Override\n        public void onError(Throwable exception) {\n            super.onError(exception);\n        }\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/RealmAny.java",
    "content": "/*\n * Copyright 2020 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\npackage io.realm;\n\nimport org.bson.types.Decimal128;\nimport org.bson.types.ObjectId;\n\nimport java.util.Date;\nimport java.util.UUID;\n\nimport javax.annotation.Nonnull;\nimport javax.annotation.Nullable;\n\nimport edu.umd.cs.findbugs.annotations.SuppressFBWarnings;\n\nimport static io.realm.RealmFieldTypeConstants.MAX_CORE_TYPE_VALUE;\n\n\n/**\n * {@link io.realm.RealmAny} is used to represent a polymorphic Realm value.\n * <p>\n * At any particular moment an instance of this class stores a\n * definite value of a definite type. If, for instance, that is an\n * double value, you may call asDouble() to extract that value. You\n * may call getType() to discover what type of value is currently\n * stored. Calling asDouble() on an instance that does not store an\n * double would raise a {@link java.lang.ClassCastException}.\n * <p>\n * RealmAny behaves like a value type on all the supported types except on\n * Realm objects. It means that Realm will not persist any change to the\n * RealmAny value except when the type is Realm object. When a RealmAny\n * holds a Realm object, it just holds the reference to it, not a copy of\n * the object. So modifications to the Realm object are reflected in the\n * RealmAny value, including if the object is deleted. Because RealmAny\n * instances are immutable, a new instance is needed to update a RealmAny\n * attribute.\n * <pre>\n * <code>\n *      anObject.realmAnyAttribute = RealmAny.valueOf(5);\n *      anObject.realmAnyAttribute = RealmAny.valueOf(10.f);\n * </code>\n * </pre>\n * It is crucial to understand that the act of extracting a value of\n * a particular type requires definite knowledge about the stored\n * type. Calling a getter method for any particular type, that is not\n * the same type as the stored value, would raise an exception.\n * <p>\n * Our recommendation to handle the RealmAny polymorphism is to write a\n * switch case around the RealmAny type and its inner value class.\n * <pre>\n * <code>\n *      RealmAny realmAny = aRealmObject.realmAnyAttribute;\n *\n *      switch (realmAny.getType()) {\n *          case OBJECT:\n *              if (realmAny.getValueClass().equals(DogRealmModel.class)) {\n *                  DogRealmModel value = realmAny.asRealmModel(DogRealmModel.class);\n *              }\n *          case INTEGER:\n *              performAction(realmAny.asInteger());\n *              break;\n *          case BOOLEAN:\n *              performAction(realmAny.asBoolean());\n *              break;\n *          case STRING:\n *              performAction(realmAny.asString());\n *              break;\n *          case BINARY:\n *              performAction(realmAny.asBinary());\n *              break;\n *          case DATE:\n *              performAction(realmAny.asDate());\n *              break;\n *          case FLOAT:\n *              performAction(realmAny.asFloat());\n *              break;\n *          case DOUBLE:\n *              performAction(realmAny.asDouble());\n *              break;\n *          case DECIMAL128:\n *              performAction(realmAny.asDecimal128());\n *              break;\n *          case OBJECT_ID:\n *              performAction(realmAny.asObjectId());\n *              break;\n *          case UUID:\n *              performAction(realmAny.asUUID());\n *              break;\n *          case NULL:\n *              performNullAction();\n *              break;\n *      }\n * </code>\n * </pre>\n * <p>\n * getValueClass() returns the Java class that represents the inner\n * value wrapped by the RealmAny instance. If the resulting class is\n * a realization of {@link io.realm.RealmModel} asRealmModel() can be\n * called to cast the RealmAny value to a Realm object reference.\n * <p>\n * RealmAny values can also be sorted. The sorting order used between\n * different RealmAny types, from lowest to highest, is:\n * <ol>\n *     <li>Boolean</li>\n *     <li>Byte/Short/Integer/Long/Float/Double/Decimal128</li>\n *     <li>byte[]/String</li>\n *     <li>Date</li>\n *     <li>ObjectId</li>\n *     <li>UUID</li>\n *     <li>RealmObject</li>\n * </ol>\n * This has implications on how {@link RealmQuery#sort(String)},\n * {@link RealmQuery#minRealmAny(String)} and {@link RealmQuery#maxRealmAny(String)}\n * work. Especially {@code min()} and {@code max()} will not only take\n * numeric fields into account, but will use the sorting order to determine\n * the \"largest\" or \"lowest\" value.\n */\npublic class RealmAny {\n    @Nonnull\n    private final RealmAnyOperator operator;\n\n    RealmAny(@Nonnull RealmAnyOperator operator) {\n        this.operator = operator;\n    }\n\n    final long getNativePtr() {\n        return this.operator.getNativePtr();\n    }\n\n    /**\n     * Gets the inner type of this RealmAny object.\n     *\n     * @return the inner RealmAny.Type\n     */\n    public RealmAny.Type getType() {\n        return this.operator.getType();\n    }\n\n    /**\n     * Returns the Java class that represents the inner value wrapped by this RealmAny value.\n     *\n     * @return the class that represents the inner value wrapped by this RealmAny value.\n     */\n    @Nullable\n    public Class<?> getValueClass() {\n        return this.operator.getTypedClass();\n    }\n\n    /**\n     * Creates a new RealmAny with the specified value.\n     * If the value is not null the type will be {@link RealmAny.Type#INTEGER}, {@link RealmAny.Type#NULL} otherwise.\n     *\n     * @param value the RealmAny value.\n     * @return a new RealmAny containing a Byte value.\n     */\n    public static RealmAny valueOf(@Nullable Byte value) {\n        return new RealmAny((value == null) ? new NullRealmAnyOperator() : new IntegerRealmAnyOperator(value));\n    }\n\n    /**\n     * Creates a new RealmAny with the specified value.\n     * If the value is not null the type will be {@link RealmAny.Type#INTEGER}, {@link RealmAny.Type#NULL} otherwise.\n     *\n     * @param value the RealmAny value.\n     * @return a new RealmAny of a Short.\n     */\n    public static RealmAny valueOf(@Nullable Short value) {\n        return new RealmAny((value == null) ? new NullRealmAnyOperator() : new IntegerRealmAnyOperator(value));\n    }\n\n    /**\n     * Creates a new RealmAny with the specified value.\n     * If the value is not null the type will be {@link RealmAny.Type#INTEGER}, {@link RealmAny.Type#NULL} otherwise.\n     *\n     * @param value the RealmAny value.\n     * @return a new RealmAny of a Integer.\n     */\n    public static RealmAny valueOf(@Nullable Integer value) {\n        return new RealmAny((value == null) ? new NullRealmAnyOperator() : new IntegerRealmAnyOperator(value));\n    }\n\n    /**\n     * Creates a new RealmAny with the specified value.\n     * If the value is not null the type will be {@link RealmAny.Type#INTEGER}, {@link RealmAny.Type#NULL} otherwise.\n     *\n     * @param value the RealmAny value.\n     * @return a new RealmAny of a Long.\n     */\n    public static RealmAny valueOf(@Nullable Long value) {\n        return new RealmAny((value == null) ? new NullRealmAnyOperator() : new IntegerRealmAnyOperator(value));\n    }\n\n\n    /**\n     * Creates a new RealmAny with the specified value.\n     * If the value is not null the type will be {@link RealmAny.Type#BOOLEAN}, {@link RealmAny.Type#NULL} otherwise.\n     *\n     * @param value the RealmAny value.\n     * @return a new RealmAny of a Boolean.\n     */\n    public static RealmAny valueOf(@Nullable Boolean value) {\n        return new RealmAny((value == null) ? new NullRealmAnyOperator() : new BooleanRealmAnyOperator(value));\n    }\n\n    /**\n     * Creates a new RealmAny with the specified value.\n     * If the value is not null the type will be {@link RealmAny.Type#FLOAT}, {@link RealmAny.Type#NULL} otherwise.\n     *\n     * @param value the RealmAny value.\n     * @return a new RealmAny of a Float.\n     */\n    public static RealmAny valueOf(@Nullable Float value) {\n        return new RealmAny((value == null) ? new NullRealmAnyOperator() : new FloatRealmAnyOperator(value));\n    }\n\n    /**\n     * Creates a new RealmAny with the specified value.\n     * If the value is not null the type will be {@link RealmAny.Type#DOUBLE}, {@link RealmAny.Type#NULL} otherwise.\n     *\n     * @param value the RealmAny value.\n     * @return a new RealmAny of a Double.\n     */\n    public static RealmAny valueOf(@Nullable Double value) {\n        return new RealmAny((value == null) ? new NullRealmAnyOperator() : new DoubleRealmAnyOperator(value));\n    }\n\n    /**\n     * Creates a new RealmAny with the specified value.\n     * If the value is not null the type will be {@link RealmAny.Type#STRING}, {@link RealmAny.Type#NULL} otherwise.\n     *\n     * @param value the RealmAny value.\n     * @return a new RealmAny of a String.\n     */\n    public static RealmAny valueOf(@Nullable String value) {\n        return new RealmAny((value == null) ? new NullRealmAnyOperator() : new StringRealmAnyOperator(value));\n    }\n\n    /**\n     * Creates a new RealmAny with the specified value.\n     * If the value is not null the type will be {@link RealmAny.Type#BINARY}, {@link RealmAny.Type#NULL} otherwise.\n     *\n     * @param value the RealmAny value.\n     * @return a new RealmAny of a byte[].\n     */\n    public static RealmAny valueOf(@Nullable byte[] value) {\n        return new RealmAny((value == null) ? new NullRealmAnyOperator() : new BinaryRealmAnyOperator(value));\n    }\n\n    /**\n     * Creates a new RealmAny with the specified value.\n     * If the value is not null the type will be {@link RealmAny.Type#DATE}, {@link RealmAny.Type#NULL} otherwise.\n     *\n     * @param value the RealmAny value.\n     * @return a new RealmAny of a Date.\n     */\n    public static RealmAny valueOf(@Nullable Date value) {\n        return new RealmAny((value == null) ? new NullRealmAnyOperator() : new DateRealmAnyOperator(value));\n    }\n\n    /**\n     * Creates a new RealmAny with the specified value.\n     * If the value is not null the type will be {@link RealmAny.Type#OBJECT_ID}, {@link RealmAny.Type#NULL} otherwise.\n     *\n     * @param value the RealmAny value.\n     * @return a new RealmAny of an ObjectId.\n     */\n    public static RealmAny valueOf(@Nullable ObjectId value) {\n        return new RealmAny((value == null) ? new NullRealmAnyOperator() : new ObjectIdRealmAnyOperator(value));\n    }\n\n    /**\n     * Creates a new RealmAny with the specified value.\n     * If the value is not null the type will be {@link RealmAny.Type#DECIMAL128}, {@link RealmAny.Type#NULL} otherwise.\n     *\n     * @param value the RealmAny value.\n     * @return a new RealmAny of a Decimal128.\n     */\n    public static RealmAny valueOf(@Nullable Decimal128 value) {\n        return new RealmAny((value == null) ? new NullRealmAnyOperator() : new Decimal128RealmAnyOperator(value));\n    }\n\n    /**\n     * Creates a new RealmAny with the specified value.\n     * If the value is not null the type will be {@link RealmAny.Type#UUID}, {@link RealmAny.Type#NULL} otherwise.\n     *\n     * @param value the RealmAny value.\n     * @return a new RealmAny of a UUID.\n     */\n    public static RealmAny valueOf(@Nullable UUID value) {\n        return new RealmAny((value == null) ? new NullRealmAnyOperator() : new UUIDRealmAnyOperator(value));\n    }\n\n    /**\n     * Creates a new RealmAny of a null value.\n     *\n     * @return a new RealmAny instance of a null value.\n     */\n    public static RealmAny nullValue() {\n        return new RealmAny(new NullRealmAnyOperator());\n    }\n\n    /**\n     * Creates a new RealmAny with the specified value.\n     *\n     * @param value the RealmAny value.\n     * @return a new RealmAny of a RealmModel.\n     */\n    public static RealmAny valueOf(@Nullable RealmModel value) {\n        return new RealmAny((value == null) ? new NullRealmAnyOperator() : new RealmModelOperator(value));\n    }\n\n    /**\n     * Returns true if the inner value is null, false otherwise.\n     *\n     * @return true if the inner value is null, false otherwise.\n     */\n    public boolean isNull() {\n        return this.getType() == RealmAny.Type.NULL;\n    }\n\n    /**\n     * Gets this value as a Byte if it is one, otherwise throws exception.\n     *\n     * @return a Byte.\n     * @throws java.lang.ClassCastException if this value is not of the expected type.\n     */\n    public Byte asByte() {\n        Number value = operator.getValue(Number.class);\n        return (value == null) ? null : value.byteValue();\n    }\n\n    /**\n     * Gets this value as a Short if it is one, otherwise throws exception.\n     *\n     * @return a Short.\n     * @throws java.lang.ClassCastException if this value is not of the expected type.\n     */\n    public Short asShort() {\n        Number value = operator.getValue(Number.class);\n        return (value == null) ? null : value.shortValue();\n    }\n\n    /**\n     * Gets this value as a Integer if it is one, otherwise throws exception.\n     *\n     * @return an Integer.\n     * @throws java.lang.ClassCastException if this value is not of the expected type.\n     */\n    public Integer asInteger() {\n        Number value = operator.getValue(Number.class);\n        return (value == null) ? null : value.intValue();\n    }\n\n    /**\n     * Gets this value as a Long if it is one, otherwise throws exception.\n     *\n     * @return a Long.\n     * @throws java.lang.ClassCastException if this value is not of the expected type.\n     */\n    public Long asLong() {\n        Number value = operator.getValue(Number.class);\n        return (value == null) ? null : value.longValue();\n    }\n\n    /**\n     * Gets this value as a Boolean if it is one, otherwise throws exception.\n     *\n     * @return a Boolean.\n     * @throws java.lang.ClassCastException if this value is not of the expected type.\n     */\n    public Boolean asBoolean() {\n        return operator.getValue(Boolean.class);\n    }\n\n    /**\n     * Gets this value as a Float if it is one, otherwise throws exception.\n     *\n     * @return a Float.\n     * @throws java.lang.ClassCastException if this value is not of the expected type.\n     */\n    public Float asFloat() {\n        return operator.getValue(Float.class);\n    }\n\n    /**\n     * Gets this value as a Double if it is one, otherwise throws exception.\n     *\n     * @return a Double.\n     * @throws java.lang.ClassCastException if this value is not of the expected type.\n     */\n    public Double asDouble() {\n        return operator.getValue(Double.class);\n    }\n\n    /**\n     * Gets this value as a String if it is one, otherwise throws exception.\n     *\n     * @return a String.\n     * @throws java.lang.ClassCastException if this value is not of the expected type.\n     */\n    public String asString() {\n        return operator.getValue(String.class);\n    }\n\n    /**\n     * Gets this value as a byte[] if it is one, otherwise throws exception.\n     *\n     * @return a byte[].\n     * @throws java.lang.ClassCastException if this value is not of the expected type.\n     */\n    public byte[] asBinary() {\n        return operator.getValue(byte[].class);\n    }\n\n    /**\n     * Gets this value as a Date if it is one, otherwise throws exception.\n     *\n     * @return a Date.\n     * @throws java.lang.ClassCastException if this value is not of the expected type.\n     */\n    public Date asDate() {\n        return operator.getValue(Date.class);\n    }\n\n    /**\n     * Gets this value as a ObjectId if it is one, otherwise throws exception.\n     *\n     * @return an ObjectId.\n     * @throws java.lang.ClassCastException if this value is not of the expected type.\n     */\n    public ObjectId asObjectId() {\n        return operator.getValue(ObjectId.class);\n    }\n\n    /**\n     * Gets this value as a UUID if it is one, otherwise throws exception.\n     *\n     * @return an UUID.\n     * @throws java.lang.ClassCastException if this value is not of the expected type.\n     */\n    public UUID asUUID() {\n        return operator.getValue(UUID.class);\n    }\n\n    /**\n     * Gets this value as a Decimal128 if it is one, otherwise throws exception.\n     *\n     * @return a Decimal128.\n     * @throws java.lang.ClassCastException if this value is not of the expected type.\n     */\n    public Decimal128 asDecimal128() {\n        return operator.getValue(Decimal128.class);\n    }\n\n    /**\n     * Gets this value as a RealmModel if it is one, otherwise throws exception.\n     *\n     * @param <T> the RealmModel type to cast the inner value to.\n     * @return a RealmModel of the T type.\n     * @throws java.lang.ClassCastException if this value is not of the expected type.\n     */\n    public <T extends RealmModel> T asRealmModel(Class<T> clazz) {\n        return operator.getValue(clazz);\n    }\n\n    /**\n     * Creates a new RealmAny out of an Object.\n     *\n     * @param value initial value.\n     * @return a new RealmAny wrapping the object.\n     */\n    static RealmAny valueOf(@Nullable Object value) {\n        if (value == null) {\n            return RealmAny.nullValue();\n        } else if (value instanceof Boolean) {\n            return RealmAny.valueOf((Boolean) value);\n        } else if (value instanceof Byte) {\n            return RealmAny.valueOf((Byte) value);\n        } else if (value instanceof Short) {\n            return RealmAny.valueOf((Short) value);\n        } else if (value instanceof Integer) {\n            return RealmAny.valueOf((Integer) value);\n        } else if (value instanceof Long) {\n            return RealmAny.valueOf((Long) value);\n        } else if (value instanceof Float) {\n            return RealmAny.valueOf((Float) value);\n        } else if (value instanceof Double) {\n            return RealmAny.valueOf((Double) value);\n        } else if (value instanceof Decimal128) {\n            return RealmAny.valueOf((Decimal128) value);\n        } else if (value instanceof String) {\n            return RealmAny.valueOf((String) value);\n        } else if (value instanceof byte[]) {\n            return RealmAny.valueOf((byte[]) value);\n        } else if (value instanceof Date) {\n            return RealmAny.valueOf((Date) value);\n        } else if (value instanceof ObjectId) {\n            return RealmAny.valueOf((ObjectId) value);\n        } else if (value instanceof UUID) {\n            return RealmAny.valueOf((UUID) value);\n        } else if (value instanceof RealmAny) {\n            return (RealmAny) value;\n        } else if (RealmModel.class.isAssignableFrom(value.getClass())) {\n            RealmModel model = (RealmModel) value;\n\n            if (!RealmObject.isValid(model) || !RealmObject.isManaged(model)) {\n                throw new IllegalArgumentException(\"RealmObject is not a valid managed object.\");\n            }\n\n            return RealmAny.valueOf((RealmModel) model);\n        } else {\n            throw new IllegalArgumentException(\"Type not supported on RealmAny: \" + value.getClass().getSimpleName());\n        }\n    }\n\n    /**\n     * A {@code RealmAny}'s hash code is, exactly, the hash code of its value.\n     *\n     * @return true if the target has the same value\n     * @throws NullPointerException if the inner value is null\n     */\n    @Override\n    public final int hashCode() {\n        return this.operator.hashCode();\n    }\n\n    /**\n     * Two {@code RealmAny}s are {@code .equals} if and only if their contents are equal.\n     *\n     * @param other compare target\n     * @return true if the target has the same value\n     */\n    @Override\n    @SuppressFBWarnings(\"NP_METHOD_PARAMETER_TIGHTENS_ANNOTATION\")\n    public final boolean equals(@Nullable Object other) {\n        if (other == this) { return true; }\n        if (!(other instanceof RealmAny)) { return false; }\n        RealmAny otherRealmAny = ((RealmAny) other);\n        return this.operator.equals(otherRealmAny.operator);\n    }\n\n    public final boolean coercedEquals(@Nullable RealmAny other) {\n        if (other == null) { return false; }\n        return this.operator.coercedEquals(other.operator);\n    }\n\n    @Override\n    public String toString() {\n        return this.operator.toString();\n    }\n\n    void checkValidObject(BaseRealm realm) {\n        operator.checkValidObject(realm);\n    }\n\n    /**\n     * Enum describing all the types supported by RealmAny.\n     */\n    public enum Type {\n        INTEGER(RealmFieldType.INTEGER, Long.class),\n        BOOLEAN(RealmFieldType.BOOLEAN, Boolean.class),\n        STRING(RealmFieldType.STRING, String.class),\n        BINARY(RealmFieldType.BINARY, Byte[].class),\n        DATE(RealmFieldType.DATE, Date.class),\n        FLOAT(RealmFieldType.FLOAT, Float.class),\n        DOUBLE(RealmFieldType.DOUBLE, Double.class),\n        DECIMAL128(RealmFieldType.DECIMAL128, Decimal128.class),\n        OBJECT_ID(RealmFieldType.OBJECT_ID, ObjectId.class),\n        OBJECT(RealmFieldType.TYPED_LINK, RealmModel.class),\n        UUID(RealmFieldType.UUID, java.util.UUID.class),\n        NULL(null, null);\n\n        private static final Type[] realmFieldToRealmAnyTypeMap = new Type[MAX_CORE_TYPE_VALUE + 2];\n\n        static {\n            for (Type realmAnyType : values()) {\n                if (realmAnyType == NULL) { continue; }\n\n                final int nativeValue = realmAnyType.realmFieldType.getNativeValue();\n                realmFieldToRealmAnyTypeMap[nativeValue] = realmAnyType;\n            }\n            // TODO: only used for testing purposes, see https://github.com/realm/realm-java/issues/7385\n            // Links Object field type to RealmAny object.\n            realmFieldToRealmAnyTypeMap[RealmFieldType.OBJECT.getNativeValue()] = OBJECT;\n        }\n\n        public static Type fromNativeValue(int realmFieldType) {\n            if (realmFieldType == -1) { return NULL; }\n\n            return realmFieldToRealmAnyTypeMap[realmFieldType];\n        }\n\n        private final Class<?> clazz;\n        private final RealmFieldType realmFieldType;\n\n        Type(@Nullable RealmFieldType realmFieldType, @Nullable Class<?> clazz) {\n            this.realmFieldType = realmFieldType;\n            this.clazz = clazz;\n        }\n\n        public Class<?> getTypedClass() {\n            return clazz;\n        }\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/RealmAnyNativeFunctionsImpl.java",
    "content": "/*\n * Copyright 2021 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 */\npackage io.realm;\n\nimport java.util.Map;\nimport javax.annotation.Nullable;\n\nimport io.realm.internal.RealmAnyNativeFunctions;\nimport io.realm.internal.TableQuery;\nimport io.realm.internal.objectstore.OsKeyPathMapping;\nimport io.realm.internal.objectstore.OsObjectBuilder;\n\n\npublic class RealmAnyNativeFunctionsImpl implements RealmAnyNativeFunctions {\n\n    @Override\n    public void handleItem(long listPtr, RealmAny realmAny) {\n        OsObjectBuilder.nativeAddRealmAnyListItem(listPtr, realmAny.getNativePtr());\n    }\n\n    @Override\n    public void handleItem(long containerPtr, Map.Entry<String, RealmAny> entry) {\n        OsObjectBuilder.nativeAddRealmAnyDictionaryEntry(containerPtr, entry.getKey(), entry.getValue().getNativePtr());\n    }\n\n    @Override\n    public void callRawPredicate(TableQuery query, @Nullable OsKeyPathMapping mapping, String predicate, RealmAny... arguments) {\n        long[] args = new long[arguments.length];\n\n        try {\n            for (int i = 0; i < arguments.length; i++) {\n                args[i] = arguments[i].getNativePtr();\n            }\n        } catch (IllegalStateException cause) {\n            // This might happen if a query is constructed with a RealmAny value containing an unmanaged Realm object.\n            throw new IllegalArgumentException(\"Unmanaged Realm objects are not valid query arguments\", cause);\n        }\n\n        query.rawPredicateWithPointers(mapping, predicate, args);\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/RealmAnyOperator.java",
    "content": "/*\n * Copyright 2020 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\npackage io.realm;\n\nimport org.bson.types.Decimal128;\nimport org.bson.types.ObjectId;\n\nimport java.util.Arrays;\nimport java.util.Collections;\nimport java.util.Date;\nimport java.util.UUID;\n\nimport javax.annotation.Nonnull;\nimport javax.annotation.Nullable;\n\nimport io.realm.exceptions.RealmException;\nimport io.realm.internal.OsSharedRealm;\nimport io.realm.internal.RealmObjectProxy;\nimport io.realm.internal.Table;\nimport io.realm.internal.core.NativeRealmAny;\n\n\npublic abstract class RealmAnyOperator {\n    static RealmAnyOperator fromNativeRealmAny(BaseRealm realm, NativeRealmAny nativeRealmAny) {\n        RealmAny.Type fieldType = nativeRealmAny.getType();\n\n        switch (fieldType) {\n            case INTEGER:\n                return new IntegerRealmAnyOperator(nativeRealmAny);\n            case BOOLEAN:\n                return new BooleanRealmAnyOperator(nativeRealmAny);\n            case STRING:\n                return new StringRealmAnyOperator(nativeRealmAny);\n            case BINARY:\n                return new BinaryRealmAnyOperator(nativeRealmAny);\n            case DATE:\n                return new DateRealmAnyOperator(nativeRealmAny);\n            case FLOAT:\n                return new FloatRealmAnyOperator(nativeRealmAny);\n            case DOUBLE:\n                return new DoubleRealmAnyOperator(nativeRealmAny);\n            case DECIMAL128:\n                return new Decimal128RealmAnyOperator(nativeRealmAny);\n            case OBJECT_ID:\n                return new ObjectIdRealmAnyOperator(nativeRealmAny);\n            case UUID:\n                return new UUIDRealmAnyOperator(nativeRealmAny);\n            case OBJECT:\n                if (realm instanceof Realm) {\n                    try {\n                        Class<RealmModel> clazz = nativeRealmAny.getModelClass(realm.sharedRealm, realm.configuration.getSchemaMediator());\n                        return new RealmModelOperator(realm, nativeRealmAny, clazz);\n                    } catch (RealmException ignore) {\n                        // Fall through to DynamicRealmModelOperator\n                    }\n                }\n                return new DynamicRealmModelRealmAnyOperator(realm, nativeRealmAny);\n            case NULL:\n                return new NullRealmAnyOperator(nativeRealmAny);\n            default:\n                throw new ClassCastException(\"Couldn't cast to \" + fieldType);\n        }\n    }\n\n    @Nullable\n    private NativeRealmAny nativeRealmAny;\n    private RealmAny.Type type;\n\n    private synchronized NativeRealmAny getNativeRealmAny() {\n        if (nativeRealmAny == null) { nativeRealmAny = createNativeRealmAny(); }\n\n        return nativeRealmAny;\n    }\n\n    long getNativePtr() {\n        return getNativeRealmAny().getNativePtr();\n    }\n\n    protected abstract NativeRealmAny createNativeRealmAny();\n\n    protected RealmAnyOperator(RealmAny.Type type) {\n        this.type = type;\n    }\n\n    protected RealmAnyOperator(RealmAny.Type type, NativeRealmAny nativeRealmAny) {\n        this.type = type;\n        this.nativeRealmAny = nativeRealmAny;\n    }\n\n    abstract <T> T getValue(Class<T> clazz);\n\n    RealmAny.Type getType(){\n        return this.type;\n    }\n\n    Class<?> getTypedClass() {\n        return type.getTypedClass();\n    }\n\n    boolean coercedEquals(RealmAnyOperator realmAnyOperator) {\n        return getNativeRealmAny().coercedEquals(realmAnyOperator.getNativeRealmAny());\n    }\n\n    public void checkValidObject(BaseRealm realm) { }\n}\n\nfinal class NullRealmAnyOperator extends RealmAnyOperator {\n    NullRealmAnyOperator() {\n        super(RealmAny.Type.NULL);\n    }\n\n    NullRealmAnyOperator(NativeRealmAny nativeRealmAny) {\n        super(RealmAny.Type.NULL, nativeRealmAny);\n    }\n\n    @Override\n    protected NativeRealmAny createNativeRealmAny() {\n        return new NativeRealmAny();\n    }\n\n    @Override\n    public <T> T getValue(Class<T> clazz) {\n        return null;\n    }\n\n    @Override\n    public String toString() {\n        return \"null\";\n    }\n\n    @Override\n    public int hashCode() {\n        return super.hashCode();\n    }\n\n    @Override\n    public boolean equals(Object other) {\n        return (other != null) && getClass().equals(other.getClass());\n    }\n}\n\nabstract class PrimitiveRealmAnyOperator extends RealmAnyOperator {\n    @Nullable\n    private final Object value;\n\n    PrimitiveRealmAnyOperator(@Nullable Object value, @Nonnull RealmAny.Type type) {\n        super(type);\n        this.value = value;\n    }\n\n    PrimitiveRealmAnyOperator(@Nullable Object value, @Nonnull RealmAny.Type type, @Nonnull NativeRealmAny nativeRealmAny) {\n        super(type, nativeRealmAny);\n        this.value = value;\n    }\n\n    @Override\n    <T> T getValue(Class<T> clazz) {\n        return clazz.cast(value);\n    }\n\n    @Override\n    public final int hashCode() {\n        return (this.value == null) ? 0 : this.value.hashCode();\n    }\n\n    @Override\n    public boolean equals(Object other) {\n        if ((other == null) || !getClass().equals(other.getClass())) { return false; }\n\n        PrimitiveRealmAnyOperator otherOperator = (PrimitiveRealmAnyOperator) other;\n        return (this.value == null) ? (otherOperator.value == null) : this.value.equals(otherOperator.value);\n    }\n\n    @Override\n    public String toString() {\n        return this.value.toString();\n    }\n}\n\nfinal class BooleanRealmAnyOperator extends PrimitiveRealmAnyOperator {\n    BooleanRealmAnyOperator(Boolean value) {\n        super(value, RealmAny.Type.BOOLEAN);\n    }\n\n    BooleanRealmAnyOperator(NativeRealmAny nativeRealmAny) {\n        super(nativeRealmAny.asBoolean(), RealmAny.Type.BOOLEAN, nativeRealmAny);\n    }\n\n    @Override\n    protected NativeRealmAny createNativeRealmAny() {\n        return new NativeRealmAny(super.getValue(Boolean.class));\n    }\n}\n\nfinal class IntegerRealmAnyOperator extends PrimitiveRealmAnyOperator {\n    IntegerRealmAnyOperator(Byte value) {\n        super(value, RealmAny.Type.INTEGER);\n    }\n\n    IntegerRealmAnyOperator(Short value) {\n        super(value, RealmAny.Type.INTEGER);\n    }\n\n    IntegerRealmAnyOperator(Integer value) {\n        super(value, RealmAny.Type.INTEGER);\n    }\n\n    IntegerRealmAnyOperator(Long value) {\n        super(value, RealmAny.Type.INTEGER);\n    }\n\n    IntegerRealmAnyOperator(NativeRealmAny nativeRealmAny) {\n        super(nativeRealmAny.asLong(), RealmAny.Type.INTEGER, nativeRealmAny);\n    }\n\n    @Override\n    protected NativeRealmAny createNativeRealmAny() {\n        return new NativeRealmAny(super.getValue(Number.class));\n    }\n\n    @Override\n    public boolean equals(Object other) {\n        if ((other == null) || !getClass().equals(other.getClass())) { return false; }\n\n        RealmAnyOperator otherOperator = (RealmAnyOperator) other;\n        return this.getValue(Number.class).longValue() == otherOperator.getValue(Number.class).longValue();\n    }\n}\n\nfinal class FloatRealmAnyOperator extends PrimitiveRealmAnyOperator {\n    FloatRealmAnyOperator(Float value) {\n        super(value, RealmAny.Type.FLOAT);\n    }\n\n    FloatRealmAnyOperator(NativeRealmAny nativeRealmAny) {\n        super(nativeRealmAny.asFloat(), RealmAny.Type.FLOAT, nativeRealmAny);\n    }\n\n    @Override\n    protected NativeRealmAny createNativeRealmAny() {\n        return new NativeRealmAny(super.getValue(Float.class));\n    }\n}\n\nfinal class DoubleRealmAnyOperator extends PrimitiveRealmAnyOperator {\n    DoubleRealmAnyOperator(Double value) {\n        super(value, RealmAny.Type.DOUBLE);\n    }\n\n    DoubleRealmAnyOperator(NativeRealmAny nativeRealmAny) {\n        super(nativeRealmAny.asDouble(), RealmAny.Type.DOUBLE, nativeRealmAny);\n    }\n\n    @Override\n    protected NativeRealmAny createNativeRealmAny() {\n        return new NativeRealmAny(super.getValue(Double.class));\n    }\n}\n\nfinal class StringRealmAnyOperator extends PrimitiveRealmAnyOperator {\n    StringRealmAnyOperator(String value) {\n        super(value, RealmAny.Type.STRING);\n    }\n\n    StringRealmAnyOperator(NativeRealmAny nativeRealmAny) {\n        super(nativeRealmAny.asString(), RealmAny.Type.STRING, nativeRealmAny);\n    }\n\n    @Override\n    protected NativeRealmAny createNativeRealmAny() {\n        return new NativeRealmAny(super.getValue(String.class));\n    }\n}\n\nfinal class BinaryRealmAnyOperator extends PrimitiveRealmAnyOperator {\n    BinaryRealmAnyOperator(byte[] value) {\n        super(value, RealmAny.Type.BINARY);\n    }\n\n    BinaryRealmAnyOperator(NativeRealmAny nativeRealmAny) {\n        super(nativeRealmAny.asBinary(), RealmAny.Type.BINARY, nativeRealmAny);\n    }\n\n    @Override\n    protected NativeRealmAny createNativeRealmAny() {\n        return new NativeRealmAny(super.getValue(byte[].class));\n    }\n\n    @Override\n    public boolean equals(Object other) {\n        if ((other == null) || !getClass().equals(other.getClass())) { return false; }\n\n        RealmAnyOperator otherOperator = (RealmAnyOperator) other;\n        return Arrays.equals(this.getValue(byte[].class), otherOperator.getValue(byte[].class));\n    }\n}\n\nfinal class DateRealmAnyOperator extends PrimitiveRealmAnyOperator {\n    DateRealmAnyOperator(Date value) {\n        super(value, RealmAny.Type.DATE);\n    }\n\n    DateRealmAnyOperator(NativeRealmAny nativeRealmAny) {\n        super(nativeRealmAny.asDate(), RealmAny.Type.DATE, nativeRealmAny);\n    }\n\n    @Override\n    protected NativeRealmAny createNativeRealmAny() {\n        return new NativeRealmAny(super.getValue(Date.class));\n    }\n}\n\nfinal class ObjectIdRealmAnyOperator extends PrimitiveRealmAnyOperator {\n    ObjectIdRealmAnyOperator(ObjectId value) {\n        super(value, RealmAny.Type.OBJECT_ID);\n    }\n\n    ObjectIdRealmAnyOperator(NativeRealmAny nativeRealmAny) {\n        super(nativeRealmAny.asObjectId(), RealmAny.Type.OBJECT_ID, nativeRealmAny);\n    }\n\n    @Override\n    protected NativeRealmAny createNativeRealmAny() {\n        return new NativeRealmAny(super.getValue(ObjectId.class));\n    }\n}\n\nfinal class Decimal128RealmAnyOperator extends PrimitiveRealmAnyOperator {\n    Decimal128RealmAnyOperator(Decimal128 value) {\n        super(value, RealmAny.Type.DECIMAL128);\n    }\n\n    Decimal128RealmAnyOperator(NativeRealmAny nativeRealmAny) {\n        super(nativeRealmAny.asDecimal128(), RealmAny.Type.DECIMAL128, nativeRealmAny);\n    }\n\n    @Override\n    protected NativeRealmAny createNativeRealmAny() {\n        return new NativeRealmAny(super.getValue(Decimal128.class));\n    }\n}\n\nfinal class UUIDRealmAnyOperator extends PrimitiveRealmAnyOperator {\n    UUIDRealmAnyOperator(UUID value) {\n        super(value, RealmAny.Type.UUID);\n    }\n\n    UUIDRealmAnyOperator(NativeRealmAny nativeRealmAny) {\n        super(nativeRealmAny.asUUID(), RealmAny.Type.UUID, nativeRealmAny);\n    }\n\n    @Override\n    protected NativeRealmAny createNativeRealmAny() {\n        return new NativeRealmAny(super.getValue(UUID.class));\n    }\n}\n\nclass RealmModelOperator extends RealmAnyOperator {\n    private static <T extends RealmModel> T getRealmModel(BaseRealm realm, Class<T> clazz, NativeRealmAny nativeRealmAny) {\n        return realm\n                .get(clazz, nativeRealmAny.getRealmModelRowKey(), false, Collections.emptyList());\n    }\n\n    private final Class<? extends RealmModel> clazz;\n    private final RealmModel value;\n\n    RealmModelOperator(RealmModel realmModel) {\n        super(RealmAny.Type.OBJECT);\n        this.value = realmModel;\n        this.clazz = realmModel.getClass();\n    }\n\n    <T extends RealmModel> RealmModelOperator(BaseRealm realm, NativeRealmAny nativeRealmAny, Class<T> clazz) {\n        super(RealmAny.Type.OBJECT, nativeRealmAny);\n\n        this.clazz = clazz;\n        this.value = getRealmModel(realm, clazz, nativeRealmAny);\n    }\n\n    @Override\n    protected NativeRealmAny createNativeRealmAny() {\n        if (!(value instanceof RealmObjectProxy)) {\n            throw new IllegalStateException(\"Native RealmAny instances only allow managed Realm objects or primitives\");\n        }\n        return new NativeRealmAny(getValue(RealmObjectProxy.class));\n    }\n\n    @Override\n    <T> T getValue(Class<T> clazz) {\n        return clazz.cast(value);\n    }\n\n    @Override\n    Class<?> getTypedClass() {\n        return RealmObjectProxy.class.isAssignableFrom(clazz) ? clazz.getSuperclass() : clazz;\n    }\n\n    @Override\n    public int hashCode() {\n        return this.value.hashCode();\n    }\n\n    @Override\n    public boolean equals(Object other) {\n        if ((other == null) || !getClass().equals(other.getClass())) { return false; }\n\n        RealmModelOperator otherOperator = (RealmModelOperator) other;\n        return (this.value == null) ? (otherOperator.value == null) : this.value.equals(otherOperator.value);\n    }\n\n    @Override\n    public String toString() {\n        return this.value.toString();\n    }\n\n    @Override\n    public void checkValidObject(BaseRealm realm) {\n        if (!RealmObject.isValid(value) || !RealmObject.isManaged(value)) {\n            throw new IllegalArgumentException(\"Realm object is not a valid managed object.\");\n        }\n        if (((RealmObjectProxy) value).realmGet$proxyState().getRealm$realm() != realm) {\n            throw new IllegalArgumentException(\"Realm object belongs to a different Realm.\");\n        }\n    }\n}\n\nfinal class DynamicRealmModelRealmAnyOperator extends RealmModelOperator {\n    @SuppressWarnings({\"unchecked\", \"TypeParameterUnusedInFormals\"})\n    private static <T extends RealmModel> T getRealmModel(BaseRealm realm, NativeRealmAny nativeRealmAny) {\n        OsSharedRealm sharedRealm = realm.getSharedRealm();\n\n        String className = Table.getClassNameForTable(nativeRealmAny.getRealmModelTableName(sharedRealm));\n\n        return realm.get((Class<T>) DynamicRealmObject.class, className, nativeRealmAny.getRealmModelRowKey());\n    }\n\n    DynamicRealmModelRealmAnyOperator(BaseRealm realm, NativeRealmAny nativeRealmAny) {\n        super(getRealmModel(realm, nativeRealmAny));\n    }\n\n    @Override\n    Class<?> getTypedClass() {\n        return DynamicRealmObject.class;\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/RealmAsyncTask.java",
    "content": "/*\n * Copyright 2015 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\npackage io.realm;\n\n/**\n * Represents a pending asynchronous Realm task, like asynchronous transactions.\n * <p>\n * Users are responsible for maintaining a reference to {@code RealmAsyncTask} in order to call {@link #cancel()} in\n * case of a configuration change for example (to avoid memory leak, as the transaction will post the result to the\n * caller's thread callback).\n */\npublic interface RealmAsyncTask {\n\n    /**\n     * Attempts to cancel execution of this transaction (if it hasn't already completed or previously cancelled).\n     */\n    void cancel();\n\n    /**\n     * Checks whether an attempt to cancel the transaction was performed.\n     *\n     * @return {@code true} if {@link #cancel()} has already been called, {@code false} otherwise.\n     */\n    boolean isCancelled();\n}\n\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/RealmCache.java",
    "content": "/*\n * Copyright 2015 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 */\npackage io.realm;\n\nimport java.io.File;\nimport java.io.FileOutputStream;\nimport java.io.IOException;\nimport java.io.InputStream;\nimport java.lang.ref.WeakReference;\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.Collection;\nimport java.util.HashMap;\nimport java.util.HashSet;\nimport java.util.Iterator;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Set;\nimport java.util.concurrent.ConcurrentLinkedQueue;\nimport java.util.concurrent.CountDownLatch;\nimport java.util.concurrent.Future;\nimport java.util.concurrent.TimeUnit;\nimport java.util.concurrent.atomic.AtomicBoolean;\nimport java.util.concurrent.atomic.AtomicInteger;\n\nimport io.realm.exceptions.RealmFileException;\nimport io.realm.internal.Capabilities;\nimport io.realm.internal.ObjectServerFacade;\nimport io.realm.internal.OsObjectStore;\nimport io.realm.internal.OsRealmConfig;\nimport io.realm.internal.OsSharedRealm;\nimport io.realm.internal.RealmNotifier;\nimport io.realm.internal.Util;\nimport io.realm.internal.android.AndroidCapabilities;\nimport io.realm.internal.android.AndroidRealmNotifier;\nimport io.realm.internal.async.RealmAsyncTaskImpl;\nimport io.realm.internal.util.Pair;\nimport io.realm.log.RealmLog;\n\n\n/**\n * To cache {@link Realm}, {@link DynamicRealm} instances and related resources.\n * Every thread will share the same {@link Realm} and {@link DynamicRealm} instances which are referred to the same\n * {@link RealmConfiguration}.\n * One {@link RealmCache} is created for each {@link RealmConfiguration}, and it caches all the {@link Realm} and\n * {@link DynamicRealm} instances which are created from the same {@link RealmConfiguration}.\n */\nfinal class RealmCache {\n\n    interface Callback {\n        void onResult(int count);\n    }\n\n    interface Callback0 {\n        void onCall();\n    }\n\n    private abstract static class ReferenceCounter {\n\n        // How many references to this Realm instance in this thread.\n        protected final ThreadLocal<Integer> localCount = new ThreadLocal<>();\n        // How many threads have instances refer to this configuration.\n        protected AtomicInteger globalCount = new AtomicInteger(0);\n\n        // Returns `true` if an instance of the Realm is available on the caller thread.\n        abstract boolean hasInstanceAvailableForThread();\n\n        // Increment how many times an instance has been handed out for the current thread.\n        public void incrementThreadCount(int increment) {\n            Integer currentCount = localCount.get();\n            localCount.set(currentCount != null ? currentCount + increment : increment);\n        }\n\n        // Returns the Realm instance for the caller thread\n        abstract BaseRealm getRealmInstance();\n\n        // Cache the Realm instance. Should only be called when `hasInstanceAvailableForThread` returns false.\n        abstract void onRealmCreated(BaseRealm realm);\n\n        // Clears the the cache for a given thread when all Realms on that thread are closed.\n        abstract void clearThreadLocalCache();\n\n        // Returns the number of instances handed out for the caller thread.\n        abstract int getThreadLocalCount();\n\n        // Updates the number of references handed out for a given thread\n        public void setThreadCount(int refCount) {\n            localCount.set(refCount);\n        }\n\n        // Returns the number of gloal instances handed out. This is roughly equivalent\n        // to the number of threads currently using the Realm as each thread also does\n        // reference counting of Realm instances.\n        public int getGlobalCount() {\n            return globalCount.get();\n        }\n    }\n\n    // Reference counter for Realms that are accessible across all threads\n    private static class GlobalReferenceCounter extends ReferenceCounter {\n        private BaseRealm cachedRealm;\n\n        @Override\n        boolean hasInstanceAvailableForThread() {\n            return cachedRealm != null;\n        }\n\n        @Override\n        BaseRealm getRealmInstance() {\n            return cachedRealm;\n        }\n\n        @Override\n        void onRealmCreated(BaseRealm realm) {\n            // The Realm instance has been created without exceptions. Cache and reference count can be updated now.\n            cachedRealm = realm;\n\n            localCount.set(0);\n            // This is the first instance in current thread, increase the global count.\n            globalCount.incrementAndGet();\n\n        }\n\n        @Override\n        public void clearThreadLocalCache() {\n            String canonicalPath = cachedRealm.getPath();\n\n            // The last instance in this thread.\n            // Clears local ref & counter.\n            localCount.set(null);\n            cachedRealm = null;\n\n            // Clears global counter.\n            if (globalCount.decrementAndGet() < 0) {\n                // Should never happen.\n                throw new IllegalStateException(\"Global reference counter of Realm\" + canonicalPath + \" not be negative.\");\n            }\n        }\n\n        @Override\n        int getThreadLocalCount() {\n            // For frozen Realms the Realm can be accessed from all threads, so the concept\n            // of a thread local count doesn't make sense. Just return the global count instead.\n            return globalCount.get();\n        }\n    }\n\n    // Reference counter for Realms that are thread confined\n    private static class ThreadConfinedReferenceCounter extends ReferenceCounter {\n        // The Realm instance in this thread.\n        private final ThreadLocal<BaseRealm> localRealm = new ThreadLocal<>();\n\n        @Override\n        public boolean hasInstanceAvailableForThread() {\n            return localRealm.get() != null;\n        }\n\n        @Override\n        public BaseRealm getRealmInstance() {\n            return localRealm.get();\n        }\n\n        @Override\n        public void onRealmCreated(BaseRealm realm) {\n            // The Realm instance has been created without exceptions. Cache and reference count can be updated now.\n            localRealm.set(realm);\n            localCount.set(0);\n            // This is the first instance in current thread, increase the global count.\n            globalCount.incrementAndGet();\n        }\n\n        @Override\n        public void clearThreadLocalCache() {\n            String canonicalPath = localRealm.get().getPath();\n\n            // The last instance in this thread.\n            // Clears local ref & counter.\n            localCount.set(null);\n            localRealm.set(null);\n\n            // Clears global counter.\n            if (globalCount.decrementAndGet() < 0) {\n                // Should never happen.\n                throw new IllegalStateException(\"Global reference counter of Realm\" + canonicalPath + \" can not be negative.\");\n            }\n        }\n\n        @Override\n        public int getThreadLocalCount() {\n            Integer refCount = localCount.get();\n            return (refCount != null) ? refCount : 0;\n        }\n    }\n\n    private enum RealmCacheType {\n        TYPED_REALM,\n        DYNAMIC_REALM;\n\n        static RealmCacheType valueOf(Class<? extends BaseRealm> clazz) {\n            if (clazz == Realm.class) {\n                return TYPED_REALM;\n            } else if (clazz == DynamicRealm.class) {\n                return DYNAMIC_REALM;\n            }\n\n            throw new IllegalArgumentException(WRONG_REALM_CLASS_MESSAGE);\n        }\n    }\n\n    private static class CreateRealmRunnable<T extends BaseRealm> implements Runnable {\n        private final RealmConfiguration configuration;\n        private final BaseRealm.InstanceCallback<T> callback;\n        private final Class<T> realmClass;\n        private final CountDownLatch canReleaseBackgroundInstanceLatch = new CountDownLatch(1);\n        private final RealmNotifier notifier;\n        // The Future this runnable belongs to.\n        private Future future;\n\n        CreateRealmRunnable(RealmNotifier notifier, RealmConfiguration configuration,\n                BaseRealm.InstanceCallback<T> callback, Class<T> realmClass) {\n            this.configuration = configuration;\n            this.realmClass = realmClass;\n            this.callback = callback;\n            this.notifier = notifier;\n        }\n\n        public void setFuture(Future future) {\n            this.future = future;\n        }\n\n        @Override\n        public void run() {\n            T instance = null;\n            try {\n                // First call that will run all schema validation, migrations or initial transactions.\n                instance = createRealmOrGetFromCache(configuration, realmClass);\n                boolean results = notifier.post(new Runnable() {\n                    @Override\n                    public void run() {\n                        // If the RealmAsyncTask.cancel() is called before, we just return without creating the Realm\n                        // instance on the caller thread.\n                        // Thread.isInterrupted() cannot be used for checking here since CountDownLatch.await() will\n                        // will clear interrupted status.\n                        // Using the future to check which this runnable belongs to is to ensure if it is canceled from\n                        // the caller thread before, the callback will never be delivered.\n                        if (future == null || future.isCancelled()) {\n                            canReleaseBackgroundInstanceLatch.countDown();\n                            return;\n                        }\n                        T instanceToReturn = null;\n                        Throwable throwable = null;\n                        try {\n                            // This will run on the caller thread, but since the first `createRealmOrGetFromCache`\n                            // should have completed at this point, all expensive initializer functions have already\n                            // run.\n                            instanceToReturn = createRealmOrGetFromCache(configuration, realmClass);\n                        } catch (Throwable e) {\n                            throwable = e;\n                        } finally {\n                            canReleaseBackgroundInstanceLatch.countDown();\n                        }\n                        if (instanceToReturn != null) {\n                            callback.onSuccess(instanceToReturn);\n                        } else {\n                            // throwable is non-null\n                            //noinspection ConstantConditions\n                            callback.onError(throwable);\n                        }\n                    }\n                });\n                if (!results) {\n                    canReleaseBackgroundInstanceLatch.countDown();\n                }\n                // There is a small chance that the posted runnable cannot be executed because of the thread terminated\n                // before the runnable gets fetched from the event queue.\n                if (!canReleaseBackgroundInstanceLatch.await(2, TimeUnit.SECONDS)) {\n                    RealmLog.warn(\"Timeout for creating Realm instance in foreground thread in `CreateRealmRunnable` \");\n                }\n            } catch (InterruptedException e) {\n                RealmLog.warn(e, \"`CreateRealmRunnable` has been interrupted.\");\n            } catch (final Throwable e) {\n                // DownloadingRealmInterruptedException is treated specially.\n                // It async open is canceled, this could interrupt the download, but the user should\n                // not care in this case, so just ignore it.\n                if (!ObjectServerFacade.getSyncFacadeIfPossible().wasDownloadInterrupted(e)) {\n                    RealmLog.error(e, \"`CreateRealmRunnable` failed.\");\n                    notifier.post(new Runnable() {\n                        @Override\n                        public void run() {\n                            callback.onError(e);\n                        }\n                    });\n                }\n            } finally {\n                if (instance != null) {\n                    instance.close();\n                }\n            }\n        }\n    }\n\n    private static final String ASYNC_NOT_ALLOWED_MSG =\n            \"Realm instances cannot be loaded asynchronously on a non-looper thread.\";\n    private static final String ASYNC_CALLBACK_NULL_MSG =\n            \"The callback cannot be null.\";\n\n    // Separated references and counters for typed Realm and dynamic Realm.\n    private final Map<Pair<RealmCacheType, OsSharedRealm.VersionID>, ReferenceCounter> refAndCountMap = new HashMap<>();\n\n    // Path to the Realm file to identify this cache.\n    private final String realmPath;\n\n    // This will be only valid if getTotalGlobalRefCount() > 0.\n    // NOTE: We do reset this when globalCount reaches 0, but if exception thrown in doCreateRealmOrGetFromCache at the\n    // first time when globalCount == 0, this could have a non-null value but it will be reset when the next\n    // doCreateRealmOrGetFromCache is called with globalCount == 0.\n    private RealmConfiguration configuration;\n\n    // Realm path will be used to identify different RealmCaches. Different Realm configurations with same path\n    // are not allowed and an exception will be thrown when trying to add it to the cache list.\n    // A weak ref is used to hold the RealmCache instance. The weak ref entry will be cleared if and only if there\n    // is no Realm instance holding a strong ref to it and there is no Realm instance associated it is BEING created.\n    private static final List<WeakReference<RealmCache>> cachesList = new ArrayList<WeakReference<RealmCache>>();\n\n    // See leak()\n    // isLeaked flag is used to avoid adding strong ref multiple times without iterating the list.\n    private final AtomicBoolean isLeaked = new AtomicBoolean(false);\n    // Keep strong ref to the leaked RealmCache\n    @SuppressWarnings(\"MismatchedQueryAndUpdateOfCollection\")\n    private static final Collection<RealmCache> leakedCaches = new ConcurrentLinkedQueue<RealmCache>();\n\n    // Keeps track if a Realm needs to download its initial remote data\n    private final Set<String> pendingRealmFileCreation = new HashSet<>();\n\n    private static final String DIFFERENT_KEY_MESSAGE = \"Wrong key used to decrypt Realm.\";\n    private static final String WRONG_REALM_CLASS_MESSAGE = \"The type of Realm class must be Realm or DynamicRealm.\";\n\n    private RealmCache(String path) {\n        realmPath = path;\n    }\n\n    private static RealmCache getCache(String realmPath, boolean createIfNotExist) {\n        RealmCache cacheToReturn = null;\n        synchronized (cachesList) {\n            Iterator<WeakReference<RealmCache>> it = cachesList.iterator();\n\n            while (it.hasNext()) {\n                RealmCache cache = it.next().get();\n                if (cache == null) {\n                    // Clear the entry if there is no one holding the RealmCache.\n                    it.remove();\n                } else if (cache.realmPath.equals(realmPath)) {\n                    cacheToReturn = cache;\n                }\n            }\n\n            if (cacheToReturn == null && createIfNotExist) {\n                cacheToReturn = new RealmCache(realmPath);\n                cachesList.add(new WeakReference<RealmCache>(cacheToReturn));\n            }\n        }\n        return cacheToReturn;\n    }\n\n    static <T extends BaseRealm> RealmAsyncTask createRealmOrGetFromCacheAsync(\n            RealmConfiguration configuration, BaseRealm.InstanceCallback<T> callback, Class<T> realmClass) {\n        RealmCache cache = getCache(configuration.getPath(), true);\n        return cache.doCreateRealmOrGetFromCacheAsync(configuration, callback, realmClass);\n    }\n\n    private synchronized <T extends BaseRealm> RealmAsyncTask doCreateRealmOrGetFromCacheAsync(\n            RealmConfiguration configuration, BaseRealm.InstanceCallback<T> callback, Class<T> realmClass) {\n        Capabilities capabilities = new AndroidCapabilities();\n        capabilities.checkCanDeliverNotification(ASYNC_NOT_ALLOWED_MSG);\n        //noinspection ConstantConditions\n        if (callback == null) {\n            throw new IllegalArgumentException(ASYNC_CALLBACK_NULL_MSG);\n        }\n\n        // If there is no Realm file it means that we need to sync the initial remote data in the worker thread.\n        if (configuration.isSyncConfiguration() && !configuration.realmExists()) {\n            pendingRealmFileCreation.add(configuration.getPath());\n        }\n\n        // Always create a Realm instance in the background thread even when there are instances existing on current\n        // thread. This to ensure that onSuccess will always be called in the following event loop but not current one.\n        CreateRealmRunnable<T> createRealmRunnable = new CreateRealmRunnable<T>(\n                new AndroidRealmNotifier(null, capabilities), configuration, callback, realmClass);\n        Future<?> future = BaseRealm.asyncTaskExecutor.submitTransaction(createRealmRunnable);\n        createRealmRunnable.setFuture(future);\n\n        // For Realms using Async Open on the server, we need to create the session right away\n        // in order to interact with it in a imperative way, e.g. by attaching download progress\n        // listeners\n        ObjectServerFacade.getSyncFacadeIfPossible().createNativeSyncSession(configuration);\n\n        return new RealmAsyncTaskImpl(future, BaseRealm.asyncTaskExecutor);\n    }\n\n    /**\n     * Creates a new Realm instance or get an existing instance for current thread.\n     *\n     * @param configuration {@link RealmConfiguration} will be used to create or get the instance.\n     * @param realmClass class of {@link Realm} or {@link DynamicRealm} to be created in or gotten from the cache.\n     * @return the {@link Realm} or {@link DynamicRealm} instance.\n     */\n    static <E extends BaseRealm> E createRealmOrGetFromCache(RealmConfiguration configuration, Class<E> realmClass) {\n        RealmCache cache = getCache(configuration.getPath(), true);\n        return cache.doCreateRealmOrGetFromCache(configuration, realmClass, OsSharedRealm.VersionID.LIVE);\n    }\n\n    static <E extends BaseRealm> E createRealmOrGetFromCache(RealmConfiguration configuration, Class<E> realmClass, OsSharedRealm.VersionID version) {\n        RealmCache cache = getCache(configuration.getPath(), true);\n        return cache.doCreateRealmOrGetFromCache(configuration, realmClass, version);\n    }\n\n    private synchronized <E extends BaseRealm> E doCreateRealmOrGetFromCache(RealmConfiguration configuration, Class<E> realmClass, OsSharedRealm.VersionID version) {\n        ReferenceCounter referenceCounter = getRefCounter(realmClass, version);\n        boolean firstRealmInstanceInProcess = (getTotalGlobalRefCount() == 0);\n\n        if (firstRealmInstanceInProcess) {\n            copyAssetFileIfNeeded(configuration);\n            // If waitForInitialRemoteData() was enabled, we need to make sure that all data is downloaded\n            // before proceeding. We need to open the Realm instance first to start any potential underlying\n            // SyncSession so this will work.\n            boolean realmFileIsBeingCreated = !configuration.realmExists();\n            if (configuration.isSyncConfiguration() && (realmFileIsBeingCreated || pendingRealmFileCreation.contains(configuration.getPath()))) {\n                // Manually create the Java session wrapper session as this might otherwise\n                // not be created\n                OsRealmConfig osConfig = new OsRealmConfig.Builder(configuration).build();\n                ObjectServerFacade.getSyncFacadeIfPossible().wrapObjectStoreSessionIfRequired(osConfig);\n\n                // Fully synchronized Realms are supported by AsyncOpen\n                ObjectServerFacade.getSyncFacadeIfPossible().downloadInitialRemoteChanges(configuration);\n\n                // Initial remote data has been synced at this point\n                pendingRealmFileCreation.remove(configuration.getPath());\n            }\n\n            // We are holding the lock, and we can set the valid configuration since there is no global ref to it.\n            this.configuration = configuration;\n        } else {\n            // Throws exception if validation failed.\n            validateConfiguration(configuration);\n        }\n\n        if (!referenceCounter.hasInstanceAvailableForThread()) {\n            createInstance(realmClass, referenceCounter, version);\n        }\n\n        referenceCounter.incrementThreadCount(1);\n\n        //noinspection unchecked\n        E realmInstance = (E) referenceCounter.getRealmInstance();\n        if (firstRealmInstanceInProcess) {\n            // If flexible sync initial subscriptions are configured, we need to make\n            // sure they are in the COMPLETE state before proceeding\n            // TODO Ideally this would be part of `downloadInitialRemoteChanges` called before\n            //  but his requires a larger refactor, so for now just run the logic here.\n            ObjectServerFacade.getSyncFacadeIfPossible().downloadInitialFlexibleSyncData(\n                    Realm.createInstance(realmInstance.sharedRealm),\n                    configuration\n            );\n            if (!configuration.isReadOnly()) {\n                realmInstance.refresh();\n            }\n        }\n        return realmInstance;\n    }\n\n    private <E extends BaseRealm> ReferenceCounter getRefCounter(Class<E> realmClass, OsSharedRealm.VersionID version) {\n        RealmCacheType cacheType = RealmCacheType.valueOf(realmClass);\n        Pair<RealmCacheType, OsSharedRealm.VersionID> key = new Pair<>(cacheType, version);\n        ReferenceCounter refCounter = refAndCountMap.get(key);\n        if (refCounter == null) {\n            if (version.equals(OsSharedRealm.VersionID.LIVE)) {\n                refCounter = new ThreadConfinedReferenceCounter();\n            } else {\n                refCounter = new GlobalReferenceCounter();\n            }\n\n            refAndCountMap.put(key, refCounter);\n        }\n        return refCounter;\n    }\n\n    private <E extends BaseRealm> void createInstance(Class<E> realmClass,\n                                                      ReferenceCounter referenceCounter,\n                                                      OsSharedRealm.VersionID version) {\n        // Creates a new local Realm instance\n        BaseRealm realm;\n\n        if (realmClass == Realm.class) {\n            // RealmMigrationNeededException might be thrown here.\n            realm = Realm.createInstance(this, version);\n            // Only create mappings after the Realm was opened, so schema mismatch is correctly\n            // thrown by ObjectStore when checking the schema.\n            realm.getSchema().createKeyPathMapping();\n\n        } else if (realmClass == DynamicRealm.class) {\n            realm = DynamicRealm.createInstance(this, version);\n        } else {\n            throw new IllegalArgumentException(WRONG_REALM_CLASS_MESSAGE);\n        }\n\n\n        referenceCounter.onRealmCreated(realm);\n    }\n\n    /**\n     * Releases a given {@link Realm} or {@link DynamicRealm} from cache. The instance will be closed by this method\n     * if there is no more local reference to this Realm instance in current Thread.\n     *\n     * @param realm Realm instance to be released from cache.\n     */\n    synchronized void release(BaseRealm realm) {\n        String canonicalPath = realm.getPath();\n        ReferenceCounter referenceCounter = getRefCounter(realm.getClass(), (realm.isFrozen()) ? realm.sharedRealm.getVersionID() : OsSharedRealm.VersionID.LIVE);\n        int refCount = referenceCounter.getThreadLocalCount();\n\n        if (refCount <= 0) {\n            RealmLog.warn(\"%s has been closed already. refCount is %s\", canonicalPath, refCount);\n            return;\n        }\n\n        // Decreases the local counter.\n        refCount -= 1;\n\n        if (refCount == 0) {\n            referenceCounter.clearThreadLocalCache();\n\n            // No more local reference to this Realm in current thread, close the instance.\n            realm.doClose();\n\n            // No more instance of typed Realm and dynamic Realm.\n            if (getTotalLiveRealmGlobalRefCount() == 0) {\n                // We keep the cache in the caches list even when its global counter reaches 0. It will be reused when\n                // next time a Realm instance with the same path is opened. By not removing it, the lock on\n                // cachesList is not needed here.\n                configuration = null;\n\n                // Close all frozen Realms. This can introduce race conditions on other\n                // threads if the lifecyle of using Realm data is not correctly controlled.\n                for (ReferenceCounter counter : refAndCountMap.values()) {\n                    if (counter instanceof GlobalReferenceCounter) {\n                        BaseRealm cachedRealm = counter.getRealmInstance();\n                        // Since we don't remove ReferenceCounters, we need to check if the Realm is still open\n                        if (cachedRealm != null) {\n                            // Gracefully close frozen Realms in a similar way to what a user would normally do.\n                            while (!cachedRealm.isClosed()) {\n                                cachedRealm.close();\n                            }\n                        }\n                    }\n                }\n                ObjectServerFacade.getFacade(realm.getConfiguration().isSyncConfiguration()).realmClosed(realm.getConfiguration());\n            }\n\n        } else {\n            referenceCounter.setThreadCount(refCount);\n        }\n    }\n\n    /**\n     * Makes sure that the new configuration doesn't clash with any cached configurations for the\n     * Realm.\n     *\n     * @throws IllegalArgumentException if the new configuration isn't valid.\n     */\n    private void validateConfiguration(RealmConfiguration newConfiguration) {\n        if (configuration.equals(newConfiguration)) {\n            // Same configuration objects.\n            return;\n        }\n\n        // Checks that encryption keys aren't different. key is not in RealmConfiguration's toString.\n        if (!Arrays.equals(configuration.getEncryptionKey(), newConfiguration.getEncryptionKey())) {\n            throw new IllegalArgumentException(DIFFERENT_KEY_MESSAGE);\n        } else {\n            // A common problem is that people are forgetting to override `equals` in their custom migration class.\n            // Tries to detect this problem specifically so we can throw a better error message.\n            RealmMigration newMigration = newConfiguration.getMigration();\n            RealmMigration oldMigration = configuration.getMigration();\n            if (oldMigration != null\n                    && newMigration != null\n                    && oldMigration.getClass().equals(newMigration.getClass())\n                    && !newMigration.equals(oldMigration)) {\n                throw new IllegalArgumentException(\"Configurations cannot be different if used to open the same file. \" +\n                        \"The most likely cause is that equals() and hashCode() are not overridden in the \" +\n                        \"migration class: \" + newConfiguration.getMigration().getClass().getCanonicalName());\n            }\n\n            throw new IllegalArgumentException(\"Configurations cannot be different if used to open the same file. \" +\n                    \"\\nCached configuration: \\n\" + configuration +\n                    \"\\n\\nNew configuration: \\n\" + newConfiguration);\n        }\n    }\n\n    /**\n     * Runs the callback function with the total reference count of {@link Realm} and {@link DynamicRealm} who refer to\n     * the given {@link RealmConfiguration}.\n     *\n     * @param configuration the {@link RealmConfiguration} of {@link Realm} or {@link DynamicRealm}.\n     * @param callback the callback will be executed with the global reference count.\n     */\n    static void invokeWithGlobalRefCount(RealmConfiguration configuration, Callback callback) {\n        // NOTE: Although getCache is locked on the cacheMap, this whole method needs to be lock with it as\n        // well. Since we need to ensure there is no Realm instance can be opened when this method is called (for\n        // deleteRealm).\n        // Recursive lock cannot be avoided here.\n        synchronized (cachesList) {\n            RealmCache cache = getCache(configuration.getPath(), false);\n            if (cache == null) {\n                callback.onResult(0);\n                return;\n            }\n            cache.doInvokeWithGlobalRefCount(callback);\n        }\n    }\n\n    private synchronized void doInvokeWithGlobalRefCount(Callback callback) {\n        callback.onResult(getTotalGlobalRefCount());\n    }\n\n    /**\n     * Runs the callback function with synchronization on {@link RealmCache}.\n     *\n     * @param callback the callback will be executed.\n     */\n    synchronized void invokeWithLock(Callback0 callback) {\n        callback.onCall();\n    }\n\n    /**\n     * Copies Realm database file from Android asset directory to the directory given in the {@link RealmConfiguration}.\n     * Copy is performed only at the first time when there is no Realm database file.\n     *\n     * WARNING: This method is not thread-safe so external synchronization is required before using it.\n     *\n     * @param configuration configuration object for Realm instance.\n     * @throws RealmFileException if copying the file fails.\n     */\n    private static void copyAssetFileIfNeeded(final RealmConfiguration configuration) {\n        final File realmFileFromAsset = configuration.hasAssetFile() ?\n                new File(configuration.getRealmDirectory(), configuration.getRealmFileName())\n                : null;\n        String syncServerCertificateFilePath = ObjectServerFacade.getFacade(\n                configuration.isSyncConfiguration()).getSyncServerCertificateFilePath(configuration\n        );\n        final boolean certFileExists = !Util.isEmptyString(syncServerCertificateFilePath);\n        if (realmFileFromAsset!= null || certFileExists) {\n            OsObjectStore.callWithLock(configuration, new Runnable() {\n                @Override\n                public void run() {\n                    if (realmFileFromAsset != null) {\n                        copyFileIfNeeded(configuration.getAssetFilePath(), realmFileFromAsset);\n                    }\n\n                    // Copy Sync Server certificate path if available\n                    if (certFileExists) {\n                        final String syncServerCertificateAssetName = ObjectServerFacade.getFacade(\n                            configuration.isSyncConfiguration()\n                        ).getSyncServerCertificateAssetName(configuration);\n                        File certificateFile = new File(syncServerCertificateFilePath);\n                        copyFileIfNeeded(syncServerCertificateAssetName, certificateFile);\n                    }\n                }\n            });\n        }\n    }\n\n    private static void copyFileIfNeeded(String assetFileName, File file) {\n        if (file.exists()) {\n            return;\n        }\n\n        IOException exceptionWhenClose = null;\n        InputStream inputStream = null;\n        FileOutputStream outputStream = null;\n        try {\n            inputStream = BaseRealm.applicationContext.getAssets().open(assetFileName);\n            if (inputStream == null) {\n                throw new RealmFileException(RealmFileException.Kind.ACCESS_ERROR,\n                        \"Invalid input stream to the asset file: \" + assetFileName);\n            }\n\n            outputStream = new FileOutputStream(file);\n            byte[] buf = new byte[4096];\n            int bytesRead;\n            while ((bytesRead = inputStream.read(buf)) > -1) {\n                outputStream.write(buf, 0, bytesRead);\n            }\n        } catch (IOException e) {\n            throw new RealmFileException(RealmFileException.Kind.ACCESS_ERROR,\n                    \"Could not resolve the path to the asset file: \" + assetFileName, e);\n        } finally {\n            if (inputStream != null) {\n                try {\n                    inputStream.close();\n                } catch (IOException e) {\n                    exceptionWhenClose = e;\n                }\n            }\n            if (outputStream != null) {\n                try {\n                    outputStream.close();\n                } catch (IOException e) {\n                    // Ignores this one if there was an exception when close inputStream.\n                    if (exceptionWhenClose == null) {\n                        exceptionWhenClose = e;\n                    }\n                }\n            }\n        }\n\n        // No other exception has been thrown, only the exception when close. So, throw it.\n        if (exceptionWhenClose != null) {\n            throw new RealmFileException(RealmFileException.Kind.ACCESS_ERROR, exceptionWhenClose);\n        }\n    }\n\n    static int getLocalThreadCount(RealmConfiguration configuration) {\n        RealmCache cache = getCache(configuration.getPath(), false);\n        if (cache == null) {\n            return 0;\n        }\n\n        // Access local ref count only, no need to be synchronized.\n        int totalRefCount = 0;\n        for (ReferenceCounter referenceCounter : cache.refAndCountMap.values()) {\n            totalRefCount += referenceCounter.getThreadLocalCount();\n        }\n        return totalRefCount;\n    }\n\n    public RealmConfiguration getConfiguration() {\n        return configuration;\n    }\n\n    /**\n     * @return the total global ref count.\n     */\n    private int getTotalGlobalRefCount() {\n        int totalRefCount = 0;\n        for (ReferenceCounter referenceCounter : refAndCountMap.values()) {\n            totalRefCount += referenceCounter.getGlobalCount();\n        }\n\n        return totalRefCount;\n    }\n\n    /**\n     * Returns the total number of threads containg a reference to a live instance of the Realm.\n     */\n    private int getTotalLiveRealmGlobalRefCount() {\n        int totalRefCount = 0;\n        for (ReferenceCounter referenceCounter : refAndCountMap.values()) {\n            if (referenceCounter instanceof ThreadConfinedReferenceCounter) {\n                totalRefCount += referenceCounter.getGlobalCount();\n            }\n        }\n\n        return totalRefCount;\n    }\n\n    /**\n     * If a Realm instance is GCed but `Realm.close()` is not called before, we still want to track the cache for\n     * debugging. Adding them to the list to keep the strong ref of the cache to prevent the cache gets GCed.\n     */\n    void leak() {\n        if (!isLeaked.getAndSet(true)) {\n            leakedCaches.add(this);\n        }\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/RealmChangeListener.java",
    "content": "/*\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\npackage io.realm;\n\n\n/**\n * RealmChangeListener can be registered with a {@link Realm}, {@link RealmResults} or {@link RealmObject}\n * to receive a notification about updates.\n * <p>\n * When registered against a {@code Realm} you'll get notified when a Realm instance has been updated.\n * Register against a {@code RealmResults}, {@code RealmList}, {@code RealmDictionary} or {@code RealmObject} to only\n * get notified about changes to them.\n * <p>\n * Realm instances on a thread without an {@link android.os.Looper} cannot register a RealmChangeListener.\n * <p>\n * All {@link io.realm.RealmObject} and {@link io.realm.RealmResults} will automatically contain their new values when\n * the {@link #onChange(Object)} method is called. Normally this means that it isn't necessary to query again for those\n * objects, but just invalidate any UI elements that are using them. If there is a chance that a object has been been\n * deleted, it can be verified by using {@link RealmObject#isValid()}.\n *\n * @param <T> The <a href=\"https://docs.mongodb.com/realm/sdk/android/fundamentals/live-queries/\">live object</a> being returned\n * ({@link Realm}, {@link DynamicRealm}, {@link RealmObject}, {@link RealmResults}, {@link DynamicRealmObject}\n * or your model implementing {@link RealmModel})\n * @see Realm#addChangeListener(RealmChangeListener)\n * @see Realm#removeAllChangeListeners()\n * @see Realm#removeChangeListener(RealmChangeListener)\n */\npublic interface RealmChangeListener<T> {\n\n    /**\n     * Called when a transaction is committed.\n     */\n    void onChange(T t);\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/RealmCollection.java",
    "content": "/*\n * Copyright 2016 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\npackage io.realm;\n\nimport java.util.Collection;\nimport java.util.Collections;\nimport java.util.Date;\n\nimport javax.annotation.Nullable;\n\nimport io.realm.internal.Freezable;\nimport io.realm.internal.ManageableObject;\n\n\n/**\n * {@code RealmCollection} is the root of the collection hierarchy that Realm supports. It defines operations on data\n * collections and the behavior that they will have in all implementations of {@code RealmCollection}s.\n * <p>\n * Realm collections are \"live\" views to the underlying data. This means that they automatically will be kept up to\n * date. As a consequence, using methods like {@link Collections#unmodifiableCollection(Collection)} will not prevent\n * a collection from being modified.\n *\n * @param <E> type of {@link RealmObject} stored in the collection.\n */\npublic interface RealmCollection<E> extends Collection<E>, ManageableObject, Freezable<RealmCollection<E>> {\n\n    /**\n     * Returns a {@link RealmQuery}, which can be used to query for specific objects from this collection.\n     *\n     * @return a RealmQuery object.\n     * @throws IllegalStateException if the Realm instance has been closed or queries are not otherwise available.\n     * @see io.realm.RealmQuery\n     */\n    RealmQuery<E> where();\n\n    /**\n     * Finds the minimum value of a field.\n     *\n     * @param fieldName the field to look for a minimum on. Only number fields are supported.\n     * @return if no objects exist or they all have {@code null} as the value for the given field, {@code null} will be\n     * returned. Otherwise the minimum value is returned. When determining the minimum value, objects with {@code null}\n     * values are ignored.\n     * @throws java.lang.IllegalArgumentException if the field is not a number type.\n     * @throws java.lang.IllegalStateException    if the Realm has been closed or called from an incorrect thread.\n     */\n    @Nullable\n    Number min(String fieldName);\n\n    /**\n     * Finds the maximum value of a field.\n     *\n     * @param fieldName the field to look for a maximum on. Only number fields are supported.\n     * @return if no objects exist or they all have {@code null} as the value for the given field, {@code null} will be\n     * returned. Otherwise the maximum value is returned. When determining the maximum value, objects with {@code null}\n     * values are ignored.\n     * @throws java.lang.IllegalArgumentException if the field is not a number type.\n     * @throws java.lang.IllegalStateException    if the Realm has been closed or called from an incorrect thread.\n     */\n    @Nullable\n    Number max(String fieldName);\n\n    /**\n     * Calculates the sum of a given field.\n     *\n     * @param fieldName the field to sum. Only number fields are supported.\n     * @return the sum. If no objects exist or they all have {@code null} as the value for the given field, {@code 0}\n     * will be returned. When computing the sum, objects with {@code null} values are ignored.\n     * @throws java.lang.IllegalArgumentException if the field is not a number type.\n     * @throws java.lang.IllegalStateException    if the Realm has been closed or called from an incorrect thread.\n     */\n    Number sum(String fieldName);\n\n    /**\n     * Returns the average of a given field.\n     *\n     * @param fieldName the field to calculate average on. Only number fields are supported.\n     * @return the average for the given field amongst objects in query results. This will be of type double for all\n     * types of number fields. If no objects exist or they all have {@code null} as the value for the given field,\n     * {@code 0} will be returned. When computing the average, objects with {@code null} values are ignored.\n     * @throws java.lang.IllegalArgumentException if the field is not a number type.\n     * @throws java.lang.IllegalStateException    if the Realm has been closed or called from an incorrect thread.\n     */\n    double average(String fieldName);\n\n    /**\n     * Finds the maximum date.\n     *\n     * @param fieldName the field to look for the maximum date. If fieldName is not of Date type, an exception is\n     *                  thrown.\n     * @return if no objects exist or they all have {@code null} as the value for the given date field, {@code null}\n     * will be returned. Otherwise the maximum date is returned. When determining the maximum date, objects with\n     * {@code null} values are ignored.\n     * @throws java.lang.IllegalArgumentException if fieldName is not a Date field.\n     * @throws java.lang.IllegalStateException    if the Realm has been closed or called from an incorrect thread.\n     */\n    @Nullable\n    Date maxDate(String fieldName);\n\n    /**\n     * Finds the minimum date.\n     *\n     * @param fieldName the field to look for the minimum date. If fieldName is not of Date type, an exception is\n     *                  thrown.\n     * @return if no objects exist or they all have {@code null} as the value for the given date field, {@code null}\n     * will be returned. Otherwise the minimum date is returned. When determining the minimum date, objects with\n     * {@code null} values are ignored.\n     * @throws java.lang.IllegalArgumentException if fieldName is not a Date field.\n     * @throws java.lang.IllegalStateException    if the Realm has been closed or called from an incorrect thread.\n     */\n    @Nullable\n    Date minDate(String fieldName);\n\n    /**\n     * This deletes all objects in the collection from the underlying Realm as well as from the collection.\n     *\n     * @return {@code true} if objects was deleted, {@code false} otherwise.\n     * @throws IllegalStateException           if the corresponding Realm is closed or in an incorrect thread.\n     * @throws java.lang.IllegalStateException if the Realm has been closed or called from an incorrect thread.\n     */\n    boolean deleteAllFromRealm();\n\n    /**\n     * Checks if a collection has finished loading its data yet.\n     *\n     * @return {@code true} if data has been loaded and is available, {@code false} if data is still being loaded.\n     */\n    boolean isLoaded();\n\n    /**\n     * Blocks the collection until all data are available.\n     *\n     * @return {@code true} if the data could be successfully loaded, {@code false} otherwise.\n     */\n    boolean load();\n\n    /**\n     * Checks if the collection is still valid to use, i.e., the {@link io.realm.Realm} instance hasn't been closed. It\n     * will always return {@code true} for an unmanaged collection.\n     *\n     * @return {@code true} if it is still valid to use or an unmanaged collection, {@code false} otherwise.\n     */\n    @Override\n    boolean isValid();\n\n    /**\n     * Checks if the collection is managed by Realm. A managed collection is just a wrapper around the data in the\n     * underlying Realm file. On Looper threads, a managed collection will be live-updated so it always points to the\n     * latest data. Managed collections are thread confined so that they cannot be accessed from other threads than the\n     * one that created them.\n     * <p>\n     * <p>\n     * If this method returns {@code false}, the collection is unmanaged. An unmanaged collection is just a normal java\n     * collection, so it will not be live updated.\n     * <p>\n     *\n     * @return {@code true} if this is a managed {@link RealmCollection}, {@code false} otherwise.\n     */\n    @Override\n    boolean isManaged();\n\n    /**\n     * Tests whether this {@code Collection} contains the specified object. Returns\n     * {@code true} if and only if at least one element {@code elem} in this\n     * {@code Collection} meets following requirement:\n     * {@code (object==null ? elem==null : object.equals(elem))}.\n     *\n     * @param object the object to search for.\n     * @return {@code true} if object is an element of this {@code Collection}, {@code false} otherwise.\n     * @throws NullPointerException if the object to look for is {@code null} and this {@code Collection} doesn't\n     *                              support {@code null} elements.\n     */\n    @Override\n    boolean contains(@Nullable Object object);\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/RealmConfiguration.java",
    "content": "/*\n * Copyright 2015 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\npackage io.realm;\n\nimport android.content.Context;\n\nimport java.io.File;\nimport java.lang.reflect.Constructor;\nimport java.lang.reflect.InvocationTargetException;\nimport java.util.Arrays;\nimport java.util.Collections;\nimport java.util.HashSet;\nimport java.util.Locale;\nimport java.util.Set;\n\nimport javax.annotation.Nonnull;\nimport javax.annotation.Nullable;\n\nimport io.realm.annotations.RealmModule;\nimport io.realm.coroutines.FlowFactory;\nimport io.realm.coroutines.RealmFlowFactory;\nimport io.realm.exceptions.RealmException;\nimport io.realm.internal.OsRealmConfig;\nimport io.realm.internal.OsSharedRealm;\nimport io.realm.internal.RealmCore;\nimport io.realm.internal.RealmProxyMediator;\nimport io.realm.internal.Util;\nimport io.realm.internal.modules.CompositeMediator;\nimport io.realm.internal.modules.FilterableMediator;\nimport io.realm.rx.RealmObservableFactory;\nimport io.realm.rx.RxObservableFactory;\n\n\n/**\n * A RealmConfiguration is used to setup a specific Realm instance.\n * <p>\n * Instances of a RealmConfiguration can only created by using the {@link io.realm.RealmConfiguration.Builder} and calling\n * its {@link io.realm.RealmConfiguration.Builder#build()} method.\n * <p>\n * A commonly used RealmConfiguration can easily be accessed by first saving it as\n * {@link Realm#setDefaultConfiguration(RealmConfiguration)} and then using {@link io.realm.Realm#getDefaultInstance()}.\n * <p>\n * A minimal configuration can be created using:\n * <p>\n * {@code RealmConfiguration config = new RealmConfiguration.Builder().build()}\n * <p>\n * This will create a RealmConfiguration with the following properties.\n * <ul>\n * <li>Realm file is called \"default.realm\"</li>\n * <li>It is saved in Context.getFilesDir()</li>\n * <li>It has its schema version set to 0.</li>\n * </ul>\n */\npublic class RealmConfiguration {\n\n    public static final String DEFAULT_REALM_NAME = \"default.realm\";\n\n    private static final Object DEFAULT_MODULE;\n    protected static final RealmProxyMediator DEFAULT_MODULE_MEDIATOR;\n\n    static {\n        DEFAULT_MODULE = Realm.getDefaultModule();\n        if (DEFAULT_MODULE != null) {\n            final RealmProxyMediator mediator = getModuleMediator(DEFAULT_MODULE.getClass().getCanonicalName());\n            if (!mediator.transformerApplied()) {\n                throw new ExceptionInInitializerError(\"RealmTransformer doesn't seem to be applied.\" +\n                        \" Please update the project configuration to use the Realm Gradle plugin.\" +\n                        \" See https://docs.mongodb.com/realm/sdk/android/install/#customize-dependecies-defined-by-the-realm-gradle-plugin\");\n            }\n            DEFAULT_MODULE_MEDIATOR = mediator;\n        } else {\n            DEFAULT_MODULE_MEDIATOR = null;\n        }\n    }\n\n    private final File realmDirectory;\n    private final String realmFileName;\n    private final String canonicalPath;\n    private final String assetFilePath;\n    private final byte[] key;\n    private final long schemaVersion;\n    private final RealmMigration migration;\n    private final boolean deleteRealmIfMigrationNeeded;\n    private final OsRealmConfig.Durability durability;\n    private final RealmProxyMediator schemaMediator;\n    private final RxObservableFactory rxObservableFactory;\n    private final FlowFactory flowFactory;\n    private final Realm.Transaction initialDataTransaction;\n    private final boolean readOnly;\n    private final CompactOnLaunchCallback compactOnLaunch;\n    private final long maxNumberOfActiveVersions;\n    private final boolean allowWritesOnUiThread;\n    private final boolean allowQueriesOnUiThread;\n\n    /**\n     * Whether this RealmConfiguration is intended to open a\n     * recovery Realm produced after an offline/online client reset.\n     */\n    private final boolean isRecoveryConfiguration;\n\n    // We need to enumerate all parameters since SyncConfiguration and RealmConfiguration supports different\n    // subsets of them.\n    protected RealmConfiguration(File realmPath,\n            @Nullable String assetFilePath,\n            @Nullable byte[] key,\n            long schemaVersion,\n            @Nullable RealmMigration migration,\n            boolean deleteRealmIfMigrationNeeded,\n            OsRealmConfig.Durability durability,\n            RealmProxyMediator schemaMediator,\n            @Nullable RxObservableFactory rxObservableFactory,\n            @Nullable FlowFactory flowFactory,\n            @Nullable Realm.Transaction initialDataTransaction,\n            boolean readOnly,\n            @Nullable CompactOnLaunchCallback compactOnLaunch,\n            boolean isRecoveryConfiguration,\n            long maxNumberOfActiveVersions,\n            boolean allowWritesOnUiThread,\n            boolean allowQueriesOnUiThread) {\n        this.realmDirectory = realmPath.getParentFile();\n        this.realmFileName = realmPath.getName();\n        this.canonicalPath = realmPath.getAbsolutePath();\n        this.assetFilePath = assetFilePath;\n        this.key = key;\n        this.schemaVersion = schemaVersion;\n        this.migration = migration;\n        this.deleteRealmIfMigrationNeeded = deleteRealmIfMigrationNeeded;\n        this.durability = durability;\n        this.schemaMediator = schemaMediator;\n        this.rxObservableFactory = rxObservableFactory;\n        this.flowFactory = flowFactory;\n        this.initialDataTransaction = initialDataTransaction;\n        this.readOnly = readOnly;\n        this.compactOnLaunch = compactOnLaunch;\n        this.isRecoveryConfiguration = isRecoveryConfiguration;\n        this.maxNumberOfActiveVersions = maxNumberOfActiveVersions;\n        this.allowWritesOnUiThread = allowWritesOnUiThread;\n        this.allowQueriesOnUiThread = allowQueriesOnUiThread;\n    }\n\n    public File getRealmDirectory() {\n        return realmDirectory;\n    }\n\n    public String getRealmFileName() {\n        return realmFileName;\n    }\n\n    public byte[] getEncryptionKey() {\n        return key == null ? null : Arrays.copyOf(key, key.length);\n    }\n\n    public long getSchemaVersion() {\n        return schemaVersion;\n    }\n\n    public RealmMigration getMigration() {\n        return migration;\n    }\n\n    public boolean shouldDeleteRealmIfMigrationNeeded() {\n        return deleteRealmIfMigrationNeeded;\n    }\n\n    public OsRealmConfig.Durability getDurability() {\n        return durability;\n    }\n\n    /**\n     * Returns the mediator instance of schema which is defined by this configuration.\n     *\n     * @return the mediator of the schema.\n     */\n    // Protected for testing with mockito.\n    protected RealmProxyMediator getSchemaMediator() {\n        return schemaMediator;\n    }\n\n    /**\n     * Returns the transaction instance with initial data.\n     *\n     * @return the initial data transaction.\n     */\n    protected Realm.Transaction getInitialDataTransaction() {\n        return initialDataTransaction;\n    }\n\n    /**\n     * Indicates if an asset file has been configured for this configuration.\n     *\n     * @return {@code true} if there is asset file, {@code false} otherwise.\n     */\n    public boolean hasAssetFile() {\n        return !Util.isEmptyString(assetFilePath);\n    }\n\n    /**\n     * Returns the path to the Realm asset file.\n     *\n     * @return path to the asset file relative to the asset directory or {@code null} if not asset\n     * file was specified.\n     */\n    @Nullable\n    public String getAssetFilePath() {\n        return assetFilePath;\n    }\n\n    /**\n     * Returns a callback to determine if the Realm file should be compacted before being returned to the user.\n     *\n     * @return a callback called when opening a Realm for the first time during the life of a process to determine if\n     * it should be compacted before being returned to the user. It is passed the total file size (data + free space)\n     * and the total bytes used by data in the file.\n     */\n    public CompactOnLaunchCallback getCompactOnLaunchCallback() {\n        return compactOnLaunch;\n    }\n\n    /**\n     * Returns the unmodifiable {@link Set} of model classes that make up the schema for this Realm.\n     *\n     * @return unmodifiable {@link Set} of model classes.\n     */\n    public Set<Class<? extends RealmModel>> getRealmObjectClasses() {\n        return schemaMediator.getModelClasses();\n    }\n\n    /**\n     * Returns the absolute path to where the Realm file will be saved.\n     *\n     * @return the absolute path to the Realm file defined by this configuration.\n     */\n    public String getPath() {\n        return canonicalPath;\n    }\n\n    /**\n     * Checks if the Realm file defined by this configuration already exists.\n     * <p>\n     * WARNING: This method is just a point-in-time check. Unless protected by external synchronization another\n     * thread or process might have created or deleted the Realm file right after this method has returned.\n     *\n     * @return {@code true} if the Realm file exists, {@code false} otherwise.\n     */\n    protected boolean realmExists() {\n        return new File(canonicalPath).exists();\n    }\n\n    /**\n     * Returns the {@link RxObservableFactory} that is used to create Rx Observables from Realm objects.\n     *\n     * @return the factory instance used to create Rx Observables.\n     * @throws UnsupportedOperationException if the required RxJava framework is not on the classpath.\n     */\n    public RxObservableFactory getRxFactory() {\n        // Since RxJava doesn't exist, rxObservableFactory is not initialized.\n        if (rxObservableFactory == null) {\n            throw new UnsupportedOperationException(\"RxJava seems to be missing from the classpath. \" +\n                    \"Remember to add it as an implementation dependency.\" +\n                    \" See https://github.com/realm/realm-java/tree/master/examples/rxJavaExample for more details.\");\n        }\n        return rxObservableFactory;\n    }\n\n    /**\n     * Returns the {@link FlowFactory} that is used to create Kotlin Flows from Realm objects.\n     *\n     * @return the factory instance used to create Flows.\n     * @throws UnsupportedOperationException if the required coroutines framework is not on the classpath.\n     */\n    public FlowFactory getFlowFactory() {\n        if (flowFactory == null) {\n            throw new UnsupportedOperationException(\"The coroutines framework is missing from the classpath. \" +\n                    \"Remember to add it as an implementation dependency. \" +\n                    \"See https://github.com/Kotlin/kotlinx.coroutines#android for more details\");\n        }\n        return flowFactory;\n    }\n\n    /**\n     * Returns whether this Realm is read-only or not. Read-only Realms cannot be modified and will throw an\n     * {@link IllegalStateException} if {@link Realm#beginTransaction()} is called on it.\n     *\n     * @return {@code true} if this Realm is read only, {@code false} if not.\n     */\n    public boolean isReadOnly() {\n        return readOnly;\n    }\n\n    /**\n     * @return {@code true} if this configuration is intended to open a backup Realm (as a result of a client reset).\n     * @see {@link ClientResetRequiredError}\n     */\n    public boolean isRecoveryConfiguration() {\n        return isRecoveryConfiguration;\n    }\n\n    /**\n     * @return the maximum number of active versions allowed before an exception is thrown.\n     */\n    public long getMaxNumberOfActiveVersions() {\n        return maxNumberOfActiveVersions;\n    }\n\n    /**\n     * Returns whether calls to {@link Realm#executeTransaction} can be done on the UI thread.\n     * <p>\n     * <b>Note: Realm does not allow blocking transactions to be run on the main thread unless users explicitly opt in with\n     * {@link Builder#allowWritesOnUiThread(boolean)} or its Realm Sync builder counterpart.</b>\n     *\n     * @return whether or not write operations are allowed to be run from the UI thread.\n     */\n    public boolean isAllowWritesOnUiThread() {\n        return allowWritesOnUiThread;\n    }\n\n    /**\n     * Returns whether a {@link RealmQuery} is allowed to be launched from the UI thread.\n     * <p>\n     * By default Realm allows queries on the main thread. To disallow this users have to explicitly opt in with\n     * {@link Builder#allowQueriesOnUiThread(boolean)} or its Realm Sync builder counterpart.\n     *\n     * @return whether or not queries are allowed to be run from the UI thread.\n     */\n    public boolean isAllowQueriesOnUiThread() {\n        return allowQueriesOnUiThread;\n    }\n\n    @Override\n    public boolean equals(Object obj) {\n        if (this == obj) { return true; }\n        if (obj == null || getClass() != obj.getClass()) { return false; }\n\n        RealmConfiguration that = (RealmConfiguration) obj;\n\n        if (schemaVersion != that.schemaVersion) { return false; }\n        if (deleteRealmIfMigrationNeeded != that.deleteRealmIfMigrationNeeded) { return false; }\n        if (readOnly != that.readOnly) { return false; }\n        if (isRecoveryConfiguration != that.isRecoveryConfiguration) { return false; }\n        if (realmDirectory != null ? !realmDirectory.equals(that.realmDirectory) : that.realmDirectory != null) {\n            return false;\n        }\n        if (realmFileName != null ? !realmFileName.equals(that.realmFileName) : that.realmFileName != null) {\n            return false;\n        }\n        if (!canonicalPath.equals(that.canonicalPath)) { return false; }\n        if (assetFilePath != null ? !assetFilePath.equals(that.assetFilePath) : that.assetFilePath != null) {\n            return false;\n        }\n        if (!Arrays.equals(key, that.key)) { return false; }\n        if (migration != null ? !migration.equals(that.migration) : that.migration != null) {\n            return false;\n        }\n        if (durability != that.durability) { return false; }\n        if (!schemaMediator.equals(that.schemaMediator)) { return false; }\n        if (rxObservableFactory != null ? !rxObservableFactory.equals(that.rxObservableFactory) : that.rxObservableFactory != null) {\n            return false;\n        }\n        if (initialDataTransaction != null ? !initialDataTransaction.equals(that.initialDataTransaction) : that.initialDataTransaction != null) {\n            return false;\n        }\n        if (compactOnLaunch != null ? !compactOnLaunch.equals(that.compactOnLaunch) : that.compactOnLaunch != null) {\n            return false;\n        }\n        return maxNumberOfActiveVersions == that.maxNumberOfActiveVersions;\n    }\n\n    protected Realm getInstance(OsSharedRealm.VersionID version) {\n        return RealmCache.createRealmOrGetFromCache(this, Realm.class, version);\n    }\n\n    @Override\n    public int hashCode() {\n        int result = realmDirectory != null ? realmDirectory.hashCode() : 0;\n        result = 31 * result + (realmFileName != null ? realmFileName.hashCode() : 0);\n        result = 31 * result + canonicalPath.hashCode();\n        result = 31 * result + (assetFilePath != null ? assetFilePath.hashCode() : 0);\n        result = 31 * result + Arrays.hashCode(key);\n        result = 31 * result + (int) (schemaVersion ^ (schemaVersion >>> 32));\n        result = 31 * result + (migration != null ? migration.hashCode() : 0);\n        result = 31 * result + (deleteRealmIfMigrationNeeded ? 1 : 0);\n        result = 31 * result + durability.hashCode();\n        result = 31 * result + schemaMediator.hashCode();\n        result = 31 * result + (rxObservableFactory != null ? rxObservableFactory.hashCode() : 0);\n        result = 31 * result + (initialDataTransaction != null ? initialDataTransaction.hashCode() : 0);\n        result = 31 * result + (readOnly ? 1 : 0);\n        result = 31 * result + (compactOnLaunch != null ? compactOnLaunch.hashCode() : 0);\n        result = 31 * result + (isRecoveryConfiguration ? 1 : 0);\n        result = 31 * result + (int) (maxNumberOfActiveVersions ^ (maxNumberOfActiveVersions >>> 32));\n        return result;\n    }\n\n    // Creates the mediator that defines the current schema.\n    protected static RealmProxyMediator createSchemaMediator(Set<Object> modules,\n            Set<Class<? extends RealmModel>> debugSchema, boolean excludeDebugSchema) {\n\n        // If using debug schema, uses special mediator.\n        if (debugSchema.size() > 0) {\n            return new FilterableMediator(DEFAULT_MODULE_MEDIATOR, debugSchema, excludeDebugSchema);\n        }\n\n        // If only one module, uses that mediator directly.\n        if (modules.size() == 1) {\n            return getModuleMediator(modules.iterator().next().getClass().getCanonicalName());\n        }\n\n        // Otherwise combines all mediators.\n        RealmProxyMediator[] mediators = new RealmProxyMediator[modules.size()];\n        int i = 0;\n        for (Object module : modules) {\n            mediators[i] = getModuleMediator(module.getClass().getCanonicalName());\n            i++;\n        }\n        return new CompositeMediator(mediators);\n    }\n\n    // Finds the mediator associated with a given module.\n    private static RealmProxyMediator getModuleMediator(String fullyQualifiedModuleClassName) {\n        String[] moduleNameParts = fullyQualifiedModuleClassName.split(\"\\\\.\");\n        String moduleSimpleName = moduleNameParts[moduleNameParts.length - 1];\n        String mediatorName = String.format(Locale.US, \"io.realm.%s%s\", moduleSimpleName, \"Mediator\");\n        Class<?> clazz;\n        //noinspection TryWithIdenticalCatches\n        try {\n            clazz = Class.forName(mediatorName);\n            Constructor<?> constructor = clazz.getDeclaredConstructors()[0];\n            constructor.setAccessible(true);\n            return (RealmProxyMediator) constructor.newInstance();\n        } catch (ClassNotFoundException e) {\n            throw new RealmException(\"Could not find \" + mediatorName, e);\n        } catch (InvocationTargetException e) {\n            throw new RealmException(\"Could not create an instance of \" + mediatorName, e);\n        } catch (InstantiationException e) {\n            throw new RealmException(\"Could not create an instance of \" + mediatorName, e);\n        } catch (IllegalAccessException e) {\n            throw new RealmException(\"Could not create an instance of \" + mediatorName, e);\n        }\n    }\n\n    @Override\n    public String toString() {\n        //noinspection StringBufferReplaceableByString\n        StringBuilder stringBuilder = new StringBuilder();\n        stringBuilder.append(\"realmDirectory: \").append(realmDirectory != null ? realmDirectory.toString() : \"\");\n        stringBuilder.append(\"\\n\");\n        stringBuilder.append(\"realmFileName : \").append(realmFileName);\n        stringBuilder.append(\"\\n\");\n        stringBuilder.append(\"canonicalPath: \").append(canonicalPath);\n        stringBuilder.append(\"\\n\");\n        stringBuilder.append(\"key: \").append(\"[length: \").append(key == null ? 0 : Realm.ENCRYPTION_KEY_LENGTH).append(\"]\");\n        stringBuilder.append(\"\\n\");\n        stringBuilder.append(\"schemaVersion: \").append(Long.toString(schemaVersion));\n        stringBuilder.append(\"\\n\");\n        stringBuilder.append(\"migration: \").append(migration);\n        stringBuilder.append(\"\\n\");\n        stringBuilder.append(\"deleteRealmIfMigrationNeeded: \").append(deleteRealmIfMigrationNeeded);\n        stringBuilder.append(\"\\n\");\n        stringBuilder.append(\"durability: \").append(durability);\n        stringBuilder.append(\"\\n\");\n        stringBuilder.append(\"schemaMediator: \").append(schemaMediator);\n        stringBuilder.append(\"\\n\");\n        stringBuilder.append(\"readOnly: \").append(readOnly);\n        stringBuilder.append(\"\\n\");\n        stringBuilder.append(\"compactOnLaunch: \").append(compactOnLaunch);\n        stringBuilder.append(\"\\n\");\n        stringBuilder.append(\"maxNumberOfActiveVersions: \").append(maxNumberOfActiveVersions);\n\n        return stringBuilder.toString();\n    }\n\n    // Checks if this configuration is a SyncConfiguration instance.\n    protected boolean isSyncConfiguration() {\n        return false;\n    }\n\n    protected static RealmConfiguration forRecovery(String canonicalPath, @Nullable byte[] encryptionKey, RealmProxyMediator schemaMediator) {\n        return new RealmConfiguration(new File(canonicalPath),null, encryptionKey, 0, null, false, OsRealmConfig.Durability.FULL, schemaMediator, null, null, null, true, null, true, Long.MAX_VALUE, false, true);\n    }\n\n    /**\n     * RealmConfiguration.Builder used to construct instances of a RealmConfiguration in a fluent manner.\n     */\n    public static class Builder {\n        // IMPORTANT: When adding any new methods to this class also add them to SyncConfiguration.\n        private File directory;\n        private String fileName;\n        private String assetFilePath;\n        private byte[] key;\n        private long schemaVersion;\n        private RealmMigration migration;\n        private boolean deleteRealmIfMigrationNeeded;\n        private OsRealmConfig.Durability durability;\n        private HashSet<Object> modules = new HashSet<Object>();\n        private HashSet<Class<? extends RealmModel>> debugSchema = new HashSet<Class<? extends RealmModel>>();\n        private boolean excludeDebugSchema = false;\n        @Nullable\n        private RxObservableFactory rxFactory;\n        @Nullable\n        private FlowFactory flowFactory;\n        private Realm.Transaction initialDataTransaction;\n        private boolean readOnly;\n        private CompactOnLaunchCallback compactOnLaunch;\n        private long maxNumberOfActiveVersions = Long.MAX_VALUE;\n        private boolean allowWritesOnUiThread;\n        private boolean allowQueriesOnUiThread;\n\n        /**\n         * Creates an instance of the Builder for the RealmConfiguration.\n         * <p>\n         * This will use the app's own internal directory for storing the Realm file. This does not require any\n         * additional permissions. The default location is {@code /data/data/<packagename>/files}, but can\n         * change depending on vendor implementations of Android.\n         */\n        public Builder() {\n            this(BaseRealm.applicationContext);\n        }\n\n        Builder(Context context) {\n            //noinspection ConstantConditions\n            if (context == null) {\n                throw new IllegalStateException(\"Call `Realm.init(Context)` before creating a RealmConfiguration\");\n            }\n            RealmCore.loadLibrary(context);\n            initializeBuilder(context);\n        }\n\n        // Setups builder in its initial state.\n        private void initializeBuilder(Context context) {\n            this.directory = context.getFilesDir();\n            this.fileName = Realm.DEFAULT_REALM_NAME;\n            this.key = null;\n            this.schemaVersion = 0;\n            this.migration = null;\n            this.deleteRealmIfMigrationNeeded = false;\n            this.durability = OsRealmConfig.Durability.FULL;\n            this.readOnly = false;\n            this.compactOnLaunch = null;\n            if (DEFAULT_MODULE != null) {\n                this.modules.add(DEFAULT_MODULE);\n            }\n            this.allowWritesOnUiThread = false;\n            this.allowQueriesOnUiThread = true;\n        }\n\n        /**\n         * Sets the filename for the Realm file.\n         */\n        public Builder name(String filename) {\n            //noinspection ConstantConditions\n            if (filename == null || filename.isEmpty()) {\n                throw new IllegalArgumentException(\"A non-empty filename must be provided\");\n            }\n\n            this.fileName = filename;\n            return this;\n        }\n\n        /**\n         * Specifies the directory where the Realm file will be saved. The default value is {@code context.getFilesDir()}.\n         * If the directory does not exist, it will be created.\n         *\n         * @param directory the directory to save the Realm file in. Directory must be writable.\n         * @throws IllegalArgumentException if {@code directory} is null, not writable or a file.\n         */\n        public Builder directory(File directory) {\n            //noinspection ConstantConditions\n            if (directory == null) {\n                throw new IllegalArgumentException(\"Non-null 'dir' required.\");\n            }\n            if (directory.isFile()) {\n                throw new IllegalArgumentException(\"'dir' is a file, not a directory: \" + directory.getAbsolutePath() + \".\");\n            }\n            if (!directory.exists() && !directory.mkdirs()) {\n                throw new IllegalArgumentException(\"Could not create the specified directory: \" + directory.getAbsolutePath() + \".\");\n            }\n            if (!directory.canWrite()) {\n                throw new IllegalArgumentException(\"Realm directory is not writable: \" + directory.getAbsolutePath() + \".\");\n            }\n            this.directory = directory;\n            return this;\n        }\n\n        /**\n         * Sets the 64 byte key used to encrypt and decrypt the Realm file.\n         * Sets the {@value io.realm.Realm#ENCRYPTION_KEY_LENGTH} bytes key used to encrypt and decrypt the Realm file.\n         */\n        public Builder encryptionKey(byte[] key) {\n            //noinspection ConstantConditions\n            if (key == null) {\n                throw new IllegalArgumentException(\"A non-null key must be provided\");\n            }\n            if (key.length != Realm.ENCRYPTION_KEY_LENGTH) {\n                throw new IllegalArgumentException(String.format(Locale.US,\n                        \"The provided key must be %s bytes. Yours was: %s\",\n                        Realm.ENCRYPTION_KEY_LENGTH, key.length));\n            }\n            this.key = Arrays.copyOf(key, key.length);\n            return this;\n        }\n\n        /**\n         * Sets the schema version of the Realm. This must be equal to or higher than the schema version of the existing\n         * Realm file, if any. If the schema version is higher than the already existing Realm, a migration is needed.\n         * <p>\n         * If no migration code is provided, Realm will throw a\n         * {@link io.realm.exceptions.RealmMigrationNeededException}.\n         *\n         * @see #migration(RealmMigration)\n         */\n        public Builder schemaVersion(long schemaVersion) {\n            if (schemaVersion < 0) {\n                throw new IllegalArgumentException(\"Realm schema version numbers must be 0 (zero) or higher. Yours was: \" + schemaVersion);\n            }\n            this.schemaVersion = schemaVersion;\n            return this;\n        }\n\n        /**\n         * Sets the {@link io.realm.RealmMigration} to be run if a migration is needed. If this migration fails to\n         * upgrade the on-disc schema to the runtime schema, a {@link io.realm.exceptions.RealmMigrationNeededException}\n         * will be thrown.\n         */\n        public Builder migration(RealmMigration migration) {\n            //noinspection ConstantConditions\n            if (migration == null) {\n                throw new IllegalArgumentException(\"A non-null migration must be provided\");\n            }\n            this.migration = migration;\n            return this;\n        }\n\n        /**\n         * Setting this will change the behavior of how migration exceptions are handled. Instead of throwing a\n         * {@link io.realm.exceptions.RealmMigrationNeededException} the on-disc Realm will be cleared and recreated\n         * with the new Realm schema.\n         * <p>\n         * <p>This cannot be configured to have an asset file at the same time by calling\n         * {@link #assetFile(String)} as the provided asset file will be deleted in migrations.\n         * <p>\n         * <p><b>WARNING!</b> This will result in loss of data.\n         *\n         * @throws IllegalStateException if configured to use an asset file by calling {@link #assetFile(String)} previously.\n         */\n        public Builder deleteRealmIfMigrationNeeded() {\n            if (this.assetFilePath != null && this.assetFilePath.length() != 0) {\n                throw new IllegalStateException(\"Realm cannot clear its schema when previously configured to use an asset file by calling assetFile().\");\n            }\n\n            this.deleteRealmIfMigrationNeeded = true;\n            return this;\n        }\n\n        /**\n         * Setting this will create an in-memory Realm instead of saving it to disk. In-memory Realms might still use\n         * disk space if memory is running low, but all files created by an in-memory Realm will be deleted when the\n         * Realm is closed.\n         * <p>\n         * Note that because in-memory Realms are not persisted, you must be sure to hold on to at least one non-closed\n         * reference to the in-memory Realm object with the specific name as long as you want the data to last.\n         */\n        public Builder inMemory() {\n            if (!Util.isEmptyString(assetFilePath)) {\n                throw new RealmException(\"Realm can not use in-memory configuration if asset file is present.\");\n            }\n\n            this.durability = OsRealmConfig.Durability.MEM_ONLY;\n\n            return this;\n        }\n\n        /**\n         * Replaces the existing module(s) with one or more {@link RealmModule}s. Using this method will replace the\n         * current schema for this Realm with the schema defined by the provided modules.\n         * <p>\n         * A reference to the default Realm module containing all Realm classes in the project (but not dependencies),\n         * can be found using {@link Realm#getDefaultModule()}. Combining the schema from the app project and a library\n         * dependency is thus done using the following code:\n         * <p>\n         * {@code builder.modules(Realm.getDefaultMode(), new MyLibraryModule()); }\n         * <p>\n         *\n         * @param baseModule the first Realm module (required).\n         * @param additionalModules the additional Realm modules\n         * @throws IllegalArgumentException if any of the modules doesn't have the {@link RealmModule} annotation.\n         * @see Realm#getDefaultModule()\n         */\n        public Builder modules(Object baseModule, Object... additionalModules) {\n            modules.clear();\n            addModule(baseModule);\n            //noinspection ConstantConditions\n            if (additionalModules != null) {\n                for (int i = 0; i < additionalModules.length; i++) {\n                    Object module = additionalModules[i];\n                    addModule(module);\n                }\n            }\n            return this;\n        }\n\n        /**\n         * FIXME: Temporary visible\n         * DEBUG method. Will add a module unconditionally.\n         *\n         * Adds a module to already defined modules.\n         */\n        public final Builder addModule(Object module) {\n            //noinspection ConstantConditions\n            if (module != null) {\n                checkModule(module);\n                modules.add(module);\n            }\n\n            return this;\n        }\n\n        /**\n         * Sets the {@link RxObservableFactory} used to create Rx Observables from Realm objects.\n         * The default factory is {@link RealmObservableFactory}.\n         *\n         * @param factory factory to use.\n         */\n        public Builder rxFactory(@Nonnull RxObservableFactory factory) {\n            if (factory == null) {\n                throw new IllegalArgumentException(\"The provided Rx Observable factory must not be null.\");\n            }\n            rxFactory = factory;\n            return this;\n        }\n\n        /**\n         * Sets the {@link FlowFactory} used to create coroutines Flows from Realm objects.\n         * The default factory is {@link RealmFlowFactory}.\n         *\n         * @param factory factory to use.\n         */\n        public Builder flowFactory(@Nonnull FlowFactory factory) {\n            if (factory == null) {\n                throw new IllegalArgumentException(\"The provided Flow factory must not be null.\");\n            }\n            flowFactory = factory;\n            return this;\n        }\n\n        /**\n         * Sets the initial data in {@link io.realm.Realm}. This transaction will be executed only for the first time\n         * when database file is created or while migrating the data when {@link Builder#deleteRealmIfMigrationNeeded()} is set.\n         *\n         * @param transaction transaction to execute.\n         */\n        public Builder initialData(Realm.Transaction transaction) {\n            initialDataTransaction = transaction;\n            return this;\n        }\n\n        /**\n         * Copies the Realm file from the given asset file path.\n         * <p>\n         * When opening the Realm for the first time, instead of creating an empty file,\n         * the Realm file will be copied from the provided asset file and used instead.\n         * <p>\n         * This cannot be combined with {@link #deleteRealmIfMigrationNeeded()} as doing so would just result in the\n         * copied file being deleted.\n         * <p>\n         * WARNING: This could potentially be a lengthy operation and should ideally be done on a background thread.\n         *\n         * @param assetFile path to the asset database file.\n         * @throws IllegalStateException if this is configured to clear its schema by calling {@link #deleteRealmIfMigrationNeeded()}.\n         */\n        public Builder assetFile(String assetFile) {\n            if (Util.isEmptyString(assetFile)) {\n                throw new IllegalArgumentException(\"A non-empty asset file path must be provided\");\n            }\n            if (durability == OsRealmConfig.Durability.MEM_ONLY) {\n                throw new RealmException(\"Realm can not use in-memory configuration if asset file is present.\");\n            }\n            if (this.deleteRealmIfMigrationNeeded) {\n                throw new IllegalStateException(\"Realm cannot use an asset file when previously configured to clear its schema in migration by calling deleteRealmIfMigrationNeeded().\");\n            }\n            this.assetFilePath = assetFile;\n\n            return this;\n        }\n\n        /**\n         * Setting this will cause the Realm to become read only and all write transactions made against this Realm will\n         * fail with an {@link IllegalStateException}.\n         * <p>\n         * This in particular mean that {@link #initialData(Realm.Transaction)} will not work in combination with a\n         * read only Realm and setting this will result in a {@link IllegalStateException} being thrown.\n         * </p>\n         * Marking a Realm as read only only applies to the Realm in this process. Other processes can still\n         * write to the Realm.\n         */\n        public Builder readOnly() {\n            this.readOnly = true;\n            return this;\n        }\n\n        /**\n         * Setting this will cause Realm to compact the Realm file if the Realm file has grown too large and a\n         * significant amount of space can be recovered. See {@link DefaultCompactOnLaunchCallback} for details.\n         */\n        public Builder compactOnLaunch() {\n            return compactOnLaunch(new DefaultCompactOnLaunchCallback());\n        }\n\n        /**\n         * Sets this to determine if the Realm file should be compacted before returned to the user. It is passed the\n         * total file size (data + free space) and the bytes used by data in the file.\n         *\n         * @param compactOnLaunch a callback called when opening a Realm for the first time during the life of a process\n         *                        to determine if it should be compacted before being returned to the user. It is passed\n         *                        the total file size (data + free space) and the bytes used by data in the file.\n         */\n        public Builder compactOnLaunch(CompactOnLaunchCallback compactOnLaunch) {\n            //noinspection ConstantConditions\n            if (compactOnLaunch == null) {\n                throw new IllegalArgumentException(\"A non-null compactOnLaunch must be provided\");\n            }\n            this.compactOnLaunch = compactOnLaunch;\n            return this;\n        }\n\n        /**\n         * Sets the maximum number of live versions in the Realm file before an {@link IllegalStateException} is thrown when\n         * attempting to write more data.\n         * <p>\n         * Realm is capable of concurrently handling many different versions of Realm objects. This can e.g. happen if you\n         * have a Realm open on many different threads or are freezing objects while data is being written to the file.\n         * <p>\n         * Under normal circumstances this is not a problem, but if the number of active versions grow too large, it will\n         * have a negative effect on the filesize on disk. Setting this parameters can therefore be used to prevent uses of\n         * Realm that can result in very large Realms.\n         *\n         * @param number the maximum number of active versions before an exception is thrown.\n         * @see <a href=\"https://docs.mongodb.com/realm/sdk/android/fundamentals/realms/#realm-file-size\">FAQ</a>\n         */\n        public Builder maxNumberOfActiveVersions(long number) {\n            if (number < 1) {\n                throw new IllegalArgumentException(\"Only positive numbers above 0 are allowed. Yours was: \" + number);\n            }\n            this.maxNumberOfActiveVersions = number;\n            return this;\n        }\n\n        /**\n         * DEBUG method. This restricts the Realm schema to only consist of the provided classes without having to\n         * create a module. These classes must be available in the default module. Calling this will remove any\n         * previously configured modules.\n         */\n        final Builder schema(Class<? extends RealmModel> firstClass, Class<? extends RealmModel>... additionalClasses) {\n            //noinspection ConstantConditions\n            if (firstClass == null) {\n                throw new IllegalArgumentException(\"A non-null class must be provided\");\n            }\n            modules.clear();\n            modules.add(DEFAULT_MODULE_MEDIATOR);\n            debugSchema.add(firstClass);\n            //noinspection ConstantConditions\n            if (additionalClasses != null) {\n                Collections.addAll(debugSchema, additionalClasses);\n            }\n\n            return this;\n        }\n\n        /**\n         * DEBUG method. This restricts the Realm schema to exclude the provided classes from the original schema\n         * without having to create a module. These classes must be available in the default module. Calling this will\n         * remove any previously configured modules.\n         */\n        final Builder excludeSchema(Class<? extends RealmModel> firstClass, Class<? extends RealmModel>... additionalClasses) {\n            excludeDebugSchema = true;\n            return schema(firstClass, additionalClasses);\n        }\n\n        /**\n         * Sets whether or not calls to {@link Realm#executeTransaction} are allowed from the UI thread.\n         * <p>\n         * <b>WARNING: Realm does not allow synchronous transactions to be run on the main thread unless users explicitly opt in\n         * with this method.</b> We recommend diverting calls to {@code executeTransaction} to non-UI threads or, alternatively,\n         * using {@link Realm#executeTransactionAsync}.\n         */\n        public Builder allowWritesOnUiThread(boolean allowWritesOnUiThread) {\n            this.allowWritesOnUiThread = allowWritesOnUiThread;\n            return this;\n        }\n\n        /**\n         * Sets whether or not a {@link RealmQuery} can be launched from the UI thread.\n         * <p>\n         * By default Realm allows queries on the main thread. However, by doing so your application may experience a drop of\n         * frames or even ANRs. We recommend diverting queries to non-UI threads or, alternatively, using\n         * {@link RealmQuery#findAllAsync()} or {@link RealmQuery#findFirstAsync()}.\n         */\n        public Builder allowQueriesOnUiThread(boolean allowQueriesOnUiThread) {\n            this.allowQueriesOnUiThread = allowQueriesOnUiThread;\n            return this;\n        }\n\n        /**\n         * Creates the RealmConfiguration based on the builder parameters.\n         *\n         * @return the created {@link RealmConfiguration}.\n         */\n        public RealmConfiguration build() {\n            // Check that readOnly() was applied to legal configuration. Right now it should only be allowed if\n            // an assetFile is configured\n            if (readOnly) {\n                if (initialDataTransaction != null) {\n                    throw new IllegalStateException(\"This Realm is marked as read-only. Read-only Realms cannot use initialData(Realm.Transaction).\");\n                }\n                if (assetFilePath == null) {\n                    throw new IllegalStateException(\"Only Realms provided using 'assetFile(path)' can be marked read-only. No such Realm was provided.\");\n                }\n                if (deleteRealmIfMigrationNeeded) {\n                    throw new IllegalStateException(\"'deleteRealmIfMigrationNeeded()' and read-only Realms cannot be combined\");\n                }\n                if (compactOnLaunch != null) {\n                    throw new IllegalStateException(\"'compactOnLaunch()' and read-only Realms cannot be combined\");\n                }\n            }\n\n            if (rxFactory == null && Util.isRxJavaAvailable()) {\n                rxFactory = new RealmObservableFactory(true);\n            }\n\n            if (flowFactory == null && Util.isCoroutinesAvailable()) {\n                flowFactory = new RealmFlowFactory(true);\n            }\n\n            return new RealmConfiguration(new File(directory, fileName),\n                    assetFilePath,\n                    key,\n                    schemaVersion,\n                    migration,\n                    deleteRealmIfMigrationNeeded,\n                    durability,\n                    createSchemaMediator(modules, debugSchema, excludeDebugSchema),\n                    rxFactory,\n                    flowFactory,\n                    initialDataTransaction,\n                    readOnly,\n                    compactOnLaunch,\n                    false,\n                    maxNumberOfActiveVersions,\n                    allowWritesOnUiThread,\n                    allowQueriesOnUiThread\n            );\n        }\n\n        private void checkModule(Object module) {\n            if (!module.getClass().isAnnotationPresent(RealmModule.class)) {\n                throw new IllegalArgumentException(module.getClass().getCanonicalName() + \" is not a RealmModule. \" +\n                        \"Add @RealmModule to the class definition.\");\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/RealmDictionary.java",
    "content": "/*\n * Copyright 2020 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\npackage io.realm;\n\nimport org.bson.types.Decimal128;\nimport org.bson.types.ObjectId;\n\nimport java.util.Date;\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.UUID;\n\nimport edu.umd.cs.findbugs.annotations.SuppressFBWarnings;\nimport io.realm.internal.OsMap;\n\n/**\n * Specialization of {@link RealmMap}s whose keys are strings.\n * <p>\n * Similarly to {@link RealmList}s, a RealmDictionary can operate in managed and unmanaged modes. In\n * managed mode a RealmDictionary persists all its contents inside a Realm whereas in unmanaged mode\n * it functions like a {@link HashMap}.\n * <p>\n * Managed RealmDictionaries can only be created by Realm and will automatically update its content\n * whenever the underlying Realm is updated. Managed RealmDictionaries can only be accessed using\n * the getter that points to a RealmDictionary field of a {@link RealmObject}.\n * <p>\n * Unmanaged RealmDictionaries can be created by the user and can contain both managed and unmanaged\n * RealmObjects. This is useful when dealing with JSON deserializers like GSON or other frameworks\n * that inject values into a class. Unmanaged RealmDictionaries can be added to a Realm using the\n * {@link Realm#copyToRealm(Iterable, ImportFlag...)} method.\n *\n * @param <V> the type of the values stored in this dictionary\n */\npublic class RealmDictionary<V> extends RealmMap<String, V> {\n\n    // ------------------------------------------\n    // Unmanaged constructors\n    // ------------------------------------------\n\n    /**\n     * Instantiates a RealmDictionary in unmanaged mode.\n     */\n    public RealmDictionary() {\n        super();\n    }\n\n    /**\n     * Instantiates a RealmDictionary in unmanaged mode with an initial dictionary.\n     *\n     * @param map initial dictionary\n     */\n    public RealmDictionary(Map<String, V> map) {\n        super(map);\n    }\n\n    // ------------------------------------------\n    // Managed constructors\n    // ------------------------------------------\n\n    /**\n     * Constructor used by {@code Realm}s.\n     *\n     * @param baseRealm\n     * @param osMap\n     * @param valueClass\n     */\n    RealmDictionary(BaseRealm baseRealm, OsMap osMap, Class<V> valueClass) {\n        super(getStrategy(valueClass, baseRealm, osMap));\n    }\n\n    /**\n     * Constructor used by {@code DynamicRealmObject}s.\n     *\n     * @param baseRealm\n     * @param osMap\n     * @param className\n     */\n    RealmDictionary(BaseRealm baseRealm, OsMap osMap, String className) {\n        super(getStrategy(className, baseRealm, osMap));\n    }\n\n    // ------------------------------------------\n    // Private stuff\n    // ------------------------------------------\n\n    private Map<String, V> toMap() {\n        Map<String, V> map = new HashMap<>();\n        for (Entry<String, V> entry : this.entrySet()) {\n            map.put(entry.getKey(), entry.getValue());\n        }\n        return map;\n    }\n\n    private static <V extends RealmModel> LinkSelectorForMap<String, V> getRealmSelector(Class<V> valueClass,\n                                                                                         BaseRealm baseRealm,\n                                                                                         OsMap osMap) {\n        return new LinkSelectorForMap<>(baseRealm, osMap, String.class, valueClass);\n    }\n\n    @SuppressWarnings(\"unchecked\")\n    private static <V> ManagedMapStrategy<String, V> getStrategy(Class<V> valueClass,\n                                                                 BaseRealm baseRealm,\n                                                                 OsMap osMap) {\n        if (CollectionUtils.isClassForRealmModel(valueClass)) {\n            Class<? extends RealmModel> typeCastClass = (Class<? extends RealmModel>) valueClass;\n            TypeSelectorForMap<String, RealmModel> realmSelector = (TypeSelectorForMap<String, RealmModel>) getRealmSelector(typeCastClass, baseRealm, osMap);\n            ManagedMapManager<String, RealmModel> dictionaryManager = new DictionaryManager<>(baseRealm,\n                    new RealmModelValueOperator<>(baseRealm, osMap, realmSelector),\n                    realmSelector);\n\n            return (ManagedMapStrategy<String, V>) new ManagedMapStrategy<>(dictionaryManager);\n        }\n\n        DictionaryManager<V> manager = getManager(valueClass, baseRealm, osMap);\n        return new ManagedMapStrategy<>(manager);\n    }\n\n    private static <V> ManagedMapStrategy<String, V> getStrategy(String valueClass,\n                                                                 BaseRealm baseRealm,\n                                                                 OsMap osMap) {\n        DictionaryManager<V> manager = getManager(valueClass, baseRealm, osMap);\n        return new ManagedMapStrategy<>(manager);\n    }\n\n    @SuppressWarnings(\"unchecked\")\n    private static <V> DictionaryManager<V> getManager(Class<V> valueClass,\n                                                       BaseRealm baseRealm,\n                                                       OsMap osMap) {\n        TypeSelectorForMap<String, V> typeSelectorForMap = new SelectorForMap<>(baseRealm, osMap, String.class, valueClass);\n\n        MapValueOperator<String, ?> mapValueOperator;\n\n        if (valueClass == RealmAny.class) {\n            mapValueOperator = new RealmAnyValueOperator<>(baseRealm, osMap, (TypeSelectorForMap<String, RealmAny>) typeSelectorForMap);\n        } else if (valueClass == Long.class) {\n            mapValueOperator = new GenericPrimitiveValueOperator<>(Long.class, baseRealm, osMap, (TypeSelectorForMap<String, Long>) typeSelectorForMap, RealmMapEntrySet.IteratorType.LONG);\n        } else if (valueClass == Float.class) {\n            mapValueOperator = new GenericPrimitiveValueOperator<>(Float.class, baseRealm, osMap, (TypeSelectorForMap<String, Float>) typeSelectorForMap, RealmMapEntrySet.IteratorType.FLOAT);\n        } else if (valueClass == Double.class) {\n            mapValueOperator = new GenericPrimitiveValueOperator<>(Double.class, baseRealm, osMap, (TypeSelectorForMap<String, Double>) typeSelectorForMap, RealmMapEntrySet.IteratorType.DOUBLE);\n        } else if (valueClass == String.class) {\n            mapValueOperator = new GenericPrimitiveValueOperator<>(String.class, baseRealm, osMap, (TypeSelectorForMap<String, String>) typeSelectorForMap, RealmMapEntrySet.IteratorType.STRING);\n        } else if (valueClass == Boolean.class) {\n            mapValueOperator = new GenericPrimitiveValueOperator<>(Boolean.class, baseRealm, osMap, (TypeSelectorForMap<String, Boolean>) typeSelectorForMap, RealmMapEntrySet.IteratorType.BOOLEAN);\n        } else if (valueClass == Date.class) {\n            mapValueOperator = new GenericPrimitiveValueOperator<>(Date.class, baseRealm, osMap, (TypeSelectorForMap<String, Date>) typeSelectorForMap, RealmMapEntrySet.IteratorType.DATE);\n        } else if (valueClass == Decimal128.class) {\n            mapValueOperator = new GenericPrimitiveValueOperator<>(Decimal128.class, baseRealm, osMap, (TypeSelectorForMap<String, Decimal128>) typeSelectorForMap, RealmMapEntrySet.IteratorType.DECIMAL128);\n        } else if (valueClass == Integer.class) {\n            mapValueOperator = new IntegerValueOperator<>(baseRealm, osMap, (TypeSelectorForMap<String, Integer>) typeSelectorForMap);\n        } else if (valueClass == Short.class) {\n            mapValueOperator = new ShortValueOperator<>(baseRealm, osMap, (TypeSelectorForMap<String, Short>) typeSelectorForMap);\n        } else if (valueClass == Byte.class) {\n            mapValueOperator = new ByteValueOperator<>(baseRealm, osMap, (TypeSelectorForMap<String, Byte>) typeSelectorForMap);\n        } else if (valueClass == byte[].class) {\n            mapValueOperator = new GenericPrimitiveValueOperator<>((Class<V>) byte[].class, baseRealm, osMap, typeSelectorForMap, RealmMapEntrySet.IteratorType.BINARY, (EqualsHelper<String, V>) new BinaryEquals<String>());\n        } else if (valueClass == ObjectId.class) {\n            mapValueOperator = new GenericPrimitiveValueOperator<>(ObjectId.class, baseRealm, osMap, (TypeSelectorForMap<String, ObjectId>) typeSelectorForMap, RealmMapEntrySet.IteratorType.OBJECT_ID);\n        } else if (valueClass == UUID.class) {\n            mapValueOperator = new GenericPrimitiveValueOperator<>(UUID.class, baseRealm, osMap, (TypeSelectorForMap<String, UUID>) typeSelectorForMap, RealmMapEntrySet.IteratorType.UUID);\n        } else {\n            throw new IllegalArgumentException(\"Only Maps of RealmAny or one of the types that can be boxed inside RealmAny can be used.\");\n        }\n\n        return new DictionaryManager<>(baseRealm,\n                (MapValueOperator<String, V>) mapValueOperator,\n                typeSelectorForMap);\n    }\n\n    @SuppressWarnings(\"unchecked\")\n    private static <V> DictionaryManager<V> getManager(String valueClass,\n                                                       BaseRealm baseRealm,\n                                                       OsMap osMap) {\n\n        MapValueOperator<String, ?> mapValueOperator;\n\n        if (valueClass.equals(RealmAny.class.getCanonicalName())) {\n            mapValueOperator = new RealmAnyValueOperator<>(baseRealm, osMap, new SelectorForMap<>(baseRealm, osMap, String.class, RealmAny.class));\n        } else if (valueClass.equals(Long.class.getCanonicalName())) {\n            mapValueOperator = new GenericPrimitiveValueOperator<>(Long.class, baseRealm, osMap, new SelectorForMap<>(baseRealm, osMap, String.class, Long.class), RealmMapEntrySet.IteratorType.LONG);\n        } else if (valueClass.equals(Float.class.getCanonicalName())) {\n            mapValueOperator = new GenericPrimitiveValueOperator<>(Float.class, baseRealm, osMap, new SelectorForMap<>(baseRealm, osMap, String.class, Float.class), RealmMapEntrySet.IteratorType.FLOAT);\n        } else if (valueClass.equals(Double.class.getCanonicalName())) {\n            mapValueOperator = new GenericPrimitiveValueOperator<>(Double.class, baseRealm, osMap, new SelectorForMap<>(baseRealm, osMap, String.class, Double.class), RealmMapEntrySet.IteratorType.DOUBLE);\n        } else if (valueClass.equals(String.class.getCanonicalName())) {\n            mapValueOperator = new GenericPrimitiveValueOperator<>(String.class, baseRealm, osMap, new SelectorForMap<>(baseRealm, osMap, String.class, String.class), RealmMapEntrySet.IteratorType.STRING);\n        } else if (valueClass.equals(Boolean.class.getCanonicalName())) {\n            mapValueOperator = new GenericPrimitiveValueOperator<>(Boolean.class, baseRealm, osMap, new SelectorForMap<>(baseRealm, osMap, String.class, Boolean.class), RealmMapEntrySet.IteratorType.BOOLEAN);\n        } else if (valueClass.equals(Date.class.getCanonicalName())) {\n            mapValueOperator = new GenericPrimitiveValueOperator<>(Date.class, baseRealm, osMap, new SelectorForMap<>(baseRealm, osMap, String.class, Date.class), RealmMapEntrySet.IteratorType.DATE);\n        } else if (valueClass.equals(Decimal128.class.getCanonicalName())) {\n            mapValueOperator = new GenericPrimitiveValueOperator<>(Decimal128.class, baseRealm, osMap, new SelectorForMap<>(baseRealm, osMap, String.class, Decimal128.class), RealmMapEntrySet.IteratorType.DECIMAL128);\n        } else if (valueClass.equals(Integer.class.getCanonicalName())) {\n            mapValueOperator = new IntegerValueOperator<>(baseRealm, osMap, new SelectorForMap<>(baseRealm, osMap, String.class, Integer.class));\n        } else if (valueClass.equals(Short.class.getCanonicalName())) {\n            mapValueOperator = new ShortValueOperator<>(baseRealm, osMap, new SelectorForMap<>(baseRealm, osMap, String.class, Short.class));\n        } else if (valueClass.equals(Byte.class.getCanonicalName())) {\n            mapValueOperator = new ByteValueOperator<>(baseRealm, osMap, new SelectorForMap<>(baseRealm, osMap, String.class, Byte.class));\n        } else if (valueClass.equals(byte[].class.getCanonicalName())) {\n            mapValueOperator = new GenericPrimitiveValueOperator<>(byte[].class, baseRealm, osMap, new SelectorForMap<>(baseRealm, osMap, String.class, byte[].class), RealmMapEntrySet.IteratorType.BINARY, (EqualsHelper<String, byte[]>) new BinaryEquals<String>());\n        } else if (valueClass.equals(ObjectId.class.getCanonicalName())) {\n            mapValueOperator = new GenericPrimitiveValueOperator<>(ObjectId.class, baseRealm, osMap,  new SelectorForMap<>(baseRealm, osMap, String.class, ObjectId.class), RealmMapEntrySet.IteratorType.OBJECT_ID);\n        } else if (valueClass.equals(UUID.class.getCanonicalName())) {\n            mapValueOperator = new GenericPrimitiveValueOperator<>(UUID.class, baseRealm, osMap,  new SelectorForMap<>(baseRealm, osMap, String.class, UUID.class), RealmMapEntrySet.IteratorType.UUID);\n        } else {\n            mapValueOperator = new RealmModelValueOperator<>(baseRealm, osMap, new DynamicSelectorForMap<>(baseRealm, osMap, valueClass));\n        }\n\n        return new DictionaryManager<>(baseRealm, (MapValueOperator<String, V>) mapValueOperator, (TypeSelectorForMap<String, V>) mapValueOperator.typeSelectorForMap);\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/RealmFieldType.java",
    "content": "/*\n * Copyright 2015 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\npackage io.realm;\n\nimport org.bson.types.Decimal128;\nimport org.bson.types.ObjectId;\n\nimport java.nio.ByteBuffer;\n\nimport io.realm.internal.Keep;\nimport io.realm.internal.Property;\n\nimport static io.realm.RealmFieldTypeConstants.CORE_TYPE_VALUE_BINARY;\nimport static io.realm.RealmFieldTypeConstants.CORE_TYPE_VALUE_BOOLEAN;\nimport static io.realm.RealmFieldTypeConstants.CORE_TYPE_VALUE_DATE;\nimport static io.realm.RealmFieldTypeConstants.CORE_TYPE_VALUE_DECIMAL128;\nimport static io.realm.RealmFieldTypeConstants.CORE_TYPE_VALUE_DOUBLE;\nimport static io.realm.RealmFieldTypeConstants.CORE_TYPE_VALUE_FLOAT;\nimport static io.realm.RealmFieldTypeConstants.CORE_TYPE_VALUE_INTEGER;\nimport static io.realm.RealmFieldTypeConstants.CORE_TYPE_VALUE_LINKING_OBJECTS;\nimport static io.realm.RealmFieldTypeConstants.CORE_TYPE_VALUE_LIST;\nimport static io.realm.RealmFieldTypeConstants.CORE_TYPE_VALUE_MIXED;\nimport static io.realm.RealmFieldTypeConstants.CORE_TYPE_VALUE_OBJECT;\nimport static io.realm.RealmFieldTypeConstants.CORE_TYPE_VALUE_OBJECTID;\nimport static io.realm.RealmFieldTypeConstants.CORE_TYPE_VALUE_STRING;\nimport static io.realm.RealmFieldTypeConstants.CORE_TYPE_VALUE_TYPED_LINK;\nimport static io.realm.RealmFieldTypeConstants.CORE_TYPE_VALUE_UUID;\nimport static io.realm.RealmFieldTypeConstants.DICTIONARY_OFFSET;\nimport static io.realm.RealmFieldTypeConstants.LIST_OFFSET;\nimport static io.realm.RealmFieldTypeConstants.MAX_CORE_TYPE_VALUE;\nimport static io.realm.RealmFieldTypeConstants.SET_OFFSET;\n\n\ninterface RealmFieldTypeConstants {\n    int LIST_OFFSET = Property.TYPE_ARRAY;\n    int DICTIONARY_OFFSET = Property.TYPE_DICTIONARY;\n    int SET_OFFSET = Property.TYPE_SET;\n\n    int CORE_TYPE_VALUE_INTEGER = 0;\n    int CORE_TYPE_VALUE_BOOLEAN = 1;\n    int CORE_TYPE_VALUE_STRING = 2;\n    int CORE_TYPE_VALUE_BINARY = 4;\n    int CORE_TYPE_VALUE_DATE = 8;\n    int CORE_TYPE_VALUE_FLOAT = 9;\n    int CORE_TYPE_VALUE_DOUBLE = 10;\n    int CORE_TYPE_VALUE_OBJECT = 12;\n    int CORE_TYPE_VALUE_LIST = 13;\n    int CORE_TYPE_VALUE_LINKING_OBJECTS = 14;\n    int CORE_TYPE_VALUE_DECIMAL128 = 11;\n    int CORE_TYPE_VALUE_OBJECTID = 15;\n    int CORE_TYPE_VALUE_UUID = 17;\n    int CORE_TYPE_VALUE_MIXED = 6;\n    int CORE_TYPE_VALUE_TYPED_LINK = 16;\n\n    int MAX_CORE_TYPE_VALUE = CORE_TYPE_VALUE_UUID;\n}\n\n/**\n * List of the types used by Realm's underlying storage engine.\n * <p>\n * Normally there is no reason to interact with the underlying Realm types as Realm will automatically\n * convert between normal Java types and the Realm types. However it is possible to access these\n * types through a {@link DynamicRealmObject}.\n */\n@Keep\npublic enum RealmFieldType {\n    // Makes sure numbers match with <realm/column_type.hpp>.\n    INTEGER(CORE_TYPE_VALUE_INTEGER),\n    BOOLEAN(CORE_TYPE_VALUE_BOOLEAN),\n    STRING(CORE_TYPE_VALUE_STRING),\n    BINARY(CORE_TYPE_VALUE_BINARY),\n    DATE(CORE_TYPE_VALUE_DATE),\n    FLOAT(CORE_TYPE_VALUE_FLOAT),\n    DOUBLE(CORE_TYPE_VALUE_DOUBLE),\n    OBJECT(CORE_TYPE_VALUE_OBJECT),\n    DECIMAL128(CORE_TYPE_VALUE_DECIMAL128),\n    OBJECT_ID(CORE_TYPE_VALUE_OBJECTID),\n    UUID(CORE_TYPE_VALUE_UUID),\n    MIXED(CORE_TYPE_VALUE_MIXED),           // Core equivalent to RealmAny\n    TYPED_LINK(CORE_TYPE_VALUE_TYPED_LINK), // It is only used by RealmAny internally.\n\n    LIST(CORE_TYPE_VALUE_LIST),\n    LINKING_OBJECTS(CORE_TYPE_VALUE_LINKING_OBJECTS),\n\n    INTEGER_LIST(CORE_TYPE_VALUE_INTEGER + LIST_OFFSET),\n    BOOLEAN_LIST(CORE_TYPE_VALUE_BOOLEAN + LIST_OFFSET),\n    STRING_LIST(CORE_TYPE_VALUE_STRING + LIST_OFFSET),\n    BINARY_LIST(CORE_TYPE_VALUE_BINARY + LIST_OFFSET),\n    DATE_LIST(CORE_TYPE_VALUE_DATE + LIST_OFFSET),\n    FLOAT_LIST(CORE_TYPE_VALUE_FLOAT + LIST_OFFSET),\n    DOUBLE_LIST(CORE_TYPE_VALUE_DOUBLE + LIST_OFFSET),\n    DECIMAL128_LIST(CORE_TYPE_VALUE_DECIMAL128 + LIST_OFFSET),\n    OBJECT_ID_LIST(CORE_TYPE_VALUE_OBJECTID + LIST_OFFSET),\n    UUID_LIST(CORE_TYPE_VALUE_UUID + LIST_OFFSET),\n    MIXED_LIST(CORE_TYPE_VALUE_MIXED + LIST_OFFSET),\n\n    STRING_TO_INTEGER_MAP(CORE_TYPE_VALUE_INTEGER + DICTIONARY_OFFSET),\n    STRING_TO_BOOLEAN_MAP(CORE_TYPE_VALUE_BOOLEAN + DICTIONARY_OFFSET),\n    STRING_TO_STRING_MAP(CORE_TYPE_VALUE_STRING + DICTIONARY_OFFSET),\n    STRING_TO_BINARY_MAP(CORE_TYPE_VALUE_BINARY + DICTIONARY_OFFSET),\n    STRING_TO_DATE_MAP(CORE_TYPE_VALUE_DATE + DICTIONARY_OFFSET),\n    STRING_TO_FLOAT_MAP(CORE_TYPE_VALUE_FLOAT + DICTIONARY_OFFSET),\n    STRING_TO_DOUBLE_MAP(CORE_TYPE_VALUE_DOUBLE + DICTIONARY_OFFSET),\n    STRING_TO_DECIMAL128_MAP(CORE_TYPE_VALUE_DECIMAL128 + DICTIONARY_OFFSET),\n    STRING_TO_OBJECT_ID_MAP(CORE_TYPE_VALUE_OBJECTID + DICTIONARY_OFFSET),\n    STRING_TO_UUID_MAP(CORE_TYPE_VALUE_UUID + DICTIONARY_OFFSET),\n    STRING_TO_MIXED_MAP(CORE_TYPE_VALUE_MIXED + DICTIONARY_OFFSET),\n    STRING_TO_LINK_MAP(CORE_TYPE_VALUE_OBJECT + DICTIONARY_OFFSET),\n\n    INTEGER_SET(CORE_TYPE_VALUE_INTEGER + SET_OFFSET),\n    BOOLEAN_SET(CORE_TYPE_VALUE_BOOLEAN + SET_OFFSET),\n    STRING_SET(CORE_TYPE_VALUE_STRING + SET_OFFSET),\n    BINARY_SET(CORE_TYPE_VALUE_BINARY + SET_OFFSET),\n    DATE_SET(CORE_TYPE_VALUE_DATE + SET_OFFSET),\n    FLOAT_SET(CORE_TYPE_VALUE_FLOAT + SET_OFFSET),\n    DOUBLE_SET(CORE_TYPE_VALUE_DOUBLE + SET_OFFSET),\n    DECIMAL128_SET(CORE_TYPE_VALUE_DECIMAL128 + SET_OFFSET),\n    OBJECT_ID_SET(CORE_TYPE_VALUE_OBJECTID + SET_OFFSET),\n    UUID_SET(CORE_TYPE_VALUE_UUID + SET_OFFSET),\n    LINK_SET(CORE_TYPE_VALUE_OBJECT + SET_OFFSET),\n    MIXED_SET(CORE_TYPE_VALUE_MIXED + SET_OFFSET);\n\n\n    // Primitive array for fast mapping between between native values and their Realm type.\n    private static final RealmFieldType[] basicTypes = new RealmFieldType[MAX_CORE_TYPE_VALUE + 1];\n    private static final RealmFieldType[] listTypes = new RealmFieldType[MAX_CORE_TYPE_VALUE + 1];\n    private static final RealmFieldType[] mapTypes = new RealmFieldType[MAX_CORE_TYPE_VALUE + 1];\n    private static final RealmFieldType[] setTypes = new RealmFieldType[MAX_CORE_TYPE_VALUE + 1];\n\n    static {\n        for (RealmFieldType columnType : values()) {\n            final int nativeValue = columnType.nativeValue;\n            if (nativeValue < LIST_OFFSET) {\n                basicTypes[nativeValue] = columnType;\n            } else if (nativeValue < SET_OFFSET) {\n                listTypes[nativeValue - LIST_OFFSET] = columnType;\n            } else if (nativeValue < DICTIONARY_OFFSET) {\n                setTypes[nativeValue - SET_OFFSET] = columnType;\n            } else {\n                mapTypes[nativeValue - DICTIONARY_OFFSET] = columnType;\n            }\n        }\n    }\n\n    private final int nativeValue;\n\n    RealmFieldType(int nativeValue) {\n        this.nativeValue = nativeValue;\n    }\n\n    /**\n     * Returns the native value representing this type.\n     *\n     * @return the value used by the underlying storage engine to represent this type.\n     */\n    public int getNativeValue() {\n        return nativeValue;\n    }\n\n    /**\n     * Checks if the given Java object can be converted to the underlying Realm type.\n     *\n     * @param obj object to test compatibility on.\n     * @return {@code true} if object can be converted to the Realm type, {@code false} otherwise.\n     */\n    public boolean isValid(Object obj) {\n        switch (nativeValue) {\n            case CORE_TYPE_VALUE_INTEGER:\n                return (obj instanceof Long || obj instanceof Integer || obj instanceof Short || obj instanceof Byte);\n            case CORE_TYPE_VALUE_BOOLEAN:\n                return (obj instanceof Boolean);\n            case CORE_TYPE_VALUE_STRING:\n                return (obj instanceof String);\n            case CORE_TYPE_VALUE_BINARY:\n                return (obj instanceof byte[] || obj instanceof ByteBuffer);\n            case CORE_TYPE_VALUE_DATE:\n                return (obj instanceof java.util.Date);\n            case CORE_TYPE_VALUE_FLOAT:\n                return (obj instanceof Float);\n            case CORE_TYPE_VALUE_DOUBLE:\n                return (obj instanceof Double);\n            case CORE_TYPE_VALUE_DECIMAL128:\n                return (obj instanceof Decimal128);\n            case CORE_TYPE_VALUE_OBJECTID:\n                return (obj instanceof ObjectId);\n            case CORE_TYPE_VALUE_UUID:\n                return (obj instanceof java.util.UUID);\n            case CORE_TYPE_VALUE_MIXED:\n                return (obj instanceof RealmAny);\n            case CORE_TYPE_VALUE_OBJECT:\n            case CORE_TYPE_VALUE_LIST:\n            case CORE_TYPE_VALUE_LINKING_OBJECTS:\n            case CORE_TYPE_VALUE_INTEGER + LIST_OFFSET:\n            case CORE_TYPE_VALUE_BOOLEAN + LIST_OFFSET:\n            case CORE_TYPE_VALUE_STRING + LIST_OFFSET:\n            case CORE_TYPE_VALUE_BINARY + LIST_OFFSET:\n            case CORE_TYPE_VALUE_DATE + LIST_OFFSET:\n            case CORE_TYPE_VALUE_FLOAT + LIST_OFFSET:\n            case CORE_TYPE_VALUE_DOUBLE + LIST_OFFSET:\n            case CORE_TYPE_VALUE_DECIMAL128 + LIST_OFFSET:\n            case CORE_TYPE_VALUE_OBJECTID + LIST_OFFSET:\n            case CORE_TYPE_VALUE_UUID + LIST_OFFSET:\n            case CORE_TYPE_VALUE_MIXED + LIST_OFFSET:\n                return false;\n            case CORE_TYPE_VALUE_INTEGER + DICTIONARY_OFFSET:\n            case CORE_TYPE_VALUE_BOOLEAN + DICTIONARY_OFFSET:\n            case CORE_TYPE_VALUE_STRING + DICTIONARY_OFFSET:\n            case CORE_TYPE_VALUE_BINARY + DICTIONARY_OFFSET:\n            case CORE_TYPE_VALUE_DATE + DICTIONARY_OFFSET:\n            case CORE_TYPE_VALUE_FLOAT + DICTIONARY_OFFSET:\n            case CORE_TYPE_VALUE_DOUBLE + DICTIONARY_OFFSET:\n            case CORE_TYPE_VALUE_MIXED + DICTIONARY_OFFSET:\n            case CORE_TYPE_VALUE_OBJECTID + DICTIONARY_OFFSET:\n            case CORE_TYPE_VALUE_UUID + DICTIONARY_OFFSET:\n            case CORE_TYPE_VALUE_DECIMAL128 + DICTIONARY_OFFSET:\n            case CORE_TYPE_VALUE_OBJECT + DICTIONARY_OFFSET:\n                return false;\n            case CORE_TYPE_VALUE_INTEGER + SET_OFFSET:\n            case CORE_TYPE_VALUE_BOOLEAN + SET_OFFSET:\n            case CORE_TYPE_VALUE_STRING + SET_OFFSET:\n            case CORE_TYPE_VALUE_BINARY + SET_OFFSET:\n            case CORE_TYPE_VALUE_DATE + SET_OFFSET:\n            case CORE_TYPE_VALUE_FLOAT + SET_OFFSET:\n            case CORE_TYPE_VALUE_DOUBLE + SET_OFFSET:\n            case CORE_TYPE_VALUE_DECIMAL128 + SET_OFFSET:\n            case CORE_TYPE_VALUE_OBJECTID + SET_OFFSET:\n            case CORE_TYPE_VALUE_UUID + SET_OFFSET:\n            case CORE_TYPE_VALUE_OBJECT + SET_OFFSET:\n            case CORE_TYPE_VALUE_MIXED + SET_OFFSET:\n                return false;\n            default:\n                throw new RuntimeException(\"Unsupported Realm type:  \" + this);\n        }\n    }\n\n    /**\n     * Converts the underlying value used by the storage engine to the proper Realm type.\n     *\n     * @param value the value to convert\n     * @return the corresponding Realm type.\n     * @throws IllegalArgumentException if value isn't valid.\n     */\n    public static RealmFieldType fromNativeValue(int value) {\n        if (0 <= value && value < basicTypes.length) {\n            RealmFieldType e = basicTypes[value];\n            if (e != null) {\n                return e;\n            }\n        }\n        if (LIST_OFFSET <= value && value < SET_OFFSET) {\n            final int elementValue = value - LIST_OFFSET;\n            if (elementValue < listTypes.length) {\n                RealmFieldType e = listTypes[elementValue];\n                if (e != null) {\n                    return e;\n                }\n            }\n        }\n        if (SET_OFFSET <= value && value < DICTIONARY_OFFSET) {\n            final int elementValue = value - SET_OFFSET;\n            if (elementValue < setTypes.length) {\n                RealmFieldType e = setTypes[elementValue];\n                if (e != null) {\n                    return e;\n                }\n            }\n        }\n        if (DICTIONARY_OFFSET <= value) {\n            final int elementValue = value - DICTIONARY_OFFSET;\n            if (elementValue < mapTypes.length) {\n                RealmFieldType e = mapTypes[elementValue];\n                if (e != null) {\n                    return e;\n                }\n            }\n        }\n        throw new IllegalArgumentException(\"Invalid native Realm type: \" + value);\n    }\n}\n\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/RealmList.java",
    "content": "/*\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\npackage io.realm;\n\nimport org.bson.types.Decimal128;\nimport org.bson.types.ObjectId;\n\nimport java.util.AbstractList;\nimport java.util.ArrayList;\nimport java.util.Collection;\nimport java.util.Collections;\nimport java.util.ConcurrentModificationException;\nimport java.util.Date;\nimport java.util.Iterator;\nimport java.util.List;\nimport java.util.ListIterator;\nimport java.util.NoSuchElementException;\nimport java.util.UUID;\n\nimport javax.annotation.Nonnull;\nimport javax.annotation.Nullable;\n\nimport io.reactivex.Flowable;\nimport io.reactivex.Observable;\nimport io.realm.internal.Freezable;\nimport io.realm.internal.InvalidRow;\nimport io.realm.internal.OsList;\nimport io.realm.internal.OsResults;\nimport io.realm.internal.RealmObjectProxy;\nimport io.realm.rx.CollectionChange;\n\n\n/**\n * RealmList is used to model one-to-many relationships in a {@link io.realm.RealmObject}.\n * RealmList has two modes: A managed and unmanaged mode. In managed mode all objects are persisted inside a Realm, in\n * unmanaged mode it works as a normal ArrayList.\n * <p>\n * Only Realm can create managed RealmLists. Managed RealmLists will automatically update the content whenever the\n * underlying Realm is updated, and can only be accessed using the getter of a {@link io.realm.RealmObject}.\n * <p>\n * Unmanaged RealmLists can be created by the user and can contain both managed and unmanaged RealmObjects. This is\n * useful when dealing with JSON deserializers like GSON or other frameworks that inject values into a class.\n * Unmanaged elements in this list can be added to a Realm using the {@link Realm#copyToRealm(Iterable, ImportFlag...)} method.\n * <p>\n * {@link RealmList} can contain more elements than {@code Integer.MAX_VALUE}.\n * In that case, you can access only first {@code Integer.MAX_VALUE} elements in it.\n *\n * @param <E> the class of objects in list.\n */\npublic class RealmList<E> extends AbstractList<E> implements OrderedRealmCollection<E> {\n\n    private static final String ONLY_IN_MANAGED_MODE_MESSAGE = \"This method is only available in managed mode.\";\n    static final String ALLOWED_ONLY_FOR_REALM_MODEL_ELEMENT_MESSAGE = \"This feature is available only when the element type is implementing RealmModel.\";\n    private static final String REMOVE_OUTSIDE_TRANSACTION_ERROR = \"Objects can only be removed from inside a write transaction.\";\n\n    @Nullable\n    protected Class<E> clazz;\n    @Nullable\n    protected String className;\n\n    // Always null if RealmList is unmanaged, always non-null if managed.\n    private final ManagedListOperator<E> osListOperator;\n\n    /**\n     * The {@link BaseRealm} instance in which this list resides.\n     * <p>\n     * Warning: This field is only exposed for internal usage, and should not be used.\n     */\n    public final BaseRealm baseRealm;\n\n    private List<E> unmanagedList;\n\n    /**\n     * Creates a RealmList in unmanaged mode, where the elements are not controlled by a Realm.\n     * This effectively makes the RealmList function as a {@link java.util.ArrayList} and it is not possible to query\n     * the objects in this state.\n     * <p>\n     * Use {@link io.realm.Realm#copyToRealm(Iterable, ImportFlag...)} to properly persist its elements in Realm.\n     */\n    public RealmList() {\n        baseRealm = null;\n        osListOperator = null;\n        unmanagedList = new ArrayList<>();\n    }\n\n    /**\n     * Creates a RealmList in unmanaged mode with an initial list of elements.\n     * A RealmList in unmanaged mode function as a {@link java.util.ArrayList} and it is not possible to query the\n     * objects in this state.\n     * <p>\n     * Use {@link io.realm.Realm#copyToRealm(Iterable, ImportFlag...)} to properly persist all unmanaged elements in Realm.\n     *\n     * @param objects initial objects in the list.\n     */\n    public RealmList(E... objects) {\n        //noinspection ConstantConditions\n        if (objects == null) {\n            throw new IllegalArgumentException(\"The objects argument cannot be null\");\n        }\n        baseRealm = null;\n        osListOperator = null;\n        unmanagedList = new ArrayList<>(objects.length);\n        Collections.addAll(unmanagedList, objects);\n    }\n\n    /**\n     * Creates a RealmList from a OsList, so its elements are managed by Realm.\n     *\n     * @param clazz type of elements in the Array.\n     * @param osList backing {@link OsList}.\n     * @param baseRealm reference to Realm containing the data.\n     */\n    RealmList(Class<E> clazz, OsList osList, BaseRealm baseRealm) {\n        this.clazz = clazz;\n        osListOperator = getOperator(baseRealm, osList, clazz, null);\n        this.baseRealm = baseRealm;\n    }\n\n    RealmList(String className, OsList osList, BaseRealm baseRealm) {\n        this.baseRealm = baseRealm;\n        this.className = className;\n        osListOperator = getOperator(baseRealm, osList, null, className);\n    }\n\n    OsList getOsList() {\n        return osListOperator.getOsList();\n    }\n\n    long createAndAddEmbeddedObject() {\n        return osListOperator.getOsList().createAndAddEmbeddedObject();\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    @Override\n    public boolean isValid() {\n        if (baseRealm == null) {\n            return true;\n        }\n        //noinspection SimplifiableIfStatement\n        if (baseRealm.isClosed()) {\n            return false;\n        }\n        return isAttached();\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    @Override\n    public RealmList<E> freeze() {\n        if (isManaged()) {\n            if (!isValid()) {\n                throw new IllegalStateException(\"Only valid, managed RealmLists can be frozen.\");\n            }\n\n            BaseRealm frozenRealm = baseRealm.freeze();\n            OsList frozenList = getOsList().freeze(frozenRealm.sharedRealm);\n            if (className != null) {\n                return new RealmList<>(className, frozenList, frozenRealm);\n            } else {\n                return new RealmList<>(clazz, frozenList, frozenRealm);\n            }\n        } else {\n            throw new UnsupportedOperationException(ONLY_IN_MANAGED_MODE_MESSAGE);\n        }\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    @Override\n    public boolean isFrozen() {\n        return (baseRealm != null && baseRealm.isFrozen());\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    @Override\n    public boolean isManaged() {\n        return baseRealm != null;\n    }\n\n    private boolean isAttached() {\n        return osListOperator != null && osListOperator.isValid();\n    }\n\n    /**\n     * Inserts the specified object into this List at the specified location. The object is inserted before any previous\n     * element at the specified location. If the location is equal to the size of this List, the object is added at the\n     * end.\n     * <ol>\n     * <li><b>Unmanaged RealmLists</b>: It is possible to add both managed and unmanaged objects. If adding managed\n     * objects to an unmanaged RealmList they will not be copied to the Realm again if using\n     * {@link Realm#copyToRealm(RealmModel, ImportFlag...)} afterwards.</li>\n     * <li><b>Managed RealmLists</b>: It is possible to add unmanaged objects to a RealmList that is already managed. In\n     * that case the object will transparently be copied to Realm using {@link Realm#copyToRealm(RealmModel, ImportFlag...)}\n     * or {@link Realm#copyToRealmOrUpdate(RealmModel, ImportFlag...)} if it has a primary key.</li>\n     * </ol>\n     *\n     * @param location the index at which to insert.\n     * @param element the element to add.\n     * @throws IllegalStateException if Realm instance has been closed or container object has been removed.\n     * @throws IndexOutOfBoundsException if {@code location < 0 || location > size()}.\n     */\n    @Override\n    public void add(int location, @Nullable E element) {\n        //noinspection ConstantConditions\n        if (isManaged()) {\n            checkValidRealm();\n            osListOperator.insert(location, element);\n        } else {\n            unmanagedList.add(location, element);\n        }\n        modCount++;\n    }\n\n    /**\n     * Adds the specified object at the end of this List.\n     * <ol>\n     * <li><b>Unmanaged RealmLists</b>: It is possible to add both managed and unmanaged objects. If adding managed\n     * objects to an unmanaged RealmList they will not be copied to the Realm again if using\n     * {@link Realm#copyToRealm(RealmModel, ImportFlag...)} afterwards.</li>\n     * <li><b>Managed RealmLists</b>: It is possible to add unmanaged objects to a RealmList that is already managed. In\n     * that case the object will transparently be copied to Realm using {@link Realm#copyToRealm(RealmModel, ImportFlag...)}\n     * or {@link Realm#copyToRealmOrUpdate(RealmModel, ImportFlag...)} if it has a primary key.</li>\n     * </ol>\n     *\n     * @param object the object to add.\n     * @return always {@code true}.\n     * @throws IllegalStateException if Realm instance has been closed or parent object has been removed.\n     */\n    @Override\n    public boolean add(@Nullable E object) {\n        if (isManaged()) {\n            checkValidRealm();\n            osListOperator.append(object);\n        } else {\n            unmanagedList.add(object);\n        }\n        modCount++;\n        return true;\n    }\n\n    /**\n     * Replaces the element at the specified location in this list with the specified object.\n     * <ol>\n     * <li><b>Unmanaged RealmLists</b>: It is possible to add both managed and unmanaged objects. If adding managed\n     * objects to an unmanaged RealmList they will not be copied to the Realm again if using\n     * {@link Realm#copyToRealm(RealmModel, ImportFlag...)} afterwards.</li>\n     * <li><b>Managed RealmLists</b>: It is possible to add unmanaged objects to a RealmList that is already managed.\n     * In that case the object will transparently be copied to Realm using {@link Realm#copyToRealm(RealmModel, ImportFlag...)} or\n     * {@link Realm#copyToRealmOrUpdate(RealmModel, ImportFlag...)} if it has a primary key.</li>\n     * </ol>\n     *\n     * @param location the index at which to put the specified object.\n     * @param object the object to add.\n     * @return the previous element at the index.\n     * @throws IllegalStateException if Realm instance has been closed or parent object has been removed.\n     * @throws IndexOutOfBoundsException if {@code location < 0 || location >= size()}.\n     */\n    @Override\n    public E set(int location, @Nullable E object) {\n        E oldObject;\n        if (isManaged()) {\n            checkValidRealm();\n            oldObject = osListOperator.set(location, object);\n        } else {\n            oldObject = unmanagedList.set(location, object);\n        }\n        return oldObject;\n    }\n\n    /**\n     * Moves an object from one position to another, while maintaining a fixed sized list.\n     * RealmObjects will be shifted so no {@code null} values are introduced.\n     *\n     * @param oldPos index of RealmObject to move.\n     * @param newPos target position. If newPos &lt; oldPos the object at the location will be shifted to the right. If\n     * oldPos &lt; newPos, indexes &gt; oldPos will be shifted once to the left.\n     * @throws IllegalStateException if Realm instance has been closed or parent object has been removed.\n     * @throws java.lang.IndexOutOfBoundsException if any position is outside [0, size()].\n     */\n    public void move(int oldPos, int newPos) {\n        if (isManaged()) {\n            checkValidRealm();\n            osListOperator.move(oldPos, newPos);\n        } else {\n            final int listSize = unmanagedList.size();\n            if (oldPos < 0 || listSize <= oldPos) {\n                throw new IndexOutOfBoundsException(\"Invalid index \" + oldPos + \", size is \" + listSize);\n            }\n            if (newPos < 0 || listSize <= newPos) {\n                throw new IndexOutOfBoundsException(\"Invalid index \" + newPos + \", size is \" + listSize);\n            }\n            E object = unmanagedList.remove(oldPos);\n            unmanagedList.add(newPos, object);\n        }\n    }\n\n    /**\n     * Removes all elements from this list, leaving it empty. This method doesn't remove the objects from the Realm.\n     *\n     * @throws IllegalStateException if Realm instance has been closed or parent object has been removed.\n     * @see List#isEmpty\n     * @see List#size\n     * @see #deleteAllFromRealm()\n     */\n    @Override\n    public void clear() {\n        if (isManaged()) {\n            checkValidRealm();\n            osListOperator.removeAll();\n        } else {\n            unmanagedList.clear();\n        }\n        modCount++;\n    }\n\n    /**\n     * Removes the object at the specified location from this list.\n     *\n     * @param location the index of the object to remove.\n     * @return the removed object.\n     * @throws IllegalStateException if Realm instance has been closed or parent object has been removed.\n     * @throws IndexOutOfBoundsException if {@code location < 0 || location >= size()}.\n     */\n    @Override\n    public E remove(int location) {\n        E removedItem;\n        if (isManaged()) {\n            checkValidRealm();\n            removedItem = get(location);\n            osListOperator.remove(location);\n        } else {\n            removedItem = unmanagedList.remove(location);\n        }\n        modCount++;\n        return removedItem;\n    }\n\n    /**\n     * Removes one instance of the specified object from this {@code Collection} if one\n     * is contained. This implementation iterates over this\n     * {@code Collection} and tests each element {@code e} returned by the iterator,\n     * whether {@code e} is equal to the given object. If {@code object != null}\n     * then this test is performed using {@code object.equals(e)}, otherwise\n     * using {@code object == null}. If an element equal to the given object is\n     * found, then the {@code remove} method is called on the iterator and\n     * {@code true} is returned, {@code false} otherwise. If the iterator does\n     * not support removing elements, an {@code UnsupportedOperationException}\n     * is thrown.\n     *\n     * @param object the object to remove.\n     * @return {@code true} if this {@code Collection} is modified, {@code false} otherwise.\n     * @throws ClassCastException if the object passed is not of the correct type.\n     * @throws NullPointerException if {@code object} is {@code null}.\n     */\n    @Override\n    public boolean remove(@Nullable Object object) {\n        if (isManaged() && !baseRealm.isInTransaction()) {\n            throw new IllegalStateException(REMOVE_OUTSIDE_TRANSACTION_ERROR);\n        }\n        return super.remove(object);\n    }\n\n    /**\n     * Removes all occurrences in this {@code Collection} of each object in the\n     * specified {@code Collection}. After this method returns none of the\n     * elements in the passed {@code Collection} can be found in this {@code Collection}\n     * anymore.\n     * <p>\n     * This implementation iterates over the {@code Collection} and tests each\n     * element {@code e} returned by the iterator, whether it is contained in\n     * the specified {@code Collection}. If this test is positive, then the {@code\n     * remove} method is called on the iterator.\n     *\n     * @param collection the collection of objects to remove.\n     * @return {@code true} if this {@code Collection} is modified, {@code false} otherwise.\n     * @throws ClassCastException if one or more elements of {@code collection} isn't of the correct type.\n     * @throws NullPointerException if {@code collection} is {@code null}.\n     */\n    @Override\n    public boolean removeAll(Collection<?> collection) {\n        if (isManaged() && !baseRealm.isInTransaction()) {\n            throw new IllegalStateException(REMOVE_OUTSIDE_TRANSACTION_ERROR);\n        }\n        return super.removeAll(collection);\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    @Override\n    public boolean deleteFirstFromRealm() {\n        if (isManaged()) {\n            if (!osListOperator.isEmpty()) {\n                deleteFromRealm(0);\n                modCount++;\n                return true;\n            } else {\n                return false;\n            }\n        } else {\n            throw new UnsupportedOperationException(ONLY_IN_MANAGED_MODE_MESSAGE);\n        }\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    @Override\n    public boolean deleteLastFromRealm() {\n        if (isManaged()) {\n            if (!osListOperator.isEmpty()) {\n                osListOperator.deleteLast();\n                modCount++;\n                return true;\n            } else {\n                return false;\n            }\n        } else {\n            throw new UnsupportedOperationException(ONLY_IN_MANAGED_MODE_MESSAGE);\n        }\n    }\n\n    /**\n     * Returns the element at the specified location in this list.\n     *\n     * @param location the index of the element to return.\n     * @return the element at the specified index.\n     * @throws IllegalStateException if Realm instance has been closed or parent object has been removed.\n     * @throws IndexOutOfBoundsException if {@code location < 0 || location >= size()}.\n     */\n    @Override\n    @Nullable\n    public E get(int location) {\n        if (isManaged()) {\n            checkValidRealm();\n            return osListOperator.get(location);\n        } else {\n            return unmanagedList.get(location);\n        }\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    @Override\n    @Nullable\n    public E first() {\n        return firstImpl(true, null);\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    @Override\n    @Nullable\n    public E first(@Nullable E defaultValue) {\n        return firstImpl(false, defaultValue);\n    }\n\n    @Nullable\n    private E firstImpl(boolean shouldThrow, @Nullable E defaultValue) {\n        if (isManaged()) {\n            checkValidRealm();\n            if (!osListOperator.isEmpty()) {\n                return get(0);\n            }\n        } else if (unmanagedList != null && !unmanagedList.isEmpty()) {\n            return unmanagedList.get(0);\n        }\n\n        if (shouldThrow) {\n            throw new IndexOutOfBoundsException(\"The list is empty.\");\n        } else {\n            return defaultValue;\n        }\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    @Override\n    @Nullable\n    public E last() {\n        return lastImpl(true, null);\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    @Override\n    @Nullable\n    public E last(@Nullable E defaultValue) {\n        return lastImpl(false, defaultValue);\n    }\n\n    @Nullable\n    private E lastImpl(boolean shouldThrow, @Nullable E defaultValue) {\n        if (isManaged()) {\n            checkValidRealm();\n            if (!osListOperator.isEmpty()) {\n                return get(osListOperator.size() - 1);\n            }\n        } else if (unmanagedList != null && !unmanagedList.isEmpty()) {\n            return unmanagedList.get(unmanagedList.size() - 1);\n        }\n\n        if (shouldThrow) {\n            throw new IndexOutOfBoundsException(\"The list is empty.\");\n        } else {\n            return defaultValue;\n        }\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    @Override\n    public RealmResults<E> sort(String fieldName) {\n        return this.sort(fieldName, Sort.ASCENDING);\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    @Override\n    public RealmResults<E> sort(String fieldName, Sort sortOrder) {\n        if (isManaged()) {\n            return this.where().sort(fieldName, sortOrder).findAll();\n        } else {\n            throw new UnsupportedOperationException(ONLY_IN_MANAGED_MODE_MESSAGE);\n        }\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    @Override\n    public RealmResults<E> sort(String fieldName1, Sort sortOrder1, String fieldName2, Sort sortOrder2) {\n        return sort(new String[] {fieldName1, fieldName2}, new Sort[] {sortOrder1, sortOrder2});\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    @Override\n    public RealmResults<E> sort(String[] fieldNames, Sort[] sortOrders) {\n        if (isManaged()) {\n            return where().sort(fieldNames, sortOrders).findAll();\n        } else {\n            throw new UnsupportedOperationException(ONLY_IN_MANAGED_MODE_MESSAGE);\n        }\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    @Override\n    public void deleteFromRealm(int location) {\n        if (isManaged()) {\n            checkValidRealm();\n            osListOperator.delete(location);\n            modCount++;\n        } else {\n            throw new UnsupportedOperationException(ONLY_IN_MANAGED_MODE_MESSAGE);\n        }\n    }\n\n    /**\n     * Returns the number of elements in this {@code List}.\n     *\n     * @return the number of elements in this {@code List}.\n     * @throws IllegalStateException if Realm instance has been closed or parent object has been removed.\n     */\n    @Override\n    public int size() {\n        if (isManaged()) {\n            checkValidRealm();\n            return osListOperator.size();\n        } else {\n            return unmanagedList.size();\n        }\n    }\n\n    /**\n     * Returns a RealmQuery, which can be used to query for specific objects of this class.\n     *\n     * @return a RealmQuery object.\n     * @throws IllegalStateException if Realm instance has been closed or parent object has been removed.\n     * @see io.realm.RealmQuery\n     */\n    @Override\n    public RealmQuery<E> where() {\n        if (isManaged()) {\n            checkValidRealm();\n            if (!osListOperator.forRealmModel()) {\n                throw new UnsupportedOperationException(ALLOWED_ONLY_FOR_REALM_MODEL_ELEMENT_MESSAGE);\n            }\n            return RealmQuery.createQueryFromList(this);\n        } else {\n            throw new UnsupportedOperationException(ONLY_IN_MANAGED_MODE_MESSAGE);\n        }\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    @Override\n    @Nullable\n    public Number min(String fieldName) {\n        // where() throws if not managed\n        return where().min(fieldName);\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    @Override\n    @Nullable\n    public Number max(String fieldName) {\n        // where() throws if not managed\n        return this.where().max(fieldName);\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    @Override\n    public Number sum(String fieldName) {\n        // where() throws if not managed\n        return this.where().sum(fieldName);\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    @Override\n    public double average(String fieldName) {\n        // where() throws if not managed\n        return this.where().average(fieldName);\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    @Override\n    @Nullable\n    public Date maxDate(String fieldName) {\n        // where() throws if not managed\n        return this.where().maximumDate(fieldName);\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    @Override\n    @Nullable\n    public Date minDate(String fieldName) {\n        // where() throws if not managed\n        return this.where().minimumDate(fieldName);\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    @Override\n    public boolean deleteAllFromRealm() {\n        if (isManaged()) {\n            checkValidRealm();\n            if (!osListOperator.isEmpty()) {\n                osListOperator.deleteAll();\n                modCount++;\n                return true;\n            } else {\n                return false;\n            }\n        } else {\n            throw new UnsupportedOperationException(ONLY_IN_MANAGED_MODE_MESSAGE);\n        }\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    @Override\n    public boolean isLoaded() {\n        return true; // Managed RealmLists are always loaded, Unmanaged RealmLists return true pr. the contract.\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    @Override\n    public boolean load() {\n        return true; // Managed RealmLists are always loaded, Unmanaged RealmLists return true pr. the contract.\n    }\n\n    /**\n     * Returns {@code true} if the list contains the specified element when attached to a Realm. This\n     * method will query the native Realm underlying storage engine to quickly find the specified element.\n     * <p>\n     * If the list is not attached to a Realm, the default {@link List#contains(Object)}\n     * implementation will occur.\n     *\n     * @param object the element whose presence in this list is to be tested.\n     * @return {@code true} if this list contains the specified element otherwise {@code false}.\n     */\n    @Override\n    public boolean contains(@Nullable Object object) {\n        if (isManaged()) {\n            baseRealm.checkIfValid();\n\n            // Deleted objects can never be part of a RealmList\n            if (object instanceof RealmObjectProxy) {\n                RealmObjectProxy proxy = (RealmObjectProxy) object;\n                if (proxy.realmGet$proxyState().getRow$realm() == InvalidRow.INSTANCE) {\n                    return false;\n                }\n            }\n\n            return super.contains(object);\n        } else {\n            return unmanagedList.contains(object);\n        }\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    @Override\n    @Nonnull\n    public Iterator<E> iterator() {\n        if (isManaged()) {\n            return new RealmItr();\n        } else {\n            return super.iterator();\n        }\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    @Override\n    @Nonnull\n    public ListIterator<E> listIterator() {\n        return listIterator(0);\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    @Override\n    @Nonnull\n    public ListIterator<E> listIterator(int location) {\n        if (isManaged()) {\n            return new RealmListItr(location);\n        } else {\n            return super.listIterator(location);\n        }\n    }\n\n    private void checkValidRealm() {\n        baseRealm.checkIfValid();\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    @Override\n    public OrderedRealmCollectionSnapshot<E> createSnapshot() {\n        if (!isManaged()) {\n            throw new UnsupportedOperationException(ONLY_IN_MANAGED_MODE_MESSAGE);\n        }\n        checkValidRealm();\n        if (!osListOperator.forRealmModel()) {\n            throw new UnsupportedOperationException(ALLOWED_ONLY_FOR_REALM_MODEL_ELEMENT_MESSAGE);\n        }\n        if (className != null) {\n            return new OrderedRealmCollectionSnapshot<>(\n                    baseRealm,\n                    OsResults.createFromQuery(baseRealm.sharedRealm, osListOperator.getOsList().getQuery()),\n                    className);\n        } else {\n            // 'clazz' is non-null when 'dynamicClassName' is null.\n            //noinspection ConstantConditions\n            return new OrderedRealmCollectionSnapshot<>(\n                    baseRealm,\n                    OsResults.createFromQuery(baseRealm.sharedRealm, osListOperator.getOsList().getQuery()),\n                    clazz);\n        }\n    }\n\n    /**\n     * Returns the {@link Realm} instance to which this collection belongs.\n     * <p>\n     * Calling {@link Realm#close()} on the returned instance is discouraged as it is the same as\n     * calling it on the original Realm instance which may cause the Realm to fully close invalidating the\n     * list.\n     *\n     * @return {@link Realm} instance this collection belongs to or {@code null} if the collection is unmanaged.\n     * @throws IllegalStateException if the Realm is an instance of {@link DynamicRealm} or the\n     * {@link Realm} was already closed.\n     */\n    public Realm getRealm() {\n        if (baseRealm == null) {\n            return null;\n        }\n        baseRealm.checkIfValid();\n        if (!(baseRealm instanceof Realm)) {\n            throw new IllegalStateException(\"This method is only available for typed Realms\");\n        }\n        return (Realm) baseRealm;\n    }\n\n    @Override\n    public String toString() {\n        final String separator = \",\";\n        final StringBuilder sb = new StringBuilder();\n\n        if (!isManaged()) {\n            // Build String for unmanaged RealmList\n\n            // Unmanaged RealmList does not know actual element type.\n            sb.append(\"RealmList<?>@[\");\n            // Print list values\n            final int size = size();\n            for (int i = 0; i < size; i++) {\n                final E value = get(i);\n                if (value instanceof RealmModel) {\n                    sb.append(System.identityHashCode(value));\n                } else {\n                    if (value instanceof byte[]) {\n                        sb.append(\"byte[\").append(((byte[]) value).length).append(\"]\");\n                    } else {\n                        sb.append(value);\n                    }\n                }\n                sb.append(separator);\n            }\n            if (0 < size()) {\n                sb.setLength(sb.length() - separator.length());\n            }\n            sb.append(\"]\");\n        } else {\n            // Build String for managed RealmList\n\n            // Determines type of List\n            sb.append(\"RealmList<\");\n            if (className != null) {\n                sb.append(className);\n            } else {\n                // 'clazz' is non-null when 'dynamicClassName' is null.\n                //noinspection ConstantConditions,unchecked\n                if (isClassForRealmModel(clazz)) {\n                    //noinspection ConstantConditions,unchecked\n                    sb.append(baseRealm.getSchema().getSchemaForClass((Class<RealmModel>) clazz).getClassName());\n                } else {\n                    if (clazz == byte[].class) {\n                        sb.append(clazz.getSimpleName());\n                    } else {\n                        sb.append(clazz.getName());\n                    }\n                }\n            }\n            sb.append(\">@[\");\n\n            //Print list values\n            if (!isAttached()) {\n                sb.append(\"invalid\");\n            } else if (isClassForRealmModel(clazz)) {\n                for (int i = 0; i < size(); i++) {\n                    //noinspection ConstantConditions\n                    sb.append(((RealmObjectProxy) get(i)).realmGet$proxyState().getRow$realm().getObjectKey());\n                    sb.append(separator);\n                }\n                if (0 < size()) {\n                    sb.setLength(sb.length() - separator.length());\n                }\n            } else {\n                for (int i = 0; i < size(); i++) {\n                    final E value = get(i);\n                    if (value instanceof byte[]) {\n                        sb.append(\"byte[\").append(((byte[]) value).length).append(\"]\");\n                    } else {\n                        sb.append(value);\n                    }\n                    sb.append(separator);\n                }\n                if (0 < size()) {\n                    sb.setLength(sb.length() - separator.length());\n                }\n            }\n            sb.append(\"]\");\n        }\n        return sb.toString();\n    }\n\n    /**\n     * Returns an Rx Flowable that monitors changes to this RealmList. It will emit the current RealmList when\n     * subscribed to. RealmList will continually be emitted as the RealmList is updated -\n     * {@code onComplete} will never be called.\n     * <p>\n     * Items emitted from Realm Flowables are frozen (See {@link #freeze()}. This means that they\n     * are immutable and can be read on any thread.\n     * <p>\n     * Realm Flowables always emit items from the thread holding the live RealmList. This means that if\n     * you need to do further processing, it is recommend to observe the values on a computation\n     * scheduler:\n     * <p>\n     * {@code\n     * list.asFlowable()\n     *   .observeOn(Schedulers.computation())\n     *   .map(rxResults -> doExpensiveWork(rxResults))\n     *   .observeOn(AndroidSchedulers.mainThread())\n     *   .subscribe( ... );\n     * }\n     * <p>\n     * If you would like the {@code asFlowable()} to stop emitting items you can instruct RxJava to\n     * only emit only the first item by using the {@code first()} operator:\n     * <p>\n     * <pre>\n     * {@code\n     * list.asFlowable()\n     *      .first()\n     *      .subscribe( ... ) // You only get the results once\n     * }\n     * </pre>\n     * <p>\n     *\n     * @return RxJava Observable that only calls {@code onNext}. It will never call {@code onComplete} or {@code OnError}.\n     * @throws UnsupportedOperationException if the required RxJava framework is not on the classpath or the\n     * corresponding Realm instance doesn't support RxJava.\n     * @see <a href=\"https://github.com/realm/realm-java/tree/master/examples/rxJavaExample\">RxJava and Realm</a>\n     */\n    @SuppressWarnings(\"unchecked\")\n    public Flowable<RealmList<E>> asFlowable() {\n        if (baseRealm instanceof Realm) {\n            return baseRealm.configuration.getRxFactory().from((Realm) baseRealm, this);\n        } else if (baseRealm instanceof DynamicRealm) {\n            @SuppressWarnings(\"UnnecessaryLocalVariable\")\n            Flowable<RealmList<E>> results = baseRealm.configuration.getRxFactory().from((DynamicRealm) baseRealm, this);\n            return results;\n        } else {\n            throw new UnsupportedOperationException(baseRealm.getClass() + \" does not support RxJava2.\");\n        }\n    }\n\n    /**\n     * Returns an Rx Observable that monitors changes to this RealmList. It will emit the current RealmList when\n     * subscribed. For each update to the RealmList a pair consisting of the RealmList and the\n     * {@link OrderedCollectionChangeSet} will be sent. The changeset will be {@code null} the first\n     * time an RealmList is emitted.\n     * <p>\n     * RealmList will continually be emitted as the RealmList is updated - {@code onComplete} will never be called.\n     * <p>\n     * Items emitted from Realm Observables are frozen (See {@link #freeze()}. This means that they\n     * are immutable and can be read on any thread.\n     * <p>\n     * Realm Observables always emit items from the thread holding the live Realm. This means that if\n     * you need to do further processing, it is recommend to observe the values on a computation\n     * scheduler:\n     * <p>\n     * {@code\n     * list.asChangesetObservable()\n     *   .observeOn(Schedulers.computation())\n     *   .map((rxList, changes) -> doExpensiveWork(rxList, changes))\n     *   .observeOn(AndroidSchedulers.mainThread())\n     *   .subscribe( ... );\n     * }\n     *\n     * @return RxJava Observable that only calls {@code onNext}. It will never call {@code onComplete} or {@code OnError}.\n     * @throws UnsupportedOperationException if the required RxJava framework is not on the classpath or the\n     * corresponding Realm instance doesn't support RxJava.\n     * @throws IllegalStateException if the Realm wasn't opened on a Looper thread.\n     * @see <a href=\"https://github.com/realm/realm-java/tree/master/examples/rxJavaExample\">RxJava and Realm</a>\n     */\n    public Observable<CollectionChange<RealmList<E>>> asChangesetObservable() {\n        if (baseRealm instanceof Realm) {\n            return baseRealm.configuration.getRxFactory().changesetsFrom((Realm) baseRealm, this);\n        } else if (baseRealm instanceof DynamicRealm) {\n            DynamicRealm dynamicRealm = (DynamicRealm) baseRealm;\n            RealmList<DynamicRealmObject> dynamicResults = (RealmList<DynamicRealmObject>) this;\n            return (Observable) baseRealm.configuration.getRxFactory().changesetsFrom(dynamicRealm, dynamicResults);\n        } else {\n            throw new UnsupportedOperationException(baseRealm.getClass() + \" does not support RxJava2.\");\n        }\n    }\n\n    /**\n     * Adds a change listener to this {@link RealmList}.\n     * <p>\n     * Registering a change listener will not prevent the underlying RealmList from being garbage collected.\n     * If the RealmList is garbage collected, the change listener will stop being triggered. To avoid this, keep a\n     * strong reference for as long as appropriate e.g. in a class variable.\n     * <p>\n     * <pre>\n     * {@code\n     * public class MyActivity extends Activity {\n     *\n     *     private RealmList<Dog> dogs; // Strong reference to keep listeners alive\n     *\n     *     \\@Override\n     *     protected void onCreate(Bundle savedInstanceState) {\n     *       super.onCreate(savedInstanceState);\n     *       dogs = realm.where(Person.class).findFirst().getDogs();\n     *       dogs.addChangeListener(new OrderedRealmCollectionChangeListener<RealmList<Dog>>() {\n     *           \\@Override\n     *           public void onChange(RealmList<Dog> dogs, OrderedCollectionChangeSet changeSet) {\n     *               // React to change\n     *           }\n     *       });\n     *     }\n     * }\n     * }\n     * </pre>\n     *\n     * @param listener the change listener to be notified.\n     * @throws IllegalArgumentException if the change listener is {@code null}.\n     * @throws IllegalStateException if you try to add a listener from a non-Looper or\n     * {@link android.app.IntentService} thread.\n     */\n    public void addChangeListener(OrderedRealmCollectionChangeListener<RealmList<E>> listener) {\n        CollectionUtils.checkForAddRemoveListener(baseRealm, listener, true);\n        osListOperator.getOsList().addListener(this, listener);\n    }\n\n    /**\n     * Removes the specified change listener.\n     *\n     * @param listener the change listener to be removed.\n     * @throws IllegalArgumentException if the change listener is {@code null}.\n     * @throws IllegalStateException if you try to remove a listener from a non-Looper Thread.\n     * @see io.realm.RealmChangeListener\n     */\n    public void removeChangeListener(OrderedRealmCollectionChangeListener<RealmList<E>> listener) {\n        CollectionUtils.checkForAddRemoveListener(baseRealm, listener, true);\n        osListOperator.getOsList().removeListener(this, listener);\n    }\n\n    /**\n     * Adds a change listener to this {@link RealmList}.\n     * <p>\n     * Registering a change listener will not prevent the underlying RealmList from being garbage collected.\n     * If the RealmList is garbage collected, the change listener will stop being triggered. To avoid this, keep a\n     * strong reference for as long as appropriate e.g. in a class variable.\n     * <p>\n     * <pre>\n     * {@code\n     * public class MyActivity extends Activity {\n     *\n     *     private RealmList<Dog> dogs; // Strong reference to keep listeners alive\n     *\n     *     \\@Override\n     *     protected void onCreate(Bundle savedInstanceState) {\n     *       super.onCreate(savedInstanceState);\n     *       dogs = realm.where(Person.class).findFirst().getDogs();\n     *       dogs.addChangeListener(new RealmChangeListener<RealmList<Dog>>() {\n     *           \\@Override\n     *           public void onChange(RealmList<Dog> dogs) {\n     *               // React to change\n     *           }\n     *       });\n     *     }\n     * }\n     * }\n     * </pre>\n     *\n     * @param listener the change listener to be notified.\n     * @throws IllegalArgumentException if the change listener is {@code null}.\n     * @throws IllegalStateException if you try to add a listener from a non-Looper or\n     * {@link android.app.IntentService} thread.\n     */\n    public void addChangeListener(RealmChangeListener<RealmList<E>> listener) {\n        CollectionUtils.checkForAddRemoveListener(baseRealm, listener, true);\n        osListOperator.getOsList().addListener(this, listener);\n    }\n\n    /**\n     * Removes the specified change listener.\n     *\n     * @param listener the change listener to be removed.\n     * @throws IllegalArgumentException if the change listener is {@code null}.\n     * @throws IllegalStateException if you try to remove a listener from a non-Looper Thread.\n     * @see io.realm.RealmChangeListener\n     */\n    public void removeChangeListener(RealmChangeListener<RealmList<E>> listener) {\n        CollectionUtils.checkForAddRemoveListener(baseRealm, listener, true);\n        osListOperator.getOsList().removeListener(this, listener);\n    }\n\n    /**\n     * Removes all user-defined change listeners.\n     *\n     * @throws IllegalStateException if you try to remove listeners from a non-Looper Thread.\n     * @see io.realm.RealmChangeListener\n     */\n    public void removeAllChangeListeners() {\n        CollectionUtils.checkForAddRemoveListener(baseRealm, null, false);\n        osListOperator.getOsList().removeAllListeners();\n    }\n\n    // Custom RealmList iterator.\n    private class RealmItr implements Iterator<E> {\n        /**\n         * Index of element to be returned by subsequent call to next.\n         */\n        int cursor = 0;\n\n        /**\n         * Index of element returned by most recent call to next or\n         * previous. Resets to -1 if this element is deleted by a call\n         * to remove.\n         */\n        int lastRet = -1;\n\n        /**\n         * The modCount value that the iterator believes that the backing\n         * List should have. If this expectation is violated, the iterator\n         * has detected concurrent modification.\n         */\n        int expectedModCount = modCount;\n\n        /**\n         * {@inheritDoc}\n         */\n        @Override\n        public boolean hasNext() {\n            checkValidRealm();\n            checkConcurrentModification();\n            return cursor != size();\n        }\n\n        /**\n         * {@inheritDoc}\n         */\n        @Override\n        @Nullable\n        public E next() {\n            checkValidRealm();\n            checkConcurrentModification();\n            int i = cursor;\n            try {\n                E next = get(i);\n                lastRet = i;\n                cursor = i + 1;\n                return next;\n            } catch (IndexOutOfBoundsException e) {\n                checkConcurrentModification();\n                throw new NoSuchElementException(\"Cannot access index \" + i + \" when size is \" + size() + \". Remember to check hasNext() before using next().\");\n            }\n        }\n\n        /**\n         * {@inheritDoc}\n         */\n        @Override\n        public void remove() {\n            checkValidRealm();\n            if (lastRet < 0) {\n                throw new IllegalStateException(\"Cannot call remove() twice. Must call next() in between.\");\n            }\n            checkConcurrentModification();\n\n            try {\n                RealmList.this.remove(lastRet);\n                if (lastRet < cursor) {\n                    cursor--;\n                }\n                lastRet = -1;\n                expectedModCount = modCount;\n            } catch (IndexOutOfBoundsException e) {\n                throw new ConcurrentModificationException();\n            }\n        }\n\n        final void checkConcurrentModification() {\n            // A Realm ListView is backed by the original Table and not a TableView, this means\n            // that all changes are reflected immediately. It is therefore not possible to use\n            // the same version pinning trick we use for RealmResults (avoiding calling sync_if_needed)\n            // Fortunately a LinkView does not change unless manually altered (unlike RealmResults)\n            // So therefore it should be acceptable to use the same heuristic as a normal AbstractList\n            // when detecting concurrent modifications.\n            if (modCount != expectedModCount) {\n                throw new ConcurrentModificationException();\n            }\n        }\n    }\n\n    private class RealmListItr extends RealmItr implements ListIterator<E> {\n\n        RealmListItr(int index) {\n            if (index >= 0 && index <= size()) {\n                cursor = index;\n            } else {\n                throw new IndexOutOfBoundsException(\"Starting location must be a valid index: [0, \" + (size() - 1) + \"]. Index was \" + index);\n            }\n        }\n\n        /**\n         * {@inheritDoc}\n         */\n        @Override\n        public boolean hasPrevious() {\n            return cursor != 0;\n        }\n\n        /**\n         * {@inheritDoc}\n         */\n        @Override\n        @Nullable\n        public E previous() {\n            checkConcurrentModification();\n            int i = cursor - 1;\n            try {\n                E previous = get(i);\n                lastRet = cursor = i;\n                return previous;\n            } catch (IndexOutOfBoundsException e) {\n                checkConcurrentModification();\n                throw new NoSuchElementException(\"Cannot access index less than zero. This was \" + i + \". Remember to check hasPrevious() before using previous().\");\n            }\n        }\n\n        /**\n         * {@inheritDoc}\n         */\n        @Override\n        public int nextIndex() {\n            return cursor;\n        }\n\n        /**\n         * {@inheritDoc}\n         */\n        @Override\n        public int previousIndex() {\n            return cursor - 1;\n        }\n\n        /**\n         * {@inheritDoc}\n         */\n        @Override\n        public void set(@Nullable E e) {\n            baseRealm.checkIfValid();\n            if (lastRet < 0) {\n                throw new IllegalStateException();\n            }\n            checkConcurrentModification();\n\n            try {\n                RealmList.this.set(lastRet, e);\n                expectedModCount = modCount;\n            } catch (IndexOutOfBoundsException ex) {\n                throw new ConcurrentModificationException();\n            }\n        }\n\n        /**\n         * Adding a new object to the RealmList. If the object is not already manage by Realm it will be transparently\n         * copied using {@link Realm#copyToRealmOrUpdate(RealmModel, ImportFlag...)}\n         *\n         * @see #add(Object)\n         */\n        @Override\n        public void add(@Nullable E e) {\n            baseRealm.checkIfValid();\n            checkConcurrentModification();\n            try {\n                int i = cursor;\n                RealmList.this.add(i, e);\n                lastRet = -1;\n                cursor = i + 1;\n                expectedModCount = modCount;\n            } catch (IndexOutOfBoundsException ex) {\n                throw new ConcurrentModificationException();\n            }\n        }\n    }\n\n    private static boolean isClassForRealmModel(Class<?> clazz) {\n        return RealmModel.class.isAssignableFrom(clazz);\n    }\n\n    private ManagedListOperator<E> getOperator(BaseRealm realm, OsList osList, @Nullable Class<E> clazz, @Nullable String className) {\n        if (clazz == null || isClassForRealmModel(clazz)) {\n            return new RealmModelListOperator<>(realm, osList, clazz, className);\n        }\n        if (clazz == String.class) {\n            //noinspection unchecked\n            return (ManagedListOperator<E>) new StringListOperator(realm, osList, (Class<String>) clazz);\n        }\n        if (clazz == Long.class || clazz == Integer.class || clazz == Short.class || clazz == Byte.class) {\n            return new LongListOperator<>(realm, osList, clazz);\n        }\n        if (clazz == Boolean.class) {\n            //noinspection unchecked\n            return (ManagedListOperator<E>) new BooleanListOperator(realm, osList, (Class<Boolean>) clazz);\n        }\n        if (clazz == byte[].class) {\n            //noinspection unchecked\n            return (ManagedListOperator<E>) new BinaryListOperator(realm, osList, (Class<byte[]>) clazz);\n        }\n        if (clazz == Double.class) {\n            //noinspection unchecked\n            return (ManagedListOperator<E>) new DoubleListOperator(realm, osList, (Class<Double>) clazz);\n        }\n        if (clazz == Float.class) {\n            //noinspection unchecked\n            return (ManagedListOperator<E>) new FloatListOperator(realm, osList, (Class<Float>) clazz);\n        }\n        if (clazz == Date.class) {\n            //noinspection unchecked\n            return (ManagedListOperator<E>) new DateListOperator(realm, osList, (Class<Date>) clazz);\n        }\n        if (clazz == Decimal128.class) {\n            //noinspection unchecked\n            return (ManagedListOperator<E>) new Decimal128ListOperator(realm, osList, (Class<Decimal128>) clazz);\n        }\n        if (clazz == ObjectId.class) {\n            //noinspection unchecked\n            return (ManagedListOperator<E>) new ObjectIdListOperator(realm, osList, (Class<ObjectId>) clazz);\n        }\n        if (clazz == UUID.class) {\n            //noinspection unchecked\n            return (ManagedListOperator<E>) new UUIDListOperator(realm, osList, (Class<UUID>) clazz);\n        }\n        if (clazz == RealmAny.class) {\n            //noinspection unchecked\n            return (ManagedListOperator<E>) new RealmAnyListOperator(realm, osList, (Class<RealmAny>) clazz);\n        }\n        throw new IllegalArgumentException(\"Unexpected value class: \" + clazz.getName());\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/RealmMap.java",
    "content": "/*\n * Copyright 2020 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\npackage io.realm;\n\nimport java.util.Collection;\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.Set;\n\nimport javax.annotation.Nullable;\n\nimport io.realm.internal.Freezable;\nimport io.realm.internal.ManageableObject;\nimport io.realm.internal.OsMap;\n\n/**\n * RealmMap is used to map keys to values. A RealmMap cannot contain duplicate keys and each key can\n * map to at most one value. A RealmMap cannot have {@code null} keys but can have {@code null}\n * values.\n * <p>\n * Similarly to {@link RealmList}s, a RealmDictionary can operate in managed and unmanaged modes. In\n * managed mode a RealmDictionary persists all its contents inside a Realm whereas in unmanaged mode\n * it functions like a {@link HashMap}.\n * <p>\n * Managed RealmDictionaries can only be created by Realm and will automatically update its content\n * whenever the underlying Realm is updated. Managed RealmDictionaries can only be accessed using\n * the getter that points to a RealmDictionary field of a {@link RealmObject}.\n * <p>\n * Unmanaged RealmDictionaries can be created by the user and can contain both managed and unmanaged\n * RealmObjects. This is useful when dealing with JSON deserializers like GSON or other frameworks\n * that inject values into a class. Unmanaged RealmMaps can be added to a Realm using the\n * {@link Realm#copyToRealm(Iterable, ImportFlag...)} method.\n *\n * @param <K> the type of the keys stored in this map\n * @param <V> the type of the values stored in this map\n */\npublic abstract class RealmMap<K, V> implements Map<K, V>, ManageableObject, Freezable<RealmMap<K, V>> {\n\n    protected final MapStrategy<K, V> mapStrategy;\n\n    // ------------------------------------------\n    // Unmanaged constructors\n    // ------------------------------------------\n\n    /**\n     * Instantiates a RealmMap in unmanaged mode.\n     */\n    protected RealmMap() {\n        this.mapStrategy = new UnmanagedMapStrategy<>();\n    }\n\n    /**\n     * Instantiates a RealmMap in unmanaged mode with an initial map.\n     *\n     * @param map initial map.\n     */\n    RealmMap(Map<K, V> map) {\n        this();\n\n        mapStrategy.putAll(map);\n    }\n\n    // ------------------------------------------\n    // Managed constructors\n    // ------------------------------------------\n\n    RealmMap(MapStrategy<K, V> mapStrategy) {\n        this.mapStrategy = mapStrategy;\n    }\n\n    // ------------------------------------------\n    // ManageableObject API\n    // ------------------------------------------\n\n    /**\n     * {@inheritDoc}\n     */\n    @Override\n    public boolean isManaged() {\n        return mapStrategy.isManaged();\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    @Override\n    public boolean isValid() {\n        return mapStrategy.isValid();\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    @Override\n    public boolean isFrozen() {\n        return mapStrategy.isFrozen();\n    }\n\n    // ------------------------------------------\n    // Map API\n    // ------------------------------------------\n\n    @Override\n    public int size() {\n        return mapStrategy.size();\n    }\n\n    @Override\n    public boolean isEmpty() {\n        return mapStrategy.isEmpty();\n    }\n\n    @Override\n    public boolean containsKey(@Nullable Object key) {\n        return mapStrategy.containsKey(key);\n    }\n\n    @Override\n    public boolean containsValue(@Nullable Object value) {\n        return mapStrategy.containsValue(value);\n    }\n\n    @Override\n    public V get(Object key) {\n        return mapStrategy.get(key);\n    }\n\n    @Override\n    public V put(K key, @Nullable V value) {\n        return mapStrategy.put(key, value);\n    }\n\n    @Override\n    public V remove(Object key) {\n        return mapStrategy.remove(key);\n    }\n\n    @Override\n    public void putAll(Map<? extends K, ? extends V> m) {\n        mapStrategy.putAll(m);\n    }\n\n    @Override\n    public void clear() {\n        mapStrategy.clear();\n    }\n\n    @Override\n    public Set<K> keySet() {\n        return mapStrategy.keySet();\n    }\n\n    @Override\n    public Collection<V> values() {\n        return mapStrategy.values();\n    }\n\n    @Override\n    public Set<Entry<K, V>> entrySet() {\n        return mapStrategy.entrySet();\n    }\n\n    // ------------------------------------------\n    // Freezable API\n    // ------------------------------------------\n\n    @Override\n    public RealmMap<K, V> freeze() {\n        return mapStrategy.freeze();\n    }\n\n    // ------------------------------------------\n    // RealmMap API\n    // ------------------------------------------\n\n    /**\n     * Adds a change listener to this {@link RealmMap}.\n     * <p>\n     * Registering a change listener will not prevent the underlying RealmMap from being garbage\n     * collected. If the RealmMap is garbage collected, the change listener will stop being\n     * triggered. To avoid this, keep a strong reference for as long as appropriate e.g. in a class\n     * variable.\n     * <p>\n     * <pre>\n     * {@code\n     * public class MyActivity extends Activity {\n     *\n     *     private RealmMap<String, Dog> dogs; // Strong reference to keep listeners alive\n     *\n     *     \\@Override\n     *     protected void onCreate(Bundle savedInstanceState) {\n     *       super.onCreate(savedInstanceState);\n     *       dogs = realm.where(Person.class).findFirst().getDogs();\n     *       dogs.addChangeListener(new MapChangeListener<String, Dog>() {\n     *           \\@Override\n     *           public void onChange(RealmMap<String, Dog> map, MapChangeSet<String> changeSet) {\n     *               // React to change\n     *           }\n     *       });\n     *     }\n     * }\n     * }\n     * </pre>\n     *\n     * @param listener the change listener to be notified.\n     * @throws IllegalArgumentException if the change listener is {@code null}.\n     * @throws IllegalStateException    if you try to add a listener from a non-Looper or\n     *                                  {@link android.app.IntentService} thread.\n     */\n    public void addChangeListener(MapChangeListener<K, V> listener) {\n        mapStrategy.addChangeListener(this, listener);\n    }\n\n    /**\n     * Adds a change listener to this {@link RealmMap}.\n     * <p>\n     * Registering a change listener will not prevent the underlying RealmMap from being garbage\n     * collected. If the RealmMap is garbage collected, the change listener will stop being\n     * triggered. To avoid this, keep a strong reference for as long as appropriate e.g. in a class\n     * variable.\n     * <p>\n     * <pre>\n     * {@code\n     * public class MyActivity extends Activity {\n     *\n     *     private RealmMap<String, Dog> dogs; // Strong reference to keep listeners alive\n     *\n     *     \\@Override\n     *     protected void onCreate(Bundle savedInstanceState) {\n     *       super.onCreate(savedInstanceState);\n     *       dogs = realm.where(Person.class).findFirst().getDogs();\n     *       dogs.addChangeListener(new RealmChangeListener<RealmMap<String, Dog>>() {\n     *           \\@Override\n     *           public void onChange(RealmMap<String, Dog> map) {\n     *               // React to change\n     *           }\n     *       });\n     *     }\n     * }\n     * }\n     * </pre>\n     *\n     * @param listener the change listener to be notified.\n     * @throws IllegalArgumentException if the change listener is {@code null}.\n     * @throws IllegalStateException    if you try to add a listener from a non-Looper or\n     *                                  {@link android.app.IntentService} thread.\n     * @see io.realm.RealmChangeListener\n     */\n    public void addChangeListener(RealmChangeListener<RealmMap<K, V>> listener) {\n        mapStrategy.addChangeListener(this, listener);\n    }\n\n    /**\n     * Removes the specified change listener.\n     *\n     * @param listener the change listener to be removed.\n     * @throws IllegalArgumentException if the change listener is {@code null}.\n     * @throws IllegalStateException    if you try to remove a listener from a non-Looper Thread.\n     */\n    public void removeChangeListener(MapChangeListener<K, V> listener) {\n        mapStrategy.removeChangeListener(this, listener);\n    }\n\n    /**\n     * Removes the specified change listener.\n     *\n     * @param listener the change listener to be removed.\n     * @throws IllegalArgumentException if the change listener is {@code null}.\n     * @throws IllegalStateException    if you try to remove a listener from a non-Looper Thread.\n     * @see io.realm.RealmChangeListener\n     */\n    public void removeChangeListener(RealmChangeListener<RealmMap<K, V>> listener) {\n        mapStrategy.removeChangeListener(this, listener);\n    }\n\n    /**\n     * Removes all user-defined change listeners.\n     *\n     * @throws IllegalStateException if you try to remove listeners from a non-Looper Thread.\n     * @see io.realm.RealmChangeListener\n     */\n    public void removeAllChangeListeners() {\n        mapStrategy.removeAllChangeListeners();\n    }\n\n    boolean hasListeners() {\n        return mapStrategy.hasListeners();\n    }\n\n    OsMap getOsMap() {\n        return mapStrategy.getOsMap();\n    }\n\n    String getValueClassName() {\n        return mapStrategy.getValueClassName();\n    }\n\n    Class<V> getValueClass() {\n        return mapStrategy.getValueClass();\n    }\n\n    /**\n     * Strategy responsible for abstracting the managed/unmanaged logic for maps.\n     *\n     * @param <K> the type of the keys stored in this map\n     * @param <V> the type of the values stored in this map\n     */\n    abstract static class MapStrategy<K, V> implements Map<K, V>, ManageableObject, Freezable<RealmMap<K, V>> {\n\n        // ------------------------------------------\n        // ManageableObject API\n        // ------------------------------------------\n\n        /**\n         * Internal method which checks for invalid input when calling {@link RealmMap#put(Object, Object)}.\n         *\n         * @param key   the key to insert.\n         * @param value the value to insert.\n         * @return the inserted value.\n         */\n        abstract V putInternal(K key, @Nullable V value);\n\n        abstract void addChangeListener(RealmMap<K, V> realmMap, MapChangeListener<K, V> listener);\n\n        abstract void addChangeListener(RealmMap<K, V> realmMap, RealmChangeListener<RealmMap<K, V>> listener);\n\n        abstract void removeChangeListener(RealmMap<K, V> realmMap, MapChangeListener<K, V> listener);\n\n        abstract void removeChangeListener(RealmMap<K, V> realmMap, RealmChangeListener<RealmMap<K, V>> listener);\n\n        abstract void removeAllChangeListeners();\n\n        abstract boolean hasListeners();\n\n        abstract OsMap getOsMap();\n\n        abstract String getValueClassName();\n\n        abstract Class<V> getValueClass();\n\n        // ------------------------------------------\n        // Map API\n        // ------------------------------------------\n\n        @Override\n        public V put(K key, V value) {\n            checkValidKey(key);\n            return putInternal(key, value);\n        }\n\n        protected void checkValidKey(K key) {\n            if (key == null) {\n                // As per Map interface\n                throw new NullPointerException(\"Null keys are not allowed.\");\n            }\n\n            if (key.getClass() == String.class) {\n                String stringKey = (String) key;\n                if (stringKey.contains(\".\") || stringKey.contains(\"$\")) {\n                    throw new IllegalArgumentException(\"Keys containing dots ('.') or dollar signs ('$') are not allowed.\");\n                }\n            }\n        }\n    }\n\n    /**\n     * Concrete {@link MapStrategy} that works for managed {@link io.realm.RealmMap}s.\n     *\n     * @param <K> the key type\n     * @param <V> the value type\n     */\n    static class ManagedMapStrategy<K, V> extends MapStrategy<K, V> {\n\n        private final ManagedMapManager<K, V> managedMapManager;\n\n        /**\n         * Strategy constructor for managed maps.\n         *\n         * @param managedMapManager the manager used by the managed map\n         */\n        ManagedMapStrategy(ManagedMapManager<K, V> managedMapManager) {\n            this.managedMapManager = managedMapManager;\n        }\n\n        // ------------------------------------------\n        // ManageableObject API\n        // ------------------------------------------\n\n        @Override\n        public boolean isManaged() {\n            return managedMapManager.isManaged();\n        }\n\n        @Override\n        public boolean isValid() {\n            return managedMapManager.isValid();\n        }\n\n        @Override\n        public boolean isFrozen() {\n            return managedMapManager.isFrozen();\n        }\n\n        // ------------------------------------------\n        // Map API\n        // ------------------------------------------\n\n        @Override\n        public int size() {\n            return managedMapManager.size();\n        }\n\n        @Override\n        public boolean isEmpty() {\n            return managedMapManager.isEmpty();\n        }\n\n        @Override\n        public boolean containsKey(@Nullable Object key) {\n            return managedMapManager.containsKey(key);\n        }\n\n        @Override\n        public boolean containsValue(@Nullable Object value) {\n            return managedMapManager.containsValue(value);\n        }\n\n        @Override\n        public V get(Object key) {\n            return managedMapManager.get(key);\n        }\n\n        @Override\n        public V remove(Object key) {\n            return managedMapManager.remove(key);\n        }\n\n        @Override\n        public void putAll(Map<? extends K, ? extends V> m) {\n            managedMapManager.putAll(m);\n        }\n\n        @Override\n        public void clear() {\n            managedMapManager.clear();\n        }\n\n        @Override\n        public Set<K> keySet() {\n            return managedMapManager.keySet();\n        }\n\n        @Override\n        public Collection<V> values() {\n            return managedMapManager.values();\n        }\n\n        @Override\n        public Set<Entry<K, V>> entrySet() {\n            return managedMapManager.entrySet();\n        }\n\n        // ------------------------------------------\n        // Freezable API\n        // ------------------------------------------\n\n        @Override\n        public RealmMap<K, V> freeze() {\n            return managedMapManager.freeze();\n        }\n\n        // ------------------------------------------\n        // MapStrategy API\n        // ------------------------------------------\n\n        @Override\n        protected V putInternal(K key, V value) {\n            return managedMapManager.put(key, value);\n        }\n\n        @Override\n        protected void addChangeListener(RealmMap<K, V> realmMap, MapChangeListener<K, V> listener) {\n            managedMapManager.addChangeListener(realmMap, listener);\n        }\n\n        @Override\n        protected void addChangeListener(RealmMap<K, V> realmMap, RealmChangeListener<RealmMap<K, V>> listener) {\n            managedMapManager.addChangeListener(realmMap, listener);\n        }\n\n        @Override\n        protected void removeChangeListener(RealmMap<K, V> realmMap, MapChangeListener<K, V> listener) {\n            managedMapManager.removeListener(realmMap, listener);\n        }\n\n        @Override\n        protected void removeChangeListener(RealmMap<K, V> realmMap, RealmChangeListener<RealmMap<K, V>> listener) {\n            managedMapManager.removeListener(realmMap, listener);\n        }\n\n        @Override\n        protected void removeAllChangeListeners() {\n            managedMapManager.removeAllChangeListeners();\n        }\n\n        @Override\n        protected boolean hasListeners() {\n            return managedMapManager.hasListeners();\n        }\n\n        @Override\n        OsMap getOsMap() {\n            return managedMapManager.getOsMap();\n        }\n\n        @Override\n        String getValueClassName() {\n            return managedMapManager.getClassName();\n        }\n\n        @Override\n        Class<V> getValueClass() {\n            return managedMapManager.getValueClass();\n        }\n    }\n\n    /**\n     * Concrete {@link MapStrategy} that works for unmanaged {@link io.realm.RealmMap}s.\n     * <p>\n     * Unmanaged maps are backed internally by a {@link HashMap}.\n     *\n     * @param <K> the key type\n     * @param <V> the value type\n     */\n    private static class UnmanagedMapStrategy<K, V> extends MapStrategy<K, V> {\n\n        private final Map<K, V> unmanagedMap = new HashMap<>();\n\n        // ------------------------------------------\n        // ManageableObject API\n        // ------------------------------------------\n\n        @Override\n        public boolean isManaged() {\n            return false;\n        }\n\n        @Override\n        public boolean isValid() {\n            return true;\n        }\n\n        @Override\n        public boolean isFrozen() {\n            return false;\n        }\n\n        // ------------------------------------------\n        // Map API\n        // ------------------------------------------\n\n        @Override\n        public int size() {\n            return unmanagedMap.size();\n        }\n\n        @Override\n        public boolean isEmpty() {\n            return unmanagedMap.isEmpty();\n        }\n\n        @Override\n        public boolean containsKey(@Nullable Object key) {\n            return unmanagedMap.containsKey(key);\n        }\n\n        @Override\n        public boolean containsValue(@Nullable Object value) {\n            return unmanagedMap.containsValue(value);\n        }\n\n        @Override\n        public V get(Object key) {\n            return unmanagedMap.get(key);\n        }\n\n        @Override\n        public V remove(Object key) {\n            return unmanagedMap.remove(key);\n        }\n\n        @Override\n        public void putAll(Map<? extends K, ? extends V> m) {\n            unmanagedMap.putAll(m);\n        }\n\n        @Override\n        public void clear() {\n            unmanagedMap.clear();\n        }\n\n        @Override\n        public Set<K> keySet() {\n            return unmanagedMap.keySet();\n        }\n\n        @Override\n        public Collection<V> values() {\n            return unmanagedMap.values();\n        }\n\n        @Override\n        public Set<Entry<K, V>> entrySet() {\n            return unmanagedMap.entrySet();\n        }\n\n        // ------------------------------------------\n        // Freezable API\n        // ------------------------------------------\n\n        @Override\n        public RealmMap<K, V> freeze() {\n            throw new UnsupportedOperationException(\"Unmanaged RealmMaps cannot be frozen.\");\n        }\n\n        // ------------------------------------------\n        // MapStrategy API\n        // ------------------------------------------\n\n        @Override\n        protected V putInternal(K key, @Nullable V value) {\n            return unmanagedMap.put(key, value);\n        }\n\n        @Override\n        protected void addChangeListener(RealmMap<K, V> realmMap, MapChangeListener<K, V> listener) {\n            throw new UnsupportedOperationException(\"Unmanaged RealmMaps do not support change listeners.\");\n        }\n\n        @Override\n        protected void addChangeListener(RealmMap<K, V> realmMap, RealmChangeListener<RealmMap<K, V>> listener) {\n            throw new UnsupportedOperationException(\"Unmanaged RealmMaps do not support change listeners.\");\n        }\n\n        @Override\n        protected void removeChangeListener(RealmMap<K, V> realmMap, MapChangeListener<K, V> listener) {\n            throw new UnsupportedOperationException(\"Cannot remove change listener because unmanaged RealmMaps do not support change listeners.\");\n        }\n\n        @Override\n        protected void removeChangeListener(RealmMap<K, V> realmMap, RealmChangeListener<RealmMap<K, V>> listener) {\n            throw new UnsupportedOperationException(\"Cannot remove change listener because unmanaged RealmMaps do not support change listeners.\");\n        }\n\n        @Override\n        protected void removeAllChangeListeners() {\n            throw new UnsupportedOperationException(\"Cannot remove change listener because unmanaged RealmMaps do not support change listeners.\");\n        }\n\n        @Override\n        protected boolean hasListeners() {\n            return false;\n        }\n\n        @Override\n        OsMap getOsMap() {\n            throw new UnsupportedOperationException(\"Unmanaged maps aren't represented in native code.\");\n        }\n\n        @Override\n        String getValueClassName() {\n            throw new UnsupportedOperationException(\"Unmanaged maps do not support retrieving the value class name.\");\n        }\n\n        @Override\n        Class<V> getValueClass() {\n            throw new UnsupportedOperationException(\"Unmanaged maps do not support retrieving the value class.\");\n        }\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/RealmMapEntrySet.java",
    "content": "/*\n * Copyright 2020 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\npackage io.realm;\n\nimport org.bson.types.Decimal128;\nimport org.bson.types.ObjectId;\nimport org.jetbrains.annotations.NotNull;\nimport org.jetbrains.annotations.Nullable;\n\nimport java.lang.reflect.Array;\nimport java.util.AbstractMap;\nimport java.util.Arrays;\nimport java.util.Collection;\nimport java.util.Date;\nimport java.util.Iterator;\nimport java.util.Map;\nimport java.util.NoSuchElementException;\nimport java.util.Set;\nimport java.util.UUID;\n\nimport io.realm.internal.OsMap;\nimport io.realm.internal.core.NativeRealmAny;\nimport io.realm.internal.util.Pair;\n\n/**\n * Wrapper class used to pack key-value pairs when calling {@link RealmMap#entrySet()}.\n *\n * @param <K>\n * @param <V>\n */\nclass RealmMapEntrySet<K, V> implements Set<Map.Entry<K, V>> {\n\n    public enum IteratorType {\n        LONG, BYTE, SHORT, INTEGER, FLOAT, DOUBLE, STRING, BOOLEAN, DATE, DECIMAL128, BINARY,\n        OBJECT_ID, UUID, MIXED, OBJECT\n    }\n\n    private final BaseRealm baseRealm;\n    private final OsMap osMap;\n    private final IteratorType iteratorType;\n    private final EqualsHelper<K, V> equalsHelper;\n    private final TypeSelectorForMap<K, V> typeSelectorForMap;\n\n    RealmMapEntrySet(BaseRealm baseRealm,\n                            OsMap osMap,\n                            IteratorType iteratorType,\n                            @Nullable TypeSelectorForMap<K, V> typeSelectorForMap) {\n        this.baseRealm = baseRealm;\n        this.osMap = osMap;\n        this.iteratorType = iteratorType;\n        this.equalsHelper = new GenericEquals<>();\n        this.typeSelectorForMap = typeSelectorForMap;\n    }\n\n    RealmMapEntrySet(BaseRealm baseRealm,\n                            OsMap osMap,\n                            IteratorType iteratorType,\n                            EqualsHelper<K, V> equalsHelper,\n                            @Nullable TypeSelectorForMap<K, V> typeSelectorForMap) {\n        this.baseRealm = baseRealm;\n        this.osMap = osMap;\n        this.iteratorType = iteratorType;\n        this.equalsHelper = equalsHelper;\n        this.typeSelectorForMap = typeSelectorForMap;\n    }\n\n    @Override\n    public int size() {\n        final long actualMap = osMap.size();\n        return actualMap < Integer.MAX_VALUE ? (int) actualMap : Integer.MAX_VALUE;\n    }\n\n    @Override\n    public boolean isEmpty() {\n        return osMap.size() == 0;\n    }\n\n    @Override\n    public boolean contains(@Nullable Object o) {\n        for (Map.Entry<K, V> entry : this) {\n            if (entry == null && o == null) {\n                return true;\n            } else if (o instanceof Map.Entry) {\n                //noinspection unchecked\n                if (entry != null && equalsHelper.equalsHelper(entry, ((Map.Entry<K, V>) o))) {\n                    return true;\n                }\n            } else {\n                return false;\n            }\n        }\n        return false;\n    }\n\n    @Override\n    public Iterator<Map.Entry<K, V>> iterator() {\n        return iteratorFactory(iteratorType, osMap, baseRealm, typeSelectorForMap);\n    }\n\n    @Override\n    public Object[] toArray() {\n        Object[] array = new Object[(int) osMap.size()];\n\n        int i = 0;\n        for (Map.Entry<K, V> entry : this) {\n            array[i] = entry;\n            i++;\n        }\n\n        return array;\n    }\n\n    @Override\n    public <T> T[] toArray(T[] a) {\n        T[] array;\n        long mapSize = osMap.size();\n\n        // From docs:\n        // If the set fits in the specified array, it is returned therein.\n        // Otherwise, a new array is allocated with the runtime type of the\n        // specified array and the size of this set.\n        if (a.length == mapSize || a.length > mapSize) {\n            array = a;\n        } else {\n            //noinspection unchecked\n            array = (T[]) Array.newInstance(Map.Entry.class, (int) mapSize);\n        }\n\n        int i = 0;\n        for (Map.Entry<K, V> entry : this) {\n            //noinspection unchecked\n            array[i] = (T) entry;\n            i++;\n        }\n\n        // From docs:\n        // If this set fits in the specified array with room to spare\n        // (i.e., the array has more elements than this set), the element in\n        // the array immediately following the end of the set is set to null.\n        if (a.length > mapSize) {\n            array[i] = null;\n        }\n\n        return array;\n    }\n\n    @Override\n    public boolean add(Map.Entry<K, V> entry) {\n        throw new UnsupportedOperationException(\"This set is immutable and cannot be modified.\");\n    }\n\n    @Override\n    public boolean remove(@Nullable Object o) {\n        throw new UnsupportedOperationException(\"This set is immutable and cannot be modified.\");\n    }\n\n    @Override\n    public boolean containsAll(Collection<?> c) {\n        if (c.isEmpty()) {\n            return this.isEmpty();\n        }\n\n        for (Object elem : c) {\n            if (elem instanceof Map.Entry) {\n                //noinspection unchecked\n                Map.Entry<K, V> entry = (Map.Entry<K, V>) elem;\n                if (!this.contains(entry)) {\n                    return false;\n                }\n            } else {\n                return false;\n            }\n        }\n        return true;\n    }\n\n    @Override\n    public boolean addAll(Collection<? extends Map.Entry<K, V>> c) {\n        throw new UnsupportedOperationException(\"This set is immutable and cannot be modified.\");\n    }\n\n    @Override\n    public boolean retainAll(Collection<?> c) {\n        throw new UnsupportedOperationException(\"This set is immutable and cannot be modified.\");\n    }\n\n    @Override\n    public boolean removeAll(Collection<?> c) {\n        throw new UnsupportedOperationException(\"This set is immutable and cannot be modified.\");\n    }\n\n    @Override\n    public void clear() {\n        throw new UnsupportedOperationException(\"This set is immutable and cannot be modified.\");\n    }\n\n    private static <K, V> EntrySetIterator<K, V> iteratorFactory(IteratorType iteratorType,\n                                                                 OsMap osMap,\n                                                                 BaseRealm baseRealm,\n                                                                 @Nullable TypeSelectorForMap typeSelectorForMap) {\n        switch (iteratorType) {\n            case LONG:\n                //noinspection unchecked\n                return (EntrySetIterator<K, V>) new LongValueIterator<>(osMap, baseRealm);\n            case BYTE:\n                //noinspection unchecked\n                return (EntrySetIterator<K, V>) new ByteValueIterator<>(osMap, baseRealm);\n            case SHORT:\n                //noinspection unchecked\n                return (EntrySetIterator<K, V>) new ShortValueIterator<>(osMap, baseRealm);\n            case INTEGER:\n                //noinspection unchecked\n                return (EntrySetIterator<K, V>) new IntegerValueIterator<>(osMap, baseRealm);\n            case FLOAT:\n                //noinspection unchecked\n                return (EntrySetIterator<K, V>) new FloatValueIterator<>(osMap, baseRealm);\n            case DOUBLE:\n                //noinspection unchecked\n                return (EntrySetIterator<K, V>) new DoubleValueIterator<>(osMap, baseRealm);\n            case STRING:\n                //noinspection unchecked\n                return (EntrySetIterator<K, V>) new StringValueIterator<>(osMap, baseRealm);\n            case BOOLEAN:\n                //noinspection unchecked\n                return (EntrySetIterator<K, V>) new BooleanValueIterator<>(osMap, baseRealm);\n            case DATE:\n                //noinspection unchecked\n                return (EntrySetIterator<K, V>) new DateValueIterator<>(osMap, baseRealm);\n            case DECIMAL128:\n                //noinspection unchecked\n                return (EntrySetIterator<K, V>) new Decimal128ValueIterator<>(osMap, baseRealm);\n            case BINARY:\n                //noinspection unchecked\n                return (EntrySetIterator<K, V>) new BinaryValueIterator<>(osMap, baseRealm);\n            case OBJECT_ID:\n                //noinspection unchecked\n                return (EntrySetIterator<K, V>) new ObjectIdValueIterator<>(osMap, baseRealm);\n            case UUID:\n                //noinspection unchecked\n                return (EntrySetIterator<K, V>) new UUIDValueIterator<>(osMap, baseRealm);\n            case MIXED:\n                //noinspection unchecked\n                return (EntrySetIterator<K, V>) new RealmAnyValueIterator<K>(osMap, baseRealm);\n            case OBJECT:\n                if (typeSelectorForMap == null) {\n                    throw new IllegalArgumentException(\"Missing class container when creating RealmModelValueIterator.\");\n                }\n                return new RealmModelValueIterator<>(osMap, baseRealm, typeSelectorForMap);\n            default:\n                throw new IllegalArgumentException(\"Invalid iterator type.\");\n        }\n    }\n\n    private abstract static class EntrySetIterator<K, V> implements Iterator<Map.Entry<K, V>> {\n\n        protected final OsMap osMap;\n        protected final BaseRealm baseRealm;\n\n        private int pos = -1;\n\n        EntrySetIterator(OsMap osMap, BaseRealm baseRealm) {\n            this.osMap = osMap;\n            this.baseRealm = baseRealm;\n        }\n\n        protected abstract Map.Entry<K, V> getEntryInternal(int position);\n\n        @Override\n        public boolean hasNext() {\n            return pos + 1 < osMap.size();\n        }\n\n        @Override\n        public Map.Entry<K, V> next() {\n            pos++;\n            long size = osMap.size();\n            if (pos >= size) {\n                throw new NoSuchElementException(\"Cannot access index \" + pos + \" when size is \" + size +\n                        \". Remember to check hasNext() before using next().\");\n            }\n\n            return getEntryInternal(pos);\n        }\n    }\n\n    private static class LongValueIterator<K> extends EntrySetIterator<K, Long> {\n\n        LongValueIterator(OsMap osMap, BaseRealm baseRealm) {\n            super(osMap, baseRealm);\n        }\n\n        @Override\n        protected Map.Entry<K, Long> getEntryInternal(int position) {\n            Pair<K, Object> pair = osMap.getEntryForPrimitive(position);\n            if (pair.second == null) {\n                return new AbstractMap.SimpleImmutableEntry<>(pair.first, null);\n            }\n\n            Long longValue = (Long) pair.second;\n\n            return new AbstractMap.SimpleImmutableEntry<>(pair.first, longValue);\n        }\n    }\n\n    private static class ByteValueIterator<K> extends EntrySetIterator<K, Byte> {\n\n        ByteValueIterator(OsMap osMap, BaseRealm baseRealm) {\n            super(osMap, baseRealm);\n        }\n\n        @Override\n        protected Map.Entry<K, Byte> getEntryInternal(int position) {\n            Pair<K, Object> pair = osMap.getEntryForPrimitive(position);\n            if (pair.second == null) {\n                return new AbstractMap.SimpleImmutableEntry<>(pair.first, null);\n            }\n\n            Long longValue = (Long) pair.second;\n\n            return new AbstractMap.SimpleImmutableEntry<>(pair.first, longValue.byteValue());\n        }\n    }\n\n    private static class ShortValueIterator<K> extends EntrySetIterator<K, Short> {\n\n        ShortValueIterator(OsMap osMap, BaseRealm baseRealm) {\n            super(osMap, baseRealm);\n        }\n\n        @Override\n        protected Map.Entry<K, Short> getEntryInternal(int position) {\n            Pair<K, Object> pair = osMap.getEntryForPrimitive(position);\n            if (pair.second == null) {\n                return new AbstractMap.SimpleImmutableEntry<>(pair.first, null);\n            }\n\n            Long longValue = (Long) pair.second;\n\n            return new AbstractMap.SimpleImmutableEntry<>(pair.first, longValue.shortValue());\n        }\n    }\n\n    private static class IntegerValueIterator<K> extends EntrySetIterator<K, Integer> {\n\n        IntegerValueIterator(OsMap osMap, BaseRealm baseRealm) {\n            super(osMap, baseRealm);\n        }\n\n        @Override\n        protected Map.Entry<K, Integer> getEntryInternal(int position) {\n            Pair<K, Object> pair = osMap.getEntryForPrimitive(position);\n            if (pair.second == null) {\n                return new AbstractMap.SimpleImmutableEntry<>(pair.first, null);\n            }\n\n            Long longValue = (Long) pair.second;\n\n            return new AbstractMap.SimpleImmutableEntry<>(pair.first, longValue.intValue());\n        }\n    }\n\n    private static class FloatValueIterator<K> extends EntrySetIterator<K, Float> {\n\n        FloatValueIterator(OsMap osMap, BaseRealm baseRealm) {\n            super(osMap, baseRealm);\n        }\n\n        @Override\n        protected Map.Entry<K, Float> getEntryInternal(int position) {\n            Pair<K, Object> pair = osMap.getEntryForPrimitive(position);\n            if (pair.second == null) {\n                return new AbstractMap.SimpleImmutableEntry<>(pair.first, null);\n            }\n\n            return new AbstractMap.SimpleImmutableEntry<>(pair.first, (Float) pair.second);\n        }\n    }\n\n    private static class DoubleValueIterator<K> extends EntrySetIterator<K, Double> {\n\n        DoubleValueIterator(OsMap osMap, BaseRealm baseRealm) {\n            super(osMap, baseRealm);\n        }\n\n        @Override\n        protected Map.Entry<K, Double> getEntryInternal(int position) {\n            Pair<K, Object> pair = osMap.getEntryForPrimitive(position);\n            if (pair.second == null) {\n                return new AbstractMap.SimpleImmutableEntry<>(pair.first, null);\n            }\n\n            return new AbstractMap.SimpleImmutableEntry<>(pair.first, (Double) pair.second);\n        }\n    }\n\n    private static class StringValueIterator<K> extends EntrySetIterator<K, String> {\n\n        StringValueIterator(OsMap osMap, BaseRealm baseRealm) {\n            super(osMap, baseRealm);\n        }\n\n        @Override\n        protected Map.Entry<K, String> getEntryInternal(int position) {\n            Pair<K, Object> pair = osMap.getEntryForPrimitive(position);\n            if (pair.second == null) {\n                return new AbstractMap.SimpleImmutableEntry<>(pair.first, null);\n            }\n\n            return new AbstractMap.SimpleImmutableEntry<>(pair.first, (String) pair.second);\n        }\n    }\n\n    private static class BooleanValueIterator<K> extends EntrySetIterator<K, Boolean> {\n\n        BooleanValueIterator(OsMap osMap, BaseRealm baseRealm) {\n            super(osMap, baseRealm);\n        }\n\n        @Override\n        protected Map.Entry<K, Boolean> getEntryInternal(int position) {\n            Pair<K, Object> pair = osMap.getEntryForPrimitive(position);\n            if (pair.second == null) {\n                return new AbstractMap.SimpleImmutableEntry<>(pair.first, null);\n            }\n\n            return new AbstractMap.SimpleImmutableEntry<>(pair.first, (Boolean) pair.second);\n        }\n    }\n\n    private static class DateValueIterator<K> extends EntrySetIterator<K, Date> {\n\n        DateValueIterator(OsMap osMap, BaseRealm baseRealm) {\n            super(osMap, baseRealm);\n        }\n\n        @Override\n        protected Map.Entry<K, Date> getEntryInternal(int position) {\n            Pair<K, Object> pair = osMap.getEntryForPrimitive(position);\n            if (pair.second == null) {\n                return new AbstractMap.SimpleImmutableEntry<>(pair.first, null);\n            }\n\n            return new AbstractMap.SimpleImmutableEntry<>(pair.first, (Date) pair.second);\n        }\n    }\n\n    private static class Decimal128ValueIterator<K> extends EntrySetIterator<K, Decimal128> {\n\n        Decimal128ValueIterator(OsMap osMap, BaseRealm baseRealm) {\n            super(osMap, baseRealm);\n        }\n\n        @Override\n        protected Map.Entry<K, Decimal128> getEntryInternal(int position) {\n            Pair<K, Object> pair = osMap.getEntryForPrimitive(position);\n            if (pair.second == null) {\n                return new AbstractMap.SimpleImmutableEntry<>(pair.first, null);\n            }\n\n            return new AbstractMap.SimpleImmutableEntry<>(pair.first, (Decimal128) pair.second);\n        }\n    }\n\n    private static class BinaryValueIterator<K> extends EntrySetIterator<K, byte[]> {\n\n        BinaryValueIterator(OsMap osMap, BaseRealm baseRealm) {\n            super(osMap, baseRealm);\n        }\n\n        @Override\n        protected Map.Entry<K, byte[]> getEntryInternal(int position) {\n            Pair<K, Object> pair = osMap.getEntryForPrimitive(position);\n            if (pair.second == null) {\n                return new AbstractMap.SimpleImmutableEntry<>(pair.first, null);\n            }\n\n            return new AbstractMap.SimpleImmutableEntry<>(pair.first, (byte[]) pair.second);\n        }\n    }\n\n    private static class ObjectIdValueIterator<K> extends EntrySetIterator<K, ObjectId> {\n\n        ObjectIdValueIterator(OsMap osMap, BaseRealm baseRealm) {\n            super(osMap, baseRealm);\n        }\n\n        @Override\n        protected Map.Entry<K, ObjectId> getEntryInternal(int position) {\n            Pair<K, Object> pair = osMap.getEntryForPrimitive(position);\n            if (pair.second == null) {\n                return new AbstractMap.SimpleImmutableEntry<>(pair.first, null);\n            }\n\n            return new AbstractMap.SimpleImmutableEntry<>(pair.first, (ObjectId) pair.second);\n        }\n    }\n\n    private static class UUIDValueIterator<K> extends EntrySetIterator<K, UUID> {\n\n        UUIDValueIterator(OsMap osMap, BaseRealm baseRealm) {\n            super(osMap, baseRealm);\n        }\n\n        @Override\n        protected Map.Entry<K, UUID> getEntryInternal(int position) {\n            Pair<K, Object> pair = osMap.getEntryForPrimitive(position);\n            if (pair.second == null) {\n                return new AbstractMap.SimpleImmutableEntry<>(pair.first, null);\n            }\n\n            return new AbstractMap.SimpleImmutableEntry<>(pair.first, (UUID) pair.second);\n        }\n    }\n\n    private static class RealmModelValueIterator<K, V> extends EntrySetIterator<K, V> {\n\n        private final TypeSelectorForMap<K, V> typeSelectorForMap;\n\n        RealmModelValueIterator(OsMap osMap,\n                                       BaseRealm baseRealm,\n                                       TypeSelectorForMap<K, V> typeSelectorForMap) {\n            super(osMap, baseRealm);\n            this.typeSelectorForMap = typeSelectorForMap;\n        }\n\n        @Override\n        protected Map.Entry<K, V> getEntryInternal(int position) {\n            Pair<K, Long> pair = osMap.getKeyObjRowPair(position);\n            K key = pair.first;\n            long objRow = pair.second;\n\n            if (objRow == OsMap.NOT_FOUND) {\n                return new AbstractMap.SimpleImmutableEntry<>(key, null);\n            }\n\n            return typeSelectorForMap.getModelEntry(baseRealm, objRow, key);\n        }\n    }\n\n    private static class RealmAnyValueIterator<K> extends EntrySetIterator<K, RealmAny> {\n\n        RealmAnyValueIterator(OsMap osMap, BaseRealm baseRealm) {\n            super(osMap, baseRealm);\n        }\n\n        @Override\n        protected Map.Entry<K, RealmAny> getEntryInternal(int position) {\n            Pair<K, NativeRealmAny> pair = osMap.getKeyRealmAnyPair(position);\n            K key = pair.first;\n            NativeRealmAny nativeRealmAny = pair.second;\n            RealmAny value = new RealmAny(RealmAnyOperator.fromNativeRealmAny(baseRealm, nativeRealmAny));\n            return new AbstractMap.SimpleImmutableEntry<>(key, value);\n        }\n    }\n}\n\nabstract class EqualsHelper<K, V> {\n\n    boolean equalsHelper(Map.Entry<K, V> entry, Map.Entry<K, V> other) {\n        K otherKey = other.getKey();\n        K key = entry.getKey();\n        if (key.equals(otherKey)) {\n            return compareInternal(entry.getValue(), other.getValue());\n        }\n        return false;\n    }\n\n    protected abstract boolean compareInternal(@Nullable V value, @Nullable V otherValue);\n}\n\nclass GenericEquals<K, V> extends EqualsHelper<K, V> {\n    @Override\n    protected boolean compareInternal(@Nullable V value, @Nullable V otherValue) {\n        if (value == null) {\n            return otherValue == null;\n        } else {\n            return value.equals(otherValue);\n        }\n    }\n}\n\nclass BinaryEquals<K> extends EqualsHelper<K, byte[]> {\n    @Override\n    protected boolean compareInternal(@Nullable byte[] value, @Nullable byte[] otherValue) {\n        return Arrays.equals(value, otherValue);\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/RealmMigration.java",
    "content": "/*\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\npackage io.realm;\n\n/**\n * The RealmMigration class is used to perform the migration of one Realm schema to another.\n * The schema for a Realm is defined by all classes in a project that extend {@link io.realm.RealmObject}\n * or implement {@link io.realm.RealmModel}, so any changes to these classes will require a migration.\n * <p>\n * To support migrations from any previous schemaVersion to the newest, the following pattern is recommended when\n * writing a migration:\n * <p>\n * <pre>\n * {@code\n * public class CustomMigration implements RealmMigration {\n *   \\@Override\n *   public long migrate(DynamicRealm realm, long oldVersion, long newVersion) {\n *     RealmSchema schema = realm.getSchema();\n *\n *     if (oldVersion == 0) {\n *       // Migrate from v0 to v1\n *       oldVersion++;\n *     }\n *\n *     if (oldVersion == 1) {\n *       // Migrate from v1 to v2\n *       oldVersion++;\n *     }\n *\n *     if (oldVersion < newVersion) {\n *         throw new IllegalStateException(String.format(Locale.US, \"Migration missing from v%d to v%d\", oldVersion, newVersion));\n *     }\n *   }\n * }\n * }\n * </pre>\n * <p>\n * During development when RealmObject classes can change frequently, it is possible to use\n * {@link io.realm.Realm#deleteRealm(RealmConfiguration)}. This will delete the database file and eliminate the need for\n * any migrations.\n *\n * @see io.realm.RealmConfiguration.Builder#schemaVersion(long)\n * @see io.realm.RealmConfiguration.Builder#migration(RealmMigration)\n * @see io.realm.RealmConfiguration.Builder#deleteRealmIfMigrationNeeded()\n */\npublic interface RealmMigration {\n\n    /**\n     * This method will be called if a migration is needed. The entire method is wrapped in a\n     * write transaction so it is possible to create, update or delete any existing objects\n     * without wrapping it in your own transaction.\n     *\n     * @param realm the Realm schema on which to perform the migration.\n     * @param oldVersion the schema version of the Realm at the start of the migration.\n     * @param newVersion the schema version of the Realm after executing the migration.\n     */\n    void migrate(DynamicRealm realm, long oldVersion, long newVersion);\n}\n\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/RealmModel.java",
    "content": "/*\n * Copyright 2016 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\npackage io.realm;\n\nimport io.realm.annotations.RealmClass;\n\n\n/**\n * Interface for marking classes as RealmObjects, it can be used instead of extending {@link RealmObject}.\n * <p>\n * All helper methods available to classes that extend RealmObject are instead available as static methods:\n * <p>\n * <pre>\n * {@code\n *   Person p = realm.createObject(Person.class);\n *\n *   // With the RealmModel interface\n *   RealmObject.isValid(p);\n *\n *   // With the RealmObject base class\n *   p.isValid();\n * }\n * </pre>\n * <p>\n * Note: Object implementing this interface needs also to be annotated with {@link RealmClass}, so the annotation\n * processor can generate the underlining proxy class.\n *\n * @see RealmObject\n */\n\npublic interface RealmModel {\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/RealmObject.java",
    "content": "/*\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\npackage io.realm;\n\nimport android.app.IntentService;\n\nimport java.util.Collections;\n\nimport javax.annotation.Nullable;\n\nimport io.reactivex.Flowable;\nimport io.reactivex.Observable;\nimport io.realm.annotations.RealmClass;\nimport io.realm.internal.InvalidRow;\nimport io.realm.internal.ManageableObject;\nimport io.realm.internal.RealmObjectProxy;\nimport io.realm.internal.Row;\nimport io.realm.log.RealmLog;\nimport io.realm.rx.ObjectChange;\n\n/**\n * In Realm you define your RealmObject classes by sub-classing RealmObject and adding fields to be persisted. You then\n * create your objects within a Realm, and use your custom subclasses instead of using the RealmObject class directly.\n * <p>\n * An annotation processor will create a proxy class for your RealmObject subclass.\n * <p>\n * The following field data types are supported:\n * <ul>\n * <li>boolean/Boolean</li>\n * <li>short/Short</li>\n * <li>int/Integer</li>\n * <li>long/Long</li>\n * <li>float/Float</li>\n * <li>double/Double</li>\n * <li>byte[]</li>\n * <li>String</li>\n * <li>Date</li>\n * <li>UUID</li>\n * <li>org.bson.types.Decimal128</li>\n * <li>org.bson.types.ObjectId</li>\n * <li>Any RealmObject subclass</li>\n * <li>RealmList</li>\n * <li>RealmDictionary</li>\n * </ul>\n * <p>\n * The types <code>short</code>, <code>int</code>, and <code>long</code> are mapped to <code>long</code> when storing\n * within a Realm.\n * <p>\n * The only restriction a RealmObject has is that fields are not allowed to be final or volatile.\n * Any method as well as public fields are allowed. When providing custom constructors, a public constructor with\n * no arguments must be declared.\n * <p>\n * Fields annotated with {@link io.realm.annotations.Ignore} don't have these restrictions and don't require either a\n * getter or setter.\n * <p>\n * Realm will create indexes for fields annotated with {@link io.realm.annotations.Index}. This will speedup queries but\n * will have a negative impact on inserts and updates.\n * <p>\n * A RealmObject cannot be passed between different threads.\n *\n * @see Realm#createObject(Class)\n * @see Realm#copyToRealm(RealmModel, ImportFlag...)\n */\n\n@RealmClass\npublic abstract class RealmObject implements RealmModel, ManageableObject {\n    static final String MSG_NULL_OBJECT = \"'model' is null.\";\n    static final String MSG_DELETED_OBJECT = \"the object is already deleted.\";\n    static final String MSG_DYNAMIC_OBJECT = \"the object is an instance of DynamicRealmObject. Use DynamicRealmObject.getDynamicRealm() instead.\";\n\n    /**\n     * Deletes the object from the Realm it is currently associated to.\n     * <p>\n     * After this method is called the object will be invalid and any operation (read or write) performed on it will\n     * fail with an IllegalStateException.\n     *\n     * @throws IllegalStateException if the corresponding Realm is closed or in an incorrect thread.\n     * @see #isValid()\n     */\n    public final void deleteFromRealm() {\n        deleteFromRealm(this);\n    }\n\n    /**\n     * Deletes the object from the Realm it is currently associated with.\n     * <p>\n     * After this method is called the object will be invalid and any operation (read or write) performed on it will\n     * fail with an IllegalStateException.\n     *\n     * @throws IllegalStateException if the corresponding Realm is closed or in an incorrect thread.\n     * @see #isValid()\n     */\n    public static <E extends RealmModel> void deleteFromRealm(E object) {\n        if (!(object instanceof RealmObjectProxy)) {\n            // TODO What type of exception IllegalArgument/IllegalState?\n            throw new IllegalArgumentException(\"Object not managed by Realm, so it cannot be removed.\");\n        }\n\n        RealmObjectProxy proxy = (RealmObjectProxy) object;\n        if (proxy.realmGet$proxyState().getRow$realm() == null) {\n            throw new IllegalStateException(\"Object malformed: missing object in Realm. Make sure to instantiate RealmObjects with Realm.createObject()\");\n        }\n        if (proxy.realmGet$proxyState().getRealm$realm() == null) {\n            throw new IllegalStateException(\"Object malformed: missing Realm. Make sure to instantiate RealmObjects with Realm.createObject()\");\n        }\n\n        proxy.realmGet$proxyState().getRealm$realm().checkIfValid();\n        Row row = proxy.realmGet$proxyState().getRow$realm();\n        row.getTable().moveLastOver(row.getObjectKey());\n        proxy.realmGet$proxyState().setRow$realm(InvalidRow.INSTANCE);\n    }\n\n\n    /**\n     * Checks if the RealmObject is still valid to use i.e., the RealmObject hasn't been deleted nor has the\n     * {@link io.realm.Realm} been closed. It will always return {@code true} for unmanaged objects.\n     * <p>\n     * Note that this can be used to check the validity of certain conditions such as being {@code null}\n     * when observed.\n     * <pre>\n     * {@code\n     * realm.where(BannerRealm.class).equalTo(\"type\", type).findFirstAsync().asFlowable()\n     *      .filter(result.isLoaded() && result.isValid())\n     *      .first()\n     * }\n     * </pre>\n     *\n     * @return {@code true} if the object is still accessible or an unmanaged object, {@code false} otherwise.\n     * @see <a href=\"https://github.com/realm/realm-java/tree/master/examples/rxJavaExample\">Examples using Realm with RxJava</a>\n     */\n    @Override\n    public final boolean isValid() {\n        return RealmObject.isValid(this);\n    }\n\n    /**\n     * Checks if the RealmObject is still valid to use i.e., the RealmObject hasn't been deleted nor has the\n     * {@link io.realm.Realm} been closed. It will always return {@code true} for unmanaged objects.\n     *\n     * @param object RealmObject to check validity for.\n     * @return {@code true} if the object is still accessible or an unmanaged object, {@code false} otherwise.\n     */\n    public static <E extends RealmModel> boolean isValid(@Nullable E object) {\n        if (object instanceof RealmObjectProxy) {\n            RealmObjectProxy proxy = (RealmObjectProxy) object;\n            Row row = proxy.realmGet$proxyState().getRow$realm();\n            return row != null && row.isValid();\n        } else {\n            //noinspection ConstantConditions\n            return object != null;\n        }\n    }\n\n    /**\n     * Returns whether or not this RealmObject is frozen.\n     *\n     * @return {@code true} if the RealmObject is frozen, {@code false} if it is not.\n     * @see #freeze()\n     */\n    @Override\n    public final boolean isFrozen() {\n        return RealmObject.isFrozen(this);\n    }\n\n    /**\n     * Returns a frozen snapshot of this object. The frozen copy can be read and queried from any thread without throwing\n     * an {@link IllegalStateException}.\n     * <p>\n     * Freezing a RealmObject also creates a frozen Realm which has its own lifecycle, but if the live Realm that spawned the\n     * original collection is fully closed (i.e. all instances across all threads are closed), the frozen Realm and\n     * object will be closed as well.\n     * <p>\n     * Frozen objects can be queried as normal, but trying to mutate it in any way or attempting to register a listener will\n     * throw an {@link IllegalStateException}.\n     * <p>\n     * Note: Keeping a large number of frozen objects with different versions alive can have a negative impact on the filesize\n     * of the Realm. In order to avoid such a situation it is possible to set {@link RealmConfiguration.Builder#maxNumberOfActiveVersions(long)}.\n     *\n     * @return a frozen copy of this object.\n     * @throws IllegalStateException if this method is called from inside a write transaction.\n     */\n    @SuppressWarnings(\"TypeParameterUnusedInFormals\") // FIXME: Consider adding type parameters to all RealmObject/RealmModel classes?\n    public final <E extends RealmModel> E freeze() {\n        //noinspection unchecked\n        return (E) RealmObject.freeze(this);\n    }\n\n    /**\n     * Returns whether or not this RealmObject is frozen.\n     *\n     * @return {@code true} if the RealmObject is frozen, {@code false} if it is not.\n     * @see #freeze()\n     */\n    public static <E extends RealmModel> boolean isFrozen(E object) {\n        if (object instanceof RealmObjectProxy) {\n            RealmObjectProxy proxy = (RealmObjectProxy) object;\n            return proxy.realmGet$proxyState().getRealm$realm().isFrozen();\n        } else {\n            return false;\n        }\n    }\n\n    /**\n     * Returns a frozen snapshot of this object. The frozen copy can be read and queried from any thread without throwing\n     * an {@link IllegalStateException}.\n     * <p>\n     * Freezing a RealmObject also creates a frozen Realm which has its own lifecycle, but if the live Realm that spawned the\n     * original collection is fully closed (i.e. all instances across all threads are closed), the frozen Realm and\n     * object will be closed as well.\n     * <p>\n     * Frozen objects can be queried as normal, but trying to mutate it in any way or attempting to register a listener will\n     * throw an {@link IllegalStateException}.\n     * <p>\n     * Note: Keeping a large number of frozen objects with different versions alive can have a negative impact on the filesize\n     * of the Realm. In order to avoid such a situation it is possible to set {@link RealmConfiguration.Builder#maxNumberOfActiveVersions(long)}.\n     *\n     * @return a frozen copy of this object.\n     * @throws IllegalStateException if this method is called from inside a write transaction.\n     */\n    public static <E extends RealmModel> E freeze(E object) {\n        if (object instanceof RealmObjectProxy) {\n            RealmObjectProxy proxy = (RealmObjectProxy) object;\n            BaseRealm realm = proxy.realmGet$proxyState().getRealm$realm();\n            BaseRealm frozenRealm = (realm.isFrozen()) ? realm : realm.freeze();\n\n            Row frozenRow = proxy.realmGet$proxyState().getRow$realm().freeze(frozenRealm.sharedRealm);\n            if (frozenRealm instanceof DynamicRealm) {\n                //noinspection unchecked\n                return (E) new DynamicRealmObject(frozenRealm, frozenRow);\n            } else if (frozenRealm instanceof Realm) {\n                //noinspection unchecked\n                Class<E> modelClass = (Class<E>) object.getClass().getSuperclass();\n                return (E) frozenRealm.getConfiguration().getSchemaMediator().newInstance(\n                        modelClass, frozenRealm, frozenRow, realm.getSchema().getColumnInfo(modelClass),\n                        false, Collections.<String>emptyList());\n            } else {\n                throw new UnsupportedOperationException(\"Unknown Realm type: \" + frozenRealm.getClass().getName());\n            }\n        } else {\n            throw new IllegalArgumentException(\"It is only possible to freeze valid managed Realm objects.\");\n        }\n    }\n\n    /**\n     * Checks if the query used to find this RealmObject has completed.\n     * <p>\n     * Async methods like {@link RealmQuery#findFirstAsync()} return a {@link RealmObject} that represents the future\n     * result of the {@link RealmQuery}. It can be considered similar to a {@link java.util.concurrent.Future} in this\n     * regard.\n     * <p>\n     * Once {@code isLoaded()} returns {@code true}, the object represents the query result even if the query\n     * didn't find any object matching the query parameters. In this case the {@link RealmObject} will\n     * become a \"null\" object.\n     * <p>\n     * \"Null\" objects represents {@code null}.  An exception is throw if any accessor is called, so it is important to\n     * also check {@link #isValid()} before calling any methods. A common pattern is:\n     * <p>\n     * <pre>\n     * {@code\n     * Person person = realm.where(Person.class).findFirstAsync();\n     * person.isLoaded(); // == false\n     * person.addChangeListener(new RealmChangeListener() {\n     *      \\@Override\n     *      public void onChange(Person person) {\n     *          person.isLoaded(); // Always true here\n     *          if (person.isValid()) {\n     *              // It is safe to access the person.\n     *          }\n     *      }\n     * });\n     * }\n     * </pre>\n     * <p>\n     * Synchronous RealmObjects are by definition blocking hence this method will always return {@code true} for them.\n     * This method will return {@code true} if called on an unmanaged object (created outside of Realm).\n     *\n     * @return {@code true} if the query has completed, {@code false} if the query is in\n     * progress.\n     * @see #isValid()\n     */\n    public final boolean isLoaded() {\n        return RealmObject.isLoaded(this);\n    }\n\n\n    /**\n     * Checks if the query used to find this RealmObject has completed.\n     * <p>\n     * Async methods like {@link RealmQuery#findFirstAsync()} return an {@link RealmObject} that represents the future result\n     * of the {@link RealmQuery}. It can be considered similar to a {@link java.util.concurrent.Future} in this regard.\n     * <p>\n     * Once {@code isLoaded()} returns {@code true}, the object represents the query result even if the query\n     * didn't find any object matching the query parameters. In this case the {@link RealmObject} will\n     * become a \"null\" object.\n     * <p>\n     * \"Null\" objects represents {@code null}.  An exception is throw if any accessor is called, so it is important to also\n     * check {@link #isValid()} before calling any methods. A common pattern is:\n     * <p>\n     * <pre>\n     * {@code\n     * Person person = realm.where(Person.class).findFirstAsync();\n     * RealmObject.isLoaded(person); // == false\n     * RealmObject.addChangeListener(person, new RealmChangeListener() {\n     *      \\@Override\n     *      public void onChange(Person person) {\n     *          RealmObject.isLoaded(person); // always true here\n     *          if (RealmObject.isValid(person)) {\n     *              // It is safe to access the person.\n     *          }\n     *      }\n     * });\n     * }\n     * </pre>\n     * <p>\n     * Synchronous RealmObjects are by definition blocking hence this method will always return {@code true} for them.\n     * This method will return {@code true} if called on an unmanaged object (created outside of Realm).\n     *\n     * @param object RealmObject to check.\n     * @return {@code true} if the query has completed, {@code false} if the query is in\n     * progress.\n     * @see #isValid(RealmModel)\n     */\n    public static <E extends RealmModel> boolean isLoaded(E object) {\n        if (object instanceof RealmObjectProxy) {\n            RealmObjectProxy proxy = (RealmObjectProxy) object;\n            proxy.realmGet$proxyState().getRealm$realm().checkIfValid();\n            return proxy.realmGet$proxyState().isLoaded();\n        }\n        return true;\n    }\n\n    /**\n     * Checks if this object is managed by Realm. A managed object is just a wrapper around the data in the underlying\n     * Realm file. On Looper threads, a managed object will be live-updated so it always points to the latest data. It\n     * is possible to register a change listener using {@link #addChangeListener(RealmChangeListener)} to be notified\n     * when changes happen. Managed objects are thread confined so that they cannot be accessed from other threads than\n     * the one that created them.\n     * <p>\n     * <p>\n     * If this method returns {@code false}, the object is unmanaged. An unmanaged object is just a normal Java object,\n     * so it can be parsed freely across threads, but the data in the object is not connected to the underlying Realm,\n     * so it will not be live updated.\n     * <p>\n     * <p>\n     * It is possible to create a managed object from an unmanaged object by using\n     * {@link Realm#copyToRealm(RealmModel, ImportFlag...)}. An unmanaged object can be created from a managed object by using\n     * {@link Realm#copyFromRealm(RealmModel)}.\n     *\n     * @return {@code true} if the object is managed, {@code false} if it is unmanaged.\n     */\n    @Override\n    public boolean isManaged() {\n        return RealmObject.isManaged(this);\n    }\n\n    /**\n     * Checks if this object is managed by Realm. A managed object is just a wrapper around the data in the underlying\n     * Realm file. On Looper threads, a managed object will be live-updated so it always points to the latest data. It\n     * is possible to register a change listener using {@link #addChangeListener(RealmModel, RealmChangeListener)} to be\n     * notified when changes happen. Managed objects are thread confined so that they cannot be accessed from other threads\n     * than the one that created them.\n     * <p>\n     * <p>\n     * If this method returns {@code false}, the object is unmanaged. An unmanaged object is just a normal Java object,\n     * so it can be parsed freely across threads, but the data in the object is not connected to the underlying Realm,\n     * so it will not be live updated.\n     * <p>\n     * <p>\n     * It is possible to create a managed object from an unmanaged object by using\n     * {@link Realm#copyToRealm(RealmModel, ImportFlag...)}. An unmanaged object can be created from a managed object by using\n     * {@link Realm#copyFromRealm(RealmModel)}.\n     *\n     * @return {@code true} if the object is managed, {@code false} if it is unmanaged.\n     */\n    public static <E extends RealmModel> boolean isManaged(E object) {\n        return object instanceof RealmObjectProxy;\n    }\n\n    /**\n     * Returns {@link Realm} instance where this {@link RealmObject} belongs.\n     * <p>\n     * You <b>must not</b> call {@link Realm#close()} against returned instance.\n     *\n     * @return {@link Realm} instance where this object belongs to or {@code null} if this object is unmanaged.\n     * @throws IllegalStateException if this object is an instance of {@link DynamicRealmObject}\n     * or this object was already deleted or the corresponding {@link Realm} was already closed.\n     */\n    public Realm getRealm() {\n        return getRealm(this);\n    }\n\n    /**\n     * returns {@link Realm} instance where the {@code model} belongs.\n     * <p>\n     * You <b>must not</b> call {@link Realm#close()} against returned instance.\n     *\n     * @param model an {@link RealmModel} instance other than {@link DynamicRealmObject}.\n     * @return {@link Realm} instance where the {@code model} belongs or {@code null} if the {@code model} is unmanaged.\n     * @throws IllegalArgumentException if the {@code model} is {@code null}.\n     * @throws IllegalStateException if the {@code model}  is an instance of {@link DynamicRealmObject}\n     * or this object was already deleted or the corresponding {@link Realm} was already closed.\n     */\n    public static Realm getRealm(RealmModel model) {\n        if (model == null) {\n            throw new IllegalArgumentException(MSG_NULL_OBJECT);\n        }\n        if (model instanceof DynamicRealmObject) {\n            throw new IllegalStateException(MSG_DYNAMIC_OBJECT);\n        }\n        if (!(model instanceof RealmObjectProxy)) {\n            return null;\n        }\n        final BaseRealm realm = ((RealmObjectProxy) model).realmGet$proxyState().getRealm$realm();\n        realm.checkIfValid();\n        if (!RealmObject.isValid(model)) {\n            throw new IllegalStateException(MSG_DELETED_OBJECT);\n        }\n\n        return (Realm) realm;\n    }\n\n    /**\n     * Makes an asynchronous query blocking. This will also trigger any registered listeners.\n     * <p>\n     * Note: This will return {@code true} if called for an unmanaged object (created outside of Realm).\n     *\n     * @return {@code true} if it successfully completed the query, {@code false} otherwise.\n     */\n    public final boolean load() {\n        return RealmObject.load(this);\n    }\n\n    /**\n     * Makes an asynchronous query blocking. This will also trigger any registered listeners.\n     * <p>\n     * Note: This will return {@code true} if called for an unmanaged object (created outside of Realm).\n     *\n     * @param object RealmObject to force load.\n     * @return {@code true} if it successfully completed the query, {@code false} otherwise.\n     */\n    public static <E extends RealmModel> boolean load(E object) {\n        if (RealmObject.isLoaded(object)) {\n            return true;\n        } else if (object instanceof RealmObjectProxy) {\n            ((RealmObjectProxy) object).realmGet$proxyState().load();\n            return true;\n        }\n        return false;\n    }\n\n    /**\n     * Adds a change listener to this RealmObject to get detailed information about changes. The listener will be\n     * triggered if any value field or referenced RealmObject field is changed, or the RealmList field itself is\n     * changed.\n     * <p>\n     * Registering a change listener will not prevent the underlying RealmObject from being garbage collected.\n     * If the RealmObject is garbage collected, the change listener will stop being triggered. To avoid this, keep a\n     * strong reference for as long as appropriate e.g. in a class variable.\n     * <p>\n     * <pre>\n     * {@code\n     * public class MyActivity extends Activity {\n     *\n     *     private Person person; // Strong reference to keep listeners alive\n     *\n     *     \\@Override\n     *     protected void onCreate(Bundle savedInstanceState) {\n     *       super.onCreate(savedInstanceState);\n     *       person = realm.where(Person.class).findFirst();\n     *       person.addChangeListener(new RealmObjectChangeListener<Person>() {\n     *           \\@Override\n     *           public void onChange(Person person, ObjectChangeSet changeSet) {\n     *               // React to change\n     *           }\n     *       });\n     *     }\n     * }\n     * }\n     * </pre>\n     *\n     * @param listener the change listener to be notified.\n     * @throws IllegalArgumentException if the change listener is {@code null} or the object is an unmanaged object.\n     * @throws IllegalStateException if you try to add a listener from a non-Looper or {@link IntentService} thread.\n     * @throws IllegalStateException if you try to add a listener inside a transaction.\n     */\n    public final <E extends RealmModel> void addChangeListener(RealmObjectChangeListener<E> listener) {\n        //noinspection unchecked\n        RealmObject.addChangeListener((E) this, listener);\n    }\n\n    /**\n     * Adds a change listener to this RealmObject that will be triggered if any value field or referenced RealmObject\n     * field is changed, or the RealmList field itself is changed.\n     * <p>\n     * Registering a change listener will not prevent the underlying RealmObject from being garbage collected.\n     * If the RealmObject is garbage collected, the change listener will stop being triggered. To avoid this, keep a\n     * strong reference for as long as appropriate e.g. in a class variable.\n     * <p>\n     * <pre>\n     * {@code\n     * public class MyActivity extends Activity {\n     *\n     *     private Person person; // Strong reference to keep listeners alive\n     *\n     *     \\@Override\n     *     protected void onCreate(Bundle savedInstanceState) {\n     *       super.onCreate(savedInstanceState);\n     *       person = realm.where(Person.class).findFirst();\n     *       person.addChangeListener(new RealmChangeListener<Person>() {\n     *           \\@Override\n     *           public void onChange(Person person) {\n     *               // React to change\n     *           }\n     *       });\n     *     }\n     * }\n     * }\n     * </pre>\n     *\n     * @param listener the change listener to be notified.\n     * @throws IllegalArgumentException if the change listener is {@code null} or the object is an unmanaged object.\n     * @throws IllegalStateException if you try to add a listener from a non-Looper or {@link IntentService} thread.\n     * @throws IllegalStateException if you try to add a listener inside a transaction.\n     */\n    public final <E extends RealmModel> void addChangeListener(RealmChangeListener<E> listener) {\n        //noinspection unchecked\n        RealmObject.addChangeListener((E) this, listener);\n    }\n\n    /**\n     * Adds a change listener to a RealmObject to get detailed information about the changes. The listener will be\n     * triggered if any value field or referenced RealmObject field is changed, or the RealmList field itself is\n     * changed.\n     * <p>\n     * Registering a change listener will not prevent the underlying RealmObject from being garbage collected.\n     * If the RealmObject is garbage collected, the change listener will stop being triggered. To avoid this, keep a\n     * strong reference for as long as appropriate e.g. in a class variable.\n     * <p>\n     * <pre>\n     * {@code\n     * public class MyActivity extends Activity {\n     *\n     *     private Person person; // Strong reference to keep listeners alive\n     *\n     *     \\@Override\n     *     protected void onCreate(Bundle savedInstanceState) {\n     *       super.onCreate(savedInstanceState);\n     *       person = realm.where(Person.class).findFirst();\n     *       person.addChangeListener(new RealmObjectChangeListener<Person>() {\n     *           \\@Override\n     *           public void onChange(Person person, ObjectChangeSet changeSet) {\n     *               // React to change\n     *           }\n     *       });\n     *     }\n     * }\n     * }\n     * </pre>\n     *\n     *\n     * @param object RealmObject to add listener to.\n     * @param listener the change listener to be notified.\n     * @throws IllegalArgumentException if the {@code object} is {@code null} or an unmanaged object, or the change\n     * listener is {@code null}.\n     * @throws IllegalStateException if you try to add a listener from a non-Looper or {@link IntentService} thread.\n     * @throws IllegalStateException if you try to add a listener inside a transaction.\n     */\n    public static <E extends RealmModel> void addChangeListener(E object, RealmObjectChangeListener<E> listener) {\n        //noinspection ConstantConditions\n        if (object == null) {\n            throw new IllegalArgumentException(\"Object should not be null\");\n        }\n        //noinspection ConstantConditions\n        if (listener == null) {\n            throw new IllegalArgumentException(\"Listener should not be null\");\n        }\n        if (object instanceof RealmObjectProxy) {\n            RealmObjectProxy proxy = (RealmObjectProxy) object;\n            BaseRealm realm = proxy.realmGet$proxyState().getRealm$realm();\n            realm.checkIfValid();\n            realm.sharedRealm.capabilities.checkCanDeliverNotification(BaseRealm.LISTENER_NOT_ALLOWED_MESSAGE);\n            //noinspection unchecked\n            proxy.realmGet$proxyState().addChangeListener(listener);\n        } else {\n            throw new IllegalArgumentException(\"Cannot add listener from this unmanaged RealmObject (created outside of Realm)\");\n        }\n    }\n\n    /**\n     * Adds a change listener to a RealmObject that will be triggered if any value field or referenced RealmObject field\n     * is changed, or the RealmList field itself is changed.\n     * <p>\n     * Registering a change listener will not prevent the underlying RealmObject from being garbage collected.\n     * If the RealmObject is garbage collected, the change listener will stop being triggered. To avoid this, keep a\n     * strong reference for as long as appropriate e.g. in a class variable.\n     * <p>\n     * <pre>\n     * {@code\n     * public class MyActivity extends Activity {\n     *\n     *     private Person person; // Strong reference to keep listeners alive\n     *\n     *     \\@Override\n     *     protected void onCreate(Bundle savedInstanceState) {\n     *       super.onCreate(savedInstanceState);\n     *       person = realm.where(Person.class).findFirst();\n     *       person.addChangeListener(new RealmChangeListener<Person>() {\n     *           \\@Override\n     *           public void onChange(Person person) {\n     *               // React to change\n     *           }\n     *       });\n     *     }\n     * }\n     * }\n     * </pre>\n     *\n     * @param object RealmObject to add listener to.\n     * @param listener the change listener to be notified.\n     * @throws IllegalArgumentException if the {@code object} is {@code null} or an unmanaged object, or the change\n     * listener is {@code null}.\n     * @throws IllegalStateException if you try to add a listener from a non-Looper or {@link IntentService} thread.\n     * @throws IllegalStateException if you try to add a listener inside a transaction.\n     */\n    public static <E extends RealmModel> void addChangeListener(E object, RealmChangeListener<E> listener) {\n        addChangeListener(object, new ProxyState.RealmChangeListenerWrapper<>(listener));\n    }\n\n    /**\n     * Removes a previously registered listener.\n     *\n     * @param listener the instance to be removed.\n     * @throws IllegalArgumentException if the change listener is {@code null} or the object is an unmanaged object.\n     * @throws IllegalStateException if you try to remove a listener from a non-Looper Thread.\n     */\n    public final void removeChangeListener(RealmObjectChangeListener listener) {\n        RealmObject.removeChangeListener(this, listener);\n    }\n\n    /**\n     * Removes a previously registered listener.\n     *\n     * @param listener the instance to be removed.\n     * @throws IllegalArgumentException if the change listener is {@code null} or the object is an unmanaged object.\n     * @throws IllegalStateException if you try to remove a listener from a non-Looper Thread.\n     */\n    public final void removeChangeListener(RealmChangeListener listener) {\n        RealmObject.removeChangeListener(this, listener);\n    }\n\n    /**\n     * Removes a previously registered listener on the given RealmObject.\n     *\n     * @param object RealmObject to remove listener from.\n     * @param listener the instance to be removed.\n     * @throws IllegalArgumentException if the {@code object} or the change listener is {@code null}.\n     * @throws IllegalArgumentException if object is an unmanaged RealmObject.\n     * @throws IllegalStateException if you try to remove a listener from a non-Looper Thread.\n     */\n    public static <E extends RealmModel> void removeChangeListener(E object, RealmObjectChangeListener listener) {\n        //noinspection ConstantConditions\n        if (object == null) {\n            throw new IllegalArgumentException(\"Object should not be null\");\n        }\n        //noinspection ConstantConditions\n        if (listener == null) {\n            throw new IllegalArgumentException(\"Listener should not be null\");\n        }\n        if (object instanceof RealmObjectProxy) {\n            RealmObjectProxy proxy = (RealmObjectProxy) object;\n            BaseRealm realm = proxy.realmGet$proxyState().getRealm$realm();\n            if (realm.isClosed()) {\n                RealmLog.warn(\"Calling removeChangeListener on a closed Realm %s, \" +\n                        \"make sure to close all listeners before closing the Realm.\", realm.configuration.getPath());\n            }\n            //noinspection unchecked\n            proxy.realmGet$proxyState().removeChangeListener(listener);\n        } else {\n            throw new IllegalArgumentException(\"Cannot remove listener from this unmanaged RealmObject (created outside of Realm)\");\n        }\n    }\n\n    /**\n     * Removes a previously registered listener on the given RealmObject.\n     *\n     * @param object RealmObject to remove listener from.\n     * @param listener the instance to be removed.\n     * @throws IllegalArgumentException if the {@code object} or the change listener is {@code null}.\n     * @throws IllegalArgumentException if object is an unmanaged RealmObject.\n     * @throws IllegalStateException if you try to remove a listener from a non-Looper Thread.\n     */\n    public static <E extends RealmModel> void removeChangeListener(E object, RealmChangeListener<E> listener) {\n        removeChangeListener(object, new ProxyState.RealmChangeListenerWrapper<>(listener));\n    }\n\n    /**\n     * Removes all registered listeners.\n     */\n    public final void removeAllChangeListeners() {\n        RealmObject.removeAllChangeListeners(this);\n    }\n\n    /**\n     * Removes all registered listeners from the given RealmObject.\n     *\n     * @param object RealmObject to remove all listeners from.\n     * @throws IllegalArgumentException if object is {@code null} or isn't managed by Realm.\n     */\n    public static <E extends RealmModel> void removeAllChangeListeners(E object) {\n        if (object instanceof RealmObjectProxy) {\n            RealmObjectProxy proxy = (RealmObjectProxy) object;\n            BaseRealm realm = proxy.realmGet$proxyState().getRealm$realm();\n            if (realm.isClosed()) {\n                RealmLog.warn(\"Calling removeChangeListener on a closed Realm %s, \" +\n                        \"make sure to close all listeners before closing the Realm.\", realm.configuration.getPath());\n            }\n            proxy.realmGet$proxyState().removeAllChangeListeners();\n        } else {\n            throw new IllegalArgumentException(\"Cannot remove listeners from this unmanaged RealmObject (created outside of Realm)\");\n        }\n    }\n\n    /**\n     * Returns an RxJava Flowable that monitors changes to this RealmObject. It will emit the current object when\n     * subscribed to. Object updates will continually be emitted as the RealmObject is updated -\n     * {@code onComplete} will never be called.\n     * <p>\n     * When chaining a RealmObject flowable use {@code obj.<MyRealmObjectClass>asFlowable()} to pass on\n     * type information, otherwise the type of the following observables will be {@code RealmObject}.\n     * <p>\n     * Items emitted from Realm Flowables are frozen (See {@link #freeze()}. This means that they\n     * are immutable and can be read on any thread.\n     * <p>\n     * Realm Flowables always emit items from the thread holding the live Realm. This means that if\n     * you need to do further processing, it is recommend to observe the values on a computation\n     * scheduler:\n     * <p>\n     * {@code\n     * obj.asFlowable()\n     *   .observeOn(Schedulers.computation())\n     *   .map((rxObj) -> doExpensiveWork(rxObj))\n     *   .observeOn(AndroidSchedulers.mainThread())\n     *   .subscribe( ... );\n     * }\n     * <p>\n     * If you would like the {@code asFlowable()} to stop emitting items you can instruct RxJava to\n     * only emit only the first item by using the {@code first()} operator:\n     * <p>\n     * <pre>\n     * {@code\n     * obj.asFlowable()\n     *      .filter(obj -> obj.isLoaded())\n     *      .first()\n     *      .subscribe( ... ) // You only get the object once\n     * }\n     * </pre>\n     * <p>\n     *\n     * @param <E> RealmObject class that is being observed. Must be this class or its super types.\n     * @return RxJava Observable that only calls {@code onNext}. It will never call {@code onComplete} or {@code OnError}.\n     * @throws UnsupportedOperationException if the required RxJava framework is not on the classpath or the\n     * corresponding Realm instance doesn't support RxJava.\n     * @throws IllegalStateException if the Realm wasn't opened on a Looper thread.\n     * @see <a href=\"https://realm.io/docs/java/latest/#rxjava\">RxJava and Realm</a>\n     */\n    public final <E extends RealmObject> Flowable<E> asFlowable() {\n        //noinspection unchecked\n        return (Flowable<E>) RealmObject.asFlowable(this);\n    }\n\n    /**\n     * Returns an Rx Observable that monitors changes to this RealmObject. It will emit the current RealmObject when\n     * subscribed to. For each update to the RealmObject a pair consisting of the RealmObject and the\n     * {@link ObjectChangeSet} will be sent. The changeset will be {@code null} the first\n     * time the RealmObject is emitted.\n     * <p>\n     * The RealmObject will continually be emitted as it is updated - {@code onComplete} will never be called.\n     * <p>\n     * Items emitted from Realm Observables are frozen (See {@link #freeze()}. This means that they\n     * are immutable and can be read on any thread.\n     * <p>\n     * Realm Observables always emit items from the thread holding the live Realm. This means that if\n     * you need to do further processing, it is recommend to observe the values on a computation\n     * scheduler:\n     * <p>\n     * {@code\n     * obj.asChangesetObservable()\n     *   .observeOn(Schedulers.computation())\n     *   .map((rxObj, changes) -> doExpensiveWork(rxObj, changeså))\n     *   .observeOn(AndroidSchedulers.mainThread())\n     *   .subscribe( ... );\n     * }\n     *\n     * @return RxJava Observable that only calls {@code onNext}. It will never call {@code onComplete} or {@code OnError}.\n     * @throws UnsupportedOperationException if the required RxJava framework is not on the classpath or the\n     * corresponding Realm instance doesn't support RxJava.\n     * @throws IllegalStateException if the Realm wasn't opened on a Looper thread.\n     * @see <a href=\"https://realm.io/docs/java/latest/#rxjava\">RxJava and Realm</a>\n     */\n    public final <E extends RealmObject> Observable<ObjectChange<E>> asChangesetObservable() {\n        return (Observable) RealmObject.asChangesetObservable(this);\n    }\n\n    /**\n     * Returns an RxJava Flowable that monitors changes to this RealmObject. It will emit the current object when\n     * subscribed to. Object updates will continuously be emitted as the RealmObject is updated -\n     * {@code onComplete} will never be called.\n     * <p>\n     * When chaining a RealmObject observable use {@code obj.<MyRealmObjectClass>asFlowable()} to pass on\n     * type information, otherwise the type of the following observables will be {@code RealmObject}.\n     * <p>\n     * Items emitted from Realm Flowables are frozen (See {@link #freeze()}. This means that they\n     * are immutable and can be read on any thread.\n     * <p>\n     * Realm Flowables always emit items from the thread holding the live Realm. This means that if\n     * you need to do further processing, it is recommend to observe the values on a computation\n     * scheduler:\n     * <p>\n     * {@code\n     * obj.asFlowable()\n     *   .observeOn(Schedulers.computation())\n     *   .map((rxObj) -> doExpensiveWork(rxObj))\n     *   .observeOn(AndroidSchedulers.mainThread())\n     *   .subscribe( ... );\n     * }\n     * <p>\n     * If you would like the {@code asFlowable()} to stop emitting items you can instruct RxJava to\n     * emit only the first item by using the {@code first()} operator:\n     * <p>\n     * <pre>\n     * {@code\n     * obj.asFlowable()\n     *      .filter(obj -> obj.isLoaded())\n     *      .first()\n     *      .subscribe( ... ) // You only get the object once\n     * }\n     * </pre>\n     *\n     * @param object RealmObject class that is being observed. Must be this class or its super types.\n     * @return RxJava Observable that only calls {@code onNext}. It will never call {@code onComplete} or {@code OnError}.\n     * @throws UnsupportedOperationException if the required RxJava framework is not on the classpath.\n     * @throws IllegalStateException if the Realm wasn't opened on a Looper thread.\n     * @see <a href=\"https://realm.io/docs/java/latest/#rxjava\">RxJava and Realm</a>\n     */\n    public static <E extends RealmModel> Flowable<E> asFlowable(E object) {\n        if (object instanceof RealmObjectProxy) {\n            RealmObjectProxy proxy = (RealmObjectProxy) object;\n            BaseRealm realm = proxy.realmGet$proxyState().getRealm$realm();\n            if (realm instanceof Realm) {\n                return realm.configuration.getRxFactory().from((Realm) realm, object);\n            } else if (realm instanceof DynamicRealm) {\n                DynamicRealm dynamicRealm = (DynamicRealm) realm;\n                DynamicRealmObject dynamicObject = (DynamicRealmObject) object;\n                @SuppressWarnings(\"unchecked\")\n                Flowable<E> observable = (Flowable<E>) realm.configuration.getRxFactory().from(dynamicRealm, dynamicObject);\n                return observable;\n            } else {\n                throw new UnsupportedOperationException(realm.getClass() + \" does not support RxJava.\" +\n                        \" See https://realm.io/docs/java/latest/#rxjava for more details.\");\n            }\n        } else {\n            // TODO Is this true? Should we just return Observable.just(object) ?\n            throw new IllegalArgumentException(\"Cannot create Observables from unmanaged RealmObjects\");\n        }\n    }\n\n\n    /**\n     * Returns an Rx Observable that monitors changes to this RealmObject. It will emit the current RealmObject when\n     * subscribed to. For each update to the RealmObject a pair consisting of the RealmObject and the\n     * {@link ObjectChangeSet} will be sent. The changeset will be {@code null} the first\n     * time the RealmObject is emitted.\n     * <p>\n     * The RealmObject will continually be emitted as it is updated - {@code onComplete} will never be called.\n     * <p>\n     * Items emitted from Realm Observables are frozen (See {@link #freeze()}. This means that they\n     * are immutable and can be read on any thread.\n     * <p>\n     * Realm Observables always emit items from the thread holding the live Realm. This means that if\n     * you need to do further processing, it is recommend to observe the values on a computation\n     * scheduler:\n     * <p>\n     * {@code\n     * obj.asChangesetObservable()\n     *   .observeOn(Schedulers.computation())\n     *   .map((rxObj, changes) -> doExpensiveWork(rxObj, changeså))\n     *   .observeOn(AndroidSchedulers.mainThread())\n     *   .subscribe( ... );\n     * }\n     *\n     * @param object RealmObject class that is being observed. Must be this class or its super types.\n     * @return RxJava Observable that only calls {@code onNext}. It will never call {@code onComplete} or {@code OnError}.\n     * @throws UnsupportedOperationException if the required RxJava framework is not on the classpath or the\n     * corresponding Realm instance doesn't support RxJava.\n     * @throws IllegalStateException if the Realm wasn't opened on a Looper thread.\n     * @see <a href=\"https://realm.io/docs/java/latest/#rxjava\">RxJava and Realm</a>\n     */\n    public static <E extends RealmModel> Observable<ObjectChange<E>> asChangesetObservable(E object) {\n        if (object instanceof RealmObjectProxy) {\n            RealmObjectProxy proxy = (RealmObjectProxy) object;\n            BaseRealm realm = proxy.realmGet$proxyState().getRealm$realm();\n            if (realm instanceof Realm) {\n                return realm.configuration.getRxFactory().changesetsFrom((Realm) realm, object);\n            } else if (realm instanceof DynamicRealm) {\n                DynamicRealm dynamicRealm = (DynamicRealm) realm;\n                DynamicRealmObject dynamicObject = (DynamicRealmObject) object;\n                return (Observable) realm.configuration.getRxFactory().changesetsFrom(dynamicRealm, dynamicObject);\n            } else {\n                throw new UnsupportedOperationException(realm.getClass() + \" does not support RxJava.\" +\n                        \" See https://realm.io/docs/java/latest/#rxjava for more details.\");\n            }\n        } else {\n            // TODO Is this true? Should we just return Observable.just(object) ?\n            throw new IllegalArgumentException(\"Cannot create Observables from unmanaged RealmObjects\");\n        }\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/RealmObjectChangeListener.java",
    "content": "/*\n * Copyright 2017 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\npackage io.realm;\n\nimport javax.annotation.Nullable;\n\nimport io.realm.annotations.LinkingObjects;\n\n/**\n * {@code RealmObjectChangeListener} can be registered on a {@link RealmModel} or {@link RealmObject} to receive\n * detailed notifications when an object changes.\n * <p>\n * Realm instances on a thread without an {@link android.os.Looper} cannot register a {@code RealmObjectChangeListener}.\n * <p>\n * Listener cannot be registered inside a transaction.\n *\n * @param <T> The type of {@link RealmModel} on which your listener will be registered.\n * @see Realm#addChangeListener(RealmChangeListener)\n * @see Realm#removeAllChangeListeners()\n * @see Realm#removeChangeListener(RealmChangeListener)\n */\npublic interface RealmObjectChangeListener<T extends RealmModel> {\n\n    /**\n     * When this gets called to return the results of an asynchronous query made by {@link RealmQuery#findFirstAsync()},\n     * {@code changeSet} will be {@code null}.\n     * <p>\n     * When this gets called because the object was deleted, {@code changeSet.isDeleted()} will return {@code true}\n     * and {@code changeSet.getFieldChanges()} will return {@code null}.\n     * <p>\n     * When this gets called because the object was modified, {@code changeSet.isDeleted()} will return {@code false}\n     * and {@code changeSet.getFieldChanges()} will return the detailed information about the fields' changes.\n     * <p>\n     * If a field points to another RealmObject this listener will only be triggered if the field is set to a new object\n     * or null. Updating the referenced RealmObject will not trigger this listener.\n     * <p>\n     * If a field points to a RealmList, this listener will only be triggered if one or multiple objects are inserted,\n     * removed or moved within the List. Updating the objects in the RealmList will not trigger this listener.\n     * <p>\n     * Changes to {@link LinkingObjects} annotated {@link RealmResults} fields will not be monitored, nor reported\n     * through this change listener.\n     * @param t the {@code RealmObject} this listener is registered to.\n     * @param changeSet the detailed information about the changes.\n     */\n    void onChange(T t, @Nullable ObjectChangeSet changeSet);\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/RealmObjectSchema.java",
    "content": "/*\n * Copyright 2017 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\npackage io.realm;\n\nimport org.bson.types.Decimal128;\nimport org.bson.types.ObjectId;\n\nimport java.util.Collections;\nimport java.util.Date;\nimport java.util.HashMap;\nimport java.util.LinkedHashSet;\nimport java.util.Locale;\nimport java.util.Map;\nimport java.util.Set;\nimport java.util.UUID;\n\nimport javax.annotation.Nullable;\n\nimport io.realm.annotations.RealmClass;\nimport io.realm.annotations.Required;\nimport io.realm.internal.ColumnInfo;\nimport io.realm.internal.OsObjectStore;\nimport io.realm.internal.Table;\n\n\n/**\n * Class for interacting with the schema for a given RealmObject class. This makes it possible to inspect,\n * add, delete or change the fields for given class.\n * <p>\n * If this {@link RealmObjectSchema} is retrieved from an immutable {@link RealmSchema}, this {@link RealmObjectSchema}\n * will be immutable as well.\n *\n * @see io.realm.RealmMigration\n */\npublic abstract class RealmObjectSchema {\n\n    static final Map<Class<?>, FieldMetaData> SUPPORTED_LIST_SIMPLE_FIELDS;\n    static final Map<Class<?>, FieldMetaData> SUPPORTED_DICTIONARY_SIMPLE_FIELDS;\n    static final Map<Class<?>, FieldMetaData> SUPPORTED_SET_SIMPLE_FIELDS;\n\n    static {\n        Map<Class<?>, FieldMetaData> listMap = new HashMap<>();\n        listMap.put(String.class, new FieldMetaData(RealmFieldType.STRING, RealmFieldType.STRING_LIST, true));\n        listMap.put(short.class, new FieldMetaData(RealmFieldType.INTEGER, RealmFieldType.INTEGER_LIST, false));\n        listMap.put(Short.class, new FieldMetaData(RealmFieldType.INTEGER, RealmFieldType.INTEGER_LIST, true));\n        listMap.put(int.class, new FieldMetaData(RealmFieldType.INTEGER, RealmFieldType.INTEGER_LIST, false));\n        listMap.put(Integer.class, new FieldMetaData(RealmFieldType.INTEGER, RealmFieldType.INTEGER_LIST, true));\n        listMap.put(long.class, new FieldMetaData(RealmFieldType.INTEGER, RealmFieldType.INTEGER_LIST, false));\n        listMap.put(Long.class, new FieldMetaData(RealmFieldType.INTEGER, RealmFieldType.INTEGER_LIST, true));\n        listMap.put(float.class, new FieldMetaData(RealmFieldType.FLOAT, RealmFieldType.FLOAT_LIST, false));\n        listMap.put(Float.class, new FieldMetaData(RealmFieldType.FLOAT, RealmFieldType.FLOAT_LIST, true));\n        listMap.put(double.class, new FieldMetaData(RealmFieldType.DOUBLE, RealmFieldType.DOUBLE_LIST, false));\n        listMap.put(Double.class, new FieldMetaData(RealmFieldType.DOUBLE, RealmFieldType.DOUBLE_LIST, true));\n        listMap.put(boolean.class, new FieldMetaData(RealmFieldType.BOOLEAN, RealmFieldType.BOOLEAN_LIST, false));\n        listMap.put(Boolean.class, new FieldMetaData(RealmFieldType.BOOLEAN, RealmFieldType.BOOLEAN_LIST, true));\n        listMap.put(byte.class, new FieldMetaData(RealmFieldType.INTEGER, RealmFieldType.INTEGER_LIST, false));\n        listMap.put(Byte.class, new FieldMetaData(RealmFieldType.INTEGER, RealmFieldType.INTEGER_LIST, true));\n        listMap.put(byte[].class, new FieldMetaData(RealmFieldType.BINARY, RealmFieldType.BINARY_LIST, true));\n        listMap.put(Date.class, new FieldMetaData(RealmFieldType.DATE, RealmFieldType.DATE_LIST, true));\n        listMap.put(ObjectId.class, new FieldMetaData(RealmFieldType.OBJECT_ID, RealmFieldType.OBJECT_ID_LIST, true));\n        listMap.put(Decimal128.class, new FieldMetaData(RealmFieldType.DECIMAL128, RealmFieldType.DECIMAL128_LIST, true));\n        listMap.put(UUID.class, new FieldMetaData(RealmFieldType.UUID, RealmFieldType.UUID_LIST, true));\n        listMap.put(RealmAny.class, new FieldMetaData(RealmFieldType.MIXED, RealmFieldType.MIXED_LIST, true));\n        SUPPORTED_LIST_SIMPLE_FIELDS = Collections.unmodifiableMap(listMap);\n\n        Map<Class<?>, FieldMetaData> dictionaryMap = new HashMap<>();\n        dictionaryMap.put(String.class, new FieldMetaData(RealmFieldType.STRING, RealmFieldType.STRING_TO_STRING_MAP, true));\n        dictionaryMap.put(short.class, new FieldMetaData(RealmFieldType.INTEGER, RealmFieldType.STRING_TO_INTEGER_MAP, false));\n        dictionaryMap.put(Short.class, new FieldMetaData(RealmFieldType.INTEGER, RealmFieldType.STRING_TO_INTEGER_MAP, true));\n        dictionaryMap.put(int.class, new FieldMetaData(RealmFieldType.INTEGER, RealmFieldType.STRING_TO_INTEGER_MAP, false));\n        dictionaryMap.put(Integer.class, new FieldMetaData(RealmFieldType.INTEGER, RealmFieldType.STRING_TO_INTEGER_MAP, true));\n        dictionaryMap.put(long.class, new FieldMetaData(RealmFieldType.INTEGER, RealmFieldType.STRING_TO_INTEGER_MAP, false));\n        dictionaryMap.put(Long.class, new FieldMetaData(RealmFieldType.INTEGER, RealmFieldType.STRING_TO_INTEGER_MAP, true));\n        dictionaryMap.put(float.class, new FieldMetaData(RealmFieldType.FLOAT, RealmFieldType.STRING_TO_FLOAT_MAP, false));\n        dictionaryMap.put(Float.class, new FieldMetaData(RealmFieldType.FLOAT, RealmFieldType.STRING_TO_FLOAT_MAP, true));\n        dictionaryMap.put(double.class, new FieldMetaData(RealmFieldType.DOUBLE, RealmFieldType.STRING_TO_DOUBLE_MAP, false));\n        dictionaryMap.put(Double.class, new FieldMetaData(RealmFieldType.DOUBLE, RealmFieldType.STRING_TO_DOUBLE_MAP, true));\n        dictionaryMap.put(boolean.class, new FieldMetaData(RealmFieldType.BOOLEAN, RealmFieldType.STRING_TO_BOOLEAN_MAP, false));\n        dictionaryMap.put(Boolean.class, new FieldMetaData(RealmFieldType.BOOLEAN, RealmFieldType.STRING_TO_BOOLEAN_MAP, true));\n        dictionaryMap.put(byte.class, new FieldMetaData(RealmFieldType.INTEGER, RealmFieldType.STRING_TO_INTEGER_MAP, false));\n        dictionaryMap.put(Byte.class, new FieldMetaData(RealmFieldType.INTEGER, RealmFieldType.STRING_TO_INTEGER_MAP, true));\n        dictionaryMap.put(byte[].class, new FieldMetaData(RealmFieldType.BINARY, RealmFieldType.STRING_TO_BINARY_MAP, true));\n        dictionaryMap.put(Date.class, new FieldMetaData(RealmFieldType.DATE, RealmFieldType.STRING_TO_DATE_MAP, true));\n        dictionaryMap.put(ObjectId.class, new FieldMetaData(RealmFieldType.OBJECT_ID, RealmFieldType.STRING_TO_OBJECT_ID_MAP, true));\n        dictionaryMap.put(Decimal128.class, new FieldMetaData(RealmFieldType.DECIMAL128, RealmFieldType.STRING_TO_DECIMAL128_MAP, true));\n        dictionaryMap.put(UUID.class, new FieldMetaData(RealmFieldType.UUID, RealmFieldType.STRING_TO_UUID_MAP, true));\n        dictionaryMap.put(RealmAny.class, new FieldMetaData(RealmFieldType.MIXED, RealmFieldType.STRING_TO_MIXED_MAP, true));\n        SUPPORTED_DICTIONARY_SIMPLE_FIELDS = Collections.unmodifiableMap(dictionaryMap);\n\n        Map<Class<?>, FieldMetaData> setMap = new HashMap<>();\n        setMap.put(String.class, new FieldMetaData(RealmFieldType.STRING, RealmFieldType.STRING_SET, true));\n        setMap.put(short.class, new FieldMetaData(RealmFieldType.INTEGER, RealmFieldType.INTEGER_SET, false));\n        setMap.put(Short.class, new FieldMetaData(RealmFieldType.INTEGER, RealmFieldType.INTEGER_SET, true));\n        setMap.put(int.class, new FieldMetaData(RealmFieldType.INTEGER, RealmFieldType.INTEGER_SET, false));\n        setMap.put(Integer.class, new FieldMetaData(RealmFieldType.INTEGER, RealmFieldType.INTEGER_SET, true));\n        setMap.put(long.class, new FieldMetaData(RealmFieldType.INTEGER, RealmFieldType.INTEGER_SET, false));\n        setMap.put(Long.class, new FieldMetaData(RealmFieldType.INTEGER, RealmFieldType.INTEGER_SET, true));\n        setMap.put(float.class, new FieldMetaData(RealmFieldType.FLOAT, RealmFieldType.FLOAT_SET, false));\n        setMap.put(Float.class, new FieldMetaData(RealmFieldType.FLOAT, RealmFieldType.FLOAT_SET, true));\n        setMap.put(double.class, new FieldMetaData(RealmFieldType.DOUBLE, RealmFieldType.DOUBLE_SET, false));\n        setMap.put(Double.class, new FieldMetaData(RealmFieldType.DOUBLE, RealmFieldType.DOUBLE_SET, true));\n        setMap.put(boolean.class, new FieldMetaData(RealmFieldType.BOOLEAN, RealmFieldType.BOOLEAN_SET, false));\n        setMap.put(Boolean.class, new FieldMetaData(RealmFieldType.BOOLEAN, RealmFieldType.BOOLEAN_SET, true));\n        setMap.put(byte.class, new FieldMetaData(RealmFieldType.INTEGER, RealmFieldType.INTEGER_SET, false));\n        setMap.put(Byte.class, new FieldMetaData(RealmFieldType.INTEGER, RealmFieldType.INTEGER_SET, true));\n        setMap.put(byte[].class, new FieldMetaData(RealmFieldType.BINARY, RealmFieldType.BINARY_SET, true));\n        setMap.put(Date.class, new FieldMetaData(RealmFieldType.DATE, RealmFieldType.DATE_SET, true));\n        setMap.put(ObjectId.class, new FieldMetaData(RealmFieldType.OBJECT_ID, RealmFieldType.OBJECT_ID_SET, true));\n        setMap.put(Decimal128.class, new FieldMetaData(RealmFieldType.DECIMAL128, RealmFieldType.DECIMAL128_SET, true));\n        setMap.put(UUID.class, new FieldMetaData(RealmFieldType.UUID, RealmFieldType.UUID_SET, true));\n        setMap.put(RealmAny.class, new FieldMetaData(RealmFieldType.MIXED, RealmFieldType.MIXED_SET, true));\n        SUPPORTED_SET_SIMPLE_FIELDS = Collections.unmodifiableMap(setMap);\n    }\n\n    static final Map<Class<?>, FieldMetaData> SUPPORTED_LINKED_FIELDS;\n\n    static {\n        Map<Class<?>, FieldMetaData> m = new HashMap<>();\n        m.put(RealmObject.class, new FieldMetaData(RealmFieldType.OBJECT, null, false));\n        m.put(RealmList.class, new FieldMetaData(RealmFieldType.LIST, null, false));\n        m.put(RealmDictionary.class, new FieldMetaData(RealmFieldType.STRING_TO_LINK_MAP, null, false));\n        m.put(RealmSet.class, new FieldMetaData(RealmFieldType.LINK_SET, null, false));\n        SUPPORTED_LINKED_FIELDS = Collections.unmodifiableMap(m);\n    }\n\n    final RealmSchema schema;\n    final BaseRealm realm;\n    final Table table;\n    final ColumnInfo columnInfo;\n\n    /**\n     * Creates a schema object for a given Realm class.\n     *\n     * @param realm Realm holding the objects.\n     * @param table table representation of the Realm class\n     * @param columnInfo mapping between field names and column indexes for the given table\n     */\n    RealmObjectSchema(BaseRealm realm, RealmSchema schema, Table table, ColumnInfo columnInfo) {\n        this.schema = schema;\n        this.realm = realm;\n        this.table = table;\n        this.columnInfo = columnInfo;\n    }\n\n    /**\n     * Returns the name of the RealmObject class being represented by this schema.\n     * <p>\n     * <ul>\n     * <li>When using a normal {@link Realm} this name is the same as the {@link RealmObject} class.</li>\n     * <li>When using a {@link DynamicRealm} this is the name used in all API methods requiring a class name.</li>\n     * </ul>\n     *\n     * @return the name of the RealmObject class represented by this schema.\n     * @throws IllegalStateException if this schema defintion is no longer part of the Realm.\n     */\n    public String getClassName() {\n        return table.getClassName();\n    }\n\n    /**\n     * Sets a new name for this RealmObject class. This is equivalent to renaming it.\n     *\n     * @param className the new name for this class.\n     * @throws IllegalArgumentException if className is {@code null} or an empty string, or its length exceeds 56\n     * characters.\n     * @throws UnsupportedOperationException if this {@link RealmObjectSchema} is immutable or from a synced Realm.\n     * @see RealmSchema#rename(String, String)\n     */\n    public abstract RealmObjectSchema setClassName(String className);\n\n    /**\n     * Adds a new simple field to the RealmObject class. The type must be one supported by Realm. See\n     * {@link RealmObject} for the list of supported types. If the field should allow {@code null} values use the boxed\n     * type instead e.g., {@code Integer.class} instead of {@code int.class}.\n     * <p>\n     * To add fields that reference other RealmObjects or RealmLists use\n     * {@link #addRealmObjectField(String, RealmObjectSchema)} or {@link #addRealmListField(String, RealmObjectSchema)}\n     * instead.\n     *\n     * @param fieldName name of the field to add.\n     * @param fieldType type of field to add. See {@link RealmObject} for the full list.\n     * @param attributes set of attributes for this field.\n     * @return the updated schema.\n     * @throws IllegalArgumentException if the type isn't supported, field name is illegal or a field with that name\n     * already exists.\n     * @throws UnsupportedOperationException if this {@link RealmObjectSchema} is immutable or if adding a\n     * a field with {@link FieldAttribute#PRIMARY_KEY} attribute to a schema of a synced Realm.\n     */\n    public abstract RealmObjectSchema addField(String fieldName, Class<?> fieldType, FieldAttribute... attributes);\n\n    /**\n     * Adds a new field that references another {@link RealmObject}.\n     *\n     * @param fieldName name of the field to add.\n     * @param objectSchema schema for the Realm type being referenced.\n     * @return the updated schema.\n     * @throws IllegalArgumentException if field name is illegal or a field with that name already exists.\n     * @throws UnsupportedOperationException if this {@link RealmObjectSchema} is immutable.\n     */\n    public abstract RealmObjectSchema addRealmObjectField(String fieldName, RealmObjectSchema objectSchema);\n\n    /**\n     * Adds a new field that contains a {@link RealmList} with references to other Realm model classes.\n     * <p>\n     * If the list contains primitive types, use {@link #addRealmListField(String, Class)} instead.\n     *\n     * @param fieldName name of the field to add.\n     * @param objectSchema schema for the Realm type being referenced.\n     * @return the updated schema.\n     * @throws IllegalArgumentException if the field name is illegal or a field with that name already exists.\n     * @throws UnsupportedOperationException if this {@link RealmObjectSchema} is immutable.\n     */\n    public abstract RealmObjectSchema addRealmListField(String fieldName, RealmObjectSchema objectSchema);\n\n    /**\n     * Adds a new field that references a {@link RealmList} with primitive values. See {@link RealmObject} for the\n     * list of supported types.\n     * <p>\n     * Nullability of elements are defined by using the correct class e.g., {@code Integer.class} instead of\n     * {@code int.class}. Alternatively {@link #setRequired(String, boolean)} can be used.\n     * <p>\n     * Example:\n     * <pre>\n     * {@code\n     * // Defines the list of Strings as being non null.\n     * RealmObjectSchema schema = schema.create(\"Person\")\n     *     .addRealmListField(\"children\", String.class)\n     *     .setRequired(\"children\", true)\n     * }\n     * </pre>\n     * If the list contains references to other Realm classes, use\n     * {@link #addRealmListField(String, RealmObjectSchema)} instead.\n     *\n     * @param fieldName name of the field to add.\n     * @param primitiveType simple type of elements in the array.\n     * @return the updated schema.\n     * @throws IllegalArgumentException if the field name is illegal, a field with that name already exists or\n     * the element type isn't supported.\n     * @throws UnsupportedOperationException if this {@link RealmObjectSchema} is immutable.\n     */\n    public abstract RealmObjectSchema addRealmListField(String fieldName, Class<?> primitiveType);\n\n    /**\n     * Adds a new field that contains a {@link RealmDictionary} with references to other Realm model classes.\n     * <p>\n     * If the dictionary contains primitive types, use {@link #addRealmDictionaryField(String, Class)} instead.\n     *\n     * @param fieldName name of the field to add.\n     * @param objectSchema schema for the Realm type being referenced.\n     * @return the updated schema.\n     * @throws IllegalArgumentException if the field name is illegal or a field with that name already exists.\n     * @throws UnsupportedOperationException if this {@link RealmObjectSchema} is immutable.\n     */\n    public abstract RealmObjectSchema addRealmDictionaryField(String fieldName, RealmObjectSchema objectSchema);\n\n    /**\n     * Adds a new field that references a {@link RealmDictionary} with primitive values. See {@link RealmObject} for the\n     * list of supported types.\n     * <p>\n     * Nullability of elements are defined by using the correct class e.g., {@code Integer.class} instead of\n     * {@code int.class}. Alternatively {@link #setRequired(String, boolean)} can be used.\n     * <p>\n     * Example:\n     * <pre>\n     * {@code\n     * // Defines the dictionary of Strings as being non null.\n     * RealmObjectSchema schema = schema.create(\"Person\")\n     *     .addRealmDictionaryField(\"parentAndChild\", String.class)\n     *     .setRequired(\"parentAndChild\", true)\n     * }\n     * </pre>\n     * If the list contains references to other Realm classes, use\n     * {@link #addRealmDictionaryField(String, RealmObjectSchema)} instead.\n     *\n     * @param fieldName name of the field to add.\n     * @param primitiveType simple type of elements in the array.\n     * @return the updated schema.\n     * @throws IllegalArgumentException if the field name is illegal, a field with that name already exists or\n     * the element type isn't supported.\n     * @throws UnsupportedOperationException if this {@link RealmObjectSchema} is immutable.\n     */\n    public abstract RealmObjectSchema addRealmDictionaryField(String fieldName, Class<?> primitiveType);\n\n    /**\n     * Adds a new field that contains a {@link RealmSet} with references to other Realm model classes.\n     * <p>\n     * If the set contains primitive types, use {@link #addRealmSetField(String, Class)} instead.\n     *\n     * @param fieldName name of the field to add.\n     * @param objectSchema schema for the Realm type being referenced.\n     * @return the updated schema.\n     * @throws IllegalArgumentException if the field name is illegal or a field with that name already exists.\n     * @throws UnsupportedOperationException if this {@link RealmObjectSchema} is immutable.\n     */\n    public abstract RealmObjectSchema addRealmSetField(String fieldName, RealmObjectSchema objectSchema);\n\n    /**\n     * Adds a new field that references a {@link RealmSet} with primitive values. See {@link RealmObject} for the\n     * list of supported types.\n     * <p>\n     * Nullability of elements are defined by using the correct class e.g., {@code Integer.class} instead of\n     * {@code int.class}. Alternatively {@link #setRequired(String, boolean)} can be used.\n     * <p>\n     * Example:\n     * <pre>\n     * {@code\n     * // Defines the set of Strings as being non null.\n     * RealmObjectSchema schema = schema.create(\"Person\")\n     *     .addRealmSetField(\"children\", String.class)\n     *     .setRequired(\"children\", true)\n     * }\n     * </pre>\n     * If the list contains references to other Realm classes, use\n     * {@link #addRealmSetField(String, RealmObjectSchema)} instead.\n     *\n     * @param fieldName name of the field to add.\n     * @param primitiveType simple type of elements in the array.\n     * @return the updated schema.\n     * @throws IllegalArgumentException if the field name is illegal, a field with that name already exists or\n     * the element type isn't supported.\n     * @throws UnsupportedOperationException if this {@link RealmObjectSchema} is immutable.\n     */\n    public abstract RealmObjectSchema addRealmSetField(String fieldName, Class<?> primitiveType);\n\n    /**\n     * Removes a field from the class.\n     *\n     * @param fieldName field name to remove.\n     * @return the updated schema.\n     * @throws IllegalArgumentException if field name doesn't exist.\n     * @throws UnsupportedOperationException if this {@link RealmObjectSchema} is immutable or for a synced Realm.\n     */\n    public abstract RealmObjectSchema removeField(String fieldName);\n\n    /**\n     * Renames a field from one name to another.\n     *\n     * @param currentFieldName field name to rename.\n     * @param newFieldName the new field name.\n     * @return the updated schema.\n     * @throws IllegalArgumentException if field name doesn't exist or if the new field name already exists.\n     * @throws UnsupportedOperationException if this {@link RealmObjectSchema} is immutable or for a synced Realm.\n     */\n    public abstract RealmObjectSchema renameField(String currentFieldName, String newFieldName);\n\n    /**\n     * Tests if the class has field defined with the given name.\n     *\n     * @param fieldName field name to test.\n     * @return {@code true} if the field exists, {@code false} otherwise.\n     */\n    public boolean hasField(String fieldName) {\n        return table.getColumnKey(fieldName) != Table.NO_MATCH;\n    }\n\n    /**\n     * Adds an index to a given field. This is the equivalent of adding the {@link io.realm.annotations.Index}\n     * annotation on the field.\n     *\n     * @param fieldName field to add index to.\n     * @return the updated schema.\n     * @throws IllegalArgumentException if field name doesn't exist, the field cannot be indexed or it already has a\n     * index defined.\n     * @throws UnsupportedOperationException if this {@link RealmObjectSchema} is immutable.\n     */\n    public abstract RealmObjectSchema addIndex(String fieldName);\n\n    /**\n     * Checks if a given field has an index defined.\n     *\n     * @param fieldName existing field name to check.\n     * @return {@code true} if field is indexed, {@code false} otherwise.\n     * @throws IllegalArgumentException if field name doesn't exist.\n     * @see io.realm.annotations.Index\n     */\n    public boolean hasIndex(String fieldName) {\n        checkLegalName(fieldName);\n        checkFieldExists(fieldName);\n        return table.hasSearchIndex(table.getColumnKey(fieldName));\n    }\n\n    /**\n     * Removes an index from a given field. This is the same as removing the {@code @Index} annotation on the field.\n     *\n     * @param fieldName field to remove index from.\n     * @return the updated schema.\n     * @throws IllegalArgumentException if field name doesn't exist or the field doesn't have an index.\n     * @throws UnsupportedOperationException if this {@link RealmObjectSchema} is immutable or of a synced Realm.\n     */\n    public abstract RealmObjectSchema removeIndex(String fieldName);\n\n    /**\n     * Adds a primary key to a given field. This is the same as adding the {@link io.realm.annotations.PrimaryKey}\n     * annotation on the field. Further, this implicitly adds {@link io.realm.annotations.Index} annotation to the field\n     * as well.\n     *\n     * @param fieldName field to set as primary key.\n     * @return the updated schema.\n     * @throws IllegalArgumentException if field name doesn't exist, the field cannot be a primary key or it already\n     * has a primary key defined.\n     * @throws UnsupportedOperationException if this {@link RealmObjectSchema} is immutable or of a synced Realm.\n     */\n    public abstract RealmObjectSchema addPrimaryKey(String fieldName);\n\n    /**\n     * Removes the primary key from this class. This is the same as removing the {@link io.realm.annotations.PrimaryKey}\n     * annotation from the class. Further, this implicitly removes {@link io.realm.annotations.Index} annotation from\n     * the field as well.\n     *\n     * @return the updated schema.\n     * @throws IllegalArgumentException if the class doesn't have a primary key defined.\n     * @throws UnsupportedOperationException if this {@link RealmObjectSchema} is immutable or of a synced Realm.\n     */\n    public abstract RealmObjectSchema removePrimaryKey();\n\n    /**\n     * Sets a field to be required i.e., it is not allowed to hold {@code null} values. This is equivalent to switching\n     * between boxed types and their primitive variant e.g., {@code Integer} to {@code int}.\n     * <p>\n     * If the type of designated field is a list of values (not {@link RealmObject}s , specified nullability\n     * only affects its elements, not the field itself. Value list itself is always non-nullable.\n     *\n     * @param fieldName name of field in the class.\n     * @param required {@code true} if field should be required, {@code false} otherwise.\n     * @return the updated schema.\n     * @throws IllegalArgumentException if the field name doesn't exist, cannot have the {@link Required} annotation or\n     * the field already have been set as required.\n     * @throws UnsupportedOperationException if this {@link RealmObjectSchema} is immutable.\n     * @see Required\n     */\n    public abstract RealmObjectSchema setRequired(String fieldName, boolean required);\n\n    /**\n     * Sets a field to be nullable i.e., it should be able to hold {@code null} values. This is equivalent to switching\n     * between primitive types and their boxed variant e.g., {@code int} to {@code Integer}.\n     * <p>\n     * If the type of designated field is a list of values (not {@link RealmObject}s , specified nullability\n     * only affects its elements, not the field itself. Value list itself is always non-nullable.\n     *\n     * @param fieldName name of field in the class.\n     * @param nullable {@code true} if field should be nullable, {@code false} otherwise.\n     * @return the updated schema.\n     * @throws IllegalArgumentException if the field name doesn't exist, or cannot be set as nullable.\n     * @throws UnsupportedOperationException if this {@link RealmObjectSchema} is immutable.\n     */\n    public abstract RealmObjectSchema setNullable(String fieldName, boolean nullable);\n\n    /**\n     * Checks if a given field is required i.e., it is not allowed to contain {@code null} values.\n     *\n     * @param fieldName field to check.\n     * @return {@code true} if it is required, {@code false} otherwise.\n     * @throws IllegalArgumentException if field name doesn't exist.\n     * @see #setRequired(String, boolean)\n     */\n    public boolean isRequired(String fieldName) {\n        long columnIndex = getColumnKey(fieldName);\n        return !table.isColumnNullable(columnIndex);\n    }\n\n    /**\n     * Checks if a given field is nullable i.e., it is allowed to contain {@code null} values.\n     *\n     * @param fieldName field to check.\n     * @return {@code true} if it is required, {@code false} otherwise.\n     * @throws IllegalArgumentException if field name doesn't exist.\n     * @see #setNullable(String, boolean)\n     */\n    public boolean isNullable(String fieldName) {\n        long columnIndex = getColumnKey(fieldName);\n        return table.isColumnNullable(columnIndex);\n    }\n\n    /**\n     * Checks if a given field is the primary key field.\n     *\n     * @param fieldName field to check.\n     * @return {@code true} if it is the primary key field, {@code false} otherwise.\n     * @throws IllegalArgumentException if field name doesn't exist.\n     * @see #addPrimaryKey(String)\n     */\n    public boolean isPrimaryKey(String fieldName) {\n        checkFieldExists(fieldName);\n        return fieldName.equals(OsObjectStore.getPrimaryKeyForObject(realm.sharedRealm, getClassName()));\n    }\n\n    /**\n     * Checks if the class has a primary key defined.\n     *\n     * @return {@code true} if a primary key is defined, {@code false} otherwise.\n     * @see io.realm.annotations.PrimaryKey\n     */\n    public boolean hasPrimaryKey() {\n        return OsObjectStore.getPrimaryKeyForObject(realm.sharedRealm, getClassName()) != null;\n    }\n\n    /**\n     * Returns the name of the primary key field.\n     *\n     * @return the name of the primary key field.\n     * @throws IllegalStateException if the class doesn't have a primary key defined.\n     */\n    public String getPrimaryKey() {\n        String pkField = OsObjectStore.getPrimaryKeyForObject(realm.sharedRealm, getClassName());\n        if (pkField == null) {\n            throw new IllegalStateException(getClassName() + \" doesn't have a primary key.\");\n        }\n        return pkField;\n    }\n\n    /**\n     * Returns all fields in this class.\n     *\n     * @return a list of all the fields in this class.\n     */\n    public Set<String> getFieldNames() {\n        int columnCount = (int) table.getColumnCount();\n        Set<String> columnNames = new LinkedHashSet<>(columnCount);\n        for (String column : table.getColumnNames()) {\n                columnNames.add(column);\n        }\n        return columnNames;\n    }\n\n    /**\n     * Runs a transformation function on each RealmObject instance of the current class. The object will be represented\n     * as a {@link DynamicRealmObject}.\n     * <p>\n     * There is no guarantees in which order the objects are returned.\n     *\n     * @param function transformation function.\n     * @return this schema.\n     * @throws UnsupportedOperationException if this {@link RealmObjectSchema} is immutable.\n     */\n    public abstract RealmObjectSchema transform(Function function);\n\n    /**\n     * Returns the type used by the underlying storage engine to represent this field.\n     *\n     * @param fieldName name of the target field.\n     * @return the underlying type used by Realm to represent this field.\n     */\n    public RealmFieldType getFieldType(String fieldName) {\n        long columnKey = getColumnKey(fieldName);\n        return table.getColumnType(columnKey);\n    }\n\n    /**\n     * Returns {@code true} if objects of this type are considered \"embedded\".\n     * See {@link RealmClass#embedded()} for further details.\n     *\n     * @return {@code true} if objects of this type are embedded. {@code false} if not.\n     */\n    public boolean isEmbedded() {\n        return table.isEmbedded();\n    }\n\n    /**\n     * Converts the class to be embedded or not.\n     * <p>\n     * A class can only be marked as embedded if the following invariants are satisfied:\n     * <ul>\n     *     <li>\n     *         The class is not allowed to have a primary key defined.\n     *     </li>\n     *     <li>\n     *         All existing objects of this type, must have one and exactly one parent object\n     *         already pointing to it. If 0 or more than 1 object has a reference to an object\n     *         about to be marked embedded an {@link IllegalStateException} will be thrown.\n     *     </li>\n     * </ul>\n     *\n     * @param embedded If @{code true}, the class type will be turned into an embedded class, and\n     * must satisfy the constraints defined above. If @{code false}, the class will be turn into\n     * a normal class. An embeded class can always be turned into a non-embedded one.\n     * @throws IllegalStateException if the class could not be converted because it broke some of\n     * the Embedded Objects invariants.\n     * @see RealmClass#embedded()\n     */\n    public void setEmbedded(boolean embedded) {\n        setEmbedded(embedded, false);\n    }\n\n    /**\n     * Converts the class to be embedded or not, while also providing automatic handling of objects\n     * that break some of the constraints for making the class embedded.\n     * <p>\n     * A class can only be marked as embedded if the following invariants are satisfied:\n     * <ul>\n     *     <li>\n     *         The class is not allowed to have a primary key defined.\n     *     </li>\n     *     <li>\n     *         All existing objects of this type, must have one and exactly one parent object\n     *         already pointing to it. If 0 or more than 1 object has a reference to an object\n     *         about to be marked embedded an {@link IllegalStateException} will be thrown.\n     *     </li>\n     * </ul>\n     *\n     * If some of these constraints are broken you can ask Realm to resolve them automatically using\n     * the @{code resolveEmbeddedClassConstraints} parameter. Setting this to @{code true} will\n     * do the following:\n     * <ul>\n     *     <li>\n     *         An object with 0 parents, i.e. no other objects have a reference to it, will be\n     *         deleted.\n     *     </li>\n     *     <li>\n     *         An object with more than 1 parent, i.e. 2 or more objects have a reference to it,\n     *         will be copied so each copy have exactly one parent.\n     *     </li>\n     *     <li>\n     *         Objects with a primary key defined will still throw an IllegalStateException and\n     *         cannot be converted.\n     *     </li>\n     * </ul>\n     *\n     * @param embedded If @{code true}, the class type will be turned into an embedded class, and\n     * must satisfy the constraints defined above. If @{code false}, the class will be turn into\n     * a normal class. An embeded class can always be turned into a non-embedded one.\n     * @param resolveEmbeddedClassConstraints whether or not to automatically fix broken constraints\n     * if @{code embedded} was set to true. See above for a full description of what that entails.\n     * @throws IllegalStateException if the class could not be converted because it broke some of\n     * the Embedded Objects invariants and these could not be resolved automatically.\n     * @see RealmClass#embedded()\n     */\n    public void setEmbedded(boolean embedded, boolean resolveEmbeddedClassConstraints) {\n        if (hasPrimaryKey()) {\n            throw new IllegalStateException(\"Embedded classes cannot have primary keys. This class \" +\n                    \"has a primary key defined so cannot be marked as embedded: \" + getClassName());\n        }\n        boolean setEmbedded = table.setEmbedded(embedded, resolveEmbeddedClassConstraints);\n        if (!setEmbedded && embedded) {\n            throw new IllegalStateException(\"The class could not be marked as embedded as some \" +\n                    \"objects of this type break some of the Embedded Objects invariants. In order to convert \" +\n                    \"all objects to be embedded, they must have one and exactly one parent object\" +\n                    \"pointing to them.\");\n        }\n    }\n\n    /**\n     * Returns a string with the class name of a given property.\n     * @param propertyName the property for which we want to know the class name.\n     * @return the name of the class for the given property.\n     * @throws IllegalArgumentException if the given property is not found in the schema.\n     */\n    abstract String getPropertyClassName(String propertyName);\n\n    /**\n     * Checks whether a given property's {@code RealmFieldType} could host an acceptable embedded\n     * object reference in a parent - acceptable embedded object types are\n     * {@link RealmFieldType#OBJECT} and {@link RealmFieldType#LIST}, i.e. for the property to be\n     * acceptable it has to be either a subclass of {@code RealmModel} or a {@code RealmList}.\n     * <p>\n     * This method does not check the existence of a backlink between the child and the parent nor\n     * that the parent points at the correct child in their respective schemas nor that the object\n     * is a suitable parent/child.\n     * @param property the field type to be checked.\n     * @return whether the property could host an embedded object in a parent.\n     */\n    boolean isPropertyAcceptableForEmbeddedObject(RealmFieldType property) {\n        return property == RealmFieldType.OBJECT\n                || property == RealmFieldType.LIST;\n    }\n\n    RealmObjectSchema add(String name, RealmFieldType type, boolean primary, boolean indexed, boolean required) {\n        long columnIndex = table.addColumn(type, name, (required) ? Table.NOT_NULLABLE : Table.NULLABLE);\n\n        if (indexed) { table.addSearchIndex(columnIndex); }\n\n        if (primary) {\n            OsObjectStore.setPrimaryKeyForObject(realm.sharedRealm, getClassName(), name);\n        }\n\n        return this;\n    }\n\n    RealmObjectSchema add(String name, RealmFieldType type, RealmObjectSchema linkedTo) {\n        table.addColumnLink(\n                type,\n                name,\n                realm.getSharedRealm().getTable(Table.getTableNameForClass(linkedTo.getClassName())));\n        return this;\n    }\n\n    long getAndCheckFieldColumnKey(String fieldName) {\n        long columnKey = columnInfo.getColumnKey(fieldName);\n        if (columnKey < 0) {\n            throw new IllegalArgumentException(\"Field does not exist: \" + fieldName);\n        }\n        return columnKey;\n    }\n\n    Table getTable() {\n        return table;\n    }\n\n    /**\n     * Function interface, used when traversing all objects of the current class and apply a function on each.\n     *\n     * @see #transform(Function)\n     */\n    public interface Function {\n        void apply(DynamicRealmObject obj);\n    }\n\n    /**\n     * Returns the column index in the underlying table for the given field name.\n     * <b>FOR TESTING USE ONLY!</b>\n     *\n     * @param fieldName field name to find index for.\n     * @return column index or -1 if it doesn't exists.\n     */\n    //@VisibleForTesting(otherwise = VisibleForTesting.NONE)\n    long getFieldColumnKey(String fieldName) {\n        return columnInfo.getColumnKey(fieldName);\n    }\n\n    static void checkLegalName(String fieldName) {\n        //noinspection ConstantConditions\n        if (fieldName == null || fieldName.isEmpty()) {\n            throw new IllegalArgumentException(\"Field name can not be null or empty\");\n        }\n        if (fieldName.contains(\".\")) {\n            throw new IllegalArgumentException(\"Field name can not contain '.'\");\n        }\n        if (fieldName.length() > 63) {\n            throw new IllegalArgumentException(\"Field name is currently limited to max 63 characters.\");\n        }\n    }\n\n    void checkFieldExists(String fieldName) {\n        if (table.getColumnKey(fieldName) == Table.NO_MATCH) {\n            throw new IllegalArgumentException(\"Field name doesn't exist on object '\" + getClassName() + \"': \" + fieldName);\n        }\n    }\n\n    long getColumnKey(String fieldName) {\n        long columnKey = table.getColumnKey(fieldName);\n        if (columnKey == -1) {\n            throw new IllegalArgumentException(\n                    String.format(Locale.US,\n                            \"Field name '%s' does not exist on schema for '%s'\",\n                            fieldName, getClassName()\n                    ));\n        }\n        return columnKey;\n    }\n\n    static final class DynamicColumnIndices extends ColumnInfo {\n        private final Table table;\n\n        DynamicColumnIndices(Table table) {\n            super(null, false);\n            this.table = table;\n        }\n\n        @Override\n        public long getColumnKey(String columnName) {\n            return table.getColumnKey(columnName);\n        }\n\n        @Override\n        public ColumnDetails getColumnDetails(String columnName) {\n            throw new UnsupportedOperationException(\"DynamicColumnIndices do not support 'getColumnDetails'\");\n        }\n\n        @Override\n        public void copyFrom(ColumnInfo src) {\n            throw new UnsupportedOperationException(\"DynamicColumnIndices cannot be copied\");\n        }\n\n        @Override\n        protected ColumnInfo copy(boolean immutable) {\n            throw new UnsupportedOperationException(\"DynamicColumnIndices cannot be copied\");\n        }\n\n\n        @Override\n        protected void copy(ColumnInfo src, ColumnInfo dst) {\n            throw new UnsupportedOperationException(\"DynamicColumnIndices cannot copy\");\n        }\n    }\n\n    // Tuple containing data about each supported Java type.\n    static final class FieldMetaData {\n        final RealmFieldType fieldType; // Underlying Realm type for fields with this type\n        final RealmFieldType collectionType; // Underlying Realm type for RealmLists and RealmDictionaries containing this type\n        final boolean defaultNullable;\n\n        FieldMetaData(RealmFieldType fieldType, @Nullable RealmFieldType collectionType, boolean defaultNullable) {\n            this.fieldType = fieldType;\n            this.collectionType = collectionType;\n            this.defaultNullable = defaultNullable;\n        }\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/RealmQuery.java",
    "content": "/*\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\npackage io.realm;\n\n\nimport org.bson.types.Decimal128;\nimport org.bson.types.ObjectId;\n\nimport java.util.Collections;\nimport java.util.Date;\nimport java.util.Locale;\nimport java.util.Map;\nimport java.util.UUID;\n\nimport javax.annotation.Nullable;\n\nimport io.realm.annotations.Required;\nimport io.realm.exceptions.RealmException;\nimport io.realm.internal.OsCollection;\nimport io.realm.internal.OsList;\nimport io.realm.internal.OsResults;\nimport io.realm.internal.OsSet;\nimport io.realm.internal.PendingRow;\nimport io.realm.internal.RealmObjectProxy;\nimport io.realm.internal.Row;\nimport io.realm.internal.Table;\nimport io.realm.internal.TableQuery;\nimport io.realm.internal.Util;\n\n\n/**\n * A RealmQuery encapsulates a query on a {@link io.realm.Realm} or a {@link io.realm.RealmResults} using the Builder\n * pattern. The query is executed using either {@link #findAll()} or {@link #findFirst()}.\n * <p>\n * The input to many of the query functions take a field name as String. Note that this is not type safe. If a\n * RealmObject class is refactored care has to be taken to not break any queries.\n * <p>\n * A {@link io.realm.Realm} is unordered, which means that there is no guarantee that querying a Realm will return the\n * objects in the order they where inserted. Use {@link #sort(String)} (String)} and similar methods if a specific order\n * is required.\n * <p>\n * A RealmQuery cannot be passed between different threads.\n * <p>\n * Results are obtained quickly most of the times. However, launching heavy queries from the UI thread may result\n * in a drop of frames or even ANRs. If you want to prevent these behaviors, you can instantiate a Realm using a\n * {@link RealmConfiguration} that explicitly sets {@link RealmConfiguration.Builder#allowQueriesOnUiThread(boolean)} to\n * {@code false}. This way queries will be forced to be launched from a non-UI thread. Alternatively, you can also use\n * {@link #findAllAsync()} or {@link #findFirstAsync()}.\n *\n * @param <E> the class of the objects to be queried.\n * @see <a href=\"http://en.wikipedia.org/wiki/Builder_pattern\">Builder pattern</a>\n * @see Realm#where(Class)\n * @see RealmResults#where()\n */\npublic class RealmQuery<E> {\n\n    private final Table table;\n    private final BaseRealm realm;\n    private final TableQuery query; // FIXME Make private somehow\n    private final RealmObjectSchema schema;\n    private Class<E> clazz;\n    private String className;\n    private final boolean forValues;\n    private final OsCollection osCollection;\n\n    private static final String PRIMITIVE_LISTS_NOT_SUPPORTED_ERROR_MESSAGE = \"Queries on primitive lists are not yet supported\";\n    private static final String TYPE_MISMATCH = \"Field '%s': type mismatch - %s expected.\";\n    private static final String EMPTY_VALUES = \"Non-empty 'values' must be provided.\";\n    private static final String ASYNC_QUERY_WRONG_THREAD_MESSAGE = \"Async query cannot be created on current thread.\";\n\n    /**\n     * Creates a query for objects of a given class from a {@link Realm}.\n     *\n     * @param realm the realm to query within.\n     * @param clazz the class to query.\n     * @return {@link RealmQuery} object. After building the query call one of the {@code find*} methods\n     * to run it.\n     */\n    static <E extends RealmModel> RealmQuery<E> createQuery(Realm realm, Class<E> clazz) {\n        return new RealmQuery<>(realm, clazz);\n    }\n\n    /**\n     * Creates a query for dynamic objects of a given type from a {@link DynamicRealm}.\n     *\n     * @param realm     the realm to query within.\n     * @param className the type to query.\n     * @return {@link RealmQuery} object. After building the query call one of the {@code find*} methods\n     * to run it.\n     */\n    static <E extends RealmModel> RealmQuery<E> createDynamicQuery(DynamicRealm realm, String className) {\n        return new RealmQuery<>(realm, className);\n    }\n\n    /**\n     * Creates a query from an existing {@link RealmResults}.\n     *\n     * @param queryResults an existing @{link io.realm.RealmResults} to query against.\n     * @return {@link RealmQuery} object. After building the query call one of the {@code find*} methods\n     * to run it.\n     */\n    @SuppressWarnings(\"unchecked\")\n    static <E> RealmQuery<E> createQueryFromResult(RealmResults<E> queryResults) {\n        //noinspection ConstantConditions\n        return (queryResults.classSpec == null)\n                ? new RealmQuery(queryResults, queryResults.className)\n                : new RealmQuery<>(queryResults, queryResults.classSpec);\n    }\n\n    /**\n     * Creates a query from an existing {@link RealmList}.\n     *\n     * @param list an existing @{link io.realm.RealmList} to query against.\n     * @return {@link RealmQuery} object. After building the query call one of the {@code find*} methods\n     * to run it.\n     */\n    @SuppressWarnings(\"unchecked\")\n    static <E> RealmQuery<E> createQueryFromList(RealmList<E> list) {\n        //noinspection ConstantConditions\n        return (list.clazz == null)\n                ? new RealmQuery(list.baseRealm, list.getOsList(), list.className)\n                : new RealmQuery(list.baseRealm, list.getOsList(), list.clazz);\n    }\n\n    private static boolean isClassForRealmModel(Class<?> clazz) {\n        return RealmModel.class.isAssignableFrom(clazz);\n    }\n\n    private RealmQuery(Realm realm, Class<E> clazz) {\n        this.realm = realm;\n        this.clazz = clazz;\n        this.forValues = !isClassForRealmModel(clazz);\n        if (forValues) {\n            throw new UnsupportedOperationException(PRIMITIVE_LISTS_NOT_SUPPORTED_ERROR_MESSAGE);\n        } else {\n            //noinspection unchecked\n            this.schema = realm.getSchema().getSchemaForClass((Class<? extends RealmModel>) clazz);\n            this.table = schema.getTable();\n            this.osCollection = null;\n            this.query = table.where();\n        }\n    }\n\n    private RealmQuery(RealmResults<E> queryResults, Class<E> clazz) {\n        this.realm = queryResults.baseRealm;\n        this.clazz = clazz;\n        this.forValues = !isClassForRealmModel(clazz);\n        if (forValues) {\n            throw new UnsupportedOperationException(PRIMITIVE_LISTS_NOT_SUPPORTED_ERROR_MESSAGE);\n        } else {\n            //noinspection unchecked\n            this.schema = realm.getSchema().getSchemaForClass((Class<? extends RealmModel>) clazz);\n            this.table = queryResults.getTable();\n            this.osCollection = null;\n            this.query = queryResults.getOsResults().where();\n        }\n    }\n\n    private RealmQuery(BaseRealm realm, OsList osList, Class<E> clazz) {\n        this.realm = realm;\n        this.clazz = clazz;\n        this.forValues = !isClassForRealmModel(clazz);\n        if (forValues) {\n            throw new UnsupportedOperationException(PRIMITIVE_LISTS_NOT_SUPPORTED_ERROR_MESSAGE);\n        } else {\n            //noinspection unchecked\n            this.schema = realm.getSchema().getSchemaForClass((Class<? extends RealmModel>) clazz);\n            this.table = schema.getTable();\n            this.osCollection = osList;\n            this.query = osList.getQuery();\n        }\n    }\n\n    RealmQuery(BaseRealm realm, OsSet osSet, Class<E> clazz) {\n        this.realm = realm;\n        this.clazz = clazz;\n        this.forValues = !isClassForRealmModel(clazz);\n        if (forValues) {\n            throw new UnsupportedOperationException(PRIMITIVE_LISTS_NOT_SUPPORTED_ERROR_MESSAGE);\n        } else {\n            //noinspection unchecked\n            this.schema = realm.getSchema().getSchemaForClass((Class<? extends RealmModel>) clazz);\n            this.table = schema.getTable();\n            this.osCollection = osSet;\n            this.query = osSet.getQuery();\n        }\n    }\n\n    private RealmQuery(BaseRealm realm, String className) {\n        this.realm = realm;\n        this.className = className;\n        this.forValues = false;\n        this.schema = realm.getSchema().getSchemaForClass(className);\n        this.table = schema.getTable();\n        this.query = table.where();\n        this.osCollection = null;\n    }\n\n    private RealmQuery(RealmResults<DynamicRealmObject> queryResults, String className) {\n        this.realm = queryResults.baseRealm;\n        this.className = className;\n        this.forValues = false;\n        this.schema = realm.getSchema().getSchemaForClass(className);\n        this.table = schema.getTable();\n        this.query = queryResults.getOsResults().where();\n        this.osCollection = null;\n    }\n\n    private RealmQuery(BaseRealm realm, OsList osList, String className) {\n        this.realm = realm;\n        this.className = className;\n        this.forValues = false;\n        this.schema = realm.getSchema().getSchemaForClass(className);\n        this.table = schema.getTable();\n        this.query = osList.getQuery();\n        this.osCollection = osList;\n    }\n\n    /**\n     * Checks if {@link io.realm.RealmQuery} is still valid to use i.e., the {@link io.realm.Realm} instance hasn't been\n     * closed and any parent {@link io.realm.RealmResults} is still valid.\n     *\n     * @return {@code true} if still valid to use, {@code false} otherwise.\n     */\n    public boolean isValid() {\n        if ((realm == null) || realm.isClosed() /* this includes thread checking */) {\n            return false;\n        }\n\n        if (osCollection != null) {\n            return osCollection.isValid();\n        }\n        return (table != null) && table.isValid();\n    }\n\n    /**\n     * Tests if a field is {@code null}. Only works for nullable fields.\n     * <p>\n     * For link queries, if any part of the link path is {@code null} the whole path is considered to be {@code null}\n     * e.g., {@code isNull(\"linkField.stringField\")} will be considered to be {@code null} if either {@code linkField} or\n     * {@code linkField.stringField} is {@code null}.\n     *\n     * @param fieldName the field name.\n     * @return the query object.\n     * @throws java.lang.IllegalArgumentException if the field is not nullable.\n     * @see Required for further infomation.\n     */\n    public RealmQuery<E> isNull(String fieldName) {\n        realm.checkIfValid();\n        // Checks that fieldName has the correct type is done in C++.\n        this.query.isNull(realm.getSchema().getKeyPathMapping(), fieldName);\n        return this;\n    }\n\n    /**\n     * Tests if a field is not {@code null}. Only works for nullable fields.\n     *\n     * @param fieldName the field name.\n     * @return the query object.\n     * @throws java.lang.IllegalArgumentException if the field is not nullable.\n     * @see Required for further infomation.\n     */\n    public RealmQuery<E> isNotNull(String fieldName) {\n        realm.checkIfValid();\n        this.query.isNotNull(realm.getSchema().getKeyPathMapping(), fieldName);\n        return this;\n    }\n\n    /**\n     * Equal-to comparison.\n     *\n     * @param fieldName the field to compare.\n     * @param value     the value to compare with.\n     * @return the query object.\n     * @throws java.lang.IllegalArgumentException if one or more arguments do not match class or field type.\n     */\n    public RealmQuery<E> equalTo(String fieldName, @Nullable String value) {\n        return this.equalTo(fieldName, value, Case.SENSITIVE);\n    }\n\n    /**\n     * Equal-to comparison.\n     *\n     * @param fieldName the field to compare.\n     * @param value     the value to compare with.\n     * @param casing    how to handle casing. Setting this to {@link Case#INSENSITIVE} only works for Latin-1 characters.\n     * @return the query object.\n     * @throws java.lang.IllegalArgumentException if one or more arguments do not match class or field type.\n     */\n    public RealmQuery<E> equalTo(String fieldName, @Nullable String value, Case casing) {\n        realm.checkIfValid();\n        equalTo(fieldName, RealmAny.valueOf(value), casing);\n        return this;\n    }\n\n    /**\n     * Equal-to comparison.\n     *\n     * @param fieldName the field to compare.\n     * @param value     the value to compare with.\n     * @param casing    how to handle casing. Setting this to {@link Case#INSENSITIVE} only works for Latin-1 characters.\n     * @return the query object.\n     * @throws java.lang.IllegalArgumentException if one or more arguments do not match class or field type.\n     */\n    public RealmQuery<E> equalTo(String fieldName, RealmAny value, Case casing) {\n        realm.checkIfValid();\n        if (casing == Case.SENSITIVE) {\n            this.query.equalTo(realm.getSchema().getKeyPathMapping(), fieldName, value);\n        } else {\n            this.query.equalToInsensitive(realm.getSchema().getKeyPathMapping(), fieldName, value);\n        }\n        return this;\n    }\n\n    /**\n     * Equal-to comparison.\n     *\n     * @param fieldName the field to compare.\n     * @param value     the value to compare with.\n     * @return the query object.\n     * @throws java.lang.IllegalArgumentException if one or more arguments do not match class or field type.\n     */\n    public RealmQuery<E> equalTo(String fieldName, @Nullable Decimal128 value) {\n        realm.checkIfValid();\n        this.query.equalTo(realm.getSchema().getKeyPathMapping(), fieldName, RealmAny.valueOf(value));\n        return this;\n    }\n\n    /**\n     * Equal-to comparison.\n     *\n     * @param fieldName the field to compare.\n     * @param value     the value to compare with.\n     * @return the query object.\n     * @throws java.lang.IllegalArgumentException if one or more arguments do not match class or field type.\n     */\n    public RealmQuery<E> equalTo(String fieldName, @Nullable ObjectId value) {\n        realm.checkIfValid();\n        this.query.equalTo(realm.getSchema().getKeyPathMapping(), fieldName, RealmAny.valueOf(value));\n        return this;\n    }\n\n    /**\n     * Equal-to comparison.\n     *\n     * @param fieldName the field to compare.\n     * @param value     the value to compare with.\n     * @return the query object.\n     * @throws java.lang.IllegalArgumentException if one or more arguments do not match class or field type.\n     */\n    public RealmQuery<E> equalTo(String fieldName, @Nullable UUID value) {\n        realm.checkIfValid();\n        this.query.equalTo(realm.getSchema().getKeyPathMapping(), fieldName, RealmAny.valueOf(value));\n        return this;\n    }\n\n    /**\n     * Equal-to comparison.\n     *\n     * @param fieldName the field to compare.\n     * @param value     the value to compare with.\n     * @return the query object.\n     * @throws java.lang.IllegalArgumentException if one or more arguments do not match class or field type.\n     */\n    public RealmQuery<E> equalTo(String fieldName, @Nullable Byte value) {\n        realm.checkIfValid();\n        this.query.equalTo(realm.getSchema().getKeyPathMapping(), fieldName, RealmAny.valueOf(value));\n        return this;\n    }\n\n    /**\n     * Equal-to comparison.\n     *\n     * @param fieldName the field to compare.\n     * @param value     the value to compare with.\n     * @return the query object.\n     * @throws java.lang.IllegalArgumentException if one or more arguments do not match class or field type.\n     */\n    public RealmQuery<E> equalTo(String fieldName, @Nullable byte[] value) {\n        realm.checkIfValid();\n        this.query.equalTo(realm.getSchema().getKeyPathMapping(), fieldName, RealmAny.valueOf(value));\n        return this;\n    }\n\n    /**\n     * Equal-to comparison.\n     *\n     * @param fieldName the field to compare.\n     * @param value     the value to compare with.\n     * @return the query object.\n     * @throws java.lang.IllegalArgumentException if one or more arguments do not match class or field type.\n     */\n    public RealmQuery<E> equalTo(String fieldName, @Nullable Short value) {\n        realm.checkIfValid();\n        this.query.equalTo(realm.getSchema().getKeyPathMapping(), fieldName, RealmAny.valueOf(value));\n        return this;\n    }\n\n    /**\n     * Equal-to comparison.\n     *\n     * @param fieldName the field to compare.\n     * @param value     the value to compare with.\n     * @return the query object.\n     * @throws java.lang.IllegalArgumentException if one or more arguments do not match class or field type.\n     */\n    public RealmQuery<E> equalTo(String fieldName, @Nullable Integer value) {\n        realm.checkIfValid();\n        this.query.equalTo(realm.getSchema().getKeyPathMapping(), fieldName, RealmAny.valueOf(value));\n        return this;\n    }\n\n\n    /**\n     * Equal-to comparison.\n     *\n     * @param fieldName the field to compare.\n     * @param value     the value to compare with.\n     * @return the query object.\n     * @throws java.lang.IllegalArgumentException if one or more arguments do not match class or field type.\n     */\n    public RealmQuery<E> equalTo(String fieldName, @Nullable Long value) {\n        realm.checkIfValid();\n        this.query.equalTo(realm.getSchema().getKeyPathMapping(), fieldName, RealmAny.valueOf(value));\n        return this;\n    }\n\n    /**\n     * Equal-to comparison.\n     *\n     * @param fieldName the field to compare.\n     * @param value     the value to compare with.\n     * @return the query object.\n     * @throws java.lang.IllegalArgumentException if one or more arguments do not match class or field type.\n     */\n    public RealmQuery<E> equalTo(String fieldName, @Nullable Double value) {\n        realm.checkIfValid();\n        this.query.equalTo(realm.getSchema().getKeyPathMapping(), fieldName, RealmAny.valueOf(value));\n        return this;\n    }\n\n    /**\n     * Equal-to comparison.\n     *\n     * @param fieldName the field to compare.\n     * @param value     the value to compare with.\n     * @return The query object.\n     * @throws java.lang.IllegalArgumentException if one or more arguments do not match class or field type.\n     */\n    public RealmQuery<E> equalTo(String fieldName, @Nullable Float value) {\n        realm.checkIfValid();\n        this.query.equalTo(realm.getSchema().getKeyPathMapping(), fieldName, RealmAny.valueOf(value));\n        return this;\n    }\n\n    /**\n     * Equal-to comparison.\n     *\n     * @param fieldName the field to compare.\n     * @param value     the value to compare with.\n     * @return the query object.\n     * @throws java.lang.IllegalArgumentException if one or more arguments do not match class or field type.\n     */\n    public RealmQuery<E> equalTo(String fieldName, @Nullable Boolean value) {\n        realm.checkIfValid();\n        this.query.equalTo(realm.getSchema().getKeyPathMapping(), fieldName, RealmAny.valueOf(value));\n        return this;\n    }\n\n    /**\n     * Equal-to comparison.\n     *\n     * @param fieldName the field to compare.\n     * @param value     the value to compare with.\n     * @return the query object.\n     * @throws java.lang.IllegalArgumentException if one or more arguments do not match class or field type.\n     */\n    public RealmQuery<E> equalTo(String fieldName, @Nullable Date value) {\n        realm.checkIfValid();\n        this.query.equalTo(realm.getSchema().getKeyPathMapping(), fieldName, RealmAny.valueOf(value));\n        return this;\n    }\n\n    /**\n     * Equal-to comparison.\n     *\n     * @param fieldName the field to compare.\n     * @param value     the value to compare with.\n     * @return the query object.\n     * @throws java.lang.IllegalArgumentException if one or more arguments do not match class or field type.\n     */\n    public RealmQuery<E> equalTo(String fieldName, RealmAny value) {\n        realm.checkIfValid();\n        this.query.equalTo(realm.getSchema().getKeyPathMapping(), fieldName, value);\n        return this;\n    }\n\n    /**\n     * In comparison. This allows you to test if objects match any value in an array of values.\n     *\n     * @param fieldName the field to compare.\n     * @param values    array of values to compare with. If {@code null} or the empty array is provided the query will never\n     *                  match any results.\n     * @return the query object.\n     * @throws java.lang.IllegalArgumentException if the field isn't a String field.\n     */\n    public RealmQuery<E> in(String fieldName, @Nullable String[] values) {\n        return in(fieldName, values, Case.SENSITIVE);\n    }\n\n    /**\n     * In comparison. This allows you to test if objects match any value in an array of values.\n     *\n     * @param fieldName the field to compare.\n     * @param values    array of values to compare with. If {@code null} or the empty array is provided the query will never\n     *                  match any results.\n     * @param casing    how casing is handled. {@link Case#INSENSITIVE} works only for the Latin-1 characters.\n     * @return the query object.\n     * @throws java.lang.IllegalArgumentException if the field isn't a String field.\n     */\n    public RealmQuery<E> in(String fieldName, @Nullable String[] values, Case casing) {\n        realm.checkIfValid();\n\n        if ((values == null) || (values.length == 0)) {\n            alwaysFalse();\n        } else {\n            RealmAny[] realmAnyValues = new RealmAny[values.length];\n            for (int i = 0; i < values.length; i++) {\n                if (values[i] != null) {\n                    realmAnyValues[i] = RealmAny.valueOf(values[i]);\n                } else {\n                    realmAnyValues[i] = null;\n                }\n            }\n\n            if (casing == Case.SENSITIVE) {\n                query.in(realm.getSchema().getKeyPathMapping(), fieldName, realmAnyValues);\n            } else {\n                query.inInsensitive(realm.getSchema().getKeyPathMapping(), fieldName, realmAnyValues);\n            }\n        }\n        return this;\n    }\n\n    /**\n     * In comparison. This allows you to test if objects match any value in an array of values.\n     *\n     * @param fieldName the field to compare.\n     * @param values    array of values to compare with. If {@code null} or the empty array is provided the query will never\n     *                  match any results.\n     * @return the query object.\n     * @throws java.lang.IllegalArgumentException if the field isn't a Byte field.\n     */\n    public RealmQuery<E> in(String fieldName, @Nullable Byte[] values) {\n        realm.checkIfValid();\n\n        if ((values == null) || (values.length == 0)) {\n            alwaysFalse();\n        } else {\n            RealmAny[] realmAnyValues = new RealmAny[values.length];\n            for (int i = 0; i < values.length; i++) {\n                realmAnyValues[i] = RealmAny.valueOf(values[i]);\n            }\n            query.in(realm.getSchema().getKeyPathMapping(), fieldName, realmAnyValues);\n        }\n        return this;\n    }\n\n    /**\n     * In comparison. This allows you to test if objects match any value in an array of values.\n     *\n     * @param fieldName the field to compare.\n     * @param values    array of values to compare with. If {@code null} or the empty array is provided the query will never\n     *                  match any results.\n     * @return the query object.\n     * @throws java.lang.IllegalArgumentException if the field isn't a Short field.\n     */\n    public RealmQuery<E> in(String fieldName, @Nullable Short[] values) {\n        realm.checkIfValid();\n\n        if ((values == null) || (values.length == 0)) {\n            alwaysFalse();\n        } else {\n            RealmAny[] realmAnyValues = new RealmAny[values.length];\n            for (int i = 0; i < values.length; i++) {\n                realmAnyValues[i] = RealmAny.valueOf(values[i]);\n            }\n            query.in(realm.getSchema().getKeyPathMapping(), fieldName, realmAnyValues);\n        }\n        return this;\n    }\n\n    /**\n     * In comparison. This allows you to test if objects match any value in an array of values.\n     *\n     * @param fieldName the field to compare.\n     * @param values    array of values to compare with. If {@code null} or the empty array is provided the query will never\n     *                  match any results.\n     * @return the query object.\n     * @throws java.lang.IllegalArgumentException if the field isn't a Integer field.\n     */\n    public RealmQuery<E> in(String fieldName, @Nullable Integer[] values) {\n        realm.checkIfValid();\n\n        if ((values == null) || (values.length == 0)) {\n            alwaysFalse();\n        } else {\n            RealmAny[] realmAnyValues = new RealmAny[values.length];\n            for (int i = 0; i < values.length; i++) {\n                realmAnyValues[i] = RealmAny.valueOf(values[i]);\n            }\n            query.in(realm.getSchema().getKeyPathMapping(), fieldName, realmAnyValues);\n        }\n        return this;\n    }\n\n    /**\n     * In comparison. This allows you to test if objects match any value in an array of values.\n     *\n     * @param fieldName the field to compare.\n     * @param values    array of values to compare with. If {@code null} or the empty array is provided the query will never\n     *                  match any results.\n     * @return the query object.\n     * @throws java.lang.IllegalArgumentException if the field isn't a Long field.\n     *                                            empty.\n     */\n    public RealmQuery<E> in(String fieldName, @Nullable Long[] values) {\n        realm.checkIfValid();\n\n        if ((values == null) || (values.length == 0)) {\n            alwaysFalse();\n        } else {\n            RealmAny[] realmAnyValues = new RealmAny[values.length];\n            for (int i = 0; i < values.length; i++) {\n                realmAnyValues[i] = RealmAny.valueOf(values[i]);\n            }\n            query.in(realm.getSchema().getKeyPathMapping(), fieldName, realmAnyValues);\n        }\n        return this;\n    }\n\n    /**\n     * In comparison. This allows you to test if objects match any value in an array of values.\n     *\n     * @param fieldName the field to compare.\n     * @param values    array of values to compare with. If {@code null} or the empty array is provided the query will never\n     *                  match any results.\n     * @return the query object.\n     * @throws java.lang.IllegalArgumentException if the field isn't a Double field.\n     *                                            empty.\n     */\n    public RealmQuery<E> in(String fieldName, @Nullable Double[] values) {\n        realm.checkIfValid();\n\n        if ((values == null) || (values.length == 0)) {\n            alwaysFalse();\n        } else {\n            RealmAny[] realmAnyValues = new RealmAny[values.length];\n            for (int i = 0; i < values.length; i++) {\n                realmAnyValues[i] = RealmAny.valueOf(values[i]);\n            }\n            query.in(realm.getSchema().getKeyPathMapping(), fieldName, realmAnyValues);\n        }\n        return this;\n    }\n\n    /**\n     * In comparison. This allows you to test if objects match any value in an array of values.\n     *\n     * @param fieldName the field to compare.\n     * @param values    array of values to compare with. If {@code null} or the empty array is provided the query will never\n     *                  match any results.\n     * @return the query object.\n     * @throws java.lang.IllegalArgumentException if the field isn't a Float field.\n     */\n    public RealmQuery<E> in(String fieldName, @Nullable Float[] values) {\n        realm.checkIfValid();\n\n        if ((values == null) || (values.length == 0)) {\n            alwaysFalse();\n        } else {\n            RealmAny[] realmAnyValues = new RealmAny[values.length];\n            for (int i = 0; i < values.length; i++) {\n                realmAnyValues[i] = RealmAny.valueOf(values[i]);\n            }\n            query.in(realm.getSchema().getKeyPathMapping(), fieldName, realmAnyValues);\n        }\n        return this;\n    }\n\n    /**\n     * In comparison. This allows you to test if objects match any value in an array of values.\n     *\n     * @param fieldName the field to compare.\n     * @param values    array of values to compare with. If {@code null} or the empty array is provided the query will never\n     *                  match any results.\n     * @return the query object.\n     * @throws java.lang.IllegalArgumentException if the field isn't a Boolean.\n     *                                            or empty.\n     */\n    public RealmQuery<E> in(String fieldName, @Nullable Boolean[] values) {\n        realm.checkIfValid();\n\n        if ((values == null) || (values.length == 0)) {\n            alwaysFalse();\n        } else {\n            RealmAny[] realmAnyValues = new RealmAny[values.length];\n            for (int i = 0; i < values.length; i++) {\n                realmAnyValues[i] = RealmAny.valueOf(values[i]);\n            }\n            query.in(realm.getSchema().getKeyPathMapping(), fieldName, realmAnyValues);\n        }\n        return this;\n    }\n\n    /**\n     * In comparison. This allows you to test if objects match any value in an array of values.\n     *\n     * @param fieldName the field to compare.\n     * @param values    array of values to compare with. If {@code null} or the empty array is provided the query will never\n     *                  match any results.\n     * @return the query object.\n     * @throws java.lang.IllegalArgumentException if the field isn't a Date field.\n     */\n    public RealmQuery<E> in(String fieldName, @Nullable Date[] values) {\n        realm.checkIfValid();\n\n        if ((values == null) || (values.length == 0)) {\n            alwaysFalse();\n        } else {\n            RealmAny[] realmAnyValues = new RealmAny[values.length];\n            for (int i = 0; i < values.length; i++) {\n                realmAnyValues[i] = RealmAny.valueOf(values[i]);\n            }\n            query.in(realm.getSchema().getKeyPathMapping(), fieldName, realmAnyValues);\n        }\n        return this;\n    }\n\n    /**\n     * In comparison. This allows you to test if objects match any value in an array of values.\n     *\n     * @param fieldName the field to compare.\n     * @param values    array of values to compare with. If {@code null} or the empty array is provided the query will never\n     *                  match any results.\n     * @return the query object.\n     * @throws java.lang.IllegalArgumentException if the field isn't a Date field.\n     */\n    public RealmQuery<E> in(String fieldName, RealmAny[] values) {\n        realm.checkIfValid();\n\n        if ((values == null) || (values.length == 0)) {\n            alwaysFalse();\n        } else {\n            // Transform null values into RealmAny null values.\n            RealmAny[] realmAnyValues = new RealmAny[values.length];\n            for (int i = 0; i < values.length; i++) {\n                realmAnyValues[i] = (values[i] == null) ? RealmAny.nullValue() : values[i];\n            }\n            query.in(realm.getSchema().getKeyPathMapping(), fieldName, realmAnyValues);\n        }\n        return this;\n    }\n\n    /**\n     * Not-equal-to comparison.\n     *\n     * @param fieldName the field to compare.\n     * @param value     the value to compare with.\n     * @return the query object.\n     * @throws java.lang.IllegalArgumentException if one or more arguments do not match class or field type.\n     */\n    public RealmQuery<E> notEqualTo(String fieldName, @Nullable String value) {\n        return this.notEqualTo(fieldName, value, Case.SENSITIVE);\n    }\n\n    /**\n     * Not-equal-to comparison.\n     *\n     * @param fieldName the field to compare.\n     * @param value     the value to compare with.\n     * @param casing    how casing is handled. {@link Case#INSENSITIVE} works only for the Latin-1 characters.\n     * @return the query object.\n     * @throws java.lang.IllegalArgumentException if one or more arguments do not match class or field type.\n     */\n    public RealmQuery<E> notEqualTo(String fieldName, @Nullable String value, Case casing) {\n        realm.checkIfValid();\n        notEqualTo(fieldName, RealmAny.valueOf(value), casing);\n        return this;\n    }\n\n    /**\n     * Not-equal-to comparison.\n     *\n     * @param fieldName the field to compare.\n     * @param value     the value to compare with.\n     * @param casing    how casing is handled. {@link Case#INSENSITIVE} works only for the Latin-1 characters.\n     * @return the query object.\n     * @throws java.lang.IllegalArgumentException if one or more arguments do not match class or field type.\n     */\n    public RealmQuery<E> notEqualTo(String fieldName, RealmAny value, Case casing) {\n        realm.checkIfValid();\n        if (casing == Case.SENSITIVE) {\n            this.query.notEqualTo(realm.getSchema().getKeyPathMapping(), fieldName, value);\n        } else {\n            this.query.notEqualToInsensitive(realm.getSchema().getKeyPathMapping(), fieldName, value);\n        }\n        return this;\n    }\n\n    /**\n     * Not-equal-to comparison.\n     *\n     * @param fieldName the field to compare.\n     * @param value     the value to compare with.\n     * @return the query object.\n     * @throws java.lang.IllegalArgumentException if one or more arguments do not match class or field type.\n     */\n    public RealmQuery<E> notEqualTo(String fieldName, Decimal128 value) {\n        realm.checkIfValid();\n        this.query.notEqualTo(realm.getSchema().getKeyPathMapping(), fieldName, RealmAny.valueOf(value));\n        return this;\n    }\n\n    /**\n     * Not-equal-to comparison.\n     *\n     * @param fieldName the field to compare.\n     * @param value     the value to compare with.\n     * @return the query object.\n     * @throws java.lang.IllegalArgumentException if one or more arguments do not match class or field type.\n     */\n    public RealmQuery<E> notEqualTo(String fieldName, ObjectId value) {\n        realm.checkIfValid();\n        this.query.notEqualTo(realm.getSchema().getKeyPathMapping(), fieldName, RealmAny.valueOf(value));\n        return this;\n    }\n\n    /**\n     * Not-equal-to comparison.\n     *\n     * @param fieldName the field to compare.\n     * @param value     the value to compare with.\n     * @return the query object.\n     * @throws java.lang.IllegalArgumentException if one or more arguments do not match class or field type.\n     */\n    public RealmQuery<E> notEqualTo(String fieldName, UUID value) {\n        realm.checkIfValid();\n        this.query.notEqualTo(realm.getSchema().getKeyPathMapping(), fieldName, RealmAny.valueOf(value));\n        return this;\n    }\n\n    /**\n     * Not-equal-to comparison.\n     *\n     * @param fieldName the field to compare.\n     * @param value     the value to compare with.\n     * @return the query object.\n     * @throws java.lang.IllegalArgumentException if one or more arguments do not match class or field type.\n     */\n    public RealmQuery<E> notEqualTo(String fieldName, RealmAny value) {\n        realm.checkIfValid();\n        this.notEqualTo(fieldName, value, Case.SENSITIVE);\n        return this;\n    }\n\n    /**\n     * Not-equal-to comparison.\n     *\n     * @param fieldName the field to compare.\n     * @param value     the value to compare with.\n     * @return the query object.\n     * @throws java.lang.IllegalArgumentException if one or more arguments do not match class or field type.\n     */\n    public RealmQuery<E> notEqualTo(String fieldName, @Nullable Byte value) {\n        realm.checkIfValid();\n        this.query.notEqualTo(realm.getSchema().getKeyPathMapping(), fieldName, RealmAny.valueOf(value));\n        return this;\n    }\n\n    /**\n     * Not-equal-to comparison.\n     *\n     * @param fieldName the field to compare.\n     * @param value     the value to compare with.\n     * @return the query object.\n     * @throws java.lang.IllegalArgumentException if one or more arguments do not match class or field type.\n     */\n    public RealmQuery<E> notEqualTo(String fieldName, @Nullable byte[] value) {\n        realm.checkIfValid();\n        this.query.notEqualTo(realm.getSchema().getKeyPathMapping(), fieldName, RealmAny.valueOf(value));\n        return this;\n    }\n\n    /**\n     * Not-equal-to comparison.\n     *\n     * @param fieldName the field to compare.\n     * @param value     the value to compare with.\n     * @return the query object.\n     * @throws java.lang.IllegalArgumentException if one or more arguments do not match class or field type.\n     */\n    public RealmQuery<E> notEqualTo(String fieldName, @Nullable Short value) {\n        realm.checkIfValid();\n        this.query.notEqualTo(realm.getSchema().getKeyPathMapping(), fieldName, RealmAny.valueOf(value));\n        return this;\n    }\n\n    /**\n     * Not-equal-to comparison.\n     *\n     * @param fieldName the field to compare.\n     * @param value     the value to compare with.\n     * @return the query object.\n     * @throws java.lang.IllegalArgumentException if one or more arguments do not match class or field type.\n     */\n    public RealmQuery<E> notEqualTo(String fieldName, @Nullable Integer value) {\n        realm.checkIfValid();\n        this.query.notEqualTo(realm.getSchema().getKeyPathMapping(), fieldName, RealmAny.valueOf(value));\n        return this;\n    }\n\n    /**\n     * Not-equal-to comparison.\n     *\n     * @param fieldName the field to compare.\n     * @param value     the value to compare with.\n     * @return the query object\n     * @throws java.lang.IllegalArgumentException if one or more arguments do not match class or field type.\n     */\n    public RealmQuery<E> notEqualTo(String fieldName, @Nullable Long value) {\n        realm.checkIfValid();\n        this.query.notEqualTo(realm.getSchema().getKeyPathMapping(), fieldName, RealmAny.valueOf(value));\n        return this;\n    }\n\n    /**\n     * Not-equal-to comparison.\n     *\n     * @param fieldName the field to compare.\n     * @param value     the value to compare with.\n     * @return the query object.\n     * @throws java.lang.IllegalArgumentException if one or more arguments do not match class or field type.\n     */\n    public RealmQuery<E> notEqualTo(String fieldName, @Nullable Double value) {\n        realm.checkIfValid();\n        this.query.notEqualTo(realm.getSchema().getKeyPathMapping(), fieldName, RealmAny.valueOf(value));\n        return this;\n    }\n\n    /**\n     * Not-equal-to comparison.\n     *\n     * @param fieldName the field to compare.\n     * @param value     the value to compare with.\n     * @return the query object.\n     * @throws java.lang.IllegalArgumentException if one or more arguments do not match class or field type.\n     */\n    public RealmQuery<E> notEqualTo(String fieldName, @Nullable Float value) {\n        realm.checkIfValid();\n        this.query.notEqualTo(realm.getSchema().getKeyPathMapping(), fieldName, RealmAny.valueOf(value));\n        return this;\n    }\n\n    /**\n     * Not-equal-to comparison.\n     *\n     * @param fieldName the field to compare.\n     * @param value     the value to compare with.\n     * @return the query object.\n     * @throws java.lang.IllegalArgumentException if one or more arguments do not match class or field type.\n     */\n    public RealmQuery<E> notEqualTo(String fieldName, @Nullable Boolean value) {\n        realm.checkIfValid();\n        this.query.notEqualTo(realm.getSchema().getKeyPathMapping(), fieldName, RealmAny.valueOf(value));\n        return this;\n    }\n\n    /**\n     * Not-equal-to comparison.\n     *\n     * @param fieldName the field to compare.\n     * @param value     the value to compare with.\n     * @return the query object.\n     * @throws java.lang.IllegalArgumentException if one or more arguments do not match class or field type.\n     */\n    public RealmQuery<E> notEqualTo(String fieldName, @Nullable Date value) {\n        realm.checkIfValid();\n        this.query.notEqualTo(realm.getSchema().getKeyPathMapping(), fieldName, RealmAny.valueOf(value));\n        return this;\n    }\n\n    /**\n     * Greater-than comparison.\n     *\n     * @param fieldName the field to compare.\n     * @param value     the value to compare with.\n     * @return the query object.\n     * @throws java.lang.IllegalArgumentException if one or more arguments do not match class or field type.\n     */\n    public RealmQuery<E> greaterThan(String fieldName, int value) {\n        realm.checkIfValid();\n        this.query.greaterThan(realm.getSchema().getKeyPathMapping(), fieldName, RealmAny.valueOf(value));\n        return this;\n    }\n\n    /**\n     * Greater-than comparison.\n     *\n     * @param fieldName the field to compare.\n     * @param value     the value to compare with.\n     * @return the query object.\n     * @throws java.lang.IllegalArgumentException if one or more arguments do not match class or field type.\n     */\n    public RealmQuery<E> greaterThan(String fieldName, long value) {\n        realm.checkIfValid();\n        this.query.greaterThan(realm.getSchema().getKeyPathMapping(), fieldName, RealmAny.valueOf(value));\n        return this;\n    }\n\n    /**\n     * Greater-than comparison.\n     *\n     * @param fieldName the field to compare.\n     * @param value     the value to compare with.\n     * @return the query object.\n     * @throws java.lang.IllegalArgumentException if one or more arguments do not match class or field type.\n     */\n    public RealmQuery<E> greaterThan(String fieldName, double value) {\n        realm.checkIfValid();\n        this.query.greaterThan(realm.getSchema().getKeyPathMapping(), fieldName, RealmAny.valueOf(value));\n        return this;\n    }\n\n    /**\n     * Greater-than comparison.\n     *\n     * @param fieldName the field to compare.\n     * @param value     the value to compare with.\n     * @return the query object.\n     * @throws java.lang.IllegalArgumentException if one or more arguments do not match class or field type.\n     */\n    public RealmQuery<E> greaterThan(String fieldName, float value) {\n        realm.checkIfValid();\n        this.query.greaterThan(realm.getSchema().getKeyPathMapping(), fieldName, RealmAny.valueOf(value));\n        return this;\n    }\n\n    /**\n     * Greater-than comparison.\n     *\n     * @param fieldName the field to compare.\n     * @param value     the value to compare with.\n     * @return the query object.\n     * @throws java.lang.IllegalArgumentException if one or more arguments do not match class or field type.\n     */\n    public RealmQuery<E> greaterThan(String fieldName, Date value) {\n        realm.checkIfValid();\n        this.query.greaterThan(realm.getSchema().getKeyPathMapping(), fieldName, RealmAny.valueOf(value));\n        return this;\n    }\n\n    /**\n     * Greater-than comparison.\n     *\n     * @param fieldName the field to compare.\n     * @param value     the value to compare with.\n     * @return the query object.\n     * @throws java.lang.IllegalArgumentException if one or more arguments do not match class or field type.\n     */\n    public RealmQuery<E> greaterThan(String fieldName, RealmAny value) {\n        realm.checkIfValid();\n        this.query.greaterThan(realm.getSchema().getKeyPathMapping(), fieldName, value);\n        return this;\n    }\n\n    /**\n     * Greater-than comparison.\n     *\n     * @param fieldName the field to compare.\n     * @param value     the value to compare with.\n     * @return the query object.\n     * @throws java.lang.IllegalArgumentException if one or more arguments do not match class or field type.\n     */\n    public RealmQuery<E> greaterThan(String fieldName, Decimal128 value) {\n        realm.checkIfValid();\n        this.query.greaterThan(realm.getSchema().getKeyPathMapping(), fieldName, RealmAny.valueOf(value));\n        return this;\n    }\n\n    /**\n     * Greater-than comparison.\n     *\n     * @param fieldName the field to compare.\n     * @param value     the value to compare with.\n     * @return the query object.\n     * @throws java.lang.IllegalArgumentException if one or more arguments do not match class or field type.\n     */\n    public RealmQuery<E> greaterThan(String fieldName, ObjectId value) {\n        realm.checkIfValid();\n        this.query.greaterThan(realm.getSchema().getKeyPathMapping(), fieldName, RealmAny.valueOf(value));\n        return this;\n    }\n\n    /**\n     * Greater-than comparison.\n     *\n     * @param fieldName the field to compare.\n     * @param value     the value to compare with.\n     * @return the query object.\n     * @throws java.lang.IllegalArgumentException if one or more arguments do not match class or field type.\n     */\n    public RealmQuery<E> greaterThan(String fieldName, UUID value) {\n        realm.checkIfValid();\n        this.query.greaterThan(realm.getSchema().getKeyPathMapping(), fieldName, RealmAny.valueOf(value));\n        return this;\n    }\n\n    /**\n     * Greater-than-or-equal-to comparison.\n     *\n     * @param fieldName the field to compare.\n     * @param value     the value to compare with.\n     * @return the query object.\n     * @throws java.lang.IllegalArgumentException if one or more arguments do not match class or field type.\n     */\n    public RealmQuery<E> greaterThanOrEqualTo(String fieldName, int value) {\n        realm.checkIfValid();\n        this.query.greaterThanOrEqual(realm.getSchema().getKeyPathMapping(), fieldName, RealmAny.valueOf(value));\n        return this;\n    }\n\n    /**\n     * Greater-than-or-equal-to comparison.\n     *\n     * @param fieldName the field to compare.\n     * @param value     the value to compare with.\n     * @return the query object.\n     * @throws java.lang.IllegalArgumentException if one or more arguments do not match class or field type.\n     */\n    public RealmQuery<E> greaterThanOrEqualTo(String fieldName, long value) {\n        realm.checkIfValid();\n        this.query.greaterThanOrEqual(realm.getSchema().getKeyPathMapping(), fieldName, RealmAny.valueOf(value));\n        return this;\n    }\n\n    /**\n     * Greater-than-or-equal-to comparison.\n     *\n     * @param fieldName the field to compare.\n     * @param value     the value to compare with.\n     * @return the query object.\n     * @throws java.lang.IllegalArgumentException if one or more arguments do not match class or field type.\n     */\n    public RealmQuery<E> greaterThanOrEqualTo(String fieldName, double value) {\n        realm.checkIfValid();\n        this.query.greaterThanOrEqual(realm.getSchema().getKeyPathMapping(), fieldName, RealmAny.valueOf(value));\n        return this;\n    }\n\n    /**\n     * Greater-than-or-equal-to comparison.\n     *\n     * @param fieldName the field to compare.\n     * @param value     the value to compare with.\n     * @return the query object.\n     * @throws java.lang.IllegalArgumentException if one or more arguments do not match class or field type\n     */\n    public RealmQuery<E> greaterThanOrEqualTo(String fieldName, float value) {\n        realm.checkIfValid();\n        this.query.greaterThanOrEqual(realm.getSchema().getKeyPathMapping(), fieldName, RealmAny.valueOf(value));\n        return this;\n    }\n\n    /**\n     * Greater-than-or-equal-to comparison.\n     *\n     * @param fieldName the field to compare.\n     * @param value     the value to compare with.\n     * @return the query object.\n     * @throws java.lang.IllegalArgumentException if one or more arguments do not match class or field type.\n     */\n    public RealmQuery<E> greaterThanOrEqualTo(String fieldName, Date value) {\n        realm.checkIfValid();\n        this.query.greaterThanOrEqual(realm.getSchema().getKeyPathMapping(), fieldName, RealmAny.valueOf(value));\n        return this;\n    }\n\n    /**\n     * Greater-than-or-equal-to comparison.\n     *\n     * @param fieldName the field to compare.\n     * @param value     the value to compare with.\n     * @return the query object.\n     * @throws java.lang.IllegalArgumentException if one or more arguments do not match class or field type.\n     */\n    public RealmQuery<E> greaterThanOrEqualTo(String fieldName, Decimal128 value) {\n        realm.checkIfValid();\n        this.query.greaterThanOrEqual(realm.getSchema().getKeyPathMapping(), fieldName, RealmAny.valueOf(value));\n        return this;\n    }\n\n    /**\n     * Greater-than-or-equal-to comparison.\n     *\n     * @param fieldName the field to compare.\n     * @param value     the value to compare with.\n     * @return the query object.\n     * @throws java.lang.IllegalArgumentException if one or more arguments do not match class or field type.\n     */\n    public RealmQuery<E> greaterThanOrEqualTo(String fieldName, ObjectId value) {\n        realm.checkIfValid();\n        this.query.greaterThanOrEqual(realm.getSchema().getKeyPathMapping(), fieldName, RealmAny.valueOf(value));\n        return this;\n    }\n\n    /**\n     * Greater-than-or-equal-to comparison.\n     *\n     * @param fieldName the field to compare.\n     * @param value     the value to compare with.\n     * @return the query object.\n     * @throws java.lang.IllegalArgumentException if one or more arguments do not match class or field type.\n     */\n    public RealmQuery<E> greaterThanOrEqualTo(String fieldName, UUID value) {\n        realm.checkIfValid();\n        this.query.greaterThanOrEqual(realm.getSchema().getKeyPathMapping(), fieldName, RealmAny.valueOf(value));\n        return this;\n    }\n\n    /**\n     * Greater-than-or-equal-to comparison.\n     *\n     * @param fieldName the field to compare.\n     * @param value     the value to compare with.\n     * @return the query object.\n     * @throws java.lang.IllegalArgumentException if one or more arguments do not match class or field type.\n     */\n    public RealmQuery<E> greaterThanOrEqualTo(String fieldName, RealmAny value) {\n        realm.checkIfValid();\n        this.query.greaterThanOrEqual(realm.getSchema().getKeyPathMapping(), fieldName, value);\n        return this;\n    }\n\n    /**\n     * Less-than comparison.\n     *\n     * @param fieldName the field to compare.\n     * @param value     the value to compare with.\n     * @return the query object.\n     * @throws java.lang.IllegalArgumentException if one or more arguments do not match class or field type.\n     */\n    public RealmQuery<E> lessThan(String fieldName, int value) {\n        realm.checkIfValid();\n        this.query.lessThan(realm.getSchema().getKeyPathMapping(), fieldName, RealmAny.valueOf(value));\n        return this;\n    }\n\n    /**\n     * Less-than comparison.\n     *\n     * @param fieldName the field to compare.\n     * @param value     the value to compare with.\n     * @return the query object.\n     * @throws java.lang.IllegalArgumentException if one or more arguments do not match class or field type.\n     */\n    public RealmQuery<E> lessThan(String fieldName, long value) {\n        realm.checkIfValid();\n        this.query.lessThan(realm.getSchema().getKeyPathMapping(), fieldName, RealmAny.valueOf(value));\n        return this;\n    }\n\n    /**\n     * Less-than comparison.\n     *\n     * @param fieldName the field to compare.\n     * @param value     the value to compare with.\n     * @return the query object.\n     * @throws java.lang.IllegalArgumentException if one or more arguments do not match class or field type.\n     */\n    public RealmQuery<E> lessThan(String fieldName, Decimal128 value) {\n        realm.checkIfValid();\n        this.query.lessThan(realm.getSchema().getKeyPathMapping(), fieldName, RealmAny.valueOf(value));\n        return this;\n    }\n\n    /**\n     * Less-than comparison.\n     *\n     * @param fieldName the field to compare.\n     * @param value     the value to compare with.\n     * @return the query object.\n     * @throws java.lang.IllegalArgumentException if one or more arguments do not match class or field type.\n     */\n    public RealmQuery<E> lessThan(String fieldName, ObjectId value) {\n        realm.checkIfValid();\n        this.query.lessThan(realm.getSchema().getKeyPathMapping(), fieldName, RealmAny.valueOf(value));\n        return this;\n    }\n\n    /**\n     * Less-than comparison.\n     *\n     * @param fieldName the field to compare.\n     * @param value     the value to compare with.\n     * @return the query object.\n     * @throws java.lang.IllegalArgumentException if one or more arguments do not match class or field type.\n     */\n    public RealmQuery<E> lessThan(String fieldName, UUID value) {\n        realm.checkIfValid();\n        this.query.lessThan(realm.getSchema().getKeyPathMapping(), fieldName, RealmAny.valueOf(value));\n        return this;\n    }\n\n    /**\n     * Less-than comparison.\n     *\n     * @param fieldName the field to compare.\n     * @param value     the value to compare with.\n     * @return the query object.\n     * @throws java.lang.IllegalArgumentException if one or more arguments do not match class or field type.\n     */\n    public RealmQuery<E> lessThan(String fieldName, double value) {\n        realm.checkIfValid();\n        this.query.lessThan(realm.getSchema().getKeyPathMapping(), fieldName, RealmAny.valueOf(value));\n        return this;\n    }\n\n    /**\n     * Less-than comparison.\n     *\n     * @param fieldName the field to compare.\n     * @param value     the value to compare with.\n     * @return the query object.\n     * @throws java.lang.IllegalArgumentException if one or more arguments do not match class or field type.\n     */\n    public RealmQuery<E> lessThan(String fieldName, float value) {\n        realm.checkIfValid();\n        this.query.lessThan(realm.getSchema().getKeyPathMapping(), fieldName, RealmAny.valueOf(value));\n        return this;\n    }\n\n    /**\n     * Less-than comparison.\n     *\n     * @param fieldName the field to compare.\n     * @param value     the value to compare with.\n     * @return the query object.\n     * @throws java.lang.IllegalArgumentException if one or more arguments do not match class or field type.\n     */\n    public RealmQuery<E> lessThan(String fieldName, Date value) {\n        realm.checkIfValid();\n        this.query.lessThan(realm.getSchema().getKeyPathMapping(), fieldName, RealmAny.valueOf(value));\n        return this;\n    }\n\n    /**\n     * Less-than comparison.\n     *\n     * @param fieldName the field to compare.\n     * @param value     the value to compare with.\n     * @return the query object.\n     * @throws java.lang.IllegalArgumentException if one or more arguments do not match class or field type.\n     */\n    public RealmQuery<E> lessThan(String fieldName, RealmAny value) {\n        realm.checkIfValid();\n        this.query.lessThan(realm.getSchema().getKeyPathMapping(), fieldName, value);\n        return this;\n    }\n\n    /**\n     * Less-than-or-equal-to comparison.\n     *\n     * @param fieldName the field to compare.\n     * @param value     the value to compare with.\n     * @return the query object.\n     * @throws java.lang.IllegalArgumentException if one or more arguments do not match class or field type.\n     */\n    public RealmQuery<E> lessThanOrEqualTo(String fieldName, int value) {\n        realm.checkIfValid();\n        this.query.lessThanOrEqual(realm.getSchema().getKeyPathMapping(), fieldName, RealmAny.valueOf(value));\n        return this;\n    }\n\n    /**\n     * Less-than-or-equal-to comparison.\n     *\n     * @param fieldName the field to compare.\n     * @param value     the value to compare with.\n     * @return the query object.\n     * @throws java.lang.IllegalArgumentException if one or more arguments do not match class or field type.\n     */\n    public RealmQuery<E> lessThanOrEqualTo(String fieldName, long value) {\n        realm.checkIfValid();\n        this.query.lessThanOrEqual(realm.getSchema().getKeyPathMapping(), fieldName, RealmAny.valueOf(value));\n        return this;\n    }\n\n    /**\n     * Less-than-or-equal-to comparison.\n     *\n     * @param fieldName the field to compare.\n     * @param value     the value to compare with.\n     * @return the query object.\n     * @throws java.lang.IllegalArgumentException if one or more arguments do not match class or field type.\n     */\n    public RealmQuery<E> lessThanOrEqualTo(String fieldName, Decimal128 value) {\n        realm.checkIfValid();\n        this.query.lessThanOrEqual(realm.getSchema().getKeyPathMapping(), fieldName, RealmAny.valueOf(value));\n        return this;\n    }\n\n    /**\n     * Less-than-or-equal-to comparison.\n     *\n     * @param fieldName the field to compare.\n     * @param value     the value to compare with.\n     * @return the query object.\n     * @throws java.lang.IllegalArgumentException if one or more arguments do not match class or field type.\n     */\n    public RealmQuery<E> lessThanOrEqualTo(String fieldName, ObjectId value) {\n        realm.checkIfValid();\n        this.query.lessThanOrEqual(realm.getSchema().getKeyPathMapping(), fieldName, RealmAny.valueOf(value));\n        return this;\n    }\n\n    /**\n     * Less-than-or-equal-to comparison.\n     *\n     * @param fieldName the field to compare.\n     * @param value     the value to compare with.\n     * @return the query object.\n     * @throws java.lang.IllegalArgumentException if one or more arguments do not match class or field type.\n     */\n    public RealmQuery<E> lessThanOrEqualTo(String fieldName, UUID value) {\n        realm.checkIfValid();\n        this.query.lessThanOrEqual(realm.getSchema().getKeyPathMapping(), fieldName, RealmAny.valueOf(value));\n        return this;\n    }\n\n    /**\n     * Less-than-or-equal-to comparison.\n     *\n     * @param fieldName the field to compare.\n     * @param value     the value to compare with.\n     * @return the query object.\n     * @throws java.lang.IllegalArgumentException if one or more arguments do not match class or field type.\n     */\n    public RealmQuery<E> lessThanOrEqualTo(String fieldName, double value) {\n        realm.checkIfValid();\n        this.query.lessThanOrEqual(realm.getSchema().getKeyPathMapping(), fieldName, RealmAny.valueOf(value));\n        return this;\n    }\n\n    /**\n     * Less-than-or-equal-to comparison.\n     *\n     * @param fieldName the field to compare.\n     * @param value     the value to compare with.\n     * @return the query object.\n     * @throws java.lang.IllegalArgumentException if one or more arguments do not match class or field type.\n     */\n    public RealmQuery<E> lessThanOrEqualTo(String fieldName, float value) {\n        realm.checkIfValid();\n        this.query.lessThanOrEqual(realm.getSchema().getKeyPathMapping(), fieldName, RealmAny.valueOf(value));\n        return this;\n    }\n\n    /**\n     * Less-than-or-equal-to comparison.\n     *\n     * @param fieldName the field to compare.\n     * @param value     the value to compare with.\n     * @return the query object.\n     * @throws java.lang.IllegalArgumentException if one or more arguments do not match class or field type.\n     */\n    public RealmQuery<E> lessThanOrEqualTo(String fieldName, Date value) {\n        realm.checkIfValid();\n        this.query.lessThanOrEqual(realm.getSchema().getKeyPathMapping(), fieldName, RealmAny.valueOf(value));\n        return this;\n    }\n\n    /**\n     * Less-than-or-equal-to comparison.\n     *\n     * @param fieldName the field to compare.\n     * @param value     the value to compare with.\n     * @return the query object.\n     * @throws java.lang.IllegalArgumentException if one or more arguments do not match class or field type.\n     */\n    public RealmQuery<E> lessThanOrEqualTo(String fieldName, RealmAny value) {\n        realm.checkIfValid();\n        this.query.lessThanOrEqual(realm.getSchema().getKeyPathMapping(), fieldName, value);\n        return this;\n    }\n\n    /**\n     * Between condition.\n     *\n     * @param fieldName the field to compare.\n     * @param from      lowest value (inclusive).\n     * @param to        highest value (inclusive).\n     * @return the query object.\n     * @throws java.lang.IllegalArgumentException if one or more arguments do not match class or field type.\n     */\n    public RealmQuery<E> between(String fieldName, int from, int to) {\n        realm.checkIfValid();\n        this.query.between(realm.getSchema().getKeyPathMapping(), fieldName, RealmAny.valueOf(from), RealmAny.valueOf(to));\n        return this;\n    }\n\n    /**\n     * Between condition.\n     *\n     * @param fieldName the field to compare.\n     * @param from      lowest value (inclusive).\n     * @param to        highest value (inclusive).\n     * @return the query object.\n     * @throws java.lang.IllegalArgumentException if one or more arguments do not match class or field type.\n     */\n    public RealmQuery<E> between(String fieldName, long from, long to) {\n        realm.checkIfValid();\n        this.query.between(realm.getSchema().getKeyPathMapping(), fieldName, RealmAny.valueOf(from), RealmAny.valueOf(to));\n        return this;\n    }\n\n    /**\n     * Between condition.\n     *\n     * @param fieldName the field to compare.\n     * @param from      lowest value (inclusive).\n     * @param to        highest value (inclusive).\n     * @return the query object.\n     * @throws java.lang.IllegalArgumentException if one or more arguments do not match class or field type.\n     */\n    public RealmQuery<E> between(String fieldName, double from, double to) {\n        realm.checkIfValid();\n        this.query.between(realm.getSchema().getKeyPathMapping(), fieldName, RealmAny.valueOf(from), RealmAny.valueOf(to));\n        return this;\n    }\n\n    /**\n     * Between condition.\n     *\n     * @param fieldName the field to compare.\n     * @param from      lowest value (inclusive).\n     * @param to        highest value (inclusive).\n     * @return the query object.\n     * @throws java.lang.IllegalArgumentException if one or more arguments do not match class or field type.\n     */\n    public RealmQuery<E> between(String fieldName, float from, float to) {\n        realm.checkIfValid();\n        this.query.between(realm.getSchema().getKeyPathMapping(), fieldName, RealmAny.valueOf(from), RealmAny.valueOf(to));\n        return this;\n    }\n\n    /**\n     * Between condition.\n     *\n     * @param fieldName the field to compare.\n     * @param from      lowest value (inclusive).\n     * @param to        highest value (inclusive).\n     * @return the query object.\n     * @throws java.lang.IllegalArgumentException if one or more arguments do not match class or field type.\n     */\n    public RealmQuery<E> between(String fieldName, Date from, Date to) {\n        realm.checkIfValid();\n        this.query.between(realm.getSchema().getKeyPathMapping(), fieldName, RealmAny.valueOf(from), RealmAny.valueOf(to));\n        return this;\n    }\n\n    /**\n     * Between condition.\n     *\n     * @param fieldName the field to compare.\n     * @param from      lowest value (inclusive).\n     * @param to        highest value (inclusive).\n     * @return the query object.\n     * @throws java.lang.IllegalArgumentException if one or more arguments do not match class or field type.\n     */\n    public RealmQuery<E> between(String fieldName, RealmAny from, RealmAny to) {\n        realm.checkIfValid();\n        this.query.between(realm.getSchema().getKeyPathMapping(), fieldName, from, to);\n        return this;\n    }\n\n    /**\n     * Between condition.\n     *\n     * @param fieldName the field to compare.\n     * @param from      lowest value (inclusive).\n     * @param to        highest value (inclusive).\n     * @return the query object.\n     * @throws java.lang.IllegalArgumentException if one or more arguments do not match class or field type.\n     */\n    public RealmQuery<E> between(String fieldName, Decimal128 from, Decimal128 to) {\n        realm.checkIfValid();\n        this.query.between(realm.getSchema().getKeyPathMapping(), fieldName, RealmAny.valueOf(from), RealmAny.valueOf(to));\n        return this;\n    }\n\n    /**\n     * Condition that value of field contains the specified substring.\n     *\n     * @param fieldName the field to compare.\n     * @param value     the substring.\n     * @return the query object.\n     * @throws java.lang.IllegalArgumentException if one or more arguments do not match class or field type.\n     */\n    public RealmQuery<E> contains(String fieldName, String value) {\n        return contains(fieldName, value, Case.SENSITIVE);\n    }\n\n    /**\n     * Condition that value of field contains the specified substring.\n     *\n     * @param fieldName the field to compare.\n     * @param value     the substring.\n     * @return the query object.\n     * @throws java.lang.IllegalArgumentException if one or more arguments do not match class or field type.\n     */\n    public RealmQuery<E> contains(String fieldName, RealmAny value) {\n        return contains(fieldName, value, Case.SENSITIVE);\n    }\n\n    /**\n     * Condition that value of field contains the specified substring.\n     *\n     * @param fieldName the field to compare.\n     * @param value     the substring.\n     * @param casing    how to handle casing. Setting this to {@link Case#INSENSITIVE} only works for Latin-1 characters.\n     * @return The query object.\n     * @throws java.lang.IllegalArgumentException if one or more arguments do not match class or field type.\n     */\n    public RealmQuery<E> contains(String fieldName, String value, Case casing) {\n        Util.checkNull(value, \"value\");\n        realm.checkIfValid();\n        contains(fieldName, RealmAny.valueOf(value), casing);\n        return this;\n    }\n\n    /**\n     * Condition that value of field contains the specified substring.\n     *\n     * @param fieldName the field to compare.\n     * @param value     the substring.\n     * @param casing    how to handle casing. Setting this to {@link Case#INSENSITIVE} only works for Latin-1 characters.\n     * @return The query object.\n     * @throws java.lang.IllegalArgumentException if one or more arguments do not match class or field type.\n     */\n    public RealmQuery<E> contains(String fieldName, RealmAny value, Case casing) {\n        realm.checkIfValid();\n        if (casing == Case.SENSITIVE) {\n            this.query.contains(realm.getSchema().getKeyPathMapping(), fieldName, value);\n        } else {\n            this.query.containsInsensitive(realm.getSchema().getKeyPathMapping(), fieldName, value);\n        }\n        return this;\n    }\n\n    /**\n     * Condition that the value of field begins with the specified string.\n     *\n     * @param fieldName the field to compare.\n     * @param value     the string.\n     * @return the query object.\n     * @throws java.lang.IllegalArgumentException if one or more arguments do not match class or field type.\n     */\n    public RealmQuery<E> beginsWith(String fieldName, String value) {\n        return beginsWith(fieldName, value, Case.SENSITIVE);\n    }\n\n    /**\n     * Condition that the value of field begins with the specified string.\n     *\n     * @param fieldName the field to compare.\n     * @param value     the string.\n     * @return the query object.\n     * @throws java.lang.IllegalArgumentException if one or more arguments do not match class or field type.\n     */\n    public RealmQuery<E> beginsWith(String fieldName, RealmAny value) {\n        return beginsWith(fieldName, value, Case.SENSITIVE);\n    }\n\n    /**\n     * Condition that the value of field begins with the specified substring.\n     *\n     * @param fieldName the field to compare.\n     * @param value     the substring.\n     * @param casing    how to handle casing. Setting this to {@link Case#INSENSITIVE} only works for Latin-1 characters.\n     * @return the query object\n     * @throws java.lang.IllegalArgumentException if one or more arguments do not match class or field type.\n     */\n    public RealmQuery<E> beginsWith(String fieldName, String value, Case casing) {\n        Util.checkNull(value, \"value\");\n        realm.checkIfValid();\n        beginsWith(fieldName, RealmAny.valueOf(value), casing);\n        return this;\n    }\n\n    /**\n     * Condition that the value of field begins with the specified substring.\n     *\n     * @param fieldName the field to compare.\n     * @param value     the substring.\n     * @param casing    how to handle casing. Setting this to {@link Case#INSENSITIVE} only works for Latin-1 characters.\n     * @return the query object\n     * @throws java.lang.IllegalArgumentException if one or more arguments do not match class or field type.\n     */\n    public RealmQuery<E> beginsWith(String fieldName, RealmAny value, Case casing) {\n        realm.checkIfValid();\n        if (casing == Case.SENSITIVE) {\n            this.query.beginsWith(realm.getSchema().getKeyPathMapping(), fieldName, value);\n        } else {\n            this.query.beginsWithInsensitive(realm.getSchema().getKeyPathMapping(), fieldName, value);\n        }\n        return this;\n    }\n\n    /**\n     * Condition that the value of field ends with the specified string.\n     *\n     * @param fieldName the field to compare.\n     * @param value     the string.\n     * @return the query object.\n     * @throws java.lang.IllegalArgumentException if one or more arguments do not match class or field type.\n     */\n    public RealmQuery<E> endsWith(String fieldName, String value) {\n        return endsWith(fieldName, value, Case.SENSITIVE);\n    }\n\n    /**\n     * Condition that the value of field ends with the specified string.\n     *\n     * @param fieldName the field to compare.\n     * @param value     the string.\n     * @return the query object.\n     * @throws java.lang.IllegalArgumentException if one or more arguments do not match class or field type.\n     */\n    public RealmQuery<E> endsWith(String fieldName, RealmAny value) {\n        return endsWith(fieldName, value, Case.SENSITIVE);\n    }\n\n    /**\n     * Condition that the value of field ends with the specified substring.\n     *\n     * @param fieldName the field to compare.\n     * @param value     the substring.\n     * @param casing    how to handle casing. Setting this to {@link Case#INSENSITIVE} only works for Latin-1 characters.\n     * @return the query object.\n     * @throws java.lang.IllegalArgumentException if one or more arguments do not match class or field type.\n     */\n    public RealmQuery<E> endsWith(String fieldName, String value, Case casing) {\n        Util.checkNull(value, \"value\");\n        realm.checkIfValid();\n        endsWith(fieldName, RealmAny.valueOf(value), casing);\n        return this;\n    }\n\n    /**\n     * Condition that the value of field ends with the specified substring.\n     *\n     * @param fieldName the field to compare.\n     * @param value     the substring.\n     * @param casing    how to handle casing. Setting this to {@link Case#INSENSITIVE} only works for Latin-1 characters.\n     * @return the query object.\n     * @throws java.lang.IllegalArgumentException if one or more arguments do not match class or field type.\n     */\n    public RealmQuery<E> endsWith(String fieldName, RealmAny value, Case casing) {\n        realm.checkIfValid();\n        if (casing == Case.SENSITIVE) {\n            this.query.endsWith(realm.getSchema().getKeyPathMapping(), fieldName, value);\n        } else {\n            this.query.endsWithInsensitive(realm.getSchema().getKeyPathMapping(), fieldName, value);\n        }\n        return this;\n    }\n\n    /**\n     * Condition that the value of field matches with the specified substring, with wildcards:\n     * <ul>\n     * <li>'*' matches [0, n] unicode chars</li>\n     * <li>'?' matches a single unicode char.</li>\n     * </ul>\n     *\n     * @param fieldName the field to compare.\n     * @param value     the wildcard string.\n     * @return the query object.\n     * @throws java.lang.IllegalArgumentException if one or more arguments do not match class or field type.\n     */\n    public RealmQuery<E> like(String fieldName, String value) {\n        return like(fieldName, value, Case.SENSITIVE);\n    }\n\n    /**\n     * Condition that the value of field matches with the specified substring, with wildcards:\n     * <ul>\n     * <li>'*' matches [0, n] unicode chars</li>\n     * <li>'?' matches a single unicode char.</li>\n     * </ul>\n     *\n     * @param fieldName the field to compare.\n     * @param value     the wildcard string.\n     * @return the query object.\n     * @throws java.lang.IllegalArgumentException if one or more arguments do not match class or field type.\n     */\n    public RealmQuery<E> like(String fieldName, RealmAny value) {\n        return like(fieldName, value, Case.SENSITIVE);\n    }\n\n    /**\n     * Condition that the value of field matches with the specified substring, with wildcards:\n     * <ul>\n     * <li>'*' matches [0, n] unicode chars</li>\n     * <li>'?' matches a single unicode char.</li>\n     * </ul>\n     *\n     * @param fieldName the field to compare.\n     * @param value     the wildcard string.\n     * @param casing    how to handle casing. Setting this to {@link Case#INSENSITIVE} only works for Latin-1 characters.\n     * @return the query object.\n     * @throws java.lang.IllegalArgumentException if one or more arguments do not match class or field type.\n     */\n    public RealmQuery<E> like(String fieldName, String value, Case casing) {\n        Util.checkNull(value, \"value\");\n        realm.checkIfValid();\n        like(fieldName, RealmAny.valueOf(value), casing);\n        return this;\n    }\n\n    /**\n     * Condition that the value of field matches with the specified substring, with wildcards:\n     * <ul>\n     * <li>'*' matches [0, n] unicode chars</li>\n     * <li>'?' matches a single unicode char.</li>\n     * </ul>\n     *\n     * @param fieldName the field to compare.\n     * @param value     the wildcard string.\n     * @param casing    how to handle casing. Setting this to {@link Case#INSENSITIVE} only works for Latin-1 characters.\n     * @return the query object.\n     * @throws java.lang.IllegalArgumentException if one or more arguments do not match class or field type.\n     */\n    public RealmQuery<E> like(String fieldName, RealmAny value, Case casing) {\n        realm.checkIfValid();\n        if (casing == Case.SENSITIVE) {\n            this.query.like(realm.getSchema().getKeyPathMapping(), fieldName, value);\n        } else {\n            this.query.likeInsensitive(realm.getSchema().getKeyPathMapping(), fieldName, value);\n        }\n        return this;\n    }\n\n    /**\n     * Begin grouping of conditions (\"left parenthesis\"). A group must be closed with a call to {@code endGroup()}.\n     *\n     * @return the query object.\n     * @see #endGroup()\n     */\n    public RealmQuery<E> beginGroup() {\n        realm.checkIfValid();\n        this.query.beginGroup();\n        return this;\n    }\n\n    /**\n     * End grouping of conditions (\"right parenthesis\") which was opened by a call to {@code beginGroup()}.\n     *\n     * @return the query object.\n     * @see #beginGroup()\n     */\n    public RealmQuery<E> endGroup() {\n        realm.checkIfValid();\n        this.query.endGroup();\n        return this;\n    }\n\n    /**\n     * Logical-or two conditions.\n     *\n     * @return the query object.\n     */\n    public RealmQuery<E> or() {\n        realm.checkIfValid();\n        this.query.or();\n        return this;\n    }\n\n    /**\n     * Logical-and two conditions\n     * Realm automatically applies logical-and between all query statements, so this is intended only as a mean to increase readability.\n     *\n     * @return the query object\n     */\n    public RealmQuery<E> and() {\n        realm.checkIfValid();\n        return this;\n    }\n\n    /**\n     * Negate condition.\n     *\n     * @return the query object.\n     */\n    public RealmQuery<E> not() {\n        realm.checkIfValid();\n        this.query.not();\n        return this;\n    }\n\n    /**\n     * Condition that finds values that are considered \"empty\" i.e., an empty list, the 0-length string or byte array.\n     *\n     * @param fieldName the field to compare.\n     * @return the query object.\n     * @throws java.lang.IllegalArgumentException if the field name isn't valid or its type isn't either a RealmList,\n     *                                            String or byte array.\n     */\n    public RealmQuery<E> isEmpty(String fieldName) {\n        realm.checkIfValid();\n        this.query.isEmpty(realm.getSchema().getKeyPathMapping(), fieldName);\n        return this;\n    }\n\n    /**\n     * Condition that finds values that are considered \"Not-empty\" i.e., a list, a string or a byte array with not-empty values.\n     *\n     * @param fieldName the field to compare.\n     * @return the query object.\n     * @throws java.lang.IllegalArgumentException if the field name isn't valid or its type isn't either a RealmList,\n     *                                            String or byte array.\n     */\n    public RealmQuery<E> isNotEmpty(String fieldName) {\n        realm.checkIfValid();\n        this.query.isNotEmpty(realm.getSchema().getKeyPathMapping(), fieldName);\n        return this;\n    }\n\n    /**\n     * Condition that value, if a dictionary field, contains the specified key.\n     *\n     * @param fieldName the field to compare.\n     * @param key       the key to search for.\n     * @return the query object.\n     * @throws java.lang.IllegalArgumentException if the field name isn't valid.\n     */\n    public RealmQuery<E> containsKey(String fieldName, @Nullable String key) {\n        realm.checkIfValid();\n        this.query.containsKey(realm.getSchema().getKeyPathMapping(), fieldName, RealmAny.valueOf(key));\n        return this;\n    }\n\n    /**\n     * Condition that value, if a dictionary field, contains the specified value.\n     *\n     * @param fieldName the field to compare.\n     * @param value     the value to search for.\n     * @return the query object.\n     * @throws java.lang.IllegalArgumentException if the field name isn't valid.\n     */\n    public RealmQuery<E> containsValue(String fieldName, @Nullable Boolean value) {\n        realm.checkIfValid();\n        this.query.containsValue(realm.getSchema().getKeyPathMapping(), fieldName, RealmAny.valueOf(value));\n        return this;\n    }\n\n    /**\n     * Condition that value, if a dictionary field, contains the specified value.\n     *\n     * @param fieldName the field to compare.\n     * @param value     the value to search for.\n     * @return the query object.\n     * @throws java.lang.IllegalArgumentException if the field name isn't valid.\n     */\n    public RealmQuery<E> containsValue(String fieldName, @Nullable Byte value) {\n        realm.checkIfValid();\n        this.query.containsValue(realm.getSchema().getKeyPathMapping(), fieldName, RealmAny.valueOf(value));\n        return this;\n    }\n\n    /**\n     * Condition that value, if a dictionary field, contains the specified value.\n     *\n     * @param fieldName the field to compare.\n     * @param value     the value to search for.\n     * @return the query object.\n     * @throws java.lang.IllegalArgumentException if the field name isn't valid.\n     */\n    public RealmQuery<E> containsValue(String fieldName, @Nullable Short value) {\n        realm.checkIfValid();\n        this.query.containsValue(realm.getSchema().getKeyPathMapping(), fieldName, RealmAny.valueOf(value));\n        return this;\n    }\n\n    /**\n     * Condition that value, if a dictionary field, contains the specified value.\n     *\n     * @param fieldName the field to compare.\n     * @param value     the value to search for\n     * @return the query object.\n     * @throws java.lang.IllegalArgumentException if the field name isn't valid.\n     */\n    public RealmQuery<E> containsValue(String fieldName, @Nullable Integer value) {\n        realm.checkIfValid();\n        this.query.containsValue(realm.getSchema().getKeyPathMapping(), fieldName, RealmAny.valueOf(value));\n        return this;\n    }\n\n    /**\n     * Condition that value, if a dictionary field, contains the specified value.\n     *\n     * @param fieldName the field to compare.\n     * @param value     the value to search for.\n     * @return the query object.\n     * @throws java.lang.IllegalArgumentException if the field name isn't valid.\n     */\n    public RealmQuery<E> containsValue(String fieldName, @Nullable Long value) {\n        realm.checkIfValid();\n        this.query.containsValue(realm.getSchema().getKeyPathMapping(), fieldName, RealmAny.valueOf(value));\n        return this;\n    }\n\n    /**\n     * Condition that value, if a dictionary field, contains the specified value.\n     *\n     * @param fieldName the field to compare.\n     * @param value     the value to search for.\n     * @return the query object.\n     * @throws java.lang.IllegalArgumentException if the field name isn't valid.\n     */\n    public RealmQuery<E> containsValue(String fieldName, @Nullable Double value) {\n        realm.checkIfValid();\n        this.query.containsValue(realm.getSchema().getKeyPathMapping(), fieldName, RealmAny.valueOf(value));\n        return this;\n    }\n\n    /**\n     * Condition that value, if a dictionary field, contains the specified value.\n     *\n     * @param fieldName the field to compare.\n     * @param value     the value to search for.\n     * @return the query object.\n     * @throws java.lang.IllegalArgumentException if the field name isn't valid.\n     */\n    public RealmQuery<E> containsValue(String fieldName, @Nullable Float value) {\n        realm.checkIfValid();\n        this.query.containsValue(realm.getSchema().getKeyPathMapping(), fieldName, RealmAny.valueOf(value));\n        return this;\n    }\n\n    /**\n     * Condition that value, if a dictionary field, contains the specified value.\n     *\n     * @param fieldName the field to compare.\n     * @param value     the value to search for.\n     * @return the query object.\n     * @throws java.lang.IllegalArgumentException if the field name isn't valid.\n     */\n    public RealmQuery<E> containsValue(String fieldName, @Nullable String value) {\n        realm.checkIfValid();\n        this.query.containsValue(realm.getSchema().getKeyPathMapping(), fieldName, RealmAny.valueOf(value));\n        return this;\n    }\n\n    /**\n     * Condition that value, if a dictionary field, contains the specified value.\n     *\n     * @param fieldName the field to compare.\n     * @param value     the value to search for.\n     * @return the query object.\n     * @throws java.lang.IllegalArgumentException if the field name isn't valid.\n     */\n    public RealmQuery<E> containsValue(String fieldName, @Nullable byte[] value) {\n        realm.checkIfValid();\n        this.query.containsValue(realm.getSchema().getKeyPathMapping(), fieldName, RealmAny.valueOf(value));\n        return this;\n    }\n\n    /**\n     * Condition that value, if a dictionary field, contains the specified value.\n     *\n     * @param fieldName the field to compare.\n     * @param value     the value to search for.\n     * @return the query object.\n     * @throws java.lang.IllegalArgumentException if the field name isn't valid.\n     */\n    public RealmQuery<E> containsValue(String fieldName, @Nullable Date value) {\n        realm.checkIfValid();\n        this.query.containsValue(realm.getSchema().getKeyPathMapping(), fieldName, RealmAny.valueOf(value));\n        return this;\n    }\n\n    /**\n     * Condition that value, if a dictionary field, contains the specified value.\n     *\n     * @param fieldName the field to compare.\n     * @param value     the value to search for.\n     * @return the query object.\n     * @throws java.lang.IllegalArgumentException if the field name isn't valid.\n     */\n    public RealmQuery<E> containsValue(String fieldName, @Nullable Decimal128 value) {\n        realm.checkIfValid();\n        this.query.containsValue(realm.getSchema().getKeyPathMapping(), fieldName, RealmAny.valueOf(value));\n        return this;\n    }\n\n    /**\n     * Condition that value, if a dictionary field, contains the specified value.\n     *\n     * @param fieldName the field to compare.\n     * @param value     the value to search for.\n     * @return the query object.\n     * @throws java.lang.IllegalArgumentException if the field name isn't valid.\n     */\n    public RealmQuery<E> containsValue(String fieldName, @Nullable ObjectId value) {\n        realm.checkIfValid();\n        this.query.containsValue(realm.getSchema().getKeyPathMapping(), fieldName, RealmAny.valueOf(value));\n        return this;\n    }\n\n    /**\n     * Condition that value, if a dictionary field, contains the specified value.\n     *\n     * @param fieldName the field to compare.\n     * @param value     the value to search for.\n     * @return the query object.\n     * @throws java.lang.IllegalArgumentException if the field name isn't valid.\n     */\n    public RealmQuery<E> containsValue(String fieldName, @Nullable UUID value) {\n        realm.checkIfValid();\n        this.query.containsValue(realm.getSchema().getKeyPathMapping(), fieldName, RealmAny.valueOf(value));\n        return this;\n    }\n\n    /**\n     * Condition that value, if a dictionary field, contains the specified value.\n     *\n     * @param fieldName the field to compare.\n     * @param value     the value to search for.\n     * @return the query object.\n     * @throws java.lang.IllegalArgumentException if the field name isn't valid.\n     */\n    public RealmQuery<E> containsValue(String fieldName, RealmAny value) {\n        realm.checkIfValid();\n        this.query.containsValue(realm.getSchema().getKeyPathMapping(), fieldName, value);\n        return this;\n    }\n\n    /**\n     * Condition that value, if a dictionary field, contains the specified value.\n     *\n     * @param fieldName the field to compare.\n     * @param value     the value to search for.\n     * @return the query object.\n     * @throws java.lang.IllegalArgumentException if the field name isn't valid.\n     */\n    public RealmQuery<E> containsValue(String fieldName, RealmModel value) {\n        realm.checkIfValid();\n        this.query.containsValue(realm.getSchema().getKeyPathMapping(), fieldName, RealmAny.valueOf(value));\n        return this;\n    }\n\n    /**\n     * Condition that value, if a dictionary field, contains the specified entry.\n     *\n     * @param fieldName the field to compare.\n     * @param entry     the entry to search for.\n     * @return the query object.\n     * @throws java.lang.IllegalArgumentException if the field name isn't valid.\n     */\n    public RealmQuery<E> containsEntry(String fieldName, Map.Entry<String, ?> entry) {\n        Util.checkNull(entry, \"entry\");\n        realm.checkIfValid();\n        this.query.containsEntry(realm.getSchema().getKeyPathMapping(), fieldName, RealmAny.valueOf(entry.getKey()), RealmAny.valueOf(entry.getValue()));\n        return this;\n    }\n\n    /**\n     * Calculates the sum of a given field.\n     *\n     * @param fieldName the field to sum. Only number and RealmAny fields are supported.\n     * @return the sum of fields of the matching objects. If no objects exist or they all have\n     * {@code null} as the value for the given field, {@code 0} will be returned. When computing the\n     * sum, objects with {@code null} values are ignored. When applied to a RealmAny field, only\n     * numeric values will be summed up (Byte/Integer/Integer/Long/Float/Double/Decimal128) and the\n     * returning type will be {@code Decimal128}.\n     * @throws java.lang.IllegalArgumentException if the field is not a number type.\n     * @throws RealmException                     if called from the UI thread after opting out via {@link RealmConfiguration.Builder#allowQueriesOnUiThread(boolean)}.\n     */\n    public Number sum(String fieldName) {\n        realm.checkIfValid();\n        realm.checkAllowQueriesOnUiThread();\n\n        long columnKey = schema.getAndCheckFieldColumnKey(fieldName);\n        switch (table.getColumnType(columnKey)) {\n            case INTEGER:\n                return query.sumInt(columnKey);\n            case FLOAT:\n                return query.sumFloat(columnKey);\n            case DOUBLE:\n                return query.sumDouble(columnKey);\n            case DECIMAL128:\n                return query.sumDecimal128(columnKey);\n            case MIXED:\n                return query.sumRealmAny(columnKey);\n            default:\n                throw new IllegalArgumentException(String.format(Locale.US,\n                        TYPE_MISMATCH, fieldName, \"int, float or double\"));\n        }\n    }\n\n    /**\n     * Returns the average of a given field.\n     * Does not support dotted field notation.\n     *\n     * @param fieldName the field to calculate average on. Only number fields are supported.\n     * @return the average for the given field amongst objects in query results. This will be of type double for all\n     * types of number fields. If no objects exist or they all have {@code null} as the value for the given field,\n     * {@code 0} will be returned. When computing the average, objects with {@code null} values are ignored.\n     * @throws java.lang.IllegalArgumentException if the field is not a number type.\n     * @throws RealmException                     if called from the UI thread after opting out via {@link RealmConfiguration.Builder#allowQueriesOnUiThread(boolean)}.\n     */\n    public double average(String fieldName) {\n        realm.checkIfValid();\n        realm.checkAllowQueriesOnUiThread();\n\n        long columnIndex = schema.getAndCheckFieldColumnKey(fieldName);\n        switch (table.getColumnType(columnIndex)) {\n            case INTEGER:\n                return query.averageInt(columnIndex);\n            case DOUBLE:\n                return query.averageDouble(columnIndex);\n            case FLOAT:\n                return query.averageFloat(columnIndex);\n            default:\n                throw new IllegalArgumentException(String.format(Locale.US,\n                        TYPE_MISMATCH, fieldName, \"int, float or double. For Decimal128 use `averageDecimal128` method.\"));\n        }\n    }\n\n    /**\n     * Returns the average of a given field.\n     * Does not support dotted field notation.\n     *\n     * @param fieldName the field to calculate average on. Only Decimal128 fields is supported. For other number types consider using {@link #average(String)}.\n     * @return the average for the given field amongst objects in query results. This will be of type Decimal128. If no objects exist or they all have {@code null}\n     * as the value for the given field {@code 0} will be returned. When computing the average, objects with {@code null} values are ignored.\n     * @throws java.lang.IllegalArgumentException if the field is not a Decimal128 type.\n     * @throws RealmException                     if called from the UI thread after opting out via {@link RealmConfiguration.Builder#allowQueriesOnUiThread(boolean)}.\n     */\n    public @Nullable\n    Decimal128 averageDecimal128(String fieldName) {\n        realm.checkIfValid();\n        realm.checkAllowQueriesOnUiThread();\n\n        long columnIndex = schema.getAndCheckFieldColumnKey(fieldName);\n        return query.averageDecimal128(columnIndex);\n    }\n\n    /**\n     * Returns the average of a given field.\n     * Does not support dotted field notation.\n     *\n     * @param fieldName the field to calculate average on. Only RealmAny fields are supported. For other types consider using {@link #average(String)}.\n     * @return the average for the given field amongst objects in query results. This will be of type Decimal128. If no objects exist or they all have {@code null}\n     * as the value for the given field {@code 0} will be returned. When computing the average, objects with {@code null} values are ignored.\n     * @throws java.lang.IllegalArgumentException if the field is not a RealmAny type.\n     * @throws RealmException                     if called from the UI thread after opting out via {@link RealmConfiguration.Builder#allowQueriesOnUiThread(boolean)}.\n     */\n    public @Nullable\n    Decimal128 averageRealmAny(String fieldName) {\n        realm.checkIfValid();\n        realm.checkAllowQueriesOnUiThread();\n\n        long columnIndex = schema.getAndCheckFieldColumnKey(fieldName);\n        return query.averageRealmAny(columnIndex);\n    }\n\n    /**\n     * Finds the minimum value of a field.\n     *\n     * @param fieldName the field to look for a minimum on. Only number fields are supported.\n     * @return if no objects exist or they all have {@code null} as the value for the given field, {@code null} will be\n     * returned. Otherwise the minimum value is returned. When determining the minimum value, objects with {@code null}\n     * values are ignored.\n     * @throws java.lang.IllegalArgumentException if the field is not a number type.\n     * @throws RealmException                     if called from the UI thread after opting out via {@link RealmConfiguration.Builder#allowQueriesOnUiThread(boolean)}.\n     */\n    @Nullable\n    public Number min(String fieldName) {\n        realm.checkIfValid();\n        realm.checkAllowQueriesOnUiThread();\n\n        long columnIndex = schema.getAndCheckFieldColumnKey(fieldName);\n        switch (table.getColumnType(columnIndex)) {\n            case INTEGER:\n                return this.query.minimumInt(columnIndex);\n            case FLOAT:\n                return this.query.minimumFloat(columnIndex);\n            case DOUBLE:\n                return this.query.minimumDouble(columnIndex);\n            case DECIMAL128:\n                return this.query.minimumDecimal128(columnIndex);\n            default:\n                throw new IllegalArgumentException(String.format(Locale.US,\n                        TYPE_MISMATCH, fieldName, \"int, float or double\"));\n        }\n    }\n\n    /**\n     * Finds the minimum value of a field.\n     *\n     * @param fieldName the field name\n     * @return if no objects exist or they all have {@code null} as the value for the given date field, {@code null}\n     * will be returned. Otherwise the minimum date is returned. When determining the minimum date, objects with\n     * {@code null} values are ignored.\n     * @throws java.lang.UnsupportedOperationException if the query is not valid (\"syntax error\").\n     * @throws RealmException                          if called from the UI thread after opting out via {@link RealmConfiguration.Builder#allowQueriesOnUiThread(boolean)}.\n     */\n    @Nullable\n    public Date minimumDate(String fieldName) {\n        realm.checkIfValid();\n        realm.checkAllowQueriesOnUiThread();\n\n        long columnIndex = schema.getAndCheckFieldColumnKey(fieldName);\n        return this.query.minimumDate(columnIndex);\n    }\n\n    /**\n     * Finds the minimum value of a {@link RealmAny} field.\n     *\n     * @param fieldName the field containing a RealmAny value.\n     * @return if no objects exist or they all have {@code null} as the value for the given RealmAny field, {@link RealmAny.Type#NULL}\n     * will be returned. Otherwise the minimum RealmAny is returned. When determining the minimum RealmAny, objects with\n     * {@code null} values are ignored. See the {@link RealmAny} documentation for more details on how RealmAny values are compared.\n     * @throws java.lang.UnsupportedOperationException if the query is not valid (\"syntax error\").\n     * @throws RealmException                          if called from the UI thread after opting out via {@link RealmConfiguration.Builder#allowQueriesOnUiThread(boolean)}.\n     */\n    public RealmAny minRealmAny(String fieldName) {\n        realm.checkIfValid();\n        realm.checkAllowQueriesOnUiThread();\n\n        long columnIndex = schema.getAndCheckFieldColumnKey(fieldName);\n        return new RealmAny(RealmAnyOperator.fromNativeRealmAny(realm, this.query.minimumRealmAny(columnIndex)));\n    }\n\n    /**\n     * Finds the maximum value of a field.\n     *\n     * @param fieldName the field to look for a maximum on. Only number fields are supported.\n     * @return if no objects exist or they all have {@code null} as the value for the given field, {@code null} will be\n     * returned. Otherwise the maximum value is returned. When determining the maximum value, objects with {@code null}\n     * values are ignored.\n     * @throws java.lang.IllegalArgumentException if the field is not a number type.\n     * @throws RealmException                     if called from the UI thread after opting out via {@link RealmConfiguration.Builder#allowQueriesOnUiThread(boolean)}.\n     */\n    @Nullable\n    public Number max(String fieldName) {\n        realm.checkIfValid();\n        realm.checkAllowQueriesOnUiThread();\n\n        long columnIndex = schema.getAndCheckFieldColumnKey(fieldName);\n        switch (table.getColumnType(columnIndex)) {\n            case INTEGER:\n                return this.query.maximumInt(columnIndex);\n            case FLOAT:\n                return this.query.maximumFloat(columnIndex);\n            case DOUBLE:\n                return this.query.maximumDouble(columnIndex);\n            case DECIMAL128:\n                return this.query.maximumDecimal128(columnIndex);\n            default:\n                throw new IllegalArgumentException(String.format(Locale.US,\n                        TYPE_MISMATCH, fieldName, \"int, float or double\"));\n        }\n    }\n\n    /**\n     * Finds the maximum value of a field.\n     *\n     * @param fieldName the field name.\n     * @return if no objects exist or they all have {@code null} as the value for the given date field, {@code null}\n     * will be returned. Otherwise the maximum date is returned. When determining the maximum date, objects with\n     * {@code null} values are ignored.\n     * @throws java.lang.UnsupportedOperationException if the query is not valid (\"syntax error\").\n     */\n    @Nullable\n    public Date maximumDate(String fieldName) {\n        realm.checkIfValid();\n        realm.checkAllowQueriesOnUiThread();\n\n        long columnIndex = schema.getAndCheckFieldColumnKey(fieldName);\n        return this.query.maximumDate(columnIndex);\n    }\n\n    /**\n     * Finds the maximum value of a {@link RealmAny} field.\n     *\n     * @param fieldName the field containing a RealmAny value.\n     * @return if no objects exist or they all have {@code null} as the value for the given RealmAny field, {@link RealmAny.Type#NULL}\n     * will be returned. Otherwise the maximum RealmAny is returned. When determining the maximum RealmAny, objects with\n     * {@code null} values are ignored. See the {@link RealmAny} documentation for more details on how RealmAny values are compared.\n     * @throws java.lang.UnsupportedOperationException if the query is not valid (\"syntax error\").\n     */\n    public RealmAny maxRealmAny(String fieldName) {\n        realm.checkIfValid();\n        realm.checkAllowQueriesOnUiThread();\n\n        long columnIndex = schema.getAndCheckFieldColumnKey(fieldName);\n        return new RealmAny(RealmAnyOperator.fromNativeRealmAny(realm, this.query.maximumRealmAny(columnIndex)));\n    }\n\n    /**\n     * Counts the number of objects that fulfill the query conditions.\n     *\n     * @return the number of matching objects.\n     * @throws java.lang.UnsupportedOperationException if the query is not valid (\"syntax error\").\n     * @throws RealmException                          if called from the UI thread after opting out via {@link RealmConfiguration.Builder#allowQueriesOnUiThread(boolean)}.\n     */\n    public long count() {\n        realm.checkIfValid();\n        realm.checkAllowQueriesOnUiThread();\n\n        // The fastest way of doing `count()` is going through `TableQuery.count()`. Unfortunately\n        // doing this does not correctly apply all side effects of queries (like subscriptions). Also\n        // some queries constructs, like doing distinct is not easily supported this way.\n        // In order to get the best of both worlds we thus need to create a Java RealmResults object\n        // and then directly access the `Results` class from Object Store.\n        return lazyFindAll().size();\n    }\n\n    /**\n     * Finds all objects that fulfill the query conditions.\n     * <p>\n     * Launching heavy queries from the UI thread may result in a drop of frames or even ANRs. <b>We do not recommend\n     * doing so and therefore it is not allowed by default.</b> If you want to prevent these behaviors you can obtain\n     * a Realm using a {@link RealmConfiguration} that explicitly sets\n     * {@link RealmConfiguration.Builder#allowQueriesOnUiThread(boolean)} to {@code false}. This way you will be forced\n     * to launch your queries from a non-UI thread, otherwise calls to this method will throw a {@link RealmException}.\n     * Alternatively, you can use {@link #findAllAsync()}.\n     *\n     * @return a {@link io.realm.RealmResults} containing objects. If no objects match the condition, a list with zero\n     * objects is returned.\n     * @throws RealmException if called from the UI thread after opting out via {@link RealmConfiguration.Builder#allowQueriesOnUiThread(boolean)}.\n     * @see io.realm.RealmResults\n     */\n    @SuppressWarnings(\"unchecked\")\n    public RealmResults<E> findAll() {\n        realm.checkIfValid();\n        realm.checkAllowQueriesOnUiThread();\n        return createRealmResults(query, true);\n    }\n\n    /**\n     * The same as {@link #findAll()} expect the RealmResult is not forcefully evaluated. This\n     * means this method will return a more \"pure\" wrapper around the Object Store Results class.\n     * <p>\n     * This can be useful for internal usage where we still want to take advantage of optimizations\n     * and additional functionality provided by Object Store, but do not wish to trigger the query\n     * unless needed.\n     */\n    private OsResults lazyFindAll() {\n        realm.checkIfValid();\n        return createRealmResults(\n                query,\n                false).osResults;\n    }\n\n    /**\n     * Finds all objects that fulfill the query conditions. This method is only available from a Looper thread.\n     *\n     * @return immediately an empty {@link RealmResults}. Users need to register a listener\n     * {@link io.realm.RealmResults#addChangeListener(RealmChangeListener)} to be notified when the query completes.\n     * @see io.realm.RealmResults\n     */\n    public RealmResults<E> findAllAsync() {\n        realm.checkIfValid();\n        realm.sharedRealm.capabilities.checkCanDeliverNotification(ASYNC_QUERY_WRONG_THREAD_MESSAGE);\n        return createRealmResults(query, false);\n    }\n\n    /**\n     * Sorts the query result by the specific field name in ascending order.\n     * <p>\n     * Sorting is currently limited to character sets in 'Latin Basic', 'Latin Supplement', 'Latin Extended A',\n     * 'Latin Extended B' (UTF-8 range 0-591). For other character sets, sorting will have no effect.\n     *\n     * @param fieldName the field name to sort by.\n     * @throws IllegalArgumentException if the field name does not exist.\n     * @throws IllegalStateException    if a sorting order was already defined.\n     */\n    public RealmQuery<E> sort(String fieldName) {\n        realm.checkIfValid();\n        return sort(fieldName, Sort.ASCENDING);\n    }\n\n    /**\n     * Sorts the query result by the specified field name and order.\n     * <p>\n     * Sorting is currently limited to character sets in 'Latin Basic', 'Latin Supplement', 'Latin Extended A',\n     * 'Latin Extended B' (UTF-8 range 0-591). For other character sets, sorting will have no effect.\n     *\n     * @param fieldName the field name to sort by.\n     * @param sortOrder how to sort the results.\n     * @throws IllegalArgumentException if the field name does not exist.\n     * @throws IllegalStateException    if a sorting order was already defined.\n     */\n    public RealmQuery<E> sort(String fieldName, Sort sortOrder) {\n        realm.checkIfValid();\n        return sort(new String[] {fieldName}, new Sort[] {sortOrder});\n    }\n\n    /**\n     * Sorts the query result by the specific field names in the provided orders. {@code fieldName2} is only used\n     * in case of equal values in {@code fieldName1}.\n     * <p>\n     * Sorting is currently limited to character sets in 'Latin Basic', 'Latin Supplement', 'Latin Extended A',\n     * 'Latin Extended B' (UTF-8 range 0-591). For other character sets, sorting will have no effect.\n     *\n     * @param fieldName1 first field name\n     * @param sortOrder1 sort order for first field\n     * @param fieldName2 second field name\n     * @param sortOrder2 sort order for second field\n     * @throws IllegalArgumentException if the field name does not exist.\n     * @throws IllegalStateException    if a sorting order was already defined.\n     */\n    public RealmQuery<E> sort(String fieldName1, Sort sortOrder1, String fieldName2, Sort sortOrder2) {\n        realm.checkIfValid();\n        return sort(new String[] {fieldName1, fieldName2}, new Sort[] {sortOrder1, sortOrder2});\n    }\n\n    /**\n     * Sorts the query result by the specific field names in the provided orders. Later fields will only be used\n     * if the previous field values are equal.\n     * <p>\n     * Sorting is currently limited to character sets in 'Latin Basic', 'Latin Supplement', 'Latin Extended A',\n     * 'Latin Extended B' (UTF-8 range 0-591). For other character sets, sorting will have no effect.\n     *\n     * @param fieldNames an array of field names to sort by.\n     * @param sortOrders how to sort the field names.\n     * @throws IllegalArgumentException if the field name does not exist.\n     * @throws IllegalStateException    if a sorting order was already defined.\n     */\n    public RealmQuery<E> sort(String[] fieldNames, Sort[] sortOrders) {\n        if ((sortOrders == null) || (sortOrders.length == 0)) {\n            throw new IllegalArgumentException(\"You must provide at least one sort order.\");\n        }\n        if (fieldNames.length != sortOrders.length) {\n            throw new IllegalArgumentException(\"Number of fields and sort orders do not match.\");\n        }\n\n        realm.checkIfValid();\n\n        this.query.sort(realm.getSchema().getKeyPathMapping(), fieldNames, sortOrders);\n        return this;\n    }\n\n    /**\n     * Selects a distinct set of objects of a specific class. When multiple distinct fields are\n     * given, all unique combinations of values in the fields will be returned. In case of multiple\n     * matches, it is undefined which object is returned. Unless the result is sorted, then the\n     * first object will be returned.\n     *\n     * @param firstFieldName      first field name to use when finding distinct objects.\n     * @param remainingFieldNames remaining field names when determining all unique combinations of field values.\n     * @throws IllegalArgumentException if field names is empty or {@code null}, does not exist,\n     *                                  is an unsupported type, or points to a linked field.\n     * @throws IllegalStateException    if distinct field names were already defined.\n     */\n    public RealmQuery<E> distinct(String firstFieldName, String... remainingFieldNames) {\n        realm.checkIfValid();\n        String[] fieldNames = new String[1 + remainingFieldNames.length];\n\n        fieldNames[0] = firstFieldName;\n        for (int i = 0; i < remainingFieldNames.length; i++) {\n            fieldNames[1 + i] = remainingFieldNames[i];\n        }\n\n        this.query.distinct(realm.getSchema().getKeyPathMapping(), fieldNames);\n        return this;\n    }\n\n    /**\n     * Limits the number of objects returned in case the query matched more objects.\n     * <p>\n     * Note that when using this method in combination with {@link #sort(String)} and\n     * {@link #distinct(String, String...)} they will be executed in the order they where added which can\n     * affect the end result.\n     *\n     * @param limit a limit that is {@code &ge; 1}.\n     * @throws IllegalArgumentException if the provided {@code limit} is less than 1.\n     */\n    public RealmQuery<E> limit(long limit) {\n        realm.checkIfValid();\n        this.query.limit(limit);\n        return this;\n    }\n\n    /**\n     * This predicate will always match.\n     */\n    public RealmQuery<E> alwaysTrue() {\n        realm.checkIfValid();\n        query.alwaysTrue();\n        return this;\n    }\n\n    /**\n     * This predicate will never match, resulting in the query always returning 0 results.\n     */\n    public RealmQuery<E> alwaysFalse() {\n        realm.checkIfValid();\n        query.alwaysFalse();\n        return this;\n    }\n\n    /**\n     * Create a text-based predicate using the Realm Query Language. This predicate can be combined\n     * with other raw or type safe predicates, it accepts Realm values as arguments.\n     * <p>\n     * Class and property names used in the raw predicate can be either the names defined in the\n     * Realm Model classes or the internal names defined using the {@link io.realm.annotations.RealmClass}\n     * or {@link io.realm.annotations.RealmField} annotations. If a class or property name contains spaces those must\n     * be escaped.\n     * </p>\n     * Arguments are defined in the string predicate as $argument_index, where $argument_index is a decimal integer that\n     * specifies the position of the argument in the argument list. The first argument is referenced by $0, the second\n     * by $1, etc.\n     * <p>\n     * See <a href=\"https://docs.mongodb.com/realm-sdks/js/latest/tutorial-query-language.html\">these docs</a>\n     * for a more detailed description of the Realm Query Language.\n     * <p>\n     * <pre>\n     * Examples:\n     * {@code\n     * RealmQuery<Person> query = realm.where(Person.class);\n     *\n     * // Simple query\n     * query.rawPredicate(\"name = 'Jane'\");\n     *\n     * // Spaces in property name\n     * query.rawPredicate(\"my\\ property = 'Jane'\");\n     *\n     * // Multiple predicates\n     * query.rawPredicate(\"name = 'Jane' OR name = 'John'\")\n     *\n     * // Collection queries\n     * query.rawPredicate(\"children.@count > 3\")\n     * query.rawPredicate(\"ALL children.age > 18\")\n     *\n     * // Sub queries\n     * query.rawPredicate(\"SUBQUERY(children, $child, $child.age > 21 AND $child.gender = 'male').@count > 0\");\n     *\n     * // Sort, Distinct, Limit\n     * query.rawPredicate(\"name = 'Jane' SORT(lastName ASC) DISTINCT(city) LIMIT(5)\");\n     *\n     * // Arguments\n     * query.rawPredicate(\"name = $0 AND age > $1\", \"Jane\", 18);\n     * }\n     * </pre>\n     *\n     * @param predicate a Realm Query Language predicate.\n     * @param arguments Realm values for the predicate.\n     * @throws java.lang.IllegalArgumentException if there is an syntax error.\n     */\n    public RealmQuery<E> rawPredicate(String predicate, Object... arguments) {\n        realm.checkIfValid();\n\n        if (Util.isEmptyString(predicate)) {\n            throw new IllegalArgumentException(\"Non-null 'predicate' required.\");\n        }\n\n        RealmAny[] realmAnyArgs = new RealmAny[arguments.length];\n        for (int i = 0; i < arguments.length; i++) {\n            realmAnyArgs[i] = RealmAny.valueOf(arguments[i]);\n        }\n\n        try {\n            query.rawPredicate(realm.getSchema().getKeyPathMapping(), predicate, realmAnyArgs);\n        } catch (IllegalArgumentException e) {\n            if(e.getMessage().startsWith(\"Illegal Argument: Request for argument at index\")) {\n                throw new IllegalStateException(e.getMessage());\n            }\n            throw e;\n        }\n\n        return this;\n    }\n\n    /**\n     * Returns the {@link Realm} instance to which this query belongs.\n     * <p>\n     * Calling {@link Realm#close()} on the returned instance is discouraged as it is the same as\n     * calling it on the original Realm instance which may cause the Realm to fully close invalidating the\n     * query.\n     *\n     * @return {@link Realm} instance this query belongs to.\n     * @throws IllegalStateException if the Realm is an instance of {@link DynamicRealm} or the\n     *                               {@link Realm} was already closed.\n     */\n    public Realm getRealm() {\n        if (realm == null) {\n            return null;\n        }\n        realm.checkIfValid();\n        if (!(realm instanceof Realm)) {\n            throw new IllegalStateException(\"This method is only available for typed Realms\");\n        }\n        return (Realm) realm;\n    }\n\n    /**\n     * Returns a textual description of this query.\n     *\n     * @return the textual description of the query.\n     */\n    public String getDescription() {\n        this.query.validateQuery();\n        return nativeSerializeQuery(query.getNativePtr());\n    }\n\n    /**\n     * Returns the internal Realm name of the type being queried.\n     *\n     * @return the internal name of the Realm model class being queried.\n     */\n    public String getTypeQueried() {\n        // TODO Revisit this when primitive list queries are implemented.\n        return table.getClassName();\n    }\n\n    /**\n     * Returns the pointer to the underlying C++ query.\n     *\n     * This method is only public due to architectural design choices that are hard to work\n     * around and should be considered internal and can change without warning.\n     *\n     * @return the pointer to the underlying C++ query.\n     */\n    public long getQueryPointer() {\n        return query.getNativePtr();\n    }\n\n    private boolean isDynamicQuery() {\n        return className != null;\n    }\n\n    /**\n     * Finds the first object that fulfills the query conditions.\n     * <p>\n     * Launching heavy queries from the UI thread may result in a drop of frames or even ANRs. <b>We do not recommend\n     * doing so, but it is allowed by default.</b> If you want to prevent these behaviors you can obtain a Realm using\n     * a {@link RealmConfiguration} that explicitly sets\n     * {@link RealmConfiguration.Builder#allowQueriesOnUiThread(boolean)} to {@code false}. This way you will be forced\n     * to launch your queries from a non-UI thread, otherwise calls to this method will throw a {@link RealmException}.\n     * Alternatively, you can use {@link #findFirstAsync()}.\n     *\n     * @return the object found or {@code null} if no object matches the query conditions.\n     * @throws RealmException if called from the UI thread after opting out via {@link RealmConfiguration.Builder#allowQueriesOnUiThread(boolean)}.\n     * @see io.realm.RealmObject\n     */\n    @Nullable\n    public E findFirst() {\n        realm.checkIfValid();\n        realm.checkAllowQueriesOnUiThread();\n\n        if (forValues) {\n            // TODO implement this;\n            return null;\n        }\n\n        long tableRowIndex = getSourceRowIndexForFirstObject();\n        //noinspection unchecked\n        return (tableRowIndex < 0) ? null : (E) realm.get((Class<? extends RealmModel>) clazz, className, tableRowIndex);\n    }\n\n    /**\n     * Similar to {@link #findFirst()} but runs asynchronously on a worker thread. A listener should be registered to\n     * the returned {@link RealmObject} to get the notification when query completes. The registered listener will also\n     * be triggered if there are changes made to the queried {@link RealmObject}. If the {@link RealmObject} is deleted,\n     * the listener will be called one last time and then stop. The query will not be re-run.\n     *\n     * @return immediately an empty {@link RealmObject} with {@code isLoaded() == false}. Trying to access any field on\n     * the returned object before it is loaded will throw an {@code IllegalStateException}.\n     * @throws IllegalStateException if this is called on a non-looper thread.\n     */\n    public E findFirstAsync() {\n        realm.checkIfValid();\n\n        if (forValues) {\n            throw new UnsupportedOperationException(\"findFirstAsync() available only when type parameter 'E' is implementing RealmModel.\");\n        }\n\n        realm.sharedRealm.capabilities.checkCanDeliverNotification(ASYNC_QUERY_WRONG_THREAD_MESSAGE);\n        Row row;\n        if (realm.isInTransaction()) {\n            // It is not possible to create async query inside a transaction. So immediately query the first object.\n            // See OS Results::prepare_async()\n            row = OsResults.createFromQuery(realm.sharedRealm, query).firstUncheckedRow();\n        } else {\n            // prepares an empty reference of the RealmObject which is backed by a pending query,\n            // then update it once the query complete in the background.\n\n            // TODO: The performance by the pending query will be a little bit worse than directly calling core's\n            // Query.find(). The overhead comes with core needs to add all the row indices to the vector. However this\n            // can be optimized by adding support of limit in OS's Results which is supported by core already.\n            row = new PendingRow(realm.sharedRealm, query, isDynamicQuery());\n        }\n        final E result;\n        if (isDynamicQuery()) {\n            //noinspection unchecked\n            result = (E) new DynamicRealmObject(realm, row);\n        } else {\n            //noinspection unchecked\n            final Class<? extends RealmModel> modelClass = (Class<? extends RealmModel>) clazz;\n            //noinspection unchecked\n            result = (E) realm.getConfiguration().getSchemaMediator().newInstance(\n                    modelClass, realm, row, realm.getSchema().getColumnInfo(modelClass),\n                    false, Collections.emptyList());\n        }\n\n        if (row instanceof PendingRow) {\n            final RealmObjectProxy proxy = (RealmObjectProxy) result;\n            ((PendingRow) row).setFrontEnd(proxy.realmGet$proxyState());\n        }\n\n        return result;\n    }\n\n\n    private RealmResults<E> createRealmResults(TableQuery query,\n            boolean loadResults) {\n        RealmResults<E> results;\n        OsResults osResults;\n        osResults = OsResults.createFromQuery(realm.sharedRealm, query);\n\n        if (isDynamicQuery()) {\n            results = new RealmResults<>(realm, osResults, className);\n        } else {\n            results = new RealmResults<>(realm, osResults, clazz);\n        }\n        if (loadResults) {\n            results.load();\n        }\n\n        return results;\n    }\n\n    private long getSourceRowIndexForFirstObject() {\n        return this.query.find();\n    }\n\n    private static native String nativeSerializeQuery(long tableQueryPtr);\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/RealmResults.java",
    "content": "/*\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\npackage io.realm;\n\nimport android.annotation.SuppressLint;\nimport android.os.Looper;\n\nimport org.bson.types.Decimal128;\nimport org.bson.types.ObjectId;\n\nimport java.util.Date;\nimport java.util.Locale;\nimport java.util.UUID;\n\nimport javax.annotation.Nullable;\n\nimport io.reactivex.Flowable;\nimport io.reactivex.Observable;\nimport io.realm.internal.Freezable;\nimport io.realm.internal.OsResults;\nimport io.realm.internal.RealmObjectProxy;\nimport io.realm.internal.Row;\nimport io.realm.internal.Table;\nimport io.realm.internal.UncheckedRow;\nimport io.realm.internal.Util;\nimport io.realm.internal.android.JsonUtils;\nimport io.realm.log.RealmLog;\nimport io.realm.rx.CollectionChange;\n\n/**\n * This class holds all the matches of a {@link RealmQuery} for a given Realm. The objects are not copied from\n * the Realm to the RealmResults list, but are just referenced from the RealmResult instead. This saves memory and\n * increases speed.\n * <p>\n * RealmResults are live views, which means that if it is on an {@link Looper} thread, it will automatically\n * update its query results after a transaction has been committed. If on a non-looper thread,\n * {@link Realm#refresh()} must be called to update the results.\n * <p>\n * Updates to RealmObjects from a RealmResults list must be done from within a transaction and the modified objects are\n * persisted to the Realm file during the commit of the transaction.\n * <p>\n * A RealmResults object cannot be passed between different threads.\n * <p>\n * Notice that a RealmResults is never {@code null} not even in the case where it contains no objects. You should always\n * use the {@link RealmResults#size()} method to check if a RealmResults is empty or not.\n * <p>\n * If a RealmResults is built on RealmList through {@link RealmList#where()}, it will become empty when the source\n * RealmList gets deleted.\n * <p>\n * {@link RealmResults} can contain more elements than {@code Integer.MAX_VALUE}.\n * In that case, you can access only first {@code Integer.MAX_VALUE} elements in it.\n *\n * @param <E> The class of objects in this list.\n * @see RealmQuery#findAll()\n * @see Realm#executeTransaction(Realm.Transaction)\n */\npublic class RealmResults<E> extends OrderedRealmCollectionImpl<E> {\n\n    // Called from Realm Proxy classes\n    @SuppressLint(\"unused\")\n    static <T extends RealmModel> RealmResults<T> createBacklinkResults(BaseRealm realm, Row row, Class<T> srcTableType, String srcFieldName) {\n        UncheckedRow uncheckedRow = (UncheckedRow) row;\n        Table srcTable = realm.getSchema().getTable(srcTableType);\n        return new RealmResults<>(\n                realm,\n                OsResults.createForBacklinks(realm.sharedRealm, uncheckedRow, srcTable, srcFieldName),\n                srcTableType);\n    }\n\n    // Abandon typing information, all ye who enter here\n    static RealmResults<DynamicRealmObject> createDynamicBacklinkResults(DynamicRealm realm, UncheckedRow row, Table srcTable, String srcFieldName) {\n        final String srcClassName = Table.getClassNameForTable(srcTable.getName());\n        //noinspection ConstantConditions\n        return new RealmResults<>(\n                realm,\n                OsResults.createForBacklinks(realm.sharedRealm, row, srcTable, srcFieldName),\n                srcClassName);\n    }\n\n    RealmResults(BaseRealm realm, OsResults osResults, Class<E> clazz) {\n        this(realm, osResults, clazz, false);\n    }\n\n    RealmResults(BaseRealm realm, OsResults osResults, Class<E> clazz, boolean forPrimitives) {\n        super(realm, osResults, clazz, getCollectionOperator(forPrimitives, realm, osResults, clazz, null));\n    }\n\n    RealmResults(BaseRealm realm, OsResults osResults, String className) {\n        this(realm, osResults, className, false);\n    }\n\n    RealmResults(BaseRealm realm, OsResults osResults, String className, boolean forPrimitives) {\n        super(realm, osResults, className, getCollectionOperator(forPrimitives, realm, osResults, null, className));\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    @Override\n    public RealmQuery<E> where() {\n        baseRealm.checkIfValid();\n        return RealmQuery.createQueryFromResult(this);\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    @Override\n    public RealmResults<E> sort(String fieldName1, Sort sortOrder1, String fieldName2, Sort sortOrder2) {\n        return sort(new String[] {fieldName1, fieldName2}, new Sort[] {sortOrder1, sortOrder2});\n    }\n\n    /**\n     * Returns {@code false} if the results are not yet loaded, {@code true} if they are loaded.\n     *\n     * @return {@code true} if the query has completed and the data is available, {@code false} if the query is still\n     * running in the background.\n     */\n    @Override\n    public boolean isLoaded() {\n        baseRealm.checkIfValid();\n        return osResults.isLoaded();\n    }\n\n    /**\n     * Makes an asynchronous query blocking. This will also trigger any registered {@link RealmChangeListener} when\n     * the query completes.\n     *\n     * @return {@code true} if it successfully completed the query, {@code false} otherwise.\n     */\n    @Override\n    public boolean load() {\n        // The OsResults doesn't have to be loaded before accessing it if the query has not returned.\n        // Instead, accessing the OsResults will just trigger the execution of query if needed. We add this flag is\n        // only to keep the original behavior of those APIs. eg.: For a async RealmResults, before query returns, the\n        // size() call should return 0 instead of running the query get the real size.\n        baseRealm.checkIfValid();\n        osResults.load();\n        return true;\n    }\n\n\n    /**\n     * Updates the field given by {@code fieldName} in all objects inside the query result.\n     * <p>\n     * This method will automatically try to convert numbers and booleans that are given as\n     * {@code String} to their appropriate type. For example {@code \"10\"} will be converted to\n     * {@code 10} if the field type is {@link RealmFieldType#INTEGER}.\n     * <p>\n     * Using the typed setters like {@link #setInt(String, int)} will be faster than using\n     * this method.\n     *\n     * @param fieldName field to update\n     * @param value value to update with.\n     * @throws IllegalArgumentException if the field could not be found, could not be updated or\n     * the argument didn't match the field type or could not be converted to match the underlying\n     * field type.\n     */\n    public void setValue(String fieldName, @Nullable Object value) {\n        checkNonEmptyFieldName(fieldName);\n        baseRealm.checkIfValidAndInTransaction();\n        fieldName = mapFieldNameToInternalName(fieldName);\n        boolean isString = (value instanceof String);\n        String strValue = isString ? (String) value : null;\n\n        String className = osResults.getTable().getClassName();\n        RealmObjectSchema schema = getRealm().getSchema().get(className);\n        if (!schema.hasField(fieldName)) {\n            throw new IllegalArgumentException(String.format(\"Field '%s' could not be found in class '%s'\", fieldName, className));\n        }\n\n        // null values exit early\n        if (value == null) {\n            osResults.setNull(fieldName);\n            return;\n        }\n\n        // Does implicit conversion if needed.\n        RealmFieldType type = schema.getFieldType(fieldName);\n        if (isString && type != RealmFieldType.STRING) {\n            switch (type) {\n                case BOOLEAN:\n                    value = Boolean.parseBoolean(strValue);\n                    break;\n                case INTEGER:\n                    value = Long.parseLong(strValue);\n                    break;\n                case FLOAT:\n                    value = Float.parseFloat(strValue);\n                    break;\n                case DOUBLE:\n                    value = Double.parseDouble(strValue);\n                    break;\n                case DATE:\n                    value = JsonUtils.stringToDate(strValue);\n                    break;\n                case DECIMAL128:\n                    value = Decimal128.parse(strValue);\n                    break;\n                case OBJECT_ID:\n                    value = new ObjectId(strValue);\n                    break;\n                case UUID:\n                    value = UUID.fromString(strValue);\n                    break;\n                default:\n                    throw new IllegalArgumentException(String.format(Locale.US,\n                            \"Field %s is not a String field, \" +\n                                    \"and the provide value could not be automatically converted: %s. Use a typed\" +\n                                    \"setter instead\", fieldName, value));\n            }\n        }\n\n        //noinspection ConstantConditions\n        Class<?> valueClass = value.getClass();\n        if (valueClass == Boolean.class) {\n            setBoolean(fieldName, (Boolean) value);\n        } else if (valueClass == Short.class) {\n            setShort(fieldName, (Short) value);\n        } else if (valueClass == Integer.class) {\n            setInt(fieldName, (Integer) value);\n        } else if (valueClass == Long.class) {\n            setLong(fieldName, (Long) value);\n        } else if (valueClass == Byte.class) {\n            setByte(fieldName, (Byte) value);\n        } else if (valueClass == Float.class) {\n            setFloat(fieldName, (Float) value);\n        } else if (valueClass == Double.class) {\n            setDouble(fieldName, (Double) value);\n        } else if (valueClass == String.class) {\n            //noinspection ConstantConditions\n            setString(fieldName, (String) value);\n        } else if (value instanceof Date) {\n            setDate(fieldName, (Date) value);\n        } else if (value instanceof Decimal128) {\n            setDecimal128(fieldName, (Decimal128) value);\n        } else if (value instanceof ObjectId) {\n            setObjectId(fieldName, (ObjectId) value);\n        } else if (value instanceof UUID) {\n            setUUID(fieldName, (UUID) value);\n        } else if (value instanceof byte[]) {\n            setBlob(fieldName, (byte[]) value);\n        } else if (value instanceof RealmModel) {\n            setObject(fieldName, (RealmModel) value);\n        } else if (valueClass == RealmList.class) {\n            RealmList<?> list = (RealmList<?>) value;\n            setList(fieldName, list);\n        } else {\n            throw new IllegalArgumentException(\"Value is of a type not supported: \" + value.getClass());\n        }\n    }\n\n    /**\n     * Sets the value to {@code null} for the given field in all of the objects in the collection.\n     *\n     * @param fieldName name of the field to update.\n     * @throws IllegalArgumentException if field name doesn't exist or is a primary key property.\n     * @throws IllegalStateException if the field cannot hold {@code null} values.\n     */\n    public void setNull(String fieldName) {\n        checkNonEmptyFieldName(fieldName);\n        baseRealm.checkIfValidAndInTransaction();\n        osResults.setNull(fieldName);\n    }\n\n    /**\n     * Sets the {@code boolean} value of the given field in all of the objects in the collection.\n     *\n     * @param fieldName name of the field to update.\n     * @param value new value for the field.\n     * @throws IllegalArgumentException if field name doesn't exist, is a primary key property or isn't a boolean field.\n     */\n    public void setBoolean(String fieldName, boolean value) {\n        checkNonEmptyFieldName(fieldName);\n        baseRealm.checkIfValidAndInTransaction();\n        fieldName = mapFieldNameToInternalName(fieldName);\n        checkType(fieldName, RealmFieldType.BOOLEAN);\n        osResults.setBoolean(fieldName, value);\n    }\n\n    /**\n     * Sets the {@code byte} value of the given field in all of the objects in the collection.\n     *\n     * @param fieldName name of the field to update.\n     * @param value new value for the field.\n     * @throws IllegalArgumentException if field name doesn't exist, is a primary key property or isn't a byte field.\n     */\n    public void setByte(String fieldName, byte value) {\n        checkNonEmptyFieldName(fieldName);\n        baseRealm.checkIfValidAndInTransaction();\n        fieldName = mapFieldNameToInternalName(fieldName);\n        checkType(fieldName, RealmFieldType.INTEGER);\n        osResults.setInt(fieldName, value);\n    }\n\n    /**\n     * Sets the {@code short} value of the given field in all of the objects in the collection.\n     *\n     * @param fieldName name of the field to update.\n     * @param value new value for the field.\n     * @throws IllegalArgumentException if field name doesn't exist, is a primary key property or isn't a short field.\n     */\n    public void setShort(String fieldName, short value) {\n        checkNonEmptyFieldName(fieldName);\n        baseRealm.checkIfValidAndInTransaction();\n        fieldName = mapFieldNameToInternalName(fieldName);\n        checkType(fieldName, RealmFieldType.INTEGER);\n        osResults.setInt(fieldName, value);\n    }\n\n    /**\n     * Sets the {@code int} value of the given field in all of the objects in the collection.\n     *\n     * @param fieldName name of the field to update.\n     * @param value new value for the field.\n     * @throws IllegalArgumentException if field name doesn't exist, is a primary key property or isn't an integer field.\n     */\n    public void setInt(String fieldName, int value) {\n        checkNonEmptyFieldName(fieldName);\n        fieldName = mapFieldNameToInternalName(fieldName);\n        checkType(fieldName, RealmFieldType.INTEGER);\n        baseRealm.checkIfValidAndInTransaction();\n        osResults.setInt(fieldName, value);\n    }\n\n    /**\n     * Sets the {@code long} value of the given field in all of the objects in the collection.\n     *\n     * @param fieldName name of the field to update.\n     * @param value new value for the field.\n     * @throws IllegalArgumentException if field name doesn't exist, is a primary key property or isn't a long field.\n     */\n    public void setLong(String fieldName, long value) {\n        checkNonEmptyFieldName(fieldName);\n        baseRealm.checkIfValidAndInTransaction();\n        fieldName = mapFieldNameToInternalName(fieldName);\n        checkType(fieldName, RealmFieldType.INTEGER);\n        osResults.setInt(fieldName, value);\n    }\n\n    /**\n     * Sets the {@code float} value of the given field in all of the objects in the collection.\n     *\n     * @param fieldName name of the field to update.\n     * @param value new value for the field.\n     * @throws IllegalArgumentException if field name doesn't exist, is a primary key property or isn't a float field.\n     */\n    public void setFloat(String fieldName, float value) {\n        checkNonEmptyFieldName(fieldName);\n        baseRealm.checkIfValidAndInTransaction();\n        fieldName = mapFieldNameToInternalName(fieldName);\n        checkType(fieldName, RealmFieldType.FLOAT);\n        osResults.setFloat(fieldName, value);\n    }\n\n    /**\n     * Sets the {@code double} value of the given field in all of the objects in the collection.\n     *\n     * @param fieldName name of the field to update.\n     * @param value new value for the field.\n     * @throws IllegalArgumentException if field name doesn't exist, is a primary key property or isn't a double field.\n     */\n    public void setDouble(String fieldName, double value) {\n        checkNonEmptyFieldName(fieldName);\n        baseRealm.checkIfValidAndInTransaction();\n        fieldName = mapFieldNameToInternalName(fieldName);\n        checkType(fieldName, RealmFieldType.DOUBLE);\n        osResults.setDouble(fieldName, value);\n    }\n\n    /**\n     * Sets the {@code String} value of the given field in all of the objects in the collection.\n     *\n     * @param fieldName name of the field to update.\n     * @param value new value for the field.\n     * @throws IllegalArgumentException if field name doesn't exist, is a primary key property or isn't a String field.\n     */\n    public void setString(String fieldName, @Nullable String value) {\n        checkNonEmptyFieldName(fieldName);\n        baseRealm.checkIfValidAndInTransaction();\n        fieldName = mapFieldNameToInternalName(fieldName);\n        checkType(fieldName, RealmFieldType.STRING);\n        osResults.setString(fieldName, value);\n    }\n\n    /**\n     * Sets the binary value of the given field in all of the objects in the collection.\n     *\n     * @param fieldName name of the field to update.\n     * @param value new value for the field.\n     * @throws IllegalArgumentException if field name doesn't exist, is a primary key property or isn't a binary field.\n     */\n    public void setBlob(String fieldName, @Nullable byte[] value) {\n        checkNonEmptyFieldName(fieldName);\n        baseRealm.checkIfValidAndInTransaction();\n        fieldName = mapFieldNameToInternalName(fieldName);\n        checkType(fieldName, RealmFieldType.BINARY);\n        osResults.setBlob(fieldName, value);\n    }\n\n    /**\n     * Sets the {@code Date} value of the given field in all of the objects in the collection.\n     *\n     * @param fieldName name of the field to update.\n     * @param value new value for the field.\n     * @throws IllegalArgumentException if field name doesn't exist, is a primary key property or isn't a {@code Date} field.\n     */\n    public void setDate(String fieldName, @Nullable Date value) {\n        checkNonEmptyFieldName(fieldName);\n        baseRealm.checkIfValidAndInTransaction();\n        fieldName = mapFieldNameToInternalName(fieldName);\n        checkType(fieldName, RealmFieldType.DATE);\n        osResults.setDate(fieldName, value);\n    }\n\n    /**\n     * Sets a reference to another object on the given field in all of the objects in the collection.\n     *\n     * @param fieldName name of the field to update.\n     * @param value new object referenced by this field.\n     * @throws IllegalArgumentException if field name doesn't exist, is a primary key property or isn't an Object reference field.\n     */\n    public void setObject(String fieldName, @Nullable RealmModel value) {\n        checkNonEmptyFieldName(fieldName);\n        baseRealm.checkIfValidAndInTransaction();\n        fieldName = mapFieldNameToInternalName(fieldName);\n        checkType(fieldName, RealmFieldType.OBJECT);\n        Row row = checkRealmObjectConstraints(fieldName, value);\n        osResults.setObject(fieldName, row);\n    }\n\n    /**\n     * Sets the {@code Decimal128} value of the given field in all of the objects in the collection.\n     *\n     * @param fieldName name of the field to update.\n     * @param value new value for the field.\n     * @throws IllegalArgumentException if field name doesn't exist, is a primary key property or isn't a {@code Decimal128} field.\n     */\n    public void setDecimal128(String fieldName, @Nullable Decimal128 value) {\n        checkNonEmptyFieldName(fieldName);\n        baseRealm.checkIfValidAndInTransaction();\n        fieldName = mapFieldNameToInternalName(fieldName);\n        checkType(fieldName, RealmFieldType.DECIMAL128);\n        osResults.setDecimal128(fieldName, value);\n    }\n\n    /**\n     * Sets the {@code ObjectId} value of the given field in all of the objects in the collection.\n     *\n     * @param fieldName name of the field to update.\n     * @param value new value for the field.\n     * @throws IllegalArgumentException if field name doesn't exist, is a primary key property or isn't a {@code ObjectId} field.\n     */\n    public void setObjectId(String fieldName, @Nullable ObjectId value) {\n        checkNonEmptyFieldName(fieldName);\n        baseRealm.checkIfValidAndInTransaction();\n        fieldName = mapFieldNameToInternalName(fieldName);\n        checkType(fieldName, RealmFieldType.OBJECT_ID);\n        osResults.setObjectId(fieldName, value);\n    }\n\n    /**\n     * Sets the {@code UUID} value of the given field in all of the objects in the collection.\n     *\n     * @param fieldName name of the field to update.\n     * @param value new value for the field.\n     * @throws IllegalArgumentException if field name doesn't exist, is a primary key property or isn't a {@code UUID} field.\n     */\n    public void setUUID(String fieldName, @Nullable UUID value) {\n        checkNonEmptyFieldName(fieldName);\n        baseRealm.checkIfValidAndInTransaction();\n        fieldName = mapFieldNameToInternalName(fieldName);\n        checkType(fieldName, RealmFieldType.UUID);\n        osResults.setUUID(fieldName, value);\n    }\n\n    private Row checkRealmObjectConstraints(String fieldName, @Nullable RealmModel value) {\n        if (value != null) {\n            if (!(RealmObject.isManaged(value) && RealmObject.isValid(value))) {\n                throw new IllegalArgumentException(\"'value' is not a valid, managed Realm object.\");\n            }\n            ProxyState proxyState = ((RealmObjectProxy) value).realmGet$proxyState();\n            if (!proxyState.getRealm$realm().getPath().equals(baseRealm.getPath())) {\n                throw new IllegalArgumentException(\"'value' does not belong to the same Realm as the RealmResults.\");\n            }\n\n            // Check that type matches the expected one\n            Table currentTable = osResults.getTable();\n            long columnKey = currentTable.getColumnKey(fieldName);\n            Table expectedTable = currentTable.getLinkTarget(columnKey);\n            Table inputTable = proxyState.getRow$realm().getTable();\n            if (!expectedTable.hasSameSchema(inputTable)) {\n                throw new IllegalArgumentException(String.format(Locale.US,\n                        \"Type of object is wrong. Was '%s', expected '%s'\",\n                        inputTable.getClassName(), expectedTable.getClassName()));\n            }\n            return proxyState.getRow$realm();\n        }\n\n        return null;\n    }\n\n    /**\n     * Replaces the RealmList at the given field on all objects in this collection.\n     *\n     *\n     * @param fieldName name of the field to update.\n     * @param list new value for the field.\n     * @throws IllegalArgumentException if field name doesn't exist, isn't a RealmList field , if the\n     * objects in the list are not managed or the type of the objects in the list are wrong.\n     */\n    @SuppressWarnings(\"unchecked\")\n    public <T> void setList(String fieldName, RealmList<T> list) {\n        checkNonEmptyFieldName(fieldName);\n        fieldName = mapFieldNameToInternalName(fieldName);\n        baseRealm.checkIfValidAndInTransaction();\n\n        //noinspection ConstantConditions\n        if (list == null) {\n            throw new IllegalArgumentException(\"Non-null 'list' required\");\n        }\n\n        // Due to type erasure of generics it is not possible to have multiple overloaded methods with the same signature.\n        // So instead we fake  it by checking the first element in the list and verifies that\n        // against the underlying type.\n        RealmFieldType columnType = baseRealm.getSchema().getSchemaForClass(osResults.getTable().getClassName()).getFieldType(fieldName);\n        switch (columnType) {\n            case LIST:\n                checkTypeOfListElements(list, RealmModel.class);\n                checkRealmObjectConstraints(fieldName, (RealmModel) list.first(null));\n                osResults.setModelList(fieldName, (RealmList<RealmModel>) list);\n                break;\n            case INTEGER_LIST:\n                // Integers are a bit annoying as they are all stored as the same type in Core\n                // but the Java type system cannot seamlessly translate between e.g Short and Long.\n                Class<?> listType = getListType(list);\n                if (listType.equals(Integer.class)) {\n                    osResults.setIntegerList(fieldName, (RealmList<Integer>) list);\n                } else if (listType.equals(Long.class)) {\n                    osResults.setLongList(fieldName, (RealmList<Long>) list);\n                } else if (listType.equals(Short.class)) {\n                    osResults.setShortList(fieldName, (RealmList<Short>) list);\n                } else if (listType.equals(Byte.class)) {\n                    osResults.setByteList(fieldName, (RealmList<Byte>) list);\n                } else {\n                    throw new IllegalArgumentException(String.format(\"List contained the wrong type of elements. \" +\n                                    \"Elements that can be mapped to Integers was expected, but the actual type is '%s'\",\n                            listType));\n                }\n                break;\n            case BOOLEAN_LIST:\n                checkTypeOfListElements(list, Boolean.class);\n                osResults.setBooleanList(fieldName, (RealmList<Boolean>) list);\n                break;\n            case STRING_LIST:\n                checkTypeOfListElements(list, String.class);\n                osResults.setStringList(fieldName, (RealmList<String>) list);\n                break;\n            case BINARY_LIST:\n                checkTypeOfListElements(list, byte[].class);\n                osResults.setByteArrayList(fieldName, (RealmList<byte[]>) list);\n                break;\n            case DATE_LIST:\n                checkTypeOfListElements(list, Date.class);\n                osResults.setDateList(fieldName, (RealmList<Date>) list);\n                break;\n            case DECIMAL128_LIST:\n                checkTypeOfListElements(list, Decimal128.class);\n                osResults.setDecimal128List(fieldName, (RealmList<Decimal128>) list);\n                break;\n            case OBJECT_ID_LIST:\n                checkTypeOfListElements(list, ObjectId.class);\n                osResults.setObjectIdList(fieldName, (RealmList<ObjectId>) list);\n                break;\n            case UUID_LIST:\n                checkTypeOfListElements(list, UUID.class);\n                osResults.setUUIDList(fieldName, (RealmList<UUID>) list);\n                break;\n            case FLOAT_LIST:\n                checkTypeOfListElements(list, Float.class);\n                osResults.setFloatList(fieldName, (RealmList<Float>) list);\n                break;\n            case DOUBLE_LIST:\n                checkTypeOfListElements(list, Double.class);\n                osResults.setDoubleList(fieldName, (RealmList<Double>) list);\n                break;\n            default: {\n//                // Handle Decimal128 and ObjectId in a special way since they might not be on the\n//                // classpath\n//                if (columnType == RealmFieldType.DECIMAL128_LIST) {\n//                    checkTypeOfListElements(list, Decimal128.class);\n//                    osResults.setDecimal128List(fieldName, (RealmList<Decimal128>) list);\n//                } else if (columnType == RealmFieldType.OBJECT_ID_LIST) {\n//                    checkTypeOfListElements(list, ObjectId.class);\n//                    osResults.setObjectIdList(fieldName, (RealmList<ObjectId>) list);\n//                }\n                throw new IllegalArgumentException(String.format(\"Field '%s' is not a list but a %s\", fieldName, columnType));\n            }\n        }\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    @Override\n    public boolean isFrozen() {\n        return baseRealm != null && baseRealm.isFrozen();\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    @Override\n    public RealmResults<E> freeze() {\n        if (!isValid()) {\n            throw new IllegalStateException(\"Only valid, managed RealmResults can be frozen.\");\n        }\n\n        BaseRealm frozenRealm = baseRealm.freeze();\n        OsResults frozenResults = osResults.freeze(frozenRealm.sharedRealm);\n        if (className != null) {\n            return new RealmResults<>(frozenRealm, frozenResults, className);\n        } else {\n            return new RealmResults<>(frozenRealm, frozenResults, classSpec);\n        }\n    }\n\n    private Class<?> getListType(RealmList list) {\n        if (!list.isEmpty()) {\n            return list.first().getClass();\n        } else {\n            return Long.class; // Any valid type that maps to INTEGER will do.\n        }\n    }\n\n    private <T> void checkTypeOfListElements(RealmList<T> list, Class<?> clazz) {\n        if (!list.isEmpty()) {\n            T element = list.first();\n            Class<?> elementType = element.getClass();\n            if (!(clazz.isAssignableFrom(elementType))) {\n                throw new IllegalArgumentException(String.format(\"List contained the wrong type of elements. Elements of type '%s' was \" +\n                        \"expected, but the actual type is '%s'\", clazz, elementType));\n            }\n        }\n    }\n\n    /**\n     * Adds a change listener to this {@link RealmResults}.\n     * <p>\n     * Registering a change listener will not prevent the underlying RealmResults from being garbage collected.\n     * If the RealmResults is garbage collected, the change listener will stop being triggered. To avoid this, keep a\n     * strong reference for as long as appropriate e.g. in a class variable.\n     * <p>\n     * <pre>\n     * {@code\n     * public class MyActivity extends Activity {\n     *\n     *     private RealmResults<Person> results; // Strong reference to keep listeners alive\n     *\n     *     \\@Override\n     *     protected void onCreate(Bundle savedInstanceState) {\n     *       super.onCreate(savedInstanceState);\n     *       results = realm.where(Person.class).findAllAsync();\n     *       results.addChangeListener(new RealmChangeListener<RealmResults<Person>>() {\n     *           \\@Override\n     *           public void onChange(RealmResults<Person> persons) {\n     *               // React to change\n     *           }\n     *       });\n     *     }\n     * }\n     * }\n     * </pre>\n     *\n     * @param listener the change listener to be notified.\n     * @throws IllegalArgumentException if the change listener is {@code null}.\n     * @throws IllegalStateException if you try to add a listener from a non-Looper or\n     * {@link android.app.IntentService} thread.\n     */\n    public void addChangeListener(RealmChangeListener<RealmResults<E>> listener) {\n        checkForAddListener(listener);\n        osResults.addListener(this, listener);\n    }\n\n    /**\n     * Adds a change listener to this {@link RealmResults}.\n     * <p>\n     * Registering a change listener will not prevent the underlying RealmResults from being garbage collected.\n     * If the RealmResults is garbage collected, the change listener will stop being triggered. To avoid this, keep a\n     * strong reference for as long as appropriate e.g. in a class variable.\n     * <p>\n     * <pre>\n     * {@code\n     * public class MyActivity extends Activity {\n     *\n     *     private RealmResults<Person> results; // Strong reference to keep listeners alive\n     *\n     *     \\@Override\n     *     protected void onCreate(Bundle savedInstanceState) {\n     *       super.onCreate(savedInstanceState);\n     *       results = realm.where(Person.class).findAllAsync();\n     *       results.addChangeListener(new OrderedRealmCollectionChangeListener<RealmResults<Person>>() {\n     *           \\@Override\n     *           public void onChange(RealmResults<Person> persons, OrderedCollectionChangeSet changeSet) {\n     *               // React to change\n     *           }\n     *       });\n     *     }\n     * }\n     * }\n     * </pre>\n     *\n     * @param listener the change listener to be notified.\n     * @throws IllegalArgumentException if the change listener is {@code null}.\n     * @throws IllegalStateException if you try to add a listener from a non-Looper or\n     * {@link android.app.IntentService} thread.\n     */\n    public void addChangeListener(OrderedRealmCollectionChangeListener<RealmResults<E>> listener) {\n        checkForAddListener(listener);\n        osResults.addListener(this, listener);\n    }\n\n    private void checkForAddListener(@Nullable Object listener) {\n        if (listener == null) {\n            throw new IllegalArgumentException(\"Listener should not be null\");\n        }\n        baseRealm.checkIfValid();\n        baseRealm.sharedRealm.capabilities.checkCanDeliverNotification(BaseRealm.LISTENER_NOT_ALLOWED_MESSAGE);\n    }\n\n    private void checkForRemoveListener(@Nullable Object listener, boolean checkListener) {\n        if (checkListener && listener == null) {\n            throw new IllegalArgumentException(\"Listener should not be null\");\n        }\n\n        if (baseRealm.isClosed()) {\n            RealmLog.warn(\"Calling removeChangeListener on a closed Realm %s, \" +\n                    \"make sure to close all listeners before closing the Realm.\", baseRealm.configuration.getPath());\n        }\n    }\n\n    /**\n     * Removes all user-defined change listeners.\n     *\n     * @throws IllegalStateException if you try to remove listeners from a non-Looper Thread.\n     * @see io.realm.RealmChangeListener\n     */\n    public void removeAllChangeListeners() {\n        checkForRemoveListener(null, false);\n        osResults.removeAllListeners();\n    }\n\n    /**\n     * Removes the specified change listener.\n     *\n     * @param listener the change listener to be removed.\n     * @throws IllegalArgumentException if the change listener is {@code null}.\n     * @throws IllegalStateException if you try to remove a listener from a non-Looper Thread.\n     * @see io.realm.RealmChangeListener\n     */\n    public void removeChangeListener(RealmChangeListener<RealmResults<E>> listener) {\n        checkForRemoveListener(listener, true);\n        osResults.removeListener(this, listener);\n    }\n\n    /**\n     * Removes the specified change listener.\n     *\n     * @param listener the change listener to be removed.\n     * @throws IllegalArgumentException if the change listener is {@code null}.\n     * @throws IllegalStateException if you try to remove a listener from a non-Looper Thread.\n     * @see io.realm.RealmChangeListener\n     */\n    public void removeChangeListener(OrderedRealmCollectionChangeListener<RealmResults<E>> listener) {\n        checkForRemoveListener(listener, true);\n        osResults.removeListener(this, listener);\n    }\n\n    /**\n     * Returns an Rx Flowable that monitors changes to this RealmResults. It will emit the current RealmResults when\n     * subscribed to. RealmResults will continually be emitted as the RealmResults are updated -\n     * {@code onComplete} will never be called.\n     * <p>\n     * Items emitted from Realm Flowables are frozen (See {@link #freeze()}. This means that they\n     * are immutable and can be read on any thread.\n     * <p>\n     * Realm Flowables always emit items from the thread holding the live RealmResults. This means that if\n     * you need to do further processing, it is recommend to observe the values on a computation\n     * scheduler:\n     * <p>\n     * {@code\n     * realm.where(Foo.class).findAllAsync().asFlowable()\n     *   .observeOn(Schedulers.computation())\n     *   .map(rxResults -> doExpensiveWork(rxResults))\n     *   .observeOn(AndroidSchedulers.mainThread())\n     *   .subscribe( ... );\n     * }\n     * <p>\n     * If you would like the {@code asFlowable()} to stop emitting items you can instruct RxJava to\n     * only emit only the first item by using the {@code first()} operator:\n     * <p>\n     * <pre>\n     * {@code\n     * realm.where(Foo.class).findAllAsync().asFlowable()\n     *      .filter(results -> results.isLoaded())\n     *      .first()\n     *      .subscribe( ... ) // You only get the results once\n     * }\n     * </pre>\n     * <p>\n     *\n     * @return RxJava Observable that only calls {@code onNext}. It will never call {@code onComplete}\n     * or {@code OnError}.\n     * @throws UnsupportedOperationException if the required RxJava framework is not on the classpath or the\n     * corresponding Realm instance doesn't support RxJava.\n     * @throws IllegalStateException if the Realm wasn't opened on a Looper thread.\n     * @see <a href=\"https://github.com/realm/realm-java/tree/master/examples/rxJavaExample\">RxJava and Realm</a>\n     */\n    @SuppressWarnings(\"unchecked\")\n    public Flowable<RealmResults<E>> asFlowable() {\n        if (baseRealm instanceof Realm) {\n            return baseRealm.configuration.getRxFactory().from((Realm) baseRealm, this);\n        }\n\n        if (baseRealm instanceof DynamicRealm) {\n            DynamicRealm dynamicRealm = (DynamicRealm) baseRealm;\n            RealmResults<DynamicRealmObject> dynamicResults = (RealmResults<DynamicRealmObject>) this;\n            @SuppressWarnings(\"UnnecessaryLocalVariable\")\n            Flowable results = baseRealm.configuration.getRxFactory().from(dynamicRealm, dynamicResults);\n            return results;\n        } else {\n            throw new UnsupportedOperationException(baseRealm.getClass() + \" does not support RxJava2.\");\n        }\n    }\n\n    /**\n     * Returns an Rx Observable that monitors changes to this RealmResults. It will emit the current RealmResults when\n     * subscribed. For each update to the RealmResult a pair consisting of the RealmResults and the\n     * {@link OrderedCollectionChangeSet} will be sent. The changeset will be {@code null} the first\n     * time an RealmResults is emitted.\n     * <p>\n     * RealmResults will continually be emitted as the RealmResults are updated - {@code onComplete} will never be called.\n     * <p>\n     * Items emitted from Realm Observables are frozen (See {@link #freeze()}. This means that they\n     * are immutable and can be read on any thread.\n     * <p>\n     * Realm Observables always emit items from the thread holding the live Realm. This means that if\n     * you need to do further processing, it is recommend to observe the values on a computation\n     * scheduler:\n     * <p>\n     * {@code\n     * realm.where(Foo.class).findAllAsync().asChangesetObservable()\n     *   .observeOn(Schedulers.computation())\n     *   .map((rxResults, changes) -> doExpensiveWork(rxResults, changes))\n     *   .observeOn(AndroidSchedulers.mainThread())\n     *   .subscribe( ... );\n     * }\n     *\n     * @return RxJava Observable that only calls {@code onNext}. It will never call {@code onComplete} or {@code OnError}.\n     * @throws UnsupportedOperationException if the required RxJava framework is not on the classpath or the\n     * corresponding Realm instance doesn't support RxJava.\n     * @throws IllegalStateException if the Realm wasn't opened on a Looper thread.\n     * @see <a href=\"https://github.com/realm/realm-java/tree/master/examples/rxJavaExample\">RxJava and Realm</a>\n     */\n    public Observable<CollectionChange<RealmResults<E>>> asChangesetObservable() {\n        if (baseRealm instanceof Realm) {\n            return baseRealm.configuration.getRxFactory().changesetsFrom((Realm) baseRealm, this);\n        } else if (baseRealm instanceof DynamicRealm) {\n            DynamicRealm dynamicRealm = (DynamicRealm) baseRealm;\n            RealmResults<DynamicRealmObject> dynamicResults = (RealmResults<DynamicRealmObject>) this;\n            return (Observable) baseRealm.configuration.getRxFactory().changesetsFrom(dynamicRealm, dynamicResults);\n        } else {\n            throw new UnsupportedOperationException(baseRealm.getClass() + \" does not support RxJava2.\");\n        }\n    }\n\n    /**\n     * Returns a JSON representation of the matches of a {@link RealmQuery}. Cycles will be returned as row indices.\n     *\n     * This is a helper method used to inspect data, or for debugging purpose, this method could pull a large string which\n     * could cause an OutOfMemory error.\n     *\n     * @return string representation of a JSON array containing entries of the resulting {@link RealmQuery}.\n     */\n    public String asJSON() {\n        // maxDepth = -1:\n        // Follow links to infinite depth, but only follow each link exactly once.\n        // Cycle links are printed as a simple sequence of integers of row keys in the link column.\n        return osResults.toJSON(-1);\n    }\n\n    private void checkNonEmptyFieldName(String fieldName) {\n        if (Util.isEmptyString(fieldName)) {\n            throw new IllegalArgumentException(\"Non-empty 'fieldname' required.\");\n        }\n    }\n\n    private void checkNotNull(@Nullable Object value) {\n        if (value == null) {\n            throw new IllegalArgumentException(\"Non-null 'value' required. Use 'setNull(fieldName)' instead.\");\n        }\n    }\n\n    private void checkType(String fieldName, RealmFieldType expectedFieldType) {\n        String className = osResults.getTable().getClassName();\n        RealmFieldType fieldType = baseRealm.getSchema().get(className).getFieldType(fieldName);\n        if (fieldType != expectedFieldType) {\n            throw new IllegalArgumentException(String.format(\"The field '%s.%s' is not of the expected type. \" +\n                    \"Actual: %s, Expected: %s\", className, fieldName, fieldType, expectedFieldType));\n        }\n    }\n\n    private String mapFieldNameToInternalName(String fieldName) {\n        if (baseRealm instanceof Realm) {\n            // We only need to map field names from typed Realms.\n            String className = osResults.getTable().getClassName();\n            String mappedFieldName = baseRealm.getSchema().getColumnInfo(className).getInternalFieldName(fieldName);\n            if (mappedFieldName == null) {\n                throw new IllegalArgumentException(String.format(\"Field '%s' does not exists.\", fieldName));\n            } else {\n                fieldName = mappedFieldName;\n            }\n        }\n        return fieldName;\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/RealmSchema.java",
    "content": "/*\n * Copyright 2015 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\npackage io.realm;\n\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.Set;\n\nimport javax.annotation.Nullable;\n\nimport io.realm.internal.ColumnIndices;\nimport io.realm.internal.ColumnInfo;\nimport io.realm.internal.Table;\nimport io.realm.internal.Util;\nimport io.realm.internal.objectstore.OsKeyPathMapping;\n\n/**\n * Class for interacting with the Realm schema. This makes it possible to inspect, add, delete and change the classes in\n * the Realm.\n * <p>\n * {@link Realm#getSchema()} returns an immutable {@code RealmSchema} which can only be used for inspecting. Use\n * {@link DynamicRealm#getSchema()} to get a mutable schema.\n * <p>\n * All changes must happen inside a write transaction for the particular Realm.\n *\n * @see RealmMigration\n */\npublic abstract class RealmSchema {\n    static final String EMPTY_STRING_MSG = \"Null or empty class names are not allowed\";\n\n    // Caches Dynamic Class objects given as Strings to Realm Tables\n    private final Map<String, Table> dynamicClassToTable = new HashMap<>();\n    // Caches Class objects (both model classes and proxy classes) to Realm Tables\n    private final Map<Class<? extends RealmModel>, Table> classToTable = new HashMap<>();\n    // Caches Class objects (both model classes and proxy classes) to their Schema object\n    private final Map<Class<? extends RealmModel>, RealmObjectSchema> classToSchema = new HashMap<>();\n    // Caches Class Strings to their Schema object\n    private final Map<String, RealmObjectSchema> dynamicClassToSchema = new HashMap<>();\n    // Native pointer\n    private OsKeyPathMapping keyPathMapping = null;\n    final BaseRealm realm;\n    // Cached field look up\n    private final ColumnIndices columnIndices;\n\n    /**\n     * Creates a wrapper to easily manipulate the current schema of a Realm.\n     */\n    RealmSchema(BaseRealm realm, @Nullable ColumnIndices columnIndices) {\n        this.realm = realm;\n        this.columnIndices = columnIndices;\n    }\n\n    /**\n     * Returns the {@link RealmObjectSchema} for a given class. If this {@link RealmSchema} is immutable, an immutable\n     * {@link RealmObjectSchema} will be returned. Otherwise, it returns a mutable {@link RealmObjectSchema}.\n     *\n     * @param className name of the class\n     * @return schema object for that class or {@code null} if the class doesn't exists.\n     */\n    @Nullable\n    public abstract RealmObjectSchema get(String className);\n\n    /**\n     * Returns the {@link RealmObjectSchema}s for all RealmObject classes that can be saved in this Realm. If this\n     * {@link RealmSchema} is immutable, an immutable {@link RealmObjectSchema} set will be returned. Otherwise, it\n     * returns an mutable {@link RealmObjectSchema} set.\n     *\n     * @return the set of all classes in this Realm or no RealmObject classes can be saved in the Realm.\n     */\n    public abstract Set<RealmObjectSchema> getAll();\n\n    /**\n     * Adds a new class to the Realm.\n     *\n     * @param className name of the class.\n     * @return a Realm schema object for that class.\n     * @throws UnsupportedOperationException if this {@link RealmSchema} is immutable.\n     */\n    public abstract RealmObjectSchema create(String className);\n\n    /**\n     * Adds a new class to the Realm with a primary key field defined.\n     *\n     * @param className           name of the class.\n     * @param primaryKeyFieldName name of the primary key field.\n     * @param fieldType           type of field to add. Only {@code byte}, {@code short}, {@code int}, {@code long}\n     *                            and their boxed types or the {@code String} is supported.\n     * @param attributes          set of attributes for this field. This method implicitly adds\n     *                            {@link FieldAttribute#PRIMARY_KEY} and {@link FieldAttribute#INDEXED} attributes to\n     *                            the field.\n     * @throws UnsupportedOperationException if this {@link RealmSchema} is immutable.\n     * @return a Realm schema object for that class.\n     */\n    public abstract RealmObjectSchema createWithPrimaryKeyField(String className, String primaryKeyFieldName, Class<?> fieldType,\n                                                       FieldAttribute... attributes);\n\n    /**\n     * Removes a class from the Realm. All data will be removed. Removing a class while other classes point\n     * to it will throw an {@link IllegalStateException}. Removes those classes or fields first.\n     *\n     * @param className name of the class to remove.\n     * @throws UnsupportedOperationException if this {@link RealmSchema} is immutable or of a synced Realm.\n     */\n    public abstract void remove(String className);\n\n    /**\n     * Renames a class already in the Realm.\n     *\n     * @param oldClassName old class name.\n     * @param newClassName new class name.\n     * @return a schema object for renamed class.\n     * @throws UnsupportedOperationException if this {@link RealmSchema} is immutable or of a synced Realm.\n     */\n    public abstract RealmObjectSchema rename(String oldClassName, String newClassName);\n\n    /**\n     * Checks if a given class already exists in the schema.\n     *\n     * @param className class name to check.\n     * @return {@code true} if the class already exists. {@code false} otherwise.\n     */\n    public boolean contains(String className) {\n        return realm.getSharedRealm().hasTable(Table.getTableNameForClass(className));\n    }\n\n    void checkNotEmpty(String str, String error) {\n        //noinspection ConstantConditions\n        if (str == null || str.isEmpty()) {\n            throw new IllegalArgumentException(error);\n        }\n    }\n\n    void checkHasTable(String className, String errorMsg) {\n        String internalTableName = Table.getTableNameForClass(className);\n        if (!realm.getSharedRealm().hasTable(internalTableName)) {\n            throw new IllegalArgumentException(errorMsg);\n        }\n    }\n\n    Table getTable(String className) {\n        String tableName = Table.getTableNameForClass(className);\n        Table table = dynamicClassToTable.get(tableName);\n        if (table != null) { return table; }\n\n        table = realm.getSharedRealm().getTable(tableName);\n        dynamicClassToTable.put(tableName, table);\n\n        return table;\n    }\n\n    Table getTable(Class<? extends RealmModel> clazz) {\n        Table table = classToTable.get(clazz);\n        if (table != null) { return table; }\n\n        Class<? extends RealmModel> originalClass = Util.getOriginalModelClass(clazz);\n        if (isProxyClass(originalClass, clazz)) {\n            // If passed 'clazz' is the proxy, try again with model class.\n            table = classToTable.get(originalClass);\n        }\n        if (table == null) {\n            String tableName = Table.getTableNameForClass(\n                    realm.getConfiguration().getSchemaMediator().getSimpleClassName(originalClass));\n            table = realm.getSharedRealm().getTable(tableName);\n            classToTable.put(originalClass, table);\n        }\n        if (isProxyClass(originalClass, clazz)) {\n            // 'clazz' is the proxy class for 'originalClass'.\n            classToTable.put(clazz, table);\n        }\n\n        return table;\n    }\n\n    // Returns an immutable RealmObjectSchema for internal usage only.\n    RealmObjectSchema getSchemaForClass(Class<? extends RealmModel> clazz) {\n        RealmObjectSchema classSchema = classToSchema.get(clazz);\n        if (classSchema != null) { return classSchema; }\n\n        Class<? extends RealmModel> originalClass = Util.getOriginalModelClass(clazz);\n        if (isProxyClass(originalClass, clazz)) {\n            // If passed 'clazz' is the proxy, try again with model class.\n            classSchema = classToSchema.get(originalClass);\n        }\n        if (classSchema == null) {\n            Table table = getTable(clazz);\n            classSchema = new ImmutableRealmObjectSchema(realm, this, table, getColumnInfo(originalClass));\n            classToSchema.put(originalClass, classSchema);\n        }\n        if (isProxyClass(originalClass, clazz)) {\n            // 'clazz' is the proxy class for 'originalClass'.\n            classToSchema.put(clazz, classSchema);\n        }\n\n        return classSchema;\n    }\n\n    // Returns an immutable RealmObjectSchema for internal usage only.\n    RealmObjectSchema getSchemaForClass(String className) {\n        String tableName = Table.getTableNameForClass(className);\n        RealmObjectSchema dynamicSchema = dynamicClassToSchema.get(tableName);\n        if (dynamicSchema == null || !dynamicSchema.getTable().isValid() || !dynamicSchema.getClassName().equals(className)) {\n            if (!realm.getSharedRealm().hasTable(tableName)) {\n                throw new IllegalArgumentException(\"The class \" + className + \" doesn't exist in this Realm.\");\n            }\n            dynamicSchema = new ImmutableRealmObjectSchema(realm, this, realm.getSharedRealm().getTable(tableName));\n            dynamicClassToSchema.put(tableName, dynamicSchema);\n        }\n        return dynamicSchema;\n    }\n\n    private boolean isProxyClass(Class<? extends RealmModel> modelClass, Class<? extends RealmModel> testee) {\n        return modelClass.equals(testee);\n    }\n\n    final boolean haveColumnInfo() {\n        return columnIndices != null;\n    }\n\n    final ColumnInfo getColumnInfo(Class<? extends RealmModel> clazz) {\n        checkColumnKeys();\n        return columnIndices.getColumnInfo(clazz);\n    }\n\n    protected final ColumnInfo getColumnInfo(String className) {\n        checkColumnKeys();\n        return columnIndices.getColumnInfo(className);\n    }\n\n    final void putToClassNameToSchemaMap(String name, RealmObjectSchema objectSchema) {\n        dynamicClassToSchema.put(name, objectSchema);\n    }\n\n    final RealmObjectSchema removeFromClassNameToSchemaMap(String name) {\n        return dynamicClassToSchema.remove(name);\n    }\n\n    final OsKeyPathMapping getKeyPathMapping() {\n        return keyPathMapping;\n    }\n\n    private void checkColumnKeys() {\n        if (!haveColumnInfo()) {\n            throw new IllegalStateException(\"Attempt to use column key before set.\");\n        }\n    }\n\n    /**\n     * Create the underlying keypath mapping. Should only be called by typed Realms.\n     */\n    public void createKeyPathMapping() {\n        this.keyPathMapping = new OsKeyPathMapping(realm.sharedRealm.getNativePtr());\n    }\n\n    /**\n     * Called when schema changed. Clear all cached tables and refresh column indices.\n     */\n    void refresh() {\n        if (columnIndices != null) {\n            columnIndices.refresh();\n        }\n        dynamicClassToTable.clear();\n        classToTable.clear();\n        classToSchema.clear();\n        dynamicClassToSchema.clear();\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/RealmSet.java",
    "content": "/*\n * Copyright 2021 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\npackage io.realm;\n\nimport org.bson.types.Decimal128;\nimport org.bson.types.ObjectId;\nimport org.json.JSONArray;\nimport org.json.JSONObject;\n\nimport java.io.InputStream;\nimport java.lang.reflect.Array;\nimport java.util.Collection;\nimport java.util.Date;\nimport java.util.HashSet;\nimport java.util.Iterator;\nimport java.util.Set;\nimport java.util.UUID;\n\nimport javax.annotation.Nullable;\n\nimport io.realm.internal.ManageableObject;\nimport io.realm.internal.OsSet;\n\n/**\n * RealmSet is a collection that contains no duplicate elements.\n * <p>\n * Similarly to {@link RealmList}s, a RealmSet can operate in managed and unmanaged modes. In\n * managed mode a RealmSet persists all its contents inside a Realm whereas in unmanaged mode\n * it functions like a {@link HashSet}.\n * <p>\n * Managed RealmSets can only be created by Realm and will automatically update their content\n * whenever the underlying Realm is updated. Managed RealmSet can only be accessed using the getter\n * that points to a RealmSet field of a {@link RealmObject}.\n * <p>\n * Unmanaged elements in this set can be added to a Realm using the\n * {@link Realm#copyToRealm(Iterable, ImportFlag...)} method.\n * <p>\n * <b>Warning: </b> the following methods are not supported for classes containing set fields yet:\n * <ul>\n * <li>{@link Realm#insert(RealmModel)}</li>\n * <li>{@link Realm#insert(Collection)}</li>\n * <li>{@link Realm#insertOrUpdate(RealmModel)}</li>\n * <li>{@link Realm#insertOrUpdate(Collection)}</li>\n * <li>{@link Realm#createAllFromJson(Class, String)}</li>\n * <li>{@link Realm#createAllFromJson(Class, JSONArray)}</li>\n * <li>{@link Realm#createAllFromJson(Class, InputStream)}</li>\n * <li>{@link Realm#createObjectFromJson(Class, String)}</li>\n * <li>{@link Realm#createObjectFromJson(Class, JSONObject)}}</li>\n * <li>{@link Realm#createObjectFromJson(Class, InputStream)}}</li>\n * <li>{@link Realm#createOrUpdateAllFromJson(Class, String)}</li>\n * <li>{@link Realm#createOrUpdateAllFromJson(Class, JSONArray)}</li>\n * <li>{@link Realm#createOrUpdateAllFromJson(Class, InputStream)}</li>\n * <li>{@link Realm#createOrUpdateObjectFromJson(Class, String)}</li>\n * <li>{@link Realm#createOrUpdateObjectFromJson(Class, JSONObject)}</li>\n * <li>{@link Realm#createOrUpdateObjectFromJson(Class, InputStream)}</li>\n * </ul>\n *\n * @param <E> the type of the values stored in this set\n */\npublic class RealmSet<E> implements Set<E>, ManageableObject, RealmCollection<E> {\n\n    protected final SetStrategy<E> setStrategy;\n\n    // ------------------------------------------\n    // Unmanaged constructors\n    // ------------------------------------------\n\n    /**\n     * Instantiates a RealmSet in unmanaged mode.\n     */\n    public RealmSet() {\n        this.setStrategy = new UnmanagedSetStrategy<>();\n    }\n\n    /**\n     * Instantiates a RealmSet in unmanaged mode with another collection.\n     *\n     * @param collection the collection with which the set will be initially populated.\n     */\n    public RealmSet(Collection<E> collection) {\n        this.setStrategy = new UnmanagedSetStrategy<>(collection);\n    }\n\n    // ------------------------------------------\n    // Managed constructors\n    // ------------------------------------------\n\n    /**\n     * Instantiates a RealmSet in managed mode. This constructor is used internally by Realm.\n     *\n     * @param baseRealm\n     * @param osSet\n     * @param valueClass\n     */\n    public RealmSet(BaseRealm baseRealm, OsSet osSet, Class<E> valueClass) {\n        this.setStrategy = getStrategy(baseRealm, osSet, valueClass);\n    }\n\n    /**\n     * Instantiates a RealmSet in managed mode. This constructor is used internally by a Dynamic Realm.\n     *\n     * @param baseRealm\n     * @param osSet\n     * @param className\n     */\n    public RealmSet(BaseRealm baseRealm, OsSet osSet, String className) {\n        this.setStrategy = getStrategy(baseRealm, osSet, className);\n    }\n\n    // ------------------------------------------\n    // ManageableObject API\n    // ------------------------------------------\n\n    /**\n     * {@inheritDoc}\n     */\n    @Override\n    public boolean isManaged() {\n        return setStrategy.isManaged();\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    @Override\n    public boolean isValid() {\n        return setStrategy.isValid();\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    @Override\n    public boolean isFrozen() {\n        return setStrategy.isFrozen();\n    }\n\n    // ------------------------------------------\n    // Set API\n    // ------------------------------------------\n\n    /**\n     * {@inheritDoc}\n     */\n    @Override\n    public int size() {\n        return setStrategy.size();\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    @Override\n    public boolean isEmpty() {\n        return setStrategy.isEmpty();\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    @Override\n    public boolean contains(@Nullable Object o) {\n        return setStrategy.contains(o);\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    @Override\n    public Iterator<E> iterator() {\n        return setStrategy.iterator();\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    @Override\n    public Object[] toArray() {\n        return setStrategy.toArray();\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    @Override\n    public <T> T[] toArray(T[] a) {\n        return setStrategy.toArray(a);\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    @Override\n    public boolean add(@Nullable E e) {\n        return setStrategy.add(e);\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    @Override\n    public boolean remove(@Nullable Object o) {\n        return setStrategy.remove(o);\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    @Override\n    public boolean containsAll(Collection<?> c) {\n        return setStrategy.containsAll(c);\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    @Override\n    public boolean addAll(Collection<? extends E> c) {\n        return setStrategy.addAll(c);\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    @Override\n    public boolean retainAll(Collection<?> c) {\n        return setStrategy.retainAll(c);\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    @Override\n    public boolean removeAll(Collection<?> c) {\n        return setStrategy.removeAll(c);\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    @Override\n    public void clear() {\n        setStrategy.clear();\n    }\n\n    // ------------------------------------------\n    // Freezable API\n    // ------------------------------------------\n\n    /**\n     * {@inheritDoc}\n     */\n    @Override\n    public RealmSet<E> freeze() {\n        return setStrategy.freeze();\n    }\n\n    // ------------------------------------------\n    // RealmSet API\n    // ------------------------------------------\n\n    /**\n     * Adds a change listener to this {@link RealmSet}.\n     * <p>\n     * Registering a change listener will not prevent the underlying RealmSet from being garbage\n     * collected. If the RealmSet is garbage collected, the change listener will stop being\n     * triggered. To avoid this, keep a strong reference for as long as appropriate e.g. in a class\n     * variable.\n     * <p>\n     * <pre>\n     * {@code\n     * public class MyActivity extends Activity {\n     *\n     *     private RealmSet<Dog> dogs; // Strong reference to keep listeners alive\n     *\n     *     \\@Override\n     *     protected void onCreate(Bundle savedInstanceState) {\n     *       super.onCreate(savedInstanceState);\n     *       dogs = realm.where(Person.class).findFirst().getDogs();\n     *       dogs.addChangeListener(new RealmChangeListener<RealmSet<Dog>>() {\n     *           \\@Override\n     *           public void onChange(RealmSet<Dog> map) {\n     *               // React to change\n     *           }\n     *       });\n     *     }\n     * }\n     * }\n     * </pre>\n     *\n     * @param listener the listener to be notified.\n     * @throws IllegalArgumentException if the change listener is {@code null}.\n     * @throws IllegalStateException    if you try to add a listener from a non-Looper or\n     *                                  {@link android.app.IntentService} thread.\n     */\n    public void addChangeListener(RealmChangeListener<RealmSet<E>> listener) {\n        setStrategy.addChangeListener(this, listener);\n    }\n\n    /**\n     * Adds a change listener to this {@link RealmSet}.\n     * <p>\n     * Registering a change listener will not prevent the underlying RealmSet from being garbage\n     * collected. If the RealmSet is garbage collected, the change listener will stop being\n     * triggered. To avoid this, keep a strong reference for as long as appropriate e.g. in a class\n     * variable.\n     * <p>\n     * <pre>\n     * {@code\n     * public class MyActivity extends Activity {\n     *\n     *     private RealmSet<Dog> dogs; // Strong reference to keep listeners alive\n     *\n     *     \\@Override\n     *     protected void onCreate(Bundle savedInstanceState) {\n     *       super.onCreate(savedInstanceState);\n     *       dogs = realm.where(Person.class).findFirst().getDogs();\n     *       dogs.addChangeListener(new SetChangeListener<Dog>() {\n     *           \\@Override\n     *           public void onChange(RealmSet<Dog> set, SetChangeSet changeSet) {\n     *               // React to change\n     *           }\n     *       });\n     *     }\n     * }\n     * }\n     * </pre>\n     *\n     * @param listener the listener to be notified.\n     * @throws IllegalArgumentException if the change listener is {@code null}.\n     * @throws IllegalStateException    if you try to add a listener from a non-Looper or\n     *                                  {@link android.app.IntentService} thread.\n     */\n    public void addChangeListener(SetChangeListener<E> listener) {\n        setStrategy.addChangeListener(this, listener);\n    }\n\n    /**\n     * Removes the specified change listener.\n     *\n     * @param listener the change listener to be removed.\n     * @throws IllegalArgumentException if the change listener is {@code null}.\n     * @throws IllegalStateException    if you try to remove a listener from a non-Looper Thread.\n     */\n    public void removeChangeListener(RealmChangeListener<RealmSet<E>> listener) {\n        setStrategy.removeChangeListener(this, listener);\n    }\n\n    /**\n     * Removes the specified change listener.\n     *\n     * @param listener the change listener to be removed.\n     * @throws IllegalArgumentException if the change listener is {@code null}.\n     * @throws IllegalStateException    if you try to remove a listener from a non-Looper Thread.\n     */\n    public void removeChangeListener(SetChangeListener<E> listener) {\n        setStrategy.removeChangeListener(this, listener);\n    }\n\n    /**\n     * Removes all user-defined change listeners.\n     *\n     * @throws IllegalStateException if you try to remove listeners from a non-Looper Thread.\n     * @see io.realm.RealmChangeListener\n     */\n    public void removeAllChangeListeners() {\n        setStrategy.removeAllChangeListeners();\n    }\n\n    // ------------------------------------------\n    // RealmCollection API\n    // ------------------------------------------\n\n    /**\n     * Returns a RealmQuery, which can be used to query for specific objects of this class.\n     *\n     * @return a RealmQuery object.\n     * @throws IllegalStateException if Realm instance has been closed or parent object has been removed.\n     * @see io.realm.RealmQuery\n     */\n    @Override\n    public RealmQuery<E> where() {\n        return setStrategy.where();\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    @Nullable\n    @Override\n    public Number min(String fieldName) {\n        return setStrategy.min(fieldName);\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    @Nullable\n    @Override\n    public Number max(String fieldName) {\n        return setStrategy.max(fieldName);\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    @Override\n    public Number sum(String fieldName) {\n        return setStrategy.sum(fieldName);\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    @Override\n    public double average(String fieldName) {\n        return setStrategy.average(fieldName);\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    @Nullable\n    @Override\n    public Date maxDate(String fieldName) {\n        return setStrategy.maxDate(fieldName);\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    @Nullable\n    @Override\n    public Date minDate(String fieldName) {\n        return setStrategy.minDate(fieldName);\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    @Override\n    public boolean deleteAllFromRealm() {\n        return setStrategy.deleteAllFromRealm();\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    @Override\n    public boolean isLoaded() {\n        return true;\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    @Override\n    public boolean load() {\n        return true;\n    }\n\n    // ------------------------------------------\n    // Private stuff\n    // ------------------------------------------\n\n    OsSet getOsSet() {\n        return setStrategy.getOsSet();\n    }\n\n    boolean hasListeners() {\n        return setStrategy.hasListeners();\n    }\n\n    @SuppressWarnings(\"unchecked\")\n    private static <T> ManagedSetStrategy<T> getStrategy(BaseRealm baseRealm,\n                                                         OsSet osSet,\n                                                         Class<T> valueClass) {\n        if (CollectionUtils.isClassForRealmModel(valueClass)) {\n            Class<? extends RealmModel> typeCastClass = (Class<? extends RealmModel>) valueClass;\n            return new ManagedSetStrategy<>((SetValueOperator<T>) new RealmModelSetOperator<>(baseRealm, osSet, typeCastClass), valueClass);\n        }\n\n        SetValueOperator<T> operator;\n        if (valueClass == Boolean.class) {\n            operator = (SetValueOperator<T>) new BooleanOperator(baseRealm, osSet, Boolean.class);\n        } else if (valueClass == String.class) {\n            operator = (SetValueOperator<T>) new StringOperator(baseRealm, osSet, String.class);\n        } else if (valueClass == Integer.class) {\n            operator = (SetValueOperator<T>) new IntegerOperator(baseRealm, osSet, Integer.class);\n        } else if (valueClass == Long.class) {\n            operator = (SetValueOperator<T>) new LongOperator(baseRealm, osSet, Long.class);\n        } else if (valueClass == Short.class) {\n            operator = (SetValueOperator<T>) new ShortOperator(baseRealm, osSet, Short.class);\n        } else if (valueClass == Byte.class) {\n            operator = (SetValueOperator<T>) new ByteOperator(baseRealm, osSet, Byte.class);\n        } else if (valueClass == Float.class) {\n            operator = (SetValueOperator<T>) new FloatOperator(baseRealm, osSet, Float.class);\n        } else if (valueClass == Double.class) {\n            operator = (SetValueOperator<T>) new DoubleOperator(baseRealm, osSet, Double.class);\n        } else if (valueClass == byte[].class) {\n            operator = (SetValueOperator<T>) new BinaryOperator(baseRealm, osSet, byte[].class);\n        } else if (valueClass == Date.class) {\n            operator = (SetValueOperator<T>) new DateOperator(baseRealm, osSet, Date.class);\n        } else if (valueClass == Decimal128.class) {\n            operator = (SetValueOperator<T>) new Decimal128Operator(baseRealm, osSet, Decimal128.class);\n        } else if (valueClass == ObjectId.class) {\n            operator = (SetValueOperator<T>) new ObjectIdOperator(baseRealm, osSet, ObjectId.class);\n        } else if (valueClass == UUID.class) {\n            operator = (SetValueOperator<T>) new UUIDOperator(baseRealm, osSet, UUID.class);\n        } else if (valueClass == RealmAny.class) {\n            operator = (SetValueOperator<T>) new RealmAnySetOperator(baseRealm, osSet, RealmAny.class);\n        } else if (valueClass == Number.class) {\n            operator = (SetValueOperator<T>) new NumberOperator(baseRealm, osSet, Number.class);\n        } else {\n            throw new UnsupportedOperationException(\"getStrategy: missing class '\" + valueClass.getSimpleName() + \"'\");\n        }\n\n        return new ManagedSetStrategy<>(operator, valueClass);\n    }\n\n    @SuppressWarnings(\"unchecked\")\n    private static <T> ManagedSetStrategy<T> getStrategy(BaseRealm baseRealm,\n            OsSet osSet,\n            String className) {\n        SetValueOperator<T> operator;\n\n        if (className.equals(Boolean.class.getCanonicalName())) {\n            operator = (SetValueOperator<T>) new BooleanOperator(baseRealm, osSet, Boolean.class);\n        } else if (className.equals(String.class.getCanonicalName())) {\n            operator = (SetValueOperator<T>) new StringOperator(baseRealm, osSet, String.class);\n        } else if (className.equals(Integer.class.getCanonicalName())) {\n            operator = (SetValueOperator<T>) new IntegerOperator(baseRealm, osSet, Integer.class);\n        } else if (className.equals(Long.class.getCanonicalName())) {\n            operator = (SetValueOperator<T>) new LongOperator(baseRealm, osSet, Long.class);\n        } else if (className.equals(Short.class.getCanonicalName())) {\n            operator = (SetValueOperator<T>) new ShortOperator(baseRealm, osSet, Short.class);\n        } else if (className.equals(Byte.class.getCanonicalName())) {\n            operator = (SetValueOperator<T>) new ByteOperator(baseRealm, osSet, Byte.class);\n        } else if (className.equals(Float.class.getCanonicalName())) {\n            operator = (SetValueOperator<T>) new FloatOperator(baseRealm, osSet, Float.class);\n        } else if (className.equals(Double.class.getCanonicalName())) {\n            operator = (SetValueOperator<T>) new DoubleOperator(baseRealm, osSet, Double.class);\n        } else if (className.equals(byte[].class.getCanonicalName())) {\n            operator = (SetValueOperator<T>) new BinaryOperator(baseRealm, osSet, byte[].class);\n        } else if (className.equals(Date.class.getCanonicalName())) {\n            operator = (SetValueOperator<T>) new DateOperator(baseRealm, osSet, Date.class);\n        } else if (className.equals(Decimal128.class.getCanonicalName())) {\n            operator = (SetValueOperator<T>) new Decimal128Operator(baseRealm, osSet, Decimal128.class);\n        } else if (className.equals(ObjectId.class.getCanonicalName())) {\n            operator = (SetValueOperator<T>) new ObjectIdOperator(baseRealm, osSet, ObjectId.class);\n        } else if (className.equals(UUID.class.getCanonicalName())) {\n            operator = (SetValueOperator<T>) new UUIDOperator(baseRealm, osSet, UUID.class);\n        } else if (className.equals(RealmAny.class.getCanonicalName())) {\n            operator = (SetValueOperator<T>) new RealmAnySetOperator(baseRealm, osSet, RealmAny.class);\n        } else {\n            operator = (SetValueOperator<T>) new DynamicSetOperator(baseRealm, osSet, className);\n        }\n\n        return new ManagedSetStrategy<>(operator, operator.getValueClass());\n    }\n\n    public String getValueClassName() {\n        return setStrategy.getValueClassName();\n    }\n\n    public Class<E> getValueClass() {\n        return setStrategy.getValueClass();\n    }\n\n    /**\n     * Strategy responsible for abstracting the managed/unmanaged logic for sets.\n     *\n     * @param <E> the type of the values stored in this set\n     */\n    private abstract static class SetStrategy<E> implements Set<E>, ManageableObject, RealmCollection<E> {\n        abstract OsSet getOsSet();\n\n        abstract void addChangeListener(RealmSet<E> set, RealmChangeListener<RealmSet<E>> listener);\n\n        abstract void addChangeListener(RealmSet<E> set, SetChangeListener<E> listener);\n\n        abstract void removeChangeListener(RealmSet<E> set, RealmChangeListener<RealmSet<E>> listener);\n\n        abstract void removeChangeListener(RealmSet<E> set, SetChangeListener<E> listener);\n\n        abstract void removeAllChangeListeners();\n\n        abstract boolean hasListeners();\n\n        @Override\n        public abstract RealmSet<E> freeze();\n\n        abstract String getValueClassName();\n\n        abstract Class<E> getValueClass();\n    }\n\n    /**\n     * Concrete {@link RealmSet.SetStrategy} that works for managed {@link io.realm.RealmSet}s.\n     *\n     * @param <E> the value type\n     */\n    private static class ManagedSetStrategy<E> extends SetStrategy<E> {\n\n        private final SetValueOperator<E> setValueOperator;\n        private Class<E> valueClass;\n\n        ManagedSetStrategy(SetValueOperator<E> setValueOperator, Class<E> valueClass) {\n            this.setValueOperator = setValueOperator;\n            this.valueClass = valueClass;\n        }\n\n        // ------------------------------------------\n        // ManageableObject API\n        // ------------------------------------------\n\n        @Override\n        public boolean isManaged() {\n            return true;\n        }\n\n        // ------------------------------------------\n        // RealmCollection API\n        // ------------------------------------------\n\n        @Override\n        public RealmQuery<E> where() {\n            return setValueOperator.where();\n        }\n\n        @Nullable\n        @Override\n        public Number min(String fieldName) {\n            return where().min(fieldName);\n        }\n\n        @Nullable\n        @Override\n        public Number max(String fieldName) {\n            return where().max(fieldName);\n        }\n\n        @Override\n        public Number sum(String fieldName) {\n            return where().sum(fieldName);\n        }\n\n        @Override\n        public double average(String fieldName) {\n            return where().average(fieldName);\n        }\n\n        @Nullable\n        @Override\n        public Date maxDate(String fieldName) {\n            return where().maximumDate(fieldName);\n        }\n\n        @Nullable\n        @Override\n        public Date minDate(String fieldName) {\n            return where().minimumDate(fieldName);\n        }\n\n        @Override\n        public boolean deleteAllFromRealm() {\n            setValueOperator.baseRealm.checkIfValid();\n            if (!setValueOperator.isEmpty()) {\n                setValueOperator.deleteAll();\n                return true;\n            } else {\n                return false;\n            }\n        }\n\n        @Override\n        public boolean isLoaded() {\n            return true;\n        }\n\n        @Override\n        public boolean load() {\n            return true;\n        }\n\n        @Override\n        public boolean isValid() {\n            return setValueOperator.isValid();\n        }\n\n        @Override\n        public boolean isFrozen() {\n            return setValueOperator.isFrozen();\n        }\n\n        // ------------------------------------------\n        // Set API\n        // ------------------------------------------\n\n        @Override\n        public int size() {\n            return setValueOperator.size();\n        }\n\n        @Override\n        public boolean isEmpty() {\n            return setValueOperator.isEmpty();\n        }\n\n        @Override\n        public boolean contains(@Nullable Object o) {\n            return setValueOperator.contains(o);\n        }\n\n        @Override\n        public Iterator<E> iterator() {\n            return setValueOperator.iterator();\n        }\n\n        @Override\n        public Object[] toArray() {\n            Object[] array = new Object[size()];\n            int i = 0;\n            for (E value : this) {\n                array[i] = value;\n                i++;\n            }\n            return array;\n        }\n\n        @SuppressWarnings(\"unchecked\")\n        @Override\n        public <T> T[] toArray(T[] a) {\n            checkValidArray(a);\n\n            T[] array;\n            long setSize = size();\n\n            // From docs:\n            // If the set fits in the specified array, it is returned therein.\n            // Otherwise, a new array is allocated with the runtime type of the\n            // specified array and the size of this set.\n            if (a.length == setSize || a.length > setSize) {\n                array = a;\n            } else {\n                array = (T[]) Array.newInstance(valueClass, (int) setSize);\n            }\n\n            int i = 0;\n            for (E value : this) {\n                if (value == null) {\n                    array[i] = null;\n                } else {\n                    array[i] = (T) value;\n                }\n                i++;\n            }\n\n            // From docs:\n            // If this set fits in the specified array with room to spare\n            // (i.e., the array has more elements than this set), the element in\n            // the array immediately following the end of the set is set to null.\n            if (a.length > setSize) {\n                array[i] = null;\n            }\n\n            return array;\n        }\n\n        @Override\n        public boolean add(@Nullable E e) {\n            return setValueOperator.add(e);\n        }\n\n        @Override\n        public boolean remove(@Nullable Object o) {\n            return setValueOperator.remove(o);\n        }\n\n        @Override\n        public boolean containsAll(Collection<?> c) {\n            checkValidCollection(c);\n            return setValueOperator.containsAll(c);\n        }\n\n        @Override\n        public boolean addAll(Collection<? extends E> c) {\n            checkValidCollection(c);\n            return setValueOperator.addAll(c);\n        }\n\n        @Override\n        public boolean retainAll(Collection<?> c) {\n            checkValidCollection(c);\n            return setValueOperator.retainAll(c);\n        }\n\n        @Override\n        public boolean removeAll(Collection<?> c) {\n            checkValidCollection(c);\n            return setValueOperator.removeAll(c);\n        }\n\n        @Override\n        public void clear() {\n            setValueOperator.clear();\n        }\n\n        // ------------------------------------------\n        // Freezable API\n        // ------------------------------------------\n\n        @Override\n        public RealmSet<E> freeze() {\n            return setValueOperator.freeze();\n        }\n\n        @Override\n        OsSet getOsSet() {\n            return setValueOperator.getOsSet();\n        }\n\n        // ------------------------------------------\n        // RealmSet API\n        // ------------------------------------------\n\n        @Override\n        void addChangeListener(RealmSet<E> set, RealmChangeListener<RealmSet<E>> listener) {\n            setValueOperator.addChangeListener(set, listener);\n        }\n\n        @Override\n        void addChangeListener(RealmSet<E> set, SetChangeListener<E> listener) {\n            setValueOperator.addChangeListener(set, listener);\n        }\n\n        @Override\n        void removeChangeListener(RealmSet<E> set, RealmChangeListener<RealmSet<E>> listener) {\n            setValueOperator.removeChangeListener(set, listener);\n        }\n\n        @Override\n        void removeChangeListener(RealmSet<E> set, SetChangeListener<E> listener) {\n            setValueOperator.removeChangeListener(set, listener);\n        }\n\n        @Override\n        void removeAllChangeListeners() {\n            setValueOperator.removeAllChangeListeners();\n        }\n\n        @Override\n        boolean hasListeners() {\n            return setValueOperator.hasListeners();\n        }\n\n        // ------------------------------------------\n        // Private stuff\n        // ------------------------------------------\n\n        private <T> void checkValidArray(T[] array) {\n            if (array == null) {\n                // According to Java Set documentation\n                throw new NullPointerException(\"Cannot pass a null array when calling 'toArray'.\");\n            }\n\n            String valueClassSimpleName = valueClass.getSimpleName();\n            String arrayTypeSimpleName = array.getClass().getComponentType().getSimpleName();\n\n            // According to Java Set documentation\n            if (!valueClassSimpleName.equals(arrayTypeSimpleName)) {\n                throw new ArrayStoreException(\"Array type must be of type '\" + valueClassSimpleName +\n                        \"' but it was of type '\" + arrayTypeSimpleName + \"'.\");\n            }\n        }\n\n        private void checkValidCollection(Collection<?> collection) {\n            if (collection == null) {\n                throw new NullPointerException(\"Collection must not be null.\");\n            }\n        }\n\n        @Override\n        public String getValueClassName() {\n            return setValueOperator.getValueClassName();\n        }\n\n        @Override\n        public Class<E> getValueClass() {\n            return setValueOperator.getValueClass();\n        }\n    }\n\n    /**\n     * Concrete {@link RealmSet.SetStrategy} that works for unmanaged {@link io.realm.RealmSet}s.\n     *\n     * @param <E> the value type\n     */\n    private static class UnmanagedSetStrategy<E> extends SetStrategy<E> {\n\n        private static final String ONLY_IN_MANAGED_MODE_MESSAGE = \"This method is only available in managed mode.\";\n\n        private final Set<E> unmanagedSet;\n\n        UnmanagedSetStrategy() {\n            unmanagedSet = new HashSet<>();\n        }\n\n        UnmanagedSetStrategy(Collection<E> collection) {\n            this();\n            unmanagedSet.addAll(collection);\n        }\n\n        // ------------------------------------------\n        // ManageableObject API\n        // ------------------------------------------\n\n        @Override\n        public boolean isManaged() {\n            return false;\n        }\n\n        @Override\n        public boolean isValid() {\n            return true;\n        }\n\n        @Override\n        public boolean isFrozen() {\n            return false;\n        }\n\n        // ------------------------------------------\n        // ManageableObject API\n        // ------------------------------------------\n\n        @Override\n        public RealmQuery<E> where() {\n            throw new UnsupportedOperationException(ONLY_IN_MANAGED_MODE_MESSAGE);\n        }\n\n        @Nullable\n        @Override\n        public Number min(String fieldName) {\n            throw new UnsupportedOperationException(ONLY_IN_MANAGED_MODE_MESSAGE);\n        }\n\n        @Nullable\n        @Override\n        public Number max(String fieldName) {\n            throw new UnsupportedOperationException(ONLY_IN_MANAGED_MODE_MESSAGE);\n        }\n\n        @Override\n        public Number sum(String fieldName) {\n            throw new UnsupportedOperationException(ONLY_IN_MANAGED_MODE_MESSAGE);\n        }\n\n        @Override\n        public double average(String fieldName) {\n            throw new UnsupportedOperationException(ONLY_IN_MANAGED_MODE_MESSAGE);\n        }\n\n        @Nullable\n        @Override\n        public Date maxDate(String fieldName) {\n            throw new UnsupportedOperationException(ONLY_IN_MANAGED_MODE_MESSAGE);\n        }\n\n        @Nullable\n        @Override\n        public Date minDate(String fieldName) {\n            throw new UnsupportedOperationException(ONLY_IN_MANAGED_MODE_MESSAGE);\n        }\n\n        @Override\n        public boolean deleteAllFromRealm() {\n            throw new UnsupportedOperationException(ONLY_IN_MANAGED_MODE_MESSAGE);\n        }\n\n        @Override\n        public boolean isLoaded() {\n            return true;\n        }\n\n        @Override\n        public boolean load() {\n            return true;\n        }\n\n        // ------------------------------------------\n        // Set API\n        // ------------------------------------------\n\n        @Override\n        public int size() {\n            return unmanagedSet.size();\n        }\n\n        @Override\n        public boolean isEmpty() {\n            return unmanagedSet.isEmpty();\n        }\n\n        @Override\n        public boolean contains(@Nullable Object o) {\n            return unmanagedSet.contains(o);\n        }\n\n        @Override\n        public Iterator<E> iterator() {\n            return unmanagedSet.iterator();\n        }\n\n        @Override\n        public Object[] toArray() {\n            return unmanagedSet.toArray();\n        }\n\n        @Override\n        public <T> T[] toArray(T[] a) {\n            return unmanagedSet.toArray(a);\n        }\n\n        @Override\n        public boolean add(@Nullable E e) {\n            return unmanagedSet.add(e);\n        }\n\n        @Override\n        public boolean remove(@Nullable Object o) {\n            return unmanagedSet.remove(o);\n        }\n\n        @Override\n        public boolean containsAll(Collection<?> c) {\n            return unmanagedSet.containsAll(c);\n        }\n\n        @Override\n        public boolean addAll(Collection<? extends E> c) {\n            return unmanagedSet.addAll(c);\n        }\n\n        @Override\n        public boolean retainAll(Collection<?> c) {\n            return unmanagedSet.retainAll(c);\n        }\n\n        @Override\n        public boolean removeAll(Collection<?> c) {\n            return unmanagedSet.removeAll(c);\n        }\n\n        @Override\n        public void clear() {\n            unmanagedSet.clear();\n        }\n\n        // ------------------------------------------\n        // Freezable API\n        // ------------------------------------------\n\n        @Override\n        public RealmSet<E> freeze() {\n            throw new UnsupportedOperationException(\"Unmanaged RealmSets cannot be frozen.\");\n        }\n\n        @Override\n        public String getValueClassName() {\n            throw new UnsupportedOperationException(\"Unmanaged sets do not support retrieving the value class name.\");\n        }\n\n        @Override\n        public Class<E> getValueClass() {\n            throw new UnsupportedOperationException(\"Unmanaged sets do not support retrieving the value class.\");\n        }\n\n        @Override\n        OsSet getOsSet() {\n            throw new UnsupportedOperationException(\"Unmanaged RealmSets do not have a representation in native code.\");\n        }\n\n        // ------------------------------------------\n        // RealmSet API\n        // ------------------------------------------\n\n        @Override\n        void addChangeListener(RealmSet<E> set, RealmChangeListener<RealmSet<E>> listener) {\n            throw new UnsupportedOperationException(\"Unmanaged RealmSets do not support change listeners.\");\n        }\n\n        @Override\n        void addChangeListener(RealmSet<E> set, SetChangeListener<E> listener) {\n            throw new UnsupportedOperationException(\"Unmanaged RealmSets do not support change listeners.\");\n        }\n\n        @Override\n        void removeChangeListener(RealmSet<E> set, RealmChangeListener<RealmSet<E>> listener) {\n            throw new UnsupportedOperationException(\"Cannot remove change listener because unmanaged RealmSets do not support change listeners.\");\n        }\n\n        @Override\n        void removeChangeListener(RealmSet<E> set, SetChangeListener<E> listener) {\n            throw new UnsupportedOperationException(\"Cannot remove change listener because unmanaged RealmSets do not support change listeners.\");\n        }\n\n        @Override\n        void removeAllChangeListeners() {\n            throw new UnsupportedOperationException(\"Cannot remove change listeners because unmanaged RealmSets do not support change listeners.\");\n        }\n\n        @Override\n        boolean hasListeners() {\n            return false;\n        }\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/SetChangeListener.java",
    "content": "/*\n * Copyright 2021 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\npackage io.realm;\n\n/**\n * {@link SetChangeListener} can be registered with a {@link RealmSet} to receive a notification\n * with a {@link SetChangeSet} to describe the details of what have been changed in the set since\n * last time.\n * <p>\n * Realm instances on a thread without an {@link android.os.Looper} cannot register a\n * {@link SetChangeListener}.\n * <p>\n *\n * @param <T> the type of the values stored in the set\n * @see RealmSet#addChangeListener(SetChangeListener)\n */\npublic interface SetChangeListener<T> {\n    void onChange(RealmSet<T> set, SetChangeSet changes);\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/SetChangeSet.java",
    "content": "/*\n * Copyright 2021 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\npackage io.realm;\n\nimport io.realm.internal.OsCollectionChangeSet;\n\n/**\n * This class describes the changes made to a set during the last update.\n * <p>\n * {@link SetChangeSet} is passed to the {@link SetChangeListener} which is registered\n * by {@link RealmSet#addChangeListener(SetChangeListener)}.\n */\npublic class SetChangeSet {\n\n    // Internally, this change set is like a list change set's but without the indices\n    private final OsCollectionChangeSet osCollectionChangeSet;\n\n    public SetChangeSet(OsCollectionChangeSet osCollectionChangeSet) {\n        this.osCollectionChangeSet = osCollectionChangeSet;\n    }\n\n    /**\n     * The number of entries that have been inserted.\n     *\n     * @return the number of insertions.\n     */\n    public int getNumberOfInsertions() {\n        return osCollectionChangeSet.getInsertions().length;\n    }\n\n    /**\n     * The number of entries that have been deleted\n     *\n     * @return the number of deletions\n     */\n    public int getNumberOfDeletions() {\n        return osCollectionChangeSet.getDeletions().length;\n    }\n\n    /**\n     * Whether the change set is empty or not. This is needed to detect whether a notification has\n     * been triggered right after subscription.\n     *\n     * @return whether the change set contains changes.\n     */\n    public boolean isEmpty() {\n        // Since this wraps an Object Store change set, it will always contains changes if an\n        // Object Store change set exists.\n        return osCollectionChangeSet.getNativePtr() == 0;\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/SetValueOperator.java",
    "content": "/*\n * Copyright 2021 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\npackage io.realm;\n\nimport org.bson.types.Decimal128;\nimport org.bson.types.ObjectId;\nimport org.jetbrains.annotations.NotNull;\n\nimport java.util.ArrayList;\nimport java.util.Collection;\nimport java.util.Date;\nimport java.util.Iterator;\nimport java.util.List;\nimport java.util.NoSuchElementException;\nimport java.util.UUID;\n\nimport javax.annotation.Nullable;\n\nimport io.realm.internal.ObservableSet;\nimport io.realm.internal.ObserverPairList;\nimport io.realm.internal.OsSet;\nimport io.realm.internal.RealmObjectProxy;\nimport io.realm.internal.Row;\nimport io.realm.internal.core.NativeRealmAny;\nimport io.realm.internal.core.NativeRealmAnyCollection;\n\nimport static io.realm.CollectionUtils.SET_TYPE;\n\n\n/**\n * Abstraction for different set value types.\n *\n * @param <E> the value type\n */\nabstract class SetValueOperator<E> implements ObservableSet {\n\n    protected final BaseRealm baseRealm;\n    protected final OsSet osSet;\n    protected final Class<E> valueClass;\n    protected final String className;\n\n    protected final ObserverPairList<ObservableSet.SetObserverPair<E>> setObserverPairs = new ObserverPairList<>();\n\n    SetValueOperator(BaseRealm baseRealm, OsSet osSet, Class<E> valueClass) {\n        this(baseRealm, osSet, valueClass, valueClass.getSimpleName());\n    }\n\n    SetValueOperator(BaseRealm baseRealm, OsSet osSet, Class<E> valueClass, String className) {\n        this.baseRealm = baseRealm;\n        this.osSet = osSet;\n        this.valueClass = valueClass;\n        this.className = className;\n    }\n\n    abstract boolean add(@Nullable E value);\n\n    abstract boolean containsInternal(@Nullable Object o);\n\n    abstract boolean removeInternal(@Nullable Object o);\n\n    abstract boolean containsAllInternal(Collection<?> c);\n\n    abstract boolean addAllInternal(Collection<? extends E> c);\n\n    abstract boolean removeAllInternal(Collection<?> c);\n\n    abstract boolean retainAllInternal(Collection<?> c);\n\n    RealmQuery<E> where(){\n        throw new UnsupportedOperationException(\"This feature is available only when the element type is implementing RealmModel.\");\n    }\n\n    void deleteAll(){\n        osSet.deleteAll();\n    }\n\n    @Override\n    public void notifyChangeListeners(long nativeChangeSetPtr) {\n        osSet.notifyChangeListeners(nativeChangeSetPtr, setObserverPairs);\n    }\n\n    boolean contains(@Nullable Object o) {\n        if (!isObjectSameType(o)) {\n            // Throw as per interface contract\n            throw new ClassCastException(\"Set contents and object must be the same type when calling 'contains'.\");\n        }\n        return containsInternal(o);\n    }\n\n    boolean remove(@Nullable Object o) {\n        if (!isObjectSameType(o)) {\n            // Throw as per interface contract\n            throw new ClassCastException(\"Set contents and object must be the same type when calling 'remove'.\");\n        }\n        return removeInternal(o);\n    }\n\n    boolean containsAll(Collection<?> c) {\n        if (isRealmCollection(c)) {\n            OsSet otherOsSet = ((RealmSet<?>) c).getOsSet();\n            return funnelCollection(otherOsSet, OsSet.ExternalCollectionOperation.CONTAINS_ALL);\n        }\n        if (!isCollectionSameType(c)) {\n            // Throw as per interface contract\n            throw new ClassCastException(\"Set contents and collection must be the same type when calling 'containsAll'.\");\n        }\n\n        return containsAllInternal(c);\n    }\n\n    boolean addAll(Collection<? extends E> c) {\n        if (isRealmCollection(c)) {\n            OsSet otherOsSet = ((RealmSet<?>) c).getOsSet();\n            return funnelCollection(otherOsSet, OsSet.ExternalCollectionOperation.ADD_ALL);\n        }\n        if (!isUpperBoundCollectionSameType(c)) {\n            // Throw as per interface contract\n            throw new ClassCastException(\"Set contents and collection must be the same type when calling 'addAll'.\");\n        }\n\n        return addAllInternal(c);\n    }\n\n    boolean removeAll(Collection<?> c) {\n        if (isRealmCollection(c)) {\n            OsSet otherOsSet = ((RealmSet<?>) c).getOsSet();\n            return funnelCollection(otherOsSet, OsSet.ExternalCollectionOperation.REMOVE_ALL);\n        }\n        if (!isCollectionSameType(c)) {\n            // Throw as per interface contract\n            throw new ClassCastException(\"Set contents and collection must be the same type when calling 'removeAll'.\");\n        }\n\n        return removeAllInternal(c);\n    }\n\n    boolean retainAll(Collection<?> c) {\n        if (isRealmCollection(c)) {\n            OsSet otherOsSet = ((RealmSet<?>) c).getOsSet();\n            return funnelCollection(otherOsSet, OsSet.ExternalCollectionOperation.RETAIN_ALL);\n        }\n        if (!isCollectionSameType(c)) {\n            // Throw as per interface contract\n            throw new ClassCastException(\"Set contents and collection must be the same type when calling 'retainAll'.\");\n        }\n\n        return retainAllInternal(c);\n    }\n\n    boolean isValid() {\n        if (baseRealm.isClosed()) {\n            return false;\n        }\n        return osSet.isValid();\n    }\n\n    boolean isFrozen() {\n        return baseRealm.isFrozen();\n    }\n\n    int size() {\n        return Long.valueOf(osSet.size()).intValue();\n    }\n\n    boolean isEmpty() {\n        return size() == 0;\n    }\n\n    Iterator<E> iterator() {\n        return iteratorFactory(valueClass, osSet, baseRealm, className);\n    }\n\n    void clear() {\n        osSet.clear();\n    }\n\n    RealmSet<E> freeze() {\n        BaseRealm frozenRealm = baseRealm.freeze();\n        OsSet frozenOsSet = osSet.freeze(frozenRealm.sharedRealm);\n        return new RealmSet<>(frozenRealm, frozenOsSet, valueClass);\n    }\n\n    void addChangeListener(RealmSet<E> realmSet, SetChangeListener<E> listener) {\n        CollectionUtils.checkForAddRemoveListener(baseRealm, listener, true);\n        if (setObserverPairs.isEmpty()) {\n            osSet.startListening(this);\n        }\n        ObservableSet.SetObserverPair<E> setObserverPair = new ObservableSet.SetObserverPair<>(realmSet, listener);\n        setObserverPairs.add(setObserverPair);\n    }\n\n    void addChangeListener(RealmSet<E> realmSet, RealmChangeListener<RealmSet<E>> listener) {\n        SetChangeListener<E> changeListener = new SetChangeListener<E>() {\n            @Override\n            public void onChange(RealmSet<E> set, SetChangeSet changes) {\n                listener.onChange(set);\n            }\n        };\n        addChangeListener(realmSet, changeListener);\n    }\n\n    void removeChangeListener(RealmSet<E> realmSet, RealmChangeListener<RealmSet<E>> listener) {\n        removeChangeListener(realmSet, new SetChangeListener<E>() {\n            @Override\n            public void onChange(RealmSet<E> set, SetChangeSet changes) {\n                listener.onChange(set);\n            }\n        });\n    }\n\n    void removeChangeListener(RealmSet<E> realmSet, SetChangeListener<E> listener) {\n        setObserverPairs.remove(realmSet, listener);\n        if (setObserverPairs.isEmpty()) {\n            osSet.stopListening();\n        }\n    }\n\n    void removeAllChangeListeners() {\n        CollectionUtils.checkForAddRemoveListener(baseRealm, null, false);\n        setObserverPairs.clear();\n        osSet.stopListening();\n    }\n\n    boolean hasListeners() {\n        return !setObserverPairs.isEmpty();\n    }\n\n    OsSet getOsSet() {\n        return osSet;\n    }\n\n    @SuppressWarnings(\"unchecked\")\n    protected boolean isRealmCollection(Collection<?> c) {\n        // TODO: add support for RealmList and RealmResults when overloading is exposed by OS/Core\n        return c instanceof RealmSet && ((RealmSet<? extends E>) c).isManaged();\n    }\n\n    protected boolean funnelCollection(OsSet otherOsSet,\n                                       OsSet.ExternalCollectionOperation operation) {\n        // Special case if the passed collection is the same native set as this one\n        if (osSet.getNativePtr() == otherOsSet.getNativePtr()) {\n            switch (operation) {\n                case CONTAINS_ALL:\n                    // A set always contains itself\n                    return true;\n                case ADD_ALL:\n                    // Nothing changes if we add this set to this very set\n                    return false;\n                case REMOVE_ALL:\n                    // Clear and return true if the passed collection is this very set\n                    osSet.clear();\n                    return true;\n                case RETAIN_ALL:\n                    // Nothing changes if this set intersects this very set\n                    return false;\n                default:\n                    throw new IllegalStateException(\"Unexpected value: \" + operation);\n            }\n        }\n\n        // Otherwise compute set-specific operation\n        switch (operation) {\n            case CONTAINS_ALL:\n                return osSet.containsAll(otherOsSet);\n            case ADD_ALL:\n                return osSet.union(otherOsSet);\n            case REMOVE_ALL:\n                return osSet.asymmetricDifference(otherOsSet);\n            case RETAIN_ALL:\n                return osSet.intersect(otherOsSet);\n            default:\n                throw new IllegalStateException(\"Unexpected value: \" + operation);\n        }\n    }\n\n    private boolean isObjectSameType(@Nullable Object object) {\n        // Return false when passing something else than the correct type\n        if (object != null) {\n            return valueClass.isAssignableFrom(object.getClass());\n        } else {\n            return true;\n        }\n    }\n\n    private boolean isUpperBoundCollectionSameType(Collection<? extends E> c) {\n        if (!c.isEmpty()) {\n            for (E item : c) {\n                if (item != null && !valueClass.isAssignableFrom(item.getClass())) {\n                    return false;\n                }\n            }\n        }\n        return true;\n    }\n\n    private boolean isCollectionSameType(Collection<?> c) {\n        if (!c.isEmpty()) {\n            for (Object item : c) {\n                if (item != null && !valueClass.isAssignableFrom(item.getClass())) {\n                    return false;\n                }\n            }\n        }\n        return true;\n    }\n\n    @SuppressWarnings(\"unchecked\")\n    private static <T> SetIterator<T> iteratorFactory(Class<T> valueClass,\n                                                      OsSet osSet,\n                                                      BaseRealm baseRealm,\n                                                      String className) {\n        if (valueClass == Boolean.class) {\n            return (SetIterator<T>) new BooleanSetIterator(osSet, baseRealm);\n        } else if (valueClass == String.class) {\n            return (SetIterator<T>) new StringSetIterator(osSet, baseRealm);\n        } else if (valueClass == Integer.class) {\n            return (SetIterator<T>) new IntegerSetIterator(osSet, baseRealm);\n        } else if (valueClass == Long.class) {\n            return (SetIterator<T>) new LongSetIterator(osSet, baseRealm);\n        } else if (valueClass == Short.class) {\n            return (SetIterator<T>) new ShortSetIterator(osSet, baseRealm);\n        } else if (valueClass == Byte.class) {\n            return (SetIterator<T>) new ByteSetIterator(osSet, baseRealm);\n        } else if (valueClass == Float.class) {\n            return (SetIterator<T>) new FloatSetIterator(osSet, baseRealm);\n        } else if (valueClass == Double.class) {\n            return (SetIterator<T>) new DoubleSetIterator(osSet, baseRealm);\n        } else if (valueClass == byte[].class) {\n            return (SetIterator<T>) new BinarySetIterator(osSet, baseRealm);\n        } else if (valueClass == Date.class) {\n            return (SetIterator<T>) new DateSetIterator(osSet, baseRealm);\n        } else if (valueClass == Decimal128.class) {\n            return (SetIterator<T>) new Decimal128SetIterator(osSet, baseRealm);\n        } else if (valueClass == ObjectId.class) {\n            return (SetIterator<T>) new ObjectIdSetIterator(osSet, baseRealm);\n        } else if (valueClass == UUID.class) {\n            return (SetIterator<T>) new UUIDSetIterator(osSet, baseRealm);\n        } else if (valueClass == RealmAny.class) {\n            return (SetIterator<T>) new RealmAnySetIterator(osSet, baseRealm);\n        } else if (valueClass == DynamicRealmObject.class){\n            return (SetIterator<T>) new DynamicSetIterator(osSet, baseRealm, className);\n        } else if (CollectionUtils.isClassForRealmModel(valueClass)) {\n            return (SetIterator<T>) new RealmModelSetIterator(osSet, baseRealm, valueClass);\n        } else {\n            throw new IllegalArgumentException(\"Unknown class for iterator: \" + valueClass.getSimpleName());\n        }\n    }\n\n    public Class<E> getValueClass() {\n        return valueClass;\n    }\n\n    public String getValueClassName() {\n        return className;\n    }\n}\n\n/**\n * {@link SetValueOperator} targeting {@code boolean} values in {@link RealmSet}s.\n */\nclass BooleanOperator extends SetValueOperator<Boolean> {\n\n    BooleanOperator(BaseRealm baseRealm, OsSet osSet, Class<Boolean> valueClass) {\n        super(baseRealm, osSet, valueClass);\n    }\n\n    @Override\n    boolean add(@Nullable Boolean value) {\n        return osSet.add(value);\n    }\n\n    @Override\n    boolean containsInternal(@Nullable Object o) {\n        return osSet.contains((Boolean) o);\n    }\n\n    @Override\n    boolean removeInternal(@Nullable Object o) {\n        return osSet.remove((Boolean) o);\n    }\n\n    @Override\n    boolean containsAllInternal(Collection<?> c) {\n        // Collection has been type-checked from caller\n        //noinspection unchecked\n        Collection<Boolean> booleanCollection = (Collection<Boolean>) c;\n        NativeRealmAnyCollection collection = NativeRealmAnyCollection.newBooleanCollection(booleanCollection);\n        return osSet.collectionFunnel(collection, OsSet.ExternalCollectionOperation.CONTAINS_ALL);\n    }\n\n    @Override\n    boolean addAllInternal(Collection<? extends Boolean> c) {\n        // Collection has been type-checked from caller\n        //noinspection unchecked\n        NativeRealmAnyCollection collection = NativeRealmAnyCollection.newBooleanCollection((Collection<Boolean>) c);\n        return osSet.collectionFunnel(collection, OsSet.ExternalCollectionOperation.ADD_ALL);\n    }\n\n    @Override\n    boolean removeAllInternal(Collection<?> c) {\n        // Collection has been type-checked from caller\n        //noinspection unchecked\n        NativeRealmAnyCollection collection = NativeRealmAnyCollection.newBooleanCollection((Collection<Boolean>) c);\n        return osSet.collectionFunnel(collection, OsSet.ExternalCollectionOperation.REMOVE_ALL);\n    }\n\n    @Override\n    boolean retainAllInternal(Collection<?> c) {\n        // Collection has been type-checked from caller\n        //noinspection unchecked\n        NativeRealmAnyCollection collection = NativeRealmAnyCollection.newBooleanCollection((Collection<Boolean>) c);\n        return osSet.collectionFunnel(collection, OsSet.ExternalCollectionOperation.RETAIN_ALL);\n    }\n}\n\n/**\n * {@link SetValueOperator} targeting {@link String} values in {@link RealmSet}s.\n */\nclass StringOperator extends SetValueOperator<String> {\n\n    StringOperator(BaseRealm baseRealm, OsSet osSet, Class<String> valueClass) {\n        super(baseRealm, osSet, valueClass);\n    }\n\n    @Override\n    boolean add(@Nullable String value) {\n        return osSet.add(value);\n    }\n\n    @Override\n    boolean containsInternal(@Nullable Object o) {\n        return osSet.contains((String) o);\n    }\n\n    @Override\n    boolean removeInternal(@Nullable Object o) {\n        // Object has been type-checked from caller\n        return osSet.remove((String) o);\n    }\n\n    @Override\n    boolean containsAllInternal(Collection<?> c) {\n        // Collection has been type-checked from caller\n        //noinspection unchecked\n        Collection<String> stringCollection = (Collection<String>) c;\n        NativeRealmAnyCollection collection = NativeRealmAnyCollection.newStringCollection(stringCollection);\n        return osSet.collectionFunnel(collection, OsSet.ExternalCollectionOperation.CONTAINS_ALL);\n    }\n\n    @Override\n    boolean addAllInternal(Collection<? extends String> c) {\n        // Collection has been type-checked from caller\n        //noinspection unchecked\n        NativeRealmAnyCollection collection = NativeRealmAnyCollection.newStringCollection((Collection<String>) c);\n        return osSet.collectionFunnel(collection, OsSet.ExternalCollectionOperation.ADD_ALL);\n    }\n\n    @Override\n    boolean removeAllInternal(Collection<?> c) {\n        // Collection has been type-checked from caller\n        //noinspection unchecked\n        NativeRealmAnyCollection collection = NativeRealmAnyCollection.newStringCollection((Collection<String>) c);\n        return osSet.collectionFunnel(collection, OsSet.ExternalCollectionOperation.REMOVE_ALL);\n    }\n\n    @Override\n    boolean retainAllInternal(Collection<?> c) {\n        // Collection has been type-checked from caller\n        //noinspection unchecked\n        NativeRealmAnyCollection collection = NativeRealmAnyCollection.newStringCollection((Collection<String>) c);\n        return osSet.collectionFunnel(collection, OsSet.ExternalCollectionOperation.RETAIN_ALL);\n    }\n}\n\n/**\n * {@link SetValueOperator} targeting {@code Number} values in {@link RealmSet}s.\n */\nclass NumberOperator extends SetValueOperator<Number> {\n\n    NumberOperator(BaseRealm baseRealm, OsSet osSet, Class<Number> valueClass) {\n        super(baseRealm, osSet, valueClass);\n    }\n\n    @Override\n    boolean add(@Nullable Number value) {\n        if (value == null) { return osSet.add((Long) null); }\n\n        return osSet.add(value.longValue());\n    }\n\n    @Override\n    boolean containsInternal(@Nullable Object o) {\n        Long value;\n        if (o == null) {\n            value = null;\n        } else {\n            value = ((Number) o).longValue();\n        }\n        return osSet.contains(value);\n    }\n\n    @Override\n    boolean removeInternal(@Nullable Object o) {\n        if (o == null) { return osSet.remove((Long) null); }\n        // Object has been type-checked from caller\n        return osSet.remove(((Number) o).longValue());\n    }\n\n    @Override\n    boolean containsAllInternal(Collection<?> c) {\n        // Collection has been type-checked from caller\n        //noinspection unchecked\n        Collection<Number> numberCollection = (Collection<Number>) c;\n        NativeRealmAnyCollection collection = NativeRealmAnyCollection.newIntegerCollection(numberCollection);\n        return osSet.collectionFunnel(collection, OsSet.ExternalCollectionOperation.CONTAINS_ALL);\n    }\n\n    @Override\n    boolean addAllInternal(Collection<? extends Number> c) {\n        // Collection has been type-checked from caller\n        NativeRealmAnyCollection collection = NativeRealmAnyCollection.newIntegerCollection(c);\n        return osSet.collectionFunnel(collection, OsSet.ExternalCollectionOperation.ADD_ALL);\n    }\n\n    @Override\n    boolean removeAllInternal(Collection<?> c) {\n        // Collection has been type-checked from caller\n        //noinspection unchecked\n        NativeRealmAnyCollection collection = NativeRealmAnyCollection.newIntegerCollection((Collection<Number>) c);\n        return osSet.collectionFunnel(collection, OsSet.ExternalCollectionOperation.REMOVE_ALL);\n    }\n\n    @Override\n    boolean retainAllInternal(Collection<?> c) {\n        // Collection has been type-checked from caller\n        //noinspection unchecked\n        NativeRealmAnyCollection collection = NativeRealmAnyCollection.newIntegerCollection((Collection<Number>) c);\n        return osSet.collectionFunnel(collection, OsSet.ExternalCollectionOperation.RETAIN_ALL);\n    }\n}\n\n/**\n * {@link SetValueOperator} targeting {@code int} values in {@link RealmSet}s.\n */\nclass IntegerOperator extends SetValueOperator<Integer> {\n\n    IntegerOperator(BaseRealm baseRealm, OsSet osSet, Class<Integer> valueClass) {\n        super(baseRealm, osSet, valueClass);\n    }\n\n    @Override\n    boolean add(@Nullable Integer value) {\n        return osSet.add(value);\n    }\n\n    @Override\n    boolean containsInternal(@Nullable Object o) {\n        Long value;\n        if (o == null) {\n            value = null;\n        } else {\n            value = ((Integer) o).longValue();\n        }\n        return osSet.contains(value);\n    }\n\n    @Override\n    boolean removeInternal(@Nullable Object o) {\n        // Object has been type-checked from caller\n        return osSet.remove((Integer) o);\n    }\n\n    @Override\n    boolean containsAllInternal(Collection<?> c) {\n        // Collection has been type-checked from caller\n        //noinspection unchecked\n        Collection<Number> numberCollection = (Collection<Number>) c;\n        NativeRealmAnyCollection collection = NativeRealmAnyCollection.newIntegerCollection(numberCollection);\n        return osSet.collectionFunnel(collection, OsSet.ExternalCollectionOperation.CONTAINS_ALL);\n    }\n\n    @Override\n    boolean addAllInternal(Collection<? extends Integer> c) {\n        // Collection has been type-checked from caller\n        NativeRealmAnyCollection collection = NativeRealmAnyCollection.newIntegerCollection(c);\n        return osSet.collectionFunnel(collection, OsSet.ExternalCollectionOperation.ADD_ALL);\n    }\n\n    @Override\n    boolean removeAllInternal(Collection<?> c) {\n        // Collection has been type-checked from caller\n        //noinspection unchecked\n        NativeRealmAnyCollection collection = NativeRealmAnyCollection.newIntegerCollection((Collection<Integer>) c);\n        return osSet.collectionFunnel(collection, OsSet.ExternalCollectionOperation.REMOVE_ALL);\n    }\n\n    @Override\n    boolean retainAllInternal(Collection<?> c) {\n        // Collection has been type-checked from caller\n        //noinspection unchecked\n        NativeRealmAnyCollection collection = NativeRealmAnyCollection.newIntegerCollection((Collection<Integer>) c);\n        return osSet.collectionFunnel(collection, OsSet.ExternalCollectionOperation.RETAIN_ALL);\n    }\n}\n\n/**\n * {@link SetValueOperator} targeting {@code long} values in {@link RealmSet}s.\n */\nclass LongOperator extends SetValueOperator<Long> {\n\n    LongOperator(BaseRealm baseRealm, OsSet osSet, Class<Long> valueClass) {\n        super(baseRealm, osSet, valueClass);\n    }\n\n    @Override\n    boolean add(@Nullable Long value) {\n        return osSet.add(value);\n    }\n\n    @Override\n    boolean containsInternal(@Nullable Object o) {\n        return osSet.contains((Long) o);\n    }\n\n    @Override\n    boolean removeInternal(@Nullable Object o) {\n        // Object has been type-checked from caller\n        return osSet.remove((Long) o);\n    }\n\n    @Override\n    boolean containsAllInternal(Collection<?> c) {\n        // Collection has been type-checked from caller\n        //noinspection unchecked\n        NativeRealmAnyCollection collection = NativeRealmAnyCollection.newIntegerCollection((Collection<Number>) c);\n        return osSet.collectionFunnel(collection, OsSet.ExternalCollectionOperation.CONTAINS_ALL);\n    }\n\n    @Override\n    boolean addAllInternal(Collection<? extends Long> c) {\n        // Collection has been type-checked from caller\n        NativeRealmAnyCollection collection = NativeRealmAnyCollection.newIntegerCollection(c);\n        return osSet.collectionFunnel(collection, OsSet.ExternalCollectionOperation.ADD_ALL);\n    }\n\n    @Override\n    boolean removeAllInternal(Collection<?> c) {\n        // Collection has been type-checked from caller\n        //noinspection unchecked\n        NativeRealmAnyCollection collection = NativeRealmAnyCollection.newIntegerCollection((Collection<Long>) c);\n        return osSet.collectionFunnel(collection, OsSet.ExternalCollectionOperation.REMOVE_ALL);\n    }\n\n    @Override\n    boolean retainAllInternal(Collection<?> c) {\n        // Collection has been type-checked from caller\n        //noinspection unchecked\n        NativeRealmAnyCollection collection = NativeRealmAnyCollection.newIntegerCollection((Collection<Long>) c);\n        return osSet.collectionFunnel(collection, OsSet.ExternalCollectionOperation.RETAIN_ALL);\n    }\n}\n\n/**\n * {@link SetValueOperator} targeting {@code short} values in {@link RealmSet}s.\n */\nclass ShortOperator extends SetValueOperator<Short> {\n\n    ShortOperator(BaseRealm baseRealm, OsSet osSet, Class<Short> valueClass) {\n        super(baseRealm, osSet, valueClass);\n    }\n\n    @Override\n    boolean add(@Nullable Short value) {\n        return osSet.add(value);\n    }\n\n    @Override\n    boolean containsInternal(@Nullable Object o) {\n        Long value;\n        if (o == null) {\n            value = null;\n        } else {\n            value = ((Short) o).longValue();\n        }\n        return osSet.contains(value);\n    }\n\n    @Override\n    boolean removeInternal(@Nullable Object o) {\n        // Object has been type-checked from caller\n        return osSet.remove((Short) o);\n    }\n\n    @Override\n    boolean containsAllInternal(Collection<?> c) {\n        // Collection has been type-checked from caller\n        //noinspection unchecked\n        Collection<Number> numberCollection = (Collection<Number>) c;\n        NativeRealmAnyCollection collection = NativeRealmAnyCollection.newIntegerCollection(numberCollection);\n        return osSet.collectionFunnel(collection, OsSet.ExternalCollectionOperation.CONTAINS_ALL);\n    }\n\n    @Override\n    boolean addAllInternal(Collection<? extends Short> c) {\n        // Collection has been type-checked from caller\n        NativeRealmAnyCollection collection = NativeRealmAnyCollection.newIntegerCollection(c);\n        return osSet.collectionFunnel(collection, OsSet.ExternalCollectionOperation.ADD_ALL);\n    }\n\n    @Override\n    boolean removeAllInternal(Collection<?> c) {\n        // Collection has been type-checked from caller\n        //noinspection unchecked\n        NativeRealmAnyCollection collection = NativeRealmAnyCollection.newIntegerCollection((Collection<Short>) c);\n        return osSet.collectionFunnel(collection, OsSet.ExternalCollectionOperation.REMOVE_ALL);\n    }\n\n    @Override\n    boolean retainAllInternal(Collection<?> c) {\n        // Collection has been type-checked from caller\n        //noinspection unchecked\n        NativeRealmAnyCollection collection = NativeRealmAnyCollection.newIntegerCollection((Collection<Short>) c);\n        return osSet.collectionFunnel(collection, OsSet.ExternalCollectionOperation.RETAIN_ALL);\n    }\n}\n\n/**\n * {@link SetValueOperator} targeting {@code byte} values in {@link RealmSet}s.\n */\nclass ByteOperator extends SetValueOperator<Byte> {\n\n    ByteOperator(BaseRealm baseRealm, OsSet osSet, Class<Byte> valueClass) {\n        super(baseRealm, osSet, valueClass);\n    }\n\n    @Override\n    boolean add(@Nullable Byte value) {\n        return osSet.add(value);\n    }\n\n    @Override\n    boolean containsInternal(@Nullable Object o) {\n        Long value;\n        if (o == null) {\n            value = null;\n        } else {\n            value = ((Byte) o).longValue();\n        }\n        return osSet.contains(value);\n    }\n\n    @Override\n    boolean removeInternal(@Nullable Object o) {\n        // Object has been type-checked from caller\n        return osSet.remove((Byte) o);\n    }\n\n    @Override\n    boolean containsAllInternal(Collection<?> c) {\n        // Collection has been type-checked from caller\n        //noinspection unchecked\n        Collection<Number> numberCollection = (Collection<Number>) c;\n        NativeRealmAnyCollection collection = NativeRealmAnyCollection.newIntegerCollection(numberCollection);\n        return osSet.collectionFunnel(collection, OsSet.ExternalCollectionOperation.CONTAINS_ALL);\n    }\n\n    @Override\n    boolean addAllInternal(Collection<? extends Byte> c) {\n        // Collection has been type-checked from caller\n        NativeRealmAnyCollection collection = NativeRealmAnyCollection.newIntegerCollection(c);\n        return osSet.collectionFunnel(collection, OsSet.ExternalCollectionOperation.ADD_ALL);\n    }\n\n    @Override\n    boolean removeAllInternal(Collection<?> c) {\n        // Collection has been type-checked from caller\n        //noinspection unchecked\n        NativeRealmAnyCollection collection = NativeRealmAnyCollection.newIntegerCollection((Collection<Byte>) c);\n        return osSet.collectionFunnel(collection, OsSet.ExternalCollectionOperation.REMOVE_ALL);\n    }\n\n    @Override\n    boolean retainAllInternal(Collection<?> c) {\n        // Collection has been type-checked from caller\n        //noinspection unchecked\n        NativeRealmAnyCollection collection = NativeRealmAnyCollection.newIntegerCollection((Collection<Byte>) c);\n        return osSet.collectionFunnel(collection, OsSet.ExternalCollectionOperation.RETAIN_ALL);\n    }\n}\n\n/**\n * {@link SetValueOperator} targeting {@code float} values in {@link RealmSet}s.\n */\nclass FloatOperator extends SetValueOperator<Float> {\n\n    FloatOperator(BaseRealm baseRealm, OsSet osSet, Class<Float> valueClass) {\n        super(baseRealm, osSet, valueClass);\n    }\n\n    @Override\n    boolean add(@Nullable Float value) {\n        return osSet.add(value);\n    }\n\n    @Override\n    boolean containsInternal(@Nullable Object o) {\n        Float value;\n        if (o == null) {\n            value = null;\n        } else {\n            value = (Float) o;\n        }\n        return osSet.contains(value);\n    }\n\n    @Override\n    boolean removeInternal(@Nullable Object o) {\n        return osSet.remove((Float) o);\n    }\n\n    @Override\n    boolean containsAllInternal(Collection<?> c) {\n        // Collection has been type-checked from caller\n        //noinspection unchecked\n        Collection<Float> floatCollection = (Collection<Float>) c;\n        NativeRealmAnyCollection collection = NativeRealmAnyCollection.newFloatCollection(floatCollection);\n        return osSet.collectionFunnel(collection, OsSet.ExternalCollectionOperation.CONTAINS_ALL);\n    }\n\n    @Override\n    boolean addAllInternal(Collection<? extends Float> c) {\n        // Collection has been type-checked from caller\n        NativeRealmAnyCollection collection = NativeRealmAnyCollection.newFloatCollection(c);\n        return osSet.collectionFunnel(collection, OsSet.ExternalCollectionOperation.ADD_ALL);\n    }\n\n    @Override\n    boolean removeAllInternal(Collection<?> c) {\n        // Collection has been type-checked from caller\n        //noinspection unchecked\n        NativeRealmAnyCollection collection = NativeRealmAnyCollection.newFloatCollection((Collection<Float>) c);\n        return osSet.collectionFunnel(collection, OsSet.ExternalCollectionOperation.REMOVE_ALL);\n    }\n\n    @Override\n    boolean retainAllInternal(Collection<?> c) {\n        // Collection has been type-checked from caller\n        //noinspection unchecked\n        NativeRealmAnyCollection collection = NativeRealmAnyCollection.newFloatCollection((Collection<Float>) c);\n        return osSet.collectionFunnel(collection, OsSet.ExternalCollectionOperation.RETAIN_ALL);\n    }\n}\n\n/**\n * {@link SetValueOperator} targeting {@code double} values in {@link RealmSet}s.\n */\nclass DoubleOperator extends SetValueOperator<Double> {\n\n    DoubleOperator(BaseRealm baseRealm, OsSet osSet, Class<Double> valueClass) {\n        super(baseRealm, osSet, valueClass);\n    }\n\n    @Override\n    boolean add(@Nullable Double value) {\n        return osSet.add(value);\n    }\n\n    @Override\n    boolean containsInternal(@Nullable Object o) {\n        Double value;\n        if (o == null) {\n            value = null;\n        } else {\n            value = (Double) o;\n        }\n        return osSet.contains(value);\n    }\n\n    @Override\n    boolean removeInternal(@Nullable Object o) {\n        return osSet.remove((Double) o);\n    }\n\n    @Override\n    boolean containsAllInternal(Collection<?> c) {\n        // Collection has been type-checked from caller\n        //noinspection unchecked\n        Collection<Double> doubleCollection = (Collection<Double>) c;\n        NativeRealmAnyCollection collection = NativeRealmAnyCollection.newDoubleCollection(doubleCollection);\n        return osSet.collectionFunnel(collection, OsSet.ExternalCollectionOperation.CONTAINS_ALL);\n    }\n\n    @Override\n    boolean addAllInternal(Collection<? extends Double> c) {\n        // Collection has been type-checked from caller\n        NativeRealmAnyCollection collection = NativeRealmAnyCollection.newDoubleCollection(c);\n        return osSet.collectionFunnel(collection, OsSet.ExternalCollectionOperation.ADD_ALL);\n    }\n\n    @Override\n    boolean removeAllInternal(Collection<?> c) {\n        // Collection has been type-checked from caller\n        //noinspection unchecked\n        NativeRealmAnyCollection collection = NativeRealmAnyCollection.newDoubleCollection((Collection<Double>) c);\n        return osSet.collectionFunnel(collection, OsSet.ExternalCollectionOperation.REMOVE_ALL);\n    }\n\n    @Override\n    boolean retainAllInternal(Collection<?> c) {\n        // Collection has been type-checked from caller\n        //noinspection unchecked\n        NativeRealmAnyCollection collection = NativeRealmAnyCollection.newDoubleCollection((Collection<Double>) c);\n        return osSet.collectionFunnel(collection, OsSet.ExternalCollectionOperation.RETAIN_ALL);\n    }\n}\n\n/**\n * {@link SetValueOperator} targeting {@code byte[]} values in {@link RealmSet}s.\n */\nclass BinaryOperator extends SetValueOperator<byte[]> {\n\n    BinaryOperator(BaseRealm baseRealm, OsSet osSet, Class<byte[]> valueClass) {\n        super(baseRealm, osSet, valueClass);\n    }\n\n    @Override\n    boolean add(@Nullable byte[] value) {\n        return osSet.add(value);\n    }\n\n    @Override\n    boolean containsInternal(@Nullable Object o) {\n        byte[] value;\n        if (o == null) {\n            value = null;\n        } else {\n            value = (byte[]) o;\n        }\n        return osSet.contains(value);\n    }\n\n    @Override\n    boolean removeInternal(@Nullable Object o) {\n        return osSet.remove((byte[]) o);\n    }\n\n    @Override\n    boolean containsAllInternal(Collection<?> c) {\n        // Collection has been type-checked from caller\n        //noinspection unchecked\n        Collection<byte[]> binaryCollection = (Collection<byte[]>) c;\n        NativeRealmAnyCollection collection = NativeRealmAnyCollection.newBinaryCollection(binaryCollection);\n        return osSet.collectionFunnel(collection, OsSet.ExternalCollectionOperation.CONTAINS_ALL);\n    }\n\n    @Override\n    boolean addAllInternal(Collection<? extends byte[]> c) {\n        // Collection has been type-checked from caller\n        NativeRealmAnyCollection collection = NativeRealmAnyCollection.newBinaryCollection(c);\n        return osSet.collectionFunnel(collection, OsSet.ExternalCollectionOperation.ADD_ALL);\n    }\n\n    @Override\n    boolean removeAllInternal(Collection<?> c) {\n        // Collection has been type-checked from caller\n        //noinspection unchecked\n        NativeRealmAnyCollection collection = NativeRealmAnyCollection.newBinaryCollection((Collection<byte[]>) c);\n        return osSet.collectionFunnel(collection, OsSet.ExternalCollectionOperation.REMOVE_ALL);\n    }\n\n    @Override\n    boolean retainAllInternal(Collection<?> c) {\n        // Collection has been type-checked from caller\n        //noinspection unchecked\n        NativeRealmAnyCollection collection = NativeRealmAnyCollection.newBinaryCollection((Collection<byte[]>) c);\n        return osSet.collectionFunnel(collection, OsSet.ExternalCollectionOperation.RETAIN_ALL);\n    }\n}\n\n/**\n * {@link SetValueOperator} targeting {@link Date} values in {@link RealmSet}s.\n */\nclass DateOperator extends SetValueOperator<Date> {\n\n    DateOperator(BaseRealm baseRealm, OsSet osSet, Class<Date> valueClass) {\n        super(baseRealm, osSet, valueClass);\n    }\n\n    @Override\n    boolean add(@Nullable Date value) {\n        return osSet.add(value);\n    }\n\n    @Override\n    boolean containsInternal(@Nullable Object o) {\n        Date value;\n        if (o == null) {\n            value = null;\n        } else {\n            value = (Date) o;\n        }\n        return osSet.contains(value);\n    }\n\n    @Override\n    boolean removeInternal(@Nullable Object o) {\n        return osSet.remove((Date) o);\n    }\n\n    @Override\n    boolean containsAllInternal(Collection<?> c) {\n        // Collection has been type-checked from caller\n        //noinspection unchecked\n        Collection<Date> dateCollection = (Collection<Date>) c;\n        NativeRealmAnyCollection collection = NativeRealmAnyCollection.newDateCollection(dateCollection);\n        return osSet.collectionFunnel(collection, OsSet.ExternalCollectionOperation.CONTAINS_ALL);\n    }\n\n    @Override\n    boolean addAllInternal(Collection<? extends Date> c) {\n        // Collection has been type-checked from caller\n        NativeRealmAnyCollection collection = NativeRealmAnyCollection.newDateCollection(c);\n        return osSet.collectionFunnel(collection, OsSet.ExternalCollectionOperation.ADD_ALL);\n    }\n\n    @Override\n    boolean removeAllInternal(Collection<?> c) {\n        // Collection has been type-checked from caller\n        //noinspection unchecked\n        NativeRealmAnyCollection collection = NativeRealmAnyCollection.newDateCollection((Collection<Date>) c);\n        return osSet.collectionFunnel(collection, OsSet.ExternalCollectionOperation.REMOVE_ALL);\n    }\n\n    @Override\n    boolean retainAllInternal(Collection<?> c) {\n        // Collection has been type-checked from caller\n        //noinspection unchecked\n        NativeRealmAnyCollection collection = NativeRealmAnyCollection.newDateCollection((Collection<Date>) c);\n        return osSet.collectionFunnel(collection, OsSet.ExternalCollectionOperation.RETAIN_ALL);\n    }\n}\n\n/**\n * {@link SetValueOperator} targeting {@link Decimal128} values in {@link RealmSet}s.\n */\nclass Decimal128Operator extends SetValueOperator<Decimal128> {\n\n    Decimal128Operator(BaseRealm baseRealm, OsSet osSet, Class<Decimal128> valueClass) {\n        super(baseRealm, osSet, valueClass);\n    }\n\n    @Override\n    boolean add(@Nullable Decimal128 value) {\n        return osSet.add(value);\n    }\n\n    @Override\n    boolean containsInternal(@Nullable Object o) {\n        Decimal128 value;\n        if (o == null) {\n            value = null;\n        } else {\n            value = (Decimal128) o;\n        }\n        return osSet.contains(value);\n    }\n\n    @Override\n    boolean removeInternal(@Nullable Object o) {\n        return osSet.remove((Decimal128) o);\n    }\n\n    @Override\n    boolean containsAllInternal(Collection<?> c) {\n        // Collection has been type-checked from caller\n        //noinspection unchecked\n        Collection<Decimal128> decimal128Collection = (Collection<Decimal128>) c;\n        NativeRealmAnyCollection collection = NativeRealmAnyCollection.newDecimal128Collection(decimal128Collection);\n        return osSet.collectionFunnel(collection, OsSet.ExternalCollectionOperation.CONTAINS_ALL);\n    }\n\n    @Override\n    boolean addAllInternal(Collection<? extends Decimal128> c) {\n        // Collection has been type-checked from caller\n        NativeRealmAnyCollection collection = NativeRealmAnyCollection.newDecimal128Collection(c);\n        return osSet.collectionFunnel(collection, OsSet.ExternalCollectionOperation.ADD_ALL);\n    }\n\n    @Override\n    boolean removeAllInternal(Collection<?> c) {\n        // Collection has been type-checked from caller\n        //noinspection unchecked\n        NativeRealmAnyCollection collection = NativeRealmAnyCollection.newDecimal128Collection((Collection<Decimal128>) c);\n        return osSet.collectionFunnel(collection, OsSet.ExternalCollectionOperation.REMOVE_ALL);\n    }\n\n    @Override\n    boolean retainAllInternal(Collection<?> c) {\n        // Collection has been type-checked from caller\n        //noinspection unchecked\n        NativeRealmAnyCollection collection = NativeRealmAnyCollection.newDecimal128Collection((Collection<Decimal128>) c);\n        return osSet.collectionFunnel(collection, OsSet.ExternalCollectionOperation.RETAIN_ALL);\n    }\n}\n\n/**\n * {@link SetValueOperator} targeting {@link ObjectId} values in {@link RealmSet}s.\n */\nclass ObjectIdOperator extends SetValueOperator<ObjectId> {\n\n    ObjectIdOperator(BaseRealm baseRealm, OsSet osSet, Class<ObjectId> valueClass) {\n        super(baseRealm, osSet, valueClass);\n    }\n\n    @Override\n    boolean add(@Nullable ObjectId value) {\n        return osSet.add(value);\n    }\n\n    @Override\n    boolean containsInternal(@Nullable Object o) {\n        ObjectId value;\n        if (o == null) {\n            value = null;\n        } else {\n            value = (ObjectId) o;\n        }\n        return osSet.contains(value);\n    }\n\n    @Override\n    boolean removeInternal(@Nullable Object o) {\n        return osSet.remove((ObjectId) o);\n    }\n\n    @Override\n    boolean containsAllInternal(Collection<?> c) {\n        // Collection has been type-checked from caller\n        //noinspection unchecked\n        Collection<ObjectId> objectIdCollection = (Collection<ObjectId>) c;\n        NativeRealmAnyCollection collection = NativeRealmAnyCollection.newObjectIdCollection(objectIdCollection);\n        return osSet.collectionFunnel(collection, OsSet.ExternalCollectionOperation.CONTAINS_ALL);\n    }\n\n    @Override\n    boolean addAllInternal(Collection<? extends ObjectId> c) {\n        // Collection has been type-checked from caller\n        NativeRealmAnyCollection collection = NativeRealmAnyCollection.newObjectIdCollection(c);\n        return osSet.collectionFunnel(collection, OsSet.ExternalCollectionOperation.ADD_ALL);\n    }\n\n    @Override\n    boolean removeAllInternal(Collection<?> c) {\n        // Collection has been type-checked from caller\n        //noinspection unchecked\n        NativeRealmAnyCollection collection = NativeRealmAnyCollection.newObjectIdCollection((Collection<ObjectId>) c);\n        return osSet.collectionFunnel(collection, OsSet.ExternalCollectionOperation.REMOVE_ALL);\n    }\n\n    @Override\n    boolean retainAllInternal(Collection<?> c) {\n        // Collection has been type-checked from caller\n        //noinspection unchecked\n        NativeRealmAnyCollection collection = NativeRealmAnyCollection.newObjectIdCollection((Collection<ObjectId>) c);\n        return osSet.collectionFunnel(collection, OsSet.ExternalCollectionOperation.RETAIN_ALL);\n    }\n}\n\n/**\n * {@link SetValueOperator} targeting {@link UUID} values in {@link RealmSet}s.\n */\nclass UUIDOperator extends SetValueOperator<UUID> {\n\n    UUIDOperator(BaseRealm baseRealm, OsSet osSet, Class<UUID> valueClass) {\n        super(baseRealm, osSet, valueClass);\n    }\n\n    @Override\n    boolean add(@Nullable UUID value) {\n        return osSet.add(value);\n    }\n\n    @Override\n    boolean containsInternal(@Nullable Object o) {\n        UUID value;\n        if (o == null) {\n            value = null;\n        } else {\n            value = (UUID) o;\n        }\n        return osSet.contains(value);\n    }\n\n    @Override\n    boolean removeInternal(@Nullable Object o) {\n        // Object has been type-checked from caller\n        return osSet.remove((UUID) o);\n    }\n\n    @Override\n    boolean containsAllInternal(Collection<?> c) {\n        // Collection has been type-checked from caller\n        //noinspection unchecked\n        Collection<UUID> uuidCollection = (Collection<UUID>) c;\n        NativeRealmAnyCollection collection = NativeRealmAnyCollection.newUUIDCollection(uuidCollection);\n        return osSet.collectionFunnel(collection, OsSet.ExternalCollectionOperation.CONTAINS_ALL);\n    }\n\n    @Override\n    boolean addAllInternal(Collection<? extends UUID> c) {\n        // Collection has been type-checked from caller\n        NativeRealmAnyCollection collection = NativeRealmAnyCollection.newUUIDCollection(c);\n        return osSet.collectionFunnel(collection, OsSet.ExternalCollectionOperation.ADD_ALL);\n    }\n\n    @Override\n    boolean removeAllInternal(Collection<?> c) {\n        // Collection has been type-checked from caller\n        //noinspection unchecked\n        NativeRealmAnyCollection collection = NativeRealmAnyCollection.newUUIDCollection((Collection<UUID>) c);\n        return osSet.collectionFunnel(collection, OsSet.ExternalCollectionOperation.REMOVE_ALL);\n    }\n\n    @Override\n    boolean retainAllInternal(Collection<?> c) {\n        // Collection has been type-checked from caller\n        //noinspection unchecked\n        NativeRealmAnyCollection collection = NativeRealmAnyCollection.newUUIDCollection((Collection<UUID>) c);\n        return osSet.collectionFunnel(collection, OsSet.ExternalCollectionOperation.RETAIN_ALL);\n    }\n}\n\n/**\n * {@link SetValueOperator} targeting {@link RealmModel} values in {@link RealmSet}s.\n */\nclass RealmModelSetOperator<T extends RealmModel> extends SetValueOperator<T> {\n\n    RealmModelSetOperator(BaseRealm baseRealm, OsSet osSet, Class<T> valueClass) {\n        super(baseRealm, osSet, valueClass);\n    }\n\n    @Override\n    boolean add(T value) {\n        // Realm model sets cannot contain null values\n        RealmObjectProxy proxy = (RealmObjectProxy) getManagedObject(value);\n        Row row$realm = proxy.realmGet$proxyState().getRow$realm();\n        return osSet.addRow(row$realm.getObjectKey());\n    }\n\n    private T getManagedObject(T value) {\n        if (value == null) {\n            throw new NullPointerException(\"This set does not permit null values.\");\n        }\n        // Check we can add this object into the Realm\n        boolean copyObject = CollectionUtils.checkCanObjectBeCopied(baseRealm, value, valueClass.getName(), SET_TYPE);\n\n        // Add value into set\n        //noinspection unchecked\n        return (T) ((copyObject) ? CollectionUtils.copyToRealm(baseRealm, (RealmModel) value) : value);\n    }\n\n    /**\n     * Check that object is a valid and managed object by the set's Realm.\n     *\n     * @param value model object\n     */\n    private void checkValidObject(RealmModel value) {\n        // Realm model sets cannot contain null values\n        if (value == null) {\n            throw new NullPointerException(\"This set does not permit null values.\");\n        }\n        if (!RealmObject.isValid(value) || !RealmObject.isManaged(value)) {\n            throw new IllegalArgumentException(\"'value' is not a valid managed object.\");\n        }\n        if (((RealmObjectProxy) value).realmGet$proxyState().getRealm$realm() != baseRealm) {\n            throw new IllegalArgumentException(\"'value' belongs to a different Realm.\");\n        }\n    }\n\n    @Override\n    boolean containsInternal(Object value) {\n        checkValidObject((RealmModel) value);\n        Row row$realm = ((RealmObjectProxy) value).realmGet$proxyState().getRow$realm();\n        return osSet.containsRow(row$realm.getObjectKey());\n    }\n\n    @Override\n    boolean removeInternal(Object value) {\n        checkValidObject((RealmModel) value);\n        Row row$realm = ((RealmObjectProxy) value).realmGet$proxyState().getRow$realm();\n        return osSet.removeRow(row$realm.getObjectKey());\n    }\n\n    @Override\n    boolean containsAllInternal(Collection<?> collection) {\n        // Collection has been type-checked from caller\n        //noinspection unchecked\n        Collection<T> realmModelCollection = (Collection<T>) collection;\n        // All models must be managed and from the same set's Realm\n        checkValidCollection(realmModelCollection);\n        NativeRealmAnyCollection realmAnyCollection = NativeRealmAnyCollection.newRealmModelCollection(realmModelCollection);\n        return osSet.collectionFunnel(realmAnyCollection, OsSet.ExternalCollectionOperation.CONTAINS_ALL);\n    }\n\n    @Override\n    boolean addAllInternal(Collection<? extends T> collection) {\n        // Collection has been type-checked from caller\n        // Use add method as it contains all the necessary checks\n        List<T> managedRealmObjectCollection = new ArrayList<>(collection.size());\n        for (T item : collection) {\n            managedRealmObjectCollection.add(getManagedObject(item));\n        }\n        NativeRealmAnyCollection realmAnyCollection = NativeRealmAnyCollection.newRealmModelCollection(managedRealmObjectCollection);\n        return osSet.collectionFunnel(realmAnyCollection, OsSet.ExternalCollectionOperation.ADD_ALL);\n    }\n\n    @Override\n    boolean removeAllInternal(Collection<?> c) {\n        // Collection has been type-checked from caller\n        //noinspection unchecked\n        Collection<T> realmModelCollection = (Collection<T>) c;\n        checkValidCollection(realmModelCollection);\n        NativeRealmAnyCollection collection = NativeRealmAnyCollection.newRealmModelCollection(realmModelCollection);\n        return osSet.collectionFunnel(collection, OsSet.ExternalCollectionOperation.REMOVE_ALL);\n    }\n\n    @Override\n    boolean retainAllInternal(Collection<?> c) {\n        // Collection has been type-checked from caller\n        //noinspection unchecked\n        Collection<T> realmModelCollection = (Collection<T>) c;\n        checkValidCollection(realmModelCollection);\n        NativeRealmAnyCollection collection = NativeRealmAnyCollection.newRealmModelCollection(realmModelCollection);\n        return osSet.collectionFunnel(collection, OsSet.ExternalCollectionOperation.RETAIN_ALL);\n    }\n\n    private void checkValidCollection(Collection<? extends T> collection) {\n        for (T object : collection) {\n            checkValidObject(object);\n        }\n    }\n\n    @Override\n    RealmQuery<T> where() {\n        return new RealmQuery<>(baseRealm, osSet, valueClass);\n    }\n}\n\n/**\n * {@link SetValueOperator} targeting {@link RealmModel} values in {@link RealmSet}s.\n */\nclass DynamicSetOperator extends SetValueOperator<DynamicRealmObject> {\n    DynamicSetOperator(BaseRealm baseRealm, OsSet osSet, String className) {\n        super(baseRealm, osSet, DynamicRealmObject.class, className);\n    }\n\n    @Override\n    boolean add(DynamicRealmObject value) {\n        // Realm model sets cannot contain null values\n        RealmObjectProxy proxy = (RealmObjectProxy) getManagedObject(value);\n        Row row$realm = proxy.realmGet$proxyState().getRow$realm();\n        return osSet.addRow(row$realm.getObjectKey());\n    }\n\n    private DynamicRealmObject getManagedObject(DynamicRealmObject value) {\n        if (value == null) {\n            throw new NullPointerException(\"This set does not permit null values.\");\n        }\n        // Check we can add this object into the Realm\n        boolean copyObject = CollectionUtils.checkCanObjectBeCopied(baseRealm, value, className, SET_TYPE);\n\n        // Add value into set\n        //noinspection unchecked\n        return (DynamicRealmObject) ((copyObject) ? CollectionUtils.copyToRealm(baseRealm, (RealmModel) value) : value);\n    }\n\n    /**\n     * Check that object is a valid and managed object by the set's Realm.\n     *\n     * @param value model object\n     */\n    private void checkValidObject(RealmModel value) {\n        // Realm model sets cannot contain null values\n        if (value == null) {\n            throw new NullPointerException(\"This set does not permit null values.\");\n        }\n        if (!RealmObject.isValid(value) || !RealmObject.isManaged(value)) {\n            throw new IllegalArgumentException(\"'value' is not a valid managed object.\");\n        }\n        if (((RealmObjectProxy) value).realmGet$proxyState().getRealm$realm() != baseRealm) {\n            throw new IllegalArgumentException(\"'value' belongs to a different Realm.\");\n        }\n    }\n\n    @Override\n    boolean containsInternal(Object value) {\n        checkValidObject((RealmModel) value);\n        Row row$realm = ((RealmObjectProxy) value).realmGet$proxyState().getRow$realm();\n        return osSet.containsRow(row$realm.getObjectKey());\n    }\n\n    @Override\n    boolean removeInternal(Object value) {\n        checkValidObject((RealmModel) value);\n        Row row$realm = ((RealmObjectProxy) value).realmGet$proxyState().getRow$realm();\n        return osSet.removeRow(row$realm.getObjectKey());\n    }\n\n    @Override\n    boolean containsAllInternal(Collection<?> collection) {\n        // Collection has been type-checked from caller\n        //noinspection unchecked\n        Collection<DynamicRealmObject> realmModelCollection = (Collection<DynamicRealmObject>) collection;\n        // All models must be managed and from the same set's Realm\n        checkValidCollection(realmModelCollection);\n        NativeRealmAnyCollection realmAnyCollection = NativeRealmAnyCollection.newRealmModelCollection(realmModelCollection);\n        return osSet.collectionFunnel(realmAnyCollection, OsSet.ExternalCollectionOperation.CONTAINS_ALL);\n    }\n\n    @Override\n    boolean addAllInternal(Collection<? extends DynamicRealmObject> collection) {\n        // Collection has been type-checked from caller\n        // Use add method as it contains all the necessary checks\n        List<DynamicRealmObject> managedRealmObjectCollection = new ArrayList<>(collection.size());\n        for (DynamicRealmObject item : collection) {\n            managedRealmObjectCollection.add(getManagedObject(item));\n        }\n        NativeRealmAnyCollection realmAnyCollection = NativeRealmAnyCollection.newRealmModelCollection(managedRealmObjectCollection);\n        return osSet.collectionFunnel(realmAnyCollection, OsSet.ExternalCollectionOperation.ADD_ALL);\n    }\n\n    @Override\n    boolean removeAllInternal(Collection<?> c) {\n        // Collection has been type-checked from caller\n        //noinspection unchecked\n        Collection<DynamicRealmObject> realmModelCollection = (Collection<DynamicRealmObject>) c;\n        checkValidCollection(realmModelCollection);\n        NativeRealmAnyCollection collection = NativeRealmAnyCollection.newRealmModelCollection(realmModelCollection);\n        return osSet.collectionFunnel(collection, OsSet.ExternalCollectionOperation.REMOVE_ALL);\n    }\n\n    @Override\n    boolean retainAllInternal(Collection<?> c) {\n        // Collection has been type-checked from caller\n        //noinspection unchecked\n        Collection<DynamicRealmObject> realmModelCollection = (Collection<DynamicRealmObject>) c;\n        checkValidCollection(realmModelCollection);\n        NativeRealmAnyCollection collection = NativeRealmAnyCollection.newRealmModelCollection(realmModelCollection);\n        return osSet.collectionFunnel(collection, OsSet.ExternalCollectionOperation.RETAIN_ALL);\n    }\n\n    private void checkValidCollection(Collection<? extends DynamicRealmObject> collection) {\n        for (DynamicRealmObject object : collection) {\n            checkValidObject(object);\n        }\n    }\n\n    @Override\n    RealmQuery<DynamicRealmObject> where() {\n        return new RealmQuery<>(baseRealm, osSet, valueClass);\n    }\n}\n\n/**\n * {@link SetValueOperator} targeting {@link RealmAny} values in {@link RealmSet}s.\n */\nclass RealmAnySetOperator extends SetValueOperator<RealmAny> {\n\n    RealmAnySetOperator(BaseRealm baseRealm, OsSet osSet, Class<RealmAny> valueClass) {\n        super(baseRealm, osSet, valueClass);\n    }\n\n    @Override\n    boolean add(@Nullable RealmAny value) {\n        value = getManagedRealmAny(value);\n        return osSet.addRealmAny(value.getNativePtr());\n    }\n\n    @NotNull\n    private RealmAny getManagedRealmAny(@Nullable RealmAny value) {\n        if (value == null) {\n            value = RealmAny.nullValue();\n        } else if (value.getType() == RealmAny.Type.OBJECT) {\n            RealmModel realmModel = value.asRealmModel(RealmModel.class);\n            boolean copyObject = CollectionUtils.checkCanObjectBeCopied(baseRealm, realmModel, valueClass.getName(), SET_TYPE);\n            RealmObjectProxy proxy = (RealmObjectProxy) ((copyObject) ? CollectionUtils.copyToRealm(baseRealm, realmModel) : realmModel);\n            value = RealmAny.valueOf(proxy);\n        }\n        return value;\n    }\n\n    @Override\n    boolean containsInternal(@Nullable Object o) {\n        RealmAny value;\n        if (o == null) {\n            value = RealmAny.nullValue();\n        } else {\n            value = (RealmAny) o;\n        }\n        checkValidObject(value);\n        return osSet.containsRealmAny(value.getNativePtr());\n    }\n\n    @Override\n    boolean removeInternal(@Nullable Object o) {\n        // Object has been type-checked from caller\n        RealmAny value;\n        if (o == null) {\n            value = RealmAny.nullValue();\n        } else {\n            value = (RealmAny) o;\n        }\n        checkValidObject(value);\n        return osSet.removeRealmAny(value.getNativePtr());\n    }\n\n    @NotNull\n    private NativeRealmAnyCollection getNativeRealmAnyCollection(Collection<? extends RealmAny> realmAnyCollection) {\n        long[] realmAnyPtrs = new long[realmAnyCollection.size()];\n        boolean[] notNull = new boolean[realmAnyCollection.size()];\n\n        int i = 0;\n        for (RealmAny realmAny : realmAnyCollection) {\n            if (realmAny != null) {\n                checkValidObject(realmAny);\n                realmAnyPtrs[i] = realmAny.getNativePtr();\n                notNull[i] = true;\n            }\n            i++;\n        }\n\n        return NativeRealmAnyCollection.newRealmAnyCollection(realmAnyPtrs, notNull);\n    }\n\n    @Override\n    boolean containsAllInternal(Collection<?> c) {\n        // Collection has been type-checked from caller\n        //noinspection unchecked\n        NativeRealmAnyCollection collection = getNativeRealmAnyCollection((Collection<RealmAny>) c);\n        return osSet.collectionFunnel(collection, OsSet.ExternalCollectionOperation.CONTAINS_ALL);\n    }\n\n    @Override\n    boolean addAllInternal(Collection<? extends RealmAny> collection) {\n        // Collection has been type-checked from caller\n        List<RealmAny> managedRealmAnyCollection = new ArrayList<>(collection.size());\n        for (RealmAny realmAny : collection) {\n            managedRealmAnyCollection.add(getManagedRealmAny(realmAny));\n        }\n        NativeRealmAnyCollection nativeRealmAnyCollection = getNativeRealmAnyCollection(managedRealmAnyCollection);\n        return osSet.collectionFunnel(nativeRealmAnyCollection, OsSet.ExternalCollectionOperation.ADD_ALL);\n    }\n\n    @Override\n    boolean removeAllInternal(Collection<?> c) {\n        // Collection has been type-checked from caller\n        //noinspection unchecked\n        NativeRealmAnyCollection collection = getNativeRealmAnyCollection((Collection<RealmAny>) c);\n        return osSet.collectionFunnel(collection, OsSet.ExternalCollectionOperation.REMOVE_ALL);\n    }\n\n    @Override\n    boolean retainAllInternal(Collection<?> c) {\n        // Collection has been type-checked from caller\n        //noinspection unchecked\n        NativeRealmAnyCollection collection = getNativeRealmAnyCollection((Collection<RealmAny>) c);\n        return osSet.collectionFunnel(collection, OsSet.ExternalCollectionOperation.RETAIN_ALL);\n    }\n\n    private void checkValidObject(RealmAny realmAny) {\n        try {\n            realmAny.checkValidObject(baseRealm);\n        } catch (IllegalArgumentException exception) {\n            throw new IllegalArgumentException(\"RealmAny collection contains unmanaged objects.\", exception);\n        }\n    }\n}\n\n/**\n * Base iterator for {@link RealmSet}s.\n *\n * @param <E> the value type.\n */\nabstract class SetIterator<E> implements Iterator<E> {\n\n    protected final OsSet osSet;\n    protected final BaseRealm baseRealm;\n\n    private int pos = -1;\n\n    SetIterator(OsSet osSet, BaseRealm baseRealm) {\n        this.osSet = osSet;\n        this.baseRealm = baseRealm;\n    }\n\n    @Override\n    public boolean hasNext() {\n        return pos + 1 < osSet.size();\n    }\n\n    @Override\n    public E next() {\n        pos++;\n        long size = osSet.size();\n        if (pos >= size) {\n            throw new NoSuchElementException(\"Cannot access index \" + pos + \" when size is \" + size +\n                    \". Remember to check hasNext() before using next().\");\n        }\n\n        return getValueAtIndex(pos);\n    }\n\n    // Some types might want to override this to convert/typecast the value correctly\n    protected E getValueAtIndex(int position) {\n        //noinspection unchecked\n        return (E) osSet.getValueAtIndex(position);\n    }\n}\n\n/**\n * Set iterator for {@code boolean} values.\n */\nclass BooleanSetIterator extends SetIterator<Boolean> {\n    BooleanSetIterator(OsSet osSet, BaseRealm baseRealm) {\n        super(osSet, baseRealm);\n    }\n}\n\n/**\n * Set iterator for {@link String} values.\n */\nclass StringSetIterator extends SetIterator<String> {\n    StringSetIterator(OsSet osSet, BaseRealm baseRealm) {\n        super(osSet, baseRealm);\n    }\n}\n\n/**\n * Set iterator for {@code int} values.\n */\nclass IntegerSetIterator extends SetIterator<Integer> {\n    IntegerSetIterator(OsSet osSet, BaseRealm baseRealm) {\n        super(osSet, baseRealm);\n    }\n\n    @Override\n    protected Integer getValueAtIndex(int position) {\n        Object value = osSet.getValueAtIndex(position);\n        if (value == null) {\n            return null;\n        }\n\n        Long valueAtIndex = (Long) value;\n        return valueAtIndex.intValue();\n    }\n}\n\n/**\n * Set iterator for {@code long} values.\n */\nclass LongSetIterator extends SetIterator<Long> {\n    LongSetIterator(OsSet osSet, BaseRealm baseRealm) {\n        super(osSet, baseRealm);\n    }\n}\n\n/**\n * Set iterator for {@code short} values.\n */\nclass ShortSetIterator extends SetIterator<Short> {\n    ShortSetIterator(OsSet osSet, BaseRealm baseRealm) {\n        super(osSet, baseRealm);\n    }\n\n    @Override\n    protected Short getValueAtIndex(int position) {\n        Object value = osSet.getValueAtIndex(position);\n        if (value == null) {\n            return null;\n        }\n\n        Long longValue = (Long) value;\n        return longValue.shortValue();\n    }\n}\n\n/**\n * Set iterator for {@code byte} values.\n */\nclass ByteSetIterator extends SetIterator<Byte> {\n    ByteSetIterator(OsSet osSet, BaseRealm baseRealm) {\n        super(osSet, baseRealm);\n    }\n\n    @Override\n    protected Byte getValueAtIndex(int position) {\n        Object value = osSet.getValueAtIndex(position);\n        if (value == null) {\n            return null;\n        }\n\n        Long longValue = (Long) value;\n        return longValue.byteValue();\n    }\n}\n\n/**\n * Set iterator for {@code float} values.\n */\nclass FloatSetIterator extends SetIterator<Float> {\n    FloatSetIterator(OsSet osSet, BaseRealm baseRealm) {\n        super(osSet, baseRealm);\n    }\n}\n\n/**\n * Set iterator for {@code double} values.\n */\nclass DoubleSetIterator extends SetIterator<Double> {\n    DoubleSetIterator(OsSet osSet, BaseRealm baseRealm) {\n        super(osSet, baseRealm);\n    }\n}\n\n/**\n * Set iterator for {@code byte[]} values.\n */\nclass BinarySetIterator extends SetIterator<byte[]> {\n    BinarySetIterator(OsSet osSet, BaseRealm baseRealm) {\n        super(osSet, baseRealm);\n    }\n\n    @Override\n    protected byte[] getValueAtIndex(int position) {\n        Object value = osSet.getValueAtIndex(position);\n        if (value == null) {\n            return null;\n        }\n\n        return (byte[]) value;\n    }\n}\n\n/**\n * Set iterator for {@link Date} values.\n */\nclass DateSetIterator extends SetIterator<Date> {\n    DateSetIterator(OsSet osSet, BaseRealm baseRealm) {\n        super(osSet, baseRealm);\n    }\n}\n\n/**\n * Set iterator for {@link Decimal128} values.\n */\nclass Decimal128SetIterator extends SetIterator<Decimal128> {\n    Decimal128SetIterator(OsSet osSet, BaseRealm baseRealm) {\n        super(osSet, baseRealm);\n    }\n}\n\n/**\n * Set iterator for {@link ObjectId} values.\n */\nclass ObjectIdSetIterator extends SetIterator<ObjectId> {\n    ObjectIdSetIterator(OsSet osSet, BaseRealm baseRealm) {\n        super(osSet, baseRealm);\n    }\n}\n\n/**\n * Set iterator for {@link UUID} values.\n */\nclass UUIDSetIterator extends SetIterator<UUID> {\n    UUIDSetIterator(OsSet osSet, BaseRealm baseRealm) {\n        super(osSet, baseRealm);\n    }\n}\n\n/**\n * Set iterator for {@link RealmAny} values.\n */\nclass RealmAnySetIterator extends SetIterator<RealmAny> {\n    RealmAnySetIterator(OsSet osSet, BaseRealm baseRealm) {\n        super(osSet, baseRealm);\n    }\n\n    @Override\n    protected RealmAny getValueAtIndex(int position) {\n        NativeRealmAny nativeRealmAny = new NativeRealmAny(osSet.getRealmAny(position));\n        return new RealmAny(RealmAnyOperator.fromNativeRealmAny(baseRealm, nativeRealmAny));\n    }\n}\n\n/**\n * Set iterator for {@link RealmModel} values.\n */\nclass RealmModelSetIterator<T extends RealmModel> extends SetIterator<T> {\n\n    private final Class<T> valueClass;\n\n    RealmModelSetIterator(OsSet osSet, BaseRealm baseRealm, Class<T> valueClass) {\n        super(osSet, baseRealm);\n        this.valueClass = valueClass;\n    }\n\n    @Override\n    protected T getValueAtIndex(int position) {\n        long rowPtr = osSet.getRow(position);\n        return baseRealm.get(valueClass, rowPtr, false, new ArrayList<>());\n    }\n}\n\n/**\n * Set iterator for {@link DynamicRealmObject} values.\n */\nclass DynamicSetIterator extends SetIterator<DynamicRealmObject> {\n\n    private final String className;\n\n    DynamicSetIterator(OsSet osSet, BaseRealm baseRealm, String className) {\n        super(osSet, baseRealm);\n        this.className = className;\n    }\n\n    @Override\n    protected DynamicRealmObject getValueAtIndex(int position) {\n        long rowPtr = osSet.getRow(position);\n        return baseRealm.get(DynamicRealmObject.class, className, rowPtr);\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/Sort.java",
    "content": "/*\n * Copyright 2015 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\npackage io.realm;\n\n/**\n * This class describes the sorting order used in Realm queries.\n *\n * @see io.realm.RealmQuery#sort(String, Sort)\n */\npublic enum Sort {\n    ASCENDING(true),\n    DESCENDING(false);\n\n    private final boolean value;\n\n    Sort(boolean value) {\n        this.value = value;\n    }\n\n    /**\n     * Returns the value for this setting that is used by the underlying query engine.\n     *\n     * @return the value used by the underlying query engine to indicate this value.\n     */\n    public boolean getValue() {\n        return value;\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/TypeSelectorForMap.java",
    "content": "/*\n * Copyright 2020 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\npackage io.realm;\n\nimport java.util.AbstractMap;\nimport java.util.ArrayList;\nimport java.util.Collection;\nimport java.util.HashSet;\nimport java.util.Map;\nimport java.util.Set;\n\nimport javax.annotation.Nullable;\n\nimport io.realm.internal.OsMap;\nimport io.realm.internal.OsResults;\nimport io.realm.internal.RealmObjectProxy;\nimport io.realm.internal.Table;\nimport io.realm.internal.util.Pair;\n\nimport static io.realm.CollectionUtils.DICTIONARY_TYPE;\n\n\n/**\n * Abstracts certain operations from value operators depending on the type of Realm we are working\n * with.\n *\n * @param <K> the key type\n * @param <V> the value type\n */\nabstract class TypeSelectorForMap<K, V> {\n\n    protected final BaseRealm baseRealm;\n    protected final OsMap osMap;\n\n    TypeSelectorForMap(BaseRealm baseRealm, OsMap osMap) {\n        this.baseRealm = baseRealm;\n        this.osMap = osMap;\n    }\n\n    protected V getRealmModel(BaseRealm baseRealm, long realmModelKey) {\n        throw new UnsupportedOperationException(\"Function 'getRealmModel' can only be called from 'LinkSelectorForMap' instances.\");\n    }\n\n    protected V putRealmModel(BaseRealm baseRealm, OsMap osMap, K key, @Nullable V value) {\n        throw new UnsupportedOperationException(\"Function 'putRealmModel' can only be called from 'LinkSelectorForMap' instances.\");\n    }\n\n    protected Map.Entry<K, V> getModelEntry(BaseRealm baseRealm, long objRow, K key) {\n        throw new UnsupportedOperationException(\"Function 'getModelEntry' can only be called from 'LinkSelectorForMap' instances.\");\n    }\n\n    abstract Set<K> keySet();\n\n    abstract Collection<V> getValues();\n\n    abstract RealmDictionary<V> freeze(BaseRealm frozenBaseRealm);\n\n    abstract String getValueClassName();\n\n    abstract Class<V> getValueClass();\n}\n\n/**\n * Implementation for ordinary Realms.\n */\nclass SelectorForMap<K, V> extends TypeSelectorForMap<K, V> {\n\n    protected final Class<K> keyClass;\n    protected final Class<V> valueClass;\n\n    SelectorForMap(BaseRealm baseRealm,\n                          OsMap osMap,\n                          Class<K> keyClass,\n                          Class<V> valueClass) {\n        super(baseRealm, osMap);\n        this.keyClass = keyClass;\n        this.valueClass = valueClass;\n    }\n\n    @Override\n    public Set<K> keySet() {\n        return new HashSet<>(produceResults(baseRealm, osMap.tableAndKeyPtrs(), true, keyClass));\n    }\n\n    @Override\n    public Collection<V> getValues() {\n        boolean forPrimitives = !CollectionUtils.isClassForRealmModel(valueClass);\n        return produceResults(baseRealm, osMap.tableAndValuePtrs(), forPrimitives, valueClass);\n    }\n\n    @Override\n    public RealmDictionary<V> freeze(BaseRealm frozenBaseRealm) {\n        return new RealmDictionary<>(frozenBaseRealm, osMap, valueClass);\n    }\n\n    // Do not use <K> or <V> as this method can be used for either keys or values\n    private <T> RealmResults<T> produceResults(BaseRealm baseRealm,\n                                               Pair<Table, Long> tableAndValuesPtr,\n                                               boolean forPrimitives,\n                                               Class<T> clazz) {\n        Long valuesPtr = tableAndValuesPtr.second;\n        OsResults osResults = OsResults.createFromMap(baseRealm.sharedRealm, valuesPtr);\n        return new RealmResults<>(baseRealm, osResults, clazz, forPrimitives);\n    }\n\n    @Override\n    Class<V> getValueClass() {\n        return valueClass;\n    }\n\n    @Override\n    String getValueClassName() {\n        return valueClass.getSimpleName();\n    }\n}\n\n/**\n * Implementation for ordinary Realms in case we are working with RealmModels.\n */\nclass LinkSelectorForMap<K, V extends RealmModel> extends SelectorForMap<K, V> {\n\n    LinkSelectorForMap(BaseRealm baseRealm, OsMap osMap, Class<K> keyClass, Class<V> valueClass) {\n        super(baseRealm, osMap, keyClass, valueClass);\n    }\n\n    @Override\n    public V getRealmModel(BaseRealm baseRealm, long realmModelKey) {\n        return baseRealm.get(valueClass, null, realmModelKey);\n    }\n\n    @Override\n    public V putRealmModel(BaseRealm baseRealm, OsMap osMap, K key, @Nullable V value) {\n        long rowModelKey = osMap.getModelRowKey(key);\n\n        if (value == null) {\n            osMap.put(key, null);\n        } else {\n            boolean isEmbedded = baseRealm.getSchema().getSchemaForClass(valueClass).isEmbedded();\n            if (isEmbedded) {\n                long objKey = osMap.createAndPutEmbeddedObject(key);\n                CollectionUtils.updateEmbeddedObject((Realm) baseRealm, value, objKey);\n            } else {\n                boolean copyObject = CollectionUtils.checkCanObjectBeCopied(baseRealm, value, valueClass.getSimpleName(), DICTIONARY_TYPE);\n                RealmObjectProxy proxy = (RealmObjectProxy) ((copyObject) ? CollectionUtils.copyToRealm(baseRealm, value) : value);\n                osMap.putRow(key, proxy.realmGet$proxyState().getRow$realm().getObjectKey());\n            }\n        }\n\n        if (rowModelKey == OsMap.NOT_FOUND) {\n            return null;\n        } else {\n            return (V) baseRealm.get(valueClass, rowModelKey, false, new ArrayList<>());\n        }\n    }\n\n    @Override\n    public Map.Entry<K, V> getModelEntry(BaseRealm baseRealm, long objRow, K key) {\n        V realmModel = baseRealm.get(valueClass, null, objRow);\n        return new AbstractMap.SimpleImmutableEntry<>(key, realmModel);\n    }\n}\n\n/**\n * Implementation for DynamicRealms.\n */\nclass DynamicSelectorForMap<K> extends TypeSelectorForMap<K, DynamicRealmObject> {\n\n    private final String className;\n\n    DynamicSelectorForMap(BaseRealm baseRealm,\n                                 OsMap osMap,\n                                 String className) {\n        super(baseRealm, osMap);\n        this.className = className;\n    }\n\n    @Override\n    public DynamicRealmObject getRealmModel(BaseRealm baseRealm, long realmModelKey) {\n        return baseRealm.get(DynamicRealmObject.class, className, realmModelKey);\n    }\n\n    @Override\n    public DynamicRealmObject putRealmModel(BaseRealm baseRealm, OsMap osMap, K key, @Nullable DynamicRealmObject value) {\n        long rowModelKey = osMap.getModelRowKey(key);\n\n        if (value == null) {\n            osMap.put(key, null);\n        } else {\n            boolean isEmbedded = baseRealm.getSchema().getSchemaForClass(className).isEmbedded();\n            if (isEmbedded) {\n                long objKey = osMap.createAndPutEmbeddedObject(key);\n                CollectionUtils.updateEmbeddedObject((Realm) baseRealm, value, objKey);\n            } else {\n                boolean copyObject = CollectionUtils.checkCanObjectBeCopied(baseRealm, value, className, DICTIONARY_TYPE);\n                RealmObjectProxy proxy = (RealmObjectProxy) ((copyObject) ? CollectionUtils.copyToRealm(baseRealm, value) : value);\n                osMap.putRow(key, proxy.realmGet$proxyState().getRow$realm().getObjectKey());\n            }\n        }\n\n        if (rowModelKey == OsMap.NOT_FOUND) {\n            return null;\n        } else {\n            return baseRealm.get(DynamicRealmObject.class, className, rowModelKey);\n        }\n    }\n\n    // Do not use <K> or <V> as this method can be used for either keys or values\n    private <T> RealmResults<T> produceResults(BaseRealm baseRealm,\n            Pair<Table, Long> tableAndValuesPtr,\n            String className) {\n        Long valuesPtr = tableAndValuesPtr.second;\n        OsResults osResults = OsResults.createFromMap(baseRealm.sharedRealm, valuesPtr);\n        return new RealmResults<>(baseRealm, osResults, className, false);\n    }\n\n    @Override\n    public Map.Entry<K, DynamicRealmObject> getModelEntry(BaseRealm baseRealm, long objRow, K key) {\n        DynamicRealmObject realmModel = baseRealm.get(DynamicRealmObject.class, className, objRow);\n        return new AbstractMap.SimpleImmutableEntry<>(key, realmModel);\n    }\n\n    @Override\n    public Set<K> keySet() {\n        return new HashSet<>(produceResults(baseRealm, osMap.tableAndKeyPtrs(), className));\n    }\n\n    @Override\n    public Collection<DynamicRealmObject> getValues() {\n        return produceResults(baseRealm, osMap.tableAndValuePtrs(), className);\n    }\n\n    @Override\n    public RealmDictionary<DynamicRealmObject> freeze(BaseRealm frozenBaseRealm) {\n        return new RealmDictionary<>(frozenBaseRealm, osMap, className);\n    }\n\n    @Override\n    Class<DynamicRealmObject> getValueClass() {\n        return DynamicRealmObject.class;\n    }\n\n    @Override\n    String getValueClassName() {\n        return className;\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/coroutines/FlowFactory.java",
    "content": "/*\n * Copyright 2020 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\npackage io.realm.coroutines;\n\nimport javax.annotation.Nonnull;\n\nimport io.reactivex.Observable;\nimport io.realm.DynamicRealm;\nimport io.realm.DynamicRealmObject;\nimport io.realm.Realm;\nimport io.realm.RealmList;\nimport io.realm.RealmModel;\nimport io.realm.RealmObject;\nimport io.realm.RealmResults;\nimport io.realm.annotations.Beta;\nimport io.realm.rx.CollectionChange;\nimport io.realm.rx.ObjectChange;\nimport kotlinx.coroutines.flow.Flow;\n\n/**\n * Factory interface for creating Kotlin {@link Flow}s for Realm classes.\n */\n@Beta\npublic interface FlowFactory {\n\n    /**\n     * Creates a {@link Flow} for a {@link Realm}. It should emit the initial state of the Realm when subscribed to and\n     * on each subsequent update of the Realm.\n     *\n     * @param realm {@link Realm} instance being observed for changes to be emitted by the flow.\n     * @return Flow that emits all updates to the Realm.\n     */\n    @Beta\n    Flow<Realm> from(@Nonnull Realm realm);\n\n    /**\n     * Creates a {@link Flow} for a {@link DynamicRealm}. It should emit the initial state of the Realm when subscribed to and\n     * on each subsequent update of the Realm.\n     *\n     * @param dynamicRealm {@link DynamicRealm} instance being observed for changes to be emitted by the flow.\n     * @return Flow that emits all updates to the Realm.\n     */\n    @Beta\n    Flow<DynamicRealm> from(@Nonnull DynamicRealm dynamicRealm);\n\n    /**\n     * Creates a {@link Flow} for a {@link RealmResults}. It should emit the initial RealmResult when subscribed to and\n     * on each subsequent update of the RealmResults.\n     *\n     * @param results {@link RealmResults} instance being observed for changes to be emitted by the flow.\n     * @param realm   {@link Realm} instance from where the results are coming.\n     * @param <T>     type of RealmObject.\n     * @return {@link Flow} that emits all updates to the RealmObject.\n     */\n    @Beta\n    <T> Flow<RealmResults<T>> from(@Nonnull Realm realm, @Nonnull RealmResults<T> results);\n\n    /**\n     * Creates a {@link Flow} for a {@link RealmResults} instance. It should emit the initial results when subscribed to and on each\n     * subsequent update of the results it should emit the results plus the {@link io.realm.rx.CollectionChange} that describes\n     * the update.\n     * <p>\n     * Changeset observables do not support backpressure as a changeset depends on the state of the previous\n     * changeset. Handling backpressure should therefore be left to the user.\n     *\n     * @param realm   {@link Realm} instance from where the object is coming.\n     * @param results {@link RealmResults} instance being observed for changes to be emitted by the flow.\n     * @return {@link Flow} that emits all updates to the RealmResults.\n     */\n    @Beta\n    <T> Flow<CollectionChange<RealmResults<T>>> changesetFrom(@Nonnull Realm realm, @Nonnull RealmResults<T> results);\n\n    /**\n     * Creates a {@link Flow} for a {@link RealmResults}. It should emit the initial RealmResult when subscribed to and\n     * on each subsequent update of the RealmResults.\n     *\n     * @param results      {@link RealmResults} instance being observed for changes to be emitted by the flow.\n     * @param dynamicRealm {@link DynamicRealm} instance from where the results are coming.\n     * @param <T>          type of RealmObject.\n     * @return {@link Flow} that emits all updates to the RealmObject.\n     */\n    @Beta\n    <T> Flow<RealmResults<T>> from(@Nonnull DynamicRealm dynamicRealm, @Nonnull RealmResults<T> results);\n\n    /**\n     * Creates a {@link Flow} for a {@link RealmResults} instance. It should emit the initial results when subscribed to and on each\n     * subsequent update of the results it should emit the results plus the {@link io.realm.rx.CollectionChange} that describes\n     * the update.\n     * <p>\n     * Changeset observables do not support backpressure as a changeset depends on the state of the previous\n     * changeset. Handling backpressure should therefore be left to the user.\n     *\n     * @param dynamicRealm {@link DynamicRealm} instance from where the object is coming.\n     * @param results      {@link RealmResults} instance being observed for changes to be emitted by the flow.\n     * @return {@link Flow} that emits all updates to the RealmResults.\n     */\n    @Beta\n    <T> Flow<CollectionChange<RealmResults<T>>> changesetFrom(@Nonnull DynamicRealm dynamicRealm, @Nonnull RealmResults<T> results);\n\n    /**\n     * Creates a {@link Flow} for a {@link RealmList}. It should emit the initial RealmResult when subscribed to and\n     * on each subsequent update of the RealmList.\n     * <p>\n     * Note: {@link io.realm.RealmChangeListener} is currently not supported on RealmLists.\n     *\n     * @param realmList {@link RealmList} instance being observed for changes to be emitted by the flow.\n     * @param realm     {@link Realm} instance from where the results are coming.\n     * @param <T>       type of RealmObject\n     * @return {@link Flow} that emit all updates to the RealmList.\n     */\n    @Beta\n    <T> Flow<RealmList<T>> from(@Nonnull Realm realm, @Nonnull RealmList<T> realmList);\n\n    /**\n     * Creates a {@link Flow} for a {@link RealmList}. It should emit the initial list when subscribed to and on each\n     * subsequent update of the list it should emit the list plus the {@link io.realm.rx.CollectionChange} that describes\n     * the update.\n     * <p>\n     * Changeset observables do not support backpressure as a changeset depends on the state of the previous\n     * changeset. Handling backpressure should therefore be left to the user.\n     *\n     * @param realm {@link Realm} instance from where the object is coming.\n     * @param list  {@link RealmList} instance being observed for changes to be emitted by the flow.\n     * @return {@link Flow} that emits all updates to the RealmList.\n     */\n    @Beta\n    <T> Flow<CollectionChange<RealmList<T>>> changesetFrom(@Nonnull Realm realm, @Nonnull RealmList<T> list);\n\n    /**\n     * Creates a {@link Flow} for a {@link RealmList}. It should emit the initial RealmResult when subscribed to and\n     * on each subsequent update of the RealmList.\n     * <p>\n     * Note: {@link io.realm.RealmChangeListener} is currently not supported on RealmLists.\n     *\n     * @param realmList    {@link RealmList} instance being observed for changes to be emitted by the flow.\n     * @param dynamicRealm {@link DynamicRealm} instance from where the results are coming.\n     * @param <T>          type of RealmObject\n     * @return {@link Flow} that emit all updates to the RealmList.\n     */\n    @Beta\n    <T> Flow<RealmList<T>> from(@Nonnull DynamicRealm dynamicRealm, @Nonnull RealmList<T> realmList);\n\n    /**\n     * Creates a {@link Flow} for a {@link RealmList}. It should emit the initial list when subscribed to and on each\n     * subsequent update of the list it should emit the list plus the {@link io.realm.rx.CollectionChange} that describes\n     * the update.\n     * <p>\n     * Changeset observables do not support backpressure as a changeset depends on the state of the previous\n     * changeset. Handling backpressure should therefore be left to the user.\n     *\n     * @param dynamicRealm {@link DynamicRealm} instance from where the object is coming.\n     * @param list         {@link RealmList} instance being observed for changes to be emitted by the flow.\n     * @return {@link Flow} that emits all updates to the RealmList.\n     */\n    @Beta\n    <T> Flow<CollectionChange<RealmList<T>>> changesetFrom(@Nonnull DynamicRealm dynamicRealm, @Nonnull RealmList<T> list);\n\n    /**\n     * Creates a {@link Flow} for a {@link RealmObject}. It should emit the initial object when subscribed to and on each\n     * subsequent update of the object.\n     *\n     * @param realmObject {@link RealmObject} instance being observed for changes to be emitted by the flow.\n     * @param realm       {@link Realm} instance from where the object is coming.\n     * @param <T>         type of query target\n     * @return {@link Flow} that emits all updates to the DynamicRealmObject.\n     */\n    @Beta\n    <T extends RealmModel> Flow<T> from(@Nonnull Realm realm, @Nonnull T realmObject);\n\n    /**\n     * Creates a {@link Flow} for a {@link RealmObject}. It should emit the initial object when subscribed to and on each\n     * subsequent update of the object it should emit the object plus the {@link io.realm.ObjectChangeSet} that describes\n     * the update.\n     * <p>\n     * Changeset observables do not support backpressure as a changeset depends on the state of the previous\n     * changeset. Handling backpressure should therefore be left to the user.\n     *\n     * @param realm       {@link Realm} instance from where the object is coming.\n     * @param realmObject {@link RealmObject} instance being observed for changes to be emitted by the flow.\n     * @return {@link Flow} that emits all updates to the DynamicRealmObject.\n     */\n    @Beta\n    <T extends RealmModel> Flow<ObjectChange<T>> changesetFrom(@Nonnull Realm realm, @Nonnull T realmObject);\n\n    /**\n     * Creates a {@link Flow} for a {@link DynamicRealmObject}. It should emit the initial object when subscribed to and\n     * on each subsequent update of the object.\n     *\n     * @param dynamicRealm       {@link DynamicRealm} instance from where the object is coming.\n     * @param dynamicRealmObject {@link DynamicRealmObject} instance being observed for changes to be emitted by the flow.\n     * @return {@link Flow} that emits all updates to the DynamicRealmObject.\n     */\n    @Beta\n    Flow<DynamicRealmObject> from(@Nonnull DynamicRealm dynamicRealm, @Nonnull DynamicRealmObject dynamicRealmObject);\n\n    /**\n     * Creates a {@link Flow} for a {@link DynamicRealmObject}. It should emit the initial object when subscribed to and on each\n     * subsequent update of the object it should emit the object plus the {@link io.realm.ObjectChangeSet} that describes\n     * the update.\n     * <p>\n     * Changeset observables do not support backpressure as a changeset depends on the state of the previous\n     * changeset. Handling backpressure should therefore be left to the user.\n     *\n     * @param dynamicRealm       {@link DynamicRealm} instance from where the object is coming.\n     * @param dynamicRealmObject {@link DynamicRealmObject} instance being observed for changes to be emitted by the flow.\n     * @return {@link Flow} that emits all updates to the DynamicRealmObject.\n     */\n    @Beta\n    Flow<ObjectChange<DynamicRealmObject>> changesetFrom(@Nonnull DynamicRealm dynamicRealm, @Nonnull DynamicRealmObject dynamicRealmObject);\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/coroutines/RealmFlowFactory.java",
    "content": "/*\n * Copyright 2020 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\npackage io.realm.coroutines;\n\nimport javax.annotation.Nonnull;\n\nimport io.realm.DynamicRealm;\nimport io.realm.DynamicRealmObject;\nimport io.realm.Realm;\nimport io.realm.RealmList;\nimport io.realm.RealmModel;\nimport io.realm.RealmResults;\nimport io.realm.annotations.Beta;\nimport io.realm.internal.coroutines.InternalFlowFactory;\nimport io.realm.rx.CollectionChange;\nimport io.realm.rx.ObjectChange;\nimport kotlinx.coroutines.flow.Flow;\n\n/**\n * Factory class used to create coroutine {@link Flow}s.\n * <p>\n * This class is used by default unless overridden in {@link io.realm.RealmConfiguration.Builder#flowFactory(FlowFactory)}.\n */\n@Beta\npublic class RealmFlowFactory implements FlowFactory {\n\n    private final InternalFlowFactory factory;\n\n    /**\n     * Constructor for the Flow factory.\n     *\n     * @param returnFrozenObjects whether the emissions should return frozen objects or not.\n     */\n    public RealmFlowFactory(Boolean returnFrozenObjects) {\n        this.factory = new InternalFlowFactory(returnFrozenObjects);\n    }\n\n    @Override\n    public Flow<Realm> from(@Nonnull Realm realm) {\n        return factory.from(realm);\n    }\n\n    @Override\n    public Flow<DynamicRealm> from(@Nonnull DynamicRealm dynamicRealm) {\n        return factory.from(dynamicRealm);\n    }\n\n    @Override\n    public <T> Flow<RealmResults<T>> from(@Nonnull Realm realm, @Nonnull RealmResults<T> results) {\n        return factory.from(realm, results);\n    }\n\n    @Override\n    public <T> Flow<CollectionChange<RealmResults<T>>> changesetFrom(@Nonnull Realm realm, @Nonnull RealmResults<T> results) {\n        return factory.changesetFrom(realm, results);\n    }\n\n    @Override\n    public <T> Flow<RealmResults<T>> from(@Nonnull DynamicRealm dynamicRealm, @Nonnull RealmResults<T> results) {\n        return factory.from(dynamicRealm, results);\n    }\n\n    @Override\n    public <T> Flow<CollectionChange<RealmResults<T>>> changesetFrom(@Nonnull DynamicRealm dynamicRealm, @Nonnull RealmResults<T> results) {\n        return factory.changesetFrom(dynamicRealm, results);\n    }\n\n    @Override\n    public <T> Flow<RealmList<T>> from(@Nonnull Realm realm, @Nonnull RealmList<T> realmList) {\n        return factory.from(realm, realmList);\n    }\n\n    @Override\n    public <T> Flow<CollectionChange<RealmList<T>>> changesetFrom(@Nonnull Realm realm, @Nonnull RealmList<T> list) {\n        return factory.changesetFrom(realm, list);\n    }\n\n    @Override\n    public <T> Flow<RealmList<T>> from(@Nonnull DynamicRealm dynamicRealm, @Nonnull RealmList<T> realmList) {\n        return factory.from(dynamicRealm, realmList);\n    }\n\n    @Override\n    public <T> Flow<CollectionChange<RealmList<T>>> changesetFrom(@Nonnull DynamicRealm dynamicRealm, @Nonnull RealmList<T> list) {\n        return factory.changesetFrom(dynamicRealm, list);\n    }\n\n    @Override\n    public <T extends RealmModel> Flow<T> from(@Nonnull Realm realm, @Nonnull T realmObject) {\n        return factory.from(realm, realmObject);\n    }\n\n    @Override\n    public <T extends RealmModel> Flow<ObjectChange<T>> changesetFrom(@Nonnull Realm realm, @Nonnull T realmObject) {\n        return factory.changesetFrom(realm, realmObject);\n    }\n\n    @Override\n    public Flow<DynamicRealmObject> from(@Nonnull DynamicRealm dynamicRealm, @Nonnull DynamicRealmObject dynamicRealmObject) {\n        return factory.from(dynamicRealm, dynamicRealmObject);\n    }\n\n    @Override\n    public Flow<ObjectChange<DynamicRealmObject>> changesetFrom(@Nonnull DynamicRealm dynamicRealm, @Nonnull DynamicRealmObject dynamicRealmObject) {\n        return factory.changesetFrom(dynamicRealm, dynamicRealmObject);\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/exceptions/RealmError.java",
    "content": "/*\n * Copyright 2015 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\npackage io.realm.exceptions;\n\nimport io.realm.internal.Keep;\n\n\n/**\n * RealmError is a Realm specific Error used when unrecoverable problems happen in the underlying storage engine. A\n * RealmError should never be caught or ignored. By doing so, the Realm could possibly get corrupted.\n */\n@Keep\npublic final class RealmError extends Error {\n    public RealmError(String detailMessage) {\n        super(detailMessage);\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/exceptions/RealmException.java",
    "content": "/*\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\npackage io.realm.exceptions;\n\nimport io.realm.internal.Keep;\n\n\n/**\n * RealmException is for Realm specific exceptions.\n */\n@Keep\npublic final class RealmException extends RuntimeException {\n\n    public RealmException(String detailMessage) {\n        super(detailMessage);\n    }\n\n    public RealmException(String detailMessage, Throwable exception) {\n        super(detailMessage, exception);\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/exceptions/RealmFileException.java",
    "content": "/*\n * Copyright 2016 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 */\npackage io.realm.exceptions;\n\nimport java.util.Locale;\n\nimport io.realm.internal.Keep;\nimport io.realm.internal.OsSharedRealm;\n\n\n/**\n * Class for reporting problems when accessing the Realm related files.\n */\n@Keep\npublic class RealmFileException extends RuntimeException {\n    /**\n     * The specific kind of this {@link RealmFileException}.\n     */\n    @Keep\n    public enum Kind {\n        /**\n         * Thrown for any I/O related exception scenarios when a Realm is opened.\n         */\n        ACCESS_ERROR,\n        /**\n         * Thrown if the history type of the on-disk Realm is unexpected or incompatible.\n         */\n        BAD_HISTORY,\n        /**\n         * Thrown if the user does not have permission to open or create the specified file in the specified access\n         * mode when the Realm is opened.\n         */\n        PERMISSION_DENIED,\n        /**\n         * Thrown if the destination file exists but it is not supposed to.\n         */\n        EXISTS,\n        /**\n         * Thrown if the relevant file cannot be found.\n         */\n        NOT_FOUND,\n        /**\n         * Thrown if the database file is currently open in another process which cannot share with the current process\n         * due to an architecture mismatch.\n         */\n        INCOMPATIBLE_LOCK_FILE,\n        /**\n         * Thrown if the file needs to be upgraded to a new format, but upgrades have been explicitly disabled.\n         */\n        FORMAT_UPGRADE_REQUIRED,\n        /**\n         * Thrown if an attempt was made to open an Realm file created with Realm Object Server 1.*, which is\n         * not compatible with Realm Object Server 2.*. This exception should automatically be handled by Realm.\n         */\n        INCOMPATIBLE_SYNC_FILE;\n\n        // Created from byte values by JNI.\n        static Kind getKind(byte value) {\n            switch (value) {\n                case OsSharedRealm.FILE_EXCEPTION_KIND_ACCESS_ERROR:\n                    return ACCESS_ERROR;\n                case OsSharedRealm.FILE_EXCEPTION_KIND_PERMISSION_DENIED:\n                    return PERMISSION_DENIED;\n                case OsSharedRealm.FILE_EXCEPTION_KIND_EXISTS:\n                    return EXISTS;\n                case OsSharedRealm.FILE_EXCEPTION_KIND_NOT_FOUND:\n                    return NOT_FOUND;\n                case OsSharedRealm.FILE_EXCEPTION_KIND_INCOMPATIBLE_LOCK_FILE:\n                    return INCOMPATIBLE_LOCK_FILE;\n                case OsSharedRealm.FILE_EXCEPTION_KIND_FORMAT_UPGRADE_REQUIRED:\n                    return FORMAT_UPGRADE_REQUIRED;\n                case OsSharedRealm.FILE_EXCEPTION_KIND_BAD_HISTORY:\n                    return BAD_HISTORY;\n                case OsSharedRealm.FILE_EXCEPTION_INCOMPATIBLE_SYNC_FILE:\n                    return INCOMPATIBLE_SYNC_FILE;\n                default:\n                    throw new RuntimeException(\"Unknown value for RealmFileException kind.\");\n            }\n        }\n    }\n\n    private final Kind kind;\n\n    // Called by JNI\n    @SuppressWarnings(\"unused\")\n    public RealmFileException(byte value, String message) {\n        super(message);\n        kind = Kind.getKind(value);\n    }\n\n    public RealmFileException(Kind kind, String message) {\n        super(message);\n        this.kind = kind;\n    }\n\n    public RealmFileException(Kind kind, Throwable cause) {\n        super(cause);\n        this.kind = kind;\n    }\n\n    public RealmFileException(Kind kind, String message, Throwable cause) {\n        super(message, cause);\n        this.kind = kind;\n    }\n\n    /**\n     * Gets the {@link #kind} of this exception.\n     *\n     * @return the {@link #kind} of this exception.\n     */\n    public Kind getKind() {\n        return kind;\n    }\n\n    @Override\n    public String toString() {\n        return String.format(Locale.US, \"%s Kind: %s.\", super.toString(), kind);\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/exceptions/RealmMigrationNeededException.java",
    "content": "/*\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\npackage io.realm.exceptions;\n\nimport java.io.File;\n\nimport javax.annotation.Nullable;\n\nimport io.realm.internal.Keep;\n\n\n// Constructed from JNI\n@Keep\npublic final class RealmMigrationNeededException extends RuntimeException {\n\n    private final String canonicalRealmPath;\n\n    public RealmMigrationNeededException(String canonicalRealmPath, String detailMessage) {\n        super(detailMessage);\n        this.canonicalRealmPath = canonicalRealmPath;\n    }\n\n    /**\n     * Returns the canonical path to the Realm file that needs to be migrated.\n     * <p>\n     * This can be used for easy reference during a migration:\n     *\n     * @return Canonical path to the Realm file.\n     * @see File#getCanonicalPath()\n     */\n    public String getPath() {\n        return canonicalRealmPath;\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/exceptions/RealmPrimaryKeyConstraintException.java",
    "content": "/*\n * Copyright 2015 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\npackage io.realm.exceptions;\n\nimport io.realm.internal.Keep;\n\n\n/**\n * Class for reporting problems when the primary key constraint is being broken.\n *\n * @see io.realm.annotations.PrimaryKey\n */\n@Keep\npublic final class RealmPrimaryKeyConstraintException extends RuntimeException {\n    public RealmPrimaryKeyConstraintException(String message) {\n        super(message);\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/exceptions/package-info.java",
    "content": "/*\n * Copyright 2017 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@javax.annotation.ParametersAreNonnullByDefault\npackage io.realm.exceptions;\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/internal/Capabilities.java",
    "content": "/*\n * Copyright 2016 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\npackage io.realm.internal;\n\nimport javax.annotation.Nullable;\n\n\n/**\n * To describe what the Realm instance can do associated with the thread it is created on.\n * The capabilities are determined when the Realm gets created. This interface could be called from another thread which\n * is different from where the Realm is created on.\n */\npublic interface Capabilities {\n    /**\n     * Return true if this Realm can be notified by another thread.\n     *\n     * @return true if this Realm can be notified from an other thread.\n     */\n    boolean canDeliverNotification();\n\n    /**\n     * Check if a Realm is able to receive a notification. If not, an {@link IllegalStateException} should be be thrown.\n     *\n     * @param exceptionMessage message which is contained in the exception.\n     */\n    void checkCanDeliverNotification(@Nullable String exceptionMessage);\n\n    /**\n     * Multiple threads might be able to deliver notifications, but the Main thread in GUI applications often have\n     * special rules that need to be enforced.\n     */\n    boolean isMainThread();\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/internal/CheckedRow.java",
    "content": "/*\n * Copyright 2015 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\npackage io.realm.internal;\n\nimport java.util.Locale;\n\nimport io.realm.RealmFieldType;\n\n\n/**\n * Checked wrapper for Row data in Realm Core. All methods called through this will check that input parameters are\n * valid or throw an appropriate exception.\n * <p>\n * For low-level access to a Realm where safety checks were already performed, use {@link UncheckedRow} instead for\n * improved performance.\n */\npublic class CheckedRow extends UncheckedRow {\n\n    // Used if created from other row. This keeps a strong reference to avoid GC'ing the original object, and its\n    // underlying native data.\n    @SuppressWarnings({\"unused\", \"FieldCanBeLocal\"})\n    private UncheckedRow originalRow;\n\n    private CheckedRow(NativeContext context, Table parent, long nativePtr) {\n        super(context, parent, nativePtr);\n    }\n\n    public CheckedRow(UncheckedRow row) {\n        super(row);\n        this.originalRow = row;\n    }\n\n    /**\n     * Gets the row object associated to an index in a {@link Table}.\n     *\n     * @param context the Realm context.\n     * @param table the {@link Table} that holds the row.\n     * @param objKey the object key.\n     * @return an instance of Row for the table and index specified.\n     */\n    public static CheckedRow get(NativeContext context, Table table, long objKey) {\n        long nativeRowPointer = table.nativeGetRowPtr(table.getNativePtr(), objKey);\n        return new CheckedRow(context, table, nativeRowPointer);\n    }\n\n    /**\n     * Converts a {@link UncheckedRow} to a {@link CheckedRow}.\n     *\n     * @return an checked instance of {@link Row}.\n     */\n    public static CheckedRow getFromRow(UncheckedRow row) {\n        return new CheckedRow(row);\n    }\n\n    @Override\n    public boolean isNullLink(long columnIndex) {\n        RealmFieldType columnType = getColumnType(columnIndex);\n        if (columnType == RealmFieldType.OBJECT || columnType == RealmFieldType.LIST) {\n            return super.isNullLink(columnIndex);\n        } else {\n            return false; // Unsupported types always return false\n        }\n    }\n\n    @Override\n    public boolean isNull(long columnIndex) {\n        return super.isNull(columnIndex);\n    }\n\n    /**\n     * Sets null to a row pointer with checking if a column is nullable, except when the column type\n     * is binary.\n     *\n     * @param columnIndex 0 based index value of the cell column.\n     */\n    @Override\n    public void setNull(long columnIndex) {\n        RealmFieldType columnType = getColumnType(columnIndex);\n        if (columnType == RealmFieldType.BINARY) {\n            super.setBinaryByteArray(columnIndex, null);\n        } else {\n            super.setNull(columnIndex);\n        }\n    }\n\n    @Override\n    public OsList getModelList(long columnIndex) {\n        RealmFieldType fieldType = getTable().getColumnType(columnIndex);\n        if (fieldType != RealmFieldType.LIST) {\n            throw new IllegalArgumentException(\n                    String.format(Locale.US, \"Field '%s' is not a 'RealmList'.\",\n                            getTable().getColumnName(columnIndex)));\n        }\n        return super.getModelList(columnIndex);\n    }\n\n    @Override\n    public OsList getValueList(long columnIndex, RealmFieldType fieldType) {\n        final RealmFieldType actualFieldType = getTable().getColumnType(columnIndex);\n        if (fieldType != actualFieldType) {\n            throw new IllegalArgumentException(\n                    String.format(Locale.US, \"The type of field '%1$s' is not 'RealmFieldType.%2$s'.\",\n                            getTable().getColumnName(columnIndex), fieldType.name()));\n        }\n        return super.getValueList(columnIndex, fieldType);\n    }\n\n    @Override\n    public OsMap getRealmAnyMap(long columnIndex) {\n        RealmFieldType fieldType = getTable().getColumnType(columnIndex);\n        if (fieldType != RealmFieldType.STRING_TO_MIXED_MAP) {\n            throw new IllegalArgumentException(\n                    String.format(Locale.US, \"Field '%s' is not a 'RealmDictionary'.\",\n                            getTable().getColumnName(columnIndex)));\n        }\n        return super.getRealmAnyMap(columnIndex);\n    }\n\n    @Override\n    public OsMap getModelMap(long columnIndex) {\n        RealmFieldType fieldType = getTable().getColumnType(columnIndex);\n        if (fieldType != RealmFieldType.STRING_TO_LINK_MAP) {\n            throw new IllegalArgumentException(\n                    String.format(Locale.US, \"Field '%s' is not a 'RealmDictionary'.\",\n                            getTable().getColumnName(columnIndex)));\n        }\n        return super.getRealmAnyMap(columnIndex);\n    }\n\n    @Override\n    public OsMap getValueMap(long columnIndex, RealmFieldType fieldType) {\n        final RealmFieldType actualFieldType = getTable().getColumnType(columnIndex);\n        if (fieldType != actualFieldType) {\n            throw new IllegalArgumentException(\n                    String.format(Locale.US, \"The type of field '%1$s' is not 'RealmFieldType.%2$s'.\",\n                            getTable().getColumnName(columnIndex), fieldType.name()));\n        }\n        return super.getValueMap(columnIndex, fieldType);\n    }\n\n    @Override\n    public OsSet getRealmAnySet(long columnIndex) {\n        return super.getModelSet(columnIndex);\n    }\n\n    @Override\n    public OsSet getModelSet(long columnIndex) {\n        return super.getModelSet(columnIndex);\n    }\n\n    @Override\n    public OsSet getValueSet(long columnIndex, RealmFieldType fieldType) {\n        final RealmFieldType actualFieldType = getTable().getColumnType(columnIndex);\n        if (fieldType != actualFieldType) {\n            throw new IllegalArgumentException(\n                    String.format(Locale.US, \"The type of field '%1$s' is not 'RealmFieldType.%2$s'.\",\n                            getTable().getColumnName(columnIndex), fieldType.name()));\n        }\n        return super.getValueSet(columnIndex, fieldType);\n    }\n\n    @Override\n    public Row freeze(OsSharedRealm frozenRealm) {\n        if (!isValid()) {\n            return InvalidRow.INSTANCE;\n        }\n        return new CheckedRow(context, parent.freeze(frozenRealm), nativeFreeze(getNativePtr(), frozenRealm.getNativePtr()));\n    }\n\n    @Override\n    protected native long nativeGetColumnCount(long nativeTablePtr);\n\n    @Override\n    protected native long nativeGetColumnKey(long nativeTablePtr, String columnName);\n\n    @Override\n    protected native int nativeGetColumnType(long nativeTablePtr, long columnIndex);\n\n    @Override\n    protected native long nativeGetLong(long nativeRowPtr, long columnIndex);\n\n    @Override\n    protected native boolean nativeGetBoolean(long nativeRowPtr, long columnIndex);\n\n    @Override\n    protected native float nativeGetFloat(long nativeRowPtr, long columnIndex);\n\n    @Override\n    protected native double nativeGetDouble(long nativeRowPtr, long columnIndex);\n\n    @Override\n    protected native long nativeGetTimestamp(long nativeRowPtr, long columnIndex);\n\n    @Override\n    protected native String nativeGetString(long nativePtr, long columnIndex);\n\n    @Override\n    protected native boolean nativeIsNullLink(long nativeRowPtr, long columnIndex);\n\n    @Override\n    protected native byte[] nativeGetByteArray(long nativePtr, long columnIndex);\n\n    @Override\n    protected native void nativeSetLong(long nativeRowPtr, long columnIndex, long value);\n\n    @Override\n    protected native void nativeSetBoolean(long nativeRowPtr, long columnIndex, boolean value);\n\n    @Override\n    protected native void nativeSetFloat(long nativeRowPtr, long columnIndex, float value);\n\n    @Override\n    protected native long nativeGetLink(long nativeRowPtr, long columnIndex);\n\n    @Override\n    protected native void nativeSetDouble(long nativeRowPtr, long columnIndex, double value);\n\n    @Override\n    protected native void nativeSetTimestamp(long nativeRowPtr, long columnIndex, long dateTimeValue);\n\n    @Override\n    protected native void nativeSetString(long nativeRowPtr, long columnIndex, String value);\n\n    @Override\n    protected native void nativeSetByteArray(long nativePtr, long columnIndex, byte[] data);\n\n    @Override\n    protected native void nativeSetLink(long nativeRowPtr, long columnIndex, long value);\n\n    @Override\n    protected native void nativeNullifyLink(long nativeRowPtr, long columnIndex);\n\n    @Override\n    protected native long[] nativeGetDecimal128(long nativePtr, long columnKey);\n\n    @Override\n    protected native String nativeGetObjectId(long nativePtr, long columnKey);\n\n    @Override\n    protected native void nativeSetDecimal128(long nativePtr, long columnKey, long low, long high);\n\n    @Override\n    protected native void nativeSetObjectId(long nativePtr, long columnKey, String value);\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/internal/ColumnIndices.java",
    "content": "/*\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\npackage io.realm.internal;\n\n\nimport java.util.HashMap;\nimport java.util.Locale;\nimport java.util.Map;\nimport java.util.Set;\nimport java.util.concurrent.ConcurrentHashMap;\n\nimport javax.annotation.Nonnull;\n\nimport io.realm.RealmModel;\nimport io.realm.exceptions.RealmException;\n\n/**\n * Utility class used to cache the mapping between object field names and their column indices. The\n * {@code ColumnIndices} instance is dedicated to a single {@link io.realm.BaseRealm} instance. Different Realm\n * instances will never share the same column indices cache. The column info cache is loaded lazily. A\n * {@link ColumnInfo} will be added to the cache when the relevant Realm object gets accessed.\n * <p>\n * This class can be mutated, after construction, in two ways:\n * <ul>\n * <li>the {@code copyFrom} method</li>\n * <li>mutating one of the ColumnInfo object to which this instance holds a reference</li>\n * </ul>\n * Immutable instances of this class protect against the first possibility by throwing on calls\n * to {@code copyFrom}.  {@see ColumnInfo} for its mutability contract.\n *\n * There are two, redundant, lookup methods, for schema members: by Class and by String.\n * Query lookups must be done by the name of the class and use the String-keyed lookup table.\n * Although it would be possible to use the same table to look up ColumnInfo by Class, the\n * class lookup is very fast and on a hot path, so we maintain the redundant table.\n */\npublic final class ColumnIndices {\n    // Class to ColumnInfo map\n    private final Map<Class<? extends RealmModel>, ColumnInfo> classToColumnInfoMap =\n            new ConcurrentHashMap<Class<? extends RealmModel>, ColumnInfo>();\n    // Class name to ColumnInfo map. All the elements in this map should be existing in classToColumnInfoMap.\n    private final Map<String, ColumnInfo> simpleClassNameToColumnInfoMap =\n            new HashMap<String, ColumnInfo>();\n\n    private final RealmProxyMediator mediator;\n    // Due to the nature of Object Store's Realm::m_schema, OsSharedRealm's OsObjectSchemaInfo object is fixed after set.\n    private final OsSchemaInfo osSchemaInfo;\n\n\n    /**\n     * Create a mutable ColumnIndices initialized with the ColumnInfo objects in the passed map.\n     *\n     * @param mediator the {@link RealmProxyMediator} used for the corresponding Realm.\n     * @param osSchemaInfo the corresponding Realm's {@link OsSchemaInfo}.\n     */\n    public ColumnIndices(RealmProxyMediator mediator, OsSchemaInfo osSchemaInfo) {\n        this.mediator = mediator;\n        this.osSchemaInfo = osSchemaInfo;\n    }\n\n    /**\n     * Returns the {@link ColumnInfo} for the passed class.\n     *\n     * @param clazz the class for which to get the ColumnInfo.\n     * @return the corresponding {@link ColumnInfo} object.\n     * @throws io.realm.exceptions.RealmException if the class cannot be found in the schema.\n     */\n    @Nonnull\n    public ColumnInfo getColumnInfo(Class<? extends RealmModel> clazz) {\n        ColumnInfo columnInfo = classToColumnInfoMap.get(clazz);\n        if (columnInfo == null) {\n            columnInfo = mediator.createColumnInfo(clazz, osSchemaInfo);\n            classToColumnInfoMap.put(clazz, columnInfo);\n        }\n        return columnInfo;\n    }\n\n    /**\n     * Returns the {@link ColumnInfo} for the provided internal class name.\n     *\n     * @param simpleClassName the simple name of the class for which to get the ColumnInfo.\n     * @return the corresponding {@link ColumnInfo} object.\n     * @throws io.realm.exceptions.RealmException if the class cannot be found in the schema.\n     */\n    @Nonnull\n    public ColumnInfo getColumnInfo(String simpleClassName) {\n        ColumnInfo columnInfo = simpleClassNameToColumnInfoMap.get(simpleClassName);\n        if (columnInfo == null) {\n            Set<Class<? extends RealmModel>> modelClasses = mediator.getModelClasses();\n            for (Class<? extends RealmModel> modelClass : modelClasses) {\n                if (mediator.getSimpleClassName(modelClass).equals(simpleClassName)) {\n                    columnInfo = getColumnInfo(modelClass);\n                    simpleClassNameToColumnInfoMap.put(simpleClassName, columnInfo);\n                    break;\n                }\n            }\n        }\n        if (columnInfo == null) {\n            throw new RealmException(\n                    String.format(Locale.US, \"'%s' doesn't exist in current schema.\", simpleClassName));\n        }\n        return columnInfo;\n    }\n\n    /**\n     * Refreshes all the existing {@link ColumnInfo} in the cache.\n     */\n    public void refresh() {\n        for (Map.Entry<Class<? extends RealmModel>, ColumnInfo> entry : classToColumnInfoMap.entrySet()) {\n            ColumnInfo newColumnInfo = mediator.createColumnInfo(entry.getKey(), osSchemaInfo);\n            entry.getValue().copyFrom(newColumnInfo);\n        }\n    }\n\n    @Override\n    public String toString() {\n        StringBuilder buf = new StringBuilder(\"ColumnIndices[\");\n        boolean commaNeeded = false;\n        for (Map.Entry<Class<? extends RealmModel>, ColumnInfo> entry : classToColumnInfoMap.entrySet()) {\n            if (commaNeeded) { buf.append(\",\"); }\n            buf.append(entry.getKey().getSimpleName()).append(\"->\").append(entry.getValue());\n            commaNeeded = true;\n        }\n        return buf.append(\"]\").toString();\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/internal/ColumnInfo.java",
    "content": "/*\n * Copyright 2015 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\npackage io.realm.internal;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport javax.annotation.Nullable;\n\nimport io.realm.RealmFieldType;\n\n\n/**\n * The Subclasses of this are a fast cache of column indices, for proxy object.\n * <p>\n * The fast cache functionality is implemented in the Proxy classes generated by {@code RealmProxyClassGenerator}.\n * Every proxy object will hold an reference of its {@code ColumnInfo}. The ref to the {@code ColumnInfo} instance is\n * maintained by the {@link ColumnIndices}. As long as the reference in proxy object has been set, it should never be\n * changed. When schema changes, the relevant {@code ColumnInfo} instance's content will be refreshed therefore the\n * proxy object could have the latest column indices. Be sure to understand what is going on there,\n * before changing things here.\n * <p>\n * While the use of the fields in {@code ColumnDetails} is consistent, there are three subtly different cases:\n * <ul>\n * <li>If the column type is a simple type, the {@code linkedClassName} field is {@code null}</li>\n * <li>If the column type is OBJECT or LINK, the {@code linkedClassName} field is the class name of the OBJECT/LINK type</li>\n * <li>If the column type is LINKING_OBJECT, the {@code linkedClassName} field is the class name of the backlink source table\n * and the column index field is the index of the backlink source field, in the source table</li>\n * </ul>\n * <p>\n * The instance of this class is dedicated to a single {@link OsSharedRealm} instance. Thus this is not supposed to be\n * used across threads.\n * An instance can be mutated, after construction, in four ways:\n * <ul>\n * <li>the {@code copyFrom} method</li>\n * <li>as the dst parameter of the two-argument copy method</li>\n * <li>using the {@code addColumnDetails} method</li>\n * <li>using the {@code addBacklinkDetails} method</li>\n * </ul>\n * Immutable instances of this class protect against the first possibility by throwing on calls\n * to {@code copyFrom}.  There are no checks against the other three mutations.  In order to comply\n * with the effectively-final contract:\n * <ul>\n * <li>the methods {@code addColumnDetails} and {@code addBacklinkDetails} must be called\n * only from within instance constructors</li>\n * <li>an immutable instance must never be the dst parameter of the two-argument copy method</li>\n * </ul>\n */\npublic abstract class ColumnInfo {\n\n    // Immutable column information\n    public static final class ColumnDetails {\n        public final long columnKey;\n        public final RealmFieldType columnType;\n        public final String linkedClassName;\n\n        private ColumnDetails(long columnKey, RealmFieldType columnType, @Nullable String linkedClassName) {\n            // invariant: (columnType == OBJECT || columnType == LIST || columnType == LINKING_OBJECTS) == (linkedClassName != null)\n            this.columnKey = columnKey;\n            this.columnType = columnType;\n            this.linkedClassName = linkedClassName;\n        }\n\n        ColumnDetails(Property property) {\n            this(property.getColumnKey(), property.getType(), property.getLinkedObjectName());\n        }\n\n        @Override\n        public String toString() {\n            StringBuilder buf = new StringBuilder(\"ColumnDetails[\");\n            buf.append(columnKey);\n            buf.append(\", \").append(columnType);\n            buf.append(\", \").append(linkedClassName);\n            return buf.append(\"]\").toString();\n        }\n    }\n\n\n    private final Map<String, ColumnDetails> columnkeysFromJavaFieldNames;\n    private final Map<String, ColumnDetails> columnKeysFromColumnNames;\n    private final Map<String, String> javaFieldNameToInternalNames;\n    private final boolean mutable;\n\n    /**\n     * Create a new, empty instance\n     *\n     * @param mapSize the expected number of columns in the map.\n     */\n    protected ColumnInfo(int mapSize) {\n        this(mapSize, true);\n    }\n\n    /**\n     * Create an exact copy of the passed instance.\n     *\n     * @param src the instance to copy\n     * @param mutable false to make this instance effectively final\n     */\n    protected ColumnInfo(@Nullable ColumnInfo src, boolean mutable) {\n        this((src == null) ? 0 : src.columnkeysFromJavaFieldNames.size(), mutable);\n        // ColumnDetails are immutable and may be re-used.\n        if (src != null) {\n            columnkeysFromJavaFieldNames.putAll(src.columnkeysFromJavaFieldNames);\n        }\n    }\n\n    private ColumnInfo(int mapSize, boolean mutable) {\n        this.columnkeysFromJavaFieldNames = new HashMap<>(mapSize);\n        this.columnKeysFromColumnNames = new HashMap<>(mapSize);\n        this.javaFieldNameToInternalNames = new HashMap<>(mapSize);\n        this.mutable = mutable;\n    }\n\n    /**\n     * Get the mutability state of the instance.\n     *\n     * @return true if the instance is mutable\n     */\n    public final boolean isMutable() {\n        return mutable;\n    }\n\n    /**\n     * Returns the column key, in the described table, for the named column.\n     *\n     * @return column key.\n     */\n    public long getColumnKey(String javaFieldName) {\n        ColumnDetails details = columnkeysFromJavaFieldNames.get(javaFieldName);\n        return (details == null) ? -1 : details.columnKey;\n    }\n\n    /**\n     * Returns the {@link ColumnDetails}, in the described table, of the named column.\n     *\n     * @return {@link ColumnDetails} or {@code null} if not found.\n     */\n    @Nullable\n    public ColumnDetails getColumnDetails(String javaFieldName) {\n        return columnkeysFromJavaFieldNames.get(javaFieldName);\n    }\n\n    /**\n     * Returns the internal field name that corresponds to the name found in the Java model class.\n     * @param javaFieldName the field name in the Java model class.\n     * @return the internal field name or {@code null} if the java name doesn't exists.\n     */\n    @Nullable\n    public String getInternalFieldName(String javaFieldName) {\n        return javaFieldNameToInternalNames.get(javaFieldName);\n    }\n\n    /**\n     * Makes this ColumnInfo an exact copy of {@code src}.\n     *\n     * @param src The source for the copy.  This instance will be an exact copy of {@code src} after return.\n     * {@code src} must not be {@code null}.\n     * @throws IllegalArgumentException if {@code other} has different class than this.\n     */\n    public void copyFrom(ColumnInfo src) {\n        if (!mutable) {\n            throw new UnsupportedOperationException(\"Attempt to modify an immutable ColumnInfo\");\n        }\n        if (null == src) {\n            throw new NullPointerException(\"Attempt to copy null ColumnInfo\");\n        }\n\n        columnkeysFromJavaFieldNames.clear();\n        columnkeysFromJavaFieldNames.putAll(src.columnkeysFromJavaFieldNames);\n        columnKeysFromColumnNames.clear();\n        columnKeysFromColumnNames.putAll(src.columnKeysFromColumnNames);\n        javaFieldNameToInternalNames.clear();\n        javaFieldNameToInternalNames.putAll(src.javaFieldNameToInternalNames);\n        copy(src, this);\n    }\n\n    @Override\n    public String toString() {\n        StringBuilder buf = new StringBuilder(\"ColumnInfo[\");\n        buf.append(\"mutable=\"+mutable).append(\",\");\n        if (columnkeysFromJavaFieldNames != null) {\n            buf.append(\"JavaFieldNames=[\");\n            boolean commaNeeded = false;\n            for (Map.Entry<String, ColumnDetails> entry : columnkeysFromJavaFieldNames.entrySet()) {\n                if (commaNeeded) { buf.append(\",\"); }\n                buf.append(entry.getKey()).append(\"->\").append(entry.getValue());\n                commaNeeded = true;\n            }\n            buf.append(\"]\");\n        }\n        if (columnKeysFromColumnNames != null) {\n            buf.append(\", InternalFieldNames=[\");\n            boolean commaNeeded = false;\n            for (Map.Entry<String, ColumnDetails> entry : columnKeysFromColumnNames.entrySet()) {\n                if (commaNeeded) { buf.append(\",\"); }\n                buf.append(entry.getKey()).append(\"->\").append(entry.getValue());\n                commaNeeded = true;\n            }\n            buf.append(\"]\");\n        }\n        return buf.append(\"]\").toString();\n    }\n\n    /**\n     * Create a new object that is an exact copy of {@code src}.\n     * This is the generic factory for ColumnInfo objects.\n     * Subclasses are expected to override it with a proxy to a copy constructor.\n     *\n     * @param mutable false to make an immutable copy.\n     */\n    protected abstract ColumnInfo copy(boolean mutable);\n\n    /**\n     * Make {@code dst} into an exact copy of {@code src}.\n     * Intended for use only by subclasses.\n     * NOTE: there is no protection against calling this method with an \"immutable\" instance as dst!\n     *\n     * @param src The source for the copy\n     * @param dst The destination of the copy.  Will be an exact copy of src after return.\n     */\n    protected abstract void copy(ColumnInfo src, ColumnInfo dst);\n\n    /**\n     * Add a new column to the indexMap.\n     * <p>\n     * <b>For use only in subclass constructors!</b>.\n     * Must be called from within the subclass constructor, to maintain the effectively-final contract.\n     * <p>\n     * No validation done here.  Presuming that all necessary validation takes place in {@code Proxy.validateTable}.\n     *\n     * @param javaFieldName The name of the java field name.\n     * @param internalColumnName The underlying column name in the Realm file for the Java field name.\n     * @param objectSchemaInfo the {@link OsObjectSchemaInfo} for the corresponding {@code RealmObject}.\n     * @return the index of the column in the table.\n     */\n    protected final long addColumnDetails(String javaFieldName, String internalColumnName, OsObjectSchemaInfo objectSchemaInfo) {\n        Property property = objectSchemaInfo.getProperty(internalColumnName);\n        ColumnDetails cd = new ColumnDetails(property);\n        columnkeysFromJavaFieldNames.put(javaFieldName, cd);\n        columnKeysFromColumnNames.put(internalColumnName, cd);\n        javaFieldNameToInternalNames.put(javaFieldName, internalColumnName);\n        return property.getColumnKey();\n    }\n\n    /**\n     * Add a new backlink to the indexMap.\n     * <b>For use only by subclasses!</b>.\n     * Must be called from within the subclass constructor, to maintain the effectively-final contract.\n     *\n     * @param schemaInfo the {@link OsSchemaInfo} of the corresponding {@code Realm} instance.\n     * @param javaFieldName The name of the backlink column.\n     * @param sourceTableName The name of the backlink source class.\n     * @param sourceJavaFieldName The name of the backlink source field.\n     */\n    protected final void addBacklinkDetails(OsSchemaInfo schemaInfo, String javaFieldName, String sourceTableName, String sourceJavaFieldName) {\n        long columnKey = schemaInfo.getObjectSchemaInfo(sourceTableName).getProperty(sourceJavaFieldName).getColumnKey();\n        columnkeysFromJavaFieldNames.put(javaFieldName, new ColumnDetails(columnKey, RealmFieldType.LINKING_OBJECTS, sourceTableName));\n    }\n\n    /**\n     * Returns the {@link Map} that is the implementation for this object.\n     * <b>FOR TESTING USE ONLY!</b>\n     *\n     * @return the column details map.\n     */\n    @SuppressWarnings(\"ReturnOfCollectionOrArrayField\")\n    public Map<String, ColumnDetails> getColumnKeysMap() {\n        return columnkeysFromJavaFieldNames;\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/internal/EmptyLoadChangeSet.java",
    "content": "/*\n * Copyright 2018 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 */\npackage io.realm.internal;\n\nimport io.realm.RealmResults;\n\n/**\n * Empty changeset used if {@link RealmResults#load()} is called manually or if no collection\n * changeset was available but the subscription was updated.\n */\npublic class EmptyLoadChangeSet extends OsCollectionChangeSet {\n\n    private static final int[] NO_INDEX_CHANGES = new int[0];\n    private static final Range[] NO_RANGE_CHANGES = new Range[0];\n\n    public EmptyLoadChangeSet(boolean firstCallback) {\n        super(0, firstCallback);\n    }\n\n    public EmptyLoadChangeSet() {\n        super(0, true);\n    }\n\n    @Override\n    public State getState() {\n        return State.INITIAL;\n    }\n\n    @Override\n    public int[] getDeletions() {\n        return NO_INDEX_CHANGES;\n    }\n\n    @Override\n    public int[] getInsertions() {\n        return NO_INDEX_CHANGES;\n    }\n\n    @Override\n    public int[] getChanges() {\n        return NO_INDEX_CHANGES;\n    }\n\n    @Override\n    public Range[] getDeletionRanges() {\n        return NO_RANGE_CHANGES;\n    }\n\n    @Override\n    public Range[] getInsertionRanges() {\n        return NO_RANGE_CHANGES;\n    }\n\n    @Override\n    public Range[] getChangeRanges() {\n        return NO_RANGE_CHANGES;\n    }\n\n    @Override\n    public Throwable getError() {\n        return null;\n    }\n\n    @Override\n    public boolean isFirstAsyncCallback() {\n        return super.isFirstAsyncCallback();\n    }\n\n    @Override\n    public boolean isEmpty() {\n        return true;\n    }\n\n    @Override\n    public String toString() {\n        return super.toString();\n    }\n\n    @Override\n    public long getNativePtr() {\n        return super.getNativePtr();\n    }\n\n    @Override\n    public long getNativeFinalizerPtr() {\n        return super.getNativeFinalizerPtr();\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/internal/FinalizerRunnable.java",
    "content": "/*\n * Copyright 2016 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\npackage io.realm.internal;\n\n\nimport java.lang.ref.ReferenceQueue;\n\nimport io.realm.log.RealmLog;\n\n\n// Running in the FinalizingDaemon thread to free native objects.\nclass FinalizerRunnable implements Runnable {\n    private final ReferenceQueue<NativeObject> referenceQueue;\n\n    FinalizerRunnable(ReferenceQueue<NativeObject> referenceQueue) {\n        this.referenceQueue = referenceQueue;\n    }\n\n    @Override\n    public void run() {\n        while (true) {\n            try {\n                NativeObjectReference reference = (NativeObjectReference) referenceQueue.remove();\n                reference.cleanup();\n            } catch (InterruptedException e) {\n                // Restores the interrupted status.\n                Thread.currentThread().interrupt();\n\n                RealmLog.fatal(\"The FinalizerRunnable thread has been interrupted.\" +\n                        \" Native resources cannot be freed anymore\");\n                break;\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/internal/Freezable.java",
    "content": "/*\n * Copyright 2020 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\npackage io.realm.internal;\n\nimport io.realm.RealmConfiguration;\n\n/**\n * The {@code Freezable} interface enable {@link io.realm.RealmCollection}s to be frozen. A frozen collection is a snapshot\n * of the collection itself at the moment of calling {@link #freeze()}. The contents of a collection cannot be modified after\n * freezing it and the collection itself is not bound to any thread anymore.\n *\n * @param <T> the type of content held by the collection\n */\npublic interface Freezable<T> {\n\n    /**\n     * Returns a frozen snapshot for a Realm collection. The frozen copy can be read and queried from any thread without\n     * throwing an {@link IllegalStateException}.\n     * <p>\n     * Freezing a collection also creates a Realm which has its own lifecycle, but if the live Realm that spawned the\n     * original collection is fully closed (i.e. all instances across all threads are closed), the frozen Realm and this\n     * collection will be closed as well.\n     * <p>\n     * Frozen collections can be queried as normal, but trying to mutate them in any way or attempting to register a listener\n     * will throw an {@link IllegalStateException}.\n     * <p>\n     * Note: Keeping a large number of frozencollections with different versions alive can have a negative impact on the\n     * file size of the Realm. In order to avoid such a situation, it is possible to set\n     * {@link RealmConfiguration.Builder#maxNumberOfActiveVersions(long)}.\n     *\n     * @return a frozen copy of this collection.\n     * @throws IllegalStateException if this method is called from inside a write transaction.\n     */\n    T freeze();\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/internal/IOException.java",
    "content": "/*\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\npackage io.realm.internal;\n\n@SuppressWarnings(\"serial\")\npublic class IOException extends RuntimeException {\n\n    public IOException(Throwable cause) {\n        super(cause);\n    }\n\n    public IOException() {\n    }\n\n    public IOException(String message) {\n        super(message);\n    }\n\n    public IOException(String message, Throwable cause) {\n        super(message, cause);\n    }\n\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/internal/IdentitySet.java",
    "content": "/*\n * Copyright 2015 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 */\npackage io.realm.internal;\n\nimport java.util.IdentityHashMap;\n\n\n/**\n * Identity based Set, that guarantees store & retrieve in O(1)\n * without a huge overhead in space complexity.\n */\npublic class IdentitySet<K> extends IdentityHashMap<K, Integer> {\n    private static final Integer PLACE_HOLDER = 0;\n\n    public void add(K key) {\n        put(key, PLACE_HOLDER);\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/internal/InvalidRow.java",
    "content": "/*\n * Copyright 2015 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\npackage io.realm.internal;\n\nimport org.bson.types.Decimal128;\nimport org.bson.types.ObjectId;\n\nimport java.util.Date;\nimport java.util.UUID;\n\nimport io.realm.RealmAny;\nimport io.realm.RealmFieldType;\nimport io.realm.internal.core.NativeRealmAny;\n\n\n/**\n * Row wrapper that stubs all access with IllegalStateExceptions except for isValid. This can be used instead of\n * adding null checks everywhere when the underlying Row accessor in Realm's underlying storage engine is no longer\n * available.\n */\npublic enum InvalidRow implements Row {\n    INSTANCE;\n\n    @Override\n    public long getColumnCount() {\n        throw getStubException();\n    }\n\n    @Override\n    public String[] getColumnNames() {\n        throw getStubException();\n    }\n\n    @Override\n    public long getColumnKey(String columnName) {\n        throw getStubException();\n    }\n\n    @Override\n    public RealmFieldType getColumnType(long columnKey) {\n        throw getStubException();\n    }\n\n    @Override\n    public Table getTable() {\n        throw getStubException();\n    }\n\n    @Override\n    public long getObjectKey() {\n        throw getStubException();\n    }\n\n    @Override\n    public long getLong(long columnKey) {\n        throw getStubException();\n    }\n\n    @Override\n    public boolean getBoolean(long columnKey) {\n        throw getStubException();\n    }\n\n    @Override\n    public float getFloat(long columnKey) {\n        throw getStubException();\n    }\n\n    @Override\n    public double getDouble(long columnKey) {\n        throw getStubException();\n    }\n\n    @Override\n    public Date getDate(long columnKey) {\n        throw getStubException();\n    }\n\n    @Override\n    public String getString(long columnKey) {\n        throw getStubException();\n    }\n\n    @Override\n    public byte[] getBinaryByteArray(long columnKey) {\n        throw getStubException();\n    }\n\n    @Override\n    public Decimal128 getDecimal128(long columnKey) {\n        throw getStubException();\n    }\n\n    @Override\n    public ObjectId getObjectId(long columnKey) {\n        throw getStubException();\n    }\n\n    @Override\n    public UUID getUUID(long columnKey) {\n        throw getStubException();\n    }\n\n    @Override\n    public NativeRealmAny getNativeRealmAny(long columnKey) {\n        throw getStubException();\n    }\n\n    @Override\n    public long getLink(long columnKey) {\n        throw getStubException();\n    }\n\n    @Override\n    public boolean isNullLink(long columnKey) {\n        throw getStubException();\n    }\n\n    @Override\n    public OsList getModelList(long columnKey) {\n        throw getStubException();\n    }\n\n    @Override\n    public OsList getValueList(long columnKey, RealmFieldType fieldType) {\n        throw getStubException();\n    }\n\n    @Override\n    public OsMap getRealmAnyMap(long columnKey) {\n        throw getStubException();\n    }\n\n    @Override\n    public OsMap getValueMap(long columnKey, RealmFieldType fieldType) {\n        throw getStubException();\n    }\n\n    @Override\n    public OsSet getRealmAnySet(long columnKey) {\n        throw getStubException();\n    }\n\n    @Override\n    public OsSet getModelSet(long columnKey) {\n        throw getStubException();\n    }\n\n    @Override\n    public OsSet getValueSet(long columnKey, RealmFieldType fieldType) {\n        throw getStubException();\n    }\n\n    @Override\n    public OsMap getModelMap(long columnKey) {\n        throw getStubException();\n    }\n\n    @Override\n    public void setLong(long columnKey, long value) {\n        throw getStubException();\n    }\n\n    @Override\n    public void setBoolean(long columnKey, boolean value) {\n        throw getStubException();\n    }\n\n    @Override\n    public void setFloat(long columnKey, float value) {\n        throw getStubException();\n    }\n\n    @Override\n    public void setDouble(long columnKey, double value) {\n        throw getStubException();\n    }\n\n    @Override\n    public void setDate(long columnKey, Date date) {\n        throw getStubException();\n    }\n\n    @Override\n    public void setString(long columnKey, String value) {\n        throw getStubException();\n    }\n\n    @Override\n    public void setBinaryByteArray(long columnKey, byte[] data) {\n        throw getStubException();\n    }\n\n    @Override\n    public void setLink(long columnKey, long value) {\n        throw getStubException();\n    }\n\n    @Override\n    public void nullifyLink(long columnKey) {\n        throw getStubException();\n    }\n\n    @Override\n    public boolean isNull(long columnKey) {\n        throw getStubException();\n    }\n\n    @Override\n    public void setNull(long columnKey) {\n        throw getStubException();\n    }\n\n    @Override\n    public void setDecimal128(long columnKey, Decimal128 value) {\n        throw getStubException();\n    }\n\n    @Override\n    public void setObjectId(long columnKey, ObjectId value) {\n        throw getStubException();\n    }\n\n    @Override\n    public void setUUID(long columnKey, UUID value) {\n        throw getStubException();\n    }\n\n    @Override\n    public void setRealmAny(long columnKey, long value) {\n        throw getStubException();\n    }\n\n    @Override\n    public long createEmbeddedObject(long columnKey, RealmFieldType parentPropertyType) {\n        throw getStubException();\n    }\n\n    @Override\n    public boolean isValid() {\n        return false;\n    }\n\n    @Override\n    public void checkIfAttached() {\n        throw getStubException();\n    }\n\n    @Override\n    public boolean hasColumn(String fieldName) {\n        throw getStubException();\n    }\n\n    @Override\n    public Row freeze(OsSharedRealm frozenRealm) {\n        return INSTANCE;\n    }\n\n    @Override\n    public boolean isLoaded() {\n        return true;\n    }\n\n    private RuntimeException getStubException() {\n        return new IllegalStateException(\"Object is no longer managed by Realm. Has it been deleted?\");\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/internal/Keep.java",
    "content": "/*\n * Copyright 2015 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\npackage io.realm.internal;\n\nimport java.lang.annotation.ElementType;\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.RetentionPolicy;\nimport java.lang.annotation.Target;\n\n\n/**\n * This annotation is used to mark the classes to be kept by ProGuard/DexGuard.\n * The ProGuard configuration must have '-keep class io.realm.internal.Keep'\n * and '-keep,includedescriptorclasses @io.realm.internal.Keep class * { *; }'.\n * <p>\n * NOTE: The outer class and the inner class have to be both annotated by this if they need to be kept.\n */\n@Retention(RetentionPolicy.CLASS)\n@Target(ElementType.TYPE)\npublic @interface Keep {\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/internal/KeepMember.java",
    "content": "/*\n * Copyright 2016 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\npackage io.realm.internal;\n\nimport java.lang.annotation.ElementType;\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.RetentionPolicy;\nimport java.lang.annotation.Target;\n\n\n/**\n * This annotation is used to mark the fields and methods to be kept by ProGuard/DexGuard.\n * The ProGuard configuration must have '-keep class io.realm.internal.KeepMember'\n * and '-keep,includedescriptorclasses @io.realm.internal.KeepMember class * { @io.realm.internal.KeepMember *; }'.\n * This annotation must be added to class as well to work.\n */\n@Retention(RetentionPolicy.CLASS)\n@Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD})\npublic @interface KeepMember {\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/internal/ManageableObject.java",
    "content": "/*\n * Copyright 2017 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 */\npackage io.realm.internal;\n\n/**\n * This internal interface represents a java object that corresponds to data\n * that may be managed in the Realm core. It specifies the operations common to all such objects.\n */\npublic interface ManageableObject {\n\n    /**\n     * Checks to see if this object is managed by Realm..\n     *\n     * @return {@code true} if this is a managed Realm object, {@code false} otherwise.\n     */\n    boolean isManaged();\n\n    /**\n     * Checks to see if the managed object is still valid to use.\n     * That is if it that it hasn't been deleted nor has the {@link io.realm.Realm} been closed.\n     * It will always return {@code true} for unmanaged objects.\n     *\n     * @return {@code true} if this object is unmanaged or is still valid for use, {@code false} otherwise.\n     */\n    boolean isValid();\n\n    /**\n     * Returns whether or not this object is frozen.\n     *\n     * @return {@code true} if the object is frozen, {@code false} if it is not.\n     */\n    boolean isFrozen();\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/internal/NativeContext.java",
    "content": "/*\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\npackage io.realm.internal;\n\nimport java.lang.ref.ReferenceQueue;\nimport java.util.LinkedList;\n\n\n// Currently we free native objects in two threads, the SharedGroup is freed in the caller thread, others are freed in\n// RealmFinalizingDaemon thread. And the destruction in both threads are locked by the corresponding context.\n// The purpose of locking on NativeContext is:\n// Destruction of SharedGroup (and hence Group and Table) is currently not thread-safe with respect to destruction of\n// other accessors, you have to ensure mutual exclusion. This is also illustrated by the use of locks in the test\n// test_destructor_thread_safety.cpp. Explicit call of SharedGroup::close() or Table::detach() is also not thread-safe\n// with respect to destruction of other accessors.\npublic class NativeContext {\n    private static final ReferenceQueue<NativeObject> referenceQueue = new ReferenceQueue<NativeObject>();\n    private static final Thread finalizingThread = new Thread(new FinalizerRunnable(referenceQueue));\n    // Dummy context which will be used by native objects which's destructors are always thread safe.\n    public static final NativeContext dummyContext = new NativeContext();\n\n    static {\n        finalizingThread.setName(\"RealmFinalizingDaemon\");\n        finalizingThread.start();\n    }\n\n    public void addReference(NativeObject referent) {\n        new NativeObjectReference(this, referent, referenceQueue);\n    }\n\n    /**\n     * Executes a given NativeContextRunnable with a NativeContext which lifecycle is bound\n     * to a function scope.\n     *\n     * @param runnable function to execute.\n     */\n    static void execute(NativeContextRunnable runnable) {\n        ManualReleaseNativeContext nativeContext = new ManualReleaseNativeContext();\n        runnable.run(nativeContext);\n        nativeContext.release();\n    }\n\n    public interface NativeContextRunnable {\n        void run(NativeContext nativeContext);\n    }\n\n    private static class ManualReleaseNativeContext extends NativeContext {\n        private final LinkedList<NativeObject> references = new LinkedList<>();\n\n        ManualReleaseNativeContext(){ }\n\n        @Override\n        public void addReference(NativeObject referent) {\n            references.add(referent);\n        }\n\n        public void release() {\n            for (NativeObject object : references) {\n                NativeObjectReference.nativeCleanUp(object.getNativeFinalizerPtr(), object.getNativePtr());\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/internal/NativeObject.java",
    "content": "/*\n * Copyright 2015 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\npackage io.realm.internal;\n\n/**\n * This abstract class represents a native object from core.\n * It specifies the operations common to all such objects.\n * All Java classes wrapping a core class should implement NativeObject.\n */\npublic interface NativeObject {\n    long NULLPTR = 0L;\n\n    /**\n     * Gets the pointer of a native object.\n     *\n     * @return the native pointer.\n     */\n    long getNativePtr();\n\n    /**\n     * Gets the function pointer which points to the function to free the native object.\n     * The function should be defined like: {@code typedef void (*FinalizeFunc)(jlong ptr)}.\n     *\n     * @return the function pointer for freeing the native resource.\n     */\n    long getNativeFinalizerPtr();\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/internal/NativeObjectReference.java",
    "content": "/*\n * Copyright 2015 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\npackage io.realm.internal;\n\nimport java.lang.ref.PhantomReference;\nimport java.lang.ref.ReferenceQueue;\n\n\n/**\n * This class is used for holding the reference to the native pointers present in NativeObjects.\n * This is required as phantom references cannot access the original objects for this value.\n * The phantom references will be stored in a double linked list to avoid the reference itself gets GCed. When the\n * referent get GCed, the reference will be added to the ReferenceQueue. Loop in the daemon thread will retrieve the\n * phantom reference from the ReferenceQueue then dealloc the referent and remove the reference from the double linked\n * list. See {@link FinalizerRunnable} for more implementation details.\n */\nfinal class NativeObjectReference extends PhantomReference<NativeObject> {\n\n    // Linked list to keep the reference of the PhantomReference\n    private static class ReferencePool {\n        NativeObjectReference head;\n\n        synchronized void add(NativeObjectReference ref) {\n            ref.prev = null;\n            ref.next = head;\n            if (head != null) {\n                head.prev = ref;\n            }\n            head = ref;\n        }\n\n        synchronized void remove(NativeObjectReference ref) {\n            NativeObjectReference next = ref.next;\n            NativeObjectReference prev = ref.prev;\n            ref.next = null;\n            ref.prev = null;\n            if (prev != null) {\n                prev.next = next;\n            } else {\n                head = next;\n            }\n            if (next != null) {\n                next.prev = prev;\n            }\n        }\n    }\n\n    // The pointer to the native object to be handled\n    private final long nativePtr;\n    // The pointer to the native finalize function\n    private final long nativeFinalizerPtr;\n    private final NativeContext context;\n    private NativeObjectReference prev;\n    private NativeObjectReference next;\n\n    private static ReferencePool referencePool = new ReferencePool();\n\n    NativeObjectReference(NativeContext context,\n                          NativeObject referent,\n                          ReferenceQueue<? super NativeObject> referenceQueue) {\n        super(referent, referenceQueue);\n        this.nativePtr = referent.getNativePtr();\n        this.nativeFinalizerPtr = referent.getNativeFinalizerPtr();\n        this.context = context;\n        referencePool.add(this);\n    }\n\n    /**\n     * To dealloc native resources.\n     */\n    void cleanup() {\n        synchronized (context) {\n            nativeCleanUp(nativeFinalizerPtr, nativePtr);\n        }\n        // Remove the PhantomReference from the pool to free it.\n        referencePool.remove(this);\n    }\n\n    /**\n     * Calls the native finalizer function to free the given native pointer.\n     */\n    static native void nativeCleanUp(long nativeFinalizer, long nativePointer);\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/internal/ObjectServerFacade.java",
    "content": "/*\n * Copyright 2016 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\npackage io.realm.internal;\n\nimport android.content.Context;\n\nimport java.lang.reflect.InvocationTargetException;\n\nimport io.realm.Realm;\nimport io.realm.RealmConfiguration;\nimport io.realm.exceptions.RealmException;\n\n/**\n * Class acting as an mediator between the basic Realm APIs and the Object Server APIs.\n * This breaks the cyclic dependency between ObjectServer and Realm code.\n */\npublic class ObjectServerFacade {\n\n    public interface RealmCacheAccessor {\n        Realm createRealmOrGetFromCache(RealmConfiguration configuration, OsSharedRealm.VersionID versionID);\n    }\n\n    public interface RealmInstanceFactory {\n        Realm createInstance(OsSharedRealm sharedRealm);\n    }\n\n    public static final int SYNC_CONFIG_OPTIONS = 19;\n\n    private static final ObjectServerFacade nonSyncFacade = new ObjectServerFacade();\n    private static ObjectServerFacade syncFacade = null;\n\n    static {\n        //noinspection TryWithIdenticalCatches\n        try {\n            @SuppressWarnings(\"LiteralClassName\")\n            Class syncFacadeClass = Class.forName(\"io.realm.internal.SyncObjectServerFacade\");\n            //noinspection unchecked\n            syncFacade = (ObjectServerFacade) syncFacadeClass.getDeclaredConstructor().newInstance();\n        } catch (ClassNotFoundException ignored) {\n        } catch (InstantiationException e) {\n            throw new RealmException(\"Failed to init SyncObjectServerFacade\", e);\n        } catch (IllegalAccessException e) {\n            throw new RealmException(\"Failed to init SyncObjectServerFacade\", e);\n        } catch (NoSuchMethodException e) {\n            throw new RealmException(\"Failed to init SyncObjectServerFacade\", e);\n        } catch (InvocationTargetException e) {\n            throw new RealmException(\"Failed to init SyncObjectServerFacade\", e.getTargetException());\n        }\n    }\n\n    /**\n     * Initializes the Object Server library\n     */\n    public void initialize(Context context, String userAgent, RealmCacheAccessor accessor, RealmInstanceFactory instantiator) {\n    }\n\n    /**\n     * The last instance of this Realm was closed (across all Threads).\n     */\n    public void realmClosed(RealmConfiguration configuration) {\n    }\n\n    public Object[] getSyncConfigurationOptions(RealmConfiguration config) {\n        return new Object[SYNC_CONFIG_OPTIONS];\n    }\n\n    public static ObjectServerFacade getFacade(boolean needSyncFacade) {\n        if (needSyncFacade) {\n            return syncFacade;\n        }\n        return nonSyncFacade;\n    }\n\n    // Returns a SyncObjectServerFacade instance if the class exists. Otherwise returns a non-sync one.\n    public static ObjectServerFacade getSyncFacadeIfPossible() {\n        if (syncFacade != null) {\n            return syncFacade;\n        }\n        return nonSyncFacade;\n    }\n\n    // If no session yet exists for this path. Wrap a new Java Session around an existing OS one.\n    public void wrapObjectStoreSessionIfRequired(OsRealmConfig config) {\n    }\n\n    public String getSyncServerCertificateAssetName(RealmConfiguration config) {\n        return null;\n    }\n\n    public String getSyncServerCertificateFilePath(RealmConfiguration config) {\n        return null;\n    }\n\n    /**\n     * Block until all latest changes have been downloaded from the server. This should only\n     * be called the first time a Realm file is created.\n     *\n     * @throws {@code DownloadingRealmInterruptedException} if the thread was interrupted while blocked waiting for\n     * this to complete.\n     * @throws {@code ObjectServerException } In any other kind of error is reported.\n     */\n    @SuppressWarnings(\"JavaDoc\")\n    public void downloadInitialRemoteChanges(RealmConfiguration config) {\n        // Do nothing\n    }\n\n    /**\n     * Check if an exception is a {@code DownloadingRealmInterruptedException}\n     */\n    public boolean wasDownloadInterrupted(Throwable throwable) {\n        return false;\n    }\n\n    public void createNativeSyncSession(RealmConfiguration configuration) {\n        // Do nothing\n    }\n\n    public void checkFlexibleSyncEnabled(RealmConfiguration configuration) {\n        // Do nothing\n    }\n\n    public void downloadInitialFlexibleSyncData(Realm realm, RealmConfiguration configuration) {\n        // Do nothing\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/internal/ObservableCollection.java",
    "content": "package io.realm.internal;\n\nimport javax.annotation.Nullable;\n\nimport io.realm.OrderedCollectionChangeSet;\nimport io.realm.OrderedRealmCollectionChangeListener;\nimport io.realm.RealmChangeListener;\n\n// Helper class for supporting add change listeners on OsResults & OsList.\n@Keep\npublic interface ObservableCollection {\n    class CollectionObserverPair<T> extends ObserverPairList.ObserverPair<T, Object> {\n        CollectionObserverPair(T observer, Object listener) {\n            super(observer, listener);\n        }\n\n        public void onChange(T observer, OsCollectionChangeSet changes) {\n            if (listener instanceof OrderedRealmCollectionChangeListener) {\n                //noinspection unchecked\n                ((OrderedRealmCollectionChangeListener<T>) listener).onChange(observer, new StatefulCollectionChangeSet(changes));\n            } else if (listener instanceof RealmChangeListener) {\n                //noinspection unchecked\n                ((RealmChangeListener<T>) listener).onChange(observer);\n            } else {\n                throw new RuntimeException(\"Unsupported listener type: \" + listener);\n            }\n        }\n    }\n\n    class RealmChangeListenerWrapper<T> implements OrderedRealmCollectionChangeListener<T> {\n        private final RealmChangeListener<T> listener;\n\n        public RealmChangeListenerWrapper(RealmChangeListener<T> listener) {\n            this.listener = listener;\n        }\n\n        @Override\n        public void onChange(T collection, @Nullable OrderedCollectionChangeSet changes) {\n            listener.onChange(collection);\n        }\n\n        @Override\n        public boolean equals(Object obj) {\n            return obj instanceof RealmChangeListenerWrapper &&\n                    listener == ((RealmChangeListenerWrapper) obj).listener;\n        }\n\n        @Override\n        public int hashCode() {\n            return listener.hashCode();\n        }\n    }\n\n    class Callback implements ObserverPairList.Callback<CollectionObserverPair> {\n        private final OsCollectionChangeSet changeSet;\n\n        Callback(OsCollectionChangeSet changeSet) {\n            this.changeSet = changeSet;\n        }\n\n        @Override\n        public void onCalled(CollectionObserverPair pair, Object observer) {\n            //noinspection unchecked\n            pair.onChange(observer, changeSet);\n        }\n    }\n\n    // Called by JNI\n    @SuppressWarnings(\"SameParameterValue\")\n    void notifyChangeListeners(long nativeChangeSetPtr);\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/internal/ObservableMap.java",
    "content": "/*\n * Copyright 2021 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\npackage io.realm.internal;\n\nimport org.jetbrains.annotations.Nullable;\n\nimport io.realm.MapChangeListener;\nimport io.realm.MapChangeSet;\nimport io.realm.RealmChangeListener;\nimport io.realm.RealmMap;\n\n// Helper class for supporting add change listeners to RealmMaps via ManagedMapManager and its subclasses.\n@Keep   // Prevent this class from being obfuscated by proguard\npublic interface ObservableMap {\n\n    void notifyChangeListeners(long nativeChangeSetPtr);\n\n    class MapObserverPair<K, V> extends ObserverPairList.ObserverPair<RealmMap<K, V>, Object> {\n        public MapObserverPair(RealmMap<K, V> observer, MapChangeListener<K, V> listener) {\n            super(observer, listener);\n        }\n\n        public void onChange(Object observer, MapChangeSet<K> changes) {\n            //noinspection unchecked\n            ((MapChangeListener<K, V>) listener).onChange((RealmMap<K, V>) observer, changes);\n        }\n    }\n\n    class RealmChangeListenerWrapper<K, V> implements MapChangeListener<K, V> {\n        private final RealmChangeListener<RealmMap<K, V>> listener;\n\n        public RealmChangeListenerWrapper(RealmChangeListener<RealmMap<K, V>> listener) {\n            this.listener = listener;\n        }\n\n        @Override\n        public void onChange(RealmMap<K, V> map, @Nullable MapChangeSet<K> changes) {\n            listener.onChange(map);\n        }\n\n        @Override\n        public boolean equals(Object o) {\n            //noinspection unchecked\n            return o instanceof RealmChangeListenerWrapper &&\n                    listener == ((RealmChangeListenerWrapper<K, V>) o).listener;\n        }\n\n        @Override\n        public int hashCode() {\n            return listener.hashCode();\n        }\n    }\n\n    class Callback<K, V> implements ObserverPairList.Callback<MapObserverPair<K, V>> {\n\n        private final MapChangeSet<K> changeSet;\n\n        public Callback(MapChangeSet<K> changeSet) {\n            this.changeSet = changeSet;\n        }\n\n        @Override\n        public void onCalled(MapObserverPair<K, V> pair, Object observer) {\n            pair.onChange(observer, changeSet);\n        }\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/internal/ObservableSet.java",
    "content": "/*\n * Copyright 2021 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\npackage io.realm.internal;\n\nimport io.realm.RealmSet;\nimport io.realm.SetChangeListener;\nimport io.realm.SetChangeSet;\n\n// Helper class for supporting add change listeners to RealmSets via SetValueOperator and its subclasses.\n@Keep   // Prevent this class from being obfuscated by proguard\npublic interface ObservableSet {\n\n    void notifyChangeListeners(long nativeChangeSetPtr);\n\n    class SetObserverPair<T> extends ObserverPairList.ObserverPair<RealmSet<T>, Object> {\n        public SetObserverPair(RealmSet<T> observer, Object listener) {\n            super(observer, listener);\n        }\n\n        public void onChange(Object observer, SetChangeSet changes) {\n            //noinspection unchecked\n            ((SetChangeListener<T>) listener).onChange((RealmSet<T>) observer, changes);\n        }\n    }\n\n    class Callback<T> implements ObserverPairList.Callback<SetObserverPair<T>> {\n\n        private final SetChangeSet changeSet;\n\n        public Callback(SetChangeSet changeSet) {\n            this.changeSet = changeSet;\n        }\n\n        @Override\n        public void onCalled(SetObserverPair<T> pair, Object observer) {\n            pair.onChange(observer, changeSet);\n        }\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/internal/ObserverPairList.java",
    "content": "/*\n * Copyright 2016 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\npackage io.realm.internal;\n\n\nimport java.lang.ref.WeakReference;\nimport java.util.List;\nimport java.util.concurrent.CopyOnWriteArrayList;\n\n\n/**\n * An ObserverPairList holds a list of ObserverPairs. An {@link ObserverPair} is pair containing an observer and a\n * listener. The observer is the object to react to the changes through the listener. The observer is saved as a weak\n * reference in the pair to control the life cycle of the listener. When the observer gets GCed, the corresponding pair\n * will be removed from the list. So DO NOT keep a strong reference to the observer in the subclass of listener since it\n * will cause leaks!\n * <p>\n * This class is not thread safe and it is not supposed to be.\n *\n * @param <T> the type of {@link ObserverPair}.\n */\npublic class ObserverPairList<T extends ObserverPairList.ObserverPair> {\n\n    /**\n     * @param <T> the type of observer.\n     * @param <S> the type of listener.\n     */\n    public abstract static class ObserverPair<T, S> {\n        final WeakReference<T> observerRef;\n        protected final S listener;\n        // Should only be set by the outer class. To marked it as removed in case it is removed in foreach callback.\n        boolean removed = false;\n\n        public ObserverPair(T observer, S listener) {\n            this.listener = listener;\n            this.observerRef = new WeakReference<T>(observer);\n        }\n\n        // The two pairs will be treated as the same only when the observers are the same and the listeners are equal.\n        @Override\n        public boolean equals(Object obj) {\n            if (this == obj) {\n                return true;\n            }\n\n            if (obj instanceof ObserverPair) {\n                ObserverPair anotherPair = (ObserverPair) obj;\n                return listener.equals(anotherPair.listener) &&\n                        observerRef.get() == anotherPair.observerRef.get();\n            }\n            return false;\n        }\n\n        @Override\n        public int hashCode() {\n            T observer = observerRef.get();\n\n            int result = 17;\n            result = 31 * result + ((observer != null) ? observer.hashCode() : 0);\n            //noinspection ConstantConditions\n            result = 31 * result + ((listener != null) ? listener.hashCode() : 0);\n            return result;\n        }\n    }\n\n    /**\n     * Callback passed to the {@link #foreach(Callback)} call.\n     *\n     * @param <T> type of ObserverPair.\n     */\n    public interface Callback<T extends ObserverPair> {\n        void onCalled(T pair, Object observer);\n    }\n\n    private List<T> pairs = new CopyOnWriteArrayList<T>();\n    // In case the clear() called during the foreach loop.\n    private boolean cleared = false;\n\n    /**\n     * Iterate every valid pair in the list and call the callback on it. The pair with GCed observer will be removed and\n     * callback won't be executed. Before executing the callback, a strong reference to the observer will be kept and\n     * passed to the callback in case the observer gets GCed before callback returns.\n     *\n     * @param callback to be executed on the pair.\n     */\n    public void foreach(Callback<T> callback) {\n        for (T pair : pairs) {\n            if (cleared) {\n                break;\n            } else {\n                Object observer = pair.observerRef.get();\n                if (observer == null) {\n                    pairs.remove(pair);\n                } else if (!pair.removed) {\n                    callback.onCalled(pair, observer);\n                }\n            }\n        }\n    }\n\n    public boolean isEmpty() {\n        return pairs.isEmpty();\n    }\n\n    public void clear() {\n        cleared = true;\n        pairs.clear();\n    }\n\n    public void add(T pair) {\n        if (!pairs.contains(pair)) {\n            pairs.add(pair);\n            pair.removed = false;\n        }\n        if (cleared) {\n            cleared = false;\n        }\n    }\n\n    public <S, U> void remove(S observer, U listener) {\n        for (T pair : pairs) {\n            if (observer == pair.observerRef.get() && listener.equals(pair.listener)) {\n                pair.removed = true;\n                pairs.remove(pair);\n                break;\n            }\n        }\n    }\n\n    void removeByObserver(Object observer) {\n        for (T pair : pairs) {\n            Object object = pair.observerRef.get();\n            if (object == null || object == observer) {\n                pair.removed = true;\n                pairs.remove(pair);\n            }\n        }\n    }\n\n    public int size() {\n        return pairs.size();\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/internal/OsCollection.java",
    "content": "/*\n * Copyright 2021 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\npackage io.realm.internal;\n\npublic interface OsCollection {\n    boolean isValid();\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/internal/OsCollectionChangeSet.java",
    "content": "/*\n * Copyright 2017 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\npackage io.realm.internal;\n\nimport java.util.Arrays;\n\nimport io.realm.OrderedCollectionChangeSet;\n\n/**\n * Implementation of {@link OrderedCollectionChangeSet}. This class holds a pointer to the Object Store's\n * OsCollectionChangeSet and read from it only when needed. Creating an Java object from JNI when the collection\n * notification arrives, is avoided since we also support the collection listeners without a change set parameter,\n * parsing the change set may not be necessary all the time.\n */\npublic class OsCollectionChangeSet implements OrderedCollectionChangeSet, NativeObject {\n\n    // Used in JNI.\n    @SuppressWarnings(\"WeakerAccess\")\n    public static final int TYPE_DELETION = 0;\n    @SuppressWarnings(\"WeakerAccess\")\n    public static final int TYPE_INSERTION = 1;\n    @SuppressWarnings(\"WeakerAccess\")\n    public static final int TYPE_MODIFICATION = 2;\n    // Max array length is VM dependent. This is a safe value.\n    // See http://stackoverflow.com/questions/3038392/do-java-arrays-have-a-maximum-size\n    @SuppressWarnings({\"WeakerAccess\", \"unused\"})\n    public static final int MAX_ARRAY_LENGTH = Integer.MAX_VALUE - 8;\n\n    private static long finalizerPtr = nativeGetFinalizerPtr();\n    private final long nativePtr;\n    private final boolean firstAsyncCallback;\n\n    public OsCollectionChangeSet(long nativePtr, boolean firstAsyncCallback) {\n        this.nativePtr = nativePtr;\n        this.firstAsyncCallback = firstAsyncCallback;\n        NativeContext.dummyContext.addReference(this);\n    }\n\n    @Override\n    public State getState() {\n        throw new UnsupportedOperationException(\"This method should be overridden in a subclass\");\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    @Override\n    public int[] getDeletions() {\n        return nativeGetIndices(nativePtr, TYPE_DELETION);\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    @Override\n    public int[] getInsertions() {\n        return nativeGetIndices(nativePtr, TYPE_INSERTION);\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    @Override\n    public int[] getChanges() {\n        return nativeGetIndices(nativePtr, TYPE_MODIFICATION);\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    @Override\n    public Range[] getDeletionRanges() {\n        return longArrayToRangeArray(nativeGetRanges(nativePtr, TYPE_DELETION));\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    @Override\n    public Range[] getInsertionRanges() {\n        return longArrayToRangeArray(nativeGetRanges(nativePtr, TYPE_INSERTION));\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    @Override\n    public Range[] getChangeRanges() {\n        return longArrayToRangeArray(nativeGetRanges(nativePtr, TYPE_MODIFICATION));\n    }\n\n    @Override\n    public Throwable getError() {\n        return null;\n    }\n\n    /**\n     * Returns {@code true} if this is the first time an asynchronous query returns a result, i.e.\n     * the query completed. \n     */\n    public boolean isFirstAsyncCallback() {\n        return firstAsyncCallback;\n    }\n\n    /**\n     * Returns {@code true} if this changeset is empty, and doesn't contain any relevant changes.\n     */\n    public boolean isEmpty() {\n        // Since this wrap a Object Store changeset, it will always contains changes if an\n        // Object Store changeset exists.\n        return nativePtr == 0;\n    }\n\n    // Convert long array returned by the nativeGetXxxRanges() to Range array.\n    private Range[] longArrayToRangeArray(int[] longArray) {\n        //noinspection ConstantConditions\n        if (longArray == null) {\n            // Returns a size 0 array so we know JNI gets called.\n            return new Range[0];\n        }\n\n        Range[] ranges = new Range[longArray.length / 2];\n        for (int i = 0; i < ranges.length; i++) {\n            ranges[i] = new Range(longArray[i * 2], longArray[i * 2 + 1]);\n        }\n        return ranges;\n    }\n\n    @Override\n    public String toString() {\n        if (nativePtr == 0)  {\n            return \"Change set is empty.\";\n        }\n\n        String string = \"Deletion Ranges: \" +\n                Arrays.toString(getDeletionRanges()) +\n                \"\\n\" +\n                \"Insertion Ranges: \" +\n                Arrays.toString(getInsertionRanges()) +\n                \"\\n\" +\n                \"Change Ranges: \" +\n                Arrays.toString(getChangeRanges());\n        return string;\n\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    @Override\n    public long getNativePtr() {\n        return nativePtr;\n    }\n\n    @Override\n    public long getNativeFinalizerPtr() {\n        return finalizerPtr;\n    }\n\n    private static native long nativeGetFinalizerPtr();\n\n    // Returns the ranges as a long array. eg.: [startIndex1, length1, startIndex2, length2, ...]\n    private static native int[] nativeGetRanges(long nativePtr, int type);\n\n    // Returns the indices array.\n    private static native int[] nativeGetIndices(long nativePtr, int type);\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/internal/OsList.java",
    "content": "package io.realm.internal;\n\nimport org.bson.types.Decimal128;\nimport org.bson.types.ObjectId;\n\nimport java.util.Date;\nimport java.util.UUID;\n\nimport javax.annotation.Nullable;\n\nimport io.realm.OrderedRealmCollectionChangeListener;\nimport io.realm.RealmChangeListener;\n\n/**\n * Java wrapper of Object Store List class. This backs managed versions of RealmList.\n */\npublic class OsList implements NativeObject, ObservableCollection, OsCollection {\n\n    private final long nativePtr;\n    private final NativeContext context;\n    private final Table targetTable;\n    private static final long nativeFinalizerPtr = nativeGetFinalizerPtr();\n    private final ObserverPairList<CollectionObserverPair> observerPairs =\n            new ObserverPairList<>();\n\n    public OsList(UncheckedRow row, long columnKey) {\n        OsSharedRealm sharedRealm = row.getTable().getSharedRealm();\n        long[] ptrs = nativeCreate(sharedRealm.getNativePtr(), row.getNativePtr(), columnKey);\n\n        this.nativePtr = ptrs[0];\n        this.context = sharedRealm.context;\n        context.addReference(this);\n\n        if (ptrs[1] != 0) {\n            targetTable = new Table(sharedRealm, ptrs[1]);\n        } else {\n            targetTable = null;\n        }\n    }\n\n    // Use for creating a copy of the OsList, e.g when freezing it.\n    private OsList(OsSharedRealm sharedRealm, long listNativePtr, @Nullable Table targetTable) {\n        this.nativePtr = listNativePtr;\n        this.targetTable = targetTable;\n        this.context = sharedRealm.context;\n        context.addReference(this);\n    }\n\n    @Override\n    public long getNativePtr() {\n        return nativePtr;\n    }\n\n    @Override\n    public long getNativeFinalizerPtr() {\n        return nativeFinalizerPtr;\n    }\n\n    public UncheckedRow getUncheckedRow(long index) {\n        return targetTable.getUncheckedRowByPointer(nativeGetRow(nativePtr, index));\n    }\n\n    public void addRow(long targetRowIndex) {\n        nativeAddRow(nativePtr, targetRowIndex);\n    }\n\n    public void insertRow(long pos, long targetRowIndex) {\n        nativeInsertRow(nativePtr, pos, targetRowIndex);\n    }\n\n    public void setRow(long pos, long targetRowIndex) {\n        nativeSetRow(nativePtr, pos, targetRowIndex);\n    }\n\n    public void addNull() {\n        nativeAddNull(nativePtr);\n    }\n\n    public void insertNull(long pos) {\n        nativeInsertNull(nativePtr, pos);\n    }\n\n    public void setNull(long pos) {\n        nativeSetNull(nativePtr, pos);\n    }\n\n    public void addLong(long value) {\n        nativeAddLong(nativePtr, value);\n    }\n\n    public void insertLong(long pos, long value) {\n        nativeInsertLong(nativePtr, pos, value);\n    }\n\n    public void setLong(long pos, long value) {\n        nativeSetLong(nativePtr, pos, value);\n    }\n\n    public void addDouble(double value) {\n        nativeAddDouble(nativePtr, value);\n    }\n\n    public void insertDouble(long pos, double value) {\n        nativeInsertDouble(nativePtr, pos, value);\n    }\n\n    public void setDouble(long pos, double value) {\n        nativeSetDouble(nativePtr, pos, value);\n    }\n\n    public void addFloat(float value) {\n        nativeAddFloat(nativePtr, value);\n    }\n\n    public void insertFloat(long pos, float value) {\n        nativeInsertFloat(nativePtr, pos, value);\n    }\n\n    public void setFloat(long pos, float value) {\n        nativeSetFloat(nativePtr, pos, value);\n    }\n\n    public void addBoolean(boolean value) {\n        nativeAddBoolean(nativePtr, value);\n    }\n\n    public void insertBoolean(long pos, boolean value) {\n        nativeInsertBoolean(nativePtr, pos, value);\n    }\n\n    public void setBoolean(long pos, boolean value) {\n        nativeSetBoolean(nativePtr, pos, value);\n    }\n\n    public void addBinary(@Nullable byte[] value) {\n        nativeAddBinary(nativePtr, value);\n    }\n\n    public void insertBinary(long pos, @Nullable byte[] value) {\n        nativeInsertBinary(nativePtr, pos, value);\n    }\n\n    public void setBinary(long pos, @Nullable byte[] value) {\n        nativeSetBinary(nativePtr, pos, value);\n    }\n\n    public void addString(@Nullable String value) {\n        nativeAddString(nativePtr, value);\n    }\n\n    public void insertString(long pos, @Nullable String value) {\n        nativeInsertString(nativePtr, pos, value);\n    }\n\n    public void setString(long pos, @Nullable String value) {\n        nativeSetString(nativePtr, pos, value);\n    }\n\n    public void addDate(@Nullable Date value) {\n        if (value == null) {\n            nativeAddNull(nativePtr);\n        } else {\n            nativeAddDate(nativePtr, value.getTime());\n        }\n    }\n\n    public void insertDate(long pos, @Nullable Date value) {\n        if (value == null) {\n            nativeInsertNull(nativePtr, pos);\n        } else {\n            nativeInsertDate(nativePtr, pos, value.getTime());\n        }\n    }\n\n    public void setDate(long pos, @Nullable Date value) {\n        if (value == null) {\n            nativeSetNull(nativePtr, pos);\n        } else {\n            nativeSetDate(nativePtr, pos, value.getTime());\n        }\n    }\n\n    public void addDecimal128(@Nullable Decimal128 value) {\n        if (value == null) {\n            nativeAddNull(nativePtr);\n        } else {\n            nativeAddDecimal128(nativePtr, value.getLow(), value.getHigh());\n        }\n    }\n\n    public void insertDecimal128(long pos, @Nullable Decimal128 value) {\n        if (value == null) {\n            nativeInsertNull(nativePtr, pos);\n        } else {\n            nativeInsertDecimal128(nativePtr, pos, value.getLow(), value.getHigh());\n        }\n    }\n\n    public void setDecimal128(long pos, @Nullable Decimal128 value) {\n        if (value == null) {\n            nativeSetNull(nativePtr, pos);\n        } else {\n            nativeSetDecimal128(nativePtr, pos, value.getLow(), value.getHigh());\n        }\n    }\n\n    public void addObjectId(@Nullable ObjectId value) {\n        if (value == null) {\n            nativeAddNull(nativePtr);\n        } else {\n            nativeAddObjectId(nativePtr, value.toString());\n        }\n    }\n\n    public void insertObjectId(long pos, @Nullable ObjectId value) {\n        if (value == null) {\n            nativeInsertNull(nativePtr, pos);\n        } else {\n            nativeInsertObjectId(nativePtr, pos, value.toString());\n        }\n    }\n\n    public void setObjectId(long pos, @Nullable ObjectId value) {\n        if (value == null) {\n            nativeSetNull(nativePtr, pos);\n        } else {\n            nativeSetObjectId(nativePtr, pos, value.toString());\n        }\n    }\n\n    public void addUUID(@Nullable UUID value) {\n        if (value == null) {\n            nativeAddNull(nativePtr);\n        } else {\n            nativeAddUUID(nativePtr, value.toString());\n        }\n    }\n\n    public void insertUUID(long pos, @Nullable UUID value) {\n        if (value == null) {\n            nativeInsertNull(nativePtr, pos);\n        } else {\n            nativeInsertUUID(nativePtr, pos, value.toString());\n        }\n    }\n\n    public void setUUID(long pos, @Nullable UUID value) {\n        if (value == null) {\n            nativeSetNull(nativePtr, pos);\n        } else {\n            nativeSetUUID(nativePtr, pos, value.toString());\n        }\n    }\n\n    public void addRealmAny(long realmAnyPtr) {\n        nativeAddRealmAny(nativePtr, realmAnyPtr);\n    }\n\n    public void insertRealmAny(long pos, long realmAnyPtr) {\n        nativeInsertRealmAny(nativePtr, pos, realmAnyPtr);\n    }\n\n    public void setRealmAny(long pos, long realmAnyPtr) {\n        nativeSetRealmAny(nativePtr, pos, realmAnyPtr);\n    }\n\n    @Nullable\n    public Object getValue(long pos) {\n        return nativeGetValue(nativePtr, pos);\n    }\n\n    public void move(long sourceIndex, long targetIndex) {\n        nativeMove(nativePtr, sourceIndex, targetIndex);\n    }\n\n    public void remove(long index) {\n        nativeRemove(nativePtr, index);\n    }\n\n    public void removeAll() {\n        nativeRemoveAll(nativePtr);\n    }\n\n    public long size() {\n        return nativeSize(nativePtr);\n    }\n\n    public boolean isEmpty() {\n        return nativeSize(nativePtr) <= 0;\n    }\n\n    /**\n     * @return a {@link TableQuery} based on this list.\n     */\n    public TableQuery getQuery() {\n        return new TableQuery(context, targetTable, nativeGetQuery(nativePtr));\n    }\n\n    @Override\n    public boolean isValid() {\n        return nativeIsValid(nativePtr);\n    }\n\n    public void delete(long index) {\n        nativeDelete(nativePtr, index);\n    }\n\n    public void deleteAll() {\n        nativeDeleteAll(nativePtr);\n    }\n\n    public Table getTargetTable() {\n        return targetTable;\n    }\n\n    public <T> void addListener(T observer, OrderedRealmCollectionChangeListener<T> listener) {\n        if (observerPairs.isEmpty()) {\n            nativeStartListening(nativePtr);\n        }\n        CollectionObserverPair<T> collectionObserverPair = new CollectionObserverPair<T>(observer, listener);\n        observerPairs.add(collectionObserverPair);\n    }\n\n    public <T> void addListener(T observer, RealmChangeListener<T> listener) {\n        addListener(observer, new RealmChangeListenerWrapper<T>(listener));\n    }\n\n    public <T> void removeListener(T observer, OrderedRealmCollectionChangeListener<T> listener) {\n        observerPairs.remove(observer, listener);\n        if (observerPairs.isEmpty()) {\n            nativeStopListening(nativePtr);\n        }\n    }\n\n    public <T> void removeListener(T observer, RealmChangeListener<T> listener) {\n        removeListener(observer, new RealmChangeListenerWrapper<T>(listener));\n    }\n\n    public void removeAllListeners() {\n        observerPairs.clear();\n        nativeStopListening(nativePtr);\n    }\n\n    // Called by JNI\n    @Override\n    public void notifyChangeListeners(long nativeChangeSetPtr) {\n        OsCollectionChangeSet changeset = new OsCollectionChangeSet(nativeChangeSetPtr, false);\n        if (changeset.isEmpty()) {\n            // First time \"query\" returns. Do nothing.\n            return;\n        }\n        observerPairs.foreach(new Callback(changeset));\n    }\n\n    public OsList freeze(OsSharedRealm frozenRealm) {\n        return new OsList(frozenRealm,\n                nativeFreeze(nativePtr, frozenRealm.getNativePtr()),\n                (targetTable != null) ? targetTable.freeze(frozenRealm) : null);\n    }\n\n    public long createAndAddEmbeddedObject() {\n        return nativeCreateAndAddEmbeddedObject(nativePtr, size());\n    }\n\n    public long createAndAddEmbeddedObject(long index) {\n        return nativeCreateAndAddEmbeddedObject(nativePtr, index);\n    }\n\n    public long createAndSetEmbeddedObject(long index) {\n        return nativeCreateAndSetEmbeddedObject(nativePtr, index);\n    }\n\n\n    private static native long nativeGetFinalizerPtr();\n\n    // TODO: nativeTablePtr is not necessary. It is used to create FieldDescriptor which should be generated from\n    // OsSchemaInfo.\n    // Returns {nativeListPtr, nativeTablePtr}\n    private static native long[] nativeCreate(long nativeSharedRealmPtr, long nativeRowPtr, long columnKey);\n\n    private static native long nativeGetRow(long nativePtr, long index);\n\n    private static native void nativeAddRow(long nativePtr, long targetRowIndex);\n\n    private static native void nativeInsertRow(long nativePtr, long pos, long targetRowIndex);\n\n    private static native void nativeSetRow(long nativePtr, long pos, long targetRowIndex);\n\n    private static native void nativeMove(long nativePtr, long sourceIndex, long targetIndex);\n\n    private static native void nativeRemove(long nativePtr, long index);\n\n    private static native void nativeRemoveAll(long nativePtr);\n\n    private static native long nativeSize(long nativePtr);\n\n    private static native long nativeGetQuery(long nativePtr);\n\n    private static native boolean nativeIsValid(long nativePtr);\n\n    private static native void nativeDelete(long nativePtr, long index);\n\n    private static native void nativeDeleteAll(long nativePtr);\n\n    private static native void nativeAddNull(long nativePtr);\n\n    private static native void nativeInsertNull(long nativePtr, long pos);\n\n    private static native void nativeSetNull(long nativePtr, long pos);\n\n    private static native void nativeAddLong(long nativePtr, long value);\n\n    private static native void nativeInsertLong(long nativePtr, long pos, long value);\n\n    private static native void nativeSetLong(long nativePtr, long pos, long value);\n\n    private static native void nativeAddDouble(long nativePtr, double value);\n\n    private static native void nativeInsertDouble(long nativePtr, long pos, double value);\n\n    private static native void nativeSetDouble(long nativePtr, long pos, double value);\n\n    private static native void nativeAddFloat(long nativePtr, float value);\n\n    private static native void nativeInsertFloat(long nativePtr, long pos, float value);\n\n    private static native void nativeSetFloat(long nativePtr, long pos, float value);\n\n    private static native void nativeAddBoolean(long nativePtr, boolean value);\n\n    private static native void nativeInsertBoolean(long nativePtr, long pos, boolean value);\n\n    private static native void nativeSetBoolean(long nativePtr, long pos, boolean value);\n\n    private static native void nativeAddBinary(long nativePtr, @Nullable byte[] value);\n\n    private static native void nativeInsertBinary(long nativePtr, long pos, @Nullable byte[] value);\n\n    private static native void nativeSetBinary(long nativePtr, long pos, @Nullable byte[] value);\n\n    private static native void nativeAddDate(long nativePtr, long value);\n\n    private static native void nativeInsertDate(long nativePtr, long pos, long value);\n\n    private static native void nativeSetDate(long nativePtr, long pos, long value);\n\n    private static native void nativeAddString(long nativePtr, @Nullable String value);\n\n    private static native void nativeInsertString(long nativePtr, long pos, @Nullable String value);\n\n    private static native void nativeSetString(long nativePtr, long pos, @Nullable String value);\n\n    private static native void nativeAddDecimal128(long nativePtr, long low, long high);\n\n    private static native void nativeInsertDecimal128(long nativePtr, long pos, long low, long high);\n\n    private static native void nativeSetDecimal128(long nativePtr, long pos, long low, long high);\n\n    private static native void nativeAddObjectId(long nativePtr, String data);\n\n    private static native void nativeInsertObjectId(long nativePtr, long pos, String data);\n\n    private static native void nativeSetObjectId(long nativePtr, long pos, String data);\n\n    private static native void nativeAddUUID(long nativePtr, String data);\n\n    private static native void nativeInsertUUID(long nativePtr, long pos, String data);\n\n    private static native void nativeSetUUID(long nativePtr, long pos, String data);\n\n    private static native void nativeAddRealmAny(long nativePtr, long realmAnyPtr);\n\n    private static native void nativeInsertRealmAny(long nativePtr, long pos, long realmAnyPtr);\n\n    private static native void nativeSetRealmAny(long nativePtr, long pos, long realmAnyPtr);\n\n    private static native Object nativeGetValue(long nativePtr, long pos);\n\n    private native void nativeStartListening(long nativePtr);\n\n    private native void nativeStopListening(long nativePtr);\n\n    private static native long nativeFreeze(long nativePtr, long sharedRealmNativePtr);\n\n    // Create an \"empty\" embedded object at the end of the list\n    private static native long nativeCreateAndAddEmbeddedObject(long nativePtr, long index);\n\n    // Replaces the embedded object and index with a new \"empty\" embedded object\n    private static native long nativeCreateAndSetEmbeddedObject(long nativePtr, long index);\n\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/internal/OsMap.java",
    "content": "/*\n * Copyright 2020 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\npackage io.realm.internal;\n\nimport org.bson.types.Decimal128;\nimport org.bson.types.ObjectId;\n\nimport java.util.Date;\nimport java.util.UUID;\n\nimport javax.annotation.Nullable;\n\nimport io.realm.internal.android.TypeUtils;\nimport io.realm.internal.core.NativeRealmAny;\nimport io.realm.internal.util.Pair;\n\n/**\n * Java wrapper of Object Store Dictionary class. This backs managed versions of RealmMaps.\n */\npublic class OsMap implements NativeObject {\n\n    public static final int NOT_FOUND = -1;\n\n    private static final long nativeFinalizerPtr = nativeGetFinalizerPtr();\n\n    private final long nativePtr;\n    private final NativeContext context;\n    private final Table targetTable;\n\n    public OsMap(UncheckedRow row, long columnKey) {\n        OsSharedRealm osSharedRealm = row.getTable().getSharedRealm();\n        long[] pointers = nativeCreate(osSharedRealm.getNativePtr(), row.getNativePtr(), columnKey);\n        this.nativePtr = pointers[0];\n        if (pointers[1] != NOT_FOUND) {\n            this.targetTable = new Table(osSharedRealm, pointers[1]);\n        } else {\n            this.targetTable = null;\n        }\n        this.context = osSharedRealm.context;\n        context.addReference(this);\n    }\n\n    // Used to freeze maps\n    private OsMap(OsSharedRealm osSharedRealm, long nativePtr, Table targetTable) {\n        this.nativePtr = nativePtr;\n        this.targetTable = targetTable;\n        this.context = osSharedRealm.context;\n        context.addReference(this);\n    }\n\n    public Table getTargetTable() {\n        return targetTable;\n    }\n\n    @Override\n    public long getNativePtr() {\n        return nativePtr;\n    }\n\n    @Override\n    public long getNativeFinalizerPtr() {\n        return nativeFinalizerPtr;\n    }\n\n    public long size() {\n        return nativeSize(nativePtr);\n    }\n\n    public boolean containsKey(Object key) {\n        return nativeContainsKey(nativePtr, (String) key);\n    }\n\n    public boolean isValid() {\n        return nativeIsValid(nativePtr);\n    }\n\n    public boolean containsPrimitiveValue(@Nullable Object value) {\n        if (value == null) {\n            return nativeContainsNull(nativePtr);\n        } else if (value instanceof Integer) {\n            return nativeContainsLong(nativePtr, ((Integer) value).longValue());\n        } else if (value instanceof Long) {\n            return nativeContainsLong(nativePtr, (long) value);\n        } else if (value instanceof Double) {\n            return nativeContainsDouble(nativePtr, (double) value);\n        } else if (value instanceof Short) {\n            return nativeContainsLong(nativePtr, ((Short) value).longValue());\n        } else if (value instanceof Byte) {\n            return nativeContainsLong(nativePtr, ((Byte) value).longValue());\n        } else if (value instanceof Boolean) {\n            return nativeContainsBoolean(nativePtr, (boolean) value);\n        } else if (value instanceof String) {\n            return nativeContainsString(nativePtr, (String) value);\n        } else if (value instanceof Byte[]) {\n            return nativeContainsBinary(nativePtr, TypeUtils.convertNonPrimitiveBinaryToPrimitive((Byte[]) value));\n        } else if (value instanceof byte[]) {\n            return nativeContainsBinary(nativePtr, (byte[]) value);\n        } else if (value instanceof Float) {\n            return nativeContainsFloat(nativePtr, (float) value);\n        } else if (value instanceof UUID) {\n            return nativeContainsUUID(nativePtr, value.toString());\n        } else if (value instanceof ObjectId) {\n            return nativeContainsObjectId(nativePtr, ((ObjectId) value).toString());\n        } else if (value instanceof Date) {\n            return nativeContainsDate(nativePtr, ((Date) value).getTime());\n        } else if (value instanceof Decimal128) {\n            Decimal128 decimal128 = (Decimal128) value;\n            return nativeContainsDecimal128(nativePtr, decimal128.getHigh(), decimal128.getLow());\n        }\n        throw new IllegalArgumentException(\"Invalid object type: \" + value.getClass().getCanonicalName());\n    }\n\n    public boolean containsRealmAnyValue(long realmAnyPtr) {\n        return nativeContainsRealmAny(nativePtr, realmAnyPtr);\n    }\n\n    public boolean containsRealmModel(long objKey, long tablePtr) {\n        return nativeContainsRealmModel(nativePtr, objKey, tablePtr);\n    }\n\n    public void clear() {\n        nativeClear(nativePtr);\n    }\n\n    public Pair<Table, Long> tableAndKeyPtrs() {\n        return new Pair<>(targetTable, nativeKeys(nativePtr));\n    }\n\n    public Pair<Table, Long> tableAndValuePtrs() {\n        return new Pair<>(targetTable, nativeValues(nativePtr));\n    }\n\n    public OsMap freeze(OsSharedRealm osSharedRealm) {\n        return new OsMap(osSharedRealm, nativeFreeze(nativePtr, osSharedRealm.getNativePtr()), targetTable);\n    }\n\n    // ------------------------------------------\n    // TODO: handle other types of keys and avoid\n    //  typecasting directly to string in phase 2\n    //  for put and get methods.\n    // ------------------------------------------\n\n    public void put(Object key, @Nullable Object value) {\n        if (value == null) {\n            try {\n                nativePutNull(nativePtr, (String) key);\n            } catch (IllegalArgumentException e) {\n                if (e.getMessage().contains(\"Value cannot be null\")) {\n                    throw new NullPointerException(e.getMessage());\n                } else {\n                    throw e;\n                }\n            }\n        } else {\n            String valueClassName = value.getClass().getCanonicalName();\n            if (Long.class.getCanonicalName().equals(valueClassName)) {\n                nativePutLong(nativePtr, (String) key, (Long) value);\n            } else if (Integer.class.getCanonicalName().equals(valueClassName)) {\n                nativePutLong(nativePtr, (String) key, (Integer) value);\n            } else if (Short.class.getCanonicalName().equals(valueClassName)) {\n                nativePutLong(nativePtr, (String) key, (Short) value);\n            } else if (Byte.class.getCanonicalName().equals(valueClassName)) {\n                nativePutLong(nativePtr, (String) key, (Byte) value);\n            } else if (Float.class.getCanonicalName().equals(valueClassName)) {\n                nativePutFloat(nativePtr, (String) key, (Float) value);\n            } else if (Double.class.getCanonicalName().equals(valueClassName)) {\n                nativePutDouble(nativePtr, (String) key, (Double) value);\n            } else if (String.class.getCanonicalName().equals(valueClassName)) {\n                nativePutString(nativePtr, (String) key, (String) value);\n            } else if (Boolean.class.getCanonicalName().equals(valueClassName)) {\n                nativePutBoolean(nativePtr, (String) key, (Boolean) value);\n            } else if (Date.class.getCanonicalName().equals(valueClassName)) {\n                nativePutDate(nativePtr, (String) key, ((Date) value).getTime());\n            } else if (Decimal128.class.getCanonicalName().equals(valueClassName)) {\n                Decimal128 decimal128 = (Decimal128) value;\n                nativePutDecimal128(nativePtr, (String) key, decimal128.getHigh(), decimal128.getLow());\n            } else if (Byte[].class.getCanonicalName().equals(valueClassName)) {\n                nativePutBinary(nativePtr, (String) key, TypeUtils.convertNonPrimitiveBinaryToPrimitive((Byte[]) value));\n            } else if (byte[].class.getCanonicalName().equals(valueClassName)) {\n                nativePutBinary(nativePtr, (String) key, (byte[]) value);\n            } else if (ObjectId.class.getCanonicalName().equals(valueClassName)) {\n                nativePutObjectId(nativePtr, (String) key, ((ObjectId) value).toString());\n            } else if (UUID.class.getCanonicalName().equals(valueClassName)) {\n                nativePutUUID(nativePtr, (String) key, value.toString());\n            } else {\n                throw new UnsupportedOperationException(\"Class '\" + valueClassName + \"' not supported.\");\n            }\n        }\n    }\n\n    public void putRow(Object key, long objKey) {\n        nativePutRow(nativePtr, (String) key, objKey);\n    }\n\n    public void putRealmAny(Object key, long nativeRealmAnyPtr) {\n        nativePutRealmAny(nativePtr, (String) key, nativeRealmAnyPtr);\n    }\n\n    // TODO: add more put methods for different value types ad-hoc\n\n    public void remove(Object key) {\n        nativeRemove(nativePtr, (String) key);\n    }\n\n    public long getModelRowKey(Object key) {\n        return nativeGetRow(nativePtr, (String) key);\n    }\n\n    @Nullable\n    public Object get(Object key) {\n        return nativeGetValue(nativePtr, (String) key);\n    }\n\n    public long getRealmAnyPtr(Object key) {\n        return nativeGetRealmAnyPtr(nativePtr, (String) key);\n    }\n\n    public long createAndPutEmbeddedObject(Object key) {\n        return nativeCreateAndPutEmbeddedObject(nativePtr, (String) key);\n    }\n\n    public <K> Pair<K, Object> getEntryForPrimitive(int position) {\n        // entry from OsMap is an array: entry[0] is key and entry[1] is the object key\n        Object[] entry = nativeGetEntryForPrimitive(nativePtr, position);\n        String key = (String) entry[0];\n\n        //noinspection unchecked\n        return new Pair<>((K) key, entry[1]);\n    }\n\n    public <K> Pair<K, Long> getKeyObjRowPair(int position) {\n        // entry from OsMap is an array: entry[0] is key and entry[1] is the object key\n        Object[] entry = nativeGetEntryForModel(nativePtr, position);\n        String key = (String) entry[0];\n        long objRow = (long) entry[1];\n\n        if (objRow == NOT_FOUND) {\n            //noinspection unchecked\n            return new Pair<>((K) key, (long) NOT_FOUND);\n        }\n\n        //noinspection unchecked\n        return new Pair<>((K) key, objRow);\n    }\n\n    public <K> Pair<K, NativeRealmAny> getKeyRealmAnyPair(int position) {\n        // entry from OsMap is an array: entry[0] is key and entry[1] is a RealmAny value\n        Object[] entry = nativeGetEntryForRealmAny(nativePtr, position);\n        String key = (String) entry[0];\n        NativeRealmAny nativeRealmAny = new NativeRealmAny((long) entry[1]);\n\n        //noinspection unchecked\n        return new Pair<>((K) key, nativeRealmAny);\n    }\n\n    public void startListening(ObservableMap observableMap) {\n        nativeStartListening(nativePtr, observableMap);\n    }\n\n    public void stopListening() {\n        nativeStopListening(nativePtr);\n    }\n\n    private static native long nativeGetFinalizerPtr();\n\n    private static native long[] nativeCreate(long sharedRealmPtr, long nativeRowPtr, long columnKey);\n\n    private static native Object nativeGetValue(long nativePtr, String key);\n\n    private static native long nativeGetRealmAnyPtr(long nativePtr, String key);\n\n    private static native long nativeGetRow(long nativePtr, String key);\n\n    private static native void nativePutNull(long nativePtr, String key);\n\n    private static native void nativePutLong(long nativePtr, String key, long value);\n\n    private static native void nativePutFloat(long nativePtr, String key, float value);\n\n    private static native void nativePutDouble(long nativePtr, String key, double value);\n\n    private static native void nativePutString(long nativePtr, String key, String value);\n\n    private static native void nativePutBoolean(long nativePtr, String key, boolean value);\n\n    private static native void nativePutDate(long nativePtr, String key, long value);\n\n    private static native void nativePutDecimal128(long nativePtr, String key, long high, long low);\n\n    private static native void nativePutBinary(long nativePtr, String key, byte[] value);\n\n    private static native void nativePutObjectId(long nativePtr, String key, String value);\n\n    private static native void nativePutUUID(long nativePtr, String key, String value);\n\n    private static native void nativePutRealmAny(long nativePtr, String key, long nativeRealmAnyPtr);\n\n    private static native void nativePutRow(long nativePtr, String key, long objKey);\n\n    private static native long nativeSize(long nativePtr);\n\n    private static native boolean nativeContainsKey(long nativePtr, String key);\n\n    private static native boolean nativeIsValid(long nativePtr);\n\n    private static native void nativeClear(long nativePtr);\n\n    private static native void nativeRemove(long nativePtr, String key);\n\n    private static native long nativeKeys(long nativePtr);\n\n    private static native long nativeValues(long nativePtr);\n\n    private static native long nativeFreeze(long nativePtr, long realmPtr);\n\n    private static native long nativeCreateAndPutEmbeddedObject(long nativePtr, String key);\n\n    private static native Object[] nativeGetEntryForModel(long nativePtr, int position);\n\n    private static native Object[] nativeGetEntryForRealmAny(long nativePtr, int position);\n\n    private static native Object[] nativeGetEntryForPrimitive(long nativePtr, int position);\n\n    private static native boolean nativeContainsNull(long nativePtr);\n\n    private static native boolean nativeContainsDouble(long nativePtr, double value);\n\n    private static native boolean nativeContainsLong(long nativePtr, long value);\n\n    private static native boolean nativeContainsBoolean(long nativePtr, boolean value);\n\n    private static native boolean nativeContainsString(long nativePtr, String value);\n\n    private static native boolean nativeContainsBinary(long nativePtr, byte[] value);\n\n    private static native boolean nativeContainsFloat(long nativePtr, float value);\n\n    private static native boolean nativeContainsObjectId(long nativePtr, String value);\n\n    private static native boolean nativeContainsUUID(long nativePtr, String value);\n\n    private static native boolean nativeContainsDate(long nativePtr, long value);\n\n    private static native boolean nativeContainsDecimal128(long nativePtr, long high, long low);\n\n    private static native boolean nativeContainsRealmAny(long nativePtr, long realmAnyPtr);\n\n    private static native boolean nativeContainsRealmModel(long nativePtr, long objKey, long tablePtr);\n\n    private static native void nativeStartListening(long nativePtr, ObservableMap observableMap);\n\n    private static native void nativeStopListening(long nativePtr);\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/internal/OsMapChangeSet.java",
    "content": "/*\n * Copyright 2021 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\npackage io.realm.internal;\n\n/**\n * Similar to OsCollectionChangeSet. This class holds a pointer to the OS's map change set and read\n * from it only when needed.\n */\npublic class OsMapChangeSet implements NativeObject {\n\n    public static final int EMPTY_CHANGESET = 0;\n\n    private static long finalizerPtr = nativeGetFinalizerPtr();\n\n    private final long nativePtr;\n\n    public OsMapChangeSet(long nativePtr) {\n        this.nativePtr = nativePtr;\n    }\n\n    @Override\n    public long getNativePtr() {\n        return nativePtr;\n    }\n\n    @Override\n    public long getNativeFinalizerPtr() {\n        return finalizerPtr;\n    }\n\n    public boolean isEmpty() {\n        return nativePtr == OsMapChangeSet.EMPTY_CHANGESET;\n    }\n\n    public String[] getStringKeyDeletions() {\n        return nativeGetStringKeyDeletions(nativePtr);\n    }\n\n    public String[] getStringKeyInsertions() {\n        return nativeGetStringKeyInsertions(nativePtr);\n    }\n\n    public String[] getStringKeyModifications() {\n        return nativeGetStringKeyModifications(nativePtr);\n    }\n\n    // TODO: add more insertions and modifications methods for other types of keys ad-hoc\n\n    private static native long nativeGetFinalizerPtr();\n\n    private static native String[] nativeGetStringKeyDeletions(long nativePtr);\n\n    private static native String[] nativeGetStringKeyInsertions(long nativePtr);\n\n    private static native String[] nativeGetStringKeyModifications(long nativePtr);\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/internal/OsObject.java",
    "content": "/*\n * Copyright 2017 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\npackage io.realm.internal;\n\nimport org.bson.types.ObjectId;\n\nimport java.util.UUID;\n\nimport javax.annotation.Nullable;\n\nimport io.realm.ObjectChangeSet;\nimport io.realm.RealmFieldType;\nimport io.realm.RealmModel;\nimport io.realm.RealmObjectChangeListener;\nimport io.realm.exceptions.RealmException;\n\n\n/**\n * Java wrapper for Object Store's {@code Object} class.\n */\n@Keep\npublic class OsObject implements NativeObject {\n\n    private static class OsObjectChangeSet implements ObjectChangeSet {\n        final String[] changedFields;\n        final boolean deleted;\n\n        OsObjectChangeSet(String[] changedFields, boolean deleted) {\n            this.changedFields = changedFields;\n            this.deleted = deleted;\n        }\n\n        @Override\n        public boolean isDeleted() {\n            return deleted;\n        }\n\n        @Override\n        public String[] getChangedFields() {\n            return changedFields;\n        }\n\n        @Override\n        public boolean isFieldChanged(String fieldName) {\n            for (String name : changedFields) {\n                if (name.equals(fieldName)) {\n                    return true;\n                }\n            }\n            return false;\n        }\n    }\n\n    public static class ObjectObserverPair<T extends RealmModel>\n            extends ObserverPairList.ObserverPair<T, RealmObjectChangeListener<T>> {\n        public ObjectObserverPair(T observer, RealmObjectChangeListener<T> listener) {\n            super(observer, listener);\n        }\n\n        public void onChange(T observer, @Nullable ObjectChangeSet changeSet) {\n            listener.onChange(observer, changeSet);\n        }\n    }\n\n    private static class Callback implements ObserverPairList.Callback<ObjectObserverPair> {\n        private final String[] changedFields;\n\n        Callback(String[] changedFields) {\n            this.changedFields = changedFields;\n        }\n\n        private ObjectChangeSet createChangeSet() {\n            boolean isDeleted = changedFields == null;\n            return new OsObjectChangeSet(isDeleted ? new String[0] : changedFields, isDeleted);\n        }\n\n        @Override\n        public void onCalled(ObjectObserverPair pair, Object observer) {\n            //noinspection unchecked\n            pair.onChange((RealmModel) observer, createChangeSet());\n        }\n    }\n\n    private final long nativePtr;\n    private static final long nativeFinalizerPtr = nativeGetFinalizerPtr();\n\n    private ObserverPairList<ObjectObserverPair> observerPairs = new ObserverPairList<ObjectObserverPair>();\n\n    public OsObject(OsSharedRealm sharedRealm, UncheckedRow row) {\n        nativePtr = nativeCreate(sharedRealm.getNativePtr(), row.getNativePtr());\n        sharedRealm.context.addReference(this);\n    }\n\n    @Override\n    public long getNativePtr() {\n        return nativePtr;\n    }\n\n    @Override\n    public long getNativeFinalizerPtr() {\n        return nativeFinalizerPtr;\n    }\n\n    public <T extends RealmModel> void addListener(T observer, RealmObjectChangeListener<T> listener) {\n        if (observerPairs.isEmpty()) {\n            nativeStartListening(nativePtr);\n        }\n        ObjectObserverPair<T> pair = new ObjectObserverPair<T>(observer, listener);\n        observerPairs.add(pair);\n    }\n\n    public <T extends RealmModel> void removeListener(T observer) {\n        observerPairs.removeByObserver(observer);\n        if (observerPairs.isEmpty()) {\n            nativeStopListening(nativePtr);\n        }\n    }\n\n    public <T extends RealmModel> void removeListener(T observer, RealmObjectChangeListener<T> listener) {\n        observerPairs.remove(observer, listener);\n        if (observerPairs.isEmpty()) {\n            nativeStopListening(nativePtr);\n        }\n    }\n\n    // Set the ObserverPairList. This is useful for the findAllAsync. When the pendingRow returns the results, the whole\n    // listener list has to be moved from ProxyState to here.\n    public void setObserverPairs(ObserverPairList<ObjectObserverPair> pairs) {\n        if (!observerPairs.isEmpty()) {\n            throw new IllegalStateException(\"'observerPairs' is not empty. Listeners have been added before.\");\n        }\n\n        observerPairs = pairs;\n        if (!pairs.isEmpty()) {\n            nativeStartListening(nativePtr);\n        }\n    }\n\n    // TODO: consider to return a OsObject instead when integrating with Object Store's object accessor.\n    /**\n     * Create an object in the given table which doesn't have a primary key column defined.\n     *\n     * @param table the table where the object is created. This table must be atached to {@link OsSharedRealm}.\n     * @return a newly created {@code UncheckedRow}.\n     */\n    public static UncheckedRow create(Table table) {\n        final OsSharedRealm sharedRealm = table.getSharedRealm();\n        return new UncheckedRow(sharedRealm.context, table,\n                nativeCreateNewObject(table.getNativePtr()));\n    }\n\n    /**\n     * Create a row in the given table which doesn't have a primary key column defined.\n     * This is used for the fast bulk insertion.\n     *\n     * @param table the table where the object is created.\n     * @return a newly created row's index.\n     */\n    public static long createRow(Table table) {\n        return nativeCreateRow(table.getNativePtr());\n    }\n\n    private static long getAndVerifyPrimaryKeyColumnIndex(Table table) {\n        String pkField = OsObjectStore.getPrimaryKeyForObject(table.getSharedRealm(), table.getClassName());\n        if (pkField == null) {\n            throw new IllegalStateException(table.getName() + \" has no primary key defined.\");\n        }\n        return table.getColumnKey(pkField);\n    }\n\n    // TODO: consider to return a OsObject instead when integrating with Object Store's object accessor.\n    /**\n     * Create an object in the given table which has a primary key column defined, and set the primary key with given\n     * value.\n     *\n     * @param table the table where the object is created. This table must be atached to {@link OsSharedRealm}.\n     * @return a newly created {@code UncheckedRow}.\n     */\n    public static UncheckedRow createWithPrimaryKey(Table table, @Nullable Object primaryKeyValue) {\n        long primaryKeyColumnKey = getAndVerifyPrimaryKeyColumnIndex(table);\n        RealmFieldType type = table.getColumnType(primaryKeyColumnKey);\n        final OsSharedRealm sharedRealm = table.getSharedRealm();\n\n        if (type == RealmFieldType.STRING) {\n            if (primaryKeyValue != null && !(primaryKeyValue instanceof String)) {\n                throw new IllegalArgumentException(\"Primary key value is not a String: \" + primaryKeyValue);\n            }\n            return new UncheckedRow(sharedRealm.context, table,\n                    nativeCreateNewObjectWithStringPrimaryKey(sharedRealm.getNativePtr(), table.getNativePtr(),\n                            primaryKeyColumnKey, (String) primaryKeyValue));\n\n        } else if (type == RealmFieldType.INTEGER) {\n            long value = primaryKeyValue == null ? 0 : Long.parseLong(primaryKeyValue.toString());\n            return new UncheckedRow(sharedRealm.context, table,\n                    nativeCreateNewObjectWithLongPrimaryKey(sharedRealm.getNativePtr(), table.getNativePtr(),\n                            primaryKeyColumnKey, value, primaryKeyValue == null));\n        } else if (type == RealmFieldType.OBJECT_ID) {\n            String objectIdValue = primaryKeyValue == null ? null : primaryKeyValue.toString();\n            return new UncheckedRow(sharedRealm.context, table,\n                    nativeCreateNewObjectWithObjectIdPrimaryKey(sharedRealm.getNativePtr(), table.getNativePtr(),\n                            primaryKeyColumnKey, objectIdValue));\n        } else if (type == RealmFieldType.UUID) {\n            String uuidValue = primaryKeyValue == null ? null : primaryKeyValue.toString();\n            return new UncheckedRow(sharedRealm.context, table,\n                    nativeCreateNewObjectWithUUIDPrimaryKey(sharedRealm.getNativePtr(), table.getNativePtr(),\n                            primaryKeyColumnKey, uuidValue));\n        } else {\n            throw new RealmException(\"Cannot check for duplicate rows for unsupported primary key type: \" + type);\n        }\n    }\n\n    /**\n     * Create an object in the given table which has a primary key column defined, and set the primary key with given\n     * value.\n     * This is used for the fast bulk insertion.\n     *\n     * @param table the table where the object is created.\n     * @param primaryKeyColumnIndex the column index of primary key field.\n     * @param primaryKeyValue the primary key value.\n     * @return a newly created {@code UncheckedRow}.\n     */\n    // FIXME: Proxy could just pass the pk index here which is much faster.\n    public static long createRowWithPrimaryKey(Table table, long primaryKeyColumnIndex, @Nullable Object primaryKeyValue) {\n        RealmFieldType type = table.getColumnType(primaryKeyColumnIndex);\n        final OsSharedRealm sharedRealm = table.getSharedRealm();\n\n        if (type == RealmFieldType.STRING) {\n            if (primaryKeyValue != null && !(primaryKeyValue instanceof String)) {\n                throw new IllegalArgumentException(\"Primary key value is not a String: \" + primaryKeyValue);\n            }\n            return nativeCreateRowWithStringPrimaryKey(sharedRealm.getNativePtr(), table.getNativePtr(),\n                    primaryKeyColumnIndex, (String) primaryKeyValue);\n\n        } else if (type == RealmFieldType.INTEGER) {\n            long value = primaryKeyValue == null ? 0 : Long.parseLong(primaryKeyValue.toString());\n            return nativeCreateRowWithLongPrimaryKey(sharedRealm.getNativePtr(), table.getNativePtr(),\n                    primaryKeyColumnIndex, value, primaryKeyValue == null);\n        } else if (type == RealmFieldType.OBJECT_ID) {\n            if (primaryKeyValue != null && !(primaryKeyValue instanceof ObjectId)) {\n                throw new IllegalArgumentException(\"Primary key value is not an ObjectId: \" + primaryKeyValue);\n            }\n            String objectIdValue = primaryKeyValue == null ? null : primaryKeyValue.toString();\n            return nativeCreateRowWithObjectIdPrimaryKey(sharedRealm.getNativePtr(), table.getNativePtr(),\n                    primaryKeyColumnIndex, objectIdValue);\n        } else if (type == RealmFieldType.UUID) {\n            if (primaryKeyValue != null && !(primaryKeyValue instanceof UUID)) {\n                throw new IllegalArgumentException(\"Primary key value is not an UUID: \" + primaryKeyValue);\n            }\n            String uuidValue = primaryKeyValue == null ? null : primaryKeyValue.toString();\n            return nativeCreateRowWithUUIDPrimaryKey(sharedRealm.getNativePtr(), table.getNativePtr(),\n                    primaryKeyColumnIndex, uuidValue);\n        } else {\n            throw new RealmException(\"Cannot check for duplicate rows for unsupported primary key type: \" + type);\n        }\n    }\n\n    public static long createEmbeddedObject(Table parentTable, long parentObjectKey, long parentColumnKey) {\n        return nativeCreateEmbeddedObject(parentTable.getNativePtr(), parentObjectKey, parentColumnKey);\n    }\n\n    // Called by JNI\n    @SuppressWarnings(\"unused\")\n    private void notifyChangeListeners(String[] changedFields) {\n        observerPairs.foreach(new Callback(changedFields));\n    }\n\n    private static native long nativeGetFinalizerPtr();\n\n    private static native long nativeCreate(long shared_realm_ptr, long rowPtr);\n\n    private native void nativeStartListening(long nativePtr);\n\n    private native void nativeStopListening(long nativePtr);\n\n    private static native long nativeCreateNewObject(long tableRefPtr);\n\n    private static native long nativeCreateRow(long tableRefPtr);\n\n\n    // Return a pointer to newly created Row. We may need to return a OsObject pointer in the future.\n    private static native long nativeCreateNewObjectWithLongPrimaryKey(long sharedRealmPtr,\n                                                                       long tableRefPtr, long pk_column_index,\n                                                                       long primaryKeyValue, boolean isNullValue);\n\n    // Return a index of newly created Row.\n    private static native long nativeCreateRowWithLongPrimaryKey(long sharedRealmPtr,\n                                                                 long tableRefPtr, long pk_column_index,\n                                                                 long primaryKeyValue, boolean isNullValue);\n\n    // Return a pointer to newly created Row. We may need to return a OsObject pointer in the future.\n    private static native long nativeCreateNewObjectWithStringPrimaryKey(long sharedRealmPtr,\n                                                                         long tableRefPtr, long pk_column_index,\n                                                                         @Nullable String primaryKeyValue);\n\n    // Return a index of newly created Row.\n    private static native long nativeCreateRowWithStringPrimaryKey(long sharedRealmPtr,\n                                                                   long tableRefPtr, long pk_column_index,\n                                                                   @Nullable String primaryKeyValue);\n\n    private static native long nativeCreateRowWithObjectIdPrimaryKey(long sharedRealmPtr,\n                                                                     long tableRefPtr, long pk_column_index,\n                                                                     @Nullable String primaryKeyValue);\n\n    private static native long nativeCreateNewObjectWithObjectIdPrimaryKey(long sharedRealmPtr,\n                                                                           long tableRefPtr, long pk_column_index,\n                                                                           @Nullable String data);\n\n    private static native long nativeCreateRowWithUUIDPrimaryKey(long sharedRealmPtr,\n                                                                     long tableRefPtr, long pk_column_index,\n                                                                     @Nullable String primaryKeyValue);\n\n    private static native long nativeCreateNewObjectWithUUIDPrimaryKey(long sharedRealmPtr,\n                                                                           long tableRefPtr, long pk_column_index,\n                                                                           @Nullable String data);\n\n    private static native long nativeCreateEmbeddedObject(long parentTablePtr, long parentObjectKey, long parentObjectColumnKey);\n\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/internal/OsObjectSchemaInfo.java",
    "content": "/*\n * Copyright 2017 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 */\npackage io.realm.internal;\n\n\nimport javax.annotation.Nullable;\n\nimport io.realm.RealmFieldType;\n\n/**\n * Immutable Java wrapper for Object Store ObjectSchema.\n *\n * @see OsSchemaInfo\n */\npublic class OsObjectSchemaInfo implements NativeObject {\n\n    public static class Builder {\n        private final String internalClassName;\n        private final String publicClassName; // If \"\", it is equal to the internal class name\n        private final long[] persistedPropertyPtrArray;\n        private final boolean embedded;\n        private int persistedPropertyPtrCurPos = 0;\n        private final long[] computedPropertyPtrArray;\n        private int computedPropertyPtrCurPos = 0;\n\n        /**\n         * Creates an empty builder for {@code OsObjectSchemaInfo}. This constructor is intended to be used by\n         * the validation of schema, object schemas and properties through the object store.\n         *\n         * @param internalClassName name of the class\n         */\n        public Builder(String internalClassName, boolean embedded, int persistedPropertyCapacity, int computedPropertyCapacity) {\n            this.publicClassName = \"\";\n            this.internalClassName = internalClassName;\n            this.embedded = embedded;\n            this.persistedPropertyPtrArray = new long[persistedPropertyCapacity];\n            this.computedPropertyPtrArray = new long[computedPropertyCapacity];\n        }\n\n        public Builder(String publicClassName, String internalClassName, boolean embedded, int persistedPropertyCapacity, int computedPropertyCapacity) {\n            this.publicClassName = publicClassName;\n            this.internalClassName = internalClassName;\n            this.embedded = embedded;\n            this.persistedPropertyPtrArray = new long[persistedPropertyCapacity];\n            this.computedPropertyPtrArray = new long[computedPropertyCapacity];\n        }\n\n\n        /**\n         * Adds a persisted non-link, non value list property to this builder.\n         *\n         * @param publicName the name of the property as defined in the Java/Kotlin model class.\n         * @param internalName the internal name of the property if different from the public name, otherwise \"\".\n         * @param type the type of the property.\n         * @param isPrimaryKey set to true if this property is the primary key.\n         * @param isIndexed set to true if this property needs an index.\n         * @param isRequired set to true if this property is not nullable.\n         * @return this {@code OsObjectSchemaInfo}.\n         */\n        public Builder addPersistedProperty(String publicName, String internalName, RealmFieldType type, boolean isPrimaryKey, boolean isIndexed,\n                boolean isRequired) {\n            long propertyPtr = Property.nativeCreatePersistedProperty(internalName, publicName,\n                    Property.convertFromRealmFieldType(type, isRequired), isPrimaryKey, isIndexed);\n            persistedPropertyPtrArray[persistedPropertyPtrCurPos] = propertyPtr;\n            persistedPropertyPtrCurPos++;\n            return this;\n        }\n\n        /**\n         * Adds a persisted value list property to this builder.\n         *\n         * @param publicName the name of the property as defined in the Java/Kotlin model class.\n         * @param internalName the internal name of the property if different from the public name, otherwise \"\".\n         * @param type the type of the property. It must be one of value list type.\n         * @param isRequired set to true if this property is not nullable.\n         * @return this {@code OsObjectSchemaInfo}.\n         */\n        public Builder addPersistedValueListProperty(String publicName, String internalName, RealmFieldType type, boolean isRequired) {\n            long propertyPtr = Property.nativeCreatePersistedProperty(internalName,\n                    publicName,\n                    Property.convertFromRealmFieldType(type, isRequired),\n                    !Property.PRIMARY_KEY,\n                    !Property.INDEXED);\n            persistedPropertyPtrArray[persistedPropertyPtrCurPos] = propertyPtr;\n            persistedPropertyPtrCurPos++;\n            return this;\n        }\n\n        /**\n         * Adds a persisted map property to this builder.\n         *\n         * @param publicName the name of the property as defined in the Java/Kotlin model class.\n         * @param internalName the internal name of the property if different from the public name, otherwise \"\".\n         * @param type the type of the property. It must be one of value list type.\n         * @param isRequired set to true if this property is not nullable.\n         * @return this {@code OsObjectSchemaInfo}.\n         */\n        public Builder addPersistedMapProperty(String publicName, String internalName, RealmFieldType type, boolean isRequired) {\n            long propertyPtr = Property.nativeCreatePersistedProperty(internalName,\n                    publicName,\n                    Property.convertFromRealmFieldType(type, isRequired),\n                    !Property.PRIMARY_KEY,\n                    !Property.INDEXED);\n            persistedPropertyPtrArray[persistedPropertyPtrCurPos] = propertyPtr;\n            persistedPropertyPtrCurPos++;\n            return this;\n        }\n\n        /**\n         * TODO: UNIFY THIS AND THE TWO ABOVE\n         *\n         * Adds a persisted set property to this builder.\n         *\n         * @param publicName the name of the property as defined in the Java/Kotlin model class.\n         * @param internalName the internal name of the property if different from the public name, otherwise \"\".\n         * @param type the type of the property. It must be one of value list type.\n         * @param isRequired set to true if this property is not nullable.\n         * @return this {@code OsObjectSchemaInfo}.\n         */\n        public Builder addPersistedSetProperty(String publicName, String internalName, RealmFieldType type, boolean isRequired) {\n            long propertyPtr = Property.nativeCreatePersistedProperty(internalName,\n                    publicName,\n                    Property.convertFromRealmFieldType(type, isRequired),\n                    !Property.PRIMARY_KEY,\n                    !Property.INDEXED);\n            persistedPropertyPtrArray[persistedPropertyPtrCurPos] = propertyPtr;\n            persistedPropertyPtrCurPos++;\n            return this;\n        }\n\n        /**\n         * Adds a persisted link property to this {@code OsObjectSchemaInfo}. A persisted link property will be stored\n         * in the Realm file's schema.\n         *\n         * @param publicName the name of the property as defined in the Java/Kotlin model class.\n         * @param internalName the internal name of the property if different from the public name, otherwise \"\".\n         * @param type the type of the link property. Can only be {@link RealmFieldType#OBJECT} or\n         * {@link RealmFieldType#LIST}.\n         * @return this {@code OsObjectSchemaInfo.Builder}.\n         */\n        public Builder addPersistedLinkProperty(String publicName, String internalName, RealmFieldType type, String linkedClassName) {\n            long propertyPtr = Property.nativeCreatePersistedLinkProperty(internalName, publicName,\n                    Property.convertFromRealmFieldType(type, false), linkedClassName);\n            persistedPropertyPtrArray[persistedPropertyPtrCurPos] = propertyPtr;\n            persistedPropertyPtrCurPos++;\n            return this;\n        }\n\n        /**\n         * Adds a computed link property to this {@code OsObjectSchemaInfo}. A computed link property doesn't store\n         * information in the Realm file's schema. This property type will always be\n         * {@link RealmFieldType#LINKING_OBJECTS}.\n         *\n         * @param name the name of the property .\n         * @param sourceClass The class name of the the class linking to this class, ie. the source class.\n         * @param sourceClassName The field name in the source class that links to this class.\n         * @return this {@code OsObjectSchemaInfo.Builder}.\n         */\n        public Builder addComputedLinkProperty(String name, String sourceClass, String sourceClassName) {\n            long propertyPtr = Property.nativeCreateComputedLinkProperty(name, sourceClass, sourceClassName);\n            computedPropertyPtrArray[computedPropertyPtrCurPos] = propertyPtr;\n            computedPropertyPtrCurPos++;\n            return this;\n        }\n\n        /**\n         * Creates {@link OsObjectSchemaInfo} object from this builder. After calling, this {@code Builder} becomes\n         * invalid. All the property pointers will be freed.\n         *\n         * @return a newly created {@link OsObjectSchemaInfo}.\n         */\n        public OsObjectSchemaInfo build() {\n            if (persistedPropertyPtrCurPos == -1 || computedPropertyPtrCurPos == -1) {\n                throw new IllegalStateException(\"'OsObjectSchemaInfo.build()' has been called before on this object.\");\n            }\n            OsObjectSchemaInfo info = new OsObjectSchemaInfo(publicClassName, internalClassName, embedded);\n            nativeAddProperties(info.nativePtr, persistedPropertyPtrArray, computedPropertyPtrArray);\n            persistedPropertyPtrCurPos = -1;\n            computedPropertyPtrCurPos = -1;\n            return info;\n        }\n    }\n\n    private long nativePtr;\n    private static final long nativeFinalizerPtr = nativeGetFinalizerPtr();\n\n    /**\n     * Creates an empty schema object using object store. This constructor is intended to be used by\n     * the validation of schema, object schemas and properties through the object store.\n     *\n     * @param className name of the class\n     */\n    private OsObjectSchemaInfo(String publicClassName, String className, boolean embedded) {\n        this(nativeCreateRealmObjectSchema(publicClassName, className, embedded));\n    }\n\n    /**\n     * Creates a java wrapper class for given {@code ObjectSchema} pointer. This java wrapper will take the ownership of\n     * the object's memory and release it through phantom reference.\n     *\n     * @param nativePtr pointer to the {@code ObjectSchema} object.\n     */\n    OsObjectSchemaInfo(long nativePtr) {\n        this.nativePtr = nativePtr;\n        NativeContext.dummyContext.addReference(this);\n    }\n\n    /**\n     * @return the internal class name of this {@code OsObjectSchema} represents for.\n     */\n    public String getClassName() {\n        return nativeGetClassName(nativePtr);\n    }\n\n    /**\n     * Returns a property by the given name.\n     *\n     * @param propertyName the name of the property.\n     * @return a {@link Property} object.\n     */\n    public Property getProperty(String propertyName) {\n        return new Property(nativeGetProperty(nativePtr, propertyName));\n    }\n\n    /**\n     * Returns the primary key property for this {@code ObjectSchema}.\n     *\n     * @return a {@link Property} object of the primary key property, {@code null} if this {@code ObjectSchema} doesn't\n     * contains a primary key.\n     */\n    public @Nullable Property getPrimaryKeyProperty() {\n        long propertyPtr = nativeGetPrimaryKeyProperty(nativePtr);\n        return propertyPtr == 0 ? null : new Property(nativeGetPrimaryKeyProperty(nativePtr));\n    }\n\n\n    public boolean isEmbedded() {\n        return nativeIsEmbedded(nativePtr);\n    }\n\n    @Override\n    public long getNativePtr() {\n        return nativePtr;\n    }\n\n    @Override\n    public long getNativeFinalizerPtr() {\n        return nativeFinalizerPtr;\n    }\n\n    private static native long nativeCreateRealmObjectSchema(String publicClassName, String internalClassName, boolean embedded);\n\n    private static native long nativeGetFinalizerPtr();\n\n    // Add properties to the ObjectSchema and delete property pointers.\n    private static native void nativeAddProperties(long nativePtr, long[] persistedPropPtrs, long[] computedPropPtrs);\n\n    private static native String nativeGetClassName(long nativePtr);\n\n    // Throw ISE if the property doesn't exist.\n    private static native long nativeGetProperty(long nativePtr, String propertyName);\n\n    // Return nullptr if it doesn't have a primary key.\n    private static native long nativeGetPrimaryKeyProperty(long nativePtr);\n\n    private static native boolean nativeIsEmbedded(long nativePtr);\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/internal/OsObjectStore.java",
    "content": "/*\n * Copyright 2017 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\npackage io.realm.internal;\n\nimport javax.annotation.Nullable;\n\nimport io.realm.RealmConfiguration;\nimport io.realm.internal.Util;\n\n/**\n * Java wrapper for methods in object_store.hpp.\n */\npublic class OsObjectStore {\n\n    public static final long SCHEMA_NOT_VERSIONED = -1;\n\n    /**\n     * Sets the primary key field for the given class.\n     * <p>\n     * NOTE: The search index has to be added to the field before calling this method.\n     *\n     * @throws IllegalStateException if it is not in a transaction.\n     * @throws IllegalStateException if the given class doesn't exist.\n     * @throws IllegalStateException if the given field doesn't exist.\n     * @throws IllegalStateException if the given field is not a valid type for primary key.\n     * @throws IllegalStateException if there are duplicated values for the given field.\n     */\n    public static void setPrimaryKeyForObject(OsSharedRealm sharedRealm, String className,\n                                              @Nullable String primaryKeyFieldName) {\n        className = Util.getTablePrefix() + className;\n        try {\n            nativeSetPrimaryKeyForObject(sharedRealm.getNativePtr(), className, primaryKeyFieldName);\n        // Transform the IllegalStateException that would be thrown by core if the provided key already\n        // exists in Realm, to an IllegalArgumentException.\n        } catch (IllegalStateException e) {\n            throw new IllegalArgumentException(e.getMessage());\n        }\n    }\n\n    public static @Nullable String getPrimaryKeyForObject(OsSharedRealm sharedRealm, String className) {\n        className = Util.getTablePrefix() + className;\n        return nativeGetPrimaryKeyForObject(sharedRealm.getNativePtr(), className);\n    }\n\n    /**\n     * Sets the schema version to the given {@link OsSharedRealm}. This method will create meta tables if they don't exist.\n     * @throws IllegalStateException if it is not in a transaction.\n     */\n    public static void setSchemaVersion(OsSharedRealm sharedRealm, long schemaVersion) {\n        nativeSetSchemaVersion(sharedRealm.getNativePtr(), schemaVersion);\n    }\n\n    /**\n     * Returns the schema version of the given {@link OsSharedRealm}. If meta tables don't exist, this will return\n     * {@link #SCHEMA_NOT_VERSIONED}.\n     */\n    public static long getSchemaVersion(OsSharedRealm sharedRealm) {\n        return nativeGetSchemaVersion(sharedRealm.getNativePtr());\n    }\n\n    /**\n     * Deletes the table with the given class name.\n     *\n     * @return {@code true} if the table has been deleted. {@code false} if the table doesn't exist.\n     * @throws IllegalStateException if it is not in a transaction.\n     */\n    public static boolean deleteTableForObject(OsSharedRealm sharedRealm, String className) {\n        return nativeDeleteTableForObject(sharedRealm.getNativePtr(), className);\n    }\n\n    /**\n     * Try to grab an exclusive lock on the given Realm file. If the lock can be acquired, the {@code runnable} will be\n     * executed while the lock is held. The lock will ensure no one else can read from or write to the Realm file at the\n     * same time.\n     *\n     * @param configuration to specify the realm path.\n     * @param runnable to run with lock.\n     * @return {@code true} if the lock can be acquired and the {@code runnable} has been executed.\n     */\n    public static boolean callWithLock(RealmConfiguration configuration, Runnable runnable) {\n        return nativeCallWithLock(configuration.getPath(), runnable);\n    }\n\n    private static native void nativeSetPrimaryKeyForObject(long sharedRealmPtr, String className,\n                                                             @Nullable String primaryKeyFieldName);\n\n    private static native @Nullable String nativeGetPrimaryKeyForObject(long sharedRealmPtr, String className);\n\n    private static native void nativeSetSchemaVersion(long sharedRealmPtr, long schemaVersion);\n\n    private static native long nativeGetSchemaVersion(long sharedRealmPtr);\n\n    private static native boolean nativeDeleteTableForObject(long sharedRealmPtr, String className);\n\n    private static native boolean nativeCallWithLock(String realmPath, Runnable runnable);\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/internal/OsRealmConfig.java",
    "content": "/*\n * Copyright 2017 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\npackage io.realm.internal;\n\nimport android.os.Build;\n\nimport java.io.File;\nimport java.net.InetAddress;\nimport java.net.InetSocketAddress;\nimport java.net.Proxy;\nimport java.net.ProxySelector;\nimport java.net.SocketAddress;\nimport java.net.URI;\nimport java.net.URISyntaxException;\nimport java.util.List;\nimport java.util.Map;\n\nimport javax.annotation.Nullable;\n\nimport io.realm.CompactOnLaunchCallback;\nimport io.realm.RealmConfiguration;\nimport io.realm.log.RealmLog;\n\n/**\n * Java wrapper of Object Store's Realm::Config.\n */\npublic class OsRealmConfig implements NativeObject {\n\n    // Keep references to reset handlers to avoid being garbage collected.\n    // They cannot be on the SyncConfiguration object as they are build on the SyncObjectServerFacade\n    private final Object beforeClientResetHandler;\n    private final Object afterClientResetHandler;\n\n    public enum Durability {\n        FULL(0),\n        MEM_ONLY(1);\n\n        final int value;\n\n        Durability(int value) {\n            this.value = value;\n        }\n    }\n\n    public enum SchemaMode {\n        SCHEMA_MODE_AUTOMATIC(SCHEMA_MODE_VALUE_AUTOMATIC),\n        SCHEMA_MODE_IMMUTABLE(SCHEMA_MODE_VALUE_IMMUTABLE),\n        SCHEMA_MODE_READONLY(SCHEMA_MODE_VALUE_READONLY),\n        SCHEMA_MODE_SOFT_RESET_FILE(SCHEMA_MODE_VALUE_SOFT_RESET_FILE),\n        SCHEMA_MODE_ADDITIVE_DISCOVERED(SCHEMA_MODE_VALUE_ADDITIVE_DISCOVERED),\n\n        // TODO: implement AdditiveExplicit\n\n        SCHEMA_MODE_MANUAL(SCHEMA_MODE_VALUE_MANUAL);\n\n        final byte value;\n\n        SchemaMode(byte value) {\n            this.value = value;\n        }\n\n        public byte getNativeValue() {\n            return value;\n        }\n    }\n\n    public enum SyncSessionStopPolicy {\n        IMMEDIATELY(SYNCSESSION_STOP_POLICY_VALUE_IMMEDIATELY), // Immediately stop the session as soon as all Realms/Sessions go out of scope.\n        LIVE_INDEFINITELY(SYNCSESSION_STOP_POLICY_VALUE_LIVE_INDEFINETELY),   // Never stop the session.\n        AFTER_CHANGES_UPLOADED(SYNCSESSION_STOP_POLICY_VALUE_AFTER_CHANGES_UPLOADED); // Once all Realms/Sessions go out of scope, wait for uploads to complete and stop.\n\n        final byte value;\n\n        SyncSessionStopPolicy(byte value) {\n            this.value = value;\n        }\n\n        public byte getNativeValue() {\n            return value;\n        }\n    }\n\n    /**\n     * Builder class for creating {@code OsRealmConfig}. The {@code OsRealmConfig} instance should only be created by\n     * {@link OsSharedRealm}.\n     */\n    public static class Builder {\n        private RealmConfiguration configuration;\n        private OsSchemaInfo schemaInfo = null;\n        private OsSharedRealm.MigrationCallback migrationCallback = null;\n        private OsSharedRealm.InitializationCallback initializationCallback = null;\n        private boolean autoUpdateNotification = false;\n        private String fifoFallbackDir = \"\";\n\n        /**\n         * Initialize a {@link OsRealmConfig.Builder} with a given {@link RealmConfiguration}.\n         */\n        public Builder(RealmConfiguration configuration) {\n            this.configuration = configuration;\n        }\n\n        /**\n         * Sets the schema which Object Store initializes the Realm with.\n         *\n         * @param schemaInfo {@code null} to initialize the Realm in dynamic schema mode. Otherwise Object Store will\n         *                   initialize the Realm with given schema and handle migration with it.\n         * @return this {@link OsRealmConfig.Builder}.\n         */\n        public Builder schemaInfo(@Nullable OsSchemaInfo schemaInfo) {\n            this.schemaInfo = schemaInfo;\n            return this;\n        }\n\n        /**\n         * Sets the callback when manual migration needed.\n         *\n         * @param migrationCallback callback to be set.\n         * @return this {@link OsRealmConfig.Builder}.\n         */\n        public Builder migrationCallback(@Nullable OsSharedRealm.MigrationCallback migrationCallback) {\n            this.migrationCallback = migrationCallback;\n            return this;\n        }\n\n        /**\n         * Sets the callback which will be called when the Realm is created and the schema has just been initialized.\n         *\n         * @param initializationCallback the callback to be set.\n         * @return this {@link OsRealmConfig.Builder}.\n         */\n        public Builder initializationCallback(@Nullable OsSharedRealm.InitializationCallback initializationCallback) {\n            this.initializationCallback = initializationCallback;\n            return this;\n        }\n\n        /**\n         * Set to {@code false} to disable the background worker thread for producing change notifications. Change\n         * notifications are enabled by default.\n         *\n         * @param autoUpdateNotification {@code false} to disable. {@code true} to enable it.\n         * @return this {@link OsRealmConfig.Builder}.\n         */\n        public Builder autoUpdateNotification(boolean autoUpdateNotification) {\n            this.autoUpdateNotification = autoUpdateNotification;\n            return this;\n        }\n\n        // Package private because of the OsRealmConfig needs to carry the NativeContext. This should only be called\n        // by the OsSharedRealm.\n        public OsRealmConfig build() {\n            return new OsRealmConfig(configuration, fifoFallbackDir, autoUpdateNotification, schemaInfo,\n                    migrationCallback, initializationCallback);\n        }\n\n        public Builder fifoFallbackDir(File dir) {\n            this.fifoFallbackDir = dir.getAbsolutePath();\n            return this;\n        }\n    }\n\n    private static final byte SCHEMA_MODE_VALUE_AUTOMATIC = 0;\n    private static final byte SCHEMA_MODE_VALUE_IMMUTABLE = 1;\n    private static final byte SCHEMA_MODE_VALUE_READONLY = 2;\n    private static final byte SCHEMA_MODE_VALUE_SOFT_RESET_FILE = 3;\n    private static final byte SCHEMA_MODE_VALUE_ADDITIVE_DISCOVERED = 5;\n    private static final byte SCHEMA_MODE_VALUE_ADDITIVE_EXPLICIT = 6;\n    private static final byte SCHEMA_MODE_VALUE_MANUAL = 7;\n    private static final byte SYNCSESSION_STOP_POLICY_VALUE_IMMEDIATELY = 0;\n    private static final byte SYNCSESSION_STOP_POLICY_VALUE_LIVE_INDEFINETELY = 1;\n    private static final byte SYNCSESSION_STOP_POLICY_VALUE_AFTER_CHANGES_UPLOADED = 2;\n    private static final byte PROXYCONFIG_TYPE_VALUE_HTTP = 0;\n\n    // Public to be usable from the io.realm package\n    public static final byte CLIENT_RESYNC_MODE_MANUAL = 0;\n    public static final byte CLIENT_RESYNC_MODE_DISCARD_LOCAL = 1;\n    public static final byte CLIENT_RESYNC_MODE_RECOVER = 2;\n    public static final byte CLIENT_RESYNC_MODE_RECOVER_OR_DISCARD = 3;\n\n    private static final long nativeFinalizerPtr = nativeGetFinalizerPtr();\n\n    private final RealmConfiguration realmConfiguration;\n    private final URI resolvedRealmURI;\n    private final long nativePtr;\n    // Every OsSharedRealm instance has to be created from an OsRealmConfig instance. And the OsSharedRealm's NativeContext\n    // object will be the same as the context here. This is because of we may create different OsSharedRealm instances\n    // with different shared_ptrs which are point to the same SharedGroup object. It could happen when we create\n    // OsSharedRealm for migration/initialization callback. The context has to be the same object for those cases for\n    // core destructor's thread safety.\n    private final NativeContext context = new NativeContext();\n\n    // Hold a ref to callbacks to make sure they won't be GCed before getting called.\n    // JNI should only hold a weak ref in the lambda functions.\n    @SuppressWarnings({\"FieldCanBeLocal\", \"unused\"})\n    private final CompactOnLaunchCallback compactOnLaunchCallback;\n    @SuppressWarnings({\"FieldCanBeLocal\", \"unused\"})\n    private final OsSharedRealm.MigrationCallback migrationCallback;\n    @SuppressWarnings({\"FieldCanBeLocal\", \"unused\"})\n    private final OsSharedRealm.InitializationCallback initializationCallback;\n\n    private OsRealmConfig(final RealmConfiguration config,\n                          String fifoFallbackDir,\n                          boolean autoUpdateNotification,\n                          @Nullable OsSchemaInfo schemaInfo,\n                          @Nullable OsSharedRealm.MigrationCallback migrationCallback,\n                          @Nullable OsSharedRealm.InitializationCallback initializationCallback\n    ) {\n        this.realmConfiguration = config;\n        this.nativePtr = nativeCreate(config.getPath(), fifoFallbackDir, true, config.getMaxNumberOfActiveVersions());\n        NativeContext.dummyContext.addReference(this);\n\n        // Retrieve Sync settings first. We need syncRealmUrl to identify if this is a SyncConfig\n        int j = 0;\n        Object[] syncConfigurationOptions = ObjectServerFacade.getSyncFacadeIfPossible().getSyncConfigurationOptions(realmConfiguration);\n        String syncUserIdentifier = (String) syncConfigurationOptions[j++];\n        String syncUserProvider = (String) syncConfigurationOptions[j++];\n        String syncRealmUrl = (String) syncConfigurationOptions[j++];\n        String syncRealmAuthUrl = (String) syncConfigurationOptions[j++];\n        String syncRefreshToken = (String) syncConfigurationOptions[j++];\n        String syncAccessToken = (String) syncConfigurationOptions[j++];\n        String deviceId = (String) syncConfigurationOptions[j++];\n        Byte sessionStopPolicy = (Byte) syncConfigurationOptions[j++];\n        String urlPrefix = (String)(syncConfigurationOptions[j++]);\n        String customAuthorizationHeaderName = (String)(syncConfigurationOptions[j++]);\n        //noinspection unchecked\n        Map<String, String> customHeadersMap = (Map<String, String>) (syncConfigurationOptions[j++]);\n        Byte clientResyncMode = (Byte) syncConfigurationOptions[j++];\n        beforeClientResetHandler = syncConfigurationOptions[j++];\n        afterClientResetHandler = syncConfigurationOptions[j++];\n        String encodedPartitionValue = (String) syncConfigurationOptions[j++];\n        Object syncService = syncConfigurationOptions[j++];\n        Long appPtr = (Long) syncConfigurationOptions[j++];\n        boolean syncClientValidateSsl = (Boolean.TRUE.equals(syncConfigurationOptions[j++]));\n        String syncSslTrustCertificatePath = (String) syncConfigurationOptions[j++];\n\n        // Convert the headers into a String array to make it easier to send through JNI\n        // [key1, value1, key2, value2, ...]\n        String[] customHeaders = new String[customHeadersMap != null ? customHeadersMap.size() * 2 : 0];\n        if (customHeadersMap != null) {\n            int i = 0;\n            for (Map.Entry<String, String> entry : customHeadersMap.entrySet()) {\n                customHeaders[i] = entry.getKey();\n                customHeaders[i + 1] = entry.getValue();\n                i = i + 2;\n            }\n        }\n\n        // Set encryption key\n        byte[] key = config.getEncryptionKey();\n        if (key != null) {\n            nativeSetEncryptionKey(nativePtr, key);\n        }\n\n        // Set durability\n        nativeSetInMemory(nativePtr, config.getDurability() == Durability.MEM_ONLY);\n\n        // Set auto update notification\n        nativeEnableChangeNotification(nativePtr, autoUpdateNotification);\n\n        // Set schema related params.\n        SchemaMode schemaMode = SchemaMode.SCHEMA_MODE_MANUAL;\n        if (config.isRecoveryConfiguration()) {\n            schemaMode = SchemaMode.SCHEMA_MODE_IMMUTABLE;\n        } else if (config.isReadOnly()) {\n            schemaMode = SchemaMode.SCHEMA_MODE_READONLY;\n        } else if (syncRealmUrl != null) {\n            schemaMode = SchemaMode.SCHEMA_MODE_ADDITIVE_DISCOVERED;\n        } else if (config.shouldDeleteRealmIfMigrationNeeded()) {\n            schemaMode = SchemaMode.SCHEMA_MODE_SOFT_RESET_FILE;\n        }\n        final long schemaVersion = config.getSchemaVersion();\n        final long nativeSchemaPtr = schemaInfo == null ? 0 : schemaInfo.getNativePtr();\n        this.migrationCallback = migrationCallback;\n        nativeSetSchemaConfig(nativePtr, schemaMode.getNativeValue(), schemaVersion, nativeSchemaPtr, migrationCallback);\n\n        // Compact on launch\n        this.compactOnLaunchCallback = config.getCompactOnLaunchCallback();\n        if (compactOnLaunchCallback != null) {\n            nativeSetCompactOnLaunchCallback(nativePtr, compactOnLaunchCallback);\n        }\n\n        // Initial data transaction\n        this.initializationCallback = initializationCallback;\n        if (initializationCallback != null) {\n            nativeSetInitializationCallback(nativePtr, initializationCallback);\n        }\n\n        URI resolvedRealmURI  = null;\n        // Set sync config\n        if (syncRealmUrl != null) {\n            String resolvedSyncRealmUrl = nativeCreateAndSetSyncConfig(\n                    appPtr,\n                    nativePtr,\n                    syncRealmUrl,\n                    syncUserIdentifier,\n                    syncUserProvider,\n                    syncRefreshToken,\n                    syncAccessToken,\n                    deviceId,\n                    sessionStopPolicy,\n                    urlPrefix,\n                    customAuthorizationHeaderName,\n                    customHeaders,\n                    clientResyncMode,\n                    beforeClientResetHandler,\n                    afterClientResetHandler,\n                    encodedPartitionValue,\n                    syncService);\n            try {\n                resolvedSyncRealmUrl = syncRealmAuthUrl + urlPrefix.substring(1); // FIXME\n                resolvedRealmURI = new URI(resolvedSyncRealmUrl);\n            } catch (URISyntaxException e) {\n                RealmLog.error(e, \"Cannot create a URI from the Realm URL address\");\n            }\n            nativeSetSyncConfigSslSettings(nativePtr, syncClientValidateSsl, syncSslTrustCertificatePath);\n\n            // TODO: maybe expose the option for a custom Proxy or ProxySelector in the config?\n            ProxySelector proxySelector = ProxySelector.getDefault();\n            if (resolvedRealmURI != null && proxySelector != null) {\n                URI websocketUrl = null;\n                try {\n                    // replace scheme in URI so that a proxy selector won't be confused by 'ws://' or 'wss://'\n                    websocketUrl = new URI(resolvedSyncRealmUrl.replaceFirst(\"ws\", \"http\"));\n                } catch (URISyntaxException e) {\n                    // we shouldn't ever get here if parsing the resolved url above worked\n                    RealmLog.error(e, \"Cannot create a URI from the Realm URL address\");\n                }\n                List<Proxy> proxies = proxySelector.select(websocketUrl);\n                if (proxies != null && !proxies.isEmpty()) {\n                    Proxy proxy = proxies.get(0);\n                    if (proxy.type() != Proxy.Type.DIRECT) {\n                        byte proxyType = -1;\n                        switch (proxy.type()) {\n                            case HTTP:\n                                proxyType = PROXYCONFIG_TYPE_VALUE_HTTP;\n                                break;\n                            default:\n                                // this should never happen\n                        }\n\n                        if (proxy.type() == Proxy.Type.HTTP) {\n                            SocketAddress address = proxy.address();\n                            if (address instanceof InetSocketAddress) {\n                                InetSocketAddress inetAddress = (InetSocketAddress) address;\n                                String hostname = getHostString(inetAddress);\n                                if (hostname != null) {\n                                    nativeSetSyncConfigProxySettings(\n                                            nativePtr,\n                                            proxyType,\n                                            hostname,\n                                            inetAddress.getPort()\n                                    );\n                                } else {\n                                    RealmLog.error(\"Could not retrieve proxy's hostname.\");\n                                }\n                            } else {\n                                RealmLog.error(\"Unsupported proxy socket address type: \" + address.getClass().getName());\n                            }\n                        } else {\n                            // FIXME: enable once realm-sync adds support for SOCKS proxies\n                            RealmLog.error(\"SOCKS proxies are not supported.\");\n                        }\n                    }\n                }\n\n            }\n\n        }\n        this.resolvedRealmURI = resolvedRealmURI;\n    }\n\n    /**\n     * Backport the behavior from <a href=\"https://github.com/openjdk-mirror/jdk7u-jdk/blob/f4d80957e89a19a29bb9f9807d2a28351ed7f7df/src/share/classes/java/net/InetSocketAddress.java#L242\">InetSocketAddress.getHostString</a>, a function that is only available\n     * from SDK 19 (KITKAT)\n     *\n     * @param socketAddress address to extract the hostname from.\n     * @return hostname or the String form of the address.\n     */\n    private String getHostString(InetSocketAddress socketAddress) {\n        if (socketAddress.getHostName() != null) {\n            return socketAddress.getHostName();\n        }\n        if (socketAddress.getAddress() != null) {\n            InetAddress address = socketAddress.getAddress();\n\n            if (address.getHostName() != null) {\n                return address.getHostName();\n            } else\n                return address.getHostAddress();\n        }\n        return null;\n    }\n\n    @Override\n    public long getNativePtr() {\n        return nativePtr;\n    }\n\n    @Override\n    public long getNativeFinalizerPtr() {\n        return nativeFinalizerPtr;\n    }\n\n    public RealmConfiguration getRealmConfiguration() {\n        return realmConfiguration;\n    }\n\n    public URI getResolvedRealmURI() {\n        return resolvedRealmURI;\n    }\n\n    NativeContext getContext() {\n        return context;\n    }\n\n    private static native long nativeCreate(String path, String fifoFallbackDir, boolean enableFormatUpdate, long maxNumberOfActiveVersions);\n\n    private static native void nativeSetEncryptionKey(long nativePtr, byte[] key);\n\n    private static native void nativeSetInMemory(long nativePtr, boolean inMem);\n\n    private native void nativeSetSchemaConfig(long nativePtr, byte schemaMode, long schemaVersion,\n                                              long schemaInfoPtr,\n                                              @Nullable OsSharedRealm.MigrationCallback migrationCallback);\n\n    private static native void nativeSetCompactOnLaunchCallback(long nativePtr, CompactOnLaunchCallback callback);\n\n    private native void nativeSetInitializationCallback(long nativePtr, OsSharedRealm.InitializationCallback callback);\n\n    private static native void nativeEnableChangeNotification(long nativePtr, boolean enableNotification);\n\n    private native String nativeCreateAndSetSyncConfig(long appPtr, long configPtr, String syncRealmUrl,\n                                                              String userId, String userProvider, String refreshToken, String accessToken,\n                                                              String deviceId, byte sessionStopPolicy, String urlPrefix,\n                                                              String customAuthorizationHeaderName,\n                                                              String[] customHeaders, byte clientResetMode,\n                                                              Object beforeClientResetHandler, Object afterClientResetHandler,\n                                                              String partionKeyValue, Object syncService);\n\n    private static native void nativeSetSyncConfigSslSettings(long nativePtr,\n                                                              boolean validateSsl, String trustCertificatePath);\n\n    private static native void nativeSetSyncConfigProxySettings(long nativePtr, byte type, String address, int port);\n\n    private static native long nativeGetFinalizerPtr();\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/internal/OsResults.java",
    "content": "/*\n * Copyright 2017 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\npackage io.realm.internal;\n\nimport org.bson.types.Decimal128;\nimport org.bson.types.ObjectId;\n\nimport java.util.Collections;\nimport java.util.ConcurrentModificationException;\nimport java.util.Date;\nimport java.util.NoSuchElementException;\nimport java.util.UUID;\n\nimport javax.annotation.Nullable;\n\nimport io.realm.OrderedRealmCollectionChangeListener;\nimport io.realm.RealmChangeListener;\nimport io.realm.RealmList;\nimport io.realm.RealmModel;\nimport io.realm.Sort;\nimport io.realm.internal.objectstore.OsKeyPathMapping;\nimport io.realm.internal.objectstore.OsObjectBuilder;\n\n\n/**\n * Java wrapper of Object Store Results class.\n * It is the backend of binding's query results and back links.\n */\npublic class OsResults implements NativeObject, ObservableCollection {\n\n    private static final String CLOSED_REALM_MESSAGE =\n            \"This Realm instance has already been closed, making it unusable.\";\n\n    // Custom OsResults iterator. It ensures that we only iterate on a Realm OsResults that hasn't changed.\n    public abstract static class Iterator<T> implements java.util.Iterator<T> {\n        protected OsResults iteratorOsResults;\n        protected int pos = -1;\n\n        public Iterator(OsResults osResults) {\n            if (osResults.sharedRealm.isClosed()) {\n                throw new IllegalStateException(CLOSED_REALM_MESSAGE);\n            }\n\n            this.iteratorOsResults = osResults;\n\n            if (osResults.isSnapshot) {\n                // No need to detach a snapshot.\n                return;\n            }\n\n            if (osResults.sharedRealm.isInTransaction()) {\n                detach();\n            } else {\n                iteratorOsResults.sharedRealm.addIterator(this);\n            }\n        }\n\n        /**\n         * {@inheritDoc}\n         */\n        @Override\n        public boolean hasNext() {\n            checkValid();\n            return pos + 1 < iteratorOsResults.size();\n        }\n\n        /**\n         * {@inheritDoc}\n         */\n        @Override\n        @Nullable\n        public T next() {\n            checkValid();\n            pos++;\n            if (pos >= iteratorOsResults.size()) {\n                throw new NoSuchElementException(\"Cannot access index \" + pos + \" when size is \" + iteratorOsResults.size() +\n                        \". Remember to check hasNext() before using next().\");\n            }\n            return get(pos);\n        }\n\n        /**\n         * Not supported by Realm collection iterators.\n         */\n        @Override\n        @Deprecated\n        public void remove() {\n            throw new UnsupportedOperationException(\"remove() is not supported by RealmResults iterators.\");\n        }\n\n        void detach() {\n            iteratorOsResults = iteratorOsResults.createSnapshot();\n        }\n\n        // The iterator becomes invalid after receiving a remote change notification. In Java, the destruction of\n        // iterator totally depends on GC. If we just detach those iterators when remote change notification received\n        // like what realm-cocoa does, we will have a massive overhead since all the iterators created in the previous\n        // event loop need to be detached.\n        void invalidate() {\n            iteratorOsResults = null;\n        }\n\n        void checkValid() {\n            if (iteratorOsResults == null) {\n                throw new ConcurrentModificationException(\n                        \"No outside changes to a Realm is allowed while iterating a living Realm collection.\");\n            }\n        }\n\n        @Nullable\n        T get(int pos) {\n            return getInternal(pos, iteratorOsResults);\n        }\n\n        // Returns the RealmModel by given row in this list. This has to be implemented in the upper layer since\n        // we don't have information about the object types in the internal package.\n        protected abstract T convertRowToObject(UncheckedRow row);\n\n        protected abstract T getInternal(int pos, OsResults iteratorOsResults);\n    }\n\n    // Custom Realm collection list iterator.\n    public abstract static class ListIterator<T> extends Iterator<T> implements java.util.ListIterator<T> {\n\n        public ListIterator(OsResults osResults, int start) {\n            super(osResults);\n            if (start >= 0 && start <= iteratorOsResults.size()) {\n                pos = start - 1;\n            } else {\n                throw new IndexOutOfBoundsException(\"Starting location must be a valid index: [0, \"\n                        + (iteratorOsResults.size() - 1) + \"]. Yours was \" + start);\n            }\n        }\n\n        /**\n         * Unsupported by Realm collection iterators.\n         */\n        @Override\n        @Deprecated\n        public void add(@Nullable T object) {\n            throw new UnsupportedOperationException(\"Adding an element is not supported. Use Realm.createObject() instead.\");\n        }\n\n        /**\n         * {@inheritDoc}\n         */\n        @Override\n        public boolean hasPrevious() {\n            checkValid();\n            return pos >= 0;\n        }\n\n        /**\n         * {@inheritDoc}\n         */\n        @Override\n        public int nextIndex() {\n            checkValid();\n            return pos + 1;\n        }\n\n        /**\n         * {@inheritDoc}\n         */\n        @Override\n        @Nullable\n        public T previous() {\n            checkValid();\n            try {\n                T obj = get(pos);\n                pos--;\n                return obj;\n            } catch (IndexOutOfBoundsException e) {\n                throw new NoSuchElementException(\"Cannot access index less than zero. This was \" + pos +\n                        \". Remember to check hasPrevious() before using previous().\");\n            }\n        }\n\n        /**\n         * {@inheritDoc}\n         */\n        @Override\n        public int previousIndex() {\n            checkValid();\n            return pos;\n        }\n\n        /**\n         * Unsupported by RealmResults iterators.\n         */\n        @Override\n        @Deprecated\n        public void set(@Nullable T object) {\n            throw new UnsupportedOperationException(\"Replacing an element is not supported.\");\n        }\n    }\n\n    private final long nativePtr;\n    private static final long nativeFinalizerPtr = nativeGetFinalizerPtr();\n    private final OsSharedRealm sharedRealm;\n    private final NativeContext context;\n    private final Table table;\n    protected boolean loaded;\n    private boolean isSnapshot = false;\n\n    protected final ObserverPairList<CollectionObserverPair> observerPairs =\n            new ObserverPairList<CollectionObserverPair>();\n\n    // Public for static checking in JNI\n    @SuppressWarnings(\"WeakerAccess\")\n    public static final byte AGGREGATE_FUNCTION_MINIMUM = 1;\n    @SuppressWarnings(\"WeakerAccess\")\n    public static final byte AGGREGATE_FUNCTION_MAXIMUM = 2;\n    @SuppressWarnings(\"WeakerAccess\")\n    public static final byte AGGREGATE_FUNCTION_AVERAGE = 3;\n    @SuppressWarnings(\"WeakerAccess\")\n    public static final byte AGGREGATE_FUNCTION_SUM = 4;\n\n    public enum Aggregate {\n        MINIMUM(AGGREGATE_FUNCTION_MINIMUM),\n        MAXIMUM(AGGREGATE_FUNCTION_MAXIMUM),\n        AVERAGE(AGGREGATE_FUNCTION_AVERAGE),\n        SUM(AGGREGATE_FUNCTION_SUM);\n\n        private final byte value;\n\n        Aggregate(byte value) {\n            this.value = value;\n        }\n\n        public byte getValue() {\n            return value;\n        }\n    }\n\n    @SuppressWarnings(\"WeakerAccess\")\n    public static final byte MODE_EMPTY = 0;\n    @SuppressWarnings(\"WeakerAccess\")\n    public static final byte MODE_TABLE = 1;\n    @SuppressWarnings(\"WeakerAccess\")\n    public static final byte MODE_LIST = 2;\n    @SuppressWarnings(\"WeakerAccess\")\n    public static final byte MODE_QUERY = 3;\n    @SuppressWarnings(\"WeakerAccess\")\n    public static final byte MODE_TABLEVIEW = 4;\n\n    public enum Mode {\n        EMPTY,          // Backed by nothing (for missing tables)\n        TABLE,          // Backed directly by a Table\n        PRIMITIVE_LIST, // List of primitives\n        QUERY,          // Backed by a query that has not yet been turned into a TableView\n        TABLEVIEW;      // Backed by a TableView created from a Query\n\n        static Mode getByValue(byte value) {\n            switch (value) {\n                case MODE_EMPTY:\n                    return EMPTY;\n                case MODE_TABLE:\n                    return TABLE;\n                case MODE_QUERY:\n                    return QUERY;\n                case MODE_LIST:\n                    return PRIMITIVE_LIST;\n                case MODE_TABLEVIEW:\n                    return TABLEVIEW;\n                default:\n                    throw new IllegalArgumentException(\"Invalid value: \" + value);\n            }\n        }\n    }\n\n    public static OsResults createForBacklinks(OsSharedRealm realm, UncheckedRow row, Table srcTable,\n                                               String srcFieldName) {\n        long backlinksPtr = nativeCreateResultsFromBacklinks(\n                realm.getNativePtr(),\n                row.getNativePtr(),\n                srcTable.getNativePtr(),\n                srcTable.getColumnKey(srcFieldName));\n        return new OsResults(realm, srcTable, backlinksPtr);\n    }\n\n    public static OsResults createFromQuery(OsSharedRealm sharedRealm, TableQuery query) {\n        query.validateQuery();\n        long ptr = nativeCreateResults(sharedRealm.getNativePtr(), query.getNativePtr());\n        return new OsResults(sharedRealm, query.getTable(), ptr);\n    }\n\n    public static OsResults createFromMap(OsSharedRealm sharedRealm, long resultsPtr) {\n        return new OsResults(sharedRealm, resultsPtr);\n    }\n\n    // Use this when we don't have the table, e.g. when calling RealmDictionary.values()\n    OsResults(OsSharedRealm sharedRealm, long nativePtr) {\n        this.sharedRealm = sharedRealm;\n        this.context = sharedRealm.context;\n        this.nativePtr = nativePtr;\n        this.context.addReference(this);\n        this.loaded = getMode() != Mode.QUERY;\n        this.table = new Table(sharedRealm, nativeGetTable(nativePtr));\n    }\n\n    OsResults(OsSharedRealm sharedRealm, Table table, long nativePtr) {\n        this.sharedRealm = sharedRealm;\n        this.context = sharedRealm.context;\n        this.table = table;\n        this.nativePtr = nativePtr;\n        this.context.addReference(this);\n        this.loaded = getMode() != Mode.QUERY;\n    }\n\n    public OsResults createSnapshot() {\n        if (isSnapshot) {\n            return this;\n        }\n        OsResults osResults = new OsResults(sharedRealm, table, nativeCreateSnapshot(nativePtr));\n        osResults.isSnapshot = true;\n        return osResults;\n    }\n\n    public OsResults freeze(OsSharedRealm frozenRealm) {\n        OsResults results = new OsResults(frozenRealm, table.freeze(frozenRealm), nativeFreeze(nativePtr, frozenRealm.getNativePtr()));\n        if (isLoaded()) {\n            results.load();\n        }\n        return results;\n    }\n\n    @Override\n    public long getNativePtr() {\n        return nativePtr;\n    }\n\n    @Override\n    public long getNativeFinalizerPtr() {\n        return nativeFinalizerPtr;\n    }\n\n    public Object getValue(int index) {\n        return nativeGetValue(nativePtr, index);\n    }\n\n    public UncheckedRow getUncheckedRow(int index) {\n        return table.getUncheckedRowByPointer(nativeGetRow(nativePtr, index));\n    }\n\n    public UncheckedRow firstUncheckedRow() {\n        long rowPtr = nativeFirstRow(nativePtr);\n        if (rowPtr != 0) {\n            return table.getUncheckedRowByPointer(rowPtr);\n        }\n        return null;\n    }\n\n    public UncheckedRow lastUncheckedRow() {\n        long rowPtr = nativeLastRow(nativePtr);\n        if (rowPtr != 0) {\n            return table.getUncheckedRowByPointer(rowPtr);\n        }\n        return null;\n    }\n\n    public Table getTable() {\n        return table;\n    }\n\n    public TableQuery where() {\n        long nativeQueryPtr = nativeWhere(nativePtr);\n        return new TableQuery(this.context, this.table, nativeQueryPtr);\n    }\n\n    public String toJSON(int maxDepth) {\n        return toJSON(nativePtr, maxDepth);\n    }\n\n    public Number aggregateNumber(Aggregate aggregateMethod, long columnKey) {\n        try {\n            return (Number) nativeAggregate(nativePtr, columnKey, aggregateMethod.getValue());\n        } catch (IllegalStateException e) {\n            throw new IllegalArgumentException(\"Illegal Argument: \" + e.getMessage());\n        }\n    }\n\n    public Date aggregateDate(Aggregate aggregateMethod, long columnIndex) {\n        try {\n            return (Date) nativeAggregate(nativePtr, columnIndex, aggregateMethod.getValue());\n        } catch (IllegalStateException e) {\n            throw new IllegalArgumentException(\"Illegal Argument: \" + e.getMessage());\n        }\n    }\n\n    public long size() {\n        return nativeSize(nativePtr);\n    }\n\n    public void clear() {\n        nativeClear(nativePtr);\n    }\n\n    public OsResults sort(@Nullable OsKeyPathMapping mapping, String fieldName, Sort sortOrder) {\n        String query = TableQuery.buildSortDescriptor(new String[] {fieldName}, new Sort[] {sortOrder});\n        return new OsResults(sharedRealm, table, stringDescriptor(nativePtr, query, (mapping != null) ? mapping.getNativePtr() : 0));\n    }\n\n    public OsResults sort(@Nullable OsKeyPathMapping mapping, String[] fieldNames, Sort[] sortOrders) {\n        //noinspection ConstantConditions\n        if (sortOrders == null || sortOrders.length == 0) {\n            throw new IllegalArgumentException(\"You must provide at least one sort order.\");\n        }\n        if (fieldNames.length != sortOrders.length) {\n            throw new IllegalArgumentException(\"Number of fields and sort orders do not match.\");\n        }\n\n        String query = TableQuery.buildSortDescriptor(fieldNames, sortOrders);\n        return new OsResults(sharedRealm, table, stringDescriptor(nativePtr, query, (mapping != null) ? mapping.getNativePtr() : 0));\n    }\n\n    public OsResults distinct(@Nullable OsKeyPathMapping mapping, String[] fieldNames) {\n        String query = TableQuery.buildDistinctDescriptor(fieldNames);\n        return new OsResults(sharedRealm, table, stringDescriptor(nativePtr, query, (mapping != null) ? mapping.getNativePtr() : 0));\n    }\n\n    public boolean contains(UncheckedRow row) {\n        return nativeContains(nativePtr, row.getNativePtr());\n    }\n\n    public int indexOf(UncheckedRow row) {\n        long index = nativeIndexOf(nativePtr, row.getNativePtr());\n        return (index > Integer.MAX_VALUE) ? Integer.MAX_VALUE : (int) index;\n    }\n\n    public void delete(long index) {\n        nativeDelete(nativePtr, index);\n    }\n\n    public boolean deleteFirst() {\n        return nativeDeleteFirst(nativePtr);\n    }\n\n    public boolean deleteLast() {\n        return nativeDeleteLast(nativePtr);\n    }\n\n    public void setNull(String fieldName) {\n        nativeSetNull(nativePtr, fieldName);\n    }\n\n    public void setBoolean(String fieldName, boolean value) {\n        nativeSetBoolean(nativePtr, fieldName, value);\n    }\n\n    public void setInt(String fieldName, long value) {\n        nativeSetInt(nativePtr, fieldName, value);\n    }\n\n    public void setFloat(String fieldName, float value) {\n        nativeSetFloat(nativePtr, fieldName, value);\n    }\n\n    public void setDouble(String fieldName, double value) {\n        nativeSetDouble(nativePtr, fieldName, value);\n    }\n\n    public void setString(String fieldName, @Nullable String value) {\n        nativeSetString(nativePtr, fieldName, value);\n    }\n\n    public void setBlob(String fieldName, @Nullable byte[] value) {\n        nativeSetBinary(nativePtr, fieldName, value);\n    }\n\n    public void setDate(String fieldName, @Nullable Date timestamp) {\n        if (timestamp == null) {\n            nativeSetNull(nativePtr, fieldName);\n        } else {\n            nativeSetTimestamp(nativePtr, fieldName, timestamp.getTime());\n        }\n    }\n\n    public void setDecimal128(String fieldName, @Nullable Decimal128 value) {\n        if (value == null) {\n            nativeSetNull(nativePtr, fieldName);\n        } else {\n            nativeSetDecimal128(nativePtr, fieldName, value.getLow(), value.getHigh());\n        }\n    }\n\n    public void setObjectId(String fieldName, @Nullable ObjectId value) {\n        if (value == null) {\n            nativeSetNull(nativePtr, fieldName);\n        } else {\n            nativeSetObjectId(nativePtr, fieldName, value.toString());\n        }\n    }\n\n    public void setUUID(String fieldName, @Nullable UUID value) {\n        if (value == null) {\n            nativeSetNull(nativePtr, fieldName);\n        } else {\n            nativeSetUUID(nativePtr, fieldName, value.toString());\n        }\n    }\n\n    public void setObject(String fieldName, @Nullable Row row) {\n        if (row == null) {\n            setNull(fieldName);\n        } else {\n            long rowPtr;\n            if (row instanceof UncheckedRow) {\n                // Normal Realms\n                rowPtr = ((UncheckedRow) row).getNativePtr();\n            } else if (row instanceof CheckedRow) {\n                // Dynamic Realms\n                rowPtr = ((CheckedRow) row).getNativePtr();\n            } else {\n                // Should never happen, but just in case.\n                throw new UnsupportedOperationException(\"Unsupported Row type: \" + row.getClass().getCanonicalName());\n            }\n            nativeSetObject(nativePtr, fieldName, rowPtr);\n        }\n    }\n\n    // Interface wrapping adding the specific list type\n    private interface AddListTypeDelegate<T> {\n        void addList(OsObjectBuilder builder, RealmList<T> list);\n    }\n\n    // Helper method for adding specific types of lists.\n    private <T> void addTypeSpecificList(String fieldName, RealmList<T> list, AddListTypeDelegate<T> delegate) {\n        //noinspection unchecked\n        OsObjectBuilder builder = new OsObjectBuilder(getTable(), Collections.EMPTY_SET);\n        delegate.addList(builder, list);\n        try {\n            nativeSetList(nativePtr, fieldName, builder.getNativePtr());\n        } finally {\n            builder.close();\n        }\n    }\n\n    public void setStringList(String fieldName, RealmList<String> list) {\n        addTypeSpecificList(fieldName, list, new AddListTypeDelegate<String>() {\n            @Override\n            public void addList(OsObjectBuilder builder, RealmList<String> list) {\n                builder.addStringList(0, list);\n            }\n        });\n    }\n\n    public void setByteList(String fieldName, RealmList<Byte> list) {\n        addTypeSpecificList(fieldName, list, new AddListTypeDelegate<Byte>() {\n            @Override\n            public void addList(OsObjectBuilder builder, RealmList<Byte> list) {\n                builder.addByteList(0, list);\n            }\n        });\n    }\n\n    public void setShortList(String fieldName, RealmList<Short> list) {\n        addTypeSpecificList(fieldName, list, new AddListTypeDelegate<Short>() {\n            @Override\n            public void addList(OsObjectBuilder builder, RealmList<Short> list) {\n                builder.addShortList(0, list);\n            }\n        });\n    }\n\n    public void setIntegerList(String fieldName, RealmList<Integer> list) {\n        addTypeSpecificList(fieldName, list, new AddListTypeDelegate<Integer>() {\n            @Override\n            public void addList(OsObjectBuilder builder, RealmList<Integer> list) {\n                builder.addIntegerList(0, list);\n            }\n        });\n    }\n\n    public void setLongList(String fieldName, RealmList<Long> list) {\n        addTypeSpecificList(fieldName, list, new AddListTypeDelegate<Long>() {\n            @Override\n            public void addList(OsObjectBuilder builder, RealmList<Long> list) {\n                builder.addLongList(0, list);\n            }\n        });\n    }\n\n    public void setBooleanList(String fieldName, RealmList<Boolean> list) {\n        addTypeSpecificList(fieldName, list, new AddListTypeDelegate<Boolean>() {\n            @Override\n            public void addList(OsObjectBuilder builder, RealmList<Boolean> list) {\n                builder.addBooleanList(0, list);\n            }\n        });\n    }\n\n    public void setByteArrayList(String fieldName, RealmList<byte[]> list) {\n        addTypeSpecificList(fieldName, list, new AddListTypeDelegate<byte[]>() {\n            @Override\n            public void addList(OsObjectBuilder builder, RealmList<byte[]> list) {\n                builder.addByteArrayList(0, list);\n            }\n        });\n    }\n\n    public void setDateList(String fieldName, RealmList<Date> list) {\n        addTypeSpecificList(fieldName, list, new AddListTypeDelegate<Date>() {\n            @Override\n            public void addList(OsObjectBuilder builder, RealmList<Date> list) {\n                builder.addDateList(0, list);\n            }\n        });\n    }\n\n    public void setFloatList(String fieldName, RealmList<Float> list) {\n        addTypeSpecificList(fieldName, list, new AddListTypeDelegate<Float>() {\n            @Override\n            public void addList(OsObjectBuilder builder, RealmList<Float> list) {\n                builder.addFloatList(0, list);\n            }\n        });\n    }\n\n    public void setDoubleList(String fieldName, RealmList<Double> list) {\n        addTypeSpecificList(fieldName, list, new AddListTypeDelegate<Double>() {\n            @Override\n            public void addList(OsObjectBuilder builder, RealmList<Double> list) {\n                builder.addDoubleList(0, list);\n            }\n        });\n    }\n\n    public void setModelList(String fieldName, RealmList<RealmModel> list) {\n        addTypeSpecificList(fieldName, list, new AddListTypeDelegate<RealmModel>() {\n            @Override\n            public void addList(OsObjectBuilder builder, RealmList<RealmModel> list) {\n                builder.addObjectList(0, list);\n            }\n        });\n    }\n\n    public void setDecimal128List(String fieldName, RealmList<Decimal128> list) {\n        addTypeSpecificList(fieldName, list, new AddListTypeDelegate<Decimal128>() {\n            @Override\n            public void addList(OsObjectBuilder builder, RealmList<Decimal128> list) {\n                builder.addDecimal128List(0, list);\n            }\n        });\n    }\n\n    public void setObjectIdList(String fieldName, RealmList<ObjectId> list) {\n        addTypeSpecificList(fieldName, list, new AddListTypeDelegate<ObjectId>() {\n            @Override\n            public void addList(OsObjectBuilder builder, RealmList<ObjectId> list) {\n                builder.addObjectIdList(0, list);\n            }\n        });\n    }\n\n    public void setUUIDList(String fieldName, RealmList<UUID> list) {\n        addTypeSpecificList(fieldName, list, new AddListTypeDelegate<UUID>() {\n            @Override\n            public void addList(OsObjectBuilder builder, RealmList<UUID> list) {\n                builder.addUUIDList(0, list);\n            }\n        });\n    }\n\n    public <T> void addListener(T observer, OrderedRealmCollectionChangeListener<T> listener) {\n        if (observerPairs.isEmpty()) {\n            nativeStartListening(nativePtr);\n        }\n        CollectionObserverPair<T> collectionObserverPair = new CollectionObserverPair<T>(observer, listener);\n        observerPairs.add(collectionObserverPair);\n    }\n\n    public <T> void addListener(T observer, RealmChangeListener<T> listener) {\n        addListener(observer, new RealmChangeListenerWrapper<T>(listener));\n    }\n\n    public <T> void removeListener(T observer, OrderedRealmCollectionChangeListener<T> listener) {\n        observerPairs.remove(observer, listener);\n        if (observerPairs.isEmpty()) {\n            nativeStopListening(nativePtr);\n        }\n    }\n\n    public <T> void removeListener(T observer, RealmChangeListener<T> listener) {\n        removeListener(observer, new RealmChangeListenerWrapper<T>(listener));\n    }\n\n    public void removeAllListeners() {\n        observerPairs.clear();\n        nativeStopListening(nativePtr);\n    }\n\n    public boolean isValid() {\n        return nativeIsValid(nativePtr);\n    }\n\n    // Called by JNI\n    @Override\n    public void notifyChangeListeners(long nativeChangeSetPtr) {\n        // Object Store compute the change set between the SharedGroup versions when the query created and the latest.\n        // So it is possible it deliver a non-empty change set for the first async query returns.\n        OsCollectionChangeSet changeset = (nativeChangeSetPtr == 0)\n                ? new EmptyLoadChangeSet()\n                : new OsCollectionChangeSet(nativeChangeSetPtr, !isLoaded());\n\n        // Happens e.g. if a synchronous query is created, a change listener is added and then\n        // a transaction is started on the same thread. This will trigger all notifications\n        // and deliver an empty changeset.\n        if (changeset.isEmpty() && isLoaded()) {\n            return;\n        }\n        loaded = true;\n        observerPairs.foreach(new Callback(changeset));\n    }\n\n    public Mode getMode() {\n        return Mode.getByValue(nativeGetMode(nativePtr));\n    }\n\n    // The Results with mode QUERY will be evaluated asynchronously in Object Store. But we do have to support \"sync\"\n    // query by Java like RealmQuery.findAll().\n    // The flag is used for following cases:\n    // 1. When Results is created, loaded will be set to false if the mode is QUERY. For other modes, loaded will be set\n    //    to true.\n    // 2. For sync query (RealmQuery.findAll()), load() should be called after the Results creation. Then query will be\n    //    evaluated immediately and then loaded will be set to true (And the mode will be changed to TABLEVIEW in OS).\n    // 3. For async query, when load() gets called with loaded not set, the listener should be triggered with empty\n    //    change set since it is considered as query first returned.\n    // 4. If the listener triggered with empty change set after load() called for async queries, it is treated as the\n    //    same case as 2).\n    public boolean isLoaded() {\n        return loaded;\n    }\n\n    public void load() {\n        if (loaded) {\n            return;\n        }\n        try {\n            nativeEvaluateQueryIfNeeded(nativePtr, false);\n        } catch (IllegalStateException e) {\n            throw new IllegalArgumentException(\"Illegal Argument: \" + e.getMessage());\n        } catch (IllegalArgumentException e) {\n            if (e.getMessage().contains(\"Cannot sort on a collection property\")) {\n                throw new IllegalStateException(\"Illegal Argument: \" + e.getMessage());\n            }\n        }\n        notifyChangeListeners(0);\n    }\n\n    private static long stringDescriptor(long nativePtr, String descriptor, long mapping){\n        try {\n            return nativeStringDescriptor(nativePtr, descriptor, mapping);\n        } catch (IllegalStateException e) {\n            if (e.getMessage().contains(\"Realm accessed from incorrect thread.\")) {\n                throw e;\n            } else {\n                throw new IllegalArgumentException(\"Illegal Argument: \" + e.getMessage());\n            }\n        }\n    }\n\n    private static native long nativeGetFinalizerPtr();\n\n    protected static native long nativeCreateResults(long sharedRealmNativePtr, long queryNativePtr);\n\n    private static native long nativeCreateSnapshot(long nativePtr);\n\n    private static native long nativeFreeze(long nativePtr, long frozenRealmNativePtr);\n\n    private static native long nativeGetRow(long nativePtr, int index);\n\n    private static native long nativeFirstRow(long nativePtr);\n\n    private static native long nativeLastRow(long nativePtr);\n\n    private static native boolean nativeContains(long nativePtr, long nativeRowPtr);\n\n    private static native void nativeClear(long nativePtr);\n\n    private static native long nativeSize(long nativePtr);\n\n    private static native Object nativeAggregate(long nativePtr, long columnIndex, byte aggregateFunc);\n\n    private static native long nativeStringDescriptor(long nativePtr, String descriptor, long mapping);\n\n    private static native boolean nativeDeleteFirst(long nativePtr);\n\n    private static native boolean nativeDeleteLast(long nativePtr);\n\n    private static native void nativeDelete(long nativePtr, long index);\n\n    private static native void nativeSetNull(long nativePtr, String fieldName);\n\n    private static native void nativeSetBoolean(long nativePtr, String fieldName, boolean value);\n\n    private static native void nativeSetInt(long nativePtr, String fieldName, long value);\n\n    private static native void nativeSetFloat(long nativePtr, String fieldName, float value);\n\n    private static native void nativeSetDouble(long nativePtr, String fieldName, double value);\n\n    private static native void nativeSetString(long nativePtr, String fieldName, @Nullable String value);\n\n    private static native void nativeSetBinary(long nativePtr, String fieldName, @Nullable byte[] value);\n\n    private static native void nativeSetTimestamp(long nativePtr, String fieldName, long value);\n\n    private static native void nativeSetDecimal128(long nativePtr, String fieldName, long low, long high);\n\n    private static native void nativeSetObjectId(long nativePtr, String fieldName, String data);\n\n    private static native void nativeSetUUID(long nativePtr, String fieldName, String data);\n\n    private static native void nativeSetObject(long nativePtr, String fieldName, long rowNativePtr);\n\n    private static native void nativeSetList(long nativePtr, String fieldName, long builderNativePtr);\n\n    // Non-static, we need this OsResults object in JNI.\n    private native void nativeStartListening(long nativePtr);\n\n    private native void nativeStopListening(long nativePtr);\n\n    private static native long nativeGetTable(long nativePtr);\n\n    private static native long nativeWhere(long nativePtr);\n\n    private static native String toJSON(long nativePtr, int maxDepth);\n\n    private static native long nativeIndexOf(long nativePtr, long rowNativePtr);\n\n    private static native boolean nativeIsValid(long nativePtr);\n\n    private static native byte nativeGetMode(long nativePtr);\n\n    private static native long nativeCreateResultsFromBacklinks(long sharedRealmNativePtr, long rowNativePtr, long srcTableNativePtr, long srColIndex);\n\n    private static native void nativeEvaluateQueryIfNeeded(long nativePtr, boolean wantsNotifications);\n\n    private static native Object nativeGetValue(long nativePtr, int index);\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/internal/OsSchemaInfo.java",
    "content": "/*\n * Copyright 2017 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\npackage io.realm.internal;\n\n/**\n * Java wrapper for the Object Store Schema object.\n * <p>\n * When it is created from java binding, it is used for initializing/validating the schemas through Object Store. It\n * won't contain the column indices information.\n * <p>\n * When this is get from the Object Store {@code OsSharedRealm} instance, this represents the real schema of the Realm\n * file. It will contain all the schema information as well as the information about the column indices.\n */\npublic class OsSchemaInfo implements NativeObject {\n    private long nativePtr;\n    private static final long nativeFinalizerPtr = nativeGetFinalizerPtr();\n    // Hold the ref to the OsSharedRealm to ensure the OsSharedRealm won't be freed before this gets GCed.\n    @SuppressWarnings(\"unused\")\n    private final OsSharedRealm sharedRealm;\n\n    /**\n     * Constructs a {@code OsSchemaInfo} object from a given {@code OsObjectSchemaInfo} list.\n     *\n     * @param objectSchemaInfoList all the object schemas should be contained in this {@code OsObjectSchemaInfo}.\n     */\n    public OsSchemaInfo(java.util.Collection<OsObjectSchemaInfo> objectSchemaInfoList) {\n        this.nativePtr = nativeCreateFromList(convertObjectSchemaInfoListToNativePointerArray(objectSchemaInfoList));\n        NativeContext.dummyContext.addReference(this);\n        this.sharedRealm = null;\n    }\n\n    /**\n     * Constructs a {@code OsSchemaInfo} and bind its life cycle with the given {@code ShareRealm}. The native pointer\n     * held by this instance points to the reference of ObjectStore's {@code Realm::m_schema}. It will be valid\n     * as long as the {@code OsSharedRealm} instance is not GCed.\n     * <p>\n     * This should only be called by {@link OsSharedRealm}.\n     *\n     * @param nativePtr the pointer to the Object Store's {@code Realm::m_schema}.\n     * @param sharedRealm the {@code OsSharedRealm} instance which is owning the schema object.\n     */\n    OsSchemaInfo(long nativePtr, OsSharedRealm sharedRealm) {\n        this.nativePtr = nativePtr;\n        this.sharedRealm = sharedRealm;\n    }\n\n    private static long[] convertObjectSchemaInfoListToNativePointerArray(\n            java.util.Collection<OsObjectSchemaInfo> objectSchemaInfoList) {\n        long[] schemaNativePointers = new long[objectSchemaInfoList.size()];\n        int i = 0;\n        for (OsObjectSchemaInfo info : objectSchemaInfoList) {\n            schemaNativePointers[i] = info.getNativePtr();\n            i++;\n        }\n\n        return schemaNativePointers;\n    }\n\n    public OsObjectSchemaInfo getObjectSchemaInfo(String className) {\n        return new OsObjectSchemaInfo(nativeGetObjectSchemaInfo(nativePtr, className));\n    }\n\n    @Override\n    public long getNativePtr() {\n        return nativePtr;\n    }\n\n    @Override\n    public long getNativeFinalizerPtr() {\n        return nativeFinalizerPtr;\n    }\n\n    private static native long nativeCreateFromList(long[] objectSchemaPtrs);\n\n    private static native long nativeGetFinalizerPtr();\n\n    // Throw ISE if the object schema doesn't exist.\n    private static native long nativeGetObjectSchemaInfo(long nativePtr, String className);\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/internal/OsSet.java",
    "content": "/*\n * Copyright 2021 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\npackage io.realm.internal;\n\nimport org.bson.types.Decimal128;\nimport org.bson.types.ObjectId;\n\nimport java.util.Date;\nimport java.util.UUID;\n\nimport javax.annotation.Nullable;\n\nimport io.realm.SetChangeSet;\nimport io.realm.internal.core.NativeRealmAnyCollection;\n\n\npublic class OsSet implements NativeObject, OsCollection {\n\n\n    public enum ExternalCollectionOperation {\n        CONTAINS_ALL,\n        ADD_ALL,\n        REMOVE_ALL,\n        RETAIN_ALL\n    }\n\n    public static final int NOT_FOUND = -1;             // This means something was not found in OS\n\n    private static final int VALUE_NOT_FOUND = 0;       // comes from a native boolean\n    private static final int VALUE_FOUND = 1;           // comes from a native boolean\n\n    private static final long nativeFinalizerPtr = nativeGetFinalizerPtr();\n\n    private final long nativePtr;\n    private final NativeContext context;\n    private final OsSharedRealm osSharedRealm;\n    private final Table targetTable;\n\n    public OsSet(UncheckedRow row, long columnKey) {\n        this.osSharedRealm = row.getTable().getSharedRealm();\n        long[] pointers = nativeCreate(osSharedRealm.getNativePtr(), row.getNativePtr(), columnKey);\n        this.nativePtr = pointers[0];\n        this.context = osSharedRealm.context;\n        context.addReference(this);\n\n        if (pointers[1] != 0) {\n            targetTable = new Table(osSharedRealm, pointers[1]);\n        } else {\n            targetTable = null;\n        }\n    }\n\n    // Used to freeze sets\n    private OsSet(OsSharedRealm osSharedRealm, long nativePtr, @Nullable Table targetTable) {\n        this.osSharedRealm = osSharedRealm;\n        this.nativePtr = nativePtr;\n        this.context = osSharedRealm.context;\n        this.targetTable = targetTable;\n        context.addReference(this);\n    }\n\n    public Table getTargetTable() {\n        return targetTable;\n    }\n\n    @Override\n    public long getNativePtr() {\n        return nativePtr;\n    }\n\n    @Override\n    public long getNativeFinalizerPtr() {\n        return nativeFinalizerPtr;\n    }\n\n    @Override\n    public boolean isValid() {\n        return nativeIsValid(nativePtr);\n    }\n\n    public TableQuery getQuery() {\n        return new TableQuery(context, targetTable, nativeGetQuery(nativePtr));\n    }\n\n    public void deleteAll() {\n        nativeDeleteAll(nativePtr);\n    }\n\n    public Object getValueAtIndex(int position) {\n        return nativeGetValueAtIndex(nativePtr, position);\n    }\n\n    public long size() {\n        return nativeSize(nativePtr);\n    }\n\n    public boolean collectionFunnel(NativeRealmAnyCollection collection,\n            ExternalCollectionOperation operation) {\n        switch (operation) {\n            case CONTAINS_ALL:\n                return nativeContainsAllRealmAnyCollection(nativePtr, collection.getNativePtr());\n            case ADD_ALL:\n                return nativeAddAllRealmAnyCollection(nativePtr, collection.getNativePtr());\n            case REMOVE_ALL:\n                return nativeRemoveAllRealmAnyCollection(nativePtr, collection.getNativePtr());\n            case RETAIN_ALL:\n                return retainAllInternal(collection);\n            default:\n                throw new IllegalStateException(\"Unexpected value: \" + operation);\n        }\n    }\n\n    // ----------------------------------------------------\n    // Boolean operations\n    // ----------------------------------------------------\n\n    public boolean contains(@Nullable Boolean value) {\n        if (value == null) {\n            return nativeContainsNull(nativePtr);\n        } else {\n            return nativeContainsBoolean(nativePtr, value);\n        }\n    }\n\n    public boolean add(@Nullable Boolean value) {\n        long[] indexAndFound;\n        if (value == null) {\n            indexAndFound = nativeAddNull(nativePtr);\n        } else {\n            indexAndFound = nativeAddBoolean(nativePtr, value);\n        }\n        return indexAndFound[1] != VALUE_NOT_FOUND;\n    }\n\n    public boolean remove(@Nullable Boolean value) {\n        long[] indexAndFound;\n        if (value == null) {\n            indexAndFound = nativeRemoveNull(nativePtr);\n        } else {\n            indexAndFound = nativeRemoveBoolean(nativePtr, value);\n        }\n        return indexAndFound[1] == VALUE_FOUND;\n    }\n\n    // ----------------------------------------------------\n    // String operations\n    // ----------------------------------------------------\n\n    public boolean contains(@Nullable String value) {\n        if (value == null) {\n            return nativeContainsNull(nativePtr);\n        } else {\n            return nativeContainsString(nativePtr, value);\n        }\n    }\n\n    public boolean add(@Nullable String value) {\n        long[] indexAndFound;\n        if (value == null) {\n            indexAndFound = nativeAddNull(nativePtr);\n        } else {\n            indexAndFound = nativeAddString(nativePtr, value);\n        }\n        return indexAndFound[1] != VALUE_NOT_FOUND;\n    }\n\n    public boolean remove(@Nullable String value) {\n        long[] indexAndFound;\n        if (value == null) {\n            indexAndFound = nativeRemoveNull(nativePtr);\n        } else {\n            indexAndFound = nativeRemoveString(nativePtr, value);\n        }\n        return indexAndFound[1] == VALUE_FOUND;\n    }\n\n    // ----------------------------------------------------\n    // Integer operations\n    // ----------------------------------------------------\n\n    public boolean add(@Nullable Integer value) {\n        long[] indexAndFound;\n        if (value == null) {\n            indexAndFound = nativeAddNull(nativePtr);\n        } else {\n            indexAndFound = nativeAddLong(nativePtr, value.longValue());\n        }\n        return indexAndFound[1] != VALUE_NOT_FOUND;\n    }\n\n    public boolean remove(@Nullable Integer value) {\n        long[] indexAndFound;\n        if (value == null) {\n            indexAndFound = nativeRemoveNull(nativePtr);\n        } else {\n            indexAndFound = nativeRemoveLong(nativePtr, value.longValue());\n        }\n        return indexAndFound[1] == VALUE_FOUND;\n    }\n\n    // ----------------------------------------------------\n    // Long operations\n    // ----------------------------------------------------\n\n    public boolean contains(@Nullable Long value) {\n        if (value == null) {\n            return nativeContainsNull(nativePtr);\n        } else {\n            return nativeContainsLong(nativePtr, value);\n        }\n    }\n\n    public boolean add(@Nullable Long value) {\n        long[] indexAndFound;\n        if (value == null) {\n            indexAndFound = nativeAddNull(nativePtr);\n        } else {\n            indexAndFound = nativeAddLong(nativePtr, value);\n        }\n        return indexAndFound[1] != VALUE_NOT_FOUND;\n    }\n\n    public boolean remove(@Nullable Long value) {\n        long[] indexAndFound;\n        if (value == null) {\n            indexAndFound = nativeRemoveNull(nativePtr);\n        } else {\n            indexAndFound = nativeRemoveLong(nativePtr, value);\n        }\n        return indexAndFound[1] == VALUE_FOUND;\n    }\n\n    // ----------------------------------------------------\n    // Short operations\n    // ----------------------------------------------------\n\n    public boolean add(@Nullable Short value) {\n        long[] indexAndFound;\n        if (value == null) {\n            indexAndFound = nativeAddNull(nativePtr);\n        } else {\n            indexAndFound = nativeAddLong(nativePtr, value.longValue());\n        }\n        return indexAndFound[1] != VALUE_NOT_FOUND;\n    }\n\n    public boolean remove(@Nullable Short value) {\n        long[] indexAndFound;\n        if (value == null) {\n            indexAndFound = nativeRemoveNull(nativePtr);\n        } else {\n            indexAndFound = nativeRemoveLong(nativePtr, value.longValue());\n        }\n        return indexAndFound[1] == VALUE_FOUND;\n    }\n\n    // ----------------------------------------------------\n    // Byte operations\n    // ----------------------------------------------------\n\n    public boolean add(@Nullable Byte value) {\n        long[] indexAndFound;\n        if (value == null) {\n            indexAndFound = nativeAddNull(nativePtr);\n        } else {\n            indexAndFound = nativeAddLong(nativePtr, value.longValue());\n        }\n        return indexAndFound[1] != VALUE_NOT_FOUND;\n    }\n\n    public boolean remove(@Nullable Byte value) {\n        long[] indexAndFound;\n        if (value == null) {\n            indexAndFound = nativeRemoveNull(nativePtr);\n        } else {\n            indexAndFound = nativeRemoveLong(nativePtr, value.longValue());\n        }\n        return indexAndFound[1] == VALUE_FOUND;\n    }\n\n    // ----------------------------------------------------\n    // Float operations\n    // ----------------------------------------------------\n\n    public boolean contains(@Nullable Float value) {\n        if (value == null) {\n            return nativeContainsNull(nativePtr);\n        } else {\n            return nativeContainsFloat(nativePtr, value);\n        }\n    }\n\n    public boolean add(@Nullable Float value) {\n        long[] indexAndFound;\n        if (value == null) {\n            indexAndFound = nativeAddNull(nativePtr);\n        } else {\n            indexAndFound = nativeAddFloat(nativePtr, value);\n        }\n        return indexAndFound[1] != VALUE_NOT_FOUND;\n    }\n\n    public boolean remove(@Nullable Float value) {\n        long[] indexAndFound;\n        if (value == null) {\n            indexAndFound = nativeRemoveNull(nativePtr);\n        } else {\n            indexAndFound = nativeRemoveFloat(nativePtr, value);\n        }\n        return indexAndFound[1] == VALUE_FOUND;\n    }\n\n    // ----------------------------------------------------\n    // Double operations\n    // ----------------------------------------------------\n\n    public boolean contains(@Nullable Double value) {\n        if (value == null) {\n            return nativeContainsNull(nativePtr);\n        } else {\n            return nativeContainsDouble(nativePtr, value);\n        }\n    }\n\n    public boolean add(@Nullable Double value) {\n        long[] indexAndFound;\n        if (value == null) {\n            indexAndFound = nativeAddNull(nativePtr);\n        } else {\n            indexAndFound = nativeAddDouble(nativePtr, value);\n        }\n        return indexAndFound[1] != VALUE_NOT_FOUND;\n    }\n\n    public boolean remove(@Nullable Double value) {\n        long[] indexAndFound;\n        if (value == null) {\n            indexAndFound = nativeRemoveNull(nativePtr);\n        } else {\n            indexAndFound = nativeRemoveDouble(nativePtr, value);\n        }\n        return indexAndFound[1] == VALUE_FOUND;\n    }\n\n    // ----------------------------------------------------\n    // Binary operations\n    // ----------------------------------------------------\n\n    public boolean contains(@Nullable byte[] value) {\n        if (value == null) {\n            return nativeContainsNull(nativePtr);\n        } else {\n            return nativeContainsBinary(nativePtr, value);\n        }\n    }\n\n    public boolean add(@Nullable byte[] value) {\n        long[] indexAndFound;\n        if (value == null) {\n            indexAndFound = nativeAddNull(nativePtr);\n        } else {\n            indexAndFound = nativeAddBinary(nativePtr, value);\n        }\n        return indexAndFound[1] != VALUE_NOT_FOUND;\n    }\n\n    public boolean remove(@Nullable byte[] value) {\n        long[] indexAndFound;\n        if (value == null) {\n            indexAndFound = nativeRemoveNull(nativePtr);\n        } else {\n            indexAndFound = nativeRemoveBinary(nativePtr, value);\n        }\n        return indexAndFound[1] == VALUE_FOUND;\n    }\n\n    // ----------------------------------------------------\n    // Date operations\n    // ----------------------------------------------------\n\n    public boolean contains(@Nullable Date value) {\n        if (value == null) {\n            return nativeContainsNull(nativePtr);\n        } else {\n            return nativeContainsDate(nativePtr, value.getTime());\n        }\n    }\n\n    public boolean add(@Nullable Date value) {\n        long[] indexAndFound;\n        if (value == null) {\n            indexAndFound = nativeAddNull(nativePtr);\n        } else {\n            indexAndFound = nativeAddDate(nativePtr, value.getTime());\n        }\n        return indexAndFound[1] != VALUE_NOT_FOUND;\n    }\n\n    public boolean remove(@Nullable Date value) {\n        long[] indexAndFound;\n        if (value == null) {\n            indexAndFound = nativeRemoveNull(nativePtr);\n        } else {\n            indexAndFound = nativeRemoveDate(nativePtr, value.getTime());\n        }\n        return indexAndFound[1] == VALUE_FOUND;\n    }\n\n    // ----------------------------------------------------\n    // Decimal128 operations\n    // ----------------------------------------------------\n\n    public boolean contains(@Nullable Decimal128 value) {\n        if (value == null) {\n            return nativeContainsNull(nativePtr);\n        } else {\n            return nativeContainsDecimal128(nativePtr, value.getLow(), value.getHigh());\n        }\n    }\n\n    public boolean add(@Nullable Decimal128 value) {\n        long[] indexAndFound;\n        if (value == null) {\n            indexAndFound = nativeAddNull(nativePtr);\n        } else {\n            indexAndFound = nativeAddDecimal128(nativePtr, value.getLow(), value.getHigh());\n        }\n        return indexAndFound[1] != VALUE_NOT_FOUND;\n    }\n\n    public boolean remove(@Nullable Decimal128 value) {\n        long[] indexAndFound;\n        if (value == null) {\n            indexAndFound = nativeRemoveNull(nativePtr);\n        } else {\n            indexAndFound = nativeRemoveDecimal128(nativePtr, value.getLow(), value.getHigh());\n        }\n        return indexAndFound[1] == VALUE_FOUND;\n    }\n\n    // ----------------------------------------------------\n    // ObjectId operations\n    // ----------------------------------------------------\n\n    public boolean contains(@Nullable ObjectId value) {\n        if (value == null) {\n            return nativeContainsNull(nativePtr);\n        } else {\n            return nativeContainsObjectId(nativePtr, value.toString());\n        }\n    }\n\n    public boolean add(@Nullable ObjectId value) {\n        long[] indexAndFound;\n        if (value == null) {\n            indexAndFound = nativeAddNull(nativePtr);\n        } else {\n            indexAndFound = nativeAddObjectId(nativePtr, value.toString());\n        }\n        return indexAndFound[1] != VALUE_NOT_FOUND;\n    }\n\n    public boolean remove(@Nullable ObjectId value) {\n        long[] indexAndFound;\n        if (value == null) {\n            indexAndFound = nativeRemoveNull(nativePtr);\n        } else {\n            indexAndFound = nativeRemoveObjectId(nativePtr, value.toString());\n        }\n        return indexAndFound[1] == VALUE_FOUND;\n    }\n\n    // ----------------------------------------------------\n    // UUID operations\n    // ----------------------------------------------------\n\n    public boolean contains(@Nullable UUID value) {\n        if (value == null) {\n            return nativeContainsNull(nativePtr);\n        } else {\n            return nativeContainsUUID(nativePtr, value.toString());\n        }\n    }\n\n    public boolean add(@Nullable UUID value) {\n        long[] indexAndFound;\n        if (value == null) {\n            indexAndFound = nativeAddNull(nativePtr);\n        } else {\n            indexAndFound = nativeAddUUID(nativePtr, value.toString());\n        }\n        return indexAndFound[1] != VALUE_NOT_FOUND;\n    }\n\n    public boolean remove(@Nullable UUID value) {\n        long[] indexAndFound;\n        if (value == null) {\n            indexAndFound = nativeRemoveNull(nativePtr);\n        } else {\n            indexAndFound = nativeRemoveUUID(nativePtr, value.toString());\n        }\n        return indexAndFound[1] == VALUE_FOUND;\n    }\n\n    // ----------------------------------------------------\n    // Realm model operations\n    // ----------------------------------------------------\n\n    public boolean containsRow(long rowPtr) {\n        return nativeContainsRow(nativePtr, rowPtr);\n    }\n\n    public boolean addRow(long rowPtr) {\n        long[] indexAndFound = nativeAddRow(nativePtr, rowPtr);\n        return indexAndFound[1] != VALUE_NOT_FOUND;\n    }\n\n    public boolean removeRow(long rowPtr) {\n        long[] indexAndFound = nativeRemoveRow(nativePtr, rowPtr);\n        return indexAndFound[1] != VALUE_NOT_FOUND;\n    }\n\n    public long getRow(int index) {\n        return nativeGetRow(nativePtr, index);\n    }\n\n    // ----------------------------------------------------\n    // RealmAny operations\n    // ----------------------------------------------------\n\n    public boolean containsRealmAny(long realmAnyPtr) {\n        return nativeContainsRealmAny(nativePtr, realmAnyPtr);\n    }\n\n    public boolean addRealmAny(long realmAnyPtr) {\n        long[] indexAndFound = nativeAddRealmAny(nativePtr, realmAnyPtr);\n        return indexAndFound[1] != VALUE_NOT_FOUND;\n    }\n\n    public boolean removeRealmAny(long realmAnyPtr) {\n        long[] indexAndFound = nativeRemoveRealmAny(nativePtr, realmAnyPtr);\n        return indexAndFound[1] != VALUE_NOT_FOUND;\n    }\n\n    public long getRealmAny(int index) {\n        return nativeGetRealmAny(nativePtr, index);\n    }\n\n    // ----------------------------------------------------\n    // Set operations\n    // ----------------------------------------------------\n\n    public boolean containsAll(OsSet otherRealmSet) {\n        return nativeContainsAll(nativePtr, otherRealmSet.getNativePtr());\n    }\n\n    public boolean union(OsSet otherRealmSet) {\n        return nativeUnion(nativePtr, otherRealmSet.getNativePtr());\n    }\n\n    public boolean asymmetricDifference(OsSet otherSet) {\n        return nativeAsymmetricDifference(nativePtr, otherSet.getNativePtr());\n    }\n\n    public boolean intersect(OsSet otherSet) {\n        return nativeIntersect(nativePtr, otherSet.getNativePtr());\n    }\n\n    public void clear() {\n        nativeClear(nativePtr);\n    }\n\n    public OsSet freeze(OsSharedRealm frozenSharedRealm) {\n        long frozenNativePtr = nativeFreeze(this.nativePtr, frozenSharedRealm.getNativePtr());\n        return new OsSet(frozenSharedRealm, frozenNativePtr, targetTable);\n    }\n\n    // ----------------------------------------------------\n    // Change listeners\n    // ----------------------------------------------------\n\n    public void startListening(ObservableSet observableSet) {\n        nativeStartListening(nativePtr, observableSet);\n    }\n\n    public void stopListening() {\n        nativeStopListening(nativePtr);\n    }\n\n    public <T> void notifyChangeListeners(long nativeChangeSetPtr,\n            ObserverPairList<ObservableSet.SetObserverPair<T>> setObserverPairs) {\n        OsCollectionChangeSet collectionChangeSet = new OsCollectionChangeSet(nativeChangeSetPtr, false);\n        SetChangeSet setChangeSet = new SetChangeSet(collectionChangeSet);\n        if (setChangeSet.isEmpty()) {\n            // First time \"query\" returns. Do nothing.\n            return;\n        }\n        setObserverPairs.foreach(new ObservableSet.Callback<>(setChangeSet));\n    }\n\n    // ----------------------------------------------------\n    // Private stuff\n    // ----------------------------------------------------\n\n    private boolean retainAllInternal(NativeRealmAnyCollection collection) {\n        // If this set is empty the intersection is also the empty set and nothing changes\n        if (this.size() == 0) {\n            return false;\n        }\n\n        // If the other set is empty the intersection is also the empty set\n        if (collection.getSize() == 0) {\n            this.clear();\n            return true;\n        }\n\n        return nativeRetainAllRealmAnyCollection(nativePtr, collection.getNativePtr());\n    }\n\n    private static native long nativeGetFinalizerPtr();\n\n    private static native long[] nativeCreate(long sharedRealmPtr, long nativeRowPtr, long columnKey);\n\n    private static native boolean nativeIsValid(long nativePtr);\n\n    private static native long nativeGetQuery(long nativePtr);\n\n    private static native void nativeDeleteAll(long nativePtr);\n\n    private static native Object nativeGetValueAtIndex(long nativePtr, int position);\n\n    private static native long nativeSize(long nativePtr);\n\n    private static native boolean nativeContainsNull(long nativePtr);\n\n    private static native boolean nativeContainsBoolean(long nativePtr, boolean value);\n\n    private static native boolean nativeContainsString(long nativePtr, String value);\n\n    private static native boolean nativeContainsLong(long nativePtr, long value);\n\n    private static native boolean nativeContainsFloat(long nativePtr, float value);\n\n    private static native boolean nativeContainsDouble(long nativePtr, double value);\n\n    private static native boolean nativeContainsBinary(long nativePtr, byte[] value);\n\n    private static native boolean nativeContainsDate(long nativePtr, long value);\n\n    private static native boolean nativeContainsDecimal128(long nativePtr, long lowValue, long highValue);\n\n    private static native boolean nativeContainsObjectId(long nativePtr, String value);\n\n    private static native boolean nativeContainsUUID(long nativePtr, String value);\n\n    private static native boolean nativeContainsRow(long nativePtr, long rowPtr);\n\n    private static native boolean nativeContainsRealmAny(long nativePtr, long realmAnyPtr);\n\n    private static native long[] nativeAddNull(long nativePtr);\n\n    private static native long[] nativeAddBoolean(long nativePtr, boolean value);\n\n    private static native long[] nativeAddString(long nativePtr, String value);\n\n    private static native long[] nativeAddLong(long nativePtr, long value);\n\n    private static native long[] nativeAddFloat(long nativePtr, float value);\n\n    private static native long[] nativeAddDouble(long nativePtr, double value);\n\n    private static native long[] nativeAddBinary(long nativePtr, byte[] value);\n\n    private static native long[] nativeAddDate(long nativePtr, long value);\n\n    private static native long[] nativeAddDecimal128(long nativePtr, long lowValue, long highValue);\n\n    private static native long[] nativeAddObjectId(long nativePtr, String value);\n\n    private static native long[] nativeAddUUID(long nativePtr, String value);\n\n    private static native long[] nativeAddRow(long nativePtr, long rowPtr);\n\n    private static native long[] nativeAddRealmAny(long nativePtr, long realmAny_ptr);\n\n    private static native long[] nativeRemoveNull(long nativePtr);\n\n    private static native long[] nativeRemoveBoolean(long nativePtr, boolean value);\n\n    private static native long[] nativeRemoveString(long nativePtr, String value);\n\n    private static native long[] nativeRemoveLong(long nativePtr, long value);\n\n    private static native long[] nativeRemoveFloat(long nativePtr, float value);\n\n    private static native long[] nativeRemoveDouble(long nativePtr, double value);\n\n    private static native long[] nativeRemoveBinary(long nativePtr, byte[] value);\n\n    private static native long[] nativeRemoveDate(long nativePtr, long value);\n\n    private static native long[] nativeRemoveDecimal128(long nativePtr, long lowValue, long highValue);\n\n    private static native long[] nativeRemoveObjectId(long nativePtr, String value);\n\n    private static native long[] nativeRemoveUUID(long nativePtr, String value);\n\n    private static native long[] nativeRemoveRow(long nativePtr, long rowPtr);\n\n    private static native long[] nativeRemoveRealmAny(long nativePtr, long realmAnyPtr);\n\n    private static native long nativeGetRow(long nativePtr, int index);\n\n    private static native long nativeGetRealmAny(long nativePtr, int index);\n\n    private static native boolean nativeContainsAllRealmAnyCollection(long nativePtr, long realmAnyCollectionPtr);\n\n    private static native boolean nativeContainsAll(long nativePtr, long otherRealmSetNativePtr);\n\n    private static native boolean nativeUnion(long nativePtr, long otherRealmSetNativePtr);\n\n    private static native boolean nativeAddAllRealmAnyCollection(long nativePtr, long realmAnyCollectionPtr);\n\n    private static native boolean nativeAsymmetricDifference(long nativePtr, long otherRealmSetNativePtr);\n\n    private static native boolean nativeRemoveAllRealmAnyCollection(long nativePtr, long realmAnyCollectionPtr);\n\n    private static native boolean nativeIntersect(long nativePtr, long otherRealmSetNativePtr);\n\n    private static native boolean nativeRetainAllRealmAnyCollection(long nativePtr, long realmAnyCollectionPtr);\n\n    private static native void nativeClear(long nativePtr);\n\n    private static native long nativeFreeze(long nativePtr, long frozenRealmPtr);\n\n    private static native void nativeStartListening(long nativePtr, ObservableSet observableSet);\n\n    private static native void nativeStopListening(long nativePtr);\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/internal/OsSharedRealm.java",
    "content": "/*\n * Copyright 2016 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\npackage io.realm.internal;\n\nimport java.io.Closeable;\nimport java.io.File;\nimport java.lang.ref.WeakReference;\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.concurrent.CopyOnWriteArrayList;\n\nimport javax.annotation.Nullable;\n\nimport io.realm.RealmConfiguration;\nimport io.realm.RealmFieldType;\nimport io.realm.exceptions.RealmError;\nimport io.realm.internal.android.AndroidCapabilities;\nimport io.realm.internal.android.AndroidRealmNotifier;\nimport io.realm.internal.annotations.ObjectServer;\nimport io.realm.internal.async.RealmThreadPoolExecutor;\n\n@Keep\npublic final class OsSharedRealm implements Closeable, NativeObject {\n\n    public static class VersionID implements Comparable<VersionID> {\n        // Realm Core uses unsigned integers to represent versions. This means\n        // they could theoretically hit this value (maximum value of unsigned + overflow)\n        // but very unlikely\n        public static final VersionID LIVE = new VersionID(-1, -1);\n\n        public final long version;\n        public final long index;\n\n        VersionID(long version, long index) {\n            this.version = version;\n            this.index = index;\n        }\n\n        @Override\n        public int compareTo(@SuppressWarnings(\"NullableProblems\") VersionID another) {\n            //noinspection ConstantConditions\n            if (another == null) {\n                throw new IllegalArgumentException(\"Version cannot be compared to a null value.\");\n            }\n            if (version > another.version) {\n                return 1;\n            } else if (version < another.version) {\n                return -1;\n            } else {\n                return 0;\n            }\n        }\n\n        @Override\n        public String toString() {\n            return \"VersionID{\" +\n                    \"version=\" + version +\n                    \", index=\" + index +\n                    '}';\n        }\n\n        @Override\n        public boolean equals(Object object) {\n            if (this == object) {\n                return true;\n            }\n            if (object == null || getClass() != object.getClass()) {\n                return false;\n            }\n\n            VersionID versionID = (VersionID) object;\n            return (version == versionID.version && index == versionID.index);\n        }\n\n        @Override\n        public int hashCode() {\n            int result = (int) (version ^ (version >>> 32));\n            result = 31 * result + (int) (index ^ (index >>> 32));\n            return result;\n        }\n    }\n\n    /**\n     * The migration callback which will be called when manual migration is needed.\n     */\n    @Keep\n    public interface MigrationCallback {\n\n        /**\n         * Callback function.\n         *\n         * @param sharedRealm the same {@link OsSharedRealm} instance which has been created from the same\n         *                    {@link OsRealmConfig} instance.\n         * @param oldVersion  the schema version of the existing Realm file.\n         * @param newVersion  the expected schema version after migration.\n         */\n        void onMigrationNeeded(OsSharedRealm sharedRealm, long oldVersion, long newVersion);\n    }\n\n    /**\n     * Callback function to be executed when the schema is created.\n     */\n    @Keep\n    public interface InitializationCallback {\n        /**\n         * @param sharedRealm a {@link OsSharedRealm} instance which is in transaction state.\n         */\n        void onInit(OsSharedRealm sharedRealm);\n    }\n\n    /**\n     * Callback function to be called from JNI by Object Store when the schema is changed.\n     */\n    @Keep\n    public interface SchemaChangedCallback {\n        // Called from JNI\n        @SuppressWarnings(\"unused\")\n        void onSchemaChanged();\n    }\n\n    // Const value for RealmFileException conversion\n    public static final byte FILE_EXCEPTION_KIND_ACCESS_ERROR = 0;\n    public static final byte FILE_EXCEPTION_KIND_BAD_HISTORY = 1;\n    public static final byte FILE_EXCEPTION_KIND_PERMISSION_DENIED = 2;\n    public static final byte FILE_EXCEPTION_KIND_EXISTS = 3;\n    public static final byte FILE_EXCEPTION_KIND_NOT_FOUND = 4;\n    public static final byte FILE_EXCEPTION_KIND_INCOMPATIBLE_LOCK_FILE = 5;\n    public static final byte FILE_EXCEPTION_KIND_FORMAT_UPGRADE_REQUIRED = 6;\n    public static final byte FILE_EXCEPTION_INCOMPATIBLE_SYNC_FILE = 7;\n\n    private static final long nativeFinalizerPtr = nativeGetFinalizerPtr();\n    private final long nativePtr;\n    private final OsRealmConfig osRealmConfig;\n    public final NativeContext context;\n    private final OsSchemaInfo schemaInfo;\n    private static volatile File temporaryDirectory;\n    // JNI will only hold a weak global ref to this.\n    public final RealmNotifier realmNotifier;\n    public final Capabilities capabilities;\n    // For the Java callbacks during constructing in Object Store, some temporary OsSharedRealm objects need to be\n    // created as the parameter of the callback. The native pointers of those temp OsSharedRealm objects have to be\n    // valid during the whole life cycle of the Java object. The living native pointers still hold a ref-count to the\n    // SharedRealm which means the SharedRealm won't be closed automatically if there is any exception throws during\n    // construction. GC will clear them later, but that would be too late. So we are tracking the temp OsSharedRealm\n    // during the construction stage and manually close them if exception throws.\n    private static final List<OsSharedRealm> sharedRealmsUnderConstruction = new CopyOnWriteArrayList<OsSharedRealm>();\n    private final List<OsSharedRealm> tempSharedRealmsForCallback = new ArrayList<OsSharedRealm>();\n\n    private final List<WeakReference<PendingRow>> pendingRows = new CopyOnWriteArrayList<>();\n    // Package protected for testing\n    final List<WeakReference<OsResults.Iterator>> iterators = new ArrayList<>();\n\n    private OsSharedRealm(OsRealmConfig osRealmConfig, VersionID version) {\n        Capabilities capabilities = new AndroidCapabilities();\n        RealmNotifier realmNotifier = new AndroidRealmNotifier(this, capabilities);\n\n        // SharedRealms under constructions are identified by the Context.\n        this.context = osRealmConfig.getContext();\n        sharedRealmsUnderConstruction.add(this);\n        try {\n            this.nativePtr = nativeGetSharedRealm(osRealmConfig.getNativePtr(), version.version, version.index, realmNotifier);\n        } catch (Throwable t) {\n            // The SharedRealm instances have to be closed before throw.\n            for (OsSharedRealm sharedRealm : tempSharedRealmsForCallback) {\n                if (!sharedRealm.isClosed()) {\n                    sharedRealm.close();\n                }\n            }\n            throw t;\n        } finally {\n            tempSharedRealmsForCallback.clear();\n            sharedRealmsUnderConstruction.remove(this);\n        }\n        this.osRealmConfig = osRealmConfig;\n        this.schemaInfo = new OsSchemaInfo(nativeGetSchemaInfo(nativePtr), this);\n        this.context.addReference(this);\n\n        this.capabilities = capabilities;\n        this.realmNotifier = realmNotifier;\n        if (version.equals(VersionID.LIVE)) {\n            nativeSetAutoRefresh(nativePtr, capabilities.canDeliverNotification());\n        }\n    }\n\n    /**\n     * Creates a {@code OsSharedRealm} instance from a given Object Store's {@code OsSharedRealm} pointer. This is used to\n     * create {@code OsSharedRealm} from the callback functions. When this is called, there is another\n     * {@code OsSharedRealm} instance with the same {@link OsRealmConfig} which has been created before. Although they\n     * are different {@code shared_ptr}, they point to the same {@code SharedGroup} instance. The {@code context} has\n     * to be the same one to ensure core's destructor thread safety.\n     */\n    OsSharedRealm(long nativeSharedRealmPtr, OsRealmConfig osRealmConfig) {\n        this(nativeSharedRealmPtr, osRealmConfig, osRealmConfig.getContext());\n\n        boolean foundParentSharedRealm = false;\n        for (OsSharedRealm sharedRealm : sharedRealmsUnderConstruction) {\n            if (sharedRealm.context == osRealmConfig.getContext())  {\n                foundParentSharedRealm = true;\n                sharedRealm.tempSharedRealmsForCallback.add(this);\n                break;\n            }\n        }\n        if (!foundParentSharedRealm) {\n            throw new IllegalStateException(\"Cannot find the parent 'OsSharedRealm' which is under construction.\");\n        }\n    }\n\n    /**\n     * Creates a {@code OsSharedRealm} instance from a given Object Store's {@code OsSharedRealm}\n     * pointer with a given NativeContext. This is used to create {@code OsSharedRealm} from the\n     * callback functions.\n     */\n    OsSharedRealm(long nativeSharedRealmPtr, OsRealmConfig osRealmConfig, NativeContext nativeContext) {\n        this.nativePtr = nativeSharedRealmPtr;\n        this.osRealmConfig = osRealmConfig;\n        this.schemaInfo = new OsSchemaInfo(nativeGetSchemaInfo(nativePtr), this);\n        this.context = nativeContext;\n        this.context.addReference(this);\n\n        this.capabilities = new AndroidCapabilities();\n        // This instance should never need notifications.\n        this.realmNotifier = null;\n        nativeSetAutoRefresh(nativePtr, false);\n    }\n\n    /**\n     * Creates a {@code OsSharedRealm} instance in dynamic schema mode.\n     *\n     * @param config configuration to use\n     * @param version which version to use for a frozen instance or {@link VersionID#LIVE} for a live Realm.\n     */\n    public static OsSharedRealm getInstance(RealmConfiguration config, VersionID version) {\n        OsRealmConfig.Builder builder = new OsRealmConfig.Builder(config);\n        return getInstance(builder, version);\n    }\n\n    /**\n     * Creates a {@code ShareRealm} instance from the given {@link OsRealmConfig.Builder}.\n     *\n     * @param configBuilder configuration to use\n     * @param version which version to use for a frozen instance or {@link VersionID#LIVE} for a live Realm.\n     */\n    public static OsSharedRealm getInstance(OsRealmConfig.Builder configBuilder, VersionID version) {\n        OsRealmConfig osRealmConfig = configBuilder.build();\n        ObjectServerFacade.getSyncFacadeIfPossible().wrapObjectStoreSessionIfRequired(osRealmConfig);\n        return new OsSharedRealm(osRealmConfig, version);\n    }\n\n    public static void initialize(File tempDirectory) {\n        if (OsSharedRealm.temporaryDirectory != null) {\n            // already initialized\n            return;\n        }\n\n        String temporaryDirectoryPath = tempDirectory.getAbsolutePath();\n        if (!tempDirectory.isDirectory() && !tempDirectory.mkdirs() && !tempDirectory.isDirectory()) {\n            throw new IOException(\"failed to create temporary directory: \" + temporaryDirectoryPath);\n        }\n\n        if (!temporaryDirectoryPath.endsWith(\"/\")) {\n            temporaryDirectoryPath += \"/\";\n        }\n        nativeInit(temporaryDirectoryPath);\n        OsSharedRealm.temporaryDirectory = tempDirectory;\n    }\n\n    public static File getTemporaryDirectory() {\n        return temporaryDirectory;\n    }\n\n    public void beginTransaction() {\n        detachIterators();\n        executePendingRowQueries();\n        nativeBeginTransaction(nativePtr);\n    }\n\n    public void commitTransaction() {\n        nativeCommitTransaction(nativePtr);\n    }\n\n    public void cancelTransaction() {\n        nativeCancelTransaction(nativePtr);\n    }\n\n    public boolean isInTransaction() {\n        return nativeIsInTransaction(nativePtr);\n    }\n\n    public boolean hasTable(String name) {\n        return nativeHasTable(nativePtr, name);\n    }\n\n    /**\n     * Gets an existing {@link Table} with the given name.\n     *\n     * @param name the name of table.\n     * @return a {@link Table} object.\n     * @throws IllegalArgumentException if the table doesn't exist.\n     */\n    public Table getTable(String name) {\n        long tableRefPtr = nativeGetTableRef(nativePtr, name);\n        return new Table(this, tableRefPtr);\n    }\n\n    /**\n     * Creates a {@link Table} with then given name. Native assertion will happen if the table with the same name\n     * exists.\n     *\n     * @param name the name of table.\n     * @return a created {@link Table} object.\n     */\n    public Table createTable(String name) {\n        return new Table(this, nativeCreateTable(nativePtr, name));\n    }\n\n    /**\n     * Creates a {@link Table} and adds a primary key field to it. Native assertion will happen if the table with the\n     * same name exists.\n     *\n     * @param tableName           the name of table.\n     * @param primaryKeyFieldName the name of primary key field.\n     * @param isStringType        if this is true, the primary key field will be create as a string field. Otherwise it will\n     *                            be created as an integer field.\n     * @param isNullable          if the primary key field is nullable or not.\n     * @return a newly created {@link Table} object.\n     */\n    public Table createTableWithPrimaryKey(String tableName, String primaryKeyFieldName, RealmFieldType primaryKeyFieldType,\n                                           boolean isNullable) {\n        return new Table(this, nativeCreateTableWithPrimaryKeyField(nativePtr, tableName, primaryKeyFieldName, primaryKeyFieldType.getNativeValue(), isNullable));\n    }\n\n    public void renameTable(String oldName, String newName) {\n        try {\n            nativeRenameTable(nativePtr, oldName, newName);\n        } catch (IllegalArgumentException e) {\n            throw new RealmError(e.getMessage());\n        }\n    }\n\n    public String[] getTablesNames() {\n        String[] names = nativeGetTablesName(nativePtr);\n        return names != null? names : new String[]{};\n    }\n\n    public long size() {\n        return nativeSize(nativePtr);\n    }\n\n    public String getPath() {\n        return osRealmConfig.getRealmConfiguration().getPath();\n    }\n\n    public boolean isEmpty() {\n        return nativeIsEmpty(nativePtr);\n    }\n\n    public void refresh() {\n        if (isFrozen()) {\n            throw new IllegalStateException(\"It is not possible to refresh frozen Realms.\");\n        }\n        nativeRefresh(nativePtr);\n    }\n\n    public OsSharedRealm.VersionID getVersionID() {\n        long[] versionId = nativeGetVersionID(nativePtr);\n        if (versionId == null) {\n            throw new IllegalStateException(\"Cannot get versionId, this could be related to a non existing read/write transaction\");\n        }\n        return new OsSharedRealm.VersionID(versionId[0], versionId[1]);\n    }\n\n    @ObjectServer\n    public io.realm.mongodb.sync.SubscriptionSet getSubscriptions(RealmProxyMediator schema,\n                                            RealmThreadPoolExecutor listenerExecutor,\n                                            RealmThreadPoolExecutor writeExecutor) {\n        ObjectServerFacade facade = ObjectServerFacade.getSyncFacadeIfPossible();\n        facade.checkFlexibleSyncEnabled(getConfiguration());\n        long ptr = nativeGetLatestSubscriptionSet(nativePtr);\n        return new io.realm.internal.objectstore.OsSubscriptionSet(ptr, schema, listenerExecutor, writeExecutor);\n    }\n\n    public boolean isClosed() {\n        return nativeIsClosed(nativePtr);\n    }\n\n    public void writeCopy(File file, @Nullable byte[] key) {\n        if (file.isFile() && file.exists()) {\n            throw new IllegalArgumentException(\"The destination file must not exist\");\n        }\n        if (isSyncRealm()) {\n            Util.checkNotOnMainThread(\"writeCopyTo() cannot be called from the main \" +\n                    \"thread when using synchronized Realms.\");\n        }\n        try {\n            nativeWriteCopy(nativePtr, file.getAbsolutePath(), key);\n        } catch (RuntimeException e) {\n            // Remap Core vague exception type to better IllegalStateException\n            String msg = e.getMessage();\n            if (msg.contains(\"Could not write file as not all client changes are integrated in server\")) {\n                throw new IllegalStateException(msg);\n            } else {\n                throw e;\n            }\n        }\n    }\n\n    public boolean compact() {\n        return nativeCompact(nativePtr);\n    }\n\n    public void setAutoRefresh(boolean enabled) {\n        capabilities.checkCanDeliverNotification(null);\n        nativeSetAutoRefresh(nativePtr, enabled);\n    }\n\n    public boolean waitForChange() {\n        return nativeWaitForChange(nativePtr);\n    }\n\n    public void stopWaitForChange() {\n        nativeStopWaitForChange(nativePtr);\n    }\n\n    public boolean isAutoRefresh() {\n        return nativeIsAutoRefresh(nativePtr);\n    }\n\n    public RealmConfiguration getConfiguration() {\n        return osRealmConfig.getRealmConfiguration();\n    }\n\n    public long getNumberOfVersions() {\n        return nativeNumberOfVersions(nativePtr);\n    }\n\n    @Override\n    public void close() {\n        if (realmNotifier != null) {\n            realmNotifier.close();\n        }\n        synchronized (context) {\n            nativeCloseSharedRealm(nativePtr);\n            // Don't reset the nativePtr since we still rely on Object Store to check if the given OsSharedRealm ptr\n            // is closed or not.\n        }\n    }\n\n    @Override\n    public long getNativePtr() {\n        return nativePtr;\n    }\n\n    @Override\n    public long getNativeFinalizerPtr() {\n        return nativeFinalizerPtr;\n    }\n\n    /**\n     * @return the {@link OsSchemaInfo} of this {@code OsSharedRealm}.\n     */\n    public OsSchemaInfo getSchemaInfo() {\n        return schemaInfo;\n    }\n\n    /**\n     * Registers a {@link SchemaChangedCallback} with JNI {@code BindingContext}.\n     *\n     * @param callback to be registered. It will be held as a weak ref in the JNI. The caller needs to hold a strong ref\n     *                 to the callback to ensure it won't be GCed before calling.\n     */\n    public void registerSchemaChangedCallback(SchemaChangedCallback callback) {\n        nativeRegisterSchemaChangedCallback(nativePtr, callback);\n    }\n\n    /**\n     * Returns {@code true} if this Realm is a synchronized Realm.\n     */\n    public boolean isSyncRealm() {\n        return osRealmConfig.getResolvedRealmURI() != null;\n    }\n\n    /**\n     * Returns whether or not this Realm is frozen.\n     */\n    public boolean isFrozen() {\n        return nativeIsFrozen(nativePtr);\n    }\n\n    /**\n     * Returns a frozen copy of this Realm.\n     */\n    public OsSharedRealm freeze() {\n        return new OsSharedRealm(osRealmConfig, getVersionID());\n    }\n\n    // addIterator(), detachIterators() and invalidateIterators() are used to make RealmResults stable iterators work.\n    // The iterator will iterate on a snapshot Results if it is accessed inside a transaction.\n    // See https://github.com/realm/realm-java/issues/3883 for more information.\n    // Should only be called by Iterator's constructor.\n    void addIterator(OsResults.Iterator iterator) {\n        iterators.add(new WeakReference<>(iterator));\n    }\n\n    // The detaching should happen before transaction begins.\n    private void detachIterators() {\n        for (WeakReference<OsResults.Iterator> iteratorRef : iterators) {\n            OsResults.Iterator iterator = iteratorRef.get();\n            if (iterator != null) {\n                iterator.detach();\n            }\n        }\n        iterators.clear();\n    }\n\n    // Invalidates all iterators when a remote change notification is received.\n    void invalidateIterators() {\n        for (WeakReference<OsResults.Iterator> iteratorRef : iterators) {\n            OsResults.Iterator iterator = iteratorRef.get();\n            if (iterator != null) {\n                iterator.invalidate();\n            }\n        }\n        iterators.clear();\n    }\n\n    // addPendingRow, removePendingRow and executePendingRow queries are to solve that the listener cannot be added\n    // inside a transaction. For the findFirstAsync(), listener is registered on an Object Store Results first, then move\n    // the listeners to the Object when the query for Results returns. When beginTransaction() called, all listeners'\n    // on the results will be triggered first, that leads to the registration of listeners on the Object which will\n    // throw because of the transaction has already begun. So here we execute all PendingRow queries first before\n    // calling the Object Store begin_transaction to avoid the problem.\n    // Add pending row to the list when it is created. It should be called in the PendingRow constructor.\n    void addPendingRow(PendingRow pendingRow) {\n        pendingRows.add(new WeakReference<PendingRow>(pendingRow));\n    }\n\n    // Remove pending row from the list. It should be called when pending row's query finished.\n    void removePendingRow(PendingRow pendingRow) {\n        for (WeakReference<PendingRow> ref : pendingRows) {\n            PendingRow row = ref.get();\n            if (row == null || row == pendingRow) {\n                pendingRows.remove(ref);\n            }\n        }\n    }\n\n    // Execute all pending row queries.\n    private void executePendingRowQueries() {\n        for (WeakReference<PendingRow> ref : pendingRows) {\n            PendingRow row = ref.get();\n            if (row != null) {\n                row.executeQuery();\n            }\n        }\n        pendingRows.clear();\n    }\n\n    /**\n     * Called from JNI when the expected schema doesn't match the existing one.\n     *\n     * @param callback   the {@link MigrationCallback} in the {@link RealmConfiguration}.\n     * @param oldVersion the schema version of the existing Realm file.\n     */\n    @SuppressWarnings(\"unused\")\n    private static void runMigrationCallback(long nativeSharedRealmPtr, OsRealmConfig osRealmConfig, MigrationCallback callback,\n                                             long oldVersion) {\n        callback.onMigrationNeeded(new OsSharedRealm(nativeSharedRealmPtr, osRealmConfig), oldVersion,\n                osRealmConfig.getRealmConfiguration().getSchemaVersion());\n    }\n\n    /**\n     * Called from JNI when the schema is created the first time.\n     *\n     * @param callback to be executed with a given in-transact {@link OsSharedRealm}.\n     */\n    @SuppressWarnings(\"unused\")\n    private static void runInitializationCallback(long nativeSharedRealmPtr, OsRealmConfig osRealmConfig, InitializationCallback callback) {\n        callback.onInit(new OsSharedRealm(nativeSharedRealmPtr, osRealmConfig));\n    }\n\n    private static native void nativeInit(String temporaryDirectoryPath);\n\n    private static native long nativeGetSharedRealm(long nativeConfigPtr, long versionNo, long versionIndex, RealmNotifier notifier);\n\n    private static native void nativeCloseSharedRealm(long nativeSharedRealmPtr);\n\n    private static native boolean nativeIsClosed(long nativeSharedRealmPtr);\n\n    private static native void nativeBeginTransaction(long nativeSharedRealmPtr);\n\n    private static native void nativeCommitTransaction(long nativeSharedRealmPtr);\n\n    private static native void nativeCancelTransaction(long nativeSharedRealmPtr);\n\n    private static native boolean nativeIsInTransaction(long nativeSharedRealmPtr);\n\n    private static native boolean nativeIsEmpty(long nativeSharedRealmPtr);\n\n    private static native void nativeRefresh(long nativeSharedRealmPtr);\n\n    private static native long[] nativeGetVersionID(long nativeSharedRealmPtr);\n\n    // Throw IAE if the table doesn't exist.\n    private static native long nativeGetTableRef(long nativeSharedRealmPtr, String tableName);\n\n    // Throw IAE if the table exists already.\n    private static native long nativeCreateTable(long nativeSharedRealmPtr, String tableName);\n\n    // Throw IAE if the table exists already.\n    // If isStringType is false, the PK field will be created as an integer PK field.\n    private static native long nativeCreateTableWithPrimaryKeyField(long nativeSharedRealmPtr, String tableName,\n                                                                    String primaryKeyFieldName,\n                                                                    int primaryKeyFieldType, boolean isNullable);\n\n    private static native String[] nativeGetTablesName(long nativeSharedRealmPtr);\n\n    private static native boolean nativeHasTable(long nativeSharedRealmPtr, String tableName);\n\n    private static native void nativeRenameTable(long nativeSharedRealmPtr, String oldTableName, String newTableName);\n\n    private static native long nativeSize(long nativeSharedRealmPtr);\n\n    private static native void nativeWriteCopy(long nativeSharedRealmPtr, String path, @Nullable byte[] key);\n\n    private static native boolean nativeWaitForChange(long nativeSharedRealmPtr);\n\n    private static native void nativeStopWaitForChange(long nativeSharedRealmPtr);\n\n    private static native boolean nativeCompact(long nativeSharedRealmPtr);\n\n    private static native void nativeSetAutoRefresh(long nativePtr, boolean enabled);\n\n    private static native boolean nativeIsAutoRefresh(long nativePtr);\n\n    private static native long nativeGetFinalizerPtr();\n\n    // Return the pointer to the Realm::m_schema.\n    private static native long nativeGetSchemaInfo(long nativePtr);\n\n    private static native void nativeRegisterSchemaChangedCallback(long nativePtr, SchemaChangedCallback callback);\n\n    private static native boolean nativeIsFrozen(long nativePtr);\n\n    private static native long nativeFreeze(long nativePtr);\n\n    private static native long nativeNumberOfVersions(long nativePtr);\n\n    private static native long nativeGetLatestSubscriptionSet(long realmNativePtr);\n    private static native long nativeGetActiveSubscriptionSet(long realmNativePtr);\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/internal/PendingRow.java",
    "content": "package io.realm.internal;\n\nimport org.bson.types.Decimal128;\nimport org.bson.types.ObjectId;\n\nimport java.lang.ref.WeakReference;\nimport java.util.Date;\nimport java.util.UUID;\n\nimport io.realm.FrozenPendingRow;\nimport io.realm.RealmChangeListener;\nimport io.realm.RealmFieldType;\nimport io.realm.internal.core.NativeRealmAny;\n\n\n/**\n * A PendingRow is a row relies on a pending async query.\n * Before the query returns, calling any accessors will immediately throw. In this case run {@link #executeQuery()} to\n * get the queried row immediately. If the query results is empty, an {@link InvalidRow} will be returned.\n * After the query returns, {@link FrontEnd#onQueryFinished(Row)} will be called to give the front end a chance to reset\n * the row. If the async query returns an empty result, the query will be executed again later until a valid row is\n * contained by the query results.\n */\npublic class PendingRow implements Row {\n\n    // Implement this interface to reset the PendingRow to a Row backed by real data when query returned.\n    public interface FrontEnd {\n        // When asyncQuery is true, the pending query is executed asynchronously.\n        void onQueryFinished(Row row);\n    }\n\n    private static final String QUERY_NOT_RETURNED_MESSAGE =\n            \"The pending query has not been executed.\";\n    private static final String PROXY_NOT_SET_MESSAGE = \"The 'frontEnd' has not been set.\";\n    private static final String QUERY_EXECUTED_MESSAGE =\n            \"The query has been executed. This 'PendingRow' is not valid anymore.\";\n\n    private OsSharedRealm sharedRealm;\n    private OsResults pendingOsResults;\n    private RealmChangeListener<PendingRow> listener;\n    private WeakReference<FrontEnd> frontEndRef;\n    private boolean returnCheckedRow;\n\n    public PendingRow(OsSharedRealm sharedRealm, TableQuery query,\n                      final boolean returnCheckedRow) {\n        this.sharedRealm = sharedRealm;\n        pendingOsResults = OsResults.createFromQuery(sharedRealm, query);\n\n        listener = new RealmChangeListener<PendingRow>() {\n            @Override\n            public void onChange(PendingRow pendingRow) {\n                notifyFrontEnd();\n            }\n        };\n        pendingOsResults.addListener(this, listener);\n        this.returnCheckedRow = returnCheckedRow;\n        sharedRealm.addPendingRow(this);\n    }\n\n    // To set the front end of this PendingRow.\n    public void setFrontEnd(FrontEnd frontEnd) {\n        this.frontEndRef = new WeakReference<FrontEnd>(frontEnd);\n    }\n\n    @Override\n    public long getColumnCount() {\n        throw new IllegalStateException(QUERY_NOT_RETURNED_MESSAGE);\n    }\n\n    @Override\n    public String[] getColumnNames() {\n        throw new  IllegalStateException(QUERY_NOT_RETURNED_MESSAGE);\n    }\n\n    @Override\n    public long getColumnKey(String columnName) {\n        throw new IllegalStateException(QUERY_NOT_RETURNED_MESSAGE);\n    }\n\n    @Override\n    public RealmFieldType getColumnType(long columnKey) {\n        throw new IllegalStateException(QUERY_NOT_RETURNED_MESSAGE);\n    }\n\n    @Override\n    public Table getTable() {\n        throw new IllegalStateException(QUERY_NOT_RETURNED_MESSAGE);\n    }\n\n    @Override\n    public long getObjectKey() {\n        throw new IllegalStateException(QUERY_NOT_RETURNED_MESSAGE);\n    }\n\n    @Override\n    public long getLong(long columnKey) {\n        throw new IllegalStateException(QUERY_NOT_RETURNED_MESSAGE);\n    }\n\n    @Override\n    public boolean getBoolean(long columnKey) {\n        throw new IllegalStateException(QUERY_NOT_RETURNED_MESSAGE);\n    }\n\n    @Override\n    public float getFloat(long columnKey) {\n        throw new IllegalStateException(QUERY_NOT_RETURNED_MESSAGE);\n    }\n\n    @Override\n    public double getDouble(long columnKey) {\n        throw new IllegalStateException(QUERY_NOT_RETURNED_MESSAGE);\n    }\n\n    @Override\n    public Date getDate(long columnKey) {\n        throw new IllegalStateException(QUERY_NOT_RETURNED_MESSAGE);\n    }\n\n    @Override\n    public String getString(long columnKey) {\n        throw new IllegalStateException(QUERY_NOT_RETURNED_MESSAGE);\n    }\n\n    @Override\n    public byte[] getBinaryByteArray(long columnKey) {\n        throw new IllegalStateException(QUERY_NOT_RETURNED_MESSAGE);\n    }\n\n    @Override\n    public Decimal128 getDecimal128(long columnKey) {\n        throw new IllegalStateException(QUERY_NOT_RETURNED_MESSAGE);\n    }\n\n    @Override\n    public ObjectId getObjectId(long columnKey) {\n        throw new IllegalStateException(QUERY_NOT_RETURNED_MESSAGE);\n    }\n\n    @Override\n    public UUID getUUID(long columnKey) {\n        throw new IllegalStateException(QUERY_NOT_RETURNED_MESSAGE);\n    }\n\n    @Override\n    public NativeRealmAny getNativeRealmAny(long columnKey) {\n        throw new IllegalStateException(QUERY_NOT_RETURNED_MESSAGE);\n    }\n\n    @Override\n    public long getLink(long columnKey) {\n        throw new IllegalStateException(QUERY_NOT_RETURNED_MESSAGE);\n    }\n\n    @Override\n    public boolean isNullLink(long columnKey) {\n        throw new IllegalStateException(QUERY_NOT_RETURNED_MESSAGE);\n    }\n\n    @Override\n    public OsList getModelList(long columnKey) {\n        throw new IllegalStateException(QUERY_NOT_RETURNED_MESSAGE);\n    }\n\n    @Override\n    public OsList getValueList(long columnKey, RealmFieldType fieldType) {\n        throw new IllegalStateException(QUERY_NOT_RETURNED_MESSAGE);\n    }\n\n    @Override\n    public OsMap getRealmAnyMap(long columnKey) {\n        throw new IllegalStateException(QUERY_NOT_RETURNED_MESSAGE);\n    }\n\n    @Override\n    public OsMap getModelMap(long columnKey) {\n        throw new IllegalStateException(QUERY_NOT_RETURNED_MESSAGE);\n    }\n\n    @Override\n    public OsMap getValueMap(long columnKey, RealmFieldType fieldType) {\n        throw new IllegalStateException(QUERY_NOT_RETURNED_MESSAGE);\n    }\n\n    @Override\n    public OsSet getRealmAnySet(long columnKey) {\n        throw new IllegalStateException(QUERY_NOT_RETURNED_MESSAGE);\n    }\n\n    @Override\n    public OsSet getModelSet(long columnKey) {\n        throw new IllegalStateException(QUERY_NOT_RETURNED_MESSAGE);\n    }\n\n    @Override\n    public OsSet getValueSet(long columnKey, RealmFieldType fieldType) {\n        throw new IllegalStateException(QUERY_NOT_RETURNED_MESSAGE);\n    }\n\n    @Override\n    public void setLong(long columnKey, long value) {\n        throw new IllegalStateException(QUERY_NOT_RETURNED_MESSAGE);\n    }\n\n    @Override\n    public void setBoolean(long columnKey, boolean value) {\n        throw new IllegalStateException(QUERY_NOT_RETURNED_MESSAGE);\n    }\n\n    @Override\n    public void setFloat(long columnKey, float value) {\n        throw new IllegalStateException(QUERY_NOT_RETURNED_MESSAGE);\n    }\n\n    @Override\n    public void setDouble(long columnKey, double value) {\n        throw new IllegalStateException(QUERY_NOT_RETURNED_MESSAGE);\n    }\n\n    @Override\n    public void setDate(long columnKey, Date date) {\n        throw new IllegalStateException(QUERY_NOT_RETURNED_MESSAGE);\n    }\n\n    @Override\n    public void setString(long columnKey, String value) {\n        throw new IllegalStateException(QUERY_NOT_RETURNED_MESSAGE);\n    }\n\n    @Override\n    public void setRealmAny(long columnKey, long value) {\n        throw new IllegalStateException(QUERY_NOT_RETURNED_MESSAGE);\n    }\n\n    @Override\n    public void setBinaryByteArray(long columnKey, byte[] data) {\n        throw new IllegalStateException(QUERY_NOT_RETURNED_MESSAGE);\n    }\n\n    @Override\n    public void setLink(long columnKey, long value) {\n        throw new IllegalStateException(QUERY_NOT_RETURNED_MESSAGE);\n    }\n\n    @Override\n    public void nullifyLink(long columnKey) {\n        throw new IllegalStateException(QUERY_NOT_RETURNED_MESSAGE);\n    }\n\n    @Override\n    public boolean isNull(long columnKey) {\n        throw new IllegalStateException(QUERY_NOT_RETURNED_MESSAGE);\n    }\n\n    @Override\n    public void setNull(long columnKey) {\n        throw new IllegalStateException(QUERY_NOT_RETURNED_MESSAGE);\n    }\n\n    @Override\n    public void setDecimal128(long columnKey, Decimal128 value) {\n        throw new IllegalStateException(QUERY_NOT_RETURNED_MESSAGE);\n    }\n\n    @Override\n    public void setObjectId(long columnKey, ObjectId value) {\n        throw new IllegalStateException(QUERY_NOT_RETURNED_MESSAGE);\n    }\n\n    @Override\n    public void setUUID(long columnKey, UUID value) {\n        throw new IllegalStateException(QUERY_NOT_RETURNED_MESSAGE);\n    }\n\n    @Override\n    public long createEmbeddedObject(long columnKey, RealmFieldType parentPropertyType) {\n        throw new IllegalStateException(QUERY_NOT_RETURNED_MESSAGE);\n    }\n\n    @Override\n    public boolean isValid() {\n        return false;\n    }\n\n    @Override\n    public void checkIfAttached() {\n        throw new IllegalStateException(QUERY_NOT_RETURNED_MESSAGE);\n    }\n\n    @Override\n    public boolean hasColumn(String fieldName) {\n        throw new IllegalStateException(QUERY_NOT_RETURNED_MESSAGE);\n    }\n\n    @Override\n    public Row freeze(OsSharedRealm frozenRealm) {\n        return FrozenPendingRow.INSTANCE;\n    }\n\n    @Override\n    public boolean isLoaded() {\n        return false;\n    }\n\n    private void clearPendingCollection() {\n        pendingOsResults.removeListener(this, listener);\n        pendingOsResults = null;\n        listener = null;\n        sharedRealm.removePendingRow(this);\n    }\n\n    private void notifyFrontEnd() {\n        if (frontEndRef == null) {\n            throw new IllegalStateException(PROXY_NOT_SET_MESSAGE);\n        }\n        FrontEnd frontEnd = frontEndRef.get();\n        if (frontEnd == null) {\n            // The front end is GCed.\n            clearPendingCollection();\n            return;\n        }\n\n        if (pendingOsResults.isValid()) {\n            // PendingRow will always get the first Row of the query since we only support findFirst.\n            UncheckedRow uncheckedRow = pendingOsResults.firstUncheckedRow();\n            // Clear the pending collection immediately in case beginTransaction is called in the listener which will\n            // execute the query again.\n            clearPendingCollection();\n            // If no rows returned by the query, notify the frontend with an invalid row.\n            if (uncheckedRow != null) {\n                Row row = returnCheckedRow ? CheckedRow.getFromRow(uncheckedRow) : uncheckedRow;\n                // Ask the front end to reset the row and stop async query.\n                frontEnd.onQueryFinished(row);\n            } else {\n                // No row matches the query, return a invalid row.\n                frontEnd.onQueryFinished(InvalidRow.INSTANCE);\n            }\n        } else {\n            clearPendingCollection();\n        }\n\n    }\n\n    // Execute the query immediately and call frontend's onQueryFinished().\n    public void executeQuery() {\n        if (pendingOsResults == null) {\n            throw new IllegalStateException(QUERY_EXECUTED_MESSAGE);\n        }\n\n        notifyFrontEnd();\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/internal/Property.java",
    "content": "/*\n * Copyright 2016 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\npackage io.realm.internal;\n\n\nimport java.util.Locale;\n\nimport io.realm.RealmFieldType;\n\nimport static io.realm.RealmFieldType.BINARY_LIST;\nimport static io.realm.RealmFieldType.BINARY_SET;\nimport static io.realm.RealmFieldType.BOOLEAN_LIST;\nimport static io.realm.RealmFieldType.BOOLEAN_SET;\nimport static io.realm.RealmFieldType.DATE_LIST;\nimport static io.realm.RealmFieldType.DATE_SET;\nimport static io.realm.RealmFieldType.DECIMAL128_LIST;\nimport static io.realm.RealmFieldType.DECIMAL128_SET;\nimport static io.realm.RealmFieldType.DOUBLE_LIST;\nimport static io.realm.RealmFieldType.DOUBLE_SET;\nimport static io.realm.RealmFieldType.FLOAT_LIST;\nimport static io.realm.RealmFieldType.FLOAT_SET;\nimport static io.realm.RealmFieldType.INTEGER_LIST;\nimport static io.realm.RealmFieldType.INTEGER_SET;\nimport static io.realm.RealmFieldType.LINK_SET;\nimport static io.realm.RealmFieldType.MIXED_LIST;\nimport static io.realm.RealmFieldType.MIXED_SET;\nimport static io.realm.RealmFieldType.OBJECT_ID_LIST;\nimport static io.realm.RealmFieldType.OBJECT_ID_SET;\nimport static io.realm.RealmFieldType.STRING_LIST;\nimport static io.realm.RealmFieldType.STRING_SET;\nimport static io.realm.RealmFieldType.STRING_TO_BINARY_MAP;\nimport static io.realm.RealmFieldType.STRING_TO_BOOLEAN_MAP;\nimport static io.realm.RealmFieldType.STRING_TO_DATE_MAP;\nimport static io.realm.RealmFieldType.STRING_TO_DECIMAL128_MAP;\nimport static io.realm.RealmFieldType.STRING_TO_DOUBLE_MAP;\nimport static io.realm.RealmFieldType.STRING_TO_FLOAT_MAP;\nimport static io.realm.RealmFieldType.STRING_TO_INTEGER_MAP;\nimport static io.realm.RealmFieldType.STRING_TO_LINK_MAP;\nimport static io.realm.RealmFieldType.STRING_TO_MIXED_MAP;\nimport static io.realm.RealmFieldType.STRING_TO_OBJECT_ID_MAP;\nimport static io.realm.RealmFieldType.STRING_TO_STRING_MAP;\nimport static io.realm.RealmFieldType.STRING_TO_UUID_MAP;\nimport static io.realm.RealmFieldType.UUID_LIST;\nimport static io.realm.RealmFieldType.UUID_SET;\n\n\n/**\n * Class for handling properties/fields.\n */\n\npublic class Property implements NativeObject {\n    public static final boolean PRIMARY_KEY = true;\n    public static final boolean REQUIRED = true;\n    public static final boolean INDEXED = true;\n\n    @SuppressWarnings(\"WeakerAccess\")\n    public static final int TYPE_INT = 0;\n    @SuppressWarnings(\"WeakerAccess\")\n    public static final int TYPE_BOOL = 1;\n    @SuppressWarnings(\"WeakerAccess\")\n    public static final int TYPE_STRING = 2;\n    @SuppressWarnings(\"WeakerAccess\")\n    public static final int TYPE_DATA = 3;\n    @SuppressWarnings(\"WeakerAccess\")\n    public static final int TYPE_DATE = 4;\n    @SuppressWarnings(\"WeakerAccess\")\n    public static final int TYPE_FLOAT = 5;\n    @SuppressWarnings(\"WeakerAccess\")\n    public static final int TYPE_DOUBLE = 6;\n    @SuppressWarnings(\"WeakerAccess\")\n    public static final int TYPE_OBJECT = 7;\n    @SuppressWarnings(\"WeakerAccess\")\n    public static final int TYPE_LINKING_OBJECTS = 8;\n    @SuppressWarnings(\"WeakerAccess\")\n    public static final int TYPE_DECIMAL128 = 11;\n    @SuppressWarnings(\"WeakerAccess\")\n    public static final int TYPE_OBJECT_ID = 10;\n    @SuppressWarnings(\"WeakerAccess\")\n    public static final int TYPE_UUID = 12;\n    @SuppressWarnings(\"WeakerAccess\")\n    public static final int TYPE_MIXED = 9;\n    @SuppressWarnings(\"WeakerAccess\")\n    public static final int TYPE_REQUIRED = 0;\n    @SuppressWarnings(\"WeakerAccess\")\n    public static final int TYPE_NULLABLE = 64;\n    @SuppressWarnings(\"WeakerAccess\")\n    public static final int TYPE_ARRAY = 128;\n    @SuppressWarnings(\"WeakerAccess\")\n    public static final int TYPE_SET = 256;\n    @SuppressWarnings(\"WeakerAccess\")\n    public static final int TYPE_DICTIONARY = 512;\n\n    private long nativePtr;\n    private static final long nativeFinalizerPtr = nativeGetFinalizerPtr();\n\n    Property(long nativePtr) {\n        this.nativePtr = nativePtr;\n        NativeContext.dummyContext.addReference(this);\n    }\n\n    static int convertFromRealmFieldType(RealmFieldType fieldType, boolean isRequired) {\n        int type;\n        switch (fieldType) {\n            case OBJECT:\n                type = TYPE_OBJECT | TYPE_NULLABLE;\n                return type;\n            case LIST:\n                type = TYPE_OBJECT | TYPE_ARRAY;\n                return type;\n            case LINKING_OBJECTS:\n                type = TYPE_LINKING_OBJECTS | TYPE_ARRAY;\n                return type;\n            case INTEGER:\n                type = TYPE_INT;\n                break;\n            case BOOLEAN:\n                type = TYPE_BOOL;\n                break;\n            case STRING:\n                type = TYPE_STRING;\n                break;\n            case BINARY:\n                type = TYPE_DATA;\n                break;\n            case DATE:\n                type = TYPE_DATE;\n                break;\n            case FLOAT:\n                type = TYPE_FLOAT;\n                break;\n            case DECIMAL128:\n                type = TYPE_DECIMAL128;\n                break;\n            case OBJECT_ID:\n                type = TYPE_OBJECT_ID;\n                break;\n            case UUID:\n                type = TYPE_UUID;\n                break;\n            case MIXED:\n                type = TYPE_MIXED;\n                break;\n            case DOUBLE:\n                type = TYPE_DOUBLE;\n                break;\n            case INTEGER_LIST:\n                //noinspection PointlessBitwiseExpression\n                type = TYPE_INT | TYPE_ARRAY;\n                break;\n            case BOOLEAN_LIST:\n                type = TYPE_BOOL | TYPE_ARRAY;\n                break;\n            case STRING_LIST:\n                type = TYPE_STRING | TYPE_ARRAY;\n                break;\n            case BINARY_LIST:\n                type = TYPE_DATA | TYPE_ARRAY;\n                break;\n            case DATE_LIST:\n                type = TYPE_DATE | TYPE_ARRAY;\n                break;\n            case FLOAT_LIST:\n                type = TYPE_FLOAT | TYPE_ARRAY;\n                break;\n            case DECIMAL128_LIST:\n                type = TYPE_DECIMAL128 | TYPE_ARRAY;\n                break;\n            case OBJECT_ID_LIST:\n                type = TYPE_OBJECT_ID | TYPE_ARRAY;\n                break;\n            case UUID_LIST:\n                type = TYPE_UUID | TYPE_ARRAY;\n                break;\n            case DOUBLE_LIST:\n                type = TYPE_DOUBLE | TYPE_ARRAY;\n                break;\n            case MIXED_LIST:\n                type = TYPE_MIXED | TYPE_ARRAY;\n                break;\n            case STRING_TO_MIXED_MAP:\n                type = TYPE_MIXED | TYPE_DICTIONARY;\n                break;\n            case STRING_TO_BOOLEAN_MAP:\n                type = TYPE_BOOL | TYPE_DICTIONARY;\n                break;\n            case STRING_TO_STRING_MAP:\n                type = TYPE_STRING | TYPE_DICTIONARY;\n                break;\n            case STRING_TO_INTEGER_MAP:\n                type = TYPE_INT | TYPE_DICTIONARY;\n                break;\n            case STRING_TO_FLOAT_MAP:\n                type = TYPE_FLOAT | TYPE_DICTIONARY;\n                break;\n            case STRING_TO_DOUBLE_MAP:\n                type = TYPE_DOUBLE | TYPE_DICTIONARY;\n                break;\n            case STRING_TO_BINARY_MAP:\n                type = TYPE_DATA | TYPE_DICTIONARY;\n                break;\n            case STRING_TO_DATE_MAP:\n                type = TYPE_DATE | TYPE_DICTIONARY;\n                break;\n            case STRING_TO_DECIMAL128_MAP:\n                type = TYPE_DECIMAL128 | TYPE_DICTIONARY;\n                break;\n            case STRING_TO_OBJECT_ID_MAP:\n                type = TYPE_OBJECT_ID | TYPE_DICTIONARY;\n                break;\n            case STRING_TO_UUID_MAP:\n                type = TYPE_UUID | TYPE_DICTIONARY;\n                break;\n            case STRING_TO_LINK_MAP:\n                type = TYPE_OBJECT | TYPE_DICTIONARY;\n                break;\n            case BOOLEAN_SET:\n                type = TYPE_BOOL | TYPE_SET;\n                break;\n            case STRING_SET:\n                type = TYPE_STRING | TYPE_SET;\n                break;\n            case INTEGER_SET:\n                type = TYPE_INT | TYPE_SET;\n                break;\n            case FLOAT_SET:\n                type = TYPE_FLOAT | TYPE_SET;\n                break;\n            case DOUBLE_SET:\n                type = TYPE_DOUBLE | TYPE_SET;\n                break;\n            case BINARY_SET:\n                type = TYPE_DATA | TYPE_SET;\n                break;\n            case DATE_SET:\n                type = TYPE_DATE | TYPE_SET;\n                break;\n            case DECIMAL128_SET:\n                type = TYPE_DECIMAL128 | TYPE_SET;\n                break;\n            case OBJECT_ID_SET:\n                type = TYPE_OBJECT_ID | TYPE_SET;\n                break;\n            case UUID_SET:\n                type = TYPE_UUID | TYPE_SET;\n                break;\n            case LINK_SET:\n                type = TYPE_OBJECT | TYPE_SET;\n                return type;\n            case MIXED_SET:\n                type = TYPE_MIXED | TYPE_SET;\n                break;\n            default:\n                throw new IllegalArgumentException(\n                        String.format(Locale.US, \"Unsupported filed type: '%s'.\", fieldType.name()));\n\n        }\n        int requiredFlag = isRequired ? TYPE_REQUIRED : TYPE_NULLABLE;\n        return type | requiredFlag;\n    }\n\n    private static RealmFieldType convertToRealmFieldType(int propertyType) {\n        // Clear the nullable flag\n        switch (propertyType & ~TYPE_NULLABLE) {\n            case  TYPE_OBJECT:\n                return RealmFieldType.OBJECT;\n            case TYPE_OBJECT | TYPE_ARRAY:\n                return RealmFieldType.LIST;\n            case TYPE_LINKING_OBJECTS | TYPE_ARRAY:\n                return RealmFieldType.LINKING_OBJECTS;\n            case TYPE_INT:\n                return RealmFieldType.INTEGER;\n            case TYPE_BOOL:\n                return RealmFieldType.BOOLEAN;\n            case TYPE_STRING:\n                return RealmFieldType.STRING;\n            case TYPE_DATA:\n                return RealmFieldType.BINARY;\n            case TYPE_DATE:\n                return RealmFieldType.DATE;\n            case TYPE_FLOAT:\n                return RealmFieldType.FLOAT;\n            case TYPE_DOUBLE:\n                return RealmFieldType.DOUBLE;\n            case TYPE_DECIMAL128:\n                return RealmFieldType.DECIMAL128;\n            case TYPE_OBJECT_ID:\n                return RealmFieldType.OBJECT_ID;\n            case TYPE_UUID:\n                return RealmFieldType.UUID;\n            case TYPE_MIXED:\n                return RealmFieldType.MIXED;\n            //noinspection PointlessBitwiseExpression\n            case TYPE_INT | TYPE_ARRAY:\n                return INTEGER_LIST;\n            case TYPE_BOOL | TYPE_ARRAY:\n                return BOOLEAN_LIST;\n            case TYPE_STRING | TYPE_ARRAY:\n                return STRING_LIST;\n            case TYPE_DATA | TYPE_ARRAY:\n                return BINARY_LIST;\n            case TYPE_DATE | TYPE_ARRAY:\n                return DATE_LIST;\n            case TYPE_FLOAT | TYPE_ARRAY:\n                return FLOAT_LIST;\n            case TYPE_DOUBLE | TYPE_ARRAY:\n                return DOUBLE_LIST;\n            case TYPE_DECIMAL128 | TYPE_ARRAY:\n                return DECIMAL128_LIST;\n            case TYPE_OBJECT_ID | TYPE_ARRAY:\n                return OBJECT_ID_LIST;\n            case TYPE_UUID | TYPE_ARRAY:\n                return UUID_LIST;\n            case TYPE_MIXED | TYPE_ARRAY:\n                return MIXED_LIST;\n            case TYPE_MIXED | TYPE_DICTIONARY:\n                return STRING_TO_MIXED_MAP;\n            case TYPE_BOOL | TYPE_DICTIONARY:\n                return STRING_TO_BOOLEAN_MAP;\n            case TYPE_STRING | TYPE_DICTIONARY:\n                return STRING_TO_STRING_MAP;\n            case TYPE_INT | TYPE_DICTIONARY:\n                return STRING_TO_INTEGER_MAP;\n            case TYPE_FLOAT | TYPE_DICTIONARY:\n                return STRING_TO_FLOAT_MAP;\n            case TYPE_DOUBLE | TYPE_DICTIONARY:\n                return STRING_TO_DOUBLE_MAP;\n            case TYPE_DATA | TYPE_DICTIONARY:\n                return STRING_TO_BINARY_MAP;\n            case TYPE_DATE | TYPE_DICTIONARY:\n                return STRING_TO_DATE_MAP;\n            case TYPE_DECIMAL128 | TYPE_DICTIONARY:\n                return STRING_TO_DECIMAL128_MAP;\n            case TYPE_OBJECT_ID | TYPE_DICTIONARY:\n                return STRING_TO_OBJECT_ID_MAP;\n            case TYPE_UUID | TYPE_DICTIONARY:\n                return STRING_TO_UUID_MAP;\n            case TYPE_OBJECT | TYPE_DICTIONARY:\n                return STRING_TO_LINK_MAP;\n            case TYPE_BOOL | TYPE_SET:\n                return BOOLEAN_SET;\n            case TYPE_STRING | TYPE_SET:\n                return STRING_SET;\n            case TYPE_INT | TYPE_SET:\n                return INTEGER_SET;\n            case TYPE_FLOAT | TYPE_SET:\n                return FLOAT_SET;\n            case TYPE_DOUBLE | TYPE_SET:\n                return DOUBLE_SET;\n            case TYPE_DATA | TYPE_SET:\n                return BINARY_SET;\n            case TYPE_DATE | TYPE_SET:\n                return DATE_SET;\n            case TYPE_DECIMAL128 | TYPE_SET:\n                return DECIMAL128_SET;\n            case TYPE_OBJECT_ID | TYPE_SET:\n                return OBJECT_ID_SET;\n            case TYPE_UUID | TYPE_SET:\n                return UUID_SET;\n            case TYPE_OBJECT | TYPE_SET:\n                return LINK_SET;\n            case TYPE_MIXED | TYPE_SET:\n                return MIXED_SET;\n            default:\n                throw new IllegalArgumentException(\n                        String.format(Locale.US, \"Unsupported property type: '%d'\", propertyType));\n\n        }\n    }\n\n    public RealmFieldType getType() {\n        return convertToRealmFieldType(nativeGetType(nativePtr));\n    }\n\n    public String getLinkedObjectName() {\n        return nativeGetLinkedObjectName(nativePtr);\n    }\n\n    public long getColumnKey() {\n        return nativeGetColumnKey(nativePtr);\n    }\n\n    @Override\n    public long getNativePtr() {\n        return nativePtr;\n    }\n\n    @Override\n    public long getNativeFinalizerPtr() {\n        return nativeFinalizerPtr;\n    }\n\n    private static native long nativeGetFinalizerPtr();\n\n    // nativeCreateXxxProperty will be called by OsObjectSchemaInfo directly to avoid creating temporary Property\n    // objects.\n    static native long nativeCreatePersistedProperty(String internalName,\n                                                     String publicName,\n                                                     int type,\n                                                     boolean isPrimary,\n                                                     boolean isIndexed);\n\n    static native long nativeCreatePersistedLinkProperty(String internalName, String publicName, int type, String linkedToName);\n\n    static native long nativeCreateComputedLinkProperty(String name, String sourceClassName, String sourceFieldName);\n\n    private static native int nativeGetType(long nativePtr);\n\n    private static native long nativeGetColumnKey(long nativePtr);\n\n    // Return null if the property is not OBJECT, LIST or LINKING_OBJECT type.\n    private static native String nativeGetLinkedObjectName(long nativePtr);\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/internal/RealmAnyNativeFunctions.java",
    "content": "/*\n * Copyright 2021 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 */\npackage io.realm.internal;\n\nimport java.util.Map;\nimport javax.annotation.Nullable;\n\nimport io.realm.RealmAny;\nimport io.realm.internal.objectstore.OsKeyPathMapping;\n\n\npublic interface RealmAnyNativeFunctions {\n    void handleItem(long listPtr, RealmAny realmAny);\n\n    void handleItem(long listPtr, Map.Entry<String, RealmAny> realmAny);\n\n    void callRawPredicate(TableQuery query, @Nullable OsKeyPathMapping mapping, String predicate, RealmAny... arguments);\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/internal/RealmCore.java",
    "content": "/*\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\npackage io.realm.internal;\n\nimport android.content.Context;\n\nimport com.getkeepsafe.relinker.ReLinker;\n\nimport java.io.File;\nimport java.lang.reflect.Field;\nimport java.util.Locale;\n\nimport io.realm.BuildConfig;\n\n\n/**\n * Utility methods for Realm Core.\n */\npublic class RealmCore {\n\n    private static final String FILE_SEP = File.separator;\n    private static final String PATH_SEP = File.pathSeparator;          // On Windows \";\"\n    private static final String BINARIES_PATH = \"lib\" + PATH_SEP + \"..\" + FILE_SEP + \"lib\";\n    private static final String JAVA_LIBRARY_PATH = \"java.library.path\";\n\n    private static boolean libraryIsLoaded = false;\n\n    public static boolean osIsWindows() {\n        String os = System.getProperty(\"os.name\").toLowerCase(Locale.getDefault());\n        return (os.contains(\"win\"));\n    }\n\n    /**\n     * Loads the .so file. Typically, the .so file is installed and can be found by System.loadLibrary() but\n     * can be damaged or missing. This happens for the Android installer, especially when apps are installed\n     * through other means than the official Play store. In this case, the .so file can be found in the .apk.\n     * In other to access the .apk, an {@link android.content.Context} must be provided.\n     * <p>\n     * Although loadLibrary is synchronized internally from AOSP 4.3, for compatibility reasons,\n     * KEEP synchronized here for old devices!\n     */\n    public static synchronized void loadLibrary(Context context) {\n        if (libraryIsLoaded) {\n            return;\n        }\n        ReLinker.loadLibrary(context, \"realm-jni\", BuildConfig.VERSION_NAME);\n        libraryIsLoaded = true;\n    }\n\n    private static String loadLibraryWindows() {\n///*\n        try {\n            addNativeLibraryPath(BINARIES_PATH);\n            resetLibraryPath();\n        } catch (Throwable e) {\n            // Above can't be used on Android.\n        }\n//*/\n        // Loads debug library first - if available.\n        String jnilib;\n        jnilib = loadCorrectLibrary(\"realm_jni32d\", \"realm_jni64d\");\n        if (jnilib != null) {\n            System.out.println(\"!!! Realm debug version loaded. !!!\\n\");\n        } else {\n            jnilib = loadCorrectLibrary(\"realm_jni32\", \"realm_jni64\");\n            if (jnilib == null) {\n                System.err.println(\"Searched java.library.path=\" + System.getProperty(\"java.library.path\"));\n                throw new RuntimeException(\"Couldn't load the Realm JNI library 'realm_jni32.dll or realm_jni64.dll\" +\n                        \"'. Please include the directory to the library in java.library.path.\");\n            }\n        }\n        return jnilib;\n    }\n\n    private static String loadCorrectLibrary(String... libraryCandidateNames) {\n        for (String libraryCandidateName : libraryCandidateNames) {\n            try {\n                System.loadLibrary(libraryCandidateName);\n                return libraryCandidateName;\n            } catch (Throwable ignored) {\n            }\n        }\n        return null;\n    }\n\n    public static void addNativeLibraryPath(String path) {\n        try {\n            String libraryPath = System.getProperty(JAVA_LIBRARY_PATH) + PATH_SEP + path + PATH_SEP;\n            System.setProperty(JAVA_LIBRARY_PATH, libraryPath);\n        } catch (Exception e) {\n            throw new RuntimeException(\"Cannot set the library path!\", e);\n        }\n    }\n\n    // Hack for having a cross platform location for the lib:\n    // The ClassLoader has a static field (sys_paths) that contains the paths.\n    // If that field is set to null, it is initialized automatically.\n    // Therefore forcing that field to null will result into the reevaluation of the library path\n    // as soon as loadLibrary() is called.\n    private static void resetLibraryPath() {\n        try {\n            // Resets the library path (a hack).\n            Field fieldSysPath = ClassLoader.class.getDeclaredField(\"sys_paths\");\n            fieldSysPath.setAccessible(true);\n            fieldSysPath.set(null, null);\n        } catch (Exception e) {\n            throw new RuntimeException(\"Cannot reset the library path!\", e);\n        }\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/internal/RealmNotifier.java",
    "content": "/*\n * Copyright 2016 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\npackage io.realm.internal;\n\nimport java.io.Closeable;\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport javax.annotation.Nullable;\n\nimport io.realm.RealmChangeListener;\n\n\n/**\n * This interface needs to be implemented by Java and pass to Realm Object Store in order to get notifications when\n * other thread/process changes the Realm file.\n */\n@Keep\npublic abstract class RealmNotifier implements Closeable {\n\n// Calling sequences for a remote commit\n// |-------------------------------+--------------+-----------------------------------|\n// | Thread A                      | Thread B     | Daemon Thread                     |\n// |-------------------------------+--------------+-----------------------------------|\n// |                               | Make changes |                                   |\n// |-------------------------------+--------------+-----------------------------------|\n// |                               |              | epoll callback and notify ALooper |\n// |-------------------------------+--------------+-----------------------------------|\n// | ALooper callback              |              |                                   |\n// | BindingContext::before_notify |              |                                   |\n// | RealmNotifier.beforeNotify    |              |                                   |\n// | BindingContext::did_change    |              |                                   |\n// | RealmNotifier.didChange       |              |                                   |\n// | process_available_async       |              |                                   |\n// | Collection listeners          |              |                                   |\n// |-------------------------------+--------------+-----------------------------------|\n\n    private static class RealmObserverPair<T> extends ObserverPairList.ObserverPair<T, RealmChangeListener<T>> {\n        RealmObserverPair(T observer, RealmChangeListener<T> listener) {\n            super(observer, listener);\n        }\n\n        private void onChange(T observer) {\n            //noinspection ConstantConditions\n            if (observer != null) {\n                listener.onChange(observer);\n            }\n        }\n    }\n\n    private ObserverPairList<RealmObserverPair> realmObserverPairs = new ObserverPairList<RealmObserverPair>();\n    private final ObserverPairList.Callback<RealmObserverPair> onChangeCallBack =\n            new ObserverPairList.Callback<RealmObserverPair>() {\n                @Override\n                public void onCalled(RealmObserverPair pair, Object observer) {\n                    //noinspection unchecked\n                    if (sharedRealm != null && !sharedRealm.isClosed()) {\n                        pair.onChange(observer);\n                    }\n                }\n            };\n\n    protected RealmNotifier(@Nullable OsSharedRealm sharedRealm) {\n        this.sharedRealm = sharedRealm;\n    }\n\n    private OsSharedRealm sharedRealm;\n    // TODO: The only reason we have this is that async transactions is not supported by OS yet. And OS is using ALopper\n    // which will be using a different message queue from which java is using to deliver remote Realm changes message.\n    // We need a way to deliver the async transaction onSuccess callback to the caller thread after the caller Realm\n    // advanced. This is implemented by posting the callback by RealmNotifier.post() first, and check the realm version\n    // in the posted Runnable. If the Realm version there is still behind the async transaction we committed, the\n    // onSuccess callback will be added to this list and be executed later when we get the change event from OS.\n    // This list is NOT supposed to be thread safe!\n    private List<Runnable> transactionCallbacks = new ArrayList<Runnable>();\n\n    // List of runnables called when Object Store is about to start sending out notifications about\n    // a version update for the current thread.\n    private List<Runnable> startSendingNotificationsCallbacks = new ArrayList<>();\n\n    // List of runnables called when Object Store has finished sending out notifications for the\n    // version of the Realm on this thread.\n    private List<Runnable> finishedSendingNotificationsCallbacks = new ArrayList<>();\n\n    // Called from JavaBindingContext::did_change.\n    // This will be called in the caller thread when:\n    // - A committed remote transaction, called from changed event handler.\n    // - A committed remote transaction, called directly from refresh call.\n    // - A committed local transaction, called directly from commitTransaction instead of next event.\n    //   loop.\n    // Package protected to avoid finding class by name in JNI.\n    @SuppressWarnings(\"unused\")\n    // called from java_binding_context.cpp\n    void didChange() {\n        realmObserverPairs.foreach(onChangeCallBack);\n\n        if (!transactionCallbacks.isEmpty()) {\n            // The callback list needs to be cleared before calling to avoid synchronized transactions in the callback\n            // triggers it recursively.\n            List<Runnable> callbacks = transactionCallbacks;\n            transactionCallbacks = new ArrayList<Runnable>();\n            for (Runnable runnable : callbacks) {\n                runnable.run();\n            }\n        }\n    }\n\n    // Called from JavaBindingContext::before_notify.\n    // This will be called in the caller thread when:\n    // 1. Get changed notification by this/other Realm instances.\n    // 2. OsSharedRealm::refresh called.\n    // In both cases, this will be called before the any other callbacks (changed callbacks, async query callbacks.).\n    // Package protected to avoid finding class by name in JNI.\n    @SuppressWarnings(\"unused\")\n    void beforeNotify() {\n        // For the stable iteration.\n        sharedRealm.invalidateIterators();\n    }\n\n    // Called from JavaBindingContext::will_send_notifications\n    // This will be called before any change notifications are delivered when updating a\n    // Realm version. This will be triggered even if no change listeners are registered.\n    void willSendNotifications() {\n        for (int i = 0; i < startSendingNotificationsCallbacks.size(); i++) {\n            startSendingNotificationsCallbacks.get(i).run();\n        }\n    }\n\n    // Called from JavaBindingContext::will_send_notifications\n    void didSendNotifications() {\n        for (int i = 0; i < startSendingNotificationsCallbacks.size(); i++) {\n            finishedSendingNotificationsCallbacks.get(i).run();\n        }\n    }\n\n    /**\n     * Called when close OsSharedRealm to clean up any event left in to queue.\n     */\n    @Override\n    public void close() {\n        removeAllChangeListeners();\n        startSendingNotificationsCallbacks.clear();\n        finishedSendingNotificationsCallbacks.clear();\n    }\n\n    public <T> void addChangeListener(T observer, RealmChangeListener<T> realmChangeListener) {\n        RealmObserverPair observerPair = new RealmObserverPair<>(observer, realmChangeListener);\n        realmObserverPairs.add(observerPair);\n    }\n\n    public <E> void removeChangeListener(E observer, RealmChangeListener<E> realmChangeListener) {\n        realmObserverPairs.remove(observer, realmChangeListener);\n    }\n\n    public <E> void removeChangeListeners(E observer) {\n        realmObserverPairs.removeByObserver(observer);\n    }\n\n    // Since RealmObject is using this notifier as well, use removeChangeListeners to remove all listeners by the given\n    // observer.\n    private void removeAllChangeListeners() {\n        realmObserverPairs.clear();\n    }\n\n    public void addTransactionCallback(Runnable runnable) {\n        transactionCallbacks.add(runnable);\n    }\n\n    /**\n     * For current implementation of async transaction only. See comments for {@link #transactionCallbacks}.\n     *\n     * @param runnable to be executed in the following event loop.\n     */\n    public abstract boolean post(Runnable runnable);\n\n    public int getListenersListSize() {\n        return realmObserverPairs.size();\n    }\n\n    public void addBeginSendingNotificationsCallback(Runnable runnable) {\n        startSendingNotificationsCallbacks.add(runnable);\n    }\n\n    public void addFinishedSendingNotificationsCallback(Runnable runnable) {\n        finishedSendingNotificationsCallbacks.add(runnable);\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/internal/RealmObjectProxy.java",
    "content": "/*\n * Copyright 2015 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\npackage io.realm.internal;\n\nimport edu.umd.cs.findbugs.annotations.SuppressFBWarnings;\nimport io.realm.ProxyState;\nimport io.realm.RealmModel;\n\n\n/**\n * Interface making it easy to determine if an object is the generated RealmProxy class or the original class.\n * <p>\n * Ideally all the static methods was also present here, but that is not supported before Java 8.\n */\npublic interface RealmObjectProxy extends RealmModel {\n\n    void realm$injectObjectContext();\n\n    ProxyState realmGet$proxyState();\n\n    /**\n     * Tuple class for saving meta data about a cached RealmObject.\n     */\n    class CacheData<E extends RealmModel> {\n        @SuppressFBWarnings(\"URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD\")\n        public int minDepth;\n        public final E object;\n\n        public CacheData(int minDepth, E object) {\n            this.minDepth = minDepth;\n            this.object = object;\n        }\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/internal/RealmProxyMediator.java",
    "content": "/*\n * Copyright 2015 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\npackage io.realm.internal;\n\nimport android.util.JsonReader;\n\nimport org.json.JSONException;\nimport org.json.JSONObject;\n\nimport java.util.Collection;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Set;\n\nimport io.realm.ImportFlag;\nimport io.realm.Realm;\nimport io.realm.RealmModel;\nimport io.realm.RealmObject;\nimport io.realm.exceptions.RealmException;\n\n\n/**\n * Superclass for the RealmProxyMediator class. This class contains all static methods introduced by the annotation\n * processor as part of the RealmProxy classes.\n * <p>\n * Classes extending this class act as binders between the static methods inside each RealmProxy and the code at\n * runtime. We cannot rely on using reflection as the RealmProxies are generated by the annotation processor before\n * ProGuard is run. So after ProGuard has run there is a mismatch between the name of the RealmProxy and the original\n * RealmObject class.\n */\npublic abstract class RealmProxyMediator {\n\n    /**\n     * Returns a map of model classes to their schema information which are defined in this mediator. Classes which have\n     * same class name but in different packages should have different names in the {@code OsObjectSchemaInfo}.\n     *\n     * @return the map with classes and their schema information.\n     */\n    public abstract Map<Class<? extends RealmModel>, OsObjectSchemaInfo> getExpectedObjectSchemaInfoMap();\n\n    /**\n     * Creates {@link ColumnInfo} for the given RealmObject class.\n     *\n     * @param clazz which {@link RealmObject} model class to create the column info of.\n     * @param osSchemaInfo the {@link OsSchemaInfo} for the corresponding Realm instance.\n     * @return the field indices map.\n     */\n    public abstract ColumnInfo createColumnInfo(Class<? extends RealmModel> clazz, OsSchemaInfo osSchemaInfo);\n\n    /**\n     * Returns the name that Realm should use for all its internal tables. This is the un-obfuscated simple name of the\n     * class.\n     *\n     * @param clazz the {@link RealmModel} or the Realm object proxy class reference.\n     * @return the simple name of an RealmObject class (before it has been obfuscated).\n     */\n    public final String getSimpleClassName(Class<? extends RealmModel> clazz) {\n        return getSimpleClassNameImpl(Util.getOriginalModelClass(clazz));\n    }\n\n    /**\n     * Returns the name that Realm should use for all its internal tables. This is the un-obfuscated simple name of the\n     * class.\n     *\n     * @param clazz the {@link RealmModel} class reference.\n     * @return the simple name of an RealmObject class (before it has been obfuscated).\n     */\n    protected abstract String getSimpleClassNameImpl(Class<? extends RealmModel> clazz);\n\n    /**\n     * Returns a reference of the class that represents the specified class name. The returning class reference would be\n     * a realization of {@link RealmModel}.\n     *\n     * @param className the class name.\n     * @return a class reference to the representing class.\n     */\n    public final <T extends RealmModel> Class<T> getClazz(String className) {\n        return getClazzImpl(className);\n    }\n\n    /**\n     * Returns a reference of the class that represents the specified class name. The returning class reference would be\n     * a realization of {@link RealmModel}.\n     *\n     * @param className the class name.\n     * @return a class reference to the representing class.\n     */\n    protected abstract <T extends RealmModel> Class<T> getClazzImpl(String className);\n\n    /**\n     * Returns {@code true} true if the provided class reference has a primary key defined.\n     *\n     * @param clazz the {@link RealmModel} or the Realm object proxy class reference.\n     * @return true if the class has a defined primary key, false otherwise.\n     */\n    public boolean hasPrimaryKey(Class<? extends RealmModel> clazz){\n        return hasPrimaryKeyImpl(clazz);\n    }\n\n    /**\n     * Returns {@code true} if the provided class reference has a primary key defined.\n     *\n     * @param clazz the {@link RealmModel} or the Realm object proxy class reference.\n     * @return true if the class has a defined primary key, false otherwise.\n     */\n    protected abstract boolean hasPrimaryKeyImpl(Class<? extends RealmModel> clazz);\n\n    /**\n     * Creates a new instance of an {@link RealmObjectProxy} for the given RealmObject class.\n     *\n     * @param clazz the {@link RealmObject} to create {@link RealmObjectProxy} for.\n     * @param acceptDefaultValue {@code true} to accept the values set in the constructor, {@code false} otherwise.\n     * @param excludeFields the column names whose default value will be ignored if the {@code acceptDefaultValue}\n     * is {@code true}. Only {@link io.realm.RealmModel} and {@link io.realm.RealmList}\n     * column will respect this.\n     * No effects if the {@code acceptDefaultValue} is {@code false}.\n     * @return created {@link RealmObjectProxy} object.\n     */\n    public abstract <E extends RealmModel> E newInstance(Class<E> clazz,\n            Object baseRealm,\n            Row row,\n            ColumnInfo columnInfo,\n            boolean acceptDefaultValue,\n            List<String> excludeFields);\n\n    /**\n     * Returns the list of RealmObject classes that can be saved in this Realm.\n     *\n     * @return list of class references to RealmObject classes. Empty list if no RealmObjects are supported.\n     */\n    public abstract Set<Class<? extends RealmModel>> getModelClasses();\n\n    /**\n     * Copies an unmanaged {@link RealmObject} or a RealmObject from another Realm to this Realm. After being copied\n     * any changes to the original object will not be persisted.\n     *\n     * @param realm the reference to the {@link Realm} where the object will be copied.\n     * @param object the object to copy properties from.\n     * @param update {@code true} if object has a primary key and should try to update already existing data,\n     * {@code false} otherwise.\n     * @param cache the cache for mapping between unmanaged objects and their {@link RealmObjectProxy} representation.\n     * @param flags any special flags controlling the behaviour of the import.\n     * @return the managed Realm object.\n     */\n    public abstract <E extends RealmModel> E copyOrUpdate(Realm realm, E object, boolean update, Map<RealmModel, RealmObjectProxy> cache, Set<ImportFlag> flags);\n\n    /**\n     * Inserts an unmanaged RealmObject. This is generally faster than {@link #copyOrUpdate(Realm, RealmModel, boolean, Map, Set)}\n     * since it doesn't return the inserted elements, and performs minimum allocations and checks.\n     * After being inserted any changes to the original object will not be persisted.\n     *\n     * @param realm reference to the {@link Realm} where the object will be inserted.\n     * @param object {@link RealmObject} to insert.\n     * @param cache the cache for mapping between unmanaged objects and their table row index for eventual reuse.\n     *\n     * @return the key of the object inserted in the realm.\n     */\n    public abstract long insert(Realm realm, RealmModel object, Map<RealmModel, Long> cache);\n\n    /**\n     * Inserts or updates a RealmObject. This is generally faster than {@link #copyOrUpdate(Realm, RealmModel, boolean, Map, Set)}\n     * since it doesn't return the inserted elements, and performs minimum allocations and checks.\n     * After being inserted any changes to the original object will not be persisted.\n     *\n     * @param realm reference to the {@link Realm} where the objects will be inserted.\n     * @param object {@link RealmObject} to insert.\n     * @param cache the cache for mapping between unmanaged objects and their table row index for eventual reuse.\n     *\n     * @return the key of the object inserted or updated in the realm.\n     */\n    public abstract long insertOrUpdate(Realm realm, RealmModel object, Map<RealmModel, Long> cache);\n\n    /**\n     * Inserts or updates a RealmObject. This is generally faster than {@link #copyOrUpdate(Realm, RealmModel, boolean, Map, Set)}\n     * since it doesn't return the inserted elements, and performs minimum allocations and checks.\n     * After being inserted any changes to the original objects will not be persisted.\n     *\n     * @param realm reference to the {@link Realm} where the objects will be inserted.\n     * @param objects Collection of {@link RealmObject} to insert or update. This must not be empty.\n     */\n    public abstract void insertOrUpdate(Realm realm, Collection<? extends RealmModel> objects);\n\n    /**\n     * Inserts a RealmObject. This is generally faster than {@link #copyOrUpdate(Realm, RealmModel, boolean, Map, Set)} since\n     * it doesn't return the inserted elements, and performs minimum allocations and checks.\n     * After being inserted any changes to the original objects will not be persisted.\n     *\n     * @param realm reference to the {@link Realm} where the objects will be inserted.\n     * @param objects Collection of {@link RealmObject} to insert or update. This must not be empty.\n     */\n    public abstract void insert(Realm realm, Collection<? extends RealmModel> objects);\n\n    /**\n     * Creates or updates a {@link RealmObject} using the provided JSON data.\n     *\n     * @param clazz the type of {@link RealmObject}\n     * @param realm the reference to {@link Realm} where to create the object.\n     * @param json the JSON data\n     * @param update {@code true} if Realm should try to update a existing object. This requires that the RealmObject\n     * class has a @PrimaryKey.\n     * @return RealmObject that has been created or updated.\n     * @throws JSONException if the JSON mapping doesn't match the expected class.\n     */\n    public abstract <E extends RealmModel> E createOrUpdateUsingJsonObject(Class<E> clazz, Realm realm, JSONObject json, boolean update) throws JSONException;\n\n    /**\n     * Creates new {@link RealmObject} based on a JSON input stream.\n     *\n     * @param clazz the type of {@link RealmObject}\n     * @param realm the reference to Realm where to create the object.\n     * @param reader the reference to the InputStream containing the JSON data.\n     * @return the created {@link RealmObject}\n     * @throws IOException if an error occurs with the input stream.\n     */\n    public abstract <E extends RealmModel> E createUsingJsonStream(Class<E> clazz, Realm realm, JsonReader reader) throws java.io.IOException;\n\n    /**\n     * Creates a deep unmanaged copy of a RealmObject. This is a deep copy so all links will be copied as well.\n     * The depth can be restricted to a maximum depth after which all links will be turned into null values instead.\n     *\n     * @param realmObject RealmObject to copy. It must be a valid object.\n     * @param maxDepth restrict the depth of the copy to this level. The root object is depth {@code 0}.\n     * @param cache cache used to make sure unmanaged objects are reused correctly.\n     * @return an unmanaged copy of the given object.\n     */\n    public abstract <E extends RealmModel> E createDetachedCopy(E realmObject, int maxDepth, Map<RealmModel, RealmObjectProxy.CacheData<RealmModel>> cache);\n\n    /**\n     * Returns whether or not this class is considered \"embedded\".\n     */\n    public abstract <E extends RealmModel> boolean isEmbedded(Class<E> clazz);\n\n\n    /**\n     * Updates an embedded object with the values from an unmanaged object.\n     *\n     * @param realm the reference to the {@link Realm} where the object will be copied.\n     * @param unmanagedObject the unmanaged objects whose values should be used to update the manged object\n     * @param managedObject the managed object that should be updated\n     * @param cache the cache for mapping between unmanaged objects and their {@link RealmObjectProxy} representation.\n     * @param flags any special flags controlling the behaviour of the import.\n     */\n    public abstract <E extends RealmModel> void updateEmbeddedObject(Realm realm, E unmanagedObject, E managedObject, Map<RealmModel, RealmObjectProxy> cache, Set<ImportFlag> flags);\n\n    /**\n     * Returns whether Realm transformer has been applied or not. Subclasses of this class are\n     * created by the annotation processor and the Realm transformer will add an override of\n     * this method that always return {@code true} if the transform was successful.\n     *\n     * @return {@code true} if Realm transformer was applied, {@code false} otherwise.\n     */\n    public boolean transformerApplied() {\n        return false;\n    }\n\n    @Override\n    public boolean equals(Object o) {\n        if (!(o instanceof RealmProxyMediator)) {\n            return false;\n        }\n        RealmProxyMediator other = (RealmProxyMediator) o;\n        return getModelClasses().equals(other.getModelClasses());\n    }\n\n    @Override\n    public int hashCode() {\n        return getModelClasses().hashCode();\n    }\n\n    protected static void checkClass(Class<? extends RealmModel> clazz) {\n        //noinspection ConstantConditions\n        if (clazz == null) {\n            throw new NullPointerException(\"A class extending RealmObject must be provided\");\n        }\n    }\n\n    protected static void checkClassName(String className) {\n        //noinspection ConstantConditions\n        if ((className == null) || (className.isEmpty())) {\n            throw new NullPointerException(\"A class extending RealmObject must be provided\");\n        }\n    }\n\n    protected static RealmException getMissingProxyClassException(Class<? extends RealmModel> clazz) {\n        return new RealmException(\n                String.format(\"'%s' is not part of the schema for this Realm.\", clazz.toString()));\n    }\n\n    protected static RealmException getMissingProxyClassException(String className) {\n        return new RealmException(\n                String.format(\"'%s' is not part of the schema for this Realm.\", className));\n    }\n\n    protected static IllegalStateException getNotEmbeddedClassException(String className) {\n        return new IllegalStateException(\"This class is not marked embedded: \" + className);\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/internal/Row.java",
    "content": "/*\n * Copyright 2015 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\npackage io.realm.internal;\n\nimport org.bson.types.Decimal128;\nimport org.bson.types.ObjectId;\n\nimport java.util.Date;\nimport java.util.UUID;\n\nimport javax.annotation.Nullable;\n\nimport io.realm.RealmFieldType;\nimport io.realm.internal.core.NativeRealmAny;\n\n\n/**\n * Interface for Row objects that act as wrappers around the Realm Core Row object.\n * <p>\n * When the actual class which implements this interface is {@link CheckedRow}, all methods in this\n * interface always validate their parameters and throw an appropriate exception if invalid.\n * For example, methods which accept a column name check the existence of the column and throw\n * {@link IllegalArgumentException} if not found.\n */\npublic interface Row {\n\n    long getColumnCount();\n\n    /**\n     * Returns all the column names of the tables.\n     *\n     * @return array of column names.\n     */\n    String[] getColumnNames();\n\n    /**\n     * Returns the column key from a column name.\n     *\n     * @param columnName column name\n     * @return the column key\n     */\n    long getColumnKey(String columnName);\n\n    /**\n     * Gets the type of a column identified by the columnKey.\n     *\n     * @param columnKey column key.\n     * @return the type of the particular column.\n     */\n    RealmFieldType getColumnType(long columnKey);\n\n    Table getTable();\n\n    /**\n     * Returns the object key in the original source table, not the tableview.\n     */\n    long getObjectKey();\n\n    long getLong(long columnKey);\n\n    boolean getBoolean(long columnKey);\n\n    float getFloat(long columnKey);\n\n    double getDouble(long columnKey);\n\n    Date getDate(long columnKey);\n\n    String getString(long columnKey);\n\n    byte[] getBinaryByteArray(long columnKey);\n\n    Decimal128 getDecimal128(long columnKey);\n\n    ObjectId getObjectId(long columnKey);\n\n    UUID getUUID(long columnKey);\n\n    NativeRealmAny getNativeRealmAny(long realmAnyColKey);\n\n    long getLink(long columnKey);\n\n    boolean isNullLink(long columnKey);\n\n    OsList getModelList(long columnKey);\n\n    OsList getValueList(long columnKey, RealmFieldType fieldType);\n\n    OsMap getRealmAnyMap(long columnKey);\n\n    OsMap getModelMap(long columnKey);\n\n    OsMap getValueMap(long columnKey, RealmFieldType fieldType);\n\n    OsSet getRealmAnySet(long columnKey);\n\n    OsSet getModelSet(long columnKey);\n\n    OsSet getValueSet(long columnKey, RealmFieldType fieldType);\n\n    void setLong(long columnKey, long value);\n\n    void setBoolean(long columnKey, boolean value);\n\n    void setFloat(long columnKey, float value);\n\n    void setDouble(long columnKey, double value);\n\n    void setDate(long columnKey, Date date);\n\n    void setString(long columnKey, @Nullable String value);\n\n    void setBinaryByteArray(long columnKey, @Nullable byte[] data);\n\n    void setLink(long columnKey, long value);\n\n    void nullifyLink(long columnKey);\n\n    boolean isNull(long columnKey);\n\n    void setNull(long columnKey);\n\n    void setDecimal128(long columnKey, Decimal128 value);\n\n    void setObjectId(long columnKey, ObjectId value);\n\n    void setUUID(long columnKey, UUID value);\n\n    void setRealmAny(long columnKey, long value);\n\n    // Creates a new Embedded object in the given property.\n    // This will replace any existing object which will be\n    // deleted. The Obj pointer for the new object is returned.\n    long createEmbeddedObject(long columnKey, RealmFieldType parentPropertyType);\n\n    /**\n     * Checks if the row is still valid.\n     *\n     * @return {@code true} if the row is still valid and attached to the underlying data. {@code false} otherwise.\n     */\n    boolean isValid();\n\n    /**\n     * Throws {@link IllegalStateException} if the row is not attached.\n     */\n    void checkIfAttached();\n\n    /**\n     * Returns {@code true} if the field name exists.\n     *\n     * @param fieldName field name to check.\n     * @return {@code true} if field name exists, {@code false} otherwise.\n     */\n    boolean hasColumn(String fieldName);\n\n    /**\n     * Returns a frozen copy of this Row.\n     */\n    Row freeze(OsSharedRealm frozenRealm);\n\n    /**\n     * Return whether the row is considered to be loaded, i.e. it doesn't represent a query in flight.\n     *\n     */\n    boolean isLoaded();\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/internal/StatefulCollectionChangeSet.java",
    "content": "package io.realm.internal;\n\nimport javax.annotation.Nullable;\n\nimport io.realm.OrderedCollectionChangeSet;\n\n/**\n * A wrapper around {@link OsCollectionChangeSet} that makes it stateful with regard to how many\n * times it has been invoked.\n *\n * Note that Object Store will calculate the changes between the query was registered and when it\n * completes. This information is not useful and might even be misleading when reporting first\n * result ({@link io.realm.OrderedCollectionChangeSet.State#INITIAL}.\n */\npublic class StatefulCollectionChangeSet implements OrderedCollectionChangeSet {\n\n    private final OrderedCollectionChangeSet changeset;\n    private final Throwable error;\n    private final State state;\n\n    /**\n     * @param backingChangeset Underlying changeset backing this.\n     */\n    public StatefulCollectionChangeSet(OsCollectionChangeSet backingChangeset) {\n        this.changeset = backingChangeset;\n\n        // Calculate the state here since object is immutable\n        boolean isInitial = backingChangeset.isFirstAsyncCallback();\n        error = backingChangeset.getError();\n        if (error != null) {\n            state = State.ERROR;\n        } else {\n            state = (isInitial) ? State.INITIAL : State.UPDATE;\n        }\n    }\n\n    @Override\n    public State getState() {\n        return state;\n    }\n\n    @Override\n    public int[] getDeletions() {\n        return changeset.getDeletions();\n    }\n\n    @Override\n    public int[] getInsertions() {\n        return changeset.getInsertions();\n    }\n\n    @Override\n    public int[] getChanges() {\n        return changeset.getChanges();\n    }\n\n    @Override\n    public Range[] getDeletionRanges() {\n        return changeset.getDeletionRanges();\n    }\n\n    @Override\n    public Range[] getInsertionRanges() {\n        return changeset.getInsertionRanges();\n    }\n\n    @Override\n    public Range[] getChangeRanges() {\n        return changeset.getChangeRanges();\n    }\n\n    @Nullable\n    @Override\n    public Throwable getError() {\n        return error;\n    }\n\n}\n\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/internal/Table.java",
    "content": "/*\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\npackage io.realm.internal;\n\nimport org.bson.types.Decimal128;\nimport org.bson.types.ObjectId;\n\nimport java.util.Date;\nimport java.util.UUID;\n\nimport javax.annotation.Nullable;\n\nimport io.realm.RealmFieldType;\nimport io.realm.exceptions.RealmPrimaryKeyConstraintException;\n\n\n/**\n * This class is a base class for all Realm tables. The class supports all low level methods\n * (define/insert/delete/update) a table has. All the native communications to the Realm C++ library are also handled by\n * this class.\n */\npublic class Table implements NativeObject {\n\n    private static final String TABLE_PREFIX = Util.getTablePrefix();\n    private static final int TABLE_NAME_MAX_LENGTH = 63; // Max length of table names\n    public static final int CLASS_NAME_MAX_LENGTH = TABLE_NAME_MAX_LENGTH - TABLE_PREFIX.length(); // Max length of class names\n    public static final long INFINITE = -1;\n    public static final boolean NULLABLE = true;\n    public static final boolean NOT_NULLABLE = false;\n    public static final int NO_MATCH = -1;\n\n    public static final int MAX_BINARY_SIZE = 0xFFFFF8 - 8/*array header size*/;\n    public static final int MAX_STRING_SIZE = 0xFFFFF8 - 8/*array header size*/ - 1;\n\n    private static final long nativeFinalizerPtr = nativeGetFinalizerPtr();\n\n    private final long nativeTableRefPtr;\n    private final NativeContext context;\n\n    private final OsSharedRealm sharedRealm;\n\n    Table(OsSharedRealm sharedRealm, long nativeTableRefPointer) {\n        this.context = sharedRealm.context;\n        this.sharedRealm = sharedRealm;\n        this.nativeTableRefPtr = nativeTableRefPointer;\n        context.addReference(this);\n    }\n\n    @Override\n    public long getNativePtr() {\n        return nativeTableRefPtr;\n    }\n\n    @Override\n    public long getNativeFinalizerPtr() {\n        return nativeFinalizerPtr;\n    }\n\n    public Table getTable() {\n        return this;\n    }\n\n    /*\n     * Checks if the Table is valid.\n     * Whenever a Table/subtable is changed/updated all it's subtables are invalidated.\n     * You can no longer perform any actions on the table, and if done anyway, an exception is thrown.\n     * The only method you can call is 'isValid()'.\n     */\n    public boolean isValid() {\n        return nativeTableRefPtr != 0 && nativeIsValid(nativeTableRefPtr);\n    }\n\n    private void verifyColumnName(String name) {\n        if (name.length() > 63) {\n            throw new IllegalArgumentException(\"Column names are currently limited to max 63 characters.\");\n        }\n    }\n\n    /**\n     * Adds a column to the table dynamically.\n     *\n     * @param type the column type.\n     * @param name the field/column name.\n     * @param isNullable {@code true} if column can contain null values, {@code false} otherwise.\n     * @return the column key of the new column.\n     */\n    public long addColumn(RealmFieldType type, String name, boolean isNullable) {\n        verifyColumnName(name);\n        switch (type) {\n            case INTEGER:\n            case BOOLEAN:\n            case STRING:\n            case BINARY:\n            case DATE:\n            case FLOAT:\n            case DOUBLE:\n            case DECIMAL128:\n            case OBJECT_ID:\n            case MIXED:\n            case UUID:\n                return nativeAddColumn(nativeTableRefPtr, type.getNativeValue(), name, isNullable);\n\n            case INTEGER_LIST:\n            case BOOLEAN_LIST:\n            case STRING_LIST:\n            case BINARY_LIST:\n            case DATE_LIST:\n            case FLOAT_LIST:\n            case DOUBLE_LIST:\n            case DECIMAL128_LIST:\n            case OBJECT_ID_LIST:\n            case UUID_LIST:\n            case MIXED_LIST:\n                return nativeAddPrimitiveListColumn(nativeTableRefPtr,\n                        type.getNativeValue() - Property.TYPE_ARRAY,\n                        name,\n                        isNullable);\n\n            case STRING_TO_INTEGER_MAP:\n            case STRING_TO_BOOLEAN_MAP:\n            case STRING_TO_STRING_MAP:\n            case STRING_TO_BINARY_MAP:\n            case STRING_TO_DATE_MAP:\n            case STRING_TO_FLOAT_MAP:\n            case STRING_TO_DOUBLE_MAP:\n            case STRING_TO_DECIMAL128_MAP:\n            case STRING_TO_OBJECT_ID_MAP:\n            case STRING_TO_UUID_MAP:\n            case STRING_TO_MIXED_MAP:\n                return nativeAddPrimitiveDictionaryColumn(nativeTableRefPtr,\n                        type.getNativeValue() - Property.TYPE_DICTIONARY,\n                        name,\n                        isNullable);\n\n            case INTEGER_SET:\n            case BOOLEAN_SET:\n            case STRING_SET:\n            case BINARY_SET:\n            case DATE_SET:\n            case FLOAT_SET:\n            case DOUBLE_SET:\n            case DECIMAL128_SET:\n            case OBJECT_ID_SET:\n            case UUID_SET:\n            case MIXED_SET:\n                return nativeAddPrimitiveSetColumn(nativeTableRefPtr,\n                        type.getNativeValue() - Property.TYPE_SET,\n                        name,\n                        isNullable);\n\n            default:\n                throw new IllegalArgumentException(\"Unsupported type: \" + type);\n        }\n    }\n\n    /**\n     * Adds a non-nullable column to the table dynamically.\n     *\n     * @return the column key of the new column.\n     */\n    public long addColumn(RealmFieldType type, String name) {\n        return addColumn(type, name, false);\n    }\n\n    /**\n     * Adds a link column to the table dynamically.\n     *\n     * @return the column key of the new column.\n     */\n    public long addColumnLink(RealmFieldType type, String name, Table table) {\n        verifyColumnName(name);\n        return nativeAddColumnLink(nativeTableRefPtr, type.getNativeValue(), name, table.nativeTableRefPtr);\n    }\n\n    public long addColumnDictionaryLink(RealmFieldType type, String name, Table table) {\n        verifyColumnName(name);\n        return nativeAddColumnDictionaryLink(nativeTableRefPtr, type.getNativeValue(), name, table.nativeTableRefPtr);\n    }\n\n    public long addColumnSetLink(RealmFieldType type, String name, Table table) {\n        verifyColumnName(name);\n        return nativeAddColumnSetLink(nativeTableRefPtr, type.getNativeValue(), name, table.nativeTableRefPtr);\n    }\n\n    /**\n     * Removes a column in the table dynamically.\n     * <p>\n     * It should be noted if {@code columnKey} is the same as the primary key column key,\n     * the primary key column is removed from the meta table.\n     *\n     * @param columnKey the column key to be removed.\n     */\n    public void removeColumn(long columnKey) {\n        final String className = getClassName();\n        // Checks the PK column key before removing a column. We don't know if we're hitting a PK col,\n        // but it should be noted that once a column is removed, there is no way we can find whether\n        // a PK exists or not.\n        final String columnName = getColumnName(columnKey);\n        final String pkName = OsObjectStore.getPrimaryKeyForObject(sharedRealm, getClassName());\n\n        // First removes a column. If there is no error, we can proceed. Otherwise, it will stop here.\n        nativeRemoveColumn(nativeTableRefPtr, columnKey);\n\n        // Checks if a PK exists and takes actions if there is.\n        if (columnName.equals(pkName)) {\n            // In case we're hitting PK column, we should remove the PK as it is either 1) a user has\n            // forgotten to remove PK or 2) removeColumn gets called before setPrimaryKey(null) is called.\n            // Since there is no danger in removing PK twice, we'll do it here to be on safe side.\n            OsObjectStore.setPrimaryKeyForObject(sharedRealm, className, null);\n        }\n    }\n\n    /**\n     * Renames a column in the table. If the column is a primary key column, the corresponding entry\n     * in PrimaryKeyTable will be renamed accordingly.\n     *\n     * @param columnKey the column to be renamed.\n     * @param newName a new name replacing the old column name.\n     * @throws IllegalArgumentException if {@code newFieldName} is an empty string, or exceeds field name length limit.\n     */\n    public void renameColumn(long columnKey, String newName) {\n        verifyColumnName(newName);\n        // Gets the old column name. We'll assume that the old column name is *NOT* an empty string.\n        final String oldName = nativeGetColumnName(nativeTableRefPtr, columnKey);\n        final String pkName = OsObjectStore.getPrimaryKeyForObject(sharedRealm, getClassName());\n\n        // Then let's try to rename a column. If an error occurs for some reasons, we'll throw.\n        nativeRenameColumn(nativeTableRefPtr, columnKey, newName);\n\n        // Renames a primary key. At this point, renaming the column name should have been fine.\n        if (oldName.equals(pkName)) {\n            try {\n                OsObjectStore.setPrimaryKeyForObject(sharedRealm, getClassName(), newName);\n            } catch (Exception e) {\n                // We failed to rename the pk meta table. roll back the column name, not pk meta table\n                // then rethrow.\n                nativeRenameColumn(nativeTableRefPtr, columnKey, oldName);\n                throw new RuntimeException(e);\n            }\n        }\n    }\n\n    /**\n     * Checks whether the specific column is nullable?\n     *\n     * @param columnKey the column to check.\n     * @return {@code true} if column is nullable, {@code false} otherwise.\n     */\n    public boolean isColumnNullable(long columnKey) {\n        return nativeIsColumnNullable(nativeTableRefPtr, columnKey);\n    }\n\n    /**\n     * Converts a column to be nullable.\n     *\n     * @param columnKey the key for the column to convert.\n     */\n    public void convertColumnToNullable(long columnKey) {\n        if (sharedRealm.isSyncRealm()) {\n            throw new IllegalStateException(\"This method is only available for non-synchronized Realms\");\n        }\n        nativeConvertColumnToNullable(nativeTableRefPtr, columnKey, isPrimaryKey(columnKey));\n    }\n\n    /**\n     * Converts a column to be not nullable. null values will be converted to default values.\n     *\n     * @param columnKey the key for the column to convert.\n     */\n    public void convertColumnToNotNullable(long columnKey) {\n        if (sharedRealm.isSyncRealm()) {\n            throw new IllegalStateException(\"This method is only available for non-synchronized Realms\");\n        }\n        nativeConvertColumnToNotNullable(nativeTableRefPtr, columnKey, isPrimaryKey(columnKey));\n    }\n\n    // Table Size and deletion. AutoGenerated subclasses are nothing to do with this\n    // class.\n\n    /**\n     * Gets the number of entries/rows of this table.\n     *\n     * @return the number of rows.\n     */\n    public long size() {\n        return nativeSize(nativeTableRefPtr);\n    }\n\n    /**\n     * Checks whether this table is empty or not.\n     *\n     * @return {@code true} if empty, otherwise {@code false}.\n     */\n    public boolean isEmpty() {\n        return size() == 0;\n    }\n\n    /**\n     * Clears the table i.e., deleting all rows in the table.\n     */\n    public void clear() {\n        checkImmutable();\n        nativeClear(nativeTableRefPtr);\n    }\n\n    // Column Information.\n\n    /**\n     * Returns the number of columns in the table.\n     *\n     * @return the number of columns.\n     */\n    public long getColumnCount() {\n        return nativeGetColumnCount(nativeTableRefPtr);\n    }\n\n    /**\n     * Returns the name of a column identified by columnKey.\n     *\n     * @param columnKey the key of the column to find.\n     * @return the name of the column.\n     */\n    public String getColumnName(long columnKey) {\n        return nativeGetColumnName(nativeTableRefPtr, columnKey);\n    }\n\n    public String[] getColumnNames() {\n        return nativeGetColumnNames(nativeTableRefPtr);\n    }\n\n    public long getColumnKey(String columnName) {\n        if (columnName == null) {\n            throw new IllegalArgumentException(\"Column name can not be null.\");\n        }\n        return nativeGetColumnKey(nativeTableRefPtr, columnName);\n    }\n\n    /**\n     * Gets the type of a column identified by the columnKey.\n     *\n     * @param columnKey key of the column.\n     * @return the type of the particular column.\n     */\n    public RealmFieldType getColumnType(long columnKey) {\n        return RealmFieldType.fromNativeValue(nativeGetColumnType(nativeTableRefPtr, columnKey));\n    }\n\n    /**\n     * Removes a row from the specific row key. If it is not the last row in the table, it then moves the last row into\n     * the vacated slot.\n     *\n     * @param rowKey the row key\n     */\n    public void moveLastOver(long rowKey) {\n        checkImmutable();\n        nativeMoveLastOver(nativeTableRefPtr, rowKey);\n    }\n\n    /**\n     * Checks if a given column is a primary key column.\n     *\n     * @param columnKey key of the column.\n     * @return {@code true} if column is a primary key, {@code false} otherwise.\n     */\n    private boolean isPrimaryKey(long columnKey) {\n        return getColumnName(columnKey).equals(OsObjectStore.getPrimaryKeyForObject(sharedRealm, getClassName()));\n    }\n\n    /**\n     * Throws a properly formatted exception when multiple objects with the same primary key\n     * value is detected.\n     *\n     * @param value the primary key value.\n     */\n    public static void throwDuplicatePrimaryKeyException(Object value) {\n        throw new RealmPrimaryKeyConstraintException(\"Value already exists: \" + value);\n    }\n\n    //\n    // Getters\n    //\n\n    public OsSharedRealm getSharedRealm() {\n        return sharedRealm;\n    }\n\n    public long getLong(long columnKey, long rowKey) {\n        return nativeGetLong(nativeTableRefPtr, columnKey, rowKey);\n    }\n\n    public boolean getBoolean(long columnKey, long rowKey) {\n        return nativeGetBoolean(nativeTableRefPtr, columnKey, rowKey);\n    }\n\n    public float getFloat(long columnKey, long rowKey) {\n        return nativeGetFloat(nativeTableRefPtr, columnKey, rowKey);\n    }\n\n    public double getDouble(long columnKey, long rowKey) {\n        return nativeGetDouble(nativeTableRefPtr, columnKey, rowKey);\n    }\n\n    public Date getDate(long columnKey, long rowKey) {\n        return new Date(nativeGetTimestamp(nativeTableRefPtr, columnKey, rowKey));\n    }\n\n    /**\n     * Gets the value of a (string) cell.\n     *\n     * @param columnKey column key.\n     * @param rowKey row key.\n     * @return value of the particular cell\n     */\n    public String getString(long columnKey, long rowKey) {\n        return nativeGetString(nativeTableRefPtr, columnKey, rowKey);\n    }\n\n    public byte[] getBinaryByteArray(long columnKey, long rowKey) {\n        return nativeGetByteArray(nativeTableRefPtr, columnKey, rowKey);\n    }\n\n    public long getLink(long columnKey, long rowKey) {\n        return nativeGetLink(nativeTableRefPtr, columnKey, rowKey);\n    }\n\n    public Table getLinkTarget(long columnKey) {\n        long nativeTablePointer = nativeGetLinkTarget(nativeTableRefPtr, columnKey);\n        // Copies context reference from parent.\n        return new Table(this.sharedRealm, nativeTablePointer);\n    }\n\n    /**\n     * Returns a non-checking Row. Incorrect use of this Row will cause a hard core crash.\n     * If error checking is required, use {@link #getCheckedRow(long)} instead.\n     *\n     * @param rowKey row  key to fetch.\n     * @return the unsafe row wrapper object.\n     */\n    public UncheckedRow getUncheckedRow(long rowKey) {\n        return UncheckedRow.getByRowKey(context, this, rowKey);\n    }\n\n    /**\n     * Returns a non-checking Row. Incorrect use of this Row will cause a hard core crash.\n     * If error checking is required, use {@link #getCheckedRow(long)} instead.\n     *\n     * @param nativeRowPointer the pointer to the row to fetch.\n     * @return the unsafe row wrapper object.\n     */\n    public UncheckedRow getUncheckedRowByPointer(long nativeRowPointer) {\n        return UncheckedRow.getByRowPointer(context, this, nativeRowPointer);\n    }\n\n    /**\n     * Returns a wrapper around Row access. All access will be error checked in JNI and will throw an appropriate\n     * {@link RuntimeException} if used incorrectly.\n     * <p>\n     * If error checking is done elsewhere, consider using {@link #getUncheckedRow(long)} for better performance.\n     *\n     * @param objKey the Object Key.\n     * @return the safe row wrapper object.\n     */\n    public CheckedRow getCheckedRow(long objKey) {\n        return CheckedRow.get(context, this, objKey);\n    }\n\n    //\n    // Setters\n    //\n\n    public void setLong(long columnKey, long rowKey, long value, boolean isDefault) {\n        checkImmutable();\n        nativeSetLong(nativeTableRefPtr, columnKey, rowKey, value, isDefault);\n    }\n\n    // must not be called on a primary key field\n    public void incrementLong(long columnKey, long rowKey, long value) {\n        checkImmutable();\n        nativeIncrementLong(nativeTableRefPtr, columnKey, rowKey, value);\n    }\n\n    public void setBoolean(long columnKey, long rowKey, boolean value, boolean isDefault) {\n        checkImmutable();\n        nativeSetBoolean(nativeTableRefPtr, columnKey, rowKey, value, isDefault);\n    }\n\n    public void setFloat(long columnKey, long rowKey, float value, boolean isDefault) {\n        checkImmutable();\n        nativeSetFloat(nativeTableRefPtr, columnKey, rowKey, value, isDefault);\n    }\n\n    public void setDouble(long columnKey, long rowKey, double value, boolean isDefault) {\n        checkImmutable();\n        nativeSetDouble(nativeTableRefPtr, columnKey, rowKey, value, isDefault);\n    }\n\n    public void setDate(long columnKey, long rowKey, Date date, boolean isDefault) {\n        if (date == null) { throw new IllegalArgumentException(\"Null Date is not allowed.\"); }\n        checkImmutable();\n        nativeSetTimestamp(nativeTableRefPtr, columnKey, rowKey, date.getTime(), isDefault);\n    }\n\n    /**\n     * Sets a String value to a cell of Table, pointed by column and row key.\n     *\n     * @param columnKey cell column.\n     * @param rowKey cell row.\n     * @param value a String value to set in the cell.\n     */\n    public void setString(long columnKey, long rowKey, @Nullable String value, boolean isDefault) {\n        checkImmutable();\n        if (value == null) {\n            nativeSetNull(nativeTableRefPtr, columnKey, rowKey, isDefault);\n        } else {\n            nativeSetString(nativeTableRefPtr, columnKey, rowKey, value, isDefault);\n        }\n    }\n\n    public void setBinaryByteArray(long columnKey, long rowKey, byte[] data, boolean isDefault) {\n        checkImmutable();\n        nativeSetByteArray(nativeTableRefPtr, columnKey, rowKey, data, isDefault);\n    }\n\n    public void setDecimal128(long columnKey, long rowKey, @Nullable Decimal128 value, boolean isDefault) {\n        checkImmutable();\n        if (value == null) {\n            nativeSetNull(nativeTableRefPtr, columnKey, rowKey, isDefault);\n        } else {\n            nativeSetDecimal128(nativeTableRefPtr, columnKey, rowKey, value.getLow(), value.getHigh(), isDefault);\n        }\n    }\n\n    public void setObjectId(long columnKey, long rowKey, @Nullable ObjectId value, boolean isDefault) {\n        checkImmutable();\n        if (value == null) {\n            nativeSetNull(nativeTableRefPtr, columnKey, rowKey, isDefault);\n        } else {\n            nativeSetObjectId(nativeTableRefPtr, columnKey, rowKey, value.toString(), isDefault);\n        }\n    }\n\n    public void setUUID(long columnKey, long rowKey, @Nullable UUID value, boolean isDefault) {\n        checkImmutable();\n        if (value == null) {\n            nativeSetNull(nativeTableRefPtr, columnKey, rowKey, isDefault);\n        } else {\n            nativeSetUUID(nativeTableRefPtr, columnKey, rowKey, value.toString(), isDefault);\n        }\n    }\n\n    public void setRealmAny(long columnKey, long rowKey, long nativePtr, boolean isDefault) {\n        checkImmutable();\n        nativeSetRealmAny(nativeTableRefPtr, columnKey, rowKey, nativePtr, isDefault);\n    }\n\n    public void setLink(long columnKey, long rowKey, long value, boolean isDefault) {\n        checkImmutable();\n        nativeSetLink(nativeTableRefPtr, columnKey, rowKey, value, isDefault);\n    }\n\n    public void setNull(long columnKey, long rowKey, boolean isDefault) {\n        checkImmutable();\n        nativeSetNull(nativeTableRefPtr, columnKey, rowKey, isDefault);\n    }\n\n    public void addSearchIndex(long columnKey) {\n        checkImmutable();\n        nativeAddSearchIndex(nativeTableRefPtr, columnKey);\n    }\n\n    public void removeSearchIndex(long columnKey) {\n        checkImmutable();\n        nativeRemoveSearchIndex(nativeTableRefPtr, columnKey);\n    }\n\n    public boolean hasSearchIndex(long columnKey) {\n        return nativeHasSearchIndex(nativeTableRefPtr, columnKey);\n    }\n\n    public boolean isNullLink(long columnKey, long rowKey) {\n        return nativeIsNullLink(nativeTableRefPtr, columnKey, rowKey);\n    }\n\n    public void nullifyLink(long columnKey, long rowKey) {\n        nativeNullifyLink(nativeTableRefPtr, columnKey, rowKey);\n    }\n\n    boolean isImmutable() {\n        return sharedRealm != null && !sharedRealm.isInTransaction();\n    }\n\n    // This checking should be moved to OsSharedRealm level.\n    void checkImmutable() {\n        if (isImmutable()) {\n            throwImmutable();\n        }\n    }\n\n    //\n    // Count\n    //\n\n    public long count(long columnKey, long value) {\n        return nativeCountLong(nativeTableRefPtr, columnKey, value);\n    }\n\n    public long count(long columnKey, float value) {\n        return nativeCountFloat(nativeTableRefPtr, columnKey, value);\n    }\n\n    public long count(long columnKey, double value) {\n        return nativeCountDouble(nativeTableRefPtr, columnKey, value);\n    }\n\n    public long count(long columnKey, String value) {\n        return nativeCountString(nativeTableRefPtr, columnKey, value);\n    }\n\n    //\n    // Searching methods.\n    //\n\n    public TableQuery where() {\n        long nativeQueryPtr = nativeWhere(nativeTableRefPtr);\n        // Copies context reference from parent.\n        return new TableQuery(this.context, this, nativeQueryPtr);\n    }\n\n    public long findFirstLong(long columnKey, long value) {\n        return nativeFindFirstInt(nativeTableRefPtr, columnKey, value);\n    }\n\n    public long findFirstBoolean(long columnKey, boolean value) {\n        return nativeFindFirstBool(nativeTableRefPtr, columnKey, value);\n    }\n\n    public long findFirstFloat(long columnKey, float value) {\n        return nativeFindFirstFloat(nativeTableRefPtr, columnKey, value);\n    }\n\n    public long findFirstDouble(long columnKey, double value) {\n        return nativeFindFirstDouble(nativeTableRefPtr, columnKey, value);\n    }\n\n    public long findFirstDate(long columnKey, Date date) {\n        if (date == null) {\n            throw new IllegalArgumentException(\"null is not supported\");\n        }\n        return nativeFindFirstTimestamp(nativeTableRefPtr, columnKey, date.getTime());\n    }\n\n    public long findFirstString(long columnKey, String value) {\n        if (value == null) {\n            throw new IllegalArgumentException(\"null is not supported\");\n        }\n        return nativeFindFirstString(nativeTableRefPtr, columnKey, value);\n    }\n\n    public long findFirstDecimal128(long columnKey, Decimal128 value) {\n        if (value == null) {\n            throw new IllegalArgumentException(\"null is not supported\");\n        }\n        return nativeFindFirstDecimal128(nativeTableRefPtr, columnKey, value.getLow(), value.getHigh());\n    }\n\n    public long findFirstObjectId(long columnKey, ObjectId value) {\n        if (value == null) {\n            throw new IllegalArgumentException(\"null is not supported\");\n        }\n        return nativeFindFirstObjectId(nativeTableRefPtr, columnKey, value.toString());\n    }\n\n    public long findFirstUUID(long columnKey, UUID value) {\n        if (value == null) {\n            throw new IllegalArgumentException(\"null is not supported\");\n        }\n        return nativeFindFirstUUID(nativeTableRefPtr, columnKey, value.toString());\n    }\n\n    /**\n     * Searches for first occurrence of null. Beware that the order in the column is undefined.\n     *\n     * @param columnKey the column to search in.\n     * @return the row index for the first match found or {@link #NO_MATCH}.\n     */\n    public long findFirstNull(long columnKey) {\n        return nativeFindFirstNull(nativeTableRefPtr, columnKey);\n    }\n\n    //\n\n    /**\n     * Returns the table name as it is in the associated group.\n     *\n     * @return Name of the the table or {@code null} if it not part of a group.\n     */\n    @Nullable\n    public String getName() {\n        return nativeGetName(nativeTableRefPtr);\n    }\n\n    /**\n     * Returns the class name for the table.\n     *\n     * @return Name of the the table\n     * @throws IllegalStateException if the table has been deleted or no longer is part of the group.\n     */\n    public String getClassName() {\n        String name = getClassNameForTable(getName()); // Core returns \"\" if Table is no longer attached\n        if (Util.isEmptyString(name)) {\n            throw new IllegalStateException(\"This object class is no longer part of the schema for the Realm file. It is therefor not possible to access the schema name.\");\n        }\n        return name;\n    }\n\n    @Override\n    public String toString() {\n        long columnCount = getColumnCount();\n        String name = getName();\n        StringBuilder stringBuilder = new StringBuilder(\"The Table \");\n        if (name != null && !name.isEmpty()) {\n            stringBuilder.append(getName());\n            stringBuilder.append(\" \");\n        }\n        stringBuilder.append(\"contains \");\n        stringBuilder.append(columnCount);\n        stringBuilder.append(\" columns: \");\n\n        boolean isFirst = true;\n        for (String column : getColumnNames()) {\n            if (!isFirst) {\n                stringBuilder.append(\", \");\n            }\n            isFirst = false;\n            stringBuilder.append(column);\n        }\n        stringBuilder.append(\".\");\n\n        stringBuilder.append(\" And \");\n        stringBuilder.append(size());\n        stringBuilder.append(\" rows.\");\n\n        return stringBuilder.toString();\n    }\n\n    private static void throwImmutable() {\n        throw new IllegalStateException(\"Cannot modify managed objects outside of a write transaction.\");\n    }\n\n    /**\n     * Compares the schema of the current instance of Table with another instance.\n     *\n     * @param table the instance to compare with. It cannot be null.\n     * @return {@code true} if the two instances have the same schema (column names and types).\n     */\n    public boolean hasSameSchema(Table table) {\n        if (table == null) {\n            throw new IllegalArgumentException(\"The argument cannot be null\");\n        }\n        return nativeHasSameSchema(this.nativeTableRefPtr, table.nativeTableRefPtr);\n    }\n\n    /**\n     * Returns a frozen copy of this table.\n     */\n    public Table freeze(OsSharedRealm frozenRealm) {\n        if (!frozenRealm.isFrozen()) {\n            throw new IllegalArgumentException(\"Frozen Realm required\");\n        }\n        return new Table(frozenRealm, nativeFreeze(frozenRealm.getNativePtr(), nativeTableRefPtr));\n    }\n\n    public boolean isEmbedded() {\n        return nativeIsEmbedded(nativeTableRefPtr);\n    }\n\n    /**\n     * Returns true if the state was changed, false if not. If false was returned, it meant\n     * some invariant was broken when trying to change the state\n     */\n    public boolean setEmbedded(boolean embedded) {\n        return setEmbedded(embedded, false);\n    }\n\n    /**\n     * Returns true if the state was changed, false if not. If false was returned, it meant\n     * some invariant was broken when trying to change the state. The {@code handleBackLinks}\n     * parameter tells Core to automatically handle all unsatisfied invariants for backlinks, e.g.\n     * children becoming orphan or cloning objects with multiple references during migrations from\n     * a regular object to an embedded object.\n     */\n    public boolean setEmbedded(boolean embedded, boolean handleBackLinks) {\n        return nativeSetEmbedded(nativeTableRefPtr, embedded, handleBackLinks);\n    }\n\n    @Nullable\n    public static String getClassNameForTable(@Nullable String name) {\n        if (name == null) { return null; }\n        if (!name.startsWith(TABLE_PREFIX)) {\n            return name;\n        }\n        return name.substring(TABLE_PREFIX.length());\n    }\n\n    public static String getTableNameForClass(String name) {\n        //noinspection ConstantConditions\n        if (name == null) { return null; }\n        return TABLE_PREFIX + name;\n    }\n\n    private native boolean nativeIsValid(long nativeTableRefPtr);\n\n    private native long nativeAddColumn(long nativeTableRefPtr, int type, String name, boolean isNullable);\n\n    private native long nativeAddPrimitiveListColumn(long nativeTableRefPtr, int type, String name, boolean isNullable);\n\n    private native long nativeAddPrimitiveDictionaryColumn(long nativeTableRefPtr, int type, String name, boolean isNullable);\n\n    private native long nativeAddPrimitiveSetColumn(long nativeTableRefPtr, int type, String name, boolean isNullable);\n\n    private native long nativeAddColumnLink(long nativeTableRefPtr, int type, String name, long targetTablePtr);\n\n    private native long nativeAddColumnDictionaryLink(long nativeTableRefPtr, int type, String name, long targetTablePtr);\n\n    private native long nativeAddColumnSetLink(long nativeTableRefPtr, int type, String name, long targetTablePtr);\n\n    private native void nativeRenameColumn(long nativeTableRefPtr, long columnKey, String name);\n\n    private native void nativeRemoveColumn(long nativeTableRefPtr, long columnKey);\n\n    private native boolean nativeIsColumnNullable(long nativePtr, long columnKey);\n\n    private native void nativeConvertColumnToNullable(long nativeTableRefPtr, long columnKey, boolean isPrimaryKey);\n\n    private native void nativeConvertColumnToNotNullable(long nativePtr, long columnKey, boolean isPrimaryKey);\n\n    private native long nativeSize(long nativeTableRefPtr);\n\n    private native void nativeClear(long nativeTableRefPtr);\n\n    private native long nativeGetColumnCount(long nativeTableRefPtr);\n\n    private native String nativeGetColumnName(long nativeTableRefPtr, long columnKey);\n\n    private native String[] nativeGetColumnNames(long nativeTableRefPtr);\n\n    private native long nativeGetColumnKey(long nativeTableRefPtr, String columnName);\n\n    private native int nativeGetColumnType(long nativeTableRefPtr, long columnKey);\n\n    private native void nativeMoveLastOver(long nativeTableRefPtr, long rowKey);\n\n    private native long nativeGetLong(long nativeTableRefPtr, long columnKey, long rowKey);\n\n    private native boolean nativeGetBoolean(long nativeTableRefPtr, long columnKey, long rowKey);\n\n    private native float nativeGetFloat(long nativeTableRefPtr, long columnKey, long rowKey);\n\n    private native double nativeGetDouble(long nativeTableRefPtr, long columnKey, long rowKey);\n\n    private native long nativeGetTimestamp(long nativeTableRefPtr, long columnKey, long rowKey);\n\n    private native String nativeGetString(long nativePtr, long columnKey, long rowKey);\n\n    private native byte[] nativeGetByteArray(long nativePtr, long columnKey, long rowKey);\n\n    private native long nativeGetLink(long nativePtr, long columnKey, long rowKey);\n\n    private native long nativeGetLinkTarget(long nativePtr, long columnKey);\n\n    private native long[] nativeGetDecimal128(long nativePtr, long columnKey, long rowKey);\n\n    private native String nativeGetObjectId(long nativePtr, long columnKey, long rowKey);\n\n    private native boolean nativeIsNull(long nativePtr, long columnKey, long rowKey);\n\n    native long nativeGetRowPtr(long nativePtr, long objKey);\n\n    public static native void nativeSetLong(long nativeTableRefPtr, long columnKey, long rowKey, long value, boolean isDefault);\n\n    public static native void nativeIncrementLong(long nativeTableRefPtr, long columnKey, long rowKey, long value);\n\n    public static native void nativeSetBoolean(long nativeTableRefPtr, long columnKey, long rowKey, boolean value, boolean isDefault);\n\n    public static native void nativeSetFloat(long nativeTableRefPtr, long columnKey, long rowKey, float value, boolean isDefault);\n\n    public static native void nativeSetDouble(long nativeTableRefPtr, long columnKey, long rowKey, double value, boolean isDefault);\n\n    public static native void nativeSetTimestamp(long nativeTableRefPtr, long columnKey, long rowKey, long dateTimeValue, boolean isDefault);\n\n    public static native void nativeSetString(long nativeTableRefPtr, long columnKey, long rowKey, String value, boolean isDefault);\n\n    public static native void nativeSetNull(long nativeTableRefPtr, long columnKey, long rowKey, boolean isDefault);\n\n    public static native void nativeSetByteArray(long nativePtr, long columnKey, long rowKey, byte[] data, boolean isDefault);\n\n    public static native void nativeSetDecimal128(long nativeTableRefPtr, long columnKey, long rowKey, long low, long high, boolean isDefault);\n\n    public static native void nativeSetObjectId(long nativeTableRefPtr, long columnKey, long rowKey, String data, boolean isDefault);\n\n    public static native void nativeSetUUID(long nativeTableRefPtr, long columnKey, long rowKey, String data, boolean isDefault);\n\n    public static native void nativeSetLink(long nativeTableRefPtr, long columnKey, long rowKey, long value, boolean isDefault);\n\n    public static native void nativeSetRealmAny(long nativeTableRefPtr, long columnKey, long rowKey, long value, boolean isDefault);\n\n    private native void nativeAddSearchIndex(long nativePtr, long columnKey);\n\n    private native void nativeRemoveSearchIndex(long nativePtr, long columnKey);\n\n    private native boolean nativeHasSearchIndex(long nativePtr, long columnKey);\n\n    private native boolean nativeIsNullLink(long nativePtr, long columnKey, long rowKey);\n\n    public static native void nativeNullifyLink(long nativePtr, long columnKey, long rowKey);\n\n    private native long nativeCountLong(long nativePtr, long columnKey, long value);\n\n    private native long nativeCountFloat(long nativePtr, long columnKey, float value);\n\n    private native long nativeCountDouble(long nativePtr, long columnKey, double value);\n\n    private native long nativeCountString(long nativePtr, long columnKey, String value);\n\n    private native long nativeWhere(long nativeTableRefPtr);\n\n    public static native long nativeFindFirstInt(long nativeTableRefPtr, long columnKey, long value);\n\n    private native long nativeFindFirstBool(long nativePtr, long columnKey, boolean value);\n\n    private native long nativeFindFirstFloat(long nativePtr, long columnKey, float value);\n\n    private native long nativeFindFirstDouble(long nativePtr, long columnKey, double value);\n\n    private native long nativeFindFirstTimestamp(long nativeTableRefPtr, long columnKey, long dateTimeValue);\n\n    public static native long nativeFindFirstString(long nativeTableRefPtr, long columnKey, String value);\n\n    public static native long nativeFindFirstDecimal128(long nativeTableRefPtr, long columnKey, long low, long high);\n\n    public static native long nativeFindFirstObjectId(long nativeTableRefPtr, long columnKey, String value);\n\n    public static native long nativeFindFirstUUID(long nativeTableRefPtr, long columnKey, String value);\n\n    public static native long nativeFindFirstNull(long nativeTableRefPtr, long columnKey);\n\n    private native String nativeGetName(long nativeTableRefPtr);\n\n    private native boolean nativeHasSameSchema(long thisTable, long otherTable);\n\n    private static native long nativeGetFinalizerPtr();\n\n    private static native long nativeFreeze(long frozenSharedRealmPtr, long nativeTableRefPtr);\n\n    private static native boolean nativeIsEmbedded(long nativeTableRefPtr);\n\n    private static native boolean nativeSetEmbedded(long nativeTableRefPtr, boolean isEmbedded, boolean handleBackLinks);\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/internal/TableQuery.java",
    "content": "/*\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\npackage io.realm.internal;\n\nimport org.bson.types.Decimal128;\n\nimport java.util.Date;\n\nimport javax.annotation.Nullable;\n\nimport io.realm.RealmAny;\nimport io.realm.RealmAnyNativeFunctionsImpl;\nimport io.realm.Sort;\nimport io.realm.internal.core.NativeRealmAny;\nimport io.realm.internal.objectstore.OsKeyPathMapping;\nimport io.realm.log.RealmLog;\n\n\npublic class TableQuery implements NativeObject {\n    private static final boolean DEBUG = false;\n\n    private static final long nativeFinalizerPtr = nativeGetFinalizerPtr();\n\n    private final Table table;\n    private final long nativePtr;\n\n    private final RealmAnyNativeFunctionsImpl realmAnyNativeFunctions = new RealmAnyNativeFunctionsImpl();\n\n    private boolean queryValidated = true;\n\n    private static String escapeFieldName(@Nullable String fieldName) {\n        if (fieldName == null) { return null; }\n        return fieldName.replace(\" \", \"\\\\ \");\n    }\n\n    public TableQuery(NativeContext context,\n            Table table,\n            long nativeQueryPtr) {\n        if (DEBUG) {\n            RealmLog.debug(\"New TableQuery: ptr=%x\", nativeQueryPtr);\n        }\n        this.table = table;\n        this.nativePtr = nativeQueryPtr;\n\n        context.addReference(this);\n    }\n\n    @Override\n    public long getNativePtr() {\n        return nativePtr;\n    }\n\n    @Override\n    public long getNativeFinalizerPtr() {\n        return nativeFinalizerPtr;\n    }\n\n    public Table getTable() {\n        return table;\n    }\n\n    /**\n     * Checks in core if query syntax is valid. Throws exception, if not.\n     */\n    public void validateQuery() {\n        if (!queryValidated) {\n            String invalidMessage = nativeValidateQuery(nativePtr);\n            if (\"\".equals(invalidMessage)) {\n                queryValidated = true; // If empty string error message, query is valid\n            } else { throw new UnsupportedOperationException(invalidMessage); }\n        }\n    }\n\n    // Grouping\n\n    public TableQuery beginGroup() {\n        nativeBeginGroup(nativePtr);\n        queryValidated = false;\n        return this;\n    }\n\n    public TableQuery endGroup() {\n        nativeEndGroup(nativePtr);\n        queryValidated = false;\n        return this;\n    }\n\n    public TableQuery or() {\n        nativeOr(nativePtr);\n        queryValidated = false;\n        return this;\n    }\n\n    public TableQuery not() {\n        nativeNot(nativePtr);\n        queryValidated = false;\n        return this;\n    }\n\n    public static String buildSortDescriptor(String[] fieldNames, Sort[] sortOrders) {\n        StringBuilder descriptorBuilder = new StringBuilder(\"SORT(\");\n\n        String sortSeparator = \"\";\n        for (int i = 0; i < fieldNames.length; i++) {\n            String fieldName = fieldNames[i];\n\n            descriptorBuilder.append(sortSeparator)\n                    .append(escapeFieldName(fieldName))\n                    .append(\" \")\n                    .append((sortOrders[i] == Sort.ASCENDING) ? \"ASC\" : \"DESC\");\n\n            sortSeparator = \", \";\n        }\n\n        descriptorBuilder.append(\")\");\n\n        return descriptorBuilder.toString();\n    }\n\n    public TableQuery sort(@Nullable OsKeyPathMapping mapping, String[] fieldNames, Sort[] sortOrders) {\n        String descriptor = buildSortDescriptor(fieldNames, sortOrders);\n        rawDescriptor(mapping, descriptor);\n        return this;\n    }\n\n    public static String buildDistinctDescriptor(String[] fieldNames) {\n        StringBuilder descriptorBuilder = new StringBuilder(\"DISTINCT(\");\n\n        String distinctSeparator = \"\";\n        for (String fieldName : fieldNames) {\n            descriptorBuilder.append(distinctSeparator)\n                    .append(escapeFieldName(fieldName));\n\n            distinctSeparator = \", \";\n        }\n\n        descriptorBuilder.append(\")\");\n\n        return descriptorBuilder.toString();\n    }\n\n    public TableQuery distinct(@Nullable OsKeyPathMapping mapping, String[] fieldNames) {\n        String descriptor = buildDistinctDescriptor(fieldNames);\n        rawDescriptor(mapping, descriptor);\n        return this;\n    }\n\n    public TableQuery limit(long limit) {\n        rawDescriptor(null, \"LIMIT(\" + limit + \")\");\n        return this;\n    }\n\n    public TableQuery isEmpty(@Nullable OsKeyPathMapping mapping, String fieldName) {\n        rawPredicateWithPointers(mapping, escapeFieldName(fieldName) + \".@count = 0\");\n        queryValidated = false;\n        return this;\n    }\n\n    public TableQuery isNotEmpty(@Nullable OsKeyPathMapping mapping, String fieldName) {\n        rawPredicateWithPointers(mapping, escapeFieldName(fieldName) + \".@count != 0\");\n        queryValidated = false;\n        return this;\n    }\n\n    public TableQuery rawPredicate(@Nullable OsKeyPathMapping mapping, String predicate, RealmAny... args) {\n        realmAnyNativeFunctions.callRawPredicate(this, mapping, predicate, args);\n        return this;\n    }\n\n    public void rawPredicateWithPointers(@Nullable OsKeyPathMapping mapping, String predicate, long... values) {\n        nativeRawPredicate(nativePtr,\n                predicate,\n                values,\n                (mapping != null) ? mapping.getNativePtr() : 0);\n    }\n\n    private void rawDescriptor(@Nullable OsKeyPathMapping mapping, String descriptor) {\n        nativeRawDescriptor(nativePtr,\n                descriptor,\n                (mapping != null) ? mapping.getNativePtr() : 0);\n    }\n\n    public TableQuery equalTo(@Nullable OsKeyPathMapping mapping, String fieldName, RealmAny value) {\n        realmAnyNativeFunctions.callRawPredicate(this, mapping, escapeFieldName(fieldName) + \" = $0\", value);\n        queryValidated = false;\n        return this;\n    }\n\n    public TableQuery notEqualTo(@Nullable OsKeyPathMapping mapping, String fieldName, RealmAny value) {\n        realmAnyNativeFunctions.callRawPredicate(this, mapping, escapeFieldName(fieldName) + \" != $0\", value);\n        queryValidated = false;\n        return this;\n    }\n\n    public TableQuery equalToInsensitive(@Nullable OsKeyPathMapping mapping, String fieldName, RealmAny value) {\n        realmAnyNativeFunctions.callRawPredicate(this, mapping, escapeFieldName(fieldName) + \" =[c] $0\", value);\n        queryValidated = false;\n        return this;\n    }\n\n    public TableQuery notEqualToInsensitive(@Nullable OsKeyPathMapping mapping, String fieldName, RealmAny value) {\n        realmAnyNativeFunctions.callRawPredicate(this, mapping, escapeFieldName(fieldName) + \" !=[c] $0\", value);\n        queryValidated = false;\n        return this;\n    }\n\n    public TableQuery greaterThan(@Nullable OsKeyPathMapping mapping, String fieldName, RealmAny value) {\n        realmAnyNativeFunctions.callRawPredicate(this, mapping, escapeFieldName(fieldName) + \" > $0\", value);\n        queryValidated = false;\n        return this;\n    }\n\n    public TableQuery greaterThanOrEqual(@Nullable OsKeyPathMapping mapping, String fieldName, RealmAny value) {\n        realmAnyNativeFunctions.callRawPredicate(this, mapping, escapeFieldName(fieldName) + \" >= $0\", value);\n        queryValidated = false;\n        return this;\n    }\n\n    public TableQuery lessThan(@Nullable OsKeyPathMapping mapping, String fieldName, RealmAny value) {\n        realmAnyNativeFunctions.callRawPredicate(this, mapping, escapeFieldName(fieldName) + \" < $0\", value);\n        queryValidated = false;\n        return this;\n    }\n\n    public TableQuery lessThanOrEqual(@Nullable OsKeyPathMapping mapping, String fieldName, RealmAny value) {\n        realmAnyNativeFunctions.callRawPredicate(this, mapping, escapeFieldName(fieldName) + \" <= $0\", value);\n        queryValidated = false;\n        return this;\n    }\n\n    public TableQuery between(@Nullable OsKeyPathMapping mapping, String fieldName, RealmAny value1, RealmAny value2) {\n        realmAnyNativeFunctions.callRawPredicate(this, mapping, \"(\" + escapeFieldName(fieldName) + \" >= $0 AND \" + escapeFieldName(fieldName) + \" <= $1)\", value1, value2);\n        queryValidated = false;\n        return this;\n    }\n\n    public TableQuery beginsWith(@Nullable OsKeyPathMapping mapping, String fieldName, RealmAny value) {\n        realmAnyNativeFunctions.callRawPredicate(this, mapping, escapeFieldName(fieldName) + \" BEGINSWITH $0\", value);\n        queryValidated = false;\n        return this;\n    }\n\n    public TableQuery beginsWithInsensitive(@Nullable OsKeyPathMapping mapping, String fieldName, RealmAny value) {\n        realmAnyNativeFunctions.callRawPredicate(this, mapping, escapeFieldName(fieldName) + \" BEGINSWITH[c] $0\", value);\n        queryValidated = false;\n        return this;\n    }\n\n    public TableQuery endsWith(@Nullable OsKeyPathMapping mapping, String fieldName, RealmAny value) {\n        realmAnyNativeFunctions.callRawPredicate(this, mapping, escapeFieldName(fieldName) + \" ENDSWITH $0\", value);\n        queryValidated = false;\n        return this;\n    }\n\n    public TableQuery endsWithInsensitive(@Nullable OsKeyPathMapping mapping, String fieldName, RealmAny value) {\n        realmAnyNativeFunctions.callRawPredicate(this, mapping, escapeFieldName(fieldName) + \" ENDSWITH[c] $0\", value);\n        queryValidated = false;\n        return this;\n    }\n\n    public TableQuery like(@Nullable OsKeyPathMapping mapping, String fieldName, RealmAny value) {\n        realmAnyNativeFunctions.callRawPredicate(this, mapping, escapeFieldName(fieldName) + \" LIKE $0\", value);\n        queryValidated = false;\n        return this;\n    }\n\n    public TableQuery likeInsensitive(@Nullable OsKeyPathMapping mapping, String fieldName, RealmAny value) {\n        realmAnyNativeFunctions.callRawPredicate(this, mapping, escapeFieldName(fieldName) + \" LIKE[c] $0\", value);\n        queryValidated = false;\n        return this;\n    }\n\n    public TableQuery contains(@Nullable OsKeyPathMapping mapping, String fieldName, RealmAny value) {\n        realmAnyNativeFunctions.callRawPredicate(this, mapping, escapeFieldName(fieldName) + \" CONTAINS $0\", value);\n        queryValidated = false;\n        return this;\n    }\n\n    public TableQuery containsInsensitive(@Nullable OsKeyPathMapping mapping, String fieldName, RealmAny value) {\n        realmAnyNativeFunctions.callRawPredicate(this, mapping, escapeFieldName(fieldName) + \" CONTAINS[c] $0\", value);\n        queryValidated = false;\n        return this;\n    }\n\n    // Dictionary queries\n\n    public TableQuery containsKey(@Nullable OsKeyPathMapping mapping, String fieldName, RealmAny key) {\n        realmAnyNativeFunctions.callRawPredicate(this, mapping, \"ANY \" + escapeFieldName(fieldName) + \".@keys == $0\", key);\n        queryValidated = false;\n        return this;\n    }\n\n    public TableQuery containsValue(@Nullable OsKeyPathMapping mapping, String fieldName, RealmAny value) {\n        realmAnyNativeFunctions.callRawPredicate(this, mapping, \"ANY \" + escapeFieldName(fieldName) + \".@values == $0\", value);\n        queryValidated = false;\n        return this;\n    }\n\n    public TableQuery containsEntry(@Nullable OsKeyPathMapping mapping, String fieldName, RealmAny key, RealmAny value) {\n        realmAnyNativeFunctions.callRawPredicate(this, mapping, escapeFieldName(fieldName) + \"[$0] == $1\", key, value);\n        queryValidated = false;\n        return this;\n    }\n\n    // isNull and isNotNull\n    public TableQuery isNull(@Nullable OsKeyPathMapping mapping, String fieldName) {\n        rawPredicateWithPointers(mapping, escapeFieldName(fieldName) + \" = NULL\");\n        queryValidated = false;\n        return this;\n    }\n\n    public TableQuery isNotNull(@Nullable OsKeyPathMapping mapping, String fieldName) {\n        rawPredicateWithPointers(mapping, escapeFieldName(fieldName) + \" != NULL\");\n        queryValidated = false;\n        return this;\n    }\n\n    public TableQuery alwaysTrue() {\n        rawPredicateWithPointers(null, \"TRUEPREDICATE\");\n        queryValidated = false;\n        return this;\n    }\n\n    public TableQuery alwaysFalse() {\n        rawPredicateWithPointers(null, \"FALSEPREDICATE\");\n        queryValidated = false;\n        return this;\n    }\n\n    public TableQuery in(@Nullable OsKeyPathMapping mapping, String fieldName, RealmAny[] values) {\n        fieldName = escapeFieldName(fieldName);\n\n        beginGroup();\n\n        boolean first = true;\n        for (RealmAny value : values) {\n            if (!first) { or(); }\n            if (value == null) {\n                isNull(mapping, fieldName);\n            } else {\n                equalTo(mapping, fieldName, value);\n            }\n            first = false;\n        }\n        endGroup();\n\n        queryValidated = false;\n        return this;\n    }\n\n    public TableQuery inInsensitive(@Nullable OsKeyPathMapping mapping, String fieldName, RealmAny[] values) {\n        fieldName = escapeFieldName(fieldName);\n\n        beginGroup();\n\n        boolean first = true;\n        for (RealmAny value : values) {\n            if (!first) { or(); }\n            if (value == null) {\n                isNull(mapping, fieldName);\n            } else {\n                equalToInsensitive(mapping, fieldName, value);\n            }\n            first = false;\n        }\n        endGroup();\n\n        queryValidated = false;\n        return this;\n    }\n\n    // Searching methods.\n\n    /**\n     * Returns the table row index for the first element matching the query.\n     */\n    public long find() {\n        validateQuery();\n        return nativeFind(nativePtr);\n    }\n\n    //\n    // Aggregation methods\n    //\n\n    // Integer aggregation\n\n    public long sumInt(long columnKey) {\n        validateQuery();\n        return nativeSumInt(nativePtr, columnKey);\n    }\n\n    public Long maximumInt(long columnKey) {\n        validateQuery();\n        return nativeMaximumInt(nativePtr, columnKey);\n    }\n\n    public Long minimumInt(long columnKey) {\n        validateQuery();\n        return nativeMinimumInt(nativePtr, columnKey);\n    }\n\n    public double averageInt(long columnKey) {\n        validateQuery();\n        return nativeAverageInt(nativePtr, columnKey);\n    }\n\n    // Float aggregation\n\n    public double sumFloat(long columnKey) {\n        validateQuery();\n        return nativeSumFloat(nativePtr, columnKey);\n    }\n\n    public Float maximumFloat(long columnKey) {\n        validateQuery();\n        return nativeMaximumFloat(nativePtr, columnKey);\n    }\n\n    public Float minimumFloat(long columnKey) {\n        validateQuery();\n        return nativeMinimumFloat(nativePtr, columnKey);\n    }\n\n    public double averageFloat(long columnKey) {\n        validateQuery();\n        return nativeAverageFloat(nativePtr, columnKey);\n    }\n\n    // Double aggregation\n\n    public double sumDouble(long columnKey) {\n        validateQuery();\n        return nativeSumDouble(nativePtr, columnKey);\n    }\n\n    public Decimal128 sumDecimal128(long columnKey) {\n        validateQuery();\n        long[] data = nativeSumDecimal128(nativePtr, columnKey);\n        if (data != null) {\n            return Decimal128.fromIEEE754BIDEncoding(data[1]/*high*/, data[0]/*low*/);\n        } else {\n            return null;\n        }\n    }\n\n    public Double maximumDouble(long columnKey) {\n        validateQuery();\n        return nativeMaximumDouble(nativePtr, columnKey);\n    }\n\n    public Double minimumDouble(long columnKey) {\n        validateQuery();\n        return nativeMinimumDouble(nativePtr, columnKey);\n    }\n\n    public double averageDouble(long columnKey) {\n        validateQuery();\n        return nativeAverageDouble(nativePtr, columnKey);\n    }\n\n    // RealmAny aggregation\n    public Decimal128 sumRealmAny(long columnKey) {\n        validateQuery();\n        long[] data =  nativeSumRealmAny(nativePtr, columnKey);\n        return Decimal128.fromIEEE754BIDEncoding(data[1]/*high*/, data[0]/*low*/);\n    }\n\n    public NativeRealmAny maximumRealmAny(long columnKey) {\n        validateQuery();\n        return nativeMaximumRealmAny(nativePtr, columnKey);\n    }\n\n    public NativeRealmAny minimumRealmAny(long columnKey) {\n        validateQuery();\n        return nativeMinimumRealmAny(nativePtr, columnKey);\n    }\n\n    public Decimal128 averageRealmAny(long columnKey) {\n        validateQuery();\n        long[] data =  nativeAverageRealmAny(nativePtr, columnKey);\n        return Decimal128.fromIEEE754BIDEncoding(data[1]/*high*/, data[0]/*low*/);\n    }\n\n    public Decimal128 averageDecimal128(long columnKey) {\n        validateQuery();\n        long[] result = nativeAverageDecimal128(nativePtr, columnKey);\n        if (result != null) {\n            return Decimal128.fromIEEE754BIDEncoding(result[1]/*high*/, result[0]/*low*/);\n        } else {\n            // 'query.avg' now returns null if no rows exist in the table\n            return new Decimal128(0L);\n        }\n    }\n\n    public Decimal128 maximumDecimal128(long columnKey) {\n        validateQuery();\n        long[] result = nativeMaximumDecimal128(nativePtr, columnKey);\n        if (result != null) {\n            return Decimal128.fromIEEE754BIDEncoding(result[1]/*high*/, result[0]/*low*/);\n        }\n        return null;\n    }\n\n    // Date aggregation\n\n    public Date maximumDate(long columnKey) {\n        validateQuery();\n        Long result = nativeMaximumTimestamp(nativePtr, columnKey);\n        if (result != null) {\n            return new Date(result);\n        }\n        return null;\n    }\n\n    public Date minimumDate(long columnKey) {\n        validateQuery();\n        Long result = nativeMinimumTimestamp(nativePtr, columnKey);\n        if (result != null) {\n            return new Date(result);\n        }\n        return null;\n    }\n\n    public Decimal128 minimumDecimal128(long columnKey) {\n        validateQuery();\n        long[] result = nativeMinimumDecimal128(nativePtr, columnKey);\n        if (result != null) {\n            return Decimal128.fromIEEE754BIDEncoding(result[1]/*high*/, result[0]/*low*/);\n        }\n        return null;\n    }\n\n    // Count\n\n    /**\n     * Returns only the number of matching objects.\n     * This method is very fast compared to evaluating a query completely, but it does not\n     * goes around any logic implemented in Object Store and other parts of the API that works\n     * on query results. So the primary use case for this method is testing.\n     */\n    @Deprecated\n    public long count() {\n        validateQuery();\n        return nativeCount(nativePtr);\n    }\n\n    public long remove() {\n        validateQuery();\n        if (table.isImmutable()) { throwImmutable(); }\n        return nativeRemove(nativePtr);\n    }\n\n    private void throwImmutable() {\n        throw new IllegalStateException(\"Mutable method call during read transaction.\");\n    }\n\n    private native long nativeFind(long nativeQueryPtr);\n\n    private native long nativeSumInt(long nativeQueryPtr, long columnKey);\n\n    private native Long nativeMaximumInt(long nativeQueryPtr, long columnKey);\n\n    private native Long nativeMinimumInt(long nativeQueryPtr, long columnKey);\n\n    private native double nativeAverageInt(long nativeQueryPtr, long columnKey);\n\n    private native double nativeSumFloat(long nativeQueryPtr, long columnKey);\n\n    private native Float nativeMaximumFloat(long nativeQueryPtr, long columnKey);\n\n    private native Float nativeMinimumFloat(long nativeQueryPtr, long columnKey);\n\n    private native double nativeAverageFloat(long nativeQueryPtr, long columnKey);\n\n    private native long[] nativeSumRealmAny(long nativeQueryPtr, long columnKey);\n\n    private native double nativeSumDouble(long nativeQueryPtr, long columnKey);\n\n    private native long[] nativeSumDecimal128(long nativeQueryPtr, long columnKey);\n\n    private native Double nativeMaximumDouble(long nativeQueryPtr, long columnKey);\n\n    private native NativeRealmAny nativeMaximumRealmAny(long nativeQueryPtr, long columnKey);\n\n    private native long[] nativeMaximumDecimal128(long nativeQueryPtr, long columnKey);\n\n    private native NativeRealmAny nativeMinimumRealmAny(long nativeQueryPtr, long columnKey);\n\n    private native Double nativeMinimumDouble(long nativeQueryPtr, long columnKey);\n\n    private native long[] nativeMinimumDecimal128(long nativeQueryPtr, long columnKey);\n\n    private native long[] nativeAverageRealmAny(long nativeQueryPtr, long columnKey);\n\n    private native double nativeAverageDouble(long nativeQueryPtr, long columnKey);\n\n    private native long[] nativeAverageDecimal128(long nativeQueryPtr, long columnKey);\n\n    private native Long nativeMaximumTimestamp(long nativeQueryPtr, long columnKey);\n\n    private native Long nativeMinimumTimestamp(long nativeQueryPtr, long columnKey);\n\n    private native long nativeCount(long nativeQueryPtr);\n\n    private native long nativeRemove(long nativeQueryPtr);\n\n    private native void nativeRawPredicate(long nativeQueryPtr, String filter, long[] argsPtr, long mappingPtr);\n\n    private native void nativeRawDescriptor(long nativeQueryPtr, String descriptor, long mappingPtr);\n\n    private native void nativeBeginGroup(long nativeQueryPtr);\n\n    private native void nativeEndGroup(long nativeQueryPtr);\n\n    private native void nativeOr(long nativeQueryPtr);\n\n    private native void nativeNot(long nativeQueryPtr);\n\n    private native String nativeValidateQuery(long nativeQueryPtr);\n\n    private static native long nativeGetFinalizerPtr();\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/internal/TestUtil.java",
    "content": "/*\n * Copyright 2016 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\npackage io.realm.internal;\n\nclass TestUtil {\n\n    public static native long getMaxExceptionNumber();\n\n    public static native String getExpectedMessage(long exceptionKind);\n\n    public static native void testThrowExceptions(long exceptionKind);\n\n    /**\n     * Returns the Date representation of a Core timestamp\n     */\n    public static native long getDateFromTimestamp(long seconds, int nanoseconds);\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/internal/UncheckedRow.java",
    "content": "/*\n * Copyright 2015 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\npackage io.realm.internal;\n\nimport org.bson.types.Decimal128;\nimport org.bson.types.ObjectId;\n\nimport java.util.Date;\nimport java.util.UUID;\n\nimport javax.annotation.Nullable;\n\nimport io.realm.RealmFieldType;\nimport io.realm.internal.core.NativeRealmAny;\n\n\n/**\n * Wrapper around a Row in Realm Core.\n * <p>\n * IMPORTANT: All access to methods using this class are non-checking. Safety guarantees are given by the\n * annotation processor and Object Store's typed Realm schema validation which is called before the typed API can be\n * used.\n * <p>\n * For low-level access to Row data where error checking is required, use {@link CheckedRow}.\n */\npublic class UncheckedRow implements NativeObject, Row {\n    private static final long nativeFinalizerPtr = nativeGetFinalizerPtr();\n\n    protected final NativeContext context; // This is only kept because for now it's needed by the constructor of LinkView\n    protected final Table parent;\n    private final long nativePtr;\n\n    public UncheckedRow(NativeContext context, Table parent, long nativePtr) {\n        this.context = context;\n        this.parent = parent;\n        this.nativePtr = nativePtr;\n        context.addReference(this);\n    }\n\n    // This is called by the CheckedRow constructor. The caller should hold a reference to the\n    // source UncheckedRow since the native destruction is handled by the source UncheckedRow.\n    UncheckedRow(UncheckedRow row) {\n        this.context = row.context;\n        this.parent = row.parent;\n        this.nativePtr = row.nativePtr;\n        // The destruction is handled by the source UncheckedRow. No need to add to the ref pool.\n    }\n\n    @Override\n    public long getNativePtr() {\n        return nativePtr;\n    }\n\n    @Override\n    public long getNativeFinalizerPtr() {\n        return nativeFinalizerPtr;\n    }\n\n    /**\n     * Gets the row object associated with a row key in a Table.\n     *\n     * @param context the Realm context.\n     * @param table   the Table that holds the row.\n     * @param rowKey  Row key.\n     * @return an instance of Row for the table and row key specified.\n     */\n    static UncheckedRow getByRowKey(NativeContext context, Table table, long rowKey) {\n        long nativeRowPointer = table.nativeGetRowPtr(table.getNativePtr(), rowKey);\n        return new UncheckedRow(context, table, nativeRowPointer);\n    }\n\n    /**\n     * Gets the row object from a row pointer.\n     *\n     * @param context          the Realm context.\n     * @param table            the Table that holds the row.\n     * @param nativeRowPointer pointer of a row.\n     * @return an instance of Row for the table and row specified.\n     */\n    static UncheckedRow getByRowPointer(NativeContext context, Table table, long nativeRowPointer) {\n        return new UncheckedRow(context, table, nativeRowPointer);\n    }\n\n    @Override\n    public long getColumnCount() {\n        return nativeGetColumnCount(nativePtr);\n    }\n\n    @Override\n    public String[] getColumnNames() {\n        return nativeGetColumnNames(nativePtr);\n    }\n\n    @Override\n    public long getColumnKey(String columnName) {\n        //noinspection ConstantConditions\n        if (columnName == null) {\n            throw new IllegalArgumentException(\"Column name can not be null.\");\n        }\n        return nativeGetColumnKey(nativePtr, columnName);\n    }\n\n    @Override\n    public RealmFieldType getColumnType(long columnKey) {\n        return RealmFieldType.fromNativeValue(nativeGetColumnType(nativePtr, columnKey));\n    }\n\n    // Getters\n\n    @Override\n    public Table getTable() {\n        return parent;\n    }\n\n    @Override\n    public long getObjectKey() {\n        return nativeGetObjectKey(nativePtr);\n    }\n\n    @Override\n    public long getLong(long columnKey) {\n        return nativeGetLong(nativePtr, columnKey);\n    }\n\n    @Override\n    public boolean getBoolean(long columnKey) {\n        return nativeGetBoolean(nativePtr, columnKey);\n    }\n\n    @Override\n    public float getFloat(long columnKey) {\n        return nativeGetFloat(nativePtr, columnKey);\n    }\n\n    @Override\n    public double getDouble(long columnKey) {\n        return nativeGetDouble(nativePtr, columnKey);\n    }\n\n    @Override\n    public Date getDate(long columnKey) {\n        return new Date(nativeGetTimestamp(nativePtr, columnKey));\n    }\n\n    @Override\n    public String getString(long columnKey) {\n        return nativeGetString(nativePtr, columnKey);\n    }\n\n    @Override\n    public byte[] getBinaryByteArray(long columnKey) {\n        return nativeGetByteArray(nativePtr, columnKey);\n    }\n\n    @Override\n    public Decimal128 getDecimal128(long columnKey) {\n        long[] data = nativeGetDecimal128(nativePtr, columnKey);\n        if (data != null) {\n            return Decimal128.fromIEEE754BIDEncoding(data[1]/*high*/, data[0]/*low*/);\n        } else {\n            return null;\n        }\n    }\n\n    @Override\n    public ObjectId getObjectId(long columnKey) {\n        return new ObjectId(nativeGetObjectId(nativePtr, columnKey));\n    }\n\n    @Override\n    public UUID getUUID(long columnKey) {\n        return UUID.fromString(nativeGetUUID(nativePtr, columnKey));\n    }\n\n    @Override\n    public NativeRealmAny getNativeRealmAny(long columnKey) {\n        return new NativeRealmAny(nativeGetRealmAny(nativePtr, columnKey));\n    }\n\n    @Override\n    public long getLink(long columnKey) {\n        return nativeGetLink(nativePtr, columnKey);\n    }\n\n    @Override\n    public boolean isNullLink(long columnKey) {\n        return nativeIsNullLink(nativePtr, columnKey);\n    }\n\n    @Override\n    public OsList getModelList(long columnKey) {\n        return new OsList(this, columnKey);\n    }\n\n    @Override\n    public OsList getValueList(long columnKey, RealmFieldType fieldType) {\n        return new OsList(this, columnKey);\n    }\n\n    @Override\n    public OsMap getRealmAnyMap(long columnKey) {\n        return new OsMap(this, columnKey);\n    }\n\n    @Override\n    public OsMap getModelMap(long columnKey) {\n        return new OsMap(this, columnKey);\n    }\n\n    @Override\n    public OsMap getValueMap(long columnKey, RealmFieldType fieldType) {\n        return new OsMap(this, columnKey);\n    }\n\n    @Override\n    public OsSet getRealmAnySet(long columnKey) {\n        return new OsSet(this, columnKey);\n    }\n\n    @Override\n    public OsSet getModelSet(long columnKey) {\n        return new OsSet(this, columnKey);\n    }\n\n    @Override\n    public OsSet getValueSet(long columnKey, RealmFieldType fieldType) {\n        return new OsSet(this, columnKey);\n    }\n\n    // Setters\n\n    @Override\n    public void setLong(long columnKey, long value) {\n        parent.checkImmutable();\n        nativeSetLong(nativePtr, columnKey, value);\n    }\n\n    @Override\n    public void setBoolean(long columnKey, boolean value) {\n        parent.checkImmutable();\n        nativeSetBoolean(nativePtr, columnKey, value);\n    }\n\n    @Override\n    public void setFloat(long columnKey, float value) {\n        parent.checkImmutable();\n        nativeSetFloat(nativePtr, columnKey, value);\n    }\n\n    @Override\n    public void setDouble(long columnKey, double value) {\n        parent.checkImmutable();\n        nativeSetDouble(nativePtr, columnKey, value);\n    }\n\n    @Override\n    public void setDate(long columnKey, Date date) {\n        parent.checkImmutable();\n        //noinspection ConstantConditions\n        if (date == null) {\n            throw new IllegalArgumentException(\"Null Date is not allowed.\");\n        }\n        long timestamp = date.getTime();\n        nativeSetTimestamp(nativePtr, columnKey, timestamp);\n    }\n\n    @Override\n    public void setRealmAny(long columnKey, long realmAnyNativePtr) {\n        parent.checkImmutable();\n        nativeSetRealmAny(nativePtr, columnKey, realmAnyNativePtr);\n    }\n\n    /**\n     * Sets a string value to a row pointer.\n     *\n     * @param columnKey column key.\n     * @param value     the value to to a row\n     */\n    @Override\n    public void setString(long columnKey, @Nullable String value) {\n        parent.checkImmutable();\n        if (value == null) {\n            nativeSetNull(nativePtr, columnKey);\n        } else {\n            nativeSetString(nativePtr, columnKey, value);\n        }\n    }\n\n    @Override\n    public void setBinaryByteArray(long columnKey, @Nullable byte[] data) {\n        parent.checkImmutable();\n        nativeSetByteArray(nativePtr, columnKey, data);\n    }\n\n    @Override\n    public void setLink(long columnKey, long value) {\n        parent.checkImmutable();\n        nativeSetLink(nativePtr, columnKey, value);\n    }\n\n    @Override\n    public void nullifyLink(long columnKey) {\n        parent.checkImmutable();\n        nativeNullifyLink(nativePtr, columnKey);\n    }\n\n    @Override\n    public boolean isNull(long columnKey) {\n        return nativeIsNull(nativePtr, columnKey);\n    }\n\n    /**\n     * Sets null to a row pointer.\n     *\n     * @param columnKey column key.\n     */\n    @Override\n    public void setNull(long columnKey) {\n        parent.checkImmutable();\n        nativeSetNull(nativePtr, columnKey);\n    }\n\n    @Override\n    public void setDecimal128(long columnKey, @Nullable Decimal128 value) {\n        parent.checkImmutable();\n        if (value == null) {\n            nativeSetNull(nativePtr, columnKey);\n        } else {\n            nativeSetDecimal128(nativePtr, columnKey, value.getLow(), value.getHigh());\n        }\n    }\n\n    @Override\n    public void setObjectId(long columnKey, @Nullable ObjectId value) {\n        parent.checkImmutable();\n        if (value == null) {\n            nativeSetNull(nativePtr, columnKey);\n        } else {\n            nativeSetObjectId(nativePtr, columnKey, value.toString());\n        }\n    }\n\n    @Override\n    public void setUUID(long columnKey, @Nullable UUID value) {\n        parent.checkImmutable();\n        if (value == null) {\n            nativeSetNull(nativePtr, columnKey);\n        } else {\n            nativeSetUUID(nativePtr, columnKey, value.toString());\n        }\n    }\n\n    @Override\n    public long createEmbeddedObject(long columnKey, RealmFieldType parentPropertyType) {\n        switch (parentPropertyType) {\n            case OBJECT:\n                parent.checkImmutable();\n                return nativeCreateEmbeddedObject(nativePtr, columnKey);\n            case LIST:\n                return getModelList(columnKey).createAndAddEmbeddedObject();\n            default:\n                throw new IllegalArgumentException(\"Wrong parentPropertyType, expected OBJECT or LIST but received \" + parentPropertyType);\n        }\n    }\n\n    /**\n     * Converts the unchecked Row to a checked variant.\n     *\n     * @return the {@link CheckedRow} wrapping the same Realm data as the original {@link Row}.\n     */\n    public CheckedRow convertToChecked() {\n        return CheckedRow.getFromRow(this);\n    }\n\n    @Override\n    public boolean isValid() {\n        return nativePtr != 0 && nativeIsValid(nativePtr);\n    }\n\n    @Override\n    public void checkIfAttached() {\n        if (!isValid()) {\n            throw new IllegalStateException(\"Object is no longer managed by Realm. Has it been deleted?\");\n        }\n    }\n\n    @Override\n    public boolean hasColumn(String fieldName) {\n        return nativeHasColumn(nativePtr, fieldName);\n    }\n\n    @Override\n    public Row freeze(OsSharedRealm frozenRealm) {\n        if (!isValid()) {\n            return InvalidRow.INSTANCE;\n        }\n        return new UncheckedRow(context, parent.freeze(frozenRealm), nativeFreeze(nativePtr, frozenRealm.getNativePtr()));\n    }\n\n    @Override\n    public boolean isLoaded() {\n        return true;\n    }\n\n    protected native long nativeGetColumnCount(long nativeTablePtr);\n\n    protected native long nativeGetColumnKey(long nativeTablePtr, String columnName);\n\n    protected native String[] nativeGetColumnNames(long nativeTablePtr);\n\n    protected native int nativeGetColumnType(long nativeTablePtr, long columnKey);\n\n    protected native long nativeGetObjectKey(long nativeRowPtr);\n\n    protected native long nativeGetLong(long nativeRowPtr, long columnKey);\n\n    protected native boolean nativeGetBoolean(long nativeRowPtr, long columnKey);\n\n    protected native float nativeGetFloat(long nativeRowPtr, long columnKey);\n\n    protected native double nativeGetDouble(long nativeRowPtr, long columnKey);\n\n    protected native long nativeGetTimestamp(long nativeRowPtr, long columnKey);\n\n    protected native String nativeGetString(long nativePtr, long columnKey);\n\n    protected native boolean nativeIsNullLink(long nativeRowPtr, long columnKey);\n\n    protected native byte[] nativeGetByteArray(long nativePtr, long columnKey);\n\n    // Returns String representation for Decimal128()\n    protected native long[] nativeGetDecimal128(long nativePtr, long columnKey);\n\n    protected native String nativeGetObjectId(long nativePtr, long columnKey);\n\n    protected native String nativeGetUUID(long nativePtr, long columnKey);\n\n    protected native long nativeGetRealmAny(long nativePtr, long columnKey);\n\n    protected native void nativeSetLong(long nativeRowPtr, long columnKey, long value);\n\n    protected native void nativeSetBoolean(long nativeRowPtr, long columnKey, boolean value);\n\n    protected native void nativeSetFloat(long nativeRowPtr, long columnKey, float value);\n\n    protected native long nativeGetLink(long nativeRowPtr, long columnKey);\n\n    protected native void nativeSetDouble(long nativeRowPtr, long columnKey, double value);\n\n    protected native void nativeSetTimestamp(long nativeRowPtr, long columnKey, long dateTimeValue);\n\n    protected native void nativeSetString(long nativeRowPtr, long columnKey, String value);\n\n    protected native void nativeSetByteArray(long nativePtr, long columnKey, @Nullable byte[] data);\n\n    protected native void nativeSetDecimal128(long nativePtr, long columnKey, long low, long high);\n\n    protected native void nativeSetObjectId(long nativePtr, long columnKey, String value);\n\n    protected native void nativeSetUUID(long nativePtr, long columnKey, String value);\n\n    protected native void nativeSetRealmAny(long nativeRowPtr, long columnKey, long nativePtr);\n\n    protected native void nativeSetLink(long nativeRowPtr, long columnKey, long value);\n\n    protected native void nativeNullifyLink(long nativeRowPtr, long columnKey);\n\n    protected native boolean nativeIsValid(long nativeRowPtr);\n\n    protected native boolean nativeHasColumn(long nativeRowPtr, String columnName);\n\n    protected native boolean nativeIsNull(long nativeRowPtr, long columnKey);\n\n    protected native void nativeSetNull(long nativeRowPtr, long columnKey);\n\n    protected native long nativeFreeze(long nativeRowPtr, long frozenRealmNativePtr);\n\n    protected native long nativeCreateEmbeddedObject(long nativeRowPtr, long columnKey);\n\n    private static native long nativeGetFinalizerPtr();\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/internal/UnmanagedSubscription.java",
    "content": "/*\n * Copyright 2022 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 */\npackage io.realm.internal;\n\nimport java.util.Date;\n\nimport javax.annotation.Nullable;\n\nimport io.realm.RealmQuery;\nimport io.realm.internal.annotations.ObjectServer;\nimport io.realm.mongodb.sync.Subscription;\n\n/**\n * Class that handles unmanaged subscriptions. Required as we need to track a realm query ptr.\n */\n@ObjectServer\npublic class UnmanagedSubscription implements Subscription {\n\n    private final Date createdAt;\n    private final Date updatedAt;\n    @Nullable\n    private final String name;\n    private final String objectType;\n    private final String queryDesc;\n    private final long queryPtr;\n\n    public UnmanagedSubscription(@Nullable String name, RealmQuery query) {\n        this.createdAt = null;\n        this.updatedAt = null;\n        this.name = name;\n        this.objectType = query.getTypeQueried();\n        this.queryDesc = query.getDescription();\n        this.queryPtr = query.getQueryPointer();\n    }\n\n    @Override\n    public Date getCreatedAt() {\n        return null;\n    }\n\n    @Override\n    public Date getUpdatedAt() {\n        return null;\n    }\n\n    @Override\n    public String getName() {\n        return name;\n    }\n\n    @Override\n    public String getObjectType() {\n        return objectType;\n    }\n\n    @Override\n    public String getQuery() {\n        return queryDesc;\n    }\n\n    public long getQueryPointer() {\n        return queryPtr;\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/internal/Util.java",
    "content": "/*\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\npackage io.realm.internal;\n\nimport android.os.Build;\n\nimport java.io.File;\nimport java.io.PrintWriter;\nimport java.io.StringWriter;\nimport java.util.Collections;\nimport java.util.LinkedHashSet;\nimport java.util.Locale;\nimport java.util.Map;\nimport java.util.Set;\n\nimport javax.annotation.Nullable;\n\nimport io.realm.RealmConfiguration;\nimport io.realm.RealmModel;\nimport io.realm.RealmObject;\nimport io.realm.internal.android.AndroidCapabilities;\nimport io.realm.log.RealmLog;\n\n\npublic class Util {\n\n    private static Boolean rxJavaAvailable;\n    private static Boolean coroutinesAvailable;\n\n    public static String getTablePrefix() {\n        return nativeGetTablePrefix();\n    }\n\n    static native String nativeGetTablePrefix();\n\n    /**\n     * Normalizes a input class to it's original RealmObject class so it is transparent whether or not the input class\n     * was a RealmProxy class.\n     */\n    public static Class<? extends RealmModel> getOriginalModelClass(Class<? extends RealmModel> clazz) {\n\n        // The compiler would allow these classes to be passed as arguments, but they are never\n        // valid as a Realm model class\n        if (clazz.equals(RealmModel.class) || clazz.equals(RealmObject.class)) {\n            throw new IllegalArgumentException(\"RealmModel or RealmObject was passed as an argument. \" +\n                    \"Only subclasses of these can be used as arguments to methods that accept a Realm model class.\");\n        }\n\n        // This cast is correct because 'clazz' is either the type\n        // generated by RealmProxy or the original type extending directly from RealmObject.\n        @SuppressWarnings(\"unchecked\")\n        Class<? extends RealmModel> superclass = (Class<? extends RealmModel>) clazz.getSuperclass();\n\n        if (!superclass.equals(Object.class) && !superclass.equals(RealmObject.class)) {\n            clazz = superclass;\n        }\n\n        return clazz;\n    }\n\n    //-----------------------------------------------------------------------\n\n    /**\n     * <p>Gets the stack trace from a Throwable as a String.</p>\n     * <p>\n     * <p>The result of this method vary by JDK version as this method\n     * uses {@link Throwable#printStackTrace(java.io.PrintWriter)}.\n     * On JDK1.3 and earlier, the cause exception will not be shown\n     * unless the specified throwable alters printStackTrace.</p>\n     *\n     * @param throwable the <code>Throwable</code> to be examined\n     * @return the stack trace as generated by the exception's\n     * <code>printStackTrace(PrintWriter)</code> method\n     * <p>\n     * Credit: https://commons.apache.org/proper/commons-lang/apidocs/src-html/org/apache/commons/lang3/exception/ExceptionUtils.html\n     */\n    public static String getStackTrace(final Throwable throwable) {\n        final StringWriter sw = new StringWriter();\n        final PrintWriter pw = new PrintWriter(sw, true);\n        throwable.printStackTrace(pw);\n        return sw.getBuffer().toString();\n    }\n\n    // Credit: http://stackoverflow.com/questions/2799097/how-can-i-detect-when-an-android-application-is-running-in-the-emulator\n    public static boolean isEmulator() {\n        return Build.FINGERPRINT.startsWith(\"generic\")\n                || Build.FINGERPRINT.startsWith(\"unknown\")\n                || Build.MODEL.contains(\"google_sdk\")\n                || Build.MODEL.contains(\"Emulator\")\n                || Build.MODEL.contains(\"Android SDK built for x86\")\n                || Build.MANUFACTURER.contains(\"Genymotion\")\n                || (Build.BRAND.startsWith(\"generic\") && Build.DEVICE.startsWith(\"generic\"))\n                || \"google_sdk\".equals(Build.PRODUCT);\n    }\n\n    public static boolean isEmptyString(@Nullable String str) {\n        return str == null || str.length() == 0;\n    }\n\n    /**\n     * To delete Realm and related temporary files. This must be called in\n     * {@link OsObjectStore#callWithLock(RealmConfiguration, Runnable)}'s callback.\n     *\n     * @return {@code true} if the realm file is deleted. Temporary file deletion failure will not impact the return\n     * value, instead, a warning will be logged.\n     */\n    public static boolean deleteRealm(String canonicalPath, File realmFolder, String realmFileName) {\n        final String management = \".management\";\n        File managementFolder = new File(realmFolder, realmFileName + management);\n        File realmFile = new File(canonicalPath);\n        // This file is not always stored here, but if it is we want to delete it.\n        // If it isn't found it is placed in a temporary folder, so no reason to delete it.\n        File fifoFile = new File(canonicalPath + \".note\");\n\n        // Deletes files in management directory and the directory.\n        // There is no subfolders in the management directory.\n        File[] files = managementFolder.listFiles();\n        if (files != null) {\n            for (File file : files) {\n                boolean deleteResult = file.delete();\n                if (!deleteResult) {\n                    RealmLog.warn( String.format(Locale.ENGLISH,\"Realm temporary file at %s cannot be deleted\",\n                            file.getAbsolutePath()));\n                }\n            }\n        }\n        if (managementFolder.exists() && !managementFolder.delete()) {\n            RealmLog.warn( String.format(Locale.ENGLISH,\"Realm temporary folder at %s cannot be deleted\",\n                    managementFolder.getAbsolutePath()));\n        }\n\n        boolean realmDeleted;\n        if (realmFile.exists()) {\n            realmDeleted = realmFile.delete();\n            if (!realmDeleted) {\n                RealmLog.warn(String.format(Locale.ENGLISH,\"Realm file at %s cannot be deleted\",\n                        realmFile.getAbsolutePath()));\n            }\n        } else {\n            realmDeleted = true;\n        }\n\n        if (fifoFile.exists() && !fifoFile.delete()) {\n            RealmLog.warn(String.format(Locale.ENGLISH,\".note file at %s cannot be deleted\",\n                        fifoFile.getAbsolutePath()));\n        }\n\n        return realmDeleted;\n    }\n\n    /**\n     * Converts a var arg argument list to a set ignoring any duplicates and null values.\n     */\n    public static <T> Set<T> toSet(T... items) {\n        //noinspection ConstantConditions\n        if (items == null) {\n            return Collections.emptySet();\n        } else {\n            Set<T> set = new LinkedHashSet<>();\n            for (int i = 0; i < items.length; i++) {\n                T item = items[i];\n                if (item != null) {\n                    set.add(item);\n                }\n            }\n            return set;\n        }\n    }\n\n    public static void checkEmpty(String argValue, String argName) {\n        if (isEmptyString(argValue)) {\n            throw new IllegalArgumentException(\"Non-empty '\" + argName + \"' required.\");\n        }\n    }\n\n    public static void checkNull(@Nullable Object argValue, String argName) {\n        if (argValue == null) {\n            throw new IllegalArgumentException(\"Nonnull '\" + argName + \"' required.\");\n        }\n    }\n\n    public static void checkLooperThread(String errorMessage) {\n        AndroidCapabilities capabilities = new AndroidCapabilities();\n        capabilities.checkCanDeliverNotification(errorMessage);\n    }\n\n    public static void checkNotOnMainThread(String errorMessage) {\n        if (new AndroidCapabilities().isMainThread()) {\n            throw new IllegalStateException(errorMessage);\n        }\n    }\n\n    /**\n     * Checks if RxJava is present and can be loaded.\n     *\n     * @return {@code true} if RxJava dependency exists, {@code false} otherwise.\n     */\n    @SuppressWarnings(\"LiteralClassName\")\n    public static synchronized boolean isRxJavaAvailable() {\n        if (rxJavaAvailable == null) {\n            try {\n                Class.forName(\"io.reactivex.Flowable\");\n                rxJavaAvailable = true;\n            } catch (ClassNotFoundException ignore) {\n                rxJavaAvailable = false;\n            }\n        }\n        return rxJavaAvailable;\n    }\n\n    /**\n     * Checks if the coroutines framework is present and can be loaded.\n     *\n     * @return {@code true} if the coroutines dependency exists, {@code false} otherwise.\n     */\n    public static synchronized boolean isCoroutinesAvailable() {\n        if (coroutinesAvailable == null) {\n            try {\n                Class.forName(\"kotlinx.coroutines.flow.Flow\");\n                coroutinesAvailable = true;\n            } catch (ClassNotFoundException ignore) {\n                coroutinesAvailable = false;\n            }\n        }\n        return coroutinesAvailable;\n    }\n\n    /**\n     * Validates that a key is present in a given map\n     *\n     * @param key the key to expect.\n     * @param map the map to search.\n     * @param argName the map argument name\n     * @throws IllegalArgumentException if key is not present.\n     */\n    public static void checkContainsKey(final String key, final Map<String, ?> map, final String argName) {\n        if (!map.containsKey(key)) {\n            throw new IllegalArgumentException(\"Key '\" + key + \"' required in '\"+ argName +\"'.\");\n        }\n    }\n\n    /**\n     * Returns a {@link Class} object from a string.\n     *\n     * @param className the class name\n     * @return the {@code Class} object matching the string.\n     * @throws IllegalArgumentException if the class does not exist.\n     */\n    public static Class<?> getClassForName(String className) {\n        try {\n            return Class.forName(className);\n        } catch (ClassNotFoundException e) {\n            throw new IllegalArgumentException(\"Class '\" + className + \"' does not exist.\");\n        }\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/internal/android/AndroidCapabilities.java",
    "content": "/*\n * Copyright 2016 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 */\npackage io.realm.internal.android;\n\nimport android.os.Looper;\n\nimport edu.umd.cs.findbugs.annotations.SuppressFBWarnings;\nimport javax.annotation.Nullable;\n\nimport io.realm.internal.Capabilities;\n\n\n/**\n * Realm capabilities for Android.\n */\npublic class AndroidCapabilities implements Capabilities {\n\n    // Public so it can be set from tests.\n    // If set, it will treat the current looper thread as the main thread.\n    // It is up to the caller to handle any race conditions around this. Right now only\n    // RunInLooperThread.java does this as part of setting up the test.\n    @SuppressFBWarnings({\"MS_SHOULD_BE_FINAL\", \"MS_CANNOT_BE_FINAL\"})\n    public static boolean EMULATE_MAIN_THREAD = false;\n\n    private final Looper looper;\n    private final boolean isIntentServiceThread;\n\n    public AndroidCapabilities() {\n        looper = Looper.myLooper();\n        isIntentServiceThread = isIntentServiceThread();\n    }\n\n    @Override\n    public boolean canDeliverNotification() {\n        return hasLooper() && !isIntentServiceThread;\n    }\n\n    @Override\n    public void checkCanDeliverNotification(@Nullable String exceptionMessage) {\n        if (!hasLooper()) {\n            throw new IllegalStateException(exceptionMessage == null ? \"\" : (exceptionMessage + \" \") +\n                    \"Realm cannot be automatically updated on a thread without a looper.\");\n        }\n        if (isIntentServiceThread) {\n            throw new IllegalStateException(exceptionMessage == null ? \"\" : (exceptionMessage + \" \") +\n                    \"Realm cannot be automatically updated on an IntentService thread.\");\n        }\n    }\n\n    @Override\n    public boolean isMainThread() {\n        return looper != null && (EMULATE_MAIN_THREAD || looper == Looper.getMainLooper());\n    }\n\n    private boolean hasLooper() {\n        return looper != null;\n    }\n\n    private static boolean isIntentServiceThread() {\n        // Tries to determine if a thread is an IntentService thread. No public API can detect this,\n        // so use the thread name as a heuristic:\n        // https://android.googlesource.com/platform/frameworks/base/+/master/core/java/android/app/IntentService.java#108\n        String threadName = Thread.currentThread().getName();\n        return threadName != null && threadName.startsWith(\"IntentService[\");\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/internal/android/AndroidRealmNotifier.java",
    "content": "package io.realm.internal.android;\n\nimport android.os.Handler;\nimport android.os.Looper;\n\nimport javax.annotation.Nullable;\n\nimport io.realm.internal.Capabilities;\nimport io.realm.internal.Keep;\nimport io.realm.internal.RealmNotifier;\nimport io.realm.internal.OsSharedRealm;\n\n\n/**\n * {@link RealmNotifier} implementation for Android.\n */\n@Keep\npublic class AndroidRealmNotifier extends RealmNotifier {\n    private Handler handler;\n\n    public AndroidRealmNotifier(@Nullable OsSharedRealm sharedRealm, Capabilities capabilities) {\n        super(sharedRealm);\n        if (capabilities.canDeliverNotification()) {\n            handler = new Handler(Looper.myLooper());\n        } else {\n            handler = null;\n        }\n    }\n\n    @Override\n    public boolean post(Runnable runnable) {\n        return handler != null && handler.post(runnable);\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/internal/android/ISO8601Utils.java",
    "content": "/*\n * Copyright 2015 FasterXML\n * Copyright 2015 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 */\npackage io.realm.internal.android;\n\nimport java.text.ParseException;\nimport java.text.ParsePosition;\nimport java.util.Calendar;\nimport java.util.Date;\nimport java.util.GregorianCalendar;\nimport java.util.TimeZone;\n\n\n/**\n * Utilities methods for manipulating dates in iso8601 format. This is much much faster and GC friendly than using SimpleDateFormat so\n * highly suitable if you (un)serialize lots of date objects.\n * <p>\n * Supported parse format: [yyyy-MM-dd|yyyyMMdd][T(hh:mm[:ss[.sss]]|hhmm[ss[.sss]])]?[Z|[+-]hh[:]mm]]\n *\n * @see <a href=\"http://www.w3.org/TR/NOTE-datetime\">this specification</a>\n * @see <a href=\"https://github.com/FasterXML/jackson-databind/blob/master/src/main/java/com/fasterxml/jackson/databind/util/ISO8601Utils.java\">Original Source</a>\n */\npublic class ISO8601Utils {\n\n    /**\n     * ID to represent the 'UTC' string, default timezone since Jackson 2.7\n     *\n     * @since 2.7\n     */\n    private static final String UTC_ID = \"UTC\";\n\n    /**\n     * The UTC timezone, prefetched to avoid more lookups.\n     *\n     * @since 2.7\n     */\n    private static final TimeZone TIMEZONE_UTC = TimeZone.getTimeZone(UTC_ID);\n\n    /**\n     * Timezone we use for 'Z' in ISO-8601 date/time values: since 2.7\n     * {@link #TIMEZONE_UTC};\n     */\n    private static final TimeZone TIMEZONE_Z = TIMEZONE_UTC;\n\n    /**\n     * Parses a date from ISO-8601 formatted string. It expects a format\n     * [yyyy-MM-dd|yyyyMMdd][T(hh:mm[:ss[.sss]]|hhmm[ss[.sss]])]?[Z|[+-]hh:mm]]\n     *\n     * @param date ISO string to parse in the appropriate format.\n     * @param pos The position to start parsing from, updated to where parsing stopped.\n     * @return the parsed date\n     * @throws ParseException if the date is not in the appropriate format\n     */\n    public static Date parse(String date, ParsePosition pos) throws ParseException {\n        Exception fail;\n        //noinspection TryWithIdenticalCatches\n        try {\n            int offset = pos.getIndex();\n\n            // Extracts year.\n            int year = parseInt(date, offset, offset += 4);\n            if (checkOffset(date, offset, '-')) {\n                offset += 1;\n            }\n\n            // Extracts month.\n            int month = parseInt(date, offset, offset += 2);\n            if (checkOffset(date, offset, '-')) {\n                offset += 1;\n            }\n\n            // Extracts day.\n            int day = parseInt(date, offset, offset += 2);\n            // Default time value.\n            int hour = 0;\n            int minutes = 0;\n            int seconds = 0;\n            int milliseconds = 0; // Always use 0 otherwise returned date will include millis of current time.\n\n            // If the value has no time component (and no time zone), we are done.\n            boolean hasT = checkOffset(date, offset, 'T');\n\n            if (!hasT && (date.length() <= offset)) {\n                Calendar calendar = new GregorianCalendar(year, month - 1, day);\n\n                pos.setIndex(offset);\n                return calendar.getTime();\n            }\n\n            if (hasT) {\n\n                // Extracts hours, minutes, seconds and milliseconds.\n                hour = parseInt(date, offset += 1, offset += 2);\n                if (checkOffset(date, offset, ':')) {\n                    offset += 1;\n                }\n\n                minutes = parseInt(date, offset, offset += 2);\n                if (checkOffset(date, offset, ':')) {\n                    offset += 1;\n                }\n                // Second and milliseconds can be optional.\n                if (date.length() > offset) {\n                    char c = date.charAt(offset);\n                    if (c != 'Z' && c != '+' && c != '-') {\n                        seconds = parseInt(date, offset, offset += 2);\n                        if (seconds > 59 && seconds < 63) {\n                            seconds = 59; // Truncates up to 3 leap seconds.\n                        }\n                        // Milliseconds can be optional in the format.\n                        if (checkOffset(date, offset, '.')) {\n                            offset += 1;\n                            int endOffset = indexOfNonDigit(date, offset + 1); // Assumes at least one digit.\n                            int parseEndOffset = Math.min(endOffset, offset + 3); // Parses up to 3 digits.\n                            int fraction = parseInt(date, offset, parseEndOffset);\n                            // Compensates for \"missing\" digits.\n                            switch (parseEndOffset - offset) { // Number of digits parsed.\n                                case 2:\n                                    milliseconds = fraction * 10;\n                                    break;\n                                case 1:\n                                    milliseconds = fraction * 100;\n                                    break;\n                                default:\n                                    milliseconds = fraction;\n                            }\n                            offset = endOffset;\n                        }\n                    }\n                }\n            }\n\n            // Extracts timezone.\n            if (date.length() <= offset) {\n                throw new IllegalArgumentException(\"No time zone indicator\");\n            }\n\n            TimeZone timezone;\n            char timezoneIndicator = date.charAt(offset);\n\n            if (timezoneIndicator == 'Z') {\n                timezone = TIMEZONE_Z;\n                offset += 1;\n            } else if (timezoneIndicator == '+' || timezoneIndicator == '-') {\n                String timezoneOffset = date.substring(offset);\n                offset += timezoneOffset.length();\n                // Convert 2-digit time zone designator to 4-digit designator\n                if (timezoneOffset.length() == 3) {\n                    timezoneOffset += \"00\";\n                }\n                // 18-Jun-2015, tatu: Minor simplification, skip offset of \"+0000\"/\"+00:00\"\n                if (\"+0000\".equals(timezoneOffset) || \"+00:00\".equals(timezoneOffset)) {\n                    timezone = TIMEZONE_Z;\n                } else {\n                    // 18-Jun-2015, tatu: Looks like offsets only work from GMT, not UTC...\n                    //    not sure why, but that's the way it looks. Further, Javadocs for\n                    //    `java.util.TimeZone` specifically instruct use of GMT as base for\n                    //    custom timezones... odd.\n                    String timezoneId = \"GMT\" + timezoneOffset;\n\n                    timezone = TimeZone.getTimeZone(timezoneId);\n\n                    String act = timezone.getID();\n                    if (!act.equals(timezoneId)) {\n                        /* 22-Jan-2015, tatu: Looks like canonical version has colons, but we may be given\n                         *    one without. If so, don't sweat.\n                         *   Yes, very inefficient. Hopefully not hit often.\n                         *   If it becomes a perf problem, add 'loose' comparison instead.\n                         */\n                        String cleaned = act.replace(\":\", \"\");\n                        if (!cleaned.equals(timezoneId)) {\n                            throw new IndexOutOfBoundsException(\"Mismatching time zone indicator: \" + timezoneId + \" given, resolves to \"\n                                    + timezone.getID());\n                        }\n                    }\n                }\n            } else {\n                throw new IndexOutOfBoundsException(\"Invalid time zone indicator '\" + timezoneIndicator + \"'\");\n            }\n\n            Calendar calendar = new GregorianCalendar(timezone);\n            calendar.setLenient(false);\n            calendar.set(Calendar.YEAR, year);\n            calendar.set(Calendar.MONTH, month - 1);\n            calendar.set(Calendar.DAY_OF_MONTH, day);\n            calendar.set(Calendar.HOUR_OF_DAY, hour);\n            calendar.set(Calendar.MINUTE, minutes);\n            calendar.set(Calendar.SECOND, seconds);\n            calendar.set(Calendar.MILLISECOND, milliseconds);\n\n            pos.setIndex(offset);\n            return calendar.getTime();\n            // If we get a ParseException it'll already have the right message/offset.\n            // Other exception types can convert here.\n        } catch (IndexOutOfBoundsException e) {\n            fail = e;\n        } catch (NumberFormatException e) {\n            fail = e;\n        } catch (IllegalArgumentException e) {\n            fail = e;\n        }\n        String input = (date == null) ? null : ('\"' + date + \"'\");\n        String msg = fail.getMessage();\n        if (msg == null || msg.isEmpty()) {\n            msg = \"(\" + fail.getClass().getName() + \")\";\n        }\n        ParseException ex = new ParseException(\"Failed to parse date [\" + input + \"]: \" + msg, pos.getIndex());\n        ex.initCause(fail);\n        throw ex;\n    }\n\n\n    /**\n     * Checks if the expected character exist at the given offset in the value.\n     *\n     * @param value the string to check at the specified offset\n     * @param offset the offset to look for the expected character\n     * @param expected the expected character\n     * @return true if the expected character exist at the given offset\n     */\n    private static boolean checkOffset(String value, int offset, char expected) {\n        return (offset < value.length()) && (value.charAt(offset) == expected);\n    }\n\n    /**\n     * Parses an integer located between 2 given offsets in a string\n     *\n     * @param value the string to parse\n     * @param beginIndex the start index for the integer in the string\n     * @param endIndex the end index for the integer in the string\n     * @return the int\n     * @throws NumberFormatException if the value is not a number\n     */\n    private static int parseInt(String value, int beginIndex, int endIndex) throws NumberFormatException {\n        if (beginIndex < 0 || endIndex > value.length() || beginIndex > endIndex) {\n            throw new NumberFormatException(value);\n        }\n        // use same logic as in Integer.parseInt() but less generic we're not supporting negative values\n        int i = beginIndex;\n        int result = 0;\n        int digit;\n        if (i < endIndex) {\n            digit = Character.digit(value.charAt(i++), 10);\n            if (digit < 0) {\n                throw new NumberFormatException(\"Invalid number: \" + value.substring(beginIndex, endIndex));\n            }\n            result = -digit;\n        }\n        while (i < endIndex) {\n            digit = Character.digit(value.charAt(i++), 10);\n            if (digit < 0) {\n                throw new NumberFormatException(\"Invalid number: \" + value.substring(beginIndex, endIndex));\n            }\n            result *= 10;\n            result -= digit;\n        }\n        return -result;\n    }\n\n    /**\n     * Returns the index of the first character in the string that is not a digit, starting at offset.\n     */\n    private static int indexOfNonDigit(String string, int offset) {\n        for (int i = offset; i < string.length(); i++) {\n            char c = string.charAt(i);\n            if (c < '0' || c > '9') { return i; }\n        }\n        return string.length();\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/internal/android/JsonUtils.java",
    "content": "/*\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\npackage io.realm.internal.android;\n\nimport android.util.Base64;\n\nimport java.text.ParseException;\nimport java.text.ParsePosition;\nimport java.util.Date;\nimport java.util.regex.Matcher;\nimport java.util.regex.Pattern;\n\nimport javax.annotation.Nullable;\n\nimport io.realm.exceptions.RealmException;\n\n\npublic class JsonUtils {\n\n    private static Pattern jsonDate = Pattern.compile(\"/Date\\\\((\\\\d*)(?:[+-]\\\\d*)?\\\\)/\");\n    private static Pattern numericOnly = Pattern.compile(\"-?\\\\d+\");\n    private static ParsePosition parsePosition = new ParsePosition(0);\n\n    /**\n     * Converts a Json string to a Java Date object. Currently supports 2 types:\n     * - \"<long>\"\n     * - \"/Date(<long>[+-Zone])/\"\n     *\n     * @param date the String input of date of the the supported types.\n     * @return the Date object or {@code null} if invalid input.\n     * @throws NumberFormatException if date is not a proper long or has an illegal format.\n     */\n    @Nullable\n    public static Date stringToDate(String date) {\n        if (date == null || date.length() == 0) { return null; }\n\n        // Checks for JSON date.\n        Matcher matcher = jsonDate.matcher(date);\n        if (matcher.find()) {\n            String dateMatch = matcher.group(1);\n            return new Date(Long.parseLong(dateMatch));\n        }\n\n        // Checks for millisecond based date.\n        if (numericOnly.matcher(date).matches()) {\n            try {\n                return new Date(Long.parseLong(date));\n            } catch (NumberFormatException e) {\n                throw new RealmException(e.getMessage(), e);\n            }\n        }\n\n        // Tries for ISO8601 date.\n        try {\n            parsePosition.setIndex(0); // Resets the position each time.\n            return ISO8601Utils.parse(date, parsePosition);\n        } catch (ParseException e) {\n            throw new RealmException(e.getMessage(), e);\n        }\n    }\n\n    /**\n     * Converts a Json string to byte[]. String must be Base64 encoded.\n     *\n     * @param str the base 64 encoded bytes.\n     * @return the Byte array or empty byte array.\n     */\n    public static byte[] stringToBytes(String str) {\n        if (str == null || str.length() == 0) { return new byte[0]; }\n        return Base64.decode(str, Base64.DEFAULT);\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/internal/android/TypeUtils.java",
    "content": "/*\n * Copyright 2020 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\npackage io.realm.internal.android;\n\npublic class TypeUtils {\n    public static byte[] convertNonPrimitiveBinaryToPrimitive(Byte[] bytes) {\n        byte[] transfer = new byte[bytes.length];\n        for (int i = 0; i < bytes.length; i++) {\n            if (bytes[i] == null) {\n                throw new IllegalArgumentException(\"Byte arrays cannot contain null values.\");\n            }\n            transfer[i] = bytes[i];\n        }\n        return transfer;\n    }\n\n    public static Byte[] convertPrimitiveBinaryToNonPrimitive(byte[] bytes) {\n        Byte[] transfer = new Byte[bytes.length];\n        for (int i = 0; i < bytes.length; i++) {\n            transfer[i] = bytes[i];\n        }\n        return transfer;\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/internal/android/package-info.java",
    "content": "/*\n * Copyright 2017 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@javax.annotation.ParametersAreNonnullByDefault\npackage io.realm.internal.android;\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/internal/annotations/ObjectServer.java",
    "content": "/*\n * Copyright 2018 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\npackage io.realm.internal.annotations;\n\nimport java.lang.annotation.ElementType;\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.RetentionPolicy;\nimport java.lang.annotation.Target;\n\n/**\n * This annotation is used to mark the classes as being specific to the Realm Object Server.\n * They will be stripped in the Base variant.\n */\n@Retention(RetentionPolicy.CLASS)\n@Target({ElementType.TYPE, ElementType.METHOD})\npublic @interface ObjectServer {\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/internal/async/BadVersionException.java",
    "content": "/*\n * Copyright 2015 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\npackage io.realm.internal.async;\n\nimport io.realm.internal.Keep;\n\n\n/**\n * Triggered from JNI level when the result of a query (from a different thread) could not be used against the current\n * state of the Realm which might be more up-to-date than the provided results or vice versa.\n */\n@Keep\npublic class BadVersionException extends Exception {\n\n    public BadVersionException(String detailMessage) {\n        super(detailMessage);\n    }\n\n    public BadVersionException(String detailMessage, Throwable exception) {\n        super(detailMessage, exception);\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/internal/async/BgPriorityCallable.java",
    "content": "/*\n * Copyright 2015 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\npackage io.realm.internal.async;\n\nimport java.util.concurrent.Callable;\n\n\n/**\n * Decorator to set the thread priority according to\n * <a href=\"https://developer.android.com/training/multiple-threads/define-runnable.html\"> Androids recommendation</a>.\n */\npublic class BgPriorityCallable<T> implements Callable<T> {\n    private final Callable<T> callable;\n\n    BgPriorityCallable(Callable<T> callable) {\n        this.callable = callable;\n    }\n\n    @Override\n    public T call() throws Exception {\n        // Moves the current Thread into the background\n        android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_BACKGROUND);\n        return callable.call();\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/internal/async/BgPriorityRunnable.java",
    "content": "/*\n * Copyright 2015 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\npackage io.realm.internal.async;\n\n/**\n * Decorator to set the thread priority according to\n * <a href=\"https://developer.android.com/training/multiple-threads/define-runnable.html\"> Androids recommendation</a>.\n */\npublic class BgPriorityRunnable implements Runnable {\n    private final Runnable runnable;\n\n    BgPriorityRunnable(Runnable runnable) {\n        this.runnable = runnable;\n    }\n\n    @Override\n    public void run() {\n        // Moves the current Thread into the background\n        android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_BACKGROUND);\n        runnable.run();\n    }\n\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/internal/async/RealmAsyncTaskImpl.java",
    "content": "/*\n * Copyright 2016 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\npackage io.realm.internal.async;\n\nimport java.util.concurrent.Future;\nimport java.util.concurrent.ThreadPoolExecutor;\n\nimport io.realm.RealmAsyncTask;\n\n\npublic final class RealmAsyncTaskImpl implements RealmAsyncTask {\n    private final Future<?> pendingTask;\n    private final ThreadPoolExecutor service;\n    private volatile boolean isCancelled = false;\n\n    public RealmAsyncTaskImpl(Future<?> pendingTask, ThreadPoolExecutor service) {\n        this.pendingTask = pendingTask;\n        this.service = service;\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    @Override\n    public void cancel() {\n        pendingTask.cancel(true);\n        isCancelled = true;\n\n        // From \"Java Threads\": By Scott Oaks & Henry Wong\n        // cancelled tasks are never executed, but may\n        // accumulate in work queues, which may causes a memory leak\n        // if the task hold references (to an enclosing class for example)\n        // we can use purge() but one caveat applies: if a second thread attempts to add\n        // something to the pool (using the execute() method) at the same time the\n        // first thread is attempting to purge the queue the attempt to purge\n        // the queue fails and the cancelled object remain in the queue.\n        // A better way to cancel objects with thread pools is to use the remove()\n        service.getQueue().remove(pendingTask);\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    @Override\n    public boolean isCancelled() {\n        return isCancelled;\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/internal/async/RealmThreadPoolExecutor.java",
    "content": "/*\n * Copyright 2015 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\npackage io.realm.internal.async;\n\nimport java.io.File;\nimport java.io.FileFilter;\nimport java.util.concurrent.ArrayBlockingQueue;\nimport java.util.concurrent.Future;\nimport java.util.concurrent.ThreadPoolExecutor;\nimport java.util.concurrent.TimeUnit;\nimport java.util.concurrent.locks.Condition;\nimport java.util.concurrent.locks.ReentrantLock;\nimport java.util.regex.Pattern;\n\nimport edu.umd.cs.findbugs.annotations.SuppressFBWarnings;\n\n\n/**\n * Custom thread pool settings, instances of this executor can be paused, and resumed, this will also set\n * appropriate number of Threads & wrap submitted tasks to set the thread priority according to\n * <a href=\"https://developer.android.com/training/multiple-threads/define-runnable.html\"> Androids recommendation</a>.\n */\npublic class RealmThreadPoolExecutor extends ThreadPoolExecutor {\n    private static final String SYS_CPU_DIR = \"/sys/devices/system/cpu/\";\n\n    // Reduces context switching by using a number of thread proportionate to the number of cores.\n    private static final int CORE_POOL_SIZE = calculateCorePoolSize();\n    private static final int QUEUE_SIZE = 100;\n\n    private boolean isPaused;\n    private ReentrantLock pauseLock = new ReentrantLock();\n    private Condition unpaused = pauseLock.newCondition();\n\n    /**\n     * Creates a default RealmThreadPool that is bounded by the number of available cores.\n     */\n    public static RealmThreadPoolExecutor newDefaultExecutor() {\n        return new RealmThreadPoolExecutor(CORE_POOL_SIZE, CORE_POOL_SIZE);\n    }\n\n    /**\n     * Creates a RealmThreadPool with only 1 thread. This is primarily useful for testing.\n     */\n    public static RealmThreadPoolExecutor newSingleThreadExecutor() {\n        return new RealmThreadPoolExecutor(1, 1);\n    }\n\n    /**\n     * Tries using the number of files named 'cpuNN' in sysfs to figure out the number of\n     * processors on this device. `Runtime.getRuntime().availableProcessors()` may return\n     * a smaller number when the device is sleeping.\n     *\n     * @return the number of threads to be allocated for the executor pool\n     */\n    @SuppressFBWarnings(\"DMI_HARDCODED_ABSOLUTE_FILENAME\")\n    private static int calculateCorePoolSize() {\n        int cpus = countFilesInDir(SYS_CPU_DIR, \"cpu[0-9]+\");\n        if (cpus <= 0) {\n            cpus = Runtime.getRuntime().availableProcessors();\n        }\n        return (cpus <= 0) ? 1 : (cpus * 2) + 1;\n    }\n\n    /**\n     * @param dirPath a directory path\n     * @param pattern a regex\n     * @return the number of files, in the `dirPath` directory, whose names match `pattern`\n     */\n    private static int countFilesInDir(String dirPath, String pattern) {\n        final Pattern filePattern = Pattern.compile(pattern);\n        try {\n            File[] files = new File(dirPath).listFiles(new FileFilter() {\n                @Override\n                public boolean accept(File file) {\n                    return filePattern.matcher(file.getName()).matches();\n                }\n            });\n            return (files == null) ? 0 : files.length;\n        } catch (SecurityException ignore) {\n        }\n        return 0;\n    }\n\n    private RealmThreadPoolExecutor(int corePoolSize, int maxPoolSize) {\n        super(corePoolSize, maxPoolSize,\n                0L, TimeUnit.MILLISECONDS, //terminated idle thread\n                new ArrayBlockingQueue<Runnable>(QUEUE_SIZE));\n    }\n\n    /**\n     * Submits a runnable for executing a transaction.\n     *\n     * @param task the task to submit\n     * @return a future representing pending completion of the task\n     */\n    public Future<?> submitTransaction(Runnable task) {\n        Future<?> future = super.submit(new BgPriorityRunnable(task));\n        return future;\n    }\n\n    /**\n     * Method invoked prior to executing the given Runnable to pause execution of the thread.\n     *\n     * @param t the thread that will run task r\n     * @param r the task that will be executed\n     */\n    @Override\n    protected void beforeExecute(Thread t, Runnable r) {\n        super.beforeExecute(t, r);\n        pauseLock.lock();\n        try {\n            while (isPaused) { unpaused.await(); }\n        } catch (InterruptedException ie) {\n            t.interrupt();\n        } finally {\n            pauseLock.unlock();\n        }\n    }\n\n    /**\n     * Pauses the executor. Pausing means the executor will stop starting new tasks (but complete current ones).\n     */\n    public void pause() {\n        pauseLock.lock();\n        try {\n            isPaused = true;\n        } finally {\n            pauseLock.unlock();\n        }\n    }\n\n    /**\n     * Resumes executing any scheduled tasks.\n     */\n    public void resume() {\n        pauseLock.lock();\n        try {\n            isPaused = false;\n            unpaused.signalAll();\n        } finally {\n            pauseLock.unlock();\n        }\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/internal/coroutines/InternalFlowFactory.kt",
    "content": "/*\n * Copyright 2020 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\npackage io.realm.internal.coroutines\n\nimport io.realm.*\nimport io.realm.annotations.Beta\nimport io.realm.coroutines.FlowFactory\nimport io.realm.rx.CollectionChange\nimport io.realm.rx.ObjectChange\nimport kotlinx.coroutines.channels.awaitClose\nimport kotlinx.coroutines.flow.Flow\nimport kotlinx.coroutines.flow.callbackFlow\nimport kotlinx.coroutines.flow.flowOf\nimport kotlinx.coroutines.isActive\n\n/**\n * Internal factory implementation used to conceal Kotlin implementation details from the public\n * API and to avoid having to use Kotlin's documentation solution for just one class.\n */\nclass InternalFlowFactory(\n        private val returnFrozenObjects: Boolean = true\n) : FlowFactory {\n\n    @Beta\n    override fun from(realm: Realm): Flow<Realm> {\n        if (realm.isFrozen) {\n            return flowOf(realm)\n        }\n\n        return callbackFlow {\n            val flowRealm = Realm.getInstance(realm.configuration)\n            val listener = RealmChangeListener<Realm> { listenerRealm ->\n                if (isActive) {\n                    if (returnFrozenObjects) {\n                        trySend(realm.freeze())\n                    } else {\n                        trySend(listenerRealm)\n                    }\n                }\n            }\n\n            flowRealm.addChangeListener(listener)\n\n            if (returnFrozenObjects) {\n                trySend(flowRealm.freeze())\n            } else {\n                trySend(flowRealm)\n            }\n\n            awaitClose {\n                flowRealm.removeChangeListener(listener)\n                flowRealm.close()\n            }\n        }\n    }\n\n    @Beta\n    override fun from(dynamicRealm: DynamicRealm): Flow<DynamicRealm> {\n        if (dynamicRealm.isFrozen) {\n            return flowOf(dynamicRealm)\n        }\n\n        return callbackFlow {\n            val flowRealm = DynamicRealm.getInstance(dynamicRealm.configuration)\n            val listener = RealmChangeListener<DynamicRealm> { listenerRealm ->\n                if (isActive) {\n                    if (returnFrozenObjects) {\n                        trySend(dynamicRealm.freeze())\n                    } else {\n                        trySend(listenerRealm)\n                    }\n                }\n            }\n\n            flowRealm.addChangeListener(listener)\n\n            if (returnFrozenObjects) {\n                trySend(flowRealm.freeze())\n            } else {\n                trySend(flowRealm)\n            }\n\n            awaitClose {\n                flowRealm.removeChangeListener(listener)\n                flowRealm.close()\n            }\n        }\n    }\n\n    @Beta\n    override fun <T> from(realm: Realm, results: RealmResults<T>): Flow<RealmResults<T>> {\n        // Return \"as is\" if frozen, there will be no listening for changes\n        if (realm.isFrozen) {\n            return flowOf(results)\n        }\n\n        val config = realm.configuration\n\n        return callbackFlow {\n            // Do nothing if the results are invalid\n            if (!results.isValid) {\n                awaitClose {}\n\n                return@callbackFlow\n            }\n\n            // Get instance to ensure the Realm is open for as long as we are listening\n            val flowRealm = Realm.getInstance(config)\n            val listener = RealmChangeListener<RealmResults<T>> { listenerResults ->\n                if (isActive) {\n                    if (returnFrozenObjects) {\n                        trySend(listenerResults.freeze())\n                    } else {\n                        trySend(listenerResults)\n                    }\n                }\n            }\n\n            results.addChangeListener(listener)\n\n            // Emit current value\n            if (returnFrozenObjects) {\n                trySend(results.freeze())\n            } else {\n                trySend(results)\n            }\n\n            awaitClose {\n                // Remove listener and cleanup\n                if (!flowRealm.isClosed) {\n                    results.removeChangeListener(listener)\n                    flowRealm.close()\n                }\n            }\n        }\n    }\n\n    override fun <T> changesetFrom(\n            realm: Realm,\n            results: RealmResults<T>\n    ): Flow<CollectionChange<RealmResults<T>>> {\n        // Return \"as is\" if frozen, there will be no listening for changes\n        if (realm.isFrozen) {\n            return flowOf(CollectionChange(results, null))\n        }\n\n        val config = realm.configuration\n\n        return callbackFlow {\n            // Do nothing if the results are invalid\n            if (!results.isValid) {\n                awaitClose {}\n\n                return@callbackFlow\n            }\n\n            // Get instance to ensure the Realm is open for as long as we are listening\n            val flowRealm = Realm.getInstance(config)\n            val listener = OrderedRealmCollectionChangeListener<RealmResults<T>> { listenerResults, changeSet ->\n                if (isActive) {\n                    if (returnFrozenObjects) {\n                        trySend(CollectionChange(listenerResults.freeze(), changeSet))\n                    } else {\n                        trySend(CollectionChange(listenerResults, changeSet))\n                    }\n                }\n            }\n\n            results.addChangeListener(listener)\n\n            // Emit current value\n            if (returnFrozenObjects) {\n                trySend(CollectionChange(results.freeze(), null))\n            } else {\n                trySend(CollectionChange(results, null))\n            }\n\n            awaitClose {\n                // Remove listener and cleanup\n                if (!flowRealm.isClosed) {\n                    results.removeChangeListener(listener)\n                    flowRealm.close()\n                }\n            }\n        }\n    }\n\n    override fun <T> from(\n            dynamicRealm: DynamicRealm,\n            results: RealmResults<T>\n    ): Flow<RealmResults<T>> {\n        // Return \"as is\" if frozen, there will be no listening for changes\n        if (dynamicRealm.isFrozen) {\n            return flowOf(results)\n        }\n\n        val config = dynamicRealm.configuration\n\n        return callbackFlow {\n            // Do nothing if the results are invalid\n            if (!results.isValid) {\n                awaitClose {}\n\n                return@callbackFlow\n            }\n\n            // Get instance to ensure the Realm is open for as long as we are listening\n            val flowRealm = DynamicRealm.getInstance(config)\n            val listener = RealmChangeListener<RealmResults<T>> { listenerResults ->\n                if (isActive) {\n                    if (returnFrozenObjects) {\n                        trySend(listenerResults.freeze())\n                    } else {\n                        trySend(listenerResults)\n                    }\n                }\n            }\n\n            results.addChangeListener(listener)\n\n            // Emit current value\n            if (returnFrozenObjects) {\n                trySend(results.freeze())\n            } else {\n                trySend(results)\n            }\n\n            awaitClose {\n                // Remove listener and cleanup\n                if (!flowRealm.isClosed) {\n                    results.removeChangeListener(listener)\n                    flowRealm.close()\n                }\n            }\n        }\n    }\n\n    override fun <T> changesetFrom(\n            dynamicRealm: DynamicRealm,\n            results: RealmResults<T>\n    ): Flow<CollectionChange<RealmResults<T>>> {\n        // Return \"as is\" if frozen, there will be no listening for changes\n        if (dynamicRealm.isFrozen) {\n            return flowOf(CollectionChange(results, null))\n        }\n\n        val config = dynamicRealm.configuration\n\n        return callbackFlow {\n            // Do nothing if the results are invalid\n            if (!results.isValid) {\n                awaitClose {}\n\n                return@callbackFlow\n            }\n\n            // Get instance to ensure the Realm is open for as long as we are listening\n            val flowRealm = DynamicRealm.getInstance(config)\n            val listener = OrderedRealmCollectionChangeListener<RealmResults<T>> { listenerResults, changeSet ->\n                if (isActive) {\n                    if (returnFrozenObjects) {\n                        trySend(CollectionChange(listenerResults.freeze(), changeSet))\n                    } else {\n                        trySend(CollectionChange(listenerResults, changeSet))\n                    }\n                }\n            }\n\n            results.addChangeListener(listener)\n\n            // Emit current value\n            if (returnFrozenObjects) {\n                trySend(CollectionChange(results.freeze(), null))\n            } else {\n                trySend(CollectionChange(results, null))\n            }\n\n            awaitClose {\n                // Remove listener and cleanup\n                if (!flowRealm.isClosed) {\n                    results.removeChangeListener(listener)\n                    flowRealm.close()\n                }\n            }\n        }\n    }\n\n    @Beta\n    override fun <T> from(realm: Realm, realmList: RealmList<T>): Flow<RealmList<T>> {\n        // Return \"as is\" if frozen, there will be no listening for changes\n        if (realm.isFrozen) {\n            return flowOf(realmList)\n        }\n\n        val config = realm.configuration\n\n        return callbackFlow {\n            // Do nothing if the results are invalid\n            if (!realmList.isValid) {\n                awaitClose {}\n\n                return@callbackFlow\n            }\n\n            // Get instance to ensure the Realm is open for as long as we are listening\n            val flowRealm = Realm.getInstance(config)\n            val listener = RealmChangeListener<RealmList<T>> { listenerResults ->\n                if (isActive) {\n                    if (!listenerResults.isValid) {\n                        close()\n                    } else if (returnFrozenObjects) {\n                        trySend(listenerResults.freeze())\n                    } else {\n                        trySend(listenerResults)\n                    }\n                }\n            }\n\n            realmList.addChangeListener(listener)\n\n            // Emit current value\n            if (returnFrozenObjects) {\n                trySend(realmList.freeze())\n            } else {\n                trySend(realmList)\n            }\n\n            awaitClose {\n                // Remove listener and cleanup\n                if (!flowRealm.isClosed) {\n                    realmList.removeChangeListener(listener)\n                    flowRealm.close()\n                }\n            }\n        }\n    }\n\n    override fun <T : Any?> changesetFrom(\n            realm: Realm,\n            list: RealmList<T>\n    ): Flow<CollectionChange<RealmList<T>>> {\n        // Return \"as is\" if frozen, there will be no listening for changes\n        if (realm.isFrozen) {\n            return flowOf(CollectionChange(list, null))\n        }\n\n        val config = realm.configuration\n\n        return callbackFlow {\n            // Do nothing if the results are invalid\n            if (!list.isValid) {\n                awaitClose {}\n\n                return@callbackFlow\n            }\n\n            // Get instance to ensure the Realm is open for as long as we are listening\n            val flowRealm = Realm.getInstance(config)\n            val listener = OrderedRealmCollectionChangeListener<RealmList<T>> { listenerList, changeSet ->\n                if (isActive) {\n                    if (!listenerList.isValid) {\n                        close()\n                    } else if (returnFrozenObjects) {\n                        trySend(CollectionChange(listenerList.freeze(), changeSet))\n                    } else {\n                        trySend(CollectionChange(listenerList, changeSet))\n                    }\n                }\n            }\n\n            list.addChangeListener(listener)\n\n            // Emit current value\n            if (returnFrozenObjects) {\n                trySend(CollectionChange(list.freeze(), null))\n            } else {\n                trySend(CollectionChange(list, null))\n            }\n\n            awaitClose {\n                // Remove listener and cleanup\n                if (!flowRealm.isClosed) {\n                    list.removeChangeListener(listener)\n                    flowRealm.close()\n                }\n            }\n        }\n    }\n\n    override fun <T> from(dynamicRealm: DynamicRealm, realmList: RealmList<T>): Flow<RealmList<T>> {\n        // Return \"as is\" if frozen, there will be no listening for changes\n        if (dynamicRealm.isFrozen) {\n            return flowOf(realmList)\n        }\n\n        val config = dynamicRealm.configuration\n\n        return callbackFlow {\n            // Do nothing if the results are invalid\n            if (!realmList.isValid) {\n                awaitClose {}\n\n                return@callbackFlow\n            }\n\n            // Get instance to ensure the Realm is open for as long as we are listening\n            val flowRealm = DynamicRealm.getInstance(config)\n            val listener = RealmChangeListener<RealmList<T>> { listenerResults ->\n                if (isActive) {\n                    if (!listenerResults.isValid) {\n                        close()\n                    } else if (returnFrozenObjects) {\n                        trySend(listenerResults.freeze())\n                    } else {\n                        trySend(listenerResults)\n                    }\n                }\n            }\n\n            realmList.addChangeListener(listener)\n\n            // Emit current value\n            if (returnFrozenObjects) {\n                trySend(realmList.freeze())\n            } else {\n                trySend(realmList)\n            }\n\n            awaitClose {\n                // Remove listener and cleanup\n                if (!flowRealm.isClosed) {\n                    realmList.removeChangeListener(listener)\n                    flowRealm.close()\n                }\n            }\n        }\n    }\n\n    override fun <T> changesetFrom(\n            dynamicRealm: DynamicRealm,\n            list: RealmList<T>\n    ): Flow<CollectionChange<RealmList<T>>> {\n        // Return \"as is\" if frozen, there will be no listening for changes\n        if (dynamicRealm.isFrozen) {\n            return flowOf(CollectionChange(list, null))\n        }\n\n        val config = dynamicRealm.configuration\n\n        return callbackFlow {\n            // Do nothing if the results are invalid\n            if (!list.isValid) {\n                awaitClose {}\n\n                return@callbackFlow\n            }\n\n            // Get instance to ensure the Realm is open for as long as we are listening\n            val flowRealm = DynamicRealm.getInstance(config)\n            val listener = OrderedRealmCollectionChangeListener<RealmList<T>> { listenerList, changeSet ->\n                if (isActive) {\n                    if (!listenerList.isValid) {\n                        close()\n                    } else if (returnFrozenObjects) {\n                        trySend(CollectionChange(listenerList.freeze(), changeSet))\n                    } else {\n                        trySend(CollectionChange(listenerList, changeSet))\n                    }\n                }\n            }\n\n            list.addChangeListener(listener)\n\n            // Emit current value\n            if (returnFrozenObjects) {\n                trySend(CollectionChange(list.freeze(), null))\n            } else {\n                trySend(CollectionChange(list, null))\n            }\n\n            awaitClose {\n                // Remove listener and cleanup\n                if (!flowRealm.isClosed) {\n                    list.removeChangeListener(listener)\n                    flowRealm.close()\n                }\n            }\n        }\n    }\n\n    @Beta\n    override fun <T : RealmModel> from(realm: Realm, realmObject: T): Flow<T> {\n        // Return \"as is\" if frozen, there will be no listening for changes\n        if (realm.isFrozen) {\n            return flowOf(realmObject)\n        }\n\n        val config = realm.configuration\n\n        return callbackFlow<T> {\n            // Check if the Realm is closed (instead of using isValid - findFirstAsync always return \"invalid object\" right away, which would render this logic useless\n            if (realm.isClosed) {\n                awaitClose {}\n\n                return@callbackFlow\n            }\n\n            // Get instance to ensure the Realm is open for as long as we are listening\n            val flowRealm = Realm.getInstance(config)\n            val listener = RealmChangeListener<T> { listenerObj ->\n                if (isActive) {\n                    if (returnFrozenObjects) {\n                        trySend(RealmObject.freeze(listenerObj) as T)\n                    } else {\n                        trySend(listenerObj)\n                    }\n                }\n            }\n\n            RealmObject.addChangeListener(realmObject, listener)\n\n            // Emit current value\n            if (RealmObject.isLoaded(realmObject)) {\n                if (returnFrozenObjects) {\n                    trySend(RealmObject.freeze(realmObject))\n                } else {\n                    trySend(realmObject)\n                }\n            }\n\n            awaitClose {\n                // Remove listener and cleanup\n                if (!flowRealm.isClosed) {\n                    RealmObject.removeChangeListener(realmObject, listener)\n                    flowRealm.close()\n                }\n            }\n        }\n    }\n\n    override fun <T : RealmModel> changesetFrom(\n            realm: Realm,\n            realmObject: T\n    ): Flow<ObjectChange<T>> {\n        // Return \"as is\" if frozen, there will be no listening for changes\n        if (realm.isFrozen) {\n            return flowOf(ObjectChange(realmObject, null))\n        }\n\n        val config = realm.configuration\n\n        return callbackFlow {\n            // Check if the Realm is closed (instead of using isValid - findFirstAsync always return \"invalid object\" right away, which would render this logic useless\n            if (realm.isClosed) {\n                awaitClose {}\n\n                return@callbackFlow\n            }\n\n            // Get instance to ensure the Realm is open for as long as we are listening\n            val flowRealm = Realm.getInstance(config)\n            val listener = RealmObjectChangeListener<T> { listenerObject, changeSet ->\n                if (isActive) {\n                    if (returnFrozenObjects) {\n                        trySend(ObjectChange(RealmObject.freeze(listenerObject), changeSet))\n                    } else {\n                        trySend(ObjectChange(listenerObject, changeSet))\n                    }\n                }\n            }\n\n            RealmObject.addChangeListener(realmObject, listener)\n\n            // Emit current value\n            if (RealmObject.isLoaded(realmObject)) {\n                if (returnFrozenObjects) {\n                    trySend(ObjectChange(RealmObject.freeze(realmObject), null))\n                } else {\n                    trySend(ObjectChange(realmObject, null))\n                }\n            }\n\n            awaitClose {\n                // Remove listener and cleanup\n                if (!flowRealm.isClosed) {\n                    RealmObject.removeChangeListener(realmObject, listener)\n                    flowRealm.close()\n                }\n            }\n        }\n    }\n\n    @Beta\n    override fun from(\n            dynamicRealm: DynamicRealm,\n            dynamicRealmObject: DynamicRealmObject\n    ): Flow<DynamicRealmObject> {\n        // Return \"as is\" if frozen, there will be no listening for changes\n        if (dynamicRealm.isFrozen) {\n            return flowOf(dynamicRealmObject)\n        }\n\n        val config = dynamicRealm.configuration\n\n        return callbackFlow<DynamicRealmObject> {\n            // Check if the Realm is closed (instead of using isValid - findFirstAsync always return \"invalid object\" right away, which would render this logic useless\n            if (dynamicRealm.isClosed) {\n                awaitClose {}\n\n                return@callbackFlow\n            }\n\n            // Get instance to ensure the Realm is open for as long as we are listening\n            val flowRealm = DynamicRealm.getInstance(config)\n            val listener = RealmChangeListener<DynamicRealmObject> { listenerObj ->\n                if (isActive) {\n                    if (returnFrozenObjects) {\n                        trySend(listenerObj.freeze())\n                    } else {\n                        trySend(listenerObj)\n                    }\n                }\n            }\n\n            dynamicRealmObject.addChangeListener(listener)\n\n            // Emit current value\n            if (RealmObject.isLoaded(dynamicRealmObject)) {\n                if (returnFrozenObjects) {\n                    trySend(RealmObject.freeze(dynamicRealmObject))\n                } else {\n                    trySend(dynamicRealmObject)\n                }\n            }\n\n            awaitClose {\n                // Remove listener and cleanup\n                if (!flowRealm.isClosed) {\n                    dynamicRealmObject.removeChangeListener(listener)\n                    flowRealm.close()\n                }\n            }\n        }\n    }\n\n    override fun changesetFrom(\n            dynamicRealm: DynamicRealm,\n            dynamicRealmObject: DynamicRealmObject\n    ): Flow<ObjectChange<DynamicRealmObject>> {\n        // Return \"as is\" if frozen, there will be no listening for changes\n        if (dynamicRealm.isFrozen) {\n            return flowOf(ObjectChange(dynamicRealmObject, null))\n        }\n\n        val config = dynamicRealm.configuration\n\n        return callbackFlow {\n            // Do nothing if the results are invalid\n            if (!RealmObject.isValid(dynamicRealmObject)) {\n                awaitClose {}\n\n                return@callbackFlow\n            }\n\n            // Get instance to ensure the Realm is open for as long as we are listening\n            val flowRealm = Realm.getInstance(config)\n            val listener = RealmObjectChangeListener<DynamicRealmObject> { listenerObject, changeSet ->\n                if (isActive) {\n                    if (returnFrozenObjects) {\n                        trySend(ObjectChange(RealmObject.freeze(listenerObject), changeSet))\n                    } else {\n                        trySend(ObjectChange(listenerObject, changeSet))\n                    }\n                }\n            }\n\n            RealmObject.addChangeListener(dynamicRealmObject, listener)\n\n            // Emit current value\n            if (RealmObject.isLoaded(dynamicRealmObject)) {\n                if (returnFrozenObjects) {\n                    trySend(ObjectChange(RealmObject.freeze(dynamicRealmObject), null))\n                } else {\n                    trySend(ObjectChange(dynamicRealmObject, null))\n                }\n            }\n\n            awaitClose {\n                // Remove listener and cleanup\n                if (!flowRealm.isClosed) {\n                    RealmObject.removeChangeListener(dynamicRealmObject, listener)\n                    flowRealm.close()\n                }\n            }\n        }\n    }\n}"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/internal/modules/CompositeMediator.java",
    "content": "/*\n * Copyright 2015 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\npackage io.realm.internal.modules;\n\nimport android.util.JsonReader;\n\nimport org.json.JSONException;\nimport org.json.JSONObject;\n\nimport java.io.IOException;\nimport java.util.Collection;\nimport java.util.Collections;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Set;\n\nimport io.realm.ImportFlag;\nimport io.realm.Realm;\nimport io.realm.RealmModel;\nimport io.realm.exceptions.RealmException;\nimport io.realm.internal.ColumnInfo;\nimport io.realm.internal.OsObjectSchemaInfo;\nimport io.realm.internal.OsSchemaInfo;\nimport io.realm.internal.RealmObjectProxy;\nimport io.realm.internal.RealmProxyMediator;\nimport io.realm.internal.Row;\nimport io.realm.internal.Util;\n\n\n/**\n * This class is able to merge different RealmProxyMediators, so they look like one.\n */\npublic class CompositeMediator extends RealmProxyMediator {\n\n    private final Map<Class<? extends RealmModel>, RealmProxyMediator> mediators;\n    private final Map<String, Class<? extends RealmModel>> internalClassNames = new HashMap<>();\n\n    public CompositeMediator(RealmProxyMediator... mediators) {\n        final HashMap<Class<? extends RealmModel>, RealmProxyMediator> tempMediators = new HashMap<>();\n        //noinspection ConstantConditions\n        if (mediators != null) {\n            for (RealmProxyMediator mediator : mediators) {\n                for (Class<? extends RealmModel> realmClass : mediator.getModelClasses()) {\n                    // Verify that the module doesn't contain conflicting definitions for the same\n                    // underlying internal name. Can only happen if we add a module from a library\n                    // and a module from the app at the same time.\n                    String newInternalName = mediator.getSimpleClassName(realmClass);\n                    Class existingClass = internalClassNames.get(newInternalName);\n                    if (existingClass != null && !existingClass.equals(realmClass)) {\n                         throw new IllegalStateException(String.format(\"It is not allowed for two different \" +\n                                 \"model classes to share the same internal name in Realm. The \" +\n                                 \"classes %s and %s are being included from the modules '%s' and '%s' \" +\n                                 \"and they share the same internal name '%s'.\", existingClass, realmClass,\n                                 tempMediators.get(existingClass), mediator,\n                                 newInternalName));\n                    }\n\n                    // Store mapping between\n                    tempMediators.put(realmClass, mediator);\n                    internalClassNames.put(newInternalName, realmClass);\n                }\n            }\n        }\n        this.mediators = Collections.unmodifiableMap(tempMediators);\n    }\n\n    @Override\n    public Map<Class<? extends RealmModel>, OsObjectSchemaInfo> getExpectedObjectSchemaInfoMap() {\n        Map<Class<? extends RealmModel>, OsObjectSchemaInfo> infoMap = new HashMap<>();\n        for (RealmProxyMediator mediator : mediators.values()) {\n            infoMap.putAll(mediator.getExpectedObjectSchemaInfoMap());\n        }\n        return infoMap;\n    }\n\n    @Override\n    public ColumnInfo createColumnInfo(Class<? extends RealmModel> clazz, OsSchemaInfo osSchemaInfo) {\n        RealmProxyMediator mediator = getMediator(clazz);\n        return mediator.createColumnInfo(clazz, osSchemaInfo);\n    }\n\n    @Override\n    protected String getSimpleClassNameImpl(Class<? extends RealmModel> clazz) {\n        RealmProxyMediator mediator = getMediator(clazz);\n        return mediator.getSimpleClassName(clazz);\n    }\n\n    @Override\n    protected <T extends RealmModel> Class<T> getClazzImpl(String className) {\n        RealmProxyMediator mediator = getMediator(className);\n        return mediator.getClazz(className);\n    }\n\n    @Override\n    protected boolean hasPrimaryKeyImpl(Class<? extends RealmModel> clazz) {\n        RealmProxyMediator mediator = getMediator(clazz);\n        return mediator.hasPrimaryKey(clazz);\n    }\n\n    @Override\n    public <E extends RealmModel> E newInstance(Class<E> clazz,\n            Object baseRealm,\n            Row row,\n            ColumnInfo columnInfo,\n            boolean acceptDefaultValue,\n            List<String> excludeFields) {\n        RealmProxyMediator mediator = getMediator(clazz);\n        return mediator.newInstance(clazz, baseRealm, row, columnInfo, acceptDefaultValue, excludeFields);\n    }\n\n    @Override\n    public Set<Class<? extends RealmModel>> getModelClasses() {\n        return mediators.keySet();\n    }\n\n    @Override\n    public <E extends RealmModel> E copyOrUpdate(Realm realm, E object, boolean update, Map<RealmModel, RealmObjectProxy> cache, Set<ImportFlag> flags) {\n        RealmProxyMediator mediator = getMediator(Util.getOriginalModelClass(object.getClass()));\n        return mediator.copyOrUpdate(realm, object, update, cache, flags);\n    }\n\n    @Override\n    public long insert(Realm realm, RealmModel object, Map<RealmModel, Long> cache) {\n        RealmProxyMediator mediator = getMediator(Util.getOriginalModelClass(object.getClass()));\n        return mediator.insert(realm, object, cache);\n    }\n\n    @Override\n    public void insert(Realm realm, Collection<? extends RealmModel> objects) {\n        RealmProxyMediator mediator = getMediator(Util.getOriginalModelClass(Util.getOriginalModelClass(objects.iterator().next().getClass())));\n        mediator.insert(realm, objects);\n    }\n\n    @Override\n    public long insertOrUpdate(Realm realm, RealmModel object, Map<RealmModel, Long> cache) {\n        RealmProxyMediator mediator = getMediator(Util.getOriginalModelClass(object.getClass()));\n        return mediator.insertOrUpdate(realm, object, cache);\n    }\n\n    @Override\n    public void insertOrUpdate(Realm realm, Collection<? extends RealmModel> objects) {\n        RealmProxyMediator mediator = getMediator(Util.getOriginalModelClass(Util.getOriginalModelClass(objects.iterator().next().getClass())));\n        mediator.insertOrUpdate(realm, objects);\n    }\n\n    @Override\n    public <E extends RealmModel> E createOrUpdateUsingJsonObject(Class<E> clazz, Realm realm, JSONObject json, boolean update) throws JSONException {\n        RealmProxyMediator mediator = getMediator(clazz);\n        return mediator.createOrUpdateUsingJsonObject(clazz, realm, json, update);\n    }\n\n    @Override\n    public <E extends RealmModel> E createUsingJsonStream(Class<E> clazz, Realm realm, JsonReader reader) throws IOException {\n        RealmProxyMediator mediator = getMediator(clazz);\n        return mediator.createUsingJsonStream(clazz, realm, reader);\n    }\n\n    @Override\n    public <E extends RealmModel> E createDetachedCopy(E realmObject, int maxDepth, Map<RealmModel, RealmObjectProxy.CacheData<RealmModel>> cache) {\n        RealmProxyMediator mediator = getMediator(Util.getOriginalModelClass(realmObject.getClass()));\n        return mediator.createDetachedCopy(realmObject, maxDepth, cache);\n    }\n\n    @Override\n    public <E extends RealmModel> boolean isEmbedded(Class<E> clazz) {\n        RealmProxyMediator mediator = getMediator(Util.getOriginalModelClass(clazz));\n        return mediator.isEmbedded(clazz);\n    }\n\n    @Override\n    public <E extends RealmModel> void updateEmbeddedObject(Realm realm, E unmanagedObject, E managedObject, Map<RealmModel, RealmObjectProxy> cache, Set<ImportFlag> flags) {\n        RealmProxyMediator mediator = getMediator(Util.getOriginalModelClass(managedObject.getClass()));\n        mediator.updateEmbeddedObject(realm, unmanagedObject, managedObject, cache, flags);\n    }\n\n    @Override\n    public boolean transformerApplied() {\n        for (Map.Entry<Class<? extends RealmModel>, RealmProxyMediator> entry : mediators.entrySet()) {\n            if (!entry.getValue().transformerApplied()) {\n                return false;\n            }\n        }\n        return true;\n    }\n\n    // Returns the mediator for a given model class (not RealmProxy) or throws exception\n    private RealmProxyMediator getMediator(Class<? extends RealmModel> clazz) {\n        RealmProxyMediator mediator = mediators.get(Util.getOriginalModelClass(clazz));\n        if (mediator == null) {\n            throw new RealmException(clazz.getSimpleName() + \" is not part of the schema for this Realm\");\n        }\n        return mediator;\n    }\n\n    // Returns the mediator for a given model class (not RealmProxy) or throws exception\n    private RealmProxyMediator getMediator(String className) {\n        Class<? extends RealmModel> clazz = internalClassNames.get(className);\n        return getMediator(clazz);\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/internal/modules/FilterableMediator.java",
    "content": "/*\n * Copyright 2015 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\npackage io.realm.internal.modules;\n\nimport android.util.JsonReader;\n\nimport org.json.JSONException;\nimport org.json.JSONObject;\n\nimport java.io.IOException;\nimport java.util.Collection;\nimport java.util.Collections;\nimport java.util.HashMap;\nimport java.util.HashSet;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Set;\n\nimport io.realm.ImportFlag;\nimport io.realm.Realm;\nimport io.realm.RealmModel;\nimport io.realm.internal.ColumnInfo;\nimport io.realm.internal.OsObjectSchemaInfo;\nimport io.realm.internal.OsSchemaInfo;\nimport io.realm.internal.RealmObjectProxy;\nimport io.realm.internal.RealmProxyMediator;\nimport io.realm.internal.Row;\nimport io.realm.internal.Util;\n\n\n/**\n * Specialized version of a {@link RealmProxyMediator} that can further filter the available classes based on provided\n * filter.\n */\npublic class FilterableMediator extends RealmProxyMediator {\n\n    private final RealmProxyMediator originalMediator;\n    private final Set<Class<? extends RealmModel>> classes;\n\n    /**\n     * Creates a filterable {@link RealmProxyMediator}.\n     *\n     * @param originalMediator the original auto generated mediator.\n     * @param allowedClasses the subset of classes from original mediator to allow.\n     */\n    public FilterableMediator(RealmProxyMediator originalMediator, Collection<Class<? extends RealmModel>> allowedClasses) {\n        this(originalMediator, allowedClasses, false);\n    }\n\n    /**\n     * Creates a filterable {@link RealmProxyMediator}.\n     *\n     * @param originalMediator the original auto generated mediator.\n     * @param classes the subset of classes from original mediator.\n     * @param exclude sets to exclude the classes from the original mediator schema.\n     */\n    public FilterableMediator(RealmProxyMediator originalMediator, Collection<Class<? extends RealmModel>> classes, boolean exclude) {\n        this.originalMediator = originalMediator;\n\n        Set<Class<? extends RealmModel>> tempAllowedClasses = new HashSet<>();\n        //noinspection ConstantConditions\n        if (originalMediator != null) {\n            Set<Class<? extends RealmModel>> originalClasses = originalMediator.getModelClasses();\n            if (!exclude) {\n                for (Class<? extends RealmModel> clazz : classes) {\n                    if (originalClasses.contains(clazz)) {\n                        tempAllowedClasses.add(clazz);\n                    }\n                }\n            } else {\n                for (Class<? extends RealmModel> clazz : originalClasses) {\n                    if (!classes.contains(clazz)) {\n                        tempAllowedClasses.add(clazz);\n                    }\n                }\n            }\n        }\n\n        this.classes = Collections.unmodifiableSet(tempAllowedClasses);\n    }\n\n    @Override\n    public Map<Class<? extends RealmModel>, OsObjectSchemaInfo> getExpectedObjectSchemaInfoMap() {\n        Map<Class<? extends RealmModel>, OsObjectSchemaInfo> infoMap = new HashMap<>();\n        for (Map.Entry<Class<? extends RealmModel>, OsObjectSchemaInfo> entry :\n                originalMediator.getExpectedObjectSchemaInfoMap().entrySet()) {\n            if (classes.contains(entry.getKey())) {\n                infoMap.put(entry.getKey(), entry.getValue());\n            }\n        }\n        return infoMap;\n    }\n\n    @Override\n    public ColumnInfo createColumnInfo(Class<? extends RealmModel> clazz, OsSchemaInfo osSchemaInfo) {\n        checkSchemaHasClass(clazz);\n        return originalMediator.createColumnInfo(clazz, osSchemaInfo);\n    }\n\n    @Override\n    protected String getSimpleClassNameImpl(Class<? extends RealmModel> clazz) {\n        checkSchemaHasClass(clazz);\n        return originalMediator.getSimpleClassName(clazz);\n    }\n\n    @Override\n    protected <T extends RealmModel> Class<T> getClazzImpl(String className) {\n        return originalMediator.getClazz(className);\n    }\n\n    @Override\n    protected boolean hasPrimaryKeyImpl(Class<? extends RealmModel> clazz) {\n        return originalMediator.hasPrimaryKey(clazz);\n    }\n\n    @Override\n    public <E extends RealmModel> E newInstance(Class<E> clazz,\n            Object baseRealm,\n            Row row,\n            ColumnInfo columnInfo,\n            boolean acceptDefaultValue,\n            List<String> excludeFields) {\n        checkSchemaHasClass(clazz);\n        return originalMediator.newInstance(clazz, baseRealm, row, columnInfo, acceptDefaultValue, excludeFields);\n    }\n\n    @Override\n    public Set<Class<? extends RealmModel>> getModelClasses() {\n        return classes;\n    }\n\n    @Override\n    public <E extends RealmModel> E copyOrUpdate(Realm realm, E object, boolean update, Map<RealmModel, RealmObjectProxy> cache, Set<ImportFlag> flags) {\n        checkSchemaHasClass(Util.getOriginalModelClass(object.getClass()));\n        return originalMediator.copyOrUpdate(realm, object, update, cache, flags);\n    }\n\n    @Override\n    public long insert(Realm realm, RealmModel object, Map<RealmModel, Long> cache) {\n        checkSchemaHasClass(Util.getOriginalModelClass(object.getClass()));\n        return originalMediator.insert(realm, object, cache);\n    }\n\n    @Override\n    public void insert(Realm realm, Collection<? extends RealmModel> objects) {\n        checkSchemaHasClass(Util.getOriginalModelClass(objects.iterator().next().getClass()));\n        originalMediator.insert(realm, objects);\n    }\n\n    @Override\n    public long insertOrUpdate(Realm realm, RealmModel object, Map<RealmModel, Long> cache) {\n        checkSchemaHasClass(Util.getOriginalModelClass(object.getClass()));\n        return originalMediator.insertOrUpdate(realm, object, cache);\n    }\n\n    @Override\n    public void insertOrUpdate(Realm realm, Collection<? extends RealmModel> objects) {\n        checkSchemaHasClass(Util.getOriginalModelClass(objects.iterator().next().getClass()));\n        originalMediator.insertOrUpdate(realm, objects);\n    }\n\n    @Override\n    public <E extends RealmModel> E createOrUpdateUsingJsonObject(Class<E> clazz, Realm realm, JSONObject json, boolean update) throws JSONException {\n        checkSchemaHasClass(clazz);\n        return originalMediator.createOrUpdateUsingJsonObject(clazz, realm, json, update);\n    }\n\n    @Override\n    public <E extends RealmModel> E createUsingJsonStream(Class<E> clazz, Realm realm, JsonReader reader) throws IOException {\n        checkSchemaHasClass(clazz);\n        return originalMediator.createUsingJsonStream(clazz, realm, reader);\n    }\n\n    @Override\n    public <E extends RealmModel> E createDetachedCopy(E realmObject, int maxDepth, Map<RealmModel, RealmObjectProxy.CacheData<RealmModel>> cache) {\n        checkSchemaHasClass(Util.getOriginalModelClass(realmObject.getClass()));\n        return originalMediator.createDetachedCopy(realmObject, maxDepth, cache);\n    }\n\n    @Override\n    public <E extends RealmModel> boolean isEmbedded(Class<E> clazz) {\n        checkSchemaHasClass(Util.getOriginalModelClass(clazz));\n        return originalMediator.isEmbedded(clazz);\n    }\n\n    @Override\n    public <E extends RealmModel> void updateEmbeddedObject(Realm realm, E unmanagedObject, E managedObject, Map<RealmModel, RealmObjectProxy> cache, Set<ImportFlag> flags) {\n        checkSchemaHasClass(Util.getOriginalModelClass(managedObject.getClass()));\n        originalMediator.updateEmbeddedObject(realm, unmanagedObject, managedObject, cache, flags);\n    }\n\n    @Override\n    public boolean transformerApplied() {\n        //noinspection SimplifiableIfStatement\n        if (originalMediator == null) {\n            return true;\n        }\n        return originalMediator.transformerApplied();\n    }\n\n    // Validates if a model class (not RealmProxy) is part of this Schema.\n    private void checkSchemaHasClass(Class<? extends RealmModel> clazz) {\n        if (!classes.contains(clazz)) {\n            throw new IllegalArgumentException(clazz.getSimpleName() + \" is not part of the schema for this Realm\");\n        }\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/internal/modules/package-info.java",
    "content": "/*\n * Copyright 2017 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@javax.annotation.ParametersAreNonnullByDefault\npackage io.realm.internal.modules;\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/internal/objectstore/OsKeyPathMapping.java",
    "content": "/*\n * Copyright 2021 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\npackage io.realm.internal.objectstore;\n\nimport io.realm.RealmSchema;\nimport io.realm.exceptions.RealmError;\nimport io.realm.internal.NativeContext;\nimport io.realm.internal.NativeObject;\n\n/**\n * Wrapper for ObjectStore's KeyPathMapping class.\n * <p>\n * The primary use case for this  class is to make sure that we release native memory for any old\n * mappings when the schema is updated.\n * <p>\n * It will use the already constructed ObjectStore schema to create the mappings required by\n * the Query Parser.\n *\n * @see RealmSchema#refresh()\n */\npublic class OsKeyPathMapping implements NativeObject {\n\n    private static final long nativeFinalizerPtr = nativeGetFinalizerMethodPtr();\n    public long mappingPointer = -1;\n\n    public OsKeyPathMapping(long sharedRealmNativePointer) {\n        mappingPointer = nativeCreateMapping(sharedRealmNativePointer);\n        NativeContext.dummyContext.addReference(this);\n    }\n\n    @Override\n    public long getNativePtr() {\n        return mappingPointer;\n    }\n\n    @Override\n    public long getNativeFinalizerPtr() {\n        return nativeFinalizerPtr;\n    }\n\n    private static native long nativeGetFinalizerMethodPtr();\n    private static native long nativeCreateMapping(long sharedRealmNativePointer);\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/internal/objectstore/OsMutableSubscriptionSet.java",
    "content": "/*\n * Copyright 2022 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 */\npackage io.realm.internal.objectstore;\n\nimport io.realm.RealmModel;\nimport io.realm.internal.RealmProxyMediator;\nimport io.realm.internal.UnmanagedSubscription;\nimport io.realm.internal.annotations.ObjectServer;\nimport io.realm.internal.async.RealmThreadPoolExecutor;\nimport io.realm.mongodb.sync.MutableSubscriptionSet;\nimport io.realm.mongodb.sync.Subscription;\n\n@ObjectServer\npublic class OsMutableSubscriptionSet extends OsSubscriptionSet implements MutableSubscriptionSet {\n\n    public OsMutableSubscriptionSet(long nativePtr,\n                                    RealmProxyMediator schema,\n                                    RealmThreadPoolExecutor listenerExecutor,\n                                    RealmThreadPoolExecutor updateExecutor) {\n        super(nativePtr, schema, listenerExecutor, updateExecutor);\n    }\n\n    @Override\n    public Subscription add(Subscription subscription) {\n        return addSubscription(subscription, true);\n    }\n\n    @Override\n    public Subscription addOrUpdate(Subscription subscription) {\n        return addSubscription(subscription, false);\n    }\n\n    private Subscription addSubscription(Subscription subscription, boolean throwOnUpdate) {\n        if (subscription instanceof UnmanagedSubscription) {\n            UnmanagedSubscription sub = (UnmanagedSubscription) subscription;\n            long subscriptionPtr = nativeInsertOrAssign(getNativePtr(), sub.getName(), sub.getQueryPointer(), throwOnUpdate);\n            return new OsSubscription(subscriptionPtr);\n        } else {\n            throw new IllegalArgumentException(\"Only unmanaged subscriptions are allowed as input. This subscription was managed.\");\n        }\n    }\n\n    @Override\n    public boolean remove(Subscription subscription) {\n        if (subscription instanceof OsSubscription) {\n            return nativeRemove(getNativePtr(), ((OsSubscription) subscription).getNativePtr());\n        } else {\n            throw new IllegalArgumentException(\"Only managed Subscriptions can be removed.\");\n        }\n    }\n\n    @Override\n    public boolean remove(String name) {\n        return nativeRemoveNamed(getNativePtr(), name);\n    }\n\n    @Override\n    public boolean removeAll(String type) {\n        return nativeRemoveAllForType(getNativePtr(), type);\n    }\n\n    @Override\n    public <T extends RealmModel> boolean removeAll(Class<T> clazz) {\n        return nativeRemoveAllForType(getNativePtr(), schema.getSimpleClassName(clazz));\n    }\n\n    @Override\n    public boolean removeAll() {\n        return nativeRemoveAll(getNativePtr());\n    }\n\n    /**\n     * Returns the native pointer for the updated underlying SubscriptionSet\n     */\n    public long commit() {\n        return nativeCommit(getNativePtr());\n    }\n\n    private static native long nativeInsertOrAssign(long mutableSubscriptionsPtr, String name, long queryPtr, boolean throwOnUpdate);\n    private static native boolean nativeRemoveNamed(long mutableSubscriptionsPtr, String name);\n    private static native boolean nativeRemove(long mutableSubscriptionsPtr, long subscriptionPtr);\n    private static native long nativeCommit(long mutableSubscriptionsPtr);\n    private static native boolean nativeRemoveAll(long mutableSubscriptionsPtr);\n    private static native boolean nativeRemoveAllForType(long mutableSubscriptionsPtr, String clazzType);\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/internal/objectstore/OsObjectBuilder.java",
    "content": "/*\n * Copyright 2018 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 */\npackage io.realm.internal.objectstore;\n\nimport org.bson.types.Decimal128;\nimport org.bson.types.ObjectId;\n\nimport java.io.Closeable;\nimport java.util.Date;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Set;\nimport java.util.UUID;\n\nimport javax.annotation.Nullable;\n\nimport io.realm.ImportFlag;\nimport io.realm.RealmAny;\nimport io.realm.RealmAnyNativeFunctionsImpl;\nimport io.realm.MutableRealmInteger;\nimport io.realm.RealmDictionary;\nimport io.realm.RealmList;\nimport io.realm.RealmModel;\nimport io.realm.RealmSet;\nimport io.realm.internal.RealmAnyNativeFunctions;\nimport io.realm.internal.NativeContext;\nimport io.realm.internal.OsSharedRealm;\nimport io.realm.internal.RealmObjectProxy;\nimport io.realm.internal.Table;\nimport io.realm.internal.UncheckedRow;\n\n\n/**\n * This class is a wrapper around building up object data for calling `Object::create()`\n * <p>\n * Fill the object data by calling the various `addX()` methods, then create a new Object or update\n * an existing one by calling {@link #createNewObject()}, {@link #updateExistingTopLevelObject()} or\n * {@link #updateExistingEmbeddedObject(RealmObjectProxy)}.\n * <p>\n * This class assumes it is only being used from within a write transaction. Using it outside one\n * will result in undefined behaviour.\n * <p>\n * The native\n * resources are created in the constructor of this class and destroyed when calling either of the\n * above two methods.\n * <p>\n * <H1>Design thoughts</H1>\n * <p>\n * Ideally we would have sent all properties across in one JNI call, but the only way to do that would\n * have been using two `Object[]` arrays which would have resulted in a ton of JNI calls back\n * again for resolving the primitive values of boxed types (since JNI do not know about boxed\n * primitives).\n * <p>\n * The upside of making a JNI call for each property is that we do minimal allocations on the Java\n * side. Also each method call is fairly lightweight as no checks are performed compared to using\n * Proxy setters and {@link io.realm.internal.UncheckedRow}. The only downside is the current need for\n * sending the key as well. Hopefully we can change that to schema indices at some point.\n * <p>\n * There is quite a few variants we can attempt to optimize this, but at this point we lack data\n * that can guide any architectural design and the only way to really find out is to build out each\n * solution and benchmark it.\n */\npublic class OsObjectBuilder implements Closeable {\n\n    private final Table table;\n    private final long sharedRealmPtr;\n    private final long builderPtr;\n    private final long tablePtr;\n    private final NativeContext context;\n\n    // ------------------------------------------\n    // List handlers\n    // ------------------------------------------\n\n    private static ItemCallback<? extends RealmModel> objectItemCallback = new ItemCallback<RealmModel>() {\n        @Override\n        public void handleItem(long containerPtr, RealmModel item) {\n            RealmObjectProxy proxyItem = (RealmObjectProxy) item;\n            nativeAddIntegerListItem(containerPtr, ((UncheckedRow) proxyItem.realmGet$proxyState().getRow$realm()).getNativePtr());\n        }\n    };\n\n    private static ItemCallback<String> stringItemCallback = new ItemCallback<String>() {\n        @Override\n        public void handleItem(long containerPtr, String item) {\n            nativeAddStringListItem(containerPtr, item);\n        }\n    };\n\n    private static ItemCallback<Byte> byteItemCallback = new ItemCallback<Byte>() {\n        @Override\n        public void handleItem(long containerPtr, Byte item) {\n            nativeAddIntegerListItem(containerPtr, item.longValue());\n        }\n    };\n\n    private static ItemCallback<Short> shortItemCallback = new ItemCallback<Short>() {\n        @Override\n        public void handleItem(long containerPtr, Short item) {\n            nativeAddIntegerListItem(containerPtr, item);\n        }\n    };\n\n    private static ItemCallback<Integer> integerItemCallback = new ItemCallback<Integer>() {\n        @Override\n        public void handleItem(long containerPtr, Integer item) {\n            nativeAddIntegerListItem(containerPtr, item);\n        }\n    };\n\n    private static ItemCallback<Long> longItemCallback = new ItemCallback<Long>() {\n        @Override\n        public void handleItem(long containerPtr, Long item) {\n            nativeAddIntegerListItem(containerPtr, item);\n        }\n    };\n\n    private static ItemCallback<Boolean> booleanItemCallback = new ItemCallback<Boolean>() {\n        @Override\n        public void handleItem(long containerPtr, Boolean item) {\n            nativeAddBooleanListItem(containerPtr, item);\n        }\n    };\n\n    private static ItemCallback<Float> floatItemCallback = new ItemCallback<Float>() {\n        @Override\n        public void handleItem(long containerPtr, Float item) {\n            nativeAddFloatListItem(containerPtr, item);\n        }\n    };\n\n    private static ItemCallback<Double> doubleItemCallback = new ItemCallback<Double>() {\n        @Override\n        public void handleItem(long containerPtr, Double item) {\n            nativeAddDoubleListItem(containerPtr, item);\n        }\n    };\n\n    private static ItemCallback<Date> dateItemCallback = new ItemCallback<Date>() {\n        @Override\n        public void handleItem(long containerPtr, Date item) {\n            nativeAddDateListItem(containerPtr, item.getTime());\n        }\n    };\n\n    private static ItemCallback<byte[]> byteArrayItemCallback = new ItemCallback<byte[]>() {\n        @Override\n        public void handleItem(long containerPtr, byte[] item) {\n            nativeAddByteArrayListItem(containerPtr, item);\n        }\n    };\n\n    private static ItemCallback<MutableRealmInteger> mutableRealmIntegerItemCallback = new ItemCallback<MutableRealmInteger>() {\n        @Override\n        public void handleItem(long containerPtr, MutableRealmInteger item) {\n            Long value = item.get();\n            if (value == null) {\n                nativeAddNullListItem(containerPtr);\n            } else {\n                nativeAddIntegerListItem(containerPtr, value);\n            }\n        }\n    };\n\n    private static ItemCallback<Decimal128> decimal128ItemCallback = new ItemCallback<Decimal128>() {\n        @Override\n        public void handleItem(long containerPtr, Decimal128 item) {\n            nativeAddDecimal128ListItem(containerPtr, item.getLow(), item.getHigh());\n        }\n    };\n\n    private static ItemCallback<ObjectId> objectIdItemCallback = new ItemCallback<ObjectId>() {\n        @Override\n        public void handleItem(long containerPtr, ObjectId item) {\n            nativeAddObjectIdListItem(containerPtr, item.toString());\n        }\n    };\n\n    private static ItemCallback<UUID> uuidItemCallback = new ItemCallback<UUID>() {\n        @Override\n        public void handleItem(long containerPtr, UUID item) {\n            nativeAddUUIDListItem(containerPtr, item.toString());\n        }\n    };\n\n    // ------------------------------------------\n    // Map/Dictionary handlers\n    // ------------------------------------------\n\n    private static ItemCallback<Map.Entry<String, Boolean>> booleanMapItemCallback = new ItemCallback<Map.Entry<String, Boolean>>() {\n        @Override\n        public void handleItem(long containerPtr, Map.Entry<String, Boolean> item) {\n            nativeAddBooleanDictionaryEntry(containerPtr, item.getKey(), item.getValue());\n        }\n    };\n\n    private static ItemCallback<Map.Entry<String, String>> stringMapItemCallback = new ItemCallback<Map.Entry<String, String>>() {\n        @Override\n        public void handleItem(long containerPtr, Map.Entry<String, String> item) {\n            nativeAddStringDictionaryEntry(containerPtr, item.getKey(), item.getValue());\n        }\n    };\n\n    private static ItemCallback<Map.Entry<String, Integer>> integerMapItemCallback = new ItemCallback<Map.Entry<String, Integer>>() {\n        @Override\n        public void handleItem(long containerPtr, Map.Entry<String, Integer> item) {\n            nativeAddIntegerDictionaryEntry(containerPtr, item.getKey(), item.getValue());\n        }\n    };\n\n    private static ItemCallback<Map.Entry<String, Float>> floatMapItemCallback = new ItemCallback<Map.Entry<String, Float>>() {\n        @Override\n        public void handleItem(long containerPtr, Map.Entry<String, Float> item) {\n            nativeAddFloatDictionaryEntry(containerPtr, item.getKey(), item.getValue());\n        }\n    };\n\n    private static ItemCallback<Map.Entry<String, Long>> longMapItemCallback = new ItemCallback<Map.Entry<String, Long>>() {\n        @Override\n        public void handleItem(long containerPtr, Map.Entry<String, Long> item) {\n            nativeAddIntegerDictionaryEntry(containerPtr, item.getKey(), item.getValue());\n        }\n    };\n\n    private static ItemCallback<Map.Entry<String, Short>> shortMapItemCallback = new ItemCallback<Map.Entry<String, Short>>() {\n        @Override\n        public void handleItem(long containerPtr, Map.Entry<String, Short> item) {\n            nativeAddIntegerDictionaryEntry(containerPtr, item.getKey(), item.getValue());\n        }\n    };\n\n    private static ItemCallback<Map.Entry<String, Byte>> byteMapItemCallback = new ItemCallback<Map.Entry<String, Byte>>() {\n        @Override\n        public void handleItem(long containerPtr, Map.Entry<String, Byte> item) {\n            nativeAddIntegerDictionaryEntry(containerPtr, item.getKey(), item.getValue());\n        }\n    };\n\n    private static ItemCallback<Map.Entry<String, Double>> doubleMapItemCallback = new ItemCallback<Map.Entry<String, Double>>() {\n        @Override\n        public void handleItem(long containerPtr, Map.Entry<String, Double> item) {\n            nativeAddDoubleDictionaryEntry(containerPtr, item.getKey(), item.getValue());\n        }\n    };\n\n    private static ItemCallback<Map.Entry<String, byte[]>> binaryMapItemCallback = new ItemCallback<Map.Entry<String, byte[]>>() {\n        @Override\n        public void handleItem(long containerPtr, Map.Entry<String, byte[]> item) {\n            nativeAddBinaryDictionaryEntry(containerPtr, item.getKey(), item.getValue());\n        }\n    };\n\n    private static ItemCallback<Map.Entry<String, Date>> dateMapItemCallback = new ItemCallback<Map.Entry<String, Date>>() {\n        @Override\n        public void handleItem(long containerPtr, Map.Entry<String, Date> item) {\n            nativeAddDateDictionaryEntry(containerPtr, item.getKey(), item.getValue().getTime());\n        }\n    };\n\n    private static ItemCallback<Map.Entry<String, Decimal128>> decimal128MapItemCallback = new ItemCallback<Map.Entry<String, Decimal128>>() {\n        @Override\n        public void handleItem(long containerPtr, Map.Entry<String, Decimal128> item) {\n            nativeAddDecimal128DictionaryEntry(containerPtr, item.getKey(), item.getValue().getHigh(), item.getValue().getLow());\n        }\n    };\n\n    private static ItemCallback<Map.Entry<String, ObjectId>> objectIdMapItemCallback = new ItemCallback<Map.Entry<String, ObjectId>>() {\n        @Override\n        public void handleItem(long containerPtr, Map.Entry<String, ObjectId> item) {\n            nativeAddObjectIdDictionaryEntry(containerPtr, item.getKey(), item.getValue().toString());\n        }\n    };\n\n    private static ItemCallback<Map.Entry<String, UUID>> uuidMapItemCallback = new ItemCallback<Map.Entry<String, UUID>>() {\n        @Override\n        public void handleItem(long containerPtr, Map.Entry<String, UUID> item) {\n            nativeAddUUIDDictionaryEntry(containerPtr, item.getKey(), item.getValue().toString());\n        }\n    };\n\n    private static ItemCallback<Map.Entry<String, RealmAny>> realmAnyMapItemCallback = new ItemCallback<Map.Entry<String, RealmAny>>() {\n        private final RealmAnyNativeFunctions realmAnyNativeFunctions = new RealmAnyNativeFunctionsImpl();\n\n        @Override\n        public void handleItem(long containerPtr, Map.Entry<String, RealmAny> item) {\n            realmAnyNativeFunctions.handleItem(containerPtr, item);\n        }\n    };\n\n    private static ItemCallback<RealmAny> realmAnyItemCallback = new ItemCallback<RealmAny>() {\n        private final RealmAnyNativeFunctions realmAnyNativeFunctions = new RealmAnyNativeFunctionsImpl();\n\n        @Override\n        public void handleItem(long listPtr, RealmAny realmAny) {\n            realmAnyNativeFunctions.handleItem(listPtr, realmAny);\n        }\n    };\n\n    // If true, fields will not be updated if the same value would be written to it.\n    private final boolean ignoreFieldsWithSameValue;\n\n    public OsObjectBuilder(Table table, Set<ImportFlag> flags) {\n        OsSharedRealm sharedRealm = table.getSharedRealm();\n        this.sharedRealmPtr = sharedRealm.getNativePtr();\n        this.table = table;\n        this.table.getColumnNames();\n        this.tablePtr = table.getNativePtr();\n        this.builderPtr = nativeCreateBuilder();\n        this.context = sharedRealm.context;\n        this.ignoreFieldsWithSameValue = flags.contains(ImportFlag.CHECK_SAME_VALUES_BEFORE_SET);\n    }\n\n    public void addInteger(long columnKey, @Nullable Byte val) {\n        if (val == null) {\n            nativeAddNull(builderPtr, columnKey);\n        } else {\n            nativeAddInteger(builderPtr, columnKey, val);\n        }\n    }\n\n    public void addInteger(long columnKey, @Nullable Short val) {\n        if (val == null) {\n            nativeAddNull(builderPtr, columnKey);\n        } else {\n            nativeAddInteger(builderPtr, columnKey, val);\n        }\n    }\n\n    public void addInteger(long columnKey, @Nullable Integer val) {\n        if (val == null) {\n            nativeAddNull(builderPtr, columnKey);\n        } else {\n            nativeAddInteger(builderPtr, columnKey, val);\n        }\n    }\n\n    public void addInteger(long columnKey, @Nullable Long val) {\n        if (val == null) {\n            nativeAddNull(builderPtr, columnKey);\n        } else {\n            nativeAddInteger(builderPtr, columnKey, val);\n        }\n    }\n\n    public void addMutableRealmInteger(long columnKey, @Nullable MutableRealmInteger val) {\n        if (val == null || val.get() == null) {\n            nativeAddNull(builderPtr, columnKey);\n        } else {\n            nativeAddInteger(builderPtr, columnKey, val.get());\n        }\n    }\n\n    public void addRealmAny(long columnKey, long realmAnyPtr) {\n        nativeAddRealmAny(builderPtr, columnKey, realmAnyPtr);\n    }\n\n    public void addString(long columnKey, @Nullable String val) {\n        if (val == null) {\n            nativeAddNull(builderPtr, columnKey);\n        } else {\n            nativeAddString(builderPtr, columnKey, val);\n        }\n    }\n\n    public void addFloat(long columnKey, @Nullable Float val) {\n        if (val == null) {\n            nativeAddNull(builderPtr, columnKey);\n        } else {\n            nativeAddFloat(builderPtr, columnKey, val);\n        }\n    }\n\n    public void addDouble(long columnKey, @Nullable Double val) {\n        if (val == null) {\n            nativeAddNull(builderPtr, columnKey);\n        } else {\n            nativeAddDouble(builderPtr, columnKey, val);\n        }\n    }\n\n    public void addBoolean(long columnKey, @Nullable Boolean val) {\n        if (val == null) {\n            nativeAddNull(builderPtr, columnKey);\n        } else {\n            nativeAddBoolean(builderPtr, columnKey, val);\n        }\n    }\n\n    public void addDate(long columnKey, @Nullable Date val) {\n        if (val == null) {\n            nativeAddNull(builderPtr, columnKey);\n        } else {\n            nativeAddDate(builderPtr, columnKey, val.getTime());\n        }\n    }\n\n    public void addByteArray(long columnKey, @Nullable byte[] val) {\n        if (val == null) {\n            nativeAddNull(builderPtr, columnKey);\n        } else {\n            nativeAddByteArray(builderPtr, columnKey, val);\n        }\n    }\n\n    public void addDecimal128(long columnKey, @Nullable Decimal128 val) {\n        if (val == null) {\n            nativeAddNull(builderPtr, columnKey);\n        } else {\n            nativeAddDecimal128(builderPtr, columnKey, val.getLow(), val.getHigh());\n        }\n    }\n\n    public void addObjectId(long columnKey, @Nullable ObjectId val) {\n        if (val == null) {\n            nativeAddNull(builderPtr, columnKey);\n        } else {\n            nativeAddObjectId(builderPtr, columnKey, val.toString());\n        }\n    }\n\n    public void addUUID(long columnKey, @Nullable UUID val) {\n        if (val == null) {\n            nativeAddNull(builderPtr, columnKey);\n        } else {\n            nativeAddUUID(builderPtr, columnKey, val.toString());\n        }\n    }\n\n    public void addNull(long columnKey) {\n        nativeAddNull(builderPtr, columnKey);\n    }\n\n    public void addObject(long columnKey, @Nullable RealmModel val) {\n        if (val == null) {\n            nativeAddNull(builderPtr, columnKey);\n        } else {\n            RealmObjectProxy proxy = (RealmObjectProxy) val;\n            UncheckedRow row = (UncheckedRow) proxy.realmGet$proxyState().getRow$realm();\n            nativeAddObject(builderPtr, columnKey, row.getNativePtr());\n        }\n    }\n\n    private <T> void addListItem(long builderPtr, long columnKey, @Nullable List<T> list, ItemCallback<T> itemCallback) {\n        if (list != null) {\n            long listPtr = nativeStartList(list.size());\n            boolean isNullable = (columnKey == 0) || table.isColumnNullable(columnKey);\n            for (int i = 0; i < list.size(); i++) {\n                T item = list.get(i);\n                if (item == null) {\n                    if (!isNullable) {\n                        throw new IllegalArgumentException(\"This 'RealmList' is not nullable. A non-null value is expected.\");\n                    }\n                    nativeAddNullListItem(listPtr);\n                } else {\n                    itemCallback.handleItem(listPtr, item);\n                }\n            }\n            nativeStopList(builderPtr, columnKey, listPtr);\n        } else {\n            addEmptyList(columnKey);\n        }\n    }\n\n    public <T extends RealmModel> void addObjectList(long columnKey, @Nullable RealmList<T> list) {\n        // Null objects references are not allowed. So we can optimize the JNI boundary by\n        // sending all object references in one long[] array.\n        if (list != null) {\n            long[] rowPointers = new long[list.size()];\n            for (int i = 0; i < list.size(); i++) {\n                RealmObjectProxy item = (RealmObjectProxy) list.get(i);\n                if (item == null) {\n                    throw new IllegalArgumentException(\"Null values are not allowed in RealmLists containing Realm models\");\n                } else {\n                    rowPointers[i] = ((UncheckedRow) item.realmGet$proxyState().getRow$realm()).getNativePtr();\n                }\n            }\n            nativeAddObjectList(builderPtr, columnKey, rowPointers);\n        } else {\n            nativeAddObjectList(builderPtr, columnKey, new long[0]);\n        }\n    }\n\n    public void addStringList(long columnKey, RealmList<String> list) {\n        addListItem(builderPtr, columnKey, list, stringItemCallback);\n    }\n\n    public void addByteList(long columnKey, RealmList<Byte> list) {\n        addListItem(builderPtr, columnKey, list, byteItemCallback);\n    }\n\n    public void addShortList(long columnKey, RealmList<Short> list) {\n        addListItem(builderPtr, columnKey, list, shortItemCallback);\n    }\n\n    public void addIntegerList(long columnKey, RealmList<Integer> list) {\n        addListItem(builderPtr, columnKey, list, integerItemCallback);\n    }\n\n    public void addLongList(long columnKey, RealmList<Long> list) {\n        addListItem(builderPtr, columnKey, list, longItemCallback);\n    }\n\n    public void addBooleanList(long columnKey, RealmList<Boolean> list) {\n        addListItem(builderPtr, columnKey, list, booleanItemCallback);\n    }\n\n    public void addFloatList(long columnKey, RealmList<Float> list) {\n        addListItem(builderPtr, columnKey, list, floatItemCallback);\n    }\n\n    public void addDoubleList(long columnKey, RealmList<Double> list) {\n        addListItem(builderPtr, columnKey, list, doubleItemCallback);\n    }\n\n    public void addDateList(long columnKey, RealmList<Date> list) {\n        addListItem(builderPtr, columnKey, list, dateItemCallback);\n    }\n\n    public void addByteArrayList(long columnKey, RealmList<byte[]> list) {\n        addListItem(builderPtr, columnKey, list, byteArrayItemCallback);\n    }\n\n    public void addMutableRealmIntegerList(long columnKey, RealmList<MutableRealmInteger> list) {\n        addListItem(builderPtr, columnKey, list, mutableRealmIntegerItemCallback);\n    }\n\n    public void addDecimal128List(long columnKey, RealmList<Decimal128> list) {\n        addListItem(builderPtr, columnKey, list, decimal128ItemCallback);\n    }\n\n    public void addObjectIdList(long columnKey, RealmList<ObjectId> list) {\n        addListItem(builderPtr, columnKey, list, objectIdItemCallback);\n    }\n\n    public void addUUIDList(long columnKey, RealmList<UUID> list) {\n        addListItem(builderPtr, columnKey, list, uuidItemCallback);\n    }\n\n    public void addRealmAnyList(long columnKey, RealmList<RealmAny> list) {\n        addListItem(builderPtr, columnKey, list, realmAnyItemCallback);\n    }\n\n    private void addEmptyList(long columnKey) {\n        long listPtr = nativeStartList(0);\n        nativeStopList(builderPtr, columnKey, listPtr);\n    }\n\n    public void addBooleanValueDictionary(long columnKey, RealmDictionary<Boolean> dictionary) {\n        addDictionaryItem(builderPtr, columnKey, dictionary, booleanMapItemCallback);\n    }\n\n    public void addIntegerValueDictionary(long columnKey, RealmDictionary<Integer> dictionary) {\n        addDictionaryItem(builderPtr, columnKey, dictionary, integerMapItemCallback);\n    }\n\n    public void addFloatValueDictionary(long columnKey, RealmDictionary<Float> dictionary) {\n        addDictionaryItem(builderPtr, columnKey, dictionary, floatMapItemCallback);\n    }\n\n    public void addLongValueDictionary(long columnKey, RealmDictionary<Long> dictionary) {\n        addDictionaryItem(builderPtr, columnKey, dictionary, longMapItemCallback);\n    }\n\n    public void addShortValueDictionary(long columnKey, RealmDictionary<Short> dictionary) {\n        addDictionaryItem(builderPtr, columnKey, dictionary, shortMapItemCallback);\n    }\n\n    public void addByteValueDictionary(long columnKey, RealmDictionary<Byte> dictionary) {\n        addDictionaryItem(builderPtr, columnKey, dictionary, byteMapItemCallback);\n    }\n\n    public void addDoubleValueDictionary(long columnKey, RealmDictionary<Double> dictionary) {\n        addDictionaryItem(builderPtr, columnKey, dictionary, doubleMapItemCallback);\n    }\n\n    public void addStringValueDictionary(long columnKey, RealmDictionary<String> dictionary) {\n        addDictionaryItem(builderPtr, columnKey, dictionary, stringMapItemCallback);\n    }\n\n    public void addDateValueDictionary(long columnKey, RealmDictionary<Date> dictionary) {\n        addDictionaryItem(builderPtr, columnKey, dictionary, dateMapItemCallback);\n    }\n\n    public void addDecimal128ValueDictionary(long columnKey, RealmDictionary<Decimal128> dictionary) {\n        addDictionaryItem(builderPtr, columnKey, dictionary, decimal128MapItemCallback);\n    }\n\n    public void addBinaryValueDictionary(long columnKey, RealmDictionary<byte[]> dictionary) {\n        addDictionaryItem(builderPtr, columnKey, dictionary, binaryMapItemCallback);\n    }\n\n    public void addObjectIdValueDictionary(long columnKey, RealmDictionary<ObjectId> dictionary) {\n        addDictionaryItem(builderPtr, columnKey, dictionary, objectIdMapItemCallback);\n    }\n\n    public void addUUIDValueDictionary(long columnKey, RealmDictionary<UUID> dictionary) {\n        addDictionaryItem(builderPtr, columnKey, dictionary, uuidMapItemCallback);\n    }\n\n    public void addRealmAnyValueDictionary(long columnKey, RealmDictionary<RealmAny> dictionary) {\n        addDictionaryItem(builderPtr, columnKey, dictionary, realmAnyMapItemCallback);\n    }\n\n    public <T extends RealmModel> void addObjectDictionary(long columnKey, @Nullable RealmDictionary<T> dictionary) {\n        if (dictionary != null) {\n            long dictionaryPtr = nativeStartDictionary();\n            for (Map.Entry<String, T> entry : dictionary.entrySet()) {\n                if (entry.getValue() == null) {\n                    nativeAddNullDictionaryEntry(dictionaryPtr, entry.getKey());\n                } else {\n                    RealmObjectProxy realmObjectProxy = (RealmObjectProxy) entry.getValue();\n                    long objectPtr = ((UncheckedRow) realmObjectProxy.realmGet$proxyState().getRow$realm()).getNativePtr();\n                    nativeAddObjectDictionaryEntry(dictionaryPtr, entry.getKey(), objectPtr);\n                }\n            }\n            nativeStopDictionary(builderPtr, columnKey, dictionaryPtr);\n        } else {\n            addEmptyDictionary(columnKey);\n        }\n    }\n\n    private <T> void addDictionaryItem(\n            long builderPtr,\n            long columnKey,\n            @Nullable RealmDictionary<T> dictionary,\n            ItemCallback<Map.Entry<String, T>> mapItemCallback\n    ) {\n        if (dictionary != null) {\n            long dictionaryPtr = nativeStartDictionary();\n            for (Map.Entry<String, T> entry : dictionary.entrySet()) {\n                if (entry.getValue() == null) {\n                    nativeAddNullDictionaryEntry(dictionaryPtr, entry.getKey());\n                } else {\n                    mapItemCallback.handleItem(dictionaryPtr, entry);\n                }\n            }\n            nativeStopDictionary(builderPtr, columnKey, dictionaryPtr);\n        } else {\n            addEmptyDictionary(columnKey);\n        }\n    }\n\n    private void addEmptyDictionary(long columnKey) {\n        nativeStopDictionary(builderPtr, columnKey, nativeStartDictionary());\n    }\n\n    // -----------------------------------------------\n    // SET\n    // -----------------------------------------------\n\n    private static ItemCallback<String> stringSetItemCallback = new ItemCallback<String>() {\n        @Override\n        public void handleItem(long containerPtr, String item) {\n            nativeAddStringSetItem(containerPtr, item);\n        }\n    };\n\n    private static ItemCallback<Boolean> booleanSetItemCallback = new ItemCallback<Boolean>() {\n        @Override\n        public void handleItem(long containerPtr, Boolean item) {\n            nativeAddBooleanSetItem(containerPtr, item);\n        }\n    };\n\n    private static ItemCallback<Integer> integerSetItemCallback = new ItemCallback<Integer>() {\n        @Override\n        public void handleItem(long containerPtr, Integer item) {\n            nativeAddIntegerSetItem(containerPtr, item);\n        }\n    };\n\n    private static ItemCallback<Long> longSetItemCallback = new ItemCallback<Long>() {\n        @Override\n        public void handleItem(long containerPtr, Long item) {\n            nativeAddIntegerSetItem(containerPtr, item);\n        }\n    };\n\n    private static ItemCallback<Short> shortSetItemCallback = new ItemCallback<Short>() {\n        @Override\n        public void handleItem(long containerPtr, Short item) {\n            nativeAddIntegerSetItem(containerPtr, item);\n        }\n    };\n\n    private static ItemCallback<Byte> byteSetItemCallback = new ItemCallback<Byte>() {\n        @Override\n        public void handleItem(long containerPtr, Byte item) {\n            nativeAddIntegerSetItem(containerPtr, item);\n        }\n    };\n\n    private static ItemCallback<Float> floatSetItemCallback = new ItemCallback<Float>() {\n        @Override\n        public void handleItem(long containerPtr, Float item) {\n            nativeAddFloatSetItem(containerPtr, item);\n        }\n    };\n\n    private static ItemCallback<Double> doubleSetItemCallback = new ItemCallback<Double>() {\n        @Override\n        public void handleItem(long containerPtr, Double item) {\n            nativeAddDoubleSetItem(containerPtr, item);\n        }\n    };\n\n    private static ItemCallback<byte[]> binarySetItemCallback = new ItemCallback<byte[]>() {\n        @Override\n        public void handleItem(long containerPtr, byte[] item) {\n            nativeAddByteArraySetItem(containerPtr, item);\n        }\n    };\n\n    private static ItemCallback<Date> dateSetItemCallback = new ItemCallback<Date>() {\n        @Override\n        public void handleItem(long containerPtr, Date item) {\n            nativeAddDateSetItem(containerPtr, item.getTime());\n        }\n    };\n\n    private static ItemCallback<Decimal128> decimal128SetItemCallback = new ItemCallback<Decimal128>() {\n        @Override\n        public void handleItem(long containerPtr, Decimal128 item) {\n            nativeAddDecimal128SetItem(containerPtr, item.getLow(), item.getHigh());\n        }\n    };\n\n    private static ItemCallback<ObjectId> objectIdSetItemCallback = new ItemCallback<ObjectId>() {\n        @Override\n        public void handleItem(long containerPtr, ObjectId item) {\n            nativeAddObjectIdSetItem(containerPtr, item.toString());\n        }\n    };\n\n    private static ItemCallback<UUID> uuidSetItemCallback = new ItemCallback<UUID>() {\n        @Override\n        public void handleItem(long containerPtr, UUID item) {\n            nativeAddUUIDSetItem(containerPtr, item.toString());\n        }\n    };\n\n    private static ItemCallback<RealmAny> realmAnySetItemCallback = new ItemCallback<RealmAny>() {\n        private final RealmAnyNativeFunctions realmAnyNativeFunctions = new RealmAnyNativeFunctionsImpl();\n\n        @Override\n        public void handleItem(long containerPtr, RealmAny item) {\n            realmAnyNativeFunctions.handleItem(containerPtr, item);\n        }\n    };\n\n    private static native long nativeStartSet(long size);\n\n    private static native void nativeStopSet(long builderPtr, long columnKey, long setPtr);\n\n    private static native void nativeAddNullSetItem(long setPtr);\n\n    private static native void nativeAddStringSetItem(long setPtr, String val);\n\n    private static native void nativeAddBooleanSetItem(long setPtr, boolean val);\n\n    private static native void nativeAddIntegerSetItem(long setPtr, long val);\n\n    private static native void nativeAddFloatSetItem(long setPtr, float val);\n\n    private static native void nativeAddDoubleSetItem(long setPtr, double val);\n\n    private static native void nativeAddByteArraySetItem(long setPtr, byte[] val);\n\n    private static native void nativeAddDateSetItem(long setPtr, long val);\n\n    private static native void nativeAddDecimal128SetItem(long setPtr, long lowVal, long highVal);\n\n    private static native void nativeAddObjectIdSetItem(long setPtr, String val);\n\n    private static native void nativeAddUUIDSetItem(long setPtr, String val);\n\n    private void addEmptySet(long columnKey) {\n        nativeStopSet(builderPtr, columnKey, nativeStartSet(0));\n    }\n\n    public void addStringSet(long columnKey, RealmSet<String> set) {\n        addSetItem(builderPtr, columnKey, set, stringSetItemCallback);\n    }\n\n    public void addBooleanSet(long columnKey, RealmSet<Boolean> set) {\n        addSetItem(builderPtr, columnKey, set, booleanSetItemCallback);\n    }\n\n    public void addIntegerSet(long columnKey, RealmSet<Integer> set) {\n        addSetItem(builderPtr, columnKey, set, integerSetItemCallback);\n    }\n\n    public void addLongSet(long columnKey, RealmSet<Long> set) {\n        addSetItem(builderPtr, columnKey, set, longSetItemCallback);\n    }\n\n    public void addShortSet(long columnKey, RealmSet<Short> set) {\n        addSetItem(builderPtr, columnKey, set, shortSetItemCallback);\n    }\n\n    public void addByteSet(long columnKey, RealmSet<Byte> set) {\n        addSetItem(builderPtr, columnKey, set, byteSetItemCallback);\n    }\n\n    public void addFloatSet(long columnKey, RealmSet<Float> set) {\n        addSetItem(builderPtr, columnKey, set, floatSetItemCallback);\n    }\n\n    public void addDoubleSet(long columnKey, RealmSet<Double> set) {\n        addSetItem(builderPtr, columnKey, set, doubleSetItemCallback);\n    }\n\n    public void addBinarySet(long columnKey, RealmSet<byte[]> set) {\n        addSetItem(builderPtr, columnKey, set, binarySetItemCallback);\n    }\n\n    public void addDateSet(long columnKey, RealmSet<Date> set) {\n        addSetItem(builderPtr, columnKey, set, dateSetItemCallback);\n    }\n\n    public void addDecimal128Set(long columnKey, RealmSet<Decimal128> set) {\n        addSetItem(builderPtr, columnKey, set, decimal128SetItemCallback);\n    }\n\n    public void addObjectIdSet(long columnKey, RealmSet<ObjectId> set) {\n        addSetItem(builderPtr, columnKey, set, objectIdSetItemCallback);\n    }\n\n    public void addUUIDSet(long columnKey, RealmSet<UUID> set) {\n        addSetItem(builderPtr, columnKey, set, uuidSetItemCallback);\n    }\n\n    public void addRealmAnySet(long columnKey, RealmSet<RealmAny> set) {\n        addSetItem(builderPtr, columnKey, set, realmAnySetItemCallback);\n    }\n\n    public <T extends RealmModel> void addObjectSet(long columnKey, @Nullable RealmSet<T> set) {\n        if (set != null) {\n            long setPtr = nativeStartSet(set.size());\n            for (T entry : set) {\n                if (entry == null) {\n                    throw new IllegalArgumentException(\"This 'RealmSet' is not nullable. A non-null value is expected.\");\n                } else {\n                    RealmObjectProxy realmObjectProxy = (RealmObjectProxy) entry;\n                    long objectPtr = ((UncheckedRow) realmObjectProxy.realmGet$proxyState().getRow$realm()).getNativePtr();\n                    nativeAddObjectListItem(setPtr, objectPtr);\n                }\n            }\n            nativeStopSet(builderPtr, columnKey, setPtr);\n        } else {\n            addEmptySet(columnKey);\n        }\n    }\n\n    private <T> void addSetItem(long builderPtr,\n                                long columnKey,\n                                @Nullable Set<T> set,\n                                ItemCallback<T> itemCallback) {\n        if (set != null) {\n            long setPtr = nativeStartSet(set.size());\n            boolean isNullable = (columnKey == 0) || table.isColumnNullable(columnKey);\n            for (T item : set) {\n                if (item == null) {\n                    if (!isNullable) {\n                        throw new IllegalArgumentException(\"This 'RealmSet' is not nullable. A non-null value is expected.\");\n                    }\n                    nativeAddNullSetItem(setPtr);\n                } else {\n                    itemCallback.handleItem(setPtr, item);\n                }\n            }\n            nativeStopSet(builderPtr, columnKey, setPtr);\n        } else {\n            addEmptySet(columnKey);\n        }\n    }\n\n    //--------------------------------------------------\n    //--------------------------------------------------\n\n    /**\n     * Updates any existing object if it exists, otherwise creates a new one.\n     * <p>\n     * Updating an existing object requires that the primary key is defined as one of the fields.\n     * <p>\n     * The builder is automatically closed after calling this method.\n     */\n    public void updateExistingTopLevelObject() {\n        try {\n            nativeCreateOrUpdateTopLevelObject(sharedRealmPtr, tablePtr, builderPtr, true, ignoreFieldsWithSameValue);\n        } finally {\n            close();\n        }\n    }\n\n    /**\n     * Updates an existing embedded object.\n     * <p>\n     * The builder is automatically closed after calling this method.\n     */\n    public void updateExistingEmbeddedObject(RealmObjectProxy embeddedObject) {\n        try {\n            long objKey = embeddedObject.realmGet$proxyState().getRow$realm().getObjectKey();\n            nativeUpdateEmbeddedObject(sharedRealmPtr, tablePtr, builderPtr, objKey, ignoreFieldsWithSameValue);\n        } finally {\n            close();\n        }\n    }\n\n    /**\n     * Create a new object.\n     * <p>\n     * The builder is automatically closed after calling this method.\n     */\n    public UncheckedRow createNewObject() {\n        UncheckedRow row;\n        try {\n            long rowPtr = nativeCreateOrUpdateTopLevelObject(sharedRealmPtr, tablePtr, builderPtr, false, false);\n            row = new UncheckedRow(context, table, rowPtr);\n        } finally {\n            close();\n        }\n        return row;\n    }\n\n    /**\n     * Returns the underlying native pointer representing this builder.\n     */\n    public long getNativePtr() {\n        return builderPtr;\n    }\n\n    /**\n     * Manually closes the underlying Builder\n     */\n    @Override\n    public void close() {\n        nativeDestroyBuilder(builderPtr);\n    }\n\n    private interface ItemCallback<T> {\n        void handleItem(long containerPtr, T item);\n    }\n\n    private static native long nativeCreateBuilder();\n\n    private static native void nativeDestroyBuilder(long builderPtr);\n\n    private static native long nativeCreateOrUpdateTopLevelObject(long sharedRealmPtr,\n                                                                  long tablePtr,\n                                                                  long builderPtr,\n                                                                  boolean updateExistingObject,\n                                                                  boolean ignoreFieldsWithSameValue);\n\n    private static native long nativeUpdateEmbeddedObject(long sharedRealmPtr,\n                                                          long tablePtr,\n                                                          long builderPtr,\n                                                          long objKey,\n                                                          boolean ignoreFieldsWithSameValue);\n\n    // Add simple properties\n    private static native void nativeAddNull(long builderPtr, long columnKey);\n\n    private static native void nativeAddInteger(long builderPtr, long columnKey, long val);\n\n    private static native void nativeAddString(long builderPtr, long columnKey, String val);\n\n    private static native void nativeAddFloat(long builderPtr, long columnKey, float val);\n\n    private static native void nativeAddDouble(long builderPtr, long columnKey, double val);\n\n    private static native void nativeAddBoolean(long builderPtr, long columnKey, boolean val);\n\n    private static native void nativeAddByteArray(long builderPtr, long columnKey, byte[] val);\n\n    private static native void nativeAddDate(long builderPtr, long columnKey, long val);\n\n    private static native void nativeAddObject(long builderPtr, long columnKey, long rowPtr);\n\n    private static native void nativeAddDecimal128(long builderPtr, long columnKey, long low, long high);\n\n    private static native void nativeAddObjectId(long builderPtr, long columnKey, String data);\n\n    private static native void nativeAddUUID(long builderPtr, long columnKey, String data);\n\n    private static native void nativeAddRealmAny(long builderPtr, long columnKey, long realmAnyPtr);\n\n    // Methods for adding lists\n    // Lists sent across JNI one element at a time\n    private static native long nativeStartList(long size);\n\n    private static native void nativeStopList(long builderPtr, long columnKey, long listPtr);\n\n    private static native void nativeAddNullListItem(long listPtr);\n\n    private static native void nativeAddIntegerListItem(long listPtr, long value);\n\n    private static native void nativeAddStringListItem(long listPtr, String val);\n\n    private static native void nativeAddFloatListItem(long listPtr, float val);\n\n    private static native void nativeAddDoubleListItem(long listPtr, double val);\n\n    private static native void nativeAddBooleanListItem(long listPtr, boolean val);\n\n    private static native void nativeAddByteArrayListItem(long listPtr, byte[] val);\n\n    private static native void nativeAddDateListItem(long listPtr, long val);\n\n    private static native void nativeAddDecimal128ListItem(long listPtr, long low, long high);\n\n    private static native void nativeAddObjectIdListItem(long listPtr, String data);\n\n    private static native void nativeAddUUIDListItem(long listPtr, String data);\n\n    public static native void nativeAddRealmAnyListItem(long listPtr, long realmAnyPtr);\n\n    private static native void nativeAddObjectListItem(long listPtr, long rowPtr);\n\n    private static native void nativeAddObjectList(long builderPtr, long columnKey, long[] rowPtrs);\n\n    // dictionaries\n    private static native long nativeStartDictionary();\n\n    private static native void nativeStopDictionary(long builderPtr, long columnKey, long dictionaryPtr);\n\n    private static native void nativeAddNullDictionaryEntry(long dictionaryPtr, String key);\n\n    private static native void nativeAddBooleanDictionaryEntry(long dictionaryPtr, String key, boolean value);\n\n    private static native void nativeAddStringDictionaryEntry(long dictionaryPtr, String key, String value);\n\n    private static native void nativeAddIntegerDictionaryEntry(long dictionaryPtr, String key, long value);\n\n    private static native void nativeAddDoubleDictionaryEntry(long dictionaryPtr, String key, double value);\n\n    private static native void nativeAddFloatDictionaryEntry(long dictionaryPtr, String key, float value);\n\n    private static native void nativeAddBinaryDictionaryEntry(long dictionaryPtr, String key, byte[] value);\n\n    private static native void nativeAddDateDictionaryEntry(long dictionaryPtr, String key, long value);\n\n    private static native void nativeAddDecimal128DictionaryEntry(long dictionaryPtr, String key, long high, long low);\n\n    private static native void nativeAddObjectIdDictionaryEntry(long dictionaryPtr, String key, String value);\n\n    private static native void nativeAddUUIDDictionaryEntry(long dictionaryPtr, String key, String value);\n\n    private static native void nativeAddObjectDictionaryEntry(long dictionaryPtr, String key, long rowPtr);\n\n    public static native void nativeAddRealmAnyDictionaryEntry(long dictionaryPtr, String key, long realmAnyPtr);\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/internal/objectstore/OsSubscription.java",
    "content": "/*\n * Copyright 2022 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 */\npackage io.realm.internal.objectstore;\n\nimport java.util.Date;\n\nimport io.realm.internal.NativeObject;\nimport io.realm.internal.annotations.ObjectServer;\nimport io.realm.mongodb.sync.Subscription;\n\n@ObjectServer\npublic class OsSubscription implements NativeObject, Subscription {\n\n    private static final long nativeFinalizerPtr = nativeGetFinalizerMethodPtr();\n    private final long nativePtr;\n\n    public OsSubscription(long nativePtr) {\n        this.nativePtr = nativePtr;\n    }\n\n    @Override\n    public long getNativePtr() {\n        return this.nativePtr;\n    }\n\n    @Override\n    public long getNativeFinalizerPtr() {\n        return nativeFinalizerPtr;\n    }\n\n    @Override\n    public Date getCreatedAt() {\n        return new Date(nativeCreatedAt(nativePtr));\n    }\n\n    @Override\n    public Date getUpdatedAt() {\n        return new Date(nativeUpdatedAt(nativePtr));\n    }\n\n    @Override\n    public String getName() {\n        return nativeName(nativePtr);\n    }\n\n    @Override\n    public String getObjectType() {\n        return nativeObjectClassName(nativePtr);\n    }\n\n    @Override\n    public String getQuery() {\n        return nativeQueryString(nativePtr);\n    }\n\n    private static native long nativeGetFinalizerMethodPtr();\n    private static native String nativeName(long nativePtr);\n    private static native String nativeObjectClassName(long nativePtr);\n    private static native String nativeQueryString(long nativePtr);\n    private static native long nativeCreatedAt(long nativePtr);\n    private static native long nativeUpdatedAt(long nativePtr);\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/internal/objectstore/OsSubscriptionSet.java",
    "content": "/*\n * Copyright 2022 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 */\npackage io.realm.internal.objectstore;\n\nimport android.os.Handler;\nimport android.os.Looper;\n\nimport java.util.Iterator;\nimport java.util.NoSuchElementException;\nimport java.util.concurrent.CountDownLatch;\nimport java.util.concurrent.Future;\nimport java.util.concurrent.TimeUnit;\nimport java.util.concurrent.atomic.AtomicBoolean;\n\nimport javax.annotation.Nullable;\n\nimport io.realm.RealmAsyncTask;\nimport io.realm.RealmQuery;\nimport io.realm.internal.NativeObject;\nimport io.realm.internal.RealmProxyMediator;\nimport io.realm.internal.annotations.ObjectServer;\nimport io.realm.internal.async.RealmAsyncTaskImpl;\nimport io.realm.internal.async.RealmThreadPoolExecutor;\nimport io.realm.mongodb.sync.Subscription;\nimport io.realm.mongodb.sync.SubscriptionSet;\n\n@ObjectServer\npublic class OsSubscriptionSet implements NativeObject, SubscriptionSet {\n\n    public static final byte STATE_VALUE_UNCOMMITTED = 0;\n    public static final byte STATE_VALUE_PENDING = 1;\n    public static final byte STATE_VALUE_BOOTSTRAPPING = 2;\n    public static final byte STATE_VALUE_COMPLETE = 3;\n    public static final byte STATE_VALUE_ERROR = 4;\n    public static final byte STATE_VALUE_SUPERSEDED = 5;\n    public static final byte STATE_VALUE_AWAITING_MARK = 6;\n\n    private static final long nativeFinalizerPtr = nativeGetFinalizerMethodPtr();\n    protected final RealmProxyMediator schema;\n    private final RealmThreadPoolExecutor stateListenerExecutor;\n    private final RealmThreadPoolExecutor updateExecutor;\n    private long nativePtr;\n    private Handler mainHandler = new Handler(Looper.getMainLooper());\n\n    public OsSubscriptionSet(long nativePtr, RealmProxyMediator schema, RealmThreadPoolExecutor listenerExecutor, RealmThreadPoolExecutor writeExecutor) {\n        this.nativePtr = nativePtr;\n        this.schema = schema;\n        this.stateListenerExecutor = listenerExecutor;\n        this.updateExecutor= writeExecutor;\n    }\n\n    @Override\n    public long getNativePtr() {\n        return this.nativePtr;\n    }\n\n    @Override\n    public long getNativeFinalizerPtr() {\n        return nativeFinalizerPtr;\n    }\n\n    @Nullable\n    @Override\n    public Subscription find(RealmQuery query) {\n        long subscriptionPtr = nativeFindByQuery(nativePtr, query.getQueryPointer());\n        if (subscriptionPtr != -1) {\n            return new OsSubscription(subscriptionPtr);\n        } else {\n            return null;\n        }\n    }\n\n    @Nullable\n    @Override\n    public Subscription find(String name) {\n        long subscriptionPtr = nativeFindByName(nativePtr, name);\n        if (subscriptionPtr != -1) {\n            return new OsSubscription(subscriptionPtr);\n        } else {\n            return null;\n        }\n    }\n\n    @Override\n    public SubscriptionSet.State getState() {\n        byte value = nativeState(nativePtr);\n        return SubscriptionSet.State.fromNativeValue(value);\n    }\n\n    @Override\n    public int size() {\n        return (int) nativeSize(nativePtr);\n    }\n\n    @Override\n    public String getErrorMessage() {\n        return nativeErrorMessage(nativePtr);\n    }\n\n    @Override\n    public boolean waitForSynchronization() {\n        return waitForSynchronization(Long.MAX_VALUE, TimeUnit.SECONDS);\n    }\n\n    @Override\n    public boolean waitForSynchronization(Long timeOut, TimeUnit unit) {\n        CountDownLatch latch = new CountDownLatch(1);\n        AtomicBoolean success = new AtomicBoolean(false);\n        nativeWaitForSynchronization(nativePtr, new StateChangeCallback() {\n            @Override\n            public void onChange(byte state) {\n                success.set(State.fromNativeValue(state) == State.COMPLETE);\n                latch.countDown();\n            }\n        });\n        try {\n            if (!latch.await(timeOut, unit)) {\n                throw new RuntimeException(\"Waiting for waitForSynchronization() timed out.\");\n            }\n        } catch (InterruptedException e) {\n            throw new RuntimeException(\"Waiting for waitForSynchronization() was interrupted.\");\n        }\n        refresh();\n        return success.get();\n    }\n\n    @Override\n    public RealmAsyncTask waitForSynchronizationAsync(SubscriptionSet.StateChangeCallback callback) {\n        return waitForSynchronizationAsync(Long.MAX_VALUE, TimeUnit.SECONDS, callback);\n    }\n\n    @Override\n    public RealmAsyncTask waitForSynchronizationAsync(Long timeOut, TimeUnit unit, SubscriptionSet.StateChangeCallback callback) {\n        Future<?> future = stateListenerExecutor.submit(new Runnable() {\n            @Override\n            public void run() {\n                try {\n                    waitForSynchronization(timeOut, unit);\n                    mainHandler.post(new Runnable() {\n                        @Override\n                        public void run() {\n                            callback.onStateChange(OsSubscriptionSet.this);\n                        }\n                    });\n                } catch (Exception e) {\n                    mainHandler.post(new Runnable() {\n                        @Override\n                        public void run() {\n                            callback.onError(e);\n                        }\n                    });\n                }\n            }\n        });\n        return new RealmAsyncTaskImpl(future, stateListenerExecutor);\n    }\n\n    @Override\n    public SubscriptionSet update(UpdateCallback action) {\n        OsMutableSubscriptionSet mutableSubs = new OsMutableSubscriptionSet(\n                nativeCreateMutableSubscriptionSet(nativePtr),\n                schema,\n                stateListenerExecutor,\n                updateExecutor\n        );\n        action.update(mutableSubs);\n        long newSubscriptionsSet = mutableSubs.commit();\n        // Once commit succeed, replace the current SubscriptionSet pointer with\n        // the new one. If the commit fails, the MutableSubscriptionSet will be\n        // GC'ed and released and the SubscriptionSet will keep the state before\n        // the UpdateCallback was called.\n        long oldPointer = nativePtr;\n        nativePtr = newSubscriptionsSet;\n        nativeRelease(oldPointer);\n        return this;\n    }\n\n    @Override\n    public RealmAsyncTask updateAsync(UpdateAsyncCallback callback) {\n        Future<?> future = updateExecutor.submit(new Runnable() {\n            @Override\n            public void run() {\n                try {\n                    SubscriptionSet updatedSubscriptions = update(callback);\n                    mainHandler.post(new Runnable() {\n                        @Override\n                        public void run() {\n                            callback.onSuccess(updatedSubscriptions);\n                        }\n                    });\n                } catch (Throwable exception) {\n                    mainHandler.post(new Runnable() {\n                        @Override\n                        public void run() {\n                            callback.onError(exception);\n                        }\n                    });\n                }\n            }\n        });\n        return new RealmAsyncTaskImpl(future, updateExecutor);\n    }\n\n    public void refresh() {\n        nativeRefresh(nativePtr);\n    }\n\n    @Override\n    public Iterator<Subscription> iterator() {\n        // This iterator does not support removals.\n        return new Iterator<Subscription>() {\n            private int cursor = 0;\n            private final int size = size();\n\n            @Override\n            public boolean hasNext() {\n                return (cursor < size);\n            }\n\n            @Override\n            public Subscription next() {\n                if (cursor >= size) {\n                    throw new NoSuchElementException(\"Iterator has no more elements. \" +\n                            \"Tried index \" + cursor + \". Size is \" + size + \".\");\n                }\n                long subscriptionPtr = nativeSubscriptionAt(nativePtr, cursor);\n                cursor++;\n                return new OsSubscription(subscriptionPtr);\n            }\n        };\n    }\n\n    private interface StateChangeCallback {\n        void onChange(byte state); // Must not throw\n    }\n\n    private static native long nativeGetFinalizerMethodPtr();\n    private static native void nativeRelease(long nativePtr);\n    private static native long nativeSize(long nativePtr);\n    private static native byte nativeState(long nativePtr);\n    private static native String nativeErrorMessage(long nativePtr);\n    private static native long nativeCreateMutableSubscriptionSet(long nativePtr);\n    private static native long nativeSubscriptionAt(long nativePtr, int index);\n    private static native void nativeWaitForSynchronization(long nativePtr, StateChangeCallback callback);\n    private static native long nativeFindByName(long nativePtr, String name);\n    private static native long nativeFindByQuery(long nativePtr, long queryPtr);\n    private static native void nativeRefresh(long nativePtr);\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/internal/package-info.java",
    "content": "/*\n * Copyright 2017 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@javax.annotation.ParametersAreNonnullByDefault\npackage io.realm.internal;\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/internal/util/Pair.java",
    "content": "/*\n * Copyright (C) 2009 The Android Open Source Project\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\npackage io.realm.internal.util;\n\n/**\n * Container to ease passing around a tuple of two objects. This object provides a sensible\n * implementation of equals(), returning true if equals() is true on each of the contained\n * objects.\n */\npublic class Pair<F, S> {\n    /**\n     * Implementation notes:\n     *\n     * Copy from the Android framework to avoid the dependency on Android classes + slight adjustment\n     * to support older versions of Android.\n     *\n     * Original source: https://android.googlesource.com/platform/frameworks/base/+/master/core/java/android/util/Pair.java\n     */\n    public F first;\n    public S second;\n\n    /**\n     * Constructor for a Pair.\n     *\n     * @param first the first object in the Pair.\n     * @param second the second object in the pair.\n     */\n    public Pair(F first, S second) {\n        this.first = first;\n        this.second = second;\n    }\n\n    /**\n     * Checks the two objects for equality by delegating to their respective\n     * {@link Object#equals(Object)} methods.\n     *\n     * @param o the {@link Pair} to which this one is to be checked for equality.\n     * @return true if the underlying objects of the Pair are both considered\n     *         equal.\n     */\n    @Override\n    public boolean equals(Object o) {\n        if (!(o instanceof Pair)) {\n            return false;\n        }\n        Pair<?, ?> p = (Pair<?, ?>) o;\n        return equals(p.first, first) && (equals(p.second, second));\n    }\n\n    private boolean equals(Object a, Object b) {\n        return (a == b) || (a != null && a.equals(b));\n    }\n\n    /**\n     * Compute a hash code using the hash codes of the underlying objects.\n     *\n     * @return a hashcode of the Pair.\n     */\n    @Override\n    public int hashCode() {\n        return (first == null ? 0 : first.hashCode()) ^ (second == null ? 0 : second.hashCode());\n    }\n\n    @Override\n    public String toString() {\n        return \"Pair{\" + String.valueOf(first) + \" \" + String.valueOf(second) + \"}\";\n    }\n\n    /**\n     * Convenience method for creating an appropriately typed pair.\n     *\n     * @param a the first object in the Pair.\n     * @param b the second object in the pair.\n     * @return a Pair that is templatized with the types of a and b.\n     */\n    public static <A, B> Pair <A, B> create(A a, B b) {\n        return new Pair<>(a, b);\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/log/LogLevel.java",
    "content": "/*\n * Copyright 2016 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\npackage io.realm.log;\n\n/**\n * The Log levels defined and used by Realm when logging events in the API.\n * <p>\n * Realm uses the log levels defined by Log4J:\n * https://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/Level.html\n *\n * @see RealmLog#add(RealmLogger)\n */\npublic class LogLevel {\n\n    /**\n     * Not implemented. It forces javac to generate the JNI header file for this class.\n     */\n    @SuppressWarnings(\"unused\")\n    private native void forceJNIHeaderGeneration();\n\n    /**\n     * The ALL has the lowest possible rank and is intended to turn on all logging.\n     */\n    public static final int ALL = 1;\n\n    /**\n     * The TRACE level designates finer-grained informational events than DEBUG.\n     */\n    public static final int TRACE = 2;\n\n    /**\n     * The DEBUG level designates fine-grained informational events that are mostly useful to debug an application.\n     */\n    public static final int DEBUG = 3;\n\n    /**\n     * The INFO level designates informational messages that highlight the progress of the application at\n     * coarse-grained level.\n     */\n    public static final int INFO = 4;\n\n    /**\n     * The WARN level designates potentially harmful situations.\n     */\n    public static final int WARN = 5;\n\n    /**\n     * The ERROR level designates error events that might still allow the application to continue running.\n     */\n    public static final int ERROR = 6;\n\n    /**\n     * The FATAL level designates very severe error events that will presumably lead the application to abort.\n     */\n    public static final int FATAL = 7;\n\n    /**\n     * The OFF has the highest possible rank and is intended to turn off logging.\n     */\n    public static final int OFF = 8;\n}\n\n\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/log/RealmLog.java",
    "content": "/*\n * Copyright 2016 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\npackage io.realm.log;\n\nimport android.util.Log;\n\nimport java.util.Locale;\n\nimport javax.annotation.Nullable;\n\n\n/**\n * Global logger used by all Realm components.\n * Custom loggers can be added by registering classes implementing {@link RealmLogger}.\n */\npublic final class RealmLog {\n\n    @SuppressWarnings(\"FieldCanBeLocal\")\n    private static String REALM_JAVA_TAG = \"REALM_JAVA\";\n\n    /**\n     * Adds a logger implementation that will be notified on log events.\n     *\n     * @param logger the reference to a {@link RealmLogger} implementation.\n     */\n    public static void add(RealmLogger logger) {\n        //noinspection ConstantConditions\n        if (logger == null) {\n            throw new IllegalArgumentException(\"A non-null logger has to be provided\");\n        }\n        nativeAddLogger(logger);\n    }\n\n    /**\n     * Sets the current {@link LogLevel}. Setting this will affect all registered loggers.\n     *\n     * @param level see {@link LogLevel}.\n     */\n    public static void setLevel(int level) {\n        if (level < LogLevel.ALL || level > LogLevel.OFF) {\n            throw new IllegalArgumentException(\"Invalid log level: \" + level);\n        }\n        nativeSetLogLevel(level);\n    }\n\n    /**\n     * Get the current {@link LogLevel}.\n     *\n     * @return the current {@link LogLevel}.\n     */\n    public static int getLevel() {\n        return nativeGetLogLevel();\n    }\n\n    /**\n     * Removes the given logger if it is currently added.\n     *\n     * @return {@code true} if the logger was removed, {@code false} otherwise.\n     */\n    public static boolean remove(RealmLogger logger) {\n        //noinspection ConstantConditions\n        if (logger == null) {\n            throw new IllegalArgumentException(\"A non-null logger has to be provided\");\n        }\n        nativeRemoveLogger(logger);\n        return true;\n    }\n\n    /**\n     * Removes all loggers. The default native logger will be removed as well. Use {@link #registerDefaultLogger()} to\n     * add it back.\n     */\n    public static void clear() {\n        nativeClearLoggers();\n    }\n\n    /**\n     * Adds default native logger if it has been removed before. If the default logger has been registered already,\n     * it won't be added again. The default logger on Android will log to logcat.\n     */\n    public static void registerDefaultLogger() {\n        nativeRegisterDefaultLogger();\n    }\n\n    /**\n     * Logs a {@link LogLevel#TRACE} exception.\n     *\n     * @param throwable exception to log.\n     */\n    public static void trace(Throwable throwable) {\n        trace(throwable, null);\n    }\n\n    /**\n     * Logs a {@link LogLevel#TRACE} event.\n     *\n     * @param message message to log.\n     * @param args optional args used to format the message using {@link String#format(String, Object...)}.\n     */\n    public static void trace(String message, Object... args) {\n        trace(null, message, args);\n    }\n\n    /**\n     * Logs a {@link LogLevel#TRACE} event.\n     *\n     * @param throwable optional exception to log.\n     * @param message optional message.\n     * @param args optional args used to format the message using {@link String#format(String, Object...)}.\n     */\n    public static void trace(@Nullable Throwable throwable, @Nullable String message, Object... args) {\n        log(LogLevel.TRACE, throwable, message, args);\n    }\n\n    /**\n     * Logs a {@link LogLevel#DEBUG} exception.\n     *\n     * @param throwable exception to log.\n     */\n    public static void debug(@Nullable Throwable throwable) {\n        debug(throwable, null);\n    }\n\n    /**\n     * Logs a {@link LogLevel#DEBUG} event.\n     *\n     * @param message message to log.\n     * @param args optional args used to format the message using {@link String#format(String, Object...)}.\n     */\n    public static void debug(String message, Object... args) {\n        debug(null, message, args);\n    }\n\n    /**\n     * Logs a {@link LogLevel#DEBUG} event.\n     *\n     * @param throwable optional exception to log.\n     * @param message optional message.\n     * @param args optional args used to format the message using {@link String#format(String, Object...)}.\n     */\n    public static void debug(@Nullable Throwable throwable, @Nullable String message, Object... args) {\n        log(LogLevel.DEBUG, throwable, message, args);\n    }\n\n    /**\n     * Logs an {@link LogLevel#INFO} exception.\n     *\n     * @param throwable exception to log.\n     */\n    public static void info(Throwable throwable) {\n        info(throwable, null);\n    }\n\n    /**\n     * Logs an {@link LogLevel#INFO} event.\n     *\n     * @param message message to log.\n     * @param args optional args used to format the message using {@link String#format(String, Object...)}.\n     */\n    public static void info(String message, Object... args) {\n        info(null, message, args);\n    }\n\n    /**\n     * Logs an {@link LogLevel#INFO} event.\n     *\n     * @param throwable optional exception to log.\n     * @param message optional message.\n     * @param args optional args used to format the message using {@link String#format(String, Object...)}.\n     */\n    public static void info(@Nullable Throwable throwable, @Nullable String message, Object... args) {\n        log(LogLevel.INFO, throwable, message, args);\n    }\n\n    /**\n     * Logs a {@link LogLevel#WARN} exception.\n     *\n     * @param throwable exception to log.\n     */\n    public static void warn(Throwable throwable) {\n        warn(throwable, null);\n    }\n\n    /**\n     * Logs a {@link LogLevel#WARN} event.\n     *\n     * @param message message to log.\n     * @param args optional args used to format the message using {@link String#format(String, Object...)}.\n     */\n    public static void warn(String message, Object... args) {\n        warn(null, message, args);\n    }\n\n    /**\n     * Logs a {@link LogLevel#WARN} event.\n     *\n     * @param throwable optional exception to log.\n     * @param message optional message.\n     * @param args optional args used to format the message using {@link String#format(String, Object...)}.\n     */\n    public static void warn(@Nullable Throwable throwable, @Nullable String message, Object... args) {\n        log(LogLevel.WARN, throwable, message, args);\n    }\n\n    /**\n     * Logs an {@link LogLevel#ERROR} exception.\n     *\n     * @param throwable exception to log.\n     */\n    public static void error(Throwable throwable) {\n        error(throwable, null);\n    }\n\n    /**\n     * Logs an {@link LogLevel#ERROR} event.\n     *\n     * @param message message to log.\n     * @param args optional args used to format the message using {@link String#format(String, Object...)}.\n     */\n    public static void error(String message, Object... args) {\n        error(null, message, args);\n    }\n\n    /**\n     * Logs an {@link LogLevel#ERROR} event.\n     *\n     * @param throwable optional exception to log.\n     * @param message optional message.\n     * @param args optional args used to format the message using {@link String#format(String, Object...)}.\n     */\n    public static void error(@Nullable Throwable throwable, @Nullable String message, Object... args) {\n        log(LogLevel.ERROR, throwable, message, args);\n    }\n\n    /**\n     * Logs a {@link LogLevel#FATAL} exception.\n     *\n     * @param throwable exception to log.\n     */\n    public static void fatal(Throwable throwable) {\n        fatal(throwable, null);\n    }\n\n    /**\n     * Logs an {@link LogLevel#FATAL} event.\n     *\n     * @param message message to log.\n     * @param args optional args used to format the message using {@link String#format(String, Object...)}.\n     */\n    public static void fatal(String message, Object... args) {\n        fatal(null, message, args);\n    }\n\n    /**\n     * Logs a {@link LogLevel#FATAL} event.\n     *\n     * @param throwable optional exception to log.\n     * @param message optional message.\n     * @param args optional args used to format the message using {@link String#format(String, Object...)}.\n     */\n    public static void fatal(@Nullable Throwable throwable, @Nullable String message, Object... args) {\n        log(LogLevel.FATAL, throwable, message, args);\n    }\n\n    // Formats the message, parses the stacktrace of given throwable and passes them to nativeLog.\n    private static void log(int level, @Nullable Throwable throwable, @Nullable String message, @Nullable Object... args) {\n        if (level < getLevel()) {\n            return;\n        }\n\n        StringBuilder stringBuilder = new StringBuilder();\n        if (message != null && args != null && args.length > 0) {\n            message = String.format(Locale.US, message, args);\n        }\n        if (throwable != null) {\n            stringBuilder.append(Log.getStackTraceString(throwable));\n        }\n        if (message != null) {\n            if (throwable != null) {\n                stringBuilder.append(\"\\n\");\n            }\n            stringBuilder.append(message);\n        }\n        nativeLog(level, REALM_JAVA_TAG, throwable, stringBuilder.toString());\n    }\n\n    private static native void nativeAddLogger(RealmLogger logger);\n\n    private static native void nativeRemoveLogger(RealmLogger logger);\n\n    private static native void nativeClearLoggers();\n\n    private static native void nativeRegisterDefaultLogger();\n\n    private static native void nativeLog(int level, String tag, @Nullable Throwable throwable, @Nullable String message);\n\n    private static native void nativeSetLogLevel(int level);\n\n    private static native int nativeGetLogLevel();\n\n    // Methods below are used for testing core logger bridge only.\n    static native long nativeCreateCoreLoggerBridge(@SuppressWarnings(\"SameParameterValue\") String tag);\n\n    static native void nativeCloseCoreLoggerBridge(long nativePtr);\n\n    static native void nativeLogToCoreLoggerBridge(long nativePtr, int level, String message);\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/log/RealmLogger.java",
    "content": "/*\n * Copyright 2016 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\npackage io.realm.log;\n\nimport javax.annotation.Nullable;\n\nimport io.realm.internal.Keep;\n\n\n/**\n * Interface for custom loggers that can be registered at {@link RealmLog#add(RealmLogger)}.\n * The different log levels are described in {@link LogLevel}.\n */\n@Keep // This interface is used as a parameter type of a native method in OsSharedRealm.java\npublic interface RealmLogger {\n\n    /**\n     * Handles a log event.\n     *\n     * @param level for this log event. It can only be a value between {@link LogLevel#TRACE} and\n     * {@link LogLevel#FATAL}\n     * @param tag for this log event.\n     * @param throwable optional exception to log.\n     * @param message optional additional message.\n     */\n    void log(int level, String tag, @Nullable Throwable throwable, @Nullable String message);\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/log/package-info.java",
    "content": "/*\n * Copyright 2017 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@javax.annotation.ParametersAreNonnullByDefault\npackage io.realm.log;\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/mongodb/sync/MutableSubscriptionSet.java",
    "content": "package io.realm.mongodb.sync;\n\nimport io.realm.RealmModel;\nimport io.realm.RealmQuery;\nimport io.realm.annotations.Beta;\nimport io.realm.internal.annotations.ObjectServer;\n\n/**\n * A mutable subscription set is available when calling {@link SubscriptionSet#update(UpdateCallback)}\n *\n * This is the only way to modify a {@link SubscriptionSet}.\n *\n * {@link Subscription}s can be either <i>managed</i> or <i>unmanaged</i>. Unmanaged subscriptions\n * are those created by using {@link Subscription#create(RealmQuery)} or\n * {@link Subscription#create(String, RealmQuery)}, while managed subscriptions are the ones being\n * returned from the subscription set.\n *\n * @see SubscriptionSet for more information about subscription sets and flexible sync.\n */\n@ObjectServer\n@Beta\npublic interface MutableSubscriptionSet extends SubscriptionSet {\n\n    /**\n     * Adds a new unmanaged subscription to the subscription set.\n     *\n     * @param subscription unmanaged subscription to add.\n     * @return the newly added managed subscription.\n     * @throws IllegalArgumentException if a subscription matching the provided one already exists.\n     */\n     Subscription add(Subscription subscription);\n\n    /**\n     * Add a new subscription or update an existing named subscription. It isn't possible to update\n     * an anonymous subscription. These must removed and re-inserted.\n     *\n     * @param subscription anonymous or named subscription created via {@code Subscription.create(...)},\n     *                     used to update a matching one within a specific set. It creates a new\n     *                     one in case there is no match..\n     * @return the updated or inserted managed subscription.\n     */\n    Subscription addOrUpdate(Subscription subscription);\n\n    /**\n     * Remove a managed subscription.\n     *\n     * @param subscription managed subscription to remove\n     * @return {@code true} if the subscription was removed, {@code false} if not.\n     * @throws IllegalArgumentException if the subscription provided is unmanaged. Only managed\n     * subscriptions can be used as input.\n     */\n    boolean remove(Subscription subscription);\n\n    /**\n     * Remove a named subscription.\n     *\n     * @param name name of managed subscription to remove.\n     * @return {@code true} if the subscription was removed, {@code false} if not.\n     */\n    boolean remove(String name);\n\n    /**\n     * Remove all subscriptions on a given {@link Subscription#getObjectType()}.\n     *\n     * @param objectType subscriptions on this object type will be removed.\n     * @return {@code true} if 1 or more subscriptions were removed, {@code false} if no\n     * subscriptions were removed.\n     */\n    boolean removeAll(String objectType);\n\n    /**\n     * Remove all subscriptions with queries on a given given model class.\n     *\n     * @param clazz subscriptions on this type will be removed.\n     * @return {@code true} if 1 or more subscriptions were removed, {@code false} if no\n     * subscriptions were removed.\n     */\n    <T extends RealmModel> boolean removeAll(Class<T> clazz);\n\n    /**\n     * Remove all current managed subscriptions.\n     *\n     * @return {@code true} if 1 or more subscriptions were removed, {@code false} if no\n     * subscriptions were removed.\n     */\n    boolean removeAll();\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/mongodb/sync/Subscription.java",
    "content": "package io.realm.mongodb.sync;\n\nimport java.util.Date;\n\nimport javax.annotation.Nullable;\n\nimport io.realm.RealmQuery;\nimport io.realm.annotations.Beta;\nimport io.realm.internal.Util;\nimport io.realm.internal.annotations.ObjectServer;\nimport io.realm.internal.UnmanagedSubscription;\n\n/**\n * A subscription defines a specific server query and its metadata. The result of this query\n * is continuously being synchronized with the device as long as the subscription is part of a\n * {@link SubscriptionSet} with a state of {@link SubscriptionSet.State#COMPLETE}.\n *\n * Subscriptions are immutable once created, but they can be updated by using a\n * {@link MutableSubscriptionSet#addOrUpdate(Subscription)}.\n */\n@ObjectServer\n@Beta\npublic interface Subscription {\n\n    /**\n     * Create an unmanaged named subscription for a flexible sync enabled Realm.\n     * The subscription will not take effect until it has been stored using either\n     * {@link MutableSubscriptionSet#add(Subscription)} or\n     * {@link MutableSubscriptionSet#addOrUpdate(Subscription)}.\n     *\n     * @param name the name of the subscription\n     * @param query the query that is subscribed to. Note, subscription queries have\n     *              restrictions compared to normal queries.\n     * @return the unmanaged subscription.\n     */\n    static Subscription create(String name, RealmQuery query) {\n        Util.checkEmpty(name, \"name\");\n        return new UnmanagedSubscription(name, query);\n    }\n\n    /**\n     * Create an unmanaged anonymous subscription for a flexible sync enabled Realm.\n     * The subscription will not take effect until it has been stored using either\n     * {@link MutableSubscriptionSet#add(Subscription)} or\n     * {@link MutableSubscriptionSet#addOrUpdate(Subscription)}.\n     *\n     * @param query the query that is subscribed to. Note, subscription queries have\n     *              restrictions compared to normal queries.\n     * @return the unmanaged subscription.\n     */\n    static Subscription create(RealmQuery query) {\n        return new UnmanagedSubscription(null, query);\n    }\n\n    /**\n     * Returns the timestamp for when this subscription was persisted. This will\n     * return {@code null} until the Subscription has been added using either\n     * {@link MutableSubscriptionSet#add(Subscription)} or\n     * {@link MutableSubscriptionSet#addOrUpdate(Subscription)}.\n     *\n     * @return the time this subscription was persisted, or {@code null} if the\n     * subscription hasn't been persisted yet.\n     */\n    @Nullable\n    Date getCreatedAt();\n\n    /**\n     * Returns the timestamp for when a persisted subscription was updated. This will\n     * return {@code null} until the Subscription has been added using either\n     * {@link MutableSubscriptionSet#add(Subscription)} or\n     * {@link MutableSubscriptionSet#addOrUpdate(Subscription)}.\n     *\n     * @return the time this subscription was updated, or {@code null} if the\n     * subscription hasn't been persisted yet.\n     */\n    @Nullable\n    Date getUpdatedAt();\n\n    /**\n     * Returns the name of subscription or {@code null} if no name was defined.\n     *\n     * @return the name of the subscription.\n     */\n    @Nullable\n    String getName();\n\n    /**\n     * Returns the type that is being queried.\n     *\n     * @return the type that is being queried.\n     */\n    String getObjectType();\n\n    /**\n     * Returns the subscription query that is running on objects of type\n     * {@link #getObjectType()}.\n     *\n     * @return the query covered by this subscription.\n     */\n    String getQuery();\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/mongodb/sync/SubscriptionSet.java",
    "content": "package io.realm.mongodb.sync;\n\nimport java.util.concurrent.TimeUnit;\n\nimport javax.annotation.Nullable;\n\nimport io.realm.Realm;\nimport io.realm.RealmAsyncTask;\nimport io.realm.RealmQuery;\nimport io.realm.annotations.Beta;\nimport io.realm.internal.Keep;\nimport io.realm.internal.annotations.ObjectServer;\nimport io.realm.internal.objectstore.OsSubscriptionSet;\n\n/**\n * A subscription set is an immutable view of all current {@link Subscription}s for a given\n * Realm that has been configured for flexible sync.\n * <p>\n * Flexible Sync is a way of defining which data gets synchronized to and from the device using\n * {@link RealmQuery}s. The query and its metadata are represented by a {@link Subscription}.\n * <p>\n * A subscription set thus defines all the data that is available to the device and being\n * synchronized with the server. If the subscription set encounters an error, e.g. by containing an\n * invalid query, the entire subscription set will enter an {@link SubscriptionSet.State#ERROR}\n * state, and no synchronization will happen until the error has been fixed.\n * <p>\n * If a subscription is removed, so is the corresponding data, but it is only removed from the\n * device. It isn't deleted on the server.\n * <p>\n * It is possible to modify a subscription set while offline, but modification isn't\n * accepted by the server before {@link #getState()} returns {@link SubscriptionSet.State#COMPLETE}.\n * <p>\n * It is possible to force the subscription set to be synchronized with the server by using\n * {@link #waitForSynchronization()} and its variants.\n *\n */\n@Beta\n@Keep\n@ObjectServer\npublic interface SubscriptionSet extends Iterable<Subscription> {\n\n    /**\n     * The possible states a subscription set can be in.\n     */\n    enum State {\n        /**\n         * The initial state of subscriptions when opening a new Realm or when entering a\n         * {@link #update(UpdateCallback)}. This state is only valid for\n         * {@link MutableSubscriptionSet}.\n         */\n        UNCOMMITTED(OsSubscriptionSet.STATE_VALUE_UNCOMMITTED),\n\n        /**\n         * A subscription set has been modified locally, but is still waiting to be sent to the\n         * server.\n         */\n        PENDING(OsSubscriptionSet.STATE_VALUE_PENDING),\n\n        /**\n         * A subscription set was accepted by the server and initial data is being sent to the\n         * device.\n         */\n        BOOTSTRAPPING(OsSubscriptionSet.STATE_VALUE_BOOTSTRAPPING),\n\n        /**\n         * A subscription set is actively synchronizing data between the server and the device.\n         */\n        COMPLETE(OsSubscriptionSet.STATE_VALUE_COMPLETE),\n\n        /**\n         * An error occurred in the subscription set or one of the subscriptions. The cause is\n         * found in {@link #getErrorMessage()}.\n         */\n        ERROR(OsSubscriptionSet.STATE_VALUE_ERROR),\n\n        /**\n         * Another subscription set was stored before this one, the changes made to this set\n         * are ignorde by the server. Get the latest subscription set by calling\n         * {@link Realm#getSubscriptions()}.\n         */\n        SUPERSEDED(OsSubscriptionSet.STATE_VALUE_SUPERSEDED),\n\n        /**\n         * The last initialization message containing the initial state for this subscription set\n         * has been received. The client is awaiting a mark message to mark this subscription as\n         * fully caught up to history.\n         */\n        AWAITING_MARK(OsSubscriptionSet.STATE_VALUE_AWAITING_MARK);\n\n        private final byte value;\n\n        State(byte nativeValue) {\n            this.value = nativeValue;\n        }\n\n        public static State fromNativeValue(long value) {\n            for (State state : values()) {\n                if (state.value == value) {\n                    return state;\n                }\n            }\n\n            throw new IllegalArgumentException(\"Unknown SubscriptionSetState code: \" + value);\n        }\n    }\n\n    /**\n     * Find the first subscription that contains the given query. It is possible for multiple\n     * named subscriptions to contain the same query.\n     *\n     * @param query query to search for.\n     * @return the first subscription containing the query or {@code null} if no match was found.\n     */\n    @Nullable\n    Subscription find(RealmQuery query);\n\n    /**\n     * Find the subscription with a given name.\n     *\n     * @param name name of subscription to search for.\n     * @return the matching subscription or {@code null} if no subscription with that name was found.\n     */\n    @Nullable\n    Subscription find(String name);\n\n    /**\n     * Returns the current state of the SubscriptionSet. See {@link SubscriptionSet.State} for more\n     * details about each state.\n     *\n     * @return current state of the SubscriptionSet.\n     */\n    State getState();\n\n    /**\n     * Returns how many subscriptions are currently in this subscription set.\n     *\n     * @return the number of of subscriptions in the subscription set.\n     */\n    int size();\n\n    /**\n     * If {@link #getState()} returns {@link State#ERROR}, this method will return the reason.\n     * Errors can be fixed by modifying the subscription accordingly and then calling\n     * {@link #waitForSynchronization()}.\n     *\n     * @return the underlying error if the subscription set is in the {@link State#ERROR} state. For\n     * all other states {@code null} will be returned.\n     */\n    @Nullable\n    String getErrorMessage();\n\n    /**\n     * Wait for the subscription set to synchronize with the server. It will return when the\n     * server either accepts the set of queries and has downloaded data for them, or if an\n     * error has occurred. Note, that you will either need to manually call {@link Realm#refresh()}\n     * or wait for change listeners to trigger to see the downloaded data.\n     *\n     * If an error occurred, the underlying reason can be found through {@link #getErrorMessage()}.\n     *\n     * @return {@code true} if all current subscriptions were accepted by the server and data has\n     * been downloaded, or {@code false} if an error occurred.\n     */\n    boolean waitForSynchronization();\n\n    /**\n     * Wait for the subscription set to synchronize with the server. It will return when the\n     * server either accepts the set of queries and has downloaded data for them, or if an\n     * error has occurred. Note, that you will either need to manually call {@link Realm#refresh()}\n     * or wait for change listeners to trigger to see the downloaded data.\n     *\n     * If an error occurred, the underlying reason can be found through {@link #getErrorMessage()}.\n     *\n     * @param timeOut how long to wait for the synchronization to either succeed or fail.\n     * @param unit unit of time used for the timeout.\n     * @return {@code true} if all current subscriptions were accepted by the server and data has\n     * been downloaded, or {@code false} if an error occurred.\n     * @throws RuntimeException if the timeout is exceeded.\n     */\n    boolean waitForSynchronization(Long timeOut, TimeUnit unit);\n\n    /**\n     * Asynchronously wait for the subscription set to synchronize with the server. It will invoke\n     * the callback when the server either accepts the set of queries and has downloaded data for\n     * them, or if an error has occurred. Note, that you will either need to manually call\n     * {@link Realm#refresh()} or wait for change listeners to trigger to see the downloaded data.\n     *\n     * If an error occurred, the underlying reason can be found through {@link #getErrorMessage()}.\n     *\n     * @param callback callback to trigger when the synchronization either succeed or fail. Results\n     *                 will be reported on the UI thread.\n     * @return {@code true} if all current subscriptions were accepted by the server and data has\n     * been downloaded, or {@code false} if an error occurred.\n     */\n    RealmAsyncTask waitForSynchronizationAsync(StateChangeCallback callback);\n\n    /**\n     * Asynchronously wait for the subscription set to synchronize with the server. The callback is\n     * invoked when the server either accepts the set of queries and has downloaded data for them,\n     * or if an error has occurred. Note, that you will either need to manually call\n     * {@link Realm#refresh()} or wait for change listeners to trigger to see the downloaded data.\n     *\n     * If an error occurred, the underlying reason can be found through {@link #getErrorMessage()}.\n     *\n     * @param timeOut how long to wait for the synchronization to either succeed or fail.\n     * @param unit unit of time used for the timeout.\n     * @param callback callback to trigger when the synchronization either succeed or fail. Results\n     *                 will be reported on the UI thread.\n     * @return {@code true} if all current subscriptions were accepted by the server and data has\n     * been downloaded, or {@code false} if an error occurred.\n     */\n    RealmAsyncTask waitForSynchronizationAsync(Long timeOut, TimeUnit unit, StateChangeCallback callback);\n\n    /**\n     * Modify the subscription set. If an exception is thrown during the update, no changes will be\n     * applied. If the update succeeds, this subscription set is updated with the modified state.\n     *\n     * @param action the block that modifies the subscription set. It will run on the caller thread.\n     * @return this subscription set, that now has been updated.\n     * @throws Exception any exception thrown during the update, will propagate back.\n     */\n    SubscriptionSet update(UpdateCallback action);\n\n    /**\n     * Asynchronously modify the subscription set. If an exception is thrown during the update, no\n     * changes will be applied.\n     * *\n     * @param callback callback that controls the asynct ask. Succces or failure will be reported here.\n     * @return task controlling the async execution.\n     */\n    RealmAsyncTask updateAsync(UpdateAsyncCallback callback);\n\n    /**\n     * Interface used when modifying a subscription set. See {@link #update(UpdateCallback)} and\n     * {@link #updateAsync(UpdateAsyncCallback)}.\n     */\n    interface UpdateCallback {\n        /**\n         * Updates the current subscription set by passing in a version of it that can be modified.\n         *\n         * If an exception is throwing during the update, all changes will be rolled back.\n         *\n         * @param subscriptions a modifiable version of the subscription set.\n         */\n        void update(MutableSubscriptionSet subscriptions);\n    }\n\n    /**\n     * Callback used when asynchronously updating a subscription set.\n     *\n     * If an exception is throwing during the update, all changes will be rolled back and the\n     * exception will be reported in {@code onError()}.\n     */\n    interface UpdateAsyncCallback extends UpdateCallback {\n        void onSuccess(SubscriptionSet subscriptions);\n        void onError(Throwable exception);\n    }\n\n    /**\n     * Callback used when asynchronously waiting for the server to process the subscription set.\n     * When the server either succeed or fail to apply the subscription set, the result is returned\n     * in {@code onStateChange}. This include errors from the server.\n     *\n     * If a local exception is thrown, it is reported through on {@code onError()}.\n     */\n    @Keep\n    interface StateChangeCallback {\n        void onStateChange(SubscriptionSet subscriptions);\n        void onError(Throwable e);\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/package-info.java",
    "content": "/*\n * Copyright 2017 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@javax.annotation.ParametersAreNonnullByDefault\npackage io.realm;\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/rx/CollectionChange.java",
    "content": "/*\n * Copyright 2017 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\npackage io.realm.rx;\n\nimport javax.annotation.Nullable;\n\nimport io.realm.OrderedCollectionChangeSet;\nimport io.realm.OrderedRealmCollection;\nimport io.realm.RealmList;\nimport io.realm.RealmResults;\n\n/**\n * Container wrapping the result of a {@link io.realm.OrderedRealmCollectionChangeListener} being triggered.\n * <p>\n * This is used by {@link RealmResults#asChangesetObservable()}} and {@link RealmList#asChangesetObservable()} as\n * RxJava is only capable of emitting one item, not multiple.\n */\npublic class CollectionChange<E extends OrderedRealmCollection> {\n\n    private final E collection;\n    private final OrderedCollectionChangeSet changeset;\n\n    /**\n     * Constructor for a CollectionChange.\n     *\n     * @param collection the collection that changed.\n     * @param changeset the changeset describing the change.\n     */\n    public CollectionChange(E collection, @Nullable OrderedCollectionChangeSet changeset) {\n        this.collection = collection;\n        this.changeset = changeset;\n    }\n\n    /**\n     * Returns the collection that was updated.\n     *\n     * @return collection that was updated.\n     */\n    public E getCollection() {\n        return collection;\n    }\n\n    /**\n     * Returns the changeset describing the update.\n     * <p>\n     * This will be {@code null} the first time the stream emits the collection as well as when a asynchronous query\n     * is loaded for the first time.\n     * <p>\n     * <pre>\n     * {@code\n     * // Example\n     * realm.where(Person.class).findAllAsync().asChangesetObservable()\n     *   .subscribe(new Consumer<CollectionChange>() {\n     *    \\@Override\n     *     public void accept(CollectionChange item) throws Exception {\n     *       item.getChangeset(); // Will return null the first two times\n     *   }\n     * });\n     * }\n     * </pre>\n     *\n     * @return the changeset describing how the collection was updated.\n     */\n    @Nullable\n    public OrderedCollectionChangeSet getChangeset() {\n        return changeset;\n    }\n\n    @Override\n    public boolean equals(Object o) {\n        if (this == o) return true;\n        if (o == null || getClass() != o.getClass()) return false;\n\n        CollectionChange<?> that = (CollectionChange<?>) o;\n\n        if (!collection.equals(that.collection)) return false;\n        return changeset != null ? changeset.equals(that.changeset) : that.changeset == null;\n    }\n\n    @Override\n    public int hashCode() {\n        int result = collection.hashCode();\n        result = 31 * result + (changeset != null ? changeset.hashCode() : 0);\n        return result;\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/rx/ObjectChange.java",
    "content": "/*\n * Copyright 2017 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\npackage io.realm.rx;\n\nimport javax.annotation.Nullable;\n\nimport io.realm.ObjectChangeSet;\nimport io.realm.RealmModel;\nimport io.realm.RealmObject;\n\n/**\n * Container wrapping the result of a {@link io.realm.RealmObjectChangeListener} being triggered.\n * <p>\n * This is used by {@link RealmObject#asChangesetObservable()} and {@link RealmObject#asChangesetObservable(RealmModel)}\n * as RxJava is only capable of emitting one item, not multiple.\n */\npublic class ObjectChange<E extends RealmModel> {\n\n    private final E object;\n    private final ObjectChangeSet changeset;\n\n    /**\n     * Constructor for a ObjectChange.\n     *\n     * @param object the object that was updated.\n     * @param changeset the changeset describing the update.\n     */\n    public ObjectChange(E object, @Nullable ObjectChangeSet changeset) {\n        this.object = object;\n        this.changeset = changeset;\n    }\n\n    public E getObject() {\n        return object;\n    }\n\n    /**\n     * Returns the changeset describing the update.\n     * <p>\n     * This will be {@code null} the first time the stream emits the object as well as when a asynchronous query\n     * is loaded for the first time.\n     * <p>\n     * <pre>\n     * {@code\n     * // Example\n     * realm.where(Person.class).findFirstAsync().asChangesetObservable()\n     *   .subscribe(new Consumer<ObjectChange>() {\n     *    \\@Override\n     *     public void accept(ObjectChange item) throws Exception {\n     *       item.getChangeset(); // Will return null the first two times\n     *   }\n     * });\n     * }\n     * </pre>\n     *\n     * @return the changeset describing how the object was updated.\n     */\n    @Nullable\n    public ObjectChangeSet getChangeset() {\n        return changeset;\n    }\n\n    @Override\n    public boolean equals(Object o) {\n        if (this == o) return true;\n        if (o == null || getClass() != o.getClass()) return false;\n\n        ObjectChange<?> that = (ObjectChange<?>) o;\n\n        if (!object.equals(that.object)) return false;\n        return changeset != null ? changeset.equals(that.changeset) : that.changeset == null;\n    }\n\n    @Override\n    public int hashCode() {\n        int result = object.hashCode();\n        result = 31 * result + (changeset != null ? changeset.hashCode() : 0);\n        return result;\n    }\n\n    @Override\n    public String toString() {\n        return \"ObjectChange{\" +\n                \"object=\" + object +\n                \", changeset=\" + changeset +\n                '}';\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/rx/RealmObservableFactory.java",
    "content": "/*\n * Copyright 2015 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\npackage io.realm.rx;\n\nimport android.os.Looper;\n\nimport java.util.IdentityHashMap;\nimport java.util.Map;\n\nimport io.reactivex.BackpressureStrategy;\nimport io.reactivex.Flowable;\nimport io.reactivex.FlowableEmitter;\nimport io.reactivex.FlowableOnSubscribe;\nimport io.reactivex.Observable;\nimport io.reactivex.ObservableEmitter;\nimport io.reactivex.ObservableOnSubscribe;\nimport io.reactivex.Scheduler;\nimport io.reactivex.Single;\nimport io.reactivex.android.schedulers.AndroidSchedulers;\nimport io.reactivex.disposables.Disposables;\nimport io.realm.DynamicRealm;\nimport io.realm.DynamicRealmObject;\nimport io.realm.ObjectChangeSet;\nimport io.realm.OrderedCollectionChangeSet;\nimport io.realm.OrderedRealmCollectionChangeListener;\nimport io.realm.Realm;\nimport io.realm.RealmChangeListener;\nimport io.realm.RealmConfiguration;\nimport io.realm.RealmList;\nimport io.realm.RealmModel;\nimport io.realm.RealmObject;\nimport io.realm.RealmObjectChangeListener;\nimport io.realm.RealmQuery;\nimport io.realm.RealmResults;\n\n/**\n * Factory class for creating Observables for RxJava (&lt;=2.0.*).\n *\n * @see Realm#asFlowable() ()\n * @see RealmObject#asFlowable()\n * @see RealmResults#asFlowable()\n * @see DynamicRealm#asFlowable()\n * @see DynamicRealmObject#asFlowable()\n */\npublic class RealmObservableFactory implements RxObservableFactory {\n\n    private final boolean returnFrozenObjects;\n\n    // Maps for storing strong references to Realm classes while they are subscribed to.\n    // This is needed if users create Observables without manually maintaining a reference to them.\n    // In that case RealmObjects/RealmResults/RealmLists might be GC'ed too early.\n    private ThreadLocal<StrongReferenceCounter<RealmResults>> resultsRefs = new ThreadLocal<StrongReferenceCounter<RealmResults>>() {\n        @Override\n        protected StrongReferenceCounter<RealmResults> initialValue() {\n            return new StrongReferenceCounter<>();\n        }\n    };\n    private ThreadLocal<StrongReferenceCounter<RealmList>> listRefs = new ThreadLocal<StrongReferenceCounter<RealmList>>() {\n        @Override\n        protected StrongReferenceCounter<RealmList> initialValue() {\n            return new StrongReferenceCounter<>();\n        }\n    };\n    private ThreadLocal<StrongReferenceCounter<RealmModel>> objectRefs = new ThreadLocal<StrongReferenceCounter<RealmModel>>() {\n        @Override\n        protected StrongReferenceCounter<RealmModel> initialValue() {\n            return new StrongReferenceCounter<>();\n        }\n    };\n\n    private static final BackpressureStrategy BACK_PRESSURE_STRATEGY = BackpressureStrategy.LATEST;\n\n    @Override\n    public Flowable<Realm> from(Realm realm) {\n        if (realm.isFrozen()) {\n            return Flowable.just(realm);\n        }\n        final RealmConfiguration realmConfig = realm.getConfiguration();\n        Scheduler scheduler = getScheduler();\n        return Flowable.create(new FlowableOnSubscribe <Realm>() {\n            @Override\n            public void subscribe(final FlowableEmitter<Realm> emitter) throws Exception {\n                // Instance is cached by Realm, so no need to keep strong reference\n                final Realm observableRealm = Realm.getInstance(realmConfig);\n                final RealmChangeListener<Realm> listener = new RealmChangeListener<Realm>() {\n                    @Override\n                    public void onChange(Realm realm) {\n                        if (!emitter.isCancelled()) {\n                            emitter.onNext(returnFrozenObjects ? realm.freeze() : realm);\n                        }\n                    }\n                };\n                observableRealm.addChangeListener(listener);\n\n                // Cleanup when stream is disposed\n                emitter.setDisposable(Disposables.fromRunnable(new Runnable() {\n                    @Override\n                    public void run() {\n                        if (!observableRealm.isClosed()) {\n                            observableRealm.removeChangeListener(listener);\n                            observableRealm.close();\n                        }\n                    }\n                }));\n\n                // Emit current value immediately\n                emitter.onNext(returnFrozenObjects ? observableRealm.freeze() : observableRealm);\n            }\n        }, BACK_PRESSURE_STRATEGY).subscribeOn(scheduler).unsubscribeOn(scheduler);\n    }\n\n    /**\n     * Constructs the factory for creating Realm observables for RxJava.\n     *\n     * @param emitFrozenObjects {@code true} if all objects should be frozen before being returned\n *                              to the user. {@code false} if they should be live objects.\n     */\n    public RealmObservableFactory(boolean emitFrozenObjects) {\n        this.returnFrozenObjects = emitFrozenObjects;\n    }\n\n    @Override\n    public Flowable<DynamicRealm> from(DynamicRealm realm) {\n        if (realm.isFrozen()) {\n            return Flowable.just(realm);\n        }\n        final RealmConfiguration realmConfig = realm.getConfiguration();\n        Scheduler scheduler = getScheduler();\n        return Flowable.create(new FlowableOnSubscribe<DynamicRealm>() {\n            @Override\n            public void subscribe(final FlowableEmitter<DynamicRealm> emitter) throws Exception {\n                // Instance is cached by Realm, so no need to keep strong reference\n                final DynamicRealm observableRealm = DynamicRealm.getInstance(realmConfig);\n                final RealmChangeListener<DynamicRealm> listener = new RealmChangeListener<DynamicRealm>() {\n                    @Override\n                    public void onChange(DynamicRealm realm) {\n                        if (!emitter.isCancelled()) {\n                            emitter.onNext(returnFrozenObjects ? realm.freeze() : realm);\n                        }\n                    }\n                };\n                observableRealm.addChangeListener(listener);\n\n                // Cleanup when stream is disposed\n                emitter.setDisposable(Disposables.fromRunnable(new Runnable() {\n                    @Override\n                    public void run() {\n                        if (!observableRealm.isClosed()) {\n                            observableRealm.removeChangeListener(listener);\n                            observableRealm.close();\n                        }\n                    }\n                }));\n\n                // Emit current value immediately\n                emitter.onNext(returnFrozenObjects ? observableRealm.freeze() : observableRealm);\n            }\n        }, BACK_PRESSURE_STRATEGY).subscribeOn(scheduler).unsubscribeOn(scheduler);\n    }\n\n    @Override\n    public <E> Flowable<RealmResults<E>> from(final Realm realm, final RealmResults<E> results) {\n        if (realm.isFrozen()) {\n            return Flowable.just(results);\n        }\n        final RealmConfiguration realmConfig = realm.getConfiguration();\n        Scheduler scheduler = getScheduler();\n        return Flowable.create(new FlowableOnSubscribe<RealmResults<E>>() {\n            @Override\n            public void subscribe(final FlowableEmitter<RealmResults<E>> emitter) {\n                // If the Realm has been closed, just create an empty Observable because we assume it is going to be disposed shortly.\n                if (!results.isValid()) return;\n\n                // Gets instance to make sure that the Realm is open for as long as the\n                // Observable is subscribed to it.\n                final Realm observableRealm = Realm.getInstance(realmConfig);\n                resultsRefs.get().acquireReference(results);\n                final RealmChangeListener<RealmResults<E>> listener = new RealmChangeListener<RealmResults<E>>() {\n                    @Override\n                    public void onChange(RealmResults<E> results) {\n                        if (!emitter.isCancelled()) {\n                            emitter.onNext(returnFrozenObjects ? results.freeze() : results);\n                        }\n                    }\n                };\n                results.addChangeListener(listener);\n\n                // Cleanup when stream is disposed\n                emitter.setDisposable(Disposables.fromRunnable(new Runnable() {\n                    @Override\n                    public void run() {\n                        if (!observableRealm.isClosed()) {\n                            results.removeChangeListener(listener);\n                            observableRealm.close();\n                        }\n                        resultsRefs.get().releaseReference(results);\n                    }\n                }));\n\n                // Emit current value immediately\n                emitter.onNext(returnFrozenObjects ? results.freeze() : results);\n\n            }\n        }, BACK_PRESSURE_STRATEGY).subscribeOn(scheduler).unsubscribeOn(scheduler);\n    }\n\n    private Scheduler getScheduler() {\n        Looper looper = Looper.myLooper();\n        if (looper == null) {\n            throw new IllegalStateException(\"No looper found\");\n        }\n        return AndroidSchedulers.from(looper);\n    }\n\n    @Override\n    public <E> Observable<CollectionChange<RealmResults<E>>> changesetsFrom(Realm realm, final RealmResults<E> results) {\n        if (realm.isFrozen()) {\n            return Observable.just(new CollectionChange<RealmResults<E>>(results, null));\n        }\n        final RealmConfiguration realmConfig = realm.getConfiguration();\n        Scheduler scheduler = getScheduler();\n        return Observable.create(new ObservableOnSubscribe<CollectionChange<RealmResults<E>>>() {\n            @Override\n            public void subscribe(final ObservableEmitter<CollectionChange<RealmResults<E>>> emitter) {\n                // If the Realm has been closed, just create an empty Observable because we assume it is going to be disposed shortly.\n                if (!results.isValid()) return;\n\n                // Gets instance to make sure that the Realm is open for as long as the\n                // Observable is subscribed to it.\n                final Realm observableRealm = Realm.getInstance(realmConfig);\n                resultsRefs.get().acquireReference(results);\n                final OrderedRealmCollectionChangeListener<RealmResults<E>> listener = new OrderedRealmCollectionChangeListener<RealmResults<E>>() {\n                    @Override\n                    public void onChange(RealmResults<E> e, OrderedCollectionChangeSet changeSet) {\n                        if (!emitter.isDisposed()) {\n                            emitter.onNext(new CollectionChange<RealmResults<E>>(returnFrozenObjects ? results.freeze() : results, changeSet));\n                        }\n                    }\n                };\n                results.addChangeListener(listener);\n\n                // Cleanup when stream is disposed\n                emitter.setDisposable(Disposables.fromRunnable(new Runnable() {\n                    @Override\n                    public void run() {\n                        if (!observableRealm.isClosed()) {\n                            results.removeChangeListener(listener);\n                            observableRealm.close();\n                        }\n                        resultsRefs.get().releaseReference(results);\n                    }\n                }));\n\n                // Emit current value immediately\n                emitter.onNext(new CollectionChange<>(returnFrozenObjects ? results.freeze() : results, null));\n            }\n        }).subscribeOn(scheduler).unsubscribeOn(scheduler);\n    }\n\n    @Override\n    public <E> Flowable<RealmResults<E>> from(DynamicRealm realm, final RealmResults<E> results) {\n        if (realm.isFrozen()) {\n            return Flowable.just(results);\n        }\n        final RealmConfiguration realmConfig = realm.getConfiguration();\n        Scheduler scheduler = getScheduler();\n        return Flowable.create(new FlowableOnSubscribe<RealmResults<E>>() {\n            @Override\n            public void subscribe(final FlowableEmitter<RealmResults<E>> emitter) {\n                // If the Realm has been closed, just create an empty Observable because we assume it is going to be disposed shortly.\n                if (!results.isValid()) return;\n\n                // Gets instance to make sure that the Realm is open for as long as the\n                // Observable is subscribed to it.\n                final DynamicRealm observableRealm = DynamicRealm.getInstance(realmConfig);\n                resultsRefs.get().acquireReference(results);\n                final RealmChangeListener<RealmResults<E>> listener = new RealmChangeListener<RealmResults<E>>() {\n                    @Override\n                    public void onChange(RealmResults<E> results) {\n                        if (!emitter.isCancelled()) {\n                            emitter.onNext(returnFrozenObjects ? results.freeze() : results);\n                        }\n                    }\n                };\n                results.addChangeListener(listener);\n\n                // Cleanup when stream is disposed\n                emitter.setDisposable(Disposables.fromRunnable(new Runnable() {\n                    @Override\n                    public void run() {\n                        if (!observableRealm.isClosed()) {\n                            results.removeChangeListener(listener);\n                            observableRealm.close();\n                        }\n                        resultsRefs.get().releaseReference(results);\n                    }\n                }));\n\n                // Emit current value immediately\n                emitter.onNext(returnFrozenObjects ? results.freeze() : results);\n\n            }\n        }, BACK_PRESSURE_STRATEGY).subscribeOn(scheduler).unsubscribeOn(scheduler);\n    }\n\n    @Override\n    public <E> Observable<CollectionChange<RealmResults<E>>> changesetsFrom(DynamicRealm realm, final RealmResults<E> results) {\n        if (realm.isFrozen()) {\n            return Observable.just(new CollectionChange<RealmResults<E>>(results, null));\n        }\n        final RealmConfiguration realmConfig = realm.getConfiguration();\n        Scheduler scheduler = getScheduler();\n        return Observable.create(new ObservableOnSubscribe<CollectionChange<RealmResults<E>>>() {\n            @Override\n            public void subscribe(final ObservableEmitter<CollectionChange<RealmResults<E>>> emitter) {\n                // If the Realm has been closed, just create an empty Observable because we assume it is going to be disposed shortly.\n                if (!results.isValid()) return;\n\n                // Gets instance to make sure that the Realm is open for as long as the\n                // Observable is subscribed to it.\n                final DynamicRealm observableRealm = DynamicRealm.getInstance(realmConfig);\n                resultsRefs.get().acquireReference(results);\n                final OrderedRealmCollectionChangeListener<RealmResults<E>> listener = new OrderedRealmCollectionChangeListener<RealmResults<E>>() {\n                    @Override\n                    public void onChange(RealmResults<E> results, OrderedCollectionChangeSet changeSet) {\n                        if (!emitter.isDisposed()) {\n                            emitter.onNext(new CollectionChange<>(returnFrozenObjects ? results.freeze() : results, changeSet));\n                        }\n                    }\n                };\n                results.addChangeListener(listener);\n\n                // Cleanup when stream is disposed\n                emitter.setDisposable(Disposables.fromRunnable(new Runnable() {\n                    @Override\n                    public void run() {\n                        if (!observableRealm.isClosed()) {\n                            results.removeChangeListener(listener);\n                            observableRealm.close();\n                        }\n                        resultsRefs.get().releaseReference(results);\n                    }\n                }));\n\n                // Emit current value immediately\n                emitter.onNext(new CollectionChange<>(returnFrozenObjects ? results.freeze() : results, null));\n            }\n        }).subscribeOn(scheduler).unsubscribeOn(scheduler);\n    }\n\n    @Override\n    public <E> Flowable<RealmList<E>> from(Realm realm, final RealmList<E> list) {\n        if (realm.isFrozen()) {\n            return Flowable.just(list);\n        }\n        final RealmConfiguration realmConfig = realm.getConfiguration();\n        Scheduler scheduler = getScheduler();\n        return Flowable.create(new FlowableOnSubscribe<RealmList<E>>() {\n            @Override\n            public void subscribe(final FlowableEmitter<RealmList<E>> emitter) {\n                // If the Realm has been closed, just create an empty Observable because we assume it is going to be disposed shortly.\n                if (!list.isValid()) return;\n\n                // Gets instance to make sure that the Realm is open for as long as the\n                // Observable is subscribed to it.\n                final Realm observableRealm = Realm.getInstance(realmConfig);\n                listRefs.get().acquireReference(list);\n                final RealmChangeListener<RealmList<E>> listener = new RealmChangeListener<RealmList<E>>() {\n                    @Override\n                    public void onChange(RealmList<E> list) {\n                        if (!list.isValid()) {\n                            // Terminate stream if list is no longer valid. This indicates\n                            // the parent object has been deleted, so no further updates\n                            // will be coming.\n                            emitter.onComplete();\n                            return;\n                        }\n                        if (!emitter.isCancelled()) {\n                            emitter.onNext(returnFrozenObjects ? list.freeze() : list);\n                        }\n                    }\n                };\n                list.addChangeListener(listener);\n\n                // Cleanup when stream is disposed\n                emitter.setDisposable(Disposables.fromRunnable(new Runnable() {\n                    @Override\n                    public void run() {\n                        if (!observableRealm.isClosed()) {\n                            list.removeChangeListener(listener);\n                            observableRealm.close();\n                        }\n                        listRefs.get().releaseReference(list);\n                    }\n                }));\n\n                // Emit current value immediately\n                emitter.onNext(returnFrozenObjects ? list.freeze() : list);\n\n            }\n        }, BACK_PRESSURE_STRATEGY).subscribeOn(scheduler).unsubscribeOn(scheduler);\n    }\n\n    @Override\n    public <E> Observable<CollectionChange<RealmList<E>>> changesetsFrom(Realm realm, final RealmList<E> list) {\n        if (realm.isFrozen()) {\n            return Observable.just(new CollectionChange<RealmList<E>>(list, null));\n        }\n        final RealmConfiguration realmConfig = realm.getConfiguration();\n        Scheduler scheduler = getScheduler();\n        return Observable.create(new ObservableOnSubscribe<CollectionChange<RealmList<E>>>() {\n            @Override\n            public void subscribe(final ObservableEmitter<CollectionChange<RealmList<E>>> emitter) {\n                // If the Realm has been closed, just create an empty Observable because we assume it is going to be disposed shortly.\n                if (!list.isValid()) return;\n\n                // Gets instance to make sure that the Realm is open for as long as the\n                // Observable is subscribed to it.\n                final Realm observableRealm = Realm.getInstance(realmConfig);\n                listRefs.get().acquireReference(list);\n                final OrderedRealmCollectionChangeListener<RealmList<E>> listener = new OrderedRealmCollectionChangeListener<RealmList<E>>() {\n                    @Override\n                    public void onChange(RealmList<E> list, OrderedCollectionChangeSet changeSet) {\n                        if (!list.isValid()) {\n                            // Terminate stream if list is no longer valid. This indicates\n                            // the parent object has been deleted, so no further updates\n                            // will be coming.\n                            emitter.onComplete();\n                            return;\n                        }\n                        if (!emitter.isDisposed()) {\n                            emitter.onNext(new CollectionChange<>(returnFrozenObjects ? list.freeze() : list, changeSet));\n                        }\n                    }\n                };\n                list.addChangeListener(listener);\n\n                // Cleanup when stream is disposed\n                emitter.setDisposable(Disposables.fromRunnable(new Runnable() {\n                    @Override\n                    public void run() {\n                        if (!observableRealm.isClosed()) {\n                            list.removeChangeListener(listener);\n                            observableRealm.close();\n                        }\n                        listRefs.get().releaseReference(list);\n                    }\n                }));\n\n                // Emit current value immediately\n                emitter.onNext(new CollectionChange<>(returnFrozenObjects ? list.freeze() : list, null));\n            }\n        }).subscribeOn(scheduler).unsubscribeOn(scheduler);\n    }\n\n    @Override\n    public <E> Flowable<RealmList<E>> from(DynamicRealm realm, final RealmList<E> list) {\n        if (realm.isFrozen()) {\n            return Flowable.just(list);\n        }\n        final RealmConfiguration realmConfig = realm.getConfiguration();\n        Scheduler scheduler = getScheduler();\n        return Flowable.create(new FlowableOnSubscribe<RealmList<E>>() {\n            @Override\n            public void subscribe(final FlowableEmitter<RealmList<E>> emitter) {\n                // If the Realm has been closed, just create an empty Observable because we assume it is going to be disposed shortly.\n                if (!list.isValid()) return;\n\n                // Gets instance to make sure that the Realm is open for as long as the\n                // Observable is subscribed to it.\n                final DynamicRealm observableRealm = DynamicRealm.getInstance(realmConfig);\n                listRefs.get().acquireReference(list);\n                final RealmChangeListener<RealmList<E>> listener = new RealmChangeListener<RealmList<E>>() {\n                    @Override\n                    public void onChange(RealmList<E> list) {\n                        if (!list.isValid()) {\n                            // Terminate stream if list is no longer valid. This indicates\n                            // the parent object has been deleted, so no further updates\n                            // will be coming.\n                            emitter.onComplete();\n                            return;\n                        }\n                        if (!emitter.isCancelled()) {\n                            emitter.onNext(returnFrozenObjects ? list.freeze() : list);\n                        }\n                    }\n                };\n                list.addChangeListener(listener);\n\n                // Cleanup when stream is disposed\n                emitter.setDisposable(Disposables.fromRunnable(new Runnable() {\n                    @Override\n                    public void run() {\n                        if (!observableRealm.isClosed()) {\n                            list.removeChangeListener(listener);\n                            observableRealm.close();\n                        }\n                        listRefs.get().releaseReference(list);\n                    }\n                }));\n\n                // Emit current value immediately\n                emitter.onNext(returnFrozenObjects ? list.freeze() : list);\n\n            }\n        }, BACK_PRESSURE_STRATEGY).subscribeOn(scheduler).unsubscribeOn(scheduler);\n    }\n\n    @Override\n    public <E> Observable<CollectionChange<RealmList<E>>> changesetsFrom(DynamicRealm realm, final RealmList<E> list) {\n        if (realm.isFrozen()) {\n            return Observable.just(new CollectionChange<RealmList<E>>(list, null));\n        }\n        final RealmConfiguration realmConfig = realm.getConfiguration();\n        Scheduler scheduler = getScheduler();\n        return Observable.create(new ObservableOnSubscribe<CollectionChange<RealmList<E>>>() {\n            @Override\n            public void subscribe(final ObservableEmitter<CollectionChange<RealmList<E>>> emitter) {\n                // If the Realm has been closed, just create an empty Observable because we assume it is going to be disposed shortly.\n                if (!list.isValid()) return;\n\n                // Gets instance to make sure that the Realm is open for as long as the\n                // Observable is subscribed to it.\n                final DynamicRealm observableRealm = DynamicRealm.getInstance(realmConfig);\n                listRefs.get().acquireReference(list);\n                final OrderedRealmCollectionChangeListener<RealmList<E>> listener = new OrderedRealmCollectionChangeListener<RealmList<E>>() {\n                    @Override\n                    public void onChange(RealmList<E> list, OrderedCollectionChangeSet changeSet) {\n                        if (!list.isValid()) {\n                            // Terminate stream if list is no longer valid. This indicates\n                            // the parent object has been deleted, so no further updates\n                            // will be coming.\n                            emitter.onComplete();\n                            return;\n                        }\n                        if (!emitter.isDisposed()) {\n                            emitter.onNext(new CollectionChange<>(returnFrozenObjects ? list.freeze() : list, changeSet));\n                        }\n                    }\n                };\n                list.addChangeListener(listener);\n\n                // Cleanup when stream is disposed\n                emitter.setDisposable(Disposables.fromRunnable(new Runnable() {\n                    @Override\n                    public void run() {\n                        if (!observableRealm.isClosed()) {\n                            list.removeChangeListener(listener);\n                            observableRealm.close();\n                        }\n                        listRefs.get().releaseReference(list);\n                    }\n                }));\n\n                // Emit current value immediately\n                emitter.onNext(new CollectionChange<>(returnFrozenObjects ? list.freeze() : list, null));\n            }\n        }).subscribeOn(scheduler).unsubscribeOn(scheduler);\n    }\n\n    @Override\n    public <E extends RealmModel> Flowable<E> from(final Realm realm, final E object) {\n        if (realm.isFrozen()) {\n            return Flowable.just(object);\n        }\n        final RealmConfiguration realmConfig = realm.getConfiguration();\n        Scheduler scheduler = getScheduler();\n        return Flowable.create(new FlowableOnSubscribe<E>() {\n            @Override\n            public void subscribe(final FlowableEmitter<E> emitter) {\n                // If the Realm has been closed, just create an empty Observable because we assume it is going to be disposed shortly.\n                if (realm.isClosed()) return;\n\n                // Gets instance to make sure that the Realm is open for as long as the\n                // Observable is subscribed to it.\n                final Realm observableRealm = Realm.getInstance(realmConfig);\n                objectRefs.get().acquireReference(object);\n                final RealmChangeListener<E> listener = new RealmChangeListener<E>() {\n                    @Override\n                    public void onChange(E obj) {\n                        if (!emitter.isCancelled()) {\n                            emitter.onNext(returnFrozenObjects ? RealmObject.freeze(obj) : obj);\n                        }\n                    }\n                };\n                RealmObject.addChangeListener(object, listener);\n\n                // Cleanup when stream is disposed\n                emitter.setDisposable(Disposables.fromRunnable(new Runnable() {\n                    @Override\n                    public void run() {\n                        if (!observableRealm.isClosed()) {\n                            RealmObject.removeChangeListener(object, listener);\n                            observableRealm.close();\n                        }\n                        objectRefs.get().releaseReference(object);\n                    }\n                }));\n\n                // Emit current value immediately\n                emitter.onNext(returnFrozenObjects ? RealmObject.freeze(object) : object);\n            }\n        }, BACK_PRESSURE_STRATEGY).subscribeOn(scheduler).unsubscribeOn(scheduler);\n    }\n\n    @Override\n    public <E extends RealmModel> Observable<ObjectChange<E>> changesetsFrom(Realm realm, final E object) {\n        if (realm.isFrozen()) {\n            return Observable.just(new ObjectChange<E>(object, null));\n        }\n        final RealmConfiguration realmConfig = realm.getConfiguration();\n        Scheduler scheduler = getScheduler();\n        return Observable.create(new ObservableOnSubscribe<ObjectChange<E>>() {\n            @Override\n            public void subscribe(final ObservableEmitter<ObjectChange<E>> emitter) {\n                // If the Realm has been closed, just create an empty Observable because we assume it is going to be disposed shortly.\n                if (!RealmObject.isValid(object)) return;\n\n                // Gets instance to make sure that the Realm is open for as long as the\n                // Observable is subscribed to it.\n                final Realm observableRealm = Realm.getInstance(realmConfig);\n                objectRefs.get().acquireReference(object);\n                final RealmObjectChangeListener<E> listener = new RealmObjectChangeListener<E>() {\n                    @Override\n                    public void onChange(E obj, ObjectChangeSet changeSet) {\n                        if (!emitter.isDisposed()) {\n                            emitter.onNext(new ObjectChange<>(returnFrozenObjects ? RealmObject.freeze(obj) : obj, changeSet));\n                        }\n                    }\n                };\n                RealmObject.addChangeListener(object, listener);\n\n                // Cleanup when stream is disposed\n                emitter.setDisposable(Disposables.fromRunnable(new Runnable() {\n                    @Override\n                    public void run() {\n                        if (!observableRealm.isClosed()) {\n                            RealmObject.removeChangeListener(object, listener);\n                            observableRealm.close();\n                        }\n                        objectRefs.get().releaseReference(object);\n                    }\n                }));\n\n                // Emit current value immediately\n                emitter.onNext(new ObjectChange<>(returnFrozenObjects ? RealmObject.freeze(object) : object, null));\n            }\n        }).subscribeOn(scheduler).unsubscribeOn(scheduler);\n    }\n\n    @Override\n    public Flowable<DynamicRealmObject> from(DynamicRealm realm, final DynamicRealmObject object) {\n        if (realm.isFrozen()) {\n            return Flowable.just(object);\n        }\n        final RealmConfiguration realmConfig = realm.getConfiguration();\n        Scheduler scheduler = getScheduler();\n        return Flowable.create(new FlowableOnSubscribe<DynamicRealmObject>() {\n            @Override\n            public void subscribe(final FlowableEmitter<DynamicRealmObject> emitter) {\n                // If the Realm has been closed, just create an empty Observable because we assume it is going to be disposed shortly.\n                if (realm.isClosed()) return;\n\n                // Gets instance to make sure that the Realm is open for as long as the\n                // Observable is subscribed to it.\n                final DynamicRealm observableRealm = DynamicRealm.getInstance(realmConfig);\n                objectRefs.get().acquireReference(object);\n                final RealmChangeListener<DynamicRealmObject> listener = new RealmChangeListener<DynamicRealmObject>() {\n                    @Override\n                    public void onChange(DynamicRealmObject obj) {\n                        if (!emitter.isCancelled()) {\n                            emitter.onNext(returnFrozenObjects ? RealmObject.freeze(obj) : obj);\n                        }\n                    }\n                };\n                RealmObject.addChangeListener(object, listener);\n\n                // Cleanup when stream is disposed\n                emitter.setDisposable(Disposables.fromRunnable(new Runnable() {\n                    @Override\n                    public void run() {\n                        if (!observableRealm.isClosed()) {\n                            RealmObject.removeChangeListener(object, listener);\n                            observableRealm.close();\n                        }\n                        objectRefs.get().releaseReference(object);\n                    }\n                }));\n\n                // Emit current value immediately\n                emitter.onNext(returnFrozenObjects ? RealmObject.freeze(object) : object);\n\n            }\n        }, BACK_PRESSURE_STRATEGY).subscribeOn(scheduler).unsubscribeOn(scheduler);\n    }\n\n    @Override\n    public Observable<ObjectChange<DynamicRealmObject>> changesetsFrom(DynamicRealm realm, final DynamicRealmObject object) {\n        if (realm.isFrozen()) {\n            return Observable.just(new ObjectChange<DynamicRealmObject>(object, null));\n        }\n        final RealmConfiguration realmConfig = realm.getConfiguration();\n        Scheduler scheduler = getScheduler();\n        return Observable.create(new ObservableOnSubscribe<ObjectChange<DynamicRealmObject>>() {\n            @Override\n            public void subscribe(final ObservableEmitter<ObjectChange<DynamicRealmObject>> emitter) {\n                // If the Realm has been closed, just create an empty Observable because we assume it is going to be disposed shortly.\n                if (!RealmObject.isValid(object)) return;\n\n                // Gets instance to make sure that the Realm is open for as long as the\n                // Observable is subscribed to it.\n                final DynamicRealm observableRealm = DynamicRealm.getInstance(realmConfig);\n                objectRefs.get().acquireReference(object);\n                final RealmObjectChangeListener<DynamicRealmObject> listener = new RealmObjectChangeListener<DynamicRealmObject>() {\n                    @Override\n                    public void onChange(DynamicRealmObject obj, ObjectChangeSet changeSet) {\n                        if (!emitter.isDisposed()) {\n                            emitter.onNext(new ObjectChange<>(returnFrozenObjects ? RealmObject.freeze(obj) : obj, changeSet));\n                        }\n                    }\n                };\n                object.addChangeListener(listener);\n\n                // Cleanup when stream is disposed\n                emitter.setDisposable(Disposables.fromRunnable(new Runnable() {\n                    @Override\n                    public void run() {\n                        if (!observableRealm.isClosed()) {\n                            RealmObject.removeChangeListener(object, listener);\n                            observableRealm.close();\n                        }\n                        objectRefs.get().releaseReference(object);\n                    }\n                }));\n\n                // Emit current value immediately\n                emitter.onNext(new ObjectChange<>(returnFrozenObjects ? RealmObject.freeze(object) : object, null));\n            }\n        }).subscribeOn(scheduler).unsubscribeOn(scheduler);\n    }\n\n    @Override\n    public <E> Single<RealmQuery<E>> from(Realm realm, RealmQuery<E> query) {\n        throw new RuntimeException(\"RealmQuery not supported yet.\");\n    }\n\n    @Override\n    public <E> Single<RealmQuery<E>> from(DynamicRealm realm, RealmQuery<E> query) {\n        throw new RuntimeException(\"RealmQuery not supported yet.\");\n    }\n\n    @Override\n    public boolean equals(Object o) {\n        return o instanceof RealmObservableFactory;\n    }\n\n    @Override\n    public int hashCode() {\n        return 37; // Random number\n    }\n\n    // Helper class for keeping track of strong references to objects.\n    private static class StrongReferenceCounter<K> {\n\n        private final Map<K, Integer> references = new IdentityHashMap<K, Integer>();\n\n        public void acquireReference(K object) {\n            Integer count = references.get(object);\n            if (count == null) {\n                references.put(object, 1);\n            } else {\n                references.put(object, count + 1);\n            }\n        }\n\n        public void releaseReference(K object) {\n            Integer count = references.get(object);\n            if (count == null) {\n                throw new IllegalStateException(\"Object does not have any references: \" + object);\n            } else if (count > 1) {\n                references.put(object, count - 1);\n            } else if (count == 1) {\n                references.remove(object);\n            } else {\n                throw new IllegalStateException(\"Invalid reference count: \" + count);\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/rx/RxObservableFactory.java",
    "content": "/*\n * Copyright 2015 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\npackage io.realm.rx;\n\nimport io.reactivex.Flowable;\nimport io.reactivex.Observable;\nimport io.reactivex.Single;\nimport io.realm.DynamicRealm;\nimport io.realm.DynamicRealmObject;\nimport io.realm.OrderedCollectionChangeSet;\nimport io.realm.Realm;\nimport io.realm.RealmList;\nimport io.realm.RealmModel;\nimport io.realm.RealmObject;\nimport io.realm.RealmQuery;\nimport io.realm.RealmResults;\n\n/**\n * Factory interface for creating Rx Observables for Realm classes.\n */\npublic interface RxObservableFactory {\n\n    /**\n     * Creates a Flowable for a {@link Realm}. It should emit the initial state of the Realm when subscribed to and\n     * on each subsequent update of the Realm.\n     * <p>\n     * Realm flowables are hot as Realms are automatically kept up to date.\n     *\n     * @param realm {@link Realm} to listen to changes for.\n     * @return Rx observable that emit all updates to the Realm.\n     */\n    Flowable<Realm> from(Realm realm);\n\n    /**\n     * Creates a Flowable for a {@link DynamicRealm}. It should emit the initial state of the Realm when subscribed\n     * to and on each subsequent update of the Realm.\n     * <p>\n     * DynamicRealm observables are hot as DynamicRealms are automatically kept up to date.\n     *\n     * @param realm {@link DynamicRealm} to listen to changes for.\n     * @return Rx observable that emit all updates to the DynamicRealm.\n     */\n    Flowable<DynamicRealm> from(DynamicRealm realm);\n\n    /**\n     * Creates a Flowable for a {@link RealmResults}. It should emit the initial RealmResult when subscribed to and\n     * on each subsequent update of the RealmResults.\n     * <p>\n     * RealmResults observables are hot as RealmResults are automatically kept up to date.\n     *\n     * @param results {@link RealmResults} to listen to changes for.\n     * @param realm {@link Realm} instance results are coming from.\n     * @param <E> type of RealmObject\n     * @return Rx observable that emit all updates to the RealmObject.\n     */\n    <E> Flowable<RealmResults<E>> from(Realm realm, RealmResults<E> results);\n\n    /**\n     * Creates an Observable for a {@link RealmResults}. It should emit the initial RealmResult when subscribed to and\n     * on each subsequent update of the RealmResults it should emit the RealmResults + the {@link OrderedCollectionChangeSet}\n     * that describes the update.\n     * <p>\n     * Changeset observables do not support backpressure as a changeset depends on the state of the previous\n     * changeset. Handling backpressure should therefor be left to users.\n     *\n     * @param results {@link RealmResults} to listen to changes for.\n     * @param realm {@link Realm} instance results are coming from.\n     * @param <E> type of RealmObject\n     * @return Rx observable that emit all updates + their changeset.\n     */\n    <E> Observable<CollectionChange<RealmResults<E>>> changesetsFrom(Realm realm, RealmResults<E> results);\n\n    /**\n     * Creates a Flowable for a {@link RealmResults}. It should emit the initial RealmResult when subscribed to and\n     * on each subsequent update of the RealmResults.\n     * <p>\n     * Realm observables are hot as RealmResults are automatically kept up to date.\n     *\n     * @param results {@link RealmResults} to listen to changes for.\n     * @param realm {@link DynamicRealm} instance results are coming from.\n     * @return Rx observable that emit all updates to the RealmResults.\n     */\n    <E> Flowable<RealmResults<E>> from(DynamicRealm realm, RealmResults<E> results);\n\n    /**\n     * Creates an Observable for a {@link RealmResults}. It should emit the initial RealmResult when subscribed to and\n     * on each subsequent update of the RealmResults it should emit the RealmResults + the {@link OrderedCollectionChangeSet}\n     * that describes the update.\n     * <p>\n     * Changeset observables do not support backpressure as a changeset depends on the state of the previous\n     * changeset. Handling backpressure should therefor be left to users.\n     *\n     * @param results {@link RealmResults} to listen to changes for.\n     * @param realm {@link Realm} instance results are coming from.\n     * @return Rx observable that emit all updates + their changeset.\n     */\n    <E> Observable<CollectionChange<RealmResults<E>>> changesetsFrom(DynamicRealm realm, RealmResults<E> results);\n\n    /**\n     * Creates an Observable for a {@link RealmList}. It should emit the initial list when subscribed to and on each\n     * subsequent update of the RealmList.\n     * <p>\n     * RealmList observables are hot as RealmLists are automatically kept up to date.\n     * <p>\n     * Note: {@link io.realm.RealmChangeListener} is currently not supported on RealmLists.\n     *\n     * @param list RealmObject to listen to changes for.\n     * @param realm {@link Realm} instance list is coming from.\n     * @param <E> type of query target\n     */\n    <E> Flowable<RealmList<E>> from(Realm realm, RealmList<E> list);\n\n    /**\n     * Creates an Observable for a {@link RealmList}. It should emit the initial RealmList when subscribed to and\n     * on each subsequent update of the RealmIst it should emit the RealmList + the {@link OrderedCollectionChangeSet}\n     * that describes the update.\n     * <p>\n     * Changeset observables do not support backpressure as a changeset depends on the state of the previous\n     * changeset. Handling backpressure should therefor be left to users.\n     *\n     * @param list {@link RealmList} to listen to changes for.\n     * @param realm {@link Realm} instance list is coming from.\n     * @param <E> type of RealmObject\n     * @return Rx observable that emit all updates + their changeset.\n     */\n    <E> Observable<CollectionChange<RealmList<E>>> changesetsFrom(Realm realm, RealmList<E> list);\n\n    /**\n     * Creates a Flowable for a {@link RealmList}. It should emit the initial list when subscribed to and on each\n     * subsequent update of the RealmList.\n     * <p>\n     * RealmList observables are hot as RealmLists are automatically kept up to date.\n     * <p>\n     * Note: {@link io.realm.RealmChangeListener} is currently not supported on RealmLists.\n     *\n     * @param list RealmList to listen to changes for.\n     * @param realm {@link DynamicRealm} instance list is coming from.\n     */\n    <E> Flowable<RealmList<E>> from(DynamicRealm realm, RealmList<E> list);\n\n    /**\n     * Creates an Observable for a {@link RealmList}. It should emit the initial RealmList when subscribed to and\n     * on each subsequent update of the RealmList it should emit the RealmList + the {@link OrderedCollectionChangeSet}\n     * that describes the update.\n     * <p>\n     * Changeset observables do not support backpressure as a changeset depends on the state of the previous\n     * changeset. Handling backpressure should therefor be left to users.\n     *\n     * @param list {@link RealmList} to listen to changes for.\n     * @param realm {@link Realm} instance list is coming from.\n     * @return Rx observable that emit all updates + their changeset.\n     */\n    <E> Observable<CollectionChange<RealmList<E>>> changesetsFrom(DynamicRealm realm, RealmList<E> list);\n\n    /**\n     * Creates a Flowable for a {@link RealmObject}. It should emit the initial object when subscribed to and on each\n     * subsequent update of the object.\n     * <p>\n     * RealmObject observables are hot as RealmObjects are automatically kept up to date.\n     *\n     * @param object RealmObject to listen to changes for.\n     * @param realm {@link Realm} instance object is coming from.\n     * @param <E> type of query target\n     */\n    <E extends RealmModel> Flowable<E> from(Realm realm, E object);\n\n    /**\n     * Creates an Observable for a {@link RealmObject}. It should emit the initial object when subscribed to and on each\n     * subsequent update of the object it should emit the object + the {@link io.realm.ObjectChangeSet} that describes\n     * the update.\n     * <p>\n     * Changeset observables do not support backpressure as a changeset depends on the state of the previous\n     * changeset. Handling backpressure should therefore be left to the user.\n     *\n     * @param object RealmObject to listen to changes for.\n     * @param realm {@link Realm} instance object is coming from.\n     * @param <E> type of RealmObject\n     */\n    <E extends RealmModel> Observable<ObjectChange<E>> changesetsFrom(Realm realm, E object);\n\n    /**\n     * Creates a Flowable for a {@link DynamicRealmObject}. It should emit the initial object when subscribed to and\n     * on each subsequent update of the object.\n     * <p>\n     * DynamicRealmObject observables are hot as DynamicRealmObjects automatically are kept up to date.\n     *\n     * @param object DynamicRealmObject to listen to changes for.\n     * @param realm {@link DynamicRealm} instance object is coming from.\n     */\n    Flowable<DynamicRealmObject> from(DynamicRealm realm, DynamicRealmObject object);\n\n    /**\n     * Creates an Observable for a {@link RealmObject}. It should emit the initial object when subscribed to and on each\n     * subsequent update of the object it should emit the object + the {@link io.realm.ObjectChangeSet} that describes\n     * the update.\n     * <p>\n     * Changeset observables do not support backpressure as a changeset depends on the state of the previous\n     * changeset. Handling backpressure should therefore be left to the user.\n     *\n     * @param object RealmObject to listen to changes for.\n     * @param realm {@link Realm} instance object is coming from.\n     */\n    Observable<ObjectChange<DynamicRealmObject>> changesetsFrom(DynamicRealm realm, DynamicRealmObject object);\n\n    /**\n     * Creates a Single from a {@link RealmQuery}. It should emit the query and then complete.\n     * <p>\n     * A RealmQuery observable is cold.\n     *\n     * @param query RealmQuery to emit.\n     * @param realm {@link Realm} instance query is coming from.\n     * @param <E> type of query target\n     */\n    <E> Single<RealmQuery<E>> from(Realm realm, RealmQuery<E> query);\n\n    /**\n     * Creates a Single from a {@link RealmQuery}. It should emit the query and then complete.\n     * <p>\n     * A RealmQuery observable is cold.\n     *\n     * @param query RealmObject to listen to changes for.\n     * @param realm {@link DynamicRealm} instance query is coming from.\n     */\n    <E> Single<RealmQuery<E>> from(DynamicRealm realm, RealmQuery<E> query);\n}\n"
  },
  {
    "path": "realm/realm-library/src/main/java/io/realm/rx/package-info.java",
    "content": "/*\n * Copyright 2017 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@javax.annotation.ParametersAreNonnullByDefault\npackage io.realm.rx;\n"
  },
  {
    "path": "realm/realm-library/src/objectServer/AndroidManifest.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    package=\"io.realm\" >\n\n    <uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\" />\n    <uses-permission android:name=\"android.permission.INTERNET\" />\n\n</manifest>"
  },
  {
    "path": "realm/realm-library/src/objectServer/java/io/realm/exceptions/DownloadingRealmInterruptedException.java",
    "content": "/*\n * Copyright 2017 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\npackage io.realm.exceptions;\n\nimport io.realm.annotations.Beta;\nimport io.realm.mongodb.sync.SyncConfiguration;\n\n\n/**\n * Exception class used when a Realm was interrupted while downloading the initial data set.\n * This can only happen if {@link SyncConfiguration.Builder#waitForInitialRemoteData()} is set.\n */\n@Beta\npublic class DownloadingRealmInterruptedException extends RuntimeException {\n    public DownloadingRealmInterruptedException(SyncConfiguration syncConfig, Throwable exception) {\n        super(\"Realm was interrupted while downloading the latest changes from the server: \" + syncConfig.getPath(),\n                exception);\n    }\n    public DownloadingRealmInterruptedException(SyncConfiguration syncConfig, String message) {\n        super(\"Realm was interrupted while downloading the latest changes from the server: \" + syncConfig.getPath() + \"\\n\" + message);\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/objectServer/java/io/realm/internal/ErrorCategory.java",
    "content": "/*\n * Copyright 2023 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\npackage io.realm.internal;\n\nimport java.lang.annotation.Native;\n\nimport io.realm.mongodb.ErrorCode;\n\npublic class ErrorCategory {\n    @Native // annotate a member to force JNI header generation\n    public static final byte RLM_APP_ERROR_CATEGORY_LOGIC = 0;\n    public static final byte RLM_APP_ERROR_CATEGORY_RUNTIME = 1;\n    public static final byte RLM_APP_ERROR_CATEGORY_INVALID_ARGUMENT = 2;\n    public static final byte RLM_APP_ERROR_CATEGORY_FILE_ACCESS = 3;\n    public static final byte RLM_APP_ERROR_CATEGORY_SYSTEM = 4; // System error - POSIX errno, Win32 HRESULT, etc.\n    public static final byte RLM_SYNC_ERROR_CATEGORY_APP = 5;\n    public static final byte RLM_SYNC_ERROR_CATEGORY_CLIENT = 6;\n    public static final byte RLM_SYNC_ERROR_CATEGORY_JSON = 7;\n    public static final byte RLM_SYNC_ERROR_CATEGORY_SERVICE = 8;\n    public static final byte RLM_SYNC_ERROR_CATEGORY_HTTP = 9;\n    public static final byte RLM_SYNC_ERROR_CATEGORY_CUSTOM = 10;\n    public static final byte RLM_SYNC_ERROR_CATEGORY_WEBSOCKET = 11;\n    public static final byte RLM_SYNC_ERROR_CATEGORY_SYNC = 12;\n    public static final byte RLM_SYNC_ERROR_CATEGORY_UNKNOWN = 13; // Unknown source of error. This is not a category exposed by Core.\n\n    public static String toCategory(byte value) {\n        String category;\n        switch (value) {\n            case RLM_APP_ERROR_CATEGORY_LOGIC:\n                category = ErrorCode.Type.LOGIC;\n                break;\n            case RLM_APP_ERROR_CATEGORY_RUNTIME:\n                category = ErrorCode.Type.RUNTIME;\n                break;\n            case RLM_APP_ERROR_CATEGORY_INVALID_ARGUMENT:\n                category = ErrorCode.Type.INVALID_ARGUMENT;\n                break;\n            case RLM_APP_ERROR_CATEGORY_SYSTEM:\n                category = ErrorCode.Type.SYSTEM;\n                break;\n            case RLM_APP_ERROR_CATEGORY_FILE_ACCESS:\n                category = ErrorCode.Type.FILE_ACCESS;\n                break;\n            case RLM_SYNC_ERROR_CATEGORY_APP:\n                category = ErrorCode.Type.APP;\n                break;\n            case RLM_SYNC_ERROR_CATEGORY_CLIENT:\n                category = ErrorCode.Type.CLIENT;\n                break;\n            case RLM_SYNC_ERROR_CATEGORY_JSON:\n                category = ErrorCode.Type.JSON;\n                break;\n            case RLM_SYNC_ERROR_CATEGORY_SERVICE:\n                category = ErrorCode.Type.SERVICE;\n                break;\n            case RLM_SYNC_ERROR_CATEGORY_HTTP:\n                category = ErrorCode.Type.HTTP;\n                break;\n            case RLM_SYNC_ERROR_CATEGORY_CUSTOM:\n                category = ErrorCode.Type.CUSTOM;\n                break;\n            case RLM_SYNC_ERROR_CATEGORY_WEBSOCKET:\n                category = ErrorCode.Type.WEBSOCKET;\n                break;\n            case RLM_SYNC_ERROR_CATEGORY_SYNC:\n                category = ErrorCode.Type.SYNC;\n                break;\n            default:\n                category = ErrorCode.Type.UNKNOWN;\n        }\n        return category;\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/objectServer/java/io/realm/internal/SyncObjectServerFacade.java",
    "content": "/*\n * Copyright 2016 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\npackage io.realm.internal;\n\nimport android.annotation.SuppressLint;\nimport android.content.Context;\nimport android.content.IntentFilter;\nimport android.net.ConnectivityManager;\n\nimport org.bson.BsonValue;\n\nimport java.lang.reflect.Field;\nimport java.lang.reflect.InvocationTargetException;\nimport java.lang.reflect.Method;\nimport java.util.Map;\nimport java.util.concurrent.TimeUnit;\n\nimport io.realm.Realm;\nimport io.realm.RealmConfiguration;\nimport io.realm.exceptions.DownloadingRealmInterruptedException;\nimport io.realm.exceptions.RealmException;\nimport io.realm.internal.android.AndroidCapabilities;\nimport io.realm.internal.jni.JniBsonProtocol;\nimport io.realm.internal.network.NetworkStateReceiver;\nimport io.realm.internal.objectstore.OsApp;\nimport io.realm.internal.objectstore.OsAsyncOpenTask;\nimport io.realm.mongodb.App;\nimport io.realm.mongodb.AppConfiguration;\nimport io.realm.mongodb.User;\nimport io.realm.mongodb.sync.AutomaticClientResetStrategy;\nimport io.realm.mongodb.sync.RecoverOrDiscardUnsyncedChangesStrategy;\nimport io.realm.mongodb.sync.RecoverUnsyncedChangesStrategy;\nimport io.realm.mongodb.sync.DiscardUnsyncedChangesStrategy;\nimport io.realm.mongodb.sync.ManuallyRecoverUnsyncedChangesStrategy;\nimport io.realm.mongodb.sync.MutableSubscriptionSet;\nimport io.realm.mongodb.sync.SubscriptionSet;\nimport io.realm.mongodb.sync.Sync;\nimport io.realm.mongodb.sync.SyncClientResetStrategy;\nimport io.realm.mongodb.sync.SyncConfiguration;\n\n@SuppressWarnings({\"unused\", \"WeakerAccess\"}) // Used through reflection. See ObjectServerFacade\n@Keep\npublic class SyncObjectServerFacade extends ObjectServerFacade {\n\n    private static final String WRONG_TYPE_OF_CONFIGURATION =\n            \"'configuration' has to be an instance of 'SyncConfiguration'.\";\n    @SuppressLint(\"StaticFieldLeak\") //\n    private static Context applicationContext;\n    private static volatile Method removeSessionMethod;\n    private static volatile Field osAppField;\n    RealmCacheAccessor accessor;\n    RealmInstanceFactory realmInstanceFactory;\n\n    @Override\n    public void initialize(Context context, String userAgent, RealmCacheAccessor accessor, RealmInstanceFactory realmInstanceFactory) {\n        if (applicationContext == null) {\n            applicationContext = context;\n            applicationContext.registerReceiver(new NetworkStateReceiver(),\n                    new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION));\n        }\n        this.accessor = accessor;\n        this.realmInstanceFactory = realmInstanceFactory;\n    }\n\n    @Override\n    public void realmClosed(RealmConfiguration configuration) {\n        // Last Thread using the specified configuration is closed\n        // delete the wrapped Java session\n        if (configuration instanceof SyncConfiguration) {\n            SyncConfiguration syncConfig = (SyncConfiguration) configuration;\n            invokeRemoveSession(syncConfig);\n        } else {\n            throw new IllegalArgumentException(WRONG_TYPE_OF_CONFIGURATION);\n        }\n    }\n\n    @Keep\n    public interface BeforeClientResetHandler {\n        void onBeforeReset(long beforePtr, OsRealmConfig config);\n    }\n\n    @Keep\n    public interface AfterClientResetHandler {\n        void onAfterReset(long beforePtr, long afterPtr, OsRealmConfig config, boolean didRecover);\n    }\n\n    @Override\n    public Object[] getSyncConfigurationOptions(RealmConfiguration config) {\n        if (config instanceof SyncConfiguration) {\n            SyncConfiguration syncConfig = (SyncConfiguration) config;\n            User user = syncConfig.getUser();\n            // Check if user is logged out\n            if (!user.isLoggedIn()) {\n                throw new IllegalStateException(\"User is not logged in: \" + user);\n            }\n            App app = user.getApp();\n            String rosServerUrl = syncConfig.getServerUrl().toString();\n            String rosUserIdentity = user.getId();\n            String syncRealmAuthUrl = user.getApp().getConfiguration().getBaseUrl().toString();\n            String rosUserProvider = user.getProviderType().getId();\n            String syncUserRefreshToken = user.getRefreshToken();\n            String syncUserAccessToken = user.getAccessToken();\n            String deviceId = user.getDeviceId();\n            byte sessionStopPolicy = syncConfig.getSessionStopPolicy().getNativeValue();\n            String urlPrefix = syncConfig.getUrlPrefix();\n            String customAuthorizationHeaderName = app.getConfiguration().getAuthorizationHeaderName();\n            Map<String, String> customHeaders = app.getConfiguration().getCustomRequestHeaders();\n            SyncClientResetStrategy clientResetStrategy = syncConfig.getSyncClientResetStrategy();\n\n\n            byte clientResetMode = -1; // undefined value\n            if (clientResetStrategy instanceof ManuallyRecoverUnsyncedChangesStrategy) {\n                clientResetMode = OsRealmConfig.CLIENT_RESYNC_MODE_MANUAL;\n            } else if (clientResetStrategy instanceof DiscardUnsyncedChangesStrategy) {\n                clientResetMode = OsRealmConfig.CLIENT_RESYNC_MODE_DISCARD_LOCAL;\n            } else if (clientResetStrategy instanceof RecoverUnsyncedChangesStrategy) {\n                clientResetMode = OsRealmConfig.CLIENT_RESYNC_MODE_RECOVER;\n            } else if (clientResetStrategy instanceof RecoverOrDiscardUnsyncedChangesStrategy) {\n                clientResetMode = OsRealmConfig.CLIENT_RESYNC_MODE_RECOVER_OR_DISCARD;\n            }\n\n            BeforeClientResetHandler beforeClientResetHandler = (localPtr, osRealmConfig) -> {\n                NativeContext.execute(nativeContext -> {\n                    Realm before = realmInstanceFactory.createInstance(new OsSharedRealm(localPtr, osRealmConfig, nativeContext));\n\n                    if (clientResetStrategy instanceof AutomaticClientResetStrategy) {\n                        ((AutomaticClientResetStrategy) clientResetStrategy).onBeforeReset(before);\n                    }\n                });\n            };\n            AfterClientResetHandler afterClientResetHandler = (localPtr, afterPtr, osRealmConfig, didRecover) -> {\n                NativeContext.execute(nativeContext -> {\n                    Realm before = realmInstanceFactory.createInstance(new OsSharedRealm(localPtr, osRealmConfig, nativeContext));\n                    Realm after = realmInstanceFactory.createInstance(new OsSharedRealm(afterPtr, osRealmConfig, nativeContext));\n\n                    if (clientResetStrategy instanceof DiscardUnsyncedChangesStrategy) {\n                        ((DiscardUnsyncedChangesStrategy) clientResetStrategy).onAfterReset(before, after);\n                    } else if (clientResetStrategy instanceof RecoverUnsyncedChangesStrategy) {\n                        ((RecoverUnsyncedChangesStrategy) clientResetStrategy).onAfterReset(before, after);\n                    } else if (clientResetStrategy instanceof RecoverOrDiscardUnsyncedChangesStrategy) {\n                        if (didRecover) {\n                            ((RecoverOrDiscardUnsyncedChangesStrategy) clientResetStrategy).onAfterRecovery(before, after);\n                        } else {\n                            ((RecoverOrDiscardUnsyncedChangesStrategy) clientResetStrategy).onAfterDiscard(before, after);\n                        }\n                    }\n                });\n            };\n\n            long appNativePointer;\n\n            // We cannot get the app native pointer without exposing it in the public API due to\n            // how our packages are structured. Instead of polluting the API we use reflection to\n            // access it.\n            try {\n                if (osAppField == null) {\n                    synchronized (SyncObjectServerFacade.class) {\n                        if (osAppField == null) {\n                            Field field = App.class.getDeclaredField(\"osApp\");\n                            field.setAccessible(true);\n                            osAppField = field;\n                        }\n                    }\n                }\n                OsApp osApp = (OsApp) osAppField.get(app);\n                appNativePointer = osApp.getNativePtr();\n            } catch (Exception e) {\n                throw new RuntimeException(e);\n            }\n\n            // TODO Simplify. org.bson serialization only allows writing full documents, so the partition\n            //  key is embedded in a document with key 'value' and unwrapped in JNI.\n            String encodedPartitionValue = null;\n            if (syncConfig.isPartitionBasedSyncConfiguration()) {\n                BsonValue partitionValue = syncConfig.getPartitionValue();\n                switch (partitionValue.getBsonType()) {\n                    case STRING:\n                    case OBJECT_ID:\n                    case INT32:\n                    case INT64:\n                    case BINARY:\n                    case NULL:\n                        encodedPartitionValue = JniBsonProtocol.encode(partitionValue, AppConfiguration.DEFAULT_BSON_CODEC_REGISTRY);\n                        break;\n                    default:\n                        throw new IllegalArgumentException(\"Unsupported type: \" + partitionValue);\n                }\n            }\n\n            int i = 0;\n            Object[] configObj = new Object[SYNC_CONFIG_OPTIONS];\n            configObj[i++] = rosUserIdentity;\n            configObj[i++] = rosUserProvider;\n            configObj[i++] = rosServerUrl;\n            configObj[i++] = syncRealmAuthUrl;\n            configObj[i++] = syncUserRefreshToken;\n            configObj[i++] = syncUserAccessToken;\n            configObj[i++] = deviceId;\n            configObj[i++] = sessionStopPolicy;\n            configObj[i++] = urlPrefix;\n            configObj[i++] = customAuthorizationHeaderName;\n            configObj[i++] = customHeaders;\n            configObj[i++] = clientResetMode;\n            configObj[i++] = beforeClientResetHandler;\n            configObj[i++] = afterClientResetHandler;\n            configObj[i++] = encodedPartitionValue;\n            configObj[i++] = app.getSync();\n            configObj[i++] = appNativePointer;\n            configObj[i++] = syncConfig.syncClientValidateSsl();\n            configObj[i++] = syncConfig.getServerCertificateFilePath();\n            return configObj;\n        } else {\n            return new Object[SYNC_CONFIG_OPTIONS];\n        }\n    }\n\n    public static Context getApplicationContext() {\n        return applicationContext;\n    }\n\n    @Override\n    public void wrapObjectStoreSessionIfRequired(OsRealmConfig config) {\n        if (config.getRealmConfiguration() instanceof SyncConfiguration) {\n            SyncConfiguration syncConfig = (SyncConfiguration) config.getRealmConfiguration();\n            App app = syncConfig.getUser().getApp();\n            app.getSync().getOrCreateSession(syncConfig);\n        }\n    }\n\n    @Override\n    public String getSyncServerCertificateAssetName(RealmConfiguration configuration) {\n        if (configuration instanceof SyncConfiguration) {\n            SyncConfiguration syncConfig = (SyncConfiguration) configuration;\n            return syncConfig.getServerCertificateAssetName();\n        } else {\n            throw new IllegalArgumentException(WRONG_TYPE_OF_CONFIGURATION);\n        }\n    }\n\n    @Override\n    public String getSyncServerCertificateFilePath(RealmConfiguration configuration) {\n        if (configuration instanceof SyncConfiguration) {\n            SyncConfiguration syncConfig = (SyncConfiguration) configuration;\n            return syncConfig.getServerCertificateFilePath();\n        } else {\n            throw new IllegalArgumentException(WRONG_TYPE_OF_CONFIGURATION);\n        }\n    }\n\n    //FIXME remove this reflection call once we redesign the SyncManager to separate interface\n    //      from implementation to avoid issue like exposing internal method like SyncManager#removeSession\n    //      or SyncSession#close. This happens because SyncObjectServerFacade is internal, whereas\n    //      SyncManager#removeSession or SyncSession#close are package private & should not be public.\n    private void invokeRemoveSession(SyncConfiguration syncConfig) {\n        try {\n            if (removeSessionMethod == null) {\n                synchronized (SyncObjectServerFacade.class) {\n                    if (removeSessionMethod == null) {\n                        Method removeSession = Sync.class.getDeclaredMethod(\"removeSession\", SyncConfiguration.class);\n                        removeSession.setAccessible(true);\n                        removeSessionMethod = removeSession;\n                    }\n                }\n            }\n            removeSessionMethod.invoke(syncConfig.getUser().getApp().getSync(), syncConfig);\n        } catch (NoSuchMethodException e) {\n            throw new RealmException(\"Could not lookup method to remove session: \" + syncConfig.toString(), e);\n        } catch (InvocationTargetException e) {\n            throw new RealmException(\"Could not invoke method to remove session: \" + syncConfig.toString(), e);\n        } catch (IllegalAccessException e) {\n            throw new RealmException(\"Could not remove session: \" + syncConfig.toString(), e);\n        }\n    }\n\n    @Override\n    public void downloadInitialRemoteChanges(RealmConfiguration config) {\n        if (config instanceof SyncConfiguration) {\n            SyncConfiguration syncConfig = (SyncConfiguration) config;\n            if (syncConfig.shouldWaitForInitialRemoteData()) {\n                if (new AndroidCapabilities().isMainThread()) {\n                    throw new IllegalStateException(\"waitForInitialRemoteData() cannot be used synchronously on the main thread. Use Realm.getInstanceAsync() instead.\");\n                }\n                downloadInitialFullRealm(syncConfig);\n            }\n        }\n    }\n\n    // This is guaranteed by other code to never run on the UI thread.\n    private void downloadInitialFullRealm(SyncConfiguration syncConfig) {\n        OsAsyncOpenTask task = new OsAsyncOpenTask(new OsRealmConfig.Builder(syncConfig).build());\n        try {\n            task.start(syncConfig.getInitialRemoteDataTimeout(TimeUnit.MILLISECONDS), TimeUnit.MILLISECONDS);\n        } catch (InterruptedException e) {\n            throw new DownloadingRealmInterruptedException(syncConfig, e);\n        }\n    }\n\n    @Override\n    public boolean wasDownloadInterrupted(Throwable throwable) {\n        return (throwable instanceof DownloadingRealmInterruptedException);\n    }\n\n    @Override\n    public void createNativeSyncSession(RealmConfiguration configuration) {\n        if (configuration instanceof SyncConfiguration) {\n            SyncConfiguration syncConfig = (SyncConfiguration) configuration;\n            App app = syncConfig.getUser().getApp();\n            app.getSync().getOrCreateSession(syncConfig);\n        }\n    }\n\n    @Override\n    public void checkFlexibleSyncEnabled(RealmConfiguration configuration) {\n        if (configuration instanceof SyncConfiguration) {\n            SyncConfiguration syncConfig = (SyncConfiguration) configuration;\n            if (!syncConfig.isFlexibleSyncConfiguration()) {\n                throw new IllegalStateException(\"This method is only available for synchronized \" +\n                        \"realms configured for Flexible Sync. This realm is configured for \" +\n                        \"Partition-based Sync: \" + configuration.getPath());\n            }\n        } else {\n            throw new IllegalStateException(\"This method is only available for synchronized Realms.\");\n        }\n    }\n\n    @Override\n    public void downloadInitialFlexibleSyncData(Realm realm, RealmConfiguration configuration) {\n        if (configuration instanceof SyncConfiguration) {\n            SyncConfiguration syncConfig = (SyncConfiguration) configuration;\n            if (syncConfig.isFlexibleSyncConfiguration()) {\n                SyncConfiguration.InitialFlexibleSyncSubscriptions handler  = syncConfig.getInitialSubscriptionsHandler();\n                if (handler != null) {\n                    SubscriptionSet subscriptions = realm.getSubscriptions();\n                    subscriptions.update(new SubscriptionSet.UpdateCallback() {\n                        @Override\n                        public void update(MutableSubscriptionSet subscriptions) {\n                            handler.configure(realm, subscriptions);\n                        }\n                    });\n                    if (!subscriptions.waitForSynchronization()) {\n                        throw new IllegalStateException(\"Realm couldn't be fully opened because \" +\n                                \"flexible sync encountered an error when bootstrapping initial\" +\n                                \"subscriptions: \" + subscriptions.getErrorMessage());\n                    }\n                }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/objectServer/java/io/realm/internal/async/RealmEventStreamAsyncTaskImpl.java",
    "content": "/*\n * Copyright 2020 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\npackage io.realm.internal.async;\n\nimport java.io.IOException;\n\nimport io.realm.internal.Util;\nimport io.realm.internal.objectserver.EventStream;\nimport io.realm.mongodb.App;\nimport io.realm.mongodb.AppException;\nimport io.realm.mongodb.ErrorCode;\nimport io.realm.mongodb.RealmEventStreamAsyncTask;\nimport io.realm.mongodb.mongo.events.BaseChangeEvent;\n\npublic class RealmEventStreamAsyncTaskImpl<T> implements RealmEventStreamAsyncTask<T> {\n    private final String name;\n    private final Executor<T> executor;\n    private volatile EventStream<T> eventStream;\n    private volatile boolean isCancelled;\n    private Thread thread;\n\n    public RealmEventStreamAsyncTaskImpl(final String name, final Executor<T> executor) {\n        Util.checkNull(executor, \"name\");\n        Util.checkNull(executor, \"executor\");\n\n        this.executor = executor;\n        this.name = name;\n    }\n\n    @Override\n    public synchronized void get(App.Callback<BaseChangeEvent<T>> callback) throws IllegalStateException {\n        Util.checkNull(callback, \"callback\");\n\n        if (thread != null) {\n            throw new IllegalStateException(\"Resource already open\");\n        } else {\n            thread = new Thread(new Runnable() {\n                @Override\n                public void run() {\n                    try {\n                        eventStream = executor.run();\n\n                        while (true) {\n                            BaseChangeEvent<T> nextEvent = eventStream.getNextEvent();\n                            callback.onResult(App.Result.withResult(nextEvent));\n                        }\n                    } catch (AppException exception) {\n                        callback.onResult(App.Result.withError(exception));\n                    } catch (IOException exception) {\n                        AppException appException = new AppException(ErrorCode.NETWORK_IO_EXCEPTION, exception);\n                        callback.onResult(App.Result.withError(appException));\n                    }\n                }\n            }, String.format(\"RealmStreamTask|%s\", name));\n\n            thread.start();\n        }\n    }\n\n    @Override\n    public boolean isOpen() {\n        return (eventStream != null) && eventStream.isOpen();\n    }\n\n    @Override\n    public void cancel() {\n        if (eventStream != null) {\n            isCancelled = true;\n            eventStream.close();\n        }\n    }\n\n    @Override\n    public boolean isCancelled() {\n        return isCancelled;\n    }\n\n    public abstract static class Executor<T> {\n\n        /**\n         * Executes the code block.\n         *\n         * @return the result yielded by the task.\n         */\n        public abstract EventStream<T> run() throws IOException;\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/objectServer/java/io/realm/internal/async/RealmEventStreamTaskImpl.java",
    "content": "/*\n * Copyright 2020 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\npackage io.realm.internal.async;\n\nimport java.io.IOException;\n\nimport io.realm.internal.Util;\nimport io.realm.internal.objectserver.EventStream;\nimport io.realm.mongodb.AppException;\nimport io.realm.mongodb.RealmEventStreamTask;\nimport io.realm.mongodb.mongo.events.BaseChangeEvent;\n\npublic class RealmEventStreamTaskImpl<T> implements RealmEventStreamTask<T> {\n    private final String name;\n    private final Executor<T> executor;\n    private volatile EventStream<T> eventStream;\n    private volatile boolean isCancelled;\n\n    public RealmEventStreamTaskImpl(final String name, final Executor<T> executor) {\n        Util.checkNull(executor, \"name\");\n        Util.checkNull(executor, \"executor\");\n\n        this.executor = executor;\n        this.name = name;\n    }\n\n    private EventStream<T> getEventStream() throws IOException {\n        if (eventStream == null) {\n            eventStream = executor.run();\n        }\n\n        return this.eventStream;\n    }\n\n    @Override\n    public synchronized BaseChangeEvent<T> getNext() throws AppException, IOException {\n        eventStream = getEventStream();\n        return eventStream.getNextEvent();\n    }\n\n    @Override\n    public boolean isOpen() {\n        return (eventStream != null) && eventStream.isOpen();\n    }\n\n    @Override\n    public void cancel() {\n        if (eventStream != null) {\n            isCancelled = true;\n            eventStream.close();\n        }\n    }\n\n    @Override\n    public boolean isCancelled() {\n        return isCancelled;\n    }\n\n    public abstract static class Executor<T> {\n\n        /**\n         * Executes the code block.\n         *\n         * @return the result yielded by the task.\n         */\n        public abstract EventStream<T> run() throws IOException;\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/objectServer/java/io/realm/internal/async/RealmResultTaskImpl.java",
    "content": "/*\n * Copyright 2020 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\npackage io.realm.internal.async;\n\nimport java.util.concurrent.Future;\nimport java.util.concurrent.ThreadPoolExecutor;\n\nimport javax.annotation.Nullable;\n\nimport io.realm.internal.RealmNotifier;\nimport io.realm.internal.Util;\nimport io.realm.internal.android.AndroidCapabilities;\nimport io.realm.internal.android.AndroidRealmNotifier;\nimport io.realm.log.RealmLog;\nimport io.realm.mongodb.App;\nimport io.realm.mongodb.AppException;\nimport io.realm.mongodb.ErrorCode;\nimport io.realm.mongodb.RealmResultTask;\n\n/**\n * Implementation of RealmResultTask used internally by MongoDB Realm APIs. Implementation is\n * separate from the interface so that we can hide the constructor from end users.\n *\n * @param <T> the result type delivered by this task.\n */\npublic class RealmResultTaskImpl<T> implements RealmResultTask<T> {\n\n    private Future<?> pendingTask;\n    private volatile boolean isCancelled = false;\n    private final ThreadPoolExecutor service;\n    private Executor<T> executor;\n\n    /**\n     * Constructor for RealmResultTaskImpl.\n     *\n     * @param service  pool thread service on which the task will be executed.\n     * @param executor the code block executed by the task.\n     */\n    public RealmResultTaskImpl(ThreadPoolExecutor service, Executor<T> executor) {\n        Util.checkNull(service, \"service\");\n        this.service = service;\n        Util.checkNull(executor, \"executor\");\n        this.executor = executor;\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    @Override\n    public void cancel() {\n        if (pendingTask != null) {\n            pendingTask.cancel(true);\n            isCancelled = true;\n\n            // From \"Java Threads\": By Scott Oaks & Henry Wong\n            // cancelled tasks are never executed, but may\n            // accumulate in work queues, which may causes a memory leak\n            // if the task hold references (to an enclosing class for example)\n            // we can use purge() but one caveat applies: if a second thread attempts to add\n            // something to the pool (using the execute() method) at the same time the\n            // first thread is attempting to purge the queue the attempt to purge\n            // the queue fails and the cancelled object remain in the queue.\n            // A better way to cancel objects with thread pools is to use the remove()\n            service.getQueue().remove(pendingTask);\n        }\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    @Override\n    public boolean isCancelled() {\n        return isCancelled;\n    }\n\n    @Override\n    public T get() {\n        return executor.run();\n    }\n\n    @Override\n    public void getAsync(App.Callback<T> callback) {\n        Util.checkNull(callback, \"callback\");\n        Util.checkLooperThread(\"RealmResultTaskImpl can only run on looper threads.\");\n\n        RealmNotifier handler = new AndroidRealmNotifier(null, new AndroidCapabilities());\n\n        pendingTask = service.submit(new Runnable() {\n            @Override\n            public void run() {\n                try {\n                    postSuccess(handler, executor.run(), callback);\n                } catch (AppException e) {\n                    postError(handler, e, callback);\n                } catch (Throwable e) {\n                    postError(handler, new AppException(ErrorCode.UNKNOWN, \"Unexpected error\", e), callback);\n                }\n            }\n        });\n    }\n\n    private void postError(RealmNotifier handler,\n                           final AppException error,\n                           App.Callback<T> callback) {\n        boolean errorHandled;\n        Runnable action = new Runnable() {\n            @Override\n            public void run() {\n                if (!isCancelled) {\n                    callback.onResult(App.Result.withError(error));\n                }\n            }\n        };\n        errorHandled = handler.post(action);\n\n        if (!errorHandled) {\n            RealmLog.error(error, \"An error was thrown, but could not be posted: \\n\" + error.toString());\n        }\n    }\n\n    private void postSuccess(RealmNotifier handler,\n                             @Nullable final T result,\n                             App.Callback<T> callback) {\n        handler.post(new Runnable() {\n            @Override\n            public void run() {\n                if (!isCancelled) {\n                    callback.onResult((result == null) ? App.Result.success() : App.Result.withResult(result));\n                }\n            }\n        });\n    }\n\n    /**\n     * The Executor class represent the portion of code the RealmResultTaskImpl will execute.\n     *\n     * @param <T> the result type delivered by the task.\n     */\n    public abstract static class Executor<T> {\n\n        /**\n         * Executes the code block.\n         *\n         * @return the result yielded by the task.\n         */\n        @Nullable\n        public abstract T run();\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/objectServer/java/io/realm/internal/async/package-info.java",
    "content": "/*\n * Copyright 2017 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@javax.annotation.ParametersAreNonnullByDefault\npackage io.realm.internal.async;\n"
  },
  {
    "path": "realm/realm-library/src/objectServer/java/io/realm/internal/events/ChangeEvent.java",
    "content": "/*\n * Copyright 2020 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\npackage io.realm.internal.events;\n\nimport org.bson.BsonBoolean;\nimport org.bson.BsonDocument;\nimport org.bson.BsonString;\nimport org.bson.BsonValue;\nimport org.bson.codecs.DecoderContext;\nimport org.bson.codecs.configuration.CodecRegistry;\n\nimport io.realm.mongodb.AppException;\nimport io.realm.mongodb.ErrorCode;\nimport io.realm.mongodb.mongo.MongoNamespace;\nimport io.realm.mongodb.mongo.events.BaseChangeEvent;\nimport io.realm.mongodb.mongo.events.UpdateDescription;\n\nimport static io.realm.internal.Util.checkContainsKey;\nimport static io.realm.mongodb.mongo.events.BaseChangeEvent.OperationType.DELETE;\nimport static io.realm.mongodb.mongo.events.BaseChangeEvent.OperationType.INSERT;\nimport static io.realm.mongodb.mongo.events.BaseChangeEvent.OperationType.REPLACE;\nimport static io.realm.mongodb.mongo.events.BaseChangeEvent.OperationType.UNKNOWN;\nimport static io.realm.mongodb.mongo.events.BaseChangeEvent.OperationType.UPDATE;\n\n/**\n * The representation of a MongoDB Realm change event\n *\n * @param <DocumentT> the full document type\n * @see <a href=\"https://docs.mongodb.com/realm/triggers/database-triggers/index.html#database-change-events\">Realm - Database change events</a>\n */\n\npublic class ChangeEvent<DocumentT> extends BaseChangeEvent<DocumentT> {\n    \n    private final BsonDocument id; // Metadata related to the operation (the resumeToken).\n    private final MongoNamespace ns;\n\n    /**\n     * Constructs a change event.\n     *\n     * @param id                   The id of the change event.\n     * @param operationType        The operation type represented by the change event.\n     * @param fullDocument         The full document at some point after the change is applied.\n     * @param ns                   The namespace (database and collection) of the document.\n     * @param documentKey          The id if the underlying document that changed.\n     * @param updateDescription    The description of what has changed (for updates only).\n     * @param hasUncommittedWrites Whether this represents a local uncommitted write.\n     */\n    private ChangeEvent(\n            final BsonDocument id,\n            final OperationType operationType,\n            final DocumentT fullDocument,\n            final MongoNamespace ns,\n            final BsonDocument documentKey,\n            final UpdateDescription updateDescription,\n            final boolean hasUncommittedWrites\n    ) {\n        super(operationType, fullDocument, documentKey, updateDescription, hasUncommittedWrites);\n\n        this.id = id;\n        this.ns = ns;\n    }\n\n    /**\n     * Returns the ID of the change event itself.\n     *\n     * @return the id of this change event.\n     */\n    public BsonDocument getId() {\n        return id;\n    }\n\n    /**\n     * The namespace the change relates to.\n     *\n     * @return the namespace.\n     */\n    public MongoNamespace getNamespace() {\n        return ns;\n    }\n\n    /**\n     * Creates a copy of this change event with uncommitted writes flag set to false.\n     *\n     * @return new change event without uncommitted writes flag\n     */\n    public ChangeEvent<DocumentT> withoutUncommittedWrites() {\n        return new ChangeEvent<>(this.getId(),\n                this.getOperationType(),\n                this.getFullDocument(),\n                this.getNamespace(),\n                this.getDocumentKey(),\n                this.getUpdateDescription(),\n                false);\n    }\n\n    /**\n     * Serializes this change event into a {@link BsonDocument}.\n     *\n     * @return the serialized document.\n     */\n    @Override\n    public BsonDocument toBsonDocument() {\n        final BsonDocument asDoc = new BsonDocument();\n        asDoc.put(Fields.ID_FIELD, id);\n\n        asDoc.put(Fields.OPERATION_TYPE_FIELD, new BsonString(toRemote(getOperationType())));\n\n        final BsonDocument nsDoc = new BsonDocument();\n        nsDoc.put(Fields.NS_DB_FIELD, new BsonString(ns.getDatabaseName()));\n        nsDoc.put(Fields.NS_COLL_FIELD, new BsonString(getNamespace().getCollectionName()));\n        asDoc.put(Fields.NS_FIELD, nsDoc);\n\n        asDoc.put(Fields.DOCUMENT_KEY_FIELD, getDocumentKey());\n        DocumentT fullDocument = getFullDocument();\n\n        if ((fullDocument instanceof BsonValue) && ((BsonValue) fullDocument).isDocument()) {\n            asDoc.put(Fields.FULL_DOCUMENT_FIELD, (BsonValue) fullDocument);\n        }\n\n        UpdateDescription updateDescription = getUpdateDescription();\n        if (updateDescription != null) {\n            asDoc.put(Fields.UPDATE_DESCRIPTION_FIELD, updateDescription.toBsonDocument());\n        }\n\n        asDoc.put(Fields.WRITE_PENDING_FIELD, new BsonBoolean(hasUncommittedWrites()));\n        return asDoc;\n    }\n\n    /**\n     * Deserializes a {@link BsonDocument} into an instance of change event.\n     *\n     * @param document the serialized document\n     * @return the deserialized change event\n     */\n    static <T> ChangeEvent<T> fromBsonDocument(final BsonDocument document, final Class<T> documentClass, CodecRegistry codecRegistry) {\n        try {\n            checkContainsKey(Fields.ID_FIELD, document, \"document\");\n            checkContainsKey(Fields.OPERATION_TYPE_FIELD, document, \"document\");\n            checkContainsKey(Fields.NS_FIELD, document, \"document\");\n            checkContainsKey(Fields.DOCUMENT_KEY_FIELD, document, \"document\");\n        } catch (IllegalArgumentException exception) {\n            throw new AppException(ErrorCode.EVENT_DESERIALIZING, exception);\n        }\n\n        final BsonDocument nsDoc = document.getDocument(Fields.NS_FIELD);\n\n        final UpdateDescription updateDescription;\n        if (document.containsKey(Fields.UPDATE_DESCRIPTION_FIELD)) {\n            updateDescription = UpdateDescription.fromBsonDocument(\n                    document.getDocument(Fields.UPDATE_DESCRIPTION_FIELD)\n            );\n        } else {\n            updateDescription = null;\n        }\n\n        final T fullDocument;\n\n        if (document.containsKey(Fields.FULL_DOCUMENT_FIELD)) {\n            final BsonValue fdVal = document.get(Fields.FULL_DOCUMENT_FIELD);\n            if (fdVal.isDocument()) {\n                fullDocument = codecRegistry.get(documentClass).decode(fdVal.asDocument().asBsonReader(), DecoderContext.builder().build());\n            } else {\n                fullDocument = null;\n            }\n        } else {\n            fullDocument = null;\n        }\n\n        return new ChangeEvent<>(\n                document.getDocument(Fields.ID_FIELD),\n                fromRemote(document.getString(Fields.OPERATION_TYPE_FIELD).getValue()),\n                fullDocument,\n                new MongoNamespace(\n                        nsDoc.getString(Fields.NS_DB_FIELD).getValue(),\n                        nsDoc.getString(Fields.NS_COLL_FIELD).getValue()),\n                document.getDocument(Fields.DOCUMENT_KEY_FIELD),\n                updateDescription,\n                document.getBoolean(Fields.WRITE_PENDING_FIELD, BsonBoolean.FALSE).getValue());\n    }\n\n    private static final class Fields {\n        static final String ID_FIELD = \"_id\";\n        static final String OPERATION_TYPE_FIELD = \"operationType\";\n        static final String FULL_DOCUMENT_FIELD = \"fullDocument\";\n        static final String DOCUMENT_KEY_FIELD = \"documentKey\";\n\n        static final String NS_FIELD = \"ns\";\n        static final String NS_DB_FIELD = \"db\";\n        static final String NS_COLL_FIELD = \"coll\";\n\n        static final String UPDATE_DESCRIPTION_FIELD = \"updateDescription\";\n        static final String WRITE_PENDING_FIELD = \"writePending\";\n    }\n\n    /**\n     * Returns the appropriate local operation type enum value based on the remote operation type\n     * string from a change stream event.\n     *\n     * @param type the string description of the operation type.\n     * @return the operation type.\n     */\n    private static OperationType fromRemote(final String type) {\n        switch (type) {\n            case \"insert\":\n                return INSERT;\n            case \"delete\":\n                return DELETE;\n            case \"replace\":\n                return REPLACE;\n            case \"update\":\n                return UPDATE;\n            default:\n                return UNKNOWN;\n        }\n    }\n\n    /**\n     * Converts this operation to the remote string representation of the operation as\n     * represented in a {@link ChangeEvent} from a remote cluster.\n     *\n     * @return the remote representation of the update operation.\n     */\n    private String toRemote(OperationType operationType) {\n        switch (operationType) {\n            case INSERT:\n                return \"insert\";\n            case DELETE:\n                return \"delete\";\n            case REPLACE:\n                return \"replace\";\n            case UPDATE:\n                return \"update\";\n            default:\n                return \"unknown\";\n        }\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/objectServer/java/io/realm/internal/events/NetworkEventStream.java",
    "content": "package io.realm.internal.events;\n\nimport org.bson.codecs.configuration.CodecRegistry;\n\nimport java.io.IOException;\n\nimport io.realm.internal.objectserver.EventStream;\nimport io.realm.internal.objectstore.OsJavaNetworkTransport;\nimport io.realm.internal.objectstore.OsWatchStream;\nimport io.realm.mongodb.AppException;\nimport io.realm.mongodb.mongo.events.BaseChangeEvent;\n\npublic class NetworkEventStream<T> implements EventStream<T> {\n    private final OsJavaNetworkTransport.Response response;\n    private final OsWatchStream watchStream;\n    private final CodecRegistry codecRegistry;\n    private final Class<T> documentClass;\n\n    public NetworkEventStream(OsJavaNetworkTransport.Response response, CodecRegistry codecRegistry, Class<T> documentClass) {\n        this.response = response;\n        this.watchStream = new OsWatchStream(codecRegistry);\n        this.codecRegistry = codecRegistry;\n        this.documentClass = documentClass;\n    }\n\n    /**\n     * Fetch the next event from a given stream\n     *\n     * @return the next event\n     * @throws AppException on a stream error\n     */\n    @Override\n    public BaseChangeEvent<T> getNextEvent() throws AppException, IOException {\n        while (true) {\n            watchStream.feedLine(response.readBodyLine());\n            String watchStreamState = watchStream.getState();\n\n            if (watchStreamState.equals(OsWatchStream.HAVE_EVENT)) {\n                return ChangeEvent.fromBsonDocument(watchStream.getNextEvent(), documentClass, codecRegistry);\n            }\n            if (watchStreamState.equals(OsWatchStream.HAVE_ERROR)) {\n                response.close();\n                throw watchStream.getError();\n            }\n        }\n    }\n\n    /**\n     * Closes the current stream.\n     * <p>\n     * Note: we use a close flag because the underlaying input stream might not be thread safe.\n     *\n     * @see <a href=\"http://google.com\">https://github.com/square/okio/issues/163#issuecomment-127052956</a>\n     */\n    @Override\n    public void close() {\n        response.close();\n    }\n\n    /**\n     * Indicates whether or not the change stream is currently open.\n     *\n     * @return True if the underlying change stream is open.\n     */\n    @Override\n    public boolean isOpen() {\n        return response.isOpen();\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/objectServer/java/io/realm/internal/events/package-info.java",
    "content": "/*\n * Copyright 2017 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@javax.annotation.ParametersAreNonnullByDefault\npackage io.realm.internal.events;\n"
  },
  {
    "path": "realm/realm-library/src/objectServer/java/io/realm/internal/jni/JniBsonProtocol.java",
    "content": "/*\n * Copyright 2020 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\npackage io.realm.internal.jni;\n\nimport org.bson.BsonValue;\nimport org.bson.codecs.Codec;\nimport org.bson.codecs.Decoder;\nimport org.bson.codecs.DecoderContext;\nimport org.bson.codecs.Encoder;\nimport org.bson.codecs.EncoderContext;\nimport org.bson.codecs.configuration.CodecConfigurationException;\nimport org.bson.codecs.configuration.CodecRegistry;\nimport org.bson.json.JsonMode;\nimport org.bson.json.JsonReader;\nimport org.bson.json.JsonWriter;\nimport org.bson.json.JsonWriterSettings;\n\nimport java.io.StringReader;\nimport java.io.StringWriter;\n\nimport io.realm.mongodb.ErrorCode;\nimport io.realm.mongodb.AppException;\n\n/**\n * Protocol for passing {@link BsonValue}s to JNI.\n * <p>\n * For now this just encapsulated the BSON value in a document with key {@value VALUE}. This\n * overcomes the shortcoming of {@code org.bson.JsonWrite} not being able to serialize single values.\n */\npublic class JniBsonProtocol {\n\n    private static final String VALUE = \"value\";\n\n    private static JsonWriterSettings writerSettings = JsonWriterSettings.builder()\n            .outputMode(JsonMode.EXTENDED)\n            .build();\n\n    public static <T> String encode(T value, CodecRegistry registry) {\n        // catch possible missing codecs before the actual encoding\n        return encode(value, (Encoder<T>) getCodec(value.getClass(), registry));\n    }\n\n    public static <T> String encode(T value, Encoder<T> encoder) {\n        try {\n            StringWriter stringWriter = new StringWriter();\n            JsonWriter jsonWriter = new JsonWriter(stringWriter, writerSettings);\n            jsonWriter.writeStartDocument();\n            jsonWriter.writeName(VALUE);\n            encoder.encode(jsonWriter, value, EncoderContext.builder().build());\n            jsonWriter.writeEndDocument();\n            return stringWriter.toString();\n        } catch (CodecConfigurationException e) {\n            // same exception as in the guard above, but needed here as well nonetheless as the\n            // result might be wrapped inside an iterable or a map and the codec for the end type\n            // might be missing\n            throw new AppException(ErrorCode.BSON_CODEC_NOT_FOUND, \"Could not resolve encoder for end type\", e);\n        } catch (Exception e) {\n            throw new AppException(ErrorCode.BSON_ENCODING, \"Error encoding value\", e);\n        }\n    }\n\n    public static <T> T decode(String string, Class<T> clz, CodecRegistry registry) {\n        // catch possible missing codecs before the actual decoding\n        return decode(string, getCodec(clz, registry));\n    }\n\n    public static <T> T decode(String string, Decoder<T> decoder) {\n        try {\n            StringReader stringReader = new StringReader(string);\n            JsonReader jsonReader = new JsonReader(stringReader);\n            jsonReader.readStartDocument();\n            jsonReader.readName(VALUE);\n            T value = decoder.decode(jsonReader, DecoderContext.builder().build());\n            jsonReader.readEndDocument();\n            return value;\n        } catch (CodecConfigurationException e) {\n            // same exception as in the guard above, but needed here as well nonetheless as the\n            // result might be wrapped inside an iterable or a map and the codec for the end type\n            // might be missing\n            throw new AppException(ErrorCode.BSON_CODEC_NOT_FOUND, \"Could not resolve decoder for end type\" + string, e);\n        } catch (Exception e) {\n            throw new AppException(ErrorCode.BSON_DECODING, \"Error decoding value \" + string, e);\n        }\n    }\n\n    public static <T> Codec<T> getCodec(Class<T> clz, CodecRegistry registry) {\n        try {\n            return registry.get(clz);\n        } catch (CodecConfigurationException e) {\n            throw new AppException(ErrorCode.BSON_CODEC_NOT_FOUND, \"Could not resolve codec for \" + clz.getSimpleName(), e);\n        }\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/objectServer/java/io/realm/internal/log/obfuscator/ApiKeyObfuscator.java",
    "content": "/*\n * Copyright 2020 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\npackage io.realm.internal.log.obfuscator;\n\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.regex.Pattern;\n\n/**\n * Obfuscator for API key-related login requests. It will replace the {@code \"key\":\"<KEY>\"} pattern\n * with {@code \"key\":\"***\"}.\n */\n\npublic class ApiKeyObfuscator extends RegexPatternObfuscator {\n\n    public static final String API_KEY_KEY = \"key\";\n\n    private ApiKeyObfuscator(Map<Pattern, String> patternReplacementMap) {\n        super(patternReplacementMap);\n    }\n\n    /**\n     * Creates a {@link RegexPatternObfuscator} for API keys.\n     *\n     * @return an obfuscator that keeps API key information from being displayed in the logcat.\n     */\n    public static ApiKeyObfuscator obfuscator() {\n        return new ApiKeyObfuscator(getPatterns());\n    }\n\n    private static Map<Pattern, String> getPatterns() {\n        Map<Pattern, String> map = new HashMap<>();\n        map.put(Pattern.compile(\"((\\\"\" + API_KEY_KEY + \"\\\"):(\\\\s?\\\".+?\\\"))\"), \"\\\"\" + API_KEY_KEY + \"\\\":\\\"***\\\"\");\n        return map;\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/objectServer/java/io/realm/internal/log/obfuscator/CustomFunctionObfuscator.java",
    "content": "/*\n * Copyright 2020 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\npackage io.realm.internal.log.obfuscator;\n\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.regex.Pattern;\n\n/**\n * Obfuscator for custom function-related login requests. It will replace all function arguments\n * that appear before {@code \"options\":\"***\"} with {@code \"functionArgs\":\"***\"}.\n */\npublic class CustomFunctionObfuscator extends RegexPatternObfuscator {\n\n    public static final String CUSTOM_FUNCTION_KEY = \"functionArgs\";\n\n    private CustomFunctionObfuscator(Map<Pattern, String> patternReplacementMap) {\n        super(patternReplacementMap);\n    }\n\n    /**\n     * Creates a {@link RegexPatternObfuscator} for custom functions.\n     *\n     * @return an obfuscator that keeps custom function information from being displayed in the\n     * logcat.\n     */\n    public static CustomFunctionObfuscator obfuscator() {\n        return new CustomFunctionObfuscator(getPatterns());\n    }\n\n    private static Map<Pattern, String> getPatterns() {\n        Map<Pattern, String> map = new HashMap<>();\n        map.put(Pattern.compile(\"\\\\{(.+?),\\\"options\\\":\"), \"{\\\"\" + CUSTOM_FUNCTION_KEY + \"\\\":\\\"***\\\",\\\"options\\\":\");\n        return map;\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/objectServer/java/io/realm/internal/log/obfuscator/EmailPasswordObfuscator.java",
    "content": "/*\n * Copyright 2020 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\npackage io.realm.internal.log.obfuscator;\n\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.regex.Pattern;\n\n/**\n * Obfuscator for email- and password-related login requests.\n * <p>\n * It will replace the\n * <ul>\n * <li>{@code \"email\":\"<EMAIL>\"},</li>\n * <li>{@code \"username\":\"<USERNAME>\"} and</li>\n * <li>{@code \"password\":\"<PASSWORD>\"}</li>\n * </ul>\n * patterns with\n * <ul>\n * <li>{@code \"email\":\"***\"},</li>\n * <li>{@code \"username\":\"***\"} and</li>\n * <li>{@code \"password\":\"***\"}</li>\n * </ul>\n * respectively.\n */\npublic class EmailPasswordObfuscator extends RegexPatternObfuscator {\n\n    public static final String EMAIL_KEY = \"email\";\n    public static final String USERNAME_KEY = \"username\";\n    public static final String PASSWORD_KEY = \"password\";\n\n    private EmailPasswordObfuscator(Map<Pattern, String> patternReplacementMap) {\n        super(patternReplacementMap);\n    }\n\n    /**\n     * Creates a {@link RegexPatternObfuscator} for emails and passwords.\n     *\n     * @return an obfuscator that keeps emails and passwords from being displayed in the logcat.\n     */\n    public static EmailPasswordObfuscator obfuscator() {\n        return new EmailPasswordObfuscator(getPatterns());\n    }\n\n    private static Map<Pattern, String> getPatterns() {\n        Map<Pattern, String> map = new HashMap<>();\n        map.put(Pattern.compile(\"((\\\"\" + EMAIL_KEY + \"\\\"):(\\\".+?\\\"))\"), \"\\\"\" + EMAIL_KEY + \"\\\":\\\"***\\\"\");\n        map.put(Pattern.compile(\"((\\\"\" + USERNAME_KEY + \"\\\"):(\\\".+?\\\"))\"), \"\\\"\" + USERNAME_KEY + \"\\\":\\\"***\\\"\");\n        map.put(Pattern.compile(\"((\\\"\" + PASSWORD_KEY + \"\\\"):(\\\".+?\\\"))\"), \"\\\"\" + PASSWORD_KEY + \"\\\":\\\"***\\\"\");\n        return map;\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/objectServer/java/io/realm/internal/log/obfuscator/RegexPatternObfuscator.java",
    "content": "/*\n * Copyright 2020 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\npackage io.realm.internal.log.obfuscator;\n\nimport java.util.Map;\nimport java.util.Set;\nimport java.util.regex.Matcher;\nimport java.util.regex.Pattern;\n\nimport io.realm.internal.Util;\n\n/**\n * The obfuscator removes sensitive information from logcat entries.\n * <p>\n * Children classes have to provide a map of regex {@link Pattern}s and replacement strings to\n * correctly hide the information.\n * <p>\n * For example, the following pattern finds instances of {@code \"token\":\"<TOKEN_GOES_HERE>\"} in the\n * logcat: {@code Pattern.compile(\"((\\\"token\\\"):(\\\".+?\\\"))\")}. And the replacement string\n * {@code \"\\\"token\\\":\\\"***\\\"\"} replaces those instances with {@code \"token\":\"***\"}.\n */\npublic abstract class RegexPatternObfuscator {\n\n    private Map<Pattern, String> patternReplacementMap;\n\n    RegexPatternObfuscator(Map<Pattern, String> patternReplacementMap) {\n        this.patternReplacementMap = patternReplacementMap;\n    }\n\n    /**\n     * Obfuscates a string according to the patterns and replacements an obfuscator has.\n     *\n     * @param input the string to obfuscate\n     * @return the obfuscate string\n     */\n    public String obfuscate(String input) {\n        String obfuscatedString = input;\n        Set<Map.Entry<Pattern, String>> entries = patternReplacementMap.entrySet();\n        for (Map.Entry<Pattern, String> entry : entries) {\n            String replacement = entry.getValue();\n            Pattern pattern = entry.getKey();\n            Util.checkNull(replacement, \"replacement\");\n            Matcher matcher = pattern.matcher(obfuscatedString);\n            obfuscatedString = matcher.replaceFirst(replacement);\n        }\n        return obfuscatedString;\n    }\n\n    @Override\n    public boolean equals(Object o) {\n        if (this == o) return true;\n        if (!(o instanceof RegexPatternObfuscator)) return false;\n        RegexPatternObfuscator that = (RegexPatternObfuscator) o;\n        return patternReplacementMap.equals(that.patternReplacementMap);\n    }\n\n    @Override\n    public int hashCode() {\n        return patternReplacementMap.hashCode() + 13;\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/objectServer/java/io/realm/internal/log/obfuscator/TokenObfuscator.java",
    "content": "/*\n * Copyright 2020 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\npackage io.realm.internal.log.obfuscator;\n\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.regex.Pattern;\n\n/**\n * Obfuscator for oAuth2 token-related login requests.\n * <p>\n * It will replace the\n * <ul>\n * <li>{@code \"authCode\":\"<TOKEN>\"},</li>\n * <li>{@code \"id_token\":\"<TOKEN>\"},</li>\n * <li>{@code \"token\":\"<TOKEN>\"}, and</li>\n * <li>{@code \"access_token\":\"<TOKEN>\"}</li>\n * </ul>\n * patterns with\n * <ul>\n * <li>{@code \"authCode\":\"***\"},</li>\n * <li>{@code \"id_token\":\"***\"},</li>\n * <li>{@code \"token\":\"***\"}, and</li>\n * <li>{@code \"access_token\":\"***\"}</li>\n * </ul>\n * respectively.\n */\npublic class TokenObfuscator extends RegexPatternObfuscator {\n\n    public static final String AUTHCODE_KEY = \"authCode\";\n    public static final String ID_TOKEN_KEY = \"id_token\";\n    public static final String TOKEN_KEY = \"token\";\n    public static final String ACCESS_TOKEN_KEY = \"accessToken\";\n\n    private TokenObfuscator(Map<Pattern, String> patternReplacementMap) {\n        super(patternReplacementMap);\n    }\n\n    /**\n     * Creates a {@link RegexPatternObfuscator} for tokens.\n     *\n     * @return an obfuscator that keeps token information from being displayed in the logcat.\n     */\n    public static TokenObfuscator obfuscator() {\n        return new TokenObfuscator(getPatterns());\n    }\n\n    private static Map<Pattern, String> getPatterns() {\n        Map<Pattern, String> map = new HashMap<>();\n        map.put(Pattern.compile(\"((\\\"\" + AUTHCODE_KEY + \"\\\"):(\\\".+?\\\"))\"), \"\\\"\" + AUTHCODE_KEY + \"\\\":\\\"***\\\"\");\n        map.put(Pattern.compile(\"((\\\"\" + ID_TOKEN_KEY + \"\\\"):(\\\".+?\\\"))\"), \"\\\"\" + ID_TOKEN_KEY + \"\\\":\\\"***\\\"\");\n        map.put(Pattern.compile(\"((\\\"\" + TOKEN_KEY + \"\\\"):(\\\".+?\\\"))\"), \"\\\"\" + TOKEN_KEY + \"\\\":\\\"***\\\"\");\n        map.put(Pattern.compile(\"((\\\"\" + ACCESS_TOKEN_KEY + \"\\\"):(\\\".+?\\\"))\"), \"\\\"\" + ACCESS_TOKEN_KEY + \"\\\":\\\"***\\\"\");\n        return map;\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/objectServer/java/io/realm/internal/mongodb/Request.java",
    "content": "/*\n * Copyright 2020 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\npackage io.realm.internal.mongodb;\n\nimport java.util.concurrent.Future;\nimport java.util.concurrent.ThreadPoolExecutor;\n\nimport javax.annotation.Nullable;\n\nimport io.realm.RealmAsyncTask;\nimport io.realm.internal.RealmNotifier;\nimport io.realm.internal.android.AndroidCapabilities;\nimport io.realm.internal.android.AndroidRealmNotifier;\nimport io.realm.internal.async.RealmAsyncTaskImpl;\nimport io.realm.log.RealmLog;\nimport io.realm.mongodb.App;\nimport io.realm.mongodb.ErrorCode;\nimport io.realm.mongodb.AppException;\n\n// Class wrapping requests made against MongoDB Realm. Is also responsible for calling with success/error on the\n// correct thread.\npublic abstract class Request<T> {\n    @Nullable\n    private final App.Callback<T> callback;\n    private final RealmNotifier handler;\n    private final ThreadPoolExecutor networkPoolExecutor;\n\n    public Request(ThreadPoolExecutor networkPoolExecutor, @Nullable App.Callback<T> callback) {\n        this.callback = callback;\n        this.handler = new AndroidRealmNotifier(null, new AndroidCapabilities());\n        this.networkPoolExecutor = networkPoolExecutor;\n    }\n\n    // Implements the request. Return the current sync user if the request succeeded. Otherwise throw an error.\n    public abstract T run() throws AppException;\n\n    // Start the request\n    public RealmAsyncTask start() {\n        Future<?> authenticateRequest = networkPoolExecutor.submit(new Runnable() {\n            @Override\n            public void run() {\n                try {\n                    postSuccess(Request.this.run());\n                } catch (AppException e) {\n                    postError(e);\n                } catch (Throwable e) {\n                    postError(new AppException(ErrorCode.UNKNOWN, \"Unexpected error\", e));\n                }\n            }\n        });\n        return new RealmAsyncTaskImpl(authenticateRequest, networkPoolExecutor);\n    }\n\n    private void postError(final AppException error) {\n        boolean errorHandled = false;\n        if (callback != null) {\n            Runnable action = new Runnable() {\n                @Override\n                public void run() {\n                    callback.onResult(App.Result.withError(error));\n                }\n            };\n            errorHandled = handler.post(action);\n        }\n\n        if (!errorHandled) {\n            RealmLog.error(error, \"An error was thrown, but could not be posted: \\n\" + error.toString());\n        }\n    }\n\n    private void postSuccess(final T result) {\n        if (callback != null) {\n            handler.post(new Runnable() {\n                @Override\n                public void run() {\n                    callback.onResult((result == null) ? App.Result.success() : App.Result.withResult(result));\n                }\n            });\n        }\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/objectServer/java/io/realm/internal/network/LoggingInterceptor.java",
    "content": "/*\n * Copyright 2020 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\npackage io.realm.internal.network;\n\nimport java.io.IOException;\nimport java.nio.charset.Charset;\n\nimport javax.annotation.Nullable;\n\nimport io.realm.log.LogLevel;\nimport io.realm.log.RealmLog;\nimport io.realm.mongodb.log.obfuscator.HttpLogObfuscator;\nimport okhttp3.Interceptor;\nimport okhttp3.Request;\nimport okhttp3.Response;\nimport okio.Buffer;\n\n/**\n * The LoggingInterceptor prints information on the HTTP requests produced by a Realm app.\n */\npublic class LoggingInterceptor implements Interceptor {\n\n    public static final String LOGIN_FEATURE = \"providers\";\n\n    private static final Charset UTF8 = Charset.forName(\"UTF-8\");\n\n    @Nullable\n    private HttpLogObfuscator httpLogObfuscator;\n\n    LoggingInterceptor(@Nullable HttpLogObfuscator httpLogObfuscator) {\n        this.httpLogObfuscator = httpLogObfuscator;\n    }\n\n    @Override\n    public Response intercept(Chain chain) throws IOException {\n        Request request = chain.request();\n        if (RealmLog.getLevel() <= LogLevel.DEBUG) {\n            StringBuilder sb = new StringBuilder(request.method());\n            sb.append(' ');\n            sb.append(request.url());\n            sb.append('\\n');\n            sb.append(request.headers());\n            if (request.body() != null) {\n                // Stripped down version of https://github.com/square/okhttp/blob/master/okhttp-logging-interceptor/src/main/java/okhttp3/logging/HttpLoggingInterceptor.java\n                // We only expect request context to be JSON.\n                Buffer buffer = new Buffer();\n                request.body().writeTo(buffer);\n\n                // Obfuscate sensitive information if applicable\n                String input = buffer.readString(UTF8);\n                if (httpLogObfuscator != null) {\n                    input = httpLogObfuscator.obfuscate(request.url().pathSegments(), input);\n                }\n                sb.append(input);\n            }\n            RealmLog.debug(\"HTTP Request = \\n%s\", sb);\n        }\n        return chain.proceed(request);\n    }\n\n    @Override\n    public boolean equals(Object o) {\n        if (this == o) return true;\n        if (!(o instanceof LoggingInterceptor)) return false;\n        LoggingInterceptor that = (LoggingInterceptor) o;\n        if (httpLogObfuscator == null) {\n            return that.httpLogObfuscator == null;\n        }\n        return httpLogObfuscator.equals(that.httpLogObfuscator);\n    }\n\n    @Override\n    public int hashCode() {\n        if (httpLogObfuscator == null) {\n            return super.hashCode();\n        }\n        return httpLogObfuscator.hashCode() + 27;\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/objectServer/java/io/realm/internal/network/MockableNetworkTransport.java",
    "content": "package io.realm.internal.network;\n\nimport java.io.IOException;\nimport java.util.Map;\n\nimport javax.annotation.Nonnull;\n\nimport io.realm.internal.objectstore.OsJavaNetworkTransport;\nimport io.realm.mongodb.AppException;\n\npublic class MockableNetworkTransport extends OsJavaNetworkTransport {\n\n    private final OsJavaNetworkTransport originalNetworkTransport;\n    private OsJavaNetworkTransport networkTransport;\n\n    public MockableNetworkTransport(OsJavaNetworkTransport networkTransport) {\n        this.originalNetworkTransport = networkTransport;\n        this.networkTransport = networkTransport;\n    }\n\n    public void setMockNetworkTransport(@Nonnull OsJavaNetworkTransport networkTransport) {\n        this.networkTransport = networkTransport;\n    }\n\n    public void setOriginalNetworkTransport() {\n        this.networkTransport = this.originalNetworkTransport;\n    }\n\n    @Override\n    public void sendRequestAsync(String method, String url, long timeoutMs, Map<String, String> headers, String body, long completionBlockPtr) {\n        this.networkTransport.sendRequestAsync(method, url, timeoutMs, headers, body, completionBlockPtr);\n    }\n\n    @Override\n    public Response executeRequest(String method, String url, long timeoutMs, Map<String, String> headers, String body) {\n        return this.networkTransport.executeRequest(method, url, timeoutMs, headers, body);\n    }\n\n    @Override\n    public Response sendStreamingRequest(Request request) throws IOException, AppException {\n        return this.networkTransport.sendStreamingRequest(request);\n    }\n\n    @Override\n    public void setAuthorizationHeaderName(String headerName) {\n        this.networkTransport.setAuthorizationHeaderName(headerName);\n    }\n\n    @Override\n    public void addCustomRequestHeader(String headerName, String headerValue) {\n        this.networkTransport.addCustomRequestHeader(headerName, headerValue);\n    }\n\n    @Override\n    public void reset() {\n        this.networkTransport.reset();\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/objectServer/java/io/realm/internal/network/NetworkRequest.java",
    "content": "package io.realm.internal.network;\n\nimport android.os.Looper;\nimport android.os.NetworkOnMainThreadException;\n\nimport java.util.concurrent.CountDownLatch;\nimport java.util.concurrent.atomic.AtomicReference;\n\nimport javax.annotation.Nullable;\n\nimport io.realm.internal.ErrorCategory;\nimport io.realm.internal.Keep;\nimport io.realm.internal.objectstore.OsJavaNetworkTransport;\nimport io.realm.log.RealmLog;\nimport io.realm.mongodb.AppException;\nimport io.realm.mongodb.ErrorCode;\n\n/**\n * Class wrapping the back-and-forth required by the Network Transport layer in ObjectStore.\n *\n * This class wraps the request itself as well as handles the completion block triggered by\n * ObjectStore.\n *\n * That API exposed by this class is synchronous, but the callbacks from ObjectStore will happen\n * on a thread determined by the {@link OsJavaNetworkTransport} implementation. In release builds,\n * this is {@link OkHttpNetworkTransport} which run on a special Looper thread.\n */\n@Keep\npublic abstract class NetworkRequest<T> extends OsJavaNetworkTransport.NetworkTransportJNIResultCallback {\n\n    CountDownLatch latch = new CountDownLatch(1);\n    AtomicReference<T> success = new AtomicReference<>(null);\n    AtomicReference<AppException> error = new AtomicReference<>(null);\n\n    /**\n     * In the case of a successful request. Map the return value back to the type\n     * expected by top-level consumers.\n     */\n    protected abstract T mapSuccess(Object result);\n\n    /**\n     * Responsible for doing the network request by calling the relevant ObjectStore method.\n     */\n    protected abstract void execute(NetworkRequest<T> callback);\n\n    /**\n     * Request was successful. Will be called by the ObjectStore completion handler.\n     */\n    @SuppressWarnings(\"unused\") // Called by JNI\n    @Override\n    public void onSuccess(Object result) {\n        T mappedResult = mapSuccess(result);\n        success.set(mappedResult);\n        latch.countDown();\n    }\n\n    /**\n     * Request failed. Will be called by the ObjectStore completion handler.\n     */\n    @SuppressWarnings(\"unused\")  // Called by JNI\n    @Override\n    public void onError(byte nativeErrorCategory, int nativeErrorCode, @Nullable String errorMessage, @Nullable String logUrl) {\n        String formattedErrorMessage = \"\";\n        if (errorMessage != null && !errorMessage.isEmpty()) {\n            if (formattedErrorMessage.endsWith(\".\")) {\n                formattedErrorMessage = errorMessage;\n            } else {\n                formattedErrorMessage = errorMessage + \".\";\n            }\n        }\n        if (logUrl != null && !logUrl.isEmpty()) {\n            String logMsg = \"Server log entry: \" + logUrl;\n            if (formattedErrorMessage.isEmpty()) {\n                formattedErrorMessage = logMsg;\n            } else {\n                formattedErrorMessage += \" \" + logMsg;\n            }\n        }\n\n        ErrorCode code = ErrorCode.fromNativeError(ErrorCategory.toCategory(nativeErrorCategory), nativeErrorCode);\n        if (code == ErrorCode.UNKNOWN) {\n            // In case of UNKNOWN errors parse as much error information on as possible.\n            String detailedErrorMessage = String.format(\"{%s::%s} %s\", nativeErrorCategory, nativeErrorCode, formattedErrorMessage);\n            error.set(new AppException(code, detailedErrorMessage));\n        } else {\n            error.set(new AppException(code, formattedErrorMessage));\n        }\n        latch.countDown();\n    }\n\n    /**\n     * Run the network request and wait for the result.\n     * If the request was a success, the result is returned. \n     * \n     * If not, an error occurred and it will be thrown as an AppException.\n     */\n    public T resultOrThrow() {\n\n        // Avoid changing behavior. Old implementation would throw an exception if\n        // this method was called from the UI thread\n        if (Looper.myLooper() == Looper.getMainLooper()) {\n            throw new AppException(ErrorCode.NETWORK_UNKNOWN, new NetworkOnMainThreadException());\n        }\n\n        execute(this);\n        try {\n            // Wait indefinitely. Timeouts should be handled by the Network layer, otherwise\n            // it can be interrupted manually by calling `RealmAsyncTask.cancel()`\n            latch.await();\n        } catch (InterruptedException e) {\n            error.set(new AppException(ErrorCode.NETWORK_INTERRUPTED, \"Network request interrupted.\"));\n        }\n\n        // Result of request should be available. Throw if an error happened, otherwise return\n        // the result.\n        if (error.get() != null) {\n            throw error.get();\n        } else {\n            return success.get();\n        }\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/objectServer/java/io/realm/internal/network/NetworkStateReceiver.java",
    "content": "/*\n * Copyright 2016 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\npackage io.realm.internal.network;\n\nimport android.content.BroadcastReceiver;\nimport android.content.Context;\nimport android.content.Intent;\nimport android.net.ConnectivityManager;\nimport android.net.NetworkInfo;\n\nimport java.util.List;\nimport java.util.concurrent.CopyOnWriteArrayList;\n\nimport io.realm.mongodb.sync.Sync;\nimport io.realm.internal.Util;\n\n/**\n * This class is responsible for keeping track of system events related to the network so it can delegate them to\n * interested parties.\n */\npublic class NetworkStateReceiver extends BroadcastReceiver {\n\n    private static List<ConnectionListener> listeners = new CopyOnWriteArrayList<ConnectionListener>();\n\n    /**\n     * Add a listener to be notified about any network changes.\n     * This method is thread safe.\n     * <p>\n     * IMPORTANT: Not removing it again will result in major leaks.\n     *\n     * @param listener the listener.\n     */\n    public static void addListener(ConnectionListener listener) {\n        listeners.add(listener);\n    }\n\n    /**\n     * Removes a network listener.\n     * This method is thread safe.\n     *\n     * @param listener the listener.\n     */\n    public static synchronized void removeListener(ConnectionListener listener) {\n        listeners.remove(listener);\n    }\n\n    /**\n     * Attempt to detect if a device is online and can transmit or receive data.\n     * This method is thread safe.\n     * <p>\n     * An emulator is always considered online, as `getActiveNetworkInfo()` does not report the correct value.\n     *\n     * @param context an Android context.\n     * @return {@code true} if device is online, otherwise {@code false}.\n     */\n    public static boolean isOnline(Context context) {\n        if (Sync.Debug.skipOnlineChecking) {\n            return true;\n        }\n        ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);\n        NetworkInfo networkInfo = cm.getActiveNetworkInfo();\n        return ((networkInfo != null && networkInfo.isConnectedOrConnecting()) || Util.isEmulator());\n    }\n\n\n    @Override\n    public void onReceive(Context context, Intent intent) {\n        boolean connected = isOnline(context);\n        for (ConnectionListener listener : listeners) {\n            listener.onChange(connected);\n        }\n    }\n\n    public interface ConnectionListener {\n        void onChange(boolean connectionAvailable);\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/objectServer/java/io/realm/internal/network/OkHttpNetworkTransport.java",
    "content": "package io.realm.internal.network;\n\nimport java.io.IOException;\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.concurrent.ThreadPoolExecutor;\nimport java.util.concurrent.TimeUnit;\n\nimport javax.annotation.Nullable;\n\nimport edu.umd.cs.findbugs.annotations.SuppressFBWarnings;\nimport io.realm.internal.async.RealmThreadPoolExecutor;\nimport io.realm.internal.objectstore.OsJavaNetworkTransport;\nimport io.realm.mongodb.AppConfiguration;\nimport io.realm.mongodb.AppException;\nimport io.realm.mongodb.ErrorCode;\nimport io.realm.mongodb.log.obfuscator.HttpLogObfuscator;\nimport okhttp3.Call;\nimport okhttp3.ConnectionPool;\nimport okhttp3.Headers;\nimport okhttp3.MediaType;\nimport okhttp3.OkHttpClient;\nimport okhttp3.RequestBody;\nimport okhttp3.ResponseBody;\nimport okio.BufferedSource;\n\npublic class OkHttpNetworkTransport extends OsJavaNetworkTransport {\n\n    public static final MediaType JSON = MediaType.parse(\"application/json; charset=utf-8\");\n\n    private volatile OkHttpClient client = null;\n    private volatile OkHttpClient streamClient = null;\n\n    @Nullable\n    private final HttpLogObfuscator httpLogObfuscator;\n    // Cannot use App.NETWORK_POOL_EXECUTOR as they end up blocking each other.\n    private final ThreadPoolExecutor threadPool = RealmThreadPoolExecutor.newDefaultExecutor();\n\n    public OkHttpNetworkTransport(@Nullable HttpLogObfuscator httpLogObfuscator) {\n        this.httpLogObfuscator = httpLogObfuscator;\n    }\n\n    private okhttp3.Request createRequest(String method, String url, Map<String, String> headers, String body){\n        okhttp3.Request.Builder builder = new okhttp3.Request.Builder().url(url);\n\n        // Ensure that we have correct custom headers until OS handles it.\n\n        // 1. First of all add all custom headers\n        for (Map.Entry<String, String> entry : getCustomRequestHeaders().entrySet()) {\n            builder.addHeader(entry.getKey(), entry.getValue());\n        }\n        // 2. Then replace default authorization header with custom one if present\n        String authorizationHeaderValue = headers.get(AppConfiguration.DEFAULT_AUTHORIZATION_HEADER_NAME);\n        String authorizationHeaderName = getAuthorizationHeaderName();\n        if (authorizationHeaderValue != null && !AppConfiguration.DEFAULT_AUTHORIZATION_HEADER_NAME.equals(authorizationHeaderName)) {\n            headers.remove(AppConfiguration.DEFAULT_AUTHORIZATION_HEADER_NAME);\n            headers.put(authorizationHeaderName, authorizationHeaderValue);\n        }\n\n        // 3. Finally add all headers defined by Object Store\n        for (Map.Entry<String, String> entry : headers.entrySet()) {\n            builder.addHeader(entry.getKey(), entry.getValue());\n        }\n        \n        switch (method) {\n            case \"get\":\n                builder.get();\n                break;\n            case \"delete\":\n                builder.delete(RequestBody.create(JSON, body));\n                break;\n            case \"patch\":\n                builder.patch(RequestBody.create(JSON, body));\n                break;\n            case \"post\":\n                builder.post(RequestBody.create(JSON, body));\n                break;\n            case \"put\":\n                builder.put(RequestBody.create(JSON, body));\n                break;\n            default:\n                throw new IllegalArgumentException(\"Unknown method type: \" + method);\n        }\n\n        return builder.build();\n    }\n\n\n    @SuppressFBWarnings(\"REC_CATCH_EXCEPTION\")\n    @Override\n    public void sendRequestAsync(String method,\n                            String url,\n                            long timeoutMs,\n                            Map<String, String> headers,\n                            String body,\n                            long completionBlockPtr) {\n        threadPool.execute(new Runnable() {\n            @Override\n            public void run() {\n                try {\n                    OsJavaNetworkTransport.Response response = OkHttpNetworkTransport.this.executeRequest(method, url, timeoutMs, headers, body);\n                    OkHttpNetworkTransport.this.handleResponse(response, completionBlockPtr);\n                } catch (Error e) {\n                    OkHttpNetworkTransport.this.handleResponse(Response.unknownError(e.toString()), completionBlockPtr);\n                }\n            }\n        });\n    }\n\n    @Override\n    public OsJavaNetworkTransport.Response executeRequest(String method, String url, long timeoutMs, Map<String, String> headers, String body) {\n        try {\n            OkHttpClient client = getClient(timeoutMs);\n\n            okhttp3.Response response = null;\n            try {\n                okhttp3.Request request = createRequest(method, url, headers, body);\n\n                Call call = client.newCall(request);\n                response = call.execute();\n                ResponseBody responseBody = response.body();\n                String result = \"\";\n                if (responseBody != null) {\n                    result = responseBody.string();\n                }\n                return Response.httpResponse(response.code(), parseHeaders(response.headers()), result);\n            } catch (IOException ex) {\n                return Response.ioError(ex.toString());\n            } catch (Exception ex) {\n                return Response.unknownError(ex.toString());\n            } finally {\n                if (response != null) {\n                    response.close();\n                }\n            }\n        } catch (Exception e) {\n            return Response.unknownError(e.toString());\n        }\n    }\n\n    @Override\n    public OsJavaNetworkTransport.Response sendStreamingRequest(Request request) throws IOException, AppException {\n        OkHttpClient client = getStreamClient();\n\n        okhttp3.Request okRequest = createRequest(request.getMethod(), request.getUrl(), request.getHeaders(), request.getBody());\n\n        Call call = client.newCall(okRequest);\n        okhttp3.Response response = call.execute();\n\n        if ((response.code() >= 300) || ((response.code() < 200) && (response.code() != 0))) {\n            throw new AppException(ErrorCode.fromNativeError(ErrorCode.Type.HTTP, response.code()), response.message());\n        }\n\n        return Response.httpResponse(response.code(), parseHeaders(response.headers()), response.body().source());\n    }\n\n    @Override\n    public void reset() {\n        try {\n            threadPool.shutdownNow();\n            threadPool.awaitTermination(30, TimeUnit.SECONDS);\n        } catch (InterruptedException e) {\n            throw new IllegalStateException(\"Threadpool did not terminate in time\", e);\n        }\n        super.reset();\n    }\n\n    // Lazily creates the client if not already created\n    // TODO: timeOuts are not expected to change between requests. So for now just use the timeout first send.\n    private synchronized OkHttpClient getClient(long timeoutMs) {\n        if (client == null) {\n            client = new OkHttpClient.Builder()\n                    // TODO There doesn't appear to set a timeout for the entire http request,\n                    //  so just reuse it across all 3 phases. In the worst case that means the\n                    //  the timeout is 3x the defined timeout which is acceptable.\n                    .connectTimeout(timeoutMs, TimeUnit.MILLISECONDS)\n                    .readTimeout(timeoutMs, TimeUnit.MILLISECONDS)\n                    .writeTimeout(timeoutMs, TimeUnit.MILLISECONDS)\n                    .followRedirects(true)\n                    .addInterceptor(new LoggingInterceptor(httpLogObfuscator))\n                    // using custom Connection Pool to evict idle connection after 5 seconds rather than 5 minutes (which is the default)\n                    // keeping idle connection on the pool will prevent the ROS to be stopped, since the HttpUtils#stopSyncServer query\n                    // will not return before the tests timeout (ex 10 seconds for AuthTests)\n                    .connectionPool(new ConnectionPool(5, 5, TimeUnit.SECONDS))\n                    .build();\n        }\n\n        return client;\n    }\n\n    private synchronized OkHttpClient getStreamClient() {\n        if (streamClient == null) {\n            streamClient = new OkHttpClient.Builder()\n                    .readTimeout(0, TimeUnit.MILLISECONDS)\n                    .followRedirects(true)\n                    .addInterceptor(new LoggingInterceptor(httpLogObfuscator))\n                    .build();\n        }\n\n        return streamClient;\n    }\n\n    // Parse Headers output from OKHttp to the format expected by ObjectStore\n    private Map<String, String> parseHeaders(Headers headers) {\n        HashMap<String, String> osHeaders = new HashMap<>(headers.size() / 2);\n        for (String key : headers.names()) {\n            osHeaders.put(key, headers.get(key));\n        }\n        return osHeaders;\n    }\n\n    public static class Response extends OsJavaNetworkTransport.Response {\n        private BufferedSource bufferedSource;\n        private volatile boolean closed;\n\n        public static OsJavaNetworkTransport.Response unknownError(String stacktrace) {\n            return new Response(0, ERROR_UNKNOWN, new HashMap<>(), stacktrace);\n        }\n\n        public static OsJavaNetworkTransport.Response ioError(String stackTrace) {\n            return new Response(0, ERROR_IO, new HashMap<>(), stackTrace);\n        }\n\n        public static OsJavaNetworkTransport.Response interruptedError(String stackTrace) {\n            return new Response(0, ERROR_INTERRUPTED, new HashMap<>(), stackTrace);\n        }\n\n        public static OsJavaNetworkTransport.Response httpResponse(int statusCode, Map<String, String> responseHeaders, String body) {\n            return new Response(statusCode, 0, responseHeaders, body);\n        }\n\n        private Response(int httpResponseCode, int customResponseCode, Map<String, String> headers, String body) {\n            super(httpResponseCode, customResponseCode, headers, body);\n        }\n\n        private Response(int httpResponseCode, Map<String, String> headers, BufferedSource bufferedSource) {\n            super(httpResponseCode, 0, headers, \"\");\n\n            this.bufferedSource = bufferedSource;\n        }\n\n        public static OsJavaNetworkTransport.Response httpResponse(int httpResponseCode, Map<String, String> headers, BufferedSource originalResponse) {\n            return new Response(httpResponseCode, headers, originalResponse);\n        }\n\n        @Override\n        public String readBodyLine() throws IOException {\n            if (!closed){\n                return bufferedSource.readUtf8LineStrict();\n            } else{\n                bufferedSource.close();\n                throw new IOException(\"Stream closed\");\n            }\n        }\n\n        /**\n         * Closes the current stream.\n         *\n         * Note: we use a close flag because okio buffers are not thread safe:\n         * @see <a href=\"http://google.com\">https://github.com/square/okio/issues/163#issuecomment-127052956</a>\n         */\n        @Override\n        public void close() {\n            closed = true;\n        }\n\n        @Override\n        public boolean isOpen() {\n            return !closed && bufferedSource.isOpen();\n        }\n    }\n\n}\n\n"
  },
  {
    "path": "realm/realm-library/src/objectServer/java/io/realm/internal/network/StreamNetworkTransport.java",
    "content": "/*\n * Copyright 2020 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\npackage io.realm.internal.network;\n\nimport java.io.IOException;\n\nimport io.realm.internal.objectstore.OsApp;\nimport io.realm.internal.objectstore.OsJavaNetworkTransport;\nimport io.realm.internal.objectstore.OsSyncUser;\n\n/**\n * StreamNetworkTransport provides an interface to the Realm remote streaming functions.\n * Such functions are package protected and this class offers a portable way to access them.\n */\npublic class StreamNetworkTransport {\n    private final OsApp app;\n    private final OsSyncUser user;\n\n    public StreamNetworkTransport(OsApp app, OsSyncUser user) {\n        this.app = app;\n        this.user = user;\n    }\n\n    /**\n     * Creates a request for a streaming function\n     *\n     * @param functionName name of the function\n     * @param arguments     function arguments encoded as a {@link String}\n     * @param serviceName  service that will handle the function\n     * @return {@link io.realm.internal.objectstore.OsJavaNetworkTransport.Request}\n     */\n    public OsJavaNetworkTransport.Request makeStreamingRequest(String functionName,\n                                                                        String arguments,\n                                                                        String serviceName){\n        return app.makeStreamingRequest(user, functionName, arguments, serviceName);\n    }\n\n    /**\n     * Executes a given request\n     *\n     * @param request to execute\n     * @return {@link io.realm.internal.objectstore.OsJavaNetworkTransport.Response}\n     * @throws IOException\n     */\n    public OsJavaNetworkTransport.Response\n    sendRequest(OsJavaNetworkTransport.Request request) throws IOException{\n        return app.getNetworkTransport().sendStreamingRequest(request);\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/objectServer/java/io/realm/internal/network/VoidNetworkRequest.java",
    "content": "package io.realm.internal.network;\n\nimport java.util.concurrent.CountDownLatch;\nimport java.util.concurrent.atomic.AtomicReference;\n\nimport io.realm.internal.Keep;\nimport io.realm.internal.objectstore.OsJavaNetworkTransport;\nimport io.realm.log.RealmLog;\nimport io.realm.mongodb.AppException;\nimport io.realm.mongodb.ErrorCode;\n\n/**\n * Specialized case of {@link NetworkRequest} where we are not interested in the response value,\n * just whether or not the request succeeded.\n */\npublic abstract class VoidNetworkRequest extends NetworkRequest<Void> {\n\n    @Override\n    protected Void mapSuccess(Object result) {\n        return null;\n    }\n\n    /**\n     * Run the network request and wait for confirmation that it succeded.\n     * This method will block until this confirmation arrives after which it will return.\n     *\n     * @throws {@link AppException} if an error occurred.\n     */\n    public void execute() {\n        super.resultOrThrow();\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/objectServer/java/io/realm/internal/objectserver/EventStream.java",
    "content": "/*\n * Copyright 2020 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\npackage io.realm.internal.objectserver;\n\nimport java.io.IOException;\n\nimport io.realm.mongodb.AppException;\nimport io.realm.mongodb.mongo.events.BaseChangeEvent;\n\npublic interface EventStream<T> {\n    /**\n     * Fetch the next event from a given stream.\n     *\n     * @return the next event\n     * @throws IOException any io exception that could occur\n     */\n    BaseChangeEvent<T> getNextEvent() throws AppException, IOException;\n\n    /**\n     * Closes the current stream.\n     *\n     * @throws IOException can throw exception if internal buffer not closed properly\n     */\n    void close();\n\n    /**\n     * Indicates whether or not the change stream is currently open.\n     *\n     * @return True if the underlying change stream is open.\n     */\n    boolean isOpen();\n}\n"
  },
  {
    "path": "realm/realm-library/src/objectServer/java/io/realm/internal/objectserver/SyncWorker.java",
    "content": "/*\n * Copyright 2019 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\npackage io.realm.internal.objectserver;\n\nimport org.json.JSONException;\nimport org.json.JSONObject;\n\n/**\n * This class represents a value describing a sync worker on the Realm Cloud.\n */\npublic class SyncWorker {\n\n    private static final String KEY_PATH = \"path\";\n\n    private final String path;\n\n    public static SyncWorker from(JSONObject syncWorker) throws JSONException {\n        String path = syncWorker.getString(KEY_PATH);\n\n        return new SyncWorker(path);\n    }\n\n    public SyncWorker(String path) {\n        this.path = path;\n    }\n\n    public String path() {\n        return path;\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/objectServer/java/io/realm/internal/objectserver/Token.java",
    "content": "/*\n * Copyright 2016 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\npackage io.realm.internal.objectserver;\n\nimport org.json.JSONArray;\nimport org.json.JSONException;\nimport org.json.JSONObject;\n\nimport java.util.Arrays;\nimport java.util.Locale;\n\nimport edu.umd.cs.findbugs.annotations.SuppressFBWarnings;\n\n/**\n * This class represents a value from the Realm Authentication Server.\n */\npublic class Token {\n\n    private static final String KEY_TOKEN = \"token\";\n    private static final String KEY_TOKEN_DATA = \"token_data\";\n    private static final String KEY_IDENTITY = \"identity\";\n    private static final String KEY_PATH = \"path\";\n    private static final String KEY_EXPIRES = \"expires\";\n    private static final String KEY_ACCESS = \"access\";\n    private static final String KEY_IS_ADMIN = \"is_admin\";\n\n    private final String value;\n    private final long expiresSec;\n    private final Permission[] permissions;\n    private final String identity;\n    private final String path;\n    private final boolean isAdmin;\n\n    public static Token from(JSONObject token) throws JSONException {\n        String value = token.getString(KEY_TOKEN);\n        JSONObject tokenData = token.getJSONObject(KEY_TOKEN_DATA);\n        String identity = tokenData.getString(KEY_IDENTITY);\n        String path = tokenData.optString(KEY_PATH);\n        long expiresSec = tokenData.getLong(KEY_EXPIRES);\n        Permission[] permissions;\n        JSONArray access = tokenData.getJSONArray(KEY_ACCESS);\n        if (access != null) {\n            permissions = new Permission[access.length()];\n            for (int i = 0; i < access.length(); i++) {\n                try {\n                    permissions[i] = Permission.valueOf(access.getString(i));\n                } catch (IllegalArgumentException e) {\n                    permissions[i] = Permission.UNKNOWN;\n                }\n            }\n        } else {\n            permissions = new Permission[0];\n        }\n        boolean isAdmin = tokenData.optBoolean(KEY_IS_ADMIN);\n\n        return new Token(value, identity, path, expiresSec, permissions, isAdmin);\n    }\n\n    public Token(String value, String identity, String path, long expiresSec, Permission[] permissions) {\n        this(value, identity, path, expiresSec, permissions, false);\n    }\n\n    public Token(String value, String identity, String path, long expiresSec, Permission[] permissions, boolean isAdmin) {\n        this.value = value;\n        this.identity = identity;\n        this.path = path;\n        this.expiresSec = expiresSec;\n        if (permissions != null) {\n            this.permissions = Arrays.copyOf(permissions, permissions.length);\n        } else {\n            this.permissions = new Permission[0];\n        }\n        this.isAdmin = isAdmin;\n    }\n\n    public String value() {\n        return value;\n    }\n\n    public String identity() { return identity; }\n\n    public String path() { return path; }\n\n    public boolean isAdmin() { return isAdmin; }\n\n    /**\n     * Returns when this token expires. Timestamp is in UTC seconds.\n     */\n    public long expiresSec() {\n        return expiresSec;\n    }\n\n    /**\n     * Returns when this token expires. Timestamp is in UTC milliseconds.\n     */\n    public long expiresMs() {\n        long expiresMs = expiresSec * 1000;\n        if (expiresMs < expiresSec) {\n            return Long.MAX_VALUE; // Prevent overflow\n        } else {\n            return expiresMs;\n        }\n    }\n\n    @SuppressFBWarnings(\"MS_MUTABLE_ARRAY\")\n    public Permission[] permissions() {\n        return Arrays.copyOf(permissions, permissions.length);\n    }\n\n    public JSONObject toJson() {\n        JSONObject obj = new JSONObject();\n        try {\n            obj.put(KEY_TOKEN, value);\n            JSONObject tokenData = new JSONObject();\n            tokenData.put(KEY_IDENTITY, identity);\n            tokenData.put(KEY_PATH, path);\n            tokenData.put(KEY_EXPIRES, expiresSec);\n            JSONArray perms = new JSONArray();\n            for (int i = 0; i < permissions.length; i++) {\n                perms.put(permissions[i].toString().toLowerCase(Locale.US));\n            }\n            tokenData.put(KEY_ACCESS, perms);\n            tokenData.put(KEY_IS_ADMIN, isAdmin);\n            obj.put(KEY_TOKEN_DATA, tokenData);\n            return obj;\n        } catch (JSONException e) {\n            throw new RuntimeException(\"Could not convert Token to JSON.\", e);\n        }\n    }\n\n    @Override\n    public boolean equals(Object o) {\n        if (this == o) { return true; }\n        if (o == null || getClass() != o.getClass()) { return false; }\n\n        Token token = (Token) o;\n\n        if (expiresSec != token.expiresSec) { return false; }\n        if (isAdmin != token.isAdmin) { return false; }\n        if (!value.equals(token.value)) { return false; }\n        if (!Arrays.equals(permissions, token.permissions)) { return false; }\n        if (!identity.equals(token.identity)) { return false; }\n        return path != null ? path.equals(token.path) : token.path == null;\n    }\n\n    @Override\n    public int hashCode() {\n        int result = value.hashCode();\n        result = 31 * result + (int) (expiresSec ^ (expiresSec >>> 32));\n        result = 31 * result + Arrays.hashCode(permissions);\n        result = 31 * result + identity.hashCode();\n        result = 31 * result + (path != null ? path.hashCode() : 0);\n        result = 31 * result + (isAdmin ? 1 : 0);\n        return result;\n    }\n\n    public enum Permission {\n        UNKNOWN,\n        UPLOAD,\n        DOWNLOAD,\n        REFRESH,\n        MANAGE;\n\n        public static final Permission[] ALL = { UPLOAD, DOWNLOAD, REFRESH, MANAGE };\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/objectServer/java/io/realm/internal/objectstore/OsApp.java",
    "content": "package io.realm.internal.objectstore;\n\nimport java.util.Map;\n\nimport javax.annotation.Nullable;\n\nimport io.realm.internal.KeepMember;\nimport io.realm.internal.NativeObject;\nimport io.realm.internal.network.MockableNetworkTransport;\nimport io.realm.internal.network.NetworkRequest;\nimport io.realm.internal.network.OkHttpNetworkTransport;\nimport io.realm.mongodb.AppConfiguration;\n\npublic class OsApp implements NativeObject {\n    private static final long nativeFinalizerPtr = nativeGetFinalizerMethodPtr();\n\n    private MockableNetworkTransport networkTransport;\n    private final long nativePtr;\n\n    @Override\n    public long getNativePtr() {\n        return this.nativePtr;\n    }\n\n    @Override\n    public long getNativeFinalizerPtr() {\n        return nativeFinalizerPtr;\n    }\n\n    public OsApp(AppConfiguration config, String userAgentBindingInfo, String appDefinedUserAgent, String syncDir) {\n        synchronized (OsApp.class) { // We need to synchronize access as OS caches the App instance\n            // Network transport must be created before the C++ App instance as it is used\n            // as part of setting it up.\n            this.networkTransport = new MockableNetworkTransport(new OkHttpNetworkTransport(config.getHttpLogObfuscator()));\n            networkTransport.setAuthorizationHeaderName(config.getAuthorizationHeaderName());\n            for (Map.Entry<String, String> entry : config.getCustomRequestHeaders().entrySet()) {\n                networkTransport.addCustomRequestHeader(entry.getKey(), entry.getValue());\n            }\n            String cpuArch;\n             if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.LOLLIPOP) {\n                cpuArch = android.os.Build.CPU_ABI;\n            } else {\n                 cpuArch = android.os.Build.SUPPORTED_ABIS[0];\n            }\n\n            nativePtr = nativeCreate(\n                    config.getAppId(),\n                    config.getBaseUrl().toString(),\n                    config.getAppName(),\n                    config.getAppVersion(),\n                    config.getRequestTimeoutMs(),\n                    config.getEncryptionKey(),\n                    syncDir,\n                    userAgentBindingInfo,\n                    appDefinedUserAgent,\n                    \"android\",\n                    android.os.Build.VERSION.RELEASE,\n                    io.realm.BuildConfig.VERSION_NAME,\n                    cpuArch,\n                    android.os.Build.MANUFACTURER,\n                    android.os.Build.MODEL,\n                    \"Android\",\n                    String.valueOf(android.os.Build.VERSION.SDK_INT)\n            );\n        }\n    }\n\n    public void setNetworkTransport(@Nullable OsJavaNetworkTransport transport) {\n        networkTransport.setMockNetworkTransport(transport);\n    }\n\n    public void setOriginalNetworkTransport() {\n        networkTransport.setOriginalNetworkTransport();\n    }\n\n    /**\n     * Creates a request for a streaming function\n     *\n     * @param user         that requests the execution\n     * @param functionName name of the function\n     * @param arguments    function arguments encoded as a {@link String}\n     * @param serviceName  service that will handle the function\n     * @return {@link io.realm.internal.objectstore.OsJavaNetworkTransport.Request}\n     */\n    public OsJavaNetworkTransport.Request makeStreamingRequest(OsSyncUser user,\n                                                               String functionName,\n                                                               String arguments,\n                                                               String serviceName) {\n        return nativeMakeStreamingRequest(nativePtr, user.getNativePtr(), functionName, arguments, serviceName);\n    }\n\n    public OsSyncUser currentUser() {\n        Long userPtr = nativeCurrentUser(nativePtr);\n        return (userPtr != null) ? new OsSyncUser(userPtr) : null;\n    }\n\n    public OsSyncUser[] allUsers() {\n        long[] nativeUsers = nativeGetAllUsers(nativePtr);\n        OsSyncUser[] osSyncUsers = new OsSyncUser[nativeUsers.length];\n\n        for (int i = 0; i < nativeUsers.length; i++) {\n            osSyncUsers[i] = new OsSyncUser(nativeUsers[i]);\n        }\n        return osSyncUsers;\n    }\n\n    public void switchUser(OsSyncUser osUser) {\n        nativeSwitchUser(nativePtr, osUser.getNativePtr());\n    }\n\n    public OsSyncUser login(OsAppCredentials credentials) {\n        return new NetworkRequest<OsSyncUser>() {\n            @Override\n            public OsSyncUser mapSuccess(Object result) {\n                Long nativePtr = (Long) result;\n                return new OsSyncUser(nativePtr);\n            }\n            @Override\n            public void execute(NetworkRequest<OsSyncUser> callback) {\n                nativeLogin(nativePtr, credentials.getNativePtr(), callback);\n            }\n        }.resultOrThrow();\n    }\n\n    // Called from JNI\n    @KeepMember\n    public OsJavaNetworkTransport getNetworkTransport() {\n        return networkTransport;\n    }\n\n    private native long nativeCreate(String appId,\n                                     String baseUrl,\n                                     String appName,\n                                     String appVersion,\n                                     long requestTimeoutMs,\n                                     byte[] encryptionKey,\n                                     String syncDirPath,\n                                     String bindingUserInfo,\n                                     String appUserInfo,\n                                     String platform,\n                                     String platformVersion,\n                                     String sdkVersion,\n                                     String cpuArch,\n                                     String deviceName,\n                                     String deviceVersion,\n                                     String frameworkName,\n                                     String frameworkVersion\n    );\n\n    private static native void nativeLogin(long nativeAppPtr, long nativeCredentialsPtr, NetworkRequest callback);\n\n    @Nullable\n    private static native Long nativeCurrentUser(long nativePtr);\n\n    private static native long[] nativeGetAllUsers(long nativePtr);\n\n    private static native void nativeSwitchUser(long nativeAppPtr, long nativeUserPtr);\n\n    private static native long nativeGetFinalizerMethodPtr();\n\n    private static native OsJavaNetworkTransport.Request nativeMakeStreamingRequest(long nativeAppPtr, long nativeUserPtr, String functionName, String bsonArgs, String serviceName);\n}\n"
  },
  {
    "path": "realm/realm-library/src/objectServer/java/io/realm/internal/objectstore/OsAppCredentials.java",
    "content": "/*\n * Copyright 2020 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 */\npackage io.realm.internal.objectstore;\n\nimport org.bson.Document;\n\nimport io.realm.internal.NativeObject;\nimport io.realm.internal.jni.JniBsonProtocol;\nimport io.realm.mongodb.AppConfiguration;\nimport io.realm.mongodb.AppException;\nimport io.realm.mongodb.Credentials;\nimport io.realm.mongodb.auth.GoogleAuthType;\n\n\n/**\n * Class wrapping ObjectStores {@code realm::app::AppCredentials}.\n */\npublic class OsAppCredentials implements NativeObject {\n\n    private static final int TYPE_ANONYMOUS = 1;\n    private static final int TYPE_API_KEY = 2;\n    private static final int TYPE_APPLE = 3;\n    private static final int TYPE_CUSTOM_FUNCTION = 4;\n    private static final int TYPE_EMAIL_PASSWORD = 5;\n    private static final int TYPE_FACEBOOK = 6;\n    private static final int TYPE_JWT = 7;\n    private static final int TYPE_GOOGLE_AUTH_CODE = 8;\n    private static final int TYPE_GOOGLE_ID_TOKEN = 9;\n\n    private static final long finalizerPtr = nativeGetFinalizerMethodPtr();\n\n    public static OsAppCredentials anonymous() {\n        return new OsAppCredentials(nativeCreate(TYPE_ANONYMOUS));\n    }\n\n    public static OsAppCredentials apiKey(String key) {\n        return new OsAppCredentials(nativeCreate(TYPE_API_KEY, key));\n    }\n\n    public static OsAppCredentials apple(String idToken) {\n        return new OsAppCredentials(nativeCreate(TYPE_APPLE, idToken));\n    }\n\n    public static OsAppCredentials customFunction(Document args) {\n        String encodedArgs = JniBsonProtocol.encode(args, AppConfiguration.DEFAULT_BSON_CODEC_REGISTRY);\n        return new OsAppCredentials(nativeCreate(TYPE_CUSTOM_FUNCTION, encodedArgs));\n    }\n\n    public static OsAppCredentials emailPassword(String email, String password) {\n        return new OsAppCredentials(nativeCreate(TYPE_EMAIL_PASSWORD, email, password));\n    }\n\n    public static OsAppCredentials facebook(String accessToken) {\n        return new OsAppCredentials(nativeCreate(TYPE_FACEBOOK, accessToken));\n    }\n\n    public static OsAppCredentials google(String accessToken, GoogleAuthType type) {\n        int authType;\n\n        switch (type){\n            case AUTH_CODE:\n                authType = TYPE_GOOGLE_AUTH_CODE;\n                break;\n            case ID_TOKEN:\n                authType = TYPE_GOOGLE_ID_TOKEN;\n                break;\n            default:\n                throw new RuntimeException(\"Unsupported GoogleAuthType:  \" + type);\n        }\n\n        return new OsAppCredentials(nativeCreate(authType, accessToken));\n    }\n\n    public static OsAppCredentials jwt(String jwtToken) {\n        return new OsAppCredentials(nativeCreate(TYPE_JWT, jwtToken));\n    }\n\n    private final long nativePtr;\n\n    private OsAppCredentials(long nativePtr) {\n        this.nativePtr = nativePtr;\n    }\n\n    public String getProvider() {\n        return nativeGetProvider(nativePtr);\n    }\n\n    public String asJson() {\n        return nativeAsJson(nativePtr);\n    }\n\n    @Override\n    public long getNativePtr() {\n        return nativePtr;\n    }\n\n    @Override\n    public long getNativeFinalizerPtr() {\n        return finalizerPtr;\n    }\n\n    private static native long nativeCreate(int type, Object... args);\n    private static native String nativeGetProvider(long nativePtr);\n    private static native String nativeAsJson(long nativePtr);\n    private static native long nativeGetFinalizerMethodPtr();\n}\n"
  },
  {
    "path": "realm/realm-library/src/objectServer/java/io/realm/internal/objectstore/OsAsyncOpenTask.java",
    "content": "package io.realm.internal.objectstore;\n\n\nimport java.util.concurrent.CountDownLatch;\nimport java.util.concurrent.TimeUnit;\nimport java.util.concurrent.atomic.AtomicReference;\n\nimport io.realm.internal.ErrorCategory;\nimport io.realm.mongodb.ErrorCode;\nimport io.realm.mongodb.AppException;\nimport io.realm.internal.KeepMember;\nimport io.realm.internal.OsRealmConfig;\n\n/**\n * Wrapper for the ASyncOpenTask in ObjectStore, which also support timeouts.\n *\n * This ObjectStore class controls its own lifecycle, i.e. discards itself once complete, so the\n * Java object does not need to implement {@link io.realm.internal.NativeObject}.\n */\n@KeepMember\npublic class OsAsyncOpenTask {\n\n    private final OsRealmConfig config;\n    private long nativePtr;\n    private final CountDownLatch taskComplete = new CountDownLatch(1);\n    private final AtomicReference<ErrorCode> errorCode = new AtomicReference<>(null);\n    private final AtomicReference<String> errorMessage = new AtomicReference<>(null);\n\n    public OsAsyncOpenTask(OsRealmConfig config) {\n        this.config = config;\n    }\n\n    public void start(long timeOut, TimeUnit unit) throws InterruptedException {\n        this.nativePtr = start(config.getNativePtr());\n\n        try {\n            taskComplete.await(timeOut, unit);\n        } catch (InterruptedException e) {\n            cancel(nativePtr);\n            throw e;\n        }\n\n        ErrorCode errorCode = this.errorCode.get();\n        String errorMessage = this.errorMessage.get();\n        if (errorCode != null && errorMessage != null) {\n            throw new AppException(errorCode, errorMessage);\n        }\n    }\n\n    /**\n     * Called from JNI when the underlying async task has successfully downloaded the Realm.\n     */\n    @KeepMember\n    @SuppressWarnings(\"unused\")\n    private void notifyRealmReady() {\n        errorCode.set(null);\n        errorMessage.set(null);\n        taskComplete.countDown();\n    }\n\n    /**\n     * Called from JNI when the underlying async task encounters an error.\n     */\n    @KeepMember\n    @SuppressWarnings(\"unused\")\n    private void notifyError(byte nativeErrorCategory, int nativeErrorCode, String errorMessage) {\n        ErrorCode errorCode = ErrorCode.fromNativeError(ErrorCategory.toCategory(nativeErrorCategory), nativeErrorCode);\n        this.errorCode.set(errorCode);\n        this.errorMessage.set(errorMessage);\n        taskComplete.countDown();\n    }\n\n    private native long start(long configPtr);\n    private native void cancel(long nativePtr);\n}\n"
  },
  {
    "path": "realm/realm-library/src/objectServer/java/io/realm/internal/objectstore/OsJavaNetworkTransport.java",
    "content": "/*\n * Copyright 2020 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 */\npackage io.realm.internal.objectstore;\n\nimport java.io.IOException;\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport io.realm.internal.Keep;\nimport io.realm.mongodb.AppConfiguration;\nimport io.realm.mongodb.AppException;\n\n/**\n * Java implementation of the transport layer exposed by ObjectStore when communicating with\n * the MongoDB Realm Server.\n */\n@Keep\npublic abstract class OsJavaNetworkTransport {\n\n    // Custom error codes. These must not match any HTTP response error codes\n    public static final int ERROR_IO = 1000;\n    public static final int ERROR_INTERRUPTED = 1001;\n    public static final int ERROR_UNKNOWN = 1002;\n\n    // Header configuration\n    private String authorizationHeaderName;\n    private Map<String, String> customHeaders = new HashMap<>();\n\n    /**\n     * This method is being called from JNI in order to execute the network transport itself.\n     * All logic around retry and parsing of results should be done by ObjectStore.\n     *\n     * Warning: This method is not allowed to throw. Any exception should be wrapped in a\n     * {@link Response} and be returned as a result.\n     *\n     * This method assumes the network request is executed in an asynchronous manner.\n     * The actual request itself should always be executed within {@link #executeRequest(String, String, long, Map, String)}\n     * as that allow sub-classes to modify the behaviour on the thread actually doing the request.\n     *\n     * @param method Which kind of HTTP method in lowercase.\n     * @param url Url to connect to.\n     * @param timeoutMs How long does the request has to complete?\n     * @param headers Which headers to send?\n     * @param body Which body to include?\n     * @param completionBlockPtr completion block that must be called on the C++ side. Must be\n     *                           passed through {@link #handleResponse(Response, long)}.\n     */\n    public abstract void sendRequestAsync(String method,\n                                     String url,\n                                     long timeoutMs,\n                                     Map<String, String> headers,\n                                     String body,\n                                     long completionBlockPtr);\n\n    /**\n     * This method is responsible for actually exucuting the network request.\n     * The thread on which this method is called should be controlled by\n     * {@link #sendRequestAsync(String, String, long, Map, String, long)}.\n     *\n     * Warning: This method is not allowed to throw. Any exception should be wrapped in a\n     * {@link Response} and be returned as a result.\n     *\n     * @param method Which kind of HTTP method in lowercase.\n     * @param url Url to connect to.\n     * @param timeoutMs How long does the request has to complete?\n     * @param headers Which headers to send?\n     * @param body Which body to include?\n     * @return the response from the server or any exception being thrown\n     */\n    public abstract Response executeRequest(String method,\n                                            String url,\n                                            long timeoutMs,\n                                            Map<String, String> headers,\n                                            String body);\n\n    /**\n     * Pass back network response back to ObjectStore. All Exceptions should also be wrapped in\n     * Response object. The {@code completionBlockPtr} is deleted by the native side and is no longer\n     * valid after calling this method.\n     *\n     * @param response the response to a given request. Including exceptions.\n     * @param completionBlockPtr The native completion block responsible for handling the response.\n     */\n    public void handleResponse(Response response, long completionBlockPtr) {\n        nativeHandleResponse(response, completionBlockPtr);\n    }\n\n    /**\n     * This method is being called from Java when executing streaming requests.\n     * It returns a {@link Response} which body can be access line by line.\n     *\n     * Warning: this method and the returning {@link Response} throws exceptions\n     *\n     * @param request streaming request\n     * @return Result of the request.\n     * @throws IOException if the request fails to execute\n     * @throws AppException on an http error\n     */\n    public abstract Response sendStreamingRequest(Request request) throws IOException, AppException;\n\n    public void setAuthorizationHeaderName(String headerName) {\n        authorizationHeaderName = headerName;\n    }\n\n    public void addCustomRequestHeader(String headerName, String headerValue) {\n        customHeaders.put(headerName, headerValue);\n    }\n\n    public String getAuthorizationHeaderName() {\n        return authorizationHeaderName;\n    }\n\n    public Map<String, String> getCustomRequestHeaders() {\n        return customHeaders;\n    }\n\n    /**\n     * Reset to their default.\n     * Used for testing.\n     */\n    public void reset() {\n        authorizationHeaderName = AppConfiguration.DEFAULT_AUTHORIZATION_HEADER_NAME;\n        customHeaders.clear();\n    }\n\n    @Keep\n    public abstract static class Response {\n        private final int httpResponseCode;\n        private final int customResponseCode;\n        private final Map<String, String> headers;\n        private final String body;\n\n        protected Response(int httpResponseCode, int customResponseCode, Map<String, String> headers, String body) {\n            this.httpResponseCode = httpResponseCode;\n            this.customResponseCode = customResponseCode;\n            this.headers = headers;\n            this.body = body;\n        }\n\n        public int getHttpResponseCode() {\n            return httpResponseCode;\n        }\n\n        public int getCustomResponseCode() {\n            return customResponseCode;\n        }\n\n        public Map<String, String> getHeaders() {\n            return headers;\n        }\n\n        // Returns the HTTP headers in a JNI friendly way where it is being serialized to a\n        // String array consisting of pairs of { key , value } pairs.\n        public String[] getJNIFriendlyHeaders() {\n            String[] jniHeaders = new String[headers.size() * 2];\n            int i = 0;\n            for (Map.Entry<String, String> entry : headers.entrySet()) {\n                jniHeaders[i] = entry.getKey();\n                jniHeaders[i + 1] = entry.getValue();\n                i = i + 2;\n            }\n            return jniHeaders;\n        }\n\n        public String getBody() {\n            return body;\n        }\n\n        public String readBodyLine() throws IOException {\n            return null;\n        }\n\n        public boolean isOpen() {\n            return false;\n        }\n\n\n        @Override\n        public String toString() {\n            return \"Response{\" +\n                    \"httpResponseCode=\" + httpResponseCode +\n                    \", customResponseCode=\" + customResponseCode +\n                    \", headers=\" + headers +\n                    \", body='\" + body + '\\'' +\n                    '}';\n        }\n\n        /**\n         * Closes the current stream.\n         *\n         * Note: we use a close flag because the underlaying input stream might not be thread safe.\n         * @see <a href=\"http://google.com\">https://github.com/square/okio/issues/163#issuecomment-127052956</a>\n         *\n         * @throws IOException can throw exception if internal buffer not closed properly\n         */\n        public abstract void close();\n    }\n\n    public static class Request {\n        private String method;\n        private String url;\n        private Map<String, String> headers;\n        private String body;\n\n        public Request(String method, String url, Map<String, String> headers, String body) {\n            this.method = method;\n            this.url = url;\n            this.headers = headers;\n            this.body = body;\n        }\n\n        public String getMethod() {\n            return method;\n        }\n\n        public String getUrl() {\n            return url;\n        }\n\n        public Map<String, String> getHeaders() {\n            return headers;\n        }\n\n        public String getBody() {\n            return body;\n        }\n    }\n\n    /**\n     * Callback used when sending back results from network requests performed by ObjectStores\n     * {@code realm::app::NetworkTransport}.\n     *\n     * The callback will happen on the thread running the network request, not the intended receiver thread.\n     */\n    // Abstract because these methods needs to be called from JNI and we cannot look up interface methods.\n    // NOTE: This class is called from JNI. If renamed, adjust callbacks in App.cpp\n    @Keep\n    public abstract static class NetworkTransportJNIResultCallback {\n        public void onSuccess(Object result) {}\n        public void onError(byte nativeErrorCategory, int nativeErrorCode, String errorMessage, String logUrl) {}\n    }\n\n    private static native void nativeHandleResponse(Response response, long completionBlockPtr);\n}\n"
  },
  {
    "path": "realm/realm-library/src/objectServer/java/io/realm/internal/objectstore/OsMongoClient.java",
    "content": "/*\n * Copyright 2020 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\npackage io.realm.internal.objectstore;\n\nimport org.bson.codecs.configuration.CodecRegistry;\n\nimport java.util.concurrent.ThreadPoolExecutor;\n\nimport io.realm.internal.NativeObject;\nimport io.realm.internal.network.StreamNetworkTransport;\n\npublic class OsMongoClient implements NativeObject {\n\n    private static final long nativeFinalizerPtr = nativeGetFinalizerMethodPtr();\n\n    private final long nativePtr;\n    private final String serviceName;\n    private final StreamNetworkTransport streamNetworkTransport;\n\n    public OsMongoClient(final OsSyncUser osSyncUser,\n                         final String serviceName,\n                         final StreamNetworkTransport streamNetworkTransport) {\n        this.nativePtr = nativeCreate(osSyncUser.getNativePtr(), serviceName);\n        this.serviceName = serviceName;\n        this.streamNetworkTransport = streamNetworkTransport;\n    }\n\n    public OsMongoDatabase getDatabase(final String databaseName,\n                                       final CodecRegistry codecRegistry) {\n        long nativeDatabasePtr = nativeCreateDatabase(nativePtr, databaseName);\n        return new OsMongoDatabase(nativeDatabasePtr, serviceName, codecRegistry, streamNetworkTransport);\n    }\n\n    public String getServiceName() {\n        return serviceName;\n    }\n\n    @Override\n    public long getNativePtr() {\n        return nativePtr;\n    }\n\n    @Override\n    public long getNativeFinalizerPtr() {\n        return nativeFinalizerPtr;\n    }\n\n    private static native long nativeCreate(long nativeUserPtr, String serviceName);\n\n    private static native long nativeCreateDatabase(long nativeAppPtr, String databaseName);\n\n    private static native long nativeGetFinalizerMethodPtr();\n}\n"
  },
  {
    "path": "realm/realm-library/src/objectServer/java/io/realm/internal/objectstore/OsMongoCollection.java",
    "content": "/*\n * Copyright 2020 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\npackage io.realm.internal.objectstore;\n\nimport org.bson.BsonArray;\nimport org.bson.BsonDocument;\nimport org.bson.BsonNull;\nimport org.bson.BsonValue;\nimport org.bson.Document;\nimport org.bson.codecs.configuration.CodecRegistry;\nimport org.bson.conversions.Bson;\n\nimport java.io.IOException;\nimport java.util.ArrayList;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.concurrent.ThreadPoolExecutor;\n\nimport javax.annotation.Nullable;\n\nimport io.realm.internal.NativeObject;\nimport io.realm.internal.Util;\nimport io.realm.internal.events.NetworkEventStream;\nimport io.realm.internal.jni.JniBsonProtocol;\nimport io.realm.internal.network.NetworkRequest;\nimport io.realm.internal.network.StreamNetworkTransport;\nimport io.realm.internal.objectserver.EventStream;\nimport io.realm.mongodb.App;\nimport io.realm.mongodb.mongo.MongoNamespace;\nimport io.realm.mongodb.mongo.iterable.AggregateIterable;\nimport io.realm.mongodb.mongo.iterable.FindIterable;\nimport io.realm.mongodb.mongo.options.CountOptions;\nimport io.realm.mongodb.mongo.options.FindOneAndModifyOptions;\nimport io.realm.mongodb.mongo.options.FindOptions;\nimport io.realm.mongodb.mongo.options.InsertManyResult;\nimport io.realm.mongodb.mongo.options.UpdateOptions;\nimport io.realm.mongodb.mongo.result.DeleteResult;\nimport io.realm.mongodb.mongo.result.InsertOneResult;\nimport io.realm.mongodb.mongo.result.UpdateResult;\n\npublic class OsMongoCollection<DocumentT> implements NativeObject {\n\n    private static final int DELETE_ONE = 1;\n    private static final int DELETE_MANY = 2;\n    private static final int UPDATE_ONE = 3;\n    private static final int UPDATE_ONE_WITH_OPTIONS = 4;\n    private static final int UPDATE_MANY = 5;\n    private static final int UPDATE_MANY_WITH_OPTIONS = 6;\n    private static final int FIND_ONE_AND_UPDATE = 7;\n    private static final int FIND_ONE_AND_UPDATE_WITH_OPTIONS = 8;\n    private static final int FIND_ONE_AND_REPLACE = 9;\n    private static final int FIND_ONE_AND_REPLACE_WITH_OPTIONS = 10;\n    private static final int FIND_ONE_AND_DELETE = 11;\n    private static final int FIND_ONE_AND_DELETE_WITH_OPTIONS = 12;\n    private static final int FIND_ONE = 13;\n    private static final int FIND_ONE_WITH_OPTIONS = 14;\n    private static final int WATCH = 15;\n    private static final int WATCH_IDS = 16;\n    private static final int WATCH_WITH_FILTER= 17;\n\n\n    private static final long nativeFinalizerPtr = nativeGetFinalizerMethodPtr();\n\n    private final long nativePtr;\n    private final Class<DocumentT> documentClass;\n    private final CodecRegistry codecRegistry;\n    private final String encodedEmptyDocument;\n    private final ThreadPoolExecutor threadPoolExecutor = App.NETWORK_POOL_EXECUTOR;\n    private final String serviceName;\n    private final MongoNamespace namespace;\n    private final StreamNetworkTransport streamNetworkTransport;\n\n    OsMongoCollection(final long nativeCollectionPtr,\n                      final MongoNamespace namespace,\n                      final String serviceName,\n                      final Class<DocumentT> documentClass,\n                      final CodecRegistry codecRegistry,\n                      final StreamNetworkTransport streamNetworkTransport) {\n        this.nativePtr = nativeCollectionPtr;\n        this.namespace = namespace;\n        this.serviceName = serviceName;\n        this.documentClass = documentClass;\n        this.codecRegistry = codecRegistry;\n        this.encodedEmptyDocument = JniBsonProtocol.encode(new Document(), codecRegistry);\n        this.streamNetworkTransport = streamNetworkTransport;\n    }\n\n    @Override\n    public long getNativePtr() {\n        return nativePtr;\n    }\n\n    @Override\n    public long getNativeFinalizerPtr() {\n        return nativeFinalizerPtr;\n    }\n\n    public Class<DocumentT> getDocumentClass() {\n        return documentClass;\n    }\n\n    public CodecRegistry getCodecRegistry() {\n        return codecRegistry;\n    }\n\n    public <NewDocumentT> OsMongoCollection<NewDocumentT> withDocumentClass(\n            final Class<NewDocumentT> clazz) {\n        return new OsMongoCollection<>(nativePtr, namespace, serviceName, clazz, codecRegistry, streamNetworkTransport);\n    }\n\n    public OsMongoCollection<DocumentT> withCodecRegistry(final CodecRegistry codecRegistry) {\n        return new OsMongoCollection<>(nativePtr, namespace, serviceName, documentClass, codecRegistry, streamNetworkTransport);\n    }\n\n    public Long count() {\n        return countInternal(new Document(), null);\n    }\n\n    public Long count(final Bson filter) {\n        return countInternal(filter, null);\n    }\n\n    public Long count(final Bson filter, final CountOptions options) {\n        return countInternal(filter, options);\n    }\n\n    private Long countInternal(final Bson filter, @Nullable final CountOptions options) {\n        return new NetworkRequest<Long>() {\n            @Override\n            protected Long mapSuccess(Object result) {\n                return (Long) result;\n            }\n            @Override\n            protected void execute(NetworkRequest<Long> callback) {\n                final String filterString = JniBsonProtocol.encode(filter, codecRegistry);\n                final int limit = (options == null) ? 0 : options.getLimit();\n                nativeCount(nativePtr, filterString, limit, callback);\n            }\n        }.resultOrThrow();\n    }\n\n    public FindIterable<DocumentT> find() {\n        return findInternal(new Document(), documentClass, null);\n    }\n\n    public FindIterable<DocumentT> find(final FindOptions options) {\n        return findInternal(new Document(), documentClass, options);\n    }\n\n    public <ResultT> FindIterable<ResultT> find(final Class<ResultT> resultClass) {\n        return findInternal(new Document(), resultClass, null);\n    }\n\n    public <ResultT> FindIterable<ResultT> find(final Class<ResultT> resultClass, final FindOptions options) {\n        return findInternal(new Document(), resultClass, options);\n    }\n\n    public FindIterable<DocumentT> find(final Bson filter) {\n        return findInternal(filter, documentClass, null);\n    }\n\n    public FindIterable<DocumentT> find(final Bson filter, final FindOptions options) {\n        return findInternal(filter, documentClass, options);\n    }\n\n    public <ResultT> FindIterable<ResultT> find(final Bson filter,\n                                                final Class<ResultT> resultClass) {\n        return findInternal(filter, resultClass, null);\n    }\n\n    public <ResultT> FindIterable<ResultT> find(final Bson filter,\n                                                final Class<ResultT> resultClass,\n                                                final FindOptions options) {\n        return findInternal(filter, resultClass, options);\n    }\n\n    private <ResultT> FindIterable<ResultT> findInternal(final Bson filter,\n                                                         final Class<ResultT> resultClass,\n                                                         @Nullable final FindOptions options) {\n        FindIterable<ResultT> findIterable =\n                new FindIterable<>(threadPoolExecutor, this, codecRegistry, resultClass);\n        findIterable.filter(filter);\n\n        if (options != null) {\n            findIterable.limit(options.getLimit());\n            findIterable.projection(options.getProjection());\n        }\n        return findIterable;\n    }\n\n    public AggregateIterable<DocumentT> aggregate(final List<? extends Bson> pipeline) {\n        return aggregate(pipeline, documentClass);\n    }\n\n    public <ResultT> AggregateIterable<ResultT> aggregate(final List<? extends Bson> pipeline,\n                                                          final Class<ResultT> resultClass) {\n        return new AggregateIterable<>(threadPoolExecutor, this, codecRegistry, resultClass, pipeline);\n    }\n\n    public DocumentT findOne() {\n        return findOneInternal(FIND_ONE, new Document(), null, documentClass);\n    }\n\n    public <ResultT> ResultT findOne(final Class<ResultT> resultClass) {\n        return findOneInternal(FIND_ONE, new Document(), null, resultClass);\n    }\n\n    public DocumentT findOne(final Bson filter) {\n        return findOneInternal(FIND_ONE, filter, null, documentClass);\n    }\n\n    public <ResultT> ResultT findOne(final Bson filter, final Class<ResultT> resultClass) {\n        return findOneInternal(FIND_ONE, filter, null, resultClass);\n    }\n\n    public DocumentT findOne(final Bson filter, final FindOptions options) {\n        return findOneInternal(FIND_ONE_WITH_OPTIONS, filter, options, documentClass);\n    }\n\n    public <ResultT> ResultT findOne(final Bson filter,\n                                     final FindOptions options,\n                                     final Class<ResultT> resultClass) {\n        return findOneInternal(FIND_ONE_WITH_OPTIONS, filter, options, resultClass);\n    }\n\n    private <ResultT> ResultT findOneInternal(final int type,\n                                              final Bson filter,\n                                              @Nullable final FindOptions options,\n                                              final Class<ResultT> resultClass) {\n        return new NetworkRequest<ResultT>() {\n            @Override\n            protected ResultT mapSuccess(Object result) {\n                return findSuccessMapper(result, resultClass);\n            }\n\n            @Override\n            protected void execute(NetworkRequest<ResultT> callback) {\n                final String encodedFilter = JniBsonProtocol.encode(filter, codecRegistry);\n\n                // default to empty docs or update if needed\n                String projectionString = encodedEmptyDocument;\n                String sortString = encodedEmptyDocument;\n\n                switch (type) {\n                    case FIND_ONE:\n                        nativeFindOne(FIND_ONE, nativePtr, encodedFilter, projectionString, sortString, 0, callback);\n                        break;\n                    case FIND_ONE_WITH_OPTIONS:\n                        Util.checkNull(options, \"options\");\n                        projectionString = JniBsonProtocol.encode(options.getProjection(), codecRegistry);\n                        sortString = JniBsonProtocol.encode(options.getSort(), codecRegistry);\n\n                        nativeFindOne(FIND_ONE_WITH_OPTIONS, nativePtr, encodedFilter, projectionString, sortString, options.getLimit(), callback);\n                        break;\n                    default:\n                        throw new IllegalArgumentException(\"Invalid fineOne type: \" + type);\n                }\n            }\n        }.resultOrThrow();\n    }\n\n    public InsertOneResult insertOne(final DocumentT document) {\n        return new NetworkRequest<InsertOneResult>() {\n            @Override\n            protected InsertOneResult mapSuccess(Object result) {\n                BsonValue id = JniBsonProtocol.decode((String) result, BsonValue.class, codecRegistry);\n                return new InsertOneResult(id);\n            }\n            @Override\n            protected void execute(NetworkRequest<InsertOneResult> callback) {\n                final String encodedDocument = JniBsonProtocol.encode(document, codecRegistry);\n                nativeInsertOne(nativePtr, encodedDocument, callback);\n            }\n        }.resultOrThrow();\n    }\n\n    public InsertManyResult insertMany(final List<? extends DocumentT> documents) {\n        return new NetworkRequest<InsertManyResult>() {\n            @Override\n            protected InsertManyResult mapSuccess(Object result) {\n                Object[] objects = (Object[]) result;\n                Map<Long, BsonValue> insertedIdsMap = new HashMap<>();\n                for (int i = 0; i < objects.length; i++) {\n                    BsonValue id = JniBsonProtocol.decode((String) objects[i], BsonValue.class, codecRegistry);\n                    insertedIdsMap.put((long) i, id);\n                }\n                return new InsertManyResult(insertedIdsMap);\n            }\n            @Override\n            protected void execute(NetworkRequest<InsertManyResult> callback) {\n                final String encodedDocumentArray = JniBsonProtocol.encode(documents, codecRegistry);\n                nativeInsertMany(nativePtr, encodedDocumentArray, callback);\n            }\n        }.resultOrThrow();\n    }\n\n    public DeleteResult deleteOne(final Bson filter) {\n        return deleteInternal(DELETE_ONE, filter);\n    }\n\n    public DeleteResult deleteMany(final Bson filter) {\n        return deleteInternal(DELETE_MANY, filter);\n    }\n\n    // FIXME Type illegal argument might be thrown wrong\n    private DeleteResult deleteInternal(final int type, final Bson filter) {\n        return new NetworkRequest<DeleteResult>() {\n            @Override\n            protected DeleteResult mapSuccess(Object result) {\n                return new DeleteResult((Long) result);\n            }\n            @Override\n            protected void execute(NetworkRequest<DeleteResult> callback) {\n                final String jsonDocument = JniBsonProtocol.encode(filter, codecRegistry);\n                switch (type) {\n                    case DELETE_ONE:\n                        nativeDelete(DELETE_ONE, nativePtr, jsonDocument, callback);\n                        break;\n                    case DELETE_MANY:\n                        nativeDelete(DELETE_MANY, nativePtr, jsonDocument, callback);\n                        break;\n                    default:\n                        throw new IllegalArgumentException(\"Invalid delete type: \" + type);\n                }\n            }\n        }.resultOrThrow();\n    }\n\n    public UpdateResult updateOne(final Bson filter, final Bson update) {\n        return updateInternal(UPDATE_ONE, filter, update, null);\n    }\n\n    public UpdateResult updateOne(final Bson filter,\n                                  final Bson update,\n                                  final UpdateOptions options) {\n        return updateInternal(UPDATE_ONE_WITH_OPTIONS, filter, update, options);\n    }\n\n    public UpdateResult updateMany(final Bson filter, final Bson update) {\n        return updateInternal(UPDATE_MANY, filter, update, null);\n    }\n\n    public UpdateResult updateMany(final Bson filter,\n                                   final Bson update,\n                                   final UpdateOptions options) {\n        return updateInternal(UPDATE_MANY_WITH_OPTIONS, filter, update, options);\n    }\n\n    private UpdateResult updateInternal(final int type,\n                                        final Bson filter,\n                                        final Bson update,\n                                        @Nullable final UpdateOptions options) {\n        return new NetworkRequest<UpdateResult>() {\n            @Override\n            protected UpdateResult mapSuccess(Object result) {\n                BsonArray array = JniBsonProtocol.decode((String) result, BsonArray.class, codecRegistry);\n                long matchedCount = array.get(0).asInt32().getValue();\n                long modifiedCount = array.get(1).asInt32().getValue();\n                BsonValue upsertedId = array.get(2);\n\n                if (upsertedId instanceof BsonNull) {\n                    upsertedId = null;\n                }\n                return new UpdateResult(matchedCount, modifiedCount, upsertedId);\n            }\n            @Override\n            protected void execute(NetworkRequest<UpdateResult> callback) {\n                final String jsonFilter = JniBsonProtocol.encode(filter, codecRegistry);\n                final String jsonUpdate = JniBsonProtocol.encode(update, codecRegistry);\n\n                switch (type) {\n                    case UPDATE_ONE:\n                    case UPDATE_MANY:\n                        nativeUpdate(type, nativePtr, jsonFilter, jsonUpdate, false, callback);\n                        break;\n                    case UPDATE_ONE_WITH_OPTIONS:\n                    case UPDATE_MANY_WITH_OPTIONS:\n                        Util.checkNull(options, \"options\");\n                        nativeUpdate(type, nativePtr, jsonFilter, jsonUpdate, options.isUpsert(), callback);\n                        break;\n                    default:\n                        throw new IllegalArgumentException(\"Invalid update type: \" + type);\n                }\n            }\n        }.resultOrThrow();\n    }\n\n    public DocumentT findOneAndUpdate(final Bson filter, final Bson update) {\n        return findOneAndUpdate(filter, update, documentClass);\n    }\n\n    public <ResultT> ResultT findOneAndUpdate(final Bson filter,\n                                              final Bson update,\n                                              final Class<ResultT> resultClass) {\n        return findOneAndModify(FIND_ONE_AND_UPDATE, filter, update, null, resultClass);\n    }\n\n    public DocumentT findOneAndUpdate(final Bson filter,\n                                      final Bson update,\n                                      final FindOneAndModifyOptions options) {\n        return findOneAndUpdate(filter, update, options, documentClass);\n    }\n\n    public <ResultT> ResultT findOneAndUpdate(final Bson filter,\n                                              final Bson update,\n                                              final FindOneAndModifyOptions options,\n                                              final Class<ResultT> resultClass) {\n        return findOneAndModify(FIND_ONE_AND_UPDATE_WITH_OPTIONS, filter, update, options, resultClass);\n    }\n\n    public DocumentT findOneAndReplace(final Bson filter, final Bson replacement) {\n        return findOneAndReplace(filter, replacement, documentClass);\n    }\n\n    public <ResultT> ResultT findOneAndReplace(final Bson filter,\n                                               final Bson replacement,\n                                               final Class<ResultT> resultClass) {\n        return findOneAndModify(FIND_ONE_AND_REPLACE, filter, replacement, null, resultClass);\n    }\n\n    public DocumentT findOneAndReplace(final Bson filter,\n                                       final Bson replacement,\n                                       final FindOneAndModifyOptions options) {\n        return findOneAndReplace(filter, replacement, options, documentClass);\n    }\n\n    public <ResultT> ResultT findOneAndReplace(final Bson filter,\n                                               final Bson replacement,\n                                               final FindOneAndModifyOptions options,\n                                               final Class<ResultT> resultClass) {\n        return findOneAndModify(FIND_ONE_AND_REPLACE_WITH_OPTIONS, filter, replacement, options, resultClass);\n    }\n\n    public DocumentT findOneAndDelete(final Bson filter) {\n        return findOneAndDelete(filter, documentClass);\n    }\n\n    public <ResultT> ResultT findOneAndDelete(final Bson filter,\n                                              final Class<ResultT> resultClass) {\n        return findOneAndModify(FIND_ONE_AND_DELETE, filter, new Document(), null, resultClass);\n    }\n\n    public DocumentT findOneAndDelete(final Bson filter,\n                                      final FindOneAndModifyOptions options) {\n        return findOneAndDelete(filter, options, documentClass);\n    }\n\n    public <ResultT> ResultT findOneAndDelete(final Bson filter,\n                                              final FindOneAndModifyOptions options,\n                                              final Class<ResultT> resultClass) {\n        return findOneAndModify(FIND_ONE_AND_DELETE_WITH_OPTIONS, filter, new Document(), options, resultClass);\n    }\n\n    public String getServiceName() {\n        return serviceName;\n    }\n\n    private <ResultT> ResultT findOneAndModify(final int type,\n                                               final Bson filter,\n                                               final Bson update,\n                                               @Nullable final FindOneAndModifyOptions options,\n                                               final Class<ResultT> resultClass) {\n        return new NetworkRequest<ResultT>() {\n            @Override\n            protected ResultT mapSuccess(Object result) {\n                return findSuccessMapper(result, resultClass);\n            }\n            @Override\n            protected void execute(NetworkRequest<ResultT> callback) {\n                final String encodedFilter = JniBsonProtocol.encode(filter, codecRegistry);\n                final String encodedUpdate = JniBsonProtocol.encode(update, codecRegistry);\n\n                // default to empty docs or update if needed\n                String encodedProjection = encodedEmptyDocument;\n                String encodedSort = encodedEmptyDocument;\n                if (options != null) {\n                    if (options.getProjection() != null) {\n                        encodedProjection = JniBsonProtocol.encode(options.getProjection(), codecRegistry);\n                    }\n                    if (options.getSort() != null) {\n                        encodedSort = JniBsonProtocol.encode(options.getSort(), codecRegistry);\n                    }\n                }\n\n                switch (type) {\n                    case FIND_ONE_AND_UPDATE:\n                        nativeFindOneAndUpdate(type, nativePtr, encodedFilter, encodedUpdate, encodedProjection, encodedSort, false, false, callback);\n                        break;\n                    case FIND_ONE_AND_UPDATE_WITH_OPTIONS:\n                        Util.checkNull(options, \"options\");\n                        nativeFindOneAndUpdate(type, nativePtr, encodedFilter, encodedUpdate, encodedProjection, encodedSort, options.isUpsert(), options.isReturnNewDocument(), callback);\n                        break;\n                    case FIND_ONE_AND_REPLACE:\n                        nativeFindOneAndReplace(type, nativePtr, encodedFilter, encodedUpdate, encodedProjection, encodedSort, false, false, callback);\n                        break;\n                    case FIND_ONE_AND_REPLACE_WITH_OPTIONS:\n                        Util.checkNull(options, \"options\");\n                        nativeFindOneAndReplace(type, nativePtr, encodedFilter, encodedUpdate, encodedProjection, encodedSort, options.isUpsert(), options.isReturnNewDocument(), callback);\n                        break;\n                    case FIND_ONE_AND_DELETE:\n                        nativeFindOneAndDelete(type, nativePtr, encodedFilter, encodedProjection, encodedSort, false, false, callback);\n                        break;\n                    case FIND_ONE_AND_DELETE_WITH_OPTIONS:\n                        Util.checkNull(options, \"options\");\n                        nativeFindOneAndDelete(type, nativePtr, encodedFilter, encodedProjection, encodedSort, options.isUpsert(), options.isReturnNewDocument(), callback);\n                        break;\n                    default:\n                        throw new IllegalArgumentException(\"Invalid modify type: \" + type);\n                }\n            }\n        }.resultOrThrow();\n    }\n\n    private <T> T findSuccessMapper(@Nullable Object result, Class<T> resultClass) {\n        if (result == null) {\n            return null;\n        } else {\n            return JniBsonProtocol.decode((String) result, resultClass, codecRegistry);\n        }\n    }\n\n    private EventStream<DocumentT> watchInternal(int type, @Nullable List<?> ids, @Nullable BsonDocument matchFilter) throws IOException {\n        List<Document> args = new ArrayList<>();\n\n        Document watchArgs = new Document(\"database\", namespace.getDatabaseName());\n        watchArgs.put(\"collection\", namespace.getCollectionName());\n\n        switch (type) {\n            case WATCH:\n                break;\n            case WATCH_IDS:\n                watchArgs.put(\"ids\", ids);\n                break;\n            case WATCH_WITH_FILTER:\n                watchArgs.put(\"filter\", matchFilter);\n                break;\n            default:\n                throw new IllegalArgumentException(\"Invalid watch type: \" + type);\n        }\n\n        args.add(watchArgs);\n\n        String encodedArguments = JniBsonProtocol.encode(args, codecRegistry);\n\n        OsJavaNetworkTransport.Request request = streamNetworkTransport.makeStreamingRequest(\"watch\", encodedArguments, serviceName);\n        OsJavaNetworkTransport.Response response = streamNetworkTransport.sendRequest(request);\n\n        return new NetworkEventStream<>(response, codecRegistry, documentClass);\n    }\n\n    public EventStream<DocumentT> watch() throws IOException {\n        return watchInternal(WATCH, null, null);\n    }\n\n    public EventStream<DocumentT> watch(final List<?> ids) throws IOException {\n        return watchInternal(WATCH_IDS, ids, null);\n    }\n\n    public EventStream<DocumentT> watchWithFilter(Document matchFilter) throws IOException {\n        return watchInternal(WATCH_WITH_FILTER, null, matchFilter.toBsonDocument(getDocumentClass(), getCodecRegistry()));\n    }\n\n    public EventStream<DocumentT> watchWithFilter(BsonDocument matchFilter) throws IOException {\n        return watchInternal(WATCH_WITH_FILTER, null, matchFilter);\n    }\n\n    private static native long nativeGetFinalizerMethodPtr();\n\n    private static native void nativeCount(long remoteMongoCollectionPtr,\n                                           String filter,\n                                           long limit,\n                                           OsJavaNetworkTransport.NetworkTransportJNIResultCallback callback);\n\n    private static native void nativeFindOne(int findOneType,\n                                             long nativePtr,\n                                             String filter,\n                                             String projection,\n                                             String sort,\n                                             long limit,\n                                             OsJavaNetworkTransport.NetworkTransportJNIResultCallback callback);\n\n    private static native void nativeInsertOne(long remoteMongoCollectionPtr,\n                                               String document,\n                                               OsJavaNetworkTransport.NetworkTransportJNIResultCallback callback);\n\n    private static native void nativeInsertMany(long remoteMongoCollectionPtr,\n                                                String documents,\n                                                OsJavaNetworkTransport.NetworkTransportJNIResultCallback callback);\n\n    private static native void nativeDelete(int deleteType,\n                                            long remoteMongoCollectionPtr,\n                                            String document,\n                                            OsJavaNetworkTransport.NetworkTransportJNIResultCallback callback);\n\n    private static native void nativeUpdate(int updateType,\n                                            long remoteMongoCollectionPtr,\n                                            String filter,\n                                            String update,\n                                            boolean upsert,\n                                            OsJavaNetworkTransport.NetworkTransportJNIResultCallback callback);\n\n    private static native void nativeFindOneAndUpdate(int findOneAndUpdateType,\n                                                      long remoteMongoCollectionPtr,\n                                                      String filter,\n                                                      String update,\n                                                      String projection,\n                                                      String sort,\n                                                      boolean upsert,\n                                                      boolean returnNewDocument,\n                                                      OsJavaNetworkTransport.NetworkTransportJNIResultCallback callback);\n\n    private static native void nativeFindOneAndReplace(int findOneAndReplaceType,\n                                                       long remoteMongoCollectionPtr,\n                                                       String filter,\n                                                       String update,\n                                                       String projection,\n                                                       String sort,\n                                                       boolean upsert,\n                                                       boolean returnNewDocument,\n                                                       OsJavaNetworkTransport.NetworkTransportJNIResultCallback callback);\n\n    private static native void nativeFindOneAndDelete(int findOneAndDeleteType,\n                                                      long remoteMongoCollectionPtr,\n                                                      String filter,\n                                                      String projection,\n                                                      String sort,\n                                                      boolean upsert,\n                                                      boolean returnNewDocument,\n                                                      OsJavaNetworkTransport.NetworkTransportJNIResultCallback callback);\n}\n"
  },
  {
    "path": "realm/realm-library/src/objectServer/java/io/realm/internal/objectstore/OsMongoDatabase.java",
    "content": "/*\n * Copyright 2020 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\npackage io.realm.internal.objectstore;\n\nimport org.bson.Document;\nimport org.bson.codecs.configuration.CodecRegistry;\n\nimport java.util.concurrent.ThreadPoolExecutor;\n\nimport io.realm.internal.NativeObject;\nimport io.realm.internal.network.StreamNetworkTransport;\nimport io.realm.mongodb.mongo.MongoNamespace;\n\npublic class OsMongoDatabase implements NativeObject {\n\n    private static final long nativeFinalizerPtr = nativeGetFinalizerMethodPtr();\n\n    private final long nativePtr;\n    private final String serviceName;\n    private final CodecRegistry codecRegistry;\n    private final StreamNetworkTransport streamNetworkTransport;\n\n    OsMongoDatabase(final long nativeDatabasePtr,\n                    final String serviceName,\n                    final CodecRegistry codecRegistry,\n                    final StreamNetworkTransport streamNetworkTransport) {\n        this.nativePtr = nativeDatabasePtr;\n        this.serviceName = serviceName;\n        this.codecRegistry = codecRegistry;\n        this.streamNetworkTransport = streamNetworkTransport;\n    }\n\n    public OsMongoCollection<Document> getCollection(final String collectionName, final MongoNamespace namespace) {\n        return getCollection(collectionName, namespace, Document.class);\n    }\n\n    public <DocumentT> OsMongoCollection<DocumentT> getCollection(final String collectionName,\n                                                                  final MongoNamespace namespace,\n                                                                  final Class<DocumentT> documentClass) {\n        long nativeCollectionPtr = nativeGetCollection(nativePtr, collectionName);\n        return new OsMongoCollection<>(nativeCollectionPtr, namespace, serviceName, documentClass, codecRegistry, streamNetworkTransport);\n    }\n\n    @Override\n    public long getNativePtr() {\n        return nativePtr;\n    }\n\n    @Override\n    public long getNativeFinalizerPtr() {\n        return nativeFinalizerPtr;\n    }\n\n    private static native long nativeGetCollection(long nativeDatabasePtr, String collectionName);\n    private static native long nativeGetFinalizerMethodPtr();\n}\n"
  },
  {
    "path": "realm/realm-library/src/objectServer/java/io/realm/internal/objectstore/OsPush.java",
    "content": "/*\n * Copyright 2020 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\npackage io.realm.internal.objectstore;\n\nimport io.realm.internal.NativeObject;\nimport io.realm.internal.network.NetworkRequest;\nimport io.realm.internal.network.VoidNetworkRequest;\n\npublic class OsPush implements NativeObject {\n\n    private static final long nativeFinalizerPtr = nativeGetFinalizerMethodPtr();\n\n    private final long nativePtr;\n    private final OsSyncUser osSyncUser;\n    private final String serviceName;\n\n    public OsPush(final OsApp osApp, final OsSyncUser osSyncUser, final String serviceName) {\n        this.nativePtr = nativeCreate(osApp.getNativePtr(), serviceName);\n        this.osSyncUser = osSyncUser;\n        this.serviceName = serviceName;\n    }\n\n    @Override\n    public long getNativePtr() {\n        return nativePtr;\n    }\n\n    @Override\n    public long getNativeFinalizerPtr() {\n        return nativeFinalizerPtr;\n    }\n\n    public void registerDevice(String registrationToken) {\n        new VoidNetworkRequest() {\n            @Override\n            protected void execute(NetworkRequest<Void> callback) {\n                nativeRegisterDevice(nativePtr, osSyncUser.getNativePtr(), serviceName, registrationToken, callback);\n            }\n        }.execute();\n    }\n\n    public void deregisterDevice() {\n        new VoidNetworkRequest() {\n            @Override\n            protected void execute(NetworkRequest<Void> callback) {\n                nativeDeregisterDevice(nativePtr, osSyncUser.getNativePtr(), serviceName, callback);\n            }\n        }.execute();\n    }\n\n    private static native long nativeCreate(long nativeAppPtr, String serviceName);\n    private static native long nativeGetFinalizerMethodPtr();\n    private static native void nativeRegisterDevice(long nativePtr, long nativeUserPtr, String serviceName, String registrationToken, OsJavaNetworkTransport.NetworkTransportJNIResultCallback callback);\n    private static native void nativeDeregisterDevice(long nativePtr, long nativeUserPtr, String serviceName, OsJavaNetworkTransport.NetworkTransportJNIResultCallback callback);\n}\n"
  },
  {
    "path": "realm/realm-library/src/objectServer/java/io/realm/internal/objectstore/OsSyncUser.java",
    "content": "/*\n * Copyright 2020 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 */\npackage io.realm.internal.objectstore;\n\nimport org.bson.Document;\n\nimport io.realm.internal.NativeObject;\nimport io.realm.internal.jni.JniBsonProtocol;\nimport io.realm.internal.network.NetworkRequest;\nimport io.realm.internal.network.VoidNetworkRequest;\nimport io.realm.internal.util.Pair;\nimport io.realm.mongodb.AppConfiguration;\n\npublic class OsSyncUser implements NativeObject {\n\n    private final long nativePtr;\n    private static final long nativeFinalizerPtr = nativeGetFinalizerMethodPtr();\n\n    public static final byte STATE_LOGGED_IN = 1;\n    public static final byte STATE_REMOVED = 2;\n    public static final byte STATE_LOGGED_OUT = 3;\n\n    public OsSyncUser(long nativePtr) {\n        this.nativePtr = nativePtr;\n    }\n\n    @Override\n    public long getNativePtr() {\n        return nativePtr;\n    }\n\n    @Override\n    public long getNativeFinalizerPtr() {\n        return nativeFinalizerPtr;\n    }\n\n    public String nativeGetName() {\n        return nativeGetName(nativePtr);\n    }\n\n    public String getEmail() {\n        return nativeGetEmail(nativePtr);\n    }\n\n    public String getPictureUrl() {\n        return nativeGetPictureUrl(nativePtr);\n    }\n\n    public String getFirstName() {\n        return nativeGetFirstName(nativePtr);\n    }\n\n    public String getLastName() {\n        return nativeGetLastName(nativePtr);\n    }\n\n    public String getGender() {\n        return nativeGetGender(nativePtr);\n    }\n\n    public String getBirthday() {\n        return nativeGetBirthday(nativePtr);\n    }\n\n    public String getMinAge() {\n        return nativeGetMinAge(nativePtr);\n    }\n\n    public String getMaxAge() {\n        return nativeGetMaxAge(nativePtr);\n    }\n\n    public String getIdentity() {\n        return nativeGetIdentity(nativePtr);\n    }\n\n    public String getAccessToken() {\n        return nativeGetAccessToken(nativePtr);\n    }\n\n    public String getRefreshToken() {\n        return nativeGetRefreshToken(nativePtr);\n    }\n\n    public Pair<String, String>[] getIdentities() {\n        String[] identityData = nativeGetIdentities(nativePtr);\n        @SuppressWarnings(\"unchecked\")\n        Pair<String, String>[] identities = new Pair[identityData.length/2];\n        for (int i = 0; i < identityData.length; i = i + 2) {\n            identities[i/2] = new Pair<>(identityData[i], identityData[i+1]);\n        }\n        return identities;\n    }\n\n    public String getDeviceId() {\n        return nativeGetDeviceId(nativePtr);\n    }\n\n    /**\n     * @return {@link #STATE_LOGGED_IN}, {@link #STATE_LOGGED_OUT} or {@link #STATE_REMOVED}\n     */\n    public byte getState() {\n        return nativeGetState(nativePtr);\n    }\n\n    public Document getCustomData() {\n        String encodedData = nativeCustomData(nativePtr);\n        // Stitch also used default codec registry for parsing access token\n        return JniBsonProtocol.decode(encodedData, AppConfiguration.DEFAULT_BSON_CODEC_REGISTRY.get(Document.class));\n    }\n\n    public void refreshCustomData() {\n        new VoidNetworkRequest() {\n            @Override\n            protected void execute(NetworkRequest<Void> callback) {\n                nativeRefreshCustomData(nativePtr, callback);\n            }\n        }.execute();\n    }\n\n    public String getProviderType() {\n        return nativeGetProviderType(nativePtr);\n    }\n\n    @Override\n    public boolean equals(Object o) {\n        if (this == o) return true;\n        if (o == null || getClass() != o.getClass()) return false;\n\n        OsSyncUser that = (OsSyncUser) o;\n        return getIdentity().equals(that.getIdentity());\n    }\n\n    @Override\n    public int hashCode() {\n        return getIdentity().hashCode();\n    }\n\n    private static native long nativeGetFinalizerMethodPtr();\n    private static native String nativeGetName(long nativePtr);\n    private static native String nativeGetEmail(long nativePtr);\n    private static native String nativeGetPictureUrl(long nativePtr);\n    private static native String nativeGetFirstName(long nativePtr);\n    private static native String nativeGetLastName(long nativePtr);\n    private static native String nativeGetGender(long nativePtr);\n    private static native String nativeGetBirthday(long nativePtr);\n    private static native String nativeGetMinAge(long nativePtr);\n    private static native String nativeGetMaxAge(long nativePtr);\n    private static native String nativeGetIdentity(long nativePtr);\n    private static native String nativeGetAccessToken(long nativePtr);\n    private static native String nativeGetRefreshToken(long nativePtr);\n    private static native String[] nativeGetIdentities(long nativePtr); // Returns pairs of {id, provider}\n    private static native byte nativeGetState(long nativePtr);\n    private static native String nativeGetProviderType(long nativePtr);\n    private static native String nativeGetDeviceId(long nativePtr);\n    private static native String nativeCustomData(long nativeUserPtr);\n    private static native void nativeRefreshCustomData(long nativeUserPtr, OsJavaNetworkTransport.NetworkTransportJNIResultCallback callback);\n}\n"
  },
  {
    "path": "realm/realm-library/src/objectServer/java/io/realm/internal/objectstore/OsWatchStream.java",
    "content": "package io.realm.internal.objectstore;\n\nimport org.bson.BsonDocument;\nimport org.bson.codecs.configuration.CodecRegistry;\n\nimport io.realm.internal.NativeObject;\nimport io.realm.internal.jni.JniBsonProtocol;\nimport io.realm.mongodb.AppException;\n\npublic class OsWatchStream implements NativeObject {\n    public static final String NEED_DATA = \"NEED_DATA\";\n    public static final String HAVE_EVENT = \"HAVE_EVENT\";\n    public static final String HAVE_ERROR = \"HAVE_ERROR\";\n\n    private final long nativePtr;\n    private final CodecRegistry codecRegistry;\n\n    public OsWatchStream(CodecRegistry codecRegistry) {\n        this.codecRegistry = codecRegistry;\n        this.nativePtr = nativeCreateWatchStream();\n    }\n\n    @Override\n    public long getNativePtr() {\n        return this.nativePtr;\n    }\n\n    @Override\n    public long getNativeFinalizerPtr() {\n        return nativeGetFinalizerMethodPtr();\n    }\n\n    public BsonDocument getNextEvent() {\n        String bsonEvent = nativeGetNextEvent(nativePtr);\n        return JniBsonProtocol.decode(bsonEvent, codecRegistry.get(BsonDocument.class));\n    }\n\n    public String getState() {\n        return nativeGetState(nativePtr);\n    }\n\n    public AppException getError() {\n        return nativeGetError(nativePtr);\n    }\n\n    public void feedLine(String line) {\n        nativeFeedLine(nativePtr, line);\n    }\n\n    private static native long nativeGetFinalizerMethodPtr();\n    private static native long nativeCreateWatchStream();\n    private static native void nativeFeedLine(long nativePtr, String line);\n    private static native String nativeGetState(long nativePtr);\n    private static native String nativeGetNextEvent(long nativePtr);\n    private static native AppException nativeGetError(long nativePtr);\n}\n"
  },
  {
    "path": "realm/realm-library/src/objectServer/java/io/realm/internal/objectstore/package-info.java",
    "content": "/*\n * Copyright 2017 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@javax.annotation.ParametersAreNonnullByDefault\npackage io.realm.internal.objectstore;\n"
  },
  {
    "path": "realm/realm-library/src/objectServer/java/io/realm/mongodb/ApiKeyAuthImpl.java",
    "content": "/*\n * Copyright 2020 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\npackage io.realm.mongodb;\n\nimport javax.annotation.Nullable;\n\nimport io.realm.annotations.Beta;\nimport io.realm.internal.objectstore.OsJavaNetworkTransport;\nimport io.realm.mongodb.auth.ApiKeyAuth;\n\n@Beta\nclass ApiKeyAuthImpl extends ApiKeyAuth {\n\n    ApiKeyAuthImpl(User user) {\n        super(user);\n    }\n\n    @Override\n    protected void call(int functionType, @Nullable String arg, OsJavaNetworkTransport.NetworkTransportJNIResultCallback callback) {\n        nativeCallFunction(functionType, getApp().osApp.getNativePtr(), getUser().osUser.getNativePtr(), arg, callback);\n    }\n\n    private static native void nativeCallFunction(int functionType, long nativeAppPtr, long nativeUserPtr, @Nullable String arg, OsJavaNetworkTransport.NetworkTransportJNIResultCallback callback);\n\n}\n"
  },
  {
    "path": "realm/realm-library/src/objectServer/java/io/realm/mongodb/App.java",
    "content": "/*\n * Copyright 2020 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 */\npackage io.realm.mongodb;\n\nimport android.content.Context;\nimport android.os.Build;\nimport android.os.Handler;\nimport android.os.Looper;\n\nimport org.bson.codecs.configuration.CodecRegistry;\n\nimport java.io.File;\nimport java.io.IOException;\nimport java.util.HashMap;\nimport java.util.Locale;\nimport java.util.Map;\nimport java.util.concurrent.CopyOnWriteArrayList;\nimport java.util.concurrent.ThreadPoolExecutor;\n\nimport javax.annotation.Nullable;\n\nimport edu.umd.cs.findbugs.annotations.SuppressFBWarnings;\nimport io.realm.BuildConfig;\nimport io.realm.Realm;\nimport io.realm.RealmAsyncTask;\nimport io.realm.annotations.Beta;\nimport io.realm.internal.KeepMember;\nimport io.realm.internal.Util;\nimport io.realm.internal.async.RealmThreadPoolExecutor;\nimport io.realm.internal.mongodb.Request;\nimport io.realm.internal.objectstore.OsApp;\nimport io.realm.internal.objectstore.OsJavaNetworkTransport;\nimport io.realm.internal.objectstore.OsSyncUser;\nimport io.realm.log.RealmLog;\nimport io.realm.mongodb.auth.EmailPasswordAuth;\nimport io.realm.mongodb.functions.Functions;\nimport io.realm.mongodb.sync.Sync;\n\n/**\n * An <i>App</i> is the main client-side entry point for interacting with a <i>MongoDB Realm App</i>.\n * <p>\n * The <i>App</i> can be used to:\n * <ul>\n *   <li>Register uses and perform various user-related operations through authentication providers\n *   ({@link io.realm.mongodb.auth.ApiKeyAuth}, {@link EmailPasswordAuthImpl})</li>\n *   <li>Synchronize data between the local device and a remote Realm App with Synchronized Realms</li>\n *   <li>Invoke Realm App functions with {@link Functions}</li>\n *   <li>Access remote data from MongoDB databases with a {@link io.realm.mongodb.mongo.MongoClient}</li>\n * </ul>\n * <p>\n * To create an app that is linked with a remote <i>Realm App</i> initialize Realm and configure the\n * <i>App</i> as shown below:\n * <p>\n * <pre>\n *    class MyApplication extends Application {\n *\n *         App APP; // The App instance should be a global singleton\n *\n *         \\@Override\n *         public void onCreate() {\n *             super.onCreate();\n *\n *             Realm.init(this);\n *\n *             AppConfiguration appConfiguration = new AppConfiguration.Builder(BuildConfig.MONGODB_REALM_APP_ID)\n *                     .appName(BuildConfig.VERSION_NAME)\n *                     .appVersion(Integer.toString(BuildConfig.VERSION_CODE))\n *                     .build();\n *\n *             APP = new App(appConfiguration);\n *         }\n *\n *     }\n * </pre>\n * <p>\n * After configuring the <i>App</i> you can start managing users, configure Synchronized Realms,\n * call remote Realm Functions and access remote data through Mongo Collections. The examples below\n * show the synchronized APIs which cannot be used from the main thread. For the equivalent\n * asynchronous counterparts. The example project in please see\n * https://github.com/realm/realm-java/tree/v10/examples/mongoDbRealmExample.\n * <p>\n * To register a new user and/or login with an existing user do as shown below:\n * <pre>\n *     // Register new user\n *     APP.getEmailPassword().registerUser(username, password);\n *\n *     // Login with existing user\n *     User user = APP.login(Credentials.emailPassword(username, password))\n * </pre>\n * <p>\n * With an authorized user you can synchronize data between the local device and the remote Realm\n * App by opening a Realm with a {@link io.realm.mongodb.sync.SyncConfiguration} as indicated below:\n * <pre>\n *     SyncConfiguration syncConfiguration = new SyncConfiguration.Builder(user, \"&lt;partition value&gt;\")\n *              .build();\n *\n *     Realm instance = Realm.getInstance(syncConfiguration);\n *     SyncSession session = APP.getSync().getSession(syncConfiguration);\n *\n *     instance.executeTransaction(realm -&gt; {\n *         realm.insert(...);\n *     });\n *     session.uploadAllLocalChanges();\n *     instance.close();\n * </pre>\n * <p>\n * You can call remote Realm functions as shown below:\n * <pre>\n *     Functions functions = user.getFunctions();\n *     Integer sum = functions.callFunction(\"sum\", Arrays.asList(1, 2, 3, 4), Integer.class);\n * </pre>\n * <p>\n * And access collections from the remote Realm App as shown here:\n * <pre>\n *     MongoClient client = user.getMongoClient(SERVICE_NAME)\n *     MongoDatabase database = client.getDatabase(DATABASE_NAME)\n *     MongoCollection&lt;DocumentT&gt; collection = database.getCollection(COLLECTION_NAME);\n *     Long count = collection.count().get()\n * </pre>\n * <p>\n *\n * @see AppConfiguration.Builder\n * @see EmailPasswordAuth\n * @see io.realm.mongodb.sync.SyncConfiguration\n * @see User#getFunctions()\n * @see User#getMongoClient(String)\n */\n@Beta\npublic class App {\n\n    @KeepMember\n    final OsApp osApp;\n\n    static final class SyncImpl extends Sync {\n        protected SyncImpl(App app) {\n            super(app, app.osApp.getNativePtr());\n        }\n    }\n\n    /**\n     * Thread pool used when doing network requests against MongoDB Realm.\n     * <p>\n     * This pool is only exposed for testing purposes and replacing it while the queue is not\n     * empty will result in undefined behaviour.\n     */\n    @SuppressFBWarnings(\"MS_SHOULD_BE_FINAL\")\n    public static ThreadPoolExecutor NETWORK_POOL_EXECUTOR = RealmThreadPoolExecutor.newDefaultExecutor();\n\n    private final AppConfiguration config;\n    final Sync syncManager;\n    private final EmailPasswordAuth emailAuthProvider = new EmailPasswordAuthImpl(this);\n    private CopyOnWriteArrayList<AuthenticationListener> authListeners = new CopyOnWriteArrayList<>();\n    private Handler mainHandler = new Handler(Looper.getMainLooper());\n\n    public App(String appId) {\n        this(new AppConfiguration.Builder(appId).build());\n    }\n\n    /**\n     * Constructor for creating an <i>App</i> according to the given <i>AppConfiguration</i>.\n     *\n     * @param config The configuration to use for this <i>App</i> instance.\n     * @see AppConfiguration.Builder\n     */\n    public App(AppConfiguration config) {\n        this.config = config;\n        this.osApp = init(config);\n        this.syncManager = new SyncImpl(this);\n    }\n\n    private OsApp init(AppConfiguration config) {\n        String userAgentBindingInfo = getBindingInfo();\n        String appDefinedUserAgent = getAppInfo(config);\n        String syncDir = getSyncBaseDirectory(config);\n\n        return new OsApp(config, userAgentBindingInfo, appDefinedUserAgent, syncDir);\n    }\n\n    private String getSyncBaseDirectory(AppConfiguration config) {\n        Context context = Realm.getApplicationContext();\n        if (context == null) {\n            throw new IllegalStateException(\"Call Realm.init() first.\");\n        }\n        String syncDir;\n        if (Sync.Debug.separatedDirForSyncManager) {\n            try {\n                // Files.createTempDirectory is not available on JDK 6.\n                File dir = File.createTempFile(\"remote_sync_\", \"_\" + android.os.Process.myPid(), context.getFilesDir());\n                if (!dir.delete()) {\n                    throw new IllegalStateException(String.format(Locale.US,\n                            \"Temp file '%s' cannot be deleted.\", dir.getPath()));\n                }\n                if (!dir.mkdir()) {\n                    throw new IllegalStateException(String.format(Locale.US,\n                            \"Directory '%s' for SyncManager cannot be created. \",\n                            dir.getPath()));\n                }\n                syncDir = dir.getPath();\n            } catch (IOException e) {\n                throw new IllegalStateException(e);\n            }\n        } else {\n            syncDir = config.getSyncRootDirectory().getPath();\n        }\n        return syncDir;\n    }\n\n    private String getAppInfo(AppConfiguration config) {\n        // Create app UserAgent string\n        String appDefinedUserAgent = \"Unknown\";\n        try {\n            String appName = config.getAppName();\n            String appVersion = config.getAppVersion();\n            if (!Util.isEmptyString(appName) || !Util.isEmptyString(appVersion)) {\n                StringBuilder sb = new StringBuilder();\n                sb.append(Util.isEmptyString(appName) ? \"Undefined\" : appName);\n                sb.append('/');\n                sb.append(Util.isEmptyString(appName) ? \"Undefined\" : appVersion);\n                appDefinedUserAgent = sb.toString();\n            }\n        } catch (Exception e) {\n            // Failures to construct the user agent should never cause the system itself to crash.\n            RealmLog.warn(\"Constructing Binding User-Agent description failed.\", e);\n        }\n        return appDefinedUserAgent;\n    }\n\n    private String getBindingInfo() {\n        // Setup Realm part of User-Agent string\n        String userAgentBindingInfo = \"Unknown\"; // Fallback in case of anything going wrong\n        try {\n            StringBuilder sb = new StringBuilder();\n            sb.append(\"RealmJava/\");\n            sb.append(BuildConfig.VERSION_NAME);\n            sb.append(\" (\");\n            sb.append(Util.isEmptyString(Build.DEVICE) ? \"unknown-device\" : Build.DEVICE);\n            sb.append(\", \");\n            sb.append(Util.isEmptyString(Build.MODEL) ? \"unknown-model\" : Build.MODEL);\n            sb.append(\", v\");\n            sb.append(Build.VERSION.SDK_INT);\n            sb.append(\")\");\n            userAgentBindingInfo = sb.toString();\n        } catch (Exception e) {\n            // Failures to construct the user agent should never cause the system itself to crash.\n            RealmLog.warn(\"Constructing User-Agent description failed.\", e);\n        }\n        return userAgentBindingInfo;\n    }\n\n    /**\n     * Returns the current user that is logged in and still valid.\n     * <p>\n     * A user is invalidated when he/she logs out or the user's refresh token expires or is revoked.\n     * <p>\n     * If two or more users are logged in, it is the last valid user that is returned by this method.\n     *\n     * @return current {@link User} that has logged in and is still valid. {@code null} if no\n     * user is logged in or the user has expired.\n     */\n    @Nullable\n    public User currentUser() {\n        OsSyncUser osSyncUser = osApp.currentUser();\n        return (osSyncUser != null) ? new User(osSyncUser, this) : null;\n    }\n\n    /**\n     * Returns all known users that are either {@link User.State#LOGGED_IN} or\n     * {@link User.State#LOGGED_OUT}.\n     * <p>\n     * Only users that at some point logged into this device will be returned.\n     *\n     * @return a map of user identifiers and users known locally.\n     */\n    public Map<String, User> allUsers() {\n        OsSyncUser[] allUsers = osApp.allUsers();\n\n        HashMap<String, User> users = new HashMap<>(allUsers.length);\n        for (int i = 0; i < allUsers.length; i++) {\n            User user = new User(allUsers[i], this);\n            users.put(user.getId(), user);\n        }\n        return users;\n    }\n\n    /**\n     * Switch current user.\n     * <p>\n     * The current user is the user returned by {@link #currentUser()}.\n     *\n     * @param user the new current user.\n     * @throws IllegalArgumentException if the user is is not {@link User.State#LOGGED_IN}.\n     */\n    public User switchUser(User user) {\n        Util.checkNull(user, \"user\");\n        osApp.switchUser(user.osUser);\n\n        return user;\n    }\n\n    /**\n     * Removes a users credentials from this device. If the user was currently logged in, they\n     * will be logged out as part of the process. This is only a local change and does not\n     * affect the user state on the server.\n     *\n     * @param user to remove\n     * @return user that was removed.\n     * @throws AppException if called from the UI thread or if the user was logged in, but\n     *                      could not be logged out.\n     */\n    public User removeUser(User user) throws AppException {\n        return user.remove();\n    }\n\n    /**\n     * Removes a user's credentials from this device. If the user was currently logged in, they\n     * will be logged out as part of the process. This is only a local change and does not\n     * affect the user state on the server.\n     *\n     * @param user to remove\n     * @param callback callback when removing the user has completed or failed. The callback will always\n     *                 happen on the same thread as this method is called on.\n     * @throws IllegalStateException if called from a non-looper thread.\n     */\n    RealmAsyncTask removeAsync(User user, App.Callback<User> callback) {\n        return user.removeAsync(callback);\n    }\n\n    /**\n     * Logs in as a user with the given credentials associated with an authentication provider.\n     * <p>\n     * The user who logs in becomes the current user. Other App functionality acts on behalf of\n     * the current user.\n     * <p>\n     * If there was already a current user, that user is still logged in and can be found in the\n     * list returned by {@link #allUsers()}.\n     * <p>\n     * It is also possible to switch between which user is considered the current user by using\n     * {@link #switchUser(User)}.\n     *\n     * @param credentials the credentials representing the type of login.\n     * @return a {@link User} representing the logged in user.\n     * @throws AppException if the user could not be logged in.\n     */\n    public User login(Credentials credentials) throws AppException {\n        Util.checkNull(credentials, \"credentials\");\n\n        OsSyncUser osSyncUser = osApp.login(credentials.osCredentials);\n        User user = new User(osSyncUser, this);\n\n        notifyUserLoggedIn(user);\n        return user;\n    }\n\n    private void notifyUserLoggedIn(User user) {\n        mainHandler.post(new Runnable() {\n            @Override\n            public void run() {\n                for (AuthenticationListener listener : authListeners) {\n                    listener.loggedIn(user);\n                }\n            }\n        });\n    }\n\n    void notifyUserLoggedOut(User user) {\n        mainHandler.post(new Runnable() {\n            @Override\n            public void run() {\n                for (AuthenticationListener listener : authListeners) {\n                    listener.loggedOut(user);\n                }\n            }\n        });\n    }\n\n    /**\n     * Logs in as a user with the given credentials associated with an authentication provider.\n     * <p>\n     * The user who logs in becomes the current user. Other App functionality acts on behalf of\n     * the current user.\n     * <p>\n     * If there was already a current user, that user is still logged in and can be found in the\n     * list returned by {@link #allUsers()}.\n     * <p>\n     * It is also possible to switch between which user is considered the current user by using\n     * {@link #switchUser(User)}.\n     *\n     * @param credentials the credentials representing the type of login.\n     * @param callback    callback when logging in has completed or failed. The callback will always\n     *                    happen on the same thread as this method is called on.\n     * @throws IllegalStateException if not called on a looper thread.\n     */\n    public RealmAsyncTask loginAsync(Credentials credentials, Callback<User> callback) {\n        Util.checkLooperThread(\"Asynchronous log in is only possible from looper threads.\");\n        return new Request<User>(NETWORK_POOL_EXECUTOR, callback) {\n            @Override\n            public User run() throws AppException {\n                return login(credentials);\n            }\n        }.start();\n    }\n\n    /**\n     * Returns a wrapper for interacting with functionality related to users either being created or\n     * logged in using the {@link Credentials.Provider#EMAIL_PASSWORD} identity provider.\n     *\n     * @return wrapper for interacting with the {@link Credentials.Provider#EMAIL_PASSWORD} identity provider.\n     */\n    public EmailPasswordAuth getEmailPassword() {\n        return emailAuthProvider;\n    }\n\n    /**\n     * Sets a global authentication listener that will be notified about User events like\n     * login and logout.\n     * <p>\n     * Callbacks to authentication listeners will happen on the UI thread.\n     *\n     * @param listener listener to register.\n     * @throws IllegalArgumentException if {@code listener} is {@code null}.\n     */\n    public void addAuthenticationListener(AuthenticationListener listener) {\n        //noinspection ConstantConditions\n        if (listener == null) {\n            throw new IllegalArgumentException(\"Non-null 'listener' required.\");\n        }\n        authListeners.add(listener);\n    }\n\n    /**\n     * Removes the provided global authentication listener.\n     *\n     * @param listener listener to remove.\n     */\n    public void removeAuthenticationListener(AuthenticationListener listener) {\n        //noinspection ConstantConditions\n        if (listener == null) {\n            return;\n        }\n        authListeners.remove(listener);\n    }\n\n    /**\n     * Returns the <i>Sync</i> instance managing the ongoing <i>Realm Sync</i> sessions\n     * synchronizing data between the local and the remote <i>Realm App</i> associated with this app.\n     *\n     * @return the <i>Sync</i> instance associated with this <i>App</i>.\n     */\n    public Sync getSync() {\n        return syncManager;\n    }\n\n    /**\n     * Returns a <i>Functions</i> manager for invoking the Realm App's Realm Functions.\n     * <p>\n     * This will use the app's default codec registry to encode and decode arguments and results.\n     *\n     * @see Functions\n     * @see AppConfiguration#getDefaultCodecRegistry()\n     */\n    public Functions getFunctions(User user) {\n        return new FunctionsImpl(user);\n    }\n\n    /**\n     * Returns a <i>Functions</i> manager for invoking the Realm App's Realm Functions with a custom\n     * codec registry for encoding and decoding arguments and results.\n     *\n     * @see Functions\n     */\n    public Functions getFunctions(User user, CodecRegistry codecRegistry) {\n        return new FunctionsImpl(user, codecRegistry);\n    }\n\n    /**\n     * Returns the configuration object for this app.\n     *\n     * @return the configuration for this app.\n     */\n    public AppConfiguration getConfiguration() {\n        return config;\n    }\n\n    /**\n     * Exposed for testing.\n     * <p>\n     * Swap the currently configured network transport with the provided one.\n     * This should only be done if no network requests are currently running.\n     */\n    protected void setNetworkTransport(OsJavaNetworkTransport transport) {\n        osApp.setNetworkTransport(transport);\n    }\n\n    /**\n     * Two Apps are considered equal and will share their underlying state if they both refer\n     * to the same {@link AppConfiguration#getAppId()}.\n     */\n    @Override\n    public boolean equals(Object o) {\n        if (this == o) return true;\n        if (o == null || getClass() != o.getClass()) return false;\n\n        App app = (App) o;\n\n        if (!osApp.equals(app.osApp)) return false;\n        return config.equals(app.config);\n    }\n\n    @Override\n    public int hashCode() {\n        int result = osApp.hashCode();\n        result = 31 * result + config.hashCode();\n        return result;\n    }\n\n    /**\n     * Result class representing the result of an async request from this app towards MongoDB Realm.\n     *\n     * @param <T> Type returned if the request was a success.\n     * @see Callback\n     */\n    public static class Result<T> {\n        private T result;\n        private AppException error;\n\n        private Result(@Nullable T result, @Nullable AppException exception) {\n            this.result = result;\n            this.error = exception;\n        }\n\n        /**\n         * Creates a successful request result with no return value.\n         */\n        public static <T> Result<T> success() {\n            return new Result(null, null);\n        }\n\n        /**\n         * Creates a successful request result with a return value.\n         *\n         * @param result the result value.\n         */\n        public static <T> Result<T> withResult(T result) {\n            return new Result<>(result, null);\n        }\n\n        /**\n         * Creates a failed request result. The request failed for some reason, either because there\n         * was a network error or the Realm Object Server returned an error.\n         *\n         * @param exception error that occurred.\n         */\n        public static <T> Result<T> withError(AppException exception) {\n            return new Result<>(null, exception);\n        }\n\n        /**\n         * Returns whether or not request was successful\n         *\n         * @return {@code true} if the request was a success, {@code false} if not.\n         */\n        public boolean isSuccess() {\n            return error == null;\n        }\n\n        /**\n         * Returns the response in case the request was a success.\n         *\n         * @return the response value in case of a successful request.\n         */\n        public T get() {\n            return result;\n        }\n\n        /**\n         * Returns the response if the request was a success. If it failed, the default value is\n         * returned instead.\n         *\n         * @return the response value in case of a successful request. If the request failed, the\n         * default value is returned instead.\n         */\n        public T getOrDefault(T defaultValue) {\n            return isSuccess() ? result : defaultValue;\n        }\n\n        /**\n         * If the request was successful the response is returned, otherwise the provided error\n         * is thrown.\n         *\n         * @return the response object in case the request was a success.\n         * @throws AppException provided error in case the request failed.\n         */\n        public T getOrThrow() {\n            if (isSuccess()) {\n                return result;\n            } else {\n                throw error;\n            }\n        }\n\n        /**\n         * Returns the error in case of a failed request.\n         *\n         * @return the {@link AppException} in case of a failed request.\n         */\n        public AppException getError() {\n            return error;\n        }\n    }\n\n    /**\n     * Callback for async methods available to the {@link App}.\n     *\n     * @param <T> Type returned if the request was a success.\n     */\n    public interface Callback<T> {\n        /**\n         * Returns the result of the request when available.\n         *\n         * @param result the request response.\n         */\n        void onResult(Result<T> result);\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/objectServer/java/io/realm/mongodb/AppConfiguration.java",
    "content": "/*\n * Copyright 2020 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 */\npackage io.realm.mongodb;\n\nimport android.content.Context;\n\nimport org.bson.codecs.BsonValueCodecProvider;\nimport org.bson.codecs.DocumentCodecProvider;\nimport org.bson.codecs.IterableCodecProvider;\nimport org.bson.codecs.MapCodecProvider;\nimport org.bson.codecs.ValueCodecProvider;\nimport org.bson.codecs.configuration.CodecRegistries;\nimport org.bson.codecs.configuration.CodecRegistry;\n\nimport java.io.File;\nimport java.net.MalformedURLException;\nimport java.net.URL;\nimport java.util.Arrays;\nimport java.util.Collections;\nimport java.util.HashMap;\nimport java.util.Locale;\nimport java.util.Map;\nimport java.util.concurrent.TimeUnit;\n\nimport javax.annotation.Nonnull;\nimport javax.annotation.Nullable;\nimport javax.annotation.ParametersAreNonnullByDefault;\n\nimport io.realm.Realm;\nimport io.realm.annotations.Beta;\nimport io.realm.internal.Util;\nimport io.realm.internal.log.obfuscator.ApiKeyObfuscator;\nimport io.realm.internal.log.obfuscator.CustomFunctionObfuscator;\nimport io.realm.internal.log.obfuscator.EmailPasswordObfuscator;\nimport io.realm.internal.log.obfuscator.RegexPatternObfuscator;\nimport io.realm.internal.log.obfuscator.TokenObfuscator;\nimport io.realm.log.RealmLog;\nimport io.realm.mongodb.log.obfuscator.HttpLogObfuscator;\nimport io.realm.mongodb.sync.RecoverOrDiscardUnsyncedChangesStrategy;\nimport io.realm.mongodb.sync.RecoverUnsyncedChangesStrategy;\nimport io.realm.mongodb.sync.ClientResetRequiredError;\nimport io.realm.mongodb.sync.DiscardUnsyncedChangesStrategy;\nimport io.realm.mongodb.sync.ManuallyRecoverUnsyncedChangesStrategy;\nimport io.realm.mongodb.sync.SyncClientResetStrategy;\nimport io.realm.mongodb.sync.SyncSession;\n\nimport static io.realm.internal.network.LoggingInterceptor.LOGIN_FEATURE;\n\n/**\n * A AppConfiguration is used to setup a MongoDB Realm application.\n * <p>\n * Instances of a AppConfiguration can only created by using the\n * {@link AppConfiguration.Builder} and calling its\n * {@link AppConfiguration.Builder#build()} method.\n * <p>\n * Configuring a App is only required if the default settings are not enough. Otherwise calling\n * {@code new App(\"app-id\")} is sufficient.\n */\n@Beta\npublic class AppConfiguration {\n\n    /**\n     * The default url for MongoDB Realm applications.\n     *\n     * @see Builder#baseUrl(String)\n     */\n    public static final String DEFAULT_BASE_URL = \"https://realm.mongodb.com\";\n\n    /**\n     * The default request timeout for network requests towards MongoDB Realm in seconds.\n     *\n     * @see Builder#requestTimeout(long, TimeUnit)\n     */\n    public static final long DEFAULT_REQUEST_TIMEOUT = 60;\n\n    /**\n     * The default header name used to carry authorization data when making network requests\n     * towards MongoDB Realm.\n     */\n    public static final String DEFAULT_AUTHORIZATION_HEADER_NAME = \"Authorization\";\n\n    /**\n     * Default BSON codec registry for encoding/decoding arguments and results to/from MongoDB Realm backend.\n     * <p>\n     * This will encode/decode most primitive types, list and map types and BsonValues.\n     *\n     * @see AppConfiguration#getDefaultCodecRegistry()\n     * @see AppConfiguration.Builder#codecRegistry(CodecRegistry)\n     * @see ValueCodecProvider\n     * @see BsonValueCodecProvider\n     * @see IterableCodecProvider\n     * @see MapCodecProvider\n     * @see DocumentCodecProvider\n     */\n    public static final CodecRegistry DEFAULT_BSON_CODEC_REGISTRY = CodecRegistries.fromRegistries(\n            CodecRegistries.fromProviders(\n                    // For primitive support\n                    new ValueCodecProvider(),\n                    // For BSONValue support\n                    new BsonValueCodecProvider(),\n                    new DocumentCodecProvider(),\n                    // For list support\n                    new IterableCodecProvider(),\n                    new MapCodecProvider()\n            )\n    );\n\n    /**\n     * Default obfuscators for login requests used in a MongoDB Realm app.\n     * <p>\n     * This map is needed to instantiate the default {@link HttpLogObfuscator}, which will keep all\n     * login-sensitive information from being shown in Logcat.\n     * <p>\n     * This map's keys represent the different login identity providers which can be used to\n     * authenticate against an app and the values are the concrete obfuscators used for that\n     * provider.\n     *\n     * @see Credentials.Provider\n     * @see RegexPatternObfuscator\n     * @see ApiKeyObfuscator\n     * @see TokenObfuscator\n     * @see CustomFunctionObfuscator\n     * @see EmailPasswordObfuscator\n     * @see HttpLogObfuscator\n     */\n    public static final Map<String, RegexPatternObfuscator> loginObfuscators = getLoginObfuscators();\n\n    private final String appId;\n    private final String appName;\n    private final String appVersion;\n    private final URL baseUrl;\n    private final SyncSession.ErrorHandler defaultErrorHandler;\n    private final SyncClientResetStrategy defaultSyncClientResetStrategy;\n    @Nullable\n    private final byte[] encryptionKey;\n    private final long requestTimeoutMs;\n    private final String authorizationHeaderName;\n    private final Map<String, String> customHeaders;\n    private final File syncRootDir; // Root directory for storing Sync related files\n    private final CodecRegistry codecRegistry;\n    @Nullable\n    private final HttpLogObfuscator httpLogObfuscator;\n\n    private AppConfiguration(String appId,\n                             String appName,\n                             String appVersion,\n                             URL baseUrl,\n                             SyncSession.ErrorHandler defaultErrorHandler,\n                             SyncClientResetStrategy defaultSyncClientResetStrategy,\n                             @Nullable byte[] encryptionKey,\n                             long requestTimeoutMs,\n                             String authorizationHeaderName,\n                             Map<String, String> customHeaders,\n                             File syncRootdir,\n                             CodecRegistry codecRegistry,\n                             @Nullable HttpLogObfuscator httpLogObfuscator) {\n        this.appId = appId;\n        this.appName = appName;\n        this.appVersion = appVersion;\n        this.baseUrl = baseUrl;\n        this.defaultErrorHandler = defaultErrorHandler;\n        this.defaultSyncClientResetStrategy = defaultSyncClientResetStrategy;\n        this.encryptionKey = (encryptionKey == null) ? null : Arrays.copyOf(encryptionKey, encryptionKey.length);\n        this.requestTimeoutMs = requestTimeoutMs;\n        this.authorizationHeaderName = (!Util.isEmptyString(authorizationHeaderName)) ? authorizationHeaderName : \"Authorization\";\n        this.customHeaders = Collections.unmodifiableMap(customHeaders);\n        this.syncRootDir = syncRootdir;\n        this.codecRegistry = codecRegistry;\n        this.httpLogObfuscator = httpLogObfuscator;\n    }\n\n    /**\n     * Returns the unique app id that identities the Realm application.\n     *\n     * @return the app unique identifier.\n     */\n    public String getAppId() {\n        return appId;\n    }\n\n    /**\n     * Returns the name used to describe the Realm application. This is only used as debug\n     * information.\n     *\n     * @return the app name.\n     */\n    @Nullable\n    public String getAppName() {\n        return appName;\n    }\n\n    /**\n     * Returns the version of this Realm application. This is only used as debug information.\n     *\n     * @return the app version.\n     */\n    @Nullable\n    public String getAppVersion() {\n        return appVersion;\n    }\n\n    /**\n     * Returns the base url for this Realm application.\n     *\n     * @return the app base url.\n     */\n    public URL getBaseUrl() {\n        return baseUrl;\n    }\n\n    /**\n     * Returns the encryption key, if any, that is used to encrypt Realm users meta data on this\n     * device. If no key is returned, the data is not encrypted.\n     *\n     * @return the encryption key if exists, or {@code null} otherwise.\n     */\n    @Nullable\n    public byte[] getEncryptionKey() {\n        return encryptionKey == null ? null : Arrays.copyOf(encryptionKey, encryptionKey.length);\n    }\n\n    /**\n     * Returns the default timeout for network requests against the Realm application in\n     * milliseconds.\n     *\n     * @return the default timeout for network requests in milliseconds.\n     */\n    public long getRequestTimeoutMs() {\n        return requestTimeoutMs;\n    }\n\n    /**\n     * Returns the name of the header used to carry authentication data when making network\n     * requests towards MongoDB Realm.\n     *\n     * @return the authentication header name.\n     */\n    public String getAuthorizationHeaderName() {\n        return authorizationHeaderName;\n    }\n\n    /**\n     * Returns any custom configured headers that will be sent alongside other headers when\n     * making network requests towards MongoDB Realm.\n     *\n     * @return a {@code Map} of custom configured headers.\n     */\n    public Map<String, String> getCustomRequestHeaders() {\n        return customHeaders;\n    }\n\n    /**\n     * Returns the default error handler used by synced Realms if there are problems with their\n     * {@link SyncSession}.\n     *\n     * @return the app default error handler.\n     */\n    public SyncSession.ErrorHandler getDefaultErrorHandler() {\n        return defaultErrorHandler;\n    }\n\n    /**\n     * Returns the default Client Reset handler used by synced Realms if there are problems with their\n     * {@link SyncSession}.\n     *\n     * @return the app default error handler.\n     *\n     * @deprecated replaced by {@link #getDefaultSyncClientResetStrategy()}\n     */\n    @Deprecated\n    public SyncSession.ClientResetHandler getDefaultClientResetHandler() {\n        try {\n            return (SyncSession.ClientResetHandler) defaultSyncClientResetStrategy;\n        } catch (ClassCastException exception) {\n            throw new ClassCastException(exception.getMessage() + \": getDefaultClientResetHandler() \" +\n                    \"is deprecated and has been replaced by getDefaultSyncClientResetStrategy()\");\n        }\n    }\n\n    /**\n     * Returns the default sync client reset strategy used by synced Realms if there are problems with their\n     * {@link SyncSession}.\n     *\n     * @return the app default error handler.\n     */\n    public SyncClientResetStrategy getDefaultSyncClientResetStrategy() {\n        return defaultSyncClientResetStrategy;\n    }\n\n    /**\n     * Returns the root folder containing all files and Realms used when synchronizing data\n     * between the device and MongoDB Realm.\n     *\n     * @return the sync root directory.\n     */\n    public File getSyncRootDirectory() {\n        return syncRootDir;\n    }\n\n    /**\n     * Returns the default codec registry used to encode and decode BSON arguments and results when\n     * calling remote Realm {@link io.realm.mongodb.functions.Functions} and accessing a remote\n     * {@link io.realm.mongodb.mongo.MongoDatabase}.\n     *\n     * @return The default codec registry for the App.\n     * @see #DEFAULT_BSON_CODEC_REGISTRY\n     * @see Builder#getDefaultCodecRegistry()\n     */\n    public CodecRegistry getDefaultCodecRegistry() {\n        return codecRegistry;\n    }\n\n    /**\n     * Returns the {@link HttpLogObfuscator} used in the app, which keeps sensitive information in\n     * HTTP requests from being displayed in the logcat.\n     *\n     * @return the HTTP log obfuscator.\n     */\n    @Nullable\n    public HttpLogObfuscator getHttpLogObfuscator() {\n        return httpLogObfuscator;\n    }\n\n    @Override\n    public boolean equals(Object o) {\n        if (this == o) return true;\n        if (o == null || getClass() != o.getClass()) return false;\n\n        AppConfiguration that = (AppConfiguration) o;\n\n        if (requestTimeoutMs != that.requestTimeoutMs) return false;\n        if (!appId.equals(that.appId)) return false;\n        if (appName != null ? !appName.equals(that.appName) : that.appName != null) return false;\n        if (appVersion != null ? !appVersion.equals(that.appVersion) : that.appVersion != null)\n            return false;\n        if (!baseUrl.toString().equals(that.baseUrl.toString())) return false;\n        if (!defaultErrorHandler.equals(that.defaultErrorHandler)) return false;\n        if (!Arrays.equals(encryptionKey, that.encryptionKey)) return false;\n        if (!authorizationHeaderName.equals(that.authorizationHeaderName)) return false;\n        if (!customHeaders.equals(that.customHeaders)) return false;\n        if (!syncRootDir.equals(that.syncRootDir)) return false;\n        if (!codecRegistry.equals(that.codecRegistry)) return false;\n        return httpLogObfuscator != null ? httpLogObfuscator.equals(that.httpLogObfuscator) : that.httpLogObfuscator == null;\n    }\n\n    @Override\n    public int hashCode() {\n        int result = appId.hashCode();\n        result = 31 * result + (appName != null ? appName.hashCode() : 0);\n        result = 31 * result + (appVersion != null ? appVersion.hashCode() : 0);\n        result = 31 * result + baseUrl.toString().hashCode();\n        result = 31 * result + defaultErrorHandler.hashCode();\n        result = 31 * result + Arrays.hashCode(encryptionKey);\n        result = 31 * result + (int) (requestTimeoutMs ^ (requestTimeoutMs >>> 32));\n        result = 31 * result + authorizationHeaderName.hashCode();\n        result = 31 * result + customHeaders.hashCode();\n        result = 31 * result + syncRootDir.hashCode();\n        result = 31 * result + codecRegistry.hashCode();\n        result = 31 * result + (httpLogObfuscator != null ? httpLogObfuscator.hashCode() : 0);\n        return result;\n    }\n\n    private static Map<String, RegexPatternObfuscator> getLoginObfuscators() {\n        final HashMap<String, RegexPatternObfuscator> obfuscators = new HashMap<>();\n        obfuscators.put(Credentials.Provider.API_KEY.getId(), ApiKeyObfuscator.obfuscator());\n        obfuscators.put(Credentials.Provider.APPLE.getId(), TokenObfuscator.obfuscator());\n        obfuscators.put(Credentials.Provider.CUSTOM_FUNCTION.getId(), CustomFunctionObfuscator.obfuscator());\n        obfuscators.put(Credentials.Provider.EMAIL_PASSWORD.getId(), EmailPasswordObfuscator.obfuscator());\n        obfuscators.put(Credentials.Provider.FACEBOOK.getId(), TokenObfuscator.obfuscator());\n        obfuscators.put(Credentials.Provider.GOOGLE.getId(), TokenObfuscator.obfuscator());\n        obfuscators.put(Credentials.Provider.JWT.getId(), TokenObfuscator.obfuscator());\n        return obfuscators;\n    }\n\n    /**\n     * Builder used to construct instances of a {@link AppConfiguration} in a fluent manner.\n     */\n    public static class Builder {\n\n        private String appId;\n        private String appName;\n        private String appVersion;\n        private URL baseUrl = createUrl(DEFAULT_BASE_URL);\n        private SyncSession.ErrorHandler defaultErrorHandler = new SyncSession.ErrorHandler() {\n            @Override\n            public void onError(SyncSession session, AppException error) {\n                String errorMsg = String.format(Locale.US, \"Session Error[%s]: %s\",\n                        session.getConfiguration().getServerUrl(),\n                        error.toString());\n                switch (error.getErrorCode().getCategory()) {\n                    case FATAL:\n                        RealmLog.error(errorMsg);\n                        break;\n                    case RECOVERABLE:\n                        RealmLog.info(errorMsg);\n                        break;\n                    default:\n                        throw new IllegalArgumentException(\"Unsupported error category: \" + error.getErrorCode().getCategory());\n                }\n            }\n        };\n        private SyncClientResetStrategy defaultSyncClientResetStrategy = new RecoverOrDiscardUnsyncedChangesStrategy() {\n            @Override\n            public void onBeforeReset(Realm realm) {\n                RealmLog.debug(\"Client reset: attempting to automatically recover unsynced changes in Realm: \" + realm.getPath());\n            }\n\n            @Override\n            public void onAfterRecovery(Realm before, Realm after) {\n                RealmLog.debug(\"Client reset: successful recovered all unsynced changes in Realm: \" + after.getPath());\n            }\n\n            @Override\n            public void onAfterDiscard(Realm before, Realm after) {\n                RealmLog.debug(\"Client reset: couldn't recover successfully, all unsynced changes were discarded in Realm\" + after.getPath());\n            }\n\n            @Override\n            public void onManualResetFallback(SyncSession session, ClientResetRequiredError error) {\n                RealmLog.fatal(\"Client reset: manual reset required\" + session.getConfiguration().getServerUrl());\n            }\n        };\n        private byte[] encryptionKey;\n        private long requestTimeoutMs = TimeUnit.MILLISECONDS.convert(DEFAULT_REQUEST_TIMEOUT, TimeUnit.SECONDS);\n        private String authorizationHeaderName;\n        private Map<String, String> customHeaders = new HashMap<>();\n        private File syncRootDir;\n        private CodecRegistry codecRegistry = DEFAULT_BSON_CODEC_REGISTRY;\n        @Nullable\n        private HttpLogObfuscator httpLogObfuscator = new HttpLogObfuscator(LOGIN_FEATURE, loginObfuscators);\n\n        /**\n         * Creates an instance of the Builder for the AppConfiguration.\n         *\n         * @param appId the application id of the MongoDB Realm Application.\n         */\n        public Builder(String appId) {\n            Util.checkEmpty(appId, \"appId\");\n            this.appId = appId;\n            Context context = Realm.getApplicationContext();\n            if (context == null) {\n                throw new IllegalStateException(\"Call `Realm.init(Context)` before calling this method.\");\n            }\n        }\n\n        /**\n         * Sets the encryption key used to encrypt user meta data only. Individual Realms needs to\n         * use {@link io.realm.mongodb.sync.SyncConfiguration.Builder#encryptionKey(byte[])} to make them encrypted.\n         *\n         * @param key a 64 byte encryption key.\n         * @throws IllegalArgumentException if the key is not 64 bytes long.\n         */\n        public Builder encryptionKey(@ParametersAreNonnullByDefault byte[] key) {\n            Util.checkNull(key, \"key\");\n            if (key.length != Realm.ENCRYPTION_KEY_LENGTH) {\n                throw new IllegalArgumentException(String.format(Locale.US,\n                        \"The provided key must be %s bytes. Yours was: %s\",\n                        Realm.ENCRYPTION_KEY_LENGTH, key.length));\n            }\n            this.encryptionKey = Arrays.copyOf(key, key.length);\n            return this;\n        }\n\n        /**\n         * Sets the base url for the MongoDB Realm Application. The default value is\n         * {@link #DEFAULT_BASE_URL}.\n         *\n         * @param baseUrl the base url for the MongoDB Realm application.\n         */\n        public Builder baseUrl(String baseUrl) {\n            Util.checkNull(baseUrl, \"baseUrl\");\n            this.baseUrl = createUrl(baseUrl);\n            return this;\n        }\n\n        /**\n         * Sets the apps name. This is only used as part of debug headers sent when making\n         * network requests at the MongoDB Realm application.\n         *\n         * @param appName app name used to identify the application.\n         */\n        public Builder appName(String appName) {\n            Util.checkEmpty(appName, \"appName\");\n            this.appName = appName;\n            return this;\n        }\n\n        /**\n         * Sets the apps version. This is only used as part of debug headers sent when making\n         * network requests at the MongoDB Realm application.\n         *\n         * @param appVersion app version used to identify the application.\n         */\n        public Builder appVersion(String appVersion) {\n            Util.checkEmpty(appVersion, \"appVersion\");\n            this.appVersion = appVersion;\n            return this;\n        }\n\n        /**\n         * Sets the default timeout used by network requests against the MongoDB Realm application.\n         * Requests will terminate with a failure if they exceed this limit. The default value is\n         * {@link AppConfiguration#DEFAULT_REQUEST_TIMEOUT} seconds.\n         *\n         * @param time the timeout value for network requests.\n         * @param unit the unit of time used to define the timeout.\n         */\n        public Builder requestTimeout(long time, TimeUnit unit) {\n            if (time < 1) {\n                throw new IllegalArgumentException(\"A timeout above 0 is required: \" + time);\n            }\n            Util.checkNull(unit, \"unit\");\n            this.requestTimeoutMs = TimeUnit.MILLISECONDS.convert(time, unit);\n            return this;\n        }\n\n        /**\n         * Sets the name of the HTTP header used to send authorization data in when making requests to\n         * MongoDB Realm. The MongoDB server or firewall must have been configured to expect a\n         * custom authorization header.\n         * <p>\n         * The default authorization header is named {@link #DEFAULT_AUTHORIZATION_HEADER_NAME}.\n         *\n         * @param headerName name of the header.\n         * @throws IllegalArgumentException if a null or empty header is provided.\n         */\n        public Builder authorizationHeaderName(String headerName) {\n            Util.checkEmpty(headerName, \"headerName\");\n            this.authorizationHeaderName = headerName;\n            return this;\n        }\n\n        /**\n         * Adds an extra HTTP header to append to every request to a Realm Object Server.\n         *\n         * @param headerName the name of the header.\n         * @param headerValue the value of header.\n         * @throws IllegalArgumentException if a non-empty {@code headerName} is provided or a null {@code headerValue}.\n         */\n        public Builder addCustomRequestHeader(String headerName, String headerValue) {\n            Util.checkEmpty(headerName, \"headerName\");\n            Util.checkNull(headerValue, \"headerValue\");\n            customHeaders.put(headerName, headerValue);\n            return this;\n        }\n\n        /**\n         * Adds extra HTTP headers to append to every request to a Realm Object Server.\n         *\n         * @param headers map of (headerName, headerValue) pairs.\n         * @throws IllegalArgumentException If any of the headers provided are illegal.\n         */\n        public Builder addCustomRequestHeaders(@Nullable Map<String, String> headers) {\n            if (headers != null) {\n                customHeaders.putAll(headers);\n            }\n            return this;\n        }\n\n        /**\n         * Sets the default error handler used by Synced Realms when reporting errors with their\n         * session.\n         * <p>\n         * This default can be overridden by calling\n         * {@link io.realm.mongodb.sync.SyncConfiguration.Builder#errorHandler(SyncSession.ErrorHandler)} when creating\n         * the {@link io.realm.mongodb.sync.SyncConfiguration}.\n         *\n         * @param errorHandler the default error handler.\n         */\n        public Builder defaultSyncErrorHandler(SyncSession.ErrorHandler errorHandler) {\n            Util.checkNull(errorHandler, \"errorHandler\");\n            defaultErrorHandler = errorHandler;\n            return this;\n        }\n\n        /**\n         * Sets the default Client Reset handler used by Synced Realms when they report a Client Reset.\n         * <p>\n         * This default can be overridden by calling\n         * {@link io.realm.mongodb.sync.SyncConfiguration.Builder#clientResetHandler(SyncSession.ClientResetHandler)} when creating\n         * the {@link io.realm.mongodb.sync.SyncConfiguration}.\n         *\n         * @param handler the default Client Reset handler.\n         *                \n         * @deprecated replaced by {@link #defaultSyncClientResetStrategy(ManuallyRecoverUnsyncedChangesStrategy)}\n         */\n        @Deprecated\n        public Builder defaultClientResetHandler(SyncSession.ClientResetHandler handler) {\n            Util.checkNull(handler, \"handler\");\n            defaultSyncClientResetStrategy = handler;\n            return this;\n        }\n\n        /**\n         * Sets the default sync client reset strategy used by Synced Realms when they report a Client Reset.\n         * <p>\n         * This default can be overridden by calling\n         * {@link io.realm.mongodb.sync.SyncConfiguration.Builder#syncClientResetStrategy(ManuallyRecoverUnsyncedChangesStrategy)}\n         * or {@link io.realm.mongodb.sync.SyncConfiguration.Builder#syncClientResetStrategy(DiscardUnsyncedChangesStrategy)}\n         * or {@link io.realm.mongodb.sync.SyncConfiguration.Builder#syncClientResetStrategy(RecoverUnsyncedChangesStrategy)}\n         * or {@link io.realm.mongodb.sync.SyncConfiguration.Builder#syncClientResetStrategy(RecoverOrDiscardUnsyncedChangesStrategy)}\n         * when creating the {@link io.realm.mongodb.sync.SyncConfiguration}.\n         *\n         * @param strategy the default sync client reset strategy.\n         */\n        public Builder defaultSyncClientResetStrategy(@Nonnull ManuallyRecoverUnsyncedChangesStrategy strategy) {\n            Util.checkNull(strategy, \"strategy\");\n            defaultSyncClientResetStrategy = strategy;\n            return this;\n        }\n\n        /**\n         * Sets the default sync client reset strategy used by Synced Realms when they report a Client Reset.\n         * <p>\n         * This default can be overridden by calling\n         * {@link io.realm.mongodb.sync.SyncConfiguration.Builder#syncClientResetStrategy(ManuallyRecoverUnsyncedChangesStrategy)}\n         * or {@link io.realm.mongodb.sync.SyncConfiguration.Builder#syncClientResetStrategy(DiscardUnsyncedChangesStrategy)}\n         * or {@link io.realm.mongodb.sync.SyncConfiguration.Builder#syncClientResetStrategy(RecoverUnsyncedChangesStrategy)}\n         * or {@link io.realm.mongodb.sync.SyncConfiguration.Builder#syncClientResetStrategy(RecoverOrDiscardUnsyncedChangesStrategy)}\n         * when creating the {@link io.realm.mongodb.sync.SyncConfiguration}.\n         *\n         * @param strategy the default sync client reset strategy.\n         */\n        public Builder defaultSyncClientResetStrategy(@Nonnull DiscardUnsyncedChangesStrategy strategy) {\n            Util.checkNull(strategy, \"strategy\");\n            defaultSyncClientResetStrategy = strategy;\n            return this;\n        }\n\n        /**\n         * Sets the default sync client reset strategy used by Synced Realms when they report a Client Reset.\n         * <p>\n         * This default can be overridden by calling\n         * {@link io.realm.mongodb.sync.SyncConfiguration.Builder#syncClientResetStrategy(ManuallyRecoverUnsyncedChangesStrategy)}\n         * or {@link io.realm.mongodb.sync.SyncConfiguration.Builder#syncClientResetStrategy(DiscardUnsyncedChangesStrategy)}\n         * or {@link io.realm.mongodb.sync.SyncConfiguration.Builder#syncClientResetStrategy(RecoverUnsyncedChangesStrategy)}\n         * or {@link io.realm.mongodb.sync.SyncConfiguration.Builder#syncClientResetStrategy(RecoverOrDiscardUnsyncedChangesStrategy)}\n         * when creating the {@link io.realm.mongodb.sync.SyncConfiguration}.\n         *\n         * @param strategy the default sync client reset strategy.\n         */\n        public Builder defaultSyncClientResetStrategy(@Nonnull RecoverUnsyncedChangesStrategy strategy) {\n            Util.checkNull(strategy, \"strategy\");\n            defaultSyncClientResetStrategy = strategy;\n            return this;\n        }\n\n        /**\n         * Sets the default sync client reset strategy used by Synced Realms when they report a Client Reset.\n         * <p>\n         * This default can be overridden by calling\n         * {@link io.realm.mongodb.sync.SyncConfiguration.Builder#syncClientResetStrategy(ManuallyRecoverUnsyncedChangesStrategy)}\n         * or {@link io.realm.mongodb.sync.SyncConfiguration.Builder#syncClientResetStrategy(DiscardUnsyncedChangesStrategy)}\n         * or {@link io.realm.mongodb.sync.SyncConfiguration.Builder#syncClientResetStrategy(RecoverUnsyncedChangesStrategy)}\n         * or {@link io.realm.mongodb.sync.SyncConfiguration.Builder#syncClientResetStrategy(RecoverOrDiscardUnsyncedChangesStrategy)}\n         * when creating the {@link io.realm.mongodb.sync.SyncConfiguration}.\n         *\n         * @param strategy the default sync client reset strategy.\n         */\n        public Builder defaultSyncClientResetStrategy(@Nonnull RecoverOrDiscardUnsyncedChangesStrategy strategy) {\n            Util.checkNull(strategy, \"strategy\");\n            defaultSyncClientResetStrategy = strategy;\n            return this;\n        }\n\n        /**\n         * Configures the root folder containing all files and Realms used when synchronizing data\n         * between the device and MongoDB Realm.\n         * <p>\n         * The default root dir is {@code Context.getFilesDir()/mongodb-realm}.\n         *\n         * @param rootDir where to store sync related files.\n         */\n        public Builder syncRootDirectory(File rootDir) {\n            Util.checkNull(rootDir, \"rootDir\");\n            if (rootDir.isFile()) {\n                throw new IllegalArgumentException(\"'rootDir' is a file, not a directory: \" +\n                        rootDir.getAbsolutePath() + \".\");\n            }\n            if (!rootDir.exists() && !rootDir.mkdirs()) {\n                throw new IllegalArgumentException(\"Could not create the specified directory: \" +\n                        rootDir.getAbsolutePath() + \".\");\n            }\n            if (!rootDir.canWrite()) {\n                throw new IllegalArgumentException(\"Realm directory is not writable: \" +\n                        rootDir.getAbsolutePath() + \".\");\n            }\n            syncRootDir = rootDir;\n            return this;\n        }\n\n        private URL createUrl(String baseUrl) {\n            try {\n                return new URL(baseUrl);\n            } catch (MalformedURLException e) {\n                throw new IllegalArgumentException(baseUrl);\n            }\n        }\n\n        /**\n         * Set the default codec registry used to encode and decode BSON arguments and results when\n         * calling remote Realm {@link io.realm.mongodb.functions.Functions} and accessing a remote\n         * {@link io.realm.mongodb.mongo.MongoDatabase}.\n         * <p>\n         * Will default to {@link #DEFAULT_BSON_CODEC_REGISTRY} if not specified.\n         *\n         * @param codecRegistry The default codec registry for the App.\n         * @see #DEFAULT_BSON_CODEC_REGISTRY\n         * @see Builder#getDefaultCodecRegistry()\n         */\n        public Builder codecRegistry(CodecRegistry codecRegistry) {\n            Util.checkNull(codecRegistry, \"codecRegistry\");\n            this.codecRegistry = codecRegistry;\n            return this;\n        }\n\n        /**\n         * Sets the {@link HttpLogObfuscator} used to keep sensitive information in HTTP requests\n         * from being displayed in the logcat.\n         * <p>\n         * If left unspecified, it will default to obfuscating HTTP login requests.\n         *\n         * @param httpLogObfuscator the default HTTP log obfuscator for the app.\n         */\n        public Builder httpLogObfuscator(@Nullable HttpLogObfuscator httpLogObfuscator) {\n            this.httpLogObfuscator = httpLogObfuscator;\n            return this;\n        }\n\n        /**\n         * Creates the AppConfiguration.\n         *\n         * @return the AppConfiguration that can be used to create a {@link App}.\n         */\n        public AppConfiguration build() {\n            // Initialize default sync root if none has been defined.\n            if (syncRootDir == null) {\n                syncRootDir = Realm.getApplicationContext().getFilesDir();\n            }\n\n            return new AppConfiguration(appId,\n                    appName,\n                    appVersion,\n                    baseUrl,\n                    defaultErrorHandler,\n                    defaultSyncClientResetStrategy,\n                    encryptionKey,\n                    requestTimeoutMs,\n                    authorizationHeaderName,\n                    customHeaders,\n                    syncRootDir,\n                    codecRegistry,\n                    httpLogObfuscator);\n        }\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/objectServer/java/io/realm/mongodb/AppException.java",
    "content": "/*\n * Copyright 2020 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\npackage io.realm.mongodb;\n\nimport javax.annotation.Nullable;\n\nimport io.realm.annotations.Beta;\nimport io.realm.internal.Keep;\nimport io.realm.internal.Util;\nimport io.realm.mongodb.sync.SyncSession;\n\n/**\n * This class is a wrapper for all errors happening when communicating with a MongoDB Realm app.\n * This include both exceptions and protocol errors.\n *\n * Only {@link #getErrorCode()} is guaranteed to contain a value. If the error was caused by an underlying exception\n * {@link #getErrorMessage()} is {@code null} and {@link #getException()} is set, while if the error was a protocol error\n * {@link #getErrorMessage()} is set and {@link #getException()} is null.\n *\n * @see ErrorCode for a list of possible errors.\n */\n@Beta\n@Keep\npublic class AppException extends RuntimeException {\n\n    // The Java representation of the error.\n    private final ErrorCode error;\n\n    // The native error representation. Mostly relevant for ErrorCode.UNKNOWN\n    // where it can provide more details into the exact error.\n    private final String nativeErrorType;\n    private final int nativeErrorIntValue;\n\n    private final String errorMessage;\n    private final Throwable exception;\n\n    /**\n     * Create an error caused by an error in the protocol when communicating with the Object Server.\n     *\n     * @param errorCode error code for this type of error.\n     * @param errorMessage detailed error message.\n     */\n    public AppException(ErrorCode errorCode, String errorMessage) {\n        this(errorCode, errorCode.getType(), errorCode.intValue(), errorMessage, (Throwable) null);\n    }\n\n    /**\n     * Creates an unknown error that could not be mapped to any known error case.\n     * <p>\n     * This means that {@link #getErrorCode()} will return {@link ErrorCode#UNKNOWN}, but\n     * {@link #getErrorType()} and {@link #getErrorIntValue()} will return the underlying values\n     * which can help identify the real error.\n     *\n     * @param errorCode error code for this type of error.\n     * @param errorMessage detailed error message.\n     */\n    public AppException(String errorType, int errorCode, String errorMessage) {\n        this(ErrorCode.UNKNOWN, errorType, errorCode, errorMessage, null);\n    }\n\n    /**\n     * Create an error caused by an an exception when communicating with the Object Server.\n     *\n     * @param errorCode error code for this type of error.\n     * @param exception underlying exception causing this error.\n     */\n    public AppException(ErrorCode errorCode, Throwable exception) {\n        this(errorCode, null, exception);\n    }\n\n    /**\n     * Errors happening while trying to authenticate a user.\n     *\n     * @param errorCode error code for this type of error.\n     * @param title title for this type of error.\n     * @param hint a hint for resolving the error.\n     */\n    public AppException(ErrorCode errorCode, String title, @Nullable String hint) {\n        this(errorCode, (hint != null) ? title + \" : \" + hint : title, (Throwable) null);\n    }\n\n    /**\n     * Generic error happening that could happen anywhere.\n     *\n     * @param errorCode error code for this type of error.\n     * @param errorMessage detailed error message.\n     * @param exception underlying exception if the error was caused by this.\n     */\n    public AppException(ErrorCode errorCode, @Nullable String errorMessage, @Nullable Throwable exception) {\n        this(errorCode, errorCode.getType(), errorCode.intValue(), errorMessage, exception);\n    }\n\n    public AppException(ErrorCode errorCode, String nativeErrorType, int nativeErrorCode,\n                        @Nullable String errorMessage, @Nullable Throwable exception) {\n        super(errorMessage);\n        this.error = errorCode;\n        this.nativeErrorType = nativeErrorType;\n        this.nativeErrorIntValue = nativeErrorCode;\n        this.errorMessage = errorMessage;\n        this.exception = exception;\n    }\n\n    /**\n     * Returns the {@link ErrorCode} identifying the type of error.\n     * <p>\n     * If {@link ErrorCode#UNKNOWN} is returned, it means that the error could not be mapped to any\n     * known errors. In that case {@link #getErrorType()} and {@link #getErrorIntValue()} will\n     * return the underlying error information which can better identify the type of error.\n     *\n     * @return the error code identifying the type of error.\n     * @see ErrorCode\n     */\n    public ErrorCode getErrorCode() {\n        return error;\n    }\n\n    /**\n     * Returns a string describing the type of error it is.\n     *\n     * @return\n     */\n    public String getErrorType() {\n        return nativeErrorType;\n    }\n\n    /**\n     * Returns an integer representing this specific type of error. This value is only unique within\n     * the value provided by {@link #getErrorType()}.\n     *\n     * @return the integer value representing this type of error.\n     */\n    public int getErrorIntValue() {\n        return nativeErrorIntValue;\n    }\n\n    /**\n     * Returns a more detailed error message about the cause of this error.\n     *\n     * @return a detailed error message or {@code null} if one was not available.\n     */\n    @Nullable\n    public String getErrorMessage() {\n        return errorMessage;\n    }\n\n    /**\n     * Returns the underlying exception causing this error, if any.\n     *\n     * @return the underlying exception causing this error, or {@code null} if not caused by an exception.\n     */\n    @Nullable\n    public Throwable getException() {\n        return exception;\n    }\n\n    /**\n     * Returns the {@link ErrorCode.Category} category for this error.\n     * Errors that are {@link ErrorCode.Category#RECOVERABLE} mean that it is still possible for a\n     * given {@link SyncSession} to resume synchronization. {@link ErrorCode.Category#FATAL} errors\n     * means that session has stopped and cannot be recovered.\n     *\n     * @return the error category.\n     */\n    public ErrorCode.Category getCategory() {\n        return error.getCategory();\n    }\n\n    @Override\n    public String toString() {\n        StringBuilder sb = new StringBuilder();\n\n        sb.append(getErrorCode().name());\n        sb.append(\"(\");\n        sb.append(getErrorType());\n        sb.append(\":\");\n        sb.append(getErrorIntValue());\n        sb.append(')');\n        if (errorMessage != null) {\n            sb.append(\": \");\n            sb.append(errorMessage);\n        }\n        if (exception != null) {\n            sb.append('\\n');\n            sb.append(Util.getStackTrace(exception));\n        }\n        return sb.toString();\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/objectServer/java/io/realm/mongodb/AuthenticationListener.java",
    "content": "/*\n * Copyright 2020 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\npackage io.realm.mongodb;\n\nimport io.realm.annotations.Beta;\n\n/**\n * Interface describing events related to Users and their authentication\n */\n@Beta\npublic interface AuthenticationListener {\n    /**\n     * A user was logged into the Object Server\n     *\n     * @param user {@link User} that is now logged in.\n     */\n    void loggedIn(User user);\n\n    /**\n     * A user was successfully logged out from the Object Server.\n     *\n     * @param user {@link User} that was successfully logged out.\n     */\n    void loggedOut(User user);\n}\n"
  },
  {
    "path": "realm/realm-library/src/objectServer/java/io/realm/mongodb/Credentials.java",
    "content": "/*\n * Copyright 2020 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\npackage io.realm.mongodb;\n\nimport org.bson.Document;\n\nimport io.realm.annotations.Beta;\nimport io.realm.internal.Util;\nimport io.realm.internal.objectstore.OsAppCredentials;\nimport io.realm.mongodb.auth.EmailPasswordAuth;\nimport io.realm.mongodb.auth.GoogleAuthType;\n\n\n/**\n * Credentials represent a login with a given login provider, and are used by the MongoDB Realm to\n * verify the user and grant access. The {@link Provider#EMAIL_PASSWORD} provider is enabled\n * by default. All other providers must be enabled on MongoDB Realm to work.\n * <p>\n * Note that users wanting to login using Email/Password must register first using\n * {@link EmailPasswordAuth#registerUser(String, String)}.\n * </p>\n * Credentials are used the following way:\n * <pre>\n * {@code\n * // Example\n * App app = new App(\"app-id\");\n * Credentials credentials = Credentials.emailPassword(\"email\", \"password\");\n * User user = app.loginAsync(credentials, new App.Callback&lt;User&gt;() {\n *   \\@Override\n *   public void onResult(Result&lt;User&gt; result) {\n *     if (result.isSuccess() {\n *       handleLogin(result.get());\n *     } else {\n *       handleError(result.getError());\n *     }\n *   }\n * ));\n * }\n * }\n * </pre>\n *\n * @see <a href=\"https://docs.mongodb.com/realm/authentication/providers/\">Authentication Providers</a>\n */\n@Beta\npublic class Credentials {\n\n    OsAppCredentials osCredentials;\n\n    private final Provider identityProvider;\n\n    /**\n     * Creates credentials representing an anonymous user.\n     * <p>\n     * Logging the user out again means that data is lost with no means of recovery\n     * and it isn't possible to share the user details across devices.\n     * <p>\n     * The anonymous user must be linked to another real user to preserve data after a log out.\n     *\n     * @return a set of credentials that can be used to log into MongoDB Realm using\n     * {@link App#loginAsync(Credentials, App.Callback)}.\n     */\n    public static Credentials anonymous() {\n        return new Credentials(OsAppCredentials.anonymous(), Provider.ANONYMOUS);\n    }\n\n    /**\n     * Creates credentials representing a login using a user API key.\n     * <p>\n     * This provider must be enabled on MongoDB Realm to work.\n     *\n     * @param key the API key to use for login.\n     * @return a set of credentials that can be used to log into MongoDB Realm using\n     * {@link App#loginAsync(Credentials, App.Callback)}.\n     */\n    public static Credentials apiKey(String key) {\n        Util.checkEmpty(key, \"key\");\n        return new Credentials(OsAppCredentials.apiKey(key), Provider.API_KEY);\n    }\n\n    /**\n     * Creates credentials representing a login using an Apple ID token.\n     * <p>\n     * This provider must be enabled on MongoDB Realm to work.\n     *\n     * @param idToken the ID token generated when using your Apple login.\n     * @return a set of credentials that can be used to log into MongoDB Realm using\n     * {@link App#loginAsync(Credentials, App.Callback)}.\n     */\n    public static Credentials apple(String idToken) {\n        Util.checkEmpty(idToken, \"idToken\");\n        return new Credentials(OsAppCredentials.apple(idToken), Provider.APPLE);\n    }\n\n    /**\n     * Creates credentials representing a remote function from MongoDB Realm using a\n     * {@link Document} which will be parsed as an argument to the remote function, so the keys must\n     * match the format and names the function expects.\n     * <p>\n     * This provider must be enabled on MongoDB Realm to work.\n     *\n     * @param arguments document containing the function arguments.\n     * @return a set of credentials that can be used to log into MongoDB Realm using\n     * {@link App#loginAsync(Credentials, App.Callback)}.\n     */\n    public static Credentials customFunction(Document arguments) {\n        Util.checkNull(arguments, \"arguments\");\n        return new Credentials(OsAppCredentials.customFunction(arguments),\n                Provider.CUSTOM_FUNCTION);\n    }\n\n    /**\n     * Creates credentials representing a login using email and password.\n     *\n     * @param email    email of the user logging in.\n     * @param password password of the user logging in.\n     * @return a set of credentials that can be used to log into MongoDB Realm using\n     * {@link App#loginAsync(Credentials, App.Callback)}.\n     */\n    public static Credentials emailPassword(String email, String password) {\n        Util.checkEmpty(email, \"email\");\n        Util.checkEmpty(password, \"password\");\n        return new Credentials(OsAppCredentials.emailPassword(email, password),\n                Provider.EMAIL_PASSWORD);\n    }\n\n    /**\n     * Creates credentials representing a login using a Facebook access token.\n     * <p>\n     * This provider must be enabled on MongoDB Realm to work.\n     *\n     * @param accessToken the access token returned when logging in to Facebook.\n     * @return a set of credentials that can be used to log into MongoDB Realm using\n     * {@link App#loginAsync(Credentials, App.Callback)}.\n     */\n    public static Credentials facebook(String accessToken) {\n        Util.checkEmpty(accessToken, \"accessToken\");\n        return new Credentials(OsAppCredentials.facebook(accessToken), Provider.FACEBOOK);\n    }\n\n    /**\n     * Creates credentials representing a login using a Google access token of a given {@link GoogleAuthType}.\n     * <p>\n     * This provider must be enabled on MongoDB Realm to work.\n     *\n     * @param token the access token returned when logging in to Google.\n     * @param type the access token type\n     * @return a set of credentials that can be used to log into MongoDB Realm using\n     * {@link App#loginAsync(Credentials, App.Callback)}.\n     */\n    public static Credentials google(String token, GoogleAuthType type) {\n        Util.checkEmpty(token, \"token\");\n        return new Credentials(OsAppCredentials.google(token, type), Provider.GOOGLE);\n    }\n\n    /**\n     * Creates credentials representing a login using a {@link GoogleAuthType#AUTH_CODE} Google access token.\n     * <p>\n     * This provider must be enabled on MongoDB Realm to work.\n     *\n     * @param authorizationCode the authorization code returned when logging in to Google.\n     * @return a set of credentials that can be used to log into MongoDB Realm using\n     * {@link App#loginAsync(Credentials, App.Callback)}.\n     * @deprecated Use {@link Credentials#google(String, GoogleAuthType)} instead.\n     */\n    @Deprecated\n    public static Credentials google(String authorizationCode) {\n        return google(authorizationCode, GoogleAuthType.AUTH_CODE);\n    }\n\n    /**\n     * Creates credentials representing a login using a JWT Token. This token is normally generated\n     * after a custom OAuth2 login flow.\n     * <p>\n     * This provider must be enabled on MongoDB Realm to work.\n     *\n     * @param jwtToken the jwt token returned after a custom login to a another service.\n     * @return a set of credentials that can be used to log into MongoDB Realm using\n     * {@link App#loginAsync(Credentials, App.Callback)}.\n     */\n    public static Credentials jwt(String jwtToken) {\n        Util.checkEmpty(jwtToken, \"jwtToken\");\n        return new Credentials(OsAppCredentials.jwt(jwtToken), Provider.JWT);\n    }\n\n    /**\n     * Returns the identity provider used to authenticate with.\n     *\n     * @return the provider identifying the chosen credentials.\n     */\n    public Provider getIdentityProvider() {\n        String nativeProvider = osCredentials.getProvider();\n        String id = identityProvider.getId();\n\n        // Sanity check - ensure nothing changed in the OS\n        if (nativeProvider.equals(id)) {\n            return identityProvider;\n        } else {\n            throw new AssertionError(\"The provider from the Object Store differs from the one in Realm.\");\n        }\n    }\n\n    /**\n     * Returns the credentials object serialized as a json string.\n     *\n     * @return a json serialized string of the credentials object.\n     */\n    public String asJson() {\n        return osCredentials.asJson();\n    }\n\n    private Credentials(OsAppCredentials credentials, Provider identityProvider) {\n        this.osCredentials = credentials;\n        this.identityProvider = identityProvider;\n    }\n\n    /**\n     * This enum contains the list of identity providers supported by MongoDB Realm.\n     * All of these except {@link #EMAIL_PASSWORD} must be enabled manually on MongoDB Realm to\n     * work.\n     *\n     * @see <a href=\"https://docs.mongodb.com/realm/authentication/providers/\">Authentication Providers</a>\n     */\n    public enum Provider {\n        ANONYMOUS(\"anon-user\"),\n        API_KEY(\"api-key\"),    // same value as API_KEY as per OS specifications\n        APPLE(\"oauth2-apple\"),\n        CUSTOM_FUNCTION(\"custom-function\"),\n        EMAIL_PASSWORD(\"local-userpass\"),\n        FACEBOOK(\"oauth2-facebook\"),\n        GOOGLE(\"oauth2-google\"),\n        JWT(\"jwt\"),\n        UNKNOWN(\"\");\n\n        /**\n         * Create the identity provider from the ID string returned by MongoDB Realm.\n         *\n         * @param id the string identifier for the provider\n         * @return the enum representing the provider or {@link #UNKNOWN} if no matching provider\n         * was found.\n         */\n        public static Provider fromId(String id) {\n            for (Provider value : values()) {\n                if (value.getId().equals(id)) {\n                    return value;\n                }\n            }\n            return UNKNOWN;\n        }\n\n        private final String id;\n\n        Provider(String id) {\n            this.id = id;\n        }\n\n        /**\n         * Return the string presentation of this identity provider.\n         */\n        public String getId() {\n            return id;\n        }\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/objectServer/java/io/realm/mongodb/EmailPasswordAuthImpl.java",
    "content": "/*\n * Copyright 2020 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\npackage io.realm.mongodb;\n\nimport io.realm.annotations.Beta;\nimport io.realm.internal.objectstore.OsJavaNetworkTransport;\nimport io.realm.mongodb.auth.EmailPasswordAuth;\n\n@Beta\nclass EmailPasswordAuthImpl extends EmailPasswordAuth {\n\n    EmailPasswordAuthImpl(App app) {\n        super(app);\n    }\n\n    @Override\n    protected void call(int functionType, OsJavaNetworkTransport.NetworkTransportJNIResultCallback callback, String... args) {\n        nativeCallFunction(functionType, app.osApp.getNativePtr(), callback, args);\n    }\n\n    private static native void nativeCallFunction(int functionType,\n                                                  long appNativePtr,\n                                                  OsJavaNetworkTransport.NetworkTransportJNIResultCallback callback,\n                                                  String... args);\n\n}\n"
  },
  {
    "path": "realm/realm-library/src/objectServer/java/io/realm/mongodb/ErrorCode.java",
    "content": "/*\n * Copyright 2020 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\npackage io.realm.mongodb;\n\n\nimport java.util.Locale;\n\nimport io.realm.internal.Keep;\nimport io.realm.internal.objectstore.OsJavaNetworkTransport;\nimport io.realm.log.RealmLog;\nimport io.realm.mongodb.sync.SyncConfiguration;\n\n/**\n * This class enumerate all potential errors related to using the Object Server or synchronizing data.\n */\n@Keep\npublic enum ErrorCode {\n    // See https://github.com/realm/realm-core/blob/master/src/realm/sync/client_base.hpp#L73\n    // See https://github.com/realm/realm-core/blob/master/src/realm/sync/protocol.hpp\n    // See https://github.com/realm/realm-core/blob/master/src/realm/object-store/sync/generic_network_transport.hpp#L40\n\n    // Catch-all\n    // The underlying type and error code should be part of the error message\n    UNKNOWN(Type.UNKNOWN, -1),\n\n    //\n    // Custom SDK errors. Errors originating from Java\n    //\n\n    //Network Transport related errors originating from Java\n    NETWORK_IO_EXCEPTION(Type.JAVA, OsJavaNetworkTransport.ERROR_IO),\n    NETWORK_INTERRUPTED(Type.JAVA, OsJavaNetworkTransport.ERROR_INTERRUPTED),\n    NETWORK_UNKNOWN(Type.JAVA, OsJavaNetworkTransport.ERROR_UNKNOWN),\n\n    // BSON encoding/decoding errors originating from java\n    BSON_CODEC_NOT_FOUND(Type.JAVA, 1100),\n    BSON_ENCODING(Type.JAVA, 1101),\n    BSON_DECODING(Type.JAVA, 1102),\n\n    // Stream serializing errors originated from Java\n    EVENT_DESERIALIZING(Type.JAVA, 1200),\n\n    // Custom Object Store errors\n    CLIENT_RESET(Type.CUSTOM, 7),                   // Client Reset required. Don't change this value without modifying io_realm_internal_OsRealmConfig.cpp\n\n    // Sync errors\n    // Catch-all sync errors. The error code should be part of the error message.\n    RUNTIME_ERROR(Type.RUNTIME, 1000),\n    UNKNOWN_SYNC_ERROR(Type.SYNC, -1),\n    AUTOMATIC_CLIENT_RESET_FAILED(Type.SYNC, 1028),\n    BAD_CHANGESET(Type.SYNC, 1015),\n    BAD_SYNC_PARTITION_VALUE(Type.SYNC, 1029),\n    CONNECTION_CLOSED(Type.SYNC, 1030, Category.RECOVERABLE),\n    INVALID_SUBSCRIPTION_QUERY(Type.SYNC, 1031),\n    SYNC_CLIENT_RESET_REQUIRED(Type.SYNC, 1032),\n    SYNC_COMPENSATING_WRITE(Type.SYNC, 1033),\n    SYNC_CONNECT_FAILED(Type.SYNC, 1034),\n    SYNC_INVALID_SCHEMA_CHANGE(Type.SYNC, 1035),\n    SYNC_PERMISSION_DENIED(Type.SYNC, 1036),\n    SYNC_PROTOCOL_INVARIANT_FAILED(Type.SYNC, 1037),\n    SYNC_PROTOCOL_NEGOTIATION_FAILED(Type.SYNC, 1038),\n    SYNC_SERVER_PERMISSIONS_CHANGED(Type.SYNC, 1039),\n    SYNC_USER_MISMATCH(Type.SYNC, 1040),\n    TLS_HANDSHAKE_FAILED(Type.SYNC, 1041),\n    WRONG_SYNC_TYPE(Type.SYNC, 1042),\n    SYNC_WRITE_NOT_ALLOWED(Type.SYNC, 1043),\n    \n    //\n    // Type.Protocol\n    //\n    // Connection level and protocol errors from the native Sync Client\n    //\n    // See https://github.com/realm/realm-core/blob/master/src/realm/sync/protocol.hpp#L260\n    //\n    @Deprecated // Use RUNTIME_ERROR instead\n    OTHER_ERROR(Type.PROTOCOL, 101),                                          // Other connection level error\n    @Deprecated // Use SYNC_PROTOCOL_INVARIANT_FAILED instead\n    UNKNOWN_MESSAGE(Type.PROTOCOL, 102),                            // Unknown type of input message\n    @Deprecated // Use SYNC_PROTOCOL_INVARIANT_FAILED instead\n    BAD_SYNTAX(Type.PROTOCOL, 103),                                 // Bad syntax in input message head\n    @Deprecated // Is not used anymore\n    LIMITS_EXCEEDED(Type.PROTOCOL, 104),                            // Limits exceeded in input message\n    @Deprecated // Use SYNC_PROTOCOL_NEGOTIATION_FAILED instead\n    WRONG_PROTOCOL_VERSION(Type.PROTOCOL, 105),                     // Wrong protocol version (CLIENT)\n    @Deprecated // Use SYNC_PROTOCOL_INVARIANT_FAILED instead\n    BAD_SESSION_IDENT(Type.PROTOCOL, 106),                          // Bad session identifier in input message\n    @Deprecated // Use SYNC_PROTOCOL_INVARIANT_FAILED instead\n    REUSE_OF_SESSION_IDENT(Type.PROTOCOL, 107),                     // Overlapping reuse of session identifier (BIND)\n    @Deprecated // Use SYNC_PROTOCOL_INVARIANT_FAILED instead\n    BOUND_IN_OTHER_SESSION(Type.PROTOCOL, 108),                     // Client file bound in other session (IDENT)\n    @Deprecated // Use SYNC_PROTOCOL_INVARIANT_FAILED instead\n    BAD_MESSAGE_ORDER(Type.PROTOCOL, 109),                          // Bad input message order\n    @Deprecated // Use RUNTIME_ERROR instead\n    BAD_DECOMPRESSION(Type.PROTOCOL, 110),                                   // Error in decompression (UPLOAD)\n    @Deprecated // Use SYNC_PROTOCOL_INVARIANT_FAILED instead\n    BAD_CHANGESET_HEADER_SYNTAX(Type.PROTOCOL, 111),                // Bad server version in changeset header (DOWNLOAD)\n    @Deprecated // Use SYNC_PROTOCOL_INVARIANT_FAILED instead\n    BAD_CHANGESET_SIZE(Type.PROTOCOL, 112),                         // Bad size specified in changeset header (UPLOAD)\n    @Deprecated // Use BAD_CHANGESET instead\n    BAD_CHANGESETS(Type.PROTOCOL, 113),                             // Bad changesets (UPLOAD)\n\n    // Session level errors from the native Sync Client\n    @Deprecated // Use CONNECTION_CLOSED instead\n    SESSION_CLOSED(Type.SESSION, 200, Category.RECOVERABLE),      // Session closed (no error)\n    @Deprecated // Use RUNTIME_ERROR instead\n    OTHER_SESSION_ERROR(Type.SESSION, 201, Category.RECOVERABLE),           // Other session level error\n    @Deprecated // Not used anymore\n    TOKEN_EXPIRED(Type.SESSION, 202, Category.RECOVERABLE),       // Access token expired\n\n    // Session fatal: Auth wrong. Cannot be fixed without a new User/SyncConfiguration.\n    @Deprecated // Not used anymore\n    BAD_AUTHENTICATION(Type.SESSION, 203),                        // Bad user authentication (BIND, REFRESH)\n    @Deprecated // Use BAD_SYNC_PARTITION_VALUE instead\n    ILLEGAL_REALM_PATH(Type.SESSION, 204),                        // Illegal Realm path (BIND)\n    @Deprecated // Not used anymore\n    NO_SUCH_PATH(Type.SESSION, 205),                              // No such Realm (BIND)\n    @Deprecated // Use SYNC_PERMISSION_DENIED instead\n    PERMISSION_DENIED(Type.SESSION, 206),                         // Permission denied (BIND, REFRESH)\n\n    // Fatal: Wrong server/client versions. Trying to sync incompatible files or the file was corrupted.\n    @Deprecated // Not used anymore\n    BAD_SERVER_FILE_IDENT(Type.SESSION, 207),                     // Bad server file identifier (IDENT)\n    @Deprecated // Use SYNC_CLIENT_RESET_REQUIRED instead\n    BAD_CLIENT_FILE_IDENT(Type.SESSION, 208),                     // Bad client file identifier (IDENT)\n    @Deprecated // Use SYNC_CLIENT_RESET_REQUIRED instead\n    BAD_SERVER_VERSION(Type.SESSION, 209),                        // Bad server version (IDENT, UPLOAD)\n    @Deprecated // Use SYNC_CLIENT_RESET_REQUIRED instead\n    BAD_CLIENT_VERSION(Type.SESSION, 210),                        // Bad client version (IDENT, UPLOAD)\n    @Deprecated // Use SYNC_CLIENT_RESET_REQUIRED instead\n    DIVERGING_HISTORIES(Type.SESSION, 211),                       // Diverging histories (IDENT)\n    @Deprecated // Not used anymore\n    DISABLED_SESSION(Type.SESSION, 213),                                   // Disabled session\n    @Deprecated // Not used anymore\n    PARTIAL_SYNC_DISABLED(Type.SESSION, 214),                     // Partial sync disabled (BIND)\n    @Deprecated // Not used anymore\n    UNSUPPORTED_SESSION_FEATURE(Type.SESSION, 215),               // Unsupported session-level feature\n    @Deprecated // Use SYNC_PROTOCOL_INVARIANT_FAILED instead\n    BAD_ORIGIN_FILE_IDENT(Type.SESSION, 216),                     // Bad origin file identifier (UPLOAD)\n    @Deprecated // Use SYNC_CLIENT_RESET_REQUIRED instead\n    BAD_CLIENT_FILE(Type.SESSION, 217),                           // Synchronization no longer possible for client-side file\n    @Deprecated // Not used anymore\n    SERVER_FILE_DELETED(Type.SESSION, 218),                       // Server file was deleted while session was bound to it\n    @Deprecated // Not used anymore\n    CLIENT_FILE_BLACKLISTED(Type.SESSION, 219),                   // Client file has been blacklisted (IDENT)\n    @Deprecated // Not used anymore\n    USER_BLACKLISTED(Type.SESSION, 220),                          // User has been blacklisted (BIND)\n    @Deprecated // Not used anymore\n    TRANSACT_BEFORE_UPLOAD(Type.SESSION, 221),                    // Serialized transaction before upload completion\n    @Deprecated // Use SYNC_CLIENT_RESET_REQUIRED instead\n    CLIENT_FILE_EXPIRED(Type.SESSION, 222),                       // Client file has expired\n    @Deprecated // Use SYNC_USER_MISMATCH instead\n    USER_MISMATCH(Type.SESSION, 223),                             // User mismatch for client file identifier (IDENT)\n    @Deprecated // Not used anymore\n    TOO_MANY_SESSIONS(Type.SESSION, 224),                         // Too many sessions in connection (BIND)\n    @Deprecated // Use INVALID_SCHEMA_CHANGE instead\n    INVALID_SCHEMA_CHANGE(Type.SESSION, 225),                     // Invalid schema change (UPLOAD)\n    @Deprecated // Use INVALID_SUBSCRIPTION_QUERY instead\n    BAD_QUERY(Type.SESSION, 226),                                 // Client query is invalid/malformed (IDENT, QUERY)\n    @Deprecated // Use SYNC_SERVER_PERMISSIONS_CHANGED instead\n    SERVER_PERMISSIONS_CHANGED(Type.SESSION, 228),                // Server permissions for this file ident have changed since the last time it was used (IDENT)\n    @Deprecated // Use CONNECTION_CLOSED instead\n    INITIAL_SYNC_NOT_COMPLETE(Type.SESSION, 229),                 // Client tried to open a session before initial sync is complete (BIND)\n    @Deprecated // Use SYNC_WRITE_NOT_ALLOWED\n    WRITE_NOT_ALLOWED(Type.SESSION, 230),                         // Client attempted a write that is disallowed by permissions, or modifies an object outside the current query - requires client reset (UPLOAD)\n    @Deprecated // Use SYNC_COMPENSATING_WRITE instead\n    COMPENSATING_WRITE(Type.SESSION, 231),                        // Client attempted a write that is disallowed by permissions, or modifies an object outside the current query, and the server undid the change\n\n    //\n    // Type.Client\n    //\n    // Sync Network Client errors.\n    // See https://github.com/realm/realm-core/blob/master/src/realm/sync/client_base.hpp#L75\n    //\n    @Deprecated // Use CONNECTION_CLOSED instead\n    CLIENT_CONNECTION_CLOSED(Type.CLIENT, 100),            // Connection closed (no error)\n    @Deprecated // Use SYNC_PROTOCOL_INVARIANT_FAILED instead\n    CLIENT_UNKNOWN_MESSAGE(Type.CLIENT, 101),              // Unknown type of input message\n    @Deprecated // Not used anymore\n    CLIENT_LIMITS_EXCEEDED(Type.CLIENT, 103),              // Limits exceeded in input message\n    @Deprecated // Use SYNC_PROTOCOL_INVARIANT_FAILED instead\n    CLIENT_BAD_SESSION_IDENT(Type.CLIENT, 104),            // Bad session identifier in input message\n    @Deprecated // Use SYNC_PROTOCOL_INVARIANT_FAILED instead\n    CLIENT_BAD_MESSAGE_ORDER(Type.CLIENT, 105),            // Bad input message order\n    @Deprecated // Use SYNC_PROTOCOL_INVARIANT_FAILED instead\n    CLIENT_BAD_CLIENT_FILE_IDENT(Type.CLIENT, 106),        // Bad client file identifier (IDENT)\n    @Deprecated // Use SYNC_PROTOCOL_INVARIANT_FAILED instead\n    CLIENT_BAD_PROGRESS(Type.CLIENT, 107),                 // Bad progress information (DOWNLOAD)\n    @Deprecated // Use SYNC_PROTOCOL_INVARIANT_FAILED instead\n    CLIENT_BAD_CHANGESET_HEADER_SYNTAX(Type.CLIENT, 108),  // Bad syntax in changeset header (DOWNLOAD)\n    @Deprecated // Use SYNC_PROTOCOL_INVARIANT_FAILED instead\n    CLIENT_BAD_CHANGESET_SIZE(Type.CLIENT, 109),           // Bad changeset size in changeset header (DOWNLOAD)\n    @Deprecated // Use SYNC_PROTOCOL_INVARIANT_FAILED instead\n    CLIENT_BAD_ORIGIN_FILE_IDENT(Type.CLIENT, 110),        // Bad origin file identifier in changeset header (DOWNLOAD)\n    @Deprecated // Use CLIENT_RESET instead\n    CLIENT_BAD_SERVER_VERSION(Type.CLIENT, 111),           // Bad server version in changeset header (DOWNLOAD)\n    @Deprecated // Use BAD_CHANGESET instead\n    CLIENT_BAD_CHANGESET(Type.CLIENT, 112),                // Bad changeset (DOWNLOAD)\n    @Deprecated // Use UNKNOWN_SYNC_ERROR instead\n    CLIENT_BAD_REQUEST_IDENT(Type.CLIENT, 113),            // Bad request identifier (MARK)\n    @Deprecated // Use SYNC_PROTOCOL_INVARIANT_FAILED instead\n    CLIENT_BAD_ERROR_CODE(Type.CLIENT, 114),               // Bad error code (ERROR)\n    @Deprecated // Use UNKNOWN_SYNC_ERROR instead\n    CLIENT_BAD_COMPRESSION(Type.CLIENT, 115),              // Bad compression (DOWNLOAD)\n    @Deprecated // Not used anymore\n    CLIENT_BAD_CLIENT_VERSION_DOWNLOAD(Type.CLIENT, 116),  // Bad last integrated client version in changeset header (DOWNLOAD)\n    @Deprecated // Use TLS_HANDSHAKE_FAILED instead\n    CLIENT_SSL_SERVER_CERT_REJECTED(Type.CLIENT, 117),     // SSL server certificate rejected\n    @Deprecated // Use CONNECTION_CLOSED instead\n    CLIENT_PONG_TIMEOUT(Type.CLIENT, 118),                 // Timeout on reception of PONG respone message\n    @Deprecated // Use UNKNOWN_SYNC_ERROR instead\n    CLIENT_BAD_CLIENT_FILE_IDENT_SALT(Type.CLIENT, 119),   // Bad client file identifier salt (IDENT)\n    @Deprecated // Use UNKNOWN_SYNC_ERROR instead\n    CLIENT_FILE_IDENT(Type.CLIENT, 120),                   // Bad file identifier (ALLOC)\n    @Deprecated // Use UNKNOWN_SYNC_ERROR instead\n    CLIENT_CONNECT_TIMEOUT(Type.CLIENT, 121),              // Sync connection was not fully established in time\n    @Deprecated // Use UNKNOWN_SYNC_ERROR instead\n    CLIENT_BAD_TIMESTAMP(Type.CLIENT, 122),                // Bad timestamp (PONG)\n    @Deprecated // Use SYNC_PROTOCOL_NEGOTIATION_FAILED instead\n    CLIENT_BAD_PROTOCOL_FROM_SERVER(Type.CLIENT, 123),     // Bad or missing protocol version information from server\n    @Deprecated // Use SYNC_PROTOCOL_NEGOTIATION_FAILED instead\n    CLIENT_TOO_OLD_FOR_SERVER(Type.CLIENT, 124),           // Protocol version negotiation failed: Client is too old for server\n    @Deprecated // Use SYNC_PROTOCOL_NEGOTIATION_FAILED instead\n    CLIENT_TOO_NEW_FOR_SERVER(Type.CLIENT, 125),           // Protocol version negotiation failed: Client is too new for server\n    @Deprecated // Use SYNC_PROTOCOL_NEGOTIATION_FAILED instead\n    CLIENT_PROTOCOL_MISMATCH(Type.CLIENT, 126),            // Protocol version negotiation failed: No version supported by both client and server\n    @Deprecated // Use UNKNOWN_SYNC_ERROR instead\n    CLIENT_BAD_STATE_MESSAGE(Type.CLIENT, 127),            // Bad values in state message (STATE)\n    @Deprecated // Use UNKNOWN_SYNC_ERROR instead\n    CLIENT_MISSING_PROTOCOL_FEATURE(Type.CLIENT, 128),     // Requested feature missing in negotiated protocol version\n    @Deprecated // Use UNKNOWN_SYNC_ERROR instead\n    CLIENT_BAD_SERIAL_TRANSACT_STATUS(Type.CLIENT, 129),   // Bad status of serialized transaction (TRANSACT)\n    @Deprecated // Use UNKNOWN_SYNC_ERROR instead\n    CLIENT_BAD_OBJECT_ID_SUBSTITUTIONS(Type.CLIENT, 130),  // Bad encoded object identifier substitutions (TRANSACT)\n    @Deprecated // Use UNKNOWN_SYNC_ERROR instead\n    CLIENT_HTTP_TUNNEL_FAILED(Type.CLIENT, 131),           // Failed to establish HTTP tunnel with configured proxy\n    @Deprecated // Use AUTOMATIC_CLIENT_RESET_FAILED instead\n    AUTO_CLIENT_RESET_FAILURE(Type.CLIENT, 132),           // Automatic client reset failed\n\n    //\n    // Type.HTTP\n    //\n    // 300 - 599 Reserved for Standard HTTP error codes\n    //\n    MULTIPLE_CHOICES(Type.HTTP, 300),\n    MOVED_PERMANENTLY(Type.HTTP, 301),\n    FOUND(Type.HTTP, 302),\n    SEE_OTHER(Type.HTTP, 303),\n    NOT_MODIFIED(Type.HTTP, 304),\n    USE_PROXY(Type.HTTP, 305),\n    TEMPORARY_REDIRECT(Type.HTTP, 307),\n    PERMANENT_REDIRECT(Type.HTTP, 308),\n    HTTP_BAD_REQUEST(Type.HTTP, 400),\n    UNAUTHORIZED(Type.HTTP, 401),\n    PAYMENT_REQUIRED(Type.HTTP, 402),\n    FORBIDDEN(Type.HTTP, 403),\n    NOT_FOUND(Type.HTTP, 404),\n    METHOD_NOT_ALLOWED(Type.HTTP, 405),\n    NOT_ACCEPTABLE(Type.HTTP, 406),\n    PROXY_AUTHENTICATION_REQUIRED(Type.HTTP, 407),\n    REQUEST_TIMEOUT(Type.HTTP, 408),\n    CONFLICT(Type.HTTP, 409),\n    GONE(Type.HTTP, 410),\n    LENGTH_REQUIRED(Type.HTTP, 411),\n    PRECONDITION_FAILED(Type.HTTP, 412),\n    PAYLOAD_TOO_LARGE(Type.HTTP, 413),\n    URI_TOO_LONG(Type.HTTP, 414),\n    UNSUPPORTED_MEDIA_TYPE(Type.HTTP, 415),\n    RANGE_NOT_SATISFIABLE(Type.HTTP, 416),\n    EXPECTATION_FAILED(Type.HTTP, 417),\n    MISDIRECTED_REQUEST(Type.HTTP, 421),\n    UNPROCESSABLE_ENTITY(Type.HTTP, 422),\n    LOCKED(Type.HTTP, 423),\n    FAILED_DEPENDENCY(Type.HTTP, 424),\n    UPGRADE_REQUIRED(Type.HTTP, 426),\n    PRECONDITION_REQUIRED(Type.HTTP, 428),\n    TOO_MANY_REQUESTS(Type.HTTP, 429),\n    REQUEST_HEADER_FIELDS_TOO_LARGE(Type.HTTP, 431),\n    UNAVAILABLE_FOR_LEGAL_REASONS(Type.HTTP, 451),\n    INTERNAL_SERVER_ERROR(Type.HTTP, 500),\n    NOT_IMPLEMENTED(Type.HTTP, 501),\n    BAD_GATEWAY(Type.HTTP, 502),\n    SERVICE_UNAVAILABLE(Type.HTTP, 503),\n    GATEWAY_TIMEOUT(Type.HTTP, 504),\n    HTTP_VERSION_NOT_SUPPORTED(Type.HTTP, 505),\n    VARIANT_ALSO_NEGOTIATES(Type.HTTP, 506),\n    INSUFFICIENT_STORAGE(Type.HTTP, 507),\n    LOOP_DETECTED(Type.HTTP, 508),\n    NOT_EXTENDED(Type.HTTP, 510),\n    NETWORK_AUTHENTICATION_REQUIRED(Type.HTTP, 511),\n\n    ///\n    // Type.SERVICE\n    //\n    // MongoDB Realm Service Response codes\n    //\n    // See https://github.com/realm/realm-core/blob/master/src/realm/sync/error_codes.hpp#L75\n    // See https://github.com/realm/realm-core/blob/master/src/realm/sync/error_codes.cpp#L29\n    //\n    CLIENT_USER_NOT_FOUND(Type.APP, 4100),\n    CLIENT_USER_NOT_LOGGED_IN(Type.APP, 4101),\n    CLIENT_APP_DEALLOCATED(Type.APP, 4102),\n    CLIENT_REDIRECT_ERROR(Type.APP, 4103),\n    CLIENT_TOO_MANY_REDIRECTS(Type.APP, 4104),\n    BAD_TOKEN(Type.JSON, 4200),\n    MALFORMED_JSON(Type.JSON, 4201),\n    MISSING_JSON_KEY(Type.JSON, 4202),\n    BAD_BSON_PARSE(Type.JSON, 4203),\n    MISSING_AUTH_REQ(Type.SERVICE, 4300),\n    INVALID_SESSION(Type.SERVICE, 4301),\n    USER_APP_DOMAIN_MISMATCH(Type.SERVICE, 4302),\n    DOMAIN_NOT_ALLOWED(Type.SERVICE, 4303),\n    READ_SIZE_LIMIT_EXCEEDED(Type.SERVICE, 4304),\n    INVALID_PARAMETER(Type.SERVICE, 4305),\n    MISSING_PARAMETER(Type.SERVICE, 4306),\n    TWILIO_ERROR(Type.SERVICE, 4307),\n    GCM_ERROR(Type.SERVICE, 4308),\n    HTTP_ERROR(Type.SERVICE, 4309),\n    AWS_ERROR(Type.SERVICE, 4310),\n    MONGODB_ERROR(Type.SERVICE, 4311),\n    ARGUMENTS_NOT_ALLOWED(Type.SERVICE, 4312),\n    FUNCTION_EXECUTION_ERROR(Type.SERVICE, 4313),\n    NO_MATCHING_RULE(Type.SERVICE, 4314),\n    SERVER_ERROR(Type.SERVICE, 4315),\n    AUTH_PROVIDER_NOT_FOUND(Type.SERVICE, 4316),\n    AUTH_PROVIDER_ALREADY_EXISTS(Type.SERVICE, 4317),\n    SERVICE_NOT_FOUND(Type.SERVICE, 4318),\n    SERVICE_TYPE_NOT_FOUND(Type.SERVICE, 4319),\n    SERVICE_ALREADY_EXISTS(Type.SERVICE, 4320),\n    SERVICE_COMMAND_NOT_FOUND(Type.SERVICE, 4321),\n    VALUE_NOT_FOUND(Type.SERVICE, 4322),\n    VALUE_ALREADY_EXISTS(Type.SERVICE, 4323),\n    VALUE_DUPLICATE_NAME(Type.SERVICE, 4324),\n    FUNCTION_NOT_FOUND(Type.SERVICE, 4325),\n    FUNCTION_ALREADY_EXISTS(Type.SERVICE, 4326),\n    FUNCTION_DUPLICATE_NAME(Type.SERVICE, 4327),\n    FUNCTION_SYNTAX_ERROR(Type.SERVICE, 4328),\n    FUNCTION_INVALID(Type.SERVICE, 4329),\n    INCOMING_WEBHOOK_NOT_FOUND(Type.SERVICE, 4330),\n    INCOMING_WEBHOOK_ALREADY_EXISTS(Type.SERVICE, 4331),\n    INCOMING_WEBHOOK_DUPLICATE_NAME(Type.SERVICE, 4332),\n    RULE_NOT_FOUND(Type.SERVICE, 4333),\n    API_KEY_NOT_FOUND(Type.SERVICE, 4334),\n    RULE_ALREADY_EXISTS(Type.SERVICE, 4335),\n    RULE_DUPLICATE_NAME(Type.SERVICE, 4336),\n    AUTH_PROVIDER_DUPLICATE_NAME(Type.SERVICE, 4337),\n    RESTRICTED_HOST(Type.SERVICE, 4338),\n    API_KEY_ALREADY_EXISTS(Type.SERVICE, 4339),\n    INCOMING_WEBHOOK_AUTH_FAILED(Type.SERVICE, 4340),\n    EXECUTION_TIME_LIMIT_EXCEEDED(Type.SERVICE, 4341),\n    NOT_CALLABLE(Type.SERVICE, 4342),\n    USER_ALREADY_CONFIRMED(Type.SERVICE, 4343),\n    USER_NOT_FOUND(Type.SERVICE, 4344),\n    USER_DISABLED(Type.SERVICE, 4345),\n    AUTH_ERROR(Type.SERVICE, 4346),\n    BAD_REQUEST(Type.SERVICE, 4347),\n    ACCOUNT_NAME_IN_USE(Type.SERVICE, 4348),\n    INVALID_EMAIL_PASSWORD(Type.SERVICE, 4349),\n    SCHEMA_VALIDATION_FAILED_WRITE(Type.SERVICE, 4350),\n    APP_UNKNOWN(Type.SERVICE, 4351),\n    MAINTENANCE_IN_PROGRESS(Type.SERVICE, 4352),\n\n    SERVICE_UNKNOWN(Type.SERVICE, 2000000),\n\n    //\n    // Type.SYSTEM\n    //\n    // Generic system errors we want to enumerate specifically\n    //\n    CONNECTION_RESET_BY_PEER(Type.SYSTEM, 104, Category.RECOVERABLE), // ECONNRESET: Connection reset by peer\n    CONNECTION_SOCKET_SHUTDOWN(Type.SYSTEM, 110, Category.RECOVERABLE), // ESHUTDOWN: Can't send after socket shutdown\n    CONNECTION_REFUSED(Type.SYSTEM, 111, Category.RECOVERABLE), // ECONNREFUSED: Connection refused\n    CONNECTION_ADDRESS_IN_USE(Type.SYSTEM, 112, Category.RECOVERABLE), // EADDRINUSE: Address already i use\n    CONNECTION_CONNECTION_ABORTED(Type.SYSTEM, 113, Category.RECOVERABLE); // ECONNABORTED: Connection aborted\n\n    private final String type;\n    private final int code;\n    private final Category category;\n\n    ErrorCode(String type, int errorCode) {\n        this(type, errorCode, Category.FATAL);\n    }\n\n    ErrorCode(String type, int errorCode, Category category) {\n        this.type = type;\n        this.code = errorCode;\n        this.category = category;\n    }\n\n    @Override\n    public String\n\n    toString() {\n        return super.toString() + \"(\" + type + \":\" + code + \")\";\n    }\n\n    /**\n     * Returns the numerical value for this error code. Note that an error is only uniquely\n     * identified by the {@code (type:value)} pair.\n     *\n     * @return the error code as an unique {@code int} value.\n     */\n    public int intValue() {\n        return code;\n    }\n\n    /**\n     * Returns the getCategory of the error.\n     * <p>\n     * Errors come in 2 categories: FATAL, RECOVERABLE\n     * <p>\n     * FATAL: The session cannot be recovered and needs to be re-created. A likely cause is that the User does not\n     * have access to this Realm. Check that the {@link SyncConfiguration} is correct.\n     * <p>\n     * RECOVERABLE: Temporary error. The session will automatically try to recover as soon as possible.\n     * <p>\n     *\n     * @return the severity of the error.\n     */\n    public Category getCategory() {\n        return category;\n    }\n\n    /**\n     * Returns the type of error.  Note that an error is only uniquely identified by the\n     * {@code (type:value)} pair.\n     *\n     * @return the type of error.\n     */\n    public String getType() {\n        return type;\n    }\n\n    /**\n     * Converts a native error to the appropriate Java equivalent\n     *\n     * @param type type of error. This is normally the C++ category.\n     * @param errorCode specific code within the type\n     *\n     * @return the Java error representing the native error. This method will never throw, so in case\n     * a Java error does not exists. {@link #UNKNOWN} will be returned.\n     */\n    public static ErrorCode fromNativeError(String type, int errorCode) {\n        ErrorCode[] errorCodes = values();\n        for (int i = 0; i < errorCodes.length; i++) {\n            ErrorCode error = errorCodes[i];\n            if (error.intValue() == errorCode && error.type.equals(type)) {\n                return error;\n            }\n        }\n        RealmLog.warn(String.format(Locale.US, \"Unknown error code: '%s:%d'\", type, errorCode));\n        return UNKNOWN;\n    }\n\n    public static class Type {\n\n        // Generic errors\n        public static final String LOGIC = \"LogicError\";\n        public static final String RUNTIME = \"RuntimeError\";\n        public static final String INVALID_ARGUMENT = \"IllegalArgumentError\";\n        public static final String FILE_ACCESS = \"FileAccessError\";\n        public static final String SYSTEM = \"realm.basic_system\"; // Connection/System errors from the native Sync Client\n\n        // App error types\n        public static final String APP = \"realm::app::ClientError\"; // Session level errors from the native App Client\n        public static final String JSON = \"realm::app::JSONError\"; // Errors when parsing JSON\n        public static final String SERVICE = \"realm::app::ServiceError\"; // MongoDB Realm Response errors\n        public static final String HTTP = \"realm::app::HttpError\"; // Errors from the HTTP layer\n        @Deprecated // Use CUSTOM instead.\n        public static final String JAVA = \"realm::app::CustomError\"; // Errors from the Java layer\n        public static final String CUSTOM = \"realm::app::CustomError\";\n\n        // Sync error types\n        @Deprecated // Use SYNC instead\n        public static final String CLIENT = \"realm::sync::ClientError\"; // Session level errors from the native Sync Client\n        @Deprecated // Use SYNC instead\n        public static final String PROTOCOL = \"realm::sync::ProtocolError\"; // Protocol level errors from the native Sync Client\n        @Deprecated // Use SYNC instead\n        public static final String SESSION = \"realm::sync::Session\"; // Session errors from the native Sync Client\n        public static final String WEBSOCKET = \"realm::sync::WebSocketError\";\n        public static final String SYNC = \"realm::sync::SyncError\";\n\n        // Catch-all category\n        public static final String UNKNOWN = \"unknown\";\n    }\n\n    public enum Category {\n        FATAL,          // Abort session as soon as possible\n        RECOVERABLE,    // Still possible to recover the session by either rebinding or providing the required information.\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/objectServer/java/io/realm/mongodb/FunctionsImpl.java",
    "content": "/*\n * Copyright 2020 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 */\npackage io.realm.mongodb;\n\nimport org.bson.codecs.Decoder;\nimport org.bson.codecs.configuration.CodecRegistry;\n\nimport java.util.List;\n\nimport io.realm.annotations.Beta;\nimport io.realm.internal.Util;\nimport io.realm.internal.jni.JniBsonProtocol;\nimport io.realm.internal.network.NetworkRequest;\nimport io.realm.internal.objectstore.OsJavaNetworkTransport;\nimport io.realm.mongodb.functions.Functions;\n\n/**\n * Internal implementation of Functions invoking the actual OS function in the context of the\n * {@link User}/{@link App}.\n */\n@Beta\nclass FunctionsImpl extends Functions {\n\n    FunctionsImpl(User user) {\n        this(user, user.getApp().getConfiguration().getDefaultCodecRegistry());\n    }\n\n    FunctionsImpl(User user, CodecRegistry codecRegistry) {\n        super(user, codecRegistry);\n    }\n\n    // Invokes actual MongoDB Realm Function in the context of the associated user/app.\n    @Override\n    public <T> T invoke(String name, List<?> args, CodecRegistry codecRegistry, Decoder<T> resultDecoder) {\n        Util.checkEmpty(name, \"name\");\n        String encodedResponse = new NetworkRequest<String>() {\n            @Override\n            protected String mapSuccess(Object result) {\n                return (String) result;\n            }\n            @Override\n            protected void execute(NetworkRequest<String> callback) {\n                String encodedArgs = JniBsonProtocol.encode(args, codecRegistry);\n                nativeCallFunction(\n                        user.getApp().osApp.getNativePtr(),\n                        user.osUser.getNativePtr(),\n                        name,\n                        encodedArgs,\n                        callback\n                );\n            }\n        }.resultOrThrow();\n        return JniBsonProtocol.decode(encodedResponse, resultDecoder);\n    }\n\n    private static native void nativeCallFunction(long nativeAppPtr, long nativeUserPtr, String name, String args_json, OsJavaNetworkTransport.NetworkTransportJNIResultCallback callback);\n\n}\n"
  },
  {
    "path": "realm/realm-library/src/objectServer/java/io/realm/mongodb/RealmEventStreamAsyncTask.java",
    "content": "/*\n * Copyright 2020 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\npackage io.realm.mongodb;\n\nimport io.realm.RealmAsyncTask;\nimport io.realm.mongodb.mongo.events.BaseChangeEvent;\n\n\n/**\n * The RealmEventStreamAsyncTask is a specific version of {@link RealmAsyncTask} that provides a non-blocking mechanism\n * to work with asynchronous operations carried out against MongoDB Realm that yield stream results.\n *\n * @param <T> the result type delivered by this task.\n */\npublic interface RealmEventStreamAsyncTask<T> extends RealmAsyncTask {\n    /**\n     * Provides a way to subscribe to asynchronous operations via a callback, which handles both\n     * results and errors.\n     *\n     * @param callback the {@link App.Callback} designed to receive event results.\n     * @throws IllegalStateException if the stream is already open.\n     */\n    void get(App.Callback<BaseChangeEvent<T>> callback) throws IllegalStateException;\n\n    /**\n     * Whether or not the stream is currently open.\n     * @return true if open, false if not.\n     */\n    boolean isOpen();\n}\n\n"
  },
  {
    "path": "realm/realm-library/src/objectServer/java/io/realm/mongodb/RealmEventStreamTask.java",
    "content": "/*\n * Copyright 2020 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\npackage io.realm.mongodb;\n\nimport java.io.IOException;\n\nimport io.realm.RealmAsyncTask;\nimport io.realm.mongodb.mongo.events.BaseChangeEvent;\n\n\n/**\n * The RealmEventStreamTask is a specific version of {@link RealmAsyncTask} that provides a blocking mechanism\n * to work with asynchronous operations carried out against MongoDB Realm that yield stream results.\n *\n * @param <T> the result type delivered by this task.\n */\npublic interface RealmEventStreamTask<T> extends RealmAsyncTask {\n\n    /**\n     * Blocks the thread on which the call is made until the result of the operation arrives.\n     *\n     * @return the next event in the stream.\n     * @throws AppException if the server raises an error\n     * @throws IOException if something is wrong with the input stream\n     */\n    BaseChangeEvent<T> getNext() throws AppException, IOException;\n\n    /**\n     * Whether or not the stream is currently open.\n     *\n     * @return true if open, false if not.\n     */\n    boolean isOpen();\n}\n\n"
  },
  {
    "path": "realm/realm-library/src/objectServer/java/io/realm/mongodb/RealmResultTask.java",
    "content": "/*\n * Copyright 2020 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\npackage io.realm.mongodb;\n\nimport io.realm.RealmAsyncTask;\n\n/**\n * The RealmResultTask is a specific version of {@link RealmAsyncTask} that provides a mechanism\n * to work with asynchronous operations carried out against MongoDB Realm that yield a result.\n * <p>\n * This class offers both blocking ({@code get}) and non-blocking ({@code getAsync}) method calls.\n *\n * @param <T> the result type delivered by this task.\n */\npublic interface RealmResultTask<T> extends RealmAsyncTask {\n\n    /**\n     * Blocks the thread on which the call is made until the result of the operation arrives.\n     *\n     * @return the result of the operation executed by this task.\n     */\n    T get();\n\n    /**\n     * Provides a way to subscribe to asynchronous operations via a callback, which handles both\n     * results and errors.\n     *\n     * @param callback the {@link App.Callback} designed to receive results.\n     * @throws IllegalStateException if called from a thread without a {@link android.os.Looper} or\n     *                               from an {@link android.app.IntentService} thread.\n     */\n    void getAsync(App.Callback<T> callback);\n}\n\n"
  },
  {
    "path": "realm/realm-library/src/objectServer/java/io/realm/mongodb/User.java",
    "content": "/*\n * Copyright 2020 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 */\npackage io.realm.mongodb;\n\nimport org.bson.Document;\nimport org.bson.codecs.configuration.CodecRegistry;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport javax.annotation.Nullable;\n\nimport edu.umd.cs.findbugs.annotations.SuppressFBWarnings;\nimport io.realm.RealmAsyncTask;\nimport io.realm.annotations.Beta;\nimport io.realm.internal.Util;\nimport io.realm.internal.mongodb.Request;\nimport io.realm.internal.network.NetworkRequest;\nimport io.realm.internal.network.StreamNetworkTransport;\nimport io.realm.internal.network.VoidNetworkRequest;\nimport io.realm.internal.objectstore.OsJavaNetworkTransport;\nimport io.realm.internal.objectstore.OsMongoClient;\nimport io.realm.internal.objectstore.OsPush;\nimport io.realm.internal.objectstore.OsSyncUser;\nimport io.realm.internal.util.Pair;\nimport io.realm.mongodb.auth.ApiKeyAuth;\nimport io.realm.mongodb.functions.Functions;\nimport io.realm.mongodb.mongo.MongoClient;\nimport io.realm.mongodb.push.Push;\n\n/**\n * A <i>user</i> holds the user's meta data and tokens for accessing Realm App functionality.\n * <p>\n * The user is used to configure Synchronized Realms and gives access to calling Realm App <i>Functions</i>\n * through {@link Functions} and accessing remote Realm App <i>Mongo Databases</i> through a\n * {@link MongoClient}.\n *\n * @see App#login(Credentials)\n * @see io.realm.mongodb.sync.SyncConfiguration.Builder#Builder(User, String)\n */\n@Beta\npublic class User {\n\n    OsSyncUser osUser;\n    private final App app;\n    private final UserProfile profile;\n    private ApiKeyAuth apiKeyAuthProvider = null;\n    private MongoClient mongoClient = null;\n    private Functions functions = null;\n    private Push push = null;\n\n    /**\n     * The different types of users.\n     */\n    enum UserType {\n        NORMAL(\"normal\"),\n        SERVER(\"server\"),\n        UNKNOWN(\"unknown\");\n\n        private final String key;\n\n        UserType(String key) {\n            this.key = key;\n        }\n\n        public String getKey() {\n            return key;\n        }\n    }\n\n    /**\n     * The user's potential states.\n     */\n    public enum State {\n        LOGGED_IN(OsSyncUser.STATE_LOGGED_IN),\n        REMOVED(OsSyncUser.STATE_REMOVED),\n        LOGGED_OUT(OsSyncUser.STATE_LOGGED_OUT);\n\n        private final byte nativeValue;\n\n        State(byte nativeValue) {\n            this.nativeValue = nativeValue;\n        }\n\n        byte getKey() {\n            return nativeValue;\n        }\n    }\n\n    private static class MongoClientImpl extends MongoClient {\n        protected MongoClientImpl(OsMongoClient osMongoClient,\n                                  CodecRegistry codecRegistry) {\n            super(osMongoClient, codecRegistry);\n        }\n    }\n\n    private static class PushImpl extends Push {\n        protected PushImpl(OsPush osPush) {\n            super(osPush);\n        }\n    }\n\n    User(OsSyncUser osUser, App app) {\n        this.osUser = osUser;\n        this.app = app;\n        this.profile = new UserProfile(this);\n    }\n\n    /**\n     * Returns the server id of the user.\n     *\n     * @return the server id of the user.\n     */\n    public String getId() {\n        return osUser.getIdentity();\n    }\n\n    /**\n     * Returns the profile for this user.\n     *\n     * @return the profile for this user\n     */\n    public UserProfile getProfile(){\n        return profile;\n    }\n\n    /**\n     * Returns a new list of the user's identities.\n     *\n     * @return the list of identities.\n     * @see UserIdentity\n     */\n    public List<UserIdentity> getIdentities() {\n        Pair<String, String>[] osIdentities = osUser.getIdentities();\n        List<UserIdentity> identities = new ArrayList<>(osIdentities.length);\n        for (int i = 0; i < osIdentities.length; i++) {\n            Pair<String, String> data = osIdentities[i];\n            identities.add(new UserIdentity(data.first, data.second));\n        }\n        return identities;\n    }\n\n    /**\n     * Returns the provider type of this users first identity. This is normally the one\n     * used to log the user in, but not always.\n     *\n     * @return the provider type of the user.\n     *\n     * @deprecated Use {@link #getIdentities()} instead.\n     */\n    @Deprecated\n    public Credentials.Provider getProviderType() {\n        return Credentials.Provider.fromId(osUser.getProviderType());\n    }\n\n    /**\n     * Returns the current access token for the user.\n     *\n     * @return the current access token.\n     */\n    public String getAccessToken() {\n        return osUser.getAccessToken();\n    }\n\n    /**\n     * Returns the current refresh token for the user.\n     *\n     * @return the current refresh token.\n     */\n    public String getRefreshToken() {\n        return osUser.getRefreshToken();\n    }\n\n    /**\n     * Returns a unique identifier for the device the user logged in to.\n     *\n     * @return a unique device identifier for the user.\n     */\n    public String getDeviceId() {\n        return osUser.getDeviceId();\n    }\n\n    /**\n     * Returns the {@link App} this user is associated with.\n     *\n     * @return the {@link App} this user is associated with.\n     */\n    public App getApp() {\n        return app;\n    }\n\n    /**\n     * Returns the {@link State} the user is in.\n     *\n     * @return the {@link State} of the user.\n     */\n    public State getState() {\n        byte nativeState = osUser.getState();\n        for (State state : State.values()) {\n            if (state.nativeValue == nativeState) {\n                return state;\n            }\n        }\n        throw new IllegalStateException(\"Unknown state: \" + nativeState);\n    }\n\n    /**\n     * Return the custom user data associated with the user in the Realm App.\n     * <p>\n     * The data is only refreshed when the user's access token is refreshed or when explicitly\n     * calling {@link #refreshCustomData()}.\n     *\n     * @return The custom user data associated with the user.\n     */\n    public Document getCustomData() {\n        return osUser.getCustomData();\n    }\n\n    /**\n     * Re-fetch custom user data from the Realm App.\n     *\n     * @return The updated custom user data associated with the user.\n     * @throws AppException if the request failed in some way.\n     */\n    public Document refreshCustomData() {\n        osUser.refreshCustomData();\n        return getCustomData();\n    }\n\n    /**\n     * Re-fetch custom user data from the Realm App asynchronously.\n     * <p>\n     * This is the asynchronous variant of {@link #refreshCustomData()}.\n     *\n     * @param callback The callback that will receive the result or any errors from the request.\n     * @return The task representing the ongoing operation.\n     * @throws IllegalStateException if not called on a looper thread.\n     */\n    public RealmAsyncTask refreshCustomData(App.Callback<Document> callback) {\n        Util.checkLooperThread(\"Asynchronous functions is only possible from looper threads.\");\n        return new Request<Document>(App.NETWORK_POOL_EXECUTOR, callback) {\n            @Override\n            public Document run() throws AppException {\n                return refreshCustomData();\n            }\n        }.start();\n    }\n\n\n    /**\n     * Returns true if the user is currently logged in.\n     * Returns whether or not this user is still logged into the MongoDB Realm App.\n     *\n     * @return {@code true} if still logged in, {@code false} if not.\n     */\n    public boolean isLoggedIn() {\n        return getState() == State.LOGGED_IN;\n    }\n\n    /**\n     * Links the current user with a new user identity represented by the given credentials.\n     * <p>\n     * Linking a user with more credentials, mean the user can login either of these credentials.\n     * It also makes it possible to \"upgrade\" an anonymous user by linking it with e.g.\n     * Email/Password credentials.\n     * <pre>\n     * {@code\n     * // Example\n     * App app = new App(\"app-id\")\n     * User user = app.login(Credentials.anonymous());\n     * user.linkCredentials(Credentials.emailPassword(\"email\", \"password\"));\n     * }\n     * </pre>\n     * <p>\n     * Note: It is not possible to link two existing users of MongoDB Realm. The provided credentials\n     * must not have been used by another user.\n     *\n     * @param credentials the credentials to link with the current user.\n     * @return the {@link User} the credentials were linked to.\n     *\n     * @throws IllegalStateException if no user is currently logged in.\n     */\n    public User linkCredentials(Credentials credentials) {\n        Util.checkNull(credentials, \"credentials\");\n        checkLoggedIn();\n\n        return new NetworkRequest<User>() {\n            @Override\n            protected User mapSuccess(Object result) {\n                osUser = new OsSyncUser((long) result); // OS returns the updated user as a new one.\n                return User.this;\n            }\n\n            @Override\n            protected void execute(NetworkRequest<User> callback) {\n                nativeLinkUser(\n                        app.osApp.getNativePtr(),\n                        osUser.getNativePtr(),\n                        credentials.osCredentials.getNativePtr(),\n                        callback\n                );\n            }\n        }.resultOrThrow();\n    }\n\n    /**\n     * Links the current user with a new user identity represented by the given credentials.\n     * <p>\n     * Linking a user with more credentials, mean the user can login either of these credentials.\n     * It also makes it possible to \"upgrade\" an anonymous user by linking it with e.g.\n     * Email/Password credentials.\n     * <pre>\n     * {@code\n     * // Example\n     * App app = new App(\"app-id\")\n     * User user = app.login(Credentials.anonymous());\n     * user.linkCredentials(Credentials.emailPassword(\"email\", \"password\"));\n     * }\n     * </pre>\n     * <p>\n     * Note: It is not possible to link two existing users of MongoDB Realm. The provided credentials\n     * must not have been used by another user.\n     *\n     * @param credentials the credentials to link with the current user.\n     * @param callback    callback when user identities has been linked or it failed. The callback will\n     *                    always happen on the same thread as this method is called on.\n     *\n     * @throws IllegalStateException if called from a non-looper thread.\n     */\n    public RealmAsyncTask linkCredentialsAsync(Credentials credentials, App.Callback<User> callback) {\n        Util.checkLooperThread(\"Asynchronous linking identities is only possible from looper threads.\");\n        return new Request<User>(App.NETWORK_POOL_EXECUTOR, callback) {\n            @Override\n            public User run() throws AppException {\n                return linkCredentials(credentials);\n            }\n        }.start();\n    }\n\n    /**\n     * Calling this will remove the user and any Realms the user has from the device. No data\n     * is removed from the server.\n     *\n     * If the user is logged in when calling this method, the user is logged out before any data\n     * is deleted.\n     *\n     * @throws AppException if an error occurred while trying to remove the user.\n     * @return the user that was removed.\n     */\n    public User remove() throws AppException {\n        boolean loggedIn = isLoggedIn();\n        new VoidNetworkRequest() {\n            @Override\n            protected void execute(NetworkRequest<Void> callback) {\n                nativeRemoveUser(\n                        app.osApp.getNativePtr(),\n                        osUser.getNativePtr(),\n                        callback\n                );\n            }\n        }.execute();\n        if (loggedIn) {\n            app.notifyUserLoggedOut(this);\n        }\n        return this;\n    }\n\n    /**\n     * Calling this will asynchronously remove the user and any Realms the user has from the device.\n     * No data is removed from the server.\n     *\n     * If the user is logged in when calling this method, the user is logged out before any data\n     * is deleted.\n     *\n     * @param callback callback when removing the user has completed or failed. The callback will\n     *                 always happen on the same thread as this method is called on.\n     * @throws IllegalStateException if called from a non-looper thread.\n     */\n    public RealmAsyncTask removeAsync(App.Callback<User> callback) {\n        Util.checkLooperThread(\"Asynchronous removal of users is only possible from looper threads.\");\n        return new Request<User>(App.NETWORK_POOL_EXECUTOR, callback) {\n            @Override\n            public User run() throws AppException {\n                return remove();\n            }\n        }.start();\n    }\n\n    /**\n     * Log the user out of the Realm App. This will unregister them on the device and stop any\n     * synchronization to and from the users' Realms. Any Realms owned by the user will\n     * not be deleted from the device before {@link User#remove()} is called.\n     *\n     * <p>\n     * Once the Realm App has confirmed the logout any registered {@link AuthenticationListener}\n     * will be notified and user credentials will be deleted from this device.\n     * <p>\n     * Logging out anonymous users will remove them immediately instead of marking them as\n     * {@link User.State#LOGGED_OUT}.\n     * <p>\n     * All other users will be marked as {@link User.State#LOGGED_OUT}\n     * and will still be returned by {@link App#allUsers()}. They can be removed completely by\n     * calling {@link User#remove()}.\n     *\n     * @throws AppException if an error occurred while trying to log the user out of the Realm\n     *                      App.\n     */\n    public void logOut() throws AppException {\n        boolean loggedIn = isLoggedIn();\n        new VoidNetworkRequest() {\n            @Override\n            protected void execute(NetworkRequest<Void> callback) {\n                nativeLogOut(app.osApp.getNativePtr(), osUser.getNativePtr(), callback);\n            }\n        }.execute();\n        if (loggedIn) {\n            app.notifyUserLoggedOut(this);\n        }\n    }\n\n    /**\n     * Log the user out of the Realm App asynchronously. This will unregister them on the device and\n     * stop any synchronization to and from the users' Realms. Any Realms owned by the user will\n     * not be deleted from the device before {@link User#remove()} is called.\n     * <p>\n     * Once the Realm App has confirmed the logout any registered {@link AuthenticationListener}\n     * will be notified and user credentials will be deleted from this device.\n     * <p>\n     * Logging out anonymous users will remove them immediately instead of marking them as\n     * {@link User.State#LOGGED_OUT}.\n     * <p>\n     * All other users will be marked as {@link User.State#LOGGED_OUT} and will still be returned\n     * by {@link App#allUsers()}. They can be removed completely by calling {@link User#remove()}.\n     *\n     * @param callback callback when logging out has completed or failed. The callback will always\n     *                 happen on the same thread as this method is called on.\n     * @throws IllegalStateException if called from a non-looper thread.\n     */\n    public RealmAsyncTask logOutAsync(App.Callback<User> callback) {\n        Util.checkLooperThread(\"Asynchronous log out is only possible from looper threads.\");\n        return new Request<User>(App.NETWORK_POOL_EXECUTOR, callback) {\n            @Override\n            public User run() throws AppException {\n                logOut();\n                return User.this;\n            }\n        }.start();\n    }\n\n    /**\n     * Returns a wrapper for managing API keys controlled by the current user.\n     *\n     * @return wrapper for managing API keys controlled by the current user.\n     * @throws IllegalStateException if no user is currently logged in.\n     */\n    public synchronized ApiKeyAuth getApiKeys() {\n        checkLoggedIn();\n        if (apiKeyAuthProvider == null) {\n            apiKeyAuthProvider = new ApiKeyAuthImpl(this);\n        }\n        return apiKeyAuthProvider;\n    }\n\n    /**\n     * Returns a <i>functions</i> manager for invoking MongoDB Realm Functions.\n     * <p>\n     * This will use the associated app's default codec registry to encode and decode arguments and\n     * results.\n     *\n     * @see Functions\n     */\n    public synchronized Functions getFunctions() {\n        checkLoggedIn();\n        if (functions == null) {\n            functions = new FunctionsImpl(this);\n        }\n        return functions;\n    }\n\n    /**\n     * Returns a <i>functions</i> manager for invoking Realm Functions with custom\n     * codec registry for encoding and decoding arguments and results.\n     *\n     * @param codecRegistry The codec registry to use for encoding and decoding arguments and results\n     *                      towards the remote Realm App.\n     * @see Functions\n     */\n    public Functions getFunctions(CodecRegistry codecRegistry) {\n        return new FunctionsImpl(this, codecRegistry);\n    }\n\n    /**\n     * Returns the {@link Push} instance for managing push notification registrations.\n     *\n     * @param serviceName the service name used to connect to the server.\n     */\n    public synchronized Push getPush(String serviceName) {\n        if (push == null) {\n            OsPush osPush = new OsPush(app.osApp, osUser, serviceName);\n            push = new PushImpl(osPush);\n        }\n        return push;\n    }\n\n    /**\n     * Returns a {@link MongoClient} instance for accessing documents in the database.\n     *\n     * @param serviceName the service name used to connect to the server.\n     */\n    public synchronized MongoClient getMongoClient(String serviceName) {\n        Util.checkEmpty(serviceName, \"serviceName\");\n        if (mongoClient == null) {\n            StreamNetworkTransport streamNetworkTransport = new StreamNetworkTransport(app.osApp, this.osUser);\n            OsMongoClient osMongoClient = new OsMongoClient(osUser, serviceName, streamNetworkTransport);\n            mongoClient = new MongoClientImpl(osMongoClient, app.getConfiguration().getDefaultCodecRegistry());\n        }\n        return mongoClient;\n    }\n\n    /**\n     * Two Users are considered equal if they have the same user identity and are associated\n     * with the same app.\n     */\n    @SuppressFBWarnings(\"NP_METHOD_PARAMETER_TIGHTENS_ANNOTATION\")\n    @Override\n    public boolean equals(@Nullable Object o) {\n        if (this == o) return true;\n        if (o == null || getClass() != o.getClass()) return false;\n\n        User user = (User) o;\n\n        if (!osUser.getIdentity().equals(user.osUser.getIdentity())) return false;\n        return app.getConfiguration().getAppId().equals(user.app.getConfiguration().getAppId());\n    }\n\n    @Override\n    public int hashCode() {\n        int result = osUser.hashCode();\n        result = 31 * result + app.hashCode();\n        return result;\n    }\n\n    private void checkLoggedIn() {\n        if (!isLoggedIn()) {\n            throw new IllegalStateException(\"User is not logged in.\");\n        }\n    }\n\n    private static native void nativeRemoveUser(long nativeAppPtr, long nativeUserPtr, OsJavaNetworkTransport.NetworkTransportJNIResultCallback callback);\n\n    private static native void nativeLinkUser(long nativeAppPtr, long nativeUserPtr, long nativeCredentialsPtr, OsJavaNetworkTransport.NetworkTransportJNIResultCallback callback);\n\n    private static native void nativeLogOut(long appNativePtr, long userNativePtr, OsJavaNetworkTransport.NetworkTransportJNIResultCallback callback);\n}\n"
  },
  {
    "path": "realm/realm-library/src/objectServer/java/io/realm/mongodb/UserIdentity.java",
    "content": "/*\n * Copyright 2020 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 */\npackage io.realm.mongodb;\n\nimport io.realm.annotations.Beta;\n\n/**\n * Each User is represented by 1 or more identities each defined by an\n * {@link Credentials.Provider}.\n *\n * This class represents the identity defined by a specific provider.\n */\n@Beta\npublic class UserIdentity {\n\n    private final String userId;\n    private final String providerId;\n    private final Credentials.Provider provider;\n\n    UserIdentity(String id, String providerId) {\n        this.userId = id;\n        this.providerId = providerId;\n        this.provider = Credentials.Provider.fromId(providerId);\n    }\n\n    /**\n     * Returns a unique identifier for this identity.\n     *\n     * @return a unique identifier for this identifier.\n     */\n    public String getId() {\n        return userId;\n    }\n\n    /**\n     * Returns the provider defining this identity.\n     *\n     * @return\n     */\n    public Credentials.Provider getProvider() {\n        return provider;\n    }\n\n    @Override\n    public boolean equals(Object o) {\n        if (this == o) return true;\n        if (o == null || getClass() != o.getClass()) return false;\n\n        UserIdentity that = (UserIdentity) o;\n\n        if (!userId.equals(that.userId)) return false;\n        if (!providerId.equals(that.providerId)) return false;\n        return provider == that.provider;\n    }\n\n    @Override\n    public int hashCode() {\n        int result = userId.hashCode();\n        result = 31 * result + providerId.hashCode();\n        result = 31 * result + provider.hashCode();\n        return result;\n    }\n\n    @Override\n    public String toString() {\n        return \"UserIdentity{\" +\n                \"userId='\" + userId + '\\'' +\n                \", providerId='\" + providerId + '\\'' +\n                '}';\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/objectServer/java/io/realm/mongodb/UserProfile.java",
    "content": "/*\n * Copyright 2020 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\npackage io.realm.mongodb;\n\nimport javax.annotation.Nullable;\n\nimport edu.umd.cs.findbugs.annotations.SuppressFBWarnings;\n\npublic class UserProfile {\n    private final User user;\n\n    UserProfile(User user) {\n        this.user = user;\n    }\n\n    /**\n     * Returns the name of the user.\n     *\n     * @return the name of the user.\n     */\n    @Nullable\n    public String getName() {\n        return user.osUser.nativeGetName();\n    }\n\n    /**\n     * Returns the email address of the user.\n     *\n     * @return the email address of the user or null if there is no email address associated with the user.\n     * address.\n     */\n    @Nullable\n    public String getEmail() {\n        return user.osUser.getEmail();\n    }\n\n    /**\n     * Returns the picture URL of the user.\n     *\n     * @return the picture URL of the user or null if there is no picture URL associated with the user.\n     */\n    @Nullable\n    public String getPictureUrl() {\n        return user.osUser.getPictureUrl();\n    }\n\n    /**\n     * Return the first name of the user.\n     *\n     * @return the first name of the user or null if there is no first name associated with the user.\n     */\n    @Nullable\n    public String getFirstName() {\n        return user.osUser.getFirstName();\n    }\n\n    /**\n     * Return the last name of the user.\n     *\n     * @return the last name of the user or null if there is no last name associated with the user.\n     */\n    @Nullable\n    public String getLastName() {\n        return user.osUser.getLastName();\n    }\n\n    /**\n     * Returns the gender of the user.\n     *\n     * @return the gender of the user or null if there is no gender associated with the user.\n     */\n    @Nullable\n    public String getGender() {\n        return user.osUser.getGender();\n    }\n\n    /**\n     * Returns the birthday of the user.\n     *\n     * @return the birthday of the user or null if there is no birthday associated with the user.\n     */\n    @Nullable\n    public String getBirthday() {\n        return user.osUser.getBirthday();\n    }\n\n    /**\n     * Returns the minimum age of the user.\n     *\n     * @return the minimum age of the user or null if there is no minimum age associated with the user.\n     */\n    @Nullable\n    public Long getMinAge() {\n        String minAge = user.osUser.getMinAge();\n        return (minAge == null) ? null : Long.parseLong(minAge);\n    }\n\n    /**\n     * Returns the maximum age of the user.\n     *\n     * @return the maximum age of the user or null if there is no maximum age associated with the user.\n     */\n    @Nullable\n    public Long getMaxAge() {\n        String maxAge = user.osUser.getMaxAge();\n        return (maxAge == null) ? null : Long.parseLong(maxAge);\n    }\n\n    /**\n     * Returns the {@link User} that this instance in associated with.\n     *\n     * @return The {@link User} that this instance in associated with.\n     */\n    public User getUser() {\n        return user;\n    }\n\n    @Override\n    public String toString() {\n        return \"Profile{\" +\n                \"name='\" + getName() + '\\'' +\n                \", email='\" + getEmail() + '\\'' +\n                \", pictureUrl='\" + getPictureUrl() + '\\'' +\n                \", firstName='\" + getFirstName() + '\\'' +\n                \", lastName='\" + getLastName() + '\\'' +\n                \", gender='\" + getGender() + '\\'' +\n                \", birthday='\" + getBirthday() + '\\'' +\n                \", minAge=\" + getMinAge() +\n                \", maxAge=\" + getMaxAge() +\n                '}';\n    }\n\n    @SuppressFBWarnings(\"NP_METHOD_PARAMETER_TIGHTENS_ANNOTATION\")\n    @Override\n    public boolean equals(Object o) {\n        if (this == o) return true;\n        if (o == null || getClass() != o.getClass()) return false;\n\n        UserProfile profile = (UserProfile) o;\n\n        return user.equals(profile.user);\n    }\n\n    @Override\n    public int hashCode() {\n        return user.hashCode();\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/objectServer/java/io/realm/mongodb/auth/ApiKey.java",
    "content": "/*\n * Copyright 2020 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 */\npackage io.realm.mongodb.auth;\n\nimport org.bson.types.ObjectId;\n\nimport javax.annotation.Nullable;\n\nimport io.realm.annotations.Beta;\nimport io.realm.mongodb.User;\n\n/**\n * Class representing an API key for a {@link User}. An API can be used to represent the\n * user when logging instead of using email and password.\n * <p>\n * These keys are created or fetched through {@link ApiKeyAuth#create(String)} or the various\n * {@code fetch}-methods.\n * <p>\n * Note that a keys {@link #value} is only available when the key is created, after that it is not\n * visible. So anyone creating an API key is responsible for storing it safely after that.\n */\n@Beta\npublic class ApiKey {\n    private final ObjectId id;\n    private final String value;\n    private final String name;\n    private final boolean enabled;\n\n    ApiKey(ObjectId id, @Nullable String value, String name, boolean enabled) {\n        this.id = id;\n        this.value = value;\n        this.name = name;\n        this.enabled = enabled;\n    }\n\n    /**\n     * Returns the unique identifier for this key.\n     *\n     * @return the id, uniquely identifying the key.\n     */\n    public ObjectId getId() {\n        return id;\n    }\n\n    /**\n     * Returns this keys value. This value is only returned when the key is created. After that\n     * the value is no longer visible.\n     *\n     * @return the value of this key. Is only returned when the key is created.\n     */\n    @Nullable\n    public String getValue() {\n        return value;\n    }\n\n    /**\n     * Returns the name of this key.\n     *\n     * @return the name of the key.\n     */\n    public String getName() {\n        return name;\n    }\n\n\n    /**\n     * Returns whether or not this key is currently enabled.\n     *\n     * @return if the key is enabled or not.\n     */\n    public boolean isEnabled() {\n        return enabled;\n    }\n\n    @Override\n    public boolean equals(Object o) {\n        if (this == o) return true;\n        if (o == null || getClass() != o.getClass()) return false;\n\n        ApiKey that = (ApiKey) o;\n\n        if (enabled != that.enabled) return false;\n        if (!id.equals(that.id)) return false;\n        if (!value.equals(that.value)) return false;\n        return name.equals(that.name);\n    }\n\n    @Override\n    public int hashCode() {\n        int result = id.hashCode();\n        result = 31 * result + value.hashCode();\n        result = 31 * result + name.hashCode();\n        result = 31 * result + (enabled ? 1 : 0);\n        return result;\n    }\n\n    @Override\n    public String toString() {\n        return \"ApiKey{\" +\n                \"id=\" + id +\n                \", value='\" + value + '\\'' +\n                \", name='\" + name + '\\'' +\n                \", enabled=\" + enabled +\n                '}';\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/objectServer/java/io/realm/mongodb/auth/ApiKeyAuth.java",
    "content": "/*\n * Copyright 2020 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 */\npackage io.realm.mongodb.auth;\n\nimport static io.realm.mongodb.App.NETWORK_POOL_EXECUTOR;\n\nimport org.bson.types.ObjectId;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport javax.annotation.Nullable;\n\nimport io.realm.RealmAsyncTask;\nimport io.realm.annotations.Beta;\nimport io.realm.internal.Util;\nimport io.realm.internal.mongodb.Request;\nimport io.realm.internal.network.NetworkRequest;\nimport io.realm.internal.network.VoidNetworkRequest;\nimport io.realm.internal.objectstore.OsJavaNetworkTransport;\nimport io.realm.mongodb.App;\nimport io.realm.mongodb.AppException;\nimport io.realm.mongodb.User;\n\n/**\n * This class exposes functionality for a user to manage API keys under their control.\n */\n@Beta\npublic abstract class ApiKeyAuth {\n\n    private static final int TYPE_CREATE = 1;\n    private static final int TYPE_FETCH_SINGLE = 2;\n    private static final int TYPE_FETCH_ALL = 3;\n    private static final int TYPE_DELETE = 4;\n    private static final int TYPE_DISABLE = 5;\n    private static final int TYPE_ENABLE = 6;\n\n    private final User user;\n\n    /**\n     * Create an instance of this class for a specific user.\n     *\n     * @param user user that is controlling the API keys.\n     */\n    protected ApiKeyAuth(User user) {\n        this.user = user;\n    }\n\n    /**\n     * Returns the {@link User} that this instance in associated with.\n     *\n     * @return The {@link User} that this instance in associated with.\n     */\n    public User getUser() {\n        return user;\n    }\n\n    /**\n     * Returns the {@link App} that this instance in associated with.\n     *\n     * @return The {@link App} that this instance in associated with.\n     */\n    public App getApp() {\n        return user.getApp();\n    }\n\n    /**\n     * Creates a user API key that can be used to authenticate as the user.\n     * <p>\n     * The value of the key must be persisted at this time as this is the only time it is visible.\n     * <p>\n     * The key is enabled when created. It can be disabled by calling {@link #disable(ObjectId)}.\n     *\n     * @param name the name of the key\n     * @throws AppException if the server failed to create the API key.\n     * @return the new API key for the user.\n     */\n    public ApiKey create(String name) throws AppException {\n        Util.checkEmpty(name, \"name\");\n        return new NetworkRequest<ApiKey>() {\n            @Override\n            protected ApiKey mapSuccess(Object result) {\n                return createKeyFromNative((Object[]) result);\n            }\n            @Override\n            protected void execute(NetworkRequest<ApiKey> callback) {\n                call(TYPE_CREATE, name, callback);\n            }\n        }.resultOrThrow();\n    }\n\n    /**\n     * Asynchronously creates a user API key that can be used to authenticate as the user.\n     * <p>\n     * The value of the key must be persisted at this time as this is the only time it is visible.\n     * <p>\n     * The key is enabled when created. It can be disabled by calling {@link #disable(ObjectId)}.\n     *\n     * @param name the name of the key\n     * @param callback callback when key creation has completed or failed. The callback will always\n     * happen on the same thread as this method is called on.\n     * @throws IllegalStateException if called from a non-looper thread.\n     */\n    public RealmAsyncTask createAsync(String name, App.Callback<ApiKey> callback) {\n        Util.checkLooperThread(\"Asynchronous creation of api keys are only possible from looper threads.\");\n        return new Request<ApiKey>(NETWORK_POOL_EXECUTOR, callback) {\n            @Override\n            public ApiKey run() throws AppException {\n                return create(name);\n            }\n        }.start();\n    }\n\n    /**\n     * Fetches a specific user API key associated with the user.\n     *\n     * @param id the id of the key to fetch.\n     * @throws AppException if the server failed to fetch the API key.\n     */\n    public ApiKey fetch(ObjectId id) throws AppException {\n        Util.checkNull(id, \"id\");\n        return new NetworkRequest<ApiKey>() {\n            @Override\n            protected ApiKey mapSuccess(Object result) {\n                return createKeyFromNative((Object[]) result);\n            }\n            @Override\n            protected void execute(NetworkRequest<ApiKey> callback) {\n                call(TYPE_FETCH_SINGLE, id.toHexString(), callback);\n            }\n        }.resultOrThrow();\n    }\n\n    /**\n     * Fetches a specific user API key associated with the user.\n     *\n     * @param id the id of the key to fetch.\n     * @param callback callback used when the key was fetched or the call failed. The callback\n     * will always happen on the same thread as this method was called on.\n     * @throws IllegalStateException if called from a non-looper thread.\n     */\n    public RealmAsyncTask fetchAsync(ObjectId id, App.Callback<ApiKey> callback) {\n        Util.checkLooperThread(\"Asynchronous fetching an api key is only possible from looper threads.\");\n        return new Request<ApiKey>(NETWORK_POOL_EXECUTOR, callback) {\n            @Override\n            public ApiKey run() throws AppException {\n                return fetch(id);\n            }\n        }.start();\n    }\n\n    /**\n     * Fetches all API keys associated with the user.\n     *\n     * @throws AppException if the server failed to fetch the API keys.\n     */\n    public List<ApiKey> fetchAll() throws AppException {\n        return new NetworkRequest<List<ApiKey>>() {\n            @Override\n            protected List<ApiKey> mapSuccess(Object result) {\n                Object[] keyData = (Object[]) result;\n                List<ApiKey> list = new ArrayList<>();\n                for (int i = 0; i < keyData.length; i++) {\n                    list.add(createKeyFromNative((Object[]) keyData[i]));\n                }\n                return list;\n            }\n            @Override\n            protected void execute(NetworkRequest<List<ApiKey>> callback) {\n                call(TYPE_FETCH_ALL, null, callback);\n            }\n        }.resultOrThrow();\n    }\n\n\n    /**\n     * Fetches all API keys associated with the user.\n     *\n     * @param callback callback used when the keys were fetched or the call failed. The callback\n     * will always happen on the same thread as this method was called on.\n     * @throws IllegalStateException if called from a non-looper thread.\n     */\n    public RealmAsyncTask fetchAll(App.Callback<List<ApiKey>> callback) {\n        Util.checkLooperThread(\"Asynchronous fetching an api key is only possible from looper threads.\");\n        return new Request<List<ApiKey>>(NETWORK_POOL_EXECUTOR, callback) {\n            @Override\n            public List<ApiKey> run() throws AppException {\n                return fetchAll();\n            }\n        }.start();\n    }\n\n    /**\n     * Deletes a specific API key created by the user.\n     *\n     * @param id the id of the key to delete.\n     * @throws AppException if the server failed to delete the API key.\n     */\n    public void delete(ObjectId id) throws AppException {\n        Util.checkNull(id, \"id\");\n        new VoidNetworkRequest() {\n            @Override\n            protected void execute(NetworkRequest<Void> callback) {\n                call(TYPE_DELETE, id.toHexString(), callback);\n            }\n        }.execute();\n    }\n\n    /**\n     * Deletes a specific API key created by the user.\n     *\n     * @param id the id of the key to delete.\n     * @param callback callback used when the was deleted or the call failed. The callback\n     * will always happen on the same thread as this method was called on.\n     * @throws IllegalStateException if called from a non-looper thread.\n     */\n    public RealmAsyncTask deleteAsync(ObjectId id, App.Callback<Void> callback) {\n        Util.checkLooperThread(\"Asynchronous deleting an api key is only possible from looper threads.\");\n        return new Request<Void>(NETWORK_POOL_EXECUTOR, callback) {\n            @Override\n            public Void run() throws AppException {\n                delete(id);\n                return null;\n            }\n        }.start();\n    }\n\n    /**\n     * Disables a specific API key created by the user.\n     *\n     * @param id the id of the key to disable.\n     * @throws AppException if the server failed to disable the API key.\n     */\n    public void disable(ObjectId id) throws AppException {\n        Util.checkNull(id, \"id\");\n        new VoidNetworkRequest() {\n            @Override\n            protected void execute(NetworkRequest<Void> callback) {\n                call(TYPE_DISABLE, id.toHexString(), callback);\n            }\n        }.execute();\n    }\n\n    /**\n     * Disables a specific API key created by the user.\n     *\n     * @param id the id of the key to disable.\n     * @param callback callback used when the key was disabled or the call failed. The callback\n     * will always happen on the same thread as this method was called on.\n     * @throws IllegalStateException if called from a non-looper thread.\n     */\n    public RealmAsyncTask disableAsync(ObjectId id, App.Callback<Void> callback) {\n        Util.checkLooperThread(\"Asynchronous disabling an api key is only possible from looper threads.\");\n        return new Request<Void>(NETWORK_POOL_EXECUTOR, callback) {\n            @Override\n            public Void run() throws AppException {\n                disable(id);\n                return null;\n            }\n        }.start();\n    }\n\n    /**\n     * Enables a specific API key created by the user.\n     *\n     * @param id the id of the key to enable.\n     * @throws AppException if the server failed to enable the API key.\n     */\n    public void enable(ObjectId id) throws AppException {\n        Util.checkNull(id, \"id\");\n        new VoidNetworkRequest() {\n            @Override\n            protected void execute(NetworkRequest<Void> callback) {\n                call(TYPE_ENABLE, id.toHexString(), callback);            }\n        }.execute();\n    }\n\n    /**\n     * Enables a specific API key created by the user.\n     *\n     * @param id the id of the key to enable.\n     * @param callback callback used when the key was enabled or the call failed. The callback\n     * will always happen on the same thread as this method was called on.\n     * @throws IllegalStateException if called from a non-looper thread.\n     */\n    public RealmAsyncTask enableAsync(ObjectId id, App.Callback<Void> callback) {\n        Util.checkLooperThread(\"Asynchronous enabling an api key is only possible from looper threads.\");\n        return new Request<Void>(NETWORK_POOL_EXECUTOR, callback) {\n            @Override\n            public Void run() throws AppException {\n                enable(id);\n                return null;\n            }\n        }.start();\n    }\n\n    private ApiKey createKeyFromNative(Object[] keyData) {\n        return new ApiKey(new ObjectId((String) keyData[0]),\n                (String) keyData[1],\n                (String) keyData[2],\n                !(Boolean) keyData[3]); // Server returns disabled state instead of enabled\n    }\n\n    @Override\n    public boolean equals(Object o) {\n        if (this == o) return true;\n        if (o == null || getClass() != o.getClass()) return false;\n\n        ApiKeyAuth that = (ApiKeyAuth) o;\n\n        return user.equals(that.user);\n    }\n\n    @Override\n    public int hashCode() {\n        return user.hashCode();\n    }\n\n    @Override\n    public String toString() {\n        return \"ApiKeyAuthProvider{\" +\n                \"user=\" + user.getId() +\n                '}';\n    }\n\n    protected abstract void call(int functionType, @Nullable String arg, OsJavaNetworkTransport.NetworkTransportJNIResultCallback callback);\n\n}\n"
  },
  {
    "path": "realm/realm-library/src/objectServer/java/io/realm/mongodb/auth/EmailPasswordAuth.java",
    "content": "/*\n * Copyright 2020 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 */\npackage io.realm.mongodb.auth;\n\nimport static io.realm.mongodb.App.NETWORK_POOL_EXECUTOR;\n\nimport java.util.Arrays;\n\nimport io.realm.RealmAsyncTask;\nimport io.realm.annotations.Beta;\nimport io.realm.internal.Util;\nimport io.realm.internal.jni.JniBsonProtocol;\nimport io.realm.internal.mongodb.Request;\nimport io.realm.internal.network.NetworkRequest;\nimport io.realm.internal.network.VoidNetworkRequest;\nimport io.realm.internal.objectstore.OsJavaNetworkTransport;\nimport io.realm.mongodb.App;\nimport io.realm.mongodb.AppException;\nimport io.realm.mongodb.Credentials;\nimport io.realm.mongodb.User;\n\n/**\n * Class encapsulating functionality provided when {@link User}'s are logged in through the\n * {@link Credentials.Provider#EMAIL_PASSWORD} provider.\n */\n@Beta\npublic abstract class EmailPasswordAuth {\n\n    private static final int TYPE_REGISTER_USER = 1;\n    private static final int TYPE_CONFIRM_USER = 2;\n    private static final int TYPE_RESEND_CONFIRMATION_EMAIL = 3;\n    private static final int TYPE_SEND_RESET_PASSWORD_EMAIL = 4;\n    private static final int TYPE_CALL_RESET_PASSWORD_FUNCTION = 5;\n    private static final int TYPE_RESET_PASSWORD = 6;\n    private static final int TYPE_RETRY_CUSTOM_CONFIRMATION = 7;\n\n    protected final App app;\n\n    /**\n     * Creates an authentication provider exposing functionality to using an email and password\n     * for login into a Realm Application.\n     */\n    protected EmailPasswordAuth(App app) {\n        this.app = app;\n    }\n\n    /**\n     * Registers a new user with the given email and password.\n     *\n     * @param email the email to register with. This will be the username used during log in.\n     * @param password the password to associate with the email. The password must be between\n     * 6 and 128 characters long.\n     *\n     * @throws AppException if the server failed to register the user.\n     */\n    public void registerUser(String email, String password) throws AppException {\n        Util.checkEmpty(email, \"email\");\n        Util.checkEmpty(password, \"password\");\n        new VoidNetworkRequest() {\n            @Override\n            protected void execute(NetworkRequest<Void> callback) {\n                call(TYPE_REGISTER_USER, this, email, password);\n            }\n        }.execute();\n    }\n\n    /**\n     * Registers a new user with the given email and password.\n     *\n     * @param email the email to register with. This will be the username used during log in.\n     * @param password the password to associated with the email. The password must be between\n     * 6 and 128 characters long.\n     * @param callback callback when registration has completed or failed. The callback will always\n     * happen on the same thread as this method is called on.\n     *\n     * @throws IllegalStateException if called from a non-looper thread.\n     * @throws AppException if the server failed to register the user.\n     */\n    public RealmAsyncTask registerUserAsync(String email, String password, App.Callback<Void> callback) {\n        Util.checkLooperThread(\"Asynchronous registration of a user is only possible from looper threads.\");\n        return new Request<Void>(NETWORK_POOL_EXECUTOR, callback) {\n            @Override\n            public Void run() throws AppException {\n                registerUser(email, password);\n                return null;\n            }\n        }.start();\n    }\n\n    /**\n     * Confirms a user with the given token and token id.\n     *\n     * @param token the confirmation token.\n     * @param tokenId the id of the confirmation token.\n     * @throws AppException if the server failed to confirm the user.\n     */\n    public void confirmUser(String token, String tokenId) throws AppException {\n        Util.checkEmpty(token, \"token\");\n        Util.checkEmpty(tokenId, \"tokenId\");\n        new VoidNetworkRequest() {\n            @Override\n            protected void execute(NetworkRequest<Void> callback) {\n                call(TYPE_CONFIRM_USER, callback, token, tokenId);\n            }\n        }.execute();\n    }\n\n    /**\n     * Confirms a user with the given token and token id.\n     *\n     * @param token the confirmation token.\n     * @param tokenId the id of the confirmation token.\n     * @param callback callback when confirmation has completed or failed. The callback will always\n     * happen on the same thread as this method is called on.\n     * @throws IllegalStateException if called from a non-looper thread.\n     */\n    public RealmAsyncTask confirmUserAsync(String token, String tokenId, App.Callback<Void> callback) {\n        Util.checkLooperThread(\"Asynchronous confirmation of a user is only possible from looper threads.\");\n        return new Request<Void>(NETWORK_POOL_EXECUTOR, callback) {\n            @Override\n            public Void run() throws AppException {\n                confirmUser(token, tokenId);\n                return null;\n            }\n        }.start();\n    }\n\n    /**\n     * Resend the confirmation for a user to the given email.\n     *\n     * @param email the email of the user.\n     * @throws AppException if the server failed to confirm the user.\n     */\n    public void resendConfirmationEmail(String email) throws AppException {\n        Util.checkEmpty(email, \"email\");\n        new VoidNetworkRequest() {\n            @Override\n            protected void execute(NetworkRequest<Void> callback) {\n                call(TYPE_RESEND_CONFIRMATION_EMAIL, callback, email);\n            }\n        }.execute();\n    }\n\n    /**\n     * Resend the confirmation for a user to the given email.\n     *\n     * @param email the email of the user.\n     * @param callback callback when resending the email has completed or failed. The callback will\n     * always happen on the same thread as this method is called on.\n     * @throws IllegalStateException if called from a non-looper thread.\n     */\n    public RealmAsyncTask resendConfirmationEmailAsync(String email, App.Callback<Void> callback) {\n        Util.checkLooperThread(\"Asynchronous resending the confirmation email is only possible from looper threads.\");\n        return new Request<Void>(NETWORK_POOL_EXECUTOR, callback) {\n            @Override\n            public Void run() throws AppException {\n                resendConfirmationEmail(email);\n                return null;\n            }\n        }.start();\n    }\n\n    /**\n     * Retries the custom confirmation on a user for a given email.\n     *\n     * @param email the email of the user.\n     * @throws AppException if the server failed to confirm the user.\n     */\n    public void retryCustomConfirmation(String email) throws AppException {\n        Util.checkEmpty(email, \"email\");\n        new VoidNetworkRequest() {\n            @Override\n            protected void execute(NetworkRequest<Void> callback) {\n                call(TYPE_RETRY_CUSTOM_CONFIRMATION, callback, email);\n            }\n        }.execute();\n    }\n\n    /**\n     * Retries the custom confirmation on a user for a given email.\n     *\n     * @param email the email of the user.\n     * @param callback callback when retrying the custom confirmation has completed or failed. The callback will\n     * always happen on the same thread as this method is called on.\n     * @throws IllegalStateException if called from a non-looper thread.\n     */\n    public RealmAsyncTask retryCustomConfirmationAsync(String email, App.Callback<Void> callback) {\n        Util.checkLooperThread(\"Asynchronous retry custom confirmation is only possible from looper threads.\");\n        return new Request<Void>(NETWORK_POOL_EXECUTOR, callback) {\n            @Override\n            public Void run() throws AppException {\n                retryCustomConfirmation(email);\n                return null;\n            }\n        }.start();\n    }\n\n    /**\n     * Sends a user a password reset email for the given email.\n     *\n     * @param email the email of the user.\n     * @throws AppException if the server failed to confirm the user.\n     */\n    public void sendResetPasswordEmail(String email) throws AppException {\n        Util.checkEmpty(email, \"email\");\n        new VoidNetworkRequest() {\n            @Override\n            protected void execute(NetworkRequest<Void> callback) {\n                call(TYPE_SEND_RESET_PASSWORD_EMAIL, callback, email);\n            }\n        }.execute();\n    }\n\n    /**\n     * Sends a user a password reset email for the given email.\n     *\n     * @param email the email of the user.\n     * @param callback callback when sending the email has completed or failed. The callback will\n     * always happen on the same thread as this method is called on.\n     * @throws AppException if the server failed to confirm the user.\n     */\n    public RealmAsyncTask sendResetPasswordEmailAsync(String email, App.Callback<Void> callback) {\n        Util.checkLooperThread(\"Asynchronous sending the reset password email is only possible from looper threads.\");\n        return new Request<Void>(NETWORK_POOL_EXECUTOR, callback) {\n            @Override\n            public Void run() throws AppException {\n                sendResetPasswordEmail(email);\n                return null;\n            }\n        }.start();\n    }\n\n    /**\n     * Call the reset password function configured to the\n     * {@link Credentials.Provider#EMAIL_PASSWORD} provider.\n     *\n     * @param email the email of the user.\n     * @param newPassword the new password of the user.\n     * @param args any additional arguments provided to the reset function. All arguments must\n     * be able to be converted to JSON compatible values using {@code toString()}.\n     * @throws AppException if the server failed to confirm the user.\n     */\n    public void callResetPasswordFunction(String email, String newPassword, Object... args) throws AppException {\n        Util.checkEmpty(email, \"email\");\n        Util.checkEmpty(newPassword, \"newPassword\");\n        String encodedArgs = JniBsonProtocol.encode(Arrays.asList(args), app.getConfiguration().getDefaultCodecRegistry());\n        new VoidNetworkRequest() {\n            @Override\n            protected void execute(NetworkRequest<Void> callback) {\n                call(TYPE_CALL_RESET_PASSWORD_FUNCTION, callback, email, newPassword, encodedArgs);\n            }\n        }.execute();\n    }\n\n    /**\n     * Call the reset password function configured to the\n     * {@link Credentials.Provider#EMAIL_PASSWORD} provider.\n     *\n     * @param email the email of the user.\n     * @param newPassword the new password of the user.\n     * @param args any additional arguments provided to the reset function. All arguments must\n     * be able to be converted to JSON compatible values using {@code toString()}.\n     * @param callback callback when the reset has completed or failed. The callback will always\n     * happen on the same thread as this this method is called on.\n     * @throws IllegalStateException if called from a non-looper thread.\n     */\n    public RealmAsyncTask callResetPasswordFunctionAsync(String email, String newPassword, Object[] args, App.Callback<Void> callback) {\n        Util.checkLooperThread(\"Asynchronous calling the password reset function is only possible from looper threads.\");\n        return new Request<Void>(NETWORK_POOL_EXECUTOR, callback) {\n            @Override\n            public Void run() throws AppException {\n                callResetPasswordFunction(email, newPassword, args);\n                return null;\n            }\n        }.start();\n    }\n\n    /**\n     * Resets the password of a user with the given token, token id, and new password.\n     *\n     * @param token the reset password token.\n     * @param tokenId the id of the reset password token.\n     * @param newPassword the new password for the user identified by the {@code token}. The password\n     * must be between 6 and 128 characters long.\n     * @throws AppException if the server failed to confirm the user.\n     */\n    public void resetPassword(String token, String tokenId, String newPassword) throws AppException {\n        Util.checkEmpty(token, \"token\");\n        Util.checkEmpty(tokenId, \"tokenId\");\n        Util.checkEmpty(newPassword, \"newPassword\");\n        new VoidNetworkRequest() {\n            @Override\n            protected void execute(NetworkRequest<Void> callback) {\n                // The order of arguments in ObjectStore is different than the order of arguments in the\n                // Java API. The Java API order came from the old Stitch API.\n                call(TYPE_RESET_PASSWORD, callback, newPassword, token, tokenId);\n            }\n        }.execute();\n    }\n\n    /**\n     * Resets the newPassword of a user with the given token, token id, and new password.\n     *\n     * @param token the reset password token.\n     * @param tokenId the id of the reset password token.\n     * @param newPassword the new password for the user identified by the {@code token}. The password\n     * must be between 6 and 128 characters long.\n     * @param callback callback when the reset has completed or failed. The callback will always\n     * happen on the same thread as this this method is called on.\n     * @throws IllegalStateException if called from a non-looper thread.\n     */\n    public RealmAsyncTask resetPasswordAsync(String token, String tokenId, String newPassword, App.Callback<Void> callback) {\n        Util.checkLooperThread(\"Asynchronous reset of a password is only possible from looper threads.\");\n        return new Request<Void>(NETWORK_POOL_EXECUTOR, callback) {\n            @Override\n            public Void run() throws AppException {\n                resetPassword(token, tokenId, newPassword);\n                return null;\n            }\n        }.start();\n    }\n\n    protected abstract void call(int functionType, OsJavaNetworkTransport.NetworkTransportJNIResultCallback callback, String... args);\n\n}\n"
  },
  {
    "path": "realm/realm-library/src/objectServer/java/io/realm/mongodb/auth/GoogleAuthType.java",
    "content": "/*\n * Copyright 2020 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\npackage io.realm.mongodb.auth;\n\n/**\n * This enum contains the list of Google authentication types supported by MongoDB Realm.\n *\n * @see <a href=\"https://docs.mongodb.com/realm/authentication/google\">Google Authentication</a>\n */\npublic enum GoogleAuthType {\n    AUTH_CODE,\n    ID_TOKEN\n}\n"
  },
  {
    "path": "realm/realm-library/src/objectServer/java/io/realm/mongodb/functions/Functions.java",
    "content": "/*\n * Copyright 2020 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\npackage io.realm.mongodb.functions;\n\nimport org.bson.codecs.Decoder;\nimport org.bson.codecs.configuration.CodecRegistry;\n\nimport java.util.List;\n\nimport io.realm.RealmAsyncTask;\nimport io.realm.annotations.Beta;\nimport io.realm.internal.Util;\nimport io.realm.internal.jni.JniBsonProtocol;\nimport io.realm.internal.mongodb.Request;\nimport io.realm.mongodb.App;\nimport io.realm.mongodb.AppConfiguration;\nimport io.realm.mongodb.AppException;\nimport io.realm.mongodb.User;\n\n/**\n * A <i>Functions</i> manager to call remote Realm functions for the associated Realm App.\n * <p>\n * Arguments and results are encoded/decoded with the <i>Functions'</i> codec registry either\n * inherited from the {@link AppConfiguration#getDefaultCodecRegistry()} or set explicitly\n * when creating the <i>Functions</i>-instance through {@link User#getFunctions(CodecRegistry)}\n * or through the individual calls to {@link #callFunction(String, List, Class, CodecRegistry)}.\n *\n * @see User#getFunctions()\n * @see User#getFunctions(CodecRegistry)\n * @see App#getFunctions(User)\n * @see App#getFunctions(User, CodecRegistry)\n * @see AppConfiguration\n * @see CodecRegistry\n */\n@Beta\npublic abstract class Functions {\n\n    protected User user;\n\n    private CodecRegistry defaultCodecRegistry;\n\n    protected Functions(User user, CodecRegistry codecRegistry) {\n        this.user = user;\n        this.defaultCodecRegistry = codecRegistry;\n    }\n\n    /**\n     * Call a MongoDB Realm function synchronously with custom codec registry encoding/decoding\n     * arguments/results.\n     *\n     * @param name Name of the Realm function to call.\n     * @param args Arguments to the Realm function.\n     * @param resultClass  The type that the functions result should be converted to.\n     * @param codecRegistry Codec registry to use for argument encoding and result decoding.\n     * @param <ResultT> The type that the response will be decoded as using the {@code codecRegistry}.\n     * @return Result of the Realm function.\n     *\n     * @throws AppException if the request failed in some way.\n     *\n     * @see #callFunctionAsync(String, List, Class, CodecRegistry, App.Callback)\n     * @see AppConfiguration#getDefaultCodecRegistry()\n     */\n    public <ResultT> ResultT callFunction(String name, List<?> args, Class<ResultT> resultClass, CodecRegistry codecRegistry) {\n        return invoke(name, args, codecRegistry, JniBsonProtocol.getCodec(resultClass, codecRegistry));\n    }\n\n    /**\n     * Call a MongoDB Realm function synchronously with default codec registry encoding/decoding\n     * arguments/results.\n     *\n     * @param name Name of the Realm function to call.\n     * @param args Arguments to the Realm function.\n     * @param resultClass  The type that the functions result should be converted to.\n     * @param <ResultT> The type that the response will be decoded as using the default codec registry.\n     * @return Result of the Realm function.\n     *\n     * @throws AppException if the request failed in some way.\n     *\n     * @see #callFunction(String, List, Class, CodecRegistry)\n     * @see AppConfiguration#getDefaultCodecRegistry()\n     */\n    public <ResultT> ResultT callFunction(String name, List<?> args, Class<ResultT> resultClass) {\n        return callFunction(name, args, resultClass, defaultCodecRegistry);\n    }\n\n    /**\n     * Call a MongoDB Realm function synchronously with custom result decoder.\n     * <p>\n     * The arguments will be encoded with the default codec registry encoding.\n     *\n     * @param name Name of the Realm function to call.\n     * @param args Arguments to the Realm function.\n     * @param resultDecoder The decoder used to decode the result.\n     * @param <ResultT> The type that the response will be decoded as using the {@code resultDecoder}\n     * @return Result of the Realm function.\n     *\n     * @throws AppException if the request failed in some way.\n     *\n     * @see #callFunction(String, List, Class, CodecRegistry)\n     * @see AppConfiguration#getDefaultCodecRegistry()\n     */\n    public <ResultT> ResultT callFunction(String name, List<?> args, Decoder<ResultT> resultDecoder) {\n        return invoke(name, args, defaultCodecRegistry, resultDecoder);\n    }\n\n    /**\n     * Call a MongoDB Realm function asynchronously with custom codec registry for encoding/decoding\n     * arguments/results.\n     * <p>\n     * This is the asynchronous equivalent of {@link #callFunction(String, List, Class, CodecRegistry)}.\n     *\n     * @param name Name of the Realm function to call.\n     * @param args Arguments to the Realm function.\n     * @param resultClass  The type that the functions result should be converted to.\n     * @param codecRegistry Codec registry to use for argument encoding and result decoding.\n     * @param callback The callback that will receive the result or any errors from the request.\n     * @param <T> The type that the response will be decoded as using the default codec registry.\n     * @return The task representing the ongoing operation.\n     *\n     * @throws IllegalStateException if not called on a looper thread.\n     *\n     * @see #callFunction(String, List, Class, CodecRegistry)\n     * @see #callFunctionAsync(String, List, Class, CodecRegistry, App.Callback)\n     * @see AppConfiguration#getDefaultCodecRegistry()\n     */\n    public <T> RealmAsyncTask callFunctionAsync(String name, List<?> args, Class<T> resultClass, CodecRegistry codecRegistry, App.Callback<T> callback) {\n        Util.checkLooperThread(\"Asynchronous functions is only possible from looper threads.\");\n        return new Request<T>(App.NETWORK_POOL_EXECUTOR, callback) {\n            @Override\n            public T run() throws AppException {\n                Decoder<T> decoder = JniBsonProtocol.getCodec(resultClass, codecRegistry);\n                return invoke(name, args, codecRegistry, decoder);\n            }\n        }.start();\n    }\n\n    /**\n     * Call a MongoDB Realm function asynchronously with custom codec registry for encoding/decoding\n     * arguments/results.\n     * <p>\n     * This is the asynchronous equivalent of {@link #callFunction(String, List, Class)}.\n     *\n     * @param name Name of the Realm function to call.\n     * @param args Arguments to the Realm function.\n     * @param resultClass  The type that the functions result should be converted to.\n     * @param callback The callback that will receive the result or any errors from the request.\n     * @param <T> The type that the response will be decoded as using the default codec registry.\n     * @return The task representing the ongoing operation.\n     *\n     * @throws IllegalStateException if not called on a looper thread.\n     *\n     * @see #callFunction(String, List, Class)\n     * @see #callFunctionAsync(String, List, Class, CodecRegistry, App.Callback)\n     * @see AppConfiguration#getDefaultCodecRegistry()\n     */\n    public <T> RealmAsyncTask callFunctionAsync(String name, List<?> args, Class<T> resultClass, App.Callback<T> callback) {\n        return callFunctionAsync(name, args, resultClass, defaultCodecRegistry, callback);\n    }\n\n    /**\n     * Call a MongoDB Realm function asynchronously with custom result decoder.\n     * <p>\n     * This is the asynchronous equivalent of {@link #callFunction(String, List, Decoder)}.\n     *\n     * @param name Name of the Realm function to call.\n     * @param args Arguments to the Realm function.\n     * @param resultDecoder The decoder used to decode the result.\n     * @param callback The callback that will receive the result or any errors from the request.\n     * @param <T> The type that the response will be decoded as using the {@code resultDecoder}\n     * @return The task representing the ongoing operation.\n     *\n     * @throws IllegalStateException if not called on a looper thread.\n     *\n     * @see #callFunction(String, List, Class)\n     * @see #callFunctionAsync(String, List, Class, CodecRegistry, App.Callback)\n     * @see AppConfiguration#getDefaultCodecRegistry()\n     */\n    public <T> RealmAsyncTask callFunctionAsync(String name, List<?> args, Decoder<T> resultDecoder, App.Callback<T> callback) {\n        Util.checkLooperThread(\"Asynchronous functions is only possible from looper threads.\");\n        return new Request<T>(App.NETWORK_POOL_EXECUTOR, callback) {\n            @Override\n            public T run() throws AppException {\n                return invoke(name, args, defaultCodecRegistry, resultDecoder);\n            }\n        }.start();\n    }\n\n    /**\n     * Returns the default codec registry used for encoding arguments and decoding results for this\n     * <i>Realm functions</i> instance.\n     *\n     * @return The default codec registry.\n     */\n    public CodecRegistry getDefaultCodecRegistry() {\n        return defaultCodecRegistry;\n    }\n\n    /**\n     * Returns the {@link App} that this instance in associated with.\n     *\n     * @return The {@link App} that this instance in associated with.\n     */\n    public App getApp() {\n        return user.getApp();\n    }\n\n    /**\n     * Returns the {@link User} that this instance in associated with.\n     *\n     * @return The {@link User} that this instance in associated with.\n     */\n    public User getUser() {\n        return user;\n    }\n\n    protected abstract <T> T invoke(String name, List<?> args, CodecRegistry codecRegistry, Decoder<T> resultDecoder);\n\n}\n"
  },
  {
    "path": "realm/realm-library/src/objectServer/java/io/realm/mongodb/log/obfuscator/HttpLogObfuscator.java",
    "content": "/*\n * Copyright 2020 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\npackage io.realm.mongodb.log.obfuscator;\n\nimport java.util.List;\nimport java.util.Map;\n\nimport io.realm.internal.Util;\nimport io.realm.internal.log.obfuscator.RegexPatternObfuscator;\n\n/**\n * The HttpLogObfuscator keeps sensitive information from being displayed in Logcat.\n */\npublic class HttpLogObfuscator {\n\n    private String feature;\n    private Map<String, RegexPatternObfuscator> patternObfuscatorMap;\n\n    /**\n     * Constructor for creating an HTTP log obfuscator.\n     *\n     * @param feature              the feature to obfuscate, e.g. \"providers\" for login requests -\n     *                             see {@link io.realm.internal.network.LoggingInterceptor}.\n     * @param patternObfuscatorMap {@link Map} of keys subject to being obfuscated and\n     *                             {@link RegexPatternObfuscator}s used to determine which\n     *                             obfuscator has to be used for the given feature.\n     */\n    public HttpLogObfuscator(String feature, Map<String, RegexPatternObfuscator> patternObfuscatorMap) {\n        Util.checkNull(feature, \"feature\");\n        this.feature = feature;\n        Util.checkNull(patternObfuscatorMap, \"patternObfuscatorMap\");\n        this.patternObfuscatorMap = patternObfuscatorMap;\n    }\n\n    /**\n     * Obfuscates a logcat entry or not depending on whether the request being sent matches the\n     * specified feature. If it doesn't, the logcat entry will be returned unmodified.\n     *\n     * @param urlSegments the URL segments of the request to be sent.\n     * @param input       the original logcat entry.\n     * @return the logcat entry to be shown in the logcat.\n     */\n    public String obfuscate(List<String> urlSegments, String input) {\n        int featureIndex = urlSegments.indexOf(feature);\n        if (featureIndex != -1) {\n            String value = urlSegments.get(featureIndex + 1);    // value is in the next segment\n            RegexPatternObfuscator patternObfuscator = patternObfuscatorMap.get(value);\n            if (patternObfuscator != null) {\n                return patternObfuscator.obfuscate(input);\n            }\n        }\n        return input;\n    }\n\n    @Override\n    public boolean equals(Object o) {\n        if (this == o) return true;\n        if (!(o instanceof HttpLogObfuscator)) return false;\n        HttpLogObfuscator that = (HttpLogObfuscator) o;\n        return patternObfuscatorMap.equals(that.patternObfuscatorMap);\n    }\n\n    @Override\n    public int hashCode() {\n        return patternObfuscatorMap.hashCode() + 13;\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/objectServer/java/io/realm/mongodb/mongo/MongoClient.java",
    "content": "/*\n * Copyright 2020 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\npackage io.realm.mongodb.mongo;\n\nimport org.bson.codecs.configuration.CodecRegistry;\n\nimport io.realm.annotations.Beta;\nimport io.realm.internal.Util;\nimport io.realm.internal.objectstore.OsMongoClient;\n\n/**\n * The remote MongoClient used for working with data in MongoDB remotely via Realm.\n */\n@Beta\npublic abstract class MongoClient {\n\n    private final OsMongoClient osMongoClient;\n    private final CodecRegistry codecRegistry;\n\n    protected MongoClient(final OsMongoClient osMongoClient,\n                          final CodecRegistry codecRegistry) {\n        this.osMongoClient = osMongoClient;\n        this.codecRegistry = codecRegistry;\n    }\n\n    /**\n     * Gets a {@link MongoDatabase} instance for the given database name.\n     *\n     * @param databaseName the name of the database to retrieve\n     * @return a {@code RemoteMongoDatabase} representing the specified database\n     */\n    public MongoDatabase getDatabase(final String databaseName) {\n        Util.checkEmpty(databaseName, \"databaseName\");\n        return new MongoDatabase(osMongoClient.getDatabase(databaseName, codecRegistry),\n                databaseName);\n    }\n\n    /**\n     * Returns the service name for this client.\n     *\n     * @return the service name.\n     */\n    public String getServiceName() {\n        return osMongoClient.getServiceName();\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/objectServer/java/io/realm/mongodb/mongo/MongoCollection.java",
    "content": "/*\n * Copyright 2020 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\npackage io.realm.mongodb.mongo;\n\nimport org.bson.BsonDocument;\nimport org.bson.BsonObjectId;\nimport org.bson.BsonValue;\nimport org.bson.Document;\nimport org.bson.codecs.configuration.CodecRegistry;\nimport org.bson.conversions.Bson;\nimport org.bson.types.ObjectId;\n\nimport java.io.IOException;\nimport java.util.Arrays;\nimport java.util.List;\nimport java.util.concurrent.ThreadPoolExecutor;\n\nimport javax.annotation.Nullable;\n\nimport io.realm.annotations.Beta;\nimport io.realm.internal.async.RealmEventStreamAsyncTaskImpl;\nimport io.realm.internal.async.RealmEventStreamTaskImpl;\nimport io.realm.internal.async.RealmResultTaskImpl;\nimport io.realm.internal.objectserver.EventStream;\nimport io.realm.internal.objectstore.OsMongoCollection;\nimport io.realm.mongodb.App;\nimport io.realm.mongodb.RealmEventStreamAsyncTask;\nimport io.realm.mongodb.RealmEventStreamTask;\nimport io.realm.mongodb.RealmResultTask;\nimport io.realm.mongodb.mongo.iterable.AggregateIterable;\nimport io.realm.mongodb.mongo.iterable.FindIterable;\nimport io.realm.mongodb.mongo.options.CountOptions;\nimport io.realm.mongodb.mongo.options.FindOneAndModifyOptions;\nimport io.realm.mongodb.mongo.options.FindOptions;\nimport io.realm.mongodb.mongo.options.InsertManyResult;\nimport io.realm.mongodb.mongo.options.UpdateOptions;\nimport io.realm.mongodb.mongo.result.DeleteResult;\nimport io.realm.mongodb.mongo.result.InsertOneResult;\nimport io.realm.mongodb.mongo.result.UpdateResult;\n\n/**\n * The MongoCollection interface provides read and write access to documents.\n * <p>\n * Use {@link MongoDatabase#getCollection} to get a collection instance.\n * </p><p>\n * Before any access is possible, there must be an active, logged-in user.\n *\n * @param <DocumentT> The type that this collection will encode documents from and decode documents\n *                    to.\n * @see MongoDatabase\n */\n@Beta\npublic class MongoCollection<DocumentT> {\n\n    private final MongoNamespace nameSpace;\n    private final OsMongoCollection<DocumentT> osMongoCollection;\n    private final ThreadPoolExecutor threadPoolExecutor = App.NETWORK_POOL_EXECUTOR;\n\n    MongoCollection(final MongoNamespace nameSpace,\n                    final OsMongoCollection<DocumentT> osMongoCollection) {\n        this.nameSpace = nameSpace;\n        this.osMongoCollection = osMongoCollection;\n    }\n\n    /**\n     * Gets the namespace of this collection, i.e. the database and collection names together.\n     *\n     * @return the namespace\n     */\n    public MongoNamespace getNamespace() {\n        return nameSpace;\n    }\n\n    /**\n     * Gets the name of this collection\n     *\n     * @return the name\n     */\n    public String getName() {\n        return nameSpace.getCollectionName();\n    }\n\n    /**\n     * Gets the class of documents stored in this collection.\n     * <p>\n     * If you used the simple {@link MongoDatabase#getCollection(String)} to get this collection,\n     * this is {@link org.bson.Document}.\n     * </p>\n     *\n     * @return the class of documents in this collection\n     */\n    public Class<DocumentT> getDocumentClass() {\n        return osMongoCollection.getDocumentClass();\n    }\n\n    /**\n     * Gets the codec registry for the MongoCollection.\n     *\n     * @return the {@link CodecRegistry} for this collection\n     */\n    public CodecRegistry getCodecRegistry() {\n        return osMongoCollection.getCodecRegistry();\n    }\n\n    /**\n     * Creates a new MongoCollection instance with a different default class to cast any\n     * documents returned from the database into.\n     *\n     * @param clazz          the default class to which any documents returned from the database\n     *                       will be cast.\n     * @param <NewDocumentT> The type that the new collection will encode documents from and decode\n     *                       documents to.\n     * @return a new MongoCollection instance with the different default class\n     */\n    public <NewDocumentT> MongoCollection<NewDocumentT> withDocumentClass(\n            final Class<NewDocumentT> clazz) {\n        return new MongoCollection<>(nameSpace, osMongoCollection.withDocumentClass(clazz));\n    }\n\n    /**\n     * Creates a new MongoCollection instance with a different codec registry.\n     *\n     * @param codecRegistry the new {@link CodecRegistry} for the\n     *                      collection.\n     * @return a new MongoCollection instance with the different codec registry\n     */\n    public MongoCollection<DocumentT> withCodecRegistry(final CodecRegistry codecRegistry) {\n        return new MongoCollection<>(nameSpace, osMongoCollection.withCodecRegistry(codecRegistry));\n    }\n\n    /**\n     * Counts the number of documents in the collection.\n     *\n     * @return a task containing the number of documents in the collection\n     */\n    public RealmResultTask<Long> count() {\n        return new RealmResultTaskImpl<>(threadPoolExecutor, new RealmResultTaskImpl.Executor<Long>() {\n            @Nullable\n            @Override\n            public Long run() {\n                return osMongoCollection.count();\n            }\n        });\n    }\n\n    /**\n     * Counts the number of documents in the collection according to the given options.\n     *\n     * @param filter the query filter\n     * @return a task containing the number of documents in the collection\n     */\n    public RealmResultTask<Long> count(final Bson filter) {\n        return new RealmResultTaskImpl<>(threadPoolExecutor, new RealmResultTaskImpl.Executor<Long>() {\n            @Nullable\n            @Override\n            public Long run() {\n                return osMongoCollection.count(filter);\n            }\n        });\n    }\n\n    /**\n     * Counts the number of documents in the collection according to the given options.\n     *\n     * @param filter  the query filter\n     * @param options the options describing the count\n     * @return a task containing the number of documents in the collection\n     */\n    public RealmResultTask<Long> count(final Bson filter, final CountOptions options) {\n        return new RealmResultTaskImpl<>(threadPoolExecutor, new RealmResultTaskImpl.Executor<Long>() {\n            @Nullable\n            @Override\n            public Long run() {\n                return osMongoCollection.count(filter, options);\n            }\n        });\n    }\n\n    /**\n     * Finds a document in the collection.\n     *\n     * @return a task containing the result of the find one operation\n     */\n    public RealmResultTask<DocumentT> findOne() {\n        return new RealmResultTaskImpl<>(threadPoolExecutor, new RealmResultTaskImpl.Executor<DocumentT>() {\n            @Nullable\n            @Override\n            public DocumentT run() {\n                return osMongoCollection.findOne();\n            }\n        });\n    }\n\n    /**\n     * Finds a document in the collection.\n     *\n     * @param resultClass the class to decode each document into\n     * @param <ResultT>   the target document type\n     * @return a task containing the result of the find one operation\n     */\n    public <ResultT> RealmResultTask<ResultT> findOne(final Class<ResultT> resultClass) {\n        return new RealmResultTaskImpl<>(threadPoolExecutor, new RealmResultTaskImpl.Executor<ResultT>() {\n            @Nullable\n            @Override\n            public ResultT run() {\n                return osMongoCollection.findOne(resultClass);\n            }\n        });\n    }\n\n    /**\n     * Finds a document in the collection.\n     *\n     * @param filter the query filter\n     * @return a task containing the result of the find one operation\n     */\n    public RealmResultTask<DocumentT> findOne(final Bson filter) {\n        return new RealmResultTaskImpl<>(threadPoolExecutor, new RealmResultTaskImpl.Executor<DocumentT>() {\n            @Nullable\n            @Override\n            public DocumentT run() {\n                return osMongoCollection.findOne(filter);\n            }\n        });\n    }\n\n    /**\n     * Finds a document in the collection.\n     *\n     * @param filter      the query filter\n     * @param resultClass the class to decode each document into\n     * @param <ResultT>   the target document type of the iterable.\n     * @return a task containing the result of the find one operation\n     */\n    public <ResultT> RealmResultTask<ResultT> findOne(final Bson filter, final Class<ResultT> resultClass) {\n        return new RealmResultTaskImpl<>(threadPoolExecutor, new RealmResultTaskImpl.Executor<ResultT>() {\n            @Nullable\n            @Override\n            public ResultT run() {\n                return osMongoCollection.findOne(filter, resultClass);\n            }\n        });\n    }\n\n    /**\n     * Finds a document in the collection.\n     *\n     * @param filter  the query filter\n     * @param options a {@link FindOptions} struct\n     * @return a task containing the result of the find one operation\n     */\n    public RealmResultTask<DocumentT> findOne(final Bson filter, final FindOptions options) {\n        return new RealmResultTaskImpl<>(threadPoolExecutor, new RealmResultTaskImpl.Executor<DocumentT>() {\n            @Nullable\n            @Override\n            public DocumentT run() {\n                return osMongoCollection.findOne(filter, options);\n            }\n        });\n    }\n\n    /**\n     * Finds a document in the collection.\n     *\n     * @param filter      the query filter\n     * @param options     a {@link FindOptions} struct\n     * @param resultClass the class to decode each document into\n     * @param <ResultT>   the target document type of the iterable.\n     * @return a task containing the result of the find one operation\n     */\n    public <ResultT> RealmResultTask<ResultT> findOne(final Bson filter,\n                                                      final FindOptions options,\n                                                      final Class<ResultT> resultClass) {\n        return new RealmResultTaskImpl<>(threadPoolExecutor, new RealmResultTaskImpl.Executor<ResultT>() {\n            @Nullable\n            @Override\n            public ResultT run() {\n                return osMongoCollection.findOne(filter, options, resultClass);\n            }\n        });\n    }\n\n    /**\n     * Finds all documents in the collection.\n     * <p>\n     * All documents will be delivered in the form of a {@link FindIterable} from which individual\n     * elements can be extracted.\n     *\n     * @return an iterable containing the result of the find operation\n     */\n    public FindIterable<DocumentT> find() {\n        return osMongoCollection.find();\n    }\n\n    /**\n     * Finds all documents in the collection using {@link FindOptions} to build the query.\n     * <p>\n     * All documents will be delivered in the form of a {@link FindIterable} from which individual\n     * elements can be extracted.\n     *\n     * @param options a {@link FindOptions} struct for building the query\n     * @return an iterable containing the result of the find operation\n     */\n    public FindIterable<DocumentT> find(final FindOptions options) {\n        return osMongoCollection.find(options);\n    }\n\n    /**\n     * Finds all documents in the collection specifying an output class.\n     * <p>\n     * All documents will be delivered in the form of a {@link FindIterable} from which individual\n     * elements can be extracted.\n     *\n     * @param resultClass the class to decode each document into\n     * @param <ResultT>   the target document type of the iterable.\n     * @return an iterable containing the result of the find operation\n     */\n    public <ResultT> FindIterable<ResultT> find(final Class<ResultT> resultClass) {\n        return osMongoCollection.find(resultClass);\n    }\n\n    /**\n     * Finds all documents in the collection specifying an output class and also using\n     * {@link FindOptions} to build the query.\n     * <p>\n     * All documents will be delivered in the form of a {@link FindIterable} from which individual\n     * elements can be extracted.\n     *\n     * @param resultClass the class to decode each document into\n     * @param options     a {@link FindOptions} struct for building the query\n     * @param <ResultT>   the target document type of the iterable.\n     * @return an iterable containing the result of the find operation\n     */\n    public <ResultT> FindIterable<ResultT> find(final Class<ResultT> resultClass,\n                                                final FindOptions options) {\n        return osMongoCollection.find(resultClass, options);\n    }\n\n    /**\n     * Finds all documents in the collection that match the given filter.\n     * <p>\n     * All documents will be delivered in the form of a {@link FindIterable} from which individual\n     * elements can be extracted.\n     *\n     * @param filter the query filter\n     * @return an iterable containing the result of the find operation\n     */\n    public FindIterable<DocumentT> find(final Bson filter) {\n        return osMongoCollection.find(filter);\n    }\n\n    /**\n     * Finds all documents in the collection that match the given filter using {@link FindOptions}\n     * to build the query.\n     * <p>\n     * All documents will be delivered in the form of a {@link FindIterable} from which individual\n     * elements can be extracted.\n     *\n     * @param filter  the query filter\n     * @param options a {@link FindOptions} struct\n     * @return an iterable containing the result of the find operation\n     */\n    public FindIterable<DocumentT> find(final Bson filter, final FindOptions options) {\n        return osMongoCollection.find(filter, options);\n    }\n\n    /**\n     * Finds all documents in the collection that match the given filter specifying an output class.\n     * <p>\n     * All documents will be delivered in the form of a {@link FindIterable} from which individual\n     * elements can be extracted.\n     *\n     * @param filter      the query filter\n     * @param resultClass the class to decode each document into\n     * @param <ResultT>   the target document type of the iterable.\n     * @return an iterable containing the result of the find operation\n     */\n    public <ResultT> FindIterable<ResultT> find(final Bson filter,\n                                                final Class<ResultT> resultClass) {\n        return osMongoCollection.find(filter, resultClass);\n    }\n\n    /**\n     * Finds all documents in the collection that match the given filter specifying an output class\n     * and also using {@link FindOptions} to build the query.\n     * <p>\n     * All documents will be delivered in the form of a {@link FindIterable} from which individual\n     * elements can be extracted.\n     *\n     * @param filter      the query filter\n     * @param resultClass the class to decode each document into\n     * @param options     a {@link FindOptions} struct\n     * @param <ResultT>   the target document type of the iterable.\n     * @return an iterable containing the result of the find operation\n     */\n    public <ResultT> FindIterable<ResultT> find(final Bson filter,\n                                                final Class<ResultT> resultClass,\n                                                final FindOptions options) {\n        return osMongoCollection.find(filter, resultClass, options);\n    }\n\n    /**\n     * Aggregates documents according to the specified aggregation pipeline.\n     * <p>\n     * All documents will be delivered in the form of an {@link AggregateIterable} from which\n     * individual elements can be extracted.\n     *\n     * @param pipeline the aggregation pipeline\n     * @return an {@link AggregateIterable} from which the results can be extracted\n     */\n    public AggregateIterable<DocumentT> aggregate(final List<? extends Bson> pipeline) {\n        return osMongoCollection.aggregate(pipeline);\n    }\n\n    /**\n     * Aggregates documents according to the specified aggregation pipeline specifying an output\n     * class.\n     * <p>\n     * All documents will be delivered in the form of an {@link AggregateIterable} from which\n     * individual elements can be extracted.\n     *\n     * @param pipeline    the aggregation pipeline\n     * @param resultClass the class to decode each document into\n     * @param <ResultT>   the target document type of the iterable.\n     * @return an {@link AggregateIterable} from which the results can be extracted\n     */\n    public <ResultT> AggregateIterable<ResultT> aggregate(final List<? extends Bson> pipeline,\n                                                          final Class<ResultT> resultClass) {\n        return osMongoCollection.aggregate(pipeline, resultClass);\n    }\n\n    /**\n     * Inserts the provided document. If the document is missing an identifier, the client should\n     * generate one.\n     *\n     * @param document the document to insert\n     * @return a task containing the result of the insert one operation\n     */\n    public RealmResultTask<InsertOneResult> insertOne(final DocumentT document) {\n        return new RealmResultTaskImpl<>(threadPoolExecutor, new RealmResultTaskImpl.Executor<InsertOneResult>() {\n            @Nullable\n            @Override\n            public InsertOneResult run() {\n                return osMongoCollection.insertOne(document);\n            }\n        });\n    }\n\n    /**\n     * Inserts one or more documents.\n     *\n     * @param documents the documents to insert\n     * @return a task containing the result of the insert many operation\n     */\n    public RealmResultTask<InsertManyResult> insertMany(final List<? extends DocumentT> documents) {\n        return new RealmResultTaskImpl<>(threadPoolExecutor, new RealmResultTaskImpl.Executor<InsertManyResult>() {\n            @Nullable\n            @Override\n            public InsertManyResult run() {\n                return osMongoCollection.insertMany(documents);\n            }\n        });\n    }\n\n    /**\n     * Removes at most one document from the collection that matches the given filter.  If no\n     * documents match, the collection is not\n     * modified.\n     *\n     * @param filter the query filter to apply the the delete operation\n     * @return a task containing the result of the remove one operation\n     */\n    public RealmResultTask<DeleteResult> deleteOne(final Bson filter) {\n        return new RealmResultTaskImpl<>(threadPoolExecutor, new RealmResultTaskImpl.Executor<DeleteResult>() {\n            @Nullable\n            @Override\n            public DeleteResult run() {\n                return osMongoCollection.deleteOne(filter);\n            }\n        });\n    }\n\n    /**\n     * Removes all documents from the collection that match the given query filter.  If no documents\n     * match, the collection is not modified.\n     *\n     * @param filter the query filter to apply the the delete operation\n     * @return a task containing the result of the remove many operation\n     */\n    public RealmResultTask<DeleteResult> deleteMany(final Bson filter) {\n        return new RealmResultTaskImpl<>(threadPoolExecutor, new RealmResultTaskImpl.Executor<DeleteResult>() {\n            @Nullable\n            @Override\n            public DeleteResult run() {\n                return osMongoCollection.deleteMany(filter);\n            }\n        });\n    }\n\n    /**\n     * Update a single document in the collection according to the specified arguments.\n     *\n     * @param filter a document describing the query filter, which may not be null.\n     * @param update a document describing the update, which may not be null. The update to\n     *               apply must include only update operators.\n     * @return a task containing the result of the update one operation\n     */\n    public RealmResultTask<UpdateResult> updateOne(final Bson filter, final Bson update) {\n        return new RealmResultTaskImpl<>(threadPoolExecutor, new RealmResultTaskImpl.Executor<UpdateResult>() {\n            @Nullable\n            @Override\n            public UpdateResult run() {\n                return osMongoCollection.updateOne(filter, update);\n            }\n        });\n    }\n\n    /**\n     * Update a single document in the collection according to the specified arguments.\n     *\n     * @param filter        a document describing the query filter, which may not be null.\n     * @param update        a document describing the update, which may not be null. The update to\n     *                      apply must include only update operators.\n     * @param updateOptions the options to apply to the update operation\n     * @return a task containing the result of the update one operation\n     */\n    public RealmResultTask<UpdateResult> updateOne(\n            final Bson filter,\n            final Bson update,\n            final UpdateOptions updateOptions) {\n        return new RealmResultTaskImpl<>(threadPoolExecutor, new RealmResultTaskImpl.Executor<UpdateResult>() {\n            @Nullable\n            @Override\n            public UpdateResult run() {\n                return osMongoCollection.updateOne(filter, update, updateOptions);\n            }\n        });\n    }\n\n    /**\n     * Update all documents in the collection according to the specified arguments.\n     *\n     * @param filter a document describing the query filter, which may not be null.\n     * @param update a document describing the update, which may not be null. The update to\n     *               apply must include only update operators.\n     * @return a task containing the result of the update many operation\n     */\n    public RealmResultTask<UpdateResult> updateMany(final Bson filter, final Bson update) {\n        return new RealmResultTaskImpl<>(threadPoolExecutor, new RealmResultTaskImpl.Executor<UpdateResult>() {\n            @Nullable\n            @Override\n            public UpdateResult run() {\n                return osMongoCollection.updateMany(filter, update);\n            }\n        });\n    }\n\n    /**\n     * Update all documents in the collection according to the specified arguments.\n     *\n     * @param filter        a document describing the query filter, which may not be null.\n     * @param update        a document describing the update, which may not be null. The update to\n     *                      apply must include only update operators.\n     * @param updateOptions the options to apply to the update operation\n     * @return a task containing the result of the update many operation\n     */\n    public RealmResultTask<UpdateResult> updateMany(\n            final Bson filter,\n            final Bson update,\n            final UpdateOptions updateOptions) {\n        return new RealmResultTaskImpl<>(threadPoolExecutor, new RealmResultTaskImpl.Executor<UpdateResult>() {\n            @Nullable\n            @Override\n            public UpdateResult run() {\n                return osMongoCollection.updateMany(filter, update, updateOptions);\n            }\n        });\n    }\n\n    /**\n     * Finds a document in the collection and performs the given update.\n     *\n     * @param filter the query filter\n     * @param update the update document\n     * @return a task containing the resulting document\n     */\n    public RealmResultTask<DocumentT> findOneAndUpdate(final Bson filter, final Bson update) {\n        return new RealmResultTaskImpl<>(threadPoolExecutor, new RealmResultTaskImpl.Executor<DocumentT>() {\n            @Nullable\n            @Override\n            public DocumentT run() {\n                return osMongoCollection.findOneAndUpdate(filter, update);\n            }\n        });\n    }\n\n    /**\n     * Finds a document in the collection and performs the given update.\n     *\n     * @param filter      the query filter\n     * @param update      the update document\n     * @param resultClass the class to decode each document into\n     * @param <ResultT>   the target document type of the iterable.\n     * @return a task containing the resulting document\n     */\n    public <ResultT> RealmResultTask<ResultT> findOneAndUpdate(final Bson filter,\n                                                               final Bson update,\n                                                               final Class<ResultT> resultClass) {\n        return new RealmResultTaskImpl<>(threadPoolExecutor, new RealmResultTaskImpl.Executor<ResultT>() {\n            @Nullable\n            @Override\n            public ResultT run() {\n                return osMongoCollection.findOneAndUpdate(filter, update, resultClass);\n            }\n        });\n    }\n\n    /**\n     * Finds a document in the collection and performs the given update.\n     *\n     * @param filter  the query filter\n     * @param update  the update document\n     * @param options a {@link FindOneAndModifyOptions} struct\n     * @return a task containing the resulting document\n     */\n    public RealmResultTask<DocumentT> findOneAndUpdate(final Bson filter,\n                                                       final Bson update,\n                                                       final FindOneAndModifyOptions options) {\n        return new RealmResultTaskImpl<>(threadPoolExecutor, new RealmResultTaskImpl.Executor<DocumentT>() {\n            @Nullable\n            @Override\n            public DocumentT run() {\n                return osMongoCollection.findOneAndUpdate(filter, update, options);\n            }\n        });\n    }\n\n    /**\n     * Finds a document in the collection and performs the given update.\n     *\n     * @param filter      the query filter\n     * @param update      the update document\n     * @param options     a {@link FindOneAndModifyOptions} struct\n     * @param resultClass the class to decode each document into\n     * @param <ResultT>   the target document type of the iterable.\n     * @return a task containing the resulting document\n     */\n    public <ResultT> RealmResultTask<ResultT> findOneAndUpdate(final Bson filter,\n                                                               final Bson update,\n                                                               final FindOneAndModifyOptions options,\n                                                               final Class<ResultT> resultClass) {\n        return new RealmResultTaskImpl<>(threadPoolExecutor, new RealmResultTaskImpl.Executor<ResultT>() {\n            @Nullable\n            @Override\n            public ResultT run() {\n                return osMongoCollection.findOneAndUpdate(filter, update, options, resultClass);\n            }\n        });\n    }\n\n    /**\n     * Finds a document in the collection and replaces it with the given document.\n     *\n     * @param filter      the query filter\n     * @param replacement the document to replace the matched document with\n     * @return a task containing the resulting document\n     */\n    public RealmResultTask<DocumentT> findOneAndReplace(final Bson filter, final Bson replacement) {\n        return new RealmResultTaskImpl<>(threadPoolExecutor, new RealmResultTaskImpl.Executor<DocumentT>() {\n            @Nullable\n            @Override\n            public DocumentT run() {\n                return osMongoCollection.findOneAndReplace(filter, replacement);\n            }\n        });\n    }\n\n    /**\n     * Finds a document in the collection and replaces it with the given document.\n     *\n     * @param filter      the query filter\n     * @param replacement the document to replace the matched document with\n     * @param resultClass the class to decode each document into\n     * @param <ResultT>   the target document type of the iterable.\n     * @return a task containing the resulting document\n     */\n    public <ResultT> RealmResultTask<ResultT> findOneAndReplace(final Bson filter,\n                                                                final Bson replacement,\n                                                                final Class<ResultT> resultClass) {\n        return new RealmResultTaskImpl<>(threadPoolExecutor, new RealmResultTaskImpl.Executor<ResultT>() {\n            @Nullable\n            @Override\n            public ResultT run() {\n                return osMongoCollection.findOneAndReplace(filter, replacement, resultClass);\n            }\n        });\n    }\n\n    /**\n     * Finds a document in the collection and replaces it with the given document.\n     *\n     * @param filter      the query filter\n     * @param replacement the document to replace the matched document with\n     * @param options     a {@link FindOneAndModifyOptions} struct\n     * @return a task containing the resulting document\n     */\n    public RealmResultTask<DocumentT> findOneAndReplace(final Bson filter,\n                                                        final Bson replacement,\n                                                        final FindOneAndModifyOptions options) {\n        return new RealmResultTaskImpl<>(threadPoolExecutor, new RealmResultTaskImpl.Executor<DocumentT>() {\n            @Nullable\n            @Override\n            public DocumentT run() {\n                return osMongoCollection.findOneAndReplace(filter, replacement, options);\n            }\n        });\n    }\n\n    /**\n     * Finds a document in the collection and replaces it with the given document.\n     *\n     * @param filter      the query filter\n     * @param replacement the document to replace the matched document with\n     * @param options     a {@link FindOneAndModifyOptions} struct\n     * @param resultClass the class to decode each document into\n     * @param <ResultT>   the target document type of the iterable.\n     * @return a task containing the resulting document\n     */\n    public <ResultT> RealmResultTask<ResultT> findOneAndReplace(final Bson filter,\n                                                                final Bson replacement,\n                                                                final FindOneAndModifyOptions options,\n                                                                final Class<ResultT> resultClass) {\n        return new RealmResultTaskImpl<>(threadPoolExecutor, new RealmResultTaskImpl.Executor<ResultT>() {\n            @Nullable\n            @Override\n            public ResultT run() {\n                return osMongoCollection.findOneAndReplace(filter, replacement, options, resultClass);\n            }\n        });\n    }\n\n    /**\n     * Finds a document in the collection and delete it.\n     *\n     * @param filter the query filter\n     * @return a task containing the resulting document\n     */\n    public RealmResultTask<DocumentT> findOneAndDelete(final Bson filter) {\n        return new RealmResultTaskImpl<>(threadPoolExecutor, new RealmResultTaskImpl.Executor<DocumentT>() {\n            @Nullable\n            @Override\n            public DocumentT run() {\n                return osMongoCollection.findOneAndDelete(filter);\n            }\n        });\n    }\n\n    /**\n     * Finds a document in the collection and delete it.\n     *\n     * @param filter      the query filter\n     * @param resultClass the class to decode each document into\n     * @param <ResultT>   the target document type of the iterable.\n     * @return a task containing the resulting document\n     */\n    public <ResultT> RealmResultTask<ResultT> findOneAndDelete(final Bson filter,\n                                                               final Class<ResultT> resultClass) {\n        return new RealmResultTaskImpl<>(threadPoolExecutor, new RealmResultTaskImpl.Executor<ResultT>() {\n            @Nullable\n            @Override\n            public ResultT run() {\n                return osMongoCollection.findOneAndDelete(filter, resultClass);\n            }\n        });\n    }\n\n    /**\n     * Finds a document in the collection and delete it.\n     *\n     * @param filter  the query filter\n     * @param options a {@link FindOneAndModifyOptions} struct\n     * @return a task containing the resulting document\n     */\n    public RealmResultTask<DocumentT> findOneAndDelete(final Bson filter,\n                                                       final FindOneAndModifyOptions options) {\n        return new RealmResultTaskImpl<>(threadPoolExecutor, new RealmResultTaskImpl.Executor<DocumentT>() {\n            @Nullable\n            @Override\n            public DocumentT run() {\n                return osMongoCollection.findOneAndDelete(filter, options);\n            }\n        });\n    }\n\n    /**\n     * Finds a document in the collection and delete it.\n     *\n     * @param filter      the query filter\n     * @param options     a {@link FindOneAndModifyOptions} struct\n     * @param resultClass the class to decode each document into\n     * @param <ResultT>   the target document type of the iterable.\n     * @return a task containing the resulting document\n     */\n    public <ResultT> RealmResultTask<ResultT> findOneAndDelete(final Bson filter,\n                                                               final FindOneAndModifyOptions options,\n                                                               final Class<ResultT> resultClass) {\n        return new RealmResultTaskImpl<>(threadPoolExecutor, new RealmResultTaskImpl.Executor<ResultT>() {\n            @Nullable\n            @Override\n            public ResultT run() {\n                return osMongoCollection.findOneAndDelete(filter, options, resultClass);\n            }\n        });\n    }\n\n    /**\n     * Watches a collection. The resulting stream will be notified of all events on this collection\n     * that the active user is authorized to see based on the configured MongoDB Realm rules.\n     *\n     * @return a task that provides access to the stream of change events.\n     */\n    public RealmEventStreamTask<DocumentT> watch() {\n        return new RealmEventStreamTaskImpl<>(getNamespace().getFullName(),\n                new RealmEventStreamTaskImpl.Executor<DocumentT>() {\n                    @Override\n                    public EventStream<DocumentT> run() throws IOException {\n                        return osMongoCollection.watch();\n                    }\n                });\n    }\n\n    /**\n     * Watches specified IDs in a collection.\n     *\n     * @param ids the ids to watch.\n     * @return a task that provides access to the stream of change events.\n     */\n    public RealmEventStreamTask<DocumentT> watch(final BsonValue... ids) {\n        return new RealmEventStreamTaskImpl<>(getNamespace().getFullName(),\n                new RealmEventStreamTaskImpl.Executor<DocumentT>() {\n                    @Override\n                    public EventStream<DocumentT> run() throws IOException {\n                        return osMongoCollection.watch(Arrays.asList(ids));\n                    }\n                });\n    }\n\n    /**\n     * Watches specified IDs in a collection. This convenience overload supports the use case\n     * of non-{@link BsonValue} instances of {@link ObjectId} by wrapping them in\n     * {@link BsonObjectId} instances for the user.\n     *\n     * @param ids unique object identifiers of the IDs to watch.\n     * @return a task that provides access to the stream of change events.\n     */\n    public RealmEventStreamTask<DocumentT> watch(final ObjectId... ids) {\n        return new RealmEventStreamTaskImpl<>(getNamespace().getFullName(),\n                new RealmEventStreamTaskImpl.Executor<DocumentT>() {\n                    @Override\n                    public EventStream<DocumentT> run() throws IOException {\n                        return osMongoCollection.watch(Arrays.asList(ids));\n                    }\n                });\n    }\n\n    /**\n     * Watches a collection. The provided document will be used as a match expression filter on\n     * the change events coming from the stream. This convenience overload supports the use of\n     * non-{@link BsonDocument} instances for the user.\n     * <p>\n     * See <a href=\"https://docs.mongodb.com/manual/reference/operator/aggregation/match/\" target=\"_blank\">how to define a match filter</a>.\n     * <p>\n     * Defining the match expression to filter ChangeEvents is similar to\n     * <a href=\"https://docs.mongodb.com/realm/triggers/database-triggers/\" target=\"_blank\">how to define the match expression for triggers</a>\n     *\n     * @param matchFilter the $match filter to apply to incoming change events\n     * @return a task that provides access to the stream of change events.\n     */\n    public RealmEventStreamTask<DocumentT> watchWithFilter(Document matchFilter) {\n        return new RealmEventStreamTaskImpl<>(getNamespace().getFullName(),\n                new RealmEventStreamTaskImpl.Executor<DocumentT>() {\n                    @Override\n                    public EventStream<DocumentT> run() throws IOException {\n                        return osMongoCollection.watchWithFilter(matchFilter);\n                    }\n                });\n    }\n\n    /**\n     * Watches a collection. The provided BSON document will be used as a match expression filter on\n     * the change events coming from the stream.\n     * <p>\n     * See <a href=\"https://docs.mongodb.com/manual/reference/operator/aggregation/match/\" target=\"_blank\">how to define a match filter</a>.\n     * <p>\n     * Defining the match expression to filter ChangeEvents is similar to\n     * <a href=\"https://docs.mongodb.com/realm/triggers/database-triggers/\" target=\"_blank\">how to define the match expression for triggers</a>\n     *\n     * @param matchFilter the $match filter to apply to incoming change events\n     * @return a task that provides access to the stream of change events.\n     */\n    public RealmEventStreamTask<DocumentT> watchWithFilter(BsonDocument matchFilter) {\n        return new RealmEventStreamTaskImpl<>(getNamespace().getFullName(),\n                new RealmEventStreamTaskImpl.Executor<DocumentT>() {\n                    @Override\n                    public EventStream<DocumentT> run() throws IOException {\n                        return osMongoCollection.watchWithFilter(matchFilter);\n                    }\n                });\n    }\n\n    /**\n     * Watches a collection asynchronously. The resulting stream will be notified of all events on this collection\n     * that the active user is authorized to see based on the configured MongoDB Realm rules.\n     *\n     * @return a task that provides access to the stream of change events.\n     */\n    public RealmEventStreamAsyncTask<DocumentT> watchAsync() {\n        return new RealmEventStreamAsyncTaskImpl<>(getNamespace().getFullName(),\n                new RealmEventStreamAsyncTaskImpl.Executor<DocumentT>() {\n                    @Override\n                    public EventStream<DocumentT> run() throws IOException {\n                        return osMongoCollection.watch();\n                    }\n                });\n    }\n\n    /**\n     * Watches specified IDs in a collection asynchronously.\n     *\n     * @param ids the ids to watch.\n     * @return a task that provides access to the stream of change events.\n     */\n    public RealmEventStreamAsyncTask<DocumentT> watchAsync(final BsonValue... ids) {\n        return new RealmEventStreamAsyncTaskImpl<>(getNamespace().getFullName(),\n                new RealmEventStreamAsyncTaskImpl.Executor<DocumentT>() {\n                    @Override\n                    public EventStream<DocumentT> run() throws IOException {\n                        return osMongoCollection.watch(Arrays.asList(ids));\n                    }\n                });\n    }\n\n    /**\n     * Watches specified IDs in a collection asynchronously. This convenience overload supports the use case\n     * of non-{@link BsonValue} instances of {@link ObjectId} by wrapping them in\n     * {@link BsonObjectId} instances for the user.\n     *\n     * @param ids unique object identifiers of the IDs to watch.\n     * @return a task that provides access to the stream of change events.\n     */\n    public RealmEventStreamAsyncTask<DocumentT> watchAsync(final ObjectId... ids) {\n        return new RealmEventStreamAsyncTaskImpl<>(getNamespace().getFullName(),\n                new RealmEventStreamAsyncTaskImpl.Executor<DocumentT>() {\n                    @Override\n                    public EventStream<DocumentT> run() throws IOException {\n                        return osMongoCollection.watch(Arrays.asList(ids));\n                    }\n                });\n    }\n\n    /**\n     * Watches a collection asynchronously. The provided document will be used as a match expression filter on\n     * the change events coming from the stream. This convenience overload supports the use of\n     * non-{@link BsonDocument} instances for the user.\n     * <p>\n     * See <a href=\"https://docs.mongodb.com/manual/reference/operator/aggregation/match/\" target=\"_blank\">how to define a match filter</a>.\n     * <p>\n     * Defining the match expression to filter ChangeEvents is similar to\n     * <a href=\"https://docs.mongodb.com/realm/triggers/database-triggers/\" target=\"_blank\">how to define the match expression for triggers</a>\n     *\n     * @param matchFilter the $match filter to apply to incoming change events\n     * @return a task that provides access to the stream of change events.\n     */\n    public RealmEventStreamAsyncTask<DocumentT> watchWithFilterAsync(Document matchFilter) {\n        return new RealmEventStreamAsyncTaskImpl<>(getNamespace().getFullName(),\n                new RealmEventStreamAsyncTaskImpl.Executor<DocumentT>() {\n                    @Override\n                    public EventStream<DocumentT> run() throws IOException {\n                        return osMongoCollection.watchWithFilter(matchFilter);\n                    }\n                });\n    }\n\n    /**\n     * Watches a collection asynchronously. The provided BSON document will be used as a match expression filter on\n     * the change events coming from the stream.\n     * <p>\n     * See <a href=\"https://docs.mongodb.com/manual/reference/operator/aggregation/match/\" target=\"_blank\">how to define a match filter</a>.\n     * <p>\n     * Defining the match expression to filter ChangeEvents is similar to\n     * <a href=\"https://docs.mongodb.com/realm/triggers/database-triggers/\" target=\"_blank\">how to define the match expression for triggers</a>\n     *\n     * @param matchFilter the $match filter to apply to incoming change events\n     * @return a task that provides access to the stream of change events.\n     */\n    public RealmEventStreamAsyncTask<DocumentT> watchWithFilterAsync(BsonDocument matchFilter) {\n        return new RealmEventStreamAsyncTaskImpl<>(getNamespace().getFullName(),\n                new RealmEventStreamAsyncTaskImpl.Executor<DocumentT>() {\n                    @Override\n                    public EventStream<DocumentT> run() throws IOException {\n                        return osMongoCollection.watchWithFilter(matchFilter);\n                    }\n                });\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/objectServer/java/io/realm/mongodb/mongo/MongoDatabase.java",
    "content": "/*\n * Copyright 2020 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\npackage io.realm.mongodb.mongo;\n\nimport org.bson.Document;\n\nimport io.realm.annotations.Beta;\nimport io.realm.internal.Util;\nimport io.realm.internal.objectstore.OsMongoDatabase;\n\n/**\n * The RemoteMongoDatabase provides access to its {@link Document} {@link MongoCollection}s.\n */\n@Beta\npublic class MongoDatabase {\n\n    private final OsMongoDatabase osMongoDatabase;\n    private final String name;\n\n    MongoDatabase(final OsMongoDatabase osMongoDatabase,\n                  final String name) {\n        this.osMongoDatabase = osMongoDatabase;\n        this.name = name;\n    }\n\n    /**\n     * Gets the name of the database.\n     *\n     * @return the database name\n     */\n    public String getName() {\n        return name;\n    }\n\n    /**\n     * Gets a collection.\n     *\n     * @param collectionName the name of the collection to return\n     * @return the collection\n     */\n    public MongoCollection<Document> getCollection(final String collectionName) {\n        Util.checkEmpty(collectionName, \"collectionName\");\n        MongoNamespace namespace = new MongoNamespace(name, collectionName);\n\n        return new MongoCollection<>(namespace,\n                osMongoDatabase.getCollection(collectionName, namespace));\n    }\n\n    /**\n     * Gets a collection, with a specific default document class.\n     *\n     * @param collectionName the name of the collection to return\n     * @param documentClass  the default class to cast any documents returned from the database into.\n     * @param <DocumentT>    the type of the class to use instead of {@code Document}.\n     * @return the collection\n     */\n    public <DocumentT> MongoCollection<DocumentT> getCollection(\n            final String collectionName,\n            final Class<DocumentT> documentClass\n    ) {\n        Util.checkEmpty(collectionName, \"collectionName\");\n        Util.checkNull(documentClass, \"documentClass\");\n        MongoNamespace namespace = new MongoNamespace(name, collectionName);\n        return new MongoCollection<>(namespace,\n                osMongoDatabase.getCollection(collectionName, namespace, documentClass));\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/objectServer/java/io/realm/mongodb/mongo/MongoNamespace.java",
    "content": "/*\n * Copyright 2020 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\npackage io.realm.mongodb.mongo;\n\nimport org.bson.codecs.pojo.annotations.BsonCreator;\nimport org.bson.codecs.pojo.annotations.BsonIgnore;\nimport org.bson.codecs.pojo.annotations.BsonProperty;\n\nimport java.util.HashSet;\nimport java.util.Set;\n\nimport io.realm.annotations.Beta;\n\nimport static java.util.Arrays.asList;\nimport static org.bson.assertions.Assertions.isTrueArgument;\nimport static org.bson.assertions.Assertions.notNull;\n\n/**\n * A MongoDB namespace, which includes a database name and collection name.\n */\n@Beta\npublic final class MongoNamespace {\n    public static final String COMMAND_COLLECTION_NAME = \"$cmd\";\n\n    private static final Set<Character> PROHIBITED_CHARACTERS_IN_DATABASE_NAME =\n            new HashSet<Character>(asList('\\0', '/', '\\\\', ' ', '\"', '.'));\n\n    private final String databaseName;\n    private final String collectionName;\n    @BsonIgnore\n    private final String fullName;  // cache to avoid repeated string building\n\n    /**\n     * Check the validity of the given database name. A valid database name is non-null, non-empty, and does not contain any of the\n     * following characters: {@code '\\0', '/', '\\\\', ' ', '\"', '.'}. The server may impose additional restrictions on database names.\n     *\n     * @param databaseName the database name\n     * @throws IllegalArgumentException if the database name is invalid\n     */\n    public static void checkDatabaseNameValidity(final String databaseName) {\n        notNull(\"databaseName\", databaseName);\n        isTrueArgument(\"databaseName is not empty\", !databaseName.isEmpty());\n        for (int i = 0; i < databaseName.length(); i++) {\n            isTrueArgument(\"databaseName does not contain '\" + databaseName.charAt(i) + \"'\",\n                    !PROHIBITED_CHARACTERS_IN_DATABASE_NAME.contains(databaseName.charAt(i)));\n        }\n    }\n\n    /**\n     * Check the validity of the given collection name.   A valid collection name is non-null and non-empty.  The server may impose\n     * additional restrictions on collection names.\n     *\n     * @param collectionName the collection name\n     * @throws IllegalArgumentException if the collection name is invalid\n     */\n    public static void checkCollectionNameValidity(final String collectionName) {\n        notNull(\"collectionName\", collectionName);\n        isTrueArgument(\"collectionName is not empty\", !collectionName.isEmpty());\n    }\n\n    /**\n     * Construct an instance for the given full name.  The database name is the string preceding the first {@code \".\"} character.\n     *\n     * @param fullName the non-null full namespace\n     * @see #checkDatabaseNameValidity(String)\n     * @see #checkCollectionNameValidity(String)\n     */\n    public MongoNamespace(final String fullName) {\n        notNull(\"fullName\", fullName);\n        this.fullName = fullName;\n        this.databaseName = getDatatabaseNameFromFullName(fullName);\n        this.collectionName = getCollectionNameFullName(fullName);\n        checkDatabaseNameValidity(databaseName);\n        checkCollectionNameValidity(collectionName);\n    }\n\n    /**\n     * Construct an instance from the given database name and collection name.\n     *\n     * @param databaseName   the valid database name\n     * @param collectionName the valid collection name\n     * @see #checkDatabaseNameValidity(String)\n     * @see #checkCollectionNameValidity(String)\n     */\n    @BsonCreator\n    public MongoNamespace(@BsonProperty(\"db\") final String databaseName,\n                          @BsonProperty(\"coll\") final String collectionName) {\n        checkDatabaseNameValidity(databaseName);\n        checkCollectionNameValidity(collectionName);\n        this.databaseName = databaseName;\n        this.collectionName = collectionName;\n        this.fullName = databaseName + '.' + collectionName;\n    }\n\n    /**\n     * Gets the database name.\n     *\n     * @return the database name\n     */\n    public String getDatabaseName() {\n        return databaseName;\n    }\n\n    /**\n     * Gets the collection name.\n     *\n     * @return the collection name\n     */\n    public String getCollectionName() {\n        return collectionName;\n    }\n\n    /**\n     * Gets the full name, which is the database name and the collection name, separated by a period.\n     *\n     * @return the full name\n     */\n    public String getFullName() {\n        return fullName;\n    }\n\n    @Override\n    public boolean equals(final Object o) {\n        if (this == o) {\n            return true;\n        }\n        if (o == null || getClass() != o.getClass()) {\n            return false;\n        }\n\n        MongoNamespace that = (MongoNamespace) o;\n\n        if (!collectionName.equals(that.collectionName)) {\n            return false;\n        }\n        if (!databaseName.equals(that.databaseName)) {\n            return false;\n        }\n\n        return true;\n    }\n\n    /**\n     * Returns the standard MongoDB representation of a namespace, which is {@code &lt;database&gt;.&lt;collection&gt;}.\n     *\n     * @return string representation of the namespace.\n     */\n    @Override\n    public String toString() {\n        return fullName;\n    }\n\n    @Override\n    public int hashCode() {\n        int result = databaseName.hashCode();\n        result = 31 * result + (collectionName.hashCode());\n        return result;\n    }\n\n    private static String getCollectionNameFullName(final String namespace) {\n        int firstDot = namespace.indexOf('.');\n        if (firstDot == -1) {\n            return namespace;\n        }\n        return namespace.substring(firstDot + 1);\n    }\n\n    private static String getDatatabaseNameFromFullName(final String namespace) {\n        int firstDot = namespace.indexOf('.');\n        if (firstDot == -1) {\n            return \"\";\n        }\n        return namespace.substring(0, firstDot);\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/objectServer/java/io/realm/mongodb/mongo/events/BaseChangeEvent.java",
    "content": "/*\n * Copyright 2020 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\npackage io.realm.mongodb.mongo.events;\n\nimport org.bson.BsonDocument;\n\nimport javax.annotation.Nullable;\n\n/**\n * Represents the set of properties that exist on all MongoDB realm change events produced\n * by watch streams in this SDK. Other change event types inherit from this type.\n *\n * @param <DocumentT> The type of the full document in the change event.\n */\npublic abstract class BaseChangeEvent<DocumentT> {\n    private final OperationType operationType;\n    @Nullable\n    private final DocumentT fullDocument;\n    private final BsonDocument documentKey;\n    @Nullable\n    private final UpdateDescription updateDescription;\n\n    private final boolean hasUncommittedWrites;\n\n    /**\n     * Returns the operation type of the change that triggered the change event.\n     *\n     * @return the operation type of this change event.\n     */\n    public OperationType getOperationType() {\n        return operationType;\n    }\n\n    /**\n     * The full document at some point after the change has been applied.\n     *\n     * @return the full document.\n     */\n    @Nullable\n    public DocumentT getFullDocument() {\n        return fullDocument;\n    }\n\n    /**\n     * The unique identifier for the document that was actually changed.\n     *\n     * @return the document key.\n     */\n    public BsonDocument getDocumentKey() {\n        return documentKey;\n    }\n\n    /**\n     * In the case of an update, the description of which fields have been added, removed or updated.\n     *\n     * @return the update description.\n     */\n    @Nullable\n    public UpdateDescription getUpdateDescription() {\n        return updateDescription;\n    }\n\n    /**\n     * Indicates a local change event that has not yet been synchronized with a remote data store.\n     * Used only for the sync use case.\n     *\n     * @return whether or not this change event represents uncommitted writes.\n     */\n    public boolean hasUncommittedWrites() {\n        return hasUncommittedWrites;\n    }\n\n    protected BaseChangeEvent(\n            final OperationType operationType,\n            @Nullable final DocumentT fullDocument,\n            final BsonDocument documentKey,\n            @Nullable final UpdateDescription updateDescription,\n            final boolean hasUncommittedWrites\n    ) {\n        this.operationType = operationType;\n        this.fullDocument = fullDocument;\n        this.documentKey = documentKey;\n        this.updateDescription = (updateDescription == null)\n                ? new UpdateDescription(null, null) : updateDescription;\n        this.hasUncommittedWrites = hasUncommittedWrites;\n    }\n\n    /**\n     * Converts the change event to a BSON representation, as it would look on a MongoDB realm change\n     * stream, or a Realm compact watch stream.\n     *\n     * @return The BSON document representation of the change event.\n     */\n    public abstract BsonDocument toBsonDocument();\n\n    /**\n     * Represents the different MongoDB operations that can occur.\n     */\n    public enum OperationType {\n        INSERT, DELETE, REPLACE, UPDATE, UNKNOWN;\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/objectServer/java/io/realm/mongodb/mongo/events/UpdateDescription.java",
    "content": "/*\n * Copyright 2020 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\npackage io.realm.mongodb.mongo.events;\n\nimport org.bson.BsonArray;\nimport org.bson.BsonBoolean;\nimport org.bson.BsonDocument;\nimport org.bson.BsonElement;\nimport org.bson.BsonString;\nimport org.bson.BsonValue;\n\nimport java.util.ArrayList;\nimport java.util.Collection;\nimport java.util.HashSet;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Set;\n\nimport javax.annotation.Nullable;\n\nimport io.realm.mongodb.AppException;\nimport io.realm.mongodb.ErrorCode;\n\nimport static io.realm.internal.Util.checkContainsKey;\n\n/**\n * Indicates which fields have been modified in a given update operation.\n */\npublic final class UpdateDescription {\n    private static final String DOCUMENT_VERSION_FIELD = \"__stitch_sync_version\";\n\n    private final BsonDocument updatedFields;\n    private final Set<String> removedFields;\n\n    /**\n     * Creates an update description with the specified updated fields and removed field names.\n     *\n     * @param updatedFields Nested key-value pair representation of updated fields.\n     * @param removedFields Collection of removed field names.\n     */\n    UpdateDescription(\n            final BsonDocument updatedFields,\n            final Collection<String> removedFields\n    ) {\n        this.updatedFields = (updatedFields == null) ? new BsonDocument() : updatedFields;\n        this.removedFields = (removedFields == null) ? new HashSet<>() : new HashSet<>(removedFields);\n    }\n\n    /**\n     * Returns a {@link BsonDocument} containing keys and values representing (respectively) the\n     * fields that have changed in the corresponding update and their new values.\n     *\n     * @return the updated field names and their new values.\n     */\n    public BsonDocument getUpdatedFields() {\n        return updatedFields;\n    }\n\n    /**\n     * Returns a {@link List} containing the field names that have been removed in the corresponding\n     * update.\n     *\n     * @return the removed fields names.\n     */\n    public Collection<String> getRemovedFields() {\n        return removedFields;\n    }\n\n    /**\n     * Convert this update description to an update document.\n     *\n     * @return an update document with the appropriate $set and $unset documents.\n     */\n    public BsonDocument toUpdateDocument() {\n        final List<BsonElement> unsets = new ArrayList<>();\n        for (final String removedField : this.removedFields) {\n            unsets.add(new BsonElement(removedField, new BsonBoolean(true)));\n        }\n        final BsonDocument updateDocument = new BsonDocument();\n\n        if (this.updatedFields.size() > 0) {\n            updateDocument.append(\"$set\", this.updatedFields);\n        }\n\n        if (unsets.size() > 0) {\n            updateDocument.append(\"$unset\", new BsonDocument(unsets));\n        }\n\n        return updateDocument;\n    }\n\n    /**\n     * Converts this update description to its document representation as it would appear in a\n     * MongoDB Change Event.\n     *\n     * @return the update description document as it would appear in a change event\n     */\n    public BsonDocument toBsonDocument() {\n        final BsonDocument updateDescDoc = new BsonDocument();\n        updateDescDoc.put(\n                Fields.UPDATED_FIELDS_FIELD,\n                this.getUpdatedFields());\n\n        final BsonArray removedFields = new BsonArray();\n        for (final String field : this.getRemovedFields()) {\n            removedFields.add(new BsonString(field));\n        }\n        updateDescDoc.put(\n                Fields.REMOVED_FIELDS_FIELD,\n                removedFields);\n\n        return updateDescDoc;\n    }\n\n    /**\n     * Converts an update description BSON document from a MongoDB Change Event into an\n     * UpdateDescription object.\n     *\n     * @param document the\n     * @return the converted UpdateDescription\n     */\n    public static UpdateDescription fromBsonDocument(final BsonDocument document) {\n        try {\n            checkContainsKey(Fields.UPDATED_FIELDS_FIELD, document, \"document\");\n            checkContainsKey(Fields.REMOVED_FIELDS_FIELD, document, \"document\");\n        } catch (IllegalArgumentException exception) {\n            throw new AppException(ErrorCode.EVENT_DESERIALIZING, exception);\n        }\n\n        final BsonArray removedFieldsArr =\n                document.getArray(Fields.REMOVED_FIELDS_FIELD);\n        final Set<String> removedFields = new HashSet<>(removedFieldsArr.size());\n        for (final BsonValue field : removedFieldsArr) {\n            removedFields.add(field.asString().getValue());\n        }\n\n        return new UpdateDescription(document.getDocument(Fields.UPDATED_FIELDS_FIELD), removedFields);\n    }\n\n    /**\n     * Unilaterally merge an update description into this update description.\n     *\n     * @param otherDescription the update description to merge into this\n     * @return this merged update description\n     */\n    public UpdateDescription merge(@Nullable final UpdateDescription otherDescription) {\n        if (otherDescription != null) {\n            for (final Map.Entry<String, BsonValue> entry : this.updatedFields.entrySet()) {\n                if (otherDescription.removedFields.contains(entry.getKey())) {\n                    this.updatedFields.remove(entry.getKey());\n                }\n            }\n            for (final String removedField : this.removedFields) {\n                if (otherDescription.updatedFields.containsKey(removedField)) {\n                    this.removedFields.remove(removedField);\n                }\n            }\n\n            this.removedFields.addAll(otherDescription.removedFields);\n            this.updatedFields.putAll(otherDescription.updatedFields);\n        }\n\n        return this;\n    }\n\n    /**\n     * Find the diff between two documents.\n     *\n     * <p>NOTE: This does not do a full diff on {@link BsonArray}. If there is\n     * an inequality between the old and new array, the old array will\n     * simply be replaced by the new one.\n     *\n     * @param beforeDocument original document\n     * @param afterDocument  document to diff on\n     * @param onKey          the key for our depth level\n     * @param updatedFields  contiguous document of updated fields,\n     *                       nested or otherwise\n     * @param removedFields  contiguous list of removedFields,\n     *                       nested or otherwise\n     * @return a description of the updated fields and removed keys between the documents\n     */\n    private static UpdateDescription diff(\n            final BsonDocument beforeDocument,\n            final BsonDocument afterDocument,\n            final @Nullable String onKey,\n            final BsonDocument updatedFields,\n            final Set<String> removedFields) {\n        // for each key in this document...\n        for (final Map.Entry<String, BsonValue> entry : beforeDocument.entrySet()) {\n            final String key = entry.getKey();\n            // don't worry about the _id or version field for now\n            if (key.equals(\"_id\") || key.equals(DOCUMENT_VERSION_FIELD)) {\n                continue;\n            }\n            final BsonValue oldValue = entry.getValue();\n\n            final String actualKey = onKey == null ? key : String.format(\"%s.%s\", onKey, key);\n            // if the key exists in the other document AND both are BsonDocuments\n            // diff the documents recursively, carrying over the keys to keep\n            // updatedFields and removedFields flat.\n            // this will allow us to reference whole objects as well as nested\n            // properties.\n            // else if the key does not exist, the key has been removed.\n            if (afterDocument.containsKey(key)) {\n                final BsonValue newValue = afterDocument.get(key);\n                if ((oldValue instanceof BsonDocument) && (newValue instanceof BsonDocument)) {\n                    diff((BsonDocument) oldValue,\n                            (BsonDocument) newValue,\n                            actualKey,\n                            updatedFields,\n                            removedFields);\n                } else if (!oldValue.equals(newValue)) {\n                    updatedFields.put(actualKey, newValue);\n                }\n            } else {\n                removedFields.add(actualKey);\n            }\n        }\n\n        // for each key in the other document...\n        for (final Map.Entry<String, BsonValue> entry : afterDocument.entrySet()) {\n            final String key = entry.getKey();\n            // don't worry about the _id or version field for now\n            if (key.equals(\"_id\") || key.equals(DOCUMENT_VERSION_FIELD)) {\n                continue;\n            }\n\n            final BsonValue newValue = entry.getValue();\n            // if the key is not in the this document,\n            // it is a new key with a new value.\n            // updatedFields will included keys that must\n            // be newly created.\n            final String actualKey = (onKey == null) ? key : String.format(\"%s.%s\", onKey, key);\n            if (!beforeDocument.containsKey(key)) {\n                updatedFields.put(actualKey, newValue);\n            }\n        }\n\n        return new UpdateDescription(updatedFields, removedFields);\n    }\n\n    /**\n     * Find the diff between two documents.\n     *\n     * <p>NOTE: This does not do a full diff on [BsonArray]. If there is\n     * an inequality between the old and new array, the old array will\n     * simply be replaced by the new one.\n     *\n     * @param beforeDocument original document\n     * @param afterDocument  document to diff on\n     * @return a description of the updated fields and removed keys between the documents.\n     */\n    public static UpdateDescription diff(\n            @Nullable final BsonDocument beforeDocument,\n            @Nullable final BsonDocument afterDocument) {\n        if ((beforeDocument == null) || (afterDocument == null)) {\n            return new UpdateDescription(new BsonDocument(), new HashSet<>());\n        }\n\n        return UpdateDescription.diff(\n                beforeDocument,\n                afterDocument,\n                null,\n                new BsonDocument(),\n                new HashSet<>()\n        );\n    }\n\n    /**\n     * Determines whether this update description is empty.\n     *\n     * @return true if the update description is empty, false otherwise\n     */\n    public boolean isEmpty() {\n        return (this.updatedFields.isEmpty()) && (this.removedFields.isEmpty());\n    }\n\n    @Override\n    public boolean equals(final Object obj) {\n        if ((obj == null) || !obj.getClass().equals(UpdateDescription.class)) {\n            return false;\n        }\n        final UpdateDescription other = (UpdateDescription) obj;\n\n        return other.getRemovedFields().equals(this.removedFields)\n                && other.getUpdatedFields().equals(this.updatedFields);\n    }\n\n    @Override\n    public int hashCode() {\n        return removedFields.hashCode() + (31 * updatedFields.hashCode());\n    }\n\n    private static final class Fields {\n        static final String UPDATED_FIELDS_FIELD = \"updatedFields\";\n        static final String REMOVED_FIELDS_FIELD = \"removedFields\";\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/objectServer/java/io/realm/mongodb/mongo/iterable/AggregateIterable.java",
    "content": "/*\n * Copyright 2020 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\npackage io.realm.mongodb.mongo.iterable;\n\nimport org.bson.codecs.configuration.CodecRegistry;\nimport org.bson.conversions.Bson;\n\nimport java.util.List;\nimport java.util.concurrent.ThreadPoolExecutor;\n\nimport io.realm.internal.jni.JniBsonProtocol;\nimport io.realm.internal.network.NetworkRequest;\nimport io.realm.internal.objectstore.OsJavaNetworkTransport;\nimport io.realm.internal.objectstore.OsMongoCollection;\n\n/**\n * Specific iterable for {@link io.realm.mongodb.mongo.MongoCollection#aggregate(List)} operations.\n *\n * @param <ResultT> The type to which this iterable will decode documents.\n */\npublic class AggregateIterable<ResultT> extends MongoIterable<ResultT> {\n\n    private List<? extends Bson> pipeline;\n\n    public AggregateIterable(final ThreadPoolExecutor threadPoolExecutor,\n                             final OsMongoCollection<?> osMongoCollection,\n                             final CodecRegistry codecRegistry,\n                             final Class<ResultT> resultClass,\n                             final List<? extends Bson> pipeline) {\n        super(threadPoolExecutor, osMongoCollection, codecRegistry, resultClass);\n        this.pipeline = pipeline;\n    }\n\n    @Override\n    void callNative(final NetworkRequest<?> callback) {\n        String pipelineString = JniBsonProtocol.encode(pipeline, codecRegistry);\n        nativeAggregate(osMongoCollection.getNativePtr(), pipelineString, callback);\n    }\n\n    private static native void nativeAggregate(long remoteMongoCollectionPtr,\n                                               String pipeline,\n                                               OsJavaNetworkTransport.NetworkTransportJNIResultCallback callback);\n}\n"
  },
  {
    "path": "realm/realm-library/src/objectServer/java/io/realm/mongodb/mongo/iterable/FindIterable.java",
    "content": "/*\n * Copyright 2020 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\npackage io.realm.mongodb.mongo.iterable;\n\nimport org.bson.Document;\nimport org.bson.codecs.configuration.CodecRegistry;\nimport org.bson.conversions.Bson;\n\nimport java.util.concurrent.ThreadPoolExecutor;\n\nimport javax.annotation.Nullable;\n\nimport io.realm.internal.jni.JniBsonProtocol;\nimport io.realm.internal.network.NetworkRequest;\nimport io.realm.internal.objectstore.OsJavaNetworkTransport;\nimport io.realm.internal.objectstore.OsMongoCollection;\nimport io.realm.mongodb.mongo.options.FindOptions;\n\n/**\n * Specific iterable for {@link io.realm.mongodb.mongo.MongoCollection#find()} operations.\n *\n * @param <ResultT> The type to which this iterable will decode documents.\n */\npublic class FindIterable<ResultT> extends MongoIterable<ResultT> {\n\n    private static final int FIND = 1;\n    private static final int FIND_WITH_OPTIONS = 2;\n\n    private final FindOptions options;\n    private final String encodedEmptyDocument;\n\n    private Bson filter;\n\n    public FindIterable(final ThreadPoolExecutor threadPoolExecutor,\n                        final OsMongoCollection<?> osMongoCollection,\n                        final CodecRegistry codecRegistry,\n                        final Class<ResultT> resultClass) {\n        super(threadPoolExecutor, osMongoCollection, codecRegistry, resultClass);\n        this.options = new FindOptions();\n        this.filter = new Document();\n        this.encodedEmptyDocument = JniBsonProtocol.encode(new Document(), codecRegistry);\n    }\n\n    @Override\n    void callNative(final NetworkRequest<?> callback) {\n        String filterString = JniBsonProtocol.encode(filter, codecRegistry);\n        String projectionString = encodedEmptyDocument;\n        String sortString = encodedEmptyDocument;\n\n        if (options == null) {\n            nativeFind(FIND, osMongoCollection.getNativePtr(), filterString, projectionString, sortString, 0, callback);\n        } else {\n            projectionString = JniBsonProtocol.encode(options.getProjection(), codecRegistry);\n            sortString = JniBsonProtocol.encode(options.getSort(), codecRegistry);\n\n            nativeFind(FIND_WITH_OPTIONS, osMongoCollection.getNativePtr(), filterString, projectionString, sortString, options.getLimit(), callback);\n        }\n    }\n\n    /**\n     * Sets the query filter to apply to the query.\n     *\n     * @param filter the filter, which may be null.\n     * @return this\n     */\n    public FindIterable<ResultT> filter(@Nullable final Bson filter) {\n        this.filter = filter;\n        return this;\n    }\n\n    /**\n     * Sets the limit to apply.\n     *\n     * @param limit the limit, which may be 0\n     * @return this\n     */\n    public FindIterable<ResultT> limit(int limit) {\n        this.options.limit(limit);\n        return this;\n    }\n\n    /**\n     * Sets a document describing the fields to return for all matching documents.\n     *\n     * @param projection the project document, which may be null.\n     * @return this\n     */\n    public FindIterable<ResultT> projection(@Nullable final Bson projection) {\n        this.options.projection(projection);\n        return this;\n    }\n\n    /**\n     * Sets the sort criteria to apply to the query.\n     *\n     * @param sort the sort criteria, which may be null.\n     * @return this\n     */\n    public FindIterable<ResultT> sort(@Nullable final Bson sort) {\n        this.options.sort(sort);\n        return this;\n    }\n\n    private static native void nativeFind(int findType,\n                                          long remoteMongoCollectionPtr,\n                                          String filter,\n                                          String projection,\n                                          String sort,\n                                          long limit,\n                                          OsJavaNetworkTransport.NetworkTransportJNIResultCallback callback);\n}\n"
  },
  {
    "path": "realm/realm-library/src/objectServer/java/io/realm/mongodb/mongo/iterable/MongoCursor.java",
    "content": "/*\n * Copyright 2020 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\npackage io.realm.mongodb.mongo.iterable;\n\nimport java.io.Closeable;\nimport java.util.Iterator;\n\n/**\n * The Mongo Cursor class is fundamentally an {@link Iterator} containing an additional\n * {@code tryNext()} method for convenience.\n * <p>\n * An application should ensure that a cursor is closed in all circumstances, e.g. using a\n * try-with-resources statement.\n *\n * @param <ResultT> The type of documents the cursor contains\n */\npublic class MongoCursor<ResultT> implements Iterator<ResultT>, Closeable {\n\n    private final Iterator<ResultT> iterator;\n\n    MongoCursor(Iterator<ResultT> iterator) {\n        this.iterator = iterator;\n    }\n\n    @Override\n    public boolean hasNext() {\n        return iterator.hasNext();\n    }\n\n    @Override\n    public ResultT next() {\n        return iterator.next();\n    }\n\n    /**\n     * A special {@code next()} case that returns the next document if available or null.\n     *\n     * @return A {@code Task} containing the next document if available or null.\n     */\n    public ResultT tryNext() {\n        if (!iterator.hasNext()) {\n            return null;\n        }\n        return iterator.next();\n    }\n\n    @Override\n    public void close() {\n\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/objectServer/java/io/realm/mongodb/mongo/iterable/MongoIterable.java",
    "content": "/*\n * Copyright 2020 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\npackage io.realm.mongodb.mongo.iterable;\n\nimport org.bson.codecs.configuration.CodecRegistry;\n\nimport java.util.ArrayList;\nimport java.util.Collection;\nimport java.util.Iterator;\nimport java.util.concurrent.ThreadPoolExecutor;\n\nimport javax.annotation.Nullable;\n\nimport io.realm.internal.async.RealmResultTaskImpl;\nimport io.realm.internal.jni.JniBsonProtocol;\nimport io.realm.internal.network.NetworkRequest;\nimport io.realm.internal.objectstore.OsMongoCollection;\nimport io.realm.mongodb.RealmResultTask;\n\n/**\n * The MongoIterable is the results from an operation, such as a {@code find()} or an\n * {@code aggregate()} query.\n * <p>\n * This class somewhat mimics the behavior of an {@link Iterable} but given its results are\n * obtained asynchronously, its values are wrapped inside a {@code Task}.\n *\n * @param <ResultT> The type to which this iterable will decode documents.\n */\npublic abstract class MongoIterable<ResultT> {\n\n    protected final OsMongoCollection<?> osMongoCollection;\n    protected final CodecRegistry codecRegistry;\n\n    private final Class<ResultT> resultClass;\n    private final ThreadPoolExecutor threadPoolExecutor;\n\n    MongoIterable(final ThreadPoolExecutor threadPoolExecutor,\n                  final OsMongoCollection<?> osMongoCollection,\n                  final CodecRegistry codecRegistry,\n                  final Class<ResultT> resultClass) {\n        this.threadPoolExecutor = threadPoolExecutor;\n        this.osMongoCollection = osMongoCollection;\n        this.codecRegistry = codecRegistry;\n        this.resultClass = resultClass;\n    }\n\n    abstract void callNative(NetworkRequest<?> callback);\n\n    /**\n     * Returns a cursor of the operation represented by this iterable.\n     * <p>\n     * The result is wrapped in a {@code Task} since the iterator should be capable of\n     * asynchronously retrieve documents from the server.\n     *\n     * @return an asynchronous task with cursor of the operation represented by this iterable.\n     */\n    public RealmResultTask<MongoCursor<ResultT>> iterator() {\n        return new RealmResultTaskImpl<>(threadPoolExecutor, new RealmResultTaskImpl.Executor<MongoCursor<ResultT>>() {\n            @Nullable\n            @Override\n            public MongoCursor<ResultT> run() {\n                return new MongoCursor<>(MongoIterable.this.getCollection().iterator());\n            }\n        });\n    }\n\n    /**\n     * Helper to return the first item in the iterator or null.\n     * <p>\n     * The result is wrapped in a {@code Task} since the iterator should be capable of\n     * asynchronously retrieve documents from the server.\n     *\n     * @return a task containing the first item or null.\n     */\n    public RealmResultTask<ResultT> first() {\n        NetworkRequest<ResultT> task = new NetworkRequest<ResultT>() {\n            @Override\n            protected ResultT mapSuccess(Object result) {\n                Collection<ResultT> decodedCollection = mapCollection(result);\n                Iterator<ResultT> iter = decodedCollection.iterator();\n                return iter.hasNext() ? iter.next() : null;\n            }\n            @Override\n            protected void execute(NetworkRequest<ResultT> callback) {\n                callNative(callback);\n            }\n        };\n\n        return new RealmResultTaskImpl<>(threadPoolExecutor, new RealmResultTaskImpl.Executor<ResultT>() {\n            @Nullable\n            @Override\n            public ResultT run() {\n                return task.resultOrThrow();\n            }\n        });\n    }\n\n    private Collection<ResultT> getCollection() {\n        return new NetworkRequest<Collection<ResultT>>() {\n            @Override\n            protected Collection<ResultT> mapSuccess(Object result) {\n                return mapCollection(result);\n            }\n            @Override\n            protected void execute(NetworkRequest<Collection<ResultT>> callback) {\n                callNative(callback);\n            }\n        }.resultOrThrow();\n    }\n\n    private Collection<ResultT> mapCollection(Object result) {\n        Collection<?> collection = JniBsonProtocol.decode((String) result, Collection.class, codecRegistry);\n        Collection<ResultT> decodedCollection = new ArrayList<>();\n        for (Object collectionElement : collection) {\n            String encodedElement = JniBsonProtocol.encode(collectionElement, codecRegistry);\n            decodedCollection.add(JniBsonProtocol.decode(encodedElement, resultClass, codecRegistry));\n        }\n        return decodedCollection;\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/objectServer/java/io/realm/mongodb/mongo/options/CountOptions.java",
    "content": "/*\n * Copyright 2020 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\npackage io.realm.mongodb.mongo.options;\n\nimport io.realm.annotations.Beta;\n\n/**\n * The options for a count operation.\n */\n@Beta\npublic class CountOptions {\n    private int limit;\n\n    /**\n     * Gets the limit to apply.  The default is 0, which means there is no limit.\n     *\n     * @return the limit\n     */\n    public int getLimit() {\n        return limit;\n    }\n\n    /**\n     * Sets the limit to apply.\n     *\n     * @param limit the limit\n     * @return this\n     */\n    public CountOptions limit(final int limit) {\n        this.limit = limit;\n        return this;\n    }\n\n    @Override\n    public String toString() {\n        return \"RemoteCountOptions{\"\n                + \"limit=\" + limit\n                + '}';\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/objectServer/java/io/realm/mongodb/mongo/options/FindOneAndModifyOptions.java",
    "content": "/*\n * Copyright 2020 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\npackage io.realm.mongodb.mongo.options;\n\nimport javax.annotation.Nullable;\n\nimport org.bson.Document;\nimport org.bson.conversions.Bson;\n\nimport io.realm.annotations.Beta;\n\n/**\n * The options to apply to a findOneAndUpdate, findOneAndReplace, or findOneAndDelete operation\n * (also commonly referred to as findOneAndModify operations).\n */\n@Beta\npublic class FindOneAndModifyOptions {\n\n    private Bson projection;\n    private Bson sort;\n    private boolean upsert;\n    private boolean returnNewDocument;\n\n    public FindOneAndModifyOptions() {\n        this.projection = new Document();\n        this.sort = new Document();\n    }\n\n    /**\n     * Gets a document describing the fields to return for all matching documents.\n     *\n     * @return the project document, which may be null\n     */\n    @Nullable\n    public Bson getProjection() {\n        return projection;\n    }\n\n    /**\n     * Sets a document describing the fields to return for all matching documents.\n     *\n     * @param projection the project document, which may be null.\n     * @return this\n     */\n    public FindOneAndModifyOptions projection(@Nullable final Bson projection) {\n        this.projection = projection;\n        return this;\n    }\n\n    /**\n     * Gets the sort criteria to apply to the query. The default is null, which means that the\n     * documents will be returned in an undefined order.\n     *\n     * @return a document describing the sort criteria\n     */\n    @Nullable\n    public Bson getSort() {\n        return sort;\n    }\n\n    /**\n     * Sets the sort criteria to apply to the query.\n     *\n     * @param sort the sort criteria, which may be null.\n     * @return this\n     */\n    public FindOneAndModifyOptions sort(@Nullable final Bson sort) {\n        this.sort = sort;\n        return this;\n    }\n\n    /**\n     * Returns true if a new document should be inserted if there are no matches to the query filter.\n     * The default is false.\n     * Note: Only findOneAndUpdate and findOneAndReplace take this option\n     *\n     * @return true if a new document should be inserted if there are no matches to the query filter\n     */\n    public boolean isUpsert() {\n        return upsert;\n    }\n\n    /**\n     * Set to true if a new document should be inserted if there are no matches to the query filter.\n     *\n     * @param upsert true if a new document should be inserted if there are no matches to the query\n     *               filter.\n     * @return this\n     */\n    public FindOneAndModifyOptions upsert(final boolean upsert) {\n        this.upsert = upsert;\n        return this;\n    }\n\n    /**\n     * Returns true if the findOneAndModify operation should return the new document.\n     * The default is false\n     * Note: Only findOneAndUpdate and findOneAndReplace take this options\n     * findOneAndDelete will always return the old document\n     *\n     * @return true if findOneAndModify operation should return the new document\n     */\n    public boolean isReturnNewDocument() {\n        return returnNewDocument;\n    }\n\n    /**\n     * Set to true if findOneAndModify operations should return the new updated document.\n     * Set to false / leave blank to have these operation return the document before the update.\n     * Note: Only findOneAndUpdate and findOneAndReplace take this options\n     * findOneAndDelete will always return the old document\n     *\n     * @param returnNewDocument true if findOneAndModify operations should return the updated document\n     * @return this\n     */\n    public FindOneAndModifyOptions returnNewDocument(final boolean returnNewDocument) {\n        this.returnNewDocument = returnNewDocument;\n        return this;\n    }\n\n    @Override\n    public String toString() {\n        return \"RemoteFindOneAndModifyOptions{\"\n                + \"projection=\" + projection\n                + \", sort=\" + sort\n                + \", upsert=\" + upsert\n                + \", returnNewDocument=\" + returnNewDocument\n                + \"}\";\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/objectServer/java/io/realm/mongodb/mongo/options/FindOptions.java",
    "content": "/*\n * Copyright 2020 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\npackage io.realm.mongodb.mongo.options;\n\nimport javax.annotation.Nullable;\n\nimport org.bson.Document;\nimport org.bson.conversions.Bson;\n\nimport io.realm.annotations.Beta;\n\n/**\n * The options to apply to a find operation (also commonly referred to as a query).\n */\n@Beta\npublic class FindOptions {\n\n    private int limit;\n    private Bson projection;\n    private Bson sort;\n\n    /**\n     * Construct a new instance.\n     */\n    public FindOptions() {\n        this.projection = new Document();\n        this.sort = new Document();\n    }\n\n    /**\n     * Gets the limit to apply.  The default is null.\n     *\n     * @return the limit\n     */\n    public int getLimit() {\n        return limit;\n    }\n\n    /**\n     * Sets the limit to apply.\n     *\n     * @param limit the limit, which may be null\n     * @return this\n     */\n    public FindOptions limit(final int limit) {\n        this.limit = limit;\n        return this;\n    }\n\n    /**\n     * Gets a document describing the fields to return for all matching documents.\n     *\n     * @return the project document, which may be null\n     */\n    @Nullable\n    public Bson getProjection() {\n        return projection;\n    }\n\n    /**\n     * Sets a document describing the fields to return for all matching documents.\n     *\n     * @param projection the project document, which may be null.\n     * @return this\n     */\n    public FindOptions projection(@Nullable final Bson projection) {\n        this.projection = projection;\n        return this;\n    }\n\n    /**\n     * Gets the sort criteria to apply to the query. The default is null, which means that the\n     * documents will be returned in an undefined order.\n     *\n     * @return a document describing the sort criteria\n     */\n    @Nullable\n    public Bson getSort() {\n        return sort;\n    }\n\n    /**\n     * Sets the sort criteria to apply to the query.\n     *\n     * @param sort the sort criteria, which may be null.\n     * @return this\n     */\n    public FindOptions sort(@Nullable final Bson sort) {\n        this.sort = sort;\n        return this;\n    }\n\n    @Override\n    public String toString() {\n        return \"RemoteFindOptions{\"\n                + \"limit=\" + limit\n                + \", projection=\" + projection\n                + \", sort=\" + sort\n                + \"}\";\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/objectServer/java/io/realm/mongodb/mongo/options/InsertManyResult.java",
    "content": "/*\n * Copyright 2020 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\npackage io.realm.mongodb.mongo.options;\n\nimport java.util.Map;\n\nimport org.bson.BsonValue;\n\nimport io.realm.annotations.Beta;\n\n/**\n * The result of an insert many operation.\n */\n@Beta\npublic class InsertManyResult {\n\n    private final Map<Long, BsonValue> insertedIds;\n\n    /**\n     * Constructs a result.\n     *\n     * @param insertedIds the _ids of the inserted documents arranged by the index of the document\n     *                    from the operation and its corresponding id.\n     */\n    public InsertManyResult(final Map<Long, BsonValue> insertedIds) {\n        this.insertedIds = insertedIds;\n    }\n\n    /**\n     * Returns the _ids of the inserted documents arranged by the index of the document from the\n     * operation and its corresponding id.\n     *\n     * @return the _ids of the inserted documents arranged by the index of the document from the\n     * operation and its corresponding id.\n     */\n    public Map<Long, BsonValue> getInsertedIds() {\n        return insertedIds;\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/objectServer/java/io/realm/mongodb/mongo/options/UpdateOptions.java",
    "content": "/*\n * Copyright 2020 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\npackage io.realm.mongodb.mongo.options;\n\nimport io.realm.annotations.Beta;\n\n/**\n * The options to apply when updating documents.\n */\n@Beta\npublic class UpdateOptions {\n    private boolean upsert;\n\n    /**\n     * Returns true if a new document should be inserted if there are no matches to the query filter.\n     * The default is false.\n     *\n     * @return true if a new document should be inserted if there are no matches to the query filter\n     */\n    public boolean isUpsert() {\n        return upsert;\n    }\n\n    /**\n     * Set to true if a new document should be inserted if there are no matches to the query filter.\n     *\n     * @param upsert true if a new document should be inserted if there are no matches to the query\n     *               filter.\n     * @return this\n     */\n    public UpdateOptions upsert(final boolean upsert) {\n        this.upsert = upsert;\n        return this;\n    }\n\n    @Override\n    public String toString() {\n        return \"RemoteUpdateOptions{\"\n                + \"upsert=\" + upsert\n                + '}';\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/objectServer/java/io/realm/mongodb/mongo/result/DeleteResult.java",
    "content": "/*\n * Copyright 2020 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\npackage io.realm.mongodb.mongo.result;\n\nimport io.realm.annotations.Beta;\n\n/**\n * The result of a delete operation.\n */\n@Beta\npublic class DeleteResult {\n\n    private final long deletedCount;\n\n    /**\n     * Constructs a result.\n     *\n     * @param deletedCount the number of documents deleted.\n     */\n    public DeleteResult(final long deletedCount) {\n        this.deletedCount = deletedCount;\n    }\n\n    /**\n     * Gets the number of documents deleted.\n     *\n     * @return the number of documents deleted\n     */\n    public long getDeletedCount() {\n        return deletedCount;\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/objectServer/java/io/realm/mongodb/mongo/result/InsertOneResult.java",
    "content": "/*\n * Copyright 2020 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\npackage io.realm.mongodb.mongo.result;\n\nimport org.bson.BsonValue;\n\nimport io.realm.annotations.Beta;\n\n/**\n * The result of an insert one operation.\n */\n@Beta\npublic class InsertOneResult {\n\n    private final BsonValue insertedId;\n\n    /**\n     * Constructs a result.\n     *\n     * @param insertedId the _id of the inserted document.\n     */\n    public InsertOneResult(final BsonValue insertedId) {\n        this.insertedId = insertedId;\n    }\n\n    /**\n     * Returns the _id of the inserted document.\n     *\n     * @return the _id of the inserted document.\n     */\n    public BsonValue getInsertedId() {\n        return insertedId;\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/objectServer/java/io/realm/mongodb/mongo/result/UpdateResult.java",
    "content": "/*\n * Copyright 2020 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\npackage io.realm.mongodb.mongo.result;\n\nimport javax.annotation.Nullable;\n\nimport org.bson.BsonValue;\n\nimport io.realm.annotations.Beta;\n\n/**\n * The result of an update operation.\n */\n@Beta\npublic class UpdateResult {\n\n    private final long matchedCount;\n    private final long modifiedCount;\n    private final BsonValue upsertedId;\n\n    /**\n     * Constructs a result.\n     *\n     * @param matchedCount  the number of documents matched by the query.\n     * @param modifiedCount the number of documents modified.\n     * @param upsertedId    the _id of the inserted document if the replace resulted in an inserted\n     *                      document, otherwise null.\n     */\n    public UpdateResult(\n            final long matchedCount,\n            final long modifiedCount,\n            final BsonValue upsertedId\n    ) {\n        this.matchedCount = matchedCount;\n        this.modifiedCount = modifiedCount;\n        this.upsertedId = upsertedId;\n    }\n\n    /**\n     * Returns the number of documents matched by the query.\n     *\n     * @return the number of documents matched.\n     */\n    public long getMatchedCount() {\n        return matchedCount;\n    }\n\n    /**\n     * Returns the number of documents modified.\n     *\n     * @return the number of documents modified.\n     */\n    public long getModifiedCount() {\n        return modifiedCount;\n    }\n\n    /**\n     * If the replace resulted in an inserted document, gets the _id of the inserted document,\n     * otherwise null.\n     *\n     * @return if the replace resulted in an inserted document, the _id of the inserted document,\n     * otherwise null.\n     */\n    @Nullable\n    public BsonValue getUpsertedId() {\n        return upsertedId;\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/objectServer/java/io/realm/mongodb/push/Push.java",
    "content": "/*\n * Copyright 2020 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 */\npackage io.realm.mongodb.push;\n\nimport io.realm.RealmAsyncTask;\nimport io.realm.annotations.Beta;\nimport io.realm.internal.Util;\nimport io.realm.internal.mongodb.Request;\nimport io.realm.internal.objectstore.OsPush;\nimport io.realm.mongodb.App;\nimport io.realm.mongodb.AppException;\n\n/**\n * The Push client allows to register/deregister for push notifications from a client app.\n */\n@Beta\npublic abstract class Push {\n\n    private final OsPush osPush;\n\n    public Push(final OsPush osPush) {\n        this.osPush = osPush;\n    }\n\n    /**\n     * Registers the given FCM registration token with the currently logged in user's\n     * device on MongoDB Realm.\n     *\n     * @param registrationToken The registration token to register.\n     */\n    public void registerDevice(String registrationToken) {\n        osPush.registerDevice(registrationToken);\n    }\n\n    /**\n     * Registers the given FCM registration token with the currently logged in user's\n     * device on MongoDB Realm.\n     *\n     * @param registrationToken The registration token to register.\n     * @param callback          The callback used when the device has been registered or the call\n     *                          failed - it will always happen on the same thread as this method was\n     *                          called on.\n     */\n    public RealmAsyncTask registerDeviceAsync(String registrationToken,\n                                              App.Callback<Void> callback) {\n        Util.checkLooperThread(\"Asynchronous registering a device is only possible from looper threads.\");\n        return new Request<Void>(App.NETWORK_POOL_EXECUTOR, callback) {\n            @Override\n            public Void run() throws AppException {\n                osPush.registerDevice(registrationToken);\n                return null;\n            }\n        }.start();\n    }\n\n    /**\n     * Deregisters the FCM registration token bound to the currently logged in user's\n     * device on MongoDB Realm.\n     */\n    public void deregisterDevice() {\n        osPush.deregisterDevice();\n    }\n\n    /**\n     * Deregisters the FCM registration token bound to the currently logged in user's\n     * device on MongoDB Realm.\n     *\n     * @param callback The callback used when the device has been registered or the call\n     *                 failed - it will always happen on the same thread as this method was\n     *                 called on.\n     */\n    public RealmAsyncTask deregisterDeviceAsync(App.Callback<Void> callback) {\n        Util.checkLooperThread(\"Asynchronous deregistering a device is only possible from looper threads.\");\n        return new Request<Void>(App.NETWORK_POOL_EXECUTOR, callback) {\n            @Override\n            public Void run() throws AppException {\n                osPush.deregisterDevice();\n                return null;\n            }\n        }.start();\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/objectServer/java/io/realm/mongodb/sync/AutomaticClientResetStrategy.java",
    "content": "/*\n * Copyright 2022 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 */\npackage io.realm.mongodb.sync;\n\nimport io.realm.Realm;\n\n/**\n * Interface that defines an automatic sync client reset strategy, it could be either\n * {@link DiscardUnsyncedChangesStrategy}, {@link RecoverOrDiscardUnsyncedChangesStrategy} or\n * {@link RecoverUnsyncedChangesStrategy}.\n */\npublic interface AutomaticClientResetStrategy extends SyncClientResetStrategy {\n    /**\n     * Callback that indicates a Client Reset is about to happen. It provides a handle to the local realm\n     * before the reset.\n     *\n     * @param realm frozen {@link Realm} in its state before the reset.\n     *\n     */\n    void onBeforeReset(Realm realm);\n\n    /**\n     * Callback that indicates the Client reset failed to complete. It should be handled\n     * as {@link ManuallyRecoverUnsyncedChangesStrategy#onClientReset(SyncSession, ClientResetRequiredError)}.\n     *\n     * @param session {@link SyncSession} this error happened on.\n     * @param error   {@link ClientResetRequiredError} the specific Client Reset error.\n     */\n    void onManualResetFallback(SyncSession session, ClientResetRequiredError error);\n}\n"
  },
  {
    "path": "realm/realm-library/src/objectServer/java/io/realm/mongodb/sync/ClientResetRequiredError.java",
    "content": "/*\n * Copyright 2020 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\npackage io.realm.mongodb.sync;\n\nimport java.io.File;\n\nimport io.realm.DynamicRealm;\nimport io.realm.annotations.Beta;\nimport io.realm.mongodb.ErrorCode;\nimport io.realm.mongodb.AppException;\nimport io.realm.Realm;\nimport io.realm.RealmConfiguration;\n\n/**\n * Class encapsulating information needed for handling a Client Reset event.\n *\n * @see SyncSession.ErrorHandler#onError(SyncSession, AppException) for more information\n *      about when and why Client Reset occurs and how to deal with it.\n */\n@Beta\npublic class ClientResetRequiredError extends AppException {\n\n    private final long appNativePointer;\n    private final SyncConfiguration originalConfiguration;\n    private final RealmConfiguration backupConfiguration;\n    private final File backupFile;\n    private final File originalFile;\n\n    ClientResetRequiredError(long appNativePointer, ErrorCode errorCode, String errorMessage, SyncConfiguration originalConfiguration, RealmConfiguration backupConfiguration) {\n        super(errorCode, errorMessage);\n        this.originalConfiguration = originalConfiguration;\n        this.backupConfiguration = backupConfiguration;\n        this.backupFile = new File(backupConfiguration.getPath());\n        this.originalFile = new File(originalConfiguration.getPath());\n        this.appNativePointer = appNativePointer;\n    }\n\n    /**\n     * Calling this method will execute the Client Reset manually instead of waiting until next app restart. This will\n     * only be possible if all instances of that Realm have been closed, otherwise a {@link IllegalStateException} will\n     * be thrown.\n     * <p>\n     * After this method returns, the backup file can be found in the location returned by {@link #getBackupFile()}.\n     * The file at {@link #getOriginalFile()} have been deleted, but will be recreated from scratch next time a\n     * Realm instance is opened.\n     *\n     * @throws IllegalStateException if not all instances have been closed.\n     */\n    public void executeClientReset()  {\n        synchronized (Realm.class) {\n            if (Realm.getGlobalInstanceCount(originalConfiguration) > 0) {\n                throw new IllegalStateException(\"Realm has not been fully closed. Client Reset cannot run before all \" +\n                        \"instances have been closed.\");\n            }\n            nativeExecuteClientReset(appNativePointer, originalConfiguration.getPath());\n        }\n    }\n\n    /**\n     * Returns the location of the backed up Realm file. The file will not be present until the Client Reset has been\n     * fully executed.\n     *\n     * @return a reference to the location of the backup file once Client Reset has been executed.\n     *         Use {@code file.exists()} to check if the file exists or not.\n     *\n     */\n    public File getBackupFile() {\n        return backupFile;\n    }\n\n    /**\n     * The configuration that can be used to open the backup Realm offline. This configuration can\n     * only be used in combination with a {@link DynamicRealm}.\n     *\n     * @return the configuration that can be used to open the backup Realm offline.\n     */\n    public RealmConfiguration getBackupRealmConfiguration() {\n        return backupConfiguration;\n    }\n    /**\n     * Returns the location of the original Realm file. After the Client Reset has completed, the file at this location\n     * will be deleted.\n     *\n     * @return a reference to the location of the original Realm file. After Client Reset has been executed this file\n     *         will no longer exists. Use {@code file.exists()} to check this.\n     */\n    public File getOriginalFile() {\n        return originalFile;\n    }\n\n    // PRECONDITION: All Realm instances for this path must have been closed.\n    private native void nativeExecuteClientReset(long appNativePointer, String originalPath);\n}\n"
  },
  {
    "path": "realm/realm-library/src/objectServer/java/io/realm/mongodb/sync/ConnectionListener.java",
    "content": "/*\n * Copyright 2020 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 */\npackage io.realm.mongodb.sync;\n\nimport io.realm.annotations.Beta;\n\n/**\n * Interface used when reporting changes that happened to the connection used by the session.\n * <p>\n * Multiple sessions might re-use the same connection. In that case, any connection\n * change will be reported to all sessions.\n * <p>\n * If a disconnect happened due to an error, that error will be reported to the sessions\n * {@link SyncSession.ErrorHandler}.\n *\n * @see SyncSession#isConnected()\n * @see SyncConfiguration.Builder#errorHandler(SyncSession.ErrorHandler)\n */\n@Beta\npublic interface ConnectionListener {\n\n    /**\n     * A change in the connection to the server was detected.\n     *\n     * @param oldState the state the connection transitioned from.\n     * @param newState the state the connection transitioned to.\n     */\n    void onChange(ConnectionState oldState, ConnectionState newState);\n}\n"
  },
  {
    "path": "realm/realm-library/src/objectServer/java/io/realm/mongodb/sync/ConnectionState.java",
    "content": "/*\n * Copyright 2020 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\npackage io.realm.mongodb.sync;\n\nimport io.realm.annotations.Beta;\n\n/**\n * Enum describing the states of the underlying connection used by a {@link SyncSession}.\n */\n@Beta\npublic enum ConnectionState {\n\n    /**\n     * No connection to the server exists. No data is being transferred even if the session\n     * is {@link SyncSession.State#ACTIVE}. If the connection entered this state due to an error, this\n     * error will be reported to the {@link SyncSession.ErrorHandler}.\n     */\n    DISCONNECTED(SyncSession.CONNECTION_VALUE_DISCONNECTED),\n\n    /**\n     * A connection is currently in progress of being established. If successful the next\n     * state is {@link #CONNECTED}. If the connection fails it will be {@link #DISCONNECTED}.\n     */\n    CONNECTING(SyncSession.CONNECTION_VALUE_CONNECTING),\n\n    /**\n     * A connection was successfully established to the server. If the SyncSession is {@link SyncSession.State#ACTIVE}\n     * data will now be transferred between the device and the server.\n     */\n    CONNECTED(SyncSession.CONNECTION_VALUE_CONNECTED);\n\n    final int value;\n\n    ConnectionState(int value) {\n        this.value = value;\n    }\n\n    static ConnectionState fromNativeValue(long value) {\n        ConnectionState[] stateCodes = values();\n        for (ConnectionState state : stateCodes) {\n            if (state.value == value) {\n                return state;\n            }\n        }\n\n        throw new IllegalArgumentException(\"Unknown connection state code: \" + value);\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/objectServer/java/io/realm/mongodb/sync/DiscardUnsyncedChangesStrategy.java",
    "content": "/*\n * Copyright 2021 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 */\npackage io.realm.mongodb.sync;\n\nimport io.realm.Realm;\n\n/**\n * Strategy that automatically resolves a Client Reset by discarding any unsynced data. Unlike\n * {@link ManuallyRecoverUnsyncedChangesStrategy} there is no need to close Realm instances before\n * performing the client reset. Once completed changes will be reported through the normal collection and\n * object notifications.\n * <p>\n * A synced Realm may need to be reset because the MongoDB Realm Server encountered an error and had\n * to be restored from a backup or because it has been too long since the client connected to the\n * server so the server has rotated the logs.\n * <p>\n * The Client Reset thus occurs because the server does not have the full information required to\n * bring the Client fully up to date.\n * <p>\n * The discard unsynced changes process is as follows: when a client reset is received by the client\n * the {@link #onBeforeReset(Realm)} callback is invoked, then the client would be reset. Once the reset\n * has concluded the callback {@link #onAfterReset(Realm, Realm)} would be invoked if the changes have\n * been discarded successfully.\n * <p>\n * In the event that the client reset could not discard the unsynced data the\n * {@link #onManualResetFallback(SyncSession, ClientResetRequiredError)} would be invoked. It allows\n * to manually resolve the reset as it would have been done in\n * {@link ManuallyRecoverUnsyncedChangesStrategy#onClientReset(SyncSession, ClientResetRequiredError)}.\n */\npublic interface DiscardUnsyncedChangesStrategy extends AutomaticClientResetStrategy {\n\n    /**\n     * {@inheritDoc}\n     */\n    @Override\n    void onBeforeReset(Realm realm);\n\n    /**\n     * Callback invoked before the Client Reset discards any unsynced changes. It provides\n     * two Realm instances, a frozen one displaying the state before the reset and a regular Realm\n     * displaying the current state that can be used to recover any unsynced changes from being discarded.\n     *\n     * @param before {@link Realm} frozen Realm in the before after the reset.\n     * @param after  {@link Realm} Realm after the reset.\n     */\n    void onAfterReset(Realm before, Realm after);\n\n    /**\n     * Callback that indicates the Client reset failed to complete. It should be handled\n     * as {@link ManuallyRecoverUnsyncedChangesStrategy#onClientReset(SyncSession, ClientResetRequiredError)}.\n     *\n     * @param session {@link SyncSession} this error happened on.\n     * @param error   {@link ClientResetRequiredError} the specific Client Reset error.\n     *\n     * @deprecated Use {@link DiscardUnsyncedChangesStrategy#onManualResetFallback} instead.\n     */\n    @Deprecated\n    void onError(SyncSession session, ClientResetRequiredError error);\n\n    /**\n     * {@inheritDoc}\n     */\n    @Override\n    void onManualResetFallback(SyncSession session, ClientResetRequiredError error);\n}\n"
  },
  {
    "path": "realm/realm-library/src/objectServer/java/io/realm/mongodb/sync/ManuallyRecoverUnsyncedChangesStrategy.java",
    "content": "/*\n * Copyright 2021 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 */\npackage io.realm.mongodb.sync;\n\nimport io.realm.mongodb.ErrorCode;\n\n/**\n * Strategy to manually resolve a Client Reset, determined by the error code\n * {@link ErrorCode#CLIENT_RESET}.\n * <p>\n * A synced Realm may need to be reset because the MongoDB Realm Server encountered an error and had\n * to be restored from a backup or because it has been too long since the client connected to the\n * server so the server has rotated the logs.\n * <p>\n * The Client Reset thus occurs because the server does not have the full information required to\n * bring the Client fully up to date.\n * <p>\n * The manual reset process is as follows: the local copy of the Realm is copied into a recovery directory\n * for safekeeping, and then deleted from the original location. The next time the Realm for that\n * URL is opened, the Realm will automatically be re-downloaded from MongoDB Realm, and\n * can be used as normal.\n * <p>\n * Data written to the Realm after the local copy of the Realm diverged from the backup remote copy\n * will be present in the local recovery copy of the Realm file. The re-downloaded Realm will\n * initially contain only the data present at the time the Realm was backed up on the server.\n * <p>\n * The client reset process can be initiated in one of two ways:\n * <ol>\n *     <li>\n *         Run {@link ClientResetRequiredError#executeClientReset()} manually. All Realm instances must be\n *         closed before this method is called.\n *     </li>\n *     <li>\n *         If Client Reset isn't executed manually, it will automatically be carried out the next time all\n *         Realm instances have been closed and re-opened. This will most likely be\n *         when the app is restarted.\n *     </li>\n * </ol>\n *\n * <b>WARNING:</b>\n * Any writes to the Realm file between this callback and Client Reset has been executed, will not be\n * synchronized to MongoDB Realm. Those changes will only be present in the backed up file. It is therefore\n * recommended to close all open Realm instances as soon as possible.\n */\npublic interface ManuallyRecoverUnsyncedChangesStrategy extends SyncClientResetStrategy {\n    /**\n     * Callback that indicates a Client Reset has happened. This should be handled as quickly as\n     * possible as any further changes to the Realm will not be synchronized with the server and\n     * must be moved manually from the backup Realm to the new one.\n     *\n     * @param session {@link SyncSession} this error happened on.\n     * @param error   {@link ClientResetRequiredError} the specific Client Reset error.\n     */\n    void onClientReset(SyncSession session, ClientResetRequiredError error);\n}\n"
  },
  {
    "path": "realm/realm-library/src/objectServer/java/io/realm/mongodb/sync/Progress.java",
    "content": "/*\n * Copyright 2020 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\npackage io.realm.mongodb.sync;\n\nimport io.realm.annotations.Beta;\nimport io.realm.log.RealmLog;\n\n\n/**\n * Class used to encapsulate progress notifications when either downloading or uploading Realm data.\n * Each instance of this class is an immutable snapshot of the current progress.\n * <p>\n * If the {@link ProgressListener} was registered with {@link ProgressMode#INDEFINITELY}, the progress reported by\n * {@link #getFractionTransferred()} can both increase and decrease since more changes might be added while\n * the progres listener is registered. This means it is possible for one notification to report\n * {@code true} for {@link #isTransferComplete()}, and then on the next event report {@code false}.\n * <p>\n * If the {@link ProgressListener} was registered with {@link ProgressMode#CURRENT_CHANGES}, progress can only ever\n * increase, and once {@link #isTransferComplete()} returns {@code true}, no further events will be generated.\n *\n * @see SyncSession#addDownloadProgressListener(ProgressMode, ProgressListener)\n * @see SyncSession#addUploadProgressListener(ProgressMode, ProgressListener)\n */\n@Beta\npublic class Progress {\n\n    private final long transferredBytes;\n    private final long transferableBytes;\n\n    /**\n     * Creates a snapshot of the current progress when downloading or uploading changes.\n     *\n     * @param transferredBytes number of bytes transferred.\n     * @param transferableBytes total number of bytes that needs to be transferred (including those already transferred).\n     */\n    Progress(long transferredBytes, long transferableBytes) {\n        this.transferredBytes = transferredBytes;\n        this.transferableBytes = transferableBytes;\n    }\n\n    /**\n     * Returns the total number of bytes that has been transferred since the {@link ProgressListener} was added.\n     *\n     * @return the total number of bytes transferred since the {@link ProgressListener} was added.\n     */\n    public long getTransferredBytes() {\n        return transferredBytes;\n    }\n\n    /**\n     * Returns the total number of transferable bytes (bytes that have been transferred + bytes pending transfer).\n     * <p>\n     * If the {@link ProgressListener} is tracking downloads, this number represents the size of the changesets\n     * generated by all other clients using the Realm.\n     * <p>\n     * If the {@link ProgressListener} is tracking uploads, this number represents the size of changesets created\n     * locally.\n     *\n     * @return the total number of bytes that has been transferred + number of bytes still pending transfer.\n     */\n    public long getTransferableBytes() {\n        return transferableBytes;\n    }\n\n    /**\n     * The fraction of bytes transferred out of all transferable bytes. Counting from since the {@link ProgressListener}\n     * was added.\n     *\n     * @return a number between {@code 0.0} and {@code 1.0}, where {@code 0.0} represents that no data has been\n     * transferred yet, and {@code 1.0} that all data has been transferred.\n     */\n    public double getFractionTransferred() {\n        if (transferableBytes == 0) {\n            return 1.0D;\n        } else {\n            double percentage = (double) transferredBytes / (double) transferableBytes;\n            if (percentage > 1.0D) {\n                RealmLog.error(\"Invalid progress state: %s\", this);\n                return 1.0D;\n            } else {\n                return percentage;\n            }\n        }\n    }\n\n    /**\n     * Returns {@code true} when all pending bytes have been transferred.\n     * <p>\n     * If the {@link ProgressListener} was registered with {@link ProgressMode#INDEFINITELY}, this method can return\n     * {@code false} for subsequent events after returning {@code true}.\n     * <p>\n     * If the {@link ProgressListener} was registered with {@link ProgressMode#CURRENT_CHANGES}, when this method\n     * returns {@code true}, no more progress events will be sent.\n     *\n     * @return {@code true} if all changes have been transferred, {@code false} otherwise.\n     */\n    public boolean isTransferComplete() {\n        return transferredBytes >= transferableBytes;\n    }\n\n    @Override\n    public boolean equals(Object o) {\n        if (this == o) return true;\n        if (o == null || getClass() != o.getClass()) return false;\n\n        Progress progress = (Progress) o;\n\n        if (transferredBytes != progress.transferredBytes) return false;\n        return transferableBytes == progress.transferableBytes;\n\n    }\n\n    @Override\n    public int hashCode() {\n        int result = (int) (transferredBytes ^ (transferredBytes >>> 32));\n        result = 31 * result + (int) (transferableBytes ^ (transferableBytes >>> 32));\n        return result;\n    }\n\n    @Override\n    public String toString() {\n        return \"Progress{\" +\n                \"transferredBytes=\" + transferredBytes +\n                \", transferableBytes=\" + transferableBytes +\n                '}';\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/objectServer/java/io/realm/mongodb/sync/ProgressListener.java",
    "content": "/*\n * Copyright 2020 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\npackage io.realm.mongodb.sync;\n\n\nimport io.realm.annotations.Beta;\n\n/**\n * Interface used when interested in updates on data either being uploaded to or downloaded from\n * a Realm Object Server.\n */\n@Beta\npublic interface ProgressListener {\n    /**\n     * This method will be called periodically from the underlying Object Server Client responsible\n     * for uploading and downloading changes from the remote Object Server.\n     * <p>\n     * This callback will <i>not</i> happen on the UI thread, but on the worker thread controlling\n     * the Object Server Client. Use {@code Activity.runOnUiThread(Runnable)} or similar to update\n     * any UI elements.\n     * <p>\n     * <pre>\n     * {@code\n     * // Adding an upload progress listener that completes when all known changes have been\n     * // uploaded.\n     * session.addUploadProgressListener(ProgressMode.CURRENT_CHANGES, new ProgressListener() {\n     *   \\@Override\n     *    public void onChange(Progress progress) {\n     *      activity.runOnUiThread(new Runnable() {\n     *        \\@Override\n     *         public void run() {\n     *           updateProgressBar(progress);\n     *         }\n     *      });\n     *      if (progress.isTransferComplete() {\n     *        session.removeProgressListener(this);\n     *      }\n     *    }\n     * });\n     * }\n     * </pre>\n     *\n     * @param progress an immutable progress change event with information about current progress. This object is thread safe.\n     */\n    void onChange(Progress progress);\n}\n"
  },
  {
    "path": "realm/realm-library/src/objectServer/java/io/realm/mongodb/sync/ProgressMode.java",
    "content": "/*\n * Copyright 2020 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\npackage io.realm.mongodb.sync;\n\nimport io.realm.annotations.Beta;\n\n/**\n * Enum describing how to listen to progress changes.\n */\n@Beta\npublic enum ProgressMode {\n    /**\n     * When registering the {@link ProgressListener}, it will record the current size of changes, and will only\n     * continue to report progress updates until those changes have been either downloaded or uploaded. After that\n     * the progress listener will not report any further changes.\n     * <p>\n     * This means that listeners registered in this mode should be done <i>before</i> changes are written to\n     * the Realm.\n     * <p>\n     * Progress reported in this mode will only ever increase.\n     * <p>\n     * This is useful when e.g. reporting progress when downloading a Realm for the first time.\n     */\n    CURRENT_CHANGES,\n\n    /**\n     * A {@link ProgressListener} registered in this mode, will continue to report progress changes, even\n     * if changes are being added after the listener was registered.\n     * <p>\n     * Progress reported in this mode can both increase and decrease, e.g. if large amounts of data is\n     * written after registering the listener.\n     * <p>\n     * This is useful when you want to track if all changes have been uploaded to the server from the device.\n     */\n    INDEFINITELY\n}\n"
  },
  {
    "path": "realm/realm-library/src/objectServer/java/io/realm/mongodb/sync/RecoverOrDiscardUnsyncedChangesStrategy.java",
    "content": "/*\n * Copyright 2022 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 */\npackage io.realm.mongodb.sync;\n\nimport io.realm.Realm;\n\n/**\n * Strategy that attempts to automatically recover any unsynced changes during a Client Reset, if the \n * recovery fails the changes would be discarded.\n * <p>\n * A synced Realm may need to be reset because the MongoDB Realm Server encountered an error and had\n * to be restored from a backup or because it has been too long since the client connected to the\n * server so the server has rotated the logs.\n * <p>\n * The Client Reset thus occurs because the server does not have the full information required to\n * bring the Client fully up to date.\n * <p>\n * The recover or discard unsynced changes process is as follows: when a client reset is received by \n * the client the {@link #onBeforeReset(Realm)} callback is invoked, then the client would be reset. \n * Once the reset has concluded the callback {@link #onAfterRecovery(Realm, Realm)} (Realm, Realm)} \n * would be invoked if the changes have been recovered successfully, otherwise the changes would be \n * discarded and {@link #onAfterDiscard(Realm, Realm)} (Realm, Realm)} (Realm, Realm)} would be invoked.\n * <p>\n * In the event that the client reset could not discard the unsynced data the\n * {@link #onManualResetFallback(SyncSession, ClientResetRequiredError)} would be invoked. It allows to manually\n * resolve the reset as it would have been done in\n * {@link ManuallyRecoverUnsyncedChangesStrategy#onClientReset(SyncSession, ClientResetRequiredError)}.\n */\npublic interface RecoverOrDiscardUnsyncedChangesStrategy extends AutomaticClientResetStrategy {\n    /**\n     * {@inheritDoc}\n     */\n    @Override\n    void onBeforeReset(Realm realm);\n\n    /**\n     * Callback invoked once the Client Reset has recovered the unsynced changes successfully.\n     * It provides two Realm instances, a frozen one displaying the state before the reset and a\n     * regular Realm with the current state.\n     *\n     * @param before {@link Realm} frozen Realm in the state before the reset.\n     * @param after  {@link Realm} Realm after the reset.\n     */\n    void onAfterRecovery(Realm before, Realm after);\n\n    /**\n     * Callback invoked before the Client Reset discards any unsynced changes because the recovery\n     * failed. It provides two Realm instances, a frozen one displaying the state before the reset\n     * and a regular Realm displaying the current state that can be used to recover objects from the\n     * reset.\n     *\n     * @param before {@link Realm} frozen Realm in the state before the reset.\n     * @param after  {@link Realm} Realm after the reset.\n     */\n    void onAfterDiscard(Realm before, Realm after);\n\n    /**\n     * {@inheritDoc}\n     */\n    @Override\n    void onManualResetFallback(SyncSession session, ClientResetRequiredError error);\n}\n"
  },
  {
    "path": "realm/realm-library/src/objectServer/java/io/realm/mongodb/sync/RecoverUnsyncedChangesStrategy.java",
    "content": "/*\n * Copyright 2022 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 */\npackage io.realm.mongodb.sync;\n\nimport io.realm.Realm;\n\n/**\n * Strategy that attempts to automatically recover any unsynced changes during a Client Reset.\n * <p>\n * A synced Realm may need to be reset because the MongoDB Realm Server encountered an error and had\n * to be restored from a backup or because it has been too long since the client connected to the\n * server so the server has rotated the logs.\n * <p>\n * The Client Reset thus occurs because the server does not have the full information required to\n * bring the Client fully up to date.\n * <p>\n * The recover unsynced changes process is as follows: when a client reset is received by the client\n * the {@link #onBeforeReset(Realm)} callback is invoked, then the client would be reset. Once the reset\n * has concluded the callback {@link #onAfterReset(Realm, Realm)} would be invoked if the changes have\n * been recovered successfully.\n * <p>\n * In the event that the client reset could not automatically recover the unsynced data the\n * {@link #onManualResetFallback(SyncSession, ClientResetRequiredError)} would be invoked. It allows to manually\n * resolve the reset as it would have been done in\n * {@link ManuallyRecoverUnsyncedChangesStrategy#onClientReset(SyncSession, ClientResetRequiredError)}.\n\n */\npublic interface RecoverUnsyncedChangesStrategy extends AutomaticClientResetStrategy {\n    /**\n     * {@inheritDoc}\n     */\n    @Override\n    void onBeforeReset(Realm realm);\n\n    /**\n     * Callback invoked after a client reset has recovered the unsynced changes successfully. It provides\n     * two realm instances, a frozen one displaying the state before the reset and a regular realm with\n     * the current state.\n     *\n     * @param before the frozen realm from before the reset.\n     * @param after  {@link Realm} Realm after the reset.\n     */\n    void onAfterReset(Realm before, Realm after);\n\n    /**\n     * {@inheritDoc}\n     */\n    @Override\n    void onManualResetFallback(SyncSession session, ClientResetRequiredError error);\n}\n"
  },
  {
    "path": "realm/realm-library/src/objectServer/java/io/realm/mongodb/sync/Sync.java",
    "content": "/*\n * Copyright 2020 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\npackage io.realm.mongodb.sync;\n\nimport org.bson.BsonValue;\n\nimport java.io.ByteArrayInputStream;\nimport java.io.IOException;\nimport java.io.InputStream;\nimport java.security.GeneralSecurityException;\nimport java.security.KeyStore;\nimport java.security.cert.CertificateException;\nimport java.security.cert.CertificateFactory;\nimport java.security.cert.X509Certificate;\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.Collection;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.concurrent.ConcurrentHashMap;\n\nimport javax.annotation.Nullable;\nimport javax.net.ssl.TrustManager;\nimport javax.net.ssl.TrustManagerFactory;\nimport javax.net.ssl.X509TrustManager;\n\nimport edu.umd.cs.findbugs.annotations.SuppressFBWarnings;\nimport io.realm.annotations.Beta;\nimport io.realm.internal.ErrorCategory;\nimport io.realm.internal.jni.JniBsonProtocol;\nimport io.realm.mongodb.AppConfiguration;\nimport io.realm.mongodb.ErrorCode;\nimport io.realm.internal.Keep;\nimport io.realm.internal.network.NetworkStateReceiver;\nimport io.realm.log.RealmLog;\nimport io.realm.mongodb.App;\nimport okhttp3.internal.tls.OkHostnameVerifier;\n\n/**\n * A <i>sync</i> manager handling synchronization of local Realms with remote Realm Apps.\n * <p>\n * The primary role of this is to access the {@link SyncSession} for a synchronized Realm. After\n * opening the synchronized Realm you can access the {@link SyncSession} and perform synchronization\n * related operations as shown below:\n * <pre>\n *     App app = new App(\"app-id\");\n *     User user = app.login(Credentials.anonymous());\n *     SyncConfiguration syncConfiguration = new SyncConfiguration.Builder(user, \"&lt;partition value&gt;\")\n *              .build();\n *     Realm instance = Realm.getInstance(syncConfiguration);\n *     SyncSession session = app.getSync().getSession(syncConfiguration);\n *\n *     instance.executeTransaction(realm -&gt; {\n *         realm.insert(...);\n *     });\n *     session.uploadAllLocalChanges();\n *     instance.close();\n * </pre>\n *\n * @see App#getSync()\n * @see Sync#getSession(SyncConfiguration)\n */\n@Keep\n@SuppressFBWarnings(\"MS_CANNOT_BE_FINAL\")\n@Beta\npublic abstract class Sync {\n\n    private final App app;\n    private final long appNativePointer;\n    // keeps track of SyncSession, using 'realm_path'. Java interface with the ObjectStore using the 'realm_path'\n    private Map<String, SyncSession> sessions = new ConcurrentHashMap<>();\n\n    protected Sync(App app, long appNativePointer) {\n        this.app = app;\n        this.appNativePointer = appNativePointer;\n    }\n\n    /**\n     * Debugging related options.\n     */\n    @SuppressFBWarnings(\"MS_SHOULD_BE_FINAL\")\n    public static class Debug {\n        /**\n         * Set this to true to bypass checking if the device is offline before making HTTP requests.\n         */\n        public static boolean skipOnlineChecking = false;\n\n        /**\n         * Set this to true to init a SyncManager with a directory named by the process ID. This is useful for\n         * integration tests which are emulating multiple sync client by using multiple processes.\n         */\n        public static boolean separatedDirForSyncManager = false;\n    }\n\n    private NetworkStateReceiver.ConnectionListener networkListener = new NetworkStateReceiver.ConnectionListener() {\n        @Override\n        public void onChange(boolean connectionAvailable) {\n            if (connectionAvailable) {\n                RealmLog.debug(\"[App(%s)] NetworkListener: Connection available\", app.getConfiguration().getAppId());\n                // notify all sessions\n                notifyNetworkIsBack();\n            } else {\n                RealmLog.debug(\"[App(%s)] NetworkListener: Connection lost\", app.getConfiguration().getAppId());\n            }\n        }\n    };\n\n    /**\n     * Gets a cached {@link SyncSession} for the given {@link SyncConfiguration} or throw if no one exists yet.\n     *\n     * A session should exist after you open a Realm with a {@link SyncConfiguration}.\n     *\n     * @param syncConfiguration configuration object for the synchronized Realm.\n     * @return the {@link SyncSession} for the specified Realm.\n     * @throws IllegalArgumentException if syncConfiguration is {@code null}.\n     * @throws IllegalStateException if the session could not be found using the provided {@code SyncConfiguration}.\n     */\n    public synchronized SyncSession getSession(SyncConfiguration syncConfiguration) throws IllegalStateException {\n        //noinspection ConstantConditions\n        if (syncConfiguration == null) {\n            throw new IllegalArgumentException(\"A non-empty 'syncConfiguration' is required.\");\n        }\n\n        SyncSession session = sessions.get(syncConfiguration.getPath());\n        if (session == null) {\n            throw new IllegalStateException(\"No SyncSession found using the path : \" + syncConfiguration.getPath()\n                    + \"\\nplease ensure to call this method after you've open the Realm\");\n        }\n\n        return session;\n    }\n\n    /**\n     * Gets a collection of all the cached {@link SyncSession}.\n     *\n     * @return a collection of {@link SyncSession}.\n     */\n    public synchronized Collection<SyncSession> getAllSessions(){\n        return this.sessions.values();\n    }\n\n    /**\n     * Gets any cached {@link SyncSession} for the given {@link SyncConfiguration} or create a new one if\n     * no one exists.\n     *\n     * Note: This is mainly for internal usage, consider using {@link #getSession(SyncConfiguration)} instead.\n     *\n     * @param syncConfiguration configuration object for the synchronized Realm.\n     * @return the {@link SyncSession} for the specified Realm.\n     * @throws IllegalArgumentException if syncConfiguration is {@code null}.\n     */\n    public synchronized SyncSession getOrCreateSession(SyncConfiguration syncConfiguration) {\n        // This will not create a new native (Object Store) session, this will only associate a Realm's path\n        // with a SyncSession. Object Store's SyncManager is responsible of the life cycle (including creation)\n        // of the native session. The provided Java wrap, helps interact with the native session, when reporting error\n        // or requesting an access_token for example.\n\n        //noinspection ConstantConditions\n        if (syncConfiguration == null) {\n            throw new IllegalArgumentException(\"A non-empty 'syncConfiguration' is required.\");\n        }\n\n        SyncSession session = sessions.get(syncConfiguration.getPath());\n        if (session == null) {\n            RealmLog.debug(\"Creating session for: %s\", syncConfiguration.getPath());\n            session = new SyncSession(syncConfiguration, appNativePointer);\n            sessions.put(syncConfiguration.getPath(), session);\n            if (sessions.size() == 1) {\n                RealmLog.debug(\"First session created. Adding network listener.\");\n                NetworkStateReceiver.addListener(networkListener);\n            }\n        }\n\n        return session;\n    }\n\n    /**\n     * Returns the absolute path for the location of the Realm file on disk.\n     * Partition-based sync files will construct their name from the partition value while Flexible\n     * Sync Realms will use \"default.realm\" unless overriden.\n     */\n    String getAbsolutePathForRealm(String userId, @Nullable BsonValue partitionValue, @Nullable String overrideFileName) {\n        String encodedPartitionValue;\n        if (partitionValue != null) {\n            switch (partitionValue.getBsonType()) {\n                case STRING:\n                case OBJECT_ID:\n                case INT32:\n                case INT64:\n                    // Only way to here is through Realm API's which only allow UUID's. So we can safely\n                    // just convert it to a Bson binary which will give it its correct UUID subtype.\n                case BINARY:\n                case NULL:\n                    encodedPartitionValue = JniBsonProtocol.encode(partitionValue, AppConfiguration.DEFAULT_BSON_CODEC_REGISTRY);\n                    break;\n                default:\n                    throw new IllegalArgumentException(\"Unsupported type: \" + partitionValue);\n            }\n        } else {\n            // Encode a dummy value for Flexible Sync Realms, it will be ignored by the native codepaths\n            // anyway, but is currently required due to how the native code is wired together when\n            // creating the synced Realm paths.\n            encodedPartitionValue = JniBsonProtocol.encode(\"\", AppConfiguration.DEFAULT_BSON_CODEC_REGISTRY);\n            if (overrideFileName == null) {\n                overrideFileName = \"default\";\n            }\n        }\n        return nativeGetPathForRealm(appNativePointer, userId, encodedPartitionValue, overrideFileName);\n    }\n\n    /**\n     * Remove the wrapped Java session.\n     * @param syncConfiguration configuration object for the synchronized Realm.\n     */\n    @SuppressWarnings(\"unused\")\n    private synchronized void removeSession(SyncConfiguration syncConfiguration) {\n        //noinspection ConstantConditions\n        if (syncConfiguration == null) {\n            throw new IllegalArgumentException(\"A non-empty 'syncConfiguration' is required.\");\n        }\n        RealmLog.debug(\"Removing session for: %s\", syncConfiguration.getPath());\n        SyncSession syncSession = sessions.remove(syncConfiguration.getPath());\n        if (syncSession != null) {\n            syncSession.close();\n        }\n        if (sessions.isEmpty()) {\n            RealmLog.debug(\"Last session dropped. Remove network listener.\");\n            NetworkStateReceiver.removeListener(networkListener);\n        }\n    }\n\n    /**\n     * All errors from native Sync is reported to this method. From the path we can determine which\n     * session to contact.\n     */\n    @SuppressWarnings(\"unused\")\n    private void notifyErrorHandler(\n            byte nativeErrorCategory,\n            int nativeErrorCode,\n            String errorMessage,\n            String logUrl,\n            String clientResetPathInfo,\n            String path\n    ) {\n        ErrorCode errCode = ErrorCode.fromNativeError(ErrorCategory.toCategory(nativeErrorCategory), nativeErrorCode);\n\n        if (errCode == ErrorCode.CLIENT_RESET) {\n            // Avoid deadlock while trying to close realm instances during a client reset\n            // Not acquiring the lock here would allow acquiring it later on when we try to close the\n            // session in `Sync.removeSession()`.\n            doNotifyError(nativeErrorCategory, nativeErrorCode, errorMessage, clientResetPathInfo, path);\n        } else {\n            // Keep the logic for the rest of the sync errors\n            synchronized (this) {\n                doNotifyError(nativeErrorCategory, nativeErrorCode, errorMessage, clientResetPathInfo, path);\n            }\n        }\n    }\n\n    private void doNotifyError(byte nativeErrorCategory, int nativeErrorCode, String errorMessage, String clientResetPathInfo, String path) {\n        SyncSession syncSession = sessions.get(path);\n        if (syncSession != null) {\n            try {\n                syncSession.notifySessionError(nativeErrorCategory, nativeErrorCode, errorMessage, clientResetPathInfo);\n            } catch (Exception exception) {\n                RealmLog.error(exception);\n            }\n        } else {\n            RealmLog.warn(\"Cannot find the SyncSession corresponding to the path: \" + path);\n        }\n    }\n\n    private synchronized void notifyNetworkIsBack() {\n        try {\n            nativeReconnect(appNativePointer);\n        } catch (Exception exception) {\n            RealmLog.error(exception);\n        }\n    }\n\n    /**\n     * All progress listener events from native Sync are reported to this method.\n     * It costs 2 HashMap lookups for each listener triggered (one to find the session, one to\n     * find the progress listener), but it means we don't have to cache anything on the C++ side which\n     * can leak since we don't have control over the session lifecycle.\n     */\n    @SuppressWarnings(\"unused\")\n    private synchronized void notifyProgressListener(String localRealmPath, long listenerId, long transferedBytes, long transferableBytes) {\n        SyncSession session = sessions.get(localRealmPath);\n        if (session != null) {\n            try {\n                session.notifyProgressListener(listenerId, transferedBytes, transferableBytes);\n            } catch (Exception exception) {\n                RealmLog.error(exception);\n            }\n        }\n    }\n\n    /**\n     * Realm will automatically detect when a device gets connectivity after being offline and\n     * resume syncing.\n     * <p>\n     * However, as some of these checks are performed using incremental backoff, this will in some\n     * cases not happen immediately.\n     * <p>\n     * In those cases it can be beneficial to call this method manually, which will force all\n     * sessions to attempt to reconnect immediately and reset any timers they are using for\n     * incremental backoff.\n     */\n    public void reconnect() {\n        notifyNetworkIsBack();\n    }\n\n    /**\n     * Resets the SyncManger and clear all existing users.\n     * This will also terminate all sessions.\n     *\n     * Only call this method when testing.\n     */\n    synchronized void reset() {\n        nativeReset(appNativePointer);\n        sessions.clear();\n    }\n\n    /**\n     * Simulate a Client Reset by triggering the Object Store error handler with Sync Error Code that will be\n     * converted to a Client Reset (211 - Diverging Histories).\n     *\n     * Only call this method when testing.\n     *\n     * WARNING: This method will not prepare the metadata for an actual Client Reset, thus trying\n     * to call `ClientResetRequiredError.executeClientReset()` will not actually work, since the\n     * underlying metadata has not been correctly modified.\n     *\n     * @param session Session to trigger Client Reset for.\n     */\n    void simulateClientReset(SyncSession session) {\n        // Client reset events are thrown from the sync client thread. We need to invoke the `simulateClientReset`\n        // on a different thread to fully simulate the scenario.\n        new Thread(() -> simulateClientReset(session, ErrorCode.DIVERGING_HISTORIES), \"Simulated sync thread\").start();\n    }\n\n    /**\n     * Simulate a Client Reset by triggering the Object Store error handler\n     *\n     * Only call this method when testing.\n     *\n     * @param session Session to trigger Client Reset for.\n     * @param errorCode error code to simulate.\n     */\n    void simulateClientReset(SyncSession session, ErrorCode errorCode) {\n        nativeSimulateSyncError(appNativePointer,\n                session.getConfiguration().getPath(),\n                errorCode.intValue(),\n                errorCode.getType(),\n                \"Simulate Client Reset\",\n                true);\n    }\n\n    // Holds the certificate chain (per hostname). We need to keep the order of each certificate\n    // according to it's depth in the chain. The depth of the last\n    // certificate is 0. The depth of the first certificate is chain\n    // length - 1.\n    private static HashMap<String, List<String>> ATLAS_CERTIFICATES_CHAIN;\n\n    // The default Android Trust Manager which uses the default KeyStore to\n    // validate the certificate chain.\n    private static X509TrustManager TRUST_MANAGER;\n\n    // Help transform a String PEM representation of the certificate, into\n    // X509Certificate format.\n    private static CertificateFactory CERTIFICATE_FACTORY;\n\n    // From Sync implementation:\n    //  A recommended way of using the callback function is to return true\n    //  if preverify_ok = 1 and depth > 0,\n    //  always check the host name if depth = 0,\n    //  and use an independent verification step if preverify_ok = 0.\n    //\n    //  Another possible way of using the callback is to collect all the\n    //  ROS_CERTIFICATES_CHAIN until depth = 0, and present the entire chain for\n    //  independent verification.\n    //\n    // In this implementation we use the second method, since it's more suitable for\n    // the underlying Java API we need to call to validate the certificate chain.\n    @SuppressWarnings(\"unused\")\n    static synchronized boolean sslVerifyCallback(String serverAddress, String pemData, int depth) {\n        try {\n            if (ATLAS_CERTIFICATES_CHAIN == null) {\n                ATLAS_CERTIFICATES_CHAIN = new HashMap<>();\n                TRUST_MANAGER = systemDefaultTrustManager();\n                CERTIFICATE_FACTORY = CertificateFactory.getInstance(\"X.509\");\n            }\n\n            if (!ATLAS_CERTIFICATES_CHAIN.containsKey(serverAddress)) {\n                ATLAS_CERTIFICATES_CHAIN.put(serverAddress, new ArrayList<String>());\n            }\n\n            ATLAS_CERTIFICATES_CHAIN.get(serverAddress).add(pemData);\n\n            if (depth == 0) {\n                // transform all PEM ROS_CERTIFICATES_CHAIN into Java X509\n                // with respecting the order/depth provided from Sync.\n                List<String> pemChain = ATLAS_CERTIFICATES_CHAIN.get(serverAddress);\n                int n = pemChain.size();\n                X509Certificate[] chain = new X509Certificate[n];\n                for (String pem : pemChain) {\n                    // The depth of the last certificate is 0.\n                    // The depth of the first certificate is chain length - 1.\n                    chain[--n] = buildCertificateFromPEM(pem);\n                }\n\n                // verify the entire chain\n                try {\n                    TRUST_MANAGER.checkClientTrusted(chain, \"RSA\");\n                    // verify the hostname\n                    boolean isValid = OkHostnameVerifier.INSTANCE.verify(serverAddress, chain[0]);\n                    if (isValid) {\n                        return true;\n                    } else {\n                        RealmLog.error(\"Can not verify the hostname for the host: \" + serverAddress);\n                        return false;\n                    }\n                } catch (CertificateException e) {\n                    RealmLog.error(e, \"Can not validate SSL chain certificate for the host: \" + serverAddress);\n                    return false;\n                } finally {\n                    // don't keep the certificate chain in memory\n                    ATLAS_CERTIFICATES_CHAIN.remove(serverAddress);\n                }\n            } else {\n                // return true, since the verification will happen for the entire chain\n                // when receiving the depth == 0 (host certificate)\n                return true;\n            }\n        } catch (Exception e) {\n            RealmLog.error(e, \"Error during certificate validation for host: \" + serverAddress);\n            return false;\n        }\n    }\n\n    // Credit OkHttp https://github.com/square/okhttp/blob/e5c84e1aef9572adb493197c1b6c4e882aca085b/okhttp/src/main/java/okhttp3/OkHttpClient.java#L270\n    private static X509TrustManager systemDefaultTrustManager() {\n        try {\n            TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(\n                    TrustManagerFactory.getDefaultAlgorithm());\n            trustManagerFactory.init((KeyStore) null);\n            TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();\n            if (trustManagers.length != 1 || !(trustManagers[0] instanceof X509TrustManager)) {\n                throw new IllegalStateException(\"Unexpected default trust managers:\"\n                        + Arrays.toString(trustManagers));\n            }\n            return (X509TrustManager) trustManagers[0];\n        } catch (GeneralSecurityException e) {\n            throw new IllegalStateException(\"No System TLS\", e); // The system has no TLS. Just give up.\n        }\n    }\n\n    private static X509Certificate buildCertificateFromPEM(String pem) throws IOException, CertificateException {\n        InputStream stream = null;\n        try {\n            stream = new ByteArrayInputStream(pem.getBytes(\"UTF-8\"));\n            return (X509Certificate) CERTIFICATE_FACTORY.generateCertificate(stream);\n        } finally {\n            if (stream != null) {\n                stream.close();\n            }\n        }\n    }\n\n    private static native void nativeReset(long appNativePointer);\n    private static native void nativeSimulateSyncError(long appNativePointer, String realmPath, int errorCode, String type, String errorMessage, boolean isFatal);\n    private static native void nativeReconnect(long appNativePointer);\n    private static native String nativeGetPathForRealm(long appNativePointer, String userId, String partitionValue, @Nullable String overrideFileName);\n}\n"
  },
  {
    "path": "realm/realm-library/src/objectServer/java/io/realm/mongodb/sync/SyncClientResetStrategy.java",
    "content": "/*\n * Copyright 2021 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 */\npackage io.realm.mongodb.sync;\n\n/**\n * Interface that defines a generic sync client reset strategy, it could be either\n * {@link ManuallyRecoverUnsyncedChangesStrategy} or {@link AutomaticClientResetStrategy}.\n */\npublic interface SyncClientResetStrategy {\n}\n"
  },
  {
    "path": "realm/realm-library/src/objectServer/java/io/realm/mongodb/sync/SyncConfiguration.java",
    "content": "/*\n * Copyright 2020 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\npackage io.realm.mongodb.sync;\n\nimport android.content.Context;\n\nimport org.bson.BsonBinary;\nimport org.bson.BsonInt32;\nimport org.bson.BsonInt64;\nimport org.bson.BsonNull;\nimport org.bson.BsonObjectId;\nimport org.bson.BsonString;\nimport org.bson.BsonValue;\nimport org.bson.types.ObjectId;\n\nimport java.io.File;\nimport java.io.UnsupportedEncodingException;\nimport java.net.URI;\nimport java.net.URISyntaxException;\nimport java.net.URL;\nimport java.security.MessageDigest;\nimport java.security.NoSuchAlgorithmException;\nimport java.util.Arrays;\nimport java.util.Collections;\nimport java.util.HashSet;\nimport java.util.Locale;\nimport java.util.UUID;\nimport java.util.concurrent.TimeUnit;\n\nimport javax.annotation.Nonnull;\nimport javax.annotation.Nullable;\n\nimport edu.umd.cs.findbugs.annotations.SuppressFBWarnings;\nimport io.realm.CompactOnLaunchCallback;\nimport io.realm.DefaultCompactOnLaunchCallback;\nimport io.realm.Realm;\nimport io.realm.RealmConfiguration;\nimport io.realm.RealmMigration;\nimport io.realm.RealmModel;\nimport io.realm.RealmQuery;\nimport io.realm.annotations.RealmModule;\nimport io.realm.coroutines.FlowFactory;\nimport io.realm.coroutines.RealmFlowFactory;\nimport io.realm.exceptions.RealmException;\nimport io.realm.internal.OsRealmConfig;\nimport io.realm.internal.RealmProxyMediator;\nimport io.realm.internal.Util;\nimport io.realm.log.RealmLog;\nimport io.realm.mongodb.App;\nimport io.realm.mongodb.Credentials;\nimport io.realm.mongodb.User;\nimport io.realm.rx.RealmObservableFactory;\nimport io.realm.rx.RxObservableFactory;\n\n/**\n * A {@link SyncConfiguration} is used to setup a Realm Database that can be synchronized between\n * devices using MongoDB Realm.\n * <p>\n * A valid {@link User} is required to create a {@link SyncConfiguration}. See\n * {@link Credentials} and {@link App#loginAsync(Credentials, App.Callback)} for\n * more information on how to get a user object.\n * <p>\n * A minimal {@link SyncConfiguration} can be found below.\n * <pre>\n * {@code\n * App app = new App(\"app-id\");\n * User user = app.login(Credentials.anonymous());\n * SyncConfiguration config = SyncConfiguration.defaultConfiguration(user, \"partition-value\");\n * Realm realm = Realm.getInstance(config);\n * }\n * </pre>\n * <p>\n * Synchronized Realms only support additive migrations which can be detected and performed\n * automatically, so the following builder options are not accessible compared to a normal Realm:\n *\n * <ul>\n *     <li>{@code deleteRealmIfMigrationNeeded()}</li>\n *     <li>{@code migration(Migration)}</li>\n * </ul>\n *\n * Synchronized Realms are created by using {@link Realm#getInstance(RealmConfiguration)} and\n * {@link Realm#getDefaultInstance()} like ordinary unsynchronized Realms.\n *\n * @see <a href=\"https://docs.mongodb.com/realm/sync/\">The docs</a> for\n * more information about synchronization.\n */\npublic class SyncConfiguration extends RealmConfiguration {\n\n    private final URI serverUrl;\n    private final User user;\n    private final SyncSession.ErrorHandler errorHandler;\n    private final SyncClientResetStrategy syncClientResetStrategy;\n    private final boolean deleteRealmOnLogout;\n    private final boolean syncClientValidateSsl;\n    @Nullable private final String serverCertificateAssetName;\n    @Nullable private final String serverCertificateFilePath;\n    private final boolean waitForInitialData;\n    private final long initialDataTimeoutMillis;\n    private final OsRealmConfig.SyncSessionStopPolicy sessionStopPolicy;\n    @Nullable private final String syncUrlPrefix;\n    private final BsonValue partitionValue;\n    @Nullable private final InitialFlexibleSyncSubscriptions initialSubscriptionsHandler;\n\n    private SyncConfiguration(File realmPath,\n                              @Nullable String assetFilePath,\n                              @Nullable byte[] key,\n                              long schemaVersion,\n                              @Nullable RealmMigration migration,\n                              boolean deleteRealmIfMigrationNeeded,\n                              OsRealmConfig.Durability durability,\n                              RealmProxyMediator schemaMediator,\n                              @Nullable RxObservableFactory rxFactory,\n                              @Nullable FlowFactory flowFactory,\n                              @Nullable Realm.Transaction initialDataTransaction,\n                              boolean readOnly,\n                              long maxNumberOfActiveVersions,\n                              boolean allowWritesOnUiThread,\n                              boolean allowQueriesOnUiThread,\n                              User user,\n                              URI serverUrl,\n                              SyncSession.ErrorHandler errorHandler,\n                              SyncClientResetStrategy syncClientResetStrategy,\n                              boolean deleteRealmOnLogout,\n                              boolean syncClientValidateSsl,\n                              @Nullable String serverCertificateAssetName,\n                              @Nullable String serverCertificateFilePath,\n                              boolean waitForInitialData,\n                              long initialDataTimeoutMillis,\n                              OsRealmConfig.SyncSessionStopPolicy sessionStopPolicy,\n                              CompactOnLaunchCallback compactOnLaunch,\n                              @Nullable String syncUrlPrefix,\n                              BsonValue partitionValue,\n                              InitialFlexibleSyncSubscriptions initialSubscriptionsHandler) {\n        super(realmPath,\n                assetFilePath,\n                key,\n                schemaVersion,\n                migration,\n                deleteRealmIfMigrationNeeded,\n                durability,\n                schemaMediator,\n                rxFactory,\n                flowFactory,\n                initialDataTransaction,\n                readOnly,\n                compactOnLaunch,\n                false,\n                maxNumberOfActiveVersions,\n                allowWritesOnUiThread,\n                allowQueriesOnUiThread\n        );\n\n        this.user = user;\n        this.serverUrl = serverUrl;\n        this.errorHandler = errorHandler;\n        this.syncClientResetStrategy = syncClientResetStrategy;\n        this.deleteRealmOnLogout = deleteRealmOnLogout;\n        this.syncClientValidateSsl = syncClientValidateSsl;\n        this.serverCertificateAssetName = serverCertificateAssetName;\n        this.serverCertificateFilePath = serverCertificateFilePath;\n        this.waitForInitialData = waitForInitialData;\n        this.initialSubscriptionsHandler = initialSubscriptionsHandler;\n        this.initialDataTimeoutMillis = initialDataTimeoutMillis;\n        this.sessionStopPolicy = sessionStopPolicy;\n        this.syncUrlPrefix = syncUrlPrefix;\n        this.partitionValue = partitionValue;\n    }\n\n    /**\n     * Returns a {@link RealmConfiguration} appropriate to open a read-only, non-synced Realm to recover any pending changes.\n     * This is useful when trying to open a backup/recovery Realm (after a client reset).\n     *\n     * @param canonicalPath the absolute path to the Realm file defined by this configuration.\n     * @param encryptionKey the key used to encrypt/decrypt the Realm file.\n     * @param modules if specified it will restricts Realm schema to the provided module.\n     * @return RealmConfiguration that can be used offline\n     */\n    public static RealmConfiguration forRecovery(String canonicalPath, @Nullable byte[] encryptionKey, @Nullable Object... modules) {\n        HashSet<Object> validatedModules = new HashSet<>();\n        if (modules != null && modules.length > 0) {\n            for (Object module : modules) {\n                if (!module.getClass().isAnnotationPresent(RealmModule.class)) {\n                    throw new IllegalArgumentException(module.getClass().getCanonicalName() + \" is not a RealmModule. \" +\n                            \"Add @RealmModule to the class definition.\");\n                }\n                validatedModules.add(module);\n            }\n        } else {\n            if (Realm.getDefaultModule() != null) {\n                validatedModules.add(Realm.getDefaultModule());\n            }\n        }\n\n        RealmProxyMediator schemaMediator = createSchemaMediator(validatedModules, Collections.<Class<? extends RealmModel>>emptySet(), false);\n        return RealmConfiguration.forRecovery(canonicalPath, encryptionKey, schemaMediator);\n    }\n\n    RealmConfiguration forErrorRecovery(String canonicalPath) {\n        return RealmConfiguration.forRecovery(canonicalPath, getEncryptionKey(), getSchemaMediator());\n    }\n\n    /**\n     * Returns a default Flexible Sync configuration for the given user.\n     *\n     * @param user The user that will be used for accessing the Realm App.\n     * @return the default Flexible Sync configuration for the given user.\n     * @see {@link SubscriptionSet} for more information about Flexible Sync.\n     */\n    public static SyncConfiguration defaultConfig(User user) {\n        return new SyncConfiguration.Builder(user).build();\n    }\n\n    /**\n     * Returns a default Partition-based Sync configuration for the given user and partition value.\n     *\n     * @param user The user that will be used for accessing the Realm App.\n     * @param partitionValue The partition value identifying the remote Realm that will be synchronized.\n     * @return the default configuration for the given user and partition value.\n     */\n    public static SyncConfiguration defaultConfig(User user, @Nullable String partitionValue) {\n        return new SyncConfiguration.Builder(user, partitionValue).build();\n    }\n\n    /**\n     * Returns a default Partition-based Sync configuration for the given user and partition value.\n     *\n     * @param user The user that will be used for accessing the Realm App.\n     * @param partitionValue The partition value identifying the remote Realm that will be synchronized.\n     * @return the default configuration for the given user and partition value.\n     */\n    public static SyncConfiguration defaultConfig(User user, @Nullable Long partitionValue) {\n        return new SyncConfiguration.Builder(user, partitionValue).build();\n    }\n\n    /**\n     * Returns a default Partition-based Sync configuration for the given user and partition value.\n     *\n     * @param user The user that will be used for accessing the Realm App.\n     * @param partitionValue The partition value identifying the remote Realm that will be synchronized.\n     * @return the default configuration for the given user and partition value.\n     */\n    public static SyncConfiguration defaultConfig(User user, @Nullable Integer partitionValue) {\n        return new SyncConfiguration.Builder(user, partitionValue).build();\n    }\n\n    /**\n     * Returns a default Partition-based Sync configuration for the given user and partition value.\n     *\n     * @param user The user that will be used for accessing the Realm App.\n     * @param partitionValue The partition value identifying the remote Realm that will be synchronized.\n     * @return the default configuration for the given user and partition value.\n     */\n    public static SyncConfiguration defaultConfig(User user, @Nullable ObjectId partitionValue) {\n        return new SyncConfiguration.Builder(user, partitionValue).build();\n    }\n\n    /**\n     * Returns a default Partition-based Sync configuration for the given user and partition value.\n     *\n     * @param user The user that will be used for accessing the Realm App.\n     * @param partitionValue The partition value identifying the remote Realm that will be synchronized.\n     * @return the default configuration for the given user and partition value.\n     */\n    public static SyncConfiguration defaultConfig(User user, @Nullable UUID partitionValue) {\n        return new SyncConfiguration.Builder(user, partitionValue).build();\n    }\n\n    /**\n     * Returns a {@link RealmConfiguration} appropriate to open a read-only, non-synced Realm to recover any pending changes.\n     * This is useful when trying to open a backup/recovery Realm (after a client reset).\n     *\n     * Note: This will use the default Realm module (composed of all {@link RealmModel}), and\n     * assume no encryption should be used as well.\n     *\n     * @param canonicalPath the absolute path to the Realm file defined by this configuration.\n     * @return RealmConfiguration that can be used offline\n     */\n    public static RealmConfiguration forRecovery(String canonicalPath) {\n        return forRecovery(canonicalPath, null);\n    }\n\n    @Override\n    protected Realm.Transaction getInitialDataTransaction() {\n        return super.getInitialDataTransaction();\n    }\n\n    /**\n     * Returns the configured initial subscription handler for this realm.\n     *\n     * @return the handler used to configure initial subscriptions for this realm.\n     */\n    public InitialFlexibleSyncSubscriptions getInitialSubscriptionsHandler() {\n        return initialSubscriptionsHandler;\n    }\n\n    // Extract the full server path, minus the file name\n    private static String getServerPath(User user, URI serverUrl) {\n        // FIXME Add support for partition key\n        // Current scheme is <rootDir>/<appId>/<userId>/default.realm or\n        // Current scheme is <rootDir>/<appId>/<userId>/<hashedPartitionKey>/default.realm\n        return user.getApp().getConfiguration().getAppId() + \"/\" + user.getId(); // TODO Check that it doesn't contain invalid filesystem chars\n    }\n\n    @SuppressFBWarnings(\"NP_METHOD_PARAMETER_TIGHTENS_ANNOTATION\")\n    @Override\n    public boolean equals(@Nullable Object o) {\n        if (this == o) return true;\n        if (o == null || getClass() != o.getClass()) return false;\n        if (!super.equals(o)) return false;\n\n        SyncConfiguration that = (SyncConfiguration) o;\n\n        if (deleteRealmOnLogout != that.deleteRealmOnLogout) return false;\n        if (syncClientValidateSsl != that.syncClientValidateSsl) return false;\n        if (waitForInitialData != that.waitForInitialData) return false;\n        if (initialDataTimeoutMillis != that.initialDataTimeoutMillis) return false;\n        if (!serverUrl.equals(that.serverUrl)) return false;\n        if (!user.equals(that.user)) return false;\n        if (!errorHandler.equals(that.errorHandler)) return false;\n        if (serverCertificateAssetName != null ? !serverCertificateAssetName.equals(that.serverCertificateAssetName) : that.serverCertificateAssetName != null)\n            return false;\n        if (serverCertificateFilePath != null ? !serverCertificateFilePath.equals(that.serverCertificateFilePath) : that.serverCertificateFilePath != null)\n            return false;\n        if (sessionStopPolicy != that.sessionStopPolicy) return false;\n        if (initialSubscriptionsHandler != null ? !initialSubscriptionsHandler.equals(that.initialSubscriptionsHandler) : that.initialSubscriptionsHandler != null)\n            return false;\n        if (syncUrlPrefix != null ? !syncUrlPrefix.equals(that.syncUrlPrefix) : that.syncUrlPrefix != null)\n            return false;\n        return partitionValue != null ? partitionValue.equals(that.partitionValue) : that.partitionValue == null;\n    }\n\n    @Override\n    public int hashCode() {\n        int result = super.hashCode();\n        result = 31 * result + serverUrl.hashCode();\n        result = 31 * result + user.hashCode();\n        result = 31 * result + errorHandler.hashCode();\n        result = 31 * result + (initialSubscriptionsHandler != null ? initialSubscriptionsHandler.hashCode() : 0);\n        result = 31 * result + (deleteRealmOnLogout ? 1 : 0);\n        result = 31 * result + (syncClientValidateSsl ? 1 : 0);\n        result = 31 * result + (serverCertificateAssetName != null ? serverCertificateAssetName.hashCode() : 0);\n        result = 31 * result + (serverCertificateFilePath != null ? serverCertificateFilePath.hashCode() : 0);\n        result = 31 * result + (waitForInitialData ? 1 : 0);\n        result = 31 * result + (int) (initialDataTimeoutMillis ^ (initialDataTimeoutMillis >>> 32));\n        result = 31 * result + sessionStopPolicy.hashCode();\n        result = 31 * result + (syncUrlPrefix != null ? syncUrlPrefix.hashCode() : 0);\n        result = 31 * result + (partitionValue != null ? partitionValue.hashCode() : 0);\n        return result;\n    }\n\n    @Override\n    public String toString() {\n        StringBuilder sb = new StringBuilder(super.toString());\n        sb.append(\"\\n\");\n        sb.append(\"serverUrl: \").append(serverUrl);\n        sb.append(\"\\n\");\n        sb.append(\"user: \").append(user);\n        sb.append(\"\\n\");\n        sb.append(\"errorHandler: \").append(errorHandler);\n        sb.append(\"\\n\");\n        sb.append(\"initialSubscriptions: \").append(initialSubscriptionsHandler);\n        sb.append(\"\\n\");\n        sb.append(\"deleteRealmOnLogout: \").append(deleteRealmOnLogout);\n        sb.append(\"\\n\");\n        sb.append(\"syncClientValidateSsl: \").append(syncClientValidateSsl);\n        sb.append(\"\\n\");\n        sb.append(\"serverCertificateAssetName: \").append(serverCertificateAssetName);\n        sb.append(\"\\n\");\n        sb.append(\"serverCertificateFilePath: \").append(serverCertificateFilePath);\n        sb.append(\"\\n\");\n        sb.append(\"waitForInitialData: \").append(waitForInitialData);\n        sb.append(\"\\n\");\n        sb.append(\"initialDataTimeoutMillis: \").append(initialDataTimeoutMillis);\n        sb.append(\"\\n\");\n        sb.append(\"sessionStopPolicy: \").append(sessionStopPolicy);\n        sb.append(\"\\n\");\n        sb.append(\"syncUrlPrefix: \").append(syncUrlPrefix);\n        sb.append(\"\\n\");\n        sb.append(\"partitionValue: \").append(partitionValue);\n        return sb.toString();\n    }\n\n    /**\n     * Returns the user.\n     *\n     * @return the user.\n     */\n    public User getUser() {\n        return user;\n    }\n\n    /**\n     * Returns the server URI for the remote MongoDB Realm the local Realm is synchronizing with.\n     *\n     * @return {@link URI} identifying the MongoDB Realm this local Realm is synchronized with.\n     */\n    public URI getServerUrl() {\n        return serverUrl;\n    }\n\n    /**\n     * Returns the error handler for this <i>SyncConfiguration</i>.\n     *\n     * @return the error handler.\n     */\n    public SyncSession.ErrorHandler getErrorHandler() {\n        return errorHandler;\n    }\n\n    /**\n     * Returns the Client Reset handler for this <i>SyncConfiguration</i>.\n     *\n     * @return the Client Reset handler.\n     *\n     * @deprecated replaced by {@link #getSyncClientResetStrategy()}\n     */\n    @Deprecated\n    public SyncSession.ClientResetHandler getClientResetHandler() {\n        try {\n            return (SyncSession.ClientResetHandler) syncClientResetStrategy;\n        } catch (ClassCastException exception) {\n            throw new ClassCastException(exception.getMessage() + \": getClientResetHandler() is deprecated and has been replaced by getSyncClientResetStrategy()\");\n        }\n    }\n\n    /**\n     * Returns the sync client reset strategy for this <i>SyncConfiguration</i>.\n     *\n     * @return the sync client reset strategy.\n     */\n    public SyncClientResetStrategy getSyncClientResetStrategy() {\n        return syncClientResetStrategy;\n    }\n\n    /**\n     * Returns {@code true} if the Realm file must be deleted once the {@link User} owning it logs out.\n     *\n     * @return {@code true} if the Realm file must be deleted if the {@link User} logs out. {@code false} if the file\n     *         is allowed to remain behind.\n     */\n    public boolean shouldDeleteRealmOnLogout() {\n        return deleteRealmOnLogout;\n    }\n\n    /**\n     * Returns the name of certificate stored under the {@code assets}, to be used to validate\n     * the TLS connection to Atlas.\n     *\n     * @return name of the certificate to be copied from the {@code assets}.\n     * @see #getServerCertificateFilePath()\n     */\n    @Nullable\n    public String getServerCertificateAssetName() {\n        return serverCertificateAssetName;\n    }\n\n    /**\n     * Returns the name of the certificate copied from {@code assets} into internal storage, so it\n     * can be used to validate the TLS connection to Atlas.\n     *\n     * @return absolute path to the certificate.\n     * @see #getServerCertificateAssetName()\n     */\n    @Nullable\n    public String getServerCertificateFilePath() {\n        return serverCertificateFilePath;\n    }\n\n    /**\n     * Whether the Atlas certificate should be validated in order\n     * to establish a valid TLS connection.\n     *\n     * @return {@code true} to validate the remote certificate, or {@code false} to bypass certificate validation.\n     */\n    public boolean syncClientValidateSsl() {\n        return syncClientValidateSsl;\n    }\n\n    /**\n     * Returns {@code true} if the Realm will download all known changes from the remote server before being opened the\n     * first time.\n     *\n     * @return {@code true} if all remote changes will be downloaded before the Realm can be opened. {@code false} if\n     * the Realm can be opened immediately.\n     */\n    public boolean shouldWaitForInitialRemoteData() {\n        return waitForInitialData;\n    }\n\n    /**\n     * Returns the timeout defined when downloading any initial data the first time the Realm is opened.\n     * <p>\n     * This value is only applicable if {@link #shouldWaitForInitialRemoteData()} returns {@code true}.\n     *\n     * @return the time Realm will wait for all changes to be downloaded before it is aborted and an exception is thrown.\n     * @see SyncConfiguration.Builder#waitForInitialRemoteData(long, TimeUnit)\n     */\n    public long getInitialRemoteDataTimeout(TimeUnit unit) {\n        return unit.convert(initialDataTimeoutMillis, TimeUnit.MILLISECONDS);\n    }\n\n    @Override\n    protected boolean isSyncConfiguration() {\n        return true;\n    }\n\n    /**\n     * NOTE: Only for internal usage. May change without warning.\n     *\n     * Returns the stop policy for the session for this Realm once the Realm has been closed.\n     *\n     * @return the stop policy used by the session once the Realm is closed.\n     */\n    public OsRealmConfig.SyncSessionStopPolicy getSessionStopPolicy() {\n        return sessionStopPolicy;\n    }\n\n    /**\n     * Returns the url prefix used when establishing a sync connection to Atlas.\n     */\n    @Nullable\n    public String getUrlPrefix() {\n        return syncUrlPrefix;\n    }\n\n    /**\n     * Returns the value this Realm is partitioned on. The partition key is a property defined in\n     * MongoDB Realm. All classes with a property with this value will be synchronized to the\n     * Realm.\n     *\n     * @return the value being used by MongoDB Realm to partition the server side MongoDB Database\n     * into Realms that can be synchronized independently.\n     * @throws IllegalStateException if this configuration is for a realm configured for flexible\n     * sync. You can use {@link #isPartitionBasedSyncConfiguration()} before calling this method\n     * to check.\n     */\n    public BsonValue getPartitionValue() {\n        checkPartitionConfiguration();\n        return partitionValue;\n    }\n\n    /**\n     * Returns whether or not this configuration is for opening a Realm configured for Flexible\n     * Sync.\n     * \n     * @return {@code true} if this configuration is for a Flexible Sync Realm, {@code false} if not.\n     */\n    public boolean isFlexibleSyncConfiguration() {\n        return partitionValue == null;\n    }\n\n    /**\n     * Returns whether or not this configuration is for opening a Realm configured for Partition-based\n     * Sync.\n     *\n     * @return {@code true} if this configuration is for a Partition-based Sync Realm, {@code false}\n     * if not.\n     */\n    public boolean isPartitionBasedSyncConfiguration() {\n        return partitionValue != null;\n    }\n\n    @Override\n    protected boolean realmExists() {\n        return super.realmExists();\n    }\n\n    private void checkPartitionConfiguration() {\n        if (partitionValue == null) {\n            throw new IllegalStateException(\"This method is only available for Partition-based Sync configurations.\");\n        }\n    }\n\n    /**\n     * Interface for configuring the initial set of of subscriptions. This should only be\n     * used for synced realms configured for flexible sync.\n     *\n     * @see Builder#initialSubscriptions(SyncConfiguration.InitialFlexibleSyncSubscriptions)\n     */\n    public interface InitialFlexibleSyncSubscriptions {\n        void configure(Realm realm, MutableSubscriptionSet subscriptions);\n    }\n\n    /**\n     * Builder used to construct instances of a SyncConfiguration in a fluent manner.\n     */\n    public static final class Builder  {\n\n        @Nullable\n        private byte[] key;\n        private long schemaVersion = 0;\n        private HashSet<Object> modules = new HashSet<Object>();\n        private HashSet<Class<? extends RealmModel>> debugSchema = new HashSet<Class<? extends RealmModel>>();\n        @Nullable\n        private RxObservableFactory rxFactory;\n        @Nullable\n        private FlowFactory flowFactory;\n        @Nullable\n        private Realm.Transaction initialDataTransaction;\n        @Nullable\n        private InitialFlexibleSyncSubscriptions initialSubscriptionsHandler;\n        @Nullable\n        private String filename;\n        private String assetFilePath;\n        private OsRealmConfig.Durability durability = OsRealmConfig.Durability.FULL;\n        private boolean readOnly = false;\n        private boolean waitForServerChanges = false;\n        private long initialDataTimeoutMillis = Long.MAX_VALUE;\n        // sync specific\n        private boolean deleteRealmOnLogout = false;\n        private boolean syncClientValidateSsl = true;\n        @Nullable\n        private String serverCertificateAssetName;\n        @Nullable\n        private String serverCertificateFilePath;\n        private URI serverUrl;\n        private User user = null;\n        private SyncSession.ErrorHandler errorHandler;\n        @Nullable\n        private SyncClientResetStrategy syncClientResetStrategy;\n        private OsRealmConfig.SyncSessionStopPolicy sessionStopPolicy = OsRealmConfig.SyncSessionStopPolicy.AFTER_CHANGES_UPLOADED;\n        private CompactOnLaunchCallback compactOnLaunch;\n        private String syncUrlPrefix = null;\n        private long maxNumberOfActiveVersions = Long.MAX_VALUE;\n        private boolean allowWritesOnUiThread;\n        private boolean allowQueriesOnUiThread;\n        @Nullable\n        private final BsonValue partitionValue;\n\n\n        /**\n         * Creates an instance of the builder for a Flexible Sync <i>SyncConfiguration</i> with the\n         * given user.\n         *\n         * @param user The user that will be used for accessing the Realm App.\n         * @see {@link SubscriptionSet} for more information about Flexible Sync.\n         */\n        public Builder(User user) {\n            this(user, (BsonValue) null);\n        }\n\n        /**\n         * Creates an instance of the builder for a Partition-based Sync <i>SyncConfiguration</i>\n         * with the given user and partition value.\n         *\n         * @param user The user that will be used for accessing the Realm App.\n         * @param partitionValue The partition value identifying the remote Realm that will be synchronized.\n         */\n        public Builder(User user, @Nullable String partitionValue) {\n            this(user, (partitionValue == null? new BsonNull() : new BsonString(partitionValue)));\n        }\n\n        /**\n         * Creates an instance of the builder for a Partition-based Sync <i>SyncConfiguration</i>\n         * with the given user and partition value.\n         *\n         * @param user The user that will be used for accessing the Realm App.\n         * @param partitionValue The partition value identifying the remote Realm that will be synchronized.\n         */\n        public Builder(User user, @Nullable ObjectId partitionValue) {\n            this(user, (partitionValue == null? new BsonNull() : new BsonObjectId(partitionValue)));\n        }\n\n        /**\n         * Creates an instance of the builder for a Partition-based Sync <i>SyncConfiguration</i>\n         * with the given user and partition value.\n         *\n         * @param user The user that will be used for accessing the Realm App.\n         * @param partitionValue The partition value identifying the remote Realm that will be synchronized.\n         */\n        public Builder(User user, @Nullable Integer partitionValue) {\n            this(user, (partitionValue == null? new BsonNull() : new BsonInt32(partitionValue)));\n        }\n\n        /**\n         * Creates an instance of the builder for a Partition-based Sync <i>SyncConfiguration</i>\n         * with the given user and partition value.\n         *\n         * @param user The user that will be used for accessing the Realm App.\n         * @param partitionValue The partition value identifying the remote Realm that will be synchronized.\n         */\n        public Builder(User user, @Nullable Long partitionValue) {\n            this(user, (partitionValue == null? new BsonNull() : new BsonInt64(partitionValue)));\n        }\n\n        /**\n         * Creates an instance of the builder for a Partition-based Sync <i>SyncConfiguration</i>\n         * with the given user and partition value.\n         *\n         * @param user The user that will be used for accessing the Realm App.\n         * @param partitionValue The partition value identifying the remote Realm that will be synchronized.\n         */\n        public Builder(User user, @Nullable UUID partitionValue) {\n            this(user, (partitionValue == null? new BsonNull() : new BsonBinary(partitionValue)));\n        }\n\n        /**\n         * Builder used to construct instances of a SyncConfiguration in a fluent manner.\n         *\n         * @param user the user opening the Realm on the server.\n         * @param partitionValue the value this Realm is partitioned on. The partition key is a\n         * property defined in MongoDB Realm. All classes with a property with this value will be\n         * synchronized to the Realm. If {@code null} is provided, the configuration is treated\n         * as a Flexible Sync configuration.\n         */\n        Builder(User user, @Nullable BsonValue partitionValue) {\n            Context context = Realm.getApplicationContext();\n            if (context == null) {\n                throw new IllegalStateException(\"Call `Realm.init(Context)` before creating a SyncConfiguration\");\n            }\n            Util.checkNull(user, \"user\");\n            validateAndSet(user);\n            validateAndSet(user.getApp().getConfiguration().getBaseUrl());\n            this.partitionValue = partitionValue;\n            if (Realm.getDefaultModule() != null) {\n                this.modules.add(Realm.getDefaultModule());\n            }\n            this.errorHandler = user.getApp().getConfiguration().getDefaultErrorHandler();\n            this.allowQueriesOnUiThread = true;\n            this.allowWritesOnUiThread = false;\n        }\n\n        private void validateAndSet(User user) {\n            //noinspection ConstantConditions\n            if (user == null) {\n                throw new IllegalArgumentException(\"Non-null `user` required.\");\n            }\n            if (!user.isLoggedIn()) {\n                throw new IllegalArgumentException(\"User not authenticated or authentication expired.\");\n            }\n            this.user = user;\n        }\n\n        private void validateAndSet(URL baseUrl ) {\n            try {\n                serverUrl = new URI(baseUrl.toString());\n            } catch (URISyntaxException e) {\n                throw new IllegalArgumentException(\"Invalid URI: \" + baseUrl.toString(), e);\n            }\n\n            try {\n                // Automatically set scheme based on auth server if not set or wrongly set\n                String serverScheme = serverUrl.getScheme();\n                if (serverScheme == null || serverScheme.equalsIgnoreCase(\"http\")) {\n                    serverScheme = \"ws\";\n                } else if (serverScheme.equalsIgnoreCase(\"https\")) {\n                    serverScheme = \"wss\";\n                }\n\n                // Automatically set host if one wasn't defined\n                String host = serverUrl.getHost();\n\n                // Convert relative paths to absolute if required\n                String path = serverUrl.getPath();\n                if (path != null && !path.startsWith(\"/\")) {\n                    path = \"/\" + path;\n                }\n\n                serverUrl = new URI(serverScheme,\n                        serverUrl.getUserInfo(),\n                        host,\n                        serverUrl.getPort(),\n                        (path != null) ? path.replace(host + \"/\", \"\") : null, // Remove host if it accidentially was interpreted as a path segment\n                        serverUrl.getQuery(),\n                        serverUrl.getRawFragment());\n\n            } catch (URISyntaxException e) {\n                throw new IllegalArgumentException(\"Invalid URI: \" + baseUrl, e);\n            }\n        }\n\n        /**\n         * Sets the filename for the Realm file on this device.\n         *\n         * @param filename name for the Realm file.\n         */\n        public Builder name(String filename) {\n            //noinspection ConstantConditions\n            if (filename == null || filename.isEmpty()) {\n                throw new IllegalArgumentException(\"A non-empty filename must be provided\");\n            }\n\n            // Strip `.realm` suffix as it will be appended by Object Store later\n            if (filename.endsWith(\".realm\")) {\n                if (filename.length() == 6) {\n                    throw new IllegalArgumentException(\"'.realm' is not a valid filename\");\n                } else {\n                    filename = filename.substring(0, filename.length() - 6);\n                }\n            }\n\n            this.filename = filename;\n            return this;\n        }\n\n        /**\n         * Sets the {@value io.realm.Realm#ENCRYPTION_KEY_LENGTH} bytes key used to encrypt and decrypt the Realm file.\n         *\n         * @param key the encryption key.\n         * @throws IllegalArgumentException if key is invalid.\n         */\n        public Builder encryptionKey(byte[] key) {\n            //noinspection ConstantConditions\n            if (key == null) {\n                throw new IllegalArgumentException(\"A non-null key must be provided\");\n            }\n            if (key.length != Realm.ENCRYPTION_KEY_LENGTH) {\n                throw new IllegalArgumentException(String.format(Locale.US,\n                        \"The provided key must be %s bytes. Yours was: %s\",\n                        Realm.ENCRYPTION_KEY_LENGTH, key.length));\n            }\n            this.key = Arrays.copyOf(key, key.length);\n            return this;\n        }\n\n        /**\n         * DEBUG method. This restricts the Realm schema to only consist of the provided classes without having to\n         * create a module. These classes must be available in the default module. Calling this will remove any\n         * previously configured modules.\n         */\n        SyncConfiguration.Builder schema(Class<? extends RealmModel> firstClass, Class<? extends RealmModel>... additionalClasses) {\n            //noinspection ConstantConditions\n            if (firstClass == null) {\n                throw new IllegalArgumentException(\"A non-null class must be provided\");\n            }\n            modules.clear();\n            modules.add(DEFAULT_MODULE_MEDIATOR);\n            debugSchema.add(firstClass);\n            //noinspection ConstantConditions\n            if (additionalClasses != null) {\n                Collections.addAll(debugSchema, additionalClasses);\n            }\n\n            return this;\n        }\n\n        /**\n         * DEBUG method. This makes it possible to define different policies for when a session should be stopped when\n         * the Realm is closed.\n         *\n         * @param policy how a session for a Realm should behave when the Realm is closed.\n         */\n        SyncConfiguration.Builder sessionStopPolicy(OsRealmConfig.SyncSessionStopPolicy policy) {\n            sessionStopPolicy = policy;\n            return this;\n        }\n\n\n        /**\n         * Sets the schema version of the Realm.\n         * <p>\n         * Synced Realms only support additive schema changes which can be applied without requiring a manual\n         * migration. The schema version will only be used as an indication to the underlying storage layer to remove\n         * or add indexes. These will be recalculated if the provided schema version differ from the version in the\n         * Realm file.\n         *\n         * <b>WARNING:</b> There is no guarantee that the value inserted here is the same returned by {@link Realm#getVersion()}.\n         * Due to the nature of synced Realms, the value can both be higher and lower.\n         * <ul>\n         *     <li>It will be lower if another client with a lesser {@code schemaVersion} connected to the server for\n         *         the first time after this schemaVersion was used.\n     *         </li>\n         *     <li>It will be higher if another client with a higher {@code schemaVersion} connected to the server after\n         *         this Realm was created.\n     *         </li>\n         * </ul>\n         *\n         * @param schemaVersion the schema version.\n         * @throws IllegalArgumentException if schema version is invalid.\n         */\n        public Builder schemaVersion(long schemaVersion) {\n            if (schemaVersion < 0) {\n                throw new IllegalArgumentException(\"Realm schema version numbers must be 0 (zero) or higher. Yours was: \" + schemaVersion);\n            }\n            this.schemaVersion = schemaVersion;\n            return this;\n        }\n\n        /**\n         * Replaces the existing module(s) with one or more {@link RealmModule}s. Using this method will replace the\n         * current schema for this Realm with the schema defined by the provided modules.\n         * <p>\n         * A reference to the default Realm module containing all Realm classes in the project (but not dependencies),\n         * can be found using {@link Realm#getDefaultModule()}. Combining the schema from the app project and a library\n         * dependency is thus done using the following code:\n         * <p>\n         * {@code builder.modules(Realm.getDefaultMode(), new MyLibraryModule()); }\n         * <p>\n         * @param baseModule the first Realm module (required).\n         * @param additionalModules the additional Realm modules\n         * @throws IllegalArgumentException if any of the modules don't have the {@link RealmModule} annotation.\n         * @see Realm#getDefaultModule()\n         */\n        public Builder modules(Object baseModule, Object... additionalModules) {\n            modules.clear();\n            addModule(baseModule);\n            //noinspection ConstantConditions\n            if (additionalModules != null) {\n                for (Object module : additionalModules) {\n                    addModule(module);\n                }\n            }\n            return this;\n        }\n\n        /**\n         * Replaces the existing module(s) with one or more {@link RealmModule}s. Using this method will replace the\n         * current schema for this Realm with the schema defined by the provided modules.\n         * <p>\n         * A reference to the default Realm module containing all Realm classes in the project (but not dependencies),\n         * can be found using {@link Realm#getDefaultModule()}. Combining the schema from the app project and a library\n         * dependency is thus done using the following code:\n         * <p>\n         * {@code builder.modules(Realm.getDefaultMode(), new MyLibraryModule()); }\n         * <p>\n         * @param modules list of modules tthe first Realm module (required).\n         * @throws IllegalArgumentException if any of the modules don't have the {@link RealmModule} annotation.\n         * @see Realm#getDefaultModule()\n         */\n        public Builder modules(Iterable<Object> modules) {\n            this.modules.clear();\n            if (modules != null) {\n                for (Object module : modules) {\n                    addModule(module);\n                }\n            }\n            return this;\n        }\n\n        /**\n         * Adds a module to the already defined modules.\n         */\n        public Builder addModule(Object module) {\n            //noinspection ConstantConditions\n            if (module != null) {\n                checkModule(module);\n                modules.add(module);\n            }\n\n            return this;\n        }\n\n        /**\n         * Sets the {@link RxObservableFactory} used to create Rx Observables from Realm objects.\n         * The default factory is {@link RealmObservableFactory}.\n         *\n         * @param factory factory to use.\n         */\n        public Builder rxFactory(@Nonnull RxObservableFactory factory) {\n            if (factory == null) {\n                throw new IllegalArgumentException(\"The provided Rx Observable factory must not be null.\");\n            }\n            rxFactory = factory;\n            return this;\n        }\n\n        /**\n         * Sets the {@link FlowFactory} used to create coroutines Flows from Realm objects.\n         * The default factory is {@link RealmFlowFactory}.\n         *\n         * @param factory factory to use.\n         */\n        public Builder flowFactory(@Nonnull FlowFactory factory) {\n            if (factory == null) {\n                throw new IllegalArgumentException(\"The provided Flow factory must not be null.\");\n            }\n            flowFactory = factory;\n            return this;\n        }\n\n        /**\n         * Sets the initial data in {@link io.realm.Realm}. This transaction will be executed only the first time\n         * the Realm file is opened (created) or while migrating the data if\n         * {@link RealmConfiguration.Builder#deleteRealmIfMigrationNeeded()} is set.\n         *\n         * @param transaction transaction to execute.\n         */\n        public Builder initialData(Realm.Transaction transaction) {\n            initialDataTransaction = transaction;\n            return this;\n        }\n\n        /**\n         * Sets the initial {@link Subscription}s for the {@link io.realm.Realm}. This will only be\n         * executed the first time the Realm file is opened (and the file created).\n         *\n         * If {@link #waitForInitialRemoteData()} is configured as well, the realm file isn't fully\n         * opened until all subscription data also has been uploaded.\n         *\n         * @param action {@link MutableSubscriptionSet} where subscriptions can be added.\n         */\n        public Builder initialSubscriptions(InitialFlexibleSyncSubscriptions action) {\n            initialSubscriptionsHandler = action;\n            return this;\n        }\n\n        /**\n         * Setting this will create an in-memory Realm instead of saving it to disk. In-memory Realms might still use\n         * disk space if memory is running low, but all files created by an in-memory Realm will be deleted when the\n         * Realm is closed.\n         * <p>\n         * Note that because in-memory Realms are not persisted, you must be sure to hold on to at least one non-closed\n         * reference to the in-memory Realm object with the specific name as long as you want the data to last.\n         */\n        public Builder inMemory() {\n            this.durability = OsRealmConfig.Durability.MEM_ONLY;\n            return this;\n        }\n\n        /**\n         * Sets the error handler used by this configuration.\n         * <p>\n         * Only errors not handled by the defined {@code SyncPolicy} will be reported to this error handler.\n         *\n         * @param errorHandler error handler used to report back errors when communicating with Atlas.\n         * @throws IllegalArgumentException if {@code null} is given as an error handler.\n         */\n        public Builder errorHandler(SyncSession.ErrorHandler errorHandler) {\n            Util.checkNull(errorHandler, \"handler\");\n            this.errorHandler = errorHandler;\n            return this;\n        }\n\n        /**\n         * Provides the trusted root certificate(s) authority (CA) in {@code PEM} format, that should be used to\n         * validate the TLS connections to Atlas.\n         * <p>\n         * The file should be stored under {@code assets}, it will be copied at runtime into the internal storage.\n         * <p>\n         * Note: This is similar to passing the parameter {@code CAfile} to {@code SSL_CTX_load_verify_locations},\n         *       Therefore it is recommended to include only the root CA you trust, and not the entire list of root CA\n         *       as this file will be loaded at runtime.\n         *       It is your responsibility to download and verify the correct {@code PEM} for the root CA you trust.\n         *       An existing list by Mozilla exist that could be used https://mozillacaprogram.secure.force.com/CA/IncludedCACertificateReportPEMCSV\n         *\n         * @param filename the path under {@code assets} to the root CA.\n         * @see <a href=\"https://www.openssl.org/docs/man1.0.2/ssl/SSL_CTX_load_verify_locations.html\">SSL_CTX_load_verify_locations</a>\n         */\n        public Builder trustedRootCA(String filename) {\n            //noinspection ConstantConditions\n            if (filename == null || filename.isEmpty()) {\n                throw new IllegalArgumentException(\"A non-empty filename must be provided\");\n            }\n            this.serverCertificateAssetName = filename;\n            return this;\n        }\n\n        /**\n         * This will disable TLS certificate verification for Atlas.\n         * It is not recommended to use this in production.\n         * <p>\n         * This might be useful in non-production environments where you use a self-signed certificate\n         * for testing.\n         */\n        public Builder disableSSLVerification() {\n            this.syncClientValidateSsl = false;\n            return this;\n        }\n\n        Builder syncClientResetStrategyInternal(SyncClientResetStrategy strategy) {\n            Util.checkNull(strategy, \"strategy\");\n            this.syncClientResetStrategy = strategy;\n            return this;\n        }\n\n        /**\n         * Sets the handler for when a Client Reset occurs. If no handler is set, and error is\n         * logged when a Client Reset occurs.\n         *\n         * @param handler custom handler in case of a Client Reset.\n         *\n         * @deprecated replaced by {@link #syncClientResetStrategy(ManuallyRecoverUnsyncedChangesStrategy)}\n         */\n        @Deprecated\n        public Builder clientResetHandler(SyncSession.ClientResetHandler handler) {\n            return syncClientResetStrategyInternal(handler);\n        }\n\n        /**\n         * Sets the strategy used to resolve Client Resets. If no strategy is set, a message would\n         * be logged when a Client Reset occurs.\n         *\n         * @param strategy user defined manual strategy.\n         */\n        public Builder syncClientResetStrategy(ManuallyRecoverUnsyncedChangesStrategy strategy) {\n            return syncClientResetStrategyInternal(strategy);\n        }\n\n        /**\n         * Sets the strategy used to resolve Client Resets. If no strategy is set, a message would\n         * be logged when a Client Reset occurs.\n         *\n         * @param strategy user defined discard unsynced changes strategy.\n         */\n        public Builder syncClientResetStrategy(DiscardUnsyncedChangesStrategy strategy) {\n            return syncClientResetStrategyInternal(strategy);\n        }\n\n        /**\n         * Sets the strategy used to resolve Client Resets. If no strategy is set, a message would\n         * be logged when a Client Reset occurs.\n         *\n         * @param strategy user defined recover unsynced changes strategy.\n         */\n        public Builder syncClientResetStrategy(RecoverUnsyncedChangesStrategy strategy) {\n            return syncClientResetStrategyInternal(strategy);\n        }\n\n        /**\n         * Sets the strategy used to resolve Client Resets. If no strategy is set, a message would\n         * be logged when a Client Reset occurs.\n         *\n         * @param strategy user defined recover or discard unsynced changes strategy.\n         */\n        public Builder syncClientResetStrategy(RecoverOrDiscardUnsyncedChangesStrategy strategy) {\n            return syncClientResetStrategyInternal(strategy);\n        }\n\n        /**\n         * Setting this will cause the Realm to download all known changes from the server the first time a Realm is\n         * opened. The Realm will not open until all the data has been downloaded. This means that if a device is\n         * offline the Realm will not open.\n         * <p>\n         * Since downloading all changes can be an lengthy operation that might block the UI thread, Realms with this\n         * setting enabled should only be opened on background threads or with\n         * {@link Realm#getInstanceAsync(RealmConfiguration, Realm.Callback)} on the UI thread.\n         * <p>\n         * This check is only enforced the first time a Realm is created. If you otherwise want to make sure a Realm\n         * has the latest changes, use {@link SyncSession#downloadAllServerChanges()}.\n         */\n        public Builder waitForInitialRemoteData() {\n            this.waitForServerChanges = true;\n            this.initialDataTimeoutMillis = Long.MAX_VALUE;\n            return this;\n        }\n\n        /**\n         * Setting this will cause the Realm to download all known changes from the server the first time a Realm is\n         * opened. The Realm will not open until all the data has been downloaded. This means that if a device is\n         * offline the Realm will not open.\n         * <p>\n         * Since downloading all changes can be an lengthy operation that might block the UI thread, Realms with this\n         * setting enabled should only be opened on background threads or with\n         * {@link Realm#getInstanceAsync(RealmConfiguration, Realm.Callback)} on the UI thread.\n         * <p>\n         * This check is only enforced the first time a Realm is created. If you otherwise want to make sure a Realm\n         * has the latest changes, use {@link SyncSession#downloadAllServerChanges()}.\n         *\n         * @param timeout how long to wait for the download to complete before an {@link io.realm.exceptions.DownloadingRealmInterruptedException} is thrown.\n         * @param unit the unit of time used to define the timeout.\n         */\n        public Builder waitForInitialRemoteData(long timeout, TimeUnit unit) {\n            if (timeout < 0) {\n                throw new IllegalArgumentException(\"'timeout' must be >= 0. It was: \" + timeout);\n            }\n            //noinspection ConstantConditions\n            if (unit == null) {\n                throw new IllegalArgumentException(\"Non-null 'unit' required\");\n            }\n            this.waitForServerChanges = true;\n            this.initialDataTimeoutMillis = unit.toMillis(timeout);\n            return this;\n        }\n\n        /**\n         * Setting this will cause the Realm to become read only and all write transactions made against this Realm will\n         * fail with an {@link IllegalStateException}.\n         * <p>\n         * This in particular mean that {@link #initialData(Realm.Transaction)} will not work in combination with a\n         * read only Realm and setting this will result in a {@link IllegalStateException} being thrown.\n         * </p>\n         * Marking a Realm as read only only applies to the Realm in this process. Other processes and devices can still\n         * write to the Realm.\n         */\n        public SyncConfiguration.Builder readOnly() {\n            this.readOnly = true;\n            return this;\n        }\n\n        /**\n         * Setting this will cause Realm to compact the Realm file if the Realm file has grown too large and a\n         * significant amount of space can be recovered. See {@link DefaultCompactOnLaunchCallback} for details.\n         */\n        public SyncConfiguration.Builder compactOnLaunch() {\n            return compactOnLaunch(new DefaultCompactOnLaunchCallback());\n        }\n\n        /**\n         * Sets this to determine if the Realm file should be compacted before returned to the user. It is passed the\n         * total file size (data + free space) and the bytes used by data in the file.\n         *\n         * @param compactOnLaunch a callback called when opening a Realm for the first time during the life of a process\n         *                        to determine if it should be compacted before being returned to the user. It is passed\n         *                        the total file size (data + free space) and the bytes used by data in the file.\n         */\n        public SyncConfiguration.Builder compactOnLaunch(CompactOnLaunchCallback compactOnLaunch) {\n            //noinspection ConstantConditions\n            if (compactOnLaunch == null) {\n                throw new IllegalArgumentException(\"A non-null compactOnLaunch must be provided\");\n            }\n            this.compactOnLaunch = compactOnLaunch;\n            return this;\n        }\n\n        /**\n         * When opening the Realm for the first time, instead of creating an empty file,\n         * the Realm file will be copied from the provided asset file and used instead.\n         * <p>\n         * This can be used to pre-populate the Realm with data, so it doesn't have to be\n         * downloaded from the server.\n         * <p>\n         * The provided Realm file must be a valid synced Realm for the given user, and it must\n         * have been created using the {@link Realm#writeCopyTo(File)} API.\n         * <p>\n         * WARNING: This could potentially be a lengthy operation and should ideally be done on a background thread.\n         *\n         * @param assetFile path to the asset database file.\n         * @throws IllegalStateException if this Realm is also marked as {@link #inMemory()}.\n         */\n        public SyncConfiguration.Builder assetFile(String assetFile) {\n            if (Util.isEmptyString(assetFile)) {\n                throw new IllegalArgumentException(\"A non-empty asset file path must be provided\");\n            }\n            if (durability == OsRealmConfig.Durability.MEM_ONLY) {\n                throw new IllegalStateException(\"Realm can not use in-memory configuration if asset file is present.\");\n            }\n            this.assetFilePath = assetFile;\n\n            return this;\n        }\n\n\n        /**\n         * The prefix that is prepended to the path in the WebSocket request that initiates a sync\n         * connection to MongoDB Realm. The value specified must match the server’s configuration\n         * otherwise the device will not be able to create a connection. This value is optional\n         * and should only be set if a specific firewall rule requires it.\n         *\n         * @param urlPrefix The prefix to append to the sync connection url.\n         */\n        public SyncConfiguration.Builder urlPrefix(String urlPrefix) {\n            if (Util.isEmptyString(urlPrefix)) {\n                throw new IllegalArgumentException(\"Non-empty 'urlPrefix' required\");\n            }\n            if (urlPrefix.endsWith(\"/\")) {\n                urlPrefix = urlPrefix.substring(0, Math.min(0, urlPrefix.length() - 2));\n            }\n            this.syncUrlPrefix = urlPrefix;\n            return this;\n        }\n\n        private String MD5(String in) {\n            try {\n                MessageDigest digest = MessageDigest.getInstance(\"MD5\");\n                byte[] buf = digest.digest(in.getBytes(\"UTF-8\"));\n                StringBuilder builder = new StringBuilder();\n                for (byte b : buf) {\n                    builder.append(String.format(Locale.US, \"%02X\", b));\n                }\n                return builder.toString();\n            } catch (NoSuchAlgorithmException e) {\n                throw new RealmException(e.getMessage());\n            } catch (UnsupportedEncodingException e) {\n                throw new RealmException(e.getMessage());\n            }\n        }\n\n        /**\n         * Setting this will cause the local Realm file used to synchronize changes to be deleted if the {@link SyncUser}\n         * owning this Realm logs out from the device using {@link SyncUser#logOut()}.\n         * <p>\n         * The default behavior is that the Realm file is allowed to stay behind, making it possible for users to log\n         * in again and have access to their data faster.\n         */\n        /* FIXME: Disable this API since we cannot support it without https://github.com/realm/realm-core/issues/2165\n        public Builder deleteRealmOnLogout() {\n            this.deleteRealmOnLogout = true;\n            return this;\n        }\n        */\n\n        /**\n         * Sets the maximum number of live versions in the Realm file before an {@link IllegalStateException} is thrown when\n         * attempting to write more data.\n         * <p>\n         * Realm is capable of concurrently handling many different versions of Realm objects. This can happen if you\n         * have a Realm open on many different threads or are freezing objects while data is being written to the file.\n         * <p>\n         * Under normal circumstances this is not a problem, but if the number of active versions grow too large, it will\n         * have a negative effect on the filesize on disk. Setting this parameters can therefore be used to prevent uses of\n         * Realm that can result in very large Realms.\n         * <p>\n         * Note, the version number will also increase when changes from other devices are integrated on this device,\n         * so the number of active versions will also depend on what other devices writing to the same Realm are doing.\n         *\n         * @param number the maximum number of active versions before an exception is thrown.\n         * @see <a href=\"https://docs.mongodb.com/realm/sdk/android/fundamentals/realms/#realm-file-size\">FAQ</a>\n         */\n        public Builder maxNumberOfActiveVersions(long number) {\n            this.maxNumberOfActiveVersions = number;\n            return this;\n        }\n\n        /**\n         * Sets whether or not calls to {@link Realm#executeTransaction} are allowed from the UI thread.\n         * <p>\n         * <b>WARNING: Realm does not allow synchronous transactions to be run on the main thread unless users explicitly opt in\n         * with this method.</b> We recommend diverting calls to {@code executeTransaction} to non-UI threads or, alternatively,\n         * using {@link Realm#executeTransactionAsync}.\n         */\n        public Builder allowWritesOnUiThread(boolean allowWritesOnUiThread) {\n            this.allowWritesOnUiThread = allowWritesOnUiThread;\n            return this;\n        }\n\n        /**\n         * Sets whether or not {@code RealmQueries} are allowed from the UI thread.\n         * <p>\n         * By default Realm allows queries on the main thread. However, by doing so your application may experience a drop of\n         * frames or even ANRs. We recommend diverting queries to non-UI threads or, alternatively, using\n         * {@link RealmQuery#findAllAsync()} or {@link RealmQuery#findFirstAsync()}.\n         */\n        public Builder allowQueriesOnUiThread(boolean allowQueriesOnUiThread) {\n            this.allowQueriesOnUiThread = allowQueriesOnUiThread;\n            return this;\n        }\n\n        /**\n         * Creates the RealmConfiguration based on the builder parameters.\n         *\n         * @return the created {@link SyncConfiguration}.\n         * @throws IllegalStateException if the configuration parameters are invalid or inconsistent.\n         */\n        public SyncConfiguration build() {\n            if (serverUrl == null || user == null) {\n                throw new IllegalStateException(\"serverUrl() and user() are both required.\");\n            }\n\n            // Check that readOnly() was applied to legal configuration. Right now it should only be allowd if\n            // an assetFile is configured\n            if (readOnly) {\n                if (initialDataTransaction != null) {\n                    throw new IllegalStateException(\"This Realm is marked as read-only. \" +\n                            \"Read-only Realms cannot use initialData(Realm.Transaction).\");\n                }\n                if (!waitForServerChanges) {\n                    throw new IllegalStateException(\"A read-only Realms must be provided by some source. \" +\n                            \"'waitForInitialRemoteData()' wasn't enabled which is currently the only supported source.\");\n                }\n            }\n\n            if (syncClientResetStrategy == null) {\n                this.syncClientResetStrategy = user.getApp().getConfiguration().getDefaultSyncClientResetStrategy();\n            }\n\n            if (rxFactory == null && Util.isRxJavaAvailable()) {\n                rxFactory = new RealmObservableFactory(true);\n            }\n\n            if (flowFactory == null && Util.isCoroutinesAvailable()) {\n                flowFactory = new RealmFlowFactory(true);\n            }\n\n            URI resolvedServerUrl = serverUrl;\n            syncUrlPrefix = String.format(\"/api/client/v2.0/app/%s/realm-sync\", user.getApp().getConfiguration().getAppId());\n\n            String absolutePathForRealm = user.getApp().getSync().getAbsolutePathForRealm(user.getId(), partitionValue, filename);\n            File realmFile = new File(absolutePathForRealm);\n\n            if (!Util.isEmptyString(serverCertificateAssetName)) {\n                if (syncClientValidateSsl) {\n                    // Create the path where the serverCertificateAssetName will be copied\n                    // so we can supply it to the Sync client.\n                    // using realmFileDirectory avoid file collision between same filename from different users (Realms)\n                    String fileName = serverCertificateAssetName.substring(serverCertificateAssetName.lastIndexOf(File.separatorChar) + 1);\n                    File realmFileDirectory = new File(realmFile.getParent());\n                    serverCertificateFilePath = new File(realmFileDirectory, fileName).getAbsolutePath();\n                } else {\n                    RealmLog.warn(\"SSL Verification is disabled, the provided server certificate will not be used.\");\n                }\n            }\n\n            return new SyncConfiguration(\n                    realmFile,\n                    assetFilePath,\n                    key,\n                    schemaVersion,\n                    null, // Custom migrations not supported\n                    false, // MigrationNeededException is never thrown\n                    durability,\n                    createSchemaMediator(modules, debugSchema, false),\n                    rxFactory,\n                    flowFactory,\n                    initialDataTransaction,\n                    readOnly,\n                    maxNumberOfActiveVersions,\n                    allowWritesOnUiThread,\n                    allowQueriesOnUiThread,\n\n                    // Sync Configuration specific\n                    user,\n                    resolvedServerUrl,\n                    errorHandler,\n                    syncClientResetStrategy,\n                    deleteRealmOnLogout,\n                    syncClientValidateSsl,\n                    serverCertificateAssetName,\n                    serverCertificateFilePath,\n                    waitForServerChanges,\n                    initialDataTimeoutMillis,\n                    sessionStopPolicy,\n                    compactOnLaunch,\n                    syncUrlPrefix,\n                    partitionValue,\n                    initialSubscriptionsHandler\n            );\n        }\n\n        private void checkModule(Object module) {\n            if (!module.getClass().isAnnotationPresent(RealmModule.class)) {\n                throw new IllegalArgumentException(module.getClass().getCanonicalName() + \" is not a RealmModule. \" +\n                        \"Add @RealmModule to the class definition.\");\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/objectServer/java/io/realm/mongodb/sync/SyncSession.java",
    "content": "/*\n * Copyright 2020 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\npackage io.realm.mongodb.sync;\n\nimport java.net.URI;\nimport java.util.HashMap;\nimport java.util.IdentityHashMap;\nimport java.util.Iterator;\nimport java.util.Locale;\nimport java.util.Map;\nimport java.util.concurrent.CopyOnWriteArrayList;\nimport java.util.concurrent.CountDownLatch;\nimport java.util.concurrent.TimeUnit;\nimport java.util.concurrent.atomic.AtomicInteger;\nimport java.util.concurrent.atomic.AtomicLong;\nimport java.util.concurrent.atomic.AtomicReference;\n\nimport io.realm.annotations.Beta;\nimport io.realm.internal.ErrorCategory;\nimport io.realm.mongodb.ErrorCode;\nimport io.realm.mongodb.AppException;\nimport io.realm.Realm;\nimport io.realm.RealmConfiguration;\nimport io.realm.internal.Keep;\nimport io.realm.internal.Util;\nimport io.realm.internal.util.Pair;\nimport io.realm.log.RealmLog;\nimport io.realm.mongodb.User;\n\n/**\n * A session controls how data is synchronized between a single Realm on the device and the server\n * Realm on the Realm Object Server.\n * <p>\n * A Session is created by opening a Realm instance using a {@link SyncConfiguration}. Once a session has been created,\n * it will continue to exist until the app is closed or all threads using this {@link SyncConfiguration} closes their respective {@link Realm}s.\n * <p>\n * A session is controlled by Realm, but can provide additional information in case of errors.\n * These errors are passed along in the {@link SyncSession.ErrorHandler}.\n * <p>\n * When creating a session, Realm will establish a connection to the server. This connection is\n * controlled by Realm and might be shared between multiple sessions. It is possible to get insight\n * into the connection using {@link #addConnectionChangeListener(ConnectionListener)} and {@link #isConnected()}.\n * <p>\n * The session itself has a different lifecycle than the underlying connection. The state of the session\n * can be found using {@link #getState()}.\n * <p>\n * The {@link SyncSession} object is thread safe.\n */\n@Keep\n@Beta\npublic class SyncSession {\n    private static final int DIRECTION_DOWNLOAD = 1;\n    private static final int DIRECTION_UPLOAD = 2;\n\n    private final long appNativePointer;\n    private final SyncConfiguration configuration;\n    private final ErrorHandler errorHandler;\n    private final SyncClientResetStrategy clientResetHandler;\n    private volatile boolean isClosed = false;\n    private final AtomicReference<WaitForSessionWrapper> waitingForServerChanges = new AtomicReference<>(null);\n\n    // Keeps track of how many times `uploadAllLocalChanges()` or `downloadAllServerChanges()` have\n    // been called. This is needed so we can correctly ignore canceled requests.\n    private final AtomicInteger waitCounter = new AtomicInteger(0);\n    private final Object waitForChangesMutex = new Object();\n\n    // We need JavaId -> Listener so C++ can trigger callbacks without keeping a reference to the\n    // jobject, which would require a similar map on the C++ side.\n    // We need Listener -> Token map in order to remove the progress listener in C++ from Java.\n    private final Map<Long, Pair<ProgressListener, Progress>> listenerIdToProgressListenerMap = new HashMap<>();\n    private final Map<ProgressListener, Long> progressListenerToOsTokenMap = new IdentityHashMap<>();\n    // Counter used to assign all ProgressListeners on this session with a unique id.\n    // ListenerId is created by Java to enable C++ to reference the java listener without holding\n    // a reference to the actual object.\n    // ListenerToken is the same concept, but created by OS and represents the listener.\n    // We can unfortunately not just use the ListenerToken, since we need it to be available before\n    // we register the listener.\n    private final AtomicLong progressListenerId = new AtomicLong(-1);\n\n    // represent different states as defined in SyncSession::PublicState 'sync_session.hpp'\n    private static final byte STATE_VALUE_ACTIVE = 0;\n    private static final byte STATE_VALUE_DYING = 1;\n    private static final byte STATE_VALUE_INACTIVE = 2;\n    private static final byte STATE_VALUE_WAITING_FOR_ACCESS_TOKEN = 3;\n    private static final byte STATE_VALUE_PAUSED = 4;\n\n\n    // List of Java connection change listeners\n    private final CopyOnWriteArrayList<ConnectionListener> connectionListeners = new CopyOnWriteArrayList<>();\n\n    // Reference to the token representing the native listener for connection changes\n    // Only one native listener is used for all Java listeners\n    private long nativeConnectionListenerToken;\n\n    // represent different states as defined in SyncSession::PublicConnectionState 'sync_session.hpp'\n    // saved here instead of as constants in ConnectionState.java to enable static checking by JNI\n    static final byte CONNECTION_VALUE_DISCONNECTED = 0;\n    static final byte CONNECTION_VALUE_CONNECTING = 1;\n    static final byte CONNECTION_VALUE_CONNECTED = 2;\n\n    /**\n     * Enum describing the states a SyncSession can be in. The initial state is\n     * {@link State#INACTIVE}.\n     * <p>\n     * A Realm will automatically synchronize data with the server if the session is either {@link State#ACTIVE}\n     * or {@link State#DYING} and {@link #isConnected()} returns {@code true}.\n     */\n    public enum State {\n\n        /**\n         * This is the initial state. The session is closed. No data is being synchronized. The session\n         * will automatically transition to {@link #ACTIVE} when a Realm is opened.\n         */\n        INACTIVE(STATE_VALUE_INACTIVE),\n\n        /**\n         * The Realm is open and data will be synchronized between the device and the server\n         * if the underlying connection is {@link ConnectionState#CONNECTED}.\n         * <p>\n         * The session will remain in this state until the Realm\n         * is closed. In which case it will become {@link #DYING}.\n         */\n        ACTIVE(STATE_VALUE_ACTIVE),\n\n        /**\n         * The Realm was closed, but still contains data that needs to be synchronized to the server.\n         * The session will attempt to upload all local data before going {@link #INACTIVE}.\n         */\n        DYING(STATE_VALUE_DYING),\n\n        /**\n         * The user is attempting to synchronize data but needs a valid access token to do so. Realm\n         * will either use a cached token or automatically try to acquire one based on the current\n         * users login. This requires a network connection.\n         * <p>\n         * Data cannot be synchronized in this state.\n         * <p>\n         * Once a valid token is acquired, the session will transition to {@link #ACTIVE}.\n         */\n        WAITING_FOR_ACCESS_TOKEN(STATE_VALUE_WAITING_FOR_ACCESS_TOKEN),\n\n        /**\n         * The Realm is open and has a connection to the server, but no data is allowed to be\n         * transferred between the device and the server. Call {@link SyncSession#start()} to start\n         * transferring data again. The state will then become {@link #ACTIVE}.\n         */\n        PAUSED(STATE_VALUE_PAUSED);\n\n        final byte value;\n\n        State(byte value) {\n            this.value = value;\n        }\n\n        static State fromNativeValue(long value) {\n            State[] stateCodes = values();\n            for (State state : stateCodes) {\n                if (state.value == value) {\n                    return state;\n                }\n            }\n\n            throw new IllegalArgumentException(\"Unknown session state code: \" + value);\n        }\n    }\n\n    SyncSession(SyncConfiguration configuration, long appNativePointer) {\n        this.configuration = configuration;\n        this.errorHandler = configuration.getErrorHandler();\n        this.clientResetHandler = configuration.getSyncClientResetStrategy();\n        this.appNativePointer = appNativePointer;\n    }\n\n    /**\n     * Returns the {@link SyncConfiguration} that is responsible for controlling the session.\n     *\n     * @return SyncConfiguration that defines and controls this session.\n     */\n    public SyncConfiguration getConfiguration() {\n        return configuration;\n    }\n\n    /**\n     * Returns the {@link User} defined by the {@link SyncConfiguration} that is used to connect to\n     * MongoDB Realm.\n     *\n     * @return {@link User} used to authenticate the session on MongoDB Realm.\n     */\n    public User getUser() {\n        return configuration.getUser();\n    }\n\n    /**\n     * Returns the {@link URI} describing the remote Realm which this session connects to and synchronizes changes with.\n     *\n     * @return {@link URI} describing the remote Realm.\n     */\n    public URI getServerUrl() {\n        return configuration.getServerUrl();\n    }\n\n    // This callback will happen on the thread running the Sync Client.\n    void notifySessionError(byte nativeErrorCategory, int nativeErrorCode, String errorMessage, String clientResetPathInfo) {\n        if (errorHandler == null) {\n            return;\n        }\n        ErrorCode errCode = ErrorCode.fromNativeError(ErrorCategory.toCategory(nativeErrorCategory), nativeErrorCode);\n        if (errCode == ErrorCode.CLIENT_RESET) {\n            // errorMessage contains the path to the backed up file\n            if (clientResetPathInfo == null) {\n                throw new IllegalStateException(\"Missing Client Reset info.\");\n            }\n            RealmConfiguration backupRealmConfiguration = configuration.forErrorRecovery(clientResetPathInfo);\n\n            if (clientResetHandler instanceof ManuallyRecoverUnsyncedChangesStrategy) {\n                ((ManuallyRecoverUnsyncedChangesStrategy) clientResetHandler).onClientReset(\n                        this,\n                        new ClientResetRequiredError(\n                                appNativePointer,\n                                errCode,\n                                errorMessage,\n                                configuration,\n                                backupRealmConfiguration\n                        )\n                );\n            } else if (clientResetHandler instanceof AutomaticClientResetStrategy) {\n                // Required to support the deprecated DiscardUnsyncedChangesStrategy::onError\n                if (clientResetHandler instanceof DiscardUnsyncedChangesStrategy) {\n                    ((DiscardUnsyncedChangesStrategy) clientResetHandler).onError(\n                            this,\n                            new ClientResetRequiredError(\n                                    appNativePointer,\n                                    errCode,\n                                    errorMessage,\n                                    configuration,\n                                    backupRealmConfiguration\n                            )\n                    );\n                }\n                ((AutomaticClientResetStrategy) clientResetHandler).onManualResetFallback(\n                        this,\n                        new ClientResetRequiredError(\n                                appNativePointer,\n                                errCode,\n                                errorMessage,\n                                configuration,\n                                backupRealmConfiguration\n                        )\n                );\n            }\n        } else {\n            AppException wrappedError;\n            if (errCode == ErrorCode.UNKNOWN) {\n                wrappedError = new AppException(errCode.getType(), nativeErrorCode, errorMessage);\n            } else {\n                wrappedError = new AppException(errCode, errorMessage);\n            }\n            errorHandler.onError(this, wrappedError);\n        }\n    }\n\n    /**\n     * Get the current session's state, as defined in {@link SyncSession.State}.\n     * <p>\n     * Note that the state may change after this method returns.\n     *\n     * @return the state of the session.\n     * @see SyncSession.State\n     */\n    public State getState() {\n        byte state = nativeGetState(appNativePointer, configuration.getPath());\n        if (state == -1) {\n            // session was not found, probably the Realm was closed\n            throw new IllegalStateException(\"Could not find session, Realm was probably closed\");\n        }\n        return State.fromNativeValue(state);\n    }\n\n    /**\n     * Get the current state of the connection used by the session as defined in {@link ConnectionState}.\n     *\n     * @return the state of connection used by the session.\n     * @see ConnectionState\n     */\n    public ConnectionState getConnectionState() {\n        byte state = nativeGetConnectionState(appNativePointer, configuration.getPath());\n        if (state == -1) {\n            // session was not found, probably the Realm was closed\n            throw new IllegalStateException(\"Could not find session, Realm was probably closed\");\n        }\n        return ConnectionState.fromNativeValue(state);\n    }\n\n    /**\n     * Checks if the session is connected to the server and can synchronize data.\n     *\n     * This is a best guess effort. To conserve battery the underlying implementation uses heartbeats\n     * to  detect if the connection is still available. So if no data is actively being synced\n     * and some time has elapsed since the last heartbeat, the connection could have been dropped but\n     * this method will still return {@code true}.\n     *\n     * @return {@code true} if the session is connected and ready to synchronize data, {@code false}\n     * if not or if it is in the process of connecting.\n     */\n    public boolean isConnected() {\n        ConnectionState connectionState = ConnectionState.fromNativeValue(nativeGetConnectionState(appNativePointer, configuration.getPath()));\n        State sessionState = getState();\n        return (sessionState == State.ACTIVE || sessionState == State.DYING) && connectionState == ConnectionState.CONNECTED;\n    }\n\n    /**\n     * All progress listener events from native Sync are reported to this method.\n     */\n    @SuppressWarnings(\"unused\")\n    synchronized void notifyProgressListener(long listenerId, long transferredBytes, long transferableBytes) {\n        Pair<ProgressListener, Progress> listener = listenerIdToProgressListenerMap.get(listenerId);\n        if (listener != null) {\n            Progress newProgressNotification = new Progress(transferredBytes, transferableBytes);\n            if (!newProgressNotification.equals(listener.second)) {\n                listener.second = newProgressNotification;\n                try {\n                    listener.first.onChange(newProgressNotification);\n                } catch (Exception exception) {\n                    RealmLog.error(exception);\n                }\n            }\n        } else {\n            RealmLog.debug(\"Trying unknown listener failed: \" + listenerId);\n        }\n    }\n\n    /**\n     * Called from native code. This method is not allowed to throw as it would be swallowed\n     * by the native Sync Client thread. Instead log all exceptions to logcat.\n     */\n    @SuppressWarnings(\"unused\")\n    void notifyConnectionListeners(long oldState, long newState) {\n        for (ConnectionListener listener : connectionListeners) {\n            try {\n                listener.onChange(ConnectionState.fromNativeValue(oldState), ConnectionState.fromNativeValue(newState));\n            } catch (Exception exception) {\n                RealmLog.error(exception);\n            }\n        }\n    }\n\n    /**\n     * Adds a progress listener tracking changes that need to be downloaded from the Realm Object\n     * Server.\n     * <p>\n     * The {@link ProgressListener} will be triggered immediately when registered, and periodically\n     * afterwards.\n     *\n     * @param mode type of mode used. See {@link ProgressMode} for more information.\n     * @param listener the listener to register.\n     */\n    public synchronized void addDownloadProgressListener(ProgressMode mode, ProgressListener listener) {\n        addProgressListener(mode, DIRECTION_DOWNLOAD, listener);\n    }\n\n    /**\n     * Adds a progress listener tracking changes that need to be uploaded from the device to the\n     * Realm Object Server.\n     * <p>\n     * The {@link ProgressListener} will be triggered immediately when registered, and periodically\n     * afterwards.\n     *\n     * @param mode type of mode used. See {@link ProgressMode} for more information.\n     * @param listener the listener to register.\n     */\n    public synchronized void addUploadProgressListener(ProgressMode mode, ProgressListener listener) {\n        addProgressListener(mode, DIRECTION_UPLOAD, listener);\n    }\n\n    /**\n     * Removes a progress listener. If the listener wasn't registered, this method will do nothing.\n     *\n     * @param listener listener to remove.\n     */\n    public synchronized void removeProgressListener(ProgressListener listener) {\n        //noinspection ConstantConditions\n        if (listener == null) {\n            return;\n        }\n        // If an exception is thrown somewhere in here, we will most likely leave the various\n        // maps in an inconsistent manner. Not much we can do about it.\n        Long token = progressListenerToOsTokenMap.remove(listener);\n        if (token != null) {\n            Iterator<Map.Entry<Long, Pair<ProgressListener, Progress>>> it = listenerIdToProgressListenerMap.entrySet().iterator();\n            while (it.hasNext()) {\n                Map.Entry<Long, Pair<ProgressListener, Progress>> entry = it.next();\n                if (entry.getValue().first.equals(listener)) {\n                    it.remove();\n                    break;\n                }\n            }\n            nativeRemoveProgressListener(appNativePointer, configuration.getPath(), token);\n        }\n    }\n\n    private void addProgressListener(ProgressMode mode, int direction, ProgressListener listener) {\n        checkProgressListenerArguments(mode, listener);\n        boolean isStreaming = (mode == ProgressMode.INDEFINITELY);\n        long listenerId = progressListenerId.incrementAndGet();\n\n        // A listener might be triggered immediately as part of `nativeAddProgressListener`, so\n        // we need to make sure it can be found by SyncManager.notifyProgressListener()\n        listenerIdToProgressListenerMap.put(listenerId, new Pair<ProgressListener, Progress>(listener, null));\n        long listenerToken = nativeAddProgressListener(appNativePointer, configuration.getPath(), listenerId , direction, isStreaming);\n        if (listenerToken == 0) {\n            // ObjectStore did not register the listener. This can happen if a\n            // listener is registered with ProgressMode.CURRENT_CHANGES and no changes actually\n            // exists. In that case the listener was triggered immediately and we just need\n            // to clean it up, since it will never be called again.\n            listenerIdToProgressListenerMap.remove(listenerId);\n        } else {\n            // Listener was properly registered.\n            progressListenerToOsTokenMap.put(listener, listenerToken);\n        }\n    }\n\n    private void checkProgressListenerArguments(ProgressMode mode, ProgressListener listener) {\n        Util.checkNull(listener, \"listener\");\n        Util.checkNull(mode, \"mode\");\n    }\n\n    /**\n     * Adds a listener tracking changes to the connection backing this session. See {@link ConnectionState}\n     * for further details.\n     *\n     * @param listener the listener to register.\n     * @throws IllegalArgumentException if the listener is {@code null}.\n     * @see ConnectionState\n     */\n    public synchronized void addConnectionChangeListener(ConnectionListener listener) {\n        Util.checkNull(listener, \"listener\");\n        if (connectionListeners.isEmpty()) {\n            nativeConnectionListenerToken = nativeAddConnectionListener(appNativePointer, configuration.getPath());\n        }\n        connectionListeners.add(listener);\n    }\n\n    /**\n     * Removes a previously registered {@link ConnectionListener}.\n     *\n     * @param listener listener to remove\n     * @throws IllegalArgumentException if the listener is {@code null}.\n     */\n    public synchronized void removeConnectionChangeListener(ConnectionListener listener) {\n        Util.checkNull(listener, \"listener\");\n        connectionListeners.remove(listener);\n        if (connectionListeners.isEmpty()) {\n            nativeRemoveConnectionListener(appNativePointer, nativeConnectionListenerToken, configuration.getPath());\n        }\n    }\n\n    synchronized void close() {\n        // Clear any running listeners as they might prevent the underlying session\n        // from correctly closing.\n        if (!connectionListeners.isEmpty()) {\n            connectionListeners.clear();\n            nativeRemoveConnectionListener(appNativePointer, nativeConnectionListenerToken, configuration.getPath());\n        }\n        for (Long token : progressListenerToOsTokenMap.values()) {\n            nativeRemoveProgressListener(appNativePointer, configuration.getPath(), token);\n        }\n        listenerIdToProgressListenerMap.clear();\n        progressListenerToOsTokenMap.clear();\n        isClosed = true;\n    }\n\n    // This method will be called once all changes have been downloaded or uploaded.\n    // This method might be called on another thread than the one that called `downloadAllServerChanges` or\n    // `uploadAllLocalChanges()`\n    //\n    // Be very careful with synchronized blocks.\n    // If the native listener was successfully registered, Object Store guarantees that this method will be called at\n    // least once, even if the session is closed.\n    @SuppressWarnings(\"unused\")\n    private void notifyAllChangesSent(int callbackId, Long errorCategory, Long errorCode, String errorMessage) {\n        WaitForSessionWrapper wrapper = waitingForServerChanges.get();\n        if (wrapper != null) {\n            // Only react to callback if the callback is \"active\"\n            // A callback can only become inactive if the thread was interrupted:\n            // 1. Call `downloadAllServerChanges()` (callback = 1)\n            // 2. Interrupt it\n            // 3. Call `uploadAllLocalChanges()` ( callback = 2)\n            // 4. Sync notifies session that callback:1 is done. It should be ignored.\n            if (waitCounter.get() == callbackId) {\n                wrapper.handleResult(errorCategory, errorCode, errorMessage);\n            }\n        }\n    }\n\n    /**\n     * Calling this method will block until all known remote changes have been downloaded and applied to the Realm.\n     * This will involve network access, so calling this method should only be done from a non-UI thread.\n     * <p>\n     * If the device is offline, this method might never return.\n     * <p>\n     * This method cannot be called before the session has been started.\n     *\n     * @throws IllegalStateException if called on the Android main thread.\n     * @throws InterruptedException if the thread was interrupted while downloading was in progress.\n     */\n    public void downloadAllServerChanges() throws InterruptedException {\n        Util.checkNotOnMainThread(\"downloadAllServerChanges() cannot be called from the main thread.\");\n\n        // Blocking only happens at the Java layer. To prevent deadlocking the underlying SyncSession we register\n        // an async listener there and let it callback to the Java Session when done. This feels icky at best, but\n        // since all operations on the SyncSession operate under a shared mutex, we would prevent all other actions on the\n        // session, including trying to stop it.\n        // In Java we cannot lock on the Session object either since it will prevent any attempt at modifying the\n        // lifecycle while it is in a waiting state. Thus we use a specialised mutex.\n        synchronized (waitForChangesMutex) {\n            waitForChanges(DIRECTION_DOWNLOAD, Long.MAX_VALUE, TimeUnit.MILLISECONDS);\n        }\n    }\n\n    /**\n     * Calling this method will block until all known remote changes have been downloaded and applied to the Realm\n     * or the specified timeout is hit. This will involve network access, so calling this method should only be done\n     * from a non-UI thread.\n     * <p>\n     * This method cannot be called before the Realm has been opened.\n     *\n     * @throws IllegalStateException if called on the Android main thread.\n     * @throws InterruptedException if the download took longer than the specified timeout or the thread was interrupted while downloading was in progress.\n     * The download will continue in the background even after this exception is thrown.\n     * @throws IllegalArgumentException if {@code timeout} is less than or equal to {@code 0} or {@code unit} is {@code null}.\n     * @return {@code true} if the data was downloaded before the timeout. {@code false} if the operation timed out or otherwise failed.\n     */\n    public boolean downloadAllServerChanges(long timeout, TimeUnit unit) throws InterruptedException {\n        Util.checkNotOnMainThread(\"downloadAllServerChanges() cannot be called from the main thread.\");\n        checkTimeout(timeout, unit);\n\n        // Blocking only happens at the Java layer. To prevent deadlocking the underlying SyncSession we register\n        // an async listener there and let it callback to the Java Session when done. This feels icky at best, but\n        // since all operations on the SyncSession operate under a shared mutex, we would prevent all other actions on the\n        // session, including trying to stop it.\n        // In Java we cannot lock on the Session object either since it will prevent any attempt at modifying the\n        // lifecycle while it is in a waiting state. Thus we use a specialised mutex.\n        synchronized (waitForChangesMutex) {\n            return waitForChanges(DIRECTION_DOWNLOAD, timeout, unit);\n        }\n    }\n\n    /**\n     * Calling this method will block until all known local changes have been uploaded to the server.\n     * This will involve network access, so calling this method should only be done from a non-UI thread.\n     * <p>\n     * If the device is offline, this method might never return.\n     * <p>\n     * This method cannot be called before the Realm has been opened.\n     *\n     * @throws IllegalStateException if called on the Android main thread.\n     * @throws InterruptedException if the thread was interrupted while downloading was in progress.\n     */\n    public void uploadAllLocalChanges() throws InterruptedException {\n        Util.checkNotOnMainThread(\"uploadAllLocalChanges() cannot be called from the main thread.\");\n\n        // Blocking only happens at the Java layer. To prevent deadlocking the underlying SyncSession we register\n        // an async listener there and let it callback to the Java Session when done. This feels icky at best, but\n        // since all operations on the SyncSession operate under a shared mutex, we would prevent all other actions on the\n        // session, including trying to stop it.\n        // In Java we cannot lock on the Session object either since it will prevent any attempt at modifying the\n        // lifecycle while it is in a waiting state. Thus we use a specialised mutex.\n        synchronized (waitForChangesMutex) {\n            waitForChanges(DIRECTION_UPLOAD, Long.MAX_VALUE, TimeUnit.MILLISECONDS);\n        }\n    }\n\n    /**\n     * Calling this method will block until all known local changes have been uploaded to the server or the specified\n     * timeout is hit. This will involve network access, so calling this method should only be done from a non-UI\n     * thread.\n     * <p>\n     * This method cannot be called before the Realm has been opened.\n     *\n     * @throws IllegalStateException if called on the Android main thread.\n     * @throws InterruptedException if the upload took longer than the specified timeout or the thread was interrupted while uploading was in progress.\n     * The upload will continue in the background even after this exception is thrown.\n     * @throws IllegalArgumentException if {@code timeout} is less than or equal to {@code 0} or {@code unit} is {@code null}.\n     * @return {@code true} if the data was uploaded before the timeout. {@code false} if the operation timed out or otherwise failed.\n     */\n    public boolean uploadAllLocalChanges(long timeout, TimeUnit unit) throws InterruptedException {\n        Util.checkNotOnMainThread(\"uploadAllLocalChanges() cannot be called from the main thread.\");\n        checkTimeout(timeout, unit);\n\n        // Blocking only happens at the Java layer. To prevent deadlocking the underlying SyncSession we register\n        // an async listener there and let it callback to the Java Session when done. This feels icky at best, but\n        // since all operations on the SyncSession operate under a shared mutex, we would prevent all other actions on the\n        // session, including trying to stop it.\n        // In Java we cannot lock on the Session object either since it will prevent any attempt at modifying the\n        // lifecycle while it is in a waiting state. Thus we use a specialised mutex.\n        synchronized (waitForChangesMutex) {\n            return waitForChanges(DIRECTION_UPLOAD, timeout, unit);\n        }\n    }\n\n    /**\n     * Attempts to start the session and enable synchronization with the Realm Object Server.\n     * <p>\n     * This happens automatically when opening the Realm instance, so doing it manually should only\n     * be needed if the session was stopped using {@link #stop()}.\n     * <p>\n     * If the session was already started, calling this method will do nothing.\n     * <p>\n     * A session is considered started if {@link #getState()} returns {@link State#ACTIVE}.\n     * If the session is {@link State#DYING}, the session\n     * will be moved back to {@link State#ACTIVE}.\n     *\n     * @see #getState()\n     * @see #stop()\n     */\n    public synchronized void start() {\n        nativeStart(appNativePointer, configuration.getPath());\n    }\n\n    /**\n     * Stops any synchronization with the Realm Object Server until the Realm is re-opened again\n     * after fully closing it.\n     * <p>\n     * Synchronization can be re-enabled by calling {@link #start()} again.\n     * <p>\n     * If the session is already stopped, calling this method will do nothing.\n     */\n    public synchronized void stop() {\n        close();\n        nativeStop(appNativePointer, configuration.getPath());\n    }\n\n    /**\n     * This method should only be called when guarded by the {@link #waitForChangesMutex}.\n     * It will block into all changes have been either uploaded or downloaded depending on the chosen direction.\n     *\n     * @param direction either {@link #DIRECTION_DOWNLOAD} or {@link #DIRECTION_UPLOAD}.\n     * @param timeout timeout parameter.\n     * @param unit timeout unit.\n     * @return {@code true} if the job completed before the timeout was hit, {@code false}\n     */\n    private boolean waitForChanges(int direction, long timeout, TimeUnit unit) throws InterruptedException {\n        if (direction != DIRECTION_DOWNLOAD && direction != DIRECTION_UPLOAD) {\n            throw new IllegalArgumentException(\"Unknown direction: \" + direction);\n        }\n        boolean result = false;\n        if (!isClosed) {\n            String realmPath = configuration.getPath();\n            WaitForSessionWrapper wrapper = new WaitForSessionWrapper();\n            waitingForServerChanges.set(wrapper);\n            int callbackId = waitCounter.incrementAndGet();\n            boolean listenerRegistered = (direction == DIRECTION_DOWNLOAD)\n                    ? nativeWaitForDownloadCompletion(appNativePointer, callbackId, realmPath)\n                    : nativeWaitForUploadCompletion(appNativePointer, callbackId, realmPath);\n            if (!listenerRegistered) {\n                waitingForServerChanges.set(null);\n                String errorMsg;\n                switch (direction) {\n                    case DIRECTION_DOWNLOAD: errorMsg = \"It was not possible to download all remote changes.\"; break;\n                    case DIRECTION_UPLOAD: errorMsg = \"It was not possible upload all local changes.\"; break;\n                    default:\n                        throw new IllegalArgumentException(\"Unknown direction: \" + direction);\n                }\n\n                throw new AppException(ErrorCode.UNKNOWN, errorMsg + \" Has the SyncClient been started?\");\n            }\n            try {\n                result = wrapper.waitForServerChanges(timeout, unit);\n            } catch(InterruptedException e) {\n                waitingForServerChanges.set(null); // Ignore any results being sent if the wait was interrupted.\n                throw e;\n            }\n\n            // This might return after the session was closed. In that case, just ignore any result\n            try {\n                if (!isClosed) {\n                    if (!wrapper.isSuccess()) {\n                        wrapper.throwExceptionIfNeeded();\n                    }\n                }\n            } finally {\n                waitingForServerChanges.set(null);\n            }\n        }\n        return result;\n    }\n\n    private void checkTimeout(long timeout, TimeUnit unit) {\n        if (timeout <= 0) {\n            throw new IllegalArgumentException(\"'timeout' must be > 0. It was: \" + timeout);\n        }\n        //noinspection ConstantConditions\n        if (unit == null) {\n            throw new IllegalArgumentException(\"Non-null 'unit' required\");\n        }\n    }\n\n    void shutdownAndWait() {\n        nativeShutdownAndWait(appNativePointer, configuration.getPath());\n    }\n\n    /**\n     * Interface used to report any session errors.\n     *\n     * @see SyncConfiguration.Builder#errorHandler(ErrorHandler)\n     */\n    public interface ErrorHandler {\n        /**\n         * Callback for errors on a session object. It is not allowed to throw an exception inside an error handler.\n         * If the operations in an error handler can throw, it is safer to catch any exception in the error handler.\n         * When an exception is thrown in the error handler, the occurrence will be logged and the exception\n         * will be ignored.\n         *\n         * @param session {@link SyncSession} this error happened on.\n         * @param error type of error.\n         */\n        void onError(SyncSession session, AppException error);\n    }\n\n    /**\n     * Callback for the specific error event known as a Client Reset, determined by the error code\n     * {@link ErrorCode#CLIENT_RESET}.\n     * <p>\n     * A synced Realm may need to be reset because the MongoDB Realm Server encountered an error and had\n     * to be restored from a backup or because it has been too long since the client connected to the\n     * server so the server has rotated the logs.\n     * <p>\n     * The Client Reset thus occurs because the server does not have the full information required to\n     * bring the Client fully up to date.\n     * <p>\n     * The reset process is as follows: the local copy of the Realm is copied into a recovery directory\n     * for safekeeping, and then deleted from the original location. The next time the Realm for that\n     * URL is opened, the Realm will automatically be re-downloaded from MongoDB Realm, and\n     * can be used as normal.\n     * <p>\n     * Data written to the Realm after the local copy of the Realm diverged from the backup remote copy\n     * will be present in the local recovery copy of the Realm file. The re-downloaded Realm will\n     * initially contain only the data present at the time the Realm was backed up on the server.\n     * <p>\n     * The client reset process can be initiated in one of two ways:\n     * <ol>\n     *     <li>\n     *         Run {@link ClientResetRequiredError#executeClientReset()} manually. All Realm instances must be\n     *         closed before this method is called.\n     *     </li>\n     *     <li>\n     *         If Client Reset isn't executed manually, it will automatically be carried out the next time all\n     *         Realm instances have been closed and re-opened. This will most likely be\n     *         when the app is restarted.\n     *     </li>\n     * </ol>\n     *\n     * <b>WARNING:</b>\n     * Any writes to the Realm file between this callback and Client Reset has been executed, will not be\n     * synchronized to MongoDB Realm. Those changes will only be present in the backed up file. It is therefore\n     * recommended to close all open Realm instances as soon as possible.\n     *\n     * @deprecated replaced by {@link ManuallyRecoverUnsyncedChangesStrategy}\n     */\n    @Deprecated\n    public interface ClientResetHandler extends ManuallyRecoverUnsyncedChangesStrategy {\n    }\n\n    // Wrapper class for handling the async operations of the underlying SyncSession calling\n    // `async_wait_for_download_completion` or `async_wait_for_upload_completion`\n    private static class WaitForSessionWrapper {\n\n        private final CountDownLatch waiter = new CountDownLatch(1);\n        private volatile boolean resultReceived = false;\n        private Long errorCategory = null;\n        private Long errorCode = null;\n        private String errorMessage;\n\n        /**\n         * Block until the wait either completes, timeouts or is terminated for other reasons.\n         * Timeouts are only applied if `timeout` >= 0.\n         */\n        public boolean waitForServerChanges(long timeout, TimeUnit unit) throws InterruptedException {\n            if (!resultReceived) {\n                return waiter.await(timeout, unit);\n            }\n            return isSuccess();\n        }\n\n        /**\n         * Process the result of a waiting action. This will also unblock anyone who called {@link #waiter}.\n         *\n         * @param errorCode error code if an error occurred, {@code null} if changes were successfully downloaded.\n         * @param errorMessage error message (if any).\n         */\n        public void handleResult(Long errorCategory, Long errorCode, String errorMessage) {\n            this.errorCategory = errorCategory;\n            this.errorCode = errorCode;\n            this.errorMessage = errorMessage;\n            this.resultReceived = true;\n            waiter.countDown();\n        }\n\n        public boolean isSuccess() {\n            return resultReceived && errorCode == null;\n        }\n\n        /**\n         * Will throw an exception if the wait was terminated with an error. If it was canceled, this method will\n         * do nothing.\n         */\n        public void throwExceptionIfNeeded() {\n            if (resultReceived && errorCode != null) {\n                // Core report errors with int64, so we need to add some extra checks\n                // to make sure the value is within a range of known errors we can map to,\n                // which are all inside Integer range\n                long longErrorCode = errorCode;\n                ErrorCode mappedError = ErrorCode.fromNativeError(ErrorCategory.toCategory(errorCategory.byteValue()), (int) longErrorCode);\n                if (longErrorCode >= Integer.MIN_VALUE && longErrorCode <= Integer.MAX_VALUE && mappedError != ErrorCode.UNKNOWN) {\n                    throw new AppException(mappedError, errorMessage);\n                } else {\n                    throw new AppException(mappedError, String.format(Locale.US, \"Internal error (%d): %s\", errorCode, errorMessage));\n                }\n            }\n        }\n    }\n\n    private native long nativeAddConnectionListener(long appNativePointer, String localRealmPath);\n    private static native void nativeRemoveConnectionListener(long appNativePointer, long listenerId, String localRealmPath);\n    private native long nativeAddProgressListener(long appNativePointer, String localRealmPath, long listenerId, int direction, boolean isStreaming);\n    private static native void nativeRemoveProgressListener(long appNativePointer, String localRealmPath, long listenerToken);\n    private native boolean nativeWaitForDownloadCompletion(long appNativePointer, int callbackId, String localRealmPath);\n    private native boolean nativeWaitForUploadCompletion(long appNativePointer, int callbackId, String localRealmPath);\n    private static native byte nativeGetState(long appNativePointer, String localRealmPath);\n    private static native byte nativeGetConnectionState(long appNativePointer, String localRealmPath);\n    private static native void nativeStart(long appNativePointer, String localRealmPath);\n    private static native void nativeStop(long appNativePointer, String localRealmPath);\n    private static native void nativeShutdownAndWait(long appNativePointer, String localRealmPath);\n}\n"
  },
  {
    "path": "realm/realm-library/src/objectServer/java/io/realm/mongodb/sync/package-info.java",
    "content": "/*\n * Copyright 2021 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@javax.annotation.ParametersAreNonnullByDefault\npackage io.realm.mongodb.sync;\n"
  },
  {
    "path": "realm/realm-library/src/overview.html",
    "content": "<body>\n<h2>Quick start</h2>\n\n<img src=\"./realm-java-overview.png\" alt=\"Overview of Realm\" style=\"display: block; margin: 0 auto;\" width=\"35%\"/>\n\n<ul>\n    <li><b>{@link io.realm.Realm}</b><br/> The Realm database. The storage and transactional manager of your object\n        persistent store. It is in charge of creating and removing instances of your RealmObjects, querying, and\n        performing transactions.\n        <a href=\"https://docs.mongodb.com/realm/sdk/android/fundamentals/realms/\">Read more</a>.\n        <p />\n    </li>\n\n    <li><b>{@link io.realm.RealmConfiguration}</b><br/>\n        A configuration object that is used to setup a specific Realm instance.\n        <a href=\"https://docs.mongodb.com/realm/sdk/android/examples/open-and-close-a-local-realm/\">Read more</a>.\n        <p />\n    </li>\n\n    <li><b>{@link io.realm.RealmObject}</b><br/>\n        The super class of all objects (models) that are to be stored in Realm. A Java object must extend\n        {@link io.realm.RealmObject} in order to be considered a <i>RealmObject</i>.\n        <a href=\"https://docs.mongodb.com/realm/sdk/android/fundamentals/object-models-and-schemas/\">Read more</a>.\n        <p />\n    </li>\n\n    <li><b>{@link io.realm.RealmList}</b><br/>\n        A <a href=\"https://docs.oracle.com/javase/7/docs/api/java/util/List.html\">List</a> that is used in\n        <i>RealmObject</i>s to model one-to-many relationships with other <i>RealmObject</i>s.\n        <a href=\"https://docs.mongodb.com/realm/sdk/android/data-types/collections/#list-collections\">Read more</a>.\n        <p />\n    </li>\n\n    <li><b>{@link io.realm.RealmQuery}</b><br/>\n        An object that encapsulates a query as defined through Realms fluent query interface. Queries are executed\n        using either the {@link io.realm.RealmQuery#findAll}, {@link io.realm.RealmQuery#findFirst} or their variants.\n        <a href=\"https://docs.mongodb.com/realm/sdk/android/fundamentals/live-queries/\">Read more</a>.\n        <p />\n    </li>\n\n    <li><b>{@link io.realm.RealmResults}</b><br/>\n        The result set of an executed <i>RealmQuery</i> for a given Realm. <i>RealmResults</i> are live,\n        <a href=\"https://docs.mongodb.com/realm/sdk/android/data-types/collections/#collections-are-live\">auto-updating</a> \n        views into the underlying data, which means results never have to be re-fetched.\n        <a href=\"https://docs.mongodb.com/realm/sdk/android/data-types/collections/#results-collections\">Read more</a>.\n        <p />\n    </li>\n</ul>\n</body>\n"
  },
  {
    "path": "realm/realm-library/src/syncIntegrationTest/assets/trusted_ca.pem",
    "content": "Certificate:\n    Data:\n        Version: 3 (0x2)\n        Serial Number: 1 (0x1)\n    Signature Algorithm: sha1WithRSAEncryption\n        Issuer: DC=io, DC=realm, O=Realm, OU=Realm Test Root CA, CN=Realm Test Root CA\n        Validity\n            Not Before: Sep  7 09:42:23 2016 GMT\n            Not After : Sep  7 09:42:23 2026 GMT\n        Subject: DC=io, DC=realm, O=Realm, OU=Realm Test Root CA, CN=Realm Test Root CA\n        Subject Public Key Info:\n            Public Key Algorithm: rsaEncryption\n                Public-Key: (4096 bit)\n                Modulus:\n                    00:dc:43:b2:92:b1:be:ff:da:43:f3:b8:d5:4b:42:\n                    9e:05:7f:4e:bf:09:2f:02:33:1a:24:44:ff:12:7e:\n                    35:9c:cd:b3:61:78:0a:b0:83:80:82:ec:a2:5c:66:\n                    f0:7d:d4:df:f9:9c:be:b5:4e:e6:6b:60:59:e7:ed:\n                    0f:85:47:2e:83:5a:55:c1:1a:32:a9:c8:b8:d4:5a:\n                    96:94:ef:4f:f1:aa:64:59:c8:8c:89:1a:e6:1a:f4:\n                    94:5c:e8:be:59:0f:6b:cc:9d:58:e5:e4:29:22:ba:\n                    54:96:dd:8a:f6:28:d6:d6:c8:ca:df:b2:c2:f7:1e:\n                    19:58:75:ab:a2:ab:04:e4:1f:ed:fe:04:ec:f2:f1:\n                    da:62:d2:bd:9b:4b:84:ba:d0:5e:dc:63:40:03:cc:\n                    c6:88:1c:15:5c:96:41:b0:58:3d:af:08:bd:64:34:\n                    b8:3b:00:03:28:21:37:bf:5c:bc:1c:e7:2d:08:a5:\n                    02:ad:c0:49:ba:34:56:8e:63:66:ba:60:8c:5c:89:\n                    ba:0f:76:47:9c:bc:31:6a:5d:8e:4d:a9:4d:74:c7:\n                    18:29:b1:9f:08:98:0b:ff:13:5b:58:52:0b:85:f1:\n                    b0:fe:be:3f:ba:ea:5e:50:2f:ea:1d:85:1f:c2:87:\n                    2a:70:14:05:3d:70:6c:e3:c7:a7:81:6b:3e:11:67:\n                    bf:b4:9e:26:a4:57:df:16:0a:f3:83:7c:fb:64:e3:\n                    33:9f:08:55:25:de:1e:93:e6:13:0a:38:94:33:0c:\n                    40:87:f7:c7:69:1c:1d:5b:aa:0e:8e:e7:8f:ae:36:\n                    07:5b:1b:7d:c3:5c:13:20:c6:01:7b:9b:f2:f6:c7:\n                    ec:82:5d:33:75:cb:5b:b1:6b:be:96:36:f6:c4:1d:\n                    83:eb:88:dd:9a:ae:92:ea:ee:0f:20:8a:d6:c1:04:\n                    24:c8:4b:6a:89:0e:c5:46:4c:f9:79:2a:7a:60:7a:\n                    4a:72:9a:82:03:d2:75:c6:10:fb:d3:00:3b:6b:13:\n                    bc:f5:fe:83:94:40:18:a1:97:46:8c:5e:5b:ae:4a:\n                    c5:93:74:a5:9f:1e:d2:64:13:b0:d6:83:60:4e:69:\n                    f7:16:05:0b:e9:45:ec:b9:52:78:12:53:60:d7:88:\n                    f5:58:75:20:e4:ab:4a:e3:cb:b1:5d:82:57:4c:3f:\n                    47:44:70:90:06:a7:70:14:3c:6b:83:f9:28:07:12:\n                    81:f6:70:02:24:2d:52:70:01:96:1c:77:29:67:6c:\n                    5e:80:d8:51:fd:e5:43:5d:60:ad:2c:5f:95:aa:74:\n                    2d:f2:8e:43:30:e9:67:eb:c7:65:0a:4b:3b:b0:3f:\n                    ae:85:da:30:26:2a:b8:20:11:b3:92:9a:8a:d0:13:\n                    e6:d7:23\n                Exponent: 65537 (0x10001)\n        X509v3 extensions:\n            X509v3 Key Usage: critical\n                Certificate Sign, CRL Sign\n            X509v3 Basic Constraints: critical\n                CA:TRUE\n            X509v3 Subject Key Identifier: \n                84:70:71:2C:04:3B:D0:92:83:B5:FB:7C:7F:B0:61:0C:62:16:71:74\n            X509v3 Authority Key Identifier: \n                keyid:84:70:71:2C:04:3B:D0:92:83:B5:FB:7C:7F:B0:61:0C:62:16:71:74\n\n    Signature Algorithm: sha1WithRSAEncryption\n         6c:35:e0:07:db:3a:15:30:00:7f:38:fd:6d:b7:7a:85:84:87:\n         1b:72:78:33:ee:00:81:c0:51:33:6f:f3:a8:e8:3b:30:fd:ef:\n         19:c5:d2:95:83:b7:80:8f:1b:79:ff:ac:e6:f2:f5:f6:a0:71:\n         16:57:72:58:1a:75:e4:4c:3d:b3:4b:b5:3d:8c:d9:66:1a:5f:\n         7c:c0:2c:1f:2c:0a:3e:fb:84:20:ce:c8:7d:8e:9b:e6:fe:4b:\n         06:af:10:4f:db:97:3c:cd:04:df:3c:2f:c2:c6:29:c0:70:19:\n         b3:5a:9e:fe:0f:7d:83:95:83:a5:db:01:d8:c4:91:6f:ee:25:\n         6b:cd:8e:2e:b2:69:88:1f:e9:57:ef:4c:c4:18:cd:d2:42:4e:\n         c1:19:bd:8d:c9:4e:e7:b3:05:fa:6e:c5:32:0a:c3:f0:bd:ec:\n         d3:44:d4:80:08:26:2d:12:cb:1b:a4:9d:09:ca:0b:02:eb:5a:\n         b6:54:51:ac:90:63:77:76:6f:33:35:fe:87:db:d2:c0:bc:ea:\n         5b:c5:9b:e9:4c:c2:82:28:a7:4f:62:df:18:4f:1c:8b:93:7a:\n         f3:32:89:0a:3e:c1:bd:8a:45:29:f8:7f:18:4c:a1:77:e1:e2:\n         b4:eb:50:31:6b:77:d5:78:12:95:c9:02:d7:61:03:13:6e:be:\n         fe:dd:83:35:2b:4c:dc:45:81:6f:16:7f:29:b8:6f:bb:6d:f6:\n         15:6d:3b:d2:14:f9:94:24:86:df:4e:b7:9e:93:2e:94:25:e6:\n         b1:b5:c0:96:c9:a3:56:cf:95:15:7f:43:41:f0:3e:c2:ed:8d:\n         16:c1:7b:db:ff:38:48:08:b4:39:43:81:65:31:ba:78:d1:77:\n         e9:1a:f0:5a:18:05:db:db:91:ca:e8:f9:8c:2e:6e:a9:8c:ba:\n         69:96:01:2e:fa:6a:f5:de:bf:1c:53:ca:14:2a:91:0b:2a:f2:\n         fa:b9:07:eb:6d:9d:59:ae:08:6b:fa:61:95:75:9c:76:4b:22:\n         a7:0c:c4:66:e7:aa:9e:da:84:76:fc:8e:50:59:c2:55:b8:e1:\n         01:e5:54:85:7f:32:4f:63:e0:74:77:96:ae:6b:35:db:0a:0c:\n         da:27:3b:c7:c8:3b:ba:d4:41:3a:aa:5c:ed:71:0b:10:88:05:\n         9e:21:c5:99:c3:3a:e2:a2:de:f9:f5:c6:ce:9a:16:be:18:41:\n         24:14:ee:47:76:f2:db:b1:98:f2:0e:fd:18:ae:a7:f0:f1:55:\n         56:7a:9a:f2:84:50:77:f2:08:c7:f4:3f:f5:1b:03:97:49:41:\n         e3:a1:2b:c3:ee:f5:bc:bc:9d:2b:38:39:10:74:5b:18:92:2a:\n         fa:c0:4b:46:c0:ff:46:56\n-----BEGIN CERTIFICATE-----\nMIIFyDCCA7CgAwIBAgIBATANBgkqhkiG9w0BAQUFADB1MRIwEAYKCZImiZPyLGQB\nGRYCaW8xFTATBgoJkiaJk/IsZAEZFgVyZWFsbTEOMAwGA1UECgwFUmVhbG0xGzAZ\nBgNVBAsMElJlYWxtIFRlc3QgUm9vdCBDQTEbMBkGA1UEAwwSUmVhbG0gVGVzdCBS\nb290IENBMB4XDTE2MDkwNzA5NDIyM1oXDTI2MDkwNzA5NDIyM1owdTESMBAGCgmS\nJomT8ixkARkWAmlvMRUwEwYKCZImiZPyLGQBGRYFcmVhbG0xDjAMBgNVBAoMBVJl\nYWxtMRswGQYDVQQLDBJSZWFsbSBUZXN0IFJvb3QgQ0ExGzAZBgNVBAMMElJlYWxt\nIFRlc3QgUm9vdCBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANxD\nspKxvv/aQ/O41UtCngV/Tr8JLwIzGiRE/xJ+NZzNs2F4CrCDgILsolxm8H3U3/mc\nvrVO5mtgWeftD4VHLoNaVcEaMqnIuNRalpTvT/GqZFnIjIka5hr0lFzovlkPa8yd\nWOXkKSK6VJbdivYo1tbIyt+ywvceGVh1q6KrBOQf7f4E7PLx2mLSvZtLhLrQXtxj\nQAPMxogcFVyWQbBYPa8IvWQ0uDsAAyghN79cvBznLQilAq3ASbo0Vo5jZrpgjFyJ\nug92R5y8MWpdjk2pTXTHGCmxnwiYC/8TW1hSC4XxsP6+P7rqXlAv6h2FH8KHKnAU\nBT1wbOPHp4FrPhFnv7SeJqRX3xYK84N8+2TjM58IVSXeHpPmEwo4lDMMQIf3x2kc\nHVuqDo7nj642B1sbfcNcEyDGAXub8vbH7IJdM3XLW7FrvpY29sQdg+uI3Zqukuru\nDyCK1sEEJMhLaokOxUZM+XkqemB6SnKaggPSdcYQ+9MAO2sTvPX+g5RAGKGXRoxe\nW65KxZN0pZ8e0mQTsNaDYE5p9xYFC+lF7LlSeBJTYNeI9Vh1IOSrSuPLsV2CV0w/\nR0RwkAancBQ8a4P5KAcSgfZwAiQtUnABlhx3KWdsXoDYUf3lQ11grSxflap0LfKO\nQzDpZ+vHZQpLO7A/roXaMCYquCARs5KaitAT5tcjAgMBAAGjYzBhMA4GA1UdDwEB\n/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBSEcHEsBDvQkoO1+3x/\nsGEMYhZxdDAfBgNVHSMEGDAWgBSEcHEsBDvQkoO1+3x/sGEMYhZxdDANBgkqhkiG\n9w0BAQUFAAOCAgEAbDXgB9s6FTAAfzj9bbd6hYSHG3J4M+4AgcBRM2/zqOg7MP3v\nGcXSlYO3gI8bef+s5vL19qBxFldyWBp15Ew9s0u1PYzZZhpffMAsHywKPvuEIM7I\nfY6b5v5LBq8QT9uXPM0E3zwvwsYpwHAZs1qe/g99g5WDpdsB2MSRb+4la82OLrJp\niB/pV+9MxBjN0kJOwRm9jclO57MF+m7FMgrD8L3s00TUgAgmLRLLG6SdCcoLAuta\ntlRRrJBjd3ZvMzX+h9vSwLzqW8Wb6UzCgiinT2LfGE8ci5N68zKJCj7BvYpFKfh/\nGEyhd+HitOtQMWt31XgSlckC12EDE26+/t2DNStM3EWBbxZ/Kbhvu232FW070hT5\nlCSG3063npMulCXmsbXAlsmjVs+VFX9DQfA+wu2NFsF72/84SAi0OUOBZTG6eNF3\n6RrwWhgF29uRyuj5jC5uqYy6aZYBLvpq9d6/HFPKFCqRCyry+rkH622dWa4Ia/ph\nlXWcdksipwzEZueqntqEdvyOUFnCVbjhAeVUhX8yT2PgdHeWrms12woM2ic7x8g7\nutRBOqpc7XELEIgFniHFmcM64qLe+fXGzpoWvhhBJBTuR3by27GY8g79GK6n8PFV\nVnqa8oRQd/IIx/Q/9RsDl0lB46Erw+71vLydKzg5EHRbGJIq+sBLRsD/RlY=\n-----END CERTIFICATE-----\n"
  },
  {
    "path": "realm/realm-library/src/syncIntegrationTest/assets/untrusted_ca.pem",
    "content": "-----BEGIN CERTIFICATE-----\nMIIEsTCCA5mgAwIBAgIQBOHnpNxc8vNtwCtCuF0VnzANBgkqhkiG9w0BAQsFADBs\nMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3\nd3cuZGlnaWNlcnQuY29tMSswKQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5j\nZSBFViBSb290IENBMB4XDTEzMTAyMjEyMDAwMFoXDTI4MTAyMjEyMDAwMFowcDEL\nMAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3\nLmRpZ2ljZXJ0LmNvbTEvMC0GA1UEAxMmRGlnaUNlcnQgU0hBMiBIaWdoIEFzc3Vy\nYW5jZSBTZXJ2ZXIgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC2\n4C/CJAbIbQRf1+8KZAayfSImZRauQkCbztyfn3YHPsMwVYcZuU+UDlqUH1VWtMIC\nKq/QmO4LQNfE0DtyyBSe75CxEamu0si4QzrZCwvV1ZX1QK/IHe1NnF9Xt4ZQaJn1\nitrSxwUfqJfJ3KSxgoQtxq2lnMcZgqaFD15EWCo3j/018QsIJzJa9buLnqS9UdAn\n4t07QjOjBSjEuyjMmqwrIw14xnvmXnG3Sj4I+4G3FhahnSMSTeXXkgisdaScus0X\nsh5ENWV/UyU50RwKmmMbGZJ0aAo3wsJSSMs5WqK24V3B3aAguCGikyZvFEohQcft\nbZvySC/zA/WiaJJTL17jAgMBAAGjggFJMIIBRTASBgNVHRMBAf8ECDAGAQH/AgEA\nMA4GA1UdDwEB/wQEAwIBhjAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIw\nNAYIKwYBBQUHAQEEKDAmMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdpY2Vy\ndC5jb20wSwYDVR0fBEQwQjBAoD6gPIY6aHR0cDovL2NybDQuZGlnaWNlcnQuY29t\nL0RpZ2lDZXJ0SGlnaEFzc3VyYW5jZUVWUm9vdENBLmNybDA9BgNVHSAENjA0MDIG\nBFUdIAAwKjAoBggrBgEFBQcCARYcaHR0cHM6Ly93d3cuZGlnaWNlcnQuY29tL0NQ\nUzAdBgNVHQ4EFgQUUWj/kK8CB3U8zNllZGKiErhZcjswHwYDVR0jBBgwFoAUsT7D\naQP4v0cB1JgmGggC72NkK8MwDQYJKoZIhvcNAQELBQADggEBABiKlYkD5m3fXPwd\naOpKj4PWUS+Na0QWnqxj9dJubISZi6qBcYRb7TROsLd5kinMLYBq8I4g4Xmk/gNH\nE+r1hspZcX30BJZr01lYPf7TMSVcGDiEo+afgv2MW5gxTs14nhr9hctJqvIni5ly\n/D6q1UEL2tU2ob8cbkdJf17ZSHwD2f2LSaCYJkJA69aSEaRkCldUxPUd1gJea6zu\nxICaEnL6VpPX/78whQYwvwt/Tv9XBZ0k7YXDK/umdaisLRbvfXknsuvCnQsH6qqF\n0wGjIChBWUMo0oHjqvbsezt3tkBigAVBRQHvFwY+3sAzm2fTYS5yh+Rp/BIAV0Ae\ncPUeybQ=\n-----END CERTIFICATE-----\n"
  },
  {
    "path": "realm/realm-library/src/syncIntegrationTest/java/io/realm/BaseIntegrationTest.java",
    "content": "/*\n * Copyright 2017 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\npackage io.realm;\n\nimport androidx.test.rule.UiThreadTestRule;\nimport android.util.Log;\n\nimport org.junit.Rule;\nimport org.junit.rules.ExpectedException;\n\nimport java.io.File;\nimport java.io.IOException;\n\nimport io.realm.internal.OsRealmConfig;\nimport io.realm.internal.Util;\nimport io.realm.objectserver.utils.HttpUtils;\nimport io.realm.rule.RunInLooperThread;\n\n\n/**\n * Base class used by Integration Tests.\n * This class should not be used directly. Instead {@link StandardIntegrationTest} or {@link IsolatedIntegrationTests }\n * should be used instead.\n */\npublic abstract class BaseIntegrationTest {\n\n    @Rule\n    public RunInLooperThread looperThread = new RunInLooperThread();\n\n    @Rule\n    public final UiThreadTestRule uiThreadTestRule = new UiThreadTestRule();\n\n    @Rule\n    public final ExpectedException thrown = ExpectedException.none();\n\n    protected ConfigurationWrapper configurationFactory = new ConfigurationWrapper(looperThread);\n\n    /**\n     * Starts a new ROS instance that can be used for testing.\n     */\n    protected static void startSyncServer() {\n        SyncManager.Debug.skipOnlineChecking = true;\n        try {\n            HttpUtils.startSyncServer();\n        } catch (Exception e) {\n            throw new IllegalStateException(e);\n        }\n    }\n\n    /**\n     * Stops the ROS instance used for the test. The {@link #startSyncServer()} will stop the sync server if needed, so\n     * normally there is no need to call this.\n     */\n    protected static void stopSyncServer() {\n        try {\n            HttpUtils.stopSyncServer();\n        } catch (Exception e) {\n            Log.e(HttpUtils.TAG, \"Failed to stop Sync Server: \" + Util.getStackTrace(e));\n        }\n    }\n    \n    // Returns a valid SyncConfiguration usable by tests\n    // FIXME: WARNING: Do not use `SyncTestRealmConfigurationFactory`, but use this. Refactor later.\n    protected static class ConfigurationWrapper {\n\n        private final RunInLooperThread looperThread;\n\n        ConfigurationWrapper(RunInLooperThread looperThread) {\n            this.looperThread = looperThread;\n            try {\n                // The RunInLooperThread rule might not be fully created yet. Do it here.\n                // The `create()` call is idempotent, so should be safe.\n                looperThread.create();\n            } catch (IOException e) {\n                throw new IllegalStateException(e);\n            }\n        }\n\n        public SyncConfiguration.Builder createSyncConfigurationBuilder(SyncUser user, String url) {\n            return user.createConfiguration(url)\n                    .sessionStopPolicy(OsRealmConfig.SyncSessionStopPolicy.IMMEDIATELY)\n                    .modules(Realm.getDefaultModule())\n                    .directory(looperThread.getRoot());\n        }\n\n        public File getRoot() {\n            return looperThread.getRoot();\n        }\n    }\n}"
  },
  {
    "path": "realm/realm-library/src/syncIntegrationTest/java/io/realm/IsolatedIntegrationTests.java",
    "content": "package io.realm;\n\nimport org.junit.After;\nimport org.junit.AfterClass;\nimport org.junit.Before;\nimport org.junit.BeforeClass;\n\nimport java.io.IOException;\n\n\n/**\n * Base class for integration tests where each test is run on a separate ROS instance.\n * This adds quite a lot of overhead between each test, so only use this base class if absolutely needed.\n * Otherwise use {@link IsolatedIntegrationTests}.\n */\npublic class IsolatedIntegrationTests extends BaseIntegrationTest {\n\n    @Before\n    public void setupTest() throws IOException {\n        startSyncServer();\n        SyncTestUtils.prepareEnvironmentForTest();\n    }\n\n    @After\n    public void teardownTest() throws IOException {\n        if (!looperThread.isRuleUsed() || looperThread.isTestComplete()) {\n            // Non-looper tests can reset here\n            SyncTestUtils.restoreEnvironmentAfterTest();\n            stopSyncServer();\n        } else {\n            // Otherwise we need to wait for the test to complete\n            looperThread.runAfterTest(new Runnable() {\n                @Override\n                public void run() {\n                    try {\n                        SyncTestUtils.restoreEnvironmentAfterTest();\n                    } catch (IOException e) {\n                        throw new RuntimeException(e);\n                    }\n                    stopSyncServer();\n                }\n            });\n        }\n    }\n\n}\n"
  },
  {
    "path": "realm/realm-library/src/syncIntegrationTest/java/io/realm/StandardIntegrationTest.java",
    "content": "/*\n * Copyright 2017 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\npackage io.realm;\n\nimport org.junit.After;\nimport org.junit.AfterClass;\nimport org.junit.Before;\nimport org.junit.BeforeClass;\n\nimport java.io.IOException;\n\n\n/**\n * The standard base class for integration tests.\n * This class will keep a ROS instance running for all tests to minimize the overhead between each test.\n *\n * NOTE: All tests extending this class should use `@RunTestInLooperThread` tests.\n */\npublic abstract class StandardIntegrationTest extends BaseIntegrationTest {\n\n    @BeforeClass\n    public static void setupTestClass() throws Exception {\n        startSyncServer();\n    }\n\n    @AfterClass\n    public static void tearDownTestClass() throws Exception {\n        stopSyncServer();\n    }\n\n    @Before\n    public void setupTest() throws IOException {\n        SyncTestUtils.prepareEnvironmentForTest();\n    }\n\n    @After\n    public void teardownTest() throws IOException {\n        if (!looperThread.isRuleUsed() || looperThread.isTestComplete()) {\n            // Non-looper tests can reset here\n            SyncTestUtils.restoreEnvironmentAfterTest();\n        } else {\n            // Otherwise we need to wait for the test to complete\n            looperThread.runAfterTest(new Runnable() {\n                @Override\n                public void run() {\n                    try {\n                        SyncTestUtils.restoreEnvironmentAfterTest();\n                    } catch (IOException e) {\n                        throw new RuntimeException(e);\n                    }\n                }\n            });\n        }\n    }\n\n}\n"
  },
  {
    "path": "realm/realm-library/src/syncIntegrationTest/java/io/realm/objectserver/ProcessCommitTests.java",
    "content": "/*\n * Copyright 2016 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 */\npackage io.realm.objectserver;\n\nimport android.os.Looper;\nimport androidx.test.ext.junit.runners.AndroidJUnit4;\n\nimport org.junit.Rule;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\n\nimport java.io.IOException;\nimport java.util.UUID;\nimport java.util.concurrent.atomic.AtomicInteger;\n\nimport io.realm.Realm;\nimport io.realm.RealmChangeListener;\nimport io.realm.RealmResults;\nimport io.realm.StandardIntegrationTest;\nimport io.realm.SyncConfiguration;\nimport io.realm.SyncManager;\nimport io.realm.SyncUser;\nimport io.realm.TestHelper;\nimport io.realm.annotations.RealmModule;\nimport io.realm.objectserver.model.ProcessInfo;\nimport io.realm.objectserver.model.TestObject;\nimport io.realm.objectserver.utils.Constants;\nimport io.realm.objectserver.utils.RemoteIntegrationTestService;\nimport io.realm.objectserver.utils.UserFactory;\nimport io.realm.rule.RunTestInLooperThread;\nimport io.realm.rule.RunTestWithRemoteService;\nimport io.realm.rule.RunWithRemoteService;\nimport io.realm.services.RemoteTestService;\n\nimport static org.junit.Assert.assertEquals;\n\n\n@RunWith(AndroidJUnit4.class)\npublic class ProcessCommitTests extends StandardIntegrationTest {\n\n    @RealmModule(classes = { ProcessInfo.class, TestObject.class })\n    public static class ProcessCommitTestsModule { }\n\n    @Rule\n    public RunWithRemoteService remoteService = new RunWithRemoteService();\n\n    @Override\n    public void setupTest() throws IOException {\n        super.setupTest();\n        UserFactory.resetInstance();\n    }\n\n    public static class SimpleCommitRemoteService extends RemoteIntegrationTestService {\n        private static SyncUser user;\n        public static final Step stepA_openRealmAndCreateOneObject = new Step(RemoteTestService.BASE_SIMPLE_COMMIT, 1) {\n\n            @Override\n            protected void run() {\n                user = UserFactory.getInstance().loginWithDefaultUser(Constants.AUTH_URL);\n                String realmUrl = Constants.SYNC_SERVER_URL;\n\n                final SyncConfiguration syncConfig = user.createConfiguration(realmUrl)\n                        .modules(new ProcessCommitTestsModule())\n                        .directory(getService().getRoot())\n                        .build();\n                getService().setRealm(Realm.getInstance(syncConfig));\n                Realm realm = getService().getRealm();\n\n                realm.beginTransaction();\n                ProcessInfo processInfo = realm.createObject(ProcessInfo.class);\n                processInfo.setName(\"Background_Process1\");\n                processInfo.setPid(android.os.Process.myPid());\n                processInfo.setThreadId(Thread.currentThread().getId());\n                realm.commitTransaction();\n                Thread t = new Thread(() -> {\n                    try {\n                        SyncManager.getSession(syncConfig).uploadAllLocalChanges();\n                    } catch (InterruptedException e) {\n                        throw new IllegalStateException(\"Upload interrupted\", e);\n                    }\n                });\n                t.start();\n                try {\n                    t.join(TestHelper.SHORT_WAIT_SECS * 1000);\n                } catch (InterruptedException e) {\n                    throw new IllegalStateException(\"Waiting for background thread interrupted\", e);\n                }\n                realm.close();\n            }\n        };\n\n        public static final Step stepB_closeRealmAndLogOut = new Step(RemoteTestService.BASE_SIMPLE_COMMIT, 2) {\n            @Override\n            protected void run() {\n                getService().getRealm().close();\n                user.logOut();\n            }\n        };\n    }\n\n    // 1. Open a sync Realm and listen to changes.\n    // A. Open the same sync Realm and add one object.\n    // 2. Get the notification, check if the change in A is received.\n    @Test\n    @RunTestInLooperThread\n    @RunTestWithRemoteService(remoteService = SimpleCommitRemoteService.class, onLooperThread = true)\n    public void expectSimpleCommit() {\n        looperThread.runAfterTest(remoteService.afterRunnable);\n        remoteService.createHandler(Looper.myLooper());\n\n        final SyncUser user = UserFactory.getInstance().createDefaultUser(Constants.AUTH_URL);\n        String realmUrl = Constants.SYNC_SERVER_URL;\n        final SyncConfiguration syncConfig = user.createConfiguration(realmUrl)\n                .modules(new ProcessCommitTestsModule())\n                .directory(looperThread.getRoot())\n                .build();\n        final Realm realm = Realm.getInstance(syncConfig);\n        final RealmResults<ProcessInfo> all = realm.where(ProcessInfo.class).findAll();\n        looperThread.keepStrongReference(all);\n        all.addChangeListener(new RealmChangeListener<RealmResults<ProcessInfo>>() {\n            @Override\n            public void onChange(RealmResults<ProcessInfo> element) {\n                assertEquals(1, all.size());\n                assertEquals(\"Background_Process1\", all.get(0).getName());\n                realm.close();\n                user.logOut();\n\n                remoteService.triggerServiceStep(SimpleCommitRemoteService.stepB_closeRealmAndLogOut);\n\n                looperThread.testComplete();\n            }\n        });\n\n        remoteService.triggerServiceStep(SimpleCommitRemoteService.stepA_openRealmAndCreateOneObject);\n    }\n\n    public static class ALotCommitsRemoteService extends RemoteIntegrationTestService {\n        private static SyncUser user;\n        public static final Step stepA_openRealm = new Step(RemoteTestService.BASE_A_LOT_COMMITS, 1) {\n\n            @Override\n            protected void run() {\n                user = UserFactory.getInstance().loginWithDefaultUser(Constants.AUTH_URL);\n                String realmUrl = Constants.SYNC_SERVER_URL;\n\n                final SyncConfiguration syncConfig = user.createConfiguration(realmUrl)\n                        .modules(new ProcessCommitTestsModule())\n                        .directory(getService().getRoot())\n                        .name(UUID.randomUUID().toString() + \".realm\")\n                        .build();\n                getService().setRealm(Realm.getInstance(syncConfig));\n            }\n        };\n\n        public static final Step stepB_createObjects = new Step(RemoteTestService.BASE_A_LOT_COMMITS, 2) {\n            @Override\n            protected void run() {\n                Realm realm = getService().getRealm();\n                realm.beginTransaction();\n                for (int i = 0; i < 100; i++) {\n                    Number max = realm.where(TestObject.class).findAll().max(\"intProp\");\n                    int pk = max == null ? 0 : max.intValue() + 1;\n                    TestObject testObject = realm.createObject(TestObject.class, pk);\n                    testObject.setStringProp(\"Str\" + pk);\n                }\n                realm.commitTransaction();\n            }\n        };\n\n        public static final Step stepC_closeRealm = new Step(RemoteTestService.BASE_A_LOT_COMMITS, 3) {\n            @Override\n            protected void run() {\n                getService().getRealm().close();\n                user.logOut();\n            }\n        };\n    }\n\n    // 1. Open a sync Realm and listen to changes.\n    // A. Open the same sync Realm.\n    // B. Create 100 objects.\n    // 2. Check if the 100 objects are received.\n    // #. Repeat B/2 10 times.\n    @Test\n    @RunTestWithRemoteService(remoteService = ALotCommitsRemoteService.class, onLooperThread = true)\n    @RunTestInLooperThread\n    public void expectALot() throws Throwable {\n        looperThread.runAfterTest(remoteService.afterRunnable);\n        remoteService.createHandler(Looper.myLooper());\n\n        final SyncUser user = UserFactory.getInstance().createDefaultUser(Constants.AUTH_URL);\n        String realmUrl = Constants.SYNC_SERVER_URL;\n        final SyncConfiguration syncConfig = user.createConfiguration(realmUrl)\n                .modules(new ProcessCommitTestsModule())\n                .directory(looperThread.getRoot())\n                .build();\n        final Realm realm = Realm.getInstance(syncConfig);\n        final RealmResults<TestObject> all = realm.where(TestObject.class).sort(\"intProp\").findAll();\n        looperThread.keepStrongReference(all);\n        final AtomicInteger listenerCalledCounter = new AtomicInteger(0);\n        all.addChangeListener(new RealmChangeListener<RealmResults<TestObject>>() {\n            @Override\n            public void onChange(RealmResults<TestObject> element) {\n                int counter = listenerCalledCounter.incrementAndGet();\n                int size = all.size();\n                if (size == 0) {\n                    listenerCalledCounter.decrementAndGet();\n                    return;\n                }\n                assertEquals(0, size % 100); // Added 100 objects every time.\n                assertEquals(counter * 100 - 1, all.last().getIntProp());\n                assertEquals(\"Str\" + (counter * 100 - 1), all.last().getStringProp());\n                if (counter == 10) {\n                    remoteService.triggerServiceStep(ALotCommitsRemoteService.stepC_closeRealm);\n                    realm.close();\n                    user.logOut();\n                    looperThread.testComplete();\n                } else {\n                    remoteService.triggerServiceStep(ALotCommitsRemoteService.stepB_createObjects);\n                }\n            }\n        });\n\n        remoteService.triggerServiceStep(ALotCommitsRemoteService.stepA_openRealm);\n        remoteService.triggerServiceStep(ALotCommitsRemoteService.stepB_createObjects);\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/syncIntegrationTest/java/io/realm/objectserver/model/PartialSyncModule.java",
    "content": "/*\n * Copyright 2017 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\npackage io.realm.objectserver.model;\n\nimport io.realm.annotations.RealmModule;\nimport io.realm.entities.AllJavaTypes;\nimport io.realm.entities.BacklinksSource;\nimport io.realm.entities.BacklinksTarget;\n\n@RealmModule(classes = {PartialSyncObjectA.class, PartialSyncObjectB.class, AllJavaTypes.class, BacklinksSource.class, BacklinksTarget.class})\npublic class PartialSyncModule {\n}\n"
  },
  {
    "path": "realm/realm-library/src/syncIntegrationTest/java/io/realm/objectserver/model/PartialSyncObjectA.java",
    "content": "/*\n * Copyright 2017 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\npackage io.realm.objectserver.model;\n\nimport io.realm.RealmObject;\n\npublic class PartialSyncObjectA extends RealmObject {\n    private int number;\n    private String string;\n\n    public int getNumber() {\n        return number;\n    }\n\n    public void setNumber(int number) {\n        this.number = number;\n    }\n\n    public String getString() {\n        return string;\n    }\n\n    public void setString(String string) {\n        this.string = string;\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/syncIntegrationTest/java/io/realm/objectserver/model/PartialSyncObjectB.java",
    "content": "/*\n * Copyright 2017 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\npackage io.realm.objectserver.model;\n\nimport io.realm.RealmObject;\n\npublic class PartialSyncObjectB extends RealmObject {\n    private int number;\n    private String firstString;\n    private String secondString;\n\n    public int getNumber() {\n        return number;\n    }\n\n    public void setNumber(int number) {\n        this.number = number;\n    }\n\n    public String getFirstString() {\n        return firstString;\n    }\n\n    public void setFirstString(String firstString) {\n        this.firstString = firstString;\n    }\n\n    public String getSecondString() {\n        return secondString;\n    }\n\n    public void setSecondString(String secondString) {\n        this.secondString = secondString;\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/syncIntegrationTest/java/io/realm/objectserver/model/ProcessInfo.java",
    "content": "/*\n * Copyright 2016 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\npackage io.realm.objectserver.model;\n\nimport io.realm.RealmObject;\n\npublic class ProcessInfo extends RealmObject {\n    private String name;\n    private int pid;\n    private long threadId;\n\n    public int getPid() {\n        return pid;\n    }\n\n    public void setPid(int pid) {\n        this.pid = pid;\n    }\n\n    public String getName() {\n        return name;\n    }\n\n    public void setName(String name) {\n        this.name = name;\n    }\n\n    public long getThreadId() {\n        return threadId;\n    }\n\n    public void setThreadId(long threadId) {\n        this.threadId = threadId;\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/syncIntegrationTest/java/io/realm/objectserver/model/TestObject.java",
    "content": "/*\n * Copyright 2016 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\npackage io.realm.objectserver.model;\n\nimport io.realm.RealmObject;\nimport io.realm.annotations.PrimaryKey;\n\npublic class TestObject extends RealmObject {\n    @PrimaryKey\n    private int intProp;\n\n    private String stringProp;\n\n    public int getIntProp() {\n        return intProp;\n    }\n\n    public void setIntProp(int intProp) {\n        this.intProp = intProp;\n    }\n\n    public String getStringProp() {\n        return stringProp;\n    }\n\n    public void setStringProp(String stringProp) {\n        this.stringProp = stringProp;\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/syncIntegrationTest/java/io/realm/objectserver/package-info.java",
    "content": "/*\n * Copyright 2017 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@javax.annotation.ParametersAreNonnullByDefault\npackage io.realm.objectserver;\n"
  },
  {
    "path": "realm/realm-library/src/syncIntegrationTest/java/io/realm/objectserver/utils/HttpUtils.java",
    "content": "/*\n * Copyright 2016 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\npackage io.realm.objectserver.utils;\n\nimport android.os.SystemClock;\n\nimport java.io.IOException;\nimport java.util.concurrent.TimeUnit;\n\nimport okhttp3.OkHttpClient;\nimport okhttp3.Request;\nimport okhttp3.Response;\n\n/**\n * Start and Stop the node server responsible of creating a\n * temp directory & start a sync server on it for each unit test.\n *\n * WARNING: This class is called before Realm is initialized, so RealmLog cannot be used.\n */\npublic class HttpUtils {\n    // TODO If the timeouts are longer than the test timeout you risk getting\n    // \"Realm could not be deleted errors\".\n    // FIXME re-adjust timeout after https://github.com/realm/realm-object-server-private/issues/697 is fixed\n    private final static OkHttpClient client = new OkHttpClient.Builder()\n            .connectTimeout(60, TimeUnit.SECONDS)\n            .readTimeout(60, TimeUnit.SECONDS)// since ROS startup timeout is 30s\n            .build();\n\n    // adb reverse tcp:8888 tcp:8888\n    // will forward this query to the host, running the integration test server on 8888\n    private static final String START_SERVER = \"http://127.0.0.1:8888/start\";\n    private static final String STOP_SERVER = \"http://127.0.0.1:8888/stop\";\n    public static final String TAG = \"IntegrationTestServer\";\n\n    /**\n     * Start the sync server. If the server has been started before, stop it first.\n     */\n    public static void startSyncServer() throws Exception {\n        Request request = new Request.Builder()\n                .url(START_SERVER)\n                .build();\n\n        Response response = client.newCall(request).execute();\n        if (!response.isSuccessful()) throw new IOException(\"Unexpected code \" + response);\n    }\n\n    /**\n     * Stop the sync server if it is alive. {@link #startSyncServer()} will implicitly stop the server if needed, so\n     * normally there is no need to call this.\n     */\n    public static void stopSyncServer() throws Exception {\n        Request request = new Request.Builder()\n                .url(STOP_SERVER)\n                .build();\n\n        Response response = client.newCall(request).execute();\n        if (!response.isSuccessful()) throw new IOException(\"Unexpected code \" + response);\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/syncIntegrationTest/java/io/realm/objectserver/utils/RemoteIntegrationTestService.java",
    "content": "/*\n * Copyright 2017 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\npackage io.realm.objectserver.utils;\n\nimport io.realm.SyncManager;\nimport io.realm.services.RemoteTestService;\n\n// Remote test service base class which contains some initialization for sync.\npublic class RemoteIntegrationTestService extends RemoteTestService {\n    public RemoteIntegrationTestService() {\n        super();\n        SyncManager.Debug.skipOnlineChecking = true;\n        SyncManager.Debug.separatedDirForSyncManager = true;\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/syncIntegrationTest/kotlin/io/realm/EncryptedSynchronizedRealmTests.kt",
    "content": "/*\n * Copyright 2020 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 */\npackage io.realm\n\nimport androidx.test.platform.app.InstrumentationRegistry\nimport io.realm.entities.SyncStringOnly\nimport io.realm.exceptions.RealmFileException\nimport io.realm.kotlin.syncSession\nimport io.realm.mongodb.App\nimport io.realm.mongodb.Credentials\nimport io.realm.mongodb.close\nimport io.realm.mongodb.registerUserAndLogin\nimport io.realm.mongodb.sync.SyncConfiguration\nimport io.realm.mongodb.sync.testSchema\nimport org.bson.BsonString\nimport org.bson.types.ObjectId\nimport org.junit.After\nimport org.junit.Assert.*\nimport org.junit.Before\nimport org.junit.Ignore\nimport org.junit.Test\nimport java.util.*\nimport kotlin.test.assertFailsWith\n\nprivate val SECRET_PASSWORD = \"123456\"\n\nclass EncryptedSynchronizedRealmTests {\n\n    private lateinit var app: App\n\n    private val configurationFactory: TestSyncConfigurationFactory = TestSyncConfigurationFactory()\n\n    @Before\n    fun setup() {\n        Realm.init(InstrumentationRegistry.getInstrumentation().targetContext)\n        app = TestApp()\n    }\n\n    @After\n    fun teardown() {\n        if (this::app.isInitialized) {\n            app.close()\n        }\n    }\n\n    // Make sure the encryption is local, i.e after deleting a synced Realm\n    // re-open it again with no (or different) key, should be possible.\n    @Test\n    fun setEncryptionKey_canReOpenRealmWithoutKey() {\n\n        // STEP 1: open a synced Realm using a local encryption key\n        val user = app.registerUserAndLogin(TestHelper.getRandomEmail(), SECRET_PASSWORD)\n        val randomKey = TestHelper.getRandomKey()\n        val configWithEncryption: SyncConfiguration = configurationFactory.createSyncConfigurationBuilder(user, BsonString(UUID.randomUUID().toString()))\n                .testSchema(SyncStringOnly::class.java)\n                .waitForInitialRemoteData()\n                .errorHandler { _, error -> fail(error.errorMessage) }\n                .encryptionKey(randomKey)\n                .build()\n\n        Realm.getInstance(configWithEncryption).use { realm ->\n            assertTrue(realm.isEmpty)\n            realm.executeTransaction {\n                realm.createObject(SyncStringOnly::class.java, ObjectId()).chars = \"Hi Alice\"\n            }\n\n            // STEP 2:  make sure the changes gets to the server\n            realm.syncSession.uploadAllLocalChanges()\n        }\n        user.logOut()\n\n        // STEP 3: try to open again the same sync Realm but different local name without the encryption key should not\n        // fail\n        val user2 = app.registerUserAndLogin(TestHelper.getRandomEmail(), SECRET_PASSWORD)\n        val configWithoutEncryption: SyncConfiguration = configurationFactory.createSyncConfigurationBuilder(user2, configWithEncryption.partitionValue)\n                // Using different user with same partition value to trigger a different path instead of\n                // .name(\"newName\")\n                .testSchema(SyncStringOnly::class.java)\n                .waitForInitialRemoteData()\n                .errorHandler { _, error -> fail(error.errorMessage) }\n                .build()\n\n        Realm.getInstance(configWithoutEncryption).use { realm ->\n            val all = realm.where(SyncStringOnly::class.java).findAll()\n            assertEquals(1, all.size.toLong())\n            assertEquals(\"Hi Alice\", all[0]!!.chars)\n        }\n        user.logOut()\n    }\n\n    // FIXME: ignore until https://github.com/realm/realm-java/issues/7028 is fixed\n    // If an encrypted synced Realm is re-opened with the wrong key, throw an exception.\n    @Test\n    @Ignore(\"Crashes at random - https://github.com/realm/realm-java/issues/7028\")\n    fun setEncryptionKey_shouldCrashIfKeyNotProvided() {\n        // STEP 1: open a synced Realm using a local encryption key\n        var user = app.registerUserAndLogin(TestHelper.getRandomEmail(), SECRET_PASSWORD)\n        val randomKey = TestHelper.getRandomKey()\n        val configWithEncryption: SyncConfiguration = configurationFactory.createSyncConfigurationBuilder(user, BsonString(UUID.randomUUID().toString()))\n                .testSchema(SyncStringOnly::class.java)\n                .waitForInitialRemoteData()\n                .errorHandler { session, error -> fail(error.getErrorMessage()) }\n                .encryptionKey(randomKey)\n                .build()\n\n        Realm.getInstance(configWithEncryption).use { realm ->\n            assertTrue(realm.isEmpty)\n            realm.executeTransaction {\n                realm.createObject(SyncStringOnly::class.java, ObjectId()).chars = \"Hi Alice\"\n            }\n            // STEP 2: Close the Realm and log the user out to forget about it.\n        }\n        user.logOut()\n\n        // STEP 3: try to open again the Realm without the encryption key should fail\n        user = app.login(Credentials.emailPassword(user.profile.email, SECRET_PASSWORD))\n        val configWithoutEncryption: SyncConfiguration = configurationFactory.createSyncConfigurationBuilder(user, configWithEncryption.partitionValue)\n                .testSchema(SyncStringOnly::class.java)\n                .waitForInitialRemoteData()\n                .errorHandler { session, error -> fail(error.getErrorMessage()) }\n                .build()\n\n        assertFailsWith<RealmFileException> {\n            Realm.getInstance(configWithoutEncryption).close()\n        }\n    }\n\n    // If client B encrypts its synced Realm, client A should be able to access that Realm with a different encryption key.\n    @Test\n    fun setEncryptionKey_differentClientsWithDifferentKeys() {\n        // STEP 1: prepare a synced Realm for client A\n        val user = app.registerUserAndLogin(TestHelper.getRandomEmail(), SECRET_PASSWORD)\n        val randomKey = TestHelper.getRandomKey()\n        val configWithEncryption: SyncConfiguration = configurationFactory.createSyncConfigurationBuilder(user, BsonString(UUID.randomUUID().toString()))\n                .testSchema(SyncStringOnly::class.java)\n                .waitForInitialRemoteData()\n                .errorHandler { session, error -> fail(error.getErrorMessage()) }\n                .encryptionKey(randomKey)\n                .build()\n\n        Realm.getInstance(configWithEncryption).use { realm ->\n            assertTrue(realm.isEmpty)\n            realm.executeTransaction {\n                realm.createObject(SyncStringOnly::class.java, ObjectId()).chars = \"Hi Alice\"\n            }\n            // STEP 2: make sure the changes gets to the server\n            realm.syncSession.uploadAllLocalChanges()\n        }\n\n        // STEP 3: prepare a synced Realm for client B\n        val user2 = app.registerUserAndLogin(TestHelper.getRandomEmail(), SECRET_PASSWORD)\n        val key2 = TestHelper.getRandomKey()\n        val configWithEncryption2: SyncConfiguration = configurationFactory.createSyncConfigurationBuilder(user2, configWithEncryption.partitionValue)\n                .testSchema(SyncStringOnly::class.java)\n                .waitForInitialRemoteData()\n                .errorHandler { session, error -> fail(error.getErrorMessage()) }\n                .encryptionKey(key2)\n                .build()\n\n        Realm.getInstance(configWithEncryption2).use { realm ->\n            val all = realm.where(SyncStringOnly::class.java).findAll()\n            assertEquals(1, all.size.toLong())\n            assertEquals(\"Hi Alice\", all[0]!!.chars)\n            realm.executeTransaction {\n                realm.createObject(SyncStringOnly::class.java, ObjectId()).chars = \"Hi Bob\"\n            }\n            realm.syncSession.uploadAllLocalChanges()\n        }\n\n        // STEP 4: client A can see changes from client B (although they're using different encryption keys)\n        Realm.getInstance(configWithEncryption).use { realm ->\n            realm.syncSession.downloadAllServerChanges() // force download latest commits from remote realm\n            realm.refresh() // Not calling refresh will still point to the previous version of the Realm without the latest admin commit  \"Hi Bob\"\n            assertEquals(2, realm.where(SyncStringOnly::class.java).count())\n            val allSorted = realm.where(SyncStringOnly::class.java).sort(SyncStringOnly.FIELD_CHARS).findAll()\n            val allSortedAdmin = realm.where(SyncStringOnly::class.java).sort(SyncStringOnly.FIELD_CHARS).findAll()\n            assertEquals(\"Hi Alice\", allSorted[0]!!.chars)\n            assertEquals(\"Hi Bob\", allSorted[1]!!.chars)\n            assertEquals(\"Hi Alice\", allSortedAdmin[0]!!.chars)\n            assertEquals(\"Hi Bob\", allSortedAdmin[1]!!.chars)\n        }\n\n        user.logOut()\n        user2.logOut()\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/syncIntegrationTest/kotlin/io/realm/SyncSessionTests.kt",
    "content": "package io.realm\n\nimport android.os.Handler\nimport android.os.HandlerThread\nimport android.os.SystemClock\nimport androidx.test.ext.junit.runners.AndroidJUnit4\nimport androidx.test.platform.app.InstrumentationRegistry\nimport io.realm.admin.ServerAdmin\nimport io.realm.entities.*\nimport io.realm.exceptions.DownloadingRealmInterruptedException\nimport io.realm.internal.OsRealmConfig\nimport io.realm.kotlin.syncSession\nimport io.realm.kotlin.where\nimport io.realm.log.LogLevel\nimport io.realm.log.RealmLog\nimport io.realm.mongodb.*\nimport io.realm.mongodb.sync.*\nimport io.realm.rule.BlockingLooperThread\nimport io.realm.util.ResourceContainer\nimport io.realm.util.assertFailsWithMessage\nimport kotlinx.coroutines.runBlocking\nimport org.bson.*\nimport org.bson.types.ObjectId\nimport org.hamcrest.CoreMatchers\nimport org.junit.*\nimport org.junit.Assert.*\nimport org.junit.runner.RunWith\nimport java.io.Closeable\nimport java.lang.IllegalStateException\nimport java.lang.Thread\nimport java.util.*\nimport java.util.concurrent.CountDownLatch\nimport java.util.concurrent.TimeUnit\nimport java.util.concurrent.atomic.AtomicInteger\nimport java.util.concurrent.atomic.AtomicReference\nimport kotlin.test.assertEquals\nimport kotlin.test.assertFailsWith\n\ntypealias SessionCallback = (SyncSession) -> Unit\n\nprivate val SECRET_PASSWORD = \"123456\"\n\nfun validateManualResetIsAvailable(\n    session: SyncSession,\n    error: ClientResetRequiredError\n) {\n    val filePathFromError = error.originalFile.absolutePath\n    val filePathFromConfig = session.configuration.path\n    assertEquals(filePathFromError, filePathFromConfig)\n    assertFalse(error.backupFile.exists())\n    assertTrue(error.originalFile.exists())\n\n    assertTrue(\n        error.toString(),\n        error.toString().startsWith(\"CLIENT_RESET(realm::app::CustomError:7):\"),\n    )\n}\n\n@RunWith(AndroidJUnit4::class)\nclass SyncSessionTests {\n\n    @get:Rule\n    private val looperThread = BlockingLooperThread()\n\n    private lateinit var app: TestApp\n    private lateinit var user: User\n    private lateinit var syncConfiguration: SyncConfiguration\n    private lateinit var admin: ServerAdmin\n\n    private val configFactory: TestSyncConfigurationFactory = TestSyncConfigurationFactory()\n\n    private fun getSession(callback: SessionCallback) {\n        // Work-around for a race condition happening when shutting down a Looper test and\n        // Resetting the SyncManager\n        // The problem is the `@After` block which runs as soon as the test method has completed.\n        // For integration tests this will attempt to reset the SyncManager which will fail\n        // if Realms are still open as they hold a reference to a session object.\n        // By moving this into a Looper callback we ensure that a looper test can shutdown as\n        // intended.\n        // Generally it seems that using calling `RunInLooperThread.testComplete()` in a synchronous\n        looperThread.postRunnable(Runnable {\n            val user = app.registerUserAndLogin(TestHelper.getRandomEmail(), SECRET_PASSWORD)\n            val syncConfiguration = configFactory\n                    .createSyncConfigurationBuilder(user)\n                    .testSchema(SyncStringOnly::class.java)\n                    .build()\n            val realm = Realm.getInstance(syncConfiguration)\n            looperThread.closeAfterTest(realm)\n            callback(realm.syncSession)\n        })\n    }\n\n    private fun getActiveSession(callback: SessionCallback) {\n        getSession { session ->\n            if (session.isConnected) {\n                callback(session)\n            } else {\n                session.addConnectionChangeListener(object : ConnectionListener {\n                    override fun onChange(oldState: ConnectionState, newState: ConnectionState) {\n                        if (newState == ConnectionState.CONNECTED) {\n                            session.removeConnectionChangeListener(this)\n                            callback(session)\n                        }\n                    }\n                })\n            }\n        }\n    }\n\n    @Before\n    fun setup() {\n        Realm.init(InstrumentationRegistry.getInstrumentation().targetContext)\n        RealmLog.setLevel(LogLevel.ALL)\n\n        app = TestApp()\n        admin = ServerAdmin(app)\n        user = app.registerUserAndLogin(TestHelper.getRandomEmail(), SECRET_PASSWORD)\n        syncConfiguration = configFactory\n                // TODO We generate new partition value for each test to avoid overlaps in data. We\n                //  could make test booting with a cleaner state by somehow flushing data between\n                //  tests.\n                .createSyncConfigurationBuilder(user, BsonString(UUID.randomUUID().toString()))\n                .modules(DefaultSyncSchema())\n                .build()\n    }\n\n    @After\n    fun teardown() {\n        if (this::app.isInitialized) {\n            app.close()\n        }\n        RealmLog.setLevel(LogLevel.WARN)\n    }\n\n    // Check that a Seamless Client Reset is correctly reported.\n    // Placed here instead of in SessionTests.kt because it would fails to run if executed with the\n    // whole test suite.\n    @Test\n    fun clientReset_discardUnsyncedChangesStrategy_discards() = looperThread.runBlocking {\n        val latch = CountDownLatch(2)\n        val partitionKey = UUID.randomUUID().toString()\n        val config = configFactory.createSyncConfigurationBuilder(user, partitionKey)\n                .syncClientResetStrategy(object : DiscardUnsyncedChangesStrategy {\n                    override fun onBeforeReset(realm: Realm) {\n                        assertTrue(realm.isFrozen)\n                        Assert.assertEquals(1, realm.where<DummySyncObject>().count())\n                        latch.countDown()\n                    }\n\n                    override fun onAfterReset(before: Realm, after: Realm) {\n                        assertTrue(before.isFrozen)\n                        assertFalse(after.isFrozen)\n\n                        Assert.assertEquals(1, before.where<DummySyncObject>().count())\n                        Assert.assertEquals(0, after.where<DummySyncObject>().count())\n\n                        //Validate we can move data to the reset Realm.\n                        after.executeTransaction{\n                            it.insert(before.where<DummySyncObject>().findFirst()!!)\n                        }\n                        Assert.assertEquals(1, after.where<DummySyncObject>().count())\n                        latch.countDown()\n                    }\n\n                    @Deprecated(\"Deprecated in favor of onManualResetFallback\")\n                    override fun onError(session: SyncSession, error: ClientResetRequiredError) {\n                        fail(\"This test case was not supposed to trigger DiscardUnsyncedChangesStrategy::onError()\")\n                    }\n\n                    override fun onManualResetFallback(\n                        session: SyncSession,\n                        error: ClientResetRequiredError\n                    ) {\n                        fail(\"This test case was not supposed to trigger DiscardUnsyncedChangesStrategy::onManualResetFallback()\")\n                    }\n\n                })\n                .modules(ObjectSyncSchema())\n                .build()\n\n        val realm = Realm.getInstance(config)\n        looperThread.closeAfterTest(realm)\n        admin.triggerClientReset(realm.syncSession) {\n            realm.executeTransaction {\n                it.insert(DummySyncObject())\n            }\n\n            Assert.assertEquals(1, realm.where<DummySyncObject>().count())\n        }\n\n        looperThread.testComplete(latch)\n    }\n\n    @Test\n    fun clientReset_discardUnsyncedChangesStrategy_fallback_userException_onBeforeReset() = looperThread.runBlocking {\n        val latch = CountDownLatch(2)\n\n        val partitionKey = UUID.randomUUID().toString()\n        val config = configFactory.createSyncConfigurationBuilder(user, partitionKey)\n            .syncClientResetStrategy(object : DiscardUnsyncedChangesStrategy {\n                override fun onBeforeReset(realm: Realm) {\n                    throw RuntimeException()\n                }\n\n                override fun onAfterReset(before: Realm, after: Realm) {\n                    fail(\"This test case was not supposed to trigger DiscardUnsyncedChangesStrategy::onAfterReset()\")\n                }\n\n                @Deprecated(\"Deprecated in favor of onManualResetFallback\")\n                override fun onError(session: SyncSession, error: ClientResetRequiredError) {\n                    latch.countDown()\n                }\n\n                override fun onManualResetFallback(\n                    session: SyncSession,\n                    error: ClientResetRequiredError\n                ) {\n                    validateManualResetIsAvailable(session, error)\n\n                    latch.countDown()\n                }\n\n            })\n            .modules(ObjectSyncSchema())\n            .build()\n\n        val realm = Realm.getInstance(config)\n        looperThread.closeAfterTest(realm)\n\n        admin.triggerClientReset(realm.syncSession) {\n            realm.executeTransaction {\n                it.insert(DummySyncObject())\n            }\n\n            Assert.assertEquals(1, realm.where<DummySyncObject>().count())\n        }\n\n        looperThread.testComplete(latch)\n    }\n\n    @Test\n    fun clientReset_discardUnsyncedChangesStrategy_fallback_userException_onAfterReset() = looperThread.runBlocking {\n        val latch = CountDownLatch(2)\n\n        val partitionKey = UUID.randomUUID().toString()\n        val config = configFactory.createSyncConfigurationBuilder(user, partitionKey)\n            .syncClientResetStrategy(object : DiscardUnsyncedChangesStrategy {\n                override fun onBeforeReset(realm: Realm) {\n                    assertNotNull(realm)\n                }\n\n                override fun onAfterReset(before: Realm, after: Realm) {\n                    throw RuntimeException()\n                }\n\n                @Deprecated(\"Deprecated in favor of onManualResetFallback\")\n                override fun onError(session: SyncSession, error: ClientResetRequiredError) {\n                    latch.countDown()\n                }\n\n                override fun onManualResetFallback(\n                    session: SyncSession,\n                    error: ClientResetRequiredError\n                ) {\n                    validateManualResetIsAvailable(session, error)\n\n                    latch.countDown()\n                }\n\n            })\n            .modules(ObjectSyncSchema())\n            .build()\n\n        val realm = Realm.getInstance(config)\n        looperThread.closeAfterTest(realm)\n\n        admin.triggerClientReset(realm.syncSession) {\n            realm.executeTransaction {\n                it.insert(DummySyncObject())\n            }\n\n            Assert.assertEquals(1, realm.where<DummySyncObject>().count())\n        }\n\n        looperThread.testComplete(latch)\n    }\n\n    @Test\n    fun clientReset_recoverUnsyncedChangesStrategy_recover() = looperThread.runBlocking {\n        val latch = CountDownLatch(2)\n\n        val partitionKey = UUID.randomUUID().toString()\n        val config = configFactory.createSyncConfigurationBuilder(user, partitionKey)\n            .syncClientResetStrategy(object: RecoverUnsyncedChangesStrategy {\n                override fun onBeforeReset(realm: Realm) {\n                    latch.countDown()\n                }\n\n                override fun onAfterReset(before: Realm, after: Realm) {\n                    latch.countDown()\n                }\n\n                override fun onManualResetFallback(session: SyncSession, error: ClientResetRequiredError) {\n                    fail(\"This test case was not supposed to trigger RecoverUnsyncedChangesStrategy::onManualResetFallback()\")\n                }\n            })\n            .modules(ObjectSyncSchema())\n            .build()\n\n        val realm = Realm.getInstance(config)\n        looperThread.closeAfterTest(realm)\n        admin.triggerClientReset(realm.syncSession) {\n            realm.executeTransaction {\n                it.insert(DummySyncObject())\n            }\n\n            Assert.assertEquals(1, realm.where<DummySyncObject>().count())\n        }\n\n        looperThread.testComplete(latch)\n    }\n\n    @Test\n    fun clientReset_recoverUnsyncedChangesStrategy_fallback_userException_onBeforeReset() = looperThread.runBlocking {\n        val partitionKey = UUID.randomUUID().toString()\n        val config = configFactory.createSyncConfigurationBuilder(user, partitionKey)\n            .syncClientResetStrategy(object : RecoverUnsyncedChangesStrategy {\n                override fun onBeforeReset(realm: Realm) {\n                    throw RuntimeException()\n                }\n\n                override fun onAfterReset(before: Realm, after: Realm) {\n                    fail(\"This test case was not supposed to trigger RecoverUnsyncedChangesStrategy::onAfterReset()\")\n                }\n\n                override fun onManualResetFallback(\n                    session: SyncSession,\n                    error: ClientResetRequiredError\n                ) {\n                    validateManualResetIsAvailable(session, error)\n\n                    looperThread.testComplete()\n                }\n            })\n            .modules(ObjectSyncSchema())\n            .build()\n\n        val realm = Realm.getInstance(config)\n        looperThread.closeAfterTest(realm)\n\n        admin.triggerClientReset(realm.syncSession) {\n            realm.executeTransaction {\n                it.insert(DummySyncObject())\n            }\n\n            Assert.assertEquals(1, realm.where<DummySyncObject>().count())\n        }\n    }\n\n    @Test\n    fun clientReset_recoverUnsyncedChangesStrategy_fallback_userException_onAfterReset() = looperThread.runBlocking {\n        val partitionKey = UUID.randomUUID().toString()\n        val config = configFactory.createSyncConfigurationBuilder(user, partitionKey)\n            .syncClientResetStrategy(object : RecoverUnsyncedChangesStrategy {\n                override fun onBeforeReset(realm: Realm) {\n                    assertNotNull(realm)\n                }\n\n                override fun onAfterReset(before: Realm, after: Realm) {\n                    throw RuntimeException()\n                }\n\n                override fun onManualResetFallback(\n                    session: SyncSession,\n                    error: ClientResetRequiredError\n                ) {\n                    validateManualResetIsAvailable(session, error)\n\n                    looperThread.testComplete()\n                }\n            })\n            .modules(ObjectSyncSchema())\n            .build()\n\n        val realm = Realm.getInstance(config)\n        looperThread.closeAfterTest(realm)\n\n        admin.triggerClientReset(realm.syncSession) {\n            realm.executeTransaction {\n                it.insert(DummySyncObject())\n            }\n\n            Assert.assertEquals(1, realm.where<DummySyncObject>().count())\n        }\n    }\n\n    @Test\n    fun clientReset_recoverOrDiscardUnsyncedChangesStrategy_recover() = looperThread.runBlocking {\n        val latch = CountDownLatch(2)\n        val partitionKey = UUID.randomUUID().toString()\n        val config = configFactory.createSyncConfigurationBuilder(user, partitionKey)\n            .syncClientResetStrategy(object: RecoverOrDiscardUnsyncedChangesStrategy {\n                override fun onBeforeReset(realm: Realm) {\n                    latch.countDown()\n                }\n\n                override fun onAfterRecovery(before: Realm, after: Realm) {\n                    latch.countDown()\n                }\n\n                override fun onAfterDiscard(before: Realm, after: Realm) {\n                    fail(\"This test case was not supposed to trigger AutomaticRecoveryStrategy::onAfterDiscard()\")\n                }\n\n                override fun onManualResetFallback(session: SyncSession, error: ClientResetRequiredError) {\n                    fail(\"This test case was not supposed to trigger AutomaticRecoveryStrategy::onManualResetFallback()\")\n                }\n            })\n            .modules(ObjectSyncSchema())\n            .build()\n\n        val realm = Realm.getInstance(config)\n        looperThread.closeAfterTest(realm)\n        admin.triggerClientReset(realm.syncSession) {\n            realm.executeTransaction {\n                it.insert(DummySyncObject())\n            }\n\n            Assert.assertEquals(1, realm.where<DummySyncObject>().count())\n        }\n\n        looperThread.testComplete(latch)\n    }\n\n    @Test\n    fun clientReset_recoverOrDiscardUnsyncedChangesStrategy_discards() = looperThread.runBlocking {\n        val latch = CountDownLatch(2)\n        val partitionKey = UUID.randomUUID().toString()\n        val config = configFactory.createSyncConfigurationBuilder(user, partitionKey)\n            .syncClientResetStrategy(object: RecoverOrDiscardUnsyncedChangesStrategy {\n                override fun onBeforeReset(realm: Realm) {\n                    assertTrue(realm.isFrozen)\n                    Assert.assertEquals(1, realm.where<DummySyncObject>().count())\n                    latch.countDown()\n                }\n\n                override fun onAfterRecovery(before: Realm, after: Realm) {\n                    fail(\"This test case was not supposed to trigger RecoverOrDiscardUnsyncedChangesStrategy::onAfterRecovery()\")\n                }\n\n                override fun onAfterDiscard(before: Realm, after: Realm) {\n                    assertTrue(before.isFrozen)\n                    assertFalse(after.isFrozen)\n\n                    Assert.assertEquals(1, before.where<DummySyncObject>().count())\n                    Assert.assertEquals(0, after.where<DummySyncObject>().count())\n\n                    //Validate we can move data to the reset Realm.\n                    after.executeTransaction{\n                        it.insert(before.where<DummySyncObject>().findFirst()!!)\n                    }\n                    Assert.assertEquals(1, after.where<DummySyncObject>().count())\n                    latch.countDown()\n                }\n\n                override fun onManualResetFallback(session: SyncSession, error: ClientResetRequiredError) {\n                    fail(\"This test case was not supposed to trigger RecoverOrDiscardUnsyncedChangesStrategy::onManualResetFallback()\")\n                }\n            })\n            .modules(ObjectSyncSchema())\n            .build()\n\n        val realm = Realm.getInstance(config)\n        looperThread.closeAfterTest(realm)\n        admin.triggerClientReset(realm.syncSession, false, latch) {\n            realm.executeTransaction {\n                it.insert(DummySyncObject())\n            }\n\n            Assert.assertEquals(1, realm.where<DummySyncObject>().count())\n        }\n\n        looperThread.testComplete(latch)\n    }\n\n    @Test\n    fun clientReset_recoverOrDiscardUnsyncedChangesStrategy_fallback_userException_onBeforeReset() = looperThread.runBlocking {\n        val partitionKey = UUID.randomUUID().toString()\n        val config = configFactory.createSyncConfigurationBuilder(user, partitionKey)\n            .syncClientResetStrategy(object : RecoverOrDiscardUnsyncedChangesStrategy {\n                override fun onBeforeReset(realm: Realm) {\n                    throw RuntimeException()\n                }\n\n                override fun onAfterRecovery(before: Realm, after: Realm) {\n                    fail(\"This test case was not supposed to trigger RecoverOrDiscardUnsyncedChangesStrategy::onAfterRecovery()\")\n                }\n\n                override fun onAfterDiscard(before: Realm, after: Realm) {\n                    fail(\"This test case was not supposed to trigger RecoverOrDiscardUnsyncedChangesStrategy::onAfterDiscard()\")\n                }\n\n                override fun onManualResetFallback(\n                    session: SyncSession,\n                    error: ClientResetRequiredError\n                ) {\n                    validateManualResetIsAvailable(session, error)\n\n                    looperThread.testComplete()\n                }\n            })\n            .modules(ObjectSyncSchema())\n            .build()\n\n        val realm = Realm.getInstance(config)\n        looperThread.closeAfterTest(realm)\n\n        admin.triggerClientReset(realm.syncSession) {\n            realm.executeTransaction {\n                it.insert(DummySyncObject())\n            }\n\n            Assert.assertEquals(1, realm.where<DummySyncObject>().count())\n        }\n    }\n\n    @Test\n    fun clientReset_recoverOrDiscardUnsyncedChangesStrategy_fallback_userException_onAfterRecovery() = looperThread.runBlocking {\n        val partitionKey = UUID.randomUUID().toString()\n        val config = configFactory.createSyncConfigurationBuilder(user, partitionKey)\n            .syncClientResetStrategy(object : RecoverOrDiscardUnsyncedChangesStrategy {\n                override fun onBeforeReset(realm: Realm) {\n                    assertNotNull(realm)\n                }\n\n                override fun onAfterRecovery(before: Realm, after: Realm) {\n                    throw RuntimeException()\n                }\n\n                override fun onAfterDiscard(before: Realm, after: Realm) {\n                    fail(\"This test case was not supposed to trigger RecoverOrDiscardUnsyncedChangesStrategy::onAfterDiscard()\")\n                }\n\n                override fun onManualResetFallback(\n                    session: SyncSession,\n                    error: ClientResetRequiredError\n                ) {\n                    validateManualResetIsAvailable(session, error)\n\n                    looperThread.testComplete()\n                }\n            })\n            .modules(ObjectSyncSchema())\n            .build()\n\n        val realm = Realm.getInstance(config)\n        looperThread.closeAfterTest(realm)\n\n        admin.triggerClientReset(realm.syncSession) {\n            realm.executeTransaction {\n                it.insert(DummySyncObject())\n            }\n\n            Assert.assertEquals(1, realm.where<DummySyncObject>().count())\n        }\n    }\n\n    @Test\n    fun clientReset_recoverOrDiscardUnsyncedChangesStrategy_fallback_userException_onAfterDiscard() = looperThread.runBlocking {\n        val partitionKey = UUID.randomUUID().toString()\n        val config = configFactory.createSyncConfigurationBuilder(user, partitionKey)\n            .syncClientResetStrategy(object : RecoverOrDiscardUnsyncedChangesStrategy {\n                override fun onBeforeReset(realm: Realm) {\n                    assertNotNull(realm)\n                }\n\n                override fun onAfterRecovery(before: Realm, after: Realm) {\n                    fail(\"This test case was not supposed to trigger RecoverOrDiscardUnsyncedChangesStrategy::onAfterRecovery()\")\n                }\n\n                override fun onAfterDiscard(before: Realm, after: Realm) {\n                    throw RuntimeException()\n                }\n\n                override fun onManualResetFallback(\n                    session: SyncSession,\n                    error: ClientResetRequiredError\n                ) {\n                    validateManualResetIsAvailable(session, error)\n\n                    looperThread.testComplete()\n                }\n            })\n            .modules(ObjectSyncSchema())\n            .build()\n\n        val realm = Realm.getInstance(config)\n        looperThread.closeAfterTest(realm)\n\n        admin.triggerClientReset(realm.syncSession, withRecoveryModeEnabled = false) {\n            realm.executeTransaction {\n                it.insert(DummySyncObject())\n            }\n\n            Assert.assertEquals(1, realm.where<DummySyncObject>().count())\n        }\n    }\n\n    @Test\n    fun partitionValue_string() {\n        val partitionValue = \"123464652\"\n        val syncConfiguration = configFactory\n                .createSyncConfigurationBuilder(user, BsonString(partitionValue))\n                .modules(DefaultSyncSchema())\n                .build()\n        Realm.getInstance(syncConfiguration).use { realm ->\n            realm.executeTransaction {\n                realm.createObject(SyncDog::class.java, ObjectId())\n            }\n            realm.syncSession.uploadAllLocalChanges()\n        }\n    }\n\n    @Test\n    fun partitionValue_int32_failsWhenServerConfiguredWithStringPartition() {\n        val int = 123536462\n        val syncConfiguration = configFactory\n                .createSyncConfigurationBuilder(user, BsonInt32(int))\n                .modules(DefaultSyncSchema())\n                .build()\n\n        looperThread.runBlocking {\n            Realm.getInstance(syncConfiguration).use { realm ->\n                realm.executeTransaction {\n                    realm.createObject(SyncDog::class.java, ObjectId())\n                }\n\n                assertFailsWith<AppException> {\n                    // This throws as the server has NOT been configured to have int partitions!\n                    realm.syncSession.uploadAllLocalChanges()\n                }.also {\n                    looperThread.testComplete()\n                }\n            }\n        }\n    }\n\n    @Test\n    fun partitionValue_int64_failsWhenServerConfiguredWithStringPartition() {\n        val long = 1243513244L\n        val syncConfiguration = configFactory\n                .createSyncConfigurationBuilder(user, BsonInt64(long))\n                .modules(DefaultSyncSchema())\n                .build()\n\n        looperThread.runBlocking {\n            Realm.getInstance(syncConfiguration).use { realm ->\n                realm.executeTransaction {\n                    realm.createObject(SyncDog::class.java, ObjectId())\n                }\n                try {\n                    realm.syncSession.uploadAllLocalChanges()\n                    fail()\n                } catch (ex: AppException) {\n                    assertEquals(ErrorCode.Type.SYNC, ex.errorType)\n                    assertEquals(ErrorCode.BAD_SYNC_PARTITION_VALUE, ex.errorCode)\n                    looperThread.testComplete()\n                }\n            }\n        }\n    }\n\n    @Test\n    fun partitionValue_objectId() {\n        val syncConfiguration = configFactory\n                .createSyncConfigurationBuilder(user, BsonString(UUID.randomUUID().toString()))\n                .modules(DefaultSyncSchema())\n                .build()\n        Realm.getInstance(syncConfiguration).use { realm ->\n            realm.executeTransaction {\n                realm.createObject(SyncDog::class.java, ObjectId())\n            }\n            realm.syncSession.uploadAllLocalChanges()\n        }\n    }\n\n    @Test(timeout = 3000)\n    fun getState_active() {\n        Realm.getInstance(syncConfiguration).use { realm ->\n            val session: SyncSession = realm.syncSession\n\n            // make sure the `access_token` is acquired. otherwise we can still be\n            // in WAITING_FOR_ACCESS_TOKEN state\n            while (session.state != SyncSession.State.ACTIVE) {\n                SystemClock.sleep(200)\n            }\n        }\n    }\n\n    @Test\n    fun getState_throwOnClosedSession() {\n        var session: SyncSession? = null\n        Realm.getInstance(syncConfiguration).use { realm ->\n            session = realm.syncSession\n        }\n        user.logOut()\n\n        assertFailsWithMessage<java.lang.IllegalStateException>(CoreMatchers.equalTo(\"Could not find session, Realm was probably closed\")) {\n            session!!.state\n        }\n    }\n\n    @Test\n    fun getState_loggedOut() {\n        Realm.getInstance(syncConfiguration).use { realm ->\n            val session = realm.syncSession\n            user.logOut()\n            assertEquals(SyncSession.State.INACTIVE, session.state)\n        }\n    }\n\n    // FIXME: Investigate if this behavior is correct https://github.com/realm/realm-java/issues/7591\n    @Test\n    fun session_throwOnLogoutUser() {\n        user.logOut()\n        assertFailsWith<IllegalStateException> {\n            Realm.getInstance(syncConfiguration).use { }\n        }\n    }\n\n    @Test\n    fun uploadDownloadAllChanges() {\n        Realm.getInstance(syncConfiguration).use { realm ->\n            realm.executeTransaction {\n                realm.createObject(SyncAllTypes::class.java, ObjectId())\n            }\n            realm.syncSession.uploadAllLocalChanges()\n        }\n\n        // New user but same Realm as configuration has the same partition value\n        val user2 = app.registerUserAndLogin(TestHelper.getRandomEmail(), SECRET_PASSWORD)\n        val config2 = configFactory\n                .createSyncConfigurationBuilder(user2, syncConfiguration.partitionValue)\n                .modules(DefaultSyncSchema())\n                .build()\n\n        Realm.getInstance(config2).use { realm ->\n            realm.syncSession.downloadAllServerChanges()\n            realm.refresh()\n            assertEquals(1, realm.where(SyncAllTypes::class.java).count())\n        }\n    }\n\n    @Test\n    fun differentPartitionValue_allTypes() {\n        Realm.getInstance(syncConfiguration).use { realm ->\n            realm.executeTransaction {\n                realm.createObject(SyncAllTypes::class.java, ObjectId())\n            }\n            realm.syncSession.uploadAllLocalChanges()\n        }\n\n        // New user and different partition value\n        val user2 = app.registerUserAndLogin(TestHelper.getRandomEmail(), SECRET_PASSWORD)\n        val config2 = configFactory\n                .createSyncConfigurationBuilder(user2, BsonString(UUID.randomUUID().toString()))\n                .modules(DefaultSyncSchema())\n                .build()\n\n        Realm.getInstance(config2).use { realm ->\n            realm.executeTransaction {\n                realm.createObject(SyncAllTypes::class.java, ObjectId())\n            }\n            realm.syncSession.uploadAllLocalChanges()\n        }\n    }\n\n    @Test\n    fun differentPartitionValue_noCrosstalk() {\n        Realm.getInstance(syncConfiguration).use { realm ->\n            realm.executeTransaction {\n                realm.createObject(SyncAllTypes::class.java, ObjectId())\n            }\n            realm.syncSession.uploadAllLocalChanges()\n        }\n\n        // New user and different partition value\n        val user2 = app.registerUserAndLogin(TestHelper.getRandomEmail(), SECRET_PASSWORD)\n        val config2 = configFactory\n                .createSyncConfigurationBuilder(user2, BsonString(UUID.randomUUID().toString()))\n                .modules(DefaultSyncSchema())\n                .build()\n\n        Realm.getInstance(config2).use { realm ->\n            realm.syncSession.downloadAllServerChanges()\n            // We should not have any data here\n            assertEquals(0, realm.where(SyncAllTypes::class.java).count())\n        }\n    }\n\n    @Test\n    fun interruptWaits() {\n        Realm.getInstance(syncConfiguration).use { userRealm ->\n            userRealm.executeTransaction {\n                userRealm.createObject(SyncAllTypes::class.java, ObjectId())\n            }\n            val userSession = userRealm.syncSession\n            try {\n                // 1. Start download (which will be interrupted)\n                Thread.currentThread().interrupt()\n                userSession.downloadAllServerChanges()\n                fail()\n            } catch (ignored: InterruptedException) {\n                assertFalse(Thread.currentThread().isInterrupted)\n            }\n            try {\n                // 2. Upload all changes\n                userSession.uploadAllLocalChanges()\n            } catch (e: InterruptedException) {\n                fail(\"Upload interrupted\")\n            }\n        }\n\n        // New user but same Realm as configuration has the same partition value\n        val user2 = app.registerUserAndLogin(TestHelper.getRandomEmail(), SECRET_PASSWORD)\n        val config2 = configFactory\n                .createSyncConfigurationBuilder(user2, syncConfiguration.partitionValue)\n                .modules(DefaultSyncSchema())\n                .build()\n\n        Realm.getInstance(config2).use { adminRealm ->\n            val adminSession: SyncSession = adminRealm.syncSession\n            try {\n                // 3. Start upload (which will be interrupted)\n                Thread.currentThread().interrupt()\n                adminSession.uploadAllLocalChanges()\n                fail()\n            } catch (ignored: InterruptedException) {\n                assertFalse(Thread.currentThread().isInterrupted) // clear interrupted flag\n            }\n            try {\n                // 4. Download all changes\n                adminSession.downloadAllServerChanges()\n            } catch (e: InterruptedException) {\n                fail(\"Download interrupted\")\n            }\n            adminRealm.refresh()\n\n            assertEquals(1, adminRealm.where(SyncAllTypes::class.java).count())\n        }\n    }\n\n    // check that logging out a SyncUser used by different Realm will\n    // affect all associated sessions.\n    @Test(timeout = 5000)\n    fun logout_sameSyncUserMultipleSessions() {\n        Realm.getInstance(syncConfiguration).use { realm1 ->\n            // New partitionValue to differentiate sync session\n            val syncConfiguration2 = configFactory\n                    .createSyncConfigurationBuilder(user, BsonString(UUID.randomUUID().toString()))\n                    .modules(DefaultSyncSchema())\n                    .build()\n\n            Realm.getInstance(syncConfiguration2).use { realm2 ->\n                val session1: SyncSession = realm1.syncSession\n                val session2: SyncSession = realm2.syncSession\n\n                // make sure the `access_token` is acquired. otherwise we can still be\n                // in WAITING_FOR_ACCESS_TOKEN state\n                // FIXME Reavaluate with new sync states\n                while (session1.state != SyncSession.State.ACTIVE || session2.state != SyncSession.State.ACTIVE) {\n                    SystemClock.sleep(200)\n                }\n\n                assertEquals(SyncSession.State.ACTIVE, session1.state)\n                assertEquals(SyncSession.State.ACTIVE, session2.state)\n                assertNotEquals(realm1, realm2)\n                assertNotEquals(session1, session2)\n                assertEquals(session1.user, session2.user)\n                user.logOut()\n                assertEquals(SyncSession.State.INACTIVE, session1.state)\n                assertEquals(SyncSession.State.INACTIVE, session2.state)\n\n                // Login again\n                app.login(Credentials.emailPassword(user.profile.email!!, SECRET_PASSWORD))\n\n                // reviving the sessions. The state could be changed concurrently.\n                assertTrue(\n                        //session1.state == SyncSession.State.WAITING_FOR_ACCESS_TOKEN ||\n                        session1.state == SyncSession.State.ACTIVE)\n                assertTrue(\n                        //session2.state == SyncSession.State.WAITING_FOR_ACCESS_TOKEN ||\n                        session2.state == SyncSession.State.ACTIVE)\n            }\n        }\n    }\n\n    // A Realm that was opened before a user logged out should be able to resume uploading if the user logs back in.\n    @Test\n    fun logBackResumeUpload() {\n        val config1 = configFactory\n                .createSyncConfigurationBuilder(user, UUID.randomUUID().toString())\n                .modules(SyncStringOnlyModule())\n                .waitForInitialRemoteData()\n                .build()\n        Realm.getInstance(config1).use { realm1 ->\n            realm1.executeTransaction { realm -> realm.createObject(SyncStringOnly::class.java, ObjectId()).chars = \"1\" }\n            val session1: SyncSession = realm1.syncSession\n            session1.uploadAllLocalChanges()\n            user.logOut()\n\n            // add a commit while we're still offline\n            realm1.executeTransaction { realm -> realm.createObject(SyncStringOnly::class.java, ObjectId()).chars = \"2\" }\n            val testCompleted = CountDownLatch(1)\n            val handlerThread = HandlerThread(\"HandlerThread\")\n            handlerThread.start()\n            val looper = handlerThread.looper\n            val handler = Handler(looper)\n            val allResults = AtomicReference<RealmResults<SyncStringOnly>>() // notifier could be GC'ed before it get a chance to trigger the second commit, so declaring it outside the Runnable\n            handler.post { // access the Realm from an different path on the device (using admin user), then monitor\n                // when the offline commits get synchronized\n                val user2 = app.registerUserAndLogin(TestHelper.getRandomEmail(), SECRET_PASSWORD)\n                val config2: SyncConfiguration = configFactory.createSyncConfigurationBuilder(user2, config1.partitionValue)\n                        .modules(SyncStringOnlyModule())\n                        .build()\n                val realm2 = Realm.getInstance(config2)\n\n                allResults.set(realm2.where(SyncStringOnly::class.java).sort(SyncStringOnly.FIELD_CHARS).findAll())\n                val realmChangeListener: RealmChangeListener<RealmResults<SyncStringOnly>> = object : RealmChangeListener<RealmResults<SyncStringOnly>> {\n                    override fun onChange(stringOnlies: RealmResults<SyncStringOnly>) {\n                        if (stringOnlies.size == 2) {\n                            assertEquals(\"1\", stringOnlies[0]!!.chars)\n                            assertEquals(\"2\", stringOnlies[1]!!.chars)\n                            handler.post {\n\n                                // Closing a Realm from inside a listener doesn't seem to remove the\n                                // active session reference in Object Store\n                                realm2.close()\n                                testCompleted.countDown()\n                                handlerThread.quitSafely()\n                            }\n                        }\n                    }\n                }\n                allResults.get().addChangeListener(realmChangeListener)\n\n                // login again to re-activate the user\n                val credentials = Credentials.emailPassword(user.profile.email!!, SECRET_PASSWORD)\n                // this login will re-activate the logged out user, and resume all it's pending sessions\n                // the OS will trigger bindSessionWithConfig with the new refresh_token, in order to obtain\n                // a new access_token.\n                app.login(credentials)\n            }\n            TestHelper.awaitOrFail(testCompleted)\n        }\n    }\n\n    // A Realm that was opened before a user logged out should be able to resume uploading if the user logs back in.\n    // this test validate the behaviour of SyncSessionStopPolicy::AfterChangesUploaded\n    @Test\n    fun uploadChangesWhenRealmOutOfScope() = looperThread.runBlocking {\n        val strongRefs: MutableList<Any> = ArrayList()\n        val chars = CharArray(1000000) // 2MB\n        Arrays.fill(chars, '.')\n        val twoMBString = String(chars)\n        val config1 = configFactory\n                .createSyncConfigurationBuilder(user, UUID.randomUUID().toString())\n                .testSessionStopPolicy(OsRealmConfig.SyncSessionStopPolicy.AFTER_CHANGES_UPLOADED)\n                .modules(SyncStringOnlyModule())\n                .build()\n        Realm.getInstance(config1).use { realm ->\n            realm.executeTransaction {\n                // upload 10MB\n                for (i in 0..4) {\n                    realm.createObject(SyncStringOnly::class.java, ObjectId()).chars = twoMBString\n                }\n            }\n        }\n\n        val testCompleted = CountDownLatch(1)\n        val handlerThread = HandlerThread(\"HandlerThread\")\n        handlerThread.start()\n        val looper = handlerThread.looper\n        val handler = Handler(looper)\n        handler.post { // using an other user to open the Realm on different path on the device to monitor when all the uploads are done\n            val user2 = app.registerUserAndLogin(TestHelper.getRandomEmail(), SECRET_PASSWORD)\n            val config2: SyncConfiguration = configFactory.createSyncConfigurationBuilder(user2, config1.partitionValue)\n                    .modules(SyncStringOnlyModule())\n                    .build()\n            val realm2 = Realm.getInstance(config2)\n            val all = realm2.where(SyncStringOnly::class.java).findAll()\n            if (all.size == 5) {\n                realm2.close()\n                testCompleted.countDown()\n                handlerThread.quit()\n            } else {\n                strongRefs.add(all)\n                val realmChangeListener = OrderedRealmCollectionChangeListener { results: RealmResults<SyncStringOnly?>, changeSet: OrderedCollectionChangeSet? ->\n                    if (results.size == 5) {\n                        realm2.close()\n                        testCompleted.countDown()\n                        handlerThread.quit()\n                    }\n                }\n                all.addChangeListener(realmChangeListener)\n            }\n        }\n        TestHelper.awaitOrFail(testCompleted, TestHelper.STANDARD_WAIT_SECS)\n        handlerThread.join()\n        user.logOut()\n        looperThread.testComplete()\n    }\n\n    // A Realm that was opened before a user logged out should be able to resume downloading if the user logs back in.\n    @Test\n    fun downloadChangesWhenRealmOutOfScope() {\n        val uniqueName = UUID.randomUUID().toString()\n        app.emailPassword.registerUser(uniqueName, \"password\")\n        val config1 = configFactory\n                .createSyncConfigurationBuilder(user, UUID.randomUUID().toString())\n                .modules(SyncStringOnlyModule())\n                .build()\n        Realm.getInstance(config1).use { realm ->\n            realm.executeTransaction {\n                realm.createObject(SyncStringOnly::class.java, ObjectId()).chars = \"1\"\n            }\n            val session: SyncSession = realm.syncSession\n            session.uploadAllLocalChanges()\n\n            // Log out the user.\n            user.logOut()\n\n            // Log the user back in.\n            val credentials = Credentials.emailPassword(user.profile.email!!, SECRET_PASSWORD)\n            app.login(credentials)\n\n            // Write updates from a different user\n            val backgroundUpload = CountDownLatch(1)\n            val handlerThread = HandlerThread(\"HandlerThread\")\n            handlerThread.start()\n            val looper = handlerThread.looper\n            val handler = Handler(looper)\n            handler.post { // Using a different user to open the Realm on different path on the device then some commits\n                val user2 = app.registerUserAndLogin(TestHelper.getRandomEmail(), SECRET_PASSWORD)\n                val config2: SyncConfiguration = configFactory.createSyncConfigurationBuilder(user2, config1.partitionValue)\n                        .modules(SyncStringOnlyModule())\n                        .waitForInitialRemoteData()\n                        .build()\n                Realm.getInstance(config2).use { realm2 ->\n                    realm2.executeTransaction {\n                        realm2.createObject(SyncStringOnly::class.java, ObjectId()).chars = \"2\"\n                        realm2.createObject(SyncStringOnly::class.java, ObjectId()).chars = \"3\"\n                    }\n                    realm2.syncSession.uploadAllLocalChanges()\n                }\n                backgroundUpload.countDown()\n                handlerThread.quit()\n            }\n            TestHelper.awaitOrFail(backgroundUpload, 60)\n            // Resume downloading\n            session.downloadAllServerChanges()\n            realm.refresh() //FIXME not calling refresh will still point to the previous version of the Realm count == 1\n            assertEquals(3, realm.where(SyncStringOnly::class.java).count())\n        }\n    }\n\n    // Check that if we manually trigger a Client Reset, then it should be possible to start\n    // downloading the Realm immediately after.\n    @Test\n    // TODO Seems to align with tests in SessionTests, should we move them to same location\n    fun clientReset_manualTriggerAllowSessionToRestart() = looperThread.runBlocking {\n        val resources = ResourceContainer()\n        val configRef = AtomicReference<SyncConfiguration?>(null)\n        val config: SyncConfiguration = configFactory.createSyncConfigurationBuilder(user)\n                .testSchema(SyncStringOnly::class.java)\n                // ClientResyncMode is currently hidden, but MANUAL is the default\n                // .clientResyncMode(ClientResyncMode.MANUAL)\n                // FIXME Is this critical for the test\n                //.directory(looperThread.getRoot())\n                .clientResetHandler { session, error ->\n                    // Execute Client Reset\n                    runBlocking(looperThread.asDispatcher()) {\n                        resources.close()\n                    }\n                    error.executeClientReset()\n\n                    // Try to re-open Realm and download it again\n                    looperThread.postRunnable(Runnable { // Validate that files have been moved\n                        assertFalse(error.originalFile.exists())\n                        assertTrue(error.backupFile.exists())\n                        val config = configRef.get()\n                        Realm.getInstance(config!!).use { realm ->\n                            realm.syncSession.downloadAllServerChanges()\n                            looperThread.testComplete()\n                        }\n                    })\n                }\n                .build()\n        configRef.set(config)\n        val realm = Realm.getInstance(config)\n        resources.add(realm)\n        // Trigger error\n        admin.triggerClientReset(realm.syncSession) { /* Do nothing */ }\n    }\n\n    @Test\n    fun registerConnectionListener() = looperThread.runBlocking {\n        getSession { session: SyncSession ->\n            RealmLog.info(\"Starting state: ${session.connectionState}\")\n            session.addConnectionChangeListener { oldState: ConnectionState?, newState: ConnectionState ->\n                // It is impossible to 100% guarantee the state of the connection here.\n                // But any state change is considered a success.\n                RealmLog.info(\"Connection: $oldState -> $newState\")\n                when (newState) {\n                    ConnectionState.DISCONNECTED,\n                    ConnectionState.CONNECTING,\n                    ConnectionState.CONNECTED -> {\n                        // Closing a Realm inside a connection listener doesn't work: https://github.com/realm/realm-java/issues/6249\n                        looperThread.testComplete()\n                    }\n                }\n            }\n            if (session.connectionState == ConnectionState.CONNECTED) {\n                // Failsafe in case the connection is actually established before\n                // we can attach the connection listener. Manual testing shows\n                // that this is highly unlikely.\n                looperThread.testComplete()\n            }\n        }\n    }\n\n    @Test\n    fun removeConnectionListener() = looperThread.runBlocking {\n        Realm.getInstance(syncConfiguration).use { realm ->\n            val session: SyncSession = realm.syncSession\n            val listener1 = ConnectionListener { oldState: ConnectionState?, newState: ConnectionState ->\n                if (newState == ConnectionState.DISCONNECTED) {\n                    fail(\"Listener should have been removed\")\n                }\n            }\n            val listener2 = ConnectionListener { oldState, newState ->\n                if (newState == ConnectionState.DISCONNECTED) {\n                    looperThread.testComplete()\n                }\n            }\n            session.addConnectionChangeListener(listener1)\n            session.addConnectionChangeListener(listener2)\n            session.removeConnectionChangeListener(listener1)\n        }\n    }\n\n    @Test\n    fun getIsConnected() = looperThread.runBlocking {\n        getActiveSession { session: SyncSession ->\n            assertEquals(session.connectionState, ConnectionState.CONNECTED)\n            assertTrue(session.isConnected)\n            looperThread.testComplete()\n        }\n    }\n\n    @Test\n    fun stopStartSession() = looperThread.runBlocking {\n        getActiveSession { session: SyncSession ->\n            assertEquals(SyncSession.State.ACTIVE, session.state)\n            session.stop()\n            assertEquals(SyncSession.State.INACTIVE, session.state)\n            session.start()\n            assertNotEquals(SyncSession.State.INACTIVE, session.state)\n            looperThread.testComplete()\n        }\n    }\n\n    @Test\n    fun start_multipleTimes() = looperThread.runBlocking {\n        getActiveSession { session ->\n            session.start()\n            assertEquals(SyncSession.State.ACTIVE, session.state)\n            session.start()\n            assertEquals(SyncSession.State.ACTIVE, session.state)\n            looperThread.testComplete()\n        }\n    }\n\n    @Test\n    fun stop_multipleTimes() = looperThread.runBlocking {\n        getActiveSession { session ->\n            session.stop()\n            assertEquals(SyncSession.State.INACTIVE, session.state)\n            session.stop()\n            assertEquals(SyncSession.State.INACTIVE, session.state)\n            looperThread.testComplete()\n        }\n    }\n\n    @Test\n    // FIXME Investigate\n    @Ignore(\"Asserts with no_session when tearing down, meaning that all session are not \" +\n            \"closed, but realm seems to be closed, so further investigation is needed \" +\n            \"seems to be caused by https://github.com/realm/realm-java/issues/5416\")\n    fun waitForInitialRemoteData_throwsOnTimeout() = looperThread.runBlocking {\n        val syncConfiguration = configFactory\n                .createSyncConfigurationBuilder(user)\n                .modules(DefaultSyncSchema())\n                .initialData { bgRealm: Realm ->\n                    for (i in 0..99) {\n                        bgRealm.createObject(SyncAllTypes::class.java, ObjectId())\n                    }\n                }\n                .waitForInitialRemoteData(1, TimeUnit.MILLISECONDS)\n                .build()\n        assertFailsWith<DownloadingRealmInterruptedException> {\n            val instance = Realm.getInstance(syncConfiguration)\n            looperThread.closeAfterTest(Closeable {\n                instance.syncSession.testClose()\n                instance.close()\n            })\n        }\n        looperThread.testComplete()\n    }\n\n    @Test\n    fun cachedInstanceShouldNotThrowIfUserTokenIsInvalid() {\n        val configuration: RealmConfiguration = configFactory.createSyncConfigurationBuilder(user)\n                .testSchema(SyncStringOnly::class.java)\n                .errorHandler { session, error ->\n                    RealmLog.debug(\"error\", error)\n                }\n                .build()\n\n        Realm.getInstance(configuration).close()\n\n        admin.disableUser(user)\n\n        // It should be possible to open a cached Realm with expired token\n        Realm.getInstance(configuration).close()\n\n        // It should also be possible to open a Realm with an expired token from a different thread\n        looperThread.runBlocking {\n            val instance = Realm.getInstance(configuration)\n            instance.close()\n            looperThread.testComplete()\n        }\n\n        // TODO We cannot currently easily verify that token is actually invalid and triggering\n        //  refresh. If OS includes support for reacting on this we should verify that it is\n        //  refreshed.\n        //Realm.getInstance(configuration).use { realm ->\n        //     realm.syncSession.downloadAllServerChanges()\n        //}\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/syncIntegrationTest/kotlin/io/realm/SyncedRealmIntegrationTests.kt",
    "content": "/*\n * Copyright 2020 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 */\npackage io.realm\n\nimport android.os.SystemClock\nimport androidx.test.annotation.UiThreadTest\nimport androidx.test.ext.junit.runners.AndroidJUnit4\nimport androidx.test.filters.FlakyTest\nimport androidx.test.platform.app.InstrumentationRegistry\nimport io.realm.entities.DefaultSyncSchema\nimport io.realm.entities.StringOnly\nimport io.realm.entities.SyncSchemeMigration\nimport io.realm.entities.SyncStringOnly\nimport io.realm.exceptions.DownloadingRealmInterruptedException\nimport io.realm.exceptions.RealmMigrationNeededException\nimport io.realm.internal.OsRealmConfig\nimport io.realm.kotlin.syncSession\nimport io.realm.log.LogLevel\nimport io.realm.log.RealmLog\nimport io.realm.mongodb.*\nimport io.realm.mongodb.sync.*\nimport io.realm.objectserver.utils.Constants\nimport io.realm.rule.BlockingLooperThread\nimport org.bson.BsonObjectId\nimport org.bson.types.ObjectId\nimport org.junit.After\nimport org.junit.Assert.*\nimport org.junit.Before\nimport org.junit.Ignore\nimport org.junit.Test\nimport org.junit.runner.RunWith\nimport java.io.File\nimport java.util.*\nimport kotlin.test.assertEquals\nimport kotlin.test.assertFailsWith\n\nprivate const val SECRET_PASSWORD = \"123456\"\n\n/**\n * Catch all class for tests that not naturally fit anywhere else.\n */\n@RunWith(AndroidJUnit4::class)\nclass SyncedRealmIntegrationTests {\n\n    private val looperThread = BlockingLooperThread()\n\n    private lateinit var app: App\n    private lateinit var user: User\n    private lateinit var syncConfiguration: SyncConfiguration\n\n    private val configurationFactory: TestSyncConfigurationFactory = TestSyncConfigurationFactory()\n\n    @Before\n    fun setup() {\n        Realm.init(InstrumentationRegistry.getInstrumentation().targetContext)\n        RealmLog.setLevel(LogLevel.ALL)\n        app = TestApp()\n        user = app.registerUserAndLogin(TestHelper.getRandomEmail(), SECRET_PASSWORD)\n        syncConfiguration = configurationFactory\n                // TODO We generate new partition value for each test to avoid overlaps in data. We\n                //  could make test booting with a cleaner state by somehow flushing data between\n                //  tests.\n                .createSyncConfigurationBuilder(user, BsonObjectId(ObjectId()))\n                .testSchema(StringOnly::class.java)\n                .modules(DefaultSyncSchema())\n                .build()\n    }\n\n    @After\n    fun teardown() {\n        if (this::app.isInitialized) {\n            app.close()\n        }\n        RealmLog.setLevel(LogLevel.WARN)\n    }\n\n    @Test\n    fun loginLogoutResumeSyncing() = looperThread.runBlocking {\n        val config: SyncConfiguration = configurationFactory.createSyncConfigurationBuilder(user, user.id)\n                .testSchema(SyncStringOnly::class.java)\n                .testSessionStopPolicy(OsRealmConfig.SyncSessionStopPolicy.IMMEDIATELY)\n                .build()\n        Realm.getInstance(config).use { realm ->\n            realm.executeTransaction {\n                realm.createObject(SyncStringOnly::class.java, ObjectId()).chars = \"Foo\"\n            }\n            realm.syncSession.uploadAllLocalChanges()\n            user.logOut()\n        }\n        try {\n            assertTrue(Realm.deleteRealm(config))\n        } catch (e: IllegalStateException) {\n            // TODO: We don't have a way to ensure that the Realm instance on client thread has been\n            //  closed for now https://github.com/realm/realm-java/issues/5416\n            if (e.message!!.contains(\"It's not allowed to delete the file\")) {\n                // retry after 1 second\n                SystemClock.sleep(1000)\n                assertTrue(Realm.deleteRealm(config))\n            }\n        }\n\n        user = app.login(Credentials.emailPassword(user.profile.email, SECRET_PASSWORD))\n        val config2: SyncConfiguration = configurationFactory.createSyncConfigurationBuilder(user, user.id)\n                .testSchema(SyncStringOnly::class.java)\n                .build()\n        Realm.getInstance(config2).use { realm ->\n            realm.syncSession.downloadAllServerChanges()\n            realm.refresh()\n            assertEquals(1, realm.where(SyncStringOnly::class.java).count())\n        }\n        looperThread.testComplete()\n    }\n\n    @Test\n    @UiThreadTest\n    fun waitForInitialRemoteData_mainThreadThrows() {\n        var user: User? = null\n        val t = Thread { user = SyncTestUtils.createTestUser(app) }\n        t.start()\n        t.join()\n        val config: SyncConfiguration = configurationFactory.createSyncConfigurationBuilder(user!!, user!!.id)\n                .waitForInitialRemoteData()\n                .build()\n        assertFailsWith<java.lang.IllegalStateException> {\n            Realm.getInstance(config).close()\n        }\n    }\n\n    @Test\n    fun waitForInitialRemoteData() {\n        // 1. Copy a valid Realm to the server (and pray it does it within 10 seconds)\n        val configOld: SyncConfiguration = configurationFactory.createSyncConfigurationBuilder(user, user.id)\n                .testSchema(SyncStringOnly::class.java)\n                .testSessionStopPolicy(OsRealmConfig.SyncSessionStopPolicy.IMMEDIATELY)\n                .build()\n        Realm.getInstance(configOld).use { realm ->\n            realm.executeTransaction { realm ->\n                for (i in 0..9) {\n                    realm.createObject(SyncStringOnly::class.java, ObjectId()).chars = \"Foo$i\"\n                }\n            }\n            realm.syncSession.uploadAllLocalChanges()\n        }\n        user.logOut()\n\n        // 2. Local state should now be completely reset. Open the same sync Realm but different local name again with\n        // a new configuration which should download the uploaded changes (pray it managed to do so within the time frame).\n        // Use different user to trigger different path\n        val user2 = app.registerUserAndLogin(TestHelper.getRandomEmail(), SECRET_PASSWORD)\n        val config: SyncConfiguration = configurationFactory.createSyncConfigurationBuilder(user2, user.id)\n                .testSchema(SyncStringOnly::class.java)\n                .waitForInitialRemoteData()\n                .build()\n        Realm.getInstance(config).use { realm ->\n            realm.executeTransaction { realm ->\n                for (i in 0..9) {\n                    realm.createObject(SyncStringOnly::class.java, ObjectId()).chars = \"Foo 1$i\"\n                }\n            }\n            assertEquals(20, realm.where(SyncStringOnly::class.java).count())\n        }\n    }\n\n    // Attempt to reproduce: https://github.com/realm/realm-java/issues/7517. getInstanceAsync did not\n    // wait for the initial remote data.\n    @Test\n    fun waitForInitialRemoteData_getInstanceAsync() = looperThread.runBlocking {\n        // 1. Copy a valid Realm to the server (and pray it does it within 10 seconds)\n        val configOld: SyncConfiguration = configurationFactory.createSyncConfigurationBuilder(user, user.id)\n            .testSchema(SyncStringOnly::class.java)\n            .testSessionStopPolicy(OsRealmConfig.SyncSessionStopPolicy.IMMEDIATELY)\n            .build()\n        Realm.getInstance(configOld).use { realm ->\n            // Create many changesets to make sure that download is \"slow\"\n            for (i in 0..99) {\n                realm.executeTransaction { realm ->\n                    realm.createObject(SyncStringOnly::class.java, ObjectId()).chars = \"Foo$i\"\n                }\n            }\n            realm.syncSession.uploadAllLocalChanges()\n        }\n        user.logOut()\n\n        // 2. Local state should now be completely reset. Open the same sync Realm but different local name again with\n        // a new configuration which should download the uploaded changes (pray it managed to do so within the time frame).\n        // Use different user to trigger different path\n        val user2 = app.registerUserAndLogin(TestHelper.getRandomEmail(), SECRET_PASSWORD)\n        val config: SyncConfiguration = configurationFactory.createSyncConfigurationBuilder(user2, user.id)\n            .testSchema(SyncStringOnly::class.java)\n            .waitForInitialRemoteData()\n            .build()\n\n        assertFalse(File(config.path).exists())\n        Realm.getInstanceAsync(config, object: Realm.Callback() {\n            override fun onSuccess(realm: Realm) {\n                looperThread.closeAfterTest(realm)\n                assertEquals(100, realm.where(SyncStringOnly::class.java).count())\n                looperThread.testComplete()\n            }\n\n            override fun onError(exception: Throwable) {\n                fail(exception.toString())\n            }\n        })\n    }\n\n    // Try an scenario where a Sync and Async race to wait for the initial remote data.\n    @Test\n    @FlakyTest(detail = \"Depend on the server being able to integrate changes into MongoDB fast enough before the new client downloads data.\")\n    fun waitForInitialRemoteData_getInstance_race_AsyncAndSync() = looperThread.runBlocking {\n        // 1. Copy a valid Realm to the server (and pray it does it within 10 seconds)\n        val configOld: SyncConfiguration = configurationFactory.createSyncConfigurationBuilder(user, user.id)\n            .testSchema(SyncStringOnly::class.java)\n            .testSessionStopPolicy(OsRealmConfig.SyncSessionStopPolicy.IMMEDIATELY)\n            .build()\n        Realm.getInstance(configOld).use { realm ->\n            // Create many changesets to make sure that download is \"slow\"\n            for (i in 0..99) {\n                realm.executeTransaction { realm ->\n                    realm.createObject(SyncStringOnly::class.java, ObjectId()).chars = \"Foo$i\"\n                }\n            }\n            realm.syncSession.uploadAllLocalChanges()\n        }\n        user.logOut()\n\n        // 2. Local state should now be completely reset. Open the same sync Realm but different local name again with\n        // a new configuration which should download the uploaded changes (pray it managed to do so within the time frame).\n        // Use different user to trigger different path\n        val user2 = app.registerUserAndLogin(TestHelper.getRandomEmail(), SECRET_PASSWORD)\n        val config: SyncConfiguration = configurationFactory.createSyncConfigurationBuilder(user2, user.id)\n            .testSchema(SyncStringOnly::class.java)\n            .waitForInitialRemoteData()\n            .build()\n\n        assertFalse(File(config.path).exists())\n\n        // Validate both async and sync are properly initialized.\n        Realm.getInstanceAsync(config, object: Realm.Callback() {\n            override fun onSuccess(realm: Realm) {\n                looperThread.closeAfterTest(realm)\n                assertEquals(100, realm.where(SyncStringOnly::class.java).count())\n                looperThread.testComplete()\n            }\n\n            override fun onError(exception: Throwable) {\n                fail(exception.toString())\n            }\n        })\n        Realm.getInstance(config).use { realm ->\n            assertEquals(100, realm.where(SyncStringOnly::class.java).count())\n        }\n    }\n\n    // This tests will start and cancel getting a Realm 10 times. The Realm should be resilient towards that\n    // We cannot do much better since we cannot control the order of events internally in Realm which would be\n    // needed to correctly test all error paths.\n    @Test\n    @Ignore(\"Sync somehow keeps a Realm alive, causing the Realm.deleteRealm to throw \" +\n            \" https://github.com/realm/realm-java/issues/5416\")\n    fun waitForInitialData_resilientInCaseOfRetries() = looperThread.runBlocking {\n        val config: SyncConfiguration = configurationFactory.createSyncConfigurationBuilder(user, user.id)\n                .waitForInitialRemoteData()\n                .build()\n        for (i in 0..9) {\n            val blockingLooperThread = BlockingLooperThread()\n            blockingLooperThread.runDetached {\n                var realm: Realm? = null\n                try {\n                    Thread.currentThread().interrupt()\n                    Realm.getInstance(config).close()\n                } catch (e: DownloadingRealmInterruptedException) {\n                }\n                // TODO: We don't have a way to ensure that the Realm instance on client thread has been\n                //  closed for now https://github.com/realm/realm-java/issues/5416\n                app.sync.getSession(config).testShutdownAndWait()\n                try {\n                    Realm.deleteRealm(config)\n                } catch (e: IllegalStateException) {\n                    if (e.message!!.contains(\"It's not allowed to delete the file\")) {\n                        // retry after 1 second\n                        SystemClock.sleep(1000)\n                        assertTrue(Realm.deleteRealm(config))\n                    }\n                }\n                blockingLooperThread.testComplete()\n            }.await()\n        }\n        looperThread.testComplete()\n    }\n\n    // This tests will start and cancel getting a Realm 10 times. The Realm should be resilient towards that\n    // We cannot do much better since we cannot control the order of events internally in Realm which would be\n    // needed to correctly test all error paths.\n    @Test\n    fun waitForInitialData_resilientInCaseOfRetriesAsync() = looperThread.runBlocking {\n        val config: SyncConfiguration = configurationFactory.createSyncConfigurationBuilder(user, user.id)\n                .testSessionStopPolicy(OsRealmConfig.SyncSessionStopPolicy.IMMEDIATELY)\n                .testSchema(SyncStringOnly::class.java)\n                .waitForInitialRemoteData()\n                .build()\n        val randomizer = Random()\n        for (i in 0..9) {\n            val task = Realm.getInstanceAsync(config, object : Realm.Callback() {\n                override fun onSuccess(realm: Realm) { fail() }\n                override fun onError(exception: Throwable) { fail(exception.toString()) }\n            })\n            SystemClock.sleep(randomizer.nextInt(5).toLong())\n            task.cancel()\n        }\n        // Leave some time for the async callbacks to actually get through\n        looperThread.postRunnableDelayed(\n                Runnable { looperThread.testComplete() },\n                1000\n        )\n    }\n\n    @Test\n    fun waitForInitialRemoteData_readOnlyTrue() {\n        // 1. Copy a valid Realm to the server (and pray it does it within 10 seconds)\n        val configOld: SyncConfiguration = configurationFactory.createSyncConfigurationBuilder(user, user.id)\n                .testSchema(SyncStringOnly::class.java)\n                .build()\n        Realm.getInstance(configOld).use { realm ->\n            realm.executeTransaction { realm ->\n                for (i in 0..9) {\n                    realm.createObject(SyncStringOnly::class.java, ObjectId()).chars = \"Foo$i\"\n                }\n            }\n            realm.syncSession.uploadAllLocalChanges()\n        }\n        user.logOut()\n\n        // 2. Local state should now be completely reset. Open the Realm again with a new configuration which should\n        // download the uploaded changes (pray it managed to do so within the time frame).\n        // Use different user to trigger different path\n        val user2 = app.registerUserAndLogin(TestHelper.getRandomEmail(), SECRET_PASSWORD)\n        val configNew: SyncConfiguration = configurationFactory.createSyncConfigurationBuilder(user2, user.id)\n                .waitForInitialRemoteData()\n                .readOnly()\n                .testSchema(SyncStringOnly::class.java)\n                .build()\n        assertFalse(configNew.testRealmExists())\n        Realm.getInstance(configNew).use { realm ->\n            assertEquals(10, realm.where(SyncStringOnly::class.java).count())\n        }\n        user.logOut()\n    }\n\n    @Test\n    fun waitForInitialRemoteData_readOnlyTrue_throwsIfWrongServerSchema() {\n        val configNew: SyncConfiguration = configurationFactory.createSyncConfigurationBuilder(user, user.id)\n                .waitForInitialRemoteData()\n                .readOnly()\n                .testSchema(SyncSchemeMigration::class.java)\n                .build()\n        assertFalse(configNew.testRealmExists())\n        assertFailsWith<RealmMigrationNeededException> {\n            Realm.getInstance(configNew).use { realm ->\n                realm.executeTransaction {\n                    it.createObject(SyncSchemeMigration::class.java, ObjectId())\n                }\n            }\n        }\n        user.logOut()\n    }\n\n    @Test\n    fun waitForInitialRemoteData_readOnlyFalse_upgradeSchema() {\n        val config: SyncConfiguration = configurationFactory.createSyncConfigurationBuilder(user, user.id)\n                .waitForInitialRemoteData() // Not readonly so Client should be allowed to write schema\n                .testSchema(SyncStringOnly::class.java) // This schema should be written when opening the empty Realm.\n                .schemaVersion(2)\n                .build()\n        assertFalse(config.testRealmExists())\n        Realm.getInstance(config).use { realm ->\n            assertEquals(0, realm.where(SyncStringOnly::class.java).count())\n        }\n        user.logOut()\n    }\n\n    @Test\n    fun defaultRealm() {\n        val config: SyncConfiguration = SyncConfiguration.Builder(user, user.id)\n                .testSchema(SyncStringOnly::class.java)\n                .build()\n\n        Realm.getInstance(config).use { realm ->\n            realm.syncSession.downloadAllServerChanges()\n            realm.refresh()\n            assertTrue(realm.isEmpty)\n        }\n        user.logOut()\n    }\n\n\n    // Smoke test to check that `refreshConnections` doesn't crash.\n    // Testing that it actually works is not feasible in a unit test.\n    @Test\n    fun refreshConnections() = looperThread.runBlocking {\n        RealmLog.setLevel(LogLevel.DEBUG)\n        app.sync.reconnect() // No Realms\n\n        // A single active Realm\n        val username = UUID.randomUUID().toString()\n        val password = \"password\"\n        val user: User = app.registerUserAndLogin(username, password)\n        val config: SyncConfiguration = configurationFactory.createSyncConfigurationBuilder(user, Constants.USER_REALM)\n                .testSchema(SyncStringOnly::class.java)\n                .build()\n        val realm = Realm.getInstance(config)\n        app.sync.reconnect()\n\n        // A single logged out Realm\n        realm.close()\n        app.sync.reconnect()\n        looperThread.testComplete()\n    }\n\n}\n"
  },
  {
    "path": "realm/realm-library/src/syncTestUtils/java/io/realm/objectserver/utils/Constants.java",
    "content": "/*\n * Copyright 2016 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\npackage io.realm.objectserver.utils;\n\npublic class Constants {\n\n    public static final String HOST = \"127.0.0.1\";\n    public static final String USER_REALM = \"realm://\" + HOST + \":9080/~/tests\";\n    public static final String USER_REALM_2 = \"realm://\" + HOST + \":9080/~/tests2\";\n    public static final String GLOBAL_REALM = \"realm://\" + HOST + \":9080/tests\";\n    public static final String USER_REALM_SECURE = \"realms://\" + HOST + \":9443/~/tests\";\n    public static final String SYNC_SERVER_URL = \"realm://\" + HOST + \":9080/~/tests\";\n    public static final String SYNC_SERVER_URL_2 = \"realm://\" + HOST + \":9080/~/tests2\";\n    public static final String DEFAULT_REALM = \"realm://\" + HOST + \":9080/default\";\n    public static final String AUTH_SERVER_URL = \"http://\" + HOST + \":9080/\";\n    public static final String AUTH_URL = AUTH_SERVER_URL + \"auth\";\n    public static final String APP_ID = \"mongdodb-realm-integrationtest-app\"; // FIXME: This doesn't work because the name changes\n}\n"
  },
  {
    "path": "realm/realm-library/src/syncTestUtils/java/io/realm/objectserver/utils/UserFactory.java",
    "content": "/*\n * Copyright 2016 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\npackage io.realm.objectserver.utils;\n\nimport android.os.Handler;\nimport android.os.HandlerThread;\n\nimport java.util.concurrent.CountDownLatch;\nimport java.util.concurrent.TimeUnit;\n\nimport io.realm.Realm;\nimport io.realm.RealmConfiguration;\nimport io.realm.TestHelper;\nimport io.realm.log.RealmLog;\n\n\n// Helper class to retrieve users with same IDs even in multi-processes.\n// Must be in `io.realm.objectserver` to work around package protected methods.\n// This require Realm.init() to be called before using this class.\npublic class UserFactory {\n    public static final String PASSWORD = \"myPassw0rd\";\n    // Since the integration tests need to use the same user for different processes, we create a new user name when the\n    // test starts and store it in a Realm. Then it can be retrieved for every process.\n    private String userName;\n    private static UserFactory instance;\n    private static RealmConfiguration configuration;\n\n    // Run initializer here to make it possible to ensure that Realm.init has been called.\n    // It is unpredictable when the static initializer is running\n    private static synchronized void initFactory(boolean forceReset) {\n        if (configuration == null || forceReset) {\n            RealmConfiguration.Builder builder = new RealmConfiguration.Builder().name(\"user-factory.realm\");\n            configuration = builder.build();\n        }\n    }\n\n    private UserFactory(String userName) {\n        this.userName = userName;\n    }\n\n    // The @Before method will be called before the looper tests finished. We need to find a better place to call this.\n    public static void clearInstance()  {\n        Realm realm = Realm.getInstance(configuration);\n        realm.beginTransaction();\n        realm.delete(UserFactoryStore.class);\n        realm.commitTransaction();\n        realm.close();\n    }\n\n    public static synchronized UserFactory getInstance() {\n        if (instance == null)  {\n            initFactory(false);\n            Realm realm = Realm.getInstance(configuration);\n            UserFactoryStore store = realm.where(UserFactoryStore.class).findFirst();\n            if (store == null || store.getUserName() == null) {\n                throw new IllegalStateException(\"Current user has not been set. Call resetInstance() first.\");\n            }\n\n            instance = new UserFactory(store.getUserName());\n            realm.close();\n        }\n        RealmLog.debug(\"UserFactory.getInstance, the default user is \" + instance.userName + \" .\");\n        return instance;\n    }\n\n    /**\n     * Blocking call that logs out all users\n     */\n    public static void logoutAllUsers() {\n        final CountDownLatch allUsersLoggedOut = new CountDownLatch(1);\n        final HandlerThread ht = new HandlerThread(\"LoggingOutUsersThread\");\n        ht.start();\n        Handler handler = new Handler(ht.getLooper());\n        handler.post(new Runnable() {\n            @Override\n            public void run() {\n//                Map<String, User> users = App.allUsers();\n//                for (User user : users.values()) {\n//                    App.logout(user);\n//                }\n                TestHelper.waitForNetworkThreadExecutorToFinish();\n                allUsersLoggedOut.countDown();\n            }\n        });\n        TestHelper.awaitOrFail(allUsersLoggedOut);\n        ht.quit();\n        try {\n            ht.join(TimeUnit.SECONDS.toMillis(TestHelper.SHORT_WAIT_SECS));\n        } catch (InterruptedException e) {\n            throw new AssertionError(\"LoggingOutUsersThread failed to finish in time\");\n        }\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/syncTestUtils/java/io/realm/objectserver/utils/UserFactoryStore.java",
    "content": "/*\n * Copyright 2017 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\npackage io.realm.objectserver.utils;\n\nimport io.realm.RealmObject;\n\n// Used by UserFactory. Storing current user name for testing to share the same user name across processes.\npublic class UserFactoryStore extends RealmObject {\n    private String userName;\n\n    public String getUserName() {\n        return userName;\n    }\n\n    public void setUserName(String userName) {\n        this.userName = userName;\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/syncTestUtils/kotlin/io/realm/RealmExt.kt",
    "content": "/*\n * Copyright 2020 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\npackage io.realm\n\nclass RealmExt {\n    companion object {}\n}\n\nfun RealmExt.Companion.testClearApplicationContext() {\n    BaseRealm.applicationContext = null;\n}\n"
  },
  {
    "path": "realm/realm-library/src/syncTestUtils/kotlin/io/realm/TestApp.kt",
    "content": "/*\n * Copyright 2020 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 */\npackage io.realm\n\nimport io.realm.internal.network.OkHttpNetworkTransport\nimport io.realm.internal.objectstore.OsJavaNetworkTransport\nimport io.realm.mongodb.App\nimport io.realm.mongodb.AppConfiguration\n\n/**\n * This class wraps various methods making it easier to create an App that can be used\n * for testing.\n *\n * NOTE: This class must remain in the [io.realm] package in order to work.\n */\nconst val SERVICE_NAME = \"BackingDB\"    // it comes from the test server's BackingDB/config.json\nconst val DATABASE_NAME = \"test_data\"   // same as above\nconst val TEST_APP_1 = \"testapp1\"       // Id for the default test app\nconst val TEST_APP_2 = \"testapp2\"       // ID for the 2nd test app, which is a direct copy of the default test app.\nconst val TEST_APP_3 = \"testapp3\"       // ID for the 3rd test app, which is configured for Flexible Sync instead of Partion-based sync\n\nclass TestApp(\n    networkTransport: OsJavaNetworkTransport? = null,\n    appName: String = TEST_APP_1,\n    builder: (AppConfiguration.Builder) -> AppConfiguration.Builder = { it }\n) : App(builder(configurationBuilder(appName)).build()) {\n\n    init {\n        if (networkTransport != null) {\n            this.setNetworkTransport(networkTransport)\n        }\n    }\n\n    companion object {\n        fun configurationBuilder(appName: String): AppConfiguration.Builder {\n            return AppConfiguration.Builder(initializeMongoDbRealm(appName))\n                .baseUrl(\"http://127.0.0.1:9090\")\n                .appName(\"MongoDB Realm Integration Tests\")\n                .appVersion(\"1.0.\")\n                .httpLogObfuscator(null)\n        }\n\n        // Initializes MongoDB Realm. Clears all local state and fetches the application ID.\n        private fun initializeMongoDbRealm(appName: String): String {\n            val transport = OkHttpNetworkTransport(null)\n            val response = transport.executeRequest(\n                \"get\",\n                \"http://127.0.0.1:8888/$appName\",\n                5000,\n                mapOf(),\n                \"\"\n            )\n            return when (response.httpResponseCode) {\n                200 -> response.body\n                else -> throw IllegalStateException(response.toString())\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/syncTestUtils/kotlin/io/realm/TestSyncConfigurationFactory.kt",
    "content": "/*\n * Copyright 2017 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 */\npackage io.realm\n\nimport io.realm.internal.OsRealmConfig\nimport io.realm.mongodb.User\nimport io.realm.mongodb.sync.Builder\nimport io.realm.mongodb.sync.SyncConfiguration\nimport io.realm.mongodb.sync.SyncConfigurationExt\nimport org.bson.BsonValue;\n\nimport io.realm.mongodb.sync.testSessionStopPolicy\n\n/**\n * Test rule used for creating SyncConfigurations. Will ensure that any Realm files are deleted when the\n * test ends.\n */\nclass TestSyncConfigurationFactory : TestRealmConfigurationFactory() {\n\n    fun createFlexibleSyncConfigurationBuilder(user: User): SyncConfiguration.Builder {\n        return SyncConfiguration.Builder(user)\n            .testSessionStopPolicy(OsRealmConfig.SyncSessionStopPolicy.IMMEDIATELY)\n    }\n\n    fun createSyncConfigurationBuilder(user: User): SyncConfiguration.Builder {\n        return SyncConfiguration.Builder(user, TestHelper.getRandomString(20))\n                .testSessionStopPolicy(OsRealmConfig.SyncSessionStopPolicy.IMMEDIATELY)\n    }\n\n    fun createSyncConfigurationBuilder(user: User, partitionValue: String): SyncConfiguration.Builder {\n        return SyncConfiguration.Builder(user, partitionValue)\n                .testSessionStopPolicy(OsRealmConfig.SyncSessionStopPolicy.IMMEDIATELY)\n    }\n\n    fun createSyncConfigurationBuilder(user: User, partitionValue: BsonValue): SyncConfiguration.Builder {\n        return SyncConfigurationExt.Builder(user, partitionValue)\n                .testSessionStopPolicy(OsRealmConfig.SyncSessionStopPolicy.IMMEDIATELY);\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/syncTestUtils/kotlin/io/realm/mongodb/SyncTestUtils.kt",
    "content": "/*\n * Copyright 2020 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 */\npackage io.realm.mongodb\n\nimport androidx.test.platform.app.InstrumentationRegistry\nimport io.realm.Realm\nimport io.realm.TestHelper\nimport io.realm.internal.network.OkHttpNetworkTransport\nimport io.realm.internal.objectstore.OsJavaNetworkTransport\nimport io.realm.log.LogLevel\nimport io.realm.log.RealmLog\nimport io.realm.mongodb.sync.SyncConfiguration\nimport java.io.File\nimport java.util.*\n\nclass SyncTestUtils {\n    companion object {\n        private var originalLogLevel = RealmLog.getLevel() // Should only be modified by prepareEnvironmentForTest and restoreEnvironmentAfterTest = 0\n        fun prepareEnvironmentForTest() {\n            Realm.init(InstrumentationRegistry.getInstrumentation().targetContext)\n            originalLogLevel = RealmLog.getLevel()\n            RealmLog.setLevel(LogLevel.DEBUG)\n        }\n\n        // Cleanup filesystem to make sure nothing lives for the next test.\n        // Failing to do so might lead to DIVERGENT_HISTORY errors being thrown if Realms from\n        // previous tests are being accessed.\n        fun deleteSyncFiles() {\n            val syncFiles = File(InstrumentationRegistry.getInstrumentation().context.filesDir, \"mongodb-realm\")\n            deleteFile(syncFiles)\n        }\n\n        private fun deleteFile(file: File) {\n            if (file.isDirectory) {\n                for (c in file.listFiles()) {\n                    deleteFile(c)\n                }\n            }\n            check(file.delete()) { \"Failed to delete file or directory: \" + file.absolutePath }\n        }\n\n        @JvmStatic\n        @JvmOverloads\n        fun createTestUser(app: App, userIdentifier: String = UUID.randomUUID().toString()): User {\n            app.osApp.networkTransport = object : OsJavaNetworkTransport() {\n                override fun sendRequestAsync(method: String,\n                                         url: String,\n                                         timeoutMs: Long,\n                                         headers: Map<String, String>,\n                                         body: String,\n                                         completionBlockPtr: Long) {\n                    val response = executeRequest(method, url, timeoutMs, headers, body)\n                    handleResponse(response, completionBlockPtr)\n                }\n\n                override fun executeRequest(\n                    method: String,\n                    url: String,\n                    timeoutMs: Long,\n                    headers: Map<String, String>,\n                    body: String\n                ): Response {\n                    when {\n                        url.endsWith(\"/login\") -> {\n                            return OkHttpNetworkTransport.Response.httpResponse(200, mapOf(), \"\"\"\n                                        {\n                                            \"access_token\": \"eyJhbGciOiJSUzI1NiIsImtpZCI6IjVlNjk2M2RmYWZlYTYzMjU0NTgxYzAyNiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1ODM5NjcyMDgsImlhdCI6MTU4Mzk2NTQwOCwiaXNzIjoiNWU2OTY0ZTBhZmVhNjMyNTQ1ODFjMWEzIiwic3RpdGNoX2RldklkIjoiMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwIiwic3RpdGNoX2RvbWFpbklkIjoiNWU2OTYzZGVhZmVhNjMyNTQ1ODFjMDI1Iiwic3ViIjoiNWU2OTY0ZTBhZmVhNjMyNTQ1ODFjMWExIiwidHlwIjoiYWNjZXNzIn0.J4mp8LnlsxTQRV_7W2Er4qY0tptR76PJGG1k6HSMmUYqgfpJC2Fnbcf1VCoebzoNolH2-sr8AHDVBBCyjxRjqoY9OudFHmWZKmhDV1ysxPP4XmID0nUuN45qJSO8QEAqoOmP1crXjrUZWedFw8aaCZE-bxYfvcDHyjBcbNKZqzawwUw2PyTOlrNjgs01k2J4o5a5XzYkEsJuzr4_8UqKW6zXvYj24UtqnqoYatW5EzpX63m2qig8AcBwPK4ZHb5wEEUdf4QZxkRY5QmTgRHP8SSqVUB_mkHgKaizC_tSB3E0BekaDfLyWVC1taAstXJNfzgFtLI86AzuXS2dCiCfqQ\",\n                                            \"refresh_token\": \"eyJhbGciOiJSUzI1NiIsImtpZCI6IjVlNjk2M2RmYWZlYTYzMjU0NTgxYzAyNiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1ODkxNDk0MDgsImlhdCI6MTU4Mzk2NTQwOCwic3RpdGNoX2RhdGEiOm51bGwsInN0aXRjaF9kZXZJZCI6IjAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMCIsInN0aXRjaF9kb21haW5JZCI6IjVlNjk2M2RlYWZlYTYzMjU0NTgxYzAyNSIsInN0aXRjaF9pZCI6IjVlNjk2NGUwYWZlYTYzMjU0NTgxYzFhMyIsInN0aXRjaF9pZGVudCI6eyJpZCI6IjVlNjk2NGUwYWZlYTYzMjU0NTgxYzFhMC1oaWF2b3ZkbmJxbGNsYXBwYnl1cmJpaW8iLCJwcm92aWRlcl90eXBlIjoiYW5vbi11c2VyIiwicHJvdmlkZXJfaWQiOiI1ZTY5NjNlMGFmZWE2MzI1NDU4MWMwNGEifSwic3ViIjoiNWU2OTY0ZTBhZmVhNjMyNTQ1ODFjMWExIiwidHlwIjoicmVmcmVzaCJ9.FhLdpmL48Mw0SyUKWuaplz3wfeS8TCO8S7I9pIJenQww9nPqQ7lIvykQxjCCtinGvsZIJKt_7R31xYCq4Jp53Nw81By79IwkXtO7VXHPsXXZG5_2xV-s0u44e85sYD5su_H-xnx03sU2piJbWJLSB8dKu3rMD4mO-S0HNXCCAty-JkYKSaM2-d_nS8MNb6k7Vfm7y69iz_uwHc-bb_1rPg7r827K6DEeEMF41Hy3Nx1kCdAUOM9-6nYv3pZSU1PFrGYi2uyTXPJ7R7HigY5IGHWd0hwONb_NUr4An2omqfvlkLEd77ut4V9m6mExFkoKzRz7shzn-IGkh3e4h7ECGA\",\n                                            \"user_id\": \"$userIdentifier\",\n                                            \"device_id\": \"000000000000000000000000\"\n                                        }                    \n                                        \"\"\".trimIndent())\n                        }\n                        url.endsWith(\"/auth/profile\") -> {\n                            return OkHttpNetworkTransport.Response.httpResponse(200, mapOf(), \"\"\"\n                                        {\n                                            \"user_id\": \"$userIdentifier\",\n                                            \"domain_id\": \"000000000000000000000000\",\n                                            \"identities\": [\n                                                {\n                                                    \"id\": \"5e68f51ade5ba998bb17500d\",\n                                                    \"provider_type\": \"local-userpass\",\n                                                    \"provider_id\": \"000000000000000000000003\",\n                                                    \"provider_data\": {\n                                                        \"email\": \"unique_user@domain.com\"\n                                                    }\n                                                }\n                                            ],\n                                            \"data\": {\n                                                \"email\": \"unique_user@domain.com\"\n                                            },\n                                            \"type\": \"normal\",\n                                            \"roles\": [\n                                                {\n                                                    \"role_name\": \"GROUP_OWNER\",\n                                                    \"group_id\": \"5e68f51e087b1b33a53f56d5\"\n                                                }\n                                            ]\n                                        }\n                                        \"\"\".trimIndent())\n                        }\n                        url.endsWith(\"/location\") -> {\n                            return OkHttpNetworkTransport.Response.httpResponse(200, mapOf(), \"\"\"\n                                        { \"deployment_model\" : \"GLOBAL\",\n                                          \"location\": \"US-VA\", \n                                          \"hostname\": \"http://localhost:9090\",\n                                          \"ws_hostname\": \"ws://localhost:9090\"\n                                        }\n                                        \"\"\".trimIndent())\n                        }\n                        else -> {\n                            throw IllegalStateException(\"Unsupported URL: $url\")\n                        }\n                    }\n                }\n\n                override fun sendStreamingRequest(request: Request): Response {\n                    TODO(\"Not yet implemented\")\n                }\n            }\n            val user = app.login(Credentials.emailPassword(TestHelper.getRandomEmail(), \"123456\"))\n            app.osApp.setOriginalNetworkTransport()\n            return user\n        }\n\n        // Fully synchronize a Realm with the server by making sure that all changes are uploaded\n        // and downloaded again.\n        fun syncRealm(realm: Realm) {\n            val config = realm.getConfiguration() as SyncConfiguration\n            val session = config.user.app.sync.getSession(config)\n            try {\n                session.uploadAllLocalChanges()\n                session.downloadAllServerChanges()\n            } catch (e: InterruptedException) {\n                throw AssertionError(e)\n            }\n            realm.refresh()\n        }\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/syncTestUtils/kotlin/io/realm/mongodb/sync/SyncConfigurationExt.kt",
    "content": "/*\n * Copyright 2020 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\npackage io.realm.mongodb.sync\n\nimport io.realm.RealmModel\nimport io.realm.internal.OsRealmConfig\nimport io.realm.mongodb.User\nimport org.bson.BsonValue\n\nclass SyncConfigurationExt {\n    companion object\n}\n\nfun SyncConfiguration.testRealmExists(): Boolean{\n    return this.realmExists()\n}\n\n// Added to expose Builder(User, BsonValue) outside io.realm.mongodb.sync package for test\nfun SyncConfigurationExt.Companion.Builder(user: User, partitionValue: BsonValue): SyncConfiguration.Builder {\n    return SyncConfiguration.Builder(user, partitionValue)\n}\n\n// Added to expose schema outside io.realm.mongodb.sync package for test\nfun SyncConfiguration.Builder.testSchema(firstClass: Class<out RealmModel>, vararg x: Class<out RealmModel> ) : SyncConfiguration.Builder {\n    return this.schema(firstClass, *x)\n}\n\n// Added to expose sesssionStopPolicy outside io.realm.mongodb.sync package for test\nfun SyncConfiguration.Builder.testSessionStopPolicy(policy: OsRealmConfig.SyncSessionStopPolicy): SyncConfiguration.Builder {\n    return this.sessionStopPolicy(policy)\n}\n"
  },
  {
    "path": "realm/realm-library/src/testObjectServer/kotlin/io/realm/ObfuscatorHelper.kt",
    "content": "/*\n * Copyright 2020 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\npackage io.realm\n\nobject ObfuscatorHelper {\n    const val IRRELEVANT_INPUT = \"\"\"{\"blahblahblah\":\"blehblehbleh\"}\"\"\"\n\n    val API_KEY_ORIGINAL_INPUT = \"\"\"\n{\n  \"blahblahblah\":\"blehblehbleh\",\n  \"key\":\"my_key\",\n  \"something\":\"random\"\n}\n\"\"\".trimIndent()\n    val API_KEY_OBFUSCATED_OUTPUT = \"\"\"\n{\n  \"blahblahblah\":\"blehblehbleh\",\n  \"key\":\"***\",\n  \"something\":\"random\"\n}\n\"\"\".trimIndent()\n\n    val EMAIL_PASSWORD_ORIGINAL_INPUT = \"\"\"\n{\n  \"blahblahblah\":\"blehblehbleh\",\n  \"username\":\"my_username\",\n  \"password\":\"123456\",\n  \"something\":\"random\"\n}\n\"\"\".trimIndent()\n    val EMAIL_PASSWORD_OBFUSCATED_OUTPUT = \"\"\"\n{\n  \"blahblahblah\":\"blehblehbleh\",\n  \"username\":\"***\",\n  \"password\":\"***\",\n  \"something\":\"random\"\n}\n\"\"\".trimIndent()\n\n    val CUSTOM_FUNCTION_ORIGINAL_INPUT = \"\"\"\n{\n  \"mail\":\"myfakemail@mongodb.com\",\n  \"id\":{\n    \"{${'$'}}numberInt\": 666\"\n  },\n  \"options\":{\n    \"device\":{\n      \"appVersion\":\"1.0.\",\n      \"appId\":\"realm-sdk-integration-tests-grbrc\",\n      \"platform\":\"android\",\n      \"platformVersion\":\"10\",\n      \"sdkVersion\":\"10.0.0-BETA.5-SNAPSHOT\"\n    }\n  }\n}\n\"\"\".trimStartMultiline()\n    val CUSTOM_FUNCTION_OBFUSCATED_OUTPUT = \"\"\"\n{\n  \"functionArgs\":\"***\",\n  \"options\":{\n    \"device\":{\n      \"appVersion\":\"1.0.\",\n      \"appId\":\"realm-sdk-integration-tests-grbrc\",\n      \"platform\":\"android\",\n      \"platformVersion\":\"10\",\n      \"sdkVersion\":\"10.0.0-BETA.5-SNAPSHOT\"\n    }\n  }\n}\n\"\"\".trimStartMultiline()\n\n    val TOKEN_ORIGINAL_INPUT_GENERIC = \"\"\"\n{\n  \"blahblahblah\":\"blehblehbleh\",\n  \"token\":\"my_token\",\n  \"something\":\"random\"\n}\n\"\"\".trimIndent()\n    val TOKEN_ORIGINAL_INPUT_APPLE = \"\"\"\n{\n  \"blahblahblah\":\"blehblehbleh\",\n  \"id_token\":\"my_provider\",\n  \"something\":\"random\"\n}\n\"\"\".trimIndent()\n    val TOKEN_ORIGINAL_INPUT_FACEBOOK = \"\"\"\n{\n  \"blahblahblah\":\"blehblehbleh\",\n  \"accessToken\":\"my_access_token\",\n  \"something\":\"random\"\n}\n\"\"\".trimIndent()\n    val TOKEN_ORIGINAL_INPUT_GOOGLE = \"\"\"\n{\n  \"blahblahblah\":\"blehblehbleh\",\n  \"authCode\":\"my_authCode\",\n  \"something\":\"random\"\n}\n\"\"\".trimIndent()\n    val TOKEN_OBFUSCATED_OUTPUT_GENERIC = \"\"\"\n{\n  \"blahblahblah\":\"blehblehbleh\",\n  \"token\":\"***\",\n  \"something\":\"random\"\n}\n\"\"\".trimIndent()\n    val TOKEN_OBFUSCATED_OUTPUT_APPLE = \"\"\"\n{\n  \"blahblahblah\":\"blehblehbleh\",\n  \"id_token\":\"***\",\n  \"something\":\"random\"\n}\n\"\"\".trimIndent()\n    val TOKEN_OBFUSCATED_OUTPUT_FACEBOOK = \"\"\"\n{\n  \"blahblahblah\":\"blehblehbleh\",\n  \"accessToken\":\"***\",\n  \"something\":\"random\"\n}\n\"\"\".trimIndent()\n    val TOKEN_OBFUSCATED_OUTPUT_GOOGLE = \"\"\"\n{\n  \"blahblahblah\":\"blehblehbleh\",\n  \"authCode\":\"***\",\n  \"something\":\"random\"\n}\n\"\"\".trimIndent()\n\n    private fun String.trimStartMultiline(): String {\n        return this.split(\"\\n\").joinToString(separator = \"\") { it.trimStart() }\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/testObjectServer/kotlin/io/realm/internal/log/obfuscator/ApiKeyObfuscatorTest.kt",
    "content": "/*\n * Copyright 2020 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 */\npackage io.realm.internal.log.obfuscator\n\nimport io.realm.ObfuscatorHelper\nimport org.junit.Test\nimport kotlin.test.assertEquals\nimport kotlin.test.assertFailsWith\n\nclass ApiKeyObfuscatorTest {\n\n    @Test\n    fun obfuscate() {\n        ApiKeyObfuscator.obfuscator()\n                .obfuscate(ObfuscatorHelper.API_KEY_ORIGINAL_INPUT)\n                .let { assertEquals(ObfuscatorHelper.API_KEY_OBFUSCATED_OUTPUT, it) }\n    }\n\n    @Test\n    fun obfuscate_doesNothing() {\n        ApiKeyObfuscator.obfuscator()\n                .obfuscate(ObfuscatorHelper.IRRELEVANT_INPUT)\n                .let { assertEquals(ObfuscatorHelper.IRRELEVANT_INPUT, it) }\n    }\n\n    @Test\n    fun obfuscate_fails() {\n        assertFailsWith<NullPointerException> {\n            ApiKeyObfuscator.obfuscator().obfuscate(null)\n        }\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/testObjectServer/kotlin/io/realm/internal/log/obfuscator/CustomFunctionObfuscatorTest.kt",
    "content": "/*\n * Copyright 2020 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 */\npackage io.realm.internal.log.obfuscator\n\nimport io.realm.ObfuscatorHelper\nimport org.junit.Test\nimport kotlin.test.assertEquals\nimport kotlin.test.assertFailsWith\n\nclass CustomFunctionObfuscatorTest {\n\n    @Test\n    fun obfuscate() {\n        CustomFunctionObfuscator.obfuscator()\n                .obfuscate(ObfuscatorHelper.CUSTOM_FUNCTION_ORIGINAL_INPUT)\n                .let { assertEquals(ObfuscatorHelper.CUSTOM_FUNCTION_OBFUSCATED_OUTPUT, it) }\n    }\n\n    @Test\n    fun obfuscate_doesNothing() {\n        CustomFunctionObfuscator.obfuscator()\n                .obfuscate(ObfuscatorHelper.IRRELEVANT_INPUT)\n                .let { assertEquals(ObfuscatorHelper.IRRELEVANT_INPUT, it) }\n    }\n\n    @Test\n    fun obfuscate_fails() {\n        assertFailsWith<NullPointerException> {\n            CustomFunctionObfuscator.obfuscator().obfuscate(null)\n        }\n    }\n}\n\n\n"
  },
  {
    "path": "realm/realm-library/src/testObjectServer/kotlin/io/realm/internal/log/obfuscator/EmailPasswordObfuscatorTest.kt",
    "content": "/*\n * Copyright 2020 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 */\npackage io.realm.internal.log.obfuscator\n\nimport io.realm.ObfuscatorHelper\nimport org.junit.Test\nimport kotlin.test.assertEquals\nimport kotlin.test.assertFailsWith\n\nclass EmailPasswordObfuscatorTest {\n\n    @Test\n    fun obfuscate() {\n        EmailPasswordObfuscator.obfuscator()\n                .obfuscate(ObfuscatorHelper.EMAIL_PASSWORD_ORIGINAL_INPUT)\n                .let { assertEquals(ObfuscatorHelper.EMAIL_PASSWORD_OBFUSCATED_OUTPUT, it) }\n    }\n\n    @Test\n    fun obfuscate_doesNothing() {\n        EmailPasswordObfuscator.obfuscator()\n                .obfuscate(ObfuscatorHelper.IRRELEVANT_INPUT)\n                .let { assertEquals(ObfuscatorHelper.IRRELEVANT_INPUT, it) }\n    }\n\n    @Test\n    fun obfuscate_fails() {\n        assertFailsWith<NullPointerException> {\n            EmailPasswordObfuscator.obfuscator().obfuscate(null)\n        }\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/testObjectServer/kotlin/io/realm/internal/log/obfuscator/TokenObfuscatorTest.kt",
    "content": "/*\n * Copyright 2020 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 */\npackage io.realm.internal.log.obfuscator\n\nimport io.realm.ObfuscatorHelper\nimport org.junit.Test\nimport kotlin.test.assertEquals\nimport kotlin.test.assertFailsWith\n\nclass TokenObfuscatorTest {\n\n    @Test\n    fun obfuscate() {\n        TokenObfuscator.obfuscator()\n                .obfuscate(ObfuscatorHelper.TOKEN_ORIGINAL_INPUT_GENERIC)\n                .let { assertEquals(ObfuscatorHelper.TOKEN_OBFUSCATED_OUTPUT_GENERIC, it) }\n        TokenObfuscator.obfuscator()\n                .obfuscate(ObfuscatorHelper.TOKEN_ORIGINAL_INPUT_APPLE)\n                .let { assertEquals(ObfuscatorHelper.TOKEN_OBFUSCATED_OUTPUT_APPLE, it) }\n        TokenObfuscator.obfuscator()\n                .obfuscate(ObfuscatorHelper.TOKEN_ORIGINAL_INPUT_FACEBOOK)\n                .let { assertEquals(ObfuscatorHelper.TOKEN_OBFUSCATED_OUTPUT_FACEBOOK, it) }\n        TokenObfuscator.obfuscator()\n                .obfuscate(ObfuscatorHelper.TOKEN_ORIGINAL_INPUT_GOOGLE)\n                .let { assertEquals(ObfuscatorHelper.TOKEN_OBFUSCATED_OUTPUT_GOOGLE, it) }\n    }\n\n    @Test\n    fun obfuscate_doesNothing() {\n        TokenObfuscator.obfuscator()\n                .obfuscate(ObfuscatorHelper.IRRELEVANT_INPUT)\n                .let { assertEquals(ObfuscatorHelper.IRRELEVANT_INPUT, it) }\n    }\n\n    @Test\n    fun obfuscate_fails() {\n        assertFailsWith<NullPointerException> {\n            TokenObfuscator.obfuscator().obfuscate(null)\n        }\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/testObjectServer/kotlin/io/realm/mongodb/log/obfuscator/HttpLogObfuscatorTest.kt",
    "content": "/*\n * Copyright 2020 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 */\npackage io.realm.mongodb.log.obfuscator\n\nimport io.realm.ObfuscatorHelper\nimport io.realm.mongodb.AppConfiguration\nimport org.junit.Test\nimport kotlin.test.assertEquals\n\nconst val IRRELEVANT_INPUT = \"\"\"{\"blahblahblah\":\"blehblehbleh\"}\"\"\"\nconst val FEATURE = \"providers\"\n\nclass HttpLogObfuscatorTest {\n\n    private val apiKeyUrlSegments = listOf(FEATURE, \"api-key\")\n    private val customFunctionUrlSegments = listOf(FEATURE, \"custom-function\")\n    private val emailPasswordUrlSegments = listOf(FEATURE, \"local-userpass\")\n    private val tokenUrlSegmentsApple = listOf(FEATURE, \"oauth2-apple\")\n    private val tokenUrlSegmentsFacebook = listOf(FEATURE, \"oauth2-facebook\")\n    private val tokenUrlSegmentsGoogle = listOf(FEATURE, \"oauth2-google\")\n\n    private val loginObfuscators = AppConfiguration.loginObfuscators\n\n    @Test\n    fun obfuscate_nothing() {\n        with(HttpLogObfuscator(FEATURE, mapOf())) {\n            assertEquals(IRRELEVANT_INPUT, obfuscate(listOf(), IRRELEVANT_INPUT))\n        }\n    }\n\n    @Test\n    fun obfuscate_apiKey() {\n        with(HttpLogObfuscator(FEATURE, loginObfuscators)) {\n            assertEquals(ObfuscatorHelper.API_KEY_OBFUSCATED_OUTPUT, obfuscate(apiKeyUrlSegments, ObfuscatorHelper.API_KEY_ORIGINAL_INPUT))\n        }\n    }\n\n    @Test\n    fun obfuscate_customFunction() {\n        with(HttpLogObfuscator(FEATURE, loginObfuscators)) {\n            assertEquals(ObfuscatorHelper.CUSTOM_FUNCTION_OBFUSCATED_OUTPUT, obfuscate(customFunctionUrlSegments, ObfuscatorHelper.CUSTOM_FUNCTION_ORIGINAL_INPUT))\n        }\n    }\n\n    @Test\n    fun obfuscate_emailPassword() {\n        with(HttpLogObfuscator(FEATURE, loginObfuscators)) {\n            assertEquals(ObfuscatorHelper.EMAIL_PASSWORD_OBFUSCATED_OUTPUT, obfuscate(emailPasswordUrlSegments, ObfuscatorHelper.EMAIL_PASSWORD_ORIGINAL_INPUT))\n        }\n    }\n\n    @Test\n    fun obfuscate_tokenApple() {\n        with(HttpLogObfuscator(FEATURE, loginObfuscators)) {\n            assertEquals(ObfuscatorHelper.TOKEN_OBFUSCATED_OUTPUT_APPLE, obfuscate(tokenUrlSegmentsApple, ObfuscatorHelper.TOKEN_ORIGINAL_INPUT_APPLE))\n        }\n    }\n\n    @Test\n    fun obfuscate_tokenFacebook() {\n        with(HttpLogObfuscator(FEATURE, loginObfuscators)) {\n            assertEquals(ObfuscatorHelper.TOKEN_OBFUSCATED_OUTPUT_FACEBOOK, obfuscate(tokenUrlSegmentsFacebook, ObfuscatorHelper.TOKEN_ORIGINAL_INPUT_FACEBOOK))\n        }\n    }\n\n    @Test\n    fun obfuscate_tokenGoogle() {\n        with(HttpLogObfuscator(FEATURE, loginObfuscators)) {\n            assertEquals(ObfuscatorHelper.TOKEN_OBFUSCATED_OUTPUT_GOOGLE, obfuscate(tokenUrlSegmentsGoogle, ObfuscatorHelper.TOKEN_ORIGINAL_INPUT_GOOGLE))\n        }\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/testUtils/java/io/realm/TestHelper.java",
    "content": "/*\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\npackage io.realm;\n\nimport android.content.Context;\nimport android.content.res.AssetManager;\nimport android.os.Build;\nimport android.os.Looper;\n\nimport org.bson.types.Decimal128;\nimport org.bson.types.ObjectId;\nimport org.junit.Assert;\n\nimport java.io.BufferedReader;\nimport java.io.ByteArrayInputStream;\nimport java.io.File;\nimport java.io.IOException;\nimport java.io.InputStream;\nimport java.io.InputStreamReader;\nimport java.lang.reflect.Constructor;\nimport java.lang.reflect.Field;\nimport java.lang.reflect.InvocationTargetException;\nimport java.math.BigDecimal;\nimport java.nio.charset.Charset;\nimport java.security.MessageDigest;\nimport java.security.NoSuchAlgorithmException;\nimport java.security.SecureRandom;\nimport java.util.Date;\nimport java.util.Iterator;\nimport java.util.Locale;\nimport java.util.NoSuchElementException;\nimport java.util.Random;\nimport java.util.UUID;\nimport java.util.concurrent.ArrayBlockingQueue;\nimport java.util.concurrent.CountDownLatch;\nimport java.util.concurrent.ExecutorService;\nimport java.util.concurrent.ThreadPoolExecutor;\nimport java.util.concurrent.TimeUnit;\nimport java.util.concurrent.atomic.AtomicReference;\n\nimport javax.annotation.Nonnull;\nimport javax.annotation.Nullable;\n\nimport androidx.test.platform.app.InstrumentationRegistry;\nimport io.realm.entities.AllTypesPrimaryKey;\nimport io.realm.entities.AnnotationIndexTypes;\nimport io.realm.entities.BacklinksSource;\nimport io.realm.entities.BacklinksTarget;\nimport io.realm.entities.NullTypes;\nimport io.realm.entities.PrimaryKeyAsBoxedByte;\nimport io.realm.entities.PrimaryKeyAsBoxedInteger;\nimport io.realm.entities.PrimaryKeyAsBoxedLong;\nimport io.realm.entities.PrimaryKeyAsBoxedShort;\nimport io.realm.entities.PrimaryKeyAsString;\nimport io.realm.internal.OsObject;\nimport io.realm.internal.OsResults;\nimport io.realm.internal.OsSharedRealm;\nimport io.realm.internal.Table;\nimport io.realm.internal.Util;\nimport io.realm.internal.async.RealmThreadPoolExecutor;\nimport io.realm.log.LogLevel;\nimport io.realm.log.RealmLogger;\n\nimport static junit.framework.Assert.assertEquals;\nimport static junit.framework.Assert.fail;\n\npublic class TestHelper {\n    public static final int VERY_SHORT_WAIT_SECS = 1;\n    public static final int SHORT_WAIT_SECS = 10;\n    public static final int STANDARD_WAIT_SECS = 300;\n\n    private static final Charset UTF_8 = Charset.forName(\"UTF-8\");\n    private static final SecureRandom RANDOM = new SecureRandom();\n\n    public static class ExpectedCountCallback implements RealmCache.Callback {\n\n        private int expectedCount;\n\n        ExpectedCountCallback(int expectedCount) {\n            this.expectedCount = expectedCount;\n        }\n\n        @Override\n        public void onResult(int count) {\n            assertEquals(expectedCount, count);\n        }\n    }\n\n    public static RealmFieldType getColumnType(Object o) {\n        if (o instanceof Boolean) {\n            return RealmFieldType.BOOLEAN;\n        }\n        if (o instanceof String) {\n            return RealmFieldType.STRING;\n        }\n        if (o instanceof Long) {\n            return RealmFieldType.INTEGER;\n        }\n        if (o instanceof Float) {\n            return RealmFieldType.FLOAT;\n        }\n        if (o instanceof Double) {\n            return RealmFieldType.DOUBLE;\n        }\n        if (o instanceof Date) {\n            return RealmFieldType.DATE;\n        }\n        if (o instanceof byte[]) {\n            return RealmFieldType.BINARY;\n        }\n        if (o instanceof Decimal128) {\n            return RealmFieldType.DECIMAL128;\n        }\n        if (o instanceof ObjectId) {\n            return RealmFieldType.OBJECT_ID;\n        }\n\n        throw new IllegalArgumentException(\"Unsupported type\");\n    }\n\n    /**\n     * Appends the specified row to the end of the table. For internal testing usage only.\n     *\n     * @param table the table where the object to be added.\n     * @param values values.\n     * @return the row index of the appended row.\n     * @deprecated Remove this functions since it doesn't seem to be useful. And this function does deal with tables\n     * with primary key defined well. Primary key has to be set with `setXxxUnique` as the first thing to do after row\n     * added.\n     */\n    @Deprecated\n    public static long addRowWithValues(Table table, long[] columnKeys, Object[] values) {\n        long rowKey = OsObject.createRow(table);\n\n        // Checks values types.\n        int columns = (int) table.getColumnCount();\n        if (columns != values.length) {\n            throw new IllegalArgumentException(\"The number of value parameters (\" +\n                    String.valueOf(values.length) +\n                    \") does not match the number of columns in the table (\" +\n                    String.valueOf(columns) + \").\");\n        }\n        RealmFieldType[] colTypes = new RealmFieldType[columns];\n        for (int i = 0; i < columnKeys.length; i++) {\n            Object value = values[i];\n            RealmFieldType colType = table.getColumnType(columnKeys[i]);\n            colTypes[i] = colType;\n            if (!colType.isValid(value)) {\n                // String representation of the provided value type.\n                String providedType = value.getClass().toString();\n\n                throw new IllegalArgumentException(\"Invalid argument no \" + (i + 1) +\n                        \". Expected a value compatible with column type \" + colType + \", but got \" + providedType + \".\");\n            }\n        }\n\n        // Inserts values.\n        for (int i = 0; i < columnKeys.length; i++) {\n            Object value = values[i];\n            switch (colTypes[i]) {\n                case BOOLEAN:\n                    if (value == null) {\n                        table.setNull(columnKeys[i], rowKey, false);\n                    } else {\n                        table.setBoolean(columnKeys[i], rowKey, (Boolean) value, false);\n                    }\n                    break;\n                case INTEGER:\n                    if (value == null) {\n                        table.setNull(columnKeys[i], rowKey, false);\n                    } else {\n                        long longValue = ((Number) value).longValue();\n                        table.setLong(columnKeys[i], rowKey, longValue, false);\n                    }\n                    break;\n                case FLOAT:\n                    if (value == null) {\n                        table.setNull(columnKeys[i], rowKey, false);\n                    } else {\n                        table.setFloat(columnKeys[i], rowKey, (Float) value, false);\n                    }\n                    break;\n                case DOUBLE:\n                    if (value == null) {\n                        table.setNull(columnKeys[i], rowKey, false);\n                    } else {\n                        table.setDouble(columnKeys[i], rowKey, (Double) value, false);\n                    }\n                    break;\n                case STRING:\n                    if (value == null) {\n                        table.setNull(columnKeys[i], rowKey, false);\n                    } else {\n                        table.setString(columnKeys[i], rowKey, (String) value, false);\n                    }\n                    break;\n                case DATE:\n                    if (value == null) {\n                        table.setNull(columnKeys[i], rowKey, false);\n                    } else {\n                        table.setDate(columnKeys[i], rowKey, (Date) value, false);\n                    }\n                    break;\n                case BINARY:\n                    if (value == null) {\n                        table.setNull(columnKeys[i], rowKey, false);\n                    } else {\n                        table.setBinaryByteArray(columnKeys[i], rowKey, (byte[]) value, false);\n                    }\n                    break;\n                case DECIMAL128:\n                    if (value == null) {\n                        table.setNull(columnKeys[i], rowKey, false);\n                    } else {\n                        table.setDecimal128(columnKeys[i], rowKey, (Decimal128) value, false);\n                    }\n                    break;\n                case OBJECT_ID:\n                    if (value == null) {\n                        table.setNull(columnKeys[i], rowKey, false);\n                    } else {\n                        table.setObjectId(columnKeys[i], rowKey, (ObjectId) value, false);\n                    }\n                    break;\n                default:\n                    throw new RuntimeException(\"Unexpected columnType: \" + String.valueOf(colTypes[i]));\n            }\n        }\n        return rowKey;\n    }\n\n    /**\n     * Creates an empty table whose name is \"temp\" with 1 column of all our supported column types, currently 7 columns.\n     *\n     * @param sharedRealm A {@link OsSharedRealm} where the table is created.\n     * @return created table.\n     */\n    public static Table createTableWithAllColumnTypes(OsSharedRealm sharedRealm) {\n        return createTableWithAllColumnTypes(sharedRealm, \"temp\");\n    }\n\n    /**\n     * Creates an empty table with 1 column of all our supported column types, currently 7 columns.\n     *\n     * @param sharedRealm A {@link OsSharedRealm} where the table is created.\n     * @param name name of the table.\n     * @return created table.\n     */\n    @SuppressWarnings(\"WeakerAccess\")\n    public static Table createTableWithAllColumnTypes(OsSharedRealm sharedRealm,\n            @SuppressWarnings(\"SameParameterValue\") String name) {\n        boolean wasInTransaction = sharedRealm.isInTransaction();\n        if (!wasInTransaction) {\n            sharedRealm.beginTransaction();\n        }\n        try {\n            Table t = sharedRealm.createTable(name);\n\n            t.addColumn(RealmFieldType.BINARY, \"binary\");\n            t.addColumn(RealmFieldType.BOOLEAN, \"boolean\");\n            t.addColumn(RealmFieldType.DATE, \"date\");\n            t.addColumn(RealmFieldType.DOUBLE, \"double\");\n            t.addColumn(RealmFieldType.FLOAT, \"float\");\n            t.addColumn(RealmFieldType.INTEGER, \"long\");\n            t.addColumn(RealmFieldType.STRING, \"string\");\n            t.addColumn(RealmFieldType.DECIMAL128, \"decimal128\");\n            t.addColumn(RealmFieldType.OBJECT_ID, \"object_id\");\n\n            return t;\n        } catch (RuntimeException e) {\n            if (!wasInTransaction) {\n                sharedRealm.cancelTransaction();\n            }\n            throw e;\n        } finally {\n            if (!wasInTransaction && sharedRealm.isInTransaction()) {\n                sharedRealm.commitTransaction();\n            }\n        }\n    }\n\n    public static Table createTable(OsSharedRealm sharedRealm, String name) {\n        return createTable(sharedRealm, name, null);\n    }\n\n    public interface AdditionalTableSetup {\n        void execute(Table table);\n    }\n\n    public static Table createTable(OsSharedRealm sharedRealm, String name, @Nullable AdditionalTableSetup additionalSetup) {\n        boolean wasInTransaction = sharedRealm.isInTransaction();\n        if (!wasInTransaction) {\n            sharedRealm.beginTransaction();\n        }\n        try {\n            Table table = sharedRealm.createTable(name);\n            if (additionalSetup != null) {\n                additionalSetup.execute(table);\n            }\n            return table;\n        } catch (RuntimeException e) {\n            if (!wasInTransaction) {\n                sharedRealm.cancelTransaction();\n            }\n            throw e;\n        } finally {\n            if (!wasInTransaction && sharedRealm.isInTransaction()) {\n                sharedRealm.commitTransaction();\n            }\n        }\n    }\n\n    public static String streamToString(InputStream in) throws IOException {\n        BufferedReader br = null;\n        StringBuilder sb = new StringBuilder();\n        String line;\n        try {\n            br = new BufferedReader(new InputStreamReader(in, UTF_8));\n            while ((line = br.readLine()) != null) {\n                sb.append(line);\n            }\n        } finally {\n            if (br != null) {\n                br.close();\n            }\n        }\n\n        return sb.toString();\n    }\n\n    public static InputStream stringToStream(String str) {\n        return new ByteArrayInputStream(str.getBytes(UTF_8));\n    }\n\n    // Returns a random key used by encrypted Realms.\n    public static byte[] getRandomKey() {\n        byte[] key = new byte[Realm.ENCRYPTION_KEY_LENGTH];\n        RANDOM.nextBytes(key);\n        return key;\n    }\n\n    public static int getRandomId() {\n        return Math.abs(RANDOM.nextInt());\n    }\n\n    public static String getRandomEmail() {\n        StringBuilder sb = new StringBuilder(UUID.randomUUID().toString().toLowerCase());\n        sb.append('@');\n        sb.append(\"10gen.com\");\n        return sb.toString();\n    }\n\n    // Returns a random key from the given seed. Used by encrypted Realms.\n    public static byte[] getRandomKey(long seed) {\n        byte[] key = new byte[Realm.ENCRYPTION_KEY_LENGTH];\n        new Random(seed).nextBytes(key);\n        return key;\n    }\n\n    /**\n     * Returns a RealmLogger that will fail if it is asked to log a message above a certain level.\n     *\n     * @param failureLevel level at which the unit test will fail: {@see Log}.\n     * @return RealmLogger implementation\n     */\n    public static RealmLogger getFailureLogger(final int failureLevel) {\n        return new RealmLogger() {\n            private void failIfEqualOrAbove(int logLevel) {\n                if (logLevel >= failureLevel) {\n                    fail(\"Message logged that was above valid level: \" + logLevel + \" >= \" + failureLevel);\n                }\n            }\n\n            @Override\n            public void log(int level, String tag, Throwable throwable, String message) {\n                failIfEqualOrAbove(level);\n            }\n        };\n    }\n\n    // Generate a random string with only capital letters which is always a valid class/field name.\n    public static String getRandomString(int length) {\n        Random r = new Random();\n        StringBuilder sb = new StringBuilder(length);\n        for (int i = 0; i < length; i++) {\n            sb.append((char) (r.nextInt(26) + 'A')); // Restrict to capital letters\n        }\n        return sb.toString();\n    }\n\n    public static class MessageBuffer {\n\n        private final int size;\n\n        private int writeIndex = 0;\n        private int availablePos = 0;\n\n        public String[] entries;\n\n        public MessageBuffer(int size) {\n            this.size = size;\n            this.entries = new String[size];\n        }\n\n        public void put(String entry) {\n            if (availablePos < size) {\n                if (writeIndex >= size) {\n                    writeIndex = 0;\n                }\n                entries[writeIndex] = entry;\n                writeIndex++;\n                availablePos++;\n            }\n        }\n\n        public String take() {\n            if (availablePos == 0) {\n                return null;\n            }\n            int nextAvailable = writeIndex - availablePos;\n            if (nextAvailable < 0) {\n                nextAvailable += size;\n            }\n            String nextObj = entries[nextAvailable];\n            availablePos--;\n            return nextObj;\n        }\n\n        public Iterator<String> iterator() {\n            return new Iterator<String>() {\n\n                private int pos = -1;\n\n                @Override\n                public boolean hasNext() {\n                    return pos + 1 < size;\n                }\n\n                @Override\n                public String next() {\n                    pos = pos + 1;\n                    if (pos > size) {\n                        throw new NoSuchElementException(\"Went beyond message buffer capacity.\");\n                    }\n                    return entries[pos];\n                }\n            };\n        }\n    }\n\n    /**\n     * Returns a naive logger that can be used to test the values that are sent to the logger.\n     */\n    public static class TestLogger implements RealmLogger {\n\n        private final int minimumLevel;\n        public String message;\n        public Throwable throwable;\n\n        // Store just a few log entries\n        public MessageBuffer messageBuffer = new MessageBuffer(10);\n\n        public TestLogger() {\n            this(LogLevel.DEBUG);\n        }\n\n        public TestLogger(int minimumLevel) {\n            this.minimumLevel = minimumLevel;\n        }\n\n        @Override\n        public void log(int level, String tag, Throwable throwable, String message) {\n            if (minimumLevel <= level) {\n                messageBuffer.put(message);\n                this.message = message;\n                this.throwable = throwable;\n            }\n        }\n    }\n\n    public static class StubInputStream extends InputStream {\n        @Override\n        public int read() throws IOException {\n            return 0; // Stub implementation\n        }\n    }\n\n    // Allocs as much garbage as we can. Pass maxSize = 0 to use it.\n    public static byte[] allocGarbage(int garbageSize) {\n        if (garbageSize == 0) {\n            long maxMemory = Runtime.getRuntime().maxMemory();\n            long totalMemory = Runtime.getRuntime().totalMemory();\n            garbageSize = (int) (maxMemory - totalMemory) / 10 * 9;\n        }\n        byte garbage[] = new byte[0];\n        try {\n            if (garbageSize > 0) {\n                garbage = new byte[garbageSize];\n                garbage[0] = 1;\n                garbage[garbage.length - 1] = 1;\n            }\n        } catch (OutOfMemoryError oom) {\n            return allocGarbage(garbageSize / 10 * 9);\n        }\n\n        return garbage;\n    }\n\n    // Creates SHA512 hash of a String. Can be used as password for encrypted Realms.\n    public static byte[] SHA512(String str) {\n        try {\n            MessageDigest md = MessageDigest.getInstance(\"SHA-512\");\n            md.update(str.getBytes(UTF_8), 0, str.length());\n            return md.digest();\n        } catch (NoSuchAlgorithmException e) {\n            throw new RuntimeException(e);\n        }\n    }\n\n    /**\n     * @deprecated Use {@link TestRealmConfigurationFactory#createConfiguration()} instead.\n     */\n    @Deprecated\n    public static RealmConfiguration createConfiguration(Context context) {\n        return createConfiguration(context, Realm.DEFAULT_REALM_NAME);\n    }\n\n    /**\n     * @deprecated Use {@link TestRealmConfigurationFactory#createConfiguration(String)} instead.\n     */\n    @Deprecated\n    public static RealmConfiguration createConfiguration(Context context, String name) {\n        return createConfiguration(context.getFilesDir(), name);\n    }\n\n    /**\n     * @deprecated Use {@link TestRealmConfigurationFactory#createConfiguration(String)} instead.\n     */\n    @Deprecated\n    public static RealmConfiguration createConfiguration(File folder, String name) {\n        return createConfiguration(folder, name, null);\n    }\n\n    /**\n     * @deprecated Use {@link TestRealmConfigurationFactory#createConfiguration(String, byte[])} instead.\n     */\n    @Deprecated\n    public static RealmConfiguration createConfiguration(Context context, String name, @Nullable byte[] key) {\n        return createConfiguration(context.getFilesDir(), name, key);\n    }\n\n    /**\n     * @deprecated Use {@link TestRealmConfigurationFactory#createConfiguration(String, byte[])} instead.\n     */\n    @Deprecated\n    public static RealmConfiguration createConfiguration(File dir, String name, @Nullable byte[] key) {\n        RealmConfiguration.Builder config = new RealmConfiguration.Builder(InstrumentationRegistry.getInstrumentation().getTargetContext())\n                .directory(dir)\n                .name(name);\n        if (key != null) {\n            config.encryptionKey(key);\n        }\n\n        return config.build();\n    }\n\n    /**\n     * Adds a String type PrimaryKey object to a realm with values for name field (PrimaryKey) and id field\n     */\n    public static PrimaryKeyAsString addStringPrimaryKeyObjectToTestRealm(Realm testRealm, String primaryFieldValue, long secondaryFieldValue) {\n        testRealm.beginTransaction();\n        PrimaryKeyAsString obj = new PrimaryKeyAsString();\n        obj.setName(primaryFieldValue);\n        obj.setId(secondaryFieldValue);\n        testRealm.copyToRealm(obj);\n        testRealm.commitTransaction();\n        return obj;\n    }\n\n    /**\n     * Populates a realm with String type Primarykey objects for a number of numberOfPopulation - 1,\n     * starting with iteratorBeginValue. One object is setup to have given values from parameters.\n     */\n    public static void populateTestRealmWithStringPrimaryKey(Realm testRealm, String primaryFieldValue, long secondaryFieldValue, int numberOfPopulation, int iteratorBeginValue) {\n        testRealm.beginTransaction();\n        PrimaryKeyAsString userObj = new PrimaryKeyAsString();\n        userObj.setName(primaryFieldValue);\n        userObj.setId(secondaryFieldValue);\n        testRealm.copyToRealm(userObj);\n        int idValue = iteratorBeginValue;\n        for (int i = 0; i < numberOfPopulation - 1; ++i, ++idValue) {\n            PrimaryKeyAsString obj = new PrimaryKeyAsString();\n            obj.setName(String.valueOf(idValue));\n            obj.setId(idValue);\n            testRealm.copyToRealm(obj);\n        }\n        testRealm.commitTransaction();\n    }\n\n    /**\n     * Adds a Byte type PrimaryKey object to a realm with values for id field (PrimaryKey) and name field\n     */\n    public static PrimaryKeyAsBoxedByte addBytePrimaryKeyObjectToTestRealm(Realm testRealm, Byte primaryFieldValue, String secondaryFieldValue) {\n        testRealm.beginTransaction();\n        PrimaryKeyAsBoxedByte obj = new PrimaryKeyAsBoxedByte();\n        obj.setId(primaryFieldValue);\n        obj.setName(secondaryFieldValue);\n        testRealm.copyToRealm(obj);\n        testRealm.commitTransaction();\n        return obj;\n    }\n\n    /**\n     * Populates a realm with Byte type Primarykey objects for a number of numberOfPopulation - 1,\n     * starting with iteratorBeginValue. One object is setup to have given values from parameters.\n     */\n    public static void populateTestRealmWithBytePrimaryKey(Realm testRealm, Byte primaryFieldValue, String secondaryFieldValue, int numberOfPopulation, int iteratorBeginValue) {\n        testRealm.beginTransaction();\n        PrimaryKeyAsBoxedByte userObj = new PrimaryKeyAsBoxedByte();\n        userObj.setId(primaryFieldValue);\n        userObj.setName(secondaryFieldValue);\n        testRealm.copyToRealm(userObj);\n        byte idValue = (byte) iteratorBeginValue;\n        for (int i = 0; i < numberOfPopulation - 1; ++i, ++idValue) {\n            PrimaryKeyAsBoxedByte obj = new PrimaryKeyAsBoxedByte();\n            obj.setId(idValue);\n            obj.setName(String.valueOf(idValue));\n            testRealm.copyToRealm(obj);\n        }\n        testRealm.commitTransaction();\n    }\n\n    /**\n     * Adds a Short type PrimaryKey object to a realm with values for id field (PrimaryKey) and name field\n     */\n    public static PrimaryKeyAsBoxedShort addShortPrimaryKeyObjectToTestRealm(Realm testRealm, Short primaryFieldValue, String secondaryFieldValue) {\n        testRealm.beginTransaction();\n        PrimaryKeyAsBoxedShort obj = new PrimaryKeyAsBoxedShort();\n        obj.setId(primaryFieldValue);\n        obj.setName(secondaryFieldValue);\n        testRealm.copyToRealm(obj);\n        testRealm.commitTransaction();\n        return obj;\n    }\n\n    /**\n     * Populates a realm with Short type Primarykey objects for a number of numberOfPopulation - 1,\n     * starting with iteratorBeginValue. One object is setup to have given values from parameters.\n     */\n    public static void populateTestRealmWithShortPrimaryKey(Realm testRealm, Short primaryFieldValue, String secondaryFieldValue, int numberOfPopulation, int iteratorBeginValue) {\n        testRealm.beginTransaction();\n        PrimaryKeyAsBoxedShort userObj = new PrimaryKeyAsBoxedShort();\n        userObj.setId(primaryFieldValue);\n        userObj.setName(secondaryFieldValue);\n        testRealm.copyToRealm(userObj);\n        short idValue = (short)iteratorBeginValue;\n        for (int i = 0; i < numberOfPopulation - 1; ++i, ++idValue) {\n            PrimaryKeyAsBoxedShort obj = new PrimaryKeyAsBoxedShort();\n            obj.setId(idValue);\n            obj.setName(String.valueOf(idValue));\n            testRealm.copyToRealm(obj);\n        }\n        testRealm.commitTransaction();\n    }\n\n    /**\n     * Adds a Integer type PrimaryKey object to a realm with values for id field (PrimaryKey) and name field\n     */\n    public static PrimaryKeyAsBoxedInteger addIntegerPrimaryKeyObjectToTestRealm(Realm testRealm, Integer primaryFieldValue, String secondaryFieldValue) {\n        testRealm.beginTransaction();\n        PrimaryKeyAsBoxedInteger obj = new PrimaryKeyAsBoxedInteger();\n        obj.setId(primaryFieldValue);\n        obj.setName(secondaryFieldValue);\n        testRealm.copyToRealm(obj);\n        testRealm.commitTransaction();\n        return obj;\n    }\n\n    /**\n     * Populates a realm with Integer type Primarykey objects for a number of numberOfPopulation - 1,\n     * starting with iteratorBeginValue. One object is setup to have given values from parameters.\n     */\n    public static void populateTestRealmWithIntegerPrimaryKey(Realm testRealm, Integer primaryFieldValue, String secondaryFieldValue, int numberOfPopulation, int iteratorBeginValue) {\n        testRealm.beginTransaction();\n        PrimaryKeyAsBoxedInteger userObj = new PrimaryKeyAsBoxedInteger();\n        userObj.setId(primaryFieldValue);\n        userObj.setName(secondaryFieldValue);\n        testRealm.copyToRealm(userObj);\n        int idValue = iteratorBeginValue;\n        for (int i = 0; i < numberOfPopulation - 1; ++i, ++idValue) {\n            PrimaryKeyAsBoxedInteger obj = new PrimaryKeyAsBoxedInteger();\n            obj.setId(idValue);\n            obj.setName(String.valueOf(idValue));\n            testRealm.copyToRealm(obj);\n        }\n        testRealm.commitTransaction();\n    }\n\n    /**\n     * Adds a Long type PrimaryKey object to a realm with values for id field (PrimaryKey) and name field\n     */\n    public static PrimaryKeyAsBoxedLong addLongPrimaryKeyObjectToTestRealm(Realm testRealm, Long primaryFieldValue, String secondaryFieldValue) {\n        testRealm.beginTransaction();\n        PrimaryKeyAsBoxedLong obj = new PrimaryKeyAsBoxedLong();\n        obj.setId(primaryFieldValue);\n        obj.setName(secondaryFieldValue);\n        testRealm.copyToRealm(obj);\n        testRealm.commitTransaction();\n        return obj;\n    }\n\n    /**\n     * Populates a realm with Long type Primarykey objects for a number of numberOfPopulation - 1,\n     * starting with iteratorBeginValue. One object is setup to have given values from parameters.\n     */\n    public static void populateTestRealmWithLongPrimaryKey(Realm testRealm, Long primaryFieldValue, String secondaryFieldValue, long numberOfPopulation, long iteratorBeginValue) {\n        testRealm.beginTransaction();\n        PrimaryKeyAsBoxedLong userObj = new PrimaryKeyAsBoxedLong();\n        userObj.setId(primaryFieldValue);\n        userObj.setName(secondaryFieldValue);\n        testRealm.copyToRealm(userObj);\n        long idValue = iteratorBeginValue;\n        for (long i = 0; i < numberOfPopulation - 1; ++i, ++idValue) {\n            PrimaryKeyAsBoxedLong obj = new PrimaryKeyAsBoxedLong();\n            obj.setId(idValue);\n            obj.setName(String.valueOf(idValue));\n            testRealm.copyToRealm(obj);\n        }\n        testRealm.commitTransaction();\n    }\n\n    public static void populateTestRealmForNullTests(Realm testRealm) {\n\n        // Creates 3 NullTypes objects. The objects are self-referenced (link) in\n        // order to test link queries.\n        //\n        // +-+--------+------+---------+--------+--------------------+\n        // | | string | link | numeric | binary | numeric (not null) |\n        // +-+--------+------+---------+--------+--------------------+\n        // |0| Fish   |    0 |       1 |    {0} |                  1 |\n        // |1| null   | null |    null |   null |                  0 |\n        // |2| Horse  |    1 |       3 |  {1,2} |                  3 |\n        // +-+--------+------+---------+--------+--------------------+\n\n        // 1 String\n        String[] words = {\"Fish\", null, \"Horse\"};\n        // 2 Bytes\n        byte[][] binaries = {new byte[]{0}, null, new byte[]{1, 2}};\n        // 3 Boolean\n        Boolean[] booleans = {false, null, true};\n        // Numeric fields will be 1, 0/null, 3\n        // 10 Date\n        Date[] dates = {new Date(0), null, new Date(10000)};\n        NullTypes[] nullTypesArray = new NullTypes[3];\n\n        Decimal128[] decimals = {new Decimal128(BigDecimal.TEN), null, new Decimal128(BigDecimal.ONE)};\n        ObjectId[] ids = {new ObjectId(TestHelper.generateObjectIdHexString(10)), null, new ObjectId(TestHelper.generateObjectIdHexString(1))};\n\n        testRealm.beginTransaction();\n        for (int i = 0; i < 3; i++) {\n            NullTypes nullTypes = new NullTypes();\n            nullTypes.setId(i + 1);\n            // 1 String\n            nullTypes.setFieldStringNull(words[i]);\n            if (words[i] != null) {\n                nullTypes.setFieldStringNotNull(words[i]);\n            }\n            // 2 Bytes\n            nullTypes.setFieldBytesNull(binaries[i]);\n            if (binaries[i] != null) {\n                nullTypes.setFieldBytesNotNull(binaries[i]);\n            }\n            // 3 Boolean\n            nullTypes.setFieldBooleanNull(booleans[i]);\n            if (booleans[i] != null) {\n                nullTypes.setFieldBooleanNotNull(booleans[i]);\n            }\n            if (i != 1) {\n                int n = i + 1;\n                // 4 Byte\n                nullTypes.setFieldByteNull((byte) n);\n                nullTypes.setFieldByteNotNull((byte) n);\n                // 5 Short\n                nullTypes.setFieldShortNull((short) n);\n                nullTypes.setFieldShortNotNull((short) n);\n                // 6 Integer\n                nullTypes.setFieldIntegerNull(n);\n                nullTypes.setFieldIntegerNotNull(n);\n                // 7 Long\n                nullTypes.setFieldLongNull((long) n);\n                nullTypes.setFieldLongNotNull((long) n);\n                // 8 Float\n                nullTypes.setFieldFloatNull((float) n);\n                nullTypes.setFieldFloatNotNull((float) n);\n                // 9 Double\n                nullTypes.setFieldDoubleNull((double) n);\n                nullTypes.setFieldDoubleNotNull((double) n);\n            }\n            // 10 Date\n            nullTypes.setFieldDateNull(dates[i]);\n            if (dates[i] != null) {\n                nullTypes.setFieldDateNotNull(dates[i]);\n            }\n\n            nullTypes.setFieldDecimal128Null(decimals[i]);\n\n            nullTypes.setFieldObjectIdNull(ids[i]);\n\n            nullTypesArray[i] = testRealm.copyToRealm(nullTypes);\n        }\n        nullTypesArray[0].setFieldObjectNull(nullTypesArray[0]);\n        nullTypesArray[1].setFieldObjectNull(null);\n        nullTypesArray[2].setFieldObjectNull(nullTypesArray[1]);\n        testRealm.commitTransaction();\n    }\n\n    public static void populateAllNonNullRowsForNumericTesting(Realm realm) {\n        NullTypes nullTypes1 = new NullTypes();\n        nullTypes1.setId(1);\n        nullTypes1.setFieldIntegerNull(3);\n        nullTypes1.setFieldFloatNull(4F);\n        nullTypes1.setFieldDoubleNull(5D);\n        nullTypes1.setFieldBooleanNull(true);\n        nullTypes1.setFieldStringNull(\"4\");\n        nullTypes1.setFieldDateNull(new Date(12345));\n\n        NullTypes nullTypes2 = new NullTypes();\n        nullTypes2.setId(2);\n        nullTypes2.setFieldIntegerNull(-1);\n        nullTypes2.setFieldFloatNull(-2F);\n        nullTypes2.setFieldDoubleNull(-3D);\n        nullTypes2.setFieldBooleanNull(false);\n        nullTypes2.setFieldStringNull(\"str\");\n        nullTypes2.setFieldDateNull(new Date(-2000));\n\n        NullTypes nullTypes3 = new NullTypes();\n        nullTypes3.setId(3);\n        nullTypes3.setFieldIntegerNull(4);\n        nullTypes3.setFieldFloatNull(5F);\n        nullTypes3.setFieldDoubleNull(6D);\n        nullTypes3.setFieldBooleanNull(false);\n        nullTypes3.setFieldStringNull(\"0\");\n        nullTypes3.setFieldDateNull(new Date(0));\n\n        realm.beginTransaction();\n        realm.copyToRealm(nullTypes1);\n        realm.copyToRealm(nullTypes2);\n        realm.copyToRealm(nullTypes3);\n        realm.commitTransaction();\n    }\n\n    public static void populatePartialNullRowsForNumericTesting(Realm realm) {\n        // Id values are [1, 2, 3]\n        // IntegerNull values are [3, null, 4]\n        // FloatNull values are [4F, null, 5F]\n        // DoubleNull values are [5D, null, 6F]\n        NullTypes nullTypes1 = new NullTypes();\n        nullTypes1.setId(1);\n        nullTypes1.setFieldIntegerNull(3);\n        nullTypes1.setFieldFloatNull(4F);\n        nullTypes1.setFieldDoubleNull(5D);\n        nullTypes1.setFieldBooleanNull(true);\n        nullTypes1.setFieldStringNull(\"4\");\n        nullTypes1.setFieldDateNull(new Date(12345));\n\n        NullTypes nullTypes2 = new NullTypes();\n        nullTypes2.setId(2);\n\n        NullTypes nullTypes3 = new NullTypes();\n        nullTypes3.setId(3);\n        nullTypes3.setFieldIntegerNull(4);\n        nullTypes3.setFieldFloatNull(5F);\n        nullTypes3.setFieldDoubleNull(6D);\n        nullTypes3.setFieldBooleanNull(false);\n        nullTypes3.setFieldStringNull(\"0\");\n        nullTypes3.setFieldDateNull(new Date(0));\n\n        realm.beginTransaction();\n        realm.copyToRealm(nullTypes1);\n        realm.copyToRealm(nullTypes2);\n        realm.copyToRealm(nullTypes3);\n        realm.commitTransaction();\n    }\n\n    public static void populateAllNullRowsForNumericTesting(Realm realm) {\n        NullTypes nullTypes1 = new NullTypes();\n        nullTypes1.setId(1);\n        NullTypes nullTypes2 = new NullTypes();\n        nullTypes2.setId(2);\n\n        realm.beginTransaction();\n        realm.copyToRealm(nullTypes1);\n        realm.copyToRealm(nullTypes2);\n        realm.commitTransaction();\n    }\n\n    // Helper function to create all columns except the given excluding field for NullTypes.\n    // The schema version will be set to 0.\n    public static void initNullTypesTableExcludes(DynamicRealm realm, String excludingField) {\n        realm.beginTransaction();\n\n        RealmObjectSchema nullTypesSchema = realm.getSchema().create(NullTypes.CLASS_NAME);\n        if (!excludingField.equals(NullTypes.FIELD_ID)) {\n            nullTypesSchema.addField(NullTypes.FIELD_ID, int.class, FieldAttribute.PRIMARY_KEY);\n        }\n        if (!excludingField.equals(NullTypes.FIELD_STRING_NOT_NULL)) {\n            nullTypesSchema.addField(NullTypes.FIELD_STRING_NOT_NULL, String.class, FieldAttribute.REQUIRED);\n        }\n        if (!excludingField.equals(NullTypes.FIELD_STRING_NULL)) {\n            nullTypesSchema.addField(NullTypes.FIELD_STRING_NULL, String.class);\n        }\n        if (!excludingField.equals(NullTypes.FIELD_BYTES_NOT_NULL)) {\n            nullTypesSchema.addField(NullTypes.FIELD_BYTES_NOT_NULL, byte[].class, FieldAttribute.REQUIRED);\n        }\n        if (!excludingField.equals(NullTypes.FIELD_BYTES_NULL)) {\n            nullTypesSchema.addField(NullTypes.FIELD_BYTES_NULL, byte[].class);\n        }\n        if (!excludingField.equals(NullTypes.FIELD_BOOLEAN_NOT_NULL)) {\n            nullTypesSchema.addField(NullTypes.FIELD_BOOLEAN_NOT_NULL, boolean.class);\n        }\n        if (!excludingField.equals(NullTypes.FIELD_BOOLEAN_NULL)) {\n            nullTypesSchema.addField(NullTypes.FIELD_BOOLEAN_NULL, Boolean.class);\n        }\n        if (!excludingField.equals(NullTypes.FIELD_BYTE_NOT_NULL)) {\n            nullTypesSchema.addField(NullTypes.FIELD_BYTE_NOT_NULL, byte.class);\n        }\n        if (!excludingField.equals(NullTypes.FIELD_BYTE_NULL)) {\n            nullTypesSchema.addField(NullTypes.FIELD_BYTE_NULL, Byte.class);\n        }\n        if (!excludingField.equals(NullTypes.FIELD_SHORT_NOT_NULL)) {\n            nullTypesSchema.addField(NullTypes.FIELD_SHORT_NOT_NULL, short.class);\n        }\n        if (!excludingField.equals(NullTypes.FIELD_SHORT_NULL)) {\n            nullTypesSchema.addField(NullTypes.FIELD_SHORT_NULL, Short.class);\n        }\n        if (!excludingField.equals(NullTypes.FIELD_INTEGER_NOT_NULL)) {\n            nullTypesSchema.addField(NullTypes.FIELD_INTEGER_NOT_NULL, int.class);\n        }\n        if (!excludingField.equals(NullTypes.FIELD_INTEGER_NULL)) {\n            nullTypesSchema.addField(NullTypes.FIELD_INTEGER_NULL, Integer.class);\n        }\n        if (!excludingField.equals(NullTypes.FIELD_LONG_NOT_NULL)) {\n            nullTypesSchema.addField(NullTypes.FIELD_LONG_NOT_NULL, long.class);\n        }\n        if (!excludingField.equals(NullTypes.FIELD_LONG_NULL)) {\n            nullTypesSchema.addField(NullTypes.FIELD_LONG_NULL, Long.class);\n        }\n        if (!excludingField.equals(NullTypes.FIELD_FLOAT_NOT_NULL)) {\n            nullTypesSchema.addField(NullTypes.FIELD_FLOAT_NOT_NULL, float.class);\n        }\n        if (!excludingField.equals(NullTypes.FIELD_FLOAT_NULL)) {\n            nullTypesSchema.addField(NullTypes.FIELD_FLOAT_NULL, Float.class);\n        }\n        if (!excludingField.equals(NullTypes.FIELD_DOUBLE_NOT_NULL)) {\n            nullTypesSchema.addField(NullTypes.FIELD_DOUBLE_NOT_NULL, double.class);\n        }\n        if (!excludingField.equals(NullTypes.FIELD_DOUBLE_NULL)) {\n            nullTypesSchema.addField(NullTypes.FIELD_DOUBLE_NULL, Double.class);\n        }\n        if (!excludingField.equals(NullTypes.FIELD_DATE_NOT_NULL)) {\n            nullTypesSchema.addField(NullTypes.FIELD_DATE_NOT_NULL, Date.class, FieldAttribute.REQUIRED);\n        }\n        if (!excludingField.equals(NullTypes.FIELD_DATE_NULL)) {\n            nullTypesSchema.addField(NullTypes.FIELD_DATE_NULL, Date.class);\n        }\n        if (!excludingField.equals(NullTypes.FIELD_OBJECT_NULL)) {\n            nullTypesSchema.addRealmObjectField(NullTypes.FIELD_OBJECT_NULL, nullTypesSchema);\n        }\n\n        nullTypesSchema.addRealmListField(NullTypes.FIELD_LIST_NULL, nullTypesSchema);\n\n        realm.setVersion(0);\n        realm.commitTransaction();\n    }\n\n    public static void populateSimpleAllTypesPrimaryKey(Realm realm) {\n        realm.beginTransaction();\n        AllTypesPrimaryKey obj = new AllTypesPrimaryKey();\n        obj.setColumnLong(1);\n        obj.setColumnString(\"Foo\");\n        realm.copyToRealm(obj);\n        realm.commitTransaction();\n    }\n\n\n    /*\n     * Fields order test for Chained or Multi-Arguments Distinct()\n     *\n     * The idea is to interweave different values in 2's multiplier and 3's multiplier in a way that\n     * the outcome is different if the order of distinct* operations alternates. More numbers of\n     * fields can be constructed with the combination of multipliers in prime numbers such as 2, 3,\n     * and 5.\n     *\n     * An example is illustrated below.\n     *\n     * Object      : O1| O2| O3| O4| O5| O6\n     * indexString : A | A | B | B | A | A\n     * indexLong   : 1 | 1 | 1 | 2 | 2 | 2\n     *\n     * @param realm a {@link Realm} instance.\n     * @param numberOfBlocks number of times set of unique objects should be created.\n     */\n    public static void populateForDistinctFieldsOrder(Realm realm, long numberOfBlocks) {\n        realm.beginTransaction();\n        for (int i = 0; i < numberOfBlocks; i++) {\n            for (int j = 0; j < 6; j++) {\n                AnnotationIndexTypes obj = realm.createObject(AnnotationIndexTypes.class);\n                obj.setIndexString((((j / 2) % 2) == 0) ? \"A\" : \"B\");\n                obj.setIndexLong((j < 3) ? 1 : 2);\n            }\n        }\n        realm.commitTransaction();\n    }\n\n    public static void awaitOrFail(CountDownLatch latch) {\n        awaitOrFail(latch, STANDARD_WAIT_SECS);\n    }\n\n    public static void awaitOrFail(CountDownLatch latch, int numberOfSeconds) {\n        try {\n            if (android.os.Debug.isDebuggerConnected()) {\n                // If we are debugging the tests, just waits without a timeout.\n                // Don't want a timeout while we are stopped at a break point.\n                latch.await();\n            } else if (!latch.await(numberOfSeconds, TimeUnit.SECONDS)) {\n                fail(\"Test took longer than \" + numberOfSeconds + \" seconds\");\n            }\n        } catch (InterruptedException e) {\n            fail(e.getMessage());\n        }\n    }\n\n    public interface LooperTest {\n        Looper getLooper();\n        Throwable getAssertionError();\n    }\n\n    // Cleans resource, shutdowns the executor service and throws any background exception.\n    @SuppressWarnings(\"Finally\")\n    public static void exitOrThrow(ExecutorService executorService, CountDownLatch testFinishedSignal, LooperTest test) throws Throwable {\n\n        // Waits for the signal indicating the test's use case is done.\n        try {\n            // Even if this fails we want to try as hard as possible to cleanup. If we fail to close all resources\n            // properly, the `after()` method will most likely throw as well because it tries do delete any Realms\n            // used. Any exception in the `after()` code will mask the original error.\n            TestHelper.awaitOrFail(testFinishedSignal);\n        } finally {\n            Looper looper = test.getLooper();\n            if (looper != null) {\n                // Failing to quit the looper will not execute the finally block responsible\n                // of closing the Realm.\n                looper.quit();\n            }\n\n            // Closes the executor.\n            // This needs to be called after waiting since it might interrupt waitRealmThreadExecutorFinish().\n            executorService.shutdownNow();\n\n            Throwable fault = test.getAssertionError();\n            if (fault != null) {\n                // Throws any assertion errors happened in the background thread.\n                throw fault;\n            }\n        }\n    }\n\n    public static InputStream loadJsonFromAssets(Context context, String file) throws IOException {\n        AssetManager assetManager = context.getAssets();\n        return assetManager.open(file);\n    }\n\n    public static void quitLooperOrFail() {\n        Looper looper = Looper.myLooper();\n        if (looper != null) {\n            looper.quit();\n        } else {\n            Assert.fail();\n        }\n    }\n\n    /**\n     * Creates a {@link RealmResults} instance.\n     * This helper method is useful to create a mocked {@link RealmResults}.\n     *\n     * @param realm a {@link Realm} or a {@link DynamicRealm} instance.\n     * @param osResults a {@link OsResults} instance.\n     * @param tableClass a Class of Table.\n     * @return a created {@link RealmResults} instance.\n     */\n    public static <T extends RealmObject> RealmResults<T> newRealmResults(\n            BaseRealm realm, OsResults osResults, Class<T> tableClass) {\n        //noinspection TryWithIdenticalCatches\n        try {\n            final Constructor<RealmResults> c = RealmResults.class.getDeclaredConstructor(\n                    BaseRealm.class, OsResults.class, Class.class);\n            c.setAccessible(true);\n            //noinspection unchecked\n            return c.newInstance(realm, osResults, tableClass);\n        } catch (NoSuchMethodException e) {\n            throw new RuntimeException(e);\n        } catch (InstantiationException e) {\n            throw new RuntimeException(e);\n        } catch (IllegalAccessException e) {\n            throw new RuntimeException(e);\n        } catch (InvocationTargetException e) {\n            throw new RuntimeException(e);\n        }\n    }\n\n    public static void testNoObjectFound(\n            Realm realm,\n            Class<? extends RealmModel> clazz,\n            String fieldName, Object value) {\n        testObjectCount(realm, 0L, clazz, fieldName, value);\n    }\n\n    public static void testOneObjectFound(\n            Realm realm,\n            Class<? extends RealmModel> clazz,\n            String fieldName, Object value) {\n        testObjectCount(realm, 1L, clazz, fieldName, value);\n    }\n\n    public static void testObjectCount(\n            Realm realm,\n            long expectedCount,\n            Class<? extends RealmModel> clazz,\n            String fieldName, Object value) {\n        final RealmQuery<? extends RealmModel> query;\n        switch (value.getClass().getSimpleName()) {\n            case \"String\":\n                query = realm.where(clazz).equalTo(fieldName, (String) value);\n                break;\n            case \"Byte\":\n                query = realm.where(clazz).equalTo(fieldName, (Byte) value);\n                break;\n            case \"Short\":\n                query = realm.where(clazz).equalTo(fieldName, (Short) value);\n                break;\n            case \"Integer\":\n                query = realm.where(clazz).equalTo(fieldName, (Integer) value);\n                break;\n            case \"Long\":\n                query = realm.where(clazz).equalTo(fieldName, (Long) value);\n                break;\n            case \"Float\":\n                query = realm.where(clazz).equalTo(fieldName, (Float) value);\n                break;\n            case \"Double\":\n                query = realm.where(clazz).equalTo(fieldName, (Double) value);\n                break;\n            case \"Boolean\":\n                query = realm.where(clazz).equalTo(fieldName, (Boolean) value);\n                break;\n            case \"Date\":\n                query = realm.where(clazz).equalTo(fieldName, (Date) value);\n                break;\n            case \"byte[]\":\n                query = realm.where(clazz).equalTo(fieldName, (byte[]) value);\n                break;\n            default:\n                throw new AssertionError(\"unknown type: \" + value.getClass().getSimpleName());\n        }\n\n        assertEquals(expectedCount, query.count());\n    }\n\n    /**\n     * Replaces the current thread executor with a another one for testing.\n     * WARNING: This method should only be called before any async tasks have been started.\n     *          Call {@link #resetRealmThreadExecutor()} before test return to reset the excutor to default.\n     *\n     * @param executor {@link RealmThreadPoolExecutor} that should replace the current one\n     */\n    public static RealmThreadPoolExecutor replaceRealmThreadExecutor(RealmThreadPoolExecutor executor)\n            throws NoSuchFieldException, IllegalAccessException {\n        Field field = BaseRealm.class.getDeclaredField(\"asyncTaskExecutor\");\n        field.setAccessible(true);\n        RealmThreadPoolExecutor oldExecutor = (RealmThreadPoolExecutor) field.get(null);\n        field.set(field, executor);\n        return oldExecutor;\n    }\n\n    /**\n     * This will first wait for finishing all tasks in BaseRealm.asyncTaskExecutor, throws if time out.\n     * Then reset the BaseRealm.asyncTaskExecutor to the default value.\n     *\n     * @throws NoSuchFieldException\n     * @throws IllegalAccessException\n     */\n    public static void resetRealmThreadExecutor() throws NoSuchFieldException, IllegalAccessException {\n        waitRealmThreadExecutorFinish();\n        replaceRealmThreadExecutor(RealmThreadPoolExecutor.newDefaultExecutor());\n    }\n\n    /**\n     * Waits and checks if all tasks in BaseRealm.asyncTaskExecutor can be finished in 5 seconds, otherwise fails the test.\n     */\n    public static void waitRealmThreadExecutorFinish() {\n        int counter = 50;\n        while (counter > 0) {\n            if (BaseRealm.asyncTaskExecutor.getActiveCount() == 0) {\n                return;\n            }\n            try {\n                Thread.sleep(100);\n            } catch (InterruptedException e) {\n                fail(e.getMessage());\n            }\n            counter--;\n        }\n        fail(\"'BaseRealm.asyncTaskExecutor' is not finished in \" + counter/10.0D + \" seconds\");\n    }\n\n    /**\n     * Emulates an environment where RxJava is not available.\n     *\n     * @param config {@link RealmConfiguration} instance to be modified.\n     */\n    public static void emulateRxJavaUnavailable(RealmConfiguration config) {\n        //noinspection TryWithIdenticalCatches\n        try {\n            final Field field = config.getClass().getDeclaredField(\"rxObservableFactory\");\n            field.setAccessible(true);\n            field.set(config, null);\n        } catch (NoSuchFieldException e) {\n            throw new RuntimeException(e);\n        } catch (IllegalAccessException e) {\n            throw new RuntimeException(e);\n        }\n    }\n\n    public static abstract class Task {\n        public abstract void run() throws Exception;\n    }\n\n    public static void executeOnNonLooperThread(final Task task) throws Throwable {\n        final AtomicReference<Throwable> thrown = new AtomicReference<Throwable>();\n        final Thread thread = new Thread() {\n            @Override\n            public void run() {\n                try {\n                    task.run();\n                } catch (Throwable e) {\n                    thrown.set(e);\n                    if (e instanceof Error) {\n                        throw (Error) e;\n                    }\n                }\n            }\n        };\n        thread.start();\n        thread.join();\n\n        final Throwable throwable = thrown.get();\n        if (throwable != null) {\n            throw throwable;\n        }\n    }\n\n    @SuppressWarnings(\"WeakerAccess\")\n    public static void deleteRecursively(File file) {\n        if (!file.exists()) {\n            return;\n        }\n\n        if (file.isDirectory()) {\n            File[] files = file.listFiles();\n            for (File f : files) {\n                if (f != null) {\n                    deleteRecursively(f);\n                }\n            }\n        }\n\n        if (!file.delete()) {\n            throw new AssertionError(\"failed to delete \" + file.getAbsolutePath());\n        }\n    }\n\n    @SuppressWarnings(\"WeakerAccess\")\n    public static boolean isSelinuxEnforcing() {\n        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR2) {\n            // SELinux is not enabled for these versions.\n            return false;\n        }\n        try {\n            final Process process = new ProcessBuilder(\"/system/bin/getenforce\")\n                    .redirectErrorStream(true)\n                    .start();\n            try {\n                final BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream(), UTF_8));\n                //noinspection TryFinallyCanBeTryWithResources\n                try {\n                    String line = reader.readLine();\n                    if (line != null) {\n                        return line.toLowerCase(Locale.ENGLISH).equals(\"enforcing\");\n                    } else {\n                        return false;\n                    }\n                } finally {\n                    try {\n                        reader.close();\n                    } catch (IOException ignored) {\n                    }\n                }\n            } finally {\n                try {\n                    process.waitFor();\n                } catch (InterruptedException ignored) {\n                }\n            }\n        } catch (IOException e) {\n            return false;\n        }\n    }\n\n    public static void populateLinkedDataSet(Realm realm) {\n        realm.beginTransaction();\n        realm.delete(BacklinksSource.class);\n        realm.delete(BacklinksTarget.class);\n\n        BacklinksTarget target1 = realm.createObject(BacklinksTarget.class);\n        target1.setId(1);\n\n        BacklinksTarget target2 = realm.createObject(BacklinksTarget.class);\n        target2.setId(2);\n\n        BacklinksTarget target3 = realm.createObject(BacklinksTarget.class);\n        target3.setId(3);\n\n        BacklinksSource source1 = realm.createObject(BacklinksSource.class);\n        source1.setName(\"1\");\n        source1.setChild(target1);\n        BacklinksSource source2 = realm.createObject(BacklinksSource.class);\n        source2.setName(\"2\");\n        source2.setChild(target2);\n\n        BacklinksSource source3 = realm.createObject(BacklinksSource.class);\n        source3.setName(\"3\");\n\n        BacklinksSource source4 = realm.createObject(BacklinksSource.class);\n        source4.setName(\"4\");\n        source4.setChild(target1);\n\n        realm.commitTransaction();\n    }\n\n    /**\n     * This method will kill all tasks then shutdown and replace the SyncManager.NETWORK_POOL_EXECUTOR\n     * with a fresh and empty instance. This should only be called when exiting tests.\n     *\n     * If the build does not support Sync, this method will do nothing\n     */\n    private static final Field networkPoolExecutorField;\n    static {\n        Class app = null;\n        try {\n            app = Class.forName(\"io.realm.mongodb.App\");\n        } catch (ClassNotFoundException e) {\n            // Ignore\n        }\n\n        try {\n            networkPoolExecutorField = (app != null) ? app.getDeclaredField(\"NETWORK_POOL_EXECUTOR\") : null;\n        } catch (NoSuchFieldException e) {\n            throw new AssertionError(\"Could not find field: NETWORK_POOL_EXECUTOR\\n\" + Util.getStackTrace(e));\n        }\n    }\n\n    public static void waitForNetworkThreadExecutorToFinish() {\n        if (networkPoolExecutorField == null) {\n            return; // This build do not support Sync\n        }\n        try {\n            ThreadPoolExecutor pool = (ThreadPoolExecutor) networkPoolExecutorField.get(null);\n            // Since this method should only be called when exiting a test, it should be safe to just\n            // cancel all ongoing network requests and shut down the pool as soon as possible.\n            // When shut down we replace it with a new, now empty, pool that can be used by future\n            // tests\n            pool.shutdownNow();\n            try {\n                pool.awaitTermination(5, TimeUnit.SECONDS);\n            } catch (InterruptedException e) {\n                throw new AssertionError(\"NetworkPoolExecutor was not shut down in time:\\n\" + Util.getStackTrace(e));\n            } finally {\n                // Replace the executor, since the old one is now dead.\n                // The setup of this should mirror what is done in SyncManager.\n                networkPoolExecutorField.set(null, new ThreadPoolExecutor(\n                        10, 10, 0, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(100)));\n            }\n        } catch (IllegalAccessException e) {\n            throw new AssertionError(Util.getStackTrace(e));\n        }\n    }\n\n    // Workaround to cheat Kotlins type system when testing interop with Java\n    @SuppressWarnings(\"TypeParameterUnusedInFormals\")\n    public static <T> T getNull() {\n        return null;\n    }\n\n    // Workaround to cheat Kotlins type system when testing interop with Java\n    @Nonnull\n    public static <T> T allowNull(@Nullable T value) {\n        return value;\n    }\n\n    public static String randomObjectIdHexString() {\n        char[] hex = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E' , 'F'};\n\n        StringBuilder randomId = new StringBuilder(24);\n        for (int i = 0; i < 24; i++) {\n            randomId.append(hex[RANDOM.nextInt(16)]);\n        }\n        return randomId.toString();\n    }\n\n    public static String generateObjectIdHexString(int i) {\n        char[] hex = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E' , 'F'};\n\n        StringBuilder randomId = new StringBuilder(24);\n        for (int j = 0; j < 24; j++) {\n            randomId.append(hex[(i + j) % 16]);\n        }\n        return randomId.toString();\n    }\n\n    public static String generateUUIDString(int i){\n        return String.format(\"%08d-aa12-4afa-9219-e20cc3018599\", i);\n    }\n\n}\n"
  },
  {
    "path": "realm/realm-library/src/testUtils/java/io/realm/TestRealmConfigurationFactory.java",
    "content": "/*\n * Copyright 2016 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\npackage io.realm;\n\nimport android.content.Context;\n\nimport androidx.test.platform.app.InstrumentationRegistry;\n\nimport org.junit.rules.TemporaryFolder;\nimport org.junit.runner.Description;\nimport org.junit.runners.model.Statement;\n\nimport java.io.File;\nimport java.io.FileOutputStream;\nimport java.io.IOException;\nimport java.io.InputStream;\nimport java.util.Collections;\nimport java.util.Locale;\nimport java.util.Map;\nimport java.util.Set;\nimport java.util.concurrent.ConcurrentHashMap;\n\nimport javax.annotation.Nullable;\n\nimport static org.junit.Assert.assertTrue;\n\n\n/**\n * Rule that creates the {@link RealmConfiguration } in a temporary directory and deletes the Realm created with that\n * configuration once the test finishes. Be sure to close all Realm instances before finishing the test. Otherwise\n * {@link Realm#deleteRealm(RealmConfiguration)} will throw an exception in the {@link #after()} method.\n * The temp directory will be deleted regardless if the {@link Realm#deleteRealm(RealmConfiguration)} fails or not.\n */\npublic class TestRealmConfigurationFactory extends TemporaryFolder {\n    private final Map<RealmConfiguration, Boolean> map = new ConcurrentHashMap<RealmConfiguration, Boolean>();\n    private final Set<RealmConfiguration> configurations = Collections.newSetFromMap(map);\n\n    private boolean unitTestFailed = false;\n    private String testName = \"\";\n    private File tempFolder = null;\n\n    @Override\n    public Statement apply(final Statement base, final Description description) {\n        return new Statement() {\n            @Override\n            public void evaluate() throws Throwable {\n                setTestName(description);\n                before();\n                try {\n                    base.evaluate();\n                } catch (Throwable throwable) {\n                    setUnitTestFailed();\n                    throw throwable;\n                } finally {\n                    after();\n                }\n            }\n        };\n    }\n\n    @Override\n    protected void before() throws Throwable {\n        Realm.init(InstrumentationRegistry.getInstrumentation().getTargetContext());\n        super.before();\n    }\n\n    @Override\n    protected void after() {\n        try {\n            for (RealmConfiguration configuration : configurations) {\n                Realm.deleteRealm(configuration);\n            }\n        } catch (IllegalStateException e) {\n            // Only throws the exception caused by deleting the opened Realm if the test case itself doesn't throw.\n            if (!isUnitTestFailed()) {\n                throw e;\n            }\n        } finally {\n            // This will delete the temp directory.\n            super.after();\n        }\n    }\n\n    @Override\n    public void create() throws IOException {\n        super.create();\n        tempFolder = new File(super.getRoot(), testName);\n        if (tempFolder.exists() && !tempFolder.delete()) {\n            throw new IllegalStateException(\"Could not delete folder: \" + tempFolder.getAbsolutePath());\n        }\n        if (!tempFolder.mkdir()) {\n            throw new IllegalStateException(\"Could not create folder: \" + tempFolder.getAbsolutePath());\n        }\n    }\n\n    @Override\n    public File getRoot() {\n        if (tempFolder == null) {\n            throw new IllegalStateException(\n                    \"the temporary folder has not yet been created\");\n        }\n        return tempFolder;\n    }\n\n    /**\n     * To be called in the {@link #apply(Statement, Description)}.\n     */\n    protected void setTestName(Description description) {\n        testName = description.getDisplayName();\n    }\n\n    public synchronized void setUnitTestFailed() {\n        this.unitTestFailed = true;\n    }\n\n    private synchronized boolean isUnitTestFailed() {\n        return this.unitTestFailed;\n    }\n\n    // This builder creates a configuration that is *NOT* managed.\n    // You have to delete it yourself.\n    public RealmConfiguration.Builder createConfigurationBuilder() {\n        RealmConfiguration.Builder builder = new RealmConfiguration.Builder().directory(getRoot());\n        return builder;\n    }\n\n    public RealmConfiguration createSchemaConfiguration(boolean exclude,\n            Class<? extends RealmModel> firstClass, Class<? extends RealmModel>... additionalClasses) {\n        return createConfiguration(null, null, null, null,\n                exclude, firstClass, additionalClasses);\n    }\n\n    public RealmConfiguration createConfiguration() {\n        return createConfiguration(null);\n    }\n\n    public RealmConfiguration createConfiguration(@Nullable String name) {\n        return createConfiguration(null, name);\n    }\n\n    public RealmConfiguration createConfiguration(@Nullable String subDir, @Nullable String name) {\n        return createConfiguration(subDir, name, null, null, false, null);\n    }\n\n    public RealmConfiguration createConfiguration(@Nullable String name, @Nullable byte[] key) {\n        return createConfiguration(null, name, null, key, false, null);\n    }\n\n    public RealmConfiguration createConfiguration(@Nullable String name, @Nullable Object module) {\n        return createConfiguration(null, name, module, null, false, null);\n    }\n\n    public RealmConfiguration createConfiguration(@Nullable String subDir, @Nullable String name, @Nullable Object module, @Nullable byte[] key,\n            boolean exclude, @Nullable Class<? extends RealmModel> firstClass, Class<? extends RealmModel>... additionalClasses) {\n        RealmConfiguration.Builder builder = createConfigurationBuilder();\n\n        File folder = getRoot();\n        if (subDir != null) {\n            folder = new File(folder, subDir);\n            assertTrue(folder.mkdirs());\n        }\n        builder.directory(folder);\n\n        if (name != null) {\n            builder.name(name);\n        }\n\n        if (module != null) {\n            builder.modules(module);\n        }\n\n        if (key != null) {\n            builder.encryptionKey(key);\n        }\n\n        // Allow writes on UI\n        builder.allowWritesOnUiThread(true);\n\n        if (firstClass != null) {\n            if (exclude) {\n                builder.excludeSchema(firstClass, additionalClasses);\n            } else {\n                builder.schema(firstClass, additionalClasses);\n            }\n        }\n\n        RealmConfiguration configuration = builder.build();\n        configurations.add(configuration);\n\n        return configuration;\n    }\n\n    // Copies a Realm file from assets to temp dir\n    public void copyRealmFromAssets(Context context, String realmPath, String newName) throws IOException {\n        RealmConfiguration config = new RealmConfiguration.Builder()\n                .directory(getRoot())\n                .name(newName)\n                .build();\n\n        copyRealmFromAssets(context, realmPath, config);\n    }\n\n    public void copyRealmFromAssets(Context context, String realmPath, RealmConfiguration config) throws IOException {\n        if (new File(config.getPath()).exists()) {\n            throw new IllegalStateException(String.format(Locale.ENGLISH, \"%s exists!\", config.getPath()));\n        }\n        File outFile = new File(config.getRealmDirectory(), config.getRealmFileName());\n        copyFileFromAssets(context, realmPath, outFile);\n    }\n\n    public void copyFileFromAssets(Context context, String assetPath, File outFile) throws IOException {\n        InputStream is = null;\n        FileOutputStream os = null;\n        try {\n            is = context.getAssets().open(assetPath);\n            os = new FileOutputStream(outFile);\n\n            byte[] buf = new byte[1024];\n            int bytesRead;\n            while ((bytesRead = is.read(buf)) > -1) {\n                os.write(buf, 0, bytesRead);\n            }\n        } finally {\n            if (is != null) {\n                try { is.close(); } catch (IOException ignore) {}\n            }\n            if (os != null) {\n                try { os.close(); } catch (IOException ignore) {}\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/testUtils/java/io/realm/entities/AllTypes.java",
    "content": "/*\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\npackage io.realm.entities;\n\nimport org.bson.types.Decimal128;\nimport org.bson.types.ObjectId;\n\nimport java.math.BigDecimal;\nimport java.util.Date;\nimport java.util.UUID;\n\nimport io.realm.RealmAny;\nimport io.realm.MutableRealmInteger;\nimport io.realm.RealmList;\nimport io.realm.RealmObject;\nimport io.realm.RealmResults;\nimport io.realm.TestHelper;\nimport io.realm.annotations.LinkingObjects;\nimport io.realm.annotations.Required;\n\npublic class AllTypes extends RealmObject {\n\n    public static final String CLASS_NAME = \"AllTypes\";\n    public static final String FIELD_STRING = \"columnString\";\n    public static final String FIELD_LONG = \"columnLong\";\n    public static final String FIELD_FLOAT = \"columnFloat\";\n    public static final String FIELD_DOUBLE = \"columnDouble\";\n    public static final String FIELD_BOOLEAN = \"columnBoolean\";\n    public static final String FIELD_DATE = \"columnDate\";\n    public static final String FIELD_BINARY = \"columnBinary\";\n    public static final String FIELD_MUTABLEREALMINTEGER = \"columnMutableRealmInteger\";\n    public static final String FIELD_DECIMAL128 = \"columnDecimal128\";\n    public static final String FIELD_OBJECT_ID = \"columnObjectId\";\n    public static final String FIELD_UUID = \"columnUUID\";\n    public static final String FIELD_REALM_ANY = \"columnRealmAny\";\n    public static final String FIELD_REALMOBJECT = \"columnRealmObject\";\n    public static final String FIELD_REALMLINK = \"columnRealmLink\";\n    public static final String FIELD_REALMBACKLINK = \"columnRealmBackLink\";\n\n    public static final String FIELD_REALMLIST = \"columnRealmList\";\n    public static final String FIELD_STRING_LIST = \"columnStringList\";\n    public static final String FIELD_BINARY_LIST = \"columnBinaryList\";\n    public static final String FIELD_BOOLEAN_LIST = \"columnBooleanList\";\n    public static final String FIELD_LONG_LIST = \"columnLongList\";\n    public static final String FIELD_DOUBLE_LIST = \"columnDoubleList\";\n    public static final String FIELD_FLOAT_LIST = \"columnFloatList\";\n    public static final String FIELD_DATE_LIST = \"columnDateList\";\n\n    public static final String[] INVALID_TYPES_FIELDS_FOR_DISTINCT\n            = new String[]{FIELD_REALMOBJECT, FIELD_REALMLIST, FIELD_DOUBLE, FIELD_FLOAT,\n            FIELD_STRING_LIST, FIELD_BINARY_LIST, FIELD_BOOLEAN_LIST, FIELD_LONG_LIST,\n            FIELD_DOUBLE_LIST, FIELD_FLOAT_LIST, FIELD_DATE_LIST};\n\n\n    @Required\n    private String columnString = \"\";\n    private long columnLong;\n    private float columnFloat;\n    private double columnDouble;\n    private boolean columnBoolean;\n    @Required\n    private Date columnDate = new Date(0);\n    @Required\n    private byte[] columnBinary = new byte[0];\n    @Required\n    private Decimal128 columnDecimal128 = new Decimal128(BigDecimal.ZERO);\n    @Required\n    private ObjectId columnObjectId = new ObjectId(TestHelper.randomObjectIdHexString());\n    @Required\n    private UUID columnUUID = UUID.randomUUID();\n\n    private RealmAny columnRealmAny = RealmAny.nullValue();\n\n    private final MutableRealmInteger columnMutableRealmInteger = MutableRealmInteger.ofNull();\n\n    private Dog columnRealmObject;\n    private AllTypes columnRealmLink;\n\n    @LinkingObjects(\"columnRealmLink\")\n    final private RealmResults<AllTypes> columnRealmBackLink = null;\n\n    private RealmList<Dog> columnRealmList;\n\n    private RealmList<String> columnStringList;\n    private RealmList<byte[]> columnBinaryList;\n    private RealmList<Boolean> columnBooleanList;\n    private RealmList<Long> columnLongList;\n    private RealmList<Double> columnDoubleList;\n    private RealmList<Float> columnFloatList;\n    private RealmList<Date> columnDateList;\n    private RealmList<Decimal128> columnDecimal128List;\n    private RealmList<ObjectId> columnObjectIdList;\n    private RealmList<UUID> columnUUIDList;\n    private RealmList<RealmAny> columnRealmAnyList;\n\n    public String getColumnString() {\n        return columnString;\n    }\n\n    public void setColumnString(String columnString) {\n        this.columnString = columnString;\n    }\n\n    public long getColumnLong() {\n        return columnLong;\n    }\n\n    public void setColumnLong(long columnLong) {\n        this.columnLong = columnLong;\n    }\n\n    public float getColumnFloat() {\n        return columnFloat;\n    }\n\n    public void setColumnFloat(float columnFloat) {\n        this.columnFloat = columnFloat;\n    }\n\n    public double getColumnDouble() {\n        return columnDouble;\n    }\n\n    public void setColumnDouble(double columnDouble) {\n        this.columnDouble = columnDouble;\n    }\n\n    public boolean isColumnBoolean() {\n        return columnBoolean;\n    }\n\n    public void setColumnBoolean(boolean columnBoolean) {\n        this.columnBoolean = columnBoolean;\n    }\n\n    public Date getColumnDate() {\n        return columnDate;\n    }\n\n    public void setColumnDate(Date columnDate) {\n        this.columnDate = columnDate;\n    }\n\n    public byte[] getColumnBinary() {\n        return columnBinary;\n    }\n\n    public MutableRealmInteger getColumnRealmInteger() {\n        return columnMutableRealmInteger;\n    }\n\n    public void setColumnMutableRealmInteger(int value) {\n        columnMutableRealmInteger.set(value);\n    }\n\n\n    public void setColumnBinary(byte[] columnBinary) {\n        this.columnBinary = columnBinary;\n    }\n\n    public Dog getColumnRealmObject() {\n        return columnRealmObject;\n    }\n\n    public void setColumnRealmObject(Dog columnRealmObject) {\n        this.columnRealmObject = columnRealmObject;\n    }\n\n    public AllTypes getColumnRealmLink() {\n        return columnRealmLink;\n    }\n\n    public void setColumnRealmLink(AllTypes columnRealmLink) {\n        this.columnRealmLink = columnRealmLink;\n    }\n\n    public RealmResults<AllTypes> getColumnRealmBackLink() {\n        return columnRealmBackLink;\n    }\n\n    public RealmList<Dog> getColumnRealmList() {\n        return columnRealmList;\n    }\n\n    public void setColumnRealmList(RealmList<Dog> columnRealmList) {\n        this.columnRealmList = columnRealmList;\n    }\n\n    public RealmList<String> getColumnStringList() {\n        return columnStringList;\n    }\n\n    public void setColumnStringList(RealmList<String> columnStringList) {\n        this.columnStringList = columnStringList;\n    }\n\n    public RealmList<byte[]> getColumnBinaryList() {\n        return columnBinaryList;\n    }\n\n    public void setColumnBinaryList(RealmList<byte[]> columnBinaryList) {\n        this.columnBinaryList = columnBinaryList;\n    }\n\n    public RealmList<Boolean> getColumnBooleanList() {\n        return columnBooleanList;\n    }\n\n    public void setColumnBooleanList(RealmList<Boolean> columnBooleanList) {\n        this.columnBooleanList = columnBooleanList;\n    }\n\n    public RealmList<Long> getColumnLongList() {\n        return columnLongList;\n    }\n\n    public void setColumnLongList(RealmList<Long> columnLongList) {\n        this.columnLongList = columnLongList;\n    }\n\n    public RealmList<Double> getColumnDoubleList() {\n        return columnDoubleList;\n    }\n\n    public void setColumnDoubleList(RealmList<Double> columnDoubleList) {\n        this.columnDoubleList = columnDoubleList;\n    }\n\n    public RealmList<Float> getColumnFloatList() {\n        return columnFloatList;\n    }\n\n    public void setColumnFloatList(RealmList<Float> columnFloatList) {\n        this.columnFloatList = columnFloatList;\n    }\n\n    public RealmList<Date> getColumnDateList() {\n        return columnDateList;\n    }\n\n    public void setColumnDateList(RealmList<Date> columnDateList) {\n        this.columnDateList = columnDateList;\n    }\n\n    public Decimal128 getColumnDecimal128() {\n        return columnDecimal128;\n    }\n\n    public void setColumnDecimal128(Decimal128 columnDecimal128) {\n        this.columnDecimal128 = columnDecimal128;\n    }\n\n    public ObjectId getColumnObjectId() {\n        return columnObjectId;\n    }\n\n    public void setColumnObjectId(ObjectId columnObjectId) {\n        this.columnObjectId = columnObjectId;\n    }\n\n    public UUID getColumnUUID() {\n        return columnUUID;\n    }\n\n    public void setColumnUUID(UUID columnUUID) {\n        this.columnUUID = columnUUID;\n    }\n\n    public RealmAny getColumnRealmAny() {\n        return columnRealmAny;\n    }\n\n    public void setColumnRealmAny(RealmAny columnRealmAny) {\n        this.columnRealmAny = columnRealmAny;\n    }\n\n    public RealmList<Decimal128> getColumnDecimal128List() {\n        return columnDecimal128List;\n    }\n\n    public void setColumnDecimal128List(RealmList<Decimal128> columnDecimal128List) {\n        this.columnDecimal128List = columnDecimal128List;\n    }\n\n    public RealmList<ObjectId> getColumnObjectIdList() {\n        return columnObjectIdList;\n    }\n\n    public void setColumnObjectIdList(RealmList<ObjectId> columnObjectIdList) {\n        this.columnObjectIdList = columnObjectIdList;\n    }\n\n    public RealmList<UUID> getColumnUUIDList() {\n        return columnUUIDList;\n    }\n\n    public void setColumnUUIDList(RealmList<UUID> columnUUIDList) {\n        this.columnUUIDList = columnUUIDList;\n    }\n\n    public RealmList<RealmAny> getColumnRealmAnyList() {\n        return columnRealmAnyList;\n    }\n\n    public void setColumnRealmAnyList(RealmList<RealmAny> columnRealmAnyList) {\n        this.columnRealmAnyList = columnRealmAnyList;\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/testUtils/java/io/realm/entities/AllTypesModelModule.java",
    "content": "/*\n * Copyright 2018 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 */\npackage io.realm.entities;\n\nimport io.realm.annotations.RealmModule;\n\n@RealmModule(classes = { AllTypes.class, Dog.class, Owner.class, Cat.class, DogPrimaryKey.class })\npublic class AllTypesModelModule {\n\n}\n\n"
  },
  {
    "path": "realm/realm-library/src/testUtils/java/io/realm/entities/AllTypesPrimaryKey.java",
    "content": "/*\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\npackage io.realm.entities;\n\nimport org.bson.types.Decimal128;\nimport org.bson.types.ObjectId;\n\nimport java.util.Date;\nimport java.util.UUID;\n\nimport io.realm.RealmAny;\nimport io.realm.RealmList;\nimport io.realm.RealmObject;\nimport io.realm.annotations.PrimaryKey;\n\npublic class AllTypesPrimaryKey extends RealmObject {\n    private String columnString;\n    @PrimaryKey\n    private long columnLong;\n    private float columnFloat;\n    private double columnDouble;\n    private boolean columnBoolean;\n    private Date columnDate;\n    private byte[] columnBinary;\n    private DogPrimaryKey columnRealmObject;\n    private RealmList<DogPrimaryKey> columnRealmList;\n    private Boolean columnBoxedBoolean;\n    private ObjectId columnObjectId;\n    private Decimal128 columnDecimal128;\n    private UUID columnUUID;\n    private RealmAny columnRealmAny;\n\n    private RealmList<String> columnStringList;\n    private RealmList<byte[]> columnBinaryList;\n    private RealmList<Boolean> columnBooleanList;\n    private RealmList<Long> columnLongList;\n    private RealmList<Double> columnDoubleList;\n    private RealmList<Float> columnFloatList;\n    private RealmList<Date> columnDateList;\n    private RealmList<ObjectId> columnObjectIdList;\n    private RealmList<Decimal128> columnDecimal128List;\n    private RealmList<UUID> columnUUIDList;\n    private RealmList<RealmAny> columnRealmAnyList;\n\n    public String getColumnString() {\n        return columnString;\n    }\n\n    public void setColumnString(String columnString) {\n        this.columnString = columnString;\n    }\n\n    public long getColumnLong() {\n        return columnLong;\n    }\n\n    public void setColumnLong(long columnLong) {\n        this.columnLong = columnLong;\n    }\n\n    public float getColumnFloat() {\n        return columnFloat;\n    }\n\n    public void setColumnFloat(float columnFloat) {\n        this.columnFloat = columnFloat;\n    }\n\n    public double getColumnDouble() {\n        return columnDouble;\n    }\n\n    public void setColumnDouble(double columnDouble) {\n        this.columnDouble = columnDouble;\n    }\n\n    public boolean isColumnBoolean() {\n        return columnBoolean;\n    }\n\n    public void setColumnBoolean(boolean columnBoolean) {\n        this.columnBoolean = columnBoolean;\n    }\n\n    public Date getColumnDate() {\n        return columnDate;\n    }\n\n    public void setColumnDate(Date columnDate) {\n        this.columnDate = columnDate;\n    }\n\n    public byte[] getColumnBinary() {\n        return columnBinary;\n    }\n\n    public void setColumnBinary(byte[] columnBinary) {\n        this.columnBinary = columnBinary;\n    }\n\n    public DogPrimaryKey getColumnRealmObject() {\n        return columnRealmObject;\n    }\n\n    public void setColumnRealmObject(DogPrimaryKey columnRealmObject) {\n        this.columnRealmObject = columnRealmObject;\n    }\n\n    public RealmList<DogPrimaryKey> getColumnRealmList() {\n        return columnRealmList;\n    }\n\n    public void setColumnRealmList(RealmList<DogPrimaryKey> columnRealmList) {\n        this.columnRealmList = columnRealmList;\n    }\n\n    public Boolean getColumnBoxedBoolean() {\n        return columnBoxedBoolean;\n    }\n\n    public void setColumnBoxedBoolean(Boolean columnBoxedBoolean) {\n        this.columnBoxedBoolean = columnBoxedBoolean;\n    }\n\n    public ObjectId getColumnObjectId() {\n        return columnObjectId;\n    }\n\n    public void setColumnObjectId(ObjectId columnObjectId) {\n        this.columnObjectId = columnObjectId;\n    }\n\n    public Decimal128 getColumnDecimal128() {\n        return columnDecimal128;\n    }\n\n    public void setColumnDecimal128(Decimal128 columnDecimal128) {\n        this.columnDecimal128 = columnDecimal128;\n    }\n\n    public UUID getColumnUUID() {\n        return columnUUID;\n    }\n\n    public void setColumnUUID(UUID columnUUID) {\n        this.columnUUID = columnUUID;\n    }\n\n    public RealmAny getColumnRealmAny() {\n        return columnRealmAny;\n    }\n\n    public void setColumnRealmAny(RealmAny columnRealmAny) {\n        this.columnRealmAny = columnRealmAny;\n    }\n\n    public RealmList<String> getColumnStringList() {\n        return columnStringList;\n    }\n\n    public void setColumnStringList(RealmList<String> columnStringList) {\n        this.columnStringList = columnStringList;\n    }\n\n    public RealmList<byte[]> getColumnBinaryList() {\n        return columnBinaryList;\n    }\n\n    public void setColumnBinaryList(RealmList<byte[]> columnBinaryList) {\n        this.columnBinaryList = columnBinaryList;\n    }\n\n    public RealmList<Boolean> getColumnBooleanList() {\n        return columnBooleanList;\n    }\n\n    public void setColumnBooleanList(RealmList<Boolean> columnBooleanList) {\n        this.columnBooleanList = columnBooleanList;\n    }\n\n    public RealmList<Long> getColumnLongList() {\n        return columnLongList;\n    }\n\n    public void setColumnLongList(RealmList<Long> columnLongList) {\n        this.columnLongList = columnLongList;\n    }\n\n    public RealmList<Double> getColumnDoubleList() {\n        return columnDoubleList;\n    }\n\n    public void setColumnDoubleList(RealmList<Double> columnDoubleList) {\n        this.columnDoubleList = columnDoubleList;\n    }\n\n    public RealmList<Float> getColumnFloatList() {\n        return columnFloatList;\n    }\n\n    public void setColumnFloatList(RealmList<Float> columnFloatList) {\n        this.columnFloatList = columnFloatList;\n    }\n\n    public RealmList<Date> getColumnDateList() {\n        return columnDateList;\n    }\n\n    public void setColumnDateList(RealmList<Date> columnDateList) {\n        this.columnDateList = columnDateList;\n    }\n\n    public RealmList<ObjectId> getColumnObjectIdList() {\n        return columnObjectIdList;\n    }\n\n    public void setColumnObjectIdList(RealmList<ObjectId> columnObjectIdList) {\n        this.columnObjectIdList = columnObjectIdList;\n    }\n\n    public RealmList<Decimal128> getColumnDecimal128List() {\n        return columnDecimal128List;\n    }\n\n    public void setColumnDecimal128List(RealmList<Decimal128> columnDecimal128List) {\n        this.columnDecimal128List = columnDecimal128List;\n    }\n\n    public RealmList<UUID> getColumnUUIDList() {\n        return columnUUIDList;\n    }\n\n    public void setColumnUUIDList(RealmList<UUID> columnUUIDList) {\n        this.columnUUIDList = columnUUIDList;\n    }\n\n    public RealmList<RealmAny> getColumnRealmAnyList() {\n        return columnRealmAnyList;\n    }\n\n    public void setColumnRealmAnyList(RealmList<RealmAny> columnRealmAnyList) {\n        this.columnRealmAnyList = columnRealmAnyList;\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/testUtils/java/io/realm/entities/AnnotationIndexTypes.java",
    "content": "/*\n * Copyright 2015 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\npackage io.realm.entities;\n\nimport java.util.Date;\n\nimport io.realm.RealmObject;\nimport io.realm.annotations.Index;\n\n// Class for testing annotation index only\npublic class AnnotationIndexTypes extends RealmObject {\n\n    public static final String CLASS_NAME = \"AnnotationIndexTypes\";\n\n    public static final String FIELD_INDEX_STRING = \"indexString\";\n    public static final String FIELD_INDEX_INT = \"indexInt\";\n    public static final String FIELD_INDEX_BYTE = \"indexByte\";\n    public static final String FIELD_INDEX_SHORT = \"indexShort\";\n    public static final String FIELD_INDEX_LONG = \"indexLong\";\n    public static final String FIELD_INDEX_BOOL = \"indexBoolean\";\n    public static final String FIELD_INDEX_DATE = \"indexDate\";\n\n    public static final String FIELD_NOT_INDEX_STRING = \"notIndexString\";\n    public static final String FIELD_NOT_INDEX_INT = \"notIndexInt\";\n    public static final String FIELD_NOT_INDEX_BYTE = \"notIndexByte\";\n    public static final String FIELD_NOT_INDEX_SHORT = \"notIndexShort\";\n    public static final String FIELD_NOT_INDEX_LONG = \"notIndexLong\";\n    public static final String FIELD_NOT_INDEX_BOOL = \"notIndexBoolean\";\n    public static final String FIELD_NOT_INDEX_DATE = \"notIndexDate\";\n\n    public static final String FIELD_OBJECT = \"fieldObject\";\n\n    public static final String[] INDEX_FIELDS = new String[]{FIELD_INDEX_STRING, FIELD_INDEX_INT, FIELD_INDEX_BYTE, FIELD_INDEX_SHORT, FIELD_INDEX_LONG, FIELD_INDEX_BOOL, FIELD_INDEX_DATE};\n    public static final String[] NOT_INDEX_FIELDS = new String[]{FIELD_NOT_INDEX_STRING, FIELD_NOT_INDEX_INT, FIELD_NOT_INDEX_BYTE, FIELD_NOT_INDEX_SHORT, FIELD_NOT_INDEX_LONG, FIELD_NOT_INDEX_BOOL, FIELD_NOT_INDEX_DATE};\n    public static final String   INDEX_LINKED_FIELD_STRING = AnnotationIndexTypes.FIELD_OBJECT + \".\" + AnnotationIndexTypes.FIELD_INDEX_STRING;\n    public static final String[] INDEX_LINKED_FIELDS = new String[]{FIELD_OBJECT + \".\" + FIELD_INDEX_STRING, FIELD_OBJECT + \".\" + FIELD_INDEX_INT};\n    public static final String   NOT_INDEX_LINKED_FILED_STRING = FIELD_OBJECT + \".\" + FIELD_NOT_INDEX_STRING;\n    public static final String[] NOT_INDEX_LINKED_FIELDS = new String[]{FIELD_OBJECT + \".\" + FIELD_NOT_INDEX_STRING, FIELD_OBJECT + \".\" + FIELD_NOT_INDEX_INT};\n    public static final String[] NONEXISTANT_MIX_FIELDS = new String[]{FIELD_INDEX_INT, \"doesNotExists\", FIELD_INDEX_STRING};\n\n    @Index\n    private String indexString;\n    private String notIndexString;\n\n    @Index\n    private int indexInt;\n    private int notIndexInt;\n\n    @Index\n    private byte indexByte;\n    private byte notIndexByte;\n\n    @Index\n    private short indexShort;\n    private short notIndexShort;\n\n    @Index\n    private long indexLong;\n    private long notIndexLong;\n\n    @Index\n    private boolean indexBoolean;\n    private boolean notIndexBoolean;\n\n    @Index\n    private Date indexDate;\n    private Date notIndexDate;\n\n    private AnnotationIndexTypes fieldObject;\n\n    public String getIndexString() {\n        return indexString;\n    }\n\n    public void setIndexString(String indexString) {\n        this.indexString = indexString;\n    }\n\n    public String getNotIndexString() {\n        return notIndexString;\n    }\n\n    public void setNotIndexString(String notIndexString) {\n        this.notIndexString = notIndexString;\n    }\n\n    public int getIndexInt() {\n        return indexInt;\n    }\n\n    public void setIndexInt(int indexInt) {\n        this.indexInt = indexInt;\n    }\n\n    public int getNotIndexInt() {\n        return notIndexInt;\n    }\n\n    public void setNotIndexInt(int notIndexInt) {\n        this.notIndexInt = notIndexInt;\n    }\n\n    public short getIndexShort() {\n        return indexShort;\n    }\n\n    public void setIndexShort(short indexShort) {\n        this.indexShort = indexShort;\n    }\n\n    public byte getIndexByte() {\n        return indexByte;\n    }\n\n    public void setIndexByte(byte indexByte) {\n        this.indexByte = indexByte;\n    }\n\n    public byte getNotIndexByte() {\n        return notIndexByte;\n    }\n\n    public void setNotIndexByte(byte notIndexByte) {\n        this.notIndexByte = notIndexByte;\n    }\n\n    public short getNotIndexShort() {\n        return notIndexShort;\n    }\n\n    public void setNotIndexShort(short notIndexShort) {\n        this.notIndexShort = notIndexShort;\n    }\n\n    public long getIndexLong() {\n        return indexLong;\n    }\n\n    public void setIndexLong(long indexLong) {\n        this.indexLong = indexLong;\n    }\n\n    public long getNotIndexLong() {\n        return notIndexLong;\n    }\n\n    public void setNotIndexLong(long notIndexLong) {\n        this.notIndexLong = notIndexLong;\n    }\n\n    public boolean isIndexBoolean() {\n        return indexBoolean;\n    }\n\n    public void setIndexBoolean(boolean indexBoolean) {\n        this.indexBoolean = indexBoolean;\n    }\n\n    public boolean isNotIndexBoolean() {\n        return notIndexBoolean;\n    }\n\n    public void setNotIndexBoolean(boolean notIndexBoolean) {\n        this.notIndexBoolean = notIndexBoolean;\n    }\n\n    public Date getIndexDate() {\n        return indexDate;\n    }\n\n    public void setIndexDate(Date indexDate) {\n        this.indexDate = indexDate;\n    }\n\n    public Date getNotIndexDate() {\n        return notIndexDate;\n    }\n\n    public void setNotIndexDate(Date notIndexDate) {\n        this.notIndexDate = notIndexDate;\n    }\n\n    public void setFieldObject(AnnotationIndexTypes object) {\n        this.fieldObject = object;\n    }\n\n    public AnnotationIndexTypes getFieldObject() { return this.fieldObject; }\n}\n"
  },
  {
    "path": "realm/realm-library/src/testUtils/java/io/realm/entities/BacklinkWithOverridenNames.java",
    "content": "/*\n * Copyright 2019 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 */\npackage io.realm.entities;\n\nimport io.realm.RealmObject;\nimport io.realm.RealmResults;\nimport io.realm.annotations.LinkingObjects;\nimport io.realm.annotations.PrimaryKey;\nimport io.realm.annotations.RealmClass;\nimport io.realm.annotations.RealmField;\n\n@RealmClass(name = \"backlink_override_name\")\npublic class BacklinkWithOverridenNames extends RealmObject {\n\n    @PrimaryKey\n    public String id;\n\n    @RealmField(name = \"forward_link\")\n    public BacklinkWithOverridenNames child;\n\n    @LinkingObjects(\"child\")\n    public final RealmResults<BacklinkWithOverridenNames> parents = null;\n\n    public BacklinkWithOverridenNames() {\n\n    }\n\n    public BacklinkWithOverridenNames(String id) {\n        this.id = id;\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/testUtils/java/io/realm/entities/BacklinksSource.java",
    "content": "/*\n * Copyright 2017 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 */\npackage io.realm.entities;\n\nimport io.realm.RealmObject;\n\npublic class BacklinksSource extends RealmObject {\n    public static final String CLASS_NAME = \"BacklinksSource\";\n    public static final String FIELD_NAME = \"name\";\n    public static final String FIELD_CHILD = \"child\";\n\n\n    private String name;\n\n    private BacklinksTarget child;\n\n    public String getName() {\n        return name;\n    }\n\n    public void setName(String name) {\n        this.name = name;\n    }\n\n    public BacklinksTarget getChild() {\n        return child;\n    }\n\n    public void setChild(BacklinksTarget child) {\n        this.child = child;\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/testUtils/java/io/realm/entities/BacklinksTarget.java",
    "content": "/*\n * Copyright 2017 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 */\npackage io.realm.entities;\n\nimport io.realm.RealmObject;\nimport io.realm.RealmResults;\nimport io.realm.annotations.LinkingObjects;\n\npublic class BacklinksTarget extends RealmObject {\n    public static final String CLASS_NAME = \"BacklinksTarget\";\n    public static final String FIELD_ID = \"id\";\n    public static final String FIELD_PARENTS = \"parents\";\n\n    private int id;\n\n    @LinkingObjects(BacklinksSource.FIELD_CHILD)\n    private final RealmResults<BacklinksSource> parents = null;\n\n    public int getId() {\n        return id;\n    }\n\n    public void setId(int id) {\n        this.id = id;\n    }\n\n    public RealmResults<BacklinksSource> getParents() {\n        return parents;\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/testUtils/java/io/realm/entities/Cat.java",
    "content": "/*\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\npackage io.realm.entities;\n\nimport java.util.Date;\n\nimport io.realm.RealmObject;\n\npublic class Cat extends RealmObject {\n\n    public static final String CLASS_NAME = \"Cat\";\n    public static final String FIELD_NAME = \"name\";\n    public static final String FIELD_AGE = \"age\";\n    public static final String FIELD_HEIGHT = \"height\";\n    public static final String FIELD_WEIGHT = \"weight\";\n    public static final String FIELD_HAS_TAIL = \"hasTail\";\n    public static final String FIELD_BIRTHDAY = \"birthday\";\n    public static final String FIELD_OWNER = \"owner\";\n    public static final String FIELD_SCARED_OF_DOG = \"scaredOfDog\";\n\n    private String name;\n    private long age;\n    private float height;\n    private double weight;\n    private boolean hasTail;\n    private Date birthday;\n    private Owner owner;\n    private DogPrimaryKey scaredOfDog;\n\n    public Owner getOwner() {\n        return owner;\n    }\n\n    public void setOwner(Owner owner) {\n        this.owner = owner;\n    }\n\n    public Date getBirthday() {\n        return birthday;\n    }\n\n    public void setBirthday(Date birthday) {\n        this.birthday = birthday;\n    }\n\n    public boolean isHasTail() {\n        return hasTail;\n    }\n\n    public void setHasTail(boolean hasTail) {\n        this.hasTail = hasTail;\n    }\n\n\n    public double getWeight() {\n        return weight;\n    }\n\n    public void setWeight(double weight) {\n        this.weight = weight;\n    }\n\n    public float getHeight() {\n        return height;\n    }\n\n    public void setHeight(float height) {\n        this.height = height;\n    }\n\n    public long getAge() {\n        return age;\n    }\n\n    public void setAge(long age) {\n        this.age = age;\n    }\n\n    public String getName() {\n        return name;\n    }\n\n    public void setName(String name) {\n        this.name = name;\n    }\n\n    public DogPrimaryKey getScaredOfDog() {\n        return scaredOfDog;\n    }\n\n    public void setScaredOfDog(DogPrimaryKey scaredOfDog) {\n        this.scaredOfDog = scaredOfDog;\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/testUtils/java/io/realm/entities/Dog.java",
    "content": "/*\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\npackage io.realm.entities;\n\nimport java.util.Date;\n\nimport io.realm.RealmObject;\nimport io.realm.annotations.Index;\n\npublic class Dog extends RealmObject {\n\n    public static final String CLASS_NAME = \"Dog\";\n    public static final String FIELD_NAME = \"name\";\n    public static final String FIELD_AGE = \"age\";\n    public static final String FIELD_HEIGHT = \"height\";\n    public static final String FIELD_WEIGHT = \"weight\";\n    public static final String FIELD_BIRTHDAY = \"birthday\";\n    public static final String FIELD_HAS_TAIL = \"hasTail\";\n\n    @Index\n    private String name;\n    private long age;\n    private float height;\n    private double weight;\n    private boolean hasTail;\n    private Date birthday;\n    private Owner owner;\n\n    public Dog() {\n    }\n\n    public Dog(String name) {\n        this.name = name;\n    }\n    public Dog(String name, long age) {\n        this.name = name;\n        this.age = age;\n    }\n\n    public Owner getOwner() {\n        return owner;\n    }\n\n    public void setOwner(Owner owner) {\n        this.owner = owner;\n    }\n\n    public Date getBirthday() {\n        return birthday;\n    }\n\n    public void setBirthday(Date birthday) {\n        this.birthday = birthday;\n    }\n\n    public boolean isHasTail() {\n        return hasTail;\n    }\n\n    public void setHasTail(boolean hasTail) {\n        this.hasTail = hasTail;\n    }\n\n    public double getWeight() {\n        return weight;\n    }\n\n    public void setWeight(double weight) {\n        this.weight = weight;\n    }\n\n    public float getHeight() {\n        return height;\n    }\n\n    public void setHeight(float height) {\n        this.height = height;\n    }\n\n    public long getAge() {\n        return age;\n    }\n\n    public void setAge(long age) {\n        this.age = age;\n    }\n\n    public String getName() {\n        return name;\n    }\n\n    public void setName(String name) {\n        this.name = name;\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/testUtils/java/io/realm/entities/DogPrimaryKey.java",
    "content": "/*\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\npackage io.realm.entities;\n\nimport java.util.Date;\n\nimport io.realm.RealmObject;\nimport io.realm.annotations.PrimaryKey;\n\npublic class DogPrimaryKey extends RealmObject {\n\n    public static final String CLASS_NAME = \"DogPrimaryKey\";\n    public static final String AGE = \"age\";\n    public static final String BIRTHDAY = \"birthday\";\n    public static final String ID = \"id\";\n\n    @PrimaryKey\n    private long id;\n    private String name;\n    private long age;\n    private float height;\n    private double weight;\n    private boolean hasTail;\n    private Date birthday;\n    private Owner owner;\n\n    public DogPrimaryKey() {\n\n    }\n\n    public DogPrimaryKey(long id, String name) {\n        this.id = id;\n        this.name = name;\n    }\n\n    public DogPrimaryKey(String name) {\n        this.name = name;\n    }\n\n\n    public long getId() {\n        return id;\n    }\n\n    public void setId(long id) {\n        this.id = id;\n    }\n\n    public Owner getOwner() {\n        return owner;\n    }\n\n    public void setOwner(Owner owner) {\n        this.owner = owner;\n    }\n\n    public Date getBirthday() {\n        return birthday;\n    }\n\n    public void setBirthday(Date birthday) {\n        this.birthday = birthday;\n    }\n\n    public boolean isHasTail() {\n        return hasTail;\n    }\n\n    public void setHasTail(boolean hasTail) {\n        this.hasTail = hasTail;\n    }\n\n    public double getWeight() {\n        return weight;\n    }\n\n    public void setWeight(double weight) {\n        this.weight = weight;\n    }\n\n    public float getHeight() {\n        return height;\n    }\n\n    public void setHeight(float height) {\n        this.height = height;\n    }\n\n    public long getAge() {\n        return age;\n    }\n\n    public void setAge(long age) {\n        this.age = age;\n    }\n\n    public String getName() {\n        return name;\n    }\n\n    public void setName(String name) {\n        this.name = name;\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/testUtils/java/io/realm/entities/KeywordFieldNames.java",
    "content": "package io.realm.entities;\n\nimport io.realm.RealmObject;\n\npublic class KeywordFieldNames extends RealmObject {\n    public String desc;\n    public String sort;\n    public String distinct;\n    public String limit;\n}"
  },
  {
    "path": "realm/realm-library/src/testUtils/java/io/realm/entities/NullTypes.java",
    "content": "/*\n * Copyright 2015 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\npackage io.realm.entities;\n\nimport org.bson.types.Decimal128;\nimport org.bson.types.ObjectId;\n\nimport java.math.BigDecimal;\nimport java.util.Date;\nimport java.util.UUID;\n\nimport io.realm.RealmList;\nimport io.realm.RealmObject;\nimport io.realm.RealmResults;\nimport io.realm.TestHelper;\nimport io.realm.annotations.LinkingObjects;\nimport io.realm.annotations.PrimaryKey;\nimport io.realm.annotations.Required;\n\n// Always follow below order and put comments like below to make NullTypes Related cases\n// 1 String\n// 2 Bytes\n// 3 Boolean\n// 4 Byte\n// 5 Short\n// 6 Integer\n// 7 Long\n// 8 Float\n// 9 Double\n// 10 Date\n// 11 Object\npublic class NullTypes extends RealmObject {\n\n    public static final String CLASS_NAME = \"NullTypes\";\n    public static final String FIELD_ID = \"id\";\n    public static final String FIELD_STRING_NOT_NULL = \"fieldStringNotNull\";\n    public static final String FIELD_STRING_NULL = \"fieldStringNull\";\n    public static final String FIELD_BYTES_NOT_NULL = \"fieldBytesNotNull\";\n    public static final String FIELD_BYTES_NULL = \"fieldBytesNull\";\n    public static final String FIELD_BOOLEAN_NOT_NULL = \"fieldBooleanNotNull\";\n    public static final String FIELD_BOOLEAN_NULL = \"fieldBooleanNull\";\n    public static final String FIELD_BYTE_NOT_NULL = \"fieldByteNotNull\";\n    public static final String FIELD_BYTE_NULL = \"fieldByteNull\";\n    public static final String FIELD_SHORT_NOT_NULL = \"fieldShortNotNull\";\n    public static final String FIELD_SHORT_NULL = \"fieldShortNull\";\n    public static final String FIELD_INTEGER_NOT_NULL = \"fieldIntegerNotNull\";\n    public static final String FIELD_INTEGER_NULL = \"fieldIntegerNull\";\n    public static final String FIELD_LONG_NOT_NULL = \"fieldLongNotNull\";\n    public static final String FIELD_LONG_NULL = \"fieldLongNull\";\n    public static final String FIELD_FLOAT_NOT_NULL = \"fieldFloatNotNull\";\n    public static final String FIELD_FLOAT_NULL = \"fieldFloatNull\";\n    public static final String FIELD_DOUBLE_NOT_NULL = \"fieldDoubleNotNull\";\n    public static final String FIELD_DOUBLE_NULL = \"fieldDoubleNull\";\n    public static final String FIELD_DATE_NOT_NULL = \"fieldDateNotNull\";\n    public static final String FIELD_DATE_NULL = \"fieldDateNull\";\n    public static final String FIELD_DECIMAL128_NULL = \"fieldDecimal128Null\";\n    public static final String FIELD_DECIMAL128_NOT_NULL = \"fieldDecimal128NotNull\";\n    public static final String FIELD_OBJECT_ID_NULL = \"fieldObjectIdNull\";\n    public static final String FIELD_OBJECT_ID_NOT_NULL = \"fieldObjectIdNotNull\";\n    public static final String FIELD_UUID_NULL = \"fieldUUIDNull\";\n    public static final String FIELD_UUID_NOT_NULL = \"fieldUUIDNotNull\";\n    public static final String FIELD_OBJECT_NULL = \"fieldObjectNull\";\n    public static final String FIELD_LIST_NULL = \"fieldListNull\";\n    public static final String FIELD_LO_OBJECT = \"objectParents\";\n    public static final String FIELD_LO_LIST = \"listParents\";\n\n    public static final String FIELD_STRING_LIST_NOT_NULL = \"fieldStringListNotNull\";\n    public static final String FIELD_STRING_LIST_NULL = \"fieldStringListNull\";\n    public static final String FIELD_BINARY_LIST_NOT_NULL = \"fieldBinaryListNotNull\";\n    public static final String FIELD_BINARY_LIST_NULL = \"fieldBinaryListNull\";\n    public static final String FIELD_BOOLEAN_LIST_NOT_NULL = \"fieldBooleanListNotNull\";\n    public static final String FIELD_BOOLEAN_LIST_NULL = \"fieldBooleanListNull\";\n    public static final String FIELD_LONG_LIST_NOT_NULL = \"fieldLongListNotNull\";\n    public static final String FIELD_LONG_LIST_NULL = \"fieldLongListNull\";\n    public static final String FIELD_INTEGER_LIST_NOT_NULL = \"fieldIntegerListNotNull\";\n    public static final String FIELD_INTEGER_LIST_NULL = \"fieldIntegerListNull\";\n    public static final String FIELD_SHORT_LIST_NOT_NULL = \"fieldShortListNotNull\";\n    public static final String FIELD_SHORT_LIST_NULL = \"fieldShortListNull\";\n    public static final String FIELD_BYTE_LIST_NOT_NULL = \"fieldByteListNotNull\";\n    public static final String FIELD_BYTE_LIST_NULL = \"fieldByteListNull\";\n    public static final String FIELD_DOUBLE_LIST_NOT_NULL = \"fieldDoubleListNotNull\";\n    public static final String FIELD_DOUBLE_LIST_NULL = \"fieldDoubleListNull\";\n    public static final String FIELD_FLOAT_LIST_NOT_NULL = \"fieldFloatListNotNull\";\n    public static final String FIELD_FLOAT_LIST_NULL = \"fieldFloatListNull\";\n    public static final String FIELD_DATE_LIST_NOT_NULL = \"fieldDateListNotNull\";\n    public static final String FIELD_DATE_LIST_NULL = \"fieldDateListNull\";\n    public static final String FIELD_DECIMAL128_LIST_NULL = \"fieldDecimal128ListNull\";\n    public static final String FIELD_DECIMAL128_LIST_NOT_NULL = \"fieldDecimal128ListNotNull\";\n    public static final String FIELD_OBJECT_ID_LIST_NULL = \"fieldObjectIdListNull\";\n    public static final String FIELD_OBJECT_ID_LIST_NOT_NULL = \"fieldObjectIdListNotNull\";\n    public static final String FIELD_UUID_LIST_NULL = \"fieldUUIDListNull\";\n    public static final String FIELD_UUID_LIST_NOT_NULL = \"fieldUUIDListNotNull\";\n\n    @PrimaryKey\n    private int id;\n\n    @Required\n    private String fieldStringNotNull = \"\";\n    private String fieldStringNull;\n\n    @Required\n    private byte[] fieldBytesNotNull = new byte[0];\n    private byte[] fieldBytesNull;\n\n    @Required\n    private Boolean fieldBooleanNotNull = false;\n    private Boolean fieldBooleanNull;\n\n    @Required\n    private Byte fieldByteNotNull = 0;\n    private Byte fieldByteNull;\n\n    @Required\n    private Short fieldShortNotNull = 0;\n    private Short fieldShortNull;\n\n    @Required\n    private Integer fieldIntegerNotNull = 0;\n    private Integer fieldIntegerNull;\n\n    @Required\n    private Long fieldLongNotNull = 0L;\n    private Long fieldLongNull;\n\n    @Required\n    private Float fieldFloatNotNull = 0F;\n    private Float fieldFloatNull;\n\n    @Required\n    private Double fieldDoubleNotNull = 0D;\n    private Double fieldDoubleNull;\n\n    @Required\n    private Date fieldDateNotNull = new Date(0);\n    private Date fieldDateNull;\n\n    @Required\n    private Decimal128 fieldDecimal128NotNull = new Decimal128(BigDecimal.ZERO);\n    private Decimal128 fieldDecimal128Null;\n\n    @Required\n    private ObjectId fieldObjectIdNotNull = new ObjectId(TestHelper.generateObjectIdHexString(0));\n    private ObjectId fieldObjectIdNull;\n\n    @Required\n    private UUID fieldUUIDNotNull = UUID.randomUUID();\n    private UUID fieldUUIDNull;\n\n    private NullTypes fieldObjectNull;\n\n    // never nullable\n    private RealmList<NullTypes> fieldListNull;\n\n    @Required\n    private RealmList<String> fieldStringListNotNull;\n    private RealmList<String> fieldStringListNull;\n\n    @Required\n    private RealmList<byte[]> fieldBinaryListNotNull;\n    private RealmList<byte[]> fieldBinaryListNull;\n\n    @Required\n    private RealmList<Boolean> fieldBooleanListNotNull;\n    private RealmList<Boolean> fieldBooleanListNull;\n\n    @Required\n    private RealmList<Long> fieldLongListNotNull;\n    private RealmList<Long> fieldLongListNull;\n\n    @Required\n    private RealmList<Integer> fieldIntegerListNotNull;\n    private RealmList<Integer> fieldIntegerListNull;\n\n    @Required\n    private RealmList<Short> fieldShortListNotNull;\n    private RealmList<Short> fieldShortListNull;\n\n    @Required\n    private RealmList<Byte> fieldByteListNotNull;\n    private RealmList<Byte> fieldByteListNull;\n\n    @Required\n    private RealmList<Double> fieldDoubleListNotNull;\n    private RealmList<Double> fieldDoubleListNull;\n\n    @Required\n    private RealmList<Float> fieldFloatListNotNull;\n    private RealmList<Float> fieldFloatListNull;\n\n    @Required\n    private RealmList<Date> fieldDateListNotNull;\n    private RealmList<Date> fieldDateListNull;\n\n    @Required\n    private RealmList<Decimal128> fieldDecimal128ListNotNull;\n    private RealmList<Decimal128> fieldDecimal128ListNull;\n\n    @Required\n    private RealmList<ObjectId> fieldObjectIdListNotNull;\n    private RealmList<ObjectId> fieldObjectIdListNull;\n\n    @Required\n    private RealmList<UUID> fieldUUIDListNotNull;\n    private RealmList<UUID> fieldUUIDListNull;\n\n    // never nullable\n    @LinkingObjects(FIELD_OBJECT_NULL)\n    private final RealmResults<NullTypes> objectParents = null;\n\n    // never nullable\n    @LinkingObjects(FIELD_LIST_NULL)\n    private final RealmResults<NullTypes> listParents = null;\n\n    public int getId() {\n        return id;\n    }\n\n    public void setId(int id) {\n        this.id = id;\n    }\n\n    public String getFieldStringNotNull() {\n        return fieldStringNotNull;\n    }\n\n    public void setFieldStringNotNull(String fieldStringNotNull) {\n        this.fieldStringNotNull = fieldStringNotNull;\n    }\n\n    public String getFieldStringNull() {\n        return fieldStringNull;\n    }\n\n    public void setFieldStringNull(String fieldStringNull) {\n        this.fieldStringNull = fieldStringNull;\n    }\n\n    public byte[] getFieldBytesNull() {\n        return fieldBytesNull;\n    }\n\n    public void setFieldBytesNull(byte[] fieldBytesNull) {\n        this.fieldBytesNull = fieldBytesNull;\n    }\n\n    public byte[] getFieldBytesNotNull() {\n        return fieldBytesNotNull;\n    }\n\n    public void setFieldBytesNotNull(byte[] fieldBytesNotNull) {\n        this.fieldBytesNotNull = fieldBytesNotNull;\n    }\n\n    public Boolean getFieldBooleanNotNull() {\n        return fieldBooleanNotNull;\n    }\n\n    public void setFieldBooleanNotNull(Boolean fieldBooleanNotNull) {\n        this.fieldBooleanNotNull = fieldBooleanNotNull;\n    }\n\n    public Boolean getFieldBooleanNull() {\n        return fieldBooleanNull;\n    }\n\n    public void setFieldBooleanNull(Boolean fieldBooleanNull) {\n        this.fieldBooleanNull = fieldBooleanNull;\n    }\n\n    public Byte getFieldByteNotNull() {\n        return fieldByteNotNull;\n    }\n\n    public void setFieldByteNotNull(Byte fieldByteNotNull) {\n        this.fieldByteNotNull = fieldByteNotNull;\n    }\n\n    public Byte getFieldByteNull() {\n        return fieldByteNull;\n    }\n\n    public void setFieldByteNull(Byte fieldByteNull) {\n        this.fieldByteNull = fieldByteNull;\n    }\n\n    public Short getFieldShortNotNull() {\n        return fieldShortNotNull;\n    }\n\n    public void setFieldShortNotNull(Short fieldShortNotNull) {\n        this.fieldShortNotNull = fieldShortNotNull;\n    }\n\n    public Short getFieldShortNull() {\n        return fieldShortNull;\n    }\n\n    public void setFieldShortNull(Short fieldShortNull) {\n        this.fieldShortNull = fieldShortNull;\n    }\n\n    public Integer getFieldIntegerNotNull() {\n        return fieldIntegerNotNull;\n    }\n\n    public void setFieldIntegerNotNull(Integer fieldIntegerNotNull) {\n        this.fieldIntegerNotNull = fieldIntegerNotNull;\n    }\n\n    public Integer getFieldIntegerNull() {\n        return fieldIntegerNull;\n    }\n\n    public void setFieldIntegerNull(Integer fieldIntegerNull) {\n        this.fieldIntegerNull = fieldIntegerNull;\n    }\n\n    public Long getFieldLongNotNull() {\n        return fieldLongNotNull;\n    }\n\n    public void setFieldLongNotNull(Long fieldLongNotNull) {\n        this.fieldLongNotNull = fieldLongNotNull;\n    }\n\n    public Long getFieldLongNull() {\n        return fieldLongNull;\n    }\n\n    public void setFieldLongNull(Long fieldLongNull) {\n        this.fieldLongNull = fieldLongNull;\n    }\n\n    public Float getFieldFloatNotNull() {\n        return fieldFloatNotNull;\n    }\n\n    public void setFieldFloatNotNull(Float fieldFloatNotNull) {\n        this.fieldFloatNotNull = fieldFloatNotNull;\n    }\n\n    public Float getFieldFloatNull() {\n        return fieldFloatNull;\n    }\n\n    public void setFieldFloatNull(Float fieldFloatNull) {\n        this.fieldFloatNull = fieldFloatNull;\n    }\n\n    public Double getFieldDoubleNotNull() {\n        return fieldDoubleNotNull;\n    }\n\n    public void setFieldDoubleNotNull(Double fieldDoubleNotNull) {\n        this.fieldDoubleNotNull = fieldDoubleNotNull;\n    }\n\n    public Double getFieldDoubleNull() {\n        return fieldDoubleNull;\n    }\n\n    public void setFieldDoubleNull(Double fieldDoubleNull) {\n        this.fieldDoubleNull = fieldDoubleNull;\n    }\n\n    public Date getFieldDateNotNull() {\n        return fieldDateNotNull;\n    }\n\n    public void setFieldDateNotNull(Date fieldDateNotNull) {\n        this.fieldDateNotNull = fieldDateNotNull;\n    }\n\n    public Date getFieldDateNull() {\n        return fieldDateNull;\n    }\n\n    public void setFieldDateNull(Date fieldDateNull) {\n        this.fieldDateNull = fieldDateNull;\n    }\n\n    public NullTypes getFieldObjectNull() {\n        return fieldObjectNull;\n    }\n\n    public void setFieldObjectNull(NullTypes fieldObjectNull) {\n        this.fieldObjectNull = fieldObjectNull;\n    }\n\n    public RealmList<NullTypes> getFieldListNull() {\n        return fieldListNull;\n    }\n\n    public void setFieldListNull(RealmList<NullTypes> fieldListNull) {\n        this.fieldListNull = fieldListNull;\n    }\n\n    public RealmResults<NullTypes> getObjectParents() {\n        return objectParents;\n    }\n\n    public RealmResults<NullTypes> getListParents() {\n        return listParents;\n    }\n\n    public RealmList<String> getFieldStringListNotNull() {\n        return fieldStringListNotNull;\n    }\n\n    public void setFieldStringListNotNull(RealmList<String> fieldStringListNotNull) {\n        this.fieldStringListNotNull = fieldStringListNotNull;\n    }\n\n    public RealmList<String> getFieldStringListNull() {\n        return fieldStringListNull;\n    }\n\n    public void setFieldStringListNull(RealmList<String> fieldStringListNull) {\n        this.fieldStringListNull = fieldStringListNull;\n    }\n\n    public RealmList<byte[]> getFieldBinaryListNotNull() {\n        return fieldBinaryListNotNull;\n    }\n\n    public void setFieldBinaryListNotNull(RealmList<byte[]> fieldBinaryListNotNull) {\n        this.fieldBinaryListNotNull = fieldBinaryListNotNull;\n    }\n\n    public RealmList<byte[]> getFieldBinaryListNull() {\n        return fieldBinaryListNull;\n    }\n\n    public void setFieldBinaryListNull(RealmList<byte[]> fieldBinaryListNull) {\n        this.fieldBinaryListNull = fieldBinaryListNull;\n    }\n\n    public RealmList<Boolean> getFieldBooleanListNotNull() {\n        return fieldBooleanListNotNull;\n    }\n\n    public void setFieldBooleanListNotNull(RealmList<Boolean> fieldBooleanListNotNull) {\n        this.fieldBooleanListNotNull = fieldBooleanListNotNull;\n    }\n\n    public RealmList<Boolean> getFieldBooleanListNull() {\n        return fieldBooleanListNull;\n    }\n\n    public void setFieldBooleanListNull(RealmList<Boolean> fieldBooleanListNull) {\n        this.fieldBooleanListNull = fieldBooleanListNull;\n    }\n\n    public RealmList<Long> getFieldLongListNotNull() {\n        return fieldLongListNotNull;\n    }\n\n    public void setFieldLongListNotNull(RealmList<Long> fieldLongListNotNull) {\n        this.fieldLongListNotNull = fieldLongListNotNull;\n    }\n\n    public RealmList<Long> getFieldLongListNull() {\n        return fieldLongListNull;\n    }\n\n    public void setFieldLongListNull(RealmList<Long> fieldLongListNull) {\n        this.fieldLongListNull = fieldLongListNull;\n    }\n\n    public RealmList<Integer> getFieldIntegerListNotNull() {\n        return fieldIntegerListNotNull;\n    }\n\n    public void setFieldIntegerListNotNull(RealmList<Integer> fieldIntegerListNotNull) {\n        this.fieldIntegerListNotNull = fieldIntegerListNotNull;\n    }\n\n    public RealmList<Integer> getFieldIntegerListNull() {\n        return fieldIntegerListNull;\n    }\n\n    public void setFieldIntegerListNull(RealmList<Integer> fieldIntegerListNull) {\n        this.fieldIntegerListNull = fieldIntegerListNull;\n    }\n\n    public RealmList<Short> getFieldShortListNotNull() {\n        return fieldShortListNotNull;\n    }\n\n    public void setFieldShortListNotNull(RealmList<Short> fieldShortListNotNull) {\n        this.fieldShortListNotNull = fieldShortListNotNull;\n    }\n\n    public RealmList<Short> getFieldShortListNull() {\n        return fieldShortListNull;\n    }\n\n    public void setFieldShortListNull(RealmList<Short> fieldShortListNull) {\n        this.fieldShortListNull = fieldShortListNull;\n    }\n\n    public RealmList<Byte> getFieldByteListNotNull() {\n        return fieldByteListNotNull;\n    }\n\n    public void setFieldByteListNotNull(RealmList<Byte> fieldByteListNotNull) {\n        this.fieldByteListNotNull = fieldByteListNotNull;\n    }\n\n    public RealmList<Byte> getFieldByteListNull() {\n        return fieldByteListNull;\n    }\n\n    public void setFieldByteListNull(RealmList<Byte> fieldByteListNull) {\n        this.fieldByteListNull = fieldByteListNull;\n    }\n\n    public RealmList<Double> getFieldDoubleListNotNull() {\n        return fieldDoubleListNotNull;\n    }\n\n    public void setFieldDoubleListNotNull(RealmList<Double> fieldDoubleListNotNull) {\n        this.fieldDoubleListNotNull = fieldDoubleListNotNull;\n    }\n\n    public RealmList<Double> getFieldDoubleListNull() {\n        return fieldDoubleListNull;\n    }\n\n    public void setFieldDoubleListNull(RealmList<Double> fieldDoubleListNull) {\n        this.fieldDoubleListNull = fieldDoubleListNull;\n    }\n\n    public RealmList<Float> getFieldFloatListNotNull() {\n        return fieldFloatListNotNull;\n    }\n\n    public void setFieldFloatListNotNull(RealmList<Float> fieldFloatListNotNull) {\n        this.fieldFloatListNotNull = fieldFloatListNotNull;\n    }\n\n    public RealmList<Float> getFieldFloatListNull() {\n        return fieldFloatListNull;\n    }\n\n    public void setFieldFloatListNull(RealmList<Float> fieldFloatListNull) {\n        this.fieldFloatListNull = fieldFloatListNull;\n    }\n\n    public RealmList<Date> getFieldDateListNotNull() {\n        return fieldDateListNotNull;\n    }\n\n    public void setFieldDateListNotNull(RealmList<Date> fieldDateListNotNull) {\n        this.fieldDateListNotNull = fieldDateListNotNull;\n    }\n\n    public RealmList<Date> getFieldDateListNull() {\n        return fieldDateListNull;\n    }\n\n    public void setFieldDateListNull(RealmList<Date> fieldDateListNull) {\n        this.fieldDateListNull = fieldDateListNull;\n    }\n\n    public Decimal128 getFieldDecimal128NotNull() {\n        return fieldDecimal128NotNull;\n    }\n\n    public void setFieldDecimal128NotNull(Decimal128 fieldDecimal128NotNull) {\n        this.fieldDecimal128NotNull = fieldDecimal128NotNull;\n    }\n\n    public Decimal128 getFieldDecimal128Null() {\n        return fieldDecimal128Null;\n    }\n\n    public void setFieldDecimal128Null(Decimal128 fieldDecimal128Null) {\n        this.fieldDecimal128Null = fieldDecimal128Null;\n    }\n\n    public ObjectId getFieldObjectIdNotNull() {\n        return fieldObjectIdNotNull;\n    }\n\n    public void setFieldObjectIdNotNull(ObjectId fieldObjectIdNotNull) {\n        this.fieldObjectIdNotNull = fieldObjectIdNotNull;\n    }\n\n    public ObjectId getFieldObjectIdNull() {\n        return fieldObjectIdNull;\n    }\n\n    public void setFieldObjectIdNull(ObjectId fieldObjectIdNull) {\n        this.fieldObjectIdNull = fieldObjectIdNull;\n    }\n\n    public RealmList<Decimal128> getFieldDecimal128ListNotNull() {\n        return fieldDecimal128ListNotNull;\n    }\n\n    public void setFieldDecimal128ListNotNull(RealmList<Decimal128> fieldDecimal128ListNotNull) {\n        this.fieldDecimal128ListNotNull = fieldDecimal128ListNotNull;\n    }\n\n    public RealmList<Decimal128> getFieldDecimal128ListNull() {\n        return fieldDecimal128ListNull;\n    }\n\n    public void setFieldDecimal128ListNull(RealmList<Decimal128> fieldDecimal128ListNull) {\n        this.fieldDecimal128ListNull = fieldDecimal128ListNull;\n    }\n\n    public RealmList<ObjectId> getFieldObjectIdListNotNull() {\n        return fieldObjectIdListNotNull;\n    }\n\n    public void setFieldObjectIdListNotNull(RealmList<ObjectId> fieldObjectIdListNotNull) {\n        this.fieldObjectIdListNotNull = fieldObjectIdListNotNull;\n    }\n\n    public RealmList<ObjectId> getFieldObjectIdListNull() {\n        return fieldObjectIdListNull;\n    }\n\n    public void setFieldObjectIdListNull(RealmList<ObjectId> fieldObjectIdListNull) {\n        this.fieldObjectIdListNull = fieldObjectIdListNull;\n    }\n\n    public RealmList<UUID> getFieldUUIDListNotNull() {\n        return fieldUUIDListNotNull;\n    }\n\n    public void setFieldUUIDListNotNull(RealmList<UUID> fieldUUIDListNotNull) {\n        this.fieldUUIDListNotNull = fieldUUIDListNotNull;\n    }\n\n    public RealmList<UUID> getFieldUUIDListNull() {\n        return fieldUUIDListNull;\n    }\n\n    public void setFieldUUIDListNull(RealmList<UUID> fieldUUIDListNull) {\n        this.fieldUUIDListNull = fieldUUIDListNull;\n    }\n\n    public UUID getFieldUUIDNotNull() {\n        return fieldUUIDNotNull;\n    }\n\n    public void setFieldUUIDNotNull(UUID fieldUUIDNotNull) {\n        this.fieldUUIDNotNull = fieldUUIDNotNull;\n    }\n\n    public UUID getFieldUUIDNull() {\n        return fieldUUIDNull;\n    }\n\n    public void setFieldUUIDNull(UUID fieldUUIDNull) {\n        this.fieldUUIDNull = fieldUUIDNull;\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/testUtils/java/io/realm/entities/Owner.java",
    "content": "/*\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\npackage io.realm.entities;\n\nimport io.realm.RealmList;\nimport io.realm.RealmObject;\n\npublic class Owner extends RealmObject {\n\n    public static String CLASS_NAME = \"Owner\";\n    public static String FIELD_NAME = \"name\";\n    public static String FIELD_DOGS = \"dogs\";\n    public static String FIELD_CAT = \"cat\";\n\n    private String name;\n    private RealmList<Dog> dogs;\n    private Cat cat;\n\n    public Cat getCat() {\n        return cat;\n    }\n\n    public void setCat(Cat cat) {\n        this.cat = cat;\n    }\n\n    public RealmList<Dog> getDogs() {\n        return dogs;\n    }\n\n    public void setDogs(RealmList<Dog> dogs) {\n        this.dogs = dogs;\n    }\n\n    public String getName() {\n        return name;\n    }\n\n    public void setName(String name) {\n        this.name = name;\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/testUtils/java/io/realm/entities/PrimaryKeyAsBoxedByte.java",
    "content": "/*\n * Copyright 2016 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\npackage io.realm.entities;\n\nimport io.realm.RealmObject;\nimport io.realm.annotations.PrimaryKey;\nimport io.realm.objectid.NullPrimaryKey;\n\npublic class PrimaryKeyAsBoxedByte extends RealmObject implements NullPrimaryKey<Byte, String> {\n\n    public static final String CLASS_NAME = \"PrimaryKeyAsBoxedByte\";\n    public static final String FIELD_PRIMARY_KEY = \"id\";\n\n    @PrimaryKey\n    private Byte id;\n\n    private String name;\n\n    public PrimaryKeyAsBoxedByte() {}\n    public PrimaryKeyAsBoxedByte(Byte id, String name) {\n        this.id = id;\n        this.name = name;\n    }\n\n    @Override\n    public Byte getId() {\n        return id;\n    }\n\n    @Override\n    public void setId(Byte id) {\n        this.id = id;\n    }\n\n    @Override\n    public String getName() {\n        return name;\n    }\n\n    @Override\n    public void setName(String name) {\n        this.name = name;\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/testUtils/java/io/realm/entities/PrimaryKeyAsBoxedInteger.java",
    "content": "/*\n * Copyright 2016 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\npackage io.realm.entities;\n\nimport io.realm.RealmObject;\nimport io.realm.annotations.PrimaryKey;\nimport io.realm.objectid.NullPrimaryKey;\n\npublic class PrimaryKeyAsBoxedInteger extends RealmObject implements NullPrimaryKey<Integer, String> {\n\n    public static final String CLASS_NAME = \"PrimaryKeyAsBoxedInteger\";\n    public static final String FIELD_PRIMARY_KEY = \"id\";\n\n    @PrimaryKey\n    private Integer id;\n\n    private String name;\n\n    public PrimaryKeyAsBoxedInteger() {}\n    public PrimaryKeyAsBoxedInteger(Integer id, String name) {\n        this.id = id;\n        this.name = name;\n    }\n\n    @Override\n    public Integer getId() {\n        return id;\n    }\n\n    @Override\n    public void setId(Integer id) {\n        this.id = id;\n    }\n\n    @Override\n    public String getName() {\n        return name;\n    }\n\n    @Override\n    public void setName(String name) {\n        this.name = name;\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/testUtils/java/io/realm/entities/PrimaryKeyAsBoxedLong.java",
    "content": "/*\n * Copyright 2016 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\npackage io.realm.entities;\n\nimport io.realm.RealmObject;\nimport io.realm.annotations.PrimaryKey;\nimport io.realm.objectid.NullPrimaryKey;\n\npublic class PrimaryKeyAsBoxedLong extends RealmObject implements NullPrimaryKey<Long, String> {\n\n    public static final String CLASS_NAME = \"PrimaryKeyAsBoxedLong\";\n    public static final String FIELD_PRIMARY_KEY = \"id\";\n    public static final String FIELD_NAME = \"name\";\n\n    @PrimaryKey\n    private Long id;\n\n    private String name;\n\n    public PrimaryKeyAsBoxedLong() {}\n    public PrimaryKeyAsBoxedLong(Long id, String name) {\n        this.id = id;\n        this.name = name;\n    }\n\n    @Override\n    public Long getId() {\n        return id;\n    }\n\n    @Override\n    public void setId(Long id) {\n        this.id = id;\n    }\n\n    @Override\n    public String getName() {\n        return name;\n    }\n\n    @Override\n    public void setName(String name) {\n        this.name = name;\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/testUtils/java/io/realm/entities/PrimaryKeyAsBoxedShort.java",
    "content": "/*\n * Copyright 2016 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\npackage io.realm.entities;\n\nimport io.realm.RealmObject;\nimport io.realm.annotations.PrimaryKey;\nimport io.realm.objectid.NullPrimaryKey;\n\npublic class PrimaryKeyAsBoxedShort extends RealmObject implements NullPrimaryKey<Short, String> {\n\n    public static final String CLASS_NAME = \"PrimaryKeyAsBoxedShort\";\n    public static final String FIELD_PRIMARY_KEY = \"id\";\n\n    @PrimaryKey\n    private Short id;\n\n    private String name;\n\n    public PrimaryKeyAsBoxedShort() {}\n    public PrimaryKeyAsBoxedShort(Short id, String name) {\n        this.id = id;\n        this.name = name;\n    }\n\n    @Override\n    public Short getId() {\n        return id;\n    }\n\n    @Override\n    public void setId(Short id) {\n        this.id = id;\n    }\n\n    @Override\n    public String getName() {\n        return name;\n    }\n\n    @Override\n    public void setName(String name) {\n        this.name = name;\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/testUtils/java/io/realm/entities/PrimaryKeyAsByte.java",
    "content": "/*\n * Copyright 2016 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\npackage io.realm.entities;\n\nimport io.realm.RealmObject;\nimport io.realm.annotations.PrimaryKey;\n\npublic class PrimaryKeyAsByte extends RealmObject {\n\n    public static final String CLASS_NAME = \"PrimaryKeyAsByte\";\n    public static final String FIELD_ID = \"id\";\n\n    @PrimaryKey\n    private byte id;\n\n    private String name;\n\n    public byte getId() {\n        return id;\n    }\n\n    public void setId(byte id) {\n        this.id = id;\n    }\n\n    public String getName() {\n        return name;\n    }\n\n    public void setName(String name) {\n        this.name = name;\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/testUtils/java/io/realm/entities/PrimaryKeyAsInteger.java",
    "content": "/*\n * Copyright 2016 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\npackage io.realm.entities;\n\nimport io.realm.RealmObject;\nimport io.realm.annotations.PrimaryKey;\n\npublic class PrimaryKeyAsInteger extends RealmObject {\n\n    public static final String CLASS_NAME = \"PrimaryKeyAsInteger\";\n    public static final String FIELD_ID = \"id\";\n    public static final String FIELD_NAME= \"name\";\n\n    @PrimaryKey\n    private int id;\n\n    private String name;\n\n    public int getId() {\n        return id;\n    }\n\n    public void setId(int id) {\n        this.id = id;\n    }\n\n    public String getName() {\n        return name;\n    }\n\n    public void setName(String name) {\n        this.name = name;\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/testUtils/java/io/realm/entities/PrimaryKeyAsLong.java",
    "content": "/*\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\npackage io.realm.entities;\n\nimport io.realm.RealmObject;\nimport io.realm.annotations.PrimaryKey;\n\npublic class PrimaryKeyAsLong extends RealmObject {\n\n    public static final String CLASS_NAME = \"PrimaryKeyAsLong\";\n    public static final String FIELD_ID = \"id\";\n    public static final String FIELD_NAME = \"name\";\n\n    public PrimaryKeyAsLong() { }\n    public PrimaryKeyAsLong(long id) {\n        this.id = id;\n    }\n\n    @PrimaryKey\n    private long id;\n\n    private String name;\n\n    public long getId() {\n        return id;\n    }\n\n    public void setId(long id) {\n        this.id = id;\n    }\n\n    public String getName() {\n        return name;\n    }\n\n    public void setName(String name) {\n        this.name = name;\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/testUtils/java/io/realm/entities/PrimaryKeyAsShort.java",
    "content": "/*\n * Copyright 2016 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\npackage io.realm.entities;\n\nimport io.realm.RealmObject;\nimport io.realm.annotations.PrimaryKey;\n\npublic class PrimaryKeyAsShort extends RealmObject {\n\n    public static final String CLASS_NAME = \"PrimaryKeyAsShort\";\n    public static final String FIELD_ID = \"id\";\n\n    @PrimaryKey\n    private short id;\n\n    private String name;\n\n    public short getId() {\n        return id;\n    }\n\n    public void setId(short id) {\n        this.id = id;\n    }\n\n    public String getName() {\n        return name;\n    }\n\n    public void setName(String name) {\n        this.name = name;\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/testUtils/java/io/realm/entities/PrimaryKeyAsString.java",
    "content": "/*\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\npackage io.realm.entities;\n\nimport io.realm.RealmObject;\nimport io.realm.annotations.PrimaryKey;\nimport io.realm.objectid.NullPrimaryKey;\n\npublic class PrimaryKeyAsString extends RealmObject {\n\n    public static final String CLASS_NAME = \"PrimaryKeyAsString\";\n    public static final String FIELD_PRIMARY_KEY = \"name\";\n    public static final String FIELD_ID = \"id\";\n\n    @PrimaryKey\n    private String name;\n\n    private long id;\n\n    public PrimaryKeyAsString() {}\n    public PrimaryKeyAsString(String name, long id) {\n        this.name = name;\n        this.id = id;\n    }\n\n    public PrimaryKeyAsString(String name) {\n        this.name = name;\n    }\n\n    public String getName() {\n        return name;\n    }\n\n    public void setName(String name) {\n        this.name = name;\n    }\n\n    public long getId() {\n        return id;\n    }\n\n    public void setId(long id) {\n        this.id = id;\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/testUtils/java/io/realm/entities/PrimaryKeyAsUUID.java",
    "content": "/*\n * Copyright 2020 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\npackage io.realm.entities;\n\nimport java.util.UUID;\n\nimport io.realm.RealmObject;\nimport io.realm.annotations.PrimaryKey;\n\n\npublic class PrimaryKeyAsUUID extends RealmObject {\n\n    public static final String CLASS_NAME = \"PrimaryKeyAsUUID\";\n    public static final String FIELD_PRIMARY_KEY = \"id\";\n    public static final String FIELD_NAME = \"name\";\n\n    @PrimaryKey\n    private UUID id;\n\n    private String name;\n\n    public PrimaryKeyAsUUID() {}\n    public PrimaryKeyAsUUID(UUID id, String name) {\n        this.id = id;\n        this.name = name;\n    }\n\n    public UUID getId() {\n        return id;\n    }\n\n    public void setId(UUID id) {\n        this.id = id;\n    }\n\n    public String getName() {\n        return name;\n    }\n\n    public void setName(String name) {\n        this.name = name;\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/testUtils/java/io/realm/entities/PrimaryKeyRequiredAsBoxedByte.java",
    "content": "/*\n * Copyright 2016 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\npackage io.realm.entities;\n\nimport io.realm.RealmObject;\nimport io.realm.annotations.PrimaryKey;\nimport io.realm.annotations.Required;\nimport io.realm.objectid.NullPrimaryKey;\n\npublic class PrimaryKeyRequiredAsBoxedByte extends RealmObject implements NullPrimaryKey<Byte, String> {\n\n    @PrimaryKey\n    @Required\n    private Byte id;\n\n    private String name;\n\n    public PrimaryKeyRequiredAsBoxedByte() {}\n    public PrimaryKeyRequiredAsBoxedByte(Byte id, String name) {\n        this.id = id;\n        this.name = name;\n    }\n\n    @Override\n    public Byte getId() {\n        return id;\n    }\n\n    @Override\n    public void setId(Byte id) {\n        this.id = id;\n    }\n\n    @Override\n    public String getName() {\n        return name;\n    }\n\n    @Override\n    public void setName(String name) {\n        this.name = name;\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/testUtils/java/io/realm/entities/PrimaryKeyRequiredAsBoxedInteger.java",
    "content": "/*\n * Copyright 2016 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\npackage io.realm.entities;\n\nimport io.realm.RealmObject;\nimport io.realm.annotations.PrimaryKey;\nimport io.realm.annotations.Required;\nimport io.realm.objectid.NullPrimaryKey;\n\npublic class PrimaryKeyRequiredAsBoxedInteger extends RealmObject implements NullPrimaryKey<Integer, String> {\n\n    @PrimaryKey\n    @Required\n    private Integer id;\n\n    private String name;\n\n    public PrimaryKeyRequiredAsBoxedInteger() {}\n    public PrimaryKeyRequiredAsBoxedInteger(Integer id, String name) {\n        this.id = id;\n        this.name = name;\n    }\n\n    @Override\n    public Integer getId() {\n        return id;\n    }\n\n    @Override\n    public void setId(Integer id) {\n        this.id = id;\n    }\n\n    @Override\n    public String getName() {\n        return name;\n    }\n\n    @Override\n    public void setName(String name) {\n        this.name = name;\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/testUtils/java/io/realm/entities/PrimaryKeyRequiredAsBoxedLong.java",
    "content": "/*\n * Copyright 2016 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\npackage io.realm.entities;\n\nimport io.realm.RealmObject;\nimport io.realm.annotations.PrimaryKey;\nimport io.realm.annotations.Required;\nimport io.realm.objectid.NullPrimaryKey;\n\npublic class PrimaryKeyRequiredAsBoxedLong extends RealmObject implements NullPrimaryKey<Long, String> {\n\n    @PrimaryKey\n    @Required\n    private Long id;\n\n    private String name;\n\n    public PrimaryKeyRequiredAsBoxedLong() {}\n    public PrimaryKeyRequiredAsBoxedLong(Long id, String name) {\n        this.id = id;\n        this.name = name;\n    }\n\n    @Override\n    public Long getId() {\n        return id;\n    }\n\n    @Override\n    public void setId(Long id) {\n        this.id = id;\n    }\n\n    @Override\n    public String getName() {\n        return name;\n    }\n\n    @Override\n    public void setName(String name) {\n        this.name = name;\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/testUtils/java/io/realm/entities/PrimaryKeyRequiredAsBoxedShort.java",
    "content": "/*\n * Copyright 2016 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\npackage io.realm.entities;\n\nimport io.realm.RealmObject;\nimport io.realm.annotations.PrimaryKey;\nimport io.realm.annotations.Required;\nimport io.realm.objectid.NullPrimaryKey;\n\npublic class PrimaryKeyRequiredAsBoxedShort extends RealmObject implements NullPrimaryKey<Short, String> {\n\n    @PrimaryKey\n    @Required\n    private Short id;\n\n    private String name;\n\n    public PrimaryKeyRequiredAsBoxedShort() {}\n    public PrimaryKeyRequiredAsBoxedShort(Short id, String name) {\n        this.id = id;\n        this.name = name;\n    }\n\n    @Override\n    public Short getId() {\n        return id;\n    }\n\n    @Override\n    public void setId(Short id) {\n        this.id = id;\n    }\n\n    @Override\n    public String getName() {\n        return name;\n    }\n\n    @Override\n    public void setName(String name) {\n        this.name = name;\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/testUtils/java/io/realm/entities/SyncByteArray.java",
    "content": "package io.realm.entities;\n\nimport org.bson.types.ObjectId;\n\nimport io.realm.RealmObject;\nimport io.realm.annotations.PrimaryKey;\nimport io.realm.annotations.Required;\n\npublic class SyncByteArray extends RealmObject {\n    @PrimaryKey\n    public ObjectId _id;\n    @Required\n    public byte[] columnBinary = new byte[0];\n}\n"
  },
  {
    "path": "realm/realm-library/src/testUtils/java/io/realm/objectid/NullPrimaryKey.java",
    "content": "/*\n * Copyright 2016 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\npackage io.realm.objectid;\n\npublic interface NullPrimaryKey<P, S> {\n\n    public P getId();\n\n    public void setId(P id);\n\n    public S getName();\n\n    public void setName(S name);\n}\n"
  },
  {
    "path": "realm/realm-library/src/testUtils/java/io/realm/rule/RunInLooperThread.java",
    "content": "/*\n * Copyright 2015 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\npackage io.realm.rule;\n\nimport android.os.Handler;\nimport android.os.Looper;\n\nimport org.junit.runner.Description;\nimport org.junit.runners.model.MultipleFailureException;\nimport org.junit.runners.model.Statement;\n\nimport java.io.Closeable;\nimport java.io.IOException;\nimport java.io.PrintStream;\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.List;\nimport java.util.UUID;\nimport java.util.concurrent.CountDownLatch;\nimport java.util.concurrent.ExecutorService;\nimport java.util.concurrent.Executors;\nimport java.util.concurrent.Future;\nimport java.util.concurrent.ThreadFactory;\n\nimport io.realm.Realm;\nimport io.realm.RealmConfiguration;\nimport io.realm.TestHelper;\nimport io.realm.TestRealmConfigurationFactory;\nimport io.realm.internal.android.AndroidCapabilities;\n\n\n/**\n * Rule that runs the test inside a worker looper thread. This rule is responsible\n * of creating a temp directory containing a Realm instance then deleting it, once the test finishes.\n * <p>\n * All Realms used in a method method annotated with {@code @RunTestInLooperThread } should use\n * {@link RunInLooperThread#createConfiguration()} and friends to create their configurations.\n * Failing to do so can result in the test failing because the Realm could not be deleted\n * (this class and {@link TestRealmConfigurationFactory} do not agree in which order to delete\n * the open Realms).\n */\npublic class RunInLooperThread extends TestRealmConfigurationFactory {\n    private static final long WAIT_TIMEOUT_MS = 20 * 1000;\n\n    // lock protecting objects shared with the test thread\n    private final Object lock = new Object();\n\n    // Thread safe\n    private final CountDownLatch signalTestCompleted = new CountDownLatch(1);\n\n    // Thread safe\n    private boolean ruleBeingUsed = false;\n\n    // Access guarded by 'lock'\n    private RealmConfiguration realmConfiguration;\n\n    // Default Realm created by this Rule. It is guaranteed to be closed when the test finishes.\n    // Access guarded by 'lock'\n    private Realm realm;\n\n    // Access guarded by 'lock'\n    private Handler backgroundHandler;\n\n    // the variables created inside the test are local and eligible for GC.\n    // but sometimes we need the variables to survive across different Looper\n    // events (Callbacks happening in the future), so we add a strong reference\n    // to them for the duration of the test.\n    // Access guarded by 'lock'\n    private List<Object> keepStrongReference;\n\n    // Custom Realm used by the test. Saving the reference here will guarantee\n    // that the instance is closed when exiting the test.\n    // Access guarded by 'lock'\n    private List<Realm> testRealms;\n\n    // List of closable resources that will be automatically closed when the test finishes.\n    // Access guarded by 'lock'\n    private List<Closeable> closableResources;\n\n    // Runnable guaranteed to trigger after the test either succeeded or failed.\n    // Access guarded by 'lock'\n    private List<Runnable> runAfterTestIsComplete = new ArrayList<>();\n\n    // Used to indicate that a test is being marked as complete, but teardown hasn't fully finished yet.\n    private boolean testCompletedButNotFullyTornDown;\n\n    /**\n     * Get the configuration for the test realm.\n     * <p>\n     * Set on main thread, accessed from test thread.\n     * Valid after {@code before}.\n     *\n     * @return the test realm configuration.\n     */\n    public RealmConfiguration getConfiguration() {\n        synchronized (lock) {\n            return realmConfiguration;\n        }\n    }\n\n    /**\n     * Get the test realm.\n     * <p>\n     * Set on test thread, accessed from main thread.\n     * Valid only after the test thread has started.\n     *\n     * @return the test realm.\n     */\n    public Realm getRealm() {\n        synchronized (lock) {\n            while (backgroundHandler == null) {\n                try {\n                    lock.wait(WAIT_TIMEOUT_MS);\n                } catch (InterruptedException ignore) {\n                    break;\n                }\n            }\n            return realm;\n        }\n    }\n\n    /**\n     * Hold a reference to an object, to prevent it from being GCed,\n     * until after the test completes.\n     * <p>\n     * Accessed only from the main thread, here, but synchronized in case it is called from within a test.\n     * Valid after {@code before}.\n     */\n    public void keepStrongReference(Object obj) {\n        synchronized (lock) {\n            keepStrongReference.add(obj);\n        }\n    }\n\n    /**\n     * Add a closable resource which this test will guarantee to call {@link Closeable#close()} on\n     * when the tests is done.\n     *\n     * @param closeable {@link Closeable} to close.\n     */\n    public void closeAfterTest(Closeable closeable) {\n        synchronized (lock) {\n            closableResources.add(closeable);\n        }\n    }\n\n    /**\n     * Run this task after the unit test either failed or succeeded.\n     * This is a work-around for the the current @After being triggered right after the unit test method exits,\n     * but before the @RunTestInLooperThread has determined the test is done\n     *\n     * TODO: Consider replacing this pattern with `@AfterLooperTest` annotation.\n     *\n     * @param task task to run. Only one task can be provided\n     */\n    public void runAfterTest(Runnable task) {\n        synchronized (lock) {\n            runAfterTestIsComplete.add(task);\n        }\n    }\n\n    /**\n     * Add a Realm to be closed when test is complete.\n     * <p>\n     * Accessed from both test and main threads.\n     * Valid after {@code before}.\n     */\n    public void addTestRealm(Realm realm) {\n        synchronized (lock) {\n            testRealms.add(realm);\n        }\n    }\n\n    /**\n     * Explicitly close all held realms.\n     * <p>\n     * 'testRealms' is accessed from both test and main threads.\n     * 'testRealms' is valid after {@code before}.\n     */\n    public void closeTestRealms() {\n        List<Realm> realms = new ArrayList<>();\n        synchronized (lock) {\n            List<Realm> tmp = testRealms;\n            testRealms = realms;\n            realms = tmp;\n        }\n\n        for (Realm testRealm : realms) {\n            testRealm.close();\n        }\n    }\n\n    /**\n     * Posts a runnable to the currently running looper.\n     */\n    public void postRunnable(Runnable runnable) {\n        getBackgroundHandler().post(runnable);\n    }\n\n    /**\n     * Posts a runnable to this worker threads looper with a delay in milli second.\n     */\n    public void postRunnableDelayed(Runnable runnable, long delayMillis) {\n        getBackgroundHandler().postDelayed(runnable, delayMillis);\n    }\n\n    /**\n     * Signal that the test has completed.\n     * <p>\n     * Can be used on both the main and test threads.\n     */\n    public void testComplete() {\n        // Close all resources and run any after test tasks\n        // Post as runnable to ensure that this code runs on the correct thread.\n        postRunnable(new Runnable() {\n            @Override\n            public void run() {\n                closeTestResources();\n            }\n        });\n    }\n\n    /**\n     * Internal logic for shutting down a test.\n     */\n    private void closeTestResources() {\n        testCompletedButNotFullyTornDown = true;\n        try {\n            closeResources();\n            closeRealms();\n            for (Runnable task : runAfterTestIsComplete) {\n                task.run();\n            }\n        } catch (Throwable t) {\n            throw new AssertionError(\"Failed to close test resources correctly\", t);\n        } finally {\n            testCompletedButNotFullyTornDown = false;\n            signalTestCompleted.countDown();\n        }\n    }\n\n    /**\n     * Signal that the test has completed, after waiting for any additional latches.\n     *\n     * @param latches additional latches to wait on, before setting the test completed flag.\n     */\n    public void\n    testComplete(CountDownLatch... latches) {\n        for (CountDownLatch latch : latches) {\n            TestHelper.awaitOrFail(latch);\n        }\n        testComplete();\n    }\n\n    // Accessed from both test and main threads\n    // Valid after the test thread has started.\n    private Handler getBackgroundHandler() {\n        synchronized (lock) {\n            while (backgroundHandler == null) {\n                try {\n                    lock.wait(WAIT_TIMEOUT_MS);\n                } catch (InterruptedException e) {\n                    throw new AssertionError(\"Could not acquire the test handler.\", e);\n                }\n            }\n            return this.backgroundHandler;\n        }\n    }\n\n    // Accessed from both test and main threads\n    // Storing the handler is the gate that indicates that the test thread has started.\n    void setBackgroundHandler(Handler backgroundHandler) {\n        synchronized (lock) {\n            this.backgroundHandler = backgroundHandler;\n            lock.notifyAll();\n        }\n    }\n\n    @Override\n    protected void before() throws Throwable {\n        super.before();\n\n        RealmConfiguration config = createConfiguration(UUID.randomUUID().toString());\n        List<Object> refs = new ArrayList<>();\n        List<Realm> realms = new ArrayList<>();\n        List<Closeable> closeables = new ArrayList<>();\n\n        synchronized (lock) {\n            realmConfiguration = config;\n            realm = null;\n            backgroundHandler = null;\n            keepStrongReference = refs;\n            testRealms = realms;\n            closableResources = closeables;\n        }\n    }\n\n    @Override\n    protected void after() {\n        // Wait for all async tasks to have completed to ensure a successful deleteRealm call.\n        // If it times out, it will throw.\n        TestHelper.waitRealmThreadExecutorFinish();\n        TestHelper.waitForNetworkThreadExecutorToFinish();\n        AndroidCapabilities.EMULATE_MAIN_THREAD = false;\n        super.after();\n\n        // probably belt *and* suspenders...\n        synchronized (lock) {\n            backgroundHandler = null;\n            keepStrongReference = null;\n        }\n    }\n\n    @Override\n    public Statement apply(Statement base, Description description) {\n        setTestName(description);\n        final RunTestInLooperThread annotation = description.getAnnotation(RunTestInLooperThread.class);\n        if (annotation == null) {\n            return base;\n        }\n        synchronized (lock) {\n            ruleBeingUsed = true;\n        }\n        return new RunInLooperThreadStatement(annotation, base);\n    }\n\n    /**\n     * Tears down logic which is guaranteed to run after the looper test has either completed or failed.\n     * This will run on the same thread as the looper test.\n     */\n    public void looperTearDown() {\n        // Do nothing\n        // Override in test classes if needed.\n    }\n\n    private void initRealm() {\n        synchronized (lock) {\n            realm = Realm.getInstance(realmConfiguration);\n        }\n    }\n\n    private void closeRealms() {\n        closeTestRealms();\n\n        Realm oldRealm;\n        synchronized (lock) {\n            oldRealm = realm;\n\n            realm = null;\n            realmConfiguration = null;\n        }\n\n        if (oldRealm != null) {\n            oldRealm.close();\n        }\n    }\n\n    private void closeResources() throws IOException {\n        synchronized (lock) {\n            for (Closeable cr : closableResources) {\n                cr.close();\n            }\n        }\n    }\n\n    /**\n     * Checks if the current test is considered completed or not.\n     *\n     * It is completed if either {@link #testComplete()} was called or an uncaught exception was thrown.\n     */\n    public boolean isTestComplete() {\n        synchronized (lock) {\n            return signalTestCompleted.getCount() <= 0 || testCompletedButNotFullyTornDown;\n        }\n    }\n\n    /**\n     * Returns true if the current test being run is using this rule.\n     */\n    public boolean isRuleUsed() {\n        return ruleBeingUsed;\n    }\n\n    /**\n     * If an implementation of this is supplied with the annotation, the {@link RunnableBefore#run(RealmConfiguration)}\n     * will be executed before the looper thread starts. It is normally for populating the Realm before the test.\n     */\n    public interface RunnableBefore {\n        void run(RealmConfiguration realmConfig);\n    }\n\n    private class RunInLooperThreadStatement extends Statement {\n        private final RunTestInLooperThread annotation;\n        private final Statement base;\n\n        RunInLooperThreadStatement(RunTestInLooperThread annotation, Statement base) {\n            this.annotation = annotation;\n            this.base = base;\n        }\n\n        @Override\n        @SuppressWarnings(\"ClassNewInstance\")\n        public void evaluate() throws Throwable {\n            before();\n\n            Class<? extends RunnableBefore> runnableBefore = annotation.before();\n            if (!runnableBefore.isInterface()) {\n                // this is dangerous: newInstance can throw checked exceptions.\n                // this is dangerous: config is mutable.\n                runnableBefore.newInstance().run(getConfiguration());\n            }\n\n            AndroidCapabilities.EMULATE_MAIN_THREAD = annotation.emulateMainThread();\n            runTest(annotation.threadName());\n        }\n\n        private void runTest(final String threadName) throws Throwable {\n            Throwable failure = null;\n\n            try {\n                ExecutorService executorService = Executors.newSingleThreadExecutor(new ThreadFactory() {\n                    @Override\n                    public Thread newThread(Runnable runnable) { return new Thread(runnable, threadName); }\n                });\n\n                TestThread test = new TestThread(base);\n\n                @SuppressWarnings({\"UnusedAssignment\", \"unused\"})\n                Future<?> ignored = executorService.submit(test);\n\n                TestHelper.exitOrThrow(executorService, signalTestCompleted, test);\n            } catch (Throwable testfailure) {\n                // These exceptions should only come from TestHelper.awaitOrFail()\n                failure = testfailure;\n            } finally {\n                // Tries as hard as possible to close down gracefully, while still keeping all exceptions intact.\n                failure = cleanUp(failure);\n            }\n            if (failure != null) {\n                throw failure;\n            }\n        }\n\n        private Throwable cleanUp(Throwable testfailure) {\n            try {\n                after();\n                return testfailure;\n            } catch (Throwable afterFailure) {\n                if (testfailure == null) {\n                    // Only after() threw an exception\n                    return afterFailure;\n                }\n\n                // Both TestHelper.awaitOrFail() and after() threw exceptions\n                return new MultipleFailureException(Arrays.asList(testfailure, afterFailure)) {\n                    @Override\n                    public void printStackTrace(PrintStream out) {\n                        int i = 0;\n                        for (Throwable t : getFailures()) {\n                            out.println(\"Error \" + i + \": \" + t.getMessage());\n                            t.printStackTrace(out);\n                            out.println();\n                            i++;\n                        }\n                    }\n                };\n            }\n        }\n    }\n\n    private class TestThread implements Runnable, TestHelper.LooperTest {\n        private final CountDownLatch signalClosedRealm = new CountDownLatch(1);\n        private final Statement base;\n        private Looper looper;\n        private Throwable threadAssertionError;\n\n        TestThread(Statement base) {\n            this.base = base;\n        }\n\n//        @Override\n//        public CountDownLatch getRealmClosedSignal() {\n//            return signalClosedRealm;\n//        }\n//\n        @Override\n        public synchronized Looper getLooper() {\n            return looper;\n        }\n\n        private synchronized void setLooper(Looper looper) {\n            this.looper = looper;\n            setBackgroundHandler(new Handler(looper));\n        }\n\n        @Override\n        public synchronized Throwable getAssertionError() {\n            return threadAssertionError;\n        }\n\n        // Only record the first error\n        private synchronized void setAssertionError(Throwable threadAssertionError) {\n            if (this.threadAssertionError == null) {\n                this.threadAssertionError = threadAssertionError;\n            }\n        }\n\n        @Override\n        public void run() {\n            Looper.prepare();\n            try {\n                initRealm();\n                setLooper(Looper.myLooper());\n                base.evaluate();\n                Looper.loop();\n            } catch (Throwable t) {\n                setAssertionError(t);\n                setUnitTestFailed();\n\n                // If an exception occurred, `looperThread.testComplete()` was probably no called.\n                // Rerun it here, but ignore any failures as the first failure is more important.\n                try {\n                    closeTestResources();\n                } catch (Throwable ignore) {\n                }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/testUtils/java/io/realm/rule/RunTestInLooperThread.java",
    "content": "/*\n * Copyright 2015 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\npackage io.realm.rule;\n\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.Target;\n\nimport static java.lang.annotation.ElementType.METHOD;\nimport static java.lang.annotation.RetentionPolicy.RUNTIME;\n/**\n * This annotation should be used along with {@link RunInLooperThread}\n * When the annotation is present, the test method is executed on a worker thread with a looper.\n * This will also uses {@link org.junit.rules.TemporaryFolder} to create and open a Realm.\n * Annotation param {@link io.realm.rule.RunInLooperThread.RunnableBefore} can be supplied which will run before the\n * looper thread.\n */\n@Target(METHOD)\n@Retention(RUNTIME)\npublic @interface RunTestInLooperThread {\n        String threadName() default \"RunTestInLooperThread\";\n        Class<?extends RunInLooperThread.RunnableBefore> before() default RunInLooperThread.RunnableBefore.class;\n        boolean emulateMainThread() default false;\n}\n"
  },
  {
    "path": "realm/realm-library/src/testUtils/java/io/realm/rule/RunTestWithRemoteService.java",
    "content": "/*\n * Copyright 2017 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\npackage io.realm.rule;\n\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.Target;\n\nimport io.realm.services.RemoteTestService;\n\nimport static java.lang.annotation.ElementType.METHOD;\nimport static java.lang.annotation.RetentionPolicy.RUNTIME;\n\n/**\n * This should be used along with {@link RunWithRemoteService}. See comments there for usage.\n */\n@Target(METHOD)\n@Retention(RUNTIME)\npublic @interface RunTestWithRemoteService {\n    Class<? extends RemoteTestService> remoteService();\n    boolean onLooperThread();\n}\n"
  },
  {
    "path": "realm/realm-library/src/testUtils/java/io/realm/rule/RunWithRemoteService.java",
    "content": "/*\n * Copyright 2017 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\npackage io.realm.rule;\n\nimport android.app.ActivityManager;\nimport android.app.Instrumentation;\nimport android.content.ComponentName;\nimport android.content.Context;\nimport android.content.Intent;\nimport android.content.ServiceConnection;\nimport android.os.Bundle;\nimport android.os.Handler;\nimport android.os.IBinder;\nimport android.os.Looper;\nimport android.os.Message;\nimport android.os.Messenger;\nimport android.os.RemoteException;\n\nimport androidx.test.platform.app.InstrumentationRegistry;\n\nimport org.junit.rules.TestRule;\nimport org.junit.runner.Description;\nimport org.junit.runners.model.Statement;\n\nimport java.util.List;\nimport java.util.concurrent.CountDownLatch;\n\nimport io.realm.TestHelper;\nimport io.realm.services.RemoteTestService;\n\nimport static junit.framework.Assert.fail;\n\n/**\n * This is a helper {@link TestRule} to do test which needs interaction with a remote process.\n * To use this:\n * 1. Define a subclass of {@link RemoteTestService} and create steps as static member of it. Those steps should be\n * named as \"stepA_doXXX\", \"stepB_doYYY\", etc. to indicate the order of them.\n * 2. Add a base message id in {@link RemoteTestService}.\n * 3. Add the service into the AndroidManifest.xml. And the android:process property must be \":remote\".\n * 4. Annotate your test case by {@link RunTestWithRemoteService} with your remote service class.\n * 5. To run the tests on the looper thread:\n *    a) Add {@link RunTestInLooperThread} to the tests.\n *    b) Add {@code @RunTestWithRemoteService(remoteService = SimpleCommitRemoteService.class, onLooperThread = true)}\n *       Please notice that {@code onLooperThread} needs to be set to true to avoid the remote service getting killed\n *       before looper thread finished\n *    c) Call {@code looperThread.runAfterTest(remoteService.afterRunnable)} to kill the remote service after test.\n * 6. When your looper thread starts, register the service messenger by calling\n * {@link RunWithRemoteService#createHandler(Looper)}.\n * 7. Trigger your first step in the remote service process by calling\n * {@link RunWithRemoteService#triggerServiceStep(RemoteTestService.Step)}.\n * 8. Name steps in the foreground process with step1, step2 ... stepN.\n *    Name steps in the remote process with stepA, stepB ... stepZ.\n *\n * See the existing test cases for examples.\n */\npublic class RunWithRemoteService implements TestRule {\n\n    private class InterprocessHandler extends Handler {\n\n        private InterprocessHandler(Looper looper) {\n            super(looper);\n            localMessenger = new Messenger(this);\n        }\n\n        @Override\n        public void handleMessage(Message msg) {\n            Bundle bundle = msg.getData();\n            String error = bundle.getString(RemoteTestService.BUNDLE_KEY_ERROR);\n            if (error != null) {\n                // Assert and show error from remote process\n                fail(error);\n            }\n        }\n    }\n\n    private static final String REMOTE_PROCESS_POSTFIX = \":remote\";\n\n    private Messenger remoteMessenger;\n    private Messenger localMessenger;\n    private CountDownLatch serviceStartLatch;\n    public Runnable afterRunnable = new Runnable() {\n        @Override\n        public void run() {\n            after();\n        }\n    };\n\n    private final ServiceConnection serviceConnection = new ServiceConnection() {\n        @Override\n        public void onServiceConnected(ComponentName componentName, IBinder iBinder) {\n            remoteMessenger = new Messenger(iBinder);\n            serviceStartLatch.countDown();\n        }\n\n        @Override\n        public void onServiceDisconnected(ComponentName componentName) {\n            if (serviceStartLatch != null && serviceStartLatch.getCount() > 1) {\n                serviceStartLatch.countDown();\n            }\n            serviceStartLatch = null;\n            remoteMessenger = null;\n        }\n    };\n\n    private void before(Class<?> serviceClass) throws Throwable {\n        // Start the testing remote process.\n        serviceStartLatch = new CountDownLatch(1);\n        Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();\n        Intent intent = new Intent(instrumentation.getContext(), serviceClass);\n        instrumentation.getContext().bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE);\n        TestHelper.awaitOrFail(serviceStartLatch);\n    }\n\n    private void after() {\n        InstrumentationRegistry.getInstrumentation().getContext().unbindService(serviceConnection);\n\n        // Kill the remote process.\n        ActivityManager.RunningAppProcessInfo info = getRemoteProcessInfo();\n        if (info != null) {\n            android.os.Process.killProcess(info.pid);\n        }\n        int counter = 10;\n        while (getRemoteProcessInfo() != null) {\n            if (counter == 0) {\n                fail(\"The remote process is still alive.\");\n            }\n            try {\n                Thread.sleep(300);\n            } catch (InterruptedException e) {\n                throw new RuntimeException(e);\n            }\n            counter--;\n        }\n    }\n\n    @Override\n    public Statement apply(final Statement base, Description description) {\n        final RunTestWithRemoteService annotation = description.getAnnotation(RunTestWithRemoteService.class);\n        if (annotation == null) {\n            return base;\n        }\n        return new Statement() {\n            @Override\n            public void evaluate() throws Throwable {\n                before(annotation.remoteService());\n                try {\n                    base.evaluate();\n                } finally {\n                    if (!annotation.onLooperThread()) {\n                        after();\n                    }\n                }\n            }\n        };\n    }\n\n    public void createHandler(Looper looper) {\n        new InterprocessHandler(looper);\n    }\n\n    // Call this to trigger the next step of remote process\n    public void triggerServiceStep(RemoteTestService.Step step) {\n        Message msg = Message.obtain(null, step.message);\n        msg.replyTo = localMessenger;\n        try {\n            remoteMessenger.send(msg);\n        } catch (RemoteException e) {\n            fail(e.getMessage());\n        }\n        // TODO: Find a way to block caller thread until the service process finishes current step.\n    }\n\n    // Get the remote process info if it is alive.\n    private ActivityManager.RunningAppProcessInfo getRemoteProcessInfo() {\n        Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();\n        ActivityManager manager = (ActivityManager) instrumentation.getContext().getSystemService(Context.ACTIVITY_SERVICE);\n        List<ActivityManager.RunningAppProcessInfo> processInfoList = manager.getRunningAppProcesses();\n        for (ActivityManager.RunningAppProcessInfo info : processInfoList) {\n            if (info.processName.equals(instrumentation.getContext().getPackageName() + REMOTE_PROCESS_POSTFIX)) {\n                return info;\n            }\n        }\n\n        return null;\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/testUtils/java/io/realm/services/RemoteProcessService.java",
    "content": "/*\n * Copyright 2015 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\npackage io.realm.services;\n\nimport android.app.Service;\nimport android.content.Intent;\nimport android.os.Bundle;\nimport android.os.Handler;\nimport android.os.IBinder;\nimport android.os.Message;\nimport android.os.Messenger;\nimport android.os.RemoteException;\nimport android.os.SystemClock;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport io.realm.Realm;\nimport io.realm.RealmConfiguration;\nimport io.realm.entities.AllTypes;\nimport io.realm.entities.AllTypesModelModule;\n\n/**\n * Helper service for multi-processes support testing.\n * @deprecated use {@link RemoteTestService} instead.\n */\n@Deprecated\npublic class RemoteProcessService extends Service {\n\n    public abstract static class Step {\n        public final int message;\n        private Step(int message) {\n            this.message = message;\n            stepMap.put(message, this);\n        }\n\n        abstract void run();\n\n        // Passes a null to tell main process that everything is OK.\n        // Otherwise, passes a error String which will be used by assertion in main process.\n        protected void response(String error) {\n            try {\n                Message msg = Message.obtain(null, message);\n                if (error != null) {\n                    Bundle bundle = new Bundle();\n                    bundle.putString(BUNDLE_KEY_ERROR, error);\n                    msg.setData(bundle);\n                }\n                thiz.client.send(msg);\n            } catch (RemoteException e) {\n                e.printStackTrace();\n            }\n        }\n    }\n\n    public static final String BUNDLE_KEY_ERROR = \"error\";\n    private static Map<Integer, Step> stepMap = new HashMap<Integer, Step>();\n\n    private static RemoteProcessService thiz;\n    private Realm testRealm;\n\n    private final Messenger messenger = new Messenger(new IncomingHandler());\n    private Messenger client;\n\n    public RemoteProcessService() {\n        if (thiz != null) {\n            throw new RuntimeException(\"Only one instance is allowed!\");\n        }\n        thiz = this;\n    }\n\n    @Override\n    public void onCreate() {\n        super.onCreate();\n        Realm.init(this);\n    }\n\n    @Override\n    public IBinder onBind(Intent intent) {\n        return messenger.getBinder();\n    }\n\n    @Override\n    public boolean onUnbind(Intent intent) {\n        stopSelf();\n        return super.onUnbind(intent);\n    }\n\n    @Override\n    public int onStartCommand(Intent intent, int flags, int startId) {\n        return START_NOT_STICKY;\n    }\n\n    private static class IncomingHandler extends Handler {\n        @Override\n        public void handleMessage(Message msg) {\n            thiz.client = msg.replyTo;\n            if (thiz.client == null) {\n                throw new RuntimeException(\"Message with an empty client.\");\n            }\n            Step step = stepMap.get(msg.what);\n            if (step != null) {\n                step.run();\n            } else {\n                throw new RuntimeException(\"Cannot find corresponding step to message \" + msg.what + \".\");\n            }\n        }\n    }\n\n    // Calls this function to return the String of current class and line number.\n    private static String currentLine() {\n        StackTraceElement element = new Throwable().getStackTrace()[1];\n        return element.getClassName() + \" line \" + element.getLineNumber() + \": \";\n    }\n\n    public final static Step stepCreateInitialRealm_A = new Step(10) {\n\n        @Override\n        void run() {\n            thiz.testRealm = Realm.getInstance(getConfiguration());\n            int expected = 1;\n            long got = thiz.testRealm.where(AllTypes.class).count();\n            if (expected == got) {\n                response(null);\n            } else {\n                response(currentLine() + \"expected: \" + expected + \", but got \" + got);\n            }\n            thiz.testRealm.close();\n        }\n    };\n\n    public final static Step stepExitProcess_A = new Step(20) {\n\n        @Override\n        void run() {\n            thiz.testRealm = Realm.getInstance(getConfiguration());\n            thiz.testRealm.close();\n            response(null);\n            Runtime.getRuntime().exit(0);\n        }\n    };\n\n    public final static Step stepCreateObjects = new Step(30) {\n\n        @Override\n        void run() {\n            thiz.testRealm = Realm.getInstance(getConfiguration());\n            thiz.testRealm.executeTransaction(new Realm.Transaction() {\n                @Override\n                public void execute(Realm realm) {\n                    realm.createObject(AllTypes.class);\n                }\n            });\n            SystemClock.sleep(1000);\n            thiz.testRealm.executeTransaction(new Realm.Transaction() {\n                @Override\n                public void execute(Realm realm) {\n                    realm.createObject(AllTypes.class);\n                }\n            });\n            thiz.testRealm.close();\n            response(null);\n            Runtime.getRuntime().exit(0);\n        }\n    };\n\n    private static RealmConfiguration getConfiguration() {\n        return new RealmConfiguration.Builder()\n                .allowQueriesOnUiThread(true)\n                .allowWritesOnUiThread(true)\n                .modules(new AllTypesModelModule()).build();\n    }\n\n}\n"
  },
  {
    "path": "realm/realm-library/src/testUtils/java/io/realm/services/RemoteTestService.java",
    "content": "/*\n * Copyright 2017 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\npackage io.realm.services;\n\nimport android.annotation.SuppressLint;\nimport android.app.Service;\nimport android.content.Intent;\nimport android.os.Bundle;\nimport android.os.Handler;\nimport android.os.IBinder;\nimport android.os.Message;\nimport android.os.Messenger;\nimport android.os.RemoteException;\nimport android.os.StrictMode;\n\nimport java.io.File;\nimport java.io.IOException;\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport io.realm.Realm;\nimport io.realm.internal.Util;\nimport io.realm.log.RealmLog;\n\n/**\n * Helper class for multi-processes support testing.\n * @see io.realm.rule.RunWithRemoteService\n */\npublic abstract class RemoteTestService extends Service {\n    // There is no easy way to dynamically ensure step IDs have same value for different processes. So, use the stupid\n    // way.\n    private static final int BASE_MSG_ID = 0;\n    protected static final int BASE_SIMPLE_COMMIT = BASE_MSG_ID;\n    protected static final int BASE_A_LOT_COMMITS  = BASE_SIMPLE_COMMIT + 100;\n\n    public static abstract class Step {\n        public final int message;\n\n        protected Step(int base, int id) {\n            this.message = base + id;\n            stepMap.put(this.message, this);\n        }\n\n        protected abstract void run();\n\n        protected RemoteTestService getService() {\n            return RemoteTestService.thiz;\n        }\n\n        // Pass a null to tell main process that everything is OK.\n        // Otherwise, pass an error String which will be used by assertion in main process.\n        private void response(String error) {\n            try {\n                Message msg = Message.obtain(null, message);\n                if (error != null) {\n                    Bundle bundle = new Bundle();\n                    bundle.putString(BUNDLE_KEY_ERROR, error);\n                    msg.setData(bundle);\n                }\n                thiz.client.send(msg);\n            } catch (RemoteException e) {\n                RealmLog.error(e);\n            }\n        }\n    }\n\n    public static final String BUNDLE_KEY_ERROR = \"error\";\n    @SuppressLint(\"UseSparseArrays\")\n    private static Map<Integer, Step> stepMap = new HashMap<Integer, Step>();\n    static RemoteTestService thiz;\n    private final Messenger messenger = new Messenger(new IncomingHandler());\n    private Messenger client;\n    private File rootFolder;\n    private Realm realm;\n\n    public RemoteTestService() {\n        if (thiz != null) {\n            throw new RuntimeException(\"Only one instance is allowed!\");\n        }\n        thiz = this;\n    }\n\n    @Override\n    public void onCreate() {\n        super.onCreate();\n        StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();\n        StrictMode.setThreadPolicy(policy);\n        try {\n            rootFolder = File.createTempFile(this.getClass().getSimpleName(), \"\");\n        } catch (IOException e) {\n            RealmLog.error(e);\n        }\n        if (rootFolder.exists() && !rootFolder.delete()) {\n            throw new IllegalStateException(\"Could not delete folder: \" + rootFolder.getAbsolutePath());\n        }\n        if (!rootFolder.mkdir()) {\n            throw new IllegalStateException(\"Could not create folder: \" + rootFolder.getAbsolutePath());\n        }\n\n        Realm.init(getApplicationContext());\n    }\n\n    public File getRoot() {\n        return rootFolder;\n    }\n\n    @Override\n    public IBinder onBind(Intent intent) {\n        return messenger.getBinder();\n    }\n\n    @Override\n    public boolean onUnbind(Intent intent) {\n        stopSelf();\n        recursiveDelete(rootFolder);\n        return super.onUnbind(intent);\n    }\n\n    @Override\n    public int onStartCommand(Intent intent, int flags, int startId) {\n        return START_NOT_STICKY;\n    }\n\n    private static class IncomingHandler extends Handler {\n        @Override\n        public void handleMessage(Message msg) {\n            thiz.client = msg.replyTo;\n            if (thiz.client == null) {\n                throw new RuntimeException(\"Message with an empty client.\");\n            }\n            Step step = stepMap.get(msg.what);\n            Throwable throwable = null;\n            if (step != null) {\n                try {\n                    step.run();\n                } catch (Throwable t) {\n                    throwable = t;\n                } finally {\n                    if (throwable != null) {\n                        step.response(throwable.getMessage() + \"\\n\" + Util.getStackTrace(throwable));\n                    } else {\n                        step.response(null);\n                    }\n                }\n            } else {\n                throw new RuntimeException(\"Cannot find corresponding step to message \" + msg.what + \".\");\n            }\n        }\n    }\n\n    private void recursiveDelete(File file) {\n        File[] files = file.listFiles();\n        if (files != null) {\n            for (File each : files) {\n                recursiveDelete(each);\n            }\n        }\n\n        if (!file.delete()) {\n            throw new IllegalStateException(\"Could not delete file: \" + file.getAbsolutePath());\n        }\n    }\n\n    public Realm getRealm() {\n        return realm;\n    }\n\n    public void setRealm(Realm realm) {\n        this.realm = realm;\n    }\n}\n"
  },
  {
    "path": "realm/realm-library/src/testUtils/kotlin/io/realm/entities/AllKotlinTypes.kt",
    "content": "/*\n * Copyright 2017 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\npackage io.realm.entities\n\nimport io.realm.RealmAny\nimport io.realm.RealmList\nimport io.realm.RealmObject\nimport io.realm.RealmResults\nimport io.realm.annotations.Ignore\nimport io.realm.annotations.Index\nimport io.realm.annotations.LinkingObjects\nimport io.realm.annotations.PrimaryKey\nimport java.util.*\n\nopen class AllKotlinTypes : RealmObject() {\n\n    @Ignore\n    var ignoredString: String = \"\"\n    var nullString: String? = null\n    var nonNullString: String = \"\"\n    @Index\n    var indexedString: String = \"\"\n\n    var nullLong: Long? = null\n    @PrimaryKey\n    var nonNullLong: Long = 0\n\n    var nullShort : Short? = null\n    var nonNullShort: Short = 0\n\n    var nullInt: Int? = null\n    var nonNullInt: Int = 0\n\n    var nullByte: Byte? = null\n    var nonNullByte: Byte = 0\n\n    var nullFloat: Float? = null\n    var nonNullFloat: Float = 0F\n\n    var nullDouble: Double? = null\n    var nonNullDouble: Double = 0.0 // Double by default\n\n    var nullBoolean: Boolean? = null\n    var nonNullBoolean: Boolean = false\n\n    var nullDate: Date? = null\n    var nonNullDate: Date = Date()\n\n    var nullBinary: ByteArray? = null\n    var nonNullBinary: ByteArray = ByteArray(0)\n\n    // This turns into Byte[] which we dont support for some reason?\n    // var nullBoxedBinary: Array<Byte>? = null\n    // var nonNullBoxedBinary: Array<Byte> = emptyArray()\n\n    var nullObject: AllKotlinTypes? = null\n\n    // Not-null object references cannot be enforced generically at the schema level, e.g. sync that\n    // removes an object reference.\n    // If people can maintain the variant themselves they can just expose a custom non-null getter.\n    // var nonNullObject: AllKotlinTypes = AllKotlinTypes()\n\n    // This is only possible in unmanaged objects, managed objects are never null\n    // For now we allow this anyway.\n    var nullList: RealmList<AllKotlinTypes>? = null\n    var nonNullList: RealmList<AllKotlinTypes> = RealmList()\n\n    @LinkingObjects(\"nullObject\")\n    val objectParents: RealmResults<AllKotlinTypes>? = null;\n\n    @LinkingObjects(\"nonNullList\")\n    val listParents: RealmResults<AllKotlinTypes>? = null;\n}\n\nopen class WithRealmAnyTestEntity(\n    @PrimaryKey\n    var id: Long = 0,\n    var items: RealmList<RealmAny> = RealmList<RealmAny>()\n) : RealmObject()\n"
  },
  {
    "path": "realm/realm-library/src/testUtils/kotlin/io/realm/rule/BlockingLooperThread.kt",
    "content": "/*\n * Copyright 2021 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\npackage io.realm.rule\n\nimport android.os.Handler\nimport android.os.Looper\nimport io.realm.TestHelper\nimport io.realm.internal.android.AndroidCapabilities\nimport kotlinx.coroutines.android.asCoroutineDispatcher\nimport org.junit.runners.model.MultipleFailureException\nimport java.io.Closeable\nimport java.io.PrintStream\nimport java.util.*\nimport java.util.concurrent.CountDownLatch\nimport java.util.concurrent.ExecutorService\nimport java.util.concurrent.Executors\nimport java.util.concurrent.TimeUnit\nimport java.util.concurrent.locks.ReentrantLock\nimport kotlin.collections.ArrayList\nimport kotlin.coroutines.CoroutineContext\n\n/**\n * Helper class that makes it easier to run a piece of code inside a [Looper] Thread. This can be\n * achieved by calling either [runBlocking] (which blocks the method execution until the `Looper`\n * either completes, is flagged as completed by the user by calling [testComplete] or throws an\n * exception) or [runDetached] (similar to `runBlocking` but it defers its execution to a later\n * point, signaling its execution with [Condition.await]).\n *\n * **WARNING**\n *\n * **You should not reuse instances of `BlockingLooperThread` across parameterized tests** as\n * `BlockingLooperThread` stores state to handle thread synchronization and this could lead to\n * an unexpected behavior. It is recommended you declare a property that holds a\n * `BlockingLooperThread` instance in your test class as the safest way to work with it as it will\n * be recreated after every test you run. Alternatively, you can declare `BlockingLooperThread`\n * local variables if you deem it necessary based on the scope of your individual tests.\n *\n * Usage:\n * ```\n * val lopperThread = BlockingLooperThread()\n *\n * @Before\n * fun setUp() {\n *     // Runs before test\n * }\n *\n * @After\n * fun tearDown() {\n *     // Runs after test completed or failed\n * }\n *\n * @Test\n * fun myTest() = looperThread.runBlocking {\n *     // test code\n * }\n * ```\n */\nclass BlockingLooperThread {\n    // lock protecting objects shared with the test thread\n    private val lock = ReentrantLock()\n    private var condition: CountDownLatch = CountDownLatch(1)\n\n    // Thread safe\n    private val signalTestCompleted = CountDownLatch(1)\n\n    // Access guarded by 'lock'\n    private var backgroundHandler: Handler? = null\n\n    // the variables created inside the test are local and eligible for GC.\n    // but sometimes we need the variables to survive across different Looper\n    // events (Callbacks happening in the future), so we add a strong reference\n    // to them for the duration of the test.\n    // Access guarded by 'lock'\n    private var keepStrongReference = ArrayList<Any>()\n\n    // List of closable resources that will be automatically closed when the test finishes.\n    // These will run before any methods marked with `@After`.\n    // Access guarded by 'lock'\n    private var closableResources = ArrayList<Closeable>()\n\n    // Runnable guaranteed to trigger after the test either succeeded or failed.\n    // These will run before any methods marked with `@After`.\n    // Access guarded by 'lock'\n    private val runAfterTestIsComplete = ArrayList<Runnable>()\n\n    /**\n     * Runs the test on a Looper thread\n     */\n    fun runBlocking(threadName: String = \"TestLooperThread\", emulateMainThread: Boolean = false, test: () -> Unit) {\n        RunInLooperThreadStatement(threadName, emulateMainThread, test).evaluate()\n    }\n\n    /**\n     * Run the test on a Looper Thread. This override is mostly here for easy JVM interop\n     */\n    fun runBlocking(test: Runnable) {\n        runBlocking(test = {\n            test.run()\n        })\n    }\n\n    /**\n     * Runs the test on a Looper thread. Returns an object that can be used to wait for the test to complete\n     */\n    fun runDetached(threadName: String = \"TestLooperThread\", emulateMainThread: Boolean = false, test: () -> Unit): Condition {\n        return RunInLooperThreadStatement(threadName, emulateMainThread, test).evaluateDetached()\n    }\n\n    /**\n     * Hold a reference to an object, to prevent it from being GCed,\n     * until after the test completes.\n     *\n     * Accessed only from the main thread, here, but synchronized in case it is called from within a test.\n     */\n    fun keepStrongReference(obj: Any) {\n        synchronized(lock) { keepStrongReference.add(obj) }\n    }\n\n    /**\n     * Add a closable resource which this test will guarantee to call [Closeable.close] on\n     * when the tests is done.\n     *\n     * @param closeable [Closeable] to close.\n     */\n    fun closeAfterTest(closeable: Closeable) {\n        synchronized(lock) { closableResources.add(closeable) }\n    }\n\n    /**\n     * Posts a runnable to the currently running looper.\n     */\n    fun postRunnable(runnable: Runnable) {\n        getBackgroundHandler().post(runnable)\n    }\n\n    /**\n     * Posts a runnable to this worker threads looper with a delay in milli second.\n     */\n    fun postRunnableDelayed(runnable: Runnable, delayMillis: Long) {\n        getBackgroundHandler().postDelayed(runnable, delayMillis)\n    }\n\n    /**\n     * Signal that the test has completed.\n     */\n    fun testComplete() {\n        // Close all resources and run any after test tasks\n        // Post as runnable to ensure that this code runs on the correct thread.\n        postRunnable(Runnable { closeTestResources() })\n    }\n\n    /**\n     * Internal logic for shutting down a test.\n     */\n    private fun closeTestResources() {\n        try {\n            closeResources()\n            for (task in runAfterTestIsComplete) {\n                task.run()\n            }\n        } catch (t: Throwable) {\n            throw AssertionError(\"Failed to close test resources correctly\", t)\n        } finally {\n            signalTestCompleted.countDown()\n        }\n    }\n\n    /**\n     * Signal that the test has completed, after waiting for any additional latches.\n     *\n     * @param latches additional latches to wait on, before setting the test completed flag.\n     */\n    fun testComplete(vararg latches: CountDownLatch) {\n        for (latch in latches) {\n            TestHelper.awaitOrFail(latch)\n        }\n        testComplete()\n    }\n\n    private fun getBackgroundHandler(): Handler {\n        synchronized(lock) {\n            while (backgroundHandler == null) {\n                try {\n                    condition.await(5 * 1000, TimeUnit.MILLISECONDS)\n                } catch (e: InterruptedException) {\n                    throw AssertionError(\"Could not acquire the test handler.\", e)\n                }\n            }\n            return backgroundHandler!!\n        }\n    }\n\n    // Accessed from both test and main threads\n    // Storing the handler is the gate that indicates that the test thread has started.\n    private fun setBackgroundHandler(backgroundHandler: Handler?) {\n        synchronized(lock) {\n            this.backgroundHandler = backgroundHandler\n            condition.countDown()\n        }\n    }\n\n    private fun before() {\n        synchronized(lock) {\n            backgroundHandler = null\n            keepStrongReference.clear()\n            closableResources.clear()\n        }\n    }\n\n    private fun after() {\n        // Wait for all async tasks to have completed to ensure a successful deleteRealm call.\n        // If it times out, it will throw.\n        TestHelper.waitRealmThreadExecutorFinish()\n        TestHelper.waitForNetworkThreadExecutorToFinish()\n        AndroidCapabilities.EMULATE_MAIN_THREAD = false\n\n        // probably belt *and* suspenders...\n        synchronized(lock) {\n            backgroundHandler = null\n            keepStrongReference.clear()\n            condition = CountDownLatch(1)\n        }\n    }\n\n    private fun closeResources() {\n        synchronized(lock) {\n            for (cr in closableResources) {\n                cr.close()\n            }\n        }\n    }\n\n    fun asDispatcher(): CoroutineContext {\n        return backgroundHandler?.asCoroutineDispatcher(\"TestLooperDispatcher\")\n                ?: throw IllegalStateException(\"Dispatcher is only available inside 'runBlocking { .. }'.\")\n    }\n\n    inner class RunInLooperThreadStatement(private val threadName: String,\n                                           private val emulateMainThread: Boolean,\n                                           private val test: () -> Unit) {\n\n        fun evaluate() {\n            before()\n            AndroidCapabilities.EMULATE_MAIN_THREAD = emulateMainThread\n            runTest(threadName)\n            after()\n        }\n\n        fun evaluateDetached(): Condition {\n            before()\n            AndroidCapabilities.EMULATE_MAIN_THREAD = emulateMainThread\n\n            return runTestDetached(threadName)\n        }\n\n        private fun runTest(threadName: String) {\n            var failure: Throwable? = null\n\n            try {\n                val executorService = Executors.newSingleThreadExecutor { runnable -> Thread(runnable, threadName) }\n                val test = TestThread(test)\n                executorService.submit(test)\n                TestHelper.exitOrThrow(executorService, signalTestCompleted, test)\n            } catch (testFailure: Throwable) {\n                // These exceptions should only come from TestHelper.awaitOrFail()\n                failure = testFailure\n            } finally {\n                // Tries as hard as possible to close down gracefully, while still keeping all exceptions intact.\n                failure = cleanUp(failure)\n            }\n\n            if (failure != null) {\n                throw failure\n            }\n        }\n\n        private fun runTestDetached(threadName: String): Condition {\n            val executorService = Executors.newSingleThreadExecutor { runnable -> Thread(runnable, threadName) }\n            val test = TestThread(test)\n            executorService.submit(test)\n\n            return Condition(this, executorService, signalTestCompleted, test)\n        }\n\n        fun cleanUp(testfailure: Throwable?): Throwable? {\n            return try {\n                after()\n                testfailure\n            } catch (afterFailure: Throwable) {\n                if (testfailure == null) {\n                    // Only after() threw an exception\n                    afterFailure\n                } else object : MultipleFailureException(Arrays.asList(testfailure, afterFailure)) {\n                    override fun printStackTrace(out: PrintStream) {\n                        var i = 0\n                        for (t in failures) {\n                            out.println(\"Error \" + i + \": \" + t.message)\n                            t.printStackTrace(out)\n                            out.println()\n                            i++\n                        }\n                    }\n                }\n            }\n        }\n    }\n\n    inner class Condition(private val threadStatement: RunInLooperThreadStatement,\n                          private val executorService: ExecutorService,\n                          private val signalTestCompleted: CountDownLatch,\n                          private val test: TestHelper.LooperTest) {\n\n        fun await() {\n            var failure: Throwable? = null\n\n            try {\n                TestHelper.exitOrThrow(executorService, signalTestCompleted, test)\n            } catch (testFailure: Throwable) {\n                // These exceptions should only come from TestHelper.awaitOrFail()\n                failure = testFailure\n            } finally {\n                // Tries as hard as possible to close down gracefully, while still keeping all exceptions intact.\n                failure = threadStatement.cleanUp(failure)\n            }\n\n            if (failure != null) {\n                throw failure\n            }\n            TestHelper.exitOrThrow(executorService, signalTestCompleted, test)\n            after()\n        }\n    }\n\n    private inner class TestThread(private val test: () -> Unit) : Runnable, TestHelper.LooperTest {\n        private var threadAssertionError: Throwable? = null\n        private var looper: Looper? = null\n\n        @Synchronized\n        override fun getLooper(): Looper? {\n            return looper\n        }\n\n        @Synchronized\n        private fun setLooper(looper: Looper) {\n            this.looper = looper\n            setBackgroundHandler(Handler(looper))\n        }\n\n        @Synchronized\n        override fun getAssertionError(): Throwable? {\n            return threadAssertionError\n        }\n\n        // Only record the first error\n        @Synchronized\n        private fun setAssertionError(threadAssertionError: Throwable) {\n            if (this.threadAssertionError == null) {\n                this.threadAssertionError = threadAssertionError\n            }\n        }\n\n        override fun run() {\n            Looper.prepare()\n            try {\n                setLooper(Looper.myLooper()!!)\n                test()\n                Looper.loop()\n            } catch (t: Throwable) {\n                setAssertionError(t)\n                // If an exception occurred, `looperThread.testComplete()` was probably no called.\n                // Rerun it here, but ignore any failures as the first failure is more important.\n                try {\n                    closeTestResources()\n                } catch (ignore: Throwable) {\n                }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "realm/settings.gradle",
    "content": "// Realm projects\ninclude ':realm-library'\ninclude ':realm-annotations-processor'\ninclude ':kotlin-extensions'\n"
  },
  {
    "path": "realm/templates/README.md",
    "content": "This folder contains template files used when releasing Realm Java\n\n**redirect.html.template**\t\nTemplate file that can be used to redirect people to other parts of the documentation. \n"
  },
  {
    "path": "realm/templates/redirect.html.template",
    "content": "<!DOCTYPE HTML>\n<meta charset=\"UTF-8\">\n<meta http-equiv=\"refresh\" content=\"0; url=${url}\">\n<script>\n  window.location.href = \"${url}\"\n</script>\n<title>${title}</title>\nIf you are not redirected automatically, follow the <a href=\"${url}\">link to the documentation.</a>"
  },
  {
    "path": "realm/tools/backlink-ut-source/missingField/source/io/realm/entities/BacklinksMissingFieldSource.java",
    "content": "/*\n * Copyright 2017 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 */\npackage io.realm.entities;\n\nimport io.realm.RealmObject;\n\npublic class BacklinksMissingFieldSource extends RealmObject {\n    private BacklinksMissingFieldTarget child;\n\n    public BacklinksMissingFieldTarget getChild() {\n        return child;\n    }\n\n    public void setChild(BacklinksMissingFieldTarget child) {\n        this.child = child;\n    }\n}\n"
  },
  {
    "path": "realm/tools/backlink-ut-source/missingField/source/io/realm/entities/BacklinksMissingFieldSourceModule.java",
    "content": "/*\n * Copyright 2017 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 */\npackage io.realm.entities;\n\nimport io.realm.annotations.RealmModule;\n\n@RealmModule(classes = {BacklinksMissingFieldSource.class})\npublic class BacklinksMissingFieldSourceModule {\n}\n"
  },
  {
    "path": "realm/tools/backlink-ut-source/missingField/source/io/realm/entities/BacklinksMissingFieldTarget.java",
    "content": "/*\n * Copyright 2017 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 */\npackage io.realm.entities;\n\nimport io.realm.RealmObject;\nimport io.realm.RealmResults;\nimport io.realm.annotations.LinkingObjects;\n\npublic class BacklinksMissingFieldTarget extends RealmObject {\n    private int id;\n\n    @LinkingObjects(\"child\")\n    private final RealmResults<BacklinksMissingFieldSource> parents = null;\n\n    public int getId() {\n        return id;\n    }\n\n    public void setId(int id) {\n        this.id = id;\n    }\n\n    public RealmResults<BacklinksMissingFieldSource> getParents() {\n        return parents;\n    }\n}\n"
  },
  {
    "path": "realm/tools/backlink-ut-source/missingField/source/io/realm/entities/BacklinksMissingFieldTargetModule.java",
    "content": "/*\n * Copyright 2017 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 */\npackage io.realm.entities;\n\nimport io.realm.annotations.RealmModule;\n\n@RealmModule(classes = {BacklinksMissingFieldTarget.class})\npublic class BacklinksMissingFieldTargetModule {\n}\n"
  },
  {
    "path": "realm/tools/backlink-ut-source/missingField/target/io/realm/entities/BacklinksMissingFieldSource.java",
    "content": "/*\n * Copyright 2017 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 */\npackage io.realm.entities;\n\nimport io.realm.RealmObject;\n\npublic class BacklinksMissingFieldSource extends RealmObject {\n    private BacklinksMissingFieldTarget xxxchild;\n\n    public BacklinksMissingFieldTarget getChild() {\n        return xxxchild;\n    }\n\n    public void setChild(BacklinksMissingFieldTarget child) {\n        this.xxxchild = child;\n    }\n}\n"
  },
  {
    "path": "realm/tools/backlink-ut-source/missingField/target/io/realm/entities/BacklinksMissingFieldSourceModule.java",
    "content": "/*\n * Copyright 2017 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 */\npackage io.realm.entities;\n\nimport io.realm.annotations.RealmModule;\n\n@RealmModule(classes = {BacklinksMissingFieldSource.class})\npublic class BacklinksMissingFieldSourceModule {\n}\n"
  },
  {
    "path": "realm/tools/backlink-ut-source/missingField/target/io/realm/entities/BacklinksMissingFieldTarget.java",
    "content": "/*\n * Copyright 2017 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 */\npackage io.realm.entities;\n\nimport io.realm.RealmObject;\nimport io.realm.RealmResults;\nimport io.realm.annotations.LinkingObjects;\n\npublic class BacklinksMissingFieldTarget extends RealmObject {\n    private int id;\n\n    @LinkingObjects(\"xxxchild\")\n    private final RealmResults<BacklinksMissingFieldSource> parents = null;\n\n    public int getId() {\n        return id;\n    }\n\n    public void setId(int id) {\n        this.id = id;\n    }\n\n    public RealmResults<BacklinksMissingFieldSource> getParents() {\n        return parents;\n    }\n}\n"
  },
  {
    "path": "realm/tools/backlink-ut-source/missingField/target/io/realm/entities/BacklinksMissingFieldTargetModule.java",
    "content": "/*\n * Copyright 2017 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 */\npackage io.realm.entities;\n\nimport io.realm.annotations.RealmModule;\n\n@RealmModule(classes = {BacklinksMissingFieldTarget.class})\npublic class BacklinksMissingFieldTargetModule {\n}\n"
  },
  {
    "path": "realm/tools/backlink-ut-source/wrongType/source/io/realm/entities/BacklinksWrongTypeSource.java",
    "content": "/*\n * Copyright 2017 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 */\npackage io.realm.entities;\n\nimport io.realm.RealmObject;\n\npublic class BacklinksWrongTypeSource extends RealmObject {\n    private Integer childId;\n\n    private BacklinksWrongTypeTarget child;\n\n    public Integer getChildId() {\n        return childId;\n    }\n\n    public void setChildId(Integer childId) {\n        this.childId = childId;\n    }\n\n    public BacklinksWrongTypeTarget getChild() {\n        return child;\n    }\n\n    public void setChild(BacklinksWrongTypeTarget child) {\n        this.child = child;\n    }\n}\n"
  },
  {
    "path": "realm/tools/backlink-ut-source/wrongType/source/io/realm/entities/BacklinksWrongTypeSourceModule.java",
    "content": "/*\n * Copyright 2017 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 */\npackage io.realm.entities;\n\nimport io.realm.annotations.RealmModule;\n\n@RealmModule(classes = {BacklinksWrongTypeSource.class})\npublic class BacklinksWrongTypeSourceModule {\n}\n"
  },
  {
    "path": "realm/tools/backlink-ut-source/wrongType/source/io/realm/entities/BacklinksWrongTypeTarget.java",
    "content": "/*\n * Copyright 2017 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 */\npackage io.realm.entities;\n\nimport io.realm.RealmObject;\nimport io.realm.RealmResults;\nimport io.realm.annotations.LinkingObjects;\n\npublic class BacklinksWrongTypeTarget extends RealmObject {\n    private int id;\n\n    @LinkingObjects(\"child\")\n    private final RealmResults<BacklinksWrongTypeSource> parents = null;\n\n    public int getId() {\n        return id;\n    }\n\n    public void setId(int id) {\n        this.id = id;\n    }\n\n    public RealmResults<BacklinksWrongTypeSource> getParents() {\n        return parents;\n    }\n}\n"
  },
  {
    "path": "realm/tools/backlink-ut-source/wrongType/source/io/realm/entities/BacklinksWrongTypeTargetModule.java",
    "content": "/*\n * Copyright 2017 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 */\npackage io.realm.entities;\n\nimport io.realm.annotations.RealmModule;\n\n@RealmModule(classes = {BacklinksWrongTypeTarget.class})\npublic class BacklinksWrongTypeTargetModule {\n}\n"
  },
  {
    "path": "realm/tools/backlink-ut-source/wrongType/target/io/realm/entities/BacklinksWrongTypeSource.java",
    "content": "/*\n * Copyright 2017 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 */\npackage io.realm.entities;\n\nimport io.realm.RealmObject;\n\npublic class BacklinksWrongTypeSource extends RealmObject {\n    private Integer child;\n\n    private BacklinksWrongTypeTarget childId;\n\n    public Integer getChildId() {\n        return child;\n    }\n\n    public void setChildId(Integer childId) {\n        this.child = childId;\n    }\n\n    public BacklinksWrongTypeTarget getChild() {\n        return childId;\n    }\n\n    public void setChild(BacklinksWrongTypeTarget child) {\n        this.childId = childId;\n    }\n}\n"
  },
  {
    "path": "realm/tools/backlink-ut-source/wrongType/target/io/realm/entities/BacklinksWrongTypeSourceModule.java",
    "content": "/*\n * Copyright 2017 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 */\npackage io.realm.entities;\n\nimport io.realm.annotations.RealmModule;\n\n@RealmModule(classes = {BacklinksWrongTypeSource.class})\npublic class BacklinksWrongTypeSourceModule {\n}\n"
  },
  {
    "path": "realm/tools/backlink-ut-source/wrongType/target/io/realm/entities/BacklinksWrongTypeTarget.java",
    "content": "/*\n * Copyright 2017 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 */\npackage io.realm.entities;\n\nimport io.realm.RealmObject;\nimport io.realm.RealmResults;\nimport io.realm.annotations.LinkingObjects;\n\npublic class BacklinksWrongTypeTarget extends RealmObject {\n    private int id;\n\n    @LinkingObjects(\"childId\")\n    private final RealmResults<BacklinksWrongTypeSource> parents = null;\n\n    public int getId() {\n        return id;\n    }\n\n    public void setId(int id) {\n        this.id = id;\n    }\n\n    public RealmResults<BacklinksWrongTypeSource> getParents() {\n        return parents;\n    }\n}\n"
  },
  {
    "path": "realm/tools/backlink-ut-source/wrongType/target/io/realm/entities/BacklinksWrongTypeTargetModule.java",
    "content": "/*\n * Copyright 2017 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 */\npackage io.realm.entities;\n\nimport io.realm.annotations.RealmModule;\n\n@RealmModule(classes = {BacklinksWrongTypeTarget.class})\npublic class BacklinksWrongTypeTargetModule {\n}\n"
  },
  {
    "path": "realm/tools/bin/cgen",
    "content": "#!/bin/bash\n\n# Customize as necessary\nREALM_JAVA=~/Working/java\nGRADLE_CACHE=~/.gradle\nANDROID_SDK=~/Library/Android/sdk\n\nif [ $# -lt 2 ] ; then\n  echo \"Usage: $0 <destination folder> <java file>...\"\n  exit 1\nfi\n\nTARGET_DIR=\"$1\"\nshift\n\nif [ ! -d \"$TARGET_DIR\" ] ; then\n  echo \"$TARGET_DIR is not a directory\"\n  exit 1\nfi\n\nREALM_ANNOTATIONS=`find \"$REALM_JAVA/realm-annotations/build\" -name 'realm-annotations-*.jar'`\nif [ ! -f \"$REALM_ANNOTATIONS\" ] ; then\n  echo \"Cannot find the Realm Annotations jar in $REALM_JAVA\"\n  exit 1\nfi\n\nREALM_ANNOTATION_PROCESSOR=`find \"$REALM_JAVA/realm/realm-annotations-processor\" -name 'realm-annotations-processor-*.jar'`\nif [ ! -f \"$REALM_ANNOTATION_PROCESSOR\" ] ; then\n  echo \"Cannot find the Realm Annotation Processor jar in $REALM_JAVA\"\n  exit 1\nfi\n\nREALM_CLASSES=\"$REALM_JAVA/realm/realm-library/build/intermediates/classes/base/release\"\nif [ ! -d \"$REALM_CLASSES\" ] ; then\n  echo \"Cannot find the Realm classes in $REALM_JAVA\"\n  exit 1\nfi\n\nJAVAWRITER=`find \"$GRADLE_CACHE/caches/jars\"* -name 'javawriter-2.5*.jar' | head -1`\nif [ ! -f \"$JAVAWRITER\" ] ; then\n  echo \"Cannot find JavaWriter jar in $GRADLE_CACHE\"\n  exit 1\nfi\n\nCLASSPATH=\"$REALM_ANNOTATION_PROCESSOR\":\"$JAVAWRITER\":\"$REALM_ANNOTATIONS\":\"$REALM_CLASSES\"\n\njavac \\\n  -d \"$TARGET_DIR\" \\\n  -bootclasspath \"$ANDROID_SDK/platforms/android-24/android.jar\" \\\n  -source 7 \\\n  -target 7 \\\n  -cp \"$CLASSPATH\" \\\n  -processor io.realm.processor.RealmProcessor \\\n  $*\n\n"
  },
  {
    "path": "realm-annotations/build.gradle",
    "content": "buildscript {\n    def properties = new Properties()\n    properties.load(new FileInputStream(\"${projectDir}/../dependencies.list\"))\n\n    repositories {\n        jcenter()\n        maven {\n            url \"https://plugins.gradle.org/m2/\"\n        }\n    }\n    dependencies {\n        classpath \"org.jfrog.buildinfo:build-info-extractor-gradle:${properties.get('BUILD_INFO_EXTRACTOR_GRADLE')}\"\n        classpath \"io.github.gradle-nexus:publish-plugin:${properties.get(\"GRADLE_NEXUS_PLUGIN\")}\"\n    }\n}\n\napply plugin: 'java'\napply plugin: 'maven-publish'\n\nsourceCompatibility = JavaVersion.VERSION_1_8\ntargetCompatibility = JavaVersion.VERSION_1_8\n\ngroup = 'io.realm'\nversion = file(\"${projectDir}/../version.txt\").text.trim()\n\napply from: \"${rootDir}/../mavencentral-publications.gradle\"\napply from: \"${rootDir}/../mavencentral-publish.gradle\"\n\npublishing {\n    publications {\n        realmPublication(MavenPublication) {\n            groupId 'io.realm'\n            artifactId = 'realm-annotations'\n            from components.java\n            populatePom(\n                    it,\n                    'realm-annotations',\n                    'Annotations for Realm. Realm is a mobile database: Build better apps, faster.'\n            )\n        }\n    }\n}\n\njava {\n    withSourcesJar()\n    withJavadocJar()\n    sourceCompatibility = JavaVersion.VERSION_1_8\n    targetCompatibility = JavaVersion.VERSION_1_8\n}\n\njavadoc {\n    options.encoding = 'UTF-8'\n}\n"
  },
  {
    "path": "realm-annotations/gradle/wrapper/gradle-wrapper.properties",
    "content": "distributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\ndistributionUrl=https\\://services.gradle.org/distributions/gradle-7.5-all.zip\nzipStoreBase=GRADLE_USER_HOME\nzipStorePath=wrapper/dists\n"
  },
  {
    "path": "realm-annotations/gradle.properties",
    "content": "org.gradle.caching=true"
  },
  {
    "path": "realm-annotations/gradlew",
    "content": "#!/bin/sh\n\n#\n# Copyright © 2015-2021 the original authors.\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#      https://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##############################################################################\n#\n#   Gradle start up script for POSIX generated by Gradle.\n#\n#   Important for running:\n#\n#   (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is\n#       noncompliant, but you have some other compliant shell such as ksh or\n#       bash, then to run this script, type that shell name before the whole\n#       command line, like:\n#\n#           ksh Gradle\n#\n#       Busybox and similar reduced shells will NOT work, because this script\n#       requires all of these POSIX shell features:\n#         * functions;\n#         * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,\n#           «${var#prefix}», «${var%suffix}», and «$( cmd )»;\n#         * compound commands having a testable exit status, especially «case»;\n#         * various built-in commands including «command», «set», and «ulimit».\n#\n#   Important for patching:\n#\n#   (2) This script targets any POSIX shell, so it avoids extensions provided\n#       by Bash, Ksh, etc; in particular arrays are avoided.\n#\n#       The \"traditional\" practice of packing multiple parameters into a\n#       space-separated string is a well documented source of bugs and security\n#       problems, so this is (mostly) avoided, by progressively accumulating\n#       options in \"$@\", and eventually passing that to Java.\n#\n#       Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,\n#       and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;\n#       see the in-line comments for details.\n#\n#       There are tweaks for specific operating systems such as AIX, CygWin,\n#       Darwin, MinGW, and NonStop.\n#\n#   (3) This script is generated from the Groovy template\n#       https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt\n#       within the Gradle project.\n#\n#       You can find Gradle at https://github.com/gradle/gradle/.\n#\n##############################################################################\n\n# Attempt to set APP_HOME\n\n# Resolve links: $0 may be a link\napp_path=$0\n\n# Need this for daisy-chained symlinks.\nwhile\n    APP_HOME=${app_path%\"${app_path##*/}\"}  # leaves a trailing /; empty if no leading path\n    [ -h \"$app_path\" ]\ndo\n    ls=$( ls -ld \"$app_path\" )\n    link=${ls#*' -> '}\n    case $link in             #(\n      /*)   app_path=$link ;; #(\n      *)    app_path=$APP_HOME$link ;;\n    esac\ndone\n\nAPP_HOME=$( cd \"${APP_HOME:-./}\" && pwd -P ) || exit\n\nAPP_NAME=\"Gradle\"\nAPP_BASE_NAME=${0##*/}\n\n# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\nDEFAULT_JVM_OPTS='\"-Xmx64m\" \"-Xms64m\"'\n\n# Use the maximum available, or set MAX_FD != -1 to use that value.\nMAX_FD=maximum\n\nwarn () {\n    echo \"$*\"\n} >&2\n\ndie () {\n    echo\n    echo \"$*\"\n    echo\n    exit 1\n} >&2\n\n# OS specific support (must be 'true' or 'false').\ncygwin=false\nmsys=false\ndarwin=false\nnonstop=false\ncase \"$( uname )\" in                #(\n  CYGWIN* )         cygwin=true  ;; #(\n  Darwin* )         darwin=true  ;; #(\n  MSYS* | MINGW* )  msys=true    ;; #(\n  NONSTOP* )        nonstop=true ;;\nesac\n\nCLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar\n\n\n# Determine the Java command to use to start the JVM.\nif [ -n \"$JAVA_HOME\" ] ; then\n    if [ -x \"$JAVA_HOME/jre/sh/java\" ] ; then\n        # IBM's JDK on AIX uses strange locations for the executables\n        JAVACMD=$JAVA_HOME/jre/sh/java\n    else\n        JAVACMD=$JAVA_HOME/bin/java\n    fi\n    if [ ! -x \"$JAVACMD\" ] ; then\n        die \"ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME\n\nPlease set the JAVA_HOME variable in your environment to match the\nlocation of your Java installation.\"\n    fi\nelse\n    JAVACMD=java\n    which java >/dev/null 2>&1 || die \"ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.\n\nPlease set the JAVA_HOME variable in your environment to match the\nlocation of your Java installation.\"\nfi\n\n# Increase the maximum file descriptors if we can.\nif ! \"$cygwin\" && ! \"$darwin\" && ! \"$nonstop\" ; then\n    case $MAX_FD in #(\n      max*)\n        MAX_FD=$( ulimit -H -n ) ||\n            warn \"Could not query maximum file descriptor limit\"\n    esac\n    case $MAX_FD in  #(\n      '' | soft) :;; #(\n      *)\n        ulimit -n \"$MAX_FD\" ||\n            warn \"Could not set maximum file descriptor limit to $MAX_FD\"\n    esac\nfi\n\n# Collect all arguments for the java command, stacking in reverse order:\n#   * args from the command line\n#   * the main class name\n#   * -classpath\n#   * -D...appname settings\n#   * --module-path (only if needed)\n#   * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.\n\n# For Cygwin or MSYS, switch paths to Windows format before running java\nif \"$cygwin\" || \"$msys\" ; then\n    APP_HOME=$( cygpath --path --mixed \"$APP_HOME\" )\n    CLASSPATH=$( cygpath --path --mixed \"$CLASSPATH\" )\n\n    JAVACMD=$( cygpath --unix \"$JAVACMD\" )\n\n    # Now convert the arguments - kludge to limit ourselves to /bin/sh\n    for arg do\n        if\n            case $arg in                                #(\n              -*)   false ;;                            # don't mess with options #(\n              /?*)  t=${arg#/} t=/${t%%/*}              # looks like a POSIX filepath\n                    [ -e \"$t\" ] ;;                      #(\n              *)    false ;;\n            esac\n        then\n            arg=$( cygpath --path --ignore --mixed \"$arg\" )\n        fi\n        # Roll the args list around exactly as many times as the number of\n        # args, so each arg winds up back in the position where it started, but\n        # possibly modified.\n        #\n        # NB: a `for` loop captures its iteration list before it begins, so\n        # changing the positional parameters here affects neither the number of\n        # iterations, nor the values presented in `arg`.\n        shift                   # remove old arg\n        set -- \"$@\" \"$arg\"      # push replacement arg\n    done\nfi\n\n# Collect all arguments for the java command;\n#   * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of\n#     shell script including quotes and variable substitutions, so put them in\n#     double quotes to make sure that they get re-expanded; and\n#   * put everything else in single quotes, so that it's not re-expanded.\n\nset -- \\\n        \"-Dorg.gradle.appname=$APP_BASE_NAME\" \\\n        -classpath \"$CLASSPATH\" \\\n        org.gradle.wrapper.GradleWrapperMain \\\n        \"$@\"\n\n# Stop when \"xargs\" is not available.\nif ! command -v xargs >/dev/null 2>&1\nthen\n    die \"xargs is not available\"\nfi\n\n# Use \"xargs\" to parse quoted args.\n#\n# With -n1 it outputs one arg per line, with the quotes and backslashes removed.\n#\n# In Bash we could simply go:\n#\n#   readarray ARGS < <( xargs -n1 <<<\"$var\" ) &&\n#   set -- \"${ARGS[@]}\" \"$@\"\n#\n# but POSIX shell has neither arrays nor command substitution, so instead we\n# post-process each arg (as a line of input to sed) to backslash-escape any\n# character that might be a shell metacharacter, then use eval to reverse\n# that process (while maintaining the separation between arguments), and wrap\n# the whole thing up as a single \"set\" statement.\n#\n# This will of course break if any of these variables contains a newline or\n# an unmatched quote.\n#\n\neval \"set -- $(\n        printf '%s\\n' \"$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS\" |\n        xargs -n1 |\n        sed ' s~[^-[:alnum:]+,./:=@_]~\\\\&~g; ' |\n        tr '\\n' ' '\n    )\" '\"$@\"'\n\nexec \"$JAVACMD\" \"$@\"\n"
  },
  {
    "path": "realm-annotations/gradlew.bat",
    "content": "@rem\r\n@rem Copyright 2015 the original author or authors.\r\n@rem\r\n@rem Licensed under the Apache License, Version 2.0 (the \"License\");\r\n@rem you may not use this file except in compliance with the License.\r\n@rem You may obtain a copy of the License at\r\n@rem\r\n@rem      https://www.apache.org/licenses/LICENSE-2.0\r\n@rem\r\n@rem Unless required by applicable law or agreed to in writing, software\r\n@rem distributed under the License is distributed on an \"AS IS\" BASIS,\r\n@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n@rem See the License for the specific language governing permissions and\r\n@rem limitations under the License.\r\n@rem\r\n\r\n@if \"%DEBUG%\"==\"\" @echo off\r\n@rem ##########################################################################\r\n@rem\r\n@rem  Gradle startup script for Windows\r\n@rem\r\n@rem ##########################################################################\r\n\r\n@rem Set local scope for the variables with windows NT shell\r\nif \"%OS%\"==\"Windows_NT\" setlocal\r\n\r\nset DIRNAME=%~dp0\r\nif \"%DIRNAME%\"==\"\" set DIRNAME=.\r\nset APP_BASE_NAME=%~n0\r\nset APP_HOME=%DIRNAME%\r\n\r\n@rem Resolve any \".\" and \"..\" in APP_HOME to make it shorter.\r\nfor %%i in (\"%APP_HOME%\") do set APP_HOME=%%~fi\r\n\r\n@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\r\nset DEFAULT_JVM_OPTS=\"-Xmx64m\" \"-Xms64m\"\r\n\r\n@rem Find java.exe\r\nif defined JAVA_HOME goto findJavaFromJavaHome\r\n\r\nset JAVA_EXE=java.exe\r\n%JAVA_EXE% -version >NUL 2>&1\r\nif %ERRORLEVEL% equ 0 goto execute\r\n\r\necho.\r\necho ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.\r\necho.\r\necho Please set the JAVA_HOME variable in your environment to match the\r\necho location of your Java installation.\r\n\r\ngoto fail\r\n\r\n:findJavaFromJavaHome\r\nset JAVA_HOME=%JAVA_HOME:\"=%\r\nset JAVA_EXE=%JAVA_HOME%/bin/java.exe\r\n\r\nif exist \"%JAVA_EXE%\" goto execute\r\n\r\necho.\r\necho ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%\r\necho.\r\necho Please set the JAVA_HOME variable in your environment to match the\r\necho location of your Java installation.\r\n\r\ngoto fail\r\n\r\n:execute\r\n@rem Setup the command line\r\n\r\nset CLASSPATH=%APP_HOME%\\gradle\\wrapper\\gradle-wrapper.jar\r\n\r\n\r\n@rem Execute Gradle\r\n\"%JAVA_EXE%\" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% \"-Dorg.gradle.appname=%APP_BASE_NAME%\" -classpath \"%CLASSPATH%\" org.gradle.wrapper.GradleWrapperMain %*\r\n\r\n:end\r\n@rem End local scope for the variables with windows NT shell\r\nif %ERRORLEVEL% equ 0 goto mainEnd\r\n\r\n:fail\r\nrem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of\r\nrem the _cmd.exe /c_ return code!\r\nset EXIT_CODE=%ERRORLEVEL%\r\nif %EXIT_CODE% equ 0 set EXIT_CODE=1\r\nif not \"\"==\"%GRADLE_EXIT_CONSOLE%\" exit %EXIT_CODE%\r\nexit /b %EXIT_CODE%\r\n\r\n:mainEnd\r\nif \"%OS%\"==\"Windows_NT\" endlocal\r\n\r\n:omega\r\n"
  },
  {
    "path": "realm-annotations/settings.gradle",
    "content": "rootProject.name = 'realm-annotations'\n"
  },
  {
    "path": "realm-annotations/src/main/java/io/realm/annotations/Beta.java",
    "content": "/*\n * Copyright 2016 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\npackage io.realm.annotations;\n\nimport java.lang.annotation.ElementType;\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.RetentionPolicy;\nimport java.lang.annotation.Target;\n\n/**\n * This annotation is added to classes, constructors or methods which are considered in beta phase.\n * It indicates that any public interface can change without prior announcements.\n * Moreover, classes, constructors, and methods annotated as beta are not considered at production\n * quality, and should be used with care.\n */\n@Retention(RetentionPolicy.SOURCE)\n@Target({ElementType.TYPE, ElementType.CONSTRUCTOR, ElementType.METHOD})\npublic @interface Beta {\n}\n"
  },
  {
    "path": "realm-annotations/src/main/java/io/realm/annotations/Ignore.java",
    "content": "/*\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\npackage io.realm.annotations;\n\nimport java.lang.annotation.ElementType;\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.RetentionPolicy;\nimport java.lang.annotation.Target;\n\n@Retention(RetentionPolicy.RUNTIME)\n@Target(ElementType.FIELD)\npublic @interface Ignore {\n\n}\n"
  },
  {
    "path": "realm-annotations/src/main/java/io/realm/annotations/Index.java",
    "content": "/*\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\npackage io.realm.annotations;\n\nimport java.lang.annotation.ElementType;\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.RetentionPolicy;\nimport java.lang.annotation.Target;\n\n/**\n * This annotation will add a search index to the field. A search index will make the\n * Realm file larger and inserts slower but queries will be faster. \n * <p>\n * NOTICE: Only String, int, byte, short, long, boolean and Date fields can be indexed.\n */\n@Retention(RetentionPolicy.RUNTIME)\n@Target(ElementType.FIELD)\npublic @interface Index {\n\n}\n"
  },
  {
    "path": "realm-annotations/src/main/java/io/realm/annotations/LinkingObjects.java",
    "content": "/*\n * Copyright 2017 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\npackage io.realm.annotations;\n\nimport java.lang.annotation.ElementType;\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.RetentionPolicy;\nimport java.lang.annotation.Target;\n\n/**\n * Annotation for defining a reverse relationship from one class to another. This annotation can\n * only be added to a field of the type {@code RealmResults}.\n *<pre>\n * To expose reverse relationships for use, create a declaration as follows:\n * {@code\n *\n * public class Person extends RealmObject {\n *   String name;\n *   Dog dog; // Normal relation\n * }\n *\n * public class Dog extends RealmObject {\n *   // This holds all Person objects with a relation to this Dog object (= linking objects)\n *   \\@LinkingObjects(\"dog\")\n *   final RealmResults&gt;Person&lt; owners = null;\n * }\n *\n * // Find all Dogs with at least one owner named John\n * realm.where(Dog.class).equalTo(\"owners.name\", \"John\").findAll();\n * }\n * </pre>\n * In the above example `Person` is related to `Dog` through the field `dog`.\n * This in turn means that an implicit reverse relationship exists between the class `Dog`\n * and the class `Person`. This inverse relationship is made public and queryable by the `RealmResults`\n * field annotated with `@LinkingObject`. This makes it possible to query properties of the dogs owner\n * without having to manually maintain a \"owner\" field in the `Dog` class.\n * <p>\n * Linking objects have the following properties:\n * <ul>\n *     <li>The link is maintained by Realm and only works for managed objects.</li>\n *     <li>They can be queried just like normal relation.</li>\n *     <li>They can be followed just like normal relation.</li>\n *     <li>They are ignored when doing a `copyToRealm().`</li>\n *     <li>They are ignored when doing a `copyFromRealm().`</li>\n *     <li>They are ignored when using the various `createObjectFromJson*` and `createAllFromJson*` methods.</li>\n *     <li>Listeners on an object with a `@LinkingObject` field will not be triggered if the linking objects change,\n *     e.g: if another object drops a reference to this object.</li>\n * </ul>\n * <p>\n * In addition, they have the following restrictions:\n * <ul>\n *     <li>{@literal @}Ignore takes precedence.  A {@literal @}LinkingObjects annotation on {@literal @}Ignore field will be ignored.</li>\n *     <li>The annotated field cannot be {@literal @}Required.</li>\n *     <li>The annotated field must be `final`.</li>\n *     <li>The annotation argument (the name of the backlinked field) is required.</li>\n *     <li>The annotation argument must be a simple field name.  It cannot contain periods ('.').</li>\n *     <li>The annotated field must be of type `RealmResults&lt;T&gt;` where T is concrete class that extends `RealmModel`.</li>\n * </ul>\n *\n * Note that when the source of the reverse reference (`dog` in the case above) is a `List`, there is a reverse\n * reference for each forward reference, even if both forward references are to the same object.\n * If the `Person` class above were defined as:\n * {@code\n *\n * public class DogLover extends RealmObject {\n *   String name;\n *   List<Dog> dogs = new ArrayList<Dog>;\n * }\n * }\n * then the following code executes without error\n * {@code\n *\n * Dog fido = new Dog();\n * DogLover john = new DogLover()\n * john.dogs.add(fido);\n * john.dogs.add(fido);\n * assert john.dogs.size() == 2;\n * assert fido.owners.size() == 2;\n * }\n * <p>\n * Querying inverse relationship is like querying any {@code RealmResults}. This means that an inverse relationship\n * cannot be {@code null} but it can be empty (length is 0). It is possible to query fields in the source class. This is\n * equivalent to link queries. Please read <a href=\"https://docs.mongodb.com/realm/sdk/android/examples/define-a-realm-object-model/#std-label-android-field-relationships-inverse\">for more\n * information</a>.\n */\n@Retention(RetentionPolicy.RUNTIME)\n@Target(ElementType.FIELD)\npublic @interface LinkingObjects {\n    /**\n     * The name of a field that contains a relation to an instance of the\n     * class containing this annotation.  If this argument is not provided\n     * the annotation processor will abort with an {@code IllegalArgumentException}.\n     */\n    String value() default \"\";\n}\n"
  },
  {
    "path": "realm-annotations/src/main/java/io/realm/annotations/PrimaryKey.java",
    "content": "/*\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\npackage io.realm.annotations;\n\nimport java.lang.annotation.ElementType;\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.RetentionPolicy;\nimport java.lang.annotation.Target;\n\n/**\n * The @PrimaryKey annotation will mark a field as a primary key inside Realm. Only one field in a\n * RealmObject class can have this annotation, and the field should uniquely identify the object.\n * Trying to insert an object with an existing primary key will result in an\n * {@code io.realm.exceptions.RealmPrimaryKeyConstraintException}. Primary key cannot be changed\n * after the object created.\n * <p>\n * Primary keys also count as having the {@link Index} annotation.\n * <p>\n * It is allowed to apply this annotation on the following primitive types: byte, short, int, and long.\n * String, Byte, Short, Integer, Long, ObjectId and UUID are also allowed, and further permitted to have\n * {@code null} as a primary key value.\n * <p>\n * This annotation is not allowed inside Realm classes marked as {@code \\@RealmClass(embedded = true)}.\n * </p>\n */\n@Retention(RetentionPolicy.RUNTIME)\n@Target(ElementType.FIELD)\npublic @interface PrimaryKey {\n\n}\n"
  },
  {
    "path": "realm-annotations/src/main/java/io/realm/annotations/RealmClass.java",
    "content": "/*\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\npackage io.realm.annotations;\n\n\nimport java.lang.annotation.ElementType;\nimport java.lang.annotation.Inherited;\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.RetentionPolicy;\nimport java.lang.annotation.Target;\n\n/**\n * Interface used to mark a class that can be persisted by Realm.\n */\n@Retention(RetentionPolicy.RUNTIME)\n@Target(ElementType.TYPE)\n@Inherited\npublic @interface RealmClass {\n\n    /**\n     * Manually set the internal name used by Realm for this class. If this class is part of\n     * any modules, this will also override any name policy set using\n     * {@link RealmModule#classNamingPolicy()}.\n     *\n     * @see io.realm.annotations.RealmNamingPolicy for more information about what setting the name means.\n     * @see #name()\n     */\n    String value() default \"\";\n\n    /**\n     * Manually set the internal name used by Realm for this class. If this class is part of\n     * any modules, this will also override any name policy set using\n     * {@link RealmModule#classNamingPolicy()}.\n     *\n     * @see io.realm.annotations.RealmNamingPolicy for more information about what setting the name means.\n     */\n    String name() default \"\";\n\n    /**\n     * Define objects of this type as \"Embedded\". Embedded objects have a slightly different behavior than\n     * normal objects:\n     * <ul>\n     *     <li>\n     *         They must have exactly 1 parent linking to them when the embedded object is added to\n     *         the Realm. Embedded objects can be the parent of other embedded objects. The parent\n     *         cannot be changed later, except by copying the object.\n     *     </li>\n     *     <li>\n     *         They cannot have fields annotated with {@code \\@PrimaryKey}.\n     *     </li>\n     *     <li>\n     *         When a parent object is deleted, all embedded objects are also deleted.\n     *     </li>\n     *     <li>\n     *         It is possible to define an easy reference to the parent object using the\n     *         {@code \\@LinkingObjects} annotation:\n     *         <pre>\n     *         {@code\n     *              \\@LinkingObjects\n     *              public Parent parent;\n     *         }\n     *         </pre>\n     *     </li>\n     * </ul>\n     */\n    boolean embedded() default false;\n\n    /**\n     * The naming policy applied to all fields in this class. The default policy is {@link RealmNamingPolicy#NO_POLICY}.\n     * <p>\n     * It is possible to override the naming policy for each field by using the {@link RealmField} annotation.\n     *\n     * @see io.realm.annotations.RealmNamingPolicy for more information about what setting this policy means.\n     */\n    RealmNamingPolicy fieldNamingPolicy() default RealmNamingPolicy.NO_POLICY;\n}\n"
  },
  {
    "path": "realm-annotations/src/main/java/io/realm/annotations/RealmField.java",
    "content": "/*\n * Copyright 2018 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 */\npackage io.realm.annotations;\n\n\nimport java.lang.annotation.ElementType;\nimport java.lang.annotation.Inherited;\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.RetentionPolicy;\nimport java.lang.annotation.Target;\n\n/**\n * Annotation used on fields in Realm model classes. It describes metadata about the field.\n */\n@Retention(RetentionPolicy.RUNTIME)\n@Target(ElementType.FIELD)\n@Inherited\npublic @interface RealmField {\n\n    /**\n     * Manually set the internal name used by Realm for this field. This will override any\n     * {@link RealmNamingPolicy} set on the class or the module.\n     *\n     * @see io.realm.annotations.RealmNamingPolicy for more information about what setting the name means.\n     * @see #name()\n     */\n    String value() default \"\";\n\n    /**\n     * Manually set the internal name used by Realm for this field. This will override any\n     * {@link RealmNamingPolicy} set on the class or the module.\n     *\n     * @see io.realm.annotations.RealmNamingPolicy for more information about what setting the name means.\n     */\n    String name() default \"\";\n}\n"
  },
  {
    "path": "realm-annotations/src/main/java/io/realm/annotations/RealmModule.java",
    "content": "/*\n * Copyright 2015 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\npackage io.realm.annotations;\n\nimport java.lang.annotation.ElementType;\nimport java.lang.annotation.Inherited;\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.RetentionPolicy;\nimport java.lang.annotation.Target;\n\n/**\n * By default a Realm can store all classes extending RealmObject in a project. However, if you want to restrict a\n * Realm to only contain a subset of classes or want to share them between a library project and an app project, you must\n * use a RealmModule.\n * <p>\n * A RealmModule is a collection of classes extending RealmObject that can be combined with other RealmModules to create\n * the schema for a Realm. This makes it easier to control versioning and migration of those Realms.\n * <p>\n * A RealmModule can either be a library module or an app module. The distinction is made by setting\n * {@code library = true}. Setting {@code library = true} is normally only relevant for library authors. See below for\n * further details.\n *\n * <p>\n * Currently, it is not possible to have multiple RealmModule declarations in a single file. If you have more than one\n * RealmModule, you will have to use separate Java files for each module.\n *\n *\n * <h2>RealmModules and libraries</h2>\n *\n * Realms default behavior is to automatically create a RealmModule called {@code DefaultRealmModule} which contains all\n * classes extending RealmObject in a project. This module is automatically known by Realm.\n * <p>\n * This behavior is problematic when combining a library project and an app project that both uses Realm. This is\n * because the {@code DefaultRealmModule} will be created for both the library project and the app project, which will\n * cause the project to fail with duplicate class definition errors.\n * <p>\n * Library authors are responsible for avoiding this conflict by using explicit modules where {@code library = true} is\n * set. This disables the generation of the DefaultRealmModule for the library project and allows the library to be\n * included in the app project that also uses Realm. This means that library projects that uses Realm internally are\n * required to specify a specific module using {@code RealmConfiguration.modules()}.\n * <p>\n * App developers are not required to specify any modules, as they implicitly use the {@code DefaultRealmModule}, but\n * they now has the option of adding the library project classes to their schema using\n * {@code RealmConfiguration.addModule()}.\n *\n * @see <a href=\"https://github.com/realm/realm-java/tree/master/examples/moduleExample\">Example of a project using modules</a>\n */\n@Retention(RetentionPolicy.RUNTIME)\n@Target(ElementType.TYPE)\n@Inherited\npublic @interface RealmModule {\n\n    /**\n     * Setting this to true will mark this module as a library module. This will prevent Realm from generating the\n     * {@code DefaultRealmModule} containing all classes. This is required by libraries so they do not interfere with\n     * Realms running in app code, but it also means that all libraries using Realm must explicitly use a module and\n     * cannot  rely on the default module being present.\n     *\n     * Creating library modules and normal modules in the same project is not allowed and will result in the annotation\n     * processor throwing an exception.\n     */\n    boolean library() default false;\n\n    /**\n     * Instead of adding all Realm classes manually to a module, set this boolean to true to automatically include all\n     * Realm classes in this project. This does not include classes from other libraries which must be exposed using\n     * their own module.\n     *\n     * Setting both {@code allClasses = true} and {@code classes()} will result in the annotation processor throwing\n     * an exception.\n     */\n    boolean allClasses() default false;\n\n    /**\n     * Specifies the classes extending RealmObject that should be part of this module. Only classes in this project can\n     * be included. Classes from other libraries must be exposed using their own module.\n     *\n     * Setting both {@code allClasses = true} and {@code classes()} will result in the annotation processor throwing\n     * an exception.\n     */\n    Class<?>[] classes() default {};\n\n    /**\n     * The naming policy applied to all classes part of this module. The default policy is {@link RealmNamingPolicy#NO_POLICY}.\n     * To define a naming policy for all fields in the classes, use {@link #fieldNamingPolicy()}.\n     * <p>\n     * It is possible to override the naming policy specified in the module in each class using the {@link RealmClass}\n     * annotation.\n     * <p>\n     * If a class is part of multiple modules, the same naming policy must be applied to both modules, otherwise\n     * an error will be thrown.\n     *\n     * @see io.realm.annotations.RealmNamingPolicy for more information about what setting this policy means.\n     */\n    RealmNamingPolicy classNamingPolicy() default RealmNamingPolicy.NO_POLICY;\n\n    /**\n     * The naming policy applied to all field names in all classes part of this module. The default policy is\n     * {@link RealmNamingPolicy#NO_POLICY}. To define a naming policy for class names, use {@link #classNamingPolicy()}.\n     * <p>\n     * It is possible to override this naming policy using either {@link RealmClass#fieldNamingPolicy()} or\n     * {@link RealmField#name()}.\n     *\n     * @see io.realm.annotations.RealmNamingPolicy for more information about what setting this policy means.\n     */\n    RealmNamingPolicy fieldNamingPolicy() default RealmNamingPolicy.NO_POLICY;\n}\n"
  },
  {
    "path": "realm-annotations/src/main/java/io/realm/annotations/RealmNamingPolicy.java",
    "content": "package io.realm.annotations;\n\n/**\n * This enum defines the possible ways class and field names can be mapped from what is used in Java\n * to the name used internally in the Realm file.\n * <p>\n * Examples where this is useful:\n * <ul>\n *      <li>\n *          To support two model classes with the same simple name but in different packages.\n *      </li>\n *      <li>\n *          To make it easier to work with cross platform schemas as naming conventions are different.\n *      </li>\n *      <li>\n *          To use a Java class name that is longer than the 57 character limit enforced by Realm.\n *      </li>\n *      <li>\n *          To change a field name in Java without forcing app users through a migration process.\n *      </li>\n * </ul>\n *\n * Depending on where the policy is applied, it will have slightly different semantics:\n * <ul>\n *     <li>\n *         If applied to {@link RealmModule#classNamingPolicy} all classes part of that module\n *         will be affected. If a class is part of multiple modules, the same naming policy must be\n *         applied to both modules, otherwise an error will be thrown.\n *     </li>\n *     <li>\n *         If applied to {@link RealmModule#fieldNamingPolicy} all persistable fields in all classes\n *         part of this module will be affected.\n *     </li>\n *\n *      <li>\n *          If applied to {@link RealmClass#fieldNamingPolicy} all fields in that class will be\n *          affected. This will override any field naming policy specified on a module.\n *      </li>\n * </ul>\n * <p>\n * An example of this:\n * <pre>\n * {@code\n * \\@RealmClass(name = \"__person\", fieldNamingPolicy = RealmNamingPolicy.LOWER_CASE_WITH_UNDERSCORES)\n * public class Person implements RealmModel { // is converted to \"__person\" internally\n *     public string firstName; // Is converted to \"first_name\" internally\n * }\n * }\n * </pre>\n * <p>\n * Choosing an internal name that differs from the name used in the Java model classes has the\n * following implications:\n * <ul>\n *      <li>\n *          Queries on {@code DynamicRealm} must use the internal name. Queries on normal {@code Realm}\n *          instances must continue to use the name as it is defined in the Java class.\n *      </li>\n *      <li>\n *          Migrations must use the internal name when creating classes and fields.\n *      </li>\n *      <li>\n *          Schema errors reported will use the internal names.\n *      </li>\n * </ul>\n * <p>\n * When automatically converting Java variable names, each variable name is normalized by splitting\n * it into a list of words that are then joined using the rules of the target format. The following\n * heuristics are used for determining what constitutes a \"word\".\n * <ol>\n *     <li>\n *         Anytime a {@code _} or {@code $} is encountered.\n *         Examples are \"_FirstName\", \"_First_Name\" and \"$First$Name\" which all becomes \"First\" and \"Name\".\n *     </li>\n *     <li>\n *         Anytime you switch from a lower case character to an upper case character as\n *         identified by {@link Character#isUpperCase(int)} and {@link Character#isLowerCase(int)}.\n *         Example is \"FirstName\" which becomes \"First\" and \"Name\".\n *     </li>\n *     <li>\n *         Anytime you switch from more than one uppercase character to a lower case one. The last\n *         upper case letter is assumed to be part of the next word. This is identified by using\n *         {@link Character#isUpperCase(int)} and {@link Character#isLowerCase(int)}.\n *         Example is \"FIRSTName\" which becomes \"FIRST\" and \"Name.\n *     </li>\n *     <li>\n *         Some characters like emojiis are neither uppercase nor lowercase characters, so they will\n *         be part of the current word.\n *         Examples are \"my😁\" and \"MY😁\" which are both treated as one word.\n *     </li>\n *     <li>\n *         Hungarian notation, i.e. variable names starting with lowercase \"m\" followed by uppercase\n *         letter is stripped and not considered part of any word.\n *         Example is \"mFirstName\" and \"mFIRSTName\" which becomes \"First\" and \"Name.\n *     </li>\n * </ol>\n * <p>\n * Note that changing the internal name does <i>NOT</i> affect importing data from JSON. The JSON\n * data must still follow the names as defined in the Realm Java class.\n * <p>\n * When it comes to parsing JSON using standard libraries like Moshi, GSON or Jackson it is\n * important to keep in mind that these libraries define the transformation from JSON to Java\n * while setting internal Realm names define the transformation from Java to the Realm file.\n * <p>\n * This means that if you want to import data into Realm from JSON using these libraries you still\n * need to provide the annotations from both the JSON parser library and Realm.\n * <p>\n * Using Moshi, it would look something like this:\n * <pre>\n * {@code\n * public class Person extends RealmObject {\n *     \\@Json(name = \"first_name\") // Name used in JSON input.\n *     \\@RealmField(name = \"first_name\") // Name used internally in the Realm file.\n *     public string firstName; // name used in Java\n * }\n * }\n * </pre>\n *\n * @see RealmModule\n * @see RealmClass\n * @see RealmField\n */\npublic enum RealmNamingPolicy {\n\n    /**\n     * No policy is applied. This policy will not override any policy set on a parent element, e.g.\n     * if set in {@link RealmClass#fieldNamingPolicy}, the module policy will still apply to field\n     * names.\n     * <p>\n     * If two modules disagree on the policy and one of them is {@code NO_POLICY}, the other will\n     * be chosen without an error being thrown.\n     * <p>\n     * This policy is the default.\n     */\n    NO_POLICY,\n\n    /**\n     * The name in the Java model class is used as is internally.\n     */\n    IDENTITY,\n\n    /**\n     * The name in the Java model class is converted to camelCase, i.e. all words are joined\n     * together with the first letter in the first word lower cased, and the first letter of\n     * all subsequent words upper cased. This is the standard naming schema in Java, Kotlin, Swift\n     * and JavaScript.\n     * <p>\n     * Examples: \"firstName\", \"FirstName\", \"mFirstName\", \"FIRST_NAME\", \"First$Name\" all becomes\n     * \"firstName\".\n     */\n    CAMEL_CASE,\n\n    /**\n     * The name in the Java model class is converted to PascalCase, i.e. all words are joined\n     * together with the first letter of all words upper cased. This is the default naming scheme\n     * in .NET.\n     * <p>\n     * Examples: \"firstName\", \"FirstName\", \"mFirstName\", \"FIRST_NAME\", \"First$Name\" all becomes\n     * \"FirstName\".\n     */\n    PASCAL_CASE,\n\n    /**\n     * The name in the Java model class is converted lowercase with each word separated by {@code _}.\n     * This is the default naming scheme in C++.\n     * <p>\n     * Examples: \"firstName\", \"FirstName\", \"mFirstName\", \"FIRST_NAME\", \"First$Name\" all becomes\n     * \"first_name\".\n     */\n    LOWER_CASE_WITH_UNDERSCORES\n}\n"
  },
  {
    "path": "realm-annotations/src/main/java/io/realm/annotations/Required.java",
    "content": "/*\n * Copyright 2015 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\npackage io.realm.annotations;\nimport java.lang.annotation.ElementType;\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.RetentionPolicy;\nimport java.lang.annotation.Target;\n\n/**\n * This annotation will mark the field or the element in {@code io.realm.RealmList} as not nullable.\n * <p>\n * When a field of type {@code Boolean, Byte, Short, Integer, Long, Float, Double, String, byte[], Date} is annotated\n * with {@link Required}, it cannot be set to {@code null} and Realm will throw an exception if it happens.\n * <p>\n * Fields with primitive types are implicitly required. Note, {@code String} is not a primitive type, so in Java\n * it is default nullable unless it is marked {@code \\@Required}. In Kotlin the reverse is true, so a {@code String} is\n * non-null. To specify a nullable String in Kotlin you should use {@code String?}.\n * <p>\n * If this annotation is used on a {@code RealmList}, the annotation is applied to the elements inside\n * the list and not the list itself. The list itself is always non-null. This means that a list marked with this\n * annotation are never allowed to hold {@code null} values even if the datatype would otherwise allow it.\n * Realm will throw an exception if you attempt to store null values into a list marked {@code \\@Required}.\n * <p>\n * This annotation cannot be used on a {@code RealmAny}, as the inner value of a RealmAny field is always nullable.\n * Realm will throw an exception if you attempt mark a {@code RealmAny} as {@code \\@Required}.\n * <p>\n * Compiling will fail if the {@link Required} annotation is put an a {@code RealmList} containing references to other\n * Realm objects.\n */\n@Retention(RetentionPolicy.RUNTIME)\n@Target(ElementType.FIELD)\npublic @interface Required {\n\n}\n"
  },
  {
    "path": "realm-transformer/build.gradle",
    "content": "buildscript {\n    def properties = new Properties()\n    properties.load(new FileInputStream(\"${projectDir}/../dependencies.list\"))\n    ext.kotlin_version = properties.get('KOTLIN')\n    repositories {\n        google()\n        jcenter()\n        maven {\n            url \"https://plugins.gradle.org/m2/\"\n        }\n    }\n    dependencies {\n        classpath \"io.github.gradle-nexus:publish-plugin:${properties.get(\"GRADLE_NEXUS_PLUGIN\")}\"\n        classpath \"org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version\"\n    }\n}\n\napply plugin: 'kotlin'\napply plugin: 'java'\napply plugin: 'maven-publish'\n\ngroup = 'io.realm'\nversion = file(\"${projectDir}/../version.txt\").text.trim()\n\ndef properties = new Properties()\nproperties.load(new FileInputStream(\"${projectDir}/../dependencies.list\"))\n\ndef coreVersion = properties.getProperty('REALM_CORE')\n\nsourceCompatibility = JavaVersion.VERSION_11\ntargetCompatibility = JavaVersion.VERSION_11\n\nrepositories {\n    mavenLocal()\n    google()\n    jcenter()\n}\n\nconfigurations {\n    provided\n    compile.extendsFrom provided\n}\n\n// Include the generated Version file\nsourceSets {\n    main {\n        compileClasspath += configurations.provided\n        java.srcDirs += ['build/generated-src/main/java', 'src/main/kotlin']\n    }\n}\n\ndependencies {\n    implementation gradleApi()\n    implementation \"io.realm:realm-annotations:${version}\"\n    compileOnly \"com.android.tools.build:gradle:${properties.get(\"GRADLE_BUILD_TOOLS\")}\"\n    implementation 'org.javassist:javassist:3.25.0-GA'\n    implementation \"org.jetbrains.kotlin:kotlin-stdlib-jdk8:${kotlin_version}\"\n    implementation \"com.google.guava:guava:31.0.1-jre\"\n    // JAX-B dependencies for JDK 9+ (this is not available in JVM env 'java.lang.NoClassDefFoundError: javax/xml/bind/DatatypeConverter'\n    // and it was removed in Java 11 https://stackoverflow.com/a/43574427\n    implementation(\"javax.xml.bind:jaxb-api:2.3.1\")\n\n    testImplementation 'junit:junit:4.12'\n}\n\n// for Ant filter\nimport org.apache.tools.ant.filters.ReplaceTokens\n\ntask generateVersionClass(type: Copy) {\n    from 'src/main/templates/Version.java'\n    into 'build/generated-src/main/java/io/realm/transformer'\n    filter(ReplaceTokens, tokens: [version: version, coreVersion: coreVersion])\n    outputs.upToDateWhen { false }\n}\n\ncompileKotlin.dependsOn generateVersionClass\n\napply from: \"${rootDir}/../mavencentral-publications.gradle\"\napply from: \"${rootDir}/../mavencentral-publish.gradle\"\n\npublishing {\n    publications {\n        realmPublication(MavenPublication) {\n            groupId 'io.realm'\n            artifactId = 'realm-transformer'\n            from components.java\n            populatePom(\n                    it,\n                    'realm-transformer',\n                    'Android Gradle Transformer for Realm. Realm is a mobile database: Build better apps, faster.'\n            )\n        }\n    }\n}\n\njava {\n    withSourcesJar()\n    withJavadocJar()\n    sourceCompatibility = JavaVersion.VERSION_11\n    targetCompatibility = JavaVersion.VERSION_11\n}\n\ncompileKotlin {\n    kotlinOptions {\n        jvmTarget = JavaVersion.VERSION_11\n        freeCompilerArgs = [\"-Xinline-classes\", \"-Xjvm-default=all-compatibility\"]\n    }\n}\n"
  },
  {
    "path": "realm-transformer/gradle/wrapper/gradle-wrapper.properties",
    "content": "distributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\ndistributionUrl=https\\://services.gradle.org/distributions/gradle-7.5-all.zip\nzipStoreBase=GRADLE_USER_HOME\nzipStorePath=wrapper/dists\n"
  },
  {
    "path": "realm-transformer/gradle.properties",
    "content": "org.gradle.caching=true"
  },
  {
    "path": "realm-transformer/gradlew",
    "content": "#!/bin/sh\n\n#\n# Copyright © 2015-2021 the original authors.\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#      https://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##############################################################################\n#\n#   Gradle start up script for POSIX generated by Gradle.\n#\n#   Important for running:\n#\n#   (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is\n#       noncompliant, but you have some other compliant shell such as ksh or\n#       bash, then to run this script, type that shell name before the whole\n#       command line, like:\n#\n#           ksh Gradle\n#\n#       Busybox and similar reduced shells will NOT work, because this script\n#       requires all of these POSIX shell features:\n#         * functions;\n#         * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,\n#           «${var#prefix}», «${var%suffix}», and «$( cmd )»;\n#         * compound commands having a testable exit status, especially «case»;\n#         * various built-in commands including «command», «set», and «ulimit».\n#\n#   Important for patching:\n#\n#   (2) This script targets any POSIX shell, so it avoids extensions provided\n#       by Bash, Ksh, etc; in particular arrays are avoided.\n#\n#       The \"traditional\" practice of packing multiple parameters into a\n#       space-separated string is a well documented source of bugs and security\n#       problems, so this is (mostly) avoided, by progressively accumulating\n#       options in \"$@\", and eventually passing that to Java.\n#\n#       Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,\n#       and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;\n#       see the in-line comments for details.\n#\n#       There are tweaks for specific operating systems such as AIX, CygWin,\n#       Darwin, MinGW, and NonStop.\n#\n#   (3) This script is generated from the Groovy template\n#       https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt\n#       within the Gradle project.\n#\n#       You can find Gradle at https://github.com/gradle/gradle/.\n#\n##############################################################################\n\n# Attempt to set APP_HOME\n\n# Resolve links: $0 may be a link\napp_path=$0\n\n# Need this for daisy-chained symlinks.\nwhile\n    APP_HOME=${app_path%\"${app_path##*/}\"}  # leaves a trailing /; empty if no leading path\n    [ -h \"$app_path\" ]\ndo\n    ls=$( ls -ld \"$app_path\" )\n    link=${ls#*' -> '}\n    case $link in             #(\n      /*)   app_path=$link ;; #(\n      *)    app_path=$APP_HOME$link ;;\n    esac\ndone\n\nAPP_HOME=$( cd \"${APP_HOME:-./}\" && pwd -P ) || exit\n\nAPP_NAME=\"Gradle\"\nAPP_BASE_NAME=${0##*/}\n\n# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\nDEFAULT_JVM_OPTS='\"-Xmx64m\" \"-Xms64m\"'\n\n# Use the maximum available, or set MAX_FD != -1 to use that value.\nMAX_FD=maximum\n\nwarn () {\n    echo \"$*\"\n} >&2\n\ndie () {\n    echo\n    echo \"$*\"\n    echo\n    exit 1\n} >&2\n\n# OS specific support (must be 'true' or 'false').\ncygwin=false\nmsys=false\ndarwin=false\nnonstop=false\ncase \"$( uname )\" in                #(\n  CYGWIN* )         cygwin=true  ;; #(\n  Darwin* )         darwin=true  ;; #(\n  MSYS* | MINGW* )  msys=true    ;; #(\n  NONSTOP* )        nonstop=true ;;\nesac\n\nCLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar\n\n\n# Determine the Java command to use to start the JVM.\nif [ -n \"$JAVA_HOME\" ] ; then\n    if [ -x \"$JAVA_HOME/jre/sh/java\" ] ; then\n        # IBM's JDK on AIX uses strange locations for the executables\n        JAVACMD=$JAVA_HOME/jre/sh/java\n    else\n        JAVACMD=$JAVA_HOME/bin/java\n    fi\n    if [ ! -x \"$JAVACMD\" ] ; then\n        die \"ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME\n\nPlease set the JAVA_HOME variable in your environment to match the\nlocation of your Java installation.\"\n    fi\nelse\n    JAVACMD=java\n    which java >/dev/null 2>&1 || die \"ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.\n\nPlease set the JAVA_HOME variable in your environment to match the\nlocation of your Java installation.\"\nfi\n\n# Increase the maximum file descriptors if we can.\nif ! \"$cygwin\" && ! \"$darwin\" && ! \"$nonstop\" ; then\n    case $MAX_FD in #(\n      max*)\n        MAX_FD=$( ulimit -H -n ) ||\n            warn \"Could not query maximum file descriptor limit\"\n    esac\n    case $MAX_FD in  #(\n      '' | soft) :;; #(\n      *)\n        ulimit -n \"$MAX_FD\" ||\n            warn \"Could not set maximum file descriptor limit to $MAX_FD\"\n    esac\nfi\n\n# Collect all arguments for the java command, stacking in reverse order:\n#   * args from the command line\n#   * the main class name\n#   * -classpath\n#   * -D...appname settings\n#   * --module-path (only if needed)\n#   * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.\n\n# For Cygwin or MSYS, switch paths to Windows format before running java\nif \"$cygwin\" || \"$msys\" ; then\n    APP_HOME=$( cygpath --path --mixed \"$APP_HOME\" )\n    CLASSPATH=$( cygpath --path --mixed \"$CLASSPATH\" )\n\n    JAVACMD=$( cygpath --unix \"$JAVACMD\" )\n\n    # Now convert the arguments - kludge to limit ourselves to /bin/sh\n    for arg do\n        if\n            case $arg in                                #(\n              -*)   false ;;                            # don't mess with options #(\n              /?*)  t=${arg#/} t=/${t%%/*}              # looks like a POSIX filepath\n                    [ -e \"$t\" ] ;;                      #(\n              *)    false ;;\n            esac\n        then\n            arg=$( cygpath --path --ignore --mixed \"$arg\" )\n        fi\n        # Roll the args list around exactly as many times as the number of\n        # args, so each arg winds up back in the position where it started, but\n        # possibly modified.\n        #\n        # NB: a `for` loop captures its iteration list before it begins, so\n        # changing the positional parameters here affects neither the number of\n        # iterations, nor the values presented in `arg`.\n        shift                   # remove old arg\n        set -- \"$@\" \"$arg\"      # push replacement arg\n    done\nfi\n\n# Collect all arguments for the java command;\n#   * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of\n#     shell script including quotes and variable substitutions, so put them in\n#     double quotes to make sure that they get re-expanded; and\n#   * put everything else in single quotes, so that it's not re-expanded.\n\nset -- \\\n        \"-Dorg.gradle.appname=$APP_BASE_NAME\" \\\n        -classpath \"$CLASSPATH\" \\\n        org.gradle.wrapper.GradleWrapperMain \\\n        \"$@\"\n\n# Stop when \"xargs\" is not available.\nif ! command -v xargs >/dev/null 2>&1\nthen\n    die \"xargs is not available\"\nfi\n\n# Use \"xargs\" to parse quoted args.\n#\n# With -n1 it outputs one arg per line, with the quotes and backslashes removed.\n#\n# In Bash we could simply go:\n#\n#   readarray ARGS < <( xargs -n1 <<<\"$var\" ) &&\n#   set -- \"${ARGS[@]}\" \"$@\"\n#\n# but POSIX shell has neither arrays nor command substitution, so instead we\n# post-process each arg (as a line of input to sed) to backslash-escape any\n# character that might be a shell metacharacter, then use eval to reverse\n# that process (while maintaining the separation between arguments), and wrap\n# the whole thing up as a single \"set\" statement.\n#\n# This will of course break if any of these variables contains a newline or\n# an unmatched quote.\n#\n\neval \"set -- $(\n        printf '%s\\n' \"$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS\" |\n        xargs -n1 |\n        sed ' s~[^-[:alnum:]+,./:=@_]~\\\\&~g; ' |\n        tr '\\n' ' '\n    )\" '\"$@\"'\n\nexec \"$JAVACMD\" \"$@\"\n"
  },
  {
    "path": "realm-transformer/gradlew.bat",
    "content": "@rem\r\n@rem Copyright 2015 the original author or authors.\r\n@rem\r\n@rem Licensed under the Apache License, Version 2.0 (the \"License\");\r\n@rem you may not use this file except in compliance with the License.\r\n@rem You may obtain a copy of the License at\r\n@rem\r\n@rem      https://www.apache.org/licenses/LICENSE-2.0\r\n@rem\r\n@rem Unless required by applicable law or agreed to in writing, software\r\n@rem distributed under the License is distributed on an \"AS IS\" BASIS,\r\n@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n@rem See the License for the specific language governing permissions and\r\n@rem limitations under the License.\r\n@rem\r\n\r\n@if \"%DEBUG%\"==\"\" @echo off\r\n@rem ##########################################################################\r\n@rem\r\n@rem  Gradle startup script for Windows\r\n@rem\r\n@rem ##########################################################################\r\n\r\n@rem Set local scope for the variables with windows NT shell\r\nif \"%OS%\"==\"Windows_NT\" setlocal\r\n\r\nset DIRNAME=%~dp0\r\nif \"%DIRNAME%\"==\"\" set DIRNAME=.\r\nset APP_BASE_NAME=%~n0\r\nset APP_HOME=%DIRNAME%\r\n\r\n@rem Resolve any \".\" and \"..\" in APP_HOME to make it shorter.\r\nfor %%i in (\"%APP_HOME%\") do set APP_HOME=%%~fi\r\n\r\n@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\r\nset DEFAULT_JVM_OPTS=\"-Xmx64m\" \"-Xms64m\"\r\n\r\n@rem Find java.exe\r\nif defined JAVA_HOME goto findJavaFromJavaHome\r\n\r\nset JAVA_EXE=java.exe\r\n%JAVA_EXE% -version >NUL 2>&1\r\nif %ERRORLEVEL% equ 0 goto execute\r\n\r\necho.\r\necho ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.\r\necho.\r\necho Please set the JAVA_HOME variable in your environment to match the\r\necho location of your Java installation.\r\n\r\ngoto fail\r\n\r\n:findJavaFromJavaHome\r\nset JAVA_HOME=%JAVA_HOME:\"=%\r\nset JAVA_EXE=%JAVA_HOME%/bin/java.exe\r\n\r\nif exist \"%JAVA_EXE%\" goto execute\r\n\r\necho.\r\necho ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%\r\necho.\r\necho Please set the JAVA_HOME variable in your environment to match the\r\necho location of your Java installation.\r\n\r\ngoto fail\r\n\r\n:execute\r\n@rem Setup the command line\r\n\r\nset CLASSPATH=%APP_HOME%\\gradle\\wrapper\\gradle-wrapper.jar\r\n\r\n\r\n@rem Execute Gradle\r\n\"%JAVA_EXE%\" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% \"-Dorg.gradle.appname=%APP_BASE_NAME%\" -classpath \"%CLASSPATH%\" org.gradle.wrapper.GradleWrapperMain %*\r\n\r\n:end\r\n@rem End local scope for the variables with windows NT shell\r\nif %ERRORLEVEL% equ 0 goto mainEnd\r\n\r\n:fail\r\nrem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of\r\nrem the _cmd.exe /c_ return code!\r\nset EXIT_CODE=%ERRORLEVEL%\r\nif %EXIT_CODE% equ 0 set EXIT_CODE=1\r\nif not \"\"==\"%GRADLE_EXIT_CONSOLE%\" exit %EXIT_CODE%\r\nexit /b %EXIT_CODE%\r\n\r\n:mainEnd\r\nif \"%OS%\"==\"Windows_NT\" endlocal\r\n\r\n:omega\r\n"
  },
  {
    "path": "realm-transformer/settings.gradle",
    "content": "rootProject.name = 'realm-transformer'\n"
  },
  {
    "path": "realm-transformer/src/main/java/io/realm/gradle/RealmPluginExtension.java",
    "content": "/*\n * Copyright 2018 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\npackage io.realm.gradle;\n\nimport org.gradle.api.tasks.Input;\n\nimport java.util.LinkedHashMap;\nimport java.util.Map;\n\npublic class RealmPluginExtension {\n    private boolean syncEnabled;\n    private boolean kotlinExtensionsEnabled;\n\n    @Input\n    public boolean isSyncEnabled() {\n        return syncEnabled;\n    }\n\n    public void setSyncEnabled(boolean syncEnabled) {\n        this.syncEnabled = syncEnabled;\n    }\n\n    @Input\n    public boolean isKotlinExtensionsEnabled() {\n        return kotlinExtensionsEnabled;\n    }\n\n    public void setKotlinExtensionsEnabled(boolean kotlinExtensionsEnabled) {\n        this.kotlinExtensionsEnabled = kotlinExtensionsEnabled;\n    }\n}\n"
  },
  {
    "path": "realm-transformer/src/main/java/io/realm/transformer/Utils.java",
    "content": "/*\n * Copyright 2016 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\npackage io.realm.transformer;\n\nimport io.realm.gradle.RealmPluginExtension;\nimport java.io.UnsupportedEncodingException;\nimport java.security.MessageDigest;\nimport java.security.NoSuchAlgorithmException;\nimport javax.xml.bind.DatatypeConverter;\nimport org.gradle.api.Project;\n\npublic class Utils {\n\n    /**\n     * Encode the given string with Base64\n     * @param data the string to encode\n     * @return the encoded string\n     * @throws UnsupportedEncodingException if string is not valid utf8\n     */\n    public static String base64Encode(String data) throws UnsupportedEncodingException {\n        return DatatypeConverter.printBase64Binary(data.getBytes(\"UTF-8\"));\n    }\n\n    /**\n     * Compute the SHA-256 hash of the given byte array\n     * @param data the byte array to hash\n     * @return the hashed byte array\n     * @throws NoSuchAlgorithmException\n     */\n    public static byte[] sha256Hash(byte[] data) throws NoSuchAlgorithmException {\n        MessageDigest messageDigest = MessageDigest.getInstance(\"SHA-256\");\n        return messageDigest.digest(data);\n    }\n\n    /**\n     * Convert a byte array to its hex-string\n     * @param data the byte array to convert\n     * @return the hex-string of the byte array\n     */\n    public static String hexStringify(byte[] data) {\n        StringBuilder stringBuilder = new StringBuilder();\n        for (byte singleByte : data) {\n            stringBuilder.append(Integer.toString((singleByte & 0xff) + 0x100, 16).substring(1));\n        }\n\n        return stringBuilder.toString();\n    }\n\n    public static boolean isSyncEnabled(Project project) {\n        RealmPluginExtension realmExtension = (RealmPluginExtension) project.getExtensions().findByName(\"realm\");\n        return realmExtension != null && realmExtension.isSyncEnabled();\n    }\n\n}\n"
  },
  {
    "path": "realm-transformer/src/main/kotlin/io/realm/analytics/AnalyticsData.kt",
    "content": "/*\n * Copyright 2021 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 */\npackage io.realm.analytics\n\nimport io.realm.transformer.Utils\nimport io.realm.transformer.Version\nimport java.net.SocketException\nimport java.security.NoSuchAlgorithmException\n\n@JvmInline\nvalue class PublicAppId(val id: String) {\n    fun anonymize(): String {\n        val idBytes: ByteArray = id.toByteArray()\n        return Utils.hexStringify(Utils.sha256Hash(idBytes))\n    }\n}\n\n/**\n * Class wrapping data we want to send as analytics data.\n */\ndata class AnalyticsData(\n    val appId: PublicAppId,\n    val usesKotlin: Boolean,\n    val usesSync: Boolean,\n    val targetSdk: String,\n    val minSdk: String,\n    val target:String,\n    val gradleVersion: String,\n    val agpVersion: String\n) {\n\n    private val TOKEN = \"ce0fac19508f6c8f20066d345d360fd0\"\n    private val EVENT_NAME = \"Run\"\n    private val JSON_TEMPLATE = \"\"\"\n        {\n          \"event\": \"%EVENT%\",\n          \"properties\": {\n              \"token\": \"%TOKEN%\",\n              \"distinct_id\": \"%USER_ID%\",\n              \"Anonymized MAC Address\": \"%USER_ID%\",\n              \"Anonymized Bundle ID\": \"%APP_ID%\",\n              \"Binding\": \"java\",\n              \"Target\": \"%TARGET%\",\n              \"Language\": \"%LANGUAGE%\",\n              \"Sync Version\": %SYNC_VERSION%,\n              \"Realm Version\": \"%REALM_VERSION%\",\n              \"Host OS Type\": \"%OS_TYPE%\",\n              \"Host OS Version\": \"%OS_VERSION%\",\n              \"Target OS Type\": \"android\",\n              \"Target OS Version\": \"%TARGET_SDK%\",\n              \"Target OS Minimum Version\": \"%MIN_SDK%\",\n              \"Gradle version\": \"%GRADLE_VERSION%\",\n              \"Android Gradle Plugin Version\": \"%AGP_VERSION%\"\n          }\n        }\n    \"\"\".trimIndent()\n\n    @Throws(SocketException::class, NoSuchAlgorithmException::class)\n    fun generateJson(): String {\n        return JSON_TEMPLATE\n            .replace(\"%EVENT%\".toRegex(), EVENT_NAME)\n            .replace(\"%TOKEN%\".toRegex(), TOKEN)\n            .replace(\"%USER_ID%\".toRegex(), ComputerIdentifierGenerator.get())\n            .replace(\"%APP_ID%\".toRegex(), appId.anonymize())\n            .replace(\"%TARGET%\".toRegex(), target)\n            .replace(\"%LANGUAGE%\".toRegex(), if (usesKotlin) \"kotlin\" else \"java\")\n            .replace(\n                \"%SYNC_VERSION%\".toRegex(),\n                if (usesSync) \"\\\"\" + Version.SYNC_VERSION + \"\\\"\" else \"null\"\n            )\n            .replace(\"%REALM_VERSION%\".toRegex(), Version.VERSION)\n            .replace(\"%OS_TYPE%\".toRegex(), System.getProperty(\"os.name\"))\n            .replace(\"%OS_VERSION%\".toRegex(), System.getProperty(\"os.version\"))\n            .replace(\"%TARGET_SDK%\".toRegex(), targetSdk)\n            .replace(\"%MIN_SDK%\".toRegex(), minSdk)\n            .replace(\"%GRADLE_VERSION%\".toRegex(), gradleVersion)\n            .replace(\"%AGP_VERSION%\".toRegex(), agpVersion)\n    }\n}"
  },
  {
    "path": "realm-transformer/src/main/kotlin/io/realm/analytics/ComputerIdentifierGenerator.kt",
    "content": "/*\n * Copyright 2021 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 */\npackage io.realm.analytics\n\nimport io.realm.transformer.Utils\nimport java.io.File\nimport java.io.FileNotFoundException\nimport java.io.IOException\nimport java.net.NetworkInterface\nimport java.net.SocketException\nimport java.security.NoSuchAlgorithmException\nimport java.util.*\n\n/**\n * Generate a unique identifier for a computer. The method being used depends on the platform:\n * - OS X:  Mac address of en0\n * - Windows:  BIOS identifier\n * - Linux: Machine ID provided by the OS\n */\nclass ComputerIdentifierGenerator {\n    companion object {\n        private const val UNKNOWN = \"unknown\"\n        private val OS: String = System.getProperty(\"os.name\").lowercase(Locale.getDefault())\n        private val isWindows: Boolean = OS.contains(\"win\")\n        private val isMac: Boolean = OS.contains(\"mac\")\n        private val isLinux: Boolean = OS.contains(\"inux\")\n\n        fun get(): String {\n            return try {\n                when {\n                    isWindows -> getWindowsIdentifier()\n                    isMac -> getMacOsIdentifier()\n                    isLinux -> getLinuxMacAddress()\n                    else -> UNKNOWN\n                }\n            } catch (e: Exception) {\n                UNKNOWN\n            }\n        }\n\n        @Throws(FileNotFoundException::class, NoSuchAlgorithmException::class)\n        private fun  getLinuxMacAddress(): String {\n            var machineId = File(\"/var/lib/dbus/machine-id\")\n            if (!machineId.exists()) {\n                machineId = File(\"/etc/machine-id\")\n            }\n            if (!machineId.exists()) {\n                return UNKNOWN\n            }\n            var scanner: Scanner? = null\n            return try {\n                scanner = Scanner(machineId)\n                val id = scanner.useDelimiter(\"\\\\A\").next()\n                Utils.hexStringify(Utils.sha256Hash(id.toByteArray()))\n            } finally {\n                scanner?.close()\n            }\n        }\n\n        @Throws(SocketException::class, NoSuchAlgorithmException::class)\n        private fun getMacOsIdentifier(): String {\n            val networkInterface = NetworkInterface.getByName(\"en0\")\n            val hardwareAddress = networkInterface.hardwareAddress\n            return Utils.hexStringify(Utils.sha256Hash(hardwareAddress))\n        }\n\n        @Throws(IOException::class, NoSuchAlgorithmException::class)\n        private fun getWindowsIdentifier(): String {\n            val runtime = Runtime.getRuntime()\n            val process = runtime.exec(arrayOf(\"wmic\", \"csproduct\", \"get\", \"UUID\"))\n            var result: String? = null\n            val `is` = process.inputStream\n            val sc = Scanner(process.inputStream)\n            try {\n                while (sc.hasNext()) {\n                    val next = sc.next()\n                    if (next.contains(\"UUID\")) {\n                        result = sc.next().trim { it <= ' ' }\n                        break\n                    }\n                }\n            } finally {\n                `is`.close()\n            }\n            return if (result == null) UNKNOWN else Utils.hexStringify(Utils.sha256Hash(result.toByteArray()))\n        }\n    }\n}"
  },
  {
    "path": "realm-transformer/src/main/kotlin/io/realm/analytics/RealmAnalytics.kt",
    "content": "/*\n * Copyright 2021 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 */\npackage io.realm.analytics\n\nimport io.realm.transformer.ProjectMetaData\nimport io.realm.transformer.CONNECT_TIMEOUT\nimport io.realm.transformer.READ_TIMEOUT\nimport org.slf4j.Logger\nimport org.slf4j.LoggerFactory\nimport java.util.concurrent.Executors\nimport java.util.concurrent.TimeUnit\n\n// Package level logger\nval logger: Logger = LoggerFactory.getLogger(\"realm-logger\")\n\n/**\n * Asynchronously submits build information to Realm as part of running\n * the Gradle build.\n *\n * To be clear: this does *not* run when your app is in production or on\n * your end-user's devices; it will only run when you build your app from source.\n *\n * Why are we doing this? Because it helps us build a better product for you.\n * None of the data personally identifies you, your employer or your app, but it\n *  *will* help us understand what Realm version you use, what host OS you use,\n * etc. Having this info will help with prioritizing our time, adding new\n * features and deprecating old features. Collecting an anonymized bundle &\n * anonymized MAC is the only way for us to count actual usage of the other\n * metrics accurately. If we don't have a way to deduplicate the info reported,\n * it will be useless, as a single developer building their app on Windows ten\n * times would report 10 times more than a single developer that only builds\n * once from Mac OS X, making the data all but useless. No one likes sharing\n * data unless it's necessary, we get it, and we've debated adding this for a\n * long long time. Since Realm is a free product without an email signup, we\n * feel this is a necessary step so we can collect relevant data to build a\n * better product for you.\n *\n * Currently the following information is reported:\n * - What version of Realm is being used\n * - What OS you are running on\n * - An anonymized MAC address and bundle ID to aggregate the other information on.\n *\n */\nclass RealmAnalytics {\n\n    private var data: AnalyticsData? = null\n\n    /**\n     * Sends the analytics.\n     *\n     * @param inputs the inputs provided by the Transform API\n     * @param inputModelClasses a list of ctClasses describing the Realm models\n     */\n    public fun execute() {\n        try {\n            // If there is no data, analytics was disabled, so exit early.\n            val analyticsData: AnalyticsData = data ?: return\n\n            val pool = Executors.newFixedThreadPool(1);\n            try {\n                pool.execute { UrlEncodedAnalytics.create().execute(analyticsData) }\n                pool.awaitTermination(CONNECT_TIMEOUT + READ_TIMEOUT, TimeUnit.MILLISECONDS);\n            } catch (e: InterruptedException) {\n                pool.shutdownNow()\n            }\n        } catch (e: Exception) {\n            // Analytics failing for any reason should not crash the build\n            logger.debug(\"Error happened when sending Realm analytics data: $e\")\n        }\n    }\n\n    fun calculateAnalyticsData(metadata: ProjectMetaData): Boolean {\n        if (!isAnalyticsEnabled(metadata.isGradleOffline))  {\n            return false\n        }\n\n        data = AnalyticsData(\n            appId = PublicAppId(metadata.appId),\n            usesKotlin = metadata.usesKotlin,\n            usesSync = metadata.usesSync,\n            targetSdk = metadata.targetSdk,\n            minSdk = metadata.minSdk,\n            target = metadata.targetType,\n            gradleVersion = metadata.gradleVersion,\n            agpVersion = metadata.agpVersion\n        )\n        return true\n    }\n\n    private fun isAnalyticsEnabled(isOffline: Boolean): Boolean {\n        val env = System.getenv()\n        return !isOffline\n                && env[\"REALM_DISABLE_ANALYTICS\"] == null\n                && env[\"CI\"] == null\n    }\n}"
  },
  {
    "path": "realm-transformer/src/main/kotlin/io/realm/analytics/UrlEncodedAnalytics.kt",
    "content": "/*\n * Copyright 2021 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 */\npackage io.realm.analytics\n\nimport io.realm.transformer.Utils\nimport java.io.UnsupportedEncodingException\nimport java.net.HttpURLConnection\nimport java.net.MalformedURLException\nimport java.net.SocketException\nimport java.net.URL\nimport java.security.NoSuchAlgorithmException\n\nclass UrlEncodedAnalytics private constructor(private val prefix: String, private val suffix: String) {\n\n    /**\n     * Send the analytics event to the server.\n     */\n    fun execute(analytics: AnalyticsData) {\n        try {\n            val url = getUrl(analytics)\n            val connection = url.openConnection() as HttpURLConnection\n            connection.requestMethod = \"GET\"\n            connection.connect()\n            connection.responseCode\n        } catch (ignored: Exception) {\n        }\n    }\n\n    @Throws(\n        MalformedURLException::class,\n        SocketException::class,\n        NoSuchAlgorithmException::class,\n        UnsupportedEncodingException::class\n    )\n    private fun getUrl(analytics: AnalyticsData): URL {\n        return URL(prefix + Utils.base64Encode(analytics.generateJson()) + suffix)\n    }\n\n    companion object {\n        fun create(): UrlEncodedAnalytics {\n            val ADDRESS_PREFIX =\n                \"https://data.mongodb-api.com/app/realmsdkmetrics-zmhtm/endpoint/metric_webhook/metric?data=\"\n            val ADDRESS_SUFFIX = \"\"\n            return UrlEncodedAnalytics(ADDRESS_PREFIX, ADDRESS_SUFFIX)\n        }\n    }\n}\n"
  },
  {
    "path": "realm-transformer/src/main/kotlin/io/realm/transformer/ByteCodeModifier.kt",
    "content": "/*\n * Copyright 2018 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\npackage io.realm.transformer\n\nimport io.realm.annotations.Ignore\nimport io.realm.annotations.RealmClass\nimport io.realm.transformer.ext.hasRealmClassAnnotation\nimport io.realm.transformer.ext.safeSubtypeOf\nimport javassist.*\nimport javassist.expr.ExprEditor\nimport javassist.expr.FieldAccess\n\n/**\n * This class encapsulates the bytecode manipulation code needed to transform model classes\n * and the classes using them.\n */\nclass BytecodeModifier {\n\n    companion object {\n        fun CtField.isModelField(): Boolean =\n            !hasAnnotation(Ignore::class.java) &&\n                    !Modifier.isTransient(modifiers) &&\n                    !Modifier.isStatic(modifiers)\n\n        /**\n         * Adds Realm specific accessors to a model class.\n         * All the declared fields will be associated with a getter and a setter.\n         *\n         * @param clazz the CtClass to add accessors to.\n         */\n        @JvmStatic\n        fun addRealmAccessors(clazz: CtClass) {\n            val methods: List<String> = clazz.declaredMethods.map { it.name }\n            clazz.declaredFields\n                .filter { it.isModelField() }\n                .forEach { field: CtField ->\n                    if (!methods.contains(\"realmGet\\$${field.name}\")) {\n                        clazz.addMethod(CtNewMethod.getter(\"realmGet\\$${field.name}\", field))\n                    }\n                    if (!methods.contains(\"realmSet\\$${field.name}\")) {\n                        clazz.addMethod(CtNewMethod.setter(\"realmSet\\$${field.name}\", field))\n                    }\n            }\n        }\n\n        /**\n         * Modifies a class replacing field accesses with the appropriate Realm accessors.\n         *\n         * @param clazz The CtClass to modify\n         * @param managedFields List of fields whose access should be replaced\n         */\n        @JvmStatic\n        fun useRealmAccessors(\n            classPool: ClassPool,\n            clazz: CtClass,\n            managedFields: List<CtField>? = null\n        ) {\n            val methodBehaviours = clazz.declaredBehaviors\n                .filterIsInstance<CtMethod>()\n                .filterNot { it.name.startsWith(\"realmGet$\") }\n                .filterNot { it.name.startsWith(\"realmSet$\") }\n\n            val constructorBehaviours = clazz.declaredBehaviors\n                .filterIsInstance<CtConstructor>()\n\n            (methodBehaviours + constructorBehaviours)\n                .forEach { behavior ->\n                    logger.debug(\"    Behavior: ${behavior.name}\")\n                    if (managedFields != null) {\n                        behavior.instrument(\n                            FieldAccessToAccessorConverterUsingList(\n                                managedFields = managedFields,\n                                ctClass = clazz,\n                                behaviour = behavior\n                            )\n                        )\n                    } else {\n                        behavior.instrument(\n                            FieldAccessToAccessorConverterUsingClassPool(\n                                classPool = classPool,\n                                ctClass = clazz,\n                                behaviour = behavior\n                            )\n                        )\n                    }\n                }\n        }\n\n        /**\n         * Modifies a class adding its RealmProxy interface.\n         *\n         * @param clazz The CtClass to modify\n         * @param classPool the Javassist class pool\n         */\n        @JvmStatic\n        fun addRealmProxyInterface(clazz: CtClass, classPool: ClassPool) {\n            val proxyInterface: CtClass = classPool.get(\"io.realm.${clazz.getName().replace(\".\", \"_\")}RealmProxyInterface\")\n            clazz.addInterface(proxyInterface)\n        }\n\n        fun callInjectObjectContextFromConstructors(clazz: CtClass) {\n            clazz.constructors.forEach {\n                it.insertBeforeBody(\"if ($0 instanceof io.realm.internal.RealmObjectProxy) {\" +\n                        \" ((io.realm.internal.RealmObjectProxy) $0).realm\\$injectObjectContext();\" +\n                        \" }\")\n            }\n        }\n\n\n        /**\n         * Adds a method to indicate that Realm transformer has been applied.\n         *\n         * @param clazz The CtClass to modify.\n         */\n        fun overrideTransformedMarker(clazz: CtClass) {\n            logger.debug(\"  Realm: Marking as transformed ${clazz.simpleName}\")\n            try {\n                clazz.getDeclaredMethod(\"transformerApplied\")\n            } catch (ignored: NotFoundException) {\n                clazz.addMethod(CtNewMethod.make(Modifier.PUBLIC, CtClass.booleanType, \"transformerApplied\",\n                        arrayOf(), arrayOf(), \"{return true;}\", clazz))\n            }\n        }\n\n    }\n\n    /**\n     * This class goes through all the field access behaviours of a class and replaces field accesses with\n     * the appropriate accessor.\n     */\n    private class FieldAccessToAccessorConverterUsingList(val managedFields: List<CtField>,\n                                                          val ctClass: CtClass,\n                                                          val behaviour: CtBehavior) : ExprEditor() {\n\n        @Throws(CannotCompileException::class)\n        override fun edit(fieldAccess: FieldAccess) {\n            logger.debug(\"      Field being accessed: ${fieldAccess.className}.${fieldAccess.fieldName}\")\n            managedFields.find {\n                fieldAccess.className.equals(it.declaringClass.name) && fieldAccess.fieldName.equals(it.name)\n            }?.run {\n                logger.debug(\"        Realm: Manipulating ${ctClass.simpleName}.${behaviour.name}(): ${fieldAccess.fieldName}\")\n                logger.debug(\"        Methods: ${ctClass.declaredMethods}\")\n                val fieldName: String = fieldAccess.fieldName\n                if (fieldAccess.isReader) {\n                    fieldAccess.replace(\"\\$_ = $0.realmGet\\$$fieldName();\")\n                } else if (fieldAccess.isWriter) {\n                    fieldAccess.replace(\"\\$0.realmSet\\$$fieldName(\\$1);\")\n                }\n            }\n        }\n    }\n\n    /**\n     * This class goes through all the field access behaviours of a class and replaces field accesses with\n     * the appropriate accessor.\n     */\n    private class FieldAccessToAccessorConverterUsingClassPool(val classPool: ClassPool,\n                                                               val ctClass: CtClass,\n                                                               val behaviour: CtBehavior) : ExprEditor() {\n\n        val realmObjectProxyInterface: CtClass = classPool.get(\"io.realm.internal.RealmObjectProxy\")\n\n        private fun FieldAccess.classOrNull(): CtClass? = try { classPool.get(className) } catch (e: NotFoundException) { null }\n\n        @Throws(CannotCompileException::class)\n        override fun edit(fieldAccess: FieldAccess) {\n            logger.debug(\"      Field being accessed: ${fieldAccess.className}.${fieldAccess.fieldName}\")\n\n            fieldAccess.classOrNull()?.let { fieldAccessCtClass ->\n                if (fieldAccessCtClass.isRealmModelClass() && fieldAccess.field.isModelField()) {\n                    logger.debug(\"        Realm: Manipulating ${ctClass.simpleName}.${behaviour.name}(): ${fieldAccess.fieldName}\")\n                    logger.debug(\"        Methods: ${ctClass.declaredMethods}\")\n\n                    // make sure accessors are added, otherwise javassist will fail with\n                    // javassist.CannotCompileException: [source error] realmGet$id() not found in 'foo.Model'\n                    addRealmAccessors(fieldAccessCtClass)\n\n                    val fieldName: String = fieldAccess.fieldName\n                    if (fieldAccess.isReader) {\n                        fieldAccess.replace(\"\\$_ = \\$0.realmGet\\$$fieldName();\")\n                    } else if (fieldAccess.isWriter) {\n                        fieldAccess.replace(\"\\$0.realmSet\\$$fieldName(\\$1);\")\n                    }\n                }\n            }\n        }\n\n        fun CtClass.isRealmModelClass(): Boolean =\n            name != \"io.realm.RealmObject\" &&\n                    (hasAnnotation(RealmClass::class.java) || hasRealmClassAnnotation(superclass)) &&\n                    !safeSubtypeOf(realmObjectProxyInterface)\n    }\n}\n"
  },
  {
    "path": "realm-transformer/src/main/kotlin/io/realm/transformer/ManagedClassPool.kt",
    "content": "/*\n * Copyright 2018 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\npackage io.realm.transformer\n\nimport javassist.ClassPath\nimport javassist.ClassPool\nimport org.gradle.api.file.ConfigurableFileCollection\nimport org.gradle.api.file.Directory\nimport java.io.Closeable\nimport java.io.File\n\n/**\n * This class is a wrapper around JavaAssists {@code ClassPool} class that allows for correct cleanup\n * of the resources used.\n */\nclass ManagedClassPool(inputs: ConfigurableFileCollection, referencedInputs: ConfigurableFileCollection) : ClassPool(), Closeable {\n\n    private val pathElements: ArrayList<ClassPath> = arrayListOf()\n\n    /**\n     * Constructor for creating and populating the JavAssist class pool.\n     * Remember to call {@link #close()} when done with it to avoid leaking file resources\n     *\n     * @param inputs the inputs provided by the Transform API\n     * @param referencedInputs the referencedInputs provided by the Transform API\n     * @return the populated ClassPool instance\n     */\n    init {\n        // Don't use ClassPool.getDefault(). Doing consecutive builds in the same run (e.g. debug+release)\n        // will use a cached object and all the classes will be frozen.\n        appendSystemPath()\n\n        inputs.forEach{ directory: File ->\n            directory.walk().filter(File::isDirectory).forEach {\n                pathElements.add(appendClassPath(it.absolutePath))\n            }\n        }\n\n        referencedInputs.forEach {\n            pathElements.add(appendClassPath(it.absolutePath))\n        }\n    }\n\n    /**\n     * Detach all ClassPath elements, effectively closing the class pool.\n     */\n    override fun close() {\n        // Cleanup class pool. Internally it keeps a list of JarFile references that are only\n        // cleaned up if the the ClassPath element wrapping it is manually removed.\n        // See https://github.com/jboss-javassist/javassist/issues/165\n        val iter: MutableIterator<ClassPath> = pathElements.iterator()\n        while (iter.hasNext()) {\n            val cp = iter.next()\n            removeClassPath(cp)\n            iter.remove()\n        }\n    }\n\n}\n"
  },
  {
    "path": "realm-transformer/src/main/kotlin/io/realm/transformer/RealmTransformer.kt",
    "content": "/*\n * Copyright 2018 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\npackage io.realm.transformer\n\nimport com.android.build.api.variant.AndroidComponentsExtension\nimport com.android.build.api.variant.UnitTest\nimport com.android.build.gradle.internal.publishing.AndroidArtifacts\nimport io.realm.analytics.RealmAnalytics\nimport io.realm.transformer.build.BuildTemplate\nimport io.realm.transformer.build.FullBuild\nimport io.realm.transformer.build.IncrementalBuild\nimport io.realm.transformer.ext.areIncrementalBuildsDisabled\nimport io.realm.transformer.ext.getAgpVersion\nimport io.realm.transformer.ext.getAppId\nimport io.realm.transformer.ext.getBootClasspath\nimport io.realm.transformer.ext.getMinSdk\nimport io.realm.transformer.ext.getTargetSdk\nimport io.realm.transformer.ext.targetType\nimport io.realm.transformer.ext.usesKotlin\nimport org.gradle.api.DefaultTask\nimport org.gradle.api.Project\nimport org.gradle.api.file.ConfigurableFileCollection\nimport org.gradle.api.file.Directory\nimport org.gradle.api.file.RegularFile\nimport org.gradle.api.file.RegularFileProperty\nimport org.gradle.api.model.ObjectFactory\nimport org.gradle.api.provider.ListProperty\nimport org.gradle.api.provider.Property\nimport org.gradle.api.tasks.Classpath\nimport org.gradle.api.tasks.Input\nimport org.gradle.api.tasks.InputFiles\nimport org.gradle.api.tasks.Internal\nimport org.gradle.api.tasks.OutputFiles\nimport org.gradle.api.tasks.PathSensitive\nimport org.gradle.api.tasks.PathSensitivity\nimport org.gradle.api.tasks.TaskAction\nimport org.gradle.work.FileChange\nimport org.gradle.work.Incremental\nimport org.gradle.work.InputChanges\nimport org.slf4j.Logger\nimport org.slf4j.LoggerFactory\nimport java.io.BufferedOutputStream\nimport java.io.File\nimport java.io.FileOutputStream\nimport java.nio.file.FileSystem\nimport java.nio.file.FileSystems\nimport java.util.jar.JarOutputStream\nimport javax.inject.Inject\n\n// Package level logger\nval logger: Logger = LoggerFactory.getLogger(\"realm-logger\")\n\nconst val CONNECT_TIMEOUT = 4000L;\nconst val READ_TIMEOUT = 2000L;\n\n// Wrapper for storing data from org.gradle.api.Project as we cannot store a class variable to it\n// as that conflict with the Configuration Cache.\ndata class ProjectMetaData(\n    val bootClassPath: Set<File>,\n    val usesKotlin: Boolean,\n    val targetType: String,\n    val targetSdk: String,\n    val minSdk: String,\n    val agpVersion: String,\n    val appId: String,\n    val gradleVersion: String,\n    val usesSync: Boolean,\n    val isGradleOffline: Boolean\n)\n\n@Suppress(\"UnstableApiUsage\")\nfun registerRealmTransformerTask(project: Project) {\n    val androidComponents =\n        project.extensions.getByType(AndroidComponentsExtension::class.java)\n    androidComponents.onVariants { variant ->\n        variant.components\n            .filterNot {\n                // FIXME With the new transformer API changes, processed classes from the Realm transformer aren't\n                // resolved correctly by the Unit tests gradle task causing the test runner not to execute tests.\n\n                // This line disables the transformer on Unit test tasks. It is safe because Unit tests run\n                // on JVM and Realm Java is not compatible with JVM.\n                it is UnitTest\n            }\n            .forEach { component ->\n                val taskProvider =\n                    project.tasks.register(\n                        \"${component.name}RealmAccessorsTransformer\",\n                        RealmTransformerTask::class.java\n                    ) { task ->\n                        task.apply {\n                            referencedInputs.setFrom(component.runtimeConfiguration.incoming.artifactView { c ->\n                                c.attributes.attribute(\n                                    AndroidArtifacts.ARTIFACT_TYPE,\n                                    AndroidArtifacts.ArtifactType.CLASSES_JAR.type\n                                )\n                            }.files)\n                            bootClasspath.setFrom(project.getBootClasspath())\n                            offline.set(project.gradle.startParameter.isOffline)\n                            targetType.set(project.targetType())\n                            usesKotlin.set(project.usesKotlin())\n                            minSdk.set(project.getMinSdk())\n                            targetSdk.set(project.getTargetSdk())\n                            agpVersion.set(project.getAgpVersion())\n                            usesSync.set(Utils.isSyncEnabled(project))\n                            gradleVersion.set(project.gradle.gradleVersion)\n                            appId.set(project.getAppId())\n                            areIncrementalBuildsDisabled.set(project.areIncrementalBuildsDisabled())\n                        }\n                    }\n                component.artifacts.forScope(com.android.build.api.variant.ScopedArtifacts.Scope.PROJECT)\n                    .use<RealmTransformerTask>(taskProvider)\n                    .toTransform(\n                        com.android.build.api.artifact.ScopedArtifact.CLASSES,\n                        RealmTransformerTask::inputJars,\n                        RealmTransformerTask::inputDirectoriesInternal,\n                        RealmTransformerTask::output\n                    )\n            }\n    }\n}\n\n/**\n * This class implements the Transform API provided by the Android Gradle plugin.\n */\nabstract class RealmTransformerTask : DefaultTask() {\n    @get:Inject\n    abstract val objectFactory: ObjectFactory\n\n    @get:Classpath\n    abstract val referencedInputs: ConfigurableFileCollection\n\n    @get:InputFiles\n    abstract val inputJars: ListProperty<RegularFile>\n\n    @get:Incremental\n    @get:PathSensitive(PathSensitivity.RELATIVE)\n    @get:InputFiles\n    val inputDirectories: ConfigurableFileCollection = objectFactory.fileCollection().from(inputDirectoriesInternal)\n\n    @get:Internal\n    abstract val inputDirectoriesInternal: ListProperty<Directory>\n\n    @get:InputFiles\n    abstract val bootClasspath: ConfigurableFileCollection\n\n    @get:Input\n    abstract val targetType: Property<String>\n\n    @get:Input\n    abstract val offline: Property<Boolean>\n\n    @get:Input\n    abstract val usesKotlin: Property<Boolean>\n\n    @get:Input\n    abstract val targetSdk: Property<String>\n\n    @get:Input\n    abstract val minSdk: Property<String>\n\n    @get:Input\n    abstract val agpVersion: Property<String>\n\n    @get:Input\n    abstract val appId: Property<String>\n\n    @get:Input\n    abstract val gradleVersion: Property<String>\n\n    @get:Input\n    abstract val usesSync: Property<Boolean>\n\n    @get:OutputFiles\n    abstract val output: RegularFileProperty\n\n    @get:Input\n    abstract val areIncrementalBuildsDisabled: Property<Boolean>\n\n    // Checks if a JarFile exists, if not it creates an empty one.\n    private fun touchJarFile(jarFile: RegularFile) {\n        if (!jarFile.asFile.exists()) {\n            JarOutputStream(\n                BufferedOutputStream(\n                    FileOutputStream(\n                        output.get().asFile\n                    )\n                )\n            ).close()\n        }\n    }\n\n    /**\n     * Implements the transform algorithm. The heaviest part of the transform is loading the\n     * {@code CtClass} from JavaAssist, so this should be avoided as much as possible.\n     *\n     * This is also the reason that there are significant changes between a full build and a\n     * incremental build. In a full build, we can use text matching to go from a proxy class\n     * to the model class. Something we cannot do when building incrementally. In that case\n     * we have to deduce all information from the class at hand.\n     */\n    @TaskAction\n    fun transform(inputChanges: InputChanges) {\n        val metadata = ProjectMetaData(\n            bootClassPath = bootClasspath.files,\n            usesKotlin = usesKotlin.get(),\n            targetType = targetType.get(),\n            targetSdk = targetSdk.get(),\n            minSdk = minSdk.get(),\n            agpVersion = agpVersion.get(),\n            appId = appId.get(),\n            gradleVersion = gradleVersion.get(),\n            usesSync = usesSync.get(),\n            isGradleOffline = offline.get(),\n        )\n\n        val analytics: RealmAnalytics? = try {\n            RealmAnalytics().apply {\n                calculateAnalyticsData(metadata)\n            }\n        } catch (e: Exception) {\n            // Analytics should never crash the build.\n            logger.debug(\"Could not calculate Realm analytics data:\\n$e\")\n            null\n        }\n\n        val timer = Stopwatch()\n        val exitTransform = {\n            timer.stop()\n            analytics?.execute()\n        }\n\n        timer.start(\"Realm Transform time\")\n\n        // The output of this transform is a Jar file\n        // We use FileSystem instead of a JarOutputStream because it allows modifying the entries of\n        // the Jar file, and thus incremental updates.\n        val jarFileOutput: FileSystem = output.get().let { jarFile ->\n            // Workaround to create the Jar if does not exist, as FileSystems fails to do so.\n            touchJarFile(jarFile)\n            FileSystems.newFileSystem(output.get().asFile.toPath(), null)\n        }\n\n        val build: BuildTemplate =\n            when {\n                areIncrementalBuildsDisabled.get() || !inputChanges.isIncremental ->\n                    FullBuild(\n                        metadata = metadata,\n                        inputJars = inputJars.get(),\n                        inputDirectories = inputDirectories,\n                        output = jarFileOutput,\n                    )\n\n                else -> {\n                    val fileChanges: MutableIterable<FileChange> =\n                        inputChanges.getFileChanges(inputDirectories)\n\n                    IncrementalBuild(\n                        metadata = metadata,\n                        inputJars = inputJars.get(),\n                        inputDirectories = inputDirectories,\n                        output = jarFileOutput,\n                        fileChanges = fileChanges,\n                    )\n                }\n            }\n\n        build.prepareOutputClasses()\n        timer.splitTime(\"Prepare output classes\")\n        if (build.hasNoOutput()) {\n            // Abort transform as quickly as possible if no files where found for processing.\n            exitTransform()\n            return\n        }\n        build.prepareReferencedClasses(referencedInputs)\n        timer.splitTime(\"Prepare referenced classes\")\n        build.markMediatorsAsTransformed()\n        timer.splitTime(\"Mark mediators as transformed\")\n        build.transformModelClasses()\n        timer.splitTime(\"Transform model classes\")\n        build.transformDirectAccessToModelFields()\n        timer.splitTime(\"Transform references to model fields\")\n        build.copyProcessedClasses()\n        timer.splitTime(\"Copy processed classes\")\n        build.copyResourceFiles()\n        timer.splitTime(\"Copy jar files\")\n        jarFileOutput.close()\n        exitTransform()\n    }\n}\n\n"
  },
  {
    "path": "realm-transformer/src/main/kotlin/io/realm/transformer/Stopwatch.kt",
    "content": "/*\n * Copyright 2018 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 */\npackage io.realm.transformer\n\nimport org.slf4j.Logger\nimport org.slf4j.LoggerFactory\nimport java.util.concurrent.TimeUnit\n\nclass Stopwatch {\n\n    val logger: Logger = LoggerFactory.getLogger(\"realm-stopwatch\")\n\n    var start: Long = -1L\n    var lastSplit: Long = -1L\n    lateinit var label: String\n\n    /*\n     * Start the stopwatch.\n     */\n    fun start(label: String) {\n        if (start != -1L) {\n            throw IllegalStateException(\"Stopwatch was already started\");\n        }\n        this.label = label\n        start = System.nanoTime();\n        lastSplit = start;\n    }\n\n    /*\n     * Reports the split time.\n     *\n     * @param label Label to use when printing split time\n     * @param reportDiffFromLastSplit if `true` report the time from last split instead of the start\n     */\n    fun splitTime(label: String, reportDiffFromLastSplit: Boolean = true) {\n        val split = System.nanoTime()\n        val diff = if (reportDiffFromLastSplit) { split - lastSplit } else { split - start }\n        lastSplit = split;\n        logger.debug(\"$label: ${TimeUnit.NANOSECONDS.toMillis(diff)} ms.\")\n    }\n\n    /**\n     * Stops the timer and report the result.\n     */\n    fun stop() {\n        val stop = System.nanoTime()\n        val diff = stop - start\n        logger.debug(\"$label: ${TimeUnit.NANOSECONDS.toMillis(diff)} ms.\")\n    }\n}"
  },
  {
    "path": "realm-transformer/src/main/kotlin/io/realm/transformer/build/BuildTemplate.kt",
    "content": "/*\n * Copyright 2018 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 */\npackage io.realm.transformer.build\n\nimport io.realm.transformer.*\nimport javassist.ClassPool\nimport javassist.CtClass\nimport org.gradle.api.file.ConfigurableFileCollection\nimport org.gradle.api.file.Directory\nimport org.gradle.api.file.RegularFile\nimport java.io.File\nimport java.io.InputStream\nimport java.nio.file.FileSystem\nimport java.nio.file.Files\nimport java.nio.file.StandardOpenOption\nimport java.util.jar.JarFile\nimport java.util.regex.Pattern\n\nconst val DOT_CLASS = \".class\"\n\n/**\n * Abstract class defining the structure of doing different types of builds.\n *\n */\nabstract class BuildTemplate(\n    private val metadata: ProjectMetaData,\n    private val allJars: List<RegularFile>,\n    protected val output: FileSystem,\n    val inputs: ConfigurableFileCollection,\n) {\n    protected lateinit var classPool: ManagedClassPool\n    protected lateinit var outputClassNames: Set<String>\n    private lateinit var outputReferencedClassNames: Set<String>\n    protected lateinit var outputModelClasses: List<CtClass>\n    protected val processedClasses = mutableMapOf<String, CtClass>()\n\n    /**\n     * Finds all the class names available for transforms as well as all referenced classes.\n     */\n    abstract fun prepareOutputClasses()\n\n    /**\n     * Helper method where we go through all input classes and sort them into buckets of source files\n     * in the current project or source files found in jar files.\n     *\n     * @return paths in the output FileSystem for the classes to be processed.\n     */\n     fun categorizeClassNames(): Set<String> {\n        return inputs.flatMap { directory ->\n            val dirPath: String = directory.absolutePath\n\n            directory.walk()\n                .filter(File::isFile)\n                .filter { file -> file.shouldCategorize() }\n                .filter { file -> file.absolutePath.endsWith(DOT_CLASS) }\n                .map { it.categorize(dirPath) }\n        }.toSet()\n    }\n\n    private fun categorizeClassNames(referencedInputs: ConfigurableFileCollection): Set<String> =\n        referencedInputs.flatMap { file ->\n            JarFile(file).use { jarFile ->\n                jarFile.entries()\n                    .toList()\n                    .filter { jarEntry ->\n                        !jarEntry.isDirectory && jarEntry.name.endsWith(DOT_CLASS)\n                    }\n                    .map { jarEntry ->\n                        val path: String = jarEntry.name\n                        // The jar might not using File.separatorChar as the path separator. So we just replace both `\\` and\n                        // `/`. It depends on how the jar file was created.\n                        // See http://stackoverflow.com/questions/13846000/file-separators-of-path-name-of-zipentry\n                        path.substring(startIndex = 0, endIndex = path.length - DOT_CLASS.length)\n                            .replace('/', '.')\n                            .replace('\\\\', '.')\n                    }\n            }// Crash transformer if this fails to close\n        }.toSet()\n\n    /**\n     * Returns `true` if this build contains no relevant classes to transform.\n     */\n    fun hasNoOutput(): Boolean = outputClassNames.isEmpty()\n\n    fun prepareReferencedClasses(referencedInputs: ConfigurableFileCollection) {\n        outputReferencedClassNames = categorizeClassNames(referencedInputs) // referenced files\n\n        // Create and populate the Javassist class pool\n        this.classPool = ManagedClassPool(inputs, referencedInputs)\n        // Append android.jar to class pool. We don't need the class names of them but only the class in the pool for\n        // javassist. See https://github.com/realm/realm-java/issues/2703.\n        addBootClassesToClassPool(classPool)\n        logger.debug(\"ClassPool contains Realm classes: ${classPool.getOrNull(\"io.realm.RealmList\") != null}\")\n\n        filterForModelClasses(outputClassNames, outputReferencedClassNames)\n    }\n\n    protected abstract fun filterForModelClasses(outputClassNames: Set<String>, outputReferencedClassNames: Set<String>)\n\n    fun markMediatorsAsTransformed() {\n        val baseProxyMediator: CtClass = classPool.get(\"io.realm.internal.RealmProxyMediator\")\n        val mediatorPattern: Pattern = Pattern.compile(\"^io\\\\.realm\\\\.[^.]+Mediator$\")\n        val proxyMediatorClasses: Collection<CtClass> = outputClassNames\n                .filter { mediatorPattern.matcher(it).find() }\n                .map { classPool.getCtClass(it) }\n                .filter { it.superclass.equals(baseProxyMediator) }\n\n        logger.debug(\"Proxy Mediator Classes: ${proxyMediatorClasses.joinToString(\",\") { it.name }}\")\n        proxyMediatorClasses.forEach {\n            BytecodeModifier.overrideTransformedMarker(it)\n            processedClasses[it.name] = it\n        }\n    }\n\n    fun transformModelClasses() {\n        // Add accessors to the model classes in the target project\n        outputModelClasses.forEach {\n            logger.debug(\"Modify model class: ${it.name}\")\n            BytecodeModifier.addRealmAccessors(it)\n            BytecodeModifier.addRealmProxyInterface(it, classPool)\n            BytecodeModifier.callInjectObjectContextFromConstructors(it)\n\n            processedClasses[it.name] = it\n        }\n    }\n\n    abstract fun transformDirectAccessToModelFields()\n\n    fun copyProcessedClasses() {\n        processedClasses.forEach { (fqName: String, clazz: CtClass) ->\n            output.addEntry(\n                \"${fqName.replace('.', '/')}.class\",\n                clazz.toBytecode().inputStream()\n            )\n        }\n    }\n\n    fun copyResourceFiles() {\n        inputs.forEach { directory: File ->\n            val dirName = directory.absolutePath + File.separator\n            directory.walk().filter(File::isFile)\n                .filterNot { it.absolutePath.endsWith(DOT_CLASS) }\n                .forEach { file ->\n                    val pathWithoutPrefix = file.absolutePath.removePrefix(dirName)\n                    // We need to transform platform paths into consistent zip entry paths\n                    // https://github.com/realm/realm-java/issues/7757\n                    val zipEntryPath = pathWithoutPrefix.replace(File.separatorChar, '/')\n\n                    output.addEntry(zipEntryPath, file.inputStream())\n                }\n        }\n        allJars.forEach { file ->\n            JarFile(file.asFile).use { jarFile ->\n                jarFile.entries()\n                    .toList()\n                    .forEach { jarEntry ->\n                        jarFile.getInputStream(jarEntry).use {\n                            output.addEntry(\n                                jarEntry.name,\n                                it\n                            )\n                        }\n                    }\n            }\n        }\n\n        classPool.close()\n    }\n\n    /**\n     * Helper method that adds an entry into a FileSystem. It takes the path and the contents, and\n     * creates and intermediate directory.\n     */\n    private fun FileSystem.addEntry(entryPath: String, input: InputStream) {\n        getPath(entryPath).let { path ->\n            path.parent?.let { Files.createDirectories(it) }\n            Files.newOutputStream(path, StandardOpenOption.CREATE).use { stream ->\n                input.copyTo(stream)\n                stream.close()\n            }\n        }\n    }\n\n    /**\n     * There is no official way to get the path to android.jar for transform.\n     * See https://code.google.com/p/android/issues/detail?id=209426\n     */\n    private fun addBootClassesToClassPool(classPool: ClassPool) {\n        try {\n            metadata.bootClassPath.forEach {\n                val path: String = it.absolutePath\n                logger.debug(\"Add boot class $path to class pool.\")\n                classPool.appendClassPath(path)\n            }\n        } catch (e: Exception) {\n            // Just log it. It might not impact the transforming if the method which needs to be transformer doesn't\n            // contain classes from android.jar.\n            logger.debug(\"Cannot get bootClasspath caused by: \", e)\n        }\n    }\n\n    protected abstract fun findModelClasses(classNames: Set<String>): List<CtClass>\n\n    /**\n     * Helper method that computes the path in the output FileSystem for a given class.\n     */\n    protected fun File.categorize(dirPath: String): String =\n        absolutePath\n            .substring(\n                startIndex = dirPath.length + 1,\n                endIndex = absolutePath.length - DOT_CLASS.length\n            )\n            .replace(File.separatorChar, '.')\n\n    /**\n     * Tells if a given file has to be categorized.\n     */\n    abstract fun File.shouldCategorize(): Boolean\n}\n"
  },
  {
    "path": "realm-transformer/src/main/kotlin/io/realm/transformer/build/FullBuild.kt",
    "content": "/*\n * Copyright 2018 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\npackage io.realm.transformer.build\n\nimport io.realm.transformer.BytecodeModifier\nimport io.realm.transformer.BytecodeModifier.Companion.isModelField\nimport io.realm.transformer.ProjectMetaData\nimport io.realm.transformer.ext.safeSubtypeOf\nimport io.realm.transformer.logger\nimport javassist.CtClass\nimport org.gradle.api.file.ConfigurableFileCollection\nimport org.gradle.api.file.RegularFile\nimport java.io.File\nimport java.nio.file.FileSystem\n\nclass FullBuild(\n    metadata: ProjectMetaData,\n    inputJars: List<RegularFile>,\n    output: FileSystem,\n    inputDirectories: ConfigurableFileCollection\n) : BuildTemplate(\n    metadata = metadata,\n    allJars = inputJars,\n    output = output,\n    inputs = inputDirectories\n) {\n    private lateinit var allModelClasses: List<CtClass>\n\n    override fun prepareOutputClasses() {\n        outputClassNames = categorizeClassNames()\n        logger.debug(\"Full build. Number of files being processed: ${outputClassNames.size}.\")\n    }\n\n    override fun findModelClasses(classNames: Set<String>): List<CtClass> {\n        val realmObjectProxyInterface: CtClass = classPool.get(\"io.realm.internal.RealmObjectProxy\")\n\n        // For full builds, we are currently finding model classes by assuming that only\n        // the annotation processor is generating files ending with `RealmProxy`. This is\n        // a lot faster as we only need to compare the name of the type before we load\n        // the CtClass.\n        // Find the model classes\n        return classNames\n            // Quick and loose filter where we assume that classes ending with RealmProxy are\n            // a Realm model proxy class generated by the annotation processor. This can\n            // produce false positives: https://github.com/realm/realm-java/issues/3709\n            .filter { it.endsWith(\"RealmProxy\") }\n            .map { classPool.getCtClass(it) }\n            .filter { clazz ->\n                // Verify the file is in fact a proxy class, in which case the super\n                // class is always present and is the real model class.\n                clazz.safeSubtypeOf(realmObjectProxyInterface)\n            }\n            .map { it.superclass }\n    }\n\n    // Full builds must categorize all classes.\n    override fun File.shouldCategorize(): Boolean = true\n\n    override fun filterForModelClasses(classNames: Set<String>, extraClassNames: Set<String>) {\n        val allClassNames: Set<String> = merge(classNames, extraClassNames)\n\n        allModelClasses = findModelClasses(allClassNames)\n\n        outputModelClasses = allModelClasses.filter {\n            outputClassNames.contains(it.name)\n        }\n    }\n\n    override fun transformDirectAccessToModelFields() {\n        // Populate a list of the fields that need to be managed with bytecode manipulation\n        val allManagedFields = allModelClasses.flatMap { ctClass ->\n            ctClass.declaredFields.filter { ctField ->\n                ctField.isModelField()\n            }\n        }\n\n        logger.debug(\"Managed Fields: ${allManagedFields.joinToString(\",\") { it.name }}\")\n\n        // Use accessors instead of direct field access\n        outputClassNames.forEach {\n            logger.debug(\"Modifying accessors in class: $it\")\n            try {\n                val ctClass: CtClass = classPool.getCtClass(it)\n                if (ctClass.isFrozen) {\n                    ctClass.defrost()\n                }\n                BytecodeModifier.useRealmAccessors(classPool, ctClass, allManagedFields)\n                processedClasses[it] = ctClass\n            } catch (e: Exception) {\n                throw RuntimeException(\"Failed to transform $it.\", e)\n            }\n        }\n    }\n\n    private fun merge(set1: Set<String>, set2: Set<String>): Set<String>  {\n        val merged: MutableSet<String> = hashSetOf()\n        merged.addAll(set1)\n        merged.addAll(set2)\n        return merged\n    }\n}\n"
  },
  {
    "path": "realm-transformer/src/main/kotlin/io/realm/transformer/build/IncrementalBuild.kt",
    "content": "package io.realm.transformer.build\n\n/*\n * Copyright 2018 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\nimport io.realm.annotations.RealmClass\nimport io.realm.transformer.BytecodeModifier\nimport io.realm.transformer.ProjectMetaData\nimport io.realm.transformer.ext.hasRealmClassAnnotation\nimport io.realm.transformer.ext.safeSubtypeOf\nimport io.realm.transformer.logger\nimport javassist.CtClass\nimport org.gradle.api.file.ConfigurableFileCollection\nimport org.gradle.api.file.RegularFile\nimport org.gradle.work.ChangeType\nimport org.gradle.work.FileChange\nimport java.io.File\nimport java.nio.file.FileSystem\nimport kotlin.io.path.deleteIfExists\n\nclass IncrementalBuild(\n    metadata: ProjectMetaData,\n    private val fileChanges: Iterable<FileChange>,\n    inputJars: List<RegularFile>,\n    inputDirectories: ConfigurableFileCollection,\n    output: FileSystem,\n) : BuildTemplate(\n    metadata = metadata,\n    allJars = inputJars,\n    inputs = inputDirectories,\n    output = output,\n) {\n    // Map containing all file changes\n    private lateinit var fileChangeMap: Map<String, FileChange>\n\n    private fun removeDeletedEntries() {\n        inputs.forEach { directory ->\n            val dirPath: String = directory.absolutePath\n\n            fileChanges\n                .asSequence()\n                .filter { details ->\n                    details.changeType == ChangeType.REMOVED\n                }\n                .map { it.file }\n                .filter { file -> file.absolutePath.endsWith(DOT_CLASS) }\n                .filter { file -> file.startsWith(dirPath) }\n                .map { it.categorize(dirPath) }\n                .forEach { path ->\n                    // We need to transform platform paths into consistent zip entry paths\n                    // https://github.com/realm/realm-java/issues/7757\n                    val zipEntryPath = \"${path.replace('.', '/')}.class\"\n\n                    logger.debug(\"Deleting output entry: $zipEntryPath\")\n                    output.getPath(zipEntryPath).deleteIfExists()\n                }\n        }\n    }\n\n    private fun processDeltas() {\n        fileChangeMap = fileChanges\n            .asSequence()\n            .associateBy { details ->\n                details.file.absolutePath\n            }\n\n        // we require to delete any removed entry from the final JAR\n        removeDeletedEntries()\n    }\n\n    override fun prepareOutputClasses() {\n        processDeltas()\n\n        outputClassNames = categorizeClassNames()\n\n        logger.debug(\"Incremental build. Files being processed: ${outputClassNames.size}.\")\n        logger.debug(\"Incremental files: ${outputClassNames.joinToString(\",\")}\")\n    }\n\n    override fun File.shouldCategorize(): Boolean = absolutePath in fileChangeMap\n\n    override fun filterForModelClasses(\n        outputClassNames: Set<String>,\n        outputReferencedClassNames: Set<String>\n    ) {\n        outputModelClasses = findModelClasses(outputClassNames)\n    }\n\n    override fun transformDirectAccessToModelFields() {\n        // Use accessors instead of direct field access\n        outputClassNames.forEach { className ->\n            logger.debug(\"Modify accessors in class: $className\")\n            val ctClass: CtClass = classPool.getCtClass(className)\n            BytecodeModifier.useRealmAccessors(classPool, ctClass)\n            processedClasses[className] = ctClass\n        }\n    }\n\n    override fun findModelClasses(classNames: Set<String>): List<CtClass> {\n        val realmObjectProxyInterface: CtClass = classPool.get(\"io.realm.internal.RealmObjectProxy\")\n        // For incremental builds we need to determine if a class is a model class file\n        // based on information in the file itself. This require checks that are only\n        // possible once we loaded the CtClass from the ClassPool and is slower\n        // than the approach used when doing full builds.\n        return classNames\n            // Map strings to CtClass'es.\n            .map { classPool.getCtClass(it) }\n            // Model classes either have the @RealmClass annotation directly (if implementing RealmModel)\n            // or their superclass has it (if extends RealmObject). The annotation processor\n            // will have ensured the annotation is only present in these cases.\n            .filter {\n                it.hasAnnotation(RealmClass::class.java) || hasRealmClassAnnotation(it.superclass)\n            }\n            // Proxy classes are generated by the Realm Annotation Processor and might accidentally\n            // pass the above check (e.g. if the model class has the @RealmClass annotation), so\n            // ignore them.\n            .filter { !it.safeSubtypeOf(realmObjectProxyInterface) }\n            // Unfortunately the RealmObject base class passes all above checks, so explicitly\n            // ignore it.\n            .filter { !it.name.equals(\"io.realm.RealmObject\") }\n    }\n}\n"
  },
  {
    "path": "realm-transformer/src/main/kotlin/io/realm/transformer/ext/CtClassExt.kt",
    "content": "/*\n * Copyright 2018 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 */\npackage io.realm.transformer.ext\n\nimport io.realm.annotations.RealmClass\nimport javassist.CtClass\nimport javassist.NotFoundException\nimport javassist.bytecode.ClassFile\n\n\n/**\n * Returns {@code true} if 'clazz' is considered a subtype of 'superType'.\n *\n * This function is different than {@link CtClass#subtypeOf(CtClass)} in the sense\n * that it will never crash even if classes are missing from the class pool, instead\n * it will just return {@code false}.\n *\n * This e.g. happens with RxJava classes which are optional, but JavaAssist will try\n * to load them and then crash.\n *\n * @param typeToCheckAgainst the type we want to check against\n * @return `true` if `clazz` is a subtype of `typeToCheckAgainst`, `false` otherwise.\n */\nfun CtClass.safeSubtypeOf(typeToCheckAgainst: CtClass): Boolean {\n    val typeToCheckAgainstQualifiedName: String = typeToCheckAgainst.name\n    if (this == typeToCheckAgainst || this.name.equals(typeToCheckAgainstQualifiedName)) {\n        return true\n    }\n\n    val file: ClassFile = this.classFile2\n\n    // Check direct super class\n    val superName: String? = file.superclass\n    if (superName.equals(typeToCheckAgainstQualifiedName)) {\n        return true\n    }\n\n    // Check direct interfaces\n    val ifs: Array<String> = file.interfaces\n    ifs.forEach {\n        if (it == typeToCheckAgainstQualifiedName) {\n            return true\n        }\n    }\n\n    // Check other inherited super classes\n    if (superName != null) {\n        var nextSuper: CtClass\n        try {\n            nextSuper = classPool.get(superName)\n            if (nextSuper.safeSubtypeOf(typeToCheckAgainst)) {\n                return true\n            }\n        } catch (ignored: NotFoundException) {\n        }\n    }\n\n    // Check other inherited interfaces\n    ifs.forEach { interfaceName ->\n        try {\n            val interfaceClass: CtClass = classPool.get(interfaceName)\n            if (interfaceClass.safeSubtypeOf(typeToCheckAgainst)) {\n                return true\n            }\n        } catch (ignored: NotFoundException) {\n        }\n    }\n\n    return false\n}\n\nfun hasRealmClassAnnotation(superclass: CtClass?) = try {\n    superclass?.hasAnnotation(RealmClass::class.java) == true\n} catch (ignored: NotFoundException) {\n    false\n}\n"
  },
  {
    "path": "realm-transformer/src/main/kotlin/io/realm/transformer/ext/ProjectExt.kt",
    "content": "/*\n * Copyright 2018 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\npackage io.realm.transformer.ext\n\nimport com.android.build.gradle.BaseExtension\nimport org.gradle.api.Project\nimport java.io.File\n\n/**\n * Attempts to determine the best possible unique AppId for this project.\n */\nfun Project.getAppId(): String {\n    // Use the Root project name, usually set in `settings.gradle`\n    // This means that we don't treat apps with multiple flavours as different, nor\n    // if a project contains more than one app (probably unlikely).\n    // This seems acceptable. These cases would just show up as more builds for the\n    // same AppId.\n    return this.rootProject.name\n}\n\n/**\n * Returns the `targetSdk` property for this project if it is available.\n */\nfun Project.getTargetSdk(): String {\n    return getAndroidExtension(this).defaultConfig.targetSdkVersion?.apiString ?: \"unknown\"\n}\n\n/**\n * Returns the `minSdk` property for this project if it is available.\n */\nfun Project.getMinSdk(): String {\n    return getAndroidExtension(this).defaultConfig.minSdkVersion?.apiString ?: \"unknown\"\n}\n\n/**\n * Returns the version of the Android Gradle Plugin that is used.\n */\nfun Project.getAgpVersion(): String {\n    // This API is only available from AGP 7.0.0. And it is a bit unclear exactly which part of\n    // this is actually stable. Also, there appear to be problems with depending on AGP 7.* on\n    // the compile classpath (it cannot load BaseExtension).\n    //\n    // So for now, this code assumes that we are compiling against AGP 4.1 and uses reflection\n    // to try to grap the AGP version.\n    //\n    // This is done with a best-effort, but we just\n    // accept finding the version isn't possible if anything goes wrong.\n    return try {\n        val extension = this.extensions.getByName(\"androidComponents\") as Object\n        val method = extension.`class`.getMethod(\"getPluginVersion\")\n        val version = method.invoke(extension)\n        if (version != null) {\n            return version.toString()\n        } else {\n            return \"unknown\"\n        }\n    } catch (e: Exception) {\n        \"unknown\"\n    }\n}\n\n/**\n * Returns the `bootClasspath` for this project\n */\nfun Project.getBootClasspath(): List<File> {\n    return getAndroidExtension(this).bootClasspath\n}\n\nprivate fun getAndroidExtension(project: Project): BaseExtension {\n    // This will always be present, otherwise the android build would not be able to\n    // trigger the transformer code in the first place.\n    return project.extensions.getByName(\"android\") as BaseExtension\n}\n\nfun Project.areIncrementalBuildsDisabled() =\n    if(extensions.extraProperties.has(\"io.realm.disableIncrementalBuilds\")){\n        extensions.extraProperties[\"io.realm.disableIncrementalBuilds\"] == \"true\"\n    } else {\n        false\n    }\n\nfun Project.targetType(): String = with(project.plugins) {\n    when {\n        findPlugin(\"com.android.application\") != null -> \"app\"\n        findPlugin(\"com.android.library\") != null -> \"library\"\n        else -> \"unknown\"\n    }\n}\n\nfun Project.usesKotlin(): Boolean {\n    return project.pluginManager.hasPlugin(\"kotlin-kapt\")\n}"
  },
  {
    "path": "realm-transformer/src/main/templates/Version.java",
    "content": "package io.realm.transformer;\n\npublic class Version {\n    public static final String VERSION = \"@version@\";\n    public static final String SYNC_VERSION = \"@coreVersion@\";\n}\n"
  },
  {
    "path": "realm-transformer/src/test/kotlin/io/realm/transformer/ByteCodeModifierTest.kt",
    "content": "/*\n * Copyright 2018 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\npackage io.realm.transformer\n\nimport io.realm.annotations.Ignore\nimport javassist.*\nimport javassist.bytecode.AnnotationsAttribute\nimport javassist.bytecode.ConstPool\nimport javassist.bytecode.Opcode\nimport javassist.bytecode.annotation.Annotation\nimport org.junit.Assert.assertFalse\nimport org.junit.Assert.assertTrue\nimport org.junit.Test\nimport java.lang.reflect.Modifier\n\nclass ByteCodeModifierTest {\n\n    @Test\n    fun addRealmAccessors() {\n        // Generate an empty class\n        val classPool = ClassPool.getDefault()\n        val ctClass = classPool.makeClass(\"testClass\")\n\n        // Add a field\n        val ctField = CtField(CtClass.intType, \"age\", ctClass)\n        ctClass.addField(ctField)\n\n        // The accessors are added\n        BytecodeModifier.addRealmAccessors(ctClass)\n\n        // The accessors are generated\n        val ctMethods = ctClass.declaredMethods\n        val methodNames = ctMethods.map { it.name }\n        assertTrue(methodNames.contains(\"realmGet\\$age\"))\n        assertTrue(methodNames.contains(\"realmSet\\$age\"))\n\n        // The accessors are public\n        ctMethods.forEach {\n            assertTrue(it.modifiers == Modifier.PUBLIC)\n        }\n    }\n\n    // https://github.com/realm/realm-java/issues/3469\n    @Test\n    fun addRealmAccessors_duplicateSetter() {\n        // Generate an empty class\n        val classPool = ClassPool.getDefault()\n        val ctClass = classPool.makeClass(\"testClass\")\n\n        // Add a field\n        val ctField = CtField(CtClass.intType, \"age\", ctClass)\n        ctClass.addField(ctField)\n\n        // Add a setter\n        val setter = CtNewMethod.setter(\"realmSet\\$age\", ctField)\n        ctClass.addMethod(setter)\n\n        // addRealmAccessors is called\n        BytecodeModifier.addRealmAccessors(ctClass)\n\n        // a getter for the field is generated\n        val ctMethods = ctClass.declaredMethods\n        val methodNames = ctMethods.map { it.name }\n        assertTrue(methodNames.contains(\"realmGet\\$age\"))\n\n        // the setter is not changed\n        assertTrue(ctMethods.find { it.name == \"realmSet\\$age\" } == setter)\n\n        // accessors are public\n        ctMethods.forEach {\n            assertTrue(it.modifiers == Modifier.PUBLIC)\n        }\n    }\n\n    // https://github.com/realm/realm-java/issues/3469\n    @Test\n    fun addRealmAccessors_duplicateGetter() {\n        // Generate an empty class\n        val classPool = ClassPool.getDefault()\n        val ctClass = classPool.makeClass(\"testClass\")\n\n        // Add a field\n        val ctField = CtField(CtClass.intType, \"age\", ctClass)\n        ctClass.addField(ctField)\n\n        // Add a getter\n        val setter = CtNewMethod.setter(\"realmGet\\$age\", ctField)\n        ctClass.addMethod(setter)\n\n        // addRealmAccessors is called\n        BytecodeModifier.addRealmAccessors(ctClass)\n\n        // a setter for the field is generated\n        val ctMethods = ctClass.declaredMethods\n        val methodNames = ctMethods.map { it.name }\n        assertTrue(methodNames.contains(\"realmSet\\$age\"))\n\n        // the getter is not changed\n        assertTrue(ctMethods.find { it.name == \"realmGet\\$age\" } == setter)\n\n        // accessors are public\n        ctMethods.forEach {\n            assertTrue(it.modifiers == Modifier.PUBLIC)\n        }\n    }\n\n    @Test\n    fun addRealmAccessors_ignoreAnnotation() {\n        // Generate an empty class\n        val classPool = ClassPool.getDefault()\n        val ctClass = classPool.makeClass(\"testClass\")\n        val constPool = ConstPool(\"TestClass\")\n\n        // Add a field with @Ignore\n        val ctField = CtField(CtClass.intType, \"age\", ctClass)\n        ctClass.addField(ctField)\n        val attr = AnnotationsAttribute(constPool, AnnotationsAttribute.visibleTag)\n        val ignoreAnnotation = Annotation(Ignore::class.java.name, constPool)\n        attr.addAnnotation(ignoreAnnotation)\n        ctField.fieldInfo.addAttribute(attr)\n\n        // Try to add the accessor\n        BytecodeModifier.addRealmAccessors(ctClass)\n\n        // the accessor should not be generated\n        // a setter for the field is generated\n        val ctMethods = ctClass.declaredMethods\n        val methodNames = ctMethods.map { it.name }\n        assertFalse(methodNames.contains(\"realmSet\\$age\"))\n        assertFalse(methodNames.contains(\"realmGet\\$age\"))\n    }\n\n    @Test\n    fun userRealmAccessors() {\n        // Generate an empty class\n        val classPool = ClassPool.getDefault()\n        val ctClass = classPool.makeClass(\"testClass\")\n\n        // Add a field\n        val ctField = CtField(CtClass.intType, \"age\", ctClass)\n        ctClass.addField(ctField)\n\n        // Add a method that uses such field\n        val ctMethod = CtNewMethod.make(\"public boolean canDrive() { return this.age >= 18; }\", ctClass)\n        ctClass.addMethod(ctMethod)\n\n        // Realm accessors are called\n        BytecodeModifier.addRealmAccessors(ctClass)\n\n        // the field use is replaced by the accessor\n        BytecodeModifier.useRealmAccessors(classPool, ctClass, listOf(ctField))\n\n        // the field is not used and getter is called in the method\n        assertTrue(!isFieldRead(ctMethod) && hasMethodCall(ctMethod))\n    }\n\n    fun userRealmAccessors_fieldAccessConstructorIsTransformed() {\n        // Generate an empty class\n        val classPool = ClassPool.getDefault()\n        val ctClass = classPool.makeClass(\"testClass\")\n        val constPool = ConstPool(\"TestClass\")\n\n        // Add a field with @Ignore\n        val ctField = CtField(CtClass.intType, \"age\", ctClass)\n        ctClass.addField(ctField)\n\n        // Add a method sets such field\n        val ctMethod = CtNewMethod.make(\"private void setupAge(int age) { this.age = age; }\", ctClass)\n        ctClass.addMethod(ctMethod)\n\n        // Add a default constructor that uses the method\n        val ctDefaultConstructor = CtNewConstructor.make(\"public TestClass() { int myAge = this.age; }\", ctClass)\n        ctClass.addConstructor(ctDefaultConstructor)\n\n        // Add a non-default constructor that uses the method\n        val ctNonDefaultConstructor = CtNewConstructor.make(\"public TestClass(TestClass other) { int otherAge = other.age; }\", ctClass)\n        ctClass.addConstructor(ctNonDefaultConstructor)\n\n        // Realm accessors are added\n        BytecodeModifier.addRealmAccessors(ctClass)\n\n        // the field use is replaced by the accessor\n        BytecodeModifier.useRealmAccessors(classPool, ctClass, listOf(ctField))\n\n        // the field is not used in the method anymore\n        assertTrue(!isFieldRead(ctDefaultConstructor)\n                && hasMethodCall(ctDefaultConstructor)\n                && !isFieldRead(ctNonDefaultConstructor)\n                && hasMethodCall(ctNonDefaultConstructor))\n    }\n\n    private fun isFieldRead(behavior: CtBehavior): Boolean {\n        val methodInfo = behavior.methodInfo\n        val codeAttribute = methodInfo.codeAttribute\n\n        val it = codeAttribute.iterator()\n        var index = 0;\n        while (it.hasNext()) {\n            val op: Int = it.byteAt(index)\n            index = it.next()\n            if (op == Opcode.GETFIELD) {\n                return true;\n            }\n        }\n        return false\n    }\n\n    private fun hasMethodCall(behavior: CtBehavior): Boolean {\n        val methodInfo = behavior.methodInfo\n        val codeAttribute = methodInfo.codeAttribute\n\n        val it = codeAttribute.iterator()\n        var index = 0;\n        while (it.hasNext()) {\n            val op: Int = it.byteAt(index)\n            index = it.next()\n            if (op == Opcode.INVOKEVIRTUAL) {\n                return true;\n            }\n        }\n        return false\n    }\n\n}\n"
  },
  {
    "path": "settings.gradle",
    "content": "rootProject.name = 'realm-java'\n"
  },
  {
    "path": "tools/analyze_realm_metrics.sh",
    "content": "#!/bin/sh\n\n# This script will print metrics for the Realm library being deployed to end users.\n# To run it:\n#   1. Make sure that $D8 is defined in your environment, e.g. `D8=\"$ANDROID_SDK_ROOT/build-tools/29.0.2/d8\"`\n#   2. Make sure that you have built the library artifacts using `./gradlew assembleRelease` from the realm folder.\n#   3. Run the script: `> sh ./analyze_realm_metrics.sh`\n#\n# Note: This script has only been tested on MacOS\n\nHERE=`pwd`\n\ncd \"$(dirname $0)/..\"\n\ncd realm/realm-library/build/outputs/aar\n\n# Base variant\necho \"Analyzing Base...\"\nstat -f\"AAR size: %z\" realm-android-library-base-release.aar\nrm -rf unzippedBase\nunzip -qq realm-android-library-base-release.aar -d unzippedBase\nsh \"$D8\" --release --output ./unzippedBase unzippedBase/classes.jar > /dev/null 2>&1\ncat ./unzippedBase/classes.dex | head -c 92 | tail -c 4 | hexdump -e '1/4 \"Method count: %d\\n\"'\nfind ./unzippedBase -name '*.so' -exec stat -f\"%z %N\" {} \\;\n\n# ObjectServer variant\necho \"\\nAnalyzing ObjectServer...\"\nstat -f\"AAR size: %z\" realm-android-library-objectServer-release.aar\nrm -rf unzippedObjectServer\nunzip -qq realm-android-library-objectServer-release.aar -d unzippedObjectServer\nsh \"$D8\" --release --output ./unzippedObjectServer unzippedObjectServer/classes.jar > /dev/null 2>&1\ncat ./unzippedObjectServer/classes.dex | head -c 92 | tail -c 4 | hexdump -e '1/4 \"Method count: %d\\n\"'\nfind ./unzippedObjectServer -name '*.so' -exec stat -f\"%z %N\" {} \\;\n\ncd $HERE\n"
  },
  {
    "path": "tools/build-id.py",
    "content": "#!/usr/bin/python3\n\n#\n# This script allows to extract build ids from binaries published in our realm java S3 bucket.\n#\n# The user can specify an individual version or a set, that will be outputed as a table.\n#\n# The process can be slow and resource consuming, as it needs to download each release, extract it\n# to finally run the readelf tool.\n#\n\nimport os\nimport sys\nimport subprocess\nimport urllib.request\nimport zipfile\nimport argparse\n\nREADELF_TOOL_PATH = '/toolchains/llvm/prebuilt/darwin-x86_64/bin/x86_64-linux-android-readelf'\nFIND_NDK_COMMAND = 'find $ANDROID_HOME/ndk -name \".*\" -prune -maxdepth 1 -o -print | sort -rV | head -n 1'\nNDK_PATH = subprocess.check_output(FIND_NDK_COMMAND, shell=True).decode('ascii').strip()\nBUILD_ID_EXTRACT_COMMMAND = NDK_PATH + READELF_TOOL_PATH + ' -n {0} | grep \"Build ID\" | cut -d \":\" -f2'\n\nFLAVORS = ['base', 'objectServer']\nARCHS = ['arm64-v8a', 'armeabi-v7a', 'x86', 'x86_64', 'mips']\n\nZIPS_PATH = os.getcwd() + \"/downloads/\"\nLIBS_PATH = os.getcwd() + \"/libs/\"\n\n\ndef file_exists(path):\n    f = None\n    try:\n        f = open(path)\n        return True\n    except IOError:\n        return False\n    finally:\n        if f:\n            f.close()\n\n\ndef download_file(url, path):\n    urllib.request.urlretrieve(url, path)\n\n\ndef generator(major_range, minor_range, patch_range):\n    for major in major_range:\n        for minor in minor_range:\n            for patch in patch_range:\n                yield f\"{major}.{minor}.{patch}\"\n\n\ndef create_dirs(path):\n    try:\n        os.mkdir(path)\n    except OSError:\n        pass\n    return path\n\n\ndef unzip(zip_file, version):\n    print(f\"Unziping v{version}\", file=sys.stderr)\n\n    path = LIBS_PATH + f\"{version}\"\n    create_dirs(path)\n    with zipfile.ZipFile(zip_file, \"r\") as zip_ref:\n        zip_ref.extractall(path)\n\n\ndef format_table_line(build_id, version, flavor, arch):\n    return f\"{build_id.ljust(41)} {version.ljust(10)} {flavor.ljust(14)} {arch}\"\n\n\ndef extract_build_ids(ids, version):\n    print(f\"Processing v{version}\", file=sys.stderr)\n\n    for flavor in FLAVORS:\n        for arch in ARCHS:\n            so_path = f\"{LIBS_PATH}/{version}/{flavor}/{arch}/librealm-jni.so\"\n            if file_exists(so_path):\n                build_id = subprocess.check_output(BUILD_ID_EXTRACT_COMMMAND.format(so_path), shell=True).strip().decode('ascii')\n                ids.append(format_table_line(build_id, version, flavor, arch))\n\n\ndef download(zip_path, version):\n    if not file_exists(zip_path):\n        print(f\"Downloading {version}\", file=sys.stderr)\n        download_file(f\"https://static.realm.io/downloads/java/realm-java-jni-libs-unstripped-{version}.zip\", zip_path)\n\n\ndef parse_range(version):\n    if version is None:\n        print(\"⚠️ Please define major minor and patch, see --help \")\n        exit()\n    if '-' in version:\n        version_range = version.split('-')\n        return range(int(version_range[0]), int(version_range[1]) + 1)\n    return [int(version)]\n\nif __name__ == \"__main__\":\n    create_dirs(ZIPS_PATH)\n    create_dirs(LIBS_PATH)\n\n    parser = argparse.ArgumentParser(description='Extract build ids out from S3.')\n    parser.add_argument('major', nargs='?', help='specific version: 1 or range: 1-3')\n    parser.add_argument('minor', nargs='?', help='specific version: 1 or range: 1-3')\n    parser.add_argument('patch', nargs='?', help='specific version: 1 or range: 1-3')\n    args = parser.parse_args()\n\n    major_range = parse_range(args.major)\n    minor_range = parse_range(args.minor)\n    patch_range = parse_range(args.patch)\n\n    build_ids = []\n\n    print(\"-- This process can take some minutes ⏰ --\", file=sys.stderr)\n\n    for version in generator(major_range, minor_range, patch_range):\n        zip_path = ZIPS_PATH + f\"{version}.zip\"\n        try:\n            download(zip_path, version)\n            unzip(zip_path, version)\n            extract_build_ids(build_ids, version)\n        except Exception:\n            print(f\"Skipping v{version}, it does not exist in S3\", file=sys.stderr)\n\n    print(\"-- Done 🚀 --\\n\\n\", file=sys.stderr)\n\n    print(format_table_line(\"Build id\", \"Version\", \"Flavor\", \"Arch\"))\n\n    max_length = max([len(x) for x in build_ids])\n    print(''.ljust(max_length, '-'))\n\n    for build_id in build_ids:\n        print(build_id)\n"
  },
  {
    "path": "tools/buildids.txt",
    "content": "aeed05e18ea335a1f986f27f06fc77e4a8bc4cbf  4.0.0      base           arm64-v8a\nfa9814e496fc038c3f385372de736ca5ddd144fd  4.0.0      base           armeabi-v7a\n8f86435ff36537e508dcf6d84dd7a7baf8cd4504  4.0.0      base           x86\n4addcce6cfc75e0e66d22a4135535d8db737c4d5  4.0.0      base           x86_64\n833358d81cb78e20771765c2a28e98cf6efc7875  4.0.0      base           mips\n64994fa340b2fdadc191f2d1c9fb7552b7ff8706  4.0.0      objectServer   arm64-v8a\ndaba94e6102575c176e380ea0eee67e725eb55a8  4.0.0      objectServer   armeabi-v7a\ncd2ce42a7d5d79aedeaa3132931613a27481b2be  4.0.0      objectServer   x86\n23d3b35bb3a2593c6f1ff31f8328d8d8c4796bda  4.0.0      objectServer   x86_64\n156037359326d2949085222133d70847737fbf0e  4.0.0      objectServer   mips\n4ad3ecf43111c29a210734948113ce45155d6113  4.1.0      base           arm64-v8a\n99f953487802f77c344f30061f4cc63fe30e3a11  4.1.0      base           armeabi-v7a\n7909a05a1aadc091fa31191bf20ca08eef29b88e  4.1.0      base           x86\ne993a5a2c9bcee2992be57f4d1bc3e4600059d3e  4.1.0      base           x86_64\n86407b8428e971fd01a6db21c261507ccf1b8147  4.1.0      base           mips\n3e7e929f936e6fb3570215993c7e9cb38a14c374  4.1.0      objectServer   arm64-v8a\na1c12bff956ad7a64ca1d5f75ee40dc68f345a75  4.1.0      objectServer   armeabi-v7a\n406839153b16e431fdbbd7440964043dc9b57878  4.1.0      objectServer   x86\nd6635a27e56fe4431d5966889231955d9481cc97  4.1.0      objectServer   x86_64\n05c4a411351b49478769936b35e7929823f7ccc5  4.1.0      objectServer   mips\n93ce97c2182b89ee3b9e4840b2d9c61e66b5f438  4.1.1      base           arm64-v8a\nbc3c08b0988649918c909f07d2213c4dbc7a835b  4.1.1      base           armeabi-v7a\n2243666ccfacfc7d2d9aa529e7d3f749f2924cf6  4.1.1      base           x86\n0f81c15c166ad704e26b74fe508712510f8c76ab  4.1.1      base           x86_64\n81a5bab56f2a24844a4d3cb8df0f0b5a00861d3b  4.1.1      base           mips\n29b4f1b323dac6946be9eb626686730f214136c0  4.1.1      objectServer   arm64-v8a\n362f91599a65b48a13d011a1a95957184034eb3f  4.1.1      objectServer   armeabi-v7a\n4f1eaa91281e4d9d5e83c2d067f1f6ecb0514673  4.1.1      objectServer   x86\n38798dc515a80f28e7c7387744f4fa8942257aa2  4.1.1      objectServer   x86_64\n97a9028260539d2fbedccd6fb1f73b575c196174  4.1.1      objectServer   mips\nb5b8fe53fd03ceccbe625ba7f79185c2d9ba9e4c  4.2.0      base           arm64-v8a\nc0bd734d4fe495f3b0d12c9ade73985e1b04aa43  4.2.0      base           armeabi-v7a\n1a1e715ad2bbab1131d81738ebc7bfeb58ea3fb6  4.2.0      base           x86\n0a03f33316c6baf77d8fb65865ec03ff6e88fb81  4.2.0      base           x86_64\nde16bee6a514140ad2c7598f0483896738d30112  4.2.0      base           mips\n76194e173e83e53e85fddc581dcdb4ae78bc10b0  4.2.0      objectServer   arm64-v8a\n0b40b9b0f2d6c0eeab60293476477e16ef374219  4.2.0      objectServer   armeabi-v7a\n4fdb317549ef3ca899edaa2f322f8dda7c854a81  4.2.0      objectServer   x86\nbb5da3053fc511765e11223fb2e2608808b80db7  4.2.0      objectServer   x86_64\nf7dbdb4412af1e2cf117e2722bba267387ab052a  4.2.0      objectServer   mips\nb9382c71cfa9b51558a88b1dd8252c639fc2f684  4.3.0      base           arm64-v8a\n34fb5baf747c7a07b4914da95418a6bde1737144  4.3.0      base           armeabi-v7a\n302c3f8744904dee77797e6c238ee59111730f55  4.3.0      base           x86\na8033f62c10109f919a03eb370f09c32652a713f  4.3.0      base           x86_64\n52cd852585340055991b98631578bba5f59aadef  4.3.0      base           mips\ndb3c8abd28004200b857abb830ca93f6d0475714  4.3.0      objectServer   arm64-v8a\n9251a02d454ee5a44d6ba36483679032d8931dcd  4.3.0      objectServer   armeabi-v7a\n5e89faed2d3b3ba4f0196d791f57b7d7ef326bfb  4.3.0      objectServer   x86\n2ab04a529e223743df6618ad9a2e9e44dec6be63  4.3.0      objectServer   x86_64\nf26cc3fab2bed7de8be7bd97760cfda7377a15a5  4.3.0      objectServer   mips\nfae1e774aea2c1a0192ab7a883cdc163573558dc  4.3.1      base           arm64-v8a\n4900b86976f1242af6347e24a79dfbc2a7f89081  4.3.1      base           armeabi-v7a\nff77990b304021850a992c0dcb250a36600a4093  4.3.1      base           x86\nb37f2d51c50dcef0de412c9838c023853d0b9cb6  4.3.1      base           x86_64\n6f837a15b5f1dc1f14d43f923f0eaae414b2c119  4.3.1      base           mips\n8abfb1b2efe105484596acf19165d1fea3d1843c  4.3.1      objectServer   arm64-v8a\n0e09d5b8704cf19b522a7a2d736948a2fc88210d  4.3.1      objectServer   armeabi-v7a\n82a248c56b2866f32856c588f2509c1eb4b0d91b  4.3.1      objectServer   x86\nd020c11b449b1191b9bb194a876d4e1807ecc5d0  4.3.1      objectServer   x86_64\n56e4933eef175574c15915e9ebf85c8d01365a96  4.3.1      objectServer   mips\ncb4f809d5c26c9476ed4f5f5de3ddfcfc793a95d  4.3.2      base           arm64-v8a\n24d82c3256a537451c17519ea537c4493b30e9ce  4.3.2      base           armeabi-v7a\nd1f136a38d20aaca2d7105682a8180d82b58a5a2  4.3.2      base           x86\nc2f97ceec40b0a3d3670ef58f47aa91d0be2a092  4.3.2      base           x86_64\n35de1c4ade5bd228c6bcd42ef127e1d635d9ed76  4.3.2      base           mips\n2a06ac1fda868ee667f8f28c6a91d8619091258d  4.3.2      objectServer   arm64-v8a\n6276c8cb1fd98a429eec2a2b15b73f6f15ebab04  4.3.2      objectServer   armeabi-v7a\n05c142f92b57e6722f7b11143e9de6d40afddac0  4.3.2      objectServer   x86\n0889b280e89a70b5eca6a6ce77fd7461f8e01dfd  4.3.2      objectServer   x86_64\n69ce61e24ab7a8c48d6bef983c5e9134860d395d  4.3.2      objectServer   mips\ncb4f809d5c26c9476ed4f5f5de3ddfcfc793a95d  4.3.3      base           arm64-v8a\n24d82c3256a537451c17519ea537c4493b30e9ce  4.3.3      base           armeabi-v7a\nd1f136a38d20aaca2d7105682a8180d82b58a5a2  4.3.3      base           x86\nc2f97ceec40b0a3d3670ef58f47aa91d0be2a092  4.3.3      base           x86_64\n35de1c4ade5bd228c6bcd42ef127e1d635d9ed76  4.3.3      base           mips\n2a06ac1fda868ee667f8f28c6a91d8619091258d  4.3.3      objectServer   arm64-v8a\n6276c8cb1fd98a429eec2a2b15b73f6f15ebab04  4.3.3      objectServer   armeabi-v7a\n05c142f92b57e6722f7b11143e9de6d40afddac0  4.3.3      objectServer   x86\n0889b280e89a70b5eca6a6ce77fd7461f8e01dfd  4.3.3      objectServer   x86_64\n69ce61e24ab7a8c48d6bef983c5e9134860d395d  4.3.3      objectServer   mips\ncb4f809d5c26c9476ed4f5f5de3ddfcfc793a95d  4.3.4      base           arm64-v8a\n24d82c3256a537451c17519ea537c4493b30e9ce  4.3.4      base           armeabi-v7a\nd1f136a38d20aaca2d7105682a8180d82b58a5a2  4.3.4      base           x86\nc2f97ceec40b0a3d3670ef58f47aa91d0be2a092  4.3.4      base           x86_64\n35de1c4ade5bd228c6bcd42ef127e1d635d9ed76  4.3.4      base           mips\n2a06ac1fda868ee667f8f28c6a91d8619091258d  4.3.4      objectServer   arm64-v8a\n6276c8cb1fd98a429eec2a2b15b73f6f15ebab04  4.3.4      objectServer   armeabi-v7a\n05c142f92b57e6722f7b11143e9de6d40afddac0  4.3.4      objectServer   x86\n0889b280e89a70b5eca6a6ce77fd7461f8e01dfd  4.3.4      objectServer   x86_64\n69ce61e24ab7a8c48d6bef983c5e9134860d395d  4.3.4      objectServer   mips\nefe6a8a4a1ee6934f80cc7ead90e854c17a52eb3  5.0.0      base           arm64-v8a\nc7ef2f7c8124a1daba35241854a5fb6e355c66f7  5.0.0      base           armeabi-v7a\nced9732805d65d77f17088c406f4643bbaa3d69e  5.0.0      base           x86\n8ea190f00b83e272dd828e05e52a7e04ed37b049  5.0.0      base           x86_64\n223afc4242da31a5c048d4651284347ce80b7a4c  5.0.0      base           mips\n7c77444f6a1b81464716da987d9e64f1c5a2f092  5.0.0      objectServer   arm64-v8a\nbedaeae59220283af18a8f07e780de39be51c1f2  5.0.0      objectServer   armeabi-v7a\nd6108985b50b799aef7bd81ffca52aef2f7b8df4  5.0.0      objectServer   x86\na038057df03a8fb3a02808d4b1d6255d27d4ea2e  5.0.0      objectServer   x86_64\n38ce13986721b48c4cdff16c7f50d40a7740924c  5.0.0      objectServer   mips\n286a72aa3aa89a76761abe26288edaa7020dd5af  5.0.1      base           arm64-v8a\na6d1f270486a63b27b133bfebef828444f7309fe  5.0.1      base           armeabi-v7a\n171605f28550810066ff794e8cee8ef882ac6775  5.0.1      base           x86\n35055e11ed8d46da19034d2c3eba25ccc51b182e  5.0.1      base           x86_64\n7b9aa4ae0ce95129d50ed46124a393d7348f66d9  5.0.1      base           mips\naeb29d0471df73bde03c176d1c809b17d3d096f6  5.0.1      objectServer   arm64-v8a\n76e81fa1065598d84925955263cc0ee946ec936e  5.0.1      objectServer   armeabi-v7a\nfd900568622c78a4e1abb3a3c6ca3c0681ef55ad  5.0.1      objectServer   x86\n2e26bea616a6a5ae1e94a338fe331712008b51af  5.0.1      objectServer   x86_64\na0810059a6d9127a1758deb081e9219ff5ec4161  5.0.1      objectServer   mips\na94c84d2fc1c495199d9ffd45a872e290862c727  5.1.0      base           arm64-v8a\n6cb57b0ae826acb36c80a9f50ca469f99ec3bc28  5.1.0      base           armeabi-v7a\n0b4e76a385e56077b6a29b77af4a22efaa885353  5.1.0      base           x86\n92c366c884633f9ca77c8ec7183b7d7ce87aa610  5.1.0      base           x86_64\n04ab9e3ff345c9de77f4a7baa8b8fd852e99284c  5.1.0      base           mips\n1cb4f39994689d56e75baac04f838805c6cfecc5  5.1.0      objectServer   arm64-v8a\n8e679950494d49ac737dc4c960ce47114ba00e4e  5.1.0      objectServer   armeabi-v7a\na11ef533e77e0ffaa2b3a37a2e0bcf4a8c9ab38a  5.1.0      objectServer   x86\n66e0f606c0ab4e8fa07abc2d5e1f277b7839ebc7  5.1.0      objectServer   x86_64\n9403e99bf04a66b3048e081a6762e91bb6f9f1f2  5.1.0      objectServer   mips\na94c84d2fc1c495199d9ffd45a872e290862c727  5.2.0      base           arm64-v8a\n6cb57b0ae826acb36c80a9f50ca469f99ec3bc28  5.2.0      base           armeabi-v7a\n0b4e76a385e56077b6a29b77af4a22efaa885353  5.2.0      base           x86\n92c366c884633f9ca77c8ec7183b7d7ce87aa610  5.2.0      base           x86_64\n04ab9e3ff345c9de77f4a7baa8b8fd852e99284c  5.2.0      base           mips\n1cb4f39994689d56e75baac04f838805c6cfecc5  5.2.0      objectServer   arm64-v8a\n8e679950494d49ac737dc4c960ce47114ba00e4e  5.2.0      objectServer   armeabi-v7a\na11ef533e77e0ffaa2b3a37a2e0bcf4a8c9ab38a  5.2.0      objectServer   x86\n66e0f606c0ab4e8fa07abc2d5e1f277b7839ebc7  5.2.0      objectServer   x86_64\n9403e99bf04a66b3048e081a6762e91bb6f9f1f2  5.2.0      objectServer   mips\n0197796a67051aaeed1607bed3ee6d80f40da720  5.3.0      base           arm64-v8a\nc65ac6ec233a8660c2f8dcc70a3773f03f3eb496  5.3.0      base           armeabi-v7a\nbf8e555a18a8557e422299d58a1351e82c583326  5.3.0      base           x86\n4ea4b48417e7c114d80c7d091b7ca91d9afa7925  5.3.0      base           x86_64\n1b5763a6249948b16ccb4cfa0f9fd63fd6a1507f  5.3.0      base           mips\n5c47f3a93a31cd4bfd4074475df92d72b9c072b8  5.3.0      objectServer   arm64-v8a\n0b9f2cdf2fd3e0fd47b14827d8c7e848da0650c1  5.3.0      objectServer   armeabi-v7a\nab374beba25b0856c459cdd0b40c9540a7f8432f  5.3.0      objectServer   x86\n3266d725c0a0a01a18a996708d5b9cc149c29d27  5.3.0      objectServer   x86_64\n2f2a10072ec3e5e9cd02c472d9bfaa9a778c712a  5.3.0      objectServer   mips\ne50c637939b5766cba26b2609b1e8025ce9659f4  5.3.1      base           arm64-v8a\n5de3e2ef71ec83cd765c990c9febe837be3969e4  5.3.1      base           armeabi-v7a\n578966c330f01dcb00a55120f507629ba121ac6c  5.3.1      base           x86\nc71629c71b14059aec141c735985c676c7abc751  5.3.1      base           x86_64\nbe94621730003ac74e84c6e65a625090ed4712cd  5.3.1      base           mips\nb5c2545cef2952532887414936c431c537f534f9  5.3.1      objectServer   arm64-v8a\n00110987ef3140e99de8abc76d2635d938c82dde  5.3.1      objectServer   armeabi-v7a\n61f0ec0e65a701b45b31e42baf2045977e023d06  5.3.1      objectServer   x86\neba4bb74dfc3055f83b2d3e74fc2af28be52794a  5.3.1      objectServer   x86_64\n6f684e3c2ab4f30e7020efbf908a58db64350510  5.3.1      objectServer   mips\n69168af4a85d7462075e55f4138e8feaf58f926b  5.4.0      base           arm64-v8a\n4fc34f89ec5dda5ae2aa9ff57b9651241a661e1c  5.4.0      base           armeabi-v7a\n2c2a34ebec9e3d975e1f77332465fe1ed35c2eb8  5.4.0      base           x86\n1e8d9851176657eafc81e5fe1018bb7ebe11d6bc  5.4.0      base           x86_64\nbb474c6844dba400d62a09224c84976e5ba12413  5.4.0      base           mips\n5c9c97edf6a6aeb8f87d0db433e198127a2ba81b  5.4.0      objectServer   arm64-v8a\n078260740efdad04d5913928266849dcff4e5485  5.4.0      objectServer   armeabi-v7a\ndd32ceba66b5688be345f8aee1de516376187ade  5.4.0      objectServer   x86\nc15178008a519caab9dabe637648062a51f8cca8  5.4.0      objectServer   x86_64\n486184f1cddeb4366781692eec845e641e749e14  5.4.0      objectServer   mips\n69168af4a85d7462075e55f4138e8feaf58f926b  5.4.1      base           arm64-v8a\n4fc34f89ec5dda5ae2aa9ff57b9651241a661e1c  5.4.1      base           armeabi-v7a\n2c2a34ebec9e3d975e1f77332465fe1ed35c2eb8  5.4.1      base           x86\n1e8d9851176657eafc81e5fe1018bb7ebe11d6bc  5.4.1      base           x86_64\nbb474c6844dba400d62a09224c84976e5ba12413  5.4.1      base           mips\n5c9c97edf6a6aeb8f87d0db433e198127a2ba81b  5.4.1      objectServer   arm64-v8a\n078260740efdad04d5913928266849dcff4e5485  5.4.1      objectServer   armeabi-v7a\ndd32ceba66b5688be345f8aee1de516376187ade  5.4.1      objectServer   x86\nc15178008a519caab9dabe637648062a51f8cca8  5.4.1      objectServer   x86_64\n486184f1cddeb4366781692eec845e641e749e14  5.4.1      objectServer   mips\na3d6fdf326a8cae91de2cdf72334e19b5a919c5f  5.4.2      base           arm64-v8a\n9ef0b336586a257a11a0df16c5234e4c15cda55c  5.4.2      base           armeabi-v7a\n9ed83465bed21615d32669adf205defb126fd8a1  5.4.2      base           x86\n92ea49b90dee1bc2eaf6bf240fead54d3a3cad50  5.4.2      base           x86_64\n2bbff26ae47434935f654493a0c38683800f57a0  5.4.2      base           mips\nca3e2c3699f50e42f594275d5100336108b7fc3c  5.4.2      objectServer   arm64-v8a\n342487e31b5fd46a2e8356e52db5af69dc0a69b6  5.4.2      objectServer   armeabi-v7a\n6581b75ad4c8aa0b484ec450f75654f7f3d22c4d  5.4.2      objectServer   x86\na6d1e779db1996175d4e59d4d80261ce06230b1f  5.4.2      objectServer   x86_64\n6e39e60a32a06b1ad9c294d81263b447cba4cd91  5.4.2      objectServer   mips\n6797b99673bbe8bf7983ffce1a7d4b34e921058a  5.5.0      base           arm64-v8a\n3c1e941dd91b9d0fafe0b15a194323876ad20fed  5.5.0      base           armeabi-v7a\n5815d2564a87e87675a79f6101a35c0ec3f2e418  5.5.0      base           x86\n86cd6f5bf842c0478278f4f31a60fe06ecbedf4f  5.5.0      base           x86_64\n9d856b75cc645e8cbe06d269669cba6a183c2652  5.5.0      base           mips\n4a0551ce4dfc5c2543f462f36b3faa51f10e0e4d  5.5.0      objectServer   arm64-v8a\n77dbb1fce249f1f25c3741dcee1b91c78ef60b34  5.5.0      objectServer   armeabi-v7a\ne112ffc53d3bda625175a099a1af74cc1c2907b0  5.5.0      objectServer   x86\n35466be467eef596a35e61e2118ff11d0791154a  5.5.0      objectServer   x86_64\n844a0943aa131352e60ae539889e9d369574a9a5  5.5.0      objectServer   mips\n3ee23c18ca2c989014d08119a802bed52bd83c91  5.6.0      base           arm64-v8a\nf8060930ba7778b5366b21d410959dafe17c7020  5.6.0      base           armeabi-v7a\nd8c239a4fc05f53d24d2c3cf1b6b4bdf1b8a4778  5.6.0      base           x86\ncacda107701ed974397ab0aa69085b26b7a467d5  5.6.0      base           x86_64\n0b8e89d334c478690475c4cedadb280525a6768e  5.6.0      base           mips\ncbb8d3044bb5d5919d7c856874a817c1b0876209  5.6.0      objectServer   arm64-v8a\n00855f893f0cb8bf4f47050343f191962af354a4  5.6.0      objectServer   armeabi-v7a\n470406bcf712b6a3d6260ee601ae67176f3934bc  5.6.0      objectServer   x86\n4dc141fefd4ef7477db805360c0a54f74ad0b4aa  5.6.0      objectServer   x86_64\nc49e9f6213b66f6ca4d2a5df7268d2ca9f259295  5.6.0      objectServer   mips\naab1fb3bf26a02676068a1d8acbe62eaa0cc66fb  5.7.0      base           arm64-v8a\n66b4835ab1d6984bb3d2ed878fa8c3caf4f09e89  5.7.0      base           armeabi-v7a\ne31560fb40dc2a339a541ba2587e88f0a5a5b815  5.7.0      base           x86\n11fb1141418d82b8621eea9ca8b326de9ed767e9  5.7.0      base           x86_64\nd8d6f5360fb8c4788accaa988373e0c577bf2bd9  5.7.0      base           mips\nad3c75ef61c79c606a1b1cf40d586b91b7609d50  5.7.0      objectServer   arm64-v8a\nac95444db6d6a996bc82a25ee05f4ce8d5a64a09  5.7.0      objectServer   armeabi-v7a\n40674620c31f2320f569c4f71ef1720669d61f3e  5.7.0      objectServer   x86\n2839e7a8755ca3c5ce6489887943be0dd5ec827f  5.7.0      objectServer   x86_64\n29b5b922da65c3d8277a6b8b463181b2a3a9f494  5.7.0      objectServer   mips\naab1fb3bf26a02676068a1d8acbe62eaa0cc66fb  5.7.1      base           arm64-v8a\n66b4835ab1d6984bb3d2ed878fa8c3caf4f09e89  5.7.1      base           armeabi-v7a\ne31560fb40dc2a339a541ba2587e88f0a5a5b815  5.7.1      base           x86\n11fb1141418d82b8621eea9ca8b326de9ed767e9  5.7.1      base           x86_64\nd8d6f5360fb8c4788accaa988373e0c577bf2bd9  5.7.1      base           mips\nad3c75ef61c79c606a1b1cf40d586b91b7609d50  5.7.1      objectServer   arm64-v8a\nac95444db6d6a996bc82a25ee05f4ce8d5a64a09  5.7.1      objectServer   armeabi-v7a\n40674620c31f2320f569c4f71ef1720669d61f3e  5.7.1      objectServer   x86\n2839e7a8755ca3c5ce6489887943be0dd5ec827f  5.7.1      objectServer   x86_64\n29b5b922da65c3d8277a6b8b463181b2a3a9f494  5.7.1      objectServer   mips\n3e8732298786a75eec1afbca616cf5a3b57361b3  5.8.0      base           arm64-v8a\n60e562f1965017164f5e0567d6cba3dd4b698029  5.8.0      base           armeabi-v7a\n7a1dda1f3639040a28405e6e682ec667b7fc7e9c  5.8.0      base           x86\nd39ff5f70c54bea2c3fa2e2a99f25674464f49db  5.8.0      base           x86_64\nc9065288d56ef323340da2d67702e99606a103d1  5.8.0      base           mips\n319e23674f307f59195499dc7da99e5e5b89c16f  5.8.0      objectServer   arm64-v8a\n4fd8b3c573cad634b5215f56bb17b10a477302b7  5.8.0      objectServer   armeabi-v7a\n2568686bf1a100210dc6b74ec23ceecc2fe04607  5.8.0      objectServer   x86\n0e2cd3baf8b03d87a987f8e4a6bd8caed4645487  5.8.0      objectServer   x86_64\nbc2e7af8862b3f266e13508ddcb9ae081f479d42  5.8.0      objectServer   mips\n7b673c6467b20a7368997360277c6ca103d61b11  5.9.0      base           arm64-v8a\n46960acc13dc953cd1cab6cedbcde0963a3dcd16  5.9.0      base           armeabi-v7a\nf920cd63618e7bba28751fdb673dac95c7fa2149  5.9.0      base           x86\nb977428e1d23efa4cc9c2cf07c8aea915ec89523  5.9.0      base           x86_64\nae4d5916c5d6568748ad555769dfd37512567e8b  5.9.0      base           mips\n0efb752be4b4b9fd0f6b136cf364038f91dd5912  5.9.0      objectServer   arm64-v8a\n4107124df7c8990a2c8ee212ba025c936693b1d9  5.9.0      objectServer   armeabi-v7a\n1b9780342d5d1f8630d1c7549382682ccd389cd2  5.9.0      objectServer   x86\n4379d339aa5d6d2785568c0fe80a4891e39dd7ba  5.9.0      objectServer   x86_64\n86b6a827c9cebd10937f0e9af957830a8c213bf1  5.9.0      objectServer   mips\n3173993aab45a2a1b63290d2f57199a4e0cbdacd  5.9.1      base           arm64-v8a\n04211f2d06ed261207554390df184adf859cfe73  5.9.1      base           armeabi-v7a\nc14a94a306af1e78eee8eac4d3438830f238a472  5.9.1      base           x86\n3e498a88d9e3cc561366cffc60fa600fce32f47b  5.9.1      base           x86_64\n89042b3d4d7a4b878f1146b0390adf8b5cbeec18  5.9.1      base           mips\nf3dcef96981dad23629e4efd863416a0a736ef50  5.9.1      objectServer   arm64-v8a\nf18486cb5187b2f01fd84eaaee26dfd4c52d8a8b  5.9.1      objectServer   armeabi-v7a\nb0967844835ffca8206a18d8dc852d000441fcf3  5.9.1      objectServer   x86\n0569d27f1b8d675a3ffd996a2c0fd18d1b477f99  5.9.1      objectServer   x86_64\nc28679c757f8a5acdca0e74de449916ef99ef45d  5.9.1      objectServer   mips\n28993304f29958eabff77905f4a2e7cc519b5a43  5.10.0     base           arm64-v8a\n725cf5d235a0166efb1364e759811e7c35c6e9d5  5.10.0     base           armeabi-v7a\nae469a9d55fc5f70f916eac4bd8a9370ddaed992  5.10.0     base           x86\n7acdf3750fc7bdea76ffbd7217b66e71a9e2c1b9  5.10.0     base           x86_64\nbff1373b3bcfee383e0557677034708107f0bc76  5.10.0     base           mips\ne655893666ac2b95546d4b63c12e23773fd2f2a8  5.10.0     objectServer   arm64-v8a\nd148a33a38d764c21c28082429449c8972972921  5.10.0     objectServer   armeabi-v7a\nddb720161992f122af6aac45e274901a9c9dc74e  5.10.0     objectServer   x86\nb53d779ecfa77316d2f33999c816c39579faa6c8  5.10.0     objectServer   x86_64\ne28dd5dbfc0073c3f1459f0ba45a40276c6ab7ab  5.10.0     objectServer   mips\n0bddf47aa440b1d0159bc32a567157d4bd6a2a05  5.11.0     base           arm64-v8a\nd4babff3d01b2f25a3d4bc6ffefb43b0b33eb763  5.11.0     base           armeabi-v7a\n5d5759457d78d173d3faaf94ab971b1aacfd16cd  5.11.0     base           x86\ncc6c0582205077e8332aeebf53ec78fb9ed2b7df  5.11.0     base           x86_64\ne0fc24beed6ed37502b351752aa38fa39de5e269  5.11.0     base           mips\nc7aeabcb675f23be59f696e0a12c28d2c0ed418a  5.11.0     objectServer   arm64-v8a\n4f0e44342f2c12ec101489c641543d79a496b7f8  5.11.0     objectServer   armeabi-v7a\neec9e5ad8e9287df942c9f59b7f6dbe86c5aa11c  5.11.0     objectServer   x86\na52637d4dd6d3bc0c33012ca2c269b5d2418d616  5.11.0     objectServer   x86_64\n383b7fcc067161559862426fbfe08b18a275c5fa  5.11.0     objectServer   mips\n781996d954ad722bd677ea035ed1f6f08f56fc81  5.12.0     base           arm64-v8a\n05147213d4f6cc07b6b859010e8b0ff6f14a2337  5.12.0     base           armeabi-v7a\ne8c51e6e4b760c54e0147e21a8dad81a4426541c  5.12.0     base           x86\nb84c125833e419e6cb698ca37c9a8637a12ca715  5.12.0     base           x86_64\n530a1fefa5e4ebb88069b1fc5a25e641e3b23710  5.12.0     base           mips\n6f93525fbbf540baa96c6a1a0fbad1252f94e967  5.12.0     objectServer   arm64-v8a\n4753a514fb4dd93f97c859b81cc730931131069f  5.12.0     objectServer   armeabi-v7a\n25821d6c14af934c3ee57c855d1788576a5c71a5  5.12.0     objectServer   x86\nf93ba396d11b3c8fdb3bd3fe647e5d173632c778  5.12.0     objectServer   x86_64\nee63d95f25a3e4fecee19aca05870c8894337bf5  5.12.0     objectServer   mips\n1f1fe51131249e5edbf23d2a00319feefda56d67  5.13.0     base           arm64-v8a\nc3f622f845ea01e4f42e5c9195c4096b5e476ec4  5.13.0     base           armeabi-v7a\n86e597ce43319127e80c08329eee58df8d6479fe  5.13.0     base           x86\nfc6c6e8d6617c2f79fc84207c85443cba0eb38f9  5.13.0     base           x86_64\n6a31802a9b2cd1c11eff409e6867839a0911f0e0  5.13.0     base           mips\n6a98ffc44b6001faca0a83151759bc337997940b  5.13.0     objectServer   arm64-v8a\n54a12f219e551da2fd7a71a12a89c4aa76d40dc5  5.13.0     objectServer   armeabi-v7a\n078e069fa7c89410b164fedc2dcee57307c22a83  5.13.0     objectServer   x86\n5b2ad6663a754989f28d6f75cef1b8f4f550bb0f  5.13.0     objectServer   x86_64\n870f7d4731b8d7de64445a13b35d7a14604b391c  5.13.0     objectServer   mips\n2bb57fa01fcf071210c4c688222886740a6ee9b2  5.13.1     base           arm64-v8a\n0acb4023c7d3cc99ee0bad8744702b89c227bec7  5.13.1     base           armeabi-v7a\n1e2dfc165128adf0cb79a33a096d9ae22fa916b9  5.13.1     base           x86\nca9d486fbf48eea9a0b278dfc9ff7edb5da4ed49  5.13.1     base           x86_64\n5f2265a2e04e766657076a367f29ef30ae076322  5.13.1     base           mips\n7122057417fd0949b4b556983da7ba0a66eb22d2  5.13.1     objectServer   arm64-v8a\n03a48e6ad8996473bc3d800ee9cbe4bcd7ce725f  5.13.1     objectServer   armeabi-v7a\n6ad4c0c98f87a998bc5f20a187ce2e5d0fc38f41  5.13.1     objectServer   x86\n57da4db0773d5bddf7abc7240af62c30b8326b82  5.13.1     objectServer   x86_64\n578eb3701d0073b775c3146a51de6f2bb8931606  5.13.1     objectServer   mips\n16836090c1f0aacbe9ba40e4123c254d1426a460  5.15.0     base           arm64-v8a\n3ca19416c6b4e6a6d2319bd68464c851bcc9a159  5.15.0     base           armeabi-v7a\n4665ec032ae50a55d6295eea2bf0fbbf0c61298d  5.15.0     base           x86\n0aa51fb88113e2d5b7765649ea4458b62ffa1dcd  5.15.0     base           x86_64\n4d107844befad141481502e0608dba0572c1a8a4  5.15.0     base           mips\ne325897e07f6464138c597aa9e6ea80e6ce480d0  5.15.0     objectServer   arm64-v8a\nf796bf40d2c51a7e43e0133e622a95e8bb70fed6  5.15.0     objectServer   armeabi-v7a\ne919cda4f89d7aaa2aa1f8fa2d2a1f9cfe4f5762  5.15.0     objectServer   x86\nbdeaa68aad504dbe147789d5dd8ac985026cf085  5.15.0     objectServer   x86_64\nf62ba4b56778548c0a7ae9ee2ae655be9b6d95a7  5.15.0     objectServer   mips\n16836090c1f0aacbe9ba40e4123c254d1426a460  5.15.1     base           arm64-v8a\n3ca19416c6b4e6a6d2319bd68464c851bcc9a159  5.15.1     base           armeabi-v7a\n4665ec032ae50a55d6295eea2bf0fbbf0c61298d  5.15.1     base           x86\n0aa51fb88113e2d5b7765649ea4458b62ffa1dcd  5.15.1     base           x86_64\n4d107844befad141481502e0608dba0572c1a8a4  5.15.1     base           mips\ne325897e07f6464138c597aa9e6ea80e6ce480d0  5.15.1     objectServer   arm64-v8a\nf796bf40d2c51a7e43e0133e622a95e8bb70fed6  5.15.1     objectServer   armeabi-v7a\ne919cda4f89d7aaa2aa1f8fa2d2a1f9cfe4f5762  5.15.1     objectServer   x86\nbdeaa68aad504dbe147789d5dd8ac985026cf085  5.15.1     objectServer   x86_64\nf62ba4b56778548c0a7ae9ee2ae655be9b6d95a7  5.15.1     objectServer   mips\n00148e37ca2d0eb9a73ff48909a15a181c3134eb  5.15.2     base           arm64-v8a\nc8b182b6351ccb1d9fca9c559bb91f17ad776553  5.15.2     base           armeabi-v7a\n35a796942fb16cc920d3cebbbcff860b79e22eac  5.15.2     base           x86\n1acdb3525b6212580bba8b65c2acbce448e28d84  5.15.2     base           x86_64\n3a2b076710bb3c311a4ef793f86d80b45bca7e3c  5.15.2     base           mips\n11a7f453fffaa0b1a0d31c62d33adf23d5817850  5.15.2     objectServer   arm64-v8a\n8fddcd6f0ca39636e69518d93eeb21d478734bf8  5.15.2     objectServer   armeabi-v7a\n7bfaf1333c2aaa6803afdaac470b1278db9a264d  5.15.2     objectServer   x86\n735fab73fb153cfd32dabf0af34dff041d01d4cd  5.15.2     objectServer   x86_64\n9d56ec9219e2a584ad3a44536d615bf89e1af810  5.15.2     objectServer   mips\n00148e37ca2d0eb9a73ff48909a15a181c3134eb  6.0.0      base           arm64-v8a\nc8b182b6351ccb1d9fca9c559bb91f17ad776553  6.0.0      base           armeabi-v7a\n35a796942fb16cc920d3cebbbcff860b79e22eac  6.0.0      base           x86\n1acdb3525b6212580bba8b65c2acbce448e28d84  6.0.0      base           x86_64\n3a2b076710bb3c311a4ef793f86d80b45bca7e3c  6.0.0      base           mips\n11a7f453fffaa0b1a0d31c62d33adf23d5817850  6.0.0      objectServer   arm64-v8a\n8fddcd6f0ca39636e69518d93eeb21d478734bf8  6.0.0      objectServer   armeabi-v7a\n7bfaf1333c2aaa6803afdaac470b1278db9a264d  6.0.0      objectServer   x86\n735fab73fb153cfd32dabf0af34dff041d01d4cd  6.0.0      objectServer   x86_64\n9d56ec9219e2a584ad3a44536d615bf89e1af810  6.0.0      objectServer   mips\n6ecf79bef50b090879283c0bea687d0e6ea866c2  6.0.1      base           arm64-v8a\n33ecfb5b32822008bbcf95808398751bf7e6fd9d  6.0.1      base           armeabi-v7a\n62bbbb8be21cb47c75db2a0cdbd5f2d68daa485c  6.0.1      base           x86\n27f15f095cf622a3d56da982e89c8cf7cb97e7d9  6.0.1      base           x86_64\n5b5cfbd21529f2b70a6c7c469fc0a435a0d72b5a  6.0.1      base           mips\ne696c41c5ea6fd1ad99d93463175aaadf16131f9  6.0.1      objectServer   arm64-v8a\n5cd4aea59b17c7724cc08b1c9ab9231916e7c908  6.0.1      objectServer   armeabi-v7a\nb10fef4f5b15cf580b8f4e53bcd6d67a3d91318a  6.0.1      objectServer   x86\n52f0fd2f919d9a0f61c1010746605473f87ad735  6.0.1      objectServer   x86_64\ne9d5eb1f4eef65628ba82b58ecdbff6300f457c0  6.0.1      objectServer   mips\n5b9dff361dcb1f1322c7035b0e6440cc7cb3beec  6.0.2      base           arm64-v8a\n32e82ff169ea73a22b34c2ea93d7c55049d52b8a  6.0.2      base           armeabi-v7a\ne437e80414fe7465c450bc42d6da4e1671d742a1  6.0.2      base           x86\n6456496b047c40dfe1bbbe6be5ced79fc0f2406b  6.0.2      base           x86_64\n4eb1315cd8287d6b6600b4fa73d01063b95e932d  6.0.2      base           mips\nbe4cd8f47bb0e931beac38848495ff705a98a28c  6.0.2      objectServer   arm64-v8a\nc7d9c18d8ec7dfc696c287c7688097d905d7d085  6.0.2      objectServer   armeabi-v7a\ncc52086189e53e3e0353fb9f36a3ce9a8acbc32f  6.0.2      objectServer   x86\n2a1d4918d659c74bf51e7ff207bc3e22b1b7fd57  6.0.2      objectServer   x86_64\nd23d1162f199b9967cfe2fa266703e61d8e9d9fe  6.0.2      objectServer   mips\n118fda452fd9079577f8b14ae36b3cf1e9352cd8  6.1.0      base           arm64-v8a\n37e790b2f0e34574752350d9d6c5e637197beca6  6.1.0      base           armeabi-v7a\n4a35e2420941953ed01dcf75089f9378c121d8a4  6.1.0      base           x86\n01aac74176b6b1922e808c6bf332c2253e84f588  6.1.0      base           x86_64\n3d95035db336a067df8de42bfde3853394ce006a  6.1.0      base           mips\nf5245a8707390aab6cefbc53deb03dd4a201600c  6.1.0      objectServer   arm64-v8a\n486ac37f0d5f1b7bf7700307d92846e33e7fa30e  6.1.0      objectServer   armeabi-v7a\nb53c04f747c89519a9b35c0ace8f291ea51e2914  6.1.0      objectServer   x86\n13f420198cffeade0c19007b7c89d7487142facf  6.1.0      objectServer   x86_64\n780a8f3446d29c5a837b4a05856e0103cbfa6fcb  6.1.0      objectServer   mips\nc272926de4c595cfe1f6ca4c775498e94dba884a  6.1.1      base           arm64-v8a\n2c46d6ebb75985e41e18368e4cc743c68458d19a  6.1.1      base           armeabi-v7a\n1e063192e5ab5f1431b2a1e3e3db936a59605cb6  6.1.1      base           x86\ndb1a20b0137523251f795c228c33c453601688ad  6.1.1      base           x86_64\naf9f000dcbebb82ee6005d923efb7ce8191a89dd  6.1.1      base           mips\n45e05a486f988a9464cf68d7f9dc22d5c7881490  6.1.1      objectServer   arm64-v8a\n9e52ae5ce525edb54dabb5bae17454457df5ae30  6.1.1      objectServer   armeabi-v7a\n1494fb4ec374937c8c7e20d69e006c7aeacfdbf0  6.1.1      objectServer   x86\n1f91aaae6699758ea63c97f81d4f904cff717cac  6.1.1      objectServer   x86_64\n8fc043dac1613de9ce0962dfbe633089787c972d  6.1.1      objectServer   mips\n3d91652012c7960b4230739d519e3109f298484b  7.0.0      base           arm64-v8a\ne381fc094143f45e80ab4630d5a6afa3094da4c2  7.0.0      base           armeabi-v7a\n2a43fa0cb656a9e293f208d977c389d882fb53ef  7.0.0      base           x86\n030ecd2f13cce774c17128decb654cab98c12c16  7.0.0      base           x86_64\n89b615e8b20893ff93fadd4015c02971a7c559b9  7.0.0      objectServer   arm64-v8a\n9e4c58df280913e7221e34bc6633c666eb1849b5  7.0.0      objectServer   armeabi-v7a\n4ba72c503fe021ca54d7f918e04163063b9a03b7  7.0.0      objectServer   x86\neb9801d78141543cf61222736805dd3f5c93bba4  7.0.0      objectServer   x86_64\ne40ca2fe74c1a4778f371d2fb07ae692cc14e133  7.0.1      base           arm64-v8a\nf6a0c741122fc950722186b7ad6f686357c6ecc6  7.0.1      base           armeabi-v7a\ncf4835a0884696daa85079c4ae786f0bd6d8a360  7.0.1      base           x86\n12d3f19a7c5356a077d7ba0f21424cdd00f35a68  7.0.1      base           x86_64\n1707a0a68dd9129d0fe8f2be19824930861cb04a  7.0.1      objectServer   arm64-v8a\n404f02ef88247a3dca229daa2ca7bfb93a3a3dc0  7.0.1      objectServer   armeabi-v7a\n8056aa1954aaf88160f4cce7fd93c4597d6538b5  7.0.1      objectServer   x86\n77e4758faed7858e262db407e5e8b2cda82f8486  7.0.1      objectServer   x86_64\n04926858a1a347390f7b63cd2087113180457b0d  7.0.2      base           arm64-v8a\n6f1982aab698b265f4868b1cab61382520803c75  7.0.2      base           armeabi-v7a\n5420e9610f8ba107f69ccf0d1ad54c87fe49891a  7.0.2      base           x86\n09140f46d9e6dd0e9262a0094ba1acabac12af22  7.0.2      base           x86_64\nff0ee7035c30ec4d6c421952890e39ba7fbd21ff  7.0.2      objectServer   arm64-v8a\nab617f444af8dc5f3b8a37fd22dd39198bf1a6a8  7.0.2      objectServer   armeabi-v7a\n27f528af6fd4c91965a85f8d2527ee7210e96bf1  7.0.2      objectServer   x86\na876d3c58a0a83d0377a8e589618721830f900bb  7.0.2      objectServer   x86_64\nfad07531822f9d30927d0dd27bb0f7741820d065  7.0.3      base           arm64-v8a\n6cccec6cdd95eaaa6c547760f39855c772847c4b  7.0.3      base           armeabi-v7a\n2b5388098830c910e0c42d4b925c27fcaad80308  7.0.3      base           x86\n2f7e6260f56100a6135c380f4dfb1e9702b50429  7.0.3      base           x86_64\nc68f5f7f963ec030b51ebec40d8c7796fb7dee0e  7.0.3      objectServer   arm64-v8a\n45eb36fd0caff3e5785aaea3fd73d3dd07388f71  7.0.3      objectServer   armeabi-v7a\ne65bd8f5ef8adbc7a6785460dbf96bfad6b6264e  7.0.3      objectServer   x86\n3b735e37037811a4e3ff674aab8fde14f49cd5be  7.0.3      objectServer   x86_64\n641545f5c0c5c3db059f72739aa394a96469d7e5  7.0.4      base           arm64-v8a\n04a07890a7e5bcb91fc94f3e3f739941c151ae14  7.0.4      base           armeabi-v7a\ncfa6dd2f3d3041e8e62bf86f3b5470cc924d2154  7.0.4      base           x86\n99563e02cdc6cfd0c2f58aeae7a2bbf039cbb022  7.0.4      base           x86_64\n8f10b578d8b8b0da123c2da0dabbb39776fed731  7.0.4      objectServer   arm64-v8a\nd8494528e932aac5168ae3b82552c15e40b62a8f  7.0.4      objectServer   armeabi-v7a\nb817076cfb132629e588916241f503321231c1ac  7.0.4      objectServer   x86\nca612c4231937462a12ef9ae118994c35c61dcee  7.0.4      objectServer   x86_64\n0fc26039a9764065cd135afc2a81cf35a28643f5  7.0.5      base           arm64-v8a\n6b8b93b203b3507a232bf7f1816a6878f02f7619  7.0.5      base           armeabi-v7a\n3da54c105eb4fde9166d07d173f9d01a5087fa89  7.0.5      base           x86\nb240cab12d731cf411a319c1a0dea2c6c037d0d2  7.0.5      base           x86_64\n207866cc86e91941a92e608a4faea9bd2ba3dfd6  7.0.5      objectServer   arm64-v8a\nb56de31072b8d59b8ba5b0192258afb8e7095bb9  7.0.5      objectServer   armeabi-v7a\n464ff8dcca12382101c7e1ce56b8e38910a1b7b8  7.0.5      objectServer   x86\n2b5ff876e4fa58f3c7f6ac7995008df64a33c4aa  7.0.5      objectServer   x86_64\n04085ef2c78968ee54966e6637d7595f9fbe5902  7.0.6      base           arm64-v8a\nb20acc7e18428497ad7096f513bea1ee13068ade  7.0.6      base           armeabi-v7a\n54dfbe154c12d5e41a015ebf71e29500f4be8209  7.0.6      base           x86\n539c180c91acec6039f79ece8b2352a90a65e51b  7.0.6      base           x86_64\n50148d9b0707e539eef251e35ed29c184952fc6d  7.0.6      objectServer   arm64-v8a\n0380e6cf50dc3f9bcd191a732d42953799614536  7.0.6      objectServer   armeabi-v7a\n500c65a7f4f98a62acbb575425a9952c3bc0ddef  7.0.6      objectServer   x86\n11b696afdaefd33c805e3c217619b0ffcc84822c  7.0.6      objectServer   x86_64\n67ddb8168386db954b4128e2aefb98c1788f3246  7.0.7      base           arm64-v8a\nb0df75593ce21d741617d17ca12369f642810407  7.0.7      base           armeabi-v7a\nf96de4a78bc923928dfd894b3a3ac783341d85aa  7.0.7      base           x86\n0f185cc0b155d64eff5d00aa9320d6f30e75db3b  7.0.7      base           x86_64\n47ed218ee97554e281ec8c27b98963ba4210ab00  7.0.7      objectServer   arm64-v8a\n639ca3e17850a8fab8109ecc76b9b49b51a4fb8e  7.0.7      objectServer   armeabi-v7a\n63f9db34e10bf0e05757eed68d02b5c5de5a04ee  7.0.7      objectServer   x86\n6c806f36ad626d1ef65b8d68443dc919effdb5cc  7.0.7      objectServer   x86_64\n11dc6479abcde8f62b9ea7730a25c8ed50878505  7.0.8      base           arm64-v8a\n0b63a0fd7956d7c5fc96db3dc0d31b95d61e45bd  7.0.8      base           armeabi-v7a\nd9180a331451030e3207e9ec945f27b5ab60ef33  7.0.8      base           x86\n8f63962259b643dd35ee2e3f80a1fbbd63490ca1  7.0.8      base           x86_64\n2cef5a385c59021752792a74893bed694a2e8b6e  7.0.8      objectServer   arm64-v8a\n6810bbede740d243fa8ffab63e5b1c6876830bc8  7.0.8      objectServer   armeabi-v7a\n01b801d833501e87c6503884f181d95ef732d159  7.0.8      objectServer   x86\n8d6b858cd05c281f9bfb617f06867b3080ad20c5  7.0.8      objectServer   x86_64\nf34809b29072e1a06c9f255c314e804b8332faff  10.0.0     base           arm64-v8a\n07c0e801c7453bdbbb0834e5c2638f9e57a93749  10.0.0     base           armeabi-v7a\n00383e8ac38365b37446f434bc612333b860c5d4  10.0.0     base           x86\n718ba75c392d7fc019b0298f148d452d7b84ffb1  10.0.0     base           x86_64\n62328b10bfe4219788ddf32564c8c83af7925f40  10.0.0     objectServer   arm64-v8a\nbad1baa7188ecb5f834f987b738fb5e0ccc3a743  10.0.0     objectServer   armeabi-v7a\ne0132cdacb85286e1e84ea133ccb8861189a9230  10.0.0     objectServer   x86\n6fbd359b51ea7a3d144aba3cabd622ea700a1648  10.0.0     objectServer   x86_64\n6ad7f63d64a38561c8e8c41f3d5d36021f8749c5  10.0.1     base           arm64-v8a\n643172294713a34613df12f1d498fd07a9b94697  10.0.1     base           armeabi-v7a\n13852f70e0c8cdbdf6051cf41dd9f645542a737d  10.0.1     base           x86\n446f80e54d08907404fa5380b38a67e54eb63f34  10.0.1     base           x86_64\ncfb52829d58d436d29bf99ec9d8ebae325f15640  10.0.1     objectServer   arm64-v8a\n8ad9d09f944fe26c56aa0fd2f0d2948de6cc70c9  10.0.1     objectServer   armeabi-v7a\n14e7a11b2ef57168d330c9e716f54a8bd7fc6c5a  10.0.1     objectServer   x86\nf6f435e47f7b1077294310a34644a234a7852436  10.0.1     objectServer   x86_64\nedaa9a872118e03c3e598f77c5a1f50e4262a9e5  10.1.0     base           arm64-v8a\ne397bafe88e5791e3b11e9a5a3482841599eff4f  10.1.0     base           armeabi-v7a\n72d3fdfad899402900cb93d7dd7452c92e31bf1d  10.1.0     base           x86\n3c5428a7819234e958149cbe84da4cb0662cf8d7  10.1.0     base           x86_64\n456bc9021d4aa298ec2d2ec4d071ce45a2c21c68  10.1.0     objectServer   arm64-v8a\naed42b775e46d3541e0f3bca76117d1ffc56e3ec  10.1.0     objectServer   armeabi-v7a\n4d247ea26ed2dc77dcbe97829c7e00bdd12ee1e4  10.1.0     objectServer   x86\n39ab8bd1fe51fddb2960eb1b281b6a107251d564  10.1.0     objectServer   x86_64\n1349e2a69e08a45951c3c23865c43f0ef82362ae  10.1.1     base           arm64-v8a\nd51e55d5ef5ab681140c16807ddb5531b01d263a  10.1.1     base           armeabi-v7a\n30adfa2d11be1edd87b18e0fd4c8c5adc40ba797  10.1.1     base           x86\n1c8a1153054c0de70667b34cb4c1a1b5099cfa5c  10.1.1     base           x86_64\n28e3385beaa312c2b013575e9f94004cd8047589  10.1.1     objectServer   arm64-v8a\n9ea561bec0574e9b8ca76a7fd7695b26599ce304  10.1.1     objectServer   armeabi-v7a\n82479063691754c0002cad8f33c514803c8f0fb2  10.1.1     objectServer   x86\n09d782def54428178f03698b4237b45691aead8e  10.1.1     objectServer   x86_64\n1349e2a69e08a45951c3c23865c43f0ef82362ae  10.1.2     base           arm64-v8a\nd51e55d5ef5ab681140c16807ddb5531b01d263a  10.1.2     base           armeabi-v7a\n30adfa2d11be1edd87b18e0fd4c8c5adc40ba797  10.1.2     base           x86\n1c8a1153054c0de70667b34cb4c1a1b5099cfa5c  10.1.2     base           x86_64\n28e3385beaa312c2b013575e9f94004cd8047589  10.1.2     objectServer   arm64-v8a\n9ea561bec0574e9b8ca76a7fd7695b26599ce304  10.1.2     objectServer   armeabi-v7a\n82479063691754c0002cad8f33c514803c8f0fb2  10.1.2     objectServer   x86\n09d782def54428178f03698b4237b45691aead8e  10.1.2     objectServer   x86_64\n951e3e0e28a34dbfa9c2e2a189a530c85c3fb2a0  10.2.0     base           arm64-v8a\n6b7c8e279d9f7067cb08255cf0697a0890cd49e4  10.2.0     base           armeabi-v7a\n2ccd4f81c8ee90899492da22153e267de6030153  10.2.0     base           x86\nc6ff79c510674a7c879f7e15b2069b3ad4b6aaf1  10.2.0     base           x86_64\n58fc6b9cff9a81344fae7e22268dc9e0552e0931  10.2.0     objectServer   arm64-v8a\n94ac0d659ef4bf80dbf195d04974aded9c28c583  10.2.0     objectServer   armeabi-v7a\n3f974a3926819edeb8f698f7bae3ec5346851a79  10.2.0     objectServer   x86\nba51c3045053fa20b1f8c8d5f6d0ca46eab08e68  10.2.0     objectServer   x86_64\n3a49576469b671ff8da4450db8ad2fe9baa33e49  10.3.0     base           arm64-v8a\nd6c5ace51236482ebd15ebfe2d38f31cac54fdca  10.3.0     base           armeabi-v7a\nd3f03616f796e75bf93b8b31b8a4eba57ee21ef5  10.3.0     base           x86\n24dbf0ad4b7f409cea5b75918509ab0e6e9bebfe  10.3.0     base           x86_64\na46079aacee9c295aa2b2162bfc55e937ee15bb2  10.3.0     objectServer   arm64-v8a\n878a1bac66599e62507b8a7cda2e71e68db90f65  10.3.0     objectServer   armeabi-v7a\nfd8dcf015ec36b01d21d2c9914ac42ebb3fcb8c1  10.3.0     objectServer   x86\n4d312f1f75a677d35a9b334d20e423f5b79b604f  10.3.0     objectServer   x86_64\n3a49576469b671ff8da4450db8ad2fe9baa33e49  10.3.1     base           arm64-v8a\nd6c5ace51236482ebd15ebfe2d38f31cac54fdca  10.3.1     base           armeabi-v7a\nd3f03616f796e75bf93b8b31b8a4eba57ee21ef5  10.3.1     base           x86\n24dbf0ad4b7f409cea5b75918509ab0e6e9bebfe  10.3.1     base           x86_64\na46079aacee9c295aa2b2162bfc55e937ee15bb2  10.3.1     objectServer   arm64-v8a\n878a1bac66599e62507b8a7cda2e71e68db90f65  10.3.1     objectServer   armeabi-v7a\nfd8dcf015ec36b01d21d2c9914ac42ebb3fcb8c1  10.3.1     objectServer   x86\n4d312f1f75a677d35a9b334d20e423f5b79b604f  10.3.1     objectServer   x86_64"
  },
  {
    "path": "tools/fix-h1s.sh",
    "content": "#!/bin/bash -ex\n\nusage() {\ncat <<EOF\nUsage: $0 <javadoc-root-dir>\nEOF\n}\n\nif [ \"$#\" -ne 1 ] ; then\n  usage\n  exit 1\nfi\n\n# Assume Dokka has been run\npushd $1\n\nfind . -name \"*.html\" | while read ln\ndo\n  # Make the output SEO friendly by converting the \"h2\" title to the proper \"h1\"\n  sed -i -e 's|<h2\\(.* class=\"title\".*\\)</h2>|<h1\\1</h1>|' \"$ln\"\ndone\nfind . -iname \"*.html-e\" | xargs rm || true\n\npopd\n"
  },
  {
    "path": "tools/publish_release.sh",
    "content": "#!/bin/sh\n\n# Script that make sure release build is correctly published in the appropriate channels.\n#\n# The following steps are executed:\n#\n# 1. Check that version in version.txt matches git tag which indicate a release.\n# 2. Check that the changelog has a correct set date.\n# 3. Build Javadoc\n# 4. Upload all artifacts to Maven Central without releasing them.\n# 5. Verify that all artifacts have been uploaded, then release all of them at once.\n# 6. Upload native debug symobols and update latest version number on S3.\n# 7. Upload Javadoc to MongoDB Realm S3 bucket.\n# 8. Notify #realm-releases and #realm-java-team-ci about the new release.\nset -e\n\n######################################\n# Input Validation\n######################################\n\nusage() {\ncat <<EOF\nUsage: $0 <maven_central_user> <maven_central_key> <realm_s3_access_key> <realm_s3_secret_key> <docs_s3_access_key> <docs_s3_secret_key> <slack-webhook-releases-url> <slack-webhook-java-ci-url> <gradle-build-params>\nUsage: $0 verify\nEOF\n}\n\nif [ \"$#\" -ne 9 ] && [ \"$1\" != \"verify\" ]; then\n  usage\n  exit 1\nfi\n\n######################################\n# Define Release steps\n######################################\n\nHERE=$(dirname `realpath \"$0\"`)\nREALM_JAVA_PATH=\"$HERE/..\"\nRELEASE_VERSION=\"\"\nMAVEN_CENTRAL_USER=\"$1\"\nMAVEN_CENTRAL_KEY=\"$2\"\nREALM_S3_ACCESS_KEY=\"$3\"\nREALM_S3_SECRET_KEY=\"$4\"\nDOCS_S3_ACCESS_KEY=\"$5\"\nDOCS_S3_SECRET_KEY=\"$6\"\nSLACK_WEBHOOK_RELEASES_URL=\"$7\"\nSLACK_WEBHOOK_JAVA_CI_URL=\"$8\"\nGRADLE_BUILD_PARAMS=\"$9\"\n\nabort_release() {\n  # Reporting failures to #realm-java-team-ci is done from Jenkins\n  exit 1\n}\n\ncheck_env() {\n  echo \"Checking environment...\"\n\n  # Try to find s3cmd\n  path_to_s3cmd=$(type s3cmd)\n  if [ -x \"$path_to_s3cmd\" ]\n  then\n    echo \"Cannot find executable file 's3cmd'. Aborting.\"\n    abort_release\n  fi\n\n  # Try to find git\n  path_to_git=$(type git)\n  if [ -x \"$path_to_git\" ]\n  then\n    echo \"Cannot find executable file 'git'. Aborting.\"\n    abort_release\n  fi\n\n  echo \"Environment is OK.\"\n}\n\nverify_release_preconditions() {\n  echo \"Checking release branch...\"\n  gitTag=`git describe --tags | tr -d '[:space:]'`\n  version=`cat $REALM_JAVA_PATH/version.txt | tr -d '[:space:]'`\n\n  if [ \"v$version\" = \"$gitTag\" ]\n  then\n    RELEASE_VERSION=$version\n    echo \"Git tag and version.txt matches: $version. Continue releasing.\"\n  else\n    echo \"Version in version.txt was '$version' while the branch was tagged with '$gitTag'. Aborting release.\"\n    abort_release\n  fi\n}\n\nverify_changelog() {\n  echo \"Checking CHANGELOG.md...\"\n  query=\"grep -c '^## $RELEASE_VERSION ([0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9])' $REALM_JAVA_PATH/CHANGELOG.md\"\n\n  if [ `eval $query` -ne 1 ]\n  then\n    echo \"Changelog does not appear to be correct. First line should match the version being released and the date should be set. Aborting.\"\n    abort_release\n  else\n    echo \"CHANGELOG date and version is correctly set.\"\n  fi\n}\n\ncreate_javadoc() {\n  echo \"Creating JavaDoc...\"\n  cd $REALM_JAVA_PATH\n  eval \"./gradlew javadoc $GRADLE_BUILD_PARAMS --stacktrace\" \n  eval \"./tools/fix-h1s.sh realm/realm-library/build/docs/javadoc/\"\n  cd $HERE\n}\n\nupload_to_mavenCentral() {\n  echo \"Releasing on MavenCentral\"\n  cd $REALM_JAVA_PATH\n  # FIXME: Closing and releasing doesn't currently work as the plugin doesn't handle uploads from multiple projects very well. So we might end up\n  # with half a release. For this reason we must manually close and release the artifacts using the Maven Central UI:\n  # https://oss.sonatype.org/#stagingRepositories\n  # ./gradlew mavenCentralUpload closeAndReleaseStagingRepository -PossrhUsername=$MAVEN_CENTRAL_USER -PossrhPassword=$MAVEN_CENTRAL_KEY --stacktrace\n  eval \"./gradlew mavenCentralUpload $GRADLE_BUILD_PARAMS -PossrhUsername='$MAVEN_CENTRAL_USER' -PossrhPassword='$MAVEN_CENTRAL_KEY' --stacktrace\"\n  cd $HERE\n}\n\nupload_debug_symbols() {\n  echo \"Uploading native debug symbols...\"\n  cd $REALM_JAVA_PATH\n  ./gradlew distribute -PREALM_S3_ACCESS_KEY=$REALM_S3_ACCESS_KEY -PREALM_S3_SECRET_KEY=$REALM_S3_SECRET_KEY --stacktrace\n  cd $HERE\n}\n\nupload_javadoc() {\n  echo \"Uploading docs...\"\n  cd $REALM_JAVA_PATH\n  ./gradlew uploadJavadoc -PSDK_DOCS_AWS_ACCESS_KEY=$DOCS_S3_ACCESS_KEY -PSDK_DOCS_AWS_SECRET_KEY=$DOCS_S3_SECRET_KEY --stacktrace\n  cd $HERE\n}\n\nnotify_slack_channels() {\n  echo \"Notifying Slack channels...\"\n\n  # Read first . Link is the value with \".\",\")\",\"(\" and space removed.\n  command=\"grep '$RELEASE_VERSION' $REALM_JAVA_PATH/CHANGELOG.md | cut -c 4- | sed -e 's/[.)(]//g' | sed -e 's/ /-/g'\"\n  tag=`eval $command`\n  if [ -z \"$tag\" ]\n  then\n    echo \"\\$tag did not resolve correctly. Aborting.\"\n    abort_release\n  fi\n  current_commit=`git rev-parse HEAD`\n  if [ -z \"$current_commit\" ]\n  then\n    echo \"Could not find current commit. Aborting.\"\n    abort_release\n  fi\n\n  link_to_changelog=\"https://github.com/realm/realm-java/blob/$current_commit/CHANGELOG.md#$tag\"\n  payload=\"{ \\\"username\\\": \\\"Realm CI\\\", \\\"icon_emoji\\\": \\\":realm_new:\\\", \\\"text\\\": \\\"<$link_to_changelog|*Realm Java $RELEASE_VERSION has been released*>\\\\nSee the Release Notes for more details. Note, it can take up to 10 minutes before the release is visible on Maven Central.\\\" }\"\n  echo $link_to_changelog\n  echo \"Pinging #realm-releases\"\n  curl -X POST --data-urlencode \"payload=${payload}\" ${SLACK_WEBHOOK_RELEASES_URL}\n  echo \"Pinging #realm-java-team-ci\"\n  curl -X POST --data-urlencode \"payload=${payload}\" ${SLACK_WEBHOOK_JAVA_CI_URL}\n}\n\n######################################\n# Run Release steps\n######################################\\\n\ncheck_env\nverify_release_preconditions\nverify_changelog\n\nif [ \"$1\" != \"verify\" ]; then\n  create_javadoc\n  upload_to_mavenCentral\n  upload_debug_symbols\n  upload_javadoc\n  notify_slack_channels\nfi\n"
  },
  {
    "path": "tools/realm-cli.sh",
    "content": "#!/bin/bash\n\n# This script provides a single entry point to the different tools used during the\n# realm-java development. \n#\n# It needs REALM_JAVA_PATH to be set to the realm-java repository path.\n# \n# Create an alias for convenient access, for example in .zshrc:\n# alias realm=\"~/realm-java/tools/realm-cli.sh\"\n\n\nis_server_active(){\n    return `docker container ls | grep -Fq mongodb-realm`\n}\n\nstart_server(){\n    if is_server_active\n    then\n        echo \"Warning: Sync server already runnning\"\n    else\n        echo -n \"Starting sync server...\"\n        $REALM_JAVA_PATH/tools/sync_test_server/start_server.sh > /dev/null 2>&1\n        echo \" done\"\n    fi\n}\n\nstop_server(){\n    if is_server_active\n    then\n        echo -n \"Stopping sync server...\"\n        $REALM_JAVA_PATH/tools/sync_test_server/stop_server.sh > /dev/null 2>&1\n        echo \" done\"\n    else\n        echo \"Warning: Sync server not running\"\n    fi\n}\n\nrestart_server(){\n    if is_server_active\n    then\n        stop_server\n        start_server\n    else\n        echo \"Warning: Sync server wasn't running\"\n        start_server\n    fi\n}\n\nserver_status(){\n    if is_server_active\n    then\n        echo \"Sync server: ON\"\n    else\n        echo \"Sync server: OFF\"\n    fi\n}\n\nbind_server(){\n    echo -n \"Forwarding ports... \"\n    adb reverse tcp:9443 tcp:9443 && \\\n    adb reverse tcp:9080 tcp:9080 && \\\n    adb reverse tcp:9090 tcp:9090 && \\\n    adb reverse tcp:8888 tcp:8888 && \\\n    echo \"done\" || { echo \"failed\" ; exit 1 ; }\n}\n\nserver_help(){\n    echo \"Try with:\n\nstart   - starts the sync server\nstop    - stops the sync server\nrestart - restarts the sync server\nstatus  - shows the sync server status\nbind    - bind the emulator ports to the sync server\"\n}\n\nserver(){\n    action=$2\n    case $action in\n        start)\n            start_server\n            ;;\n        stop)\n            stop_server\n            ;;\n        restart)\n            restart_server\n            ;;\n        status)\n            server_status\n            ;;\n        bind)\n            bind_server\n            ;;\n        *)\n            server_help\n    esac\n}\n\njava_install(){\n    pushd $REALM_JAVA_PATH\n    ./gradlew installRealmJava\n    popd\n}\n\njava_build(){\n    pushd $REALM_JAVA_PATH\n    ./gradlew assemble --stacktrace\n    popd\n}\n\njava_test(){\n    pushd $REALM_JAVA_PATH/realm\n    ./gradlew connectedObjectServerDebugAndroidTest --stacktrace\n    popd\n}\n\njava_check(){\n    pushd $REALM_JAVA_PATH/realm\n    ./gradlew spotbugsMain pmd checkstyle\n    popd\n}\n\njava_clean(){\n    pushd $REALM_JAVA_PATH\n    ./gradlew clean\n    popd\n}\n\njava_size(){\n    pushd $REALM_JAVA_PATH/realm/ 1> /dev/null\n    ./gradlew assemble\n    cd realm-library/build/intermediates/cmake/\n    \n    pushd baseRelease/obj 1> /dev/null \n    echo \"Base\"\n    find . -name \"*.so\" -print0 | xargs -0 stat -f '%z %N'\n    echo \"-----------\"\n    popd 1> /dev/null\n    \n    pushd objectServerRelease/obj 1> /dev/null\n    echo \"Object server\"\n    find . -name \"*.so\" -print0 | xargs -0 stat -f '%z %N'\n    echo \"-----------\"\n    popd 1> /dev/null\n    \n    popd 1> /dev/null\n}\n\njava_help(){\n    echo \"Try with:\n\ninstall - install realm-java locally\nbuild   - builds realm-java\ntest    - runs the realm-java test suite\ncheck   - runs realm-java spotbugs, checkstyle, pmd\nclean   - cleans realm-java\"\nsize    - calculates and displays the JNI lib size\n}\n\njava(){\n    action=$2\n    case $action in\n        install)\n            java_install\n            ;;\n        build)\n            java_build\n            ;;\n        test)\n            java_test\n            ;;\n        check)\n            java_check\n            ;;\n        clean)\n            java_clean\n            ;;\n        size)\n            java_size\n            ;;\n        *)\n            java_help\n    esac\n}\n\nshow_help(){\n    echo \"Try with:\n\nserver - controls the sync server\njava    - executes realm-java actions\"\n}\n\nif ! [[ -n \"${REALM_JAVA_PATH}\" ]]; then\n    echo \"Error: \\$REALM_JAVA_PATH not defined.\"\n    exit 1\nfi\n\ncommand=$1\ncase $command in\n    server)\n    server $*\n    ;;\n    java)\n    java $*\n    ;;\n    *)\n    show_help\nesac\n"
  },
  {
    "path": "tools/release.sh",
    "content": "#!/usr/bin/env bash\n\n# Script to make release on the local machine.\n# See https://github.com/realm/realm-wiki/wiki/Java-Release-Checklist for more details.\n\nset -euo pipefail\nIFS=$'\\n\\t'\n\nusage() {\ncat <<EOF\nUsage: $0 <branch-to-release>\nEOF\n}\n\n######################################\n# Input Validation\n######################################\n\nif [ \"$#\" -eq 0 ] || [ \"$#\" -gt 1 ] ; then\n    usage\n    exit 1\nfi\n\n######################################\n# Variables\n######################################\n\nBRANCH_TO_RELEASE=\"$1\"\nVERSION=\"\"\nREALM_IO_PATH=${REALM_IO_PATH:-}\nREALM_JAVA_PATH=$(pwd)\n\ncheck_adb_device() {\n    if ! adb get-state 1>/dev/null 2>&1 ; then\n        read -n 1 -s -p -r \"Attach a test device or start the emulator then press any key to continue...\"\n        echo \"\"\n        check_adb_device\n    fi\n}\n\ncheck_env() {\n    echo \"Checking environment...\"\n\n    # Try to find s3cmd\n    path_to_s3cmd=$(which s3cmd)\n    if [[ ! -x \"$path_to_s3cmd\" ]] ; then\n        echo \"Cannot find executable file 's3cmd'.\"\n        exit -1\n    fi\n    if [[ ! -e \"$HOME/.s3cfg\" ]] ; then\n        echo \"'$HOME/.s3cfg' cannot be found.\"\n        exit -1\n    fi\n\n    # Check Maven Central credentials\n    if ! grep \"ossrhUsername=realm\" \"$HOME/.gradle/gradle.properties\" > /dev/null ; then\n        echo \"'ossrhUsername' is not set in the '$HOME/.gradle/gradle.properties'.\"\n        exit -1\n    fi\n\n    if ! grep \"ossrhPassword=.*\" \"$HOME/.gradle/gradle.properties\" > /dev/null; then\n        echo \"'ossrhPassword' is not set in the '$HOME/.gradle/gradle.properties'.\"\n        exit -1\n    fi\n\n    # Check gradle params\n    if grep buildTargetABIs \"$HOME/.gradle/gradle.properties\" | grep -v \"^#\" > /dev/null ; then\n        echo \"'buildTargetABIs' should be disabled in the '$HOME/.gradle/gradle.properties'.\"\n        exit -1\n    fi\n    if grep ccachePath \"$HOME/.gradle/gradle.properties\" | grep -v \"^#\" > /dev/null ; then\n        echo \"'ccachePath' should be disabled in the '$HOME/.gradle/gradle.properties'.\"\n        exit -1\n    fi\n    if grep lcachePath \"$HOME/.gradle/gradle.properties\" | grep -v \"^#\" > /dev/null ; then\n        echo \"'lcachePath' should be disabled in the '$HOME/.gradle/gradle.properties'.\"\n        exit -1\n    fi\n\n    if [[ -z ${REALM_IO_PATH} ]] ; then\n        REALM_IO_PATH=\"$(pwd)/../realm.io\"\n    fi\n    if [[ ! -e ${REALM_IO_PATH} ]] ; then\n        echo \"Please set 'REALM_IO_PATH' to the 'realm.io' repository path to publish javadoc.\"\n        exit -1\n    fi\n}\n\nprepare_branch() {\n    echo \"Preparing release branch...\"\n\n    git fetch --all\n    git checkout releases\n    git reset --hard origin/releases\n    git clean -xfd\n    git submodule update --init --recursive\n\n    # Merge the branch to the releases branch and check the CHANGELOG.md\n    if [[ \"$BRANCH_TO_RELEASE\" != \"releases\" ]] ; then\n        git merge \"origin/$BRANCH_TO_RELEASE\"\n        git submodule update --init --recursive\n\n        while true\n        do\n            read -r -p \"Type the command to edit CHANGELOG.md, default(vim):\" editor\n            if [ -z \"$editor\" ] ; then\n                editor=\"vim\"\n            fi\n            \"$editor\" CHANGELOG.md\n\n            read -r -p \"Please merge the unreleased entries in the 'CHANGELOG.md' and then press any key to continue...\" _\n            if [ \"$(grep -c \"YYYY-MM-DD\" CHANGELOG.md)\" -eq 1 ] ; then\n                break\n            else\n                echo \"There are more than one or none unreleased entries in the 'CHANGELOG.md'.\"\n            fi\n        done\n        # CHANGELOG.md is modified.\n        if ! git diff-index --quiet HEAD CHANGELOG.md ; then\n            git add CHANGELOG.md\n            git commit -m \"Merge entries in changelog\"\n        fi\n    fi\n\n    if ! grep -q \"SNAPSHOT\" version.txt ; then\n        echo \"'version.txt' doesn't contain 'SNAPSHOT'.\"\n        exit -1\n    fi\n\n    version_in_changelog=$(head -1 CHANGELOG.md | grep -o \"[0-9]*\\.[0-9]*\\.[0-9]*\")\n    VERSION=$(grep -o \"[0-9]*\\.[0-9]*\\.[0-9]*\" version.txt)\n    if [[ \"${VERSION}\" != \"${version_in_changelog}\" ]] ; then\n        echo \"'version.txt' doens't match the entry in 'CHANGELOG.md'. ${VERSION} vs ${version_in_changelog}.\"\n        exit -1\n    fi\n\n    # Check if tag exists in remote\n    if git ls-remote --tags origin | grep \"v${VERSION}\" > /dev/null ; then\n        echo \"Tag 'v${VERSION}' exists in remote!\"\n        exit -1\n    fi\n    if git tag | grep \"v${VERSION}\" > /dev/null ; then\n        git tag -d \"v${VERSION}\"\n    fi\n\n    # Update date in change log\n    cur_date=$(date \"+%F\")\n    sed \"1 s/YYYY-MM-DD/${cur_date}/\" CHANGELOG.md > CHANGELOG.md.tmp && mv CHANGELOG.md.tmp CHANGELOG.md\n    git add CHANGELOG.md\n    git commit -m \"Update changelog date\"\n\n    # This will create 2 new commits to change the version.txt. The top one is the next release version + SNAPSHOT.\n    ./gradlew release\n    # Checkout the one with current version number.\n    git checkout HEAD~1\n}\n\nbuild() {\n    echo \"Building...\"\n\n    ./gradlew assemble\n\n    echo \"Verifying examples...\"\n\n    check_adb_device\n\n    # Verify examples\n    (cd examples && ./gradlew clean uninstallAll && ./gradlew monkeyDebug)\n}\n\nupload_to_maven_central() {\n    echo \"Uploading artifacts to Maven Central...\"\n    # Upload to maven central\n    ./gradlew mavenCentralUpload\n\n    echo \"Done.\"\n    echo \"1. Login into Sonatype console, you can find the credentials in Realm's LastPass account.\"\n    echo \"2. There should be 4 stagging repositories in the console, select them all and click the Close menu option. It will take some time to process the action. Screenshot for close\"\n    echo \"3. After ~5min the repos would be closed, select them all and click the Release menu option. Screenshot for release\"\n    echo \"4. A confirmation prompt will show, select the automatically drop option and confirm. Screenshot for confirmation\"\n    echo \"5. Done! After some time you would be able to search for them.\"\n\n    while true\n    do\n        read -r -p \"Have you published 16 artifacts on Maven central? Type 'Yes' to continue... \" input\n\n        case \"$input\" in\n            [yY][eE][sS])\n                break\n                ;;\n        esac\n    done\n}\n\npublish_distribution() {\n    echo \"Publishing distribution package...\"\n\n    # Create distribution package\n    ./gradlew distributionPackage\n    pushd build/outputs/distribution\n    unzip \"realm-java-${VERSION}.zip\"\n\n    # Test\n    check_adb_device\n    pushd examples/\n    ./gradlew clean uninstallAll\n    ./gradlew monkeyRelease\n    popd\n    popd\n    ./gradlew distribute\n}\n\npush_release() {\n    echo \"Pushing releases branch to origin...\"\n\n    # Push branch & tag\n    git checkout releases\n     \n     # Don't push to releases branch if we are doing a beta release.\n    if [[ ! \"$VERSION\" =~ [a-zA-Z] ]] ; then\n        git push origin releases\n        git push origin \"v${VERSION}\"\n    else\n        echo \"Non-final release. Release was not pushed to Github. Remember to remove commits on `releases` branch manually.\"\n    fi\n}\n\npublish_javadoc() {\n    echo \"Publishing javadoc...\"\n    cd \"${REALM_IO_PATH}\"\n    git fetch --all\n    branch_name=publish_java_doc/${VERSION}\n    git checkout origin/master -b \"${branch_name}\"\n\n    while true\n    do\n        read -r -p \"Type 'Yes' to clean uncommitted files in 'source/en/docs/java'... \" input\n\n        case \"$input\" in\n            [yY][eE][sS])\n                break\n                ;;\n        esac\n    done\n    git clean -xfd ./source/en/docs/java/\n    bundle update\n    bundle exec rake generate:java_docs[$VERSION]\n    cp -R \"${REALM_JAVA_PATH}\"/realm/realm-library/build/docs/javadoc/* ./source/en/docs/java/latest/api/\n    bundle exec rake generate:inject_ga_latest_java_api\n    git add ./source/en/docs/java/\n    git commit -m \"Release realm-java doc ${VERSION}\"\n    git push origin \"${branch_name}\"\n    path_to_hub=$(which hub)\n    if [[ ! -x \"$path_to_hub\" ]] ; then\n        echo \"'hub' cannot be found in the executable path.\"\n        echo \"Please create a pull request manually in realm.io repo with branch ${branch_name}.\"\n        exit -1\n    else\n        hub pull-request\n        echo \"A pull request has been created for branch ${branch_name}.\"\n    fi\n}\n\ncheck_env\nprepare_branch\nbuild\nupload_to_maven_central\npublish_distribution\npush_release\npublish_javadoc\n"
  },
  {
    "path": "tools/sync_test_server/Dockerfile",
    "content": "# Node 18 does not work due to a network issue:\n# npm ERR! request to https://registry.npmjs.org/fs-extra failed, reason: connect ENETUNREACH 2606:4700::6810:1823:443\n# Probably an issue with IPv6 in combination with Docker. IPv6 became the default in Node 17.\n# For now, just use an older node version.\nFROM node:16\n\n# This Docker image is only responsible for running the Integration Command Server which can be\n# used to instrument other parts of the Integration tests.\n#\n# It exposes a webserver on port 8888.\n\n# set timezone to Copenhagen (by default it's using UTC) to match Android's device time.\nRUN cp /usr/share/zoneinfo/Europe/Copenhagen /etc/localtime\nRUN echo \"Europe/Copenhagen\" >  /etc/timezone\n\n# Install netstat (used for debugging)\nRUN apt-get update \\\n  && DEBIAN_FRONTEND=noninteractive apt-get install -y \\\n    net-tools \\\n    psmisc \\\n  && apt-get clean \\\n  && rm -rf /var/lib/apt/lists/*\n\n# Copy webserver script and install dependencies\nWORKDIR \"/tmp\"\nCOPY mongodb-realm-command-server.js /tmp/\nRUN npm install winston@2.4.0 temp httpdispatcher@1.0.0 fs-extra moment is-port-available@0.1.5\n\n# Run integration test server\nCMD /tmp/mongodb-realm-command-server.js\n"
  },
  {
    "path": "tools/sync_test_server/app_config_generator.sh",
    "content": "#!/bin/bash\nTARGET_APP_PATH=$1;shift\nTEMPLATE_APP_PATH=$1;shift\nSYNC_MODE=$1;shift # Must be either \"partition\" or \"flex\"\nAUTH_MODE=$1;shift # Must be either \"auto\", \"function\" or \"email\"\nmkdir -p $TARGET_APP_PATH\nfor APP_NAME in \"$@\"\ndo\n    cp -r $TEMPLATE_APP_PATH $TARGET_APP_PATH/$APP_NAME\n    sed -i'.bak' 's/APP_NAME_PLACEHOLDER/'$APP_NAME'/g' $TARGET_APP_PATH/$APP_NAME/config.json\ndone\n\n# Setup auth config\nfor APP_NAME in \"$@\" \ndo\n    JSON=\"placeholder\"\n    if [ \"$AUTH_MODE\" = \"auto\" ]; then\n        JSON='\n            \"config\": {\n                \"autoConfirm\": true,\n                \"runConfirmationFunction\": false,\n                \"confirmationFunctionName\": \"confirmFunc\",\n                \"emailConfirmationUrl\": \"http://realm.io/confirm-user\",\n                \"resetFunctionName\": \"resetFunc\",\n                \"resetPasswordSubject\": \"Reset Password\",\n                \"resetPasswordUrl\": \"http://realm.io/reset-password\",\n                \"runResetFunction\": false\n            },\n        '\n    fi\n    if [ \"$AUTH_MODE\" = \"function\" ]; then\n        JSON='\n            \"config\": {\n                \"autoConfirm\": false,\n                \"runConfirmationFunction\": true,\n                \"confirmationFunctionName\": \"confirmFunc\",\n                \"emailConfirmationUrl\": \"http://realm.io/confirm-user\",\n                \"resetFunctionName\": \"resetFunc\",\n                \"resetPasswordSubject\": \"Reset Password\",\n                \"resetPasswordUrl\": \"http://realm.io/reset-password\",\n                \"runResetFunction\": false\n            },\n        '\n    fi\n    if [ \"$AUTH_MODE\" = \"email\" ]; then\n        JSON='\n            \"config\": {\n                \"autoConfirm\": false,\n                \"runConfirmationFunction\": false,\n                \"confirmationFunctionName\": \"confirmFunc\",\n                \"emailConfirmationUrl\": \"http://realm.io/confirm-user\",\n                \"resetFunctionName\": \"resetFunc\",\n                \"resetPasswordSubject\": \"Reset Password\",\n                \"resetPasswordUrl\": \"http://realm.io/reset-password\",\n                \"runResetFunction\": false\n            },\n        '\n    fi\n\n    ESCAPED_JSON=`echo ${JSON} | tr '\\n' \"\\\\n\"`     \n    cp -r $TEMPLATE_APP_PATH $TARGET_APP_PATH/$APP_NAME\n    sed -i'.bak' \"s#%EMAIL_AUTH_CONFIG%#$ESCAPED_JSON#g\" $TARGET_APP_PATH/$APP_NAME/auth_providers/local-userpass.json\ndone\n\n# Setup sync configuration\nfor APP_NAME in \"$@\"\ndo\n    JSON=\"placeholder\"\n    if [ \"$SYNC_MODE\" = \"partition\" ]; then\n      JSON='\n        \"sync\": {\n            \"state\": \"enabled\",\n            \"database_name\": \"test_data\",\n            \"partition\": {\n                \"key\": \"realm_id\",\n                \"type\": \"string\",\n                \"permissions\": {\n                    \"read\": {\n                        \"%%true\": {\n                            \"%function\": {\n                                \"arguments\": [\n                                    \"%%partition\"\n                                ],\n                                \"name\": \"canReadPartition\"\n                            }\n                        }\n                    },\n                    \"write\": {\n                        \"%%true\": {\n                            \"%function\": {\n                                \"arguments\": [\n                                    \"%%partition\"\n                                ],\n                                \"name\": \"canWritePartition\"\n                            }\n                        }\n                    }\n                }\n            }\n        }\n      '\n    fi\n    if [ \"$SYNC_MODE\" = \"flex\" ]; then\n      JSON='\n        \"flexible_sync\": {\n            \"state\": \"enabled\",\n            \"database_name\": \"test_data\",\n            \"queryable_fields_names\": [\n                \"age\",\n                \"name\",\n                \"color\",\n                \"section\"\n            ],\n            \"permissions\": {\n                \"rules\": {},\n                \"defaultRoles\": [\n                    {\n                        \"name\": \"read-write\",\n                        \"applyWhen\": {},\n                        \"read\": true,\n                        \"write\": true\n                    }\n                ]\n            }\n        }\n      '\n    fi\n\n    ESCAPED_JSON=`echo ${JSON} | tr '\\n' \"\\\\n\"`\n    cp -r $TEMPLATE_APP_PATH $TARGET_APP_PATH/$APP_NAME\n    sed -i'.bak' \"s/%SYNC_CONFIG%/$ESCAPED_JSON/g\" $TARGET_APP_PATH/$APP_NAME/services/BackingDB/config.json\ndone\n"
  },
  {
    "path": "tools/sync_test_server/app_template/auth_providers/anon-user.json",
    "content": "{\n    \"id\": \"60489e7df5d9bdc94de663d8\",\n    \"name\": \"anon-user\",\n    \"type\": \"anon-user\",\n    \"disabled\": false\n}\n"
  },
  {
    "path": "tools/sync_test_server/app_template/auth_providers/api-key.json",
    "content": "{\n    \"id\": \"60489e7df5d9bdc94de663d9\",\n    \"name\": \"api-key\",\n    \"type\": \"api-key\",\n    \"disabled\": false\n}\n"
  },
  {
    "path": "tools/sync_test_server/app_template/auth_providers/custom-function.json",
    "content": "{\n    \"id\": \"60489e7df5d9bdc94de663da\",\n    \"name\": \"custom-function\",\n    \"type\": \"custom-function\",\n    \"config\": {\n        \"authFunctionName\": \"testAuthFunc\"\n    },\n    \"disabled\": false\n}\n"
  },
  {
    "path": "tools/sync_test_server/app_template/auth_providers/local-userpass.json",
    "content": "{\n    \"id\": \"60489e7df5d9bdc94de663db\",\n    \"name\": \"local-userpass\",\n    \"type\": \"local-userpass\",\n    %EMAIL_AUTH_CONFIG%\n    \"disabled\": false\n}\n"
  },
  {
    "path": "tools/sync_test_server/app_template/config.json",
    "content": "{\n    \"config_version\": 20200603,\n    \"name\": \"APP_NAME_PLACEHOLDER\",\n    \"location\": \"US-VA\",\n    \"deployment_model\": \"GLOBAL\",\n    \"security\": {},\n    \"custom_user_data_config\": {\n        \"enabled\": true,\n        \"mongo_service_name\": \"BackingDB\",\n        \"database_name\": \"test_data\",\n        \"collection_name\": \"custom_user_data\",\n        \"user_id_field\": \"userid\"\n    },\n    \"sync\": {\n        \"development_mode_enabled\": true\n    }\n}\n"
  },
  {
    "path": "tools/sync_test_server/app_template/functions/authFunc/config.json",
    "content": "{\n    \"can_evaluate\": {},\n    \"id\": \"60489e7df5d9bdc94de663ce\",\n    \"name\": \"authFunc\",\n    \"private\": false\n}\n"
  },
  {
    "path": "tools/sync_test_server/app_template/functions/authFunc/source.js",
    "content": "\n  /*\n\n    This function will be run when a user logs in with this provider.\n\n    The return object must contain a string id, this string id will be used to login with an existing\n    or create a new user. This is NOT the Stitch user id, but it is the id used to identify which user has\n    been created or logged in with. \n\n    If an error is thrown within the function the login will fail.\n\n    The default function provided below will always result in failure.\n  */\n\n  exports = (loginPayload) => {\n    return loginPayload[\"realmCustomAuthFuncUserId\"];\n  };\n"
  },
  {
    "path": "tools/sync_test_server/app_template/functions/authorizedOnly/config.json",
    "content": "{\n    \"can_evaluate\": {\n        \"%%user.data.email\": {\n            \"%in\": [\n                \"authorizeduser@example.org\"\n            ]\n        }\n    },\n    \"id\": \"60489e7df5d9bdc94de663cf\",\n    \"name\": \"authorizedOnly\",\n    \"private\": false\n}\n"
  },
  {
    "path": "tools/sync_test_server/app_template/functions/authorizedOnly/source.js",
    "content": "exports = function(arg){\n  /*\n    Accessing application's values:\n    var x = context.values.get(\"value_name\");\n\n    Accessing a mongodb service:\n    var collection = context.services.get(\"mongodb-atlas\").db(\"dbname\").collection(\"coll_name\");\n    var doc = collection.findOne({owner_id: context.user.id});\n\n    To call other named functions:\n    var result = context.functions.execute(\"function_name\", arg1, arg2);\n\n    Try running in the console below.\n  */\n  return {arg: context.user};\n};"
  },
  {
    "path": "tools/sync_test_server/app_template/functions/canReadPartition/config.json",
    "content": "{\n    \"can_evaluate\": {},\n    \"id\": \"60489e7df5d9bdc94de663da\",\n    \"name\": \"canReadPartition\",\n    \"private\": false\n}\n"
  },
  {
    "path": "tools/sync_test_server/app_template/functions/canReadPartition/source.js",
    "content": "/**\n * Users with an email that contains `_noread_` do not have read access,\n * all others do.\n */\nexports = async (partition) => {\n  const email = context.user.data.email;\n  if (email != undefined) {\n    return(!email.includes(\"_noread_\"));\n  } else {\n    return true;\n  }\n}\n"
  },
  {
    "path": "tools/sync_test_server/app_template/functions/canWritePartition/config.json",
    "content": "{\n    \"can_evaluate\": {},\n    \"id\": \"60489e7df5d9bdc94de783cf\",\n    \"name\": \"canWritePartition\",\n    \"private\": false\n}\n"
  },
  {
    "path": "tools/sync_test_server/app_template/functions/canWritePartition/source.js",
    "content": "/**\n * Users with an email that contains `_nowrite_` do not have write access,\n * all others do.\n */\nexports = async (partition) => {\n  const email = context.user.data.email;\n  if (email != undefined) {\n    return(!email.includes(\"_nowrite_\"));\n  } else {\n    return true;\n  }\n}\n"
  },
  {
    "path": "tools/sync_test_server/app_template/functions/confirmFunc/config.json",
    "content": "{\n    \"can_evaluate\": {},\n    \"id\": \"60489e7df5d9bdc94de663d0\",\n    \"name\": \"confirmFunc\",\n    \"private\": false\n}\n"
  },
  {
    "path": "tools/sync_test_server/app_template/functions/confirmFunc/source.js",
    "content": "  /*\n\n    This function will be run AFTER a user registers their username and password and is called with an object parameter\n    which contains three keys: 'token', 'tokenId', and 'username'.\n\n    The return object must contain a 'status' key which can be empty or one of three string values: \n      'success', 'pending', or 'fail'.\n\n    'success': the user is confirmed and is able to log in.\n\n    'pending': the user is not confirmed and the UserPasswordAuthProviderClient 'confirmUser' function would \n      need to be called with the token and tokenId via an SDK. (see below)\n\n      const emailPassClient = Stitch.defaultAppClient.auth\n        .getProviderClient(UserPasswordAuthProviderClient.factory);\n\n      return emailPassClient.confirmUser(token, tokenId);\n\n    'fail': the user is not confirmed and will not be able to log in.\n\n    If an error is thrown within the function the result is the same as 'fail'.\n\n    Example below:\n\n    exports = ({ token, tokenId, username }) => {\n      // process the confirm token, tokenId and username\n      if (context.functions.execute('isValidUser', username)) {\n        // will confirm the user\n        return { status: 'success' };\n      } else {\n        context.functions.execute('sendConfirmationEmail', username, token, tokenId);\n        return { status: 'pending' };\n      }\n  \n      return { status: 'fail' };\n    };\n\n    The uncommented function below is just a placeholder and will result in failure.\n  */\nexports = async ({ token, tokenId, username }) => {\n    // process the confirm token, tokenId and username\n\n    if (username.includes(\"realm_verify\")) {\n      // Automatically confirm users with `realm_verify` in their email.\n      return { status: 'success' }\n    } else if (username.includes(\"realm_pending\")) {\n      // This supports two versions of custom registering:\n      //\n      // 1. Emails with `realm_pending` in their email will be placed in Pending\n      //    the first time they register and then fully confirmed when they\n      //    retry the confirmation logic.\n      // 2. Emails with `only_realm_pending` in their email will be placed in\n      //    Pending the first time they register and fail all subsequent attempts\n      //    at retrying the confirmation logic.\n      const mdb = context.services.get(\"BackingDB\");\n      const collection = mdb.db(\"custom-auth\").collection(\"users\");\n      const existing = await collection.findOne({ username: username });\n      if (existing) {\n        if (username.includes(\"only_realm_pending\")) {\n            return { status: 'fail' }\n        } else {\n            return { status: 'success' };\n        }\n      }\n      await collection.insertOne({ username: username });\n      return { status: 'pending' }\n    } else if (username.endsWith(\"@10gen.com\") || username.includes(\"realm_tests_do_autoverify\")) {\n      return { status: 'success' }\n    } else {\n      // All other emails should fail to confirm outright.\n      return { status: 'fail' };\n    }\n  };\n"
  },
  {
    "path": "tools/sync_test_server/app_template/functions/error/config.json",
    "content": "{\n    \"id\": \"60489e7df5d9bdc94de663d1\",\n    \"name\": \"error\",\n    \"private\": false\n}\n"
  },
  {
    "path": "tools/sync_test_server/app_template/functions/error/source.js",
    "content": "exports = function(arg){\n  return unknown;\n};"
  },
  {
    "path": "tools/sync_test_server/app_template/functions/firstArg/config.json",
    "content": "{\n    \"id\": \"60489e7df5d9bdc94de663d2\",\n    \"name\": \"firstArg\",\n    \"private\": false\n}\n"
  },
  {
    "path": "tools/sync_test_server/app_template/functions/firstArg/source.js",
    "content": "exports = function(arg){\n  // Returns first argument\n  return arg\n};"
  },
  {
    "path": "tools/sync_test_server/app_template/functions/null/config.json",
    "content": "{\n    \"id\": \"60489e7df5d9bdc94de663d3\",\n    \"name\": \"null\",\n    \"private\": false\n}\n"
  },
  {
    "path": "tools/sync_test_server/app_template/functions/null/source.js",
    "content": "exports = function(arg){\n  return null;\n};"
  },
  {
    "path": "tools/sync_test_server/app_template/functions/resetFunc/config.json",
    "content": "{\n    \"can_evaluate\": {},\n    \"id\": \"60489e7df5d9bdc94de663d4\",\n    \"name\": \"resetFunc\",\n    \"private\": false\n}\n"
  },
  {
    "path": "tools/sync_test_server/app_template/functions/resetFunc/source.js",
    "content": "\n  /*\n    This function will be run when the client SDK 'callResetPasswordFunction' and is called with an object parameter\n    which contains four keys: 'token', 'tokenId', 'username', and 'password', and additional parameters\n    for each parameter passed in as part of the argument list from the SDK.\n\n    The return object must contain a 'status' key which can be empty or one of three string values: \n      'success', 'pending', or 'fail'\n\n    'success': the user's password is set to the passed in 'password' parameter.\n\n    'pending': the user's password is not reset and the UserPasswordAuthProviderClient 'resetPassword' function would \n      need to be called with the token, tokenId, and new password via an SDK. (see below)\n\n      const emailPassClient = Stitch.defaultAppClient.auth\n        .getProviderClient(UserPasswordAuthProviderClient.factory);\n\n      emailPassClient.resetPassword(token, tokenId, newPassword)\n\n    'fail': the user's password is not reset and will not be able to log in with that password.\n\n    If an error is thrown within the function the result is the same as 'fail'.\n\n    Example below:\n\n    exports = ({ token, tokenId, username, password }, sendEmail, securityQuestionAnswer) => {\n      // process the reset token, tokenId, username and password\n      if (sendEmail) {\n        context.functions.execute('sendResetPasswordEmail', username, token, tokenId);\n        // will wait for SDK resetPassword to be called with the token and tokenId\n        return { status: 'pending' };\n      } else if (context.functions.execute('validateSecurityQuestionAnswer', username, securityQuestionAnswer)) {\n        // will set the users password to the password parameter\n        return { status: 'success' };\n      }\n  \n      // will not reset the password\n      return { status: 'fail' };\n    };\n\n    The uncommented function below is just a placeholder and will result in failure.\n  */\n\nexports = ({ token, tokenId, username, password }, customParam1, customParam2) => {\n    if (customParam1 != \"say-the-magic-word\" || customParam2 != 42) {\n        return { status: 'fail' };\n    } else {\n        return { status: 'success' };\n    }\n}\n"
  },
  {
    "path": "tools/sync_test_server/app_template/functions/sum/config.json",
    "content": "{\n    \"id\": \"60489e7df5d9bdc94de663d5\",\n    \"name\": \"sum\",\n    \"private\": false\n}\n"
  },
  {
    "path": "tools/sync_test_server/app_template/functions/sum/source.js",
    "content": "exports = function(...args) {\n    return parseInt(args.reduce((a,b) => a + b, 0));\n};\n"
  },
  {
    "path": "tools/sync_test_server/app_template/functions/testAuthFunc/config.json",
    "content": "{\n    \"id\": \"60489e7df5d9bdc94de663d6\",\n    \"name\": \"testAuthFunc\",\n    \"private\": false\n}\n"
  },
  {
    "path": "tools/sync_test_server/app_template/functions/testAuthFunc/source.js",
    "content": "exports = ({mail, id}) => {\n    // Auth function will fail for emails with a domain different to @10gen.com\n    // or with id lower than 666\n    if (!new RegExp(\"@10gen.com$\").test(mail) || id < 666) {\n        return 0;\n    } else {\n        // Use the users email as UID\n        return mail;\n    }\n}\n"
  },
  {
    "path": "tools/sync_test_server/app_template/functions/triggerClientReset/config.json",
    "content": "{\n    \"id\": \"60489e7df5d9bdc94de66310\",\n    \"name\": \"triggerClientReset\",\n    \"private\": false\n}\n"
  },
  {
    "path": "tools/sync_test_server/app_template/functions/triggerClientReset/source.js",
    "content": "exports = async function (appId, userId) {\n  return await deleteClientFile(`__realm_sync_${appId}`, userId) || await deleteClientFile(`__realm_sync`, userId);\n};\n\nasync function deleteClientFile(db, userId) {\n  const mongodb = context.services.get(\"BackingDB\");\n\n  return (await mongodb.db(db)\n  .collection(\"clientfiles\")\n  .deleteOne({ ownerId: userId }))\n  .deletedCount > 0;\n}\n"
  },
  {
    "path": "tools/sync_test_server/app_template/functions/void/config.json",
    "content": "{\n    \"id\": \"60489e7df5d9bdc94de663d7\",\n    \"name\": \"void\",\n    \"private\": false\n}\n"
  },
  {
    "path": "tools/sync_test_server/app_template/functions/void/source.js",
    "content": "exports = function(arg){\n  return void(0);\n};"
  },
  {
    "path": "tools/sync_test_server/app_template/graphql/config.json",
    "content": "{\n    \"use_natural_pluralization\": true\n}\n"
  },
  {
    "path": "tools/sync_test_server/app_template/secrets.json",
    "content": "{\n    \"BackingDB_uri\": \"mongodb://localhost:26000\",\n    \"gcm\": \"gcm\"\n}\n"
  },
  {
    "path": "tools/sync_test_server/app_template/services/BackingDB/config.json",
    "content": "{\n    \"id\": \"60489e7df5d9bdc94de663c7\",\n    \"name\": \"BackingDB\",\n    \"type\": \"mongodb\",\n    \"config\": {\n        %SYNC_CONFIG%\n    },\n    \"secret_config\": {\n        \"uri\": \"BackingDB_uri\"\n    },\n    \"version\": 1\n}\n"
  },
  {
    "path": "tools/sync_test_server/app_template/services/BackingDB/rules/test_data.EmbeddedSimpleParent.json",
    "content": "{\n    \"collection\": \"EmbeddedSimpleParent\",\n    \"database\": \"test_data\",\n    \"id\": \"60489e7df5d9bdc95de663cd\",\n    \"roles\": [\n        {\n            \"name\": \"default\",\n            \"apply_when\": {},\n            \"insert\": true,\n            \"delete\": true,\n            \"additional_fields\": {}\n        }\n    ],\n    \"schema\": {\n        \"properties\": {\n            \"_id\": {\n                \"bsonType\": \"string\"\n            },\n            \"realm_id\": {\n            \"bsonType\": \"string\"\n            },\n            \"child\": {\n            \"title\": \"EmbeddedSimpleChild\",\n            \"bsonType\": \"object\",\n            \"required\": [\n                \"childId\"\n            ],\n            \"properties\": {\n                \"childId\": {\n                \"bsonType\": \"string\"\n                }\n            }\n            }\n        },\n        \"required\": [\n            \"_id\"\n        ],\n        \"title\": \"EmbeddedSimpleParent\"\n    }\n}\n"
  },
  {
    "path": "tools/sync_test_server/app_template/services/BackingDB/rules/test_data.FlexSyncColor.json",
    "content": "{\n    \"collection\": \"FlexSyncColor\",\n    \"database\": \"test_data\",\n    \"id\": \"60489e7df5d9bdc94de663ce\",\n    \"roles\": [\n        {\n            \"name\": \"default\",\n            \"apply_when\": {},\n            \"insert\": true,\n            \"delete\": true,\n            \"additional_fields\": {}\n        }\n    ],\n    \"schema\": {\n        \"properties\": {\n            \"_id\": {\n                \"bsonType\": \"objectId\"\n              },\n              \"realm_id\": {\n                \"bsonType\": \"string\"\n              },\n              \"section\": {\n                \"bsonType\": \"int\"\n              },\n              \"color\": {\n                \"bsonType\": \"string\"\n              }\n        },\n        \"required\": [\n            \"color\",\n            \"section\"\n        ],\n        \"title\": \"FlexSyncColor\"\n    }\n}\n"
  },
  {
    "path": "tools/sync_test_server/app_template/services/BackingDB/rules/test_data.SyncColor.json",
    "content": "{\n    \"collection\": \"SyncColor\",\n    \"database\": \"test_data\",\n    \"id\": \"60489e7df5d9bdc94de663cd\",\n    \"roles\": [\n        {\n            \"name\": \"default\",\n            \"apply_when\": {},\n            \"insert\": true,\n            \"delete\": true,\n            \"additional_fields\": {}\n        }\n    ],\n    \"schema\": {\n        \"properties\": {\n            \"_id\": {\n                \"bsonType\": \"objectId\"\n              },\n              \"realm_id\": {\n                \"bsonType\": \"string\"\n              },\n              \"color\": {\n                \"bsonType\": \"string\"\n              }\n        },\n        \"required\": [\n            \"color\"\n        ],\n        \"title\": \"SyncColor\"\n    }\n}\n"
  },
  {
    "path": "tools/sync_test_server/app_template/services/BackingDB/rules/test_data.SyncDog.json",
    "content": "{\n    \"collection\": \"SyncDog\",\n    \"database\": \"test_data\",\n    \"id\": \"60489e7df5d9bdc94de663c8\",\n    \"roles\": [\n        {\n            \"name\": \"default\",\n            \"apply_when\": {},\n            \"insert\": true,\n            \"delete\": true,\n            \"additional_fields\": {}\n        }\n    ],\n    \"schema\": {\n        \"properties\": {\n            \"_id\": {\n                \"bsonType\": \"objectId\"\n            },\n            \"breed\": {\n                \"bsonType\": \"string\"\n            },\n            \"name\": {\n                \"bsonType\": \"string\"\n            },\n            \"realm_id\": {\n                \"bsonType\": \"string\"\n            }\n        },\n        \"required\": [\n            \"name\"\n        ],\n        \"title\": \"SyncDog\"\n    }\n}\n"
  },
  {
    "path": "tools/sync_test_server/app_template/services/BackingDB/rules/test_data.SyncPerson.json",
    "content": "{\n    \"collection\": \"SyncPerson\",\n    \"database\": \"test_data\",\n    \"id\": \"60489e7df5d9bdc94de663c9\",\n    \"relationships\": {\n        \"dogs\": {\n            \"ref\": \"#/relationship/BackingDB/test_data/SyncDog\",\n            \"source_key\": \"dogs\",\n            \"foreign_key\": \"_id\",\n            \"is_list\": true\n        }\n    },\n    \"roles\": [\n        {\n            \"name\": \"default\",\n            \"apply_when\": {},\n            \"insert\": true,\n            \"delete\": true,\n            \"additional_fields\": {}\n        }\n    ],\n    \"schema\": {\n        \"properties\": {\n            \"_id\": {\n                \"bsonType\": \"objectId\"\n            },\n            \"age\": {\n                \"bsonType\": \"int\"\n            },\n            \"dogs\": {\n                \"bsonType\": \"array\",\n                \"items\": {\n                    \"bsonType\": \"objectId\"\n                }\n            },\n            \"firstName\": {\n                \"bsonType\": \"string\"\n            },\n            \"lastName\": {\n                \"bsonType\": \"string\"\n            },\n            \"realm_id\": {\n                \"bsonType\": \"string\"\n            }\n        },\n        \"required\": [\n            \"firstName\",\n            \"lastName\",\n            \"age\"\n        ],\n        \"title\": \"SyncPerson\"\n    }\n}\n"
  },
  {
    "path": "tools/sync_test_server/app_template/services/BackingDB/rules/test_data.custom_user_data.json",
    "content": "{\n    \"collection\": \"custom_user_data\",\n    \"database\": \"test_data\",\n    \"id\": \"60489e7df5d9bdc94de663ca\",\n    \"roles\": [\n        {\n            \"name\": \"default\",\n            \"apply_when\": {},\n            \"insert\": true,\n            \"delete\": true,\n            \"additional_fields\": {}\n        }\n    ],\n    \"schema\": {}\n}\n"
  },
  {
    "path": "tools/sync_test_server/app_template/services/BackingDB/rules/test_data.mongo_data.json",
    "content": "{\n    \"collection\": \"mongo_data\",\n    \"database\": \"test_data\",\n    \"id\": \"60489e7df5d9bdc94de663cb\",\n    \"roles\": [\n        {\n            \"name\": \"default\",\n            \"apply_when\": {},\n            \"insert\": true,\n            \"delete\": true,\n            \"additional_fields\": {}\n        }\n    ],\n    \"schema\": {\n        \"properties\": {\n            \"_id\": {\n                \"bsonType\": \"objectId\"\n            },\n            \"realm_id\": {\n                \"bsonType\": \"string\"\n            }\n        },\n        \"required\": [],\n        \"title\": \"mongo_data\"\n    }\n}\n"
  },
  {
    "path": "tools/sync_test_server/app_template/services/BackingDB/rules/test_data.mongo_data_alt.json",
    "content": "{\n    \"collection\": \"mongo_data_alt\",\n    \"database\": \"test_data\",\n    \"id\": \"60489e7df5d9bdc94de663cc\",\n    \"roles\": [\n        {\n            \"name\": \"default\",\n            \"apply_when\": {},\n            \"insert\": true,\n            \"delete\": true,\n            \"search\": true,\n            \"additional_fields\": {}\n        }\n    ],\n    \"schema\": {}\n}\n"
  },
  {
    "path": "tools/sync_test_server/app_template/services/gcm/config.json",
    "content": "{\n    \"id\": \"60489e7df5d9bdc94de663cd\",\n    \"name\": \"gcm\",\n    \"type\": \"gcm\",\n    \"config\": {\n        \"senderId\": \"gcm\"\n    },\n    \"secret_config\": {\n        \"apiKey\": \"gcm\"\n    },\n    \"version\": 1\n}\n"
  },
  {
    "path": "tools/sync_test_server/bind_android_ports.sh",
    "content": "#!/usr/bin/env bash\n\n# This scripts tries to bind the android emulator ports to point the local development server.\n\nadb reverse tcp:9443 tcp:9443 && \\\nadb reverse tcp:9080 tcp:9080 && \\\nadb reverse tcp:9090 tcp:9090 && \\\nadb reverse tcp:8888 tcp:8888 && \\\necho \"Done\" || { echo \"Failed to reverse android emulator ports.\" ;}\n"
  },
  {
    "path": "tools/sync_test_server/keys/HowToGenerateKey.txt",
    "content": "// The Base64-encoded user token is generated by the following command:\n//     cat test_token.json | base64\n// The Base64-encoded signature is generated by the following command:\n//     cat test_token.json | openssl dgst -sha256 -binary -sign private.pem | base64\n// The two are concatenated with a ':'.\n// This token does not contain a \"path\" field, and therefore grants access to\n// all Realms.\n\n// Example:\ng_signed_test_user_token =\n // cat test_token.json | base64\n\"ewogICJpZGVudGl0eSI6ICJ0ZXN0IiwKICAiYWNjZXNzIjogWwogICAgImRvd25sb2FkIiwKICAgICJ1cGxvYWQiCiAgXSwKICAidGltZXN0YW1wIjogMTQ1NTUzMDYxNCwKICAiZXhwaXJlcyI6IG51bGwsCiAgImFwcF9pZCI6ICJpby5yZWFsbS50ZXN0cy5zeW5jIgp9\"\n+ \":\"\n// cat test_token.json | openssl dgst -sha256 -binary -sign private.pem | base64\n\"Y5+K3Y+wd+McaZx6rte1MQvKpHgy7NoTqTzgF3CnGKcosMT7PkG1M71rLsq9/Fcldn6G26Bn3kb0vnw93TS2Ox4wa0FMiObK+N7VNdI6p/+dG5bDjBhtW2AFd2P0nOUCvx39EIdLVnGr3JUidJZEZGzFyFOdZVpnmIAnHNDaOIPOXt4vnASJ/dBjUTkOlexOwSRKIK1hvkA1GO9zpvnG5EbnVG6LuVSRM93Hp0tzuFdesns19P827/FsdZATDA9TFlwVTIa7vHz0KbzolSXKvIiOr5XWC2NXyDFEowxwFHyCuXN52jk9kylagFDTBvXu1ddmDZjWxg9SinJzS4lsYA==\"\n\n\nReference https://github.com/realm/realm-sync/blob/master/test/test_sync.cpp#L65\n"
  },
  {
    "path": "tools/sync_test_server/keys/private.pem",
    "content": "-----BEGIN RSA PRIVATE KEY-----\nMIIEpAIBAAKCAQEAo65ZQ8mFIVk0ZB22bHdNuBr4G3K7SwfFlUhmBmjQFb2EdopA\nnmu/XdXn+Zw3pmYlzIxe+3RX9M4eh8luIil0J2Nlb7tHOPZQkQAiuuud8JQ9RTND\nixUQTGS4YmhyQv+7LA9cjdaczD3Bf3Nw/yZQTQQqw7vsbTUJeAMz+6EFLeMj2Lxn\nZVLP7ePezxaSpKiQ8mp7eurQrZIqmvEC1xp8a7XvkgtqnMBepauIBiw6Wlpin0lP\nD3P5uMtrP+z5MmQXpP/GOp6XjBlULMQAMH/V03WYMwnevzMWmKhF2apepnjd65nB\nh29iaFuiE8tYvKpJxmrsmoU+aOvMt3ZORxj7LQIDAQABAoIBAGfSlWh8EOgAT00Z\n07alTjTzVmECu25yNY/lZmG2ZhcEKVuPgkF6kt4Qap5XyqzPqjY+65iQSaJMg+0Z\nhbRBmx3I3HSs1BZ7lssCzQTHo10QinS0ealk6Pur/5DcM23wDGd8LvcBJGAg4/XV\n4dzWDqVreTzCnMsAk0r+rSB1GHXr0/jMiivPvUzvxpVRZ+dyGPdxUFBQivPGC7h8\n3VJRLj8zBFlf0az7xeVCGgZMAtiaJhhGtG2QCBKhk3mqlDmhIB6jTai+b+vnL1KK\ntTOOhMsYXIhJXYeE6H2aXNn7z53sKoiRq2Zptzfl9csbQ5yelbtZ05CRC+nzAscr\nXOl2BjkCgYEA0QYexhXsd9OA8vU+kfm1WyLZmGc1biK+RLqV+nhXzy1lRy1DdaOq\n6raNgaZ9xgX5zHLqxk+2s5+dWMfyvbUxDPhl7C6R0yLNuXzW2tjsy3T5AI8ApWrA\nSTUOaamLyaqRt0VB8AVSco2bvHCVEjyY+Bc7RD0LHnDfBUSwobr+FrMCgYEAyHd+\nnGsWhqGEabtfZCS8f1f1PnS4jge5VY9PFjgSLT9K6KJv00tmG9PGRhKXgGiLs+DW\n0EHiwWIYpAGHVOvnndWIUsxo14Mg8cRfJlA/a87RrXMNu6I/4rGPRwHqeRauNWmu\nwuNSJZTul09UYo7iHqtiEFOxpSEufC4965QUlp8CgYA/9qZ+KYFWXdPNBX1jQE3e\nGLkLqTGxhVJCR/LTVfZRAOxILrLBEheggcKl1SQR8Aw0I0py6zvWldaZr345zXO4\nK19NOicHvFPGGkzJZa54yE/WeuxQsm0rOeAyN17+lILI2ZnG8Gn9ghYRQUZs8TxC\nVyGczS1U4Gdu/kkrBMTyfwKBgQCRYh//fqZ6gx7Ns2bt8LqHvBmO7wV9c9qUU3du\nzMFZ8UH5Tvy8hz0JR1/PJ+KZ7LgMfy4rIO07hFIMd1NXYjK6w8a3DamnSmEVFW5Q\nEfi8zeRA32UBRB0C4fTf8WLD6I/1Cq0Eh+nmeYlDUPQI+kjBJ1faMWhvMo5M3xhn\nBiCcTwKBgQC/oQ5R6avo15UK7Tituj9TqduLf4leGJwn3ht6GsAPNDENDJZJc30A\nwL+ghnvUieG1fz3OelZPx3Ber5QdNzhM8+24klevCLaCdF8alhg9nIEtWFrGpXEv\nRLZ4jP2FUo1XJDNqXK4l17slzdWzEs1jiB7ePLvpoiA+GVcL3Anmkg==\n-----END RSA PRIVATE KEY-----\n"
  },
  {
    "path": "tools/sync_test_server/keys/public.pem",
    "content": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAo65ZQ8mFIVk0ZB22bHdN\nuBr4G3K7SwfFlUhmBmjQFb2EdopAnmu/XdXn+Zw3pmYlzIxe+3RX9M4eh8luIil0\nJ2Nlb7tHOPZQkQAiuuud8JQ9RTNDixUQTGS4YmhyQv+7LA9cjdaczD3Bf3Nw/yZQ\nTQQqw7vsbTUJeAMz+6EFLeMj2LxnZVLP7ePezxaSpKiQ8mp7eurQrZIqmvEC1xp8\na7XvkgtqnMBepauIBiw6Wlpin0lPD3P5uMtrP+z5MmQXpP/GOp6XjBlULMQAMH/V\n03WYMwnevzMWmKhF2apepnjd65nBh29iaFuiE8tYvKpJxmrsmoU+aOvMt3ZORxj7\nLQIDAQAB\n-----END PUBLIC KEY-----\n"
  },
  {
    "path": "tools/sync_test_server/keys/test_token.json",
    "content": "{\n  \"identity\": \"test2\",\n  \"access\": [\n    \"download\",\n    \"upload\"\n  ],\n  \"timestamp\": 1455530614,\n  \"expires\": null,\n  \"app_id\": \"io.realm.tests.sync\"\n}\n"
  },
  {
    "path": "tools/sync_test_server/mongodb-realm-command-server.js",
    "content": "#!/usr/bin/env nodejs\n\n/**\n * This script controls the Command Server responsible for starting and stopping\n * ROS instances. The integration tests running on the device will communicate\n * with it using a predefined port in order to say when the ROS instance\n * should be started and stopped.\n *\n * This script is responsible for cleaning up any server state after it has been\n * stopped, so a new integration test will start from a clean slate.\n */\n\nvar winston = require('winston'); //logging\nvar http = require('http');\nconst fs = require('fs')\n\nconst isPortAvailable = require('is-port-available');\n\nfunction handleUnknownEndPoint(req, resp) {\n    resp.writeHead(404, {'Content-Type': 'text/plain'});\n    resp.end();\n}\n\nfunction handleOkHttp(req, resp) {\n    var emitSuccess = req.url.endsWith(\"?success=true\");\n    if (emitSuccess) {\n        resp.writeHead(200, {'Content-Type': 'text/plain'});\n        resp.end(req.method + \"-success\");\n    } else {\n        resp.writeHead(500, {'Content-Type': 'text/plain'});\n        resp.end(req.method + \"-failure\");\n    }\n}\n\nfunction handleWatcher(req, resp) {\n    resp.writeHead(200, {'Content-Type': 'text/event-stream'});\n\n    resp.write(\"hello world 1\\n\");\n    resp.write(\"hello world 2\\n\");\n    resp.write(\"hello world 3\\n\");\n}\n\nfunction handleApplicationId(appName, req, resp) {\n    switch(req.method) {\n        case \"GET\":\n            try {\n                 const data = fs.readFileSync('/apps/' + appName + '/app_id', 'utf8')\n                 console.log(data)\n                 resp.writeHead(200, {'Content-Type': 'text/plain'});\n                 resp.end(data.replace(/\\n$/, ''));\n            } catch (err) {\n                 console.error(err)\n                 resp.writeHead(404, {'Content-Type': 'text/plain'});\n                 resp.end(err);\n            }\n            break;\n        case \"PUT\":\n            var body = [];\n            req.on('data', (chunk) => {\n                body.push(chunk);\n            }).on('end', () => {\n                body = Buffer.concat(body).toString();\n                applicationIds[appName] = body.split(\"=\")[1];\n                resp.writeHead(201, {'Content-Location': '/application-id'});\n                resp.end();\n            });\n            break;\n        default:\n            handleUnknownEndPoint(req, resp);\n    }\n}\n\n//Create and start the Http server\nconst PORT = 8888;\nvar applicationIds = {}  // Should be updated by the Docker setup script before any tests are run.\nvar server = http.createServer(function(req, resp) {\n    try {\n        winston.info('command-server: ' + req.method + \" \" + req.url);\n        if (req.url.includes(\"/okhttp\")) {\n            handleOkHttp(req, resp);\n        } else if (req.url.includes('/testapp1')) {\n            handleApplicationId('testapp1', req, resp);\n        } else if (req.url.includes('/testapp2')) {\n            handleApplicationId('testapp2', req, resp);\n        } else if (req.url.includes('/testapp3')) {\n            handleApplicationId('testapp3', req, resp);\n        } else if (req.url.includes('/watcher')) {\n            handleWatcher(req, resp);\n        } else {\n            handleUnknownEndPoint(req, resp);\n        }\n    } catch(err) {\n        winston.error('command-server: ' + err);\n    }\n});\nserver.listen(PORT, function() {\n    winston.info(\"command-server: MongoDB Realm Integration Test Server listening on: 127.0.0.1:%s\", PORT);\n});\n"
  },
  {
    "path": "tools/sync_test_server/start_local_server.sh",
    "content": "#!/usr/bin/env bash\n# set -e\n\n# This script will download and install the BAAS server locally instead of using a docker image.\n#\n# The install location is ~/.realm_baas\n#\n# It requires the following tools installed in your system.\n# * node\n# * yarn\n# * jq\n# * realm-cli@1.3.4\n# * artifactory credentials. See https://wiki.corp.mongodb.com/display/BUILD/How+to+configure+npm+to+use+Artifactory\n# * machine hostname defined in /etc/hosts. See https://wiki.corp.mongodb.com/display/MMS/Cloud+Developer+Setup#CloudDeveloperSetup-SensibleHostnameForYourMac\n\nNC='\\033[0m'\nRED='\\033[0;31m'\nYELLOW='\\033[1;33m'\n\nBAAS_INSTALL_PATH=\"$HOME/.realm_baas_java\"\nSCRIPTPATH=\"$( cd \"$( dirname \"${BASH_SOURCE[0]}\" )\" && pwd )\"\n\nfunction echo_step () {\n  echo -e \"${RED}----> $1${NC}\" \n}\n\nfunction check_dependencies () {\n  if  ! realm-cli --version 2>&1 | grep -q \"1.3.4\"; then\n    echo \"Error: realm-cli@1.3.4 not found. Install using 'npm install -g mongodb-realm-cli@1.3.4'\" && exit 1\n  fi\n  if [ -z ${AWS_ACCESS_KEY_ID} ]; then\n    echo \"Error: AWS_ACCESS_KEY_ID not defined\" && exit 1\n  fi\n  if [ -z ${AWS_SECRET_ACCESS_KEY} ]; then\n    echo \"Error: AWS_SECRET_ACCESS_KEY not defined\" && exit 1\n  fi\n  if  ! which -s node; then\n    echo \"Error: NodeJS not found\" && exit 1\n  fi\n  if ! which -s yarn; then\n    echo \"Error: Yarn not found\" && exit 1\n  fi\n  if [[ ! -e ~/.npmrc ]]; then\n    echo \"Error: Artifactory credentials not configured\" && exit 1\n  fi\n  if ! ping -qo `hostname` >/dev/null 2>&1; then\n    echo \"Error: Hostname `hostname` missing in /etc/hosts\" && exit 1\n  fi\n  if  ! which -s yq; then\n    echo \"Error: yq not found. Install using 'brew install yq'\" && exit 1\n  fi\n  echo \"Ok\"\n}\n\nfunction bind_android_emulator_ports () {\n  $SCRIPTPATH/bind_android_ports.sh\n}\n\nfunction install_baas_ui () {\n  REALM_BAAS_UI_GIT_HASH=$(grep REALM_BAAS_UI_GIT_HASH $SCRIPTPATH/../../dependencies.list | cut -d'=' -f2)\n\n  mkdir -p $BAAS_INSTALL_PATH\n\n  pushd $BAAS_INSTALL_PATH\n\n  if [[ ! -d $BAAS_INSTALL_PATH/baas-ui/.git ]]; then\n    git clone git@github.com:10gen/baas-ui.git\n  fi\n\n  pushd baas-ui\n  git checkout $REALM_BAAS_UI_GIT_HASH\n  yarn run build \n  popd\n\n  popd\n}\n\nfunction wait_for_mongod {\n  RETRY_COUNT=${2:-120}\n  WAIT_COUNTER=0\n  until pgrep -F $BAAS_INSTALL_PATH/mongod.pid > /dev/null 2>&1; do\n    \n    WAIT_COUNTER=$(($WAIT_COUNTER + 1 ))\n    if [[ $WAIT_COUNTER = $RETRY_COUNT ]]; then\n        echo \"Error: Timed out waiting for mongod to start\"\n        exit 1\n    fi\n\n    sleep 5\n  done\n}\n\nfunction bind_baas_ui () {\n  pushd $BAAS_INSTALL_PATH\n  mkdir -p baas/static\n  ln -fs ../../baas-ui baas/static/app\n  popd\n}\n\nfunction install_baas () {\n  REALM_BAAS_GIT_HASH=$(grep REALM_BAAS_GIT_HASH $SCRIPTPATH/../../dependencies.list | cut -d'=' -f2)\n\n  EVERGREEN_DIR=$SCRIPTPATH/../../realm/realm-library/src/main/cpp/realm-core/evergreen\n\n  # boot baas in bg\n  $EVERGREEN_DIR/install_baas.sh -w $BAAS_INSTALL_PATH -b $REALM_BAAS_GIT_HASH &\n  INSTALL_BAAS_PID=$!\n\n  # We need to bind the UI after the baas server has been checked\n\n  echo_step \"Waiting for mongod to boot to bind ui\" \n  wait_for_mongod\n\n  echo_step \"Binding baas ui\" \n  bind_baas_ui\n\n  # wait for service to come up\n  $EVERGREEN_DIR/wait_for_baas.sh \"$BAAS_INSTALL_PATH/baas_server.pid\"\n}\n\nfunction boot_command_server () {\n  cd $SCRIPTPATH\n  docker build $SCRIPTPATH -f Dockerfile -t mongodb-realm-command-server\n  docker run --rm -i -t -d -p8888:8888 -v$APP_CONFIG_DIR:/apps --name mongodb-realm-command-server mongodb-realm-command-server\n}\n\nfunction generate_app_configs () {\n  APP_CONFIG_DIR=`mktemp -d -t app_config`\n  $SCRIPTPATH/app_config_generator.sh $APP_CONFIG_DIR $SCRIPTPATH/app_template partition auto testapp1\n  $SCRIPTPATH/app_config_generator.sh $APP_CONFIG_DIR $SCRIPTPATH/app_template partition email testapp2\n  $SCRIPTPATH/app_config_generator.sh $APP_CONFIG_DIR $SCRIPTPATH/app_template flex function testapp3\n}\n\nfunction import_apps () {\n  app_dir=$1\n  realm-cli login --config-path=/tmp/stitch-config --base-url=http://localhost:9090 --auth-provider=local-userpass --username=unique_user@domain.com --password=password -y\n  access_token=$(yq e \".access_token\" /tmp/stitch-config)\n  group_id=$(curl --header \"Authorization: Bearer $access_token\" http://localhost:9090/api/admin/v3.0/auth/profile -s | jq '.roles[0].group_id' -r)\n  cd $app_dir\n  for app in *; do\n      echo \"importing app: ${app}\"\n\n      manifest_file=\"config.json\"\n      app_id_param=\"\"\n      if [ -f \"$app/secrets.json\" ]; then\n          # create app by importing an empty skeleton with the same name\n          app_name=$(jq '.name' \"$app/$manifest_file\" -r)\n          temp_app=\"/tmp/stitch-apps/$app\"\n          mkdir -p \"$temp_app\" && echo \"{ \\\"name\\\": \\\"$app_name\\\" }\" > \"$temp_app/$manifest_file\"\n          realm-cli import --config-path=/tmp/stitch-config --base-url=http://localhost:9090 --path=\"$temp_app\" --project-id $group_id -y --strategy replace\n\n          app_id=$(jq '.app_id' \"$temp_app/$manifest_file\" -r)\n          app_id_param=\"--app-id=$app_id\"\n\n          # import secrets into the created app\n          while read -r secret value; do\n              realm-cli secrets add --config-path=/tmp/stitch-config --base-url=http://localhost:9090 --app-id=$app_id --name=\"$secret\" --value=\"$(echo $value | sed 's/\\\\n/\\n/g')\"\n          done < <(jq 'to_entries[] | [.key, .value] | @tsv' \"$app/secrets.json\" -r)\n      fi\n\n      realm-cli import --config-path=/tmp/stitch-config --base-url=http://localhost:9090 --path=\"$app\" $app_id_param --project-id $group_id -y --strategy replace\n      jq '.app_id' \"$app/$manifest_file\" -r > \"$app/app_id\"\n  done\n}\n\nfunction cleanup () {\n  kill -9 $INSTALL_BAAS_PID\n  $SCRIPTPATH/stop_local_server.sh\n}\n\n# terminate install_baas.sh and its processes\n# trap cleanup INT TERM ERR\n\n# Get the script dir which contains the Dockerfile\n\necho_step \"Checking dependencies\"\ncheck_dependencies\n\necho_step \"Try to bind android emulator ports\" \nbind_android_emulator_ports\n\necho_step \"Installing baas-ui in ${YELLOW}$BAAS_INSTALL_PATH\" \ninstall_baas_ui\n\necho_step \"Installing and booting BAAS in ${YELLOW}$BAAS_INSTALL_PATH\" \ninstall_baas\n\necho_step \"Generate configs\" \ngenerate_app_configs\n\necho_step \"Importing apps\" \nimport_apps $APP_CONFIG_DIR\n\necho_step \"Building and booting command server\" \nboot_command_server\n\necho_step \"Template apps are generated in/served from ${YELLOW}$APP_CONFIG_DIR\"\necho_step \"Server available at http://localhost:9090/\"\n"
  },
  {
    "path": "tools/sync_test_server/start_server.sh",
    "content": "#!/bin/sh\n\n# How to use this script:\n#\n# 1. Logging into GitHub\n# 2. Goto \"Settings > Developer Settings > Personal access tokens\"\n# 3. Press \"Generate new Token\"\n# 4. Select \"read:packages\" as Scope. Give it a name and create the token.\n# 5. Store the token in a environment variable called GITHUB_DOCKER_TOKEN.\n# 6. Store the GitHub username in an environment variable called GITHUB_DOCKER_USER.\n# 7. Run this script.\n\n# Verify that Github username and tokens are available as environment vars\nif [[ -z \"${GITHUB_DOCKER_USER}\" ]]; then\n  echo \"Could not find \\$GITHUB_DOCKER_USER as an environment variable\"\n  exit 1\nfi\n\nif [[ -z \"${GITHUB_DOCKER_TOKEN}\" ]]; then\n  echo \"Could not find \\$GITHUB_DOCKER_TOKEN as an environment variable. This is used to download Docker Registry packages.\"\n  exit 1\nfi\n\n# Get the script dir which contains the Dockerfile\nDOCKERFILE_DIR=\"$( cd \"$( dirname \"${BASH_SOURCE[0]}\" )\" && pwd )\"\n\nMONGODB_REALM_VERSION=$(grep MONGODB_REALM_SERVER $DOCKERFILE_DIR/../../dependencies.list | cut -d'=' -f2)\n\nadb reverse tcp:9443 tcp:9443 && \\\nadb reverse tcp:9080 tcp:9080 && \\\nadb reverse tcp:9090 tcp:9090 && \\\nadb reverse tcp:8888 tcp:8888 || { echo \"Failed to reverse adb port.\" ; exit 1 ; }\n\n# Make sure that Docker works correctly with Github Docker Registry by logging in\ndocker login docker.pkg.github.com -u $GITHUB_DOCKER_USER -p $GITHUB_DOCKER_TOKEN\n\nSCRIPTPATH=\"$( cd \"$(dirname \"$0\")\" >/dev/null 2>&1 ; pwd -P )\"\n\n# Create app configurations\nAPP_CONFIG_DIR=`mktemp -d -t app_config`\n$SCRIPTPATH/app_config_generator.sh $APP_CONFIG_DIR $SCRIPTPATH/app_template partition auto testapp1\n$SCRIPTPATH/app_config_generator.sh $APP_CONFIG_DIR $SCRIPTPATH/app_template partition email testapp2\n$SCRIPTPATH/app_config_generator.sh $APP_CONFIG_DIR $SCRIPTPATH/app_template flex function testapp3\n\n# Run Stitch and Stitch CLI Docker images\ndocker network create mongodb-realm-network\ndocker build $DOCKERFILE_DIR -t mongodb-realm-command-server || { echo \"Failed to build Docker image.\" ; exit 1 ; }\nID=$(docker run --rm -i -t -d -v$APP_CONFIG_DIR:/apps \\\n     --network mongodb-realm-network \\\n     -p9090:9090 \\\n     -p8888:8888 \\\n     -p26000:26000 \\\n     --name mongodb-realm \\\n     -e AWS_ACCESS_KEY_ID=\"${BAAS_AWS_ACCESS_KEY_ID}\" \\\n     -e AWS_SECRET_ACCESS_KEY=\"${BAAS_AWS_SECRET_ACCESS_KEY}\" \\\n     docker.pkg.github.com/realm/ci/mongodb-realm-test-server:$MONGODB_REALM_VERSION \\\n)\ndocker run --rm -i -t -d --network container:$ID -v$APP_CONFIG_DIR:/apps --name mongodb-realm-command-server mongodb-realm-command-server\n\necho \"Template apps are generated in/served from $APP_CONFIG_DIR\"\n"
  },
  {
    "path": "tools/sync_test_server/stop_local_server.sh",
    "content": "#!/bin/sh\n\nWORK_PATH=\"$HOME/.realm_baas_java\"\nBAAS_PID=\"\"\nMONGOD_PID=\"\"\nif [[ -f $WORK_PATH/baas_server.pid ]]; then\n    BAAS_PID=\"$(< \"$WORK_PATH/baas_server.pid\")\"\nfi\n\nif [[ -f $WORK_PATH/mongod.pid ]]; then\n    MONGOD_PID=\"$(< \"$WORK_PATH/mongod.pid\")\"\nfi\n\nif [[ -n \"$BAAS_PID\" ]]; then\n    echo \"Stopping baas $BAAS_PID\"\n    kill -9 \"$BAAS_PID\"\n    rm $WORK_PATH/baas_server.pid\nfi\n\n\nif [[ -n \"$MONGOD_PID\" ]]; then\n    echo \"Killing mongod $MONGOD_PID\"\n    kill -9 \"$MONGOD_PID\"\n    rm $WORK_PATH/mongod.pid\nfi\n\ndocker stop mongodb-realm-command-server -t0\n"
  },
  {
    "path": "tools/sync_test_server/stop_server.sh",
    "content": "#!/bin/sh\n\ndocker stop mongodb-realm -t0\ndocker stop mongodb-realm-command-server -t0\ndocker network rm mongodb-realm-network\n"
  },
  {
    "path": "tools/unroll_stacktrace.sh",
    "content": "#!/usr/bin/env bash\n\n# This script will attempt to manually unroll a stack trace using the unstripped jni libs that are available on S3.\n# It will do so using ndk-stack, so read https://developer.android.com/ndk/guides/ndk-stack.html first\n#\n# The location of ndk-stack will be infered from the ndk.dir property in `<root>/realm/local.properties`.\n#\n# Usage: > sh unroll_stacktrace.sh <version> <abi> <stacktrace_file>\n# Example: > sh unroll_stacktrace.sh 5.0.0 armeabi-v7a ./dump.txt\n#\n\nset -euo pipefail\nIFS=$'\\n\\t'\n\nusage() {\ncat <<EOF\nUsage: $0 ( <buildid> | <flavor> <version> <abi> ) <stacktrace>\n - buildid: realm java build id\n\n - flavor: base, objectServer\n - version: version number on Maven Central\n - abi: armeabi, armeabi-v7a, arm64-v8a, x86, x86_64, mips\n\n - stacktrace: absolute or relative path to file with dump information\n\nExample with build id:    $0 6ad7f63d64a38561c8e8c41f3d5d36021f8749c5 ./dump.txt\nExample without build id: $0 base 5.0.0 armeabi-v7a ./dump.txt\nEOF\n}\n\n######################################\n# Input Validation\n######################################\n\nif [ \"$#\" -ne 2 ] && [ \"$#\" -ne 4 ] ; then\n    usage\n    exit 1\nfi\n\nHERE=$(pwd)\nREALM_JAVA_TOOLS_DIR=$(dirname \"$0\")\n\nif [ \"$#\" -eq 2 ]; then\n\tDATA=`grep $1 buildids.txt | cut -c43-`\n\tif [ -z $DATA ]; then \n\t\techo \"build id not found\"\n\t\texit 1\n\telse\n\t\tIFS=' ' read -r VERSION FLAVOR ABI <<< \"$DATA\"\n\t\tSTACKTRACE=\"$HERE/$2\"\n\tfi\nelif [ \"$#\" -eq 4 ]; then\n\tFLAVOR=\"$1\"\n\tVERSION=\"$2\"\n\tABI=\"$3\"\n\tSTACKTRACE=\"$HERE/$4\"\nfi\n\nNDK_STACK=\"\"\nSTRIPPED_LIBS_DIR=\"\"\n\nfind_ndkstack() {\n\tPROPS_FILE=\"$REALM_JAVA_TOOLS_DIR/../realm/local.properties\"\n\tif [ ! -f \"$PROPS_FILE\" ]; then\n    \techo \"$PROPS_FILE not found! NDK location cannot be determined\"\n    \texit 1\n\tfi\n\tNDK_STACK=$(grep \"ndk.dir\" \"$PROPS_FILE\" | cut -d = -f2)/ndk-stack\n}\n\ndownload_and_unzip_stripped_libs() {\n\t# Define location for unstripped libs. \n\t# Use the standard REALM_CORE if defined, otherwise treat it as a temporary file.\n\tCACHED_LIBS_DIR=\"$REALM_CORE_DOWNLOAD_DIR\"\n\tif [[ -z \"${REALM_CORE_DOWNLOAD_DIR}\" ]]; then\n  \t\tCACHED_LIBS_DIR=\"/tmp\"\n\tfi\n\n\t# Check if we already have the unstripped libs downloaded\n\tSTRIPPED_LIBS_FILE=\"$CACHED_LIBS_DIR/realm-java-jni-libs-unstripped-$VERSION.zip\"\n\tif [ ! -f \"$STRIPPED_LIBS_FILE\" ]; then\n    \techo \"$STRIPPED_LIBS_FILE not found! Downloading from S3\"\n\t\tSTRIPPED_LIBS_DOWNLOAD_LOCATION=\"https://static.realm.io/downloads/java/realm-java-jni-libs-unstripped-$VERSION.zip\"\n\t\tcurl -o \"$STRIPPED_LIBS_FILE\" \"$STRIPPED_LIBS_DOWNLOAD_LOCATION\" \n\tfi\n\n\t# Exact files if needed\n\tSTRIPPED_LIBS_DIR=\"$CACHED_LIBS_DIR/realm-java-jni-libs-unstripped-$VERSION\"\n\tif [ ! -d \"$STRIPPED_LIBS_DIR\" ]; then\n\t\techo \"Extracting archive file with unstripped libraries\"\n\t\tunzip \"$STRIPPED_LIBS_FILE\" -d \"$STRIPPED_LIBS_DIR\"\n\tfi\n}\n\nunroll_stacktrace() {\n\tDIR=\"$STRIPPED_LIBS_DIR/$FLAVOR/$ABI\"\n\tif [ ! -d \"$DIR\" ]; then\n\t\techo \"Directory containing .so file could not be found: ${DIR}\"\n\t\texit 1\n\tfi\n\t$NDK_STACK -sym \"$DIR\" -dump \"$STACKTRACE\"\n}\n\necho \"Unrolling $STACKTRACE from Realm Java $VERSION ($FLAVOR) using ABI $ABI\"\nfind_ndkstack\ndownload_and_unzip_stripped_libs\nunroll_stacktrace\n"
  },
  {
    "path": "tools/update_gradle_wrapper.sh",
    "content": "#!/bin/sh\n\n# This script updates Gradle Wrappers in this repository.\n# To run it:\n#   1. Make sure that you have run ./gradlew assemble in the root directory\n#   2. Replace the gradle version number in realm.properties in the root directory, with the new version number.\n#   3. Run tools/update_gradle_wrapper.sh\n\nHERE=`pwd`\n\ncd \"$(dirname $0)/..\"\n\nGRADLE=`grep gradle dependencies.list | cut -d = -f2`\necho \"==> Update gradle to version: $GRADLE <==\"\necho\nread -n1 -r -p \"Press any key to continue...\" key\n\nfor i in $(find $(pwd) -type f -name gradlew); do\n    cd $(dirname $i)\n    pwd\n    ./gradlew wrapper --gradle-version=$GRADLE --distribution-type all\ndone\n\ncd $HERE\n\n"
  },
  {
    "path": "version.txt",
    "content": "11.0.0\n"
  }
]